[
  {
    "path": ".claude/CLAUDE.md",
    "content": "# AI Documentation\n\nRead `ai/README.md` for indexed reference docs on types, algorithms, and utilities.\n"
  },
  {
    "path": ".config/dotnet-tools.json",
    "content": "{\n  \"version\": 1,\n  \"isRoot\": true,\n  \"tools\": {\n    \"paket\": {\n      \"version\": \"10.0.0-alpha011\",\n      \"commands\": [\n        \"paket\"\n      ],\n      \"rollForward\": false\n    },\n    \"aardpack\": {\n      \"version\": \"2.0.7\",\n      \"commands\": [\n        \"aardpack\"\n      ],\n      \"rollForward\": false\n    }\n  }\n}"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build\n\non:\n  push:\n    paths-ignore:\n    - 'README.md'\n    - 'docs/**'\n  pull_request:\n    paths-ignore:\n    - 'README.md'\n    - 'docs/**'\n\njobs:\n  codegen-check:\n    runs-on: windows-latest\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: Setup .NET\n      uses: actions/setup-dotnet@v4\n      with:\n        global-json-file: global.json\n\n    - name: Cache Paket\n      uses: actions/cache@v4\n      with:\n        path: |\n          ~/.nuget/packages\n          paket-files\n        key: ${{ runner.os }}-paket-${{ hashFiles('paket.lock') }}\n        restore-keys: |\n          ${{ runner.os }}-paket-\n\n    - name: Restore\n      shell: cmd\n      run: .\\build.cmd restore\n\n    - name: Run forced code generation\n      shell: cmd\n      run: .\\generate.cmd --force\n\n    - name: Fail on generated diffs\n      shell: pwsh\n      run: |\n        git diff --quiet -- src\n        if ($LASTEXITCODE -ne 0) {\n          Write-Host \"Generated files are out of date:\"\n          git diff --name-only -- src\n          exit 1\n        }\n\n  build:\n    needs: codegen-check\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n        include:\n          - os: ubuntu-latest\n            run-build: bash ./build.sh\n          - os: windows-latest\n            run-build: .\\build.cmd\n          - os: macos-latest\n            run-build: bash ./build.sh\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: Setup .NET\n      uses: actions/setup-dotnet@v4\n      with:\n        global-json-file: global.json\n\n    - name: Cache Paket\n      uses: actions/cache@v4\n      with:\n        path: |\n          ~/.nuget/packages\n          paket-files\n        key: ${{ runner.os }}-paket-${{ hashFiles('paket.lock') }}\n        restore-keys: |\n          ${{ runner.os }}-paket-\n\n    - name: Build\n      run: ${{ matrix.run-build }}\n"
  },
  {
    "path": ".github/workflows/docs-check.yml",
    "content": "name: Docs Check\n\non:\n  push:\n  pull_request:\n\njobs:\n  docs-check:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: Setup .NET\n      uses: actions/setup-dotnet@v4\n      with:\n        global-json-file: global.json\n\n    - name: Run docs checker (Unix)\n      if: runner.os != 'Windows'\n      run: bash ./check-docs.sh\n\n    - name: Run docs checker (Windows)\n      if: runner.os == 'Windows'\n      shell: cmd\n      run: .\\check-docs.cmd\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish\non:\n  push:\n    branches:\n      - master\n      - v53\n    paths:\n      - RELEASE_NOTES.md\n      - .github/workflows/publish.yml\njobs:\n  release-check:\n    name: Check release version\n    runs-on: windows-latest\n    permissions:\n      contents: read\n    outputs:\n      should_publish: ${{ steps.compare.outputs.should_publish }}\n      release_notes_version: ${{ steps.compare.outputs.release_notes_version }}\n      latest_release_version: ${{ steps.compare.outputs.latest_release_version }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Install Dotnet\n        uses: actions/setup-dotnet@v4\n        with:\n          global-json-file: global.json\n      - name: Restore Tools\n        run: dotnet tool restore\n      - name: Compare release versions\n        id: compare\n        shell: pwsh\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          function Normalize-Version([string] $Version) {\n            if ([string]::IsNullOrWhiteSpace($Version)) {\n              return \"\"\n            }\n\n            return $Version.Trim() -replace '^[vV]', ''\n          }\n\n          $parseOutput = & dotnet aardpack --parse-only\n          if ($LASTEXITCODE -ne 0) {\n            throw \"dotnet aardpack --parse-only failed with exit code $LASTEXITCODE.\"\n          }\n\n          $releaseNotesVersion = ($parseOutput | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Last 1).Trim()\n          if ([string]::IsNullOrWhiteSpace($releaseNotesVersion)) {\n            throw \"dotnet aardpack --parse-only did not return a release notes version.\"\n          }\n\n          $headers = @{\n            Authorization = \"Bearer $env:GITHUB_TOKEN\"\n            Accept = \"application/vnd.github+json\"\n            \"X-GitHub-Api-Version\" = \"2022-11-28\"\n            \"User-Agent\" = \"github-actions\"\n          }\n\n          $latestReleaseVersion = \"\"\n          $shouldPublish = \"true\"\n          try {\n            $latestRelease = Invoke-RestMethod `\n              -Uri \"https://api.github.com/repos/${{ github.repository }}/releases/latest\" `\n              -Headers $headers\n            $latestReleaseVersion = [string] $latestRelease.tag_name\n\n            if ((Normalize-Version $releaseNotesVersion) -eq (Normalize-Version $latestReleaseVersion)) {\n              $shouldPublish = \"false\"\n            }\n          }\n          catch {\n            $statusCode = $_.Exception.Response.StatusCode.value__\n            if ($statusCode -eq 404) {\n              Write-Host \"No latest GitHub release found. Continuing publish workflow.\"\n            }\n            else {\n              throw\n            }\n          }\n\n          \"release_notes_version=$releaseNotesVersion\" >> $env:GITHUB_OUTPUT\n          \"latest_release_version=$latestReleaseVersion\" >> $env:GITHUB_OUTPUT\n          \"should_publish=$shouldPublish\" >> $env:GITHUB_OUTPUT\n\n          \"## Publish release check\" >> $env:GITHUB_STEP_SUMMARY\n          \"\" >> $env:GITHUB_STEP_SUMMARY\n          \"- Release notes version: ``$releaseNotesVersion``\" >> $env:GITHUB_STEP_SUMMARY\n          \"- Latest GitHub release: ``$latestReleaseVersion``\" >> $env:GITHUB_STEP_SUMMARY\n          \"- Should publish: ``$shouldPublish``\" >> $env:GITHUB_STEP_SUMMARY\n\n  pack:\n    name: Package\n    needs: release-check\n    if: needs.release-check.outputs.should_publish == 'true'\n    runs-on: windows-latest\n    steps:  \n      - name: Checkout\n        uses: actions/checkout@v4\n      - name: Install Dotnet\n        uses: actions/setup-dotnet@v4\n        with:\n          global-json-file: global.json\n      - name: Restore Tools\n        run: dotnet tool restore\n      - name: Restore\n        run: dotnet paket restore\n      - name: Run forced code generation\n        shell: cmd\n        run: .\\generate.cmd --force\n      - name: Fail on generated diffs\n        shell: pwsh\n        run: |\n          git diff --quiet -- src\n          if ($LASTEXITCODE -ne 0) {\n            Write-Host \"Generated files are out of date:\"\n            git diff --name-only -- src\n            exit 1\n          }\n      - name: Build\n        shell: cmd\n        run: dotnet build -c Release src\\Aardvark.sln\n      - name: Test\n        run: dotnet test src\\Aardvark.sln -c Release --no-build --nologo --logger:\"console;verbosity=normal\"\n      - name: Pack\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: dotnet aardpack src\\Aardvark.sln --notag --skip-build\n      - name: Upload Packages\n        uses: actions/upload-artifact@v4\n        with:\n          name: packages\n          path: bin\\pack\n      - name: GitHub Packages\n        env:\n          NUGET_KEY: ${{ secrets.GITHUB_TOKEN }}\n        shell: cmd\n        run: dotnet nuget push \"bin\\pack\\*.nupkg\" -k %NUGET_KEY% -s \"https://nuget.pkg.github.com/aardvark-platform/index.json\" --skip-duplicate\n      - name: NuGet\n        env:\n          NUGET_KEY: ${{ secrets.NUGET_KEY }}\n        shell: cmd\n        run: dotnet nuget push \"bin\\pack\\*.nupkg\" -k %NUGET_KEY% -s \"https://api.nuget.org/v3/index.json\" --skip-duplicate\n"
  },
  {
    "path": ".gitignore",
    "content": "**/.DS_Store\r\n/.paket/paket.exe\r\n/src/Aardvark.Base/obj\r\n/src/*.suo\r\n/src/*.userprefs\r\n/bin/net40\r\n/bin/net45\r\n/packages/*\r\n!/packages/*.config\r\n*.nupkg\r\nobj\r\n/src/Aardvark.sln.ide\r\n*.swp\r\nbin\r\n*.*~\r\n/buildLog.log\r\n/src/.vs\r\ntmp\r\n/docs\n!/docs/\n!/docs/CONTRIBUTING.md\n!/docs/INTEROP.md\n!/docs/TROUBLESHOOTING.md\n/src/Aardvark.Base/Images/TensorExtensions_generator.cs\r\n/src/Demo/Sketch/.vs/Sketch/v14/*.suo\r\n/TestResult.xml\r\n/.fake\r\n/paket-files\r\n/tests.out\r\n/*.log\r\n/src/Aardvark.Base/Tensors/TensorMathExt_generator.cs\r\n**/*.csproj.user\r\n**/*_generator.cs\r\n/.paket\r\n*.fsproj.user\r\nAardvark.log\r\n/build.fsx.lock\r\n.ionide\r\n/.vs\r\n.idea\r\n.boss/\r\nsrc/Aardvark.sln.DotSettings.user\r\n.claude/settings.local.json\r\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"dotnet-test-explorer.testProjectPath\": \"src/Aardvark.sln\",\n    \"files.exclude\": {\n        \"**/.git\": true,\n        \"**/.svn\": true,\n        \"**/.hg\": true,\n        \"**/CVS\": true,\n        \"**/.DS_Store\": true,\n        \"**/Thumbs.db\": true,\n        \".paket\": true,\n        \".ionide\": true,\n        \"packages\": true,\n        \"paket-files\": true,\n        \"**/obj/\": true\n    }\n}"
  },
  {
    "path": ".vscode/tasks.json",
    "content": "{\n    // See https://go.microsoft.com/fwlink/?LinkId=733558\n    // for the documentation about the tasks.json format\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"restore-tools\",\n            \"command\": \"dotnet\",\n            \"type\": \"shell\",\n            \"args\": [ \"tool\", \"restore\" ],\n            \"group\": \"build\",\n            \"runOptions\": {\n                \"runOn\": \"folderOpen\"\n            },\n            \"presentation\": {\n                \"echo\": false,\n                \"reveal\": \"never\",\n                \"focus\": false,\n                \"panel\": \"shared\",\n                \"showReuseMessage\": false,\n                \"clear\": false,\n                \"close\": true\n            }\n        },\n        {\n            \"label\": \"restore\",\n            \"command\": \"dotnet\",\n            \"type\": \"shell\",\n            \"args\": [ \"paket\", \"restore\" ],\n            \"group\": \"build\"\n        },\n        {\n            \"label\": \"codegen\",\n            \"command\": \"dotnet\",\n            \"type\": \"shell\",\n            \"args\": [ \"run\", \"--project\", \"src/CodeGenerator/CodeGenerator.csproj\" ],\n            \"group\": \"build\"\n        },\n        {\n            \"label\": \"build\",\n            \"command\": \"dotnet\",\n            \"type\": \"shell\",\n            \"args\": [\n                \"build\",\n                \"src/Aardvark.sln\",\n                // Ask dotnet build to generate full paths for file names.\n                \"/property:GenerateFullPaths=true\",\n                // Do not generate summary otherwise it leads to duplicate errors in Problems panel\n                \"/consoleloggerparameters:NoSummary\"\n            ],\n            \"group\": \"build\",\n            \"presentation\": {\n                \"reveal\": \"silent\"\n            },\n            \"problemMatcher\": \"$msCompile\"\n        },\n        {\n            \"label\": \"install\",\n            \"command\": \"dotnet\",\n            \"type\": \"shell\",\n            \"args\": [\n                \"paket\",\n                \"install\"\n            ],\n            \"group\": \"build\",\n            \"presentation\": {\n                \"reveal\": \"always\"\n            },\n            \"problemMatcher\": \"$msCompile\"\n        },\n        {\n            \"label\": \"clean\",\n            \"command\": \"dotnet\",\n            \"type\": \"shell\",\n            \"args\": [\n                \"clean\",\n                \"src/Aardvark.sln\"\n            ],\n            \"group\": \"build\",\n            \"presentation\": {\n                \"reveal\": \"always\"\n            }\n        }\n    ]\n}"
  },
  {
    "path": "AGENTS.md",
    "content": "# AI Agent Guide\n\nRepository-specific rules and verified operational facts for coding agents.\n\nPrimary AI reference index: `ai/README.md`\n\n## Supported Commands\n\nUse these commands for restore/build/test/codegen:\n\n| Task | Command | Notes |\n|------|---------|-------|\n| Restore only | `./build.sh restore` or `.\\build.cmd restore` | Restores dotnet tools + paket packages, auto-repairing missing Paket targets with `dotnet paket install`, and returns a nonzero exit code on the first failure |\n| Build all | `./build.sh` or `.\\build.cmd` | Builds `src/Aardvark.sln` and stops on the first failing step |\n| Build one project | `dotnet build src/Aardvark.Base/Aardvark.Base.csproj -c Debug` | Use explicit project path |\n| Test all | `./test.sh` or `.\\test.cmd` | Runs the five maintained test projects, stopping on the first failing step; excludes benchmark projects and the deprecated incremental test project |\n| Test one project | `dotnet test src/Tests/Aardvark.Base.Tests/Aardvark.Base.Tests.csproj -c Debug` | Prefer this over whole-solution test |\n| Test with filter | `dotnet test src/Tests/Aardvark.Base.Tests/Aardvark.Base.Tests.csproj --filter \"FullyQualifiedName~Vector\"` | Works with NUnit adapter; use a concrete test project |\n| Codegen | `./generate.sh` or `.\\generate.cmd` | Required after template changes |\n| Check docs drift | `./check-docs.sh` or `.\\check-docs.cmd` | Validates docs against source anchors and anti-drift rules |\n\n## Dependency Management (Paket)\n\nThis repo uses Paket, not `dotnet add package`.\n\n| Task | Command |\n|------|---------|\n| Add package | `dotnet paket add <pkg> --project <proj>` |\n| Update group | `dotnet paket update --group Main` |\n| Re-resolve lock | `dotnet paket install` |\n| Restore packages | `dotnet paket restore` |\n\nRules:\n- Never edit `paket.lock` manually\n- Never use `dotnet add package` in this repo\n- Change constraints in `paket.dependencies`, then regenerate lock with Paket\n- Top-level `build.*` / `test.*` scripts auto-run `dotnet paket install` when `.paket/Paket.Restore.targets` is missing; otherwise they use `dotnet paket restore`\n- Top-level `build.*` / `test.*` scripts now stop immediately on the first failing restore/build/test command and return that nonzero exit code\n\n## Release Notes\n\nWhen a change needs release notes:\n- `aardvark.build` reads the first `### <version>` section as the current package version\n- unreleased notes may appear above that first version section as plain text or bullet points\n- do not add a markdown heading such as `### Preliminary` above the first version section\n- do not append new notes inside an older released version block\n- if you add pending/preliminary notes, place them above the first version section instead of inside the previous released block\n\n## File Ownership by Change Type\n\n| Change Type | Files to Modify | Files to Avoid |\n|-------------|-----------------|----------------|\n| Add C# feature | `src/Aardvark.Base/**/*.cs`, `src/Aardvark.Base.IO/**/*.cs`, `src/Aardvark.Base.Essentials/**/*.cs` | `*_auto.cs`, `*_template.cs` unless you are updating generation templates intentionally |\n| Add F# feature | `src/Aardvark.Base.FSharp/**/*.fs`, `src/Aardvark.Base.Incremental/**/*.fs`, `src/Aardvark.Base.Tensors/**/*.fs`, `src/Aardvark.Geometry/**/*.fs`, `src/Aardvark.Base.Runtime/**/*.fs`, `src/Aardvark.Base.Fonts/**/*.fs` | Generated `*_auto.fs` unless template-driven change |\n| Add tests | `src/Tests/**/*Tests.cs`, `src/Tests/**/*Tests.fs` | Unrelated production modules |\n| Fix bug | Smallest relevant source area + regression test | Broad refactors without tests |\n| Update dependencies | `paket.dependencies` (+ Paket-generated lock update) | Manual lock edits |\n\n## Cross-Language Reality (Important)\n\nDo not assume strict one-way C#/F# dependency rules here. This solution intentionally mixes languages:\n\n- F# projects reference C# projects\n- Some C# projects also reference F# projects (for example `Aardvark.Base.IO` references `Aardvark.Base.Tensors.fsproj`)\n\nGuideline for agents:\n- Preserve existing dependency direction used by neighboring projects\n- If introducing a new reference, check existing project patterns first\n- Avoid creating dependency cycles\n\n## Framework, SDK, and Project Matrix\n\n- SDK pin: `.NET SDK 8.0.0` with `rollForward: latestFeature` (see `global.json`)\n- Not all projects target the same framework\n\nCurrent project reality:\n- Mixed `net8.0;netstandard2.0`: `Aardvark.Base`, `Aardvark.Base.FSharp`, `Aardvark.Base.IO`\n- `netstandard2.0` only: `Aardvark.Base.Essentials`, `Aardvark.Base.Telemetry`, `Aardvark.Base.Tensors`, `Aardvark.Base.Tensors.CSharp`, `Aardvark.Base.Runtime`, `Aardvark.Base.Fonts`, `Aardvark.Geometry`\n- `net8.0` test/demo projects: most projects in `src/Tests` and `src/Demo`\n- Deprecated legacy test project: `src/Tests/Aardvark.Base.Incremental.Tests/Aardvark.Base.Incremental.Tests.fsproj` still targets `netcoreapp3.0`, is intentionally excluded from `src/Aardvark.sln` and the standard `test.sh` / `test.cmd` path, and is tracked for removal-or-migration in GitHub issue `#94`\n- C# language version is not uniform (`12.0` in `Aardvark.Base`, `10.0` in some other C# projects)\n\n## Common Failure Modes\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| `dotnet paket restore` fails | Paket/tool state mismatch | `dotnet tool restore` then `dotnet paket restore`; if `.paket/Paket.Restore.targets` is missing or scripts are not being used, run `dotnet paket install` |\n| Compile errors in generated files | Template/output out of sync | Run `./generate.sh` or `.\\generate.cmd` |\n| Build fails due framework mismatch | Running old SDK/runtime | Install .NET 8 SDK; verify `dotnet --info` and `global.json` |\n| Test filter returns zero tests | Wrong filter syntax | Use `FullyQualifiedName~...` pattern |\n| Docs check fails | Broken links, stale examples, missing anchors, mojibake | Run `./check-docs.sh` or `.\\check-docs.cmd` and fix the reported file/pattern |\n| Rendering namespace not found | Wrong package assumption | `Aardvark.Rendering` comes from downstream package, not this repo |\n\n## Project Structure\n\n```text\nsrc/\n|- Aardvark.Base/                (core C# math/geometry/types)\n|- Aardvark.Base.Essentials/     (additional C# utilities)\n|- Aardvark.Base.IO/             (I/O and image codecs; C#)\n|- Aardvark.Base.Telemetry/      (telemetry probes; C#)\n|- Aardvark.Base.Tensors.CSharp/ (C# tensor/piximage layer)\n|- Aardvark.Base.FSharp/         (F# functional extensions)\n|- Aardvark.Base.Incremental/    (adaptive system; F#)\n|- Aardvark.Base.Tensors/        (tensor features; F#)\n|- Aardvark.Base.Runtime/        (runtime helpers; F#)\n|- Aardvark.Base.Fonts/          (font/text support; F#)\n|- Aardvark.Geometry/            (geometry algorithms; F#)\n|- Tests/                        (C# + F# test projects)\n|- Demo/                         (sample apps)\n|- CodeGenerator/                (template/code generation tooling)\n```\n\n## AI Reference Docs\n\nSee `ai/README.md` for task-based lookup across:\n- primitive math/geometry types\n- linear algebra semantics (layout/interoperability)\n- geometry semantics (transform conventions)\n- piximage/tensor APIs\n- algorithms and collections\n- serialization\n- utilities\n- F# interop\n- incremental/adaptive system\n\n## Agent Workflow Tips\n\n1. Read only the doc needed for your task, not all docs\n2. Verify API names with `rg` before using examples from docs\n3. Prefer local source as the final truth if docs and code disagree\n4. Run focused tests for touched modules before broad test runs\n5. When changing templates, regenerate before building\n6. When changing docs, run `./check-docs.sh` or `.\\check-docs.cmd`\n\n---\n\nLast updated: 2026-02-26\n"
  },
  {
    "path": "LICENSE",
    "content": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. 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\n   2. 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\n   3. 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\n   4. 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\n   5. 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\n   6. 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\n   7. 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\n   8. 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\n   9. 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\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: 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\n   Aardvark Platform\n   Copyright (C) 2006-2019  Aardvark Platform Team\n   https://aardvark.graphics\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "PACKAGES.md",
    "content": "# Approach\n\nStable packages will be pushed to nuget by the maintainers.\n\n# Developer packages\n\nCommunity packages go to github, for this register your github token using: \n`paket config add-token https://nuget.pkg.github.com/aardvark-platform   <token>`\n\nuse build pushgithub"
  },
  {
    "path": "README.md",
    "content": "# Aardvark.Base\n\n[![Build](https://github.com/aardvark-platform/aardvark.base/actions/workflows/build.yml/badge.svg)](https://github.com/aardvark-platform/aardvark.base/actions/workflows/build.yml)\n[![Publish](https://github.com/aardvark-platform/aardvark.base/actions/workflows/publish.yml/badge.svg)](https://github.com/aardvark-platform/aardvark.base/actions/workflows/publish.yml)\n[![License](https://img.shields.io/github/license/aardvark-platform/aardvark.base.svg?label=License)](https://github.com/aardvark-platform/aardvark.base/blob/master/LICENSE)\n[![NuGet](https://img.shields.io/nuget/v/Aardvark.Base.svg)](https://www.nuget.org/packages/Aardvark.Base/)\n\nHigh-performance .NET foundation for visual computing, real-time graphics and geometry processing. Cross-platform (Windows/Linux/macOS), targets .NET Standard 2.0 and .NET 8.0.\n\nFoundation of the [Aardvark Platform](https://github.com/aardvark-platform) ecosystem, powering advanced libraries for rendering (Aardvark.Rendering), UI (Aardvark.Media), VR/AR applications, and scientific visualization.\n\n## Core Components\n\n**Mathematics & Geometry**\n- Vectors, matrices, quaternions, transformations (2D/3D/4D)\n- Ranges, boxes, spheres, planes, rays, frustums\n- Polygons, meshes, BVH acceleration structures\n- Linear/ellipsoid regression, geometric algorithms\n\n**Image Processing**\n- PixImage with full tensor capabilities\n- Format support: JPEG, PNG, TIFF, EXR, WebP, DDS\n- Mipmaps, cube maps, volume textures\n- Hardware-accelerated scaling and transformations\n\n**Data Structures & Algorithms**\n- Incremental/reactive programming primitives\n- Efficient collections (IntDict, SymbolDict, MapExt)\n- Spatial indexing (KdTree, BVH)\n- Fast serialization/deserialization\n\n## Quick Start\n\n```csharp\nusing Aardvark.Base;\n\n// Vectors and matrices\nvar v = new V3d(1, 2, 3);\nvar m = M44d.RotationX(45.0.RadiansFromDegrees());\nvar transformed = m.TransformPos(v);\n\n// Image processing\nvar image = PixImage.Load(\"image.jpg\");\nvar scaled = image.Scaled(0.5);\nscaled.Save(\"output.png\");\n\n// Geometry\nvar box = new Box3d(V3d.Zero, V3d.One);\nvar ray = new Ray3d(V3d.Zero, V3d.XAxis);\nvar hit = ray.Intersects(box, out double t);\n```\n\n## Installation\n\n```\ndotnet add package Aardvark.Base\ndotnet add package Aardvark.Base.FSharp  # F# extensions\n```\n\n## Resources\n\n- [Gallery](https://github.com/aardvark-platform/aardvark.docs/wiki/Gallery)\n- [Packages & Repositories](https://github.com/aardvark-platform/aardvark.docs/wiki/Packages-and-Repositories)\n- [Documentation](https://github.com/aardvark-platform/aardvark.base/wiki)\n- [API Reference](https://aardvarkians.com/)\n- [Platform Overview](https://github.com/aardvark-platform/aardvark.docs/wiki)\n- [Discord Community](https://discord.gg/UyecnhM)\n- [AI Reference](./ai/) - Technical docs for AI coding assistants\n\n## License\n\n[Apache 2.0](LICENSE)\n"
  },
  {
    "path": "RELEASE_NOTES.md",
    "content": "- [IO] Hardened `UberStream` constructor and read/write argument validation\n- [Base] Made `EnumerableEx.AllDistinct` and `AllEqual` enumerate inputs only once\n- [PixImage] Fixed save-parameter validation messages to report numeric values without a leading dollar sign\n- [Base] Hardened `Stream.ReadBytes` argument validation before reading\n- [Random] Fixed `TakeRandomly` to reject NaN probabilities\n- [Base] Fixed `SingleValueSymbolDict` value-only construction and shared-value setter/add behavior\n- [Essentials] Fixed `EventSourceSlim<T>` next-value awaitables and non-generic `IEvent` members\n- [Base] Completed `SingleEntryDict` lookup, removal, and re-add behavior\n- [Geometry] Fixed `Plane3.Project` array-slice validation for ranges ending at the array length\n- [Base] Fixed `EnumerableEx.SelectToList` overloads for arrays and lists\n- [Base] Fixed `StringFun.Plural` for empty and one-character words\n- [Base] Fixed `ListFun.Map3` to truncate to the shortest input list when the third list is shortest\n- [Base] Hardened `Adler32` input validation for null inputs and invalid array ranges\n- [Random] Fixed `RandomSystem` boundary handling for inclusive integer and open/closed floating-point samples\n- [Geometry] Implemented `Quad2.Contains(...)` overloads for lines, triangles, quads, and circles\n- [FSharp] Fixed null-argument validation for custom `Seq` helpers\n- [FSharp] Fixed `Seq.foldi` to pass the correct element index\n- [Essentials] Fixed `Task.WithCancellation` for already-canceled tokens\n\n### 5.3.23\n- [CI] Added a publish workflow early exit when release notes already match the latest GitHub Release\n\n### 5.3.22\n- [Telemetry] Fixed `WallClockTimer` timer disposal so repeated `Dispose` calls do not corrupt timer state\n- [Introspection] Fixed native library loading on Windows using netstandard2.0 (https://github.com/aardvark-platform/aardvark.base/issues/86)\n- [Base] Fixed `Dict.Contains(key, value)` for collided entries in hash buckets\n- [Base] Fixed reentrant `Dict.GetOrCreate`\n- [Base] Fixed linear polynomial real roots\n- [Base] Fixed special dict setter behavior\n- [Base] Added fast values enumerator API for dict types\n- [PixImage] Improved reporting of inner exceptions thrown by loaders and processors\n- [FSharp] Added `Array.chooseV` and `Array.chooseiV`\n- [FSharp] Added `Array.zipV` and `Array.unzipV`\n- [FSharp] Fixed null-input handling for custom array ValueOption helpers\n- [FSharp] Added intersection methods using `ValueOption` for `BvhTree` and `KdTree`\n\n### 5.3.21\n- [Base] Simplified computation of Constant<T>.MachineEpsilon\n- [FSharp] Fixed MapExt.choose2 and MapExt.map2\n\n### 5.3.20\n- [Base] Improved native library loading and symlink creation\n- [FSharp] Added utilities for copying streams\n- [Fonts] Added Font.LoadFromAssembly for loading embedded fonts\n- [Fonts] Improved error reporting by font resolver\n- [Fonts] Added missing Symbola font\n- [Fonts] Implemented font resolver for Linux\n- [Base] Added hashing extensions for typed arrays in NET Standard 2.0 to improve binary compatibility with .NET 8 build.\n\n### 5.3.19\n- [Color] Added missing over- and underflow checks\n- [PixCube] Added null- and length checks for input arrays\n- [PixCube] Added IsEmpty\n\n### 5.3.18\n- Added ReadOnlySpan overloads for Cell, Cell2d, and range types\n- [Tensors] Added and improved XML documentation\n- [Tensors] Added PixImage and PixVolume constructors for data arrays\n- [Color] Added over- and underflow checks for integer-based arithmetic operators\n- [Color] Deprecated addition and subtraction of different types\n- [Color] Deprecated integer-based multiplication and division\n- [FSharpMath] Added min, max overloads for uint vectors\n- [Introspection] Added overloads for unpacking native dependencies for a specific platform\n\n### 5.3.17\n- [FSharp] Added non-generic isNull and notNull\n- [FSharp] Added generic inc and dec\n- [FSharp] Fixed generic constraint of NativePtr.stackUseArr\n\n### 5.3.16\n- Fixed Cell.XYZ bug and improved doc comments\n- [FSharp] Added PinnedValue and PinnedValue<'T> utility for pinning values and arrays with IDisposable semantics\n- [FSharp] Added explicit type parameters to NativePtr functions\n- [PixImage] Improved error messages regarding image loaders\n\n### 5.3.15\n- [Geometry] fixed GetPlane/GetTrafo for LinearRegression2d\n- [Math] Added Fun.IsPowerOfTwo, Fun.NextPowerOfTwo, Fun.PrevPowerOfTwo overloads for uint32 and uint64\n\n### 5.3.14\n- [FSharp] Added workaround for compiler-related bug in NativePtr.pin, pinArr, and pinArri (https://github.com/dotnet/fsharp/issues/18689)\n- [FSharp] Added tryLastV for Seq, List, and Array\n\n### 5.3.13\n- [FSharp] Added null-coalesing operator ||?\n- [FSharp] Added Seq.asArray\n- [FSharp] Added IDictionary and IReadOnlyDictionary interfaces for MapExt\n- [FSharp] Added tryFindV, tryPickV, pickV, tryHeadV for Seq, List, and Array\n- [Base] Added IDictionary and IReadOnlyDictionary interfaces for Dict, IntDict, SymbolDict, DictIEq\n- [Base] Added ContainsValue() for Dict types\n- [Ag] Use ValueOption internally and added overloads for public API returning ValueOption\n\n### 5.3.12\n- Fixed regression in range constructors\n\n### 5.3.11\n- Fixed range constructors for empty and null arrays and sequences\n- Added GrayAlpha pixel format constants\n- Added ToString() override for PixFormat\n- Added PixFileFormat.Webp and PixWebpSaveParams\n- Added more known image file extensions\n- Added PixTiffSaveParams for choosing the compression scheme when saving TIFF images\n- Added PixExrSaveParams for choosing the compression scheme when saving EXR images\n\n### 5.3.10\n- [IO] Added SymMap constructor overload\n\n### 5.3.9\n- [Base] Added AliasTable\n- [Base] Added Triangle.Distance\n- [Base] Added Triangle.SolidAngle\n- [FSharp] Added NativePtr.stackUseArr\n- [FSharp] Added Map.tryFindV\n- [FSharp] Added Map.ofSeqWithDuplicates\n- [FSharp] Added choosei, collecti for Seq, List, Array\n- [FSharp] Added assignment operators\n- [FSharp] Added Type.CLRSize extension property\n- [Introspection] Made native library loading more robust\n- [Introspection] Fixed issue with plugin cache invalidation\n- [Report] Using Stopwatch.GetTimestamp() instead of Stopwatch instance in ReportJob\n\n### 5.3.8\n- [FSharp] Added stableSum and stableSumBy for List, Array, and Seq\n- added basic BbTree implementation without operations\n\n### 5.3.7\n- Marked quaternion to matrix conversion obsolete as it is misleading\n- Added conversions between ranges and 2D vectors\n- Added Lerp and InvLerp for integer ranges and boxes\n- Unified native dependency unpacking and added Aardvark.UnpackAndListNativeDependencies\n\n### 5.3.6\n- Updated System.Text.Json dependency (CVE-2024-43485)\n- Added angle conversion utilities for ranges\n- Added Ray3.Transformed overloads\n- Added Ray3.Normalized\n- Added Vec.AngleBetweenSigned for 2D vectors\n- Added Fun.WrapToPi\n- Added 2D ray-circle intersection methods\n\n### 5.3.5\n- [Base] added IsEmpty/IsEmptyOrNull overloads for Array/ICollection with efficient implementation\n- [Base] added FindValue and FindNeighboursV to SortedSet\n- [FSharp] changed MemoryManager/FreeList to use value tuples/options and use new SortedSet methods\n- [FSharp] added Path.normalizeDirectorySeparators\n- [FSharp] fixed Path.withTrailingSlash and Path.withoutTrailingSlash to consider Path.AltDirectorySeparatorChar\n\n### 5.3.4\n- [FSharp] Moved pin utilities to modules; added pinArri, temp\n- Prevent multiple invocations of Aardvark.Init\n- Added new PixProcessor API for plugin-based scaling, rotating and remapping of images (replaces PixImage.SetScaledFun et al.)\n\n### 5.3.3\n- Optimized ReferenceCountingSet (struct enumerator, internal struct tuples)\n- Restored MD5 hashing extensions (fixes: https://github.com/aardvark-platform/aardvark.base/issues/72)\n- [Introspection] Native libraries are now unpacked to the default Aardvark cache directory with subfolders for each platform (fixes: https://github.com/aardvark-platform/aardvark.base/issues/81).\n- [Introspection] Improved support for single file deployment. Fixed plugin loading and caching (fixes: https://github.com/aardvark-platform/aardvark.base/issues/65).\n- [Introspection] Made assembly loading more robust for NET 8. If an assembly cannot be resolved the entry path is checked for the assembly file, making it possible to load assemblies by name that are not runtime or compilation dependencies (see also: https://github.com/Particular/Workshop/issues/64).\n- [FSharp] Added RequireQualifiedAccess attribute to ProcListValue\n- [FSharp] Added RequireQualifiedAccess attribute to Tree\n- [FSharp] Added pin, pinArr, and NativePtr.Address\n- Added Stream.ReadBytes extension\n\n### 5.3.2\n- [FSharp] Revert LookupTable utilities to use lists instead of seq\n\n### 5.3.1\n- [FSharp] Added Stream.readAllBytes\n- [FSharp] Added Path.withTrailingSlash and withoutTrailingSlash\n- [FSharp] Added approximateEquals\n- [FSharp] Reworked LookupTable utilities\n- [FSharp] Optimized and reworked type patterns\n- [FSharp] Imported PrimitiveValueConverter from Aardvark.Rendering\n\n### 5.3.0\n- https://github.com/aardvark-platform/aardvark.base/wiki/Aardvark-5.3-changelog\n\n### 5.3.0-prerelease0005\n- Reintroduced `IPixImage` as `IPix`\n- Renamed `PixImageCube` to `PixCube`\n\n### 5.3.0-prerelease0004\n- Fixed PixImage/Volume conversion with redundant channels\n- Added Width, Height, and Depth properties for PixImage and PixVolume\n\n### 5.3.0-prerelease0003\n- Restored Error<'T>\n- [PixImageMipMap] Re-added PixFormat and reverted rename of ImageArray field\n- [PixImageMipMap] Renamed Count to LevelCount\n- [PixImageCube] Reverted rename of MipMapArray field\n- [PixLoader] Added CanEncode and CanDecode\n- Made Array and Data of PixImage and PixVolume consistent with tensors\n\n### 5.3.0-prerelease0002\n- Removed Result<'T> alias\n- [FSharpMath] Fixed conflicts in SRTP member names with .NET\n- [Color] Added Fun.Lerp overloads with vector parameter\n\n### 5.3.0-prerelease0001\n- Initial prerelease\n\n### 5.2.32\n- Fixed Type.GetCLRSize for structs\n- Use .NET functions for Array.Copy and Set\n- Fixed Array CopyTo extension overloads for copying between an array and native memory\n- Changed SymMapBaseCollectionTraversal.Collect typeName argument to Symbol\n- Added ToBase64 extensions with span\n- Added generic Compute**Hash overloads (avoiding GetCLRSize)\n- Added AsCastSpan extension\n\n### 5.2.31\n* fixed Hash Computations for non-primitive types\n* added `AsByteSpan` extension method for System.Array/string in >=net6.0\n\n### 5.2.30\n* removed UnsafeCoerce usages and several other net6.0+ fixes\n \n### 5.2.29\n* Fixed color parsing to be independent of the current culture (regression in 5.2.27)\n* Added more value variants for Dictionary, Dict, and SymbolDict functions\n\n### 5.2.28\n* Added Brewer color schemes\n* Added String.replace\n* Added IDictionary.TryPop overload with output argument\n\n### 5.2.27\n* Improved and fixed RangeSet implementation\n* Added utilities for ValueOption\n* Added more ArraySegment utilities\n* [Text] Fixed NestedBracketSplitCount\n* [Color] Fixed overflow issue in C4ui constructors\n* [Color] Improved color parsing, now supports hexadecimal color strings\n* [PixImage] Fixed file handle leak in Windows Media loader\n* [MapExt] Added value variants of some operations\n\n### 5.2.26\n* LinearRegression3d: made fields public\n* Added getLines, normalizeLineEndings, withLineNumbers in String module\n* Fixed FGetValueOrDefault dictionary extension\n* Added value variants for Dict functions\n* Added F# ArraySegment utilities\n* [Introspection] Tidied up exception reporting\n\n### 5.2.25\n* Fixed issue with PixImageMipMap loading\n* Improved exception message of EnumHelpers methods\n* [Introspection] Use XML serialization for plugin cache\n* Replaced netcoreapp3.1 target with net6.0\n\n### 5.2.24\n* fixed and optimized Cell.Contains\n* update Aardvark.Build to 1.0.19\n\n### 5.2.23\n* Fixed build for VS 2019 / .NET 6\n\n### 5.2.22\n* Fixed RandomSample.Lambertian internal calculation precision\n* Added float bits method overloads for unsigned vectors\n* Use reflection-based PixImageMipMap creation\n* [TypeInfo] Added color-related types and patterns\n* [Trafo] Implemented infinite far plane for perspective projection\n* [Trafo] Added reversed perspective projection variants\n* [Introspection] Increased verbosity level of custom attribute error\n\n### 5.2.21\n* Made non-generic PixImage creation more flexible and robust\n* Added NativePtr.Item and NativePtr.Value\n* Added Buffer.MemoryCopy overloads with nativeint arguments\n\n### 5.2.20\n* [Base] added float overloads to RandomSample methods\n* [Base] changed array memory copies to use Buffer.MemoryCopy\n* [PixImage] respect channel order in format and type conversion\n* [PixImage] improved support for dual-channel images\n* [PixImage] fixed and improved format conversion\n* [Tensors] added simple accessors for Gray and BW\n* [Vrml] added support for gzip compressed files\n* [Vrml] allow registration of custom field parsers\n* [Vrml] improved robustness in case of unknown field tokens\n\n### 5.2.19\n* Added IPixMipmapLoader for loading images with mipmap chains\n* Marked some exotic image loading functions obsolete\n\n### 5.2.18\n* made introspection attribute querying more robust\n\n### 5.2.17\n* JSON support\n\t- add missing Range1* types\n\t- handling of special float values (NaN, +Inf, -Inf)\n* Add Vec.w\n* Update Aardvark.Build\n\n### 5.2.16\n* support System.Text.Json for primitive types \n  (vectors, matrices, boxes, transforms, geometric primitives, ...)\n\n### 5.2.15\n* Added File.writeAll* variants that create parent directories\n* [IO] Added logging output in case there is a stream position mismatch\n* [PixImage] Print path when loading from file stream\n\n### 5.2.14\n* Updated to ImageSharp 2.1\n* Implemented default PixImage scaling function\n* Configurable PixImage functions throw proper exceptions\n* Added float16 support for PixImageMipMap\n* [Introspection] changed logging message when using CustomEntryAssembly from warning to normal\n\n### 5.2.13\n* Added uint32 vector types (V2ui, V3ui, V4ui)\n* Added Disposable.empty\n* Inlined color conversion methods, deprecating lambdas\n* Implemented color conversions for Float16\n* [Patterns] Added 2x3 matrices\n\n### 5.2.12\n* Added Fun.PowerOfTwo for int32 vectors\n* [FSharpMath] Added exp2, step, and linearstep\n* [Patterns] Added missing vector and matrix types\n* Added Fun.Step and Fun.Linearstep\n\n### 5.2.11\n* [Ag] Removed compiler message\n\n### 5.2.10\n* fixed VRML transformations (missing normalization)\n\n### 5.2.9\n* Executable memory tools are now obsolete (use Aardvark.Assembler nuget package instead)\n\n### 5.2.8\n* revert obsolete AMD64 assembler to original behaviour\n\n### 5.2.7\n* fixed AMD64 assembler Begin/End (saving callee saved registers)\n\n### 5.2.6\n- [PixImage.SystemDrawing] removed System.Drawing.Common upper version constraint\n- [IO] BinaryReadingCoder: patch object reference after converter/proxy conversion (#77)\n\n### 5.2.5\n- Ported System.Drawing bitmap extensions to new PixLoader API (renamed to Aardvark.PixImage.SystemDrawing)\n- Added Aardvark.PixImage.WindowsMedia\n- Added Trafo.(Inv)TransformPosProj(Full)\n- Added constructors and comments for tensor info structs\n\n### 5.2.4\n- Added new API for PixImage loading and saving\n- Added PixImage.meanSquaredError and PixImage.peakSignalToNoiseRatio\n- Moved System.Drawing primitives extensions to Aardvark.Base.SystemDrawingInterop\n\n### 5.2.3\n- Added transform methods for Trafo types\n- Added float32 overload for WeightedSum\n- Fixed Plane3d.Transformed methods\n- Added remainder operator for vector types\n- Made Col.FormatDefaultOf more flexible\n- [Report] Create directory for log file if it does not exist\n- Added RangeSet64\n\n### 5.2.2\n- [ImageSharp] Implemented proper per row processing\n\n### 5.2.1\n- [ImageSharp] Switched to contiguous image buffers\n\n### 5.2.0\n- https://github.com/aardvark-platform/aardvark.docs/wiki/Aardvark-5.2-changelog\n\n### 5.1.27\n- added Transformed method for MatrixInfo and VolumeInfo\n- fixed ldconfig regex for entries with ABI\n\n### 5.1.26\n- added PixImage and PixVolume related extensions to native tensors\n- added PolyRegion2d.Overlaps(Box2d)\n- fixed byte color indexing\n- removed unnecessary DevILSharp references\n- added Map.unionMany\n- fixed Ceres native unpack\n- workaround for loading native IPP dependencies\n\n### 5.1.25\n- another SHA1 truncate\n\n### 5.1.24\n- \"simulated\" MD5 via truncated SHA1 (please don't hit me security bubble)\n\n### 5.1.23\n- switched MD5 to SHA1\n\n### 5.1.22\n- updated to FSharp.Core >= 5.0.0\n\n### 5.1.21\n- [Report] workaround for getting/setting Console.ForegroundColor when not available. added `NoTarget` to Report for disabling\n\n### 5.1.20\n- add Cell.GetCommonRoot(...) and corresponding constructor overloads; same for Cell2d\n\n### 5.1.19\n- fixed cell-from-box constructor for boxes with Max including 0.0\n- Relax asserts in matrix and rot methods and constructors\n\n### 5.1.18\n- cleaned up and fixed cell construction from boxes\n\n### 5.1.17\n- Add Fun.Log2CeilingInt\n- Fix power of two edge cases in Cell and Cell2d\n\n### 5.1.16\n- updated build script\n- fixed PixImage.CreateRaw loader fallback\n- fixed default AssemblyFilter\n- fixed Introspection ignoring GLSLangSharp\n- unbreak Cell to work with fixed Log2Int (same for Cell2d)\n\n### 5.1.15\n - added functions for computing mipmap level count and size\n - added support for signed integer PixImages\n - changed default introspection cache location to LocalApplicationData\n - fixed Log2Int\n - fixed missing FileStream Dispose in Vrml97 parser\n\n### 5.1.14\n - fixed Introspection caching\n\n### 5.1.13\n - added Plane2d.Intersects overload that was removed accidentally\n\n### 5.1.12\n - added missing XmlIgnore attribute to vector swizzles\n - added ValuesWithKeyEnumerator to Dicts\n - preparations for .net 5 single file deployment\n - added missing finite checks to vectors and matrices\n - added vector variants for Fun.FloatToBits and Fun.FloatFromBits\n - fixed Box2d - Line2d intersection test\n - fixed Plane2d - Ray2d intersection test\n - fixed polygon extensions\n\n### 5.1.11\n - added some IAssemblerStream methods (AddInt, MulInt, etc.)\n\n### 5.1.10\n - fixed mscorlib recursive resource lookup (#61)\n - added Constant<T> initialization (#59)\n\n### 5.1.9\n- removed System.Reactive depdendency\n- raised FSharp.Core version to >= 4.7.0\n\n### 5.1.8\n\n- added polygon transformataions (#57)\n- prioritization of custom images loaders: considering last registered first\n- consistency and completeness of Ray3d.Hits overloads\n- changed Ray3d.Hits default range to [0, double.MaxValue]\n\n### 5.1.6\n\n- fixed Fun.Frac for tiny negative numbers\n- added invLerp to FSharpMath\n\n### 5.1.5\n\n- devil loader functions are now public\n\n### 5.1.4\n\n- updated to FSharp.Data.Adaptive 1.2\n- added IEquatable to math types\n- added Array.binarySearch\n\n### 5.1.3\n\n- udpated build script\n\n### 5.1.2\n\n- testing\n- new package mechanism\n\n### 5.1.1\n\n- switched to FSharp.Data.Adaptive 1.1\n"
  },
  {
    "path": "ai/ALGORITHMS.md",
    "content": "# Aardvark.Base Algorithms Reference\n\nSource-verified map of key algorithm types and entry points.\n\n## ShortestPath<T>\n\n`ShortestPath<T>` implements `IShortestPath<T>` and runs asynchronous shortest-path computation.\n\nKey methods:\n\n- `CalculateShortestPaths(T seed)`\n- `CalculateShortestPathsByIndex(int seedIndex)`\n- `GetMinimalPath(T target)`\n- `GetMinimalPathByIndex(int targetIndex)`\n- `Cancel()`\n\nConstructors:\n\n```csharp\nnew ShortestPath<T>(List<T> nodes, List<(int,int)> edges, Func<T,T,float> getCost);\nnew ShortestPath<T>(T[] nodes, List<int>[] neighbors, Func<T,T,float> getCost);\n```\n\n## BbTree\n\nBounding-box hierarchy in `Geometry/BbTree.cs`.\n\nConstructor:\n\n```csharp\nnew BbTree(Box3d[] boundingBoxes, BbTree.BuildFlags flags = BbTree.BuildFlags.Default, int[] countArray = null);\n```\n\nUseful members:\n\n- `NodeCount`\n- `Box3d`\n- `IndexArray`\n- `LeafArray`\n- `LeftBoxArray`\n- `RightBoxArray`\n- `GetLeft(i)`, `GetRight(i)`\n\n`BbTreeHit` contains `NodeIndex` and `RayT`.\n\n## Linear Algebra Numerics\n\nAvailable in `Math/LuFactorization.cs` and `Math/QrFactorization.cs`:\n\n- `LuFactorize`\n- `LuSolve`\n- `LuInverse`\n- `QrFactorize`\n\n`LuFactorize` is in-place.\n\n## Probability Sampling\n\n### Alias tables\n\nTypes:\n\n- `AliasTableF`\n- `AliasTableD`\n\nConstruction/update:\n\n```csharp\nvar t = new AliasTableD(pdf, 1.0 / pdf.Sum());\nt.Update(newPdf, 1.0 / newPdf.Sum());\nint index = t.Sample(rnd.UniformDouble());\n```\n\n`FromPdf` / `FromNormalizedPdf` exist as instance methods on the class.\n\n### DistributionFunction\n\n`DistributionFunction` provides CDF-based sampling:\n\n```csharp\nvar d = new DistributionFunction(pdf);\nint i = d.Sample(rnd);\nint j = DistributionFunction.SampleCDF(d.CDF, rnd.UniformDouble());\n```\n\n## Polynomial\n\n`Polynomial` is in `Math/Numerics/Polynomial.cs` (not `Math/Base`).\n\nExamples:\n\n- `coeff.Evaluate(x)`\n- `coeff.Derivative()`\n- `Polynomial.RealRootsOfNormed(...)`\n\n## Source Anchors\n\n- `src/Aardvark.Base/AlgoDat/ShortestPath.cs`\n- `src/Aardvark.Base/Geometry/BbTree.cs`\n- `src/Aardvark.Base/Math/LuFactorization.cs`\n- `src/Aardvark.Base/Math/QrFactorization.cs`\n- `src/Aardvark.Base/Math/Base/AliasTable_auto.cs`\n- `src/Aardvark.Base/Math/Base/DistributionFunction.cs`\n- `src/Aardvark.Base/Math/Numerics/Polynomial.cs`\n"
  },
  {
    "path": "ai/COLLECTIONS.md",
    "content": "# Aardvark.Base Collections Reference\n\nSource-verified reference for custom collection and symbol infrastructure.\n\n## Symbol and TypedSymbol\n\n`Symbol` is interned and integer-backed.\n\n```csharp\nSymbol s0 = Symbol.Create(\"name\");\nSymbol s1 = \"name\";                 // implicit conversion\nSymbol s2 = Symbol.Create(Guid.NewGuid());\nSymbol empty = Symbol.Empty;\nSymbol neg = -s0;                   // negative key variant\n```\n\nImportant members:\n\n- `Id`\n- `IsEmpty` / `IsNotEmpty`\n- `IsPositive` / `IsNegative`\n- `ToGuid()`\n\n`TypedSymbol<T>` provides compile-time value type pairing for typed dictionary access.\n\n## Dict Family\n\nMain types in `Symbol/Dict_auto.cs`:\n\n- `Dict<TKey, TValue>`\n- `DictSet<TKey>`\n- `SymbolDict<TValue>`\n- `SymbolSet`\n\nCommon helpers:\n\n- `GetOrCreate(...)`\n- `TryRemove(...)`\n- `ValuesWithKey(...)`\n\n`SymbolDict<T>` also has typed overloads:\n\n- `Add<TType>(TypedSymbol<TType> key, TType value)`\n- `Get<TType>(TypedSymbol<TType> key)`\n- `TryGetValue<TType>(TypedSymbol<TType> key, out TType value)`\n\n## LruCache<TKey, TValue>\n\n`LruCache` is synchronized and capacity-driven.\n\nConstructors:\n\n```csharp\nnew LruCache<TKey, TValue>(capacity);\nnew LruCache<TKey, TValue>(capacity, sizeFun, readFun, deleteAct);\n```\n\nKey operations:\n\n- indexer `cache[key]` (auto-load with `readFun`)\n- `GetOrAdd(...)`\n- `TryRemove(...)`\n- `Remove(...)`\n- mutable `Capacity` (can trigger eviction)\n\n## ConcurrentHashSet<T>\n\nDefined in namespace `System.Collections.Concurrent`.\n\nCore operations:\n\n```csharp\nset.Add(item);\nset.Remove(item);   // no TryRemove API on this type\nset.Contains(item);\nset.Clear();\nset.UnionWith(other);\n```\n\n## SingleEntryDict\n\n`SingleEntryDict<TKey, TValue>` exists in `Symbol/Dicts.cs` and is optimized for one optional key/value entry. It supports normal `IDict<TKey, TValue>` lookup, removal, and re-adding the configured key after removal.\n\n## Source Anchors\n\n- `src/Aardvark.Base/Symbol/Symbol.cs`\n- `src/Aardvark.Base/Symbol/Dict_auto.cs`\n- `src/Aardvark.Base/Symbol/Dicts.cs`\n- `src/Aardvark.Base/Symbol/IDict.cs`\n- `src/Aardvark.Base/AlgoDat/LruCache.cs`\n- `src/Aardvark.Base/AlgoDat/ConcurrentHashSet.cs`\n"
  },
  {
    "path": "ai/DOC_ACCURACY_AUDIT.md",
    "content": "# AI Docs Accuracy Audit\n\nAudit baseline for coding-agent docs in this repository.\n\n## Last Audit\n\n- Date: 2026-02-26\n- Scope: `AGENTS.md`, `ai/*.md`, `docs/*.md`, selected source anchors\n\n## Verified Corrections in This Audit\n\n1. Added task-split docs for semantic depth:\n   - `ai/SEMANTICS_LINEAR_ALGEBRA.md`\n   - `ai/SEMANTICS_GEOMETRY_CORE.md`\n2. Added symbol-first discovery index:\n   - `ai/SYMBOL_INDEX.md`\n3. Rewrote inaccurate AI topic docs:\n   - `ai/UTILITIES.md`\n   - `ai/COLLECTIONS.md`\n   - `ai/ALGORITHMS.md`\n   - `ai/PIXIMAGE.md`\n   - `ai/TENSORS.md`\n4. Corrected user-facing docs that had stale command guidance:\n   - `docs/CONTRIBUTING.md`\n   - `docs/INTEROP.md`\n   - `docs/TROUBLESHOOTING.md`\n5. Added drift tooling:\n   - `tools/DocsChecker/*`\n   - `check-docs.sh`\n   - `check-docs.cmd`\n   - `.github/workflows/docs-check.yml`\n\n## Known High-Risk Drift Areas\n\n- Generated code APIs (`*_auto.cs`, `*_auto.fs`)\n- Cross-language dependencies between C# and F# projects\n- Matrix/transform semantics and interop assumptions\n- Pix/tensor APIs where historical examples often reference removed overloads\n\n## Maintenance Rule\n\nIf a PR changes public API behavior or key semantics:\n\n1. Update the relevant doc in `ai/` or `docs/`.\n2. Run docs checker (`./check-docs.sh` or `.\\check-docs.cmd`).\n3. Keep source anchors in sync with actual file locations/symbol names.\n\n## Rules Touched In This Iteration\n\nDocs checker hardening added:\n\n1. Expanded required file coverage to additional AI topic docs.\n2. Expanded forbidden/required pattern checks for common stale examples.\n3. Expanded source-anchor coverage across primitives, tensors/pix, telemetry/random, collections, and algorithms.\n4. Added fixture-based checker tests (`tools/DocsChecker.Tests`).\n5. Enabled Linux + Windows hard-fail docs-check workflow matrix.\n"
  },
  {
    "path": "ai/FSHARP_INTEROP.md",
    "content": "# Aardvark.Base F# Interop Reference\n\nAI-targeted reference for using Aardvark.Base types from F#. Covers modules, extension functions, and idiomatic patterns.\n\n---\n\n## Namespace and Module Structure\n\n### Common Open Statements\n\n```fsharp\nopen Aardvark.Base                // Core types: V3d, M44d, Box3d, etc.\nopen Aardvark.Base.Sorting        // Sorting extension methods\n```\n\n### Module Hierarchy\n\n| Namespace | Contents |\n|-----------|----------|\n| `Aardvark.Base` | All primitive types + F# modules |\n| `Aardvark.Base.Sorting` | Array sorting extensions |\n\n---\n\n## Vec Module\n\nFunctional wrappers for vector operations. Works with any vector type (V2d, V3f, V4i, etc.).\n\n```fsharp\nopen Aardvark.Base\n\n// Dot product\nlet d = Vec.dot V3d.XAxis V3d.YAxis  // 0.0\n\n// Cross product (3D only)\nlet c = Vec.cross V3d.XAxis V3d.YAxis  // V3d.ZAxis\n\n// Length and normalization\nlet len = Vec.length V3d.One           // sqrt(3)\nlet lenSq = Vec.lengthSquared V3d.One  // 3.0\nlet unit = Vec.normalize V3d.One       // unit vector\n\n// Distance\nlet dist = Vec.distance V3d.Zero V3d.One\nlet distSq = Vec.distanceSquared V3d.Zero V3d.One\n\n// Swizzles\nlet x = Vec.x v3d\nlet xy = Vec.xy v3d      // V2d\nlet xyz = Vec.xyz v4d    // V3d\n\n// Reflection/refraction\nlet refl = Vec.reflect normal incident\nlet refr = Vec.refract eta normal incident\n\n// Component-wise comparisons\nVec.anySmaller V3d.One V3d.Zero    // false\nVec.allGreater V3d.One V3d.Zero    // true\nVec.anyEqual v1 v2\nVec.allDifferent v1 v2\n```\n\n---\n\n## Mat Module\n\nFunctional wrappers for matrix operations.\n\n```fsharp\nopen Aardvark.Base\n\n// Transpose, determinant, inverse\nlet mt = Mat.transpose M33d.Identity\nlet d = Mat.det M22d.Identity\nlet inv = Mat.inverse M33d.Identity\n\n// Transform vectors\nlet v4 = Mat.transform M44d.Identity V4d.One\nlet pos = Mat.transformPos M44d.Identity V3d.One   // w=1\nlet dir = Mat.transformDir M44d.Identity V3d.One   // w=0\nlet proj = Mat.transformPosProj M44d.Identity V3d.One  // with perspective divide\n\n// Component-wise comparisons\nMat.anyEqual m1 m2\nMat.allSmaller m1 m2\n```\n\n---\n\n## Trafo Module\n\nFunctional wrappers for transformation types.\n\n```fsharp\nopen Aardvark.Base\n\nlet t = Trafo3d.Translation(V3d(1, 2, 3))\n\n// Access matrices\nlet fwd = Trafo.forward t    // M44d forward matrix\nlet bwd = Trafo.backward t   // M44d inverse matrix\n\n// Invert\nlet inv = Trafo.inverse t\n\n// Compose and transform\nlet pos = V3d.Zero |> Mat.transformPos (t |> Trafo.forward)\n```\n\n---\n\n## Lens System\n\nFunctional lenses for immutable state updates. Used extensively with Adaptify-generated models.\n\n### Lens Type\n\n```fsharp\ntype Lens<'s, 'a> =\n    abstract Get : 's -> 'a\n    abstract Set : 's * 'a -> 's\n    abstract Update : 's * ('a -> 'a) -> 's\n```\n\n### Operators\n\n| Operator | Signature | Description |\n|----------|-----------|-------------|\n| `\\|.` | `Lens<'s,'a> -> Lens<'a,'b> -> Lens<'s,'b>` | Compose lenses |\n| `\\|?` | `Lens<'s, Option<'a>> -> 'a -> Lens<'s,'a>` | Default for None |\n\n### Usage\n\n```fsharp\nopen Aardvark.Base\n\n// Adaptify generates lenses like Model.position_\n// Compose with |. operator\nlet nestedLens = Model.inner_ |. Inner.value_\n\n// Get value\nlet v = nestedLens.Get model\n\n// Set value\nlet model' = nestedLens.Set(model, newValue)\n\n// Update value\nlet model'' = nestedLens.Update(model, fun v -> v + 1)\n```\n\n### Predefined Lenses\n\n```fsharp\n// Set membership lens\nSet.Lens.contains \"item\"  // Lens<Set<string>, bool>\n\n// Map item lens\nMap.Lens.item \"key\"       // Lens<Map<string,'v>, Option<'v>>\n\n// List item lens\nList.Lens.item 0          // Lens<list<'a>, Option<'a>>\n```\n\n---\n\n## Color Module (ColorBrewer)\n\nColor scheme generation for data visualization.\n\n```fsharp\nopen Aardvark.Base\n\n// Get sequential color scheme\nlet colors = ColorBrewer.getColors ColorBrewer.SchemeType.Sequential \"Blues\" 5\n\n// Available scheme types\nColorBrewer.SchemeType.Sequential    // Light to dark\nColorBrewer.SchemeType.Diverging     // Two-ended\nColorBrewer.SchemeType.Qualitative   // Distinct categories\n```\n\n---\n\n## Interop Modules\n\nF# extensions for .NET collections.\n\n### Dictionary Extensions\n\n```fsharp\nopen Aardvark.Base\n\nlet dict = System.Collections.Generic.Dictionary<string, int>()\n\n// F#-style access\ndict.[\"key\"] <- 42\nlet v = dict.[\"key\"]\n\n// TryFind returns Option\nmatch dict.TryFind \"key\" with\n| Some v -> ...\n| None -> ...\n```\n\n### HashSet Extensions\n\n```fsharp\nopen Aardvark.Base\n\nlet set = System.Collections.Generic.HashSet<int>()\n\n// Set operations return new sets\nlet union = set.Union otherSet\nlet inter = set.Intersect otherSet\n```\n\n---\n\n## Memory and Native Utilities\n\n### MicroTime (High-Resolution Timing)\n\n```fsharp\nopen Aardvark.Base\n\nlet start = MicroTime.Now\n// ... work ...\nlet elapsed = MicroTime.Now - start\nprintfn \"Elapsed: %A\" elapsed\n```\n\n### Mem (Memory Sizes)\n\n```fsharp\nopen Aardvark.Base\n\nlet size = Mem.mebibytes 512L\nprintfn \"%d bytes\" size.Bytes\n```\n\n---\n\n## Common Patterns\n\n### Pipeline with Transformations\n\n```fsharp\nlet result =\n    V3d.Zero\n    |> Mat.transformPos (Trafo3d.Translation(V3d.One) |> Trafo.forward)\n    |> Mat.transformDir (Trafo3d.RotationZ(Constant.Pi) |> Trafo.forward)\n```\n\n### Lens-Based State Updates\n\n```fsharp\n// Update nested model immutably\nlet model' =\n    model\n    |> (Model.camera_ |. Camera.position_).Set(V3d(0, 0, 10))\n    |> (Model.camera_ |. Camera.target_).Set(V3d.Zero)\n```\n\n### Vector Comparisons in Conditionals\n\n```fsharp\nif Vec.allSmaller point boxMax && Vec.allGreater point boxMin then\n    // point is inside box\n    ()\n```\n\n---\n\n## Gotchas\n\n1. **Module Suffix Convention**: F# modules like `Vec`, `Mat`, `Trafo` use `CompilationRepresentationFlags.ModuleSuffix` to avoid name collisions with types. Don't confuse `Vec` (module) with `V3d` (type)\n\n2. **Inline Functions**: Most `Vec` and `Mat` functions are `inline` with SRTP constraints. This means they work on any type with matching static members, but error messages can be cryptic if types don't match\n\n3. **Lens Composition Order**: `outer |. inner` reads left-to-right (outer first, then inner). This is opposite to function composition `>>`. Think of `|.` as \"then focus on\"\n\n4. **Option Lenses**: `Map.Lens.item` returns `Lens<_, Option<_>>`. Use `|?` operator to provide a default, or handle `None` explicitly\n\n---\n\n## See Also\n\n- [PRIMITIVE_TYPES.md](PRIMITIVE_TYPES.md) - C# API reference for V3d, M44d, Trafo3d (same types, method syntax)\n- [COLLECTIONS.md](COLLECTIONS.md) - Symbol and SymbolDict (usable from F# with same API)\n- [ALGORITHMS.md](ALGORITHMS.md) - Graph and spatial algorithms callable from F#\n"
  },
  {
    "path": "ai/INCREMENTAL.md",
    "content": "# Incremental/Adaptive System\n\nReactive computation with automatic dependency tracking. Values form a DAG; changes propagate lazily through dependencies.\n\n## Architecture\n\nBuilt on **FSharp.Data.Adaptive** (external NuGet package). Aardvark.Base.Incremental adds:\n- `afun` - adaptive functions\n- `astate` - stateful adaptive computations\n- `Controller` - UI-like state with previous-value tracking\n- `astream` - event streams with history (experimental)\n- `Proc` - cancellable continuations\n\nNamespace: `FSharp.Data.Adaptive` (core types from external package)\n\n## Core Types\n\n### Adaptive Values\n\n| Type | Description |\n|------|-------------|\n| `aval<'a>` / `IAdaptiveValue<T>` | Read-only adaptive value |\n| `cval<'a>` / `ChangeableValue<T>` | Mutable adaptive value (source) |\n\n```fsharp\n// F#\nlet counter = cval 0\nlet doubled = counter |> AVal.map ((*) 2)\nlet value = AVal.force doubled  // 0\n```\n\n```csharp\n// C#\nvar counter = new ChangeableValue<int>(0);\nvar doubled = counter.Map(x => x * 2);\nint value = doubled.GetValue();  // 0\n```\n\n### Adaptive Collections\n\n| Type | C# Type | Delta Type |\n|------|---------|------------|\n| `aset<'a>` | `ChangeableHashSet<T>` | `HashSetDelta<T>` |\n| `amap<'k,'v>` | `ChangeableHashMap<K,V>` | `HashMapDelta<K,V>` |\n| `alist<'a>` | `ChangeableIndexList<T>` | `IndexListDelta<T>` |\n\nCollections track changes via delta objects. Use readers to get incremental updates.\n\n```csharp\n// C#\nvar set = new ChangeableHashSet<int>(new[] { 1, 2, 3 });\nvar filtered = set.Filter(x => x > 1);\nvar reader = filtered.GetReader();\n\n// Get deltas since last read\nvar deltas = reader.GetChanges(AdaptiveToken.Top);\nforeach (var d in deltas)\n{\n    if (d.Count > 0) Console.WriteLine($\"add {d.Value}\");\n    else Console.WriteLine($\"rem {d.Value}\");\n}\n```\n\n## Transactions\n\nMutations must occur inside transactions. Changes batch until transaction ends.\n\n```fsharp\n// F#\ntransact (fun () ->\n    counter.Value <- 1\n    counter.Value <- 2  // only final value propagates\n)\n```\n\n```csharp\n// C#\nusing (Adaptive.Transact)\n{\n    counter.Value = 1;\n    counter.Value = 2;  // only final value propagates\n}\n```\n\n### AdaptiveToken\n\nTracks evaluation context and dependencies. Use `AdaptiveToken.Top` for top-level reads.\n\n```fsharp\nlet value = myAVal.GetValue(AdaptiveToken.Top)\n```\n\n```csharp\nvar value = myAVal.GetValue(AdaptiveToken.Top);\n```\n\n## F# Operators\n\nFrom `FSharp.Data.Adaptive.Operators`:\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| `%+` | Adaptive add | `a %+ b` |\n| `%-` | Adaptive subtract | `a %- b` |\n| `%*` | Adaptive multiply | `a %* b` |\n| `%/` | Adaptive divide | `a %/ b` |\n| `%&&` | Adaptive AND | `a %&& b` |\n| `%||` | Adaptive OR | `a %|| b` |\n| `%?` / `%.` | Conditional | `cond %? trueVal %. falseVal` |\n| `!!` | Force value | `!!aval` |\n| `~~` | Make constant | `~~42` |\n\n```fsharp\nopen FSharp.Data.Adaptive.Operators\n\nlet a = cval 10\nlet b = cval 20\nlet sum = a %+ b        // aval<int> = 30\nlet forced = !!sum      // int = 30\nlet const = ~~100       // aval<int> (constant)\n```\n\n## Adaptive Functions (afun)\n\nFunctions that depend on adaptive values. Re-evaluated when dependencies change.\n\n```fsharp\ntype afun<'a, 'b>  // IAdaptiveFunc in C#\n```\n\n### AFun Module\n\n| Function | Description |\n|----------|-------------|\n| `AFun.create f` | Wrap pure function |\n| `AFun.constant v` | Always return v |\n| `AFun.bind f m` | Bind aval to afun |\n| `AFun.compose g f` | Compose: f then g |\n| `AFun.apply v f` | Apply afun to aval |\n| `AFun.run v f` | Run afun with constant input |\n\n```fsharp\n// Builder syntax\nlet myFunc = afun {\n    let! scale = scaleAVal\n    return fun x -> x * scale\n}\n\n// Composition\nlet combined = f >>. g  // f then g\nlet combined = g <<. f  // same as above\n```\n\n### Integration\n\n```fsharp\nlet result : aval<'b> = AFun.apply inputAVal myFunc\n```\n\n## Adaptive State (astate)\n\nStateful computations that thread state through evaluation.\n\n```fsharp\ntype astate<'s, 'a> = { runState: afun<'s, 's * 'a> }\n```\n\n### AState Module\n\n| Function | Description |\n|----------|-------------|\n| `AState.create v` | Return value, preserve state |\n| `AState.map f m` | Transform result |\n| `AState.bind f m` | Sequence computations |\n| `AState.getState` | Get current state |\n| `AState.putState s` | Replace state |\n| `AState.modifyState f` | Transform state |\n\n```fsharp\nlet computation = astate {\n    let! current = AState.getState\n    do! AState.modifyState ((+) 1)\n    return current\n}\n```\n\n### Controller Pattern\n\nTracks previous values across evaluations. Used for UI-like delta computation.\n\n```fsharp\ntype Controller<'a> = astate<ControllerState, 'a>\n```\n\n| Function | Description |\n|----------|-------------|\n| `withLast aval` | Get `(previous, current)` tuple |\n| `pre aval` | Get previous value |\n| `differentiate aval` | Get `current - previous` |\n\n```fsharp\nlet deltaController = controller {\n    let! (prev, curr) = withLast positionAVal\n    return curr - prev  // movement delta\n}\n\nlet myFunc : afun<'a, 'b> = controller.Run(deltaController)\n```\n\n## Adaptive Streams (astream)\n\nEvent streams with timestamped history. **Experimental** - namespace: `Aardvark.Base.Incremental.Experimental`\n\n```fsharp\ntype astream<'a>  // IAdaptiveStream in C#\n\ntype EventHistory<'a> =\n    | Cancel\n    | Faulted of Exception\n    | History of list<DateTime * 'a>\n```\n\n### IStreamReader\n\n```fsharp\ntype IStreamReader<'a> =\n    inherit IDisposable\n    inherit IAdaptiveObject\n    abstract GetHistory : IAdaptiveObject -> EventHistory<'a>\n    abstract SubscribeOnEvaluate : (EventHistory<'a> -> unit) -> IDisposable\n```\n\n### EventHistory Module\n\n| Function | Description |\n|----------|-------------|\n| `EventHistory.empty` | Empty history |\n| `EventHistory.map f h` | Transform events |\n| `EventHistory.choose f h` | Filter/transform |\n| `EventHistory.filter f h` | Filter events |\n| `EventHistory.union l r` | Merge histories |\n| `EventHistory.concat hs` | Concatenate list |\n\n## Proc (Cancellable Continuations)\n\nContinuation-based async with cancellation support.\n\n```fsharp\ntype Proc<'a, 'r>\n\ntype ProcResult<'a> =\n    | Value of 'a\n    | Cancelled\n    | Faulted of exn\n```\n\n### Creating Procs\n\n| Method | Description |\n|--------|-------------|\n| `Proc.Create v` | Immediate value |\n| `Proc.Await task` | Await Task<T> |\n| `Proc.Await async` | Await Async<T> |\n| `Proc.Await sem` | Await SemaphoreSlim |\n| `Proc.Sleep ms` | Delay |\n\n### Running Procs\n\n| Method | Description |\n|--------|-------------|\n| `Proc.RunSynchronously(p, ?ct)` | Block until complete |\n| `Proc.StartAsTask(p, ?ct)` | Return Task<ProcResult> |\n| `Proc.Start(p, ?ct)` | Fire and forget |\n\n### Builder Syntax\n\n```fsharp\nlet download url = proc {\n    let! response = httpClient.GetAsync(url)\n    let! content = response.Content.ReadAsStringAsync()\n    return content\n}\n\n// Run with cancellation\nuse cts = new CancellationTokenSource()\nlet result = Proc.RunSynchronously(download \"http://...\", cts.Token)\nmatch result with\n| Value content -> printfn \"Got: %s\" content\n| Cancelled -> printfn \"Cancelled\"\n| Faulted e -> printfn \"Error: %A\" e\n```\n\n## ChangeTracker\n\nDetect value changes with memoization. Used internally by afun/astate.\n\n```fsharp\n// Default equality\nlet hasChanged = ChangeTracker.track<MyType>\nif hasChanged newValue then\n    // value changed since last call\n\n// Custom equality\nlet hasChanged = ChangeTracker.trackCustom (Some myEqualityFn)\n```\n\n## Common Patterns\n\n### Reactive Collection Processing\n\n```csharp\nvar items = new ChangeableHashSet<Item>();\nvar processed = items\n    .Filter(x => x.IsActive)\n    .Map(x => ProcessItem(x));\n\nvar reader = processed.GetReader();\n// On each frame/update:\nvar changes = reader.GetChanges(AdaptiveToken.Top);\nApplyChanges(changes);\n```\n\n### Nested Collections (SelectMany)\n\n```csharp\nvar outer = new ChangeableHashSet<IAdaptiveHashSet<int>>();\nvar flattened = outer.SelectMany(x => x);\n// flattened updates when outer or any inner set changes\n```\n\n### Constant Optimization\n\n```fsharp\n// Check if value is constant (never changes)\nif myAVal.IsConstant then\n    // Can cache result permanently\n```\n\n## Gotchas\n\n1. **Always use transactions** - mutations outside `transact`/`Adaptive.Transact` throw\n2. **Force outside transactions** - calling `GetValue`/`AVal.force` inside transact can cause reentrancy issues\n3. **Dispose readers** - `IStreamReader` and collection readers hold references; dispose when done\n4. **astream is experimental** - namespace is `Aardvark.Base.Incremental.Experimental`, API may change\n5. **Proc vs Async** - Proc is simpler continuation-based; use for UI/rendering pipelines, Async for I/O\n6. **Controller state** - `ControllerState` tracks pulled values between evaluations; initialize via `controller.Run`\n\n## See Also\n\n- [FSHARP_INTEROP.md](FSHARP_INTEROP.md) - F# modules and functional patterns\n- FSharp.Data.Adaptive documentation: https://fsprojects.github.io/FSharp.Data.Adaptive/\n"
  },
  {
    "path": "ai/PIXIMAGE.md",
    "content": "# Aardvark.Base Pix/Image Reference\n\nSource-verified orientation for `PixImage`, `PixVolume`, and related types.\n\n## Core Types\n\n- `PixImage` / `PixImage<T>`\n- `PixVolume` / `PixVolume<T>`\n- `PixCube`\n- `PixImageMipMap`\n- `PixFormat`\n- `PixFileFormat`\n- `PixProcessorCaps`\n\n## Loading and Info\n\nStatic load methods are on non-generic `PixImage`:\n\n```csharp\nPixImage img = PixImage.Load(\"a.png\");\nPixImage img2 = PixImage.Load(stream);\nPixImage raw = PixImage.LoadRaw(\"a.png\");\nPixImageInfo info = PixImage.GetInfoFromFile(\"a.png\");\n```\n\nTyped load is via constructor:\n\n```csharp\nvar typed = new PixImage<byte>(\"a.png\");\n```\n\nNo static `PixImage.Load<T>(...)` API exists.\n\n## Saving\n\n```csharp\nimg.Save(\"out.png\");\nimg.Save(\"out.jpg\", new PixJpegSaveParams(90));\nimg.Save(stream, PixFileFormat.Png);\nimg.SaveAsJpeg(\"out.jpg\", 90);\nimg.SaveAsPng(\"out.png\", 6);\n```\n\n## Processing and Conversion\n\nCommon `PixImage<T>` methods:\n\n- `Resized(...)`\n- `Scaled(...)`\n- `Rotated(...)`\n- `SubImage(...)` (view on shared storage)\n- `ToPixImage<TOut>()`\n- `ToFormat(Col.Format)`\n- `ToImageLayout()`\n- `GetChannel(long)` / `GetChannel(Col.Channel)`\n\n`SubImage(...)` returns a view; edits affect shared data.\n\n## Loaders and Processors\n\nLoader hooks:\n\n```csharp\nPixImage.SetLoader(loader, priority);\nPixImage.AddLoader(loader);\n```\n\nProcessor lookup:\n\n```csharp\nvar p = PixImage.GetProcessors(PixProcessorCaps.Scale);\n```\n\n`PixProcessorCaps` values:\n\n- `None`\n- `Scale`\n- `Rotate`\n- `Remap`\n- `All`\n\n## PixFormat and File Formats\n\n`PixFormat` is defined in `Aardvark.Base` (`Color.cs`) as `(Type, Col.Format)`.\n\nCommon predefined values:\n\n- `PixFormat.ByteGray`\n- `PixFormat.ByteRGB`\n- `PixFormat.ByteRGBA`\n- `PixFormat.FloatGray`\n- `PixFormat.FloatRGB`\n\n`PixFileFormat` enum is in `PixImage.cs` and contains formats such as `Png`, `Jpeg`, `Bmp`, `Tiff`, `Exr`, `Webp`, and others.\n\n## Mipmaps and Cubemaps\n\n`PixImageMipMap`:\n\n- `Load(string|Stream, IPixLoader?)`\n- `Create(baseImage, interpolation, maxCount, powerOfTwo)`\n- `LevelCount`\n\n`PixCube`:\n\n- six `PixImageMipMap` faces addressed by `CubeSide`\n\n## Source Anchors\n\n- `src/Aardvark.Base.Tensors.CSharp/PixImage/PixImage.cs`\n- `src/Aardvark.Base.Tensors.CSharp/PixImage/PixVolume.cs`\n- `src/Aardvark.Base.Tensors.CSharp/PixImage/PixCube.cs`\n- `src/Aardvark.Base.Tensors.CSharp/PixImage/PixImageMipMap.cs`\n- `src/Aardvark.Base.Tensors.CSharp/PixImage/PixProcessor.cs`\n- `src/Aardvark.Base/Math/Colors/Color.cs`\n"
  },
  {
    "path": "ai/PRIMITIVE_TYPES.md",
    "content": "﻿# Aardvark.Base Primitive Types Reference\n\nFast orientation for core math and geometry types in `Aardvark.Base`.\n\nUse this with:\n- `SEMANTICS_LINEAR_ALGEBRA.md` for matrix/vector layout and interop details\n- `SEMANTICS_GEOMETRY_CORE.md` for geometry conventions and transform semantics\n\n## Naming Convention\n\nPattern: `{TypeName}{Dimension}{Suffix}`\n\n| Suffix | Meaning |\n|--------|---------|\n| `i` | `int` |\n| `l` | `long` |\n| `f` | `float` |\n| `d` | `double` |\n| `b` | `byte` |\n\nExamples:\n- `V3d` = 3D vector (`double`)\n- `M44f` = 4x4 matrix (`float`)\n- `Box3d` = 3D axis-aligned box (`double`)\n\n## Important Reality\n\n- Core vector/matrix structs are mutable value types (`struct`), not uniformly `readonly struct`.\n- For matrix/vector math in 3D, prefer explicit methods (`TransformPos`, `TransformDir`) over ambiguous shorthand.\n\n## Vector Families\n\nCommon families:\n- `V2*`, `V3*`, `V4*`\n- integer and floating-point variants (`i`, `l`, `f`, `d`)\n\nTypical APIs:\n```csharp\nvar a = new V3d(1, 2, 3);\nvar b = new V3d(4, 5, 6);\n\nvar dot = V3d.Dot(a, b);\nvar cross = V3d.Cross(a, b);\nvar dist = V3d.Distance(a, b);\nvar unit = a.Normalized;\n```\n\n## Matrix Families\n\nCommon families:\n- `M22*`, `M23*`, `M33*`, `M34*`, `M44*`\n\n### M44d Construction (Verified)\n```csharp\nvar t = M44d.Translation(new V3d(1, 2, 3));\nvar s = M44d.Scale(new V3d(2, 2, 2));\nvar r = M44d.RotationZ(0.5);\n\nvar fromRows = M44d.FromRows(\n    new V4d(1, 0, 0, 0),\n    new V4d(0, 1, 0, 0),\n    new V4d(0, 0, 1, 0),\n    new V4d(0, 0, 0, 1)\n);\n\nvar rot = Rot3d.RotationZ(0.5);\nvar rotAsMatrix = (M44d)rot;\n```\n\n### M44d Operations (Verified)\n```csharp\nvar m = M44d.Translation(new V3d(1, 2, 3));\n\nvar p = m.TransformPos(new V3d(5, 6, 7));   // includes translation\nvar d = m.TransformDir(new V3d(0, 1, 0));   // ignores translation\n\nvar h = m * new V4d(5, 6, 7, 1);            // valid homogeneous multiply\n```\n\nNotes:\n- `M44d * V4d` and `V4d * M44d` are defined.\n- `M44d * V3d` is not defined.\n- `M44d.Transform(V3d)` is not a supported API; use `TransformPos`/`TransformDir`.\n\n## Transformation Types\n\n3D families:\n- `Rot3*`, `Shift3*`, `Scale3*`, `Euclidean3*`, `Similarity3*`, `Affine3*`, `Trafo3*`\n\nTypical `Trafo3d` usage:\n```csharp\nvar trafo = Trafo3d.Translation(new V3d(1, 0, 0)) * Trafo3d.Scale(2.0);\n\nvar fwd = trafo.Forward;    // M44d\nvar bwd = trafo.Backward;   // M44d inverse\n\nvar p = trafo.TransformPos(new V3d(1, 2, 3));\n```\n\n## Geometry Core Families\n\nCommon primitives:\n- `Box2*`, `Box3*`\n- `Ray2*`, `Ray3*`\n- `Plane2*`, `Plane3*`\n- `Sphere3*`, `Circle2*`, `Circle3*`\n- `Triangle2*`, `Triangle3*`\n- `Hull2*`, `Hull3*`\n\nTypical APIs:\n```csharp\nvar box = new Box3d(V3d.Zero, V3d.One);\nvar ray = new Ray3d(V3d.Zero, V3d.XAxis);\n\nvar contains = box.Contains(new V3d(0.5, 0.5, 0.5));\nvar hit = ray.Hits(box, out double t);\n```\n\n## Gotchas\n\n1. Matrix convention details (layout, multiplication side, interop) are critical for performance and correctness: use `SEMANTICS_LINEAR_ALGEBRA.md`.\n2. `TransformPos` vs `TransformDir` matters for translation handling.\n3. Subtle precision loss exists when converting from `d` variants to `f` variants.\n\n## Source Anchors\n\n- `src/Aardvark.Base/Math/Vectors/Vector_auto.cs` (`V3d`)\n- `src/Aardvark.Base/Math/Trafos/Matrix_auto.cs` (`M44d`, transforms, operators)\n- `src/Aardvark.Base/Math/Trafos/Rot3_auto.cs` (`Rot3d` to `M44d` cast)\n- `src/Aardvark.Base/Math/RangesBoxes/Box_auto.cs` (`Box3d`)\n- `src/Aardvark.Base/Geometry/Types/Ray/Ray3_auto.cs` (`Ray3d` hit methods)\n"
  },
  {
    "path": "ai/README.md",
    "content": "# Aardvark.Base AI Reference\n\nTask-first docs for coding agents.\n\nGoal: open one focused document, not the whole `ai/` folder.\n\n## Fast Path\n\n1. Find symbols in [SYMBOL_INDEX.md](SYMBOL_INDEX.md).\n2. Open one task doc from the table below.\n3. Verify critical names in source with `rg`.\n\n## Task Docs\n\n| Need | Read |\n|------|------|\n| Primitive math and geometry types | [PRIMITIVE_TYPES.md](PRIMITIVE_TYPES.md) |\n| Matrix/vector layout and interop semantics | [SEMANTICS_LINEAR_ALGEBRA.md](SEMANTICS_LINEAR_ALGEBRA.md) |\n| Geometry and transform semantics | [SEMANTICS_GEOMETRY_CORE.md](SEMANTICS_GEOMETRY_CORE.md) |\n| Images, volumes, loaders, processors | [PIXIMAGE.md](PIXIMAGE.md) |\n| Tensor containers, views, strides | [TENSORS.md](TENSORS.md) |\n| Graph/spatial/numeric algorithms | [ALGORITHMS.md](ALGORITHMS.md) |\n| Symbols, dicts, caches, concurrent set | [COLLECTIONS.md](COLLECTIONS.md) |\n| Logging, telemetry, random, geodesy | [UTILITIES.md](UTILITIES.md) |\n| Serialization/coder APIs | [SERIALIZATION.md](SERIALIZATION.md) |\n| F# wrappers and idioms | [FSHARP_INTEROP.md](FSHARP_INTEROP.md) |\n| Incremental/adaptive system | [INCREMENTAL.md](INCREMENTAL.md) |\n\n## Meta Docs\n\n| Need | Read |\n|------|------|\n| Symbol-to-doc lookup | [SYMBOL_INDEX.md](SYMBOL_INDEX.md) |\n| Drift and accuracy audit log | [DOC_ACCURACY_AUDIT.md](DOC_ACCURACY_AUDIT.md) |\n| AI-friendliness recipe for other repos | [RECIPE_AI_FRIENDLINESS.md](RECIPE_AI_FRIENDLINESS.md) |\n\n## Accuracy Contract\n\n- Docs are orientation, source is truth.\n- If a method/type matters, verify with `rg` before coding.\n- If docs and code differ, fix docs in the same change.\n- Prefer examples that reflect current scripts and project targets.\n\n---\n\nLast verified against repository state: 2026-02-26\n"
  },
  {
    "path": "ai/RECIPE_AI_FRIENDLINESS.md",
    "content": "# Recipe: Making a Repository AI-Friendly\n\nStep-by-step guide for Claude instances to add AI-optimized documentation to similar codebases.\n\n---\n\n## Overview\n\nThis recipe transforms a typical .NET/F# repository into one that AI coding assistants can navigate and modify efficiently. The pattern was extracted from commits that added ~3300 lines of targeted documentation to Aardvark.Base.\n\n**Time estimate**: 2-4 hours for a medium codebase (50-200 source files).\n\n---\n\n## Step 1: Add `.editorconfig`\n\nConsistent formatting reduces diff noise and prevents AI-generated code from introducing style conflicts.\n\n```ini\nroot = true\n\n[*]\ncharset = utf-8\ninsert_final_newline = true\ntrim_trailing_whitespace = true\nend_of_line = lf\n\n[*.{cs,fs,fsx,fsi}]\nindent_style = space\nindent_size = 4\n\n[*.{csproj,fsproj,props,targets,sln}]\nindent_style = space\nindent_size = 2\n\n[*.{json,yml,yaml,xml}]\nindent_style = space\nindent_size = 2\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[*.sh]\nend_of_line = lf\n\n[*.cmd]\nend_of_line = crlf\n```\n\n---\n\n## Step 2: Add `.gitattributes`\n\nCross-platform line endings prevent spurious diffs when AI generates code on different OSes.\n\n```\n* text=auto\n\n# Source code\n*.cs text eol=lf\n*.fs text eol=lf\n*.fsx text eol=lf\n*.fsi text eol=lf\n\n# Build files\n*.csproj text eol=lf\n*.fsproj text eol=lf\n*.sln text eol=lf\n*.props text eol=lf\n*.targets text eol=lf\n\n# Config\n*.json text eol=lf\n*.yml text eol=lf\n*.yaml text eol=lf\n\n# Docs\n*.md text eol=lf\n*.txt text eol=lf\n\n# Scripts\n*.sh text eol=lf\n*.cmd text eol=crlf\n*.bat text eol=crlf\n\n# Binary\n*.png binary\n*.jpg binary\n*.dll binary\n*.exe binary\n*.pdb binary\n*.nupkg binary\n*.zip binary\n```\n\n---\n\n## Step 3: Create `AGENTS.md` at Repo Root\n\nThis is the entry point for AI agents. Include:\n\n1. **Link to detailed docs** (if any)\n2. **Supported commands table** (build, test, restore)\n3. **Dependency management rules** (npm, pip, NuGet, Paket, etc.)\n4. **File ownership by change type**\n5. **Framework/SDK constraints**\n6. **Common failure modes with fixes**\n7. **Project structure overview**\n8. **Tips for AI agents**\n9. **Release notes placement rule** when the repo keeps unreleased notes above versioned sections\n\n### Template\n\n```markdown\n# AI Agent Guide\n\nThis repository has AI-targeted reference documentation in `ai/README.md`.\n\n## Supported Commands\n\n| Task | Command | Notes |\n|------|---------|-------|\n| Restore | `./build.sh restore` or `.\\build.cmd restore` | Restores tools + packages |\n| Build | `./build.sh` or `.\\build.cmd` | Builds entire solution |\n| Test | `./test.sh` or `.\\test.cmd` | Runs the real test projects; excludes benchmark projects |\n| Build one | `dotnet build src/Foo/Foo.csproj` | Single project |\n\n## Dependency Management\n\n| Task | Command |\n|------|---------|\n| Add package | `<your package manager command>` |\n| Update | `<your update command>` |\n\n**Rules:**\n- <package manager specific rules>\n\n## File Ownership by Change Type\n\n| Change Type | Files to Modify | Files to NOT Touch |\n|-------------|-----------------|-------------------|\n| Add feature | `src/**/*.cs` | `*_auto.cs` (generated) |\n| Add test | `tests/**/*Tests.cs` | Source files, other tests |\n| Fix bug | Relevant source + test | Unrelated modules |\n\n## Framework & SDK Rules\n\n- **.NET Version**: X.Y (see `global.json`)\n- **Target Frameworks**: netstandard2.0, net8.0\n- **LangVersion**: 12\n\n## Common Failure Modes & Fixes\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| Package restore fails | Outdated lock file | `<regenerate command>` |\n| SDK not found | Wrong .NET version | Install .NET X.Y |\n\n## Project Structure\n\n```\nsrc/\n├── Core/           # Main library\n├── Extensions/     # Optional modules\n└── Tests/          # Test projects\n```\n\n## Tips for AI Agents\n\n1. Read only what you need; each doc is self-contained\n2. Check the \"Gotchas\" section before writing code\n3. If the repo has `RELEASE_NOTES.md`, say where unreleased notes belong.\n\n### Release Notes Placement\n\nIf the repository keeps unreleased notes separately from numbered releases:\n\n- tell agents whether tooling reads the first `### <version>` section as the current version\n- if plain pending notes above the first version are allowed, say that explicitly\n- explicitly forbid adding a markdown heading such as `### Preliminary` above that first version section when tooling would treat it as structural\n- explicitly forbid adding new notes inside the previous released version block\n- if pending notes belong above the first version, say that directly instead of telling agents to write into the previous released block\n3. Run tests after changes\n4. Use provided build scripts\n```\n\n---\n\n## Step 4: Create `ai/README.md` Index\n\nThis is a compact index so the AI knows which doc to read for each task.\n\n### Template\n\n```markdown\n# <Project> AI Reference\n\nIndex for AI coding assistants. Read only the doc you need.\n\n## By Task\n\n| Task | Document | Size |\n|------|----------|------|\n| Core types, APIs | CORE.md | ~10 KB |\n| Data structures | DATA_STRUCTURES.md | ~8 KB |\n| Algorithms | ALGORITHMS.md | ~8 KB |\n| Serialization | SERIALIZATION.md | ~7 KB |\n| Configuration | CONFIG.md | ~5 KB |\n\n## By Type\n\n- `FooClass`, `BarStruct` → CORE.md\n- `MyCollection<T>` → DATA_STRUCTURES.md\n```\n\n**Key rules:**\n- Include approximate file sizes (AI can estimate reading cost)\n- Group by task AND by type name\n- Keep it under 50 lines\n\n---\n\n## Step 5: Create Topic-Specific Reference Docs in `ai/`\n\nEach doc covers one topic. Target 6-12 KB per doc (500-1000 lines).\n\n### Document Structure\n\n```markdown\n# <Project> <Topic> Reference\n\nAI-targeted reference for <topic description>.\n\n---\n\n## <Major Section 1>\n\n### <Subsection>\n\n| Type | Properties | Notes |\n|------|------------|-------|\n| Foo | Bar, Baz | Description |\n\n### Usage\n```<lang>\n// Example code\n```\n\n---\n\n## <Major Section 2>\n\n...\n\n---\n\n## Usage Patterns\n\n### Pattern Name\n```<lang>\n// Complete working example\n```\n\n---\n\n## Gotchas\n\n1. **Gotcha Title**: Explanation of the trap and how to avoid it\n2. **Another Gotcha**: ...\n\n---\n\n## See Also\n\n- [OTHER_DOC.md](OTHER_DOC.md) - Why this is related\n```\n\n### Formatting Rules\n\n1. **Tables over prose** - Types, properties, commands in tables\n2. **Code examples** - Complete, copy-paste-ready\n3. **Gotchas section** - Common mistakes (3-5 items)\n4. **See Also** - Cross-references to related docs\n5. **No fluff** - Skip introductions, motivation, history\n\n### Step 5b: F# Considerations\n\nIf your repo has F# code alongside C#:\n\n1. **Document `open` statements** - F# uses `open Namespace` instead of `using`. List common opens and what they provide\n\n2. **Cover F# modules** - F# modules (like `Vec`, `Mat`) wrap C# static methods. Document these separately from the C# API\n\n3. **Note function conventions**:\n   - F# prefers curried functions: `transformPos matrix point`\n   - C# uses tupled: `TransformPos(matrix, point)`\n   - Document both forms if available\n\n4. **Dual-language examples** - For key operations, show both:\n   ```csharp\n   // C#\n   var result = V3d.Cross(a, b);\n   ```\n   ```fsharp\n   // F#\n   let result = Vec.cross a b\n   ```\n\n5. **Document lenses** - If using Adaptify or similar, document the lens system and composition operators\n\n---\n\n## Step 6: Add `.claude/CLAUDE.md` Pointer\n\nMinimal file that tells Claude Code where to find docs.\n\n```markdown\n# AI Documentation\n\nRead `ai/README.md` for indexed reference docs.\n```\n\n---\n\n## Step 7: Document Complex Build Systems\n\nIf your repo has code generation, custom build steps, or unusual tooling, create a README in that component's directory.\n\n### Template for Code Generators\n\n```markdown\n# <Generator Name>\n\n## Purpose\n\n<One paragraph explaining what it generates and why>\n\n## How to Run\n\n```bash\n./generate.sh   # Unix\n.\\generate.cmd  # Windows\n```\n\n## When to Run\n\nRun after modifying any `*_template.*` file.\n\n## Input Files\n\n`*_template.cs` files containing:\n- <syntax description>\n\n## Output Files\n\n`*_auto.cs` files that are:\n- AUTO GENERATED - DO NOT EDIT\n- <what they contain>\n\n## Generated Files Summary\n\n| Template | Output | Purpose |\n|----------|--------|---------|\n| Foo_template.cs | Foo_auto.cs | Generates type variants |\n```\n\n---\n\n## Step 8: Improve CI Configuration\n\nAI agents benefit from CI that:\n- Uses caching (faster feedback loop)\n- Sets `fail-fast: false` (see all failures, not just first)\n- Has correct path-ignore globs\n\n### GitHub Actions Example\n\n```yaml\nname: Build\n\non:\n  push:\n    paths-ignore:\n      - 'README.md'\n      - 'docs/**'\n  pull_request:\n    paths-ignore:\n      - 'README.md'\n      - 'docs/**'\n\njobs:\n  build:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup .NET\n        uses: actions/setup-dotnet@v4\n        with:\n          global-json-file: global.json\n\n      - name: Cache packages\n        uses: actions/cache@v4\n        with:\n          path: |\n            ~/.nuget/packages\n          key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}\n\n      - name: Build\n        run: <build command>\n```\n\n---\n\n## Checklist\n\nBefore considering the repository AI-friendly, verify:\n\n- [ ] `.editorconfig` exists with language-specific rules\n- [ ] `.gitattributes` handles line endings and binary files\n- [ ] `AGENTS.md` at root with commands, rules, structure\n- [ ] `ai/README.md` index with task-based lookup\n- [ ] `ai/*.md` docs for each major topic (3-10 docs typical)\n- [ ] `.claude/CLAUDE.md` points to ai/README.md\n- [ ] Build system READMEs for code generators or unusual tooling\n- [ ] CI uses caching and fail-fast: false\n- [ ] All `ai/*.md` docs have Gotchas and See Also sections\n- [ ] All `ai/*.md` docs are 6-12 KB (not too long to read, not too short to be useful)\n\n---\n\n## Anti-Patterns to Avoid\n\n1. **Walls of prose** - AI skims; tables and code are better\n2. **Incomplete examples** - Every code block should work if pasted\n3. **Missing gotchas** - The mistakes AI makes repeatedly belong here\n4. **Giant monolithic docs** - Split by topic; 6-12 KB per file\n5. **Stale docs** - Update when behavior changes; delete obsolete content\n6. **Documenting the obvious** - Skip \"what is a vector\"; focus on API specifics\n7. **Duplicating source comments** - Reference docs should add value beyond inline docs\n\n---\n\n## Maintenance\n\nWhen making changes to the codebase:\n\n1. **New types/APIs**: Update relevant `ai/*.md` doc\n2. **New failure mode**: Add to AGENTS.md failure table\n3. **New build step**: Add to AGENTS.md commands table\n4. **Breaking change**: Update Gotchas section\n5. **Removing feature**: Delete from docs (don't leave stale references)\n\n---\n\n*Last updated: December 2025*\n"
  },
  {
    "path": "ai/SEMANTICS_GEOMETRY_CORE.md",
    "content": "# Aardvark.Base Geometry Semantics\n\nUse this for transform correctness questions in geometry code.\n\n## Transform Semantics\n\nFor `M44d` and `Trafo3d`:\n\n- `TransformPos` treats input as point (`w=1`)\n- `TransformDir` treats input as direction (`w=0`)\n- `TransformPosProj` performs perspective division\n\nUse the right method for normals/vectors/points. Most correctness bugs come from mixing them.\n\n## Trafo3d Forward/Backward\n\n`Trafo3d` stores both matrices:\n\n- `Forward`: model -> transformed space\n- `Backward`: inverse transform\n\n`InvTransformPos` and related methods use `Backward`.\n\n## Trafo3d Multiplication Order\n\n`Trafo3d` composition is backward relative to raw matrix multiplication for natural postfix usage.\n\n```csharp\nvar combined = t0 * t1; // not equivalent to new Trafo3d(t0.Forward * t1.Forward, ...)\n```\n\nFor ambiguity-sensitive code, inspect resulting `Forward` explicitly.\n\n## Matrix and Geometry Interop\n\nWhen crossing APIs that use transposed conventions, use:\n\n- `m.Transposed`\n- `m.TransposedTransformPos(...)`\n- `m.TransposedTransformDir(...)`\n\nDo not assume identical handedness or memory/algebra conventions across systems.\n\n## Geodesy Units (Geo)\n\n`Geo.XyzFromLonLatHeight` and `Geo.LonLatHeightFromXyz` use:\n\n- longitude/latitude in degrees\n- height in meters\n- ellipsoid from `GeoEllipsoid` (`Wgs84`, `Grs80`, `Bessel1841`, ...)\n\n## Source Anchors\n\n- `src/Aardvark.Base/Math/Trafos/Matrix_auto.cs` (`TransformPos`, `TransformDir`, transposed variants)\n- `src/Aardvark.Base/Math/Trafos/Trafo_auto.cs` (`Trafo3d`, `Forward`, `Backward`, operator `*`)\n- `src/Aardvark.Base/Geodesy/GeoConversion.cs` (`XyzFromLonLatHeight`, `LonLatHeightFromXyz`)\n- `src/Aardvark.Base/Geodesy/GeoConsts.cs` (`GeoEllipsoid`)\n"
  },
  {
    "path": "ai/SEMANTICS_LINEAR_ALGEBRA.md",
    "content": "# Aardvark.Base Linear Algebra Semantics\n\nUse this when matrix/vector layout and interop correctness matter.\n\n## M44d Convention (Verified)\n\n`M44d` fields are named by row/column: `Mrc`.\n\n- `M00..M03` = row 0\n- `M10..M13` = row 1\n- `M20..M23` = row 2\n- `M30..M33` = row 3\n\n`double[]` export order is row-major:\n\n```csharp\nvar a = (double[])m;\n// a = [M00, M01, M02, M03, M10, ... , M33]\n```\n\n## Multiplication Semantics\n\n`M44d` supports both:\n\n- `m * v` where `v` is a column vector\n- `v * m` where `v` is a row vector\n\nColumn-vector form (`m * v`) is the canonical transform style for `TransformPos`/`TransformDir`.\n\n```csharp\nV4d c = m * v;\nV4d r = v * m;\n```\n\n## Point vs Direction\n\nFor `M44d`:\n\n- `TransformDir(v)` ignores translation (`w = 0`)\n- `TransformPos(p)` applies translation (`w = 1`)\n- translation lives in `M03/M13/M23`\n\n## Direct Answer: Row-Major or Column-Major?\n\nBoth concerns exist, but they are different:\n\n- In-memory field/array layout is row-major.\n- Algebra supports column-vector and row-vector multiplication operators.\n\nIf your external system is column-major memory, conversion is required at the boundary.\n\n## Efficient Layout Conversion\n\n### Row-major array -> M44d\n\n```csharp\nvar m = new M44d(rowMajor16);\n```\n\n### Column-major array -> M44d\n\n```csharp\nvar m = M44d.FromCols(\n    new V4d(cm[0], cm[1], cm[2], cm[3]),\n    new V4d(cm[4], cm[5], cm[6], cm[7]),\n    new V4d(cm[8], cm[9], cm[10], cm[11]),\n    new V4d(cm[12], cm[13], cm[14], cm[15])\n);\n```\n\n### M44d -> column-major array\n\n```csharp\nvar cm = new[]\n{\n    m.M00, m.M10, m.M20, m.M30,\n    m.M01, m.M11, m.M21, m.M31,\n    m.M02, m.M12, m.M22, m.M32,\n    m.M03, m.M13, m.M23, m.M33\n};\n```\n\n### Opposite algebra convention\n\nIf the other side interprets transforms with opposite multiplication side, transpose at the boundary:\n\n```csharp\nvar boundaryMatrix = m.Transposed;\n```\n\nFor one-off transforms, use `TransposedTransformDir` / `TransposedTransformPos` to avoid manual transpose logic.\n\n## Trafo3d Composition Note\n\n`Trafo3d` multiplication order is intentionally reversed relative to raw `M44d` multiplication:\n\n```csharp\nvar t = t0 * t1;\n// forward = t1.Forward * t0.Forward\n```\n\nThis is documented in `Trafo_auto.cs` and affects composition assumptions.\n\n## Source Anchors\n\n- `src/Aardvark.Base/Math/Trafos/Matrix_auto.cs` (`M44d`, `FromRows`, `FromCols`, `operator*`, `TransformPos`, `TransposedTransformPos`)\n- `src/Aardvark.Base/Math/Trafos/Trafo_auto.cs` (`Trafo3d` operator `*` composition semantics)\n"
  },
  {
    "path": "ai/SERIALIZATION.md",
    "content": "# Aardvark.Base Serialization Reference\n\nAI-targeted reference for the ICoder serialization system - bidirectional read/write abstraction.\n\n---\n\n## ICoder Pattern\n\nThe ICoder interface provides a unified API for both reading and writing. The same code handles both directions.\n\n```csharp\npublic partial interface ICoder\n{\n    bool IsReading { get; }\n    bool IsWriting { get; }\n    int CoderVersion { get; }\n    int MemoryVersion { get; }\n    int StreamVersion { get; }\n\n    void Code(ref object obj);\n    void CodeT<T>(ref T obj);\n    // ... type-specific methods\n}\n```\n\n### Key Insight\nSame method signature for read and write:\n- **Writing**: reads value from `ref` parameter, writes to stream\n- **Reading**: reads from stream, assigns to `ref` parameter\n\n```csharp\n// This code works for BOTH reading and writing\npublic void Serialize(ICoder coder)\n{\n    coder.CodeInt32(ref _x);\n    coder.CodeString(ref _name);\n    coder.CodeV3d(ref _position);\n}\n```\n\n---\n\n## Implementations\n\n### BinaryWritingCoder\n\nWrites objects to binary stream.\n\n```csharp\nusing (var coder = new BinaryWritingCoder(stream))\n{\n    object data = myObject;\n    coder.Code(ref data);\n}\n```\n\n### BinaryReadingCoder\n\nReads objects from binary stream.\n\n```csharp\nusing (var coder = new BinaryReadingCoder(stream))\n{\n    object data = null;\n    coder.Code(ref data);\n    var myObject = (MyType)data;\n}\n```\n\n---\n\n## Type-Specific Methods\n\n### Primitive Types\n```csharp\nvoid CodeBool(ref bool value);\nvoid CodeByte(ref byte value);\nvoid CodeSByte(ref sbyte value);\nvoid CodeInt16(ref short value);\nvoid CodeUInt16(ref ushort value);\nvoid CodeInt32(ref int value);\nvoid CodeUInt32(ref uint value);\nvoid CodeInt64(ref long value);\nvoid CodeUInt64(ref ulong value);\nvoid CodeFloat(ref float value);\nvoid CodeDouble(ref double value);\nvoid CodeChar(ref char value);\nvoid CodeString(ref string value);\nvoid CodeGuid(ref Guid value);\nvoid CodeType(ref Type value);\nvoid CodeSymbol(ref Symbol value);\n```\n\n### Aardvark Types\n```csharp\n// Vectors\nvoid CodeV2i(ref V2i value);\nvoid CodeV2f(ref V2f value);\nvoid CodeV2d(ref V2d value);\nvoid CodeV3i(ref V3i value);\nvoid CodeV3f(ref V3f value);\nvoid CodeV3d(ref V3d value);\nvoid CodeV4i(ref V4i value);\nvoid CodeV4f(ref V4f value);\nvoid CodeV4d(ref V4d value);\n\n// Matrices\nvoid CodeM22f(ref M22f value);\nvoid CodeM33f(ref M33f value);\nvoid CodeM44f(ref M44f value);\nvoid CodeM22d(ref M22d value);\nvoid CodeM33d(ref M33d value);\nvoid CodeM44d(ref M44d value);\n\n// Transformations\nvoid CodeTrafo2f(ref Trafo2f value);\nvoid CodeTrafo3f(ref Trafo3f value);\nvoid CodeTrafo2d(ref Trafo2d value);\nvoid CodeTrafo3d(ref Trafo3d value);\n\n// Colors\nvoid CodeC3b(ref C3b value);\nvoid CodeC4b(ref C4b value);\nvoid CodeC3f(ref C3f value);\nvoid CodeC4f(ref C4f value);\n\n// Geometric\nvoid CodeBox2i(ref Box2i value);\nvoid CodeBox3i(ref Box3i value);\nvoid CodeBox2f(ref Box2f value);\nvoid CodeBox3f(ref Box3f value);\nvoid CodeBox2d(ref Box2d value);\nvoid CodeBox3d(ref Box3d value);\n```\n\n### Collections\n```csharp\nvoid CodeT<T>(ref T obj);\nvoid CodeTArray<T>(ref T[] array);\nvoid CodeList_of_T_<T>(ref List<T> list);\nvoid CodeHashSet_of_T_<T>(ref HashSet<T> set);\n\nvoid Code(Type t, ref Array array);\nvoid Code(Type t, ref IList list);\nvoid Code(Type t, ref IDictionary dict);\n```\n\n### Tensors\n```csharp\nvoid Code(Type t, ref IArrayVector vector);\nvoid Code(Type t, ref IArrayMatrix matrix);\nvoid Code(Type t, ref IArrayVolume volume);\nvoid Code(Type t, ref IArrayTensor4 tensor4);\nvoid Code(Type t, ref IArrayTensorN tensor);\n```\n\n### Struct Arrays\n```csharp\nvoid CodeStructArray<T>(ref T[] a) where T : struct;\nvoid CodeStructList<T>(ref List<T> l) where T : struct;\n```\n\n---\n\n## Extended Interfaces\n\n### IReadingCoder\n```csharp\npublic interface IReadingCoder : ICoder\n{\n    // Code count with creation function\n    int CodeCount<T>(ref T value, Func<int, T> creator) where T : class;\n}\n```\n\n### IWritingCoder\n```csharp\npublic interface IWritingCoder : ICoder\n{\n    // Code count with counting function\n    int CodeCount<T>(ref T value, Func<T, int> counter) where T : class;\n}\n```\n\n---\n\n## Version Handling\n\nICoder supports versioned serialization:\n\n```csharp\ncoder.MemoryVersion  // current in-memory format version\ncoder.StreamVersion  // version in the stream being read\ncoder.CoderVersion   // coder implementation version\n```\n\nUse for backward compatibility:\n```csharp\npublic void Serialize(ICoder coder)\n{\n    coder.CodeInt32(ref _x);\n\n    if (coder.StreamVersion >= 2)\n    {\n        coder.CodeString(ref _newField);\n    }\n    else if (coder.IsReading)\n    {\n        _newField = \"default\";  // provide default for old data\n    }\n}\n```\n\n---\n\n## TypeInfo Registration\n\nRegister custom types for polymorphic serialization:\n\n```csharp\ncoder.Add(new TypeInfo[] {\n    new TypeInfo(typeof(MyType), \"MyType\", /* version */ 1),\n    // ...\n});\n\ncoder.Del(typeInfoArray);  // remove registration\n```\n\n---\n\n## Usage Patterns\n\n### Basic Serialization\n```csharp\n// Write\nusing (var stream = File.Create(\"data.bin\"))\nusing (var coder = new BinaryWritingCoder(stream))\n{\n    var position = new V3d(1, 2, 3);\n    var name = \"test\";\n    coder.CodeV3d(ref position);\n    coder.CodeString(ref name);\n}\n\n// Read\nusing (var stream = File.OpenRead(\"data.bin\"))\nusing (var coder = new BinaryReadingCoder(stream))\n{\n    var position = default(V3d);\n    var name = default(string);\n    coder.CodeV3d(ref position);\n    coder.CodeString(ref name);\n}\n```\n\n### Unified Read/Write Method\n```csharp\npublic class MyData\n{\n    private V3d _position;\n    private string _name;\n    private List<int> _values;\n\n    public void Code(ICoder coder)\n    {\n        coder.CodeV3d(ref _position);\n        coder.CodeString(ref _name);\n        coder.CodeList_of_T_(ref _values);\n    }\n}\n\n// Write\nmyData.Code(writingCoder);\n\n// Read\nmyData.Code(readingCoder);\n```\n\n### Conditional Coding\n```csharp\npublic void Code(ICoder coder)\n{\n    coder.CodeInt32(ref _count);\n\n    if (coder.IsWriting && _data != null)\n    {\n        coder.CodeTArray(ref _data);\n    }\n    else if (coder.IsReading)\n    {\n        _data = new float[_count];\n        coder.CodeTArray(ref _data);\n    }\n}\n```\n\n---\n\n## Special Methods\n\n### Symbol Variants\n```csharp\n// Symbol known to be from a GUID\nvoid CodeGuidSymbol(ref Symbol v);\n\n// Symbol known to be positive (has string representation)\nvoid CodePositiveSymbol(ref Symbol v);\n```\n\n### Set Types\n```csharp\nvoid CodeIntSet(ref IntSet v);\nvoid CodeSymbolSet(ref SymbolSet v);\n```\n\n### Enum Coding\n```csharp\nvoid CodeEnum(Type t, ref object value);\n```\n\n---\n\n## Gotchas\n\n1. **Unidirectional Reference Pattern**: The `ref` parameter pattern is elegant but *confusing* for debugging. Read-mode passes `null` into `ref`, write-mode reads from the ref. Always verify `IsReading`/`IsWriting` in conditional logic\n2. **Version Mismatch Silent Failures**: If code reads a newer format than `StreamVersion`, old fields stay at default values without warning. Use version guards explicitly; don't assume forward compatibility\n3. **Polymorphic Type Registration**: Polymorphic serialization requires exact `TypeInfo` registration. Missing a subclass? It silently serializes as the base type, causing silent data loss on read\n\n---\n\n## See Also\n\n- [PRIMITIVE_TYPES.md](PRIMITIVE_TYPES.md) - All primitives (V3d, M44d, Trafo3d) have `CodeXxx` methods\n- [TENSORS.md](TENSORS.md) - N-dimensional tensors serialize via `Code(Type t, ref IArrayVolume volume)`\n- [PIXIMAGE.md](PIXIMAGE.md) - `PixImage` serialization for binary save/load workflows\n- [COLLECTIONS.md](COLLECTIONS.md) - `Symbol`, `SymbolDict`, `LruCache` serialization patterns\n"
  },
  {
    "path": "ai/SYMBOL_INDEX.md",
    "content": "# Aardvark.Base Symbol Index\n\nQuick symbol-to-doc map for incremental discovery.\n\n## Core Math / Geometry\n\n| Symbol | Primary Doc |\n|--------|-------------|\n| `V2d`, `V3d`, `V4d` | [PRIMITIVE_TYPES.md](PRIMITIVE_TYPES.md) |\n| `M22d..M44d` | [PRIMITIVE_TYPES.md](PRIMITIVE_TYPES.md) |\n| `Rot3d`, `Trafo3d` | [PRIMITIVE_TYPES.md](PRIMITIVE_TYPES.md) |\n| `M44d` layout/interoperability | [SEMANTICS_LINEAR_ALGEBRA.md](SEMANTICS_LINEAR_ALGEBRA.md) |\n| Transform semantics (`TransformPos`, `TransformDir`) | [SEMANTICS_GEOMETRY_CORE.md](SEMANTICS_GEOMETRY_CORE.md) |\n| `Box3d`, `Ray3d`, `Plane3d` | [PRIMITIVE_TYPES.md](PRIMITIVE_TYPES.md) |\n\n## Images / Tensors\n\n| Symbol | Primary Doc |\n|--------|-------------|\n| `PixImage`, `PixImage<T>` | [PIXIMAGE.md](PIXIMAGE.md) |\n| `PixVolume`, `PixVolume<T>` | [PIXIMAGE.md](PIXIMAGE.md) |\n| `PixCube`, `PixImageMipMap` | [PIXIMAGE.md](PIXIMAGE.md) |\n| `PixFormat`, `PixFileFormat`, `PixProcessorCaps` | [PIXIMAGE.md](PIXIMAGE.md) |\n| `Vector<T>`, `Matrix<T>`, `Volume<T>`, `Tensor4<T>` | [TENSORS.md](TENSORS.md) |\n| `MatrixInfo`, `VolumeInfo`, `Tensor4Info` | [TENSORS.md](TENSORS.md) |\n\n## Algorithms / Numerics\n\n| Symbol | Primary Doc |\n|--------|-------------|\n| `ShortestPath<T>` | [ALGORITHMS.md](ALGORITHMS.md) |\n| `BbTree` | [ALGORITHMS.md](ALGORITHMS.md) |\n| `AliasTableF`, `AliasTableD` | [ALGORITHMS.md](ALGORITHMS.md) |\n| `DistributionFunction` | [ALGORITHMS.md](ALGORITHMS.md) |\n| `Polynomial` | [ALGORITHMS.md](ALGORITHMS.md) |\n| `LuFactorize`, `LuSolve`, `QrFactorize` | [ALGORITHMS.md](ALGORITHMS.md) |\n\n## Collections / Infrastructure\n\n| Symbol | Primary Doc |\n|--------|-------------|\n| `Symbol`, `TypedSymbol<T>` | [COLLECTIONS.md](COLLECTIONS.md) |\n| `Dict<TKey,TValue>`, `SymbolDict<T>`, `SymbolSet` | [COLLECTIONS.md](COLLECTIONS.md) |\n| `LruCache<TKey,TValue>` | [COLLECTIONS.md](COLLECTIONS.md) |\n| `ConcurrentHashSet<T>` | [COLLECTIONS.md](COLLECTIONS.md) |\n| `Report` | [UTILITIES.md](UTILITIES.md) |\n| `Telemetry` | [UTILITIES.md](UTILITIES.md) |\n| `RandomSystem`, `RandomSample`, `HaltonRandomSeries` | [UTILITIES.md](UTILITIES.md) |\n| `Geo`, `GeoEllipsoid` | [UTILITIES.md](UTILITIES.md) |\n\n## F# / Incremental\n\n| Symbol | Primary Doc |\n|--------|-------------|\n| `Vec`, `Mat`, `Trafo`, `Lens` | [FSHARP_INTEROP.md](FSHARP_INTEROP.md) |\n| `aval`, `cval`, `aset`, `amap`, `alist` | [INCREMENTAL.md](INCREMENTAL.md) |\n\n## Verification Tip\n\nAfter landing on a doc, validate exact API names in source:\n\n```bash\nrg \"SymbolName\" src\n```\n"
  },
  {
    "path": "ai/TENSORS.md",
    "content": "# Aardvark.Base Tensor Types Reference\n\nSource-verified reference for stride-based tensor containers.\n\n## Core Model\n\nIndexing is stride-based:\n\n```\nindex = Origin + x * DX + y * DY + z * DZ + ...\n```\n\nMetadata structs:\n\n- `VectorInfo`\n- `MatrixInfo`\n- `VolumeInfo`\n- `Tensor4Info`\n\nData containers:\n\n- `Vector<Td>`\n- `Matrix<Td>`\n- `Volume<Td>`\n- `Tensor4<Td>`\n\nThese are `struct` types in generated `Tensor_auto.cs`.\n\n## Default Dense Layouts\n\n`MatrixInfo(size)` defaults to:\n\n- `DX = 1`\n- `DY = SX`\n\nImage layouts (`ImageTensors.cs`):\n\n- Matrix: `DX = 1`, `DY = SX`\n- Volume: `DZ = 1`, `DX = SZ`, `DY = SX * DX`\n- Tensor4: `DW = 1`, `DX = SW`, `DY = SX * DX`, `DZ = SY * DY`\n\n## Views vs Copies\n\nSubview methods return views on shared data:\n\n- `SubMatrix(...)`, `SubMatrixWindow(...)`\n- `SubVolume(...)`, `SubVolumeWindow(...)`\n- `SubTensor4(...)`, `SubTensor4Window(...)`\n\n`Transposed` is a stride/view transform, not deep copy.\n\nUse `Copy()` or `CopyWindow()` when you need independent storage.\n\n## Matrix Convenience Methods\n\nOn `Matrix<T>`:\n\n- `Row(y)` and `Col(x)` (return `Vector<T>`)\n- `Transposed`\n- `SetByCoord(...)`\n- `Foreach...` variants for iteration\n\n## Image Layout Helpers\n\nIn `Tensors/ImageTensors.cs`:\n\n- `HasImageLayout(...)`\n- `CreateImageVolume(...)`\n- `CreateImageTensor4(...)`\n- `ToImage(...)` / `ToImageWindow(...)`\n- `CopyToImage(...)` / `CopyToImageWindow(...)`\n\nThese are important for high-performance pix/tensor interoperability.\n\n## Source Anchors\n\n- `src/Aardvark.Base.Tensors.CSharp/Tensor_auto.cs`\n- `src/Aardvark.Base.Tensors.CSharp/Tensors/ImageTensors.cs`\n"
  },
  {
    "path": "ai/UTILITIES.md",
    "content": "# Aardvark.Base Utilities Reference\n\nSource-verified orientation for reporting, telemetry, random, traversal, and geodesy APIs.\n\n## Report\n\n`Report` is global process state.\n\nCommon methods:\n\n```csharp\nReport.Line(\"msg\");\nReport.Warn(\"msg\");\nReport.Debug(\"msg\");\nReport.Trace(\"msg\");\nReport.Error(\"msg\");\nReport.Fatal(\"msg\");\n\nReport.BeginTimed(\"load\");\n// ...\nReport.End();\n\nReport.Progress(0.5);\nReport.ProgressDelta(0.1);\n```\n\nKey settings:\n\n```csharp\nReport.Verbosity = 2;\nReport.MultiThreaded = true;\nReport.ThrowOnError = false;\n```\n\n## Telemetry\n\nCore probe types:\n\n- `Telemetry.Counter`\n- `Telemetry.StopWatchTime`\n- `Telemetry.WallClockTime`\n- `Telemetry.CpuTime`\n\nRegistration:\n\n```csharp\nvar c = new Telemetry.Counter();\nTelemetry.Register(\"Frames\", c);\nTelemetry.Register(\"Frames/s\", c.RatePerSecond());\n```\n\nReset API:\n\n```csharp\nTelemetry.ResetTelemetrySystem();\n```\n\n## Random\n\n`RandomSystem` implements `IRandomUniform`.\n\n```csharp\nvar rnd = new RandomSystem(1);\nint raw = rnd.UniformInt();\nint bounded = rnd.UniformInt(100);   // extension method on IRandomUniform\ndouble u = rnd.UniformDouble();\n```\n\nGeometric sampling:\n\n```csharp\nvar dir = RandomSample.Spherical(rnd, 0);\nvar hemi = RandomSample.Lambertian(V3d.ZAxis, rnd, 0);\nvar disk = RandomSample.Disk(rnd, 0);\n```\n\nLow-discrepancy:\n\n```csharp\nvar halton = new HaltonRandomSeries(2, rnd);\ndouble q = Quasi.QuasiHaltonWithIndex(2, 0.123);\n```\n\n## INode Traversal\n\n`INode` extensions:\n\n- `DepthFirst()`\n- `BreadthFirst()`\n- `NodesAtDepth(depth)`\n- `DescendentsAndSelf()` and `Descendents()` (spelling in code is `Descendents`)\n\n## Geodesy\n\nMain conversions:\n\n```csharp\nvar xyz = Geo.XyzFromLonLatHeight(new V3d(lonDeg, latDeg, hMeters), GeoEllipsoid.Wgs84);\nvar llh = Geo.LonLatHeightFromXyz(xyz, GeoEllipsoid.Wgs84);\n```\n\n`GeoEllipsoid` presets include `Wgs84`, `Grs80`, `Bessel1841`.\n\n## Constants\n\n`Constant<T>` exposes machine-epsilon/tiny/parseable min/max style values.\n\nMathematical constants are on non-generic classes:\n\n- `Constant.Pi`, `Constant.E`\n- `ConstantF.Pi`, `ConstantF.E`\n\n## Source Anchors\n\n- `src/Aardvark.Base/Reporting/Report.cs`\n- `src/Aardvark.Base.Telemetry/Probes.cs`\n- `src/Aardvark.Base.Telemetry/Registry.cs`\n- `src/Aardvark.Base.Telemetry/IProbe.cs`\n- `src/Aardvark.Base.Telemetry/TelemetryExtensions.cs`\n- `src/Aardvark.Base/Random/RandomSystem.cs`\n- `src/Aardvark.Base/Random/IRandomUniform.cs`\n- `src/Aardvark.Base/Random/RandomSample.cs`\n- `src/Aardvark.Base/Random/HaltonRandomSeries.cs`\n- `src/Aardvark.Base/Random/Quasi.cs`\n- `src/Aardvark.Base/AlgoDat/INode.cs`\n- `src/Aardvark.Base/Geodesy/GeoConversion.cs`\n- `src/Aardvark.Base/Geodesy/GeoConsts.cs`\n- `src/Aardvark.Base/Math/Base/Constant.cs`\n"
  },
  {
    "path": "build.cmd",
    "content": "@echo off\ndotnet tool restore\nIF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\nREM `dotnet paket restore` alone does not recreate Paket.Restore.targets if it is missing.\nIF NOT EXIST \".paket\\Paket.Restore.targets\" (\n    dotnet paket install\n    IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\n) ELSE (\n    dotnet paket restore\n    IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\n)\n\nIF \"%1\"==\"restore\" exit /B\n\ndotnet build src\\Aardvark.sln\nIF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\n"
  },
  {
    "path": "build.sh",
    "content": "#!/bin/bash\n\nset -eu\n\nmode=\"${1-}\"\n\ndotnet tool restore\n# `dotnet paket restore` alone does not recreate Paket.Restore.targets if it is missing.\nif [ ! -f \".paket/Paket.Restore.targets\" ]; then\n    dotnet paket install\nelse\n    dotnet paket restore\nfi\n\nif [ \"$mode\" = \"restore\" ]; then\n    exit 0\nfi\n\ndotnet build src/Aardvark.sln\n"
  },
  {
    "path": "check-docs.cmd",
    "content": "@echo off\ndotnet run --project tools\\DocsChecker\\DocsChecker.csproj -c Release\n"
  },
  {
    "path": "check-docs.sh",
    "content": "#!/bin/bash\nset -euo pipefail\n\ndotnet run --project tools/DocsChecker/DocsChecker.csproj -c Release\n"
  },
  {
    "path": "generate.cmd",
    "content": "@echo off\ndotnet build src\\CodeGenerator\\CodeGenerator.csproj\ndotnet bin\\Debug\\net8.0\\CodeGenerator.dll %*\n"
  },
  {
    "path": "generate.sh",
    "content": "#! /bin/sh\ndotnet build src/CodeGenerator/CodeGenerator.csproj\ndotnet bin/Debug/net8.0/CodeGenerator.dll \"$@\"\n"
  },
  {
    "path": "global.json",
    "content": "{\n    \"sdk\": {\n      \"version\": \"8.0.0\",\n      \"rollForward\": \"latestFeature\",\n      \"allowPrerelease\": false\n    }\n}"
  },
  {
    "path": "paket.dependencies",
    "content": "framework: netstandard2.0, net8.0\r\nstorage: none\r\nsource https://api.nuget.org/v3/index.json\r\n\r\nnuget Aardvark.Build               ~> 2.0.7\r\n\r\nnuget FSharp.Core                  >= 8.0.300 lowest_matching: true\r\nnuget System.Collections.Immutable >= 8.0.0 lowest_matching: true\r\nnuget System.Reflection.Metadata   >= 8.0.0 lowest_matching: true\r\nnuget System.Text.Json             >= 8.0.5 lowest_matching: true\r\n\r\nnuget System.Dynamic.Runtime       ~> 4.3.0\r\n\r\nnuget Aardvark.Base.TypeProviders  ~> 4.5.15\r\n\r\nnuget FSharp.Data.Adaptive         ~> 1.2.0\r\nnuget CSharp.Data.Adaptive         ~> 1.2.0\r\nnuget Unofficial.LibTessDotNet     ~> 2.0.2\r\n\r\nnuget FsPickler                    ~> 5.3.2\r\nnuget FsPickler.Json               ~> 5.3.2\r\n\r\nnuget Unofficial.Typography        ~> 0.1.0\r\nnuget FuzzySharp                   ~> 2.0.2\r\n\r\nnuget SingleFileExtractor.Core     ~> 2.2.1\r\n\r\ngroup CodeGenerator\r\n    framework net8.0\r\n    storage: none\r\n    source https://api.nuget.org/v3/index.json\r\n\r\n    nuget Microsoft.NETFramework.ReferenceAssemblies  = 1.0.0\r\n    nuget Microsoft.CodeAnalysis.CSharp              ~> 4.1.0\r\n\r\ngroup Demo\r\n    framework net8.0\r\n    storage: none\r\n    source https://api.nuget.org/v3/index.json\r\n\r\n    nuget System.Reactive          ~> 6.0.0\r\n    nuget CSharp.Data.Adaptive     ~> 1.2.0\r\n\r\ngroup Test\r\n    framework: net8.0\r\n    storage: none\r\n    source https://api.nuget.org/v3/index.json\r\n\r\n    nuget NUnit                    ~> 3.14.0\r\n    nuget FsUnit                   ~> 5.6.1\r\n    nuget FsCheck                  ~> 2.16.6\r\n    nuget FsCheck.NUnit            ~> 2.16.6\r\n    nuget NUnit3TestAdapter        ~> 4.5.0\r\n    nuget Microsoft.NET.Test.Sdk   ~> 17.9.0\r\n    nuget Expecto                  ~> 10.2.1\r\n    nuget Expecto.FsCheck          ~> 10.2.1\r\n    nuget YoloDev.Expecto.TestSdk  ~> 0.14.3\r\n\r\n    nuget BenchmarkDotNet          ~> 0.13.12"
  },
  {
    "path": "src/Aardvark.Base/Aardvark.Base.csproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks>\r\n    <LangVersion>12.0</LangVersion>\r\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug</OutputPath>\r\n    <NoWarn>1701;1702;1705;1591</NoWarn>\r\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n    <NoWarn>1701;1702;1705;1591</NoWarn>\r\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Compile Remove=\"**\\*_template.cs\" />\r\n    <Compile Remove=\"**\\*_generator.cs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"**\\*_template.cs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Remove=\"Geometry\\Polygon2_template.cs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <CodeAnalysisDictionary Include=\"Geometry\\Types\\Polygon\\Polygon2_template.cs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\Aardvark.Base.Telemetry\\Aardvark.Base.Telemetry.csproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/AdaBoost.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Adaptive boosting creates a strong binary classifier\n    /// out of an ensemble of weak classifiers.\n    /// </summary>\n    public static class AdaBoost\n    {\n        /// <summary>\n        /// Creates a strong binary classifier out of an ensemble of weak classifiers.\n        /// </summary>\n        /// <typeparam name=\"T\">Type of items to be classified.</typeparam>\n        /// <param name=\"items\">Training set.</param>\n        /// <param name=\"groundTruth\">Correct classification of training set.</param>\n        /// <param name=\"getNextWeakClassifier\">\n        /// Returns a new weak classifier for given weighted items.\n        /// (double[] weights, T[] items, bool[] groundTruth) => T => bool.\n        /// </param>\n        /// <param name=\"iterations\">Maximium number of weak classifiers to combine.</param>\n        /// <param name=\"onIteration\">Optional callback for each learning iteration.\n        /// If onIteration returns true, then learning is stopped.</param>\n        /// <param name=\"stopIfWeakClassifierHasLessImportanceThan\">Default is 0.0, which means that the\n        /// maximum number of iterations will be performed.</param>\n        /// <returns>A strong classifier for Ts based on a weighted majority vote of\n        /// weak classifiers.</returns>\n        public static Func<T, bool> Train<T>(\n            T[] items, bool[] groundTruth,\n            Func<double[], T[], bool[], Func<T, bool>> getNextWeakClassifier,\n            int iterations,\n            Func<Func<T, bool>, bool> onIteration = null,\n            double stopIfWeakClassifierHasLessImportanceThan = 0.0\n            )\n        {\n            var count = items.Length;\n            var ws = new double[count].Set(1.0 / count);\n            var classifiers = new List<Func<T, bool>>();\n            var alphas = new List<double>();\n\n            while (iterations-- > 0)\n            {\n                try\n                {\n                    // get next weak classifier (based on examples and weights)\n                    var classifier = getNextWeakClassifier(ws, items, groundTruth);\n\n                    // predict values with new classifier\n                    var predictions = items.Select(x => classifier(x)).ToArray();\n\n                    // compare predictions to reality (and compute error rate e)\n                    double e = 0.0;\n                    for (var j = 0; j < count; j++)\n                    {\n                        e += ws[j] * (predictions[j] == groundTruth[j] ? 0 : 1);\n                    }\n\n                    if (Math.Abs(0.5 - e) < 0.02) { iterations++; continue; }\n\n                    if (e == 0.0) // we found a perfect classifier\n                    {\n                        classifiers.Clear(); classifiers.Add(classifier);\n                        alphas.Clear(); alphas.Add(1.0);\n                        break;\n                    }\n\n                    // compute importance for this classifier\n                    // (higher error rate gives less importance)\n                    var alpha = 0.5 * Math.Log((1 - e) / e);\n                    if (Math.Abs(alpha) < stopIfWeakClassifierHasLessImportanceThan) break;\n\n                    // increase weights of incorrectly classified examples, and\n                    // decrease weights of correctly classified examples\n                    var up = Math.Exp(alpha);\n                    var down = Math.Exp(-alpha);\n                    for (var j = 0; j < count; j++)\n                    {\n                        ws[j] *= (predictions[j] == groundTruth[j]) ? down : up;\n                    }\n                    var wnormf = 1.0 / ws.Sum(); // normalization factor for weights\n                    for (var j = 0; j < count; j++) ws[j] *= wnormf;\n\n                    // add classifier and its importance to list\n                    classifiers.Add(classifier);\n                    alphas.Add(alpha);\n\n                    // optional callback\n                    if (onIteration != null)\n                    {\n                        var c = new Classifier<T>(\n                            Enumerable.Range(0, ws.Length).Select(i => new WeightedExample<T>(ws[i], items[i])),\n                            Enumerable.Range(0, alphas.Count).Select(i => new WeakClassifier<T>(alphas[i], classifiers[i]))\n                            );\n                        if (onIteration(c.Classify))\n                        {\n                            break;\n                        }\n                    }\n                }\n                catch /*(Exception e)*/\n                {\n                    Report.Warn(\"AdaBoost.Train\");\n                }\n            }\n\n            // create strong classifier from weak classifiers\n            return new Classifier<T>(\n                Enumerable.Range(0, ws.Length).Select(i => new WeightedExample<T>(ws[i], items[i])),\n                Enumerable.Range(0, alphas.Count).Select(i => new WeakClassifier<T>(alphas[i], classifiers[i]))\n                ).Classify;\n        }\n\n        private readonly struct Classifier<T>\n        {\n\t\t\tprivate readonly WeakClassifier<T>[] m_weakClassifiers;\n\n            public Classifier(\n                IEnumerable<WeightedExample<T>> examples,\n                IEnumerable<WeakClassifier<T>> weakClassifiers\n                )\n            {\n                m_weakClassifiers = weakClassifiers.ToArray();\n            }\n\n            public bool Classify(T x) => SumAlphaWeightedWeakClassifiers(x) > 0.0;\n\n            /// <summary>\n            /// Computes propability of positive classification given x.\n            /// </summary>\n            public double P(T x) => 1.0 / (1.0 + Math.Exp(-2.0 * SumAlphaWeightedWeakClassifiers(x)));\n\n            private double SumAlphaWeightedWeakClassifiers(T x)\n                => m_weakClassifiers.Sum(c => c.Alpha * (c.Classifier(x) ? +1 : -1));\n        }\n\n        private readonly struct WeightedExample<T>\n        {\n            public readonly double Weight;\n            public readonly T Example;\n\n            public WeightedExample(double weight, T example)\n            {\n                Weight = weight;\n                Example = example;\n            }\n        }\n\n        private readonly struct WeakClassifier<T>\n        {\n            public readonly double Alpha;\n            public readonly Func<T, bool> Classifier;\n\n            public WeakClassifier(double alpha, Func<T, bool> classifier)\n            {\n                Alpha = alpha;\n                Classifier = classifier ?? throw new ArgumentNullException(\"classifier\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/ConcurrentHashSet.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\n\nnamespace System.Collections.Concurrent\n{\n    /// <summary>\n    /// Represents a thread-safe collection that can be accessed by multiple threads concurrently.\n    /// </summary>\n    public class ConcurrentHashSet<T> : IEnumerable<T>, ICollection<T>\n    {\n\t\t//int does not waste too much memory and might be used for reference-counting \n\t\t//or similar features. TODO: investigate if this is faster using reference types.\n        private readonly ConcurrentDictionary<T, int> m_entries;\n\n        #region Constructors\n\n        public ConcurrentHashSet()\n        {\n            m_entries = new ConcurrentDictionary<T, int>();\n        }\n\n        public ConcurrentHashSet(int concurrencyLevel, int capacity)\n        {\n            m_entries = new ConcurrentDictionary<T, int>(concurrencyLevel, capacity);\n        }\n\n        public ConcurrentHashSet(IEqualityComparer<T> comparer)\n        {\n            m_entries = new ConcurrentDictionary<T, int>(comparer);\n        }\n\n        public ConcurrentHashSet(IEnumerable<T> collection)\n        {\n            m_entries = new ConcurrentDictionary<T, int>(collection.Select(e => new KeyValuePair<T, int>(e, 1)));\n        }\n\n        public ConcurrentHashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer)\n        {\n            m_entries = new ConcurrentDictionary<T, int>(collection.Select(e => new KeyValuePair<T, int>(e, 1)), comparer);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public int Count => m_entries.Count;\n\n        #endregion\n\n        #region Methods\n\n        public void Clear() => m_entries.Clear();\n\n        public bool Add(T item) => m_entries.TryAdd(item, 1);\n\n        public bool Remove(T item) => m_entries.TryRemove(item, out int dummy);\n\n        public void UnionWith(IEnumerable<T> other)\n        {\n            foreach (var e in other)\n                Add(e);\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        public Enumerator GetEnumerator() => new Enumerator(this);\n\n        IEnumerator<T> IEnumerable<T>.GetEnumerator() => new Enumerator(this);\n\n        IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this);\n\n        #endregion\n\n        #region ICollection Members\n\n        public bool Contains(T item) => m_entries.ContainsKey(item);\n\n        public void CopyTo(T[] array, int arrayIndex) => m_entries.Keys.CopyTo(array, arrayIndex);\n\n        public bool IsReadOnly => false;\n\n        void ICollection<T>.Add(T item) => Add(item);\n\n        #endregion\n\n        public readonly struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator\n        {\n            private readonly IEnumerator<KeyValuePair<T, int>> m_enumerator;\n\n            internal Enumerator(ConcurrentHashSet<T> set)\n            {\n                m_enumerator = set.m_entries.GetEnumerator();\n            }\n\n            public T Current => m_enumerator.Current.Key;\n\n            public void Dispose() => m_enumerator.Dispose();\n\n            object IEnumerator.Current => ((IEnumerator)m_enumerator).Current;\n\n            public bool MoveNext() => m_enumerator.MoveNext();\n\n            public void Reset() => m_enumerator.Reset();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/ExtendedCore/BitHelpers.cs",
    "content": "﻿// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nusing System;\nusing System.Collections;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// ABOUT:\n    /// Helps with operations that rely on bit marking to indicate whether an item in the \n    /// collection should be added, removed, visited already, etc. \n    /// \n    /// BitHelper doesn't allocate the array; you must pass in an array or ints allocated on the \n    /// stack or heap. ToIntArrayLength() tells you the int array size you must allocate. \n    /// \n    /// USAGE:\n    /// Suppose you need to represent a bit array of length (i.e. logical bit array length)\n    /// BIT_ARRAY_LENGTH. Then this is the suggested way to instantiate BitHelper:\n    /// ***************************************************************************\n    /// int intArrayLength = BitHelper.ToIntArrayLength(BIT_ARRAY_LENGTH);\n    /// BitHelper bitHelper;\n    /// if (intArrayLength less than stack alloc threshold)\n    ///     int* m_arrayPtr = stackalloc int[intArrayLength];\n    ///     bitHelper = new BitHelper(m_arrayPtr, intArrayLength);\n    /// else\n    ///     int[] m_arrayPtr = new int[intArrayLength];\n    ///     bitHelper = new BitHelper(m_arrayPtr, intArrayLength);\n    /// ***************************************************************************\n    /// \n    /// IMPORTANT:\n    /// The second ctor args, length, should be specified as the length of the int array, not\n    /// the logical bit array. Because length is used for bounds checking into the int array,\n    /// it's especially important to get this correct for the stackalloc version. See the code \n    /// samples above; this is the value gotten from ToIntArrayLength(). \n    /// \n    /// The length ctor argument is the only exception; for other methods -- MarkBit and \n    /// IsMarked -- pass in values as indices into the logical bit array, and it will be mapped\n    /// to the position within the array of ints.\n    /// \n    /// FUTURE OPTIMIZATIONS:\n    /// A method such as FindFirstMarked/Unmarked Bit would be useful for callers that operate \n    /// on a bit array and then need to loop over it. In particular, if it avoided visiting \n    /// every bit, it would allow good perf improvements when the bit array is sparse.\n    /// </summary>\n    unsafe internal sealed class BitHelperExt\n    {   // should not be serialized\n        private const byte MarkedBitFlag = 1;\n        private const byte IntSize = 32;\n\n        // m_length of underlying int array (not logical bit array)\n        private readonly int _length;\n\n        // ptr to stack alloc'd array of ints\n        private readonly int* _arrayPtr;\n\n        // array of ints\n        private readonly int[] _array;\n\n        // whether to operate on stack alloc'd or heap alloc'd array \n        private readonly bool _useStackAlloc;\n\n        /// <summary>\n        /// Instantiates a BitHelper with a heap alloc'd array of ints\n        /// </summary>\n        /// <param name=\"bitArrayPtr\">int array to hold bits</param>\n        /// <param name=\"length\">length of int array</param>\n        internal BitHelperExt(int* bitArrayPtr, int length)\n        {\n            _arrayPtr = bitArrayPtr;\n            _length = length;\n            _useStackAlloc = true;\n        }\n\n        /// <summary>\n        /// Instantiates a BitHelper with a heap alloc'd array of ints\n        /// </summary>\n        /// <param name=\"bitArray\">int array to hold bits</param>\n        /// <param name=\"length\">length of int array</param>\n        internal BitHelperExt(int[] bitArray, int length)\n        {\n            _array = bitArray;\n            _length = length;\n        }\n\n        /// <summary>\n        /// Mark bit at specified position\n        /// </summary>\n        /// <param name=\"bitPosition\"></param>\n        internal void MarkBit(int bitPosition)\n        {\n            int bitArrayIndex = bitPosition / IntSize;\n            if (bitArrayIndex < _length && bitArrayIndex >= 0)\n            {\n                int flag = (MarkedBitFlag << (bitPosition % IntSize));\n                if (_useStackAlloc)\n                {\n                    _arrayPtr[bitArrayIndex] |= flag;\n                }\n                else\n                {\n                    _array[bitArrayIndex] |= flag;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Is bit at specified position marked?\n        /// </summary>\n        /// <param name=\"bitPosition\"></param>\n        /// <returns></returns>\n        internal bool IsMarked(int bitPosition)\n        {\n            int bitArrayIndex = bitPosition / IntSize;\n            if (bitArrayIndex < _length && bitArrayIndex >= 0)\n            {\n                int flag = (MarkedBitFlag << (bitPosition % IntSize));\n                if (_useStackAlloc)\n                {\n                    return ((_arrayPtr[bitArrayIndex] & flag) != 0);\n                }\n                else\n                {\n                    return ((_array[bitArrayIndex] & flag) != 0);\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// How many ints must be allocated to represent n bits. Returns (n+31)/32, but \n        /// avoids overflow\n        /// </summary>\n        /// <param name=\"n\"></param>\n        /// <returns></returns>\n        internal static int ToIntArrayLength(int n)\n        {\n            return n > 0 ? ((n - 1) / IntSize + 1) : 0;\n        }\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/ExtendedCore/SortedSetExt.cs",
    "content": "﻿// Copyright (c) Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/*============================================================\n**\n**\n** Purpose: A generic sorted set.\n**\n** This is a copy of SortedSet extending it with neighbourhood information\n===========================================================*/\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Diagnostics.CodeAnalysis;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    //\n    // A binary search tree is a red-black tree if it satifies the following red-black properties:\n    // 1. Every node is either red or black\n    // 2. Every leaf (nil node) is black\n    // 3. If a node is red, the both its children are black\n    // 4. Every simple path from a node to a descendant leaf contains the same number of black nodes\n    // \n    // The basic idea of red-black tree is to represent 2-3-4 trees as standard BSTs but to add one extra bit of information  \n    // per node to encode 3-nodes and 4-nodes. \n    // 4-nodes will be represented as:          B\n    //                                                              R            R\n    // 3 -node will be represented as:           B             or         B     \n    //                                                              R          B               B       R\n    // \n    // For a detailed description of the algorithm, take a look at \"Algorithm\" by Rebert Sedgewick.\n    //\n\n    internal delegate bool TreeWalkPredicate<T>(SortedSetExt<T>.Node node);\n\n    internal enum TreeRotation\n    {\n        LeftRotation = 1,\n        RightRotation = 2,\n        RightLeftRotation = 3,\n        LeftRightRotation = 4,\n    }\n\n\n    public class Optional<T>\n    {\n        public bool HasValue;\n        public T Value;\n\n        private Optional()\n        {\n            HasValue = false;\n            Value = default(T);\n        }\n\n        public Optional(T value)\n        {\n            HasValue = true;\n            Value = value;\n        }\n\n        public static Optional<T> None = new Optional<T>();\n    }\n\n    [DebuggerDisplay(\"Count = {Count}\")]\n    public class SortedSetExt<T> : ISet<T>, ICollection<T>, ICollection, IReadOnlyCollection<T>\n    {\n        #region local variables/constants\n        private Node _root;\n        private readonly IComparer<T> _comparer;\n        private int _count;\n        private int _version;\n        private Object _syncRoot;\n\n        internal const int StackAllocThreshold = 100;\n\n        #endregion\n\n        #region Constructors\n        public SortedSetExt()\n        {\n            _comparer = Comparer<T>.Default;\n        }\n\n        public SortedSetExt(IComparer<T> comparer)\n        {\n            if (comparer == null)\n            {\n                _comparer = Comparer<T>.Default;\n            }\n            else\n            {\n                _comparer = comparer;\n            }\n        }\n\n\n        public SortedSetExt(IEnumerable<T> collection) : this(collection, Comparer<T>.Default) { }\n\n        public SortedSetExt(IEnumerable<T> collection, IComparer<T> comparer)\n            : this(comparer)\n        {\n            if (collection == null)\n            {\n                throw new ArgumentNullException(\"collection\");\n            }\n\n            // these are explicit type checks in the mould of HashSet. It would have worked better\n            // with something like an ISorted<T> (we could make this work for SortedList.Keys etc)\n            SortedSetExt<T> baseSortedSet = collection as SortedSetExt<T>;\n            SortedSetExt<T> baseTreeSubSet = collection as TreeSubSet;\n            if (baseSortedSet != null && baseTreeSubSet == null && AreComparersEqual(this, baseSortedSet))\n            {\n                //breadth first traversal to recreate nodes\n                if (baseSortedSet.Count == 0)\n                {\n                    return;\n                }\n\n                //pre order way to replicate nodes\n                Stack<Node> theirStack = new Stack<SortedSetExt<T>.Node>(2 * log2(baseSortedSet.Count) + 2);\n                Stack<Node> myStack = new Stack<SortedSetExt<T>.Node>(2 * log2(baseSortedSet.Count) + 2);\n                Node theirCurrent = baseSortedSet._root;\n                Node myCurrent = (theirCurrent != null ? new SortedSetExt<T>.Node(theirCurrent.Item, theirCurrent.IsRed) : null);\n                _root = myCurrent;\n                while (theirCurrent != null)\n                {\n                    theirStack.Push(theirCurrent);\n                    myStack.Push(myCurrent);\n                    myCurrent.Left = (theirCurrent.Left != null ? new SortedSetExt<T>.Node(theirCurrent.Left.Item, theirCurrent.Left.IsRed) : null);\n                    theirCurrent = theirCurrent.Left;\n                    myCurrent = myCurrent.Left;\n                }\n                while (theirStack.Count != 0)\n                {\n                    theirCurrent = theirStack.Pop();\n                    myCurrent = myStack.Pop();\n                    Node theirRight = theirCurrent.Right;\n                    Node myRight = null;\n                    if (theirRight != null)\n                    {\n                        myRight = new SortedSetExt<T>.Node(theirRight.Item, theirRight.IsRed);\n                    }\n                    myCurrent.Right = myRight;\n\n                    while (theirRight != null)\n                    {\n                        theirStack.Push(theirRight);\n                        myStack.Push(myRight);\n                        myRight.Left = (theirRight.Left != null ? new SortedSetExt<T>.Node(theirRight.Left.Item, theirRight.Left.IsRed) : null);\n                        theirRight = theirRight.Left;\n                        myRight = myRight.Left;\n                    }\n                }\n                _count = baseSortedSet._count;\n            }\n            else\n            {\n                T[] els = collection.ToArray();\n                int count = els.Length;\n\n                if (count > 0)\n                {\n                    Array.Sort(els, 0, count, _comparer);\n                    int index = 1;\n                    for (int i = 1; i < count; i++)\n                    {\n                        if (comparer.Compare(els[i], els[i - 1]) != 0)\n                        {\n                            els[index++] = els[i];\n                        }\n                    }\n                    count = index;\n\n                    _root = ConstructRootFromSortedArray(els, 0, count - 1, null);\n                    _count = count;\n                }\n            }\n        }\n\n        #endregion\n\n        #region Bulk Operation Helpers\n        private void AddAllElements(IEnumerable<T> collection)\n        {\n            foreach (T item in collection)\n            {\n                if (!this.Contains(item))\n                    Add(item);\n            }\n        }\n\n        private void RemoveAllElements(IEnumerable<T> collection)\n        {\n            T min = this.Min;\n            T max = this.Max;\n            foreach (T item in collection)\n            {\n                if (!(_comparer.Compare(item, min) < 0 || _comparer.Compare(item, max) > 0) && this.Contains(item))\n                    this.Remove(item);\n            }\n        }\n\n        private bool ContainsAllElements(IEnumerable<T> collection)\n        {\n            foreach (T item in collection)\n            {\n                if (!this.Contains(item))\n                {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        //\n        // Do a in order walk on tree and calls the delegate for each node.\n        // If the action delegate returns false, stop the walk.\n        // \n        // Return true if the entire tree has been walked. \n        // Otherwise returns false.\n        //\n        internal bool InOrderTreeWalk(TreeWalkPredicate<T> action)\n        {\n            return InOrderTreeWalk(action, false);\n        }\n\n        // Allows for the change in traversal direction. Reverse visits nodes in descending order \n        internal virtual bool InOrderTreeWalk(TreeWalkPredicate<T> action, bool reverse)\n        {\n            if (_root == null)\n            {\n                return true;\n            }\n\n            // The maximum height of a red-black tree is 2*lg(n+1).\n            // See page 264 of \"Introduction to algorithms\" by Thomas H. Cormen\n            // note: this should be logbase2, but since the stack grows itself, we \n            // don't want the extra cost\n            Stack<Node> stack = new Stack<Node>(2 * (int)(SortedSetExt<T>.log2(Count + 1)));\n            Node current = _root;\n            while (current != null)\n            {\n                stack.Push(current);\n                current = (reverse ? current.Right : current.Left);\n            }\n            while (stack.Count != 0)\n            {\n                current = stack.Pop();\n                if (!action(current))\n                {\n                    return false;\n                }\n\n                Node node = (reverse ? current.Left : current.Right);\n                while (node != null)\n                {\n                    stack.Push(node);\n                    node = (reverse ? node.Right : node.Left);\n                }\n            }\n            return true;\n        }\n\n        //\n        // Do a left to right breadth first walk on tree and \n        // calls the delegate for each node.\n        // If the action delegate returns false, stop the walk.\n        // \n        // Return true if the entire tree has been walked. \n        // Otherwise returns false.\n        //\n        internal virtual bool BreadthFirstTreeWalk(TreeWalkPredicate<T> action)\n        {\n            if (_root == null)\n            {\n                return true;\n            }\n\n            Queue<Node> processQueue = new Queue<Node>();\n            processQueue.Enqueue(_root);\n            Node current;\n\n            while (processQueue.Count != 0)\n            {\n                current = processQueue.Dequeue();\n                if (!action(current))\n                {\n                    return false;\n                }\n                if (current.Left != null)\n                {\n                    processQueue.Enqueue(current.Left);\n                }\n                if (current.Right != null)\n                {\n                    processQueue.Enqueue(current.Right);\n                }\n            }\n            return true;\n        }\n        #endregion\n\n        #region Properties\n        public int Count\n        {\n            get\n            {\n                VersionCheck();\n                return _count;\n            }\n        }\n\n        public IComparer<T> Comparer\n        {\n            get\n            {\n                return _comparer;\n            }\n        }\n\n        bool ICollection<T>.IsReadOnly\n        {\n            get\n            {\n                return false;\n            }\n        }\n\n        bool ICollection.IsSynchronized\n        {\n            get\n            {\n                return false;\n            }\n        }\n\n        object ICollection.SyncRoot\n        {\n            get\n            {\n                if (_syncRoot == null)\n                {\n                    System.Threading.Interlocked.CompareExchange(ref _syncRoot, new Object(), null);\n                }\n                return _syncRoot;\n            }\n        }\n        #endregion\n\n        #region Subclass helpers\n\n        //virtual function for subclass that needs to update count\n        internal virtual void VersionCheck() { }\n\n\n        //virtual function for subclass that needs to do range checks\n        internal virtual bool IsWithinRange(T item)\n        {\n            return true;\n        }\n        #endregion\n\n        #region ICollection<T> Members\n        /// <summary>\n        /// Add the value ITEM to the tree, returns true if added, false if duplicate \n        /// </summary>\n        /// <param name=\"item\">item to be added</param> \n        public bool Add(T item)\n        {\n            return AddIfNotPresent(item);\n        }\n\n        void ICollection<T>.Add(T item)\n        {\n            AddIfNotPresent(item);\n        }\n\n\n        /// <summary>\n        /// Adds ITEM to the tree if not already present. Returns TRUE if value was successfully added         \n        /// or FALSE if it is a duplicate\n        /// </summary>        \n        internal virtual bool AddIfNotPresent(T item)\n        {\n            if (_root == null)\n            {   // empty tree\n                _root = new Node(item, false);\n                _count = 1;\n                _version++;\n                return true;\n            }\n\n            //\n            // Search for a node at bottom to insert the new node. \n            // If we can guanratee the node we found is not a 4-node, it would be easy to do insertion.\n            // We split 4-nodes along the search path.\n            // \n            Node current = _root;\n            Node parent = null;\n            Node grandParent = null;\n            Node greatGrandParent = null;\n\n            //even if we don't actually add to the set, we may be altering its structure (by doing rotations\n            //and such). so update version to disable any enumerators/subsets working on it\n            _version++;\n\n\n            int order = 0;\n            while (current != null)\n            {\n                order = _comparer.Compare(item, current.Item);\n                if (order == 0)\n                {\n                    // We could have changed root node to red during the search process.\n                    // We need to set it to black before we return.\n                    _root.IsRed = false;\n                    return false;\n                }\n\n                // split a 4-node into two 2-nodes                \n                if (Is4Node(current))\n                {\n                    Split4Node(current);\n                    // We could have introduced two consecutive red nodes after split. Fix that by rotation.\n                    if (IsRed(parent))\n                    {\n                        InsertionBalance(current, ref parent, grandParent, greatGrandParent);\n                    }\n                }\n                greatGrandParent = grandParent;\n                grandParent = parent;\n                parent = current;\n                current = (order < 0) ? current.Left : current.Right;\n            }\n\n            Debug.Assert(parent != null, \"Parent node cannot be null here!\");\n            // ready to insert the new node\n            Node node = new Node(item);\n            if (order > 0)\n            {\n                parent.Right = node;\n            }\n            else\n            {\n                parent.Left = node;\n            }\n\n            // the new node will be red, so we will need to adjust the colors if parent node is also red\n            if (parent.IsRed)\n            {\n                InsertionBalance(node, ref parent, grandParent, greatGrandParent);\n            }\n\n            // Root node is always black\n            _root.IsRed = false;\n            ++_count;\n            return true;\n        }\n\n        /// <summary>\n        /// Remove the T ITEM from this SortedSet. Returns true if successfully removed.\n        /// </summary>\n        /// <param name=\"item\"></param>\n        /// <returns></returns>\n        public bool Remove(T item)\n        {\n            return this.DoRemove(item); // hack so it can be made non-virtual\n        }\n\n        internal virtual bool DoRemove(T item)\n        {\n            if (_root == null)\n            {\n                return false;\n            }\n\n\n            // Search for a node and then find its succesor. \n            // Then copy the item from the succesor to the matching node and delete the successor. \n            // If a node doesn't have a successor, we can replace it with its left child (if not empty.) \n            // or delete the matching node.\n            // \n            // In top-down implementation, it is important to make sure the node to be deleted is not a 2-node.\n            // Following code will make sure the node on the path is not a 2 Node. \n\n            //even if we don't actually remove from the set, we may be altering its structure (by doing rotations\n            //and such). so update version to disable any enumerators/subsets working on it\n            _version++;\n\n            Node current = _root;\n            Node parent = null;\n            Node grandParent = null;\n            Node match = null;\n            Node parentOfMatch = null;\n            bool foundMatch = false;\n            while (current != null)\n            {\n                if (Is2Node(current))\n                { // fix up 2-Node\n                    if (parent == null)\n                    {   // current is root. Mark it as red\n                        current.IsRed = true;\n                    }\n                    else\n                    {\n                        Node sibling = GetSibling(current, parent);\n                        if (sibling.IsRed)\n                        {\n                            // If parent is a 3-node, flip the orientation of the red link. \n                            // We can acheive this by a single rotation        \n                            // This case is converted to one of other cased below.\n                            Debug.Assert(!parent.IsRed, \"parent must be a black node!\");\n                            if (parent.Right == sibling)\n                            {\n                                RotateLeft(parent);\n                            }\n                            else\n                            {\n                                RotateRight(parent);\n                            }\n\n                            parent.IsRed = true;\n                            sibling.IsRed = false;    // parent's color\n                            // sibling becomes child of grandParent or root after rotation. Update link from grandParent or root\n                            ReplaceChildOfNodeOrRoot(grandParent, parent, sibling);\n                            // sibling will become grandParent of current node \n                            grandParent = sibling;\n                            if (parent == match)\n                            {\n                                parentOfMatch = sibling;\n                            }\n\n                            // update sibling, this is necessary for following processing\n                            sibling = (parent.Left == current) ? parent.Right : parent.Left;\n                        }\n                        Debug.Assert(sibling != null || sibling.IsRed == false, \"sibling must not be null and it must be black!\");\n\n                        if (Is2Node(sibling))\n                        {\n                            Merge2Nodes(parent, current, sibling);\n                        }\n                        else\n                        {\n                            // current is a 2-node and sibling is either a 3-node or a 4-node.\n                            // We can change the color of current to red by some rotation.\n                            TreeRotation rotation = RotationNeeded(parent, current, sibling);\n                            Node newGrandParent = null;\n                            switch (rotation)\n                            {\n                                case TreeRotation.RightRotation:\n                                    Debug.Assert(parent.Left == sibling, \"sibling must be left child of parent!\");\n                                    Debug.Assert(sibling.Left.IsRed, \"Left child of sibling must be red!\");\n                                    sibling.Left.IsRed = false;\n                                    newGrandParent = RotateRight(parent);\n                                    break;\n                                case TreeRotation.LeftRotation:\n                                    Debug.Assert(parent.Right == sibling, \"sibling must be left child of parent!\");\n                                    Debug.Assert(sibling.Right.IsRed, \"Right child of sibling must be red!\");\n                                    sibling.Right.IsRed = false;\n                                    newGrandParent = RotateLeft(parent);\n                                    break;\n\n                                case TreeRotation.RightLeftRotation:\n                                    Debug.Assert(parent.Right == sibling, \"sibling must be left child of parent!\");\n                                    Debug.Assert(sibling.Left.IsRed, \"Left child of sibling must be red!\");\n                                    newGrandParent = RotateRightLeft(parent);\n                                    break;\n\n                                case TreeRotation.LeftRightRotation:\n                                    Debug.Assert(parent.Left == sibling, \"sibling must be left child of parent!\");\n                                    Debug.Assert(sibling.Right.IsRed, \"Right child of sibling must be red!\");\n                                    newGrandParent = RotateLeftRight(parent);\n                                    break;\n                            }\n\n                            newGrandParent.IsRed = parent.IsRed;\n                            parent.IsRed = false;\n                            current.IsRed = true;\n                            ReplaceChildOfNodeOrRoot(grandParent, parent, newGrandParent);\n                            if (parent == match)\n                            {\n                                parentOfMatch = newGrandParent;\n                            }\n                            grandParent = newGrandParent;\n                        }\n                    }\n                }\n\n                // we don't need to compare any more once we found the match\n                int order = foundMatch ? -1 : _comparer.Compare(item, current.Item);\n                if (order == 0)\n                {\n                    // save the matching node\n                    foundMatch = true;\n                    match = current;\n                    parentOfMatch = parent;\n                }\n\n                grandParent = parent;\n                parent = current;\n\n                if (order < 0)\n                {\n                    current = current.Left;\n                }\n                else\n                {\n                    current = current.Right;       // continue the search in  right sub tree after we find a match\n                }\n            }\n\n            // move successor to the matching node position and replace links\n            if (match != null)\n            {\n                ReplaceNode(match, parentOfMatch, parent, grandParent);\n                --_count;\n            }\n\n            if (_root != null)\n            {\n                _root.IsRed = false;\n            }\n            return foundMatch;\n        }\n\n        public virtual void Clear()\n        {\n            _root = null;\n            _count = 0;\n            ++_version;\n        }\n\n\n        public virtual bool Contains(T item)\n        {\n            return FindNode(item) != null;\n        }\n\n\n\n\n        public void CopyTo(T[] array) { CopyTo(array, 0, Count); }\n\n        public void CopyTo(T[] array, int index) { CopyTo(array, index, Count); }\n\n        public void CopyTo(T[] array, int index, int count)\n        {\n            if (array == null)\n            {\n                throw new ArgumentNullException(\"array\");\n            }\n\n            if (index < 0)\n            {\n                throw new ArgumentOutOfRangeException(\"index\");\n            }\n\n            if (count < 0)\n            {\n                throw new ArgumentOutOfRangeException(\"count\", \"SR.ArgumentOutOfRange_NeedNonNegNum\");\n            }\n\n            // will array, starting at arrayIndex, be able to hold elements? Note: not\n            // checking arrayIndex >= array.Length (consistency with list of allowing\n            // count of 0; subsequent check takes care of the rest)\n            if (index > array.Length || count > array.Length - index)\n            {\n                throw new ArgumentException(\"SR.Arg_ArrayPlusOffTooSmall\");\n            }\n            //upper bound\n            count += index;\n\n            InOrderTreeWalk(delegate (Node node)\n            {\n                if (index >= count)\n                {\n                    return false;\n                }\n                else\n                {\n                    array[index++] = node.Item;\n                    return true;\n                }\n            });\n        }\n\n        void ICollection.CopyTo(Array array, int index)\n        {\n            if (array == null)\n            {\n                throw new ArgumentNullException(\"array\");\n            }\n\n            if (array.Rank != 1)\n            {\n                throw new ArgumentException(\"SR.Arg_RankMultiDimNotSupported\");\n            }\n\n            if (array.GetLowerBound(0) != 0)\n            {\n                throw new ArgumentException(\"SR.Arg_NonZeroLowerBound\");\n            }\n\n            if (index < 0)\n            {\n                throw new ArgumentOutOfRangeException(\"arrayIndex\", \"SR.ArgumentOutOfRange_NeedNonNegNum\");\n            }\n\n            if (array.Length - index < Count)\n            {\n                throw new ArgumentException(\"SR.Arg_ArrayPlusOffTooSmall\");\n            }\n\n            T[] tarray = array as T[];\n            if (tarray != null)\n            {\n                CopyTo(tarray, index);\n            }\n            else\n            {\n                object[] objects = array as object[];\n                if (objects == null)\n                {\n                    throw new ArgumentException(\"SR.Argument_InvalidArrayType\");\n                }\n\n                try\n                {\n                    InOrderTreeWalk(delegate (Node node) { objects[index++] = node.Item; return true; });\n                }\n                catch (ArrayTypeMismatchException)\n                {\n                    throw new ArgumentException(\"SR.Argument_InvalidArrayType\");\n                }\n            }\n        }\n\n        #endregion\n\n        #region IEnumerable<T> members\n        public Enumerator GetEnumerator()\n        {\n            return new Enumerator(this);\n        }\n\n\n\n\n        IEnumerator<T> IEnumerable<T>.GetEnumerator()\n        {\n            return new Enumerator(this);\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return new Enumerator(this);\n        }\n        #endregion\n\n        #region Tree Specific Operations\n\n        private static Node GetSibling(Node node, Node parent)\n        {\n            if (parent.Left == node)\n            {\n                return parent.Right;\n            }\n            return parent.Left;\n        }\n\n        // After calling InsertionBalance, we need to make sure current and parent up-to-date.\n        // It doesn't matter if we keep grandParent and greatGrantParent up-to-date \n        // because we won't need to split again in the next node.\n        // By the time we need to split again, everything will be correctly set.\n        //  \n        private void InsertionBalance(Node current, ref Node parent, Node grandParent, Node greatGrandParent)\n        {\n            Debug.Assert(grandParent != null, \"Grand parent cannot be null here!\");\n            bool parentIsOnRight = (grandParent.Right == parent);\n            bool currentIsOnRight = (parent.Right == current);\n\n            Node newChildOfGreatGrandParent;\n            if (parentIsOnRight == currentIsOnRight)\n            { // same orientation, single rotation\n                newChildOfGreatGrandParent = currentIsOnRight ? RotateLeft(grandParent) : RotateRight(grandParent);\n            }\n            else\n            {  // different orientaton, double rotation\n                newChildOfGreatGrandParent = currentIsOnRight ? RotateLeftRight(grandParent) : RotateRightLeft(grandParent);\n                // current node now becomes the child of greatgrandparent \n                parent = greatGrandParent;\n            }\n            // grand parent will become a child of either parent of current.\n            grandParent.IsRed = true;\n            newChildOfGreatGrandParent.IsRed = false;\n\n            ReplaceChildOfNodeOrRoot(greatGrandParent, grandParent, newChildOfGreatGrandParent);\n        }\n\n        private static bool Is2Node(Node node)\n        {\n            Debug.Assert(node != null, \"node cannot be null!\");\n            return IsBlack(node) && IsNullOrBlack(node.Left) && IsNullOrBlack(node.Right);\n        }\n\n        private static bool Is4Node(Node node)\n        {\n            return IsRed(node.Left) && IsRed(node.Right);\n        }\n\n        private static bool IsBlack(Node node)\n        {\n            return (node != null && !node.IsRed);\n        }\n\n        private static bool IsNullOrBlack(Node node)\n        {\n            return (node == null || !node.IsRed);\n        }\n\n        private static bool IsRed(Node node)\n        {\n            return (node != null && node.IsRed);\n        }\n\n        private static void Merge2Nodes(Node parent, Node child1, Node child2)\n        {\n            Debug.Assert(IsRed(parent), \"parent must be be red\");\n            // combing two 2-nodes into a 4-node\n            parent.IsRed = false;\n            child1.IsRed = true;\n            child2.IsRed = true;\n        }\n\n        // Replace the child of a parent node. \n        // If the parent node is null, replace the root.        \n        private void ReplaceChildOfNodeOrRoot(Node parent, Node child, Node newChild)\n        {\n            if (parent != null)\n            {\n                if (parent.Left == child)\n                {\n                    parent.Left = newChild;\n                }\n                else\n                {\n                    parent.Right = newChild;\n                }\n            }\n            else\n            {\n                _root = newChild;\n            }\n        }\n\n        // Replace the matching node with its succesor.\n        private void ReplaceNode(Node match, Node parentOfMatch, Node succesor, Node parentOfSuccesor)\n        {\n            if (succesor == match)\n            {  // this node has no successor, should only happen if right child of matching node is null.\n                Debug.Assert(match.Right == null, \"Right child must be null!\");\n                succesor = match.Left;\n            }\n            else\n            {\n                Debug.Assert(parentOfSuccesor != null, \"parent of successor cannot be null!\");\n                Debug.Assert(succesor.Left == null, \"Left child of succesor must be null!\");\n                Debug.Assert((succesor.Right == null && succesor.IsRed) || (succesor.Right.IsRed && !succesor.IsRed), \"Succesor must be in valid state\");\n                if (succesor.Right != null)\n                {\n                    succesor.Right.IsRed = false;\n                }\n\n                if (parentOfSuccesor != match)\n                {   // detach succesor from its parent and set its right child\n                    parentOfSuccesor.Left = succesor.Right;\n                    succesor.Right = match.Right;\n                }\n\n                succesor.Left = match.Left;\n            }\n\n            if (succesor != null)\n            {\n                succesor.IsRed = match.IsRed;\n            }\n\n            ReplaceChildOfNodeOrRoot(parentOfMatch, match, succesor);\n        }\n\n        internal virtual Node FindNode(T item)\n        {\n            Node current = _root;\n            while (current != null)\n            {\n                int order = _comparer.Compare(item, current.Item);\n                if (order == 0)\n                {\n                    return current;\n                }\n                else\n                {\n                    current = (order < 0) ? current.Left : current.Right;\n                }\n            }\n\n            return null;\n        }\n\n\n        internal virtual (Node, Node, Node) FindNeighbours(T item)\n        {\n            Node current = _root;\n            Node left = null;\n            Node right = null;\n            Node self = null;\n            while (current != null)\n            {\n                int order = _comparer.Compare(item, current.Item);\n                if (order != 0)\n                {\n                    if (order > 0)\n                    {\n                        left = current;\n                        current = current.Right;\n                    }\n                    else\n                    {\n                        right = current;\n                        current = current.Left;\n                    }\n                }\n                else\n                {\n                    self = current;\n\n                    if (current.Left != null)\n                    {\n                        left = current.Left;\n                        while (left.Right != null)\n                            left = left.Right;\n                    }\n\n                    if (current.Right != null)\n                    {\n                        right = current.Right;\n                        while (right.Left != null)\n                            right = right.Left;\n                    }\n\n                    break;\n                }\n            }\n\n            return (left, self, right);\n        }\n\n\n        //used for bithelpers. Note that this implementation is completely different \n        //from the Subset's. The two should not be mixed. This indexes as if the tree were an array.\n        //http://en.wikipedia.org/wiki/Binary_Tree#Methods_for_storing_binary_trees\n        internal virtual int InternalIndexOf(T item)\n        {\n            Node current = _root;\n            int count = 0;\n            while (current != null)\n            {\n                int order = _comparer.Compare(item, current.Item);\n                if (order == 0)\n                {\n                    return count;\n                }\n                else\n                {\n                    current = (order < 0) ? current.Left : current.Right;\n                    count = (order < 0) ? (2 * count + 1) : (2 * count + 2);\n                }\n            }\n            return -1;\n        }\n\n\n\n        internal Node FindRange(T from, T to)\n        {\n            return FindRange(from, to, true, true);\n        }\n        internal Node FindRange(T from, T to, bool lowerBoundActive, bool upperBoundActive)\n        {\n            Node current = _root;\n            while (current != null)\n            {\n                if (lowerBoundActive && _comparer.Compare(from, current.Item) > 0)\n                {\n                    current = current.Right;\n                }\n                else\n                {\n                    if (upperBoundActive && _comparer.Compare(to, current.Item) < 0)\n                    {\n                        current = current.Left;\n                    }\n                    else\n                    {\n                        return current;\n                    }\n                }\n            }\n\n            return null;\n        }\n\n        internal void UpdateVersion()\n        {\n            ++_version;\n        }\n\n\n        private static Node RotateLeft(Node node)\n        {\n            Node x = node.Right;\n            node.Right = x.Left;\n            x.Left = node;\n            return x;\n        }\n\n        private static Node RotateLeftRight(Node node)\n        {\n            Node child = node.Left;\n            Node grandChild = child.Right;\n\n            node.Left = grandChild.Right;\n            grandChild.Right = node;\n            child.Right = grandChild.Left;\n            grandChild.Left = child;\n            return grandChild;\n        }\n\n        private static Node RotateRight(Node node)\n        {\n            Node x = node.Left;\n            node.Left = x.Right;\n            x.Right = node;\n            return x;\n        }\n\n        private static Node RotateRightLeft(Node node)\n        {\n            Node child = node.Right;\n            Node grandChild = child.Left;\n\n            node.Right = grandChild.Left;\n            grandChild.Left = node;\n            child.Left = grandChild.Right;\n            grandChild.Right = child;\n            return grandChild;\n        }\n        /// <summary>\n        /// Testing counter that can track rotations\n        /// </summary>\n\n\n        private static TreeRotation RotationNeeded(Node parent, Node current, Node sibling)\n        {\n            Debug.Assert(IsRed(sibling.Left) || IsRed(sibling.Right), \"sibling must have at least one red child\");\n            if (IsRed(sibling.Left))\n            {\n                if (parent.Left == current)\n                {\n                    return TreeRotation.RightLeftRotation;\n                }\n                return TreeRotation.RightRotation;\n            }\n            else\n            {\n                if (parent.Left == current)\n                {\n                    return TreeRotation.LeftRotation;\n                }\n                return TreeRotation.LeftRightRotation;\n            }\n        }\n\n        /// <summary>\n        /// Decides whether these sets are the same, given the comparer. If the EC's are the same, we can\n        /// just use SetEquals, but if they aren't then we have to manually check with the given comparer\n        /// </summary>        \n        internal static bool SortedSetEquals(SortedSetExt<T> set1, SortedSetExt<T> set2, IComparer<T> comparer)\n        {\n            // handle null cases first\n            if (set1 == null)\n            {\n                return (set2 == null);\n            }\n            else if (set2 == null)\n            {\n                // set1 != null\n                return false;\n            }\n\n            if (AreComparersEqual(set1, set2))\n            {\n                if (set1.Count != set2.Count)\n                    return false;\n\n                return set1.SetEquals(set2);\n            }\n            else\n            {\n                bool found = false;\n                foreach (T item1 in set1)\n                {\n                    found = false;\n                    foreach (T item2 in set2)\n                    {\n                        if (comparer.Compare(item1, item2) == 0)\n                        {\n                            found = true;\n                            break;\n                        }\n                    }\n                    if (!found)\n                        return false;\n                }\n                return true;\n            }\n        }\n\n\n        //This is a little frustrating because we can't support more sorted structures\n        private static bool AreComparersEqual(SortedSetExt<T> set1, SortedSetExt<T> set2)\n        {\n            return set1.Comparer.Equals(set2.Comparer);\n        }\n\n\n        private static void Split4Node(Node node)\n        {\n            node.IsRed = true;\n            node.Left.IsRed = false;\n            node.Right.IsRed = false;\n        }\n\n        /// <summary>\n        /// Copies this to an array. Used for DebugView\n        /// </summary>\n        /// <returns></returns>\n        internal T[] ToArray()\n        {\n            T[] newArray = new T[Count];\n            CopyTo(newArray);\n            return newArray;\n        }\n\n\n        #endregion\n\n        #region ISet Members\n\n        /// <summary>\n        /// Transform this set into its union with the IEnumerable OTHER            \n        ///Attempts to insert each element and rejects it if it exists.          \n        /// NOTE: The caller object is important as UnionWith uses the Comparator \n        ///associated with THIS to check equality                                \n        /// Throws ArgumentNullException if OTHER is null                         \n        /// </summary>\n        /// <param name=\"other\"></param>\n        public void UnionWith(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            SortedSetExt<T> s = other as SortedSetExt<T>;\n            TreeSubSet t = this as TreeSubSet;\n\n            if (t != null)\n                VersionCheck();\n\n            if (s != null && t == null && _count == 0)\n            {\n                SortedSetExt<T> dummy = new SortedSetExt<T>(s, _comparer);\n                _root = dummy._root;\n                _count = dummy._count;\n                _version++;\n                return;\n            }\n\n\n            if (s != null && t == null && AreComparersEqual(this, s) && (s.Count > this.Count / 2))\n            { //this actually hurts if N is much greater than M the /2 is arbitrary\n                //first do a merge sort to an array.\n                T[] merged = new T[s.Count + this.Count];\n                int c = 0;\n                Enumerator mine = this.GetEnumerator();\n                Enumerator theirs = s.GetEnumerator();\n                bool mineEnded = !mine.MoveNext(), theirsEnded = !theirs.MoveNext();\n                while (!mineEnded && !theirsEnded)\n                {\n                    int comp = Comparer.Compare(mine.Current, theirs.Current);\n                    if (comp < 0)\n                    {\n                        merged[c++] = mine.Current;\n                        mineEnded = !mine.MoveNext();\n                    }\n                    else if (comp == 0)\n                    {\n                        merged[c++] = theirs.Current;\n                        mineEnded = !mine.MoveNext();\n                        theirsEnded = !theirs.MoveNext();\n                    }\n                    else\n                    {\n                        merged[c++] = theirs.Current;\n                        theirsEnded = !theirs.MoveNext();\n                    }\n                }\n\n                if (!mineEnded || !theirsEnded)\n                {\n                    Enumerator remaining = (mineEnded ? theirs : mine);\n                    do\n                    {\n                        merged[c++] = remaining.Current;\n                    } while (remaining.MoveNext());\n                }\n\n                //now merged has all c elements\n\n                //safe to gc the root, we  have all the elements\n                _root = null;\n\n\n                _root = SortedSetExt<T>.ConstructRootFromSortedArray(merged, 0, c - 1, null);\n                _count = c;\n                _version++;\n            }\n            else\n            {\n                AddAllElements(other);\n            }\n        }\n\n\n        private static Node ConstructRootFromSortedArray(T[] arr, int startIndex, int endIndex, Node redNode)\n        {\n            //what does this do?\n            //you're given a sorted array... say 1 2 3 4 5 6 \n            //2 cases:\n            //    If there are odd # of elements, pick the middle element (in this case 4), and compute\n            //    its left and right branches\n            //    If there are even # of elements, pick the left middle element, save the right middle element\n            //    and call the function on the rest\n            //    1 2 3 4 5 6 -> pick 3, save 4 and call the fn on 1,2 and 5,6\n            //    now add 4 as a red node to the lowest element on the right branch\n            //             3                       3\n            //         1       5       ->     1        5\n            //           2       6             2     4   6            \n            //    As we're adding to the leftmost of the right branch, nesting will not hurt the red-black properties\n            //    Leaf nodes are red if they have no sibling (if there are 2 nodes or if a node trickles\n            //    down to the bottom\n\n\n            //the iterative way to do this ends up wasting more space than it saves in stack frames (at\n            //least in what i tried)\n            //so we're doing this recursively\n            //base cases are described below\n            int size = endIndex - startIndex + 1;\n            if (size == 0)\n            {\n                return null;\n            }\n            Node root = null;\n            if (size == 1)\n            {\n                root = new Node(arr[startIndex], false);\n                if (redNode != null)\n                {\n                    root.Left = redNode;\n                }\n            }\n            else if (size == 2)\n            {\n                root = new Node(arr[startIndex], false);\n                root.Right = new Node(arr[endIndex], false);\n                root.Right.IsRed = true;\n                if (redNode != null)\n                {\n                    root.Left = redNode;\n                }\n            }\n            else if (size == 3)\n            {\n                root = new Node(arr[startIndex + 1], false);\n                root.Left = new Node(arr[startIndex], false);\n                root.Right = new Node(arr[endIndex], false);\n                if (redNode != null)\n                {\n                    root.Left.Left = redNode;\n                }\n            }\n            else\n            {\n                int midpt = ((startIndex + endIndex) / 2);\n                root = new Node(arr[midpt], false);\n                root.Left = ConstructRootFromSortedArray(arr, startIndex, midpt - 1, redNode);\n                if (size % 2 == 0)\n                {\n                    root.Right = ConstructRootFromSortedArray(arr, midpt + 2, endIndex, new Node(arr[midpt + 1], true));\n                }\n                else\n                {\n                    root.Right = ConstructRootFromSortedArray(arr, midpt + 1, endIndex, null);\n                }\n            }\n            return root;\n        }\n\n\n        /// <summary>\n        /// Transform this set into its intersection with the IEnumerable OTHER     \n        /// NOTE: The caller object is important as IntersectionWith uses the        \n        /// comparator associated with THIS to check equality                        \n        /// Throws ArgumentNullException if OTHER is null                         \n        /// </summary>\n        /// <param name=\"other\"></param>   \n        public virtual void IntersectWith(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            if (Count == 0)\n                return;\n\n            //HashSet<T> optimizations can't be done until equality comparers and comparers are related\n\n            //Technically, this would work as well with an ISorted<T>\n            SortedSetExt<T> s = other as SortedSetExt<T>;\n            TreeSubSet t = this as TreeSubSet;\n            if (t != null)\n                VersionCheck();\n            //only let this happen if i am also a SortedSet, not a SubSet\n            if (s != null && t == null && AreComparersEqual(this, s))\n            {\n                //first do a merge sort to an array.\n                T[] merged = new T[this.Count];\n                int c = 0;\n                Enumerator mine = this.GetEnumerator();\n                Enumerator theirs = s.GetEnumerator();\n                bool mineEnded = !mine.MoveNext(), theirsEnded = !theirs.MoveNext();\n                T max = Max;\n                T min = Min;\n\n                while (!mineEnded && !theirsEnded && Comparer.Compare(theirs.Current, max) <= 0)\n                {\n                    int comp = Comparer.Compare(mine.Current, theirs.Current);\n                    if (comp < 0)\n                    {\n                        mineEnded = !mine.MoveNext();\n                    }\n                    else if (comp == 0)\n                    {\n                        merged[c++] = theirs.Current;\n                        mineEnded = !mine.MoveNext();\n                        theirsEnded = !theirs.MoveNext();\n                    }\n                    else\n                    {\n                        theirsEnded = !theirs.MoveNext();\n                    }\n                }\n\n                //now merged has all c elements\n\n                //safe to gc the root, we  have all the elements\n                _root = null;\n\n                _root = SortedSetExt<T>.ConstructRootFromSortedArray(merged, 0, c - 1, null);\n                _count = c;\n                _version++;\n            }\n            else\n            {\n                IntersectWithEnumerable(other);\n            }\n        }\n\n        internal virtual void IntersectWithEnumerable(IEnumerable<T> other)\n        {\n            //TODO: Perhaps a more space-conservative way to do this\n            List<T> toSave = new List<T>(this.Count);\n            foreach (T item in other)\n            {\n                if (this.Contains(item))\n                {\n                    toSave.Add(item);\n                    this.Remove(item);\n                }\n            }\n            this.Clear();\n            AddAllElements(toSave);\n        }\n\n\n\n        /// <summary>\n        ///  Transform this set into its complement with the IEnumerable OTHER       \n        ///  NOTE: The caller object is important as ExceptWith uses the        \n        ///  comparator associated with THIS to check equality                        \n        ///  Throws ArgumentNullException if OTHER is null                           \n        /// </summary>\n        /// <param name=\"other\"></param>\n        public void ExceptWith(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            if (_count == 0)\n                return;\n\n            if (other == this)\n            {\n                this.Clear();\n                return;\n            }\n\n            SortedSetExt<T> asSorted = other as SortedSetExt<T>;\n\n            if (asSorted != null && AreComparersEqual(this, asSorted))\n            {\n                //outside range, no point doing anything               \n                if (!(_comparer.Compare(asSorted.Max, this.Min) < 0 || _comparer.Compare(asSorted.Min, this.Max) > 0))\n                {\n                    T min = this.Min;\n                    T max = this.Max;\n                    foreach (T item in other)\n                    {\n                        if (_comparer.Compare(item, min) < 0)\n                            continue;\n                        if (_comparer.Compare(item, max) > 0)\n                            break;\n                        Remove(item);\n                    }\n                }\n            }\n            else\n            {\n                RemoveAllElements(other);\n            }\n        }\n\n        /// <summary>\n        ///  Transform this set so it contains elements in THIS or OTHER but not both\n        ///  NOTE: The caller object is important as SymmetricExceptWith uses the        \n        ///  comparator associated with THIS to check equality                        \n        ///  Throws ArgumentNullException if OTHER is null                           \n        /// </summary>\n        /// <param name=\"other\"></param>\n        public void SymmetricExceptWith(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            if (this.Count == 0)\n            {\n                this.UnionWith(other);\n                return;\n            }\n\n            if (other == this)\n            {\n                this.Clear();\n                return;\n            }\n\n\n            SortedSetExt<T> asSorted = other as SortedSetExt<T>;\n\n            if (asSorted != null && AreComparersEqual(this, asSorted))\n            {\n                SymmetricExceptWithSameEC(asSorted);\n            }\n            else\n            {\n                //need perf improvement on this\n                T[] elements = (new List<T>(other)).ToArray();\n                Array.Sort(elements, this.Comparer);\n                SymmetricExceptWithSameEC(elements);\n            }\n        }\n\n        //OTHER must be a set\n        internal void SymmetricExceptWithSameEC(ISet<T> other)\n        {\n            foreach (T item in other)\n            {\n                //yes, it is classier to say\n                //if (!this.Remove(item))this.Add(item);\n                //but this ends up saving on rotations                    \n                if (this.Contains(item))\n                {\n                    this.Remove(item);\n                }\n                else\n                {\n                    this.Add(item);\n                }\n            }\n        }\n\n        //OTHER must be a sorted array\n        internal void SymmetricExceptWithSameEC(T[] other)\n        {\n            if (other.Length == 0)\n            {\n                return;\n            }\n            T last = other[0];\n            for (int i = 0; i < other.Length; i++)\n            {\n                while (i < other.Length && i != 0 && _comparer.Compare(other[i], last) == 0)\n                    i++;\n                if (i >= other.Length)\n                    break;\n                if (this.Contains(other[i]))\n                {\n                    this.Remove(other[i]);\n                }\n                else\n                {\n                    this.Add(other[i]);\n                }\n                last = other[i];\n            }\n        }\n\n\n        /// <summary>\n        /// Checks whether this Tree is a subset of the IEnumerable other\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool IsSubsetOf(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            if (Count == 0)\n                return true;\n\n\n            SortedSetExt<T> asSorted = other as SortedSetExt<T>;\n            if (asSorted != null && AreComparersEqual(this, asSorted))\n            {\n                if (this.Count > asSorted.Count)\n                    return false;\n                return IsSubsetOfSortedSetWithSameEC(asSorted);\n            }\n            else\n            {\n                //worst case: mark every element in my set and see if i've counted all\n                //O(MlogN)\n\n                ElementCount result = CheckUniqueAndUnfoundElements(other, false);\n                return (result.uniqueCount == Count && result.unfoundCount >= 0);\n            }\n        }\n\n        private bool IsSubsetOfSortedSetWithSameEC(SortedSetExt<T> asSorted)\n        {\n            SortedSetExt<T> prunedOther = asSorted.GetViewBetween(this.Min, this.Max);\n            foreach (T item in this)\n            {\n                if (!prunedOther.Contains(item))\n                    return false;\n            }\n            return true;\n        }\n\n\n        /// <summary>\n        /// Checks whether this Tree is a proper subset of the IEnumerable other\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool IsProperSubsetOf(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            if ((other as ICollection) != null)\n            {\n                if (Count == 0)\n                    return (other as ICollection).Count > 0;\n            }\n\n\n            //another for sorted sets with the same comparer\n            SortedSetExt<T> asSorted = other as SortedSetExt<T>;\n            if (asSorted != null && AreComparersEqual(this, asSorted))\n            {\n                if (this.Count >= asSorted.Count)\n                    return false;\n                return IsSubsetOfSortedSetWithSameEC(asSorted);\n            }\n\n\n            //worst case: mark every element in my set and see if i've counted all\n            //O(MlogN).\n            ElementCount result = CheckUniqueAndUnfoundElements(other, false);\n            return (result.uniqueCount == Count && result.unfoundCount > 0);\n        }\n\n\n        /// <summary>\n        /// Checks whether this Tree is a super set of the IEnumerable other\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool IsSupersetOf(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            if ((other as ICollection) != null && (other as ICollection).Count == 0)\n                return true;\n\n            //do it one way for HashSets\n            //another for sorted sets with the same comparer\n            SortedSetExt<T> asSorted = other as SortedSetExt<T>;\n            if (asSorted != null && AreComparersEqual(this, asSorted))\n            {\n                if (this.Count < asSorted.Count)\n                    return false;\n                SortedSetExt<T> pruned = GetViewBetween(asSorted.Min, asSorted.Max);\n                foreach (T item in asSorted)\n                {\n                    if (!pruned.Contains(item))\n                        return false;\n                }\n                return true;\n            }\n            //and a third for everything else\n            return ContainsAllElements(other);\n        }\n\n        /// <summary>\n        /// Checks whether this Tree is a proper super set of the IEnumerable other\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool IsProperSupersetOf(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            if (Count == 0)\n                return false;\n\n            if ((other as ICollection) != null && (other as ICollection).Count == 0)\n                return true;\n\n            //another way for sorted sets\n            SortedSetExt<T> asSorted = other as SortedSetExt<T>;\n            if (asSorted != null && AreComparersEqual(asSorted, this))\n            {\n                if (asSorted.Count >= this.Count)\n                    return false;\n                SortedSetExt<T> pruned = GetViewBetween(asSorted.Min, asSorted.Max);\n                foreach (T item in asSorted)\n                {\n                    if (!pruned.Contains(item))\n                        return false;\n                }\n                return true;\n            }\n\n\n            //worst case: mark every element in my set and see if i've counted all\n            //O(MlogN)\n            //slight optimization, put it into a HashSet and then check can do it in O(N+M)\n            //but slower in better cases + wastes space\n            ElementCount result = CheckUniqueAndUnfoundElements(other, true);\n            return (result.uniqueCount < Count && result.unfoundCount == 0);\n        }\n\n\n\n        /// <summary>\n        /// Checks whether this Tree has all elements in common with IEnumerable other\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool SetEquals(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            SortedSetExt<T> asSorted = other as SortedSetExt<T>;\n            if (asSorted != null && AreComparersEqual(this, asSorted))\n            {\n                IEnumerator<T> mine = this.GetEnumerator();\n                IEnumerator<T> theirs = asSorted.GetEnumerator();\n                bool mineEnded = !mine.MoveNext();\n                bool theirsEnded = !theirs.MoveNext();\n                while (!mineEnded && !theirsEnded)\n                {\n                    if (Comparer.Compare(mine.Current, theirs.Current) != 0)\n                    {\n                        return false;\n                    }\n                    mineEnded = !mine.MoveNext();\n                    theirsEnded = !theirs.MoveNext();\n                }\n                return mineEnded && theirsEnded;\n            }\n\n            //worst case: mark every element in my set and see if i've counted all\n            //O(N) by size of other            \n            ElementCount result = CheckUniqueAndUnfoundElements(other, true);\n            return (result.uniqueCount == Count && result.unfoundCount == 0);\n        }\n\n\n\n        /// <summary>\n        /// Checks whether this Tree has any elements in common with IEnumerable other\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Overlaps(IEnumerable<T> other)\n        {\n            if (other == null)\n            {\n                throw new ArgumentNullException(\"other\");\n            }\n\n            if (this.Count == 0)\n                return false;\n\n            if ((other as ICollection<T> != null) && (other as ICollection<T>).Count == 0)\n                return false;\n\n            SortedSetExt<T> asSorted = other as SortedSetExt<T>;\n            if (asSorted != null && AreComparersEqual(this, asSorted) && (_comparer.Compare(Min, asSorted.Max) > 0 || _comparer.Compare(Max, asSorted.Min) < 0))\n            {\n                return false;\n            }\n            foreach (T item in other)\n            {\n                if (this.Contains(item))\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// This works similar to HashSet's CheckUniqueAndUnfound (description below), except that the bit\n        /// array maps differently than in the HashSet. We can only use this for the bulk boolean checks.\n        /// \n        /// Determines counts that can be used to determine equality, subset, and superset. This\n        /// is only used when other is an IEnumerable and not a HashSet. If other is a HashSet\n        /// these properties can be checked faster without use of marking because we can assume \n        /// other has no duplicates.\n        /// \n        /// The following count checks are performed by callers:\n        /// 1. Equals: checks if unfoundCount = 0 and uniqueFoundCount = Count; i.e. everything \n        /// in other is in this and everything in this is in other\n        /// 2. Subset: checks if unfoundCount >= 0 and uniqueFoundCount = Count; i.e. other may\n        /// have elements not in this and everything in this is in other\n        /// 3. Proper subset: checks if unfoundCount > 0 and uniqueFoundCount = Count; i.e\n        /// other must have at least one element not in this and everything in this is in other\n        /// 4. Proper superset: checks if unfound count = 0 and uniqueFoundCount strictly less\n        /// than Count; i.e. everything in other was in this and this had at least one element\n        /// not contained in other.\n        /// \n        /// An earlier implementation used delegates to perform these checks rather than returning\n        /// an ElementCount struct; however this was changed due to the perf overhead of delegates.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <param name=\"returnIfUnfound\">Allows us to finish faster for equals and proper superset\n        /// because unfoundCount must be 0.</param>\n        /// <returns></returns>\n        // <SecurityKernel Critical=\"True\" Ring=\"0\">\n        // <UsesUnsafeCode Name=\"Local bitArrayPtr of type: Int32*\" />\n        // <ReferencesCritical Name=\"Method: BitHelper..ctor(System.Int32*,System.Int32)\" Ring=\"1\" />\n        // <ReferencesCritical Name=\"Method: BitHelper.IsMarked(System.Int32):System.Boolean\" Ring=\"1\" />\n        // <ReferencesCritical Name=\"Method: BitHelper.MarkBit(System.Int32):System.Void\" Ring=\"1\" />\n        // </SecurityKernel>\n        private unsafe ElementCount CheckUniqueAndUnfoundElements(IEnumerable<T> other, bool returnIfUnfound)\n        {\n            ElementCount result;\n\n            // need special case in case this has no elements. \n            if (Count == 0)\n            {\n                int numElementsInOther = 0;\n                foreach (T item in other)\n                {\n                    numElementsInOther++;\n                    // break right away, all we want to know is whether other has 0 or 1 elements\n                    break;\n                }\n                result.uniqueCount = 0;\n                result.unfoundCount = numElementsInOther;\n                return result;\n            }\n\n\n            int originalLastIndex = Count;\n            int intArrayLength = BitHelperExt.ToIntArrayLength(originalLastIndex);\n\n            BitHelperExt bitHelper;\n            if (intArrayLength <= StackAllocThreshold)\n            {\n                int* bitArrayPtr = stackalloc int[intArrayLength];\n                bitHelper = new BitHelperExt(bitArrayPtr, intArrayLength);\n            }\n            else\n            {\n                int[] bitArray = new int[intArrayLength];\n                bitHelper = new BitHelperExt(bitArray, intArrayLength);\n            }\n\n            // count of items in other not found in this\n            int unfoundCount = 0;\n            // count of unique items in other found in this\n            int uniqueFoundCount = 0;\n\n            foreach (T item in other)\n            {\n                int index = InternalIndexOf(item);\n                if (index >= 0)\n                {\n                    if (!bitHelper.IsMarked(index))\n                    {\n                        // item hasn't been seen yet\n                        bitHelper.MarkBit(index);\n                        uniqueFoundCount++;\n                    }\n                }\n                else\n                {\n                    unfoundCount++;\n                    if (returnIfUnfound)\n                    {\n                        break;\n                    }\n                }\n            }\n\n            result.uniqueCount = uniqueFoundCount;\n            result.unfoundCount = unfoundCount;\n            return result;\n        }\n        public int RemoveWhere(Predicate<T> match)\n        {\n            if (match == null)\n            {\n                throw new ArgumentNullException(\"match\");\n            }\n            List<T> matches = new List<T>(this.Count);\n\n            BreadthFirstTreeWalk(delegate (Node n)\n            {\n                if (match(n.Item))\n                {\n                    matches.Add(n.Item);\n                }\n                return true;\n            });\n            // reverse breadth first to (try to) incur low cost\n            int actuallyRemoved = 0;\n            for (int i = matches.Count - 1; i >= 0; i--)\n            {\n                if (this.Remove(matches[i]))\n                {\n                    actuallyRemoved++;\n                }\n            }\n\n            return actuallyRemoved;\n        }\n\n\n        #endregion\n\n        #region ISorted Members\n\n\n        public T Min\n        {\n            get\n            {\n                T ret = default(T);\n                InOrderTreeWalk(delegate (SortedSetExt<T>.Node n) { ret = n.Item; return false; });\n                return ret;\n            }\n        }\n\n        public T Max\n        {\n            get\n            {\n                T ret = default(T);\n                InOrderTreeWalk(delegate (SortedSetExt<T>.Node n) { ret = n.Item; return false; }, true);\n                return ret;\n            }\n        }\n\n        public IEnumerable<T> Reverse()\n        {\n            Enumerator e = new Enumerator(this, true);\n            while (e.MoveNext())\n            {\n                yield return e.Current;\n            }\n        }\n\n\n        /// <summary>\n        /// Returns a subset of this tree ranging from values lBound to uBound\n        /// Any changes made to the subset reflect in the actual tree\n        /// </summary>\n        /// <param name=\"lowerValue\">Lowest Value allowed in the subset</param>\n        /// <param name=\"upperValue\">Highest Value allowed in the subset</param>        \n        public virtual SortedSetExt<T> GetViewBetween(T lowerValue, T upperValue)\n        {\n            if (Comparer.Compare(lowerValue, upperValue) > 0)\n            {\n                throw new ArgumentException(\"lowerBound is greater than upperBound\");\n            }\n            return new TreeSubSet(this, lowerValue, upperValue, true, true);\n        }\n\n        public bool TryFindGreater(T lowerValue, out T result)\n        {\n            var tup = FindNeighbours(lowerValue);\n            if (tup.Item3 != null)\n            {\n                result = tup.Item3.Item;\n                return true;\n            }\n            else\n            {\n                result = default(T);\n                return false;\n            }\n        }\n\n        public bool TryFindSmaller(T upperValue, out T result)\n        {\n            var tup = FindNeighbours(upperValue);\n            if (tup.Item1 != null)\n            {\n                result = tup.Item1.Item;\n                return true;\n            }\n            else\n            {\n                result = default(T);\n                return false;\n            }\n        }\n\n        public void FindNeighbours(T value, out Optional<T> lower, out Optional<T> self, out Optional<T> upper)\n        {\n            var tup = FindNeighbours(value);\n\n            if (tup.Item1 != null) lower = new Optional<T>(tup.Item1.Item);\n            else lower = Optional<T>.None;\n\n            if (tup.Item2 != null) self = new Optional<T>(tup.Item2.Item);\n            else self = Optional<T>.None;\n\n            if (tup.Item3 != null) upper = new Optional<T>(tup.Item3.Item);\n            else upper = Optional<T>.None;\n        }\n\n        /// <summary>\n        /// Find the neighbours of the given value\n        /// returns (hasLower, hasValue, hasUpper) and the corresponding values in the out p\n        /// </summary>\n        public (bool, bool, bool) FindNeighboursV(T value, out T lower, out T self, out T upper)\n        {\n            var (l, s, u) = FindNeighbours(value);\n\n            lower = l != null ? l.Item : default;\n            self = s != null ? s.Item : default;\n            upper = u != null ? u.Item : default;\n\n            return (l != null, s != null, u != null);\n        }\n\n\n        /// <summary>\n        /// Checks if the value is present in the set and returns the value (might be different to the value passed in when using custom IComparer)\n        /// </summary>\n        public bool FindValue(T value, out T result)\n        {\n            var val = FindNode(value);\n            result = val != null ? val.Item : default;\n            return val != null;\n        }\n\n\n#if DEBUG\n\n        /// <summary>\n        /// debug status to be checked whenever any operation is called\n        /// </summary>\n        /// <returns></returns>\n        internal virtual bool versionUpToDate()\n        {\n            return true;\n        }\n#endif\n\n\n        /// <summary>\n        /// This class represents a subset view into the tree. Any changes to this view\n        /// are reflected in the actual tree. Uses the Comparator of the underlying tree.\n        /// </summary>\n        internal sealed class TreeSubSet : SortedSetExt<T>\n        {\n            private readonly SortedSetExt<T> _underlying;\n            private readonly T _min, _max;\n            //these exist for unbounded collections\n            //for instance, you could allow this subset to be defined for i>10. The set will throw if\n            //anything <=10 is added, but there is no upperbound. These features Head(), Tail(), were punted\n            //in the spec, and are not available, but the framework is there to make them available at some point.\n            private readonly bool _lBoundActive, _uBoundActive;\n            //used to see if the count is out of date            \n\n\n#if DEBUG\n            internal override bool versionUpToDate()\n            {\n                return (_version == _underlying._version);\n            }\n#endif\n\n            public TreeSubSet(SortedSetExt<T> Underlying, T Min, T Max, bool lowerBoundActive, bool upperBoundActive)\n                : base(Underlying.Comparer)\n            {\n                _underlying = Underlying;\n                _min = Min;\n                _max = Max;\n                _lBoundActive = lowerBoundActive;\n                _uBoundActive = upperBoundActive;\n                _root = _underlying.FindRange(_min, _max, _lBoundActive, _uBoundActive); // root is first element within range                                \n                _count = 0;\n                _version = -1;\n                VersionCheckImpl();\n            }\n\n            /// <summary>\n            /// Additions to this tree need to be added to the underlying tree as well\n            /// </summary>           \n\n            internal override bool AddIfNotPresent(T item)\n            {\n                if (!IsWithinRange(item))\n                {\n                    throw new ArgumentOutOfRangeException(\"collection\");\n                }\n\n                bool ret = _underlying.AddIfNotPresent(item);\n                VersionCheck();\n#if DEBUG\n                Debug.Assert(this.versionUpToDate() && _root == _underlying.FindRange(_min, _max));\n#endif\n\n                return ret;\n            }\n\n\n            public override bool Contains(T item)\n            {\n                VersionCheck();\n#if DEBUG\n                Debug.Assert(this.versionUpToDate() && _root == _underlying.FindRange(_min, _max));\n#endif\n                return base.Contains(item);\n            }\n\n            internal override bool DoRemove(T item)\n            { // todo: uppercase this and others\n                if (!IsWithinRange(item))\n                {\n                    return false;\n                }\n\n                bool ret = _underlying.Remove(item);\n                VersionCheck();\n#if DEBUG\n                Debug.Assert(this.versionUpToDate() && _root == _underlying.FindRange(_min, _max));\n#endif\n                return ret;\n            }\n\n            public override void Clear()\n            {\n                if (_count == 0)\n                {\n                    return;\n                }\n\n                List<T> toRemove = new List<T>();\n                BreadthFirstTreeWalk(delegate (Node n) { toRemove.Add(n.Item); return true; });\n                while (toRemove.Count != 0)\n                {\n                    _underlying.Remove(toRemove[toRemove.Count - 1]);\n                    toRemove.RemoveAt(toRemove.Count - 1);\n                }\n                _root = null;\n                _count = 0;\n                _version = _underlying._version;\n            }\n\n\n            internal override bool IsWithinRange(T item)\n            {\n                int comp = (_lBoundActive ? Comparer.Compare(_min, item) : -1);\n                if (comp > 0)\n                {\n                    return false;\n                }\n                comp = (_uBoundActive ? Comparer.Compare(_max, item) : 1);\n                if (comp < 0)\n                {\n                    return false;\n                }\n                return true;\n            }\n\n            internal override bool InOrderTreeWalk(TreeWalkPredicate<T> action, Boolean reverse)\n            {\n                VersionCheck();\n\n                if (_root == null)\n                {\n                    return true;\n                }\n\n                // The maximum height of a red-black tree is 2*lg(n+1).\n                // See page 264 of \"Introduction to algorithms\" by Thomas H. Cormen\n                Stack<Node> stack = new Stack<Node>(2 * (int)SortedSetExt<T>.log2(_count + 1)); //this is not exactly right if count is out of date, but the stack can grow\n                Node current = _root;\n                while (current != null)\n                {\n                    if (IsWithinRange(current.Item))\n                    {\n                        stack.Push(current);\n                        current = (reverse ? current.Right : current.Left);\n                    }\n                    else if (_lBoundActive && Comparer.Compare(_min, current.Item) > 0)\n                    {\n                        current = current.Right;\n                    }\n                    else\n                    {\n                        current = current.Left;\n                    }\n                }\n\n                while (stack.Count != 0)\n                {\n                    current = stack.Pop();\n                    if (!action(current))\n                    {\n                        return false;\n                    }\n\n                    Node node = (reverse ? current.Left : current.Right);\n                    while (node != null)\n                    {\n                        if (IsWithinRange(node.Item))\n                        {\n                            stack.Push(node);\n                            node = (reverse ? node.Right : node.Left);\n                        }\n                        else if (_lBoundActive && Comparer.Compare(_min, node.Item) > 0)\n                        {\n                            node = node.Right;\n                        }\n                        else\n                        {\n                            node = node.Left;\n                        }\n                    }\n                }\n                return true;\n            }\n\n            internal override bool BreadthFirstTreeWalk(TreeWalkPredicate<T> action)\n            {\n                VersionCheck();\n\n                if (_root == null)\n                {\n                    return true;\n                }\n\n                Queue<Node> processQueue = new Queue<Node>();\n                processQueue.Enqueue(_root);\n                Node current;\n\n                while (processQueue.Count != 0)\n                {\n                    current = processQueue.Dequeue();\n                    if (IsWithinRange(current.Item) && !action(current))\n                    {\n                        return false;\n                    }\n                    if (current.Left != null && (!_lBoundActive || Comparer.Compare(_min, current.Item) < 0))\n                    {\n                        processQueue.Enqueue(current.Left);\n                    }\n                    if (current.Right != null && (!_uBoundActive || Comparer.Compare(_max, current.Item) > 0))\n                    {\n                        processQueue.Enqueue(current.Right);\n                    }\n                }\n                return true;\n            }\n\n            internal override SortedSetExt<T>.Node FindNode(T item)\n            {\n                if (!IsWithinRange(item))\n                {\n                    return null;\n                }\n                VersionCheck();\n#if DEBUG\n                Debug.Assert(this.versionUpToDate() && _root == _underlying.FindRange(_min, _max));\n#endif\n                return base.FindNode(item);\n            }\n\n            //this does indexing in an inefficient way compared to the actual sortedset, but it saves a\n            //lot of space\n            internal override int InternalIndexOf(T item)\n            {\n                int count = -1;\n                foreach (T i in this)\n                {\n                    count++;\n                    if (Comparer.Compare(item, i) == 0)\n                        return count;\n                }\n#if DEBUG\n                Debug.Assert(this.versionUpToDate() && _root == _underlying.FindRange(_min, _max));\n#endif\n                return -1;\n            }\n            /// <summary>\n            /// checks whether this subset is out of date. updates if necessary.\n            /// </summary>\n            internal override void VersionCheck()\n            {\n                VersionCheckImpl();\n            }\n\n            private void VersionCheckImpl()\n            {\n                Debug.Assert(_underlying != null, \"Underlying set no longer exists\");\n                if (_version != _underlying._version)\n                {\n                    _root = _underlying.FindRange(_min, _max, _lBoundActive, _uBoundActive);\n                    _version = _underlying._version;\n                    _count = 0;\n                    InOrderTreeWalk(delegate (Node n) { _count++; return true; });\n                }\n            }\n\n\n\n            //This passes functionality down to the underlying tree, clipping edges if necessary\n            //There's nothing gained by having a nested subset. May as well draw it from the base\n            //Cannot increase the bounds of the subset, can only decrease it\n            public override SortedSetExt<T> GetViewBetween(T lowerValue, T upperValue)\n            {\n                if (_lBoundActive && Comparer.Compare(_min, lowerValue) > 0)\n                {\n                    //lBound = min;\n                    throw new ArgumentOutOfRangeException(\"lowerValue\");\n                }\n                if (_uBoundActive && Comparer.Compare(_max, upperValue) < 0)\n                {\n                    //uBound = max;\n                    throw new ArgumentOutOfRangeException(\"upperValue\");\n                }\n                TreeSubSet ret = (TreeSubSet)_underlying.GetViewBetween(lowerValue, upperValue);\n                return ret;\n            }\n\n            internal override void IntersectWithEnumerable(IEnumerable<T> other)\n            {\n                List<T> toSave = new List<T>(this.Count);\n                foreach (T item in other)\n                {\n                    if (this.Contains(item))\n                    {\n                        toSave.Add(item);\n                        this.Remove(item);\n                    }\n                }\n                this.Clear();\n                this.AddAllElements(toSave);\n#if DEBUG\n                Debug.Assert(this.versionUpToDate() && _root == _underlying.FindRange(_min, _max));\n#endif\n            }\n        }\n\n        #endregion\n\n        #region Helper Classes\n        internal sealed class Node\n        {\n            public bool IsRed;\n            public T Item;\n            public Node Left;\n            public Node Right;\n\n            public Node(T item)\n            {\n                // The default color will be red, we never need to create a black node directly.                \n                this.Item = item;\n                IsRed = true;\n            }\n\n            public Node(T item, bool isRed)\n            {\n                // The default color will be red, we never need to create a black node directly.                \n                this.Item = item;\n                this.IsRed = isRed;\n            }\n        }\n\n        [SuppressMessage(\"Microsoft.Performance\", \"CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes\", Justification = \"not an expected scenario\")]\n        public struct Enumerator : IEnumerator<T>, IEnumerator\n        {\n            private readonly SortedSetExt<T> _tree;\n            private readonly int _version;\n\n\n            private readonly Stack<SortedSetExt<T>.Node> _stack;\n            private SortedSetExt<T>.Node _current;\n            //private static SortedSetExt<T>.Node s_dummyNode = new SortedSetExt<T>.Node(default(T));\n\n            private readonly bool _reverse;\n\n            internal Enumerator(SortedSetExt<T> set)\n            {\n                _tree = set;\n                //this is a hack to make sure that the underlying subset has not been changed since\n                //TODO: more elegant way to ensure failfast on concurrency failures\n                _tree.VersionCheck();\n\n                _version = _tree._version;\n\n                // 2lg(n + 1) is the maximum height\n                _stack = new Stack<SortedSetExt<T>.Node>(2 * (int)SortedSetExt<T>.log2(set.Count + 1));\n                _current = null;\n                _reverse = false;\n                Intialize();\n            }\n\n            internal Enumerator(SortedSetExt<T> set, bool reverse)\n            {\n                _tree = set;\n                //this is a hack to make sure that the underlying subset has not been changed since\n                //TODO: more elegant way to ensure failfast on concurrency failures\n                _tree.VersionCheck();\n                _version = _tree._version;\n\n                // 2lg(n + 1) is the maximum height\n                _stack = new Stack<SortedSetExt<T>.Node>(2 * (int)SortedSetExt<T>.log2(set.Count + 1));\n                _current = null;\n                _reverse = reverse;\n                Intialize();\n            }\n\n            private void Intialize()\n            {\n                _current = null;\n                SortedSetExt<T>.Node node = _tree._root;\n                Node next = null, other = null;\n                while (node != null)\n                {\n                    next = (_reverse ? node.Right : node.Left);\n                    other = (_reverse ? node.Left : node.Right);\n                    if (_tree.IsWithinRange(node.Item))\n                    {\n                        _stack.Push(node);\n                        node = next;\n                    }\n                    else if (next == null || !_tree.IsWithinRange(next.Item))\n                    {\n                        node = other;\n                    }\n                    else\n                    {\n                        node = next;\n                    }\n                }\n            }\n\n            public bool MoveNext()\n            {\n                //this is a hack to make sure that the underlying subset has not been changed since\n                //TODO: more elegant way to ensure failfast on concurrency failures\n                _tree.VersionCheck();\n\n                if (_version != _tree._version)\n                {\n                    throw new InvalidOperationException(\"SR.InvalidOperation_EnumFailedVersion\");\n                }\n\n                if (_stack.Count == 0)\n                {\n                    _current = null;\n                    return false;\n                }\n\n                _current = _stack.Pop();\n                SortedSetExt<T>.Node node = (_reverse ? _current.Left : _current.Right);\n                Node next = null, other = null;\n                while (node != null)\n                {\n                    next = (_reverse ? node.Right : node.Left);\n                    other = (_reverse ? node.Left : node.Right);\n                    if (_tree.IsWithinRange(node.Item))\n                    {\n                        _stack.Push(node);\n                        node = next;\n                    }\n                    else if (other == null || !_tree.IsWithinRange(other.Item))\n                    {\n                        node = next;\n                    }\n                    else\n                    {\n                        node = other;\n                    }\n                }\n                return true;\n            }\n\n            public readonly void Dispose()\n            {\n            }\n\n            public readonly T Current\n            {\n                get\n                {\n                    if (_current != null)\n                    {\n                        return _current.Item;\n                    }\n                    return default(T);\n                }\n            }\n\n            readonly object IEnumerator.Current\n            {\n                get\n                {\n                    if (_current == null)\n                    {\n                        throw new InvalidOperationException(\"SR.InvalidOperation_EnumOpCantHappen\");\n                    }\n\n                    return _current.Item;\n                }\n            }\n\n            internal readonly bool NotStartedOrEnded\n            {\n                get\n                {\n                    return _current == null;\n                }\n            }\n\n            internal void Reset()\n            {\n                if (_version != _tree._version)\n                {\n                    throw new InvalidOperationException(\"SR.InvalidOperation_EnumFailedVersion\");\n                }\n\n                _stack.Clear();\n                Intialize();\n            }\n\n            void IEnumerator.Reset()\n            {\n                Reset();\n            }\n        }\n\n\n\n        internal struct ElementCount\n        {\n            internal int uniqueCount;\n            internal int unfoundCount;\n        }\n        #endregion\n\n        #region misc\n        // used for set checking operations (using enumerables) that rely on counting\n        private static int log2(int value)\n        {\n            //Contract.Requires(value>0)\n            int c = 0;\n            while (value > 0)\n            {\n                c++;\n                value >>= 1;\n            }\n            return c;\n        }\n        #endregion\n\n\n    }\n\n    /// <summary>\n    /// A class that generates an IEqualityComparer for this SortedSet. Requires that the definition of\n    /// equality defined by the IComparer for this SortedSet be consistent with the default IEqualityComparer\n    /// for the type T. If not, such an IEqualityComparer should be provided through the constructor.\n    /// </summary>    \n    internal sealed class SortedSetEqualityComparer<T> : IEqualityComparer<SortedSetExt<T>>\n    {\n        private readonly IComparer<T> _comparer;\n        private readonly IEqualityComparer<T> _eqComparer;\n\n        public SortedSetEqualityComparer() : this(null, null) { }\n\n        public SortedSetEqualityComparer(IComparer<T> comparer) : this(comparer, null) { }\n\n        public SortedSetEqualityComparer(IEqualityComparer<T> memberEqualityComparer) : this(null, memberEqualityComparer) { }\n\n        /// <summary>\n        /// Create a new SetEqualityComparer, given a comparer for member order and another for member equality (these\n        /// must be consistent in their definition of equality)\n        /// </summary>        \n        public SortedSetEqualityComparer(IComparer<T> comparer, IEqualityComparer<T> memberEqualityComparer)\n        {\n            if (comparer == null)\n                _comparer = Comparer<T>.Default;\n            else\n                _comparer = comparer;\n            if (memberEqualityComparer == null)\n                _eqComparer = EqualityComparer<T>.Default;\n            else\n                _eqComparer = memberEqualityComparer;\n        }\n\n\n        // using comparer to keep equals properties in tact; don't want to choose one of the comparers\n        public bool Equals(SortedSetExt<T> x, SortedSetExt<T> y)\n        {\n            return SortedSetExt<T>.SortedSetEquals(x, y, _comparer);\n        }\n        //IMPORTANT: this part uses the fact that GetHashCode() is consistent with the notion of equality in\n        //the set\n        public int GetHashCode(SortedSetExt<T> obj)\n        {\n            int hashCode = 0;\n            if (obj != null)\n            {\n                foreach (T t in obj)\n                {\n                    hashCode = hashCode ^ (_eqComparer.GetHashCode(t) & 0x7FFFFFFF);\n                }\n            } // else returns hashcode of 0 for null HashSets\n            return hashCode;\n        }\n\n        // Equals method for the comparer itself. \n        public override bool Equals(Object obj)\n        {\n            SortedSetEqualityComparer<T> comparer = obj as SortedSetEqualityComparer<T>;\n            if (comparer == null)\n            {\n                return false;\n            }\n            return (_comparer == comparer._comparer);\n        }\n\n        public override int GetHashCode()\n        {\n            return _comparer.GetHashCode() ^ _eqComparer.GetHashCode();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/INode.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.VRVis\n{\n    /// <summary>\n    /// A simple hierarchical node interface without any\n    /// notion of a traversal state.\n    /// </summary>\n    public interface INode\n    {\n        IEnumerable<INode> SubNodes { get; }\n    }\n\n    /// <summary>\n    /// Immediately supply some basic traversal functionality.\n    /// </summary>\n    public static class INodeExtensions\n    {\n        public static int ComputeDepth(this INode self)\n        {\n            var subNodes = self.SubNodes;\n            if (subNodes.Count() == 0) return 0;\n            return 1 + subNodes.Max(x => x.ComputeDepth());\n        }\n\n        public static IEnumerable<T> NodesAtDepth<T>(this INode self, int depth)\n            where T : class\n        {\n            return from node in self.NodesAtDepth(depth)\n                   where node is T\n                   select node as T;\n        }\n\n        /// <summary>\n        /// Returns all nodes of a graph that are at the same depth as a flat\n        /// sequence.\n        /// </summary>\n        public static IEnumerable<INode> NodesAtDepth(this INode self, int depth)\n        {\n            if (depth < 0) return Enumerable.Empty<INode>();\n            if (depth == 0) return self.IntoIEnumerable();\n            var subNodes = self.SubNodes;\n            if (depth == 1) return subNodes;\n            return from sn in subNodes\n                   from n in sn.NodesAtDepth(depth - 1)\n                   select n;\n        }\n\n        /// <summary>\n        /// Enumerates all nodes of this scene graph in depth first order.\n        /// </summary>\n        public static IEnumerable<INode> DepthFirst(this INode self)\n        {\n            if (self == null) return Array.Empty<INode>();\n            return self.DepthFirst(n => n.SubNodes);\n        }\n\n        /// <summary>\n        /// Enumerates all nodes of type T of this scene graph in depth\n        /// first order.\n        /// </summary>\n        public static IEnumerable<T> DepthFirst<T>(this INode self)\n            where T : class\n        {\n            if (self == null) return Enumerable.Empty<T>();\n            return from node in self.DepthFirst()\n                   where node is T\n                   select node as T;\n        }\n\n        /// <summary>\n        /// Enumerates all nodes of this scene graph in breadth first order.\n        /// </summary>\n        public static IEnumerable<INode> BreadthFirst(this INode self)\n        {\n            if (self == null) return Enumerable.Empty<INode>();\n            return self.BreadthFirst(n => n.SubNodes);\n        }\n\n        /// <summary>\n        /// Enumerates all nodes of type T of this scene graph in breadth\n        /// first order.\n        /// </summary>\n        public static IEnumerable<T> BreadthFirst<T>(this INode self)\n            where T : class\n        {\n            if (self == null) return Enumerable.Empty<T>();\n            return from node in self.BreadthFirst()\n                   where node is T\n                   select node as T;\n        }\n\n        /// <summary>\n        /// Enumerates descendent nodes including the node itself (uses Depth-First traversal order)\n        /// </summary>\n        public static IEnumerable<T> DescendentsAndSelf<T>(this T node)\n            where T : class, INode\n        {\n            return node.DepthFirst<T>();\n        }\n\n        /// <summary>\n        /// Enumerates all descendent nodes (uses Depth-First traversal order and skips first)\n        /// </summary>\n        public static IEnumerable<T> Descendents<T>(this T node)\n            where T : class, INode\n        {\n            return node.DepthFirst<T>().Skip(1);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/LruCache.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// A least-recently-used cache, with specifyable capacity and per-item size-, read-, and delete\n    /// function. The indexer is used to access items. Capacity can be changed on the fly. All\n    /// operations are synchronized for use in multi-threaded applications.\n    /// </summary>\n    public class LruCache<TKey, TValue>\n    {\n        private class Entry\n        {\n            public long Time;\n            public long Size;\n            public int Index;\n            public TKey Key;\n            public TValue Value;\n            public Action DeleteAct;\n        }\n\n        private readonly object m_lock;\n        private readonly Dict<TKey, Entry> m_cache;\n        private readonly List<Entry> m_heap;\n        private readonly Func<TKey, long> m_sizeFun;\n        private readonly Func<TKey,TValue> m_readFun;\n        private readonly Action<TKey,TValue> m_deleteAct;\n        private long m_capacity;\n        private long m_time;\n        private long m_size;\n\n        /// <summary>\n        /// Creates an LruCache with the specified capacity, per-item (Key) size function,\n        /// per-item (Key) read function, and per-item (key/value) delete action.\n        /// The indexer is used to access items. Capacity can be changed on the fly. All\n        /// operations are synchronized for use in multi-threaded applications.\n        /// </summary>\n        public LruCache(\n            long capacity,\n            Func<TKey, long> sizeFun,\n            Func<TKey,TValue> readFun,\n            Action<TKey, TValue> deleteAct = null\n        )\n        {\n            m_lock = new object();\n            m_cache = new Dict<TKey, Entry>();\n            m_heap = new List<Entry>();\n            m_sizeFun = sizeFun;\n            m_readFun = readFun;\n            m_deleteAct = deleteAct;\n            m_capacity = capacity;\n            m_time = 0;\n            m_size = 0;\n        }\n\n        public LruCache(\n            long capacity\n        )\n        {\n            m_lock = new object();\n            m_cache = new Dict<TKey, Entry>();\n            m_heap = new List<Entry>();\n            m_sizeFun = null;\n            m_readFun = null;\n            m_deleteAct = null;\n            m_capacity = capacity;\n            m_time = 0;\n            m_size = 0;\n        }\n        \n        public long Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                lock (m_lock)\n                {\n                    m_capacity = value;\n                    Shrink(m_size);\n                }\n            }\n        }\n\n        private void Shrink(long size)\n        {\n            while (size > m_capacity)\n            {\n                var removeKey = Dequeue(m_heap).Key;\n                if (m_cache.TryRemove(removeKey, out Entry entry))\n                {\n                    m_deleteAct?.Invoke(removeKey, entry.Value);\n                    entry.DeleteAct?.Invoke();\n                    size -= entry.Size;\n                }\n                else\n                    throw new InvalidOperationException(\"tried to remove an item that is not in the cache\");  \n                    // this should never ever happen!\n            }\n            m_size = size;\n        }\n\n        /// <summary>\n        /// Accessing items in the cache. If an item is not encountred in the cache,\n        /// it is read using the read function that was specified on cache creation.\n        /// </summary>\n        public TValue this [TKey key]\n        {\n            get\n            {\n                Entry entry;\n                lock (m_lock)\n                {\n                    if (m_cache.TryGetValue(key, out entry))\n                    {\n                        entry.Time = ++m_time;\n                        Sink(m_heap, entry.Index);\n                    }\n                    else\n                    {\n                        var size = m_sizeFun(key);\n                        Shrink(m_size + size);\n                        entry = new Entry\n                        {\n                            Time = ++m_time, Size = size, Key = key, Value = m_readFun(key)\n                        };\n                        m_cache[key] = entry;\n                        Enqueue(m_heap, entry);\n                    }\n                }\n                return entry.Value;\n            }\n        }\n\n        public TValue GetOrAdd(TKey key, long size, Func<TValue> valueFun, Action deleteAct = null)\n        {\n            lock (m_lock)\n            {\n                if (m_cache.TryGetValue(key, out Entry entry))\n                {\n                    entry.Time = ++m_time;\n                    Sink(m_heap, entry.Index);\n                }\n                else\n                {\n                    Shrink(m_size + size);\n                    entry = new Entry\n                    {\n                        Time = ++m_time,\n                        Size = size,\n                        Key = key,\n                        Value = valueFun(),\n                        DeleteAct = deleteAct,\n                    };\n                    m_cache[key] = entry;\n                    Enqueue(m_heap, entry);\n                }\n                return entry.Value;\n            }\n        }\n\n        /// <summary>\n        /// Remove the entry with the supplied key from the hash.\n        /// Returns true on success and puts the value of the\n        /// entry into the out parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            lock (m_lock)\n            {\n                if (m_cache.TryRemove(key, out Entry entry))\n                {\n                    m_size -= entry.Size;\n                    RemoveAt(m_heap, entry.Index);\n                    if (m_deleteAct != null)\n                        m_deleteAct(key, entry.Value);\n                    value = entry.Value;\n                    return true;\n                }\n                value = default;\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Remove the entry with the supplied key from the hash.\n        /// Returns true on success.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            lock (m_lock)\n            {\n                if (m_cache.TryRemove(key, out Entry entry))\n                {\n                    m_size -= entry.Size;\n                    RemoveAt(m_heap, entry.Index);\n                    m_deleteAct?.Invoke(key, entry.Value);\n                    entry.DeleteAct?.Invoke();\n                    return true;\n                }\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Reomves an arbitrary element from the heap, and maintains the heap\n        /// conditions.\n        /// </summary>\n        private static void RemoveAt(List<Entry> heap, int index)\n        {\n            var count = heap.Count;\n            if (count == 1) { heap.Clear(); return; }\n            var element = heap[--count];\n            heap.RemoveAt(count);\n            if (index == count) return;\n\n            int i = index;\n            while (i > 0)\n            {\n                int i2 = (i - 1) / 2;\n                if (element.Time > heap[i2].Time) break;\n                heap[i] = heap[i2];\n                heap[i].Index = i;\n                i = i2;\n            }\n            if (i == index)\n            {\n                int i1 = 2 * i + 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                        && heap[i1].Time > heap[i2].Time)\n                        ? i2 : i1; // smaller child\n                    if (heap[ni].Time > element.Time) break;\n                    heap[i] = heap[ni];\n                    heap[i].Index = i;\n                    i = ni; i1 = 2 * i + 1;\n                }\n            }\n            heap[i] = element;\n            heap[i].Index = i;\n        }\n\n        private static void Enqueue(List<Entry> heap, Entry entry)\n        {\n            int i = heap.Count;\n            heap.Add(entry);\n            entry.Index = i;\n            while (i > 0)\n            {\n                int i2 = (i - 1) / 2;\n                if (entry.Time > heap[i2].Time) break;\n                heap[i] = heap[i2];\n                heap[i].Index = i;\n                i = i2;\n            }\n            heap[i] = entry;\n            heap[i].Index = i;\n        }\n\n        /// <summary>\n        /// Removes and returns the item at the top of the heap (i.e. the\n        /// 0th position of the list).\n        /// </summary>\n        private static Entry Dequeue(List<Entry> heap)\n        {\n            var result = heap[0];\n            var count = heap.Count;\n            if (count == 1) { heap.Clear(); return result; }\n            var entry = heap[--count];\n            heap.RemoveAt(count);\n            int i = 0, i1 = 1;\n            while (i1 < count) // at least one child\n            {\n                int i2 = i1 + 1;\n                int ni = (i2 < count // two children?\n                    && heap[i1].Time > heap[i2].Time)\n                    ? i2 : i1; // smaller child\n                if (heap[ni].Time > entry.Time) break;\n                heap[i] = heap[ni];\n                heap[i].Index = i; // track index\n                i = ni; i1 = 2 * i + 1;\n            }\n            heap[i] = entry;\n            heap[i].Index = i; // track index\n            return result;\n        }\n\n        /// <summary>\n        /// Sinks an item.\n        /// </summary>\n        private static void Sink(List<Entry> heap, int i)\n        {\n            var count = heap.Count;\n            var entry = heap[i];\n            int i1 = 2 * i + 1;\n            while (i1 < count) // at least one child\n            {\n                int i2 = i1 + 1;\n                int ni = (i2 < count // two children?\n                    && heap[i1].Time > heap[i2].Time)\n                    ? i2 : i1; // smaller child\n                if (heap[ni].Time > entry.Time) break;\n                heap[i] = heap[ni];\n                heap[i].Index = i; // track index\n                i = ni; i1 = 2 * i + 1;\n            }\n            heap[i] = entry;\n            heap[i].Index = i; // track index\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/Meta.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class Meta\n    {\n        #region MetaTypes\n\n        public class SimpleType\n        {\n            public string Name { get; set; }\n            public string Char { get; set; }\n            public string Read { get; set; }\n            public string Caps { get; set; }\n            public bool IsInteger { get; set; }\n            public bool IsReal { get; set; }\n            public bool IsCharOrString { get; set; }\n\n            private string m_fsharpName;\n            public string FSharpName { get => m_fsharpName ?? Name; set => m_fsharpName = value; }\n\n\n            public SimpleType()\n            { }\n\n            public SimpleType(string name)\n            {\n                Name = name;\n                Char = null;\n                Read = null;\n            }\n        }\n\n        public class TensorType : SimpleType\n        {\n            public SimpleType FieldType { get; set; }\n\n            public TensorType(string name)\n                : base(name)\n            {\n                Read = \"Read\" + name;\n            }\n        }\n\n        public class GenericTensorType : SimpleType\n        {\n            public SimpleType DataType { get; set; }\n            public SimpleType ViewType { get; set; }\n            public SimpleType IndexType { get; set; }\n            public SimpleType IntIndexType { get; set; }\n            public int Dim { get; set; }\n\n            public GenericTensorType(string name)\n                : base(name)\n            { }\n        }\n\n        public class VecType : TensorType\n        {\n            public int Len { get; set; }\n            public string[] Fields { get; set; }\n\n            public VecType(string name)\n                : base(name)\n            { }\n        }\n\n        public struct MatDims\n        {\n            public int Rows;\n            public int Cols;\n            public MatDims(int rows, int cols) { Rows = rows; Cols = cols; }\n        }\n\n        public class MatType : TensorType\n        {\n            public int Rows { get; set; }\n            public int Cols { get; set; }\n\n            public MatDims Dims { get { return new MatDims(Rows, Cols); } }\n\n            public MatType(string name)\n                : base(name)\n            { }\n        }\n\n        public class TrafoType : SimpleType\n        {\n            public SimpleType MatType { get; set; }\n\n            public TrafoType(string name)\n                : base(name)\n            {\n                Read = \"Read\" + name;\n            }\n        }\n\n        public class RangeType : SimpleType\n        {\n            public SimpleType LimitType { get; set; }\n\n            public RangeType(string name)\n                : base(name)\n            {\n                Read = \"Read\" + name;\n            }\n        }\n\n        public class ColorType : TensorType\n        {\n            public int Len { get; set; }\n            public string[] Channels { get; set; }\n            public string[] Fields { get; set; }\n            public bool HasAlpha { get; set; }\n            public string MinValue { get; set; }\n            public string MaxValue { get; set; }\n\n            public ColorType(string name)\n                : base(name)\n            { }\n        }\n\n        #endregion\n\n        public static readonly SimpleType BoolType = new SimpleType()\n        {\n            Name = \"bool\",\n            Caps = \"Bool\",\n            Read = \"ReadBoolean\",\n        };\n\n        public static readonly SimpleType ByteType = new SimpleType()\n        {\n            Name = \"byte\",\n            Caps = \"Byte\",\n            Char = \"b\",\n            Read = \"ReadByte\",\n            FSharpName = \"uint8\",\n            IsInteger = true,\n        };\n\n        public static readonly SimpleType SByteType = new SimpleType()\n        {\n            Name = \"sbyte\",\n            Caps = \"SByte\",\n            Char = \"sb\",\n            Read = \"ReadSByte\",\n            FSharpName = \"int8\",\n            IsInteger = true,\n        };\n\n        public static readonly SimpleType ShortType = new SimpleType()\n        {\n            Name = \"short\",\n            Caps = \"Short\",\n            Char = \"s\",\n            Read = \"ReadInt16\",\n            FSharpName = \"int16\",\n            IsInteger = true,\n        };\n\n        public static readonly SimpleType UShortType = new SimpleType()\n        {\n            Name = \"ushort\",\n            Caps = \"UShort\",\n            Char = \"us\",\n            Read = \"ReadUInt16\",\n            FSharpName = \"uint16\",\n            IsInteger = true,\n        };\n\n        public static readonly SimpleType IntType = new SimpleType()\n        {\n            Name = \"int\",\n            Caps = \"Int\",\n            Char = \"i\",\n            Read = \"ReadInt32\",\n            FSharpName = \"int32\",\n            IsInteger = true,\n        };\n\n        public static readonly SimpleType UIntType = new SimpleType()\n        {\n            Name = \"uint\",\n            Caps = \"UInt\",\n            Char = \"ui\",\n            Read = \"ReadUInt32\",\n            FSharpName = \"uint32\",\n            IsInteger = true,\n        };\n\n        public static readonly SimpleType LongType = new SimpleType()\n        {\n            Name = \"long\",\n            Caps = \"Long\",\n            Char = \"l\",\n            Read = \"ReadInt64\",\n            FSharpName = \"int64\",\n            IsInteger = true,\n        };\n\n        public static readonly SimpleType ULongType = new SimpleType()\n        {\n            Name = \"ulong\",\n            Caps = \"ULong\",\n            Char = \"ul\",\n            Read = \"ReadUInt64\",\n            FSharpName = \"uint64\",\n            IsInteger = true,\n        };\n\n        public static readonly SimpleType HalfType = new SimpleType()\n        {\n            Name = \"Half\",\n            Caps = \"Half\",\n            Char = \"h\",\n            Read = \"ReadHalf\",\n            FSharpName = \"float16\",\n            IsReal = true,\n        };\n\n        public static readonly SimpleType FloatType = new SimpleType()\n        {\n            Name = \"float\",\n            Caps = \"Float\",\n            Char = \"f\",\n            Read = \"ReadSingle\",\n            FSharpName = \"float32\",\n            IsReal = true,\n        };\n\n        public static readonly SimpleType DoubleType = new SimpleType()\n        {\n            Name = \"double\",\n            Caps = \"Double\",\n            Char = \"d\",\n            Read = \"ReadDouble\",\n            FSharpName = \"float\",\n            IsReal = true,\n        };\n\n        public static readonly SimpleType DecimalType = new SimpleType()\n        {\n            Name = \"decimal\",\n            Caps = \"Decimal\",\n            Read = \"ReadDecimal\",\n        };\n\n        public static readonly SimpleType CharType = new SimpleType()\n        {\n            Name = \"Char\",\n            Read = \"ReadChar\",\n            FSharpName = \"char\",\n            IsCharOrString = true,\n        };\n\n        public static readonly SimpleType StringType = new SimpleType()\n        {\n            Name = \"String\",\n            Read = \"ReadString\",\n            FSharpName = \"string\",\n            IsCharOrString = true,\n        };\n\n        public static readonly SimpleType TypeType = new SimpleType()\n        {\n            Name = \"Type\",\n            Read = \"ReadType\",\n        };\n\n        public static readonly SimpleType GuidType = new SimpleType()\n        {\n            Name = \"Guid\",\n            Read = \"ReadGuid\",\n        };\n\n        public static readonly SimpleType FractionType = new SimpleType()\n        {\n            Name = \"Fraction\",\n            Read = \"ReadFraction\",\n        };\n\n        public static readonly SimpleType DateTimeType = new SimpleType()\n        {\n            Name = \"DateTime\",\n        };\n\n        public static readonly SimpleType TimeSpanType = new SimpleType()\n        {\n            Name = \"TimeSpan\",\n        };\n\n        public static readonly SimpleType[] TextTypes = new[]\n        {\n            CharType, StringType,\n        };\n\n        public static readonly SimpleType[] SystemTypes = new[]\n        {\n            CharType, StringType, TypeType, GuidType,\n        };\n\n        public static readonly SimpleType[] TimeTypes = new[]\n        {\n            DateTimeType, TimeSpanType,\n        };\n\n        public static readonly SimpleType Euclidean3fType = new SimpleType()\n        {\n            Name = \"Euclidean3f\",\n            Read = \"ReadEuclidean3f\",\n        };\n\n        public static readonly SimpleType Euclidean3dType = new SimpleType()\n        {\n            Name = \"Euclidean3d\",\n            Read = \"ReadEuclidean3d\",\n        };\n\n        public static readonly SimpleType Rot2fType = new SimpleType()\n        {\n            Name = \"Rot2f\",\n            Read = \"ReadRot2f\",\n        };\n\n        public static readonly SimpleType Rot2dType = new SimpleType()\n        {\n            Name = \"Rot2d\",\n            Read = \"ReadRot2d\",\n        };\n\n        public static readonly SimpleType Rot3fType = new SimpleType()\n        {\n            Name = \"Rot3f\",\n            Read = \"ReadRot3f\",\n        };\n\n        public static readonly SimpleType Rot3dType = new SimpleType()\n        {\n            Name = \"Rot3d\",\n            Read = \"ReadRot3d\",\n        };\n\n        public static readonly SimpleType Scale3fType = new SimpleType()\n        {\n            Name = \"Scale3f\",\n            Read = \"ReadScale3f\",\n        };\n\n        public static readonly SimpleType Scale3dType = new SimpleType()\n        {\n            Name = \"Scale3d\",\n            Read = \"ReadScale3d\",\n        };\n\n        public static readonly SimpleType Shift3fType = new SimpleType()\n        {\n            Name = \"Shift3f\",\n            Read = \"ReadShift3f\",\n        };\n\n        public static readonly SimpleType Shift3dType = new SimpleType()\n        {\n            Name = \"Shift3d\",\n            Read = \"ReadShift3d\",\n        };\n\n        public static readonly SimpleType Trafo2fType = new SimpleType()\n        {\n            Name = \"Trafo2f\",\n            Read = \"ReadTrafo2f\",\n        };\n\n        public static readonly SimpleType Trafo2dType = new SimpleType()\n        {\n            Name = \"Trafo2d\",\n            Read = \"ReadTrafo2d\",\n        };\n\n        public static readonly SimpleType Trafo3fType = new SimpleType()\n        {\n            Name = \"Trafo3f\",\n            Read = \"ReadTrafo3f\",\n        };\n\n        public static readonly SimpleType Trafo3dType = new SimpleType()\n        {\n            Name = \"Trafo3d\",\n            Read = \"ReadTrafo3d\",\n        };\n\n        public static readonly SimpleType[] IntegerTypes = new SimpleType[]\n        {\n            ByteType, SByteType, ShortType, UShortType,\n            IntType, UIntType, LongType, ULongType,\n        };\n\n        public static readonly SimpleType[] IndexTypes = new SimpleType[]\n        {\n            IntType, LongType,\n        };\n\n        public static readonly SimpleType[] RealTypes = new SimpleType[]\n        {\n            FloatType, DoubleType,\n        };\n\n        public static readonly SimpleType[] SignedTypes = new SimpleType[]\n        {\n            SByteType, ShortType, IntType, LongType,\n            FloatType, DoubleType, DecimalType,\n        };\n\n        public static readonly SimpleType[] UnsignedTypes = new SimpleType[]\n        {\n            ByteType, UShortType, UIntType, ULongType,\n        };\n\n        public static readonly SimpleType[] FloatRepresentableTypes = new SimpleType[]\n        {\n            ByteType, SByteType,\n            ShortType, UShortType,\n            FloatType\n        };\n\n        public static readonly SimpleType[] DoubleRepresentableTypes = new SimpleType[]\n        {\n            ByteType, SByteType,\n            ShortType, UShortType,\n            IntType, UIntType,\n            FloatType, DoubleType\n        };\n\n        public static readonly Dictionary<SimpleType, SimpleType[]> RealRepresentableTypes\n            = new Dictionary<SimpleType, SimpleType[]>()\n            {\n                { FloatType, FloatRepresentableTypes },\n                { DoubleType, DoubleRepresentableTypes }\n            };\n\n        public static readonly SimpleType[] TrafoTypes = new SimpleType[]\n        {\n            Euclidean3fType, Euclidean3dType,\n            Rot2fType, Rot2dType, Rot3fType, Rot3dType,\n            Scale3fType, Scale3dType,\n            Shift3fType, Shift3dType,\n            Trafo2fType, Trafo2dType,\n            Trafo3fType, Trafo3dType,\n        };\n\n        public static readonly string[] VecFields = new string[]\n        {\n            \"X\", \"Y\", \"Z\", \"W\",\n        };\n\n        public static readonly string[] VecArgs = new string[]\n        {\n            \"x\", \"y\", \"z\", \"w\",\n        };\n\n        public static readonly SimpleType[] VecFieldTypes = new SimpleType[]\n        {\n            IntType, UIntType, LongType, FloatType, DoubleType,\n        };\n\n        public static readonly SimpleType[] SignedVecFieldTypes =\n            VecFieldTypes.Where(t => !UnsignedTypes.Contains(t)).ToArray();\n\n        public static readonly SimpleType[] MatFieldTypes =\n            SignedVecFieldTypes;\n\n        public static readonly string[] ColorFields = new string[]\n        {\n            \"R\", \"G\", \"B\", \"A\",\n        };\n\n        public static readonly string[] ColorArgs = new string[]\n        {\n            \"r\", \"g\", \"b\", \"a\",\n        };\n\n        public static readonly SimpleType[] ColorFieldTypes = new SimpleType[]\n        {\n            ByteType, UShortType, UIntType, FloatType, DoubleType\n        };\n\n        public static readonly SimpleType[] ColorConvertibleTypes = new SimpleType[]\n        {\n            ByteType, UShortType, UIntType, HalfType, FloatType, DoubleType\n        };\n\n        public static readonly Dictionary<SimpleType, string> ColorConvertibleTypeMinValue\n            = new Dictionary<SimpleType, string>()\n            {\n                { ByteType, \"0\" }, { UShortType, \"0\" }, { UIntType, \"0\" },\n                { HalfType, \"Half.Zero\" }, { FloatType, \"0.0f\" }, { DoubleType, \"0\" },\n            };\n\n        public static readonly Dictionary<SimpleType, string> ColorConvertibleTypeMaxValue\n            = new Dictionary<SimpleType, string>()\n            {\n                { ByteType, \"255\" }, { UShortType, \"65535\" }, { UIntType, \"UInt32.MaxValue\" },\n                { HalfType, \"Half.One\" }, { FloatType, \"1.0f\" }, { DoubleType, \"1.0\" }\n            };\n\n        public static readonly int[] VecTypeDimensions = new[] { 2, 3, 4 };\n        private static readonly Dictionary<SimpleType, VecType>[] VecTypeMapArray;\n        public static readonly VecType[] VecTypes;\n        public static readonly VecType[] SignedVecTypes;\n\n        public static VecType VecTypeOf(int dimensions, SimpleType fieldType)\n        {\n            return VecTypeMapArray[dimensions][fieldType];\n        }\n\n        public static VecType TryGetVecTypeOf(int dimensions, SimpleType fieldType)\n        {\n            if (dimensions >= 0 && dimensions < VecTypeMapArray.Length)\n            {\n                if (VecTypeMapArray[dimensions].TryGetValue(fieldType, out var result))\n                    return result;\n            }\n\n            return null;\n        }\n\n        public static readonly MatDims[] MatTypeDimensions = new[]\n        {\n            new MatDims(2, 2), new MatDims(2, 3),\n            new MatDims(3, 3), new MatDims(3, 4),\n            new MatDims(4, 4),\n        };\n\n        private static readonly Dictionary<SimpleType, MatType>[,] MatTypeMapArray;\n\n        public static MatType MatTypeOf(int rows, int cols, SimpleType fieldType)\n        {\n            return MatTypeMapArray[rows, cols][fieldType];\n        }\n\n        public static readonly MatType[] MatTypes;\n        public static readonly RangeType[] RangeTypes;\n        public static readonly RangeType[] BoxTypes;\n        public static readonly RangeType[] RangeAndBoxTypes;\n\n        public static readonly int[] ColorTypeDimensions = new[] { 3, 4 };\n\n        private static readonly Dictionary<SimpleType, ColorType>[] ColorTypeMapArray;\n        public static readonly ColorType[] ColorTypes;\n\n        public static ColorType ColorTypeOf(int dim, SimpleType fieldType)\n        {\n            return ColorTypeMapArray[dim][fieldType];\n        }\n\n        public static readonly SimpleType[] NumericTypes;\n        public static readonly SimpleType[] BuiltInTypes;\n        public static readonly SimpleType[] StandardNumericTypes;\n        public static readonly SimpleType[] BuiltInNumericTypes;\n        public static readonly SimpleType[] ComparableTypes;\n\n        private static readonly Dictionary<SimpleType, SimpleType> ComputationTypeMap\n            = new Dictionary<SimpleType, SimpleType>()\n            {\n                { ByteType, DoubleType }, { UIntType, DoubleType}, { UShortType, DoubleType},\n                { IntType, DoubleType }, { LongType, DoubleType },\n            };\n\n        public static SimpleType ComputationTypeOf(SimpleType type)\n        {\n            SimpleType computationType;\n            if (ComputationTypeMap.TryGetValue(type, out computationType))\n                return computationType;\n            return type;\n        }\n\n        private static readonly Dictionary<SimpleType, SimpleType> HighPrecisionTypeMap\n            = new Dictionary<SimpleType, SimpleType>()\n            {\n                { ByteType, IntType }, { UShortType, IntType }, { UIntType, LongType },\n                { IntType, LongType }, { FloatType, DoubleType },\n            };\n\n        public static SimpleType HighPrecisionTypeOf(SimpleType type)\n        {\n            SimpleType result;\n            if (HighPrecisionTypeMap.TryGetValue(type, out result))\n                return result;\n            return type;\n        }\n\n        private static readonly Dictionary<SimpleType, SimpleType> SummationTypeMap\n            = new Dictionary<SimpleType, SimpleType>()\n            {\n                { ByteType, IntType }, { SByteType, IntType },\n                { ShortType, LongType }, { UShortType, LongType },\n                { IntType, LongType }, { UIntType, LongType },\n                { FloatType, DoubleType }, { DoubleType, DoubleType },\n            };\n\n        public static SimpleType SummationTypeOf(SimpleType type)\n        {\n            SimpleType summationType;\n            if (SummationTypeMap.TryGetValue(type, out summationType))\n                return summationType;\n            return type;\n        }\n\n        public static readonly SimpleType[] StructTypes;\n\n\n        public static readonly SimpleType TViewType = new SimpleType(\"Tv\");\n        public static readonly SimpleType TDataType = new SimpleType(\"Td\");\n\n        public static readonly GenericTensorType VectorType;\n        public static readonly GenericTensorType VectorWithViewType;\n        public static readonly GenericTensorType MatrixType;\n        public static readonly GenericTensorType MatrixWithViewType;\n        public static readonly GenericTensorType VolumeType;\n        public static readonly GenericTensorType VolumeWithViewType;\n        public static readonly GenericTensorType Tensor4Type;\n        public static readonly GenericTensorType Tensor4WithViewType;\n\n        public static readonly GenericTensorType[] GenericTensorTypes;\n\n        public static readonly SimpleType[] DirectlyCodeableBuiltinTypes;\n        public static readonly SimpleType[] DirectlyCodeableTypes;\n\n\n        private static readonly Dictionary<string, string> s_typeNameSeparatorMap =\n            new Dictionary<string, string>\n            {\n                { \" \", \"\" },\n                { \"[]\", \"Array\" },\n                { \"[,]\", \"Array2d\" },\n                { \"[,,]\", \"Array3d\" },\n                { \"<\", \"_of_\" },\n                { \",\", \"_\" },\n                { \">\", \"_\" },\n            };\n\n        private static readonly Dictionary<string, string> s_typeNameIdentifierMap =\n            new Dictionary<string, string>();\n\n        public static string GetXmlTypeName(string typeName)\n        {\n            typeName = typeName.ReplaceIdentifiers(s_typeNameIdentifierMap);\n            foreach (var kvp in s_typeNameSeparatorMap)\n                typeName = typeName.Replace(kvp.Key, kvp.Value);\n            return typeName;\n        }\n\n        static Meta()\n        {\n            #region VecTypes\n\n            var vectorTypes = new List<VecType>();\n            VecTypeMapArray = new Dictionary<SimpleType, VecType>[5];\n\n            foreach (var n in VecTypeDimensions)\n            {\n                var typeMap = new Dictionary<SimpleType, VecType>();\n                foreach (var ft in VecFieldTypes)\n                {\n                    var t = new VecType(\"V\" + n + ft.Char)\n                    {\n                        Len = n,\n                        FieldType = ft,\n                        Fields = VecFields.Take(n).ToArray(),\n                    };\n                    typeMap[ft] = t;\n                    vectorTypes.Add(t);\n                }\n                VecTypeMapArray[n] = typeMap;\n            }\n\n            VecTypes = vectorTypes.ToArray();\n            SignedVecTypes = vectorTypes.Where(t => !UnsignedTypes.Contains(t.FieldType)).ToArray();\n\n            #endregion\n\n            #region MatTypes\n\n            var matrixTypes = new List<MatType>();\n            MatTypeMapArray = new Dictionary<SimpleType, MatType>[5, 5];\n\n            foreach (var dim in MatTypeDimensions)\n            {\n                var typeMap = new Dictionary<SimpleType, MatType>();\n                foreach (var ft in MatFieldTypes)\n                {\n                    var t = new MatType(\"M\" + dim.Rows + dim.Cols + ft.Char)\n                    { Rows = dim.Rows, Cols = dim.Cols, FieldType = ft };\n                    typeMap[ft] = t;\n                    matrixTypes.Add(t);\n                }\n                MatTypeMapArray[dim.Rows, dim.Cols] = typeMap;\n            }\n\n            MatTypes = matrixTypes.ToArray();\n\n            #endregion\n\n            VectorType = new GenericTensorType(\"Vector\")\n            {\n                DataType = TDataType,\n                ViewType = TDataType,\n                Dim = 1,\n                IndexType = LongType,\n                IntIndexType = IntType,\n            };\n\n            VectorWithViewType = new GenericTensorType(\"Vector\")\n            {\n                DataType = TDataType,\n                ViewType = TViewType,\n                Dim = 1,\n                IndexType = LongType,\n                IntIndexType = IntType,\n            };\n\n            MatrixType = new GenericTensorType(\"Matrix\")\n            {\n                DataType = TDataType,\n                ViewType = TDataType,\n                Dim = 2,\n                IndexType = VecTypeOf(2, LongType),\n                IntIndexType = VecTypeOf(2, IntType),\n            };\n\n            MatrixWithViewType = new GenericTensorType(\"Matrix\")\n            {\n                DataType = TDataType,\n                ViewType = TViewType,\n                Dim = 2,\n                IndexType = VecTypeOf(2, LongType),\n                IntIndexType = VecTypeOf(2, IntType),\n            };\n\n            VolumeType = new GenericTensorType(\"Volume\")\n            {\n                DataType = TDataType,\n                ViewType = TDataType,\n                Dim = 3,\n                IndexType = VecTypeOf(3, LongType),\n                IntIndexType = VecTypeOf(3, IntType),\n            };\n\n            VolumeWithViewType = new GenericTensorType(\"Volume\")\n            {\n                DataType = TDataType,\n                ViewType = TViewType,\n                Dim = 3,\n                IndexType = VecTypeOf(3, LongType),\n                IntIndexType = VecTypeOf(3, IntType),\n            };\n\n            Tensor4Type = new GenericTensorType(\"Tensor4\")\n            {\n                DataType = TDataType,\n                ViewType = TDataType,\n                Dim = 4,\n                IndexType = VecTypeOf(4, LongType),\n                IntIndexType = VecTypeOf(4, IntType),\n            };\n\n            Tensor4WithViewType = new GenericTensorType(\"Tensor4\")\n            {\n                DataType = TDataType,\n                ViewType = TViewType,\n                Dim = 4,\n                IndexType = VecTypeOf(4, LongType),\n                IntIndexType = VecTypeOf(4, IntType),\n            };\n\n            GenericTensorTypes = new GenericTensorType[]\n            {\n                VectorType, VectorWithViewType,\n                MatrixType, MatrixWithViewType,\n                VolumeType, VolumeWithViewType,\n                Tensor4Type, Tensor4WithViewType,\n            };\n\n            RangeTypes = GenerateRangeTypes().ToArray();\n            BoxTypes = GenerateBoxTypes().ToArray();\n            RangeAndBoxTypes = RangeTypes.Concat(BoxTypes).ToArray();\n\n            #region ColorTypes\n\n            var colorTypes = new List<ColorType>();\n            ColorTypeMapArray = new Dictionary<SimpleType, ColorType>[5];\n\n            foreach (var n in ColorTypeDimensions)\n            {\n                var typeMap = new Dictionary<SimpleType, ColorType>();\n                foreach (var ft in ColorFieldTypes)\n                {\n                    var t = new ColorType(\"C\" + n + ft.Char)\n                    {\n                        Len = n,\n                        FieldType = ft,\n                        Fields = ColorFields.Take(n).ToArray(),\n                        Channels = ColorFields.Take(3).ToArray(),\n                        HasAlpha = n == 4,\n                        MinValue = ColorConvertibleTypeMinValue[ft],\n                        MaxValue = ColorConvertibleTypeMaxValue[ft],\n                    };\n                    typeMap[ft] = t;\n                    colorTypes.Add(t);\n                }\n                ColorTypeMapArray[n] = typeMap;\n            }\n\n            ColorTypes = colorTypes.ToArray();\n\n            #endregion\n\n            DirectlyCodeableBuiltinTypes = IntegerTypes.Concat(RealTypes).ToArray();\n\n            BuiltInTypes = BoolType.IntoArray()\n                            .Concat(DirectlyCodeableBuiltinTypes)\n                            .ToArray();\n\n            StandardNumericTypes = IntegerTypes\n                                    .Concat(RealTypes)\n                                    .ToArray();\n\n            foreach (var t in StandardNumericTypes)\n                s_typeNameIdentifierMap[t.Name] = t.Caps;\n            foreach (var t in TextTypes)\n                s_typeNameIdentifierMap[t.Name.ToLower()] = t.Name;\n            s_typeNameIdentifierMap[BoolType.Name] = BoolType.Caps;\n\n            BuiltInNumericTypes = StandardNumericTypes\n                                    .Concat(DecimalType.IntoArray())\n                                    .ToArray();\n\n            NumericTypes = StandardNumericTypes\n                            .Concat(FractionType.IntoArray())\n                            .ToArray();\n\n            ComparableTypes = StandardNumericTypes\n                            .Concat(DecimalType.IntoArray())\n                            .Concat(FractionType.IntoArray())\n                            .Concat(TimeTypes)\n                            .ToArray();\n\n            StructTypes = BuiltInTypes\n                            .Concat(FractionType.IntoArray())\n                            .Concat(SystemTypes)\n                            .Concat(VecTypes)\n                            .Concat(MatTypes)\n                            .Concat(ColorTypes)\n                            .Concat(RangeAndBoxTypes)\n                            .Concat(TrafoTypes)\n                            .ToArray();\n\n            DirectlyCodeableTypes = DirectlyCodeableBuiltinTypes\n                            .Concat(FractionType.IntoArray())\n                            .Concat(SignedVecTypes)             // TODO: Also support unsigned (breaking change in interface)\n                            .Concat(MatTypes)\n                            .Concat(ColorTypes)\n                            .Concat(RangeAndBoxTypes)\n                            .Concat(TrafoTypes)\n                            .ToArray();\n        }\n\n        private static IEnumerable<RangeType> GenerateRangeTypes()\n        {\n            foreach (var t in IntegerTypes.Concat(RealTypes))\n                yield return new RangeType(\"Range1\" + t.Char) { LimitType = t };\n        }\n\n        private static IEnumerable<RangeType> GenerateBoxTypes()\n        {\n            foreach (var vt in SignedVecTypes)\n                if (vt.Len < 4)\n                    yield return new RangeType(\"Box\" + vt.Len + vt.FieldType.Char)\n                    { LimitType = vt };\n        }\n\n        public static readonly SimpleType Circle2dType = new SimpleType() { Name = \"Circle2d\" };\n        public static readonly SimpleType Line2dType = new SimpleType() { Name = \"Line2d\" };\n        public static readonly SimpleType Line3dType = new SimpleType() { Name = \"Line3d\" };\n        public static readonly SimpleType Plane2dType = new SimpleType() { Name = \"Plane2d\" };\n        public static readonly SimpleType Plane3dType = new SimpleType() { Name = \"Plane3d\" };\n        public static readonly SimpleType PlaneWithPoint3dType = new SimpleType() { Name = \"PlaneWithPoint3d\" };\n        public static readonly SimpleType Quad2dType = new SimpleType() { Name = \"Quad2d\" };\n        public static readonly SimpleType Quad3dType = new SimpleType() { Name = \"Quad3d\" };\n        public static readonly SimpleType Ray2dType = new SimpleType() { Name = \"Ray2d\" };\n        public static readonly SimpleType Ray3dType = new SimpleType() { Name = \"Ray3d\" };\n        public static readonly SimpleType Sphere3dType = new SimpleType() { Name = \"Sphere3d\" };\n        public static readonly SimpleType Triangle2dType = new SimpleType() { Name = \"Triangle2d\" };\n        public static readonly SimpleType Triangle3dType = new SimpleType() { Name = \"Triangle3d\" };\n\n        public static readonly SimpleType Circle2fType = new SimpleType() { Name = \"Circle2f\" };\n        public static readonly SimpleType Line2fType = new SimpleType() { Name = \"Line2f\" };\n        public static readonly SimpleType Line3fType = new SimpleType() { Name = \"Line3f\" };\n        public static readonly SimpleType Plane2fType = new SimpleType() { Name = \"Plane2f\" };\n        public static readonly SimpleType Plane3fType = new SimpleType() { Name = \"Plane3f\" };\n        public static readonly SimpleType PlaneWithPoint3fType = new SimpleType() { Name = \"PlaneWithPoint3f\" };\n        public static readonly SimpleType Quad2fType = new SimpleType() { Name = \"Quad2f\" };\n        public static readonly SimpleType Quad3fType = new SimpleType() { Name = \"Quad3f\" };\n        public static readonly SimpleType Ray2fType = new SimpleType() { Name = \"Ray2f\" };\n        public static readonly SimpleType Ray3fType = new SimpleType() { Name = \"Ray3f\" };\n        public static readonly SimpleType Sphere3fType = new SimpleType() { Name = \"Sphere3f\" };\n        public static readonly SimpleType Triangle2fType = new SimpleType() { Name = \"Triangle2f\" };\n        public static readonly SimpleType Triangle3fType = new SimpleType() { Name = \"Triangle3f\" };\n\n        /// <summary>\n        /// All geometry types that need to be serialized.\n        /// </summary>\n        public static readonly SimpleType[] GeometryTypes = new SimpleType[]\n        {\n            Circle2dType, Line2dType, Line3dType, Plane2dType, Plane3dType, PlaneWithPoint3dType,\n            Quad2dType, Quad3dType, Ray2dType, Ray3dType, Sphere3dType,\n            Triangle2dType, Triangle3dType,\n\n            Circle2fType, Line2fType, Line3fType, Plane2fType, Plane3fType, PlaneWithPoint3fType,\n            Quad2fType, Quad3fType, Ray2fType, Ray3fType, Sphere3fType,\n            Triangle2fType, Triangle3fType\n        };\n\n        #region Fun related\n        // Instead of manually copy pasting methods defined in the Fun class to work\n        // elementwise with vectors and matrices, we simply define the methods we are interested in here.\n        // It's a bit verbose since we require a lot of meta information, but much easier and less error-prone than\n        // manually copy pasting the code.\n\n        public class ElementwiseFun\n        {\n            public enum ParamType\n            {\n                Scalar,\n                Tensor,\n            }\n\n            public class Parameter\n            {\n                public string Name { get; set; }\n\n                public ParamType Type { get; set; }\n\n                // Parameters can specify an element type\n                // If null, it is generic and takes the element type of the current type\n                // E.g. for V2i -> int\n                public SimpleType ElementType { get; set; }\n\n                public Parameter(string name, ParamType t, SimpleType et)\n                {\n                    Name = name;\n                    Type = t;\n                    ElementType = et;\n                }\n            }\n\n            public string Name { get; set; }\n\n            // Element type of the result, if null it takes the element type of the current class\n            // E.g. for V2i -> int\n            public SimpleType ReturnType { get; set; }\n\n            public Parameter[] Parameters { get; set; }\n\n            public bool IsExtension { get; set; }\n\n            public bool HasVarArgs { get; set; }\n\n            public bool EditorBrowsable { get; set; }\n\n            public bool Obsolete { get; set; }\n\n            // Only valid for the given element types\n            public SimpleType[] Domain { get; set; }\n\n            public ElementwiseFun(string name, SimpleType returnType, bool extension, bool varArgs,\n                                    SimpleType[] domain, bool editorBrowsable, bool obsolete,\n                                    params Parameter[] parameters)\n            {\n                Name = name;\n                ReturnType = returnType;\n                Parameters = parameters;\n                IsExtension = extension;\n                HasVarArgs = varArgs;\n                Domain = domain;\n                EditorBrowsable = editorBrowsable;\n                Obsolete = obsolete;\n            }\n        }\n\n        public static bool IsScalar(this ElementwiseFun.Parameter p)\n        {\n            return p.Type == ElementwiseFun.ParamType.Scalar;\n        }\n\n        public static bool IsTensor(this ElementwiseFun.Parameter p)\n        {\n            return p.Type == ElementwiseFun.ParamType.Tensor;\n        }\n\n        private static ElementwiseFun.Parameter Scalar(string name, SimpleType t = null)\n        {\n            return new ElementwiseFun.Parameter(name, ElementwiseFun.ParamType.Scalar, t);\n        }\n\n        private static ElementwiseFun.Parameter Tensor(string name, SimpleType t = null)\n        {\n            return new ElementwiseFun.Parameter(name, ElementwiseFun.ParamType.Tensor, t);\n        }\n\n        private static ElementwiseFun.Parameter Other(string name, string typeName)\n        {\n            return new ElementwiseFun.Parameter(name, ElementwiseFun.ParamType.Scalar, new SimpleType(typeName));\n        }\n\n        private static ElementwiseFun Method(string name, SimpleType returnType,\n                                                SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return new ElementwiseFun(name, returnType, true, false, domain, true, false, parameters);\n        }\n\n        private static ElementwiseFun MethodVarArgs(string name, SimpleType returnType,\n                                        SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return new ElementwiseFun(name, returnType, true, true, domain, true, false, parameters);\n        }\n\n        private static ElementwiseFun MethodHidden(string name, SimpleType returnType,\n                                        SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return new ElementwiseFun(name, returnType, true, false, domain, false, false, parameters);\n        }\n\n        private static ElementwiseFun MethodObsolete(string name, SimpleType returnType,\n                                SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return new ElementwiseFun(name, returnType, true, false, domain, false, true, parameters);\n        }\n\n        private static ElementwiseFun Method(string name, SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return Method(name, null, domain, parameters);\n        }\n        private static ElementwiseFun MethodVarArgs(string name, SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return MethodVarArgs(name, null, domain, parameters);\n        }\n\n        private static ElementwiseFun MethodHidden(string name, SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return new ElementwiseFun(name, null, true, false, domain, false, false, parameters);\n        }\n        private static ElementwiseFun MethodObsolete(string name, SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return new ElementwiseFun(name, null, true, false, domain, false, true, parameters);\n        }\n\n        private static ElementwiseFun Method(string name, bool isExtension, SimpleType[] domain, params ElementwiseFun.Parameter[] parameters)\n        {\n            return new ElementwiseFun(name, null, isExtension, false, domain, true, false, parameters);\n        }\n\n        private static ElementwiseFun Method(string name, SimpleType returnType, params ElementwiseFun.Parameter[] parameters)\n        {\n            return new ElementwiseFun(name, returnType, true, false, VecFieldTypes, true, false, parameters);\n        }\n\n        private static ElementwiseFun Method(string name, params ElementwiseFun.Parameter[] parameters)\n        {\n            return Method(name, VecFieldTypes, parameters);\n        }\n         private static ElementwiseFun MethodVarArgs(string name, params ElementwiseFun.Parameter[] parameters)\n        {\n            return MethodVarArgs(name, VecFieldTypes, parameters);\n        }\n\n        private static Dictionary<string, ElementwiseFun[]> getElementwiseFuns()\n        {\n            var dict = new Dictionary<string, ElementwiseFun[]>();\n\n            void Add(string category, params ElementwiseFun[] funs)\n            {\n                dict.Add(category, funs);\n            }\n\n            SimpleType[] Domain(params SimpleType[] types)\n                => types;\n\n            SimpleType[] AllExcept(params SimpleType[] types)\n                => types.FoldLeft(VecFieldTypes, (arr, t) => arr.WithRemoved(t));\n\n            SimpleType[] OnlyReal()\n                => Domain(FloatType, DoubleType);\n\n            SimpleType[] NotReal()\n                => AllExcept(FloatType, DoubleType);\n\n            SimpleType[] OnlySigned()\n                => AllExcept(UIntType, ULongType);\n\n            #region Min and Max\n            Add(\n                \"Min and Max\",\n                Method(\"Min\", Tensor(\"a\"), Tensor(\"b\")),\n                Method(\"Min\", Tensor(\"a\"), Scalar(\"b\")),\n                Method(\"Min\", Scalar(\"a\"), Tensor(\"b\")),\n                Method(\"Max\", Tensor(\"a\"), Tensor(\"b\")),\n                Method(\"Max\", Tensor(\"a\"), Scalar(\"b\")),\n                Method(\"Max\", Scalar(\"a\"), Tensor(\"b\")),\n                Method(\"Min\", Tensor(\"a\"), Tensor(\"b\"), Tensor(\"c\")),\n                Method(\"Max\", Tensor(\"a\"), Tensor(\"b\"), Tensor(\"c\")),\n                Method(\"Min\", Tensor(\"a\"), Tensor(\"b\"), Tensor(\"c\"), Tensor(\"d\")),\n                Method(\"Max\", Tensor(\"a\"), Tensor(\"b\"), Tensor(\"c\"), Tensor(\"d\")),\n                MethodVarArgs(\"Min\", Tensor(\"x\"), Tensor(\"values\")),\n                MethodVarArgs(\"Max\", Tensor(\"x\"), Tensor(\"values\"))\n            );\n            #endregion\n\n            #region Abs\n            Add(\"Abs\",\n                Method(\"Abs\", OnlySigned(), Tensor(\"x\"))\n            );\n            #endregion\n\n            #region Rounding\n            Add(\"Rounding\",\n                Method(\"Floor\", RealTypes, Tensor(\"x\")),\n                Method(\"Ceiling\", RealTypes, Tensor(\"x\")),\n                Method(\"Round\", RealTypes, Tensor(\"x\")),\n                Method(\"Round\", RealTypes, Tensor(\"x\"), Other(\"mode\", \"MidpointRounding\")),\n                Method(\"Round\", RealTypes, Tensor(\"x\"), Other(\"digits\", \"int\")),\n                Method(\"Round\", RealTypes, Tensor(\"x\"), Other(\"digits\", \"int\"), Other(\"mode\", \"MidpointRounding\")),\n                Method(\"Truncate\", RealTypes, Tensor(\"x\"))\n            );\n            #endregion\n\n            #region Frac\n            Add(\"Frac\", Method(\"Frac\", RealTypes, Tensor(\"x\")));\n            #endregion\n\n            #region Clamping\n            Add(\"Clamping\",\n                    Method(\"Clamp\", Tensor(\"x\"), Tensor(\"a\"), Tensor(\"b\")),\n                    Method(\"Clamp\", Tensor(\"x\"), Scalar(\"a\"), Scalar(\"b\")),\n                    Method(\"ClampExcl\", NotReal(), Tensor(\"x\"), Tensor(\"a\"), Tensor(\"b\")),\n                    Method(\"ClampExcl\", NotReal(), Tensor(\"x\"), Scalar(\"a\"), Scalar(\"b\")),\n                    Method(\"ClampWrap\", Tensor(\"x\"), Tensor(\"a\"), Tensor(\"b\")),\n                    Method(\"ClampWrap\", Tensor(\"x\"), Scalar(\"a\"), Scalar(\"b\")),\n                    Method(\"Saturate\", Tensor(\"x\"))\n            );\n            #endregion\n\n            #region MapToUnitInterval\n            Add(\"MapToUnitInterval\",\n                Method(\"MapToUnitInterval\", RealTypes,\n                       Tensor(\"t\"), Tensor(\"tMax\"), Scalar(\"repeat\", BoolType), Scalar(\"mirror\", BoolType)),\n                Method(\"MapToUnitInterval\", RealTypes,\n                       Tensor(\"t\"), Tensor(\"tMax\"), Scalar(\"repeat\", BoolType)),\n                Method(\"MapToUnitInterval\", RealTypes,\n                       Tensor(\"t\"), Tensor(\"tMax\")),\n                Method(\"MapToUnitInterval\", RealTypes,\n                       Tensor(\"t\"), Tensor(\"tMin\"), Tensor(\"tMax\"))\n            );\n            #endregion\n\n            #region Sign\n            Add(\"Sign\",\n                Method(\"Sign\", IntType, OnlySigned(), Tensor(\"x\")),\n                Method(\"Signumi\", IntType, OnlySigned(), Tensor(\"x\")),\n                Method(\"Signum\", OnlySigned(), Tensor(\"x\"))\n            );\n            #endregion\n\n            #region Multiply-Add\n            Add(\"Multiply-Add\",\n                Method(\"MultiplyAdd\", false, AllExcept(), Tensor(\"x\"), Tensor(\"y\"), Tensor(\"z\")),\n                Method(\"MultiplyAdd\", false, AllExcept(), Tensor(\"x\"), Scalar(\"y\"), Tensor(\"z\")),\n                Method(\"MultiplyAdd\", false, AllExcept(), Scalar(\"x\"), Tensor(\"y\"), Tensor(\"z\"))\n            );\n            #endregion\n\n            #region Copy sign\n            Add(\"Copy sign\",\n                Method(\"CopySign\", false, RealTypes, Tensor(\"value\"), Tensor(\"sign\")),\n                Method(\"CopySign\", false, RealTypes, Scalar(\"value\"), Tensor(\"sign\")),\n                Method(\"CopySign\", false, RealTypes, Tensor(\"value\"), Scalar(\"sign\"))\n            );\n            #endregion\n\n            #region Roots\n            Add(\"Roots\",\n                Method(\"Sqrt\", RealTypes, Tensor(\"x\")),\n                Method(\"Sqrt\", DoubleType, NotReal(), Tensor(\"x\")),\n                Method(\"Cbrt\", RealTypes, Tensor(\"x\")),\n                Method(\"Cbrt\", DoubleType, NotReal(), Tensor(\"x\"))\n            );\n            #endregion\n\n            #region Square\n            Add(\"Square\",\n                Method(\"Square\", Tensor(\"x\"))\n            );\n            #endregion\n\n            #region Power\n            Add(\"Power\",\n                Method(\"Pown\", NotReal(), Tensor(\"x\"), Tensor(\"y\")),\n                Method(\"Pown\", NotReal(), Tensor(\"x\"), Scalar(\"y\")),\n                Method(\"Pown\", NotReal(), Scalar(\"x\"), Tensor(\"y\")),\n                Method(\"Pown\", AllExcept(IntType), Tensor(\"x\"), Tensor(\"y\", IntType)),\n                Method(\"Pown\", AllExcept(IntType), Tensor(\"x\"), Scalar(\"y\", IntType)),\n                Method(\"Pown\", AllExcept(IntType), Scalar(\"x\"), Tensor(\"y\", IntType)),\n\n                Method(\"Pow\", OnlyReal(), Tensor(\"x\"), Tensor(\"y\")),\n                Method(\"Pow\", OnlyReal(), Tensor(\"x\"), Scalar(\"y\")),\n                Method(\"Pow\", OnlyReal(), Scalar(\"x\"), Tensor(\"y\")),\n\n                Method(\"Pow\", FloatType, NotReal(), Tensor(\"x\"), Tensor(\"y\", FloatType)),\n                Method(\"Pow\", FloatType, NotReal(), Tensor(\"x\"), Scalar(\"y\", FloatType)),\n                Method(\"Pow\", FloatType, NotReal(), Scalar(\"x\"), Tensor(\"y\", FloatType)),\n                Method(\"Pow\", DoubleType, NotReal(), Tensor(\"x\"), Tensor(\"y\", DoubleType)),\n                Method(\"Pow\", DoubleType, NotReal(), Tensor(\"x\"), Scalar(\"y\", DoubleType)),\n                Method(\"Pow\", DoubleType, NotReal(), Scalar(\"x\"), Tensor(\"y\", DoubleType)),\n\n                MethodHidden(\"Power\", OnlyReal(), Tensor(\"x\"), Tensor(\"y\")),\n                MethodHidden(\"Power\", OnlyReal(), Tensor(\"x\"), Scalar(\"y\")),\n                MethodHidden(\"Power\", OnlyReal(), Scalar(\"x\"), Tensor(\"y\")),\n\n                MethodHidden(\"Power\", FloatType, NotReal(), Tensor(\"x\"), Tensor(\"y\", FloatType)),\n                MethodHidden(\"Power\", FloatType, NotReal(), Tensor(\"x\"), Scalar(\"y\", FloatType)),\n                MethodHidden(\"Power\", FloatType, NotReal(), Scalar(\"x\"), Tensor(\"y\", FloatType)),\n                MethodHidden(\"Power\", DoubleType, NotReal(), Tensor(\"x\"), Tensor(\"y\", DoubleType)),\n                MethodHidden(\"Power\", DoubleType, NotReal(), Tensor(\"x\"), Scalar(\"y\", DoubleType)),\n                MethodHidden(\"Power\", DoubleType, NotReal(), Scalar(\"x\"), Tensor(\"y\", DoubleType))\n            );\n            #endregion\n\n            #region Exp and Log\n            Add(\"Exp and Log\",\n                Method(\"Exp\", RealTypes, Tensor(\"x\")),\n                Method(\"Exp\", DoubleType, NotReal(), Tensor(\"x\")),\n                Method(\"Log\", RealTypes, Tensor(\"x\")),\n                Method(\"Log\", DoubleType, NotReal(), Tensor(\"x\")),\n                Method(\"Log2\", RealTypes, Tensor(\"x\")),\n                Method(\"Log2\", DoubleType, NotReal(), Tensor(\"x\")),\n                Method(\"Log2Int\", IntType, Tensor(\"x\")),\n                Method(\"Log10\", RealTypes, Tensor(\"x\")),\n                Method(\"Log10\", DoubleType, NotReal(), Tensor(\"x\")),\n                Method(\"Log\", RealTypes, Tensor(\"x\"), Scalar(\"basis\")),\n                Method(\"Log\", DoubleType, NotReal(), Tensor(\"x\"), Scalar(\"basis\", DoubleType))\n            );\n            #endregion\n\n            #region ModP\n            Add(\"ModP\", Method(\"ModP\", OnlySigned(), Tensor(\"a\"), Tensor(\"b\")));\n            #endregion\n\n            #region Power of Two\n            Add(\"Power of Two\",\n                Method(\"PowerOfTwo\", Domain(LongType, FloatType, DoubleType), Tensor(\"x\")),\n                Method(\"PowerOfTwo\", LongType, Domain(IntType), Tensor(\"x\")),\n                Method(\"NextPowerOfTwo\", Domain(IntType, LongType), Tensor(\"x\")),\n                Method(\"PrevPowerOfTwo\", Domain(IntType, LongType), Tensor(\"x\"))\n            );\n            #endregion\n\n            #region Trigonometry\n            Add(\"Trigonometry\",\n                Method(\"Sin\", RealTypes, Tensor(\"x\")),\n                Method(\"Cos\", RealTypes, Tensor(\"x\")),\n                Method(\"Tan\", RealTypes, Tensor(\"x\")),\n                Method(\"Asin\", RealTypes, Tensor(\"x\")),\n                Method(\"AsinClamped\", RealTypes, Tensor(\"x\")),\n                Method(\"Acos\", RealTypes, Tensor(\"x\")),\n                Method(\"AcosClamped\", RealTypes, Tensor(\"x\")),\n                Method(\"Atan\", RealTypes, Tensor(\"x\")),\n                Method(\"Atan2\", false, RealTypes, Tensor(\"y\"), Tensor(\"x\")),\n                Method(\"FastAtan2\", false, RealTypes, Tensor(\"y\"), Tensor(\"x\")),\n                Method(\"Sinh\", RealTypes, Tensor(\"x\")),\n                Method(\"Cosh\", RealTypes, Tensor(\"x\")),\n                Method(\"Tanh\", RealTypes, Tensor(\"x\")),\n                Method(\"Asinh\", RealTypes, Tensor(\"x\")),\n                Method(\"Acosh\", RealTypes, Tensor(\"x\")),\n                Method(\"Atanh\", RealTypes, Tensor(\"x\"))\n            );\n            #endregion\n\n            #region Step functions\n            Add(\"Step functions\",\n                Method(\"Step\", Tensor(\"x\"), Tensor(\"edge\")),\n                Method(\"Step\", Tensor(\"x\"), Scalar(\"edge\")),\n                Method(\"Linearstep\", RealTypes, Tensor(\"x\"), Tensor(\"edge0\"), Tensor(\"edge1\")),\n                Method(\"Linearstep\", RealTypes, Tensor(\"x\"), Scalar(\"edge0\"), Scalar(\"edge1\")),\n                Method(\"Smoothstep\", RealTypes, Tensor(\"x\"), Tensor(\"edge0\"), Tensor(\"edge1\")),\n                Method(\"Smoothstep\", RealTypes, Tensor(\"x\"), Scalar(\"edge0\"), Scalar(\"edge1\"))\n            );\n            #endregion\n\n            #region Interpolation\n            Add(\"Interpolation\",\n                Method(\"Lerp\", AllExcept(DoubleType), Scalar(\"t\", FloatType), Tensor(\"a\"), Tensor(\"b\")),\n                Method(\"Lerp\", AllExcept(DoubleType), Tensor(\"t\", FloatType), Tensor(\"a\"), Tensor(\"b\")),\n                Method(\"Lerp\", AllExcept(FloatType), Scalar(\"t\", DoubleType), Tensor(\"a\"), Tensor(\"b\")),\n                Method(\"Lerp\", AllExcept(FloatType), Tensor(\"t\", DoubleType), Tensor(\"a\"), Tensor(\"b\")),\n                Method(\"InvLerp\", Domain(FloatType), Tensor(\"y\"), Tensor(\"a\"), Tensor(\"b\")),\n                Method(\"InvLerp\", DoubleType, AllExcept(FloatType), Tensor(\"y\"), Tensor(\"a\"), Tensor(\"b\"))\n            );\n            #endregion\n\n            #region Common Divisor and Multiple\n            Add(\"Common Divisor and Multiple\",\n                Method(\"GreatestCommonDivisor\", Domain(IntType, LongType, UIntType, ULongType), Tensor(\"a\"), Tensor(\"b\")),\n                Method(\"LeastCommonMultiple\", Domain(IntType, LongType, UIntType, ULongType), Tensor(\"a\"), Tensor(\"b\"))\n            );\n            #endregion\n\n            #region Floating point bits\n            Add(\"Floating point bits\",\n                Method(\"FloatToBits\", IntType, Domain(FloatType), Tensor(\"x\")),\n                Method(\"FloatToUnsignedBits\", UIntType, Domain(FloatType), Tensor(\"x\")),\n                Method(\"FloatFromBits\", FloatType, Domain(IntType), Tensor(\"x\")),\n                Method(\"FloatFromUnsignedBits\", FloatType, Domain(UIntType), Tensor(\"x\")),\n                Method(\"FloatToBits\", LongType, Domain(DoubleType), Tensor(\"x\")),\n                Method(\"FloatFromBits\", DoubleType, Domain(LongType), Tensor(\"x\"))\n            );\n            #endregion\n\n            return dict;\n        }\n\n        public static readonly Dictionary<string, ElementwiseFun[]> ElementwiseFuns = getElementwiseFuns();\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/MinimumSpanningTree.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class MinimumSpanningTree\n    {\n        /// <summary>\n        /// Creates a minimum spanning tree from a set of weighted edges.\n        /// The input are edges ((TVertex, TVertex), TWeight) of a graph.\n        /// The output are a subset of these edges which form a minimum spanning tree.\n        /// The type of the weight (TWeight) needs to be IComparable.\n        /// </summary>\n        public static IEnumerable<((TVertex, TVertex), TWeight)> Create<TVertex, TWeight>(\n            IEnumerable<((TVertex, TVertex), TWeight)> edges\n            )\n            where TWeight : IComparable<TWeight>\n        {\n            if (edges is null) throw new ArgumentNullException(nameof(edges));\n\n            Report.BeginTimed(\"create vertex set\");\n            var vertexSet = new HashSet<TVertex>(edges.SelectMany(e => e.Item1));\n            Report.End();\n            if (vertexSet.Count < 2) yield break;\n\n            //compare function\n            int compare(KeyValuePair<TWeight, TVertex> kvp0, KeyValuePair<TWeight, TVertex> kvp1) => kvp0.Key.CompareTo(kvp1.Key);\n\n            // init per-vertex edge priority queues\n            Report.BeginTimed(\"init per-vertex edge priority queues\");\n            var v2es = new Dictionary<TVertex, List<KeyValuePair<TWeight, TVertex>>>();\n            vertexSet.ForEach(v => v2es[v] = new List<KeyValuePair<TWeight, TVertex>>());\n            foreach (var e in edges)\n            {\n                v2es[e.Item1.Item1].HeapEnqueue(compare, new KeyValuePair<TWeight, TVertex>(e.Item2, e.Item1.Item2));\n                v2es[e.Item1.Item2].HeapEnqueue(compare, new KeyValuePair<TWeight, TVertex>(e.Item2, e.Item1.Item1));\n            }\n            Report.End();\n\n            // mst\n            var mst = new HashSet<TVertex>();\n            void move(TVertex v) { vertexSet.Remove(v); mst.Add(v); }\n\n            // build minimum spanning tree using Prim's algorithm\n            Report.BeginTimed(\"build mst\");\n            move(vertexSet.First());\n            while (vertexSet.Count > 0)\n            {\n                var candidateQueues = mst\n                    .Where(v => v2es.ContainsKey(v))\n                    .Select(v => (v, v2es[v])).Where(q => !q.Item2.IsEmptyOrNull())\n                    ;\n                foreach (var q in candidateQueues)\n                {\n                    while (!q.Item2.IsEmptyOrNull() && mst.Contains(q.Item2[0].Value))\n                        q.Item2.HeapDequeue(compare);\n                    if (q.Item2.IsEmptyOrNull()) v2es.Remove(q.Item1);\n                }\n                var best = candidateQueues\n                    .Select(q => (q.Item1, q.Item2[0]))\n                    .Min((a, b) => a.Item2.Key.CompareTo(b.Item2.Key) < 0)\n                    ;\n                v2es[best.Item1].HeapDequeue(compare);\n                move(best.Item2.Value);\n                yield return ((best.Item1, best.Item2.Value), best.Item2.Key);\n            }\n            Report.End();\n        }\n    }\n\n    public static class MinimumSpanningTreeTest\n    {\n        public static void Test()\n        {\n            var r = new Random();\n            var es = from a in Enumerable.Range(1, 1000)\n                     from b in Enumerable.Range(a + 1, 1000 - a - 1)\n                     let w = r.NextDouble() + 1\n                     select ((a, b), w)\n                     ;\n            Report.Line(\"number of edges: {0}\", es.Count());\n\n            /* unused variable error under mono:\n            var edges = new Tup<(string ,string), int>[]\n            {\n                ((\"A\", \"B\"), 7),\n                ((\"A\", \"D\"), 5),\n                ((\"D\", \"B\"), 9),\n                ((\"B\", \"C\"), 8),\n                ((\"B\", \"E\"), 7),\n                ((\"C\", \"E\"), 5),\n                ((\"E\", \"D\"), 15),\n                ((\"F\", \"D\"), 6),\n                ((\"E\", \"F\"), 8),\n                ((\"F\", \"G\"), 11),\n                ((\"E\", \"G\"), 9),\n            };\n            */\n\n            Report.BeginTimed(\"building mst\");\n            var mst = MinimumSpanningTree.Create(es).ToArray();\n            Report.End();\n\n            Report.Line(\"#edges in mst: {0}\", mst.Length);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/SalesmanOfDeath.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    public readonly struct SymmetricMatrix<T>\n    {\n        private readonly T[] m_data;\n        private readonly long m_size;\n\n        #region Constructors\n\n        public SymmetricMatrix(long size)\n        {\n            m_size = size;\n            m_data = new T[size * (size + 1) / 2];\n        }\n\n        #endregion\n\n        #region Properties\n\n        private long GetIndex(long x, long y)\n        {\n            if (y > x) return x * (m_size + 1) - (x * (x + 1)) / 2 + y - x;\n            else return y * (m_size + 1) - (y * (y + 1)) / 2 + x - y;\n        }\n\n        private V2l GetCoord(long index)\n        {\n            long r, c;\n            r = (int)(0.5 * (-System.Math.Sqrt(-8 * index + 4 * m_size * m_size + 4 * m_size + 1) + 2 * m_size + 1));\n            if (r == 0) c = index;\n            else c = r + index % (r * (m_size + 1) - (r * (r + 1)) / 2);\n\n            return new V2l(c, r);\n        }\n\n        public T this[long index]\n        {\n            get { return m_data[index]; }\n            set { m_data[index] = value; }\n        }\n\n        public T this[long row, long col]\n        {\n            get { return m_data[GetIndex(col, row)]; }\n            set { m_data[GetIndex(col, row)] = value; }\n        }\n\n        public T this[V2l vec]\n        {\n            get { return m_data[GetIndex(vec.X, vec.Y)]; }\n            set { m_data[GetIndex(vec.X, vec.Y)] = value; }\n        }\n\n        public V2l Size => new V2l(m_size, m_size);\n\n        #endregion\n\n        #region Methods\n\n        public void ForeachCoord(Action<V2l> action)\n        {\n            V2l current = V2l.Zero;\n            for (long i = 0; i < m_data.Length; i++)\n            {\n                action(current);\n                current.X++;\n                if (current.X >= m_size)\n                {\n                    current.Y++;\n                    current.X = current.Y;\n                }\n            }\n        }\n\n        public void ForeachCoord(Action<long, long> action)\n        {\n            V2l current = V2l.Zero;\n            for (long i = 0; i < m_data.Length; i++)\n            {\n                action(current.X, current.Y);\n                current.X++;\n                if (current.X >= m_size)\n                {\n                    current.Y++;\n                    current.X = current.Y;\n                }\n            }\n        }\n        \n        public void ForeachIndex(Action<long> action)\n        {\n            for (long i = 0; i < m_data.Length; i++) action(i);\n        }\n\n        public void ForeachXYIndex(Action<long, long, long> action)\n        {\n            V2l current = V2l.Zero;\n            for (long i = 0; i < m_data.Length; i++)\n            {\n                action(current.X, current.Y, i);\n                current.X++;\n                if (current.X >= m_size)\n                {\n                    current.Y++;\n                    current.X = current.Y;\n                }\n            }\n        }\n        \n        public void ForeachY(int x, Action<long, V2l> action)\n        {\n            long index = GetIndex(x, 0);\n            V2l vec = new V2l(x, 0);\n            for (vec.Y = 0; vec.Y <= x; vec.Y++)\n            {\n                action(index, vec);\n                index += (m_size - vec.Y - 1);\n            }\n        }\n\n        public void ForeachX(int y, Action<long, V2l> action)\n        {\n            long index = GetIndex(y, y);\n            V2l vec = new V2l(y, y);\n            for (vec.X = y; vec.X < m_size; vec.X++)\n            {\n                action(index, vec);\n                index++;\n            }\n        }\n\n\n        public void SetByIndex(Func<long, T> setter)\n        {\n            for (long i = 0; i < m_data.Length; i++) m_data[i] = setter(i);\n        }\n\n        public void SetByCoord(Func<V2l, T> setter)\n        {\n            V2l current = V2l.Zero;\n            for (long i = 0; i < m_data.Length; i++)\n            {\n                m_data[i] = setter(current);\n                current.X++;\n                if (current.X >= m_size)\n                {\n                    current.Y++;\n                    current.X = current.Y;\n                }\n            }\n        }\n\n        public void SetByCoord(Func<long, long, T> setter)\n        {\n            V2l current = V2l.Zero;\n            for (long i = 0; i < m_data.Length; i++)\n            {\n                m_data[i] = setter(current.X, current.Y);\n                current.X++;\n                if (current.X >= m_size)\n                {\n                    current.Y++;\n                    current.X = current.Y;\n                }\n            }\n        }\n\n        #endregion\n    }\n    \n    public abstract class AbstractGraph<TVertex, TCost> where TCost : struct, IComparable<TCost>\n    {\n        protected List<TVertex> m_nodes;\n        protected Tree m_minimumSpanningTree;\n\n        #region Reference-Structures/Classes\n\n        public readonly struct Edge : IComparable<Edge>\n        {\n            private readonly AbstractGraph<TVertex, TCost> m_graph;\n            public readonly int Index0;\n            public readonly int Index1;\n\n            #region Constructors\n\n            internal Edge(AbstractGraph<TVertex, TCost> graph, int i0, int i1)\n            {\n                if (i0 == i1) throw new ArgumentException(\"Degenerated Edges are not posible\");\n                m_graph = graph;\n\n                if (i0 < i1) { Index0 = i0; Index1 = i1; }\n                else { Index0 = i1; Index1 = i0; }\n            }\n\n            #endregion\n\n            #region Properties\n\n            public TVertex Node0 => m_graph.m_nodes[Index0];\n\n            public TVertex Node1 => m_graph.m_nodes[Index1]; \n\n            public TCost Cost => m_graph.GetCost(Index0, Index1);\n\n            #endregion\n\n            #region Overrides\n\n            public override int GetHashCode()\n                => m_graph.GetHashCode() ^ ((Index0.GetHashCode() << 12) ^ Index1.GetHashCode());\n\n            public override bool Equals(object obj)\n            {\n                if (obj is Edge e)\n                {\n                    if (!e.m_graph.Equals(m_graph)) return false;\n                    else return Index0 == e.Index0 && Index1 == e.Index1;\n                }\n                else return false;\n            }\n\n            public override string ToString() => string.Format(\"[{0},{1}]\", Index0, Index1);\n\n            #endregion\n\n            #region IComparable<Edge> Members\n\n            public int CompareTo(Edge other) => Cost.CompareTo(other.Cost);\n\n            #endregion\n        }\n\n        protected class UnionFind\n        {\n            private readonly List<TVertex> m_nodes;\n            private readonly int[] m_parent;\n\n            #region Constructors\n\n            internal UnionFind(List<TVertex> nodes)\n            {\n                m_nodes = nodes;\n                m_parent = new int[m_nodes.Count].SetByIndex(i => i);\n            }\n\n            #endregion\n\n            #region Methods\n\n            private int FindRoot(int n)\n            {\n                int p = m_parent[n];\n\n                if (p != n)\n                {\n                    p = FindRoot(p);\n                    m_parent[n] = p;\n                    return p;\n                }\n                else\n                {\n                    return n;\n                }\n            }\n\n            public bool Add(int n0, int n1)\n            {\n                int p0 = FindRoot(n0);\n                int p1 = FindRoot(n1);\n\n                if (p0 != p1)\n                {\n                    m_parent[p0] = p1;\n                    return true;\n                }\n                else return false;\n            }\n\n            #endregion\n        }\n\n        public class Tree\n        {\n            private readonly AbstractGraph<TVertex, TCost> m_graph;\n\n            private readonly List<Tup<int, int>> m_edges;\n\n            private int m_edgeCount;\n            private readonly bool[] m_visited;\n\n            #region Constructors\n\n            internal Tree(AbstractGraph<TVertex, TCost> graph)\n            {\n                m_graph = graph;\n                m_edges = new List<Tup<int, int>>(m_graph.m_nodes.Count);\n\n                for (int i = 0; i < m_graph.m_nodes.Count; i++)\n                {\n                    m_edges.Add(new Tup<int, int>(-1, -1));\n                }\n                \n                m_visited = new bool[m_graph.m_nodes.Count].SetByIndex(i => false);\n                m_edgeCount = 0;\n            }\n\n            #endregion\n\n            #region Edges\n\n            private void AddHalfEdge(Edge e, int l, int r)\n            {\n                int index = l;\n\n                var tup = m_edges[index];\n                if (tup.E0 < 0)\n                {\n                    tup.E0 = r;\n                    m_edges[index] = tup;\n                }\n                else\n                {\n                    while (tup.E1 >= 0)\n                    {\n                        index = tup.E1;\n                        tup = m_edges[index];\n                    }\n                    tup.E1 = m_edges.Count;\n                    m_edges[index] = tup;\n                    m_edges.Add(new Tup<int, int>(r, -1));\n                }\n            }\n\n            internal void AddEdge(Edge edge)\n            {\n                AddHalfEdge(edge, edge.Index0, edge.Index1);\n                AddHalfEdge(edge, edge.Index1, edge.Index0);\n                m_edgeCount++;\n            }\n\n            #endregion\n\n            #region Traversals\n\n            private void TraverseAux(int n, Action<TVertex> nodeAction, Action<Edge> edgeAction)\n            {\n                if (m_visited[n]) return;\n                m_visited[n] = true;\n\n                nodeAction(m_graph.m_nodes[n]);\n\n                var tup = m_edges[n];\n                if (tup.E0 < 0) return;\n\n                int edgeIndex = n;\n                edgeAction(new Edge(m_graph, n, tup.E0));\n                TraverseAux(tup.E0, nodeAction, edgeAction);\n                \n                while (tup.E1 >= 0)\n                {\n                    edgeIndex = tup.E1;\n                    tup = m_edges[edgeIndex];\n\n                    edgeAction(new Edge(m_graph, n, tup.E0));\n                    TraverseAux(tup.E0, nodeAction, edgeAction);\n                }\n            }\n\n            public void Traverse(Action<TVertex> nodeAction, Action<Edge> edgeAction)\n            {\n                m_visited.SetByIndex(i => false);\n                TraverseAux(0, nodeAction, edgeAction);\n            }\n\n            private void TraverseEulerAux(int n, Action<int> action)\n            {\n                if (m_visited[n]) return;\n                m_visited[n] = true;\n\n                int nodeIndex = n;\n                action(nodeIndex);//m_graph.m_nodes[n]);\n\n                var tup = m_edges[n];\n                if (tup.E0 < 0) return;\n\n                TraverseEulerAux(tup.E0, action);\n                action(nodeIndex);//m_graph.m_nodes[n]);\n\n                while (tup.E1 >= 0)\n                {\n                    n = tup.E1;\n                    tup = m_edges[n];\n\n                    TraverseEulerAux(tup.E0, action);\n                    action(nodeIndex);//m_graph.m_nodes[n]);\n                }\n            }\n\n            public void TraverseEuler(Action<int> action)\n            {\n                m_visited.SetByIndex(i => false);\n                TraverseEulerAux(0, action);\n            }\n\n            #endregion\n\n            #region Properties\n\n            public int VertexCount => m_graph.VertexCount;\n\n            public int EdgeCount => m_edgeCount;\n\n            public TCost Cost => GetCost<TCost>(GraphHelpers.Add<TCost>, default(TCost));\n\n            public TAccumulate GetCost<TAccumulate>(Func<TAccumulate, TCost, TAccumulate> addition, TAccumulate seed)\n            {\n                var sum = seed;\n                Traverse(node => { }, edge => sum = addition(sum, edge.Cost));\n\n                return sum;\n            }\n\n            #endregion\n\n        }\n\n        public class Tour\n        {\n            private readonly AbstractGraph<TVertex, TCost> m_graph;\n            private readonly int[] m_permutation;\n            private bool m_2optImproved;\n            private readonly bool m_circular;\n\n            #region Constructors\n\n            internal Tour(AbstractGraph<TVertex, TCost> graph, int[] permutation, bool circular = true)\n            {\n                m_circular = circular;\n                m_graph = graph;\n                m_permutation = permutation;\n                m_2optImproved = circular ? false : true;\n            }\n\n            #endregion\n\n            #region Methods\n\n            public bool Improve(int iterations = 1)\n            {\n                if (iterations < 0) iterations = int.MaxValue;\n\n                int steps = 0;\n                if (!m_2optImproved)\n                {\n                    do\n                    {\n                        if (m_graph.Improve2Opt(m_permutation, GraphHelpers.Add<TCost>) == 0) m_2optImproved = true;\n                        else steps++;\n                    }\n                    while (steps < iterations && !m_2optImproved);\n                }\n\n                return steps != 0;\n            }\n\n            public void Improve3Opt(int iterations)\n            {\n                for (int i = 0; i < iterations; i++)\n                {\n                    m_graph.Improve3Opt(m_permutation, GraphHelpers.Add<TCost>);\n                }\n            }\n\n            #endregion\n\n            #region Properties\n\n            public IEnumerable<TVertex> Vertices\n            {\n                get\n                {\n                    foreach (var i in m_permutation) yield return m_graph.m_nodes[i];\n                }\n            }\n\n            public IEnumerable<Edge> Edges\n            {\n                get\n                {\n                    int count = m_permutation.Length;\n\n                    for (int i = 0; i < (m_circular ? count : count - 1); i++)\n                    {\n                        yield return new Edge(m_graph, m_permutation[i], m_permutation[(i + 1) % count]);\n                    }\n                }\n            }\n\n            public TAccumulate GetCost<TAccumulate>(Func<TAccumulate, TCost, TAccumulate> addition, TAccumulate seed)\n            {\n                var sum = seed;\n\n                foreach (var e in Edges)\n                {\n                    sum = addition(sum, e.Cost);\n                }\n\n                return sum;\n            }\n\n            public TCost Cost => GetCost<TCost>(GraphHelpers.Add<TCost>, default(TCost));\n\n            public int Count => m_permutation.Length;\n\n            public int[] Permutation => m_permutation;\n\n            public TVertex this[int index] => m_graph.m_nodes[m_permutation[index]];\n\n            #endregion\n\n            #region Overrides\n\n            public override string ToString()\n            {\n                var e = Vertices.GetEnumerator();\n                if (!e.MoveNext()) return \"[]\";\n\n                string res = e.Current.ToString();\n                while (e.MoveNext())\n                {\n                    res += string.Format(\", {0}\", e.Current.ToString());\n                }\n\n                return string.Format(\"[{0}]\", res);\n            }\n\n            #endregion\n        }\n\n        public readonly struct Vertex\n        {\n            private readonly AbstractGraph<TVertex, TCost> m_graph;\n            private readonly int m_index;\n\n            #region Constructors\n\n            internal Vertex(AbstractGraph<TVertex, TCost> graph, int index)\n            {\n                m_graph = graph;\n                m_index = index;\n            }\n\n            #endregion\n\n            #region Properties\n\n            public TVertex Value => m_graph.m_nodes[m_index]; \n\n            public int Index => m_index;\n\n            #endregion\n\n            #region Overrides\n\n            public override string ToString() => string.Format(\"[{0}: {1}]\", m_index, Value);\n\n            public override int GetHashCode() => m_graph.GetHashCode() ^ m_index.GetHashCode();\n\n            public override bool Equals(object obj)\n            {\n                if (obj is Vertex v)\n                {\n                    return v.m_graph.Equals(m_graph) && v.m_index == m_index;\n                }\n                else return false;\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        #region Abstract Members\n\n        public abstract int EdgeCount { get; }\n        public abstract TCost GetCost(int n0, int n1);\n        public abstract IEnumerable<Edge> Edges { get; }\n        public abstract Tree MinimumSpanningTree { get; }\n\n        #endregion\n\n        #region Properties\n\n        public int VertexCount => m_nodes.Count;\n\n        #endregion\n\n        public Vertex GetVertex(int index) => new Vertex(this, index);\n\n        public IEnumerable<Vertex> GetVertices(TVertex value)\n        {\n            int index = 0;\n            foreach (var v in m_nodes)\n            {\n                if (v.Equals(value)) yield return new Vertex(this, index);\n                index++;\n            }\n        }\n\n        #region TSP-Solver\n\n        protected int Improve2Opt(int[] tour, Func<TCost, TCost, TCost> add)\n        {\n            int steps = 0;\n            int count = tour.Length;\n            for (int i = 0; i < count; i++)\n            {\n                for (int j = i + 2; j < count; j++)\n                {\n                    int l0 = i % count;\n                    int l1 = (i + 1) % count;\n                    int r0 = j % count;\n                    int r1 = (j + 1) % count;\n\n                    var wOld = add(GetCost(tour[l0], tour[l1]), GetCost(tour[r0], tour[r1]));\n                    var wNew = add(GetCost(tour[l0], tour[r0]), GetCost(tour[r1], tour[l1]));\n\n                    if (wNew.CompareTo(wOld) < 0)\n                    {\n                        int temp;\n                        //reverse l1 to r0\n                        while (r0 > l1)\n                        {\n                            temp = tour[r0];\n                            tour[r0] = tour[l1];\n                            tour[l1] = temp;\n\n                            l1++;\n                            r0--;\n                        }\n\n                        steps++;\n                    }\n\n                }\n            }\n\n            return steps;\n        }\n\n        protected int Improve3Opt(int[] tour, Func<TCost, TCost, TCost> add)\n        {\n            int improvements = 0;\n            int count = tour.Length;\n\n            for (int i = 0; i < count; i++)\n            {\n                int i0 = tour[i];\n                int i1 = tour[(i + 1) % count];\n\n                for (int j = i + 2; j < count; j++)\n                {\n                    int i2 = tour[j];\n                    int i3 = tour[(j + 1) % count];\n\n                    for (int k = j + 2; k < count; k++)\n                    {\n                        int i4 = tour[k];\n                        int i5 = tour[(k + 1) % count];\n\n                        //Initial:\n                        //01 23 45\n\n                        //New:\n                        //0: 02 13 45      (already tested with 2-opt)\n                        //1: 02 14 35      Reverse: [2:1], [4:3]\n                        //2: 03 41 25      Reverse: nothing\n                        //3: 03 42 15      Reverse: [2:1]\n                        //4: 04 31 25      Reverse: [4:3]\n                        //5: 04 32 15      Reverse: [4:3], [2:1]\n                        int alternativeIndex = -1;\n                        var min = add(add(GetCost(i0, i1), GetCost(i2, i3)), GetCost(i4, i5));\n\n                        //02 14 35      Reverse: [2:1], [4:3]\n                        var alternativeCost = add(add(GetCost(i0, i2), GetCost(i1, i4)), GetCost(i3, i5));\n                        if (alternativeCost.CompareTo(min) < 0)\n                        {\n                            min = alternativeCost;\n                            alternativeIndex = 1;\n                        }\n\n                        //03 41 25      Reverse: nothing\n                        alternativeCost = add(add(GetCost(i0, i3), GetCost(i4, i1)), GetCost(i2, i5));\n                        if (alternativeCost.CompareTo(min) < 0)\n                        {\n                            min = alternativeCost;\n                            alternativeIndex = 2;\n                        }\n\n                        //03 42 15      Reverse: [2:1]\n                        alternativeCost = add(add(GetCost(i0, i3), GetCost(i4, i2)), GetCost(i1, i5));\n                        if (alternativeCost.CompareTo(min) < 0)\n                        {\n                            min = alternativeCost;\n                            alternativeIndex = 3;\n                        }\n\n                        //04 31 25      Reverse: [4:3]\n                        alternativeCost = add(add(GetCost(i0, i4), GetCost(i3, i1)), GetCost(i2, i5));\n                        if (alternativeCost.CompareTo(min) < 0)\n                        {\n                            min = alternativeCost;\n                            alternativeIndex = 4;\n                        }\n\n                        //04 32 15      Reverse: [4:3], [2:1]\n                        alternativeCost = add(add(GetCost(i0, i4), GetCost(i3, i2)), GetCost(i1, i5));\n                        if (alternativeCost.CompareTo(min) < 0)\n                        {\n                            min = alternativeCost;\n                            alternativeIndex = 5;\n                        }\n\n                        if (alternativeIndex > 0)\n                        {\n                            if (alternativeIndex == 1)\n                            {\n                                //1: 02 14 35      Reverse: [2:1], [4:3]\n\n                            }\n                        }\n                    }\n                }\n            }\n\n            return improvements;\n        }\n\n        #endregion\n\n        #region Shortest Path\n\n        private TR NearestNode<T, TI, TR>(IEnumerable<T> nodes, Func<T, TI> comparable, Func<T, TR> result) where TI : IComparable<TI>\n        {\n            var e = nodes.GetEnumerator();\n            if (!e.MoveNext()) throw new IndexOutOfRangeException();\n            var min = e.Current;\n            var comparableMin = comparable(min);\n\n            while (e.MoveNext())\n            {\n                var comparableTemp = comparable(e.Current);\n                if (comparableTemp.CompareTo(comparableMin) < 0)\n                {\n                    min = e.Current;\n                    comparableMin = comparableTemp;\n                }\n            }\n\n            return result(min);\n        }\n\n        public Tour ShortestPath(int start, int end)\n        {\n            var parent = new int[m_nodes.Count].Set(-1);\n            var nodes = new HashSet<int>();\n            var distances = new TCost[m_nodes.Count];\n\n            for (int i = 0; i < m_nodes.Count; i++)\n            {\n                if (i != start)\n                {\n                    distances[i] = GetCost(start, i);\n                    parent[i] = start;\n                }\n                else distances[i] = default(TCost);\n            }\n            \n            for (int i = 0; i < m_nodes.Count; i++)\n            {\n                nodes.Add(i);\n            }\n\n            while (nodes.Count > 0)\n            {\n                int u = NearestNode(nodes, n => distances[n], n => n);\n                nodes.Remove(u);\n\n                foreach (var v in nodes)\n                {\n                    //u,v\n                    var alternative = GraphHelpers.Add(distances[u], GetCost(u, v));\n                    if (alternative.CompareTo(distances[v]) < 0)\n                    {\n                        distances[v] = alternative;\n                        parent[v] = u;\n                    }\n                }\n            }\n\n            var path = new List<int> { end };\n            var current = end;\n\n            while (parent[current] >= 0)\n            {\n                current = parent[current];\n                path.Insert(0, current);\n            }\n\n            return new Tour(this, path.ToArray(), false);\n        }\n\n        #endregion\n    }\n\n    public class DenseGraph<TVertex, TCost> : AbstractGraph<TVertex, TCost> where TCost : struct, IComparable<TCost>\n    {\n        private SymmetricMatrix<TCost> m_costs;\n\n        #region Constructors\n\n        public DenseGraph(IEnumerable<TVertex> nodes, Func<TVertex, TVertex, TCost> weightFun)\n        {\n            m_nodes = nodes.ToList();\n            BuildWeights(weightFun);\n        }\n\n        public DenseGraph(IEnumerable<TVertex> nodes, Func<int, TVertex, int, TVertex, TCost> weightFun)\n        {\n            m_nodes = nodes.ToList();\n            BuildWeights(weightFun);\n        }\n\n        #endregion\n\n        #region Methods\n\n        public void BuildWeights(Func<TVertex, TVertex, TCost> weightFun)\n        {\n            m_costs = new SymmetricMatrix<TCost>(m_nodes.Count);\n\n            m_costs.SetByCoord((x, y) =>\n            {\n                return weightFun(m_nodes[(int)x], m_nodes[(int)y]);\n            });\n\n            m_minimumSpanningTree = null;\n        }\n\n        public void BuildWeights(Func<int, TVertex, int, TVertex, TCost> weightFun)\n        {\n            m_costs = new SymmetricMatrix<TCost>(m_nodes.Count);\n\n            m_costs.SetByCoord((x, y) =>\n            {\n                return weightFun((int)x, m_nodes[(int)x], (int)y, m_nodes[(int)y]);\n            });\n\n            m_minimumSpanningTree = null;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public override IEnumerable<Edge> Edges\n        {\n            get\n            {\n                for (int x = 1; x < m_nodes.Count; x++)\n                {\n                    for (int y = 0; y < x; y++)\n                    {\n                        yield return new Edge(this, y, x);\n                    }\n                }\n            }\n        }\n\n        public override int EdgeCount => m_nodes.Count * (m_nodes.Count - 1) / 2;\n\n        /// <summary>\n        /// Returns the minimum-spanning-tree for the Graph\n        /// If no Tree has been built before builds it using Prim's algorithm (which is faster than Kruskal's algorithm on dense Graphs)\n        /// </summary>\n        public override Tree MinimumSpanningTree\n        {\n            get\n            {\n                if (m_minimumSpanningTree == null) m_minimumSpanningTree = BuildMinimumSpanningTreePrim();\n                return m_minimumSpanningTree;\n            }\n        }\n\n        #endregion\n\n        #region Minimum-Spanning-Tree\n\n        /// <summary>\n        /// Builds the minimum-spanning tree using Kruskal's algorithm in O(|E|*log|E|)\n        /// where |E| is the number of Edges \n        /// and |V| the number of vertices (nodes) in the Graph\n        /// </summary>\n        /// <returns></returns>\n        private Tree BuildMinimumSpanningTreeKruskal()\n        {\n            int N = m_nodes.Count;\n            var unionFind = new UnionFind(m_nodes); //O(|V|)\n\n            Func<Edge, Edge, int> cmp = (a, b) => a.CompareTo(b);\n            var heap = new List<Edge>(EdgeCount);\n            foreach (var e in Edges) heap.HeapEnqueue(cmp, e);\n\n            var tree = new Tree(this);\n\n            long i = 0;\n            //O(|E|*log|E|)\n            while (tree.EdgeCount < N - 1)\n            {\n                var edge = heap.HeapDequeue(cmp);\n                i++;\n\n                //O(1) amortized\n                if (unionFind.Add(edge.Index0, edge.Index1))\n                {\n                    //O(1)\n                    tree.AddEdge(edge);\n                }\n            }\n\n            //O(|V| + |E|*log|E|)\n            return tree;\n        }\n        \n        /// <summary>\n        /// Builds the minimum-spanning-tree using Prim's algorithm in O(|V|^2)\n        /// where |V| is the number of vertices (nodes) in the Graph\n        /// </summary>\n        /// <returns></returns>\n        public Tree BuildMinimumSpanningTreePrim()\n        {\n            int node = 0;\n            bool[] visited = new bool[m_nodes.Count].Set(false);\n            Tree tree = new Tree(this);\n\n            while (tree.EdgeCount < m_nodes.Count - 1)\n            {\n                visited[node] = true;\n                int next = FindClosestUnvisited(node, visited);\n\n                tree.AddEdge(new Edge(this, node, next));\n                node = next;\n            }\n\n            return tree;\n        }\n\n        private int FindClosestUnvisited(int node, bool[] visited)\n        {\n            int N = m_nodes.Count;\n\n            long nearest = -1;\n            TCost min = default(TCost);\n            m_costs.ForeachX(node, (i, p) =>\n            {\n                if (node != p.X && !visited[p.X])\n                {\n                    var w = m_costs[i];\n                    if (nearest < 0 || w.CompareTo(min) < 0) { min = w; nearest = p.X; }\n                }\n            });\n\n            m_costs.ForeachY(node, (i, p) =>\n            {\n                if (node != p.Y && !visited[p.Y])\n                {\n                    var w = m_costs[i];\n                    if (nearest < 0 || w.CompareTo(min) < 0) { min = w; nearest = p.Y; }\n                }\n            });\n\n            return (int)nearest;\n        }\n\n        #endregion\n\n        #region TSP-Solver\n\n        public Tour SolveTSP()\n        {\n            int index = 0;\n            var perm = new int[m_nodes.Count];\n            var visited = new bool[m_nodes.Count].SetByIndex(i => false);\n\n            MinimumSpanningTree.TraverseEuler(ni =>\n            {\n                if (!visited[ni])\n                {\n                    visited[ni] = true;\n                    perm[index] = ni;\n                    index++;\n                }\n            });\n\n            return new Tour(this, perm);\n        }\n\n        public override TCost GetCost(int n0, int n1)\n        {\n            if (n0 < n1) return m_costs[n0, n1];\n            else return m_costs[n1, n0];\n        }\n\n        #endregion\n    }\n\n    internal static class GraphHelpers\n    {\n        private static readonly Dictionary<Type, Func<object, object, object>> m_additions = new Dictionary<Type, Func<object, object, object>>()\n        {\n            {typeof(int), (a,b) => (int)a + (int)b},\n            {typeof(uint), (a,b) => (uint)a + (uint)b},\n            {typeof(long), (a,b) => (long)a + (long)b},\n            {typeof(float), (a,b) => (float)a + (float)b},\n            {typeof(double), (a,b) => (double)a + (double)b},\n            {typeof(byte), (a,b) => (byte)a + (byte)b},\n            {typeof(short), (a,b) => (short)a + (short)b},\n            {typeof(ushort), (a,b) => (ushort)a + (ushort)b},\n        };\n        \n        public static TWeight Add<TWeight>(TWeight v0, TWeight v1)\n        {\n            return (TWeight)m_additions[typeof(TWeight)](v0, v1);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/ShortestPath.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public interface IShortestPath<T>\n    {\n        void Cancel();\n        void CalculateShortestPaths(T pos);\n        void CalculateShortestPathsByIndex(int posIdx);\n        List<T> GetMinimalPath(T pos);\n        List<T> GetMinimalPathByIndex(int posIdx);\n    }\n\n    public class ShortestPath<T> : IShortestPath<T>\n    {\n        private readonly List<T> m_nodes;\n        private readonly List<int>[] m_neighbors;\n        private readonly Func<T, T, float> m_getCostFunc;\n        private bool[] m_expanded;\n        private int[] m_pointers;\n        private bool m_cancelTask = false;\n        private int m_seedId;\n        private Task m_task = null;\n        private CancellationTokenSource m_cancellationToken;\n\n        public ShortestPath(List<T> nodes, List<(int, int)> edges, Func<T, T, float> getCostFunc)\n        {\n            m_nodes = nodes;\n            m_neighbors = new List<int>[nodes.Count];\n            for(int i = 0; i<m_nodes.Count; i++) m_neighbors[i] = new List<int>();\n            foreach (var e in edges)\n            {\n                m_neighbors[e.Item1].Add(e.Item2);\n                m_neighbors[e.Item2].Add(e.Item1);\n            }\n            m_getCostFunc = getCostFunc;\n            m_expanded = new bool[nodes.Count];\n        }\n        public ShortestPath(T[] nodes, List<int>[] neighbors, Func<T, T, float> getCostFunc)\n        {\n            m_nodes = nodes.ToList();\n            m_neighbors = neighbors;\n            m_getCostFunc = getCostFunc;\n            m_expanded = new bool[nodes.Length];\n        }\n\n        public void Cancel()\n        {\n            if (m_task != null && !(m_task.IsCanceled || m_task.IsCompleted))\n            {\n                m_cancelTask = true;\n                if (m_cancellationToken != null) m_cancellationToken.Cancel();\n                m_task.Wait();\n            }\n            m_task = null;\n            m_cancelTask = false;\n        }\n\n        public void CalculateShortestPaths(T seed)\n        {\n            //Cancel();\n            if (m_cancellationToken != null) m_cancellationToken.Cancel();\n            m_cancellationToken = new CancellationTokenSource();\n            m_task = Task.Factory.StartNew(delegate { Calculate(seed); }, m_cancellationToken);\n        }\n        public void CalculateShortestPathsByIndex(int index)\n        {\n            //Cancel();\n            if (m_cancellationToken != null) m_cancellationToken.Cancel();\n            m_cancellationToken = new CancellationTokenSource();\n            m_task = Task.Factory.StartNew(delegate { CalculateByIndex(index); }, m_cancellationToken);\n        }\n\n        private void Calculate(T seed)\n        {\n            CalculateByIndex(m_nodes.IndexOf(seed));\n        }\n        \n        private void CalculateByIndex(int index)\n        {\n            Report.BeginTimed(\"Shortest paths calculation\");\n            m_seedId = index;\n\n            var activePixels = new FibonacciHeap<int>();\n            var inActiveList = new Dictionary<int, FibonacciHeap<int>.Node>();\n            inActiveList[m_seedId] = activePixels.Insert(0, m_seedId);\n\n            var totalCost = new float[m_nodes.Count].Set(float.MaxValue);\n            m_expanded = new bool[m_nodes.Count];\n            m_pointers = new int[m_nodes.Count].Set(m_seedId);\n\n            totalCost[m_seedId] = 0;\n\n            while (!activePixels.IsEmpty())\n            {\n                if (m_cancelTask)\n                {\n                    Report.End(\"Canceled Dijkstra\");\n                    return;\n                }\n                var q = activePixels.DeleteMin();\n                inActiveList.Remove(q);\n\n                m_expanded[q] = true;\n                var totalCostQ = totalCost[q];\n\n                foreach (var r in m_neighbors[q])\n                {\n                    if (m_expanded[r]) continue;\n\n                    var gtemp = totalCostQ + m_getCostFunc(m_nodes[q], m_nodes[r]);\n                    var isActive = inActiveList.ContainsKey(r);\n\n                    if (!isActive || gtemp < totalCost[r])\n                    {\n                        if (isActive)\n                            activePixels.DecreaseKey(inActiveList[r], gtemp);\n                        else\n                            inActiveList[r] = activePixels.Insert(gtemp, r);\n\n                        totalCost[r] = gtemp;\n                        m_pointers[r] = q;\n                    }\n                }\n            }\n            Report.End();\n        }\n\n        public List<T> GetMinimalPathByIndex(int endIndex)\n        {\n            var contour = new List<T>();\n            var id = endIndex;\n            var end = m_nodes[id];\n            var seed = m_nodes[m_seedId];\n\n            if (!m_expanded[id])\n                return new List<T>() { end, seed };\n\n            while (id != m_seedId)\n            {\n                contour.Add(m_nodes[id]);\n                id = m_pointers[id];\n            }\n            return contour;\n        }\n\n        public List<T> GetMinimalPath(T end)\n        {\n            var id = m_nodes.IndexOf(end);\n            return GetMinimalPathByIndex(id);\n        }\n    }\n\n    class FibonacciHeap<T>\n    {\n        public class Node\n        {\n            private readonly T _item;\n            private Node _parent;\n            private Node _left;\n            private Node _right;\n            private Node _child;\n            private float _key = 0;\n            private int _degree = 0;\n            private bool _marked = false;\n\n            public Node(float key, T item)\n            {\n                _key = key;\n                _item = item;\n                _left = this;\n                _right = this;\n            }\n\n            public T Value => _item;\n\n            public Node Right\n            {\n                get { return _right; }\n                set\n                {\n                    _right = value;\n                    value._left = this;\n                }\n            }\n\n            public Node Left\n            {\n                get { return _left; }\n                set\n                {\n                    _left = value;\n                    value._right = this;\n                }\n            }\n\n            public Node Parent =>_parent; \n\n            public Node Child => _child; \n\n            public void AddChild(Node node)\n            {\n                _degree++;\n                node._parent = this;\n\n                if (_child == null)\n                    _child = node;\n                else\n                    _child.InsertOneBefore(node);\n            }\n\n            public void RemoveChild(Node node)\n            {\n                if (_child != null)\n                {\n                    if (_degree == 1)\n                    {\n                        _child = null;\n                        _degree = 0;\n                        node._parent = null;\n                    }\n                    else\n                    {\n                        if (_child == node)\n                            _child = _child.Left;\n                        node.Isolate();\n                        _degree--;\n                        node._parent = null;\n                    }\n                }\n            }\n\n            public void RemoveAllChildren()\n            {\n                if (_child != null)\n                {\n                    foreach (var child in _child.AllSiblings)\n                        child._parent = null;\n                    _degree = 0;\n                    _child = null;\n                }\n            }\n\n            public void InsertOneBefore(Node node)\n            {\n                var right = Right;\n                Right = node;\n                right.Left = node;\n            }\n\n            public void InsertGroupBefore(Node node)\n            {\n                var start = node;\n                var end = start.Left;\n\n                var right = Right;\n                Right = start;\n                right.Left = end;\n            }\n\n            public void Isolate()\n            {\n                var left = Left;\n                var right = Right;\n                left.Right = right;\n                Left = this;\n            }\n\n            public float Key\n            {\n                get { return _key; }\n                set { _key = value; }\n            }\n\n            public int Degree => _degree;\n\n            public bool Marked\n            {\n                get { return _marked; }\n                set { _marked = value; }\n            }\n\n            public IEnumerable<Node> GetAllChildren()\n            {\n                if (_child == null)\n                    return Enumerable.Empty<Node>();\n                return _child.AllSiblings;\n            }\n\n            public IEnumerable<Node> AllSiblings\n            {\n                get\n                {\n                    var node = this;\n                    do\n                    {\n                        yield return node;\n                        node = node.Right;\n                    } while (node != this);\n                }\n            }\n\n            public bool HasNoSiblings() => _left == this;\n\n            public bool HasMaxOneSibling() => _left._left == this;\n        }\n\n        private Node _min;\n        private int _n = 0;\n\n        public void Insert(Node node)\n        {\n            if (_min == null)\n            {\n                _min = node;\n            }\n            else\n            {\n                _min.InsertOneBefore(node);\n                if (node.Key < _min.Key)\n                    _min = node;\n            }\n            _n++;\n        }\n\n        public Node Insert(float key, T item)\n        {\n            var node = new Node(key, item);\n            Insert(node);\n            return node;\n        }\n\n        public T GetMin() => _min.Value;\n\n        public T DeleteMin()\n        {\n            var min = _min;\n            if (_min != null)\n            {\n                if (_min.HasNoSiblings() && _min.Degree == 0)\n                {\n                    _min = null;\n                }\n                else\n                {\n                    if (_min.Degree > 0)\n                    {\n                        var child = _min.Child;\n                        _min.RemoveAllChildren();\n\n                        if (!_min.HasNoSiblings())\n                        {\n                            _min.InsertGroupBefore(child);\n                            _min.Isolate();\n                        }\n                        _min = child;\n                    }\n                    else\n                    {\n                        var left = _min.Left;\n                        _min.Isolate();\n                        _min = left;\n                    }\n                    Consolidate();\n                }\n                _n--;\n            }\n            return min.Value;\n        }\n\n        /*private static Node FindMinSibling(Node node)\n        {\n            var minNode = node;\n            foreach (var n in node.AllSiblings)\n            {\n                if (n.Key < minNode.Key)\n                {\n                    minNode = n;\n                }\n            }\n            return minNode;\n        }*/\n\n        public void Delete(Node node)\n        {\n            DecreaseKey(node, int.MinValue);\n            DeleteMin();\n        }\n\n        public void DecreaseKey(Node node, float newKey)\n        {\n            node.Key = newKey;\n\n            if (node.Parent == null)\n            {\n                if (newKey < _min.Key)\n                    _min = node;\n            }\n            else if (node.Key < node.Parent.Key)\n            {\n                var parent = node.Parent;\n                parent.RemoveChild(node);\n                _min.InsertOneBefore(node);\n                if (!parent.Marked)\n                    parent.Marked = true;\n                else\n                {\n                    while (parent.Parent != null && parent.Marked)\n                    {\n                        var pparent = parent.Parent;\n                        pparent.RemoveChild(parent);\n                        _min.InsertOneBefore(parent);\n                        parent.Marked = false;\n                        parent = pparent;\n                    }\n                }\n            }\n        }\n\n        public bool IsEmpty() => _min == null;\n\n        private void Consolidate()\n        {\n            if (_min == null)\n                return;\n\n            var lookup = new Node[2 * (int)(_n.Log() + 1)];\n            var last = _min;\n            var current = _min;\n            var newMin = _min;\n            bool stop = false;\n            do\n            {\n                var next = current.Right;\n                while (lookup[current.Degree] != null)\n                {\n                    var right = current.Right;\n                    var first = current;\n                    var second = lookup[current.Degree];\n\n                    if (second == right && right.Right != first)\n                        right = right.Right;\n\n                    lookup[current.Degree] = null;\n\n                    if (second.Key < first.Key)\n                        Fun.Swap(ref first, ref second);\n\n                    second.Isolate();\n                    first.AddChild(second);\n\n                    current = first;\n                    if (newMin.Key > first.Key || second == newMin)\n                        newMin = first;\n\n                    if (second == last)\n                        stop = true;\n                }\n                lookup[current.Degree] = current;\n                current = next;\n            } while (current != last && !stop);\n            _min = newMin;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/AlgoDat/Span.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public static class SpanPinning\n    {\n        /// <summary>\n        /// Pins a span and performs the given action with the resulting pointer.\n        /// This method is required due to missing support for pinning spans in F#.\n        /// </summary>\n        /// <param name=\"span\">The span to pin.</param>\n        /// <param name=\"action\">The action to perform.</param>\n        /// <returns>The result of the action.</returns>\n        public unsafe static Result Pin<T, Result>(Span<T> span, Func<IntPtr, Result> action) where T : unmanaged\n        {\n            fixed (T* ptr = span)\n            {\n                return action((IntPtr)ptr);\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Delegates/Delegates.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public delegate void ActionValRef<T0, T1>(T0 a0, ref T1 a1);\n    public delegate void ActionRefValVal<T0, T1, T2>(ref T0 a0, T1 a1, T2 a2);\n\n    public static class LambdaApplicationExtensions\n    {\n        public static bool ApplyByType<T, T0>(\n            this T obj, Action<T0> proc0)\n            where T0 : class\n        {\n            if (obj is T0 a0) { proc0(a0); return true; }\n            return false;\n        }\n\n        public static void ApplyByTypeStrict<T, T0>(\n            this T obj, Action<T0> proc0)\n            where T0 : class\n        {\n            if (obj is T0 a0) { proc0(a0); return; }\n            throw new ArgumentException();\n        }\n\n        public static bool ApplyByType<T, T0, T1>(\n            this T obj, Action<T0> proc0, Action<T1> proc1)\n            where T0 : class\n            where T1 : class\n        {\n            if (obj is T0 a0) { proc0(a0); return true; }\n            if (obj is T1 a1) { proc1(a1); return true; }\n            return false;\n        }\n\n        public static void ApplyByTypeStrict<T, T0, T1>(\n            this T obj, Action<T0> proc0, Action<T1> proc1)\n            where T0 : class\n            where T1 : class\n        {\n            if (obj is T0 a0) { proc0(a0); return; }\n            if (obj is T1 a1) { proc1(a1); return; }\n            throw new ArgumentException();\n        }\n\n        public static Tr ApplyByTypeStrict<T, T0, Tr>(\n            this T obj, Func<T0, Tr> fun0)\n            where T0 : class\n        {\n            if (obj is T0 a0) return fun0(a0);\n            throw new ArgumentException();\n        }\n\n        public static Tr ApplyByTypeStrict<T, T0, T1, Tr>(\n            this T obj, Func<T0, Tr> fun0, Func<T1, Tr> fun1)\n            where T0 : class\n            where T1 : class\n        {\n            if (obj is T0 a0) return fun0(a0);\n            if (obj is T1 a1) return fun1(a1);\n            throw new ArgumentException();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Delegates/Delegates_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region RefFunc\n\n    public delegate TRes RefFunc<T0, TRes>\n            (ref T0 a0);\n\n    public delegate TRes RefFunc<T0, T1, TRes>\n            (ref T0 a0, ref T1 a1);\n\n    public delegate TRes RefFunc<T0, T1, T2, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate TRes RefFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n\n    #endregion\n\n    #region FuncOut\n\n    public delegate TRes FuncOut1<T0, TRes>\n            (out T0 a0);\n\n    public delegate TRes FuncOut1<T0, T1, TRes>\n            (T0 a0, out T1 a1);\n\n    public delegate TRes FuncOut1<T0, T1, T2, TRes>\n            (T0 a0, T1 a1, out T2 a2);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, TRes>\n            (T0 a0, T1 a1, T2 a2, out T3 a3);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, out T4 a4);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, out T5 a5);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out T6 a6);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out T7 a7);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out T8 a8);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, out T9 a9);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, out T10 a10);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, out T11 a11);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, out T12 a12);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, out T13 a13);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, out T14 a14);\n\n    public delegate TRes FuncOut1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, out T15 a15);\n\n    public delegate TRes FuncOut2<T0, T1, TRes>\n            (out T0 a0, out T1 a1);\n\n    public delegate TRes FuncOut2<T0, T1, T2, TRes>\n            (T0 a0, out T1 a1, out T2 a2);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, TRes>\n            (T0 a0, T1 a1, out T2 a2, out T3 a3);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, TRes>\n            (T0 a0, T1 a1, T2 a2, out T3 a3, out T4 a4);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, out T4 a4, out T5 a5);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, out T5 a5, out T6 a6);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out T6 a6, out T7 a7);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out T7 a7, out T8 a8);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out T8 a8, out T9 a9);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, out T9 a9, out T10 a10);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, out T10 a10, out T11 a11);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, out T11 a11, out T12 a12);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, out T12 a12, out T13 a13);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, out T13 a13, out T14 a14);\n\n    public delegate TRes FuncOut2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, out T14 a14, out T15 a15);\n\n    public delegate TRes FuncOut3<T0, T1, T2, TRes>\n            (out T0 a0, out T1 a1, out T2 a2);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, TRes>\n            (T0 a0, out T1 a1, out T2 a2, out T3 a3);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, TRes>\n            (T0 a0, T1 a1, out T2 a2, out T3 a3, out T4 a4);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, T1 a1, T2 a2, out T3 a3, out T4 a4, out T5 a5);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, out T4 a4, out T5 a5, out T6 a6);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, out T5 a5, out T6 a6, out T7 a7);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out T6 a6, out T7 a7, out T8 a8);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out T7 a7, out T8 a8, out T9 a9);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out T8 a8, out T9 a9, out T10 a10);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, out T9 a9, out T10 a10, out T11 a11);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, out T10 a10, out T11 a11, out T12 a12);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, out T11 a11, out T12 a12, out T13 a13);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, out T12 a12, out T13 a13, out T14 a14);\n\n    public delegate TRes FuncOut3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, out T13 a13, out T14 a14, out T15 a15);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, TRes>\n            (out T0 a0, out T1 a1, out T2 a2, out T3 a3);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, TRes>\n            (T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14);\n\n    public delegate TRes FuncOut4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, out T12 a12, out T13 a13, out T14 a14, out T15 a15);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, TRes>\n            (out T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14);\n\n    public delegate TRes FuncOut5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14, out T15 a15);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, TRes>\n            (out T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14);\n\n    public delegate TRes FuncOut6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14, out T15 a15);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (out T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14);\n\n    public delegate TRes FuncOut7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14, out T15 a15);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (out T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, out T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, out T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, out T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, out T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, out T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14);\n\n    public delegate TRes FuncOut8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out T8 a8, out T9 a9, out T10 a10, out T11 a11, out T12 a12, out T13 a13, out T14 a14, out T15 a15);\n\n    #endregion\n\n    #region FuncRef\n\n    public delegate TRes FuncRef1<T0, TRes>\n            (ref T0 a0);\n\n    public delegate TRes FuncRef1<T0, T1, TRes>\n            (T0 a0, ref T1 a1);\n\n    public delegate TRes FuncRef1<T0, T1, T2, TRes>\n            (T0 a0, T1 a1, ref T2 a2);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, TRes>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, ref T12 a12);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, ref T13 a13);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, ref T14 a14);\n\n    public delegate TRes FuncRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, ref T15 a15);\n\n    public delegate TRes FuncRef2<T0, T1, TRes>\n            (ref T0 a0, ref T1 a1);\n\n    public delegate TRes FuncRef2<T0, T1, T2, TRes>\n            (T0 a0, ref T1 a1, ref T2 a2);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, TRes>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, TRes>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate TRes FuncRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate TRes FuncRef3<T0, T1, T2, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, TRes>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, TRes>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate TRes FuncRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, TRes>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate TRes FuncRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, TRes>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate TRes FuncRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate TRes FuncRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate TRes FuncRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, TRes>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRes>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRes>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRes>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate TRes FuncRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TRes>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    #endregion\n\n    #region Recursive\n\n    public delegate Func<T0, TRes>\n            Recursive<T0, TRes>\n                    (Recursive<T0, TRes> r);\n\n    public delegate Func<T0, T1, TRes>\n            Recursive<T0, T1, TRes>\n                    (Recursive<T0, T1, TRes> r);\n\n    public delegate Func<T0, T1, T2, TRes>\n            Recursive<T0, T1, T2, TRes>\n                    (Recursive<T0, T1, T2, TRes> r);\n\n    public delegate Func<T0, T1, T2, T3, TRes>\n            Recursive<T0, T1, T2, T3, TRes>\n                    (Recursive<T0, T1, T2, T3, TRes> r);\n\n    #endregion\n\n    #region RefAction\n\n    public delegate void RefAction<T0>\n            (ref T0 a0);\n\n    public delegate void RefAction<T0, T1>\n            (ref T0 a0, ref T1 a1);\n\n    public delegate void RefAction<T0, T1, T2>\n            (ref T0 a0, ref T1 a1, ref T2 a2);\n\n    public delegate void RefAction<T0, T1, T2, T3>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate void RefAction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n\n    #endregion\n\n    #region ActionRef\n\n    public delegate void ActionRef1<T0>\n            (ref T0 a0);\n\n    public delegate void ActionRef1<T0, T1>\n            (T0 a0, ref T1 a1);\n\n    public delegate void ActionRef1<T0, T1, T2>\n            (T0 a0, T1 a1, ref T2 a2);\n\n    public delegate void ActionRef1<T0, T1, T2, T3>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, ref T12 a12);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, ref T13 a13);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, ref T14 a14);\n\n    public delegate void ActionRef1<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14, ref T15 a15);\n\n    public delegate void ActionRef2<T0, T1>\n            (ref T0 a0, ref T1 a1);\n\n    public delegate void ActionRef2<T0, T1, T2>\n            (T0 a0, ref T1 a1, ref T2 a2);\n\n    public delegate void ActionRef2<T0, T1, T2, T3>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate void ActionRef2<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate void ActionRef3<T0, T1, T2>\n            (ref T0 a0, ref T1 a1, ref T2 a2);\n\n    public delegate void ActionRef3<T0, T1, T2, T3>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate void ActionRef3<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate void ActionRef4<T0, T1, T2, T3>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate void ActionRef4<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate void ActionRef5<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate void ActionRef6<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate void ActionRef7<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7>\n            (ref T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n            (T0 a0, ref T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n            (T0 a0, T1 a1, ref T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\n            (T0 a0, T1 a1, T2 a2, ref T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>\n            (T0 a0, T1 a1, T2 a2, T3 a3, ref T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, ref T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, ref T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, ref T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14);\n\n    public delegate void ActionRef8<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>\n            (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, ref T8 a8, ref T9 a9, ref T10 a10, ref T11 a11, ref T12 a12, ref T13 a13, ref T14 a14, ref T15 a15);\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Delegates/Delegates_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    #region RefFunc\n\n    //# for (int c = 1; c < 17; c++) {\n    public delegate TRes RefFunc</*# c.ForEach(i => { */T__i__/*# }, comma); */, TRes>\n            (/*# c.ForEach(i => { */ref T__i__ a__i__/*# }, comma); */);\n\n    //# }\n\n    #endregion\n\n    #region FuncOut\n\n    //# for (int o = 1; o < 9; o++) {\n    //# for (int c = o; c < 17; c++) {\n    public delegate TRes FuncOut__o__</*# c.ForEach(i => { */T__i__/*# }, comma); */, TRes>\n            (/*# c.ForEach(i => { if (i >= c - o) {*/out /*# } */T__i__ a__i__/*# }, comma); */);\n\n    //# }\n    //# }\n    #endregion\n\n    #region FuncRef\n\n    //# for (int r = 1; r < 9; r++) {\n    //# for (int c = r; c < 17; c++) {\n    public delegate TRes FuncRef__r__</*# c.ForEach(i => { */T__i__/*# }, comma); */, TRes>\n            (/*# c.ForEach(i => { if (i >= c - r) {*/ref /*# } */T__i__ a__i__/*# }, comma); */);\n\n    //# }\n    //# }\n    #endregion\n\n    #region Recursive\n\n    //# for (int c = 1; c < 5; c++) {\n    public delegate Func</*# c.ForEach(i => { */T__i__/*# }, comma); */, TRes>\n            Recursive</*# c.ForEach(i => { */T__i__/*# }, comma); */, TRes>\n                    (Recursive</*# c.ForEach(i => { */T__i__/*# }, comma); */, TRes> r);\n\n    //# }\n    #endregion\n\n    #region RefAction\n\n    //# for (int c = 1; c < 17; c++) {\n    public delegate void RefAction</*# c.ForEach(i => { */T__i__/*# }, comma); */>\n            (/*# c.ForEach(i => { */ref T__i__ a__i__/*# }, comma); */);\n\n    //# }\n\n    #endregion\n\n    #region ActionRef\n\n    //# for (int r = 1; r < 9; r++) {\n    //# for (int c = r; c < 17; c++) {\n    public delegate void ActionRef__r__</*# c.ForEach(i => { */T__i__/*# }, comma); */>\n            (/*# c.ForEach(i => { if (i >= c - r) {*/ref /*# } */T__i__ a__i__/*# }, comma); */);\n\n    //# }\n    //# }\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Delegates/HigherOrderFunctions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public class ActionTable<T> : Dict<T, Action>\n    { }\n\n    public static class HighFun\n    {\n        #region IntoFunc\n\n        /// <summary>\n        /// Wrap a value into a function.\n        /// </summary>\n        public static Func<T> IntoFunc<T>(this T x) { return () => x; }\n\n        #endregion\n\n        #region Compose\n\n        /// <summary>\n        /// Fun.Compose(f0, f1) returns f1(f0).\n        /// </summary>\n        public static Func<T0, T2> Compose<T0, T1, T2>(\n                this Func<T0, T1> f0, Func<T1, T2> f1)\n        {\n            return x => f1(f0(x));\n        }\n\n        /// <summary>\n        /// Fun.Compose(f0, f1, f2) returns f2(f1(f0)).\n        /// </summary>\n        public static Func<T0, T3> Compose<T0, T1, T2, T3>(\n                this Func<T0, T1> f0, Func<T1, T2> f1, Func<T2, T3> f2)\n        {\n            return x => f2(f1(f0(x)));\n        }\n\n        /// <summary>\n        /// Fun.Compose(f0, f1, f2, f3) returns f3(f2(f1(f0))).\n        /// </summary>\n        public static Func<T0, T4> Compose<T0, T1, T2, T3, T4>(\n                this Func<T0, T1> f0, Func<T1, T2> f1, Func<T2, T3> f2, Func<T3, T4> f3)\n        {\n            return x => f3(f2(f1(f0(x))));\n        }\n\n        #endregion\n\n        #region Partial Application\n\n        public static Func<TArg1, TResult>\n            ApplyArg0<TArg0, TArg1, TResult>(\n                this Func<TArg0, TArg1, TResult> fun, TArg0 a0)\n        {\n            return a1 => fun(a0, a1);\n        }\n\n        public static Func<TArg0, TResult>\n            ApplyArg1<TArg0, TArg1, TResult>(\n                this Func<TArg0, TArg1, TResult> fun, TArg1 a1)\n        {\n            return a0 => fun(a0, a1);\n        }\n\n        public static Func<TArg1, TArg2, TResult>\n            ApplyArg0<TArg0, TArg1, TArg2, TResult>(\n                this Func<TArg0, TArg1, TArg2, TResult> fun, TArg0 a0)\n        {\n            return (a1, a2) => fun(a0, a1, a2);\n        }\n\n        public static Func<TArg0, TArg2, TResult>\n            ApplyArg1<TArg0, TArg1, TArg2, TResult>(\n                this Func<TArg0, TArg1, TArg2, TResult> fun, TArg1 a1)\n        {\n            return (a0, a2) => fun(a0, a1, a2);\n        }\n\n        public static Func<TArg0, TArg1, TResult>\n            ApplyArg2<TArg0, TArg1, TArg2, TResult>(\n                this Func<TArg0, TArg1, TArg2, TResult> fun, TArg2 a2)\n        {\n            return (a0, a1) => fun(a0, a1, a2);\n        }\n\n        public static Func<TArg2, TResult>\n            ApplyArg0Arg1<TArg0, TArg1, TArg2, TResult>(\n                this Func<TArg0, TArg1, TArg2, TResult> fun, TArg0 a0, TArg1 a1)\n        {\n            return a2 => fun(a0, a1, a2);\n        }\n\n        public static Func<TArg1, TResult>\n            ApplyArg0Arg2<TArg0, TArg1, TArg2, TResult>(\n                this Func<TArg0, TArg1, TArg2, TResult> fun, TArg0 a0, TArg2 a2)\n        {\n            return a1 => fun(a0, a1, a2);\n        }\n\n        public static Func<TArg0, TResult>\n            ApplyArg1Arg2<TArg0, TArg1, TArg2, TResult>(\n                this Func<TArg0, TArg1, TArg2, TResult> fun, TArg1 a1, TArg2 a2)\n        {\n            return a0 => fun(a0, a1, a2);\n        }\n\n        public static Func<TArg1, TArg2, TArg3, TResult>\n            ApplyArg0<TArg0, TArg1, TArg2, TArg3, TResult>(\n                this Func<TArg0, TArg1, TArg2, TArg3, TResult> fun, TArg0 a0)\n        {\n            return (a1, a2, a3) => fun(a0, a1, a2, a3);\n        }\n\n        public static Func<TArg0, TArg2, TArg3, TResult>\n            ApplyArg1<TArg0, TArg1, TArg2, TArg3, TResult>(\n                this Func<TArg0, TArg1, TArg2, TArg3, TResult> fun, TArg1 a1)\n        {\n            return (a0, a2, a3) => fun(a0, a1, a2, a3);\n        }\n\n        public static Func<TArg0, TArg1, TArg3, TResult>\n            ApplyArg2<TArg0, TArg1, TArg2, TArg3, TResult>(\n                this Func<TArg0, TArg1, TArg2, TArg3, TResult> fun, TArg2 a2)\n        {\n            return (a0, a1, a3) => fun(a0, a1, a2, a3);\n        }\n\n        public static Func<TArg0, TArg1, TArg2, TResult>\n            ApplyArg3<TArg0, TArg1, TArg2, TArg3, TResult>(\n                this Func<TArg0, TArg1, TArg2, TArg3, TResult> fun, TArg3 a3)\n        {\n            return (a0, a1, a2) => fun(a0, a1, a2, a3);\n        }\n\n        #endregion\n\n        #region Currying\n\n        public static Func<TArg0, Func<TArg1, TResult>>\n            Curry<TArg0, TArg1, TResult>(\n                this Func<TArg0, TArg1,\n                TResult> fun)\n        {\n            return a0 => a1 => fun(a0, a1);\n        }\n\n        public static Func<TArg0, Func<TArg1, Func<TArg2, TResult>>>\n            Curry<TArg0, TArg1, TArg2, TResult>(\n                this Func<TArg0, TArg1, TArg2,\n                TResult> fun)\n        {\n            return a0 => a1 => a2 => fun(a0, a1, a2);\n        }\n\n        public static Func<TArg0, Func<TArg1,  Func<TArg2, Func<TArg3, TResult>>>>\n            Curry<TArg0, TArg1, TArg2, TArg3, TResult>(\n                this Func<TArg0, TArg1, TArg2, TArg3,\n                TResult> fun)\n        {\n            return a0 => a1 => a2 => a3 => fun(a0, a1, a2, a3);\n        }\n\n        #endregion\n\n        #region FixedPointCombinators\n\n        public static Func<T0, TR> Y<T0, TR>(\n                Func<Func<T0, TR>, Func<T0, TR>> f)\n        {\n            Recursive<T0, TR> rec = r => a0 => f(r(r))(a0);\n            return rec(rec);\n        }\n\n        public static Func<T0, T1, TR> Y<T0, T1, TR>(\n                Func<Func<T0, T1, TR>, Func<T0, T1, TR>> f)\n        {\n            Recursive<T0, T1, TR> rec = r => (a0, a1) => f(r(r))(a0, a1);\n            return rec(rec);\n        }\n\n        public static Func<T0, T1, T2, TR> Y<T0, T1, T2, TR>(\n                Func<Func<T0, T1, T2, TR>, Func<T0, T1, T2, TR>> f)\n        {\n            Recursive<T0, T1, T2, TR> rec\n                = r => (a0, a1, a2) => f(r(r))(a0, a1, a2);\n            return rec(rec);\n        }\n\n        public static Func<T0, T1, T2, T3, TR> Y<T0, T1, T2, T3, TR>(\n                Func<Func<T0, T1, T2, T3, TR>, Func<T0, T1, T2, T3, TR>> f)\n        {\n            Recursive<T0, T1, T2, T3, TR> rec\n                = r => (a0, a1, a2, a3) => f(r(r))(a0, a1, a2, a3);\n            return rec(rec);\n        }\n\n        #endregion\n    }\n\n    public struct FuncOfT2Bool<T>\n    {\n        public Func<T, bool> F { get; private set; }\n\n        public FuncOfT2Bool(Func<T, bool> f)\n            : this()\n        {\n            F = f;\n        }\n\n        public static implicit operator Func<T, bool>(FuncOfT2Bool<T> x)\n        {\n            return x.F;\n        }\n        public static implicit operator FuncOfT2Bool<T>(Func<T, bool> x)\n        {\n            return new FuncOfT2Bool<T>(x);\n        }\n\n        //public static bool operator false(FuncOfT2Bool<T> x)\n        //{\n        //    return false;\n        //}\n        //public static bool operator true(FuncOfT2Bool<T> x)\n        //{\n        //    return true;\n        //}\n\n        public static FuncOfT2Bool<T> operator &(FuncOfT2Bool<T> a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) & b.F(et));\n        }\n        public static FuncOfT2Bool<T> operator |(FuncOfT2Bool<T> a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) | b.F(et));\n        }\n        public static FuncOfT2Bool<T> operator ^(FuncOfT2Bool<T> a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) ^ b.F(et));\n        }\n        public static FuncOfT2Bool<T> operator !(FuncOfT2Bool<T> a)\n        {\n            return new FuncOfT2Bool<T>(et => !a.F(et));\n        }\n        public static FuncOfT2Bool<T> operator ==(FuncOfT2Bool<T> a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) == b.F(et));\n        }\n        public static FuncOfT2Bool<T> operator !=(FuncOfT2Bool<T> a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) != b.F(et));\n        }\n\n        public static FuncOfT2Bool<T> operator &(FuncOfT2Bool<T> a, bool b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) & b);\n        }\n        public static FuncOfT2Bool<T> operator |(FuncOfT2Bool<T> a, bool b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) | b);\n        }\n        public static FuncOfT2Bool<T> operator ^(FuncOfT2Bool<T> a, bool b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) ^ b);\n        }\n        public static FuncOfT2Bool<T> operator ==(FuncOfT2Bool<T> a, bool b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) == b);\n        }\n        public static FuncOfT2Bool<T> operator !=(FuncOfT2Bool<T> a, bool b)\n        {\n            return new FuncOfT2Bool<T>(et => a.F(et) != b);\n        }\n        \n        public static FuncOfT2Bool<T> operator &(bool a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a & b.F(et));\n        }\n        public static FuncOfT2Bool<T> operator |(bool a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a | b.F(et));\n        }\n        public static FuncOfT2Bool<T> operator ^(bool a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a ^ b.F(et));\n        }\n        public static FuncOfT2Bool<T> operator ==(bool a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a == b.F(et));\n        }\n        public static FuncOfT2Bool<T> operator !=(bool a, FuncOfT2Bool<T> b)\n        {\n            return new FuncOfT2Bool<T>(et => a != b.F(et));\n        }\n\n        public override readonly bool Equals(object obj)\n        {\n            return F.Equals(obj);\n        }\n        public override readonly int GetHashCode()\n        {\n            return F.GetHashCode();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/ArrayExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Security.Cryptography;\nusing System.Text;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public static class ArrayFun\n    {\n        #region Generic Array Setting (initialization)\n\n        /// <summary>\n        /// Set all elements to the same supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] Set<T>(this T[] self, T value)\n        {\n#if NET6_0_OR_GREATER\n            Array.Fill(self, value);\n#else\n            var len = self.LongLength;\n            for (int i = 0; i < len; i++) self[i] = value;\n#endif\n            return self;\n        }\n\n        /// <summary>\n        /// Set count elements to the same  supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] Set<T>(this T[] self, long count, T value)\n        {\n            if (count > self.LongLength) count = self.LongLength;\n            for (long i = 0; i < count; i++) self[i] = value;\n            return self;\n        }\n\n        /// <summary>\n        /// Set count elements starting at the supplied index to the same\n        /// supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] Set<T>(\n                this T[] self, long start, long count, T value)\n        {\n            long end = start + Math.Min(count, self.LongLength - start);\n            for (long i = start; i < end; i++) self[i] = value;\n            return self;\n        }\n\n        /// <summary>\n        /// Set all elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] SetByIndex<T>(this T[] self, Func<int, T> index_fun)\n        {\n            int count = self.Length;\n            for (int i = 0; i < count; i++) self[i] = index_fun(i);\n            return self;\n        }\n\n        /// <summary>\n        /// Set all elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] SetByIndexLong<T>(this T[] self, Func<long, T> index_fun)\n        {\n            long count = self.LongLength;\n            for (long i = 0; i < count; i++) self[i] = index_fun(i);\n            return self;\n        }\n\n        /// <summary>\n        /// Set count elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] SetByIndex<T>(\n                this T[] self, int count, Func<int, T> index_fun)\n        {\n            if (count > self.Length) count = self.Length;\n            for (int i = 0; i < count; i++) self[i] = index_fun(i);\n            return self;\n        }\n\n        /// <summary>\n        /// Set count elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] SetByIndexLong<T>(\n                this T[] self, long count, Func<long, T> index_fun)\n        {\n            if (count > self.LongLength) count = self.LongLength;\n            for (long i = 0; i < count; i++) self[i] = index_fun(i);\n            return self;\n        }\n\n        /// <summary>\n        /// Set count elements starting at the supplied index to a function\n        /// of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] SetByIndex<T>(\n                this T[] self, int start, int count, Func<int, T> index_fun)\n        {\n            int end = Math.Min(start + count, self.Length);\n            for (int i = start; i < end; i++) self[i] = index_fun(i);\n            return self;\n        }\n\n        /// <summary>\n        /// Set count elements starting at the supplied index to a function\n        /// of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[] SetByIndexLong<T>(\n                this T[] self, long start, long count, Func<long, T> index_fun)\n        {\n            long end = Math.Min(start + count, self.LongLength);\n            for (long i = start; i < end; i++) self[i] = index_fun(i);\n            return self;\n        }\n\n        /// <summary>\n        /// Set all elements to the elements of the supplied array.\n        /// </summary>\n        public static T[] Set<T>(this T[] self, T[] array)\n        {\n            long len = Math.Min(self.LongLength, array.LongLength);\n            for (long i = 0; i < len; i++) self[i] = array[i];\n            return self;\n        }\n\n        /// <summary>\n        /// Set all elements to the same supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[,] Set<T>(this T[,] self, T value)\n        {\n\n            for (long i = 0; i < self.GetLongLength(0); i++)\n                for (long j = 0; j < self.GetLongLength(1); j++)\n                    self[i, j] = value;\n            return self;\n        }\n\n#endregion\n\n        #region Generic Array Copying\n\n        /// <summary>\n        /// Creates a copy of the array.\n        /// </summary>\n        public static T[] Copy<T>(this T[] array)\n        {\n            var count = array.LongLength;\n            var result = new T[count];\n            Array.Copy(array, result, count);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of the specified length. If the copy is longer\n        /// it is filled with default elements.\n        /// </summary>\n        public static T[] Copy<T>(this T[] array, long count)\n        {\n            var result = new T[count];\n            var len = Math.Min(count, array.LongLength);\n            Array.Copy(array, result, len);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of the specified length. If the copy is longer\n        /// it is filled with default elements.\n        /// </summary>\n        public static T[] Copy<T>(this T[] array, int count)\n        {\n            var result = new T[count];\n            var len = Math.Min(count, array.Length);\n            Array.Copy(array, result, len);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of the specified length starting at the specified\n        /// start. If the copy is longer it is filled with default elements.\n        /// </summary>\n        public static T[] Copy<T>(this T[] array, long start, long count)\n        {\n            var result = new T[count];\n            var len = Math.Min(count, array.LongLength - start);\n            Array.Copy(array, start, result, 0, len);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of the specified length starting at the specified\n        /// start. If the copy is longer it is filled with default elements.\n        /// </summary>\n        public static T[] Copy<T>(this T[] array, int start, int count)\n        {\n            var result = new T[count];\n            var len = Math.Min(count, array.Length - start);\n            Array.Copy(array, start, result, 0, len);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy with the elements piped through a function.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(this T[] array, Func<T, Tr> item_fun)\n        {\n            var len = array.LongLength;\n            var result = new Tr[len];\n            for (var i = 0L; i < len; i++) result[i] = item_fun(array[i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create an array of resulting items by applying a supplied binary function\n        /// to corresponding pairs of the supplied arrays.\n        /// </summary>\n        /// <returns></returns>\n        public static Tr[] Map2<T0, T1, Tr>(\n                this T0[] array0, T1[] array1, Func<T0, T1, Tr> item0_item1_fun)\n        {\n            var len = Min(array0.LongLength, array1.LongLength);\n            var result = new Tr[len];\n            for (var i = 0L; i < len; i++) result[i] = item0_item1_fun(array0[i], array1[i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create an array of resulting items by applying a supplied ternary function\n        /// to corresponding triples of the supplied arrays.\n        /// </summary>\n        /// <returns></returns>\n        public static Tr[] Map3<T0, T1, T2, Tr>(\n                this T0[] array0, T1[] array1, T2[] array2, Func<T0, T1, T2, Tr> item0_item1_item2_fun)\n        {\n            var len = Min(array0.LongLength, Min(array1.LongLength, array2.LongLength));\n            var result = new Tr[len];\n            for (var i = 0L; i < len; i++)\n                result[i] = item0_item1_item2_fun(array0[i], array1[i], array2[i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy with the elements piped through a function.\n        /// The function gets the index of the element as a second argument.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(this T[] array, Func<T, long, Tr> item_index_fun)\n        {\n            var len = array.LongLength;\n            var result = new Tr[len];\n            for (var i = 0L; i < len; i++) result[i] = item_index_fun(array[i], i);\n            return result;\n        }\n\n        public static Tr[] Map2<T0, T1, Tr>(\n                this T0[] array0, T1[] array1, Func<T0, T1, long, Tr> item0_item1_index_fun)\n        {\n            var len = Min(array0.LongLength, array1.LongLength);\n            var result = new Tr[len];\n            for (var i = 0L; i < len; i++)\n                result[i] = item0_item1_index_fun(array0[i], array1[i], i);\n            return result;\n        }\n\n        public static Tr[] Map3<T0, T1, T2, Tr>(\n                this T0[] array0, T1[] array1, T2[] array2,\n                Func<T0, T1, T2, long, Tr> item0_item1_item2_index_fun)\n        {\n            var len = Min(array0.LongLength, Min(array1.LongLength, array2.LongLength));\n            var result = new Tr[len];\n            for (var i = 0L; i < len; i++)\n                result[i] = item0_item1_item2_index_fun(array0[i], array1[i], array2[i], i);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of count elements with the elements piped through a\n        /// function. count may be longer than the array, in this case the\n        /// result array has default elements at the end.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this T[] array, long count, Func<T, Tr> element_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, array.LongLength);\n            for (var i = 0L; i < len; i++) result[i] = element_fun(array[i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of count elements with the elements piped through a\n        /// function. count may be longer than the array, in this case the\n        /// result array has default elements at the end.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this T[] array, int count, Func<T, Tr> element_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, array.Length);\n            for (var i = 0; i < len; i++) result[i] = element_fun(array[i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of count elements with the elements piped through a\n        /// function. count may be longer than the array, in this case the\n        /// result array has default elements at the end.\n        /// The function gets the index of the element as a second argument.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this T[] array, long count, Func<T, long, Tr> element_index_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, array.LongLength);\n            for (var i = 0L; i < len; i++) result[i] = element_index_fun(array[i], i);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of specified length starting at the specified\n        /// offset with the elements piped through a function.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this T[] array, long start, long count, Func<T, Tr> element_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, array.LongLength - start);\n            for (var i = 0L; i < len; i++) result[i] = element_fun(array[start + i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of specified length starting at the specified\n        /// offset with the elements piped through a function.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this T[] array, int start, int count, Func<T, Tr> element_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, array.Length - start);\n            for (var i = 0; i < len; i++) result[i] = element_fun(array[start + i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of specified length starting at the specified\n        /// offset with the elements piped through a function.\n        /// The function gets the target index of the element as a second\n        /// argument.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this T[] array, long start, long count, Func<T, long, Tr> element_index_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, array.LongLength - start);\n            for (var i = 0L; i < len; i++) result[i] = element_index_fun(array[start + i], i);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of specified length starting at the specified\n        /// offset with the elements piped through a function.\n        /// The function gets the target index of the element as a second\n        /// argument.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this T[] array, int start, int count, Func<T, int, Tr> element_index_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, array.Length - start);\n            for (var i = 0; i < len; i++) result[i] = element_index_fun(array[start + i], i);\n            return result;\n        }\n\n        /// <summary>\n        /// Copy a range of elements to the target array.\n        /// </summary>\n        public static void CopyTo<T>(this T[] array, long count, T[] target, long targetStart)\n            => Array.Copy(array, 0, target, targetStart, count);\n\n        /// <summary>\n        /// Copy a range of elements to the target array.\n        /// </summary>\n        public static void CopyTo<T>(this T[] array, int count, T[] target, int targetStart)\n            => Array.Copy(array, 0, target, targetStart, count);\n\n        /// <summary>\n        /// Copy a range of elements to the target array.\n        /// </summary>\n        public static void CopyTo<T>(this T[] array, long start, long count, T[] target, long targetStart)\n            => Array.Copy(array, start, target, targetStart, count);\n\n        /// <summary>\n        /// Copy a range of elements to the target array.\n        /// </summary>\n        public static void CopyTo<T>(this T[] array, int start, int count, T[] target, int targetStart)\n            => Array.Copy(array, start, target, targetStart, count);\n\n        /// <summary>\n        /// Copies the array into a list.\n        /// </summary>\n        public static List<T> CopyToList<T>(this T[] array)\n        {\n            var result = new List<T>(array.Length);\n            result.AddRange(array);\n            return result;\n        }\n\n        public static List<Tr> MapToList<T, Tr>(this T[] array, Func<T, Tr> element_fun)\n        {\n            var count = array.Length;\n            var result = new List<Tr>(count);\n            for (int i = 0; i < count; i++) result.Add(element_fun(array[i]));\n            return result;\n        }\n\n        public static List<Tr> MapToList<T, Tr>(this T[] array, Func<T, long, Tr> item_index_fun)\n        {\n            var count = array.Length;\n            var result = new List<Tr>(count);\n            for (int i = 0; i < count; i++) result.Add(item_index_fun(array[i], i));\n            return result;\n        }\n\n        /// <summary>\n        /// Copies the specified range of elements to the specified destination\n        /// within the same array.\n        /// </summary>\n        public static void CopyRange<T>(this T[] array, long start, long count, long targetStart)\n        {\n            var end = start + count;\n            if (targetStart < start || targetStart >= end)\n            {\n                while (start < end) array[targetStart++] = array[start++];\n            }\n            else\n            {\n                targetStart += count;\n                while (start < end) array[--targetStart] = array[--end];\n            }\n        }\n\n        /// <summary>\n        /// Create a copy with the elements reversed.\n        /// </summary>\n        public static T[] CopyReversed<T>(this T[] array)\n        {\n            var result = new T[array.LongLength];\n            var lastIndex = array.LongLength - 1;\n            for (var i = 0L; i <= lastIndex; i++)\n            {\n                result[i] = array[lastIndex - i];\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Concatenates two arrays.\n        /// </summary>\n        /// <returns>A new array with content of <paramref name=\"first\"/> concatenated with content of <paramref name=\"second\"/>.</returns>\n        public static T[] Concat<T>(this T[] first, T[] second)\n        {\n            var conArray = new T[first.Length + second.Length];\n            first.CopyTo(conArray, 0);\n            second.CopyTo(conArray, first.Length);\n            return conArray;\n        }\n\n        #endregion\n\n        #region Generic Array Operations\n\n        public static long LongSum<T>(this T[] array, Func<T, long> selector)\n        {\n            long sum = 0;\n            for (long i = 0; i < array.LongLength; i++) sum += selector(array[i]);\n            return sum;\n        }\n\n        public static T[] Resized<T>(this T[] array, int newSize)\n        {\n            Array.Resize(ref array, newSize);\n            return array;\n        }\n\n        public static T[] Resized<T>(this T[] array, long newSize)\n        {\n            var resized = new T[newSize];\n            newSize = Math.Min(array.LongLength, newSize);\n            for (long i = 0; i < newSize; i++) resized[i] = array[i];\n            return resized;\n        }\n\n        /// <summary>\n        /// Enumerates the given fraction of the array elements from the\n        /// beginning of the array. E.g. TakeFraction(0.1) would enumerate\n        /// the first 1/10 of the array elements. Fraction must be in range\n        /// [0.0, 1.0].\n        /// </summary>\n        public static IEnumerable<T> TakeFraction<T>(\n                this T[] array, double fraction)\n        {\n            if (fraction < 0.0 || fraction > 1.0)\n                throw new ArgumentOutOfRangeException(\"Fraction not in range [0.0, 1.0].\");\n            long take = (long)(array.LongLength * fraction);\n            for (long i = 0; i < take; i++) yield return array[i];\n        }\n\n        /// <summary>\n        /// Enumerate all but last elements of an array. The number of\n        /// elements to omit is supplied as a parameter and defaults to 1.\n        /// </summary>\n        public static IEnumerable<T> SkipLast<T>(this T[] array, long count = 1)\n        {\n            count = array.LongLength - count;\n            for (long i = 0; i < count; i++) yield return array[i];\n        }\n\n        /// <summary>\n        /// Enumerate all but last elements of an array. The number of\n        /// elements to omit is supplied as a parameter and defaults to 1.\n        /// </summary>\n        public static IEnumerable<T> SkipLast<T>(this T[] array, int count = 1)\n        {\n            return SkipLast(array, (long)count);\n        }\n\n        /// <summary>\n        /// Merges two already sorted arrays.\n        /// </summary>\n        /// <typeparam name=\"T\"></typeparam>\n        /// <param name=\"array\">Sorted array.</param>\n        /// <param name=\"left\">Sorted array.</param>\n        /// <param name=\"right\">Sorted array.</param>\n        /// <param name=\"comparer\"></param>\n        public static void Merge<T>(this T[] array, T[] left, T[] right, Func<T, T, int> comparer)\n        {\n            long li = 0, ri = 0, ti = 0;\n            long lc = left.LongLength, rc = right.LongLength;\n\n            while (li < lc && ri < rc)\n            {\n                if (comparer(left[li], right[ri]) < 0)\n                {\n                    array[ti++] = left[li++];\n                }\n                else\n                {\n                    array[ti++] = right[ri++];\n                }\n            }\n            while (li < lc) array[ti++] = left[li++];\n            while (ri < rc) array[ti++] = right[ri++];\n        }\n\n        private class AComparer<T> : IComparer<T>\n        {\n            public Func<T, T, int> Fun;\n            public int Compare(T x, T y) { return Fun(x, y); }\n        }\n\n        public static int BinarySearch<T>(this T[] self, T item, Func<T, T, int> comparer)\n        {\n            return Array.BinarySearch(self, item, new AComparer<T> { Fun = comparer });\n        }\n\n        public static IEnumerable<T> Elements<T>(\n                this T[] array, long first, long count)\n        {\n            for (long e = first + count; first < e; first++) yield return array[first];\n        }\n\n        public static IEnumerable<T> ElementsWhere<T>(\n                this T[] array, int first, int count, Func<T, bool> predicate)\n        {\n            for (int end = first + count; first < end; first++)\n                if (predicate(array[first])) yield return array[first];\n        }\n\n        public static IEnumerable<T> ElementsWhere<T>(\n                this T[] array, long first, long count, Func<T, bool> predicate)\n        {\n            for (long end = first + count; first < end; first++)\n                if (predicate(array[first])) yield return array[first];\n        }\n\n        #endregion\n\n        #region Generic Array Modifications\n\n        /// <summary>\n        /// Apply the supplied transformation function to each element of the\n        /// array.\n        /// </summary>\n        public static T[] Apply<T>(this T[] self, Func<T, T> element_fun)\n        {\n            long count = self.LongLength;\n            for (long i = 0; i < count; i++) self[i] = element_fun(self[i]);\n            return self;\n        }\n\n        /// <summary>\n        /// Apply the supplied transformation function to the first count\n        /// elements of the array.\n        /// </summary>\n        public static T[] Apply<T>(this T[] self, long count, Func<T, T> element_fun)\n        {\n            if (count > self.LongLength) count = self.LongLength;\n            for (long i = 0; i < count; i++) self[i] = element_fun(self[i]);\n            return self;\n        }\n\n        /// <summary>\n        /// Apply the supplied transformation function to count\n        /// elements of the array, starting at the supplied start index.\n        /// </summary>\n        public static T[] Apply<T>(this T[] self, long start, long count, Func<T, T> element_fun)\n        {\n            var end = Min(start + count, self.LongLength);\n            for (long i = start; i < end; i++) self[i] = element_fun(self[i]);\n            return self;\n        }\n\n        public static T[] Apply<T>(this T[] self, Func<T, long, T> element_index_fun)\n        {\n            long count = self.LongLength;\n            for (long i = 0; i < count; i++) self[i] = element_index_fun(self[i], i);\n            return self;\n        }\n\n        /// <summary>\n        /// Apply the supplied transformation function to the first count\n        /// elements of the array.\n        /// </summary>\n        public static T[] Apply<T>(this T[] self, long count, Func<T, long, T> element_index_fun)\n        {\n            if (count > self.LongLength) count = self.LongLength;\n            for (long i = 0; i < count; i++) self[i] = element_index_fun(self[i], i);\n            return self;\n        }\n\n        /// <summary>\n        /// Apply the supplied transformation function to count\n        /// elements of the array, starting at the supplied start index.\n        /// </summary>\n        public static T[] Apply<T>(this T[] self, long start, long count, Func<T, long, T> element_index_fun)\n        {\n            var end = Min(start + count, self.LongLength);\n            for (long i = start; i < end; i++) self[i] = element_index_fun(self[i], i);\n            return self;\n        }\n\n        /// <summary>\n        /// Move an element from a given source index to a destination index,\n        /// and shift all elements in between by one.\n        /// </summary>\n        public static void Move<T>(\n                this T[] self, long sourceIndex, long targetIndex)\n        {\n            if (sourceIndex == targetIndex) return;\n\n            T help = self[sourceIndex];\n            if (targetIndex > sourceIndex)\n                for (long i = sourceIndex; i < targetIndex; i++) self[i] = self[i + 1];\n            else\n                for (long i = sourceIndex; i > targetIndex; i--) self[i] = self[i - 1];\n            self[targetIndex] = help;\n        }\n\n\n        /// <summary>\n        /// Sets the array items to a mapped version of the items of array0.\n        /// </summary>\n        public static void SetMap<T, T0>(\n                this T[] array, T0[] array0, Func<T0, T> item0_fun)\n        {\n            var count = Min(array.LongLength, array0.LongLength);\n            for (long i = 0; i < count; i++)\n                array[i] = item0_fun(array0[i]);\n        }\n\n        /// <summary>\n        /// Sets the array items to a mapped version of corresponding\n        /// pairs of items of array0 and array1.\n        /// </summary>\n        public static void SetMap2<T, T0, T1>(\n                this T[] array, T0[] array0, T1[] array1,\n                Func<T0, T1, T> item0_item1_fun)\n        {\n            var count = Min(array.LongLength, Min(array0.LongLength, array1.LongLength));\n            for (long i = 0; i < count; i++)\n                array[i] = item0_item1_fun(array0[i], array1[i]);\n        }\n\n        /// <summary>\n        /// Sets the array items to a mapped version of corresponding\n        /// triples of  items of array0, array1, and array2.\n        /// </summary>\n        public static void SetMap3<T, T0, T1, T2>(\n                this T[] array, T0[] array0, T1[] array1, T2[] array2,\n                Func<T0, T1, T2, T> item0_item1_item2_fun)\n        {\n            var count = Min(\n                Min(array.LongLength, array0.LongLength),\n                Min(array1.LongLength, array2.LongLength)\n                );\n            for (long i = 0; i < count; i++)\n                array[i] = item0_item1_item2_fun(array0[i], array1[i], array2[i]);\n        }\n\n        /// <summary>\n        /// Swap the two elements specified by their indices.\n        /// </summary>\n        public static void Swap<T>(this T[] self, int i, int j)\n        {\n            T help = self[i]; self[i] = self[j]; self[j] = help;\n        }\n\n        /// <summary>\n        /// Swap the two elements specified by their indices.\n        /// </summary>\n        public static void Swap<T>(this T[] self, long i, long j)\n        {\n            T help = self[i]; self[i] = self[j]; self[j] = help;\n        }\n\n        /// <summary>\n        /// Reverse the order of elements in the supplied range [lo, hi[.\n        /// </summary>\n        public static void ReverseRange<T>(\n                this T[] a, long lo, long hi)\n        {\n            hi--;\n            while (lo < hi) { var t = a[lo]; a[lo++] = a[hi]; a[hi--] = t; }\n        }\n\n        public static void Revert<T>(this T[] array)\n        {\n            array.ReverseRange(0, array.LongLength);\n        }\n\n        /// <summary>\n        /// Returns a copy of the array with the specified item replaced.\n        /// </summary>\n        public static T[] With<T>(this T[] array, int index, T item)\n        {\n            if (array == null)\n            {\n                array = new T[index + 1];\n                array[index] = item;\n                return array;\n            }\n            var len = array.LongLength;\n            if (index < len) { array[index] = item; return array; }\n            var newArray = new T[index + 1];\n            for (long i = 0; i < len; i++) newArray[i] = array[i];\n            newArray[index] = item;\n            return newArray;\n        }\n\n        /// <summary>\n        /// Synonym for WithAppended().\n        /// </summary>\n        public static T[] WithAdded<T>(this T[] array, T item)\n            where T : class\n        {\n            return array.WithAppended(item);\n        }\n\n        /// <summary>\n        /// Returns a copy of the array with the specified item appended\n        /// at the end. If the item is already contained in the array,\n        /// the original array is returned.\n        /// </summary>\n        public static T[] WithAppended<T>(this T[] array, T item)\n            where T : class\n        {\n            if (array == null) return new T[] { item };\n            var len = array.Length;\n            for (int i = 0; i < len; i++) if (array[i] == item) return array;\n            var newArray = new T[len + 1];\n            for (int i = 0; i < len; i++) newArray[i] = array[i];\n            newArray[len] = item;\n            return newArray;\n        }\n\n        /// <summary>\n        /// Returns a copy of the array with the specified item prepended\n        /// to the front. If the item is already contained in the array,\n        /// the original array is returned.\n        /// </summary>\n        public static T[] WithPrepended<T>(this T[] array, T item)\n            where T : class\n        {\n            if (array == null) return new T[] { item };\n            var len = array.Length;\n            for (int i = 0; i < len; i++) if (array[i] == item) return array;\n            var newArray = new T[len + 1];\n            for (int i = 0; i < len; i++) newArray[i+1] = array[i];\n            newArray[0] = item;\n            return newArray;\n        }\n\n        /// <summary>\n        /// Returns a copy of the item with the specified item removed. If the\n        /// item is not contained in the array, the original array is returned.\n        /// </summary>\n        public static T[] WithRemoved<T>(this T[] array, T item)\n            where T : class\n        {\n            if (array == null) return array;\n            var len = array.Length;\n            if (len == 1)\n            {\n                if (array[0] == item) return null;\n            }\n            else\n            {\n                for (int i = 0; i < len; i++)\n                    if (array[i] == item)\n                    {\n                        var newArray = new T[len - 1];\n                        for (int j = 0; j < i; j++) newArray[j] = array[j];\n                        for (int j = i; j < len - 1; j++) newArray[j] = array[j + 1];\n                        return newArray;\n                    }\n            }\n            return array;\n        }\n\n\n        #endregion\n\n        #region Generic Array Functional Programming Standard Operations\n\n        /// <summary>\n        /// Performs an aggregation of all items in an array with the\n        /// supplied aggregation function starting from the left and with the\n        /// supplied seed, and returns the aggregated result.\n        /// </summary>\n        public static TSum FoldLeft<TVal, TSum>(\n                this TVal[] array, TSum seed, Func<TSum, TVal, TSum> sum_item_fun)\n        {\n            long count = array.LongLength;\n            for (long i = 0; i < count; i++)\n                seed = sum_item_fun(seed, array[i]);\n            return seed;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all corresponding pairs of items of\n        /// the supplied arrays with the supplied aggregation function\n        /// starting from the left and with the  supplied seed, and returns\n        /// the aggregated result.\n        /// </summary>\n        public static TSum FoldLeft2<T0, T1, TSum>(\n                this T0[] array0, T1[] array1,\n                TSum seed, Func<TSum, T0, T1, TSum> sum_item0_item1_fun)\n        {\n            long count = Min(array0.LongLength, array1.LongLength);\n            for (long i = 0; i < count; i++)\n                seed = sum_item0_item1_fun(seed, array0[i], array1[i]);\n            return seed;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all corresponding triples of items of\n        /// the supplied arrays with the supplied aggregation function\n        /// starting from the left and with the  supplied seed, and returns\n        /// the aggregated result.\n        /// </summary>\n        public static TSum FoldLeft3<T0, T1, T2, TSum>(\n                this T0[] array0, T1[] array1, T2[] array2,\n                TSum seed, Func<TSum, T0, T1, T2, TSum> sum_item0_item1_item2_fun)\n        {\n            long count = Min(array0.LongLength, Min(array1.LongLength, array2.LongLength));\n            for (long i = 0; i < count; i++)\n                seed = sum_item0_item1_item2_fun(seed, array0[i], array1[i], array2[i]);\n            return seed;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all items in an array with the\n        /// supplied aggregation function starting from the right and with the\n        /// supplied seed, and returns the aggregated result.\n        /// </summary>\n        public static TSum FoldRight<TVal, TSum>(\n                this TVal[] array, Func<TVal, TSum, TSum> item_sum_fun, TSum seed)\n        {\n            long count = array.LongLength;\n            for (long i = count - 1; i >= 0; i--)\n                seed = item_sum_fun(array[i], seed);\n            return seed;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all corresponding pairs of items of\n        /// the supplied arrays with the supplied aggregation function\n        /// starting from the rigth and with the  supplied seed, and returns\n        /// the aggregated result.\n        /// </summary>\n        public static TSum FoldRight2<T0, T1, TSum>(\n                this T0[] array0, T1[] array1,\n                Func<T0, T1, TSum, TSum> item0_item1_sum_fun, TSum seed)\n        {\n            long count = Min(array0.LongLength, array1.LongLength);\n            for (long i = count - 1; i >= 0; i--)\n                seed = item0_item1_sum_fun(array0[i], array1[i], seed);\n            return seed;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all corresponding triples of items of\n        /// the supplied arrays with the supplied aggregation function\n        /// starting from the rigth and with the  supplied seed, and returns\n        /// the aggregated result.\n        /// </summary>\n        public static TSum FoldRight3<T0, T1, T2, TSum>(\n                this T0[] array0, T1[] array1, T2[] array2,\n                Func<T0, T1, T2, TSum, TSum> item0_item1_item2_sum_fun, TSum seed)\n        {\n            long count = Min(array0.LongLength, Min(array1.LongLength, array2.LongLength));\n            for (long i = count - 1; i >= 0; i--)\n                seed = item0_item1_item2_sum_fun(array0[i], array1[i], array2[i], seed);\n            return seed;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of the specified slice of items in an\n        /// array with the supplied aggregation function starting from the\n        /// left and with the initial supplied left sum, and returns the\n        /// aggregated result.\n        /// </summary>\n        public static TSum FoldLeft<TVal, TSum>(\n                this TVal[] array, long start, long count,\n                TSum seed, Func<TSum, TVal, TSum> sum_item_fun)\n        {\n            for (long i = start, e = start + count; i < e; i++)\n                seed = sum_item_fun(seed, array[i]);\n            return seed;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of the specified slice of items in an\n        /// array with the supplied aggregation function starting from the\n        /// right and with the initial supplied right sum, and returns the\n        /// aggregated result.\n        /// </summary>\n        public static TSum FoldRight<TVal, TSum>(\n                this TVal[] array, long start, long count,\n                Func<TVal, TSum, TSum> item_sum_fun, TSum seed)\n        {\n            for (long i = start + count - 1; i >= start; i--)\n                seed = item_sum_fun(array[i], seed);\n            return seed;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all elements in an array with the\n        /// supplied aggregation function starting from the left and with the\n        /// initial supplied left sum.\n        /// All intermediate results are returned as an array with the same\n        /// length as the original.\n        /// </summary>\n        public static TSum[] ScanLeft<TVal, TSum>(\n                this TVal[] array, TSum leftSum, Func<TSum, TVal, TSum> sum_val_addFun)\n        {\n            long count = array.LongLength;\n            var result = new TSum[count];\n            for (long i = 0; i < count; i++)\n            {\n                leftSum = sum_val_addFun(leftSum, array[i]);\n                result[i] = leftSum;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all elements in an array with the\n        /// supplied aggregation function starting from the left and with the\n        /// initial supplied left sum.\n        /// All intermediate results are returned as an array with the same\n        /// length as the original.\n        /// </summary>\n        public static TSum[] ScanLeft<TVal, TSum>(\n            this TVal[] array, TSum leftSum, Func<TSum, TVal, long, TSum> sum_val_index_addFun)\n        {\n            long count = array.LongLength;\n            var result = new TSum[count];\n            for (long i = 0; i < count; i++)\n            {\n                leftSum = sum_val_index_addFun(leftSum, array[i], i);\n                result[i] = leftSum;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all elements in an array with the\n        /// supplied aggregation function starting from the right and with the\n        /// initial supplied right sum.\n        /// All intermediate results are returned as an array with the same\n        /// length as the original.\n        /// </summary>\n        public static TSum[] ScanRight<TVal, TSum>(\n                this TVal[] array, Func<TVal, TSum, TSum> val_sum_addFun, TSum rightSum)\n        {\n            long count = array.LongLength;\n            var result = new TSum[count];\n            for (long i = count - 1; i >= 0; i--)\n            {\n                rightSum = val_sum_addFun(array[i], rightSum);\n                result[i] = rightSum;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of all elements in an array with the\n        /// supplied aggregation function starting from the right and with the\n        /// initial supplied right sum.\n        /// All intermediate results are returned as an array with the same\n        /// length as the original.\n        /// </summary>\n        public static TSum[] ScanRight<TVal, TSum>(\n            this TVal[] array, Func<TVal, long, TSum, TSum> val_index_sum_addFun, TSum rightSum)\n        {\n            long count = array.LongLength;\n            var result = new TSum[count];\n            for (long i = count - 1; i >= 0; i--)\n            {\n                rightSum = val_index_sum_addFun(array[i], i, rightSum);\n                result[i] = rightSum;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of the specified slice of elements in an\n        /// array with the supplied aggregation function starting from the\n        /// left and with the initial supplied left sum.\n        /// All intermediate results are returned as an array with the given\n        /// count as length.\n        /// </summary>\n        public static TSum[] ScanLeft<TVal, TSum>(\n                this TVal[] array, long start, long count,\n                TSum leftSum, Func<TSum, TVal, TSum> sum_val_addFun)\n        {\n            var result = new TSum[count];\n            for (long i = 0; i < count; i++)\n            {\n                leftSum = sum_val_addFun(leftSum, array[start + i]);\n                result[i] = leftSum;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of the specified slice of elements in an\n        /// array with the supplied aggregation function starting from the\n        /// left and with the initial supplied left sum.\n        /// All intermediate results are returned as an array with the given\n        /// count as length.\n        /// </summary>\n        public static TSum[] ScanLeft<TVal, TSum>(\n            this TVal[] array, long start, long count,\n            TSum leftSum, Func<TSum, TVal, long, TSum> sum_val_index_addFun)\n        {\n            var result = new TSum[count];\n            for (long i = 0; i < count; i++)\n            {\n                leftSum = sum_val_index_addFun(leftSum, array[start + i], start + i);\n                result[i] = leftSum;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of the specified slice of elements in an\n        /// array with the supplied aggregation function starting from the\n        /// right and with the initial supplied right sum.\n        /// All intermediate results are returned as an array with the given\n        /// count as length.\n        /// </summary>\n        public static TSum[] ScanRight<TVal, TSum>(\n                this TVal[] array, long start, long count,\n                Func<TVal, TSum, TSum> val_sum_addFun, TSum rightSum)\n        {\n            var result = new TSum[count];\n            for (long i = count - 1; i >= 0; i--)\n            {\n                rightSum = val_sum_addFun(array[start + i], rightSum);\n                result[i] = rightSum;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Performs an aggregation of the specified slice of elements in an\n        /// array with the supplied aggregation function starting from the\n        /// right and with the initial supplied right sum.\n        /// All intermediate results are returned as an array with the given\n        /// count as length.\n        /// </summary>\n        public static TSum[] ScanRight<TVal, TSum>(\n            this TVal[] array, long start, long count,\n            Func<TVal, long, TSum, TSum> val_index_sum_addFun, TSum rightSum)\n        {\n            var result = new TSum[count];\n            for (long i = count - 1; i >= 0; i--)\n            {\n                rightSum = val_index_sum_addFun(array[start + i], start + i, rightSum);\n                result[i] = rightSum;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Apply the supplied mulFun to the first count corresponding pairs\n        /// of elements from the supplied arrays. Aggregate the results\n        /// starting with the supplied seed and the supplied addFun.\n        /// </summary>\n        public static TSum InnerProduct<T1, T2, TMul, TSum>(\n                this T1[] array, T2[] other, long count,\n                Func<T1, T2, TMul> mulFun,\n                TSum seed, Func<TSum, TMul, TSum> addFun)\n        {\n            if (array == null) throw new ArgumentException(\"array must be != null\");\n            if (count > Math.Min(array.LongLength, other.LongLength))\n                throw new ArgumentException(\"count must be smaller than minimum of array lengths\");\n            for (long i = 0; i < count; i++)\n                seed = addFun(seed, mulFun(array[i], other[i]));\n            return seed;\n        }\n\n        /// <summary>\n        /// Apply the supplied mulFun to the first count corresponding pairs\n        /// of elements from the supplied arrays. Aggregate the results\n        /// starting with the supplied seed and the supplied addFun.\n        /// </summary>\n        public static TSum InnerProduct<T1, T2, TMul, TSum>(\n                this T1[] array, T2[] other, long count,\n                Func<T1, T2, TMul> mulFun,\n                TSum seed, Func<TSum, TMul, TSum> addFun,\n                Func<TSum, bool> sum_exitIfTrueFun)\n        {\n            if (array == null) throw new ArgumentException(\"array must be != null\");\n            if (count > Min(array.LongLength, other.LongLength))\n                throw new ArgumentException(\"count must be smaller than minimum of array lengths\");\n            for (long i = 0; i < count; i++)\n            {\n                seed = addFun(seed, mulFun(array[i], other[i]));\n                if (sum_exitIfTrueFun(seed)) break;\n            }\n            return seed;\n        }\n\n        /// <summary>\n        /// Apply the supplied productFun to corresponding pairs of elements\n        /// from supplied arrays. Aggregate the results starting with the\n        /// supplied seed and the supplied sumFun.\n        /// </summary>\n        public static TSum InnerProduct<T1, T2, TProduct, TSum>(\n                this T1[] array0, T2[] array1,\n                Func<T1, T2, TProduct> item0_item1_productFun,\n                TSum seed, Func<TSum, TProduct, TSum> sum_product_sumFun)\n        {\n            return InnerProduct(array0, array1,\n                                Math.Min(array0.LongLength, array1.LongLength),\n                                item0_item1_productFun, seed, sum_product_sumFun);\n        }\n\n        /// <summary>\n        /// Apply the supplied productFun to corresponding pairs of elements\n        /// from supplied arrays. Aggregate the results starting with the\n        /// supplied seed and the supplied sumFun.\n        /// </summary>\n        public static TSum InnerProduct<T1, T2, TProduct, TSum>(\n                this T1[] array0, T2[] array1,\n                Func<T1, T2, TProduct> item0_item1_productFun,\n                TSum seed, Func<TSum, TProduct, TSum> sum_product_sumFun,\n                Func<TSum, bool> sum_exitIfTrueFun)\n        {\n            return InnerProduct(array0, array1,\n                                Math.Min(array0.LongLength, array1.LongLength),\n                                item0_item1_productFun, seed, sum_product_sumFun, sum_exitIfTrueFun);\n        }\n\n        public static TProduct[] ProductArray<T0, T1, TProduct>(\n                this T0[] array0, T1[] array1,\n                Func<T0, T1, TProduct> item0_item1_productFun)\n        {\n            return ProductArray(array0, array1, Math.Min(array0.LongLength, array1.LongLength),\n                                item0_item1_productFun);\n        }\n\n        public static TProduct[] ProductArray<T0, T1, TProduct>(\n                this T0[] array0, T1[] array1, long count,\n                Func<T0, T1, TProduct> item0_item1_productFun)\n        {\n            var result = new TProduct[count];\n            for (long i = 0; i < count; i++)\n                result[i] = item0_item1_productFun(array0[i], array1[i]);\n            return result;\n        }\n\n        public static TProduct[] ProductArray<T0, T1, TProduct>(\n                this T0[] array0, T1[] array1,\n                Func<T0, T1, long, TProduct> item0_item1_index_productFun)\n        {\n            return ProductArray(array0, array1, Math.Min(array0.LongLength, array1.LongLength),\n                                item0_item1_index_productFun);\n        }\n\n        public static TProduct[] ProductArray<T0, T1, TProduct>(\n                this T0[] array0, T1[] array1, long count,\n                Func<T0, T1, long, TProduct> item0_item1_index_productFun)\n        {\n            var result = new TProduct[count];\n            for (long i = 0; i < count; i++)\n                result[i] = item0_item1_index_productFun(array0[i], array1[i], i);\n            return result;\n        }\n\n        public static bool AllEqual<T0, T1>(\n                this T0[] array0, T1[] array1, Func<T0, T1, bool> item0_item1_equalFun)\n        {\n            var len = array0.LongLength;\n            return len == array1.LongLength\n                    && array0.InnerProduct(array1, len, item0_item1_equalFun,\n                                           true, (s, p) => s && p, s => !s);\n        }\n\n        #endregion\n\n        #region Generic Jagged Array Operations\n\n        /// <summary>\n        /// Use this instead of Clone() or Copy() in order to get a full copy of the jagged array back.\n        /// </summary>\n        public static T[][] JaggedCopy<T>(this T[][] array)\n        {\n            long count = array.LongLength;\n            var result = new T[count][];\n            for (long i = 0; i < count; i++) result[i] = array[i].Copy();\n            return result;\n        }\n\n        public static T[][][] JaggedCopy<T>(this T[][][] array)\n        {\n            long count = array.LongLength;\n            var result = new T[count][][];\n            for (long i = 0; i < count; i++) result[i] = array[i].JaggedCopy();\n            return result;\n        }\n\n        public static long FlatCount<T>(this T[][] array)\n        {\n            return array.LongSum(a => a.LongLength);\n        }\n\n        public static long FlatCount<T>(this T[][][] array)\n        {\n            return array.LongSum(a => a.LongSum(b => b.LongLength));\n        }\n\n        public static void FlatCopyTo<T>(this T[][] array, T[] target, long start)\n        {\n            for (long j = 0; j < array.LongLength; j++)\n            {\n                var aj = array[j];\n                for (long i = 0; i < aj.LongLength; i++)\n                    target[start++] = aj[i];\n            }\n        }\n\n        public static void FlatCopyTo<T>(this T[][][] array, T[] target, long start)\n        {\n            for (long k = 0; k < array.LongLength; k++)\n            {\n                var ak = array[k];\n                for (long j = 0; j < ak.LongLength; j++)\n                {\n                    var akj = ak[j];\n                    for (long i = 0; i < akj.LongLength; i++)\n                        target[start++] = akj[i];\n                }\n            }\n        }\n\n        public static T[] FlatCopy<T>(this T[][] array)\n        {\n            var result = new T[array.FlatCount()];\n            array.FlatCopyTo(result, 0);\n            return result;\n        }\n\n        public static T[] FlatCopy<T>(this T[][][] array)\n        {\n            var result = new T[array.FlatCount()];\n            array.FlatCopyTo(result, 0);\n            return result;\n        }\n\n        #endregion\n\n        #region Mapped Copy Functions\n\n        public static int ForwardMapAdd(\n            this int[] forwardMap, int index, ref int forwardCount)\n        {\n            int newIndex = forwardMap[index];\n            if (newIndex < 0) forwardMap[index] = newIndex = forwardCount++;\n            return newIndex;\n        }\n\n        static public int ForwardMapAdd(\n            this int[] forwardMap, int forwardCount,\n            int[] indexArray, int indexCount)\n        {\n            for (int i = 0; i < indexCount; i++)\n            {\n                int index = indexArray[i];\n                if (forwardMap[index] < 0)\n                    forwardMap[index] = forwardCount++;\n            }\n            return forwardCount;\n        }\n\n        /// <summary>\n        /// Copies from this array into the target array starting at the\n        /// supplied offset and using the supplied forward map that\n        /// specifies the new index for each element. The forward map\n        /// may contain negative values for elements to be skipped.\n        /// </summary>\n        public static void ForwardMappedCopyTo<T>(\n            this T[] sourceArray,\n            T[] targetArray,\n            int[] forwardMap,\n            int offset)\n        {\n            for (int i = 0; i < forwardMap.Length; i++)\n            {\n                int ni = forwardMap[i];\n                if (ni >= 0) targetArray[ni + offset] = sourceArray[i];\n            }\n        }\n\n        /// <summary>\n        /// Copies from this array into the target array starting at the\n        /// supplied offset using the supplied backward map that contains\n        /// the source index for each index of the target array.\n        /// </summary>\n        public static void BackMappedCopyTo<T>(\n                this T[] source, T[] target, int[] backMap, int offset)\n        {\n            int count = backMap.Length;\n            for (int i = 0; i < count; i++)\n                target[i + offset] = source[backMap[i]];\n        }\n\n        public static void BackMappedGroupCopyTo<T>(\n                this T[] source, int[] groupBackMap, int groupCount,\n                int[] fia, T[] target, int start)\n        {\n\n            for (int gi = 0; gi < groupCount; gi++)\n            {\n                int ogi = groupBackMap[gi]; if (ogi < 0) continue;\n                for (int ogei = fia[ogi], ogee = fia[ogi + 1]; ogei < ogee; ogei++)\n                    target[start++] = source[ogei];\n            }\n        }\n\n        public static void BackMappedGroupCopyTo(\n                this int[] source, int[] groupBackMap, int groupCount,\n                int[] fia, int[] elementForwardMap, int[] target, int start)\n        {\n            for (int gi = 0; gi < groupCount; gi++)\n            {\n                int ogi = groupBackMap[gi]; if (ogi < 0) continue;\n                for (int ogei = fia[ogi], ogee = fia[ogi + 1]; ogei < ogee; ogei++)\n                    target[start++] = elementForwardMap[source[ogei]];\n            }\n        }\n\n        /// <summary>\n        /// Copies from this array into the target array starting at the\n        /// supplied offset using the supplied backward map that contains\n        /// the source index for each index of the target array.\n        /// </summary>\n        public static void BackMappedCopyTo<T>(\n                this T[] source, T[] target, long[] backMap, long offset)\n        {\n            long count = backMap.LongLength;\n            for (long i = 0; i < count; i++)\n                target[i + offset] = source[backMap[i]];\n        }\n\n        /// <summary>\n        /// Returns a copy of this array by placing each element at a new\n        /// position specified by the supplied forward map. The forward map\n        /// may contain negative values for elements that should not be\n        /// copied. The length of the result is computed to hold all forward\n        /// mapped elements of the soruce array.\n        /// </summary>\n        public static T[] ForwardMappedCopy<T>(\n                this T[] sourceArray, int[] forwardMap)\n        {\n            return sourceArray.ForwardMappedCopy(forwardMap, forwardMap.Max() + 1);\n        }\n\n        /// <summary>\n        /// Returns a copy of this array by placing each element at a new\n        /// position specified by the supplied forward map. The forward map\n        /// may contain negative values for elements that should not be\n        /// copied. The length of the result needs to be supplied as\n        /// a parameter.\n        /// </summary>\n        public static T[] ForwardMappedCopy<T>(\n                this T[] sourceArray, int[] forwardMap, int targetLength)\n        {\n            T[] targetArray = new T[targetLength];\n            sourceArray.ForwardMappedCopyTo(targetArray, forwardMap, 0);\n            return targetArray;\n        }\n\n        /// <summary>\n        /// Returns a copy of this array that is created by copying the\n        /// elements at the positions specified in the supplied backward\n        /// map. An optional count argument is used for the size of the\n        /// resulting array.\n        /// </summary>\n        public static T[] BackMappedCopy<T>(\n                this T[] array, int[] backMap, int count = 0)\n        {\n            if (count <= 0) count = backMap.Length;\n            var target = new T[count];\n            count = Min(backMap.Length, count);\n            for (int i = 0; i < count; i++) target[i] = array[backMap[i]];\n            return target;\n        }\n\n        /// <summary>\n        /// Returns a copy of this array that is created by copying the\n        /// elements at the positions specified in the supplied backward\n        /// map. An optional count argument is used for the size of the\n        /// resulting array.\n        /// </summary>\n        public static T[] BackMappedCopySafe<T>(\n                this T[] array, int[] backMap, T defaultValue, int count = 0)\n        {\n            if (count <= 0) count = backMap.Length;\n            var target = new T[count].Set(defaultValue);\n            count = Min(backMap.Length, count);\n            for (int i = 0; i < count; i++)\n            {\n                var ti = backMap[i]; if (ti < 0) continue;\n                target[i] = array[ti];\n            }\n            return target;\n        }\n\n        /// <summary>\n        /// Returns a copy of this array that is created by copying the\n        /// elements at the positions specified in the supplied backward\n        /// map and applying a function to each element. An optional\n        /// count argument is used for the size of the resulting array.\n        /// </summary>\n        public static Tr[] BackMappedCopy<T, Tr>(\n                this T[] array, int[] backMap, Func<T, Tr> fun, int count = 0)\n        {\n            if (count <= 0) count = backMap.Length;\n            var target = new Tr[count];\n            count = Min(backMap.Length, count);\n            for (int i = 0; i < count; i++) target[i] = fun(array[backMap[i]]);\n            return target;\n        }\n\n        /// <summary>\n        /// Returns a copy of this array that is created by copying the\n        /// elements at the positions specified in the supplied backward\n        /// map. An optional count argument is used for the size of the\n        /// resulting array.\n        /// </summary>\n        public static T[] BackMappedCopy<T>(\n                this T[] array, long[] backMap, long count = 0)\n        {\n            if (count <= 0) count = backMap.LongLength;\n            var target = new T[count];\n            count = Min(backMap.Length, count);\n            for (long i = 0; i < count; i++) target[i] = array[backMap[i]];\n            return target;\n        }\n\n        /// <summary>\n        /// Returns a copy of this array that is created by copying the\n        /// elements at the positions specified in the supplied backward\n        /// map and applying a function to each element. An optional\n        /// count argument is used for the size of the resulting array.\n        /// </summary>\n        public static Tr[] BackMappedCopy<T, Tr>(\n                this T[] array, long[] backMap, Func<T, Tr> fun, long count = 0)\n        {\n            if (count <= 0) count = backMap.LongLength;\n            var target = new Tr[count];\n            count = Min(backMap.Length, count);\n            for (long i = 0; i < count; i++) target[i] = fun(array[backMap[i]]);\n            return target;\n        }\n\n        /// <summary>\n        /// Returns a copy of this array that is created by copying the\n        /// elements at the positions specified in the index array of the\n        /// supplied backward map. If the index array is null only the\n        /// backward map is used to compute the position. An optional count\n        /// argument is used for the size of the resulting array.\n        /// </summary>\n        public static T[] BackMappedCopy<T>(\n                this  T[] array, int[] indexArray, int[] backMap, int count = 0)\n        {\n            if (indexArray == null) return array.BackMappedCopy(backMap, count);\n            if (count <= 0) count = backMap.Length;\n            var target = new T[count];\n            count = Min(backMap.Length, count);\n            for (int i = 0; i < count; i++) target[i] = array[indexArray[backMap[i]]];\n            return target;\n        }\n\n        /// <summary>\n        /// Returns a copy of this array that is created by copying the\n        /// elements at the positions specified in the index array of the\n        /// supplied backward map and applying a function to each element.\n        /// If the index array is null only the backward map is used to\n        /// compute the position. An optional count argument is used for\n        /// the size of the resulting array.\n        /// </summary>\n        public static Tr[] BackMappedCopy<T, Tr>(\n                this T[] array, int[] indexArray, int[] backMap,\n                Func<T, Tr> fun, int count = 0)\n        {\n            if (indexArray == null) return array.BackMappedCopy(backMap, fun, count);\n            if (count <= 0) count = backMap.Length;\n            var target = new Tr[count];\n            count = Min(backMap.Length, count);\n            for (int i = 0; i < count; i++) target[i] = fun(array[indexArray[backMap[i]]]);\n            return target;\n        }\n\n        /// <summary>\n        /// Copies all source arrays into this array, using the supplied\n        /// array of forward maps.\n        /// </summary>\n        /// <returns>targetArray</returns>\n        public static T[] ForwardMappedCopyFrom<T>(\n                this T[] targetArray,\n                T[][] sourceArrays,\n                int[][] forwardMaps)\n        {\n            var offset = 0;\n            for (int i = 0; i < sourceArrays.Length; i++)\n            {\n                sourceArrays[i].ForwardMappedCopyTo(\n                                    targetArray, forwardMaps[i], offset);\n                offset += forwardMaps[i].Max() + 1;\n            }\n            return targetArray;\n        }\n\n        /// <summary>\n        /// copies all srcArrays into this array\n        /// indexed by an inversed indexMap\n        /// returns itself\n        /// </summary>\n        public static T[] BackMappedCopyFrom<T>(\n                this T[] targetArray,\n                T[][] sourceArrays,\n                int[][] backwardMaps)\n        {\n            int offset = 0;\n            int count = sourceArrays.Length;\n            for (int i = 0; i < count; i++)\n            {\n                sourceArrays[i].BackMappedCopyTo(\n                                    targetArray, backwardMaps[i], offset);\n                offset += backwardMaps[i].Length;\n            }\n            return targetArray;\n        }\n\n        /// <summary>\n        /// copies this indexArray to destinationIndexArray\n        /// over iaIndexMap at position diaOffset\n        /// and returns aIndexMap for\n        /// copying the arrays that are indexed by sourceIndexArray\n        /// !! destinationIndexArray has to be initialized with -1\n        /// </summary>\n        public static int[] ForwardMappedCopyIndexArrayTo(\n                this int[] sourceArray,\n                int[] targetArray,\n                int[] forwardMap,\n                int targetOffset)\n        {\n            int count = forwardMap.Max() + 1;\n            int targetIndexOffset = targetArray.Max() + 1;\n\n            // creating destinationIndexArray, still indexing sourceArray\n            sourceArray.ForwardMappedCopyTo(\n                            targetArray, forwardMap, targetOffset);\n\n            var indexMap = new int[sourceArray.Max() + 1].Set(-1);\n            var indexCount = 0;\n            for (var ti = targetOffset; ti < targetOffset + count; ti++)\n            {\n                var oldIndex = targetArray[ti];\n                // creating indexMap\n                var newIndex = indexMap[oldIndex];\n                if (newIndex == -1)\n                    indexMap[oldIndex] = newIndex = indexCount++;\n                // reindexing targetArray\n                targetArray[ti] = newIndex + targetIndexOffset;\n            }\n\n            return indexMap;\n        }\n\n        /// <summary>\n        /// Copies this index array to the target array over iaIndexMap at\n        /// position diaOffset and returns aIndexMap for\n        /// copying the arrays that are indexed by sourceIndexArray\n        /// !! destinationIndexArray has to be initialized with -1\n        /// </summary>\n        public static int[] BackMappedCopyIndexArrayTo(\n                this int[] sourceArray,\n                int[] targetArray,\n                int[] backwardMap,\n                int targetOffest)\n        {\n            int count = backwardMap.Length;\n            int targetIndexOffset = targetArray.Max() + 1;\n\n            // creating targetArray, still indexing sourceArray\n            sourceArray.BackMappedCopyTo(\n                            targetArray, backwardMap, targetOffest);\n\n            var indexMap = new int[sourceArray.Max() + 1].Set(-1);\n            var indexCount = 0;\n            for (var ti = targetOffest; ti < targetOffest + count; ti++)\n            {\n                var oldIndex = targetArray[ti];\n                // creating indexMap\n                var newIndex = indexMap[oldIndex];\n                if (newIndex == -1)\n                    indexMap[oldIndex] = newIndex = indexCount++;\n                // reindexing targetArray\n                targetArray[ti] = newIndex + targetIndexOffset;\n            }\n\n            return indexMap;\n        }\n\n        /// <summary>\n        /// copies from this indexArray to destinationIndexArray\n        /// over iaIndexMap\n        /// and returns aIndexMap for\n        /// copying the arrays that are indexed by sourceIndexArray\n        /// </summary>\n        public static int[] ForwardMappedCopyIndexArrayTo(\n                this int[] sourceArray,\n                out int[] targetArray,\n                int[] forwardMap)\n        {\n            targetArray = new int[forwardMap.Max() + 1].Set(-1);\n            return sourceArray.ForwardMappedCopyIndexArrayTo(\n                targetArray, forwardMap, 0);\n        }\n\n        /// <summary>\n        /// copies from this indexArray to destinationIndexArray\n        /// over iaIndexMap\n        /// and returns aIndexMap for\n        /// copying the arrays that are indexed by sourceIndexArray\n        /// </summary>\n        public static int[] BackMappedCopyIndexArrayTo(\n                this int[] sourceArray,\n                out int[] targetArray,\n                int[] backwardMap)\n        {\n            targetArray = new int[backwardMap.Length].Set(-1);\n            return sourceArray.BackMappedCopyIndexArrayTo(\n                targetArray, backwardMap, 0);\n        }\n\n        /// <summary>\n        /// copies all srcIndexArrays to this indexArray\n        /// over iaIndexMaps\n        /// and returns aIndexMaps for\n        /// copying the arrays that are indexed by srcIndexArrays\n        /// </summary>\n        public static int[][] ForwardMappedCopyFromIndexArrays(\n                this int[] targetArray,\n                int[][] sourceArrays,\n                int[][] forwardMaps)\n        {\n            var count = sourceArrays.Length;\n            var indexMaps = new int[count][];\n            var offset = 0;\n            for (int i = 0; i < count; i++)\n            {\n                indexMaps[i] = sourceArrays[i]\n                                .ForwardMappedCopyIndexArrayTo(\n                                    targetArray, forwardMaps[i], offset);\n                offset += forwardMaps[i].Max() + 1;\n            }\n            return indexMaps;\n        }\n\n        /// <summary>\n        /// copies all srcIndexArrays to this indexArray\n        /// over iaIndexMaps\n        /// and returns aIndexMaps for\n        /// copying the arrays that are indexed by srcIndexArrays\n        /// </summary>\n        public static int[][] BackMappedCopyFromIndexArrays(\n                this int[] targetArray,\n                int[][] sourceArrays,\n                int[][] backwardMaps)\n        {\n            var count = sourceArrays.Length;\n            var indexMaps = new int[count][];\n            var offset = 0;\n            for (int i = 0; i < count; i++)\n            {\n                indexMaps[i] = sourceArrays[i]\n                                .BackMappedCopyIndexArrayTo(\n                                    targetArray, backwardMaps[i], offset);\n                offset += backwardMaps[i].Length;\n            }\n            return indexMaps;\n        }\n\n        public static void ReverseGroups<T>(\n                this T[] array, int[] groupFirstIndices, int groupCount,\n                Func<int, bool> reverseMap)\n        {\n            for (int gvi = groupFirstIndices[0], fi = 0; fi < groupCount; fi++)\n            {\n                int gve = groupFirstIndices[fi + 1];\n                if (reverseMap(fi))\n                    for (int rfvi = gve - 1; gvi < rfvi; gvi++, rfvi--)\n                        array.Swap(gvi, rfvi);\n                gvi = gve;\n            }\n        }\n\n\n        /// <summary>\n        /// Return an array with reversed groups. The specified first group\n        /// indices array defines which consecutive elements constitute a\n        /// group, and the reverse map function specifies wich of these\n        /// groups should actually be reversed.\n        /// </summary>\n        public static T[] GroupReversedCopy<T>(\n                this T[] array, int[] groupFirstIndices, int groupCount,\n                Func<int, bool> reverseMap)\n        {\n            var result = new T[array.Length];\n            for (int gvi = groupFirstIndices[0], gi = 0; gi < groupCount; gi++)\n            {\n                int gve = groupFirstIndices[gi + 1];\n                if (reverseMap(gi))\n                    for (int rgvi = gve; gvi < gve; gvi++)\n                        result[--rgvi] = array[gvi];\n                else\n                    for (; gvi < gve; gvi++) result[gvi] = array[gvi];\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creating Backward Maps\n\n        /// <summary>\n        /// returns the inverse of the given indexMap\n        /// (be carefull with inversing inversedIndexMaps => can be to short!\n        /// fix if needed: use inverseIndexMap(int[] indexMap, int size) instead)\n        /// </summary>\n        public static int[] CreateBackMap(\n                this int[] forwardMap)\n        {\n            return CreateBackMap(forwardMap, forwardMap.Max() + 1);\n        }\n\n        public static int[] CreateBackToFirstMap(\n                this int[] forwardMap, int resultLength)\n        {\n            var backMap = new int[resultLength].Set(-1);\n            var count = forwardMap.Length;\n            for (int i = 0; i < count; i++)\n            {\n                int ni = forwardMap[i]; if (ni < 0) continue;\n                if (backMap[ni] < 0) backMap[ni] = i;\n            }\n            return backMap;\n        }\n\n        /// <summary>\n        /// returns the backward map in the given size of the given forward map\n        /// </summary>\n        public static int[] CreateBackMap(\n                this int[] forwardMap, int resultLength)\n        {\n            var backMap = new int[resultLength].Set(-1);\n            var count = forwardMap.Length;\n            for (int i = 0; i < count; i++)\n            {\n                int ni = forwardMap[i]; if (ni < 0) continue;\n                backMap[ni] = i;\n            }\n            return backMap;\n        }\n\n        public static int[] CreateBackMap(\n                this int[] forwardMap, int resultLength, int offset)\n        {\n            var backMap = new int[resultLength];\n            var count = forwardMap.Length;\n            for (int i = 0; i < count; i++)\n            {\n                int ni = forwardMap[i]; if (ni < 0) continue;\n                backMap[ni - offset] = i;\n            }\n            return backMap;\n        }\n\n        #endregion\n\n        #region Integration\n\n        /// <summary>\n        /// Converts an array that contains the number of elements\n        /// at each index into an array that holds the indices of\n        /// the first element if the elements are stored in\n        /// consecutive order. Returns the sum of all elements.\n        /// Using double precision during integration.\n        /// </summary>\n        public static double Integrate(this float[] array, double sum = 0)\n        {\n            for (long i = 0; i < array.LongLength; i++)\n            {\n                var delta = array[i]; array[i] = (float)sum; sum += delta;\n            }\n            return sum;\n        }\n\n        /// <summary>\n        /// Converts an array that contains the number of elements\n        /// at each index into an array that holds the indices of\n        /// the first element if the elements are stored in\n        /// consecutive order. Returns the sum of all elements.\n        /// Using single precision during integration.\n        /// </summary>\n        public static float Integrate(this float[] array, float sum = 0)\n        {\n            for (long i = 0; i < array.LongLength; i++)\n            {\n                var delta = array[i]; array[i] = sum; sum += delta;\n            }\n            return sum;\n        }\n\n        /// <summary>\n        /// Converts an array that contains the number of elements\n        /// at each index into an array that holds the indices of\n        /// the first element if the elements are stored in\n        /// consecutive order. Returns the sum of all elements.\n        /// </summary>\n        public static int Integrate(this int[] array, int sum = 0)\n        {\n            for (long i = 0; i < array.LongLength; i++)\n            {\n                var delta = array[i]; array[i] = sum; sum += delta;\n            }\n            return sum;\n        }\n\n        /// <summary>\n        /// Converts an array that contains the number of elements\n        /// at each index into an array that holds the indices of\n        /// the first element if the elements are stored in\n        /// consecutive order. Returns the sum of all elements.\n        /// </summary>\n        public static long Integrate(this long[] array, long sum = 0)\n        {\n            for (long i = 0; i < array.LongLength; i++)\n            {\n                var delta = array[i]; array[i] = sum; sum += delta;\n            }\n            return sum;\n        }\n\n        /// <summary>\n        /// Integrates the array and returns the sum. Note that the\n        /// value of the starting element will be the supplied initial\n        /// sum value after the operation.\n        /// </summary>\n        public static double Integrate(this double[] array, double sum = 0.0)\n        {\n            for (long i = 0; i < array.LongLength; i++)\n            {\n                var value = array[i]; array[i] = sum; sum += value;\n            }\n            return sum;\n        }\n\n        /// <summary>\n        /// Creates an array that contains the integrated sum up to each element of input array.\n        /// The length of the integrated array is +1 of the input array and contains the total\n        /// sum in the last element.\n        /// Using double precision during integration.\n        /// </summary>\n        public static float[] Integrated(this float[] array, double sum = 0)\n        {\n            var integrated = new float[array.Length + 1];\n            integrated[0] = (float)sum;\n            for (long i = 0; i < array.LongLength;)\n            {\n                sum += array[i];\n                integrated[++i] = (float)sum;\n            }\n            return integrated;\n        }\n\n        /// <summary>\n        /// Creates an array that contains the integrated sum up to each element of input array.\n        /// The length of the integrated array is +1 of the input array and contains the total\n        /// sum in the last element.\n        /// Using single precision during integration.\n        /// </summary>\n        public static float[] Integrated(this float[] array, float sum = 0)\n        {\n            var integrated = new float[array.Length + 1];\n            integrated[0] = sum;\n            for (long i = 0; i < array.LongLength;)\n            {\n                sum += array[i];\n                integrated[++i] = sum;\n            }\n            return integrated;\n        }\n\n        /// <summary>\n        /// Creates an array that contains the integrated sum up to each element of input array.\n        /// The length of the integrated array is +1 of the input array and contains the total\n        /// sum in the last element.\n        /// </summary>\n        public static int[] Integrated(this int[] array, int sum = 0)\n        {\n            var integrated = new int[array.Length + 1];\n            integrated[0] = sum;\n            for (long i = 0; i < array.LongLength;)\n            {\n                sum += array[i];\n                integrated[++i] = sum;\n            }\n            return integrated;\n        }\n\n        /// <summary>\n        /// Creates an array that contains the integrated sum up to each element of input array.\n        /// The length of the integrated array is +1 of the input array and contains the total\n        /// sum in the last element.\n        /// </summary>\n        public static long[] Integrated(this long[] array, long sum = 0)\n        {\n            var integrated = new long[array.Length + 1];\n            integrated[0] = sum;\n            for (long i = 0; i < array.LongLength;)\n            {\n                sum += array[i];\n                integrated[++i] = sum;\n            }\n            return integrated;\n        }\n\n        /// <summary>\n        /// Creates an array that contains the integrated sum up to each element of input array.\n        /// The length of the integrated array is +1 of the input array and contains the total\n        /// sum in the last element.\n        /// </summary>\n        public static double[] Integrated(this double[] array, double sum = 0)\n        {\n            var integrated = new double[array.Length + 1];\n            integrated[0] = sum;\n            for (long i = 0; i < array.LongLength;)\n            {\n                sum += array[i];\n                integrated[++i] = sum;\n            }\n            return integrated;\n        }\n\n        #endregion\n\n        #region Dense Forward Maps\n\n        /// <summary>\n        /// Count the indices in an index array that are actually used.\n        /// </summary>\n        static public int DenseCount(\n                this int[] indexArray, int indexCount, int maxIndex)\n        {\n            int[] forwardMap = new int[maxIndex].Set(-1);\n            return forwardMap.ForwardMapAdd(0, indexArray, indexCount);\n        }\n\n        /// <summary>\n        /// Create a forward map from an index array that contains new\n        /// indices in such a way, that no index is unused.\n        /// </summary>\n        static public int[] DenseForwardMap(\n                this int[] indexArray, int indexCount,\n                int maxIndex, out int denseCount)\n        {\n            int[] forwardMap = new int[maxIndex].Set(-1);\n            denseCount = forwardMap.ForwardMapAdd(\n                            0, indexArray, indexCount);\n            return forwardMap;\n        }\n\n        public static int[] DenseForwardMap(\n                this int[] indexArray,\n                int[] groupSelectionArray,\n                int groupSize,\n                out int denseCount)\n        {\n            int count = 0;\n            int[] forwardMap = new int[indexArray.Length].Set(-1);\n            for (int gi = 0; gi < groupSelectionArray.Length; gi++)\n            {\n                int g = groupSelectionArray[gi] * groupSize;\n                for (int i = g; i < g + groupSize; i++)\n                {\n                    int index = indexArray[i];\n                    if (forwardMap[index] < 0)\n                        forwardMap[index] = count++;\n                }\n            }\n            denseCount = count;\n            return forwardMap;\n        }\n\n        #endregion\n\n        #region Comparable Array\n\n        public static T[] MergeSorted<T>(this T[] a0, T[] a1)\n            where T : IComparable<T>\n        {\n            int count0 = a0.Length;\n            int count1 = a1.Length;\n            var a = new T[count0 + count1];\n            int i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0].CompareTo(a1[i1]) < 0)\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        public static int IndexOfMin<T>(this T[] a)\n            where T : IComparable<T>\n        {\n            int index = 0;\n            T min = a[0];\n            for (int i = 1; i < a.Length; i++)\n                if (a[i].CompareTo(min) < 0) { min = a[i]; index = i; }\n            return index;\n        }\n\n        public static int IndexOfMin<T>(this T[] a, int start, int count)\n            where T : IComparable<T>\n        {\n            int index = start;\n            T min = a[start];\n            for (int i = start + 1, e = start + count; i < e; i++)\n                if (a[i].CompareTo(min) < 0) { min = a[i]; index = i; }\n            return index;\n        }\n\n        public static int IndexOfMax<T>(this T[] a)\n            where T : IComparable<T>\n        {\n            int index = 0;\n            T max = a[0];\n            for (int i = 1; i < a.Length; i++)\n                if (a[i].CompareTo(max) > 0) { max = a[i]; index = i; }\n            return index;\n        }\n\n        public static int IndexOfMax<T>(this T[] a, int start, int count)\n            where T : IComparable<T>\n        {\n            int index = start;\n            T max = a[start];\n            for (int i = start + 1, e = start + count; i < e; i++)\n                if (a[i].CompareTo(max) > 0) { max = a[i]; index = i; }\n            return index;\n        }\n\n        public static int IndexOfMin<T>(this T[] a, Func<T, T, int> compare)\n        {\n            int index = 0;\n            T min = a[0];\n            for (int i = 1; i < a.Length; i++)\n                if (compare(a[i], min) < 0) { min = a[i]; index = i; }\n            return index;\n        }\n\n        public static int IndexOfMax<T>(this T[] a, Func<T, T, int> compare)\n        {\n            int index = 0;\n            T max = a[0];\n            for (int i = 1; i < a.Length; i++)\n                if (compare(a[i], max) > 0) { max = a[i]; index = i; }\n            return index;\n        }\n\n        public static long LongIndexOfMin<T>(this T[] a)\n            where T : IComparable<T>\n        {\n            long index = 0;\n            T min = a[0];\n            for (long i = 1; i < a.LongLength; i++)\n                if (a[i].CompareTo(min) < 0) { min = a[i]; index = i; }\n            return index;\n        }\n\n        public static long LongIndexOfMax<T>(this T[] a)\n            where T : IComparable<T>\n        {\n            long index = 0;\n            T max = a[0];\n            for (long i = 1; i < a.LongLength; i++)\n                if (a[i].CompareTo(max) > 0) { max = a[i]; index = i; }\n            return index;\n        }\n\n        public static long LongIndexOfMin<T>(this T[] a, Func<T, T, int> compare)\n        {\n            long index = 0;\n            T min = a[0];\n            for (long i = 1; i < a.LongLength; i++)\n                if (compare(a[i], min) < 0) { min = a[i]; index = i; }\n            return index;\n        }\n\n        public static long LongIndexOfMax<T>(this T[] a, Func<T, T, int> compare)\n        {\n            long index = 0;\n            T max = a[0];\n            for (long i = 1; i < a.LongLength; i++)\n                if (compare(a[i], max) > 0) { max = a[i]; index = i; }\n            return index;\n        }\n\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        /// <summary>\n        /// Set all elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[,] SetByIndex<T>(this T[,] self, Func<int, int, T> fun)\n        {\n            int count0 = self.GetLength(0);\n            int count1 = self.GetLength(1);\n            for (int i0 = 0; i0 < count0; i0++)\n                for (int i1 = 0; i1 < count1; i1++)\n                    self[i0, i1] = fun(i0, i1);\n            return self;\n        }\n\n        /// <summary>\n        /// Set all elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[,] SetByIndexLong<T>(this T[,] self, Func<long, long, T> fun)\n        {\n            long count0 = self.GetLongLength(0);\n            long count1 = self.GetLongLength(1);\n            for (long i0 = 0; i0 < count0; i0++)\n                for (long i1 = 0; i1 < count1; i1++)\n                    self[i0, i1] = fun(i0, i1);\n            return self;\n        }\n\n        /// <summary>\n        /// Set all elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[, ,] SetByIndex<T>(this T[, ,] self, Func<int, int, int, T> fun)\n        {\n            int count0 = self.GetLength(0);\n            int count1 = self.GetLength(1);\n            int count2 = self.GetLength(2);\n            for (int i0 = 0; i0 < count0; i0++)\n                for (int i1 = 0; i1 < count1; i1++)\n                    for (int i2 = 0; i2 < count2; i2++)\n                        self[i0, i1, i2] = fun(i0, i1, i2);\n            return self;\n        }\n\n        /// <summary>\n        /// Set all elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static T[, ,] SetByIndexLong<T>(this T[, ,] self, Func<long, long, long, T> fun)\n        {\n            long count0 = self.GetLongLength(0);\n            long count1 = self.GetLongLength(1);\n            long count2 = self.GetLongLength(2);\n            for (long i0 = 0; i0 < count0; i0++)\n                for (long i1 = 0; i1 < count1; i1++)\n                    for (long i2 = 0; i2 < count2; i2++)\n                        self[i0, i1, i2] = fun(i0, i1, i2);\n            return self;\n        }\n\n        #endregion\n\n        #region Memcopy\n\n        /// <summary>\n        /// Copies the specified part of an array to the target-pointer.\n        /// NOTE: May cause AccessViolationException if the target-pointer\n        ///       is not sufficiently allocated.\n        /// </summary>\n        /// <param name=\"input\">The input Array</param>\n        /// <param name=\"offset\">The start index for copying</param>\n        /// <param name=\"length\">The number of elements to copy</param>\n        /// <param name=\"target\">The target pointer</param>\n        public static void CopyTo(this Array input, int offset, int length, IntPtr target)\n        {\n            var gc = GCHandle.Alloc(input, GCHandleType.Pinned);\n\n            try\n            {\n                var typeSize = input.GetType().GetElementType().GetCLRSize();\n                var dataSize = length * typeSize;\n\n                unsafe\n                {\n                    var src = gc.AddrOfPinnedObject() + offset * typeSize;\n                    Buffer.MemoryCopy(src.ToPointer(), target.ToPointer(), dataSize, dataSize);\n                };\n\n            }\n            finally\n            {\n                gc.Free();\n            }\n        }\n\n        public static void CopyTo(this Array input, int length, IntPtr target)\n            => CopyTo(input, 0, length, target);\n\n        public static void CopyTo(this Array input, IntPtr target)\n            => CopyTo(input, 0, input.Length, target);\n\n        public static void CopyTo(this IntPtr input, Array target, int offset, int length)\n        {\n            var gc = GCHandle.Alloc(target, GCHandleType.Pinned);\n\n            try\n            {\n                var typeSize = target.GetType().GetElementType().GetCLRSize();\n                var dataSize = length * typeSize;\n\n                unsafe\n                {\n                    var dst = gc.AddrOfPinnedObject() + offset * typeSize;\n                    Buffer.MemoryCopy(input.ToPointer(), dst.ToPointer(), dataSize, dataSize);\n                };\n            }\n            finally\n            {\n                gc.Free();\n            }\n        }\n\n        public static void CopyTo(this IntPtr input, Array target, int length)\n            => CopyTo(input, target, 0, length);\n\n        public static void CopyTo(this IntPtr input, Array target)\n            => CopyTo(input, target, target.Length);\n\n        public static void CopyTo(this IntPtr input, IntPtr target, int size)\n        {\n            unsafe\n            {\n                Buffer.MemoryCopy(input.ToPointer(), target.ToPointer(), size, size);\n            };\n        }\n\n#if NET6_0_OR_GREATER\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Span<byte> AsByteSpan(this Array data)\n        {\n            var elementSize = data.GetType().GetElementType().GetCLRSize();\n            var span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetArrayDataReference(data), data.Length * elementSize);\n            return span;\n        }\n#endif\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Span<byte> AsByteSpan<T>(this T[] data) where T : struct\n        {\n            return MemoryMarshal.AsBytes(data.AsSpan());\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ReadOnlySpan<byte> AsByteSpan(this string data)\n        {\n            return MemoryMarshal.AsBytes(data.AsSpan());\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Span<TTo> AsCastSpan<TFrom, TTo>(this TFrom[] arr)\n            where TFrom : struct\n            where TTo : struct\n        {\n            return MemoryMarshal.Cast<TFrom, TTo>(arr.AsSpan());\n        }\n\n        internal static unsafe T UseAsStream<T>(this Array data, Func<UnmanagedMemoryStream, T> action)\n        {\n            var gc = GCHandle.Alloc(data, GCHandleType.Pinned);\n            var l = data.GetType().GetElementType().GetCLRSize() * data.Length;\n            try\n            {\n                using var stream = new UnmanagedMemoryStream(((byte*)gc.AddrOfPinnedObject())!, l, l, FileAccess.Read);\n                return action(stream);\n            }\n            finally\n            {\n                gc.Free();\n            }\n        }\n\n        internal static unsafe void UseAsStream(this Array data, Action<UnmanagedMemoryStream> action)\n        {\n            var gc = GCHandle.Alloc(data, GCHandleType.Pinned);\n            var l = data.GetType().GetElementType().GetCLRSize() * data.Length;\n            try\n            {\n                using var stream = new UnmanagedMemoryStream(((byte*)gc.AddrOfPinnedObject())!, l, l, FileAccess.Read);\n                action(stream);\n            }\n            finally\n            {\n                gc.Free();\n            }\n        }\n\n\n        #endregion\n\n        #region Hashes\n\n        #region MD5\n\n        /// <summary>\n        /// Computes the MD5 hash of the data array.\n        /// </summary>\n        /// <returns>128bit/16byte data hash</returns>\n        public static byte[] ComputeMD5Hash(this byte[] data)\n        {\n#if NET6_0_OR_GREATER\n            return MD5.HashData(data);\n#else\n            using var md5 = MD5.Create();\n            return md5.ComputeHash(data);\n#endif\n        }\n\n        /// <summary>\n        /// Computes the MD5 hash of the data array.\n        /// </summary>\n        /// <returns>128bit/16byte data hash</returns>\n        public static byte[] ComputeMD5Hash(this Array data)\n        {\n#if NET6_0_OR_GREATER\n            return MD5.HashData(data.AsByteSpan());\n#else\n            using var md5 = MD5.Create();\n            return data.UseAsStream((stream) => md5.ComputeHash(stream));\n#endif\n        }\n\n        /// <summary>\n        /// Computes the MD5 hash of the data array.\n        /// </summary>\n        /// <returns>128bit/16byte data hash</returns>\n        public static byte[] ComputeMD5Hash<T>(this T[] data) where T : struct\n#if NET6_0_OR_GREATER\n            => MD5.HashData(data.AsByteSpan());\n#else\n            => ((Array)data).ComputeMD5Hash();\n#endif\n\n        /// <summary>\n        /// Computes the MD5 hash of the given string.\n        /// <returns>128bit/16byte data hash</returns>\n        /// </summary>\n        public static byte[] ComputeMD5Hash(this string s)\n        {\n#if NET6_0_OR_GREATER\n            return MD5.HashData(s.AsByteSpan());\n#else\n            return Encoding.Unicode.GetBytes(s).ComputeMD5Hash();\n#endif\n        }\n\n        #endregion\n\n        #region SHA1\n\n        /// <summary>\n        /// Computes the SHA1 hash of the data array.\n        /// </summary>\n        /// <returns>160bit/20byte data hash</returns>\n        public static byte[] ComputeSHA1Hash(this byte[] data)\n        {\n#if NET6_0_OR_GREATER\n            return SHA1.HashData(data);\n#else\n            using var sha = SHA1.Create();\n            var hash = sha.ComputeHash(data);\n            return hash;\n#endif\n        }\n\n        /// <summary>\n        /// Computes the SHA1 hash of the data array.\n        /// </summary>\n        /// <returns>160bit/20byte data hash</returns>\n        public static byte[] ComputeSHA1Hash(this Array data)\n        {\n#if NET6_0_OR_GREATER\n            return SHA1.HashData(data.AsByteSpan());\n#else\n            using var sha = SHA1.Create();\n            return data.UseAsStream((stream) => sha.ComputeHash(stream));\n#endif\n        }\n\n        /// <summary>\n        /// Computes the SHA1 hash of the data array.\n        /// </summary>\n        /// <returns>160bit/20byte data hash</returns>\n        public static byte[] ComputeSHA1Hash<T>(this T[] data) where T : struct\n#if NET6_0_OR_GREATER\n            => SHA1.HashData(data.AsByteSpan());\n#else\n            => ((Array)data).ComputeSHA1Hash();\n#endif\n\n        /// <summary>\n        /// Computes the SHA1 hash of the given string.\n        /// <returns>160bit/20byte data hash</returns>\n        /// </summary>\n        public static byte[] ComputeSHA1Hash(this string s)\n        {\n#if NET6_0_OR_GREATER\n            return SHA1.HashData(s.AsByteSpan());\n#else\n            return Encoding.Unicode.GetBytes(s).ComputeSHA1Hash();\n#endif\n        }\n\n        #endregion\n\n        #region SHA256\n\n        /// <summary>\n        /// Computes the SHA256 hash of the data array.\n        /// </summary>\n        /// <returns>256bit/32byte data hash</returns>\n        public static byte[] ComputeSHA256Hash(this byte[] data)\n        {\n#if NET6_0_OR_GREATER\n            return SHA256.HashData(data);\n#else\n            using var sha = SHA256.Create();\n            var hash = sha.ComputeHash(data);\n            return hash;\n#endif\n        }\n\n        /// <summary>\n        /// Computes the SHA256 hash of the data array.\n        /// </summary>\n        /// <returns>256bit/32byte data hash</returns>\n        public static byte[] ComputeSHA256Hash(this Array data)\n        {\n#if NET6_0_OR_GREATER\n            return SHA256.HashData(data.AsByteSpan());\n#else\n            using var sha = SHA256.Create();\n            return data.UseAsStream((stream) => sha.ComputeHash(stream));\n#endif\n        }\n\n        /// <summary>\n        /// Computes the SHA256 hash of the data array.\n        /// </summary>\n        /// <returns>256bit/32byte data hash</returns>\n        public static byte[] ComputeSHA256Hash<T>(this T[] data) where T : struct\n#if NET6_0_OR_GREATER\n            => SHA256.HashData(data.AsByteSpan());\n#else\n            => ((Array)data).ComputeSHA256Hash();\n#endif\n\n        /// <summary>\n        /// Computes the SHA256 hash of the given string.\n        /// </summary>\n        /// <returns>256bit/32byte data hash</returns>\n        public static byte[] ComputeSHA256Hash(this string s)\n        {\n#if NET6_0_OR_GREATER\n            return SHA256.HashData(s.AsByteSpan());\n#else\n            return Encoding.Unicode.GetBytes(s).ComputeSHA256Hash();\n#endif\n        }\n\n        #endregion\n\n        #region SHA512\n\n        /// <summary>\n        /// Computes the SHA512 hash of the data array.\n        /// </summary>\n        /// <returns>512bit/64byte data hash</returns>\n        public static byte[] ComputeSHA512Hash(this byte[] data)\n        {\n#if NET6_0_OR_GREATER\n            return SHA512.HashData(data);\n#else\n            using var sha = SHA512.Create();\n            var hash = sha.ComputeHash(data);\n            return hash;\n#endif\n        }\n\n        /// <summary>\n        /// Computes the SHA512 hash of the data array.\n        /// </summary>\n        /// <returns>512bit/64byte data hash</returns>\n        public static byte[] ComputeSHA512Hash(this Array data)\n        {\n#if NET6_0_OR_GREATER\n            return SHA512.HashData(data.AsByteSpan());\n#else\n            using var sha = SHA512.Create();\n            return data.UseAsStream((stream) => sha.ComputeHash(stream));\n#endif\n        }\n\n        /// <summary>\n        /// Computes the SHA512 hash of the data array.\n        /// </summary>\n        /// <returns>512bit/64byte data hash</returns>\n        public static byte[] ComputeSHA512Hash<T>(this T[] data) where T : struct\n#if NET6_0_OR_GREATER\n            => SHA512.HashData(data.AsByteSpan());\n#else\n            => ((Array)data).ComputeSHA512Hash();\n#endif\n\n        /// <summary>\n        /// Computes the SHA512 hash of the given string.\n        /// </summary>\n        /// <returns>512bit/64byte data hash</returns>\n        public static byte[] ComputeSHA512Hash(this string s)\n        {\n#if NET6_0_OR_GREATER\n            return SHA512.HashData(s.AsByteSpan());\n#else\n            return Encoding.Unicode.GetBytes(s).ComputeSHA512Hash();\n#endif\n        }\n\n        #endregion\n\n        #region Adler32\n\n        /// <summary>\n        /// Computes a checksum of the data array using the Adler-32 algorithm (<see cref=\"Adler32\"/>).\n        /// </summary>\n        public static uint ComputeAdler32Checksum(this byte[] data)\n        {\n            var a = new Adler32();\n            a.Update(data);\n            return a.Checksum;\n        }\n\n        /// <summary>\n        /// Computes a checksum of the data array using the Adler-32 algorithm (<see cref=\"Adler32\"/>).\n        /// </summary>\n        public static uint ComputeAdler32Checksum(this Array data)\n        {\n            var a = new Adler32();\n            if (data != null)\n            {\n#if NET6_0_OR_GREATER\n                a.Update(data.AsByteSpan());\n#else\n                data.UseAsStream((stream) => a.Update(stream));\n#endif\n            }\n            return a.Checksum;\n        }\n\n        /// <summary>\n        /// Computes a checksum of the data array using the Adler-32 algorithm (<see cref=\"Adler32\"/>).\n        /// </summary>\n        public static uint ComputeAdler32Checksum<T>(this T[] data) where T : struct\n        {\n#if NET6_0_OR_GREATER\n            var a = new Adler32();\n            if (data != null)\n                a.Update(data.AsByteSpan());\n            return a.Checksum;\n#else\n            return ((Array)data).ComputeAdler32Checksum();\n#endif\n        }\n\n        /// <summary>\n        /// Computes a checksum of the given string using the Adler-32 algorithm (<see cref=\"Adler32\"/>).\n        /// </summary>\n        public static uint ComputeAdler32Checksum(this string s)\n        {\n            var a = new Adler32();\n\n#if NET6_0_OR_GREATER\n            a.Update(s.AsByteSpan());\n#else\n            a.Update(Encoding.Unicode.GetBytes(s));\n#endif\n            return a.Checksum;\n        }\n\n        #endregion\n\n        #endregion\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Extensions/CastExtensions.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    public static class CastExtensions\n    {\n        public static T[] ToArrayOfT<T>(this IEnumerable s)\n        {\n            return (from T o in s select (T)o).ToArray();\n        }\n\n        public static List<T> ToListOfT<T>(this IEnumerable s)\n        {\n            return (from T o in s select o).ToList();\n        }\n\n        public static IEnumerable<T> ToIEnumerableOfT<T>(this IEnumerable s)\n        {\n            return from T o in s select o;\n        }\n\n        public static List<T> IntoList<T>(this T item)\n        {\n            return new List<T>() { item };\n        }\n\n        public static T[] IntoArray<T>(this T item)\n        {\n            return new T[] { item };\n        }\n\n        public static IEnumerable<T> IntoIEnumerable<T>(this T item)\n        {\n            return new T[] { item };\n            // yield return item; // this generates a more code\n        }\n\n        /// <summary>\n        /// Returns the item as a T.\n        /// Or throws an exception if not convertible.\n        /// </summary>\n        public static T To<T>(this object item) where T : class\n        {\n            if (item is T) return item as T;\n            throw new ArgumentException(string.Format(\"expected {0} instead of {1}\", typeof(T), item.GetType()));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/DagExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.VRVis\n{\n    public static class TreeExtensions\n    {\n        public static IEnumerable<T> DepthFirst<T>(\n            this T self,\n            Func<T, IEnumerable<T>> subNodes\n            )\n        {\n            yield return self;\n\n            var stack = new Stack<IEnumerator<T>>();\n            stack.Push(subNodes(self).GetEnumerator());\n\n            while (stack.Count > 0)\n            {\n                var e = stack.Peek();\n                if (e.MoveNext())\n                {\n                    yield return e.Current;\n                    stack.Push(subNodes(e.Current).GetEnumerator());\n                }\n                else\n                {\n                    stack.Pop();\n                }\n            }\n        }\n\n        public static IEnumerable<T> BreadthFirst<T>(\n            this T self,\n            Func<T, IEnumerable<T>> subNodes\n            )\n        {\n            yield return self;\n\n            var queue = new Queue<IEnumerable<T>>();\n            queue.Enqueue(subNodes(self));\n\n            while (queue.Count > 0)\n            {\n                var nodes = queue.Dequeue();\n                if (nodes == null) continue;\n\n                foreach (var n in nodes)\n                {\n                    yield return n;\n                    queue.Enqueue(subNodes(n));\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/DateTimeExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class DateTimeExtensions\n    {\n        /// <summary>\n        /// Calculates the UTC Julian day from the given DateTime and time zone.\n        /// Julian days start at 12h noon January 1, 4713 BC (day 0). The fractional part contains the fraction of a day since the last noon. \n        /// </summary>\n        public static double ComputeJulianDayUTC(this DateTime date, double timeZone)\n        {\n            return date.ComputeJulianDay() - (timeZone / 24.0);\n        }\n\n        /// <summary>\n        /// Calculates the Julian day from the given DateTime.\n        /// Julian days start at 12h noon January 1, 4713 BC (day 0). The fractional part contains the fraction of a day since the last noon. \n        /// </summary>\n        public static double ComputeJulianDay(this DateTime date)\n        {\n            var y = date.Year;\n            var m = date.Month;\n            var d = date.Day;\n            var dt = date.TimeOfDay.TotalDays;\n\n            if (m < 3)\n            {\n                m = m + 12;\n                y = y - 1;\n            }\n\n            int jd = d + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400);\n\n            return jd + 1721118.5 + dt;\n        }\n\n        // whatever the use of this should be\n        public static double GregorianDayOfMonthFromJulianDay(double J)\n        {\n            // the following calculates the day of the month of a JD\n            var p = Fun.Floor(J + 0.5);\n            var s1 = p + 68569;\n            var n = Fun.Floor(4 * s1 / 146097);\n            var s2 = s1 - Fun.Floor((146097 * n + 3) / 4);\n            var i = Fun.Floor(4000 * (s2 + 1) / 1461001);\n            var s3 = s2 - Fun.Floor(1461 * i / 4) + 31;\n            var q = Fun.Floor(80 * s3 / 2447);\n            var e = s3 - Fun.Floor(2447 * q / 80);\n            // int s4 = System.Math.Floor(q / 11);\n            // int m = q + 2 - 12 * s4;\n            // int y = 100 * (n - 49) + i + s4;\n            return e + J - p + 0.5;\n        }\n        \n        /// <summary>\n        /// Calculates date of a Julian day.\n        /// NOTE: A Julian day starts at 12h noon\n        /// </summary>\n        public static DateTime ComputeDateFromJulianDay(double jd)\n        {\n            var p = (int)(jd + 68569.5);\n            var q = 4 * p / 146097;\n            var r = p - (146097 * q + 3) / 4;\n            var s = 4000 * (r + 1) / 1461001;\n            var t = r - 1461 * s / 4 + 31;\n            var u = 80 * t / 2447;\n            var v = u / 11;\n\n            var Y = 100 * (q - 49) + s + v;\n            var M = u + 2 - 12 * v;\n            var D = t - 2447 * u / 80;\n\n            var timeOfDay = (jd + 0.5).Frac();\n            var tmp = timeOfDay * 24;\n            var _h = (int)tmp;\n            tmp = (tmp - _h) * 60;\n            var _m = (int)tmp;\n            tmp = (tmp - _m) * 60;\n            var _s = (int)tmp;\n            tmp = (tmp - _s) * 1000;\n            var _ms = (int)tmp;\n            \n            return new DateTime(Y, M, D, _h, _m, _s, _ms);\n        }\n\n        /// <summary>\n        /// Calculates date of a Julian day.\n        /// NOTE: A Julian day starts at 12h noon\n        /// </summary>\n        public static DateTime ComputeDateFromJulianDay(int jd)\n        {\n            var p = (int)(jd + 68569);\n            var q = 4 * p / 146097;\n            var r = p - (146097 * q + 3) / 4;\n            var s = 4000 * (r + 1) / 1461001;\n            var t = r - 1461 * s / 4 + 31;\n            var u = 80 * t / 2447;\n            var v = u / 11;\n\n            var Y = 100 * (q - 49) + s + v;\n            var M = u + 2 - 12 * v;\n            var D = t - 2447 * u / 80;\n\n            return new DateTime(Y, M, D, 12, 0, 0, 0);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/DictionaryExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    #region Dictionary Extensions\n\n    public static class DictionaryFun\n    {\n        public static Dictionary<Tk, Tv> Copy<Tk, Tv>(\n            this Dictionary<Tk, Tv> self)\n        {\n            var r = new Dictionary<Tk, Tv>(self.Count);\n            foreach (var kvp in self)\n                r[kvp.Key] = kvp.Value;\n            return r;\n        }\n\n        public static Dictionary<Tk, T1v> Copy<Tk, Tv, T1v>(\n            this Dictionary<Tk, Tv> self,\n            Func<Tv, T1v> fun)\n        {\n            var r = new Dictionary<Tk, T1v>(self.Count);\n            foreach (var kvp in self)\n                r[kvp.Key] = fun(kvp.Value);\n            return r;\n        }\n\n        public static Dictionary<Tk, T1v> Copy<Tk, Tv, T1v>(\n            this Dictionary<Tk, Tv> self,\n            Dictionary<Tk, Func<Tv, T1v>> funMap,\n            Func<Tv, T1v> defaultFun)\n        {\n            var r = new Dictionary<Tk, T1v>(self.Count);\n            foreach (var kvp in self)\n            {\n                if (funMap.TryGetValue(kvp.Key, out Func<Tv, T1v> fun))\n                    r[kvp.Key] = fun(kvp.Value);\n                else if (defaultFun != null)\n                    r[kvp.Key] = defaultFun(kvp.Value);\n            }\n            return r;\n        }\n\n        /// <summary>\n        /// Combines the dictionary with another one. Duplicate keys\n        /// are overwritten.\n        /// </summary>\n        public static Dictionary<Tk, Tv> Combine<Tk, Tv>(\n            this Dictionary<Tk, Tv> self,\n            Dictionary<Tk, Tv> second)\n        {\n            var result = self.Copy();\n            foreach (var kvp in second)\n                result[kvp.Key] = kvp.Value;\n            return result;\n        }\n    }\n\n\n    #endregion\n\n    #region IDictionaryExt\n\n    public static class IDictionaryExtensions\n    { \n        /// <summary>\n        /// Tries to get a value from the dictionary.\n        /// If the key is not found, default(T) will be returned.\n        /// </summary>\n        public static Tv Get<Tk, Tv>(\n            this IDictionary<Tk, Tv> self, Tk key)\n        {\n            if (self.TryGetValue(key, out Tv value)) return value;\n            return default(Tv);\n        }\n\n        /// <summary>\n        /// Tries to get a value from the dictionary. \n        /// If the key is not found, the specified defaultValue will be returned.\n        /// </summary>\n        public static Tv Get<Tk, Tv>(\n            this IDictionary<Tk, Tv> self, Tk key, Tv defaultValue)\n        {\n            if (self.TryGetValue(key, out Tv value)) return value;\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Gets the value with the given key. If not found, a new value for the key is created.\n        /// </summary>\n        public static TV GetCreate<TK, TV>(this IDictionary<TK, TV> self, TK key, Func<TK, TV> creator = null)\n        {\n            if (!self.TryGetValue(key, out TV value))\n            {\n                value = (creator != null) ? creator(key) : default(TV);\n                self[key] = value;\n            }\n            return value;\n        }\n\n        /// <summary>\n        /// Removes the value with the given key from the dictionary and passes it as return argument.\n        /// </summary>\n        /// <return>The value removed from the dictionary</return>\n        /// <exception cref=\"KeyNotFoundException\">if key not found</exception>\n        public static TV Pop<TK, TV>(this IDictionary<TK, TV> self, TK key)\n        {\n            if (self.TryGetValue(key, out TV value))\n            {\n                self.Remove(key);\n                return value;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Removes the value with the given key from the dictionary and passes it as out argument.\n        /// In case the value is not found default(T) will be returned.\n        /// </summary>\n        /// <return>true if the value was removed from the dictionary, false otherwise.</return>\n        public static bool TryPop<TK, TV>(this IDictionary<TK, TV> self, TK key, out TV value)\n            => self.TryGetValue(key, out value) && self.Remove(key);\n\n        /// <summary>\n        /// Removes the value with the given key from the dictionary and passes it as return argument.\n        /// In case the value is not found default(T) will be returned.\n        /// </summary>\n        /// <return>The value removed from the dictionary or default(T)</return>\n        public static TV TryPop<TK, TV>(this IDictionary<TK, TV> self, TK key)\n            => self.TryPop(key, out TV value) ? value : default;\n\n\n        public static T1v[] CopyToArray<Tk, Tv, T1v>(this IDictionary<Tk, Tv> self, Func<KeyValuePair<Tk, Tv>, T1v> fun)\n        {\n            var r = new T1v[self.Count];\n            var i = 0L;\n            foreach (var kvp in self)\n                r[i++] = fun(kvp);\n            return r;\n        }\n\n        public static T1v[] CopyToArray<Tk, Tv, T1v>(this IDictionary<Tk, Tv> self, Func<Tk, Tv, T1v> fun)\n        {\n            var r = new T1v[self.Count];\n            var i = 0L;\n            foreach (var kvp in self)\n                r[i++] = fun(kvp.Key, kvp.Value);\n            return r;\n        }\n\n        /// <summary>\n        /// Adds a range of KeyValuePairs, will throw DuplicateKeyException\n        /// </summary>\n        public static Td AddRange<Td, Tk, Tv>(this Td self, IEnumerable<KeyValuePair<Tk, Tv>> keyValuePairs)\n            where Td: IDictionary<Tk, Tv>\n        {\n            foreach (var kvp in keyValuePairs)\n                self.Add(kvp.Key, kvp.Value);\n            return self;\n        }\n\n        /// <summary>\n        /// Adds a range of KeyValuePairs as Tup, will throw DuplicateKeyException\n        /// </summary>\n        public static Td AddRange<Td, Tk, Tv>(this Td self, IEnumerable<Tup<Tk, Tv>> keyValueTuples)\n            where Td : IDictionary<Tk, Tv>\n        {\n            foreach (var kvp in keyValueTuples)\n                self.Add(kvp.E0, kvp.E1);\n            return self;\n        }\n\n        /// <summary>\n        /// Adds a range of KeyValuePairs, duplicate keys will be overwritten\n        /// </summary>\n        public static Td SetRange<Td, Tk, Tv>(this Td self, IEnumerable<KeyValuePair<Tk, Tv>> keyValuePairs)\n            where Td : IDictionary<Tk, Tv>\n        {\n            foreach (var kvp in keyValuePairs)\n                self[kvp.Key] = kvp.Value;\n            return self;\n        }\n\n        /// <summary>\n        /// Adds a range of KeyValuePairs, duplicate keys will be overwritten\n        /// </summary>\n        public static Td SetRange<Td, Tk, Tv>(this Td self, IEnumerable<Tup<Tk, Tv>> keyValueTuples)\n            where Td : IDictionary<Tk, Tv>\n        {\n            foreach (var kvp in keyValueTuples)\n                self[kvp.E0] = kvp.E1;\n            return self;\n        }\n\n        /// <summary>\n        /// Compares the key value pairs of two dictionaries using Equals to compare the values.\n        /// </summary>\n        public static bool DictionaryEquals<Tk, Tv>(this IDictionary<Tk, Tv> self, IDictionary<Tk, Tv> other)\n        {\n            return DictionaryEquals(self, other, (valueA, valueB) => valueA.Equals(valueB));\n        }\n\n        /// <summary>\n        /// Compares the key value pairs of two dictionaries using a custom valueComparisonFunc\n        /// (which returns true if both are equal).\n        /// </summary>\n        public static bool DictionaryEquals<Tk, Tv>(this IDictionary<Tk, Tv> self, IDictionary<Tk, Tv> other, Func<Tv, Tv, bool> valueComparisonFunc)\n        {\n            if (self.Count != other.Count)\n                return false;\n            else\n            {\n                foreach (var item in self)\n                {\n                    Tv valueA = item.Value;\n\n                    if (!other.TryGetValue(item.Key, out Tv valueB) || !valueComparisonFunc(valueA, valueB))\n                        return false;\n\n                }\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Returns the value stored with the supplied key or the specified default value if not found.\n        /// </summary>\n        public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> self, TKey key, TValue defaultValue)\n            => self.TryGetValue(key, out var result) ? result : defaultValue;\n    }\n\n    #endregion\n\n    #region KeyValuePair Extensions\n\n    public static class KeyValuePairs\n    {\n        public static KeyValuePair<TKey, TValue> Create<TKey, TValue>(\n                TKey key, TValue value)\n        {\n            return new KeyValuePair<TKey, TValue>(key, value);\n        }\n\n        public static KeyValuePair<TKey, TValue2> Copy<TKey, TValue1, TValue2>(\n                this KeyValuePair<TKey, TValue1> kvp, Func<TValue1, TValue2> func)\n        {\n            return new KeyValuePair<TKey, TValue2>(kvp.Key, func(kvp.Value));\n        }\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/EnumHelpers.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class EnumHelpers\n    {\n        static readonly Dict<Type, Dict<long, (object, object)>> s_neighbourValuesDicts = new Dict<Type, Dict<long, (object, object)>>();\n\n        static Dict<long, (object, object)> GetNeighbourValuesDict<T>(Type enumType)\n        {\n            if (!enumType.IsEnum) throw new ArgumentException($\"{enumType.Name} is not an enumeration type.\");\n\n            if (!s_neighbourValuesDicts.TryGetValue(enumType, out Dict<long, (object, object)> neighbourValuesDict))\n            {\n                var values = (T[])Enum.GetValues(enumType);\n\n                neighbourValuesDict = new Dict<long, (object, object)>();\n                for (int i = 0; i < values.Length; i++)\n                {\n                    neighbourValuesDict[Convert.ToInt64(values[i])] = \n                        (\n                            values[(i > 0 ? i : values.Length) - 1], \n                            values[i < values.Length - 1 ? i + 1 : 0]\n                        ); // previous and next value\n                }\n\n                s_neighbourValuesDicts[enumType] = neighbourValuesDict;\n            }\n\n            return neighbourValuesDict;\n        }\n\n        /// <summary>\n        /// Returns the previous value of the enumeration or the last when the current value is the first one.\n        /// </summary>\n        public static T GetPrevValue<T>(T enumValue)\n        // NOTE: where T: enum\n        {\n            var neighbourValuesDict = GetNeighbourValuesDict<T>(typeof(T));\n\n            var intValue = Convert.ToInt64(enumValue);\n            neighbourValuesDict.TryGetValue(intValue, out (object, object) result);\n            return (T)result.Item1;\n        }\n\n        /// <summary>\n        /// Returns the next value of the enumeration or the first when the current value is the last one.\n        /// </summary>\n        public static T GetNextValue<T>(T enumValue)\n        // NOTE: where T: enum\n        {\n            var neighbourValuesDict = GetNeighbourValuesDict<T>(typeof(T));\n\n            var intValue = Convert.ToInt64(enumValue);\n            neighbourValuesDict.TryGetValue(intValue, out (object, object) result);\n            return (T)result.Item2;\n        }\n\n        static readonly Dictionary<Type, (Array, Dictionary<long, int>)> s_valueIndexMapping = new Dictionary<Type, (Array, Dictionary<long, int>)>(); // long = worst case enum value\n\n        static (Array, Dictionary<long, int>) GetValueIndexMapping(Type enumType)\n        {\n            if (!enumType.IsEnum) throw new ArgumentException($\"{enumType.Name} is not an enumeration type.\");\n\n            return s_valueIndexMapping.GetCreate(enumType, et =>\n            {\n                var enumValues = Enum.GetValues(et);\n                var enumIndices = new Dictionary<long, int>();\n                for (int i = 0; i < enumValues.Length; i++)\n                    enumIndices.Add(Convert.ToInt64(enumValues.GetValue(i)), i);\n                return (enumValues, enumIndices);\n            });\n        }\n\n        /// <summary>\n        /// Return the index of the enumeration value\n        /// </summary>\n        public static int GetIndex<T>(T enumValue)\n        {\n            var mapping = GetValueIndexMapping(typeof(T));\n            return mapping.Item2[Convert.ToInt64(enumValue)];\n        }\n\n        /// <summary>\n        /// Return the index of the enumeration value\n        /// </summary>\n        public static int GetIndex(Type enumType, object enumValue)\n        {\n            var mapping = GetValueIndexMapping(enumType);\n            return mapping.Item2[Convert.ToInt64(enumValue)]; \n        }\n\n        /// <summary>\n        /// Returns the enumeartion value of a certain index\n        /// </summary>\n        public static int GetValue(Type enumType, int index)\n        {\n            var mapping = GetValueIndexMapping(enumType);\n            return (int)mapping.Item1.GetValue(index);\n        }\n\n        /// <summary>\n        /// Returns the enumeartion value of a certain index\n        /// </summary>\n        public static T GetValue<T>(int index)\n        {\n            var mapping = GetValueIndexMapping(typeof(T));\n            return (T)mapping.Item1.GetValue(index);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/EventHandlerExtensions.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public static class EventHandlerExtensions\n    {\n        /// <summary>\n        /// Safely invokes the event using null as sender and EventArgs.Empty\n        /// </summary>\n        public static void TryInvoke(this EventHandler eh)\n        {\n            eh?.Invoke(null, EventArgs.Empty);\n        }\n\n        /// <summary>\n        /// Safely invokes the event using the supplied sender with EventArgs.Empty\n        /// </summary>\n        public static void TryInvoke(this EventHandler eh, object sender)\n        {\n            eh?.Invoke(sender, EventArgs.Empty);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/FuncActionExtensions.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public static partial class FuncActionExtensions\n    {\n        /// <summary>\n         /// Encapsulates the expression \"[object] != null ? 'select something from [object]' : defaultValue\n         /// </summary>\n        public static Tr TrySelect<To, Tr>(this To o, Func<To, Tr> selector, Tr defaultValue = default(Tr))\n            where To : class\n        {\n            return o != null ? selector(o) : defaultValue;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/FuncActionExtensions_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static partial class FuncActionExtensions\n    {\n        public static TR ExecuteFirst<T0, TR>(this Func<T0, TR>[] funArray, T0 e0)\n        {\n            return funArray[0](e0);\n        }\n\n        public static bool ExecuteUpToTrue<T0>(this Func<T0, bool>[] funArray, T0 e0)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0>(this Func<T0, bool>[] funArray, T0 e0)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, TR>(this Func<T0, TR>[] funArray, T0 e0)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, TR>(this Func<T0, TR>[] funArray, T0 e0)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, TR>(this Func<T0, T1, TR>[] funArray, T0 e0, T1 e1)\n        {\n            return funArray[0](e0, e1);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1>(this Func<T0, T1, bool>[] funArray, T0 e0, T1 e1)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1>(this Func<T0, T1, bool>[] funArray, T0 e0, T1 e1)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, TR>(this Func<T0, T1, TR>[] funArray, T0 e0, T1 e1)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, TR>(this Func<T0, T1, TR>[] funArray, T0 e0, T1 e1)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, TR>(this Func<T0, T1, T2, TR>[] funArray, T0 e0, T1 e1, T2 e2)\n        {\n            return funArray[0](e0, e1, e2);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2>(this Func<T0, T1, T2, bool>[] funArray, T0 e0, T1 e1, T2 e2)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2>(this Func<T0, T1, T2, bool>[] funArray, T0 e0, T1 e1, T2 e2)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, TR>(this Func<T0, T1, T2, TR>[] funArray, T0 e0, T1 e1, T2 e2)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, TR>(this Func<T0, T1, T2, TR>[] funArray, T0 e0, T1 e1, T2 e2)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, TR>(this Func<T0, T1, T2, T3, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3)\n        {\n            return funArray[0](e0, e1, e2, e3);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3>(this Func<T0, T1, T2, T3, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3>(this Func<T0, T1, T2, T3, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, TR>(this Func<T0, T1, T2, T3, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, TR>(this Func<T0, T1, T2, T3, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, TR>(this Func<T0, T1, T2, T3, T4, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n        {\n            return funArray[0](e0, e1, e2, e3, e4);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4>(this Func<T0, T1, T2, T3, T4, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4>(this Func<T0, T1, T2, T3, T4, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, TR>(this Func<T0, T1, T2, T3, T4, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, TR>(this Func<T0, T1, T2, T3, T4, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, TR>(this Func<T0, T1, T2, T3, T4, T5, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5>(this Func<T0, T1, T2, T3, T4, T5, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5>(this Func<T0, T1, T2, T3, T4, T5, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, TR>(this Func<T0, T1, T2, T3, T4, T5, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, TR>(this Func<T0, T1, T2, T3, T4, T5, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6>(this Func<T0, T1, T2, T3, T4, T5, T6, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6>(this Func<T0, T1, T2, T3, T4, T5, T6, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7, e8);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7, T8>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        public static TR ExecuteFirst<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14, T15 e15)\n        {\n            return funArray[0](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15);\n        }\n\n        public static bool ExecuteUpToTrue<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14, T15 e15)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, bool>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14, T15 e15)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14, T15 e15)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TR>(this Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TR>[] funArray, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9, T10 e10, T11 e11, T12 e12, T13 e13, T14 e14, T15 e15)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/FuncActionExtensions_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static partial class FuncActionExtensions\n    {\n        //# Action comma = () => Out(\", \");\n        //# for (int tc = 1; tc <= 16; tc++) {\n        //#   var Ti = tc.Expand(i => \"T\" + i).Join(\", \");\n        //#   var ei = tc.Expand(i => \"e\" + i).Join(\", \");\n        public static TR ExecuteFirst<__Ti__, TR>(this Func<__Ti__, TR>[] funArray, /*# tc.ForEach(i=>{*/T__i__ e__i__/*#}, comma); */)\n        {\n            return funArray[0](__ei__);\n        }\n\n        public static bool ExecuteUpToTrue<__Ti__>(this Func<__Ti__, bool>[] funArray, /*# tc.ForEach(i=>{*/T__i__ e__i__/*#}, comma); */)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n                if (funArray[i](__ei__)) return true;\n            return false;\n        }\n\n        public static bool ExecuteUpToTrueChecked<__Ti__>(this Func<__Ti__, bool>[] funArray, /*# tc.ForEach(i=>{*/T__i__ e__i__/*#}, comma); */)\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    if (funArray[i](__ei__)) return true;\n                }\n                catch (Exception) { }\n            }\n            return false;\n        }\n\n        public static TR ExecuteUpToNotNull<__Ti__, TR>(this Func<__Ti__, TR>[] funArray, /*# tc.ForEach(i=>{*/T__i__ e__i__/*#}, comma); */)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                var r = funArray[i](__ei__);\n                if (r != null) return r;\n            }\n            return null;\n        }\n\n        public static TR ExecuteUpToNotNullChecked<__Ti__, TR>(this Func<__Ti__, TR>[] funArray, /*# tc.ForEach(i=>{*/T__i__ e__i__/*#}, comma); */)\n            where TR : class\n        {\n            for (int i = 0; i < funArray.Length; i++)\n            {\n                try\n                {\n                    var r = funArray[i](__ei__);\n                    if (r != null) return r;\n                }\n                catch (Exception) { }\n            }\n            return null;\n        }\n\n        //# } // tc\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/HigherOrderFunctions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public static class ControlFun\n    {\n        #region ForEach on ints\n\n        /// <summary>\n        /// Perform the supplied action for all integers i in [0, n).\n        /// </summary>\n        public static void ForEach(this int n, Action<int> i_act)\n        {\n            for (int k = 0; k < n; k++) { i_act(k); }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all integers in [start, n).\n        /// </summary>\n        public static void ForEach(this int n, int start, Action<int> i_act)\n        {\n            for (int k = start; k < n; k++) { i_act(k); }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all integers i in [0, n).\n        /// Perform the supplied separating action between the integers.\n        /// </summary>\n        public static void ForEach(this int n, Action<int> i_act, Action sep)\n        {\n            for (int k = 0; k < n - 1; k++) { i_act(k); sep(); }\n            i_act(n - 1);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all integers i in [start, n).\n        /// Perform the supplied separating action between the integers.\n        /// </summary>\n        public static void ForEach(\n                this int n, int start, Action<int> i_act, Action sep)\n        {\n            for (int k = start; k < n - 1; k++) { i_act(k); sep(); }\n            i_act(n - 1);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all integers i in [0, n).\n        /// Perform the supplied separating action between the integers.\n        /// The seperating action receives the index of the preceeding item.\n        /// </summary>\n        public static void ForEach(this int n, Action<int> i_act, Action<int> i_sep)\n        {\n            for (int k = 0; k < n - 1; k++) { i_act(k); i_sep(k); }\n            i_act(n - 1);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all integers i in [start, n).\n        /// Perform the supplied separating action between the integers.\n        /// The seperating action receives the index of the preceeding item.\n        /// </summary>\n        public static void ForEach(\n                this int n, int start, Action<int> i_act, Action<int> i_sep)\n        {\n            for (int k = start; k < n - 1; k++) { i_act(k); i_sep(k); }\n            i_act(n - 1);\n        }\n\n        #endregion\n\n        #region ForEach on longs\n\n        /// <summary>\n        /// Perform the supplied action for all integers i in [0, n).\n        /// </summary>\n        public static void ForEach(this long n, Action<long> i_act)\n        {\n            for (long k = 0; k < n; k++) { i_act(k); }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all integers in [start, n).\n        /// </summary>\n        public static void ForEach(this long n, long start, Action<long> i_act)\n        {\n            for (long k = start; k < n; k++) { i_act(k); }\n        }\n\n        #endregion\n\n        #region ForEach on IEnumerable<T>\n\n        /// <summary>\n        /// Perform the supplied action for all items in the IEnumerable.\n        /// </summary>\n        public static void ForEach<T>(\n                this IEnumerable<T> items, Action<T> item_act)\n        {\n            foreach (var item in items) item_act(item);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all items in the IEnumerable.\n        /// The action gets the index of the item i out of [0, n) as last\n        /// parameter.\n        /// </summary>\n        public static void ForEach<T>(\n                this IEnumerable<T> items, Action<T, int> item_i_act)\n        {\n            int i = 0;\n            foreach (var item in items) item_i_act(item, i++);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all pairs of items in the IEnumerable\n        /// and from the second IEnumerable.\n        /// </summary>\n        public static void ForEach<T0, T1>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1,\n                Action<T0, T1> item0_item1_act)\n        {\n            foreach (var item in items0.ZipTuples(items1))\n                item0_item1_act(item.Item1, item.Item2);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all triples of items from\n        /// each of the supplied IEnumerables.\n        /// </summary>\n        public static void ForEach<T0, T1, T2>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1, IEnumerable<T2> items2,\n                Action<T0, T1, T2> item0_item1_item2_act)\n        {\n            foreach (var item in items0.ZipTuples(items1, items2))\n                item0_item1_item2_act(item.E0, item.E1, item.E2);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all corresponding pairs\n        /// of items from the IEnumerable and from the second IEnumerable.\n        /// The action gets the index of the item as last parameter.\n        /// </summary>\n        public static void ForEach<T0, T1>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1,\n                Action<T0, T1, int> item0_item1_i_act)\n        {\n            int i = 0;\n            foreach (var item in items0.ZipTuples(items1))\n                item0_item1_i_act(item.Item1, item.Item2, i++);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all triples of items from\n        /// each of the supplied IEnumerables.\n        /// The action gets the index of the item as last parameter.\n        /// </summary>\n        public static void ForEach<T0, T1, T2>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1, IEnumerable<T2> items2,\n                Action<T0, T1, T2, int> item0_item1_item2_i_act)\n        {\n            int i = 0;\n            foreach (var item in items0.ZipTuples(items1, items2))\n                item0_item1_item2_i_act(item.E0, item.E1, item.E2, i++);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all items in the IEnumerable.\n        /// Perform the supplied separating action between the items.\n        /// </summary>\n        public static void ForEach<T>(\n                this IEnumerable<T> items, Action<T> item_act, Action sep)\n        {\n            bool notfirst = false;\n            foreach (var item in items)\n            {\n                if (notfirst) sep(); else notfirst = true;\n                item_act(item);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all items in the IEnumerable.\n        /// The action gets the index i out of [0, n) of the item as last\n        /// parameter. Perform the supplied separating action between items.\n        /// </summary>\n        public static void ForEach<T>(\n                this IEnumerable<T> items,\n                Action<T, int> item_i_act, Action sep)\n        {\n            int i = -1;\n            foreach (var item in items)\n            {\n                if (i >= 0) sep();\n                item_i_act(item, ++i);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all items in the IEnumerable.\n        /// The action gets the index of the item as last parameter.\n        /// Perform the supplied separating action between items.\n        /// The seperating action receives the index of the preceeding item.\n        /// </summary>\n        public static void ForEach<T>(\n                this IEnumerable<T> items,\n                Action<T, int> item_i_act, Action<int> i_sep)\n        {\n            int i = -1;\n            foreach (var item in items)\n            {\n                if (i >= 0) i_sep(i);\n                item_i_act(item, ++i);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all corresponding pairs\n        /// of items from the IEnumerable and from the second IEnumerable.\n        /// Perform the supplied separating action between the items.\n        /// </summary>\n        public static void ForEach<T0, T1>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1,\n                Action<T0, T1> item0_item1_act, Action sep)\n        {\n            bool notfirst = false;\n            foreach (var item in items0.ZipTuples(items1))\n            {\n                if (notfirst) sep(); else notfirst = true;\n                item0_item1_act(item.Item1, item.Item2);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all triples of items from\n        /// each of the supplied IEnumerables.\n        /// Perform the supplied separating action between the items.\n        /// </summary>\n        public static void ForEach<T0, T1, T2>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1, IEnumerable<T2> items2,\n                Action<T0, T1, T2> item0_item1_item2_act, Action sep)\n        {\n            bool notfirst = false;\n            foreach (var item in items0.ZipTuples(items1, items2))\n            {\n                if (notfirst) sep(); else notfirst = true;\n                item0_item1_item2_act(item.E0, item.E1, item.E2);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all corresponding pairs\n        /// of items from the IEnumerable and from the second IEnumerable.\n        /// The action gets the index of the item as last parameter.\n        /// Perform the supplied separating action between the items.\n        /// </summary>\n        public static void ForEach<T0, T1>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1,\n                Action<T0, T1, int> item0_item1_i_act, Action sep)\n        {\n            int i = -1;\n            foreach (var item in items0.ZipTuples(items1))\n            {\n                if (i >= 0) sep();\n                item0_item1_i_act(item.Item1, item.Item2, ++i);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all triples of items from\n        /// each of the supplied IEnumerables.\n        /// The action gets the index of the item as last parameter.\n        /// Perform the supplied separating action between the items.\n        /// </summary>\n        public static void ForEach<T0, T1, T2>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1, IEnumerable<T2> items2,\n                Action<T0, T1, T2, int> item0_item1_item2_int_act, Action sep)\n        {\n            int i = -1;\n            foreach (var item in items0.ZipTuples(items1, items2))\n            {\n                if (i >= 0) sep();\n                item0_item1_item2_int_act(item.E0, item.E1, item.E2, ++i);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all corresponding pairs\n        /// of items from the IEnumerable and from the second IEnumerable.\n        /// The action gets the index of the item as last parameter.\n        /// Perform the supplied separating action between the items.\n        /// The seperating action receives the index of the preceeding items.\n        /// </summary>\n        public static void ForEach<T0, T1>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1,\n                Action<T0, T1, int> item0_item1_i_act, Action<int> i_sep)\n        {\n            int i = -1;\n            foreach (var item in items0.ZipTuples(items1))\n            {\n                if (i >= 0) i_sep(i);\n                item0_item1_i_act(item.Item1, item.Item2, ++i);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all triples of items from\n        /// each of the supplied IEnumerables.\n        /// The action gets the index of the item as last parameter.\n        /// Perform the supplied separating action between the items.\n        /// The seperating action receives the index of the preceeding items.\n        /// </summary>\n        public static void ForEach<T0, T1, T2>(\n                this IEnumerable<T0> items0, IEnumerable<T1> items1, IEnumerable<T2> items2,\n                Action<T0, T1, T2, int> item0_item1_item2_i_act, Action<int> i_sep)\n        {\n            int i = -1;\n            foreach (var item in items0.ZipTuples(items1, items2))\n            {\n                if (i >= 0) i_sep(i);\n                item0_item1_item2_i_act(item.E0, item.E1, item.E2, ++i);\n            }\n        }\n\n        #endregion\n\n        #region ForEach on Arrays\n\n        /// <summary>\n        /// Perform the supplied action for all items in the Array.\n        /// </summary>\n        public static void ForEach<T>(\n                this T[] array, Action<T> item_act)\n        {\n            int count = array.Length;\n            for (int i = 0; i < count; i++) item_act(array[i]);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all items in the Array.\n        /// The action gets the index of the item i out of [0, n) as last\n        /// parameter.\n        /// </summary>\n        public static void ForEach<T>(\n                this T[] array, Action<T, int> item_i_act)\n        {\n            int count = array.Length;\n            for (int i = 0; i < count; i++) item_i_act(array[i], i);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all pairs of items in the array\n        /// and from the second array.\n        /// </summary>\n        public static void ForEach<T0, T1>(\n                this T0[] array0, T1[] array1,\n                Action<T0, T1> item0_item1_act)\n        {\n            int count = Min(array0.Length, array1.Length);\n            for (int i = 0; i < count; i++)\n                item0_item1_act(array0[i], array1[i]);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all triples of items from\n        /// each of the supplied arrays.\n        /// </summary>\n        public static void ForEach<T0, T1, T2>(\n                this T0[] array0, T1[] array1, T2[] array2,\n                Action<T0, T1, T2> item0_item1_item2_act)\n        {\n            int count = Min(array0.Length, Min(array1.Length, array2.Length));\n            for (int i = 0; i < count; i++)\n                item0_item1_item2_act(array0[i], array1[i], array2[i]);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all corresponding pairs\n        /// of items from the array and from the second array.\n        /// The action gets the index of the item as last parameter.\n        /// </summary>\n        public static void ForEach<T0, T1>(\n                this T0[] array0, T1[] array1,\n                Action<T0, T1, int> item0_item1_i_act)\n        {\n            int count = Min(array0.Length, array1.Length);\n            for (int i = 0; i < count; i++)\n                item0_item1_i_act(array0[i], array1[i], i);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all triples of items from\n        /// each of the supplied arrays.\n        /// The action gets the index of the item as last parameter.\n        /// </summary>\n        public static void ForEach<T0, T1, T2>(\n                this T0[] array0, T1[] array1, T2[] array2,\n                Action<T0, T1, T2, int> item0_item1_item2_i_act)\n        {\n            int count = Min(array0.Length, Min(array1.Length, array2.Length));\n            for (int i = 0; i < count; i++)\n                item0_item1_item2_i_act(array0[i], array1[i], array2[i], i);\n        }\n\n        #endregion\n\n        #region ForEach on Lists\n\n        /// <summary>\n        /// Perform the supplied action for all items in the List.\n        /// The action gets the index of the item i out of [0, n) as last\n        /// parameter.\n        /// </summary>\n        public static void ForEach<T>(this List<T> list, Action<T, int> fun)\n        {\n            var cnt = list.Count;\n            for (int i = 0; i < cnt; i++)\n                fun(list[i], i);\n        }\n\n        #endregion\n\n        #region ForEach Dictionary\n\n        /// <summary>\n        /// Perform the supplied action for  all items in the ValueCollection.\n        /// </summary>\n        public static void ForEach<K, V>(this Dictionary<K, V>.ValueCollection self, Action<V> fun)\n        {\n            foreach (var v in self)\n                fun(v);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all items in the KeyCollection.\n        /// </summary>\n        public static void ForEach<K, V>(this Dictionary<K, V>.KeyCollection self, Action<K> fun)\n        {\n            foreach (var k in self)\n                fun(k);\n        }\n\n        /// <summary>\n        /// Perform the supplied action for all KeyValuePairs in the Dictionary.\n        /// </summary>\n        public static void ForEach<K, V>(this Dictionary<K, V> self, Action<KeyValuePair<K, V>> fun)\n        {\n            foreach (var kv in self)\n                fun(kv);\n        }\n\n        #endregion\n\n        #region Switch\n\n        public static void Switch<T>(\n            this T value, Dictionary<T, Action<T>> actionDict)\n        {\n            if (actionDict.TryGetValue(value, out Action<T> action))\n                action(value);\n        }\n\n        public static void Switch<T>(\n            this T value, Dictionary<T, Action<T>> actionDict, Action<T> defaultAction)\n        {\n            if (actionDict.TryGetValue(value, out Action<T> action))\n                action(value);\n            else\n                defaultAction(value);\n        }\n\n        public static TResult Switch<T, TResult>(\n            this T value, Dictionary<T, Func<T, TResult>> funcDict)\n        {\n            if (funcDict.TryGetValue(value, out Func<T, TResult> func))\n                return func(value);\n            else\n                return default(TResult);\n        }\n\n        public static TResult Switch<T, TResult>(\n            this T value, Dictionary<T, Func<T, TResult>> funcDict, Func<T, TResult> defaultFunc)\n        {\n            if (funcDict.TryGetValue(value, out Func<T, TResult> func))\n                return func(value);\n            else\n                return defaultFunc(value);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/ICollectionExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static class ICollectionExtensions\n    {\n        /// <summary>\n        /// Adds the item to the collection if not contained, otherwise removes the item from the collection.\n        /// </summary>\n        /// <returns>Containment state of the item after the operation</returns>\n        public static bool ToggleContainment<T>(this ICollection<T> self, T item)\n        {\n            if (!self.Remove(item))\n            {\n                self.Add(item);\n                return true;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Adds the elements in the items enumeration to the collection.\n        /// </summary>\n        public static void AddRange<T>(this ICollection<T> self, IEnumerable<T> items)\n        {\n            foreach (var item in items)\n                self.Add(item);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/IEnumerableExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics.Contracts;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class EnumerableUtils\n    {\n        public static IEnumerable<T> Generate<T>(this Func<T> anotherElement)\n        {\n            if (anotherElement is null) throw new ArgumentNullException(nameof(anotherElement));\n            while (true) yield return anotherElement();\n        }\n\n        public static IEnumerable<Guid> Guids()\n        {\n            while (true) yield return Guid.NewGuid();\n        }\n    }\n\n    public static partial class EnumerableEx\n    {\n        #region Indexed Values\n\n        public static IEnumerable<IndexedValue<T>> IndexedValues<T>(\n                this IEnumerable<T> self)\n        {\n            return self.Select((item, i) => new IndexedValue<T>(i, item));\n        }\n\n        /// <summary>\n        /// If you have a sequence of indexed values, where all indexes\n        /// starting from 0 up to some maximal value are present and\n        /// unique, sorting can be performed this simple array based\n        /// reshuffling operation with O(n) cost.\n        /// </summary>\n        public static T[] SortedByDenseIndex<T>(\n                this IEnumerable<IndexedValue<T>> indexedValues)\n        {\n            var array = indexedValues.ToArray();\n            var len = array.Length;\n            var sorted = new T[len];\n            for (int i = 0; i < len; i++) sorted[array[i].Index] = array[i].Value;\n            return sorted;\n        }\n\n        /// <summary>\n        /// Returns elements with index into 'other'.\n        /// </summary>\n        public static IEnumerable<IndexedValue<T>> IndexIntoOther<T>(\n                this IEnumerable<T> self, IList<T> other)\n        {\n            var map = new Dictionary<T, int>();\n            for (int i = 0; i < other.Count; i++) map[other[i]] = i;\n            return self.Select(item => new IndexedValue<T>(map[item], item));\n        }\n\n        #endregion\n\n        #region Special Selects\n\n        public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> self)\n        {\n            return self.Where(x => x != null);\n        }\n\n        public static IEnumerable<int> IndicesOf<T>(this IEnumerable<T> self, Func<T, bool> predicate)\n        {\n            int i = 0;\n            foreach (var x in self)\n            {\n                if (predicate(x))\n                    yield return i;\n                i++;\n            }\n        }\n\n        public static IEnumerable<TResult> SelectNotNull<T, TResult>(this IEnumerable<T> self, Func<T, TResult> selector)\n        {\n            return self.Select(selector).WhereNotNull();\n        }\n\n        public static T FirstOrDefault<T>(this IEnumerable<T> self, T defaultValue)\n        {\n            foreach (var x in self)\n                return x;\n            return defaultValue;\n        }\n\n        public static T FirstOrDefault<T>(this IEnumerable<T> self, Func<T, bool> predicate, T defaultValue)\n        {\n            foreach (var x in self)\n                if (predicate(x))\n                    return x;\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Yields every stride-th element.\n        /// </summary>\n        public static IEnumerable<T> TakePeriodic<T>(\n            this IEnumerable<T> self, int stride)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (stride < 1) throw new ArgumentOutOfRangeException(nameof(stride));\n\n            var i = 0;\n            foreach (var s in self) if (i++ % stride == 0) yield return s;\n        }\n\n        /// <summary>\n        /// Take the first count items of a sequence and put them into an\n        /// array. If the sequence is shorter than the specified count, the\n        /// array is filled up with default values.\n        /// </summary>\n        public static T[] TakeToArrayDefault<T>(this IEnumerable<T> self, int count)\n        {\n            var array = new T[count];\n            var en = self.GetEnumerator();\n            for (int i = 0; i < count && en.MoveNext(); i++)\n                array[i] = en.Current;\n            return array;\n        }\n\n        /// <summary>\n        /// Take the first count items of a sequence and put them into an\n        /// array. If the sequence is shorter than the specified count, an\n        /// Argument exception is thrown.\n        /// </summary>\n        public static T[] TakeToArray<T>(this IEnumerable<T> self, int count)\n        {\n            var array = new T[count];\n            var en = self.GetEnumerator();\n            for (int i = 0; i < count; i++)\n            {\n                if (en.MoveNext())\n                    array[i] = en.Current;\n                else\n                    throw new ArgumentException();\n            }\n            return array;\n        }\n\n        /// <summary>\n        /// Take the first count items of a sequence and put them into a\n        /// list. If the supplied sequence has less than count elements\n        /// the resulting list is shorter than count items.\n        /// </summary>\n        public static List<T> TakeToList<T>(this IEnumerable<T> self, int count)\n        {\n            var list = new List<T>(count);\n            var en = self.GetEnumerator();\n            for (int i = 0; i < count && en.MoveNext(); i++)\n                list.Add(en.Current);\n            return list;\n        }\n\n        /// <summary>\n        /// Returns the index of the first element triggering the condition or -1 as default.\n        /// </summary>\n        public static int FirstIndexOf<T>(this IEnumerable<T> self, Func<T, bool> where)\n        {\n            var en = self.GetEnumerator();\n            for (int i = 0; en.MoveNext(); i++)\n                if (where(en.Current))\n                    return i;\n            return -1;\n        }\n\n        /// <summary>\n        /// Maps the elements of an array to a result array.\n        /// </summary>\n        public static R[] SelectToArray<T, R>(this T[] self, Func<T, R> selector)\n        {\n            var result = new R[self.Length];\n            for (int i = 0; i < self.Length; i++)\n            {\n                result[i] = selector(self[i]);\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Maps the elements of an array to a result list.\n        /// </summary>\n        public static List<R> SelectToList<T, R>(this T[] self, Func<T, R> selector)\n        {\n            var result = new List<R>(self.Length);\n            for (int i = 0; i < self.Length; i++)\n            {\n                result.Add(selector(self[i]));\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Maps the elements of a list to a result array.\n        /// </summary>\n        public static R[] SelectToArray<T, R>(this List<T> self, Func<T, R> selector)\n        {\n            var result = new R[self.Count];\n            for (int i = 0; i < self.Count; i++)\n            {\n                result[i] = selector(self[i]);\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Maps the elements of a list to a result list.\n        /// </summary>\n        public static List<R> SelectToList<T, R>(this List<T> self, Func<T, R> selector)\n        {\n            var result = new List<R>(self.Count);\n            for (int i = 0; i < self.Count; i++)\n            {\n                result.Add(selector(self[i]));\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Zipping\n\n        /// <summary>\n        /// Interleave this' elements with other's elements resulting in\n        /// a sequence of length min(this.Length, other.Length).\n        /// </summary>\n        public static IEnumerable<T> Zip<T>(\n            this IEnumerable<T> self, IEnumerable<T> other)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other is null) throw new ArgumentNullException(nameof(other));\n\n            var e0 = self.GetEnumerator();\n            var e1 = other.GetEnumerator();\n\n            while (e0.MoveNext() && e1.MoveNext())\n            {\n                yield return e0.Current;\n                yield return e1.Current;\n            }\n        }\n\n        public static IEnumerable<T> Zip<T>(\n            this IEnumerable<T> self,\n            IEnumerable<T> other1, IEnumerable<T> other2)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other1 is null) throw new ArgumentNullException(nameof(other1));\n            if (other2 is null) throw new ArgumentNullException(nameof(other2));\n\n            var e0 = self.GetEnumerator();\n            var e1 = other1.GetEnumerator();\n            var e2 = other2.GetEnumerator();\n\n            while (e0.MoveNext() && e1.MoveNext() && e2.MoveNext())\n            {\n                yield return e0.Current;\n                yield return e1.Current;\n                yield return e2.Current;\n            }\n        }\n\n        public static IEnumerable<T> ZipAll<T>(\n            this IEnumerable<T> self, IEnumerable<T> other)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other is null) throw new ArgumentNullException(nameof(other));\n\n            var e0 = self.GetEnumerator();\n            var e1 = other.GetEnumerator();\n\n            bool t0 = e0.MoveNext(), t1 = e1.MoveNext();\n\n            while (t0 && t1)\n            {\n                yield return e0.Current; yield return e1.Current;\n                t0 = e0.MoveNext(); t1 = e1.MoveNext();\n            }\n\n            while (t0) { yield return e0.Current; t0 = e0.MoveNext(); }\n            while (t1) { yield return e1.Current; t1 = e1.MoveNext(); }\n        }\n\n        public static IEnumerable<T> ZipAll<T>(\n            this IEnumerable<T> self,\n            IEnumerable<T> other1,\n            IEnumerable<T> other2)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other1 is null) throw new ArgumentNullException(nameof(other1));\n            if (other2 is null) throw new ArgumentNullException(nameof(other2));\n\n            var e0 = self.GetEnumerator();\n            var e1 = other1.GetEnumerator();\n            var e2 = other2.GetEnumerator();\n\n            bool t0 = e0.MoveNext(), t1 = e1.MoveNext(), t2 = e2.MoveNext();\n\n            while (t0 && t1 && t2)\n            {\n                yield return e0.Current;\n                yield return e1.Current;\n                yield return e2.Current;\n                t0 = e0.MoveNext(); t1 = e1.MoveNext(); t2 = e2.MoveNext();\n            }\n\n            while (t0 && t1)\n            {\n                yield return e0.Current; yield return e1.Current;\n                t0 = e0.MoveNext(); t1 = e1.MoveNext();\n            }\n\n            while (t0 && t2)\n            {\n                yield return e0.Current; yield return e2.Current;\n                t0 = e0.MoveNext(); t2 = e2.MoveNext();\n            }\n\n            while (t1 && t2)\n            {\n                yield return e1.Current; yield return e2.Current;\n                t1 = e1.MoveNext(); t2 = e2.MoveNext();\n            }\n\n            while (t0) { yield return e0.Current; t0 = e0.MoveNext(); }\n            while (t1) { yield return e1.Current; t1 = e1.MoveNext(); }\n            while (t2) { yield return e2.Current; t2 = e2.MoveNext(); }\n        }\n\n        public static IEnumerable<(T, T)> ZipPairs<T>(\n            this IEnumerable<T> self, IEnumerable<T> other)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other is null) throw new ArgumentNullException(nameof(other));\n\n            var e0 = self.GetEnumerator();\n            var e1 = other.GetEnumerator();\n\n            while (e0.MoveNext() && e1.MoveNext())\n                yield return (e0.Current, e1.Current);\n        }\n\n        public static IEnumerable<(T, T, T)> ZipTriples<T>(\n            this IEnumerable<T> self,\n            IEnumerable<T> other1,\n            IEnumerable<T> other2)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other1 is null) throw new ArgumentNullException(nameof(other1));\n            if (other2 is null) throw new ArgumentNullException(nameof(other2));\n\n            var e0 = self.GetEnumerator();\n            var e1 = other1.GetEnumerator();\n            var e2 = other2.GetEnumerator();\n\n            while (e0.MoveNext() && e1.MoveNext() && e2.MoveNext())\n                yield return (e0.Current, e1.Current, e2.Current);\n        }\n\n        public static IEnumerable<(T0, T1)> ZipTuples<T0, T1>(\n            this IEnumerable<T0> self, IEnumerable<T1> other)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other is null) throw new ArgumentNullException(nameof(other));\n\n            var e0 = self.GetEnumerator();\n            var e1 = other.GetEnumerator();\n\n            while (e0.MoveNext() && e1.MoveNext())\n                yield return (e0.Current, e1.Current);\n        }\n\n        public static IEnumerable<Tup<T0, T1, T2>> ZipTuples<T0, T1, T2>(\n            this IEnumerable<T0> self,\n            IEnumerable<T1> other1,\n            IEnumerable<T2> other2)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other1 is null) throw new ArgumentNullException(nameof(other1));\n            if (other2 is null) throw new ArgumentNullException(nameof(other2));\n\n            var e0 = self.GetEnumerator();\n            var e1 = other1.GetEnumerator();\n            var e2 = other2.GetEnumerator();\n\n            while (e0.MoveNext() && e1.MoveNext() && e2.MoveNext())\n                yield return new Tup<T0, T1, T2>(\n                                    e0.Current, e1.Current, e2.Current);\n        }\n\n        #endregion\n\n        #region Chunking\n\n        public static IEnumerable<T[]> Chunk<T>(\n            this IEnumerable<T> self, long chunkSize\n            )\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (chunkSize < 1) throw new ArgumentOutOfRangeException(nameof(chunkSize));\n\n            var chunk = new List<T>();\n\n            foreach (var item in self)\n            {\n                chunk.Add(item);\n                if (chunk.Count == chunkSize) // yield full chunk\n                {\n                    yield return chunk.ToArray();\n                    chunk.Clear();\n                }\n            }\n\n            // yield rest\n            if (chunk.Count > 0) yield return chunk.ToArray();\n\n        }\n\n        public static IEnumerable<Tr[]> Chunk<T, Tr>(\n            this IEnumerable<T> self, long chunkSize, Func<T, Tr> selector\n            )\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (chunkSize < 1) throw new ArgumentOutOfRangeException(nameof(chunkSize));\n            if (selector is null) throw new ArgumentNullException(nameof(selector));\n\n            var chunk = new List<Tr>();\n\n            foreach (var item in self)\n            {\n                chunk.Add(selector(item));\n                if (chunk.Count == chunkSize) // yield full chunk\n                {\n                    yield return chunk.ToArray();\n                    chunk.Clear();\n                }\n            }\n\n            // yield rest\n            if (chunk.Count > 0) yield return chunk.ToArray();\n\n        }\n\n        #endregion\n\n        #region Pairs\n\n        /// <summary>\n        /// A B C D ... -> (A, B) (C, D) ...\n        /// If sequence does not have even elements the last element is not selected.\n        /// </summary>\n        public static IEnumerable<(T, T)> PairSequence<T>(this IEnumerable<T> self)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            var first = self.TakePeriodic(2);\n            var second = self.Skip(1).TakePeriodic(2);\n\n            return first.ZipPairs(second); //todo: very inefficient: double enumeration\n        }\n\n        /// <summary>\n        /// wrap = false: A B C D ... -> (A, B) (B, C) (C, D) ...\n        /// wrap = true:  A B C D -> (A, B) (B, C) (C, D) (D, A)\n        /// </summary>\n        public static IEnumerable<(T, T)> PairChain<T>(this IEnumerable<T> self, bool wrap = false)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            using (var e = self.GetEnumerator())\n            {\n                if (e.MoveNext())\n                {\n                    T first = e.Current;\n                    T prev = first;\n                    while (e.MoveNext())\n                    {\n                        var x = e.Current;\n                        yield return (prev, x);\n                        prev = x;\n                    }\n                    if (wrap)\n                        yield return (prev, first);\n                }\n            }\n        }\n\n        /// <summary>\n        /// wrap = false: A B C D ... -> (0, 1) (1, 2) (2, 3) ...\n        /// wrap = true:  A B C D -> (0, 1) (1, 2) (2, 3) (3, 0)\n        /// </summary>\n        public static IEnumerable<(int, int)> PairChainIndexed<T>(this IEnumerable<T> self, bool wrap = false)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            using (var e = self.GetEnumerator())\n            {\n                if (e.MoveNext())\n                {\n                    int prev = 0;\n                    while (e.MoveNext())\n                    {\n                        var x = prev + 1;\n                        yield return (prev, x);\n                        prev = x;\n                    }\n                    if (wrap)\n                        yield return (prev, 0);\n                }\n            }\n        }\n\n        /// <summary>\n        /// A B C D -> (A, B) (B, C) (C, D) (D, A)\n        /// </summary>\n        public static IEnumerable<(T, T)> PairChainWrap<T>(this IEnumerable<T> self)\n        {\n            return PairChain(self, true);\n        }\n\n        /// <summary>\n        /// A B C -> (0, 1) (1, 2) (2, 0)\n        /// </summary>\n        public static IEnumerable<(int, int)> PairChainWrapIndexed<T>(this IEnumerable<T> self)\n        {\n            return PairChainIndexed(self, true);\n        }\n\n        /// <summary>\n        /// A B C -> (A, A) (A, B) (A, C) (B, A) (B, B) (B, C) (C, A) (C, B) (C, C)\n        /// </summary>\n        public static IEnumerable<(T, T)> Pairs<T>(this IEnumerable<T> self)\n        {\n            return Pairs(self, false, false);\n        }\n\n        /// <summary>\n        /// A B C -> (A, A) (A, B) (A, C) (B, A) (B, B) (B, C) (C, A) (C, B) (C, C)\n        /// excludeIdenticalPairs: A B C -> (A, B) (A, C) (B, A) (B, C) (C, A) (C, B)\n        /// excludeReversePairs:   A B C -> (A, A) (A, B) (A, C) (B, B) (B, C) (C, C)\n        /// both:                  A B C -> (A, B) (A, C) (B, C)\n        /// </summary>\n        public static IEnumerable<(T, T)> Pairs<T>(this IEnumerable<T> self, bool excludeIdenticalPairs, bool excludeReversePairs)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            var a = self.ToArray();\n            for (int i = 0; i < a.Length; i++)\n                for (int j = excludeReversePairs ? i : 0; j < a.Length; j++)\n                {\n                    if (excludeIdenticalPairs && i == j) continue;\n                    yield return (a[i], a[j]);\n                }\n        }\n\n        /// <summary>\n        /// Computes how many pairs method Pairs() will generate.\n        /// Is efficient on ILists(of T), but will fully enumerate other IEnumerables.\n        /// </summary>\n        public static int PairsCount<T>(this IEnumerable<T> self, bool excludeIdenticalPairs, bool excludeReversePairs)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            var c = self.Count();\n            if(excludeIdenticalPairs)\n            {\n                if (excludeReversePairs)\n                    return (c * (c - 1)) / 2;\n                else\n                    return c * (c - 1);\n            }\n            else\n            {\n                if (excludeReversePairs)\n                    return ((c + 1) * c) / 2;\n                else\n                    return c * c;\n            }\n        }\n\n        /// <summary>\n        /// [A B C].Pairs([x y z]) -> (A, x) (A, y) (A, z) (B, x) (B, y) (B, z) (C, x) (C, y) (C, z)\n        /// </summary>\n        public static IEnumerable<(T, T)> Pairs<T>(this IEnumerable<T> self, IEnumerable<T> other)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other is null) throw new ArgumentNullException(nameof(other));\n\n            var a = self.ToArray();\n            var b = other.ToArray();\n            for (int i = 0; i < a.Length; i++)\n                for (int j = 0; j < b.Length; j++)\n                    yield return (a[i], b[j]);\n        }\n\n        #endregion\n\n        #region Triples\n\n        /// <summary>\n        /// A B C D ... -> (A, B, C) (D, E, F) ...\n        /// If sequence does not have even elements the last element is not selected.\n        /// </summary>\n        public static IEnumerable<(T, T, T)> TripleSequence<T>(this IEnumerable<T> self)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            var first = self.TakePeriodic(3);\n            var second = self.Skip(1).TakePeriodic(3);\n            var third = self.Skip(2).TakePeriodic(3);\n\n            return first.ZipTriples(second, third); //todo: very inefficient: triple enumeration\n        }\n\n        /// <summary>\n        /// wrap = false: A B C D ... -> (A, B, C) (B, C, D) (C, D, E) ...\n        /// wrap = true:  A B C D -> (A, B, C) (B, C, D) (C, D, A) (D, A, B)\n        /// </summary>\n        public static IEnumerable<(T, T, T)> TripleChain<T>(this IEnumerable<T> self, bool wrap = false)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            using (var e = self.GetEnumerator())\n            {\n                if (e.MoveNext())\n                {\n                    T first = e.Current;\n                    if (e.MoveNext())\n                    {\n                        T second = e.Current;\n                        T prev1 = first;\n                        T prev2 = second;\n                        while (e.MoveNext())\n                        {\n                            var x = e.Current;\n                            yield return (prev1, prev2, x);\n                            prev1 = prev2;\n                            prev2 = x;\n                        }\n                        if (wrap)\n                        {\n                            yield return (prev1, prev2, first);\n                            yield return (prev2, first, second);\n                        }\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// A B C D -> (A, B, C) (B, C, D) (C, D, A) (D, A, B)\n        /// </summary>\n        public static IEnumerable<(T, T, T)> TripleChainWrap<T>(this IEnumerable<T> self)\n        {\n            return TripleChain(self, true);\n        }\n\n        /// <summary>\n        /// A B C -> AAA, AAB, AAC, ABA, ABB, ABC, ACA, ACB, ACC, BAA, BAB, BAC, BBA, BBB, BBC, BCA, BCB, BCC, CAA, CAB, CAC, CBA, CBB, CBC, CCA, CCB, CCC\n        /// </summary>\n        public static IEnumerable<(T, T, T)> Triples<T>(this IEnumerable<T> self)\n        {\n            return Triples(self, false, false);\n        }\n\n        /// <summary>\n        /// A B C -> AAA, AAB, AAC, ABA, ABB, ABC, ACA, ACB, ACC, BAA, BAB, BAC, BBA, BBB, BBC, BCA, BCB, BCC, CAA, CAB, CAC, CBA, CBB, CBC, CCA, CCB, CCC\n        /// excludeIdenticalPairs: A B C -> ABC, CBA\n        /// excludeReversePairs:   A B C -> AAA, AAB, AAC, ABA, ABB, ABC, ACA, ACB, ACC, BAB, BAC, BBB, BBC, BCB, BCC, CAC, CBC, CCC\n        /// both:                  A B C -> ABC\n        /// </summary>\n        public static IEnumerable<(T, T, T)> Triples<T>(this IEnumerable<T> self, bool excludeIdenticalPairs, bool excludeReversePairs)\n        { //todo: check implementation; + what about excludePermutations? reversePairs do not extend to triples.\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            var a = self.ToArray();\n            for (int i = 0; i < a.Length; i++)\n                for (int j = excludeReversePairs ? i : 0; j < a.Length; j++)\n                {\n                    if (excludeIdenticalPairs && i == j) continue;\n                    for (int k = excludeReversePairs ? j : 0; k < a.Length; k++)\n                    {\n                        if (excludeIdenticalPairs && (j == k || i == k)) continue;\n                        yield return (a[i], a[j], a[k]);\n                    }\n                }\n        }\n\n        /// <summary>\n        /// [A B].Triples([x y], [X Y]) -> (A, x, X) (A, x, Y) (A, y, X) (A, y, Y) (B, x, X) (B, x, Y) (B, y, X) (B, y, Y) (C, x, X) (C, x, Y) (C, y, X) (C, y, Y)\n        /// </summary>\n        public static IEnumerable<(T, T, T)> Triples<T>(this IEnumerable<T> self, IEnumerable<T> other1, IEnumerable<T> other2)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (other1 is null) throw new ArgumentNullException(nameof(other1));\n            if (other2 is null) throw new ArgumentNullException(nameof(other2));\n\n            var a = self.ToArray();\n            var b = other1.ToArray();\n            var c = other2.ToArray();\n            for (int i = 0; i < a.Length; i++)\n                for (int j = 0; j < b.Length; j++)\n                    for (int k = 0; k < c.Length; k++)\n                        yield return (a[i], b[j], c[k]);\n        }\n\n        #endregion\n\n        #region Repetition\n\n        /// <summary>\n        /// Returns an enumeration which will infinitely yield copies of 'self'.\n        /// A.Repeat -> [A A A A ...]\n        /// </summary>\n        public static IEnumerable<T> Repeat<T>(this T self)\n        {\n            while (true) yield return self;\n        }\n\n        /// <summary>\n        /// Returns an enumeration which will yield 'count' copies of 'self'.\n        /// A.Repeat(3) -> [A A A]\n        /// </summary>\n        public static IEnumerable<T> Repeat<T>(this T self, long count)\n        {\n            if (count < 0) throw new ArgumentOutOfRangeException(nameof(count));\n\n            for (long i = 0; i < count; i++) yield return self;\n        }\n\n        /// <summary>\n        /// Appends an infinite number of copies of the sequence's last element.\n        /// [A B C].WithRepeatedLast() -> [A B C C C C C ...]\n        /// Does nothing for an empty sequence.\n        /// Throws an exception for a null sequence.\n        /// </summary>\n        public static IEnumerable<T> WithRepeatedLast<T>(this IEnumerable<T> self)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (self.IsEmptyOrNull()) yield break;\n\n            T last = default(T);\n            foreach (var x in self) yield return last = x;\n            while (true) yield return last;\n        }\n\n        /// <summary>\n        /// Duplicates each element of the sequence.\n        /// [A B C].DupElements() -> [A A B B C C]\n        /// </summary>\n        public static IEnumerable<T> Dup<T>(this IEnumerable<T> self)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            foreach (var x in self) { yield return x; yield return x; }\n        }\n\n        /// <summary>\n        /// Duplicates each element of the sequence n times.\n        /// [A B C].DupElements(4) -> [A A A A B B B B C C C C]\n        /// </summary>\n        public static IEnumerable<T> Dup<T>(this IEnumerable<T> self, int n)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (n < 0) throw new ArgumentOutOfRangeException(nameof(n));\n\n            foreach (var x in self)\n                for (int i = 0; i < n; i++)\n                    yield return x;\n        }\n\n        #endregion\n\n        #region Reordering\n\n        /// <summary>\n        /// Moves the first element to the end of the sequence.\n        /// [A B C].AddFirstToEnd() -> [A B C A]\n        /// </summary>\n        public static IEnumerable<T> AddFirstToEnd<T>(this IEnumerable<T> self)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            if (self.IsEmpty()) yield break;\n\n            var first = self.First();\n            foreach (var x in self)\n            {\n                yield return x;\n            }\n            yield return first;\n        }\n\n        /// <summary>\n        /// Moves the first element to the end of the sequence.\n        /// [A B C D E].MoveFirstToEnd() -> [B C D E A]\n        /// </summary>\n        public static IEnumerable<T> WithFirstMovedToEnd<T>(this IEnumerable<T> self)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            if (self.IsEmpty()) return self;\n            return self.Skip(1).Concat(self.Take(1));\n        }\n\n        /// <summary>\n        /// Interleaves given IEnumerable with specified element.\n        /// E.g. { 'A', 'B', 'C' }.Interleave('X') -> { 'A', 'X', 'B', 'X', 'C' }.\n        /// </summary>\n        public static IEnumerable<T> Interleave<T>(\n            this IEnumerable<T> self, T separator)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            bool notFirst = false;\n            foreach (var x in self)\n            {\n                if (notFirst) yield return separator; else notFirst = true;\n                yield return x;\n            }\n        }\n\n        #endregion\n\n        #region Grouping\n\n        /// <summary>\n        /// Groups enumeration by an array of keys.\n        /// </summary>\n        public static IEnumerable<TElement> FlatGroupByMany<TElement>(\n            this IEnumerable<TElement> elements,\n            params Func<TElement, object>[] groupSelectorFuncs)\n        {\n            if (elements is null) throw new ArgumentNullException(nameof(elements));\n            if (groupSelectorFuncs is null) throw new ArgumentNullException(nameof(groupSelectorFuncs));\n\n            IEnumerable<TElement> result = elements;\n            foreach (var selectorFunc in groupSelectorFuncs.Reverse())\n            {\n                if (selectorFunc is null) throw new ArgumentNullException(nameof(selectorFunc));\n                result = from g in\n                             (from item in result group item by selectorFunc(item))\n                         from e in g\n                         select e;\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region All\n\n        public static bool AllDistinct<T>(this IEnumerable<T> elements)\n        {\n            if (elements == null)\n                return true;\n\n            var set = new HashSet<T>();\n            foreach (var element in elements)\n                if (!set.Add(element))\n                    return false;\n\n            return true;\n        }\n\n        public static bool AllEqual<T>(this IEnumerable<T> elements)\n        {\n            if (elements == null)\n                return true;\n\n            using var enumerator = elements.GetEnumerator();\n            if (!enumerator.MoveNext())\n                return true;\n\n            var first = enumerator.Current;\n            var comparer = EqualityComparer<T>.Default;\n            while (enumerator.MoveNext())\n                if (!comparer.Equals(first, enumerator.Current))\n                    return false;\n\n            return true;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns true if elements contains no items or if elements is null, false otherwise.\n        /// </summary>\n        public static bool IsEmptyOrNull<T>(this T[] self) => self == null || self.Length == 0;\n\n        /// <summary>\n        /// Returns true if elements contains no items or if elements is null, false otherwise.\n        /// </summary>\n        public static bool IsEmptyOrNull<T>(this ICollection<T> self) => self == null || self.Count == 0;\n      \n        /// <summary>\n        /// Returns true if elements contains no items or if elements is null, false otherwise.\n        /// </summary>\n        public static bool IsEmptyOrNull<T>(this IEnumerable<T> elements) => elements == null || !elements.Any(); // will check for ICollection<T> internally\n\n        /// <summary>\n        /// Returns the input enumeration if it is not null, otherwise an empty enumeration.\n        /// </summary>\n        public static IEnumerable<T> NonNull<T>(IEnumerable<T> elements) => elements ?? Enumerable.Empty<T>();\n\n        /// <summary>\n        /// Compares both enumerables using SequenceEqual and additionally checks\n        /// whether both enumerables are null.\n        /// </summary>\n        public static bool EnumerableEquals<T>(this IEnumerable<T> self, IEnumerable<T> other)\n        {\n            if (self == null && other == null)\n                return true;\n            if (self != null && other == null)\n                return false;\n            if (self != null && self.SequenceEqual(other))\n                return true;\n            else\n                return false;\n        }\n\n        #endregion\n\n        #region Min/Max/Most\n\n        public static T Min<T>(this IEnumerable<T> seq, Func<T, T, bool> lessThan)\n        {\n            if (seq is null) throw new ArgumentNullException(nameof(seq));\n            if (lessThan is null) throw new ArgumentNullException(nameof(lessThan));\n            if (seq.IsEmptyOrNull()) throw new ArgumentNullException(nameof(seq));\n\n            var min = seq.First();\n            foreach (var x in seq.Skip(1))\n                if (lessThan(x, min)) min = x;\n            return min;\n        }\n\n        public static T Max<T>(this IEnumerable<T> seq, Func<T, T, bool> greaterThan)\n        {\n            if (seq is null) throw new ArgumentNullException(nameof(seq));\n            if (greaterThan is null) throw new ArgumentNullException(nameof(greaterThan));\n            if (seq.IsEmptyOrNull()) throw new ArgumentNullException(nameof(seq));\n\n            var max = seq.First();\n            foreach (var x in seq.Skip(1))\n                if (greaterThan(x, max)) max = x;\n            return max;\n        }\n\n        /// <summary>\n        /// Aardvark.Runtime.IEnumerableExtensions:\n        /// No-Throw version. Finds the smallest element in seq according to lessThan, that is smaller than maxValue, or the first such element if there are equally small elements, or maxValue if no element is smaller.\n        /// For normal operation set maxValue = +Inf or the maximum of T.\n        /// </summary>\n        public static T Min<T>(this IEnumerable<T> seq, Func<T, T, bool> lessThan, T maxValue)\n        {\n            var min = maxValue;\n            foreach (var x in seq)\n                if (lessThan(x, min)) min = x;\n            return min;\n        }\n\n        /// <summary>\n        /// Aardvark.Runtime.IEnumerableExtensions:\n        /// No-Throw version. Finds the largest element in seq according to greaterThan, that is greater than minValue, or the first such element if there are equally large elements, or minValue if no element is greater.\n        /// For normal operation set minValue = -Inf or the minimum of T.\n        /// </summary>\n        public static T Max<T>(this IEnumerable<T> seq, Func<T, T, bool> greaterThan, T minValue)\n        {\n            var max = minValue;\n            foreach (var x in seq)\n                if (greaterThan(x, max)) max = x;\n            return max;\n        }\n\n        /// <summary>\n        /// Aardvark.Runtime.IEnumerableExtensions:\n        /// Invokes a transform function on each element of a sequence and\n        /// returns the element that yielded the maximum value (and the maximum value in rv_maxVal).\n        /// Only elements that yield larger values than minVal are considered.\n        /// If multiple elements yield the maximum value, the first in the sequence is chosen.\n        /// </summary>\n        /// <typeparam name=\"TSrc\">The type of the elements of source.</typeparam>\n        /// <typeparam name=\"TDst\">The type in which the elements are to be transformed before being compared.</typeparam>\n        /// <param name=\"source\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"selector\">A transform function to apply to each element.</param>\n        /// <param name=\"greaterThan\">A function how to compare elements of type TDst. greaterThan(a,b) => a>b (Sorry, is needed for general operation without providing a function for all types.)</param>\n        /// <param name=\"minVal\">An element in the sequence has to yield a value larger than this to be considered.</param>\n        /// <param name=\"defaultRv\">The return value if no element is greater than minVal, or the source is empty.</param>\n        /// <param name=\"rv_maxVal\">The maximum value found, or minVal if no element yielded a larger value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">source, selector or greaterThan is null.</exception>\n        public static TSrc MaxElement<TSrc, TDst>(this IEnumerable<TSrc> source, Func<TSrc, TDst> selector, Func<TDst, TDst, bool> greaterThan, TDst minVal, TSrc defaultRv, out TDst rv_maxVal)\n        {\n            if (source == null) throw new ArgumentNullException();\n            if (selector == null) throw new ArgumentNullException();\n            if (greaterThan == null) throw new ArgumentNullException();\n            var e = source.GetEnumerator();\n            TSrc maxEl = defaultRv;\n            rv_maxVal = minVal;\n            while (e.MoveNext())\n            {\n                TSrc el = e.Current;\n                TDst val = selector(el);\n                if (greaterThan(val, rv_maxVal))\n                {\n                    rv_maxVal = val;\n                    maxEl = el;\n                }\n            }\n            return maxEl;\n        }\n\n        /// <summary>\n        /// Aardvark.Runtime.IEnumerableExtensions:\n        /// Invokes a transform function on each element of a sequence and\n        /// returns the element that yielded the minimum value (and the minimum value in rv_minVal).\n        /// Only elements that yield smaller values than maxVal are considered.\n        /// If multiple elements yield the minimum value, the first in the sequence is chosen.\n        /// </summary>\n        /// <typeparam name=\"TSrc\">The type of the elements of source.</typeparam>\n        /// <typeparam name=\"TDst\">The type in which the elements are to be transformed before being compared.</typeparam>\n        /// <param name=\"source\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"selector\">A transform function to apply to each element.</param>\n        /// <param name=\"smallerThan\">A function how to compare elements of type TDst. smallerThan(a,b) => a&lt;b (Sorry, is needed for general operation without providing a function for all types.)</param>\n        /// <param name=\"maxVal\">An element in the sequence has to yield a value smaller than this to be considered.</param>\n        /// <param name=\"defaultRv\">The return value if no element is smaller than maxVal, or the source is empty.</param>\n        /// <param name=\"rv_minVal\">The minimum value found, or maxVal if no element yielded a larger value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">source, selector or smallerThan is null.</exception>\n        public static TSrc MinElement<TSrc, TDst>(this IEnumerable<TSrc> source, Func<TSrc, TDst> selector, Func<TDst, TDst, bool> smallerThan, TDst maxVal, TSrc defaultRv, out TDst rv_minVal)\n        {\n            if (source == null) throw new ArgumentNullException();\n            if (selector == null) throw new ArgumentNullException();\n            if (smallerThan == null) throw new ArgumentNullException();\n            var e = source.GetEnumerator();\n            TSrc minEl = defaultRv;\n            rv_minVal = maxVal;\n            while (e.MoveNext())\n            {\n                TSrc el = e.Current;\n                TDst val = selector(el);\n                if (smallerThan(val, rv_minVal))\n                {\n                    rv_minVal = val;\n                    minEl = el;\n                }\n            }\n            return minEl;\n        }\n\n        /// <summary>\n        /// Returns true if more elements than not satisfy the given predicate.\n        /// </summary>\n        public static bool Most<T>(this IEnumerable<T> self, Func<T, bool> predicate)\n        {\n            Contract.Requires(self != null);\n            long countTrue = 0;\n            long countFalse = 0;\n            foreach (var x in self)\n                if (predicate(x)) countTrue++; else countFalse++;\n            return countTrue > countFalse;\n        }\n\n        #endregion\n\n        #region Min/Max-Index\n\n        public static int MinIndex<T>(this IEnumerable<T> self, Func<T, T, bool> lessThan, out T minValue)\n        {\n            var e = self.GetEnumerator();\n            if (!e.MoveNext())\n            {\n                minValue = default(T);\n                return -1;\n            }\n\n            var currentMinValue = e.Current;\n            var currentMinIndex = 0;\n            var index = 1;\n            while (e.MoveNext())\n            {\n                if (lessThan(e.Current, currentMinValue))\n                {\n                    currentMinValue = e.Current;\n                    currentMinIndex = index;\n                }\n                index++;\n            }\n\n            minValue = currentMinValue;\n            return currentMinIndex;\n        }\n\n        public static int MaxIndex<T>(this IEnumerable<T> self, Func<T, T, bool> greaterThan, out T maxValue)\n        {\n            var e = self.GetEnumerator();\n            if (!e.MoveNext())\n            {\n                maxValue = default(T);\n                return -1;\n            }\n\n            var currentMaxValue = e.Current;\n            var currentMaxIndex = 0;\n            var index = 1;\n            while (e.MoveNext())\n            {\n                if (greaterThan(e.Current, currentMaxValue))\n                {\n                    currentMaxValue = e.Current;\n                    currentMaxIndex = index;\n                }\n                index++;\n            }\n\n            maxValue = currentMaxValue;\n            return currentMaxIndex;\n        }\n\n        public static int MinIndex<T>(this IEnumerable<T> self, out T minValue)\n            where T : IComparable<T>\n        {\n            return MinIndex(self, (a, b) => a.CompareTo(b) < 0, out minValue);\n        }\n\n        public static int MaxIndex<T>(this IEnumerable<T> self, out T minValue)\n            where T : IComparable<T>\n        {\n            return MaxIndex(self, (a, b) => a.CompareTo(b) > 0, out minValue);\n        }\n\n        public static int MinIndex<T>(this IEnumerable<T> self)\n           where T : IComparable<T>\n        {\n            T foo;\n            return MinIndex(self, (a, b) => a.CompareTo(b) < 0, out foo);\n        }\n\n        public static int MaxIndex<T>(this IEnumerable<T> self)\n            where T : IComparable<T>\n        {\n            T foo;\n            return MaxIndex(self, (a, b) => a.CompareTo(b) > 0, out foo);\n        }\n\n\n        public static int MinIndex<T>(this T[] self, Func<T, T, bool> lessThan, out T minValue)\n        {\n            if (self.Length <= 0)\n            {\n                minValue = default(T);\n                return -1;\n            }\n\n            var currentMinValue = self[0];\n            var currentMinIndex = 0;\n            for(int i = 1; i < self.Length; i++)\n            {\n                if (lessThan(self[i], currentMinValue))\n                {\n                    currentMinValue = self[i];\n                    currentMinIndex = i;\n                }\n            }\n\n            minValue = currentMinValue;\n            return currentMinIndex;\n        }\n\n        public static int MaxIndex<T>(this T[] self, Func<T, T, bool> greaterThan, out T maxValue)\n        {\n            if (self.Length <= 0)\n            {\n                maxValue = default(T);\n                return -1;\n            }\n\n            var currentMaxValue = self[0];\n            var currentMaxIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (greaterThan(self[i], currentMaxValue))\n                {\n                    currentMaxValue = self[i];\n                    currentMaxIndex = i;\n                }\n            }\n\n            maxValue = currentMaxValue;\n            return currentMaxIndex;\n        }\n\n        public static int MinIndex<T>(this T[] self, out T minValue)\n            where T : IComparable<T>\n        {\n            return MinIndex(self, (a, b) => a.CompareTo(b) < 0, out minValue);\n        }\n\n        public static int MaxIndex<T>(this T[] self, out T maxValue)\n            where T : IComparable<T>\n        {\n            return MaxIndex(self, (a, b) => a.CompareTo(b) > 0, out maxValue);\n        }\n\n        public static int MinIndex<T>(this T[] self)\n            where T : IComparable<T>\n        {\n            T foo;\n            return MinIndex(self, (a, b) => a.CompareTo(b) < 0, out foo);\n        }\n\n        public static int MaxIndex<T>(this T[] self)\n            where T : IComparable<T>\n        {\n            T foo;\n            return MaxIndex(self, (a, b) => a.CompareTo(b) > 0, out foo);\n        }\n\n\n        public static int MinIndex<T>(this List<T> self, Func<T, T, bool> lessThan, out T minValue)\n        {\n            if (self.Count <= 0)\n            {\n                minValue = default(T);\n                return -1;\n            }\n\n            var currentMinValue = self[0];\n            var currentMinIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (lessThan(self[i], currentMinValue))\n                {\n                    currentMinValue = self[i];\n                    currentMinIndex = i;\n                }\n            }\n\n            minValue = currentMinValue;\n            return currentMinIndex;\n        }\n\n        public static int MaxIndex<T>(this List<T> self, Func<T, T, bool> greaterThan, out T maxValue)\n        {\n            if (self.Count <= 0)\n            {\n                maxValue = default(T);\n                return -1;\n            }\n\n            var currentMaxValue = self[0];\n            var currentMaxIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (greaterThan(self[i], currentMaxValue))\n                {\n                    currentMaxValue = self[i];\n                    currentMaxIndex = i;\n                }\n            }\n\n            maxValue = currentMaxValue;\n            return currentMaxIndex;\n        }\n\n        public static int MinIndex<T>(this List<T> self, out T minValue)\n            where T : IComparable<T>\n        {\n            return MinIndex(self, (a, b) => a.CompareTo(b) < 0, out minValue);\n        }\n\n        public static int MaxIndex<T>(this List<T> self, out T maxValue)\n            where T : IComparable<T>\n        {\n            return MaxIndex(self, (a, b) => a.CompareTo(b) > 0, out maxValue);\n        }\n\n        public static int MinIndex<T>(this List<T> self)\n            where T : IComparable<T>\n        {\n            T foo;\n            return MinIndex(self, (a, b) => a.CompareTo(b) < 0, out foo);\n        }\n\n        public static int MaxIndex<T>(this List<T> self)\n            where T : IComparable<T>\n        {\n            T foo;\n            return MaxIndex(self, (a, b) => a.CompareTo(b) > 0, out foo);\n        }\n\n        #region Specializations\n\n        public static int MinIndex(this byte[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this sbyte[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this short[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this ushort[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this int[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this uint[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this long[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this ulong[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this float[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this double[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this decimal[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n\n        public static int MaxIndex(this byte[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this sbyte[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this short[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this ushort[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this int[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this uint[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this long[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this ulong[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this float[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this double[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this decimal[] self)\n        {\n            if (self == null || self.Length == 0) throw new ArgumentException();\n            if (self.Length == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Length; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n\n        public static int MinIndex(this List<byte> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<sbyte> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<short> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<ushort> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<int> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<uint> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<long> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<ulong> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<float> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<double> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MinIndex(this List<decimal> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] < bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n\n        public static int MaxIndex(this List<byte> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<sbyte> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<short> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<ushort> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<int> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<uint> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<long> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<ulong> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<float> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<double> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n        public static int MaxIndex(this List<decimal> self)\n        {\n            if (self == null || self.Count == 0) throw new ArgumentException();\n            if (self.Count == 1) return 0;\n            var bestValue = self[0];\n            var bestIndex = 0;\n            for (int i = 1; i < self.Count; i++)\n            {\n                if (self[i] > bestValue)\n                {\n                    bestValue = self[i];\n                    bestIndex = i;\n                }\n            }\n            return bestIndex;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Predicates\n\n        public static bool TrueForAny<T>(\n                this IEnumerable<T> sequence, Func<T, bool> predicate)\n        {\n            foreach (var item in sequence)\n                if (predicate(item)) return true;\n            return false;\n        }\n\n        public static bool TrueForAll<T>(\n                this IEnumerable<T> sequence, Func<T, bool> predicate)\n        {\n            foreach (var item in sequence)\n                if (!predicate(item)) return false;\n            return true;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static T[] ToArrayDebug<T>(this IEnumerable<T> self)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n\n            var array = self.ToArray();\n            return array;\n        }\n\n        /// <summary>\n        /// Outputs the enumeration in the form \"(begin)element0(between)element1[...](end)\".\n        /// Each element is formatted by the delegate format.\n        /// You may set any parameter to null, in which case the default values\n        /// (v => v.ToString(), \"\", \", \", \"\") are used.\n        /// </summary>\n        public static string ToString<T>(\n            this IEnumerable<T> self, Func<T, string> format, string begin = null, string between = null, string end = null)\n        {\n            if (self is null) throw new ArgumentNullException(nameof(self));\n            if (format==null)\n                format = v => v == null ? \"\" : v.ToString();\n            if (begin == null)\n                begin = \"\";\n            if (between == null)\n                between = \", \";\n            if (end == null)\n                end = \"\";\n\n            var sb = new StringBuilder(begin);\n            bool first = true;\n            foreach (var e in self)\n            {\n                if (!first)\n                    sb.Append(between);\n                first = false;\n                sb.Append(format(e));\n            }\n            sb.Append(end);\n            return sb.ToString();\n        }\n\n        /// <summary>\n        /// Creates a Dictionary(of TKey,TValue) from an IEnumerable(of TSource)\n        ///  according to specified key selector and element selector functions.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements of source.</typeparam>\n        /// <typeparam name=\"TKey\">The type of the key returned by keySelector.</typeparam>\n        /// <typeparam name=\"TElement\">The type of the value returned by elementSelector.</typeparam>\n        /// <param name=\"source\">An IEnumerable(of TSource) to create a Dictionary(of TKey,TValue) from.</param>\n        /// <param name=\"keySelector\">A function to extract a key from each element.</param>\n        /// <param name=\"elementSelector\">A transform function to produce a result element value from each element.</param>\n        /// <param name=\"duplicateValue\">If a duplicate key was found, insert this element as value for the key. This value must be distinct from all other values generated by elementSelector.</param>\n        /// <returns>A Dictionary(of TKey,TValue) that contains values of type TElement selected from the input sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\">source or keySelector or elementSelector is null. -or- keySelector produces a key that is null.</exception>\n        public static Dictionary<TKey, TElement> ToDictionaryDistinct<TSource, TKey, TElement>(\n            this IEnumerable<TSource> source,\n            Func<TSource, TKey> keySelector,\n            Func<TSource, TElement> elementSelector,\n            TElement duplicateValue\n            )\n        {\n            if (source is null) throw new ArgumentNullException(nameof(source));\n            if (keySelector is null) throw new ArgumentNullException(nameof(keySelector));\n            if (elementSelector is null) throw new ArgumentNullException(nameof(elementSelector));\n\n            Dictionary<TKey, TElement> dictionary = new Dictionary<TKey, TElement>();\n            foreach (TSource local in source)\n            {\n                try\n                {\n                    dictionary.Add(keySelector(local), elementSelector(local));\n                }\n                catch (ArgumentException)\n                { //An element with the same key already exists in the Dictionary<TKey,TValue>.\n                    dictionary[keySelector(local)] = duplicateValue;\n                }\n            }\n            return dictionary;\n        }\n\n        /// <summary>\n        /// Creates a Dictionary(of TKey,TValue) from an IEnumerable(of TSource)\n        /// containing all Key Value pairs with distinct keys.\n        /// For duplicate keys, the returned value of <paramref name=\"duplicateKeyKeepElement\"/> is inserted instead.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements of source.</typeparam>\n        /// <typeparam name=\"TKey\">The type of the key returned by keySelector.</typeparam>\n        /// <typeparam name=\"TElement\">The type of the value returned by elementSelector.</typeparam>\n        /// <param name=\"source\">An IEnumerable(of T) to create a Dictionary(of TKey,TValue) from.</param>\n        /// <param name=\"keySelector\">A function to extract a key from each element.</param>\n        /// <param name=\"elementSelector\">A transform function to produce a result element value from each element.</param>\n        /// <param name=\"duplicateKeyKeepElement\">If a duplicate key was found, the function is called with the element to be inserted and the duplicate element already associated with the key, and must return true if the first (original) element should be kept of false if the second (new) element should be inserted.</param>\n        /// <returns>A System.Collections.Generic.Dictionary(of TKey,TValue) that contains values of type TElement selected from the input sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\">Any of the arguments is null. -or- keySelector produces a key that is null.</exception>\n        public static Dictionary<TKey, TElement> ToDictionaryDistinct<TSource, TKey, TElement>(\n            this IEnumerable<TSource> source,\n            Func<TSource, TKey> keySelector,\n            Func<TSource, TElement> elementSelector,\n            Func<TElement, TElement, bool> duplicateKeyKeepElement)\n        {\n            if (source is null) throw new ArgumentNullException(nameof(source));\n            if (keySelector is null) throw new ArgumentNullException(nameof(keySelector));\n            if (elementSelector is null) throw new ArgumentNullException(nameof(elementSelector));\n            if (duplicateKeyKeepElement is null) throw new ArgumentNullException(nameof(duplicateKeyKeepElement));\n\n            var dictionary = new Dictionary<TKey, TElement>();\n            foreach (var v in source)\n            {\n                var key = keySelector(v);\n                var element = elementSelector(v);\n                try\n                {\n                    dictionary.Add(key, element);\n                }\n                catch (ArgumentException)\n                { //[inefficient ISSUE 20091202 andi] Unfortunately very inefficient because of Dictionary implementation, since it is necessary to hash 3 times!\n                    if(!duplicateKeyKeepElement(dictionary[key], element))\n                        dictionary[key] = element;\n                }\n            }\n            return dictionary;\n        }\n\n        /// <summary>\n        /// Creates a Dictionary(of TKey,TValue) from an IEnumerable(of TSource)\n        /// containing all Key Value pairs with distinct keys.\n        /// For duplicate keys, the returned value of <paramref name=\"duplicateKeyElementSelector\"/> is inserted instead.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements of source.</typeparam>\n        /// <typeparam name=\"TKey\">The type of the key returned by keySelector.</typeparam>\n        /// <typeparam name=\"TElement\">The type of the value returned by elementSelector.</typeparam>\n        /// <param name=\"source\">An IEnumerable(of T) to create a Dictionary(of TKey,TValue) from.</param>\n        /// <param name=\"keySelector\">A function to extract a key from each element.</param>\n        /// <param name=\"elementSelector\">A transform function to produce a result element value from each element.</param>\n        /// <param name=\"duplicateKeyElementSelector\">If a duplicate key was found, the function is called with the element to be inserted and the duplicate element already associated with the key, and must return the element to be inserted instead at this key.</param>\n        /// <returns>A System.Collections.Generic.Dictionary(of TKey,TValue) that contains values of type TElement selected from the input sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\">Any of the arguments is null. -or- keySelector produces a key that is null.</exception>\n        public static Dictionary<TKey, TElement> ToDictionaryDistinct<TSource, TKey, TElement>(\n            this IEnumerable<TSource> source,\n            Func<TSource, TKey> keySelector,\n            Func<TSource, TElement> elementSelector,\n            Func<TElement, TElement, TElement> duplicateKeyElementSelector\n            )\n        {\n            if (source is null) throw new ArgumentNullException(nameof(source));\n            if (keySelector is null) throw new ArgumentNullException(nameof(keySelector));\n            if (elementSelector is null) throw new ArgumentNullException(nameof(elementSelector));\n            if (duplicateKeyElementSelector is null) throw new ArgumentNullException(nameof(duplicateKeyElementSelector));\n\n            var dictionary = new Dictionary<TKey, TElement>();\n            foreach (var v in source)\n            {\n                var key = keySelector(v);\n                var element = elementSelector(v);\n                try\n                {\n                    dictionary.Add(key, element);\n                }\n                catch (ArgumentException)\n                { //[inefficient ISSUE 20091202 andi] Unfortunately very inefficient because of Dictionary implementation, since it is necessary to hash 3 times!\n                    dictionary[key] = duplicateKeyElementSelector(dictionary[key], element);\n                }\n            }\n            return dictionary;\n        }\n\n        /// <summary>\n        /// This is a more efficient version of System.Linq.Enumerable.ToArray() when the number of elements of <paramref name=\"source\"/> cannot be efficiently determined but is known.\n        /// Creates an array from a <see cref=\"T:System.Collections.Generic.IEnumerable`1\" />.\n        /// </summary>\n        /// <returns>An array of size count that contains the elements from the input sequence.</returns>\n        /// <param name=\"source\">An <see cref=\"T:System.Collections.Generic.IEnumerable`1\" /> to create an array from.</param>\n        /// <param name=\"count\">The known size of the result-array.</param>\n        /// <exception cref=\"T:System.ArgumentNullException\"><paramref name=\"source\" /> is null.</exception>\n        /// <exception cref=\"T:System.ArgumentException\"><paramref name=\"count\"/> is different from the number of elements in <paramref name=\"source\" />.</exception>\n        public static TElement[] ToArray<TElement>(this IEnumerable<TElement> source, int count)\n        {\n            if (count == 0)\n            {\n                return Array.Empty<TElement>();\n            }\n            else\n            {\n                TElement[] array = null;\n                int num = 0;\n                ICollection<TElement> collection = source as ICollection<TElement>;\n                if (collection != null)\n                {\n                    num = collection.Count;\n                    array = new TElement[num];\n                    if (num > 0)\n                    {\n                        collection.CopyTo(array, 0);\n                    }\n                }\n                else\n                {\n                    array = new TElement[count];\n                    foreach (TElement current in source)\n                    {\n                        if (count == num)\n                            throw new ArgumentException(\"Enumerable has more elements than count.\", \"count\");\n                        array[num] = current;\n                        num++;\n                    }\n                }\n                if (count > num)\n                    throw new ArgumentException(\"Enumerable has less elements than count.\", \"count\");\n                return array;\n            }\n        }\n\n        #endregion\n\n        #region Missing Operators\n\n        /// <summary>\n        /// Lazily applies action to each element of sequence.\n        /// </summary>\n        public static IEnumerable<T> Do<T>(this IEnumerable<T> self, Action<T> action)\n        {\n            foreach (var x in self)\n            {\n                action(x);\n                yield return x;\n            }\n        }\n\n        /// <summary>\n        /// Lazily applies action to each element of sequence.\n        /// </summary>\n        public static IEnumerable<T> Do<T>(this IEnumerable<T> self, Action<T, long> action)\n        {\n            long index = 0;\n            foreach (var x in self)\n            {\n                action(x, index++);\n                yield return x;\n            }\n        }\n\n        /// <summary>\n        /// Creates sequence containing the given item.\n        /// </summary>\n        public static IEnumerable<T> Return<T>(this T item)\n        {\n            yield return item;\n        }\n\n        /// <summary>\n        /// Determines whether an array contains no elements.\n        /// </summary>\n        public static bool IsEmpty<T>(this T[] self) => self.Length == 0;\n\n        /// <summary>\n        /// Determines whether a sequence contains no elements.\n        /// </summary>\n        public static bool IsEmpty<T>(this ICollection<T> self) => self.Count == 0;\n\n        /// <summary>\n        /// Determines whether a sequence contains no elements.\n        /// </summary>\n        public static bool IsEmpty<T>(this IEnumerable<T> self) => !self.Any(); // checks for ICollection internally\n        \n        /// <summary>\n        /// Returns a sequence that contains only distinct contiguous elements.\n        /// </summary>\n        public static IEnumerable<T> DistinctUntilChanged<T>(this IEnumerable<T> self)\n            where T : IEquatable<T>\n        {\n            bool first = true;\n            T current = default(T);\n            foreach (var x in self)\n            {\n                if (first) first = false;\n                else if (x.Equals(current)) continue;\n                current = x;\n                yield return current;\n            }\n        }\n\n        /// <summary>\n        /// Returns index of first occurence of elementToFind.\n        /// </summary>\n        public static int IndexOf<T>(this IEnumerable<T> list, T elementToFind)\n        {\n            int i = 0;\n            foreach (T element in list)\n            {\n                if (element.Equals(elementToFind))\n                    return i;\n                i++;\n            }\n            return -1;\n        }\n\n        /// <summary>\n        /// Concats single item to sequence.\n        /// </summary>\n        public static IEnumerable<T> Concat<T>(this IEnumerable<T> sequence, T item)\n        {\n            foreach (var x in sequence) yield return x;\n            yield return item;\n        }\n\n        /// <summary>\n        /// Concats sequence to single item.\n        /// </summary>\n        public static IEnumerable<T> Concat<T>(this T item, IEnumerable<T> sequence)\n        {\n            yield return item;\n            foreach (var x in sequence) yield return x;\n        }\n\n        /// <summary>\n        /// Returns sequence of indices [0, sequence.Count()-1].\n        /// </summary>\n        public static IEnumerable<int> Indices<T>(this IEnumerable<T> sequence)\n        {\n            var i = 0;\n            foreach (var x in sequence) yield return i++;\n        }\n\n        public static IEnumerable<T> SelectMany<T>(this IEnumerable<(T, T)> self)\n        {\n            foreach (var x in self)\n            {\n                yield return x.Item1;\n                yield return x.Item2;\n            }\n        }\n\n        public static IEnumerable<R> SelectMany<T, R>(this IEnumerable<T> self, Func<T, (R, R)> projection)\n        {\n            foreach (var y in self)\n            {\n                var x = projection(y);\n                yield return x.Item1;\n                yield return x.Item2;\n            }\n        }\n\n        public static IEnumerable<T> SelectMany<T>(this IEnumerable<(T, T, T)> self)\n        {\n            foreach (var x in self)\n            {\n                yield return x.Item1;\n                yield return x.Item2;\n                yield return x.Item3;\n            }\n        }\n\n        public static IEnumerable<R> SelectMany<T, R>(this IEnumerable<T> self, Func<T, (R, R, R)> projection)\n        {\n            foreach (var y in self)\n            {\n                var x = projection(y);\n                yield return x.Item1;\n                yield return x.Item2;\n                yield return x.Item3;\n            }\n        }\n\n        public static IEnumerable<T> SelectMany<T>(this IEnumerable<(T, T, T, T)> self)\n        {\n            foreach (var x in self)\n            {\n                yield return x.Item1;\n                yield return x.Item2;\n                yield return x.Item3;\n                yield return x.Item4;\n            }\n        }\n\n        public static IEnumerable<R> SelectMany<T, R>(this IEnumerable<T> self, Func<T, (R, R, R, R)> projection)\n        {\n            foreach (var y in self)\n            {\n                var x = projection(y);\n                yield return x.Item1;\n                yield return x.Item2;\n                yield return x.Item3;\n                yield return x.Item4;\n            }\n        }\n\n        #endregion\n\n        #region Math\n\n        /// <summary>\n        /// Converts a sequence that contains numbers of elements\n        /// into a sequence that represents the indices of the\n        /// first element if the elements are stored in consecutive\n        /// order and is closed by the total count elements.\n        /// The length of the integrated sequence is +1 of the input.\n        /// </summary>\n        public static IEnumerable<int> Integrated(this IEnumerable<int> counts, int sum = 0)\n        {\n            foreach (var c in counts)\n            {\n                yield return sum;\n                sum += c;\n            }\n            yield return sum;\n        }\n\n        /// <summary>\n        /// Integrates a sequence of values.\n        /// Returns a sequence of N+1 values where the last is the sum off all value.\n        /// </summary>\n        public static IEnumerable<double> Integrated(this IEnumerable<double> values, double sum = 0)\n        {\n            foreach (var c in values)\n            {\n                yield return sum;\n                sum += c;\n            }\n            yield return sum;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/IListExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class IListExtensions\n    {\n        /// <summary>\n        /// Swap the two elements specified by ther indices.\n        /// </summary>\n        public static void Swap<T>(this IList<T> self, int i, int j)\n        {\n            T help = self[i]; self[i] = self[j]; self[j] = help;\n        }\n\n        public static SubRange<T> SubRange<T>(this IList<T> self, int index, int count)\n            => new SubRange<T>(self, index, count);\n\n        #region FindIndex\n\n        /// <summary>\n        /// Searches for an element that matches the conditions defined by the specified predicate, \n        /// and returns the zero-based index of the first occurrence within the range of elements in the IList(of T) \n        /// that starts at the <paramref name=\"startIndex\"/> and contains <paramref name=\"count\"/> elements.\n        /// If startSearch differs from startIndex, a cyclic search is performed in the range starting at <paramref name=\"startSearch\"/>.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the elements of the IList(of T).</typeparam>\n        /// <param name=\"list\">The list to search.</param>\n        /// <param name=\"startIndex\">The zero-based starting index of the search range.</param>\n        /// <param name=\"count\">The number of elements in the search range.</param>\n        /// <param name=\"startSearch\">The first element to search in a cyclic manner. Will be wrapped around, if outside [startIndex, startIndex+count-1]. Non-cyclick search if this equals <paramref name=\"startIndex\"/>.</param>\n        /// <param name=\"forward\">If true the search is performed in direction of increasing indices, else in the direction of decreasing indices.</param>\n        /// <param name=\"match\">The Predicate(of T) that defines the conditions of the element to search for.</param>\n        /// <returns>The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, –1.</returns>\n        public static int FindIndex<T>(this IList<T> list, int startIndex, int count, bool forward, int startSearch, Predicate<T> match)\n        {\n            if (list == null)\n                throw new ArgumentNullException(\"list\");\n            var listCount = list.Count;\n            if ((startIndex < 0) || (startIndex > listCount))\n                throw new ArgumentOutOfRangeException(\"startIndex\", \"Index was out of range. Must be non-negative and less than the size of the collection.\");\n            if ((count < 0) || (startIndex > (listCount - count)))\n                throw new ArgumentOutOfRangeException(\"count\", \"Count must be positive and count must refer to a location within the string/array/collection.\");\n            if (match == null)\n                throw new ArgumentNullException(\"match\");\n            if (count == 0)\n                return -1;\n            int endIndex = startIndex + count;\n            if ((startSearch < startIndex) || (startSearch >= endIndex))\n            {\n                //wrap around startSearch to be in the interval [startIndex, startIndex+count-1]\n                startSearch = (startSearch - startIndex) % count;\n                if (startSearch < 0)\n                    startSearch += count; //this is the ModP implementation. Since Fun.ModP() is in Aardvark.Math it is not accessible here.\n                startSearch += startIndex;\n            }\n            if (forward)\n            {\n                for (int i = startSearch; i < endIndex; i++)\n                    if (match(list[i]))\n                        return i;\n                for (int i = startIndex; i < startSearch; i++)\n                    if (match(list[i]))\n                        return i;\n            }\n            else\n            {\n                for (int i = startSearch; i >= startIndex; i--)\n                    if (match(list[i]))\n                        return i;\n                for (int i = endIndex - 1; i > startSearch; i--)\n                    if (match(list[i]))\n                        return i;\n            }\n            return -1;\n        }\n\n        /// <summary>\n        /// Searches for an element that matches the conditions defined by the specified predicate, \n        /// and returns the zero-based index of the first occurrence within the range of elements in the IList(of T) \n        /// that starts at the <paramref name=\"startIndex\"/> and contains <paramref name=\"count\"/> elements.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the elements of the IList(of T).</typeparam>\n        /// <param name=\"list\">The list to search.</param>\n        /// <param name=\"startIndex\">The zero-based starting index of the search range.</param>\n        /// <param name=\"count\">The number of elements in the search range.</param>\n        /// <param name=\"forward\">If true the search is performed in direction of increasing indices, else in the direction of decreasing indices.</param>\n        /// <param name=\"match\">The Predicate(of T) that defines the conditions of the element to search for.</param>\n        /// <returns>The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, –1.</returns>\n        public static int FindIndex<T>(this IList<T> list, int startIndex, int count, bool forward, Predicate<T> match)\n            => FindIndex(list, startIndex, count, forward, startIndex, match);\n\n        /// <summary>\n        /// Searches for an element that matches the conditions defined by the specified predicate, \n        /// and returns the zero-based index of the first occurrence within the range of elements in the IList(of T) \n        /// that extends from the <paramref name=\"startIndex\"/> to the end of the list.\n        /// If startSearch differs from startIndex, a cyclic search is performed in the range starting at <paramref name=\"startSearch\"/>.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the elements of the IList(of T).</typeparam>\n        /// <param name=\"list\">The list to search.</param>\n        /// <param name=\"startIndex\">The zero-based starting index of the search range.</param>\n        /// <param name=\"startSearch\">The first element to search in a cyclic manner. Non-cyclick search if this equals <paramref name=\"startIndex\"/></param>\n        /// <param name=\"forward\">If true the search is performed in direction of increasing indices, else in the direction of decreasing indices.</param>\n        /// <param name=\"match\">The Predicate(of T) that defines the conditions of the element to search for.</param>\n        /// <returns>The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, –1.</returns>\n        public static int FindIndex<T>(this IList<T> list, int startIndex, bool forward, int startSearch, Predicate<T> match)\n        {\n            if(list == null)\n                throw new ArgumentNullException(\"list\");\n            return FindIndex(list, startIndex, list.Count - startIndex, forward, startSearch, match);\n        }\n\n        /// <summary>\n        /// Searches for an element that matches the conditions defined by the specified predicate, \n        /// and returns the zero-based index of the first occurrence within the range of elements in the IList(of T) \n        /// that extends from the <paramref name=\"startIndex\"/> to the end of the list.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the elements of the IList(of T).</typeparam>\n        /// <param name=\"list\">The list to search.</param>\n        /// <param name=\"startIndex\">The zero-based starting index of the search range.</param>\n        /// <param name=\"forward\">If true the search is performed in direction of increasing indices, else in the direction of decreasing indices.</param>\n        /// <param name=\"match\">The Predicate(of T) that defines the conditions of the element to search for.</param>\n        /// <returns>The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, –1.</returns>\n        public static int FindIndex<T>(this IList<T> list, int startIndex, bool forward, Predicate<T> match)\n            => FindIndex(list, startIndex, forward, startIndex, match);\n\n        /// <summary>\n        /// Searches for an element that matches the conditions defined by the specified predicate, \n        /// and returns the zero-based index of the first occurrence.\n        /// If startSearch differs from startIndex, a cyclic search is performed in the range starting at <paramref name=\"startSearch\"/>.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the elements of the IList(of T).</typeparam>\n        /// <param name=\"list\">The list to search.</param>\n        /// <param name=\"startSearch\">The first element to search in a cyclic manner.</param>\n        /// <param name=\"forward\">If true the search is performed in direction of increasing indices, else in the direction of decreasing indices.</param>\n        /// <param name=\"match\">The Predicate(of T) that defines the conditions of the element to search for.</param>\n        /// <returns>The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, –1.</returns>\n        public static int FindIndex<T>(this IList<T> list, bool forward, int startSearch, Predicate<T> match)\n            => FindIndex(list, 0, forward, startSearch, match);\n\n        /// <summary>\n        /// Searches for an element that matches the conditions defined by the specified predicate, \n        /// and returns the zero-based index of the first occurrence.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the elements of the IList(of T).</typeparam>\n        /// <param name=\"list\">The list to search.</param>\n        /// <param name=\"forward\">If true the search is performed in direction of increasing indices, else in the direction of decreasing indices.</param>\n        /// <param name=\"match\">The Predicate(of T) that defines the conditions of the element to search for.</param>\n        /// <returns>The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, –1.</returns>\n        public static int FindIndex<T>(this IList<T> list, bool forward, Predicate<T> match)\n            => FindIndex(list, 0, forward, 0, match);\n\n\n        #endregion FindIndex\n\n        #region IList of IComparables\n\n        public static int CompareTo<T>(this IList<T> self, IList<T> other)\n            where T : IComparable<T>\n        {\n            int imax = System.Math.Min(self.Count, other.Count);\n            for (int i = 0; i < imax; i++)\n            {\n                int r = self[i].CompareTo(other[i]);\n                if (r != 0) return r;\n            }\n            return (self.Count < other.Count) ? -1 : ((self.Count > other.Count) ? 1 : 0);\n        }\n\n        public static int FirstIndexOf<T>(this IList<T> self, IList<T> other) where T : IComparable<T>\n            => self.FirstIndexOf(other, 0);\n\n        /// <summary>\n        /// Search first occurance of other in self, and return index if found\n        /// or -1 if not found. NOTE: simple algorithm, not optimized.\n        /// </summary>\n        public static int FirstIndexOf<T>(this IList<T> self, IList<T> other,\n                                     int startIndex)\n            where T : IComparable<T>\n        {\n            for (int i = startIndex; i < 1 + self.Count - other.Count; i++)\n            {\n                bool match = true;\n                for (int j = 0; j < other.Count; j++)\n                    if (self[i + j].CompareTo(other[j]) != 0)\n                    {\n                        match = false; break;\n                    }\n                if (match) return i;\n            }\n            return -1;\n        }\n\n        public static int SmallestIndex<T>(this IList<T> self)\n            where T: IComparable<T>\n        {\n            int index = 0;\n            T min = self[0];\n            for (int i = 1; i < self.Count; i++)\n                if (self[i].CompareTo(min) < 0) { min = self[i]; index = i; }\n            return index;\n        }\n\n        public static int LargestIndex<T>(this IList<T> self)\n            where T : IComparable<T>\n        {\n            int index = 0;\n            T max = self[0];\n            for (int i = 1; i < self.Count; i++)\n                if (self[i].CompareTo(max) > 0) { max = self[i]; index = i; }\n            return index;\n        }\n\n        /// <summary>\n        /// Returns the index of the n-smallest item.\n        /// </summary>\n        /// <param name=\"self\"></param>\n        /// <param name=\"n\">[0-self.Count()-1]; n=0 -> index of min element</param>\n        public static int NSmallestIndex<T>(this IList<T> self, int n)\n            where T : IComparable<T>\n        {\n            if (n == 0) return self.SmallestIndex();\n            T min;\n            var sorted = new List<T>(self);\n            sorted.Sort();\n            min = sorted[n];\n            return self.IndexOf(min);\n        }\n\n        /// <summary>\n        /// Returns the index of the n-largest item.\n        /// </summary>\n        /// <param name=\"self\"></param>\n        /// <param name=\"n\">[0-self.Count()-1]; n=0 -> index of max element</param>\n        public static int NLargestIndex<T>(this IList<T> self, int n)\n            where T : IComparable<T>\n        {\n            if (n == 0) return self.LargestIndex();\n            T max;\n            var sorted = new List<T>(self);\n            sorted.Sort();\n            max = sorted[sorted.Count - 1 - n];\n            return self.IndexOf(max);\n        }\n\n        #endregion\n        \n        #region Generic IList Copying\n\n        /// <summary>\n        /// Use this instead of Clone() in order to get a typed array back.\n        /// </summary>\n        public static T[] Copy<T>(this IList<T> xs)\n        {\n            var count = xs.Count;\n            var result = new T[count];\n            for (var i = 0; i < count; i++) result[i] = xs[i];\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of the specified length. If the copy is longer\n        /// it is filled with default elements.\n        /// </summary>\n        public static T[] Copy<T>(this IList<T> xs, int count)\n        {\n            var result = new T[count];\n            var len = Math.Min(count, xs.Count);\n            for (var i = 0; i < len; i++) result[i] = xs[i];\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of the specified length starting at the specified\n        /// start. If the copy is longer it is filled with default elements.\n        /// </summary>\n        public static T[] Copy<T>(this IList<T> xs, int start, int count)\n        {\n            var result = new T[count];\n            var len = Math.Min(count, xs.Count - start);\n            for (var i = 0; i < len; i++) result[i] = xs[i + start];\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy with the elements piped through a function.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(this IList<T> xs, Func<T, Tr> item_fun)\n        {\n            var len = xs.Count;\n            var result = new Tr[len];\n            for (var i = 0; i < len; i++) result[i] = item_fun(xs[i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create an array of resulting items by applying a supplied binary function\n        /// to corresponding pairs of the supplied ILists.\n        /// </summary>\n        /// <returns></returns>\n        public static Tr[] Map2<T0, T1, Tr>(\n                this IList<T0> xs0, IList<T1> xs1, Func<T0, T1, Tr> item0_item1_fun)\n        {\n            var len = Fun.Min(xs0.Count, xs1.Count);\n            var result = new Tr[len];\n            for (var i = 0; i < len; i++) result[i] = item0_item1_fun(xs0[i], xs1[i]);\n            return result;\n        }\n\n        /// <summary>\n        /// Create an array of resulting items by applying a supplied ternary function\n        /// to corresponding triples of the supplied ILists.\n        /// </summary>\n        /// <returns></returns>\n        public static Tr[] Map3<T0, T1, T2, Tr>(\n                this IList<T0> xs0, IList<T1> xs1, IList<T2> xs2, Func<T0, T1, T2, Tr> item0_item1_item2_fun)\n        {\n            var len = Fun.Min(xs0.Count, xs1.Count, xs2.Count);\n            var result = new Tr[len];\n            for (var i = 0; i < len; i++)\n                result[i] = item0_item1_item2_fun(xs0[i], xs1[i], xs2[i]);\n            return result;\n        }\n        \n        /// <summary>\n        /// Create a copy with the elements piped through a function.\n        /// The function gets the index of the element as a second argument.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(this IList<T> xs, Func<T, int, Tr> item_index_fun)\n        {\n            var len = xs.Count;\n            var result = new Tr[len];\n            for (var i = 0; i < len; i++) result[i] = item_index_fun(xs[i], i);\n            return result;\n        }\n\n        public static Tr[] Map2<T0, T1, Tr>(\n                this IList<T0> xs0, IList<T1> xs1, Func<T0, T1, int, Tr> item0_item1_index_fun)\n        {\n            var len = Fun.Min(xs0.Count, xs1.Count);\n            var result = new Tr[len];\n            for (var i = 0; i < len; i++)\n                result[i] = item0_item1_index_fun(xs0[i], xs1[i], i);\n            return result;\n        }\n\n        public static Tr[] Map3<T0, T1, T2, Tr>(\n                this IList<T0> xs0, IList<T1> xs1, IList<T2> xs2,\n                Func<T0, T1, T2, int, Tr> item0_item1_item2_index_fun)\n        {\n            var len = Fun.Min(xs0.Count, xs1.Count, xs2.Count);\n            var result = new Tr[len];\n            for (var i = 0; i < len; i++)\n                result[i] = item0_item1_item2_index_fun(xs0[i], xs1[i], xs2[i], i);\n            return result;\n        }\n        \n        /// <summary>\n        /// Create a copy of count elements with the elements piped through a\n        /// function. count may be longer than the input, in this case the\n        /// result array has default elements at the end.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this IList<T> xs, int count, Func<T, Tr> element_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, xs.Count);\n            for (var i = 0; i < len; i++) result[i] = element_fun(xs[i]);\n            return result;\n        }\n        \n        /// <summary>\n        /// Create a copy of count elements with the elements piped through a\n        /// function. count may be longer than the input, in this case the\n        /// result array has default elements at the end.\n        /// The function gets the index of the element as a second argument.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this IList<T> xs, int count, Func<T, int, Tr> element_index_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, xs.Count);\n            for (var i = 0; i < len; i++) result[i] = element_index_fun(xs[i], i);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy of specified length starting at the specified\n        /// offset with the elements piped through a function.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this IList<T> xs, int start, int count, Func<T, Tr> element_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, xs.Count - start);\n            for (var i = 0; i < len; i++) result[i] = element_fun(xs[start + i]);\n            return result;\n        }\n        \n        /// <summary>\n        /// Create a copy of specified length starting at the specified\n        /// offset with the elements piped through a function.\n        /// The function gets the target index of the element as a second\n        /// argument.\n        /// </summary>\n        public static Tr[] Map<T, Tr>(\n                this IList<T> xs, int start, int count, Func<T, int, Tr> element_index_fun)\n        {\n            var result = new Tr[count];\n            var len = Math.Min(count, xs.Count - start);\n            for (var i = 0; i < len; i++) result[i] = element_index_fun(xs[start + i], i);\n            return result;\n        }\n\n        /// <summary>\n        /// Copy a range of elements to the target array.\n        /// </summary>\n        public static void CopyTo<T>(this IList<T> xs, int count, T[] target, int targetStart)\n        {\n            for (var i = 0; i < count; i++)\n                target[targetStart + i] = xs[i];\n        }\n\n        /// <summary>\n        /// Copy a range of elements to the target array.\n        /// </summary>\n        public static void CopyTo<T>(this IList<T> xs, int start, int count, T[] target, int targetStart)\n        {\n            for (var i = 0; i < count; i++)\n                target[targetStart + i] = xs[start + i];\n        }\n\n        /// <summary>\n        /// Copies the IList into a list.\n        /// </summary>\n        public static List<T> CopyToList<T>(this IList<T> xs)\n        {\n            var result = new List<T>(xs.Count);\n            result.AddRange(xs);\n            return result;\n        }\n        \n        public static List<Tr> MapToList<T, Tr>(this IList<T> xs, Func<T, Tr> element_fun)\n        {\n            var count = xs.Count;\n            var result = new List<Tr>(count);\n            for (int i = 0; i < count; i++) result.Add(element_fun(xs[i]));\n            return result;\n        }\n        \n        public static List<Tr> MapToList<T, Tr>(this IList<T> xs, Func<T, int, Tr> item_index_fun)\n        {\n            var count = xs.Count;\n            var result = new List<Tr>(count);\n            for (int i = 0; i < count; i++) result.Add(item_index_fun(xs[i], i));\n            return result;\n        }\n\n        /// <summary>\n        /// Copies the specified range of elements to the specified destination\n        /// within the same IList.\n        /// </summary>\n        public static void CopyRange<T>(this IList<T> xs, int start, int count, int targetStart)\n        {\n            var end = start + count;\n            if (targetStart < start || targetStart >= end)\n            {\n                while (start < end) xs[targetStart++] = xs[start++];\n            }\n            else\n            {\n                targetStart += count;\n                while (start < end) xs[--targetStart] = xs[--end];\n            }\n        }\n\n        /// <summary>\n        /// Create a copy with the elements reversed. \n        /// </summary>\n        public static T[] CopyReversed<T>(this IList<T> xs)\n        {\n            var result = new T[xs.Count];\n            var lastIndex = xs.Count - 1;\n            for (var i = 0; i <= lastIndex; i++)\n            {\n                result[i] = xs[lastIndex - i];\n            }\n            return result;\n        }\n\n        #endregion\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/IsExternalInit.cs",
    "content": "﻿#if !NET8_0_OR_GREATER\n\nusing System.ComponentModel;\n\nnamespace System.Runtime.CompilerServices\n{\n    // See: https://github.com/dotnet/roslyn/issues/45510\n    [EditorBrowsable(EditorBrowsableState.Never)]\n    public static class IsExternalInit\n    {\n    }\n}\n\n#endif"
  },
  {
    "path": "src/Aardvark.Base/Extensions/ListExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public static class ListFun\n    {\n        #region Copying\n\n        public static List<T> Copy<T>(this List<T> self)\n        {\n            var result = new List<T>(self.Count);\n            foreach (var item in self) result.Add(item);\n            return result;\n        }\n\n        /// <summary>\n        /// Create a copy with the elements piped through a function.\n        /// </summary>\n        public static List<Tr> Map<T, Tr>(this List<T> list, Func<T, Tr> item_fun)\n        {\n            var count = list.Count;\n            var result = new List<Tr>(count);\n            for (var i = 0; i < count; i++) result.Add(item_fun(list[i]));\n            return result;\n        }\n\n        public static List<Tr> Map2<T0, T1, Tr>(\n                this List<T0> list0, List<T1> list1, Func<T0, T1, Tr> item0_item1_fun)\n        {\n            var count = Min(list0.Count, list1.Count);\n            var result = new List<Tr>(count);\n            for (var i = 0; i < count; i++)\n                result.Add(item0_item1_fun(list0[i], list1[i]));\n            return result;\n        }\n\n        public static List<Tr> Map3<T0, T1, T2, Tr>(\n                this List<T0> list0, List<T1> list1, List<T2> list2,\n                Func<T0, T1, T2, Tr> item0_item1_item2_fun)\n        {\n            var count = Min(Min(list0.Count, list1.Count), list2.Count);\n            var result = new List<Tr>(count);\n            for (var i = 0; i < count; i++)\n                result.Add(item0_item1_item2_fun(list0[i], list1[i], list2[i]));\n            return result;\n        }\n        \n        /// <summary>\n        /// Create a copy with the elements piped through a function.\n        /// </summary>\n        public static List<Tr> Map<T, Tr>(this List<T> list, Func<T, int, Tr> item_index_fun)\n        {\n            var count = list.Count;\n            var result = new List<Tr>(count);\n            for (int i = 0; i < count; i++) result.Add(item_index_fun(list[i], i));\n            return result;\n        }\n\n        public static List<Tr> Map2<T0, T1, Tr>(\n                this List<T0> list0, List<T1> list1, Func<T0, T1, int, Tr> item0_item1_index_fun)\n        {\n            var count = Min(list0.Count, list1.Count);\n            var result = new List<Tr>(count);\n            for (var i = 0; i < count; i++)\n                result.Add(item0_item1_index_fun(list0[i], list1[i], i));\n            return result;\n        }\n\n        public static List<Tr> Map3<T0, T1, T2, Tr>(\n                this List<T0> list0, List<T1> list1, List<T2> list2,\n                Func<T0, T1, T2, int, Tr> item0_item1_item2_index_fun)\n        {\n            var count = Min(Min(list0.Count, list1.Count), list2.Count);\n            var result = new List<Tr>(count);\n            for (var i = 0; i < count; i++)\n                result.Add(item0_item1_item2_index_fun(list0[i], list1[i], list2[i], i));\n            return result;\n        }\n\n        public static T[] CopyToArray<T>(this List<T> self)\n        {\n            return self.CopyToArray(self.Count);\n        }\n\n        public static T[] CopyToArray<T>(this List<T> self, int count)\n        {\n            var result = new T[count];\n            for (int i = 0; i < count; i++) result[i] = self[i];\n            return result;\n        }\n\n        public static Tr[] MapToArray<T, Tr>(this List<T> list, Func<T, Tr> item_fun)\n        {\n            return list.MapToArray(list.Count, item_fun);\n        }\n\n        public static Tr[] MapToArray<T, Tr>(this List<T> list, int count, Func<T, Tr> item_fun)\n        {\n            var result = new Tr[count];\n            if (list.Count < count) count = list.Count;\n            for (int i = 0; i < count; i++) result[i] = item_fun(list[i]);\n            return result;\n        }\n\n        public static Tr[] MapToArray<T, Tr>(\n                this List<T> list, int start, int count, Func<T, Tr> item_fun)\n        {\n            var result = new Tr[count];\n            if (start + count > list.Count) count = list.Count - start;\n            for (int i = 0; i < count; i++) result[i] = item_fun(list[i + start]);\n            return result;\n        }\n\n        #endregion\n\n        #region Mapped Copy\n\n        /// <summary>\n        /// Returns an array copy of this list that is created by copying the\n        /// elements at the positions specified in the supplied backward map.\n        /// </summary>\n        public static T[] BackwardMappedCopyToArray<T>(\n            this List<T> sourceArray,\n            int[] backwardMap)\n        {\n            T[] targetArray = new T[backwardMap.Length];\n            sourceArray.BackwardMappedCopyToArray(targetArray, backwardMap, 0);\n            return targetArray;\n        }\n\n        /// <summary>\n        /// Copies from this list into the target array starting at the\n        /// supplied offset using the supplied backward map that contains\n        /// the source index for each index of the target array.\n        /// </summary>\n        public static void BackwardMappedCopyToArray<T>(\n            this List<T> source,\n            T[] target,\n            int[] backwardMap,\n            int offset)\n        {\n            for (int i = 0; i < backwardMap.Length; i++)\n                target[i + offset] = source[backwardMap[i]];\n        }\n\n        /// <summary>\n        /// Returns an array copy of this list that is created by copying the\n        /// elements at the positions specified in the supplied backward map.\n        /// </summary>\n        public static Tr[] BackwardMappedCopyToArray<T, Tr>(\n            this List<T> sourceArray,\n            int[] backwardMap,\n            Func<T, Tr> fun)\n        {\n            Tr[] targetArray = new Tr[backwardMap.Length];\n            sourceArray.BackwardMappedCopyToArray(targetArray, backwardMap, 0, fun);\n            return targetArray;\n        }\n\n        /// <summary>\n        /// Copies from this list into the target array starting at the\n        /// supplied offset using the supplied backward map that contains\n        /// the source index for each index of the target array.\n        /// </summary>\n        public static void BackwardMappedCopyToArray<T, Tr>(\n            this List<T> source,\n            Tr[] target,\n            int[] backwardMap,\n            int offset,\n            Func<T, Tr> fun)\n        {\n            for (int i = 0; i < backwardMap.Length; i++)\n                target[i + offset] = fun(source[backwardMap[i]]);\n        }\n\n        #endregion\n\n        #region Adding Values\n\n\n        public static List<T> AddRange<T>(this List<T> list, T value, int count)\n        {\n            for (int i = 0; i < count; i++) list.Add(value);\n            return list;\n        }\n\n        /// <summary>\n        /// Add a specifable number of elements, each generated by a supplied\n        /// function of the respective element index in the list.\n        /// </summary>\n        /// <returns>the supplied list, so that the function can be directly used after initialization</returns>\n        public static List<T> AddByIndex<T>(this List<T> list, int count, Func<int, T> index_fun)\n        {\n            for (int i = list.Count, e = i + count; i < e; i++) list.Add(index_fun(i));\n            return list;\n        }\n\n        #endregion\n\n        #region Setters\n\n        /// <summary>\n        /// Set all elements to the same supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public static List<T> Set<T>(this List<T> self, T value)\n        {\n            for (int i = 0; i < self.Count; i++) self[i] = value;\n            return self;\n        }\n\n        /// <summary>\n        /// Set all elements to a function of the element index.\n        /// </summary>\n        /// <returns>this</returns>\n        public static List<T> Set<T>(this List<T> self, Func<int, T> fun)\n        {\n            for (int i = 0; i < self.Count; i++) self[i] = fun(i);\n            return self;\n        }\n\n        /// <summary>\n        /// Set count elements starting at the supplied index to the same\n        /// supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public static List<T> Set<T>(this List<T> self, int start, int count,\n                                     T value)\n        {\n            int end = System.Math.Min(start + count, self.Count);\n            for (int i = start; i < end; i++) self[i] = value;\n            return self;\n        }\n\n        /// <summary>\n        /// Set count elements starting at the supplied index to the same\n        /// supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public static List<T> Set<T>(this List<T> self, int start, int count,\n                                     Func<long, T> fun)\n        {\n            int end = System.Math.Min(start + count, self.Count);\n            for (int i = start; i < end; i++) self[i] = fun(i);\n            return self;\n        }\n\n        #endregion\n\n        #region\n\n        /// <summary>\n        /// Swap the two elements specified by ther indices.\n        /// </summary>\n        public static void Swap<T>(this List<T> self, int i, int j)\n        {\n            T help = self[i]; self[i] = self[j]; self[j] = help;\n        }\n        \n        #endregion\n\n        #region Heap\n\n        public static IEnumerable<ComparableIndexedValue<T>> NLargestIndicesAscending<T>(\n                this IEnumerable<T> values, int n)\n            where T : IComparable<T>\n        {\n            return values.NLargestIndices(n).HeapAscendingDequeueAll();\n        }\n\n        public static List<ComparableIndexedValue<T>> NLargestIndices<T>(\n                this IEnumerable<T> values, int n)\n            where T : IComparable<T>\n        {\n            if (n < 0) throw new ArgumentException(\"n >= 0 required\");\n            var list = new List<ComparableIndexedValue<T>>(n + 1);\n            if (n == 0) return list;\n            int i = 0;\n            foreach (var v in values)\n            {\n                var vi = i++;\n                if (list.Count < n)\n                {\n                    list.HeapAscendingEnqueue(v.ComparableIndexedValue(vi));\n                    continue;\n                }\n                if (v.CompareTo(list[0].Value) < 0) continue;\n                list.HeapAscendingEnqueue(v.ComparableIndexedValue(vi));\n                list.HeapAscendingDequeue();\n            }\n            return list;\n        }\n\n        public static IEnumerable<ComparableIndexedValue<T>> NSmallestIndicesDescending<T>(\n                this IEnumerable<T> values, int n)\n            where T : IComparable<T>\n        {\n            return values.NSmallestIndices(n).HeapDescendingDequeueAll();\n        }\n\n        public static List<ComparableIndexedValue<T>> NSmallestIndices<T>(\n                this IEnumerable<T> values, int n)\n            where T : IComparable<T>\n        {\n            if (n < 0) throw new ArgumentException(\"n < 0 requried\");\n            var list = new List<ComparableIndexedValue<T>>(n + 1);\n            if (n == 0) return list;\n            int i = 0;\n            foreach (var v in values)\n            {\n                var vi = i++;\n                if (list.Count < n)\n                {\n                    list.HeapDescendingEnqueue(v.ComparableIndexedValue(vi));\n                    continue;\n                }\n                if (v.CompareTo(list[0].Value) > 0) continue;\n                list.HeapDescendingEnqueue(v.ComparableIndexedValue(vi));\n                list.HeapDescendingDequeue();\n            }\n            return list;\n        }\n\n        /// <summary>\n        /// Adds an element to the heap, and maintains the heap condition.\n        /// For default comparison functions the smallest item is on top of\n        /// the heap.\n        /// </summary>\n        public static void HeapEnqueue<T>(\n                this List<T> heap, Func<T, T, int> compare, T element)\n        {\n            int i = heap.Count;\n            heap.Add(element);\n            while (i > 0)\n            {\n                int i2 = (i - 1) / 2;\n                if (compare(element, heap[i2]) > 0) break;\n                heap[i] = heap[i2];\n                i = i2;\n            }\n            heap[i] = element;\n        }\n\n        /// <summary>\n        /// Removes and returns the item at the top of the heap (i.e. the\n        /// 0th position of the list). For default comparison functions this\n        /// is the smallest element.\n        /// </summary>\n        public static T HeapDequeue<T>(\n                this List<T> heap, Func<T, T, int> compare)\n        {\n            var result = heap[0];\n            var count = heap.Count;\n            if (count == 1) { heap.Clear(); return result; }\n            var element = heap[--count];\n            heap.RemoveAt(count);\n            int i = 0, i1 = 1;\n            while (i1 < count) // at least one child\n            {\n                int i2 = i1 + 1;\n                int ni = (i2 < count // two children?\n                          && compare(heap[i1], heap[i2]) > 0)\n                             ? i2 : i1; // smaller child\n                if (compare(heap[ni], element) > 0) break;\n                heap[i] = heap[ni];\n                i = ni; i1 = 2 * i + 1;\n            }\n            heap[i] = element;\n            return result;\n        }\n\n        /// <summary>\n        /// Removes and returns all items from the heap as an IEnumerable. For\n        /// default comparison functiosn this is in ascending order.\n        /// </summary>\n        public static IEnumerable<T> HeapDequeueAll<T>(\n                this List<T> heap, Func<T, T, int> compare)\n        {\n            while (heap.Count > 0) yield return heap.HeapDequeue(compare);\n        }\n\n        /// <summary>\n        /// Reomves an arbitrary element from the heap, maintains the heap\n        /// conditions, and returns the removed element.\n        /// </summary>\n        public static T HeapRemoveAt<T>(\n                this List<T> heap, Func<T, T, int> compare, int index)\n        {\n            var result = heap[index];\n            var count = heap.Count;\n            if (count == 1) { heap.Clear(); return result; }\n            var element = heap[--count];\n            heap.RemoveAt(count);\n            if (index == count) return result;\n\n            int i = index;\n            while (i > 0)\n            {\n                int i2 = (i - 1) / 2;\n                if (compare(element, heap[i2]) > 0) break;\n                heap[i] = heap[i2];\n                i = i2;\n            }\n            if (i == index)\n            {\n                int i1 = 2 * i + 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && compare(heap[i1], heap[i2]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (compare(heap[ni], element) > 0) break;\n                    heap[i] = heap[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n            }\n            heap[i] = element;\n            return result;\n        }\n\n        /// <summary>\n        /// Adds an element to the heap, and maintains the heap condition.\n        /// For default comparison functions the smallest item is on top of\n        /// the heap.\n        /// </summary>\n        public static void HeapAscendingEnqueue<T>(\n                this List<T> heap, T element)\n            where T : IComparable<T>\n        {\n            int i = heap.Count;\n            heap.Add(element);\n            while (i > 0)\n            {\n                int i2 = (i - 1) / 2;\n                if (element.CompareTo(heap[i2]) > 0) break;\n                heap[i] = heap[i2];\n                i = i2;\n            }\n            heap[i] = element;\n        }\n\n        /// <summary>\n        /// Removes and returns the item at the top of the heap (i.e. the\n        /// 0th position of the list). For default comparison functions this\n        /// is the smallest element.\n        /// </summary>\n        public static T HeapAscendingDequeue<T>(\n                this List<T> heap)\n            where T : IComparable<T>\n        {\n            var result = heap[0];\n            var count = heap.Count;\n            if (count == 1) { heap.Clear(); return result; }\n            var element = heap[--count];\n            heap.RemoveAt(count);\n            int i = 0, i1 = 1;\n            while (i1 < count) // at least one child\n            {\n                int i2 = i1 + 1;\n                int ni = (i2 < count // two children?\n                          && heap[i1].CompareTo(heap[i2]) > 0)\n                             ? i2 : i1; // smaller child\n                if (heap[ni].CompareTo(element) > 0) break;\n                heap[i] = heap[ni];\n                i = ni; i1 = 2 * i + 1;\n            }\n            heap[i] = element;\n            return result;\n        }\n\n        /// <summary>\n        /// Removes and returns all items from the heap as an IEnumerable. For\n        /// default comparison functiosn this is in ascending order.\n        /// </summary>\n        public static IEnumerable<T> HeapAscendingDequeueAll<T>(\n                this List<T> heap)\n            where T : IComparable<T>\n        {\n            while (heap.Count > 0) yield return heap.HeapAscendingDequeue();\n        }\n\n        /// <summary>\n        /// Reomves an arbitrary element from the heap, maintains the heap\n        /// conditions, and returns the removed element.\n        /// </summary>\n        public static T HeapAscendingRemoveAt<T>(\n                this List<T> heap, int index)\n            where T : IComparable<T>\n        {\n            var result = heap[index];\n            var count = heap.Count;\n            if (count == 1) { heap.Clear(); return result; }\n            var element = heap[--count];\n            heap.RemoveAt(count);\n            if (index == count) return result;\n\n            int i = index;\n            while (i > 0)\n            {\n                int i2 = (i - 1) / 2;\n                if (element.CompareTo(heap[i2]) > 0) break;\n                heap[i] = heap[i2];\n                i = i2;\n            }\n            if (i == index)\n            {\n                int i1 = 2 * i + 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && heap[i1].CompareTo(heap[i2]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (heap[ni].CompareTo(element) > 0) break;\n                    heap[i] = heap[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n            }\n            heap[i] = element;\n            return result;\n        }\n\n        /// <summary>\n        /// Adds an element to the heap, and maintains the heap condition.\n        /// For default comparison functions the smallest item is on top of\n        /// the heap.\n        /// </summary>\n        public static void HeapDescendingEnqueue<T>(\n                this List<T> heap, T element)\n            where T : IComparable<T>\n        {\n            int i = heap.Count;\n            heap.Add(element);\n            while (i > 0)\n            {\n                int i2 = (i - 1) / 2;\n                if (element.CompareTo(heap[i2]) < 0) break;\n                heap[i] = heap[i2];\n                i = i2;\n            }\n            heap[i] = element;\n        }\n\n        /// <summary>\n        /// Removes and returns the item at the top of the heap (i.e. the\n        /// 0th position of the list). For default comparison functions this\n        /// is the smallest element.\n        /// </summary>\n        public static T HeapDescendingDequeue<T>(\n                this List<T> heap)\n            where T : IComparable<T>\n        {\n            var result = heap[0];\n            var count = heap.Count;\n            if (count == 1) { heap.Clear(); return result; }\n            var element = heap[--count];\n            heap.RemoveAt(count);\n            int i = 0, i1 = 1;\n            while (i1 < count) // at least one child\n            {\n                int i2 = i1 + 1;\n                int ni = (i2 < count // two children?\n                          && heap[i1].CompareTo(heap[i2]) < 0)\n                             ? i2 : i1; // smaller child\n                if (heap[ni].CompareTo(element) < 0) break;\n                heap[i] = heap[ni];\n                i = ni; i1 = 2 * i + 1;\n            }\n            heap[i] = element;\n            return result;\n        }\n\n        /// <summary>\n        /// Removes and returns all items from the heap as an IEnumerable. For\n        /// default comparison functiosn this is in ascending order.\n        /// </summary>\n        public static IEnumerable<T> HeapDescendingDequeueAll<T>(\n                this List<T> heap)\n            where T : IComparable<T>\n        {\n            while (heap.Count > 0) yield return heap.HeapDescendingDequeue();\n        }\n\n        /// <summary>\n        /// Reomves an arbitrary element from the heap, maintains the heap\n        /// conditions, and returns the removed element.\n        /// </summary>\n        public static T HeapDescendingRemoveAt<T>(\n                this List<T> heap, int index)\n            where T : IComparable<T>\n        {\n            var result = heap[index];\n            var count = heap.Count;\n            if (count == 1) { heap.Clear(); return result; }\n            var element = heap[--count];\n            heap.RemoveAt(count);\n            if (index == count) return result;\n\n            int i = index;\n            while (i > 0)\n            {\n                int i2 = (i - 1) / 2;\n                if (element.CompareTo(heap[i2]) < 0) break;\n                heap[i] = heap[i2];\n                i = i2;\n            }\n            if (i == index)\n            {\n                int i1 = 2 * i + 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && heap[i1].CompareTo(heap[i2]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (heap[ni].CompareTo(element) < 0) break;\n                    heap[i] = heap[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n            }\n            heap[i] = element;\n            return result;\n        }\n\n        #endregion\n\n        #region Lists of IComparables\n\n        public static List<T> MergeSortedAscending<T>(this List<T> a0, List<T> a1)\n            where T : IComparable<T>\n        {\n            int c0 = a0.Count;\n            int c1 = a1.Count;\n            var a = new List<T>(c0 + c1);\n            int i0 = 0, i1 = 0;\n            while (i0 < c0 && i1 < c1)\n            {\n                if (a0[i0].CompareTo(a1[i1]) <= 0)\n                    a.Add(a0[i0++]);\n                else\n                    a.Add(a1[i1++]);\n            }\n            while (i0 < c0) a.Add(a0[i0++]);\n            while (i1 < c1) a.Add(a1[i1++]);\n            return a;\n        }\n\n        public static T[] MergeSortAscending<T>(this T[] a0, T[] a1)\n            where T : IComparable<T>\n        {\n            long c0 = a0.LongLength;\n            long c1 = a1.LongLength;\n            var a = new T[c0 + c1];\n            long i0 = 0, i1 = 0, i = 0;\n            while (i0 < c0 && i1 < c1)\n            {\n                if (a0[i0].CompareTo(a1[i1]) <= 0)\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < c0) a[i++] = a0[i0++];\n            while (i1 < c1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        public static int SmallestIndex<T>(this List<T> a)\n            where T : IComparable<T>\n        {\n            int index = 0;\n            T min = a[0];\n            for (int i = 1; i < a.Count; i++)\n                if (a[i].CompareTo(min) < 0) { min = a[i]; index = i; }\n            return index;\n        }\n\n        public static int LargestIndex<T>(this List<T> a)\n            where T : IComparable<T>\n        {\n            int index = 0;\n            T max = a[0];\n            for (int i = 1; i < a.Count; i++)\n                if (a[i].CompareTo(max) > 0) { max = a[i]; index = i; }\n            return index;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/NonGenericArray.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class NonGenericArrayExtensions\n    {\n\t\t#region Non-Generic Array\n\n\t\t[Obsolete]\n\t\tprivate static readonly Dictionary<Type, Func<Array, Array>> CopyFunMap =\n\t\t\tnew Dictionary<Type, Func<Array, Array>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), a => ((byte[])a).Copy() },\n\t\t\t\t{ typeof(sbyte[]), a => ((sbyte[])a).Copy() },\n\t\t\t\t{ typeof(ushort[]), a => ((ushort[])a).Copy() },\n\t\t\t\t{ typeof(short[]), a => ((short[])a).Copy() },\n\t\t\t\t{ typeof(uint[]), a => ((uint[])a).Copy() },\n\t\t\t\t{ typeof(int[]), a => ((int[])a).Copy() },\n\t\t\t\t{ typeof(ulong[]), a => ((ulong[])a).Copy() },\n\t\t\t\t{ typeof(long[]), a => ((long[])a).Copy() },\n\t\t\t\t{ typeof(float[]), a => ((float[])a).Copy() },\n\t\t\t\t{ typeof(double[]), a => ((double[])a).Copy() },\n\t\t\t\t{ typeof(C3b[]), a => ((C3b[])a).Copy() },\n\t\t\t\t{ typeof(C3us[]), a => ((C3us[])a).Copy() },\n\t\t\t\t{ typeof(C3ui[]), a => ((C3ui[])a).Copy() },\n\t\t\t\t{ typeof(C3f[]), a => ((C3f[])a).Copy() },\n\t\t\t\t{ typeof(C3d[]), a => ((C3d[])a).Copy() },\n\t\t\t\t{ typeof(C4b[]), a => ((C4b[])a).Copy() },\n\t\t\t\t{ typeof(C4us[]), a => ((C4us[])a).Copy() },\n\t\t\t\t{ typeof(C4ui[]), a => ((C4ui[])a).Copy() },\n\t\t\t\t{ typeof(C4f[]), a => ((C4f[])a).Copy() },\n\t\t\t\t{ typeof(C4d[]), a => ((C4d[])a).Copy() },\n\t\t\t\t{ typeof(V2i[]), a => ((V2i[])a).Copy() },\n\t\t\t\t{ typeof(V2l[]), a => ((V2l[])a).Copy() },\n\t\t\t\t{ typeof(V2f[]), a => ((V2f[])a).Copy() },\n\t\t\t\t{ typeof(V2d[]), a => ((V2d[])a).Copy() },\n\t\t\t\t{ typeof(V3i[]), a => ((V3i[])a).Copy() },\n\t\t\t\t{ typeof(V3l[]), a => ((V3l[])a).Copy() },\n\t\t\t\t{ typeof(V3f[]), a => ((V3f[])a).Copy() },\n\t\t\t\t{ typeof(V3d[]), a => ((V3d[])a).Copy() },\n\t\t\t\t{ typeof(V4i[]), a => ((V4i[])a).Copy() },\n\t\t\t\t{ typeof(V4l[]), a => ((V4l[])a).Copy() },\n\t\t\t\t{ typeof(V4f[]), a => ((V4f[])a).Copy() },\n\t\t\t\t{ typeof(V4d[]), a => ((V4d[])a).Copy() },\n\t\t\t};\n\n        /// <summary>\n        /// Creates a copy of the array.\n        /// </summary>\n        public static Array Copy(this Array array)\n        {\n            var counts = new long[array.Rank];\n\n            for (int i = 0; i < counts.Length; i++)\n            {\n                counts[i] = array.GetLongLength(i);\n            }\n\n            var result = Array.CreateInstance(array.GetType().GetElementType(), counts);\n            Array.Copy(array, result, array.LongLength);\n            return result;\n        }\n\n        [Obsolete]\n        private static readonly Dictionary<Type, Func<Array, object, Array>> CopyFunFunMap =\n\t\t\tnew Dictionary<Type, Func<Array, object, Array>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (a, f) => ((byte[])a).Map((Func<byte,byte>)f) },\n\t\t\t\t{ typeof(sbyte[]), (a, f) => ((sbyte[])a).Map((Func<sbyte,sbyte>)f) },\n\t\t\t\t{ typeof(ushort[]), (a, f) => ((ushort[])a).Map((Func<ushort,ushort>)f) },\n\t\t\t\t{ typeof(short[]), (a, f) => ((short[])a).Map((Func<short,short>)f) },\n\t\t\t\t{ typeof(uint[]), (a, f) => ((uint[])a).Map((Func<uint,uint>)f) },\n\t\t\t\t{ typeof(int[]), (a, f) => ((int[])a).Map((Func<int,int>)f) },\n\t\t\t\t{ typeof(ulong[]), (a, f) => ((ulong[])a).Map((Func<ulong,ulong>)f) },\n\t\t\t\t{ typeof(long[]), (a, f) => ((long[])a).Map((Func<long,long>)f) },\n\t\t\t\t{ typeof(float[]), (a, f) => ((float[])a).Map((Func<float,float>)f) },\n\t\t\t\t{ typeof(double[]), (a, f) => ((double[])a).Map((Func<double,double>)f) },\n\t\t\t\t{ typeof(C3b[]), (a, f) => ((C3b[])a).Map((Func<C3b,C3b>)f) },\n\t\t\t\t{ typeof(C3us[]), (a, f) => ((C3us[])a).Map((Func<C3us,C3us>)f) },\n\t\t\t\t{ typeof(C3ui[]), (a, f) => ((C3ui[])a).Map((Func<C3ui,C3ui>)f) },\n\t\t\t\t{ typeof(C3f[]), (a, f) => ((C3f[])a).Map((Func<C3f,C3f>)f) },\n\t\t\t\t{ typeof(C3d[]), (a, f) => ((C3d[])a).Map((Func<C3d,C3d>)f) },\n\t\t\t\t{ typeof(C4b[]), (a, f) => ((C4b[])a).Map((Func<C4b,C4b>)f) },\n\t\t\t\t{ typeof(C4us[]), (a, f) => ((C4us[])a).Map((Func<C4us,C4us>)f) },\n\t\t\t\t{ typeof(C4ui[]), (a, f) => ((C4ui[])a).Map((Func<C4ui,C4ui>)f) },\n\t\t\t\t{ typeof(C4f[]), (a, f) => ((C4f[])a).Map((Func<C4f,C4f>)f) },\n\t\t\t\t{ typeof(C4d[]), (a, f) => ((C4d[])a).Map((Func<C4d,C4d>)f) },\n\t\t\t\t{ typeof(V2i[]), (a, f) => ((V2i[])a).Map((Func<V2i,V2i>)f) },\n\t\t\t\t{ typeof(V2l[]), (a, f) => ((V2l[])a).Map((Func<V2l,V2l>)f) },\n\t\t\t\t{ typeof(V2f[]), (a, f) => ((V2f[])a).Map((Func<V2f,V2f>)f) },\n\t\t\t\t{ typeof(V2d[]), (a, f) => ((V2d[])a).Map((Func<V2d,V2d>)f) },\n\t\t\t\t{ typeof(V3i[]), (a, f) => ((V3i[])a).Map((Func<V3i,V3i>)f) },\n\t\t\t\t{ typeof(V3l[]), (a, f) => ((V3l[])a).Map((Func<V3l,V3l>)f) },\n\t\t\t\t{ typeof(V3f[]), (a, f) => ((V3f[])a).Map((Func<V3f,V3f>)f) },\n\t\t\t\t{ typeof(V3d[]), (a, f) => ((V3d[])a).Map((Func<V3d,V3d>)f) },\n\t\t\t\t{ typeof(V4i[]), (a, f) => ((V4i[])a).Map((Func<V4i,V4i>)f) },\n\t\t\t\t{ typeof(V4l[]), (a, f) => ((V4l[])a).Map((Func<V4l,V4l>)f) },\n\t\t\t\t{ typeof(V4f[]), (a, f) => ((V4f[])a).Map((Func<V4f,V4f>)f) },\n\t\t\t\t{ typeof(V4d[]), (a, f) => ((V4d[])a).Map((Func<V4d,V4d>)f) },\n\t\t\t};\n\n        [Obsolete(\"Anybody using this?\")]\n        public static Array Copy<T>(this Array array,\n\t\t\t\t\t\t\t\t\tFunc<T, T> funOfElementTypeToElementType,\n\t\t\t\t\t\t\t\t\tFunc<Array, Array> defaultFun = null)\n\t\t{\n\t\t\tvar arrayType = array.GetType();\n\t\t\tif (typeof(T) == arrayType.GetElementType())\n\t\t\t\treturn CopyFunFunMap[arrayType](array, funOfElementTypeToElementType);\n\t\t\telse if (defaultFun != null)\n\t\t\t\treturn defaultFun(array);\n\t\t\telse\n\t\t\t\treturn CopyFunMap[arrayType](array);\n\t\t}\n\n\t\tprivate static readonly Dictionary<Type, Func<Array, int, Array>> ResizedFunMap =\n\t\t\tnew Dictionary<Type, Func<Array, int, Array>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (a, s) => ((byte[])a).Resized(s) },\n\t\t\t\t{ typeof(sbyte[]), (a, s) => ((sbyte[])a).Resized(s) },\n\t\t\t\t{ typeof(ushort[]), (a, s) => ((ushort[])a).Resized(s) },\n\t\t\t\t{ typeof(short[]), (a, s) => ((short[])a).Resized(s) },\n\t\t\t\t{ typeof(uint[]), (a, s) => ((uint[])a).Resized(s) },\n\t\t\t\t{ typeof(int[]), (a, s) => ((int[])a).Resized(s) },\n\t\t\t\t{ typeof(ulong[]), (a, s) => ((ulong[])a).Resized(s) },\n\t\t\t\t{ typeof(long[]), (a, s) => ((long[])a).Resized(s) },\n\t\t\t\t{ typeof(float[]), (a, s) => ((float[])a).Resized(s) },\n\t\t\t\t{ typeof(double[]), (a, s) => ((double[])a).Resized(s) },\n\t\t\t\t{ typeof(C3b[]), (a, s) => ((C3b[])a).Resized(s) },\n\t\t\t\t{ typeof(C3us[]), (a, s) => ((C3us[])a).Resized(s) },\n\t\t\t\t{ typeof(C3ui[]), (a, s) => ((C3ui[])a).Resized(s) },\n\t\t\t\t{ typeof(C3f[]), (a, s) => ((C3f[])a).Resized(s) },\n\t\t\t\t{ typeof(C3d[]), (a, s) => ((C3d[])a).Resized(s) },\n\t\t\t\t{ typeof(C4b[]), (a, s) => ((C4b[])a).Resized(s) },\n\t\t\t\t{ typeof(C4us[]), (a, s) => ((C4us[])a).Resized(s) },\n\t\t\t\t{ typeof(C4ui[]), (a, s) => ((C4ui[])a).Resized(s) },\n\t\t\t\t{ typeof(C4f[]), (a, s) => ((C4f[])a).Resized(s) },\n\t\t\t\t{ typeof(C4d[]), (a, s) => ((C4d[])a).Resized(s) },\n\t\t\t\t{ typeof(V2i[]), (a, s) => ((V2i[])a).Resized(s) },\n\t\t\t\t{ typeof(V2l[]), (a, s) => ((V2l[])a).Resized(s) },\n\t\t\t\t{ typeof(V2f[]), (a, s) => ((V2f[])a).Resized(s) },\n\t\t\t\t{ typeof(V2d[]), (a, s) => ((V2d[])a).Resized(s) },\n\t\t\t\t{ typeof(V3i[]), (a, s) => ((V3i[])a).Resized(s) },\n\t\t\t\t{ typeof(V3l[]), (a, s) => ((V3l[])a).Resized(s) },\n\t\t\t\t{ typeof(V3f[]), (a, s) => ((V3f[])a).Resized(s) },\n\t\t\t\t{ typeof(V3d[]), (a, s) => ((V3d[])a).Resized(s) },\n\t\t\t\t{ typeof(V4i[]), (a, s) => ((V4i[])a).Resized(s) },\n\t\t\t\t{ typeof(V4l[]), (a, s) => ((V4l[])a).Resized(s) },\n\t\t\t\t{ typeof(V4f[]), (a, s) => ((V4f[])a).Resized(s) },\n\t\t\t\t{ typeof(V4d[]), (a, s) => ((V4d[])a).Resized(s) },\n\t\t\t};\n\n\t\tpublic static Array Resized(this Array array, int size)\n\t\t{\n\t\t\treturn ResizedFunMap[array.GetType()](array, size);\n\t\t}\n\n\t\tprivate static readonly Dictionary<Type, Func<Array, int[], int, Array>>\n\t\t\tBackMappedCopyFunMap = new Dictionary<Type, Func<Array, int[], int, Array>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (a,m,c) => ((byte[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(sbyte[]), (a,m,c) => ((sbyte[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(short[]), (a,m,c) => ((short[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(ushort[]), (a,m,c) => ((ushort[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(int[]), (a,m,c) => ((int[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(uint[]), (a,m,c) => ((uint[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(long[]), (a,m,c) => ((long[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(ulong[]), (a,m,c) => ((ulong[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(float[]), (a,m,c) => ((float[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(double[]), (a,m,c) => ((double[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C3b[]), (a,m,c) => ((C3b[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C3us[]), (a,m,c) => ((C3us[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C3ui[]), (a,m,c) => ((C3ui[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C3f[]), (a,m,c) => ((C3f[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C3d[]), (a,m,c) => ((C3d[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C4b[]), (a,m,c) => ((C4b[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C4us[]), (a,m,c) => ((C4us[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C4ui[]), (a,m,c) => ((C4ui[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C4f[]), (a,m,c) => ((C4f[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(C4d[]), (a,m,c) => ((C4d[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V2i[]), (a,m,c) => ((V2i[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V2l[]), (a,m,c) => ((V2l[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V2f[]), (a,m,c) => ((V2f[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V2d[]), (a,m,c) => ((V2d[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V3i[]), (a,m,c) => ((V3i[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V3l[]), (a,m,c) => ((V3l[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V3f[]), (a,m,c) => ((V3f[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V3d[]), (a,m,c) => ((V3d[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V4i[]), (a,m,c) => ((V4i[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V4l[]), (a,m,c) => ((V4l[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V4f[]), (a,m,c) => ((V4f[])a).BackMappedCopy(m, c) },\n\t\t\t\t{ typeof(V4d[]), (a,m,c) => ((V4d[])a).BackMappedCopy(m, c) },\n\t\t\t};\n\n\t\tpublic static Array BackMappedCopy(\n\t\t\t\tthis Array source, int[] backMap, int count = 0)\n\t\t{\n            if (BackMappedCopyFunMap.TryGetValue(source.GetType(), out Func<Array, int[], int, Array> fun))\n                return fun(source, backMap, count);\n            return null;\n\t\t}\n\n\t\tprivate static readonly Dictionary<Type, Func<Array, int[], int[], int, Array>>\n\t\t\tBackMappedIndexedCopyFunMap = new Dictionary<Type, Func<Array, int[], int[], int, Array>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (a,i,m,c) => ((byte[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(sbyte[]), (a,i,m,c) => ((sbyte[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(short[]), (a,i,m,c) => ((short[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(ushort[]), (a,i,m,c) => ((ushort[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(int[]), (a,i,m,c) => ((int[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(uint[]), (a,i,m,c) => ((uint[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(long[]), (a,i,m,c) => ((long[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(ulong[]), (a,i,m,c) => ((ulong[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(float[]), (a,i,m,c) => ((float[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(double[]), (a,i,m,c) => ((double[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C3b[]), (a,i,m,c) => ((C3b[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C3us[]), (a,i,m,c) => ((C3us[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C3ui[]), (a,i,m,c) => ((C3ui[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C3f[]), (a,i,m,c) => ((C3f[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C3d[]), (a,i,m,c) => ((C3d[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C4b[]), (a,i,m,c) => ((C4b[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C4us[]), (a,i,m,c) => ((C4us[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C4ui[]), (a,i,m,c) => ((C4ui[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C4f[]), (a,i,m,c) => ((C4f[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(C4d[]), (a,i,m,c) => ((C4d[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V2i[]), (a,i,m,c) => ((V2i[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V2l[]), (a,i,m,c) => ((V2l[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V2f[]), (a,i,m,c) => ((V2f[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V2d[]), (a,i,m,c) => ((V2d[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V3i[]), (a,i,m,c) => ((V3i[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V3l[]), (a,i,m,c) => ((V3l[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V3f[]), (a,i,m,c) => ((V3f[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V3d[]), (a,i,m,c) => ((V3d[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V4i[]), (a,i,m,c) => ((V4i[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V4l[]), (a,i,m,c) => ((V4l[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V4f[]), (a,i,m,c) => ((V4f[])a).BackMappedCopy(i, m, c) },\n\t\t\t\t{ typeof(V4d[]), (a,i,m,c) => ((V4d[])a).BackMappedCopy(i, m, c) },\n\t\t\t};\n\n\t\tpublic static Array BackMappedCopy(\n\t\t\t\tthis Array source, int[] indexArray, int[] backMap, int count = 0)\n\t\t{\n            if (BackMappedIndexedCopyFunMap.TryGetValue(source.GetType(), out Func<Array, int[], int[], int, Array> fun))\n                return fun(source, indexArray, backMap, count);\n            return null;\n\t\t}\n\n\t\tprivate static readonly Dictionary<Type, Action<Array, Array, int[], int>>\n\t\t\tBackMappedCopyToFunMap = new Dictionary<Type, Action<Array, Array, int[], int>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (s,t,m,o) => ((byte[])s).BackMappedCopyTo((byte[])t,m,o) },\n\t\t\t\t{ typeof(sbyte[]), (s,t,m,o) => ((sbyte[])s).BackMappedCopyTo((sbyte[])t,m,o) },\n\t\t\t\t{ typeof(short[]), (s,t,m,o) => ((short[])s).BackMappedCopyTo((short[])t,m,o) },\n\t\t\t\t{ typeof(ushort[]), (s,t,m,o) => ((ushort[])s).BackMappedCopyTo((ushort[])t,m,o) },\n\t\t\t\t{ typeof(int[]), (s,t,m,o) => ((int[])s).BackMappedCopyTo((int[])t,m,o) },\n\t\t\t\t{ typeof(uint[]), (s,t,m,o) => ((uint[])s).BackMappedCopyTo((uint[])t,m,o) },\n\t\t\t\t{ typeof(long[]), (s,t,m,o) => ((long[])s).BackMappedCopyTo((long[])t,m,o) },\n\t\t\t\t{ typeof(ulong[]), (s,t,m,o) => ((ulong[])s).BackMappedCopyTo((ulong[])t,m,o) },\n\t\t\t\t{ typeof(float[]), (s,t,m,o) => ((float[])s).BackMappedCopyTo((float[])t,m,o) },\n\t\t\t\t{ typeof(double[]), (s,t,m,o) => ((double[])s).BackMappedCopyTo((double[])t,m,o) },\n\t\t\t\t{ typeof(C3b[]), (s,t,m,o) => ((C3b[])s).BackMappedCopyTo((C3b[])t,m,o) },\n\t\t\t\t{ typeof(C3us[]), (s,t,m,o) => ((C3us[])s).BackMappedCopyTo((C3us[])t,m,o) },\n\t\t\t\t{ typeof(C3ui[]), (s,t,m,o) => ((C3ui[])s).BackMappedCopyTo((C3ui[])t,m,o) },\n\t\t\t\t{ typeof(C3f[]), (s,t,m,o) => ((C3f[])s).BackMappedCopyTo((C3f[])t,m,o) },\n\t\t\t\t{ typeof(C3d[]), (s,t,m,o) => ((C3d[])s).BackMappedCopyTo((C3d[])t,m,o) },\n\t\t\t\t{ typeof(C4b[]), (s,t,m,o) => ((C4b[])s).BackMappedCopyTo((C4b[])t,m,o) },\n\t\t\t\t{ typeof(C4us[]), (s,t,m,o) => ((C4us[])s).BackMappedCopyTo((C4us[])t,m,o) },\n\t\t\t\t{ typeof(C4ui[]), (s,t,m,o) => ((C4ui[])s).BackMappedCopyTo((C4ui[])t,m,o) },\n\t\t\t\t{ typeof(C4f[]), (s,t,m,o) => ((C4f[])s).BackMappedCopyTo((C4f[])t,m,o) },\n\t\t\t\t{ typeof(C4d[]), (s,t,m,o) => ((C4d[])s).BackMappedCopyTo((C4d[])t,m,o) },\n\t\t\t\t{ typeof(V2i[]), (s,t,m,o) => ((V2i[])s).BackMappedCopyTo((V2i[])t,m,o) },\n\t\t\t\t{ typeof(V2l[]), (s,t,m,o) => ((V2l[])s).BackMappedCopyTo((V2l[])t,m,o) },\n\t\t\t\t{ typeof(V2f[]), (s,t,m,o) => ((V2f[])s).BackMappedCopyTo((V2f[])t,m,o) },\n\t\t\t\t{ typeof(V2d[]), (s,t,m,o) => ((V2d[])s).BackMappedCopyTo((V2d[])t,m,o) },\n\t\t\t\t{ typeof(V3i[]), (s,t,m,o) => ((V3i[])s).BackMappedCopyTo((V3i[])t,m,o) },\n\t\t\t\t{ typeof(V3l[]), (s,t,m,o) => ((V3l[])s).BackMappedCopyTo((V3l[])t,m,o) },\n\t\t\t\t{ typeof(V3f[]), (s,t,m,o) => ((V3f[])s).BackMappedCopyTo((V3f[])t,m,o) },\n\t\t\t\t{ typeof(V3d[]), (s,t,m,o) => ((V3d[])s).BackMappedCopyTo((V3d[])t,m,o) },\n\t\t\t\t{ typeof(V4i[]), (s,t,m,o) => ((V4i[])s).BackMappedCopyTo((V4i[])t,m,o) },\n\t\t\t\t{ typeof(V4l[]), (s,t,m,o) => ((V4l[])s).BackMappedCopyTo((V4l[])t,m,o) },\n\t\t\t\t{ typeof(V4f[]), (s,t,m,o) => ((V4f[])s).BackMappedCopyTo((V4f[])t,m,o) },\n\t\t\t\t{ typeof(V4d[]), (s,t,m,o) => ((V4d[])s).BackMappedCopyTo((V4d[])t,m,o) },\n\t\t\t};\n\n\t\tpublic static Array BackMappedCopyTo(\n\t\t\t\tthis Array source, int[] backwardMap,\n\t\t\t\tArray target, int offset)\n\t\t{\n\t\t\tBackMappedCopyToFunMap[source.GetType()](\n\t\t\t\t\tsource, target, backwardMap, offset);\n\t\t\treturn target;\n\t\t}\n\n\n\n\t\tprivate static readonly Dictionary<Type, Action<Array, Array, int, int[], int[], int>>\n\t\t\tBackMappedGroupCopyToFunMap = new Dictionary<Type, Action<Array, Array, int, int[], int[], int>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (s,t,c,b,f,o) => ((byte[])s).BackMappedGroupCopyTo(b, c, f, (byte[])t, o) },\n\t\t\t\t{ typeof(sbyte[]), (s,t,c,b,f,o) => ((sbyte[])s).BackMappedGroupCopyTo(b, c, f, (sbyte[])t, o) },\n\t\t\t\t{ typeof(short[]), (s,t,c,b,f,o) => ((short[])s).BackMappedGroupCopyTo(b, c, f, (short[])t, o) },\n\t\t\t\t{ typeof(ushort[]), (s,t,c,b,f,o) => ((ushort[])s).BackMappedGroupCopyTo(b, c, f, (ushort[])t, o) },\n\t\t\t\t{ typeof(int[]), (s,t,c,b,f,o) => ((int[])s).BackMappedGroupCopyTo(b, c, f, (int[])t, o) },\n\t\t\t\t{ typeof(uint[]), (s,t,c,b,f,o) => ((uint[])s).BackMappedGroupCopyTo(b, c, f, (uint[])t, o) },\n\t\t\t\t{ typeof(long[]), (s,t,c,b,f,o) => ((long[])s).BackMappedGroupCopyTo(b, c, f, (long[])t, o) },\n\t\t\t\t{ typeof(ulong[]), (s,t,c,b,f,o) => ((ulong[])s).BackMappedGroupCopyTo(b, c, f, (ulong[])t, o) },\n\t\t\t\t{ typeof(float[]), (s,t,c,b,f,o) => ((float[])s).BackMappedGroupCopyTo(b, c, f, (float[])t, o) },\n\t\t\t\t{ typeof(double[]), (s,t,c,b,f,o) => ((double[])s).BackMappedGroupCopyTo(b, c, f, (double[])t, o) },\n\t\t\t};\n\n\t\tpublic static void BackMappedGroupCopyTo(this Array source, int[] faceBackMap, int faceCount, int[] fia, Array target, int offset)\n\t\t{\n\t\t\tBackMappedGroupCopyToFunMap[source.GetType()]\n\t\t\t\t\t(source, target, faceCount, faceBackMap, fia, offset);\n\t\t}\n\n\t\tprivate static readonly Dictionary<Type, Action<Array, long, long>>\n\t\t\tSwapFunMap = new Dictionary<Type, Action<Array, long, long>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (a, i, j) => ((byte[])a).Swap(i, j) },\n\t\t\t\t{ typeof(sbyte[]), (a, i, j) => ((sbyte[])a).Swap(i, j) },\n\t\t\t\t{ typeof(short[]), (a, i, j) => ((short[])a).Swap(i, j) },\n\t\t\t\t{ typeof(ushort[]), (a, i, j) => ((ushort[])a).Swap(i, j) },\n\t\t\t\t{ typeof(int[]), (a, i, j) => ((int[])a).Swap(i, j) },\n\t\t\t\t{ typeof(uint[]), (a, i, j) => ((uint[])a).Swap(i, j) },\n\t\t\t\t{ typeof(long[]), (a, i, j) => ((long[])a).Swap(i, j) },\n\t\t\t\t{ typeof(ulong[]), (a, i, j) => ((ulong[])a).Swap(i, j) },\n\t\t\t\t{ typeof(float[]), (a, i, j) => ((float[])a).Swap(i, j) },\n\t\t\t\t{ typeof(double[]), (a, i, j) => ((double[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C3b[]), (a, i, j) => ((C3b[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C3us[]), (a, i, j) => ((C3us[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C3ui[]), (a, i, j) => ((C3ui[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C3f[]), (a, i, j) => ((C3f[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C3d[]), (a, i, j) => ((C3d[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C4b[]), (a, i, j) => ((C4b[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C4us[]), (a, i, j) => ((C4us[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C4ui[]), (a, i, j) => ((C4ui[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C4f[]), (a, i, j) => ((C4f[])a).Swap(i, j) },\n\t\t\t\t{ typeof(C4d[]), (a, i, j) => ((C4d[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V2i[]), (a, i, j) => ((V2i[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V2l[]), (a, i, j) => ((V2l[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V2f[]), (a, i, j) => ((V2f[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V2d[]), (a, i, j) => ((V2d[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V3i[]), (a, i, j) => ((V3i[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V3l[]), (a, i, j) => ((V3l[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V3f[]), (a, i, j) => ((V3f[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V3d[]), (a, i, j) => ((V3d[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V4i[]), (a, i, j) => ((V4i[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V4l[]), (a, i, j) => ((V4l[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V4f[]), (a, i, j) => ((V4f[])a).Swap(i, j) },\n\t\t\t\t{ typeof(V4d[]), (a, i, j) => ((V4d[])a).Swap(i, j) },\n\t\t\t};\n\n\t\tpublic static void Swap(this Array array, long i, long j)\n\t\t{\n\t\t\tSwapFunMap[array.GetType()](array, i, j);\n\t\t}\n\n\t\tprivate static readonly Dictionary<Type, Func<Array, int[], int, Func<int, bool>, Array>>\n\t\t\tGroupReversedCopyMap = new Dictionary<Type, Func<Array, int[], int, Func<int, bool>, Array>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (a, g, c, r) => ((byte[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(sbyte[]), (a, g, c, r) => ((sbyte[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(short[]), (a, g, c, r) => ((short[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(ushort[]), (a, g, c, r) => ((ushort[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(int[]), (a, g, c, r) => ((int[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(uint[]), (a, g, c, r) => ((uint[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(long[]), (a, g, c, r) => ((long[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(ulong[]), (a, g, c, r) => ((ulong[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(float[]), (a, g, c, r) => ((float[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(double[]), (a, g, c, r) => ((double[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C3b[]), (a, g, c, r) => ((C3b[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C3us[]), (a, g, c, r) => ((C3us[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C3ui[]), (a, g, c, r) => ((C3ui[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C3f[]), (a, g, c, r) => ((C3f[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C3d[]), (a, g, c, r) => ((C3d[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C4b[]), (a, g, c, r) => ((C4b[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C4us[]), (a, g, c, r) => ((C4us[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C4ui[]), (a, g, c, r) => ((C4ui[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C4f[]), (a, g, c, r) => ((C4f[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(C4d[]), (a, g, c, r) => ((C4d[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V2i[]), (a, g, c, r) => ((V2i[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V2l[]), (a, g, c, r) => ((V2l[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V2f[]), (a, g, c, r) => ((V2f[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V2d[]), (a, g, c, r) => ((V2d[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V3i[]), (a, g, c, r) => ((V3i[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V3l[]), (a, g, c, r) => ((V3l[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V3f[]), (a, g, c, r) => ((V3f[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V3d[]), (a, g, c, r) => ((V3d[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V4i[]), (a, g, c, r) => ((V4i[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V4l[]), (a, g, c, r) => ((V4l[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V4f[]), (a, g, c, r) => ((V4f[])a).GroupReversedCopy(g, c, r) },\n\t\t\t\t{ typeof(V4d[]), (a, g, c, r) => ((V4d[])a).GroupReversedCopy(g, c, r) },\n\t\t\t};\n\n\t\tpublic static Array GroupReversedCopy(\n\t\t\t\tthis Array array, int[] groupArray, int groupCount,\n\t\t\t\tFunc<int, bool> reverseMap)\n\t\t{\n\t\t\treturn GroupReversedCopyMap[array.GetType()](\n\t\t\t\t\t\tarray, groupArray, groupCount, reverseMap);\n\t\t}\n\n\t\tprivate static readonly Dictionary<Type, Action<Array, int[], int, Func<int, bool>>>\n\t\t\tReverseGroupsMap = new Dictionary<Type, Action<Array, int[], int, Func<int, bool>>>\n\t\t\t{\n\t\t\t\t{ typeof(byte[]), (a, g, c, r) => ((byte[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(sbyte[]), (a, g, c, r) => ((sbyte[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(short[]), (a, g, c, r) => ((short[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(ushort[]), (a, g, c, r) => ((ushort[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(int[]), (a, g, c, r) => ((int[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(uint[]), (a, g, c, r) => ((uint[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(long[]), (a, g, c, r) => ((long[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(ulong[]), (a, g, c, r) => ((ulong[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(float[]), (a, g, c, r) => ((float[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(double[]), (a, g, c, r) => ((double[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C3b[]), (a, g, c, r) => ((C3b[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C3us[]), (a, g, c, r) => ((C3us[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C3ui[]), (a, g, c, r) => ((C3ui[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C3f[]), (a, g, c, r) => ((C3f[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C3d[]), (a, g, c, r) => ((C3d[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C4b[]), (a, g, c, r) => ((C4b[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C4us[]), (a, g, c, r) => ((C4us[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C4ui[]), (a, g, c, r) => ((C4ui[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C4f[]), (a, g, c, r) => ((C4f[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(C4d[]), (a, g, c, r) => ((C4d[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V2i[]), (a, g, c, r) => ((V2i[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V2l[]), (a, g, c, r) => ((V2l[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V2f[]), (a, g, c, r) => ((V2f[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V2d[]), (a, g, c, r) => ((V2d[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V3i[]), (a, g, c, r) => ((V3i[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V3l[]), (a, g, c, r) => ((V3l[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V3f[]), (a, g, c, r) => ((V3f[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V3d[]), (a, g, c, r) => ((V3d[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V4i[]), (a, g, c, r) => ((V4i[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V4l[]), (a, g, c, r) => ((V4l[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V4f[]), (a, g, c, r) => ((V4f[])a).ReverseGroups(g, c, r) },\n\t\t\t\t{ typeof(V4d[]), (a, g, c, r) => ((V4d[])a).ReverseGroups(g, c, r) },\n\t\t\t};\n\n\t\tpublic static void ReverseGroups(\n\t\t\t\tthis Array array, int[] groupArray, int groupCount,\n\t\t\t\tFunc<int, bool> reverseMap)\n\t\t{\n\t\t\tReverseGroupsMap[array.GetType()](\n\t\t\t\t\tarray, groupArray, groupCount, reverseMap);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Apply a supplied function to each element of an array, with\n\t\t/// supplied conversion functions if the array is of a different\n\t\t/// type.\n\t\t/// </summary>\n\t\tpublic static Array Apply<T0, T1>(\n\t\t\tthis Array array, Func<T1, T1> fun,\n\t\t\tFunc<T0, T1> funT1ofT0, Func<T1, T0> funT0ofT1)\n\t\t{\n\t\t\tint length = array.Length;\n            if (array is T0[] t0a)\n            {\n                for (int i = 0; i < length; i++)\n                    t0a[i] = funT0ofT1(fun(funT1ofT0(t0a[i])));\n                return array;\n            }\n            if (array is T1[] t1a)\n            {\n                for (int i = 0; i < length; i++)\n                    t1a[i] = fun(t1a[i]);\n                return array;\n            }\n            throw new InvalidOperationException();\n\t\t}\n\n\t\tpublic static IEnumerable<T1> Elements<T0, T1>(\n\t\t\tthis Array array, Func<T0, T1> convert)\n\t\t{\n            if (array is T0[] t0a)\n            {\n                foreach (var e in t0a) yield return convert(e); yield break;\n            }\n            if (array is T1[] t1a)\n            {\n                foreach (var e in t1a) yield return e; yield break;\n            }\n        }\n\n\t\tpublic static T1[] CopyAndConvert<T0, T1>(\n\t\t\tthis Array array, Func<T0, T1> convert)\n\t\t{\n\t\t\tint length = array.Length;\n\t\t\tvar result = new T1[length];\n            if (array is T0[] t0a)\n            {\n                for (int i = 0; i < length; i++)\n                    result[i] = convert(t0a[i]);\n                return result;\n            }\n            if (array is T1[] t1a)\n            {\n                for (int i = 0; i < length; i++)\n                    result[i] = t1a[i];\n                return result;\n            }\n            throw new InvalidOperationException();\n\t\t}\n\n\t\tpublic static Tr[] CopyAndConvert<T0, T1, Tr>(\n\t\t\tthis Array array, Func<T0, T1> convert, Func<T1, Tr> fun)\n\t\t{\n\t\t\tint length = array.Length;\n\t\t\tvar result = new Tr[length];\n            if (array is T0[] t0a)\n            {\n                for (int i = 0; i < length; i++)\n                    result[i] = fun(convert(t0a[i]));\n                return result;\n            }\n            if (array is T1[] t1a)\n            {\n                for (int i = 0; i < length; i++)\n                    result[i] = fun(t1a[i]);\n                return result;\n            }\n            throw new InvalidOperationException();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/SequenceExtensions_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static partial class SequenceExtensions\n    {\n        #region byte Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is byte.MaxValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static byte Min(this IEnumerable<byte> sequence, byte minValue = byte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is byte.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static byte MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, byte> element_valueSelector, byte minValue = byte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is byte.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static byte MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, byte> element_valueSelector, ref TSeq minElement, byte minValue = byte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is byte.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, byte> element_valueSelector, byte minValue = byte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static byte MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, byte> element_valueSelector, byte minValue = byte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static byte MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, byte> element_valueSelector, ref TSeq minElement, byte minValue = byte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, byte> element_valueSelector, byte minValue = byte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is byte.MinValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static byte Max(this IEnumerable<byte> sequence, byte maxValue = byte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is byte.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static byte MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, byte> element_valueSelector, byte maxValue = byte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is byte.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static byte MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, byte> element_valueSelector, ref TSeq maxElement, byte maxValue = byte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is byte.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, byte> element_valueSelector, byte maxValue = byte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static byte MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, byte> element_valueSelector, byte maxValue = byte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static byte MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, byte> element_valueSelector, ref TSeq maxElement, byte maxValue = byte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, byte> element_valueSelector, byte maxValue = byte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted byte array with another ascendingly\n        /// sorted byte array resulting in a single ascendingly sorted\n        /// byte array.\n        /// </summary>\n        public static byte[] MergeAscending(this byte[] a0, byte[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new byte[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted byte array with another ascendingly\n        /// sorted byte array resulting in a single ascendingly sorted\n        /// byte array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, byte> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted byte array with another descendingly\n        /// sorted byte array resulting in a single descendingly sorted\n        /// byte array.\n        /// </summary>\n        public static byte[] MergeDescending(this byte[] a0, byte[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new byte[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted byte array with another descendingly\n        /// sorted byte array resulting in a single descendingly sorted\n        /// byte array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, byte> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region sbyte Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is sbyte.MaxValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static sbyte Min(this IEnumerable<sbyte> sequence, sbyte minValue = sbyte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is sbyte.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static sbyte MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, sbyte> element_valueSelector, sbyte minValue = sbyte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is sbyte.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static sbyte MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, sbyte> element_valueSelector, ref TSeq minElement, sbyte minValue = sbyte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is sbyte.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, sbyte> element_valueSelector, sbyte minValue = sbyte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static sbyte MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, sbyte> element_valueSelector, sbyte minValue = sbyte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static sbyte MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, sbyte> element_valueSelector, ref TSeq minElement, sbyte minValue = sbyte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, sbyte> element_valueSelector, sbyte minValue = sbyte.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is sbyte.MinValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static sbyte Max(this IEnumerable<sbyte> sequence, sbyte maxValue = sbyte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is sbyte.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static sbyte MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, sbyte> element_valueSelector, sbyte maxValue = sbyte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is sbyte.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static sbyte MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, sbyte> element_valueSelector, ref TSeq maxElement, sbyte maxValue = sbyte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is sbyte.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, sbyte> element_valueSelector, sbyte maxValue = sbyte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static sbyte MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, sbyte> element_valueSelector, sbyte maxValue = sbyte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static sbyte MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, sbyte> element_valueSelector, ref TSeq maxElement, sbyte maxValue = sbyte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, sbyte> element_valueSelector, sbyte maxValue = sbyte.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted sbyte array with another ascendingly\n        /// sorted sbyte array resulting in a single ascendingly sorted\n        /// sbyte array.\n        /// </summary>\n        public static sbyte[] MergeAscending(this sbyte[] a0, sbyte[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new sbyte[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted sbyte array with another ascendingly\n        /// sorted sbyte array resulting in a single ascendingly sorted\n        /// sbyte array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, sbyte> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted sbyte array with another descendingly\n        /// sorted sbyte array resulting in a single descendingly sorted\n        /// sbyte array.\n        /// </summary>\n        public static sbyte[] MergeDescending(this sbyte[] a0, sbyte[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new sbyte[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted sbyte array with another descendingly\n        /// sorted sbyte array resulting in a single descendingly sorted\n        /// sbyte array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, sbyte> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region short Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is short.MaxValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static short Min(this IEnumerable<short> sequence, short minValue = short.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is short.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static short MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, short> element_valueSelector, short minValue = short.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is short.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static short MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, short> element_valueSelector, ref TSeq minElement, short minValue = short.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is short.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, short> element_valueSelector, short minValue = short.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static short MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, short> element_valueSelector, short minValue = short.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static short MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, short> element_valueSelector, ref TSeq minElement, short minValue = short.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, short> element_valueSelector, short minValue = short.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is short.MinValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static short Max(this IEnumerable<short> sequence, short maxValue = short.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is short.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static short MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, short> element_valueSelector, short maxValue = short.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is short.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static short MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, short> element_valueSelector, ref TSeq maxElement, short maxValue = short.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is short.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, short> element_valueSelector, short maxValue = short.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static short MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, short> element_valueSelector, short maxValue = short.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static short MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, short> element_valueSelector, ref TSeq maxElement, short maxValue = short.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, short> element_valueSelector, short maxValue = short.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted short array with another ascendingly\n        /// sorted short array resulting in a single ascendingly sorted\n        /// short array.\n        /// </summary>\n        public static short[] MergeAscending(this short[] a0, short[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new short[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted short array with another ascendingly\n        /// sorted short array resulting in a single ascendingly sorted\n        /// short array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, short> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted short array with another descendingly\n        /// sorted short array resulting in a single descendingly sorted\n        /// short array.\n        /// </summary>\n        public static short[] MergeDescending(this short[] a0, short[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new short[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted short array with another descendingly\n        /// sorted short array resulting in a single descendingly sorted\n        /// short array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, short> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region ushort Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is ushort.MaxValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static ushort Min(this IEnumerable<ushort> sequence, ushort minValue = ushort.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is ushort.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static ushort MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ushort> element_valueSelector, ushort minValue = ushort.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is ushort.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static ushort MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ushort> element_valueSelector, ref TSeq minElement, ushort minValue = ushort.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is ushort.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ushort> element_valueSelector, ushort minValue = ushort.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static ushort MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, ushort> element_valueSelector, ushort minValue = ushort.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static ushort MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, ushort> element_valueSelector, ref TSeq minElement, ushort minValue = ushort.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, ushort> element_valueSelector, ushort minValue = ushort.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is ushort.MinValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static ushort Max(this IEnumerable<ushort> sequence, ushort maxValue = ushort.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is ushort.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static ushort MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ushort> element_valueSelector, ushort maxValue = ushort.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is ushort.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static ushort MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ushort> element_valueSelector, ref TSeq maxElement, ushort maxValue = ushort.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is ushort.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ushort> element_valueSelector, ushort maxValue = ushort.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static ushort MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, ushort> element_valueSelector, ushort maxValue = ushort.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static ushort MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, ushort> element_valueSelector, ref TSeq maxElement, ushort maxValue = ushort.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, ushort> element_valueSelector, ushort maxValue = ushort.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted ushort array with another ascendingly\n        /// sorted ushort array resulting in a single ascendingly sorted\n        /// ushort array.\n        /// </summary>\n        public static ushort[] MergeAscending(this ushort[] a0, ushort[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new ushort[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted ushort array with another ascendingly\n        /// sorted ushort array resulting in a single ascendingly sorted\n        /// ushort array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, ushort> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted ushort array with another descendingly\n        /// sorted ushort array resulting in a single descendingly sorted\n        /// ushort array.\n        /// </summary>\n        public static ushort[] MergeDescending(this ushort[] a0, ushort[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new ushort[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted ushort array with another descendingly\n        /// sorted ushort array resulting in a single descendingly sorted\n        /// ushort array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, ushort> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region int Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is int.MaxValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static int Min(this IEnumerable<int> sequence, int minValue = int.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is int.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static int MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, int> element_valueSelector, int minValue = int.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is int.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static int MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, int> element_valueSelector, ref TSeq minElement, int minValue = int.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is int.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, int> element_valueSelector, int minValue = int.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static int MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, int> element_valueSelector, int minValue = int.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static int MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, int> element_valueSelector, ref TSeq minElement, int minValue = int.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, int> element_valueSelector, int minValue = int.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is int.MinValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static int Max(this IEnumerable<int> sequence, int maxValue = int.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is int.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static int MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, int> element_valueSelector, int maxValue = int.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is int.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static int MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, int> element_valueSelector, ref TSeq maxElement, int maxValue = int.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is int.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, int> element_valueSelector, int maxValue = int.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static int MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, int> element_valueSelector, int maxValue = int.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static int MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, int> element_valueSelector, ref TSeq maxElement, int maxValue = int.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, int> element_valueSelector, int maxValue = int.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted int array with another ascendingly\n        /// sorted int array resulting in a single ascendingly sorted\n        /// int array.\n        /// </summary>\n        public static int[] MergeAscending(this int[] a0, int[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new int[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted int array with another ascendingly\n        /// sorted int array resulting in a single ascendingly sorted\n        /// int array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, int> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted int array with another descendingly\n        /// sorted int array resulting in a single descendingly sorted\n        /// int array.\n        /// </summary>\n        public static int[] MergeDescending(this int[] a0, int[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new int[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted int array with another descendingly\n        /// sorted int array resulting in a single descendingly sorted\n        /// int array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, int> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region uint Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is uint.MaxValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static uint Min(this IEnumerable<uint> sequence, uint minValue = uint.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is uint.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static uint MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, uint> element_valueSelector, uint minValue = uint.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is uint.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static uint MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, uint> element_valueSelector, ref TSeq minElement, uint minValue = uint.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is uint.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, uint> element_valueSelector, uint minValue = uint.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static uint MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, uint> element_valueSelector, uint minValue = uint.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static uint MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, uint> element_valueSelector, ref TSeq minElement, uint minValue = uint.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, uint> element_valueSelector, uint minValue = uint.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is uint.MinValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static uint Max(this IEnumerable<uint> sequence, uint maxValue = uint.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is uint.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static uint MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, uint> element_valueSelector, uint maxValue = uint.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is uint.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static uint MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, uint> element_valueSelector, ref TSeq maxElement, uint maxValue = uint.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is uint.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, uint> element_valueSelector, uint maxValue = uint.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static uint MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, uint> element_valueSelector, uint maxValue = uint.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static uint MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, uint> element_valueSelector, ref TSeq maxElement, uint maxValue = uint.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, uint> element_valueSelector, uint maxValue = uint.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted uint array with another ascendingly\n        /// sorted uint array resulting in a single ascendingly sorted\n        /// uint array.\n        /// </summary>\n        public static uint[] MergeAscending(this uint[] a0, uint[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new uint[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted uint array with another ascendingly\n        /// sorted uint array resulting in a single ascendingly sorted\n        /// uint array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, uint> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted uint array with another descendingly\n        /// sorted uint array resulting in a single descendingly sorted\n        /// uint array.\n        /// </summary>\n        public static uint[] MergeDescending(this uint[] a0, uint[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new uint[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted uint array with another descendingly\n        /// sorted uint array resulting in a single descendingly sorted\n        /// uint array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, uint> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region long Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is long.MaxValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static long Min(this IEnumerable<long> sequence, long minValue = long.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is long.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static long MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, long> element_valueSelector, long minValue = long.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is long.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static long MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, long> element_valueSelector, ref TSeq minElement, long minValue = long.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is long.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, long> element_valueSelector, long minValue = long.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static long MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, long> element_valueSelector, long minValue = long.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static long MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, long> element_valueSelector, ref TSeq minElement, long minValue = long.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, long> element_valueSelector, long minValue = long.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is long.MinValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static long Max(this IEnumerable<long> sequence, long maxValue = long.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is long.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static long MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, long> element_valueSelector, long maxValue = long.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is long.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static long MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, long> element_valueSelector, ref TSeq maxElement, long maxValue = long.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is long.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, long> element_valueSelector, long maxValue = long.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static long MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, long> element_valueSelector, long maxValue = long.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static long MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, long> element_valueSelector, ref TSeq maxElement, long maxValue = long.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, long> element_valueSelector, long maxValue = long.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted long array with another ascendingly\n        /// sorted long array resulting in a single ascendingly sorted\n        /// long array.\n        /// </summary>\n        public static long[] MergeAscending(this long[] a0, long[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new long[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted long array with another ascendingly\n        /// sorted long array resulting in a single ascendingly sorted\n        /// long array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, long> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted long array with another descendingly\n        /// sorted long array resulting in a single descendingly sorted\n        /// long array.\n        /// </summary>\n        public static long[] MergeDescending(this long[] a0, long[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new long[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted long array with another descendingly\n        /// sorted long array resulting in a single descendingly sorted\n        /// long array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, long> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region ulong Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is ulong.MaxValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static ulong Min(this IEnumerable<ulong> sequence, ulong minValue = ulong.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is ulong.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static ulong MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ulong> element_valueSelector, ulong minValue = ulong.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is ulong.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static ulong MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ulong> element_valueSelector, ref TSeq minElement, ulong minValue = ulong.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is ulong.MaxValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ulong> element_valueSelector, ulong minValue = ulong.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static ulong MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, ulong> element_valueSelector, ulong minValue = ulong.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static ulong MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, ulong> element_valueSelector, ref TSeq minElement, ulong minValue = ulong.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, ulong> element_valueSelector, ulong minValue = ulong.MaxValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is ulong.MinValue.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static ulong Max(this IEnumerable<ulong> sequence, ulong maxValue = ulong.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is ulong.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static ulong MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ulong> element_valueSelector, ulong maxValue = ulong.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is ulong.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static ulong MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ulong> element_valueSelector, ref TSeq maxElement, ulong maxValue = ulong.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is ulong.MinValue.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, ulong> element_valueSelector, ulong maxValue = ulong.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static ulong MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, ulong> element_valueSelector, ulong maxValue = ulong.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static ulong MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, ulong> element_valueSelector, ref TSeq maxElement, ulong maxValue = ulong.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, ulong> element_valueSelector, ulong maxValue = ulong.MinValue)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted ulong array with another ascendingly\n        /// sorted ulong array resulting in a single ascendingly sorted\n        /// ulong array.\n        /// </summary>\n        public static ulong[] MergeAscending(this ulong[] a0, ulong[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new ulong[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted ulong array with another ascendingly\n        /// sorted ulong array resulting in a single ascendingly sorted\n        /// ulong array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, ulong> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted ulong array with another descendingly\n        /// sorted ulong array resulting in a single descendingly sorted\n        /// ulong array.\n        /// </summary>\n        public static ulong[] MergeDescending(this ulong[] a0, ulong[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new ulong[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted ulong array with another descendingly\n        /// sorted ulong array resulting in a single descendingly sorted\n        /// ulong array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, ulong> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region float Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is float.PositiveInfinity.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static float Min(this IEnumerable<float> sequence, float minValue = float.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is float.PositiveInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static float MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, float> element_valueSelector, float minValue = float.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is float.PositiveInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static float MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, float> element_valueSelector, ref TSeq minElement, float minValue = float.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is float.PositiveInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, float> element_valueSelector, float minValue = float.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static float MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, float> element_valueSelector, float minValue = float.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static float MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, float> element_valueSelector, ref TSeq minElement, float minValue = float.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, float> element_valueSelector, float minValue = float.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is float.NegativeInfinity.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static float Max(this IEnumerable<float> sequence, float maxValue = float.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is float.NegativeInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static float MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, float> element_valueSelector, float maxValue = float.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is float.NegativeInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static float MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, float> element_valueSelector, ref TSeq maxElement, float maxValue = float.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is float.NegativeInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, float> element_valueSelector, float maxValue = float.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static float MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, float> element_valueSelector, float maxValue = float.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static float MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, float> element_valueSelector, ref TSeq maxElement, float maxValue = float.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, float> element_valueSelector, float maxValue = float.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted float array with another ascendingly\n        /// sorted float array resulting in a single ascendingly sorted\n        /// float array.\n        /// </summary>\n        public static float[] MergeAscending(this float[] a0, float[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new float[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted float array with another ascendingly\n        /// sorted float array resulting in a single ascendingly sorted\n        /// float array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, float> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted float array with another descendingly\n        /// sorted float array resulting in a single descendingly sorted\n        /// float array.\n        /// </summary>\n        public static float[] MergeDescending(this float[] a0, float[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new float[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted float array with another descendingly\n        /// sorted float array resulting in a single descendingly sorted\n        /// float array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, float> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region double Sequences\n\n        #region Extreme Values\n\n        /// <summary>\n        /// Finds the smallest element in a sequence, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or maxValue if no element is smaller.\n        /// The default value of minValue is double.PositiveInfinity.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static double Min(this IEnumerable<double> sequence, double minValue = double.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value < minValue) minValue = value;\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is double.PositiveInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static double MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, double> element_valueSelector, double minValue = double.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is double.PositiveInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minElement\">Is set to the element that yielded the smallest value or is not set if no element is smaller than the initial min value.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static double MinValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, double> element_valueSelector, ref TSeq minElement, double minValue = double.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the smallest value, that is smaller than the initially\n        /// supplied minValue, or the first such element if there are equally small\n        /// elements, or minValue if no element is smaller.\n        /// The default value of minValue is double.PositiveInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the minimum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"minValue\">The initially supplied minimum value.</param>\n        /// <returns>The element that yielded the minimum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MinElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, double> element_valueSelector, double minValue = double.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and return this value.\n        /// </summary>\n        public static double MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, double> element_valueSelector, double minValue = double.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value < minValue) minValue = value;\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static double MinValue<TSeq>(this TSeq[] sequence, Func<TSeq, double> element_valueSelector, ref TSeq minElement, double minValue = double.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the smallest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MinElement<TSeq>(this TSeq[] sequence, Func<TSeq, double> element_valueSelector, double minValue = double.PositiveInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var minElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value < minValue)\n                {\n                    minValue = value;\n                    minElement = element;\n                }\n            }\n            return minElement;\n        }\n\n        /// <summary>\n        /// Finds the largest element in a sequence, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or minValue if no element is larger.\n        /// The default value of maxValue is double.NegativeInfinity.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static double Max(this IEnumerable<double> sequence, double maxValue = double.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value > maxValue) maxValue = value;\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is double.NegativeInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static double MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, double> element_valueSelector, double maxValue = double.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is double.NegativeInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxElement\">Is set to the element that yielded the smallest value or is not set if no element is larger than the initial max value.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static double MaxValue<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, double> element_valueSelector, ref TSeq maxElement, double maxValue = double.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the largest value, that is larger than the initially\n        /// supplied maxValue, or the first such element if there are equally large\n        /// elements, or maxValue if no element is larger.\n        /// The default value of maxValue is double.NegativeInfinity.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the maximum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"maxValue\">The initially supplied maximum value.</param>\n        /// <returns>The element that yielded the maximum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq MaxElement<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, double> element_valueSelector, double maxValue = double.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and return this value.\n        /// </summary>\n        public static double MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, double> element_valueSelector, double maxValue = double.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value > maxValue) maxValue = value;\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static double MaxValue<TSeq>(this TSeq[] sequence, Func<TSeq, double> element_valueSelector, ref TSeq maxElement, double maxValue = double.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxValue;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the largest value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq MaxElement<TSeq>(this TSeq[] sequence, Func<TSeq, double> element_valueSelector, double maxValue = double.NegativeInfinity)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var maxElement = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value > maxValue)\n                {\n                    maxValue = value;\n                    maxElement = element;\n                }\n            }\n            return maxElement;\n        }\n\n        #endregion\n\n        #region Sorting\n\n        /// <summary>\n        /// Merge an ascendingly sorted double array with another ascendingly\n        /// sorted double array resulting in a single ascendingly sorted\n        /// double array.\n        /// </summary>\n        public static double[] MergeAscending(this double[] a0, double[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new double[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] < a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an ascendingly sorted double array with another ascendingly\n        /// sorted double array resulting in a single ascendingly sorted\n        /// double array.\n        /// </summary>\n        public static TSeq[] MergeAscending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, double> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) < element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted double array with another descendingly\n        /// sorted double array resulting in a single descendingly sorted\n        /// double array.\n        /// </summary>\n        public static double[] MergeDescending(this double[] a0, double[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new double[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0] > a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an descendingly sorted double array with another descendingly\n        /// sorted double array resulting in a single descendingly sorted\n        /// double array.\n        /// </summary>\n        public static TSeq[] MergeDescending<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, double> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0]) > element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        #endregion\n\n        #endregion\n\n\n    }\n}\n\nnamespace Aardvark.Base.CSharp\n{\n    /// <summary>\n    /// The following extensions reside in the special namespace\n    /// Aardvark.Base.CSharp as they mess with normal FSharp operation.\n    /// </summary>\n    public static partial class CSharpSequenceExtensions\n    {\n        #region Sequences of Tups\n\n        public static IEnumerable<T> Select<T0, T1, T>(\n        this IEnumerable<Tup<T0, T1>> sequence, Func<T0, T1, T> selector)\n        {\n            return sequence.Select(tup => selector(tup.E0, tup.E1));\n        }\n        public static IEnumerable<Tup<T0, T1>> Where<T0, T1>(\n        this IEnumerable<Tup<T0, T1>> sequence, Func<T0, T1, bool> predicate)\n        {\n            return sequence.Where(tup => predicate(tup.E0, tup.E1));\n        }\n\n        public static void ForEach<T0, T1>(this Tup<T0, T1>[] array, Action<T0, T1> act)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1);\n            }\n        }\n\n        public static void ForEach<T0, T1>(this Tup<T0, T1>[] array, Action<T0, T1, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1>(this List<Tup<T0, T1>> list, Action<T0, T1> act)\n        {\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1);\n            }\n        }\n\n        public static void ForEach<T0, T1>(this List<Tup<T0, T1>> list, Action<T0, T1, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1>(this IEnumerable<Tup<T0, T1>> seq, Action<T0, T1> act)\n        {\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1);\n        }\n\n        public static void ForEach<T0, T1>(this IEnumerable<Tup<T0, T1>> seq, Action<T0, T1, int> act)\n        {\n            int index = 0;\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, index++);\n        }\n\n        public static void Add<T0, T1>(this List<Tup<T0, T1>> list, T0 e0, T1 e1)\n        {\n            list.Add(new Tup<T0, T1>(e0, e1));\n        }\n\n        public static T[] CopyToArray<T0, T1, T>(this List<Tup<T0, T1>> list, Func<T0, T1, T> fun)\n        {\n            var count = list.Count;\n            var array = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; array[i] = fun(tup.E0, tup.E1);\n            }\n            return array;\n        }\n\n        public static T[] Map<T0, T1, T>(this Tup<T0, T1>[] array, Func<T0, T1, T> fun)\n        {\n            var count = array.Length;\n            var result = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = array[i]; result[i] = fun(tup.E0, tup.E1);\n            }\n            return result;\n        }\n\n        public static List<T> Map<T0, T1, T>(this List<Tup<T0, T1>> list, Func<T0, T1, T> fun)\n        {\n            var count = list.Count;\n            var result = new List<T>(count);\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; result.Add(fun(tup.E0, tup.E1));\n            }\n            return result;\n        }\n\n        public static IEnumerable<T> Select<T0, T1, T2, T>(\n        this IEnumerable<Tup<T0, T1, T2>> sequence, Func<T0, T1, T2, T> selector)\n        {\n            return sequence.Select(tup => selector(tup.E0, tup.E1, tup.E2));\n        }\n        public static IEnumerable<Tup<T0, T1, T2>> Where<T0, T1, T2>(\n        this IEnumerable<Tup<T0, T1, T2>> sequence, Func<T0, T1, T2, bool> predicate)\n        {\n            return sequence.Where(tup => predicate(tup.E0, tup.E1, tup.E2));\n        }\n\n        public static void ForEach<T0, T1, T2>(this Tup<T0, T1, T2>[] array, Action<T0, T1, T2> act)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2>(this Tup<T0, T1, T2>[] array, Action<T0, T1, T2, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2>(this List<Tup<T0, T1, T2>> list, Action<T0, T1, T2> act)\n        {\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2>(this List<Tup<T0, T1, T2>> list, Action<T0, T1, T2, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2>(this IEnumerable<Tup<T0, T1, T2>> seq, Action<T0, T1, T2> act)\n        {\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2);\n        }\n\n        public static void ForEach<T0, T1, T2>(this IEnumerable<Tup<T0, T1, T2>> seq, Action<T0, T1, T2, int> act)\n        {\n            int index = 0;\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, index++);\n        }\n\n        public static void Add<T0, T1, T2>(this List<Tup<T0, T1, T2>> list, T0 e0, T1 e1, T2 e2)\n        {\n            list.Add(new Tup<T0, T1, T2>(e0, e1, e2));\n        }\n\n        public static T[] CopyToArray<T0, T1, T2, T>(this List<Tup<T0, T1, T2>> list, Func<T0, T1, T2, T> fun)\n        {\n            var count = list.Count;\n            var array = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; array[i] = fun(tup.E0, tup.E1, tup.E2);\n            }\n            return array;\n        }\n\n        public static T[] Map<T0, T1, T2, T>(this Tup<T0, T1, T2>[] array, Func<T0, T1, T2, T> fun)\n        {\n            var count = array.Length;\n            var result = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = array[i]; result[i] = fun(tup.E0, tup.E1, tup.E2);\n            }\n            return result;\n        }\n\n        public static List<T> Map<T0, T1, T2, T>(this List<Tup<T0, T1, T2>> list, Func<T0, T1, T2, T> fun)\n        {\n            var count = list.Count;\n            var result = new List<T>(count);\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; result.Add(fun(tup.E0, tup.E1, tup.E2));\n            }\n            return result;\n        }\n\n        public static IEnumerable<T> Select<T0, T1, T2, T3, T>(\n        this IEnumerable<Tup<T0, T1, T2, T3>> sequence, Func<T0, T1, T2, T3, T> selector)\n        {\n            return sequence.Select(tup => selector(tup.E0, tup.E1, tup.E2, tup.E3));\n        }\n        public static IEnumerable<Tup<T0, T1, T2, T3>> Where<T0, T1, T2, T3>(\n        this IEnumerable<Tup<T0, T1, T2, T3>> sequence, Func<T0, T1, T2, T3, bool> predicate)\n        {\n            return sequence.Where(tup => predicate(tup.E0, tup.E1, tup.E2, tup.E3));\n        }\n\n        public static void ForEach<T0, T1, T2, T3>(this Tup<T0, T1, T2, T3>[] array, Action<T0, T1, T2, T3> act)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3>(this Tup<T0, T1, T2, T3>[] array, Action<T0, T1, T2, T3, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3>(this List<Tup<T0, T1, T2, T3>> list, Action<T0, T1, T2, T3> act)\n        {\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3>(this List<Tup<T0, T1, T2, T3>> list, Action<T0, T1, T2, T3, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3>(this IEnumerable<Tup<T0, T1, T2, T3>> seq, Action<T0, T1, T2, T3> act)\n        {\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3);\n        }\n\n        public static void ForEach<T0, T1, T2, T3>(this IEnumerable<Tup<T0, T1, T2, T3>> seq, Action<T0, T1, T2, T3, int> act)\n        {\n            int index = 0;\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, index++);\n        }\n\n        public static void Add<T0, T1, T2, T3>(this List<Tup<T0, T1, T2, T3>> list, T0 e0, T1 e1, T2 e2, T3 e3)\n        {\n            list.Add(new Tup<T0, T1, T2, T3>(e0, e1, e2, e3));\n        }\n\n        public static T[] CopyToArray<T0, T1, T2, T3, T>(this List<Tup<T0, T1, T2, T3>> list, Func<T0, T1, T2, T3, T> fun)\n        {\n            var count = list.Count;\n            var array = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; array[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3);\n            }\n            return array;\n        }\n\n        public static T[] Map<T0, T1, T2, T3, T>(this Tup<T0, T1, T2, T3>[] array, Func<T0, T1, T2, T3, T> fun)\n        {\n            var count = array.Length;\n            var result = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = array[i]; result[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3);\n            }\n            return result;\n        }\n\n        public static List<T> Map<T0, T1, T2, T3, T>(this List<Tup<T0, T1, T2, T3>> list, Func<T0, T1, T2, T3, T> fun)\n        {\n            var count = list.Count;\n            var result = new List<T>(count);\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; result.Add(fun(tup.E0, tup.E1, tup.E2, tup.E3));\n            }\n            return result;\n        }\n\n        public static IEnumerable<T> Select<T0, T1, T2, T3, T4, T>(\n        this IEnumerable<Tup<T0, T1, T2, T3, T4>> sequence, Func<T0, T1, T2, T3, T4, T> selector)\n        {\n            return sequence.Select(tup => selector(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4));\n        }\n        public static IEnumerable<Tup<T0, T1, T2, T3, T4>> Where<T0, T1, T2, T3, T4>(\n        this IEnumerable<Tup<T0, T1, T2, T3, T4>> sequence, Func<T0, T1, T2, T3, T4, bool> predicate)\n        {\n            return sequence.Where(tup => predicate(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4));\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4>(this Tup<T0, T1, T2, T3, T4>[] array, Action<T0, T1, T2, T3, T4> act)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4>(this Tup<T0, T1, T2, T3, T4>[] array, Action<T0, T1, T2, T3, T4, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4>(this List<Tup<T0, T1, T2, T3, T4>> list, Action<T0, T1, T2, T3, T4> act)\n        {\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4>(this List<Tup<T0, T1, T2, T3, T4>> list, Action<T0, T1, T2, T3, T4, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4>(this IEnumerable<Tup<T0, T1, T2, T3, T4>> seq, Action<T0, T1, T2, T3, T4> act)\n        {\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4);\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4>(this IEnumerable<Tup<T0, T1, T2, T3, T4>> seq, Action<T0, T1, T2, T3, T4, int> act)\n        {\n            int index = 0;\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, index++);\n        }\n\n        public static void Add<T0, T1, T2, T3, T4>(this List<Tup<T0, T1, T2, T3, T4>> list, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n        {\n            list.Add(new Tup<T0, T1, T2, T3, T4>(e0, e1, e2, e3, e4));\n        }\n\n        public static T[] CopyToArray<T0, T1, T2, T3, T4, T>(this List<Tup<T0, T1, T2, T3, T4>> list, Func<T0, T1, T2, T3, T4, T> fun)\n        {\n            var count = list.Count;\n            var array = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; array[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4);\n            }\n            return array;\n        }\n\n        public static T[] Map<T0, T1, T2, T3, T4, T>(this Tup<T0, T1, T2, T3, T4>[] array, Func<T0, T1, T2, T3, T4, T> fun)\n        {\n            var count = array.Length;\n            var result = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = array[i]; result[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4);\n            }\n            return result;\n        }\n\n        public static List<T> Map<T0, T1, T2, T3, T4, T>(this List<Tup<T0, T1, T2, T3, T4>> list, Func<T0, T1, T2, T3, T4, T> fun)\n        {\n            var count = list.Count;\n            var result = new List<T>(count);\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; result.Add(fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4));\n            }\n            return result;\n        }\n\n        public static IEnumerable<T> Select<T0, T1, T2, T3, T4, T5, T>(\n        this IEnumerable<Tup<T0, T1, T2, T3, T4, T5>> sequence, Func<T0, T1, T2, T3, T4, T5, T> selector)\n        {\n            return sequence.Select(tup => selector(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5));\n        }\n        public static IEnumerable<Tup<T0, T1, T2, T3, T4, T5>> Where<T0, T1, T2, T3, T4, T5>(\n        this IEnumerable<Tup<T0, T1, T2, T3, T4, T5>> sequence, Func<T0, T1, T2, T3, T4, T5, bool> predicate)\n        {\n            return sequence.Where(tup => predicate(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5));\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5>(this Tup<T0, T1, T2, T3, T4, T5>[] array, Action<T0, T1, T2, T3, T4, T5> act)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5>(this Tup<T0, T1, T2, T3, T4, T5>[] array, Action<T0, T1, T2, T3, T4, T5, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5>(this List<Tup<T0, T1, T2, T3, T4, T5>> list, Action<T0, T1, T2, T3, T4, T5> act)\n        {\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5>(this List<Tup<T0, T1, T2, T3, T4, T5>> list, Action<T0, T1, T2, T3, T4, T5, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5>(this IEnumerable<Tup<T0, T1, T2, T3, T4, T5>> seq, Action<T0, T1, T2, T3, T4, T5> act)\n        {\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5);\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5>(this IEnumerable<Tup<T0, T1, T2, T3, T4, T5>> seq, Action<T0, T1, T2, T3, T4, T5, int> act)\n        {\n            int index = 0;\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, index++);\n        }\n\n        public static void Add<T0, T1, T2, T3, T4, T5>(this List<Tup<T0, T1, T2, T3, T4, T5>> list, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5)\n        {\n            list.Add(new Tup<T0, T1, T2, T3, T4, T5>(e0, e1, e2, e3, e4, e5));\n        }\n\n        public static T[] CopyToArray<T0, T1, T2, T3, T4, T5, T>(this List<Tup<T0, T1, T2, T3, T4, T5>> list, Func<T0, T1, T2, T3, T4, T5, T> fun)\n        {\n            var count = list.Count;\n            var array = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; array[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5);\n            }\n            return array;\n        }\n\n        public static T[] Map<T0, T1, T2, T3, T4, T5, T>(this Tup<T0, T1, T2, T3, T4, T5>[] array, Func<T0, T1, T2, T3, T4, T5, T> fun)\n        {\n            var count = array.Length;\n            var result = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = array[i]; result[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5);\n            }\n            return result;\n        }\n\n        public static List<T> Map<T0, T1, T2, T3, T4, T5, T>(this List<Tup<T0, T1, T2, T3, T4, T5>> list, Func<T0, T1, T2, T3, T4, T5, T> fun)\n        {\n            var count = list.Count;\n            var result = new List<T>(count);\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; result.Add(fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5));\n            }\n            return result;\n        }\n\n        public static IEnumerable<T> Select<T0, T1, T2, T3, T4, T5, T6, T>(\n        this IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6>> sequence, Func<T0, T1, T2, T3, T4, T5, T6, T> selector)\n        {\n            return sequence.Select(tup => selector(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6));\n        }\n        public static IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6>> Where<T0, T1, T2, T3, T4, T5, T6>(\n        this IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6>> sequence, Func<T0, T1, T2, T3, T4, T5, T6, bool> predicate)\n        {\n            return sequence.Where(tup => predicate(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6));\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6>(this Tup<T0, T1, T2, T3, T4, T5, T6>[] array, Action<T0, T1, T2, T3, T4, T5, T6> act)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6>(this Tup<T0, T1, T2, T3, T4, T5, T6>[] array, Action<T0, T1, T2, T3, T4, T5, T6, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6>(this List<Tup<T0, T1, T2, T3, T4, T5, T6>> list, Action<T0, T1, T2, T3, T4, T5, T6> act)\n        {\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6>(this List<Tup<T0, T1, T2, T3, T4, T5, T6>> list, Action<T0, T1, T2, T3, T4, T5, T6, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6>(this IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6>> seq, Action<T0, T1, T2, T3, T4, T5, T6> act)\n        {\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6);\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6>(this IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6>> seq, Action<T0, T1, T2, T3, T4, T5, T6, int> act)\n        {\n            int index = 0;\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, index++);\n        }\n\n        public static void Add<T0, T1, T2, T3, T4, T5, T6>(this List<Tup<T0, T1, T2, T3, T4, T5, T6>> list, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6)\n        {\n            list.Add(new Tup<T0, T1, T2, T3, T4, T5, T6>(e0, e1, e2, e3, e4, e5, e6));\n        }\n\n        public static T[] CopyToArray<T0, T1, T2, T3, T4, T5, T6, T>(this List<Tup<T0, T1, T2, T3, T4, T5, T6>> list, Func<T0, T1, T2, T3, T4, T5, T6, T> fun)\n        {\n            var count = list.Count;\n            var array = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; array[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6);\n            }\n            return array;\n        }\n\n        public static T[] Map<T0, T1, T2, T3, T4, T5, T6, T>(this Tup<T0, T1, T2, T3, T4, T5, T6>[] array, Func<T0, T1, T2, T3, T4, T5, T6, T> fun)\n        {\n            var count = array.Length;\n            var result = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = array[i]; result[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6);\n            }\n            return result;\n        }\n\n        public static List<T> Map<T0, T1, T2, T3, T4, T5, T6, T>(this List<Tup<T0, T1, T2, T3, T4, T5, T6>> list, Func<T0, T1, T2, T3, T4, T5, T6, T> fun)\n        {\n            var count = list.Count;\n            var result = new List<T>(count);\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; result.Add(fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6));\n            }\n            return result;\n        }\n\n        public static IEnumerable<T> Select<T0, T1, T2, T3, T4, T5, T6, T7, T>(\n        this IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> sequence, Func<T0, T1, T2, T3, T4, T5, T6, T7, T> selector)\n        {\n            return sequence.Select(tup => selector(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7));\n        }\n        public static IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> Where<T0, T1, T2, T3, T4, T5, T6, T7>(\n        this IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> sequence, Func<T0, T1, T2, T3, T4, T5, T6, T7, bool> predicate)\n        {\n            return sequence.Where(tup => predicate(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7));\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(this Tup<T0, T1, T2, T3, T4, T5, T6, T7>[] array, Action<T0, T1, T2, T3, T4, T5, T6, T7> act)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(this Tup<T0, T1, T2, T3, T4, T5, T6, T7>[] array, Action<T0, T1, T2, T3, T4, T5, T6, T7, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(this List<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> list, Action<T0, T1, T2, T3, T4, T5, T6, T7> act)\n        {\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(this List<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> list, Action<T0, T1, T2, T3, T4, T5, T6, T7, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7, index++);\n            }\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(this IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> seq, Action<T0, T1, T2, T3, T4, T5, T6, T7> act)\n        {\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7);\n        }\n\n        public static void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(this IEnumerable<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> seq, Action<T0, T1, T2, T3, T4, T5, T6, T7, int> act)\n        {\n            int index = 0;\n            foreach (var tup in seq)\n                act(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7, index++);\n        }\n\n        public static void Add<T0, T1, T2, T3, T4, T5, T6, T7>(this List<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> list, T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7)\n        {\n            list.Add(new Tup<T0, T1, T2, T3, T4, T5, T6, T7>(e0, e1, e2, e3, e4, e5, e6, e7));\n        }\n\n        public static T[] CopyToArray<T0, T1, T2, T3, T4, T5, T6, T7, T>(this List<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> list, Func<T0, T1, T2, T3, T4, T5, T6, T7, T> fun)\n        {\n            var count = list.Count;\n            var array = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; array[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7);\n            }\n            return array;\n        }\n\n        public static T[] Map<T0, T1, T2, T3, T4, T5, T6, T7, T>(this Tup<T0, T1, T2, T3, T4, T5, T6, T7>[] array, Func<T0, T1, T2, T3, T4, T5, T6, T7, T> fun)\n        {\n            var count = array.Length;\n            var result = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = array[i]; result[i] = fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7);\n            }\n            return result;\n        }\n\n        public static List<T> Map<T0, T1, T2, T3, T4, T5, T6, T7, T>(this List<Tup<T0, T1, T2, T3, T4, T5, T6, T7>> list, Func<T0, T1, T2, T3, T4, T5, T6, T7, T> fun)\n        {\n            var count = list.Count;\n            var result = new List<T>(count);\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; result.Add(fun(tup.E0, tup.E1, tup.E2, tup.E3, tup.E4, tup.E5, tup.E6, tup.E7));\n            }\n            return result;\n        }\n\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/SequenceExtensions_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static partial class SequenceExtensions\n    {\n        //# Action<Action<int>, Func<string, string>> F = (o, f) => { Filter = f; o(0); Filter = null; };\n        //# foreach (var t in Meta.StandardNumericTypes) {\n        //#     var type = t.Name;\n        #region __type__ Sequences\n\n        #region Extreme Values\n\n        //# foreach (var isMin in new[] { true, false }) {\n        //#     Func<string, string> f = null; if (!isMin) f = s => s == \" < \" ? \" > \" : s;\n        //#     string Min, min, max, MaxValue, small, smalle; //string-tokens to be replaced in Max-Version\n        //#     if (isMin) {\n        //#         Min = \"Min\";\n        //#         min = \"min\"; max = \"max\";\n        //#         MaxValue = t.IsReal ? \"PositiveInfinity\" : \"MaxValue\";\n        //#         small = \"small\"; smalle = \"smalle\";\n        //#     } else {\n        //#         Min = \"Max\";\n        //#         min = \"max\"; max = \"min\";\n        //#         MaxValue = t.IsReal ? \"NegativeInfinity\" : \"MinValue\";\n        //#         small = \"large\"; smalle = \"large\";\n        //#     }\n        /// <summary>\n        /// Finds the __smalle__st element in a sequence, that is __smalle__r than the initially\n        /// supplied __min__Value, or the first such element if there are equally __small__\n        /// elements, or __max__Value if no element is __smalle__r.\n        /// The default value of __min__Value is __type__.__MaxValue__.\n        /// </summary>\n        /// <param name=\"sequence\">A sequence of values to determine the __min__imum value of.</param>\n        /// <param name=\"__min__Value\">The initially supplied __min__imum value.</param>\n        /// <returns>The __min__imum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence is null.</exception>\n        public static __type__ __Min__(this IEnumerable<__type__> sequence, __type__ __min__Value = __type__.__MaxValue__)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            foreach (var value in sequence)\n                if (value/*#F(o=>{*/ < /*#},f);*/__min__Value) __min__Value = value;\n            return __min__Value;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the __smalle__st value, that is __smalle__r than the initially\n        /// supplied __min__Value, or the first such element if there are equally __small__\n        /// elements, or __min__Value if no element is __smalle__r.\n        /// The default value of __min__Value is __type__.__MaxValue__.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the __min__imum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"__min__Value\">The initially supplied __min__imum value.</param>\n        /// <returns>The __min__imum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static __type__ __Min__Value<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, __type__> element_valueSelector, __type__ __min__Value = __type__.__MaxValue__)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value/*#F(o=>{*/ < /*#},f);*/__min__Value) __min__Value = value;\n            }\n            return __min__Value;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the __smalle__st value, that is __smalle__r than the initially\n        /// supplied __min__Value, or the first such element if there are equally __small__\n        /// elements, or __min__Value if no element is __smalle__r.\n        /// The default value of __min__Value is __type__.__MaxValue__.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the __min__imum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"__min__Element\">Is set to the element that yielded the smallest value or is not set if no element is __smalle__r than the initial __min__ value.</param>\n        /// <param name=\"__min__Value\">The initially supplied __min__imum value.</param>\n        /// <returns>The element that yielded the __min__imum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static __type__ __Min__Value<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, __type__> element_valueSelector, ref TSeq __min__Element, __type__ __min__Value = __type__.__MaxValue__)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value/*#F(o=>{*/ < /*#},f);*/__min__Value)\n                {\n                    __min__Value = value;\n                    __min__Element = element;\n                }\n            }\n            return __min__Value;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence, and\n        /// finds the element with the __smalle__st value, that is __smalle__r than the initially\n        /// supplied __min__Value, or the first such element if there are equally __small__\n        /// elements, or __min__Value if no element is __smalle__r.\n        /// The default value of __min__Value is __type__.__MaxValue__.\n        /// </summary>\n        /// <typeparam name=\"TSeq\">The type of the elements of sequence.</typeparam>\n        /// <param name=\"sequence\">A sequence of values to determine the __min__imum value of.</param>\n        /// <param name=\"element_valueSelector\">A transform function to apply to each element.</param>\n        /// <param name=\"__min__Value\">The initially supplied __min__imum value.</param>\n        /// <returns>The element that yielded the __min__imum value in the sequence.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">sequence or selector is null.</exception>\n        public static TSeq __Min__Element<TSeq>(this IEnumerable<TSeq> sequence, Func<TSeq, __type__> element_valueSelector, __type__ __min__Value = __type__.__MaxValue__)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var __min__Element = default(TSeq);\n            foreach (var element in sequence)\n            {\n                var value = element_valueSelector(element);\n                if (value/*#F(o=>{*/ < /*#},f);*/__min__Value)\n                {\n                    __min__Value = value;\n                    __min__Element = element;\n                }\n            }\n            return __min__Element;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the __smalle__st value of all elements and return this value.\n        /// </summary>\n        public static __type__ __Min__Value<TSeq>(this TSeq[] sequence, Func<TSeq, __type__> element_valueSelector, __type__ __min__Value = __type__.__MaxValue__)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var value = element_valueSelector(sequence[i]);\n                if (value/*#F(o=>{*/ < /*#},f);*/__min__Value) __min__Value = value;\n            }\n            return __min__Value;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the __smalle__st value of all elements, returns the value and\n        /// the corresponding element as a referenced parameter.\n        /// </summary>\n        public static __type__ __Min__Value<TSeq>(this TSeq[] sequence, Func<TSeq, __type__> element_valueSelector, ref TSeq __min__Element, __type__ __min__Value = __type__.__MaxValue__)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value/*#F(o=>{*/ < /*#},f);*/__min__Value)\n                {\n                    __min__Value = value;\n                    __min__Element = element;\n                }\n            }\n            return __min__Value;\n        }\n\n        /// <summary>\n        /// Invokes the value selector function on each element of a sequence,\n        /// finds the __smalle__st value of all elements and returns the\n        /// corresponding element.\n        /// </summary>\n        public static TSeq __Min__Element<TSeq>(this TSeq[] sequence, Func<TSeq, __type__> element_valueSelector, __type__ __min__Value = __type__.__MaxValue__)\n        {\n            if (sequence == null) throw new ArgumentNullException(\"sequence\");\n            if (element_valueSelector == null) throw new ArgumentNullException(\"element_valueSelector\");\n            var __min__Element = default(TSeq);\n            for (long i = 0; i < sequence.LongLength; i++)\n            {\n                var element = sequence[i];\n                var value = element_valueSelector(element);\n                if (value/*#F(o=>{*/ < /*#},f);*/__min__Value)\n                {\n                    __min__Value = value;\n                    __min__Element = element;\n                }\n            }\n            return __min__Element;\n        }\n\n        //# } // foreach isMin\n        #endregion\n\n        #region Sorting\n\n        //# foreach (var isAsc in new[] { true, false }) {\n        //#     var Ascending = isAsc ? \"Ascending\" : \"Descending\";\n        //#     var ascending = isAsc ? \"ascending\" : \"descending\";\n        //#     Func<string, string> f = null; if (!isAsc) f = s => s == \" < \" ? \" > \" : s;\n        /// <summary>\n        /// Merge an __ascending__ly sorted __type__ array with another __ascending__ly\n        /// sorted __type__ array resulting in a single __ascending__ly sorted\n        /// __type__ array.\n        /// </summary>\n        public static __type__[] Merge__Ascending__(this __type__[] a0, __type__[] a1)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new __type__[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (a0[i0]/*#F(o=>{*/ < /*#},f);*/a1[i1])\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        /// <summary>\n        /// Merge an __ascending__ly sorted __type__ array with another __ascending__ly\n        /// sorted __type__ array resulting in a single __ascending__ly sorted\n        /// __type__ array.\n        /// </summary>\n        public static TSeq[] Merge__Ascending__<TSeq>(this TSeq[] a0, TSeq[] a1, Func<TSeq, __type__> element_valueSelector)\n        {\n            long count0 = a0.LongLength;\n            long count1 = a1.LongLength;\n            var a = new TSeq[count0 + count1];\n            long i = 0, i0 = 0, i1 = 0;\n            while (i0 < count0 && i1 < count1)\n            {\n                if (element_valueSelector(a0[i0])/*#F(o=>{*/ < /*#},f);*/element_valueSelector(a1[i1]))\n                    a[i++] = a0[i0++];\n                else\n                    a[i++] = a1[i1++];\n            }\n            while (i0 < count0) a[i++] = a0[i0++];\n            while (i1 < count1) a[i++] = a1[i1++];\n            return a;\n        }\n\n        //# } // isAsc\n        #endregion\n\n        #endregion\n\n        //# } // foreach t\n\n    }\n}\n\nnamespace Aardvark.Base.CSharp\n{\n    /// <summary>\n    /// The following extensions reside in the special namespace\n    /// Aardvark.Base.CSharp as they mess with normal FSharp operation.\n    /// </summary>\n    public static partial class CSharpSequenceExtensions\n    {\n        #region Sequences of Tups\n\n        //# Action comma = () => Out(\", \");\n        //# for (int tc = 2; tc <= 8; tc++) {\n        //#   var Ti = tc.Expand(i => \"T\" + i).Join(\", \");\n        //#   var ei = tc.Expand(i => \"e\" + i).Join(\", \");\n        //#   var tupEi = tc.Expand(i => \"tup.E\" + i).Join(\", \");\n        public static IEnumerable<T> Select<__Ti__, T>(\n        this IEnumerable<Tup<__Ti__>> sequence, Func<__Ti__, T> selector)\n        {\n            return sequence.Select(tup => selector(__tupEi__));\n        }\n        public static IEnumerable<Tup<__Ti__>> Where<__Ti__>(\n        this IEnumerable<Tup<__Ti__>> sequence, Func<__Ti__, bool> predicate)\n        {\n            return sequence.Where(tup => predicate(__tupEi__));\n        }\n\n        public static void ForEach<__Ti__>(this Tup<__Ti__>[] array, Action<__Ti__> act)\n        {\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(__tupEi__);\n            }\n        }\n\n        public static void ForEach<__Ti__>(this Tup<__Ti__>[] array, Action<__Ti__, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < array.Length; i++)\n            {\n                var tup = array[i]; act(__tupEi__, index++);\n            }\n        }\n\n        public static void ForEach<__Ti__>(this List<Tup<__Ti__>> list, Action<__Ti__> act)\n        {\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(__tupEi__);\n            }\n        }\n\n        public static void ForEach<__Ti__>(this List<Tup<__Ti__>> list, Action<__Ti__, int> act)\n        {\n            int index = 0;\n            for (int i = 0; i < list.Count; i++)\n            {\n                var tup = list[i]; act(__tupEi__, index++);\n            }\n        }\n\n        public static void ForEach<__Ti__>(this IEnumerable<Tup<__Ti__>> seq, Action<__Ti__> act)\n        {\n            foreach (var tup in seq)\n                act(__tupEi__);\n        }\n\n        public static void ForEach<__Ti__>(this IEnumerable<Tup<__Ti__>> seq, Action<__Ti__, int> act)\n        {\n            int index = 0;\n            foreach (var tup in seq)\n                act(__tupEi__, index++);\n        }\n\n        public static void Add<__Ti__>(this List<Tup<__Ti__>> list, /*# tc.ForEach(i=>{*/T__i__ e__i__/*#}, comma); */)\n        {\n            list.Add(new Tup<__Ti__>(__ei__));\n        }\n\n        public static T[] CopyToArray<__Ti__, T>(this List<Tup<__Ti__>> list, Func<__Ti__, T> fun)\n        {\n            var count = list.Count;\n            var array = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; array[i] = fun(__tupEi__);\n            }\n            return array;\n        }\n\n        public static T[] Map<__Ti__, T>(this Tup<__Ti__>[] array, Func<__Ti__, T> fun)\n        {\n            var count = array.Length;\n            var result = new T[count];\n            for (int i = 0; i < count; i++)\n            {\n                var tup = array[i]; result[i] = fun(__tupEi__);\n            }\n            return result;\n        }\n\n        public static List<T> Map<__Ti__, T>(this List<Tup<__Ti__>> list, Func<__Ti__, T> fun)\n        {\n            var count = list.Count;\n            var result = new List<T>(count);\n            for (int i = 0; i < count; i++)\n            {\n                var tup = list[i]; result.Add(fun(__tupEi__));\n            }\n            return result;\n        }\n\n        //# } // tc\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/StreamExtensions.cs",
    "content": "﻿using System;\nusing System.IO;\n\nnamespace Aardvark.Base\n{\n    public static class StreamExtensions\n    {\n        /// <summary>\n        /// Reads <paramref name=\"count\"/> number of bytes from the current stream and advances the position within the stream.\n        /// </summary>\n        /// <param name=\"stream\">The stream to read from.</param>\n        /// <param name=\"buffer\">The buffer to read into.</param>\n        /// <param name=\"offset\">The byte offset in <paramref name=\"buffer\"/> at which to begin storing the data read from the current stream.</param>\n        /// <param name=\"count\">The number of bytes to be read from the current stream. Defaults to <paramref name=\"buffer\"/>.Length - <paramref name=\"offset\"/> if negative.</param>\n        /// <exception cref=\"EndOfStreamException\"></exception>\n        public static void ReadBytes(this Stream stream, byte[] buffer, int offset = 0, int count = -1)\n        {\n            if (stream == null) throw new ArgumentNullException(nameof(stream));\n            if (buffer == null) throw new ArgumentNullException(nameof(buffer));\n            if (offset < 0 || offset > buffer.Length) throw new ArgumentOutOfRangeException(nameof(offset));\n            if (count < 0) count = buffer.Length - offset;\n            if (count > buffer.Length - offset) throw new ArgumentException(\"The offset and count do not describe a valid range inside the buffer.\", nameof(count));\n\n#if NET8_0_OR_GREATER\n            stream.ReadExactly(buffer, offset, count);\n#else\n            int totalRead = 0;\n\n            while (totalRead < count)\n            {\n                int read = stream.Read(buffer, offset + totalRead, count - totalRead);\n                if (read == 0)\n                {\n                    throw new EndOfStreamException();\n                }\n\n                totalRead += read;\n            }\n#endif\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/StringExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class CharFun\n    {\n        public static bool IsWhiteSpace(this char ch)\n        {\n            return ch == ' ' || ch == '\\t' || ch == '\\r' || ch == '\\n';\n        }\n\n        public static bool IsSpaceOrTab(this char ch)\n        {\n            return ch == ' ' || ch == '\\t';\n        }\n    }\n\n    public static class StringFun\n    {\n        #region To<Type>\n\n        public static bool ToBool(this string self)\n        {\n            var s = self.Trim().ToLower();\n            if (s == \"true\" || s == \"t\") return true;\n            if (s == \"false\" || s == \"f\") return false;\n            double r;\n            // Double.TryParse() sets r to 0 if the conversion fails,\n            // which means we don't really need to check the return value.\n            Double.TryParse(s, out r);\n            return r != 0.0;\n        }\n\n        public static byte ToByte(this string self)\n        {\n            return byte.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static sbyte ToSByte(this string self)\n        {\n            return sbyte.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static short ToShort(this string self)\n        {\n            return short.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static ushort ToUShort(this string self)\n        {\n            return ushort.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static int ToInt(this string self)\n        {\n            return int.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static uint ToUInt(this string self)\n        {\n            return uint.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static long ToLong(this string self)\n        {\n            return long.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static ulong ToULong(this string self)\n        {\n            return ulong.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static float ToFloat(this string self)\n        {\n            return float.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static double ToDouble(this string self)\n        {\n            return double.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static DateTime ToDateTime(this string self)\n        {\n            return DateTime.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        public static decimal ToDecimal(this string self, decimal def)\n        {\n            decimal result;\n\n            if (!decimal.TryParse(self, out result))\n            {\n                result = def;\n            }\n\n            return result;\n        }\n\n        public static decimal ToDecimal(this string self)\n        {\n            return decimal.Parse(self, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Manipulations\n\n        public static string Capitalized(this string self)\n        {\n            if (self == null || self == \"\") return self;\n            return self.Substring(0, 1).ToUpperInvariant() + self.Substring(1);\n        }\n\n        public static string[] ToLower(this string[] self)\n        {\n            return self.Map(s => s.ToLower());\n        }\n\n        public static string[] ToUpper(this string[] self)\n        {\n            return self.Map(s => s.ToUpper());\n        }\n\n        public static IEnumerable<string> ToLower(this IEnumerable<string> self)\n        {\n            foreach (var s in self)\n                yield return s.ToLower();\n        }\n\n        public static IEnumerable<string> ToUpper(this IEnumerable<string> self)\n        {\n            foreach (var s in self)\n                yield return s.ToUpper();\n        }\n\n        #endregion\n\n        #region Plural\n\n        /// <summary>\n        /// Returns the english plural of the supplied word (i.e. the word\n        /// with \"s\" appended) if the supplied integer is not equal to one.\n        /// Otherwise the word is returned unchanged.\n        /// </summary>\n        public static string Plural(this string word, int s)\n        {\n            return word.Plural((long)s);\n        }\n\n        static readonly Dictionary<string, string> s_irregularPlural\n            = new Dictionary<string, string>\n        {\n            { \"aircraft\", \"aircraft\" },\n            { \"axis\", \"axes\" },\n            { \"bison\", \"bison\" },\n            { \"child\", \"children\" },\n            { \"deer\", \"deer\" },\n            { \"fish\", \"fish\" },\n            { \"foot\", \"feet\" },\n            { \"goose\", \"geese\" },\n            { \"louse\", \"lice\" },\n            { \"man\", \"men\" },\n            { \"moose\", \"moose\" },\n            { \"mouse\", \"mice\" },\n            { \"ox\", \"oxen\" },\n            { \"pike\", \"pike\" },\n            { \"salmon\", \"salmon\" },\n            { \"sheep\", \"sheep\" },\n            { \"tooth\", \"teeth\" },\n            { \"trout\", \"trout\" },\n            { \"woman\", \"women\" },\n        };\n\n        static readonly Dictionary<string, string>[] s_pluralEndings\n            = new Dictionary<string, string>[]\n        {\n            null,\n            new Dictionary<string, string> { { \"y\", \"ies\" } },\n            new Dictionary<string, string>\n            {\n                { \"ch\" , \"ches\" }, { \"ex\", \"ices\" },\n                { \"sh\" , \"shes\" }, { \"ss\", \"sses\" },\n            },\n        };\n\n        /// <summary>\n        /// Returns the english plural of the supplied word (i.e. the word\n        /// with \"s\" appended) if the supplied integer is not equal to one.\n        /// Otherwise the word is returned unchanged.\n        /// </summary>\n        public static string Plural(this string word, long s)\n        {\n            if (s == 1) return word;\n            string irregular;\n            if (s_irregularPlural.TryGetValue(word, out irregular))\n                return irregular;\n            else\n            {\n                for (int i = s_pluralEndings.Length-1; i > 0; i--)\n                {\n                    if (i > word.Length) continue;\n\n                    string ending = word.Substring(word.Length - i);\n                    string plural;\n                    if (s_pluralEndings[i].TryGetValue(ending, out plural))\n                        return word.Substring(0, word.Length - i) + plural;\n                }\n                return word + \"s\";\n            }\n        }\n\n        #endregion\n\n        #region Sub strings\n\n        /// <summary>\n        /// Returns leftmost n characters of this string.\n        /// </summary>\n        public static string Left(this string self, int n)\n        {\n            if (self.Length <= n) return self;\n            return self.Substring(0, n);\n        }\n\n        /// <summary>\n        /// Returns rightmost n characters of this string.\n        /// </summary>\n        public static string Right(this string self, int n)\n        {\n            int length = self.Length;\n            if (length <= n) return self;\n            return self.Substring(length - n);\n        }\n\n        /// <summary>\n        /// Return the substring for the range [start, end). For the start\n        /// index, negative indices count from the end. For the end index,\n        /// negative and the indices and the index 0 count from the end.\n        /// The ranges are clamped to the input string so that no exceptions\n        /// can occur. If the the start and end index are crossed, the null\n        /// string is returned.  As an example the call s.Sub(-3, 0) returns\n        /// a string containing the last 3 characters s or the complete\n        /// string s if its length is less than 3 characters.\n        /// </summary>\n        public static string Sub(this string self, int start, int end)\n        {\n            int len = self.Length;\n            start = start < 0 ? Math.Max(0, len + start) : Math.Min(start, len);\n            end = end <= 0 ? Math.Max(0, len + end) : Math.Min(end, len);\n            return start < end ? self.Substring(start, end - start) : null;\n        }\n\n        public static string Join(this IEnumerable<string> strings)\n        {\n            var result = new StringBuilder();\n            foreach (var s in strings) result.Append(s);\n            return result.ToString();\n        }\n\n        public static string Join(this IEnumerable<string> strings, string delimiter)\n        {\n            var result = new StringBuilder();\n            bool notFirst = false;\n            foreach (var s in strings)\n            {\n                if (notFirst) result.Append(delimiter); else notFirst = true;\n                result.Append(s);\n            }\n            return result.ToString();\n        }\n\n        private static readonly char[] s_whiteSpace\n                = new char[] { ' ', '\\t', '\\n', '\\r' };\n\n        public static string[] SplitOnWhitespace(this string s)\n        {\n            return s.Split(s_whiteSpace, StringSplitOptions.RemoveEmptyEntries);\n        }\n\n        #endregion\n\n        #region Square Brackets/Comma Split\n\n        /// <summary>\n        /// Splits a nested structure of comma-separated square bracket\n        /// delimited lists at level 1, i.e. inside the top most bracket.\n        /// E.g. \"[[a, b], foo, [c, d]]\" returns \"[a, b]\", \"foo\" and \"[c, d]\".\n        /// </summary>\n        public static IEnumerable<string> NestedBracketSplitLevelOne(this string text)\n        {\n            int level = 0;\n            int begin = 0;\n            int len = text.Length;\n            for (int pos = 0; pos < len; pos++)\n            {\n                switch (text[pos])\n                {\n                    case '[':\n                        if (++level == 1) begin = pos + 1;\n                        break;\n                    case ']':\n                        if (level-- == 1)\n                            yield return text.Substring(begin, pos - begin).Trim();\n                        break;\n                    case ',':\n                        if (level == 1)\n                        {\n                            yield return text.Substring(begin, pos - begin).Trim();\n                            begin = pos + 1;\n                        }\n                        break;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Splits a nested structure of comma-separated square bracked\n        /// delimited lists at a specified split level. Level 0 means that\n        /// the split is performed outside the outermost square brackets.\n        /// Level 1 means that the split is peformed inside the outermost\n        /// square brackets.\n        /// NOTE: The resulting parts are not trimmed. Use the Trim extension\n        /// to trim all resulting strings.\n        /// </summary>\n        public static IEnumerable<string> NestedBracketSplit(this string text, int splitLevel)\n        {\n            int level = 0;\n            int begin = 0;\n            int len = text.Length;\n            for (int pos = 0; pos < len; pos++)\n            {\n                switch (text[pos])\n                {\n                    case '[':\n                        ++level;\n                        if (level == splitLevel) begin = pos + 1;\n                        break;\n                    case ']':\n                        if (level == splitLevel)\n                            yield return text.Substring(begin, pos - begin);\n                        --level;\n                        break;\n                    case ',':\n                        if (level == splitLevel)\n                        {\n                            yield return text.Substring(begin, pos - begin);\n                            begin = pos + 1;\n                        }\n                        break;\n                }\n            }\n            if (level == splitLevel && len > begin)\n                yield return text.Substring(begin, len - begin);\n        }\n\n        #endregion\n\n        #region Guid\n\n        /// <summary>\n        /// Computes the SHA1 hash of the given string and returns it as Guid.\n        /// </summary>\n        public static Guid ToGuid(this string self)\n        {\n            if (string.IsNullOrEmpty(self)) return Guid.Empty;\n            var hash = self.ComputeSHA1Hash();\n#if NET8_0_OR_GREATER\n            return new Guid(hash.AsSpan(0, 16));\n#else\n            Array.Resize(ref hash, 16);\n            return new Guid(hash);\n#endif\n        }\n\n        /// <summary>\n        /// Combines the given strings and returns a Guid based on the SHA1 hash.\n        /// </summary>\n        public static Guid ToGuid(this IEnumerable<string> self)\n        {\n            var sb = new StringBuilder();\n            foreach (var x in self) sb.Append(x);\n            return sb.ToString().ToGuid();\n        }\n\n        /// <summary>\n        /// Combines the given Guids to a string and returns a Guid based on the SHA1 hash.\n        /// </summary>\n        public static Guid ToGuid(this IEnumerable<Guid> self)\n        {\n            var sb = new StringBuilder();\n            foreach (var x in self) sb.Append(x.ToString());\n            return sb.ToString().ToGuid();\n        }\n\n#endregion\n\n        #region Properties\n\n        public static bool IsNullOrEmpty(this string self)\n        {\n            return string.IsNullOrEmpty(self);\n        }\n\n        #endregion\n\n        #region Formatting\n        /// <summary>\n        /// Same as String.Format, but uses the InvariantCulture formatter\n        /// (The one we usually want. You know, . as decimal point,...)\n        /// </summary>\n        public static string FormatInvariant(this string format, params object[] args)\n        {\n            return string.Format(System.Globalization.CultureInfo.InvariantCulture, format, args);\n        }\n\n        #endregion\n\n        #region Hex/Binary\n\n        /// <summary>\n        /// Converts the byte array to string using base-64 encoding;\n        /// </summary>\n        public static string ToBase64(this byte[] data)\n        {\n            return Convert.ToBase64String(data);\n        }\n\n#if NET6_0_OR_GREATER\n        /// <summary>\n        /// Converts the byte span to string using base-64 encoding;\n        /// </summary>\n        public static string ToBase64(this Span<byte> span)\n        {\n            return Convert.ToBase64String(span);\n        }\n\n        /// <summary>\n        /// Converts the byte span to string using base-64 encoding;\n        /// </summary>\n        public static string ToBase64(this ReadOnlySpan<byte> span)\n        {\n            return Convert.ToBase64String(span);\n        }\n#endif\n\n        /// <summary>\n        /// Builds a string representing the byte arrays as hexadecimal number.\n        /// </summary>\n        public static string ToHex(this byte[] bytes)\n        {\n            char[] c = new char[bytes.Length * 2];\n\n            byte b;\n\n            for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)\n            {\n                b = ((byte)(bytes[bx] >> 4));\n                c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);\n\n                b = ((byte)(bytes[bx] & 0x0F));\n                c[++cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);\n            }\n\n            return new string(c);\n        }\n\n        /// <summary>\n        /// Converts a hexadecimal number as string to a byte array.\n        /// </summary>\n        public static byte[] HexToBytes(this string str)\n        {\n            if (str.Length == 0 || str.Length % 2 != 0)\n                return System.Array.Empty<byte>();\n\n            byte[] buffer = new byte[str.Length / 2];\n            char c;\n            for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)\n            {\n                // Convert first half of byte\n                c = str[sx];\n                buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);\n\n                // Convert second half of byte\n                c = str[++sx];\n                buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));\n            }\n\n            return buffer;\n        }\n\n#endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/Structs.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics.Contracts;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    #region IndexedValue\n\n    public readonly struct IndexedValue<T>\n    {\n        public readonly int Index;\n        public readonly T Value;\n\n        #region Constructor\n\n        public IndexedValue(int index, T value)\n        {\n            Index = index; Value = value;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ComparableIndexedValue\n\n    public readonly struct ComparableIndexedValue<T> : IComparable<ComparableIndexedValue<T>>\n        where T : IComparable<T>\n    {\n        public readonly int Index;\n        public readonly T Value;\n\n        #region Constructor\n\n        public ComparableIndexedValue(int index, T value)\n        {\n            Index = index; Value = value;\n        }\n\n        #endregion\n\n        #region IComparable<IndexedValue<T>> Members\n\n        public int CompareTo(ComparableIndexedValue<T> other)\n        {\n            return Value.CompareTo(other.Value);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    public static class StructsExtensions\n    {\n        #region ComparableIndexedValue\n\n        public static IEnumerable<ComparableIndexedValue<T>> ComparableIndexedValues<T>(\n                this IEnumerable<T> self)\n            where T : IComparable<T>\n        {\n            return self.Select((item, i) => new ComparableIndexedValue<T>(i, item));\n        }\n        \n        public static ComparableIndexedValue<T> ComparableIndexedValue<T>(\n                this T self, int index)\n            where T : IComparable<T>\n        {\n            return new ComparableIndexedValue<T>(index, self);\n        }\n\n        #endregion\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Extensions/SubRange.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// A SubRange is an IList that servers as a window into other ILists.\n    /// </summary>\n    public class SubRange<T> : IList<T>\n    {\n        private readonly IList<T> m_base;\n        private readonly int m_start;\n        private readonly int m_count;\n        private readonly int m_stop;\n\n        #region Constructor\n\n        public SubRange(IList<T> of, int index, int count)\n        {\n            m_base = of;\n            m_start = index;\n            m_count = count;\n            m_stop = m_start + m_count;\n        }\n\n        #endregion\n\n        #region IList<T> Members\n\n        public int IndexOf(T item)\n        {\n            for (int i = m_start; i < m_stop; i++)\n            {\n                if (m_base[i].Equals(item)) return i - m_start;\n            }\n            return -1;\n        }\n\n        public void Insert(int index, T item)\n        {\n            throw new InvalidOperationException();\n        }\n\n        public void RemoveAt(int index)\n        {\n            throw new InvalidOperationException();\n        }\n\n        public T this[int index]\n        {\n            get\n            {\n                if (index < 0 || index > m_count)\n                    throw new IndexOutOfRangeException();\n                return m_base[m_start + index];\n            }\n            set\n            {\n                if (index < 0 || index > m_count)\n                    throw new IndexOutOfRangeException();\n                m_base[m_start + index] = value;\n            }\n        }\n\n        #endregion\n\n        #region ICollection<T> Members\n\n        public void Add(T item)\n        {\n            throw new InvalidOperationException();\n        }\n\n        public void Clear()\n        {\n            throw new InvalidOperationException();\n        }\n\n        public bool Contains(T item)\n        {\n            return IndexOf(item) != -1;\n        }\n\n        public void CopyTo(T[] array, int arrayIndex)\n        {\n            for (int i = 0; i < m_count; i++)\n            {\n                array[arrayIndex + i] = m_base[m_start + i];\n            }\n        }\n\n        public int Count\n        {\n            get { return m_count; }\n        }\n\n        public bool IsReadOnly\n        {\n            get { return m_base.IsReadOnly; }\n        }\n\n        public bool Remove(T item)\n        {\n            throw new InvalidOperationException();\n        }\n\n        #endregion\n\n        #region IEnumerable<T> Members\n\n        public IEnumerator<T> GetEnumerator()\n        {\n            for (int i = m_start; i < m_stop; i++) yield return m_base[i];\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            for (int i = m_start; i < m_stop; i++) yield return m_base[i];\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/SystemDrawingExtensions.cs",
    "content": "﻿using System.Drawing;\n\nnamespace Aardvark.Base.SystemDrawingInterop\n{\n    /// <summary>\n    /// Extensions for converting between System.Drawing and Aardvark data types.\n    /// </summary>\n    public static class SystemDrawingExtensions\n    {\n        #region System.Drawing.Point\n\n        /// <summary>\n        /// System.Drawing.Point to V2i.\n        /// </summary>\n        public static V2i ToV2i(this Point p) => new V2i(p.X, p.Y);\n\n        /// <summary>\n        /// V2i to System.Drawing.Point.\n        /// </summary>\n        public static Point ToPoint(this V2i p) => new Point(p.X, p.Y);\n\n        #endregion\n\n        #region System.Drawing.Size\n\n        /// <summary>\n        /// System.Drawing.Size to V2i.\n        /// </summary>\n        public static V2i ToV2i(this Size s) => new V2i(s.Width, s.Height);\n\n        /// <summary>\n        /// V2i to System.Drawing.Size.\n        /// </summary>\n        public static Size ToSize(this V2i v) => new Size(v.X, v.Y);\n\n        #endregion\n\n        #region System.Drawing.Rectangle\n\n        /// <summary>\n        /// System.Drawing.Rectangle to Box2i.\n        /// </summary>\n        public static Box2i ToBox2i(this Rectangle r)\n            => new Box2i(r.Left, r.Top, r.Right, r.Bottom);\n\n        /// <summary>\n        /// Box2i to System.Drawing.Rectangle.\n        /// </summary>\n        public static Rectangle ToRectangle(this Box2i p)\n            => new Rectangle(p.Min.X, p.Min.Y, p.SizeX, p.SizeY);\n\n        #endregion\n\n        #region System.Drawing.Color\n\n        /// <summary>\n        /// C3b to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C3b color)\n            => Color.FromArgb(color.R, color.G, color.B);\n\n        /// <summary>\n        /// System.Drawing.Color to C3b.\n        /// </summary>\n        public static C3b ToC3b(this Color color)\n            => new C3b(color.R, color.G, color.B);\n\n        /// <summary>\n        /// C3us to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C3us color) => Color.FromArgb(\n            Col.UShortToByte(color.R),\n            Col.UShortToByte(color.G),\n            Col.UShortToByte(color.B));\n\n        /// <summary>\n        /// System.Drawing.Color to C3us.\n        /// </summary>\n        public static C3us ToC3us(this Color color) => new C3us(\n            Col.ByteToUShort(color.R),\n            Col.ByteToUShort(color.G),\n            Col.ByteToUShort(color.B));\n\n        /// <summary>\n        /// C3ui to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C3ui color) => Color.FromArgb(\n            Col.UIntToByte(color.R),\n            Col.UIntToByte(color.G),\n            Col.UIntToByte(color.B));\n\n        /// <summary>\n        /// System.Drawing.Color to C3ui.\n        /// </summary>\n        public static C3ui ToC3ui(this Color color) => new C3ui(\n            Col.ByteToUInt(color.R),\n            Col.ByteToUInt(color.G),\n            Col.ByteToUInt(color.B));\n\n        /// <summary>\n        /// C3f to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C3f color) => Color.FromArgb(\n            Col.FloatToByteClamped(color.R),\n            Col.FloatToByteClamped(color.G),\n            Col.FloatToByteClamped(color.B));\n\n        /// <summary>\n        /// System.Drawing.Color to C3f.\n        /// </summary>\n        public static C3f ToC3f(this Color color) => new C3f(\n            Col.ByteToFloat(color.R),\n            Col.ByteToFloat(color.G),\n            Col.ByteToFloat(color.B));\n\n        /// <summary>\n        /// C3d to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C3d color) => Color.FromArgb(\n            Col.DoubleToByteClamped(color.R),\n            Col.DoubleToByteClamped(color.G),\n            Col.DoubleToByteClamped(color.B));\n\n        /// <summary>\n        /// System.Drawing.Color to C3d.\n        /// </summary>\n        public static C3d ToC3d(this Color color) => new C3d(\n            Col.ByteToDouble(color.R),\n            Col.ByteToDouble(color.G),\n            Col.ByteToDouble(color.B));\n\n        /// <summary>\n        /// C4b to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C4b color)\n            => Color.FromArgb(color.A, color.R, color.G, color.B);\n\n        /// <summary>\n        /// System.Drawing.Color to C4b.\n        /// </summary>\n        public static C4b ToC4b(this Color color)\n            => new C4b(color.R, color.G, color.B, color.A);\n\n        /// <summary>\n        /// C4us to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C4us color) => Color.FromArgb(\n            Col.UShortToByte(color.A),\n            Col.UShortToByte(color.R),\n            Col.UShortToByte(color.G),\n            Col.UShortToByte(color.B));\n\n        /// <summary>\n        /// System.Drawing.Color to C4us.\n        /// </summary>\n        public static C4us ToC4us(this Color color) => new C4us(\n            Col.ByteToUShort(color.R),\n            Col.ByteToUShort(color.G),\n            Col.ByteToUShort(color.B),\n            Col.ByteToUShort(color.A));\n\n        /// <summary>\n        /// C4ui to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C4ui color) => Color.FromArgb(\n            Col.UIntToByte(color.A),\n            Col.UIntToByte(color.R),\n            Col.UIntToByte(color.G),\n            Col.UIntToByte(color.B));\n\n        /// <summary>\n        /// System.Drawing.Color to C4ui.\n        /// </summary>\n        public static C4ui ToC4ui(this Color color) => new C4ui(\n            Col.ByteToUInt(color.R),\n            Col.ByteToUInt(color.G),\n            Col.ByteToUInt(color.B),\n            Col.ByteToUInt(color.A));\n\n        /// <summary>\n        /// C4f to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C4f color) => Color.FromArgb(\n            Col.FloatToByteClamped(color.A),\n            Col.FloatToByteClamped(color.R),\n            Col.FloatToByteClamped(color.G),\n            Col.FloatToByteClamped(color.B));\n\n        /// <summary>\n        /// System.Drawing.Color to C4f.\n        /// </summary>\n        public static C4f ToC4f(this Color color) => new C4f(\n            Col.ByteToFloat(color.R),\n            Col.ByteToFloat(color.G),\n            Col.ByteToFloat(color.B),\n            Col.ByteToFloat(color.A));\n\n        /// <summary>\n        /// C4d to System.Drawing.Color.\n        /// </summary>\n        public static Color ToColor(this C4d color) => Color.FromArgb(\n            Col.DoubleToByteClamped(color.A),\n            Col.DoubleToByteClamped(color.R),\n            Col.DoubleToByteClamped(color.G),\n            Col.DoubleToByteClamped(color.B));\n\n        /// <summary>\n        /// System.Drawing.Color to C4d.\n        /// </summary>\n        public static C4d ToC4d(this Color color) => new C4d(\n            Col.ByteToDouble(color.R),\n            Col.ByteToDouble(color.G),\n            Col.ByteToDouble(color.B),\n            Col.ByteToDouble(color.A));\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/TupleExtensions.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public static class TupleExtensions\n    {\n        /// <summary>\n        /// Number of NaNs in tuple.\n        /// </summary>\n        public static int CountNonNaNs(this (double, double) p)\n        {\n            int count = 2;\n            if (double.IsNaN(p.Item1)) --count;\n            if (double.IsNaN(p.Item2)) --count;\n            return count;\n        }\n\n        /// <summary>\n        /// Number of NaNs in tuple.\n        /// </summary>\n        public static int CountNonNaNs(this (double, double, double) p)\n        {\n            int count = 3;\n            if (double.IsNaN(p.Item1)) --count;\n            if (double.IsNaN(p.Item2)) --count;\n            if (double.IsNaN(p.Item3)) --count;\n            return count;\n        }\n\n        /// <summary>\n        /// Number of NaNs in tuple.\n        /// </summary>\n        public static int CountNonNaNs(this (double, double, double, double) p)\n        {\n            int count = 4;\n            if (double.IsNaN(p.Item1)) --count;\n            if (double.IsNaN(p.Item2)) --count;\n            if (double.IsNaN(p.Item3)) --count;\n            if (double.IsNaN(p.Item4)) --count;\n            return count;\n        }\n\n        /// <summary>\n        /// Gets i-th value of tuple.\n        /// </summary>\n        public static double Get(this (double, double) p, int i)\n        {\n            switch (i)\n            {\n                case 0: return p.Item1;\n                case 1: return p.Item2;\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        /// <summary>\n        /// Gets i-th value of tuple.\n        /// </summary>\n        public static double Get(this (double, double, double) p, int i)\n        {\n            switch (i)\n            {\n                case 0: return p.Item1;\n                case 1: return p.Item2;\n                case 2: return p.Item3;\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        /// <summary>\n        /// Gets i-th value of tuple.\n        /// </summary>\n        public static double Get(this (double, double, double, double) p, int i)\n        {\n            switch (i)\n            {\n                case 0: return p.Item1;\n                case 1: return p.Item2;\n                case 2: return p.Item3;\n                case 3: return p.Item4;\n                default: throw new IndexOutOfRangeException();\n            }\n        }\r\n\r\n#if !TRAVIS_CI\n\n        /// <summary>\n        /// Sets i-th value in tuple (in-place).\n        /// </summary>\n        public static void Set(this ref (double, double) p, int i, double value)\n        {\n            switch (i)\n            {\n                case 0: p.Item1 = value; break;\n                case 1: p.Item2 = value; break;\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        /// <summary>\n        /// Sets i-th value in tuple (in-place).\n        /// </summary>\n        public static void Set(this ref (double, double, double) p, int i, double value)\n        {\n            switch (i)\n            {\n                case 0: p.Item1 = value; break;\n                case 1: p.Item2 = value; break;\n                case 2: p.Item3 = value; break;\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        /// <summary>\n        /// Sets i-th value in tuple (in-place).\n        /// </summary>\n        public static void Set(this ref (double, double, double, double) p, int i, double value)\n        {\n            switch (i)\n            {\n                case 0: p.Item1 = value; break;\n                case 1: p.Item2 = value; break;\n                case 2: p.Item3 = value; break;\n                case 3: p.Item4 = value; break;\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n#endif\n\r\n        /// <summary>\n        /// Creates tuple from given values with values in ascending order. \n        /// </summary>\n        public static (double, double) CreateAscending(double d0, double d1)\n            => d0 < d1 ? (d0, d1) : (d1, d0);\n\n        /// <summary>\n        /// Creates tuple from given values with values in ascending order. \n        /// </summary>\n        public static (double, double, double) CreateAscending(double d0, double d1, double d2)\n        {\n            if (d0 < d1)\n            {\n                if (d1 < d2)\n                    return (d0, d1, d2);\n                else\n                    return (d0 < d2) ? (d0, d2, d1) : (d2, d0, d1);\n            }\n            else\n            {\n                if (d2 < d1)\n                    return (d2, d1, d0);\n                else\n                    return (d0 < d2) ? (d1, d0, d2) : (d1, d2, d0);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/TypeExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Concurrent;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    public static class TypeExtensions\n    {\n        private static readonly MethodInfo unsafeSizeOfMeth = typeof(Unsafe).GetMethod(nameof(Unsafe.SizeOf), BindingFlags.Public | BindingFlags.Static);\n\n        private static readonly ConcurrentDictionary<Type, int> unsafeTypeSizes = new();\n\n        /// <summary>\n        /// Returns the managed size of the given type.\n        /// </summary>\n        public static int GetCLRSize(this Type t)\n        {\n            return unsafeTypeSizes.GetOrAdd(t, t =>\n            {\n                var mi = unsafeSizeOfMeth.MakeGenericMethod(t);\n                return (int)mi.Invoke(null, null);\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Extensions/VariousExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class VariousExtensions\n    {\n        public static IEnumerable<T> Expand<T>(this int n, Func<int, T> fun)\n        {\n            for (int i = 0; i < n; i++)\n                yield return fun(i);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geodesy/GeoConsts.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// Holds data for a geodesic transform from one datum to another. \n    /// </summary>\n    public class GeoDatum\n    {\n        private readonly double m_dx;\n        private readonly double m_dy;\n        private readonly double m_dz;\n\n        private readonly double m_rx;\n        private readonly double m_ry;\n        private readonly double m_rz;\n        private readonly double m_ds;\n\n        /// <summary>\n        /// Constructs geodetic datum.\n        /// Deltas and Scaling should be provided in meters.\n        /// Rotation has to be given in arc-seconds.\n        /// </summary>\n        /// <param name=\"dx\">Delta x</param>\n        /// <param name=\"dy\">Delta y</param>\n        /// <param name=\"dz\">Delta z</param>\n        /// <param name=\"rx\">Rotation x</param>\n        /// <param name=\"ry\">Rotation y</param>\n        /// <param name=\"rz\">Rotation z</param>\n        /// <param name=\"ds\">Scaling</param>\n        public GeoDatum(\n                double dx, double dy, double dz,\n                double rx, double ry, double rz,\n                double ds )\n        {\n            m_dx = dx;\n            m_dy = dy;\n            m_dz = dy;\n            m_rx = rx;\n            m_ry = ry;\n            m_rz = rz;\n\n            m_ds = ds;\n        }\n\n        /// <summary>\n        /// Delta X\n        /// </summary>\n        public double dX  => m_dx;\n\n        /// <summary>\n        /// Delta Y\n        /// </summary>\n        public double dY => m_dy;\n\n        /// <summary>\n        /// Delta Z\n        /// </summary>\n        public double dZ => m_dz;\n\n        /// <summary>\n        /// Rotation X in arc-seconds.\n        /// </summary>\n        public double rXsec => m_rx;\n\n        /// <summary>\n        /// Rotation Y in arc-seconds.\n        /// </summary>\n        public double rYsec => m_ry;\n\n        /// <summary>\n        /// Rotation Z in arc seconds.\n        /// </summary>\n        public double rZsec => m_rz;\n\n        /// <summary>\n        /// Rotation X in radians.\n        /// </summary>\n        public double rXrad => m_rx * Constant.ArcSecond;\n\n        /// <summary>\n        /// Rotation Y in radians.\n        /// </summary>\n        public double rYrad => m_ry * Constant.ArcSecond;\n\n        /// <summary>\n        /// Rotation Z in radians.\n        /// </summary>\n        public double rZrad => m_rz * Constant.ArcSecond;\n\n        /// <summary>\n        /// Scaling in meters.\n        /// </summary>\n        public double dS => m_ds;\n\n\n        /// <summary>\n        /// Conversion from WGS84 to Austria NS (MGI 1).\n        /// </summary>\n        public static readonly GeoDatum Wgs84toAustriaNs1 =\n            new GeoDatum(-575.0, -93.0, -466.0, 5.1, 1.6, 5.2, -2.5);\n\n        /// <summary>\n        /// Cconversion from WGS84 to Austria NS (MGI 2).\n        /// </summary>\n        public static readonly GeoDatum Wgs84toAustriaNs2 =\n            new GeoDatum(-577.326, -90.129, -463.919, 5.14, 1.47, 5.30, -2.4232);\n\n        /// <summary>\n        /// Conversion from Austria NS1 (MGI) to WGS84.\n        /// </summary>\n        public static readonly GeoDatum AustriaNs1toWgs84 =\n            new GeoDatum(575.0, 93.0, 466.0, -5.1, -1.6, -5.2, 2.5);\n\n        /// <summary>\n        /// Conversion FROM Austria NS2 (MGI) TO WGS84.\n        /// </summary>\n        public static readonly GeoDatum AustriaNs2toWgs84 =\n            new GeoDatum(577.326, 90.129, 463.919, -5.14, -1.47, -5.30, 2.4232);\n    }\n\n    /// <summary>\n    /// This struct provides properties for a particular World-Ellipsoid. \n    /// It is defined by ist two radii: \"a\" and \"b\".\n    /// </summary>\n    public readonly struct GeoEllipsoid\n    {\n        public readonly double A;\n        public readonly double B;\n        public readonly double F;\n\n        /// <summary>\n        /// Construct a geo-ellipsoid from semi-major axis a (bigger radius),\n        /// semi-minor axis b (smaller radius) and flattening f. Since only\n        /// two of these are necessary for specification, use the static\n        /// functions <see cref=\"FromAB\"/> and <see cref=\"FromAF\"/> to construct\n        /// ellipsoids given their defining parameters.\n        /// </summary>\n        public GeoEllipsoid(double a, double b, double f)\n        {\n            A = a; B = b; F = f;\n        }\n\n        public static GeoEllipsoid FromAB(double a, double b)\n            => new GeoEllipsoid(a, b, (a - b) / a);\n\n        public static GeoEllipsoid FromAF(double a, double f)\n            => new GeoEllipsoid(a, a * (1.0 - f), f);\n\n        /// <summary>\n        /// Returns the inverse of the flattening: 1/f.\n        /// </summary>\n        public double InvF => (1.0 / F);\n\n        /// <summary>\n        /// Returns the first eccentricity squared: e^2 = (a^2-b^2)/a^2.\n        /// </summary>\n        public double EQ => (A * A - B * B) / (A * A);\n\n        /// <summary>\n        /// Returns the second eccentricity squared: e2^2 = (a^2-b^2)/b^2.\n        /// </summary>\n        public double E2Q => (A * A - B * B) / (B * B);\n\n        public static readonly GeoEllipsoid Airy1830 = FromAB(6377563.396, 6356256.909);\n        public static readonly GeoEllipsoid Bessel1841 = FromAB(6377397.15508, 6356078.96290);\n        public static readonly GeoEllipsoid Grs80 = FromAF(6378137.0, 1.0 / 298.257222101);\n        public static readonly GeoEllipsoid International1924 = FromAF(6378388.0, 1.0 / 297.0);\n        public static readonly GeoEllipsoid Clarke1880 = FromAF(6378249.145, 1.0 / 293.465);\n        public static readonly GeoEllipsoid Wgs84 = FromAF(6378137.0, 1.0 / 298.257223563);\n    }\n\n    /// <summary>\n    /// Static class. Provides constants for Geodesic Conversions.\n    /// </summary>\n    public static class GeoConstant\n    {\n        /// <summary>\n        /// Returns the M28 meridian used in austrian Gauss-Krueger System (MGI) -> GK-reference meridian for West-Austria.\n        /// (28 deg from Ferro = 10 deg + 20 min from Greenwich).\n        /// </summary>\n        public const double AustriaM28 = 10 + 1 / 3.0;\n        /// <summary>\n        /// Returns the M31 meridian used in austrian Gauss-Krueger System (MGI) -> GK-reference meridian for Mid-Austria.\n        /// (31 deg from Ferro = 13 deg + 20 min from Greenwich).\n        /// </summary>\n        public const double AustriaM31 = 13 + 1 / 3.0;\n        /// <summary>\n        /// Returns the M34 meridian used in austrian Gauss-Krueger System (MGI) -> GK-reference meridian for East-Austria.\n        /// (34 deg from Ferro = 16 deg + 20 min from Greenwich).\n        /// </summary>\n        public const double AustriaM34 = 16 + 1 / 3.0;\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geodesy/GeoConversion.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Net;\nusing static Aardvark.Base.Constant;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public static class Geo\n    {\n        #region Conversion Methods\n\n        /// <summary>\n        /// Returns the XYZ-coordinates from longitude, latitude and height on a given reference ellipsoid.\n        /// </summary>\n        public static V3d XyzFromLonLatHeight(V3d lonLatHeight, GeoEllipsoid ellipsoid)\n        {\n            double lam = Conversion.RadiansFromDegrees(lonLatHeight.X);\n            double phi = Conversion.RadiansFromDegrees(lonLatHeight.Y);\n            double h = lonLatHeight.Z;\n\n            double cos_lam = Cos(lam);\n            double cos_phi = Cos(phi);\n            double sin_lam = Sin(lam);\n            double sin_phi = Sin(phi);\n\n            // eccentricity square\n            double eq = ellipsoid.EQ;\n\n            // radius of the curvature in prime vertical\n            double Rv = ellipsoid.A / (1.0 - eq * sin_phi * sin_phi).Sqrt();\n\n            V3d result = new V3d\n            {\n                X = (Rv + h) * cos_phi * cos_lam,\n                Y = (Rv + h) * cos_phi * sin_lam,\n                Z = ((1.0 - eq) * Rv + h) * sin_phi\n            };\n\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the longitude, latitude and height from XYZ-coords on a given world reference ellipsoid. \n        /// </summary>\n        /// <param name=\"xyz\">Vector with xyz.</param>\n        /// <param name=\"ellipsoid\">GeoEllipsoid from the GeoConsts class.</param>\n        /// <returns>Position vector with Lon,Lat,Hei</returns>\n        public static V3d LonLatHeightFromXyz(V3d xyz, GeoEllipsoid ellipsoid)\n        {\n            // this implementation follows the Bowring Method (85).\n            // It might be extended to the newer Toms Method (99), but is delivers suitable results.\n\n            double a = ellipsoid.A;\n            double b = ellipsoid.B;\n\n            // Distance between x and y.\n            double W = (xyz.X * xyz.X + xyz.Y * xyz.Y).Sqrt();\n\n            // apprx phi\n            double PHI = Atan((xyz.Z * a) / (W * b));\n\n            double eq = ellipsoid.EQ;\n            double e2q = ellipsoid.E2Q;// (eq / (1.0 - eq)).Sqrt();\n\n            double lam = Atan(xyz.Y / xyz.X);\n\n            double sinPhi = (PHI).Sin();\n            double sinPhiTo3 = sinPhi * sinPhi * sinPhi;\n\n            double cosPhi = (PHI).Cos();\n            double cosPhiTo3 = cosPhi * cosPhi * cosPhi;\n\n            double phi = Atan((xyz.Z + e2q * b * sinPhiTo3) / (W - eq * a * cosPhiTo3));\n            double sinphi = phi.Sin();\n\n            // curvature in the prime vertical\n            double Rv = a / (1.0 - eq * sinphi * sinphi).Sqrt();\n\n            double cosphi = phi.Cos();\n            double h = W / cosphi - Rv;\n\n            double lat = Conversion.DegreesFromRadians(phi);// phi * 180 / pi;\n            double lon = Conversion.DegreesFromRadians(lam); // lam * 180 / pi;\n\n            return new V3d(lon, lat, h);\n        }\n\n        /// <summary>\n        /// Returns WGS84 Longitude/Latitude/Height for given street address,\n        /// or null if address not found. Uses maps.google.com webservice.\n        /// </summary>\n        [Obsolete(\"Uses unsupported Google Geocoding V2 API.\")]\n        public static V3d? Wgs84FromStreetAddress(string address, string key)\n        {\n            var output = \"csv\";\n            var url = @\"http://maps.google.com/maps/geo?\"\n                        + \"q=\" + Uri.EscapeDataString(address)\n                        + \"&output=\" + output\n                        + \"&key=\" + key;\n\n            var resp = new WebClient().DownloadString(url);\n            var tokens = resp.Split(',');\n            if (tokens.Length != 4) throw new FormatException();\n            if (tokens[0] != \"200\") return null;\n            return new V3d(\n                double.Parse(tokens[2], CultureInfo.InvariantCulture),\n                double.Parse(tokens[3], CultureInfo.InvariantCulture),\n                151.0);\n        }\n\n        /// <summary>\n        /// Transforms XYZ coord on one reference ellipsoid to XYZ coords on another\n        /// ref ellipsoid. The ellipsoids-difference is defined in a geometric datum\n        /// which is passes as the second argument.\n        /// </summary>\n        public static V3d HelmertsTransformXyzToXyz(V3d xyz, GeoDatum datum)\n        {\n            // transformation matrix\n            var T = new M33d(1.0, datum.rZrad, -datum.rYrad,\n                            -datum.rZrad, 1.0, datum.rXrad,\n                             datum.rYrad, -datum.rXrad, 1.0);\n\n            // delta in ellipsoid center positions\n            var dP = new V3d(datum.dX, datum.dY, datum.dZ);\n\n            // scale factor\n            var mu = new Scale3d(datum.dS * 0.000001 + 1.0);\n\n            var result = dP + (mu * T) * xyz;\n            return result;\n        }\n\n        /// <summary>\n        /// Gauss-Krueger projection from a reference ellipsoid datum (Lon/Lat/Height) to local GK-coordinates (in meters).\n        /// </summary>\n        /// <param name=\"lonLatHeight\">V3d with Lon/Lat/Height.</param>\n        /// <param name=\"ellipsoid\"></param>\n        /// <param name=\"zeroMeridian\"></param>\n        public static V3d GaussKruegerEllipsoidToPlane(\n            V3d lonLatHeight, GeoEllipsoid ellipsoid, double zeroMeridian\n            )\n        {\n            double phi = Conversion.RadiansFromDegrees(lonLatHeight.Y);\n            double lam = Conversion.RadiansFromDegrees(lonLatHeight.X - zeroMeridian);\n\n            double cosphi = phi.Cos();\n\n            double a = ellipsoid.A;\n            double b = ellipsoid.B;\n            double n = (a - b) / (a + b);\n\n            //n = (a-b)/(a+b);\n            double nTo2 = n * n;\n            double nTo3 = nTo2 * n;\n            double nTo4 = nTo3 * n;\n            double nTo5 = nTo4 * n;\n\n            // arc length approx. polynom coefficients\n            double c1 = (a + b) / 2.0 * (1.0 + nTo2 / 4.0 + nTo4 / 64.0);\n            double c2 = -(3.0 / 2.0) * n + (9.0 / 16.0) * nTo3 - (3.0 / 32.0) * nTo5;\n            double c3 = (15.0 / 16.0) * nTo2 - (15.0 / 32.0) * nTo4;\n            double c4 = -(35.0 / 48.0) * nTo3 + (105.0 / 256.0) * nTo5;\n            double c5 = (315.0 / 512.0) * nTo4;\n\n            // sine of multiple of phi\n            double sin2phi = (2.0 * phi).Sin();\n            double sin4phi = (4.0 * phi).Sin();\n            double sin6phi = (6.0 * phi).Sin();\n            double sin8phi = (8.0 * phi).Sin();\n\n            // arc lenght of the meridan\n            double B = c1 * (phi + c2 * sin2phi + c3 * sin4phi + c4 * sin6phi + c5 * sin8phi);\n\n            //% second nummerical eccentrencity\n            double e2q = ellipsoid.E2Q;\n\n            // cos(phi) to powers\n            double cosphiTo2 = cosphi * cosphi;\n            double cosphiTo3 = cosphiTo2 * cosphi;\n            double cosphiTo4 = cosphiTo3 * cosphi;\n            double cosphiTo5 = cosphiTo4 * cosphi;\n            double cosphiTo6 = cosphiTo5 * cosphi;\n            double cosphiTo7 = cosphiTo6 * cosphi;\n            double cosphiTo8 = cosphiTo7 * cosphi;\n\n            //% auxilary quantity 1\n            double nuTo2 = e2q * cosphiTo2;\n\n            //%radius of the curvature in prime vertical\n            double N = (a * a) / (b * (1.0 + nuTo2).Sqrt());\n\n            // lambda to powers\n            double lamTo2 = lam * lam;\n            double lamTo3 = lamTo2 * lam;\n            double lamTo4 = lamTo3 * lam;\n            double lamTo5 = lamTo4 * lam;\n            double lamTo6 = lamTo5 * lam;\n            double lamTo7 = lamTo6 * lam;\n            double lamTo8 = lamTo7 * lam;\n\n            //% auxilary quantity 2\n            double t = phi.Tan();\n\n            // t to powers\n            double tTo2 = t * t;\n            double tTo4 = tTo2 * tTo2;\n            double tTo6 = tTo2 * tTo4;\n\n            // nu^2 to powers\n            double nuTo4 = nuTo2 * nuTo2;\n            //double nuqTo22 = nuq.Pow(22);\n\n            //% x-coord: breite\n            double x1 = t / 2.0 * N * cosphiTo2 * lamTo2;\n            double x2 = t / 24.0 * N * cosphiTo4 * (5.0 - tTo2 + 9.0 * nuTo2 + 4.0 * nuTo4) * lamTo4;\n            double x3 = t / 720.0 * N * cosphiTo6 * (61.0 - 58.0 * tTo2 + tTo4 + 270.0 * nuTo2 - 330.0 * tTo2 * nuTo4) * lamTo6;\n            double x4 = t / 403204.0 * N * cosphiTo8 * (1385.0 - 3111.0 * tTo2 + 543.0 * tTo4 - tTo6) * lamTo8;\n\n            double nX = B + x1 + x2 + x3 + x4;\n            nX = nX - 5000000; // <-- im model \n\n            // y-coord: laenge\n            double y1 = N * cosphi * lam;\n            double y2 = N / 6.0 * cosphiTo3 * (1.0 - tTo2 + nuTo2) * lamTo3;\n            double y3 = N / 120.0 * cosphiTo5 * (5.0 - 18.0 * tTo2 + tTo4 + 14 * nuTo2 - 58.0 * tTo2 * nuTo2) * lamTo5;\n            double y4 = N / 5040.0 * cosphiTo7 * (61.0 - 479.0 * tTo2 + 179.0 * tTo4 - tTo6) * lamTo7;\n\n            double nY = y1 + y2 + y3 + y4;\n            //%nY = nY + 500000+L0/3*1000000; %<-- potsdam datum\n            return new V3d(nY, nX, lonLatHeight.Z); //<-- Laenge, Breite, Hoehe\n        }\n\n        public static V3d GaussKruegerPlaneToEllipsoid(\n            V3d rightHeightAlt, GeoEllipsoid ellipsoid, double referenceMeridan\n            )\n        {\n            double a = ellipsoid.A;\n            double b = ellipsoid.B;\n\n            double Y = rightHeightAlt.X;\n            double X = rightHeightAlt.Y + 5000000;\n\n            double n = (a - b) / (a + b);\n            double nTo2 = n * n;\n            double nTo3 = nTo2 * n;\n            double nTo4 = nTo3 * n;\n            double nTo5 = nTo4 * n;\n\n            double c1 = (a + b) / 2.0 * (1.0 + 1.0 / 4.0 * nTo2 * 1.0 / 64.0 * nTo4);\n            double c2 = 3.0 / 2.0 * n - 27.0 / 32.0 * nTo3 - 269.0 / 512.0 * nTo5;\n            double c3 = 21.0 / 16.0 * nTo2 - 55.0 / 32 * nTo4;\n            double c4 = 151.0 / 96.0 * nTo3 - 417.0 / 128.0 * nTo5;\n            double c5 = 1097.0 / 512.0 * nTo4;\n\n            double c0 = X / c1;\n\n            //latitude footprint in radians\n            double fPHI = c0 + c2 * (2.0 * c0).Sin() + c3 * (4.0 * c0).Sin() + c4 * (6.0 * c0).Sin() + c5 * (8.0 * c0).Sin();\n\n            //% second nummerical eccentrencity\n            double e2q = ellipsoid.E2Q;\n\n            //% auxilary quantity 1\n            double cosfPHI = fPHI.Cos();\n            double nuTo2 = e2q * cosfPHI * cosfPHI;\n            double nuTo4 = nuTo2 * nuTo2;\n\n            //%radius of the curvature in prime vertical\n            double N = (a * a) / (b * (1.0 + nuTo2).Sqrt());\n\n            double Nto2 = N * N;\n            double Nto3 = Nto2 * N;\n            double Nto4 = Nto3 * N;\n            double Nto5 = Nto4 * N;\n            double Nto6 = Nto5 * N;\n            double Nto7 = Nto6 * N;\n            double Nto8 = Nto7 * N;\n\n            //% auxilary quantity 2\n            double t = fPHI.Tan();\n\n            // t to powers\n            double tTo2 = t * t;\n            double tTo4 = tTo2 * tTo2;\n            double tTo6 = tTo2 * tTo4;\n\n            double Yto2 = Y * Y;\n            double Yto3 = Yto2 * Y;\n            double Yto4 = Yto3 * Y;\n            double Yto5 = Yto4 * Y;\n            double Yto6 = Yto5 * Y;\n            double Yto7 = Yto6 * Y;\n            double Yto8 = Yto7 * Y;\n\n            double p1 = fPHI + (t / (2.0 * Nto2)) * (-1.0 - nuTo2) * Yto2;\n            double p2 = (t / (24.0 * Nto4)) * (5.0 + 3.0 * tTo2 + 6.0 * nuTo2 - 6 * tTo2 * nuTo2 - 3.0 * nuTo4 - 9.0 * tTo2 * nuTo4) * Yto4;\n            double p3 = (t / (720.0 * Nto6)) * (-61.0 - 90.0 * tTo2 - 45.0 * tTo4 - 107.0 * nuTo2 + 162.0 * tTo2 * nuTo2 + 45.0 * tTo4 * nuTo2) * Yto6;\n            double p4 = (t / (40320.0 * Nto8)) * (1385.0 + 3633.0 * tTo2 + 4045 * tTo4 + 1575 * tTo6) * Yto8;\n\n            double phi = p1 + p2 + p3 + p4;\n\n            double l1 = Y / (cosfPHI * N);\n            double l2 = ((-1.0 - 2.0 * tTo2 - nuTo2) * Yto3) / (6.0 * Nto3 * cosfPHI);\n            double l3 = (5.0 + 28.0 * tTo2 + 24 * tTo4 + 6.0 * nuTo2 + 8.0 * tTo2 * nuTo2) * Yto5 / (120.0 * Nto5 * cosfPHI);\n            double l4 = (-61.0 - 662 * tTo2 - 1320 * tTo4 - 720 * tTo6) * Yto7 / (5040.0 * Nto7 * cosfPHI);\n\n            double lam = l1 + l2 + l3 + l4;\n\n            double lat = Conversion.DegreesFromRadians(phi);\n            double lon = Conversion.DegreesFromRadians(lam) + referenceMeridan;\n            return new V3d(lon, lat, rightHeightAlt.Z);\n        }\n\n        #endregion\n\n        #region Amap conversions\n\n        // amap info for OK50 map\n        // utm zone 33\n        // easting 68500 - 682900 (low = east)\n        // northing 5104320 - 5432000 (low = south)\n        // no pixel offsets\n\n        // 0/65535 ------------------------122880/65535\n        //  |                                    |\n        //  |                                    |\n        //  |                                    |\n        //  |----x/y                             |\n        //  |     |                              |\n        //  |     |                              |\n        //  0/0------------------------------122880/0\n\n        // conversion into pixel coordinates\n        // map size: width 122880 px, height 65535 px\n        // given: utm wgs84 coordinates of zone 33 (important, zone 32 does not work\n        // and needs to be converted into zone 33 first; this is only required for parts\n        // of western austria).\n        // x = (easting - 68500.0) / 5.0\n        // y = (northing - 5104320) / 5.0\n\n        public static V2i OK50PixelCoordinatesFromWgs84(int easting, int northing)\n            => new V2i((easting - 68500) / 5.0, (northing - 5104320) / 5.0);\n\n        public static V2i OK50PixelCoordinatesFromWgs84(V2i wgs84)\n            => OK50PixelCoordinatesFromWgs84(wgs84.X, wgs84.Y);\n\n        public static V2i Wgs84FromOK50PixelCoordinates(V2i pos)\n            => new V2i(pos.X * 5 + 68500, pos.Y * 5 + 5104320);\n\n        #endregion\n\n        #region Distance\n\n        public static double DistanceVincentyWgs84(V2d lonLat0, V2d lonLat1)\n            => DistanceVincenty(lonLat0, lonLat1, GeoEllipsoid.Wgs84);\n\n        /// <summary>\n        /// Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2012\n        /// from: Vincenty inverse formula - T Vincenty, \"Direct and Inverse Solutions of Geodesics on the\n        /// Ellipsoid with application of nested equations\", Survey Review, vol XXII no 176, 1975\n        /// http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf \n        /// Calculates geodetic distance between two points on the WGS 84\n        /// ellipsoid specified by latitude/longitude using  Vincenty\n        /// inverse formula for ellipsoids.\n        /// </summary>\n        public static double DistanceVincenty(\n            V2d lonLat0, V2d lonLat1, GeoEllipsoid ellipsoid)\n        {\n            double a = ellipsoid.A, b = ellipsoid.B, f = ellipsoid.F;\n            double L = (lonLat1.X - lonLat0.X) * RadiansPerDegree;\n            double U1 = Atan((1 - f) * Tan(lonLat0.Y * RadiansPerDegree));\n            double U2 = Atan((1 - f) * Tan(lonLat1.Y * RadiansPerDegree));\n            double sinU1 = Sin(U1), cosU1 = Cos(U1);\n            double sinU2 = Sin(U2), cosU2 = Cos(U2);\n            double lambda = L, lambdaP;\n            int iterLimit = 100;\n            double sinSigma, cosSigma, sigma, cosSqAlpha, cos2SigmaM;\n            do\n            {\n                double sinLambda = Sin(lambda), cosLambda = Cos(lambda);\n                sinSigma = Sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) +\n                    (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)\n                    * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));\n                if (sinSigma == 0) return 0;  // co-incident points\n                cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;\n                sigma = Atan2(sinSigma, cosSigma);\n                double sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;\n                cosSqAlpha = 1 - sinAlpha * sinAlpha;\n                cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;\n                if (double.IsNaN(cos2SigmaM)) cos2SigmaM = 0;  // equatorial line: cosSqAlpha=0 (§6)\n                double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));\n                lambdaP = lambda;\n                lambda = L + (1 - C) * f * sinAlpha *\n                    (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));\n            }\n            while (Abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);\n\n            if (iterLimit == 0) return double.NaN;  // formula failed to converge\n\n            double uSq = cosSqAlpha * (a * a - b * b) / (b * b);\n            double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));\n            double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));\n            double deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -\n                B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));\n            double s = b * A * (sigma - deltaSigma);\n\n            return s;\n        }\n\n        public static double DistanceVincentyWgs84(\n            V2d lonLat0, V2d lonLat1,\n            out double brng0, out double brng1)\n            => DistanceVincenty(lonLat0, lonLat1, GeoEllipsoid.Wgs84, out brng0, out brng1);\n\n        /// <summary>\n        /// Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2012\n        /// from: Vincenty inverse formula - T Vincenty, \"Direct and Inverse Solutions of Geodesics on the\n        /// Ellipsoid with application of nested equations\", Survey Review, vol XXII no 176, 1975\n        /// http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf \n        /// Calculates geodetic distance between two points on the WGS 84\n        /// ellipsoid specified by latitude/longitude using  Vincenty\n        /// inverse formula for ellipsoids.\n        /// </summary>\n        public static double DistanceVincenty(\n            V2d lonLat0, V2d lonLat1, GeoEllipsoid ellipsoid,\n            out double brng0, out double brng1)\n        {\n            double a = ellipsoid.A, b = ellipsoid.B, f = ellipsoid.F;\n            double L = (lonLat1.X - lonLat0.X) * RadiansPerDegree;\n            double U1 = Atan((1 - f) * Tan(lonLat0.Y * RadiansPerDegree));\n            double U2 = Atan((1 - f) * Tan(lonLat1.Y * RadiansPerDegree));\n            double sinU1 = Sin(U1), cosU1 = Cos(U1);\n            double sinU2 = Sin(U2), cosU2 = Cos(U2);\n            double lambda = L, lambdaP;\n            int iterLimit = 100;\n            double sinSigma, cosSigma, sinLambda, cosLambda, sigma, cosSqAlpha, cos2SigmaM;\n            do\n            {\n                sinLambda = Sin(lambda); cosLambda = Cos(lambda);\n                sinSigma = Sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) +\n                    (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)\n                    * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));\n                if (sinSigma == 0)\n                {\n                    brng0 = double.NaN;\n                    brng1 = double.NaN;\n                    return 0;  // co-incident points\n                }\n                cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;\n                sigma = Atan2(sinSigma, cosSigma);\n                var sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;\n                cosSqAlpha = 1 - sinAlpha * sinAlpha;\n                cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;\n                if (double.IsNaN(cos2SigmaM)) cos2SigmaM = 0;  // equatorial line: cosSqAlpha=0 (§6)\n                var C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));\n                lambdaP = lambda;\n                lambda = L + (1 - C) * f * sinAlpha *\n                    (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));\n            }\n            while (Abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);\n\n            if (iterLimit == 0)\n            {\n                brng0 = double.NaN;\n                brng1 = double.NaN;\n                return double.NaN;  // formula failed to converge\n            }\n            var uSq = cosSqAlpha * (a * a - b * b) / (b * b);\n            var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));\n            var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));\n            var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -\n                B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));\n            var s = b * A * (sigma - deltaSigma);\n\n            var fwdAz = Atan2(cosU2 * sinLambda, cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);\n            var revAz = Atan2(cosU1 * sinLambda, -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);\n\n            brng0 = fwdAz * DegreesPerRadian;\n            brng1 = revAz * DegreesPerRadian;\n\n            return s;\n        }\n\n        public static V2d DirectionVincentyWgs84(V2d lonLat, double brng, double dist)\n            => DirectionVincenty(lonLat, brng, dist, GeoEllipsoid.Wgs84, out double finalBrng);\n\n        /// <summary>\n        /// Vincenty Direct Solution of Geodesics on the Ellipsoid (c) Chris Veness 2005-2012\n        /// from: Vincenty direct formula - T Vincenty, \"Direct and Inverse Solutions of Geodesics on the\n        /// Ellipsoid with application of nested equations\", Survey Review, vol XXII no 176, 1975\n        /// http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf \n        /// </summary>\n        public static V2d DirectionVincenty(V2d lonLat, double brng, double dist, GeoEllipsoid gel)\n            => DirectionVincenty(lonLat, brng, dist, gel, out double finalBrng);\n\n        public static V2d DirectionVincentyWgs84(\n            V2d lonLat, double brng, double dist, out double finalBrng)\n            => DirectionVincenty(lonLat, brng, dist, GeoEllipsoid.Wgs84, out finalBrng);\n\n        /// <summary>\n        /// Vincenty Direct Solution of Geodesics on the Ellipsoid (c) Chris Veness 2005-2012\n        /// from: Vincenty direct formula - T Vincenty, \"Direct and Inverse Solutions of Geodesics on the\n        /// Ellipsoid with application of nested equations\", Survey Review, vol XXII no 176, 1975\n        /// http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf \n        /// </summary>\n        public static V2d DirectionVincenty(V2d lonLat, double brng, double dist, GeoEllipsoid gel,\n            out double finalBrng)\n        {\n            double a = gel.A, b = gel.B, f = gel.F;  // WGS-84 ellipsiod\n            var s = dist;\n            var alpha1 = brng * RadiansPerDegree;\n            var sinAlpha1 = Sin(alpha1);\n            var cosAlpha1 = Cos(alpha1);\n\n            var tanU1 = (1 - f) * Tan(lonLat.Y * RadiansPerDegree);\n            double cosU1 = 1 / Sqrt((1 + tanU1 * tanU1)), sinU1 = tanU1 * cosU1;\n            var sigma1 = Atan2(tanU1, cosAlpha1);\n            var sinAlpha = cosU1 * sinAlpha1;\n            var cosSqAlpha = 1 - sinAlpha * sinAlpha;\n            var uSq = cosSqAlpha * (a * a - b * b) / (b * b);\n            var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));\n            var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));\n\n            var sigma = s / (b * A); var sigmaP = 2 * PI;\n            double sinSigma = 0, cosSigma = 0, cos2SigmaM = 0;\n            while (Abs(sigma - sigmaP) > 1e-12)\n            {\n                cos2SigmaM = Cos(2 * sigma1 + sigma);\n                sinSigma = Sin(sigma);\n                cosSigma = Cos(sigma);\n                var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -\n                    B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));\n                sigmaP = sigma;\n                sigma = s / (b * A) + deltaSigma;\n            }\n\n            var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;\n            var lat2 = Atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,\n                (1 - f) * Sqrt(sinAlpha * sinAlpha + tmp * tmp));\n            var lambda = Atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);\n            var C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));\n            var L = lambda - (1 - C) * f * sinAlpha *\n                (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));\n            var lon2 = (lonLat.X * RadiansPerDegree + L + 3 * PI) % (2 * PI) - PI;  // normalise to -180...+180\n\n            var revAz = Atan2(sinAlpha, -tmp);  // final bearing, if required\n\n            finalBrng = revAz * DegreesPerRadian;\n            return new V2d(lon2 * DegreesPerRadian, lat2 * DegreesPerRadian);\n\n        }\n\n        public static double ComputeLength(V2d[] lonLatArray, GeoEllipsoid gel, params int[] indexArray)\n        {\n            var pc = indexArray.Length;\n            var p0 = lonLatArray[indexArray[0]];\n            var d = 0.0;\n            for (int i = 1; i < pc; i++)\n            {\n                var p1 = lonLatArray[indexArray[i]];\n                d += DistanceVincenty(p0, p1, gel);\n                p0 = p1;\n            }\n            return d;\n        }\n\n        public static double ComputeLengthWgs84(V2d[] lonLatArray, params int[] indexArray)\n            => ComputeLength(lonLatArray, GeoEllipsoid.Wgs84, indexArray);\n\n        public static double ComputePerimeter(V2d[] lonLatArray, GeoEllipsoid gel, params int[] indexArray)\n        {\n            var pc = indexArray.Length;\n            var p0 = lonLatArray[indexArray[pc - 1]];\n            var d = 0.0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = lonLatArray[indexArray[i]];\n                d += DistanceVincenty(p0, p1, gel);\n                p0 = p1;\n            }\n            return d;\n        }\n\n        public static double ComputePerimeterWgs84(V2d[] lonLatArray, params int[] indexArray)\n            => ComputePerimeter(lonLatArray, GeoEllipsoid.Wgs84, indexArray);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Algorithms_auto.cs",
    "content": "using Aardvark.Base.Sorting;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    public static partial class GeometryFun\n    {\n        #region Bresenham\n\n        /// <summary>\n        /// Iterates along Bresenham Discrete Line Raster from P0 to P1. \n        /// Yields each integer position V2i.\n        /// </summary>\n        public static IEnumerable<V2i> BresenhamLineIterator(V2i p0, V2i p1)\n        {\n            int x0 = p0.X, y0 = p0.Y, x1 = p1.X, y1 = p1.Y;\n            int dx, dy;\n            int incx, incy;\n            int balance;\n\n            if (x1 >= x0)\n            {\n                dx = x1 - x0;\n                incx = 1;\n            }\n            else\n            {\n                dx = x0 - x1;\n                incx = -1;\n            }\n\n            if (y1 >= y0)\n            {\n                dy = y1 - y0;\n                incy = 1;\n            }\n            else\n            {\n                dy = y0 - y1;\n                incy = -1;\n            }\n\n            if (dx >= dy)\n            {\n                dy <<= 1;\n                balance = dy - dx;\n                dx <<= 1;\n\n                while (x0 != x1)\n                {\n                    yield return new V2i(x0, y0);\n                    if (balance >= 0)\n                    {\n                        y0 += incy;\n                        balance -= dx;\n                    }\n                    balance += dy;\n                    x0 += incx;\n                }\n\n                yield return new V2i(x0, y0);\n            }\n            else\n            {\n                dx <<= 1;\n                balance = dx - dy;\n                dy <<= 1;\n\n                while (y0 != y1)\n                {\n                    yield return new V2i(x0, y0);\n                    if (balance >= 0)\n                    {\n                        x0 += incx;\n                        balance -= dy;\n                    }\n                    balance += dx;\n                    y0 += incy;\n                }\n\n                yield return new V2i(x0, y0);\n            }\n        }\n\n        /// <summary>\n        /// Iterates along Bresenham discrete line raster from p0 to p1. \n        /// Yields each integer position V2l.\n        /// </summary>\n        public static IEnumerable<V2l> BresenhamLineIterator(V2l p0, V2l p1)\n        {\n            long x0 = p0.X, y0 = p0.Y, x1 = p1.X, y1 = p1.Y;\n            long dx, dy;\n            long incx, incy;\n            long balance;\n\n            if (x1 >= x0)\n            {\n                dx = x1 - x0;\n                incx = 1;\n            }\n            else\n            {\n                dx = x0 - x1;\n                incx = -1;\n            }\n\n            if (y1 >= y0)\n            {\n                dy = y1 - y0;\n                incy = 1;\n            }\n            else\n            {\n                dy = y0 - y1;\n                incy = -1;\n            }\n\n            if (dx >= dy)\n            {\n                dy <<= 1;\n                balance = dy - dx;\n                dx <<= 1;\n\n                while (x0 != x1)\n                {\n                    yield return new V2l(x0, y0);\n                    if (balance >= 0)\n                    {\n                        y0 += incy;\n                        balance -= dx;\n                    }\n                    balance += dy;\n                    x0 += incx;\n                }\n\n                yield return new V2l(x0, y0);\n            }\n            else\n            {\n                dx <<= 1;\n                balance = dx - dy;\n                dy <<= 1;\n\n                while (y0 != y1)\n                {\n                    yield return new V2l(x0, y0);\n                    if (balance >= 0)\n                    {\n                        x0 += incx;\n                        balance -= dy;\n                    }\n                    balance += dx;\n                    y0 += incy;\n                }\n\n                yield return new V2l(x0, y0);\n            }\n        }\n\n        #endregion\n\n        #region Convex Hull in 2D (float)\n\n        /// <summary>\n        /// Returns those indices of the supplied index array to the supplied\n        /// points set that constitute the convex hull. The returned indices\n        /// enumerate the convex hull in counter-clockwise fashion.\n        /// Implemented via Andrew's monotone chain 2d convex hull algorithm.\n        /// </summary>\n        public static IndexPolygon2f ConvexHullIndexPolygon(\n                this int[] indexArray, V2f[] pointArray)\n        {\n            var sortedIndex = indexArray.Copy();\n            sortedIndex.PermutationQuickSort(pointArray, Vec.LexicalCompare);\n            return ConvexHullIndexPolygonOfSortedIndexArray(sortedIndex, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the indices of the points of the supplied point set that\n        /// constitute the convex hull. The returned indices enumerate the\n        /// convex hull in counter-clockwise fashion. Implemented via Andrew's\n        /// monotone chain 2d convex hull algorithm.\n        /// </summary>\n        public static IndexPolygon2f ConvexHullIndexPolygon(this V2f[] pointArray, int pointCount = 0)\n        {\n            if (pointCount == 0) pointCount = pointArray.Length;\n            var sortedIndex = new int[pointCount].SetByIndex(i => i);\n            sortedIndex.PermutationQuickSort(pointArray, Vec.LexicalCompare);\n            return ConvexHullIndexPolygonOfSortedIndexArray(sortedIndex, pointArray);\n        }\n\n        private static IndexPolygon2f ConvexHullIndexPolygonOfSortedIndexArray(int[] idx, V2f[] p)\n        {\n            // Copyright 2001, softSurfer (www.softsurfer.com)\n            // This code may be freely used and modified for any purpose\n            // providing that this copyright notice is included with it.\n            // SoftSurfer makes no warranty for this code, and cannot be held\n            // liable for any real or imagined damage resulting from its use.\n            // Users of this code must verify correctness for their application.\n\n            int n = idx.Length;\n            var hull = new int[n + 1];\n            // the output array hull[] will be used as the stack\n            int bot = 0, top = -1;  // indices for bottom and top of the stack\n            int i;                // array scan index\n\n            // Get the indices of points with min x-coord and min|max y-coord\n            int minmin = 0, minmax;\n            float xmin = p[idx[0]].X;\n            for (i = 1; i < n; i++)\n                if (p[idx[i]].X != xmin) break;\n            minmax = i - 1;\n            if (minmax == n - 1)\n            {       // degenerate case: all x-coords == xmin\n                hull[++top] = idx[minmin];\n                if (p[idx[minmax]].Y != p[idx[minmin]].Y) // a nontrivial segment\n                    hull[++top] = idx[minmax];\n                return new IndexPolygon2f(hull, 0, top + 1, p);\n            }\n\n            // get the indices of points with max x-coord and min|max y-coord\n            int maxmin, maxmax = n - 1;\n            float xmax = p[idx[maxmax]].X;\n            for (i = n - 2; i >= 0; i--)\n                if (p[idx[i]].X != xmax) break;\n            maxmin = i + 1;\n\n            // compute the lower hull on the stack hull\n            hull[++top] = idx[minmin]; // push minmin point onto stack\n            i = minmax;\n            var pimaxmin = p[idx[maxmin]];\n            var phtop = p[hull[top]];\n            while (++i <= maxmin)\n            {\n                int ii = idx[i]; var pii = p[ii];\n                // ignore points above or on line p[idx[minmin], p[idx[maxmin]]\n                if (pii.PosLeftOfLineValue(phtop, pimaxmin) >= 0 && i < maxmin) continue;\n                while (top > 0)         // at least 2 points on the stack\n                {\n                    // test if p[ii] is left of the line at the stack top\n                    if (pii.PosLeftOfLineValue(p[hull[top - 1]], p[hull[top]]) > 0)\n                        break;          // p[ii] is a new hull vertex\n                    top--;              // pop top point off stack\n                }\n                hull[++top] = ii;       // push p[ii] onto stack\n                phtop = pii;\n            }\n\n            // compute the upper hull on the stack hull above the bottom hull\n            if (maxmax != maxmin)      // if distinct xmax points\n                hull[++top] = idx[maxmax]; // push maxmax point onto stack\n            bot = top;                  // the bottom point of the upper hull stack\n            i = maxmin;\n            var piminmax = p[idx[minmax]];\n            phtop = p[hull[top]];\n            while (--i >= minmax)\n            {\n                int ii = idx[i]; var pii = p[ii];\n                // ignore points below the line p[idx[maxmax]], p[idx[minmax]]\n                if (pii.PosLeftOfLineValue(phtop, piminmax) >= 0 && i > minmax) continue;\n                while (top > bot)       // at least 2 points on the upper stack\n                {\n                    // test if p[ii] is left of the line at the stack top\n                    if (pii.PosLeftOfLineValue(p[hull[top - 1]], p[hull[top]]) > 0)\n                        break;          // p[ii] is a new hull vertex\n                    top--;              // pop top point off stack\n                }\n                hull[++top] = ii;       // push p[ii] onto stack\n                phtop = pii;\n            }\n            if (minmax != minmin)\n                ++top;\n\n            return new IndexPolygon2f(hull, 0, top, p);\n        }\n\n        #endregion\n\n        #region Ramer–Douglas–Peucker (float)\n\n        /// <summary>\n        /// Returns those indices of the supplied polyline that constitute\n        /// the simplified polyline. A larger epsilon results in a simpler polyline.\n        /// Implemented via the Ramer–Douglas–Peucker algorithm.\n        /// http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm\n        /// </summary>\n        public static int[] Simplify(this V2f[] polyline, float epsilon)\n        {\n            return Simplify(polyline, epsilon, 0, polyline.Length - 1);\n        }\n\n        private static int[] Simplify(V2f[] polyline, float eps, int indexFirst, int indexLast)\n        {\n            if (indexFirst == indexLast - 1) return new[] { indexFirst, indexLast };\n\n            var pFirst = polyline[indexFirst]; var pLast = polyline[indexLast];\n            var line = new Line2f(pFirst, pLast);\n\n            float distMax = 0; var indexMax = 0;\n            for (var i = indexFirst + 1; i < indexLast; i++)\n            {\n                var d = line.GetDistanceToLine(polyline[i]);\n                if (d > distMax) { distMax = d; indexMax = i; }\n            }\n\n            if (distMax < eps) return new[] { indexFirst, indexLast };\n\n            var left = Simplify(polyline, eps, indexFirst, indexMax);\n            var right = Simplify(polyline, eps, indexMax, indexLast);\n\n            var result = new int[left.Length + right.Length - 1];\n            left.CopyTo(result, 0);\n            right.CopyTo(1, right.Length - 1, result, left.Length);\n            return result;\n        }\n\n        #endregion\n\n        #region Delaunay Triangulation O(n^2/3) (float)\n\n        /// <summary>\n        /// Compute the Delaunay triangulation of the supplied x-sorted point\n        /// array in the XY-plane and return a triangle index array with\n        /// counter-clockwise triangles.\n        /// </summary>\n        public static int[] TriangulateXY(this V3f[] xSortedPoints)\n        {\n            int vc = xSortedPoints.Length;\n            V2f[] pxy = new V2f[vc + 4].SetByIndexLong(0, vc, i => xSortedPoints[i].XY);\n            return Triangulate2d(pxy);\n        }\n\n        /// <summary>\n        /// Compute the Delaunay triangulation of the supplied x-sorted point\n        /// array and return a triangle index array with counter-clockwise\n        /// triangles.\n        /// </summary>\n        public static int[] Triangulate(this V2f[] xSortedPoints)\n        {\n            int vc = xSortedPoints.Length;\n            V2f[] pxy = new V2f[vc + 4].SetByIndexLong(0, vc, i => xSortedPoints[i]);\n            return Triangulate2d(pxy);\n        }\n\n        /// <summary>\n        /// Internal wrapper around the Delaunay triangulation that constructs\n        /// the triangle index array.\n        /// </summary>\n        private static int[] Triangulate2d(V2f[] pa)\n        {\n            Triangulate2d(pa, out Triangle1i[] tri, out int tc);\n            var ia = new int[3 * tc];\n            for (int ti = 0, i = 0; ti < tc; ti++)\n            {\n                var tr = tri[ti];\n                ia[i++] = tr.I0; ia[i++] = tr.I1; ia[i++] = tr.I2;\n            }\n            return ia;\n        }\n\n        /// <summary>\n        /// Compute the Delaunay triangluation of the supplied points. Note that\n        /// the supplied point array must be by 3 larger than the actual number of\n        /// points.\n        /// </summary>\n        private static void Triangulate2d(V2f[] pa,\n            out Triangle1i[] ta, out int triangleCount)\n        {\n            int vc = pa.Length - 4;\n            int tcMax = 2 * vc + 2; // sharp upper bound with no degenerates\n            int ecMax = 6 * vc - 3; // sharp bound: last step replaces all tris\n\n            ta = new Triangle1i[tcMax];\n            var ra = new float[tcMax];\n            var ca = new V2f[tcMax];\n            var ea = new Line1i[ecMax];\n\n            // -------------------------------------- set up the supertriangle\n            ta[0] = new Triangle1i(vc, vc + 2, vc + 1);\n            ra[0] = -1;\n            ta[1] = new Triangle1i(vc, vc + 3, vc + 2);\n            ra[1] = -1;\n            int tc = 2, cc = 0; // triangle count, complete count\n\n            // ------------- superquad vertices at the end of vertex array\n            var box = new Box2f(pa.Take(vc)).EnlargedBy(0.1f);\n            V2f center = box.Center, size = box.Size;\n            pa[vc + 0] = box.Min;\n            pa[vc + 1] = new V2f(box.Min.X, box.Max.Y);\n            pa[vc + 2] = box.Max;\n            pa[vc + 3] = new V2f(box.Max.X, box.Min.Y); \n\n            // ------------------------------ include the points one at a time\n            for (int i = 0; i < vc; i++)\n            {\n                V2f p = pa[i];\n                int ec = 0;\n                /*\n                   if the point lies inside the circumcircle then the triangle\n                   is removed and its edges are added to the edge array\n                */\n                for (int ti = cc; ti < tc; ti++)\n                {\n                    var tr = ta[ti];\n                    float r2 = ra[ti];\n                    if (r2 < 0)\n                    {\n                        Triangle2f.ComputeCircumCircleSquared(\n                                pa[tr.I0], pa[tr.I1], pa[tr.I2],\n                                out center, out r2);\n                        ra[ti] = r2; ca[ti] = center;\n                    }\n                    else\n                        center = ca[ti];\n\n                    // ---------------- include this if points are sorted by X\n                    if (center.X < p.X && (p.X - center.X).Square() > r2)\n                    {\n                        Fun.Swap(ref ta[ti], ref ta[cc]);\n                        ra[ti] = ra[cc]; ca[ti] = ca[cc];\n                        ++cc; continue;\n                    }\n                    if (Vec.DistanceSquared(p, center) <= r2)\n                    {\n                        int nec = ec + 3;\n                        if (nec >= ecMax)\n                        {\n                            ecMax = Fun.Max(nec, (int)(1.1f * (float)ecMax));\n                            Array.Resize(ref ea, ecMax);\n                        }\n                        ea[ec] = tr.Line01; ea[ec + 1] = tr.Line12; ea[ec + 2] = tr.Line20;\n                        --tc; ec = nec;\n                        ta[ti] = ta[tc]; ra[ti] = ra[tc]; ca[ti] = ca[tc];\n                        --ti;\n                    }\n                }\n\n                // ---------------------------------------- tag multiple edges\n                for (int ei = 0; ei < ec - 1; ei++)\n                    for (int ej = ei + 1; ej < ec; ej++)\n                        if (ea[ei].I0 == ea[ej].I1 && ea[ei].I1 == ea[ej].I0)\n                        {\n                            ea[ei] = Line1i.Invalid; ea[ej] = Line1i.Invalid;\n                        }\n\n                // ------------------ form new triangles for the current point\n                for (int ei = 0; ei < ec; ei++)\n                {\n                    var e = ea[ei];\n                    if (e.I0 < 0 || e.I1 < 0) continue; // skip tagged edges\n                    if (tc >= tcMax) // necessary for degenerate cases\n                    {\n                        tcMax = Fun.Max(tcMax + 1, (int)(1.1 * (float)tcMax));\n                        Array.Resize(ref ta, tcMax);\n                        Array.Resize(ref ra, tcMax);\n                        Array.Resize(ref ca, tcMax);\n                    }\n                    ta[tc] = new Triangle1i(e.I0, e.I1, i);\n                    ra[tc++] = -1;\n                }\n            }\n\n            // ------------------ remove triangles with supertriangle vertices\n            for (int ti = 0; ti < tc; ti++)\n                if (ta[ti].I0 >= vc || ta[ti].I1 >= vc || ta[ti].I2 >= vc)\n                    ta[ti--] = ta[--tc];\n\n            triangleCount = tc;\n        }\n\n        #endregion\n\n        #region Box containing Percentile of points (float)\n\n        /// <summary>\n        /// Compute a box containing approximately the supplied percentile\n        /// of points, by performing a separate sorting operation on each\n        /// coordinate.\n        /// </summary>\n        public static Box3f ComputeBoxContaining(\n                this IEnumerable<V3f> points, float percentile)\n        {\n            if (percentile < 0 || percentile > 1) throw new ArgumentOutOfRangeException();\n            var pa = points.ToArray();\n            long offset = (long)(pa.Length * percentile) / 2;\n            long mid = pa.Length / 2;\n            long lo = mid - offset, hi = mid + offset;\n\n            var xa = pa.Map(v => v.X); xa.QuickSortAscending();\n            var ya = pa.Map(v => v.Y); ya.QuickSortAscending();\n            var za = pa.Map(v => v.Z); za.QuickSortAscending();\n\n            return new Box3f(new V3f(xa[lo], ya[lo], za[lo]),\n                             new V3f(xa[hi], ya[hi], za[hi]));\n        }\n\n        #endregion\n\n        #region Convex Hull in 2D (double)\n\n        /// <summary>\n        /// Returns those indices of the supplied index array to the supplied\n        /// points set that constitute the convex hull. The returned indices\n        /// enumerate the convex hull in counter-clockwise fashion.\n        /// Implemented via Andrew's monotone chain 2d convex hull algorithm.\n        /// </summary>\n        public static IndexPolygon2d ConvexHullIndexPolygon(\n                this int[] indexArray, V2d[] pointArray)\n        {\n            var sortedIndex = indexArray.Copy();\n            sortedIndex.PermutationQuickSort(pointArray, Vec.LexicalCompare);\n            return ConvexHullIndexPolygonOfSortedIndexArray(sortedIndex, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the indices of the points of the supplied point set that\n        /// constitute the convex hull. The returned indices enumerate the\n        /// convex hull in counter-clockwise fashion. Implemented via Andrew's\n        /// monotone chain 2d convex hull algorithm.\n        /// </summary>\n        public static IndexPolygon2d ConvexHullIndexPolygon(this V2d[] pointArray, int pointCount = 0)\n        {\n            if (pointCount == 0) pointCount = pointArray.Length;\n            var sortedIndex = new int[pointCount].SetByIndex(i => i);\n            sortedIndex.PermutationQuickSort(pointArray, Vec.LexicalCompare);\n            return ConvexHullIndexPolygonOfSortedIndexArray(sortedIndex, pointArray);\n        }\n\n        private static IndexPolygon2d ConvexHullIndexPolygonOfSortedIndexArray(int[] idx, V2d[] p)\n        {\n            // Copyright 2001, softSurfer (www.softsurfer.com)\n            // This code may be freely used and modified for any purpose\n            // providing that this copyright notice is included with it.\n            // SoftSurfer makes no warranty for this code, and cannot be held\n            // liable for any real or imagined damage resulting from its use.\n            // Users of this code must verify correctness for their application.\n\n            int n = idx.Length;\n            var hull = new int[n + 1];\n            // the output array hull[] will be used as the stack\n            int bot = 0, top = -1;  // indices for bottom and top of the stack\n            int i;                // array scan index\n\n            // Get the indices of points with min x-coord and min|max y-coord\n            int minmin = 0, minmax;\n            double xmin = p[idx[0]].X;\n            for (i = 1; i < n; i++)\n                if (p[idx[i]].X != xmin) break;\n            minmax = i - 1;\n            if (minmax == n - 1)\n            {       // degenerate case: all x-coords == xmin\n                hull[++top] = idx[minmin];\n                if (p[idx[minmax]].Y != p[idx[minmin]].Y) // a nontrivial segment\n                    hull[++top] = idx[minmax];\n                return new IndexPolygon2d(hull, 0, top + 1, p);\n            }\n\n            // get the indices of points with max x-coord and min|max y-coord\n            int maxmin, maxmax = n - 1;\n            double xmax = p[idx[maxmax]].X;\n            for (i = n - 2; i >= 0; i--)\n                if (p[idx[i]].X != xmax) break;\n            maxmin = i + 1;\n\n            // compute the lower hull on the stack hull\n            hull[++top] = idx[minmin]; // push minmin point onto stack\n            i = minmax;\n            var pimaxmin = p[idx[maxmin]];\n            var phtop = p[hull[top]];\n            while (++i <= maxmin)\n            {\n                int ii = idx[i]; var pii = p[ii];\n                // ignore points above or on line p[idx[minmin], p[idx[maxmin]]\n                if (pii.PosLeftOfLineValue(phtop, pimaxmin) >= 0 && i < maxmin) continue;\n                while (top > 0)         // at least 2 points on the stack\n                {\n                    // test if p[ii] is left of the line at the stack top\n                    if (pii.PosLeftOfLineValue(p[hull[top - 1]], p[hull[top]]) > 0)\n                        break;          // p[ii] is a new hull vertex\n                    top--;              // pop top point off stack\n                }\n                hull[++top] = ii;       // push p[ii] onto stack\n                phtop = pii;\n            }\n\n            // compute the upper hull on the stack hull above the bottom hull\n            if (maxmax != maxmin)      // if distinct xmax points\n                hull[++top] = idx[maxmax]; // push maxmax point onto stack\n            bot = top;                  // the bottom point of the upper hull stack\n            i = maxmin;\n            var piminmax = p[idx[minmax]];\n            phtop = p[hull[top]];\n            while (--i >= minmax)\n            {\n                int ii = idx[i]; var pii = p[ii];\n                // ignore points below the line p[idx[maxmax]], p[idx[minmax]]\n                if (pii.PosLeftOfLineValue(phtop, piminmax) >= 0 && i > minmax) continue;\n                while (top > bot)       // at least 2 points on the upper stack\n                {\n                    // test if p[ii] is left of the line at the stack top\n                    if (pii.PosLeftOfLineValue(p[hull[top - 1]], p[hull[top]]) > 0)\n                        break;          // p[ii] is a new hull vertex\n                    top--;              // pop top point off stack\n                }\n                hull[++top] = ii;       // push p[ii] onto stack\n                phtop = pii;\n            }\n            if (minmax != minmin)\n                ++top;\n\n            return new IndexPolygon2d(hull, 0, top, p);\n        }\n\n        #endregion\n\n        #region Ramer–Douglas–Peucker (double)\n\n        /// <summary>\n        /// Returns those indices of the supplied polyline that constitute\n        /// the simplified polyline. A larger epsilon results in a simpler polyline.\n        /// Implemented via the Ramer–Douglas–Peucker algorithm.\n        /// http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm\n        /// </summary>\n        public static int[] Simplify(this V2d[] polyline, double epsilon)\n        {\n            return Simplify(polyline, epsilon, 0, polyline.Length - 1);\n        }\n\n        private static int[] Simplify(V2d[] polyline, double eps, int indexFirst, int indexLast)\n        {\n            if (indexFirst == indexLast - 1) return new[] { indexFirst, indexLast };\n\n            var pFirst = polyline[indexFirst]; var pLast = polyline[indexLast];\n            var line = new Line2d(pFirst, pLast);\n\n            double distMax = 0; var indexMax = 0;\n            for (var i = indexFirst + 1; i < indexLast; i++)\n            {\n                var d = line.GetDistanceToLine(polyline[i]);\n                if (d > distMax) { distMax = d; indexMax = i; }\n            }\n\n            if (distMax < eps) return new[] { indexFirst, indexLast };\n\n            var left = Simplify(polyline, eps, indexFirst, indexMax);\n            var right = Simplify(polyline, eps, indexMax, indexLast);\n\n            var result = new int[left.Length + right.Length - 1];\n            left.CopyTo(result, 0);\n            right.CopyTo(1, right.Length - 1, result, left.Length);\n            return result;\n        }\n\n        #endregion\n\n        #region Delaunay Triangulation O(n^2/3) (double)\n\n        /// <summary>\n        /// Compute the Delaunay triangulation of the supplied x-sorted point\n        /// array in the XY-plane and return a triangle index array with\n        /// counter-clockwise triangles.\n        /// </summary>\n        public static int[] TriangulateXY(this V3d[] xSortedPoints)\n        {\n            int vc = xSortedPoints.Length;\n            V2d[] pxy = new V2d[vc + 4].SetByIndexLong(0, vc, i => xSortedPoints[i].XY);\n            return Triangulate2d(pxy);\n        }\n\n        /// <summary>\n        /// Compute the Delaunay triangulation of the supplied x-sorted point\n        /// array and return a triangle index array with counter-clockwise\n        /// triangles.\n        /// </summary>\n        public static int[] Triangulate(this V2d[] xSortedPoints)\n        {\n            int vc = xSortedPoints.Length;\n            V2d[] pxy = new V2d[vc + 4].SetByIndexLong(0, vc, i => xSortedPoints[i]);\n            return Triangulate2d(pxy);\n        }\n\n        /// <summary>\n        /// Internal wrapper around the Delaunay triangulation that constructs\n        /// the triangle index array.\n        /// </summary>\n        private static int[] Triangulate2d(V2d[] pa)\n        {\n            Triangulate2d(pa, out Triangle1i[] tri, out int tc);\n            var ia = new int[3 * tc];\n            for (int ti = 0, i = 0; ti < tc; ti++)\n            {\n                var tr = tri[ti];\n                ia[i++] = tr.I0; ia[i++] = tr.I1; ia[i++] = tr.I2;\n            }\n            return ia;\n        }\n\n        /// <summary>\n        /// Compute the Delaunay triangluation of the supplied points. Note that\n        /// the supplied point array must be by 3 larger than the actual number of\n        /// points.\n        /// </summary>\n        private static void Triangulate2d(V2d[] pa,\n            out Triangle1i[] ta, out int triangleCount)\n        {\n            int vc = pa.Length - 4;\n            int tcMax = 2 * vc + 2; // sharp upper bound with no degenerates\n            int ecMax = 6 * vc - 3; // sharp bound: last step replaces all tris\n\n            ta = new Triangle1i[tcMax];\n            var ra = new double[tcMax];\n            var ca = new V2d[tcMax];\n            var ea = new Line1i[ecMax];\n\n            // -------------------------------------- set up the supertriangle\n            ta[0] = new Triangle1i(vc, vc + 2, vc + 1);\n            ra[0] = -1;\n            ta[1] = new Triangle1i(vc, vc + 3, vc + 2);\n            ra[1] = -1;\n            int tc = 2, cc = 0; // triangle count, complete count\n\n            // ------------- superquad vertices at the end of vertex array\n            var box = new Box2d(pa.Take(vc)).EnlargedBy(0.1);\n            V2d center = box.Center, size = box.Size;\n            pa[vc + 0] = box.Min;\n            pa[vc + 1] = new V2d(box.Min.X, box.Max.Y);\n            pa[vc + 2] = box.Max;\n            pa[vc + 3] = new V2d(box.Max.X, box.Min.Y); \n\n            // ------------------------------ include the points one at a time\n            for (int i = 0; i < vc; i++)\n            {\n                V2d p = pa[i];\n                int ec = 0;\n                /*\n                   if the point lies inside the circumcircle then the triangle\n                   is removed and its edges are added to the edge array\n                */\n                for (int ti = cc; ti < tc; ti++)\n                {\n                    var tr = ta[ti];\n                    double r2 = ra[ti];\n                    if (r2 < 0)\n                    {\n                        Triangle2d.ComputeCircumCircleSquared(\n                                pa[tr.I0], pa[tr.I1], pa[tr.I2],\n                                out center, out r2);\n                        ra[ti] = r2; ca[ti] = center;\n                    }\n                    else\n                        center = ca[ti];\n\n                    // ---------------- include this if points are sorted by X\n                    if (center.X < p.X && (p.X - center.X).Square() > r2)\n                    {\n                        Fun.Swap(ref ta[ti], ref ta[cc]);\n                        ra[ti] = ra[cc]; ca[ti] = ca[cc];\n                        ++cc; continue;\n                    }\n                    if (Vec.DistanceSquared(p, center) <= r2)\n                    {\n                        int nec = ec + 3;\n                        if (nec >= ecMax)\n                        {\n                            ecMax = Fun.Max(nec, (int)(1.1 * (double)ecMax));\n                            Array.Resize(ref ea, ecMax);\n                        }\n                        ea[ec] = tr.Line01; ea[ec + 1] = tr.Line12; ea[ec + 2] = tr.Line20;\n                        --tc; ec = nec;\n                        ta[ti] = ta[tc]; ra[ti] = ra[tc]; ca[ti] = ca[tc];\n                        --ti;\n                    }\n                }\n\n                // ---------------------------------------- tag multiple edges\n                for (int ei = 0; ei < ec - 1; ei++)\n                    for (int ej = ei + 1; ej < ec; ej++)\n                        if (ea[ei].I0 == ea[ej].I1 && ea[ei].I1 == ea[ej].I0)\n                        {\n                            ea[ei] = Line1i.Invalid; ea[ej] = Line1i.Invalid;\n                        }\n\n                // ------------------ form new triangles for the current point\n                for (int ei = 0; ei < ec; ei++)\n                {\n                    var e = ea[ei];\n                    if (e.I0 < 0 || e.I1 < 0) continue; // skip tagged edges\n                    if (tc >= tcMax) // necessary for degenerate cases\n                    {\n                        tcMax = Fun.Max(tcMax + 1, (int)(1.1 * (double)tcMax));\n                        Array.Resize(ref ta, tcMax);\n                        Array.Resize(ref ra, tcMax);\n                        Array.Resize(ref ca, tcMax);\n                    }\n                    ta[tc] = new Triangle1i(e.I0, e.I1, i);\n                    ra[tc++] = -1;\n                }\n            }\n\n            // ------------------ remove triangles with supertriangle vertices\n            for (int ti = 0; ti < tc; ti++)\n                if (ta[ti].I0 >= vc || ta[ti].I1 >= vc || ta[ti].I2 >= vc)\n                    ta[ti--] = ta[--tc];\n\n            triangleCount = tc;\n        }\n\n        #endregion\n\n        #region Box containing Percentile of points (double)\n\n        /// <summary>\n        /// Compute a box containing approximately the supplied percentile\n        /// of points, by performing a separate sorting operation on each\n        /// coordinate.\n        /// </summary>\n        public static Box3d ComputeBoxContaining(\n                this IEnumerable<V3d> points, double percentile)\n        {\n            if (percentile < 0 || percentile > 1) throw new ArgumentOutOfRangeException();\n            var pa = points.ToArray();\n            long offset = (long)(pa.Length * percentile) / 2;\n            long mid = pa.Length / 2;\n            long lo = mid - offset, hi = mid + offset;\n\n            var xa = pa.Map(v => v.X); xa.QuickSortAscending();\n            var ya = pa.Map(v => v.Y); ya.QuickSortAscending();\n            var za = pa.Map(v => v.Z); za.QuickSortAscending();\n\n            return new Box3d(new V3d(xa[lo], ya[lo], za[lo]),\n                             new V3d(xa[hi], ya[hi], za[hi]));\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Algorithms_template.cs",
    "content": "﻿using Aardvark.Base.Sorting;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    public static partial class GeometryFun\n    {\n        #region Bresenham\n\n        /// <summary>\n        /// Iterates along Bresenham Discrete Line Raster from P0 to P1. \n        /// Yields each integer position V2i.\n        /// </summary>\n        public static IEnumerable<V2i> BresenhamLineIterator(V2i p0, V2i p1)\n        {\n            int x0 = p0.X, y0 = p0.Y, x1 = p1.X, y1 = p1.Y;\n            int dx, dy;\n            int incx, incy;\n            int balance;\n\n            if (x1 >= x0)\n            {\n                dx = x1 - x0;\n                incx = 1;\n            }\n            else\n            {\n                dx = x0 - x1;\n                incx = -1;\n            }\n\n            if (y1 >= y0)\n            {\n                dy = y1 - y0;\n                incy = 1;\n            }\n            else\n            {\n                dy = y0 - y1;\n                incy = -1;\n            }\n\n            if (dx >= dy)\n            {\n                dy <<= 1;\n                balance = dy - dx;\n                dx <<= 1;\n\n                while (x0 != x1)\n                {\n                    yield return new V2i(x0, y0);\n                    if (balance >= 0)\n                    {\n                        y0 += incy;\n                        balance -= dx;\n                    }\n                    balance += dy;\n                    x0 += incx;\n                }\n\n                yield return new V2i(x0, y0);\n            }\n            else\n            {\n                dx <<= 1;\n                balance = dx - dy;\n                dy <<= 1;\n\n                while (y0 != y1)\n                {\n                    yield return new V2i(x0, y0);\n                    if (balance >= 0)\n                    {\n                        x0 += incx;\n                        balance -= dy;\n                    }\n                    balance += dx;\n                    y0 += incy;\n                }\n\n                yield return new V2i(x0, y0);\n            }\n        }\n\n        /// <summary>\n        /// Iterates along Bresenham discrete line raster from p0 to p1. \n        /// Yields each integer position V2l.\n        /// </summary>\n        public static IEnumerable<V2l> BresenhamLineIterator(V2l p0, V2l p1)\n        {\n            long x0 = p0.X, y0 = p0.Y, x1 = p1.X, y1 = p1.Y;\n            long dx, dy;\n            long incx, incy;\n            long balance;\n\n            if (x1 >= x0)\n            {\n                dx = x1 - x0;\n                incx = 1;\n            }\n            else\n            {\n                dx = x0 - x1;\n                incx = -1;\n            }\n\n            if (y1 >= y0)\n            {\n                dy = y1 - y0;\n                incy = 1;\n            }\n            else\n            {\n                dy = y0 - y1;\n                incy = -1;\n            }\n\n            if (dx >= dy)\n            {\n                dy <<= 1;\n                balance = dy - dx;\n                dx <<= 1;\n\n                while (x0 != x1)\n                {\n                    yield return new V2l(x0, y0);\n                    if (balance >= 0)\n                    {\n                        y0 += incy;\n                        balance -= dx;\n                    }\n                    balance += dy;\n                    x0 += incx;\n                }\n\n                yield return new V2l(x0, y0);\n            }\n            else\n            {\n                dx <<= 1;\n                balance = dx - dy;\n                dy <<= 1;\n\n                while (y0 != y1)\n                {\n                    yield return new V2l(x0, y0);\n                    if (balance >= 0)\n                    {\n                        x0 += incx;\n                        balance -= dy;\n                    }\n                    balance += dx;\n                    y0 += incy;\n                }\n\n                yield return new V2l(x0, y0);\n            }\n        }\n\n        #endregion\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var box2t = \"Box2\" + tc;\n        //#   var line2t = \"Line2\" + tc;\n        //#   var box3t = \"Box3\" + tc;\n        //#   var triangle2t = \"Triangle2\" + tc;\n        //#   var zerodotone = isDouble ? \"0.1\" : \"0.1f\";\n        //#   var onedotone = isDouble ? \"1.1\" : \"1.1f\";\n        //#   var ipolygon2t = \"IndexPolygon2\" + tc;\n        #region Convex Hull in 2D (__rtype__)\n\n        /// <summary>\n        /// Returns those indices of the supplied index array to the supplied\n        /// points set that constitute the convex hull. The returned indices\n        /// enumerate the convex hull in counter-clockwise fashion.\n        /// Implemented via Andrew's monotone chain 2d convex hull algorithm.\n        /// </summary>\n        public static __ipolygon2t__ ConvexHullIndexPolygon(\n                this int[] indexArray, __v2t__[] pointArray)\n        {\n            var sortedIndex = indexArray.Copy();\n            sortedIndex.PermutationQuickSort(pointArray, Vec.LexicalCompare);\n            return ConvexHullIndexPolygonOfSortedIndexArray(sortedIndex, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the indices of the points of the supplied point set that\n        /// constitute the convex hull. The returned indices enumerate the\n        /// convex hull in counter-clockwise fashion. Implemented via Andrew's\n        /// monotone chain 2d convex hull algorithm.\n        /// </summary>\n        public static __ipolygon2t__ ConvexHullIndexPolygon(this __v2t__[] pointArray, int pointCount = 0)\n        {\n            if (pointCount == 0) pointCount = pointArray.Length;\n            var sortedIndex = new int[pointCount].SetByIndex(i => i);\n            sortedIndex.PermutationQuickSort(pointArray, Vec.LexicalCompare);\n            return ConvexHullIndexPolygonOfSortedIndexArray(sortedIndex, pointArray);\n        }\n\n        private static __ipolygon2t__ ConvexHullIndexPolygonOfSortedIndexArray(int[] idx, __v2t__[] p)\n        {\n            // Copyright 2001, softSurfer (www.softsurfer.com)\n            // This code may be freely used and modified for any purpose\n            // providing that this copyright notice is included with it.\n            // SoftSurfer makes no warranty for this code, and cannot be held\n            // liable for any real or imagined damage resulting from its use.\n            // Users of this code must verify correctness for their application.\n\n            int n = idx.Length;\n            var hull = new int[n + 1];\n            // the output array hull[] will be used as the stack\n            int bot = 0, top = -1;  // indices for bottom and top of the stack\n            int i;                // array scan index\n\n            // Get the indices of points with min x-coord and min|max y-coord\n            int minmin = 0, minmax;\n            __rtype__ xmin = p[idx[0]].X;\n            for (i = 1; i < n; i++)\n                if (p[idx[i]].X != xmin) break;\n            minmax = i - 1;\n            if (minmax == n - 1)\n            {       // degenerate case: all x-coords == xmin\n                hull[++top] = idx[minmin];\n                if (p[idx[minmax]].Y != p[idx[minmin]].Y) // a nontrivial segment\n                    hull[++top] = idx[minmax];\n                return new __ipolygon2t__(hull, 0, top + 1, p);\n            }\n\n            // get the indices of points with max x-coord and min|max y-coord\n            int maxmin, maxmax = n - 1;\n            __rtype__ xmax = p[idx[maxmax]].X;\n            for (i = n - 2; i >= 0; i--)\n                if (p[idx[i]].X != xmax) break;\n            maxmin = i + 1;\n\n            // compute the lower hull on the stack hull\n            hull[++top] = idx[minmin]; // push minmin point onto stack\n            i = minmax;\n            var pimaxmin = p[idx[maxmin]];\n            var phtop = p[hull[top]];\n            while (++i <= maxmin)\n            {\n                int ii = idx[i]; var pii = p[ii];\n                // ignore points above or on line p[idx[minmin], p[idx[maxmin]]\n                if (pii.PosLeftOfLineValue(phtop, pimaxmin) >= 0 && i < maxmin) continue;\n                while (top > 0)         // at least 2 points on the stack\n                {\n                    // test if p[ii] is left of the line at the stack top\n                    if (pii.PosLeftOfLineValue(p[hull[top - 1]], p[hull[top]]) > 0)\n                        break;          // p[ii] is a new hull vertex\n                    top--;              // pop top point off stack\n                }\n                hull[++top] = ii;       // push p[ii] onto stack\n                phtop = pii;\n            }\n\n            // compute the upper hull on the stack hull above the bottom hull\n            if (maxmax != maxmin)      // if distinct xmax points\n                hull[++top] = idx[maxmax]; // push maxmax point onto stack\n            bot = top;                  // the bottom point of the upper hull stack\n            i = maxmin;\n            var piminmax = p[idx[minmax]];\n            phtop = p[hull[top]];\n            while (--i >= minmax)\n            {\n                int ii = idx[i]; var pii = p[ii];\n                // ignore points below the line p[idx[maxmax]], p[idx[minmax]]\n                if (pii.PosLeftOfLineValue(phtop, piminmax) >= 0 && i > minmax) continue;\n                while (top > bot)       // at least 2 points on the upper stack\n                {\n                    // test if p[ii] is left of the line at the stack top\n                    if (pii.PosLeftOfLineValue(p[hull[top - 1]], p[hull[top]]) > 0)\n                        break;          // p[ii] is a new hull vertex\n                    top--;              // pop top point off stack\n                }\n                hull[++top] = ii;       // push p[ii] onto stack\n                phtop = pii;\n            }\n            if (minmax != minmin)\n                ++top;\n\n            return new __ipolygon2t__(hull, 0, top, p);\n        }\n\n        #endregion\n\n        #region Ramer–Douglas–Peucker (__rtype__)\n\n        /// <summary>\n        /// Returns those indices of the supplied polyline that constitute\n        /// the simplified polyline. A larger epsilon results in a simpler polyline.\n        /// Implemented via the Ramer–Douglas–Peucker algorithm.\n        /// http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm\n        /// </summary>\n        public static int[] Simplify(this __v2t__[] polyline, __rtype__ epsilon)\n        {\n            return Simplify(polyline, epsilon, 0, polyline.Length - 1);\n        }\n\n        private static int[] Simplify(__v2t__[] polyline, __rtype__ eps, int indexFirst, int indexLast)\n        {\n            if (indexFirst == indexLast - 1) return new[] { indexFirst, indexLast };\n\n            var pFirst = polyline[indexFirst]; var pLast = polyline[indexLast];\n            var line = new __line2t__(pFirst, pLast);\n\n            __rtype__ distMax = 0; var indexMax = 0;\n            for (var i = indexFirst + 1; i < indexLast; i++)\n            {\n                var d = line.GetDistanceToLine(polyline[i]);\n                if (d > distMax) { distMax = d; indexMax = i; }\n            }\n\n            if (distMax < eps) return new[] { indexFirst, indexLast };\n\n            var left = Simplify(polyline, eps, indexFirst, indexMax);\n            var right = Simplify(polyline, eps, indexMax, indexLast);\n\n            var result = new int[left.Length + right.Length - 1];\n            left.CopyTo(result, 0);\n            right.CopyTo(1, right.Length - 1, result, left.Length);\n            return result;\n        }\n\n        #endregion\n\n        #region Delaunay Triangulation O(n^2/3) (__rtype__)\n\n        /// <summary>\n        /// Compute the Delaunay triangulation of the supplied x-sorted point\n        /// array in the XY-plane and return a triangle index array with\n        /// counter-clockwise triangles.\n        /// </summary>\n        public static int[] TriangulateXY(this __v3t__[] xSortedPoints)\n        {\n            int vc = xSortedPoints.Length;\n            __v2t__[] pxy = new __v2t__[vc + 4].SetByIndexLong(0, vc, i => xSortedPoints[i].XY);\n            return Triangulate2d(pxy);\n        }\n\n        /// <summary>\n        /// Compute the Delaunay triangulation of the supplied x-sorted point\n        /// array and return a triangle index array with counter-clockwise\n        /// triangles.\n        /// </summary>\n        public static int[] Triangulate(this __v2t__[] xSortedPoints)\n        {\n            int vc = xSortedPoints.Length;\n            __v2t__[] pxy = new __v2t__[vc + 4].SetByIndexLong(0, vc, i => xSortedPoints[i]);\n            return Triangulate2d(pxy);\n        }\n\n        /// <summary>\n        /// Internal wrapper around the Delaunay triangulation that constructs\n        /// the triangle index array.\n        /// </summary>\n        private static int[] Triangulate2d(__v2t__[] pa)\n        {\n            Triangulate2d(pa, out Triangle1i[] tri, out int tc);\n            var ia = new int[3 * tc];\n            for (int ti = 0, i = 0; ti < tc; ti++)\n            {\n                var tr = tri[ti];\n                ia[i++] = tr.I0; ia[i++] = tr.I1; ia[i++] = tr.I2;\n            }\n            return ia;\n        }\n\n        /// <summary>\n        /// Compute the Delaunay triangluation of the supplied points. Note that\n        /// the supplied point array must be by 3 larger than the actual number of\n        /// points.\n        /// </summary>\n        private static void Triangulate2d(__v2t__[] pa,\n            out Triangle1i[] ta, out int triangleCount)\n        {\n            int vc = pa.Length - 4;\n            int tcMax = 2 * vc + 2; // sharp upper bound with no degenerates\n            int ecMax = 6 * vc - 3; // sharp bound: last step replaces all tris\n\n            ta = new Triangle1i[tcMax];\n            var ra = new __rtype__[tcMax];\n            var ca = new __v2t__[tcMax];\n            var ea = new Line1i[ecMax];\n\n            // -------------------------------------- set up the supertriangle\n            ta[0] = new Triangle1i(vc, vc + 2, vc + 1);\n            ra[0] = -1;\n            ta[1] = new Triangle1i(vc, vc + 3, vc + 2);\n            ra[1] = -1;\n            int tc = 2, cc = 0; // triangle count, complete count\n\n            // ------------- superquad vertices at the end of vertex array\n            var box = new __box2t__(pa.Take(vc)).EnlargedBy(__zerodotone__);\n            __v2t__ center = box.Center, size = box.Size;\n            pa[vc + 0] = box.Min;\n            pa[vc + 1] = new __v2t__(box.Min.X, box.Max.Y);\n            pa[vc + 2] = box.Max;\n            pa[vc + 3] = new __v2t__(box.Max.X, box.Min.Y); \n\n            // ------------------------------ include the points one at a time\n            for (int i = 0; i < vc; i++)\n            {\n                __v2t__ p = pa[i];\n                int ec = 0;\n                /*\n                   if the point lies inside the circumcircle then the triangle\n                   is removed and its edges are added to the edge array\n                */\n                for (int ti = cc; ti < tc; ti++)\n                {\n                    var tr = ta[ti];\n                    __rtype__ r2 = ra[ti];\n                    if (r2 < 0)\n                    {\n                        __triangle2t__.ComputeCircumCircleSquared(\n                                pa[tr.I0], pa[tr.I1], pa[tr.I2],\n                                out center, out r2);\n                        ra[ti] = r2; ca[ti] = center;\n                    }\n                    else\n                        center = ca[ti];\n\n                    // ---------------- include this if points are sorted by X\n                    if (center.X < p.X && (p.X - center.X).Square() > r2)\n                    {\n                        Fun.Swap(ref ta[ti], ref ta[cc]);\n                        ra[ti] = ra[cc]; ca[ti] = ca[cc];\n                        ++cc; continue;\n                    }\n                    if (Vec.DistanceSquared(p, center) <= r2)\n                    {\n                        int nec = ec + 3;\n                        if (nec >= ecMax)\n                        {\n                            ecMax = Fun.Max(nec, (int)(__onedotone__ * (__rtype__)ecMax));\n                            Array.Resize(ref ea, ecMax);\n                        }\n                        ea[ec] = tr.Line01; ea[ec + 1] = tr.Line12; ea[ec + 2] = tr.Line20;\n                        --tc; ec = nec;\n                        ta[ti] = ta[tc]; ra[ti] = ra[tc]; ca[ti] = ca[tc];\n                        --ti;\n                    }\n                }\n\n                // ---------------------------------------- tag multiple edges\n                for (int ei = 0; ei < ec - 1; ei++)\n                    for (int ej = ei + 1; ej < ec; ej++)\n                        if (ea[ei].I0 == ea[ej].I1 && ea[ei].I1 == ea[ej].I0)\n                        {\n                            ea[ei] = Line1i.Invalid; ea[ej] = Line1i.Invalid;\n                        }\n\n                // ------------------ form new triangles for the current point\n                for (int ei = 0; ei < ec; ei++)\n                {\n                    var e = ea[ei];\n                    if (e.I0 < 0 || e.I1 < 0) continue; // skip tagged edges\n                    if (tc >= tcMax) // necessary for degenerate cases\n                    {\n                        tcMax = Fun.Max(tcMax + 1, (int)(1.1 * (__rtype__)tcMax));\n                        Array.Resize(ref ta, tcMax);\n                        Array.Resize(ref ra, tcMax);\n                        Array.Resize(ref ca, tcMax);\n                    }\n                    ta[tc] = new Triangle1i(e.I0, e.I1, i);\n                    ra[tc++] = -1;\n                }\n            }\n\n            // ------------------ remove triangles with supertriangle vertices\n            for (int ti = 0; ti < tc; ti++)\n                if (ta[ti].I0 >= vc || ta[ti].I1 >= vc || ta[ti].I2 >= vc)\n                    ta[ti--] = ta[--tc];\n\n            triangleCount = tc;\n        }\n\n        #endregion\n\n        #region Box containing Percentile of points (__rtype__)\n\n        /// <summary>\n        /// Compute a box containing approximately the supplied percentile\n        /// of points, by performing a separate sorting operation on each\n        /// coordinate.\n        /// </summary>\n        public static __box3t__ ComputeBoxContaining(\n                this IEnumerable<__v3t__> points, __rtype__ percentile)\n        {\n            if (percentile < 0 || percentile > 1) throw new ArgumentOutOfRangeException();\n            var pa = points.ToArray();\n            long offset = (long)(pa.Length * percentile) / 2;\n            long mid = pa.Length / 2;\n            long lo = mid - offset, hi = mid + offset;\n\n            var xa = pa.Map(v => v.X); xa.QuickSortAscending();\n            var ya = pa.Map(v => v.Y); ya.QuickSortAscending();\n            var za = pa.Map(v => v.Z); za.QuickSortAscending();\n\n            return new __box3t__(new __v3t__(xa[lo], ya[lo], za[lo]),\n                             new __v3t__(xa[hi], ya[hi], za[hi]));\n        }\n\n        #endregion\n\n        //# }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/BbTree.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing Aardvark.Base.Sorting;\n\nnamespace Aardvark.Base\n{\n    public struct BbTreeHit\n    {\n        public int NodeIndex;\n        public double RayT;\n        \n        public BbTreeHit(int nodeIndex, double rayT)\n        {\n            NodeIndex = nodeIndex;\n            RayT = rayT;\n        }\n    }\n    \n    \n    public class BbTree\n    {\n        private int m_nodeCount;\n        private Box3d m_box;\n        private int[] m_indexArray;\n        private int[] m_leafArray;\n        private Box3d[] m_boxes;\n\n        private Box3dAndFlags[] m_combinedBoxArray;\n        public Box3d[] m_leftBoxArray;\n        public Box3d[] m_rightBoxArray;\n\n        [Flags]\n        public enum BuildFlags\n        {\n            None,\n            CreateBoxArrays = 0x01,\n            CreateCombinedArray = 0x02,\n\n            LeafLimit01         = 0x010,\n            LeafLimit04         = 0x040,\n            LeafLimit08         = 0x080,\n            LeafLimit16         = 0x100,\n            LeafLimitMask       = 0xff0,\n\n            Default = CreateBoxArrays | LeafLimit01\n        }\n\n        #region Constructor\n\n        public BbTree(Box3d[] boundingBoxes, BuildFlags buildFlags = BuildFlags.Default,\n                      int[] countArray = null)\n        {\n            var count = boundingBoxes.Length;\n            m_combinedBoxArray = null;\n            m_leftBoxArray = null;\n            m_rightBoxArray = null;\n\n            Report.BeginTimed(c_reportVerbosity, \"building bb-tree [{0}]\", count);\n            if (count > 1)\n            {\n                m_boxes = boundingBoxes;\n                m_nodeCount = count - 1;\n                var createParams = new InParams\n                {\n                    LeafLimit = Fun.Max(1, (int)(buildFlags & BuildFlags.LeafLimitMask) >> 4),\n                    LeafCount = 0,\n                    BuildFlags = buildFlags,\n                    NodeCount = 0,\n                    BbArray = boundingBoxes,\n                    CountArray = countArray,\n                };\n                if (createParams.LeafLimit > 1)\n                    m_leafArray = new int[2 * count];\n\n                m_indexArray = new int[2 * m_nodeCount];\n                if ((buildFlags & BuildFlags.CreateCombinedArray) != 0)\n                    m_combinedBoxArray = new Box3dAndFlags[m_nodeCount];\n                if ((buildFlags & BuildFlags.CreateBoxArrays) != 0)\n                {\n                    m_leftBoxArray = new Box3d[m_nodeCount];\n                    m_rightBoxArray = new Box3d[m_nodeCount];\n                }\n                m_box = new Box3d(createParams.BbArray);\n\n                Create(createParams, new int[count].SetByIndex(i => i), 0, count, m_box);\n                if (createParams.LeafLimit > 1)\n                    m_leafArray = m_leafArray.Copy(createParams.LeafCount);\n            }\n            else\n            {\n                m_nodeCount = 0;\n                m_box = count > 0 ? new Box3d(boundingBoxes) : Box3d.Invalid;\n            }\n            Report.End(c_reportVerbosity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public int[] IndexArray { get { return m_indexArray; } }\n        public int[] LeafArray { get { return m_leafArray; } }\n        public int NodeCount { get { return m_nodeCount; } }\n        public Box3d Box3d { get { return m_box; } }\n        public Box3d[] Boxes { get { return m_boxes; } }\n        public Box3d[] LeftBoxArray { get { return m_leftBoxArray; } }\n        public Box3d[] RightBoxArray { get { return m_rightBoxArray; } }\n\n        public int GetLeft(int i) { return m_indexArray[i * 2]; }\n        public int GetRight(int i) { return m_indexArray[i * 2 + 1]; }\n\n        #endregion\n\n        #region Constants\n\n        private const double c_splitPenalty = 1.0; // 2.0 still OK, but gets slow beyond that\n        private const int c_reportVerbosity = 2;\n\n        #endregion\n\n        #region Construction\n\n        private class InParams\n        {\n            public BuildFlags BuildFlags;\n            public int NodeCount;\n            public int LeafLimit;\n            public Box3d[] BbArray;\n            public int[] CountArray;\n            public int LeafCount;\n        }\n\n        private int CalculateSplit(\n                InParams inParams,\n                int[] indexArray,\n                int start,\n                int count,\n                Box3d box,\n                out int[] sortedIndexArray,\n                out Box3d leftBox,\n                out Box3d rightBox)\n        {\n            int bestLeft = 0;\n            var bestCost = double.MaxValue;\n            var bestLeftBox = Box3d.Invalid;\n            var bestRightBox = Box3d.Invalid;\n            var bestDim = -1;\n            double invBoxArea = box.SurfaceArea > Constant<double>.PositiveTinyValue\n                                    ? 1.0 / box.SurfaceArea : 0.0;\n\n            var iaa = new int[3][].SetByIndex(i => indexArray.Copy(start, count));\n\n            for (int d = 0; d < 3; d++)\n            {\n                var ia = iaa[d];\n                ia.PermutationQuickSortAscending(inParams.BbArray, (ba, i) => ba[i].Center[d]);\n\n                var bbLeftArray = ia.ScanLeft(Box3d.Invalid, (b, i) => new Box3d(b, inParams.BbArray[i]));\n                var bbRightArray = ia.ScanRight((i, b) => new Box3d(inParams.BbArray[i], b), Box3d.Invalid);\n\n                long[] cLeftArray = null, cRightArray = null;\n                if (inParams.CountArray != null)\n                {\n                    cLeftArray = ia.ScanLeft(0L, (c, i) => c + inParams.CountArray[i]);\n                    cRightArray = ia.ScanRight((i, c) => inParams.CountArray[i] + c, 0L);\n                }\n                for (int s = 1; s < count; s++)\n                {\n                    var lBox = bbLeftArray[s-1]; var leftP = lBox.SurfaceArea * invBoxArea;\n                    var rBox = bbRightArray[s]; var rightP = rBox.SurfaceArea * invBoxArea;\n                    long lCount = cLeftArray != null ? cLeftArray[s - 1] : s;\n                    long rCount = cRightArray != null ? cRightArray[s] : count - s;\n\n                    var cBox = Box.Intersection(lBox, rBox);\n                    var cSize = new V3d(cBox.Max.X > cBox.Min.X ? cBox.Max.X - cBox.Min.X : 0,\n                                        cBox.Max.Y > cBox.Min.Y ? cBox.Max.Y - cBox.Min.Y : 0,\n                                        cBox.Max.Z > cBox.Min.Z ? cBox.Max.Z - cBox.Min.Z : 0);\n                    var commonP = 2 * (cSize.X * cSize.Y + cSize.X * cSize.Z + cSize.Y * cSize.Z)\n                                    * invBoxArea;\n\n                    var cost = (leftP + (commonP * c_splitPenalty)) * (1 + lCount)\n                              + (rightP + (commonP * c_splitPenalty)) * (1 + rCount);\n\n                    if (cost < bestCost)\n                    {\n                        bestCost = cost; bestDim = d; bestLeft = s;\n                        bestLeftBox = lBox;  bestRightBox = rBox;\n                    }\n                }\n            }\n            sortedIndexArray = iaa[bestDim];\n            leftBox = bestLeftBox;\n            rightBox = bestRightBox;\n            return bestLeft;\n        }\n\n        private int CreateLeaf(InParams inParams, int[] indices, int signedCount)\n        {\n            var index = inParams.LeafCount;\n            if (signedCount > 0)\n            {\n                m_leafArray[index++] = signedCount;\n                indices.CopyTo(m_leafArray, index);\n                inParams.LeafCount = index + signedCount;\n            }\n            else\n            {\n                m_leafArray[index++] = -signedCount;\n                indices.CopyTo(indices.Length + signedCount, -signedCount, m_leafArray, index);\n                inParams.LeafCount = index - signedCount;\n            }\n            return -index;\n        }\n\n        private int Create(InParams inParams, int[] indices, int start, int count, Box3d box)\n        {\n            int ni = inParams.NodeCount++;\n            int[] sortedIndices;\n            Box3d leftBox, rightBox;\n            var leftCount = CalculateSplit(inParams, indices, start, count, box,\n                                           out sortedIndices, out leftBox, out rightBox);\n            var rightCount = count - leftCount;\n\n            m_indexArray[2 * ni] = leftCount > inParams.LeafLimit\n                ? Create(inParams, sortedIndices, 0, leftCount, leftBox)\n                : m_leafArray == null ? -1 - sortedIndices[0] : CreateLeaf(inParams, sortedIndices, leftCount);\n            m_indexArray[2 * ni + 1] = rightCount > inParams.LeafLimit\n                ? Create(inParams, sortedIndices, leftCount, rightCount, rightBox)\n                : m_leafArray == null ? -1 - sortedIndices[count - 1] : CreateLeaf(inParams, sortedIndices, -rightCount);\n\n            if ((inParams.BuildFlags & BuildFlags.CreateBoxArrays) != 0)\n            {\n                m_leftBoxArray[ni] = leftBox;\n                m_rightBoxArray[ni] = rightBox;\n            }\n            if ((inParams.BuildFlags & BuildFlags.CreateCombinedArray) != 0)\n                m_combinedBoxArray[ni] = new Box3dAndFlags(box, leftBox, rightBox);\n            return ni;\n        }\n\n        #endregion\n\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/ClippingFunctions_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static partial class GeometryFun\n    {\n        #region Helpers (float)\n\n        public static bool ClosestIntersection(this Polygon2f poly, V2f start, V2f end, out bool enter, out int otherIndex, out V2f p)\n        {\n            float min = float.MaxValue;\n\n            bool intersects = false;\n\n            V2f point = V2f.NaN;\n\n            bool tempenter = false;\n            int tempindex = -1;\n            V2f temppoint = V2f.NaN;\n            float templength = float.MaxValue;\n\n            Line2f line = new Line2f(start, end);\n\n            int i = 0;\n            foreach (var l in poly.EdgeLines)\n            {\n                if (line.Intersects(l, 4 * float.Epsilon, out temppoint))\n                {\n                    templength = (temppoint - line.P0).Length;\n                    if (templength < min)\n                    {\n                        tempenter = l.LeftValueOfDir(line.Direction) >= 0;\n                        tempindex = i;\n                        min = templength;\n                        point = temppoint;\n                    }\n\n                    intersects = true;\n                }\n                i++;\n            }\n\n            enter = tempenter;\n            otherIndex = tempindex;\n            p = point;\n            return intersects;\n        }\n\n        internal static float Closest(this List<V2f> points, V2f p)\n        {\n            float temp;\n            float min = float.MaxValue;\n            for (int i = 0; i < points.Count; i++)\n            {\n                temp = (p - points[i]).Length;\n                if (temp < min) min = temp;\n            }\n\n            return min;\n        }\n\n        internal static bool Intersects(V2f[] poly, V2f p0, V2f p1, ref List<V2f> known, out bool enter, out int index0, out V2f p)\n        {\n            int index = 0;\n\n            Line2f l;\n            int i0 = 0;\n            int i1 = 1;\n            for (int i = 1; i <= poly.Length; i++)\n            {\n                if (i < poly.Length)\n                {\n                    i0 = i - 1;\n                    i1 = i;\n                }\n                else\n                {\n                    i0 = poly.Length - 1;\n                    i1 = 0;\n                }\n\n                l = new Line2f(poly[i0], poly[i1]);\n                if (l.Intersects(new Line2f(p0, p1), 4 *float.Epsilon, out p))\n                {\n                    if (!Fun.IsTiny(known.Closest(p)))\n                    {\n                        enter = (l.LeftValueOfPos(p1) >= -4 *float.Epsilon);\n                        index0 = index;\n\n                        return true;\n                    }\n                }\n\n                index++;\n            }\n\n            p = V2f.NaN;\n            index0 = -1;\n            enter = false;\n            return false;\n        }\n\n        internal static IEnumerable<V2f> AllVertices(Polygon2f poly)\n        {\n            int pc = poly.PointCount;\n            for (int pi = 0; pi < pc; pi++) yield return poly[pi];\n            yield return poly[0];\n        }\n\n        #endregion\n\n        #region Intersections (float)\n\n        #region Line2f - Polygon2f\n\n        /// <summary>\n        /// Returns the Line-Segments of line inside the Polygon (CCW ordered).\n        /// Works with all (convex and non-convex) Polygons\n        /// </summary>\n        public static IEnumerable<Line2f> ClipWith(this Line2f line, Polygon2f poly)\n        {\n            bool i0, i1;\n\n            i0 = poly.Contains(line.P0);\n            i1 = poly.Contains(line.P1);\n\n            var resulting = new List<V2f>();\n            var enter = new List<bool>();\n\n            if (i0)\n            {\n                resulting.Add(line.P0);\n                enter.Add(true);\n            }\n            if (i1)\n            {\n                resulting.Add(line.P1);\n                enter.Add(false);\n            }\n\n            var p = V2f.NaN;\n            var direction = line.Direction;\n\n            foreach (var l in poly.EdgeLines)\n            {\n                if (line.Intersects(l, out p))\n                {\n                    var d = l.Direction;\n                    var n = new V2f(-d.Y, d.X);\n\n                    if (!p.IsNaN)\n                    {\n                        bool addflag = true;\n                        bool flag = direction.Dot(n) > 0;\n\n                        for (int i = 0; i < resulting.Count; i++)\n                        {\n                            if (Fun.IsTiny((resulting[i] - p).Length))\n                            {\n                                if (flag != enter[i])\n                                {\n                                    resulting.RemoveAt(i);\n                                    enter.RemoveAt(i);\n                                }\n\n                                addflag = false;\n                                break;\n                            }\n                        }\n\n                        if (addflag)\n                        {\n                            resulting.Add(p);\n                            enter.Add(flag);\n                        }\n                    }\n                }\n            }\n\n            var dir = line.P1 - line.P0;\n            resulting = (from r in resulting select r).OrderBy(x => x.Dot(dir)).ToList();\n\n            var counter = resulting.Count;\n            var lines = new List<Line2f>();\n            for (int i = 0; i < counter - 1; i += 2)\n            {\n                lines.Add(new Line2f(resulting[i], resulting[i + 1]));\n            }\n            return lines;\n        }\n\n        /// <summary>\n        /// Returns the Line-Segments of line inside the Polygon (CCW ordered).\n        /// Works only with Convex-Polygons\n        /// If the line is clipped entirely, the points of the returned Line2f are NaN.\n        /// </summary>\n        public static Line2f ClipWithConvex(this Line2f line, Polygon2f poly)\n        {\n            var p = V2f.NaN;\n            bool i0, i1;\n\n            i0 = poly.Contains(line.P0);\n            i1 = poly.Contains(line.P1);\n\n            if (i0 && i1) return line;\n            else if ((!i0 && i1) || (i0 && !i1))\n            {\n                foreach (var l in poly.EdgeLines)\n                {\n                    if (line.Intersects(l, out p)) break;\n                }\n\n                if (i0) return new Line2f(line.P0, p);\n                else return new Line2f(p, line.P1);\n            }\n            else\n            {\n                V2f p0 = V2f.NaN;\n                V2f p1 = V2f.NaN;\n                int c = 0;\n\n                foreach (var l in poly.EdgeLines)\n                {\n                    if (line.Intersects(l, out p))\n                    {\n                        if (c == 0) p0 = p;\n                        else p1 = p;\n                        c++;\n                    }\n                }\n\n                if (c == 2)\n                {\n                    V2f u = p1 - p0;\n\n                    if (u.Dot(line.Direction) > 0) return new Line2f(p0, p1);\n                    else return new Line2f(p1, p0);\n                }\n                else return new Line2f(V2f.NaN, V2f.NaN);\n            }\n        }\n\n        #endregion\n\n        #region Polygon2f - Polygon2f\n\n        /// <summary>\n        /// Clips one Polygon with an other. Returns a Polygon representing the Intersection of the two.\n        /// Works only with Convex Polygons. (For non-convex Polygons use Polygon2f.ClipWith(Polygon2f))\n        /// !!!! UNTESTED !!!!\n        /// </summary>\n        public static Polygon2f ClippedByConvex(this Polygon2f poly, Polygon2f second)\n        {\n            V2f[][] arr = new V2f[2][];\n            arr[0] = AllVertices(poly).ToArray();\n            arr[1] = AllVertices(second).ToArray();\n\n            Polygon2f[] polygon = new Polygon2f[2];\n            polygon[0] = poly;\n            polygon[1] = second;\n\n            bool current = false;\n            int currentIndex = 0;\n            int otherIndex = 1;\n\n            bool enter = false;\n            int index = -1;\n            V2f point = V2f.NaN;\n\n            List<V2f> points = new List<V2f>();\n\n            for (int i = 1; i < arr[currentIndex].Length; i = (i + 1) % arr[currentIndex].Length)\n            {\n                if (i < 1) i = 1;\n                currentIndex = (current ? 1 : 0);\n                otherIndex = (current ? 0 : 1);\n\n                V2f start = arr[currentIndex][i - 1];\n                V2f end = arr[currentIndex][i];\n\n                if (Intersects(arr[otherIndex], start, end, ref points, out enter, out index, out point))\n                {\n                    if (enter)\n                    {\n                        points.Add(point);\n                        int u = i;\n                        int count = 0;\n                        while (polygon[otherIndex].Contains(arr[currentIndex][u]))\n                        {\n                            points.Add(arr[currentIndex][u]);\n                            u = (u + arr[currentIndex].Length - 1) % arr[currentIndex].Length;\n                            count++;\n                        }\n                        if (count == 0) i--;\n                        else\n                        {\n                            i += count - 1;\n                        }\n                    }\n                    else\n                    {\n                        points.Add(point);\n                        i = index;\n                        current = !current;\n                        currentIndex = (current ? 1 : 0);\n                        otherIndex = (current ? 0 : 1);\n                    }\n                }\n                else\n                {\n\n                    if (i < arr[currentIndex].Length && polygon[otherIndex].Contains(arr[currentIndex][i]))\n                    {\n                        if (Closest(points, arr[currentIndex][i]) < 0.001f) break;\n                        points.Add(arr[currentIndex][i]);\n                    }\n                }\n            }\n\n\n            return new Polygon2f(points);\n        }\n\n        /// <summary>\n        /// Clips one Polygon with an other. Returns a Polygon-Set representing the Intersections of the two.\n        /// Works only with all (convex/concave) Polygons\n        /// !!!! UNTESTED !!!!\n        /// </summary>\n        public static IEnumerable<Polygon2f> ClippedBy(this Polygon2f p0, Polygon2f p1, float relativeEpsilon)\n        {\n            List<int[]> i0 = SubPrimitives.ComputeNonConcaveSubPolygons(p0, relativeEpsilon);\n            List<int[]> i1 = SubPrimitives.ComputeNonConcaveSubPolygons(p1, relativeEpsilon);\n\n            List<Polygon2f> polys = new List<Polygon2f>();\n            for (int i = 0; i < i0.Count; i++)\n            {\n                for (int u = 0; u < i1.Count; u++)\n                {\n                    Polygon2f q0 = new Polygon2f(from o in i0[i] select p0[o]);\n                    Polygon2f q1 = new Polygon2f(from o in i1[u] select p1[o]);\n\n                    Polygon2f r = q0.ClippedByConvex(q1);\n                    if (r.PointCount > 0) polys.Add(r);\n                }\n            }\n\n            return Union(polys);\n\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Unions (float)\n\n        #region Polygon2f - Polygon2f\n\n\n        public static IEnumerable<Polygon2f> Union(List<Polygon2f> p)\n        {\n            List<Polygon2f> polys = new List<Polygon2f>();\n            polys.Add(p[0]);\n            List<Polygon2f> temp;\n\n            for (int i = 1; i < p.Count; i++)\n            {\n                bool found = false;\n                for (int u = 0; u < polys.Count; u++)\n                {\n                    temp = polys[u].Union(p[i]).ToList();\n\n                    if (temp.Count == 1)\n                    {\n                        polys[u] = temp[0];\n                        found = true;\n                    }\n                }\n\n                if (!found)\n                {\n                    polys.Add(p[i]);\n                }\n            }\n\n            return polys;\n        }\n\n        /// <summary>\n        /// Returns the unified Polygon of the two given ones.\n        /// Works only with convex-Polygons\n        /// Returns an empty Polygon if the two do not intersect\n        /// </summary>\n        public static IEnumerable<Polygon2f> Union(this Polygon2f p0, Polygon2f p1)\n        {\n            Polygon2f[] arr = new Polygon2f[2];\n            arr[0] = p0;\n            arr[1] = p1;\n\n            int current = 0;\n            int other = 1;\n\n            List<V2f> points = new List<V2f>();\n            bool enter = false;\n            int index = -1;\n            V2f point = V2f.NaN;\n\n            bool firstIntersectionFound = false;\n            V2f firstIntersectionPoint = V2f.NaN;\n\n            for (int i = 0; i >= 0; i = (i + 1) % arr[current].PointCount)\n            {\n                V2f start = arr[current][(i + arr[current].PointCount - 1) % arr[current].PointCount];\n                V2f end = arr[current][i];\n\n                if (arr[other].ClosestIntersection(start, end, out enter, out index, out point))\n                {\n                    if (!firstIntersectionFound)\n                    {\n                        firstIntersectionFound = true;\n                        firstIntersectionPoint = point;\n                    }\n                    else\n                    {\n                        if ((point - firstIntersectionPoint).Length < 0.001f) break;\n                    }\n\n                    if (enter)\n                    {\n                        points.Add(point);\n\n                        while ((arr[other][(index + 1) % arr[other].PointCount] - point).Length < 0.001f) index = (index + 1) % arr[other].PointCount;\n\n                        if (!arr[current].Contains(arr[other][(index + 1) % arr[other].PointCount]))\n                        {\n                            points.Add(arr[other][(index + 1) % arr[other].PointCount]);\n                            index = (index + 1) % arr[other].PointCount;\n                        }\n\n                        i = index;\n                        current = (current == 1 ? 0 : 1);\n                        other = (current == 1 ? 0 : 1);\n                    }\n                    else\n                    {\n                        points.Add(point);\n                        if (!arr[other].Contains(arr[current][i]))\n                        {\n                            points.Add(arr[current][i]);\n                        }\n                    }\n                }\n                else\n                {\n                    if (i == arr[current].PointCount - 1 && !firstIntersectionFound) break;\n\n                    if (!arr[other].Contains(end) && firstIntersectionFound)\n                    {\n                        points.Add(end);\n                    }\n                }\n            }\n\n            if (!firstIntersectionFound)\n            {\n                if (p0.Contains(p1[0])) yield return p0;\n                else if (p1.Contains(p0[0])) yield return p1;\n                else\n                {\n                    yield return p0;\n                    yield return p1;\n                }\n            }\n            else yield return new Polygon2f(points);\n        }\n\n        #endregion\n\n        public static IEnumerable<Polygon2f> Union(this Box2f b0, Box2f b1)\n        {\n            Polygon2f p0 = new Polygon2f(b0.ComputeCornersCCW());\n            Polygon2f p1 = new Polygon2f(b1.ComputeCornersCCW());\n\n            return p0.Union(p1);\n        }\n\n        #endregion\n\n        #region Helpers (double)\n\n        public static bool ClosestIntersection(this Polygon2d poly, V2d start, V2d end, out bool enter, out int otherIndex, out V2d p)\n        {\n            double min = double.MaxValue;\n\n            bool intersects = false;\n\n            V2d point = V2d.NaN;\n\n            bool tempenter = false;\n            int tempindex = -1;\n            V2d temppoint = V2d.NaN;\n            double templength = double.MaxValue;\n\n            Line2d line = new Line2d(start, end);\n\n            int i = 0;\n            foreach (var l in poly.EdgeLines)\n            {\n                if (line.Intersects(l, 4 * double.Epsilon, out temppoint))\n                {\n                    templength = (temppoint - line.P0).Length;\n                    if (templength < min)\n                    {\n                        tempenter = l.LeftValueOfDir(line.Direction) >= 0;\n                        tempindex = i;\n                        min = templength;\n                        point = temppoint;\n                    }\n\n                    intersects = true;\n                }\n                i++;\n            }\n\n            enter = tempenter;\n            otherIndex = tempindex;\n            p = point;\n            return intersects;\n        }\n\n        internal static double Closest(this List<V2d> points, V2d p)\n        {\n            double temp;\n            double min = double.MaxValue;\n            for (int i = 0; i < points.Count; i++)\n            {\n                temp = (p - points[i]).Length;\n                if (temp < min) min = temp;\n            }\n\n            return min;\n        }\n\n        internal static bool Intersects(V2d[] poly, V2d p0, V2d p1, ref List<V2d> known, out bool enter, out int index0, out V2d p)\n        {\n            int index = 0;\n\n            Line2d l;\n            int i0 = 0;\n            int i1 = 1;\n            for (int i = 1; i <= poly.Length; i++)\n            {\n                if (i < poly.Length)\n                {\n                    i0 = i - 1;\n                    i1 = i;\n                }\n                else\n                {\n                    i0 = poly.Length - 1;\n                    i1 = 0;\n                }\n\n                l = new Line2d(poly[i0], poly[i1]);\n                if (l.Intersects(new Line2d(p0, p1), 4 *double.Epsilon, out p))\n                {\n                    if (!Fun.IsTiny(known.Closest(p)))\n                    {\n                        enter = (l.LeftValueOfPos(p1) >= -4 *double.Epsilon);\n                        index0 = index;\n\n                        return true;\n                    }\n                }\n\n                index++;\n            }\n\n            p = V2d.NaN;\n            index0 = -1;\n            enter = false;\n            return false;\n        }\n\n        internal static IEnumerable<V2d> AllVertices(Polygon2d poly)\n        {\n            int pc = poly.PointCount;\n            for (int pi = 0; pi < pc; pi++) yield return poly[pi];\n            yield return poly[0];\n        }\n\n        #endregion\n\n        #region Intersections (double)\n\n        #region Line2d - Polygon2d\n\n        /// <summary>\n        /// Returns the Line-Segments of line inside the Polygon (CCW ordered).\n        /// Works with all (convex and non-convex) Polygons\n        /// </summary>\n        public static IEnumerable<Line2d> ClipWith(this Line2d line, Polygon2d poly)\n        {\n            bool i0, i1;\n\n            i0 = poly.Contains(line.P0);\n            i1 = poly.Contains(line.P1);\n\n            var resulting = new List<V2d>();\n            var enter = new List<bool>();\n\n            if (i0)\n            {\n                resulting.Add(line.P0);\n                enter.Add(true);\n            }\n            if (i1)\n            {\n                resulting.Add(line.P1);\n                enter.Add(false);\n            }\n\n            var p = V2d.NaN;\n            var direction = line.Direction;\n\n            foreach (var l in poly.EdgeLines)\n            {\n                if (line.Intersects(l, out p))\n                {\n                    var d = l.Direction;\n                    var n = new V2d(-d.Y, d.X);\n\n                    if (!p.IsNaN)\n                    {\n                        bool addflag = true;\n                        bool flag = direction.Dot(n) > 0;\n\n                        for (int i = 0; i < resulting.Count; i++)\n                        {\n                            if (Fun.IsTiny((resulting[i] - p).Length))\n                            {\n                                if (flag != enter[i])\n                                {\n                                    resulting.RemoveAt(i);\n                                    enter.RemoveAt(i);\n                                }\n\n                                addflag = false;\n                                break;\n                            }\n                        }\n\n                        if (addflag)\n                        {\n                            resulting.Add(p);\n                            enter.Add(flag);\n                        }\n                    }\n                }\n            }\n\n            var dir = line.P1 - line.P0;\n            resulting = (from r in resulting select r).OrderBy(x => x.Dot(dir)).ToList();\n\n            var counter = resulting.Count;\n            var lines = new List<Line2d>();\n            for (int i = 0; i < counter - 1; i += 2)\n            {\n                lines.Add(new Line2d(resulting[i], resulting[i + 1]));\n            }\n            return lines;\n        }\n\n        /// <summary>\n        /// Returns the Line-Segments of line inside the Polygon (CCW ordered).\n        /// Works only with Convex-Polygons\n        /// If the line is clipped entirely, the points of the returned Line2d are NaN.\n        /// </summary>\n        public static Line2d ClipWithConvex(this Line2d line, Polygon2d poly)\n        {\n            var p = V2d.NaN;\n            bool i0, i1;\n\n            i0 = poly.Contains(line.P0);\n            i1 = poly.Contains(line.P1);\n\n            if (i0 && i1) return line;\n            else if ((!i0 && i1) || (i0 && !i1))\n            {\n                foreach (var l in poly.EdgeLines)\n                {\n                    if (line.Intersects(l, out p)) break;\n                }\n\n                if (i0) return new Line2d(line.P0, p);\n                else return new Line2d(p, line.P1);\n            }\n            else\n            {\n                V2d p0 = V2d.NaN;\n                V2d p1 = V2d.NaN;\n                int c = 0;\n\n                foreach (var l in poly.EdgeLines)\n                {\n                    if (line.Intersects(l, out p))\n                    {\n                        if (c == 0) p0 = p;\n                        else p1 = p;\n                        c++;\n                    }\n                }\n\n                if (c == 2)\n                {\n                    V2d u = p1 - p0;\n\n                    if (u.Dot(line.Direction) > 0) return new Line2d(p0, p1);\n                    else return new Line2d(p1, p0);\n                }\n                else return new Line2d(V2d.NaN, V2d.NaN);\n            }\n        }\n\n        #endregion\n\n        #region Polygon2d - Polygon2d\n\n        /// <summary>\n        /// Clips one Polygon with an other. Returns a Polygon representing the Intersection of the two.\n        /// Works only with Convex Polygons. (For non-convex Polygons use Polygon2d.ClipWith(Polygon2d))\n        /// !!!! UNTESTED !!!!\n        /// </summary>\n        public static Polygon2d ClippedByConvex(this Polygon2d poly, Polygon2d second)\n        {\n            V2d[][] arr = new V2d[2][];\n            arr[0] = AllVertices(poly).ToArray();\n            arr[1] = AllVertices(second).ToArray();\n\n            Polygon2d[] polygon = new Polygon2d[2];\n            polygon[0] = poly;\n            polygon[1] = second;\n\n            bool current = false;\n            int currentIndex = 0;\n            int otherIndex = 1;\n\n            bool enter = false;\n            int index = -1;\n            V2d point = V2d.NaN;\n\n            List<V2d> points = new List<V2d>();\n\n            for (int i = 1; i < arr[currentIndex].Length; i = (i + 1) % arr[currentIndex].Length)\n            {\n                if (i < 1) i = 1;\n                currentIndex = (current ? 1 : 0);\n                otherIndex = (current ? 0 : 1);\n\n                V2d start = arr[currentIndex][i - 1];\n                V2d end = arr[currentIndex][i];\n\n                if (Intersects(arr[otherIndex], start, end, ref points, out enter, out index, out point))\n                {\n                    if (enter)\n                    {\n                        points.Add(point);\n                        int u = i;\n                        int count = 0;\n                        while (polygon[otherIndex].Contains(arr[currentIndex][u]))\n                        {\n                            points.Add(arr[currentIndex][u]);\n                            u = (u + arr[currentIndex].Length - 1) % arr[currentIndex].Length;\n                            count++;\n                        }\n                        if (count == 0) i--;\n                        else\n                        {\n                            i += count - 1;\n                        }\n                    }\n                    else\n                    {\n                        points.Add(point);\n                        i = index;\n                        current = !current;\n                        currentIndex = (current ? 1 : 0);\n                        otherIndex = (current ? 0 : 1);\n                    }\n                }\n                else\n                {\n\n                    if (i < arr[currentIndex].Length && polygon[otherIndex].Contains(arr[currentIndex][i]))\n                    {\n                        if (Closest(points, arr[currentIndex][i]) < 0.001) break;\n                        points.Add(arr[currentIndex][i]);\n                    }\n                }\n            }\n\n\n            return new Polygon2d(points);\n        }\n\n        /// <summary>\n        /// Clips one Polygon with an other. Returns a Polygon-Set representing the Intersections of the two.\n        /// Works only with all (convex/concave) Polygons\n        /// !!!! UNTESTED !!!!\n        /// </summary>\n        public static IEnumerable<Polygon2d> ClippedBy(this Polygon2d p0, Polygon2d p1, double relativeEpsilon)\n        {\n            List<int[]> i0 = SubPrimitives.ComputeNonConcaveSubPolygons(p0, relativeEpsilon);\n            List<int[]> i1 = SubPrimitives.ComputeNonConcaveSubPolygons(p1, relativeEpsilon);\n\n            List<Polygon2d> polys = new List<Polygon2d>();\n            for (int i = 0; i < i0.Count; i++)\n            {\n                for (int u = 0; u < i1.Count; u++)\n                {\n                    Polygon2d q0 = new Polygon2d(from o in i0[i] select p0[o]);\n                    Polygon2d q1 = new Polygon2d(from o in i1[u] select p1[o]);\n\n                    Polygon2d r = q0.ClippedByConvex(q1);\n                    if (r.PointCount > 0) polys.Add(r);\n                }\n            }\n\n            return Union(polys);\n\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Unions (double)\n\n        #region Polygon2d - Polygon2d\n\n\n        public static IEnumerable<Polygon2d> Union(List<Polygon2d> p)\n        {\n            List<Polygon2d> polys = new List<Polygon2d>();\n            polys.Add(p[0]);\n            List<Polygon2d> temp;\n\n            for (int i = 1; i < p.Count; i++)\n            {\n                bool found = false;\n                for (int u = 0; u < polys.Count; u++)\n                {\n                    temp = polys[u].Union(p[i]).ToList();\n\n                    if (temp.Count == 1)\n                    {\n                        polys[u] = temp[0];\n                        found = true;\n                    }\n                }\n\n                if (!found)\n                {\n                    polys.Add(p[i]);\n                }\n            }\n\n            return polys;\n        }\n\n        /// <summary>\n        /// Returns the unified Polygon of the two given ones.\n        /// Works only with convex-Polygons\n        /// Returns an empty Polygon if the two do not intersect\n        /// </summary>\n        public static IEnumerable<Polygon2d> Union(this Polygon2d p0, Polygon2d p1)\n        {\n            Polygon2d[] arr = new Polygon2d[2];\n            arr[0] = p0;\n            arr[1] = p1;\n\n            int current = 0;\n            int other = 1;\n\n            List<V2d> points = new List<V2d>();\n            bool enter = false;\n            int index = -1;\n            V2d point = V2d.NaN;\n\n            bool firstIntersectionFound = false;\n            V2d firstIntersectionPoint = V2d.NaN;\n\n            for (int i = 0; i >= 0; i = (i + 1) % arr[current].PointCount)\n            {\n                V2d start = arr[current][(i + arr[current].PointCount - 1) % arr[current].PointCount];\n                V2d end = arr[current][i];\n\n                if (arr[other].ClosestIntersection(start, end, out enter, out index, out point))\n                {\n                    if (!firstIntersectionFound)\n                    {\n                        firstIntersectionFound = true;\n                        firstIntersectionPoint = point;\n                    }\n                    else\n                    {\n                        if ((point - firstIntersectionPoint).Length < 0.001) break;\n                    }\n\n                    if (enter)\n                    {\n                        points.Add(point);\n\n                        while ((arr[other][(index + 1) % arr[other].PointCount] - point).Length < 0.001) index = (index + 1) % arr[other].PointCount;\n\n                        if (!arr[current].Contains(arr[other][(index + 1) % arr[other].PointCount]))\n                        {\n                            points.Add(arr[other][(index + 1) % arr[other].PointCount]);\n                            index = (index + 1) % arr[other].PointCount;\n                        }\n\n                        i = index;\n                        current = (current == 1 ? 0 : 1);\n                        other = (current == 1 ? 0 : 1);\n                    }\n                    else\n                    {\n                        points.Add(point);\n                        if (!arr[other].Contains(arr[current][i]))\n                        {\n                            points.Add(arr[current][i]);\n                        }\n                    }\n                }\n                else\n                {\n                    if (i == arr[current].PointCount - 1 && !firstIntersectionFound) break;\n\n                    if (!arr[other].Contains(end) && firstIntersectionFound)\n                    {\n                        points.Add(end);\n                    }\n                }\n            }\n\n            if (!firstIntersectionFound)\n            {\n                if (p0.Contains(p1[0])) yield return p0;\n                else if (p1.Contains(p0[0])) yield return p1;\n                else\n                {\n                    yield return p0;\n                    yield return p1;\n                }\n            }\n            else yield return new Polygon2d(points);\n        }\n\n        #endregion\n\n        public static IEnumerable<Polygon2d> Union(this Box2d b0, Box2d b1)\n        {\n            Polygon2d p0 = new Polygon2d(b0.ComputeCornersCCW());\n            Polygon2d p1 = new Polygon2d(b1.ComputeCornersCCW());\n\n            return p0.Union(p1);\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/ClippingFunctions_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static partial class GeometryFun\n    {\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var box2t = \"Box2\" + tc;\n        //#   var line2t = \"Line2\" + tc;\n        //#   var box3t = \"Box3\" + tc;\n        //#   var triangle2t = \"Triangle2\" + tc;\n        //#   var polygon2t = \"Polygon2\" + tc;\n        //#   var eps = isDouble ? \"0.001\" : \"0.001f\";\n        #region Helpers (__rtype__)\n\n        public static bool ClosestIntersection(this __polygon2t__ poly, __v2t__ start, __v2t__ end, out bool enter, out int otherIndex, out __v2t__ p)\n        {\n            __rtype__ min = __rtype__.MaxValue;\n\n            bool intersects = false;\n\n            __v2t__ point = __v2t__.NaN;\n\n            bool tempenter = false;\n            int tempindex = -1;\n            __v2t__ temppoint = __v2t__.NaN;\n            __rtype__ templength = __rtype__.MaxValue;\n\n            __line2t__ line = new __line2t__(start, end);\n\n            int i = 0;\n            foreach (var l in poly.EdgeLines)\n            {\n                if (line.Intersects(l, 4 * __rtype__.Epsilon, out temppoint))\n                {\n                    templength = (temppoint - line.P0).Length;\n                    if (templength < min)\n                    {\n                        tempenter = l.LeftValueOfDir(line.Direction) >= 0;\n                        tempindex = i;\n                        min = templength;\n                        point = temppoint;\n                    }\n\n                    intersects = true;\n                }\n                i++;\n            }\n\n            enter = tempenter;\n            otherIndex = tempindex;\n            p = point;\n            return intersects;\n        }\n\n        internal static __rtype__ Closest(this List<__v2t__> points, __v2t__ p)\n        {\n            __rtype__ temp;\n            __rtype__ min = __rtype__.MaxValue;\n            for (int i = 0; i < points.Count; i++)\n            {\n                temp = (p - points[i]).Length;\n                if (temp < min) min = temp;\n            }\n\n            return min;\n        }\n\n        internal static bool Intersects(__v2t__[] poly, __v2t__ p0, __v2t__ p1, ref List<__v2t__> known, out bool enter, out int index0, out __v2t__ p)\n        {\n            int index = 0;\n\n            __line2t__ l;\n            int i0 = 0;\n            int i1 = 1;\n            for (int i = 1; i <= poly.Length; i++)\n            {\n                if (i < poly.Length)\n                {\n                    i0 = i - 1;\n                    i1 = i;\n                }\n                else\n                {\n                    i0 = poly.Length - 1;\n                    i1 = 0;\n                }\n\n                l = new __line2t__(poly[i0], poly[i1]);\n                if (l.Intersects(new __line2t__(p0, p1), 4 *__rtype__.Epsilon, out p))\n                {\n                    if (!Fun.IsTiny(known.Closest(p)))\n                    {\n                        enter = (l.LeftValueOfPos(p1) >= -4 *__rtype__.Epsilon);\n                        index0 = index;\n\n                        return true;\n                    }\n                }\n\n                index++;\n            }\n\n            p = __v2t__.NaN;\n            index0 = -1;\n            enter = false;\n            return false;\n        }\n\n        internal static IEnumerable<__v2t__> AllVertices(__polygon2t__ poly)\n        {\n            int pc = poly.PointCount;\n            for (int pi = 0; pi < pc; pi++) yield return poly[pi];\n            yield return poly[0];\n        }\n\n        #endregion\n\n        #region Intersections (__rtype__)\n\n        #region __line2t__ - __polygon2t__\n\n        /// <summary>\n        /// Returns the Line-Segments of line inside the Polygon (CCW ordered).\n        /// Works with all (convex and non-convex) Polygons\n        /// </summary>\n        public static IEnumerable<__line2t__> ClipWith(this __line2t__ line, __polygon2t__ poly)\n        {\n            bool i0, i1;\n\n            i0 = poly.Contains(line.P0);\n            i1 = poly.Contains(line.P1);\n\n            var resulting = new List<__v2t__>();\n            var enter = new List<bool>();\n\n            if (i0)\n            {\n                resulting.Add(line.P0);\n                enter.Add(true);\n            }\n            if (i1)\n            {\n                resulting.Add(line.P1);\n                enter.Add(false);\n            }\n\n            var p = __v2t__.NaN;\n            var direction = line.Direction;\n\n            foreach (var l in poly.EdgeLines)\n            {\n                if (line.Intersects(l, out p))\n                {\n                    var d = l.Direction;\n                    var n = new __v2t__(-d.Y, d.X);\n\n                    if (!p.IsNaN)\n                    {\n                        bool addflag = true;\n                        bool flag = direction.Dot(n) > 0;\n\n                        for (int i = 0; i < resulting.Count; i++)\n                        {\n                            if (Fun.IsTiny((resulting[i] - p).Length))\n                            {\n                                if (flag != enter[i])\n                                {\n                                    resulting.RemoveAt(i);\n                                    enter.RemoveAt(i);\n                                }\n\n                                addflag = false;\n                                break;\n                            }\n                        }\n\n                        if (addflag)\n                        {\n                            resulting.Add(p);\n                            enter.Add(flag);\n                        }\n                    }\n                }\n            }\n\n            var dir = line.P1 - line.P0;\n            resulting = (from r in resulting select r).OrderBy(x => x.Dot(dir)).ToList();\n\n            var counter = resulting.Count;\n            var lines = new List<__line2t__>();\n            for (int i = 0; i < counter - 1; i += 2)\n            {\n                lines.Add(new __line2t__(resulting[i], resulting[i + 1]));\n            }\n            return lines;\n        }\n\n        /// <summary>\n        /// Returns the Line-Segments of line inside the Polygon (CCW ordered).\n        /// Works only with Convex-Polygons\n        /// If the line is clipped entirely, the points of the returned __line2t__ are NaN.\n        /// </summary>\n        public static __line2t__ ClipWithConvex(this __line2t__ line, __polygon2t__ poly)\n        {\n            var p = __v2t__.NaN;\n            bool i0, i1;\n\n            i0 = poly.Contains(line.P0);\n            i1 = poly.Contains(line.P1);\n\n            if (i0 && i1) return line;\n            else if ((!i0 && i1) || (i0 && !i1))\n            {\n                foreach (var l in poly.EdgeLines)\n                {\n                    if (line.Intersects(l, out p)) break;\n                }\n\n                if (i0) return new __line2t__(line.P0, p);\n                else return new __line2t__(p, line.P1);\n            }\n            else\n            {\n                __v2t__ p0 = __v2t__.NaN;\n                __v2t__ p1 = __v2t__.NaN;\n                int c = 0;\n\n                foreach (var l in poly.EdgeLines)\n                {\n                    if (line.Intersects(l, out p))\n                    {\n                        if (c == 0) p0 = p;\n                        else p1 = p;\n                        c++;\n                    }\n                }\n\n                if (c == 2)\n                {\n                    __v2t__ u = p1 - p0;\n\n                    if (u.Dot(line.Direction) > 0) return new __line2t__(p0, p1);\n                    else return new __line2t__(p1, p0);\n                }\n                else return new __line2t__(__v2t__.NaN, __v2t__.NaN);\n            }\n        }\n\n        #endregion\n\n        #region __polygon2t__ - __polygon2t__\n\n        /// <summary>\n        /// Clips one Polygon with an other. Returns a Polygon representing the Intersection of the two.\n        /// Works only with Convex Polygons. (For non-convex Polygons use __polygon2t__.ClipWith(__polygon2t__))\n        /// !!!! UNTESTED !!!!\n        /// </summary>\n        public static __polygon2t__ ClippedByConvex(this __polygon2t__ poly, __polygon2t__ second)\n        {\n            __v2t__[][] arr = new __v2t__[2][];\n            arr[0] = AllVertices(poly).ToArray();\n            arr[1] = AllVertices(second).ToArray();\n\n            __polygon2t__[] polygon = new __polygon2t__[2];\n            polygon[0] = poly;\n            polygon[1] = second;\n\n            bool current = false;\n            int currentIndex = 0;\n            int otherIndex = 1;\n\n            bool enter = false;\n            int index = -1;\n            __v2t__ point = __v2t__.NaN;\n\n            List<__v2t__> points = new List<__v2t__>();\n\n            for (int i = 1; i < arr[currentIndex].Length; i = (i + 1) % arr[currentIndex].Length)\n            {\n                if (i < 1) i = 1;\n                currentIndex = (current ? 1 : 0);\n                otherIndex = (current ? 0 : 1);\n\n                __v2t__ start = arr[currentIndex][i - 1];\n                __v2t__ end = arr[currentIndex][i];\n\n                if (Intersects(arr[otherIndex], start, end, ref points, out enter, out index, out point))\n                {\n                    if (enter)\n                    {\n                        points.Add(point);\n                        int u = i;\n                        int count = 0;\n                        while (polygon[otherIndex].Contains(arr[currentIndex][u]))\n                        {\n                            points.Add(arr[currentIndex][u]);\n                            u = (u + arr[currentIndex].Length - 1) % arr[currentIndex].Length;\n                            count++;\n                        }\n                        if (count == 0) i--;\n                        else\n                        {\n                            i += count - 1;\n                        }\n                    }\n                    else\n                    {\n                        points.Add(point);\n                        i = index;\n                        current = !current;\n                        currentIndex = (current ? 1 : 0);\n                        otherIndex = (current ? 0 : 1);\n                    }\n                }\n                else\n                {\n\n                    if (i < arr[currentIndex].Length && polygon[otherIndex].Contains(arr[currentIndex][i]))\n                    {\n                        if (Closest(points, arr[currentIndex][i]) < __eps__) break;\n                        points.Add(arr[currentIndex][i]);\n                    }\n                }\n            }\n\n\n            return new __polygon2t__(points);\n        }\n\n        /// <summary>\n        /// Clips one Polygon with an other. Returns a Polygon-Set representing the Intersections of the two.\n        /// Works only with all (convex/concave) Polygons\n        /// !!!! UNTESTED !!!!\n        /// </summary>\n        public static IEnumerable<__polygon2t__> ClippedBy(this __polygon2t__ p0, __polygon2t__ p1, __rtype__ relativeEpsilon)\n        {\n            List<int[]> i0 = SubPrimitives.ComputeNonConcaveSubPolygons(p0, relativeEpsilon);\n            List<int[]> i1 = SubPrimitives.ComputeNonConcaveSubPolygons(p1, relativeEpsilon);\n\n            List<__polygon2t__> polys = new List<__polygon2t__>();\n            for (int i = 0; i < i0.Count; i++)\n            {\n                for (int u = 0; u < i1.Count; u++)\n                {\n                    __polygon2t__ q0 = new __polygon2t__(from o in i0[i] select p0[o]);\n                    __polygon2t__ q1 = new __polygon2t__(from o in i1[u] select p1[o]);\n\n                    __polygon2t__ r = q0.ClippedByConvex(q1);\n                    if (r.PointCount > 0) polys.Add(r);\n                }\n            }\n\n            return Union(polys);\n\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Unions (__rtype__)\n\n        #region __polygon2t__ - __polygon2t__\n\n\n        public static IEnumerable<__polygon2t__> Union(List<__polygon2t__> p)\n        {\n            List<__polygon2t__> polys = new List<__polygon2t__>();\n            polys.Add(p[0]);\n            List<__polygon2t__> temp;\n\n            for (int i = 1; i < p.Count; i++)\n            {\n                bool found = false;\n                for (int u = 0; u < polys.Count; u++)\n                {\n                    temp = polys[u].Union(p[i]).ToList();\n\n                    if (temp.Count == 1)\n                    {\n                        polys[u] = temp[0];\n                        found = true;\n                    }\n                }\n\n                if (!found)\n                {\n                    polys.Add(p[i]);\n                }\n            }\n\n            return polys;\n        }\n\n        /// <summary>\n        /// Returns the unified Polygon of the two given ones.\n        /// Works only with convex-Polygons\n        /// Returns an empty Polygon if the two do not intersect\n        /// </summary>\n        public static IEnumerable<__polygon2t__> Union(this __polygon2t__ p0, __polygon2t__ p1)\n        {\n            __polygon2t__[] arr = new __polygon2t__[2];\n            arr[0] = p0;\n            arr[1] = p1;\n\n            int current = 0;\n            int other = 1;\n\n            List<__v2t__> points = new List<__v2t__>();\n            bool enter = false;\n            int index = -1;\n            __v2t__ point = __v2t__.NaN;\n\n            bool firstIntersectionFound = false;\n            __v2t__ firstIntersectionPoint = __v2t__.NaN;\n\n            for (int i = 0; i >= 0; i = (i + 1) % arr[current].PointCount)\n            {\n                __v2t__ start = arr[current][(i + arr[current].PointCount - 1) % arr[current].PointCount];\n                __v2t__ end = arr[current][i];\n\n                if (arr[other].ClosestIntersection(start, end, out enter, out index, out point))\n                {\n                    if (!firstIntersectionFound)\n                    {\n                        firstIntersectionFound = true;\n                        firstIntersectionPoint = point;\n                    }\n                    else\n                    {\n                        if ((point - firstIntersectionPoint).Length < __eps__) break;\n                    }\n\n                    if (enter)\n                    {\n                        points.Add(point);\n\n                        while ((arr[other][(index + 1) % arr[other].PointCount] - point).Length < __eps__) index = (index + 1) % arr[other].PointCount;\n\n                        if (!arr[current].Contains(arr[other][(index + 1) % arr[other].PointCount]))\n                        {\n                            points.Add(arr[other][(index + 1) % arr[other].PointCount]);\n                            index = (index + 1) % arr[other].PointCount;\n                        }\n\n                        i = index;\n                        current = (current == 1 ? 0 : 1);\n                        other = (current == 1 ? 0 : 1);\n                    }\n                    else\n                    {\n                        points.Add(point);\n                        if (!arr[other].Contains(arr[current][i]))\n                        {\n                            points.Add(arr[current][i]);\n                        }\n                    }\n                }\n                else\n                {\n                    if (i == arr[current].PointCount - 1 && !firstIntersectionFound) break;\n\n                    if (!arr[other].Contains(end) && firstIntersectionFound)\n                    {\n                        points.Add(end);\n                    }\n                }\n            }\n\n            if (!firstIntersectionFound)\n            {\n                if (p0.Contains(p1[0])) yield return p0;\n                else if (p1.Contains(p0[0])) yield return p1;\n                else\n                {\n                    yield return p0;\n                    yield return p1;\n                }\n            }\n            else yield return new __polygon2t__(points);\n        }\n\n        #endregion\n\n        public static IEnumerable<__polygon2t__> Union(this __box2t__ b0, __box2t__ b1)\n        {\n            __polygon2t__ p0 = new __polygon2t__(b0.ComputeCornersCCW());\n            __polygon2t__ p1 = new __polygon2t__(b1.ComputeCornersCCW());\n\n            return p0.Union(p1);\n        }\n\n        #endregion\n\n    //# }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Interfaces/IBoundingBox_auto.cs",
    "content": "namespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    /// <summary>\n    /// Return an axis aligned two-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox2i\n    {\n        Box2i BoundingBox2i { get; }\n    }\n\n    /// <summary>\n    /// Return an axis aligned three-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox3i\n    {\n        Box3i BoundingBox3i { get; }\n    }\n\n    /// <summary>\n    /// Return an axis aligned two-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox2l\n    {\n        Box2l BoundingBox2l { get; }\n    }\n\n    /// <summary>\n    /// Return an axis aligned three-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox3l\n    {\n        Box3l BoundingBox3l { get; }\n    }\n\n    /// <summary>\n    /// Return an axis aligned two-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox2f\n    {\n        Box2f BoundingBox2f { get; }\n    }\n\n    /// <summary>\n    /// Return an axis aligned three-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox3f\n    {\n        Box3f BoundingBox3f { get; }\n    }\n\n    /// <summary>\n    /// Return an axis aligned two-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox2d\n    {\n        Box2d BoundingBox2d { get; }\n    }\n\n    /// <summary>\n    /// Return an axis aligned three-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox3d\n    {\n        Box3d BoundingBox3d { get; }\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Interfaces/IBoundingBox_template.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var ft in Meta.SignedVecFieldTypes) {\n    //#   var ftype = ft.Name;\n    //#   var tc = ft.Char;\n    /// <summary>\n    /// Return an axis aligned two-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox2__tc__\n    {\n        Box2__tc__ BoundingBox2__tc__ { get; }\n    }\n\n    /// <summary>\n    /// Return an axis aligned three-dimensional box that contains the complete geometry.\n    /// </summary>\n    public interface IBoundingBox3__tc__\n    {\n        Box3__tc__ BoundingBox3__tc__ { get; }\n    }\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Interfaces/IBoundingCircle.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    public interface IBoundingCircle2f\n    {\n        Circle2f BoundingCircle2f { get; }\n    }\n\n    public interface IBoundingCircle2d\n    {\n        Circle2d BoundingCircle2d { get; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Interfaces/IBoundingSphere.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    public interface IBoundingSphere3f\n    {\n        Sphere3f BoundingSphere3f { get; }\n    }\n\n    public interface IBoundingSphere3d\n    {\n        Sphere3d BoundingSphere3d { get; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Interfaces/IImmutablePolygon.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// An immutable polygon.\n    /// </summary>\n    public interface IImmutablePolygon<T>\n    {\n        /// <summary>\n        /// Polygon outline.\n        /// </summary>\n        IReadOnlyList<T> Points { get; }\n\n        /// <summary>\n        /// Gets number of vertices.\n        /// </summary>\n        int Count { get; }\n\n        /// <summary>\n        /// Returns new polygon with point added. \n        /// </summary>\n        IImmutablePolygon<T> AddPoint(T p);\n\n        /// <summary>\n        /// Returns new polygon with points added. \n        /// </summary>\n        IImmutablePolygon<T> AddPoints(IEnumerable<T> points);\n\n        /// <summary>\n        /// Returns new polygon with point replaced. \n        /// </summary>\n        IImmutablePolygon<T> SetPoint(int index, T p);\n\n        /// <summary>\n        /// Returns new polygon with point p inserted at given index. \n        /// </summary>\n        IImmutablePolygon<T> InsertPoint(int index, T p);\n\n        /// <summary>\n        /// Returns new polygon with point removed. \n        /// </summary>\n        IImmutablePolygon<T> RemovePoint(int index);\n\n        /// <summary>\n        /// Returns new polygon with points removed. \n        /// </summary>\n        IImmutablePolygon<T> RemovePoints(IEnumerable<int> indexes);\n\n        /// <summary>\n        /// Returns new polygon with transformed points.\n        /// </summary>\n        IImmutablePolygon<U> Transform<U>(Func<T, U> transform);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Interfaces/IPolygon.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    public interface IPolygon<T>\n    {\n        int PointCount { get; }\n        T this[int index] { get; } // counter clockwise access\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/IntersectionTests_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    public static partial class GeometryFun\n    {\n        private static readonly int[] c_cubeEdgeVertex0 =\n            new int[] { 0, 2, 4, 6, 0, 1, 4, 5, 0, 1, 2, 3 };\n\n        private static readonly int[] c_cubeEdgeVertex1 =\n            new int[] { 1, 3, 5, 7, 2, 3, 6, 7, 4, 5, 6, 7 };\n\n        // Contains-tests should return true if the contained object is\n        // either entirely inside the containing object or lies on the\n        // boundary of the containing object.\n\n        #region Triangle2f contains V2f\n\n        public static bool Contains(\n            this Triangle2f triangle, V2f point\n            )\n        {\n            var v0p = point - triangle.P0;\n            return triangle.Line01.LeftValueOfDir(v0p) >= 0\n                    && triangle.Line02.RightValueOfDir(v0p) >= 0\n                    && triangle.Line12.LeftValueOfPos(point) >= 0;\n        }\n\n        #endregion\n\n        #region Triangle2f contains Line2f (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Triangle2f triangle, Line2f linesegment)\n            => triangle.Contains(linesegment.P0) && triangle.Contains(linesegment.P1);\n\n        #endregion\n\n        #region Triangle2f contains Triangle2f (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Triangle2f triangle, Triangle2f other)\n            => triangle.Contains(other.P0) && triangle.Contains(other.P1) && triangle.Contains(other.P2);\n\n        #endregion\n\n        #region Triangle2f contains Quad2f (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Triangle2f triangle, Quad2f q)\n            => triangle.Contains(q.P0) && triangle.Contains(q.P1) && triangle.Contains(q.P2) && triangle.Contains(q.P3);\n\n        #endregion\n\n        #region Triangle2f contains Circle2f\n\n        public static bool Contains(this Triangle2f triangle, Circle2f circle)\n        {\n            var center = circle.Center;\n            return triangle.Contains(center)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line01)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line12)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line20);\n        }\n\n        #endregion\n\n\n        #region Circle2f contains V2f (sm)\n\n        /// <summary>\n        /// True if point p is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2f circle, V2f p)\n            => (p - circle.Center).LengthSquared <= circle.RadiusSquared;\n\n        #endregion\n\n        #region Circle2f contains Line2f (sm)\n\n        /// <summary>\n        /// True if line segment is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2f circle, Line2f l)\n            => circle.Contains(l.P0) && circle.Contains(l.P1);\n\n        #endregion\n\n        #region Circle2f contains Triangle2f (sm)\n\n        /// <summary>\n        /// True if triangle is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2f circle, Triangle2f t)\n            => circle.Contains(t.P0) && circle.Contains(t.P1) && circle.Contains(t.P2);\n\n        #endregion\n\n        #region Circle2f contains Quad2f (sm)\n\n        /// <summary>\n        /// True if quad is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2f circle, Quad2f q)\n            => circle.Contains(q.P0) && circle.Contains(q.P1) && circle.Contains(q.P2) && circle.Contains(q.P3);\n\n        #endregion\n\n        #region Circle2f contains Circle2f (sm)\n\n        /// <summary>\n        /// True if other circle is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2f circle, Circle2f other)\n            => (other.Center - circle.Center).Length + other.Radius <= circle.Radius;\n\n        #endregion\n\n\n        #region Quad2f contains V2f (haaser)\n\n        /// <summary>\n        /// True if point is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2f quad, V2f point)\n        {\n            return LeftValOfPos(0, 1, ref point) >= 0 &&\n                   LeftValOfPos(1, 2, ref point) >= 0 &&\n                   LeftValOfPos(2, 3, ref point) >= 0 &&\n                   LeftValOfPos(3, 0, ref point) >= 0;\n\n            float LeftValOfPos(int i0, int i1, ref V2f p)\n                => (p.X - quad[i0].X) * (quad[i0].Y - quad[i1].Y) + (p.Y - quad[i0].Y) * (quad[i1].X - quad[i0].X);\n        }\n\n        #endregion\n\n        #region Quad2f contains Line2f\n\n        /// <summary>\n        /// True if line segment is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2f quad, Line2f l)\n            => quad.Contains(l.P0) && quad.Contains(l.P1);\n\n        #endregion\n\n        #region Quad2f contains Triangle2f\n\n        /// <summary>\n        /// True if triangle is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2f quad, Triangle2f t)\n            => quad.Contains(t.P0) && quad.Contains(t.P1) && quad.Contains(t.P2);\n\n        #endregion\n\n        #region Quad2f contains Quad2f\n\n        /// <summary>\n        /// True if other quad is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2f quad, Quad2f q)\n            => quad.Contains(q.P0) && quad.Contains(q.P1) && quad.Contains(q.P2) && quad.Contains(q.P3);\n\n        #endregion\n\n        #region Quad2f contains Circle2f\n\n        /// <summary>\n        /// True if circle is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2f quad, Circle2f circle)\n        {\n            var center = circle.Center;\n            return quad.Contains(center)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line01)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line12)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line23)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line30);\n        }\n\n        #endregion\n\n\n        #region Box3f contains Quad3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n            this Box3f box, Quad3f quad\n            )\n        {\n            return box.Contains(quad.P0)\n                    && box.Contains(quad.P1)\n                    && box.Contains(quad.P2)\n                    && box.Contains(quad.P3);\n        }\n\n        #endregion\n\n        #region Box3f contains Triangle3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n             this Box3f box, Triangle3f triangle\n            )\n        {\n            return box.Contains(triangle.P0)\n                    && box.Contains(triangle.P1)\n                    && box.Contains(triangle.P2);\n        }\n\n        #endregion\n\n        #region Box3f contains Sphere3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n             this Box3f box, Sphere3f sphere\n            )\n        {\n            return box.Contains(sphere.Center)\n                    && !box.Intersects(sphere);\n        }\n\n        #endregion\n\n        #region Box3f contains Cylinder3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n            this Box3f box, Cylinder3f cylinder\n           )\n        {\n            return box.Contains(cylinder.Center)\n                    && !box.Intersects(cylinder);\n        }\n\n        #endregion\n\n\n        #region Hull3f contains V3f\n\n        /// <summary>\n        /// Hull normals are expected to point outside.\n        /// </summary>\n        public static bool Contains(this Hull3f hull, V3f point)\n        {\n            var planes = hull.PlaneArray;\n            for (var i = 0; i < planes.Length; i++)\n            {\n                if (planes[i].Height(point) > 0)\n                    return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region Hull3f contains Sphere3f (sm)\n\n        /// <summary>\n        /// Hull normals are expected to point outside.\n        /// </summary>\n        public static bool Contains(this Hull3f hull, Sphere3f sphere)\n        {\n            var planes = hull.PlaneArray;\n            var negativeRadius = -sphere.Radius;\n            for (var i = 0; i < planes.Length; i++)\n            {\n                if (planes[i].Height(sphere.Center) > negativeRadius)\n                    return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n\n        #region Polygon2f contains V2f (haaser)\n\n        internal static V3i InsideTriangleFlags(ref V2f p0, ref V2f p1, ref V2f p2, ref V2f point)\n        {\n            V2f n0 = new V2f(p0.Y - p1.Y, p1.X - p0.X);\n            V2f n1 = new V2f(p1.Y - p2.Y, p2.X - p1.X);\n            V2f n2 = new V2f(p2.Y - p0.Y, p0.X - p2.X);\n\n            int t0 = Fun.Sign(n0.Dot(point - p0));\n            int t1 = Fun.Sign(n1.Dot(point - p1));\n            int t2 = Fun.Sign(n2.Dot(point - p2));\n\n            if (t0 == 0) t1 = 1;\n            if (t1 == 0) t1 = 1;\n            if (t2 == 0) t2 = 1;\n\n            return new V3i(t0, t1, t2);\n        }\n\n        internal static V3i InsideTriangleFlags(ref V2f p0, ref V2f p1, ref V2f p2, ref V2f point, int t0)\n        {\n            V2f n1 = new V2f(p1.Y - p2.Y, p2.X - p1.X);\n            V2f n2 = new V2f(p2.Y - p0.Y, p0.X - p2.X);\n\n            int t1 = Fun.Sign(n1.Dot(point - p1));\n            int t2 = Fun.Sign(n2.Dot(point - p2));\n\n            if (t1 == 0) t1 = 1;\n            if (t2 == 0) t2 = 1;\n\n            return new V3i(t0, t1, t2);\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon2f contains the given point.\n        /// Works with all (convex and non-convex) Polygons.\n        /// Assumes that the Vertices of the Polygon are sorted counter clockwise\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Polygon2f poly, V2f point)\n        {\n            return poly.Contains(point, true);\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon2f contains the given point.\n        /// Works with all (convex and non-convex) Polygons.\n        /// CCW represents the sorting order of the Polygon-Vertices (true -> CCW, false -> CW)\n        /// </summary>\n        public static bool Contains(this Polygon2f poly, V2f point, bool CCW)\n        {\n            int pc = poly.PointCount;\n            if (pc < 3)\n                return false;\n            int counter = 0;\n            V2f p0 = poly[0], p1 = poly[1], p2 = poly[2];\n            V3i temp = InsideTriangleFlags(ref p0, ref p1, ref p2, ref point);\n            int t2_cache = temp.Z;\n            if (temp.X == temp.Y && temp.Y == temp.Z) counter += temp.X;\n            for (int pi = 3; pi < pc; pi++)\n            {\n                p1 = p2; p2 = poly[pi];\n                temp = InsideTriangleFlags(ref p0, ref p1, ref p2, ref point, -t2_cache);\n                t2_cache = temp.Z;\n                if (temp.X == temp.Y && temp.Y == temp.Z) counter += temp.X;\n            }\n            if (CCW) return counter > 0;\n            else return counter < 0;\n        }\n\n        #endregion\n\n\n        #region Plane3f +- eps contains V3f (sm)\n\n        /// <summary>\n        /// Returns true if point is within given eps to plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Plane3f plane, float eps, V3f point)\n        {\n            var d = plane.Height(point);\n            return d >= -eps && d <= eps;\n        }\n\n        #endregion\n\n        #region Plane3f +- eps contains Box3f (sm)\n\n        /// <summary>\n        /// Returns true if the space within eps to a plane fully contains the given box.\n        /// </summary>\n        public static bool Contains(this Plane3f plane, float eps, Box3f box)\n        {\n            var corners = box.ComputeCorners();\n            for (var i = 0; i < 8; i++)\n            {\n                var d = plane.Height(corners[i]);\n                if (d < -eps || d > eps) return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region Polygon3f +- eps contains V3f (sm)\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Polygon3f polygon, float eps, V3f point, out float distance)\n        {\n            var plane = polygon.GetPlane3f();\n            distance = plane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            var w2p = plane.GetWorldToPlane();\n            var poly2d = new Polygon2f(polygon.GetPointArray().Map(p => w2p.TransformPos(p).XY));\n            return poly2d.Contains(w2p.TransformPos(point).XY);\n        }\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Polygon3f polygon, Plane3f supportingPlane, Euclidean3f world2plane, Polygon2f poly2d, float eps, V3f point, out float distance)\n        {\n            distance = supportingPlane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            return poly2d.Contains(world2plane.TransformPos(point).XY);\n        }\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Polygon3f polygon, Plane3f supportingPlane, M44f world2plane, Polygon2f poly2d, float eps, V3f point, out float distance)\n        {\n            distance = supportingPlane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            return poly2d.Contains(world2plane.TransformPos(point).XY);\n        }\n\n        #endregion\n\n\n        // Intersection tests\n\n        #region Line2f intersects Line2f\n\n        /// <summary>\n        /// Returns true if the two line segments intersect.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Line2f l0, Line2f l1)\n            => l0.IntersectsLine(l1.P0, l1.P1, out V2f _);\n\n        /// <summary>\n        /// Returns true if the two line segments intersect.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Line2f l0, Line2f l1, out V2f p)\n            => l0.IntersectsLine(l1.P0, l1.P1, out p);\n\n        /// <summary>\n        /// Returns true if the two line segments intersect within given tolerance.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Line2f l0, Line2f l1, float absoluteEpsilon, out V2f p)\n            => l0.IntersectsLine(l1.P0, l1.P1, absoluteEpsilon, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this Line2f line, V2f p0, V2f p1)\n            => line.IntersectsLine(p0, p1, out _);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this Line2f line, V2f p0, V2f p1, out V2f p)\n            => line.IntersectsLine(p0, p1, false, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// The intersection point is returned in p.\n        /// If overlapping is true and the segments are parallel, then\n        /// the closest point to p0 of the intersection range is returned in p.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Line2f line,\n            V2f p0, V2f p1,\n            bool overlapping,\n            out V2f p\n            )\n        {\n            var a = line.P0 - p0;\n\n            if (Fun.IsTiny(a.LengthSquared))\n            {\n                p = p0;\n                return true;\n            }\n\n            var u = line.P1 - line.P0;\n            var v = p1 - p0;\n            var lu = u.Length;\n\n            var cross = u.X * v.Y - u.Y * v.X;\n            if (!Fun.IsTiny(cross))\n            {\n                // non-parallel lines\n                cross = 1 / cross;\n                var t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 > 1 || t0 < 0)\n                {\n                    p = V2f.NaN;\n                    return false;\n                }\n\n                float t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                if (t1 > 1 || t1 < 0)\n                {\n                    p = V2f.NaN;\n                    return false;\n                }\n\n                p = line.P0 + u * t0;\n                return true;\n            }\n            else\n            {\n                // parallel lines\n                if (!overlapping)\n                {\n                    p = V2f.NaN;\n                    return false;\n                }\n\n                var normalizedDirection = u / lu;\n\n                var r0 = new Range1f(0, lu);\n                var r1 = new Range1f((p0 - line.P0).Dot(normalizedDirection), (p1 - line.P0).Dot(normalizedDirection));\n                r1.Repair();\n\n                if (r0.Intersects(r1, 0, out Range1f result))\n                {\n                    p = line.P0 + normalizedDirection * result.Min;\n                    return true;\n                }\n\n                p = V2f.NaN;\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1 within given tolerance.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this Line2f line, V2f p0, V2f p1, float absoluteEpsilon, out V2f p)\n            => line.IntersectsLine(p0, p1, absoluteEpsilon, false, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1 within given tolerance.\n        /// The intersection point is returned in p.\n        /// If overlapping is true and the segments are parallel, then\n        /// the closest point to p0 of the intersection range is returned in p.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Line2f line,\n            V2f p0, V2f p1,\n            float absoluteEpsilon,\n            bool overlapping,\n            out V2f p\n            )\n        {\n            var a = line.P0 - p0;\n\n            if (Fun.IsTiny(a.LengthSquared))\n            {\n                p = p0;\n                return true;\n            }\n\n            var u = line.P1 - line.P0;\n            var v = p1 - p0;\n\n            var lu = u.Length;\n            var lv = v.Length;\n            var relativeEpsilonU = absoluteEpsilon / lu;\n            var RelativeEpsilonV = absoluteEpsilon / lv;\n\n            var cross = u.X * v.Y - u.Y * v.X;\n            if (!Fun.IsTiny(cross))\n            {\n                // non-parallel lines\n                cross = 1 / cross;\n                var t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 > 1 + relativeEpsilonU || t0 < -relativeEpsilonU)\n                {\n                    p = V2f.NaN;\n                    return false;\n                }\n\n                var t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                if (t1 > 1 + RelativeEpsilonV || t1 < -RelativeEpsilonV)\n                {\n                    p = V2f.NaN;\n                    return false;\n                }\n\n                p = line.P0 + u * t0;\n                return true;\n            }\n            else\n            {\n                // parallel lines\n                if (!overlapping)\n                {\n                    p = V2f.NaN;\n                    return false;\n                }\n\n                var normalizedDirection = u / lu;\n\n                var r0 = new Range1f(0, lu);\n                var r1 = new Range1f((p0 - line.P0).Dot(normalizedDirection), (p1 - line.P0).Dot(normalizedDirection));\n                r1.Repair();\n\n                if (r0.Intersects(r1, absoluteEpsilon, out Range1f result))\n                {\n                    p = line.P0 + normalizedDirection * result.Min;\n                    return true;\n                }\n\n                p = V2f.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Ray2f intersects Line2f\n\n        /// <summary>\n        /// Returns true if the Ray and the Line intersect.\n        /// ATTENTION: Both-Sided Ray\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray2f ray,\n            Line2f line\n            )\n        {\n            return ray.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// returns true if the Ray and the Line intersect.\n        /// t holds the smallest Intersection-Parameter for the Ray\n        /// ATTENTION: t can be negative\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray2f ray,\n            Line2f line,\n            out float t\n            )\n        {\n            return ray.IntersectsLine(line.P0, line.P1, out t);\n        }\n\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// ATTENTION: Both-Sided Ray\n        /// </summary>\n        public static bool IntersectsLine(\n            this Ray2f ray,\n            V2f p0, V2f p1\n            )\n        {\n            V2f n = new V2f(-ray.Direction.Y, ray.Direction.X);\n\n            float d0 = n.Dot(p0 - ray.Origin);\n            float d1 = n.Dot(p1 - ray.Origin);\n\n            if (d0.Sign() != d1.Sign()) return true;\n            else if (Fun.IsTiny(d0) && Fun.IsTiny(d1)) return true;\n            else return false;\n        }\n\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// t holds the Intersection-Parameter for the Ray\n        /// If both Line-Points are on the Ray no Intersection is returned\n        /// ATTENTION: t can be negative\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this Ray2f ray,\n            V2f p0, V2f p1,\n            out float t\n            )\n        {\n            return ray.IntersectsLine(p0, p1, false, out t);\n        }\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// if overlapping is true t holds the smallest Intersection-Parameter for the Ray\n        /// if overlagging is false and both Line-Points are on the Ray no Intersection is returned\n        /// ATTENTION: t can be negative\n        /// </summary>\n        public static bool IntersectsLine(\n            this Ray2f ray,\n            V2f p0, V2f p1,\n            bool overlapping,\n            out float t\n            )\n        {\n            V2f a = p0 - ray.Origin;\n            V2f u = p1 - p0;\n            V2f v = ray.Direction;\n            float lv2 = v.LengthSquared;\n\n\n            float cross = u.X * v.Y - u.Y * v.X;\n            float n = a.Y * u.X - a.X * u.Y;\n\n            if (!Fun.IsTiny(cross))\n            {\n                cross = 1 / cross;\n\n                float t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 >= 0 && t0 <= 1)\n                {\n                    t = n * cross;\n                    return true;\n                }\n\n                t = float.NaN;\n                return false;\n            }\n\n            if (Fun.IsTiny(n) && overlapping)\n            {\n                float ta = v.Dot(a) / lv2;\n                float tb = v.Dot(p1 - ray.Origin) / lv2;\n\n                if ((ta < 0 && tb > 0) || (ta > 0 && tb < 0))\n                {\n                    t = 0;\n                    return true;\n                }\n                else\n                {\n                    if (ta >= 0) t = Fun.Min(ta, tb);\n                    else t = Fun.Max(ta, tb);\n\n                    return true;\n                }\n            }\n\n            t = float.NaN;\n            return false;\n        }\n\n\n\n        #endregion\n\n        #region Ray2f intersects Ray2f\n\n        /// <summary>\n        /// Returns true if the Rays intersect\n        /// ATTENTION: Both-Sided Rays\n        /// </summary>\n        public static bool Intersects(\n            this Ray2f r0,\n            Ray2f r1\n            )\n        {\n            if (!r0.Direction.IsParallelTo(r1.Direction)) return true;\n            else\n            {\n                V2f n0 = new V2f(-r0.Direction.Y, r0.Direction.X);\n\n                if (Fun.IsTiny(n0.Dot(r1.Origin - r0.Origin))) return true;\n                else return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the Rays intersect\n        /// t0 and t1 are the corresponding Ray-Parameters for the Intersection\n        /// ATTENTION: Both-Sided Rays\n        /// </summary>\n        public static bool Intersects(\n            this Ray2f r0, Ray2f r1,\n            out float t0, out float t1\n            )\n        {\n            V2f a = r0.Origin - r1.Origin;\n\n            if (r0.Origin.ApproximateEquals(r1.Origin, Constant<float>.PositiveTinyValue))\n            {\n                t0 = 0;\n                t1 = 0;\n                return true;\n            }\n\n            V2f u = r0.Direction;\n            V2f v = r1.Direction;\n\n            float cross = u.X * v.Y - u.Y * v.X;\n\n            if (!Fun.IsTiny(cross))\n            {\n                //Rays not parallel\n                cross = 1 / cross;\n\n                t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                return true;\n            }\n            else\n            {\n                t0 = float.NaN;\n                t1 = float.NaN;\n                //Rays are parallel\n                if (Fun.IsTiny(a.Y * u.X - a.X * u.Y)) return true;\n                else return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the Rays intersect.\n        /// </summary>\n        public static bool Intersects(this Ray2f r0, Ray2f r1, out float t)\n        {\n            V2f a = r1.Origin - r0.Origin;\n            if (a.Abs().AllSmaller(Constant<float>.PositiveTinyValue))\n            {\n                t = 0;\n                return true; // Early exit when rays have same origin\n            }\n\n            float cross = r0.Direction.Dot270(r1.Direction);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n            {\n                t = r1.Direction.Dot90(a) / cross;\n                return true;\n            }\n            else // Rays are parallel\n            {\n                t = float.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Ray2f intersects Circle2f\n\n        /// <summary>\n        /// Computes the intersection between the given <see cref=\"Ray2f\"/> and <see cref=\"Circle2f\"/>.\n        /// </summary>\n        /// <param name=\"ray\">The ray to intersect.</param>\n        /// <param name=\"circle\">The circle to intersect the ray with.</param>\n        /// <param name=\"t0\">The ray parameter of the first intersection. Set to infinity if there is no intersection.</param>\n        /// <param name=\"t1\">The ray parameter of the second intersection. Set to infinity if there is no intersection.</param>\n        /// <returns>True if there is an intersection, false otherwise.</returns>\n        public static bool Intersects(this Ray2f ray, Circle2f circle, out float t0, out float t1)\n        {\n            var p = ray.Origin - circle.Center;\n            var a = ray.Direction.X.Square() + ray.Direction.Y.Square();\n            var b = 2 * ray.Direction.X * p.X + 2 * ray.Direction.Y * p.Y;\n            var c = p.X.Square() + p.Y.Square() - circle.Radius.Square();\n            var d = b.Square() - 4 * a * c;\n\n            if (d < 0)\n            {\n                t0 = float.PositiveInfinity;\n                t1 = float.PositiveInfinity;\n                return false;\n            }\n            else\n            {\n                var div = 1 / (a + a);\n                d = d.Sqrt();\n                t0 = (-b + d) * div;\n                t1 = (-b - d) * div;\n                return true;\n            }\n        }\n\n        #endregion\n\n\n        #region Plane2f intersects Line2f\n\n        /// <summary>\n        /// Returns true if the Plane2f and the Line2f intersect or the Line2f\n        /// lies completely in the Plane's Epsilon-Range\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        public static bool Intersects(\n            this Plane2f plane,\n            Line2f line,\n            float absoluteEpsilon\n            )\n        {\n            float lengthOfNormal2 = plane.Normal.LengthSquared;\n            float d0 = plane.Height(line.P0);\n            float d1 = plane.Height(line.P1);\n\n            return d0 * d1 < absoluteEpsilon * absoluteEpsilon * lengthOfNormal2;\n        }\n\n        /// <summary>\n        /// Returns true if the Plane2f and the Line2f intersect\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Plane2f plane,\n            Line2f line\n            )\n        {\n            return plane.IntersectsLine(line.P0, line.P1);\n        }\n\n\n        /// <summary>\n        /// Returns true if the Plane2f and the line between p0 and p1 intersect\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this Plane2f plane,\n            V2f p0, V2f p1\n            )\n        {\n            float d0 = plane.Height(p0);\n            float d1 = plane.Height(p1);\n\n            return d0 * d1 <= 0;\n        }\n\n        /// <summary>\n        /// Returns true if the Plane2f and the Line2f intersect\n        /// point holds the Intersection-Point. If no Intersection is found point is V2f.NaN\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Plane2f plane,\n            Line2f line,\n            out V2f point\n            )\n        {\n            return plane.Intersects(line, 0, out point);\n        }\n\n        /// <summary>\n        /// Returns true if the Plane2f and the Line2f intersect or the Line2f\n        /// lies completely in the Plane's Epsilon-Range\n        /// point holds the Intersection-Point. If the Line2f is inside Epsilon point holds the centroid of the Line2f\n        /// If no Intersection is found point is V2f.NaN\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        public static bool Intersects(\n            this Plane2f plane,\n            Line2f line,\n            float absoluteEpsilon,\n            out V2f point\n            )\n        {\n            float h0 = plane.Height(line.P0);\n            float h1 = plane.Height(line.P1);\n\n            int s0 = (h0 > -absoluteEpsilon ? (h0 < absoluteEpsilon ? 0 : 1) : -1);\n            int s1 = (h1 > -absoluteEpsilon ? (h1 < absoluteEpsilon ? 0 : 1) : -1);\n\n            if (s0 == s1)\n            {\n                if (s0 != 0)\n                {\n                    point = V2f.NaN;\n                    return false;\n                }\n                else\n                {\n                    point = (line.P0 + line.P1) * 0.5f;\n                    return true;\n                }\n            }\n            else\n            {\n                if (s0 == 0)\n                {\n                    point = line.P0;\n                    return true;\n                }\n                else if (s1 == 0)\n                {\n                    point = line.P1;\n                    return true;\n                }\n                else\n                {\n                    V2f dir = line.Direction;\n                    float no = plane.Normal.Dot(line.P0);\n                    float nd = plane.Normal.Dot(dir);\n                    float t = (plane.Distance - no) / nd;\n\n                    point = line.P0 + t * dir;\n                    return true;\n                }\n            }\n        }\n\n\n\n        #endregion\n\n        #region Plane2f intersects Ray2f\n\n        /// <summary>\n        /// Returns true if the Plane2f and the Ray2f intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2f plane, Ray2f ray)\n            => !plane.Normal.IsOrthogonalTo(ray.Direction);\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Ray2d intersect.\n        /// point holds the Intersection-Point if an intersection is found (else V2d.NaN)\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2f plane, Ray2f ray, out V2f point)\n            => plane.Intersects(ray, out float t, out point);\n\n        /// <summary>\n        /// Returns true if the Plane2f and the Ray2f intersect.\n        /// t holds the ray paramater of the intersection point if the intersection is found (else Double.PositiveInfinity).\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2f plane, Ray2f ray, out float t)\n        {\n            float dot = Vec.Dot(plane.Normal, ray.Direction);\n            if (Fun.IsTiny(dot))\n            {\n                t = float.PositiveInfinity;\n                return false;\n            }\n            t = -plane.Height(ray.Origin) / dot;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the Plane2f and the Ray2f intersect.\n        /// t and p hold the ray paramater and point of the intersection if one is found (else Double.PositiveInfinity and V2f.PositiveInfinity).\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2f plane, Ray2f ray, out float t, out V2f p)\n        {\n            bool result = Intersects(plane, ray, out t);\n            p = ray.Origin + t * ray.Direction;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the intersection point of the given Plane2f and Ray2f, or V2f.PositiveInfinity if ray is parallel to plane.\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Intersect(this Plane2f plane, Ray2f ray)\n        {\n            float dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot)) return V2f.PositiveInfinity;\n            return ray.GetPointOnRay(-plane.Height(ray.Origin) / dot);\n        }\n\n        #endregion\n\n        #region Plane2f intersects Plane2f\n\n        /// <summary>\n        /// Returns true if the two Plane2ds intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2f p0, Plane2f p1)\n        {\n            var hit = p0.Coefficients.Cross(p1.Coefficients);\n            return !hit.Z.IsTiny();\n        }\n\n        /// <summary>\n        /// Returns true if the two Plane2ds intersect.\n        /// Point holds the intersection point if an intersection is found.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2f p0, Plane2f p1, out V2f point)\n        {\n            var hit = p0.Coefficients.Cross(p1.Coefficients);\n            point = hit.XY / hit.Z;\n\n            return !hit.Z.IsTiny();\n        }\n\n        #endregion\n\n        #region Plane2f intersects IEnumerable<V2f>\n\n        /// <summary>\n        /// returns true if the Plane2f divides the Point-Cloud\n        /// </summary>\n        public static bool Divides(\n            this Plane2f plane,\n            IEnumerable<V2f> data\n            )\n        {\n            int first = int.MinValue;\n            foreach (var p in data)\n            {\n                if (first == int.MinValue)\n                {\n                    first = plane.Height(p).Sign();\n                }\n                else\n                {\n                    if (plane.Height(p).Sign() != first) return true;\n                }\n            }\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region Circle2f intersects Circle2f (sm)\n\n        /// <summary>\n        /// Returns true if the circles intersect, or one contains the other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Circle2f c0, Circle2f c1)\n            => (c0.Center - c1.Center).LengthSquared <= (c0.Radius + c1.Radius).Square();\n\n        #endregion\n\n\n        #region Triangle2f intersects Line2f\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect or the triangle contains the line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle2f triangle,\n            Line2f line\n            )\n        {\n            return triangle.IntersectsLine(line.P0, line.P1);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the line between p0 and p1 intersect or the triangle contains the line\n        /// </summary>\n        public static bool IntersectsLine(\n            this Triangle2f triangle,\n            V2f p0, V2f p1\n            )\n        {\n            if(triangle.Contains(p0))return true;\n            if(triangle.Contains(p1))return true;\n\n            if(triangle.Line01.IntersectsLine(p0,p1))return true;\n            if(triangle.Line12.IntersectsLine(p0,p1))return true;\n            if(triangle.Line20.IntersectsLine(p0,p1))return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Triangle2f intersects Ray2f\n\n        /// <summary>\n        /// Returns true if the Triangle and the Ray intersect\n        /// </summary>\n        public static bool Intersects(\n            this Triangle2f triangle,\n            Ray2f ray\n            )\n        {\n            if (triangle.Contains(ray.Origin)) return true;\n\n            if (ray.IntersectsLine(triangle.P0, triangle.P1)) return true;\n            if (ray.IntersectsLine(triangle.P1, triangle.P2)) return true;\n            if (ray.IntersectsLine(triangle.P2, triangle.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Triangle2f intersects Plane2f\n\n        /// <summary>\n        /// returns true if the Triangle2f and the Plane2f intersect\n        /// </summary>\n        public static bool Intersects(\n            this Triangle2f triangle,\n            Plane2f plane\n            )\n        {\n            if (plane.Intersects(triangle.Line01)) return true;\n            if (plane.Intersects(triangle.Line12)) return true;\n            if (plane.Intersects(triangle.Line20)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Triangle2f intersects Triangle2f\n\n        /// <summary>\n        /// Returns true if the triangles intersect or one contains the other.\n        /// </summary>\n        public static bool Intersects(this Triangle2f t0, Triangle2f t1)\n        {\n            var l = t0.Line01;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            l = t0.Line12;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            l = t0.Line20;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            if (t0.Contains(t1.P0)) return true;\n            if (t1.Contains(t0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region Box2f intersects Line2f\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool Intersects(this Box2f box, Line2f line)\n        {\n            var out0 = box.OutsideFlags(line.P0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(line.P1); if (out1 == 0) return true;\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n                this Box2f box, Line2f line, Box.Flags out0, Box.Flags out1)\n        {\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsLine(\n                this Box2f box, V2f p0, V2f p1)\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            return box.IntersectsLine(p0, p1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsLine(\n                this Box2f box, V2f p0, V2f p1,\n                Box.Flags out0, Box.Flags out1)\n        {\n            if ((out0 & out1) != 0) return false;\n\n            V2f min = box.Min;\n            V2f max = box.Max;\n            var bf = out0 | out1;\n\n            if ((bf & Box.Flags.X) != 0)\n            {\n                float dx = p1.X - p0.X;\n                if ((bf & Box.Flags.MinX) != 0)\n                {\n                    if (dx == 0 && p0.X < min.X) return false;\n                    float t = (min.X - p0.X) / dx;\n                    V2f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinX) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxX) != 0)\n                {\n                    if (dx == 0 && p0.X > max.X) return false;\n                    float t = (max.X - p0.X) / dx;\n                    V2f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxX) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Y) != 0)\n            {\n                float dy = p1.Y - p0.Y;\n                if ((bf & Box.Flags.MinY) != 0)\n                {\n                    if (dy == 0 && p0.Y < min.Y) return false;\n                    float t = (min.Y - p0.Y) / dy;\n                    V2f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinY) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxY) != 0)\n                {\n                    if (dy == 0 && p0.Y > max.Y) return false;\n                    float t = (max.Y - p0.Y) / dy;\n                    V2f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxY) == 0)\n                        return true;\n                }\n            }\n            return false;\n        }\n\n\n        #endregion\n\n        #region Box2f intersects Ray2f\n\n        /// <summary>\n        /// Returns true if the box and the ray intersect\n        /// </summary>\n        public static bool Intersects(\n            this Box2f box,\n            Ray2f ray\n            )\n        {\n            /*\n             * Getting a Normal-Vector for the Ray and calculating\n             * the Normal Distances for every Box-Point:\n             */\n            V2f n = new V2f(-ray.Direction.Y, ray.Direction.X);\n\n            float d0 = n.Dot(box.Min - ray.Origin);                                            //n.Dot(box.p0 - ray.Origin)\n            float d1 = n.X * (box.Max.X - ray.Origin.X) + n.Y * (box.Min.Y - ray.Origin.Y);    //n.Dot(box.p1 - ray.Origin)\n            float d2 = n.Dot(box.Max - ray.Origin);                                            //n.Dot(box.p2 - ray.Origin)\n            float d3 = n.X * (box.Min.X - ray.Origin.X) + n.Y * (box.Max.Y - ray.Origin.Y);    //n.Dot(box.p3 - ray.Origin)\n\n            /*\n             * If Zero lies in the Range of the Distances there\n             * have to be Points on both sides of the Ray.\n             * This means the Box and the Ray have an Intersection\n             */\n\n            Range1f r = new Range1f(d0, d1, d2, d3);\n            return r.Contains(0);\n        }\n\n        #endregion\n\n        #region Box2f intersects Plane2f\n\n        /// <summary>\n        /// returns true if the box and the plane intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Box2f box,\n            Plane2f plane\n            )\n        {\n            //UNTESTED\n            return plane.Divides(box.ComputeCorners());\n        }\n\n\n        /// <summary>\n        /// NOT TESTED YET.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Box2f box,\n            Plane2f plane,\n            out Line2f line)\n        {\n            return Intersects(\n                    plane.Normal.X, plane.Normal.Y, plane.Distance,\n                    box.Min.X, box.Min.Y, box.Max.X, box.Max.Y,\n                    out line);\n        }\n\n        /// <summary>\n        /// Intersects an infinite line given by its normal vector [nx, ny]\n        /// and its distance to the origin d, with an axis aligned box given\n        /// by it minimal point [xmin, ymin] and its maximal point\n        /// [xmax, ymax]. Returns true if there is an intersection and computes\n        /// the actual intersection line.\n        /// NOT TESTED YET.\n        /// </summary>\n        public static bool Intersects(\n                float nx, float ny, float d,\n                float xmin, float ymin, float xmax, float ymax,\n                out Line2f line)\n        {\n            if (nx.IsTiny()) // horizontal\n            {\n                if (d <= ymin || d >= ymax) { line = default; return false; }\n                line = new Line2f(new V2f(xmin, d), new V2f(xmax, d));\n                return true;\n            }\n\n            if (ny.IsTiny()) // vertical\n            {\n                if (d <= xmin || d >= xmax) { line = default; return false; }\n                line = new Line2f(new V2f(d, ymin), new V2f(d, ymax));\n                return true;\n            }\n\n            if (nx.Sign() != ny.Sign())\n            {\n                float x0 = (d - ny * ymin) / nx;\n                if (x0 >= xmax) { line = default; return false; }\n                if (x0 > xmin) xmin = x0;\n                float x1 = (d - ny * ymax) / nx;\n                if (x1 <= xmin) { line = default; return false; }\n                if (x1 < xmax) xmax = x1;\n\n                float y0 = (d - nx * xmin) / ny;\n                if (y0 >= ymax) { line = default; return false; }\n                if (y0 > ymin) ymin = y0;\n                float y1 = (d - nx * xmax) / ny;\n                if (y1 <= ymin) { line = default; return false; }\n                if (y1 < ymax) ymax = y1;\n\n                line = new Line2f(new V2f(xmin, ymin), new V2f(xmax, ymax));\n            }\n            else\n            {\n                float x0 = (d - ny * ymax) / nx;\n                if (x0 >= xmax) { line = default; return false; }\n                if (x0 > xmin) xmin = x0;\n                float x1 = (d - ny * ymin) / nx;\n                if (x1 <= xmin) { line = default; return false; }\n                if (x1 < xmax) xmax = x1;\n                float y0 = (d - nx * xmax) / ny;\n                if (y0 >= ymax) { line = default; return false; }\n                if (y0 > ymin) ymin = y0;\n                float y1 = (d - nx * xmin) / ny;\n                if (y1 <= ymin) { line = default; return false; }\n                if (y1 < ymax) ymax = y1;\n\n                line = new Line2f(new V2f(xmax, ymin), new V2f(xmin, ymax));\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region Box2f intersects Triangle2f\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Box2f box,\n            Triangle2f triangle\n            )\n        {\n            return box.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2);\n        }\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect\n        /// </summary>\n        public static bool IntersectsTriangle(\n            this Box2f box,\n            V2f p0, V2f p1, V2f p2\n            )\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n\n            return box.IntersectsTriangle(p0, p1, p2, out0, out1, out2);\n        }\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect. The outside flags\n        /// of the end points of the Triangle with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsTriangle(\n            this Box2f box, V2f p0, V2f p1, V2f p2,\n            Box.Flags out0, Box.Flags out1, Box.Flags out2\n            )\n        {\n\n            /* ---------------------------------------------------------------\n                If all of the points of the triangle are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n               If two points of the triangle are not on the same side\n               outside the box, it is possible that the edge between them\n               intersects the box. The outside flags we computed are also\n               used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p0, out2, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n               The only case left: The triangle contains the the whole box\n               i.e. every point. When no triangle-line intersects the box and one\n               box point is inside the triangle the triangle must contain the box\n            --------------------------------------------------------------- */\n            V2f a = box.Min - p0;\n            V2f u = p1 - p0;\n            V2f v = p2 - p0;\n\n\n            float cross = u.X * v.Y - u.Y * v.X;\n            if (Fun.IsTiny(cross)) return false;\n            cross = 1 / cross;\n\n            float t0 = (a.Y * v.X - a.X * v.Y) * cross; if (t0 < 0 || t0 > 1) return false;\n            float t1 = (a.Y * u.X - a.X * u.Y) * cross; if (t1 < 0 || t1 > 1) return false;\n\n            return (t0 + t1 < 1);\n        }\n\n        #endregion\n\n        #region Box2f intersects Box2f (Box2f-Implementation)\n\n        //Directly in Box-Implementation\n\n        #endregion\n\n\n        #region Quad2f intersects Line2f\n\n        /// <summary>\n        /// returns true if the Quad and the line intersect or the quad contains the line\n        /// </summary>\n        public static bool Intersects(\n            this Quad2f quad,\n            Line2f line\n            )\n        {\n            if (quad.Contains(line.P0)) return true;\n            if (quad.Contains(line.P1)) return true;\n\n            if (line.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (line.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (line.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (line.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n        /// <summary>\n        /// returns true if the Quad and the line between p0 and p1 intersect or the quad contains the line\n        /// </summary>\n        public static bool IntersectsLine(\n            this Quad2f quad,\n            V2f p0, V2f p1\n            )\n        {\n            if (quad.Contains(p0)) return true;\n            if (quad.Contains(p1)) return true;\n\n            Line2f line = new Line2f(p0, p1);\n            if (line.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (line.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (line.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (line.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Quad2f intersects Ray2f\n\n        /// <summary>\n        /// returns true if the quad and the ray intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad2f quad,\n            Ray2f ray\n            )\n        {\n            return ray.Plane2f.Divides(quad.Points);\n        }\n\n        #endregion\n\n        #region Quad2f intersects Plane2f\n\n        /// <summary>\n        /// returns true if the Quad2f and the Plane2f intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad2f quad,\n            Plane2f plane\n            )\n        {\n            //UNTESTED\n            if (plane.Divides(quad.Points)) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region Quad2f intersects Triangle2f\n\n        /// <summary>\n        /// returns true if the Quad2f and the Triangle2f intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Quad2f quad,\n            Triangle2f triangle\n            )\n        {\n            if (quad.Intersects(triangle.Line01)) return true;\n            if (quad.Intersects(triangle.Line12)) return true;\n            if (quad.Intersects(triangle.Line20)) return true;\n\n            if (quad.Contains(triangle.P0)) return true;\n            if (triangle.Contains(quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Quad2f intersects Box2f\n\n        /// <summary>\n        /// Returns true if the box and the Quad intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Box2f box,\n            Quad2f quad\n            )\n        {\n            Box.Flags out0 = box.OutsideFlags(quad.P0); if (out0 == 0) return true;\n            Box.Flags out1 = box.OutsideFlags(quad.P1); if (out1 == 0) return true;\n            Box.Flags out2 = box.OutsideFlags(quad.P2); if (out2 == 0) return true;\n            Box.Flags out3 = box.OutsideFlags(quad.P3); if (out3 == 0) return true;\n\n\n            /* ---------------------------------------------------------------\n                If all of the points of the Quad are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2 & out3) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n               If two points of the Quad are not on the same side\n               outside the box, it is possible that the edge between them\n               intersects the box. The outside flags we computed are also\n               used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(quad.P0, quad.P1, out0, out1)) return true;\n            if (box.IntersectsLine(quad.P1, quad.P2, out1, out2)) return true;\n            if (box.IntersectsLine(quad.P2, quad.P3, out2, out3)) return true;\n            if (box.IntersectsLine(quad.P3, quad.P0, out3, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n               The only case left: The Quad contains the the whole box\n               i.e. every point. When no triangle-line intersects the box and one\n               box point is inside the Quad the Quad must contain the box\n            --------------------------------------------------------------- */\n\n            return quad.Contains(box.Min);\n        }\n\n        #endregion\n\n        #region Quad2f intersects Quad2f\n\n        /// <summary>\n        /// returns true if the Quad2ds intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Quad2f q0,\n            Quad2f quad\n            )\n        {\n            if (q0.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (q0.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (q0.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (q0.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            if (q0.Contains(quad.P0)) return true;\n            if (quad.Contains(q0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region Polygon2f intersects Line2f\n\n        /// <summary>\n        /// returns true if the Polygon2f and the Line2f intersect or the Polygon contains the Line\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2f poly,\n            Line2f line\n            )\n        {\n            foreach (var l in poly.EdgeLines)\n            {\n                if (l.Intersects(line)) return true;\n            }\n\n            if (poly.Contains(line.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Polygon2f intersects Ray2f\n\n        /// <summary>\n        /// returns true if the Polygon2f and the Ray2f intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Polygon2f poly,\n            Ray2f ray\n            )\n        {\n            //UNTESTED\n            return ray.Plane2f.Divides(poly.Points);\n        }\n\n\n        #endregion\n\n        #region Polygon2f intersects Plane2f\n\n        /// <summary>\n        /// returns true if the Polygon2f and the Plane2f itnersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Polygon2f poly,\n            Plane2f plane\n            )\n        {\n            //UNTESTED\n            return plane.Divides(poly.Points);\n        }\n\n        #endregion\n\n        #region Polygon2f intersects Triangle2f\n\n        /// <summary>\n        /// returns true if the Polygon2f and the Triangle2f intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2f poly,\n            Triangle2f triangle\n            )\n        {\n            foreach (var line in poly.EdgeLines)\n            {\n                if (triangle.Intersects(line)) return true;\n            }\n\n            if (triangle.Contains(poly[0])) return true;\n            if (poly.Contains(triangle.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Polygon2f intersects Box2f\n\n        /// <summary>\n        /// returns true if the Polygon2f and the Box2f intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2f poly,\n            Box2f box\n            )\n        {\n            //UNTESTED\n            int count = poly.PointCount;\n            Box.Flags[] outFlags = new Box.Flags[count];\n\n            int i0 = 0;\n            foreach (var p in poly.Points) outFlags[i0++] = box.OutsideFlags(p);\n\n            i0 = 0;\n            int i1 = 1;\n            foreach (var l in poly.EdgeLines)\n            {\n                if (box.Intersects(l, outFlags[i0], outFlags[i1])) return true;\n\n                i0++;\n                i1 = (i1 + 1) % count;\n            }\n\n            if (box.Contains(poly[0])) return true;\n            if (poly.Contains(box.Min)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Polygon2f intersects Quad2f\n\n        /// <summary>\n        /// returns true if the Polygon2f and the Quad2f interset or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2f poly,\n            Quad2f quad\n            )\n        {\n            foreach (var l in poly.EdgeLines)\n            {\n                if (quad.Intersects(l)) return true;\n            }\n\n            if (quad.Contains(poly[0])) return true;\n            if (poly.Contains(quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Polygon2f intersects Polygon2f\n\n        /// <summary>\n        /// returns true if the Polygon2ds intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2f poly0,\n            Polygon2f poly1\n            )\n        {\n            //check if projected ranges intersect for all possible normals\n\n\n            V2f[] allnormals = new V2f[poly0.PointCount + poly1.PointCount];\n            int c = 0;\n\n            foreach (var d in poly0.Edges)\n            {\n                allnormals[c] = new V2f(-d.Y, d.X);\n                c++;\n            }\n            foreach (var d in poly1.Edges)\n            {\n                allnormals[c] = new V2f(-d.Y, d.X);\n                c++;\n            }\n\n\n\n            foreach (var n in allnormals)\n            {\n                var r0 = poly0.ProjectTo(n);\n                var r1 = poly1.ProjectTo(n);\n\n                if (!r0.Intersects(r1)) return false;\n            }\n\n            return true;\n        }\n\n        private static Range1f ProjectTo(this Polygon2f poly, V2f dir)\n        {\n            float min = float.MaxValue;\n            float max = float.MinValue;\n            foreach (var p in poly.Points)\n            {\n                float dotproduct = p.Dot(dir);\n\n                if (dotproduct < min) min = dotproduct;\n                if (dotproduct > max) max = dotproduct;\n            }\n\n            return new Range1f(min, max);\n        }\n\n        #endregion\n\n\n        #region Line3f intersects Line3f (haaser)\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Line3f l0,\n            Line3f l1\n            )\n        {\n            return l0.Intersects(l1, Constant<float>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than absoluteEpsilon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Line3f l0,\n            Line3f l1,\n            float absoluteEpsilon\n            )\n        {\n            if (l0.GetMinimalDistanceTo(l1) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than absoluteEpsilon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Line3f l0,\n            Line3f l1,\n            float absoluteEpsilon,\n            out V3f point\n            )\n        {\n            if (l0.GetMinimalDistanceTo(l1, out point) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region Line3f intersects Special (inconsistent argument order)\n\n        #region Line3f intersects Plane3f\n\n        /// <summary>\n        /// Returns true if the line and the plane intersect.\n        /// </summary>\n        public static bool Intersects(\n             this Line3f line, Plane3f plane, out float t\n             )\n        {\n            if (!line.Ray3f.Intersects(plane, out t)) return false;\n            if (t >= 0 && t <= 1) return true;\n            t = float.PositiveInfinity;\n            return false;\n\n        }\n\n        /// <summary>\n        /// Returns true if the line and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Line3f line, Plane3f plane, out float t, out V3f p\n             )\n        {\n            bool result = line.Intersects(plane, out t);\n            p = line.Origin + t * line.Direction;\n            return result;\n        }\n\n        #endregion\n\n        #region Line3f intersects Triangle3f\n\n        /// <summary>\n        /// Returns true if the line and the triangle intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Line3f line,\n            Triangle3f triangle\n            )\n        {\n            return line.Ray3f.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2, 0, 1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the line and the triangle intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool Intersects(\n            this Line3f line,\n            Triangle3f triangle,\n            out V3f point\n            )\n        {\n            Ray3f ray = line.Ray3f;\n\n            if (ray.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2, 0, 1, out float temp))\n            {\n                point = ray.GetPointOnRay(temp);\n                return true;\n            }\n            else\n            {\n                point = V3f.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #endregion\n\n\n        #region Ray3f intersects Line3f (haaser)\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than Constant&lt;float&gt;.PositiveTinyValue\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3f ray, Line3f line\n            )\n        {\n            return ray.Intersects(line, Constant<float>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than absoluteEpsilon\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3f ray, Line3f line,\n            float absoluteEpsilon\n            )\n        {\n            if (ray.GetMinimalDistanceTo(line) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than absoluteEpsilon\n        /// t holds the corresponding ray parameter\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3f ray, Line3f line,\n            float absoluteEpsilon,\n            out float t\n            )\n        {\n            if (ray.GetMinimalDistanceTo(line, out t) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region Ray3f intersects Ray3f (haaser)\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than Constant&lt;float&gt;.PositiveTinyValue\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3f r0,\n            Ray3f r1\n            )\n        {\n            return r0.Intersects(r1, out _, out _, Constant<float>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than Constant&lt;float&gt;.PositiveTinyValue\n        /// t0 and t1 hold the ray-parameters for the intersection\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3f r0,\n            Ray3f r1,\n            out float t0,\n            out float t1\n            )\n        {\n            return r0.Intersects(r1, out t0, out t1, Constant<float>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than absoluteEpsilon\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3f r0,\n            Ray3f r1,\n            float absoluteEpsilon\n            )\n        {\n            return r0.Intersects(r1, out _, out _, absoluteEpsilon);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than absoluteEpsilon\n        /// t0 and t1 hold the ray-parameters for the intersection\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3f r0,\n            Ray3f r1,\n            out float t0,\n            out float t1,\n            float absoluteEpsilon\n            )\n        {\n            if (r0.GetMinimalDistanceTo(r1, out t0, out t1) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region Ray3f intersects Special (inconsistent argument order)\n\n        #region Ray3f intersects Triangle3f\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3f ray, Triangle3f triangle)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                float.MinValue, float.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3f ray, Triangle3f triangle, float tmin, float tmax)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3f ray, Triangle3f triangle, float tmin, float tmax, out float t)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTriangle(this Ray3f ray, V3f p0, V3f p1, V3f p2, float tmin, float tmax)\n            => ray.IntersectsTriangle(p0, p1, p2, tmin, tmax, out float _);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        public static bool IntersectsTriangle(this Ray3f ray, V3f p0, V3f p1, V3f p2, float tmin, float tmax, out float t)\n        {\n            var edge01 = p1 - p0;\n            var edge02 = p2 - p0;\n            var plane = Vec.Cross(ray.Direction, edge02);\n            var det = Vec.Dot(edge01, plane);\n            if (det > -1E-4f && det < 1E-4f) { t = float.NaN; return false; }\n            //ray ~= parallel / Triangle\n            var tv = ray.Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            var u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) { t = float.NaN; return false; }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            var v = Vec.Dot(ray.Direction, plane) * det;\n            if (v < 0 || u + v > 1) { t = float.NaN; return false; }\n            var temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < tmin || temp_t >= tmax) { t = float.NaN; return false; }\n\n            t = temp_t;\n            return true;\n        }\n\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTrianglePointAndEdges(this Ray3f ray, V3f p0, V3f edge01, V3f edge02, float tmin, float tmax)\n            => ray.IntersectsTrianglePointAndEdges(p0, edge01, edge02, tmin, tmax, out _);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        public static bool IntersectsTrianglePointAndEdges(this Ray3f ray, V3f p0, V3f edge01, V3f edge02, float tmin, float tmax, out float t)\n        {\n            var plane = Vec.Cross(ray.Direction, edge02);\n            var det = Vec.Dot(edge01, plane);\n            if (det > -1E-4f && det < 1E-4f) { t = float.NaN; return false; }\n            //ray ~= parallel / Triangle\n            var tv = ray.Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            var u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) { t = float.NaN; return false; }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            var v = Vec.Dot(ray.Direction, plane) * det;\n            if (v < 0 || u + v > 1) { t = float.NaN; return false; }\n            var temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < tmin || temp_t >= tmax) { t = float.NaN; return false; }\n\n            t = temp_t;\n            return true;\n        }\n\n        #endregion\n\n        #region Ray3f intersects Quad3f\n\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3f ray, Quad3f quad)\n            => ray.Intersects(quad, float.MinValue, float.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the quad intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        public static bool Intersects(this Ray3f ray, Quad3f quad, float tmin, float tmax)\n        {\n            var edge02 = quad.P2 - quad.P0;\n            return ray.IntersectsTrianglePointAndEdges(quad.P0, quad.Edge01, edge02, tmin, tmax)\n                || ray.IntersectsTrianglePointAndEdges(quad.P0, edge02, quad.Edge03, tmin, tmax);\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the quad intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        public static bool IntersectsQuad(this Ray3f ray, V3f p0, V3f p1, V3f p2, V3f p3, float tmin, float tmax)\n        {\n            var edge02 = p2 - p0;\n            return ray.IntersectsTrianglePointAndEdges(p0, p1 - p0, edge02, tmin, tmax)\n                || ray.IntersectsTrianglePointAndEdges(p0, edge02, p3 - p0, tmin, tmax);\n        }\n\n        #endregion\n\n        #region Ray3f intersects Polygon3f (haaser)\n\n        /// <summary>\n        /// Returns true if the ray and the polygon intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3f ray, Polygon3f poly, float tmin, float tmax)\n            => ray.Intersects(poly, tmin, tmax, out _);\n\n        /// <summary>\n        /// Returns true if the ray and the polygon intersect within the\n        /// supplied parameter interval of the ray.\n        /// t holds the correspoinding paramter.\n        /// </summary>\n        public static bool Intersects(this Ray3f ray, Polygon3f poly, float tmin, float tmax, out float t)\n        {\n            var tris = poly.ComputeTriangulationOfConcavePolygon(1E-5f);\n            var count = tris.Length;\n\n            for (var i = 0; i < count; i += 3)\n            {\n                if (ray.IntersectsTriangle(poly[tris[i + 0]], poly[tris[i + 1]], poly[tris[i + 2]],\n                                           tmin, tmax, out t))\n                {\n                    return true;\n                }\n            }\n\n            t = float.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices, intersect within the\n        /// supplied parameter interval of the ray.\n        /// (The Method triangulates the polygon)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsPolygon(this Ray3f ray, V3f[] vertices, float tmin, float tmax)\n            => ray.Intersects(new Polygon3f(vertices), tmin, tmax);\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices and triangulation, intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        public static bool IntersectsPolygon(\n            this Ray3f ray,\n            V3f[] vertices,\n            int[] triangulation,\n            float tmin, float tmax\n            )\n        {\n            for (var i = 0; i < triangulation.Length; i += 3)\n            {\n                if (ray.IntersectsTriangle(vertices[triangulation[i + 0]],\n                                           vertices[triangulation[i + 1]],\n                                           vertices[triangulation[i + 2]], tmin, tmax)) return true;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices and triangulation, intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        public static bool Intersects(\n            this Ray3f ray,\n            Polygon3f polygon,\n            int[] triangulation,\n            float tmin, float tmax\n            )\n        {\n            for (var i = 0; i < triangulation.Length; i += 3)\n            {\n                if (ray.IntersectsTriangle(polygon[triangulation[i + 0]],\n                                           polygon[triangulation[i + 1]],\n                                           polygon[triangulation[i + 2]], tmin, tmax)) return true;\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region Ray3f intersects Sphere3f\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3f ray, Sphere3f sphere)\n            => ray.Intersects(sphere, float.MinValue, float.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3f.Hits method.\n        /// </summary>\n        public static bool Intersects(this Ray3f ray, Sphere3f sphere, float tmin, float tmax)\n        {\n            // calculate closest point\n            var t = ray.Direction.Dot(sphere.Center - ray.Origin) / ray.Direction.LengthSquared;\n            if (t < 0) t = 0;\n            if (t < tmin) t = tmin;\n            if (t > tmax) t = tmax;\n            V3f p = ray.Origin + t * ray.Direction;\n\n            // distance to sphere?\n            var d = (p - sphere.Center).LengthSquared;\n            if (d <= sphere.RadiusSquared)\n                return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Sphere3f intersects Triangle3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Sphere3f sphere, Triangle3f triangle\n             )\n        {\n            V3f v = sphere.Center.GetClosestPointOn(triangle) - sphere.Center;\n            return sphere.RadiusSquared >= v.LengthSquared;\n        }\n\n        #endregion\n\n        #endregion\n\n\n        #region Triangle3f intersects Line3f (haaser)\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3f tri,\n            Line3f line\n            )\n        {\n            return tri.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3f tri,\n            Line3f line,\n            out V3f point\n            )\n        {\n            return tri.IntersectsLine(line.P0, line.P1, out point);\n        }\n\n        /// <summary>\n        /// returns true if the triangle and the line, given by p0 and p1, intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Triangle3f tri,\n            V3f p0, V3f p1\n            )\n        {\n            V3f edge01 = tri.Edge01;\n            V3f edge02 = tri.Edge02;\n            V3f dir = p1 - p0;\n\n            V3f plane = Vec.Cross(dir, edge02);\n            float det = Vec.Dot(edge01, plane);\n            if (det > -1E-4f && det < 1E-4f)return false;\n            //ray ~= parallel / Triangle\n            V3f tv = p0 - tri.P0;\n            det = 1 / det;  // det is now inverse det\n            float u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1)\n            {\n                return false;\n            }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            float v = Vec.Dot(dir, plane) * det;\n            if (v < 0 || u + v > 1)\n            {\n                return false;\n            }\n            float temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < 0 || temp_t >= 1)\n            {\n                return false;\n            }\n\n            return true;\n        }\n\n        /// <summary>\n        /// returns true if the triangle and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Triangle3f tri,\n            V3f p0, V3f p1,\n            out V3f point\n            )\n        {\n            V3f edge01 = tri.Edge01;\n            V3f edge02 = tri.Edge02;\n            V3f dir = p1 - p0;\n\n            V3f plane = Vec.Cross(dir, edge02);\n            float det = Vec.Dot(edge01, plane);\n            if (det > -1E-4f && det < 1E-4f) { point = V3f.NaN; return false; }\n            //ray ~= parallel / Triangle\n            V3f tv = p0 - tri.P0;\n            det = 1 / det;  // det is now inverse det\n            float u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1)\n            {\n                point = V3f.NaN;\n                return false;\n            }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            float v = Vec.Dot(dir, plane) * det;\n            if (v < 0 || u + v > 1)\n            {\n                point = V3f.NaN;\n                return false;\n            }\n            float temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < 0 || temp_t >= 1)\n            {\n                point = V3f.NaN;\n                return false;\n            }\n\n            point = p0 + temp_t * dir;\n            return true;\n        }\n\n\n        #endregion\n\n        #region Triangle3f intersects Ray3f (haaser)\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3f tri,\n            Ray3f ray\n            )\n        {\n            return tri.Intersects(ray, float.MinValue, float.MaxValue, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect\n        /// within the given parameter interval\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3f tri,\n            Ray3f ray,\n            float tmin, float tmax\n            )\n        {\n            return tri.Intersects(ray, tmin, tmax, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect.\n        /// t holds the intersection paramter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3f tri,\n            Ray3f ray,\n            out float t\n            )\n        {\n            return tri.Intersects(ray, float.MinValue, float.MaxValue, out t);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect\n        /// within the given parameter interval\n        /// t holds the intersection paramter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3f tri,\n            Ray3f ray,\n            float tmin, float tmax,\n            out float t\n            )\n        {\n            return ray.Intersects(tri, tmin, tmax, out t);\n        }\n\n        #endregion\n\n        #region Triangle3f intersects Triangle3f (haaser)\n\n        /// <summary>\n        /// Returns true if the triangles intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Triangle3f t0,\n            Triangle3f t1\n            )\n        {\n            if (t0.IntersectsLine(t1.P0, t1.P1, out _)) return true;\n            if (t0.IntersectsLine(t1.P1, t1.P2, out _)) return true;\n            if (t0.IntersectsLine(t1.P2, t1.P0, out _)) return true;\n\n            if (t1.IntersectsLine(t0.P0, t0.P1, out _)) return true;\n            if (t1.IntersectsLine(t0.P1, t0.P2, out _)) return true;\n            if (t1.IntersectsLine(t0.P2, t0.P0, out _)) return true;\n\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the triangles intersect.\n        /// line holds the cutting-line of the two triangles.\n        /// </summary>\n        public static bool Intersects(\n            this Triangle3f t0,\n            Triangle3f t1,\n            out Line3f line\n            )\n        {\n            List<V3f> points = new List<V3f>();\n\n            if (t0.IntersectsLine(t1.P0, t1.P1, out V3f temp)) points.Add(temp);\n            if (t0.IntersectsLine(t1.P1, t1.P2, out temp)) points.Add(temp);\n            if (t0.IntersectsLine(t1.P2, t1.P0, out temp)) points.Add(temp);\n\n            if (points.Count == 2)\n            {\n                line = new Line3f(points[0], points[1]);\n                return true;\n            }\n\n            if (t1.IntersectsLine(t0.P0, t0.P1, out temp)) points.Add(temp);\n            if (t1.IntersectsLine(t0.P1, t0.P2, out temp)) points.Add(temp);\n            if (t1.IntersectsLine(t0.P2, t0.P0, out temp)) points.Add(temp);\n\n            if (points.Count == 2)\n            {\n                line = new Line3f(points[0], points[1]);\n                return true;\n            }\n\n            line = new Line3f(V3f.NaN, V3f.NaN);\n            return false;\n        }\n\n        #endregion\n\n\n        #region Quad3f intersects Line3f (haaser)\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3f quad,\n            Line3f line)\n        {\n            return quad.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3f quad,\n            Line3f line,\n            out V3f point)\n        {\n            return quad.IntersectsLine(line.P0, line.P1, out point);\n        }\n\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Quad3f quad,\n            V3f p0, V3f p1)\n        {\n            Ray3f ray = new Ray3f(p0, p1 - p0);\n            if (quad.Intersects(ray, 0, 1, out _))\n            {\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Quad3f quad,\n            V3f p0, V3f p1,\n            out V3f point)\n        {\n            Ray3f ray = new Ray3f(p0, p1 - p0);\n            if (quad.Intersects(ray, 0, 1, out float t))\n            {\n                point = ray.GetPointOnRay(t);\n                return true;\n            }\n            else\n            {\n                point = V3f.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Quad3f intersects Ray3f (haaser)\n\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3f quad,\n            Ray3f ray\n            )\n        {\n            return quad.Intersects(ray, float.MinValue, float.MaxValue, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect.\n        /// t holds the intersection parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3f quad,\n            Ray3f ray,\n            out float t\n            )\n        {\n            return quad.Intersects(ray, float.MinValue, float.MaxValue, out t);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect\n        /// within the given paramter range\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3f quad,\n            Ray3f ray,\n            float tmin, float tmax\n            )\n        {\n            return quad.Intersects(ray, tmin, tmax, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect\n        /// within the given paramter range\n        /// t holds the intersection parameter.\n        /// </summary>\n        public static bool Intersects(\n            this Quad3f quad,\n            Ray3f ray,\n            float tmin, float tmax,\n            out float t\n            )\n        {\n            V3f edge02 = quad.P2 - quad.P0;\n            if (ray.IntersectsTrianglePointAndEdges(quad.P0, quad.Edge01, edge02, tmin, tmax, out t)) return true;\n            if (ray.IntersectsTrianglePointAndEdges(quad.P0, edge02, quad.Edge03, tmin, tmax, out t)) return true;\n\n            t = float.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region Quad3f intersects Triangle3f (haaser)\n\n        /// <summary>\n        /// Returns true if the quad and the triangle intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Quad3f quad,\n            Triangle3f tri\n            )\n        {\n            if (quad.IntersectsLine(tri.P0, tri.P1)) return true;\n            if (quad.IntersectsLine(tri.P1, tri.P2)) return true;\n            if (quad.IntersectsLine(tri.P2, tri.P0)) return true;\n\n            if (tri.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (tri.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (tri.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (tri.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n\n        /// <summary>\n        /// Returns true if the quad and the triangle, given by p0/p1/p1, intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTriangle(\n            this Quad3f quad,\n            V3f p0, V3f p1, V3f p2\n            )\n        {\n            Triangle3f tri = new Triangle3f(p0, p1, p2);\n            return quad.Intersects(tri);\n        }\n\n        #endregion\n\n        #region Quad3f intersects Quad3f (haaser)\n\n        /// <summary>\n        /// Returns true if the given quads intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Quad3f q0,\n            Quad3f q1\n            )\n        {\n            if (q0.IntersectsTriangle(q1.P0, q1.P1, q1.P2)) return true;\n            if (q0.IntersectsTriangle(q1.P2, q1.P3, q1.P0)) return true;\n\n            if (q1.IntersectsTriangle(q0.P0, q0.P1, q0.P2)) return true;\n            if (q1.IntersectsTriangle(q0.P2, q0.P3, q0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region Plane3f intersects Line3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane3f plane, Line3f line)\n        {\n            return plane.IntersectsLine(line.P0, line.P1, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane3f plane, Line3f line, float absoluteEpsilon)\n        {\n            return plane.IntersectsLine(line.P0, line.P1, absoluteEpsilon);\n        }\n\n        public static bool IntersectsLine(this Plane3f plane, V3f p0, V3f p1, float absoluteEpsilon)\n        {\n            float h0 = plane.Height(p0);\n            int s0 = (h0 > absoluteEpsilon ? 1 :(h0 < -absoluteEpsilon ? -1 : 0));\n            if (s0 == 0) return true;\n\n            float h1 = plane.Height(p1);\n            int s1 = (h1 > absoluteEpsilon ? 1 : (h1 < -absoluteEpsilon ? -1 : 0));\n            if (s1 == 0) return true;\n\n\n            if (s0 == s1) return false;\n            else return true;\n        }\n\n        public static bool IntersectsLine(this Plane3f plane, V3f p0, V3f p1, float absoluteEpsilon, out V3f point)\n        {\n            //<n|origin + t0*dir> == d\n            //<n|or> + t0*<n|dir> == d\n            //t0 == (d - <n|or>) / <n|dir>;\n\n            V3f dir = p1 - p0;\n            float ld = dir.Length;\n            dir /= ld;\n\n            float nDotd = plane.Normal.Dot(dir);\n\n\n            if (!Fun.IsTiny(nDotd))\n            {\n                float t0 = (plane.Distance - plane.Normal.Dot(p0)) / nDotd;\n\n                if (t0 >= -absoluteEpsilon && t0 <= ld + absoluteEpsilon)\n                {\n                    point = p0 + dir * t0;\n                    return true;\n                }\n                else\n                {\n                    point = V3f.NaN;\n                    return false;\n                }\n            }\n            else\n            {\n                point = V3f.NaN;\n                return false;\n            }\n\n        }\n\n        #endregion\n\n        #region Plane3f intersects Ray3f\n\n        /// <summary>\n        /// Returns true if the Ray3f and the Plane3f intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3f ray, Plane3f plane)\n            => !plane.Normal.IsOrthogonalTo(ray.Direction);\n\n        /// <summary>\n        /// Returns true if the ray and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Ray3f ray, Plane3f plane, out float t\n             )\n        {\n            float dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot))\n            {\n                t = float.PositiveInfinity;\n                return false;\n            }\n            t = -plane.Height(ray.Origin) / dot;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns the intersection point with the given plane, or V3f.PositiveInfinity if ray is parallel to plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Intersect(\n             this Ray3f ray, Plane3f plane\n             )\n        {\n            float dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot)) return V3f.PositiveInfinity;\n            return ray.GetPointOnRay(-plane.Height(ray.Origin) / dot);\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Ray3f ray, Plane3f plane, out float t, out V3f p\n             )\n        {\n            bool result = Intersects(ray, plane, out t);\n            p = ray.Origin + t * ray.Direction;\n            return result;\n        }\n\n        #endregion\n\n        #region Plane3f intersects Plane3f\n\n        public static bool Intersects(this Plane3f p0, Plane3f p1)\n        {\n            bool parallel = p0.Normal.IsParallelTo(p1.Normal);\n\n            if (parallel) return Fun.IsTiny(p0.Distance - p1.Distance);\n            else return true;\n        }\n\n        public static bool Intersects(this Plane3f p0, Plane3f p1, out Ray3f ray)\n        {\n            V3f dir = p0.Normal.Cross(p1.Normal);\n            float len = dir.Length;\n\n            if (Fun.IsTiny(len))\n            {\n                if (Fun.IsTiny(p0.Distance - p1.Distance))\n                {\n                    ray = new Ray3f(p0.Normal * p0.Distance, V3f.Zero);\n                    return true;\n                }\n                else\n                {\n                    ray = Ray3f.Invalid;\n                    return false;\n                }\n            }\n\n            dir *= 1 / len;\n\n            var alu = new float[,]\n                { { p0.Normal.X, p0.Normal.Y, p0.Normal.Z },\n                  { p1.Normal.X, p1.Normal.Y, p1.Normal.Z },\n                  { dir.X, dir.Y, dir.Z } };\n\n            int[] p = alu.LuFactorize();\n\n            var b = new float[] { p0.Distance, p1.Distance, 0 };\n\n            var x = alu.LuSolve(p, b);\n\n            ray = new Ray3f(new V3f(x), dir);\n            return true;\n        }\n\n        #endregion\n\n        #region Plane3f intersects Plane3f intersects Plane3f\n\n        public static bool Intersects(this Plane3f p0, Plane3f p1, Plane3f p2, out V3f point)\n        {\n            var alu = new float[,]\n                { { p0.Normal.X, p0.Normal.Y, p0.Normal.Z },\n                  { p1.Normal.X, p1.Normal.Y, p1.Normal.Z },\n                  { p2.Normal.X, p2.Normal.Y, p2.Normal.Z } };\n\n            var p = new int[3];\n            if (!alu.LuFactorize(p)) { point = V3f.NaN; return false; }\n            var b = new float[] { p0.Distance, p1.Distance, p2.Distance };\n            var x = alu.LuSolve(p, b);\n            point = new V3f(x);\n            return true;\n        }\n\n        #endregion\n\n        #region Plane3f intersects Triangle3f\n\n        /// <summary>\n        /// Returns whether the given plane and triangle intersect.\n        /// </summary>\n        public static bool Intersects(\n             this Plane3f plane, Triangle3f triangle\n             )\n        {\n            int sign = plane.Sign(triangle.P0);\n            if (sign == 0) return true;\n            if (sign != plane.Sign(triangle.P1)) return true;\n            if (sign != plane.Sign(triangle.P2)) return true;\n            return false;\n        }\n\n        #endregion\n\n        #region Plane3f intersects Sphere3f\n\n        /// <summary>\n        /// Returns whether the given sphere and plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Plane3f plane, Sphere3f sphere\n             )\n        {\n            return sphere.Radius >= plane.Height(sphere.Center).Abs();\n        }\n\n        #endregion\n\n        #region Plane3f intersects Polygon3f\n\n        /// <summary>\n        /// returns true if the Plane3f and the Polygon3f intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Plane3f plane,\n            Polygon3f poly\n            )\n        {\n            return plane.Intersects(poly, Constant<float>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the Plane3f and the polygon, intersect\n        /// within a tolerance of absoluteEpsilon\n        /// </summary>\n        public static bool Intersects(\n            this Plane3f plane,\n            Polygon3f polygon,\n            float absoluteEpsilon\n            )\n        {\n            float height = plane.Height(polygon[0]);\n            int sign0 = height > -absoluteEpsilon ? (height < absoluteEpsilon ? 0 : 1) : -1; if (sign0 == 0) return true;\n            int pc = polygon.PointCount;\n            for (int i = 1; i < pc; i++)\n            {\n                height = plane.Height(polygon[i]);\n                int sign = height > -absoluteEpsilon ? (height < absoluteEpsilon ? 0 : 1) : -1;\n                if (sign != sign0) return true;\n            }\n\n            return false;\n        }\n\n\n        /// <summary>\n        /// returns true if the Plane3f and the Polygon3f intersect.\n        /// line holds the intersection line\n        /// ATTENTION: works only with non-concave polygons!\n        /// </summary>\n        public static bool IntersectsConvex(\n            this Plane3f plane,\n            Polygon3f poly,\n            out Line3f line\n            )\n        {\n            return plane.IntersectsConvex(poly, Constant<float>.PositiveTinyValue, out line);\n        }\n\n        /// <summary>\n        /// Returns true if the Plane3f and the polygon, given by points, intersect\n        /// within a tolerance of absoluteEpsilon.\n        /// Line holds the intersection line.\n        /// ATTENTION: works only with non-concave polygons!\n        /// </summary>\n        public static bool IntersectsConvex(\n            this Plane3f plane,\n            Polygon3f polygon,\n            float absoluteEpsilon,\n            out Line3f line\n            )\n        {\n            int count = polygon.PointCount;\n            int[] signs = new int[count];\n            int pc = 0, nc = 0, zc = 0;\n            for (int pi = 0; pi < count; pi++)\n            {\n                float h = plane.Height(polygon[pi]);\n                if (h < -absoluteEpsilon) { nc++; signs[pi] = -1; continue; }\n                if (h > absoluteEpsilon) { pc++; signs[pi] = 1; continue;  }\n                zc++; signs[pi] = 0;\n            }\n\n            if (zc == count)\n            {\n                line = new Line3f(polygon[0], polygon[0]);\n                return false;\n            }\n            else if (pc == 0 && zc == 0)\n            {\n                line = new Line3f(V3f.NaN, V3f.NaN);\n                return false;\n            }\n            else if (nc == 0 && zc == 0)\n            {\n                line = new Line3f(V3f.NaN, V3f.NaN);\n                return false;\n            }\n            else\n            {\n                int pointcount = 0;\n                V3f[] linePoints = new V3f[2];\n                for (int i = 0; i < count; i++)\n                {\n                    int u = (i + 1) % count;\n\n                    if (signs[i] != signs[u] || signs[i] == 0 || signs[u] == 0)\n                    {\n                        if (plane.IntersectsLine(polygon[i], polygon[u], absoluteEpsilon, out V3f point))\n                        {\n                            linePoints[pointcount++] = point;\n                            //If Endpoint is on Plane => Next startpoint is on plane => same intersection point\n                            // => skip all following lines which start within absoluteEpsilon (whic have a zero sign)\n                            while (signs[(i + 1) % count] == 0) i++;\n                        }\n                    }\n                    if (pointcount == 2)\n                    {\n                        //\n                        line = new Line3f(linePoints[0], linePoints[1]);\n                        return true;\n                    }\n                }\n                line = new Line3f(V3f.NaN, V3f.NaN);\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Plane3f intersects Cylinder3f\n\n        /// <summary>\n        /// Returns whether the given sphere and cylinder intersect.\n        /// </summary>\n        public static bool Intersects(this Plane3f plane, Cylinder3f cylinder)\n        {\n            if (plane.IsParallelToAxis(cylinder))\n            {\n                var distance = cylinder.P0.GetMinimalDistanceTo(plane);\n                return distance < cylinder.Radius;\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Tests if the given plane is parallel to the cylinder axis (i.e. the plane's normal is orthogonal to the axis).\n        /// The plane will intersect the cylinder in two rays or in one tangent line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelToAxis(this Plane3f plane, Cylinder3f cylinder)\n            => plane.Normal.IsOrthogonalTo(cylinder.Axis.Direction.Normalized);\n\n        /// <summary>\n        /// Tests if the given plane is orthogonal to the cylinder axis (i.e. the plane's normal is parallel to the axis).\n        /// The plane will intersect the cylinder in a circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalToAxis(this Plane3f plane, Cylinder3f cylinder)\n            => plane.Normal.IsParallelTo(cylinder.Axis.Direction.Normalized);\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in an ellipse.\n        /// This is only true if the plane is neither orthogonal nor parallel to the cylinder axis. Otherwise the intersection methods returning a circle or rays have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"ellipse\"></param>\n        public static bool Intersects(this Plane3f plane, Cylinder3f cylinder, out Ellipse3f ellipse)\n        {\n            if (plane.IsParallelToAxis(cylinder) || plane.IsOrthogonalToAxis(cylinder))\n            {\n                ellipse = Ellipse3f.Zero;\n                return false;\n            }\n\n            var dir = cylinder.Axis.Direction.Normalized;\n            cylinder.Axis.Ray3f.Intersects(plane, out _, out V3f center);\n            var cosTheta = dir.Dot(plane.Normal);\n\n            var eNormal = plane.Normal;\n            var eCenter = center;\n            var eMajor = (dir - cosTheta * eNormal).Normalized;\n            var eMinor = (eNormal.Cross(eMajor)).Normalized;\n            eMajor = eNormal.Cross(eMinor).Normalized; //to be sure - if ellipse is nearly a circle\n            eMajor = eMajor * cylinder.Radius / cosTheta.Abs();\n            eMinor *= cylinder.Radius;\n            ellipse = new Ellipse3f(eCenter, eNormal, eMajor, eMinor);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in a circle.\n        /// This is only true if the plane is orthogonal to the cylinder axis. Otherwise the intersection methods returning an ellipse or rays have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"circle\"></param>\n        public static bool Intersects(this Plane3f plane, Cylinder3f cylinder, out Circle3f circle)\n        {\n            if (plane.IsOrthogonalToAxis(cylinder))\n            {\n                circle = cylinder.GetCircle(cylinder.GetHeight(plane.Point));\n                return true;\n            }\n\n            circle = Circle3f.Zero;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in one or two rays.\n        /// This is only true if the plane is parallel to the cylinder axis. Otherwise the intersection methods returning an ellipse or a circle have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"rays\">Output of intersection rays. The array contains two rays (intersection), one ray (plane is tangent to cylinder) or no ray (no intersection).</param>\n        public static bool Intersects(this Plane3f plane, Cylinder3f cylinder, out Ray3f[] rays)\n        {\n            if (plane.IsParallelToAxis(cylinder))\n            {\n                var distance = cylinder.P0.GetMinimalDistanceTo(plane);\n                var center = cylinder.P0 - distance * plane.Normal;\n                var axis = cylinder.Axis.Direction.Normalized;\n\n                if (distance == cylinder.Radius) //one tangent line\n                {\n                    rays = new[] { new Ray3f(center, axis) };\n                    return true;\n                }\n                else //two intersection lines\n                {\n                    var offset = axis.Cross(plane.Normal);\n                    var extent = (cylinder.Radius.Square() - distance.Square()).Sqrt();\n                    rays = new[]\n                    {\n                        new Ray3f(center - extent * offset, axis),\n                        new Ray3f(center + extent * offset, axis)\n                    };\n                    return true;\n                }\n            }\n            rays = Array.Empty<Ray3f>();\n            return false;\n        }\n\n        #endregion\n\n\n        #region Sphere3f intersects Sphere3f (sm)\n\n        /// <summary>\n        /// Returns true if the spheres intersect, or one contains the other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Sphere3f s0, Sphere3f s1)\n            => (s0.Center - s1.Center).LengthSquared <= (s0.Radius + s1.Radius).Square();\n\n        #endregion\n\n\n        #region Box3f intersects Line3f\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool Intersects(this Box3f box, Line3f line)\n        {\n            var out0 = box.OutsideFlags(line.P0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(line.P1); if (out1 == 0) return true;\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n                this Box3f box, V3f p0, V3f p1)\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            return box.IntersectsLine(p0, p1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied, and have to be already individually tested against\n        /// intersection with the box.\n        /// </summary>\n        public static bool IntersectsLine(\n                this Box3f box, V3f p0, V3f p1, Box.Flags out0, Box.Flags out1)\n        {\n            if ((out0 & out1) != 0) return false;\n\n            V3f min = box.Min;\n            V3f max = box.Max;\n            var bf = out0 | out1;\n\n            if ((bf & Box.Flags.X) != 0)\n            {\n                float dx = p1.X - p0.X;\n                if ((bf & Box.Flags.MinX) != 0)\n                {\n                    if (dx == 0 && p0.X < min.X) return false;\n                    float t = (min.X - p0.X) / dx;\n                    V3f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinX) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxX) != 0)\n                {\n                    if (dx == 0 && p0.X > max.X) return false;\n                    float t = (max.X - p0.X) / dx;\n                    V3f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxX) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Y) != 0)\n            {\n                float dy = p1.Y - p0.Y;\n                if ((bf & Box.Flags.MinY) != 0)\n                {\n                    if (dy == 0 && p0.Y < min.Y) return false;\n                    float t = (min.Y - p0.Y) / dy;\n                    V3f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinY) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxY) != 0)\n                {\n                    if (dy == 0 && p0.Y > max.Y) return false;\n                    float t = (max.Y - p0.Y) / dy;\n                    V3f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxY) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Z) != 0)\n            {\n                float dz = p1.Z - p0.Z;\n                if ((bf & Box.Flags.MinZ) != 0)\n                {\n                    if (dz == 0 && p0.Z < min.Z) return false;\n                    float t = (min.Z - p0.Z) / dz;\n                    V3f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinZ) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxZ) != 0)\n                {\n                    if (dz == 0 && p0.Z > max.Z) return false;\n                    float t = (max.Z - p0.Z) / dz;\n                    V3f p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxZ) == 0)\n                        return true;\n                }\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region Box3f intersects Ray3f (haaser)\n\n        public static bool Intersects(this Box3f box, Ray3f ray, out float t)\n        {\n            Box.Flags out0 = box.OutsideFlags(ray.Origin);\n\n            if (out0 == 0)\n            {\n                t = 0;\n                return true;\n            }\n\n            Box3f largeBox = box.EnlargedByRelativeEps(1E-5f);\n            float tmin = float.PositiveInfinity;\n            float ttemp;\n            if ((out0 & Box.Flags.X) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.X))\n                {\n                    if ((out0 & Box.Flags.MinX) != 0)\n                    {\n                        ttemp = (box.Min.X - ray.Origin.X) / ray.Direction.X;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxX) != 0)\n                    {\n                        ttemp = (box.Max.X - ray.Origin.X) / ray.Direction.X;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if ((out0 & Box.Flags.Y) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.Y))\n                {\n                    if ((out0 & Box.Flags.MinY) != 0)\n                    {\n                        ttemp = (box.Min.Y - ray.Origin.Y) / ray.Direction.Y;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxY) != 0)\n                    {\n                        ttemp = (box.Max.Y - ray.Origin.Y) / ray.Direction.Y;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if ((out0 & Box.Flags.Z) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.Z))\n                {\n                    if ((out0 & Box.Flags.MinZ) != 0)\n                    {\n                        ttemp = (box.Min.Z - ray.Origin.Z) / ray.Direction.Z;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxZ) != 0)\n                    {\n                        ttemp = (box.Max.Z - ray.Origin.Z) / ray.Direction.Z;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if (tmin < float.PositiveInfinity)\n            {\n                t = tmin;\n                return true;\n            }\n\n            t = float.NaN;\n            return false;\n        }\n\n\n        #endregion\n\n        #region Box3f intersects Plane3f\n\n        /// <summary>\n        /// Returns true if the box and the plane intersect or touch with a\n        /// supplied epsilon tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Box3f box, Plane3f plane, float eps)\n        {\n            var signs = box.GetIntersectionSignsWithPlane(plane, eps);\n            return signs != Signs.Negative && signs != Signs.Positive;\n        }\n\n        /// <summary>\n        /// Classify the position of all the eight vertices of a box with\n        /// respect to a supplied plane.\n        /// </summary>\n        public static Signs GetIntersectionSignsWithPlane(\n            this Box3f box, Plane3f plane, float eps)\n        {\n            var normal = plane.Normal;\n            var distance = plane.Distance;\n\n            float npMinX = normal.X * box.Min.X;\n            float npMaxX = normal.X * box.Max.X;\n            float npMinY = normal.Y * box.Min.Y;\n            float npMaxY = normal.Y * box.Max.Y;\n            float npMinZ = normal.Z * box.Min.Z;\n            float npMaxZ = normal.Z * box.Max.Z;\n\n            float hMinZ = npMinZ - distance;\n            float hMaxZ = npMaxZ - distance;\n\n            float hMinYMinZ = npMinY + hMinZ;\n            float hMaxYMinZ = npMaxY + hMinZ;\n            float hMinYMaxZ = npMinY + hMaxZ;\n            float hMaxYMaxZ = npMaxY + hMaxZ;\n\n            return (npMinX + hMinYMinZ).GetSigns(eps)\n                 | (npMaxX + hMinYMinZ).GetSigns(eps)\n                 | (npMinX + hMaxYMinZ).GetSigns(eps)\n                 | (npMaxX + hMaxYMinZ).GetSigns(eps)\n                 | (npMinX + hMinYMaxZ).GetSigns(eps)\n                 | (npMaxX + hMinYMaxZ).GetSigns(eps)\n                 | (npMinX + hMaxYMaxZ).GetSigns(eps)\n                 | (npMaxX + hMaxYMaxZ).GetSigns(eps);\n        }\n\n        /// <summary>\n        /// Returns true if the box intersects the supplied plane. The\n        /// bounding boxes of the resulting parts are returned in the out\n        /// parameters.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Signs GetIntersectionSigns(\n                this Box3f box, Plane3f plane, float eps,\n                out Box3f negBox, out Box3f zeroBox, out Box3f posBox)\n        {\n            return box.GetIntersectionSigns(plane.Normal, plane.Distance, eps,\n                                       out negBox, out zeroBox, out posBox);\n        }\n\n        /// <summary>\n        /// Returns true if the box intersects the supplied plane. The\n        /// bounding boxes of the resulting parts are returned in the out\n        /// parameters.\n        /// </summary>\n        public static Signs GetIntersectionSigns(\n                this Box3f box, V3f normal, float distance, float eps,\n                out Box3f negBox, out Box3f zeroBox, out Box3f posBox)\n        {\n            float npMinX = normal.X * box.Min.X;\n            float npMaxX = normal.X * box.Max.X;\n            float npMinY = normal.Y * box.Min.Y;\n            float npMaxY = normal.Y * box.Max.Y;\n            float npMinZ = normal.Z * box.Min.Z;\n            float npMaxZ = normal.Z * box.Max.Z;\n\n            var ha = new float[8];\n\n            float hMinZ = npMinZ - distance;\n            float hMaxZ = npMaxZ - distance;\n\n            float hMinYMinZ = npMinY + hMinZ;\n            ha[0] = npMinX + hMinYMinZ;\n            ha[1] = npMaxX + hMinYMinZ;\n\n            float hMaxYMinZ = npMaxY + hMinZ;\n            ha[2] = npMinX + hMaxYMinZ;\n            ha[3] = npMaxX + hMaxYMinZ;\n\n            float hMinYMaxZ = npMinY + hMaxZ;\n            ha[4] = npMinX + hMinYMaxZ;\n            ha[5] = npMaxX + hMinYMaxZ;\n\n            float hMaxYMaxZ = npMaxY + hMaxZ;\n            ha[6] = npMinX + hMaxYMaxZ;\n            ha[7] = npMaxX + hMaxYMaxZ;\n\n            Signs all = Signs.None;\n            var sa = new Signs[8];\n            for (int i = 0; i < 8; i++) { sa[i] = ha[i].GetSigns(eps); all |= sa[i]; }\n\n            negBox = Box3f.Invalid;\n            zeroBox = Box3f.Invalid;\n            posBox = Box3f.Invalid;\n\n            if (all == Signs.Zero) { zeroBox = box; return all; }\n            if (all == Signs.Positive) { posBox = box; return all; }\n            if (all == Signs.Negative) { negBox = box; return all; }\n\n            var pa = box.ComputeCorners();\n\n            for (int i = 0; i < 8; i++)\n            {\n                if (sa[i] == Signs.Negative)\n                    negBox.ExtendBy(pa[i]);\n                else if (sa[i] == Signs.Positive)\n                    posBox.ExtendBy(pa[i]);\n                else\n                {\n                    negBox.ExtendBy(pa[i]);\n                    zeroBox.ExtendBy(pa[i]);\n                    posBox.ExtendBy(pa[i]);\n                }\n            }\n\n            if (all == Signs.NonPositive) { posBox = Box3f.Invalid; return all; }\n            if (all == Signs.NonNegative) { negBox = Box3f.Invalid; return all; }\n\n            for (int ei = 0; ei < 12; ei++)\n            {\n                int i0 = c_cubeEdgeVertex0[ei], i1 = c_cubeEdgeVertex1[ei];\n\n                if ((sa[i0] == Signs.Negative && sa[i1] == Signs.Positive)\n                    || (sa[i0] == Signs.Positive && sa[i1] == Signs.Negative))\n                {\n                    float h0 = ha[i0];\n                    float t = h0 / (h0 - ha[i1]);\n                    V3f p0 = pa[i0];\n                    V3f sp = p0 + t * (pa[i1] - p0);\n                    negBox.ExtendBy(sp);\n                    zeroBox.ExtendBy(sp);\n                    posBox.ExtendBy(sp);\n                }\n            }\n\n            return all;\n        }\n\n        #endregion\n\n        #region Box3f intersects Sphere3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Box3f box, Sphere3f sphere\n             )\n        {\n            V3f v = sphere.Center.GetClosestPointOn(box) - sphere.Center;\n            return sphere.RadiusSquared >= v.LengthSquared;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Box3f box, Cylinder3f cylinder\n             )\n        {\n\n            return box.Intersects(cylinder.BoundingBox3f);\n\n            //throw new NotImplementedException();\n        }\n\n        #endregion\n\n        #region Box3f intersects Triangle3f\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Box3f box, Triangle3f triangle\n             )\n        {\n            return box.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect.\n        /// </summary>\n        public static bool IntersectsTriangle(\n             this Box3f box, V3f p0, V3f p1, V3f p2\n             )\n        {\n            /* ---------------------------------------------------------------\n               If one of the points of the triangle is inside the box, it\n               intersects, of course.\n            --------------------------------------------------------------- */\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n            return box.IntersectsTriangle(p0, p1, p2, out0, out1, out2);\n        }\n\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect. The outside\n        /// flags of the triangle vertices with respect to the box have to be\n        /// supplied, and already be individually tested for intersection with\n        /// the box.\n        /// </summary>\n        public static bool IntersectsTriangle(\n             this Box3f box, V3f p0, V3f p1, V3f p2,\n             Box.Flags out0, Box.Flags out1, Box.Flags out2\n             )\n        {\n            /* ---------------------------------------------------------------\n                If all of the points of the triangle are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2) != 0) return false;\n\n            /* ---------------------------------------------------------------\n                If two points of the triangle are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p0, out2, out0)) return true;\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the triangle go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n            --------------------------------------------------------------- */\n            Ray3f ray = new Ray3f(box.Min, box.Size);\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Box3f intersects Quad3f (haaser)\n\n        public static bool Intersects(\n            this Box3f box, Quad3f quad\n            )\n        {\n            Box.Flags out0 = box.OutsideFlags(quad.P0); if (out0 == 0) return true;\n            Box.Flags out1 = box.OutsideFlags(quad.P1); if (out1 == 0) return true;\n            Box.Flags out2 = box.OutsideFlags(quad.P2); if (out2 == 0) return true;\n            Box.Flags out3 = box.OutsideFlags(quad.P3); if (out3 == 0) return true;\n\n            return box.IntersectsQuad(quad.P0, quad.P1, quad.P2, quad.P3, out0, out1, out2, out3);\n        }\n\n        public static bool IntersectsQuad(\n             this Box3f box, V3f p0, V3f p1, V3f p2, V3f p3\n             )\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n            var out3 = box.OutsideFlags(p3); if (out3 == 0) return true;\n\n            return box.IntersectsQuad(p0, p1, p2, p3, out0, out1, out2, out3);\n        }\n\n        public static bool IntersectsQuad(\n            this Box3f box, V3f p0, V3f p1, V3f p2, V3f p3,\n            Box.Flags out0, Box.Flags out1, Box.Flags out2, Box.Flags out3\n            )\n        {\n            /* ---------------------------------------------------------------\n                If all of the points of the quad are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2 & out3) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n                If two points of the quad are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p3, out2, out3)) return true;\n            if (box.IntersectsLine(p3, p0, out3, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the quad go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n            --------------------------------------------------------------- */\n            Ray3f ray = new Ray3f(box.Min, box.Size);\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Box3f intersects Polygon3f (haaser)\n\n        public static bool Intersects(this Box3f box, Polygon3f poly)\n        {\n            int edges = poly.PointCount;\n            Box.Flags[] outside = new Box.Flags[edges];\n            for (int i = 0; i < edges; i++)\n            {\n                outside[i] = box.OutsideFlags(poly[i]); if (outside[i] == 0) return true;\n            }\n\n            /* ---------------------------------------------------------------\n                If all of the points of the polygon are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            Box.Flags sum = outside[0];\n            for (int i = 1; i < edges; i++) sum &= outside[i];\n            if (sum != 0) return false;\n\n            /* ---------------------------------------------------------------\n                If two points of the polygon are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            int u;\n            for (int i = 0; i < edges; i++)\n            {\n                u = (i + 1) % edges;\n                if (box.IntersectsLine(poly[i], poly[u], outside[i], outside[u])) return true;\n            }\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the polygon go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n                The polygon needs to be triangulated for this check\n            --------------------------------------------------------------- */\n\n            int[] tris = poly.ComputeTriangulationOfConcavePolygon(1E-5f);\n\n            Ray3f ray = new Ray3f(box.Min, box.Size);\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Box3f intersects Projection-Trafo (haaser)\n\n        /// <summary>\n        /// returns true if the Box3f and the frustum described by the M44f intersect or the frustum contains the Box3f\n        /// Assumes DirectX clip-space:\n        ///     -w &lt; x &lt; w\n        ///     -w &lt; y &lt; w\n        ///      0 &lt; z &lt; w\n        /// </summary>\n        public static bool IntersectsFrustum(this Box3f box, M44f projection)\n        {\n            //Let's look at the left clip-plane\n            //which corresponds to:\n            //-w < x\n            //  # which can easily be transformed to:\n            //0 < x + w\n            //  # for a given vector v this means (* is a dot product here)\n            //0 < proj.R0 * v + proj.R3 * v\n            //  # or in other words:\n            //0 < (proj.R0 + proj.R3) * v\n\n            //therefore (proj.R0 + proj.R3) is the plane describing the left clip-plane.\n            //The other planes can be derived in a similar way (only the near plane is a little different)\n            //see http://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/ for a full explanation\n\n            var r0 = projection.R0;\n            var r1 = projection.R1;\n            var r2 = projection.R2;\n            var r3 = projection.R3;\n\n\n            V4f plane;\n            V3f n;\n\n            //left\n            plane = r3 + r0;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out V3f min, out V3f max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //right\n            plane = r3 - r0;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //top\n            plane = r3 + r1;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //bottom\n            plane = r3 - r1;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //near\n            plane = r2;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //far\n            plane = r3 - r2;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n\n            return true;\n        }\n\n\n\n        #endregion\n\n\n        #region Hull3f intersects Line3f\n\n        /// <summary>\n        /// returns true if the Hull3f and the Line3f intersect or the Hull3f contains the Line3f\n        /// [Hull3f-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Hull3f hull,\n            Line3f line\n            )\n        {\n            if (hull.Contains(line.P0)) return true;\n            if (hull.Contains(line.P1)) return true;\n\n            return hull.Intersects(line.Ray3f, 0, 1, out _);\n        }\n\n        /// <summary>\n        /// returns true if the Hull3f and the Line between p0 and p1 intersect or the Hull3f contains the Line\n        /// [Hull3f-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this Hull3f hull,\n            V3f p0, V3f p1\n            )\n        {\n            return hull.Intersects(new Line3f(p0, p1));\n        }\n\n        #endregion\n\n        #region Hull3f intersects Ray3f\n\n        /// <summary>\n        /// returns true if the Hull3f and the Ray3f intersect\n        /// [Hull3f-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Hull3f hull,\n            Ray3f ray\n            )\n        {\n            return hull.Intersects(ray, float.NegativeInfinity, float.PositiveInfinity, out _);\n        }\n\n        /// <summary>\n        /// returns true if the Hull3f and the Ray3f intersect\n        /// the out parameter t holds the ray-parameter where an intersection was found\n        /// [Hull3f-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Hull3f hull,\n            Ray3f ray,\n            out float t\n            )\n        {\n            return hull.Intersects(ray, float.NegativeInfinity, float.PositiveInfinity, out t);\n        }\n\n        /// <summary>\n        /// returns true if the Hull3f and the Ray3f intersect and the\n        /// ray-parameter for the intersection is between t_min and t_max\n        /// the out parameter t holds the ray-parameter where an intersection was found\n        /// [Hull3f-Normals must point outside]\n        /// </summary>\n        public static bool Intersects(\n            this Hull3f hull,\n            Ray3f ray,\n            float t_min, float t_max,\n            out float t\n            )\n        {\n            if (!float.IsInfinity(t_min) && hull.Contains(ray.GetPointOnRay(t_min))) { t = t_min; return true; }\n            if (!float.IsInfinity(t_max) && hull.Contains(ray.GetPointOnRay(t_max))) { t = t_max; return true; }\n\n            var planes = hull.PlaneArray;\n            for (int i = 0; i < planes.Length; i++)\n            {\n                if (!Fun.IsTiny(planes[i].Normal.Dot(ray.Direction)) &&\n                    ray.Intersects(planes[i], out float temp_t) &&\n                    temp_t >= t_min && temp_t <= t_max)\n                {\n                    V3f candidatePoint = ray.GetPointOnRay(temp_t);\n                    bool contained = true;\n\n                    for (int u = 0; u < planes.Length; u++)\n                    {\n                        if (u != i && planes[u].Height(candidatePoint) > Constant<float>.PositiveTinyValue)\n                        {\n                            contained = false;\n                            break;\n                        }\n                    }\n\n                    if (contained)\n                    {\n                        t = temp_t;\n                        return true;\n                    }\n                }\n            }\n\n            t = float.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region Hull3f intersects Plane3f\n\n        /// <summary>\n        /// returns true if the Hull3f and the Plane3f intersect\n        /// [Hull3f-Normals must point outside]\n        /// </summary>\n        public static bool Intersects(\n            this Hull3f hull,\n            Plane3f plane\n            )\n        {\n            foreach (var p in hull.PlaneArray)\n            {\n                if (!p.Normal.IsParallelTo(plane.Normal) && p.Intersects(plane, out Ray3f ray))\n                {\n                    if (hull.Intersects(ray)) return true;\n                }\n            }\n\n            return false;\n        }\n\n        #endregion\n\n        #region Hull3f intersects Box3f\n\n        /// <summary>\n        /// Returns true if the hull and the box intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Hull3f hull, Box3f box\n            )\n        {\n            if (box.IsInvalid) return false;\n            bool intersecting = false;\n            foreach (Plane3f p in hull.PlaneArray)\n            {\n                box.GetMinMaxInDirection(p.Normal, out V3f min, out V3f max);\n                if (p.Height(min) > 0) return false; // outside\n                if (p.Height(max) >= 0) intersecting = true;\n            }\n            if (intersecting) return true; // intersecting\n            return true; // inside\n        }\n\n        /// Test hull against intersection of the supplied bounding box.\n        /// Note that this is a conservative test, since in some cases\n        /// around the edges of the hull it may return true although the\n        /// hull does not intersect the box.\n        public static bool Intersects(\n                this FastHull3f fastHull,\n                Box3f box)\n        {\n            var planes = fastHull.Hull.PlaneArray;\n            int count = planes.Length;\n            bool intersecting = false;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCornerIndex = fastHull.MinCornerIndexArray[pi];\n                if (planes[pi].Height(box.Corner(minCornerIndex)) > 0)\n                    return false;\n                if (planes[pi].Height(box.Corner(minCornerIndex ^ 7)) >= 0)\n                    intersecting = true;\n            }\n            if (intersecting) return true;\n            return true;\n        }\n\n        #endregion\n\n        #region Hull3f intersects Sphere3f\n\n        /// <summary>\n        /// Returns true if the hull and the sphere intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Hull3f hull, Sphere3f sphere\n            )\n        {\n            if (sphere.IsInvalid) return false;\n            bool intersecting = false;\n            foreach (Plane3f p in hull.PlaneArray)\n            {\n                float height = p.Height(sphere.Center);\n                if (height > sphere.Radius) return false; // outside\n                if (height.Abs() < sphere.Radius) intersecting = true;\n            }\n            if (intersecting) return true; // intersecting\n            return true; // inside\n        }\n\n        #endregion\n\n\n        #region Plane3f intersects Box3f\n\n        /// <summary>\n        /// Returns true if the box and the plane intersect or touch with a\n        /// supplied epsilon tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane3f plane, float eps, Box3f box)\n            => box.Intersects(plane, eps);\n\n        #endregion\n\n        // Contains-tests should return true if the contained object is\n        // either entirely inside the containing object or lies on the\n        // boundary of the containing object.\n\n        #region Triangle2d contains V2d\n\n        public static bool Contains(\n            this Triangle2d triangle, V2d point\n            )\n        {\n            var v0p = point - triangle.P0;\n            return triangle.Line01.LeftValueOfDir(v0p) >= 0\n                    && triangle.Line02.RightValueOfDir(v0p) >= 0\n                    && triangle.Line12.LeftValueOfPos(point) >= 0;\n        }\n\n        #endregion\n\n        #region Triangle2d contains Line2d (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Triangle2d triangle, Line2d linesegment)\n            => triangle.Contains(linesegment.P0) && triangle.Contains(linesegment.P1);\n\n        #endregion\n\n        #region Triangle2d contains Triangle2d (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Triangle2d triangle, Triangle2d other)\n            => triangle.Contains(other.P0) && triangle.Contains(other.P1) && triangle.Contains(other.P2);\n\n        #endregion\n\n        #region Triangle2d contains Quad2d (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Triangle2d triangle, Quad2d q)\n            => triangle.Contains(q.P0) && triangle.Contains(q.P1) && triangle.Contains(q.P2) && triangle.Contains(q.P3);\n\n        #endregion\n\n        #region Triangle2d contains Circle2d\n\n        public static bool Contains(this Triangle2d triangle, Circle2d circle)\n        {\n            var center = circle.Center;\n            return triangle.Contains(center)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line01)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line12)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line20);\n        }\n\n        #endregion\n\n\n        #region Circle2d contains V2d (sm)\n\n        /// <summary>\n        /// True if point p is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2d circle, V2d p)\n            => (p - circle.Center).LengthSquared <= circle.RadiusSquared;\n\n        #endregion\n\n        #region Circle2d contains Line2d (sm)\n\n        /// <summary>\n        /// True if line segment is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2d circle, Line2d l)\n            => circle.Contains(l.P0) && circle.Contains(l.P1);\n\n        #endregion\n\n        #region Circle2d contains Triangle2d (sm)\n\n        /// <summary>\n        /// True if triangle is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2d circle, Triangle2d t)\n            => circle.Contains(t.P0) && circle.Contains(t.P1) && circle.Contains(t.P2);\n\n        #endregion\n\n        #region Circle2d contains Quad2d (sm)\n\n        /// <summary>\n        /// True if quad is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2d circle, Quad2d q)\n            => circle.Contains(q.P0) && circle.Contains(q.P1) && circle.Contains(q.P2) && circle.Contains(q.P3);\n\n        #endregion\n\n        #region Circle2d contains Circle2d (sm)\n\n        /// <summary>\n        /// True if other circle is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Circle2d circle, Circle2d other)\n            => (other.Center - circle.Center).Length + other.Radius <= circle.Radius;\n\n        #endregion\n\n\n        #region Quad2d contains V2d (haaser)\n\n        /// <summary>\n        /// True if point is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2d quad, V2d point)\n        {\n            return LeftValOfPos(0, 1, ref point) >= 0 &&\n                   LeftValOfPos(1, 2, ref point) >= 0 &&\n                   LeftValOfPos(2, 3, ref point) >= 0 &&\n                   LeftValOfPos(3, 0, ref point) >= 0;\n\n            double LeftValOfPos(int i0, int i1, ref V2d p)\n                => (p.X - quad[i0].X) * (quad[i0].Y - quad[i1].Y) + (p.Y - quad[i0].Y) * (quad[i1].X - quad[i0].X);\n        }\n\n        #endregion\n\n        #region Quad2d contains Line2d\n\n        /// <summary>\n        /// True if line segment is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2d quad, Line2d l)\n            => quad.Contains(l.P0) && quad.Contains(l.P1);\n\n        #endregion\n\n        #region Quad2d contains Triangle2d\n\n        /// <summary>\n        /// True if triangle is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2d quad, Triangle2d t)\n            => quad.Contains(t.P0) && quad.Contains(t.P1) && quad.Contains(t.P2);\n\n        #endregion\n\n        #region Quad2d contains Quad2d\n\n        /// <summary>\n        /// True if other quad is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2d quad, Quad2d q)\n            => quad.Contains(q.P0) && quad.Contains(q.P1) && quad.Contains(q.P2) && quad.Contains(q.P3);\n\n        #endregion\n\n        #region Quad2d contains Circle2d\n\n        /// <summary>\n        /// True if circle is contained in this quad.\n        /// </summary>\n        public static bool Contains(this Quad2d quad, Circle2d circle)\n        {\n            var center = circle.Center;\n            return quad.Contains(center)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line01)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line12)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line23)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line30);\n        }\n\n        #endregion\n\n\n        #region Box3d contains Quad3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n            this Box3d box, Quad3d quad\n            )\n        {\n            return box.Contains(quad.P0)\n                    && box.Contains(quad.P1)\n                    && box.Contains(quad.P2)\n                    && box.Contains(quad.P3);\n        }\n\n        #endregion\n\n        #region Box3d contains Triangle3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n             this Box3d box, Triangle3d triangle\n            )\n        {\n            return box.Contains(triangle.P0)\n                    && box.Contains(triangle.P1)\n                    && box.Contains(triangle.P2);\n        }\n\n        #endregion\n\n        #region Box3d contains Sphere3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n             this Box3d box, Sphere3d sphere\n            )\n        {\n            return box.Contains(sphere.Center)\n                    && !box.Intersects(sphere);\n        }\n\n        #endregion\n\n        #region Box3d contains Cylinder3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n            this Box3d box, Cylinder3d cylinder\n           )\n        {\n            return box.Contains(cylinder.Center)\n                    && !box.Intersects(cylinder);\n        }\n\n        #endregion\n\n\n        #region Hull3d contains V3d\n\n        /// <summary>\n        /// Hull normals are expected to point outside.\n        /// </summary>\n        public static bool Contains(this Hull3d hull, V3d point)\n        {\n            var planes = hull.PlaneArray;\n            for (var i = 0; i < planes.Length; i++)\n            {\n                if (planes[i].Height(point) > 0)\n                    return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region Hull3d contains Sphere3d (sm)\n\n        /// <summary>\n        /// Hull normals are expected to point outside.\n        /// </summary>\n        public static bool Contains(this Hull3d hull, Sphere3d sphere)\n        {\n            var planes = hull.PlaneArray;\n            var negativeRadius = -sphere.Radius;\n            for (var i = 0; i < planes.Length; i++)\n            {\n                if (planes[i].Height(sphere.Center) > negativeRadius)\n                    return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n\n        #region Polygon2d contains V2d (haaser)\n\n        internal static V3i InsideTriangleFlags(ref V2d p0, ref V2d p1, ref V2d p2, ref V2d point)\n        {\n            V2d n0 = new V2d(p0.Y - p1.Y, p1.X - p0.X);\n            V2d n1 = new V2d(p1.Y - p2.Y, p2.X - p1.X);\n            V2d n2 = new V2d(p2.Y - p0.Y, p0.X - p2.X);\n\n            int t0 = Fun.Sign(n0.Dot(point - p0));\n            int t1 = Fun.Sign(n1.Dot(point - p1));\n            int t2 = Fun.Sign(n2.Dot(point - p2));\n\n            if (t0 == 0) t1 = 1;\n            if (t1 == 0) t1 = 1;\n            if (t2 == 0) t2 = 1;\n\n            return new V3i(t0, t1, t2);\n        }\n\n        internal static V3i InsideTriangleFlags(ref V2d p0, ref V2d p1, ref V2d p2, ref V2d point, int t0)\n        {\n            V2d n1 = new V2d(p1.Y - p2.Y, p2.X - p1.X);\n            V2d n2 = new V2d(p2.Y - p0.Y, p0.X - p2.X);\n\n            int t1 = Fun.Sign(n1.Dot(point - p1));\n            int t2 = Fun.Sign(n2.Dot(point - p2));\n\n            if (t1 == 0) t1 = 1;\n            if (t2 == 0) t2 = 1;\n\n            return new V3i(t0, t1, t2);\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon2d contains the given point.\n        /// Works with all (convex and non-convex) Polygons.\n        /// Assumes that the Vertices of the Polygon are sorted counter clockwise\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Polygon2d poly, V2d point)\n        {\n            return poly.Contains(point, true);\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon2d contains the given point.\n        /// Works with all (convex and non-convex) Polygons.\n        /// CCW represents the sorting order of the Polygon-Vertices (true -> CCW, false -> CW)\n        /// </summary>\n        public static bool Contains(this Polygon2d poly, V2d point, bool CCW)\n        {\n            int pc = poly.PointCount;\n            if (pc < 3)\n                return false;\n            int counter = 0;\n            V2d p0 = poly[0], p1 = poly[1], p2 = poly[2];\n            V3i temp = InsideTriangleFlags(ref p0, ref p1, ref p2, ref point);\n            int t2_cache = temp.Z;\n            if (temp.X == temp.Y && temp.Y == temp.Z) counter += temp.X;\n            for (int pi = 3; pi < pc; pi++)\n            {\n                p1 = p2; p2 = poly[pi];\n                temp = InsideTriangleFlags(ref p0, ref p1, ref p2, ref point, -t2_cache);\n                t2_cache = temp.Z;\n                if (temp.X == temp.Y && temp.Y == temp.Z) counter += temp.X;\n            }\n            if (CCW) return counter > 0;\n            else return counter < 0;\n        }\n\n        #endregion\n\n\n        #region Plane3d +- eps contains V3d (sm)\n\n        /// <summary>\n        /// Returns true if point is within given eps to plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Plane3d plane, double eps, V3d point)\n        {\n            var d = plane.Height(point);\n            return d >= -eps && d <= eps;\n        }\n\n        #endregion\n\n        #region Plane3d +- eps contains Box3d (sm)\n\n        /// <summary>\n        /// Returns true if the space within eps to a plane fully contains the given box.\n        /// </summary>\n        public static bool Contains(this Plane3d plane, double eps, Box3d box)\n        {\n            var corners = box.ComputeCorners();\n            for (var i = 0; i < 8; i++)\n            {\n                var d = plane.Height(corners[i]);\n                if (d < -eps || d > eps) return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region Polygon3d +- eps contains V3d (sm)\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Polygon3d polygon, double eps, V3d point, out double distance)\n        {\n            var plane = polygon.GetPlane3d();\n            distance = plane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            var w2p = plane.GetWorldToPlane();\n            var poly2d = new Polygon2d(polygon.GetPointArray().Map(p => w2p.TransformPos(p).XY));\n            return poly2d.Contains(w2p.TransformPos(point).XY);\n        }\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Polygon3d polygon, Plane3d supportingPlane, Euclidean3d world2plane, Polygon2d poly2d, double eps, V3d point, out double distance)\n        {\n            distance = supportingPlane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            return poly2d.Contains(world2plane.TransformPos(point).XY);\n        }\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this Polygon3d polygon, Plane3d supportingPlane, M44d world2plane, Polygon2d poly2d, double eps, V3d point, out double distance)\n        {\n            distance = supportingPlane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            return poly2d.Contains(world2plane.TransformPos(point).XY);\n        }\n\n        #endregion\n\n\n        // Intersection tests\n\n        #region Line2d intersects Line2d\n\n        /// <summary>\n        /// Returns true if the two line segments intersect.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Line2d l0, Line2d l1)\n            => l0.IntersectsLine(l1.P0, l1.P1, out V2d _);\n\n        /// <summary>\n        /// Returns true if the two line segments intersect.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Line2d l0, Line2d l1, out V2d p)\n            => l0.IntersectsLine(l1.P0, l1.P1, out p);\n\n        /// <summary>\n        /// Returns true if the two line segments intersect within given tolerance.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Line2d l0, Line2d l1, double absoluteEpsilon, out V2d p)\n            => l0.IntersectsLine(l1.P0, l1.P1, absoluteEpsilon, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this Line2d line, V2d p0, V2d p1)\n            => line.IntersectsLine(p0, p1, out _);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this Line2d line, V2d p0, V2d p1, out V2d p)\n            => line.IntersectsLine(p0, p1, false, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// The intersection point is returned in p.\n        /// If overlapping is true and the segments are parallel, then\n        /// the closest point to p0 of the intersection range is returned in p.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Line2d line,\n            V2d p0, V2d p1,\n            bool overlapping,\n            out V2d p\n            )\n        {\n            var a = line.P0 - p0;\n\n            if (Fun.IsTiny(a.LengthSquared))\n            {\n                p = p0;\n                return true;\n            }\n\n            var u = line.P1 - line.P0;\n            var v = p1 - p0;\n            var lu = u.Length;\n\n            var cross = u.X * v.Y - u.Y * v.X;\n            if (!Fun.IsTiny(cross))\n            {\n                // non-parallel lines\n                cross = 1 / cross;\n                var t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 > 1 || t0 < 0)\n                {\n                    p = V2d.NaN;\n                    return false;\n                }\n\n                double t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                if (t1 > 1 || t1 < 0)\n                {\n                    p = V2d.NaN;\n                    return false;\n                }\n\n                p = line.P0 + u * t0;\n                return true;\n            }\n            else\n            {\n                // parallel lines\n                if (!overlapping)\n                {\n                    p = V2d.NaN;\n                    return false;\n                }\n\n                var normalizedDirection = u / lu;\n\n                var r0 = new Range1d(0, lu);\n                var r1 = new Range1d((p0 - line.P0).Dot(normalizedDirection), (p1 - line.P0).Dot(normalizedDirection));\n                r1.Repair();\n\n                if (r0.Intersects(r1, 0, out Range1d result))\n                {\n                    p = line.P0 + normalizedDirection * result.Min;\n                    return true;\n                }\n\n                p = V2d.NaN;\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1 within given tolerance.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this Line2d line, V2d p0, V2d p1, double absoluteEpsilon, out V2d p)\n            => line.IntersectsLine(p0, p1, absoluteEpsilon, false, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1 within given tolerance.\n        /// The intersection point is returned in p.\n        /// If overlapping is true and the segments are parallel, then\n        /// the closest point to p0 of the intersection range is returned in p.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Line2d line,\n            V2d p0, V2d p1,\n            double absoluteEpsilon,\n            bool overlapping,\n            out V2d p\n            )\n        {\n            var a = line.P0 - p0;\n\n            if (Fun.IsTiny(a.LengthSquared))\n            {\n                p = p0;\n                return true;\n            }\n\n            var u = line.P1 - line.P0;\n            var v = p1 - p0;\n\n            var lu = u.Length;\n            var lv = v.Length;\n            var relativeEpsilonU = absoluteEpsilon / lu;\n            var RelativeEpsilonV = absoluteEpsilon / lv;\n\n            var cross = u.X * v.Y - u.Y * v.X;\n            if (!Fun.IsTiny(cross))\n            {\n                // non-parallel lines\n                cross = 1 / cross;\n                var t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 > 1 + relativeEpsilonU || t0 < -relativeEpsilonU)\n                {\n                    p = V2d.NaN;\n                    return false;\n                }\n\n                var t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                if (t1 > 1 + RelativeEpsilonV || t1 < -RelativeEpsilonV)\n                {\n                    p = V2d.NaN;\n                    return false;\n                }\n\n                p = line.P0 + u * t0;\n                return true;\n            }\n            else\n            {\n                // parallel lines\n                if (!overlapping)\n                {\n                    p = V2d.NaN;\n                    return false;\n                }\n\n                var normalizedDirection = u / lu;\n\n                var r0 = new Range1d(0, lu);\n                var r1 = new Range1d((p0 - line.P0).Dot(normalizedDirection), (p1 - line.P0).Dot(normalizedDirection));\n                r1.Repair();\n\n                if (r0.Intersects(r1, absoluteEpsilon, out Range1d result))\n                {\n                    p = line.P0 + normalizedDirection * result.Min;\n                    return true;\n                }\n\n                p = V2d.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Ray2d intersects Line2d\n\n        /// <summary>\n        /// Returns true if the Ray and the Line intersect.\n        /// ATTENTION: Both-Sided Ray\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray2d ray,\n            Line2d line\n            )\n        {\n            return ray.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// returns true if the Ray and the Line intersect.\n        /// t holds the smallest Intersection-Parameter for the Ray\n        /// ATTENTION: t can be negative\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray2d ray,\n            Line2d line,\n            out double t\n            )\n        {\n            return ray.IntersectsLine(line.P0, line.P1, out t);\n        }\n\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// ATTENTION: Both-Sided Ray\n        /// </summary>\n        public static bool IntersectsLine(\n            this Ray2d ray,\n            V2d p0, V2d p1\n            )\n        {\n            V2d n = new V2d(-ray.Direction.Y, ray.Direction.X);\n\n            double d0 = n.Dot(p0 - ray.Origin);\n            double d1 = n.Dot(p1 - ray.Origin);\n\n            if (d0.Sign() != d1.Sign()) return true;\n            else if (Fun.IsTiny(d0) && Fun.IsTiny(d1)) return true;\n            else return false;\n        }\n\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// t holds the Intersection-Parameter for the Ray\n        /// If both Line-Points are on the Ray no Intersection is returned\n        /// ATTENTION: t can be negative\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this Ray2d ray,\n            V2d p0, V2d p1,\n            out double t\n            )\n        {\n            return ray.IntersectsLine(p0, p1, false, out t);\n        }\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// if overlapping is true t holds the smallest Intersection-Parameter for the Ray\n        /// if overlagging is false and both Line-Points are on the Ray no Intersection is returned\n        /// ATTENTION: t can be negative\n        /// </summary>\n        public static bool IntersectsLine(\n            this Ray2d ray,\n            V2d p0, V2d p1,\n            bool overlapping,\n            out double t\n            )\n        {\n            V2d a = p0 - ray.Origin;\n            V2d u = p1 - p0;\n            V2d v = ray.Direction;\n            double lv2 = v.LengthSquared;\n\n\n            double cross = u.X * v.Y - u.Y * v.X;\n            double n = a.Y * u.X - a.X * u.Y;\n\n            if (!Fun.IsTiny(cross))\n            {\n                cross = 1 / cross;\n\n                double t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 >= 0 && t0 <= 1)\n                {\n                    t = n * cross;\n                    return true;\n                }\n\n                t = double.NaN;\n                return false;\n            }\n\n            if (Fun.IsTiny(n) && overlapping)\n            {\n                double ta = v.Dot(a) / lv2;\n                double tb = v.Dot(p1 - ray.Origin) / lv2;\n\n                if ((ta < 0 && tb > 0) || (ta > 0 && tb < 0))\n                {\n                    t = 0;\n                    return true;\n                }\n                else\n                {\n                    if (ta >= 0) t = Fun.Min(ta, tb);\n                    else t = Fun.Max(ta, tb);\n\n                    return true;\n                }\n            }\n\n            t = double.NaN;\n            return false;\n        }\n\n\n\n        #endregion\n\n        #region Ray2d intersects Ray2d\n\n        /// <summary>\n        /// Returns true if the Rays intersect\n        /// ATTENTION: Both-Sided Rays\n        /// </summary>\n        public static bool Intersects(\n            this Ray2d r0,\n            Ray2d r1\n            )\n        {\n            if (!r0.Direction.IsParallelTo(r1.Direction)) return true;\n            else\n            {\n                V2d n0 = new V2d(-r0.Direction.Y, r0.Direction.X);\n\n                if (Fun.IsTiny(n0.Dot(r1.Origin - r0.Origin))) return true;\n                else return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the Rays intersect\n        /// t0 and t1 are the corresponding Ray-Parameters for the Intersection\n        /// ATTENTION: Both-Sided Rays\n        /// </summary>\n        public static bool Intersects(\n            this Ray2d r0, Ray2d r1,\n            out double t0, out double t1\n            )\n        {\n            V2d a = r0.Origin - r1.Origin;\n\n            if (r0.Origin.ApproximateEquals(r1.Origin, Constant<double>.PositiveTinyValue))\n            {\n                t0 = 0;\n                t1 = 0;\n                return true;\n            }\n\n            V2d u = r0.Direction;\n            V2d v = r1.Direction;\n\n            double cross = u.X * v.Y - u.Y * v.X;\n\n            if (!Fun.IsTiny(cross))\n            {\n                //Rays not parallel\n                cross = 1 / cross;\n\n                t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                return true;\n            }\n            else\n            {\n                t0 = double.NaN;\n                t1 = double.NaN;\n                //Rays are parallel\n                if (Fun.IsTiny(a.Y * u.X - a.X * u.Y)) return true;\n                else return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the Rays intersect.\n        /// </summary>\n        public static bool Intersects(this Ray2d r0, Ray2d r1, out double t)\n        {\n            V2d a = r1.Origin - r0.Origin;\n            if (a.Abs().AllSmaller(Constant<double>.PositiveTinyValue))\n            {\n                t = 0;\n                return true; // Early exit when rays have same origin\n            }\n\n            double cross = r0.Direction.Dot270(r1.Direction);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n            {\n                t = r1.Direction.Dot90(a) / cross;\n                return true;\n            }\n            else // Rays are parallel\n            {\n                t = double.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Ray2d intersects Circle2d\n\n        /// <summary>\n        /// Computes the intersection between the given <see cref=\"Ray2d\"/> and <see cref=\"Circle2d\"/>.\n        /// </summary>\n        /// <param name=\"ray\">The ray to intersect.</param>\n        /// <param name=\"circle\">The circle to intersect the ray with.</param>\n        /// <param name=\"t0\">The ray parameter of the first intersection. Set to infinity if there is no intersection.</param>\n        /// <param name=\"t1\">The ray parameter of the second intersection. Set to infinity if there is no intersection.</param>\n        /// <returns>True if there is an intersection, false otherwise.</returns>\n        public static bool Intersects(this Ray2d ray, Circle2d circle, out double t0, out double t1)\n        {\n            var p = ray.Origin - circle.Center;\n            var a = ray.Direction.X.Square() + ray.Direction.Y.Square();\n            var b = 2 * ray.Direction.X * p.X + 2 * ray.Direction.Y * p.Y;\n            var c = p.X.Square() + p.Y.Square() - circle.Radius.Square();\n            var d = b.Square() - 4 * a * c;\n\n            if (d < 0)\n            {\n                t0 = double.PositiveInfinity;\n                t1 = double.PositiveInfinity;\n                return false;\n            }\n            else\n            {\n                var div = 1 / (a + a);\n                d = d.Sqrt();\n                t0 = (-b + d) * div;\n                t1 = (-b - d) * div;\n                return true;\n            }\n        }\n\n        #endregion\n\n\n        #region Plane2d intersects Line2d\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Line2d intersect or the Line2d\n        /// lies completely in the Plane's Epsilon-Range\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        public static bool Intersects(\n            this Plane2d plane,\n            Line2d line,\n            double absoluteEpsilon\n            )\n        {\n            double lengthOfNormal2 = plane.Normal.LengthSquared;\n            double d0 = plane.Height(line.P0);\n            double d1 = plane.Height(line.P1);\n\n            return d0 * d1 < absoluteEpsilon * absoluteEpsilon * lengthOfNormal2;\n        }\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Line2d intersect\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Plane2d plane,\n            Line2d line\n            )\n        {\n            return plane.IntersectsLine(line.P0, line.P1);\n        }\n\n\n        /// <summary>\n        /// Returns true if the Plane2d and the line between p0 and p1 intersect\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this Plane2d plane,\n            V2d p0, V2d p1\n            )\n        {\n            double d0 = plane.Height(p0);\n            double d1 = plane.Height(p1);\n\n            return d0 * d1 <= 0;\n        }\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Line2d intersect\n        /// point holds the Intersection-Point. If no Intersection is found point is V2d.NaN\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Plane2d plane,\n            Line2d line,\n            out V2d point\n            )\n        {\n            return plane.Intersects(line, 0, out point);\n        }\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Line2d intersect or the Line2d\n        /// lies completely in the Plane's Epsilon-Range\n        /// point holds the Intersection-Point. If the Line2d is inside Epsilon point holds the centroid of the Line2d\n        /// If no Intersection is found point is V2d.NaN\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        public static bool Intersects(\n            this Plane2d plane,\n            Line2d line,\n            double absoluteEpsilon,\n            out V2d point\n            )\n        {\n            double h0 = plane.Height(line.P0);\n            double h1 = plane.Height(line.P1);\n\n            int s0 = (h0 > -absoluteEpsilon ? (h0 < absoluteEpsilon ? 0 : 1) : -1);\n            int s1 = (h1 > -absoluteEpsilon ? (h1 < absoluteEpsilon ? 0 : 1) : -1);\n\n            if (s0 == s1)\n            {\n                if (s0 != 0)\n                {\n                    point = V2d.NaN;\n                    return false;\n                }\n                else\n                {\n                    point = (line.P0 + line.P1) * 0.5;\n                    return true;\n                }\n            }\n            else\n            {\n                if (s0 == 0)\n                {\n                    point = line.P0;\n                    return true;\n                }\n                else if (s1 == 0)\n                {\n                    point = line.P1;\n                    return true;\n                }\n                else\n                {\n                    V2d dir = line.Direction;\n                    double no = plane.Normal.Dot(line.P0);\n                    double nd = plane.Normal.Dot(dir);\n                    double t = (plane.Distance - no) / nd;\n\n                    point = line.P0 + t * dir;\n                    return true;\n                }\n            }\n        }\n\n\n\n        #endregion\n\n        #region Plane2d intersects Ray2d\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Ray2d intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2d plane, Ray2d ray)\n            => !plane.Normal.IsOrthogonalTo(ray.Direction);\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Ray2d intersect.\n        /// point holds the Intersection-Point if an intersection is found (else V2d.NaN)\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2d plane, Ray2d ray, out V2d point)\n            => plane.Intersects(ray, out double t, out point);\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Ray2d intersect.\n        /// t holds the ray paramater of the intersection point if the intersection is found (else Double.PositiveInfinity).\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2d plane, Ray2d ray, out double t)\n        {\n            double dot = Vec.Dot(plane.Normal, ray.Direction);\n            if (Fun.IsTiny(dot))\n            {\n                t = double.PositiveInfinity;\n                return false;\n            }\n            t = -plane.Height(ray.Origin) / dot;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Ray2d intersect.\n        /// t and p hold the ray paramater and point of the intersection if one is found (else Double.PositiveInfinity and V2d.PositiveInfinity).\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2d plane, Ray2d ray, out double t, out V2d p)\n        {\n            bool result = Intersects(plane, ray, out t);\n            p = ray.Origin + t * ray.Direction;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the intersection point of the given Plane2d and Ray2d, or V2d.PositiveInfinity if ray is parallel to plane.\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Intersect(this Plane2d plane, Ray2d ray)\n        {\n            double dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot)) return V2d.PositiveInfinity;\n            return ray.GetPointOnRay(-plane.Height(ray.Origin) / dot);\n        }\n\n        #endregion\n\n        #region Plane2d intersects Plane2d\n\n        /// <summary>\n        /// Returns true if the two Plane2ds intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2d p0, Plane2d p1)\n        {\n            var hit = p0.Coefficients.Cross(p1.Coefficients);\n            return !hit.Z.IsTiny();\n        }\n\n        /// <summary>\n        /// Returns true if the two Plane2ds intersect.\n        /// Point holds the intersection point if an intersection is found.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane2d p0, Plane2d p1, out V2d point)\n        {\n            var hit = p0.Coefficients.Cross(p1.Coefficients);\n            point = hit.XY / hit.Z;\n\n            return !hit.Z.IsTiny();\n        }\n\n        #endregion\n\n        #region Plane2d intersects IEnumerable<V2d>\n\n        /// <summary>\n        /// returns true if the Plane2d divides the Point-Cloud\n        /// </summary>\n        public static bool Divides(\n            this Plane2d plane,\n            IEnumerable<V2d> data\n            )\n        {\n            int first = int.MinValue;\n            foreach (var p in data)\n            {\n                if (first == int.MinValue)\n                {\n                    first = plane.Height(p).Sign();\n                }\n                else\n                {\n                    if (plane.Height(p).Sign() != first) return true;\n                }\n            }\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region Circle2d intersects Circle2d (sm)\n\n        /// <summary>\n        /// Returns true if the circles intersect, or one contains the other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Circle2d c0, Circle2d c1)\n            => (c0.Center - c1.Center).LengthSquared <= (c0.Radius + c1.Radius).Square();\n\n        #endregion\n\n\n        #region Triangle2d intersects Line2d\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect or the triangle contains the line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle2d triangle,\n            Line2d line\n            )\n        {\n            return triangle.IntersectsLine(line.P0, line.P1);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the line between p0 and p1 intersect or the triangle contains the line\n        /// </summary>\n        public static bool IntersectsLine(\n            this Triangle2d triangle,\n            V2d p0, V2d p1\n            )\n        {\n            if(triangle.Contains(p0))return true;\n            if(triangle.Contains(p1))return true;\n\n            if(triangle.Line01.IntersectsLine(p0,p1))return true;\n            if(triangle.Line12.IntersectsLine(p0,p1))return true;\n            if(triangle.Line20.IntersectsLine(p0,p1))return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Triangle2d intersects Ray2d\n\n        /// <summary>\n        /// Returns true if the Triangle and the Ray intersect\n        /// </summary>\n        public static bool Intersects(\n            this Triangle2d triangle,\n            Ray2d ray\n            )\n        {\n            if (triangle.Contains(ray.Origin)) return true;\n\n            if (ray.IntersectsLine(triangle.P0, triangle.P1)) return true;\n            if (ray.IntersectsLine(triangle.P1, triangle.P2)) return true;\n            if (ray.IntersectsLine(triangle.P2, triangle.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Triangle2d intersects Plane2d\n\n        /// <summary>\n        /// returns true if the Triangle2d and the Plane2d intersect\n        /// </summary>\n        public static bool Intersects(\n            this Triangle2d triangle,\n            Plane2d plane\n            )\n        {\n            if (plane.Intersects(triangle.Line01)) return true;\n            if (plane.Intersects(triangle.Line12)) return true;\n            if (plane.Intersects(triangle.Line20)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Triangle2d intersects Triangle2d\n\n        /// <summary>\n        /// Returns true if the triangles intersect or one contains the other.\n        /// </summary>\n        public static bool Intersects(this Triangle2d t0, Triangle2d t1)\n        {\n            var l = t0.Line01;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            l = t0.Line12;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            l = t0.Line20;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            if (t0.Contains(t1.P0)) return true;\n            if (t1.Contains(t0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region Box2d intersects Line2d\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool Intersects(this Box2d box, Line2d line)\n        {\n            var out0 = box.OutsideFlags(line.P0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(line.P1); if (out1 == 0) return true;\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n                this Box2d box, Line2d line, Box.Flags out0, Box.Flags out1)\n        {\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsLine(\n                this Box2d box, V2d p0, V2d p1)\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            return box.IntersectsLine(p0, p1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsLine(\n                this Box2d box, V2d p0, V2d p1,\n                Box.Flags out0, Box.Flags out1)\n        {\n            if ((out0 & out1) != 0) return false;\n\n            V2d min = box.Min;\n            V2d max = box.Max;\n            var bf = out0 | out1;\n\n            if ((bf & Box.Flags.X) != 0)\n            {\n                double dx = p1.X - p0.X;\n                if ((bf & Box.Flags.MinX) != 0)\n                {\n                    if (dx == 0 && p0.X < min.X) return false;\n                    double t = (min.X - p0.X) / dx;\n                    V2d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinX) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxX) != 0)\n                {\n                    if (dx == 0 && p0.X > max.X) return false;\n                    double t = (max.X - p0.X) / dx;\n                    V2d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxX) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Y) != 0)\n            {\n                double dy = p1.Y - p0.Y;\n                if ((bf & Box.Flags.MinY) != 0)\n                {\n                    if (dy == 0 && p0.Y < min.Y) return false;\n                    double t = (min.Y - p0.Y) / dy;\n                    V2d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinY) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxY) != 0)\n                {\n                    if (dy == 0 && p0.Y > max.Y) return false;\n                    double t = (max.Y - p0.Y) / dy;\n                    V2d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxY) == 0)\n                        return true;\n                }\n            }\n            return false;\n        }\n\n\n        #endregion\n\n        #region Box2d intersects Ray2d\n\n        /// <summary>\n        /// Returns true if the box and the ray intersect\n        /// </summary>\n        public static bool Intersects(\n            this Box2d box,\n            Ray2d ray\n            )\n        {\n            /*\n             * Getting a Normal-Vector for the Ray and calculating\n             * the Normal Distances for every Box-Point:\n             */\n            V2d n = new V2d(-ray.Direction.Y, ray.Direction.X);\n\n            double d0 = n.Dot(box.Min - ray.Origin);                                            //n.Dot(box.p0 - ray.Origin)\n            double d1 = n.X * (box.Max.X - ray.Origin.X) + n.Y * (box.Min.Y - ray.Origin.Y);    //n.Dot(box.p1 - ray.Origin)\n            double d2 = n.Dot(box.Max - ray.Origin);                                            //n.Dot(box.p2 - ray.Origin)\n            double d3 = n.X * (box.Min.X - ray.Origin.X) + n.Y * (box.Max.Y - ray.Origin.Y);    //n.Dot(box.p3 - ray.Origin)\n\n            /*\n             * If Zero lies in the Range of the Distances there\n             * have to be Points on both sides of the Ray.\n             * This means the Box and the Ray have an Intersection\n             */\n\n            Range1d r = new Range1d(d0, d1, d2, d3);\n            return r.Contains(0);\n        }\n\n        #endregion\n\n        #region Box2d intersects Plane2d\n\n        /// <summary>\n        /// returns true if the box and the plane intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Box2d box,\n            Plane2d plane\n            )\n        {\n            //UNTESTED\n            return plane.Divides(box.ComputeCorners());\n        }\n\n\n        /// <summary>\n        /// NOT TESTED YET.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Box2d box,\n            Plane2d plane,\n            out Line2d line)\n        {\n            return Intersects(\n                    plane.Normal.X, plane.Normal.Y, plane.Distance,\n                    box.Min.X, box.Min.Y, box.Max.X, box.Max.Y,\n                    out line);\n        }\n\n        /// <summary>\n        /// Intersects an infinite line given by its normal vector [nx, ny]\n        /// and its distance to the origin d, with an axis aligned box given\n        /// by it minimal point [xmin, ymin] and its maximal point\n        /// [xmax, ymax]. Returns true if there is an intersection and computes\n        /// the actual intersection line.\n        /// NOT TESTED YET.\n        /// </summary>\n        public static bool Intersects(\n                double nx, double ny, double d,\n                double xmin, double ymin, double xmax, double ymax,\n                out Line2d line)\n        {\n            if (nx.IsTiny()) // horizontal\n            {\n                if (d <= ymin || d >= ymax) { line = default; return false; }\n                line = new Line2d(new V2d(xmin, d), new V2d(xmax, d));\n                return true;\n            }\n\n            if (ny.IsTiny()) // vertical\n            {\n                if (d <= xmin || d >= xmax) { line = default; return false; }\n                line = new Line2d(new V2d(d, ymin), new V2d(d, ymax));\n                return true;\n            }\n\n            if (nx.Sign() != ny.Sign())\n            {\n                double x0 = (d - ny * ymin) / nx;\n                if (x0 >= xmax) { line = default; return false; }\n                if (x0 > xmin) xmin = x0;\n                double x1 = (d - ny * ymax) / nx;\n                if (x1 <= xmin) { line = default; return false; }\n                if (x1 < xmax) xmax = x1;\n\n                double y0 = (d - nx * xmin) / ny;\n                if (y0 >= ymax) { line = default; return false; }\n                if (y0 > ymin) ymin = y0;\n                double y1 = (d - nx * xmax) / ny;\n                if (y1 <= ymin) { line = default; return false; }\n                if (y1 < ymax) ymax = y1;\n\n                line = new Line2d(new V2d(xmin, ymin), new V2d(xmax, ymax));\n            }\n            else\n            {\n                double x0 = (d - ny * ymax) / nx;\n                if (x0 >= xmax) { line = default; return false; }\n                if (x0 > xmin) xmin = x0;\n                double x1 = (d - ny * ymin) / nx;\n                if (x1 <= xmin) { line = default; return false; }\n                if (x1 < xmax) xmax = x1;\n                double y0 = (d - nx * xmax) / ny;\n                if (y0 >= ymax) { line = default; return false; }\n                if (y0 > ymin) ymin = y0;\n                double y1 = (d - nx * xmin) / ny;\n                if (y1 <= ymin) { line = default; return false; }\n                if (y1 < ymax) ymax = y1;\n\n                line = new Line2d(new V2d(xmax, ymin), new V2d(xmin, ymax));\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region Box2d intersects Triangle2d\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Box2d box,\n            Triangle2d triangle\n            )\n        {\n            return box.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2);\n        }\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect\n        /// </summary>\n        public static bool IntersectsTriangle(\n            this Box2d box,\n            V2d p0, V2d p1, V2d p2\n            )\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n\n            return box.IntersectsTriangle(p0, p1, p2, out0, out1, out2);\n        }\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect. The outside flags\n        /// of the end points of the Triangle with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsTriangle(\n            this Box2d box, V2d p0, V2d p1, V2d p2,\n            Box.Flags out0, Box.Flags out1, Box.Flags out2\n            )\n        {\n\n            /* ---------------------------------------------------------------\n                If all of the points of the triangle are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n               If two points of the triangle are not on the same side\n               outside the box, it is possible that the edge between them\n               intersects the box. The outside flags we computed are also\n               used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p0, out2, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n               The only case left: The triangle contains the the whole box\n               i.e. every point. When no triangle-line intersects the box and one\n               box point is inside the triangle the triangle must contain the box\n            --------------------------------------------------------------- */\n            V2d a = box.Min - p0;\n            V2d u = p1 - p0;\n            V2d v = p2 - p0;\n\n\n            double cross = u.X * v.Y - u.Y * v.X;\n            if (Fun.IsTiny(cross)) return false;\n            cross = 1 / cross;\n\n            double t0 = (a.Y * v.X - a.X * v.Y) * cross; if (t0 < 0 || t0 > 1) return false;\n            double t1 = (a.Y * u.X - a.X * u.Y) * cross; if (t1 < 0 || t1 > 1) return false;\n\n            return (t0 + t1 < 1);\n        }\n\n        #endregion\n\n        #region Box2d intersects Box2d (Box2d-Implementation)\n\n        //Directly in Box-Implementation\n\n        #endregion\n\n\n        #region Quad2d intersects Line2d\n\n        /// <summary>\n        /// returns true if the Quad and the line intersect or the quad contains the line\n        /// </summary>\n        public static bool Intersects(\n            this Quad2d quad,\n            Line2d line\n            )\n        {\n            if (quad.Contains(line.P0)) return true;\n            if (quad.Contains(line.P1)) return true;\n\n            if (line.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (line.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (line.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (line.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n        /// <summary>\n        /// returns true if the Quad and the line between p0 and p1 intersect or the quad contains the line\n        /// </summary>\n        public static bool IntersectsLine(\n            this Quad2d quad,\n            V2d p0, V2d p1\n            )\n        {\n            if (quad.Contains(p0)) return true;\n            if (quad.Contains(p1)) return true;\n\n            Line2d line = new Line2d(p0, p1);\n            if (line.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (line.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (line.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (line.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Quad2d intersects Ray2d\n\n        /// <summary>\n        /// returns true if the quad and the ray intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad2d quad,\n            Ray2d ray\n            )\n        {\n            return ray.Plane2d.Divides(quad.Points);\n        }\n\n        #endregion\n\n        #region Quad2d intersects Plane2d\n\n        /// <summary>\n        /// returns true if the Quad2d and the Plane2d intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad2d quad,\n            Plane2d plane\n            )\n        {\n            //UNTESTED\n            if (plane.Divides(quad.Points)) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region Quad2d intersects Triangle2d\n\n        /// <summary>\n        /// returns true if the Quad2d and the Triangle2d intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Quad2d quad,\n            Triangle2d triangle\n            )\n        {\n            if (quad.Intersects(triangle.Line01)) return true;\n            if (quad.Intersects(triangle.Line12)) return true;\n            if (quad.Intersects(triangle.Line20)) return true;\n\n            if (quad.Contains(triangle.P0)) return true;\n            if (triangle.Contains(quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Quad2d intersects Box2d\n\n        /// <summary>\n        /// Returns true if the box and the Quad intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Box2d box,\n            Quad2d quad\n            )\n        {\n            Box.Flags out0 = box.OutsideFlags(quad.P0); if (out0 == 0) return true;\n            Box.Flags out1 = box.OutsideFlags(quad.P1); if (out1 == 0) return true;\n            Box.Flags out2 = box.OutsideFlags(quad.P2); if (out2 == 0) return true;\n            Box.Flags out3 = box.OutsideFlags(quad.P3); if (out3 == 0) return true;\n\n\n            /* ---------------------------------------------------------------\n                If all of the points of the Quad are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2 & out3) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n               If two points of the Quad are not on the same side\n               outside the box, it is possible that the edge between them\n               intersects the box. The outside flags we computed are also\n               used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(quad.P0, quad.P1, out0, out1)) return true;\n            if (box.IntersectsLine(quad.P1, quad.P2, out1, out2)) return true;\n            if (box.IntersectsLine(quad.P2, quad.P3, out2, out3)) return true;\n            if (box.IntersectsLine(quad.P3, quad.P0, out3, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n               The only case left: The Quad contains the the whole box\n               i.e. every point. When no triangle-line intersects the box and one\n               box point is inside the Quad the Quad must contain the box\n            --------------------------------------------------------------- */\n\n            return quad.Contains(box.Min);\n        }\n\n        #endregion\n\n        #region Quad2d intersects Quad2d\n\n        /// <summary>\n        /// returns true if the Quad2ds intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Quad2d q0,\n            Quad2d quad\n            )\n        {\n            if (q0.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (q0.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (q0.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (q0.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            if (q0.Contains(quad.P0)) return true;\n            if (quad.Contains(q0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region Polygon2d intersects Line2d\n\n        /// <summary>\n        /// returns true if the Polygon2d and the Line2d intersect or the Polygon contains the Line\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2d poly,\n            Line2d line\n            )\n        {\n            foreach (var l in poly.EdgeLines)\n            {\n                if (l.Intersects(line)) return true;\n            }\n\n            if (poly.Contains(line.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Polygon2d intersects Ray2d\n\n        /// <summary>\n        /// returns true if the Polygon2d and the Ray2d intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Polygon2d poly,\n            Ray2d ray\n            )\n        {\n            //UNTESTED\n            return ray.Plane2d.Divides(poly.Points);\n        }\n\n\n        #endregion\n\n        #region Polygon2d intersects Plane2d\n\n        /// <summary>\n        /// returns true if the Polygon2d and the Plane2d itnersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Polygon2d poly,\n            Plane2d plane\n            )\n        {\n            //UNTESTED\n            return plane.Divides(poly.Points);\n        }\n\n        #endregion\n\n        #region Polygon2d intersects Triangle2d\n\n        /// <summary>\n        /// returns true if the Polygon2d and the Triangle2d intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2d poly,\n            Triangle2d triangle\n            )\n        {\n            foreach (var line in poly.EdgeLines)\n            {\n                if (triangle.Intersects(line)) return true;\n            }\n\n            if (triangle.Contains(poly[0])) return true;\n            if (poly.Contains(triangle.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Polygon2d intersects Box2d\n\n        /// <summary>\n        /// returns true if the Polygon2d and the Box2d intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2d poly,\n            Box2d box\n            )\n        {\n            //UNTESTED\n            int count = poly.PointCount;\n            Box.Flags[] outFlags = new Box.Flags[count];\n\n            int i0 = 0;\n            foreach (var p in poly.Points) outFlags[i0++] = box.OutsideFlags(p);\n\n            i0 = 0;\n            int i1 = 1;\n            foreach (var l in poly.EdgeLines)\n            {\n                if (box.Intersects(l, outFlags[i0], outFlags[i1])) return true;\n\n                i0++;\n                i1 = (i1 + 1) % count;\n            }\n\n            if (box.Contains(poly[0])) return true;\n            if (poly.Contains(box.Min)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Polygon2d intersects Quad2d\n\n        /// <summary>\n        /// returns true if the Polygon2d and the Quad2d interset or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2d poly,\n            Quad2d quad\n            )\n        {\n            foreach (var l in poly.EdgeLines)\n            {\n                if (quad.Intersects(l)) return true;\n            }\n\n            if (quad.Contains(poly[0])) return true;\n            if (poly.Contains(quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Polygon2d intersects Polygon2d\n\n        /// <summary>\n        /// returns true if the Polygon2ds intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this Polygon2d poly0,\n            Polygon2d poly1\n            )\n        {\n            //check if projected ranges intersect for all possible normals\n\n\n            V2d[] allnormals = new V2d[poly0.PointCount + poly1.PointCount];\n            int c = 0;\n\n            foreach (var d in poly0.Edges)\n            {\n                allnormals[c] = new V2d(-d.Y, d.X);\n                c++;\n            }\n            foreach (var d in poly1.Edges)\n            {\n                allnormals[c] = new V2d(-d.Y, d.X);\n                c++;\n            }\n\n\n\n            foreach (var n in allnormals)\n            {\n                var r0 = poly0.ProjectTo(n);\n                var r1 = poly1.ProjectTo(n);\n\n                if (!r0.Intersects(r1)) return false;\n            }\n\n            return true;\n        }\n\n        private static Range1d ProjectTo(this Polygon2d poly, V2d dir)\n        {\n            double min = double.MaxValue;\n            double max = double.MinValue;\n            foreach (var p in poly.Points)\n            {\n                double dotproduct = p.Dot(dir);\n\n                if (dotproduct < min) min = dotproduct;\n                if (dotproduct > max) max = dotproduct;\n            }\n\n            return new Range1d(min, max);\n        }\n\n        #endregion\n\n\n        #region Line3d intersects Line3d (haaser)\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Line3d l0,\n            Line3d l1\n            )\n        {\n            return l0.Intersects(l1, Constant<double>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than absoluteEpsilon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Line3d l0,\n            Line3d l1,\n            double absoluteEpsilon\n            )\n        {\n            if (l0.GetMinimalDistanceTo(l1) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than absoluteEpsilon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Line3d l0,\n            Line3d l1,\n            double absoluteEpsilon,\n            out V3d point\n            )\n        {\n            if (l0.GetMinimalDistanceTo(l1, out point) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region Line3d intersects Special (inconsistent argument order)\n\n        #region Line3d intersects Plane3d\n\n        /// <summary>\n        /// Returns true if the line and the plane intersect.\n        /// </summary>\n        public static bool Intersects(\n             this Line3d line, Plane3d plane, out double t\n             )\n        {\n            if (!line.Ray3d.Intersects(plane, out t)) return false;\n            if (t >= 0 && t <= 1) return true;\n            t = double.PositiveInfinity;\n            return false;\n\n        }\n\n        /// <summary>\n        /// Returns true if the line and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Line3d line, Plane3d plane, out double t, out V3d p\n             )\n        {\n            bool result = line.Intersects(plane, out t);\n            p = line.Origin + t * line.Direction;\n            return result;\n        }\n\n        #endregion\n\n        #region Line3d intersects Triangle3d\n\n        /// <summary>\n        /// Returns true if the line and the triangle intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Line3d line,\n            Triangle3d triangle\n            )\n        {\n            return line.Ray3d.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2, 0, 1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the line and the triangle intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool Intersects(\n            this Line3d line,\n            Triangle3d triangle,\n            out V3d point\n            )\n        {\n            Ray3d ray = line.Ray3d;\n\n            if (ray.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2, 0, 1, out double temp))\n            {\n                point = ray.GetPointOnRay(temp);\n                return true;\n            }\n            else\n            {\n                point = V3d.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #endregion\n\n\n        #region Ray3d intersects Line3d (haaser)\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than Constant&lt;double&gt;.PositiveTinyValue\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3d ray, Line3d line\n            )\n        {\n            return ray.Intersects(line, Constant<double>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than absoluteEpsilon\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3d ray, Line3d line,\n            double absoluteEpsilon\n            )\n        {\n            if (ray.GetMinimalDistanceTo(line) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than absoluteEpsilon\n        /// t holds the corresponding ray parameter\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3d ray, Line3d line,\n            double absoluteEpsilon,\n            out double t\n            )\n        {\n            if (ray.GetMinimalDistanceTo(line, out t) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region Ray3d intersects Ray3d (haaser)\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than Constant&lt;double&gt;.PositiveTinyValue\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3d r0,\n            Ray3d r1\n            )\n        {\n            return r0.Intersects(r1, out _, out _, Constant<double>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than Constant&lt;double&gt;.PositiveTinyValue\n        /// t0 and t1 hold the ray-parameters for the intersection\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3d r0,\n            Ray3d r1,\n            out double t0,\n            out double t1\n            )\n        {\n            return r0.Intersects(r1, out t0, out t1, Constant<double>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than absoluteEpsilon\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3d r0,\n            Ray3d r1,\n            double absoluteEpsilon\n            )\n        {\n            return r0.Intersects(r1, out _, out _, absoluteEpsilon);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than absoluteEpsilon\n        /// t0 and t1 hold the ray-parameters for the intersection\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Ray3d r0,\n            Ray3d r1,\n            out double t0,\n            out double t1,\n            double absoluteEpsilon\n            )\n        {\n            if (r0.GetMinimalDistanceTo(r1, out t0, out t1) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region Ray3d intersects Special (inconsistent argument order)\n\n        #region Ray3d intersects Triangle3d\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3d ray, Triangle3d triangle)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                double.MinValue, double.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3d ray, Triangle3d triangle, double tmin, double tmax)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3d ray, Triangle3d triangle, double tmin, double tmax, out double t)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTriangle(this Ray3d ray, V3d p0, V3d p1, V3d p2, double tmin, double tmax)\n            => ray.IntersectsTriangle(p0, p1, p2, tmin, tmax, out double _);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        public static bool IntersectsTriangle(this Ray3d ray, V3d p0, V3d p1, V3d p2, double tmin, double tmax, out double t)\n        {\n            var edge01 = p1 - p0;\n            var edge02 = p2 - p0;\n            var plane = Vec.Cross(ray.Direction, edge02);\n            var det = Vec.Dot(edge01, plane);\n            if (det > -1E-7 && det < 1E-7) { t = double.NaN; return false; }\n            //ray ~= parallel / Triangle\n            var tv = ray.Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            var u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) { t = double.NaN; return false; }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            var v = Vec.Dot(ray.Direction, plane) * det;\n            if (v < 0 || u + v > 1) { t = double.NaN; return false; }\n            var temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < tmin || temp_t >= tmax) { t = double.NaN; return false; }\n\n            t = temp_t;\n            return true;\n        }\n\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTrianglePointAndEdges(this Ray3d ray, V3d p0, V3d edge01, V3d edge02, double tmin, double tmax)\n            => ray.IntersectsTrianglePointAndEdges(p0, edge01, edge02, tmin, tmax, out _);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        public static bool IntersectsTrianglePointAndEdges(this Ray3d ray, V3d p0, V3d edge01, V3d edge02, double tmin, double tmax, out double t)\n        {\n            var plane = Vec.Cross(ray.Direction, edge02);\n            var det = Vec.Dot(edge01, plane);\n            if (det > -1E-7 && det < 1E-7) { t = double.NaN; return false; }\n            //ray ~= parallel / Triangle\n            var tv = ray.Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            var u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) { t = double.NaN; return false; }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            var v = Vec.Dot(ray.Direction, plane) * det;\n            if (v < 0 || u + v > 1) { t = double.NaN; return false; }\n            var temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < tmin || temp_t >= tmax) { t = double.NaN; return false; }\n\n            t = temp_t;\n            return true;\n        }\n\n        #endregion\n\n        #region Ray3d intersects Quad3d\n\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3d ray, Quad3d quad)\n            => ray.Intersects(quad, double.MinValue, double.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the quad intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        public static bool Intersects(this Ray3d ray, Quad3d quad, double tmin, double tmax)\n        {\n            var edge02 = quad.P2 - quad.P0;\n            return ray.IntersectsTrianglePointAndEdges(quad.P0, quad.Edge01, edge02, tmin, tmax)\n                || ray.IntersectsTrianglePointAndEdges(quad.P0, edge02, quad.Edge03, tmin, tmax);\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the quad intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        public static bool IntersectsQuad(this Ray3d ray, V3d p0, V3d p1, V3d p2, V3d p3, double tmin, double tmax)\n        {\n            var edge02 = p2 - p0;\n            return ray.IntersectsTrianglePointAndEdges(p0, p1 - p0, edge02, tmin, tmax)\n                || ray.IntersectsTrianglePointAndEdges(p0, edge02, p3 - p0, tmin, tmax);\n        }\n\n        #endregion\n\n        #region Ray3d intersects Polygon3d (haaser)\n\n        /// <summary>\n        /// Returns true if the ray and the polygon intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3d ray, Polygon3d poly, double tmin, double tmax)\n            => ray.Intersects(poly, tmin, tmax, out _);\n\n        /// <summary>\n        /// Returns true if the ray and the polygon intersect within the\n        /// supplied parameter interval of the ray.\n        /// t holds the correspoinding paramter.\n        /// </summary>\n        public static bool Intersects(this Ray3d ray, Polygon3d poly, double tmin, double tmax, out double t)\n        {\n            var tris = poly.ComputeTriangulationOfConcavePolygon(1E-5);\n            var count = tris.Length;\n\n            for (var i = 0; i < count; i += 3)\n            {\n                if (ray.IntersectsTriangle(poly[tris[i + 0]], poly[tris[i + 1]], poly[tris[i + 2]],\n                                           tmin, tmax, out t))\n                {\n                    return true;\n                }\n            }\n\n            t = double.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices, intersect within the\n        /// supplied parameter interval of the ray.\n        /// (The Method triangulates the polygon)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsPolygon(this Ray3d ray, V3d[] vertices, double tmin, double tmax)\n            => ray.Intersects(new Polygon3d(vertices), tmin, tmax);\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices and triangulation, intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        public static bool IntersectsPolygon(\n            this Ray3d ray,\n            V3d[] vertices,\n            int[] triangulation,\n            double tmin, double tmax\n            )\n        {\n            for (var i = 0; i < triangulation.Length; i += 3)\n            {\n                if (ray.IntersectsTriangle(vertices[triangulation[i + 0]],\n                                           vertices[triangulation[i + 1]],\n                                           vertices[triangulation[i + 2]], tmin, tmax)) return true;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices and triangulation, intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        public static bool Intersects(\n            this Ray3d ray,\n            Polygon3d polygon,\n            int[] triangulation,\n            double tmin, double tmax\n            )\n        {\n            for (var i = 0; i < triangulation.Length; i += 3)\n            {\n                if (ray.IntersectsTriangle(polygon[triangulation[i + 0]],\n                                           polygon[triangulation[i + 1]],\n                                           polygon[triangulation[i + 2]], tmin, tmax)) return true;\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region Ray3d intersects Sphere3d\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3d ray, Sphere3d sphere)\n            => ray.Intersects(sphere, double.MinValue, double.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the Ray3d.Hits method.\n        /// </summary>\n        public static bool Intersects(this Ray3d ray, Sphere3d sphere, double tmin, double tmax)\n        {\n            // calculate closest point\n            var t = ray.Direction.Dot(sphere.Center - ray.Origin) / ray.Direction.LengthSquared;\n            if (t < 0) t = 0;\n            if (t < tmin) t = tmin;\n            if (t > tmax) t = tmax;\n            V3d p = ray.Origin + t * ray.Direction;\n\n            // distance to sphere?\n            var d = (p - sphere.Center).LengthSquared;\n            if (d <= sphere.RadiusSquared)\n                return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Sphere3d intersects Triangle3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Sphere3d sphere, Triangle3d triangle\n             )\n        {\n            V3d v = sphere.Center.GetClosestPointOn(triangle) - sphere.Center;\n            return sphere.RadiusSquared >= v.LengthSquared;\n        }\n\n        #endregion\n\n        #endregion\n\n\n        #region Triangle3d intersects Line3d (haaser)\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3d tri,\n            Line3d line\n            )\n        {\n            return tri.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3d tri,\n            Line3d line,\n            out V3d point\n            )\n        {\n            return tri.IntersectsLine(line.P0, line.P1, out point);\n        }\n\n        /// <summary>\n        /// returns true if the triangle and the line, given by p0 and p1, intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Triangle3d tri,\n            V3d p0, V3d p1\n            )\n        {\n            V3d edge01 = tri.Edge01;\n            V3d edge02 = tri.Edge02;\n            V3d dir = p1 - p0;\n\n            V3d plane = Vec.Cross(dir, edge02);\n            double det = Vec.Dot(edge01, plane);\n            if (det > -1E-7 && det < 1E-7)return false;\n            //ray ~= parallel / Triangle\n            V3d tv = p0 - tri.P0;\n            det = 1 / det;  // det is now inverse det\n            double u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1)\n            {\n                return false;\n            }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            double v = Vec.Dot(dir, plane) * det;\n            if (v < 0 || u + v > 1)\n            {\n                return false;\n            }\n            double temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < 0 || temp_t >= 1)\n            {\n                return false;\n            }\n\n            return true;\n        }\n\n        /// <summary>\n        /// returns true if the triangle and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Triangle3d tri,\n            V3d p0, V3d p1,\n            out V3d point\n            )\n        {\n            V3d edge01 = tri.Edge01;\n            V3d edge02 = tri.Edge02;\n            V3d dir = p1 - p0;\n\n            V3d plane = Vec.Cross(dir, edge02);\n            double det = Vec.Dot(edge01, plane);\n            if (det > -1E-7 && det < 1E-7) { point = V3d.NaN; return false; }\n            //ray ~= parallel / Triangle\n            V3d tv = p0 - tri.P0;\n            det = 1 / det;  // det is now inverse det\n            double u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1)\n            {\n                point = V3d.NaN;\n                return false;\n            }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            double v = Vec.Dot(dir, plane) * det;\n            if (v < 0 || u + v > 1)\n            {\n                point = V3d.NaN;\n                return false;\n            }\n            double temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < 0 || temp_t >= 1)\n            {\n                point = V3d.NaN;\n                return false;\n            }\n\n            point = p0 + temp_t * dir;\n            return true;\n        }\n\n\n        #endregion\n\n        #region Triangle3d intersects Ray3d (haaser)\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3d tri,\n            Ray3d ray\n            )\n        {\n            return tri.Intersects(ray, double.MinValue, double.MaxValue, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect\n        /// within the given parameter interval\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3d tri,\n            Ray3d ray,\n            double tmin, double tmax\n            )\n        {\n            return tri.Intersects(ray, tmin, tmax, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect.\n        /// t holds the intersection paramter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3d tri,\n            Ray3d ray,\n            out double t\n            )\n        {\n            return tri.Intersects(ray, double.MinValue, double.MaxValue, out t);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect\n        /// within the given parameter interval\n        /// t holds the intersection paramter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Triangle3d tri,\n            Ray3d ray,\n            double tmin, double tmax,\n            out double t\n            )\n        {\n            return ray.Intersects(tri, tmin, tmax, out t);\n        }\n\n        #endregion\n\n        #region Triangle3d intersects Triangle3d (haaser)\n\n        /// <summary>\n        /// Returns true if the triangles intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Triangle3d t0,\n            Triangle3d t1\n            )\n        {\n            if (t0.IntersectsLine(t1.P0, t1.P1, out _)) return true;\n            if (t0.IntersectsLine(t1.P1, t1.P2, out _)) return true;\n            if (t0.IntersectsLine(t1.P2, t1.P0, out _)) return true;\n\n            if (t1.IntersectsLine(t0.P0, t0.P1, out _)) return true;\n            if (t1.IntersectsLine(t0.P1, t0.P2, out _)) return true;\n            if (t1.IntersectsLine(t0.P2, t0.P0, out _)) return true;\n\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the triangles intersect.\n        /// line holds the cutting-line of the two triangles.\n        /// </summary>\n        public static bool Intersects(\n            this Triangle3d t0,\n            Triangle3d t1,\n            out Line3d line\n            )\n        {\n            List<V3d> points = new List<V3d>();\n\n            if (t0.IntersectsLine(t1.P0, t1.P1, out V3d temp)) points.Add(temp);\n            if (t0.IntersectsLine(t1.P1, t1.P2, out temp)) points.Add(temp);\n            if (t0.IntersectsLine(t1.P2, t1.P0, out temp)) points.Add(temp);\n\n            if (points.Count == 2)\n            {\n                line = new Line3d(points[0], points[1]);\n                return true;\n            }\n\n            if (t1.IntersectsLine(t0.P0, t0.P1, out temp)) points.Add(temp);\n            if (t1.IntersectsLine(t0.P1, t0.P2, out temp)) points.Add(temp);\n            if (t1.IntersectsLine(t0.P2, t0.P0, out temp)) points.Add(temp);\n\n            if (points.Count == 2)\n            {\n                line = new Line3d(points[0], points[1]);\n                return true;\n            }\n\n            line = new Line3d(V3d.NaN, V3d.NaN);\n            return false;\n        }\n\n        #endregion\n\n\n        #region Quad3d intersects Line3d (haaser)\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3d quad,\n            Line3d line)\n        {\n            return quad.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3d quad,\n            Line3d line,\n            out V3d point)\n        {\n            return quad.IntersectsLine(line.P0, line.P1, out point);\n        }\n\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Quad3d quad,\n            V3d p0, V3d p1)\n        {\n            Ray3d ray = new Ray3d(p0, p1 - p0);\n            if (quad.Intersects(ray, 0, 1, out _))\n            {\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool IntersectsLine(\n            this Quad3d quad,\n            V3d p0, V3d p1,\n            out V3d point)\n        {\n            Ray3d ray = new Ray3d(p0, p1 - p0);\n            if (quad.Intersects(ray, 0, 1, out double t))\n            {\n                point = ray.GetPointOnRay(t);\n                return true;\n            }\n            else\n            {\n                point = V3d.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Quad3d intersects Ray3d (haaser)\n\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3d quad,\n            Ray3d ray\n            )\n        {\n            return quad.Intersects(ray, double.MinValue, double.MaxValue, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect.\n        /// t holds the intersection parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3d quad,\n            Ray3d ray,\n            out double t\n            )\n        {\n            return quad.Intersects(ray, double.MinValue, double.MaxValue, out t);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect\n        /// within the given paramter range\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Quad3d quad,\n            Ray3d ray,\n            double tmin, double tmax\n            )\n        {\n            return quad.Intersects(ray, tmin, tmax, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect\n        /// within the given paramter range\n        /// t holds the intersection parameter.\n        /// </summary>\n        public static bool Intersects(\n            this Quad3d quad,\n            Ray3d ray,\n            double tmin, double tmax,\n            out double t\n            )\n        {\n            V3d edge02 = quad.P2 - quad.P0;\n            if (ray.IntersectsTrianglePointAndEdges(quad.P0, quad.Edge01, edge02, tmin, tmax, out t)) return true;\n            if (ray.IntersectsTrianglePointAndEdges(quad.P0, edge02, quad.Edge03, tmin, tmax, out t)) return true;\n\n            t = double.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region Quad3d intersects Triangle3d (haaser)\n\n        /// <summary>\n        /// Returns true if the quad and the triangle intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Quad3d quad,\n            Triangle3d tri\n            )\n        {\n            if (quad.IntersectsLine(tri.P0, tri.P1)) return true;\n            if (quad.IntersectsLine(tri.P1, tri.P2)) return true;\n            if (quad.IntersectsLine(tri.P2, tri.P0)) return true;\n\n            if (tri.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (tri.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (tri.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (tri.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n\n        /// <summary>\n        /// Returns true if the quad and the triangle, given by p0/p1/p1, intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTriangle(\n            this Quad3d quad,\n            V3d p0, V3d p1, V3d p2\n            )\n        {\n            Triangle3d tri = new Triangle3d(p0, p1, p2);\n            return quad.Intersects(tri);\n        }\n\n        #endregion\n\n        #region Quad3d intersects Quad3d (haaser)\n\n        /// <summary>\n        /// Returns true if the given quads intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Quad3d q0,\n            Quad3d q1\n            )\n        {\n            if (q0.IntersectsTriangle(q1.P0, q1.P1, q1.P2)) return true;\n            if (q0.IntersectsTriangle(q1.P2, q1.P3, q1.P0)) return true;\n\n            if (q1.IntersectsTriangle(q0.P0, q0.P1, q0.P2)) return true;\n            if (q1.IntersectsTriangle(q0.P2, q0.P3, q0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region Plane3d intersects Line3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane3d plane, Line3d line)\n        {\n            return plane.IntersectsLine(line.P0, line.P1, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane3d plane, Line3d line, double absoluteEpsilon)\n        {\n            return plane.IntersectsLine(line.P0, line.P1, absoluteEpsilon);\n        }\n\n        public static bool IntersectsLine(this Plane3d plane, V3d p0, V3d p1, double absoluteEpsilon)\n        {\n            double h0 = plane.Height(p0);\n            int s0 = (h0 > absoluteEpsilon ? 1 :(h0 < -absoluteEpsilon ? -1 : 0));\n            if (s0 == 0) return true;\n\n            double h1 = plane.Height(p1);\n            int s1 = (h1 > absoluteEpsilon ? 1 : (h1 < -absoluteEpsilon ? -1 : 0));\n            if (s1 == 0) return true;\n\n\n            if (s0 == s1) return false;\n            else return true;\n        }\n\n        public static bool IntersectsLine(this Plane3d plane, V3d p0, V3d p1, double absoluteEpsilon, out V3d point)\n        {\n            //<n|origin + t0*dir> == d\n            //<n|or> + t0*<n|dir> == d\n            //t0 == (d - <n|or>) / <n|dir>;\n\n            V3d dir = p1 - p0;\n            double ld = dir.Length;\n            dir /= ld;\n\n            double nDotd = plane.Normal.Dot(dir);\n\n\n            if (!Fun.IsTiny(nDotd))\n            {\n                double t0 = (plane.Distance - plane.Normal.Dot(p0)) / nDotd;\n\n                if (t0 >= -absoluteEpsilon && t0 <= ld + absoluteEpsilon)\n                {\n                    point = p0 + dir * t0;\n                    return true;\n                }\n                else\n                {\n                    point = V3d.NaN;\n                    return false;\n                }\n            }\n            else\n            {\n                point = V3d.NaN;\n                return false;\n            }\n\n        }\n\n        #endregion\n\n        #region Plane3d intersects Ray3d\n\n        /// <summary>\n        /// Returns true if the Ray3d and the Plane3d intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Ray3d ray, Plane3d plane)\n            => !plane.Normal.IsOrthogonalTo(ray.Direction);\n\n        /// <summary>\n        /// Returns true if the ray and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Ray3d ray, Plane3d plane, out double t\n             )\n        {\n            double dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot))\n            {\n                t = double.PositiveInfinity;\n                return false;\n            }\n            t = -plane.Height(ray.Origin) / dot;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns the intersection point with the given plane, or V3d.PositiveInfinity if ray is parallel to plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Intersect(\n             this Ray3d ray, Plane3d plane\n             )\n        {\n            double dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot)) return V3d.PositiveInfinity;\n            return ray.GetPointOnRay(-plane.Height(ray.Origin) / dot);\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Ray3d ray, Plane3d plane, out double t, out V3d p\n             )\n        {\n            bool result = Intersects(ray, plane, out t);\n            p = ray.Origin + t * ray.Direction;\n            return result;\n        }\n\n        #endregion\n\n        #region Plane3d intersects Plane3d\n\n        public static bool Intersects(this Plane3d p0, Plane3d p1)\n        {\n            bool parallel = p0.Normal.IsParallelTo(p1.Normal);\n\n            if (parallel) return Fun.IsTiny(p0.Distance - p1.Distance);\n            else return true;\n        }\n\n        public static bool Intersects(this Plane3d p0, Plane3d p1, out Ray3d ray)\n        {\n            V3d dir = p0.Normal.Cross(p1.Normal);\n            double len = dir.Length;\n\n            if (Fun.IsTiny(len))\n            {\n                if (Fun.IsTiny(p0.Distance - p1.Distance))\n                {\n                    ray = new Ray3d(p0.Normal * p0.Distance, V3d.Zero);\n                    return true;\n                }\n                else\n                {\n                    ray = Ray3d.Invalid;\n                    return false;\n                }\n            }\n\n            dir *= 1 / len;\n\n            var alu = new double[,]\n                { { p0.Normal.X, p0.Normal.Y, p0.Normal.Z },\n                  { p1.Normal.X, p1.Normal.Y, p1.Normal.Z },\n                  { dir.X, dir.Y, dir.Z } };\n\n            int[] p = alu.LuFactorize();\n\n            var b = new double[] { p0.Distance, p1.Distance, 0 };\n\n            var x = alu.LuSolve(p, b);\n\n            ray = new Ray3d(new V3d(x), dir);\n            return true;\n        }\n\n        #endregion\n\n        #region Plane3d intersects Plane3d intersects Plane3d\n\n        public static bool Intersects(this Plane3d p0, Plane3d p1, Plane3d p2, out V3d point)\n        {\n            var alu = new double[,]\n                { { p0.Normal.X, p0.Normal.Y, p0.Normal.Z },\n                  { p1.Normal.X, p1.Normal.Y, p1.Normal.Z },\n                  { p2.Normal.X, p2.Normal.Y, p2.Normal.Z } };\n\n            var p = new int[3];\n            if (!alu.LuFactorize(p)) { point = V3d.NaN; return false; }\n            var b = new double[] { p0.Distance, p1.Distance, p2.Distance };\n            var x = alu.LuSolve(p, b);\n            point = new V3d(x);\n            return true;\n        }\n\n        #endregion\n\n        #region Plane3d intersects Triangle3d\n\n        /// <summary>\n        /// Returns whether the given plane and triangle intersect.\n        /// </summary>\n        public static bool Intersects(\n             this Plane3d plane, Triangle3d triangle\n             )\n        {\n            int sign = plane.Sign(triangle.P0);\n            if (sign == 0) return true;\n            if (sign != plane.Sign(triangle.P1)) return true;\n            if (sign != plane.Sign(triangle.P2)) return true;\n            return false;\n        }\n\n        #endregion\n\n        #region Plane3d intersects Sphere3d\n\n        /// <summary>\n        /// Returns whether the given sphere and plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Plane3d plane, Sphere3d sphere\n             )\n        {\n            return sphere.Radius >= plane.Height(sphere.Center).Abs();\n        }\n\n        #endregion\n\n        #region Plane3d intersects Polygon3d\n\n        /// <summary>\n        /// returns true if the Plane3d and the Polygon3d intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Plane3d plane,\n            Polygon3d poly\n            )\n        {\n            return plane.Intersects(poly, Constant<double>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the Plane3d and the polygon, intersect\n        /// within a tolerance of absoluteEpsilon\n        /// </summary>\n        public static bool Intersects(\n            this Plane3d plane,\n            Polygon3d polygon,\n            double absoluteEpsilon\n            )\n        {\n            double height = plane.Height(polygon[0]);\n            int sign0 = height > -absoluteEpsilon ? (height < absoluteEpsilon ? 0 : 1) : -1; if (sign0 == 0) return true;\n            int pc = polygon.PointCount;\n            for (int i = 1; i < pc; i++)\n            {\n                height = plane.Height(polygon[i]);\n                int sign = height > -absoluteEpsilon ? (height < absoluteEpsilon ? 0 : 1) : -1;\n                if (sign != sign0) return true;\n            }\n\n            return false;\n        }\n\n\n        /// <summary>\n        /// returns true if the Plane3d and the Polygon3d intersect.\n        /// line holds the intersection line\n        /// ATTENTION: works only with non-concave polygons!\n        /// </summary>\n        public static bool IntersectsConvex(\n            this Plane3d plane,\n            Polygon3d poly,\n            out Line3d line\n            )\n        {\n            return plane.IntersectsConvex(poly, Constant<double>.PositiveTinyValue, out line);\n        }\n\n        /// <summary>\n        /// Returns true if the Plane3d and the polygon, given by points, intersect\n        /// within a tolerance of absoluteEpsilon.\n        /// Line holds the intersection line.\n        /// ATTENTION: works only with non-concave polygons!\n        /// </summary>\n        public static bool IntersectsConvex(\n            this Plane3d plane,\n            Polygon3d polygon,\n            double absoluteEpsilon,\n            out Line3d line\n            )\n        {\n            int count = polygon.PointCount;\n            int[] signs = new int[count];\n            int pc = 0, nc = 0, zc = 0;\n            for (int pi = 0; pi < count; pi++)\n            {\n                double h = plane.Height(polygon[pi]);\n                if (h < -absoluteEpsilon) { nc++; signs[pi] = -1; continue; }\n                if (h > absoluteEpsilon) { pc++; signs[pi] = 1; continue;  }\n                zc++; signs[pi] = 0;\n            }\n\n            if (zc == count)\n            {\n                line = new Line3d(polygon[0], polygon[0]);\n                return false;\n            }\n            else if (pc == 0 && zc == 0)\n            {\n                line = new Line3d(V3d.NaN, V3d.NaN);\n                return false;\n            }\n            else if (nc == 0 && zc == 0)\n            {\n                line = new Line3d(V3d.NaN, V3d.NaN);\n                return false;\n            }\n            else\n            {\n                int pointcount = 0;\n                V3d[] linePoints = new V3d[2];\n                for (int i = 0; i < count; i++)\n                {\n                    int u = (i + 1) % count;\n\n                    if (signs[i] != signs[u] || signs[i] == 0 || signs[u] == 0)\n                    {\n                        if (plane.IntersectsLine(polygon[i], polygon[u], absoluteEpsilon, out V3d point))\n                        {\n                            linePoints[pointcount++] = point;\n                            //If Endpoint is on Plane => Next startpoint is on plane => same intersection point\n                            // => skip all following lines which start within absoluteEpsilon (whic have a zero sign)\n                            while (signs[(i + 1) % count] == 0) i++;\n                        }\n                    }\n                    if (pointcount == 2)\n                    {\n                        //\n                        line = new Line3d(linePoints[0], linePoints[1]);\n                        return true;\n                    }\n                }\n                line = new Line3d(V3d.NaN, V3d.NaN);\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Plane3d intersects Cylinder3d\n\n        /// <summary>\n        /// Returns whether the given sphere and cylinder intersect.\n        /// </summary>\n        public static bool Intersects(this Plane3d plane, Cylinder3d cylinder)\n        {\n            if (plane.IsParallelToAxis(cylinder))\n            {\n                var distance = cylinder.P0.GetMinimalDistanceTo(plane);\n                return distance < cylinder.Radius;\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Tests if the given plane is parallel to the cylinder axis (i.e. the plane's normal is orthogonal to the axis).\n        /// The plane will intersect the cylinder in two rays or in one tangent line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelToAxis(this Plane3d plane, Cylinder3d cylinder)\n            => plane.Normal.IsOrthogonalTo(cylinder.Axis.Direction.Normalized);\n\n        /// <summary>\n        /// Tests if the given plane is orthogonal to the cylinder axis (i.e. the plane's normal is parallel to the axis).\n        /// The plane will intersect the cylinder in a circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalToAxis(this Plane3d plane, Cylinder3d cylinder)\n            => plane.Normal.IsParallelTo(cylinder.Axis.Direction.Normalized);\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in an ellipse.\n        /// This is only true if the plane is neither orthogonal nor parallel to the cylinder axis. Otherwise the intersection methods returning a circle or rays have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"ellipse\"></param>\n        public static bool Intersects(this Plane3d plane, Cylinder3d cylinder, out Ellipse3d ellipse)\n        {\n            if (plane.IsParallelToAxis(cylinder) || plane.IsOrthogonalToAxis(cylinder))\n            {\n                ellipse = Ellipse3d.Zero;\n                return false;\n            }\n\n            var dir = cylinder.Axis.Direction.Normalized;\n            cylinder.Axis.Ray3d.Intersects(plane, out _, out V3d center);\n            var cosTheta = dir.Dot(plane.Normal);\n\n            var eNormal = plane.Normal;\n            var eCenter = center;\n            var eMajor = (dir - cosTheta * eNormal).Normalized;\n            var eMinor = (eNormal.Cross(eMajor)).Normalized;\n            eMajor = eNormal.Cross(eMinor).Normalized; //to be sure - if ellipse is nearly a circle\n            eMajor = eMajor * cylinder.Radius / cosTheta.Abs();\n            eMinor *= cylinder.Radius;\n            ellipse = new Ellipse3d(eCenter, eNormal, eMajor, eMinor);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in a circle.\n        /// This is only true if the plane is orthogonal to the cylinder axis. Otherwise the intersection methods returning an ellipse or rays have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"circle\"></param>\n        public static bool Intersects(this Plane3d plane, Cylinder3d cylinder, out Circle3d circle)\n        {\n            if (plane.IsOrthogonalToAxis(cylinder))\n            {\n                circle = cylinder.GetCircle(cylinder.GetHeight(plane.Point));\n                return true;\n            }\n\n            circle = Circle3d.Zero;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in one or two rays.\n        /// This is only true if the plane is parallel to the cylinder axis. Otherwise the intersection methods returning an ellipse or a circle have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"rays\">Output of intersection rays. The array contains two rays (intersection), one ray (plane is tangent to cylinder) or no ray (no intersection).</param>\n        public static bool Intersects(this Plane3d plane, Cylinder3d cylinder, out Ray3d[] rays)\n        {\n            if (plane.IsParallelToAxis(cylinder))\n            {\n                var distance = cylinder.P0.GetMinimalDistanceTo(plane);\n                var center = cylinder.P0 - distance * plane.Normal;\n                var axis = cylinder.Axis.Direction.Normalized;\n\n                if (distance == cylinder.Radius) //one tangent line\n                {\n                    rays = new[] { new Ray3d(center, axis) };\n                    return true;\n                }\n                else //two intersection lines\n                {\n                    var offset = axis.Cross(plane.Normal);\n                    var extent = (cylinder.Radius.Square() - distance.Square()).Sqrt();\n                    rays = new[]\n                    {\n                        new Ray3d(center - extent * offset, axis),\n                        new Ray3d(center + extent * offset, axis)\n                    };\n                    return true;\n                }\n            }\n            rays = Array.Empty<Ray3d>();\n            return false;\n        }\n\n        #endregion\n\n\n        #region Sphere3d intersects Sphere3d (sm)\n\n        /// <summary>\n        /// Returns true if the spheres intersect, or one contains the other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Sphere3d s0, Sphere3d s1)\n            => (s0.Center - s1.Center).LengthSquared <= (s0.Radius + s1.Radius).Square();\n\n        #endregion\n\n\n        #region Box3d intersects Line3d\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool Intersects(this Box3d box, Line3d line)\n        {\n            var out0 = box.OutsideFlags(line.P0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(line.P1); if (out1 == 0) return true;\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n                this Box3d box, V3d p0, V3d p1)\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            return box.IntersectsLine(p0, p1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied, and have to be already individually tested against\n        /// intersection with the box.\n        /// </summary>\n        public static bool IntersectsLine(\n                this Box3d box, V3d p0, V3d p1, Box.Flags out0, Box.Flags out1)\n        {\n            if ((out0 & out1) != 0) return false;\n\n            V3d min = box.Min;\n            V3d max = box.Max;\n            var bf = out0 | out1;\n\n            if ((bf & Box.Flags.X) != 0)\n            {\n                double dx = p1.X - p0.X;\n                if ((bf & Box.Flags.MinX) != 0)\n                {\n                    if (dx == 0 && p0.X < min.X) return false;\n                    double t = (min.X - p0.X) / dx;\n                    V3d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinX) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxX) != 0)\n                {\n                    if (dx == 0 && p0.X > max.X) return false;\n                    double t = (max.X - p0.X) / dx;\n                    V3d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxX) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Y) != 0)\n            {\n                double dy = p1.Y - p0.Y;\n                if ((bf & Box.Flags.MinY) != 0)\n                {\n                    if (dy == 0 && p0.Y < min.Y) return false;\n                    double t = (min.Y - p0.Y) / dy;\n                    V3d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinY) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxY) != 0)\n                {\n                    if (dy == 0 && p0.Y > max.Y) return false;\n                    double t = (max.Y - p0.Y) / dy;\n                    V3d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxY) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Z) != 0)\n            {\n                double dz = p1.Z - p0.Z;\n                if ((bf & Box.Flags.MinZ) != 0)\n                {\n                    if (dz == 0 && p0.Z < min.Z) return false;\n                    double t = (min.Z - p0.Z) / dz;\n                    V3d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinZ) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxZ) != 0)\n                {\n                    if (dz == 0 && p0.Z > max.Z) return false;\n                    double t = (max.Z - p0.Z) / dz;\n                    V3d p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxZ) == 0)\n                        return true;\n                }\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region Box3d intersects Ray3d (haaser)\n\n        public static bool Intersects(this Box3d box, Ray3d ray, out double t)\n        {\n            Box.Flags out0 = box.OutsideFlags(ray.Origin);\n\n            if (out0 == 0)\n            {\n                t = 0;\n                return true;\n            }\n\n            Box3d largeBox = box.EnlargedByRelativeEps(1E-5);\n            double tmin = double.PositiveInfinity;\n            double ttemp;\n            if ((out0 & Box.Flags.X) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.X))\n                {\n                    if ((out0 & Box.Flags.MinX) != 0)\n                    {\n                        ttemp = (box.Min.X - ray.Origin.X) / ray.Direction.X;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxX) != 0)\n                    {\n                        ttemp = (box.Max.X - ray.Origin.X) / ray.Direction.X;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if ((out0 & Box.Flags.Y) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.Y))\n                {\n                    if ((out0 & Box.Flags.MinY) != 0)\n                    {\n                        ttemp = (box.Min.Y - ray.Origin.Y) / ray.Direction.Y;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxY) != 0)\n                    {\n                        ttemp = (box.Max.Y - ray.Origin.Y) / ray.Direction.Y;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if ((out0 & Box.Flags.Z) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.Z))\n                {\n                    if ((out0 & Box.Flags.MinZ) != 0)\n                    {\n                        ttemp = (box.Min.Z - ray.Origin.Z) / ray.Direction.Z;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxZ) != 0)\n                    {\n                        ttemp = (box.Max.Z - ray.Origin.Z) / ray.Direction.Z;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if (tmin < double.PositiveInfinity)\n            {\n                t = tmin;\n                return true;\n            }\n\n            t = double.NaN;\n            return false;\n        }\n\n\n        #endregion\n\n        #region Box3d intersects Plane3d\n\n        /// <summary>\n        /// Returns true if the box and the plane intersect or touch with a\n        /// supplied epsilon tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Box3d box, Plane3d plane, double eps)\n        {\n            var signs = box.GetIntersectionSignsWithPlane(plane, eps);\n            return signs != Signs.Negative && signs != Signs.Positive;\n        }\n\n        /// <summary>\n        /// Classify the position of all the eight vertices of a box with\n        /// respect to a supplied plane.\n        /// </summary>\n        public static Signs GetIntersectionSignsWithPlane(\n            this Box3d box, Plane3d plane, double eps)\n        {\n            var normal = plane.Normal;\n            var distance = plane.Distance;\n\n            double npMinX = normal.X * box.Min.X;\n            double npMaxX = normal.X * box.Max.X;\n            double npMinY = normal.Y * box.Min.Y;\n            double npMaxY = normal.Y * box.Max.Y;\n            double npMinZ = normal.Z * box.Min.Z;\n            double npMaxZ = normal.Z * box.Max.Z;\n\n            double hMinZ = npMinZ - distance;\n            double hMaxZ = npMaxZ - distance;\n\n            double hMinYMinZ = npMinY + hMinZ;\n            double hMaxYMinZ = npMaxY + hMinZ;\n            double hMinYMaxZ = npMinY + hMaxZ;\n            double hMaxYMaxZ = npMaxY + hMaxZ;\n\n            return (npMinX + hMinYMinZ).GetSigns(eps)\n                 | (npMaxX + hMinYMinZ).GetSigns(eps)\n                 | (npMinX + hMaxYMinZ).GetSigns(eps)\n                 | (npMaxX + hMaxYMinZ).GetSigns(eps)\n                 | (npMinX + hMinYMaxZ).GetSigns(eps)\n                 | (npMaxX + hMinYMaxZ).GetSigns(eps)\n                 | (npMinX + hMaxYMaxZ).GetSigns(eps)\n                 | (npMaxX + hMaxYMaxZ).GetSigns(eps);\n        }\n\n        /// <summary>\n        /// Returns true if the box intersects the supplied plane. The\n        /// bounding boxes of the resulting parts are returned in the out\n        /// parameters.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Signs GetIntersectionSigns(\n                this Box3d box, Plane3d plane, double eps,\n                out Box3d negBox, out Box3d zeroBox, out Box3d posBox)\n        {\n            return box.GetIntersectionSigns(plane.Normal, plane.Distance, eps,\n                                       out negBox, out zeroBox, out posBox);\n        }\n\n        /// <summary>\n        /// Returns true if the box intersects the supplied plane. The\n        /// bounding boxes of the resulting parts are returned in the out\n        /// parameters.\n        /// </summary>\n        public static Signs GetIntersectionSigns(\n                this Box3d box, V3d normal, double distance, double eps,\n                out Box3d negBox, out Box3d zeroBox, out Box3d posBox)\n        {\n            double npMinX = normal.X * box.Min.X;\n            double npMaxX = normal.X * box.Max.X;\n            double npMinY = normal.Y * box.Min.Y;\n            double npMaxY = normal.Y * box.Max.Y;\n            double npMinZ = normal.Z * box.Min.Z;\n            double npMaxZ = normal.Z * box.Max.Z;\n\n            var ha = new double[8];\n\n            double hMinZ = npMinZ - distance;\n            double hMaxZ = npMaxZ - distance;\n\n            double hMinYMinZ = npMinY + hMinZ;\n            ha[0] = npMinX + hMinYMinZ;\n            ha[1] = npMaxX + hMinYMinZ;\n\n            double hMaxYMinZ = npMaxY + hMinZ;\n            ha[2] = npMinX + hMaxYMinZ;\n            ha[3] = npMaxX + hMaxYMinZ;\n\n            double hMinYMaxZ = npMinY + hMaxZ;\n            ha[4] = npMinX + hMinYMaxZ;\n            ha[5] = npMaxX + hMinYMaxZ;\n\n            double hMaxYMaxZ = npMaxY + hMaxZ;\n            ha[6] = npMinX + hMaxYMaxZ;\n            ha[7] = npMaxX + hMaxYMaxZ;\n\n            Signs all = Signs.None;\n            var sa = new Signs[8];\n            for (int i = 0; i < 8; i++) { sa[i] = ha[i].GetSigns(eps); all |= sa[i]; }\n\n            negBox = Box3d.Invalid;\n            zeroBox = Box3d.Invalid;\n            posBox = Box3d.Invalid;\n\n            if (all == Signs.Zero) { zeroBox = box; return all; }\n            if (all == Signs.Positive) { posBox = box; return all; }\n            if (all == Signs.Negative) { negBox = box; return all; }\n\n            var pa = box.ComputeCorners();\n\n            for (int i = 0; i < 8; i++)\n            {\n                if (sa[i] == Signs.Negative)\n                    negBox.ExtendBy(pa[i]);\n                else if (sa[i] == Signs.Positive)\n                    posBox.ExtendBy(pa[i]);\n                else\n                {\n                    negBox.ExtendBy(pa[i]);\n                    zeroBox.ExtendBy(pa[i]);\n                    posBox.ExtendBy(pa[i]);\n                }\n            }\n\n            if (all == Signs.NonPositive) { posBox = Box3d.Invalid; return all; }\n            if (all == Signs.NonNegative) { negBox = Box3d.Invalid; return all; }\n\n            for (int ei = 0; ei < 12; ei++)\n            {\n                int i0 = c_cubeEdgeVertex0[ei], i1 = c_cubeEdgeVertex1[ei];\n\n                if ((sa[i0] == Signs.Negative && sa[i1] == Signs.Positive)\n                    || (sa[i0] == Signs.Positive && sa[i1] == Signs.Negative))\n                {\n                    double h0 = ha[i0];\n                    double t = h0 / (h0 - ha[i1]);\n                    V3d p0 = pa[i0];\n                    V3d sp = p0 + t * (pa[i1] - p0);\n                    negBox.ExtendBy(sp);\n                    zeroBox.ExtendBy(sp);\n                    posBox.ExtendBy(sp);\n                }\n            }\n\n            return all;\n        }\n\n        #endregion\n\n        #region Box3d intersects Sphere3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Box3d box, Sphere3d sphere\n             )\n        {\n            V3d v = sphere.Center.GetClosestPointOn(box) - sphere.Center;\n            return sphere.RadiusSquared >= v.LengthSquared;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Box3d box, Cylinder3d cylinder\n             )\n        {\n\n            return box.Intersects(cylinder.BoundingBox3d);\n\n            //throw new NotImplementedException();\n        }\n\n        #endregion\n\n        #region Box3d intersects Triangle3d\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this Box3d box, Triangle3d triangle\n             )\n        {\n            return box.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect.\n        /// </summary>\n        public static bool IntersectsTriangle(\n             this Box3d box, V3d p0, V3d p1, V3d p2\n             )\n        {\n            /* ---------------------------------------------------------------\n               If one of the points of the triangle is inside the box, it\n               intersects, of course.\n            --------------------------------------------------------------- */\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n            return box.IntersectsTriangle(p0, p1, p2, out0, out1, out2);\n        }\n\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect. The outside\n        /// flags of the triangle vertices with respect to the box have to be\n        /// supplied, and already be individually tested for intersection with\n        /// the box.\n        /// </summary>\n        public static bool IntersectsTriangle(\n             this Box3d box, V3d p0, V3d p1, V3d p2,\n             Box.Flags out0, Box.Flags out1, Box.Flags out2\n             )\n        {\n            /* ---------------------------------------------------------------\n                If all of the points of the triangle are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2) != 0) return false;\n\n            /* ---------------------------------------------------------------\n                If two points of the triangle are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p0, out2, out0)) return true;\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the triangle go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n            --------------------------------------------------------------- */\n            Ray3d ray = new Ray3d(box.Min, box.Size);\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Box3d intersects Quad3d (haaser)\n\n        public static bool Intersects(\n            this Box3d box, Quad3d quad\n            )\n        {\n            Box.Flags out0 = box.OutsideFlags(quad.P0); if (out0 == 0) return true;\n            Box.Flags out1 = box.OutsideFlags(quad.P1); if (out1 == 0) return true;\n            Box.Flags out2 = box.OutsideFlags(quad.P2); if (out2 == 0) return true;\n            Box.Flags out3 = box.OutsideFlags(quad.P3); if (out3 == 0) return true;\n\n            return box.IntersectsQuad(quad.P0, quad.P1, quad.P2, quad.P3, out0, out1, out2, out3);\n        }\n\n        public static bool IntersectsQuad(\n             this Box3d box, V3d p0, V3d p1, V3d p2, V3d p3\n             )\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n            var out3 = box.OutsideFlags(p3); if (out3 == 0) return true;\n\n            return box.IntersectsQuad(p0, p1, p2, p3, out0, out1, out2, out3);\n        }\n\n        public static bool IntersectsQuad(\n            this Box3d box, V3d p0, V3d p1, V3d p2, V3d p3,\n            Box.Flags out0, Box.Flags out1, Box.Flags out2, Box.Flags out3\n            )\n        {\n            /* ---------------------------------------------------------------\n                If all of the points of the quad are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2 & out3) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n                If two points of the quad are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p3, out2, out3)) return true;\n            if (box.IntersectsLine(p3, p0, out3, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the quad go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n            --------------------------------------------------------------- */\n            Ray3d ray = new Ray3d(box.Min, box.Size);\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Box3d intersects Polygon3d (haaser)\n\n        public static bool Intersects(this Box3d box, Polygon3d poly)\n        {\n            int edges = poly.PointCount;\n            Box.Flags[] outside = new Box.Flags[edges];\n            for (int i = 0; i < edges; i++)\n            {\n                outside[i] = box.OutsideFlags(poly[i]); if (outside[i] == 0) return true;\n            }\n\n            /* ---------------------------------------------------------------\n                If all of the points of the polygon are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            Box.Flags sum = outside[0];\n            for (int i = 1; i < edges; i++) sum &= outside[i];\n            if (sum != 0) return false;\n\n            /* ---------------------------------------------------------------\n                If two points of the polygon are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            int u;\n            for (int i = 0; i < edges; i++)\n            {\n                u = (i + 1) % edges;\n                if (box.IntersectsLine(poly[i], poly[u], outside[i], outside[u])) return true;\n            }\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the polygon go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n                The polygon needs to be triangulated for this check\n            --------------------------------------------------------------- */\n\n            int[] tris = poly.ComputeTriangulationOfConcavePolygon(1E-5);\n\n            Ray3d ray = new Ray3d(box.Min, box.Size);\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region Box3d intersects Projection-Trafo (haaser)\n\n        /// <summary>\n        /// returns true if the Box3d and the frustum described by the M44d intersect or the frustum contains the Box3d\n        /// Assumes DirectX clip-space:\n        ///     -w &lt; x &lt; w\n        ///     -w &lt; y &lt; w\n        ///      0 &lt; z &lt; w\n        /// </summary>\n        public static bool IntersectsFrustum(this Box3d box, M44d projection)\n        {\n            //Let's look at the left clip-plane\n            //which corresponds to:\n            //-w < x\n            //  # which can easily be transformed to:\n            //0 < x + w\n            //  # for a given vector v this means (* is a dot product here)\n            //0 < proj.R0 * v + proj.R3 * v\n            //  # or in other words:\n            //0 < (proj.R0 + proj.R3) * v\n\n            //therefore (proj.R0 + proj.R3) is the plane describing the left clip-plane.\n            //The other planes can be derived in a similar way (only the near plane is a little different)\n            //see http://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/ for a full explanation\n\n            var r0 = projection.R0;\n            var r1 = projection.R1;\n            var r2 = projection.R2;\n            var r3 = projection.R3;\n\n\n            V4d plane;\n            V3d n;\n\n            //left\n            plane = r3 + r0;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out V3d min, out V3d max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //right\n            plane = r3 - r0;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //top\n            plane = r3 + r1;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //bottom\n            plane = r3 - r1;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //near\n            plane = r2;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //far\n            plane = r3 - r2;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n\n            return true;\n        }\n\n\n\n        #endregion\n\n\n        #region Hull3d intersects Line3d\n\n        /// <summary>\n        /// returns true if the Hull3d and the Line3d intersect or the Hull3d contains the Line3d\n        /// [Hull3d-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Hull3d hull,\n            Line3d line\n            )\n        {\n            if (hull.Contains(line.P0)) return true;\n            if (hull.Contains(line.P1)) return true;\n\n            return hull.Intersects(line.Ray3d, 0, 1, out _);\n        }\n\n        /// <summary>\n        /// returns true if the Hull3d and the Line between p0 and p1 intersect or the Hull3d contains the Line\n        /// [Hull3d-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this Hull3d hull,\n            V3d p0, V3d p1\n            )\n        {\n            return hull.Intersects(new Line3d(p0, p1));\n        }\n\n        #endregion\n\n        #region Hull3d intersects Ray3d\n\n        /// <summary>\n        /// returns true if the Hull3d and the Ray3d intersect\n        /// [Hull3d-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Hull3d hull,\n            Ray3d ray\n            )\n        {\n            return hull.Intersects(ray, double.NegativeInfinity, double.PositiveInfinity, out _);\n        }\n\n        /// <summary>\n        /// returns true if the Hull3d and the Ray3d intersect\n        /// the out parameter t holds the ray-parameter where an intersection was found\n        /// [Hull3d-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this Hull3d hull,\n            Ray3d ray,\n            out double t\n            )\n        {\n            return hull.Intersects(ray, double.NegativeInfinity, double.PositiveInfinity, out t);\n        }\n\n        /// <summary>\n        /// returns true if the Hull3d and the Ray3d intersect and the\n        /// ray-parameter for the intersection is between t_min and t_max\n        /// the out parameter t holds the ray-parameter where an intersection was found\n        /// [Hull3d-Normals must point outside]\n        /// </summary>\n        public static bool Intersects(\n            this Hull3d hull,\n            Ray3d ray,\n            double t_min, double t_max,\n            out double t\n            )\n        {\n            if (!double.IsInfinity(t_min) && hull.Contains(ray.GetPointOnRay(t_min))) { t = t_min; return true; }\n            if (!double.IsInfinity(t_max) && hull.Contains(ray.GetPointOnRay(t_max))) { t = t_max; return true; }\n\n            var planes = hull.PlaneArray;\n            for (int i = 0; i < planes.Length; i++)\n            {\n                if (!Fun.IsTiny(planes[i].Normal.Dot(ray.Direction)) &&\n                    ray.Intersects(planes[i], out double temp_t) &&\n                    temp_t >= t_min && temp_t <= t_max)\n                {\n                    V3d candidatePoint = ray.GetPointOnRay(temp_t);\n                    bool contained = true;\n\n                    for (int u = 0; u < planes.Length; u++)\n                    {\n                        if (u != i && planes[u].Height(candidatePoint) > Constant<double>.PositiveTinyValue)\n                        {\n                            contained = false;\n                            break;\n                        }\n                    }\n\n                    if (contained)\n                    {\n                        t = temp_t;\n                        return true;\n                    }\n                }\n            }\n\n            t = double.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region Hull3d intersects Plane3d\n\n        /// <summary>\n        /// returns true if the Hull3d and the Plane3d intersect\n        /// [Hull3d-Normals must point outside]\n        /// </summary>\n        public static bool Intersects(\n            this Hull3d hull,\n            Plane3d plane\n            )\n        {\n            foreach (var p in hull.PlaneArray)\n            {\n                if (!p.Normal.IsParallelTo(plane.Normal) && p.Intersects(plane, out Ray3d ray))\n                {\n                    if (hull.Intersects(ray)) return true;\n                }\n            }\n\n            return false;\n        }\n\n        #endregion\n\n        #region Hull3d intersects Box3d\n\n        /// <summary>\n        /// Returns true if the hull and the box intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Hull3d hull, Box3d box\n            )\n        {\n            if (box.IsInvalid) return false;\n            bool intersecting = false;\n            foreach (Plane3d p in hull.PlaneArray)\n            {\n                box.GetMinMaxInDirection(p.Normal, out V3d min, out V3d max);\n                if (p.Height(min) > 0) return false; // outside\n                if (p.Height(max) >= 0) intersecting = true;\n            }\n            if (intersecting) return true; // intersecting\n            return true; // inside\n        }\n\n        /// Test hull against intersection of the supplied bounding box.\n        /// Note that this is a conservative test, since in some cases\n        /// around the edges of the hull it may return true although the\n        /// hull does not intersect the box.\n        public static bool Intersects(\n                this FastHull3d fastHull,\n                Box3d box)\n        {\n            var planes = fastHull.Hull.PlaneArray;\n            int count = planes.Length;\n            bool intersecting = false;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCornerIndex = fastHull.MinCornerIndexArray[pi];\n                if (planes[pi].Height(box.Corner(minCornerIndex)) > 0)\n                    return false;\n                if (planes[pi].Height(box.Corner(minCornerIndex ^ 7)) >= 0)\n                    intersecting = true;\n            }\n            if (intersecting) return true;\n            return true;\n        }\n\n        #endregion\n\n        #region Hull3d intersects Sphere3d\n\n        /// <summary>\n        /// Returns true if the hull and the sphere intersect.\n        /// </summary>\n        public static bool Intersects(\n            this Hull3d hull, Sphere3d sphere\n            )\n        {\n            if (sphere.IsInvalid) return false;\n            bool intersecting = false;\n            foreach (Plane3d p in hull.PlaneArray)\n            {\n                double height = p.Height(sphere.Center);\n                if (height > sphere.Radius) return false; // outside\n                if (height.Abs() < sphere.Radius) intersecting = true;\n            }\n            if (intersecting) return true; // intersecting\n            return true; // inside\n        }\n\n        #endregion\n\n\n        #region Plane3d intersects Box3d\n\n        /// <summary>\n        /// Returns true if the box and the plane intersect or touch with a\n        /// supplied epsilon tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Plane3d plane, double eps, Box3d box)\n            => box.Intersects(plane, eps);\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/IntersectionTests_template.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    public static partial class GeometryFun\n    {\n        private static readonly int[] c_cubeEdgeVertex0 =\n            new int[] { 0, 2, 4, 6, 0, 1, 4, 5, 0, 1, 2, 3 };\n\n        private static readonly int[] c_cubeEdgeVertex1 =\n            new int[] { 1, 3, 5, 7, 2, 3, 6, 7, 4, 5, 6, 7 };\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var v4t = \"V4\" + tc;\n        //#   var m44t = \"M44\" + tc;\n        //#   var line2t = \"Line2\" + tc;\n        //#   var line3t = \"Line3\" + tc;\n        //#   var plane2t = \"Plane2\" + tc;\n        //#   var plane3t = \"Plane3\" + tc;\n        //#   var ray2t = \"Ray2\" + tc;\n        //#   var ray3t = \"Ray3\" + tc;\n        //#   var circle2t = \"Circle2\" + tc;\n        //#   var circle3t = \"Circle3\" + tc;\n        //#   var quad2t = \"Quad2\" + tc;\n        //#   var quad3t = \"Quad3\" + tc;\n        //#   var range1t = \"Range1\" + tc;\n        //#   var box2t = \"Box2\" + tc;\n        //#   var box3t = \"Box3\" + tc;\n        //#   var hull2t = \"Hull2\" + tc;\n        //#   var hull3t = \"Hull3\" + tc;\n        //#   var sphere3t = \"Sphere3\" + tc;\n        //#   var cylinder3t = \"Cylinder3\" + tc;\n        //#   var ellipse3t = \"Ellipse3\" + tc;\n        //#   var triangle2t = \"Triangle2\" + tc;\n        //#   var triangle3t = \"Triangle3\" + tc;\n        //#   var polygon2t = \"Polygon2\" + tc;\n        //#   var polygon3t = \"Polygon3\" + tc;\n        //#   var euclidean3t = \"Euclidean3\" + tc;\n        //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n        //#   var eminus5 = isDouble ? \"1E-5\" : \"1E-5f\";\n        //#   var epsdot = isDouble ? \"1E-7\" : \"1E-4f\";\n        // Contains-tests should return true if the contained object is\n        // either entirely inside the containing object or lies on the\n        // boundary of the containing object.\n\n        #region __triangle2t__ contains __v2t__\n\n        public static bool Contains(\n            this __triangle2t__ triangle, __v2t__ point\n            )\n        {\n            var v0p = point - triangle.P0;\n            return triangle.Line01.LeftValueOfDir(v0p) >= 0\n                    && triangle.Line02.RightValueOfDir(v0p) >= 0\n                    && triangle.Line12.LeftValueOfPos(point) >= 0;\n        }\n\n        #endregion\n\n        #region __triangle2t__ contains __line2t__ (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __triangle2t__ triangle, __line2t__ linesegment)\n            => triangle.Contains(linesegment.P0) && triangle.Contains(linesegment.P1);\n\n        #endregion\n\n        #region __triangle2t__ contains __triangle2t__ (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __triangle2t__ triangle, __triangle2t__ other)\n            => triangle.Contains(other.P0) && triangle.Contains(other.P1) && triangle.Contains(other.P2);\n\n        #endregion\n\n        #region __triangle2t__ contains __quad2t__ (sm)\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __triangle2t__ triangle, __quad2t__ q)\n            => triangle.Contains(q.P0) && triangle.Contains(q.P1) && triangle.Contains(q.P2) && triangle.Contains(q.P3);\n\n        #endregion\n\n        #region __triangle2t__ contains __circle2t__\n\n        public static bool Contains(this __triangle2t__ triangle, __circle2t__ circle)\n        {\n            var center = circle.Center;\n            return triangle.Contains(center)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line01)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line12)\n                    && circle.Radius <= center.GetMinimalDistanceTo(triangle.Line20);\n        }\n\n        #endregion\n\n\n        #region __circle2t__ contains __v2t__ (sm)\n\n        /// <summary>\n        /// True if point p is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __circle2t__ circle, __v2t__ p)\n            => (p - circle.Center).LengthSquared <= circle.RadiusSquared;\n\n        #endregion\n\n        #region __circle2t__ contains __line2t__ (sm)\n\n        /// <summary>\n        /// True if line segment is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __circle2t__ circle, __line2t__ l)\n            => circle.Contains(l.P0) && circle.Contains(l.P1);\n\n        #endregion\n\n        #region __circle2t__ contains __triangle2t__ (sm)\n\n        /// <summary>\n        /// True if triangle is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __circle2t__ circle, __triangle2t__ t)\n            => circle.Contains(t.P0) && circle.Contains(t.P1) && circle.Contains(t.P2);\n\n        #endregion\n\n        #region __circle2t__ contains __quad2t__ (sm)\n\n        /// <summary>\n        /// True if quad is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __circle2t__ circle, __quad2t__ q)\n            => circle.Contains(q.P0) && circle.Contains(q.P1) && circle.Contains(q.P2) && circle.Contains(q.P3);\n\n        #endregion\n\n        #region __circle2t__ contains __circle2t__ (sm)\n\n        /// <summary>\n        /// True if other circle is contained in this circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __circle2t__ circle, __circle2t__ other)\n            => (other.Center - circle.Center).Length + other.Radius <= circle.Radius;\n\n        #endregion\n\n\n        #region __quad2t__ contains __v2t__ (haaser)\n\n        /// <summary>\n        /// True if point is contained in this quad.\n        /// </summary>\n        public static bool Contains(this __quad2t__ quad, __v2t__ point)\n        {\n            return LeftValOfPos(0, 1, ref point) >= 0 &&\n                   LeftValOfPos(1, 2, ref point) >= 0 &&\n                   LeftValOfPos(2, 3, ref point) >= 0 &&\n                   LeftValOfPos(3, 0, ref point) >= 0;\n\n            __rtype__ LeftValOfPos(int i0, int i1, ref __v2t__ p)\n                => (p.X - quad[i0].X) * (quad[i0].Y - quad[i1].Y) + (p.Y - quad[i0].Y) * (quad[i1].X - quad[i0].X);\n        }\n\n        #endregion\n\n        #region __quad2t__ contains __line2t__\n\n        /// <summary>\n        /// True if line segment is contained in this quad.\n        /// </summary>\n        public static bool Contains(this __quad2t__ quad, __line2t__ l)\n            => quad.Contains(l.P0) && quad.Contains(l.P1);\n\n        #endregion\n\n        #region __quad2t__ contains __triangle2t__\n\n        /// <summary>\n        /// True if triangle is contained in this quad.\n        /// </summary>\n        public static bool Contains(this __quad2t__ quad, __triangle2t__ t)\n            => quad.Contains(t.P0) && quad.Contains(t.P1) && quad.Contains(t.P2);\n\n        #endregion\n\n        #region __quad2t__ contains __quad2t__\n\n        /// <summary>\n        /// True if other quad is contained in this quad.\n        /// </summary>\n        public static bool Contains(this __quad2t__ quad, __quad2t__ q)\n            => quad.Contains(q.P0) && quad.Contains(q.P1) && quad.Contains(q.P2) && quad.Contains(q.P3);\n\n        #endregion\n\n        #region __quad2t__ contains __circle2t__\n\n        /// <summary>\n        /// True if circle is contained in this quad.\n        /// </summary>\n        public static bool Contains(this __quad2t__ quad, __circle2t__ circle)\n        {\n            var center = circle.Center;\n            return quad.Contains(center)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line01)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line12)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line23)\n                    && circle.Radius <= center.GetMinimalDistanceTo(quad.Line30);\n        }\n\n        #endregion\n\n\n        #region __box3t__ contains __quad3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n            this __box3t__ box, __quad3t__ quad\n            )\n        {\n            return box.Contains(quad.P0)\n                    && box.Contains(quad.P1)\n                    && box.Contains(quad.P2)\n                    && box.Contains(quad.P3);\n        }\n\n        #endregion\n\n        #region __box3t__ contains __triangle3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n             this __box3t__ box, __triangle3t__ triangle\n            )\n        {\n            return box.Contains(triangle.P0)\n                    && box.Contains(triangle.P1)\n                    && box.Contains(triangle.P2);\n        }\n\n        #endregion\n\n        #region __box3t__ contains __sphere3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n             this __box3t__ box, __sphere3t__ sphere\n            )\n        {\n            return box.Contains(sphere.Center)\n                    && !box.Intersects(sphere);\n        }\n\n        #endregion\n\n        #region __box3t__ contains __cylinder3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(\n            this __box3t__ box, __cylinder3t__ cylinder\n           )\n        {\n            return box.Contains(cylinder.Center)\n                    && !box.Intersects(cylinder);\n        }\n\n        #endregion\n\n\n        #region __hull3t__ contains __v3t__\n\n        /// <summary>\n        /// Hull normals are expected to point outside.\n        /// </summary>\n        public static bool Contains(this __hull3t__ hull, __v3t__ point)\n        {\n            var planes = hull.PlaneArray;\n            for (var i = 0; i < planes.Length; i++)\n            {\n                if (planes[i].Height(point) > 0)\n                    return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region __hull3t__ contains __sphere3t__ (sm)\n\n        /// <summary>\n        /// Hull normals are expected to point outside.\n        /// </summary>\n        public static bool Contains(this __hull3t__ hull, __sphere3t__ sphere)\n        {\n            var planes = hull.PlaneArray;\n            var negativeRadius = -sphere.Radius;\n            for (var i = 0; i < planes.Length; i++)\n            {\n                if (planes[i].Height(sphere.Center) > negativeRadius)\n                    return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n\n        #region __polygon2t__ contains __v2t__ (haaser)\n\n        internal static V3i InsideTriangleFlags(ref __v2t__ p0, ref __v2t__ p1, ref __v2t__ p2, ref __v2t__ point)\n        {\n            __v2t__ n0 = new __v2t__(p0.Y - p1.Y, p1.X - p0.X);\n            __v2t__ n1 = new __v2t__(p1.Y - p2.Y, p2.X - p1.X);\n            __v2t__ n2 = new __v2t__(p2.Y - p0.Y, p0.X - p2.X);\n\n            int t0 = Fun.Sign(n0.Dot(point - p0));\n            int t1 = Fun.Sign(n1.Dot(point - p1));\n            int t2 = Fun.Sign(n2.Dot(point - p2));\n\n            if (t0 == 0) t1 = 1;\n            if (t1 == 0) t1 = 1;\n            if (t2 == 0) t2 = 1;\n\n            return new V3i(t0, t1, t2);\n        }\n\n        internal static V3i InsideTriangleFlags(ref __v2t__ p0, ref __v2t__ p1, ref __v2t__ p2, ref __v2t__ point, int t0)\n        {\n            __v2t__ n1 = new __v2t__(p1.Y - p2.Y, p2.X - p1.X);\n            __v2t__ n2 = new __v2t__(p2.Y - p0.Y, p0.X - p2.X);\n\n            int t1 = Fun.Sign(n1.Dot(point - p1));\n            int t2 = Fun.Sign(n2.Dot(point - p2));\n\n            if (t1 == 0) t1 = 1;\n            if (t2 == 0) t2 = 1;\n\n            return new V3i(t0, t1, t2);\n        }\n\n        /// <summary>\n        /// Returns true if the __polygon2t__ contains the given point.\n        /// Works with all (convex and non-convex) Polygons.\n        /// Assumes that the Vertices of the Polygon are sorted counter clockwise\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __polygon2t__ poly, __v2t__ point)\n        {\n            return poly.Contains(point, true);\n        }\n\n        /// <summary>\n        /// Returns true if the __polygon2t__ contains the given point.\n        /// Works with all (convex and non-convex) Polygons.\n        /// CCW represents the sorting order of the Polygon-Vertices (true -> CCW, false -> CW)\n        /// </summary>\n        public static bool Contains(this __polygon2t__ poly, __v2t__ point, bool CCW)\n        {\n            int pc = poly.PointCount;\n            if (pc < 3)\n                return false;\n            int counter = 0;\n            __v2t__ p0 = poly[0], p1 = poly[1], p2 = poly[2];\n            V3i temp = InsideTriangleFlags(ref p0, ref p1, ref p2, ref point);\n            int t2_cache = temp.Z;\n            if (temp.X == temp.Y && temp.Y == temp.Z) counter += temp.X;\n            for (int pi = 3; pi < pc; pi++)\n            {\n                p1 = p2; p2 = poly[pi];\n                temp = InsideTriangleFlags(ref p0, ref p1, ref p2, ref point, -t2_cache);\n                t2_cache = temp.Z;\n                if (temp.X == temp.Y && temp.Y == temp.Z) counter += temp.X;\n            }\n            if (CCW) return counter > 0;\n            else return counter < 0;\n        }\n\n        #endregion\n\n\n        #region __plane3t__ +- eps contains __v3t__ (sm)\n\n        /// <summary>\n        /// Returns true if point is within given eps to plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __plane3t__ plane, __rtype__ eps, __v3t__ point)\n        {\n            var d = plane.Height(point);\n            return d >= -eps && d <= eps;\n        }\n\n        #endregion\n\n        #region __plane3t__ +- eps contains __box3t__ (sm)\n\n        /// <summary>\n        /// Returns true if the space within eps to a plane fully contains the given box.\n        /// </summary>\n        public static bool Contains(this __plane3t__ plane, __rtype__ eps, __box3t__ box)\n        {\n            var corners = box.ComputeCorners();\n            for (var i = 0; i < 8; i++)\n            {\n                var d = plane.Height(corners[i]);\n                if (d < -eps || d > eps) return false;\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region __polygon3t__ +- eps contains __v3t__ (sm)\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __polygon3t__ polygon, __rtype__ eps, __v3t__ point, out __rtype__ distance)\n        {\n            var plane = polygon.Get__plane3t__();\n            distance = plane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            var w2p = plane.GetWorldToPlane();\n            var poly2d = new __polygon2t__(polygon.GetPointArray().Map(p => w2p.TransformPos(p).XY));\n            return poly2d.Contains(w2p.TransformPos(point).XY);\n        }\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __polygon3t__ polygon, __plane3t__ supportingPlane, __euclidean3t__ world2plane, __polygon2t__ poly2d, __rtype__ eps, __v3t__ point, out __rtype__ distance)\n        {\n            distance = supportingPlane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            return poly2d.Contains(world2plane.TransformPos(point).XY);\n        }\n\n        /// <summary>\n        /// Returns true if point is within given eps to polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Contains(this __polygon3t__ polygon, __plane3t__ supportingPlane, __m44t__ world2plane, __polygon2t__ poly2d, __rtype__ eps, __v3t__ point, out __rtype__ distance)\n        {\n            distance = supportingPlane.Height(point);\n            if (distance < -eps || distance > eps) return false;\n            return poly2d.Contains(world2plane.TransformPos(point).XY);\n        }\n\n        #endregion\n\n\n        // Intersection tests\n\n        #region __line2t__ intersects __line2t__\n\n        /// <summary>\n        /// Returns true if the two line segments intersect.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __line2t__ l0, __line2t__ l1)\n            => l0.IntersectsLine(l1.P0, l1.P1, out __v2t__ _);\n\n        /// <summary>\n        /// Returns true if the two line segments intersect.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __line2t__ l0, __line2t__ l1, out __v2t__ p)\n            => l0.IntersectsLine(l1.P0, l1.P1, out p);\n\n        /// <summary>\n        /// Returns true if the two line segments intersect within given tolerance.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __line2t__ l0, __line2t__ l1, __rtype__ absoluteEpsilon, out __v2t__ p)\n            => l0.IntersectsLine(l1.P0, l1.P1, absoluteEpsilon, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this __line2t__ line, __v2t__ p0, __v2t__ p1)\n            => line.IntersectsLine(p0, p1, out _);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this __line2t__ line, __v2t__ p0, __v2t__ p1, out __v2t__ p)\n            => line.IntersectsLine(p0, p1, false, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1.\n        /// The intersection point is returned in p.\n        /// If overlapping is true and the segments are parallel, then\n        /// the closest point to p0 of the intersection range is returned in p.\n        /// </summary>\n        public static bool IntersectsLine(\n            this __line2t__ line,\n            __v2t__ p0, __v2t__ p1,\n            bool overlapping,\n            out __v2t__ p\n            )\n        {\n            var a = line.P0 - p0;\n\n            if (Fun.IsTiny(a.LengthSquared))\n            {\n                p = p0;\n                return true;\n            }\n\n            var u = line.P1 - line.P0;\n            var v = p1 - p0;\n            var lu = u.Length;\n\n            var cross = u.X * v.Y - u.Y * v.X;\n            if (!Fun.IsTiny(cross))\n            {\n                // non-parallel lines\n                cross = 1 / cross;\n                var t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 > 1 || t0 < 0)\n                {\n                    p = __v2t__.NaN;\n                    return false;\n                }\n\n                __rtype__ t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                if (t1 > 1 || t1 < 0)\n                {\n                    p = __v2t__.NaN;\n                    return false;\n                }\n\n                p = line.P0 + u * t0;\n                return true;\n            }\n            else\n            {\n                // parallel lines\n                if (!overlapping)\n                {\n                    p = __v2t__.NaN;\n                    return false;\n                }\n\n                var normalizedDirection = u / lu;\n\n                var r0 = new __range1t__(0, lu);\n                var r1 = new __range1t__((p0 - line.P0).Dot(normalizedDirection), (p1 - line.P0).Dot(normalizedDirection));\n                r1.Repair();\n\n                if (r0.Intersects(r1, 0, out __range1t__ result))\n                {\n                    p = line.P0 + normalizedDirection * result.Min;\n                    return true;\n                }\n\n                p = __v2t__.NaN;\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1 within given tolerance.\n        /// The intersection point is returned in p.\n        /// If the segments are parallel and overlap, then no intersection is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(this __line2t__ line, __v2t__ p0, __v2t__ p1, __rtype__ absoluteEpsilon, out __v2t__ p)\n            => line.IntersectsLine(p0, p1, absoluteEpsilon, false, out p);\n\n        /// <summary>\n        /// Returns true if the line segment intersects the line segment between p0 and p1 within given tolerance.\n        /// The intersection point is returned in p.\n        /// If overlapping is true and the segments are parallel, then\n        /// the closest point to p0 of the intersection range is returned in p.\n        /// </summary>\n        public static bool IntersectsLine(\n            this __line2t__ line,\n            __v2t__ p0, __v2t__ p1,\n            __rtype__ absoluteEpsilon,\n            bool overlapping,\n            out __v2t__ p\n            )\n        {\n            var a = line.P0 - p0;\n\n            if (Fun.IsTiny(a.LengthSquared))\n            {\n                p = p0;\n                return true;\n            }\n\n            var u = line.P1 - line.P0;\n            var v = p1 - p0;\n\n            var lu = u.Length;\n            var lv = v.Length;\n            var relativeEpsilonU = absoluteEpsilon / lu;\n            var RelativeEpsilonV = absoluteEpsilon / lv;\n\n            var cross = u.X * v.Y - u.Y * v.X;\n            if (!Fun.IsTiny(cross))\n            {\n                // non-parallel lines\n                cross = 1 / cross;\n                var t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 > 1 + relativeEpsilonU || t0 < -relativeEpsilonU)\n                {\n                    p = __v2t__.NaN;\n                    return false;\n                }\n\n                var t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                if (t1 > 1 + RelativeEpsilonV || t1 < -RelativeEpsilonV)\n                {\n                    p = __v2t__.NaN;\n                    return false;\n                }\n\n                p = line.P0 + u * t0;\n                return true;\n            }\n            else\n            {\n                // parallel lines\n                if (!overlapping)\n                {\n                    p = __v2t__.NaN;\n                    return false;\n                }\n\n                var normalizedDirection = u / lu;\n\n                var r0 = new __range1t__(0, lu);\n                var r1 = new __range1t__((p0 - line.P0).Dot(normalizedDirection), (p1 - line.P0).Dot(normalizedDirection));\n                r1.Repair();\n\n                if (r0.Intersects(r1, absoluteEpsilon, out __range1t__ result))\n                {\n                    p = line.P0 + normalizedDirection * result.Min;\n                    return true;\n                }\n\n                p = __v2t__.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region __ray2t__ intersects __line2t__\n\n        /// <summary>\n        /// Returns true if the Ray and the Line intersect.\n        /// ATTENTION: Both-Sided Ray\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray2t__ ray,\n            __line2t__ line\n            )\n        {\n            return ray.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// returns true if the Ray and the Line intersect.\n        /// t holds the smallest Intersection-Parameter for the Ray\n        /// ATTENTION: t can be negative\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray2t__ ray,\n            __line2t__ line,\n            out __rtype__ t\n            )\n        {\n            return ray.IntersectsLine(line.P0, line.P1, out t);\n        }\n\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// ATTENTION: Both-Sided Ray\n        /// </summary>\n        public static bool IntersectsLine(\n            this __ray2t__ ray,\n            __v2t__ p0, __v2t__ p1\n            )\n        {\n            __v2t__ n = new __v2t__(-ray.Direction.Y, ray.Direction.X);\n\n            __rtype__ d0 = n.Dot(p0 - ray.Origin);\n            __rtype__ d1 = n.Dot(p1 - ray.Origin);\n\n            if (d0.Sign() != d1.Sign()) return true;\n            else if (Fun.IsTiny(d0) && Fun.IsTiny(d1)) return true;\n            else return false;\n        }\n\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// t holds the Intersection-Parameter for the Ray\n        /// If both Line-Points are on the Ray no Intersection is returned\n        /// ATTENTION: t can be negative\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this __ray2t__ ray,\n            __v2t__ p0, __v2t__ p1,\n            out __rtype__ t\n            )\n        {\n            return ray.IntersectsLine(p0, p1, false, out t);\n        }\n\n        /// <summary>\n        /// returns true if the Ray and the Line(p0,p1) intersect.\n        /// if overlapping is true t holds the smallest Intersection-Parameter for the Ray\n        /// if overlagging is false and both Line-Points are on the Ray no Intersection is returned\n        /// ATTENTION: t can be negative\n        /// </summary>\n        public static bool IntersectsLine(\n            this __ray2t__ ray,\n            __v2t__ p0, __v2t__ p1,\n            bool overlapping,\n            out __rtype__ t\n            )\n        {\n            __v2t__ a = p0 - ray.Origin;\n            __v2t__ u = p1 - p0;\n            __v2t__ v = ray.Direction;\n            __rtype__ lv2 = v.LengthSquared;\n\n\n            __rtype__ cross = u.X * v.Y - u.Y * v.X;\n            __rtype__ n = a.Y * u.X - a.X * u.Y;\n\n            if (!Fun.IsTiny(cross))\n            {\n                cross = 1 / cross;\n\n                __rtype__ t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                if (t0 >= 0 && t0 <= 1)\n                {\n                    t = n * cross;\n                    return true;\n                }\n\n                t = __rtype__.NaN;\n                return false;\n            }\n\n            if (Fun.IsTiny(n) && overlapping)\n            {\n                __rtype__ ta = v.Dot(a) / lv2;\n                __rtype__ tb = v.Dot(p1 - ray.Origin) / lv2;\n\n                if ((ta < 0 && tb > 0) || (ta > 0 && tb < 0))\n                {\n                    t = 0;\n                    return true;\n                }\n                else\n                {\n                    if (ta >= 0) t = Fun.Min(ta, tb);\n                    else t = Fun.Max(ta, tb);\n\n                    return true;\n                }\n            }\n\n            t = __rtype__.NaN;\n            return false;\n        }\n\n\n\n        #endregion\n\n        #region __ray2t__ intersects __ray2t__\n\n        /// <summary>\n        /// Returns true if the Rays intersect\n        /// ATTENTION: Both-Sided Rays\n        /// </summary>\n        public static bool Intersects(\n            this __ray2t__ r0,\n            __ray2t__ r1\n            )\n        {\n            if (!r0.Direction.IsParallelTo(r1.Direction)) return true;\n            else\n            {\n                __v2t__ n0 = new __v2t__(-r0.Direction.Y, r0.Direction.X);\n\n                if (Fun.IsTiny(n0.Dot(r1.Origin - r0.Origin))) return true;\n                else return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the Rays intersect\n        /// t0 and t1 are the corresponding Ray-Parameters for the Intersection\n        /// ATTENTION: Both-Sided Rays\n        /// </summary>\n        public static bool Intersects(\n            this __ray2t__ r0, __ray2t__ r1,\n            out __rtype__ t0, out __rtype__ t1\n            )\n        {\n            __v2t__ a = r0.Origin - r1.Origin;\n\n            if (r0.Origin.ApproximateEquals(r1.Origin, Constant<__rtype__>.PositiveTinyValue))\n            {\n                t0 = 0;\n                t1 = 0;\n                return true;\n            }\n\n            __v2t__ u = r0.Direction;\n            __v2t__ v = r1.Direction;\n\n            __rtype__ cross = u.X * v.Y - u.Y * v.X;\n\n            if (!Fun.IsTiny(cross))\n            {\n                //Rays not parallel\n                cross = 1 / cross;\n\n                t0 = (a.Y * v.X - a.X * v.Y) * cross;\n                t1 = (a.Y * u.X - a.X * u.Y) * cross;\n                return true;\n            }\n            else\n            {\n                t0 = __rtype__.NaN;\n                t1 = __rtype__.NaN;\n                //Rays are parallel\n                if (Fun.IsTiny(a.Y * u.X - a.X * u.Y)) return true;\n                else return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the Rays intersect.\n        /// </summary>\n        public static bool Intersects(this __ray2t__ r0, __ray2t__ r1, out __rtype__ t)\n        {\n            __v2t__ a = r1.Origin - r0.Origin;\n            if (a.Abs().AllSmaller(Constant<__rtype__>.PositiveTinyValue))\n            {\n                t = 0;\n                return true; // Early exit when rays have same origin\n            }\n\n            __rtype__ cross = r0.Direction.Dot270(r1.Direction);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n            {\n                t = r1.Direction.Dot90(a) / cross;\n                return true;\n            }\n            else // Rays are parallel\n            {\n                t = __rtype__.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region __ray2t__ intersects __circle2t__\n\n        /// <summary>\n        /// Computes the intersection between the given <see cref=\"__ray2t__\"/> and <see cref=\"__circle2t__\"/>.\n        /// </summary>\n        /// <param name=\"ray\">The ray to intersect.</param>\n        /// <param name=\"circle\">The circle to intersect the ray with.</param>\n        /// <param name=\"t0\">The ray parameter of the first intersection. Set to infinity if there is no intersection.</param>\n        /// <param name=\"t1\">The ray parameter of the second intersection. Set to infinity if there is no intersection.</param>\n        /// <returns>True if there is an intersection, false otherwise.</returns>\n        public static bool Intersects(this __ray2t__ ray, __circle2t__ circle, out __rtype__ t0, out __rtype__ t1)\n        {\n            var p = ray.Origin - circle.Center;\n            var a = ray.Direction.X.Square() + ray.Direction.Y.Square();\n            var b = 2 * ray.Direction.X * p.X + 2 * ray.Direction.Y * p.Y;\n            var c = p.X.Square() + p.Y.Square() - circle.Radius.Square();\n            var d = b.Square() - 4 * a * c;\n\n            if (d < 0)\n            {\n                t0 = __rtype__.PositiveInfinity;\n                t1 = __rtype__.PositiveInfinity;\n                return false;\n            }\n            else\n            {\n                var div = 1 / (a + a);\n                d = d.Sqrt();\n                t0 = (-b + d) * div;\n                t1 = (-b - d) * div;\n                return true;\n            }\n        }\n\n        #endregion\n\n\n        #region __plane2t__ intersects __line2t__\n\n        /// <summary>\n        /// Returns true if the __plane2t__ and the __line2t__ intersect or the __line2t__\n        /// lies completely in the Plane's Epsilon-Range\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        public static bool Intersects(\n            this __plane2t__ plane,\n            __line2t__ line,\n            __rtype__ absoluteEpsilon\n            )\n        {\n            __rtype__ lengthOfNormal2 = plane.Normal.LengthSquared;\n            __rtype__ d0 = plane.Height(line.P0);\n            __rtype__ d1 = plane.Height(line.P1);\n\n            return d0 * d1 < absoluteEpsilon * absoluteEpsilon * lengthOfNormal2;\n        }\n\n        /// <summary>\n        /// Returns true if the __plane2t__ and the __line2t__ intersect\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __plane2t__ plane,\n            __line2t__ line\n            )\n        {\n            return plane.IntersectsLine(line.P0, line.P1);\n        }\n\n\n        /// <summary>\n        /// Returns true if the __plane2t__ and the line between p0 and p1 intersect\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this __plane2t__ plane,\n            __v2t__ p0, __v2t__ p1\n            )\n        {\n            __rtype__ d0 = plane.Height(p0);\n            __rtype__ d1 = plane.Height(p1);\n\n            return d0 * d1 <= 0;\n        }\n\n        /// <summary>\n        /// Returns true if the __plane2t__ and the __line2t__ intersect\n        /// point holds the Intersection-Point. If no Intersection is found point is __v2t__.NaN\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __plane2t__ plane,\n            __line2t__ line,\n            out __v2t__ point\n            )\n        {\n            return plane.Intersects(line, 0, out point);\n        }\n\n        /// <summary>\n        /// Returns true if the __plane2t__ and the __line2t__ intersect or the __line2t__\n        /// lies completely in the Plane's Epsilon-Range\n        /// point holds the Intersection-Point. If the __line2t__ is inside Epsilon point holds the centroid of the __line2t__\n        /// If no Intersection is found point is __v2t__.NaN\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        public static bool Intersects(\n            this __plane2t__ plane,\n            __line2t__ line,\n            __rtype__ absoluteEpsilon,\n            out __v2t__ point\n            )\n        {\n            __rtype__ h0 = plane.Height(line.P0);\n            __rtype__ h1 = plane.Height(line.P1);\n\n            int s0 = (h0 > -absoluteEpsilon ? (h0 < absoluteEpsilon ? 0 : 1) : -1);\n            int s1 = (h1 > -absoluteEpsilon ? (h1 < absoluteEpsilon ? 0 : 1) : -1);\n\n            if (s0 == s1)\n            {\n                if (s0 != 0)\n                {\n                    point = __v2t__.NaN;\n                    return false;\n                }\n                else\n                {\n                    point = (line.P0 + line.P1) * __half__;\n                    return true;\n                }\n            }\n            else\n            {\n                if (s0 == 0)\n                {\n                    point = line.P0;\n                    return true;\n                }\n                else if (s1 == 0)\n                {\n                    point = line.P1;\n                    return true;\n                }\n                else\n                {\n                    __v2t__ dir = line.Direction;\n                    __rtype__ no = plane.Normal.Dot(line.P0);\n                    __rtype__ nd = plane.Normal.Dot(dir);\n                    __rtype__ t = (plane.Distance - no) / nd;\n\n                    point = line.P0 + t * dir;\n                    return true;\n                }\n            }\n        }\n\n\n\n        #endregion\n\n        #region __plane2t__ intersects __ray2t__\n\n        /// <summary>\n        /// Returns true if the __plane2t__ and the __ray2t__ intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane2t__ plane, __ray2t__ ray)\n            => !plane.Normal.IsOrthogonalTo(ray.Direction);\n\n        /// <summary>\n        /// Returns true if the Plane2d and the Ray2d intersect.\n        /// point holds the Intersection-Point if an intersection is found (else V2d.NaN)\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane2t__ plane, __ray2t__ ray, out __v2t__ point)\n            => plane.Intersects(ray, out __rtype__ t, out point);\n\n        /// <summary>\n        /// Returns true if the __plane2t__ and the __ray2t__ intersect.\n        /// t holds the ray paramater of the intersection point if the intersection is found (else Double.PositiveInfinity).\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane2t__ plane, __ray2t__ ray, out __rtype__ t)\n        {\n            __rtype__ dot = Vec.Dot(plane.Normal, ray.Direction);\n            if (Fun.IsTiny(dot))\n            {\n                t = __rtype__.PositiveInfinity;\n                return false;\n            }\n            t = -plane.Height(ray.Origin) / dot;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the __plane2t__ and the __ray2t__ intersect.\n        /// t and p hold the ray paramater and point of the intersection if one is found (else Double.PositiveInfinity and __v2t__.PositiveInfinity).\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane2t__ plane, __ray2t__ ray, out __rtype__ t, out __v2t__ p)\n        {\n            bool result = Intersects(plane, ray, out t);\n            p = ray.Origin + t * ray.Direction;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the intersection point of the given __plane2t__ and __ray2t__, or __v2t__.PositiveInfinity if ray is parallel to plane.\n        /// ATTENTION: Works only with Normalized Plane2ds\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ Intersect(this __plane2t__ plane, __ray2t__ ray)\n        {\n            __rtype__ dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot)) return __v2t__.PositiveInfinity;\n            return ray.GetPointOnRay(-plane.Height(ray.Origin) / dot);\n        }\n\n        #endregion\n\n        #region __plane2t__ intersects __plane2t__\n\n        /// <summary>\n        /// Returns true if the two Plane2ds intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane2t__ p0, __plane2t__ p1)\n        {\n            var hit = p0.Coefficients.Cross(p1.Coefficients);\n            return !hit.Z.IsTiny();\n        }\n\n        /// <summary>\n        /// Returns true if the two Plane2ds intersect.\n        /// Point holds the intersection point if an intersection is found.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane2t__ p0, __plane2t__ p1, out __v2t__ point)\n        {\n            var hit = p0.Coefficients.Cross(p1.Coefficients);\n            point = hit.XY / hit.Z;\n\n            return !hit.Z.IsTiny();\n        }\n\n        #endregion\n\n        #region __plane2t__ intersects IEnumerable<__v2t__>\n\n        /// <summary>\n        /// returns true if the __plane2t__ divides the Point-Cloud\n        /// </summary>\n        public static bool Divides(\n            this __plane2t__ plane,\n            IEnumerable<__v2t__> data\n            )\n        {\n            int first = int.MinValue;\n            foreach (var p in data)\n            {\n                if (first == int.MinValue)\n                {\n                    first = plane.Height(p).Sign();\n                }\n                else\n                {\n                    if (plane.Height(p).Sign() != first) return true;\n                }\n            }\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region __circle2t__ intersects __circle2t__ (sm)\n\n        /// <summary>\n        /// Returns true if the circles intersect, or one contains the other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __circle2t__ c0, __circle2t__ c1)\n            => (c0.Center - c1.Center).LengthSquared <= (c0.Radius + c1.Radius).Square();\n\n        #endregion\n\n\n        #region __triangle2t__ intersects __line2t__\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect or the triangle contains the line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __triangle2t__ triangle,\n            __line2t__ line\n            )\n        {\n            return triangle.IntersectsLine(line.P0, line.P1);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the line between p0 and p1 intersect or the triangle contains the line\n        /// </summary>\n        public static bool IntersectsLine(\n            this __triangle2t__ triangle,\n            __v2t__ p0, __v2t__ p1\n            )\n        {\n            if(triangle.Contains(p0))return true;\n            if(triangle.Contains(p1))return true;\n\n            if(triangle.Line01.IntersectsLine(p0,p1))return true;\n            if(triangle.Line12.IntersectsLine(p0,p1))return true;\n            if(triangle.Line20.IntersectsLine(p0,p1))return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __triangle2t__ intersects __ray2t__\n\n        /// <summary>\n        /// Returns true if the Triangle and the Ray intersect\n        /// </summary>\n        public static bool Intersects(\n            this __triangle2t__ triangle,\n            __ray2t__ ray\n            )\n        {\n            if (triangle.Contains(ray.Origin)) return true;\n\n            if (ray.IntersectsLine(triangle.P0, triangle.P1)) return true;\n            if (ray.IntersectsLine(triangle.P1, triangle.P2)) return true;\n            if (ray.IntersectsLine(triangle.P2, triangle.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __triangle2t__ intersects __plane2t__\n\n        /// <summary>\n        /// returns true if the __triangle2t__ and the __plane2t__ intersect\n        /// </summary>\n        public static bool Intersects(\n            this __triangle2t__ triangle,\n            __plane2t__ plane\n            )\n        {\n            if (plane.Intersects(triangle.Line01)) return true;\n            if (plane.Intersects(triangle.Line12)) return true;\n            if (plane.Intersects(triangle.Line20)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __triangle2t__ intersects __triangle2t__\n\n        /// <summary>\n        /// Returns true if the triangles intersect or one contains the other.\n        /// </summary>\n        public static bool Intersects(this __triangle2t__ t0, __triangle2t__ t1)\n        {\n            var l = t0.Line01;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            l = t0.Line12;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            l = t0.Line20;\n            if (l.IntersectsLine(t1.P0, t1.P1)) return true;\n            if (l.IntersectsLine(t1.P1, t1.P2)) return true;\n            if (l.IntersectsLine(t1.P2, t1.P0)) return true;\n\n            if (t0.Contains(t1.P0)) return true;\n            if (t1.Contains(t0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region __box2t__ intersects __line2t__\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool Intersects(this __box2t__ box, __line2t__ line)\n        {\n            var out0 = box.OutsideFlags(line.P0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(line.P1); if (out1 == 0) return true;\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n                this __box2t__ box, __line2t__ line, Box.Flags out0, Box.Flags out1)\n        {\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsLine(\n                this __box2t__ box, __v2t__ p0, __v2t__ p1)\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            return box.IntersectsLine(p0, p1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsLine(\n                this __box2t__ box, __v2t__ p0, __v2t__ p1,\n                Box.Flags out0, Box.Flags out1)\n        {\n            if ((out0 & out1) != 0) return false;\n\n            __v2t__ min = box.Min;\n            __v2t__ max = box.Max;\n            var bf = out0 | out1;\n\n            if ((bf & Box.Flags.X) != 0)\n            {\n                __rtype__ dx = p1.X - p0.X;\n                if ((bf & Box.Flags.MinX) != 0)\n                {\n                    if (dx == 0 && p0.X < min.X) return false;\n                    __rtype__ t = (min.X - p0.X) / dx;\n                    __v2t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinX) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxX) != 0)\n                {\n                    if (dx == 0 && p0.X > max.X) return false;\n                    __rtype__ t = (max.X - p0.X) / dx;\n                    __v2t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxX) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Y) != 0)\n            {\n                __rtype__ dy = p1.Y - p0.Y;\n                if ((bf & Box.Flags.MinY) != 0)\n                {\n                    if (dy == 0 && p0.Y < min.Y) return false;\n                    __rtype__ t = (min.Y - p0.Y) / dy;\n                    __v2t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinY) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxY) != 0)\n                {\n                    if (dy == 0 && p0.Y > max.Y) return false;\n                    __rtype__ t = (max.Y - p0.Y) / dy;\n                    __v2t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxY) == 0)\n                        return true;\n                }\n            }\n            return false;\n        }\n\n\n        #endregion\n\n        #region __box2t__ intersects __ray2t__\n\n        /// <summary>\n        /// Returns true if the box and the ray intersect\n        /// </summary>\n        public static bool Intersects(\n            this __box2t__ box,\n            __ray2t__ ray\n            )\n        {\n            /*\n             * Getting a Normal-Vector for the Ray and calculating\n             * the Normal Distances for every Box-Point:\n             */\n            __v2t__ n = new __v2t__(-ray.Direction.Y, ray.Direction.X);\n\n            __rtype__ d0 = n.Dot(box.Min - ray.Origin);                                            //n.Dot(box.p0 - ray.Origin)\n            __rtype__ d1 = n.X * (box.Max.X - ray.Origin.X) + n.Y * (box.Min.Y - ray.Origin.Y);    //n.Dot(box.p1 - ray.Origin)\n            __rtype__ d2 = n.Dot(box.Max - ray.Origin);                                            //n.Dot(box.p2 - ray.Origin)\n            __rtype__ d3 = n.X * (box.Min.X - ray.Origin.X) + n.Y * (box.Max.Y - ray.Origin.Y);    //n.Dot(box.p3 - ray.Origin)\n\n            /*\n             * If Zero lies in the Range of the Distances there\n             * have to be Points on both sides of the Ray.\n             * This means the Box and the Ray have an Intersection\n             */\n\n            __range1t__ r = new __range1t__(d0, d1, d2, d3);\n            return r.Contains(0);\n        }\n\n        #endregion\n\n        #region __box2t__ intersects __plane2t__\n\n        /// <summary>\n        /// returns true if the box and the plane intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __box2t__ box,\n            __plane2t__ plane\n            )\n        {\n            //UNTESTED\n            return plane.Divides(box.ComputeCorners());\n        }\n\n\n        /// <summary>\n        /// NOT TESTED YET.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __box2t__ box,\n            __plane2t__ plane,\n            out __line2t__ line)\n        {\n            return Intersects(\n                    plane.Normal.X, plane.Normal.Y, plane.Distance,\n                    box.Min.X, box.Min.Y, box.Max.X, box.Max.Y,\n                    out line);\n        }\n\n        /// <summary>\n        /// Intersects an infinite line given by its normal vector [nx, ny]\n        /// and its distance to the origin d, with an axis aligned box given\n        /// by it minimal point [xmin, ymin] and its maximal point\n        /// [xmax, ymax]. Returns true if there is an intersection and computes\n        /// the actual intersection line.\n        /// NOT TESTED YET.\n        /// </summary>\n        public static bool Intersects(\n                __rtype__ nx, __rtype__ ny, __rtype__ d,\n                __rtype__ xmin, __rtype__ ymin, __rtype__ xmax, __rtype__ ymax,\n                out __line2t__ line)\n        {\n            if (nx.IsTiny()) // horizontal\n            {\n                if (d <= ymin || d >= ymax) { line = default; return false; }\n                line = new __line2t__(new __v2t__(xmin, d), new __v2t__(xmax, d));\n                return true;\n            }\n\n            if (ny.IsTiny()) // vertical\n            {\n                if (d <= xmin || d >= xmax) { line = default; return false; }\n                line = new __line2t__(new __v2t__(d, ymin), new __v2t__(d, ymax));\n                return true;\n            }\n\n            if (nx.Sign() != ny.Sign())\n            {\n                __rtype__ x0 = (d - ny * ymin) / nx;\n                if (x0 >= xmax) { line = default; return false; }\n                if (x0 > xmin) xmin = x0;\n                __rtype__ x1 = (d - ny * ymax) / nx;\n                if (x1 <= xmin) { line = default; return false; }\n                if (x1 < xmax) xmax = x1;\n\n                __rtype__ y0 = (d - nx * xmin) / ny;\n                if (y0 >= ymax) { line = default; return false; }\n                if (y0 > ymin) ymin = y0;\n                __rtype__ y1 = (d - nx * xmax) / ny;\n                if (y1 <= ymin) { line = default; return false; }\n                if (y1 < ymax) ymax = y1;\n\n                line = new __line2t__(new __v2t__(xmin, ymin), new __v2t__(xmax, ymax));\n            }\n            else\n            {\n                __rtype__ x0 = (d - ny * ymax) / nx;\n                if (x0 >= xmax) { line = default; return false; }\n                if (x0 > xmin) xmin = x0;\n                __rtype__ x1 = (d - ny * ymin) / nx;\n                if (x1 <= xmin) { line = default; return false; }\n                if (x1 < xmax) xmax = x1;\n                __rtype__ y0 = (d - nx * xmax) / ny;\n                if (y0 >= ymax) { line = default; return false; }\n                if (y0 > ymin) ymin = y0;\n                __rtype__ y1 = (d - nx * xmin) / ny;\n                if (y1 <= ymin) { line = default; return false; }\n                if (y1 < ymax) ymax = y1;\n\n                line = new __line2t__(new __v2t__(xmax, ymin), new __v2t__(xmin, ymax));\n            }\n            return true;\n        }\n\n        #endregion\n\n        #region __box2t__ intersects __triangle2t__\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __box2t__ box,\n            __triangle2t__ triangle\n            )\n        {\n            return box.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2);\n        }\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect\n        /// </summary>\n        public static bool IntersectsTriangle(\n            this __box2t__ box,\n            __v2t__ p0, __v2t__ p1, __v2t__ p2\n            )\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n\n            return box.IntersectsTriangle(p0, p1, p2, out0, out1, out2);\n        }\n\n        /// <summary>\n        /// Returns true if the Box and the Triangle intersect. The outside flags\n        /// of the end points of the Triangle with respect to the box have to be\n        /// supplied as parameters.\n        /// </summary>\n        private static bool IntersectsTriangle(\n            this __box2t__ box, __v2t__ p0, __v2t__ p1, __v2t__ p2,\n            Box.Flags out0, Box.Flags out1, Box.Flags out2\n            )\n        {\n\n            /* ---------------------------------------------------------------\n                If all of the points of the triangle are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n               If two points of the triangle are not on the same side\n               outside the box, it is possible that the edge between them\n               intersects the box. The outside flags we computed are also\n               used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p0, out2, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n               The only case left: The triangle contains the the whole box\n               i.e. every point. When no triangle-line intersects the box and one\n               box point is inside the triangle the triangle must contain the box\n            --------------------------------------------------------------- */\n            __v2t__ a = box.Min - p0;\n            __v2t__ u = p1 - p0;\n            __v2t__ v = p2 - p0;\n\n\n            __rtype__ cross = u.X * v.Y - u.Y * v.X;\n            if (Fun.IsTiny(cross)) return false;\n            cross = 1 / cross;\n\n            __rtype__ t0 = (a.Y * v.X - a.X * v.Y) * cross; if (t0 < 0 || t0 > 1) return false;\n            __rtype__ t1 = (a.Y * u.X - a.X * u.Y) * cross; if (t1 < 0 || t1 > 1) return false;\n\n            return (t0 + t1 < 1);\n        }\n\n        #endregion\n\n        #region __box2t__ intersects __box2t__ (__box2t__-Implementation)\n\n        //Directly in Box-Implementation\n\n        #endregion\n\n\n        #region __quad2t__ intersects __line2t__\n\n        /// <summary>\n        /// returns true if the Quad and the line intersect or the quad contains the line\n        /// </summary>\n        public static bool Intersects(\n            this __quad2t__ quad,\n            __line2t__ line\n            )\n        {\n            if (quad.Contains(line.P0)) return true;\n            if (quad.Contains(line.P1)) return true;\n\n            if (line.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (line.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (line.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (line.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n        /// <summary>\n        /// returns true if the Quad and the line between p0 and p1 intersect or the quad contains the line\n        /// </summary>\n        public static bool IntersectsLine(\n            this __quad2t__ quad,\n            __v2t__ p0, __v2t__ p1\n            )\n        {\n            if (quad.Contains(p0)) return true;\n            if (quad.Contains(p1)) return true;\n\n            __line2t__ line = new __line2t__(p0, p1);\n            if (line.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (line.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (line.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (line.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __quad2t__ intersects __ray2t__\n\n        /// <summary>\n        /// returns true if the quad and the ray intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __quad2t__ quad,\n            __ray2t__ ray\n            )\n        {\n            return ray.__plane2t__.Divides(quad.Points);\n        }\n\n        #endregion\n\n        #region __quad2t__ intersects __plane2t__\n\n        /// <summary>\n        /// returns true if the __quad2t__ and the __plane2t__ intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __quad2t__ quad,\n            __plane2t__ plane\n            )\n        {\n            //UNTESTED\n            if (plane.Divides(quad.Points)) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region __quad2t__ intersects __triangle2t__\n\n        /// <summary>\n        /// returns true if the __quad2t__ and the __triangle2t__ intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this __quad2t__ quad,\n            __triangle2t__ triangle\n            )\n        {\n            if (quad.Intersects(triangle.Line01)) return true;\n            if (quad.Intersects(triangle.Line12)) return true;\n            if (quad.Intersects(triangle.Line20)) return true;\n\n            if (quad.Contains(triangle.P0)) return true;\n            if (triangle.Contains(quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __quad2t__ intersects __box2t__\n\n        /// <summary>\n        /// Returns true if the box and the Quad intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this __box2t__ box,\n            __quad2t__ quad\n            )\n        {\n            Box.Flags out0 = box.OutsideFlags(quad.P0); if (out0 == 0) return true;\n            Box.Flags out1 = box.OutsideFlags(quad.P1); if (out1 == 0) return true;\n            Box.Flags out2 = box.OutsideFlags(quad.P2); if (out2 == 0) return true;\n            Box.Flags out3 = box.OutsideFlags(quad.P3); if (out3 == 0) return true;\n\n\n            /* ---------------------------------------------------------------\n                If all of the points of the Quad are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2 & out3) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n               If two points of the Quad are not on the same side\n               outside the box, it is possible that the edge between them\n               intersects the box. The outside flags we computed are also\n               used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(quad.P0, quad.P1, out0, out1)) return true;\n            if (box.IntersectsLine(quad.P1, quad.P2, out1, out2)) return true;\n            if (box.IntersectsLine(quad.P2, quad.P3, out2, out3)) return true;\n            if (box.IntersectsLine(quad.P3, quad.P0, out3, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n               The only case left: The Quad contains the the whole box\n               i.e. every point. When no triangle-line intersects the box and one\n               box point is inside the Quad the Quad must contain the box\n            --------------------------------------------------------------- */\n\n            return quad.Contains(box.Min);\n        }\n\n        #endregion\n\n        #region __quad2t__ intersects __quad2t__\n\n        /// <summary>\n        /// returns true if the Quad2ds intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this __quad2t__ q0,\n            __quad2t__ quad\n            )\n        {\n            if (q0.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (q0.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (q0.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (q0.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            if (q0.Contains(quad.P0)) return true;\n            if (quad.Contains(q0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region __polygon2t__ intersects __line2t__\n\n        /// <summary>\n        /// returns true if the __polygon2t__ and the __line2t__ intersect or the Polygon contains the Line\n        /// </summary>\n        public static bool Intersects(\n            this __polygon2t__ poly,\n            __line2t__ line\n            )\n        {\n            foreach (var l in poly.EdgeLines)\n            {\n                if (l.Intersects(line)) return true;\n            }\n\n            if (poly.Contains(line.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __polygon2t__ intersects __ray2t__\n\n        /// <summary>\n        /// returns true if the __polygon2t__ and the __ray2t__ intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __polygon2t__ poly,\n            __ray2t__ ray\n            )\n        {\n            //UNTESTED\n            return ray.__plane2t__.Divides(poly.Points);\n        }\n\n\n        #endregion\n\n        #region __polygon2t__ intersects __plane2t__\n\n        /// <summary>\n        /// returns true if the __polygon2t__ and the __plane2t__ itnersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __polygon2t__ poly,\n            __plane2t__ plane\n            )\n        {\n            //UNTESTED\n            return plane.Divides(poly.Points);\n        }\n\n        #endregion\n\n        #region __polygon2t__ intersects __triangle2t__\n\n        /// <summary>\n        /// returns true if the __polygon2t__ and the __triangle2t__ intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this __polygon2t__ poly,\n            __triangle2t__ triangle\n            )\n        {\n            foreach (var line in poly.EdgeLines)\n            {\n                if (triangle.Intersects(line)) return true;\n            }\n\n            if (triangle.Contains(poly[0])) return true;\n            if (poly.Contains(triangle.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __polygon2t__ intersects __box2t__\n\n        /// <summary>\n        /// returns true if the __polygon2t__ and the __box2t__ intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this __polygon2t__ poly,\n            __box2t__ box\n            )\n        {\n            //UNTESTED\n            int count = poly.PointCount;\n            Box.Flags[] outFlags = new Box.Flags[count];\n\n            int i0 = 0;\n            foreach (var p in poly.Points) outFlags[i0++] = box.OutsideFlags(p);\n\n            i0 = 0;\n            int i1 = 1;\n            foreach (var l in poly.EdgeLines)\n            {\n                if (box.Intersects(l, outFlags[i0], outFlags[i1])) return true;\n\n                i0++;\n                i1 = (i1 + 1) % count;\n            }\n\n            if (box.Contains(poly[0])) return true;\n            if (poly.Contains(box.Min)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __polygon2t__ intersects __quad2t__\n\n        /// <summary>\n        /// returns true if the __polygon2t__ and the __quad2t__ interset or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this __polygon2t__ poly,\n            __quad2t__ quad\n            )\n        {\n            foreach (var l in poly.EdgeLines)\n            {\n                if (quad.Intersects(l)) return true;\n            }\n\n            if (quad.Contains(poly[0])) return true;\n            if (poly.Contains(quad.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __polygon2t__ intersects __polygon2t__\n\n        /// <summary>\n        /// returns true if the Polygon2ds intersect or one contains the other\n        /// </summary>\n        public static bool Intersects(\n            this __polygon2t__ poly0,\n            __polygon2t__ poly1\n            )\n        {\n            //check if projected ranges intersect for all possible normals\n\n\n            __v2t__[] allnormals = new __v2t__[poly0.PointCount + poly1.PointCount];\n            int c = 0;\n\n            foreach (var d in poly0.Edges)\n            {\n                allnormals[c] = new __v2t__(-d.Y, d.X);\n                c++;\n            }\n            foreach (var d in poly1.Edges)\n            {\n                allnormals[c] = new __v2t__(-d.Y, d.X);\n                c++;\n            }\n\n\n\n            foreach (var n in allnormals)\n            {\n                var r0 = poly0.ProjectTo(n);\n                var r1 = poly1.ProjectTo(n);\n\n                if (!r0.Intersects(r1)) return false;\n            }\n\n            return true;\n        }\n\n        private static __range1t__ ProjectTo(this __polygon2t__ poly, __v2t__ dir)\n        {\n            __rtype__ min = __rtype__.MaxValue;\n            __rtype__ max = __rtype__.MinValue;\n            foreach (var p in poly.Points)\n            {\n                __rtype__ dotproduct = p.Dot(dir);\n\n                if (dotproduct < min) min = dotproduct;\n                if (dotproduct > max) max = dotproduct;\n            }\n\n            return new __range1t__(min, max);\n        }\n\n        #endregion\n\n\n        #region __line3t__ intersects __line3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than Constant&lt;__rtype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __line3t__ l0,\n            __line3t__ l1\n            )\n        {\n            return l0.Intersects(l1, Constant<__rtype__>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than absoluteEpsilon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __line3t__ l0,\n            __line3t__ l1,\n            __rtype__ absoluteEpsilon\n            )\n        {\n            if (l0.GetMinimalDistanceTo(l1) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the given lines is smaller than absoluteEpsilon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __line3t__ l0,\n            __line3t__ l1,\n            __rtype__ absoluteEpsilon,\n            out __v3t__ point\n            )\n        {\n            if (l0.GetMinimalDistanceTo(l1, out point) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region __line3t__ intersects Special (inconsistent argument order)\n\n        #region __line3t__ intersects __plane3t__\n\n        /// <summary>\n        /// Returns true if the line and the plane intersect.\n        /// </summary>\n        public static bool Intersects(\n             this __line3t__ line, __plane3t__ plane, out __rtype__ t\n             )\n        {\n            if (!line.__ray3t__.Intersects(plane, out t)) return false;\n            if (t >= 0 && t <= 1) return true;\n            t = __rtype__.PositiveInfinity;\n            return false;\n\n        }\n\n        /// <summary>\n        /// Returns true if the line and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this __line3t__ line, __plane3t__ plane, out __rtype__ t, out __v3t__ p\n             )\n        {\n            bool result = line.Intersects(plane, out t);\n            p = line.Origin + t * line.Direction;\n            return result;\n        }\n\n        #endregion\n\n        #region __line3t__ intersects __triangle3t__\n\n        /// <summary>\n        /// Returns true if the line and the triangle intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __line3t__ line,\n            __triangle3t__ triangle\n            )\n        {\n            return line.__ray3t__.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2, 0, 1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the line and the triangle intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool Intersects(\n            this __line3t__ line,\n            __triangle3t__ triangle,\n            out __v3t__ point\n            )\n        {\n            __ray3t__ ray = line.__ray3t__;\n\n            if (ray.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2, 0, 1, out __rtype__ temp))\n            {\n                point = ray.GetPointOnRay(temp);\n                return true;\n            }\n            else\n            {\n                point = __v3t__.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #endregion\n\n\n        #region __ray3t__ intersects __line3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than Constant&lt;__rtype__&gt;.PositiveTinyValue\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray3t__ ray, __line3t__ line\n            )\n        {\n            return ray.Intersects(line, Constant<__rtype__>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than absoluteEpsilon\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray3t__ ray, __line3t__ line,\n            __rtype__ absoluteEpsilon\n            )\n        {\n            if (ray.GetMinimalDistanceTo(line) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        /// <summary>\n        /// Returns true if the minimal distance between the line and the ray is smaller than absoluteEpsilon\n        /// t holds the corresponding ray parameter\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray3t__ ray, __line3t__ line,\n            __rtype__ absoluteEpsilon,\n            out __rtype__ t\n            )\n        {\n            if (ray.GetMinimalDistanceTo(line, out t) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region __ray3t__ intersects __ray3t__ (haaser)\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than Constant&lt;__rtype__&gt;.PositiveTinyValue\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray3t__ r0,\n            __ray3t__ r1\n            )\n        {\n            return r0.Intersects(r1, out _, out _, Constant<__rtype__>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than Constant&lt;__rtype__&gt;.PositiveTinyValue\n        /// t0 and t1 hold the ray-parameters for the intersection\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray3t__ r0,\n            __ray3t__ r1,\n            out __rtype__ t0,\n            out __rtype__ t1\n            )\n        {\n            return r0.Intersects(r1, out t0, out t1, Constant<__rtype__>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than absoluteEpsilon\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray3t__ r0,\n            __ray3t__ r1,\n            __rtype__ absoluteEpsilon\n            )\n        {\n            return r0.Intersects(r1, out _, out _, absoluteEpsilon);\n        }\n\n        /// <summary>\n        /// returns true if the minimal distance between the rays is smaller than absoluteEpsilon\n        /// t0 and t1 hold the ray-parameters for the intersection\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __ray3t__ r0,\n            __ray3t__ r1,\n            out __rtype__ t0,\n            out __rtype__ t1,\n            __rtype__ absoluteEpsilon\n            )\n        {\n            if (r0.GetMinimalDistanceTo(r1, out t0, out t1) < absoluteEpsilon) return true;\n            else return false;\n        }\n\n        #endregion\n\n        #region __ray3t__ intersects Special (inconsistent argument order)\n\n        #region __ray3t__ intersects __triangle3t__\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __ray3t__ ray, __triangle3t__ triangle)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                __rtype__.MinValue, __rtype__.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __ray3t__ ray, __triangle3t__ triangle, __rtype__ tmin, __rtype__ tmax)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __ray3t__ ray, __triangle3t__ triangle, __rtype__ tmin, __rtype__ tmax, out __rtype__ t)\n            => ray.IntersectsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTriangle(this __ray3t__ ray, __v3t__ p0, __v3t__ p1, __v3t__ p2, __rtype__ tmin, __rtype__ tmax)\n            => ray.IntersectsTriangle(p0, p1, p2, tmin, tmax, out __rtype__ _);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        public static bool IntersectsTriangle(this __ray3t__ ray, __v3t__ p0, __v3t__ p1, __v3t__ p2, __rtype__ tmin, __rtype__ tmax, out __rtype__ t)\n        {\n            var edge01 = p1 - p0;\n            var edge02 = p2 - p0;\n            var plane = Vec.Cross(ray.Direction, edge02);\n            var det = Vec.Dot(edge01, plane);\n            if (det > -__epsdot__ && det < __epsdot__) { t = __rtype__.NaN; return false; }\n            //ray ~= parallel / Triangle\n            var tv = ray.Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            var u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) { t = __rtype__.NaN; return false; }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            var v = Vec.Dot(ray.Direction, plane) * det;\n            if (v < 0 || u + v > 1) { t = __rtype__.NaN; return false; }\n            var temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < tmin || temp_t >= tmax) { t = __rtype__.NaN; return false; }\n\n            t = temp_t;\n            return true;\n        }\n\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTrianglePointAndEdges(this __ray3t__ ray, __v3t__ p0, __v3t__ edge01, __v3t__ edge02, __rtype__ tmin, __rtype__ tmax)\n            => ray.IntersectsTrianglePointAndEdges(p0, edge01, edge02, tmin, tmax, out _);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// t holds the corresponding ray-parameter\n        /// </summary>\n        public static bool IntersectsTrianglePointAndEdges(this __ray3t__ ray, __v3t__ p0, __v3t__ edge01, __v3t__ edge02, __rtype__ tmin, __rtype__ tmax, out __rtype__ t)\n        {\n            var plane = Vec.Cross(ray.Direction, edge02);\n            var det = Vec.Dot(edge01, plane);\n            if (det > -__epsdot__ && det < __epsdot__) { t = __rtype__.NaN; return false; }\n            //ray ~= parallel / Triangle\n            var tv = ray.Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            var u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) { t = __rtype__.NaN; return false; }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            var v = Vec.Dot(ray.Direction, plane) * det;\n            if (v < 0 || u + v > 1) { t = __rtype__.NaN; return false; }\n            var temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < tmin || temp_t >= tmax) { t = __rtype__.NaN; return false; }\n\n            t = temp_t;\n            return true;\n        }\n\n        #endregion\n\n        #region __ray3t__ intersects __quad3t__\n\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __ray3t__ ray, __quad3t__ quad)\n            => ray.Intersects(quad, __rtype__.MinValue, __rtype__.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the quad intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        public static bool Intersects(this __ray3t__ ray, __quad3t__ quad, __rtype__ tmin, __rtype__ tmax)\n        {\n            var edge02 = quad.P2 - quad.P0;\n            return ray.IntersectsTrianglePointAndEdges(quad.P0, quad.Edge01, edge02, tmin, tmax)\n                || ray.IntersectsTrianglePointAndEdges(quad.P0, edge02, quad.Edge03, tmin, tmax);\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the quad intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        public static bool IntersectsQuad(this __ray3t__ ray, __v3t__ p0, __v3t__ p1, __v3t__ p2, __v3t__ p3, __rtype__ tmin, __rtype__ tmax)\n        {\n            var edge02 = p2 - p0;\n            return ray.IntersectsTrianglePointAndEdges(p0, p1 - p0, edge02, tmin, tmax)\n                || ray.IntersectsTrianglePointAndEdges(p0, edge02, p3 - p0, tmin, tmax);\n        }\n\n        #endregion\n\n        #region __ray3t__ intersects __polygon3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the ray and the polygon intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __ray3t__ ray, __polygon3t__ poly, __rtype__ tmin, __rtype__ tmax)\n            => ray.Intersects(poly, tmin, tmax, out _);\n\n        /// <summary>\n        /// Returns true if the ray and the polygon intersect within the\n        /// supplied parameter interval of the ray.\n        /// t holds the correspoinding paramter.\n        /// </summary>\n        public static bool Intersects(this __ray3t__ ray, __polygon3t__ poly, __rtype__ tmin, __rtype__ tmax, out __rtype__ t)\n        {\n            var tris = poly.ComputeTriangulationOfConcavePolygon(__eminus5__);\n            var count = tris.Length;\n\n            for (var i = 0; i < count; i += 3)\n            {\n                if (ray.IntersectsTriangle(poly[tris[i + 0]], poly[tris[i + 1]], poly[tris[i + 2]],\n                                           tmin, tmax, out t))\n                {\n                    return true;\n                }\n            }\n\n            t = __rtype__.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices, intersect within the\n        /// supplied parameter interval of the ray.\n        /// (The Method triangulates the polygon)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsPolygon(this __ray3t__ ray, __v3t__[] vertices, __rtype__ tmin, __rtype__ tmax)\n            => ray.Intersects(new __polygon3t__(vertices), tmin, tmax);\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices and triangulation, intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        public static bool IntersectsPolygon(\n            this __ray3t__ ray,\n            __v3t__[] vertices,\n            int[] triangulation,\n            __rtype__ tmin, __rtype__ tmax\n            )\n        {\n            for (var i = 0; i < triangulation.Length; i += 3)\n            {\n                if (ray.IntersectsTriangle(vertices[triangulation[i + 0]],\n                                           vertices[triangulation[i + 1]],\n                                           vertices[triangulation[i + 2]], tmin, tmax)) return true;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the polygon, which is given by vertices and triangulation, intersect within the\n        /// supplied parameter interval of the ray.\n        /// </summary>\n        public static bool Intersects(\n            this __ray3t__ ray,\n            __polygon3t__ polygon,\n            int[] triangulation,\n            __rtype__ tmin, __rtype__ tmax\n            )\n        {\n            for (var i = 0; i < triangulation.Length; i += 3)\n            {\n                if (ray.IntersectsTriangle(polygon[triangulation[i + 0]],\n                                           polygon[triangulation[i + 1]],\n                                           polygon[triangulation[i + 2]], tmin, tmax)) return true;\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region __ray3t__ intersects __sphere3t__\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect. If you need\n        /// information about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __ray3t__ ray, __sphere3t__ sphere)\n            => ray.Intersects(sphere, __rtype__.MinValue, __rtype__.MaxValue);\n\n        /// <summary>\n        /// Returns true if the ray and the triangle intersect within the\n        /// supplied parameter interval of the ray. If you need information\n        /// about the hit point see the __ray3t__.Hits method.\n        /// </summary>\n        public static bool Intersects(this __ray3t__ ray, __sphere3t__ sphere, __rtype__ tmin, __rtype__ tmax)\n        {\n            // calculate closest point\n            var t = ray.Direction.Dot(sphere.Center - ray.Origin) / ray.Direction.LengthSquared;\n            if (t < 0) t = 0;\n            if (t < tmin) t = tmin;\n            if (t > tmax) t = tmax;\n            __v3t__ p = ray.Origin + t * ray.Direction;\n\n            // distance to sphere?\n            var d = (p - sphere.Center).LengthSquared;\n            if (d <= sphere.RadiusSquared)\n                return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __sphere3t__ intersects __triangle3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this __sphere3t__ sphere, __triangle3t__ triangle\n             )\n        {\n            __v3t__ v = sphere.Center.GetClosestPointOn(triangle) - sphere.Center;\n            return sphere.RadiusSquared >= v.LengthSquared;\n        }\n\n        #endregion\n\n        #endregion\n\n\n        #region __triangle3t__ intersects __line3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __triangle3t__ tri,\n            __line3t__ line\n            )\n        {\n            return tri.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the line intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __triangle3t__ tri,\n            __line3t__ line,\n            out __v3t__ point\n            )\n        {\n            return tri.IntersectsLine(line.P0, line.P1, out point);\n        }\n\n        /// <summary>\n        /// returns true if the triangle and the line, given by p0 and p1, intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n            this __triangle3t__ tri,\n            __v3t__ p0, __v3t__ p1\n            )\n        {\n            __v3t__ edge01 = tri.Edge01;\n            __v3t__ edge02 = tri.Edge02;\n            __v3t__ dir = p1 - p0;\n\n            __v3t__ plane = Vec.Cross(dir, edge02);\n            __rtype__ det = Vec.Dot(edge01, plane);\n            if (det > -__epsdot__ && det < __epsdot__)return false;\n            //ray ~= parallel / Triangle\n            __v3t__ tv = p0 - tri.P0;\n            det = 1 / det;  // det is now inverse det\n            __rtype__ u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1)\n            {\n                return false;\n            }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            __rtype__ v = Vec.Dot(dir, plane) * det;\n            if (v < 0 || u + v > 1)\n            {\n                return false;\n            }\n            __rtype__ temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < 0 || temp_t >= 1)\n            {\n                return false;\n            }\n\n            return true;\n        }\n\n        /// <summary>\n        /// returns true if the triangle and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool IntersectsLine(\n            this __triangle3t__ tri,\n            __v3t__ p0, __v3t__ p1,\n            out __v3t__ point\n            )\n        {\n            __v3t__ edge01 = tri.Edge01;\n            __v3t__ edge02 = tri.Edge02;\n            __v3t__ dir = p1 - p0;\n\n            __v3t__ plane = Vec.Cross(dir, edge02);\n            __rtype__ det = Vec.Dot(edge01, plane);\n            if (det > -__epsdot__ && det < __epsdot__) { point = __v3t__.NaN; return false; }\n            //ray ~= parallel / Triangle\n            __v3t__ tv = p0 - tri.P0;\n            det = 1 / det;  // det is now inverse det\n            __rtype__ u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1)\n            {\n                point = __v3t__.NaN;\n                return false;\n            }\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            __rtype__ v = Vec.Dot(dir, plane) * det;\n            if (v < 0 || u + v > 1)\n            {\n                point = __v3t__.NaN;\n                return false;\n            }\n            __rtype__ temp_t = Vec.Dot(edge02, plane) * det;\n            if (temp_t < 0 || temp_t >= 1)\n            {\n                point = __v3t__.NaN;\n                return false;\n            }\n\n            point = p0 + temp_t * dir;\n            return true;\n        }\n\n\n        #endregion\n\n        #region __triangle3t__ intersects __ray3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __triangle3t__ tri,\n            __ray3t__ ray\n            )\n        {\n            return tri.Intersects(ray, __rtype__.MinValue, __rtype__.MaxValue, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect\n        /// within the given parameter interval\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __triangle3t__ tri,\n            __ray3t__ ray,\n            __rtype__ tmin, __rtype__ tmax\n            )\n        {\n            return tri.Intersects(ray, tmin, tmax, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect.\n        /// t holds the intersection paramter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __triangle3t__ tri,\n            __ray3t__ ray,\n            out __rtype__ t\n            )\n        {\n            return tri.Intersects(ray, __rtype__.MinValue, __rtype__.MaxValue, out t);\n        }\n\n        /// <summary>\n        /// Returns true if the triangle and the ray intersect\n        /// within the given parameter interval\n        /// t holds the intersection paramter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __triangle3t__ tri,\n            __ray3t__ ray,\n            __rtype__ tmin, __rtype__ tmax,\n            out __rtype__ t\n            )\n        {\n            return ray.Intersects(tri, tmin, tmax, out t);\n        }\n\n        #endregion\n\n        #region __triangle3t__ intersects __triangle3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the triangles intersect.\n        /// </summary>\n        public static bool Intersects(\n            this __triangle3t__ t0,\n            __triangle3t__ t1\n            )\n        {\n            if (t0.IntersectsLine(t1.P0, t1.P1, out _)) return true;\n            if (t0.IntersectsLine(t1.P1, t1.P2, out _)) return true;\n            if (t0.IntersectsLine(t1.P2, t1.P0, out _)) return true;\n\n            if (t1.IntersectsLine(t0.P0, t0.P1, out _)) return true;\n            if (t1.IntersectsLine(t0.P1, t0.P2, out _)) return true;\n            if (t1.IntersectsLine(t0.P2, t0.P0, out _)) return true;\n\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the triangles intersect.\n        /// line holds the cutting-line of the two triangles.\n        /// </summary>\n        public static bool Intersects(\n            this __triangle3t__ t0,\n            __triangle3t__ t1,\n            out __line3t__ line\n            )\n        {\n            List<__v3t__> points = new List<__v3t__>();\n\n            if (t0.IntersectsLine(t1.P0, t1.P1, out __v3t__ temp)) points.Add(temp);\n            if (t0.IntersectsLine(t1.P1, t1.P2, out temp)) points.Add(temp);\n            if (t0.IntersectsLine(t1.P2, t1.P0, out temp)) points.Add(temp);\n\n            if (points.Count == 2)\n            {\n                line = new __line3t__(points[0], points[1]);\n                return true;\n            }\n\n            if (t1.IntersectsLine(t0.P0, t0.P1, out temp)) points.Add(temp);\n            if (t1.IntersectsLine(t0.P1, t0.P2, out temp)) points.Add(temp);\n            if (t1.IntersectsLine(t0.P2, t0.P0, out temp)) points.Add(temp);\n\n            if (points.Count == 2)\n            {\n                line = new __line3t__(points[0], points[1]);\n                return true;\n            }\n\n            line = new __line3t__(__v3t__.NaN, __v3t__.NaN);\n            return false;\n        }\n\n        #endregion\n\n\n        #region __quad3t__ intersects __line3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __quad3t__ quad,\n            __line3t__ line)\n        {\n            return quad.IntersectsLine(line.P0, line.P1, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __quad3t__ quad,\n            __line3t__ line,\n            out __v3t__ point)\n        {\n            return quad.IntersectsLine(line.P0, line.P1, out point);\n        }\n\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n            this __quad3t__ quad,\n            __v3t__ p0, __v3t__ p1)\n        {\n            __ray3t__ ray = new __ray3t__(p0, p1 - p0);\n            if (quad.Intersects(ray, 0, 1, out _))\n            {\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the line, given by p0 and p1, intersect.\n        /// point holds the intersection point.\n        /// </summary>\n        public static bool IntersectsLine(\n            this __quad3t__ quad,\n            __v3t__ p0, __v3t__ p1,\n            out __v3t__ point)\n        {\n            __ray3t__ ray = new __ray3t__(p0, p1 - p0);\n            if (quad.Intersects(ray, 0, 1, out __rtype__ t))\n            {\n                point = ray.GetPointOnRay(t);\n                return true;\n            }\n            else\n            {\n                point = __v3t__.NaN;\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region __quad3t__ intersects __ray3t__ (haaser)\n\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __quad3t__ quad,\n            __ray3t__ ray\n            )\n        {\n            return quad.Intersects(ray, __rtype__.MinValue, __rtype__.MaxValue, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect.\n        /// t holds the intersection parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __quad3t__ quad,\n            __ray3t__ ray,\n            out __rtype__ t\n            )\n        {\n            return quad.Intersects(ray, __rtype__.MinValue, __rtype__.MaxValue, out t);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect\n        /// within the given paramter range\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __quad3t__ quad,\n            __ray3t__ ray,\n            __rtype__ tmin, __rtype__ tmax\n            )\n        {\n            return quad.Intersects(ray, tmin, tmax, out _);\n        }\n\n        /// <summary>\n        /// Returns true if the quad and the ray intersect\n        /// within the given paramter range\n        /// t holds the intersection parameter.\n        /// </summary>\n        public static bool Intersects(\n            this __quad3t__ quad,\n            __ray3t__ ray,\n            __rtype__ tmin, __rtype__ tmax,\n            out __rtype__ t\n            )\n        {\n            __v3t__ edge02 = quad.P2 - quad.P0;\n            if (ray.IntersectsTrianglePointAndEdges(quad.P0, quad.Edge01, edge02, tmin, tmax, out t)) return true;\n            if (ray.IntersectsTrianglePointAndEdges(quad.P0, edge02, quad.Edge03, tmin, tmax, out t)) return true;\n\n            t = __rtype__.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region __quad3t__ intersects __triangle3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the quad and the triangle intersect.\n        /// </summary>\n        public static bool Intersects(\n            this __quad3t__ quad,\n            __triangle3t__ tri\n            )\n        {\n            if (quad.IntersectsLine(tri.P0, tri.P1)) return true;\n            if (quad.IntersectsLine(tri.P1, tri.P2)) return true;\n            if (quad.IntersectsLine(tri.P2, tri.P0)) return true;\n\n            if (tri.IntersectsLine(quad.P0, quad.P1)) return true;\n            if (tri.IntersectsLine(quad.P1, quad.P2)) return true;\n            if (tri.IntersectsLine(quad.P2, quad.P3)) return true;\n            if (tri.IntersectsLine(quad.P3, quad.P0)) return true;\n\n            return false;\n        }\n\n\n        /// <summary>\n        /// Returns true if the quad and the triangle, given by p0/p1/p1, intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsTriangle(\n            this __quad3t__ quad,\n            __v3t__ p0, __v3t__ p1, __v3t__ p2\n            )\n        {\n            __triangle3t__ tri = new __triangle3t__(p0, p1, p2);\n            return quad.Intersects(tri);\n        }\n\n        #endregion\n\n        #region __quad3t__ intersects __quad3t__ (haaser)\n\n        /// <summary>\n        /// Returns true if the given quads intersect.\n        /// </summary>\n        public static bool Intersects(\n            this __quad3t__ q0,\n            __quad3t__ q1\n            )\n        {\n            if (q0.IntersectsTriangle(q1.P0, q1.P1, q1.P2)) return true;\n            if (q0.IntersectsTriangle(q1.P2, q1.P3, q1.P0)) return true;\n\n            if (q1.IntersectsTriangle(q0.P0, q0.P1, q0.P2)) return true;\n            if (q1.IntersectsTriangle(q0.P2, q0.P3, q0.P0)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n\n        #region __plane3t__ intersects __line3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane3t__ plane, __line3t__ line)\n        {\n            return plane.IntersectsLine(line.P0, line.P1, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane3t__ plane, __line3t__ line, __rtype__ absoluteEpsilon)\n        {\n            return plane.IntersectsLine(line.P0, line.P1, absoluteEpsilon);\n        }\n\n        public static bool IntersectsLine(this __plane3t__ plane, __v3t__ p0, __v3t__ p1, __rtype__ absoluteEpsilon)\n        {\n            __rtype__ h0 = plane.Height(p0);\n            int s0 = (h0 > absoluteEpsilon ? 1 :(h0 < -absoluteEpsilon ? -1 : 0));\n            if (s0 == 0) return true;\n\n            __rtype__ h1 = plane.Height(p1);\n            int s1 = (h1 > absoluteEpsilon ? 1 : (h1 < -absoluteEpsilon ? -1 : 0));\n            if (s1 == 0) return true;\n\n\n            if (s0 == s1) return false;\n            else return true;\n        }\n\n        public static bool IntersectsLine(this __plane3t__ plane, __v3t__ p0, __v3t__ p1, __rtype__ absoluteEpsilon, out __v3t__ point)\n        {\n            //<n|origin + t0*dir> == d\n            //<n|or> + t0*<n|dir> == d\n            //t0 == (d - <n|or>) / <n|dir>;\n\n            __v3t__ dir = p1 - p0;\n            __rtype__ ld = dir.Length;\n            dir /= ld;\n\n            __rtype__ nDotd = plane.Normal.Dot(dir);\n\n\n            if (!Fun.IsTiny(nDotd))\n            {\n                __rtype__ t0 = (plane.Distance - plane.Normal.Dot(p0)) / nDotd;\n\n                if (t0 >= -absoluteEpsilon && t0 <= ld + absoluteEpsilon)\n                {\n                    point = p0 + dir * t0;\n                    return true;\n                }\n                else\n                {\n                    point = __v3t__.NaN;\n                    return false;\n                }\n            }\n            else\n            {\n                point = __v3t__.NaN;\n                return false;\n            }\n\n        }\n\n        #endregion\n\n        #region __plane3t__ intersects __ray3t__\n\n        /// <summary>\n        /// Returns true if the __ray3t__ and the __plane3t__ intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __ray3t__ ray, __plane3t__ plane)\n            => !plane.Normal.IsOrthogonalTo(ray.Direction);\n\n        /// <summary>\n        /// Returns true if the ray and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this __ray3t__ ray, __plane3t__ plane, out __rtype__ t\n             )\n        {\n            __rtype__ dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot))\n            {\n                t = __rtype__.PositiveInfinity;\n                return false;\n            }\n            t = -plane.Height(ray.Origin) / dot;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns the intersection point with the given plane, or __v3t__.PositiveInfinity if ray is parallel to plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ Intersect(\n             this __ray3t__ ray, __plane3t__ plane\n             )\n        {\n            __rtype__ dot = Vec.Dot(ray.Direction, plane.Normal);\n            if (Fun.IsTiny(dot)) return __v3t__.PositiveInfinity;\n            return ray.GetPointOnRay(-plane.Height(ray.Origin) / dot);\n        }\n\n        /// <summary>\n        /// Returns true if the ray and the plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this __ray3t__ ray, __plane3t__ plane, out __rtype__ t, out __v3t__ p\n             )\n        {\n            bool result = Intersects(ray, plane, out t);\n            p = ray.Origin + t * ray.Direction;\n            return result;\n        }\n\n        #endregion\n\n        #region __plane3t__ intersects __plane3t__\n\n        public static bool Intersects(this __plane3t__ p0, __plane3t__ p1)\n        {\n            bool parallel = p0.Normal.IsParallelTo(p1.Normal);\n\n            if (parallel) return Fun.IsTiny(p0.Distance - p1.Distance);\n            else return true;\n        }\n\n        public static bool Intersects(this __plane3t__ p0, __plane3t__ p1, out __ray3t__ ray)\n        {\n            __v3t__ dir = p0.Normal.Cross(p1.Normal);\n            __rtype__ len = dir.Length;\n\n            if (Fun.IsTiny(len))\n            {\n                if (Fun.IsTiny(p0.Distance - p1.Distance))\n                {\n                    ray = new __ray3t__(p0.Normal * p0.Distance, __v3t__.Zero);\n                    return true;\n                }\n                else\n                {\n                    ray = __ray3t__.Invalid;\n                    return false;\n                }\n            }\n\n            dir *= 1 / len;\n\n            var alu = new __rtype__[,]\n                { { p0.Normal.X, p0.Normal.Y, p0.Normal.Z },\n                  { p1.Normal.X, p1.Normal.Y, p1.Normal.Z },\n                  { dir.X, dir.Y, dir.Z } };\n\n            int[] p = alu.LuFactorize();\n\n            var b = new __rtype__[] { p0.Distance, p1.Distance, 0 };\n\n            var x = alu.LuSolve(p, b);\n\n            ray = new __ray3t__(new __v3t__(x), dir);\n            return true;\n        }\n\n        #endregion\n\n        #region __plane3t__ intersects __plane3t__ intersects __plane3t__\n\n        public static bool Intersects(this __plane3t__ p0, __plane3t__ p1, __plane3t__ p2, out __v3t__ point)\n        {\n            var alu = new __rtype__[,]\n                { { p0.Normal.X, p0.Normal.Y, p0.Normal.Z },\n                  { p1.Normal.X, p1.Normal.Y, p1.Normal.Z },\n                  { p2.Normal.X, p2.Normal.Y, p2.Normal.Z } };\n\n            var p = new int[3];\n            if (!alu.LuFactorize(p)) { point = __v3t__.NaN; return false; }\n            var b = new __rtype__[] { p0.Distance, p1.Distance, p2.Distance };\n            var x = alu.LuSolve(p, b);\n            point = new __v3t__(x);\n            return true;\n        }\n\n        #endregion\n\n        #region __plane3t__ intersects __triangle3t__\n\n        /// <summary>\n        /// Returns whether the given plane and triangle intersect.\n        /// </summary>\n        public static bool Intersects(\n             this __plane3t__ plane, __triangle3t__ triangle\n             )\n        {\n            int sign = plane.Sign(triangle.P0);\n            if (sign == 0) return true;\n            if (sign != plane.Sign(triangle.P1)) return true;\n            if (sign != plane.Sign(triangle.P2)) return true;\n            return false;\n        }\n\n        #endregion\n\n        #region __plane3t__ intersects __sphere3t__\n\n        /// <summary>\n        /// Returns whether the given sphere and plane intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this __plane3t__ plane, __sphere3t__ sphere\n             )\n        {\n            return sphere.Radius >= plane.Height(sphere.Center).Abs();\n        }\n\n        #endregion\n\n        #region __plane3t__ intersects __polygon3t__\n\n        /// <summary>\n        /// returns true if the __plane3t__ and the __polygon3t__ intersect\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __plane3t__ plane,\n            __polygon3t__ poly\n            )\n        {\n            return plane.Intersects(poly, Constant<__rtype__>.PositiveTinyValue);\n        }\n\n        /// <summary>\n        /// returns true if the __plane3t__ and the polygon, intersect\n        /// within a tolerance of absoluteEpsilon\n        /// </summary>\n        public static bool Intersects(\n            this __plane3t__ plane,\n            __polygon3t__ polygon,\n            __rtype__ absoluteEpsilon\n            )\n        {\n            __rtype__ height = plane.Height(polygon[0]);\n            int sign0 = height > -absoluteEpsilon ? (height < absoluteEpsilon ? 0 : 1) : -1; if (sign0 == 0) return true;\n            int pc = polygon.PointCount;\n            for (int i = 1; i < pc; i++)\n            {\n                height = plane.Height(polygon[i]);\n                int sign = height > -absoluteEpsilon ? (height < absoluteEpsilon ? 0 : 1) : -1;\n                if (sign != sign0) return true;\n            }\n\n            return false;\n        }\n\n\n        /// <summary>\n        /// returns true if the __plane3t__ and the __polygon3t__ intersect.\n        /// line holds the intersection line\n        /// ATTENTION: works only with non-concave polygons!\n        /// </summary>\n        public static bool IntersectsConvex(\n            this __plane3t__ plane,\n            __polygon3t__ poly,\n            out __line3t__ line\n            )\n        {\n            return plane.IntersectsConvex(poly, Constant<__rtype__>.PositiveTinyValue, out line);\n        }\n\n        /// <summary>\n        /// Returns true if the __plane3t__ and the polygon, given by points, intersect\n        /// within a tolerance of absoluteEpsilon.\n        /// Line holds the intersection line.\n        /// ATTENTION: works only with non-concave polygons!\n        /// </summary>\n        public static bool IntersectsConvex(\n            this __plane3t__ plane,\n            __polygon3t__ polygon,\n            __rtype__ absoluteEpsilon,\n            out __line3t__ line\n            )\n        {\n            int count = polygon.PointCount;\n            int[] signs = new int[count];\n            int pc = 0, nc = 0, zc = 0;\n            for (int pi = 0; pi < count; pi++)\n            {\n                __rtype__ h = plane.Height(polygon[pi]);\n                if (h < -absoluteEpsilon) { nc++; signs[pi] = -1; continue; }\n                if (h > absoluteEpsilon) { pc++; signs[pi] = 1; continue;  }\n                zc++; signs[pi] = 0;\n            }\n\n            if (zc == count)\n            {\n                line = new __line3t__(polygon[0], polygon[0]);\n                return false;\n            }\n            else if (pc == 0 && zc == 0)\n            {\n                line = new __line3t__(__v3t__.NaN, __v3t__.NaN);\n                return false;\n            }\n            else if (nc == 0 && zc == 0)\n            {\n                line = new __line3t__(__v3t__.NaN, __v3t__.NaN);\n                return false;\n            }\n            else\n            {\n                int pointcount = 0;\n                __v3t__[] linePoints = new __v3t__[2];\n                for (int i = 0; i < count; i++)\n                {\n                    int u = (i + 1) % count;\n\n                    if (signs[i] != signs[u] || signs[i] == 0 || signs[u] == 0)\n                    {\n                        if (plane.IntersectsLine(polygon[i], polygon[u], absoluteEpsilon, out __v3t__ point))\n                        {\n                            linePoints[pointcount++] = point;\n                            //If Endpoint is on Plane => Next startpoint is on plane => same intersection point\n                            // => skip all following lines which start within absoluteEpsilon (whic have a zero sign)\n                            while (signs[(i + 1) % count] == 0) i++;\n                        }\n                    }\n                    if (pointcount == 2)\n                    {\n                        //\n                        line = new __line3t__(linePoints[0], linePoints[1]);\n                        return true;\n                    }\n                }\n                line = new __line3t__(__v3t__.NaN, __v3t__.NaN);\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region __plane3t__ intersects __cylinder3t__\n\n        /// <summary>\n        /// Returns whether the given sphere and cylinder intersect.\n        /// </summary>\n        public static bool Intersects(this __plane3t__ plane, __cylinder3t__ cylinder)\n        {\n            if (plane.IsParallelToAxis(cylinder))\n            {\n                var distance = cylinder.P0.GetMinimalDistanceTo(plane);\n                return distance < cylinder.Radius;\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Tests if the given plane is parallel to the cylinder axis (i.e. the plane's normal is orthogonal to the axis).\n        /// The plane will intersect the cylinder in two rays or in one tangent line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelToAxis(this __plane3t__ plane, __cylinder3t__ cylinder)\n            => plane.Normal.IsOrthogonalTo(cylinder.Axis.Direction.Normalized);\n\n        /// <summary>\n        /// Tests if the given plane is orthogonal to the cylinder axis (i.e. the plane's normal is parallel to the axis).\n        /// The plane will intersect the cylinder in a circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalToAxis(this __plane3t__ plane, __cylinder3t__ cylinder)\n            => plane.Normal.IsParallelTo(cylinder.Axis.Direction.Normalized);\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in an ellipse.\n        /// This is only true if the plane is neither orthogonal nor parallel to the cylinder axis. Otherwise the intersection methods returning a circle or rays have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"ellipse\"></param>\n        public static bool Intersects(this __plane3t__ plane, __cylinder3t__ cylinder, out __ellipse3t__ ellipse)\n        {\n            if (plane.IsParallelToAxis(cylinder) || plane.IsOrthogonalToAxis(cylinder))\n            {\n                ellipse = __ellipse3t__.Zero;\n                return false;\n            }\n\n            var dir = cylinder.Axis.Direction.Normalized;\n            cylinder.Axis.__ray3t__.Intersects(plane, out _, out __v3t__ center);\n            var cosTheta = dir.Dot(plane.Normal);\n\n            var eNormal = plane.Normal;\n            var eCenter = center;\n            var eMajor = (dir - cosTheta * eNormal).Normalized;\n            var eMinor = (eNormal.Cross(eMajor)).Normalized;\n            eMajor = eNormal.Cross(eMinor).Normalized; //to be sure - if ellipse is nearly a circle\n            eMajor = eMajor * cylinder.Radius / cosTheta.Abs();\n            eMinor *= cylinder.Radius;\n            ellipse = new __ellipse3t__(eCenter, eNormal, eMajor, eMinor);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in a circle.\n        /// This is only true if the plane is orthogonal to the cylinder axis. Otherwise the intersection methods returning an ellipse or rays have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"circle\"></param>\n        public static bool Intersects(this __plane3t__ plane, __cylinder3t__ cylinder, out __circle3t__ circle)\n        {\n            if (plane.IsOrthogonalToAxis(cylinder))\n            {\n                circle = cylinder.GetCircle(cylinder.GetHeight(plane.Point));\n                return true;\n            }\n\n            circle = __circle3t__.Zero;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the given plane and cylinder intersect in one or two rays.\n        /// This is only true if the plane is parallel to the cylinder axis. Otherwise the intersection methods returning an ellipse or a circle have to be used.\n        /// </summary>\n        /// <param name=\"plane\"></param>\n        /// <param name=\"cylinder\">The cylinder is assumed to have infinite extent along its axis.</param>\n        /// <param name=\"rays\">Output of intersection rays. The array contains two rays (intersection), one ray (plane is tangent to cylinder) or no ray (no intersection).</param>\n        public static bool Intersects(this __plane3t__ plane, __cylinder3t__ cylinder, out __ray3t__[] rays)\n        {\n            if (plane.IsParallelToAxis(cylinder))\n            {\n                var distance = cylinder.P0.GetMinimalDistanceTo(plane);\n                var center = cylinder.P0 - distance * plane.Normal;\n                var axis = cylinder.Axis.Direction.Normalized;\n\n                if (distance == cylinder.Radius) //one tangent line\n                {\n                    rays = new[] { new __ray3t__(center, axis) };\n                    return true;\n                }\n                else //two intersection lines\n                {\n                    var offset = axis.Cross(plane.Normal);\n                    var extent = (cylinder.Radius.Square() - distance.Square()).Sqrt();\n                    rays = new[]\n                    {\n                        new __ray3t__(center - extent * offset, axis),\n                        new __ray3t__(center + extent * offset, axis)\n                    };\n                    return true;\n                }\n            }\n            rays = Array.Empty<__ray3t__>();\n            return false;\n        }\n\n        #endregion\n\n\n        #region __sphere3t__ intersects __sphere3t__ (sm)\n\n        /// <summary>\n        /// Returns true if the spheres intersect, or one contains the other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __sphere3t__ s0, __sphere3t__ s1)\n            => (s0.Center - s1.Center).LengthSquared <= (s0.Radius + s1.Radius).Square();\n\n        #endregion\n\n\n        #region __box3t__ intersects __line3t__\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool Intersects(this __box3t__ box, __line3t__ line)\n        {\n            var out0 = box.OutsideFlags(line.P0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(line.P1); if (out1 == 0) return true;\n            return box.IntersectsLine(line.P0, line.P1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect.\n        /// </summary>\n        public static bool IntersectsLine(\n                this __box3t__ box, __v3t__ p0, __v3t__ p1)\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            return box.IntersectsLine(p0, p1, out0, out1);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the line intersect. The outside flags\n        /// of the end points of the line with respect to the box have to be\n        /// supplied, and have to be already individually tested against\n        /// intersection with the box.\n        /// </summary>\n        public static bool IntersectsLine(\n                this __box3t__ box, __v3t__ p0, __v3t__ p1, Box.Flags out0, Box.Flags out1)\n        {\n            if ((out0 & out1) != 0) return false;\n\n            __v3t__ min = box.Min;\n            __v3t__ max = box.Max;\n            var bf = out0 | out1;\n\n            if ((bf & Box.Flags.X) != 0)\n            {\n                __rtype__ dx = p1.X - p0.X;\n                if ((bf & Box.Flags.MinX) != 0)\n                {\n                    if (dx == 0 && p0.X < min.X) return false;\n                    __rtype__ t = (min.X - p0.X) / dx;\n                    __v3t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinX) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxX) != 0)\n                {\n                    if (dx == 0 && p0.X > max.X) return false;\n                    __rtype__ t = (max.X - p0.X) / dx;\n                    __v3t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxX) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Y) != 0)\n            {\n                __rtype__ dy = p1.Y - p0.Y;\n                if ((bf & Box.Flags.MinY) != 0)\n                {\n                    if (dy == 0 && p0.Y < min.Y) return false;\n                    __rtype__ t = (min.Y - p0.Y) / dy;\n                    __v3t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinY) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxY) != 0)\n                {\n                    if (dy == 0 && p0.Y > max.Y) return false;\n                    __rtype__ t = (max.Y - p0.Y) / dy;\n                    __v3t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxY) == 0)\n                        return true;\n                }\n            }\n            if ((bf & Box.Flags.Z) != 0)\n            {\n                __rtype__ dz = p1.Z - p0.Z;\n                if ((bf & Box.Flags.MinZ) != 0)\n                {\n                    if (dz == 0 && p0.Z < min.Z) return false;\n                    __rtype__ t = (min.Z - p0.Z) / dz;\n                    __v3t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MinZ) == 0)\n                        return true;\n                }\n                if ((bf & Box.Flags.MaxZ) != 0)\n                {\n                    if (dz == 0 && p0.Z > max.Z) return false;\n                    __rtype__ t = (max.Z - p0.Z) / dz;\n                    __v3t__ p = p0 + t * (p1 - p0);\n                    if ((box.OutsideFlags(p) & ~Box.Flags.MaxZ) == 0)\n                        return true;\n                }\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region __box3t__ intersects __ray3t__ (haaser)\n\n        public static bool Intersects(this __box3t__ box, __ray3t__ ray, out __rtype__ t)\n        {\n            Box.Flags out0 = box.OutsideFlags(ray.Origin);\n\n            if (out0 == 0)\n            {\n                t = 0;\n                return true;\n            }\n\n            __box3t__ largeBox = box.EnlargedByRelativeEps(__eminus5__);\n            __rtype__ tmin = __rtype__.PositiveInfinity;\n            __rtype__ ttemp;\n            if ((out0 & Box.Flags.X) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.X))\n                {\n                    if ((out0 & Box.Flags.MinX) != 0)\n                    {\n                        ttemp = (box.Min.X - ray.Origin.X) / ray.Direction.X;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxX) != 0)\n                    {\n                        ttemp = (box.Max.X - ray.Origin.X) / ray.Direction.X;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if ((out0 & Box.Flags.Y) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.Y))\n                {\n                    if ((out0 & Box.Flags.MinY) != 0)\n                    {\n                        ttemp = (box.Min.Y - ray.Origin.Y) / ray.Direction.Y;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxY) != 0)\n                    {\n                        ttemp = (box.Max.Y - ray.Origin.Y) / ray.Direction.Y;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if ((out0 & Box.Flags.Z) != 0)\n            {\n                if (!Fun.IsTiny(ray.Direction.Z))\n                {\n                    if ((out0 & Box.Flags.MinZ) != 0)\n                    {\n                        ttemp = (box.Min.Z - ray.Origin.Z) / ray.Direction.Z;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                    else if ((out0 & Box.Flags.MaxZ) != 0)\n                    {\n                        ttemp = (box.Max.Z - ray.Origin.Z) / ray.Direction.Z;\n                        if (ttemp.Abs() < tmin.Abs() && largeBox.Contains(ray.Origin + ttemp * ray.Direction)) tmin = ttemp;\n                    }\n                }\n            }\n\n\n            if (tmin < __rtype__.PositiveInfinity)\n            {\n                t = tmin;\n                return true;\n            }\n\n            t = __rtype__.NaN;\n            return false;\n        }\n\n\n        #endregion\n\n        #region __box3t__ intersects __plane3t__\n\n        /// <summary>\n        /// Returns true if the box and the plane intersect or touch with a\n        /// supplied epsilon tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __box3t__ box, __plane3t__ plane, __rtype__ eps)\n        {\n            var signs = box.GetIntersectionSignsWithPlane(plane, eps);\n            return signs != Signs.Negative && signs != Signs.Positive;\n        }\n\n        /// <summary>\n        /// Classify the position of all the eight vertices of a box with\n        /// respect to a supplied plane.\n        /// </summary>\n        public static Signs GetIntersectionSignsWithPlane(\n            this __box3t__ box, __plane3t__ plane, __rtype__ eps)\n        {\n            var normal = plane.Normal;\n            var distance = plane.Distance;\n\n            __rtype__ npMinX = normal.X * box.Min.X;\n            __rtype__ npMaxX = normal.X * box.Max.X;\n            __rtype__ npMinY = normal.Y * box.Min.Y;\n            __rtype__ npMaxY = normal.Y * box.Max.Y;\n            __rtype__ npMinZ = normal.Z * box.Min.Z;\n            __rtype__ npMaxZ = normal.Z * box.Max.Z;\n\n            __rtype__ hMinZ = npMinZ - distance;\n            __rtype__ hMaxZ = npMaxZ - distance;\n\n            __rtype__ hMinYMinZ = npMinY + hMinZ;\n            __rtype__ hMaxYMinZ = npMaxY + hMinZ;\n            __rtype__ hMinYMaxZ = npMinY + hMaxZ;\n            __rtype__ hMaxYMaxZ = npMaxY + hMaxZ;\n\n            return (npMinX + hMinYMinZ).GetSigns(eps)\n                 | (npMaxX + hMinYMinZ).GetSigns(eps)\n                 | (npMinX + hMaxYMinZ).GetSigns(eps)\n                 | (npMaxX + hMaxYMinZ).GetSigns(eps)\n                 | (npMinX + hMinYMaxZ).GetSigns(eps)\n                 | (npMaxX + hMinYMaxZ).GetSigns(eps)\n                 | (npMinX + hMaxYMaxZ).GetSigns(eps)\n                 | (npMaxX + hMaxYMaxZ).GetSigns(eps);\n        }\n\n        /// <summary>\n        /// Returns true if the box intersects the supplied plane. The\n        /// bounding boxes of the resulting parts are returned in the out\n        /// parameters.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Signs GetIntersectionSigns(\n                this __box3t__ box, __plane3t__ plane, __rtype__ eps,\n                out __box3t__ negBox, out __box3t__ zeroBox, out __box3t__ posBox)\n        {\n            return box.GetIntersectionSigns(plane.Normal, plane.Distance, eps,\n                                       out negBox, out zeroBox, out posBox);\n        }\n\n        /// <summary>\n        /// Returns true if the box intersects the supplied plane. The\n        /// bounding boxes of the resulting parts are returned in the out\n        /// parameters.\n        /// </summary>\n        public static Signs GetIntersectionSigns(\n                this __box3t__ box, __v3t__ normal, __rtype__ distance, __rtype__ eps,\n                out __box3t__ negBox, out __box3t__ zeroBox, out __box3t__ posBox)\n        {\n            __rtype__ npMinX = normal.X * box.Min.X;\n            __rtype__ npMaxX = normal.X * box.Max.X;\n            __rtype__ npMinY = normal.Y * box.Min.Y;\n            __rtype__ npMaxY = normal.Y * box.Max.Y;\n            __rtype__ npMinZ = normal.Z * box.Min.Z;\n            __rtype__ npMaxZ = normal.Z * box.Max.Z;\n\n            var ha = new __rtype__[8];\n\n            __rtype__ hMinZ = npMinZ - distance;\n            __rtype__ hMaxZ = npMaxZ - distance;\n\n            __rtype__ hMinYMinZ = npMinY + hMinZ;\n            ha[0] = npMinX + hMinYMinZ;\n            ha[1] = npMaxX + hMinYMinZ;\n\n            __rtype__ hMaxYMinZ = npMaxY + hMinZ;\n            ha[2] = npMinX + hMaxYMinZ;\n            ha[3] = npMaxX + hMaxYMinZ;\n\n            __rtype__ hMinYMaxZ = npMinY + hMaxZ;\n            ha[4] = npMinX + hMinYMaxZ;\n            ha[5] = npMaxX + hMinYMaxZ;\n\n            __rtype__ hMaxYMaxZ = npMaxY + hMaxZ;\n            ha[6] = npMinX + hMaxYMaxZ;\n            ha[7] = npMaxX + hMaxYMaxZ;\n\n            Signs all = Signs.None;\n            var sa = new Signs[8];\n            for (int i = 0; i < 8; i++) { sa[i] = ha[i].GetSigns(eps); all |= sa[i]; }\n\n            negBox = __box3t__.Invalid;\n            zeroBox = __box3t__.Invalid;\n            posBox = __box3t__.Invalid;\n\n            if (all == Signs.Zero) { zeroBox = box; return all; }\n            if (all == Signs.Positive) { posBox = box; return all; }\n            if (all == Signs.Negative) { negBox = box; return all; }\n\n            var pa = box.ComputeCorners();\n\n            for (int i = 0; i < 8; i++)\n            {\n                if (sa[i] == Signs.Negative)\n                    negBox.ExtendBy(pa[i]);\n                else if (sa[i] == Signs.Positive)\n                    posBox.ExtendBy(pa[i]);\n                else\n                {\n                    negBox.ExtendBy(pa[i]);\n                    zeroBox.ExtendBy(pa[i]);\n                    posBox.ExtendBy(pa[i]);\n                }\n            }\n\n            if (all == Signs.NonPositive) { posBox = __box3t__.Invalid; return all; }\n            if (all == Signs.NonNegative) { negBox = __box3t__.Invalid; return all; }\n\n            for (int ei = 0; ei < 12; ei++)\n            {\n                int i0 = c_cubeEdgeVertex0[ei], i1 = c_cubeEdgeVertex1[ei];\n\n                if ((sa[i0] == Signs.Negative && sa[i1] == Signs.Positive)\n                    || (sa[i0] == Signs.Positive && sa[i1] == Signs.Negative))\n                {\n                    __rtype__ h0 = ha[i0];\n                    __rtype__ t = h0 / (h0 - ha[i1]);\n                    __v3t__ p0 = pa[i0];\n                    __v3t__ sp = p0 + t * (pa[i1] - p0);\n                    negBox.ExtendBy(sp);\n                    zeroBox.ExtendBy(sp);\n                    posBox.ExtendBy(sp);\n                }\n            }\n\n            return all;\n        }\n\n        #endregion\n\n        #region __box3t__ intersects __sphere3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this __box3t__ box, __sphere3t__ sphere\n             )\n        {\n            __v3t__ v = sphere.Center.GetClosestPointOn(box) - sphere.Center;\n            return sphere.RadiusSquared >= v.LengthSquared;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this __box3t__ box, __cylinder3t__ cylinder\n             )\n        {\n\n            return box.Intersects(cylinder.BoundingBox3__tc__);\n\n            //throw new NotImplementedException();\n        }\n\n        #endregion\n\n        #region __box3t__ intersects __triangle3t__\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n             this __box3t__ box, __triangle3t__ triangle\n             )\n        {\n            return box.IntersectsTriangle(triangle.P0, triangle.P1, triangle.P2);\n        }\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect.\n        /// </summary>\n        public static bool IntersectsTriangle(\n             this __box3t__ box, __v3t__ p0, __v3t__ p1, __v3t__ p2\n             )\n        {\n            /* ---------------------------------------------------------------\n               If one of the points of the triangle is inside the box, it\n               intersects, of course.\n            --------------------------------------------------------------- */\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n            return box.IntersectsTriangle(p0, p1, p2, out0, out1, out2);\n        }\n\n\n        /// <summary>\n        /// Returns true if the box and the triangle intersect. The outside\n        /// flags of the triangle vertices with respect to the box have to be\n        /// supplied, and already be individually tested for intersection with\n        /// the box.\n        /// </summary>\n        public static bool IntersectsTriangle(\n             this __box3t__ box, __v3t__ p0, __v3t__ p1, __v3t__ p2,\n             Box.Flags out0, Box.Flags out1, Box.Flags out2\n             )\n        {\n            /* ---------------------------------------------------------------\n                If all of the points of the triangle are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2) != 0) return false;\n\n            /* ---------------------------------------------------------------\n                If two points of the triangle are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p0, out2, out0)) return true;\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the triangle go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n            --------------------------------------------------------------- */\n            __ray3t__ ray = new __ray3t__(box.Min, box.Size);\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.IntersectsTriangle(p0, p1, p2, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __box3t__ intersects __quad3t__ (haaser)\n\n        public static bool Intersects(\n            this __box3t__ box, __quad3t__ quad\n            )\n        {\n            Box.Flags out0 = box.OutsideFlags(quad.P0); if (out0 == 0) return true;\n            Box.Flags out1 = box.OutsideFlags(quad.P1); if (out1 == 0) return true;\n            Box.Flags out2 = box.OutsideFlags(quad.P2); if (out2 == 0) return true;\n            Box.Flags out3 = box.OutsideFlags(quad.P3); if (out3 == 0) return true;\n\n            return box.IntersectsQuad(quad.P0, quad.P1, quad.P2, quad.P3, out0, out1, out2, out3);\n        }\n\n        public static bool IntersectsQuad(\n             this __box3t__ box, __v3t__ p0, __v3t__ p1, __v3t__ p2, __v3t__ p3\n             )\n        {\n            var out0 = box.OutsideFlags(p0); if (out0 == 0) return true;\n            var out1 = box.OutsideFlags(p1); if (out1 == 0) return true;\n            var out2 = box.OutsideFlags(p2); if (out2 == 0) return true;\n            var out3 = box.OutsideFlags(p3); if (out3 == 0) return true;\n\n            return box.IntersectsQuad(p0, p1, p2, p3, out0, out1, out2, out3);\n        }\n\n        public static bool IntersectsQuad(\n            this __box3t__ box, __v3t__ p0, __v3t__ p1, __v3t__ p2, __v3t__ p3,\n            Box.Flags out0, Box.Flags out1, Box.Flags out2, Box.Flags out3\n            )\n        {\n            /* ---------------------------------------------------------------\n                If all of the points of the quad are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            if ((out0 & out1 & out2 & out3) != 0) return false;\n\n\n            /* ---------------------------------------------------------------\n                If two points of the quad are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            if (box.IntersectsLine(p0, p1, out0, out1)) return true;\n            if (box.IntersectsLine(p1, p2, out1, out2)) return true;\n            if (box.IntersectsLine(p2, p3, out2, out3)) return true;\n            if (box.IntersectsLine(p3, p0, out3, out0)) return true;\n\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the quad go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n            --------------------------------------------------------------- */\n            __ray3t__ ray = new __ray3t__(box.Min, box.Size);\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.IntersectsQuad(p0, p1, p2, p3, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __box3t__ intersects __polygon3t__ (haaser)\n\n        public static bool Intersects(this __box3t__ box, __polygon3t__ poly)\n        {\n            int edges = poly.PointCount;\n            Box.Flags[] outside = new Box.Flags[edges];\n            for (int i = 0; i < edges; i++)\n            {\n                outside[i] = box.OutsideFlags(poly[i]); if (outside[i] == 0) return true;\n            }\n\n            /* ---------------------------------------------------------------\n                If all of the points of the polygon are on the same side\n                outside the box, no intersection is possible.\n            --------------------------------------------------------------- */\n            Box.Flags sum = outside[0];\n            for (int i = 1; i < edges; i++) sum &= outside[i];\n            if (sum != 0) return false;\n\n            /* ---------------------------------------------------------------\n                If two points of the polygon are not on the same side\n                outside the box, it is possible that the edge between them\n                intersects the box. The outside flags we computed are also\n                used to optimize the intersection routine with the edge.\n            --------------------------------------------------------------- */\n            int u;\n            for (int i = 0; i < edges; i++)\n            {\n                u = (i + 1) % edges;\n                if (box.IntersectsLine(poly[i], poly[u], outside[i], outside[u])) return true;\n            }\n\n            /* ---------------------------------------------------------------\n                The only case left: the edges of the polygon go outside\n                around the box. Intersect the four space diagonals of the box\n                with the triangle to test for intersection.\n                The polygon needs to be triangulated for this check\n            --------------------------------------------------------------- */\n\n            int[] tris = poly.ComputeTriangulationOfConcavePolygon(__eminus5__);\n\n            __ray3t__ ray = new __ray3t__(box.Min, box.Size);\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n\n            ray.Origin.X = box.Max.X;\n            ray.Direction.X = -ray.Direction.X;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n            ray.Direction.X = -ray.Direction.X;\n            ray.Origin.X = box.Min.X;\n\n            ray.Origin.Y = box.Max.Y;\n            ray.Direction.Y = -ray.Direction.Y;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n            ray.Direction.Y = -ray.Direction.Y;\n            ray.Origin.Y = box.Min.Y;\n\n            ray.Origin.Z = box.Max.Z;\n            ray.Direction.Z = -ray.Direction.Z;\n            if (ray.Intersects(poly, tris, 0, 1)) return true;\n\n            return false;\n        }\n\n        #endregion\n\n        #region __box3t__ intersects Projection-Trafo (haaser)\n\n        /// <summary>\n        /// returns true if the __box3t__ and the frustum described by the __m44t__ intersect or the frustum contains the __box3t__\n        /// Assumes DirectX clip-space:\n        ///     -w &lt; x &lt; w\n        ///     -w &lt; y &lt; w\n        ///      0 &lt; z &lt; w\n        /// </summary>\n        public static bool IntersectsFrustum(this __box3t__ box, __m44t__ projection)\n        {\n            //Let's look at the left clip-plane\n            //which corresponds to:\n            //-w < x\n            //  # which can easily be transformed to:\n            //0 < x + w\n            //  # for a given vector v this means (* is a dot product here)\n            //0 < proj.R0 * v + proj.R3 * v\n            //  # or in other words:\n            //0 < (proj.R0 + proj.R3) * v\n\n            //therefore (proj.R0 + proj.R3) is the plane describing the left clip-plane.\n            //The other planes can be derived in a similar way (only the near plane is a little different)\n            //see http://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/ for a full explanation\n\n            var r0 = projection.R0;\n            var r1 = projection.R1;\n            var r2 = projection.R2;\n            var r3 = projection.R3;\n\n\n            __v4t__ plane;\n            __v3t__ n;\n\n            //left\n            plane = r3 + r0;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out __v3t__ min, out __v3t__ max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //right\n            plane = r3 - r0;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //top\n            plane = r3 + r1;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //bottom\n            plane = r3 - r1;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //near\n            plane = r2;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n            //far\n            plane = r3 - r2;\n            n = plane.XYZ; box.GetMinMaxInDirection(n, out min, out max);\n            if (min.Dot(n) + plane.W < 0 && max.Dot(n) + plane.W < 0) return false;\n\n\n            return true;\n        }\n\n\n\n        #endregion\n\n\n        #region __hull3t__ intersects __line3t__\n\n        /// <summary>\n        /// returns true if the __hull3t__ and the __line3t__ intersect or the __hull3t__ contains the __line3t__\n        /// [__hull3t__-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __hull3t__ hull,\n            __line3t__ line\n            )\n        {\n            if (hull.Contains(line.P0)) return true;\n            if (hull.Contains(line.P1)) return true;\n\n            return hull.Intersects(line.__ray3t__, 0, 1, out _);\n        }\n\n        /// <summary>\n        /// returns true if the __hull3t__ and the Line between p0 and p1 intersect or the __hull3t__ contains the Line\n        /// [__hull3t__-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IntersectsLine(\n            this __hull3t__ hull,\n            __v3t__ p0, __v3t__ p1\n            )\n        {\n            return hull.Intersects(new __line3t__(p0, p1));\n        }\n\n        #endregion\n\n        #region __hull3t__ intersects __ray3t__\n\n        /// <summary>\n        /// returns true if the __hull3t__ and the __ray3t__ intersect\n        /// [__hull3t__-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __hull3t__ hull,\n            __ray3t__ ray\n            )\n        {\n            return hull.Intersects(ray, __rtype__.NegativeInfinity, __rtype__.PositiveInfinity, out _);\n        }\n\n        /// <summary>\n        /// returns true if the __hull3t__ and the __ray3t__ intersect\n        /// the out parameter t holds the ray-parameter where an intersection was found\n        /// [__hull3t__-Normals must point outside]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(\n            this __hull3t__ hull,\n            __ray3t__ ray,\n            out __rtype__ t\n            )\n        {\n            return hull.Intersects(ray, __rtype__.NegativeInfinity, __rtype__.PositiveInfinity, out t);\n        }\n\n        /// <summary>\n        /// returns true if the __hull3t__ and the __ray3t__ intersect and the\n        /// ray-parameter for the intersection is between t_min and t_max\n        /// the out parameter t holds the ray-parameter where an intersection was found\n        /// [__hull3t__-Normals must point outside]\n        /// </summary>\n        public static bool Intersects(\n            this __hull3t__ hull,\n            __ray3t__ ray,\n            __rtype__ t_min, __rtype__ t_max,\n            out __rtype__ t\n            )\n        {\n            if (!__rtype__.IsInfinity(t_min) && hull.Contains(ray.GetPointOnRay(t_min))) { t = t_min; return true; }\n            if (!__rtype__.IsInfinity(t_max) && hull.Contains(ray.GetPointOnRay(t_max))) { t = t_max; return true; }\n\n            var planes = hull.PlaneArray;\n            for (int i = 0; i < planes.Length; i++)\n            {\n                if (!Fun.IsTiny(planes[i].Normal.Dot(ray.Direction)) &&\n                    ray.Intersects(planes[i], out __rtype__ temp_t) &&\n                    temp_t >= t_min && temp_t <= t_max)\n                {\n                    __v3t__ candidatePoint = ray.GetPointOnRay(temp_t);\n                    bool contained = true;\n\n                    for (int u = 0; u < planes.Length; u++)\n                    {\n                        if (u != i && planes[u].Height(candidatePoint) > Constant<__rtype__>.PositiveTinyValue)\n                        {\n                            contained = false;\n                            break;\n                        }\n                    }\n\n                    if (contained)\n                    {\n                        t = temp_t;\n                        return true;\n                    }\n                }\n            }\n\n            t = __rtype__.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region __hull3t__ intersects __plane3t__\n\n        /// <summary>\n        /// returns true if the __hull3t__ and the __plane3t__ intersect\n        /// [__hull3t__-Normals must point outside]\n        /// </summary>\n        public static bool Intersects(\n            this __hull3t__ hull,\n            __plane3t__ plane\n            )\n        {\n            foreach (var p in hull.PlaneArray)\n            {\n                if (!p.Normal.IsParallelTo(plane.Normal) && p.Intersects(plane, out __ray3t__ ray))\n                {\n                    if (hull.Intersects(ray)) return true;\n                }\n            }\n\n            return false;\n        }\n\n        #endregion\n\n        #region __hull3t__ intersects __box3t__\n\n        /// <summary>\n        /// Returns true if the hull and the box intersect.\n        /// </summary>\n        public static bool Intersects(\n            this __hull3t__ hull, __box3t__ box\n            )\n        {\n            if (box.IsInvalid) return false;\n            bool intersecting = false;\n            foreach (__plane3t__ p in hull.PlaneArray)\n            {\n                box.GetMinMaxInDirection(p.Normal, out __v3t__ min, out __v3t__ max);\n                if (p.Height(min) > 0) return false; // outside\n                if (p.Height(max) >= 0) intersecting = true;\n            }\n            if (intersecting) return true; // intersecting\n            return true; // inside\n        }\n\n        /// Test hull against intersection of the supplied bounding box.\n        /// Note that this is a conservative test, since in some cases\n        /// around the edges of the hull it may return true although the\n        /// hull does not intersect the box.\n        public static bool Intersects(\n                this Fast__hull3t__ fastHull,\n                __box3t__ box)\n        {\n            var planes = fastHull.Hull.PlaneArray;\n            int count = planes.Length;\n            bool intersecting = false;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCornerIndex = fastHull.MinCornerIndexArray[pi];\n                if (planes[pi].Height(box.Corner(minCornerIndex)) > 0)\n                    return false;\n                if (planes[pi].Height(box.Corner(minCornerIndex ^ 7)) >= 0)\n                    intersecting = true;\n            }\n            if (intersecting) return true;\n            return true;\n        }\n\n        #endregion\n\n        #region __hull3t__ intersects __sphere3t__\n\n        /// <summary>\n        /// Returns true if the hull and the sphere intersect.\n        /// </summary>\n        public static bool Intersects(\n            this __hull3t__ hull, __sphere3t__ sphere\n            )\n        {\n            if (sphere.IsInvalid) return false;\n            bool intersecting = false;\n            foreach (__plane3t__ p in hull.PlaneArray)\n            {\n                __rtype__ height = p.Height(sphere.Center);\n                if (height > sphere.Radius) return false; // outside\n                if (height.Abs() < sphere.Radius) intersecting = true;\n            }\n            if (intersecting) return true; // intersecting\n            return true; // inside\n        }\n\n        #endregion\n\n\n        #region __plane3t__ intersects __box3t__\n\n        /// <summary>\n        /// Returns true if the box and the plane intersect or touch with a\n        /// supplied epsilon tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __plane3t__ plane, __rtype__ eps, __box3t__ box)\n            => box.Intersects(plane, eps);\n\n        #endregion\n\n        //# }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Relations/LinearCombination_auto.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    public static class LinearCombination\n    {\n        // AUTO GENERATED CODE - DO NOT CHANGE!\n\n\n        #region V3f - V3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsLinearCombinationOf(this V3f x, V3f u, V3f v)\n        {\n            V3f n = u.Cross(v);\n            return n.IsOrthogonalTo(x);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsLinearCombinationOf(this V3f x, V3f u)\n            => x.IsParallelTo(u);\n\n        public static bool IsLinearCombinationOf(this V3f x, V3f u, V3f v, out float t0, out float t1)\n        {\n            //x == t2*u + t1*v\n            V3f n = u.Cross(v);\n\n            float[,] mat = new float[3, 3]\n            {\n                {u.X,v.X,n.X},\n                {u.Y,v.Y,n.Y},\n                {u.Z,v.Z,n.Z}\n            };\n\n            float[] result = new float[3] { x.X, x.Y, x.Z };\n\n            int[] perm = mat.LuFactorize();\n            V3f t = new V3f(mat.LuSolve(perm, result));\n\n            if (Fun.IsTiny(t.Z))\n            {\n                t0 = t.X;\n                t1 = t.Y;\n\n                return true;\n            }\n            else\n            {\n                t0 = float.NaN;\n                t1 = float.NaN;\n\n                return false;\n            }\n\n            //x == \n        }\n\n        #endregion\n\n\n        #region V3d - V3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsLinearCombinationOf(this V3d x, V3d u, V3d v)\n        {\n            V3d n = u.Cross(v);\n            return n.IsOrthogonalTo(x);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsLinearCombinationOf(this V3d x, V3d u)\n            => x.IsParallelTo(u);\n\n        public static bool IsLinearCombinationOf(this V3d x, V3d u, V3d v, out double t0, out double t1)\n        {\n            //x == t2*u + t1*v\n            V3d n = u.Cross(v);\n\n            double[,] mat = new double[3, 3]\n            {\n                {u.X,v.X,n.X},\n                {u.Y,v.Y,n.Y},\n                {u.Z,v.Z,n.Z}\n            };\n\n            double[] result = new double[3] { x.X, x.Y, x.Z };\n\n            int[] perm = mat.LuFactorize();\n            V3d t = new V3d(mat.LuSolve(perm, result));\n\n            if (Fun.IsTiny(t.Z))\n            {\n                t0 = t.X;\n                t1 = t.Y;\n\n                return true;\n            }\n            else\n            {\n                t0 = double.NaN;\n                t1 = double.NaN;\n\n                return false;\n            }\n\n            //x == \n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Relations/LinearCombination_template.cs",
    "content": "﻿using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    public static class LinearCombination\n    {\n        // AUTO GENERATED CODE - DO NOT CHANGE!\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n\n        #region __v3t__ - __v3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsLinearCombinationOf(this __v3t__ x, __v3t__ u, __v3t__ v)\n        {\n            __v3t__ n = u.Cross(v);\n            return n.IsOrthogonalTo(x);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsLinearCombinationOf(this __v3t__ x, __v3t__ u)\n            => x.IsParallelTo(u);\n\n        public static bool IsLinearCombinationOf(this __v3t__ x, __v3t__ u, __v3t__ v, out __ftype__ t0, out __ftype__ t1)\n        {\n            //x == t2*u + t1*v\n            __v3t__ n = u.Cross(v);\n\n            __ftype__[,] mat = new __ftype__[3, 3]\n            {\n                {u.X,v.X,n.X},\n                {u.Y,v.Y,n.Y},\n                {u.Z,v.Z,n.Z}\n            };\n\n            __ftype__[] result = new __ftype__[3] { x.X, x.Y, x.Z };\n\n            int[] perm = mat.LuFactorize();\n            __v3t__ t = new __v3t__(mat.LuSolve(perm, result));\n\n            if (Fun.IsTiny(t.Z))\n            {\n                t0 = t.X;\n                t1 = t.Y;\n\n                return true;\n            }\n            else\n            {\n                t0 = __ftype__.NaN;\n                t1 = __ftype__.NaN;\n\n                return false;\n            }\n\n            //x == \n        }\n\n        #endregion\n\n        //# }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Relations/Orthogonality_auto.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Provides various methods determining normalism\n    /// </summary>\n    public static class Orthogonality\n    {\n        // 2-Dimensional\n\n        #region V2f - V2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this V2f u, V2f v)\n            => Fun.IsTiny(u.Dot(v));\n\n        #endregion\n\n        #region Ray2f - V2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray2f ray, V2f v)\n            => ray.Direction.IsOrthogonalTo(v);\n\n        #endregion\n\n        #region Ray2f - Ray2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray2f r0, Ray2f r1)\n            => r0.Direction.IsOrthogonalTo(r1.Direction);\n\n        #endregion\n\n        // 3-Dimensional\n\n        #region V3f - V3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this V3f u, V3f v)\n            => Fun.IsTiny(u.Dot(v));\n\n        #endregion\n\n        #region Ray3f - V3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray3f ray, V3f vec)\n            => ray.Direction.IsOrthogonalTo(vec);\n\n        #endregion\n\n        #region Ray3f - Ray3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray3f r0, Ray3f r1)\n            => r0.Direction.IsOrthogonalTo(r1.Direction);\n\n        #endregion\n\n        #region Plane3f - Plane3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Plane3f p0, Plane3f p1)\n            => p0.Normal.IsOrthogonalTo(p1.Normal);\n\n        #endregion\n\n        #region Ray3f - Plane3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray3f ray, Plane3f plane)\n            => ray.Direction.IsParallelTo(plane.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNormalTo(this Plane3f plane, Ray3f ray)\n            => ray.Direction.IsParallelTo(plane.Normal);\n\n        #endregion\n\n        // 2-Dimensional\n\n        #region V2d - V2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this V2d u, V2d v)\n            => Fun.IsTiny(u.Dot(v));\n\n        #endregion\n\n        #region Ray2d - V2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray2d ray, V2d v)\n            => ray.Direction.IsOrthogonalTo(v);\n\n        #endregion\n\n        #region Ray2d - Ray2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray2d r0, Ray2d r1)\n            => r0.Direction.IsOrthogonalTo(r1.Direction);\n\n        #endregion\n\n        // 3-Dimensional\n\n        #region V3d - V3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this V3d u, V3d v)\n            => Fun.IsTiny(u.Dot(v));\n\n        #endregion\n\n        #region Ray3d - V3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray3d ray, V3d vec)\n            => ray.Direction.IsOrthogonalTo(vec);\n\n        #endregion\n\n        #region Ray3d - Ray3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray3d r0, Ray3d r1)\n            => r0.Direction.IsOrthogonalTo(r1.Direction);\n\n        #endregion\n\n        #region Plane3d - Plane3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Plane3d p0, Plane3d p1)\n            => p0.Normal.IsOrthogonalTo(p1.Normal);\n\n        #endregion\n\n        #region Ray3d - Plane3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this Ray3d ray, Plane3d plane)\n            => ray.Direction.IsParallelTo(plane.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNormalTo(this Plane3d plane, Ray3d ray)\n            => ray.Direction.IsParallelTo(plane.Normal);\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Relations/Orthogonality_template.cs",
    "content": "﻿using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Provides various methods determining normalism\n    /// </summary>\n    public static class Orthogonality\n    {\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var plane3t = \"Plane3\" + tc;\n        //#   var ray2t = \"Ray2\" + tc;\n        //#   var ray3t = \"Ray3\" + tc;\n        // 2-Dimensional\n\n        #region __v2t__ - __v2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this __v2t__ u, __v2t__ v)\n            => Fun.IsTiny(u.Dot(v));\n\n        #endregion\n\n        #region __ray2t__ - __v2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this __ray2t__ ray, __v2t__ v)\n            => ray.Direction.IsOrthogonalTo(v);\n\n        #endregion\n\n        #region __ray2t__ - __ray2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this __ray2t__ r0, __ray2t__ r1)\n            => r0.Direction.IsOrthogonalTo(r1.Direction);\n\n        #endregion\n\n        // 3-Dimensional\n\n        #region __v3t__ - __v3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this __v3t__ u, __v3t__ v)\n            => Fun.IsTiny(u.Dot(v));\n\n        #endregion\n\n        #region __ray3t__ - __v3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this __ray3t__ ray, __v3t__ vec)\n            => ray.Direction.IsOrthogonalTo(vec);\n\n        #endregion\n\n        #region __ray3t__ - __ray3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this __ray3t__ r0, __ray3t__ r1)\n            => r0.Direction.IsOrthogonalTo(r1.Direction);\n\n        #endregion\n\n        #region __plane3t__ - __plane3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this __plane3t__ p0, __plane3t__ p1)\n            => p0.Normal.IsOrthogonalTo(p1.Normal);\n\n        #endregion\n\n        #region __ray3t__ - __plane3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonalTo(this __ray3t__ ray, __plane3t__ plane)\n            => ray.Direction.IsParallelTo(plane.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNormalTo(this __plane3t__ plane, __ray3t__ ray)\n            => ray.Direction.IsParallelTo(plane.Normal);\n\n        #endregion\n\n        //# }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Relations/Parallelism_auto.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Provides various methods determining parallelism\n    /// </summary>\n    public static class Parallelism\n    {\n        // 2-Dimensional\n\n        #region V2f - V2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this V2f u, V2f v)\n            => Fun.IsTiny(u.X * v.Y - u.Y * v.X);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this V2f u, V2f v, float epsilon = 1e-4f)\n        {\n            var un = u.Normalized;\n            var vn = v.Normalized;\n            return (un - vn).Length < epsilon || (un + vn).Length < epsilon;\n        }\n\n        #endregion\n\n        #region Ray2f - V2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray2f ray, V2f v)\n            => ray.Direction.IsParallelTo(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray2f ray, V2f v, float epsilon = 1e-4f)\n            => ray.Direction.IsParallelTo(v, epsilon);\n\n        #endregion\n\n        #region Ray2f - Ray2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray2f r0, Ray2f r1)\n            => r0.Direction.IsParallelTo(r1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray2f r0, Ray2f r1, float epsilon = 1e-4f)\n            => r0.Direction.IsParallelTo(r1.Direction, epsilon);\n\n        #endregion\n\n        #region Line2f - Line2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Line2f l0, Line2f l1)\n            => l0.Direction.IsParallelTo(l1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Line2f l0, Line2f l1, float epsilon = 1e-4f)\n            => l0.Direction.IsParallelTo(l1.Direction, epsilon);\n\n        #endregion\n\n        // 3-Dimensional\n\n        #region V3f - V3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this V3f u, V3f v)\n            => Fun.IsTiny(u.Cross(v).Norm1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this V3f u, V3f v, float epsilon = 1e-4f)\n        {\n            var un = u.Normalized;\n            var vn = v.Normalized;\n\n            return (un - vn).Length < epsilon || (un + vn).Length < epsilon;\n        }\n\n        #endregion\n\n        #region Ray3f - V3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3f ray, V3f vec)\n            => ray.Direction.IsParallelTo(vec);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3f ray, V3f vec, float epsilon = 1e-4f)\n            => ray.Direction.IsParallelTo(vec, epsilon);\n\n        #endregion\n\n        #region Ray3f - Ray3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3f r0, Ray3f r1)\n            => r0.Direction.IsParallelTo(r1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3f r0, Ray3f r1, float epsilon = 1e-4f)\n            => r0.Direction.IsParallelTo(r1.Direction, epsilon);\n\n        #endregion\n\n        #region Plane3f - Plane3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Plane3f p0, Plane3f p1)\n            => p0.Normal.IsParallelTo(p1.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Plane3f p0, Plane3f p1, float epsilon = 1e-4f)\n            => p0.Normal.IsParallelTo(p1.Normal, epsilon);\n\n        #endregion\n\n        #region Ray3f - Plane3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3f ray, Plane3f plane)\n            => ray.Direction.IsOrthogonalTo(plane.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Plane3f plane, Ray3f ray)\n            => ray.Direction.IsOrthogonalTo(plane.Normal);\n\n        #endregion\n\n        #region Line3f - Line3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Line3f l0, Line3f l1)\n            => l0.Direction.IsParallelTo(l1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Line3f l0, Line3f l1, float epsilon = 1e-4f)\n            => l0.Direction.IsParallelTo(l1.Direction, epsilon);\n\n        #endregion\n\n        // 2-Dimensional\n\n        #region V2d - V2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this V2d u, V2d v)\n            => Fun.IsTiny(u.X * v.Y - u.Y * v.X);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this V2d u, V2d v, double epsilon = 1e-6)\n        {\n            var un = u.Normalized;\n            var vn = v.Normalized;\n            return (un - vn).Length < epsilon || (un + vn).Length < epsilon;\n        }\n\n        #endregion\n\n        #region Ray2d - V2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray2d ray, V2d v)\n            => ray.Direction.IsParallelTo(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray2d ray, V2d v, double epsilon = 1e-6)\n            => ray.Direction.IsParallelTo(v, epsilon);\n\n        #endregion\n\n        #region Ray2d - Ray2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray2d r0, Ray2d r1)\n            => r0.Direction.IsParallelTo(r1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray2d r0, Ray2d r1, double epsilon = 1e-6)\n            => r0.Direction.IsParallelTo(r1.Direction, epsilon);\n\n        #endregion\n\n        #region Line2d - Line2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Line2d l0, Line2d l1)\n            => l0.Direction.IsParallelTo(l1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Line2d l0, Line2d l1, double epsilon = 1e-6)\n            => l0.Direction.IsParallelTo(l1.Direction, epsilon);\n\n        #endregion\n\n        // 3-Dimensional\n\n        #region V3d - V3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this V3d u, V3d v)\n            => Fun.IsTiny(u.Cross(v).Norm1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this V3d u, V3d v, double epsilon = 1e-6)\n        {\n            var un = u.Normalized;\n            var vn = v.Normalized;\n\n            return (un - vn).Length < epsilon || (un + vn).Length < epsilon;\n        }\n\n        #endregion\n\n        #region Ray3d - V3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3d ray, V3d vec)\n            => ray.Direction.IsParallelTo(vec);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3d ray, V3d vec, double epsilon = 1e-6)\n            => ray.Direction.IsParallelTo(vec, epsilon);\n\n        #endregion\n\n        #region Ray3d - Ray3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3d r0, Ray3d r1)\n            => r0.Direction.IsParallelTo(r1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3d r0, Ray3d r1, double epsilon = 1e-6)\n            => r0.Direction.IsParallelTo(r1.Direction, epsilon);\n\n        #endregion\n\n        #region Plane3d - Plane3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Plane3d p0, Plane3d p1)\n            => p0.Normal.IsParallelTo(p1.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Plane3d p0, Plane3d p1, double epsilon = 1e-6)\n            => p0.Normal.IsParallelTo(p1.Normal, epsilon);\n\n        #endregion\n\n        #region Ray3d - Plane3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Ray3d ray, Plane3d plane)\n            => ray.Direction.IsOrthogonalTo(plane.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Plane3d plane, Ray3d ray)\n            => ray.Direction.IsOrthogonalTo(plane.Normal);\n\n        #endregion\n\n        #region Line3d - Line3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Line3d l0, Line3d l1)\n            => l0.Direction.IsParallelTo(l1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this Line3d l0, Line3d l1, double epsilon = 1e-6)\n            => l0.Direction.IsParallelTo(l1.Direction, epsilon);\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Relations/Parallelism_template.cs",
    "content": "﻿using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Provides various methods determining parallelism\n    /// </summary>\n    public static class Parallelism\n    {\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var plane3t = \"Plane3\" + tc;\n        //#   var ray2t = \"Ray2\" + tc;\n        //#   var ray3t = \"Ray3\" + tc;\n        //#   var line2t = \"Line2\" + tc;\n        //#   var line3t = \"Line3\" + tc;\n        //#   var eps = isDouble ? \"1e-6\" : \"1e-4f\";\n        // 2-Dimensional\n\n        #region __v2t__ - __v2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __v2t__ u, __v2t__ v)\n            => Fun.IsTiny(u.X * v.Y - u.Y * v.X);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __v2t__ u, __v2t__ v, __rtype__ epsilon = __eps__)\n        {\n            var un = u.Normalized;\n            var vn = v.Normalized;\n            return (un - vn).Length < epsilon || (un + vn).Length < epsilon;\n        }\n\n        #endregion\n\n        #region __ray2t__ - __v2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray2t__ ray, __v2t__ v)\n            => ray.Direction.IsParallelTo(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray2t__ ray, __v2t__ v, __rtype__ epsilon = __eps__)\n            => ray.Direction.IsParallelTo(v, epsilon);\n\n        #endregion\n\n        #region __ray2t__ - __ray2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray2t__ r0, __ray2t__ r1)\n            => r0.Direction.IsParallelTo(r1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray2t__ r0, __ray2t__ r1, __rtype__ epsilon = __eps__)\n            => r0.Direction.IsParallelTo(r1.Direction, epsilon);\n\n        #endregion\n\n        #region __line2t__ - __line2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __line2t__ l0, __line2t__ l1)\n            => l0.Direction.IsParallelTo(l1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __line2t__ l0, __line2t__ l1, __rtype__ epsilon = __eps__)\n            => l0.Direction.IsParallelTo(l1.Direction, epsilon);\n\n        #endregion\n\n        // 3-Dimensional\n\n        #region __v3t__ - __v3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __v3t__ u, __v3t__ v)\n            => Fun.IsTiny(u.Cross(v).Norm1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __v3t__ u, __v3t__ v, __rtype__ epsilon = __eps__)\n        {\n            var un = u.Normalized;\n            var vn = v.Normalized;\n\n            return (un - vn).Length < epsilon || (un + vn).Length < epsilon;\n        }\n\n        #endregion\n\n        #region __ray3t__ - __v3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray3t__ ray, __v3t__ vec)\n            => ray.Direction.IsParallelTo(vec);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray3t__ ray, __v3t__ vec, __rtype__ epsilon = __eps__)\n            => ray.Direction.IsParallelTo(vec, epsilon);\n\n        #endregion\n\n        #region __ray3t__ - __ray3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray3t__ r0, __ray3t__ r1)\n            => r0.Direction.IsParallelTo(r1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray3t__ r0, __ray3t__ r1, __rtype__ epsilon = __eps__)\n            => r0.Direction.IsParallelTo(r1.Direction, epsilon);\n\n        #endregion\n\n        #region __plane3t__ - __plane3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __plane3t__ p0, __plane3t__ p1)\n            => p0.Normal.IsParallelTo(p1.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __plane3t__ p0, __plane3t__ p1, __rtype__ epsilon = __eps__)\n            => p0.Normal.IsParallelTo(p1.Normal, epsilon);\n\n        #endregion\n\n        #region __ray3t__ - __plane3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __ray3t__ ray, __plane3t__ plane)\n            => ray.Direction.IsOrthogonalTo(plane.Normal);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __plane3t__ plane, __ray3t__ ray)\n            => ray.Direction.IsOrthogonalTo(plane.Normal);\n\n        #endregion\n\n        #region __line3t__ - __line3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __line3t__ l0, __line3t__ l1)\n            => l0.Direction.IsParallelTo(l1.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsParallelTo(this __line3t__ l0, __line3t__ l1, __rtype__ epsilon = __eps__)\n            => l0.Direction.IsParallelTo(l1.Direction, epsilon);\n\n        #endregion\n\n        //# }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Relations/SubPrimitives_auto.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class SubPrimitives\n    {\n        #region Triangulation of Convex Polygons\n\n        /// <summary>\n        /// Compute a simple triangulation starting from the first point of\n        /// the polygon. Note that the indices are twice indirect (once over\n        /// pia, once over via). Returns the number of triangles (ie. two\n        /// less than the length of the array pia).\n        /// </summary>\n        public static int ComputeSimpleTriangulation(\n                this int[] pia, int[] via, int tvi, int[] tia, int[] pvibm, int[] tibm)\n        {\n            int fi = pia[0], fvi = via[fi];\n            int i1 = pia[1], vi1 = via[i1];\n            int count = pia.Length;\n            for (int ii = 2; ii < count; ii++)\n            {\n                int vi0 = vi1, i0 = i1;\n                vi1 = via[i1 = pia[ii]];\n                tia[tvi] = fvi;\n                tia[tvi + 1] = vi0;\n                tia[tvi + 2] = vi1;\n                if (tibm != null)\n                {\n                    tibm[tvi] = pvibm[fi];\n                    tibm[tvi + 1] = pvibm[i0];\n                    tibm[tvi + 2] = pvibm[i1];\n                }\n                tvi += 3;\n            }\n            return count - 2;\n        }\n\n        #endregion\n\n        #region Non-Concave Sub-Polygons of a Polygon2f\n\n        private static int[] ComputeNonConcaveSubPolygon(\n                this Polygon2f poly, ref int[] indices, float absoluteEpsilon)\n        {\n            int count = indices.Length;\n\n            if (count <= 3)\n            {\n                var result = indices;\n                indices = Array.Empty<int>();\n                return result;\n            }\n\n            Func<int, int> addFun = i => (i + 1) % count;\n            Func<int, int> subFun = i => (i + count - 1) % count;\n\n            for (int vi = 0; vi < count; vi++) // we possibly have to try all vertices\n            {\n                int nowMinIndex = vi, nowMaxIndex = vi;\n                var nowMinPoint = poly[indices[nowMinIndex]];\n                var nowMaxPoint = poly[indices[nowMaxIndex]];\n                var oldMinPoint = poly[indices[addFun(nowMinIndex)]];\n                var oldMaxPoint = poly[indices[subFun(nowMinIndex)]];\n                var subCount = 1;\n\n                bool add = true;\n\n                for (int pass = 0, goodPass = 0; pass - goodPass < 3; pass++, add = !add)\n                {\n                    // alternate between adding a point at the two ends\n                    var nextFun = add ? addFun : subFun;\n                    int lastIndex = add ? nowMinIndex : nowMaxIndex;\n\n                    int newIndex = add ? addFun(nowMaxIndex) : subFun(nowMinIndex);\n                    if (newIndex == lastIndex)\n                    {\n                        var finalIndices = indices;\n                        indices = Array.Empty<int>();\n                        return finalIndices;\n                    }\n\n                    var newPoint = poly[indices[newIndex]];\n                    var pMax = new Line2f(oldMaxPoint, nowMaxPoint).Plane2f;\n                    var pMin = new Line2f(oldMinPoint, nowMinPoint).Plane2f;\n\n                    var npMax = pMax.Normalized;\n                    var npMin = pMin.Normalized;\n\n                    var hMax = new Line2f(oldMaxPoint, nowMaxPoint).Plane2f.Normalized.Height(newPoint);\n                    var hMin = new Line2f(oldMinPoint, nowMinPoint).Plane2f.Normalized.Height(newPoint);\n\n                    if (hMax >= -absoluteEpsilon && hMin <= absoluteEpsilon)\n                    {\n                        bool good = true;\n                        if (nowMinIndex != nowMaxIndex)\n                        {\n                            var plane0 = new Line2f(nowMinPoint, nowMaxPoint).Plane2f.Normalized;\n                            var plane1 = new Line2f(nowMaxPoint, newPoint).Plane2f.Normalized;\n                            var plane2 = new Line2f(newPoint, nowMinPoint).Plane2f.Normalized;\n\n                            // check if new triangle does not contain any other points of the polygon\n                            for (int i = nextFun(newIndex); i != lastIndex; i = nextFun(i))\n                            {\n                                var point = poly[indices[i]];\n                                if (plane0.Height(point) > -absoluteEpsilon\n                                    && plane1.Height(point) >= absoluteEpsilon\n                                    && plane2.Height(point) >= absoluteEpsilon)\n                                { good = false; break; }\n                            }\n                        }\n                        if (good)\n                        {\n                            if (add)\n                            {\n                                nowMaxIndex = newIndex; oldMaxPoint = nowMaxPoint; nowMaxPoint = newPoint;\n                            }\n                            else\n                            {\n                                nowMinIndex = newIndex; oldMinPoint = nowMinPoint; nowMinPoint = newPoint;\n                            }\n                            goodPass = pass;\n                            ++subCount;\n                        }\n                    }\n                }\n                if (subCount < 3) continue;\n\n                // build new arrays here\n\n                var subIndices = new int[subCount];\n                for (int i = 0, ni = nowMinIndex; i < subCount; i++, ni = addFun(ni))\n                    subIndices[i] = indices[ni];\n                int newCount = 2 + count - subCount;\n                var newIndices = new int[newCount];\n                for (int i = 0, ni = nowMaxIndex; i < newCount; i++, ni = addFun(ni))\n                    newIndices[i] = indices[ni];\n\n                indices = newIndices;\n                return subIndices;\n            }\n            return null;\n        }\n\n        public static void AddNonConcaveSubPolygons(\n                this List<int[]> polygonList, Polygon2f poly,\n                float absoluteEpsilon)\n        {\n            var indices = new int[poly.PointCount].SetByIndex(i => i);\n            while (indices.Length > 0)\n            {\n                var subPoly = poly.ComputeNonConcaveSubPolygon(\n                                    ref indices, absoluteEpsilon);\n\n                if (subPoly == null)\n                {\n                    Console.WriteLine(\"encountered degenerated polygon that cannot be easily triangulated\");\n                    break;\n                }\n\n                if (subPoly.Length < 3)\n                {\n                    Console.WriteLine(\"encountered invalid subpolygon\");\n                    continue;\n                }\n                polygonList.Add(subPoly);\n            }\n        }\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this Polygon2f polygon, float absoluteEpsilon)\n        {\n            var polygonList = new List<int[]>();\n            polygonList.AddNonConcaveSubPolygons(polygon, absoluteEpsilon);\n            return polygonList;\n        }\n\n        #endregion\n\n        #region Non-Concave Sub-Polygons of Polygons in 3d\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this Polygon3f polygon, float absoluteEpsilon)\n        {\n            V3f normal = polygon.ComputeDoubleAreaNormal();\n            float len2 = normal.LengthSquared;\n\n            if (len2 < absoluteEpsilon * absoluteEpsilon)\n                return new int[polygon.PointCount].SetByIndex(i => i).IntoList();\n\n            M44f.NormalFrame(V3f.Zero, normal * (1 / Fun.Sqrt(len2)), out M44f local2global, out M44f global2local);\n            var polygon2d = polygon.ToPolygon2f(p => global2local.TransformPos(p).XY);\n            return polygon2d.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n        }\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this V3f[] vertexArray, int polyCount,\n                V3f[] normalArray, int[] firstIndices, int[] vertexIndices,\n                List<int> faceBackMap,\n                float absoluteEpsilon)\n        {\n            var polyList = new List<int[]>();\n            var eps2 = absoluteEpsilon * absoluteEpsilon;\n\n            for (int fvi = 0, fi = 0; fi < polyCount; fi++)\n            {\n                int fve = firstIndices[fi+1], fvc = fve - fvi;\n                var n = normalArray[fi];\n                var l2 = n.LengthSquared;\n                if (l2 < eps2)\n                {\n                    polyList.Add(new int[fvc].SetByIndex(i => vertexIndices[fvi + i]));\n                    if (faceBackMap != null)\n                        faceBackMap.Add(fi);\n                    fvi = fve;\n                    continue;\n                }\n                M44f.NormalFrame(V3f.Zero, n, out M44f local2global, out M44f global2local);\n                var polygon = new Polygon2f(fvc,\n                        i => global2local.TransformPos(vertexArray[vertexIndices[fvi + i]]).XY);\n                var subPolyList = polygon.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n                foreach (var poly in subPolyList)\n                    polyList.Add(poly.Map(i => fvi + i));\n                if (faceBackMap != null)\n                    for (int i = 0; i < subPolyList.Count; i++)\n                        faceBackMap.Add(fi);\n                fvi = fve;\n            }\n\n            return polyList;\n        }\n\n        #endregion\n\n        #region Triangulation of Non-Concave Polygons in 3d\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns>Triangle count.</returns>\n        public static int ComputeTriangulationOfNonConcavePolygon(\n                this int[] ia, int[] via, V3f[] va, V3f[] edgeArray, bool[] straightArray,\n                int tvi, int[] tia, int[] pvibm, int[] tibm)\n        {\n            int count = ia.Length;\n\n            if (count < 3) throw new ArgumentOutOfRangeException();\n\n            if (count == 3)\n            {\n                tia[tvi] = via[ia[0]];\n                tia[tvi + 1] = via[ia[1]];\n                tia[tvi + 2] = via[ia[2]];\n                if (tibm != null)\n                {\n                    tibm[tvi] = pvibm[ia[0]];\n                    tibm[tvi + 1] = pvibm[ia[1]];\n                    tibm[tvi + 2] = pvibm[ia[2]];\n                }\n                return 1;\n            }\n\n            int ii = 0;\n\n            // search for the first non-straight corner\n            while (ii < ia.Length && straightArray[ia[ii]]) ii++;\n\n            int bii = ii; ii = (ii + 1) % count;\n\n            // search for first straight corner afterwards\n            while (ii != bii && !straightArray[ia[ii]]) ii = (ii + 1) % count;\n\n            if (ii == bii) // if there is no straight corner\n                return ia.ComputeSimpleTriangulation(via, tvi, tia, pvibm, tibm);\n            bii = ii; // first\n            int eii = ii;\n            int straightCount = 0;\n            while (straightArray[ia[ii]])\n            {\n                eii = ii; ii = (ii + 1) % count;\n                ++straightCount;\n            }\n\n            if (count - straightCount < 3) // numeric problem, cop out\n                return ia.ComputeSimpleTriangulation(via, tvi, tia, pvibm, tibm);\n\n            var hii = ii; float height = 0;\n            var li = ia[eii];\n            var edge = edgeArray[li];\n            var vertex = va[via[li]];\n\n            int rightCount = 2;\n            int rc = 2;\n            ii = (ii + 1) % count;\n            while (ii != bii)\n            {\n                int i = ia[ii];\n                var h = edge.Cross(va[via[i]] - vertex).LengthSquared;\n                ++rc;\n                if (h > height)\n                {\n                    height = h;\n                    hii = ii;\n                    rightCount = rc;\n                }\n                ii = (ii + 1) % count;\n            }\n\n            straightArray[ia[bii]] = false;\n            straightArray[ia[eii]] = false;\n            straightArray[ia[hii]] = false;\n\n            int leftCount = count - straightCount - rightCount + 3;\n\n            var lia = new int[leftCount];\n            ii = hii;\n            for (int lii = 0; lii < leftCount; lii++, ii = (ii + 1) % count)\n                lia[lii] = ia[ii];\n\n            if (leftCount > 2)\n                lia.ComputeTriangulationOfNonConcavePolygon(via, va, edgeArray, straightArray,\n                        tvi, tia, pvibm, tibm);\n\n            tvi += 3 * (leftCount - 2);\n\n            if (straightCount > 1)\n            {\n                int hi = ia[hii], hvi = via[hi];\n                int i1 = ia[bii], vi1 = via[i1];\n                ii = bii;\n                for (int sii = 0; sii < straightCount - 1; sii++)\n                {\n                    ii = (ii + 1) % count;\n                    int vi0 = vi1, i0 = i1;\n                    vi1 = via[i1 = ia[ii]];\n                    tia[tvi] = hvi;\n                    tia[tvi + 1] = vi0;\n                    tia[tvi + 2] = vi1;\n\n                    if (tibm != null)\n                    {\n                        tibm[tvi] = pvibm[hi];\n                        tibm[tvi + 1] = pvibm[i0];\n                        tibm[tvi + 2] = pvibm[i1];\n                    }\n                    tvi += 3;\n                }\n            }\n\n            var ria = new int[rightCount];\n            ii = eii;\n            for (int rii = 0; rii < rightCount; rii++, ii = (ii + 1) % count)\n                ria[rii] = ia[ii];\n\n            if (rightCount > 2)\n                ria.ComputeTriangulationOfNonConcavePolygon(via, va, edgeArray, straightArray,\n                        tvi, tia, pvibm, tibm);\n\n            return count - 2;\n        }\n\n        public static void ComputeStraightVertices(\n                this int[] via, V3f[] va, float absoluteEpsilon,\n                V3f[] normalizedEdgeArray, bool[] straightArray)\n        {\n            int count = via.Length;\n            if (straightArray == null) throw new ArgumentNullException();\n            if (count <= 2) throw new ArgumentException();\n            if (straightArray.Length != count) throw new ArgumentException();\n            if (normalizedEdgeArray != null && normalizedEdgeArray.Length != count) throw new ArgumentException();\n\n            float eps2 = absoluteEpsilon * absoluteEpsilon;\n\n            V3f[] ea = new V3f[count];\n            int oi = count - 1;\n            var oldVertex = va[via[oi]];\n\n            for (int i = 0; i < count; i++)\n            {\n                var vertex = va[via[i]];\n                ea[oi] = vertex - oldVertex;\n                oi = i; oldVertex = vertex;\n            }\n\n            oi = count - 1;\n            var oldEdge = ea[oi].Normalized;\n\n            for (int i = 0; i < count; i++)\n            {\n                var edge = ea[i].Normalized;\n                if (normalizedEdgeArray != null)\n                    normalizedEdgeArray[oi] = oldEdge;\n                straightArray[i] = (edge - oldEdge).LengthSquared < eps2;\n                oi = i; oldEdge = edge;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns>Triangle count.</returns>\n        public static int ComputeTriangulationOfNonConcavePolygon(\n                this V3f[] va, int[] via, float absoluteEpsilon,\n                int ftvi, int[] tia, int[] pvibm = null, int[] tibm = null)\n        {\n            int count = via.Length;\n            var straightArray = new bool[count];\n            var normalizedEdgeArray = new V3f[count];\n\n            via.ComputeStraightVertices(va, absoluteEpsilon,\n                    normalizedEdgeArray, straightArray);\n\n            var ia = new int[count].SetByIndex(i => i);\n\n            return ia.ComputeTriangulationOfNonConcavePolygon(\n                    via, va, normalizedEdgeArray, straightArray,\n                    ftvi, tia, pvibm, tibm);\n        }\n\n        public static int[] ComputeTriangulationOfNonConcavePolygons(\n                this V3f[] vertexArray, List<int[]> nonConcavePolyList,\n                float absoluteEpsilon)\n        {\n            int tc = nonConcavePolyList.Sum(p => p.Length - 2);\n            var tia = new int[tc];\n            tc = 0;\n            foreach (var pia in nonConcavePolyList)\n            {\n                tc += 3 * vertexArray.ComputeTriangulationOfNonConcavePolygon(\n                                        pia, absoluteEpsilon, tc, tia);\n            }\n            return tia;\n        }\n\n        #endregion\n\n        #region Triangulation of Concave Polygons\n\n        /// <summary>\n        /// Compute the triangulation of the supplied concave polygon and put\n        /// the triangle vertex indices into the supplied array starting at\n        /// the supplied triangle vertex index.\n        /// </summary>\n        /// <returns>the number of triangles in the triangulation</returns>\n        private static int ComputeTriangulationOfConcavePolygon(\n                this Polygon3f polygon, float absoluteEpsilon,\n                int triangleVertexIndex, int[] triangleIndexArray)\n        {\n            var polyList = polygon.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n\n            foreach (var pia in polyList)\n            {\n                int tc = polygon.GetPointArray().ComputeTriangulationOfNonConcavePolygon(\n                                            pia, absoluteEpsilon, triangleVertexIndex,\n                    triangleIndexArray);\n                triangleVertexIndex += 3 * tc;\n            }\n            return polygon.PointCount - 2;\n        }\n\n        /// <summary>\n        /// Compute the triangulation of the supplied concave polygon and\n        /// return the resulting triangle index array.\n        /// </summary>\n        public static int[] ComputeTriangulationOfConcavePolygon(\n                this Polygon3f polygon, float absoluteEpsilon)\n        {\n            int[] triangleIndexArray = new int[3 * (polygon.PointCount - 2)];\n            polygon.ComputeTriangulationOfConcavePolygon(\n                        absoluteEpsilon, 0, triangleIndexArray);\n            return triangleIndexArray;\n        }\n\n        /// <summary>\n        /// Compute the triangulation of the concave polygons supplied in\n        /// the arrays with PolyMesh layout, and return the resulting\n        /// triangle index array.\n        /// </summary>\n        public static int[] ComputeTriangulationOfConcavePolygons(\n                this V3f[] vertexArray, int polyCount,\n                V3f[] normalArray, int[] firstIndices, int[] vertexIndices,\n                float absoluteEpsilon)\n        {\n            var polyList = vertexArray.ComputeNonConcaveSubPolygons(\n                                polyCount, normalArray, firstIndices,\n                                vertexIndices, null, absoluteEpsilon);\n            return vertexArray.ComputeTriangulationOfNonConcavePolygons(\n                                polyList, absoluteEpsilon);\n        }\n\n        #endregion\n\n        #region Non-Concave Sub-Polygons of a Polygon2d\n\n        private static int[] ComputeNonConcaveSubPolygon(\n                this Polygon2d poly, ref int[] indices, double absoluteEpsilon)\n        {\n            int count = indices.Length;\n\n            if (count <= 3)\n            {\n                var result = indices;\n                indices = Array.Empty<int>();\n                return result;\n            }\n\n            Func<int, int> addFun = i => (i + 1) % count;\n            Func<int, int> subFun = i => (i + count - 1) % count;\n\n            for (int vi = 0; vi < count; vi++) // we possibly have to try all vertices\n            {\n                int nowMinIndex = vi, nowMaxIndex = vi;\n                var nowMinPoint = poly[indices[nowMinIndex]];\n                var nowMaxPoint = poly[indices[nowMaxIndex]];\n                var oldMinPoint = poly[indices[addFun(nowMinIndex)]];\n                var oldMaxPoint = poly[indices[subFun(nowMinIndex)]];\n                var subCount = 1;\n\n                bool add = true;\n\n                for (int pass = 0, goodPass = 0; pass - goodPass < 3; pass++, add = !add)\n                {\n                    // alternate between adding a point at the two ends\n                    var nextFun = add ? addFun : subFun;\n                    int lastIndex = add ? nowMinIndex : nowMaxIndex;\n\n                    int newIndex = add ? addFun(nowMaxIndex) : subFun(nowMinIndex);\n                    if (newIndex == lastIndex)\n                    {\n                        var finalIndices = indices;\n                        indices = Array.Empty<int>();\n                        return finalIndices;\n                    }\n\n                    var newPoint = poly[indices[newIndex]];\n                    var pMax = new Line2d(oldMaxPoint, nowMaxPoint).Plane2d;\n                    var pMin = new Line2d(oldMinPoint, nowMinPoint).Plane2d;\n\n                    var npMax = pMax.Normalized;\n                    var npMin = pMin.Normalized;\n\n                    var hMax = new Line2d(oldMaxPoint, nowMaxPoint).Plane2d.Normalized.Height(newPoint);\n                    var hMin = new Line2d(oldMinPoint, nowMinPoint).Plane2d.Normalized.Height(newPoint);\n\n                    if (hMax >= -absoluteEpsilon && hMin <= absoluteEpsilon)\n                    {\n                        bool good = true;\n                        if (nowMinIndex != nowMaxIndex)\n                        {\n                            var plane0 = new Line2d(nowMinPoint, nowMaxPoint).Plane2d.Normalized;\n                            var plane1 = new Line2d(nowMaxPoint, newPoint).Plane2d.Normalized;\n                            var plane2 = new Line2d(newPoint, nowMinPoint).Plane2d.Normalized;\n\n                            // check if new triangle does not contain any other points of the polygon\n                            for (int i = nextFun(newIndex); i != lastIndex; i = nextFun(i))\n                            {\n                                var point = poly[indices[i]];\n                                if (plane0.Height(point) > -absoluteEpsilon\n                                    && plane1.Height(point) >= absoluteEpsilon\n                                    && plane2.Height(point) >= absoluteEpsilon)\n                                { good = false; break; }\n                            }\n                        }\n                        if (good)\n                        {\n                            if (add)\n                            {\n                                nowMaxIndex = newIndex; oldMaxPoint = nowMaxPoint; nowMaxPoint = newPoint;\n                            }\n                            else\n                            {\n                                nowMinIndex = newIndex; oldMinPoint = nowMinPoint; nowMinPoint = newPoint;\n                            }\n                            goodPass = pass;\n                            ++subCount;\n                        }\n                    }\n                }\n                if (subCount < 3) continue;\n\n                // build new arrays here\n\n                var subIndices = new int[subCount];\n                for (int i = 0, ni = nowMinIndex; i < subCount; i++, ni = addFun(ni))\n                    subIndices[i] = indices[ni];\n                int newCount = 2 + count - subCount;\n                var newIndices = new int[newCount];\n                for (int i = 0, ni = nowMaxIndex; i < newCount; i++, ni = addFun(ni))\n                    newIndices[i] = indices[ni];\n\n                indices = newIndices;\n                return subIndices;\n            }\n            return null;\n        }\n\n        public static void AddNonConcaveSubPolygons(\n                this List<int[]> polygonList, Polygon2d poly,\n                double absoluteEpsilon)\n        {\n            var indices = new int[poly.PointCount].SetByIndex(i => i);\n            while (indices.Length > 0)\n            {\n                var subPoly = poly.ComputeNonConcaveSubPolygon(\n                                    ref indices, absoluteEpsilon);\n\n                if (subPoly == null)\n                {\n                    Console.WriteLine(\"encountered degenerated polygon that cannot be easily triangulated\");\n                    break;\n                }\n\n                if (subPoly.Length < 3)\n                {\n                    Console.WriteLine(\"encountered invalid subpolygon\");\n                    continue;\n                }\n                polygonList.Add(subPoly);\n            }\n        }\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this Polygon2d polygon, double absoluteEpsilon)\n        {\n            var polygonList = new List<int[]>();\n            polygonList.AddNonConcaveSubPolygons(polygon, absoluteEpsilon);\n            return polygonList;\n        }\n\n        #endregion\n\n        #region Non-Concave Sub-Polygons of Polygons in 3d\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this Polygon3d polygon, double absoluteEpsilon)\n        {\n            V3d normal = polygon.ComputeDoubleAreaNormal();\n            double len2 = normal.LengthSquared;\n\n            if (len2 < absoluteEpsilon * absoluteEpsilon)\n                return new int[polygon.PointCount].SetByIndex(i => i).IntoList();\n\n            M44d.NormalFrame(V3d.Zero, normal * (1 / Fun.Sqrt(len2)), out M44d local2global, out M44d global2local);\n            var polygon2d = polygon.ToPolygon2d(p => global2local.TransformPos(p).XY);\n            return polygon2d.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n        }\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this V3d[] vertexArray, int polyCount,\n                V3d[] normalArray, int[] firstIndices, int[] vertexIndices,\n                List<int> faceBackMap,\n                double absoluteEpsilon)\n        {\n            var polyList = new List<int[]>();\n            var eps2 = absoluteEpsilon * absoluteEpsilon;\n\n            for (int fvi = 0, fi = 0; fi < polyCount; fi++)\n            {\n                int fve = firstIndices[fi+1], fvc = fve - fvi;\n                var n = normalArray[fi];\n                var l2 = n.LengthSquared;\n                if (l2 < eps2)\n                {\n                    polyList.Add(new int[fvc].SetByIndex(i => vertexIndices[fvi + i]));\n                    if (faceBackMap != null)\n                        faceBackMap.Add(fi);\n                    fvi = fve;\n                    continue;\n                }\n                M44d.NormalFrame(V3d.Zero, n, out M44d local2global, out M44d global2local);\n                var polygon = new Polygon2d(fvc,\n                        i => global2local.TransformPos(vertexArray[vertexIndices[fvi + i]]).XY);\n                var subPolyList = polygon.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n                foreach (var poly in subPolyList)\n                    polyList.Add(poly.Map(i => fvi + i));\n                if (faceBackMap != null)\n                    for (int i = 0; i < subPolyList.Count; i++)\n                        faceBackMap.Add(fi);\n                fvi = fve;\n            }\n\n            return polyList;\n        }\n\n        #endregion\n\n        #region Triangulation of Non-Concave Polygons in 3d\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns>Triangle count.</returns>\n        public static int ComputeTriangulationOfNonConcavePolygon(\n                this int[] ia, int[] via, V3d[] va, V3d[] edgeArray, bool[] straightArray,\n                int tvi, int[] tia, int[] pvibm, int[] tibm)\n        {\n            int count = ia.Length;\n\n            if (count < 3) throw new ArgumentOutOfRangeException();\n\n            if (count == 3)\n            {\n                tia[tvi] = via[ia[0]];\n                tia[tvi + 1] = via[ia[1]];\n                tia[tvi + 2] = via[ia[2]];\n                if (tibm != null)\n                {\n                    tibm[tvi] = pvibm[ia[0]];\n                    tibm[tvi + 1] = pvibm[ia[1]];\n                    tibm[tvi + 2] = pvibm[ia[2]];\n                }\n                return 1;\n            }\n\n            int ii = 0;\n\n            // search for the first non-straight corner\n            while (ii < ia.Length && straightArray[ia[ii]]) ii++;\n\n            int bii = ii; ii = (ii + 1) % count;\n\n            // search for first straight corner afterwards\n            while (ii != bii && !straightArray[ia[ii]]) ii = (ii + 1) % count;\n\n            if (ii == bii) // if there is no straight corner\n                return ia.ComputeSimpleTriangulation(via, tvi, tia, pvibm, tibm);\n            bii = ii; // first\n            int eii = ii;\n            int straightCount = 0;\n            while (straightArray[ia[ii]])\n            {\n                eii = ii; ii = (ii + 1) % count;\n                ++straightCount;\n            }\n\n            if (count - straightCount < 3) // numeric problem, cop out\n                return ia.ComputeSimpleTriangulation(via, tvi, tia, pvibm, tibm);\n\n            var hii = ii; double height = 0;\n            var li = ia[eii];\n            var edge = edgeArray[li];\n            var vertex = va[via[li]];\n\n            int rightCount = 2;\n            int rc = 2;\n            ii = (ii + 1) % count;\n            while (ii != bii)\n            {\n                int i = ia[ii];\n                var h = edge.Cross(va[via[i]] - vertex).LengthSquared;\n                ++rc;\n                if (h > height)\n                {\n                    height = h;\n                    hii = ii;\n                    rightCount = rc;\n                }\n                ii = (ii + 1) % count;\n            }\n\n            straightArray[ia[bii]] = false;\n            straightArray[ia[eii]] = false;\n            straightArray[ia[hii]] = false;\n\n            int leftCount = count - straightCount - rightCount + 3;\n\n            var lia = new int[leftCount];\n            ii = hii;\n            for (int lii = 0; lii < leftCount; lii++, ii = (ii + 1) % count)\n                lia[lii] = ia[ii];\n\n            if (leftCount > 2)\n                lia.ComputeTriangulationOfNonConcavePolygon(via, va, edgeArray, straightArray,\n                        tvi, tia, pvibm, tibm);\n\n            tvi += 3 * (leftCount - 2);\n\n            if (straightCount > 1)\n            {\n                int hi = ia[hii], hvi = via[hi];\n                int i1 = ia[bii], vi1 = via[i1];\n                ii = bii;\n                for (int sii = 0; sii < straightCount - 1; sii++)\n                {\n                    ii = (ii + 1) % count;\n                    int vi0 = vi1, i0 = i1;\n                    vi1 = via[i1 = ia[ii]];\n                    tia[tvi] = hvi;\n                    tia[tvi + 1] = vi0;\n                    tia[tvi + 2] = vi1;\n\n                    if (tibm != null)\n                    {\n                        tibm[tvi] = pvibm[hi];\n                        tibm[tvi + 1] = pvibm[i0];\n                        tibm[tvi + 2] = pvibm[i1];\n                    }\n                    tvi += 3;\n                }\n            }\n\n            var ria = new int[rightCount];\n            ii = eii;\n            for (int rii = 0; rii < rightCount; rii++, ii = (ii + 1) % count)\n                ria[rii] = ia[ii];\n\n            if (rightCount > 2)\n                ria.ComputeTriangulationOfNonConcavePolygon(via, va, edgeArray, straightArray,\n                        tvi, tia, pvibm, tibm);\n\n            return count - 2;\n        }\n\n        public static void ComputeStraightVertices(\n                this int[] via, V3d[] va, double absoluteEpsilon,\n                V3d[] normalizedEdgeArray, bool[] straightArray)\n        {\n            int count = via.Length;\n            if (straightArray == null) throw new ArgumentNullException();\n            if (count <= 2) throw new ArgumentException();\n            if (straightArray.Length != count) throw new ArgumentException();\n            if (normalizedEdgeArray != null && normalizedEdgeArray.Length != count) throw new ArgumentException();\n\n            double eps2 = absoluteEpsilon * absoluteEpsilon;\n\n            V3d[] ea = new V3d[count];\n            int oi = count - 1;\n            var oldVertex = va[via[oi]];\n\n            for (int i = 0; i < count; i++)\n            {\n                var vertex = va[via[i]];\n                ea[oi] = vertex - oldVertex;\n                oi = i; oldVertex = vertex;\n            }\n\n            oi = count - 1;\n            var oldEdge = ea[oi].Normalized;\n\n            for (int i = 0; i < count; i++)\n            {\n                var edge = ea[i].Normalized;\n                if (normalizedEdgeArray != null)\n                    normalizedEdgeArray[oi] = oldEdge;\n                straightArray[i] = (edge - oldEdge).LengthSquared < eps2;\n                oi = i; oldEdge = edge;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns>Triangle count.</returns>\n        public static int ComputeTriangulationOfNonConcavePolygon(\n                this V3d[] va, int[] via, double absoluteEpsilon,\n                int ftvi, int[] tia, int[] pvibm = null, int[] tibm = null)\n        {\n            int count = via.Length;\n            var straightArray = new bool[count];\n            var normalizedEdgeArray = new V3d[count];\n\n            via.ComputeStraightVertices(va, absoluteEpsilon,\n                    normalizedEdgeArray, straightArray);\n\n            var ia = new int[count].SetByIndex(i => i);\n\n            return ia.ComputeTriangulationOfNonConcavePolygon(\n                    via, va, normalizedEdgeArray, straightArray,\n                    ftvi, tia, pvibm, tibm);\n        }\n\n        public static int[] ComputeTriangulationOfNonConcavePolygons(\n                this V3d[] vertexArray, List<int[]> nonConcavePolyList,\n                double absoluteEpsilon)\n        {\n            int tc = nonConcavePolyList.Sum(p => p.Length - 2);\n            var tia = new int[tc];\n            tc = 0;\n            foreach (var pia in nonConcavePolyList)\n            {\n                tc += 3 * vertexArray.ComputeTriangulationOfNonConcavePolygon(\n                                        pia, absoluteEpsilon, tc, tia);\n            }\n            return tia;\n        }\n\n        #endregion\n\n        #region Triangulation of Concave Polygons\n\n        /// <summary>\n        /// Compute the triangulation of the supplied concave polygon and put\n        /// the triangle vertex indices into the supplied array starting at\n        /// the supplied triangle vertex index.\n        /// </summary>\n        /// <returns>the number of triangles in the triangulation</returns>\n        private static int ComputeTriangulationOfConcavePolygon(\n                this Polygon3d polygon, double absoluteEpsilon,\n                int triangleVertexIndex, int[] triangleIndexArray)\n        {\n            var polyList = polygon.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n\n            foreach (var pia in polyList)\n            {\n                int tc = polygon.GetPointArray().ComputeTriangulationOfNonConcavePolygon(\n                                            pia, absoluteEpsilon, triangleVertexIndex,\n                    triangleIndexArray);\n                triangleVertexIndex += 3 * tc;\n            }\n            return polygon.PointCount - 2;\n        }\n\n        /// <summary>\n        /// Compute the triangulation of the supplied concave polygon and\n        /// return the resulting triangle index array.\n        /// </summary>\n        public static int[] ComputeTriangulationOfConcavePolygon(\n                this Polygon3d polygon, double absoluteEpsilon)\n        {\n            int[] triangleIndexArray = new int[3 * (polygon.PointCount - 2)];\n            polygon.ComputeTriangulationOfConcavePolygon(\n                        absoluteEpsilon, 0, triangleIndexArray);\n            return triangleIndexArray;\n        }\n\n        /// <summary>\n        /// Compute the triangulation of the concave polygons supplied in\n        /// the arrays with PolyMesh layout, and return the resulting\n        /// triangle index array.\n        /// </summary>\n        public static int[] ComputeTriangulationOfConcavePolygons(\n                this V3d[] vertexArray, int polyCount,\n                V3d[] normalArray, int[] firstIndices, int[] vertexIndices,\n                double absoluteEpsilon)\n        {\n            var polyList = vertexArray.ComputeNonConcaveSubPolygons(\n                                polyCount, normalArray, firstIndices,\n                                vertexIndices, null, absoluteEpsilon);\n            return vertexArray.ComputeTriangulationOfNonConcavePolygons(\n                                polyList, absoluteEpsilon);\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Relations/SubPrimitives_template.cs",
    "content": "﻿using System;\nusing System.Linq;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class SubPrimitives\n    {\n        #region Triangulation of Convex Polygons\n\n        /// <summary>\n        /// Compute a simple triangulation starting from the first point of\n        /// the polygon. Note that the indices are twice indirect (once over\n        /// pia, once over via). Returns the number of triangles (ie. two\n        /// less than the length of the array pia).\n        /// </summary>\n        public static int ComputeSimpleTriangulation(\n                this int[] pia, int[] via, int tvi, int[] tia, int[] pvibm, int[] tibm)\n        {\n            int fi = pia[0], fvi = via[fi];\n            int i1 = pia[1], vi1 = via[i1];\n            int count = pia.Length;\n            for (int ii = 2; ii < count; ii++)\n            {\n                int vi0 = vi1, i0 = i1;\n                vi1 = via[i1 = pia[ii]];\n                tia[tvi] = fvi;\n                tia[tvi + 1] = vi0;\n                tia[tvi + 2] = vi1;\n                if (tibm != null)\n                {\n                    tibm[tvi] = pvibm[fi];\n                    tibm[tvi + 1] = pvibm[i0];\n                    tibm[tvi + 2] = pvibm[i1];\n                }\n                tvi += 3;\n            }\n            return count - 2;\n        }\n\n        #endregion\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var line2t = \"Line2\" + tc;\n        //#   var plane2t = \"Plane2\" + tc;\n        //#   var polygon2t = \"Polygon2\" + tc;\n        //#   var polygon3t = \"Polygon3\" + tc;\n        //#   var m44t = \"M44\" + tc;\n        #region Non-Concave Sub-Polygons of a __polygon2t__\n\n        private static int[] ComputeNonConcaveSubPolygon(\n                this __polygon2t__ poly, ref int[] indices, __rtype__ absoluteEpsilon)\n        {\n            int count = indices.Length;\n\n            if (count <= 3)\n            {\n                var result = indices;\n                indices = Array.Empty<int>();\n                return result;\n            }\n\n            Func<int, int> addFun = i => (i + 1) % count;\n            Func<int, int> subFun = i => (i + count - 1) % count;\n\n            for (int vi = 0; vi < count; vi++) // we possibly have to try all vertices\n            {\n                int nowMinIndex = vi, nowMaxIndex = vi;\n                var nowMinPoint = poly[indices[nowMinIndex]];\n                var nowMaxPoint = poly[indices[nowMaxIndex]];\n                var oldMinPoint = poly[indices[addFun(nowMinIndex)]];\n                var oldMaxPoint = poly[indices[subFun(nowMinIndex)]];\n                var subCount = 1;\n\n                bool add = true;\n\n                for (int pass = 0, goodPass = 0; pass - goodPass < 3; pass++, add = !add)\n                {\n                    // alternate between adding a point at the two ends\n                    var nextFun = add ? addFun : subFun;\n                    int lastIndex = add ? nowMinIndex : nowMaxIndex;\n\n                    int newIndex = add ? addFun(nowMaxIndex) : subFun(nowMinIndex);\n                    if (newIndex == lastIndex)\n                    {\n                        var finalIndices = indices;\n                        indices = Array.Empty<int>();\n                        return finalIndices;\n                    }\n\n                    var newPoint = poly[indices[newIndex]];\n                    var pMax = new __line2t__(oldMaxPoint, nowMaxPoint).__plane2t__;\n                    var pMin = new __line2t__(oldMinPoint, nowMinPoint).__plane2t__;\n\n                    var npMax = pMax.Normalized;\n                    var npMin = pMin.Normalized;\n\n                    var hMax = new __line2t__(oldMaxPoint, nowMaxPoint).__plane2t__.Normalized.Height(newPoint);\n                    var hMin = new __line2t__(oldMinPoint, nowMinPoint).__plane2t__.Normalized.Height(newPoint);\n\n                    if (hMax >= -absoluteEpsilon && hMin <= absoluteEpsilon)\n                    {\n                        bool good = true;\n                        if (nowMinIndex != nowMaxIndex)\n                        {\n                            var plane0 = new __line2t__(nowMinPoint, nowMaxPoint).__plane2t__.Normalized;\n                            var plane1 = new __line2t__(nowMaxPoint, newPoint).__plane2t__.Normalized;\n                            var plane2 = new __line2t__(newPoint, nowMinPoint).__plane2t__.Normalized;\n\n                            // check if new triangle does not contain any other points of the polygon\n                            for (int i = nextFun(newIndex); i != lastIndex; i = nextFun(i))\n                            {\n                                var point = poly[indices[i]];\n                                if (plane0.Height(point) > -absoluteEpsilon\n                                    && plane1.Height(point) >= absoluteEpsilon\n                                    && plane2.Height(point) >= absoluteEpsilon)\n                                { good = false; break; }\n                            }\n                        }\n                        if (good)\n                        {\n                            if (add)\n                            {\n                                nowMaxIndex = newIndex; oldMaxPoint = nowMaxPoint; nowMaxPoint = newPoint;\n                            }\n                            else\n                            {\n                                nowMinIndex = newIndex; oldMinPoint = nowMinPoint; nowMinPoint = newPoint;\n                            }\n                            goodPass = pass;\n                            ++subCount;\n                        }\n                    }\n                }\n                if (subCount < 3) continue;\n\n                // build new arrays here\n\n                var subIndices = new int[subCount];\n                for (int i = 0, ni = nowMinIndex; i < subCount; i++, ni = addFun(ni))\n                    subIndices[i] = indices[ni];\n                int newCount = 2 + count - subCount;\n                var newIndices = new int[newCount];\n                for (int i = 0, ni = nowMaxIndex; i < newCount; i++, ni = addFun(ni))\n                    newIndices[i] = indices[ni];\n\n                indices = newIndices;\n                return subIndices;\n            }\n            return null;\n        }\n\n        public static void AddNonConcaveSubPolygons(\n                this List<int[]> polygonList, __polygon2t__ poly,\n                __rtype__ absoluteEpsilon)\n        {\n            var indices = new int[poly.PointCount].SetByIndex(i => i);\n            while (indices.Length > 0)\n            {\n                var subPoly = poly.ComputeNonConcaveSubPolygon(\n                                    ref indices, absoluteEpsilon);\n\n                if (subPoly == null)\n                {\n                    Console.WriteLine(\"encountered degenerated polygon that cannot be easily triangulated\");\n                    break;\n                }\n\n                if (subPoly.Length < 3)\n                {\n                    Console.WriteLine(\"encountered invalid subpolygon\");\n                    continue;\n                }\n                polygonList.Add(subPoly);\n            }\n        }\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this __polygon2t__ polygon, __rtype__ absoluteEpsilon)\n        {\n            var polygonList = new List<int[]>();\n            polygonList.AddNonConcaveSubPolygons(polygon, absoluteEpsilon);\n            return polygonList;\n        }\n\n        #endregion\n\n        #region Non-Concave Sub-Polygons of Polygons in 3d\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this __polygon3t__ polygon, __rtype__ absoluteEpsilon)\n        {\n            __v3t__ normal = polygon.ComputeDoubleAreaNormal();\n            __rtype__ len2 = normal.LengthSquared;\n\n            if (len2 < absoluteEpsilon * absoluteEpsilon)\n                return new int[polygon.PointCount].SetByIndex(i => i).IntoList();\n\n            __m44t__.NormalFrame(__v3t__.Zero, normal * (1 / Fun.Sqrt(len2)), out __m44t__ local2global, out __m44t__ global2local);\n            var polygon2d = polygon.To__polygon2t__(p => global2local.TransformPos(p).XY);\n            return polygon2d.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n        }\n\n        public static List<int[]> ComputeNonConcaveSubPolygons(\n                this __v3t__[] vertexArray, int polyCount,\n                __v3t__[] normalArray, int[] firstIndices, int[] vertexIndices,\n                List<int> faceBackMap,\n                __rtype__ absoluteEpsilon)\n        {\n            var polyList = new List<int[]>();\n            var eps2 = absoluteEpsilon * absoluteEpsilon;\n\n            for (int fvi = 0, fi = 0; fi < polyCount; fi++)\n            {\n                int fve = firstIndices[fi+1], fvc = fve - fvi;\n                var n = normalArray[fi];\n                var l2 = n.LengthSquared;\n                if (l2 < eps2)\n                {\n                    polyList.Add(new int[fvc].SetByIndex(i => vertexIndices[fvi + i]));\n                    if (faceBackMap != null)\n                        faceBackMap.Add(fi);\n                    fvi = fve;\n                    continue;\n                }\n                __m44t__.NormalFrame(__v3t__.Zero, n, out __m44t__ local2global, out __m44t__ global2local);\n                var polygon = new __polygon2t__(fvc,\n                        i => global2local.TransformPos(vertexArray[vertexIndices[fvi + i]]).XY);\n                var subPolyList = polygon.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n                foreach (var poly in subPolyList)\n                    polyList.Add(poly.Map(i => fvi + i));\n                if (faceBackMap != null)\n                    for (int i = 0; i < subPolyList.Count; i++)\n                        faceBackMap.Add(fi);\n                fvi = fve;\n            }\n\n            return polyList;\n        }\n\n        #endregion\n\n        #region Triangulation of Non-Concave Polygons in 3d\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns>Triangle count.</returns>\n        public static int ComputeTriangulationOfNonConcavePolygon(\n                this int[] ia, int[] via, __v3t__[] va, __v3t__[] edgeArray, bool[] straightArray,\n                int tvi, int[] tia, int[] pvibm, int[] tibm)\n        {\n            int count = ia.Length;\n\n            if (count < 3) throw new ArgumentOutOfRangeException();\n\n            if (count == 3)\n            {\n                tia[tvi] = via[ia[0]];\n                tia[tvi + 1] = via[ia[1]];\n                tia[tvi + 2] = via[ia[2]];\n                if (tibm != null)\n                {\n                    tibm[tvi] = pvibm[ia[0]];\n                    tibm[tvi + 1] = pvibm[ia[1]];\n                    tibm[tvi + 2] = pvibm[ia[2]];\n                }\n                return 1;\n            }\n\n            int ii = 0;\n\n            // search for the first non-straight corner\n            while (ii < ia.Length && straightArray[ia[ii]]) ii++;\n\n            int bii = ii; ii = (ii + 1) % count;\n\n            // search for first straight corner afterwards\n            while (ii != bii && !straightArray[ia[ii]]) ii = (ii + 1) % count;\n\n            if (ii == bii) // if there is no straight corner\n                return ia.ComputeSimpleTriangulation(via, tvi, tia, pvibm, tibm);\n            bii = ii; // first\n            int eii = ii;\n            int straightCount = 0;\n            while (straightArray[ia[ii]])\n            {\n                eii = ii; ii = (ii + 1) % count;\n                ++straightCount;\n            }\n\n            if (count - straightCount < 3) // numeric problem, cop out\n                return ia.ComputeSimpleTriangulation(via, tvi, tia, pvibm, tibm);\n\n            var hii = ii; __rtype__ height = 0;\n            var li = ia[eii];\n            var edge = edgeArray[li];\n            var vertex = va[via[li]];\n\n            int rightCount = 2;\n            int rc = 2;\n            ii = (ii + 1) % count;\n            while (ii != bii)\n            {\n                int i = ia[ii];\n                var h = edge.Cross(va[via[i]] - vertex).LengthSquared;\n                ++rc;\n                if (h > height)\n                {\n                    height = h;\n                    hii = ii;\n                    rightCount = rc;\n                }\n                ii = (ii + 1) % count;\n            }\n\n            straightArray[ia[bii]] = false;\n            straightArray[ia[eii]] = false;\n            straightArray[ia[hii]] = false;\n\n            int leftCount = count - straightCount - rightCount + 3;\n\n            var lia = new int[leftCount];\n            ii = hii;\n            for (int lii = 0; lii < leftCount; lii++, ii = (ii + 1) % count)\n                lia[lii] = ia[ii];\n\n            if (leftCount > 2)\n                lia.ComputeTriangulationOfNonConcavePolygon(via, va, edgeArray, straightArray,\n                        tvi, tia, pvibm, tibm);\n\n            tvi += 3 * (leftCount - 2);\n\n            if (straightCount > 1)\n            {\n                int hi = ia[hii], hvi = via[hi];\n                int i1 = ia[bii], vi1 = via[i1];\n                ii = bii;\n                for (int sii = 0; sii < straightCount - 1; sii++)\n                {\n                    ii = (ii + 1) % count;\n                    int vi0 = vi1, i0 = i1;\n                    vi1 = via[i1 = ia[ii]];\n                    tia[tvi] = hvi;\n                    tia[tvi + 1] = vi0;\n                    tia[tvi + 2] = vi1;\n\n                    if (tibm != null)\n                    {\n                        tibm[tvi] = pvibm[hi];\n                        tibm[tvi + 1] = pvibm[i0];\n                        tibm[tvi + 2] = pvibm[i1];\n                    }\n                    tvi += 3;\n                }\n            }\n\n            var ria = new int[rightCount];\n            ii = eii;\n            for (int rii = 0; rii < rightCount; rii++, ii = (ii + 1) % count)\n                ria[rii] = ia[ii];\n\n            if (rightCount > 2)\n                ria.ComputeTriangulationOfNonConcavePolygon(via, va, edgeArray, straightArray,\n                        tvi, tia, pvibm, tibm);\n\n            return count - 2;\n        }\n\n        public static void ComputeStraightVertices(\n                this int[] via, __v3t__[] va, __rtype__ absoluteEpsilon,\n                __v3t__[] normalizedEdgeArray, bool[] straightArray)\n        {\n            int count = via.Length;\n            if (straightArray == null) throw new ArgumentNullException();\n            if (count <= 2) throw new ArgumentException();\n            if (straightArray.Length != count) throw new ArgumentException();\n            if (normalizedEdgeArray != null && normalizedEdgeArray.Length != count) throw new ArgumentException();\n\n            __rtype__ eps2 = absoluteEpsilon * absoluteEpsilon;\n\n            __v3t__[] ea = new __v3t__[count];\n            int oi = count - 1;\n            var oldVertex = va[via[oi]];\n\n            for (int i = 0; i < count; i++)\n            {\n                var vertex = va[via[i]];\n                ea[oi] = vertex - oldVertex;\n                oi = i; oldVertex = vertex;\n            }\n\n            oi = count - 1;\n            var oldEdge = ea[oi].Normalized;\n\n            for (int i = 0; i < count; i++)\n            {\n                var edge = ea[i].Normalized;\n                if (normalizedEdgeArray != null)\n                    normalizedEdgeArray[oi] = oldEdge;\n                straightArray[i] = (edge - oldEdge).LengthSquared < eps2;\n                oi = i; oldEdge = edge;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns>Triangle count.</returns>\n        public static int ComputeTriangulationOfNonConcavePolygon(\n                this __v3t__[] va, int[] via, __rtype__ absoluteEpsilon,\n                int ftvi, int[] tia, int[] pvibm = null, int[] tibm = null)\n        {\n            int count = via.Length;\n            var straightArray = new bool[count];\n            var normalizedEdgeArray = new __v3t__[count];\n\n            via.ComputeStraightVertices(va, absoluteEpsilon,\n                    normalizedEdgeArray, straightArray);\n\n            var ia = new int[count].SetByIndex(i => i);\n\n            return ia.ComputeTriangulationOfNonConcavePolygon(\n                    via, va, normalizedEdgeArray, straightArray,\n                    ftvi, tia, pvibm, tibm);\n        }\n\n        public static int[] ComputeTriangulationOfNonConcavePolygons(\n                this __v3t__[] vertexArray, List<int[]> nonConcavePolyList,\n                __rtype__ absoluteEpsilon)\n        {\n            int tc = nonConcavePolyList.Sum(p => p.Length - 2);\n            var tia = new int[tc];\n            tc = 0;\n            foreach (var pia in nonConcavePolyList)\n            {\n                tc += 3 * vertexArray.ComputeTriangulationOfNonConcavePolygon(\n                                        pia, absoluteEpsilon, tc, tia);\n            }\n            return tia;\n        }\n\n        #endregion\n\n        #region Triangulation of Concave Polygons\n\n        /// <summary>\n        /// Compute the triangulation of the supplied concave polygon and put\n        /// the triangle vertex indices into the supplied array starting at\n        /// the supplied triangle vertex index.\n        /// </summary>\n        /// <returns>the number of triangles in the triangulation</returns>\n        private static int ComputeTriangulationOfConcavePolygon(\n                this __polygon3t__ polygon, __rtype__ absoluteEpsilon,\n                int triangleVertexIndex, int[] triangleIndexArray)\n        {\n            var polyList = polygon.ComputeNonConcaveSubPolygons(absoluteEpsilon);\n\n            foreach (var pia in polyList)\n            {\n                int tc = polygon.GetPointArray().ComputeTriangulationOfNonConcavePolygon(\n                                            pia, absoluteEpsilon, triangleVertexIndex,\n                    triangleIndexArray);\n                triangleVertexIndex += 3 * tc;\n            }\n            return polygon.PointCount - 2;\n        }\n\n        /// <summary>\n        /// Compute the triangulation of the supplied concave polygon and\n        /// return the resulting triangle index array.\n        /// </summary>\n        public static int[] ComputeTriangulationOfConcavePolygon(\n                this __polygon3t__ polygon, __rtype__ absoluteEpsilon)\n        {\n            int[] triangleIndexArray = new int[3 * (polygon.PointCount - 2)];\n            polygon.ComputeTriangulationOfConcavePolygon(\n                        absoluteEpsilon, 0, triangleIndexArray);\n            return triangleIndexArray;\n        }\n\n        /// <summary>\n        /// Compute the triangulation of the concave polygons supplied in\n        /// the arrays with PolyMesh layout, and return the resulting\n        /// triangle index array.\n        /// </summary>\n        public static int[] ComputeTriangulationOfConcavePolygons(\n                this __v3t__[] vertexArray, int polyCount,\n                __v3t__[] normalArray, int[] firstIndices, int[] vertexIndices,\n                __rtype__ absoluteEpsilon)\n        {\n            var polyList = vertexArray.ComputeNonConcaveSubPolygons(\n                                polyCount, normalArray, firstIndices,\n                                vertexIndices, null, absoluteEpsilon);\n            return vertexArray.ComputeTriangulationOfNonConcavePolygons(\n                                polyList, absoluteEpsilon);\n        }\n\n        #endregion\n\n        //# }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/SpecialPoints_auto.cs",
    "content": "using System.Collections.Generic;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Provides various methods for middle point computations.\n    /// </summary>\n    public static partial class GeometryFun\n    {\n        /* Ray3f */\n\n        #region Ray3f - Ray3f\n\n        public static V3f GetMiddlePoint(this Ray3f ray0, Ray3f ray1)\n        {\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            var my = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n            var la = (my * uDotv - a.Dot(u));\n\n            var p0 = ray0.Origin + la * u;\n            var p1 = ray1.Origin + my * v;\n\n            return 0.5f*(p0 + p1);\n        }\n\n        #endregion\n\n        #region IEnumerable<Ray3f>\n\n        public static V3f GetMiddlePoint(this IEnumerable<Ray3f> rays)\n        {\n            var center = V3f.Zero;\n            var count = 0;\n\n            foreach(var r0 in rays)\n                foreach (var r1 in rays)\n                    if (r0.LexicalCompare(r1) < 0)\n                    {\n                        center += r0.GetMiddlePoint(r1);\n                        ++count;\n                    }\n\n            return center / (float)count;\n        }\n\n        #endregion\n\n        /* Ray3d */\n\n        #region Ray3d - Ray3d\n\n        public static V3d GetMiddlePoint(this Ray3d ray0, Ray3d ray1)\n        {\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            var my = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n            var la = (my * uDotv - a.Dot(u));\n\n            var p0 = ray0.Origin + la * u;\n            var p1 = ray1.Origin + my * v;\n\n            return 0.5*(p0 + p1);\n        }\n\n        #endregion\n\n        #region IEnumerable<Ray3d>\n\n        public static V3d GetMiddlePoint(this IEnumerable<Ray3d> rays)\n        {\n            var center = V3d.Zero;\n            var count = 0;\n\n            foreach(var r0 in rays)\n                foreach (var r1 in rays)\n                    if (r0.LexicalCompare(r1) < 0)\n                    {\n                        center += r0.GetMiddlePoint(r1);\n                        ++count;\n                    }\n\n            return center / (double)count;\n        }\n\n        #endregion\n\n    }\n\n    /// <summary>\n    /// Provides various methods for closest point computations.\n    /// If the query object is an surface or volume the function\n    /// return to closest point on the surface.\n    /// </summary>\n    public static partial class GeometryFun\n    {\n        /* V2f */\n\n        #region V2f - Line2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this V2f query, Line2f line)\n            => GetClosestPointOn(query, line, out float t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Line2f line, V2f query)\n            => query.GetClosestPointOn(line);\n\n        public static V2f GetClosestPointOn(this V2f query, Line2f line, out float t)\n        {\n            var p0q = query - line.P0;\n            t = Vec.Dot(p0q, line.Direction);\n            if (t <= 0) { t = 0; return line.P0; }\n            var denom = line.Direction.LengthSquared;\n            if (t >= denom) { t = 1; return line.P1; }\n            t /= denom;\n            return line.P0 + t * line.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Line2f line, V2f query, out float t)\n            => query.GetClosestPointOn(line, out t);\n\n        #endregion\n\n        #region V2f - Ray2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this V2f query, Ray2f ray)\n            => GetClosestPointOn(query, ray, out float t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Ray2f ray, V2f query)\n            => query.GetClosestPointOn(ray);\n\n        /// <summary>\n        /// Returns the t-parameter along <paramref name=\"ray\"/> at which the closest point to <paramref name=\"query\"/> is.\n        /// </summary>\n        /// <param name=\"query\">Find the closest point on the ray to this point.</param>\n        /// <param name=\"ray\">Find the closest point on this ray.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetClosestPointTOn(this V2f query, Ray2f ray)\n            => Vec.Dot(query - ray.Origin, ray.Direction) / ray.Direction.LengthSquared;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this V2f query, Ray2f ray, out float t)\n        {\n            t = GetClosestPointTOn(query, ray);\n            return ray.Origin + t * ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Ray2f ray, V2f query, out float t)\n            => query.GetClosestPointOn(ray, out t);\n\n        /// <summary>\n        /// Returns the t-parameter along <paramref name=\"ray\"/> at which the closest point to <paramref name=\"query\"/> is.\n        /// </summary>\n        /// <param name=\"query\">Find the closest point on the ray to this point.</param>\n        /// <param name=\"ray\">Find the closest point on this ray.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetClosestPointTOn(this Ray2f ray, V2f query)\n            => query.GetClosestPointTOn(ray);\n\n        #endregion\n\n        #region V2f - Plane2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this V2f point, Plane2f line)\n        {\n            var lengthOfNormal2 = line.Normal.LengthSquared;\n            return (point - (line.Normal.Dot(point - line.Point) / lengthOfNormal2) * line.Normal);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Plane2f line, V2f point)\n            => point.GetClosestPointOn(line);\n\n        #endregion\n\n        #region V2f - Box2f\n\n        public static V2f GetClosestPointOn(this V2f query, Box2f box)\n        {\n            var closest = query;\n            for (var i = 0; i < 2; i++)\n            {\n                if (query[i] < box.Min[i]) closest[i] = box.Min[i];\n                if (query[i] > box.Max[i]) closest[i] = box.Max[i];\n            }\n            return closest;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Box2f box, V2f query)\n            => query.GetClosestPointOn(box);\n\n        #endregion\n\n        #region V2f - Quad2f\n\n        public static V2f GetClosestPointOn(this V2f vec, Quad2f quad)\n        {\n            V2f closestPoint;\n            var temp = vec.GetClosestPointOn(new Line2f(quad.P0,quad.P1));\n            closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new Line2f(quad.P1, quad.P2));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new Line2f(quad.P2, quad.P3));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new Line2f(quad.P3, quad.P0));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            return closestPoint;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Quad2f quad, V2f vec)\n            => vec.GetClosestPointOn(quad);\n\n        #endregion\n\n        #region V2f - Polygon2f\n\n        public static V2f GetClosestPointOn(this V2f vec, Polygon2f poly)\n        {\n            var closestPoint = V2f.PositiveInfinity;\n            var i = 0;\n            foreach (var line in poly.EdgeLines)\n            {\n                var temp = vec.GetClosestPointOn(line);\n                if (i++ == 0) closestPoint = temp;\n                else if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n            }\n\n            return closestPoint;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Polygon2f poly, V2f vec)\n            => vec.GetClosestPointOn(poly);\n\n        #endregion\n\n        #region V2f - Circle2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this V2f query, Circle2f circle)\n            => circle.Center + circle.Radius * (query - circle.Center).Normalized;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Circle2f circle, V2f query)\n            => query.GetClosestPointOn(circle);\n\n        #endregion\n\n        #region V2f - Triangle2f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this V2f query, Triangle2f triangle)\n            => query.GetClosestPointOnTriangle(triangle.P0, triangle.P1, triangle.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetClosestPointOn(this Triangle2f triangle, V2f query)\n            => query.GetClosestPointOn(triangle);\n\n        public static V2f GetClosestPointOnTriangle(this V2f query, V2f a, V2f b, V2f c)\n        {\n            var e01 = b - a;\n            var e02 = c - a;\n\n            var p0q = query - a;\n            var d1 = Vec.Dot(e01, p0q);\n            var d2 = Vec.Dot(e02, p0q);\n            if (d1 <= 0 && d2 <= 0) return a; // bary (1,0,0)\n\n            var p1q = query - b;\n            var d3 = Vec.Dot(e01, p1q);\n            var d4 = Vec.Dot(e02, p1q);\n            if (d3 >= 0 && d4 <= d3) return b; // bary (0,1,0)\n\n            var vc = d1 * d4 - d3 * d2;\n            if (vc <= 0 && d1 >= 0 && d3 <= 0)\n            {\n                var t = d1 / (d1 - d3);\n                return a + t * e01;   // bary (1-t,t,0)\n            }\n\n            var p2q = query - c;\n            var d5 = Vec.Dot(e01, p2q);\n            var d6 = Vec.Dot(e02, p2q);\n            if (d6 >= 0 && d5 <= d6) return c; // bary (0,0,1)\n\n            var vb = d5 * d2 - d1 * d6;\n            if (vb <= 0 && d2 >= 0 && d6 <= 0)\n            {\n                var t = d2 / (d2 - d6);\n                return a + t * e02; // bary (1-t,0,t)\n            }\n\n            var va = d3 * d6 - d5 * d4;\n            if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)\n            {\n                var t = (d4 - d3) / ((d4 - d3) + (d5 - d6));\n                return b + t * (c - b); // bary (0, 1-t, t)\n            }\n\n            // var denom = 1.0 / (va + vb + vc);\n            // var v = vb * denom;\n            // var w = vc * denom;\n            // return triangle.P0 + v * e01 + w * e02; // bary (1-v-w, v, w)\n            return query;\n        }\n\n        #endregion\n\n        /* V3f */\n\n        #region V3f - Box3f\n\n        public static float GetDistanceSquared(this V3f q, Box3f b)\n            => (q.X < b.Min.X ? Fun.Square(b.Min.X - q.X) : q.X > b.Max.X ? Fun.Square(q.X - b.Max.X) : 0)\n             + (q.Y < b.Min.Y ? Fun.Square(b.Min.Y - q.Y) : q.Y > b.Max.Y ? Fun.Square(q.Y - b.Max.Y) : 0)\n             + (q.Z < b.Min.Z ? Fun.Square(b.Min.Z - q.Z) : q.Z > b.Max.Z ? Fun.Square(q.Z - b.Max.Z) : 0);\n\n        public static (float, float) GetDistanceSquared(\n            this V3f q, Box3fAndFlags boxAndFlags, Box.Flags d2Flags, V3f d2v,\n            out Box.Flags d2Flags0, out V3f d2v0,\n            out Box.Flags d2Flags1, out V3f d2v1)\n        {\n            d2Flags0 = d2Flags; d2Flags1 = d2Flags;\n            d2v0 = d2v; d2v1 = d2v;\n\n            float d0 = 0, d1 = 0;\n\n            if ((d2Flags & Box.Flags.MinX) != 0)\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MinX0) != 0)\n                {\n                    d2v0.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags0 |= Box.Flags.MinX;\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MinX1) != 0)\n                {\n                    d2v1.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags1 |= Box.Flags.MinX;\n                }\n                d0 += d2v0.X; d1 += d2v1.X;\n            }\n            else if ((d2Flags & Box.Flags.MaxX) != 0)\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MaxX0) != 0)\n                {\n                    d2v0.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags0 |= Box.Flags.MaxX;\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MaxX1) != 0)\n                {\n                    d2v1.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags1 |= Box.Flags.MaxX;\n                }\n                d0 += d2v0.X; d1 += d2v1.X;\n            }\n            else\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MinX0) != 0)\n                {\n                    if (q.X < boxAndFlags.BBox.Min.X)\n                    {\n                        d2v0.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags0 |= Box.Flags.MinX; d0 += d2v0.X;\n                    }\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MinX1) != 0)\n                {\n                    if (q.X < boxAndFlags.BBox.Min.X)\n                    {\n                        d2v1.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags1 |= Box.Flags.MinX; d1 += d2v1.X;\n                    }\n                }\n                if ((boxAndFlags.BFlags & Box.Flags.MaxX0) != 0)\n                {\n                    if (q.X > boxAndFlags.BBox.Max.X)\n                    {\n                        d2v0.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags0 |= Box.Flags.MaxX; d0 += d2v0.X;\n                    }\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MaxX1) != 0)\n                {\n                    if (q.X > boxAndFlags.BBox.Max.X)\n                    {\n                        d2v1.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags1 |= Box.Flags.MaxX; d1 += d2v1.X;\n                    }\n                }\n            }\n\n            return (d0, d1);\n        }\n\n        public static V3f GetClosestPointOn(this V3f query, Box3f box)\n        {\n            var closest = query;\n            for (int i = 0; i < 3; i++)\n            {\n                if (query[i] < box.Min[i]) closest[i] = box.Min[i];\n                if (query[i] > box.Max[i]) closest[i] = box.Max[i];\n            }\n            return closest;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Box3f box, V3f query)\n            => query.GetClosestPointOn(box);\n\n        #endregion\n\n        #region V3f - Line3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this V3f query, Line3f line)\n            => query.GetClosestPointOnLine(line.P0, line.P1, out float t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Line3f line, V3f query)\n            => query.GetClosestPointOn(line);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this V3f query, Line3f line, out float t)\n            => query.GetClosestPointOnLine(line.P0, line.P1, out t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Line3f line, V3f query, out float t)\n            => query.GetClosestPointOn(line, out t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOnLine(this V3f query, V3f p0, V3f p1)\n            => query.GetClosestPointOnLine(p0, p1, out float t);\n\n        public static V3f GetClosestPointOnLine(this V3f query, V3f p0, V3f p1, out float t)\n        {\n            var dir = p1 - p0;\n            var p0q = query - p0;\n            t = Vec.Dot(p0q, dir);\n            if (t <= 0) { t = 0; return p0; }\n            var denom = dir.LengthSquared;\n            if (t >= denom) { t = 1; return p1; }\n            t /= denom;\n            return p0 + t * dir;\n        }\n\n        #endregion\n\n        #region V3f - Plane3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this V3f query, Plane3f plane)\n            => query - plane.Height(query) * plane.Normal;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Plane3f plane, V3f query)\n            => query.GetClosestPointOn(plane);\n\n        #endregion\n\n        #region V3f - Ray3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this V3f query, Ray3f ray)\n            => GetClosestPointOn(query, ray, out float t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Ray3f ray, V3f query)\n            => query.GetClosestPointOn(ray);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this V3f query, Ray3f ray, out float t)\n        {\n            t = Vec.Dot(query - ray.Origin, ray.Direction)\n                        / ray.Direction.LengthSquared;\n            return ray.Origin + t * ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Ray3f ray, V3f query, out float t)\n            => query.GetClosestPointOn(ray, out t);\n\n        #endregion\n\n        #region V3f - Sphere3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this V3f query, Sphere3f sphere)\n            => sphere.Center + sphere.Radius * (query - sphere.Center).Normalized;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Sphere3f sphere, V3f query)\n            => query.GetClosestPointOn(sphere);\n\n        #endregion\n\n        #region V3f - Cylinder3f\n\n        /// <summary>\n        /// get closest point on cylinder with infinite length\n        /// </summary>\n        public static V3f GetClosestPointOn(this V3f query, Cylinder3f cylinder)\n        {\n            var p = query.GetClosestPointOn(cylinder.Axis.Ray3f);\n            var dir = (query - p).Normalized;\n            return p + cylinder.Radius * dir;\n        }\n\n        /// <summary>\n        /// get closest point on cylinder with infinite length\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Cylinder3f cylinder, V3f query)\n            => query.GetClosestPointOn(cylinder);\n\n        #endregion\n\n        #region V3f - Triangle3f\n\n        /// <summary>\n        /// Tested by rft on 2008-08-06.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this V3f query, Triangle3f triangle)\n            => GetClosestPointOnTriangle(query, triangle.P0, triangle.P1, triangle.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetClosestPointOn(this Triangle3f triangle, V3f query)\n            => query.GetClosestPointOn(triangle);\n\n        /// <summary>\n        /// Tested by rft on 2008-08-06.\n        /// </summary>\n        public static V3f GetClosestPointOnTriangle(this V3f query, V3f p0, V3f p1, V3f p2)\n        {\n            var e01 = p1 - p0;\n            var e02 = p2 - p0;\n\n            var p0q = query - p0;\n            var d1 = Vec.Dot(e01, p0q);\n            var d2 = Vec.Dot(e02, p0q);\n            if (d1 <= 0 && d2 <= 0) return p0; // bary (1,0,0)\n\n            var p1q = query - p1;\n            var d3 = Vec.Dot(e01, p1q);\n            var d4 = Vec.Dot(e02, p1q);\n            if (d3 >= 0 && d4 <= d3) return p1; // bary (0,1,0)\n\n            var vc = d1 * d4 - d3 * d2;\n            if (vc <= 0 && d1 >= 0 && d3 <= 0)\n            {\n                var t = d1 / (d1 - d3);\n                return p0 + t * e01;   // bary (1-t,t,0)\n            }\n\n            var p2q = query - p2;\n            var d5 = Vec.Dot(e01, p2q);\n            var d6 = Vec.Dot(e02, p2q);\n            if (d6 >= 0 && d5 <= d6) return p2; // bary (0,0,1)\n\n            var vb = d5 * d2 - d1 * d6;\n            if (vb <= 0 && d2 >= 0 && d6 <= 0)\n            {\n                var t = d2 / (d2 - d6);\n                return p0 + t * e02; // bary (1-t,0,t)\n            }\n\n            var va = d3 * d6 - d5 * d4;\n            if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)\n            {\n                var t = (d4 - d3) / ((d4 - d3) + (d5 - d6));\n                return p1 + t * (p2 - p1); // bary (0, 1-t, t)\n            }\n\n            float denom = 1 / (va + vb + vc);\n            var v = vb * denom;\n            var w = vc * denom;\n            return p0 + v * e01 + w * e02; // bary (1-v-w, v, w)\n        }\n\n        #endregion\n\n        /* Ray3f */\n\n        #region Ray3f - Ray3f\n\n        public static V3f GetClosestPointOn(this Ray3f ray0, Ray3f ray1)\n        {\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            var n = (uDotv * uDotv - 1);\n            // make sure rays are not parallel\n            if (!n.Abs().IsTiny())\n            {\n                var my = (a.Dot(u) * uDotv - a.Dot(v)) / n;\n                return ray1.Origin + my * v;\n            }\n\n            return ray1.Origin;\n        }\n\n        #endregion\n\n        /* Line3f */\n\n        #region Line3f - Line3f\n\n        /// <summary>\n        /// Returns the point on line1 which is closest to line0.\n        /// </summary>\n        public static V3f GetClosestPointOn(this Line3f line0, Line3f line1)\n        {\n            var r0 = line0.Ray3f;\n            var r1 = line1.Ray3f;\n\n            if (r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                if (line0.P0.GetMinimalDistanceTo(line1) < line0.P1.GetMinimalDistanceTo(line1))\n                    return line0.P0.GetClosestPointOn(line1);\n                else\n                    return line0.P1.GetClosestPointOn(line1);\n            }\n\n            /* var distance = */\n            r0.GetMinimalDistanceTo(r1, out float t0, out float t1);\n            if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                return r1.GetPointOnRay(t1);\n\n            var d0 = line0.P0.GetMinimalDistanceTo(line1);\n            var d1 = line0.P1.GetMinimalDistanceTo(line1);\n            var d2 = line1.P0.GetMinimalDistanceTo(line0);\n            var d3 = line1.P1.GetMinimalDistanceTo(line0);\n\n            if (d0 < d1)\n            {\n                if (d0 < d2)\n                    return d0 < d3 ? line0.P0.GetClosestPointOn(line1) : line1.P1;\n                else\n                    return d2 < d3 ? line1.P0 : line1.P1;\n            }\n            else\n            {\n                if (d1 < d2)\n                    return d1 < d3 ? line0.P1.GetClosestPointOn(line1) : line1.P1;\n                else\n                    return d2 < d3 ? line1.P0 : line1.P1;\n            }\n        }\n\n        #endregion\n\n        #region Line3f - Plane3f\n\n        /// <summary>\n        /// Returns the closest point from a line to a plane (point on line).\n        /// </summary>\n        public static V3f GetClosestPointOn(this Plane3f plane, Line3f line)\n        {\n            var ray = line.Ray3f;\n            if (ray.Intersects(plane, out float t))\n            {\n                var tClamped = t.Clamp(0, 1); // clamp point to line range\n                return ray.GetPointOnRay(tClamped);\n            }\n            else // plane and line are parallel\n            {\n                return line.P0;\n            }\n        }\n        //note: reverse method is not the same (closest point on line)\n\n        #endregion\n\n        #region Line3f - Triangle3f\n\n        /// <summary>\n        /// Returns the closest point from a triangle to a line (point on triangle).\n        /// Note: untested\n        /// </summary>\n        public static V3f GetClosestPointOn(this Line3f line, Triangle3f triangle)\n        {\n            // test if closest point on triangle plane is inside the triangle (we have the point),\n            // otherwiese find closest edge and take closest point to that edge\n\n            var plane = triangle.Plane;\n            var planePoint = plane.GetClosestPointOn(line);\n\n            // switch to 2d:\n            var trafo = Trafo3f.FromNormalFrame(plane.Point, plane.Normal);\n            var point2d = trafo.Backward.TransformPos(planePoint).XY;\n            var triangle2d = new Triangle2f(trafo.Backward.TransformPos(triangle.P0).XY,\n                                            trafo.Backward.TransformPos(triangle.P1).XY,\n                                            trafo.Backward.TransformPos(triangle.P2).XY);\n\n            if (triangle2d.Contains(point2d))\n                return trafo.Forward.TransformPos(point2d.XYO);\n\n            var edgeDistances = new [] {\n                line.GetMinimalDistanceTo(triangle.Line01),\n                line.GetMinimalDistanceTo(triangle.Line12),\n                line.GetMinimalDistanceTo(triangle.Line20)\n            };\n\n            var closestEdge = triangle.GetEdgeLine(edgeDistances.IndexOfMin());\n            return line.GetClosestPointOn(closestEdge);\n        }\n        //note: reverse method is not the same (closest point on line)\n\n        #endregion\n\n        /* V2d */\n\n        #region V2d - Line2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this V2d query, Line2d line)\n            => GetClosestPointOn(query, line, out double t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Line2d line, V2d query)\n            => query.GetClosestPointOn(line);\n\n        public static V2d GetClosestPointOn(this V2d query, Line2d line, out double t)\n        {\n            var p0q = query - line.P0;\n            t = Vec.Dot(p0q, line.Direction);\n            if (t <= 0) { t = 0; return line.P0; }\n            var denom = line.Direction.LengthSquared;\n            if (t >= denom) { t = 1; return line.P1; }\n            t /= denom;\n            return line.P0 + t * line.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Line2d line, V2d query, out double t)\n            => query.GetClosestPointOn(line, out t);\n\n        #endregion\n\n        #region V2d - Ray2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this V2d query, Ray2d ray)\n            => GetClosestPointOn(query, ray, out double t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Ray2d ray, V2d query)\n            => query.GetClosestPointOn(ray);\n\n        /// <summary>\n        /// Returns the t-parameter along <paramref name=\"ray\"/> at which the closest point to <paramref name=\"query\"/> is.\n        /// </summary>\n        /// <param name=\"query\">Find the closest point on the ray to this point.</param>\n        /// <param name=\"ray\">Find the closest point on this ray.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetClosestPointTOn(this V2d query, Ray2d ray)\n            => Vec.Dot(query - ray.Origin, ray.Direction) / ray.Direction.LengthSquared;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this V2d query, Ray2d ray, out double t)\n        {\n            t = GetClosestPointTOn(query, ray);\n            return ray.Origin + t * ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Ray2d ray, V2d query, out double t)\n            => query.GetClosestPointOn(ray, out t);\n\n        /// <summary>\n        /// Returns the t-parameter along <paramref name=\"ray\"/> at which the closest point to <paramref name=\"query\"/> is.\n        /// </summary>\n        /// <param name=\"query\">Find the closest point on the ray to this point.</param>\n        /// <param name=\"ray\">Find the closest point on this ray.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetClosestPointTOn(this Ray2d ray, V2d query)\n            => query.GetClosestPointTOn(ray);\n\n        #endregion\n\n        #region V2d - Plane2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this V2d point, Plane2d line)\n        {\n            var lengthOfNormal2 = line.Normal.LengthSquared;\n            return (point - (line.Normal.Dot(point - line.Point) / lengthOfNormal2) * line.Normal);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Plane2d line, V2d point)\n            => point.GetClosestPointOn(line);\n\n        #endregion\n\n        #region V2d - Box2d\n\n        public static V2d GetClosestPointOn(this V2d query, Box2d box)\n        {\n            var closest = query;\n            for (var i = 0; i < 2; i++)\n            {\n                if (query[i] < box.Min[i]) closest[i] = box.Min[i];\n                if (query[i] > box.Max[i]) closest[i] = box.Max[i];\n            }\n            return closest;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Box2d box, V2d query)\n            => query.GetClosestPointOn(box);\n\n        #endregion\n\n        #region V2d - Quad2d\n\n        public static V2d GetClosestPointOn(this V2d vec, Quad2d quad)\n        {\n            V2d closestPoint;\n            var temp = vec.GetClosestPointOn(new Line2d(quad.P0,quad.P1));\n            closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new Line2d(quad.P1, quad.P2));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new Line2d(quad.P2, quad.P3));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new Line2d(quad.P3, quad.P0));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            return closestPoint;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Quad2d quad, V2d vec)\n            => vec.GetClosestPointOn(quad);\n\n        #endregion\n\n        #region V2d - Polygon2d\n\n        public static V2d GetClosestPointOn(this V2d vec, Polygon2d poly)\n        {\n            var closestPoint = V2d.PositiveInfinity;\n            var i = 0;\n            foreach (var line in poly.EdgeLines)\n            {\n                var temp = vec.GetClosestPointOn(line);\n                if (i++ == 0) closestPoint = temp;\n                else if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n            }\n\n            return closestPoint;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Polygon2d poly, V2d vec)\n            => vec.GetClosestPointOn(poly);\n\n        #endregion\n\n        #region V2d - Circle2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this V2d query, Circle2d circle)\n            => circle.Center + circle.Radius * (query - circle.Center).Normalized;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Circle2d circle, V2d query)\n            => query.GetClosestPointOn(circle);\n\n        #endregion\n\n        #region V2d - Triangle2d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this V2d query, Triangle2d triangle)\n            => query.GetClosestPointOnTriangle(triangle.P0, triangle.P1, triangle.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetClosestPointOn(this Triangle2d triangle, V2d query)\n            => query.GetClosestPointOn(triangle);\n\n        public static V2d GetClosestPointOnTriangle(this V2d query, V2d a, V2d b, V2d c)\n        {\n            var e01 = b - a;\n            var e02 = c - a;\n\n            var p0q = query - a;\n            var d1 = Vec.Dot(e01, p0q);\n            var d2 = Vec.Dot(e02, p0q);\n            if (d1 <= 0 && d2 <= 0) return a; // bary (1,0,0)\n\n            var p1q = query - b;\n            var d3 = Vec.Dot(e01, p1q);\n            var d4 = Vec.Dot(e02, p1q);\n            if (d3 >= 0 && d4 <= d3) return b; // bary (0,1,0)\n\n            var vc = d1 * d4 - d3 * d2;\n            if (vc <= 0 && d1 >= 0 && d3 <= 0)\n            {\n                var t = d1 / (d1 - d3);\n                return a + t * e01;   // bary (1-t,t,0)\n            }\n\n            var p2q = query - c;\n            var d5 = Vec.Dot(e01, p2q);\n            var d6 = Vec.Dot(e02, p2q);\n            if (d6 >= 0 && d5 <= d6) return c; // bary (0,0,1)\n\n            var vb = d5 * d2 - d1 * d6;\n            if (vb <= 0 && d2 >= 0 && d6 <= 0)\n            {\n                var t = d2 / (d2 - d6);\n                return a + t * e02; // bary (1-t,0,t)\n            }\n\n            var va = d3 * d6 - d5 * d4;\n            if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)\n            {\n                var t = (d4 - d3) / ((d4 - d3) + (d5 - d6));\n                return b + t * (c - b); // bary (0, 1-t, t)\n            }\n\n            // var denom = 1.0 / (va + vb + vc);\n            // var v = vb * denom;\n            // var w = vc * denom;\n            // return triangle.P0 + v * e01 + w * e02; // bary (1-v-w, v, w)\n            return query;\n        }\n\n        #endregion\n\n        /* V3d */\n\n        #region V3d - Box3d\n\n        public static double GetDistanceSquared(this V3d q, Box3d b)\n            => (q.X < b.Min.X ? Fun.Square(b.Min.X - q.X) : q.X > b.Max.X ? Fun.Square(q.X - b.Max.X) : 0)\n             + (q.Y < b.Min.Y ? Fun.Square(b.Min.Y - q.Y) : q.Y > b.Max.Y ? Fun.Square(q.Y - b.Max.Y) : 0)\n             + (q.Z < b.Min.Z ? Fun.Square(b.Min.Z - q.Z) : q.Z > b.Max.Z ? Fun.Square(q.Z - b.Max.Z) : 0);\n\n        public static (double, double) GetDistanceSquared(\n            this V3d q, Box3dAndFlags boxAndFlags, Box.Flags d2Flags, V3d d2v,\n            out Box.Flags d2Flags0, out V3d d2v0,\n            out Box.Flags d2Flags1, out V3d d2v1)\n        {\n            d2Flags0 = d2Flags; d2Flags1 = d2Flags;\n            d2v0 = d2v; d2v1 = d2v;\n\n            double d0 = 0, d1 = 0;\n\n            if ((d2Flags & Box.Flags.MinX) != 0)\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MinX0) != 0)\n                {\n                    d2v0.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags0 |= Box.Flags.MinX;\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MinX1) != 0)\n                {\n                    d2v1.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags1 |= Box.Flags.MinX;\n                }\n                d0 += d2v0.X; d1 += d2v1.X;\n            }\n            else if ((d2Flags & Box.Flags.MaxX) != 0)\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MaxX0) != 0)\n                {\n                    d2v0.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags0 |= Box.Flags.MaxX;\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MaxX1) != 0)\n                {\n                    d2v1.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags1 |= Box.Flags.MaxX;\n                }\n                d0 += d2v0.X; d1 += d2v1.X;\n            }\n            else\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MinX0) != 0)\n                {\n                    if (q.X < boxAndFlags.BBox.Min.X)\n                    {\n                        d2v0.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags0 |= Box.Flags.MinX; d0 += d2v0.X;\n                    }\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MinX1) != 0)\n                {\n                    if (q.X < boxAndFlags.BBox.Min.X)\n                    {\n                        d2v1.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags1 |= Box.Flags.MinX; d1 += d2v1.X;\n                    }\n                }\n                if ((boxAndFlags.BFlags & Box.Flags.MaxX0) != 0)\n                {\n                    if (q.X > boxAndFlags.BBox.Max.X)\n                    {\n                        d2v0.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags0 |= Box.Flags.MaxX; d0 += d2v0.X;\n                    }\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MaxX1) != 0)\n                {\n                    if (q.X > boxAndFlags.BBox.Max.X)\n                    {\n                        d2v1.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags1 |= Box.Flags.MaxX; d1 += d2v1.X;\n                    }\n                }\n            }\n\n            return (d0, d1);\n        }\n\n        public static V3d GetClosestPointOn(this V3d query, Box3d box)\n        {\n            var closest = query;\n            for (int i = 0; i < 3; i++)\n            {\n                if (query[i] < box.Min[i]) closest[i] = box.Min[i];\n                if (query[i] > box.Max[i]) closest[i] = box.Max[i];\n            }\n            return closest;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Box3d box, V3d query)\n            => query.GetClosestPointOn(box);\n\n        #endregion\n\n        #region V3d - Line3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this V3d query, Line3d line)\n            => query.GetClosestPointOnLine(line.P0, line.P1, out double t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Line3d line, V3d query)\n            => query.GetClosestPointOn(line);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this V3d query, Line3d line, out double t)\n            => query.GetClosestPointOnLine(line.P0, line.P1, out t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Line3d line, V3d query, out double t)\n            => query.GetClosestPointOn(line, out t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOnLine(this V3d query, V3d p0, V3d p1)\n            => query.GetClosestPointOnLine(p0, p1, out double t);\n\n        public static V3d GetClosestPointOnLine(this V3d query, V3d p0, V3d p1, out double t)\n        {\n            var dir = p1 - p0;\n            var p0q = query - p0;\n            t = Vec.Dot(p0q, dir);\n            if (t <= 0) { t = 0; return p0; }\n            var denom = dir.LengthSquared;\n            if (t >= denom) { t = 1; return p1; }\n            t /= denom;\n            return p0 + t * dir;\n        }\n\n        #endregion\n\n        #region V3d - Plane3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this V3d query, Plane3d plane)\n            => query - plane.Height(query) * plane.Normal;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Plane3d plane, V3d query)\n            => query.GetClosestPointOn(plane);\n\n        #endregion\n\n        #region V3d - Ray3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this V3d query, Ray3d ray)\n            => GetClosestPointOn(query, ray, out double t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Ray3d ray, V3d query)\n            => query.GetClosestPointOn(ray);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this V3d query, Ray3d ray, out double t)\n        {\n            t = Vec.Dot(query - ray.Origin, ray.Direction)\n                        / ray.Direction.LengthSquared;\n            return ray.Origin + t * ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Ray3d ray, V3d query, out double t)\n            => query.GetClosestPointOn(ray, out t);\n\n        #endregion\n\n        #region V3d - Sphere3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this V3d query, Sphere3d sphere)\n            => sphere.Center + sphere.Radius * (query - sphere.Center).Normalized;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Sphere3d sphere, V3d query)\n            => query.GetClosestPointOn(sphere);\n\n        #endregion\n\n        #region V3d - Cylinder3d\n\n        /// <summary>\n        /// get closest point on cylinder with infinite length\n        /// </summary>\n        public static V3d GetClosestPointOn(this V3d query, Cylinder3d cylinder)\n        {\n            var p = query.GetClosestPointOn(cylinder.Axis.Ray3d);\n            var dir = (query - p).Normalized;\n            return p + cylinder.Radius * dir;\n        }\n\n        /// <summary>\n        /// get closest point on cylinder with infinite length\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Cylinder3d cylinder, V3d query)\n            => query.GetClosestPointOn(cylinder);\n\n        #endregion\n\n        #region V3d - Triangle3d\n\n        /// <summary>\n        /// Tested by rft on 2008-08-06.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this V3d query, Triangle3d triangle)\n            => GetClosestPointOnTriangle(query, triangle.P0, triangle.P1, triangle.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetClosestPointOn(this Triangle3d triangle, V3d query)\n            => query.GetClosestPointOn(triangle);\n\n        /// <summary>\n        /// Tested by rft on 2008-08-06.\n        /// </summary>\n        public static V3d GetClosestPointOnTriangle(this V3d query, V3d p0, V3d p1, V3d p2)\n        {\n            var e01 = p1 - p0;\n            var e02 = p2 - p0;\n\n            var p0q = query - p0;\n            var d1 = Vec.Dot(e01, p0q);\n            var d2 = Vec.Dot(e02, p0q);\n            if (d1 <= 0 && d2 <= 0) return p0; // bary (1,0,0)\n\n            var p1q = query - p1;\n            var d3 = Vec.Dot(e01, p1q);\n            var d4 = Vec.Dot(e02, p1q);\n            if (d3 >= 0 && d4 <= d3) return p1; // bary (0,1,0)\n\n            var vc = d1 * d4 - d3 * d2;\n            if (vc <= 0 && d1 >= 0 && d3 <= 0)\n            {\n                var t = d1 / (d1 - d3);\n                return p0 + t * e01;   // bary (1-t,t,0)\n            }\n\n            var p2q = query - p2;\n            var d5 = Vec.Dot(e01, p2q);\n            var d6 = Vec.Dot(e02, p2q);\n            if (d6 >= 0 && d5 <= d6) return p2; // bary (0,0,1)\n\n            var vb = d5 * d2 - d1 * d6;\n            if (vb <= 0 && d2 >= 0 && d6 <= 0)\n            {\n                var t = d2 / (d2 - d6);\n                return p0 + t * e02; // bary (1-t,0,t)\n            }\n\n            var va = d3 * d6 - d5 * d4;\n            if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)\n            {\n                var t = (d4 - d3) / ((d4 - d3) + (d5 - d6));\n                return p1 + t * (p2 - p1); // bary (0, 1-t, t)\n            }\n\n            double denom = 1 / (va + vb + vc);\n            var v = vb * denom;\n            var w = vc * denom;\n            return p0 + v * e01 + w * e02; // bary (1-v-w, v, w)\n        }\n\n        #endregion\n\n        /* Ray3d */\n\n        #region Ray3d - Ray3d\n\n        public static V3d GetClosestPointOn(this Ray3d ray0, Ray3d ray1)\n        {\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            var n = (uDotv * uDotv - 1);\n            // make sure rays are not parallel\n            if (!n.Abs().IsTiny())\n            {\n                var my = (a.Dot(u) * uDotv - a.Dot(v)) / n;\n                return ray1.Origin + my * v;\n            }\n\n            return ray1.Origin;\n        }\n\n        #endregion\n\n        /* Line3d */\n\n        #region Line3d - Line3d\n\n        /// <summary>\n        /// Returns the point on line1 which is closest to line0.\n        /// </summary>\n        public static V3d GetClosestPointOn(this Line3d line0, Line3d line1)\n        {\n            var r0 = line0.Ray3d;\n            var r1 = line1.Ray3d;\n\n            if (r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                if (line0.P0.GetMinimalDistanceTo(line1) < line0.P1.GetMinimalDistanceTo(line1))\n                    return line0.P0.GetClosestPointOn(line1);\n                else\n                    return line0.P1.GetClosestPointOn(line1);\n            }\n\n            /* var distance = */\n            r0.GetMinimalDistanceTo(r1, out double t0, out double t1);\n            if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                return r1.GetPointOnRay(t1);\n\n            var d0 = line0.P0.GetMinimalDistanceTo(line1);\n            var d1 = line0.P1.GetMinimalDistanceTo(line1);\n            var d2 = line1.P0.GetMinimalDistanceTo(line0);\n            var d3 = line1.P1.GetMinimalDistanceTo(line0);\n\n            if (d0 < d1)\n            {\n                if (d0 < d2)\n                    return d0 < d3 ? line0.P0.GetClosestPointOn(line1) : line1.P1;\n                else\n                    return d2 < d3 ? line1.P0 : line1.P1;\n            }\n            else\n            {\n                if (d1 < d2)\n                    return d1 < d3 ? line0.P1.GetClosestPointOn(line1) : line1.P1;\n                else\n                    return d2 < d3 ? line1.P0 : line1.P1;\n            }\n        }\n\n        #endregion\n\n        #region Line3d - Plane3d\n\n        /// <summary>\n        /// Returns the closest point from a line to a plane (point on line).\n        /// </summary>\n        public static V3d GetClosestPointOn(this Plane3d plane, Line3d line)\n        {\n            var ray = line.Ray3d;\n            if (ray.Intersects(plane, out double t))\n            {\n                var tClamped = t.Clamp(0, 1); // clamp point to line range\n                return ray.GetPointOnRay(tClamped);\n            }\n            else // plane and line are parallel\n            {\n                return line.P0;\n            }\n        }\n        //note: reverse method is not the same (closest point on line)\n\n        #endregion\n\n        #region Line3d - Triangle3d\n\n        /// <summary>\n        /// Returns the closest point from a triangle to a line (point on triangle).\n        /// Note: untested\n        /// </summary>\n        public static V3d GetClosestPointOn(this Line3d line, Triangle3d triangle)\n        {\n            // test if closest point on triangle plane is inside the triangle (we have the point),\n            // otherwiese find closest edge and take closest point to that edge\n\n            var plane = triangle.Plane;\n            var planePoint = plane.GetClosestPointOn(line);\n\n            // switch to 2d:\n            var trafo = Trafo3d.FromNormalFrame(plane.Point, plane.Normal);\n            var point2d = trafo.Backward.TransformPos(planePoint).XY;\n            var triangle2d = new Triangle2d(trafo.Backward.TransformPos(triangle.P0).XY,\n                                            trafo.Backward.TransformPos(triangle.P1).XY,\n                                            trafo.Backward.TransformPos(triangle.P2).XY);\n\n            if (triangle2d.Contains(point2d))\n                return trafo.Forward.TransformPos(point2d.XYO);\n\n            var edgeDistances = new [] {\n                line.GetMinimalDistanceTo(triangle.Line01),\n                line.GetMinimalDistanceTo(triangle.Line12),\n                line.GetMinimalDistanceTo(triangle.Line20)\n            };\n\n            var closestEdge = triangle.GetEdgeLine(edgeDistances.IndexOfMin());\n            return line.GetClosestPointOn(closestEdge);\n        }\n        //note: reverse method is not the same (closest point on line)\n\n        #endregion\n\n    }\n\n    public static partial class GeometryFun\n    {\n        #region Range1f - Range1f\n\n        public static float GetMinimalDistanceTo(this Range1f range0, Range1f range1)\n        {\n            if (range0.Min > range1.Max) return range0.Min - range1.Max;\n            if (range0.Max < range1.Min) return range1.Min - range0.Max;\n            return 0;\n        }\n\n        #endregion\n\n        #region Ray2f - Ray2f\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Ray2f ray0, Ray2f ray1)\n            => ray0.GetMinimalDistanceTo(ray1, out float t0, out float t1);\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// t0 and t1 hold the correspunding ray parameters.\n        /// if both rays are parallel the t0 and t1 are from the origin of ray1\n        /// </summary>\n        public static float GetMinimalDistanceTo(this Ray2f ray0, Ray2f ray1, out float t0, out float t1)\n        {\n            // NOTE: copy of Ray3f to Ray3f distance\n\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            if (uDotv.Abs().ApproximateEquals(1, Constant<float>.PositiveTinyValue)) // rays are parallel\n            {\n                // return origin of ray 1\n                t1 = 0;\n                t0 = ray0.GetT(ray1.Origin);\n            }\n            else\n            {\n                // change by lui: added normalization (ortherwise in case the directions are not normalized t0 and t1 are wrong)\n                t1 = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n                t0 = (t1 * uDotv - a.Dot(u)) / ray0.Direction.Length;\n                t1 = t1 / ray1.Direction.Length;\n            }\n\n            return (t1 * ray1.Direction - a - t0 * ray0.Direction).Length;\n        }\n\n        #endregion\n\n        #region Box2f - Box2f\n\n        public static float GetMinimalDistanceTo(this Box2f box0, Box2f box1)\n        {\n            var distX = box0.RangeX.GetMinimalDistanceTo(box1.RangeX);\n            var distY = box0.RangeY.GetMinimalDistanceTo(box1.RangeY);\n\n            if (distX == 0 && distY == 0)\n                return 0;\n            else if (distX == 0)\n                return distY;\n            else if (distY == 0)\n                return distX;\n\n            if (box0.Min.X > box1.Max.X) // 1 is left\n            {\n                if (box0.Min.Y > box1.Max.Y) // 1 is top left\n                    return (box0.Corner(0) - box1.Corner(3)).Length;\n                else // 1 is bottom left\n                    return (box0.Corner(2) - box1.Corner(1)).Length;\n            }\n            else // 1 is right\n            {\n                if (box0.Min.Y > box1.Max.Y) // 1 is top right\n                    return (box0.Corner(1) - box1.Corner(2)).Length;\n                else // 1 is bottom right\n                    return (box0.Corner(3) - box1.Corner(0)).Length;\n            }\n        }\n\n        #endregion\n\n        #region V2f - Line2f\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this V2f point, Line2f line)\n            => point.DistanceToLine(line.P0, line.P1);\n\n        #endregion\n\n        #region V2f - Triangle2f\n\n        /// <summary>\n        /// returns the minimal distance between the point and the triangle\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this V2f point, Triangle2f t)\n            => Triangle.Distance(t.P0, t.P1, t.P2, point);\n\n        #endregion\n\n        #region Line2f - Line2f\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// </summary>\n        public static float GetMinimalDistanceTo(this Line2f l0, Line2f l1)\n        {\n            var r0 = l0.Ray2f;\n            var r1 = l1.Ray2f;\n\n            if (!r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                var distance = r0.GetMinimalDistanceTo(r1, out float t0, out float t1);\n\n                if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                    return distance;\n            }\n\n            // lines are parallel or t0 and t1 are outside of the line\n            return Fun.Min(l0.P0.GetMinimalDistanceTo(l1), l0.P1.GetMinimalDistanceTo(l1),\n                l1.P0.GetMinimalDistanceTo(l0), l1.P1.GetMinimalDistanceTo(l0));\n        }\n        #endregion\n\n        #region V3f - Line3f\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this V3f point, Line3f line)\n            => point.DistanceToLine(line.P0, line.P1);\n\n        /// <summary>\n        /// Returns the minimal distance between the point and the Line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Line3f line, V3f point)\n            => point.GetMinimalDistanceTo(line);\n\n        #endregion\n\n        #region V3f - Ray3f\n\n        /*  Performance Test .........................................................................\n                Faster Method:                                      V3f.MinimalDistanceTo(Ray3f)\n                V3f.MinimalDistanceTo(Ray3f):                       1,841s\n                (V3f - V3f.GetClosestPointOn(Ray3f)).Length:        3,058s\n                Total Executions:                                   10000000\n                Errors outside tolerance(1E-7):                     0\n                Average Squared-Distance of Results:                2,24116481902135E-32\n                Speedup-factor:                                     1,66\n         */\n\n        /// <summary>\n        /// Returns the minimal distance between the point and the ray.\n        /// </summary>\n        public static float GetMinimalDistanceTo(this V3f point, Ray3f ray)\n        {\n            var a = point - ray.Origin;\n            float lu2 = ray.Direction.LengthSquared;\n            float acu2 = Vec.Cross(a, ray.Direction).LengthSquared;\n\n            return Fun.Sqrt(acu2 / lu2);\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Ray3f ray, V3f point)\n            => point.GetMinimalDistanceTo(ray);\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// t holds the ray parameter for the closest point.\n        /// </summary>\n        public static float GetMinimalDistanceTo(this V3f point, Ray3f ray, out float t)\n        {\n            var a = point - ray.Origin;\n            var lu2 = ray.Direction.LengthSquared;\n            var acu2 = Vec.Cross(a, ray.Direction).LengthSquared;\n\n            var NormalPart2 = acu2 / lu2;\n            var ParallelPart2 = lu2 - NormalPart2;\n\n            t = Fun.Sqrt(ParallelPart2 / lu2);\n            return Fun.Sqrt(NormalPart2);\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// t holds the ray parameter for the closest point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Ray3f ray, V3f point, out float t)\n            => point.GetMinimalDistanceTo(ray, out t);\n\n        #endregion\n\n        #region V3f - Plane3f\n\n        /// <summary>\n        /// Returns the minimal distance (unsigned) between the point and the plane.\n        /// Use Plane3f.Height to compute the signed height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this V3f point, Plane3f plane)\n            => plane.Height(point).Abs();\n\n        /// <summary>\n        /// Returns the minimal distance (unsigned) between the point and the plane.\n        /// Use Plane3f.Height to compute the signed height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Plane3f plane, V3f point)\n            => point.GetMinimalDistanceTo(plane);\n\n        #endregion\n\n        #region V3f - Box3f\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        public static float GetMinimalDistanceTo(this V3f point, Box3f box)\n        {\n            var outside = box.OutsideFlags(point); if (outside == 0) return 0;\n\n            var d = V3f.Zero;\n\n            if ((outside & Box.Flags.X) != 0)\n            {\n                if ((outside & Box.Flags.MaxX) != 0) d.X = point.X - box.Max.X;\n                else if ((outside & Box.Flags.MinX) != 0) d.X = point.X - box.Min.X;\n            }\n\n            if ((outside & Box.Flags.Y) != 0)\n            {\n                if ((outside & Box.Flags.MaxY) != 0) d.Y = point.Y - box.Max.Y;\n                else if ((outside & Box.Flags.MinY) != 0) d.Y = point.Y - box.Min.Y;\n            }\n\n            if ((outside & Box.Flags.Z) != 0)\n            {\n                if ((outside & Box.Flags.MaxZ) != 0) d.Z = point.Z - box.Max.Z;\n                else if ((outside & Box.Flags.MinZ) != 0) d.Z = point.Z - box.Min.Z;\n            }\n\n            return d.Length;\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Box3f box, V3f point)\n            => point.GetMinimalDistanceTo(box);\n\n        #endregion\n\n        #region V3f - Triangle3f\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this V3f point, Triangle3f triangle)\n            => Triangle.Distance(triangle.P0, triangle.P1, triangle.P2, point);\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Triangle3f triangle, V3f point)\n            => point.GetMinimalDistanceTo(triangle);\n\n        #endregion\n\n        #region Line3f - Line3f\n\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// </summary>\n        public static float GetMinimalDistanceTo(this Line3f l0, Line3f l1)\n        {\n            var r0 = l0.Ray3f;\n            var r1 = l1.Ray3f;\n\n            if (!r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                var distance = r0.GetMinimalDistanceTo(r1, out float t0, out float t1);\n\n                if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                    return distance;\n            }\n\n            // lines are parallel or t0 and t1 are outside of the line\n            return Fun.Min(l0.P0.GetMinimalDistanceTo(l1), l0.P1.GetMinimalDistanceTo(l1),\n                l1.P0.GetMinimalDistanceTo(l0), l1.P1.GetMinimalDistanceTo(l0));\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// points holds the centroid of the shortest connection between the lines\n        /// </summary>\n        public static float GetMinimalDistanceTo(this Line3f l0, Line3f l1, out V3f point)\n        {\n            var r0 = l0.Ray3f;\n            var r1 = l1.Ray3f;\n\n            var distance = r0.GetMinimalDistanceTo(r1, out float t0, out float t1);\n\n            if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n            {\n                point = 0.5f * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t1));\n                return distance;\n            }\n            else\n            {\n                float t;\n                if (t0 < 0 || t0 > 1)\n                {\n                    if (t0 < 0) t0 = 0;\n                    else t0 = 1;\n\n                    distance = r0.GetPointOnRay(t0).GetMinimalDistanceTo(r1, out t);\n                    if (t >= 0 && t <= 1)\n                    {\n                        point = 0.5f * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t));\n                        return distance;\n                    }\n                }\n\n                if (t1 < 0 || t1 > 1)\n                {\n                    if (t1 < 0) t1 = 0;\n                    else t1 = 1;\n\n                    distance = r1.GetPointOnRay(t1).GetMinimalDistanceTo(r0, out t);\n                    if (t >= 0 && t <= 1)\n                    {\n                        point = 0.5f * (r0.GetPointOnRay(t) + r1.GetPointOnRay(t1));\n                        return distance;\n                    }\n                }\n\n            }\n\n            point = 0.5f * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t1));\n            return (r0.GetPointOnRay(t0) - r1.GetPointOnRay(t1)).Length;\n        }\n\n        #endregion\n\n        #region Line3f - Plane3f\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Line3f line, Plane3f plane)\n            => plane.Height(GeometryFun.GetClosestPointOn(plane, line)).Abs();\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Plane3f plane, Line3f line)\n            => line.GetMinimalDistanceTo(plane);\n\n        #endregion\n\n        #region Ray3f - Line3f\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// </summary>\n        public static float GetMinimalDistanceTo(this Ray3f ray, Line3f line)\n        {\n            var r1 = line.Ray3f;\n\n            var distance = ray.GetMinimalDistanceTo(r1, out float t0, out float t1);\n\n            if (t1 >= 0 && t1 <= 1) return distance;\n            else\n            {\n                if (t1 < 0) t1 = 0;\n                if (t1 > 1) t1 = 1;\n\n                var p1 = r1.GetPointOnRay(t1);\n                return p1.GetMinimalDistanceTo(ray);\n            }\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Line3f line, Ray3f ray)\n            => ray.GetMinimalDistanceTo(line);\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// t holds the correspoinding ray parameter.\n        /// </summary>\n        public static float GetMinimalDistanceTo(this Ray3f ray, Line3f line, out float t)\n        {\n            var r1 = line.Ray3f;\n\n            var distance = ray.GetMinimalDistanceTo(r1, out float t0, out float t1);\n\n            if (t1 >= 0 && t1 <= 1)\n            {\n                t = t0;\n                return distance;\n            }\n            else\n            {\n                if (t1 < 0) t1 = 0;\n                if (t1 > 1) t1 = 1;\n\n                var p1 = r1.GetPointOnRay(t1);\n                return p1.GetMinimalDistanceTo(ray, out t);\n            }\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// t holds the correspoinding ray parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Line3f line, Ray3f ray, out float t)\n            => ray.GetMinimalDistanceTo(line, out t);\n\n        #endregion\n\n        #region Ray3f - Ray3f\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetMinimalDistanceTo(this Ray3f ray0, Ray3f ray1)\n            => ray0.GetMinimalDistanceTo(ray1, out float t0, out float t1);\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// t0 and t1 hold the correspunding ray parameters.\n        /// if both rays are parallel the t0 and t1 are from the origin of ray1\n        /// </summary>\n        public static float GetMinimalDistanceTo(this Ray3f ray0, Ray3f ray1, out float t0, out float t1)\n        {\n            // TODO: computation probalby possible without Direction.Normalized and Direction.Length\n\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            if (uDotv.Abs().ApproximateEquals(1, Constant<float>.PositiveTinyValue)) // rays are parallel\n            {\n                // return origin of ray 1\n                t1 = 0;\n                t0 = ray0.GetTOfProjectedPoint(ray1.Origin);\n            }\n            else\n            {\n                // change by lui: added normalization (ortherwise in case the directions are not normalized t0 and t1 are wrong)\n                t1 = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n                t0 = (t1 * uDotv - a.Dot(u)) / ray0.Direction.Length;\n                t1 = t1 / ray1.Direction.Length;\n            }\n\n            return (t1 * ray1.Direction - a - t0 * ray0.Direction).Length;\n        }\n\n        #endregion\n\n        #region Range1d - Range1d\n\n        public static double GetMinimalDistanceTo(this Range1d range0, Range1d range1)\n        {\n            if (range0.Min > range1.Max) return range0.Min - range1.Max;\n            if (range0.Max < range1.Min) return range1.Min - range0.Max;\n            return 0;\n        }\n\n        #endregion\n\n        #region Ray2d - Ray2d\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Ray2d ray0, Ray2d ray1)\n            => ray0.GetMinimalDistanceTo(ray1, out double t0, out double t1);\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// t0 and t1 hold the correspunding ray parameters.\n        /// if both rays are parallel the t0 and t1 are from the origin of ray1\n        /// </summary>\n        public static double GetMinimalDistanceTo(this Ray2d ray0, Ray2d ray1, out double t0, out double t1)\n        {\n            // NOTE: copy of Ray3d to Ray3d distance\n\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            if (uDotv.Abs().ApproximateEquals(1, Constant<double>.PositiveTinyValue)) // rays are parallel\n            {\n                // return origin of ray 1\n                t1 = 0;\n                t0 = ray0.GetT(ray1.Origin);\n            }\n            else\n            {\n                // change by lui: added normalization (ortherwise in case the directions are not normalized t0 and t1 are wrong)\n                t1 = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n                t0 = (t1 * uDotv - a.Dot(u)) / ray0.Direction.Length;\n                t1 = t1 / ray1.Direction.Length;\n            }\n\n            return (t1 * ray1.Direction - a - t0 * ray0.Direction).Length;\n        }\n\n        #endregion\n\n        #region Box2d - Box2d\n\n        public static double GetMinimalDistanceTo(this Box2d box0, Box2d box1)\n        {\n            var distX = box0.RangeX.GetMinimalDistanceTo(box1.RangeX);\n            var distY = box0.RangeY.GetMinimalDistanceTo(box1.RangeY);\n\n            if (distX == 0 && distY == 0)\n                return 0;\n            else if (distX == 0)\n                return distY;\n            else if (distY == 0)\n                return distX;\n\n            if (box0.Min.X > box1.Max.X) // 1 is left\n            {\n                if (box0.Min.Y > box1.Max.Y) // 1 is top left\n                    return (box0.Corner(0) - box1.Corner(3)).Length;\n                else // 1 is bottom left\n                    return (box0.Corner(2) - box1.Corner(1)).Length;\n            }\n            else // 1 is right\n            {\n                if (box0.Min.Y > box1.Max.Y) // 1 is top right\n                    return (box0.Corner(1) - box1.Corner(2)).Length;\n                else // 1 is bottom right\n                    return (box0.Corner(3) - box1.Corner(0)).Length;\n            }\n        }\n\n        #endregion\n\n        #region V2d - Line2d\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this V2d point, Line2d line)\n            => point.DistanceToLine(line.P0, line.P1);\n\n        #endregion\n\n        #region V2d - Triangle2d\n\n        /// <summary>\n        /// returns the minimal distance between the point and the triangle\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this V2d point, Triangle2d t)\n            => Triangle.Distance(t.P0, t.P1, t.P2, point);\n\n        #endregion\n\n        #region Line2d - Line2d\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// </summary>\n        public static double GetMinimalDistanceTo(this Line2d l0, Line2d l1)\n        {\n            var r0 = l0.Ray2d;\n            var r1 = l1.Ray2d;\n\n            if (!r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                var distance = r0.GetMinimalDistanceTo(r1, out double t0, out double t1);\n\n                if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                    return distance;\n            }\n\n            // lines are parallel or t0 and t1 are outside of the line\n            return Fun.Min(l0.P0.GetMinimalDistanceTo(l1), l0.P1.GetMinimalDistanceTo(l1),\n                l1.P0.GetMinimalDistanceTo(l0), l1.P1.GetMinimalDistanceTo(l0));\n        }\n        #endregion\n\n        #region V3d - Line3d\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this V3d point, Line3d line)\n            => point.DistanceToLine(line.P0, line.P1);\n\n        /// <summary>\n        /// Returns the minimal distance between the point and the Line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Line3d line, V3d point)\n            => point.GetMinimalDistanceTo(line);\n\n        #endregion\n\n        #region V3d - Ray3d\n\n        /*  Performance Test .........................................................................\n                Faster Method:                                      V3d.MinimalDistanceTo(Ray3d)\n                V3d.MinimalDistanceTo(Ray3d):                       1,841s\n                (V3d - V3d.GetClosestPointOn(Ray3d)).Length:        3,058s\n                Total Executions:                                   10000000\n                Errors outside tolerance(1E-7):                     0\n                Average Squared-Distance of Results:                2,24116481902135E-32\n                Speedup-factor:                                     1,66\n         */\n\n        /// <summary>\n        /// Returns the minimal distance between the point and the ray.\n        /// </summary>\n        public static double GetMinimalDistanceTo(this V3d point, Ray3d ray)\n        {\n            var a = point - ray.Origin;\n            double lu2 = ray.Direction.LengthSquared;\n            double acu2 = Vec.Cross(a, ray.Direction).LengthSquared;\n\n            return Fun.Sqrt(acu2 / lu2);\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Ray3d ray, V3d point)\n            => point.GetMinimalDistanceTo(ray);\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// t holds the ray parameter for the closest point.\n        /// </summary>\n        public static double GetMinimalDistanceTo(this V3d point, Ray3d ray, out double t)\n        {\n            var a = point - ray.Origin;\n            var lu2 = ray.Direction.LengthSquared;\n            var acu2 = Vec.Cross(a, ray.Direction).LengthSquared;\n\n            var NormalPart2 = acu2 / lu2;\n            var ParallelPart2 = lu2 - NormalPart2;\n\n            t = Fun.Sqrt(ParallelPart2 / lu2);\n            return Fun.Sqrt(NormalPart2);\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// t holds the ray parameter for the closest point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Ray3d ray, V3d point, out double t)\n            => point.GetMinimalDistanceTo(ray, out t);\n\n        #endregion\n\n        #region V3d - Plane3d\n\n        /// <summary>\n        /// Returns the minimal distance (unsigned) between the point and the plane.\n        /// Use Plane3d.Height to compute the signed height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this V3d point, Plane3d plane)\n            => plane.Height(point).Abs();\n\n        /// <summary>\n        /// Returns the minimal distance (unsigned) between the point and the plane.\n        /// Use Plane3d.Height to compute the signed height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Plane3d plane, V3d point)\n            => point.GetMinimalDistanceTo(plane);\n\n        #endregion\n\n        #region V3d - Box3d\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        public static double GetMinimalDistanceTo(this V3d point, Box3d box)\n        {\n            var outside = box.OutsideFlags(point); if (outside == 0) return 0;\n\n            var d = V3d.Zero;\n\n            if ((outside & Box.Flags.X) != 0)\n            {\n                if ((outside & Box.Flags.MaxX) != 0) d.X = point.X - box.Max.X;\n                else if ((outside & Box.Flags.MinX) != 0) d.X = point.X - box.Min.X;\n            }\n\n            if ((outside & Box.Flags.Y) != 0)\n            {\n                if ((outside & Box.Flags.MaxY) != 0) d.Y = point.Y - box.Max.Y;\n                else if ((outside & Box.Flags.MinY) != 0) d.Y = point.Y - box.Min.Y;\n            }\n\n            if ((outside & Box.Flags.Z) != 0)\n            {\n                if ((outside & Box.Flags.MaxZ) != 0) d.Z = point.Z - box.Max.Z;\n                else if ((outside & Box.Flags.MinZ) != 0) d.Z = point.Z - box.Min.Z;\n            }\n\n            return d.Length;\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Box3d box, V3d point)\n            => point.GetMinimalDistanceTo(box);\n\n        #endregion\n\n        #region V3d - Triangle3d\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this V3d point, Triangle3d triangle)\n            => Triangle.Distance(triangle.P0, triangle.P1, triangle.P2, point);\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Triangle3d triangle, V3d point)\n            => point.GetMinimalDistanceTo(triangle);\n\n        #endregion\n\n        #region Line3d - Line3d\n\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// </summary>\n        public static double GetMinimalDistanceTo(this Line3d l0, Line3d l1)\n        {\n            var r0 = l0.Ray3d;\n            var r1 = l1.Ray3d;\n\n            if (!r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                var distance = r0.GetMinimalDistanceTo(r1, out double t0, out double t1);\n\n                if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                    return distance;\n            }\n\n            // lines are parallel or t0 and t1 are outside of the line\n            return Fun.Min(l0.P0.GetMinimalDistanceTo(l1), l0.P1.GetMinimalDistanceTo(l1),\n                l1.P0.GetMinimalDistanceTo(l0), l1.P1.GetMinimalDistanceTo(l0));\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// points holds the centroid of the shortest connection between the lines\n        /// </summary>\n        public static double GetMinimalDistanceTo(this Line3d l0, Line3d l1, out V3d point)\n        {\n            var r0 = l0.Ray3d;\n            var r1 = l1.Ray3d;\n\n            var distance = r0.GetMinimalDistanceTo(r1, out double t0, out double t1);\n\n            if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n            {\n                point = 0.5 * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t1));\n                return distance;\n            }\n            else\n            {\n                double t;\n                if (t0 < 0 || t0 > 1)\n                {\n                    if (t0 < 0) t0 = 0;\n                    else t0 = 1;\n\n                    distance = r0.GetPointOnRay(t0).GetMinimalDistanceTo(r1, out t);\n                    if (t >= 0 && t <= 1)\n                    {\n                        point = 0.5 * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t));\n                        return distance;\n                    }\n                }\n\n                if (t1 < 0 || t1 > 1)\n                {\n                    if (t1 < 0) t1 = 0;\n                    else t1 = 1;\n\n                    distance = r1.GetPointOnRay(t1).GetMinimalDistanceTo(r0, out t);\n                    if (t >= 0 && t <= 1)\n                    {\n                        point = 0.5 * (r0.GetPointOnRay(t) + r1.GetPointOnRay(t1));\n                        return distance;\n                    }\n                }\n\n            }\n\n            point = 0.5 * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t1));\n            return (r0.GetPointOnRay(t0) - r1.GetPointOnRay(t1)).Length;\n        }\n\n        #endregion\n\n        #region Line3d - Plane3d\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Line3d line, Plane3d plane)\n            => plane.Height(GeometryFun.GetClosestPointOn(plane, line)).Abs();\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Plane3d plane, Line3d line)\n            => line.GetMinimalDistanceTo(plane);\n\n        #endregion\n\n        #region Ray3d - Line3d\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// </summary>\n        public static double GetMinimalDistanceTo(this Ray3d ray, Line3d line)\n        {\n            var r1 = line.Ray3d;\n\n            var distance = ray.GetMinimalDistanceTo(r1, out double t0, out double t1);\n\n            if (t1 >= 0 && t1 <= 1) return distance;\n            else\n            {\n                if (t1 < 0) t1 = 0;\n                if (t1 > 1) t1 = 1;\n\n                var p1 = r1.GetPointOnRay(t1);\n                return p1.GetMinimalDistanceTo(ray);\n            }\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Line3d line, Ray3d ray)\n            => ray.GetMinimalDistanceTo(line);\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// t holds the correspoinding ray parameter.\n        /// </summary>\n        public static double GetMinimalDistanceTo(this Ray3d ray, Line3d line, out double t)\n        {\n            var r1 = line.Ray3d;\n\n            var distance = ray.GetMinimalDistanceTo(r1, out double t0, out double t1);\n\n            if (t1 >= 0 && t1 <= 1)\n            {\n                t = t0;\n                return distance;\n            }\n            else\n            {\n                if (t1 < 0) t1 = 0;\n                if (t1 > 1) t1 = 1;\n\n                var p1 = r1.GetPointOnRay(t1);\n                return p1.GetMinimalDistanceTo(ray, out t);\n            }\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// t holds the correspoinding ray parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Line3d line, Ray3d ray, out double t)\n            => ray.GetMinimalDistanceTo(line, out t);\n\n        #endregion\n\n        #region Ray3d - Ray3d\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetMinimalDistanceTo(this Ray3d ray0, Ray3d ray1)\n            => ray0.GetMinimalDistanceTo(ray1, out double t0, out double t1);\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// t0 and t1 hold the correspunding ray parameters.\n        /// if both rays are parallel the t0 and t1 are from the origin of ray1\n        /// </summary>\n        public static double GetMinimalDistanceTo(this Ray3d ray0, Ray3d ray1, out double t0, out double t1)\n        {\n            // TODO: computation probalby possible without Direction.Normalized and Direction.Length\n\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            if (uDotv.Abs().ApproximateEquals(1, Constant<double>.PositiveTinyValue)) // rays are parallel\n            {\n                // return origin of ray 1\n                t1 = 0;\n                t0 = ray0.GetTOfProjectedPoint(ray1.Origin);\n            }\n            else\n            {\n                // change by lui: added normalization (ortherwise in case the directions are not normalized t0 and t1 are wrong)\n                t1 = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n                t0 = (t1 * uDotv - a.Dot(u)) / ray0.Direction.Length;\n                t1 = t1 / ray1.Direction.Length;\n            }\n\n            return (t1 * ray1.Direction - a - t0 * ray0.Direction).Length;\n        }\n\n        #endregion\n\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/SpecialPoints_template.cs",
    "content": "using System.Collections.Generic;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Provides various methods for middle point computations.\n    /// </summary>\n    public static partial class GeometryFun\n    {\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v3t = \"V3\" + tc;\n        //#   var ray3t = \"Ray3\" + tc;\n        //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n        /* __ray3t__ */\n\n        #region __ray3t__ - __ray3t__\n\n        public static __v3t__ GetMiddlePoint(this __ray3t__ ray0, __ray3t__ ray1)\n        {\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            var my = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n            var la = (my * uDotv - a.Dot(u));\n\n            var p0 = ray0.Origin + la * u;\n            var p1 = ray1.Origin + my * v;\n\n            return __half__*(p0 + p1);\n        }\n\n        #endregion\n\n        #region IEnumerable<__ray3t__>\n\n        public static __v3t__ GetMiddlePoint(this IEnumerable<__ray3t__> rays)\n        {\n            var center = __v3t__.Zero;\n            var count = 0;\n\n            foreach(var r0 in rays)\n                foreach (var r1 in rays)\n                    if (r0.LexicalCompare(r1) < 0)\n                    {\n                        center += r0.GetMiddlePoint(r1);\n                        ++count;\n                    }\n\n            return center / (__rtype__)count;\n        }\n\n        #endregion\n\n        //# }\n    }\n\n    /// <summary>\n    /// Provides various methods for closest point computations.\n    /// If the query object is an surface or volume the function\n    /// return to closest point on the surface.\n    /// </summary>\n    public static partial class GeometryFun\n    {\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var line2t = \"Line2\" + tc;\n        //#   var line3t = \"Line3\" + tc;\n        //#   var plane2t = \"Plane2\" + tc;\n        //#   var plane3t = \"Plane3\" + tc;\n        //#   var ray2t = \"Ray2\" + tc;\n        //#   var ray3t = \"Ray3\" + tc;\n        //#   var circle2t = \"Circle2\" + tc;\n        //#   var circle3t = \"Circle3\" + tc;\n        //#   var quad2t = \"Quad2\" + tc;\n        //#   var quad3t = \"Quad3\" + tc;\n        //#   var range1t = \"Range1\" + tc;\n        //#   var box2t = \"Box2\" + tc;\n        //#   var box3t = \"Box3\" + tc;\n        //#   var hull2t = \"Hull2\" + tc;\n        //#   var hull3t = \"Hull3\" + tc;\n        //#   var sphere3t = \"Sphere3\" + tc;\n        //#   var cylinder3t = \"Cylinder3\" + tc;\n        //#   var ellipse3t = \"Ellipse3\" + tc;\n        //#   var triangle2t = \"Triangle2\" + tc;\n        //#   var triangle3t = \"Triangle3\" + tc;\n        //#   var polygon2t = \"Polygon2\" + tc;\n        //#   var polygon3t = \"Polygon3\" + tc;\n        //#   var trafo3t = \"Trafo3\" + tc;\n        //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n        /* __v2t__ */\n\n        #region __v2t__ - __line2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __v2t__ query, __line2t__ line)\n            => GetClosestPointOn(query, line, out __rtype__ t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __line2t__ line, __v2t__ query)\n            => query.GetClosestPointOn(line);\n\n        public static __v2t__ GetClosestPointOn(this __v2t__ query, __line2t__ line, out __rtype__ t)\n        {\n            var p0q = query - line.P0;\n            t = Vec.Dot(p0q, line.Direction);\n            if (t <= 0) { t = 0; return line.P0; }\n            var denom = line.Direction.LengthSquared;\n            if (t >= denom) { t = 1; return line.P1; }\n            t /= denom;\n            return line.P0 + t * line.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __line2t__ line, __v2t__ query, out __rtype__ t)\n            => query.GetClosestPointOn(line, out t);\n\n        #endregion\n\n        #region __v2t__ - __ray2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __v2t__ query, __ray2t__ ray)\n            => GetClosestPointOn(query, ray, out __rtype__ t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __ray2t__ ray, __v2t__ query)\n            => query.GetClosestPointOn(ray);\n\n        /// <summary>\n        /// Returns the t-parameter along <paramref name=\"ray\"/> at which the closest point to <paramref name=\"query\"/> is.\n        /// </summary>\n        /// <param name=\"query\">Find the closest point on the ray to this point.</param>\n        /// <param name=\"ray\">Find the closest point on this ray.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetClosestPointTOn(this __v2t__ query, __ray2t__ ray)\n            => Vec.Dot(query - ray.Origin, ray.Direction) / ray.Direction.LengthSquared;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __v2t__ query, __ray2t__ ray, out __rtype__ t)\n        {\n            t = GetClosestPointTOn(query, ray);\n            return ray.Origin + t * ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __ray2t__ ray, __v2t__ query, out __rtype__ t)\n            => query.GetClosestPointOn(ray, out t);\n\n        /// <summary>\n        /// Returns the t-parameter along <paramref name=\"ray\"/> at which the closest point to <paramref name=\"query\"/> is.\n        /// </summary>\n        /// <param name=\"query\">Find the closest point on the ray to this point.</param>\n        /// <param name=\"ray\">Find the closest point on this ray.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetClosestPointTOn(this __ray2t__ ray, __v2t__ query)\n            => query.GetClosestPointTOn(ray);\n\n        #endregion\n\n        #region __v2t__ - __plane2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __v2t__ point, __plane2t__ line)\n        {\n            var lengthOfNormal2 = line.Normal.LengthSquared;\n            return (point - (line.Normal.Dot(point - line.Point) / lengthOfNormal2) * line.Normal);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __plane2t__ line, __v2t__ point)\n            => point.GetClosestPointOn(line);\n\n        #endregion\n\n        #region __v2t__ - __box2t__\n\n        public static __v2t__ GetClosestPointOn(this __v2t__ query, __box2t__ box)\n        {\n            var closest = query;\n            for (var i = 0; i < 2; i++)\n            {\n                if (query[i] < box.Min[i]) closest[i] = box.Min[i];\n                if (query[i] > box.Max[i]) closest[i] = box.Max[i];\n            }\n            return closest;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __box2t__ box, __v2t__ query)\n            => query.GetClosestPointOn(box);\n\n        #endregion\n\n        #region __v2t__ - __quad2t__\n\n        public static __v2t__ GetClosestPointOn(this __v2t__ vec, __quad2t__ quad)\n        {\n            __v2t__ closestPoint;\n            var temp = vec.GetClosestPointOn(new __line2t__(quad.P0,quad.P1));\n            closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new __line2t__(quad.P1, quad.P2));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new __line2t__(quad.P2, quad.P3));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            temp = vec.GetClosestPointOn(new __line2t__(quad.P3, quad.P0));\n            if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n\n            return closestPoint;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __quad2t__ quad, __v2t__ vec)\n            => vec.GetClosestPointOn(quad);\n\n        #endregion\n\n        #region __v2t__ - __polygon2t__\n\n        public static __v2t__ GetClosestPointOn(this __v2t__ vec, __polygon2t__ poly)\n        {\n            var closestPoint = __v2t__.PositiveInfinity;\n            var i = 0;\n            foreach (var line in poly.EdgeLines)\n            {\n                var temp = vec.GetClosestPointOn(line);\n                if (i++ == 0) closestPoint = temp;\n                else if ((temp - vec).LengthSquared < (closestPoint - vec).LengthSquared) closestPoint = temp;\n            }\n\n            return closestPoint;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __polygon2t__ poly, __v2t__ vec)\n            => vec.GetClosestPointOn(poly);\n\n        #endregion\n\n        #region __v2t__ - __circle2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __v2t__ query, __circle2t__ circle)\n            => circle.Center + circle.Radius * (query - circle.Center).Normalized;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __circle2t__ circle, __v2t__ query)\n            => query.GetClosestPointOn(circle);\n\n        #endregion\n\n        #region __v2t__ - __triangle2t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __v2t__ query, __triangle2t__ triangle)\n            => query.GetClosestPointOnTriangle(triangle.P0, triangle.P1, triangle.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ GetClosestPointOn(this __triangle2t__ triangle, __v2t__ query)\n            => query.GetClosestPointOn(triangle);\n\n        public static __v2t__ GetClosestPointOnTriangle(this __v2t__ query, __v2t__ a, __v2t__ b, __v2t__ c)\n        {\n            var e01 = b - a;\n            var e02 = c - a;\n\n            var p0q = query - a;\n            var d1 = Vec.Dot(e01, p0q);\n            var d2 = Vec.Dot(e02, p0q);\n            if (d1 <= 0 && d2 <= 0) return a; // bary (1,0,0)\n\n            var p1q = query - b;\n            var d3 = Vec.Dot(e01, p1q);\n            var d4 = Vec.Dot(e02, p1q);\n            if (d3 >= 0 && d4 <= d3) return b; // bary (0,1,0)\n\n            var vc = d1 * d4 - d3 * d2;\n            if (vc <= 0 && d1 >= 0 && d3 <= 0)\n            {\n                var t = d1 / (d1 - d3);\n                return a + t * e01;   // bary (1-t,t,0)\n            }\n\n            var p2q = query - c;\n            var d5 = Vec.Dot(e01, p2q);\n            var d6 = Vec.Dot(e02, p2q);\n            if (d6 >= 0 && d5 <= d6) return c; // bary (0,0,1)\n\n            var vb = d5 * d2 - d1 * d6;\n            if (vb <= 0 && d2 >= 0 && d6 <= 0)\n            {\n                var t = d2 / (d2 - d6);\n                return a + t * e02; // bary (1-t,0,t)\n            }\n\n            var va = d3 * d6 - d5 * d4;\n            if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)\n            {\n                var t = (d4 - d3) / ((d4 - d3) + (d5 - d6));\n                return b + t * (c - b); // bary (0, 1-t, t)\n            }\n\n            // var denom = 1.0 / (va + vb + vc);\n            // var v = vb * denom;\n            // var w = vc * denom;\n            // return triangle.P0 + v * e01 + w * e02; // bary (1-v-w, v, w)\n            return query;\n        }\n\n        #endregion\n\n        /* __v3t__ */\n\n        #region __v3t__ - __box3t__\n\n        public static __rtype__ GetDistanceSquared(this __v3t__ q, __box3t__ b)\n            => (q.X < b.Min.X ? Fun.Square(b.Min.X - q.X) : q.X > b.Max.X ? Fun.Square(q.X - b.Max.X) : 0)\n             + (q.Y < b.Min.Y ? Fun.Square(b.Min.Y - q.Y) : q.Y > b.Max.Y ? Fun.Square(q.Y - b.Max.Y) : 0)\n             + (q.Z < b.Min.Z ? Fun.Square(b.Min.Z - q.Z) : q.Z > b.Max.Z ? Fun.Square(q.Z - b.Max.Z) : 0);\n\n        public static (__rtype__, __rtype__) GetDistanceSquared(\n            this __v3t__ q, __box3t__AndFlags boxAndFlags, Box.Flags d2Flags, __v3t__ d2v,\n            out Box.Flags d2Flags0, out __v3t__ d2v0,\n            out Box.Flags d2Flags1, out __v3t__ d2v1)\n        {\n            d2Flags0 = d2Flags; d2Flags1 = d2Flags;\n            d2v0 = d2v; d2v1 = d2v;\n\n            __rtype__ d0 = 0, d1 = 0;\n\n            if ((d2Flags & Box.Flags.MinX) != 0)\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MinX0) != 0)\n                {\n                    d2v0.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags0 |= Box.Flags.MinX;\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MinX1) != 0)\n                {\n                    d2v1.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags1 |= Box.Flags.MinX;\n                }\n                d0 += d2v0.X; d1 += d2v1.X;\n            }\n            else if ((d2Flags & Box.Flags.MaxX) != 0)\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MaxX0) != 0)\n                {\n                    d2v0.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags0 |= Box.Flags.MaxX;\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MaxX1) != 0)\n                {\n                    d2v1.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags1 |= Box.Flags.MaxX;\n                }\n                d0 += d2v0.X; d1 += d2v1.X;\n            }\n            else\n            {\n                if ((boxAndFlags.BFlags & Box.Flags.MinX0) != 0)\n                {\n                    if (q.X < boxAndFlags.BBox.Min.X)\n                    {\n                        d2v0.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags0 |= Box.Flags.MinX; d0 += d2v0.X;\n                    }\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MinX1) != 0)\n                {\n                    if (q.X < boxAndFlags.BBox.Min.X)\n                    {\n                        d2v1.X = Fun.Square(boxAndFlags.BBox.Min.X - q.X); d2Flags1 |= Box.Flags.MinX; d1 += d2v1.X;\n                    }\n                }\n                if ((boxAndFlags.BFlags & Box.Flags.MaxX0) != 0)\n                {\n                    if (q.X > boxAndFlags.BBox.Max.X)\n                    {\n                        d2v0.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags0 |= Box.Flags.MaxX; d0 += d2v0.X;\n                    }\n                }\n                else if ((boxAndFlags.BFlags & Box.Flags.MaxX1) != 0)\n                {\n                    if (q.X > boxAndFlags.BBox.Max.X)\n                    {\n                        d2v1.X = Fun.Square(boxAndFlags.BBox.Max.X - q.X); d2Flags1 |= Box.Flags.MaxX; d1 += d2v1.X;\n                    }\n                }\n            }\n\n            return (d0, d1);\n        }\n\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __box3t__ box)\n        {\n            var closest = query;\n            for (int i = 0; i < 3; i++)\n            {\n                if (query[i] < box.Min[i]) closest[i] = box.Min[i];\n                if (query[i] > box.Max[i]) closest[i] = box.Max[i];\n            }\n            return closest;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __box3t__ box, __v3t__ query)\n            => query.GetClosestPointOn(box);\n\n        #endregion\n\n        #region __v3t__ - __line3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __line3t__ line)\n            => query.GetClosestPointOnLine(line.P0, line.P1, out __rtype__ t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __line3t__ line, __v3t__ query)\n            => query.GetClosestPointOn(line);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __line3t__ line, out __rtype__ t)\n            => query.GetClosestPointOnLine(line.P0, line.P1, out t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __line3t__ line, __v3t__ query, out __rtype__ t)\n            => query.GetClosestPointOn(line, out t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOnLine(this __v3t__ query, __v3t__ p0, __v3t__ p1)\n            => query.GetClosestPointOnLine(p0, p1, out __rtype__ t);\n\n        public static __v3t__ GetClosestPointOnLine(this __v3t__ query, __v3t__ p0, __v3t__ p1, out __rtype__ t)\n        {\n            var dir = p1 - p0;\n            var p0q = query - p0;\n            t = Vec.Dot(p0q, dir);\n            if (t <= 0) { t = 0; return p0; }\n            var denom = dir.LengthSquared;\n            if (t >= denom) { t = 1; return p1; }\n            t /= denom;\n            return p0 + t * dir;\n        }\n\n        #endregion\n\n        #region __v3t__ - __plane3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __plane3t__ plane)\n            => query - plane.Height(query) * plane.Normal;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __plane3t__ plane, __v3t__ query)\n            => query.GetClosestPointOn(plane);\n\n        #endregion\n\n        #region __v3t__ - __ray3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __ray3t__ ray)\n            => GetClosestPointOn(query, ray, out __rtype__ t);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __ray3t__ ray, __v3t__ query)\n            => query.GetClosestPointOn(ray);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __ray3t__ ray, out __rtype__ t)\n        {\n            t = Vec.Dot(query - ray.Origin, ray.Direction)\n                        / ray.Direction.LengthSquared;\n            return ray.Origin + t * ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __ray3t__ ray, __v3t__ query, out __rtype__ t)\n            => query.GetClosestPointOn(ray, out t);\n\n        #endregion\n\n        #region __v3t__ - __sphere3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __sphere3t__ sphere)\n            => sphere.Center + sphere.Radius * (query - sphere.Center).Normalized;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __sphere3t__ sphere, __v3t__ query)\n            => query.GetClosestPointOn(sphere);\n\n        #endregion\n\n        #region __v3t__ - __cylinder3t__\n\n        /// <summary>\n        /// get closest point on cylinder with infinite length\n        /// </summary>\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __cylinder3t__ cylinder)\n        {\n            var p = query.GetClosestPointOn(cylinder.Axis.__ray3t__);\n            var dir = (query - p).Normalized;\n            return p + cylinder.Radius * dir;\n        }\n\n        /// <summary>\n        /// get closest point on cylinder with infinite length\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __cylinder3t__ cylinder, __v3t__ query)\n            => query.GetClosestPointOn(cylinder);\n\n        #endregion\n\n        #region __v3t__ - __triangle3t__\n\n        /// <summary>\n        /// Tested by rft on 2008-08-06.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __v3t__ query, __triangle3t__ triangle)\n            => GetClosestPointOnTriangle(query, triangle.P0, triangle.P1, triangle.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetClosestPointOn(this __triangle3t__ triangle, __v3t__ query)\n            => query.GetClosestPointOn(triangle);\n\n        /// <summary>\n        /// Tested by rft on 2008-08-06.\n        /// </summary>\n        public static __v3t__ GetClosestPointOnTriangle(this __v3t__ query, __v3t__ p0, __v3t__ p1, __v3t__ p2)\n        {\n            var e01 = p1 - p0;\n            var e02 = p2 - p0;\n\n            var p0q = query - p0;\n            var d1 = Vec.Dot(e01, p0q);\n            var d2 = Vec.Dot(e02, p0q);\n            if (d1 <= 0 && d2 <= 0) return p0; // bary (1,0,0)\n\n            var p1q = query - p1;\n            var d3 = Vec.Dot(e01, p1q);\n            var d4 = Vec.Dot(e02, p1q);\n            if (d3 >= 0 && d4 <= d3) return p1; // bary (0,1,0)\n\n            var vc = d1 * d4 - d3 * d2;\n            if (vc <= 0 && d1 >= 0 && d3 <= 0)\n            {\n                var t = d1 / (d1 - d3);\n                return p0 + t * e01;   // bary (1-t,t,0)\n            }\n\n            var p2q = query - p2;\n            var d5 = Vec.Dot(e01, p2q);\n            var d6 = Vec.Dot(e02, p2q);\n            if (d6 >= 0 && d5 <= d6) return p2; // bary (0,0,1)\n\n            var vb = d5 * d2 - d1 * d6;\n            if (vb <= 0 && d2 >= 0 && d6 <= 0)\n            {\n                var t = d2 / (d2 - d6);\n                return p0 + t * e02; // bary (1-t,0,t)\n            }\n\n            var va = d3 * d6 - d5 * d4;\n            if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0)\n            {\n                var t = (d4 - d3) / ((d4 - d3) + (d5 - d6));\n                return p1 + t * (p2 - p1); // bary (0, 1-t, t)\n            }\n\n            __rtype__ denom = 1 / (va + vb + vc);\n            var v = vb * denom;\n            var w = vc * denom;\n            return p0 + v * e01 + w * e02; // bary (1-v-w, v, w)\n        }\n\n        #endregion\n\n        /* __ray3t__ */\n\n        #region __ray3t__ - __ray3t__\n\n        public static __v3t__ GetClosestPointOn(this __ray3t__ ray0, __ray3t__ ray1)\n        {\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            var n = (uDotv * uDotv - 1);\n            // make sure rays are not parallel\n            if (!n.Abs().IsTiny())\n            {\n                var my = (a.Dot(u) * uDotv - a.Dot(v)) / n;\n                return ray1.Origin + my * v;\n            }\n\n            return ray1.Origin;\n        }\n\n        #endregion\n\n        /* __line3t__ */\n\n        #region __line3t__ - __line3t__\n\n        /// <summary>\n        /// Returns the point on line1 which is closest to line0.\n        /// </summary>\n        public static __v3t__ GetClosestPointOn(this __line3t__ line0, __line3t__ line1)\n        {\n            var r0 = line0.__ray3t__;\n            var r1 = line1.__ray3t__;\n\n            if (r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                if (line0.P0.GetMinimalDistanceTo(line1) < line0.P1.GetMinimalDistanceTo(line1))\n                    return line0.P0.GetClosestPointOn(line1);\n                else\n                    return line0.P1.GetClosestPointOn(line1);\n            }\n\n            /* var distance = */\n            r0.GetMinimalDistanceTo(r1, out __rtype__ t0, out __rtype__ t1);\n            if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                return r1.GetPointOnRay(t1);\n\n            var d0 = line0.P0.GetMinimalDistanceTo(line1);\n            var d1 = line0.P1.GetMinimalDistanceTo(line1);\n            var d2 = line1.P0.GetMinimalDistanceTo(line0);\n            var d3 = line1.P1.GetMinimalDistanceTo(line0);\n\n            if (d0 < d1)\n            {\n                if (d0 < d2)\n                    return d0 < d3 ? line0.P0.GetClosestPointOn(line1) : line1.P1;\n                else\n                    return d2 < d3 ? line1.P0 : line1.P1;\n            }\n            else\n            {\n                if (d1 < d2)\n                    return d1 < d3 ? line0.P1.GetClosestPointOn(line1) : line1.P1;\n                else\n                    return d2 < d3 ? line1.P0 : line1.P1;\n            }\n        }\n\n        #endregion\n\n        #region __line3t__ - __plane3t__\n\n        /// <summary>\n        /// Returns the closest point from a line to a plane (point on line).\n        /// </summary>\n        public static __v3t__ GetClosestPointOn(this __plane3t__ plane, __line3t__ line)\n        {\n            var ray = line.__ray3t__;\n            if (ray.Intersects(plane, out __rtype__ t))\n            {\n                var tClamped = t.Clamp(0, 1); // clamp point to line range\n                return ray.GetPointOnRay(tClamped);\n            }\n            else // plane and line are parallel\n            {\n                return line.P0;\n            }\n        }\n        //note: reverse method is not the same (closest point on line)\n\n        #endregion\n\n        #region __line3t__ - __triangle3t__\n\n        /// <summary>\n        /// Returns the closest point from a triangle to a line (point on triangle).\n        /// Note: untested\n        /// </summary>\n        public static __v3t__ GetClosestPointOn(this __line3t__ line, __triangle3t__ triangle)\n        {\n            // test if closest point on triangle plane is inside the triangle (we have the point),\n            // otherwiese find closest edge and take closest point to that edge\n\n            var plane = triangle.Plane;\n            var planePoint = plane.GetClosestPointOn(line);\n\n            // switch to 2d:\n            var trafo = __trafo3t__.FromNormalFrame(plane.Point, plane.Normal);\n            var point2d = trafo.Backward.TransformPos(planePoint).XY;\n            var triangle2d = new __triangle2t__(trafo.Backward.TransformPos(triangle.P0).XY,\n                                            trafo.Backward.TransformPos(triangle.P1).XY,\n                                            trafo.Backward.TransformPos(triangle.P2).XY);\n\n            if (triangle2d.Contains(point2d))\n                return trafo.Forward.TransformPos(point2d.XYO);\n\n            var edgeDistances = new [] {\n                line.GetMinimalDistanceTo(triangle.Line01),\n                line.GetMinimalDistanceTo(triangle.Line12),\n                line.GetMinimalDistanceTo(triangle.Line20)\n            };\n\n            var closestEdge = triangle.GetEdgeLine(edgeDistances.IndexOfMin());\n            return line.GetClosestPointOn(closestEdge);\n        }\n        //note: reverse method is not the same (closest point on line)\n\n        #endregion\n\n        //# }\n    }\n\n    public static partial class GeometryFun\n    {\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var rtype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        //#   var line2t = \"Line2\" + tc;\n        //#   var line3t = \"Line3\" + tc;\n        //#   var plane2t = \"Plane2\" + tc;\n        //#   var plane3t = \"Plane3\" + tc;\n        //#   var ray2t = \"Ray2\" + tc;\n        //#   var ray3t = \"Ray3\" + tc;\n        //#   var circle2t = \"Circle2\" + tc;\n        //#   var circle3t = \"Circle3\" + tc;\n        //#   var quad2t = \"Quad2\" + tc;\n        //#   var quad3t = \"Quad3\" + tc;\n        //#   var range1t = \"Range1\" + tc;\n        //#   var box2t = \"Box2\" + tc;\n        //#   var box3t = \"Box3\" + tc;\n        //#   var hull2t = \"Hull2\" + tc;\n        //#   var hull3t = \"Hull3\" + tc;\n        //#   var sphere3t = \"Sphere3\" + tc;\n        //#   var cylinder3t = \"Cylinder3\" + tc;\n        //#   var ellipse3t = \"Ellipse3\" + tc;\n        //#   var triangle2t = \"Triangle2\" + tc;\n        //#   var triangle3t = \"Triangle3\" + tc;\n        //#   var polygon2t = \"Polygon2\" + tc;\n        //#   var polygon3t = \"Polygon3\" + tc;\n        //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n        #region __range1t__ - __range1t__\n\n        public static __rtype__ GetMinimalDistanceTo(this __range1t__ range0, __range1t__ range1)\n        {\n            if (range0.Min > range1.Max) return range0.Min - range1.Max;\n            if (range0.Max < range1.Min) return range1.Min - range0.Max;\n            return 0;\n        }\n\n        #endregion\n\n        #region __ray2t__ - __ray2t__\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __ray2t__ ray0, __ray2t__ ray1)\n            => ray0.GetMinimalDistanceTo(ray1, out __rtype__ t0, out __rtype__ t1);\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// t0 and t1 hold the correspunding ray parameters.\n        /// if both rays are parallel the t0 and t1 are from the origin of ray1\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __ray2t__ ray0, __ray2t__ ray1, out __rtype__ t0, out __rtype__ t1)\n        {\n            // NOTE: copy of __ray3t__ to __ray3t__ distance\n\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            if (uDotv.Abs().ApproximateEquals(1, Constant<__rtype__>.PositiveTinyValue)) // rays are parallel\n            {\n                // return origin of ray 1\n                t1 = 0;\n                t0 = ray0.GetT(ray1.Origin);\n            }\n            else\n            {\n                // change by lui: added normalization (ortherwise in case the directions are not normalized t0 and t1 are wrong)\n                t1 = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n                t0 = (t1 * uDotv - a.Dot(u)) / ray0.Direction.Length;\n                t1 = t1 / ray1.Direction.Length;\n            }\n\n            return (t1 * ray1.Direction - a - t0 * ray0.Direction).Length;\n        }\n\n        #endregion\n\n        #region __box2t__ - __box2t__\n\n        public static __rtype__ GetMinimalDistanceTo(this __box2t__ box0, __box2t__ box1)\n        {\n            var distX = box0.RangeX.GetMinimalDistanceTo(box1.RangeX);\n            var distY = box0.RangeY.GetMinimalDistanceTo(box1.RangeY);\n\n            if (distX == 0 && distY == 0)\n                return 0;\n            else if (distX == 0)\n                return distY;\n            else if (distY == 0)\n                return distX;\n\n            if (box0.Min.X > box1.Max.X) // 1 is left\n            {\n                if (box0.Min.Y > box1.Max.Y) // 1 is top left\n                    return (box0.Corner(0) - box1.Corner(3)).Length;\n                else // 1 is bottom left\n                    return (box0.Corner(2) - box1.Corner(1)).Length;\n            }\n            else // 1 is right\n            {\n                if (box0.Min.Y > box1.Max.Y) // 1 is top right\n                    return (box0.Corner(1) - box1.Corner(2)).Length;\n                else // 1 is bottom right\n                    return (box0.Corner(3) - box1.Corner(0)).Length;\n            }\n        }\n\n        #endregion\n\n        #region __v2t__ - __line2t__\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __v2t__ point, __line2t__ line)\n            => point.DistanceToLine(line.P0, line.P1);\n\n        #endregion\n\n        #region __v2t__ - __triangle2t__\n\n        /// <summary>\n        /// returns the minimal distance between the point and the triangle\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __v2t__ point, __triangle2t__ t)\n            => Triangle.Distance(t.P0, t.P1, t.P2, point);\n\n        #endregion\n\n        #region __line2t__ - __line2t__\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __line2t__ l0, __line2t__ l1)\n        {\n            var r0 = l0.__ray2t__;\n            var r1 = l1.__ray2t__;\n\n            if (!r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                var distance = r0.GetMinimalDistanceTo(r1, out __rtype__ t0, out __rtype__ t1);\n\n                if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                    return distance;\n            }\n\n            // lines are parallel or t0 and t1 are outside of the line\n            return Fun.Min(l0.P0.GetMinimalDistanceTo(l1), l0.P1.GetMinimalDistanceTo(l1),\n                l1.P0.GetMinimalDistanceTo(l0), l1.P1.GetMinimalDistanceTo(l0));\n        }\n        #endregion\n\n        #region __v3t__ - __line3t__\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Line\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __v3t__ point, __line3t__ line)\n            => point.DistanceToLine(line.P0, line.P1);\n\n        /// <summary>\n        /// Returns the minimal distance between the point and the Line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __line3t__ line, __v3t__ point)\n            => point.GetMinimalDistanceTo(line);\n\n        #endregion\n\n        #region __v3t__ - __ray3t__\n\n        /*  Performance Test .........................................................................\n                Faster Method:                                      __v3t__.MinimalDistanceTo(__ray3t__)\n                __v3t__.MinimalDistanceTo(__ray3t__):                       1,841s\n                (__v3t__ - __v3t__.GetClosestPointOn(__ray3t__)).Length:        3,058s\n                Total Executions:                                   10000000\n                Errors outside tolerance(1E-7):                     0\n                Average Squared-Distance of Results:                2,24116481902135E-32\n                Speedup-factor:                                     1,66\n         */\n\n        /// <summary>\n        /// Returns the minimal distance between the point and the ray.\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __v3t__ point, __ray3t__ ray)\n        {\n            var a = point - ray.Origin;\n            __rtype__ lu2 = ray.Direction.LengthSquared;\n            __rtype__ acu2 = Vec.Cross(a, ray.Direction).LengthSquared;\n\n            return Fun.Sqrt(acu2 / lu2);\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __ray3t__ ray, __v3t__ point)\n            => point.GetMinimalDistanceTo(ray);\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// t holds the ray parameter for the closest point.\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __v3t__ point, __ray3t__ ray, out __rtype__ t)\n        {\n            var a = point - ray.Origin;\n            var lu2 = ray.Direction.LengthSquared;\n            var acu2 = Vec.Cross(a, ray.Direction).LengthSquared;\n\n            var NormalPart2 = acu2 / lu2;\n            var ParallelPart2 = lu2 - NormalPart2;\n\n            t = Fun.Sqrt(ParallelPart2 / lu2);\n            return Fun.Sqrt(NormalPart2);\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the Ray.\n        /// t holds the ray parameter for the closest point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __ray3t__ ray, __v3t__ point, out __rtype__ t)\n            => point.GetMinimalDistanceTo(ray, out t);\n\n        #endregion\n\n        #region __v3t__ - __plane3t__\n\n        /// <summary>\n        /// Returns the minimal distance (unsigned) between the point and the plane.\n        /// Use __plane3t__.Height to compute the signed height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __v3t__ point, __plane3t__ plane)\n            => plane.Height(point).Abs();\n\n        /// <summary>\n        /// Returns the minimal distance (unsigned) between the point and the plane.\n        /// Use __plane3t__.Height to compute the signed height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __plane3t__ plane, __v3t__ point)\n            => point.GetMinimalDistanceTo(plane);\n\n        #endregion\n\n        #region __v3t__ - __box3t__\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __v3t__ point, __box3t__ box)\n        {\n            var outside = box.OutsideFlags(point); if (outside == 0) return 0;\n\n            var d = __v3t__.Zero;\n\n            if ((outside & Box.Flags.X) != 0)\n            {\n                if ((outside & Box.Flags.MaxX) != 0) d.X = point.X - box.Max.X;\n                else if ((outside & Box.Flags.MinX) != 0) d.X = point.X - box.Min.X;\n            }\n\n            if ((outside & Box.Flags.Y) != 0)\n            {\n                if ((outside & Box.Flags.MaxY) != 0) d.Y = point.Y - box.Max.Y;\n                else if ((outside & Box.Flags.MinY) != 0) d.Y = point.Y - box.Min.Y;\n            }\n\n            if ((outside & Box.Flags.Z) != 0)\n            {\n                if ((outside & Box.Flags.MaxZ) != 0) d.Z = point.Z - box.Max.Z;\n                else if ((outside & Box.Flags.MinZ) != 0) d.Z = point.Z - box.Min.Z;\n            }\n\n            return d.Length;\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __box3t__ box, __v3t__ point)\n            => point.GetMinimalDistanceTo(box);\n\n        #endregion\n\n        #region __v3t__ - __triangle3t__\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __v3t__ point, __triangle3t__ triangle)\n            => Triangle.Distance(triangle.P0, triangle.P1, triangle.P2, point);\n\n        /// <summary>\n        /// returns the minimal distance between the point and the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __triangle3t__ triangle, __v3t__ point)\n            => point.GetMinimalDistanceTo(triangle);\n\n        #endregion\n\n        #region __line3t__ - __line3t__\n\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __line3t__ l0, __line3t__ l1)\n        {\n            var r0 = l0.__ray3t__;\n            var r1 = l1.__ray3t__;\n\n            if (!r0.IsParallelTo(r1)) // t1 and t0 of following computation are invalid if lines are parallel\n            {\n                var distance = r0.GetMinimalDistanceTo(r1, out __rtype__ t0, out __rtype__ t1);\n\n                if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n                    return distance;\n            }\n\n            // lines are parallel or t0 and t1 are outside of the line\n            return Fun.Min(l0.P0.GetMinimalDistanceTo(l1), l0.P1.GetMinimalDistanceTo(l1),\n                l1.P0.GetMinimalDistanceTo(l0), l1.P1.GetMinimalDistanceTo(l0));\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the given lines.\n        /// points holds the centroid of the shortest connection between the lines\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __line3t__ l0, __line3t__ l1, out __v3t__ point)\n        {\n            var r0 = l0.__ray3t__;\n            var r1 = l1.__ray3t__;\n\n            var distance = r0.GetMinimalDistanceTo(r1, out __rtype__ t0, out __rtype__ t1);\n\n            if (t0 >= 0 && t0 <= 1 && t1 >= 0 && t1 <= 1)\n            {\n                point = __half__ * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t1));\n                return distance;\n            }\n            else\n            {\n                __rtype__ t;\n                if (t0 < 0 || t0 > 1)\n                {\n                    if (t0 < 0) t0 = 0;\n                    else t0 = 1;\n\n                    distance = r0.GetPointOnRay(t0).GetMinimalDistanceTo(r1, out t);\n                    if (t >= 0 && t <= 1)\n                    {\n                        point = __half__ * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t));\n                        return distance;\n                    }\n                }\n\n                if (t1 < 0 || t1 > 1)\n                {\n                    if (t1 < 0) t1 = 0;\n                    else t1 = 1;\n\n                    distance = r1.GetPointOnRay(t1).GetMinimalDistanceTo(r0, out t);\n                    if (t >= 0 && t <= 1)\n                    {\n                        point = __half__ * (r0.GetPointOnRay(t) + r1.GetPointOnRay(t1));\n                        return distance;\n                    }\n                }\n\n            }\n\n            point = __half__ * (r0.GetPointOnRay(t0) + r1.GetPointOnRay(t1));\n            return (r0.GetPointOnRay(t0) - r1.GetPointOnRay(t1)).Length;\n        }\n\n        #endregion\n\n        #region __line3t__ - __plane3t__\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __line3t__ line, __plane3t__ plane)\n            => plane.Height(GeometryFun.GetClosestPointOn(plane, line)).Abs();\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __plane3t__ plane, __line3t__ line)\n            => line.GetMinimalDistanceTo(plane);\n\n        #endregion\n\n        #region __ray3t__ - __line3t__\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __ray3t__ ray, __line3t__ line)\n        {\n            var r1 = line.__ray3t__;\n\n            var distance = ray.GetMinimalDistanceTo(r1, out __rtype__ t0, out __rtype__ t1);\n\n            if (t1 >= 0 && t1 <= 1) return distance;\n            else\n            {\n                if (t1 < 0) t1 = 0;\n                if (t1 > 1) t1 = 1;\n\n                var p1 = r1.GetPointOnRay(t1);\n                return p1.GetMinimalDistanceTo(ray);\n            }\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __line3t__ line, __ray3t__ ray)\n            => ray.GetMinimalDistanceTo(line);\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// t holds the correspoinding ray parameter.\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __ray3t__ ray, __line3t__ line, out __rtype__ t)\n        {\n            var r1 = line.__ray3t__;\n\n            var distance = ray.GetMinimalDistanceTo(r1, out __rtype__ t0, out __rtype__ t1);\n\n            if (t1 >= 0 && t1 <= 1)\n            {\n                t = t0;\n                return distance;\n            }\n            else\n            {\n                if (t1 < 0) t1 = 0;\n                if (t1 > 1) t1 = 1;\n\n                var p1 = r1.GetPointOnRay(t1);\n                return p1.GetMinimalDistanceTo(ray, out t);\n            }\n        }\n\n        /// <summary>\n        /// returns the minimal distance between the ray and the line.\n        /// t holds the correspoinding ray parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __line3t__ line, __ray3t__ ray, out __rtype__ t)\n            => ray.GetMinimalDistanceTo(line, out t);\n\n        #endregion\n\n        #region __ray3t__ - __ray3t__\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetMinimalDistanceTo(this __ray3t__ ray0, __ray3t__ ray1)\n            => ray0.GetMinimalDistanceTo(ray1, out __rtype__ t0, out __rtype__ t1);\n\n        /// <summary>\n        /// returns the minimal distance between the given rays.\n        /// t0 and t1 hold the correspunding ray parameters.\n        /// if both rays are parallel the t0 and t1 are from the origin of ray1\n        /// </summary>\n        public static __rtype__ GetMinimalDistanceTo(this __ray3t__ ray0, __ray3t__ ray1, out __rtype__ t0, out __rtype__ t1)\n        {\n            // TODO: computation probalby possible without Direction.Normalized and Direction.Length\n\n            var a = ray0.Origin - ray1.Origin;\n            var u = ray0.Direction.Normalized;\n            var v = ray1.Direction.Normalized;\n\n            var uDotv = u.Dot(v);\n            if (uDotv.Abs().ApproximateEquals(1, Constant<__rtype__>.PositiveTinyValue)) // rays are parallel\n            {\n                // return origin of ray 1\n                t1 = 0;\n                t0 = ray0.GetTOfProjectedPoint(ray1.Origin);\n            }\n            else\n            {\n                // change by lui: added normalization (ortherwise in case the directions are not normalized t0 and t1 are wrong)\n                t1 = (a.Dot(u) * uDotv - a.Dot(v)) / (uDotv * uDotv - 1);\n                t0 = (t1 * uDotv - a.Dot(u)) / ray0.Direction.Length;\n                t1 = t1 / ray1.Direction.Length;\n            }\n\n            return (t1 * ray1.Direction - a - t0 * ray0.Direction).Length;\n        }\n\n        #endregion\n\n        //# }\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Capsule/Capsule3_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Capsule3f\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Capsule3f : IEquatable<Capsule3f>, IValidity, IBoundingBox3f\n    {\n        [DataMember]\n        public V3f P0;\n        [DataMember]\n        public V3f P1;\n        [DataMember]\n        public float Radius;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Capsule3f(V3f p0, V3f p1, float radius)\n        {\n            P0 = p0;\n            P1 = p1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Capsule3f(Line3f axis, float radius)\n        {\n            P0 = axis.P0;\n            P1 = axis.P1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Capsule3f(Capsule3f capsule)\n        {\n            P0 = capsule.P0;\n            P1 = capsule.P1;\n            Radius = capsule.Radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Capsule3f(Capsule3d capsule)\n        {\n            P0 = (V3f)capsule.P0;\n            P1 = (V3f)capsule.P1;\n            Radius = (float)capsule.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Capsule3f(Capsule3d c)\n            => new Capsule3f(c);\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Capsule3f Invalid = new Capsule3f(V3f.NaN, V3f.NaN, -1);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0;\n        }\n\n        public readonly Line3f Axis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Line3f(P0, P1);\n        }\n\n        public readonly Cylinder3f Cylider\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Cylinder3f(P0, P1, Radius);\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        public readonly Box3f BoundingBox3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Box3f(new Sphere3f(P0, Radius).BoundingBox3f, new Sphere3f(P1, Radius).BoundingBox3f);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Capsule3f other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Capsule3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Capsule3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Capsule3f(V3f.Parse(x[0]), V3f.Parse(x[1]), float.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    #region Capsule3d\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Capsule3d : IEquatable<Capsule3d>, IValidity, IBoundingBox3d\n    {\n        [DataMember]\n        public V3d P0;\n        [DataMember]\n        public V3d P1;\n        [DataMember]\n        public double Radius;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Capsule3d(V3d p0, V3d p1, double radius)\n        {\n            P0 = p0;\n            P1 = p1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Capsule3d(Line3d axis, double radius)\n        {\n            P0 = axis.P0;\n            P1 = axis.P1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Capsule3d(Capsule3d capsule)\n        {\n            P0 = capsule.P0;\n            P1 = capsule.P1;\n            Radius = capsule.Radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Capsule3d(Capsule3f capsule)\n        {\n            P0 = (V3d)capsule.P0;\n            P1 = (V3d)capsule.P1;\n            Radius = (double)capsule.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Capsule3d(Capsule3f c)\n            => new Capsule3d(c);\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Capsule3d Invalid = new Capsule3d(V3d.NaN, V3d.NaN, -1);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0;\n        }\n\n        public readonly Line3d Axis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Line3d(P0, P1);\n        }\n\n        public readonly Cylinder3d Cylider\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Cylinder3d(P0, P1, Radius);\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        public readonly Box3d BoundingBox3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Box3d(new Sphere3d(P0, Radius).BoundingBox3d, new Sphere3d(P1, Radius).BoundingBox3d);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Capsule3d other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Capsule3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Capsule3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Capsule3d(V3d.Parse(x[0]), V3d.Parse(x[1]), double.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Capsule/Capsule3_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Capsule3\" + tc;\n    //#   var type2 = \"Capsule3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var line3t = \"Line3\" + tc;\n    //#   var cylinder3t = \"Cylinder3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var sphere3t = \"Sphere3\" + tc;\n    //#   var iboundingbox = \"IBoundingBox3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var fourbythree = isDouble ? \"(4.0 / 3.0)\" : \"(4.0f / 3.0f)\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    #region __type__\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, IValidity, __iboundingbox__\n    {\n        [DataMember]\n        public __v3t__ P0;\n        [DataMember]\n        public __v3t__ P1;\n        [DataMember]\n        public __ftype__ Radius;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v3t__ p0, __v3t__ p1, __ftype__ radius)\n        {\n            P0 = p0;\n            P1 = p1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__line3t__ axis, __ftype__ radius)\n        {\n            P0 = axis.P0;\n            P1 = axis.P1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ capsule)\n        {\n            P0 = capsule.P0;\n            P1 = capsule.P1;\n            Radius = capsule.Radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ capsule)\n        {\n            P0 = (__v3t__)capsule.P0;\n            P1 = (__v3t__)capsule.P1;\n            Radius = (__ftype__)capsule.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ c)\n            => new __type__(c);\n\n        #endregion\n\n        #region Constants\n\n        public static readonly __type__ Invalid = new __type__(__v3t__.NaN, __v3t__.NaN, -1);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0;\n        }\n\n        public readonly __line3t__ Axis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __line3t__(P0, P1);\n        }\n\n        public readonly __cylinder3t__ Cylider\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __cylinder3t__(P0, P1, Radius);\n        }\n\n        #endregion\n\n        #region __iboundingbox__ Members\n\n        public readonly __box3t__ BoundingBox3__tc__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __box3t__(new __sphere3t__(P0, Radius).BoundingBox3__tc__, new __sphere3t__(P1, Radius).BoundingBox3__tc__);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__v3t__.Parse(x[0]), __v3t__.Parse(x[1]), __ftype__.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Circle/Circle2_auto.cs",
    "content": "/*\n    Copyright 2006-2020. The Aardvark Platform Team.\n\n        https://aardvark.graphics\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n*/\nusing System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Circle2f\n\n    /// <summary>\n    /// A two dimensional circle represented by center and radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Circle2f : IEquatable<Circle2f>, IBoundingBox2f, IValidity\n    {\n        [DataMember]\n        public V2f Center;\n\n        [DataMember]\n        public float Radius;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates circle from center and radius.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2f(V2f center, float radius)\n        {\n            Center = center;\n            Radius = radius;\n        }\n\n        /// <summary>\n        /// Creates circle from center and point on circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2f(V2f center, V2f pointOnCircle)\n        {\n            Center = center;\n            Radius = (pointOnCircle - center).Length;\n        }\n\n        /// <summary>\n        /// Creates circle from three points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2f(V2f a, V2f b, V2f c)\n        {\n            var l0 = new Plane2f((b - a).Normalized, (a + b) * 0.5f);\n            var l1 = new Plane2f((c - b).Normalized, (b + c) * 0.5f);\n            if (l0.Intersects(l1, out Center))\n            {\n                Radius = (a - Center).Length;\n            }\n            else\n            {\n                throw new Exception(\"Cannot construct circle because given points are collinear.\");\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Circle2f\"/> from another <see cref=\"Circle2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2f(Circle2f o)\n        {\n            Center = o.Center;\n            Radius = o.Radius;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Circle2f\"/> from a <see cref=\"Circle2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2f(Circle2d o)\n        {\n            Center = (V2f)o.Center;\n            Radius = (float)o.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Circle2f(Circle2d c)\n            => new Circle2f(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Circle2f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle2f(V2f.Zero, 0);\n        }\n\n        public static Circle2f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle2f(V2f.NaN, -1);\n        }\n\n        public static Circle2f Unit\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle2f(V2f.Zero, 1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0 || float.IsNaN(Radius) || Center.IsNaN;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0 && !Center.IsNaN;\n        }\n\n        public readonly float RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius;\n        }\n\n        public readonly float Circumference\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * Radius * ConstantF.Pi;\n        }\n\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius * ConstantF.Pi;\n        }\n\n        public readonly Box2f InscribedSquare\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var a = Fun.Sqrt(RadiusSquared * 0.5f);\n                return new Box2f(new V2f(-a), new V2f(a));\n            }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Circle2f a, Circle2f b)\n            => (a.Center == b.Center) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Circle2f a, Circle2f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Circle2f other)\n            => Center.Equals(other.Center) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Circle2f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Center, Radius);\n\n        /// <summary>\n        /// Parses Circle2f from a string created with Circle2f.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Circle2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Circle2f(V2f.Parse(x[0]), float.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region IBoundingBox2f Members\n\n        public readonly Box2f BoundingBox2f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Box2f(\n                        new V2f(Center.X - Radius, Center.Y - Radius),\n                        new V2f(Center.X + Radius, Center.Y + Radius)\n                   );\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Circle2f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Circle2f a, Circle2f b, float tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Circle2f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Circle2f a, Circle2f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Circle2d\n\n    /// <summary>\n    /// A two dimensional circle represented by center and radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Circle2d : IEquatable<Circle2d>, IBoundingBox2d, IValidity\n    {\n        [DataMember]\n        public V2d Center;\n\n        [DataMember]\n        public double Radius;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates circle from center and radius.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2d(V2d center, double radius)\n        {\n            Center = center;\n            Radius = radius;\n        }\n\n        /// <summary>\n        /// Creates circle from center and point on circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2d(V2d center, V2d pointOnCircle)\n        {\n            Center = center;\n            Radius = (pointOnCircle - center).Length;\n        }\n\n        /// <summary>\n        /// Creates circle from three points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2d(V2d a, V2d b, V2d c)\n        {\n            var l0 = new Plane2d((b - a).Normalized, (a + b) * 0.5);\n            var l1 = new Plane2d((c - b).Normalized, (b + c) * 0.5);\n            if (l0.Intersects(l1, out Center))\n            {\n                Radius = (a - Center).Length;\n            }\n            else\n            {\n                throw new Exception(\"Cannot construct circle because given points are collinear.\");\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Circle2d\"/> from another <see cref=\"Circle2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2d(Circle2d o)\n        {\n            Center = o.Center;\n            Radius = o.Radius;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Circle2d\"/> from a <see cref=\"Circle2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle2d(Circle2f o)\n        {\n            Center = (V2d)o.Center;\n            Radius = (double)o.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Circle2d(Circle2f c)\n            => new Circle2d(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Circle2d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle2d(V2d.Zero, 0);\n        }\n\n        public static Circle2d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle2d(V2d.NaN, -1);\n        }\n\n        public static Circle2d Unit\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle2d(V2d.Zero, 1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0 || double.IsNaN(Radius) || Center.IsNaN;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0 && !Center.IsNaN;\n        }\n\n        public readonly double RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius;\n        }\n\n        public readonly double Circumference\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * Radius * Constant.Pi;\n        }\n\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius * Constant.Pi;\n        }\n\n        public readonly Box2d InscribedSquare\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var a = Fun.Sqrt(RadiusSquared * 0.5);\n                return new Box2d(new V2d(-a), new V2d(a));\n            }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Circle2d a, Circle2d b)\n            => (a.Center == b.Center) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Circle2d a, Circle2d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Circle2d other)\n            => Center.Equals(other.Center) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Circle2d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Center, Radius);\n\n        /// <summary>\n        /// Parses Circle2d from a string created with Circle2d.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Circle2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Circle2d(V2d.Parse(x[0]), double.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region IBoundingBox2d Members\n\n        public readonly Box2d BoundingBox2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Box2d(\n                        new V2d(Center.X - Radius, Center.Y - Radius),\n                        new V2d(Center.X + Radius, Center.Y + Radius)\n                   );\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Circle2d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Circle2d a, Circle2d b, double tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Circle2d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Circle2d a, Circle2d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Circle/Circle2_template.cs",
    "content": "/*\n    Copyright 2006-2020. The Aardvark Platform Team.\n\n        https://aardvark.graphics\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n*/\nusing System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Circle2\" + tc;\n    //#   var type2 = \"Circle2\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var box2t = \"Box2\" + tc;\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var iboundingbox = \"IBoundingBox2\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    #region __type__\n\n    /// <summary>\n    /// A two dimensional circle represented by center and radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, __iboundingbox__, IValidity\n    {\n        [DataMember]\n        public __v2t__ Center;\n\n        [DataMember]\n        public __ftype__ Radius;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates circle from center and radius.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v2t__ center, __ftype__ radius)\n        {\n            Center = center;\n            Radius = radius;\n        }\n\n        /// <summary>\n        /// Creates circle from center and point on circle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v2t__ center, __v2t__ pointOnCircle)\n        {\n            Center = center;\n            Radius = (pointOnCircle - center).Length;\n        }\n\n        /// <summary>\n        /// Creates circle from three points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v2t__ a, __v2t__ b, __v2t__ c)\n        {\n            var l0 = new __plane2t__((b - a).Normalized, (a + b) * __half__);\n            var l1 = new __plane2t__((c - b).Normalized, (b + c) * __half__);\n            if (l0.Intersects(l1, out Center))\n            {\n                Radius = (a - Center).Length;\n            }\n            else\n            {\n                throw new Exception(\"Cannot construct circle because given points are collinear.\");\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> from another <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ o)\n        {\n            Center = o.Center;\n            Radius = o.Radius;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> from a <see cref=\"__type2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ o)\n        {\n            Center = (__v2t__)o.Center;\n            Radius = (__ftype__)o.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ c)\n            => new __type__(c);\n\n        #endregion\n\n        #region Constants\n\n        public static __type__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v2t__.Zero, 0);\n        }\n\n        public static __type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v2t__.NaN, -1);\n        }\n\n        public static __type__ Unit\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v2t__.Zero, 1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0 || __ftype__.IsNaN(Radius) || Center.IsNaN;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0 && !Center.IsNaN;\n        }\n\n        public readonly __ftype__ RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius;\n        }\n\n        public readonly __ftype__ Circumference\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * Radius * __pi__;\n        }\n\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius * __pi__;\n        }\n\n        public readonly __box2t__ InscribedSquare\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var a = Fun.Sqrt(RadiusSquared * __half__);\n                return new __box2t__(new __v2t__(-a), new __v2t__(a));\n            }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => (a.Center == b.Center) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Center.Equals(other.Center) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Center, Radius);\n\n        /// <summary>\n        /// Parses __type__ from a string created with __type__.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__v2t__.Parse(x[0]), __ftype__.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region __iboundingbox__ Members\n\n        public readonly __box2t__ BoundingBox2__tc__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __box2t__(\n                        new __v2t__(Center.X - Radius, Center.Y - Radius),\n                        new __v2t__(Center.X + Radius, Center.Y + Radius)\n                   );\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Circle/Circle3_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Circle3f\n\n    /// <summary>\n    /// A circle in 3-space represented by its center, normal (normalized), and a radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Circle3f : IEquatable<Circle3f>, IBoundingBox3f, IValidity\n    {\n        [DataMember]\n        public V3f Center;\n\n        [DataMember]\n        public V3f Normal;\n\n        [DataMember]\n        public float Radius;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a circle from it's center, a normal vector (normalized) and a radius.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle3f(V3f center, V3f normal, float radius)\n        {\n            Center = center;\n            Normal = normal;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle3f(Circle3f circle)\n\t\t{\n            Center = circle.Center;\n            Normal = circle.Normal;\n            Radius = circle.Radius;\n\t\t}\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle3f(Circle3d circle)\n        {\n            Center = (V3f)circle.Center;\n            Normal = (V3f)circle.Normal;\n            Radius = (float)circle.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Circle3f(Circle3d c)\n            => new Circle3f(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Circle3f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle3f(V3f.Zero, V3f.ZAxis, 0);\n        }\n\n        public static Circle3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle3f(V3f.NaN, V3f.NaN, -1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly float RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius.Square();\n        }\n\n        public readonly float Circumference\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * Radius * ConstantF.Pi;\n        }\n\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => RadiusSquared * ConstantF.Pi;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0;\n        }\n\n        /// <summary>\n        /// Returns a point on the circumference (AxisU).\n        /// </summary>\n        public readonly V3f Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Center + AxisU * Radius;\n        }\n\n        /// <summary>\n        /// Returns an axis aligned vector pointing from the center to the circumference.\n        /// </summary>\n        public readonly V3f AxisU\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                V3f dir = Normal.Dot(V3f.XAxis).Abs() > 0.9f ? V3f.YAxis : V3f.XAxis;\n                var pdir = Normal.Cross(dir);\n                return pdir.Normalized * Radius;\n            }\n        }\n\n        /// <summary>\n        /// Returns an axis aligned vector pointing from the center to the circumference.\n        /// </summary>\n        public readonly V3f AxisV\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var axisU = AxisU;\n                return AxisU.Cross(Normal).Normalized * Radius;\n            }\n        }\n\n        /// <summary>\n        /// Return an IEnumerable of points on the circle's circumference, optionally repeating the first point as the last.\n        /// </summary>\n        /// <param name=\"tesselation\">number of distinct points to generate. the actual number of points returned depends on the <para>duplicateClosePoint</para> parameter. must be 3 or larger.</param>\n        /// <param name=\"duplicateClosePoint\">if true, the first point is repeated as the last</param>\n        /// <returns>IEnumerable of points on the circle's circumference. if diplicateClosePoint is true, <para>tesselation</para>+1 points are returned.</returns>\n        public readonly IEnumerable<V3f> Points(int tesselation, bool duplicateClosePoint = false)\n\t\t{\n\t\t\tif (tesselation < 3)\n\t\t\t\tthrow new ArgumentOutOfRangeException(\"tesselation\", \"tesselation must be at least 3.\");\n\n\t\t\tvar off = 0;\n\t\t\tif (duplicateClosePoint)\n\t\t\t\toff = 1;\n\t\t\tfor (int i = 0; i < tesselation + off; i++)\n\t\t\t{\n\t\t\t\tvar angle = ((float)i) / tesselation * ConstantF.PiTimesTwo;\n\t\t\t\tyield return Center + AxisU * Fun.Cos(angle) + AxisV * Fun.Sin(angle);\n\t\t\t}\n\t\t}\n\n        public readonly Plane3f Plane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(Normal, Center);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f GetPoint(float angle)\n            => Center + AxisU * angle.Cos() + AxisV * angle.Sin();\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Circle3f a, Circle3f b)\n            => (a.Center == b.Center) && (a.Normal == b.Normal) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Circle3f a, Circle3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Circle3f other)\n            => Center.Equals(other.Center) && Normal.Equals(other.Normal) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Circle3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Center, Normal, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Circle3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Circle3f(V3f.Parse(x[0]), V3f.Parse(x[1]), float.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        public readonly Box3f BoundingBox3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var u = AxisU; var v = AxisV;\n                return new Box3f(Center + u, Center - u, Center + v, Center - v);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Circle3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Circle3f a, Circle3f b, float tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Circle3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Circle3f a, Circle3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Circle3d\n\n    /// <summary>\n    /// A circle in 3-space represented by its center, normal (normalized), and a radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Circle3d : IEquatable<Circle3d>, IBoundingBox3d, IValidity\n    {\n        [DataMember]\n        public V3d Center;\n\n        [DataMember]\n        public V3d Normal;\n\n        [DataMember]\n        public double Radius;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a circle from it's center, a normal vector (normalized) and a radius.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle3d(V3d center, V3d normal, double radius)\n        {\n            Center = center;\n            Normal = normal;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle3d(Circle3d circle)\n\t\t{\n            Center = circle.Center;\n            Normal = circle.Normal;\n            Radius = circle.Radius;\n\t\t}\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Circle3d(Circle3f circle)\n        {\n            Center = (V3d)circle.Center;\n            Normal = (V3d)circle.Normal;\n            Radius = (double)circle.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Circle3d(Circle3f c)\n            => new Circle3d(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Circle3d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle3d(V3d.Zero, V3d.ZAxis, 0);\n        }\n\n        public static Circle3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle3d(V3d.NaN, V3d.NaN, -1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly double RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius.Square();\n        }\n\n        public readonly double Circumference\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * Radius * Constant.Pi;\n        }\n\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => RadiusSquared * Constant.Pi;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0;\n        }\n\n        /// <summary>\n        /// Returns a point on the circumference (AxisU).\n        /// </summary>\n        public readonly V3d Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Center + AxisU * Radius;\n        }\n\n        /// <summary>\n        /// Returns an axis aligned vector pointing from the center to the circumference.\n        /// </summary>\n        public readonly V3d AxisU\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                V3d dir = Normal.Dot(V3d.XAxis).Abs() > 0.9 ? V3d.YAxis : V3d.XAxis;\n                var pdir = Normal.Cross(dir);\n                return pdir.Normalized * Radius;\n            }\n        }\n\n        /// <summary>\n        /// Returns an axis aligned vector pointing from the center to the circumference.\n        /// </summary>\n        public readonly V3d AxisV\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var axisU = AxisU;\n                return AxisU.Cross(Normal).Normalized * Radius;\n            }\n        }\n\n        /// <summary>\n        /// Return an IEnumerable of points on the circle's circumference, optionally repeating the first point as the last.\n        /// </summary>\n        /// <param name=\"tesselation\">number of distinct points to generate. the actual number of points returned depends on the <para>duplicateClosePoint</para> parameter. must be 3 or larger.</param>\n        /// <param name=\"duplicateClosePoint\">if true, the first point is repeated as the last</param>\n        /// <returns>IEnumerable of points on the circle's circumference. if diplicateClosePoint is true, <para>tesselation</para>+1 points are returned.</returns>\n        public readonly IEnumerable<V3d> Points(int tesselation, bool duplicateClosePoint = false)\n\t\t{\n\t\t\tif (tesselation < 3)\n\t\t\t\tthrow new ArgumentOutOfRangeException(\"tesselation\", \"tesselation must be at least 3.\");\n\n\t\t\tvar off = 0;\n\t\t\tif (duplicateClosePoint)\n\t\t\t\toff = 1;\n\t\t\tfor (int i = 0; i < tesselation + off; i++)\n\t\t\t{\n\t\t\t\tvar angle = ((double)i) / tesselation * Constant.PiTimesTwo;\n\t\t\t\tyield return Center + AxisU * Fun.Cos(angle) + AxisV * Fun.Sin(angle);\n\t\t\t}\n\t\t}\n\n        public readonly Plane3d Plane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(Normal, Center);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d GetPoint(double angle)\n            => Center + AxisU * angle.Cos() + AxisV * angle.Sin();\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Circle3d a, Circle3d b)\n            => (a.Center == b.Center) && (a.Normal == b.Normal) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Circle3d a, Circle3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Circle3d other)\n            => Center.Equals(other.Center) && Normal.Equals(other.Normal) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Circle3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Center, Normal, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Circle3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Circle3d(V3d.Parse(x[0]), V3d.Parse(x[1]), double.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        public readonly Box3d BoundingBox3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var u = AxisU; var v = AxisV;\n                return new Box3d(Center + u, Center - u, Center + v, Center - v);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Circle3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Circle3d a, Circle3d b, double tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Circle3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Circle3d a, Circle3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Circle/Circle3_template.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Circle3\" + tc;\n    //#   var type2 = \"Circle3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var iboundingbox = \"IBoundingBox3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var dotnine = isDouble ? \"0.9\" : \"0.9f\";\n    //#   var constant = isDouble ? \"Constant\" : \"ConstantF\";\n    #region __type__\n\n    /// <summary>\n    /// A circle in 3-space represented by its center, normal (normalized), and a radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, __iboundingbox__, IValidity\n    {\n        [DataMember]\n        public __v3t__ Center;\n\n        [DataMember]\n        public __v3t__ Normal;\n\n        [DataMember]\n        public __ftype__ Radius;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a circle from it's center, a normal vector (normalized) and a radius.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v3t__ center, __v3t__ normal, __ftype__ radius)\n        {\n            Center = center;\n            Normal = normal;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ circle)\n\t\t{\n            Center = circle.Center;\n            Normal = circle.Normal;\n            Radius = circle.Radius;\n\t\t}\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ circle)\n        {\n            Center = (__v3t__)circle.Center;\n            Normal = (__v3t__)circle.Normal;\n            Radius = (__ftype__)circle.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ c)\n            => new __type__(c);\n\n        #endregion\n\n        #region Constants\n\n        public static __type__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v3t__.Zero, __v3t__.ZAxis, 0);\n        }\n\n        public static __type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v3t__.NaN, __v3t__.NaN, -1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly __ftype__ RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius.Square();\n        }\n\n        public readonly __ftype__ Circumference\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * Radius * __constant__.Pi;\n        }\n\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => RadiusSquared * __constant__.Pi;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0;\n        }\n\n        /// <summary>\n        /// Returns a point on the circumference (AxisU).\n        /// </summary>\n        public readonly __v3t__ Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Center + AxisU * Radius;\n        }\n\n        /// <summary>\n        /// Returns an axis aligned vector pointing from the center to the circumference.\n        /// </summary>\n        public readonly __v3t__ AxisU\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                __v3t__ dir = Normal.Dot(__v3t__.XAxis).Abs() > __dotnine__ ? __v3t__.YAxis : __v3t__.XAxis;\n                var pdir = Normal.Cross(dir);\n                return pdir.Normalized * Radius;\n            }\n        }\n\n        /// <summary>\n        /// Returns an axis aligned vector pointing from the center to the circumference.\n        /// </summary>\n        public readonly __v3t__ AxisV\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var axisU = AxisU;\n                return AxisU.Cross(Normal).Normalized * Radius;\n            }\n        }\n\n        /// <summary>\n        /// Return an IEnumerable of points on the circle's circumference, optionally repeating the first point as the last.\n        /// </summary>\n        /// <param name=\"tesselation\">number of distinct points to generate. the actual number of points returned depends on the <para>duplicateClosePoint</para> parameter. must be 3 or larger.</param>\n        /// <param name=\"duplicateClosePoint\">if true, the first point is repeated as the last</param>\n        /// <returns>IEnumerable of points on the circle's circumference. if diplicateClosePoint is true, <para>tesselation</para>+1 points are returned.</returns>\n        public readonly IEnumerable<__v3t__> Points(int tesselation, bool duplicateClosePoint = false)\n\t\t{\n\t\t\tif (tesselation < 3)\n\t\t\t\tthrow new ArgumentOutOfRangeException(\"tesselation\", \"tesselation must be at least 3.\");\n\n\t\t\tvar off = 0;\n\t\t\tif (duplicateClosePoint)\n\t\t\t\toff = 1;\n\t\t\tfor (int i = 0; i < tesselation + off; i++)\n\t\t\t{\n\t\t\t\tvar angle = ((__ftype__)i) / tesselation * __constant__.PiTimesTwo;\n\t\t\t\tyield return Center + AxisU * Fun.Cos(angle) + AxisV * Fun.Sin(angle);\n\t\t\t}\n\t\t}\n\n        public readonly __plane3t__ Plane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(Normal, Center);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __v3t__ GetPoint(__ftype__ angle)\n            => Center + AxisU * angle.Cos() + AxisV * angle.Sin();\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => (a.Center == b.Center) && (a.Normal == b.Normal) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Center.Equals(other.Center) && Normal.Equals(other.Normal) && Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Center, Normal, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__v3t__.Parse(x[0]), __v3t__.Parse(x[1]), __ftype__.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region __iboundingbox__ Members\n\n        public readonly __box3t__ BoundingBox3__tc__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var u = AxisU; var v = AxisV;\n                return new __box3t__(Center + u, Center - u, Center + v, Center - v);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# }\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Cone/Cone3_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region ObliqueCone3f\n\n    /// <summary>\n    /// An oblique cone in 3-space represented by its origin (apex) and base circle.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly struct ObliqueCone3f : IEquatable<ObliqueCone3f>\n    {\n        [DataMember]\n        public readonly V3f Origin;\n\n        [DataMember]\n        public readonly Circle3f Circle;\n\n        #region Constructor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ObliqueCone3f(V3f o, Circle3f c)\n        {\n            Origin = o;\n            Circle = c;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ObliqueCone3f(ObliqueCone3f o)\n        {\n            Origin = o.Origin;\n            Circle = o.Circle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ObliqueCone3f(ObliqueCone3d o)\n        {\n            Origin = (V3f)o.Origin;\n            Circle = (Circle3f)o.Circle;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ObliqueCone3f(ObliqueCone3d c)\n            => new ObliqueCone3f(c);\n\n        #endregion\n\n        #region Constants\n\n        public static ObliqueCone3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ObliqueCone3f(V3f.NaN, Circle3f.Invalid);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Circle.Radius >= 0;\n        }\n\n        public bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Circle.Radius < 0;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(ObliqueCone3f a, ObliqueCone3f b)\n            => (a.Origin == b.Origin) && (a.Circle == b.Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(ObliqueCone3f a, ObliqueCone3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override int GetHashCode() => HashCode.GetCombined(Origin, Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public bool Equals(ObliqueCone3f other)\n            => Origin.Equals(other.Origin) && Circle.Equals(other.Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override bool Equals(object other)\n            => (other is ObliqueCone3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ObliqueCone3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new ObliqueCone3f(V3f.Parse(x[0]), Circle3f.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// get circle of oblique cone where distance between cone origin and circle origin equals distance\n        /// </summary>\n        public Circle3f GetCircle(float distance)\n        {\n            var dir = Circle.Center - Origin;\n            var pDistance = dir.Length;\n            dir.Normalize();\n            var newCenter = Origin + dir * distance;\n            var newRadius = distance / pDistance * Circle.Radius;\n\n            return new Circle3f(newCenter, Circle.Normal, newRadius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"ObliqueCone3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ObliqueCone3f a, ObliqueCone3f b, float tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Circle, b.Circle, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ObliqueCone3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ObliqueCone3f a, ObliqueCone3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Cone3f\n\n    /// <summary>\n    /// A cone in 3-space represented by its origin, axis of revolution (Direction), and the angle between axis and outer edge.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Cone3f : IEquatable<Cone3f>, IValidity\n    {\n        [DataMember]\n        public V3f Origin;\n\n        /// <summary>\n        /// Axis of revolution.\n        /// </summary>\n        [DataMember]\n        public V3f Direction;\n\n        /// <summary>\n        /// Angle between axis and outer edge (in radians).\n        /// </summary>\n        [DataMember]\n        public float Angle;\n\n        #region Constructor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cone3f(V3f origin, V3f dir, float angle)\n        {\n            Origin = origin;\n            Direction = dir;\n            Angle = angle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cone3f(Cone3f o)\n        {\n            Origin = o.Origin;\n            Direction = o.Direction;\n            Angle = o.Angle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cone3f(Cone3d o)\n        {\n            Origin = (V3f)o.Origin;\n            Direction = (V3f)o.Direction;\n            Angle = (float)o.Angle;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Cone3f(Cone3d c)\n            => new Cone3f(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Cone3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Cone3f(V3f.NaN, V3f.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction != V3f.Zero;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction == V3f.Zero;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Cone3f a, Cone3f b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction) && (a.Angle == b.Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Cone3f a, Cone3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction, Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Cone3f other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction) && Angle.Equals(other.Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Cone3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Origin, Direction, Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Cone3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Cone3f(V3f.Parse(x[0]), V3f.Parse(x[1]), float.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// if zero, point is located on cone\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float GetDistance(V3f point) => Vec.Distance(point, GetClosestPoint(point));\n\n        public readonly Circle3f GetCircle(float height)\n        {\n            //circle along axis\n            var dirLength = height;\n            var radius = GetRadius(height);\n            var dir = Direction.Normalized * dirLength;\n            return new Circle3f(Origin + dir, dir.Normalized, radius);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Ray3f GetAxis() => new Ray3f(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float GetHeight(V3f position)\n            => new Ray3f(Origin, Direction).GetTOfProjectedPoint(position);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float GetRadius(float height) => height * Angle.Sin() / Angle.Cos();\n\n        public readonly V3f GetClosestPoint(V3f point)\n        {\n            var ray = new Ray3f(Origin, Direction);\n            var cp = point.GetClosestPointOn(ray);\n            var radius = GetRadius(GetHeight(point));\n            var dir = (point - cp).Normalized * radius;\n\n            var p0 = cp + dir;\n            var p1 = point.GetClosestPointOn(new Ray3f(Origin, (p0 - Origin).Normalized));\n\n            return (Vec.Distance(point, p1) < Vec.Distance(point, p0)) ? p1 : p0;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Cone3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Cone3f a, Cone3f b, float tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance) &&\n            ApproximateEquals(a.Angle, b.Angle, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Cone3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Cone3f a, Cone3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region ObliqueCone3d\n\n    /// <summary>\n    /// An oblique cone in 3-space represented by its origin (apex) and base circle.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly struct ObliqueCone3d : IEquatable<ObliqueCone3d>\n    {\n        [DataMember]\n        public readonly V3d Origin;\n\n        [DataMember]\n        public readonly Circle3d Circle;\n\n        #region Constructor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ObliqueCone3d(V3d o, Circle3d c)\n        {\n            Origin = o;\n            Circle = c;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ObliqueCone3d(ObliqueCone3d o)\n        {\n            Origin = o.Origin;\n            Circle = o.Circle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ObliqueCone3d(ObliqueCone3f o)\n        {\n            Origin = (V3d)o.Origin;\n            Circle = (Circle3d)o.Circle;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ObliqueCone3d(ObliqueCone3f c)\n            => new ObliqueCone3d(c);\n\n        #endregion\n\n        #region Constants\n\n        public static ObliqueCone3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ObliqueCone3d(V3d.NaN, Circle3d.Invalid);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Circle.Radius >= 0;\n        }\n\n        public bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Circle.Radius < 0;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(ObliqueCone3d a, ObliqueCone3d b)\n            => (a.Origin == b.Origin) && (a.Circle == b.Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(ObliqueCone3d a, ObliqueCone3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override int GetHashCode() => HashCode.GetCombined(Origin, Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public bool Equals(ObliqueCone3d other)\n            => Origin.Equals(other.Origin) && Circle.Equals(other.Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override bool Equals(object other)\n            => (other is ObliqueCone3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ObliqueCone3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new ObliqueCone3d(V3d.Parse(x[0]), Circle3d.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// get circle of oblique cone where distance between cone origin and circle origin equals distance\n        /// </summary>\n        public Circle3d GetCircle(double distance)\n        {\n            var dir = Circle.Center - Origin;\n            var pDistance = dir.Length;\n            dir.Normalize();\n            var newCenter = Origin + dir * distance;\n            var newRadius = distance / pDistance * Circle.Radius;\n\n            return new Circle3d(newCenter, Circle.Normal, newRadius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"ObliqueCone3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ObliqueCone3d a, ObliqueCone3d b, double tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Circle, b.Circle, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ObliqueCone3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ObliqueCone3d a, ObliqueCone3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Cone3d\n\n    /// <summary>\n    /// A cone in 3-space represented by its origin, axis of revolution (Direction), and the angle between axis and outer edge.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Cone3d : IEquatable<Cone3d>, IValidity\n    {\n        [DataMember]\n        public V3d Origin;\n\n        /// <summary>\n        /// Axis of revolution.\n        /// </summary>\n        [DataMember]\n        public V3d Direction;\n\n        /// <summary>\n        /// Angle between axis and outer edge (in radians).\n        /// </summary>\n        [DataMember]\n        public double Angle;\n\n        #region Constructor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cone3d(V3d origin, V3d dir, double angle)\n        {\n            Origin = origin;\n            Direction = dir;\n            Angle = angle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cone3d(Cone3d o)\n        {\n            Origin = o.Origin;\n            Direction = o.Direction;\n            Angle = o.Angle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cone3d(Cone3f o)\n        {\n            Origin = (V3d)o.Origin;\n            Direction = (V3d)o.Direction;\n            Angle = (double)o.Angle;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Cone3d(Cone3f c)\n            => new Cone3d(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Cone3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Cone3d(V3d.NaN, V3d.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction != V3d.Zero;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction == V3d.Zero;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Cone3d a, Cone3d b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction) && (a.Angle == b.Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Cone3d a, Cone3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction, Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Cone3d other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction) && Angle.Equals(other.Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Cone3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Origin, Direction, Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Cone3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Cone3d(V3d.Parse(x[0]), V3d.Parse(x[1]), double.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// if zero, point is located on cone\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double GetDistance(V3d point) => Vec.Distance(point, GetClosestPoint(point));\n\n        public readonly Circle3d GetCircle(double height)\n        {\n            //circle along axis\n            var dirLength = height;\n            var radius = GetRadius(height);\n            var dir = Direction.Normalized * dirLength;\n            return new Circle3d(Origin + dir, dir.Normalized, radius);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Ray3d GetAxis() => new Ray3d(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double GetHeight(V3d position)\n            => new Ray3d(Origin, Direction).GetTOfProjectedPoint(position);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double GetRadius(double height) => height * Angle.Sin() / Angle.Cos();\n\n        public readonly V3d GetClosestPoint(V3d point)\n        {\n            var ray = new Ray3d(Origin, Direction);\n            var cp = point.GetClosestPointOn(ray);\n            var radius = GetRadius(GetHeight(point));\n            var dir = (point - cp).Normalized * radius;\n\n            var p0 = cp + dir;\n            var p1 = point.GetClosestPointOn(new Ray3d(Origin, (p0 - Origin).Normalized));\n\n            return (Vec.Distance(point, p1) < Vec.Distance(point, p0)) ? p1 : p0;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Cone3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Cone3d a, Cone3d b, double tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance) &&\n            ApproximateEquals(a.Angle, b.Angle, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Cone3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Cone3d a, Cone3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Cone/Cone3_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Cone3\" + tc;\n    //#   var type2 = \"Cone3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var ray3t = \"Ray3\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var circle3t = \"Circle3\" + tc;\n    //#   var sphere3t = \"Sphere3\" + tc;\n    //#   var iboundingsphere3t = \"IBoundingSphere3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#   var eps = isDouble ? \"1e-9\" : \"1e-5f\";\n    #region Oblique__type__\n\n    /// <summary>\n    /// An oblique cone in 3-space represented by its origin (apex) and base circle.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly struct Oblique__type__ : IEquatable<Oblique__type__>\n    {\n        [DataMember]\n        public readonly __v3t__ Origin;\n\n        [DataMember]\n        public readonly __circle3t__ Circle;\n\n        #region Constructor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Oblique__type__(__v3t__ o, __circle3t__ c)\n        {\n            Origin = o;\n            Circle = c;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Oblique__type__(Oblique__type__ o)\n        {\n            Origin = o.Origin;\n            Circle = o.Circle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Oblique__type__(Oblique__type2__ o)\n        {\n            Origin = (__v3t__)o.Origin;\n            Circle = (__circle3t__)o.Circle;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Oblique__type__(Oblique__type2__ c)\n            => new Oblique__type__(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Oblique__type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Oblique__type__(__v3t__.NaN, __circle3t__.Invalid);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Circle.Radius >= 0;\n        }\n\n        public bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Circle.Radius < 0;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Oblique__type__ a, Oblique__type__ b)\n            => (a.Origin == b.Origin) && (a.Circle == b.Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Oblique__type__ a, Oblique__type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override int GetHashCode() => HashCode.GetCombined(Origin, Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public bool Equals(Oblique__type__ other)\n            => Origin.Equals(other.Origin) && Circle.Equals(other.Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override bool Equals(object other)\n            => (other is Oblique__type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Circle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Oblique__type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Oblique__type__(__v3t__.Parse(x[0]), __circle3t__.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// get circle of oblique cone where distance between cone origin and circle origin equals distance\n        /// </summary>\n        public __circle3t__ GetCircle(__ftype__ distance)\n        {\n            var dir = Circle.Center - Origin;\n            var pDistance = dir.Length;\n            dir.Normalize();\n            var newCenter = Origin + dir * distance;\n            var newRadius = distance / pDistance * Circle.Radius;\n\n            return new __circle3t__(newCenter, Circle.Normal, newRadius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Oblique__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Oblique__type__ a, Oblique__type__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Circle, b.Circle, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Oblique__type__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Oblique__type__ a, Oblique__type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region __type__\n\n    /// <summary>\n    /// A cone in 3-space represented by its origin, axis of revolution (Direction), and the angle between axis and outer edge.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, IValidity\n    {\n        [DataMember]\n        public __v3t__ Origin;\n\n        /// <summary>\n        /// Axis of revolution.\n        /// </summary>\n        [DataMember]\n        public __v3t__ Direction;\n\n        /// <summary>\n        /// Angle between axis and outer edge (in radians).\n        /// </summary>\n        [DataMember]\n        public __ftype__ Angle;\n\n        #region Constructor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v3t__ origin, __v3t__ dir, __ftype__ angle)\n        {\n            Origin = origin;\n            Direction = dir;\n            Angle = angle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ o)\n        {\n            Origin = o.Origin;\n            Direction = o.Direction;\n            Angle = o.Angle;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ o)\n        {\n            Origin = (__v3t__)o.Origin;\n            Direction = (__v3t__)o.Direction;\n            Angle = (__ftype__)o.Angle;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ c)\n            => new __type__(c);\n\n        #endregion\n\n        #region Constants\n\n        public static __type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v3t__.NaN, __v3t__.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction != __v3t__.Zero;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction == __v3t__.Zero;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction) && (a.Angle == b.Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction, Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction) && Angle.Equals(other.Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Origin, Direction, Angle);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__v3t__.Parse(x[0]), __v3t__.Parse(x[1]), __ftype__.Parse(x[2], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// if zero, point is located on cone\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ GetDistance(__v3t__ point) => Vec.Distance(point, GetClosestPoint(point));\n\n        public readonly __circle3t__ GetCircle(__ftype__ height)\n        {\n            //circle along axis\n            var dirLength = height;\n            var radius = GetRadius(height);\n            var dir = Direction.Normalized * dirLength;\n            return new __circle3t__(Origin + dir, dir.Normalized, radius);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ray3t__ GetAxis() => new __ray3t__(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ GetHeight(__v3t__ position)\n            => new __ray3t__(Origin, Direction).GetTOfProjectedPoint(position);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ GetRadius(__ftype__ height) => height * Angle.Sin() / Angle.Cos();\n\n        public readonly __v3t__ GetClosestPoint(__v3t__ point)\n        {\n            var ray = new __ray3t__(Origin, Direction);\n            var cp = point.GetClosestPointOn(ray);\n            var radius = GetRadius(GetHeight(point));\n            var dir = (point - cp).Normalized * radius;\n\n            var p0 = cp + dir;\n            var p1 = point.GetClosestPointOn(new __ray3t__(Origin, (p0 - Origin).Normalized));\n\n            return (Vec.Distance(point, p1) < Vec.Distance(point, p0)) ? p1 : p0;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance) &&\n            ApproximateEquals(a.Angle, b.Angle, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Cone/Conic2_auto.cs",
    "content": "using System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Conic2f\n\n    /// <summary>\n    /// WARNING: Sektch!\n    /// Defines the conic section CXX x^2 + CYY y^2 + CZZ z^2 + CXY xy + CYZ yz + CYZ yz = 0\n    /// with (x,y,z) being homogenous coordinates.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Conic2f\n    {\n        [DataMember]\n        public float CXX;\n        [DataMember]\n        public float CYY;\n        [DataMember]\n        public float CZZ;\n        [DataMember]\n        public float CXY;\n        [DataMember]\n        public float CXZ;\n        [DataMember]\n        public float CYZ;\n\n        public Conic2f(float cxx, float cyy, float czz, float cxy, float cxz, float cyz)\n        {\n            CXX = cxx; CYY = cyy; CZZ = czz; CXY = cxy; CXZ = cxz; CYZ = cyz;\n        }\n\n\n        public readonly float Discriminant { get { return CXX * CYY - CXY * CXY; } }\n\n        public readonly int ConicType\n        {\n            get\n            {\n                var d = Discriminant;\n                return d > Constant<float>.PositiveTinyValue ? 1\n                    : d < Constant<float>.NegativeTinyValue ? -1 : 0;\n            }\n        }\n    }\n\n    #endregion\n\n    #region Conic2d\n\n    /// <summary>\n    /// WARNING: Sektch!\n    /// Defines the conic section CXX x^2 + CYY y^2 + CZZ z^2 + CXY xy + CYZ yz + CYZ yz = 0\n    /// with (x,y,z) being homogenous coordinates.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Conic2d\n    {\n        [DataMember]\n        public double CXX;\n        [DataMember]\n        public double CYY;\n        [DataMember]\n        public double CZZ;\n        [DataMember]\n        public double CXY;\n        [DataMember]\n        public double CXZ;\n        [DataMember]\n        public double CYZ;\n\n        public Conic2d(double cxx, double cyy, double czz, double cxy, double cxz, double cyz)\n        {\n            CXX = cxx; CYY = cyy; CZZ = czz; CXY = cxy; CXZ = cxz; CYZ = cyz;\n        }\n\n\n        public readonly double Discriminant { get { return CXX * CYY - CXY * CXY; } }\n\n        public readonly int ConicType\n        {\n            get\n            {\n                var d = Discriminant;\n                return d > Constant<double>.PositiveTinyValue ? 1\n                    : d < Constant<double>.NegativeTinyValue ? -1 : 0;\n            }\n        }\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Cone/Conic2_template.cs",
    "content": "﻿using System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Conic2\" + tc;\n    //#   var type2 = \"Conic2\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    #region __type__\n\n    /// <summary>\n    /// WARNING: Sektch!\n    /// Defines the conic section CXX x^2 + CYY y^2 + CZZ z^2 + CXY xy + CYZ yz + CYZ yz = 0\n    /// with (x,y,z) being homogenous coordinates.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__\n    {\n        [DataMember]\n        public __ftype__ CXX;\n        [DataMember]\n        public __ftype__ CYY;\n        [DataMember]\n        public __ftype__ CZZ;\n        [DataMember]\n        public __ftype__ CXY;\n        [DataMember]\n        public __ftype__ CXZ;\n        [DataMember]\n        public __ftype__ CYZ;\n\n        public __type__(__ftype__ cxx, __ftype__ cyy, __ftype__ czz, __ftype__ cxy, __ftype__ cxz, __ftype__ cyz)\n        {\n            CXX = cxx; CYY = cyy; CZZ = czz; CXY = cxy; CXZ = cxz; CYZ = cyz;\n        }\n\n\n        public readonly __ftype__ Discriminant { get { return CXX * CYY - CXY * CXY; } }\n\n        public readonly int ConicType\n        {\n            get\n            {\n                var d = Discriminant;\n                return d > Constant<__ftype__>.PositiveTinyValue ? 1\n                    : d < Constant<__ftype__>.NegativeTinyValue ? -1 : 0;\n            }\n        }\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Cylinder/Cylinder3_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Cylinder3f\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Cylinder3f : IEquatable<Cylinder3f>, IBoundingBox3f, IValidity\n    {\n        [DataMember]\n        public V3f P0;\n        [DataMember]\n        public V3f P1;\n        [DataMember]\n        public float Radius;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cylinder3f(V3f p0, V3f p1, float radius)\n        {\n            P0 = p0;\n            P1 = p1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cylinder3f(Line3f axis, float radius)\n        {\n            P0 = axis.P0;\n            P1 = axis.P1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cylinder3f(Cylinder3f c)\n        {\n            P0 = c.P0;\n            P1 = c.P1;\n            Radius = c.Radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cylinder3f(Cylinder3d c)\n        {\n            P0 = (V3f)c.P0;\n            P1 = (V3f)c.P1;\n            Radius = (float)c.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Cylinder3f(Cylinder3d c)\n            => new Cylinder3f(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Cylinder3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Cylinder3f(V3f.NaN, V3f.NaN, -1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly float Height\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P0 - P1).Length;\n        }\n\n        public readonly V3f Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P0 + P1) * 0.5f;\n        }\n\n        public readonly Line3f Axis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Line3f(P0, P1);\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0;\n        }\n\n        public readonly Circle3f Circle0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle3f(P0, (P0 - P1).Normalized, Radius);\n        }\n\n        public readonly Circle3f Circle1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle3f(P1, (P1 - P0).Normalized, Radius);\n        }\n\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * ConstantF.PiTimesTwo * (Radius + Height);\n        }\n\n        public readonly float Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius * ConstantF.Pi * Height;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Cylinder3f a, Cylinder3f b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Cylinder3f a, Cylinder3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Cylinder3f other) =>\n            P0.Equals(other.P0) &&\n            P1.Equals(other.P1) &&\n            Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Cylinder3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Cylinder3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Cylinder3f(\n                V3f.Parse(x[0]),\n                V3f.Parse(x[1]),\n                float.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// P0 has height 0.0, P1 has height 1.0\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float GetHeight(V3f p)\n        {\n            var dir = (P1 - P0).Normalized;\n            var pp = p.GetClosestPointOn(new Ray3f(P0, dir));\n            return (pp - P0).Dot(dir);\n        }\n        /// <summary>\n        /// Get circle at a specific height\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Circle3f GetCircle(float height)\n        {\n            var dir = (P1 - P0).Normalized;\n            return new Circle3f(P0 + height * dir, dir, Radius);\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        public readonly Box3f BoundingBox3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Box3f(Circle0.BoundingBox3f, Circle1.BoundingBox3f);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Cylinder3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Cylinder3f a, Cylinder3f b, float tolerance) =>\n            ApproximateEquals(a.P0, b.P0, tolerance) &&\n            ApproximateEquals(a.P1, b.P1, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Cylinder3f\"/> are equal within\n        /// ConstantF&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Cylinder3f a, Cylinder3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Cylinder3d\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Cylinder3d : IEquatable<Cylinder3d>, IBoundingBox3d, IValidity\n    {\n        [DataMember]\n        public V3d P0;\n        [DataMember]\n        public V3d P1;\n        [DataMember]\n        public double Radius;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cylinder3d(V3d p0, V3d p1, double radius)\n        {\n            P0 = p0;\n            P1 = p1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cylinder3d(Line3d axis, double radius)\n        {\n            P0 = axis.P0;\n            P1 = axis.P1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cylinder3d(Cylinder3d c)\n        {\n            P0 = c.P0;\n            P1 = c.P1;\n            Radius = c.Radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Cylinder3d(Cylinder3f c)\n        {\n            P0 = (V3d)c.P0;\n            P1 = (V3d)c.P1;\n            Radius = (double)c.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Cylinder3d(Cylinder3f c)\n            => new Cylinder3d(c);\n\n        #endregion\n\n        #region Constants\n\n        public static Cylinder3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Cylinder3d(V3d.NaN, V3d.NaN, -1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly double Height\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P0 - P1).Length;\n        }\n\n        public readonly V3d Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P0 + P1) * 0.5;\n        }\n\n        public readonly Line3d Axis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Line3d(P0, P1);\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0;\n        }\n\n        public readonly Circle3d Circle0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle3d(P0, (P0 - P1).Normalized, Radius);\n        }\n\n        public readonly Circle3d Circle1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Circle3d(P1, (P1 - P0).Normalized, Radius);\n        }\n\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Constant.PiTimesTwo * (Radius + Height);\n        }\n\n        public readonly double Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius * Constant.Pi * Height;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Cylinder3d a, Cylinder3d b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Cylinder3d a, Cylinder3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Cylinder3d other) =>\n            P0.Equals(other.P0) &&\n            P1.Equals(other.P1) &&\n            Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Cylinder3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Cylinder3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Cylinder3d(\n                V3d.Parse(x[0]),\n                V3d.Parse(x[1]),\n                double.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// P0 has height 0.0, P1 has height 1.0\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double GetHeight(V3d p)\n        {\n            var dir = (P1 - P0).Normalized;\n            var pp = p.GetClosestPointOn(new Ray3d(P0, dir));\n            return (pp - P0).Dot(dir);\n        }\n        /// <summary>\n        /// Get circle at a specific height\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Circle3d GetCircle(double height)\n        {\n            var dir = (P1 - P0).Normalized;\n            return new Circle3d(P0 + height * dir, dir, Radius);\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        public readonly Box3d BoundingBox3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Box3d(Circle0.BoundingBox3d, Circle1.BoundingBox3d);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Cylinder3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Cylinder3d a, Cylinder3d b, double tolerance) =>\n            ApproximateEquals(a.P0, b.P0, tolerance) &&\n            ApproximateEquals(a.P1, b.P1, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Cylinder3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Cylinder3d a, Cylinder3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Cylinder/Cylinder3_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Cylinder3\" + tc;\n    //#   var type2 = \"Cylinder3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var circle3t = \"Circle3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var line3t = \"Line3\" + tc;\n    //#   var ray3t = \"Ray3\" + tc;\n    //#   var iboundingbox = \"IBoundingBox3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var dotnine = isDouble ? \"0.9\" : \"0.9f\";\n    //#   var constant = isDouble ? \"Constant\" : \"ConstantF\";\n    #region __type__\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, __iboundingbox__, IValidity\n    {\n        [DataMember]\n        public __v3t__ P0;\n        [DataMember]\n        public __v3t__ P1;\n        [DataMember]\n        public __ftype__ Radius;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v3t__ p0, __v3t__ p1, __ftype__ radius)\n        {\n            P0 = p0;\n            P1 = p1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__line3t__ axis, __ftype__ radius)\n        {\n            P0 = axis.P0;\n            P1 = axis.P1;\n            Radius = radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ c)\n        {\n            P0 = c.P0;\n            P1 = c.P1;\n            Radius = c.Radius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ c)\n        {\n            P0 = (__v3t__)c.P0;\n            P1 = (__v3t__)c.P1;\n            Radius = (__ftype__)c.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ c)\n            => new __type__(c);\n\n        #endregion\n\n        #region Constants\n\n        public static __type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v3t__.NaN, __v3t__.NaN, -1);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly __ftype__ Height\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P0 - P1).Length;\n        }\n\n        public readonly __v3t__ Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P0 + P1) * __half__;\n        }\n\n        public readonly __line3t__ Axis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __line3t__(P0, P1);\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0;\n        }\n\n        public readonly __circle3t__ Circle0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __circle3t__(P0, (P0 - P1).Normalized, Radius);\n        }\n\n        public readonly __circle3t__ Circle1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __circle3t__(P1, (P1 - P0).Normalized, Radius);\n        }\n\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * __constant__.PiTimesTwo * (Radius + Height);\n        }\n\n        public readonly __ftype__ Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius * __constant__.Pi * Height;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.Radius == b.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other) =>\n            P0.Equals(other.P0) &&\n            P1.Equals(other.P1) &&\n            Radius.Equals(other.Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(\n                __v3t__.Parse(x[0]),\n                __v3t__.Parse(x[1]),\n                __ftype__.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// P0 has height 0.0, P1 has height 1.0\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ GetHeight(__v3t__ p)\n        {\n            var dir = (P1 - P0).Normalized;\n            var pp = p.GetClosestPointOn(new __ray3t__(P0, dir));\n            return (pp - P0).Dot(dir);\n        }\n        /// <summary>\n        /// Get circle at a specific height\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __circle3t__ GetCircle(__ftype__ height)\n        {\n            var dir = (P1 - P0).Normalized;\n            return new __circle3t__(P0 + height * dir, dir, Radius);\n        }\n\n        #endregion\n\n        #region __iboundingbox__ Members\n\n        public readonly __box3t__ BoundingBox3__tc__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __box3t__(Circle0.BoundingBox3__tc__, Circle1.BoundingBox3__tc__);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.P0, b.P0, tolerance) &&\n            ApproximateEquals(a.P1, b.P1, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within\n        /// __constant__&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ellipse/Ellipse2_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Ellipse2f\n\n    public partial struct Ellipse2f : IValidity\n    {\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Abs(Axis0.X * Axis1.Y - Axis0.Y * Axis1.X) * ConstantF.Pi;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        static float GetArea(V2f axis0, V2f axis1)\n            => Fun.Abs(axis0.X * axis1.Y - axis0.Y * axis1.X) * ConstantF.Pi;\n    }\n\n    #endregion\n\n    #region Ellipse2d\n\n    public partial struct Ellipse2d : IValidity\n    {\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Abs(Axis0.X * Axis1.Y - Axis0.Y * Axis1.X) * Constant.Pi;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        static double GetArea(V2d axis0, V2d axis1)\n            => Fun.Abs(axis0.X * axis1.Y - axis0.Y * axis1.X) * Constant.Pi;\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ellipse/Ellipse2_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var type = \"Ellipse2\" + tc;\n    //#   var v2t = \"V2\" + tc;\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    #region __type__\n\n    public partial struct __type__ : IValidity\n    {\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Abs(Axis0.X * Axis1.Y - Axis0.Y * Axis1.X) * __pi__;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        static __ftype__ GetArea(__v2t__ axis0, __v2t__ axis1)\n            => Fun.Abs(axis0.X * axis1.Y - axis0.Y * axis1.X) * __pi__;\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ellipse/Ellipse3_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Ellipse3f\n\n    public partial struct Ellipse3f : IValidity\n    {\n        public static Ellipse3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ellipse3f(V3f.NaN, V3f.Zero, V3f.NaN, V3f.NaN);\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != V3f.Zero;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == V3f.Zero;\n        }\n\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Vec.Cross(Axis0, Axis1).Length * ConstantF.Pi;\n        }\n    }\n\n    #endregion\n\n    #region Ellipse3d\n\n    public partial struct Ellipse3d : IValidity\n    {\n        public static Ellipse3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ellipse3d(V3d.NaN, V3d.Zero, V3d.NaN, V3d.NaN);\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != V3d.Zero;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == V3d.Zero;\n        }\n\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Vec.Cross(Axis0, Axis1).Length * Constant.Pi;\n        }\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ellipse/Ellipse3_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var type = \"Ellipse3\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    #region __type__\n\n    public partial struct __type__ : IValidity\n    {\n        public static __type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v3t__.NaN, __v3t__.Zero, __v3t__.NaN, __v3t__.NaN);\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != __v3t__.Zero;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == __v3t__.Zero;\n        }\n\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Vec.Cross(Axis0, Axis1).Length * __pi__;\n        }\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ellipse/Ellipse_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Ellipse2f\n\n    /// <summary>\n    /// A 2d ellipse is defined by its center\n    /// and two half-axes.\n    /// Note that in principle any two conjugate half-diameters\n    /// can be used as axes, however some algorithms require that\n    /// the major and minor half axes are known. By convention\n    /// in this case, axis0 is the major half axis.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Ellipse2f\n    {\n        public V2f Center;\n        public V2f Axis0;\n        public V2f Axis1;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse2f(V2f center, V2f axis0, V2f axis1)\n        {\n            Center = center;\n            Axis0 = axis0;\n            Axis1 = axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse2f(Ellipse2f o)\n        {\n            Center = o.Center;\n            Axis0 = o.Axis0;\n            Axis1 = o.Axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse2f(Ellipse2d o)\n        {\n            Center = (V2f)o.Center;\n            Axis0 = (V2f)o.Axis0;\n            Axis1 = (V2f)o.Axis1;\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// </summary>\n        public static Ellipse2f FromConjugateDiameters(V2f center, V2f a, V2f b)\n        {\n            var ab = Vec.Dot(a, b);\n            float a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) return new Ellipse2f(center, a, b);\n                else return new Ellipse2f(center, b, a);\n            }\n            else\n            {\n                var t = 0.5f * Fun.Atan2(2 * ab, a2 - b2);\n                float ct = Fun.Cos(t), st = Fun.Sin(t);\n                V2f v0 = a * ct + b * st, v1 = b * ct - a * st;\n                if (v0.LengthSquared >= v1.LengthSquared) return new Ellipse2f(center, v0, v1);\n                else return new Ellipse2f(center, v1, v0);\n            }\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// Also computes the squared lengths of the major and minor\n        /// half axis.\n        /// </summary>\n        public static Ellipse2f FromConjugateDiameters(V2f center, V2f a, V2f b,\n                out float major2, out float minor2)\n        {\n            var ab = Vec.Dot(a, b);\n            float a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new Ellipse2f(center, a, b); }\n                else { major2 = b2; minor2 = a2; return new Ellipse2f(center, b, a); }\n            }\n            else\n            {\n                var t = 0.5f * Fun.Atan2(2 * ab, a2 - b2);\n                float ct = Fun.Cos(t), st = Fun.Sin(t);\n                V2f v0 = a * ct + b * st, v1 = b * ct - a * st;\n                a2 = v0.LengthSquared; b2 = v1.LengthSquared;\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new Ellipse2f(center, v0, v1); }\n                else { major2 = b2; minor2 = a2; return new Ellipse2f(center, v1, v0); }\n            }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Ellipse2f(Ellipse2d o)\n            => new Ellipse2f(o);\n\n        #endregion\n\n        #region Constants\n\n        public static Ellipse2f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ellipse2f(V2f.Zero, V2f.Zero, V2f.Zero);\n        }\n\n        #endregion\n\n        #region Operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f GetVector(float alpha)\n            => Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f GetPoint(float alpha)\n            => Center + Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        /// <summary>\n        /// Perform the supplied action for each of count vectors from the center\n        /// of the ellipse to the circumference.\n        /// </summary>\n        public readonly void ForEachVector(int count, Action<int, V2f> index_vector_act)\n        {\n            float d = ConstantF.PiTimesTwo / count;\n            float a = Fun.Sin(d * 0.5f).Square() * 2, b = Fun.Sin(d); // init trig. recurrence\n            float ct = 1, st = 0;\n\n            index_vector_act(0, Axis0);\n            for (int i = 1; i < count; i++)\n            {\n                float dct = a * ct + b * st, dst = a * st - b * ct; ;  // trig. recurrence\n                ct -= dct; st -= dst;                                   // cos (t + d), sin (t + d)\n                index_vector_act(i, Axis0 * ct + Axis1 * st);\n            }\n        }\n\n        /// <summary>\n        /// Get count points on the circumference of the ellipse.\n        /// </summary>\n        public readonly V2f[] GetPoints(int count)\n        {\n            var array = new V2f[count];\n            var c = Center;\n            ForEachVector(count, (i, v) => array[i] = c + v);\n            return array;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Ellipse2f a, Ellipse2f b) =>\n            (a.Center == b.Center) &&\n            (a.Axis0 == b.Axis0) &&\n            (a.Axis1 == b.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Ellipse2f a, Ellipse2f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(Center, Axis0, Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Ellipse2f other) =>\n            Center.Equals(other.Center) &&\n            Axis0.Equals(other.Axis0) &&\n            Axis1.Equals(other.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n             => (other is Ellipse2f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Center, Axis0, Axis1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Ellipse2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Ellipse2f(\n                V2f.Parse(x[0]),\n                V2f.Parse(x[1]),\n                V2f.Parse(x[2])\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ellipse2f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ellipse2f a, Ellipse2f b, float tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Axis0, b.Axis0, tolerance) &&\n            ApproximateEquals(a.Axis1, b.Axis1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ellipse2f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ellipse2f a, Ellipse2f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Ellipse3f\n\n    /// <summary>\n    /// A 3d ellipse is defined by its center, its plane normal,\n    /// and two half-axes.\n    /// Note that in principle any two conjugate half-diameters\n    /// can be used as axes, however some algorithms require that\n    /// the major and minor half axes are known. By convention\n    /// in this case, axis0 is the major half axis.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Ellipse3f\n    {\n        public V3f Center;\n        public V3f Normal;\n        public V3f Axis0;\n        public V3f Axis1;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse3f(V3f center, V3f normal, V3f axis0, V3f axis1)\n        {\n            Center = center;\n            Normal = normal;\n            Axis0 = axis0;\n            Axis1 = axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse3f(Ellipse3f o)\n        {\n            Center = o.Center;\n            Normal = o.Normal;\n            Axis0 = o.Axis0;\n            Axis1 = o.Axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse3f(Ellipse3d o)\n        {\n            Center = (V3f)o.Center;\n            Normal = (V3f)o.Normal;\n            Axis0 = (V3f)o.Axis0;\n            Axis1 = (V3f)o.Axis1;\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// </summary>\n        public static Ellipse3f FromConjugateDiameters(V3f center, V3f normal, V3f a, V3f b)\n        {\n            var ab = Vec.Dot(a, b);\n            float a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) return new Ellipse3f(center, normal, a, b);\n                else return new Ellipse3f(center, normal, b, a);\n            }\n            else\n            {\n                var t = 0.5f * Fun.Atan2(2 * ab, a2 - b2);\n                float ct = Fun.Cos(t), st = Fun.Sin(t);\n                V3f v0 = a * ct + b * st, v1 = b * ct - a * st;\n                if (v0.LengthSquared >= v1.LengthSquared) return new Ellipse3f(center, normal, v0, v1);\n                else return new Ellipse3f(center, normal, v1, v0);\n            }\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// Also computes the squared lengths of the major and minor\n        /// half axis.\n        /// </summary>\n        public static Ellipse3f FromConjugateDiameters(V3f center, V3f normal, V3f a, V3f b,\n                out float major2, out float minor2)\n        {\n            var ab = Vec.Dot(a, b);\n            float a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new Ellipse3f(center, normal, a, b); }\n                else { major2 = b2; minor2 = a2; return new Ellipse3f(center, normal, b, a); }\n            }\n            else\n            {\n                var t = 0.5f * Fun.Atan2(2 * ab, a2 - b2);\n                float ct = Fun.Cos(t), st = Fun.Sin(t);\n                V3f v0 = a * ct + b * st, v1 = b * ct - a * st;\n                a2 = v0.LengthSquared; b2 = v1.LengthSquared;\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new Ellipse3f(center, normal, v0, v1); }\n                else { major2 = b2; minor2 = a2; return new Ellipse3f(center, normal, v1, v0); }\n            }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Ellipse3f(Ellipse3d o)\n            => new Ellipse3f(o);\n\n        #endregion\n\n        #region Constants\n\n        public static Ellipse3f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ellipse3f(V3f.Zero, V3f.Zero, V3f.Zero, V3f.Zero);\n        }\n\n        #endregion\n\n        #region Operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f GetVector(float alpha)\n            => Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f GetPoint(float alpha)\n            => Center + Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        /// <summary>\n        /// Perform the supplied action for each of count vectors from the center\n        /// of the ellipse to the circumference.\n        /// </summary>\n        public readonly void ForEachVector(int count, Action<int, V3f> index_vector_act)\n        {\n            float d = ConstantF.PiTimesTwo / count;\n            float a = Fun.Sin(d * 0.5f).Square() * 2, b = Fun.Sin(d); // init trig. recurrence\n            float ct = 1, st = 0;\n\n            index_vector_act(0, Axis0);\n            for (int i = 1; i < count; i++)\n            {\n                float dct = a * ct + b * st, dst = a * st - b * ct; ;  // trig. recurrence\n                ct -= dct; st -= dst;                                   // cos (t + d), sin (t + d)\n                index_vector_act(i, Axis0 * ct + Axis1 * st);\n            }\n        }\n\n        /// <summary>\n        /// Get count points on the circumference of the ellipse.\n        /// </summary>\n        public readonly V3f[] GetPoints(int count)\n        {\n            var array = new V3f[count];\n            var c = Center;\n            ForEachVector(count, (i, v) => array[i] = c + v);\n            return array;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Ellipse3f a, Ellipse3f b) =>\n            (a.Center == b.Center) &&\n            (a.Normal == b.Normal) &&\n            (a.Axis0 == b.Axis0) &&\n            (a.Axis1 == b.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Ellipse3f a, Ellipse3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(Center, Normal, Axis0, Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Ellipse3f other) =>\n            Center.Equals(other.Center) &&\n            Normal.Equals(other.Normal) &&\n            Axis0.Equals(other.Axis0) &&\n            Axis1.Equals(other.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n             => (other is Ellipse3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", Center, Normal, Axis0, Axis1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Ellipse3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Ellipse3f(\n                V3f.Parse(x[0]),\n                V3f.Parse(x[1]),\n                V3f.Parse(x[2]),\n                V3f.Parse(x[3])\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ellipse3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ellipse3f a, Ellipse3f b, float tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Axis0, b.Axis0, tolerance) &&\n            ApproximateEquals(a.Axis1, b.Axis1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ellipse3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ellipse3f a, Ellipse3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Ellipse2d\n\n    /// <summary>\n    /// A 2d ellipse is defined by its center\n    /// and two half-axes.\n    /// Note that in principle any two conjugate half-diameters\n    /// can be used as axes, however some algorithms require that\n    /// the major and minor half axes are known. By convention\n    /// in this case, axis0 is the major half axis.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Ellipse2d\n    {\n        public V2d Center;\n        public V2d Axis0;\n        public V2d Axis1;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse2d(V2d center, V2d axis0, V2d axis1)\n        {\n            Center = center;\n            Axis0 = axis0;\n            Axis1 = axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse2d(Ellipse2d o)\n        {\n            Center = o.Center;\n            Axis0 = o.Axis0;\n            Axis1 = o.Axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse2d(Ellipse2f o)\n        {\n            Center = (V2d)o.Center;\n            Axis0 = (V2d)o.Axis0;\n            Axis1 = (V2d)o.Axis1;\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// </summary>\n        public static Ellipse2d FromConjugateDiameters(V2d center, V2d a, V2d b)\n        {\n            var ab = Vec.Dot(a, b);\n            double a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) return new Ellipse2d(center, a, b);\n                else return new Ellipse2d(center, b, a);\n            }\n            else\n            {\n                var t = 0.5 * Fun.Atan2(2 * ab, a2 - b2);\n                double ct = Fun.Cos(t), st = Fun.Sin(t);\n                V2d v0 = a * ct + b * st, v1 = b * ct - a * st;\n                if (v0.LengthSquared >= v1.LengthSquared) return new Ellipse2d(center, v0, v1);\n                else return new Ellipse2d(center, v1, v0);\n            }\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// Also computes the squared lengths of the major and minor\n        /// half axis.\n        /// </summary>\n        public static Ellipse2d FromConjugateDiameters(V2d center, V2d a, V2d b,\n                out double major2, out double minor2)\n        {\n            var ab = Vec.Dot(a, b);\n            double a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new Ellipse2d(center, a, b); }\n                else { major2 = b2; minor2 = a2; return new Ellipse2d(center, b, a); }\n            }\n            else\n            {\n                var t = 0.5 * Fun.Atan2(2 * ab, a2 - b2);\n                double ct = Fun.Cos(t), st = Fun.Sin(t);\n                V2d v0 = a * ct + b * st, v1 = b * ct - a * st;\n                a2 = v0.LengthSquared; b2 = v1.LengthSquared;\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new Ellipse2d(center, v0, v1); }\n                else { major2 = b2; minor2 = a2; return new Ellipse2d(center, v1, v0); }\n            }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Ellipse2d(Ellipse2f o)\n            => new Ellipse2d(o);\n\n        #endregion\n\n        #region Constants\n\n        public static Ellipse2d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ellipse2d(V2d.Zero, V2d.Zero, V2d.Zero);\n        }\n\n        #endregion\n\n        #region Operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d GetVector(double alpha)\n            => Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d GetPoint(double alpha)\n            => Center + Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        /// <summary>\n        /// Perform the supplied action for each of count vectors from the center\n        /// of the ellipse to the circumference.\n        /// </summary>\n        public readonly void ForEachVector(int count, Action<int, V2d> index_vector_act)\n        {\n            double d = Constant.PiTimesTwo / count;\n            double a = Fun.Sin(d * 0.5).Square() * 2, b = Fun.Sin(d); // init trig. recurrence\n            double ct = 1, st = 0;\n\n            index_vector_act(0, Axis0);\n            for (int i = 1; i < count; i++)\n            {\n                double dct = a * ct + b * st, dst = a * st - b * ct; ;  // trig. recurrence\n                ct -= dct; st -= dst;                                   // cos (t + d), sin (t + d)\n                index_vector_act(i, Axis0 * ct + Axis1 * st);\n            }\n        }\n\n        /// <summary>\n        /// Get count points on the circumference of the ellipse.\n        /// </summary>\n        public readonly V2d[] GetPoints(int count)\n        {\n            var array = new V2d[count];\n            var c = Center;\n            ForEachVector(count, (i, v) => array[i] = c + v);\n            return array;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Ellipse2d a, Ellipse2d b) =>\n            (a.Center == b.Center) &&\n            (a.Axis0 == b.Axis0) &&\n            (a.Axis1 == b.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Ellipse2d a, Ellipse2d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(Center, Axis0, Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Ellipse2d other) =>\n            Center.Equals(other.Center) &&\n            Axis0.Equals(other.Axis0) &&\n            Axis1.Equals(other.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n             => (other is Ellipse2d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Center, Axis0, Axis1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Ellipse2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Ellipse2d(\n                V2d.Parse(x[0]),\n                V2d.Parse(x[1]),\n                V2d.Parse(x[2])\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ellipse2d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ellipse2d a, Ellipse2d b, double tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Axis0, b.Axis0, tolerance) &&\n            ApproximateEquals(a.Axis1, b.Axis1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ellipse2d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ellipse2d a, Ellipse2d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Ellipse3d\n\n    /// <summary>\n    /// A 3d ellipse is defined by its center, its plane normal,\n    /// and two half-axes.\n    /// Note that in principle any two conjugate half-diameters\n    /// can be used as axes, however some algorithms require that\n    /// the major and minor half axes are known. By convention\n    /// in this case, axis0 is the major half axis.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Ellipse3d\n    {\n        public V3d Center;\n        public V3d Normal;\n        public V3d Axis0;\n        public V3d Axis1;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse3d(V3d center, V3d normal, V3d axis0, V3d axis1)\n        {\n            Center = center;\n            Normal = normal;\n            Axis0 = axis0;\n            Axis1 = axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse3d(Ellipse3d o)\n        {\n            Center = o.Center;\n            Normal = o.Normal;\n            Axis0 = o.Axis0;\n            Axis1 = o.Axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ellipse3d(Ellipse3f o)\n        {\n            Center = (V3d)o.Center;\n            Normal = (V3d)o.Normal;\n            Axis0 = (V3d)o.Axis0;\n            Axis1 = (V3d)o.Axis1;\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// </summary>\n        public static Ellipse3d FromConjugateDiameters(V3d center, V3d normal, V3d a, V3d b)\n        {\n            var ab = Vec.Dot(a, b);\n            double a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) return new Ellipse3d(center, normal, a, b);\n                else return new Ellipse3d(center, normal, b, a);\n            }\n            else\n            {\n                var t = 0.5 * Fun.Atan2(2 * ab, a2 - b2);\n                double ct = Fun.Cos(t), st = Fun.Sin(t);\n                V3d v0 = a * ct + b * st, v1 = b * ct - a * st;\n                if (v0.LengthSquared >= v1.LengthSquared) return new Ellipse3d(center, normal, v0, v1);\n                else return new Ellipse3d(center, normal, v1, v0);\n            }\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// Also computes the squared lengths of the major and minor\n        /// half axis.\n        /// </summary>\n        public static Ellipse3d FromConjugateDiameters(V3d center, V3d normal, V3d a, V3d b,\n                out double major2, out double minor2)\n        {\n            var ab = Vec.Dot(a, b);\n            double a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new Ellipse3d(center, normal, a, b); }\n                else { major2 = b2; minor2 = a2; return new Ellipse3d(center, normal, b, a); }\n            }\n            else\n            {\n                var t = 0.5 * Fun.Atan2(2 * ab, a2 - b2);\n                double ct = Fun.Cos(t), st = Fun.Sin(t);\n                V3d v0 = a * ct + b * st, v1 = b * ct - a * st;\n                a2 = v0.LengthSquared; b2 = v1.LengthSquared;\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new Ellipse3d(center, normal, v0, v1); }\n                else { major2 = b2; minor2 = a2; return new Ellipse3d(center, normal, v1, v0); }\n            }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Ellipse3d(Ellipse3f o)\n            => new Ellipse3d(o);\n\n        #endregion\n\n        #region Constants\n\n        public static Ellipse3d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ellipse3d(V3d.Zero, V3d.Zero, V3d.Zero, V3d.Zero);\n        }\n\n        #endregion\n\n        #region Operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d GetVector(double alpha)\n            => Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d GetPoint(double alpha)\n            => Center + Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        /// <summary>\n        /// Perform the supplied action for each of count vectors from the center\n        /// of the ellipse to the circumference.\n        /// </summary>\n        public readonly void ForEachVector(int count, Action<int, V3d> index_vector_act)\n        {\n            double d = Constant.PiTimesTwo / count;\n            double a = Fun.Sin(d * 0.5).Square() * 2, b = Fun.Sin(d); // init trig. recurrence\n            double ct = 1, st = 0;\n\n            index_vector_act(0, Axis0);\n            for (int i = 1; i < count; i++)\n            {\n                double dct = a * ct + b * st, dst = a * st - b * ct; ;  // trig. recurrence\n                ct -= dct; st -= dst;                                   // cos (t + d), sin (t + d)\n                index_vector_act(i, Axis0 * ct + Axis1 * st);\n            }\n        }\n\n        /// <summary>\n        /// Get count points on the circumference of the ellipse.\n        /// </summary>\n        public readonly V3d[] GetPoints(int count)\n        {\n            var array = new V3d[count];\n            var c = Center;\n            ForEachVector(count, (i, v) => array[i] = c + v);\n            return array;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Ellipse3d a, Ellipse3d b) =>\n            (a.Center == b.Center) &&\n            (a.Normal == b.Normal) &&\n            (a.Axis0 == b.Axis0) &&\n            (a.Axis1 == b.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Ellipse3d a, Ellipse3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(Center, Normal, Axis0, Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Ellipse3d other) =>\n            Center.Equals(other.Center) &&\n            Normal.Equals(other.Normal) &&\n            Axis0.Equals(other.Axis0) &&\n            Axis1.Equals(other.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n             => (other is Ellipse3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", Center, Normal, Axis0, Axis1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Ellipse3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Ellipse3d(\n                V3d.Parse(x[0]),\n                V3d.Parse(x[1]),\n                V3d.Parse(x[2]),\n                V3d.Parse(x[3])\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ellipse3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ellipse3d a, Ellipse3d b, double tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Axis0, b.Axis0, tolerance) &&\n            ApproximateEquals(a.Axis1, b.Axis1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ellipse3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ellipse3d a, Ellipse3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ellipse/Ellipse_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# { // ELLIPSES\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var constant = isDouble ? \"Constant\" : \"ConstantF\";\n    //# for (int d = 2; d < 4; d++) {\n    //#     var vt = \"V\" + d + tc;\n    //#     var vt2 = \"V\" + d + tc2;\n    //#     var et = \"Ellipse\" + d + tc;\n    //#     var et2 = \"Ellipse\" + d + tc2;\n    #region __et__\n\n    /// <summary>\n    /// A __d__d ellipse is defined by its center/*# if (d == 3) { */, its plane normal,/*# } */\n    /// and two half-axes.\n    /// Note that in principle any two conjugate half-diameters\n    /// can be used as axes, however some algorithms require that\n    /// the major and minor half axes are known. By convention\n    /// in this case, axis0 is the major half axis.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __et__\n    {\n        public __vt__ Center;\n        //# if (d == 3) {\n        public __vt__ Normal;\n        //# }\n        public __vt__ Axis0;\n        public __vt__ Axis1;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __et__(__vt__ center, /*# if (d == 3) { */__vt__ normal, /*# } */__vt__ axis0, __vt__ axis1)\n        {\n            Center = center;\n            //# if (d == 3) {\n            Normal = normal;\n            //# }\n            Axis0 = axis0;\n            Axis1 = axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __et__(__et__ o)\n        {\n            Center = o.Center;\n            //# if (d == 3) {\n            Normal = o.Normal;\n            //# }\n            Axis0 = o.Axis0;\n            Axis1 = o.Axis1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __et__(__et2__ o)\n        {\n            Center = (__vt__)o.Center;\n            //# if (d == 3) {\n            Normal = (__vt__)o.Normal;\n            //# }\n            Axis0 = (__vt__)o.Axis0;\n            Axis1 = (__vt__)o.Axis1;\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// </summary>\n        public static __et__ FromConjugateDiameters(__vt__ center, /*# if (d == 3) { */__vt__ normal, /*# } */__vt__ a, __vt__ b)\n        {\n            var ab = Vec.Dot(a, b);\n            __ftype__ a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) return new __et__(center, /*# if (d == 3) { */normal, /*# } */a, b);\n                else return new __et__(center, /*# if (d == 3) { */normal, /*# } */b, a);\n            }\n            else\n            {\n                var t = __half__ * Fun.Atan2(2 * ab, a2 - b2);\n                __ftype__ ct = Fun.Cos(t), st = Fun.Sin(t);\n                __vt__ v0 = a * ct + b * st, v1 = b * ct - a * st;\n                if (v0.LengthSquared >= v1.LengthSquared) return new __et__(center, /*# if (d == 3) { */normal, /*# } */v0, v1);\n                else return new __et__(center, /*# if (d == 3) { */normal, /*# } */v1, v0);\n            }\n        }\n\n        /// <summary>\n        /// Construct ellipse from two conjugate diameters, and set\n        /// Axis0 to the major axis and Axis1 to the minor axis.\n        /// The algorithm was constructed from first principles.\n        /// Also computes the squared lengths of the major and minor\n        /// half axis.\n        /// </summary>\n        public static __et__ FromConjugateDiameters(__vt__ center, /*# if (d == 3) { */__vt__ normal, /*# } */__vt__ a, __vt__ b,\n                out __ftype__ major2, out __ftype__ minor2)\n        {\n            var ab = Vec.Dot(a, b);\n            __ftype__ a2 = a.LengthSquared, b2 = b.LengthSquared;\n            if (ab.IsTiny())\n            {\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new __et__(center, /*# if (d == 3) { */normal, /*# } */a, b); }\n                else { major2 = b2; minor2 = a2; return new __et__(center, /*# if (d == 3) { */normal, /*# } */b, a); }\n            }\n            else\n            {\n                var t = __half__ * Fun.Atan2(2 * ab, a2 - b2);\n                __ftype__ ct = Fun.Cos(t), st = Fun.Sin(t);\n                __vt__ v0 = a * ct + b * st, v1 = b * ct - a * st;\n                a2 = v0.LengthSquared; b2 = v1.LengthSquared;\n                if (a2 >= b2) { major2 = a2; minor2 = b2; return new __et__(center, /*# if (d == 3) { */normal, /*# } */v0, v1); }\n                else { major2 = b2; minor2 = a2; return new __et__(center, /*# if (d == 3) { */normal, /*# } */v1, v0); }\n            }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __et__(__et2__ o)\n            => new __et__(o);\n\n        #endregion\n\n        #region Constants\n\n        public static __et__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __et__(__vt__.Zero, /*# if (d == 3) { */__vt__.Zero, /*# } */__vt__.Zero, __vt__.Zero);\n        }\n\n        #endregion\n\n        #region Operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vt__ GetVector(__ftype__ alpha)\n            => Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vt__ GetPoint(__ftype__ alpha)\n            => Center + Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha);\n\n        /// <summary>\n        /// Perform the supplied action for each of count vectors from the center\n        /// of the ellipse to the circumference.\n        /// </summary>\n        public readonly void ForEachVector(int count, Action<int, __vt__> index_vector_act)\n        {\n            __ftype__ d = __constant__.PiTimesTwo / count;\n            __ftype__ a = Fun.Sin(d * __half__).Square() * 2, b = Fun.Sin(d); // init trig. recurrence\n            __ftype__ ct = 1, st = 0;\n\n            index_vector_act(0, Axis0);\n            for (int i = 1; i < count; i++)\n            {\n                __ftype__ dct = a * ct + b * st, dst = a * st - b * ct; ;  // trig. recurrence\n                ct -= dct; st -= dst;                                   // cos (t + d), sin (t + d)\n                index_vector_act(i, Axis0 * ct + Axis1 * st);\n            }\n        }\n\n        /// <summary>\n        /// Get count points on the circumference of the ellipse.\n        /// </summary>\n        public readonly __vt__[] GetPoints(int count)\n        {\n            var array = new __vt__[count];\n            var c = Center;\n            ForEachVector(count, (i, v) => array[i] = c + v);\n            return array;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__et__ a, __et__ b) =>\n            (a.Center == b.Center) &&\n            //# if (d == 3) {\n            (a.Normal == b.Normal) &&\n            //# }\n            (a.Axis0 == b.Axis0) &&\n            (a.Axis1 == b.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__et__ a, __et__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(Center, /*# if (d == 3) { */Normal, /*# }*/Axis0, Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__et__ other) =>\n            Center.Equals(other.Center) &&\n            //# if (d == 3) {\n            Normal.Equals(other.Normal) &&\n            //# }\n            Axis0.Equals(other.Axis0) &&\n            Axis1.Equals(other.Axis1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n             => (other is __et__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n        {\n            //# if (d == 3) {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", Center, Normal, Axis0, Axis1);\n            //# } else {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", Center, Axis0, Axis1);\n            //# }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __et__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __et__(\n                __vt__.Parse(x[0]),\n                __vt__.Parse(x[1]),\n                __vt__.Parse(x[2])/*# if (d == 3) { */,\n                __vt__.Parse(x[3])/*# }*/\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__et__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __et__ a, __et__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            //# if (d == 3) {\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            //# }\n            ApproximateEquals(a.Axis0, b.Axis0, tolerance) &&\n            ApproximateEquals(a.Axis1, b.Axis1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__et__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __et__ a, __et__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# } // d\n    //# } // ELLIPSES\n    //# } // isDouble\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Geometry1i.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    #region Line1i\n\n    public partial struct Line1i\n    {\n        #region Static Creator\n\n        public static Line1i CreateSorted(int i0, int i1)\n        {\n            return i0 < i1 ? new Line1i(i0, i1) : new Line1i(i1, i0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly Line1i Reversed { get { return new Line1i(I1, I0); } }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Triangle1i\n\n    public partial struct Triangle1i\n    {\n        #region Static Creator\n\n        public static Triangle1i CreateSorted(int i0, int i1, int i2)\n        {\n            if (i0 < i1)\n            {\n                if (i1 < i2)\n                    return new Triangle1i(i0, i1, i2);\n                else\n                {\n                    if (i0 < i2)\n                        return new Triangle1i(i0, i2, i1);\n                    else\n                        return new Triangle1i(i2, i0, i1);\n                }\n            }\n            else\n            {\n                if (i2 < i1)\n                    return new Triangle1i(i2, i1, i0);\n                else\n                {\n                    if (i0 < i2)\n                        return new Triangle1i(i1, i0, i2);\n                    else\n                        return new Triangle1i(i1, i2, i0);\n                }\n            }\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly Triangle1i Reversed { get { return new Triangle1i(I2, I1, I0); } }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Quad1i\n\n    public partial struct Quad1i\n    {\n        #region Properties\n\n        public readonly Quad1i Reversed { get { return new Quad1i(I3, I2, I1, I0); } }\n\n        #endregion\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Geometry1i_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Line1i\n\n    /// <summary>\n    /// A structure that holds the indices of the endpoints of a line.\n    /// </summary>\n    public partial struct Line1i : IEquatable<Line1i>\n    {\n        public int I0;\n        public int I1;\n\n        #region Constructor\n\n        public Line1i(int i0, int i1)\n        {\n            I0 = i0; I1 = i1; \n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly IEnumerable<int> Indices\n        {\n            get\n            {\n                yield return I0;\n                yield return I1;\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public int this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return I0;\n                    case 1: return I1;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: I0 = value; return;\n                    case 1: I1 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static Line1i Invalid => new Line1i { I0 = -1, I1 = -1 };\n\n        #endregion\n\n        #region Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Line1i a, Line1i b)\n        {\n            return a.I0 == b.I0 && a.I1 == b.I1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Line1i a, Line1i b)\n        {\n            return a.I0 != b.I0 || a.I1 != b.I1;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(I0, I1);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is Line1i o) ? Equals(o) : false;\n\n        #endregion\n\n        #region IEquatable<Line1i> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Line1i other)\n        {\n            return this == other;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Triangle1i\n\n    /// <summary>\n    /// A structure that holds the indices of the vertices of a triangle.\n    /// </summary>\n    public partial struct Triangle1i : IEquatable<Triangle1i>\n    {\n        public int I0;\n        public int I1;\n        public int I2;\n\n        #region Constructor\n\n        public Triangle1i(int i0, int i1, int i2)\n        {\n            I0 = i0; I1 = i1; I2 = i2; \n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly IEnumerable<int> Indices\n        {\n            get\n            {\n                yield return I0;\n                yield return I1;\n                yield return I2;\n            }\n        }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line01 { get { return new Line1i(I0, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line02 { get { return new Line1i(I0, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line10 { get { return new Line1i(I1, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line12 { get { return new Line1i(I1, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line20 { get { return new Line1i(I2, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line21 { get { return new Line1i(I2, I1); } }\n\n        #endregion\n\n        #region Indexer\n\n        public int this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return I0;\n                    case 1: return I1;\n                    case 2: return I2;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: I0 = value; return;\n                    case 1: I1 = value; return;\n                    case 2: I2 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static Triangle1i Invalid => new Triangle1i { I0 = -1, I1 = -1, I2 = -1 };\n\n        #endregion\n\n        #region Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Triangle1i a, Triangle1i b)\n        {\n            return a.I0 == b.I0 && a.I1 == b.I1 && a.I2 == b.I2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Triangle1i a, Triangle1i b)\n        {\n            return a.I0 != b.I0 || a.I1 != b.I1 || a.I2 != b.I2;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(I0, I1, I2);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is Triangle1i o) ? Equals(o) : false;\n\n        #endregion\n\n        #region IEquatable<Triangle1i> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Triangle1i other)\n        {\n            return this == other;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Quad1i\n\n    /// <summary>\n    /// A structure that holds the indices of the vertices of a quad.\n    /// </summary>\n    public partial struct Quad1i : IEquatable<Quad1i>\n    {\n        public int I0;\n        public int I1;\n        public int I2;\n        public int I3;\n\n        #region Constructor\n\n        public Quad1i(int i0, int i1, int i2, int i3)\n        {\n            I0 = i0; I1 = i1; I2 = i2; I3 = i3; \n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly IEnumerable<int> Indices\n        {\n            get\n            {\n                yield return I0;\n                yield return I1;\n                yield return I2;\n                yield return I3;\n            }\n        }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line01 { get { return new Line1i(I0, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line02 { get { return new Line1i(I0, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line03 { get { return new Line1i(I0, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line10 { get { return new Line1i(I1, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line12 { get { return new Line1i(I1, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line13 { get { return new Line1i(I1, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line20 { get { return new Line1i(I2, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line21 { get { return new Line1i(I2, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line23 { get { return new Line1i(I2, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line30 { get { return new Line1i(I3, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line31 { get { return new Line1i(I3, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line32 { get { return new Line1i(I3, I2); } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle012 { get { return new Triangle1i(I0, I1, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle013 { get { return new Triangle1i(I0, I1, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle021 { get { return new Triangle1i(I0, I2, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle023 { get { return new Triangle1i(I0, I2, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle031 { get { return new Triangle1i(I0, I3, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle032 { get { return new Triangle1i(I0, I3, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle102 { get { return new Triangle1i(I1, I0, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle103 { get { return new Triangle1i(I1, I0, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle120 { get { return new Triangle1i(I1, I2, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle123 { get { return new Triangle1i(I1, I2, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle130 { get { return new Triangle1i(I1, I3, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle132 { get { return new Triangle1i(I1, I3, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle201 { get { return new Triangle1i(I2, I0, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle203 { get { return new Triangle1i(I2, I0, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle210 { get { return new Triangle1i(I2, I1, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle213 { get { return new Triangle1i(I2, I1, I3); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle230 { get { return new Triangle1i(I2, I3, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle231 { get { return new Triangle1i(I2, I3, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle301 { get { return new Triangle1i(I3, I0, I1); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle302 { get { return new Triangle1i(I3, I0, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle310 { get { return new Triangle1i(I3, I1, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle312 { get { return new Triangle1i(I3, I1, I2); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle320 { get { return new Triangle1i(I3, I2, I0); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle321 { get { return new Triangle1i(I3, I2, I1); } }\n\n        #endregion\n\n        #region Indexer\n\n        public int this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return I0;\n                    case 1: return I1;\n                    case 2: return I2;\n                    case 3: return I3;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: I0 = value; return;\n                    case 1: I1 = value; return;\n                    case 2: I2 = value; return;\n                    case 3: I3 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static Quad1i Invalid => new Quad1i { I0 = -1, I1 = -1, I2 = -1, I3 = -1 };\n\n        #endregion\n\n        #region Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Quad1i a, Quad1i b)\n        {\n            return a.I0 == b.I0 && a.I1 == b.I1 && a.I2 == b.I2 && a.I3 == b.I3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Quad1i a, Quad1i b)\n        {\n            return a.I0 != b.I0 || a.I1 != b.I1 || a.I2 != b.I2 || a.I3 != b.I3;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(I0, I1, I2, I3);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is Quad1i o) ? Equals(o) : false;\n\n        #endregion\n\n        #region IEquatable<Quad1i> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Quad1i other)\n        {\n            return this == other;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Geometry1i_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action andand = () => Out(\" && \");\n    //# Action oror = () => Out(\" || \");\n    //# var types   = new[] { null, null,   \"Line1i\",   \"Triangle1i\",   \"Quad1i\"    };\n    //# var names   = new[] { null, null,   \"line\",     \"triangle\",     \"quad\"      };\n    //# var points  = new[] { null, null,   \"endpoint\", \"vertex\",       \"vertex\"    };\n    //#\n    //# for (int d = 2; d <= 4; d++)\n    //# {\n    //#     string type = types[d], name = names[d], point = points[d].Plural(d);\n    //#\n    #region __type__\n\n    /// <summary>\n    /// A structure that holds the indices of the __point__ of a __name__.\n    /// </summary>\n    public partial struct __type__ : IEquatable<__type__>\n    {\n        //# d.ForEach(i => {\n        public int I__i__;\n        //# });\n\n        #region Constructor\n\n        public __type__(/*# d.ForEach(i => { */int i__i__/*# }, comma); */)\n        {\n            /*# d.ForEach(i => { */I__i__ = i__i__; /*# }); */\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly IEnumerable<int> Indices\n        {\n            get\n            {\n                //# d.ForEach(i => {\n                yield return I__i__;\n                //# });\n            }\n        }\n\n        //# if (d > 2) {\n        //#     d.ForEach(i0 =>  {\n        //#         d.ForEach(i1 => { if (i1 != i0) {\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Line1i Line__i0____i1__ { get { return new Line1i(I__i0__, I__i1__); } }\n        //#         }});\n        //#     });\n\n        //# }\n        //# if (d > 3) {\n        //#     d.ForEach(i0 => {\n        //#         d.ForEach(i1 => { if (i1 != i0) {\n        //#             d.ForEach(i2 => { if (i2 != i1 && i2 != i0) {\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Triangle1i Triangle__i0____i1____i2__ { get { return new Triangle1i(I__i0__, I__i1__, I__i2__); } }\n        //#             }});\n        //#         }});\n        //#     });\n\n        //# }\n        #endregion\n\n        #region Indexer\n\n        public int this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    //# d.ForEach(i => {\n                    case __i__: return I__i__;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    //# d.ForEach(i => {\n                    case __i__: I__i__ = value; return;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static __type__ Invalid => new __type__ { /*# d.ForEach(i => { */I__i__ = -1/*# }, comma); */ };\n\n        #endregion\n\n        #region Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n        {\n            return /*# d.ForEach(i => { */a.I__i__ == b.I__i__/*# }, andand); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n        {\n            return /*# d.ForEach(i => { */a.I__i__ != b.I__i__/*# }, oror); */;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(/*# d.ForEach(i => { */I__i__/*# }, comma); */);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        #endregion\n\n        #region IEquatable<__type__> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n        {\n            return this == other;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Geometry_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Polygon2f\n\n    /// <summary>\n    /// A polygon internally represented by an array of points. Implemented\n    /// as a structure, the validity of the polygon can be checked via its\n    /// PointCount, which must be bigger than 0 for a polygon to hold any\n    /// points, and bigger than 2 for a polygon to be geometrically valid.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Polygon2f : IEquatable<Polygon2f>, IValidity, IPolygon<V2f>, IBoundingBox2f\n    {\n        internal int m_pointCount;\n        internal V2f[] m_pointArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon2f(V2f[] pointArray, int pointCount)\n        {\n            if (pointArray != null)\n            {\n                if (pointCount <= pointArray.Length)\n                {\n                    m_pointCount = pointCount;\n                    m_pointArray = pointArray;\n                }\n                else\n                    throw new ArgumentException(\n                                \"point count must be smaller or equal array length\");\n            }\n            else\n            {\n                m_pointCount = 0;\n                m_pointArray = null;\n            }\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon2f(params V2f[] pointArray)\n        {\n            m_pointCount = pointArray != null ? pointArray.Length : 0;\n            m_pointArray = pointArray;\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon2f(V2f[] pointArray, int startIndex, int count)\n        {\n            if (startIndex < 0 || startIndex >= pointArray.Length - 1) throw new ArgumentException();\n            if (count <= 0 || startIndex + count >= pointArray.Length) throw new ArgumentException();\n            m_pointCount = count;\n            m_pointArray = new V2f[count];\n            for (int i = 0; i < count; i++) m_pointArray[i] = pointArray[startIndex + i];\n        }\n\n        /// <summary>\n        /// Creates a polygon from point count and point creator function.\n        /// </summary>\n        public Polygon2f(int pointCount, Func<int, V2f> index_pointCreator)\n            : this(new V2f[pointCount].SetByIndex(index_pointCreator))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a sequence of points.\n        /// </summary>\n        public Polygon2f(IEnumerable<V2f> points)\n            : this(points.ToArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from the points of a pointArray that\n        /// are selected by an index array.\n        /// </summary>\n        public Polygon2f(int[] indexArray, V2f[] pointArray)\n            : this(indexArray.Map(i => pointArray[i]))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a triangle.\n        /// </summary>\n        public Polygon2f(Triangle2f triangle)\n            : this(triangle.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a quad.\n        /// </summary>\n        public Polygon2f(Quad2f quad)\n            : this(quad.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Copy constructor.\n        /// Performs deep copy of original.\n        /// </summary>\n        public Polygon2f(Polygon2f original)\n            : this(original.GetPointArray())\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Polygon2f Invalid = new Polygon2f(null, 0);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid => m_pointArray != null;\n\n        public readonly bool IsInvalid => m_pointArray == null;\n\n        /// <summary>\n        /// The number of points in the polygon. If this is 0, the polygon\n        /// is invalid.\n        /// </summary>\n        public readonly int PointCount => m_pointCount;\n\n        /// <summary>\n        /// Enumerates points.\n        /// </summary>\n        public readonly IEnumerable<V2f> Points\n        {\n            get { for (int pi = 0; pi < m_pointCount; pi++) yield return m_pointArray[pi]; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Returns a copy of the polygons point array.\n        /// </summary>\n        public readonly V2f[] GetPointArray()\n        {\n            var pc = m_pointCount;\n            var pa = new V2f[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            return pa;\n        }\n\n        /// <summary>\n        /// [P0, P1, P2] -> [P0, P1, P2, P0].\n        /// </summary>\n        public readonly V2f[] GetPointArrayWithRepeatedFirstPoint()\n        {\n            var pc = m_pointCount;\n            var pa = new V2f[pc + 1];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            pa[pc] = pa[0];\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<V2f, T> point_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_copyFun(m_pointArray[pi]);\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<V2f, int, T> point_index_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_index_copyFun(m_pointArray[pi], pi);\n            return pa;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets the index-th point of this polygon.\n        /// </summary>\n        public readonly V2f this[int index]\n        {\n            get { return m_pointArray[index]; }\n            set { m_pointArray[index] = value; }\n        }\n\n        #endregion\n\n        #region Edges and Lines\n\n        /// <summary>\n        /// Index-th edge as vector (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly V2f Edge(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return p1 - p0;\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly IEnumerable<V2f> Edges\n        {\n            get\n            {\n                var pc = m_pointCount;\n                var p = m_pointArray[0];\n                var p0 = p;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return p1 - p0;\n                    p0 = p1;\n                }\n                yield return p - p0;\n            }\n        }\n\n        /// <summary>\n        /// Index-th edge as line segment (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly Line2f EdgeLine(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return new Line2f(p0, p1);\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly IEnumerable<Line2f> EdgeLines\n        {\n            get\n            {\n                var pc = m_pointCount;\n                if (pc < 1) yield break;\n                var p0 = m_pointArray[0];\n                var p = p0;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return new Line2f(p0, p1);\n                    p0 = p1;\n                }\n                yield return new Line2f(p0, p);\n            }\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly V2f[] GetEdgeArray()\n        {\n            var pc = m_pointCount;\n            if (pc < 2) return Array.Empty<V2f>();\n            var edgeArray = new V2f[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                edgeArray[pi - 1] = p1 - p0;\n                p0 = p1;\n            }\n            edgeArray[pc - 1] = p - p0;\n            return edgeArray;\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly Line2f[] GetEdgeLineArray()\n        {\n            var pc = PointCount;\n            if (pc < 2) return Array.Empty<Line2f>();\n            var ela = new Line2f[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                ela[pi - 1] = new Line2f(p0, p1);\n                p0 = p1;\n            }\n            ela[pc - 1] = new Line2f(p0, p);\n            return ela;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Returns copy of polygon. Same as Map(p => p).\n        /// </summary>\n        public readonly Polygon2f Copy()\n        {\n            return new Polygon2f(m_pointArray.Copy());\n        }\n\n        /// <summary>\n        /// Returns transformed copy of this polygon.\n        /// </summary>\n        public readonly Polygon2f Map(Func<V2f, V2f> point_fun)\n        {\n            var pc = m_pointCount;\n            V2f[] opa = m_pointArray, npa = new V2f[pc];\n            for (int pi = 0; pi < pc; pi++) npa[pi] = point_fun(opa[pi]);\n            return new Polygon2f(npa, pc);\n        }\n\n        /// <summary>\n        /// Gets copy with reversed order of vertices.\n        /// </summary>\n        public readonly Polygon2f Reversed\n        {\n            get\n            {\n                var pc = m_pointCount;\n                V2f[] opa = m_pointArray, npa = new V2f[pc];\n                for (int pi = 0, pj = pc - 1; pi < pc; pi++, pj--) npa[pi] = opa[pj];\n                return new Polygon2f(npa, pc);\n            }\n        }\n\n        /// <summary>\n        /// Reverses order of vertices in-place.\n        /// </summary>\n        public readonly void Reverse()\n        {\n            var pa = m_pointArray;\n            for (int pi = 0, pj = m_pointCount - 1; pi < pj; pi++, pj--)\n            { var t = pa[pi]; pa[pi] = pa[pj]; pa[pj] = t; }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Polygon2f a, Polygon2f b)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (a.m_pointArray[pi] != b.m_pointArray[pi]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Polygon2f a, Polygon2f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return m_pointArray.GetCombinedHashCode(m_pointCount);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Polygon2f other)\n        {\n            if (m_pointCount != other.m_pointCount) return false;\n            for (int pi = 0; pi < m_pointCount; pi++)\n                if (!m_pointArray[pi].Equals(other.m_pointArray[pi])) return false;\n            return true;\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is Polygon2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture,\n                \"[{0}]\", Points.Select(x => x.ToString()).Join(\", \")\n                );\n        }\n\n        public static Polygon2f Parse(string s)\n        {\n            var va = s.NestedBracketSplitLevelOne().ToArray();\n            return new Polygon2f(va.Select(x => V2f.Parse(x)));\n        }\n\n        #endregion\n\n        #region IBoundingBox2f Members\n\n        /// <summary>\n        /// Bounding box of polygon.\n        /// </summary>\n        public readonly Box2f BoundingBox2f\n        {\n            get { return new Box2f(m_pointArray, 0, m_pointCount); }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Polygon2f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Polygon2f a, Polygon2f b, float tolerance)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (!ApproximateEquals(a.m_pointArray[pi], b.m_pointArray[pi], tolerance)) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Polygon2f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Polygon2f a, Polygon2f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Polygon2fExtensions\n\n    public static partial class Polygon2fExtensions\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static V2f ComputeVertexCentroid(this Polygon2f polygon)\n        {\n            var sum = V2f.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            float scale = 1 / (float)pc;\n            return sum * scale;\n        }\n\n        public static float ComputePerimeter(this Polygon2f polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            float r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon2f polygon, float scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Scaled(this Polygon2f polygon, float scale)\n        {\n            var result = new Polygon2f(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon2f polygon, V2f center, float scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Scaled(this Polygon2f polygon, V2f center, float scale)\n        {\n            var result = new Polygon2f(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref Polygon2f polygon, float scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f ScaledAboutVertexCentroid(this Polygon2f polygon, float scale)\n        {\n            var result = new Polygon2f(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon2f polygon, V2f scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Scaled(this Polygon2f polygon, V2f scale)\n        {\n            var result = new Polygon2f(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon2f polygon, V2f center, V2f scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Scaled(this Polygon2f polygon, V2f center, V2f scale)\n        {\n            var result = new Polygon2f(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref Polygon2f polygon, V2f scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f ScaledAboutVertexCentroid(this Polygon2f polygon, V2f scale)\n        {\n            var result = new Polygon2f(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2f polygon, M33f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Transformed(this Polygon2f polygon, M33f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2f polygon, Euclidean2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Transformed(this Polygon2f polygon, Euclidean2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the inverse of the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2f polygon, Euclidean2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the inverse of the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f InvTransformed(this Polygon2f polygon, Euclidean2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2f polygon, Similarity2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Transformed(this Polygon2f polygon, Similarity2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the inverse of the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2f polygon, Similarity2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the inverse of the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f InvTransformed(this Polygon2f polygon, Similarity2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the given <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2f polygon, Affine2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the given <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Transformed(this Polygon2f polygon, Affine2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2f polygon, Shift2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Transformed(this Polygon2f polygon, Shift2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the inverse of the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2f polygon, Shift2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the inverse of the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f InvTransformed(this Polygon2f polygon, Shift2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2f polygon, Rot2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Transformed(this Polygon2f polygon, Rot2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the inverse of the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2f polygon, Rot2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the inverse of the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f InvTransformed(this Polygon2f polygon, Rot2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2f polygon, Scale2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Transformed(this Polygon2f polygon, Scale2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the inverse of the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2f polygon, Scale2f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the inverse of the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f InvTransformed(this Polygon2f polygon, Scale2f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2f\"/> by the given <see cref=\"M22f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2f polygon, M22f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2f\"/> transformed by the given <see cref=\"M22f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f Transformed(this Polygon2f polygon, M22f t)\n        {\n            var result = new Polygon2f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        public static Polygon2f WithoutMultiplePoints(this Polygon2f polygon, float eps = 1e-5f)\n        {\n            eps *= eps;\n            var opc = polygon.PointCount;\n            var pa = new V2f[opc];\n            var pc = 0;\n            pa[0] = polygon[0];\n            for (int pi = 1; pi < opc; pi++)\n                if (Vec.DistanceSquared(pa[pc], polygon[pi]) > eps)\n                    pa[++pc] = polygon[pi];\n            if (Vec.DistanceSquared(pa[pc], polygon[0]) > eps)\n                ++pc;\n            return new Polygon2f(pa, pc);\n        }\n\n        #endregion\n\n        #region Clipping\n\n        /// <summary>\n        /// Clip the supplied polygon at the supplied line. The method should\n        /// work with all non-selfintersecting polygons. Returns all parts of\n        /// the polygon that are at the positive side of the line.\n        /// </summary>\n        public static Polygon2f ConvexClipped(\n                this Polygon2f polygon, Plane2f line, float eps = 1e-5f)\n        {\n            var opc = polygon.PointCount;\n            V2f[] pa = new V2f[opc + 1];\n            var pc = 0;\n            var pf = polygon[0];\n            var hf = line.Height(pf); bool hfp = hf > eps, hfn = hf < -eps;\n            if (hf >= -eps) pa[pc++] = pf;\n            var p0 = pf; var h0 = hf; var h0p = hfp; var h0n = hfn;\n            for (int vi = 1; vi < opc; vi++)\n            {\n                var p1 = polygon[vi];\n                var h1 = line.Height(p1); bool h1p = h1 > eps, h1n = h1 < -eps;\n                if (h0p && h1n || h0n && h1p) pa[pc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));\n                if (h1 >= -eps) pa[pc++] = p1;\n                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;\n            }\n            if (h0p && hfn || h0n && hfp) pa[pc++] = p0 + (pf - p0) * (h0 / (h0 - hf));\n            return new Polygon2f(pa, pc);\n        }\n\n        /// <summary>\n        /// Returns the convex polygon clipped by the set of lines (defined\n        /// as Plane2fs), i.e. all parts of the polygon that are at the positive\n        /// side of the lines.\n        /// </summary>\n        public static Polygon2f ConvexClipped(\n                this Polygon2f polygon, Plane2f[] lines, float eps = 1e-5f)\n        {\n            foreach (var c in lines)\n            {\n                polygon = polygon.ConvexClipped(c, eps);\n                if (polygon.PointCount == 0) break;\n            }\n            return polygon;\n        }\n\n        /// <summary>\n        /// Returns the polygon clipped by the hull, i.e. all parts of the\n        /// polygon that are at the positive side of the hull lines.\n        /// </summary>\n        public static Polygon2f ConvexClipped(\n                this Polygon2f polygon, Hull2f hull, float eps = 1e-5f)\n        {\n            return polygon.ConvexClipped(hull.PlaneArray, eps);\n        }\n\n        /// <summary>\n        /// TODO summary.\n        /// </summary>\n        public static Polygon2f ConvexClipped(\n                this Polygon2f polygon, Box2f box, float eps = 1e-5f)\n        {\n            var lines = new[]\n            {\n                new Plane2f(V2f.XAxis, box.Min), new Plane2f(-V2f.XAxis, box.Max),\n                new Plane2f(V2f.YAxis, box.Min), new Plane2f(-V2f.YAxis, box.Max),\n            };\n            return polygon.ConvexClipped(lines);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon2f\n\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct IndexPolygon2f : IValidity, IPolygon<V2f>\n    {\n        private readonly int m_pointCount;\n        private readonly int m_firstIndex;\n        private readonly int[] m_indexArray;\n        private readonly V2f[] m_pointArray;\n\n        #region Constructors\n\n        public IndexPolygon2f(int[] indexArray, int firstIndex, int pointCount, V2f[] pointArray)\n        {\n            m_indexArray = indexArray;\n            m_firstIndex = firstIndex;\n            m_pointCount = pointCount;\n            m_pointArray = pointArray;\n        }\n\n        public IndexPolygon2f(V2f[] pointArray, int firstIndex, int pointCount)\n            : this(new int[pointCount].SetByIndex(i => firstIndex + i), 0, pointCount, pointArray)\n        { }\n\n        public IndexPolygon2f(V2f[] pointArray)\n            : this(new int[pointArray.Length].SetByIndex(i => i), 0, pointArray.Length, pointArray)\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly IndexPolygon2f Invalid = new IndexPolygon2f(null, 0, 0, null);\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid { get { return m_indexArray != null && m_pointArray != null; } }\n        public bool IsInvalid { get { return m_indexArray == null || m_pointArray == null; } }\n\n        public int PointCount\n        {\n            get { return m_pointCount; }\n        }\n\n        public int FirstIndex { get { return m_firstIndex; } }\n\n        /// <summary>\n        /// The index array that contains the point indices of the\n        /// index polygon at the index range [FirstIndex, FirstIndex + PointCount).\n        /// NOTE: This is different from the array returned by GetIndexArray().\n        /// </summary>\n        public int[] IndexArray { get { return m_indexArray; } }\n\n        /// <summary>\n        /// The point array that contains the points referenced by\n        /// the index array. Note: This is different from the array\n        /// returned by GetPointArray().\n        /// </summary>\n        public V2f[] PointArray { get { return m_pointArray; } }\n\n        public IEnumerable<V2f> Points\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_pointArray[m_indexArray[m_firstIndex + i]];\n            }\n        }\n\n        public IEnumerable<int> Indices\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_indexArray[m_firstIndex + i];\n            }\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public V2f this[int index]\n        {\n            get { return m_pointArray[m_indexArray[m_firstIndex + index]]; }\n            set { m_pointArray[m_indexArray[m_firstIndex + index]] = value; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        public void ForEachIndex(Action<int> index_act)\n        {\n            var ia = m_indexArray; int fi = m_firstIndex;\n            for (int i = 0; i < m_pointCount; i++) index_act(ia[fi + i]);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual indices\n        /// of the index polygon. NOTE: This is different from the\n        /// IndexArray property!\n        /// </summary>\n        public int[] GetIndexArray()\n        {\n            return m_indexArray.Copy(m_firstIndex, m_pointCount);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual points\n        /// of the index polygon. NOTE: This is different from the\n        /// PointArray property!\n        /// </summary>\n        public V2f[] GetPointArray()\n        {\n            var pa = m_pointArray;\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pa[i]);\n        }\n\n        public T[] GetPointArray<T>(T[] pointArray)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointArray[i]);\n        }\n\n        public T[] GetPointArray<T>(List<T> pointList)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointList[i]);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon2fExtensions\n\n    public static partial class IndexPolygon2fExtensions\n    {\n        #region Conversions\n\n        public static Polygon2f ToPolygon2f(this IndexPolygon2f polygon)\n        {\n            return new Polygon2f(polygon.GetPointArray());\n        }\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static V2f ComputeVertexCentroid(this IndexPolygon2f polygon)\n        {\n            var sum = V2f.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            float scale = 1 / (float)pc;\n            return sum * scale;\n        }\n\n        public static float ComputePerimeter(this IndexPolygon2f polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            float r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Line2f\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Line2f : IEquatable<Line2f>, IValidity, IPolygon<V2f>, IBoundingBox2f\n    {\n        public V2f P0, P1;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates line from 2 points.\n        /// </summary>\n        public Line2f(V2f p0, V2f p1)\n        {\n            P0 = p0; P1 = p1;\n        }\n\n        /// <summary>\n        /// Creates line from first 2 points in the sequence.\n        /// </summary>\n        public Line2f(IEnumerable<V2f> points)\n        {\n            var pa = points.TakeToArray(2);\n            P0 = pa[0]; P1 = pa[1];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        public readonly int PointCount { get { return 2; } }\n\n        public readonly IEnumerable<V2f> Points\n        {\n            get { yield return P0; yield return P1; }\n        }\n\n        public readonly Line2f Reversed\n        {\n            get { return new Line2f(P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V2f this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Line2f Copy(Func<V2f, V2f> point_copyFun)\n        {\n            return new Line2f(point_copyFun(P0), point_copyFun(P1));\n        }\n\n        public readonly Line3d ToLine3d(Func<V2f, V3d> point_copyFun)\n        {\n            return new Line3d(point_copyFun(P0), point_copyFun(P1));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Line2f a, Line2f b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Line2f a, Line2f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Line2f other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1);\n\n        public override readonly bool Equals(object other)\n             => (other is Line2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", P0, P1);\n        }\n\n        public static Line2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Line2f(V2f.Parse(x[0]), V2f.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox2f Members\n\n        public readonly Box2f BoundingBox2f\n        {\n            get\n            {\n                return new Box2f(P0, P1).Repair();\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Line2f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Line2f a, Line2f b, float tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Line2f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Line2f a, Line2f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Line2fExtensions\n\n    public static partial class Line2fExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line2f polygon, float scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Scaled(this Line2f polygon, float scale)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line2f polygon, V2f center, float scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Scaled(this Line2f polygon, V2f center, float scale)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Line2f polygon, float scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f ScaledAboutCentroid(this Line2f polygon, float scale)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line2f polygon, V2f scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Scaled(this Line2f polygon, V2f scale)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line2f polygon, V2f center, V2f scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Scaled(this Line2f polygon, V2f center, V2f scale)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Line2f polygon, V2f scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f ScaledAboutCentroid(this Line2f polygon, V2f scale)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2f polygon, M33f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Transformed(this Line2f polygon, M33f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2f polygon, Euclidean2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Transformed(this Line2f polygon, Euclidean2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the inverse of the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2f polygon, Euclidean2f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the inverse of the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f InvTransformed(this Line2f polygon, Euclidean2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2f polygon, Similarity2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Transformed(this Line2f polygon, Similarity2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the inverse of the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2f polygon, Similarity2f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the inverse of the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f InvTransformed(this Line2f polygon, Similarity2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the given <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2f polygon, Affine2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the given <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Transformed(this Line2f polygon, Affine2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2f polygon, Shift2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Transformed(this Line2f polygon, Shift2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the inverse of the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2f polygon, Shift2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the inverse of the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f InvTransformed(this Line2f polygon, Shift2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2f polygon, Rot2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Transformed(this Line2f polygon, Rot2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the inverse of the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2f polygon, Rot2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the inverse of the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f InvTransformed(this Line2f polygon, Rot2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2f polygon, Scale2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Transformed(this Line2f polygon, Scale2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the inverse of the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2f polygon, Scale2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the inverse of the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f InvTransformed(this Line2f polygon, Scale2f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2f\"/> by the given <see cref=\"M22f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2f polygon, M22f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2f\"/> transformed by the given <see cref=\"M22f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2f Transformed(this Line2f polygon, M22f t)\n        {\n            var result = new Line2f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V2f[] GetPointArray(this Line2f line)\n        {\n            var pa = new V2f[2];\n            pa[0] = line.P0;\n            pa[1] = line.P1;\n            return pa;\n        }\n\n        public static V2f ComputeCentroid(this Line2f line)\n        {\n            return 0.5f * (line.P0 + line.P1);\n        }\n    }\n\n    #endregion\n\n    #region Triangle2f\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Triangle2f : IEquatable<Triangle2f>, IValidity, IPolygon<V2f>, IBoundingBox2f\n    {\n        public V2f P0, P1, P2;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates triangle from 3 points.\n        /// </summary>\n        public Triangle2f(V2f p0, V2f p1, V2f p2)\n        {\n            P0 = p0; P1 = p1; P2 = p2;\n        }\n\n        /// <summary>\n        /// Creates triangle from first 3 points in the sequence.\n        /// </summary>\n        public Triangle2f(IEnumerable<V2f> points)\n        {\n            var pa = points.TakeToArray(3);\n            P0 = pa[0]; P1 = pa[1]; P2 = pa[2];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        /// <summary>\n        /// Edge P1 - P0\n        /// </summary>\n        public readonly V2f Edge01 { get { return P1 - P0; } }\n        /// <summary>\n        /// Edge P2 - P0\n        /// </summary>\n        public readonly V2f Edge02 { get { return P2 - P0; } }\n        /// <summary>\n        /// Edge P2 - P1\n        /// </summary>\n        public readonly V2f Edge12 { get { return P2 - P1; } }\n        /// <summary>\n        /// Edge P0 - P1\n        /// </summary>\n        public readonly V2f Edge10 { get { return P0 - P1; } }\n        /// <summary>\n        /// Edge P0 - P2\n        /// </summary>\n        public readonly V2f Edge20 { get { return P0 - P2; } }\n        /// <summary>\n        /// Edge P1 - P2\n        /// </summary>\n        public readonly V2f Edge21 { get { return P1 - P2; } }\n\n        public readonly IEnumerable<V2f> Edges\n        {\n            get\n            {\n                yield return P1 - P0;\n                yield return P2 - P1;\n                yield return P0 - P2;\n            }\n        }\n\n        public readonly V2f[] EdgeArray\n        {\n            get\n            {\n                var a = new V2f[3];\n                a[0] = P1 - P0;\n                a[1] = P2 - P1;\n                a[2] = P0 - P2;\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<Line2f> EdgeLines\n        {\n            get\n            {\n                yield return new Line2f(P0, P1);\n                yield return new Line2f(P1, P2);\n                yield return new Line2f(P2, P0);\n            }\n        }\n\n        public readonly Line2f[] EdgeLineArray\n        {\n            get\n            {\n                var a = new Line2f[3];\n                a[0] = new Line2f(P0, P1);\n                a[1] = new Line2f(P1, P2);\n                a[2] = new Line2f(P2, P0);\n                return a;\n            }\n        }\n\n        public readonly Line2f GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Line2f(P0, P1);\n                case 1: return new Line2f(P1, P2);\n                case 2: return new Line2f(P2, P0);\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly V2f GetEdge(int index)\n        {\n            switch (index)\n            {\n                case 0: return P1 - P0;\n                case 1: return P2 - P1;\n                case 2: return P0 - P2;\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly Line2f Line01 { get { return new Line2f(P0, P1); } }\n        public readonly Line2f Line02 { get { return new Line2f(P0, P2); } }\n        public readonly Line2f Line12 { get { return new Line2f(P1, P2); } }\n        public readonly Line2f Line10 { get { return new Line2f(P1, P0); } }\n        public readonly Line2f Line20 { get { return new Line2f(P2, P0); } }\n        public readonly Line2f Line21 { get { return new Line2f(P2, P1); } }\n\n        public readonly int PointCount { get { return 3; } }\n\n        public readonly IEnumerable<V2f> Points\n        {\n            get { yield return P0; yield return P1; yield return P2; }\n        }\n\n        public readonly Triangle2f Reversed\n        {\n            get { return new Triangle2f(P2, P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V2f this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    case 2: return P2;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    case 2: P2 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Triangle2f Copy(Func<V2f, V2f> point_copyFun)\n        {\n            return new Triangle2f(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2));\n        }\n\n        public readonly Triangle3d ToTriangle3d(Func<V2f, V3d> point_copyFun)\n        {\n            return new Triangle3d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Triangle2f a, Triangle2f b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.P2 == b.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Triangle2f a, Triangle2f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1, P2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Triangle2f other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2);\n\n        public override readonly bool Equals(object other)\n             => (other is Triangle2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, P2);\n        }\n\n        public static Triangle2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Triangle2f(V2f.Parse(x[0]), V2f.Parse(x[1]), V2f.Parse(x[2]));\n        }\n\n        #endregion\n\n        #region IBoundingBox2f Members\n\n        public readonly Box2f BoundingBox2f\n        {\n            get\n            {\n                return new Box2f(P0, P1, P2);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Triangle2f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Triangle2f a, Triangle2f b, float tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance) && ApproximateEquals(a.P2, b.P2, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Triangle2f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Triangle2f a, Triangle2f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Triangle2fExtensions\n\n    public static partial class Triangle2fExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle2f polygon, float scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Scaled(this Triangle2f polygon, float scale)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle2f polygon, V2f center, float scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Scaled(this Triangle2f polygon, V2f center, float scale)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Triangle2f polygon, float scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f ScaledAboutCentroid(this Triangle2f polygon, float scale)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle2f polygon, V2f scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Scaled(this Triangle2f polygon, V2f scale)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle2f polygon, V2f center, V2f scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Scaled(this Triangle2f polygon, V2f center, V2f scale)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Triangle2f polygon, V2f scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f ScaledAboutCentroid(this Triangle2f polygon, V2f scale)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2f polygon, M33f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Transformed(this Triangle2f polygon, M33f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2f polygon, Euclidean2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Transformed(this Triangle2f polygon, Euclidean2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the inverse of the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2f polygon, Euclidean2f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the inverse of the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f InvTransformed(this Triangle2f polygon, Euclidean2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2f polygon, Similarity2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Transformed(this Triangle2f polygon, Similarity2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the inverse of the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2f polygon, Similarity2f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the inverse of the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f InvTransformed(this Triangle2f polygon, Similarity2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the given <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2f polygon, Affine2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the given <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Transformed(this Triangle2f polygon, Affine2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2f polygon, Shift2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Transformed(this Triangle2f polygon, Shift2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the inverse of the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2f polygon, Shift2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the inverse of the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f InvTransformed(this Triangle2f polygon, Shift2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2f polygon, Rot2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Transformed(this Triangle2f polygon, Rot2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the inverse of the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2f polygon, Rot2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the inverse of the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f InvTransformed(this Triangle2f polygon, Rot2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2f polygon, Scale2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Transformed(this Triangle2f polygon, Scale2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the inverse of the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2f polygon, Scale2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the inverse of the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f InvTransformed(this Triangle2f polygon, Scale2f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2f\"/> by the given <see cref=\"M22f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2f polygon, M22f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2f\"/> transformed by the given <see cref=\"M22f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2f Transformed(this Triangle2f polygon, M22f t)\n        {\n            var result = new Triangle2f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V2f[] GetPointArray(this Triangle2f triangle)\n        {\n            var pa = new V2f[3];\n            pa[0] = triangle.P0;\n            pa[1] = triangle.P1;\n            pa[2] = triangle.P2;\n            return pa;\n        }\n\n        public static V2f ComputeCentroid(this Triangle2f triangle)\n        {\n            return ConstantF.OneThird * (triangle.P0 + triangle.P1 + triangle.P2);\n        }\n    }\n\n    #endregion\n\n    #region Quad2f\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Quad2f : IEquatable<Quad2f>, IValidity, IPolygon<V2f>, IBoundingBox2f\n    {\n        public V2f P0, P1, P2, P3;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates quad from 4 points.\n        /// </summary>\n        public Quad2f(V2f p0, V2f p1, V2f p2, V2f p3)\n        {\n            P0 = p0; P1 = p1; P2 = p2; P3 = p3;\n        }\n\n        /// <summary>\n        /// Creates quad from first 4 points in the sequence.\n        /// </summary>\n        public Quad2f(IEnumerable<V2f> points)\n        {\n            var pa = points.TakeToArray(4);\n            P0 = pa[0]; P1 = pa[1]; P2 = pa[2]; P3 = pa[3];\n        }\n\n        /// <summary>\n        /// Creates quad from point and two vectors representing edges.\n        /// </summary>\n        public Quad2f(V2f p0, V2f edge01, V2f edge03)\n        {\n            P0 = p0;\n            P1 = p0 + edge01;\n            P2 = P1 + edge03;\n            P3 = p0 + edge03;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        /// <summary>\n        /// Edge P1 - P0\n        /// </summary>\n        public readonly V2f Edge01 { get { return P1 - P0; } }\n        /// <summary>\n        /// Edge P3 - P0\n        /// </summary>\n        public readonly V2f Edge03 { get { return P3 - P0; } }\n        /// <summary>\n        /// Edge P2 - P1\n        /// </summary>\n        public readonly V2f Edge12 { get { return P2 - P1; } }\n        /// <summary>\n        /// Edge P0 - P1\n        /// </summary>\n        public readonly V2f Edge10 { get { return P0 - P1; } }\n        /// <summary>\n        /// Edge P3 - P2\n        /// </summary>\n        public readonly V2f Edge23 { get { return P3 - P2; } }\n        /// <summary>\n        /// Edge P1 - P2\n        /// </summary>\n        public readonly V2f Edge21 { get { return P1 - P2; } }\n        /// <summary>\n        /// Edge P0 - P3\n        /// </summary>\n        public readonly V2f Edge30 { get { return P0 - P3; } }\n        /// <summary>\n        /// Edge P2 - P3\n        /// </summary>\n        public readonly V2f Edge32 { get { return P2 - P3; } }\n\n        public readonly IEnumerable<V2f> Edges\n        {\n            get\n            {\n                yield return P1 - P0;\n                yield return P2 - P1;\n                yield return P3 - P2;\n                yield return P0 - P3;\n            }\n        }\n\n        public readonly V2f[] EdgeArray\n        {\n            get\n            {\n                var a = new V2f[4];\n                a[0] = P1 - P0;\n                a[1] = P2 - P1;\n                a[2] = P3 - P2;\n                a[3] = P0 - P3;\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<Line2f> EdgeLines\n        {\n            get\n            {\n                yield return new Line2f(P0, P1);\n                yield return new Line2f(P1, P2);\n                yield return new Line2f(P2, P3);\n                yield return new Line2f(P3, P0);\n            }\n        }\n\n        public readonly Line2f[] EdgeLineArray\n        {\n            get\n            {\n                var a = new Line2f[4];\n                a[0] = new Line2f(P0, P1);\n                a[1] = new Line2f(P1, P2);\n                a[2] = new Line2f(P2, P3);\n                a[3] = new Line2f(P3, P0);\n                return a;\n            }\n        }\n\n        public readonly Line2f GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Line2f(P0, P1);\n                case 1: return new Line2f(P1, P2);\n                case 2: return new Line2f(P2, P3);\n                case 3: return new Line2f(P3, P0);\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly V2f GetEdge(int index)\n        {\n            switch (index)\n            {\n                case 0: return P1 - P0;\n                case 1: return P2 - P1;\n                case 2: return P3 - P2;\n                case 3: return P0 - P3;\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly Line2f Line01 { get { return new Line2f(P0, P1); } }\n        public readonly Line2f Line03 { get { return new Line2f(P0, P3); } }\n        public readonly Line2f Line12 { get { return new Line2f(P1, P2); } }\n        public readonly Line2f Line10 { get { return new Line2f(P1, P0); } }\n        public readonly Line2f Line23 { get { return new Line2f(P2, P3); } }\n        public readonly Line2f Line21 { get { return new Line2f(P2, P1); } }\n        public readonly Line2f Line30 { get { return new Line2f(P3, P0); } }\n        public readonly Line2f Line32 { get { return new Line2f(P3, P2); } }\n\n        public readonly int PointCount { get { return 4; } }\n\n        public readonly IEnumerable<V2f> Points\n        {\n            get { yield return P0; yield return P1; yield return P2; yield return P3; }\n        }\n\n        public readonly Quad2f Reversed\n        {\n            get { return new Quad2f(P3, P2, P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V2f this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    case 2: return P2;\n                    case 3: return P3;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    case 2: P2 = value; return;\n                    case 3: P3 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Quad2f Copy(Func<V2f, V2f> point_copyFun)\n        {\n            return new Quad2f(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2), point_copyFun(P3));\n        }\n\n        public readonly Quad3d ToQuad3d(Func<V2f, V3d> point_copyFun)\n        {\n            return new Quad3d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2), point_copyFun(P3));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Quad2f a, Quad2f b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.P2 == b.P2) && (a.P3 == b.P3);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Quad2f a, Quad2f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1, P2, P3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Quad2f other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2) && P3.Equals(other.P3);\n\n        public override readonly bool Equals(object other)\n             => (other is Quad2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", P0, P1, P2, P3);\n        }\n\n        public static Quad2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Quad2f(V2f.Parse(x[0]), V2f.Parse(x[1]), V2f.Parse(x[2]), V2f.Parse(x[3]));\n        }\n\n        #endregion\n\n        #region IBoundingBox2f Members\n\n        public readonly Box2f BoundingBox2f\n        {\n            get\n            {\n                return new Box2f(P0, P1, P2, P3);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Quad2f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Quad2f a, Quad2f b, float tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance) && ApproximateEquals(a.P2, b.P2, tolerance) && ApproximateEquals(a.P3, b.P3, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Quad2f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Quad2f a, Quad2f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Quad2fExtensions\n\n    public static partial class Quad2fExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad2f polygon, float scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n            polygon.P3 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Scaled(this Quad2f polygon, float scale)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad2f polygon, V2f center, float scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n            polygon.P3 = center + (polygon.P3 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Scaled(this Quad2f polygon, V2f center, float scale)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Quad2f polygon, float scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f ScaledAboutCentroid(this Quad2f polygon, float scale)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad2f polygon, V2f scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n            polygon.P3 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Scaled(this Quad2f polygon, V2f scale)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad2f polygon, V2f center, V2f scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n            polygon.P3 = center + (polygon.P3 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Scaled(this Quad2f polygon, V2f center, V2f scale)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Quad2f polygon, V2f scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f ScaledAboutCentroid(this Quad2f polygon, V2f scale)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2f polygon, M33f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Transformed(this Quad2f polygon, M33f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2f polygon, Euclidean2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Transformed(this Quad2f polygon, Euclidean2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the inverse of the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2f polygon, Euclidean2f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n            polygon.P3 = t.InvTransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the inverse of the given <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f InvTransformed(this Quad2f polygon, Euclidean2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2f polygon, Similarity2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Transformed(this Quad2f polygon, Similarity2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the inverse of the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2f polygon, Similarity2f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n            polygon.P3 = t.InvTransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the inverse of the given <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f InvTransformed(this Quad2f polygon, Similarity2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the given <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2f polygon, Affine2f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the given <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Transformed(this Quad2f polygon, Affine2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2f polygon, Shift2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Transformed(this Quad2f polygon, Shift2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the inverse of the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2f polygon, Shift2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the inverse of the given <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f InvTransformed(this Quad2f polygon, Shift2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2f polygon, Rot2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Transformed(this Quad2f polygon, Rot2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the inverse of the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2f polygon, Rot2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the inverse of the given <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f InvTransformed(this Quad2f polygon, Rot2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2f polygon, Scale2f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Transformed(this Quad2f polygon, Scale2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the inverse of the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2f polygon, Scale2f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the inverse of the given <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f InvTransformed(this Quad2f polygon, Scale2f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2f\"/> by the given <see cref=\"M22f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2f polygon, M22f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2f\"/> transformed by the given <see cref=\"M22f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2f Transformed(this Quad2f polygon, M22f t)\n        {\n            var result = new Quad2f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V2f[] GetPointArray(this Quad2f quad)\n        {\n            var pa = new V2f[4];\n            pa[0] = quad.P0;\n            pa[1] = quad.P1;\n            pa[2] = quad.P2;\n            pa[3] = quad.P3;\n            return pa;\n        }\n\n        public static V2f ComputeCentroid(this Quad2f quad)\n        {\n            return 0.25f * (quad.P0 + quad.P1 + quad.P2 + quad.P3);\n        }\n    }\n\n    #endregion\n\n    #region Polygon3f\n\n    /// <summary>\n    /// A polygon internally represented by an array of points. Implemented\n    /// as a structure, the validity of the polygon can be checked via its\n    /// PointCount, which must be bigger than 0 for a polygon to hold any\n    /// points, and bigger than 2 for a polygon to be geometrically valid.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Polygon3f : IEquatable<Polygon3f>, IValidity, IPolygon<V3f>, IBoundingBox3f\n    {\n        internal int m_pointCount;\n        internal V3f[] m_pointArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon3f(V3f[] pointArray, int pointCount)\n        {\n            if (pointArray != null)\n            {\n                if (pointCount <= pointArray.Length)\n                {\n                    m_pointCount = pointCount;\n                    m_pointArray = pointArray;\n                }\n                else\n                    throw new ArgumentException(\n                                \"point count must be smaller or equal array length\");\n            }\n            else\n            {\n                m_pointCount = 0;\n                m_pointArray = null;\n            }\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon3f(params V3f[] pointArray)\n        {\n            m_pointCount = pointArray != null ? pointArray.Length : 0;\n            m_pointArray = pointArray;\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon3f(V3f[] pointArray, int startIndex, int count)\n        {\n            if (startIndex < 0 || startIndex >= pointArray.Length - 1) throw new ArgumentException();\n            if (count <= 0 || startIndex + count >= pointArray.Length) throw new ArgumentException();\n            m_pointCount = count;\n            m_pointArray = new V3f[count];\n            for (int i = 0; i < count; i++) m_pointArray[i] = pointArray[startIndex + i];\n        }\n\n        /// <summary>\n        /// Creates a polygon from point count and point creator function.\n        /// </summary>\n        public Polygon3f(int pointCount, Func<int, V3f> index_pointCreator)\n            : this(new V3f[pointCount].SetByIndex(index_pointCreator))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a sequence of points.\n        /// </summary>\n        public Polygon3f(IEnumerable<V3f> points)\n            : this(points.ToArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from the points of a pointArray that\n        /// are selected by an index array.\n        /// </summary>\n        public Polygon3f(int[] indexArray, V3f[] pointArray)\n            : this(indexArray.Map(i => pointArray[i]))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a triangle.\n        /// </summary>\n        public Polygon3f(Triangle3f triangle)\n            : this(triangle.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a quad.\n        /// </summary>\n        public Polygon3f(Quad3f quad)\n            : this(quad.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Copy constructor.\n        /// Performs deep copy of original.\n        /// </summary>\n        public Polygon3f(Polygon3f original)\n            : this(original.GetPointArray())\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Polygon3f Invalid = new Polygon3f(null, 0);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid => m_pointArray != null;\n\n        public readonly bool IsInvalid => m_pointArray == null;\n\n        /// <summary>\n        /// The number of points in the polygon. If this is 0, the polygon\n        /// is invalid.\n        /// </summary>\n        public readonly int PointCount => m_pointCount;\n\n        /// <summary>\n        /// Enumerates points.\n        /// </summary>\n        public readonly IEnumerable<V3f> Points\n        {\n            get { for (int pi = 0; pi < m_pointCount; pi++) yield return m_pointArray[pi]; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Returns a copy of the polygons point array.\n        /// </summary>\n        public readonly V3f[] GetPointArray()\n        {\n            var pc = m_pointCount;\n            var pa = new V3f[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            return pa;\n        }\n\n        /// <summary>\n        /// [P0, P1, P2] -> [P0, P1, P2, P0].\n        /// </summary>\n        public readonly V3f[] GetPointArrayWithRepeatedFirstPoint()\n        {\n            var pc = m_pointCount;\n            var pa = new V3f[pc + 1];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            pa[pc] = pa[0];\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<V3f, T> point_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_copyFun(m_pointArray[pi]);\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<V3f, int, T> point_index_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_index_copyFun(m_pointArray[pi], pi);\n            return pa;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets the index-th point of this polygon.\n        /// </summary>\n        public readonly V3f this[int index]\n        {\n            get { return m_pointArray[index]; }\n            set { m_pointArray[index] = value; }\n        }\n\n        #endregion\n\n        #region Edges and Lines\n\n        /// <summary>\n        /// Index-th edge as vector (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly V3f Edge(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return p1 - p0;\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly IEnumerable<V3f> Edges\n        {\n            get\n            {\n                var pc = m_pointCount;\n                var p = m_pointArray[0];\n                var p0 = p;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return p1 - p0;\n                    p0 = p1;\n                }\n                yield return p - p0;\n            }\n        }\n\n        /// <summary>\n        /// Index-th edge as line segment (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly Line3f EdgeLine(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return new Line3f(p0, p1);\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly IEnumerable<Line3f> EdgeLines\n        {\n            get\n            {\n                var pc = m_pointCount;\n                if (pc < 1) yield break;\n                var p0 = m_pointArray[0];\n                var p = p0;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return new Line3f(p0, p1);\n                    p0 = p1;\n                }\n                yield return new Line3f(p0, p);\n            }\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly V3f[] GetEdgeArray()\n        {\n            var pc = m_pointCount;\n            if (pc < 2) return Array.Empty<V3f>();\n            var edgeArray = new V3f[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                edgeArray[pi - 1] = p1 - p0;\n                p0 = p1;\n            }\n            edgeArray[pc - 1] = p - p0;\n            return edgeArray;\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly Line3f[] GetEdgeLineArray()\n        {\n            var pc = PointCount;\n            if (pc < 2) return Array.Empty<Line3f>();\n            var ela = new Line3f[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                ela[pi - 1] = new Line3f(p0, p1);\n                p0 = p1;\n            }\n            ela[pc - 1] = new Line3f(p0, p);\n            return ela;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Returns copy of polygon. Same as Map(p => p).\n        /// </summary>\n        public readonly Polygon3f Copy()\n        {\n            return new Polygon3f(m_pointArray.Copy());\n        }\n\n        /// <summary>\n        /// Returns transformed copy of this polygon.\n        /// </summary>\n        public readonly Polygon3f Map(Func<V3f, V3f> point_fun)\n        {\n            var pc = m_pointCount;\n            V3f[] opa = m_pointArray, npa = new V3f[pc];\n            for (int pi = 0; pi < pc; pi++) npa[pi] = point_fun(opa[pi]);\n            return new Polygon3f(npa, pc);\n        }\n\n        /// <summary>\n        /// Gets copy with reversed order of vertices.\n        /// </summary>\n        public readonly Polygon3f Reversed\n        {\n            get\n            {\n                var pc = m_pointCount;\n                V3f[] opa = m_pointArray, npa = new V3f[pc];\n                for (int pi = 0, pj = pc - 1; pi < pc; pi++, pj--) npa[pi] = opa[pj];\n                return new Polygon3f(npa, pc);\n            }\n        }\n\n        /// <summary>\n        /// Reverses order of vertices in-place.\n        /// </summary>\n        public readonly void Reverse()\n        {\n            var pa = m_pointArray;\n            for (int pi = 0, pj = m_pointCount - 1; pi < pj; pi++, pj--)\n            { var t = pa[pi]; pa[pi] = pa[pj]; pa[pj] = t; }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Polygon3f a, Polygon3f b)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (a.m_pointArray[pi] != b.m_pointArray[pi]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Polygon3f a, Polygon3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return m_pointArray.GetCombinedHashCode(m_pointCount);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Polygon3f other)\n        {\n            if (m_pointCount != other.m_pointCount) return false;\n            for (int pi = 0; pi < m_pointCount; pi++)\n                if (!m_pointArray[pi].Equals(other.m_pointArray[pi])) return false;\n            return true;\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is Polygon3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture,\n                \"[{0}]\", Points.Select(x => x.ToString()).Join(\", \")\n                );\n        }\n\n        public static Polygon3f Parse(string s)\n        {\n            var va = s.NestedBracketSplitLevelOne().ToArray();\n            return new Polygon3f(va.Select(x => V3f.Parse(x)));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        /// <summary>\n        /// Bounding box of polygon.\n        /// </summary>\n        public readonly Box3f BoundingBox3f\n        {\n            get { return new Box3f(m_pointArray, 0, m_pointCount); }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Polygon3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Polygon3f a, Polygon3f b, float tolerance)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (!ApproximateEquals(a.m_pointArray[pi], b.m_pointArray[pi], tolerance)) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Polygon3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Polygon3f a, Polygon3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Polygon3fExtensions\n\n    public static partial class Polygon3fExtensions\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static V3f ComputeVertexCentroid(this Polygon3f polygon)\n        {\n            var sum = V3f.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            float scale = 1 / (float)pc;\n            return sum * scale;\n        }\n\n        public static float ComputePerimeter(this Polygon3f polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            float r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon3f polygon, float scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Scaled(this Polygon3f polygon, float scale)\n        {\n            var result = new Polygon3f(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon3f polygon, V3f center, float scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Scaled(this Polygon3f polygon, V3f center, float scale)\n        {\n            var result = new Polygon3f(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref Polygon3f polygon, float scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f ScaledAboutVertexCentroid(this Polygon3f polygon, float scale)\n        {\n            var result = new Polygon3f(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon3f polygon, V3f scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Scaled(this Polygon3f polygon, V3f scale)\n        {\n            var result = new Polygon3f(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon3f polygon, V3f center, V3f scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Scaled(this Polygon3f polygon, V3f center, V3f scale)\n        {\n            var result = new Polygon3f(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref Polygon3f polygon, V3f scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f ScaledAboutVertexCentroid(this Polygon3f polygon, V3f scale)\n        {\n            var result = new Polygon3f(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the given <see cref=\"M44f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3f polygon, M44f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the given <see cref=\"M44f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Transformed(this Polygon3f polygon, M44f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3f polygon, Euclidean3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Transformed(this Polygon3f polygon, Euclidean3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the inverse of the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3f polygon, Euclidean3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the inverse of the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f InvTransformed(this Polygon3f polygon, Euclidean3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3f polygon, Similarity3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Transformed(this Polygon3f polygon, Similarity3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the inverse of the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3f polygon, Similarity3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the inverse of the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f InvTransformed(this Polygon3f polygon, Similarity3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3f polygon, Affine3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Transformed(this Polygon3f polygon, Affine3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3f polygon, Shift3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Transformed(this Polygon3f polygon, Shift3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the inverse of the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3f polygon, Shift3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the inverse of the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f InvTransformed(this Polygon3f polygon, Shift3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3f polygon, Rot3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Transformed(this Polygon3f polygon, Rot3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the inverse of the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3f polygon, Rot3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the inverse of the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f InvTransformed(this Polygon3f polygon, Rot3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3f polygon, Scale3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Transformed(this Polygon3f polygon, Scale3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the inverse of the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3f polygon, Scale3f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the inverse of the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f InvTransformed(this Polygon3f polygon, Scale3f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3f\"/> by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3f polygon, M33f t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3f\"/> transformed by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3f Transformed(this Polygon3f polygon, M33f t)\n        {\n            var result = new Polygon3f(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        public static Polygon3f WithoutMultiplePoints(this Polygon3f polygon, float eps = 1e-5f)\n        {\n            eps *= eps;\n            var opc = polygon.PointCount;\n            var pa = new V3f[opc];\n            var pc = 0;\n            pa[0] = polygon[0];\n            for (int pi = 1; pi < opc; pi++)\n                if (Vec.DistanceSquared(pa[pc], polygon[pi]) > eps)\n                    pa[++pc] = polygon[pi];\n            if (Vec.DistanceSquared(pa[pc], polygon[0]) > eps)\n                ++pc;\n            return new Polygon3f(pa, pc);\n        }\n\n        #endregion\n\n        #region Clipping\n\n        /// <summary>\n        /// Clip the supplied polygon at the supplied plane. The method should\n        /// work with all non-selfintersecting polygons. Returns all parts of\n        /// the polygon that are at the positive side of the plane.\n        /// </summary>\n        public static Polygon3f ConvexClipped(\n                this Polygon3f polygon, Plane3f plane, float eps = 1e-5f)\n        {\n            var opc = polygon.PointCount;\n            V3f[] pa = new V3f[opc + 1];\n            var pc = 0;\n            var pf = polygon[0];\n            var hf = plane.Height(pf); bool hfp = hf > eps, hfn = hf < -eps;\n            if (hf >= -eps) pa[pc++] = pf;\n            var p0 = pf; var h0 = hf; var h0p = hfp; var h0n = hfn;\n            for (int vi = 1; vi < opc; vi++)\n            {\n                var p1 = polygon[vi];\n                var h1 = plane.Height(p1); bool h1p = h1 > eps, h1n = h1 < -eps;\n                if (h0p && h1n || h0n && h1p) pa[pc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));\n                if (h1 >= -eps) pa[pc++] = p1;\n                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;\n            }\n            if (h0p && hfn || h0n && hfp) pa[pc++] = p0 + (pf - p0) * (h0 / (h0 - hf));\n            return new Polygon3f(pa, pc);\n        }\n\n        /// <summary>\n        /// Returns the convex polygon clipped by the set of planes (defined\n        /// as Plane3fs), i.e. all parts of the polygon that are at the positive\n        /// side of the planes.\n        /// </summary>\n        public static Polygon3f ConvexClipped(\n                this Polygon3f polygon, Plane3f[] planes, float eps = 1e-5f)\n        {\n            foreach (var c in planes)\n            {\n                polygon = polygon.ConvexClipped(c, eps);\n                if (polygon.PointCount == 0) break;\n            }\n            return polygon;\n        }\n\n        /// <summary>\n        /// Returns the polygon clipped by the hull, i.e. all parts of the\n        /// polygon that are at the positive side of the hull planes.\n        /// </summary>\n        public static Polygon3f ConvexClipped(\n                this Polygon3f polygon, Hull3f hull, float eps = 1e-5f)\n        {\n            return polygon.ConvexClipped(hull.PlaneArray, eps);\n        }\n\n        /// <summary>\n        /// TODO summary.\n        /// </summary>\n        public static Polygon3f ConvexClipped(\n                this Polygon3f polygon, Box3f box, float eps = 1e-5f)\n        {\n            var planes = new[]\n            {\n                new Plane3f(V3f.XAxis, box.Min), new Plane3f(-V3f.XAxis, box.Max),\n                new Plane3f(V3f.YAxis, box.Min), new Plane3f(-V3f.YAxis, box.Max),\n                new Plane3f(V3f.ZAxis, box.Min), new Plane3f(-V3f.ZAxis, box.Max),\n            };\n            return polygon.ConvexClipped(planes);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon3f\n\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct IndexPolygon3f : IValidity, IPolygon<V3f>\n    {\n        private readonly int m_pointCount;\n        private readonly int m_firstIndex;\n        private readonly int[] m_indexArray;\n        private readonly V3f[] m_pointArray;\n\n        #region Constructors\n\n        public IndexPolygon3f(int[] indexArray, int firstIndex, int pointCount, V3f[] pointArray)\n        {\n            m_indexArray = indexArray;\n            m_firstIndex = firstIndex;\n            m_pointCount = pointCount;\n            m_pointArray = pointArray;\n        }\n\n        public IndexPolygon3f(V3f[] pointArray, int firstIndex, int pointCount)\n            : this(new int[pointCount].SetByIndex(i => firstIndex + i), 0, pointCount, pointArray)\n        { }\n\n        public IndexPolygon3f(V3f[] pointArray)\n            : this(new int[pointArray.Length].SetByIndex(i => i), 0, pointArray.Length, pointArray)\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly IndexPolygon3f Invalid = new IndexPolygon3f(null, 0, 0, null);\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid { get { return m_indexArray != null && m_pointArray != null; } }\n        public bool IsInvalid { get { return m_indexArray == null || m_pointArray == null; } }\n\n        public int PointCount\n        {\n            get { return m_pointCount; }\n        }\n\n        public int FirstIndex { get { return m_firstIndex; } }\n\n        /// <summary>\n        /// The index array that contains the point indices of the\n        /// index polygon at the index range [FirstIndex, FirstIndex + PointCount).\n        /// NOTE: This is different from the array returned by GetIndexArray().\n        /// </summary>\n        public int[] IndexArray { get { return m_indexArray; } }\n\n        /// <summary>\n        /// The point array that contains the points referenced by\n        /// the index array. Note: This is different from the array\n        /// returned by GetPointArray().\n        /// </summary>\n        public V3f[] PointArray { get { return m_pointArray; } }\n\n        public IEnumerable<V3f> Points\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_pointArray[m_indexArray[m_firstIndex + i]];\n            }\n        }\n\n        public IEnumerable<int> Indices\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_indexArray[m_firstIndex + i];\n            }\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public V3f this[int index]\n        {\n            get { return m_pointArray[m_indexArray[m_firstIndex + index]]; }\n            set { m_pointArray[m_indexArray[m_firstIndex + index]] = value; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        public void ForEachIndex(Action<int> index_act)\n        {\n            var ia = m_indexArray; int fi = m_firstIndex;\n            for (int i = 0; i < m_pointCount; i++) index_act(ia[fi + i]);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual indices\n        /// of the index polygon. NOTE: This is different from the\n        /// IndexArray property!\n        /// </summary>\n        public int[] GetIndexArray()\n        {\n            return m_indexArray.Copy(m_firstIndex, m_pointCount);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual points\n        /// of the index polygon. NOTE: This is different from the\n        /// PointArray property!\n        /// </summary>\n        public V3f[] GetPointArray()\n        {\n            var pa = m_pointArray;\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pa[i]);\n        }\n\n        public T[] GetPointArray<T>(T[] pointArray)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointArray[i]);\n        }\n\n        public T[] GetPointArray<T>(List<T> pointList)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointList[i]);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon3fExtensions\n\n    public static partial class IndexPolygon3fExtensions\n    {\n        #region Conversions\n\n        public static Polygon3f ToPolygon3f(this IndexPolygon3f polygon)\n        {\n            return new Polygon3f(polygon.GetPointArray());\n        }\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static V3f ComputeVertexCentroid(this IndexPolygon3f polygon)\n        {\n            var sum = V3f.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            float scale = 1 / (float)pc;\n            return sum * scale;\n        }\n\n        public static float ComputePerimeter(this IndexPolygon3f polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            float r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Line3f\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Line3f : IEquatable<Line3f>, IValidity, IPolygon<V3f>, IBoundingBox3f\n    {\n        public V3f P0, P1;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates line from 2 points.\n        /// </summary>\n        public Line3f(V3f p0, V3f p1)\n        {\n            P0 = p0; P1 = p1;\n        }\n\n        /// <summary>\n        /// Creates line from first 2 points in the sequence.\n        /// </summary>\n        public Line3f(IEnumerable<V3f> points)\n        {\n            var pa = points.TakeToArray(2);\n            P0 = pa[0]; P1 = pa[1];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        public readonly int PointCount { get { return 2; } }\n\n        public readonly IEnumerable<V3f> Points\n        {\n            get { yield return P0; yield return P1; }\n        }\n\n        public readonly Line3f Reversed\n        {\n            get { return new Line3f(P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V3f this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Line3f Copy(Func<V3f, V3f> point_copyFun)\n        {\n            return new Line3f(point_copyFun(P0), point_copyFun(P1));\n        }\n\n        public readonly Line2d ToLine2d(Func<V3f, V2d> point_copyFun)\n        {\n            return new Line2d(point_copyFun(P0), point_copyFun(P1));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Line3f a, Line3f b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Line3f a, Line3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Line3f other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1);\n\n        public override readonly bool Equals(object other)\n             => (other is Line3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", P0, P1);\n        }\n\n        public static Line3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Line3f(V3f.Parse(x[0]), V3f.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        public readonly Box3f BoundingBox3f\n        {\n            get\n            {\n                return new Box3f(P0, P1).Repair();\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Line3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Line3f a, Line3f b, float tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Line3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Line3f a, Line3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Line3fExtensions\n\n    public static partial class Line3fExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line3f polygon, float scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Scaled(this Line3f polygon, float scale)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line3f polygon, V3f center, float scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Scaled(this Line3f polygon, V3f center, float scale)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Line3f polygon, float scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f ScaledAboutCentroid(this Line3f polygon, float scale)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line3f polygon, V3f scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Scaled(this Line3f polygon, V3f scale)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line3f polygon, V3f center, V3f scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Scaled(this Line3f polygon, V3f center, V3f scale)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Line3f polygon, V3f scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f ScaledAboutCentroid(this Line3f polygon, V3f scale)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the given <see cref=\"M44f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3f polygon, M44f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the given <see cref=\"M44f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Transformed(this Line3f polygon, M44f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3f polygon, Euclidean3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Transformed(this Line3f polygon, Euclidean3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the inverse of the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3f polygon, Euclidean3f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the inverse of the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f InvTransformed(this Line3f polygon, Euclidean3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3f polygon, Similarity3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Transformed(this Line3f polygon, Similarity3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the inverse of the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3f polygon, Similarity3f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the inverse of the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f InvTransformed(this Line3f polygon, Similarity3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3f polygon, Affine3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Transformed(this Line3f polygon, Affine3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3f polygon, Shift3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Transformed(this Line3f polygon, Shift3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the inverse of the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3f polygon, Shift3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the inverse of the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f InvTransformed(this Line3f polygon, Shift3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3f polygon, Rot3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Transformed(this Line3f polygon, Rot3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the inverse of the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3f polygon, Rot3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the inverse of the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f InvTransformed(this Line3f polygon, Rot3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3f polygon, Scale3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Transformed(this Line3f polygon, Scale3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the inverse of the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3f polygon, Scale3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the inverse of the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f InvTransformed(this Line3f polygon, Scale3f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3f\"/> by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3f polygon, M33f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3f\"/> transformed by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3f Transformed(this Line3f polygon, M33f t)\n        {\n            var result = new Line3f(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V3f[] GetPointArray(this Line3f line)\n        {\n            var pa = new V3f[2];\n            pa[0] = line.P0;\n            pa[1] = line.P1;\n            return pa;\n        }\n\n        public static V3f ComputeCentroid(this Line3f line)\n        {\n            return 0.5f * (line.P0 + line.P1);\n        }\n    }\n\n    #endregion\n\n    #region Triangle3f\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Triangle3f : IEquatable<Triangle3f>, IValidity, IPolygon<V3f>, IBoundingBox3f\n    {\n        public V3f P0, P1, P2;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates triangle from 3 points.\n        /// </summary>\n        public Triangle3f(V3f p0, V3f p1, V3f p2)\n        {\n            P0 = p0; P1 = p1; P2 = p2;\n        }\n\n        /// <summary>\n        /// Creates triangle from first 3 points in the sequence.\n        /// </summary>\n        public Triangle3f(IEnumerable<V3f> points)\n        {\n            var pa = points.TakeToArray(3);\n            P0 = pa[0]; P1 = pa[1]; P2 = pa[2];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        /// <summary>\n        /// Edge P1 - P0\n        /// </summary>\n        public readonly V3f Edge01 { get { return P1 - P0; } }\n        /// <summary>\n        /// Edge P2 - P0\n        /// </summary>\n        public readonly V3f Edge02 { get { return P2 - P0; } }\n        /// <summary>\n        /// Edge P2 - P1\n        /// </summary>\n        public readonly V3f Edge12 { get { return P2 - P1; } }\n        /// <summary>\n        /// Edge P0 - P1\n        /// </summary>\n        public readonly V3f Edge10 { get { return P0 - P1; } }\n        /// <summary>\n        /// Edge P0 - P2\n        /// </summary>\n        public readonly V3f Edge20 { get { return P0 - P2; } }\n        /// <summary>\n        /// Edge P1 - P2\n        /// </summary>\n        public readonly V3f Edge21 { get { return P1 - P2; } }\n\n        public readonly IEnumerable<V3f> Edges\n        {\n            get\n            {\n                yield return P1 - P0;\n                yield return P2 - P1;\n                yield return P0 - P2;\n            }\n        }\n\n        public readonly V3f[] EdgeArray\n        {\n            get\n            {\n                var a = new V3f[3];\n                a[0] = P1 - P0;\n                a[1] = P2 - P1;\n                a[2] = P0 - P2;\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<Line3f> EdgeLines\n        {\n            get\n            {\n                yield return new Line3f(P0, P1);\n                yield return new Line3f(P1, P2);\n                yield return new Line3f(P2, P0);\n            }\n        }\n\n        public readonly Line3f[] EdgeLineArray\n        {\n            get\n            {\n                var a = new Line3f[3];\n                a[0] = new Line3f(P0, P1);\n                a[1] = new Line3f(P1, P2);\n                a[2] = new Line3f(P2, P0);\n                return a;\n            }\n        }\n\n        public readonly Line3f GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Line3f(P0, P1);\n                case 1: return new Line3f(P1, P2);\n                case 2: return new Line3f(P2, P0);\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly V3f GetEdge(int index)\n        {\n            switch (index)\n            {\n                case 0: return P1 - P0;\n                case 1: return P2 - P1;\n                case 2: return P0 - P2;\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly Line3f Line01 { get { return new Line3f(P0, P1); } }\n        public readonly Line3f Line02 { get { return new Line3f(P0, P2); } }\n        public readonly Line3f Line12 { get { return new Line3f(P1, P2); } }\n        public readonly Line3f Line10 { get { return new Line3f(P1, P0); } }\n        public readonly Line3f Line20 { get { return new Line3f(P2, P0); } }\n        public readonly Line3f Line21 { get { return new Line3f(P2, P1); } }\n\n        public readonly int PointCount { get { return 3; } }\n\n        public readonly IEnumerable<V3f> Points\n        {\n            get { yield return P0; yield return P1; yield return P2; }\n        }\n\n        public readonly Triangle3f Reversed\n        {\n            get { return new Triangle3f(P2, P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V3f this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    case 2: return P2;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    case 2: P2 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Triangle3f Copy(Func<V3f, V3f> point_copyFun)\n        {\n            return new Triangle3f(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2));\n        }\n\n        public readonly Triangle2d ToTriangle2d(Func<V3f, V2d> point_copyFun)\n        {\n            return new Triangle2d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Triangle3f a, Triangle3f b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.P2 == b.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Triangle3f a, Triangle3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1, P2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Triangle3f other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2);\n\n        public override readonly bool Equals(object other)\n             => (other is Triangle3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, P2);\n        }\n\n        public static Triangle3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Triangle3f(V3f.Parse(x[0]), V3f.Parse(x[1]), V3f.Parse(x[2]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        public readonly Box3f BoundingBox3f\n        {\n            get\n            {\n                return new Box3f(P0, P1, P2);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Triangle3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Triangle3f a, Triangle3f b, float tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance) && ApproximateEquals(a.P2, b.P2, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Triangle3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Triangle3f a, Triangle3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Triangle3fExtensions\n\n    public static partial class Triangle3fExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle3f polygon, float scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Scaled(this Triangle3f polygon, float scale)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle3f polygon, V3f center, float scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Scaled(this Triangle3f polygon, V3f center, float scale)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Triangle3f polygon, float scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f ScaledAboutCentroid(this Triangle3f polygon, float scale)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle3f polygon, V3f scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Scaled(this Triangle3f polygon, V3f scale)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle3f polygon, V3f center, V3f scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Scaled(this Triangle3f polygon, V3f center, V3f scale)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Triangle3f polygon, V3f scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f ScaledAboutCentroid(this Triangle3f polygon, V3f scale)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the given <see cref=\"M44f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3f polygon, M44f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the given <see cref=\"M44f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Transformed(this Triangle3f polygon, M44f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3f polygon, Euclidean3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Transformed(this Triangle3f polygon, Euclidean3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the inverse of the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3f polygon, Euclidean3f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the inverse of the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f InvTransformed(this Triangle3f polygon, Euclidean3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3f polygon, Similarity3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Transformed(this Triangle3f polygon, Similarity3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the inverse of the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3f polygon, Similarity3f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the inverse of the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f InvTransformed(this Triangle3f polygon, Similarity3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3f polygon, Affine3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Transformed(this Triangle3f polygon, Affine3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3f polygon, Shift3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Transformed(this Triangle3f polygon, Shift3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the inverse of the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3f polygon, Shift3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the inverse of the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f InvTransformed(this Triangle3f polygon, Shift3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3f polygon, Rot3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Transformed(this Triangle3f polygon, Rot3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the inverse of the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3f polygon, Rot3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the inverse of the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f InvTransformed(this Triangle3f polygon, Rot3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3f polygon, Scale3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Transformed(this Triangle3f polygon, Scale3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the inverse of the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3f polygon, Scale3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the inverse of the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f InvTransformed(this Triangle3f polygon, Scale3f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3f\"/> by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3f polygon, M33f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3f\"/> transformed by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3f Transformed(this Triangle3f polygon, M33f t)\n        {\n            var result = new Triangle3f(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V3f[] GetPointArray(this Triangle3f triangle)\n        {\n            var pa = new V3f[3];\n            pa[0] = triangle.P0;\n            pa[1] = triangle.P1;\n            pa[2] = triangle.P2;\n            return pa;\n        }\n\n        public static V3f ComputeCentroid(this Triangle3f triangle)\n        {\n            return ConstantF.OneThird * (triangle.P0 + triangle.P1 + triangle.P2);\n        }\n    }\n\n    #endregion\n\n    #region Quad3f\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Quad3f : IEquatable<Quad3f>, IValidity, IPolygon<V3f>, IBoundingBox3f\n    {\n        public V3f P0, P1, P2, P3;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates quad from 4 points.\n        /// </summary>\n        public Quad3f(V3f p0, V3f p1, V3f p2, V3f p3)\n        {\n            P0 = p0; P1 = p1; P2 = p2; P3 = p3;\n        }\n\n        /// <summary>\n        /// Creates quad from first 4 points in the sequence.\n        /// </summary>\n        public Quad3f(IEnumerable<V3f> points)\n        {\n            var pa = points.TakeToArray(4);\n            P0 = pa[0]; P1 = pa[1]; P2 = pa[2]; P3 = pa[3];\n        }\n\n        /// <summary>\n        /// Creates quad from point and two vectors representing edges.\n        /// </summary>\n        public Quad3f(V3f p0, V3f edge01, V3f edge03)\n        {\n            P0 = p0;\n            P1 = p0 + edge01;\n            P2 = P1 + edge03;\n            P3 = p0 + edge03;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        /// <summary>\n        /// Edge P1 - P0\n        /// </summary>\n        public readonly V3f Edge01 { get { return P1 - P0; } }\n        /// <summary>\n        /// Edge P3 - P0\n        /// </summary>\n        public readonly V3f Edge03 { get { return P3 - P0; } }\n        /// <summary>\n        /// Edge P2 - P1\n        /// </summary>\n        public readonly V3f Edge12 { get { return P2 - P1; } }\n        /// <summary>\n        /// Edge P0 - P1\n        /// </summary>\n        public readonly V3f Edge10 { get { return P0 - P1; } }\n        /// <summary>\n        /// Edge P3 - P2\n        /// </summary>\n        public readonly V3f Edge23 { get { return P3 - P2; } }\n        /// <summary>\n        /// Edge P1 - P2\n        /// </summary>\n        public readonly V3f Edge21 { get { return P1 - P2; } }\n        /// <summary>\n        /// Edge P0 - P3\n        /// </summary>\n        public readonly V3f Edge30 { get { return P0 - P3; } }\n        /// <summary>\n        /// Edge P2 - P3\n        /// </summary>\n        public readonly V3f Edge32 { get { return P2 - P3; } }\n\n        public readonly IEnumerable<V3f> Edges\n        {\n            get\n            {\n                yield return P1 - P0;\n                yield return P2 - P1;\n                yield return P3 - P2;\n                yield return P0 - P3;\n            }\n        }\n\n        public readonly V3f[] EdgeArray\n        {\n            get\n            {\n                var a = new V3f[4];\n                a[0] = P1 - P0;\n                a[1] = P2 - P1;\n                a[2] = P3 - P2;\n                a[3] = P0 - P3;\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<Line3f> EdgeLines\n        {\n            get\n            {\n                yield return new Line3f(P0, P1);\n                yield return new Line3f(P1, P2);\n                yield return new Line3f(P2, P3);\n                yield return new Line3f(P3, P0);\n            }\n        }\n\n        public readonly Line3f[] EdgeLineArray\n        {\n            get\n            {\n                var a = new Line3f[4];\n                a[0] = new Line3f(P0, P1);\n                a[1] = new Line3f(P1, P2);\n                a[2] = new Line3f(P2, P3);\n                a[3] = new Line3f(P3, P0);\n                return a;\n            }\n        }\n\n        public readonly Line3f GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Line3f(P0, P1);\n                case 1: return new Line3f(P1, P2);\n                case 2: return new Line3f(P2, P3);\n                case 3: return new Line3f(P3, P0);\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly V3f GetEdge(int index)\n        {\n            switch (index)\n            {\n                case 0: return P1 - P0;\n                case 1: return P2 - P1;\n                case 2: return P3 - P2;\n                case 3: return P0 - P3;\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly Line3f Line01 { get { return new Line3f(P0, P1); } }\n        public readonly Line3f Line03 { get { return new Line3f(P0, P3); } }\n        public readonly Line3f Line12 { get { return new Line3f(P1, P2); } }\n        public readonly Line3f Line10 { get { return new Line3f(P1, P0); } }\n        public readonly Line3f Line23 { get { return new Line3f(P2, P3); } }\n        public readonly Line3f Line21 { get { return new Line3f(P2, P1); } }\n        public readonly Line3f Line30 { get { return new Line3f(P3, P0); } }\n        public readonly Line3f Line32 { get { return new Line3f(P3, P2); } }\n\n        public readonly int PointCount { get { return 4; } }\n\n        public readonly IEnumerable<V3f> Points\n        {\n            get { yield return P0; yield return P1; yield return P2; yield return P3; }\n        }\n\n        public readonly Quad3f Reversed\n        {\n            get { return new Quad3f(P3, P2, P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V3f this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    case 2: return P2;\n                    case 3: return P3;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    case 2: P2 = value; return;\n                    case 3: P3 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Quad3f Copy(Func<V3f, V3f> point_copyFun)\n        {\n            return new Quad3f(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2), point_copyFun(P3));\n        }\n\n        public readonly Quad2d ToQuad2d(Func<V3f, V2d> point_copyFun)\n        {\n            return new Quad2d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2), point_copyFun(P3));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Quad3f a, Quad3f b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.P2 == b.P2) && (a.P3 == b.P3);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Quad3f a, Quad3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1, P2, P3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Quad3f other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2) && P3.Equals(other.P3);\n\n        public override readonly bool Equals(object other)\n             => (other is Quad3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", P0, P1, P2, P3);\n        }\n\n        public static Quad3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Quad3f(V3f.Parse(x[0]), V3f.Parse(x[1]), V3f.Parse(x[2]), V3f.Parse(x[3]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        public readonly Box3f BoundingBox3f\n        {\n            get\n            {\n                return new Box3f(P0, P1, P2, P3);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Quad3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Quad3f a, Quad3f b, float tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance) && ApproximateEquals(a.P2, b.P2, tolerance) && ApproximateEquals(a.P3, b.P3, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Quad3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Quad3f a, Quad3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Quad3fExtensions\n\n    public static partial class Quad3fExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad3f polygon, float scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n            polygon.P3 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Scaled(this Quad3f polygon, float scale)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad3f polygon, V3f center, float scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n            polygon.P3 = center + (polygon.P3 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Scaled(this Quad3f polygon, V3f center, float scale)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Quad3f polygon, float scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f ScaledAboutCentroid(this Quad3f polygon, float scale)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3f\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad3f polygon, V3f scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n            polygon.P3 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Scaled(this Quad3f polygon, V3f scale)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3f\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad3f polygon, V3f center, V3f scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n            polygon.P3 = center + (polygon.P3 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Scaled(this Quad3f polygon, V3f center, V3f scale)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3f\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Quad3f polygon, V3f scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f ScaledAboutCentroid(this Quad3f polygon, V3f scale)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the given <see cref=\"M44f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3f polygon, M44f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the given <see cref=\"M44f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Transformed(this Quad3f polygon, M44f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3f polygon, Euclidean3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Transformed(this Quad3f polygon, Euclidean3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the inverse of the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3f polygon, Euclidean3f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n            polygon.P3 = t.InvTransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the inverse of the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f InvTransformed(this Quad3f polygon, Euclidean3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3f polygon, Similarity3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Transformed(this Quad3f polygon, Similarity3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the inverse of the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3f polygon, Similarity3f t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n            polygon.P3 = t.InvTransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the inverse of the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f InvTransformed(this Quad3f polygon, Similarity3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3f polygon, Affine3f t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Transformed(this Quad3f polygon, Affine3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3f polygon, Shift3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Transformed(this Quad3f polygon, Shift3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the inverse of the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3f polygon, Shift3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the inverse of the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f InvTransformed(this Quad3f polygon, Shift3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3f polygon, Rot3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Transformed(this Quad3f polygon, Rot3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the inverse of the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3f polygon, Rot3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the inverse of the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f InvTransformed(this Quad3f polygon, Rot3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3f polygon, Scale3f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Transformed(this Quad3f polygon, Scale3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the inverse of the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3f polygon, Scale3f t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the inverse of the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f InvTransformed(this Quad3f polygon, Scale3f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3f\"/> by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3f\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3f polygon, M33f t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3f\"/> transformed by the given <see cref=\"M33f\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3f to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3f Transformed(this Quad3f polygon, M33f t)\n        {\n            var result = new Quad3f(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V3f[] GetPointArray(this Quad3f quad)\n        {\n            var pa = new V3f[4];\n            pa[0] = quad.P0;\n            pa[1] = quad.P1;\n            pa[2] = quad.P2;\n            pa[3] = quad.P3;\n            return pa;\n        }\n\n        public static V3f ComputeCentroid(this Quad3f quad)\n        {\n            return 0.25f * (quad.P0 + quad.P1 + quad.P2 + quad.P3);\n        }\n    }\n\n    #endregion\n\n    #region Polygon2d\n\n    /// <summary>\n    /// A polygon internally represented by an array of points. Implemented\n    /// as a structure, the validity of the polygon can be checked via its\n    /// PointCount, which must be bigger than 0 for a polygon to hold any\n    /// points, and bigger than 2 for a polygon to be geometrically valid.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Polygon2d : IEquatable<Polygon2d>, IValidity, IPolygon<V2d>, IBoundingBox2d\n    {\n        internal int m_pointCount;\n        internal V2d[] m_pointArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon2d(V2d[] pointArray, int pointCount)\n        {\n            if (pointArray != null)\n            {\n                if (pointCount <= pointArray.Length)\n                {\n                    m_pointCount = pointCount;\n                    m_pointArray = pointArray;\n                }\n                else\n                    throw new ArgumentException(\n                                \"point count must be smaller or equal array length\");\n            }\n            else\n            {\n                m_pointCount = 0;\n                m_pointArray = null;\n            }\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon2d(params V2d[] pointArray)\n        {\n            m_pointCount = pointArray != null ? pointArray.Length : 0;\n            m_pointArray = pointArray;\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon2d(V2d[] pointArray, int startIndex, int count)\n        {\n            if (startIndex < 0 || startIndex >= pointArray.Length - 1) throw new ArgumentException();\n            if (count <= 0 || startIndex + count >= pointArray.Length) throw new ArgumentException();\n            m_pointCount = count;\n            m_pointArray = new V2d[count];\n            for (int i = 0; i < count; i++) m_pointArray[i] = pointArray[startIndex + i];\n        }\n\n        /// <summary>\n        /// Creates a polygon from point count and point creator function.\n        /// </summary>\n        public Polygon2d(int pointCount, Func<int, V2d> index_pointCreator)\n            : this(new V2d[pointCount].SetByIndex(index_pointCreator))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a sequence of points.\n        /// </summary>\n        public Polygon2d(IEnumerable<V2d> points)\n            : this(points.ToArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from the points of a pointArray that\n        /// are selected by an index array.\n        /// </summary>\n        public Polygon2d(int[] indexArray, V2d[] pointArray)\n            : this(indexArray.Map(i => pointArray[i]))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a triangle.\n        /// </summary>\n        public Polygon2d(Triangle2d triangle)\n            : this(triangle.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a quad.\n        /// </summary>\n        public Polygon2d(Quad2d quad)\n            : this(quad.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Copy constructor.\n        /// Performs deep copy of original.\n        /// </summary>\n        public Polygon2d(Polygon2d original)\n            : this(original.GetPointArray())\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Polygon2d Invalid = new Polygon2d(null, 0);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid => m_pointArray != null;\n\n        public readonly bool IsInvalid => m_pointArray == null;\n\n        /// <summary>\n        /// The number of points in the polygon. If this is 0, the polygon\n        /// is invalid.\n        /// </summary>\n        public readonly int PointCount => m_pointCount;\n\n        /// <summary>\n        /// Enumerates points.\n        /// </summary>\n        public readonly IEnumerable<V2d> Points\n        {\n            get { for (int pi = 0; pi < m_pointCount; pi++) yield return m_pointArray[pi]; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Returns a copy of the polygons point array.\n        /// </summary>\n        public readonly V2d[] GetPointArray()\n        {\n            var pc = m_pointCount;\n            var pa = new V2d[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            return pa;\n        }\n\n        /// <summary>\n        /// [P0, P1, P2] -> [P0, P1, P2, P0].\n        /// </summary>\n        public readonly V2d[] GetPointArrayWithRepeatedFirstPoint()\n        {\n            var pc = m_pointCount;\n            var pa = new V2d[pc + 1];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            pa[pc] = pa[0];\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<V2d, T> point_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_copyFun(m_pointArray[pi]);\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<V2d, int, T> point_index_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_index_copyFun(m_pointArray[pi], pi);\n            return pa;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets the index-th point of this polygon.\n        /// </summary>\n        public readonly V2d this[int index]\n        {\n            get { return m_pointArray[index]; }\n            set { m_pointArray[index] = value; }\n        }\n\n        #endregion\n\n        #region Edges and Lines\n\n        /// <summary>\n        /// Index-th edge as vector (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly V2d Edge(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return p1 - p0;\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly IEnumerable<V2d> Edges\n        {\n            get\n            {\n                var pc = m_pointCount;\n                var p = m_pointArray[0];\n                var p0 = p;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return p1 - p0;\n                    p0 = p1;\n                }\n                yield return p - p0;\n            }\n        }\n\n        /// <summary>\n        /// Index-th edge as line segment (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly Line2d EdgeLine(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return new Line2d(p0, p1);\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly IEnumerable<Line2d> EdgeLines\n        {\n            get\n            {\n                var pc = m_pointCount;\n                if (pc < 1) yield break;\n                var p0 = m_pointArray[0];\n                var p = p0;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return new Line2d(p0, p1);\n                    p0 = p1;\n                }\n                yield return new Line2d(p0, p);\n            }\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly V2d[] GetEdgeArray()\n        {\n            var pc = m_pointCount;\n            if (pc < 2) return Array.Empty<V2d>();\n            var edgeArray = new V2d[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                edgeArray[pi - 1] = p1 - p0;\n                p0 = p1;\n            }\n            edgeArray[pc - 1] = p - p0;\n            return edgeArray;\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly Line2d[] GetEdgeLineArray()\n        {\n            var pc = PointCount;\n            if (pc < 2) return Array.Empty<Line2d>();\n            var ela = new Line2d[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                ela[pi - 1] = new Line2d(p0, p1);\n                p0 = p1;\n            }\n            ela[pc - 1] = new Line2d(p0, p);\n            return ela;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Returns copy of polygon. Same as Map(p => p).\n        /// </summary>\n        public readonly Polygon2d Copy()\n        {\n            return new Polygon2d(m_pointArray.Copy());\n        }\n\n        /// <summary>\n        /// Returns transformed copy of this polygon.\n        /// </summary>\n        public readonly Polygon2d Map(Func<V2d, V2d> point_fun)\n        {\n            var pc = m_pointCount;\n            V2d[] opa = m_pointArray, npa = new V2d[pc];\n            for (int pi = 0; pi < pc; pi++) npa[pi] = point_fun(opa[pi]);\n            return new Polygon2d(npa, pc);\n        }\n\n        /// <summary>\n        /// Gets copy with reversed order of vertices.\n        /// </summary>\n        public readonly Polygon2d Reversed\n        {\n            get\n            {\n                var pc = m_pointCount;\n                V2d[] opa = m_pointArray, npa = new V2d[pc];\n                for (int pi = 0, pj = pc - 1; pi < pc; pi++, pj--) npa[pi] = opa[pj];\n                return new Polygon2d(npa, pc);\n            }\n        }\n\n        /// <summary>\n        /// Reverses order of vertices in-place.\n        /// </summary>\n        public readonly void Reverse()\n        {\n            var pa = m_pointArray;\n            for (int pi = 0, pj = m_pointCount - 1; pi < pj; pi++, pj--)\n            { var t = pa[pi]; pa[pi] = pa[pj]; pa[pj] = t; }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Polygon2d a, Polygon2d b)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (a.m_pointArray[pi] != b.m_pointArray[pi]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Polygon2d a, Polygon2d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return m_pointArray.GetCombinedHashCode(m_pointCount);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Polygon2d other)\n        {\n            if (m_pointCount != other.m_pointCount) return false;\n            for (int pi = 0; pi < m_pointCount; pi++)\n                if (!m_pointArray[pi].Equals(other.m_pointArray[pi])) return false;\n            return true;\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is Polygon2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture,\n                \"[{0}]\", Points.Select(x => x.ToString()).Join(\", \")\n                );\n        }\n\n        public static Polygon2d Parse(string s)\n        {\n            var va = s.NestedBracketSplitLevelOne().ToArray();\n            return new Polygon2d(va.Select(x => V2d.Parse(x)));\n        }\n\n        #endregion\n\n        #region IBoundingBox2d Members\n\n        /// <summary>\n        /// Bounding box of polygon.\n        /// </summary>\n        public readonly Box2d BoundingBox2d\n        {\n            get { return new Box2d(m_pointArray, 0, m_pointCount); }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Polygon2d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Polygon2d a, Polygon2d b, double tolerance)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (!ApproximateEquals(a.m_pointArray[pi], b.m_pointArray[pi], tolerance)) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Polygon2d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Polygon2d a, Polygon2d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Polygon2dExtensions\n\n    public static partial class Polygon2dExtensions\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static V2d ComputeVertexCentroid(this Polygon2d polygon)\n        {\n            var sum = V2d.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            double scale = 1 / (double)pc;\n            return sum * scale;\n        }\n\n        public static double ComputePerimeter(this Polygon2d polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            double r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon2d polygon, double scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Scaled(this Polygon2d polygon, double scale)\n        {\n            var result = new Polygon2d(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon2d polygon, V2d center, double scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Scaled(this Polygon2d polygon, V2d center, double scale)\n        {\n            var result = new Polygon2d(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref Polygon2d polygon, double scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d ScaledAboutVertexCentroid(this Polygon2d polygon, double scale)\n        {\n            var result = new Polygon2d(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon2d polygon, V2d scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Scaled(this Polygon2d polygon, V2d scale)\n        {\n            var result = new Polygon2d(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon2d polygon, V2d center, V2d scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Scaled(this Polygon2d polygon, V2d center, V2d scale)\n        {\n            var result = new Polygon2d(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon2d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref Polygon2d polygon, V2d scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d ScaledAboutVertexCentroid(this Polygon2d polygon, V2d scale)\n        {\n            var result = new Polygon2d(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2d polygon, M33d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Transformed(this Polygon2d polygon, M33d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2d polygon, Euclidean2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Transformed(this Polygon2d polygon, Euclidean2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the inverse of the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2d polygon, Euclidean2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the inverse of the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d InvTransformed(this Polygon2d polygon, Euclidean2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2d polygon, Similarity2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Transformed(this Polygon2d polygon, Similarity2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the inverse of the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2d polygon, Similarity2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the inverse of the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d InvTransformed(this Polygon2d polygon, Similarity2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the given <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2d polygon, Affine2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the given <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Transformed(this Polygon2d polygon, Affine2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2d polygon, Shift2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Transformed(this Polygon2d polygon, Shift2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the inverse of the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2d polygon, Shift2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the inverse of the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d InvTransformed(this Polygon2d polygon, Shift2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2d polygon, Rot2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Transformed(this Polygon2d polygon, Rot2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the inverse of the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2d polygon, Rot2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the inverse of the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d InvTransformed(this Polygon2d polygon, Rot2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2d polygon, Scale2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Transformed(this Polygon2d polygon, Scale2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the inverse of the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon2d polygon, Scale2d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the inverse of the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d InvTransformed(this Polygon2d polygon, Scale2d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon2d\"/> by the given <see cref=\"M22d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon2d polygon, M22d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon2d\"/> transformed by the given <see cref=\"M22d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d Transformed(this Polygon2d polygon, M22d t)\n        {\n            var result = new Polygon2d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        public static Polygon2d WithoutMultiplePoints(this Polygon2d polygon, double eps = 1e-8)\n        {\n            eps *= eps;\n            var opc = polygon.PointCount;\n            var pa = new V2d[opc];\n            var pc = 0;\n            pa[0] = polygon[0];\n            for (int pi = 1; pi < opc; pi++)\n                if (Vec.DistanceSquared(pa[pc], polygon[pi]) > eps)\n                    pa[++pc] = polygon[pi];\n            if (Vec.DistanceSquared(pa[pc], polygon[0]) > eps)\n                ++pc;\n            return new Polygon2d(pa, pc);\n        }\n\n        #endregion\n\n        #region Clipping\n\n        /// <summary>\n        /// Clip the supplied polygon at the supplied line. The method should\n        /// work with all non-selfintersecting polygons. Returns all parts of\n        /// the polygon that are at the positive side of the line.\n        /// </summary>\n        public static Polygon2d ConvexClipped(\n                this Polygon2d polygon, Plane2d line, double eps = 1e-8)\n        {\n            var opc = polygon.PointCount;\n            V2d[] pa = new V2d[opc + 1];\n            var pc = 0;\n            var pf = polygon[0];\n            var hf = line.Height(pf); bool hfp = hf > eps, hfn = hf < -eps;\n            if (hf >= -eps) pa[pc++] = pf;\n            var p0 = pf; var h0 = hf; var h0p = hfp; var h0n = hfn;\n            for (int vi = 1; vi < opc; vi++)\n            {\n                var p1 = polygon[vi];\n                var h1 = line.Height(p1); bool h1p = h1 > eps, h1n = h1 < -eps;\n                if (h0p && h1n || h0n && h1p) pa[pc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));\n                if (h1 >= -eps) pa[pc++] = p1;\n                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;\n            }\n            if (h0p && hfn || h0n && hfp) pa[pc++] = p0 + (pf - p0) * (h0 / (h0 - hf));\n            return new Polygon2d(pa, pc);\n        }\n\n        /// <summary>\n        /// Returns the convex polygon clipped by the set of lines (defined\n        /// as Plane2ds), i.e. all parts of the polygon that are at the positive\n        /// side of the lines.\n        /// </summary>\n        public static Polygon2d ConvexClipped(\n                this Polygon2d polygon, Plane2d[] lines, double eps = 1e-8)\n        {\n            foreach (var c in lines)\n            {\n                polygon = polygon.ConvexClipped(c, eps);\n                if (polygon.PointCount == 0) break;\n            }\n            return polygon;\n        }\n\n        /// <summary>\n        /// Returns the polygon clipped by the hull, i.e. all parts of the\n        /// polygon that are at the positive side of the hull lines.\n        /// </summary>\n        public static Polygon2d ConvexClipped(\n                this Polygon2d polygon, Hull2d hull, double eps = 1e-8)\n        {\n            return polygon.ConvexClipped(hull.PlaneArray, eps);\n        }\n\n        /// <summary>\n        /// TODO summary.\n        /// </summary>\n        public static Polygon2d ConvexClipped(\n                this Polygon2d polygon, Box2d box, double eps = 1e-8)\n        {\n            var lines = new[]\n            {\n                new Plane2d(V2d.XAxis, box.Min), new Plane2d(-V2d.XAxis, box.Max),\n                new Plane2d(V2d.YAxis, box.Min), new Plane2d(-V2d.YAxis, box.Max),\n            };\n            return polygon.ConvexClipped(lines);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon2d\n\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct IndexPolygon2d : IValidity, IPolygon<V2d>\n    {\n        private readonly int m_pointCount;\n        private readonly int m_firstIndex;\n        private readonly int[] m_indexArray;\n        private readonly V2d[] m_pointArray;\n\n        #region Constructors\n\n        public IndexPolygon2d(int[] indexArray, int firstIndex, int pointCount, V2d[] pointArray)\n        {\n            m_indexArray = indexArray;\n            m_firstIndex = firstIndex;\n            m_pointCount = pointCount;\n            m_pointArray = pointArray;\n        }\n\n        public IndexPolygon2d(V2d[] pointArray, int firstIndex, int pointCount)\n            : this(new int[pointCount].SetByIndex(i => firstIndex + i), 0, pointCount, pointArray)\n        { }\n\n        public IndexPolygon2d(V2d[] pointArray)\n            : this(new int[pointArray.Length].SetByIndex(i => i), 0, pointArray.Length, pointArray)\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly IndexPolygon2d Invalid = new IndexPolygon2d(null, 0, 0, null);\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid { get { return m_indexArray != null && m_pointArray != null; } }\n        public bool IsInvalid { get { return m_indexArray == null || m_pointArray == null; } }\n\n        public int PointCount\n        {\n            get { return m_pointCount; }\n        }\n\n        public int FirstIndex { get { return m_firstIndex; } }\n\n        /// <summary>\n        /// The index array that contains the point indices of the\n        /// index polygon at the index range [FirstIndex, FirstIndex + PointCount).\n        /// NOTE: This is different from the array returned by GetIndexArray().\n        /// </summary>\n        public int[] IndexArray { get { return m_indexArray; } }\n\n        /// <summary>\n        /// The point array that contains the points referenced by\n        /// the index array. Note: This is different from the array\n        /// returned by GetPointArray().\n        /// </summary>\n        public V2d[] PointArray { get { return m_pointArray; } }\n\n        public IEnumerable<V2d> Points\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_pointArray[m_indexArray[m_firstIndex + i]];\n            }\n        }\n\n        public IEnumerable<int> Indices\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_indexArray[m_firstIndex + i];\n            }\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public V2d this[int index]\n        {\n            get { return m_pointArray[m_indexArray[m_firstIndex + index]]; }\n            set { m_pointArray[m_indexArray[m_firstIndex + index]] = value; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        public void ForEachIndex(Action<int> index_act)\n        {\n            var ia = m_indexArray; int fi = m_firstIndex;\n            for (int i = 0; i < m_pointCount; i++) index_act(ia[fi + i]);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual indices\n        /// of the index polygon. NOTE: This is different from the\n        /// IndexArray property!\n        /// </summary>\n        public int[] GetIndexArray()\n        {\n            return m_indexArray.Copy(m_firstIndex, m_pointCount);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual points\n        /// of the index polygon. NOTE: This is different from the\n        /// PointArray property!\n        /// </summary>\n        public V2d[] GetPointArray()\n        {\n            var pa = m_pointArray;\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pa[i]);\n        }\n\n        public T[] GetPointArray<T>(T[] pointArray)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointArray[i]);\n        }\n\n        public T[] GetPointArray<T>(List<T> pointList)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointList[i]);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon2dExtensions\n\n    public static partial class IndexPolygon2dExtensions\n    {\n        #region Conversions\n\n        public static Polygon2d ToPolygon2d(this IndexPolygon2d polygon)\n        {\n            return new Polygon2d(polygon.GetPointArray());\n        }\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static V2d ComputeVertexCentroid(this IndexPolygon2d polygon)\n        {\n            var sum = V2d.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            double scale = 1 / (double)pc;\n            return sum * scale;\n        }\n\n        public static double ComputePerimeter(this IndexPolygon2d polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            double r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Line2d\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Line2d : IEquatable<Line2d>, IValidity, IPolygon<V2d>, IBoundingBox2d\n    {\n        public V2d P0, P1;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates line from 2 points.\n        /// </summary>\n        public Line2d(V2d p0, V2d p1)\n        {\n            P0 = p0; P1 = p1;\n        }\n\n        /// <summary>\n        /// Creates line from first 2 points in the sequence.\n        /// </summary>\n        public Line2d(IEnumerable<V2d> points)\n        {\n            var pa = points.TakeToArray(2);\n            P0 = pa[0]; P1 = pa[1];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        public readonly int PointCount { get { return 2; } }\n\n        public readonly IEnumerable<V2d> Points\n        {\n            get { yield return P0; yield return P1; }\n        }\n\n        public readonly Line2d Reversed\n        {\n            get { return new Line2d(P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V2d this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Line2d Copy(Func<V2d, V2d> point_copyFun)\n        {\n            return new Line2d(point_copyFun(P0), point_copyFun(P1));\n        }\n\n        public readonly Line3d ToLine3d(Func<V2d, V3d> point_copyFun)\n        {\n            return new Line3d(point_copyFun(P0), point_copyFun(P1));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Line2d a, Line2d b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Line2d a, Line2d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Line2d other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1);\n\n        public override readonly bool Equals(object other)\n             => (other is Line2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", P0, P1);\n        }\n\n        public static Line2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Line2d(V2d.Parse(x[0]), V2d.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox2d Members\n\n        public readonly Box2d BoundingBox2d\n        {\n            get\n            {\n                return new Box2d(P0, P1).Repair();\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Line2d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Line2d a, Line2d b, double tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Line2d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Line2d a, Line2d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Line2dExtensions\n\n    public static partial class Line2dExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line2d polygon, double scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Scaled(this Line2d polygon, double scale)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line2d polygon, V2d center, double scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Scaled(this Line2d polygon, V2d center, double scale)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Line2d polygon, double scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d ScaledAboutCentroid(this Line2d polygon, double scale)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line2d polygon, V2d scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Scaled(this Line2d polygon, V2d scale)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line2d polygon, V2d center, V2d scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Scaled(this Line2d polygon, V2d center, V2d scale)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line2d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Line2d polygon, V2d scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d ScaledAboutCentroid(this Line2d polygon, V2d scale)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2d polygon, M33d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Transformed(this Line2d polygon, M33d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2d polygon, Euclidean2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Transformed(this Line2d polygon, Euclidean2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the inverse of the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2d polygon, Euclidean2d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the inverse of the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d InvTransformed(this Line2d polygon, Euclidean2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2d polygon, Similarity2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Transformed(this Line2d polygon, Similarity2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the inverse of the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2d polygon, Similarity2d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the inverse of the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d InvTransformed(this Line2d polygon, Similarity2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the given <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2d polygon, Affine2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the given <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Transformed(this Line2d polygon, Affine2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2d polygon, Shift2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Transformed(this Line2d polygon, Shift2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the inverse of the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2d polygon, Shift2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the inverse of the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d InvTransformed(this Line2d polygon, Shift2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2d polygon, Rot2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Transformed(this Line2d polygon, Rot2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the inverse of the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2d polygon, Rot2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the inverse of the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d InvTransformed(this Line2d polygon, Rot2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2d polygon, Scale2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Transformed(this Line2d polygon, Scale2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the inverse of the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line2d polygon, Scale2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the inverse of the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d InvTransformed(this Line2d polygon, Scale2d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line2d\"/> by the given <see cref=\"M22d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line2d polygon, M22d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line2d\"/> transformed by the given <see cref=\"M22d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line2d Transformed(this Line2d polygon, M22d t)\n        {\n            var result = new Line2d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V2d[] GetPointArray(this Line2d line)\n        {\n            var pa = new V2d[2];\n            pa[0] = line.P0;\n            pa[1] = line.P1;\n            return pa;\n        }\n\n        public static V2d ComputeCentroid(this Line2d line)\n        {\n            return 0.5 * (line.P0 + line.P1);\n        }\n    }\n\n    #endregion\n\n    #region Triangle2d\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Triangle2d : IEquatable<Triangle2d>, IValidity, IPolygon<V2d>, IBoundingBox2d\n    {\n        public V2d P0, P1, P2;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates triangle from 3 points.\n        /// </summary>\n        public Triangle2d(V2d p0, V2d p1, V2d p2)\n        {\n            P0 = p0; P1 = p1; P2 = p2;\n        }\n\n        /// <summary>\n        /// Creates triangle from first 3 points in the sequence.\n        /// </summary>\n        public Triangle2d(IEnumerable<V2d> points)\n        {\n            var pa = points.TakeToArray(3);\n            P0 = pa[0]; P1 = pa[1]; P2 = pa[2];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        /// <summary>\n        /// Edge P1 - P0\n        /// </summary>\n        public readonly V2d Edge01 { get { return P1 - P0; } }\n        /// <summary>\n        /// Edge P2 - P0\n        /// </summary>\n        public readonly V2d Edge02 { get { return P2 - P0; } }\n        /// <summary>\n        /// Edge P2 - P1\n        /// </summary>\n        public readonly V2d Edge12 { get { return P2 - P1; } }\n        /// <summary>\n        /// Edge P0 - P1\n        /// </summary>\n        public readonly V2d Edge10 { get { return P0 - P1; } }\n        /// <summary>\n        /// Edge P0 - P2\n        /// </summary>\n        public readonly V2d Edge20 { get { return P0 - P2; } }\n        /// <summary>\n        /// Edge P1 - P2\n        /// </summary>\n        public readonly V2d Edge21 { get { return P1 - P2; } }\n\n        public readonly IEnumerable<V2d> Edges\n        {\n            get\n            {\n                yield return P1 - P0;\n                yield return P2 - P1;\n                yield return P0 - P2;\n            }\n        }\n\n        public readonly V2d[] EdgeArray\n        {\n            get\n            {\n                var a = new V2d[3];\n                a[0] = P1 - P0;\n                a[1] = P2 - P1;\n                a[2] = P0 - P2;\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<Line2d> EdgeLines\n        {\n            get\n            {\n                yield return new Line2d(P0, P1);\n                yield return new Line2d(P1, P2);\n                yield return new Line2d(P2, P0);\n            }\n        }\n\n        public readonly Line2d[] EdgeLineArray\n        {\n            get\n            {\n                var a = new Line2d[3];\n                a[0] = new Line2d(P0, P1);\n                a[1] = new Line2d(P1, P2);\n                a[2] = new Line2d(P2, P0);\n                return a;\n            }\n        }\n\n        public readonly Line2d GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Line2d(P0, P1);\n                case 1: return new Line2d(P1, P2);\n                case 2: return new Line2d(P2, P0);\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly V2d GetEdge(int index)\n        {\n            switch (index)\n            {\n                case 0: return P1 - P0;\n                case 1: return P2 - P1;\n                case 2: return P0 - P2;\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly Line2d Line01 { get { return new Line2d(P0, P1); } }\n        public readonly Line2d Line02 { get { return new Line2d(P0, P2); } }\n        public readonly Line2d Line12 { get { return new Line2d(P1, P2); } }\n        public readonly Line2d Line10 { get { return new Line2d(P1, P0); } }\n        public readonly Line2d Line20 { get { return new Line2d(P2, P0); } }\n        public readonly Line2d Line21 { get { return new Line2d(P2, P1); } }\n\n        public readonly int PointCount { get { return 3; } }\n\n        public readonly IEnumerable<V2d> Points\n        {\n            get { yield return P0; yield return P1; yield return P2; }\n        }\n\n        public readonly Triangle2d Reversed\n        {\n            get { return new Triangle2d(P2, P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V2d this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    case 2: return P2;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    case 2: P2 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Triangle2d Copy(Func<V2d, V2d> point_copyFun)\n        {\n            return new Triangle2d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2));\n        }\n\n        public readonly Triangle3d ToTriangle3d(Func<V2d, V3d> point_copyFun)\n        {\n            return new Triangle3d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Triangle2d a, Triangle2d b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.P2 == b.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Triangle2d a, Triangle2d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1, P2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Triangle2d other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2);\n\n        public override readonly bool Equals(object other)\n             => (other is Triangle2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, P2);\n        }\n\n        public static Triangle2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Triangle2d(V2d.Parse(x[0]), V2d.Parse(x[1]), V2d.Parse(x[2]));\n        }\n\n        #endregion\n\n        #region IBoundingBox2d Members\n\n        public readonly Box2d BoundingBox2d\n        {\n            get\n            {\n                return new Box2d(P0, P1, P2);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Triangle2d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Triangle2d a, Triangle2d b, double tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance) && ApproximateEquals(a.P2, b.P2, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Triangle2d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Triangle2d a, Triangle2d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Triangle2dExtensions\n\n    public static partial class Triangle2dExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle2d polygon, double scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Scaled(this Triangle2d polygon, double scale)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle2d polygon, V2d center, double scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Scaled(this Triangle2d polygon, V2d center, double scale)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Triangle2d polygon, double scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d ScaledAboutCentroid(this Triangle2d polygon, double scale)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle2d polygon, V2d scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Scaled(this Triangle2d polygon, V2d scale)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle2d polygon, V2d center, V2d scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Scaled(this Triangle2d polygon, V2d center, V2d scale)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle2d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Triangle2d polygon, V2d scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d ScaledAboutCentroid(this Triangle2d polygon, V2d scale)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2d polygon, M33d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Transformed(this Triangle2d polygon, M33d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2d polygon, Euclidean2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Transformed(this Triangle2d polygon, Euclidean2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the inverse of the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2d polygon, Euclidean2d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the inverse of the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d InvTransformed(this Triangle2d polygon, Euclidean2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2d polygon, Similarity2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Transformed(this Triangle2d polygon, Similarity2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the inverse of the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2d polygon, Similarity2d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the inverse of the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d InvTransformed(this Triangle2d polygon, Similarity2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the given <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2d polygon, Affine2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the given <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Transformed(this Triangle2d polygon, Affine2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2d polygon, Shift2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Transformed(this Triangle2d polygon, Shift2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the inverse of the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2d polygon, Shift2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the inverse of the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d InvTransformed(this Triangle2d polygon, Shift2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2d polygon, Rot2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Transformed(this Triangle2d polygon, Rot2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the inverse of the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2d polygon, Rot2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the inverse of the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d InvTransformed(this Triangle2d polygon, Rot2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2d polygon, Scale2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Transformed(this Triangle2d polygon, Scale2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the inverse of the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle2d polygon, Scale2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the inverse of the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d InvTransformed(this Triangle2d polygon, Scale2d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle2d\"/> by the given <see cref=\"M22d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle2d polygon, M22d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle2d\"/> transformed by the given <see cref=\"M22d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle2d Transformed(this Triangle2d polygon, M22d t)\n        {\n            var result = new Triangle2d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V2d[] GetPointArray(this Triangle2d triangle)\n        {\n            var pa = new V2d[3];\n            pa[0] = triangle.P0;\n            pa[1] = triangle.P1;\n            pa[2] = triangle.P2;\n            return pa;\n        }\n\n        public static V2d ComputeCentroid(this Triangle2d triangle)\n        {\n            return Constant.OneThird * (triangle.P0 + triangle.P1 + triangle.P2);\n        }\n    }\n\n    #endregion\n\n    #region Quad2d\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Quad2d : IEquatable<Quad2d>, IValidity, IPolygon<V2d>, IBoundingBox2d\n    {\n        public V2d P0, P1, P2, P3;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates quad from 4 points.\n        /// </summary>\n        public Quad2d(V2d p0, V2d p1, V2d p2, V2d p3)\n        {\n            P0 = p0; P1 = p1; P2 = p2; P3 = p3;\n        }\n\n        /// <summary>\n        /// Creates quad from first 4 points in the sequence.\n        /// </summary>\n        public Quad2d(IEnumerable<V2d> points)\n        {\n            var pa = points.TakeToArray(4);\n            P0 = pa[0]; P1 = pa[1]; P2 = pa[2]; P3 = pa[3];\n        }\n\n        /// <summary>\n        /// Creates quad from point and two vectors representing edges.\n        /// </summary>\n        public Quad2d(V2d p0, V2d edge01, V2d edge03)\n        {\n            P0 = p0;\n            P1 = p0 + edge01;\n            P2 = P1 + edge03;\n            P3 = p0 + edge03;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        /// <summary>\n        /// Edge P1 - P0\n        /// </summary>\n        public readonly V2d Edge01 { get { return P1 - P0; } }\n        /// <summary>\n        /// Edge P3 - P0\n        /// </summary>\n        public readonly V2d Edge03 { get { return P3 - P0; } }\n        /// <summary>\n        /// Edge P2 - P1\n        /// </summary>\n        public readonly V2d Edge12 { get { return P2 - P1; } }\n        /// <summary>\n        /// Edge P0 - P1\n        /// </summary>\n        public readonly V2d Edge10 { get { return P0 - P1; } }\n        /// <summary>\n        /// Edge P3 - P2\n        /// </summary>\n        public readonly V2d Edge23 { get { return P3 - P2; } }\n        /// <summary>\n        /// Edge P1 - P2\n        /// </summary>\n        public readonly V2d Edge21 { get { return P1 - P2; } }\n        /// <summary>\n        /// Edge P0 - P3\n        /// </summary>\n        public readonly V2d Edge30 { get { return P0 - P3; } }\n        /// <summary>\n        /// Edge P2 - P3\n        /// </summary>\n        public readonly V2d Edge32 { get { return P2 - P3; } }\n\n        public readonly IEnumerable<V2d> Edges\n        {\n            get\n            {\n                yield return P1 - P0;\n                yield return P2 - P1;\n                yield return P3 - P2;\n                yield return P0 - P3;\n            }\n        }\n\n        public readonly V2d[] EdgeArray\n        {\n            get\n            {\n                var a = new V2d[4];\n                a[0] = P1 - P0;\n                a[1] = P2 - P1;\n                a[2] = P3 - P2;\n                a[3] = P0 - P3;\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<Line2d> EdgeLines\n        {\n            get\n            {\n                yield return new Line2d(P0, P1);\n                yield return new Line2d(P1, P2);\n                yield return new Line2d(P2, P3);\n                yield return new Line2d(P3, P0);\n            }\n        }\n\n        public readonly Line2d[] EdgeLineArray\n        {\n            get\n            {\n                var a = new Line2d[4];\n                a[0] = new Line2d(P0, P1);\n                a[1] = new Line2d(P1, P2);\n                a[2] = new Line2d(P2, P3);\n                a[3] = new Line2d(P3, P0);\n                return a;\n            }\n        }\n\n        public readonly Line2d GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Line2d(P0, P1);\n                case 1: return new Line2d(P1, P2);\n                case 2: return new Line2d(P2, P3);\n                case 3: return new Line2d(P3, P0);\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly V2d GetEdge(int index)\n        {\n            switch (index)\n            {\n                case 0: return P1 - P0;\n                case 1: return P2 - P1;\n                case 2: return P3 - P2;\n                case 3: return P0 - P3;\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly Line2d Line01 { get { return new Line2d(P0, P1); } }\n        public readonly Line2d Line03 { get { return new Line2d(P0, P3); } }\n        public readonly Line2d Line12 { get { return new Line2d(P1, P2); } }\n        public readonly Line2d Line10 { get { return new Line2d(P1, P0); } }\n        public readonly Line2d Line23 { get { return new Line2d(P2, P3); } }\n        public readonly Line2d Line21 { get { return new Line2d(P2, P1); } }\n        public readonly Line2d Line30 { get { return new Line2d(P3, P0); } }\n        public readonly Line2d Line32 { get { return new Line2d(P3, P2); } }\n\n        public readonly int PointCount { get { return 4; } }\n\n        public readonly IEnumerable<V2d> Points\n        {\n            get { yield return P0; yield return P1; yield return P2; yield return P3; }\n        }\n\n        public readonly Quad2d Reversed\n        {\n            get { return new Quad2d(P3, P2, P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V2d this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    case 2: return P2;\n                    case 3: return P3;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    case 2: P2 = value; return;\n                    case 3: P3 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Quad2d Copy(Func<V2d, V2d> point_copyFun)\n        {\n            return new Quad2d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2), point_copyFun(P3));\n        }\n\n        public readonly Quad3d ToQuad3d(Func<V2d, V3d> point_copyFun)\n        {\n            return new Quad3d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2), point_copyFun(P3));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Quad2d a, Quad2d b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.P2 == b.P2) && (a.P3 == b.P3);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Quad2d a, Quad2d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1, P2, P3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Quad2d other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2) && P3.Equals(other.P3);\n\n        public override readonly bool Equals(object other)\n             => (other is Quad2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", P0, P1, P2, P3);\n        }\n\n        public static Quad2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Quad2d(V2d.Parse(x[0]), V2d.Parse(x[1]), V2d.Parse(x[2]), V2d.Parse(x[3]));\n        }\n\n        #endregion\n\n        #region IBoundingBox2d Members\n\n        public readonly Box2d BoundingBox2d\n        {\n            get\n            {\n                return new Box2d(P0, P1, P2, P3);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Quad2d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Quad2d a, Quad2d b, double tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance) && ApproximateEquals(a.P2, b.P2, tolerance) && ApproximateEquals(a.P3, b.P3, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Quad2d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Quad2d a, Quad2d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Quad2dExtensions\n\n    public static partial class Quad2dExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad2d polygon, double scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n            polygon.P3 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Scaled(this Quad2d polygon, double scale)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad2d polygon, V2d center, double scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n            polygon.P3 = center + (polygon.P3 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Scaled(this Quad2d polygon, V2d center, double scale)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Quad2d polygon, double scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d ScaledAboutCentroid(this Quad2d polygon, double scale)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad2d polygon, V2d scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n            polygon.P3 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Scaled(this Quad2d polygon, V2d scale)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad2d polygon, V2d center, V2d scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n            polygon.P3 = center + (polygon.P3 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Scaled(this Quad2d polygon, V2d center, V2d scale)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad2d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Quad2d polygon, V2d scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d ScaledAboutCentroid(this Quad2d polygon, V2d scale)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2d polygon, M33d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Transformed(this Quad2d polygon, M33d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2d polygon, Euclidean2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Transformed(this Quad2d polygon, Euclidean2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the inverse of the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2d polygon, Euclidean2d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n            polygon.P3 = t.InvTransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the inverse of the given <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d InvTransformed(this Quad2d polygon, Euclidean2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2d polygon, Similarity2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Transformed(this Quad2d polygon, Similarity2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the inverse of the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2d polygon, Similarity2d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n            polygon.P3 = t.InvTransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the inverse of the given <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d InvTransformed(this Quad2d polygon, Similarity2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the given <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2d polygon, Affine2d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the given <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Transformed(this Quad2d polygon, Affine2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2d polygon, Shift2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Transformed(this Quad2d polygon, Shift2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the inverse of the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2d polygon, Shift2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the inverse of the given <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d InvTransformed(this Quad2d polygon, Shift2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2d polygon, Rot2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Transformed(this Quad2d polygon, Rot2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the inverse of the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2d polygon, Rot2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the inverse of the given <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d InvTransformed(this Quad2d polygon, Rot2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2d polygon, Scale2d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Transformed(this Quad2d polygon, Scale2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the inverse of the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad2d polygon, Scale2d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the inverse of the given <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d InvTransformed(this Quad2d polygon, Scale2d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad2d\"/> by the given <see cref=\"M22d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad2d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad2d polygon, M22d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad2d\"/> transformed by the given <see cref=\"M22d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad2d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad2d Transformed(this Quad2d polygon, M22d t)\n        {\n            var result = new Quad2d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V2d[] GetPointArray(this Quad2d quad)\n        {\n            var pa = new V2d[4];\n            pa[0] = quad.P0;\n            pa[1] = quad.P1;\n            pa[2] = quad.P2;\n            pa[3] = quad.P3;\n            return pa;\n        }\n\n        public static V2d ComputeCentroid(this Quad2d quad)\n        {\n            return 0.25 * (quad.P0 + quad.P1 + quad.P2 + quad.P3);\n        }\n    }\n\n    #endregion\n\n    #region Polygon3d\n\n    /// <summary>\n    /// A polygon internally represented by an array of points. Implemented\n    /// as a structure, the validity of the polygon can be checked via its\n    /// PointCount, which must be bigger than 0 for a polygon to hold any\n    /// points, and bigger than 2 for a polygon to be geometrically valid.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Polygon3d : IEquatable<Polygon3d>, IValidity, IPolygon<V3d>, IBoundingBox3d\n    {\n        internal int m_pointCount;\n        internal V3d[] m_pointArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon3d(V3d[] pointArray, int pointCount)\n        {\n            if (pointArray != null)\n            {\n                if (pointCount <= pointArray.Length)\n                {\n                    m_pointCount = pointCount;\n                    m_pointArray = pointArray;\n                }\n                else\n                    throw new ArgumentException(\n                                \"point count must be smaller or equal array length\");\n            }\n            else\n            {\n                m_pointCount = 0;\n                m_pointArray = null;\n            }\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon3d(params V3d[] pointArray)\n        {\n            m_pointCount = pointArray != null ? pointArray.Length : 0;\n            m_pointArray = pointArray;\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public Polygon3d(V3d[] pointArray, int startIndex, int count)\n        {\n            if (startIndex < 0 || startIndex >= pointArray.Length - 1) throw new ArgumentException();\n            if (count <= 0 || startIndex + count >= pointArray.Length) throw new ArgumentException();\n            m_pointCount = count;\n            m_pointArray = new V3d[count];\n            for (int i = 0; i < count; i++) m_pointArray[i] = pointArray[startIndex + i];\n        }\n\n        /// <summary>\n        /// Creates a polygon from point count and point creator function.\n        /// </summary>\n        public Polygon3d(int pointCount, Func<int, V3d> index_pointCreator)\n            : this(new V3d[pointCount].SetByIndex(index_pointCreator))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a sequence of points.\n        /// </summary>\n        public Polygon3d(IEnumerable<V3d> points)\n            : this(points.ToArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from the points of a pointArray that\n        /// are selected by an index array.\n        /// </summary>\n        public Polygon3d(int[] indexArray, V3d[] pointArray)\n            : this(indexArray.Map(i => pointArray[i]))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a triangle.\n        /// </summary>\n        public Polygon3d(Triangle3d triangle)\n            : this(triangle.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a quad.\n        /// </summary>\n        public Polygon3d(Quad3d quad)\n            : this(quad.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Copy constructor.\n        /// Performs deep copy of original.\n        /// </summary>\n        public Polygon3d(Polygon3d original)\n            : this(original.GetPointArray())\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Polygon3d Invalid = new Polygon3d(null, 0);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid => m_pointArray != null;\n\n        public readonly bool IsInvalid => m_pointArray == null;\n\n        /// <summary>\n        /// The number of points in the polygon. If this is 0, the polygon\n        /// is invalid.\n        /// </summary>\n        public readonly int PointCount => m_pointCount;\n\n        /// <summary>\n        /// Enumerates points.\n        /// </summary>\n        public readonly IEnumerable<V3d> Points\n        {\n            get { for (int pi = 0; pi < m_pointCount; pi++) yield return m_pointArray[pi]; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Returns a copy of the polygons point array.\n        /// </summary>\n        public readonly V3d[] GetPointArray()\n        {\n            var pc = m_pointCount;\n            var pa = new V3d[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            return pa;\n        }\n\n        /// <summary>\n        /// [P0, P1, P2] -> [P0, P1, P2, P0].\n        /// </summary>\n        public readonly V3d[] GetPointArrayWithRepeatedFirstPoint()\n        {\n            var pc = m_pointCount;\n            var pa = new V3d[pc + 1];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            pa[pc] = pa[0];\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<V3d, T> point_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_copyFun(m_pointArray[pi]);\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<V3d, int, T> point_index_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_index_copyFun(m_pointArray[pi], pi);\n            return pa;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets the index-th point of this polygon.\n        /// </summary>\n        public readonly V3d this[int index]\n        {\n            get { return m_pointArray[index]; }\n            set { m_pointArray[index] = value; }\n        }\n\n        #endregion\n\n        #region Edges and Lines\n\n        /// <summary>\n        /// Index-th edge as vector (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly V3d Edge(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return p1 - p0;\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly IEnumerable<V3d> Edges\n        {\n            get\n            {\n                var pc = m_pointCount;\n                var p = m_pointArray[0];\n                var p0 = p;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return p1 - p0;\n                    p0 = p1;\n                }\n                yield return p - p0;\n            }\n        }\n\n        /// <summary>\n        /// Index-th edge as line segment (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly Line3d EdgeLine(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return new Line3d(p0, p1);\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly IEnumerable<Line3d> EdgeLines\n        {\n            get\n            {\n                var pc = m_pointCount;\n                if (pc < 1) yield break;\n                var p0 = m_pointArray[0];\n                var p = p0;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return new Line3d(p0, p1);\n                    p0 = p1;\n                }\n                yield return new Line3d(p0, p);\n            }\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly V3d[] GetEdgeArray()\n        {\n            var pc = m_pointCount;\n            if (pc < 2) return Array.Empty<V3d>();\n            var edgeArray = new V3d[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                edgeArray[pi - 1] = p1 - p0;\n                p0 = p1;\n            }\n            edgeArray[pc - 1] = p - p0;\n            return edgeArray;\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly Line3d[] GetEdgeLineArray()\n        {\n            var pc = PointCount;\n            if (pc < 2) return Array.Empty<Line3d>();\n            var ela = new Line3d[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                ela[pi - 1] = new Line3d(p0, p1);\n                p0 = p1;\n            }\n            ela[pc - 1] = new Line3d(p0, p);\n            return ela;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Returns copy of polygon. Same as Map(p => p).\n        /// </summary>\n        public readonly Polygon3d Copy()\n        {\n            return new Polygon3d(m_pointArray.Copy());\n        }\n\n        /// <summary>\n        /// Returns transformed copy of this polygon.\n        /// </summary>\n        public readonly Polygon3d Map(Func<V3d, V3d> point_fun)\n        {\n            var pc = m_pointCount;\n            V3d[] opa = m_pointArray, npa = new V3d[pc];\n            for (int pi = 0; pi < pc; pi++) npa[pi] = point_fun(opa[pi]);\n            return new Polygon3d(npa, pc);\n        }\n\n        /// <summary>\n        /// Gets copy with reversed order of vertices.\n        /// </summary>\n        public readonly Polygon3d Reversed\n        {\n            get\n            {\n                var pc = m_pointCount;\n                V3d[] opa = m_pointArray, npa = new V3d[pc];\n                for (int pi = 0, pj = pc - 1; pi < pc; pi++, pj--) npa[pi] = opa[pj];\n                return new Polygon3d(npa, pc);\n            }\n        }\n\n        /// <summary>\n        /// Reverses order of vertices in-place.\n        /// </summary>\n        public readonly void Reverse()\n        {\n            var pa = m_pointArray;\n            for (int pi = 0, pj = m_pointCount - 1; pi < pj; pi++, pj--)\n            { var t = pa[pi]; pa[pi] = pa[pj]; pa[pj] = t; }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Polygon3d a, Polygon3d b)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (a.m_pointArray[pi] != b.m_pointArray[pi]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Polygon3d a, Polygon3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return m_pointArray.GetCombinedHashCode(m_pointCount);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Polygon3d other)\n        {\n            if (m_pointCount != other.m_pointCount) return false;\n            for (int pi = 0; pi < m_pointCount; pi++)\n                if (!m_pointArray[pi].Equals(other.m_pointArray[pi])) return false;\n            return true;\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is Polygon3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture,\n                \"[{0}]\", Points.Select(x => x.ToString()).Join(\", \")\n                );\n        }\n\n        public static Polygon3d Parse(string s)\n        {\n            var va = s.NestedBracketSplitLevelOne().ToArray();\n            return new Polygon3d(va.Select(x => V3d.Parse(x)));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        /// <summary>\n        /// Bounding box of polygon.\n        /// </summary>\n        public readonly Box3d BoundingBox3d\n        {\n            get { return new Box3d(m_pointArray, 0, m_pointCount); }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Polygon3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Polygon3d a, Polygon3d b, double tolerance)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (!ApproximateEquals(a.m_pointArray[pi], b.m_pointArray[pi], tolerance)) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Polygon3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Polygon3d a, Polygon3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Polygon3dExtensions\n\n    public static partial class Polygon3dExtensions\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static V3d ComputeVertexCentroid(this Polygon3d polygon)\n        {\n            var sum = V3d.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            double scale = 1 / (double)pc;\n            return sum * scale;\n        }\n\n        public static double ComputePerimeter(this Polygon3d polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            double r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon3d polygon, double scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Scaled(this Polygon3d polygon, double scale)\n        {\n            var result = new Polygon3d(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon3d polygon, V3d center, double scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Scaled(this Polygon3d polygon, V3d center, double scale)\n        {\n            var result = new Polygon3d(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref Polygon3d polygon, double scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d ScaledAboutVertexCentroid(this Polygon3d polygon, double scale)\n        {\n            var result = new Polygon3d(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon3d polygon, V3d scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Scaled(this Polygon3d polygon, V3d scale)\n        {\n            var result = new Polygon3d(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref Polygon3d polygon, V3d center, V3d scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Scaled(this Polygon3d polygon, V3d center, V3d scale)\n        {\n            var result = new Polygon3d(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Polygon3d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref Polygon3d polygon, V3d scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d ScaledAboutVertexCentroid(this Polygon3d polygon, V3d scale)\n        {\n            var result = new Polygon3d(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the given <see cref=\"M44d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3d polygon, M44d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the given <see cref=\"M44d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Transformed(this Polygon3d polygon, M44d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3d polygon, Euclidean3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Transformed(this Polygon3d polygon, Euclidean3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the inverse of the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3d polygon, Euclidean3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the inverse of the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d InvTransformed(this Polygon3d polygon, Euclidean3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3d polygon, Similarity3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Transformed(this Polygon3d polygon, Similarity3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the inverse of the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3d polygon, Similarity3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the inverse of the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d InvTransformed(this Polygon3d polygon, Similarity3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3d polygon, Affine3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.TransformPos(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Transformed(this Polygon3d polygon, Affine3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3d polygon, Shift3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Transformed(this Polygon3d polygon, Shift3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the inverse of the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3d polygon, Shift3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the inverse of the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d InvTransformed(this Polygon3d polygon, Shift3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3d polygon, Rot3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Transformed(this Polygon3d polygon, Rot3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the inverse of the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3d polygon, Rot3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the inverse of the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d InvTransformed(this Polygon3d polygon, Rot3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3d polygon, Scale3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Transformed(this Polygon3d polygon, Scale3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the inverse of the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref Polygon3d polygon, Scale3d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.InvTransform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the inverse of the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d InvTransformed(this Polygon3d polygon, Scale3d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Polygon3d\"/> by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Polygon3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref Polygon3d polygon, M33d t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Transform(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Polygon3d\"/> transformed by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Polygon3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon3d Transformed(this Polygon3d polygon, M33d t)\n        {\n            var result = new Polygon3d(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        public static Polygon3d WithoutMultiplePoints(this Polygon3d polygon, double eps = 1e-8)\n        {\n            eps *= eps;\n            var opc = polygon.PointCount;\n            var pa = new V3d[opc];\n            var pc = 0;\n            pa[0] = polygon[0];\n            for (int pi = 1; pi < opc; pi++)\n                if (Vec.DistanceSquared(pa[pc], polygon[pi]) > eps)\n                    pa[++pc] = polygon[pi];\n            if (Vec.DistanceSquared(pa[pc], polygon[0]) > eps)\n                ++pc;\n            return new Polygon3d(pa, pc);\n        }\n\n        #endregion\n\n        #region Clipping\n\n        /// <summary>\n        /// Clip the supplied polygon at the supplied plane. The method should\n        /// work with all non-selfintersecting polygons. Returns all parts of\n        /// the polygon that are at the positive side of the plane.\n        /// </summary>\n        public static Polygon3d ConvexClipped(\n                this Polygon3d polygon, Plane3d plane, double eps = 1e-8)\n        {\n            var opc = polygon.PointCount;\n            V3d[] pa = new V3d[opc + 1];\n            var pc = 0;\n            var pf = polygon[0];\n            var hf = plane.Height(pf); bool hfp = hf > eps, hfn = hf < -eps;\n            if (hf >= -eps) pa[pc++] = pf;\n            var p0 = pf; var h0 = hf; var h0p = hfp; var h0n = hfn;\n            for (int vi = 1; vi < opc; vi++)\n            {\n                var p1 = polygon[vi];\n                var h1 = plane.Height(p1); bool h1p = h1 > eps, h1n = h1 < -eps;\n                if (h0p && h1n || h0n && h1p) pa[pc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));\n                if (h1 >= -eps) pa[pc++] = p1;\n                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;\n            }\n            if (h0p && hfn || h0n && hfp) pa[pc++] = p0 + (pf - p0) * (h0 / (h0 - hf));\n            return new Polygon3d(pa, pc);\n        }\n\n        /// <summary>\n        /// Returns the convex polygon clipped by the set of planes (defined\n        /// as Plane3ds), i.e. all parts of the polygon that are at the positive\n        /// side of the planes.\n        /// </summary>\n        public static Polygon3d ConvexClipped(\n                this Polygon3d polygon, Plane3d[] planes, double eps = 1e-8)\n        {\n            foreach (var c in planes)\n            {\n                polygon = polygon.ConvexClipped(c, eps);\n                if (polygon.PointCount == 0) break;\n            }\n            return polygon;\n        }\n\n        /// <summary>\n        /// Returns the polygon clipped by the hull, i.e. all parts of the\n        /// polygon that are at the positive side of the hull planes.\n        /// </summary>\n        public static Polygon3d ConvexClipped(\n                this Polygon3d polygon, Hull3d hull, double eps = 1e-8)\n        {\n            return polygon.ConvexClipped(hull.PlaneArray, eps);\n        }\n\n        /// <summary>\n        /// TODO summary.\n        /// </summary>\n        public static Polygon3d ConvexClipped(\n                this Polygon3d polygon, Box3d box, double eps = 1e-8)\n        {\n            var planes = new[]\n            {\n                new Plane3d(V3d.XAxis, box.Min), new Plane3d(-V3d.XAxis, box.Max),\n                new Plane3d(V3d.YAxis, box.Min), new Plane3d(-V3d.YAxis, box.Max),\n                new Plane3d(V3d.ZAxis, box.Min), new Plane3d(-V3d.ZAxis, box.Max),\n            };\n            return polygon.ConvexClipped(planes);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon3d\n\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct IndexPolygon3d : IValidity, IPolygon<V3d>\n    {\n        private readonly int m_pointCount;\n        private readonly int m_firstIndex;\n        private readonly int[] m_indexArray;\n        private readonly V3d[] m_pointArray;\n\n        #region Constructors\n\n        public IndexPolygon3d(int[] indexArray, int firstIndex, int pointCount, V3d[] pointArray)\n        {\n            m_indexArray = indexArray;\n            m_firstIndex = firstIndex;\n            m_pointCount = pointCount;\n            m_pointArray = pointArray;\n        }\n\n        public IndexPolygon3d(V3d[] pointArray, int firstIndex, int pointCount)\n            : this(new int[pointCount].SetByIndex(i => firstIndex + i), 0, pointCount, pointArray)\n        { }\n\n        public IndexPolygon3d(V3d[] pointArray)\n            : this(new int[pointArray.Length].SetByIndex(i => i), 0, pointArray.Length, pointArray)\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly IndexPolygon3d Invalid = new IndexPolygon3d(null, 0, 0, null);\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid { get { return m_indexArray != null && m_pointArray != null; } }\n        public bool IsInvalid { get { return m_indexArray == null || m_pointArray == null; } }\n\n        public int PointCount\n        {\n            get { return m_pointCount; }\n        }\n\n        public int FirstIndex { get { return m_firstIndex; } }\n\n        /// <summary>\n        /// The index array that contains the point indices of the\n        /// index polygon at the index range [FirstIndex, FirstIndex + PointCount).\n        /// NOTE: This is different from the array returned by GetIndexArray().\n        /// </summary>\n        public int[] IndexArray { get { return m_indexArray; } }\n\n        /// <summary>\n        /// The point array that contains the points referenced by\n        /// the index array. Note: This is different from the array\n        /// returned by GetPointArray().\n        /// </summary>\n        public V3d[] PointArray { get { return m_pointArray; } }\n\n        public IEnumerable<V3d> Points\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_pointArray[m_indexArray[m_firstIndex + i]];\n            }\n        }\n\n        public IEnumerable<int> Indices\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_indexArray[m_firstIndex + i];\n            }\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public V3d this[int index]\n        {\n            get { return m_pointArray[m_indexArray[m_firstIndex + index]]; }\n            set { m_pointArray[m_indexArray[m_firstIndex + index]] = value; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        public void ForEachIndex(Action<int> index_act)\n        {\n            var ia = m_indexArray; int fi = m_firstIndex;\n            for (int i = 0; i < m_pointCount; i++) index_act(ia[fi + i]);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual indices\n        /// of the index polygon. NOTE: This is different from the\n        /// IndexArray property!\n        /// </summary>\n        public int[] GetIndexArray()\n        {\n            return m_indexArray.Copy(m_firstIndex, m_pointCount);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual points\n        /// of the index polygon. NOTE: This is different from the\n        /// PointArray property!\n        /// </summary>\n        public V3d[] GetPointArray()\n        {\n            var pa = m_pointArray;\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pa[i]);\n        }\n\n        public T[] GetPointArray<T>(T[] pointArray)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointArray[i]);\n        }\n\n        public T[] GetPointArray<T>(List<T> pointList)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointList[i]);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon3dExtensions\n\n    public static partial class IndexPolygon3dExtensions\n    {\n        #region Conversions\n\n        public static Polygon3d ToPolygon3d(this IndexPolygon3d polygon)\n        {\n            return new Polygon3d(polygon.GetPointArray());\n        }\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static V3d ComputeVertexCentroid(this IndexPolygon3d polygon)\n        {\n            var sum = V3d.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            double scale = 1 / (double)pc;\n            return sum * scale;\n        }\n\n        public static double ComputePerimeter(this IndexPolygon3d polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            double r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Line3d\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Line3d : IEquatable<Line3d>, IValidity, IPolygon<V3d>, IBoundingBox3d\n    {\n        public V3d P0, P1;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates line from 2 points.\n        /// </summary>\n        public Line3d(V3d p0, V3d p1)\n        {\n            P0 = p0; P1 = p1;\n        }\n\n        /// <summary>\n        /// Creates line from first 2 points in the sequence.\n        /// </summary>\n        public Line3d(IEnumerable<V3d> points)\n        {\n            var pa = points.TakeToArray(2);\n            P0 = pa[0]; P1 = pa[1];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        public readonly int PointCount { get { return 2; } }\n\n        public readonly IEnumerable<V3d> Points\n        {\n            get { yield return P0; yield return P1; }\n        }\n\n        public readonly Line3d Reversed\n        {\n            get { return new Line3d(P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V3d this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Line3d Copy(Func<V3d, V3d> point_copyFun)\n        {\n            return new Line3d(point_copyFun(P0), point_copyFun(P1));\n        }\n\n        public readonly Line2d ToLine2d(Func<V3d, V2d> point_copyFun)\n        {\n            return new Line2d(point_copyFun(P0), point_copyFun(P1));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Line3d a, Line3d b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Line3d a, Line3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Line3d other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1);\n\n        public override readonly bool Equals(object other)\n             => (other is Line3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", P0, P1);\n        }\n\n        public static Line3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Line3d(V3d.Parse(x[0]), V3d.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        public readonly Box3d BoundingBox3d\n        {\n            get\n            {\n                return new Box3d(P0, P1).Repair();\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Line3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Line3d a, Line3d b, double tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Line3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Line3d a, Line3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Line3dExtensions\n\n    public static partial class Line3dExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line3d polygon, double scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Scaled(this Line3d polygon, double scale)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line3d polygon, V3d center, double scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Scaled(this Line3d polygon, V3d center, double scale)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Line3d polygon, double scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d ScaledAboutCentroid(this Line3d polygon, double scale)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line3d polygon, V3d scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Scaled(this Line3d polygon, V3d scale)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Line3d polygon, V3d center, V3d scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Scaled(this Line3d polygon, V3d center, V3d scale)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Line3d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Line3d polygon, V3d scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d ScaledAboutCentroid(this Line3d polygon, V3d scale)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the given <see cref=\"M44d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3d polygon, M44d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the given <see cref=\"M44d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Transformed(this Line3d polygon, M44d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3d polygon, Euclidean3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Transformed(this Line3d polygon, Euclidean3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the inverse of the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3d polygon, Euclidean3d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the inverse of the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d InvTransformed(this Line3d polygon, Euclidean3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3d polygon, Similarity3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Transformed(this Line3d polygon, Similarity3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the inverse of the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3d polygon, Similarity3d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the inverse of the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d InvTransformed(this Line3d polygon, Similarity3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3d polygon, Affine3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Transformed(this Line3d polygon, Affine3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3d polygon, Shift3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Transformed(this Line3d polygon, Shift3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the inverse of the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3d polygon, Shift3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the inverse of the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d InvTransformed(this Line3d polygon, Shift3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3d polygon, Rot3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Transformed(this Line3d polygon, Rot3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the inverse of the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3d polygon, Rot3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the inverse of the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d InvTransformed(this Line3d polygon, Rot3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3d polygon, Scale3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Transformed(this Line3d polygon, Scale3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the inverse of the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Line3d polygon, Scale3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the inverse of the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d InvTransformed(this Line3d polygon, Scale3d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Line3d\"/> by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Line3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Line3d polygon, M33d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Line3d\"/> transformed by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Line3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Line3d Transformed(this Line3d polygon, M33d t)\n        {\n            var result = new Line3d(polygon.P0, polygon.P1);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V3d[] GetPointArray(this Line3d line)\n        {\n            var pa = new V3d[2];\n            pa[0] = line.P0;\n            pa[1] = line.P1;\n            return pa;\n        }\n\n        public static V3d ComputeCentroid(this Line3d line)\n        {\n            return 0.5 * (line.P0 + line.P1);\n        }\n    }\n\n    #endregion\n\n    #region Triangle3d\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Triangle3d : IEquatable<Triangle3d>, IValidity, IPolygon<V3d>, IBoundingBox3d\n    {\n        public V3d P0, P1, P2;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates triangle from 3 points.\n        /// </summary>\n        public Triangle3d(V3d p0, V3d p1, V3d p2)\n        {\n            P0 = p0; P1 = p1; P2 = p2;\n        }\n\n        /// <summary>\n        /// Creates triangle from first 3 points in the sequence.\n        /// </summary>\n        public Triangle3d(IEnumerable<V3d> points)\n        {\n            var pa = points.TakeToArray(3);\n            P0 = pa[0]; P1 = pa[1]; P2 = pa[2];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        /// <summary>\n        /// Edge P1 - P0\n        /// </summary>\n        public readonly V3d Edge01 { get { return P1 - P0; } }\n        /// <summary>\n        /// Edge P2 - P0\n        /// </summary>\n        public readonly V3d Edge02 { get { return P2 - P0; } }\n        /// <summary>\n        /// Edge P2 - P1\n        /// </summary>\n        public readonly V3d Edge12 { get { return P2 - P1; } }\n        /// <summary>\n        /// Edge P0 - P1\n        /// </summary>\n        public readonly V3d Edge10 { get { return P0 - P1; } }\n        /// <summary>\n        /// Edge P0 - P2\n        /// </summary>\n        public readonly V3d Edge20 { get { return P0 - P2; } }\n        /// <summary>\n        /// Edge P1 - P2\n        /// </summary>\n        public readonly V3d Edge21 { get { return P1 - P2; } }\n\n        public readonly IEnumerable<V3d> Edges\n        {\n            get\n            {\n                yield return P1 - P0;\n                yield return P2 - P1;\n                yield return P0 - P2;\n            }\n        }\n\n        public readonly V3d[] EdgeArray\n        {\n            get\n            {\n                var a = new V3d[3];\n                a[0] = P1 - P0;\n                a[1] = P2 - P1;\n                a[2] = P0 - P2;\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<Line3d> EdgeLines\n        {\n            get\n            {\n                yield return new Line3d(P0, P1);\n                yield return new Line3d(P1, P2);\n                yield return new Line3d(P2, P0);\n            }\n        }\n\n        public readonly Line3d[] EdgeLineArray\n        {\n            get\n            {\n                var a = new Line3d[3];\n                a[0] = new Line3d(P0, P1);\n                a[1] = new Line3d(P1, P2);\n                a[2] = new Line3d(P2, P0);\n                return a;\n            }\n        }\n\n        public readonly Line3d GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Line3d(P0, P1);\n                case 1: return new Line3d(P1, P2);\n                case 2: return new Line3d(P2, P0);\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly V3d GetEdge(int index)\n        {\n            switch (index)\n            {\n                case 0: return P1 - P0;\n                case 1: return P2 - P1;\n                case 2: return P0 - P2;\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly Line3d Line01 { get { return new Line3d(P0, P1); } }\n        public readonly Line3d Line02 { get { return new Line3d(P0, P2); } }\n        public readonly Line3d Line12 { get { return new Line3d(P1, P2); } }\n        public readonly Line3d Line10 { get { return new Line3d(P1, P0); } }\n        public readonly Line3d Line20 { get { return new Line3d(P2, P0); } }\n        public readonly Line3d Line21 { get { return new Line3d(P2, P1); } }\n\n        public readonly int PointCount { get { return 3; } }\n\n        public readonly IEnumerable<V3d> Points\n        {\n            get { yield return P0; yield return P1; yield return P2; }\n        }\n\n        public readonly Triangle3d Reversed\n        {\n            get { return new Triangle3d(P2, P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V3d this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    case 2: return P2;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    case 2: P2 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Triangle3d Copy(Func<V3d, V3d> point_copyFun)\n        {\n            return new Triangle3d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2));\n        }\n\n        public readonly Triangle2d ToTriangle2d(Func<V3d, V2d> point_copyFun)\n        {\n            return new Triangle2d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Triangle3d a, Triangle3d b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.P2 == b.P2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Triangle3d a, Triangle3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1, P2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Triangle3d other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2);\n\n        public override readonly bool Equals(object other)\n             => (other is Triangle3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", P0, P1, P2);\n        }\n\n        public static Triangle3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Triangle3d(V3d.Parse(x[0]), V3d.Parse(x[1]), V3d.Parse(x[2]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        public readonly Box3d BoundingBox3d\n        {\n            get\n            {\n                return new Box3d(P0, P1, P2);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Triangle3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Triangle3d a, Triangle3d b, double tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance) && ApproximateEquals(a.P2, b.P2, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Triangle3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Triangle3d a, Triangle3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Triangle3dExtensions\n\n    public static partial class Triangle3dExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle3d polygon, double scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Scaled(this Triangle3d polygon, double scale)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle3d polygon, V3d center, double scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Scaled(this Triangle3d polygon, V3d center, double scale)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Triangle3d polygon, double scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d ScaledAboutCentroid(this Triangle3d polygon, double scale)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle3d polygon, V3d scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Scaled(this Triangle3d polygon, V3d scale)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Triangle3d polygon, V3d center, V3d scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Scaled(this Triangle3d polygon, V3d center, V3d scale)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Triangle3d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Triangle3d polygon, V3d scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d ScaledAboutCentroid(this Triangle3d polygon, V3d scale)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the given <see cref=\"M44d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3d polygon, M44d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the given <see cref=\"M44d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Transformed(this Triangle3d polygon, M44d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3d polygon, Euclidean3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Transformed(this Triangle3d polygon, Euclidean3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the inverse of the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3d polygon, Euclidean3d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the inverse of the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d InvTransformed(this Triangle3d polygon, Euclidean3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3d polygon, Similarity3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Transformed(this Triangle3d polygon, Similarity3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the inverse of the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3d polygon, Similarity3d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the inverse of the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d InvTransformed(this Triangle3d polygon, Similarity3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3d polygon, Affine3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Transformed(this Triangle3d polygon, Affine3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3d polygon, Shift3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Transformed(this Triangle3d polygon, Shift3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the inverse of the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3d polygon, Shift3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the inverse of the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d InvTransformed(this Triangle3d polygon, Shift3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3d polygon, Rot3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Transformed(this Triangle3d polygon, Rot3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the inverse of the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3d polygon, Rot3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the inverse of the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d InvTransformed(this Triangle3d polygon, Rot3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3d polygon, Scale3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Transformed(this Triangle3d polygon, Scale3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the inverse of the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Triangle3d polygon, Scale3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the inverse of the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d InvTransformed(this Triangle3d polygon, Scale3d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Triangle3d\"/> by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Triangle3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Triangle3d polygon, M33d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Triangle3d\"/> transformed by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Triangle3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Triangle3d Transformed(this Triangle3d polygon, M33d t)\n        {\n            var result = new Triangle3d(polygon.P0, polygon.P1, polygon.P2);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V3d[] GetPointArray(this Triangle3d triangle)\n        {\n            var pa = new V3d[3];\n            pa[0] = triangle.P0;\n            pa[1] = triangle.P1;\n            pa[2] = triangle.P2;\n            return pa;\n        }\n\n        public static V3d ComputeCentroid(this Triangle3d triangle)\n        {\n            return Constant.OneThird * (triangle.P0 + triangle.P1 + triangle.P2);\n        }\n    }\n\n    #endregion\n\n    #region Quad3d\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Quad3d : IEquatable<Quad3d>, IValidity, IPolygon<V3d>, IBoundingBox3d\n    {\n        public V3d P0, P1, P2, P3;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates quad from 4 points.\n        /// </summary>\n        public Quad3d(V3d p0, V3d p1, V3d p2, V3d p3)\n        {\n            P0 = p0; P1 = p1; P2 = p2; P3 = p3;\n        }\n\n        /// <summary>\n        /// Creates quad from first 4 points in the sequence.\n        /// </summary>\n        public Quad3d(IEnumerable<V3d> points)\n        {\n            var pa = points.TakeToArray(4);\n            P0 = pa[0]; P1 = pa[1]; P2 = pa[2]; P3 = pa[3];\n        }\n\n        /// <summary>\n        /// Creates quad from point and two vectors representing edges.\n        /// </summary>\n        public Quad3d(V3d p0, V3d edge01, V3d edge03)\n        {\n            P0 = p0;\n            P1 = p0 + edge01;\n            P2 = P1 + edge03;\n            P3 = p0 + edge03;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        /// <summary>\n        /// Edge P1 - P0\n        /// </summary>\n        public readonly V3d Edge01 { get { return P1 - P0; } }\n        /// <summary>\n        /// Edge P3 - P0\n        /// </summary>\n        public readonly V3d Edge03 { get { return P3 - P0; } }\n        /// <summary>\n        /// Edge P2 - P1\n        /// </summary>\n        public readonly V3d Edge12 { get { return P2 - P1; } }\n        /// <summary>\n        /// Edge P0 - P1\n        /// </summary>\n        public readonly V3d Edge10 { get { return P0 - P1; } }\n        /// <summary>\n        /// Edge P3 - P2\n        /// </summary>\n        public readonly V3d Edge23 { get { return P3 - P2; } }\n        /// <summary>\n        /// Edge P1 - P2\n        /// </summary>\n        public readonly V3d Edge21 { get { return P1 - P2; } }\n        /// <summary>\n        /// Edge P0 - P3\n        /// </summary>\n        public readonly V3d Edge30 { get { return P0 - P3; } }\n        /// <summary>\n        /// Edge P2 - P3\n        /// </summary>\n        public readonly V3d Edge32 { get { return P2 - P3; } }\n\n        public readonly IEnumerable<V3d> Edges\n        {\n            get\n            {\n                yield return P1 - P0;\n                yield return P2 - P1;\n                yield return P3 - P2;\n                yield return P0 - P3;\n            }\n        }\n\n        public readonly V3d[] EdgeArray\n        {\n            get\n            {\n                var a = new V3d[4];\n                a[0] = P1 - P0;\n                a[1] = P2 - P1;\n                a[2] = P3 - P2;\n                a[3] = P0 - P3;\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<Line3d> EdgeLines\n        {\n            get\n            {\n                yield return new Line3d(P0, P1);\n                yield return new Line3d(P1, P2);\n                yield return new Line3d(P2, P3);\n                yield return new Line3d(P3, P0);\n            }\n        }\n\n        public readonly Line3d[] EdgeLineArray\n        {\n            get\n            {\n                var a = new Line3d[4];\n                a[0] = new Line3d(P0, P1);\n                a[1] = new Line3d(P1, P2);\n                a[2] = new Line3d(P2, P3);\n                a[3] = new Line3d(P3, P0);\n                return a;\n            }\n        }\n\n        public readonly Line3d GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                case 0: return new Line3d(P0, P1);\n                case 1: return new Line3d(P1, P2);\n                case 2: return new Line3d(P2, P3);\n                case 3: return new Line3d(P3, P0);\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly V3d GetEdge(int index)\n        {\n            switch (index)\n            {\n                case 0: return P1 - P0;\n                case 1: return P2 - P1;\n                case 2: return P3 - P2;\n                case 3: return P0 - P3;\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly Line3d Line01 { get { return new Line3d(P0, P1); } }\n        public readonly Line3d Line03 { get { return new Line3d(P0, P3); } }\n        public readonly Line3d Line12 { get { return new Line3d(P1, P2); } }\n        public readonly Line3d Line10 { get { return new Line3d(P1, P0); } }\n        public readonly Line3d Line23 { get { return new Line3d(P2, P3); } }\n        public readonly Line3d Line21 { get { return new Line3d(P2, P1); } }\n        public readonly Line3d Line30 { get { return new Line3d(P3, P0); } }\n        public readonly Line3d Line32 { get { return new Line3d(P3, P2); } }\n\n        public readonly int PointCount { get { return 4; } }\n\n        public readonly IEnumerable<V3d> Points\n        {\n            get { yield return P0; yield return P1; yield return P2; yield return P3; }\n        }\n\n        public readonly Quad3d Reversed\n        {\n            get { return new Quad3d(P3, P2, P1, P0); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public V3d this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    case 0: return P0;\n                    case 1: return P1;\n                    case 2: return P2;\n                    case 3: return P3;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    case 0: P0 = value; return;\n                    case 1: P1 = value; return;\n                    case 2: P2 = value; return;\n                    case 3: P3 = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Quad3d Copy(Func<V3d, V3d> point_copyFun)\n        {\n            return new Quad3d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2), point_copyFun(P3));\n        }\n\n        public readonly Quad2d ToQuad2d(Func<V3d, V2d> point_copyFun)\n        {\n            return new Quad2d(point_copyFun(P0), point_copyFun(P1), point_copyFun(P2), point_copyFun(P3));\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Quad3d a, Quad3d b)\n            => (a.P0 == b.P0) && (a.P1 == b.P1) && (a.P2 == b.P2) && (a.P3 == b.P3);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Quad3d a, Quad3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(P0, P1, P2, P3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Quad3d other)\n            => P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2) && P3.Equals(other.P3);\n\n        public override readonly bool Equals(object other)\n             => (other is Quad3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", P0, P1, P2, P3);\n        }\n\n        public static Quad3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Quad3d(V3d.Parse(x[0]), V3d.Parse(x[1]), V3d.Parse(x[2]), V3d.Parse(x[3]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        public readonly Box3d BoundingBox3d\n        {\n            get\n            {\n                return new Box3d(P0, P1, P2, P3);\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Quad3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Quad3d a, Quad3d b, double tolerance)\n            => ApproximateEquals(a.P0, b.P0, tolerance) && ApproximateEquals(a.P1, b.P1, tolerance) && ApproximateEquals(a.P2, b.P2, tolerance) && ApproximateEquals(a.P3, b.P3, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Quad3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Quad3d a, Quad3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Quad3dExtensions\n\n    public static partial class Quad3dExtensions\n    {\n        #region Geometric Transformations\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad3d polygon, double scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n            polygon.P3 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Scaled(this Quad3d polygon, double scale)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad3d polygon, V3d center, double scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n            polygon.P3 = center + (polygon.P3 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Scaled(this Quad3d polygon, V3d center, double scale)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Quad3d polygon, double scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d ScaledAboutCentroid(this Quad3d polygon, double scale)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3d\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad3d polygon, V3d scale)\n        {\n            polygon.P0 *= scale;\n            polygon.P1 *= scale;\n            polygon.P2 *= scale;\n            polygon.P3 *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Scaled(this Quad3d polygon, V3d scale)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3d\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref Quad3d polygon, V3d center, V3d scale)\n        {\n            polygon.P0 = center + (polygon.P0 - center) * scale;\n            polygon.P1 = center + (polygon.P1 - center) * scale;\n            polygon.P2 = center + (polygon.P2 - center) * scale;\n            polygon.P3 = center + (polygon.P3 - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Scaled(this Quad3d polygon, V3d center, V3d scale)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"Quad3d\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref Quad3d polygon, V3d scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d ScaledAboutCentroid(this Quad3d polygon, V3d scale)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the given <see cref=\"M44d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3d polygon, M44d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the given <see cref=\"M44d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Transformed(this Quad3d polygon, M44d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3d polygon, Euclidean3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Transformed(this Quad3d polygon, Euclidean3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the inverse of the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3d polygon, Euclidean3d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n            polygon.P3 = t.InvTransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the inverse of the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d InvTransformed(this Quad3d polygon, Euclidean3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3d polygon, Similarity3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Transformed(this Quad3d polygon, Similarity3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the inverse of the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3d polygon, Similarity3d t)\n        {\n            polygon.P0 = t.InvTransformPos(polygon.P0);\n            polygon.P1 = t.InvTransformPos(polygon.P1);\n            polygon.P2 = t.InvTransformPos(polygon.P2);\n            polygon.P3 = t.InvTransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the inverse of the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d InvTransformed(this Quad3d polygon, Similarity3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3d polygon, Affine3d t)\n        {\n            polygon.P0 = t.TransformPos(polygon.P0);\n            polygon.P1 = t.TransformPos(polygon.P1);\n            polygon.P2 = t.TransformPos(polygon.P2);\n            polygon.P3 = t.TransformPos(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Transformed(this Quad3d polygon, Affine3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3d polygon, Shift3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Transformed(this Quad3d polygon, Shift3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the inverse of the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3d polygon, Shift3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the inverse of the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d InvTransformed(this Quad3d polygon, Shift3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3d polygon, Rot3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Transformed(this Quad3d polygon, Rot3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the inverse of the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3d polygon, Rot3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the inverse of the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d InvTransformed(this Quad3d polygon, Rot3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3d polygon, Scale3d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Transformed(this Quad3d polygon, Scale3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the inverse of the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref Quad3d polygon, Scale3d t)\n        {\n            polygon.P0 = t.InvTransform(polygon.P0);\n            polygon.P1 = t.InvTransform(polygon.P1);\n            polygon.P2 = t.InvTransform(polygon.P2);\n            polygon.P3 = t.InvTransform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the inverse of the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d InvTransformed(this Quad3d polygon, Scale3d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.InvTransform(t);\n            return result;\n        }\n\n        /// <summary>\n        /// Transforms the <see cref=\"Quad3d\"/> by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"Quad3d\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref Quad3d polygon, M33d t)\n        {\n            polygon.P0 = t.Transform(polygon.P0);\n            polygon.P1 = t.Transform(polygon.P1);\n            polygon.P2 = t.Transform(polygon.P2);\n            polygon.P3 = t.Transform(polygon.P3);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"Quad3d\"/> transformed by the given <see cref=\"M33d\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The Quad3d to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Quad3d Transformed(this Quad3d polygon, M33d t)\n        {\n            var result = new Quad3d(polygon.P0, polygon.P1, polygon.P2, polygon.P3);\n            result.Transform(t);\n            return result;\n        }\n\n        #endregion\n\n        public static V3d[] GetPointArray(this Quad3d quad)\n        {\n            var pa = new V3d[4];\n            pa[0] = quad.P0;\n            pa[1] = quad.P1;\n            pa[2] = quad.P2;\n            pa[3] = quad.P3;\n            return pa;\n        }\n\n        public static V3d ComputeCentroid(this Quad3d quad)\n        {\n            return 0.25 * (quad.P0 + quad.P1 + quad.P2 + quad.P3);\n        }\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Geometry_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# Func<string, Action> Sep = s => () => Out(s);\n    //# Action comma = () => Out(\", \");\n    //# { // POLYGONS\n    //# var planeArray = new[] { \"\", \"\", \"line\", \"plane\" };\n    //# var typeArray = new[] { \"\", \"Polygon\", \"Line\", \"Triangle\", \"Quad\" };\n    //# var nameArray = new[] { \"\", \"polygon\", \"line\", \"triangle\", \"quad\" };\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#     var ftype = isDouble ? \"double\" : \"float\";\n    //#     var ftype2 = isDouble ? \"float\" : \"double\";\n    //#     var tc = isDouble ? \"d\" : \"f\";\n    //#     var tc2 = isDouble ? \"f\" : \"d\";\n    //#     var scaleArray = isDouble ? new[] { \"\", \"\", \"0.5\", \"Constant.OneThird\", \"0.25\" }\n    //#                               : new[] { \"\", \"\", \"0.5f\", \"ConstantF.OneThird\", \"0.25f\" };\n    //#     var eps = isDouble ? \"1e-8\" : \"1e-5f\";\n    //# for (int d = 2; d < 4; d++) {\n    //#     var dp1 = d + 1;\n    //#     var dt = d.ToString() + tc;\n    //#     var di = d.ToString() + \"i\";\n    //#     var tvec = \"V\" + dt;\n    //#     var tveci = \"V\" + di;\n    //#     var tmat = \"M\" + d + dt;\n    //#     var tmat1 = \"M\" + dp1 + dp1 + tc;\n    //#     var teucl = \"Euclidean\" + dt;\n    //#     var tsimi = \"Similarity\" + dt;\n    //#     var taffi = \"Affine\" + dt;\n    //#     var tshif = \"Shift\" + dt;\n    //#     var trot = \"Rot\" + dt;\n    //#     var tscale = \"Scale\" + dt;\n    //#     var plane = planeArray[d];\n    //#     var tplane = \"Plane\" + dt;\n    //#     var tline = \"Line\" + dt;\n    //#     var tbox = \"Box\" + dt;\n    //#     var thull = \"Hull\" + dt;\n    //#     var ttriangle = \"Triangle\" + dt;\n    //#     var tquad = \"Quad\" + dt;\n    //#\n    //# for (int pc = 1; pc < 5; pc++) {\n    //#     var pcsub1 = pc - 1;\n    //#     var type = typeArray[pc] + dt;\n    //#     var name = nameArray[pc];\n    //#     var isPoly = pc == 1;\n    //#     var scale = scaleArray[pc];\n    //#\n    //# foreach (var isIndexed in new[] { false, true }) {\n    //#     if (isIndexed && !isPoly) continue;\n    //#     var indextype = isIndexed ? \"Index\" + type : type;\n    //#\n    //# if (isPoly) {\n    //# if (!isIndexed) {\n    #region __type__\n\n    /// <summary>\n    /// A polygon internally represented by an array of points. Implemented\n    /// as a structure, the validity of the polygon can be checked via its\n    /// PointCount, which must be bigger than 0 for a polygon to hold any\n    /// points, and bigger than 2 for a polygon to be geometrically valid.\n    /// </summary>\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, IValidity, IPolygon<__tvec__>, IBounding__tbox__\n    {\n        internal int m_pointCount;\n        internal __tvec__[] m_pointArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public __type__(__tvec__[] pointArray, int pointCount)\n        {\n            if (pointArray != null)\n            {\n                if (pointCount <= pointArray.Length)\n                {\n                    m_pointCount = pointCount;\n                    m_pointArray = pointArray;\n                }\n                else\n                    throw new ArgumentException(\n                                \"point count must be smaller or equal array length\");\n            }\n            else\n            {\n                m_pointCount = 0;\n                m_pointArray = null;\n            }\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public __type__(params __tvec__[] pointArray)\n        {\n            m_pointCount = pointArray != null ? pointArray.Length : 0;\n            m_pointArray = pointArray;\n        }\n\n        /// <summary>\n        /// Creates a polygon from given points.\n        /// </summary>\n        public __type__(__tvec__[] pointArray, int startIndex, int count)\n        {\n            if (startIndex < 0 || startIndex >= pointArray.Length - 1) throw new ArgumentException();\n            if (count <= 0 || startIndex + count >= pointArray.Length) throw new ArgumentException();\n            m_pointCount = count;\n            m_pointArray = new __tvec__[count];\n            for (int i = 0; i < count; i++) m_pointArray[i] = pointArray[startIndex + i];\n        }\n\n        /// <summary>\n        /// Creates a polygon from point count and point creator function.\n        /// </summary>\n        public __type__(int pointCount, Func<int, __tvec__> index_pointCreator)\n            : this(new __tvec__[pointCount].SetByIndex(index_pointCreator))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a sequence of points.\n        /// </summary>\n        public __type__(IEnumerable<__tvec__> points)\n            : this(points.ToArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from the points of a pointArray that\n        /// are selected by an index array.\n        /// </summary>\n        public __type__(int[] indexArray, __tvec__[] pointArray)\n            : this(indexArray.Map(i => pointArray[i]))\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a triangle.\n        /// </summary>\n        public __type__(__ttriangle__ triangle)\n            : this(triangle.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Creates a polygon from a quad.\n        /// </summary>\n        public __type__(__tquad__ quad)\n            : this(quad.GetPointArray())\n        { }\n\n        /// <summary>\n        /// Copy constructor.\n        /// Performs deep copy of original.\n        /// </summary>\n        public __type__(__type__ original)\n            : this(original.GetPointArray())\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly __type__ Invalid = new __type__(null, 0);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid => m_pointArray != null;\n\n        public readonly bool IsInvalid => m_pointArray == null;\n\n        /// <summary>\n        /// The number of points in the polygon. If this is 0, the polygon\n        /// is invalid.\n        /// </summary>\n        public readonly int PointCount => m_pointCount;\n\n        /// <summary>\n        /// Enumerates points.\n        /// </summary>\n        public readonly IEnumerable<__tvec__> Points\n        {\n            get { for (int pi = 0; pi < m_pointCount; pi++) yield return m_pointArray[pi]; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Returns a copy of the polygons point array.\n        /// </summary>\n        public readonly __tvec__[] GetPointArray()\n        {\n            var pc = m_pointCount;\n            var pa = new __tvec__[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            return pa;\n        }\n\n        /// <summary>\n        /// [P0, P1, P2] -> [P0, P1, P2, P0].\n        /// </summary>\n        public readonly __tvec__[] GetPointArrayWithRepeatedFirstPoint()\n        {\n            var pc = m_pointCount;\n            var pa = new __tvec__[pc + 1];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = m_pointArray[pi];\n            pa[pc] = pa[0];\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<__tvec__, T> point_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_copyFun(m_pointArray[pi]);\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a transformed copy of the polygons point array.\n        /// </summary>\n        public readonly T[] GetPointArray<T>(Func<__tvec__, int, T> point_index_copyFun)\n        {\n            var pc = m_pointCount;\n            var pa = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pa[pi] = point_index_copyFun(m_pointArray[pi], pi);\n            return pa;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets the index-th point of this polygon.\n        /// </summary>\n        public readonly __tvec__ this[int index]\n        {\n            get { return m_pointArray[index]; }\n            set { m_pointArray[index] = value; }\n        }\n\n        #endregion\n\n        #region Edges and Lines\n\n        /// <summary>\n        /// Index-th edge as vector (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly __tvec__ Edge(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return p1 - p0;\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly IEnumerable<__tvec__> Edges\n        {\n            get\n            {\n                var pc = m_pointCount;\n                var p = m_pointArray[0];\n                var p0 = p;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return p1 - p0;\n                    p0 = p1;\n                }\n                yield return p - p0;\n            }\n        }\n\n        /// <summary>\n        /// Index-th edge as line segment (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly __tline__ EdgeLine(int index)\n        {\n            var p0 = m_pointArray[index++];\n            var p1 = m_pointArray[index < m_pointCount ? index : 0];\n            return new __tline__(p0, p1);\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly IEnumerable<__tline__> EdgeLines\n        {\n            get\n            {\n                var pc = m_pointCount;\n                if (pc < 1) yield break;\n                var p0 = m_pointArray[0];\n                var p = p0;\n                for (int pi = 1; pi < pc; pi++)\n                {\n                    var p1 = m_pointArray[pi];\n                    yield return new __tline__(p0, p1);\n                    p0 = p1;\n                }\n                yield return new __tline__(p0, p);\n            }\n        }\n\n        /// <summary>\n        /// Edges as vectors (edgeEndPos - edgeBeginPos).\n        /// </summary>\n        public readonly __tvec__[] GetEdgeArray()\n        {\n            var pc = m_pointCount;\n            if (pc < 2) return Array.Empty<__tvec__>();\n            var edgeArray = new __tvec__[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                edgeArray[pi - 1] = p1 - p0;\n                p0 = p1;\n            }\n            edgeArray[pc - 1] = p - p0;\n            return edgeArray;\n        }\n\n        /// <summary>\n        /// Edges as line segments (edgeBeginPos, edgeEndPos).\n        /// </summary>\n        public readonly __tline__[] GetEdgeLineArray()\n        {\n            var pc = PointCount;\n            if (pc < 2) return Array.Empty<__tline__>();\n            var ela = new __tline__[pc];\n            var p = m_pointArray[0];\n            var p0 = p;\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p1 = m_pointArray[pi];\n                ela[pi - 1] = new __tline__(p0, p1);\n                p0 = p1;\n            }\n            ela[pc - 1] = new __tline__(p0, p);\n            return ela;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Returns copy of polygon. Same as Map(p => p).\n        /// </summary>\n        public readonly __type__ Copy()\n        {\n            return new __type__(m_pointArray.Copy());\n        }\n\n        /// <summary>\n        /// Returns transformed copy of this polygon.\n        /// </summary>\n        public readonly __type__ Map(Func<__tvec__, __tvec__> point_fun)\n        {\n            var pc = m_pointCount;\n            __tvec__[] opa = m_pointArray, npa = new __tvec__[pc];\n            for (int pi = 0; pi < pc; pi++) npa[pi] = point_fun(opa[pi]);\n            return new __type__(npa, pc);\n        }\n\n        /// <summary>\n        /// Gets copy with reversed order of vertices.\n        /// </summary>\n        public readonly __type__ Reversed\n        {\n            get\n            {\n                var pc = m_pointCount;\n                __tvec__[] opa = m_pointArray, npa = new __tvec__[pc];\n                for (int pi = 0, pj = pc - 1; pi < pc; pi++, pj--) npa[pi] = opa[pj];\n                return new __type__(npa, pc);\n            }\n        }\n\n        /// <summary>\n        /// Reverses order of vertices in-place.\n        /// </summary>\n        public readonly void Reverse()\n        {\n            var pa = m_pointArray;\n            for (int pi = 0, pj = m_pointCount - 1; pi < pj; pi++, pj--)\n            { var t = pa[pi]; pa[pi] = pa[pj]; pa[pj] = t; }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (a.m_pointArray[pi] != b.m_pointArray[pi]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return m_pointArray.GetCombinedHashCode(m_pointCount);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n        {\n            if (m_pointCount != other.m_pointCount) return false;\n            for (int pi = 0; pi < m_pointCount; pi++)\n                if (!m_pointArray[pi].Equals(other.m_pointArray[pi])) return false;\n            return true;\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture,\n                \"[{0}]\", Points.Select(x => x.ToString()).Join(\", \")\n                );\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var va = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(va.Select(x => __tvec__.Parse(x)));\n        }\n\n        #endregion\n\n        #region IBounding__tbox__ Members\n\n        /// <summary>\n        /// Bounding box of polygon.\n        /// </summary>\n        public readonly __tbox__ Bounding__tbox__\n        {\n            get { return new __tbox__(m_pointArray, 0, m_pointCount); }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance)\n        {\n            if (a.m_pointCount != b.m_pointCount) return false;\n            for (int pi = 0; pi < a.m_pointCount; pi++)\n                if (!ApproximateEquals(a.m_pointArray[pi], b.m_pointArray[pi], tolerance)) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# } // !isIndexed\n    //# if (isIndexed) {\n    #region __indextype__\n\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct __indextype__ : IValidity, IPolygon<__tvec__>\n    {\n        private readonly int m_pointCount;\n        private readonly int m_firstIndex;\n        private readonly int[] m_indexArray;\n        private readonly __tvec__[] m_pointArray;\n\n        #region Constructors\n\n        public __indextype__(int[] indexArray, int firstIndex, int pointCount, __tvec__[] pointArray)\n        {\n            m_indexArray = indexArray;\n            m_firstIndex = firstIndex;\n            m_pointCount = pointCount;\n            m_pointArray = pointArray;\n        }\n\n        public __indextype__(__tvec__[] pointArray, int firstIndex, int pointCount)\n            : this(new int[pointCount].SetByIndex(i => firstIndex + i), 0, pointCount, pointArray)\n        { }\n\n        public __indextype__(__tvec__[] pointArray)\n            : this(new int[pointArray.Length].SetByIndex(i => i), 0, pointArray.Length, pointArray)\n        { }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly __indextype__ Invalid = new __indextype__(null, 0, 0, null);\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid { get { return m_indexArray != null && m_pointArray != null; } }\n        public bool IsInvalid { get { return m_indexArray == null || m_pointArray == null; } }\n\n        public int PointCount\n        {\n            get { return m_pointCount; }\n        }\n\n        public int FirstIndex { get { return m_firstIndex; } }\n\n        /// <summary>\n        /// The index array that contains the point indices of the\n        /// index polygon at the index range [FirstIndex, FirstIndex + PointCount).\n        /// NOTE: This is different from the array returned by GetIndexArray().\n        /// </summary>\n        public int[] IndexArray { get { return m_indexArray; } }\n\n        /// <summary>\n        /// The point array that contains the points referenced by\n        /// the index array. Note: This is different from the array\n        /// returned by GetPointArray().\n        /// </summary>\n        public __tvec__[] PointArray { get { return m_pointArray; } }\n\n        public IEnumerable<__tvec__> Points\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_pointArray[m_indexArray[m_firstIndex + i]];\n            }\n        }\n\n        public IEnumerable<int> Indices\n        {\n            get\n            {\n                for (int i = 0; i < m_pointCount; i++)\n                    yield return m_indexArray[m_firstIndex + i];\n            }\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public __tvec__ this[int index]\n        {\n            get { return m_pointArray[m_indexArray[m_firstIndex + index]]; }\n            set { m_pointArray[m_indexArray[m_firstIndex + index]] = value; }\n        }\n\n        #endregion\n\n        #region Conversions\n\n        public void ForEachIndex(Action<int> index_act)\n        {\n            var ia = m_indexArray; int fi = m_firstIndex;\n            for (int i = 0; i < m_pointCount; i++) index_act(ia[fi + i]);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual indices\n        /// of the index polygon. NOTE: This is different from the\n        /// IndexArray property!\n        /// </summary>\n        public int[] GetIndexArray()\n        {\n            return m_indexArray.Copy(m_firstIndex, m_pointCount);\n        }\n\n        /// <summary>\n        /// Returns a newly created array containing only the actual points\n        /// of the index polygon. NOTE: This is different from the\n        /// PointArray property!\n        /// </summary>\n        public __tvec__[] GetPointArray()\n        {\n            var pa = m_pointArray;\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pa[i]);\n        }\n\n        public T[] GetPointArray<T>(T[] pointArray)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointArray[i]);\n        }\n\n        public T[] GetPointArray<T>(List<T> pointList)\n        {\n            return m_indexArray.Map(m_firstIndex, m_pointCount, i => pointList[i]);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } // isIndexed\n    #region __indextype__Extensions\n\n    public static partial class __indextype__Extensions\n    {\n        //# if (isIndexed) {\n        #region Conversions\n\n        public static __type__ To__type__(this __indextype__ polygon)\n        {\n            return new __type__(polygon.GetPointArray());\n        }\n\n        #endregion\n\n        //# } // isIndexed\n        #region Geometric Properties\n\n        /// <summary>\n        /// The vertex centroid is the average of the vertex coordinates.\n        /// </summary>\n        public static __tvec__ ComputeVertexCentroid(this __indextype__ polygon)\n        {\n            var sum = __tvec__.Zero;\n            int pc = polygon.PointCount;\n            for (int i = 0; i < pc; i++) sum += polygon[i];\n            __ftype__ scale = 1 / (__ftype__)pc;\n            return sum * scale;\n        }\n\n        public static __ftype__ ComputePerimeter(this __indextype__ polygon)\n        {\n            var pc = polygon.PointCount;\n            var p0 = polygon[pc - 1];\n            __ftype__ r = 0;\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                r += Vec.Distance(p0, p1);\n                p0 = p1;\n            }\n            return r;\n        }\n\n        #endregion\n        //# if (!isIndexed) {\n\n        #region Geometric Transformations\n\n        //# var scales = new string [] { ftype, tvec };\n        //# foreach (string tscalefactor in scales) {\n        /// <summary>\n        /// Scales the <see cref=\"__type__\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref __type__ polygon, __tscalefactor__ scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] *= scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scaled(this __type__ polygon, __tscalefactor__ scale)\n        {\n            var result = new __type__(polygon);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"__type__\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        public static void Scale(this ref __type__ polygon, __tvec__ center, __tscalefactor__ scale)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = center + (polygon.m_pointArray[pi] - center) * scale;\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scaled(this __type__ polygon, __tvec__ center, __tscalefactor__ scale)\n        {\n            var result = new __type__(polygon);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"__type__\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutVertexCentroid(this ref __type__ polygon, __tscalefactor__ scale)\n        {\n            var center = polygon.ComputeVertexCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ScaledAboutVertexCentroid(this __type__ polygon, __tscalefactor__ scale)\n        {\n            var result = new __type__(polygon);\n            result.ScaleAboutVertexCentroid(scale);\n            return result;\n        }\n\n        //# }\n        //# var transforms = new string [] { tmat1, teucl, tsimi, taffi, tshif, trot, tscale, tmat };\n        //# for (int i = 0; i < transforms.Length; i++) {\n        //#     var ttrafo = transforms[i];\n        //#     var transform = (i < 4) ? \"TransformPos\" : \"Transform\";\n        //#     var hasInv = (i != 0 && i != 3 && i != 7);\n        /// <summary>\n        /// Transforms the <see cref=\"__type__\"/> by the given <see cref=\"__ttrafo__\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void Transform(this ref __type__ polygon, __ttrafo__ t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.__transform__(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> transformed by the given <see cref=\"__ttrafo__\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The __type__ to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Transformed(this __type__ polygon, __ttrafo__ t)\n        {\n            var result = new __type__(polygon);\n            result.Transform(t);\n            return result;\n        }\n\n        //# if (hasInv) {\n        /// <summary>\n        /// Transforms the <see cref=\"__type__\"/> by the inverse of the given <see cref=\"__ttrafo__\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        public static void InvTransform(this ref __type__ polygon, __ttrafo__ t)\n        {\n            for (int pi = 0; pi < polygon.m_pointCount; pi++)\n                polygon.m_pointArray[pi] = t.Inv__transform__(polygon.m_pointArray[pi]);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> transformed by the inverse of the given <see cref=\"__ttrafo__\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The __type__ to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ InvTransformed(this __type__ polygon, __ttrafo__ t)\n        {\n            var result = new __type__(polygon);\n            result.InvTransform(t);\n            return result;\n        }\n\n        //# }\n        //# }\n        public static __type__ WithoutMultiplePoints(this __type__ polygon, __ftype__ eps = __eps__)\n        {\n            eps *= eps;\n            var opc = polygon.PointCount;\n            var pa = new __tvec__[opc];\n            var pc = 0;\n            pa[0] = polygon[0];\n            for (int pi = 1; pi < opc; pi++)\n                if (Vec.DistanceSquared(pa[pc], polygon[pi]) > eps)\n                    pa[++pc] = polygon[pi];\n            if (Vec.DistanceSquared(pa[pc], polygon[0]) > eps)\n                ++pc;\n            return new __type__(pa, pc);\n        }\n\n        #endregion\n\n        #region Clipping\n\n        /// <summary>\n        /// Clip the supplied polygon at the supplied __plane__. The method should\n        /// work with all non-selfintersecting polygons. Returns all parts of\n        /// the polygon that are at the positive side of the __plane__.\n        /// </summary>\n        public static __type__ ConvexClipped(\n                this __type__ polygon, __tplane__ __plane__, __ftype__ eps = __eps__)\n        {\n            var opc = polygon.PointCount;\n            __tvec__[] pa = new __tvec__[opc + 1];\n            var pc = 0;\n            var pf = polygon[0];\n            var hf = __plane__.Height(pf); bool hfp = hf > eps, hfn = hf < -eps;\n            if (hf >= -eps) pa[pc++] = pf;\n            var p0 = pf; var h0 = hf; var h0p = hfp; var h0n = hfn;\n            for (int vi = 1; vi < opc; vi++)\n            {\n                var p1 = polygon[vi];\n                var h1 = __plane__.Height(p1); bool h1p = h1 > eps, h1n = h1 < -eps;\n                if (h0p && h1n || h0n && h1p) pa[pc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));\n                if (h1 >= -eps) pa[pc++] = p1;\n                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;\n            }\n            if (h0p && hfn || h0n && hfp) pa[pc++] = p0 + (pf - p0) * (h0 / (h0 - hf));\n            return new __type__(pa, pc);\n        }\n\n        /// <summary>\n        /// Returns the convex polygon clipped by the set of __plane__s (defined\n        /// as __tplane__s), i.e. all parts of the polygon that are at the positive\n        /// side of the __plane__s.\n        /// </summary>\n        public static __type__ ConvexClipped(\n                this __type__ polygon, __tplane__[] __plane__s, __ftype__ eps = __eps__)\n        {\n            foreach (var c in __plane__s)\n            {\n                polygon = polygon.ConvexClipped(c, eps);\n                if (polygon.PointCount == 0) break;\n            }\n            return polygon;\n        }\n\n        /// <summary>\n        /// Returns the polygon clipped by the hull, i.e. all parts of the\n        /// polygon that are at the positive side of the hull __plane__s.\n        /// </summary>\n        public static __type__ ConvexClipped(\n                this __type__ polygon, __thull__ hull, __ftype__ eps = __eps__)\n        {\n            return polygon.ConvexClipped(hull.PlaneArray, eps);\n        }\n\n        /// <summary>\n        /// TODO summary.\n        /// </summary>\n        public static __type__ ConvexClipped(\n                this __type__ polygon, __tbox__ box, __ftype__ eps = __eps__)\n        {\n            var __plane__s = new[]\n            {\n                //# Meta.VecFields.Take(d).ForEach(axis => {\n                new __tplane__(__tvec__.__axis__Axis, box.Min), new __tplane__(-__tvec__.__axis__Axis, box.Max),\n                //# });\n            };\n            return polygon.ConvexClipped(__plane__s);\n        }\n\n        #endregion\n        //# } // !isIndexed\n    }\n\n    #endregion\n\n    //# } else { // !isPoly\n    #region __type__\n\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, IValidity, IPolygon<__tvec__>, IBounding__tbox__\n    {\n        public __tvec__ /*# pc.ForEach(i => { */P__i__/*# }, Sep(\", \")); */;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates __name__ from __pc__ points.\n        /// </summary>\n        public __type__(/*# pc.ForEach(i => { */__tvec__ p__i__/*# }, Sep(\", \")); */)\n        {\n            /*# pc.ForEach(i => { */P__i__ = p__i__/*# }, Sep(\"; \")); */;\n        }\n\n        /// <summary>\n        /// Creates __name__ from first __pc__ points in the sequence.\n        /// </summary>\n        public __type__(IEnumerable<__tvec__> points)\n        {\n            var pa = points.TakeToArray(__pc__);\n            /*# pc.ForEach(i => { */P__i__ = pa[__i__]/*# }, Sep(\"; \")); */;\n        }\n\n        //# if (pc == 4) {\n        /// <summary>\n        /// Creates quad from point and two vectors representing edges.\n        /// </summary>\n        public __type__(__tvec__ p0, __tvec__ edge01, __tvec__ edge03)\n        {\n            P0 = p0;\n            P1 = p0 + edge01;\n            P2 = P1 + edge03;\n            P3 = p0 + edge03;\n        }\n\n        //# }\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return true; } }\n        public readonly bool IsInvalid { get { return false; } }\n\n        //# if (pc > 2) {\n        //# pc.ForEach(i => { foreach (var j in new[] { (i + 1) % pc, (i + pcsub1) % pc }) {\n        /// <summary>\n        /// Edge P__j__ - P__i__\n        /// </summary>\n        public readonly __tvec__ Edge__i____j__ { get { return P__j__ - P__i__; } }\n        //# } });\n\n        public readonly IEnumerable<__tvec__> Edges\n        {\n            get\n            {\n                //# pc.ForEach(i => { var j = (i + 1) % pc;\n                yield return P__j__ - P__i__;\n                //# });\n            }\n        }\n\n        public readonly __tvec__[] EdgeArray\n        {\n            get\n            {\n                var a = new __tvec__[__pc__];\n                //# pc.ForEach(i => { var j = (i + 1) % pc;\n                a[__i__] = P__j__ - P__i__;\n                //# });\n                return a;\n            }\n        }\n\n        public readonly IEnumerable<__tline__> EdgeLines\n        {\n            get\n            {\n                //# pc.ForEach(i => { var j = (i + 1) % pc;\n                yield return new __tline__(P__i__, P__j__);\n                //# });\n            }\n        }\n\n        public readonly __tline__[] EdgeLineArray\n        {\n            get\n            {\n                var a = new __tline__[__pc__];\n                //# pc.ForEach(i => { var j = (i + 1) % pc;\n                a[__i__] = new __tline__(P__i__, P__j__);\n                //# });\n                return a;\n            }\n        }\n\n        public readonly __tline__ GetEdgeLine(int index)\n        {\n            switch (index)\n            {\n                //# pc.ForEach(i => { var j = (i + 1) % pc;\n                case __i__: return new __tline__(P__i__, P__j__);\n                //# });\n            }\n            throw new InvalidOperationException();\n        }\n\n        public readonly __tvec__ GetEdge(int index)\n        {\n            switch (index)\n            {\n                //# pc.ForEach(i => { var j = (i + 1) % pc;\n                case __i__: return P__j__ - P__i__;\n                //# });\n            }\n            throw new InvalidOperationException();\n        }\n\n        //# pc.ForEach(i => { foreach (var j in new[] { (i + 1) % pc, (i + pcsub1) % pc }) {\n        public readonly __tline__ Line__i____j__ { get { return new __tline__(P__i__, P__j__); } }\n        //# } });\n\n        //# } // pc > 2\n        public readonly int PointCount { get { return __pc__; } }\n\n        public readonly IEnumerable<__tvec__> Points\n        {\n            get { /*# pc.ForEach(i => { */yield return P__i__/*# }, Sep(\"; \")); */; }\n        }\n\n        public readonly __type__ Reversed\n        {\n            get { return new __type__(/*# pc.ForEach(i => { var j = pcsub1 - i; */P__j__/*# }, Sep(\", \")); */); }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public __tvec__ this[int index]\n        {\n            readonly get\n            {\n                switch (index)\n                {\n                    //# pc.ForEach(i => {\n                    case __i__: return P__i__;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n            set\n            {\n                switch (index)\n                {\n                    //# pc.ForEach(i => {\n                    case __i__: P__i__ = value; return;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly __type__ Copy(Func<__tvec__, __tvec__> point_copyFun)\n        {\n            return new __type__(/*# pc.ForEach(i => { */point_copyFun(P__i__)/*# }, Sep(\", \")); */);\n        }\n\n        //# for (int od = 2; od < 4; od++) { if (d == od) continue;\n        //#     var otype = typeArray[pc] + od + \"d\"; var otvec = \"V\" + od + \"d\";\n        public readonly __otype__ To__otype__(Func<__tvec__, __otvec__> point_copyFun)\n        {\n            return new __otype__(/*# pc.ForEach(i => { */point_copyFun(P__i__)/*# }, Sep(\", \")); */);\n        }\n\n        //# } // od\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => /*# pc.ForEach(i => { */(a.P__i__ == b.P__i__)/*# }, Sep(\" && \")); */;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(/*# pc.ForEach(i => { */P__i__/*# }, Sep(\", \")); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => /*# pc.ForEach(i => { */P__i__.Equals(other.P__i__)/*# }, Sep(\" && \")); */;\n\n        public override readonly bool Equals(object other)\n             => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            //# var format = \"[\"; pc.ForEach(i => format += \"{\" + i + \"}\", () => format += \", \"); format += \"]\";\n            return string.Format(CultureInfo.InvariantCulture, \"__format__\", /*# pc.ForEach(i => { */P__i__/*# }, Sep(\", \")); */);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(/*# pc.ForEach(i => { */__tvec__.Parse(x[__i__])/*# }, Sep(\", \")); */);\n        }\n\n        #endregion\n\n        #region IBounding__tbox__ Members\n\n        public readonly __tbox__ Bounding__tbox__\n        {\n            get\n            {\n                return new __tbox__(/*# pc.ForEach(i => { */P__i__/*# }, Sep(\", \"));\n                                        */)/*#if (pc == 2) {*/.Repair()/*# } */;\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance)\n            => /*# pc.ForEach(i => { */ApproximateEquals(a.P__i__, b.P__i__, tolerance)/*# }, Sep(\" && \")); */;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region __type__Extensions\n\n    public static partial class __type__Extensions\n    {\n        #region Geometric Transformations\n\n        //# var scales = new string [] { ftype, tvec };\n        //# foreach (string tscalefactor in scales) {\n        /// <summary>\n        /// Scales the <see cref=\"__type__\"/> by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref __type__ polygon, __tscalefactor__ scale)\n        {\n            //# pc.ForEach(i => {\n            polygon.P__i__ *= scale;\n            //# });\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> scaled by the given factor.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scaled(this __type__ polygon, __tscalefactor__ scale)\n        {\n            var result = new __type__(/*# pc.ForEach(i => {*/polygon.P__i__/*#}, comma);*/);\n            result.Scale(scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"__type__\"/> by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Scale(this ref __type__ polygon, __tvec__ center, __tscalefactor__ scale)\n        {\n            //# pc.ForEach(i => {\n            polygon.P__i__ = center + (polygon.P__i__ - center) * scale;\n            //# });\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> scaled by the given factor about the given center.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"center\">The scaling center.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scaled(this __type__ polygon, __tvec__ center, __tscalefactor__ scale)\n        {\n            var result = new __type__(/*# pc.ForEach(i => {*/polygon.P__i__/*#}, comma);*/);\n            result.Scale(center, scale);\n            return result;\n        }\n\n        /// <summary>\n        /// Scales the <see cref=\"__type__\"/> by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ScaleAboutCentroid(this ref __type__ polygon, __tscalefactor__ scale)\n        {\n            var center = polygon.ComputeCentroid();\n            polygon.Scale(center, scale);\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> scaled by the given factor about the centroid.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to scale.</param>\n        /// <param name=\"scale\">The scale factor.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ScaledAboutCentroid(this __type__ polygon, __tscalefactor__ scale)\n        {\n            var result = new __type__(/*# pc.ForEach(i => {*/polygon.P__i__/*#}, comma);*/);\n            result.ScaleAboutCentroid(scale);\n            return result;\n        }\n\n        //# }\n        //# var transforms = new string [] { tmat1, teucl, tsimi, taffi, tshif, trot, tscale, tmat };\n        //# for (int j = 0; j < transforms.Length; j++) {\n        //#     var ttrafo = transforms[j];\n        //#     var transform = (j < 4) ? \"TransformPos\" : \"Transform\";\n        //#     var hasInv = (j != 0 && j != 3 && j != 7);\n        /// <summary>\n        /// Transforms the <see cref=\"__type__\"/> by the given <see cref=\"__ttrafo__\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transform(this ref __type__ polygon, __ttrafo__ t)\n        {\n            //# pc.ForEach(i => {\n            polygon.P__i__ = t.__transform__(polygon.P__i__);\n            //# });\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> transformed by the given <see cref=\"__ttrafo__\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The __type__ to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Transformed(this __type__ polygon, __ttrafo__ t)\n        {\n            var result = new __type__(/*# pc.ForEach(i => {*/polygon.P__i__/*#}, comma);*/);\n            result.Transform(t);\n            return result;\n        }\n\n        //# if (hasInv) {\n        /// <summary>\n        /// Transforms the <see cref=\"__type__\"/> by the inverse of the given <see cref=\"__ttrafo__\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The <see cref=\"__type__\"/> to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void InvTransform(this ref __type__ polygon, __ttrafo__ t)\n        {\n            //# pc.ForEach(i => {\n            polygon.P__i__ = t.Inv__transform__(polygon.P__i__);\n            //# });\n        }\n\n        /// <summary>\n        /// Returns a copy of the <see cref=\"__type__\"/> transformed by the inverse of the given <see cref=\"__ttrafo__\"/> transformation.\n        /// </summary>\n        /// <param name=\"polygon\">The __type__ to transform.</param>\n        /// <param name=\"t\">The transformation to apply.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ InvTransformed(this __type__ polygon, __ttrafo__ t)\n        {\n            var result = new __type__(/*# pc.ForEach(i => {*/polygon.P__i__/*#}, comma);*/);\n            result.InvTransform(t);\n            return result;\n        }\n\n        //# }\n        //# }\n        #endregion\n\n        public static __tvec__[] GetPointArray(this __type__ __name__)\n        {\n            var pa = new __tvec__[__pc__];\n            //# pc.ForEach(i => {\n            pa[__i__] = __name__.P__i__;\n            //# });\n            return pa;\n        }\n\n        public static __tvec__ ComputeCentroid(this __type__ __name__)\n        {\n            return __scale__ * (/*# pc.ForEach(i => { */__name__.P__i__/*# }, Sep(\" + \")); */);\n        }\n    }\n\n    #endregion\n\n    //# } // !isPoly\n    //# } // isIndexed\n    //# } // pc\n    //# } // d\n    //# } // isDouble\n    //# } // POLYGONS\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Hull/Hull2_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Hull2f\n\n    /// <summary>\n    /// A hull is an alternative representation of a convex polygon.\n    /// </summary>\n    public partial struct Hull2f : IEquatable<Hull2f>, IValidity\n    {\n        public Plane2f[] PlaneArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create an empty Hull3d with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2f(int count)\n        {\n            PlaneArray = new Plane2f[count];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2f(Plane2f[] planeArray)\n        {\n            PlaneArray = planeArray;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2f(Box2f box)\n        {\n            PlaneArray = new[]\n            {\n                new Plane2f(V2f.XAxis, box.Min),\n                new Plane2f(V2f.YAxis, box.Min),\n                new Plane2f(-V2f.XAxis, box.Max),\n                new Plane2f(-V2f.YAxis, box.Max),\n            };\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2f(Hull2f hull)\n        {\n            PlaneArray = hull.PlaneArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2f(Hull2d hull)\n        {\n            PlaneArray = hull.PlaneArray.Map(p => new Plane2f(p));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Hull2f(Hull2d h)\n            => new Hull2f(h);\n\n        #endregion\n\n        #region Constants\n\n        public static Hull2f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Hull2f(null);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray != null;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray == null;\n        }\n\n        public readonly int PlaneCount\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray.Length;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Hull2f a, Hull2f b)\n            => a.Equals(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Hull2f a, Hull2f b)\n            => !a.Equals(b);\n\n        #endregion\n\n        #region Override\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n        {\n            if (PlaneArray == null || PlaneArray.Length == 0) return 0;\n            var h = PlaneArray[0].GetHashCode();\n            for (var i = 1; i < PlaneArray.Length; i++) HashCode.GetCombined(h, PlaneArray[i].GetHashCode());\n            return h;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Hull2f other)\n        {\n            if (PlaneArray == null || other.PlaneArray == null) return false;\n            for (var i = 0; i < PlaneArray.Length; i++) if (PlaneArray[i] != other.PlaneArray[i]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Hull2f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => PlaneArray != null\n                ? string.Format(CultureInfo.InvariantCulture, \"[{0}]\", string.Join(\",\", PlaneArray.Map(x => x.ToString())))\n                : \"[null]\"\n                ;\n\n        /// <summary>\n        /// Parses Hull2f from a string created with Hull2f.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Hull2f Parse(string s)\n        {\n            if (s == \"[null]\") return Hull2f.Invalid;\n            var planes = s.NestedBracketSplitLevelOne().Select(Plane2f.Parse).ToArray();\n            return new Hull2f(planes);\n        }\n\n        #endregion\n\n        #region Transformation\n\n        public readonly Hull2f Transformed(Trafo2f trafo)\n        {\n            int count = PlaneCount;\n            var hull = new Hull2f(new Plane2f[count]);\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new Plane2f(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n            return hull;\n        }\n\n        public readonly void TransformInto(Trafo2f trafo, ref Hull2f hull)\n        {\n            int count = PlaneCount;\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new Plane2f(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Hull2f Reversed()\n            => new Hull2f(PlaneArray.Map(p => p.Reversed));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void Reverse()\n            => PlaneArray.Apply(p => p.Reversed);\n\n        #endregion\n    }\n\n    public static class Hull2fExtensions\n    {\n        /// <summary>\n        /// Creates an inward hull (i.e. a hull whose normal vectors point\n        /// inside) from a counter-clockwise enumerated array of polygon\n        /// points.\n        /// </summary>\n        public static Hull2f ToInwardHull(this V2f[] polygon, int pointCount = 0)\n        {\n            if (pointCount == 0) pointCount = polygon.Length;\n            var planeArray = new Plane2f[pointCount];\n            var p0 = polygon[pointCount - 1];\n            for (int i = 0; i < pointCount; i++)\n            {\n                var p1 = polygon[i];\n                planeArray[i] = new Plane2f((p1 - p0).Rot90.Normalized, p0);\n                p0 = p1;\n            }\n            return new Hull2f(planeArray);\n        }\n\n        /// <summary>\n        /// Returns true if the supplied point is inside a hull with\n        /// planes whose normal vectors point to the inside of the hull.\n        /// The optional offset parameter is measured in normal direction,\n        /// i.e. a positive offset makes the hull smaller.\n        /// </summary>\n        public static bool IsInsideInwardHull(this V2f point, Hull2f hull, float offset = 0)\n        {\n            for (int i = 0; i < hull.PlaneCount; i++)\n                if (hull.PlaneArray[i].Height(point) < offset) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns unordered set of corners of this hull.\n        /// </summary>\n        public static HashSet<V2f> ComputeCorners(this Hull2f hull)\n        {\n            var corners = new HashSet<V2f>();\n            int count = hull.PlaneArray.Length;\n            for (var i0 = 0; i0 < count; i0++)\n            {\n                for (var i1 = i0 + 1; i1 < count; i1++)\n                {\n                    if (hull.PlaneArray[i0].Intersects(hull.PlaneArray[i1], out V2f temp))\n                    {\n                        if (temp.IsNaN || temp.AnyInfinity) continue;\n\n                        var inside = true;\n                        for (var j = 0; j < count; j++)\n                        {\n                            if (j == i0 || j == i1) continue;\n                            var h = hull.PlaneArray[j].Height(temp);\n                            if (h > 0) { inside = false; break; }\n                        }\n\n                        if (inside)\n                        {\n                            corners.Add(temp);\n                        }\n                    }\n                }\n            }\n\n            return corners;\n        }\n    }\n\n    #endregion\n\n    #region Hull2d\n\n    /// <summary>\n    /// A hull is an alternative representation of a convex polygon.\n    /// </summary>\n    public partial struct Hull2d : IEquatable<Hull2d>, IValidity\n    {\n        public Plane2d[] PlaneArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create an empty Hull3d with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2d(int count)\n        {\n            PlaneArray = new Plane2d[count];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2d(Plane2d[] planeArray)\n        {\n            PlaneArray = planeArray;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2d(Box2d box)\n        {\n            PlaneArray = new[]\n            {\n                new Plane2d(V2d.XAxis, box.Min),\n                new Plane2d(V2d.YAxis, box.Min),\n                new Plane2d(-V2d.XAxis, box.Max),\n                new Plane2d(-V2d.YAxis, box.Max),\n            };\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2d(Hull2d hull)\n        {\n            PlaneArray = hull.PlaneArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull2d(Hull2f hull)\n        {\n            PlaneArray = hull.PlaneArray.Map(p => new Plane2d(p));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Hull2d(Hull2f h)\n            => new Hull2d(h);\n\n        #endregion\n\n        #region Constants\n\n        public static Hull2d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Hull2d(null);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray != null;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray == null;\n        }\n\n        public readonly int PlaneCount\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray.Length;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Hull2d a, Hull2d b)\n            => a.Equals(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Hull2d a, Hull2d b)\n            => !a.Equals(b);\n\n        #endregion\n\n        #region Override\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n        {\n            if (PlaneArray == null || PlaneArray.Length == 0) return 0;\n            var h = PlaneArray[0].GetHashCode();\n            for (var i = 1; i < PlaneArray.Length; i++) HashCode.GetCombined(h, PlaneArray[i].GetHashCode());\n            return h;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Hull2d other)\n        {\n            if (PlaneArray == null || other.PlaneArray == null) return false;\n            for (var i = 0; i < PlaneArray.Length; i++) if (PlaneArray[i] != other.PlaneArray[i]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Hull2d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => PlaneArray != null\n                ? string.Format(CultureInfo.InvariantCulture, \"[{0}]\", string.Join(\",\", PlaneArray.Map(x => x.ToString())))\n                : \"[null]\"\n                ;\n\n        /// <summary>\n        /// Parses Hull2d from a string created with Hull2d.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Hull2d Parse(string s)\n        {\n            if (s == \"[null]\") return Hull2d.Invalid;\n            var planes = s.NestedBracketSplitLevelOne().Select(Plane2d.Parse).ToArray();\n            return new Hull2d(planes);\n        }\n\n        #endregion\n\n        #region Transformation\n\n        public readonly Hull2d Transformed(Trafo2d trafo)\n        {\n            int count = PlaneCount;\n            var hull = new Hull2d(new Plane2d[count]);\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new Plane2d(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n            return hull;\n        }\n\n        public readonly void TransformInto(Trafo2d trafo, ref Hull2d hull)\n        {\n            int count = PlaneCount;\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new Plane2d(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Hull2d Reversed()\n            => new Hull2d(PlaneArray.Map(p => p.Reversed));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void Reverse()\n            => PlaneArray.Apply(p => p.Reversed);\n\n        #endregion\n    }\n\n    public static class Hull2dExtensions\n    {\n        /// <summary>\n        /// Creates an inward hull (i.e. a hull whose normal vectors point\n        /// inside) from a counter-clockwise enumerated array of polygon\n        /// points.\n        /// </summary>\n        public static Hull2d ToInwardHull(this V2d[] polygon, int pointCount = 0)\n        {\n            if (pointCount == 0) pointCount = polygon.Length;\n            var planeArray = new Plane2d[pointCount];\n            var p0 = polygon[pointCount - 1];\n            for (int i = 0; i < pointCount; i++)\n            {\n                var p1 = polygon[i];\n                planeArray[i] = new Plane2d((p1 - p0).Rot90.Normalized, p0);\n                p0 = p1;\n            }\n            return new Hull2d(planeArray);\n        }\n\n        /// <summary>\n        /// Returns true if the supplied point is inside a hull with\n        /// planes whose normal vectors point to the inside of the hull.\n        /// The optional offset parameter is measured in normal direction,\n        /// i.e. a positive offset makes the hull smaller.\n        /// </summary>\n        public static bool IsInsideInwardHull(this V2d point, Hull2d hull, double offset = 0)\n        {\n            for (int i = 0; i < hull.PlaneCount; i++)\n                if (hull.PlaneArray[i].Height(point) < offset) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns unordered set of corners of this hull.\n        /// </summary>\n        public static HashSet<V2d> ComputeCorners(this Hull2d hull)\n        {\n            var corners = new HashSet<V2d>();\n            int count = hull.PlaneArray.Length;\n            for (var i0 = 0; i0 < count; i0++)\n            {\n                for (var i1 = i0 + 1; i1 < count; i1++)\n                {\n                    if (hull.PlaneArray[i0].Intersects(hull.PlaneArray[i1], out V2d temp))\n                    {\n                        if (temp.IsNaN || temp.AnyInfinity) continue;\n\n                        var inside = true;\n                        for (var j = 0; j < count; j++)\n                        {\n                            if (j == i0 || j == i1) continue;\n                            var h = hull.PlaneArray[j].Height(temp);\n                            if (h > 0) { inside = false; break; }\n                        }\n\n                        if (inside)\n                        {\n                            corners.Add(temp);\n                        }\n                    }\n                }\n            }\n\n            return corners;\n        }\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Hull/Hull2_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Hull2\" + tc;\n    //#   var type2 = \"Hull2\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var box2t = \"Box2\" + tc;\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var plane2t2 = \"Plane2\" + tc2;\n    //#   var trafo2t = \"Trafo2\" + tc;\n    //#   var iboundingbox = \"IBoundingBox2\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    #region __type__\n\n    /// <summary>\n    /// A hull is an alternative representation of a convex polygon.\n    /// </summary>\n    public partial struct __type__ : IEquatable<__type__>, IValidity\n    {\n        public __plane2t__[] PlaneArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create an empty Hull3d with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(int count)\n        {\n            PlaneArray = new __plane2t__[count];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__plane2t__[] planeArray)\n        {\n            PlaneArray = planeArray;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__box2t__ box)\n        {\n            PlaneArray = new[]\n            {\n                new __plane2t__(__v2t__.XAxis, box.Min),\n                new __plane2t__(__v2t__.YAxis, box.Min),\n                new __plane2t__(-__v2t__.XAxis, box.Max),\n                new __plane2t__(-__v2t__.YAxis, box.Max),\n            };\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ hull)\n        {\n            PlaneArray = hull.PlaneArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ hull)\n        {\n            PlaneArray = hull.PlaneArray.Map(p => new __plane2t__(p));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ h)\n            => new __type__(h);\n\n        #endregion\n\n        #region Constants\n\n        public static __type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(null);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray != null;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray == null;\n        }\n\n        public readonly int PlaneCount\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray.Length;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => a.Equals(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !a.Equals(b);\n\n        #endregion\n\n        #region Override\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n        {\n            if (PlaneArray == null || PlaneArray.Length == 0) return 0;\n            var h = PlaneArray[0].GetHashCode();\n            for (var i = 1; i < PlaneArray.Length; i++) HashCode.GetCombined(h, PlaneArray[i].GetHashCode());\n            return h;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n        {\n            if (PlaneArray == null || other.PlaneArray == null) return false;\n            for (var i = 0; i < PlaneArray.Length; i++) if (PlaneArray[i] != other.PlaneArray[i]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => PlaneArray != null\n                ? string.Format(CultureInfo.InvariantCulture, \"[{0}]\", string.Join(\",\", PlaneArray.Map(x => x.ToString())))\n                : \"[null]\"\n                ;\n\n        /// <summary>\n        /// Parses __type__ from a string created with __type__.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n        {\n            if (s == \"[null]\") return __type__.Invalid;\n            var planes = s.NestedBracketSplitLevelOne().Select(__plane2t__.Parse).ToArray();\n            return new __type__(planes);\n        }\n\n        #endregion\n\n        #region Transformation\n\n        public readonly __type__ Transformed(__trafo2t__ trafo)\n        {\n            int count = PlaneCount;\n            var hull = new __type__(new __plane2t__[count]);\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new __plane2t__(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n            return hull;\n        }\n\n        public readonly void TransformInto(__trafo2t__ trafo, ref __type__ hull)\n        {\n            int count = PlaneCount;\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new __plane2t__(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ Reversed()\n            => new __type__(PlaneArray.Map(p => p.Reversed));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void Reverse()\n            => PlaneArray.Apply(p => p.Reversed);\n\n        #endregion\n    }\n\n    public static class __type__Extensions\n    {\n        /// <summary>\n        /// Creates an inward hull (i.e. a hull whose normal vectors point\n        /// inside) from a counter-clockwise enumerated array of polygon\n        /// points.\n        /// </summary>\n        public static __type__ ToInwardHull(this __v2t__[] polygon, int pointCount = 0)\n        {\n            if (pointCount == 0) pointCount = polygon.Length;\n            var planeArray = new __plane2t__[pointCount];\n            var p0 = polygon[pointCount - 1];\n            for (int i = 0; i < pointCount; i++)\n            {\n                var p1 = polygon[i];\n                planeArray[i] = new __plane2t__((p1 - p0).Rot90.Normalized, p0);\n                p0 = p1;\n            }\n            return new __type__(planeArray);\n        }\n\n        /// <summary>\n        /// Returns true if the supplied point is inside a hull with\n        /// planes whose normal vectors point to the inside of the hull.\n        /// The optional offset parameter is measured in normal direction,\n        /// i.e. a positive offset makes the hull smaller.\n        /// </summary>\n        public static bool IsInsideInwardHull(this __v2t__ point, __type__ hull, __ftype__ offset = 0)\n        {\n            for (int i = 0; i < hull.PlaneCount; i++)\n                if (hull.PlaneArray[i].Height(point) < offset) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns unordered set of corners of this hull.\n        /// </summary>\n        public static HashSet<__v2t__> ComputeCorners(this __type__ hull)\n        {\n            var corners = new HashSet<__v2t__>();\n            int count = hull.PlaneArray.Length;\n            for (var i0 = 0; i0 < count; i0++)\n            {\n                for (var i1 = i0 + 1; i1 < count; i1++)\n                {\n                    if (hull.PlaneArray[i0].Intersects(hull.PlaneArray[i1], out __v2t__ temp))\n                    {\n                        if (temp.IsNaN || temp.AnyInfinity) continue;\n\n                        var inside = true;\n                        for (var j = 0; j < count; j++)\n                        {\n                            if (j == i0 || j == i1) continue;\n                            var h = hull.PlaneArray[j].Height(temp);\n                            if (h > 0) { inside = false; break; }\n                        }\n\n                        if (inside)\n                        {\n                            corners.Add(temp);\n                        }\n                    }\n                }\n            }\n\n            return corners;\n        }\n    }\n\n    #endregion\n\n    //# }\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Hull/Hull3_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    public static class Hull\n    {\n        #region Flags32\n\n        [Flags]\n        public enum Flags32\n        {\n            None = 0x00000000,\n            Plane00 = 0x00000001,\n            Plane01 = 0x00000002,\n            Plane02 = 0x00000004,\n            Plane03 = 0x00000008,\n            Plane04 = 0x00000010,\n            Plane05 = 0x00000020,\n            Plane06 = 0x00000040,\n            Plane07 = 0x00000080,\n            Plane08 = 0x00000100,\n            Plane09 = 0x00000200,\n            Plane10 = 0x00000400,\n            Plane11 = 0x00000800,\n            Plane12 = 0x00001000,\n            Plane13 = 0x00002000,\n            Plane14 = 0x00004000,\n            Plane15 = 0x00008000,\n            Plane16 = 0x00010000,\n            Plane17 = 0x00020000,\n            Plane18 = 0x00040000,\n            Plane19 = 0x00080000,\n            Plane20 = 0x00100000,\n            Plane21 = 0x00200000,\n            Plane22 = 0x00400000,\n            Plane23 = 0x00800000,\n            Plane24 = 0x01000000,\n            Plane25 = 0x02000000,\n            Plane26 = 0x04000000,\n            Plane27 = 0x08000000,\n            Plane28 = 0x10000000,\n            Plane29 = 0x20000000,\n            Plane30 = 0x40000000,\n            Plane31 = (int)-0x80000000,\n        }\n\n        public static Flags32 OrPlane(this Flags32 flags, int i)\n        {\n            return flags | (Flags32)((int)flags | (int)Flags32.Plane00 << i);\n        }\n        public static Flags32 AndNotPlane(this Flags32 flags, int i)\n        {\n            return flags & (Flags32)~((int)flags | (int)Flags32.Plane00 << i);\n        }\n\n        #endregion\n    }\n\n    #region Hull3f\n\n    /// <summary>\n    /// A hull is a set of planes that bounds a convex polyhedron.\n    /// Normals are expected to point outside.\n    /// </summary>\n    public partial struct Hull3f : IEquatable<Hull3f>, IValidity\n    {\n        public Plane3f[] PlaneArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create an empty Hull3f with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3f(int count)\n        {\n            PlaneArray = new Plane3f[count];\n        }\n\n        /// <summary>\n        /// Creates a Hull3f from the given planes.\n        /// The plane normals are expected to point outside.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3f(Plane3f[] planes)\n        {\n            PlaneArray = planes;\n        }\n\n        /// <summary>\n        /// Creates a Hull3f from the given box where plane normals point outside.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3f(Box3f box)\n        {\n            PlaneArray = new[]\n            {\n                new Plane3f(-V3f.XAxis, box.Min),\n                new Plane3f(-V3f.YAxis, box.Min),\n                new Plane3f(-V3f.ZAxis, box.Min),\n                new Plane3f(V3f.XAxis, box.Max),\n                new Plane3f(V3f.YAxis, box.Max),\n                new Plane3f(V3f.ZAxis, box.Max)\n            };\n        }\n\n        /// <summary>\n        /// Creates a Hull3f from another Hull3f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3f(Hull3f hull)\n        {\n            PlaneArray = hull.PlaneArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3f(Hull3d hull)\n        {\n            PlaneArray = hull.PlaneArray.Map(p => new Plane3f(p));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Hull3f(Hull3d h)\n            => new Hull3f(h);\n\n        #endregion\n\n        #region Constants\n\n        public static Hull3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Hull3f(null);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray != null;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray == null;\n        }\n\n        public readonly int PlaneCount\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray.Length;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Hull3f a, Hull3f b)\n            => a.Equals(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Hull3f a, Hull3f b)\n            => !a.Equals(b);\n\n        #endregion\n\n        #region Override\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n        {\n            if (PlaneArray == null || PlaneArray.Length == 0) return 0;\n            var h = PlaneArray[0].GetHashCode();\n            for (var i = 1; i < PlaneArray.Length; i++) HashCode.GetCombined(h, PlaneArray[i].GetHashCode());\n            return h;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Hull3f other)\n        {\n            if (PlaneArray == null || other.PlaneArray == null) return false;\n            for (var i = 0; i < PlaneArray.Length; i++) if (PlaneArray[i] != other.PlaneArray[i]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Hull3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => PlaneArray != null\n                ? string.Format(CultureInfo.InvariantCulture, \"[{0}]\", string.Join(\",\", PlaneArray.Map(x => x.ToString())))\n                : \"[null]\"\n                ;\n\n        /// <summary>\n        /// Parses Hull3f from a string created with Hull3f.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Hull3f Parse(string s)\n        {\n            if (s == \"[null]\") return Hull3f.Invalid;\n            var planes = s.NestedBracketSplitLevelOne().Select(Plane3f.Parse).ToArray();\n            return new Hull3f(planes);\n        }\n\n        #endregion\n\n        #region Transformation\n\n        public readonly Hull3f Transformed(Trafo3f trafo)\n        {\n            int count = PlaneCount;\n            var hull = new Hull3f(count);\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new Plane3f(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n            return hull;\n        }\n\n        public readonly void TransformInto(Trafo3f trafo, ref Hull3f hull)\n        {\n            int count = PlaneCount;\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new Plane3f(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n        }\n\n        #endregion\n\n        #region Reversal\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Hull3f Reversed()\n            => new Hull3f(PlaneArray.Map(p => p.Reversed));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void Reverse()\n            => PlaneArray.Apply(p => p.Reversed);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A fast hull is a set of planes bounding a convex polyhedron,\n    /// that can be quickly tested against intersection of an axis-\n    /// aligned bounding box.\n    /// </summary>\n    public struct FastHull3f\n    {\n        public Hull3f Hull;\n        public int[] MinCornerIndexArray;\n\n        #region Constructor\n\n        /// <summary>\n        /// Create an empty FastHull3f with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastHull3f(int count)\n        {\n            Hull = new Hull3f(count);\n            MinCornerIndexArray = new int[count];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastHull3f(FastHull3f fastHull)\n        {\n            Hull = new Hull3f(fastHull.Hull);\n            MinCornerIndexArray = fastHull.MinCornerIndexArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastHull3f(Hull3f hull)\n        {\n            Hull = hull;\n            MinCornerIndexArray = ComputeMinCornerIndexArray(Hull.PlaneArray);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastHull3f(FastHull3d fastHull)\n        {\n            Hull = new Hull3f(fastHull.Hull);\n            MinCornerIndexArray = fastHull.MinCornerIndexArray.Copy();\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator FastHull3f(FastHull3d h)\n            => new FastHull3f(h);\n\n        #endregion\n\n        #region Private Helper Methods\n\n        private static int[] ComputeMinCornerIndexArray(Plane3f[] planeArray)\n        {\n            int count = planeArray.Length;\n            var minCornerIndices = new int[count];\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCorner = 0;\n\n                if (planeArray[pi].Normal.X < 0) minCorner |= 1;\n                if (planeArray[pi].Normal.Y < 0) minCorner |= 2;\n                if (planeArray[pi].Normal.Z < 0) minCorner |= 4;\n\n                minCornerIndices[pi] = minCorner;\n            }\n            return minCornerIndices;\n        }\n\n        private static void ComputeMinCornerIndexArrayInto(\n            Plane3f[] planeArray, int[] minCornerIndexArray)\n        {\n            int count = planeArray.Length;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCorner = 0;\n\n                if (planeArray[pi].Normal.X < 0) minCorner |= 1;\n                if (planeArray[pi].Normal.Y < 0) minCorner |= 2;\n                if (planeArray[pi].Normal.Z < 0) minCorner |= 4;\n\n                minCornerIndexArray[pi] = minCorner;\n            }\n        }\n\n        #endregion\n\n        #region Intersection Methods\n\n        /// <summary>\n        /// Test hull against intersection of the supplied bounding box\n        /// specified by an array of its eight corner vertices, that must\n        /// be ordered as returned by the <see pref=\"corners\"/>\n        /// call of the axis aligned bounding box. The avaibility of this\n        /// corner array slightly improves the performance of the test.\n        /// Note that this is a conservative test, since in some cases\n        /// around the edges of the hull it may return true although the\n        /// hull does not intersect the box.\n        /// </summary>\n        public readonly bool IntersectsAxisAlignedBox(\n                V3f[] corners)\n        {\n            var planes = Hull.PlaneArray;\n            int count = planes.Length;\n            bool intersecting = false;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCornerIndex = MinCornerIndexArray[pi];\n                if (planes[pi].Height(corners[minCornerIndex]) > 0)\n                    return false;\n                if (planes[pi].Height(corners[minCornerIndex ^ 7]) >= 0)\n                    intersecting = true;\n            }\n            if (intersecting) return true;\n            return true;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly FastHull3f Transformed(Trafo3f trafo)\n        {\n            var newFastHull = new FastHull3f()\n            {\n                Hull = this.Hull.Transformed(trafo)\n            };\n            newFastHull.MinCornerIndexArray =\n                ComputeMinCornerIndexArray(newFastHull.Hull.PlaneArray);\n            return newFastHull;\n        }\n\n        public readonly void TransformInto(Trafo3f trafo, ref FastHull3f fastHull)\n        {\n            Hull.TransformInto(trafo, ref fastHull.Hull);\n            ComputeMinCornerIndexArrayInto(fastHull.Hull.PlaneArray,\n                                        fastHull.MinCornerIndexArray);\n        }\n\n        #endregion\n    }\n\n    public static class Hull3fExtensions\n    {\n        /// <summary>\n         /// Returns unordered set of corners of this hull.\n         /// </summary>\n        public static HashSet<V3f> ComputeCorners(this Hull3f hull)\n        {\n            var corners = new HashSet<V3f>();\n            int count = hull.PlaneArray.Length;\n            for (var i0 = 0; i0 < count; i0++)\n            {\n                for (var i1 = i0 + 1; i1 < count; i1++)\n                {\n                    for (var i2 = i1 + 1; i2 < count; i2++)\n                    {\n                        if (hull.PlaneArray[i0].Intersects(hull.PlaneArray[i1], hull.PlaneArray[i2], out V3f temp))\n                        {\n                            if (temp.IsNaN || temp.AnyInfinity) continue;\n\n                            var inside = true;\n                            for (var j = 0; j < count; j++)\n                            {\n                                if (j == i0 || j == i1 || j == i2) continue;\n                                var h = hull.PlaneArray[j].Height(temp);\n                                if (h > 0) { inside = false; break; }\n                            }\n\n                            if (inside)\n                            {\n                                corners.Add(temp);\n                            }\n                        }\n                    }\n                }\n            }\n\n            return corners;\n        }\n    }\n\n    #endregion\n\n    #region Hull3d\n\n    /// <summary>\n    /// A hull is a set of planes that bounds a convex polyhedron.\n    /// Normals are expected to point outside.\n    /// </summary>\n    public partial struct Hull3d : IEquatable<Hull3d>, IValidity\n    {\n        public Plane3d[] PlaneArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create an empty Hull3d with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3d(int count)\n        {\n            PlaneArray = new Plane3d[count];\n        }\n\n        /// <summary>\n        /// Creates a Hull3d from the given planes.\n        /// The plane normals are expected to point outside.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3d(Plane3d[] planes)\n        {\n            PlaneArray = planes;\n        }\n\n        /// <summary>\n        /// Creates a Hull3d from the given box where plane normals point outside.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3d(Box3d box)\n        {\n            PlaneArray = new[]\n            {\n                new Plane3d(-V3d.XAxis, box.Min),\n                new Plane3d(-V3d.YAxis, box.Min),\n                new Plane3d(-V3d.ZAxis, box.Min),\n                new Plane3d(V3d.XAxis, box.Max),\n                new Plane3d(V3d.YAxis, box.Max),\n                new Plane3d(V3d.ZAxis, box.Max)\n            };\n        }\n\n        /// <summary>\n        /// Creates a Hull3d from another Hull3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3d(Hull3d hull)\n        {\n            PlaneArray = hull.PlaneArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Hull3d(Hull3f hull)\n        {\n            PlaneArray = hull.PlaneArray.Map(p => new Plane3d(p));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Hull3d(Hull3f h)\n            => new Hull3d(h);\n\n        #endregion\n\n        #region Constants\n\n        public static Hull3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Hull3d(null);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray != null;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray == null;\n        }\n\n        public readonly int PlaneCount\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray.Length;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Hull3d a, Hull3d b)\n            => a.Equals(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Hull3d a, Hull3d b)\n            => !a.Equals(b);\n\n        #endregion\n\n        #region Override\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n        {\n            if (PlaneArray == null || PlaneArray.Length == 0) return 0;\n            var h = PlaneArray[0].GetHashCode();\n            for (var i = 1; i < PlaneArray.Length; i++) HashCode.GetCombined(h, PlaneArray[i].GetHashCode());\n            return h;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Hull3d other)\n        {\n            if (PlaneArray == null || other.PlaneArray == null) return false;\n            for (var i = 0; i < PlaneArray.Length; i++) if (PlaneArray[i] != other.PlaneArray[i]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Hull3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => PlaneArray != null\n                ? string.Format(CultureInfo.InvariantCulture, \"[{0}]\", string.Join(\",\", PlaneArray.Map(x => x.ToString())))\n                : \"[null]\"\n                ;\n\n        /// <summary>\n        /// Parses Hull3d from a string created with Hull3d.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Hull3d Parse(string s)\n        {\n            if (s == \"[null]\") return Hull3d.Invalid;\n            var planes = s.NestedBracketSplitLevelOne().Select(Plane3d.Parse).ToArray();\n            return new Hull3d(planes);\n        }\n\n        #endregion\n\n        #region Transformation\n\n        public readonly Hull3d Transformed(Trafo3d trafo)\n        {\n            int count = PlaneCount;\n            var hull = new Hull3d(count);\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new Plane3d(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n            return hull;\n        }\n\n        public readonly void TransformInto(Trafo3d trafo, ref Hull3d hull)\n        {\n            int count = PlaneCount;\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new Plane3d(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n        }\n\n        #endregion\n\n        #region Reversal\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Hull3d Reversed()\n            => new Hull3d(PlaneArray.Map(p => p.Reversed));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void Reverse()\n            => PlaneArray.Apply(p => p.Reversed);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A fast hull is a set of planes bounding a convex polyhedron,\n    /// that can be quickly tested against intersection of an axis-\n    /// aligned bounding box.\n    /// </summary>\n    public struct FastHull3d\n    {\n        public Hull3d Hull;\n        public int[] MinCornerIndexArray;\n\n        #region Constructor\n\n        /// <summary>\n        /// Create an empty FastHull3d with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastHull3d(int count)\n        {\n            Hull = new Hull3d(count);\n            MinCornerIndexArray = new int[count];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastHull3d(FastHull3d fastHull)\n        {\n            Hull = new Hull3d(fastHull.Hull);\n            MinCornerIndexArray = fastHull.MinCornerIndexArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastHull3d(Hull3d hull)\n        {\n            Hull = hull;\n            MinCornerIndexArray = ComputeMinCornerIndexArray(Hull.PlaneArray);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastHull3d(FastHull3f fastHull)\n        {\n            Hull = new Hull3d(fastHull.Hull);\n            MinCornerIndexArray = fastHull.MinCornerIndexArray.Copy();\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator FastHull3d(FastHull3f h)\n            => new FastHull3d(h);\n\n        #endregion\n\n        #region Private Helper Methods\n\n        private static int[] ComputeMinCornerIndexArray(Plane3d[] planeArray)\n        {\n            int count = planeArray.Length;\n            var minCornerIndices = new int[count];\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCorner = 0;\n\n                if (planeArray[pi].Normal.X < 0) minCorner |= 1;\n                if (planeArray[pi].Normal.Y < 0) minCorner |= 2;\n                if (planeArray[pi].Normal.Z < 0) minCorner |= 4;\n\n                minCornerIndices[pi] = minCorner;\n            }\n            return minCornerIndices;\n        }\n\n        private static void ComputeMinCornerIndexArrayInto(\n            Plane3d[] planeArray, int[] minCornerIndexArray)\n        {\n            int count = planeArray.Length;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCorner = 0;\n\n                if (planeArray[pi].Normal.X < 0) minCorner |= 1;\n                if (planeArray[pi].Normal.Y < 0) minCorner |= 2;\n                if (planeArray[pi].Normal.Z < 0) minCorner |= 4;\n\n                minCornerIndexArray[pi] = minCorner;\n            }\n        }\n\n        #endregion\n\n        #region Intersection Methods\n\n        /// <summary>\n        /// Test hull against intersection of the supplied bounding box\n        /// specified by an array of its eight corner vertices, that must\n        /// be ordered as returned by the <see pref=\"corners\"/>\n        /// call of the axis aligned bounding box. The avaibility of this\n        /// corner array slightly improves the performance of the test.\n        /// Note that this is a conservative test, since in some cases\n        /// around the edges of the hull it may return true although the\n        /// hull does not intersect the box.\n        /// </summary>\n        public readonly bool IntersectsAxisAlignedBox(\n                V3d[] corners)\n        {\n            var planes = Hull.PlaneArray;\n            int count = planes.Length;\n            bool intersecting = false;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCornerIndex = MinCornerIndexArray[pi];\n                if (planes[pi].Height(corners[minCornerIndex]) > 0)\n                    return false;\n                if (planes[pi].Height(corners[minCornerIndex ^ 7]) >= 0)\n                    intersecting = true;\n            }\n            if (intersecting) return true;\n            return true;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly FastHull3d Transformed(Trafo3d trafo)\n        {\n            var newFastHull = new FastHull3d()\n            {\n                Hull = this.Hull.Transformed(trafo)\n            };\n            newFastHull.MinCornerIndexArray =\n                ComputeMinCornerIndexArray(newFastHull.Hull.PlaneArray);\n            return newFastHull;\n        }\n\n        public readonly void TransformInto(Trafo3d trafo, ref FastHull3d fastHull)\n        {\n            Hull.TransformInto(trafo, ref fastHull.Hull);\n            ComputeMinCornerIndexArrayInto(fastHull.Hull.PlaneArray,\n                                        fastHull.MinCornerIndexArray);\n        }\n\n        #endregion\n    }\n\n    public static class Hull3dExtensions\n    {\n        /// <summary>\n         /// Returns unordered set of corners of this hull.\n         /// </summary>\n        public static HashSet<V3d> ComputeCorners(this Hull3d hull)\n        {\n            var corners = new HashSet<V3d>();\n            int count = hull.PlaneArray.Length;\n            for (var i0 = 0; i0 < count; i0++)\n            {\n                for (var i1 = i0 + 1; i1 < count; i1++)\n                {\n                    for (var i2 = i1 + 1; i2 < count; i2++)\n                    {\n                        if (hull.PlaneArray[i0].Intersects(hull.PlaneArray[i1], hull.PlaneArray[i2], out V3d temp))\n                        {\n                            if (temp.IsNaN || temp.AnyInfinity) continue;\n\n                            var inside = true;\n                            for (var j = 0; j < count; j++)\n                            {\n                                if (j == i0 || j == i1 || j == i2) continue;\n                                var h = hull.PlaneArray[j].Height(temp);\n                                if (h > 0) { inside = false; break; }\n                            }\n\n                            if (inside)\n                            {\n                                corners.Add(temp);\n                            }\n                        }\n                    }\n                }\n            }\n\n            return corners;\n        }\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Hull/Hull3_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    public static class Hull\n    {\n        #region Flags32\n\n        [Flags]\n        public enum Flags32\n        {\n            None = 0x00000000,\n            Plane00 = 0x00000001,\n            Plane01 = 0x00000002,\n            Plane02 = 0x00000004,\n            Plane03 = 0x00000008,\n            Plane04 = 0x00000010,\n            Plane05 = 0x00000020,\n            Plane06 = 0x00000040,\n            Plane07 = 0x00000080,\n            Plane08 = 0x00000100,\n            Plane09 = 0x00000200,\n            Plane10 = 0x00000400,\n            Plane11 = 0x00000800,\n            Plane12 = 0x00001000,\n            Plane13 = 0x00002000,\n            Plane14 = 0x00004000,\n            Plane15 = 0x00008000,\n            Plane16 = 0x00010000,\n            Plane17 = 0x00020000,\n            Plane18 = 0x00040000,\n            Plane19 = 0x00080000,\n            Plane20 = 0x00100000,\n            Plane21 = 0x00200000,\n            Plane22 = 0x00400000,\n            Plane23 = 0x00800000,\n            Plane24 = 0x01000000,\n            Plane25 = 0x02000000,\n            Plane26 = 0x04000000,\n            Plane27 = 0x08000000,\n            Plane28 = 0x10000000,\n            Plane29 = 0x20000000,\n            Plane30 = 0x40000000,\n            Plane31 = (int)-0x80000000,\n        }\n\n        public static Flags32 OrPlane(this Flags32 flags, int i)\n        {\n            return flags | (Flags32)((int)flags | (int)Flags32.Plane00 << i);\n        }\n        public static Flags32 AndNotPlane(this Flags32 flags, int i)\n        {\n            return flags & (Flags32)~((int)flags | (int)Flags32.Plane00 << i);\n        }\n\n        #endregion\n    }\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Hull3\" + tc;\n    //#   var type2 = \"Hull3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var trafo3t = \"Trafo3\" + tc;\n    //#   var iboundingbox = \"IBoundingBox3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var dotnine = isDouble ? \"0.9\" : \"0.9f\";\n    //#   var constant = isDouble ? \"Constant\" : \"ConstantF\";\n    #region __type__\n\n    /// <summary>\n    /// A hull is a set of planes that bounds a convex polyhedron.\n    /// Normals are expected to point outside.\n    /// </summary>\n    public partial struct __type__ : IEquatable<__type__>, IValidity\n    {\n        public __plane3t__[] PlaneArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create an empty __type__ with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(int count)\n        {\n            PlaneArray = new __plane3t__[count];\n        }\n\n        /// <summary>\n        /// Creates a __type__ from the given planes.\n        /// The plane normals are expected to point outside.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__plane3t__[] planes)\n        {\n            PlaneArray = planes;\n        }\n\n        /// <summary>\n        /// Creates a __type__ from the given box where plane normals point outside.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__box3t__ box)\n        {\n            PlaneArray = new[]\n            {\n                new __plane3t__(-__v3t__.XAxis, box.Min),\n                new __plane3t__(-__v3t__.YAxis, box.Min),\n                new __plane3t__(-__v3t__.ZAxis, box.Min),\n                new __plane3t__(__v3t__.XAxis, box.Max),\n                new __plane3t__(__v3t__.YAxis, box.Max),\n                new __plane3t__(__v3t__.ZAxis, box.Max)\n            };\n        }\n\n        /// <summary>\n        /// Creates a __type__ from another __type__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ hull)\n        {\n            PlaneArray = hull.PlaneArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ hull)\n        {\n            PlaneArray = hull.PlaneArray.Map(p => new __plane3t__(p));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ h)\n            => new __type__(h);\n\n        #endregion\n\n        #region Constants\n\n        public static __type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(null);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray != null;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray == null;\n        }\n\n        public readonly int PlaneCount\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => PlaneArray.Length;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => a.Equals(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !a.Equals(b);\n\n        #endregion\n\n        #region Override\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n        {\n            if (PlaneArray == null || PlaneArray.Length == 0) return 0;\n            var h = PlaneArray[0].GetHashCode();\n            for (var i = 1; i < PlaneArray.Length; i++) HashCode.GetCombined(h, PlaneArray[i].GetHashCode());\n            return h;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n        {\n            if (PlaneArray == null || other.PlaneArray == null) return false;\n            for (var i = 0; i < PlaneArray.Length; i++) if (PlaneArray[i] != other.PlaneArray[i]) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => PlaneArray != null\n                ? string.Format(CultureInfo.InvariantCulture, \"[{0}]\", string.Join(\",\", PlaneArray.Map(x => x.ToString())))\n                : \"[null]\"\n                ;\n\n        /// <summary>\n        /// Parses __type__ from a string created with __type__.ToString().\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n        {\n            if (s == \"[null]\") return __type__.Invalid;\n            var planes = s.NestedBracketSplitLevelOne().Select(__plane3t__.Parse).ToArray();\n            return new __type__(planes);\n        }\n\n        #endregion\n\n        #region Transformation\n\n        public readonly __type__ Transformed(__trafo3t__ trafo)\n        {\n            int count = PlaneCount;\n            var hull = new __type__(count);\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new __plane3t__(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n            return hull;\n        }\n\n        public readonly void TransformInto(__trafo3t__ trafo, ref __type__ hull)\n        {\n            int count = PlaneCount;\n            var invTr = trafo.Backward.Transposed;\n            for (int i = 0; i < count; i++)\n                hull.PlaneArray[i]\n                    = new __plane3t__(\n                            invTr.TransformDir(PlaneArray[i].Normal).Normalized,\n                            trafo.Forward.TransformPos(PlaneArray[i].Point));\n        }\n\n        #endregion\n\n        #region Reversal\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ Reversed()\n            => new __type__(PlaneArray.Map(p => p.Reversed));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void Reverse()\n            => PlaneArray.Apply(p => p.Reversed);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A fast hull is a set of planes bounding a convex polyhedron,\n    /// that can be quickly tested against intersection of an axis-\n    /// aligned bounding box.\n    /// </summary>\n    public struct Fast__type__\n    {\n        public __type__ Hull;\n        public int[] MinCornerIndexArray;\n\n        #region Constructor\n\n        /// <summary>\n        /// Create an empty Fast__type__ with count planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fast__type__(int count)\n        {\n            Hull = new __type__(count);\n            MinCornerIndexArray = new int[count];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fast__type__(Fast__type__ fastHull)\n        {\n            Hull = new __type__(fastHull.Hull);\n            MinCornerIndexArray = fastHull.MinCornerIndexArray.Copy();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fast__type__(__type__ hull)\n        {\n            Hull = hull;\n            MinCornerIndexArray = ComputeMinCornerIndexArray(Hull.PlaneArray);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fast__type__(Fast__type2__ fastHull)\n        {\n            Hull = new __type__(fastHull.Hull);\n            MinCornerIndexArray = fastHull.MinCornerIndexArray.Copy();\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Fast__type__(Fast__type2__ h)\n            => new Fast__type__(h);\n\n        #endregion\n\n        #region Private Helper Methods\n\n        private static int[] ComputeMinCornerIndexArray(__plane3t__[] planeArray)\n        {\n            int count = planeArray.Length;\n            var minCornerIndices = new int[count];\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCorner = 0;\n\n                if (planeArray[pi].Normal.X < 0) minCorner |= 1;\n                if (planeArray[pi].Normal.Y < 0) minCorner |= 2;\n                if (planeArray[pi].Normal.Z < 0) minCorner |= 4;\n\n                minCornerIndices[pi] = minCorner;\n            }\n            return minCornerIndices;\n        }\n\n        private static void ComputeMinCornerIndexArrayInto(\n            __plane3t__[] planeArray, int[] minCornerIndexArray)\n        {\n            int count = planeArray.Length;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCorner = 0;\n\n                if (planeArray[pi].Normal.X < 0) minCorner |= 1;\n                if (planeArray[pi].Normal.Y < 0) minCorner |= 2;\n                if (planeArray[pi].Normal.Z < 0) minCorner |= 4;\n\n                minCornerIndexArray[pi] = minCorner;\n            }\n        }\n\n        #endregion\n\n        #region Intersection Methods\n\n        /// <summary>\n        /// Test hull against intersection of the supplied bounding box\n        /// specified by an array of its eight corner vertices, that must\n        /// be ordered as returned by the <see pref=\"corners\"/>\n        /// call of the axis aligned bounding box. The avaibility of this\n        /// corner array slightly improves the performance of the test.\n        /// Note that this is a conservative test, since in some cases\n        /// around the edges of the hull it may return true although the\n        /// hull does not intersect the box.\n        /// </summary>\n        public readonly bool IntersectsAxisAlignedBox(\n                __v3t__[] corners)\n        {\n            var planes = Hull.PlaneArray;\n            int count = planes.Length;\n            bool intersecting = false;\n            for (int pi = 0; pi < count; pi++)\n            {\n                int minCornerIndex = MinCornerIndexArray[pi];\n                if (planes[pi].Height(corners[minCornerIndex]) > 0)\n                    return false;\n                if (planes[pi].Height(corners[minCornerIndex ^ 7]) >= 0)\n                    intersecting = true;\n            }\n            if (intersecting) return true;\n            return true;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        public readonly Fast__type__ Transformed(__trafo3t__ trafo)\n        {\n            var newFastHull = new Fast__type__()\n            {\n                Hull = this.Hull.Transformed(trafo)\n            };\n            newFastHull.MinCornerIndexArray =\n                ComputeMinCornerIndexArray(newFastHull.Hull.PlaneArray);\n            return newFastHull;\n        }\n\n        public readonly void TransformInto(__trafo3t__ trafo, ref Fast__type__ fastHull)\n        {\n            Hull.TransformInto(trafo, ref fastHull.Hull);\n            ComputeMinCornerIndexArrayInto(fastHull.Hull.PlaneArray,\n                                        fastHull.MinCornerIndexArray);\n        }\n\n        #endregion\n    }\n\n    public static class __type__Extensions\n    {\n        /// <summary>\n         /// Returns unordered set of corners of this hull.\n         /// </summary>\n        public static HashSet<__v3t__> ComputeCorners(this __type__ hull)\n        {\n            var corners = new HashSet<__v3t__>();\n            int count = hull.PlaneArray.Length;\n            for (var i0 = 0; i0 < count; i0++)\n            {\n                for (var i1 = i0 + 1; i1 < count; i1++)\n                {\n                    for (var i2 = i1 + 1; i2 < count; i2++)\n                    {\n                        if (hull.PlaneArray[i0].Intersects(hull.PlaneArray[i1], hull.PlaneArray[i2], out __v3t__ temp))\n                        {\n                            if (temp.IsNaN || temp.AnyInfinity) continue;\n\n                            var inside = true;\n                            for (var j = 0; j < count; j++)\n                            {\n                                if (j == i0 || j == i1 || j == i2) continue;\n                                var h = hull.PlaneArray[j].Height(temp);\n                                if (h > 0) { inside = false; break; }\n                            }\n\n                            if (inside)\n                            {\n                                corners.Add(temp);\n                            }\n                        }\n                    }\n                }\n            }\n\n            return corners;\n        }\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Line/Line2_auto.cs",
    "content": "using System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Line2f\n\n    /// <summary>\n    /// A two dimensional line with specified start and end points.\n    /// </summary>\n    public partial struct Line2f : IBoundingCircle2f\n    {\n        #region Geometric Properties\n\n        public readonly V2f Center => (P0 + P1) * 0.5f;\n\n        /// <summary>\n        /// P0\n        /// </summary>\n        [XmlIgnore]\n        public V2f Origin\n        {\n            readonly get { return P0; }\n            set { P0 = value; }\n        }\n\n        /// <summary>\n        /// P1 - P0\n        /// </summary>\n        [XmlIgnore]\n        public V2f Direction\n        {\n            readonly get { return P1 - P0; }\n            set { P1 = P0 + value; }\n        }\n\n        public readonly Ray2f Ray2f => new Ray2f(P0, P1 - P0);\n\n        public readonly Plane2f Plane2f => Ray2f.Plane2f;\n\n        public readonly float LeftValueOfDir(V2f v) => v.X * (P0.Y - P1.Y) + v.Y * (P1.X - P0.X);\n\n        public readonly float RightValueOfDir(V2f v) => v.X * (P1.Y - P0.Y) + v.Y * (P0.X - P1.X);\n\n        public readonly float LeftValueOfPos(V2f p)\n            => (p.X - P0.X) * (P0.Y - P1.Y) + (p.Y - P0.Y) * (P1.X - P0.X);\n\n        public readonly float RightValueOfPos(V2f p)\n            => (p.X - P0.X) * (P1.Y - P0.Y) + (p.Y - P0.Y) * (P0.X - P1.X);\n\n        public readonly bool IsDegenerated => Direction.AllTiny;\n\n        #endregion\n\n        #region IBoundingCircle2f Members\n\n        public readonly Circle2f BoundingCircle2f => new Circle2f(Center, 0.5f * Direction.Length);\n\n        #endregion\n\n        #region Geometric Computations\n\n        public readonly V2f GetClosestPointOnLine(V2f p)\n        {\n            var d = P0 - P1;\n            var l = d.LengthSquared;\n            if(Fun.IsTiny(l))\n                return P0; //it does not matter which of the two points we choose\n            var t = (P0.Dot(d) - p.Dot(d)) / l; //parametric distance from P0 to P1, where closest point to p is\n            if (t <= 0)\n                return P0;\n            if (t >= 1)\n                return P1;\n            return P0 - t * d;\n        }\n\n        public readonly float GetDistanceToLine(V2f p)\n        {\n            var f = GetClosestPointOnLine(p);\n            return (f - p).Length;\n        }\n\n        public readonly bool IsDistanceToPointSmallerThan(V2f p, float maxDist)\n        {\n            //speed-up by first checking the bounding box\n            var box = BoundingBox2f;\n            box.EnlargeBy(maxDist);\n            if (!box.Contains(p))\n                return false;\n            return GetDistanceToLine(p) <= maxDist;\n        }\n\n        public readonly Line2f Flipped => new Line2f(P1, P0);\n\n        #endregion\n\n        /// <summary>\n        /// Returns true if points a, b and c are exactly collinear.\n        /// </summary>\n        public static bool IsCollinear(V2f a, V2f b, V2f c)\n            => (b.Y - a.Y) * (c.X - b.X) == (c.Y - b.Y) * (b.X - a.X);\n\n        /// <summary>\n        /// Returns true if points a, b and c are collinear within eps.\n        /// </summary>\n        public static bool IsCollinear(V2f a, V2f b, V2f c, float eps = 1e-5f)\n            => Fun.ApproximateEquals((b.Y - a.Y) * (c.X - b.X), (c.Y - b.Y) * (b.X - a.X), eps);\n    }\n\n    #endregion\n\n    #region Line2d\n\n    /// <summary>\n    /// A two dimensional line with specified start and end points.\n    /// </summary>\n    public partial struct Line2d : IBoundingCircle2d\n    {\n        #region Geometric Properties\n\n        public readonly V2d Center => (P0 + P1) * 0.5;\n\n        /// <summary>\n        /// P0\n        /// </summary>\n        [XmlIgnore]\n        public V2d Origin\n        {\n            readonly get { return P0; }\n            set { P0 = value; }\n        }\n\n        /// <summary>\n        /// P1 - P0\n        /// </summary>\n        [XmlIgnore]\n        public V2d Direction\n        {\n            readonly get { return P1 - P0; }\n            set { P1 = P0 + value; }\n        }\n\n        public readonly Ray2d Ray2d => new Ray2d(P0, P1 - P0);\n\n        public readonly Plane2d Plane2d => Ray2d.Plane2d;\n\n        public readonly double LeftValueOfDir(V2d v) => v.X * (P0.Y - P1.Y) + v.Y * (P1.X - P0.X);\n\n        public readonly double RightValueOfDir(V2d v) => v.X * (P1.Y - P0.Y) + v.Y * (P0.X - P1.X);\n\n        public readonly double LeftValueOfPos(V2d p)\n            => (p.X - P0.X) * (P0.Y - P1.Y) + (p.Y - P0.Y) * (P1.X - P0.X);\n\n        public readonly double RightValueOfPos(V2d p)\n            => (p.X - P0.X) * (P1.Y - P0.Y) + (p.Y - P0.Y) * (P0.X - P1.X);\n\n        public readonly bool IsDegenerated => Direction.AllTiny;\n\n        #endregion\n\n        #region IBoundingCircle2d Members\n\n        public readonly Circle2d BoundingCircle2d => new Circle2d(Center, 0.5 * Direction.Length);\n\n        #endregion\n\n        #region Geometric Computations\n\n        public readonly V2d GetClosestPointOnLine(V2d p)\n        {\n            var d = P0 - P1;\n            var l = d.LengthSquared;\n            if(Fun.IsTiny(l))\n                return P0; //it does not matter which of the two points we choose\n            var t = (P0.Dot(d) - p.Dot(d)) / l; //parametric distance from P0 to P1, where closest point to p is\n            if (t <= 0)\n                return P0;\n            if (t >= 1)\n                return P1;\n            return P0 - t * d;\n        }\n\n        public readonly double GetDistanceToLine(V2d p)\n        {\n            var f = GetClosestPointOnLine(p);\n            return (f - p).Length;\n        }\n\n        public readonly bool IsDistanceToPointSmallerThan(V2d p, double maxDist)\n        {\n            //speed-up by first checking the bounding box\n            var box = BoundingBox2d;\n            box.EnlargeBy(maxDist);\n            if (!box.Contains(p))\n                return false;\n            return GetDistanceToLine(p) <= maxDist;\n        }\n\n        public readonly Line2d Flipped => new Line2d(P1, P0);\n\n        #endregion\n\n        /// <summary>\n        /// Returns true if points a, b and c are exactly collinear.\n        /// </summary>\n        public static bool IsCollinear(V2d a, V2d b, V2d c)\n            => (b.Y - a.Y) * (c.X - b.X) == (c.Y - b.Y) * (b.X - a.X);\n\n        /// <summary>\n        /// Returns true if points a, b and c are collinear within eps.\n        /// </summary>\n        public static bool IsCollinear(V2d a, V2d b, V2d c, double eps = 1e-9)\n            => Fun.ApproximateEquals((b.Y - a.Y) * (c.X - b.X), (c.Y - b.Y) * (b.X - a.X), eps);\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Line/Line2_template.cs",
    "content": "﻿using System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Line2\" + tc;\n    //#   var type2 = \"Line2\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var ray2t = \"Ray2\" + tc;\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var circle2t = \"Circle2\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var boundingbox2t = \"BoundingBox2\" + tc;\n    //#   var iboundingcircle = \"IBoundingCircle2\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var eps = isDouble ? \"1e-9\" : \"1e-5f\";\n    #region __type__\n\n    /// <summary>\n    /// A two dimensional line with specified start and end points.\n    /// </summary>\n    public partial struct __type__ : __iboundingcircle__\n    {\n        #region Geometric Properties\n\n        public readonly __v2t__ Center => (P0 + P1) * __half__;\n\n        /// <summary>\n        /// P0\n        /// </summary>\n        [XmlIgnore]\n        public __v2t__ Origin\n        {\n            readonly get { return P0; }\n            set { P0 = value; }\n        }\n\n        /// <summary>\n        /// P1 - P0\n        /// </summary>\n        [XmlIgnore]\n        public __v2t__ Direction\n        {\n            readonly get { return P1 - P0; }\n            set { P1 = P0 + value; }\n        }\n\n        public readonly __ray2t__ __ray2t__ => new __ray2t__(P0, P1 - P0);\n\n        public readonly __plane2t__ __plane2t__ => __ray2t__.__plane2t__;\n\n        public readonly __ftype__ LeftValueOfDir(__v2t__ v) => v.X * (P0.Y - P1.Y) + v.Y * (P1.X - P0.X);\n\n        public readonly __ftype__ RightValueOfDir(__v2t__ v) => v.X * (P1.Y - P0.Y) + v.Y * (P0.X - P1.X);\n\n        public readonly __ftype__ LeftValueOfPos(__v2t__ p)\n            => (p.X - P0.X) * (P0.Y - P1.Y) + (p.Y - P0.Y) * (P1.X - P0.X);\n\n        public readonly __ftype__ RightValueOfPos(__v2t__ p)\n            => (p.X - P0.X) * (P1.Y - P0.Y) + (p.Y - P0.Y) * (P0.X - P1.X);\n\n        public readonly bool IsDegenerated => Direction.AllTiny;\n\n        #endregion\n\n        #region __iboundingcircle__ Members\n\n        public readonly __circle2t__ BoundingCircle2__tc__ => new __circle2t__(Center, __half__ * Direction.Length);\n\n        #endregion\n\n        #region Geometric Computations\n\n        public readonly __v2t__ GetClosestPointOnLine(__v2t__ p)\n        {\n            var d = P0 - P1;\n            var l = d.LengthSquared;\n            if(Fun.IsTiny(l))\n                return P0; //it does not matter which of the two points we choose\n            var t = (P0.Dot(d) - p.Dot(d)) / l; //parametric distance from P0 to P1, where closest point to p is\n            if (t <= 0)\n                return P0;\n            if (t >= 1)\n                return P1;\n            return P0 - t * d;\n        }\n\n        public readonly __ftype__ GetDistanceToLine(__v2t__ p)\n        {\n            var f = GetClosestPointOnLine(p);\n            return (f - p).Length;\n        }\n\n        public readonly bool IsDistanceToPointSmallerThan(__v2t__ p, __ftype__ maxDist)\n        {\n            //speed-up by first checking the bounding box\n            var box = __boundingbox2t__;\n            box.EnlargeBy(maxDist);\n            if (!box.Contains(p))\n                return false;\n            return GetDistanceToLine(p) <= maxDist;\n        }\n\n        public readonly __type__ Flipped => new __type__(P1, P0);\n\n        #endregion\n\n        /// <summary>\n        /// Returns true if points a, b and c are exactly collinear.\n        /// </summary>\n        public static bool IsCollinear(__v2t__ a, __v2t__ b, __v2t__ c)\n            => (b.Y - a.Y) * (c.X - b.X) == (c.Y - b.Y) * (b.X - a.X);\n\n        /// <summary>\n        /// Returns true if points a, b and c are collinear within eps.\n        /// </summary>\n        public static bool IsCollinear(__v2t__ a, __v2t__ b, __v2t__ c, __ftype__ eps = __eps__)\n            => Fun.ApproximateEquals((b.Y - a.Y) * (c.X - b.X), (c.Y - b.Y) * (b.X - a.X), eps);\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Line/Line3_auto.cs",
    "content": "using System;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Line3f\n\n    /// <summary>\n    /// A three-dimensional line with specified start and end points.\n    /// </summary>\n    [Serializable]\n    public partial struct Line3f : IBoundingSphere3f\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// P0\n        /// </summary>\n        [XmlIgnore]\n        public V3f Origin\n        {\n            readonly get { return P0; }\n            set { P0 = value; }\n        }\n\n        /// <summary>\n        /// P1 - P0\n        /// </summary>\n        [XmlIgnore]\n        public V3f Direction\n        {\n            readonly get { return P1 - P0; }\n            set { P1 = P0 + value; }\n        }\n\n        public readonly Ray3f Ray3f => new Ray3f(P0, P1 - P0);\n\n        public readonly bool IsDegenerated => !Direction.Abs().AnyGreater(Constant<float>.PositiveTinyValue);\n\n        #endregion\n\n        #region IBoundingSphere3f Members\n\n        public readonly Sphere3f BoundingSphere3f => new Sphere3f(this.ComputeCentroid(), 0.5f * Direction.Length);\n\n        #endregion\n\n        public readonly Line3f Flipped => new Line3f(P1, P0);\n    }\n\n    #endregion\n\n    #region Line3d\n\n    /// <summary>\n    /// A three-dimensional line with specified start and end points.\n    /// </summary>\n    [Serializable]\n    public partial struct Line3d : IBoundingSphere3d\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// P0\n        /// </summary>\n        [XmlIgnore]\n        public V3d Origin\n        {\n            readonly get { return P0; }\n            set { P0 = value; }\n        }\n\n        /// <summary>\n        /// P1 - P0\n        /// </summary>\n        [XmlIgnore]\n        public V3d Direction\n        {\n            readonly get { return P1 - P0; }\n            set { P1 = P0 + value; }\n        }\n\n        public readonly Ray3d Ray3d => new Ray3d(P0, P1 - P0);\n\n        public readonly bool IsDegenerated => !Direction.Abs().AnyGreater(Constant<double>.PositiveTinyValue);\n\n        #endregion\n\n        #region IBoundingSphere3d Members\n\n        public readonly Sphere3d BoundingSphere3d => new Sphere3d(this.ComputeCentroid(), 0.5 * Direction.Length);\n\n        #endregion\n\n        public readonly Line3d Flipped => new Line3d(P1, P0);\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Line/Line3_template.cs",
    "content": "﻿using System;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Line3\" + tc;\n    //#   var type2 = \"Line3\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var ray3t = \"Ray3\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var sphere3t = \"Sphere3\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var boundingbox3t = \"BoundingBox3\" + tc;\n    //#   var iboundingsphere = \"IBoundingSphere3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var eps = isDouble ? \"1e-9\" : \"1e-5f\";\n    #region __type__\n\n    /// <summary>\n    /// A three-dimensional line with specified start and end points.\n    /// </summary>\n    [Serializable]\n    public partial struct __type__ : __iboundingsphere__\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// P0\n        /// </summary>\n        [XmlIgnore]\n        public __v3t__ Origin\n        {\n            readonly get { return P0; }\n            set { P0 = value; }\n        }\n\n        /// <summary>\n        /// P1 - P0\n        /// </summary>\n        [XmlIgnore]\n        public __v3t__ Direction\n        {\n            readonly get { return P1 - P0; }\n            set { P1 = P0 + value; }\n        }\n\n        public readonly __ray3t__ __ray3t__ => new __ray3t__(P0, P1 - P0);\n\n        public readonly bool IsDegenerated => !Direction.Abs().AnyGreater(Constant<__ftype__>.PositiveTinyValue);\n\n        #endregion\n\n        #region __iboundingsphere__ Members\n\n        public readonly __sphere3t__ BoundingSphere3__tc__ => new __sphere3t__(this.ComputeCentroid(), __half__ * Direction.Length);\n\n        #endregion\n\n        public readonly __type__ Flipped => new __type__(P1, P0);\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Line1iPoint.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// Represents a value at an interpolated point between two indexed\n    /// values of an indexable set of values. This is implemented as a\n    /// class in order to avoid duplicating interpolated points in some\n    /// algorithms.\n    /// </summary>\n    public class Line1iPoint\n    {\n        public readonly Line1i Line;\n        public readonly double T;\n\n        #region Constructor\n\n        public Line1iPoint(\n            int i0, int i1, double t)\n        {\n            Line.I0 = i0; Line.I1 = i1; T = t;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Plane/Plane2_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Plane2f\n\n    /// <summary>\n    /// A line represented by a (possibly) normalized normal vector and the\n    /// distance to the origin. Note that the plane does not enforce the\n    /// normalized normal vector.\n    /// Equation for points p on the plane: Normal dot p == Distance\n    /// </summary>\n    public partial struct Plane2f : IEquatable<Plane2f>, IValidity // should be InfiniteLine2d\n    {\n        public V2f Normal;\n        public float Distance;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and constant. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane2f(V2f normalizedNormal, float distance)\n        {\n            Normal = normalizedNormal;\n            Distance = distance;\n        }\n\n        /// <summary>\n        /// Creates plane from point and normal vector. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane2f(V2f normalizedNormal, V2f point)\n        {\n            Normal = normalizedNormal;\n            Distance = Vec.Dot(normalizedNormal, point);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane2f\"/> from another <see cref=\"Plane2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane2f(Plane2f o)\n        {\n            Normal = o.Normal;\n            Distance = o.Distance;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane2f\"/> from a <see cref=\"Plane2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane2f(Plane2d o)\n        {\n            Normal = (V2f)o.Normal;\n            Distance = (float)o.Distance;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Plane2f(Plane2d o)\n            => new Plane2f(o);\n\n        #endregion\n\n        #region Constants\n\n        public static Plane2f XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2f(V2f.OI, 0);\n        }\n\n        public static Plane2f YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2f(-V2f.IO, 0);\n        }\n\n        public static Plane2f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2f(V2f.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// The point on the plane which is closest to the origin.\n        /// </summary>\n        [XmlIgnore]\n        public V2f Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Normal * Distance; }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Distance = Vec.Dot(Normal, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is not the zero-vector.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != V2f.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is the zero-vector.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == V2f.Zero;\n        }\n\n        /// <summary>\n        /// Returns a Plane3f whose cutting-line with the XY-Plane\n        /// is represented by the Plane2f\n        /// </summary>\n        public readonly Plane3f PlaneXY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(Normal.XYO, Distance);\n        }\n\n        /// <summary>\n        /// Returns a Plane3f whose cutting-line with the XZ-Plane\n        /// is represented by the Plane2f\n        /// </summary>\n        public readonly Plane3f PlaneXZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(Normal.XOY, Distance);\n        }\n\n        /// <summary>\n        /// Returns a Plane3f whose cutting-line with the YZ-Plane\n        /// is represented by the Plane2f\n        /// </summary>\n        public readonly Plane3f PlaneYZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(Normal.OXY, Distance);\n        }\n\n        #endregion\n\n        #region Plane Arithmetics\n\n        /// <summary>\n        /// Returns the normalized <see cref=\"Plane2f\"/> as new <see cref=\"Plane2f\"/>.\n        /// </summary>\n        public readonly Plane2f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                float scale = Normal.Length;\n                return new Plane2f(Normal / scale, Distance / scale);\n            }\n        }\n\n        /// <summary>\n        /// Calculates the nomalized plane of this <see cref=\"Plane2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize()\n        {\n            float scale =  Normal.Length;\n            Normal /= scale;\n            Distance /= scale;\n        }\n\n        /// <summary>\n        /// Changes sign of normal vector\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse()\n        {\n            Normal = -Normal;\n            Distance = -Distance;\n        }\n\n        /// <summary>\n        /// Returns <see cref=\"Plane2f\"/> with normal vector in opposing direction.\n        /// </summary>\n        /// <returns></returns>\n        public readonly Plane2f Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2f(-Normal, -Distance);\n        }\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// IMPORTANT: If the plane is not normalized the returned height is scaled with the magnitued of the plane normal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float Height(V2f p) => Vec.Dot(Normal, p) - Distance;\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(V2f p) => Height(p).Sign();\n\n        /// <summary>\n        /// Projets the given point x perpendicular on the plane\n        /// and returns the nearest point on the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f NearestPoint(V2f x)\n        {\n            var p = Point;\n            return (x - Normal.Dot(x - p) * Normal);\n        }\n\n        /// <summary>\n        /// Returns the coefficients (a, b, c, d) of the normal equation.\n        /// </summary>\n        public readonly V3f Coefficients\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3f(Normal, -Distance);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Plane2f a, Plane2f b)\n            => (a.Normal == b.Normal) && (a.Distance == b.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Plane2f a, Plane2f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Plane2f other)\n            => Normal.Equals(other.Normal) && Distance.Equals(other.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Plane2f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString() =>\n            string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Plane2f(V2f.Parse(x[0]), float.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Plane2f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Plane2f a, Plane2f b, float tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Distance, b.Distance, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Plane2f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Plane2f a, Plane2f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Plane2d\n\n    /// <summary>\n    /// A line represented by a (possibly) normalized normal vector and the\n    /// distance to the origin. Note that the plane does not enforce the\n    /// normalized normal vector.\n    /// Equation for points p on the plane: Normal dot p == Distance\n    /// </summary>\n    public partial struct Plane2d : IEquatable<Plane2d>, IValidity // should be InfiniteLine2d\n    {\n        public V2d Normal;\n        public double Distance;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and constant. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane2d(V2d normalizedNormal, double distance)\n        {\n            Normal = normalizedNormal;\n            Distance = distance;\n        }\n\n        /// <summary>\n        /// Creates plane from point and normal vector. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane2d(V2d normalizedNormal, V2d point)\n        {\n            Normal = normalizedNormal;\n            Distance = Vec.Dot(normalizedNormal, point);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane2d\"/> from another <see cref=\"Plane2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane2d(Plane2d o)\n        {\n            Normal = o.Normal;\n            Distance = o.Distance;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane2d\"/> from a <see cref=\"Plane2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane2d(Plane2f o)\n        {\n            Normal = (V2d)o.Normal;\n            Distance = (double)o.Distance;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Plane2d(Plane2f o)\n            => new Plane2d(o);\n\n        #endregion\n\n        #region Constants\n\n        public static Plane2d XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2d(V2d.OI, 0);\n        }\n\n        public static Plane2d YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2d(-V2d.IO, 0);\n        }\n\n        public static Plane2d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2d(V2d.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// The point on the plane which is closest to the origin.\n        /// </summary>\n        [XmlIgnore]\n        public V2d Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Normal * Distance; }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Distance = Vec.Dot(Normal, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is not the zero-vector.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != V2d.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is the zero-vector.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == V2d.Zero;\n        }\n\n        /// <summary>\n        /// Returns a Plane3d whose cutting-line with the XY-Plane\n        /// is represented by the Plane2d\n        /// </summary>\n        public readonly Plane3d PlaneXY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(Normal.XYO, Distance);\n        }\n\n        /// <summary>\n        /// Returns a Plane3d whose cutting-line with the XZ-Plane\n        /// is represented by the Plane2d\n        /// </summary>\n        public readonly Plane3d PlaneXZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(Normal.XOY, Distance);\n        }\n\n        /// <summary>\n        /// Returns a Plane3d whose cutting-line with the YZ-Plane\n        /// is represented by the Plane2d\n        /// </summary>\n        public readonly Plane3d PlaneYZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(Normal.OXY, Distance);\n        }\n\n        #endregion\n\n        #region Plane Arithmetics\n\n        /// <summary>\n        /// Returns the normalized <see cref=\"Plane2d\"/> as new <see cref=\"Plane2d\"/>.\n        /// </summary>\n        public readonly Plane2d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                double scale = Normal.Length;\n                return new Plane2d(Normal / scale, Distance / scale);\n            }\n        }\n\n        /// <summary>\n        /// Calculates the nomalized plane of this <see cref=\"Plane2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize()\n        {\n            double scale =  Normal.Length;\n            Normal /= scale;\n            Distance /= scale;\n        }\n\n        /// <summary>\n        /// Changes sign of normal vector\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse()\n        {\n            Normal = -Normal;\n            Distance = -Distance;\n        }\n\n        /// <summary>\n        /// Returns <see cref=\"Plane2d\"/> with normal vector in opposing direction.\n        /// </summary>\n        /// <returns></returns>\n        public readonly Plane2d Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2d(-Normal, -Distance);\n        }\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// IMPORTANT: If the plane is not normalized the returned height is scaled with the magnitued of the plane normal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Height(V2d p) => Vec.Dot(Normal, p) - Distance;\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(V2d p) => Height(p).Sign();\n\n        /// <summary>\n        /// Projets the given point x perpendicular on the plane\n        /// and returns the nearest point on the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d NearestPoint(V2d x)\n        {\n            var p = Point;\n            return (x - Normal.Dot(x - p) * Normal);\n        }\n\n        /// <summary>\n        /// Returns the coefficients (a, b, c, d) of the normal equation.\n        /// </summary>\n        public readonly V3d Coefficients\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3d(Normal, -Distance);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Plane2d a, Plane2d b)\n            => (a.Normal == b.Normal) && (a.Distance == b.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Plane2d a, Plane2d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Plane2d other)\n            => Normal.Equals(other.Normal) && Distance.Equals(other.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Plane2d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString() =>\n            string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Plane2d(V2d.Parse(x[0]), double.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Plane2d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Plane2d a, Plane2d b, double tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Distance, b.Distance, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Plane2d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Plane2d a, Plane2d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Plane/Plane2_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var plane2t2 = \"Plane2\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    #region __plane2t__\n\n    /// <summary>\n    /// A line represented by a (possibly) normalized normal vector and the\n    /// distance to the origin. Note that the plane does not enforce the\n    /// normalized normal vector.\n    /// Equation for points p on the plane: Normal dot p == Distance\n    /// </summary>\n    public partial struct __plane2t__ : IEquatable<__plane2t__>, IValidity // should be InfiniteLine2d\n    {\n        public __v2t__ Normal;\n        public __ftype__ Distance;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and constant. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane2t__(__v2t__ normalizedNormal, __ftype__ distance)\n        {\n            Normal = normalizedNormal;\n            Distance = distance;\n        }\n\n        /// <summary>\n        /// Creates plane from point and normal vector. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane2t__(__v2t__ normalizedNormal, __v2t__ point)\n        {\n            Normal = normalizedNormal;\n            Distance = Vec.Dot(normalizedNormal, point);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__plane2t__\"/> from another <see cref=\"__plane2t__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane2t__(__plane2t__ o)\n        {\n            Normal = o.Normal;\n            Distance = o.Distance;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__plane2t__\"/> from a <see cref=\"__plane2t2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane2t__(__plane2t2__ o)\n        {\n            Normal = (__v2t__)o.Normal;\n            Distance = (__ftype__)o.Distance;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __plane2t__(__plane2t2__ o)\n            => new __plane2t__(o);\n\n        #endregion\n\n        #region Constants\n\n        public static __plane2t__ XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane2t__(__v2t__.OI, 0);\n        }\n\n        public static __plane2t__ YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane2t__(-__v2t__.IO, 0);\n        }\n\n        public static __plane2t__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane2t__(__v2t__.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// The point on the plane which is closest to the origin.\n        /// </summary>\n        [XmlIgnore]\n        public __v2t__ Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Normal * Distance; }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Distance = Vec.Dot(Normal, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is not the zero-vector.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != __v2t__.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is the zero-vector.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == __v2t__.Zero;\n        }\n\n        /// <summary>\n        /// Returns a __plane3t__ whose cutting-line with the XY-Plane\n        /// is represented by the __plane2t__\n        /// </summary>\n        public readonly __plane3t__ PlaneXY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(Normal.XYO, Distance);\n        }\n\n        /// <summary>\n        /// Returns a __plane3t__ whose cutting-line with the XZ-Plane\n        /// is represented by the __plane2t__\n        /// </summary>\n        public readonly __plane3t__ PlaneXZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(Normal.XOY, Distance);\n        }\n\n        /// <summary>\n        /// Returns a __plane3t__ whose cutting-line with the YZ-Plane\n        /// is represented by the __plane2t__\n        /// </summary>\n        public readonly __plane3t__ PlaneYZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(Normal.OXY, Distance);\n        }\n\n        #endregion\n\n        #region Plane Arithmetics\n\n        /// <summary>\n        /// Returns the normalized <see cref=\"__plane2t__\"/> as new <see cref=\"__plane2t__\"/>.\n        /// </summary>\n        public readonly __plane2t__ Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                __ftype__ scale = Normal.Length;\n                return new __plane2t__(Normal / scale, Distance / scale);\n            }\n        }\n\n        /// <summary>\n        /// Calculates the nomalized plane of this <see cref=\"__plane2t__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize()\n        {\n            __ftype__ scale =  Normal.Length;\n            Normal /= scale;\n            Distance /= scale;\n        }\n\n        /// <summary>\n        /// Changes sign of normal vector\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse()\n        {\n            Normal = -Normal;\n            Distance = -Distance;\n        }\n\n        /// <summary>\n        /// Returns <see cref=\"__plane2t__\"/> with normal vector in opposing direction.\n        /// </summary>\n        /// <returns></returns>\n        public readonly __plane2t__ Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane2t__(-Normal, -Distance);\n        }\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// IMPORTANT: If the plane is not normalized the returned height is scaled with the magnitued of the plane normal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ Height(__v2t__ p) => Vec.Dot(Normal, p) - Distance;\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(__v2t__ p) => Height(p).Sign();\n\n        /// <summary>\n        /// Projets the given point x perpendicular on the plane\n        /// and returns the nearest point on the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __v2t__ NearestPoint(__v2t__ x)\n        {\n            var p = Point;\n            return (x - Normal.Dot(x - p) * Normal);\n        }\n\n        /// <summary>\n        /// Returns the coefficients (a, b, c, d) of the normal equation.\n        /// </summary>\n        public readonly __v3t__ Coefficients\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __v3t__(Normal, -Distance);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__plane2t__ a, __plane2t__ b)\n            => (a.Normal == b.Normal) && (a.Distance == b.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__plane2t__ a, __plane2t__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__plane2t__ other)\n            => Normal.Equals(other.Normal) && Distance.Equals(other.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __plane2t__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString() =>\n            string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __plane2t__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __plane2t__(__v2t__.Parse(x[0]), __ftype__.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__plane2t__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __plane2t__ a, __plane2t__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Distance, b.Distance, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__plane2t__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __plane2t__ a, __plane2t__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Plane/Plane3_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Plane3f\n\n    /// <summary>\n    /// A plane represented by a (possibly) normalized normal vector and the\n    /// distance to the origin. Note that the plane does not enforce the\n    /// normalized normal vector.\n    /// Equation for points p on the plane: Normal dot p == Distance\n    /// </summary>\n    public partial struct Plane3f : IEquatable<Plane3f>, IValidity, IBoundingBox3f\n    {\n        /// <summary>\n        /// Plane normal.\n        /// </summary>\n        public V3f Normal;\n\n        /// <summary>\n        /// Distance from origin to plane.\n        /// </summary>\n        public float Distance;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and distance to origin.\n        /// IMPORTANT: The normal has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3f(V3f normalizedNormal, float distance)\n        {\n            Normal = normalizedNormal;\n            Distance = distance;\n        }\n\n        /// <summary>\n        /// Creates plane from normal vector and point.\n        /// IMPORTANT: The normal has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3f(V3f normalizedNormal, V3f point)\n        {\n            Normal = normalizedNormal;\n            Distance = Vec.Dot(normalizedNormal, point);\n        }\n\n        /// <summary>\n        /// Creates a plane from 3 independent points.\n        /// A normalized normal vector is computed and stored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3f(V3f p0, V3f p1, V3f p2)\n        {\n            Normal = Vec.Cross(p1 - p0, p2 - p0).Normalized;\n            Distance = Vec.Dot(Normal, p0);\n        }\n\n        /// <summary>\n        /// Create a plane from coefficients (a, b, c, d) of the normal equation: ax + by + cz + d = 0\n        /// Normal = [a, b, c]; Distance = -d\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3f(V4f coefficients)\n        {\n            Normal = coefficients.XYZ;\n            Distance = -coefficients.W;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane3f\"/> from another <see cref=\"Plane3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3f(Plane3f o)\n        {\n            Normal = o.Normal;\n            Distance = o.Distance;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane3f\"/> from a <see cref=\"Plane3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3f(Plane3d o)\n        {\n            Normal = (V3f)o.Normal;\n            Distance = (float)o.Distance;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Plane3f(Plane3d o)\n            => new Plane3f(o);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Plane3f(PlaneWithPoint3f o)\n            => new Plane3f(o.Normal, o.Point);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>YZ plane.</summary>\n        public static Plane3f XPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(V3f.XAxis, V3f.Zero);\n        }\n\n        /// <summary>XZ plane.</summary>\n        public static Plane3f YPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(V3f.YAxis, V3f.Zero);\n        }\n\n        /// <summary>XY plane.</summary>\n        public static Plane3f ZPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(V3f.ZAxis, V3f.Zero);\n        }\n\n        /// <summary>Invalid plane.</summary>\n        public static Plane3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(V3f.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// The point on the plane which is closest to the origin.\n        /// </summary>\n        [XmlIgnore]\n        public V3f Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Normal * Distance / Normal.LengthSquared; }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Distance = Vec.Dot(Normal, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is not the zero-vector.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != V3f.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is the zero-vector.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == V3f.Zero;\n        }\n\n        /// <summary>\n        /// Returns the normalized <see cref=\"Plane3f\"/> as new <see cref=\"Plane3f\"/>.\n        /// </summary>\n        public readonly Plane3f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                float scale = Normal.Length;\n                return new Plane3f(Normal / scale, Distance / scale);\n            }\n        }\n\n        /// <summary>\n        /// Returns the coefficients (a, b, c, d) of the normal equation: ax + by + cz + d = 0\n        /// </summary>\n        public readonly V4f Coefficients\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4f(Normal, -Distance);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        /// <summary>\n        /// Normalizes this <see cref=\"Plane3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize()\n        {\n            float scale = Normal.Length;\n            Normal /= scale;\n            Distance /= scale;\n        }\n\n        /// <summary>\n        /// Changes sign of normal vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse()\n        {\n            Normal = -Normal;\n            Distance = -Distance;\n        }\n\n        /// <summary>\n        /// Returns <see cref=\"Plane3f\"/> with normal vector in opposing direction.\n        /// </summary>\n        public readonly Plane3f Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(-Normal, -Distance);\n        }\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// IMPORTANT: If the plane is not normalized the returned height is scaled by the magnitued of the plane normal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float Height(V3f p)\n            => Vec.Dot(Normal, p) - Distance;\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(V3f p) => Height(p).Sign();\n\n        /// <summary>\n        /// Projets the given point x perpendicular on the plane\n        /// and returns the nearest point on the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f NearestPoint(V3f x)\n        {\n            var p = Point;\n            return (x - Normal.Dot(x - p) * Normal);\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given trafo using the inverse\n        /// transposed matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Plane3f Transformed(Trafo3f trafo)\n        {\n            return new Plane3f(\n                new V3f(\n                    trafo.Backward.M00 * Normal.X + trafo.Backward.M10 * Normal.Y + trafo.Backward.M20 * Normal.Z - trafo.Backward.M30 * Distance,\n                    trafo.Backward.M01 * Normal.X + trafo.Backward.M11 * Normal.Y + trafo.Backward.M21 * Normal.Z - trafo.Backward.M31 * Distance,\n                    trafo.Backward.M02 * Normal.X + trafo.Backward.M12 * Normal.Y + trafo.Backward.M22 * Normal.Z - trafo.Backward.M32 * Distance\n                ),\n                trafo.Backward.M33 * Distance - trafo.Backward.M03 * Normal.X - trafo.Backward.M13 * Normal.Y - trafo.Backward.M23 * Normal.Z\n            );\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given matrix. The matrix is assumed\n        /// to represent a euclidean transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Plane3f Transformed(M44f trafo)\n        {\n            var n = trafo.TransformDir(Normal);\n            var d = Distance + trafo.C0.Dot(trafo.C3) * Normal.X + trafo.C1.Dot(trafo.C3) * Normal.Y + trafo.C2.Dot(trafo.C3) * Normal.Z;\n            return new Plane3f(n, d);\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given Euclidean3f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Plane3f Transformed(Euclidean3f trafo)\n        {\n            var n1 = trafo.TransformDir(Normal);\n            return new Plane3f(n1, Distance + trafo.Trans.Dot(n1));\n        }\n\n        #endregion\n\n        #region Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Plane3f a, Plane3f b)\n            => a.Normal == b.Normal && a.Distance == b.Distance;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Plane3f a, Plane3f b)\n            => a.Normal != b.Normal || a.Distance != b.Distance;\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Plane3f other)\n            => Normal.Equals(other.Normal) && Distance.Equals(other.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Plane3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString() =>\n            string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Plane3f(V3f.Parse(x[0]), float.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        /// <summary>\n        /// Gets entire float space as bounding box.\n        /// </summary>\n        public readonly Box3f BoundingBox3f\n        {\n            get\n            {\n                var box = new Box3f(V3f.MinValue, V3f.MaxValue);\n\n                if (Normal == V3f.XAxis)\n                {\n                    box.Min.X = Distance; box.Max.X = Distance; return box;\n                }\n                if (Normal == V3f.YAxis)\n                {\n                    box.Min.Y = Distance; box.Max.Y = Distance; return box;\n                }\n                if (Normal == V3f.ZAxis)\n                {\n                    box.Min.Z = Distance; box.Max.Z = Distance; return box;\n                }\n\n                return box;\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Plane3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Plane3f a, Plane3f b, float tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Distance, b.Distance, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Plane3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Plane3f a, Plane3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region PlaneWithPoint3f\n\n    /// <summary>\n    /// A plane with a specific point that can be retrieved later.\n    /// </summary>\n    public struct PlaneWithPoint3f : IBoundingBox3f\n    {\n        public V3f Normal;\n        public V3f Point;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and point. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneWithPoint3f(V3f normalizedNormal, V3f point)\n        {\n            Normal = normalizedNormal;\n            Point = point;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane3f\"/> from another <see cref=\"Plane3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneWithPoint3f(PlaneWithPoint3f o)\n        {\n            Normal = o.Normal;\n            Point = o.Point;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane3f\"/> from a <see cref=\"Plane3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneWithPoint3f(PlaneWithPoint3d o)\n        {\n            Normal = (V3f)o.Normal;\n            Point = (V3f)o.Point;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator PlaneWithPoint3f(PlaneWithPoint3d o)\n            => new PlaneWithPoint3f(o);\n\n        #endregion\n\n        #region Constants\n\n        public static PlaneWithPoint3f XPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3f(V3f.XAxis, V3f.Zero);\n        }\n\n        public static PlaneWithPoint3f YPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3f(V3f.YAxis, V3f.Zero);\n        }\n\n        public static PlaneWithPoint3f ZPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3f(V3f.ZAxis, V3f.Zero);\n        }\n\n        public static PlaneWithPoint3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3f(V3f.Zero, V3f.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly PlaneWithPoint3f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3f(Normal.Normalized, Point);\n        }\n\n        public readonly Plane3f Plane3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3f(Normal, Point);\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == V3f.Zero;\n        }\n\n        public readonly PlaneWithPoint3f Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3f(-Normal, Point);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize() => Normal.Normalize();\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse() => Normal = -Normal;\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float Height(V3f p) => Vec.Dot(Normal, p - Point);\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(V3f p) => Height(p).Sign();\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(PlaneWithPoint3f other)\n            => Normal.Equals(other.Normal) && Point.Equals(other.Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is PlaneWithPoint3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static PlaneWithPoint3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new PlaneWithPoint3f(V3f.Parse(x[0]), V3f.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        /// <summary>\n        /// Gets entire float space as bounding box.\n        /// </summary>\n        public readonly Box3f BoundingBox3f\n        {\n            get\n            {\n                var box = new Box3f(V3f.MinValue, V3f.MaxValue);\n\n                if (Normal == V3f.XAxis)\n                {\n                    box.Min.X = Point.X; box.Max.X = Point.X; return box;\n                }\n                if (Normal == V3f.YAxis)\n                {\n                    box.Min.Y = Point.Y; box.Max.Y = Point.Y; return box;\n                }\n                if (Normal == V3f.ZAxis)\n                {\n                    box.Min.Z = Point.Z; box.Max.Z = Point.Z; return box;\n                }\n\n                return box;\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"PlaneWithPoint3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this PlaneWithPoint3f a, PlaneWithPoint3f b, float tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Point, b.Point, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"PlaneWithPoint3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this PlaneWithPoint3f a, PlaneWithPoint3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region PlanePair3f\n\n    /// <summary>\n    /// A plane pair defines a ray at their intersection.\n    /// </summary>\n    public struct PlanePair3f\n    {\n        public Plane3f Plane0;\n        public Plane3f Plane1;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlanePair3f(Plane3f plane0, Plane3f plane1)\n        {\n            Plane0 = plane0; Plane1 = plane1;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"PlanePair3f\"/> from another <see cref=\"PlanePair3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlanePair3f(PlanePair3f o)\n        {\n            Plane0 = o.Plane0;\n            Plane1 = o.Plane1;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"PlanePair3f\"/> from a <see cref=\"PlanePair3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlanePair3f(PlanePair3d o)\n        {\n            Plane0 = (Plane3f)o.Plane0;\n            Plane1 = (Plane3f)o.Plane1;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator PlanePair3f(PlanePair3d o)\n            => new PlanePair3f(o);\n\n        #endregion\n\n        #region Arithmetics\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Ray3f GetRay3f()\n        {\n            Plane0.Intersects(Plane1, out Ray3f ray);\n            return ray;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region PlaneTriple3f\n\n    /// <summary>\n    /// A plane triple defines a point at their intersection.\n    /// </summary>\n    public struct PlaneTriple3f\n    {\n        public Plane3f Plane0;\n        public Plane3f Plane1;\n        public Plane3f Plane2;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneTriple3f(Plane3f plane0, Plane3f plane1, Plane3f plane2)\n        {\n            Plane0 = plane0; Plane1 = plane1; Plane2 = plane2;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"PlaneTriple3f\"/> from another <see cref=\"PlaneTriple3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneTriple3f(PlaneTriple3f o)\n        {\n            Plane0 = o.Plane0;\n            Plane1 = o.Plane1;\n            Plane2 = o.Plane2;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"PlaneTriple3f\"/> from a <see cref=\"PlaneTriple3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneTriple3f(PlaneTriple3d o)\n        {\n            Plane0 = (Plane3f)o.Plane0;\n            Plane1 = (Plane3f)o.Plane1;\n            Plane2 = (Plane3f)o.Plane2;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator PlaneTriple3f(PlaneTriple3d o)\n            => new PlaneTriple3f(o);\n\n        #endregion\n\n        #region Properties\n\n        public readonly PlanePair3f Pair01\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3f(Plane0, Plane1);\n        }\n\n        public readonly PlanePair3f Pair02\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3f(Plane0, Plane2);\n        }\n\n        public readonly PlanePair3f Pair12\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3f(Plane1, Plane2);\n        }\n\n        public readonly PlanePair3f Pair10\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3f(Plane1, Plane0);\n        }\n\n        public readonly PlanePair3f Pair20\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3f(Plane2, Plane0);\n        }\n\n        public readonly PlanePair3f Pair21\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3f(Plane2, Plane1);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        public readonly V3f GetPoint()\n        {\n            Plane0.Intersects(Plane1, Plane2, out V3f point);\n            return point;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Plane3fExtensions\n\n    public static class Plane3fExtensions\n    {\n        /// <summary>\n        /// Returns a transformation of an orthonormal basis in Plane- to WorldSpace.\n        /// </summary>\n        public static Trafo3f GetPlaneSpaceTransform(this Plane3f self)\n            => Trafo3f.FromNormalFrame(self.Point, self.Normal);\n\n        /// <summary>\n        /// 3D world space to 2D plane space.\n        /// Plane space is defined by a normal-frame from Point and Normal of the plane.\n        /// </summary>\n        public static M44f GetWorldToPlane(this Plane3f self)\n        {\n            M44f.NormalFrame(self.Point, self.Normal, out M44f _, out M44f global2local);\n            return global2local;\n        }\n\n        /// <summary>\n        /// 2D plane space to 3D world space.\n        /// Plane space is defined by a normal-frame from Point and Normal of the plane.\n        /// </summary>\n        public static M44f GetPlaneToWorld(this Plane3f self)\n        {\n            M44f.NormalFrame(self.Point, self.Normal, out M44f local2global, out M44f _);\n            return local2global;\n        }\n\n        /// <summary>\n        /// Projects a point onto the plane (shortest distance).\n        /// </summary>\n        public static V3f Project(this Plane3f plane, V3f p) => p - plane.Height(p) * plane.Normal;\n\n        /// <summary>\n        /// Projects a point onto the plane along given direction.\n        /// </summary>\n        public static V3f Project(this Plane3f plane, V3f p, V3f direction)\n        {\n            var r = new Ray3f(p, direction);\n            if (r.Intersects(plane, out float t))\n            {\n                return r.GetPointOnRay(t);\n            }\n            else\n            {\n                throw new Exception(string.Format(\n                    \"Failed to project point {0} onto plane {1} along direction {2}.\", p, plane, direction)\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Projects points onto plane (shortest distance).\n        /// </summary>\n        public static V3f[] Project(this Plane3f plane, V3f[] pointArray, int startIndex = 0, int count = 0)\n        {\n            if (pointArray == null) throw new ArgumentNullException();\n            if (startIndex < 0 || startIndex >= pointArray.Length) throw new ArgumentOutOfRangeException();\n            if (count < 0) throw new ArgumentOutOfRangeException();\n            if (count == 0) count = pointArray.Length - startIndex;\n            if (count > pointArray.Length - startIndex) throw new ArgumentOutOfRangeException();\n\n            var normal = plane.Normal;\n            var result = new V3f[count];\n            for (int i = startIndex, j = 0; j < count; i++, j++)\n            {\n                var p = pointArray[i];\n                var height = plane.Height(p);\n                result[j] = p - height * normal;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Projects points onto plane along given direction.\n        /// </summary>\n        public static V3f[] Project(this Plane3f plane, V3f[] pointArray, V3f direction, int startIndex = 0, int count = 0)\n        {\n            if (pointArray == null) throw new ArgumentNullException();\n            if (startIndex < 0 || startIndex >= pointArray.Length) throw new ArgumentOutOfRangeException();\n            if (count < 0) throw new ArgumentOutOfRangeException();\n            if (count == 0) count = pointArray.Length - startIndex;\n            if (count > pointArray.Length - startIndex) throw new ArgumentOutOfRangeException();\n\n            var result = new V3f[count];\n            for (int i = startIndex, j = 0; j < count; i++, j++)\n            {\n                var r = new Ray3f(pointArray[i], direction);\n                if (r.Intersects(plane, out float t))\n                {\n                    result[j] = r.GetPointOnRay(t);\n                }\n                else\n                {\n                    throw new Exception(string.Format(\n                        \"Failed to project point {0} onto plane {1} along direction {2}.\", pointArray[i], plane, direction)\n                        );\n                }\n            };\n            return result;\n        }\n\n        /// <summary>\n        /// Projects a point from world space to plane space (shortest distance).\n        /// </summary>\n        public static V2f ProjectToPlaneSpace(this Plane3f plane, V3f p)\n            => plane.GetWorldToPlane().TransformPos(p).XY;\n\n        /// <summary>\n        /// Projects points from world space to plane space (shortest distance).\n        /// </summary>\n        public static V2f[] ProjectToPlaneSpace(this Plane3f plane, V3f[] points)\n        {\n            var global2local = plane.GetWorldToPlane();\n            return points.Map(p => global2local.TransformPos(p).XY);\n        }\n\n        /// <summary>\n        /// Transforms point from plane space to world space.\n        /// </summary>\n        public static V3f Unproject(this Plane3f plane, V2f point)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            return local2global.TransformPos(point.XYO);\n        }\n\n        /// <summary>\n        /// Transforms points from plane space to world space.\n        /// </summary>\n        public static V3f[] Unproject(this Plane3f plane, V2f[] points)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            return points.Map(p => local2global.TransformPos(p.XYO));\n        }\n\n        /// <summary>\n        /// Transforms points from plane space to world space.\n        /// </summary>\n        public static V3f[] Unproject(this Plane3f plane, IReadOnlyList<V2f> points)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            var xs = new V3f[points.Count];\n            for (var i = 0; i < points.Count; i++)\n                xs[i] = local2global.TransformPos(points[i].XYO);\n            return xs;\n        }\n    }\n\n    #endregion\n\n    #region Plane3d\n\n    /// <summary>\n    /// A plane represented by a (possibly) normalized normal vector and the\n    /// distance to the origin. Note that the plane does not enforce the\n    /// normalized normal vector.\n    /// Equation for points p on the plane: Normal dot p == Distance\n    /// </summary>\n    public partial struct Plane3d : IEquatable<Plane3d>, IValidity, IBoundingBox3d\n    {\n        /// <summary>\n        /// Plane normal.\n        /// </summary>\n        public V3d Normal;\n\n        /// <summary>\n        /// Distance from origin to plane.\n        /// </summary>\n        public double Distance;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and distance to origin.\n        /// IMPORTANT: The normal has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3d(V3d normalizedNormal, double distance)\n        {\n            Normal = normalizedNormal;\n            Distance = distance;\n        }\n\n        /// <summary>\n        /// Creates plane from normal vector and point.\n        /// IMPORTANT: The normal has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3d(V3d normalizedNormal, V3d point)\n        {\n            Normal = normalizedNormal;\n            Distance = Vec.Dot(normalizedNormal, point);\n        }\n\n        /// <summary>\n        /// Creates a plane from 3 independent points.\n        /// A normalized normal vector is computed and stored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3d(V3d p0, V3d p1, V3d p2)\n        {\n            Normal = Vec.Cross(p1 - p0, p2 - p0).Normalized;\n            Distance = Vec.Dot(Normal, p0);\n        }\n\n        /// <summary>\n        /// Create a plane from coefficients (a, b, c, d) of the normal equation: ax + by + cz + d = 0\n        /// Normal = [a, b, c]; Distance = -d\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3d(V4d coefficients)\n        {\n            Normal = coefficients.XYZ;\n            Distance = -coefficients.W;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane3d\"/> from another <see cref=\"Plane3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3d(Plane3d o)\n        {\n            Normal = o.Normal;\n            Distance = o.Distance;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane3d\"/> from a <see cref=\"Plane3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Plane3d(Plane3f o)\n        {\n            Normal = (V3d)o.Normal;\n            Distance = (double)o.Distance;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Plane3d(Plane3f o)\n            => new Plane3d(o);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Plane3d(PlaneWithPoint3d o)\n            => new Plane3d(o.Normal, o.Point);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>YZ plane.</summary>\n        public static Plane3d XPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(V3d.XAxis, V3d.Zero);\n        }\n\n        /// <summary>XZ plane.</summary>\n        public static Plane3d YPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(V3d.YAxis, V3d.Zero);\n        }\n\n        /// <summary>XY plane.</summary>\n        public static Plane3d ZPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(V3d.ZAxis, V3d.Zero);\n        }\n\n        /// <summary>Invalid plane.</summary>\n        public static Plane3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(V3d.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// The point on the plane which is closest to the origin.\n        /// </summary>\n        [XmlIgnore]\n        public V3d Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Normal * Distance / Normal.LengthSquared; }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Distance = Vec.Dot(Normal, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is not the zero-vector.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != V3d.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is the zero-vector.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == V3d.Zero;\n        }\n\n        /// <summary>\n        /// Returns the normalized <see cref=\"Plane3d\"/> as new <see cref=\"Plane3d\"/>.\n        /// </summary>\n        public readonly Plane3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                double scale = Normal.Length;\n                return new Plane3d(Normal / scale, Distance / scale);\n            }\n        }\n\n        /// <summary>\n        /// Returns the coefficients (a, b, c, d) of the normal equation: ax + by + cz + d = 0\n        /// </summary>\n        public readonly V4d Coefficients\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4d(Normal, -Distance);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        /// <summary>\n        /// Normalizes this <see cref=\"Plane3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize()\n        {\n            double scale = Normal.Length;\n            Normal /= scale;\n            Distance /= scale;\n        }\n\n        /// <summary>\n        /// Changes sign of normal vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse()\n        {\n            Normal = -Normal;\n            Distance = -Distance;\n        }\n\n        /// <summary>\n        /// Returns <see cref=\"Plane3d\"/> with normal vector in opposing direction.\n        /// </summary>\n        public readonly Plane3d Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(-Normal, -Distance);\n        }\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// IMPORTANT: If the plane is not normalized the returned height is scaled by the magnitued of the plane normal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Height(V3d p)\n            => Vec.Dot(Normal, p) - Distance;\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(V3d p) => Height(p).Sign();\n\n        /// <summary>\n        /// Projets the given point x perpendicular on the plane\n        /// and returns the nearest point on the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d NearestPoint(V3d x)\n        {\n            var p = Point;\n            return (x - Normal.Dot(x - p) * Normal);\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given trafo using the inverse\n        /// transposed matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Plane3d Transformed(Trafo3d trafo)\n        {\n            return new Plane3d(\n                new V3d(\n                    trafo.Backward.M00 * Normal.X + trafo.Backward.M10 * Normal.Y + trafo.Backward.M20 * Normal.Z - trafo.Backward.M30 * Distance,\n                    trafo.Backward.M01 * Normal.X + trafo.Backward.M11 * Normal.Y + trafo.Backward.M21 * Normal.Z - trafo.Backward.M31 * Distance,\n                    trafo.Backward.M02 * Normal.X + trafo.Backward.M12 * Normal.Y + trafo.Backward.M22 * Normal.Z - trafo.Backward.M32 * Distance\n                ),\n                trafo.Backward.M33 * Distance - trafo.Backward.M03 * Normal.X - trafo.Backward.M13 * Normal.Y - trafo.Backward.M23 * Normal.Z\n            );\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given matrix. The matrix is assumed\n        /// to represent a euclidean transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Plane3d Transformed(M44d trafo)\n        {\n            var n = trafo.TransformDir(Normal);\n            var d = Distance + trafo.C0.Dot(trafo.C3) * Normal.X + trafo.C1.Dot(trafo.C3) * Normal.Y + trafo.C2.Dot(trafo.C3) * Normal.Z;\n            return new Plane3d(n, d);\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given Euclidean3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Plane3d Transformed(Euclidean3d trafo)\n        {\n            var n1 = trafo.TransformDir(Normal);\n            return new Plane3d(n1, Distance + trafo.Trans.Dot(n1));\n        }\n\n        #endregion\n\n        #region Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Plane3d a, Plane3d b)\n            => a.Normal == b.Normal && a.Distance == b.Distance;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Plane3d a, Plane3d b)\n            => a.Normal != b.Normal || a.Distance != b.Distance;\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Plane3d other)\n            => Normal.Equals(other.Normal) && Distance.Equals(other.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Plane3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString() =>\n            string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Plane3d(V3d.Parse(x[0]), double.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        /// <summary>\n        /// Gets entire double space as bounding box.\n        /// </summary>\n        public readonly Box3d BoundingBox3d\n        {\n            get\n            {\n                var box = new Box3d(V3d.MinValue, V3d.MaxValue);\n\n                if (Normal == V3d.XAxis)\n                {\n                    box.Min.X = Distance; box.Max.X = Distance; return box;\n                }\n                if (Normal == V3d.YAxis)\n                {\n                    box.Min.Y = Distance; box.Max.Y = Distance; return box;\n                }\n                if (Normal == V3d.ZAxis)\n                {\n                    box.Min.Z = Distance; box.Max.Z = Distance; return box;\n                }\n\n                return box;\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Plane3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Plane3d a, Plane3d b, double tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Distance, b.Distance, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Plane3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Plane3d a, Plane3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region PlaneWithPoint3d\n\n    /// <summary>\n    /// A plane with a specific point that can be retrieved later.\n    /// </summary>\n    public struct PlaneWithPoint3d : IBoundingBox3d\n    {\n        public V3d Normal;\n        public V3d Point;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and point. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneWithPoint3d(V3d normalizedNormal, V3d point)\n        {\n            Normal = normalizedNormal;\n            Point = point;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane3d\"/> from another <see cref=\"Plane3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneWithPoint3d(PlaneWithPoint3d o)\n        {\n            Normal = o.Normal;\n            Point = o.Point;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Plane3d\"/> from a <see cref=\"Plane3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneWithPoint3d(PlaneWithPoint3f o)\n        {\n            Normal = (V3d)o.Normal;\n            Point = (V3d)o.Point;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator PlaneWithPoint3d(PlaneWithPoint3f o)\n            => new PlaneWithPoint3d(o);\n\n        #endregion\n\n        #region Constants\n\n        public static PlaneWithPoint3d XPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3d(V3d.XAxis, V3d.Zero);\n        }\n\n        public static PlaneWithPoint3d YPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3d(V3d.YAxis, V3d.Zero);\n        }\n\n        public static PlaneWithPoint3d ZPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3d(V3d.ZAxis, V3d.Zero);\n        }\n\n        public static PlaneWithPoint3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3d(V3d.Zero, V3d.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly PlaneWithPoint3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3d(Normal.Normalized, Point);\n        }\n\n        public readonly Plane3d Plane3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane3d(Normal, Point);\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == V3d.Zero;\n        }\n\n        public readonly PlaneWithPoint3d Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlaneWithPoint3d(-Normal, Point);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize() => Normal.Normalize();\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse() => Normal = -Normal;\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Height(V3d p) => Vec.Dot(Normal, p - Point);\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(V3d p) => Height(p).Sign();\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(PlaneWithPoint3d other)\n            => Normal.Equals(other.Normal) && Point.Equals(other.Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is PlaneWithPoint3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static PlaneWithPoint3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new PlaneWithPoint3d(V3d.Parse(x[0]), V3d.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        /// <summary>\n        /// Gets entire double space as bounding box.\n        /// </summary>\n        public readonly Box3d BoundingBox3d\n        {\n            get\n            {\n                var box = new Box3d(V3d.MinValue, V3d.MaxValue);\n\n                if (Normal == V3d.XAxis)\n                {\n                    box.Min.X = Point.X; box.Max.X = Point.X; return box;\n                }\n                if (Normal == V3d.YAxis)\n                {\n                    box.Min.Y = Point.Y; box.Max.Y = Point.Y; return box;\n                }\n                if (Normal == V3d.ZAxis)\n                {\n                    box.Min.Z = Point.Z; box.Max.Z = Point.Z; return box;\n                }\n\n                return box;\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"PlaneWithPoint3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this PlaneWithPoint3d a, PlaneWithPoint3d b, double tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Point, b.Point, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"PlaneWithPoint3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this PlaneWithPoint3d a, PlaneWithPoint3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region PlanePair3d\n\n    /// <summary>\n    /// A plane pair defines a ray at their intersection.\n    /// </summary>\n    public struct PlanePair3d\n    {\n        public Plane3d Plane0;\n        public Plane3d Plane1;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlanePair3d(Plane3d plane0, Plane3d plane1)\n        {\n            Plane0 = plane0; Plane1 = plane1;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"PlanePair3d\"/> from another <see cref=\"PlanePair3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlanePair3d(PlanePair3d o)\n        {\n            Plane0 = o.Plane0;\n            Plane1 = o.Plane1;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"PlanePair3d\"/> from a <see cref=\"PlanePair3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlanePair3d(PlanePair3f o)\n        {\n            Plane0 = (Plane3d)o.Plane0;\n            Plane1 = (Plane3d)o.Plane1;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator PlanePair3d(PlanePair3f o)\n            => new PlanePair3d(o);\n\n        #endregion\n\n        #region Arithmetics\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Ray3d GetRay3d()\n        {\n            Plane0.Intersects(Plane1, out Ray3d ray);\n            return ray;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region PlaneTriple3d\n\n    /// <summary>\n    /// A plane triple defines a point at their intersection.\n    /// </summary>\n    public struct PlaneTriple3d\n    {\n        public Plane3d Plane0;\n        public Plane3d Plane1;\n        public Plane3d Plane2;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneTriple3d(Plane3d plane0, Plane3d plane1, Plane3d plane2)\n        {\n            Plane0 = plane0; Plane1 = plane1; Plane2 = plane2;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"PlaneTriple3d\"/> from another <see cref=\"PlaneTriple3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneTriple3d(PlaneTriple3d o)\n        {\n            Plane0 = o.Plane0;\n            Plane1 = o.Plane1;\n            Plane2 = o.Plane2;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"PlaneTriple3d\"/> from a <see cref=\"PlaneTriple3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public PlaneTriple3d(PlaneTriple3f o)\n        {\n            Plane0 = (Plane3d)o.Plane0;\n            Plane1 = (Plane3d)o.Plane1;\n            Plane2 = (Plane3d)o.Plane2;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator PlaneTriple3d(PlaneTriple3f o)\n            => new PlaneTriple3d(o);\n\n        #endregion\n\n        #region Properties\n\n        public readonly PlanePair3d Pair01\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3d(Plane0, Plane1);\n        }\n\n        public readonly PlanePair3d Pair02\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3d(Plane0, Plane2);\n        }\n\n        public readonly PlanePair3d Pair12\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3d(Plane1, Plane2);\n        }\n\n        public readonly PlanePair3d Pair10\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3d(Plane1, Plane0);\n        }\n\n        public readonly PlanePair3d Pair20\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3d(Plane2, Plane0);\n        }\n\n        public readonly PlanePair3d Pair21\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new PlanePair3d(Plane2, Plane1);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        public readonly V3d GetPoint()\n        {\n            Plane0.Intersects(Plane1, Plane2, out V3d point);\n            return point;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Plane3dExtensions\n\n    public static class Plane3dExtensions\n    {\n        /// <summary>\n        /// Returns a transformation of an orthonormal basis in Plane- to WorldSpace.\n        /// </summary>\n        public static Trafo3d GetPlaneSpaceTransform(this Plane3d self)\n            => Trafo3d.FromNormalFrame(self.Point, self.Normal);\n\n        /// <summary>\n        /// 3D world space to 2D plane space.\n        /// Plane space is defined by a normal-frame from Point and Normal of the plane.\n        /// </summary>\n        public static M44d GetWorldToPlane(this Plane3d self)\n        {\n            M44d.NormalFrame(self.Point, self.Normal, out M44d _, out M44d global2local);\n            return global2local;\n        }\n\n        /// <summary>\n        /// 2D plane space to 3D world space.\n        /// Plane space is defined by a normal-frame from Point and Normal of the plane.\n        /// </summary>\n        public static M44d GetPlaneToWorld(this Plane3d self)\n        {\n            M44d.NormalFrame(self.Point, self.Normal, out M44d local2global, out M44d _);\n            return local2global;\n        }\n\n        /// <summary>\n        /// Projects a point onto the plane (shortest distance).\n        /// </summary>\n        public static V3d Project(this Plane3d plane, V3d p) => p - plane.Height(p) * plane.Normal;\n\n        /// <summary>\n        /// Projects a point onto the plane along given direction.\n        /// </summary>\n        public static V3d Project(this Plane3d plane, V3d p, V3d direction)\n        {\n            var r = new Ray3d(p, direction);\n            if (r.Intersects(plane, out double t))\n            {\n                return r.GetPointOnRay(t);\n            }\n            else\n            {\n                throw new Exception(string.Format(\n                    \"Failed to project point {0} onto plane {1} along direction {2}.\", p, plane, direction)\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Projects points onto plane (shortest distance).\n        /// </summary>\n        public static V3d[] Project(this Plane3d plane, V3d[] pointArray, int startIndex = 0, int count = 0)\n        {\n            if (pointArray == null) throw new ArgumentNullException();\n            if (startIndex < 0 || startIndex >= pointArray.Length) throw new ArgumentOutOfRangeException();\n            if (count < 0) throw new ArgumentOutOfRangeException();\n            if (count == 0) count = pointArray.Length - startIndex;\n            if (count > pointArray.Length - startIndex) throw new ArgumentOutOfRangeException();\n\n            var normal = plane.Normal;\n            var result = new V3d[count];\n            for (int i = startIndex, j = 0; j < count; i++, j++)\n            {\n                var p = pointArray[i];\n                var height = plane.Height(p);\n                result[j] = p - height * normal;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Projects points onto plane along given direction.\n        /// </summary>\n        public static V3d[] Project(this Plane3d plane, V3d[] pointArray, V3d direction, int startIndex = 0, int count = 0)\n        {\n            if (pointArray == null) throw new ArgumentNullException();\n            if (startIndex < 0 || startIndex >= pointArray.Length) throw new ArgumentOutOfRangeException();\n            if (count < 0) throw new ArgumentOutOfRangeException();\n            if (count == 0) count = pointArray.Length - startIndex;\n            if (count > pointArray.Length - startIndex) throw new ArgumentOutOfRangeException();\n\n            var result = new V3d[count];\n            for (int i = startIndex, j = 0; j < count; i++, j++)\n            {\n                var r = new Ray3d(pointArray[i], direction);\n                if (r.Intersects(plane, out double t))\n                {\n                    result[j] = r.GetPointOnRay(t);\n                }\n                else\n                {\n                    throw new Exception(string.Format(\n                        \"Failed to project point {0} onto plane {1} along direction {2}.\", pointArray[i], plane, direction)\n                        );\n                }\n            };\n            return result;\n        }\n\n        /// <summary>\n        /// Projects a point from world space to plane space (shortest distance).\n        /// </summary>\n        public static V2d ProjectToPlaneSpace(this Plane3d plane, V3d p)\n            => plane.GetWorldToPlane().TransformPos(p).XY;\n\n        /// <summary>\n        /// Projects points from world space to plane space (shortest distance).\n        /// </summary>\n        public static V2d[] ProjectToPlaneSpace(this Plane3d plane, V3d[] points)\n        {\n            var global2local = plane.GetWorldToPlane();\n            return points.Map(p => global2local.TransformPos(p).XY);\n        }\n\n        /// <summary>\n        /// Transforms point from plane space to world space.\n        /// </summary>\n        public static V3d Unproject(this Plane3d plane, V2d point)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            return local2global.TransformPos(point.XYO);\n        }\n\n        /// <summary>\n        /// Transforms points from plane space to world space.\n        /// </summary>\n        public static V3d[] Unproject(this Plane3d plane, V2d[] points)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            return points.Map(p => local2global.TransformPos(p.XYO));\n        }\n\n        /// <summary>\n        /// Transforms points from plane space to world space.\n        /// </summary>\n        public static V3d[] Unproject(this Plane3d plane, IReadOnlyList<V2d> points)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            var xs = new V3d[points.Count];\n            for (var i = 0; i < points.Count; i++)\n                xs[i] = local2global.TransformPos(points[i].XYO);\n            return xs;\n        }\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Plane/Plane3_template.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var plane3t2 = \"Plane3\" + tc2;\n    //#   var planewithpoint3t = \"PlaneWithPoint3\" + tc;\n    //#   var planewithpoint3t2 = \"PlaneWithPoint3\" + tc2;\n    //#   var planepair3t = \"PlanePair3\" + tc;\n    //#   var planepair3t2 = \"PlanePair3\" + tc2;\n    //#   var planetriple3t = \"PlaneTriple3\" + tc;\n    //#   var planetriple3t2 = \"PlaneTriple3\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var v4t = \"V4\" + tc;\n    //#   var m44t = \"M44\" + tc;\n    //#   var euclidean3t = \"Euclidean3\" + tc;\n    //#   var trafo3t = \"Trafo3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var ray3t = \"Ray3\" + tc;\n    //#   var iboundingbox3t = \"IBoundingBox3\" + tc;\n    #region __plane3t__\n\n    /// <summary>\n    /// A plane represented by a (possibly) normalized normal vector and the\n    /// distance to the origin. Note that the plane does not enforce the\n    /// normalized normal vector.\n    /// Equation for points p on the plane: Normal dot p == Distance\n    /// </summary>\n    public partial struct __plane3t__ : IEquatable<__plane3t__>, IValidity, __iboundingbox3t__\n    {\n        /// <summary>\n        /// Plane normal.\n        /// </summary>\n        public __v3t__ Normal;\n\n        /// <summary>\n        /// Distance from origin to plane.\n        /// </summary>\n        public __ftype__ Distance;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and distance to origin.\n        /// IMPORTANT: The normal has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane3t__(__v3t__ normalizedNormal, __ftype__ distance)\n        {\n            Normal = normalizedNormal;\n            Distance = distance;\n        }\n\n        /// <summary>\n        /// Creates plane from normal vector and point.\n        /// IMPORTANT: The normal has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane3t__(__v3t__ normalizedNormal, __v3t__ point)\n        {\n            Normal = normalizedNormal;\n            Distance = Vec.Dot(normalizedNormal, point);\n        }\n\n        /// <summary>\n        /// Creates a plane from 3 independent points.\n        /// A normalized normal vector is computed and stored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane3t__(__v3t__ p0, __v3t__ p1, __v3t__ p2)\n        {\n            Normal = Vec.Cross(p1 - p0, p2 - p0).Normalized;\n            Distance = Vec.Dot(Normal, p0);\n        }\n\n        /// <summary>\n        /// Create a plane from coefficients (a, b, c, d) of the normal equation: ax + by + cz + d = 0\n        /// Normal = [a, b, c]; Distance = -d\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane3t__(__v4t__ coefficients)\n        {\n            Normal = coefficients.XYZ;\n            Distance = -coefficients.W;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__plane3t__\"/> from another <see cref=\"__plane3t__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane3t__(__plane3t__ o)\n        {\n            Normal = o.Normal;\n            Distance = o.Distance;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__plane3t__\"/> from a <see cref=\"__plane3t2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __plane3t__(__plane3t2__ o)\n        {\n            Normal = (__v3t__)o.Normal;\n            Distance = (__ftype__)o.Distance;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __plane3t__(__plane3t2__ o)\n            => new __plane3t__(o);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __plane3t__(__planewithpoint3t__ o)\n            => new __plane3t__(o.Normal, o.Point);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>YZ plane.</summary>\n        public static __plane3t__ XPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(__v3t__.XAxis, __v3t__.Zero);\n        }\n\n        /// <summary>XZ plane.</summary>\n        public static __plane3t__ YPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(__v3t__.YAxis, __v3t__.Zero);\n        }\n\n        /// <summary>XY plane.</summary>\n        public static __plane3t__ ZPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(__v3t__.ZAxis, __v3t__.Zero);\n        }\n\n        /// <summary>Invalid plane.</summary>\n        public static __plane3t__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(__v3t__.Zero, 0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// The point on the plane which is closest to the origin.\n        /// </summary>\n        [XmlIgnore]\n        public __v3t__ Point\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Normal * Distance / Normal.LengthSquared; }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Distance = Vec.Dot(Normal, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is not the zero-vector.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal != __v3t__.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if the normal of the plane is the zero-vector.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == __v3t__.Zero;\n        }\n\n        /// <summary>\n        /// Returns the normalized <see cref=\"__plane3t__\"/> as new <see cref=\"__plane3t__\"/>.\n        /// </summary>\n        public readonly __plane3t__ Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                __ftype__ scale = Normal.Length;\n                return new __plane3t__(Normal / scale, Distance / scale);\n            }\n        }\n\n        /// <summary>\n        /// Returns the coefficients (a, b, c, d) of the normal equation: ax + by + cz + d = 0\n        /// </summary>\n        public readonly __v4t__ Coefficients\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __v4t__(Normal, -Distance);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        /// <summary>\n        /// Normalizes this <see cref=\"__plane3t__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize()\n        {\n            __ftype__ scale = Normal.Length;\n            Normal /= scale;\n            Distance /= scale;\n        }\n\n        /// <summary>\n        /// Changes sign of normal vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse()\n        {\n            Normal = -Normal;\n            Distance = -Distance;\n        }\n\n        /// <summary>\n        /// Returns <see cref=\"__plane3t__\"/> with normal vector in opposing direction.\n        /// </summary>\n        public readonly __plane3t__ Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(-Normal, -Distance);\n        }\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// IMPORTANT: If the plane is not normalized the returned height is scaled by the magnitued of the plane normal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ Height(__v3t__ p)\n            => Vec.Dot(Normal, p) - Distance;\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(__v3t__ p) => Height(p).Sign();\n\n        /// <summary>\n        /// Projets the given point x perpendicular on the plane\n        /// and returns the nearest point on the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __v3t__ NearestPoint(__v3t__ x)\n        {\n            var p = Point;\n            return (x - Normal.Dot(x - p) * Normal);\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given trafo using the inverse\n        /// transposed matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __plane3t__ Transformed(__trafo3t__ trafo)\n        {\n            return new __plane3t__(\n                new __v3t__(\n                    trafo.Backward.M00 * Normal.X + trafo.Backward.M10 * Normal.Y + trafo.Backward.M20 * Normal.Z - trafo.Backward.M30 * Distance,\n                    trafo.Backward.M01 * Normal.X + trafo.Backward.M11 * Normal.Y + trafo.Backward.M21 * Normal.Z - trafo.Backward.M31 * Distance,\n                    trafo.Backward.M02 * Normal.X + trafo.Backward.M12 * Normal.Y + trafo.Backward.M22 * Normal.Z - trafo.Backward.M32 * Distance\n                ),\n                trafo.Backward.M33 * Distance - trafo.Backward.M03 * Normal.X - trafo.Backward.M13 * Normal.Y - trafo.Backward.M23 * Normal.Z\n            );\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given matrix. The matrix is assumed\n        /// to represent a euclidean transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __plane3t__ Transformed(__m44t__ trafo)\n        {\n            var n = trafo.TransformDir(Normal);\n            var d = Distance + trafo.C0.Dot(trafo.C3) * Normal.X + trafo.C1.Dot(trafo.C3) * Normal.Y + trafo.C2.Dot(trafo.C3) * Normal.Z;\n            return new __plane3t__(n, d);\n        }\n\n        /// <summary>\n        /// Transforms the plane with a given __euclidean3t__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __plane3t__ Transformed(__euclidean3t__ trafo)\n        {\n            var n1 = trafo.TransformDir(Normal);\n            return new __plane3t__(n1, Distance + trafo.Trans.Dot(n1));\n        }\n\n        #endregion\n\n        #region Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__plane3t__ a, __plane3t__ b)\n            => a.Normal == b.Normal && a.Distance == b.Distance;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__plane3t__ a, __plane3t__ b)\n            => a.Normal != b.Normal || a.Distance != b.Distance;\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__plane3t__ other)\n            => Normal.Equals(other.Normal) && Distance.Equals(other.Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __plane3t__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString() =>\n            string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Distance);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __plane3t__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __plane3t__(__v3t__.Parse(x[0]), __ftype__.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region __iboundingbox3t__ Members\n\n        /// <summary>\n        /// Gets entire __ftype__ space as bounding box.\n        /// </summary>\n        public readonly __box3t__ BoundingBox3__tc__\n        {\n            get\n            {\n                var box = new __box3t__(__v3t__.MinValue, __v3t__.MaxValue);\n\n                if (Normal == __v3t__.XAxis)\n                {\n                    box.Min.X = Distance; box.Max.X = Distance; return box;\n                }\n                if (Normal == __v3t__.YAxis)\n                {\n                    box.Min.Y = Distance; box.Max.Y = Distance; return box;\n                }\n                if (Normal == __v3t__.ZAxis)\n                {\n                    box.Min.Z = Distance; box.Max.Z = Distance; return box;\n                }\n\n                return box;\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__plane3t__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __plane3t__ a, __plane3t__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Distance, b.Distance, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__plane3t__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __plane3t__ a, __plane3t__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region __planewithpoint3t__\n\n    /// <summary>\n    /// A plane with a specific point that can be retrieved later.\n    /// </summary>\n    public struct __planewithpoint3t__ : __iboundingbox3t__\n    {\n        public __v3t__ Normal;\n        public __v3t__ Point;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates plane from normal vector and point. IMPORTANT: The\n        /// supplied vector has to be normalized in order for all methods\n        /// to work correctly, however if only relative height computations\n        /// using the <see cref=\"Height\"/> method are necessary, the normal\n        /// vector need not be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planewithpoint3t__(__v3t__ normalizedNormal, __v3t__ point)\n        {\n            Normal = normalizedNormal;\n            Point = point;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__plane3t__\"/> from another <see cref=\"__plane3t__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planewithpoint3t__(__planewithpoint3t__ o)\n        {\n            Normal = o.Normal;\n            Point = o.Point;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__plane3t__\"/> from a <see cref=\"__plane3t2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planewithpoint3t__(__planewithpoint3t2__ o)\n        {\n            Normal = (__v3t__)o.Normal;\n            Point = (__v3t__)o.Point;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __planewithpoint3t__(__planewithpoint3t2__ o)\n            => new __planewithpoint3t__(o);\n\n        #endregion\n\n        #region Constants\n\n        public static __planewithpoint3t__ XPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planewithpoint3t__(__v3t__.XAxis, __v3t__.Zero);\n        }\n\n        public static __planewithpoint3t__ YPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planewithpoint3t__(__v3t__.YAxis, __v3t__.Zero);\n        }\n\n        public static __planewithpoint3t__ ZPlane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planewithpoint3t__(__v3t__.ZAxis, __v3t__.Zero);\n        }\n\n        public static __planewithpoint3t__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planewithpoint3t__(__v3t__.Zero, __v3t__.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly __planewithpoint3t__ Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planewithpoint3t__(Normal.Normalized, Point);\n        }\n\n        public readonly __plane3t__ __plane3t__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane3t__(Normal, Point);\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Normal == __v3t__.Zero;\n        }\n\n        public readonly __planewithpoint3t__ Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planewithpoint3t__(-Normal, Point);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Normalize() => Normal.Normalize();\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Reverse() => Normal = -Normal;\n\n        /// <summary>\n        /// The signed height of the supplied point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ Height(__v3t__ p) => Vec.Dot(Normal, p - Point);\n\n        /// <summary>\n        /// The sign of the height of the point over the plane.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Sign(__v3t__ p) => Height(p).Sign();\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Normal, Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__planewithpoint3t__ other)\n            => Normal.Equals(other.Normal) && Point.Equals(other.Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __planewithpoint3t__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Normal, Point);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __planewithpoint3t__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __planewithpoint3t__(__v3t__.Parse(x[0]), __v3t__.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region __iboundingbox3t__ Members\n\n        /// <summary>\n        /// Gets entire __ftype__ space as bounding box.\n        /// </summary>\n        public readonly __box3t__ BoundingBox3__tc__\n        {\n            get\n            {\n                var box = new __box3t__(__v3t__.MinValue, __v3t__.MaxValue);\n\n                if (Normal == __v3t__.XAxis)\n                {\n                    box.Min.X = Point.X; box.Max.X = Point.X; return box;\n                }\n                if (Normal == __v3t__.YAxis)\n                {\n                    box.Min.Y = Point.Y; box.Max.Y = Point.Y; return box;\n                }\n                if (Normal == __v3t__.ZAxis)\n                {\n                    box.Min.Z = Point.Z; box.Max.Z = Point.Z; return box;\n                }\n\n                return box;\n            }\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__planewithpoint3t__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __planewithpoint3t__ a, __planewithpoint3t__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Normal, b.Normal, tolerance) &&\n            ApproximateEquals(a.Point, b.Point, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__planewithpoint3t__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __planewithpoint3t__ a, __planewithpoint3t__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region __planepair3t__\n\n    /// <summary>\n    /// A plane pair defines a ray at their intersection.\n    /// </summary>\n    public struct __planepair3t__\n    {\n        public __plane3t__ Plane0;\n        public __plane3t__ Plane1;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planepair3t__(__plane3t__ plane0, __plane3t__ plane1)\n        {\n            Plane0 = plane0; Plane1 = plane1;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__planepair3t__\"/> from another <see cref=\"__planepair3t__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planepair3t__(__planepair3t__ o)\n        {\n            Plane0 = o.Plane0;\n            Plane1 = o.Plane1;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__planepair3t__\"/> from a <see cref=\"__planepair3t2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planepair3t__(__planepair3t2__ o)\n        {\n            Plane0 = (__plane3t__)o.Plane0;\n            Plane1 = (__plane3t__)o.Plane1;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __planepair3t__(__planepair3t2__ o)\n            => new __planepair3t__(o);\n\n        #endregion\n\n        #region Arithmetics\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ray3t__ Get__ray3t__()\n        {\n            Plane0.Intersects(Plane1, out __ray3t__ ray);\n            return ray;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region __planetriple3t__\n\n    /// <summary>\n    /// A plane triple defines a point at their intersection.\n    /// </summary>\n    public struct __planetriple3t__\n    {\n        public __plane3t__ Plane0;\n        public __plane3t__ Plane1;\n        public __plane3t__ Plane2;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planetriple3t__(__plane3t__ plane0, __plane3t__ plane1, __plane3t__ plane2)\n        {\n            Plane0 = plane0; Plane1 = plane1; Plane2 = plane2;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__planetriple3t__\"/> from another <see cref=\"__planetriple3t__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planetriple3t__(__planetriple3t__ o)\n        {\n            Plane0 = o.Plane0;\n            Plane1 = o.Plane1;\n            Plane2 = o.Plane2;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__planetriple3t__\"/> from a <see cref=\"__planetriple3t2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __planetriple3t__(__planetriple3t2__ o)\n        {\n            Plane0 = (__plane3t__)o.Plane0;\n            Plane1 = (__plane3t__)o.Plane1;\n            Plane2 = (__plane3t__)o.Plane2;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __planetriple3t__(__planetriple3t2__ o)\n            => new __planetriple3t__(o);\n\n        #endregion\n\n        #region Properties\n\n        public readonly __planepair3t__ Pair01\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planepair3t__(Plane0, Plane1);\n        }\n\n        public readonly __planepair3t__ Pair02\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planepair3t__(Plane0, Plane2);\n        }\n\n        public readonly __planepair3t__ Pair12\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planepair3t__(Plane1, Plane2);\n        }\n\n        public readonly __planepair3t__ Pair10\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planepair3t__(Plane1, Plane0);\n        }\n\n        public readonly __planepair3t__ Pair20\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planepair3t__(Plane2, Plane0);\n        }\n\n        public readonly __planepair3t__ Pair21\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __planepair3t__(Plane2, Plane1);\n        }\n\n        #endregion\n\n        #region Arithmetics\n\n        public readonly __v3t__ GetPoint()\n        {\n            Plane0.Intersects(Plane1, Plane2, out __v3t__ point);\n            return point;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region __plane3t__Extensions\n\n    public static class __plane3t__Extensions\n    {\n        /// <summary>\n        /// Returns a transformation of an orthonormal basis in Plane- to WorldSpace.\n        /// </summary>\n        public static __trafo3t__ GetPlaneSpaceTransform(this __plane3t__ self)\n            => __trafo3t__.FromNormalFrame(self.Point, self.Normal);\n\n        /// <summary>\n        /// 3D world space to 2D plane space.\n        /// Plane space is defined by a normal-frame from Point and Normal of the plane.\n        /// </summary>\n        public static __m44t__ GetWorldToPlane(this __plane3t__ self)\n        {\n            __m44t__.NormalFrame(self.Point, self.Normal, out __m44t__ _, out __m44t__ global2local);\n            return global2local;\n        }\n\n        /// <summary>\n        /// 2D plane space to 3D world space.\n        /// Plane space is defined by a normal-frame from Point and Normal of the plane.\n        /// </summary>\n        public static __m44t__ GetPlaneToWorld(this __plane3t__ self)\n        {\n            __m44t__.NormalFrame(self.Point, self.Normal, out __m44t__ local2global, out __m44t__ _);\n            return local2global;\n        }\n\n        /// <summary>\n        /// Projects a point onto the plane (shortest distance).\n        /// </summary>\n        public static __v3t__ Project(this __plane3t__ plane, __v3t__ p) => p - plane.Height(p) * plane.Normal;\n\n        /// <summary>\n        /// Projects a point onto the plane along given direction.\n        /// </summary>\n        public static __v3t__ Project(this __plane3t__ plane, __v3t__ p, __v3t__ direction)\n        {\n            var r = new __ray3t__(p, direction);\n            if (r.Intersects(plane, out __ftype__ t))\n            {\n                return r.GetPointOnRay(t);\n            }\n            else\n            {\n                throw new Exception(string.Format(\n                    \"Failed to project point {0} onto plane {1} along direction {2}.\", p, plane, direction)\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Projects points onto plane (shortest distance).\n        /// </summary>\n        public static __v3t__[] Project(this __plane3t__ plane, __v3t__[] pointArray, int startIndex = 0, int count = 0)\n        {\n            if (pointArray == null) throw new ArgumentNullException();\n            if (startIndex < 0 || startIndex >= pointArray.Length) throw new ArgumentOutOfRangeException();\n            if (count < 0) throw new ArgumentOutOfRangeException();\n            if (count == 0) count = pointArray.Length - startIndex;\n            if (count > pointArray.Length - startIndex) throw new ArgumentOutOfRangeException();\n\n            var normal = plane.Normal;\n            var result = new __v3t__[count];\n            for (int i = startIndex, j = 0; j < count; i++, j++)\n            {\n                var p = pointArray[i];\n                var height = plane.Height(p);\n                result[j] = p - height * normal;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Projects points onto plane along given direction.\n        /// </summary>\n        public static __v3t__[] Project(this __plane3t__ plane, __v3t__[] pointArray, __v3t__ direction, int startIndex = 0, int count = 0)\n        {\n            if (pointArray == null) throw new ArgumentNullException();\n            if (startIndex < 0 || startIndex >= pointArray.Length) throw new ArgumentOutOfRangeException();\n            if (count < 0) throw new ArgumentOutOfRangeException();\n            if (count == 0) count = pointArray.Length - startIndex;\n            if (count > pointArray.Length - startIndex) throw new ArgumentOutOfRangeException();\n\n            var result = new __v3t__[count];\n            for (int i = startIndex, j = 0; j < count; i++, j++)\n            {\n                var r = new __ray3t__(pointArray[i], direction);\n                if (r.Intersects(plane, out __ftype__ t))\n                {\n                    result[j] = r.GetPointOnRay(t);\n                }\n                else\n                {\n                    throw new Exception(string.Format(\n                        \"Failed to project point {0} onto plane {1} along direction {2}.\", pointArray[i], plane, direction)\n                        );\n                }\n            };\n            return result;\n        }\n\n        /// <summary>\n        /// Projects a point from world space to plane space (shortest distance).\n        /// </summary>\n        public static __v2t__ ProjectToPlaneSpace(this __plane3t__ plane, __v3t__ p)\n            => plane.GetWorldToPlane().TransformPos(p).XY;\n\n        /// <summary>\n        /// Projects points from world space to plane space (shortest distance).\n        /// </summary>\n        public static __v2t__[] ProjectToPlaneSpace(this __plane3t__ plane, __v3t__[] points)\n        {\n            var global2local = plane.GetWorldToPlane();\n            return points.Map(p => global2local.TransformPos(p).XY);\n        }\n\n        /// <summary>\n        /// Transforms point from plane space to world space.\n        /// </summary>\n        public static __v3t__ Unproject(this __plane3t__ plane, __v2t__ point)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            return local2global.TransformPos(point.XYO);\n        }\n\n        /// <summary>\n        /// Transforms points from plane space to world space.\n        /// </summary>\n        public static __v3t__[] Unproject(this __plane3t__ plane, __v2t__[] points)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            return points.Map(p => local2global.TransformPos(p.XYO));\n        }\n\n        /// <summary>\n        /// Transforms points from plane space to world space.\n        /// </summary>\n        public static __v3t__[] Unproject(this __plane3t__ plane, IReadOnlyList<__v2t__> points)\n        {\n            var local2global = plane.GetPlaneToWorld();\n            var xs = new __v3t__[points.Count];\n            for (var i = 0; i < points.Count; i++)\n                xs[i] = local2global.TransformPos(points[i].XYO);\n            return xs;\n        }\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/IImmutablePolygonExtensions_auto.cs",
    "content": "using System;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    public static class IImmutablePolygonExtensions\n    {\n        /// <summary>\n        /// Maps index into range [0, count).\n        /// </summary>\n        internal static int RepairIndex(int count, int index)\n        {\n            if (index >= 0)\n            {\n                return (index < count) ? index : (index % count);\n            }\n            else\n            {\n                if (index >= -count)\n                {\n                    return count + index;\n                }\n                else\n                {\n                    return count - 1 + (index + 1) % count;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Maps arbitrary index into valid range.\n        /// </summary>\n        public static int RepairIndex<T>(this IImmutablePolygon<T> self, int index)\n            => RepairIndex(self.Count, index);\n    }\n\n    #region IImmutablePolygon2fExtensions\n\n    /// <summary>\n    /// Extensions for IImmutablePolygon(of T).\n    /// </summary>\n    public static class IImmutablePolygon2fExtensions\n    {\n        /// <summary>\n        /// Converts this IImmutablePolygon(of V2f) to a Polygon2f.\n        /// </summary>\n        public static Polygon2f ToPolygon2f(this IImmutablePolygon<V2f> self)\n            => new Polygon2f(self.Points);\n\n        /// <summary>\n        /// Returns the index and distance of the polygon's closest point to the given query point.\n        /// </summary>\n        public static Tuple<int, double> QueryNearestVertex(this IImmutablePolygon<V2f> self, V2f queryPoint)\n        {\n            if (self.Count == 0) return null;\n\n            int bestIndex = 0;\n            double bestDist = double.MaxValue;\n            for (int i = 0; i < self.Count; i++)\n            {\n                var d = (queryPoint - self.Points[i]).LengthSquared;\n                if (d < bestDist) { bestDist = d; bestIndex = i; }\n            }\n\n            return Tuple.Create(bestIndex, bestDist.Sqrt());\n        }\n\n        /// <summary>\n        /// Returns new polygon with point moved. \n        /// </summary>\n        public static IImmutablePolygon<V2f> MovePoint(this IImmutablePolygon<V2f> self, int index, V2f delta)\n            => self.SetPoint(index, self.Points[index] + delta);\n\n        /// <summary>\n        /// Returns new polygon with point transformed. \n        /// </summary>\n        public static IImmutablePolygon<V2f> TransformPoint(this IImmutablePolygon<V2f> self, int index, M33f trafo)\n            => self.SetPoint(index, trafo.TransformPos(self.Points[index]));\n\n        /// <summary>\n        /// Gets the index-th edge of this polygon.\n        /// </summary>\n        public static Line2f GetEdge(this IImmutablePolygon<V2f> self, int index)\n        {\n            index = self.RepairIndex(index);\n            var p0 = self.Points[index++];\n            var p1 = self.Points[index < self.Count ? index : 0];\n            return new Line2f(p0, p1);\n        }\n\n        /// <summary>\n        /// Sets the index-th edge of this polygon.\n        /// </summary>\n        public static IImmutablePolygon<V2f> SetEdge(this IImmutablePolygon<V2f> self, int index, Line2f edge)\n        {\n            index = self.RepairIndex(index);\n            var i0 = index++;\n            var i1 = index < self.Count ? index : 0;\n            return self.SetPoint(i0, edge.P0).SetPoint(i1, edge.P1);\n        }\n\n        /// <summary>\n        /// Maps arbitrary index into valid range.\n        /// </summary>\n        public static int RepairIndex(this Polygon2f self, int index)\n            => IImmutablePolygonExtensions.RepairIndex(self.PointCount, index);\n\n        /// <summary>\n        /// Maps arbitrary index into valid range.\n        /// </summary>\n        public static int RepairIndex(this Polygon3f self, int index)\n            => IImmutablePolygonExtensions.RepairIndex(self.PointCount, index);\n\n        /// <summary>\n        /// Makes index-th edge parallel to x- or y-axis.\n        /// </summary>\n        public static IImmutablePolygon<V2f> AlignEdge(this IImmutablePolygon<V2f> self, int index)\n        {\n            var e = self.GetEdge(index);\n\n            if ((Math.Abs(e.P0.X - e.P1.X) < Math.Abs(e.P0.Y - e.P1.Y)))\n            {\n                var x = (e.P0.X + e.P1.X) * 0.5;\n                return self.SetEdge(index, new Line2f(new V2f(x, e.P0.Y), new V2f(x, e.P1.Y)));\n            }\n            else\n            {\n                var y = (e.P0.Y + e.P1.Y) * 0.5;\n                return self.SetEdge(index, new Line2f(new V2f(e.P0.X, y), new V2f(e.P1.X, y)));\n            }\n        }\n\n        /// <summary>\n        /// Ensures that the outline is oriented counter-clockwise.\n        /// </summary>\n        public static IImmutablePolygon<V2f> ToCounterClockwise(this IImmutablePolygon<V2f> self)\n            => self.ToPolygon2f().IsCcw() ? self : new ImmutablePolygon<V2f>(self.Points.Reverse());\n\n        /// <summary>\n        /// Ensures that the outline is oriented clockwise.\n        /// </summary>\n        public static IImmutablePolygon<V2f> ToClockwise(this IImmutablePolygon<V2f> self)\n            => self.ToPolygon2f().IsCcw() ? new ImmutablePolygon<V2f>(self.Points.Reverse()) : self;\n    }\n\n    #endregion\n\n    #region IImmutablePolygon2dExtensions\n\n    /// <summary>\n    /// Extensions for IImmutablePolygon(of T).\n    /// </summary>\n    public static class IImmutablePolygon2dExtensions\n    {\n        /// <summary>\n        /// Converts this IImmutablePolygon(of V2d) to a Polygon2d.\n        /// </summary>\n        public static Polygon2d ToPolygon2d(this IImmutablePolygon<V2d> self)\n            => new Polygon2d(self.Points);\n\n        /// <summary>\n        /// Returns the index and distance of the polygon's closest point to the given query point.\n        /// </summary>\n        public static Tuple<int, double> QueryNearestVertex(this IImmutablePolygon<V2d> self, V2d queryPoint)\n        {\n            if (self.Count == 0) return null;\n\n            int bestIndex = 0;\n            double bestDist = double.MaxValue;\n            for (int i = 0; i < self.Count; i++)\n            {\n                var d = (queryPoint - self.Points[i]).LengthSquared;\n                if (d < bestDist) { bestDist = d; bestIndex = i; }\n            }\n\n            return Tuple.Create(bestIndex, bestDist.Sqrt());\n        }\n\n        /// <summary>\n        /// Returns new polygon with point moved. \n        /// </summary>\n        public static IImmutablePolygon<V2d> MovePoint(this IImmutablePolygon<V2d> self, int index, V2d delta)\n            => self.SetPoint(index, self.Points[index] + delta);\n\n        /// <summary>\n        /// Returns new polygon with point transformed. \n        /// </summary>\n        public static IImmutablePolygon<V2d> TransformPoint(this IImmutablePolygon<V2d> self, int index, M33d trafo)\n            => self.SetPoint(index, trafo.TransformPos(self.Points[index]));\n\n        /// <summary>\n        /// Gets the index-th edge of this polygon.\n        /// </summary>\n        public static Line2d GetEdge(this IImmutablePolygon<V2d> self, int index)\n        {\n            index = self.RepairIndex(index);\n            var p0 = self.Points[index++];\n            var p1 = self.Points[index < self.Count ? index : 0];\n            return new Line2d(p0, p1);\n        }\n\n        /// <summary>\n        /// Sets the index-th edge of this polygon.\n        /// </summary>\n        public static IImmutablePolygon<V2d> SetEdge(this IImmutablePolygon<V2d> self, int index, Line2d edge)\n        {\n            index = self.RepairIndex(index);\n            var i0 = index++;\n            var i1 = index < self.Count ? index : 0;\n            return self.SetPoint(i0, edge.P0).SetPoint(i1, edge.P1);\n        }\n\n        /// <summary>\n        /// Maps arbitrary index into valid range.\n        /// </summary>\n        public static int RepairIndex(this Polygon2d self, int index)\n            => IImmutablePolygonExtensions.RepairIndex(self.PointCount, index);\n\n        /// <summary>\n        /// Maps arbitrary index into valid range.\n        /// </summary>\n        public static int RepairIndex(this Polygon3d self, int index)\n            => IImmutablePolygonExtensions.RepairIndex(self.PointCount, index);\n\n        /// <summary>\n        /// Makes index-th edge parallel to x- or y-axis.\n        /// </summary>\n        public static IImmutablePolygon<V2d> AlignEdge(this IImmutablePolygon<V2d> self, int index)\n        {\n            var e = self.GetEdge(index);\n\n            if ((Math.Abs(e.P0.X - e.P1.X) < Math.Abs(e.P0.Y - e.P1.Y)))\n            {\n                var x = (e.P0.X + e.P1.X) * 0.5;\n                return self.SetEdge(index, new Line2d(new V2d(x, e.P0.Y), new V2d(x, e.P1.Y)));\n            }\n            else\n            {\n                var y = (e.P0.Y + e.P1.Y) * 0.5;\n                return self.SetEdge(index, new Line2d(new V2d(e.P0.X, y), new V2d(e.P1.X, y)));\n            }\n        }\n\n        /// <summary>\n        /// Ensures that the outline is oriented counter-clockwise.\n        /// </summary>\n        public static IImmutablePolygon<V2d> ToCounterClockwise(this IImmutablePolygon<V2d> self)\n            => self.ToPolygon2d().IsCcw() ? self : new ImmutablePolygon<V2d>(self.Points.Reverse());\n\n        /// <summary>\n        /// Ensures that the outline is oriented clockwise.\n        /// </summary>\n        public static IImmutablePolygon<V2d> ToClockwise(this IImmutablePolygon<V2d> self)\n            => self.ToPolygon2d().IsCcw() ? new ImmutablePolygon<V2d>(self.Points.Reverse()) : self;\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/IImmutablePolygonExtensions_template.cs",
    "content": "﻿using System;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    public static class IImmutablePolygonExtensions\n    {\n        /// <summary>\n        /// Maps index into range [0, count).\n        /// </summary>\n        internal static int RepairIndex(int count, int index)\n        {\n            if (index >= 0)\n            {\n                return (index < count) ? index : (index % count);\n            }\n            else\n            {\n                if (index >= -count)\n                {\n                    return count + index;\n                }\n                else\n                {\n                    return count - 1 + (index + 1) % count;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Maps arbitrary index into valid range.\n        /// </summary>\n        public static int RepairIndex<T>(this IImmutablePolygon<T> self, int index)\n            => RepairIndex(self.Count, index);\n    }\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Circle2\" + tc;\n    //#   var type2 = \"Circle2\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var m33t = \"M33\" + tc;\n    //#   var box2t = \"Box2\" + tc;\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var line2t = \"Line2\" + tc;\n    //#   var polygon2t = \"Polygon2\" + tc;\n    //#   var polygon3t = \"Polygon3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    #region IImmutable__polygon2t__Extensions\n\n    /// <summary>\n    /// Extensions for IImmutablePolygon(of T).\n    /// </summary>\n    public static class IImmutable__polygon2t__Extensions\n    {\n        /// <summary>\n        /// Converts this IImmutablePolygon(of __v2t__) to a __polygon2t__.\n        /// </summary>\n        public static __polygon2t__ To__polygon2t__(this IImmutablePolygon<__v2t__> self)\n            => new __polygon2t__(self.Points);\n\n        /// <summary>\n        /// Returns the index and distance of the polygon's closest point to the given query point.\n        /// </summary>\n        public static Tuple<int, double> QueryNearestVertex(this IImmutablePolygon<__v2t__> self, __v2t__ queryPoint)\n        {\n            if (self.Count == 0) return null;\n\n            int bestIndex = 0;\n            double bestDist = double.MaxValue;\n            for (int i = 0; i < self.Count; i++)\n            {\n                var d = (queryPoint - self.Points[i]).LengthSquared;\n                if (d < bestDist) { bestDist = d; bestIndex = i; }\n            }\n\n            return Tuple.Create(bestIndex, bestDist.Sqrt());\n        }\n\n        /// <summary>\n        /// Returns new polygon with point moved. \n        /// </summary>\n        public static IImmutablePolygon<__v2t__> MovePoint(this IImmutablePolygon<__v2t__> self, int index, __v2t__ delta)\n            => self.SetPoint(index, self.Points[index] + delta);\n\n        /// <summary>\n        /// Returns new polygon with point transformed. \n        /// </summary>\n        public static IImmutablePolygon<__v2t__> TransformPoint(this IImmutablePolygon<__v2t__> self, int index, __m33t__ trafo)\n            => self.SetPoint(index, trafo.TransformPos(self.Points[index]));\n\n        /// <summary>\n        /// Gets the index-th edge of this polygon.\n        /// </summary>\n        public static __line2t__ GetEdge(this IImmutablePolygon<__v2t__> self, int index)\n        {\n            index = self.RepairIndex(index);\n            var p0 = self.Points[index++];\n            var p1 = self.Points[index < self.Count ? index : 0];\n            return new __line2t__(p0, p1);\n        }\n\n        /// <summary>\n        /// Sets the index-th edge of this polygon.\n        /// </summary>\n        public static IImmutablePolygon<__v2t__> SetEdge(this IImmutablePolygon<__v2t__> self, int index, __line2t__ edge)\n        {\n            index = self.RepairIndex(index);\n            var i0 = index++;\n            var i1 = index < self.Count ? index : 0;\n            return self.SetPoint(i0, edge.P0).SetPoint(i1, edge.P1);\n        }\n\n        /// <summary>\n        /// Maps arbitrary index into valid range.\n        /// </summary>\n        public static int RepairIndex(this __polygon2t__ self, int index)\n            => IImmutablePolygonExtensions.RepairIndex(self.PointCount, index);\n\n        /// <summary>\n        /// Maps arbitrary index into valid range.\n        /// </summary>\n        public static int RepairIndex(this __polygon3t__ self, int index)\n            => IImmutablePolygonExtensions.RepairIndex(self.PointCount, index);\n\n        /// <summary>\n        /// Makes index-th edge parallel to x- or y-axis.\n        /// </summary>\n        public static IImmutablePolygon<__v2t__> AlignEdge(this IImmutablePolygon<__v2t__> self, int index)\n        {\n            var e = self.GetEdge(index);\n\n            if ((Math.Abs(e.P0.X - e.P1.X) < Math.Abs(e.P0.Y - e.P1.Y)))\n            {\n                var x = (e.P0.X + e.P1.X) * 0.5;\n                return self.SetEdge(index, new __line2t__(new __v2t__(x, e.P0.Y), new __v2t__(x, e.P1.Y)));\n            }\n            else\n            {\n                var y = (e.P0.Y + e.P1.Y) * 0.5;\n                return self.SetEdge(index, new __line2t__(new __v2t__(e.P0.X, y), new __v2t__(e.P1.X, y)));\n            }\n        }\n\n        /// <summary>\n        /// Ensures that the outline is oriented counter-clockwise.\n        /// </summary>\n        public static IImmutablePolygon<__v2t__> ToCounterClockwise(this IImmutablePolygon<__v2t__> self)\n            => self.To__polygon2t__().IsCcw() ? self : new ImmutablePolygon<__v2t__>(self.Points.Reverse());\n\n        /// <summary>\n        /// Ensures that the outline is oriented clockwise.\n        /// </summary>\n        public static IImmutablePolygon<__v2t__> ToClockwise(this IImmutablePolygon<__v2t__> self)\n            => self.To__polygon2t__().IsCcw() ? new ImmutablePolygon<__v2t__>(self.Points.Reverse()) : self;\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/ImmutablePolygon.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Collections.Immutable;\nusing System.Globalization;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// An immutable polygon.\n    /// </summary>\n    public class ImmutablePolygon<T>: IImmutablePolygon<T>\n    {\n        /// <summary>\n        /// The empty polygon (no points).\n        /// </summary>\n        public static readonly IImmutablePolygon<T> Empty = new ImmutablePolygon<T>(Array.Empty<T>());\n\n        /// <summary>\n        /// Vertices.\n        /// </summary>\n        private readonly ImmutableList<T> m_ps = ImmutableList<T>.Empty;\n\n        /// <summary>\n        /// Creates an immutable polygon from given outline.\n        /// </summary>\n        public ImmutablePolygon(IEnumerable<T> outline)\n        {\n            if (outline == null) throw new ArgumentNullException();\n            m_ps = ImmutableList.CreateRange(outline);\n        }\n\n        /// <summary>\n        /// Creates an immutable polygon from given outline.\n        /// </summary>\n        public ImmutablePolygon(ImmutableList<T> outline)\n        {\n            m_ps = outline ?? throw new ArgumentNullException();\n        }\n\n        /// <summary>\n        /// Gets index-th point.\n        /// Index will be wrapped around if not in range [0, count).\n        /// </summary>\n        public T GetPoint(int index) => m_ps[this.RepairIndex(index)];\n\n        /// <summary>\n        /// Returns a string that represents the current object.\n        /// </summary>\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}]\", string.Join(\", \", m_ps.Select(x => x.ToString())));\n\n        #region IImmutablePolygon\n\n        /// <summary>\n        /// Polygon outline.\n        /// </summary>\n        public IReadOnlyList<T> Points => m_ps;\n\n        /// <summary>\n        /// Gets number of vertices.\n        /// </summary>\n        public int Count => m_ps.Count;\n\n        /// <summary>\n        /// Returns new polygon with point added.\n        /// </summary>\n        public IImmutablePolygon<T> AddPoint(T p)\n            => new ImmutablePolygon<T>(m_ps.Add(p));\n\n        /// <summary>\n        /// Returns new polygon with points added.\n        /// </summary>\n        public IImmutablePolygon<T> AddPoints(IEnumerable<T> points)\n            => new ImmutablePolygon<T>(m_ps.AddRange(points));\n\n        /// <summary>\n        /// Returns new polygon with point replaced.\n        /// </summary>\n        public IImmutablePolygon<T> SetPoint(int index, T p)\n            => new ImmutablePolygon<T>(m_ps.SetItem(index, p));\n\n        /// <summary>\n        /// Returns new polygon with point p inserted at given index.\n        /// </summary>\n        public IImmutablePolygon<T> InsertPoint(int index, T p)\n            => new ImmutablePolygon<T>(m_ps.Insert(index, p));\n\n        /// <summary>\n        /// Returns new polygon with point removed.\n        /// </summary>\n        public IImmutablePolygon<T> RemovePoint(int index)\n            => new ImmutablePolygon<T>(m_ps.RemoveAt(index));\n\n        /// <summary>\n        /// Returns new polygon with points removed.\n        /// </summary>\n        public IImmutablePolygon<T> RemovePoints(IEnumerable<int> indexes)\n        {\n            var builder = m_ps.ToBuilder();\n            foreach (var index in indexes.OrderByDescending(i => i))\n            {\n                builder.RemoveAt(index);\n            }\n            return new ImmutablePolygon<T>(builder.ToImmutable());\n        }\n\n        /// <summary>\n        /// Returns new polygon with transformed points.\n        /// </summary>\n        public IImmutablePolygon<U> Transform<U>(Func<T, U> transform)\n            => new ImmutablePolygon<U>(m_ps.Select(x => transform(x)));\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/Polygon2_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Polygon2fExtensions\n\n    public static partial class Polygon2fExtensions\n    {\n        #region Conversions\n\n        public static Polygon2f ToPolygon2fCCW(this Box2f self)\n            => new Polygon2f(self.Min, new V2f(self.Max.X, self.Min.Y), self.Max, new V2f(self.Min.X, self.Max.Y));\n\n        public static Polygon3f ToPolygon3f(this Polygon2f polygon, Func<V2f, V3f> point_copyFun)\n            => new Polygon3f(polygon.GetPointArray(point_copyFun));\n\n        public static Polygon3f ToPolygon3f(this Polygon2f polygon, Func<V2f, int, V3f> point_index_copyFun)\n            => new Polygon3f(polygon.GetPointArray(point_index_copyFun));\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a 2d polygon into 3d.\n        /// The z-coordinate is assumed to be zero.\n        /// </summary>\n        public static Polygon3f Transformed(this Polygon2f polygon, M44f transform)\n        {\n            return new Polygon3f(polygon.GetPointArray(p => transform.TransformPos(p.XYO)));\n        }\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// The geometric center of the polygon.\n        /// </summary>\n        public static V2f ComputeCentroid(this Polygon2f polygon)\n        {\n            var pc = polygon.PointCount;\n            float area = 0;\n            var centroid = V2f.Zero;\n\n            // signed area as weight for center of edge line\n            var p0 = polygon[pc - 1];\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                var a = p0.X * p1.Y - p0.Y * p1.X;\n                area += a;\n                centroid += (p0 + p1) * a; // center point would be /2\n                p0 = p1;\n            }\n\n            area *= 0.5f; // /2 moved outside loop\n            return area > 0 ? centroid / (area * 6) : V2f.Zero; // normalization by area/6\n        }\n\n        /// <summary>\n        /// Computes the area of the polygon according to\n        /// \"Fast Polygon Area and Newell Normal Computation\"\n        ///  journal of graphics tools, 7(2):9-13, 2002\n        /// </summary>\n        public static float ComputeSignedArea(this Polygon2f polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return 0;\n            float area = polygon[pc - 1].X * (polygon[0].Y - polygon[pc - 2].Y);\n            area += polygon[0].X * (polygon[1].Y - polygon[pc - 1].Y);\n            for (int pi = 2; pi < pc; pi++)\n                area += polygon[pi - 1].X * (polygon[pi].Y - polygon[pi - 2].Y);\n            return area / 2;\n        }\n\n        /// <summary>\n        /// Computes the area of the polygon according to\n        /// \"Fast Polygon Area and Newell Normal Computation\"\n        ///  journal of graphics tools, 7(2):9-13, 2002. The\n        ///  absolute value is returned (i.e. area >= 0.0).\n        /// </summary>\n        public static float ComputeArea(this Polygon2f polygon)\n            => polygon.ComputeSignedArea().Abs();\n\n        /// <summary>\n        /// Returns the rotation of the supplied counter clockwise enumerated\n        /// convex polygon that results in the minimum area enclosing box.\n        /// If multiple rotations are within epsilon in their area, the one\n        /// that is closest to an axis-aligned rotation (0, 90, 180, 270) is\n        /// returned. O(n).\n        /// </summary>\n        public static M22f ComputeMinAreaEnclosingBoxRotation(\n                this Polygon2f polygon, float epsilon = 1e-4f)\n        {\n            polygon = polygon.WithoutMultiplePoints(epsilon);\n            var pc = polygon.PointCount;\n\n            if (pc < 2) return M22f.Identity;\n            var ea = polygon.GetEdgeArray();\n            ea.Apply(v => v.Normalized);\n\n            int i0 = 0, i1 = 0;\n            int i2 = 0, i3 = 0;\n            var min = polygon[0]; var max = polygon[0];\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p = polygon[pi];\n                if (p.Y < min.Y) { i0 = pi; min.Y = p.Y; }\n                else if (p.Y > max.Y) { i2 = pi; max.Y = p.Y; }\n                if (p.X > max.X) { i1 = pi; max.X = p.X; }\n                else if (p.X < min.X) { i3 = pi; min.X = p.X; }\n            }\n\n            V2f p0 = polygon[i0], e0 = ea[i0], p1 = polygon[i1], e1 = ea[i1];\n            V2f p2 = polygon[i2], e2 = ea[i2], p3 = polygon[i3], e3 = ea[i3];\n\n            int end0 = (i0 + 1) % pc, end1 = (i1 + 1) % pc;\n            int end2 = (i2 + 1) % pc, end3 = (i3 + 1) % pc;\n            var dir = V2f.XAxis;\n\n            var best = dir;\n            var bestArea = float.MaxValue;\n            var bestValue = float.MaxValue;\n            while (true)\n            {\n                var s0 = Fun.FastAtan2(e0.Dot90(dir), e0.Dot(dir));\n                var s1 = Fun.FastAtan2(e1.Dot180(dir), e1.Dot90(dir));\n                var s2 = Fun.FastAtan2(e2.Dot270(dir), e2.Dot180(dir));\n                var s3 = Fun.FastAtan2(e3.Dot(dir), e3.Dot270(dir));\n\n                int si, si01, si23; float s01, s23;\n                if (s0 < s1) { s01 = s0; si01 = 0; } else { s01 = s1; si01 = 1; }\n                if (s2 < s3) { s23 = s2; si23 = 2; } else { s23 = s3; si23 = 3; }\n                if (s01 < s23) { si = si01; } else { si = si23; }\n\n                if (si == 0) dir = ea[i0];\n                else if (si == 1) dir = ea[i1].Rot270;\n                else if (si == 2) dir = ea[i2].Rot180;\n                else dir = ea[i3].Rot90;\n\n                float sx = (p2 - p0).Dot90(dir), sy = (p1 - p3).Dot(dir);\n                float area = sx * sy;\n                float value = Fun.Min(Fun.Abs(dir.X), Fun.Abs(dir.Y));\n\n                if (area < bestArea - epsilon\n                    || (area < bestArea + epsilon && value < bestValue))\n                {\n                    bestArea = area; bestValue = value; best = dir;\n                }\n\n                if (si == 0)\n                {\n                    if (++i0 >= pc) i0 -= pc;\n                    if (i0 == end1) break;\n                    p0 = polygon[i0]; e0 = ea[i0];\n                }\n                else if (si == 1)\n                {\n                    if (++i1 >= pc) i1 -= pc;\n                    if (i1 == end2) break;\n                    p1 = polygon[i1]; e1 = ea[i1];\n                }\n                else if (si == 2)\n                {\n                    if (++i2 >= pc) i2 -= pc;\n                    if (i2 == end3) break;\n                    p2 = polygon[i2]; e2 = ea[i2];\n                }\n                else\n                {\n                    if (++i3 >= pc) i3 -= pc;\n                    if (i3 == end0) break;\n                    p3 = polygon[i3]; e3 = ea[i3];\n                }\n            }\n            return new M22f(best.X, best.Y, -best.Y, best.X);\n        }\n\n        /// <summary>\n        /// Gets oriented bounding box of this polygon\n        /// </summary>\n        public static Polygon2f ComputeOrientedBoundingBox(this Polygon2f polygon)\n        {\n            var rot = polygon.ComputeMinAreaEnclosingBoxRotation();\n            var rotInv = rot.Transposed;\n            var bbGlobal = new Box2f(polygon.Points.Select(p => rot * p));\n            return new Polygon2f(bbGlobal.ComputeCornersCCW().Apply(p => rotInv * p));\n        }\n        \n        /// <summary>\n        /// Computes the winding number of the polyon.\n        /// The winding number is positive for counter-\n        /// clockwise polygons, negative for clockwise polygons.\n        /// </summary>\n        public static int ComputeWindingNumber(this Polygon2f polygon)\n        {\n            int pc = polygon.PointCount;\n            V2f e = polygon[0] - polygon[pc - 1];\n            var a = Fun.Atan2(e.Y, e.X);\n            var a0 = a;\n            var radians = 0.0;\n            for (int pi = 0; pi < pc - 1; pi++)\n            {\n                V2f e1 = polygon[pi + 1] - polygon[pi];\n                var a1 = Fun.Atan2(e1.Y, e1.X);\n                var alpha = a1 - a0;\n                if (alpha >= ConstantF.Pi) alpha -= ConstantF.PiTimesTwo;\n                else if (alpha < -ConstantF.Pi) alpha += ConstantF.PiTimesTwo;\n                radians += alpha;\n                a0 = a1;\n            }\n            var alpha0 = a - a0;\n            if (alpha0 >= ConstantF.Pi) alpha0 -= ConstantF.PiTimesTwo;\n            else if (alpha0 < -ConstantF.Pi) alpha0 += ConstantF.PiTimesTwo;\n            radians += alpha0;\n\n            var winding = radians >= 0\n                ? (int)((ConstantF.Pi + radians) / ConstantF.PiTimesTwo)\n                : -(int)((ConstantF.Pi - radians) / ConstantF.PiTimesTwo);\n\n            return winding;\n        }\n\n        private const int V = 1;\n        private static readonly Func<V2f, V2f, bool> c_ccwFun = (a, b) => (a.X * b.Y - a.Y * b.X) >= 0;\n        private static readonly Func<V2f, V2f, bool> c_cwFun = (a, b) => (a.X * b.Y - a.Y * b.X) <= 0;\n\n        /// <summary>\n        /// Check if a polygon has a specified winding.\n        /// </summary>\n        public static bool HasWinding(\n                this Polygon2f polygon, Winding winding)\n        {\n            var winFun = winding == Winding.CCW ? c_ccwFun : c_cwFun;\n            var ef = polygon.Edge(0);\n            var e0 = polygon.Edge(1);\n            var orientation = winFun(ef, e0);\n            for (int i = 2; i < polygon.PointCount; i++)\n            {\n                var e1 = polygon.Edge(i);\n                if (winFun(e0, e1) != orientation) return false;\n                e0 = e1;\n            }\n            return winFun(e0, ef) == orientation;\n        }\n\n        /// <summary>\n        /// Returns true if polygon points are oriented in counter-clockwise order.\n        /// </summary>\n        public static bool IsCcw(this Polygon2f polygon) => polygon.ComputeWindingNumber() >= 0;\n\n        public static bool IsConcave(this Polygon2f polygon) => polygon.HasWinding(Winding.CW);\n\n        public static bool IsConvex(this Polygon2f polygon) => polygon.HasWinding(Winding.CCW);\n\n        #endregion\n\n        #region Convex Hull\n\n        /// <summary>\n        /// Returns convex hull of this polygon.\n        /// </summary>\n        public static IndexPolygon2f ComputeConvexHullIndexPolygon(this Polygon2f polygon)\n            => polygon.m_pointArray.ConvexHullIndexPolygon(polygon.m_pointCount);\n\n        #endregion\n\n        #region Intersection\n\n        /// <summary>\n        /// Returns:\n        ///      1 if the Polygon created by poly has no self-intersections\n        ///      0 if one point of the polygon lies close to a line (absoluteEpsilon)\n        ///     -1 if the Polygon created by poly has a real self-intersection\n        /// </summary>\n        public static int HasSelfIntersections(\n                this Polygon2f poly, float absoluteEpsilon)\n        {\n            var pointCount = poly.PointCount;\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n            int worst = V;\n            V2f n0;\n\n            //Triangles cannot have self-intersections\n            if (pointCount == 3) return 1;\n\n            Line2f line;\n            int i;\n            for (i = 0; i < pointCount - 1; i++)\n            {\n                //line between i and i+1\n                line = new Line2f(poly[i], poly[i + 1]);\n                n0 = line.Direction.Normalized;\n                n0 = new V2f(-n0.Y, n0.X);\n\n\n                for (int u = i + 2; u < pointCount && (u + 1) % pointCount != i; u++)\n                {\n                    //Polygon not degenerated -> Line cannot intersect with line directly before and directly after\n                    //All lines prior to (u,u1) have already been tested with (i,i+1)\n                    int u1 = (u + 1) % pointCount;\n\n                    if (line.IntersectsLine(poly[u], poly[u1]))\n                    {\n                        //One Point of (u,u1) lies on line (within absoluteEpsilon)\n                        if (n0.Dot(poly[u1] - line.P0).Abs() < absoluteEpsilon || n0.Dot(poly[u] - line.P0).Abs() < absoluteEpsilon)\n                        {\n                            worst = 0;\n                        }\n                        else return -1;\n                    }\n                }\n            }\n\n            return worst;\n        }\n\n        /// <summary>\n        /// Returns true if this polygon is fully contained inside the 'other' polygon.\n        /// </summary>\n        public static bool IsFullyContainedInside(this Polygon2f self, Polygon2f other)\n        {\n            // check if all my vertices are inside the other polygon\n            foreach (var v in self.Points)\n            {\n                if (!other.Contains(v)) return false;\n            }\n\n            // check if all my edges do NOT intersect with edges of the other polygon\n            foreach (var e in self.EdgeLines)\n            {\n                foreach (var x in other.EdgeLines)\n                {\n                    if (x.Intersects(e)) return false;\n                }\n            }\n\n            // :-)\n            return true;\n        }\n\n        #endregion\n\n        #region Relations\n\n        /// <summary>\n        /// Returns the minimal distance between the polygon and the\n        /// other supplied polygon. O(n).\n        /// </summary>\n        public static float MinDistanceTo(this Polygon2f polygon, Polygon2f polygon1)\n            => polygon.MinDistanceTo(polygon1, out _, out _, out _);\n\n        /// <summary>\n        /// Returns the minimal distance between the polygon and the non-\n        /// overlapping other supplied polygon. The minimal distance is\n        /// always computed as the distance between a line segment and a\n        /// point. The indices of the minimal distance configuration are\n        /// returned in the out parameter, as the indices of points on the\n        /// two polygons, and wether the line segement was on this or the\n        /// other polygon. O(n). The returned index of the line segment is\n        /// the lower point index (except in case of wraparound).\n        /// </summary>\n        public static float MinDistanceTo(\n                this Polygon2f polygon, Polygon2f polygon1,\n                out int pi0, out int pi1, out bool lineOnThis)\n        {\n            var p0a = polygon.m_pointArray;\n            var p1a = polygon1.m_pointArray;\n            var p0c = polygon.m_pointCount;\n            var p1c = polygon1.m_pointCount;\n            var e0a = polygon.GetEdgeArray();\n            var e1a = polygon1.GetEdgeArray();\n            int i0 = p0a.IndexOfMinY(p0c), i1 = p1a.IndexOfMaxY(p1c);\n            V2f p0 = p0a[i0], e0 = e0a[i0], p1 = p1a[i1], e1 = e1a[i1];\n\n            int start0 = i0, start1 = i1;\n            var dir = V2f.XAxis;\n            var d = Vec.Distance(p0, p1);\n\n            var bestValue = float.MaxValue;\n            int bpi0 = -1, bpi1 = -1;\n            var bLineOnThis = true;\n\n            do\n            {\n                var s0 = Fun.Atan2(e0.Dot90(dir), e0.Dot(dir));\n                var s1 = Fun.Atan2(e1.Dot270(dir), e1.Dot180(dir));\n                if (s0 <= s1)\n                {\n                    dir = e0a[i0];\n                    int i0n = (i0 + 1) % p0c; var p0n = p0a[i0];\n                    var dn = Vec.Distance(p0n, p1);\n                    var dist = DistanceToLine(p1, p0, p0n, d, dn);\n                    if (dist < bestValue)\n                    {\n                        bestValue = dist;\n                        bLineOnThis = true; bpi0 = i0; bpi1 = i1;\n                    }\n                    i0 = i0n; p0 = p0n; e0 = e0a[i0]; d = dn;\n                }\n                else\n                {\n                    dir = e0a[i1].Rot180;\n                    int i1n = (i1 + 1) % p1c; var p1n = p1a[i1];\n                    var dn = Vec.Distance(p0, p1n);\n                    var dist = DistanceToLine(p0, p1, p1n, d, dn);\n                    if (dist < bestValue)\n                    {\n                        bestValue = dist;\n                        bLineOnThis = false; bpi0 = i0; bpi1 = i1;\n                    }\n                    i1 = i1n; p1 = p1n; e1 = e1a[i1]; d = dn;\n                }\n            }\n            while (i0 != start0 || i1 != start1);\n            lineOnThis = bLineOnThis; pi0 = bpi0; pi1 = bpi1;\n            return bestValue;\n        }\n\n        private static float DistanceToLine(V2f query, V2f p0, V2f p1, float d0, float d1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Vec.Dot(p0q, p0p1);\n            if (t <= 0) { return d0; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return d1; }\n            t /= denom;\n            return Vec.Distance(query, p0 + t * p0p1);\n        }\n\n        #endregion\n\n        #region Degenerated parts of a Polygon2f\n\n        #region Polygon2f-Extensions\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2f poly)\n            => poly.PolygonHasDegeneratedPart();\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2f poly, float absoluteEpsilon)\n            => poly.PolygonHasDegeneratedPart(absoluteEpsilon);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2f poly, out Polygon2f NonDegenerated)\n        {\n            bool result = poly.PolygonHasDegeneratedPart(out int[] temp);\n            NonDegenerated = new Polygon2f((from i in temp select poly[i]).ToArray<V2f>());\n            return result;\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2f poly, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(out NonDegenerated);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2f poly, float absoluteEpsilon, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(absoluteEpsilon, out NonDegenerated);\n\n        #endregion\n\n        #region V2f[]-Extension\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this Polygon2f poly)\n            => poly.PolygonHasDegeneratedPart(4 * float.Epsilon);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this Polygon2f poly, float absoluteEpsilon)\n        {\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n\n            int i = 0;\n            int count = poly.PointCount;\n\n            V2f e0;\n            V2f e1;\n\n            float l0 = 0;\n            float l1 = 0;\n\n            while (i < count - 1)\n            {\n                if ((poly[i + 1] - poly[i]).Length < absoluteEpsilon) return true;\n\n                e0 = (poly[i + 1] - poly[i]);\n                e1 = (poly[(i + 2) % count] - poly[i + 1]);\n\n                l0 = e0.Length;\n                l1 = e1.Length;\n\n                e0 = e0 / l0;\n                //e1 = e1 / l1;\n\n                if ((e0.X * e1.Y - e0.Y * e1.X).Abs() > absoluteEpsilon) return true;\n            }\n\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this Polygon2f poly, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(4 * float.Epsilon, out NonDegenerated);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this Polygon2f poly, float absoluteEpsilon, out int[] NonDegenerated)\n        {\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n\n            int i = 0;\n            int u = 1;\n            int start = 0;\n            V2f e0;\n            V2f e1;\n            bool found = false;\n            int count = poly.PointCount;\n\n            List<int> newPoints = new List<int>();\n            newPoints.Add(0);\n\n            float l0 = 0;\n\n            while (i < count - 1)\n            {\n                e0 = (poly[i + 1] - poly[i]);\n                l0 = e0.Length;\n\n                e0 = e0 / l0;\n\n                u = i + 1;\n                V2f e = poly[(u + 1) % count] - poly[u];\n                while (\n                    (((e0.X * e.Y - e0.Y * e.X).Abs() < absoluteEpsilon && e.Dot(e0) > 0) ||\n                    (poly[(u + 1) % count] - poly[i + 1]).Length < absoluteEpsilon)\n                    && u < count - 1)\n                {\n                    if ((poly[(u + 1) % count] - poly[i + 1]).Length < absoluteEpsilon) found = true;\n\n                    u++;\n                    e0 = (poly[u] - poly[i]).Normalized;\n                    e = poly[(u + 1) % count] - poly[u];\n                }\n                u--;\n\n                start = u;\n\n                do\n                {\n                    u++;\n                    e1 = (poly[(u + 1) % count] - poly[u]);\n                }\n                while (u < count && ((e0.X * e1.Y - e0.Y * e1.X).Abs() < absoluteEpsilon && e.Dot(e0) < 0));\n\n                if (u != start + 1) found = true;\n\n                newPoints.Add(u);\n\n                i = u;\n            }\n\n            NonDegenerated = newPoints.ToArray();\n            return found;\n        }\n\n        #endregion\n\n        #endregion\n    }\n\n    public static partial class IndexPolygon2fExtensions\n    {\n        #region Conversions\n\n        public static Polygon3f ToPolygon3f(this IndexPolygon2f polygon, V3f[] pointArray)\n            => new Polygon3f(polygon.GetPointArray(pointArray));\n\n        public static Polygon3f ToPolygon3f(this IndexPolygon2f polygon, List<V3f> pointList)\n            => new Polygon3f(polygon.GetPointArray(pointList));\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Polygon2dExtensions\n\n    public static partial class Polygon2dExtensions\n    {\n        #region Conversions\n\n        public static Polygon2d ToPolygon2dCCW(this Box2d self)\n            => new Polygon2d(self.Min, new V2d(self.Max.X, self.Min.Y), self.Max, new V2d(self.Min.X, self.Max.Y));\n\n        public static Polygon3d ToPolygon3d(this Polygon2d polygon, Func<V2d, V3d> point_copyFun)\n            => new Polygon3d(polygon.GetPointArray(point_copyFun));\n\n        public static Polygon3d ToPolygon3d(this Polygon2d polygon, Func<V2d, int, V3d> point_index_copyFun)\n            => new Polygon3d(polygon.GetPointArray(point_index_copyFun));\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a 2d polygon into 3d.\n        /// The z-coordinate is assumed to be zero.\n        /// </summary>\n        public static Polygon3d Transformed(this Polygon2d polygon, M44d transform)\n        {\n            return new Polygon3d(polygon.GetPointArray(p => transform.TransformPos(p.XYO)));\n        }\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// The geometric center of the polygon.\n        /// </summary>\n        public static V2d ComputeCentroid(this Polygon2d polygon)\n        {\n            var pc = polygon.PointCount;\n            double area = 0;\n            var centroid = V2d.Zero;\n\n            // signed area as weight for center of edge line\n            var p0 = polygon[pc - 1];\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                var a = p0.X * p1.Y - p0.Y * p1.X;\n                area += a;\n                centroid += (p0 + p1) * a; // center point would be /2\n                p0 = p1;\n            }\n\n            area *= 0.5; // /2 moved outside loop\n            return area > 0 ? centroid / (area * 6) : V2d.Zero; // normalization by area/6\n        }\n\n        /// <summary>\n        /// Computes the area of the polygon according to\n        /// \"Fast Polygon Area and Newell Normal Computation\"\n        ///  journal of graphics tools, 7(2):9-13, 2002\n        /// </summary>\n        public static double ComputeSignedArea(this Polygon2d polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return 0;\n            double area = polygon[pc - 1].X * (polygon[0].Y - polygon[pc - 2].Y);\n            area += polygon[0].X * (polygon[1].Y - polygon[pc - 1].Y);\n            for (int pi = 2; pi < pc; pi++)\n                area += polygon[pi - 1].X * (polygon[pi].Y - polygon[pi - 2].Y);\n            return area / 2;\n        }\n\n        /// <summary>\n        /// Computes the area of the polygon according to\n        /// \"Fast Polygon Area and Newell Normal Computation\"\n        ///  journal of graphics tools, 7(2):9-13, 2002. The\n        ///  absolute value is returned (i.e. area >= 0.0).\n        /// </summary>\n        public static double ComputeArea(this Polygon2d polygon)\n            => polygon.ComputeSignedArea().Abs();\n\n        /// <summary>\n        /// Returns the rotation of the supplied counter clockwise enumerated\n        /// convex polygon that results in the minimum area enclosing box.\n        /// If multiple rotations are within epsilon in their area, the one\n        /// that is closest to an axis-aligned rotation (0, 90, 180, 270) is\n        /// returned. O(n).\n        /// </summary>\n        public static M22d ComputeMinAreaEnclosingBoxRotation(\n                this Polygon2d polygon, double epsilon = 1e-6)\n        {\n            polygon = polygon.WithoutMultiplePoints(epsilon);\n            var pc = polygon.PointCount;\n\n            if (pc < 2) return M22d.Identity;\n            var ea = polygon.GetEdgeArray();\n            ea.Apply(v => v.Normalized);\n\n            int i0 = 0, i1 = 0;\n            int i2 = 0, i3 = 0;\n            var min = polygon[0]; var max = polygon[0];\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p = polygon[pi];\n                if (p.Y < min.Y) { i0 = pi; min.Y = p.Y; }\n                else if (p.Y > max.Y) { i2 = pi; max.Y = p.Y; }\n                if (p.X > max.X) { i1 = pi; max.X = p.X; }\n                else if (p.X < min.X) { i3 = pi; min.X = p.X; }\n            }\n\n            V2d p0 = polygon[i0], e0 = ea[i0], p1 = polygon[i1], e1 = ea[i1];\n            V2d p2 = polygon[i2], e2 = ea[i2], p3 = polygon[i3], e3 = ea[i3];\n\n            int end0 = (i0 + 1) % pc, end1 = (i1 + 1) % pc;\n            int end2 = (i2 + 1) % pc, end3 = (i3 + 1) % pc;\n            var dir = V2d.XAxis;\n\n            var best = dir;\n            var bestArea = double.MaxValue;\n            var bestValue = double.MaxValue;\n            while (true)\n            {\n                var s0 = Fun.FastAtan2(e0.Dot90(dir), e0.Dot(dir));\n                var s1 = Fun.FastAtan2(e1.Dot180(dir), e1.Dot90(dir));\n                var s2 = Fun.FastAtan2(e2.Dot270(dir), e2.Dot180(dir));\n                var s3 = Fun.FastAtan2(e3.Dot(dir), e3.Dot270(dir));\n\n                int si, si01, si23; double s01, s23;\n                if (s0 < s1) { s01 = s0; si01 = 0; } else { s01 = s1; si01 = 1; }\n                if (s2 < s3) { s23 = s2; si23 = 2; } else { s23 = s3; si23 = 3; }\n                if (s01 < s23) { si = si01; } else { si = si23; }\n\n                if (si == 0) dir = ea[i0];\n                else if (si == 1) dir = ea[i1].Rot270;\n                else if (si == 2) dir = ea[i2].Rot180;\n                else dir = ea[i3].Rot90;\n\n                double sx = (p2 - p0).Dot90(dir), sy = (p1 - p3).Dot(dir);\n                double area = sx * sy;\n                double value = Fun.Min(Fun.Abs(dir.X), Fun.Abs(dir.Y));\n\n                if (area < bestArea - epsilon\n                    || (area < bestArea + epsilon && value < bestValue))\n                {\n                    bestArea = area; bestValue = value; best = dir;\n                }\n\n                if (si == 0)\n                {\n                    if (++i0 >= pc) i0 -= pc;\n                    if (i0 == end1) break;\n                    p0 = polygon[i0]; e0 = ea[i0];\n                }\n                else if (si == 1)\n                {\n                    if (++i1 >= pc) i1 -= pc;\n                    if (i1 == end2) break;\n                    p1 = polygon[i1]; e1 = ea[i1];\n                }\n                else if (si == 2)\n                {\n                    if (++i2 >= pc) i2 -= pc;\n                    if (i2 == end3) break;\n                    p2 = polygon[i2]; e2 = ea[i2];\n                }\n                else\n                {\n                    if (++i3 >= pc) i3 -= pc;\n                    if (i3 == end0) break;\n                    p3 = polygon[i3]; e3 = ea[i3];\n                }\n            }\n            return new M22d(best.X, best.Y, -best.Y, best.X);\n        }\n\n        /// <summary>\n        /// Gets oriented bounding box of this polygon\n        /// </summary>\n        public static Polygon2d ComputeOrientedBoundingBox(this Polygon2d polygon)\n        {\n            var rot = polygon.ComputeMinAreaEnclosingBoxRotation();\n            var rotInv = rot.Transposed;\n            var bbGlobal = new Box2d(polygon.Points.Select(p => rot * p));\n            return new Polygon2d(bbGlobal.ComputeCornersCCW().Apply(p => rotInv * p));\n        }\n        \n        /// <summary>\n        /// Computes the winding number of the polyon.\n        /// The winding number is positive for counter-\n        /// clockwise polygons, negative for clockwise polygons.\n        /// </summary>\n        public static int ComputeWindingNumber(this Polygon2d polygon)\n        {\n            int pc = polygon.PointCount;\n            V2d e = polygon[0] - polygon[pc - 1];\n            var a = Fun.Atan2(e.Y, e.X);\n            var a0 = a;\n            var radians = 0.0;\n            for (int pi = 0; pi < pc - 1; pi++)\n            {\n                V2d e1 = polygon[pi + 1] - polygon[pi];\n                var a1 = Fun.Atan2(e1.Y, e1.X);\n                var alpha = a1 - a0;\n                if (alpha >= Constant.Pi) alpha -= Constant.PiTimesTwo;\n                else if (alpha < -Constant.Pi) alpha += Constant.PiTimesTwo;\n                radians += alpha;\n                a0 = a1;\n            }\n            var alpha0 = a - a0;\n            if (alpha0 >= Constant.Pi) alpha0 -= Constant.PiTimesTwo;\n            else if (alpha0 < -Constant.Pi) alpha0 += Constant.PiTimesTwo;\n            radians += alpha0;\n\n            var winding = radians >= 0\n                ? (int)((Constant.Pi + radians) / Constant.PiTimesTwo)\n                : -(int)((Constant.Pi - radians) / Constant.PiTimesTwo);\n\n            return winding;\n        }\n\n        private const int V = 1;\n        private static readonly Func<V2d, V2d, bool> c_ccwFun = (a, b) => (a.X * b.Y - a.Y * b.X) >= 0;\n        private static readonly Func<V2d, V2d, bool> c_cwFun = (a, b) => (a.X * b.Y - a.Y * b.X) <= 0;\n\n        /// <summary>\n        /// Check if a polygon has a specified winding.\n        /// </summary>\n        public static bool HasWinding(\n                this Polygon2d polygon, Winding winding)\n        {\n            var winFun = winding == Winding.CCW ? c_ccwFun : c_cwFun;\n            var ef = polygon.Edge(0);\n            var e0 = polygon.Edge(1);\n            var orientation = winFun(ef, e0);\n            for (int i = 2; i < polygon.PointCount; i++)\n            {\n                var e1 = polygon.Edge(i);\n                if (winFun(e0, e1) != orientation) return false;\n                e0 = e1;\n            }\n            return winFun(e0, ef) == orientation;\n        }\n\n        /// <summary>\n        /// Returns true if polygon points are oriented in counter-clockwise order.\n        /// </summary>\n        public static bool IsCcw(this Polygon2d polygon) => polygon.ComputeWindingNumber() >= 0;\n\n        public static bool IsConcave(this Polygon2d polygon) => polygon.HasWinding(Winding.CW);\n\n        public static bool IsConvex(this Polygon2d polygon) => polygon.HasWinding(Winding.CCW);\n\n        #endregion\n\n        #region Convex Hull\n\n        /// <summary>\n        /// Returns convex hull of this polygon.\n        /// </summary>\n        public static IndexPolygon2d ComputeConvexHullIndexPolygon(this Polygon2d polygon)\n            => polygon.m_pointArray.ConvexHullIndexPolygon(polygon.m_pointCount);\n\n        #endregion\n\n        #region Intersection\n\n        /// <summary>\n        /// Returns:\n        ///      1 if the Polygon created by poly has no self-intersections\n        ///      0 if one point of the polygon lies close to a line (absoluteEpsilon)\n        ///     -1 if the Polygon created by poly has a real self-intersection\n        /// </summary>\n        public static int HasSelfIntersections(\n                this Polygon2d poly, double absoluteEpsilon)\n        {\n            var pointCount = poly.PointCount;\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n            int worst = V;\n            V2d n0;\n\n            //Triangles cannot have self-intersections\n            if (pointCount == 3) return 1;\n\n            Line2d line;\n            int i;\n            for (i = 0; i < pointCount - 1; i++)\n            {\n                //line between i and i+1\n                line = new Line2d(poly[i], poly[i + 1]);\n                n0 = line.Direction.Normalized;\n                n0 = new V2d(-n0.Y, n0.X);\n\n\n                for (int u = i + 2; u < pointCount && (u + 1) % pointCount != i; u++)\n                {\n                    //Polygon not degenerated -> Line cannot intersect with line directly before and directly after\n                    //All lines prior to (u,u1) have already been tested with (i,i+1)\n                    int u1 = (u + 1) % pointCount;\n\n                    if (line.IntersectsLine(poly[u], poly[u1]))\n                    {\n                        //One Point of (u,u1) lies on line (within absoluteEpsilon)\n                        if (n0.Dot(poly[u1] - line.P0).Abs() < absoluteEpsilon || n0.Dot(poly[u] - line.P0).Abs() < absoluteEpsilon)\n                        {\n                            worst = 0;\n                        }\n                        else return -1;\n                    }\n                }\n            }\n\n            return worst;\n        }\n\n        /// <summary>\n        /// Returns true if this polygon is fully contained inside the 'other' polygon.\n        /// </summary>\n        public static bool IsFullyContainedInside(this Polygon2d self, Polygon2d other)\n        {\n            // check if all my vertices are inside the other polygon\n            foreach (var v in self.Points)\n            {\n                if (!other.Contains(v)) return false;\n            }\n\n            // check if all my edges do NOT intersect with edges of the other polygon\n            foreach (var e in self.EdgeLines)\n            {\n                foreach (var x in other.EdgeLines)\n                {\n                    if (x.Intersects(e)) return false;\n                }\n            }\n\n            // :-)\n            return true;\n        }\n\n        #endregion\n\n        #region Relations\n\n        /// <summary>\n        /// Returns the minimal distance between the polygon and the\n        /// other supplied polygon. O(n).\n        /// </summary>\n        public static double MinDistanceTo(this Polygon2d polygon, Polygon2d polygon1)\n            => polygon.MinDistanceTo(polygon1, out _, out _, out _);\n\n        /// <summary>\n        /// Returns the minimal distance between the polygon and the non-\n        /// overlapping other supplied polygon. The minimal distance is\n        /// always computed as the distance between a line segment and a\n        /// point. The indices of the minimal distance configuration are\n        /// returned in the out parameter, as the indices of points on the\n        /// two polygons, and wether the line segement was on this or the\n        /// other polygon. O(n). The returned index of the line segment is\n        /// the lower point index (except in case of wraparound).\n        /// </summary>\n        public static double MinDistanceTo(\n                this Polygon2d polygon, Polygon2d polygon1,\n                out int pi0, out int pi1, out bool lineOnThis)\n        {\n            var p0a = polygon.m_pointArray;\n            var p1a = polygon1.m_pointArray;\n            var p0c = polygon.m_pointCount;\n            var p1c = polygon1.m_pointCount;\n            var e0a = polygon.GetEdgeArray();\n            var e1a = polygon1.GetEdgeArray();\n            int i0 = p0a.IndexOfMinY(p0c), i1 = p1a.IndexOfMaxY(p1c);\n            V2d p0 = p0a[i0], e0 = e0a[i0], p1 = p1a[i1], e1 = e1a[i1];\n\n            int start0 = i0, start1 = i1;\n            var dir = V2d.XAxis;\n            var d = Vec.Distance(p0, p1);\n\n            var bestValue = double.MaxValue;\n            int bpi0 = -1, bpi1 = -1;\n            var bLineOnThis = true;\n\n            do\n            {\n                var s0 = Fun.Atan2(e0.Dot90(dir), e0.Dot(dir));\n                var s1 = Fun.Atan2(e1.Dot270(dir), e1.Dot180(dir));\n                if (s0 <= s1)\n                {\n                    dir = e0a[i0];\n                    int i0n = (i0 + 1) % p0c; var p0n = p0a[i0];\n                    var dn = Vec.Distance(p0n, p1);\n                    var dist = DistanceToLine(p1, p0, p0n, d, dn);\n                    if (dist < bestValue)\n                    {\n                        bestValue = dist;\n                        bLineOnThis = true; bpi0 = i0; bpi1 = i1;\n                    }\n                    i0 = i0n; p0 = p0n; e0 = e0a[i0]; d = dn;\n                }\n                else\n                {\n                    dir = e0a[i1].Rot180;\n                    int i1n = (i1 + 1) % p1c; var p1n = p1a[i1];\n                    var dn = Vec.Distance(p0, p1n);\n                    var dist = DistanceToLine(p0, p1, p1n, d, dn);\n                    if (dist < bestValue)\n                    {\n                        bestValue = dist;\n                        bLineOnThis = false; bpi0 = i0; bpi1 = i1;\n                    }\n                    i1 = i1n; p1 = p1n; e1 = e1a[i1]; d = dn;\n                }\n            }\n            while (i0 != start0 || i1 != start1);\n            lineOnThis = bLineOnThis; pi0 = bpi0; pi1 = bpi1;\n            return bestValue;\n        }\n\n        private static double DistanceToLine(V2d query, V2d p0, V2d p1, double d0, double d1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Vec.Dot(p0q, p0p1);\n            if (t <= 0) { return d0; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return d1; }\n            t /= denom;\n            return Vec.Distance(query, p0 + t * p0p1);\n        }\n\n        #endregion\n\n        #region Degenerated parts of a Polygon2d\n\n        #region Polygon2d-Extensions\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2d poly)\n            => poly.PolygonHasDegeneratedPart();\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2d poly, double absoluteEpsilon)\n            => poly.PolygonHasDegeneratedPart(absoluteEpsilon);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2d poly, out Polygon2d NonDegenerated)\n        {\n            bool result = poly.PolygonHasDegeneratedPart(out int[] temp);\n            NonDegenerated = new Polygon2d((from i in temp select poly[i]).ToArray<V2d>());\n            return result;\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2d poly, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(out NonDegenerated);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this Polygon2d poly, double absoluteEpsilon, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(absoluteEpsilon, out NonDegenerated);\n\n        #endregion\n\n        #region V2d[]-Extension\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this Polygon2d poly)\n            => poly.PolygonHasDegeneratedPart(4 * double.Epsilon);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this Polygon2d poly, double absoluteEpsilon)\n        {\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n\n            int i = 0;\n            int count = poly.PointCount;\n\n            V2d e0;\n            V2d e1;\n\n            double l0 = 0;\n            double l1 = 0;\n\n            while (i < count - 1)\n            {\n                if ((poly[i + 1] - poly[i]).Length < absoluteEpsilon) return true;\n\n                e0 = (poly[i + 1] - poly[i]);\n                e1 = (poly[(i + 2) % count] - poly[i + 1]);\n\n                l0 = e0.Length;\n                l1 = e1.Length;\n\n                e0 = e0 / l0;\n                //e1 = e1 / l1;\n\n                if ((e0.X * e1.Y - e0.Y * e1.X).Abs() > absoluteEpsilon) return true;\n            }\n\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this Polygon2d poly, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(4 * double.Epsilon, out NonDegenerated);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this Polygon2d poly, double absoluteEpsilon, out int[] NonDegenerated)\n        {\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n\n            int i = 0;\n            int u = 1;\n            int start = 0;\n            V2d e0;\n            V2d e1;\n            bool found = false;\n            int count = poly.PointCount;\n\n            List<int> newPoints = new List<int>();\n            newPoints.Add(0);\n\n            double l0 = 0;\n\n            while (i < count - 1)\n            {\n                e0 = (poly[i + 1] - poly[i]);\n                l0 = e0.Length;\n\n                e0 = e0 / l0;\n\n                u = i + 1;\n                V2d e = poly[(u + 1) % count] - poly[u];\n                while (\n                    (((e0.X * e.Y - e0.Y * e.X).Abs() < absoluteEpsilon && e.Dot(e0) > 0) ||\n                    (poly[(u + 1) % count] - poly[i + 1]).Length < absoluteEpsilon)\n                    && u < count - 1)\n                {\n                    if ((poly[(u + 1) % count] - poly[i + 1]).Length < absoluteEpsilon) found = true;\n\n                    u++;\n                    e0 = (poly[u] - poly[i]).Normalized;\n                    e = poly[(u + 1) % count] - poly[u];\n                }\n                u--;\n\n                start = u;\n\n                do\n                {\n                    u++;\n                    e1 = (poly[(u + 1) % count] - poly[u]);\n                }\n                while (u < count && ((e0.X * e1.Y - e0.Y * e1.X).Abs() < absoluteEpsilon && e.Dot(e0) < 0));\n\n                if (u != start + 1) found = true;\n\n                newPoints.Add(u);\n\n                i = u;\n            }\n\n            NonDegenerated = newPoints.ToArray();\n            return found;\n        }\n\n        #endregion\n\n        #endregion\n    }\n\n    public static partial class IndexPolygon2dExtensions\n    {\n        #region Conversions\n\n        public static Polygon3d ToPolygon3d(this IndexPolygon2d polygon, V3d[] pointArray)\n            => new Polygon3d(polygon.GetPointArray(pointArray));\n\n        public static Polygon3d ToPolygon3d(this IndexPolygon2d polygon, List<V3d> pointList)\n            => new Polygon3d(polygon.GetPointArray(pointList));\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/Polygon2_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var polygon2t = \"Polygon2\" + tc;\n    //#   var polygon3t = \"Polygon3\" + tc;\n    //#   var v2t = \"V2\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var m22t = \"M22\" + tc;\n    //#   var m44t = \"M44\" + tc;\n    //#   var box2t = \"Box2\" + tc;\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var line2t = \"Line2\" + tc;\n    //#   var iboundingbox = \"IBoundingBox2\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var constant = isDouble ? \"Constant\" : \"ConstantF\";\n    //#   var eps = isDouble ? \"1e-6\" : \"1e-4f\";\n    #region __polygon2t__Extensions\n\n    public static partial class __polygon2t__Extensions\n    {\n        #region Conversions\n\n        public static __polygon2t__ To__polygon2t__CCW(this __box2t__ self)\n            => new __polygon2t__(self.Min, new __v2t__(self.Max.X, self.Min.Y), self.Max, new __v2t__(self.Min.X, self.Max.Y));\n\n        public static __polygon3t__ To__polygon3t__(this __polygon2t__ polygon, Func<__v2t__, __v3t__> point_copyFun)\n            => new __polygon3t__(polygon.GetPointArray(point_copyFun));\n\n        public static __polygon3t__ To__polygon3t__(this __polygon2t__ polygon, Func<__v2t__, int, __v3t__> point_index_copyFun)\n            => new __polygon3t__(polygon.GetPointArray(point_index_copyFun));\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a 2d polygon into 3d.\n        /// The z-coordinate is assumed to be zero.\n        /// </summary>\n        public static __polygon3t__ Transformed(this __polygon2t__ polygon, __m44t__ transform)\n        {\n            return new __polygon3t__(polygon.GetPointArray(p => transform.TransformPos(p.XYO)));\n        }\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// The geometric center of the polygon.\n        /// </summary>\n        public static __v2t__ ComputeCentroid(this __polygon2t__ polygon)\n        {\n            var pc = polygon.PointCount;\n            __ftype__ area = 0;\n            var centroid = __v2t__.Zero;\n\n            // signed area as weight for center of edge line\n            var p0 = polygon[pc - 1];\n            for (int i = 0; i < pc; i++)\n            {\n                var p1 = polygon[i];\n                var a = p0.X * p1.Y - p0.Y * p1.X;\n                area += a;\n                centroid += (p0 + p1) * a; // center point would be /2\n                p0 = p1;\n            }\n\n            area *= __half__; // /2 moved outside loop\n            return area > 0 ? centroid / (area * 6) : __v2t__.Zero; // normalization by area/6\n        }\n\n        /// <summary>\n        /// Computes the area of the polygon according to\n        /// \"Fast Polygon Area and Newell Normal Computation\"\n        ///  journal of graphics tools, 7(2):9-13, 2002\n        /// </summary>\n        public static __ftype__ ComputeSignedArea(this __polygon2t__ polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return 0;\n            __ftype__ area = polygon[pc - 1].X * (polygon[0].Y - polygon[pc - 2].Y);\n            area += polygon[0].X * (polygon[1].Y - polygon[pc - 1].Y);\n            for (int pi = 2; pi < pc; pi++)\n                area += polygon[pi - 1].X * (polygon[pi].Y - polygon[pi - 2].Y);\n            return area / 2;\n        }\n\n        /// <summary>\n        /// Computes the area of the polygon according to\n        /// \"Fast Polygon Area and Newell Normal Computation\"\n        ///  journal of graphics tools, 7(2):9-13, 2002. The\n        ///  absolute value is returned (i.e. area >= 0.0).\n        /// </summary>\n        public static __ftype__ ComputeArea(this __polygon2t__ polygon)\n            => polygon.ComputeSignedArea().Abs();\n\n        /// <summary>\n        /// Returns the rotation of the supplied counter clockwise enumerated\n        /// convex polygon that results in the minimum area enclosing box.\n        /// If multiple rotations are within epsilon in their area, the one\n        /// that is closest to an axis-aligned rotation (0, 90, 180, 270) is\n        /// returned. O(n).\n        /// </summary>\n        public static __m22t__ ComputeMinAreaEnclosingBoxRotation(\n                this __polygon2t__ polygon, __ftype__ epsilon = __eps__)\n        {\n            polygon = polygon.WithoutMultiplePoints(epsilon);\n            var pc = polygon.PointCount;\n\n            if (pc < 2) return __m22t__.Identity;\n            var ea = polygon.GetEdgeArray();\n            ea.Apply(v => v.Normalized);\n\n            int i0 = 0, i1 = 0;\n            int i2 = 0, i3 = 0;\n            var min = polygon[0]; var max = polygon[0];\n            for (int pi = 1; pi < pc; pi++)\n            {\n                var p = polygon[pi];\n                if (p.Y < min.Y) { i0 = pi; min.Y = p.Y; }\n                else if (p.Y > max.Y) { i2 = pi; max.Y = p.Y; }\n                if (p.X > max.X) { i1 = pi; max.X = p.X; }\n                else if (p.X < min.X) { i3 = pi; min.X = p.X; }\n            }\n\n            __v2t__ p0 = polygon[i0], e0 = ea[i0], p1 = polygon[i1], e1 = ea[i1];\n            __v2t__ p2 = polygon[i2], e2 = ea[i2], p3 = polygon[i3], e3 = ea[i3];\n\n            int end0 = (i0 + 1) % pc, end1 = (i1 + 1) % pc;\n            int end2 = (i2 + 1) % pc, end3 = (i3 + 1) % pc;\n            var dir = __v2t__.XAxis;\n\n            var best = dir;\n            var bestArea = __ftype__.MaxValue;\n            var bestValue = __ftype__.MaxValue;\n            while (true)\n            {\n                var s0 = Fun.FastAtan2(e0.Dot90(dir), e0.Dot(dir));\n                var s1 = Fun.FastAtan2(e1.Dot180(dir), e1.Dot90(dir));\n                var s2 = Fun.FastAtan2(e2.Dot270(dir), e2.Dot180(dir));\n                var s3 = Fun.FastAtan2(e3.Dot(dir), e3.Dot270(dir));\n\n                int si, si01, si23; __ftype__ s01, s23;\n                if (s0 < s1) { s01 = s0; si01 = 0; } else { s01 = s1; si01 = 1; }\n                if (s2 < s3) { s23 = s2; si23 = 2; } else { s23 = s3; si23 = 3; }\n                if (s01 < s23) { si = si01; } else { si = si23; }\n\n                if (si == 0) dir = ea[i0];\n                else if (si == 1) dir = ea[i1].Rot270;\n                else if (si == 2) dir = ea[i2].Rot180;\n                else dir = ea[i3].Rot90;\n\n                __ftype__ sx = (p2 - p0).Dot90(dir), sy = (p1 - p3).Dot(dir);\n                __ftype__ area = sx * sy;\n                __ftype__ value = Fun.Min(Fun.Abs(dir.X), Fun.Abs(dir.Y));\n\n                if (area < bestArea - epsilon\n                    || (area < bestArea + epsilon && value < bestValue))\n                {\n                    bestArea = area; bestValue = value; best = dir;\n                }\n\n                if (si == 0)\n                {\n                    if (++i0 >= pc) i0 -= pc;\n                    if (i0 == end1) break;\n                    p0 = polygon[i0]; e0 = ea[i0];\n                }\n                else if (si == 1)\n                {\n                    if (++i1 >= pc) i1 -= pc;\n                    if (i1 == end2) break;\n                    p1 = polygon[i1]; e1 = ea[i1];\n                }\n                else if (si == 2)\n                {\n                    if (++i2 >= pc) i2 -= pc;\n                    if (i2 == end3) break;\n                    p2 = polygon[i2]; e2 = ea[i2];\n                }\n                else\n                {\n                    if (++i3 >= pc) i3 -= pc;\n                    if (i3 == end0) break;\n                    p3 = polygon[i3]; e3 = ea[i3];\n                }\n            }\n            return new __m22t__(best.X, best.Y, -best.Y, best.X);\n        }\n\n        /// <summary>\n        /// Gets oriented bounding box of this polygon\n        /// </summary>\n        public static __polygon2t__ ComputeOrientedBoundingBox(this __polygon2t__ polygon)\n        {\n            var rot = polygon.ComputeMinAreaEnclosingBoxRotation();\n            var rotInv = rot.Transposed;\n            var bbGlobal = new __box2t__(polygon.Points.Select(p => rot * p));\n            return new __polygon2t__(bbGlobal.ComputeCornersCCW().Apply(p => rotInv * p));\n        }\n        \n        /// <summary>\n        /// Computes the winding number of the polyon.\n        /// The winding number is positive for counter-\n        /// clockwise polygons, negative for clockwise polygons.\n        /// </summary>\n        public static int ComputeWindingNumber(this __polygon2t__ polygon)\n        {\n            int pc = polygon.PointCount;\n            __v2t__ e = polygon[0] - polygon[pc - 1];\n            var a = Fun.Atan2(e.Y, e.X);\n            var a0 = a;\n            var radians = 0.0;\n            for (int pi = 0; pi < pc - 1; pi++)\n            {\n                __v2t__ e1 = polygon[pi + 1] - polygon[pi];\n                var a1 = Fun.Atan2(e1.Y, e1.X);\n                var alpha = a1 - a0;\n                if (alpha >= __constant__.Pi) alpha -= __constant__.PiTimesTwo;\n                else if (alpha < -__constant__.Pi) alpha += __constant__.PiTimesTwo;\n                radians += alpha;\n                a0 = a1;\n            }\n            var alpha0 = a - a0;\n            if (alpha0 >= __constant__.Pi) alpha0 -= __constant__.PiTimesTwo;\n            else if (alpha0 < -__constant__.Pi) alpha0 += __constant__.PiTimesTwo;\n            radians += alpha0;\n\n            var winding = radians >= 0\n                ? (int)((__constant__.Pi + radians) / __constant__.PiTimesTwo)\n                : -(int)((__constant__.Pi - radians) / __constant__.PiTimesTwo);\n\n            return winding;\n        }\n\n        private const int V = 1;\n        private static readonly Func<__v2t__, __v2t__, bool> c_ccwFun = (a, b) => (a.X * b.Y - a.Y * b.X) >= 0;\n        private static readonly Func<__v2t__, __v2t__, bool> c_cwFun = (a, b) => (a.X * b.Y - a.Y * b.X) <= 0;\n\n        /// <summary>\n        /// Check if a polygon has a specified winding.\n        /// </summary>\n        public static bool HasWinding(\n                this __polygon2t__ polygon, Winding winding)\n        {\n            var winFun = winding == Winding.CCW ? c_ccwFun : c_cwFun;\n            var ef = polygon.Edge(0);\n            var e0 = polygon.Edge(1);\n            var orientation = winFun(ef, e0);\n            for (int i = 2; i < polygon.PointCount; i++)\n            {\n                var e1 = polygon.Edge(i);\n                if (winFun(e0, e1) != orientation) return false;\n                e0 = e1;\n            }\n            return winFun(e0, ef) == orientation;\n        }\n\n        /// <summary>\n        /// Returns true if polygon points are oriented in counter-clockwise order.\n        /// </summary>\n        public static bool IsCcw(this __polygon2t__ polygon) => polygon.ComputeWindingNumber() >= 0;\n\n        public static bool IsConcave(this __polygon2t__ polygon) => polygon.HasWinding(Winding.CW);\n\n        public static bool IsConvex(this __polygon2t__ polygon) => polygon.HasWinding(Winding.CCW);\n\n        #endregion\n\n        #region Convex Hull\n\n        /// <summary>\n        /// Returns convex hull of this polygon.\n        /// </summary>\n        public static Index__polygon2t__ ComputeConvexHullIndexPolygon(this __polygon2t__ polygon)\n            => polygon.m_pointArray.ConvexHullIndexPolygon(polygon.m_pointCount);\n\n        #endregion\n\n        #region Intersection\n\n        /// <summary>\n        /// Returns:\n        ///      1 if the Polygon created by poly has no self-intersections\n        ///      0 if one point of the polygon lies close to a line (absoluteEpsilon)\n        ///     -1 if the Polygon created by poly has a real self-intersection\n        /// </summary>\n        public static int HasSelfIntersections(\n                this __polygon2t__ poly, __ftype__ absoluteEpsilon)\n        {\n            var pointCount = poly.PointCount;\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n            int worst = V;\n            __v2t__ n0;\n\n            //Triangles cannot have self-intersections\n            if (pointCount == 3) return 1;\n\n            __line2t__ line;\n            int i;\n            for (i = 0; i < pointCount - 1; i++)\n            {\n                //line between i and i+1\n                line = new __line2t__(poly[i], poly[i + 1]);\n                n0 = line.Direction.Normalized;\n                n0 = new __v2t__(-n0.Y, n0.X);\n\n\n                for (int u = i + 2; u < pointCount && (u + 1) % pointCount != i; u++)\n                {\n                    //Polygon not degenerated -> Line cannot intersect with line directly before and directly after\n                    //All lines prior to (u,u1) have already been tested with (i,i+1)\n                    int u1 = (u + 1) % pointCount;\n\n                    if (line.IntersectsLine(poly[u], poly[u1]))\n                    {\n                        //One Point of (u,u1) lies on line (within absoluteEpsilon)\n                        if (n0.Dot(poly[u1] - line.P0).Abs() < absoluteEpsilon || n0.Dot(poly[u] - line.P0).Abs() < absoluteEpsilon)\n                        {\n                            worst = 0;\n                        }\n                        else return -1;\n                    }\n                }\n            }\n\n            return worst;\n        }\n\n        /// <summary>\n        /// Returns true if this polygon is fully contained inside the 'other' polygon.\n        /// </summary>\n        public static bool IsFullyContainedInside(this __polygon2t__ self, __polygon2t__ other)\n        {\n            // check if all my vertices are inside the other polygon\n            foreach (var v in self.Points)\n            {\n                if (!other.Contains(v)) return false;\n            }\n\n            // check if all my edges do NOT intersect with edges of the other polygon\n            foreach (var e in self.EdgeLines)\n            {\n                foreach (var x in other.EdgeLines)\n                {\n                    if (x.Intersects(e)) return false;\n                }\n            }\n\n            // :-)\n            return true;\n        }\n\n        #endregion\n\n        #region Relations\n\n        /// <summary>\n        /// Returns the minimal distance between the polygon and the\n        /// other supplied polygon. O(n).\n        /// </summary>\n        public static __ftype__ MinDistanceTo(this __polygon2t__ polygon, __polygon2t__ polygon1)\n            => polygon.MinDistanceTo(polygon1, out _, out _, out _);\n\n        /// <summary>\n        /// Returns the minimal distance between the polygon and the non-\n        /// overlapping other supplied polygon. The minimal distance is\n        /// always computed as the distance between a line segment and a\n        /// point. The indices of the minimal distance configuration are\n        /// returned in the out parameter, as the indices of points on the\n        /// two polygons, and wether the line segement was on this or the\n        /// other polygon. O(n). The returned index of the line segment is\n        /// the lower point index (except in case of wraparound).\n        /// </summary>\n        public static __ftype__ MinDistanceTo(\n                this __polygon2t__ polygon, __polygon2t__ polygon1,\n                out int pi0, out int pi1, out bool lineOnThis)\n        {\n            var p0a = polygon.m_pointArray;\n            var p1a = polygon1.m_pointArray;\n            var p0c = polygon.m_pointCount;\n            var p1c = polygon1.m_pointCount;\n            var e0a = polygon.GetEdgeArray();\n            var e1a = polygon1.GetEdgeArray();\n            int i0 = p0a.IndexOfMinY(p0c), i1 = p1a.IndexOfMaxY(p1c);\n            __v2t__ p0 = p0a[i0], e0 = e0a[i0], p1 = p1a[i1], e1 = e1a[i1];\n\n            int start0 = i0, start1 = i1;\n            var dir = __v2t__.XAxis;\n            var d = Vec.Distance(p0, p1);\n\n            var bestValue = __ftype__.MaxValue;\n            int bpi0 = -1, bpi1 = -1;\n            var bLineOnThis = true;\n\n            do\n            {\n                var s0 = Fun.Atan2(e0.Dot90(dir), e0.Dot(dir));\n                var s1 = Fun.Atan2(e1.Dot270(dir), e1.Dot180(dir));\n                if (s0 <= s1)\n                {\n                    dir = e0a[i0];\n                    int i0n = (i0 + 1) % p0c; var p0n = p0a[i0];\n                    var dn = Vec.Distance(p0n, p1);\n                    var dist = DistanceToLine(p1, p0, p0n, d, dn);\n                    if (dist < bestValue)\n                    {\n                        bestValue = dist;\n                        bLineOnThis = true; bpi0 = i0; bpi1 = i1;\n                    }\n                    i0 = i0n; p0 = p0n; e0 = e0a[i0]; d = dn;\n                }\n                else\n                {\n                    dir = e0a[i1].Rot180;\n                    int i1n = (i1 + 1) % p1c; var p1n = p1a[i1];\n                    var dn = Vec.Distance(p0, p1n);\n                    var dist = DistanceToLine(p0, p1, p1n, d, dn);\n                    if (dist < bestValue)\n                    {\n                        bestValue = dist;\n                        bLineOnThis = false; bpi0 = i0; bpi1 = i1;\n                    }\n                    i1 = i1n; p1 = p1n; e1 = e1a[i1]; d = dn;\n                }\n            }\n            while (i0 != start0 || i1 != start1);\n            lineOnThis = bLineOnThis; pi0 = bpi0; pi1 = bpi1;\n            return bestValue;\n        }\n\n        private static __ftype__ DistanceToLine(__v2t__ query, __v2t__ p0, __v2t__ p1, __ftype__ d0, __ftype__ d1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Vec.Dot(p0q, p0p1);\n            if (t <= 0) { return d0; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return d1; }\n            t /= denom;\n            return Vec.Distance(query, p0 + t * p0p1);\n        }\n\n        #endregion\n\n        #region Degenerated parts of a __polygon2t__\n\n        #region __polygon2t__-Extensions\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool HasDegeneratedPart(this __polygon2t__ poly)\n            => poly.PolygonHasDegeneratedPart();\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool HasDegeneratedPart(this __polygon2t__ poly, __ftype__ absoluteEpsilon)\n            => poly.PolygonHasDegeneratedPart(absoluteEpsilon);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this __polygon2t__ poly, out __polygon2t__ NonDegenerated)\n        {\n            bool result = poly.PolygonHasDegeneratedPart(out int[] temp);\n            NonDegenerated = new __polygon2t__((from i in temp select poly[i]).ToArray<__v2t__>());\n            return result;\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this __polygon2t__ poly, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(out NonDegenerated);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool HasDegeneratedPart(this __polygon2t__ poly, __ftype__ absoluteEpsilon, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(absoluteEpsilon, out NonDegenerated);\n\n        #endregion\n\n        #region __v2t__[]-Extension\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this __polygon2t__ poly)\n            => poly.PolygonHasDegeneratedPart(4 * __ftype__.Epsilon);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this __polygon2t__ poly, __ftype__ absoluteEpsilon)\n        {\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n\n            int i = 0;\n            int count = poly.PointCount;\n\n            __v2t__ e0;\n            __v2t__ e1;\n\n            __ftype__ l0 = 0;\n            __ftype__ l1 = 0;\n\n            while (i < count - 1)\n            {\n                if ((poly[i + 1] - poly[i]).Length < absoluteEpsilon) return true;\n\n                e0 = (poly[i + 1] - poly[i]);\n                e1 = (poly[(i + 2) % count] - poly[i + 1]);\n\n                l0 = e0.Length;\n                l1 = e1.Length;\n\n                e0 = e0 / l0;\n                //e1 = e1 / l1;\n\n                if ((e0.X * e1.Y - e0.Y * e1.X).Abs() > absoluteEpsilon) return true;\n            }\n\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this __polygon2t__ poly, out int[] NonDegenerated)\n            => poly.PolygonHasDegeneratedPart(4 * __ftype__.Epsilon, out NonDegenerated);\n\n        /// <summary>\n        /// Returns true if the Polygon contains a degenerated part\n        /// NonDegenerated holds the Non-Degenerated part of the polygon\n        /// </summary>\n        public static bool PolygonHasDegeneratedPart(this __polygon2t__ poly, __ftype__ absoluteEpsilon, out int[] NonDegenerated)\n        {\n            if (absoluteEpsilon < 0) throw new ArgumentOutOfRangeException();\n\n            int i = 0;\n            int u = 1;\n            int start = 0;\n            __v2t__ e0;\n            __v2t__ e1;\n            bool found = false;\n            int count = poly.PointCount;\n\n            List<int> newPoints = new List<int>();\n            newPoints.Add(0);\n\n            __ftype__ l0 = 0;\n\n            while (i < count - 1)\n            {\n                e0 = (poly[i + 1] - poly[i]);\n                l0 = e0.Length;\n\n                e0 = e0 / l0;\n\n                u = i + 1;\n                __v2t__ e = poly[(u + 1) % count] - poly[u];\n                while (\n                    (((e0.X * e.Y - e0.Y * e.X).Abs() < absoluteEpsilon && e.Dot(e0) > 0) ||\n                    (poly[(u + 1) % count] - poly[i + 1]).Length < absoluteEpsilon)\n                    && u < count - 1)\n                {\n                    if ((poly[(u + 1) % count] - poly[i + 1]).Length < absoluteEpsilon) found = true;\n\n                    u++;\n                    e0 = (poly[u] - poly[i]).Normalized;\n                    e = poly[(u + 1) % count] - poly[u];\n                }\n                u--;\n\n                start = u;\n\n                do\n                {\n                    u++;\n                    e1 = (poly[(u + 1) % count] - poly[u]);\n                }\n                while (u < count && ((e0.X * e1.Y - e0.Y * e1.X).Abs() < absoluteEpsilon && e.Dot(e0) < 0));\n\n                if (u != start + 1) found = true;\n\n                newPoints.Add(u);\n\n                i = u;\n            }\n\n            NonDegenerated = newPoints.ToArray();\n            return found;\n        }\n\n        #endregion\n\n        #endregion\n    }\n\n    public static partial class Index__polygon2t__Extensions\n    {\n        #region Conversions\n\n        public static __polygon3t__ To__polygon3t__(this Index__polygon2t__ polygon, __v3t__[] pointArray)\n            => new __polygon3t__(polygon.GetPointArray(pointArray));\n\n        public static __polygon3t__ To__polygon3t__(this Index__polygon2t__ polygon, List<__v3t__> pointList)\n            => new __polygon3t__(polygon.GetPointArray(pointList));\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/Polygon3_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Polygon3fExtensions\n\n    public static partial class Polygon3fExtensions\n    {\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f ToPolygon2f(this Polygon3f polygon, Func<V3f, V2f> point_copyFun)\n            => new Polygon2f(polygon.GetPointArray(point_copyFun));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f ToPolygon2f(\n            this Polygon3f polygon, Func<V3f, int, V2f> point_index_copyFun\n            )\n            => new Polygon2f(polygon.GetPointArray(point_index_copyFun));\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// Computes the area as the length of the sum of  the simple\n        /// triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ComputeArea(this Polygon3f polygon)\n            => 0.5f * polygon.ComputeDoubleAreaNormal().Length;\n\n        /// <summary>\n        /// Computes the normalized normal as the sum of  the simple\n        /// triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f ComputeNormal(this Polygon3f polygon)\n            => polygon.ComputeDoubleAreaNormal().Normalized;\n\n        /// <summary>\n        /// The geometric center of a 3-dimensional, flat polygon.\n        /// WARNING: UNTESTED!\n        /// </summary>\n        public static V3f ComputeCentroid(this Polygon3f polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return V3f.Zero;\n            V3f p0 = polygon[0], p1 = polygon[1];\n            V3f e0 = p1 - p0;\n            var p2 = polygon[2];\n            var e1 = p2 - p0;\n            var normal = e0.Cross(e1);\n            var area2 = normal.Length;\n            var centroid = area2 * (p0 + p1 + p2);\n            p1 = p2; e0 = e1;\n            for (int pi = 3; pi < pc; pi++)\n            {\n                p2 = polygon[pi]; e1 = p2 - p0;\n                var n = e0.Cross(e1);\n                var a2 = Fun.Sign(normal.Dot(n)) * n.Length;\n                area2 += a2;\n                centroid += a2 * (p0 + p1 + p2);\n                p1 = p2; e0 = e1;\n            }\n            if (area2 > Constant<float>.PositiveTinyValue)\n                return centroid * (ConstantF.OneThird / area2);\n            else if (area2 < Constant<float>.NegativeTinyValue)\n                return centroid * (-ConstantF.OneThird / area2);\n            else\n                return V3f.Zero;\n        }\n\n        /// <summary>\n        /// Computes the normal with the length of twice the polygon area as\n        /// the sum of  the simple triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        public static V3f ComputeDoubleAreaNormal(this Polygon3f polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return V3f.Zero;\n            V3f p0 = polygon[0];\n            V3f e0 = polygon[1] - p0;\n            V3f normal = V3f.Zero;\n            for (int pi = 2; pi < pc; pi++)\n            {\n                var e1 = polygon[pi] - p0;\n                normal += e0.Cross(e1);\n                e0 = e1;\n            }\n            return normal;\n        }\n\n        /// <summary>\n        /// Computes the supporting plane of the polygon via the vertex centroid\n        /// and the sum of  the simple triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3f ComputePlane3f(this Polygon3f polygon)\n            => new Plane3f(polygon.ComputeNormal(), polygon.ComputeVertexCentroid());\n\n        /// <summary>\n        /// Returns the plane through the first 3 points of the polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3f GetPlane3f(this Polygon3f polygon)\n            => new Plane3f(polygon[0], polygon[1], polygon[2]);\n\n        #endregion\n\n        #region FormFactor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ComputeToPointFormFactor(\n                this Polygon3f sourcePolygon, float polygonArea,\n                V3f targetPoint, V3f targetNormal,\n                float eps = 1e-4f)\n        {\n            return sourcePolygon.ComputeUnscaledFormFactor(\n                                        targetPoint, targetNormal, eps)\n                    / (ConstantF.PiTimesTwo * polygonArea);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ComputeFromPointFormFactor(\n                this Polygon3f targetPolygon,\n                V3f sourcePoint, V3f sourceNormal,\n                float eps = 1e-4f)\n        {\n            return targetPolygon.ComputeUnscaledFormFactor(\n                                        sourcePoint, sourceNormal, eps)\n                    / ConstantF.PiTimesTwo;\n        }\n\n        public static float ComputeUnscaledFormFactor(\n                this Polygon3f polygon,\n                V3f p, V3f n,\n                float eps = 1e-4f)\n        {\n            var vc = polygon.PointCount;\n\n            V3f[] cpa = new V3f[vc + 1];\n\n            var cc = 0;\n            var pb = polygon[0] - p;\n            var hb = Vec.Dot(pb, n); bool hbp = hb > eps, hbn = hb < -eps;\n            if (hb >= -eps) cpa[cc++] = pb;\n            var p0 = pb; var h0 = hb; var h0p = hbp; var h0n = hbn;\n            for (int vi = 1; vi < vc; vi++)\n            {\n                var p1 = polygon[vi] - p; var h1 = Vec.Dot(p1, n);\n                bool h1p = h1 > eps, h1n = h1 < -eps;\n                if (h0p && h1n || h0n && h1p)\n                    cpa[cc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));\n                if (h1 >= -eps) cpa[cc++] = p1;\n                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;\n            }\n            if (h0p && hbn || h0n && hbp)\n                cpa[cc++] = p0 + (pb - p0) * (h0 / (h0 - hb));\n\n            var cpr = cpa.Map(cc, v => v.Length);\n\n            var cv = Vec.Cross(cpa[0], cpa[cc - 1]);\n            float ff = Vec.Dot(n, cv)\n                        * Fun.AcosClamped(Vec.Dot(cpa[0], cpa[cc - 1])\n                                    / (cpr[0] * cpr[cc - 1]))\n                        / cv.Length;\n\n            for (int ci = 0; ci < cc - 1; ci++)\n            {\n                cv = Vec.Cross(cpa[ci + 1], cpa[ci]);\n                ff += Vec.Dot(n, cv)\n                       * Fun.AcosClamped(Vec.Dot(cpa[ci + 1], cpa[ci])\n                                    / (cpr[ci + 1] * cpr[ci]))\n                        / cv.Length;\n            }\n            return ff;\n        }\n\n        #endregion\n\n        #region Shape Analysis\n\n        /// <summary>\n        /// Enumerates all pairs of coincident vertices (as pairs of vertex indices).\n        /// </summary>\n        public static IEnumerable<(int, int)> GetCoincidentPoints(\n                this Polygon3f polygon, float toleranceAbsolute)\n        {\n            if (toleranceAbsolute < 0) throw new ArgumentOutOfRangeException();\n            var pc = polygon.PointCount;\n            for (int pi = 0; pi < pc; pi++)\n            {\n                for (int pj = pi + 1; pj < pc; pj++)\n                {\n                    if (polygon[pi].ApproximateEquals(polygon[pj], toleranceAbsolute))\n                        yield return (pi, pj);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least two vertices are coincident.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool HasCoincidentPoints(\n                this Polygon3f polygon, float toleranceAbsolute)\n        {\n            return GetCoincidentPoints(polygon, toleranceAbsolute).Any();\n        }\n\n        /// <summary>\n        /// Enumerates all pairs of edges that intersect (as pairs of edge indices).\n        /// </summary>\n        public static IEnumerable<(int, int)> GetSelfIntersections(\n                this Polygon3f polygon, float toleranceAbsolute)\n        {\n            if (toleranceAbsolute < 0) throw new ArgumentOutOfRangeException();\n            var pc = polygon.PointCount;\n            var la = polygon.GetEdgeLineArray();\n            for (int i = 0; i < pc; i++)\n            {\n                int jmax = (i > 0) ? pc : pc - 1;\n                for (int j = i + 2; j < jmax; j++)\n                {\n                    if (la[i].Intersects(la[j], toleranceAbsolute)) yield return (i, j);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least two edges intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsSelfIntersecting(\n                this Polygon3f self, float toleranceAbsolute = 1e-5f)\n        {\n            return GetSelfIntersections(self, toleranceAbsolute).Any();\n        }\n\n        /// <summary>\n        /// Enumerates all vertex indexes at which\n        /// both outgoing edges meet at an angle that\n        /// is less than the given threshold.\n        /// </summary>\n        public static IEnumerable<int> GetSpikes(\n                this Polygon3f self, float toleranceInDegrees = 0.1f)\n        {\n            if (toleranceInDegrees < 0) throw new ArgumentOutOfRangeException();\n            var threshold = Conversion.RadiansFromDegrees(toleranceInDegrees).Cos();\n            var edges = self.GetEdgeArray();\n            edges.Apply(e => e.Normalized);\n            var ec = edges.Length;\n            if (Vec.Dot(-edges[ec - 1], edges[0]) > threshold) yield return 0;\n            for (int i = 1; i < ec; i++)\n            {\n                if (Vec.Dot(-edges[i - 1], edges[i]) > threshold) yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least one vertex\n        /// both outgoing edges meet at an angle that\n        /// is less than the given threshold.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool HasSpikes(\n                this Polygon3f self, float toleranceInDegrees = 0.1f)\n        {\n            return GetSpikes(self, toleranceInDegrees).Any();\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon3fExtensions\n\n    public static partial class IndexPolygon3fExtensions\n    {\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f ToPolygon3f(this IndexPolygon3f polygon, V2f[] pointArray)\n            => new Polygon2f(polygon.GetPointArray(pointArray));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2f ToPolygon3f(this IndexPolygon3f polygon, List<V2f> pointList)\n            => new Polygon2f(polygon.GetPointArray(pointList));\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Polygon3dExtensions\n\n    public static partial class Polygon3dExtensions\n    {\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d ToPolygon2d(this Polygon3d polygon, Func<V3d, V2d> point_copyFun)\n            => new Polygon2d(polygon.GetPointArray(point_copyFun));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d ToPolygon2d(\n            this Polygon3d polygon, Func<V3d, int, V2d> point_index_copyFun\n            )\n            => new Polygon2d(polygon.GetPointArray(point_index_copyFun));\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// Computes the area as the length of the sum of  the simple\n        /// triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ComputeArea(this Polygon3d polygon)\n            => 0.5 * polygon.ComputeDoubleAreaNormal().Length;\n\n        /// <summary>\n        /// Computes the normalized normal as the sum of  the simple\n        /// triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d ComputeNormal(this Polygon3d polygon)\n            => polygon.ComputeDoubleAreaNormal().Normalized;\n\n        /// <summary>\n        /// The geometric center of a 3-dimensional, flat polygon.\n        /// WARNING: UNTESTED!\n        /// </summary>\n        public static V3d ComputeCentroid(this Polygon3d polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return V3d.Zero;\n            V3d p0 = polygon[0], p1 = polygon[1];\n            V3d e0 = p1 - p0;\n            var p2 = polygon[2];\n            var e1 = p2 - p0;\n            var normal = e0.Cross(e1);\n            var area2 = normal.Length;\n            var centroid = area2 * (p0 + p1 + p2);\n            p1 = p2; e0 = e1;\n            for (int pi = 3; pi < pc; pi++)\n            {\n                p2 = polygon[pi]; e1 = p2 - p0;\n                var n = e0.Cross(e1);\n                var a2 = Fun.Sign(normal.Dot(n)) * n.Length;\n                area2 += a2;\n                centroid += a2 * (p0 + p1 + p2);\n                p1 = p2; e0 = e1;\n            }\n            if (area2 > Constant<double>.PositiveTinyValue)\n                return centroid * (Constant.OneThird / area2);\n            else if (area2 < Constant<double>.NegativeTinyValue)\n                return centroid * (-Constant.OneThird / area2);\n            else\n                return V3d.Zero;\n        }\n\n        /// <summary>\n        /// Computes the normal with the length of twice the polygon area as\n        /// the sum of  the simple triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        public static V3d ComputeDoubleAreaNormal(this Polygon3d polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return V3d.Zero;\n            V3d p0 = polygon[0];\n            V3d e0 = polygon[1] - p0;\n            V3d normal = V3d.Zero;\n            for (int pi = 2; pi < pc; pi++)\n            {\n                var e1 = polygon[pi] - p0;\n                normal += e0.Cross(e1);\n                e0 = e1;\n            }\n            return normal;\n        }\n\n        /// <summary>\n        /// Computes the supporting plane of the polygon via the vertex centroid\n        /// and the sum of  the simple triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3d ComputePlane3d(this Polygon3d polygon)\n            => new Plane3d(polygon.ComputeNormal(), polygon.ComputeVertexCentroid());\n\n        /// <summary>\n        /// Returns the plane through the first 3 points of the polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3d GetPlane3d(this Polygon3d polygon)\n            => new Plane3d(polygon[0], polygon[1], polygon[2]);\n\n        #endregion\n\n        #region FormFactor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ComputeToPointFormFactor(\n                this Polygon3d sourcePolygon, double polygonArea,\n                V3d targetPoint, V3d targetNormal,\n                double eps = 1e-6)\n        {\n            return sourcePolygon.ComputeUnscaledFormFactor(\n                                        targetPoint, targetNormal, eps)\n                    / (Constant.PiTimesTwo * polygonArea);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ComputeFromPointFormFactor(\n                this Polygon3d targetPolygon,\n                V3d sourcePoint, V3d sourceNormal,\n                double eps = 1e-6)\n        {\n            return targetPolygon.ComputeUnscaledFormFactor(\n                                        sourcePoint, sourceNormal, eps)\n                    / Constant.PiTimesTwo;\n        }\n\n        public static double ComputeUnscaledFormFactor(\n                this Polygon3d polygon,\n                V3d p, V3d n,\n                double eps = 1e-6)\n        {\n            var vc = polygon.PointCount;\n\n            V3d[] cpa = new V3d[vc + 1];\n\n            var cc = 0;\n            var pb = polygon[0] - p;\n            var hb = Vec.Dot(pb, n); bool hbp = hb > eps, hbn = hb < -eps;\n            if (hb >= -eps) cpa[cc++] = pb;\n            var p0 = pb; var h0 = hb; var h0p = hbp; var h0n = hbn;\n            for (int vi = 1; vi < vc; vi++)\n            {\n                var p1 = polygon[vi] - p; var h1 = Vec.Dot(p1, n);\n                bool h1p = h1 > eps, h1n = h1 < -eps;\n                if (h0p && h1n || h0n && h1p)\n                    cpa[cc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));\n                if (h1 >= -eps) cpa[cc++] = p1;\n                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;\n            }\n            if (h0p && hbn || h0n && hbp)\n                cpa[cc++] = p0 + (pb - p0) * (h0 / (h0 - hb));\n\n            var cpr = cpa.Map(cc, v => v.Length);\n\n            var cv = Vec.Cross(cpa[0], cpa[cc - 1]);\n            double ff = Vec.Dot(n, cv)\n                        * Fun.AcosClamped(Vec.Dot(cpa[0], cpa[cc - 1])\n                                    / (cpr[0] * cpr[cc - 1]))\n                        / cv.Length;\n\n            for (int ci = 0; ci < cc - 1; ci++)\n            {\n                cv = Vec.Cross(cpa[ci + 1], cpa[ci]);\n                ff += Vec.Dot(n, cv)\n                       * Fun.AcosClamped(Vec.Dot(cpa[ci + 1], cpa[ci])\n                                    / (cpr[ci + 1] * cpr[ci]))\n                        / cv.Length;\n            }\n            return ff;\n        }\n\n        #endregion\n\n        #region Shape Analysis\n\n        /// <summary>\n        /// Enumerates all pairs of coincident vertices (as pairs of vertex indices).\n        /// </summary>\n        public static IEnumerable<(int, int)> GetCoincidentPoints(\n                this Polygon3d polygon, double toleranceAbsolute)\n        {\n            if (toleranceAbsolute < 0) throw new ArgumentOutOfRangeException();\n            var pc = polygon.PointCount;\n            for (int pi = 0; pi < pc; pi++)\n            {\n                for (int pj = pi + 1; pj < pc; pj++)\n                {\n                    if (polygon[pi].ApproximateEquals(polygon[pj], toleranceAbsolute))\n                        yield return (pi, pj);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least two vertices are coincident.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool HasCoincidentPoints(\n                this Polygon3d polygon, double toleranceAbsolute)\n        {\n            return GetCoincidentPoints(polygon, toleranceAbsolute).Any();\n        }\n\n        /// <summary>\n        /// Enumerates all pairs of edges that intersect (as pairs of edge indices).\n        /// </summary>\n        public static IEnumerable<(int, int)> GetSelfIntersections(\n                this Polygon3d polygon, double toleranceAbsolute)\n        {\n            if (toleranceAbsolute < 0) throw new ArgumentOutOfRangeException();\n            var pc = polygon.PointCount;\n            var la = polygon.GetEdgeLineArray();\n            for (int i = 0; i < pc; i++)\n            {\n                int jmax = (i > 0) ? pc : pc - 1;\n                for (int j = i + 2; j < jmax; j++)\n                {\n                    if (la[i].Intersects(la[j], toleranceAbsolute)) yield return (i, j);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least two edges intersect.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsSelfIntersecting(\n                this Polygon3d self, double toleranceAbsolute = 1e-10)\n        {\n            return GetSelfIntersections(self, toleranceAbsolute).Any();\n        }\n\n        /// <summary>\n        /// Enumerates all vertex indexes at which\n        /// both outgoing edges meet at an angle that\n        /// is less than the given threshold.\n        /// </summary>\n        public static IEnumerable<int> GetSpikes(\n                this Polygon3d self, double toleranceInDegrees = 0.1)\n        {\n            if (toleranceInDegrees < 0) throw new ArgumentOutOfRangeException();\n            var threshold = Conversion.RadiansFromDegrees(toleranceInDegrees).Cos();\n            var edges = self.GetEdgeArray();\n            edges.Apply(e => e.Normalized);\n            var ec = edges.Length;\n            if (Vec.Dot(-edges[ec - 1], edges[0]) > threshold) yield return 0;\n            for (int i = 1; i < ec; i++)\n            {\n                if (Vec.Dot(-edges[i - 1], edges[i]) > threshold) yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least one vertex\n        /// both outgoing edges meet at an angle that\n        /// is less than the given threshold.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool HasSpikes(\n                this Polygon3d self, double toleranceInDegrees = 0.1)\n        {\n            return GetSpikes(self, toleranceInDegrees).Any();\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IndexPolygon3dExtensions\n\n    public static partial class IndexPolygon3dExtensions\n    {\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d ToPolygon3d(this IndexPolygon3d polygon, V2d[] pointArray)\n            => new Polygon2d(polygon.GetPointArray(pointArray));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Polygon2d ToPolygon3d(this IndexPolygon3d polygon, List<V2d> pointList)\n            => new Polygon2d(polygon.GetPointArray(pointList));\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/Polygon3_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var polygon2t = \"Polygon2\" + tc;\n    //#   var polygon3t = \"Polygon3\" + tc;\n    //#   var v2t = \"V2\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var m22t = \"M22\" + tc;\n    //#   var m44t = \"M44\" + tc;\n    //#   var box2t = \"Box2\" + tc;\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var line2t = \"Line2\" + tc;\n    //#   var iboundingbox = \"IBoundingBox2\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var zerodotone = isDouble ? \"0.1\" : \"0.1f\";\n    //#   var constant = isDouble ? \"Constant\" : \"ConstantF\";\n    //#   var eps = isDouble ? \"1e-6\" : \"1e-4f\";\n    #region __polygon3t__Extensions\n\n    public static partial class __polygon3t__Extensions\n    {\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __polygon2t__ To__polygon2t__(this __polygon3t__ polygon, Func<__v3t__, __v2t__> point_copyFun)\n            => new __polygon2t__(polygon.GetPointArray(point_copyFun));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __polygon2t__ To__polygon2t__(\n            this __polygon3t__ polygon, Func<__v3t__, int, __v2t__> point_index_copyFun\n            )\n            => new __polygon2t__(polygon.GetPointArray(point_index_copyFun));\n\n        #endregion\n\n        #region Geometric Properties\n\n        /// <summary>\n        /// Computes the area as the length of the sum of  the simple\n        /// triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ ComputeArea(this __polygon3t__ polygon)\n            => __half__ * polygon.ComputeDoubleAreaNormal().Length;\n\n        /// <summary>\n        /// Computes the normalized normal as the sum of  the simple\n        /// triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ ComputeNormal(this __polygon3t__ polygon)\n            => polygon.ComputeDoubleAreaNormal().Normalized;\n\n        /// <summary>\n        /// The geometric center of a 3-dimensional, flat polygon.\n        /// WARNING: UNTESTED!\n        /// </summary>\n        public static __v3t__ ComputeCentroid(this __polygon3t__ polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return __v3t__.Zero;\n            __v3t__ p0 = polygon[0], p1 = polygon[1];\n            __v3t__ e0 = p1 - p0;\n            var p2 = polygon[2];\n            var e1 = p2 - p0;\n            var normal = e0.Cross(e1);\n            var area2 = normal.Length;\n            var centroid = area2 * (p0 + p1 + p2);\n            p1 = p2; e0 = e1;\n            for (int pi = 3; pi < pc; pi++)\n            {\n                p2 = polygon[pi]; e1 = p2 - p0;\n                var n = e0.Cross(e1);\n                var a2 = Fun.Sign(normal.Dot(n)) * n.Length;\n                area2 += a2;\n                centroid += a2 * (p0 + p1 + p2);\n                p1 = p2; e0 = e1;\n            }\n            if (area2 > Constant<__ftype__>.PositiveTinyValue)\n                return centroid * (__constant__.OneThird / area2);\n            else if (area2 < Constant<__ftype__>.NegativeTinyValue)\n                return centroid * (-__constant__.OneThird / area2);\n            else\n                return __v3t__.Zero;\n        }\n\n        /// <summary>\n        /// Computes the normal with the length of twice the polygon area as\n        /// the sum of  the simple triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        public static __v3t__ ComputeDoubleAreaNormal(this __polygon3t__ polygon)\n        {\n            var pc = polygon.PointCount;\n            if (pc < 3) return __v3t__.Zero;\n            __v3t__ p0 = polygon[0];\n            __v3t__ e0 = polygon[1] - p0;\n            __v3t__ normal = __v3t__.Zero;\n            for (int pi = 2; pi < pc; pi++)\n            {\n                var e1 = polygon[pi] - p0;\n                normal += e0.Cross(e1);\n                e0 = e1;\n            }\n            return normal;\n        }\n\n        /// <summary>\n        /// Computes the supporting plane of the polygon via the vertex centroid\n        /// and the sum of  the simple triangulation cross-product normals.\n        /// NOTE: This has been tested to be slightly faster and slightly more\n        /// accurate than the computation via the 3d Newell normal\n        /// (see Math.Tests/GeometryTests, rft 2013-05-04).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __plane3t__ Compute__plane3t__(this __polygon3t__ polygon)\n            => new __plane3t__(polygon.ComputeNormal(), polygon.ComputeVertexCentroid());\n\n        /// <summary>\n        /// Returns the plane through the first 3 points of the polygon.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __plane3t__ Get__plane3t__(this __polygon3t__ polygon)\n            => new __plane3t__(polygon[0], polygon[1], polygon[2]);\n\n        #endregion\n\n        #region FormFactor\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ ComputeToPointFormFactor(\n                this __polygon3t__ sourcePolygon, __ftype__ polygonArea,\n                __v3t__ targetPoint, __v3t__ targetNormal,\n                __ftype__ eps = __eps__)\n        {\n            return sourcePolygon.ComputeUnscaledFormFactor(\n                                        targetPoint, targetNormal, eps)\n                    / (__constant__.PiTimesTwo * polygonArea);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ ComputeFromPointFormFactor(\n                this __polygon3t__ targetPolygon,\n                __v3t__ sourcePoint, __v3t__ sourceNormal,\n                __ftype__ eps = __eps__)\n        {\n            return targetPolygon.ComputeUnscaledFormFactor(\n                                        sourcePoint, sourceNormal, eps)\n                    / __constant__.PiTimesTwo;\n        }\n\n        public static __ftype__ ComputeUnscaledFormFactor(\n                this __polygon3t__ polygon,\n                __v3t__ p, __v3t__ n,\n                __ftype__ eps = __eps__)\n        {\n            var vc = polygon.PointCount;\n\n            __v3t__[] cpa = new __v3t__[vc + 1];\n\n            var cc = 0;\n            var pb = polygon[0] - p;\n            var hb = Vec.Dot(pb, n); bool hbp = hb > eps, hbn = hb < -eps;\n            if (hb >= -eps) cpa[cc++] = pb;\n            var p0 = pb; var h0 = hb; var h0p = hbp; var h0n = hbn;\n            for (int vi = 1; vi < vc; vi++)\n            {\n                var p1 = polygon[vi] - p; var h1 = Vec.Dot(p1, n);\n                bool h1p = h1 > eps, h1n = h1 < -eps;\n                if (h0p && h1n || h0n && h1p)\n                    cpa[cc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));\n                if (h1 >= -eps) cpa[cc++] = p1;\n                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;\n            }\n            if (h0p && hbn || h0n && hbp)\n                cpa[cc++] = p0 + (pb - p0) * (h0 / (h0 - hb));\n\n            var cpr = cpa.Map(cc, v => v.Length);\n\n            var cv = Vec.Cross(cpa[0], cpa[cc - 1]);\n            __ftype__ ff = Vec.Dot(n, cv)\n                        * Fun.AcosClamped(Vec.Dot(cpa[0], cpa[cc - 1])\n                                    / (cpr[0] * cpr[cc - 1]))\n                        / cv.Length;\n\n            for (int ci = 0; ci < cc - 1; ci++)\n            {\n                cv = Vec.Cross(cpa[ci + 1], cpa[ci]);\n                ff += Vec.Dot(n, cv)\n                       * Fun.AcosClamped(Vec.Dot(cpa[ci + 1], cpa[ci])\n                                    / (cpr[ci + 1] * cpr[ci]))\n                        / cv.Length;\n            }\n            return ff;\n        }\n\n        #endregion\n\n        #region Shape Analysis\n\n        /// <summary>\n        /// Enumerates all pairs of coincident vertices (as pairs of vertex indices).\n        /// </summary>\n        public static IEnumerable<(int, int)> GetCoincidentPoints(\n                this __polygon3t__ polygon, __ftype__ toleranceAbsolute)\n        {\n            if (toleranceAbsolute < 0) throw new ArgumentOutOfRangeException();\n            var pc = polygon.PointCount;\n            for (int pi = 0; pi < pc; pi++)\n            {\n                for (int pj = pi + 1; pj < pc; pj++)\n                {\n                    if (polygon[pi].ApproximateEquals(polygon[pj], toleranceAbsolute))\n                        yield return (pi, pj);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least two vertices are coincident.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool HasCoincidentPoints(\n                this __polygon3t__ polygon, __ftype__ toleranceAbsolute)\n        {\n            return GetCoincidentPoints(polygon, toleranceAbsolute).Any();\n        }\n\n        /// <summary>\n        /// Enumerates all pairs of edges that intersect (as pairs of edge indices).\n        /// </summary>\n        public static IEnumerable<(int, int)> GetSelfIntersections(\n                this __polygon3t__ polygon, __ftype__ toleranceAbsolute)\n        {\n            if (toleranceAbsolute < 0) throw new ArgumentOutOfRangeException();\n            var pc = polygon.PointCount;\n            var la = polygon.GetEdgeLineArray();\n            for (int i = 0; i < pc; i++)\n            {\n                int jmax = (i > 0) ? pc : pc - 1;\n                for (int j = i + 2; j < jmax; j++)\n                {\n                    if (la[i].Intersects(la[j], toleranceAbsolute)) yield return (i, j);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least two edges intersect.\n        /// </summary>\n        //# var toleranceAbsolute = isDouble ? \"1e-10\" : \"1e-5f\";\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsSelfIntersecting(\n                this __polygon3t__ self, __ftype__ toleranceAbsolute = __toleranceAbsolute__)\n        {\n            return GetSelfIntersections(self, toleranceAbsolute).Any();\n        }\n\n        /// <summary>\n        /// Enumerates all vertex indexes at which\n        /// both outgoing edges meet at an angle that\n        /// is less than the given threshold.\n        /// </summary>\n        public static IEnumerable<int> GetSpikes(\n                this __polygon3t__ self, __ftype__ toleranceInDegrees = __zerodotone__)\n        {\n            if (toleranceInDegrees < 0) throw new ArgumentOutOfRangeException();\n            var threshold = Conversion.RadiansFromDegrees(toleranceInDegrees).Cos();\n            var edges = self.GetEdgeArray();\n            edges.Apply(e => e.Normalized);\n            var ec = edges.Length;\n            if (Vec.Dot(-edges[ec - 1], edges[0]) > threshold) yield return 0;\n            for (int i = 1; i < ec; i++)\n            {\n                if (Vec.Dot(-edges[i - 1], edges[i]) > threshold) yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Returns true if at least one vertex\n        /// both outgoing edges meet at an angle that\n        /// is less than the given threshold.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool HasSpikes(\n                this __polygon3t__ self, __ftype__ toleranceInDegrees = __zerodotone__)\n        {\n            return GetSpikes(self, toleranceInDegrees).Any();\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Index__polygon3t__Extensions\n\n    public static partial class Index__polygon3t__Extensions\n    {\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __polygon2t__ To__polygon3t__(this Index__polygon3t__ polygon, __v2t__[] pointArray)\n            => new __polygon2t__(polygon.GetPointArray(pointArray));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __polygon2t__ To__polygon3t__(this Index__polygon3t__ polygon, List<__v2t__> pointList)\n            => new __polygon2t__(polygon.GetPointArray(pointList));\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/PolygonExtensions_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class IPolygonExtensions\n    {\n        // AUTO GENERATED CODE - DO NOT CHANGE!\n\n        #region Conversions\n\n        public static IEnumerable<T> GetPoints<T>(this IPolygon<T> polygon)\n        {\n            var pc = polygon.PointCount;\n            for (int pi = 0; pi < pc; pi++) yield return polygon[pi];\n        }\n\n        public static T[] GetPointArray<T>(this IPolygon<T> polygon)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = polygon[pi];\n            return pointArray;\n        }\n\n        public static TCopy[] GetPointArray<TCopy, T>(\n                this IPolygon<T> polygon, Func<T, TCopy> point_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new TCopy[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_copyFun(polygon[pi]);\n            return pointArray;\n        }\n\n        #region Polygon2f\n\n        public static Polygon2f ToPolygon2f<T>(\n                this IPolygon<T> polygon, Func<T, V2f> point_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new V2f[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_copyFun(polygon[pi]);\n            return new Polygon2f(pointArray);\n        }\n\n        public static Polygon2f ToPolygon2f<T>(\n                this IPolygon<T> polygon, Func<T, int, V2f> point_index_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new V2f[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_index_copyFun(polygon[pi], pi);\n            return new Polygon2f(pointArray);\n        }\n\n        #endregion\n\n        #region Polygon3f\n\n        public static Polygon3f ToPolygon3f<T>(\n                this IPolygon<T> polygon, Func<T, V3f> point_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new V3f[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_copyFun(polygon[pi]);\n            return new Polygon3f(pointArray);\n        }\n\n        public static Polygon3f ToPolygon3f<T>(\n                this IPolygon<T> polygon, Func<T, int, V3f> point_index_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new V3f[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_index_copyFun(polygon[pi], pi);\n            return new Polygon3f(pointArray);\n        }\n\n        #endregion\n\n        #region Polygon2d\n\n        public static Polygon2d ToPolygon2d<T>(\n                this IPolygon<T> polygon, Func<T, V2d> point_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new V2d[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_copyFun(polygon[pi]);\n            return new Polygon2d(pointArray);\n        }\n\n        public static Polygon2d ToPolygon2d<T>(\n                this IPolygon<T> polygon, Func<T, int, V2d> point_index_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new V2d[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_index_copyFun(polygon[pi], pi);\n            return new Polygon2d(pointArray);\n        }\n\n        #endregion\n\n        #region Polygon3d\n\n        public static Polygon3d ToPolygon3d<T>(\n                this IPolygon<T> polygon, Func<T, V3d> point_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new V3d[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_copyFun(polygon[pi]);\n            return new Polygon3d(pointArray);\n        }\n\n        public static Polygon3d ToPolygon3d<T>(\n                this IPolygon<T> polygon, Func<T, int, V3d> point_index_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new V3d[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_index_copyFun(polygon[pi], pi);\n            return new Polygon3d(pointArray);\n        }\n\n        #endregion\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Polygon/PolygonExtensions_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class IPolygonExtensions\n    {\n        // AUTO GENERATED CODE - DO NOT CHANGE!\n\n        #region Conversions\n\n        public static IEnumerable<T> GetPoints<T>(this IPolygon<T> polygon)\n        {\n            var pc = polygon.PointCount;\n            for (int pi = 0; pi < pc; pi++) yield return polygon[pi];\n        }\n\n        public static T[] GetPointArray<T>(this IPolygon<T> polygon)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new T[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = polygon[pi];\n            return pointArray;\n        }\n\n        public static TCopy[] GetPointArray<TCopy, T>(\n                this IPolygon<T> polygon, Func<T, TCopy> point_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new TCopy[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_copyFun(polygon[pi]);\n            return pointArray;\n        }\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var polygon2t = \"Polygon2\" + tc;\n        //#   var polygon3t = \"Polygon3\" + tc;\n        //#   var v2t = \"V2\" + tc;\n        //#   var v3t = \"V3\" + tc;\n        #region __polygon2t__\n\n        public static __polygon2t__ To__polygon2t__<T>(\n                this IPolygon<T> polygon, Func<T, __v2t__> point_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new __v2t__[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_copyFun(polygon[pi]);\n            return new __polygon2t__(pointArray);\n        }\n\n        public static __polygon2t__ To__polygon2t__<T>(\n                this IPolygon<T> polygon, Func<T, int, __v2t__> point_index_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new __v2t__[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_index_copyFun(polygon[pi], pi);\n            return new __polygon2t__(pointArray);\n        }\n\n        #endregion\n\n        #region __polygon3t__\n\n        public static __polygon3t__ To__polygon3t__<T>(\n                this IPolygon<T> polygon, Func<T, __v3t__> point_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new __v3t__[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_copyFun(polygon[pi]);\n            return new __polygon3t__(pointArray);\n        }\n\n        public static __polygon3t__ To__polygon3t__<T>(\n                this IPolygon<T> polygon, Func<T, int, __v3t__> point_index_copyFun)\n        {\n            var pc = polygon.PointCount;\n            var pointArray = new __v3t__[pc];\n            for (int pi = 0; pi < pc; pi++) pointArray[pi] = point_index_copyFun(polygon[pi], pi);\n            return new __polygon3t__(pointArray);\n        }\n\n        #endregion\n\n        //# }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Quad/Quad2_auto.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Quad2f\n\n    /// <summary>\n    /// A two-dimensional quadrangle specified by its four points.\n    /// </summary>\n    public partial struct Quad2f\n    {\n        #region Geometric Properties\n\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 0.5f * ((P2.X - P0.X) * (P3.Y - P1.Y) - (P3.X - P1.X) * (P2.Y - P0.Y)).Abs();\n        }\n\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P1 - P0).AllTiny || (P2 - P1).AllTiny || (P3 - P2).AllTiny || (P0 - P3).AllTiny || WindingOrder.IsTiny();\n        }\n\n        /// <summary>\n        /// Returns a value less than zero for ccw and greater than zero for cw.\n        /// The magnitude magnitude is twice the area.\n        /// </summary>\n        public readonly float WindingOrder\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P2.X - P0.X) * (P3.Y - P1.Y) - (P3.X - P1.X) * (P2.Y - P0.Y);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Quad2d\n\n    /// <summary>\n    /// A two-dimensional quadrangle specified by its four points.\n    /// </summary>\n    public partial struct Quad2d\n    {\n        #region Geometric Properties\n\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 0.5 * ((P2.X - P0.X) * (P3.Y - P1.Y) - (P3.X - P1.X) * (P2.Y - P0.Y)).Abs();\n        }\n\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P1 - P0).AllTiny || (P2 - P1).AllTiny || (P3 - P2).AllTiny || (P0 - P3).AllTiny || WindingOrder.IsTiny();\n        }\n\n        /// <summary>\n        /// Returns a value less than zero for ccw and greater than zero for cw.\n        /// The magnitude magnitude is twice the area.\n        /// </summary>\n        public readonly double WindingOrder\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P2.X - P0.X) * (P3.Y - P1.Y) - (P3.X - P1.X) * (P2.Y - P0.Y);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Quad/Quad2_template.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var type = \"Quad2\" + tc;\n    //#   var v2t = \"V2\" + tc;\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    #region __type__\n\n    /// <summary>\n    /// A two-dimensional quadrangle specified by its four points.\n    /// </summary>\n    public partial struct __type__\n    {\n        #region Geometric Properties\n\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => __half__ * ((P2.X - P0.X) * (P3.Y - P1.Y) - (P3.X - P1.X) * (P2.Y - P0.Y)).Abs();\n        }\n\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P1 - P0).AllTiny || (P2 - P1).AllTiny || (P3 - P2).AllTiny || (P0 - P3).AllTiny || WindingOrder.IsTiny();\n        }\n\n        /// <summary>\n        /// Returns a value less than zero for ccw and greater than zero for cw.\n        /// The magnitude magnitude is twice the area.\n        /// </summary>\n        public readonly __ftype__ WindingOrder\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (P2.X - P0.X) * (P3.Y - P1.Y) - (P3.X - P1.X) * (P2.Y - P0.Y);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Quad/Quad3_auto.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Quad3f\n\n    /// <summary>\n    /// A three-dimensional quadrangle specified by its four points.\n    /// The points are not required to lie on the same plane.\n    /// </summary>\n    public partial struct Quad3f\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area when projected onto a plane normal to the area\n        /// weighted average normal of the triangles (P0,P1,P2) and (P0,P2,P3).\n        /// </summary>\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var v02 = P2 - P0;\n                return 0.5f * ((P1 - P0).Cross(v02) + v02.Cross(P3 - P0)).Length;\n            }\n        }\n\n        public readonly bool IsDegenerated\n        {\n            get\n            {\n                var v01 = P1 - P0; if (v01.AllTiny) return true;\n                var v03 = P3 - P0; if (v03.AllTiny) return true;\n                if ((P2 - P1).AllTiny || (P3 - P2).AllTiny) return true;\n                var v02 = P2 - P0;\n                return (v01.Cross(v02) + v02.Cross(v03)).AllTiny;\n            }\n        }\n\n        public readonly V3f Normal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var v02 = P2 - P0;\n                return ((P1 - P0).Cross(v02) + v02.Cross(P3 - P0)).Normalized;\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Quad3d\n\n    /// <summary>\n    /// A three-dimensional quadrangle specified by its four points.\n    /// The points are not required to lie on the same plane.\n    /// </summary>\n    public partial struct Quad3d\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area when projected onto a plane normal to the area\n        /// weighted average normal of the triangles (P0,P1,P2) and (P0,P2,P3).\n        /// </summary>\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var v02 = P2 - P0;\n                return 0.5 * ((P1 - P0).Cross(v02) + v02.Cross(P3 - P0)).Length;\n            }\n        }\n\n        public readonly bool IsDegenerated\n        {\n            get\n            {\n                var v01 = P1 - P0; if (v01.AllTiny) return true;\n                var v03 = P3 - P0; if (v03.AllTiny) return true;\n                if ((P2 - P1).AllTiny || (P3 - P2).AllTiny) return true;\n                var v02 = P2 - P0;\n                return (v01.Cross(v02) + v02.Cross(v03)).AllTiny;\n            }\n        }\n\n        public readonly V3d Normal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var v02 = P2 - P0;\n                return ((P1 - P0).Cross(v02) + v02.Cross(P3 - P0)).Normalized;\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Quad/Quad3_template.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var type = \"Quad3\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    #region __type__\n\n    /// <summary>\n    /// A three-dimensional quadrangle specified by its four points.\n    /// The points are not required to lie on the same plane.\n    /// </summary>\n    public partial struct __type__\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area when projected onto a plane normal to the area\n        /// weighted average normal of the triangles (P0,P1,P2) and (P0,P2,P3).\n        /// </summary>\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var v02 = P2 - P0;\n                return __half__ * ((P1 - P0).Cross(v02) + v02.Cross(P3 - P0)).Length;\n            }\n        }\n\n        public readonly bool IsDegenerated\n        {\n            get\n            {\n                var v01 = P1 - P0; if (v01.AllTiny) return true;\n                var v03 = P3 - P0; if (v03.AllTiny) return true;\n                if ((P2 - P1).AllTiny || (P3 - P2).AllTiny) return true;\n                var v02 = P2 - P0;\n                return (v01.Cross(v02) + v02.Cross(v03)).AllTiny;\n            }\n        }\n\n        public readonly __v3t__ Normal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var v02 = P2 - P0;\n                return ((P1 - P0).Cross(v02) + v02.Cross(P3 - P0)).Normalized;\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Quadric/Quadric_auto.cs",
    "content": "using System;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region QuadricF\n\n    public struct QuadricF\n    {\n        V3f m_normal;\n        M44f m_errorQuadric;\n\n        #region Properties\n\n        public V3f Normal\n        {\n            readonly get { return m_normal.Normalized; }\n            set { m_normal = value; }\n        }\n\n        public M44f ErrorQuadric\n        {\n            readonly get { return m_errorQuadric; }\n            set { m_errorQuadric = value; }\n        }\n\n        public readonly float ErrorOffset => ErrorQuadric.M33;\n\n        public M44f ErrorHeuristic { readonly get; set; }\n\n        #endregion\n\n        public void Create(Plane3f plane)\n        {\n            CreateQuadric(plane);\n            CreateHeuristic();\n        }\n\n        #region Create QuadricF/Heuristic\n\n        public void CreateQuadric(Plane3f plane)\n        {\n            Normal = plane.Normal;\n            float a = Normal.X;\n            float b = Normal.Y;\n            float c = Normal.Z;\n\n            // Garland uses \"ax + by + cz + d = 0\"\n            // Aardvark uses \"ax + by + cz - d = 0\"\n            float d = -plane.Distance;\n\n            m_errorQuadric.M00 = a * a;\n            m_errorQuadric.M11 = b * b;\n            m_errorQuadric.M22 = c * c;\n            m_errorQuadric.M33 = d * d;\n\n            m_errorQuadric.M01 = m_errorQuadric.M10 = a * b;\n            m_errorQuadric.M02 = m_errorQuadric.M20 = a * c;\n            m_errorQuadric.M03 = m_errorQuadric.M30 = a * d;\n            m_errorQuadric.M12 = m_errorQuadric.M21 = b * c;\n            m_errorQuadric.M13 = m_errorQuadric.M31 = b * d;\n            m_errorQuadric.M23 = m_errorQuadric.M32 = c * d;\n        }\n\n        public void CreateHeuristic()\n        {\n            if (m_errorQuadric == M44f.Zero)\n            {\n                throw new InvalidOperationException(\"Must call CreateQuadric(...) first\");\n            }\n\n            ErrorHeuristic = ToHeuristic(ErrorQuadric);\n        }\n\n        #endregion\n\n        #region Operator Overload\n\n        public static QuadricF operator +(QuadricF lhs, QuadricF rhs)\n        {\n            var result = new QuadricF\n            {\n                ErrorQuadric = lhs.ErrorQuadric + rhs.ErrorQuadric,\n                Normal = lhs.Normal + rhs.Normal\n            };\n\n            result.ErrorHeuristic = ToHeuristic(result.ErrorQuadric);\n\n            return result;\n        }\n\n        //public static QuadricF operator -(QuadricF lhs, QuadricF rhs)\n        //{\n        //    QuadricF result = new QuadricF();\n\n        //    result.ErrorQuadric = lhs.ErrorQuadric - rhs.ErrorQuadric;\n\n        //    result.ErrorHeuristic = QuadricF.ToHeuristic(result.ErrorQuadric);\n\n        //    return result;\n        //}\n\n        #endregion\n\n        #region Static Methods\n\n        static M44f ToHeuristic(M44f quadric)\n        {\n            var result = new M44f();\n\n            result = quadric;\n            result.R3 = new V4f(0, 0, 0, 1);\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region QuadricD\n\n    public struct QuadricD\n    {\n        V3d m_normal;\n        M44d m_errorQuadric;\n\n        #region Properties\n\n        public V3d Normal\n        {\n            readonly get { return m_normal.Normalized; }\n            set { m_normal = value; }\n        }\n\n        public M44d ErrorQuadric\n        {\n            readonly get { return m_errorQuadric; }\n            set { m_errorQuadric = value; }\n        }\n\n        public readonly double ErrorOffset => ErrorQuadric.M33;\n\n        public M44d ErrorHeuristic { readonly get; set; }\n\n        #endregion\n\n        public void Create(Plane3d plane)\n        {\n            CreateQuadric(plane);\n            CreateHeuristic();\n        }\n\n        #region Create QuadricD/Heuristic\n\n        public void CreateQuadric(Plane3d plane)\n        {\n            Normal = plane.Normal;\n            double a = Normal.X;\n            double b = Normal.Y;\n            double c = Normal.Z;\n\n            // Garland uses \"ax + by + cz + d = 0\"\n            // Aardvark uses \"ax + by + cz - d = 0\"\n            double d = -plane.Distance;\n\n            m_errorQuadric.M00 = a * a;\n            m_errorQuadric.M11 = b * b;\n            m_errorQuadric.M22 = c * c;\n            m_errorQuadric.M33 = d * d;\n\n            m_errorQuadric.M01 = m_errorQuadric.M10 = a * b;\n            m_errorQuadric.M02 = m_errorQuadric.M20 = a * c;\n            m_errorQuadric.M03 = m_errorQuadric.M30 = a * d;\n            m_errorQuadric.M12 = m_errorQuadric.M21 = b * c;\n            m_errorQuadric.M13 = m_errorQuadric.M31 = b * d;\n            m_errorQuadric.M23 = m_errorQuadric.M32 = c * d;\n        }\n\n        public void CreateHeuristic()\n        {\n            if (m_errorQuadric == M44d.Zero)\n            {\n                throw new InvalidOperationException(\"Must call CreateQuadric(...) first\");\n            }\n\n            ErrorHeuristic = ToHeuristic(ErrorQuadric);\n        }\n\n        #endregion\n\n        #region Operator Overload\n\n        public static QuadricD operator +(QuadricD lhs, QuadricD rhs)\n        {\n            var result = new QuadricD\n            {\n                ErrorQuadric = lhs.ErrorQuadric + rhs.ErrorQuadric,\n                Normal = lhs.Normal + rhs.Normal\n            };\n\n            result.ErrorHeuristic = ToHeuristic(result.ErrorQuadric);\n\n            return result;\n        }\n\n        //public static QuadricD operator -(QuadricD lhs, QuadricD rhs)\n        //{\n        //    QuadricD result = new QuadricD();\n\n        //    result.ErrorQuadric = lhs.ErrorQuadric - rhs.ErrorQuadric;\n\n        //    result.ErrorHeuristic = QuadricD.ToHeuristic(result.ErrorQuadric);\n\n        //    return result;\n        //}\n\n        #endregion\n\n        #region Static Methods\n\n        static M44d ToHeuristic(M44d quadric)\n        {\n            var result = new M44d();\n\n            result = quadric;\n            result.R3 = new V4d(0, 0, 0, 1);\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Quadric/Quadric_template.cs",
    "content": "﻿using System;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var tccaps = tc.ToUpper();\n    //#   var tccaps2 = tc2.ToUpper();\n    //#   var type = \"Quadric\" + tccaps;\n    //#   var type2 = \"Quadric\" + tccaps2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var v4t = \"V4\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var m44t = \"M44\" + tc;\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    #region __type__\n\n    public struct __type__\n    {\n        __v3t__ m_normal;\n        __m44t__ m_errorQuadric;\n\n        #region Properties\n\n        public __v3t__ Normal\n        {\n            readonly get { return m_normal.Normalized; }\n            set { m_normal = value; }\n        }\n\n        public __m44t__ ErrorQuadric\n        {\n            readonly get { return m_errorQuadric; }\n            set { m_errorQuadric = value; }\n        }\n\n        public readonly __ftype__ ErrorOffset => ErrorQuadric.M33;\n\n        public __m44t__ ErrorHeuristic { readonly get; set; }\n\n        #endregion\n\n        public void Create(__plane3t__ plane)\n        {\n            CreateQuadric(plane);\n            CreateHeuristic();\n        }\n\n        #region Create __type__/Heuristic\n\n        public void CreateQuadric(__plane3t__ plane)\n        {\n            Normal = plane.Normal;\n            __ftype__ a = Normal.X;\n            __ftype__ b = Normal.Y;\n            __ftype__ c = Normal.Z;\n\n            // Garland uses \"ax + by + cz + d = 0\"\n            // Aardvark uses \"ax + by + cz - d = 0\"\n            __ftype__ d = -plane.Distance;\n\n            m_errorQuadric.M00 = a * a;\n            m_errorQuadric.M11 = b * b;\n            m_errorQuadric.M22 = c * c;\n            m_errorQuadric.M33 = d * d;\n\n            m_errorQuadric.M01 = m_errorQuadric.M10 = a * b;\n            m_errorQuadric.M02 = m_errorQuadric.M20 = a * c;\n            m_errorQuadric.M03 = m_errorQuadric.M30 = a * d;\n            m_errorQuadric.M12 = m_errorQuadric.M21 = b * c;\n            m_errorQuadric.M13 = m_errorQuadric.M31 = b * d;\n            m_errorQuadric.M23 = m_errorQuadric.M32 = c * d;\n        }\n\n        public void CreateHeuristic()\n        {\n            if (m_errorQuadric == __m44t__.Zero)\n            {\n                throw new InvalidOperationException(\"Must call CreateQuadric(...) first\");\n            }\n\n            ErrorHeuristic = ToHeuristic(ErrorQuadric);\n        }\n\n        #endregion\n\n        #region Operator Overload\n\n        public static __type__ operator +(__type__ lhs, __type__ rhs)\n        {\n            var result = new __type__\n            {\n                ErrorQuadric = lhs.ErrorQuadric + rhs.ErrorQuadric,\n                Normal = lhs.Normal + rhs.Normal\n            };\n\n            result.ErrorHeuristic = ToHeuristic(result.ErrorQuadric);\n\n            return result;\n        }\n\n        //public static __type__ operator -(__type__ lhs, __type__ rhs)\n        //{\n        //    __type__ result = new __type__();\n\n        //    result.ErrorQuadric = lhs.ErrorQuadric - rhs.ErrorQuadric;\n\n        //    result.ErrorHeuristic = __type__.ToHeuristic(result.ErrorQuadric);\n\n        //    return result;\n        //}\n\n        #endregion\n\n        #region Static Methods\n\n        static __m44t__ ToHeuristic(__m44t__ quadric)\n        {\n            var result = new __m44t__();\n\n            result = quadric;\n            result.R3 = new __v4t__(0, 0, 0, 1);\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ray/Ray2_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Ray2f\n\n    /// <summary>\n    /// A two-dimensional ray with an origin and a direction.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Ray2f : IEquatable<Ray2f>, IValidity, IBoundingBox2f\n    {\n        [DataMember]\n        public V2f Origin;\n        [DataMember]\n        public V2f Direction;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates Ray from origin point and directional vector\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ray2f(V2f origin, V2f direction)\n        {\n            Origin = origin;\n            Direction = direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ray2f(Ray2f o)\n        {\n            Origin = o.Origin;\n            Direction = o.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ray2f(Ray2d o)\n        {\n            Origin = (V2f)o.Origin;\n            Direction = (V2f)o.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Ray2f FromEndPoints(V2f origin, V2f target)\n            => new Ray2f(origin, target - origin);\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Ray2f(Ray2d c)\n            => new Ray2f(c);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// An invalid ray has a zero direction.\n        /// </summary>\n        public static Ray2f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ray2f(V2f.NaN, V2f.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// A ray is valid if its direction is non-zero.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction != V2f.Zero;\n        }\n\n        /// <summary>\n        /// A ray is invalid if its direction is zero.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction == V2f.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if either the origin or the direction contains any NaN value.\n        /// </summary>\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Origin.AnyNaN || Direction.AnyNaN;\n        }\n\n        public readonly Line2f Line2f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Line2f(Origin, Origin + Direction);\n        }\n\n        public readonly Plane2f Plane2f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2f(new V2f(-Direction.Y, Direction.X), Origin); // Direction.Rot90\n        }\n\n        public readonly Ray2f Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ray2f(Origin, -Direction);\n        }\n\n        /// <summary>\n        /// Returns the ray with its directional normalized.\n        /// </summary>\n        public readonly Ray2f Normalized => new(Origin, Direction.Normalized);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        /// <summary>\n        /// Gets the point on the ray that is t * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f GetPointOnRay(float t) => (Origin + Direction * t);\n\n        /// <summary>\n        /// Gets segment on the ray starting at range.Min * direction from origin\n        /// and ending at range.Max * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Line2f GetLine2fOnRay(Range1f range)\n            => new Line2f(Origin + Direction * range.Min, Origin + Direction * range.Max);\n\n        /// <summary>\n        /// Gets segment on the ray starting at tMin * direction from origin\n        /// and ending at tMax * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Line2f GetLine2fOnRay(float tMin, float tMax)\n            => new Line2f(Origin + Direction * tMin, Origin + Direction * tMax);\n\n        /// <summary>\n        /// Gets the t for a point p on this ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float GetT(V2f p)\n        {\n            var v = p - Origin;\n            return (Direction.X.Abs() > Direction.Y.Abs())\n                ? (v.X / Direction.X)\n                : (v.Y / Direction.Y);\n        }\n\n        /// <summary>\n        /// Gets the point on the ray that is closest to the given point.\n        /// Ray direction must be normalized (length 1).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f GetClosestPointOnRay(V2f p)\n            => Origin + Direction * Direction.Dot(p - Origin);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float GetDistanceToRay(V2f p)\n        {\n            var f = GetClosestPointOnRay(p);\n            return (f - p).Length;\n        }\n\n        public readonly V2f Intersect(Ray2f r)\n        {\n            V2f a = r.Origin - Origin;\n            if (a.Abs().AllSmaller(Constant<float>.PositiveTinyValue))\n                return Origin; // Early exit when rays have same origin\n\n            float cross = Direction.Dot270(r.Direction);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n                return Origin + Direction * r.Direction.Dot90(a) / cross;\n            else // Rays are parallel\n                return V2f.NaN;\n        }\n\n        public readonly V2f Intersect(V2f dirVector)\n        {\n            if (Origin.Abs().AllSmaller(Constant<float>.PositiveTinyValue))\n                return Origin; // Early exit when rays have same origin\n\n            float cross = Direction.Dot270(dirVector);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n                return Origin + Direction * dirVector.Dot270(Origin) / cross;\n            else // Rays are parallel\n                return V2f.NaN;\n        }\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"Ray2f\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float AngleBetweenFast(Ray2f r)\n            => Direction.AngleBetweenFast(r.Direction);\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"Ray2f\"/> in radians using a numerically stable algorithm.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float AngleBetween(Ray2f r)\n            => Direction.AngleBetween(r.Direction);\n\n        /// <summary>\n        /// Returns the signed angle between this and the given <see cref=\"Ray2f\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float AngleBetweenSigned(Ray2f r)\n            => Direction.AngleBetweenSigned(r.Direction);\n\n        /// <summary>\n        /// Returns a signed value where left is negative and right positive.\n        /// The magnitude is equal to the float size of the triangle the ray + direction and p.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float GetPointSide(V2f p) => Direction.Dot90(p - Origin);\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Ray2f a, Ray2f b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Ray2f a, Ray2f b)\n            => !((a.Origin == b.Origin) && (a.Direction == b.Direction));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int LexicalCompare(Ray2f other)\n        {\n            var cmp = Origin.LexicalCompare(other.Origin);\n            if (cmp != 0) return cmp;\n            return Direction.LexicalCompare(other.Direction);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        /// <summary>\n        /// Calculates Hash-code of the given ray.\n        /// </summary>\n        /// <returns>Hash-code.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Ray2f other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Ray2f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Ray2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Ray2f(V2f.Parse(x[0]), V2f.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox2f\n\n        public readonly Box2f BoundingBox2f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Box2f.FromPoints(Origin, Direction + Origin);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ray2f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ray2f a, Ray2f b, float tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ray2f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ray2f a, Ray2f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region FastRay2f\n\n    /// <summary>\n    /// A fast ray contains a ray and a number of precomputed flags and\n    /// fields for fast intersection computation with bounding boxes and\n    /// other axis-aligned sturctures such as kd-Trees.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct FastRay2f\n    {\n        [DataMember]\n        public readonly Ray2f Ray;\n        [DataMember]\n        public readonly DirFlags DirFlags;\n        [DataMember]\n        public readonly V2f InvDir;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastRay2f(Ray2f ray)\n        {\n            Ray = ray;\n            DirFlags = ray.Direction.DirFlags();\n            InvDir = 1 / ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastRay2f(V2f origin, V2f direction)\n            : this(new Ray2f(origin, direction))\n        { }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastRay2f(FastRay2f o)\n        {\n            Ray = o.Ray;\n            DirFlags = o.DirFlags;\n            InvDir = o.InvDir;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastRay2f(FastRay2d o)\n        {\n            Ray = (Ray2f)o.Ray;\n            DirFlags = o.DirFlags;\n            InvDir = (V2f)o.InvDir;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator FastRay2f(FastRay2d r)\n            => new FastRay2f(r);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        public bool Intersects(\n            Box2f box,\n            ref float tmin,\n            ref float tmax\n        )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else    // ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else    // ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method returns the affected\n        /// planes of the box if the box was hit.\n        /// </summary>\n        public bool Intersects(\n            Box2f box,\n            ref float tmin,\n            ref float tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n        )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else    // ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else    // ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Ray2d\n\n    /// <summary>\n    /// A two-dimensional ray with an origin and a direction.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Ray2d : IEquatable<Ray2d>, IValidity, IBoundingBox2d\n    {\n        [DataMember]\n        public V2d Origin;\n        [DataMember]\n        public V2d Direction;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates Ray from origin point and directional vector\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ray2d(V2d origin, V2d direction)\n        {\n            Origin = origin;\n            Direction = direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ray2d(Ray2d o)\n        {\n            Origin = o.Origin;\n            Direction = o.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Ray2d(Ray2f o)\n        {\n            Origin = (V2d)o.Origin;\n            Direction = (V2d)o.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Ray2d FromEndPoints(V2d origin, V2d target)\n            => new Ray2d(origin, target - origin);\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Ray2d(Ray2f c)\n            => new Ray2d(c);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// An invalid ray has a zero direction.\n        /// </summary>\n        public static Ray2d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ray2d(V2d.NaN, V2d.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// A ray is valid if its direction is non-zero.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction != V2d.Zero;\n        }\n\n        /// <summary>\n        /// A ray is invalid if its direction is zero.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction == V2d.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if either the origin or the direction contains any NaN value.\n        /// </summary>\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Origin.AnyNaN || Direction.AnyNaN;\n        }\n\n        public readonly Line2d Line2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Line2d(Origin, Origin + Direction);\n        }\n\n        public readonly Plane2d Plane2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Plane2d(new V2d(-Direction.Y, Direction.X), Origin); // Direction.Rot90\n        }\n\n        public readonly Ray2d Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Ray2d(Origin, -Direction);\n        }\n\n        /// <summary>\n        /// Returns the ray with its directional normalized.\n        /// </summary>\n        public readonly Ray2d Normalized => new(Origin, Direction.Normalized);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        /// <summary>\n        /// Gets the point on the ray that is t * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d GetPointOnRay(double t) => (Origin + Direction * t);\n\n        /// <summary>\n        /// Gets segment on the ray starting at range.Min * direction from origin\n        /// and ending at range.Max * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Line2d GetLine2dOnRay(Range1d range)\n            => new Line2d(Origin + Direction * range.Min, Origin + Direction * range.Max);\n\n        /// <summary>\n        /// Gets segment on the ray starting at tMin * direction from origin\n        /// and ending at tMax * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Line2d GetLine2dOnRay(double tMin, double tMax)\n            => new Line2d(Origin + Direction * tMin, Origin + Direction * tMax);\n\n        /// <summary>\n        /// Gets the t for a point p on this ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double GetT(V2d p)\n        {\n            var v = p - Origin;\n            return (Direction.X.Abs() > Direction.Y.Abs())\n                ? (v.X / Direction.X)\n                : (v.Y / Direction.Y);\n        }\n\n        /// <summary>\n        /// Gets the point on the ray that is closest to the given point.\n        /// Ray direction must be normalized (length 1).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d GetClosestPointOnRay(V2d p)\n            => Origin + Direction * Direction.Dot(p - Origin);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double GetDistanceToRay(V2d p)\n        {\n            var f = GetClosestPointOnRay(p);\n            return (f - p).Length;\n        }\n\n        public readonly V2d Intersect(Ray2d r)\n        {\n            V2d a = r.Origin - Origin;\n            if (a.Abs().AllSmaller(Constant<double>.PositiveTinyValue))\n                return Origin; // Early exit when rays have same origin\n\n            double cross = Direction.Dot270(r.Direction);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n                return Origin + Direction * r.Direction.Dot90(a) / cross;\n            else // Rays are parallel\n                return V2d.NaN;\n        }\n\n        public readonly V2d Intersect(V2d dirVector)\n        {\n            if (Origin.Abs().AllSmaller(Constant<double>.PositiveTinyValue))\n                return Origin; // Early exit when rays have same origin\n\n            double cross = Direction.Dot270(dirVector);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n                return Origin + Direction * dirVector.Dot270(Origin) / cross;\n            else // Rays are parallel\n                return V2d.NaN;\n        }\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"Ray2d\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double AngleBetweenFast(Ray2d r)\n            => Direction.AngleBetweenFast(r.Direction);\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"Ray2d\"/> in radians using a numerically stable algorithm.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double AngleBetween(Ray2d r)\n            => Direction.AngleBetween(r.Direction);\n\n        /// <summary>\n        /// Returns the signed angle between this and the given <see cref=\"Ray2d\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double AngleBetweenSigned(Ray2d r)\n            => Direction.AngleBetweenSigned(r.Direction);\n\n        /// <summary>\n        /// Returns a signed value where left is negative and right positive.\n        /// The magnitude is equal to the double size of the triangle the ray + direction and p.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double GetPointSide(V2d p) => Direction.Dot90(p - Origin);\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Ray2d a, Ray2d b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Ray2d a, Ray2d b)\n            => !((a.Origin == b.Origin) && (a.Direction == b.Direction));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int LexicalCompare(Ray2d other)\n        {\n            var cmp = Origin.LexicalCompare(other.Origin);\n            if (cmp != 0) return cmp;\n            return Direction.LexicalCompare(other.Direction);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        /// <summary>\n        /// Calculates Hash-code of the given ray.\n        /// </summary>\n        /// <returns>Hash-code.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Ray2d other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Ray2d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Ray2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Ray2d(V2d.Parse(x[0]), V2d.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox2d\n\n        public readonly Box2d BoundingBox2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Box2d.FromPoints(Origin, Direction + Origin);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ray2d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ray2d a, Ray2d b, double tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ray2d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ray2d a, Ray2d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region FastRay2d\n\n    /// <summary>\n    /// A fast ray contains a ray and a number of precomputed flags and\n    /// fields for fast intersection computation with bounding boxes and\n    /// other axis-aligned sturctures such as kd-Trees.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct FastRay2d\n    {\n        [DataMember]\n        public readonly Ray2d Ray;\n        [DataMember]\n        public readonly DirFlags DirFlags;\n        [DataMember]\n        public readonly V2d InvDir;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastRay2d(Ray2d ray)\n        {\n            Ray = ray;\n            DirFlags = ray.Direction.DirFlags();\n            InvDir = 1 / ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastRay2d(V2d origin, V2d direction)\n            : this(new Ray2d(origin, direction))\n        { }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastRay2d(FastRay2d o)\n        {\n            Ray = o.Ray;\n            DirFlags = o.DirFlags;\n            InvDir = o.InvDir;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public FastRay2d(FastRay2f o)\n        {\n            Ray = (Ray2d)o.Ray;\n            DirFlags = o.DirFlags;\n            InvDir = (V2d)o.InvDir;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator FastRay2d(FastRay2f r)\n            => new FastRay2d(r);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        public bool Intersects(\n            Box2d box,\n            ref double tmin,\n            ref double tmax\n        )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else    // ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else    // ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method returns the affected\n        /// planes of the box if the box was hit.\n        /// </summary>\n        public bool Intersects(\n            Box2d box,\n            ref double tmin,\n            ref double tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n        )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else    // ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else    // ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ray/Ray2_template.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var ray2t = \"Ray2\" + tc;\n    //#   var ray2t2 = \"Ray2\" + tc2;\n    //#   var fastray2t = \"FastRay2\" + tc;\n    //#   var fastray2t2 = \"FastRay2\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var range1t = \"Range1\" + tc;\n    //#   var box2t = \"Box2\" + tc;\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var line2t = \"Line2\" + tc;\n    //#   var iboundingbox = \"IBoundingBox2\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    #region __ray2t__\n\n    /// <summary>\n    /// A two-dimensional ray with an origin and a direction.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __ray2t__ : IEquatable<__ray2t__>, IValidity, __iboundingbox__\n    {\n        [DataMember]\n        public __v2t__ Origin;\n        [DataMember]\n        public __v2t__ Direction;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates Ray from origin point and directional vector\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __ray2t__(__v2t__ origin, __v2t__ direction)\n        {\n            Origin = origin;\n            Direction = direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __ray2t__(__ray2t__ o)\n        {\n            Origin = o.Origin;\n            Direction = o.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __ray2t__(__ray2t2__ o)\n        {\n            Origin = (__v2t__)o.Origin;\n            Direction = (__v2t__)o.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ray2t__ FromEndPoints(__v2t__ origin, __v2t__ target)\n            => new __ray2t__(origin, target - origin);\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __ray2t__(__ray2t2__ c)\n            => new __ray2t__(c);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// An invalid ray has a zero direction.\n        /// </summary>\n        public static __ray2t__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ray2t__(__v2t__.NaN, __v2t__.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// A ray is valid if its direction is non-zero.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction != __v2t__.Zero;\n        }\n\n        /// <summary>\n        /// A ray is invalid if its direction is zero.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Direction == __v2t__.Zero;\n        }\n\n        /// <summary>\n        /// Returns true if either the origin or the direction contains any NaN value.\n        /// </summary>\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Origin.AnyNaN || Direction.AnyNaN;\n        }\n\n        public readonly __line2t__ __line2t__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __line2t__(Origin, Origin + Direction);\n        }\n\n        public readonly __plane2t__ __plane2t__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __plane2t__(new __v2t__(-Direction.Y, Direction.X), Origin); // Direction.Rot90\n        }\n\n        public readonly __ray2t__ Reversed\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ray2t__(Origin, -Direction);\n        }\n\n        /// <summary>\n        /// Returns the ray with its directional normalized.\n        /// </summary>\n        public readonly __ray2t__ Normalized => new(Origin, Direction.Normalized);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        /// <summary>\n        /// Gets the point on the ray that is t * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __v2t__ GetPointOnRay(__ftype__ t) => (Origin + Direction * t);\n\n        /// <summary>\n        /// Gets segment on the ray starting at range.Min * direction from origin\n        /// and ending at range.Max * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __line2t__ Get__line2t__OnRay(__range1t__ range)\n            => new __line2t__(Origin + Direction * range.Min, Origin + Direction * range.Max);\n\n        /// <summary>\n        /// Gets segment on the ray starting at tMin * direction from origin\n        /// and ending at tMax * direction from origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __line2t__ Get__line2t__OnRay(__ftype__ tMin, __ftype__ tMax)\n            => new __line2t__(Origin + Direction * tMin, Origin + Direction * tMax);\n\n        /// <summary>\n        /// Gets the t for a point p on this ray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ GetT(__v2t__ p)\n        {\n            var v = p - Origin;\n            return (Direction.X.Abs() > Direction.Y.Abs())\n                ? (v.X / Direction.X)\n                : (v.Y / Direction.Y);\n        }\n\n        /// <summary>\n        /// Gets the point on the ray that is closest to the given point.\n        /// Ray direction must be normalized (length 1).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __v2t__ GetClosestPointOnRay(__v2t__ p)\n            => Origin + Direction * Direction.Dot(p - Origin);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ GetDistanceToRay(__v2t__ p)\n        {\n            var f = GetClosestPointOnRay(p);\n            return (f - p).Length;\n        }\n\n        public readonly __v2t__ Intersect(__ray2t__ r)\n        {\n            __v2t__ a = r.Origin - Origin;\n            if (a.Abs().AllSmaller(Constant<__ftype__>.PositiveTinyValue))\n                return Origin; // Early exit when rays have same origin\n\n            __ftype__ cross = Direction.Dot270(r.Direction);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n                return Origin + Direction * r.Direction.Dot90(a) / cross;\n            else // Rays are parallel\n                return __v2t__.NaN;\n        }\n\n        public readonly __v2t__ Intersect(__v2t__ dirVector)\n        {\n            if (Origin.Abs().AllSmaller(Constant<__ftype__>.PositiveTinyValue))\n                return Origin; // Early exit when rays have same origin\n\n            __ftype__ cross = Direction.Dot270(dirVector);\n            if (!Fun.IsTiny(cross)) // Rays not parallel\n                return Origin + Direction * dirVector.Dot270(Origin) / cross;\n            else // Rays are parallel\n                return __v2t__.NaN;\n        }\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"__ray2t__\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ AngleBetweenFast(__ray2t__ r)\n            => Direction.AngleBetweenFast(r.Direction);\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"__ray2t__\"/> in radians using a numerically stable algorithm.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ AngleBetween(__ray2t__ r)\n            => Direction.AngleBetween(r.Direction);\n\n        /// <summary>\n        /// Returns the signed angle between this and the given <see cref=\"__ray2t__\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ AngleBetweenSigned(__ray2t__ r)\n            => Direction.AngleBetweenSigned(r.Direction);\n\n        /// <summary>\n        /// Returns a signed value where left is negative and right positive.\n        /// The magnitude is equal to the __ftype__ size of the triangle the ray + direction and p.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ GetPointSide(__v2t__ p) => Direction.Dot90(p - Origin);\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__ray2t__ a, __ray2t__ b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__ray2t__ a, __ray2t__ b)\n            => !((a.Origin == b.Origin) && (a.Direction == b.Direction));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int LexicalCompare(__ray2t__ other)\n        {\n            var cmp = Origin.LexicalCompare(other.Origin);\n            if (cmp != 0) return cmp;\n            return Direction.LexicalCompare(other.Direction);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        /// <summary>\n        /// Calculates Hash-code of the given ray.\n        /// </summary>\n        /// <returns>Hash-code.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__ray2t__ other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __ray2t__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ray2t__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __ray2t__(__v2t__.Parse(x[0]), __v2t__.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region __iboundingbox__\n\n        public readonly __box2t__ BoundingBox2__tc__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => __box2t__.FromPoints(Origin, Direction + Origin);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ray2t__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __ray2t__ a, __ray2t__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ray2t__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __ray2t__ a, __ray2t__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region __fastray2t__\n\n    /// <summary>\n    /// A fast ray contains a ray and a number of precomputed flags and\n    /// fields for fast intersection computation with bounding boxes and\n    /// other axis-aligned sturctures such as kd-Trees.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct Fast__ray2t__\n    {\n        [DataMember]\n        public readonly __ray2t__ Ray;\n        [DataMember]\n        public readonly DirFlags DirFlags;\n        [DataMember]\n        public readonly __v2t__ InvDir;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fast__ray2t__(__ray2t__ ray)\n        {\n            Ray = ray;\n            DirFlags = ray.Direction.DirFlags();\n            InvDir = 1 / ray.Direction;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fast__ray2t__(__v2t__ origin, __v2t__ direction)\n            : this(new __ray2t__(origin, direction))\n        { }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fast__ray2t__(Fast__ray2t__ o)\n        {\n            Ray = o.Ray;\n            DirFlags = o.DirFlags;\n            InvDir = o.InvDir;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fast__ray2t__(Fast__ray2t2__ o)\n        {\n            Ray = (__ray2t__)o.Ray;\n            DirFlags = o.DirFlags;\n            InvDir = (__v2t__)o.InvDir;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Fast__ray2t__(Fast__ray2t2__ r)\n            => new Fast__ray2t__(r);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        public bool Intersects(\n            __box2t__ box,\n            ref __ftype__ tmin,\n            ref __ftype__ tmax\n        )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else    // ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else    // ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method returns the affected\n        /// planes of the box if the box was hit.\n        /// </summary>\n        public bool Intersects(\n            __box2t__ box,\n            ref __ftype__ tmin,\n            ref __ftype__ tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n        )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else    // ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else    // ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ray/Ray3_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Ray3f\n\n    /// <summary>\n    /// A three-dimensional ray with an origin and a direction.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Ray3f : IEquatable<Ray3f>, IValidity, IBoundingBox3f\n    {\n        [DataMember]\n        public V3f Origin;\n        [DataMember]\n        public V3f Direction;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates Ray from origin point and directional vector\n        /// </summary>\n        public Ray3f(V3f origin, V3f direction)\n        {\n            Origin = origin;\n            Direction = direction;\n        }\n\n        public static Ray3f FromEndPoints(V3f origin, V3f target) => new Ray3f(origin, target - origin);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// An invalid ray has a zero direction.\n        /// </summary>\n        public static readonly Ray3f Invalid = new Ray3f(V3f.NaN, V3f.Zero);\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// A ray is valid if its direction is non-zero.\n        /// </summary>\n        public readonly bool IsValid { get { return Direction != V3f.Zero; } }\n\n        /// <summary>\n        /// A ray is invalid if its direction is zero.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Direction == V3f.Zero; } }\n\n        /// <summary>\n        /// Returns true if either the origin or the direction contains any NaN value.\n        /// </summary>\n        public readonly bool AnyNaN { get { return Origin.AnyNaN || Direction.AnyNaN; } }\n\n        /// <summary>\n        /// Line segment from origin to origin + direction.\n        /// </summary>\n        public readonly Line3f Line3f => new Line3f(Origin, Origin + Direction);\n\n        /// <summary>\n        /// Returns new ray with flipped direction.\n        /// </summary>\n        public readonly Ray3f Reversed => new Ray3f(Origin, -Direction);\n\n        /// <summary>\n        /// Returns the ray with its directional normalized.\n        /// </summary>\n        public readonly Ray3f Normalized => new(Origin, Direction.Normalized);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        /// <summary>\n        /// Gets the point on the ray that is t * Direction from Origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f GetPointOnRay(float t) => Origin + Direction * t;\n\n        /// <summary>\n        /// Gets the t for a point p on this ray.\n        /// </summary>\n        public readonly float GetT(V3f p)\n        {\n            var v = p - Origin;\n            var d = Direction.Abs();\n\n            if (d.X > d.Y)\n                return (d.X > d.Z) ? (v.X / Direction.X) : (v.Z / Direction.Z);\n            else\n                return (d.Y > d.Z) ? (v.Y / Direction.Y) : (v.Z / Direction.Z);\n        }\n\n        /// <summary>\n        /// Gets the t of the closest point on the ray for any point p.\n        /// </summary>\n        public readonly float GetTOfProjectedPoint(V3f p)\n        {\n            var v = p - Origin;\n            return v.Dot(Direction) / Direction.LengthSquared;\n        }\n\n        /// <summary>\n        /// Returns the ray transformed with the given matrix.\n        /// This method is only valid for similarity transformations (uniform scale).\n        /// </summary>\n        public readonly Ray3f Transformed(M44f mat)\n            => new(mat.TransformPos(Origin), mat.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        public readonly Ray3f Transformed(Rot3f transform)\n            => new(transform.Transform(Origin), transform.Transform(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        public readonly Ray3f Transformed(Scale3f transform)\n            => new(transform.Transform(Origin), transform.Transform(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        public readonly Ray3f Transformed(Shift3f transform)\n            => new(transform.Transform(Origin), Direction);\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        public readonly Ray3f Transformed(Euclidean3f transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        public readonly Ray3f Transformed(Similarity3f transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        public readonly Ray3f Transformed(Affine3f transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"Ray3f\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float AngleBetweenFast(Ray3f r)\n            => Direction.AngleBetweenFast(r.Direction);\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"Ray3f\"/> in radians using a numerically stable algorithm.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float AngleBetween(Ray3f r)\n            => Direction.AngleBetween(r.Direction);\n\n        #endregion\n\n        #region Ray hit intersections\n\n        #region Private functions\n\n        private readonly bool ComputeHit(\n              float t,\n              float tmin, float tmax,\n              ref RayHit3f hit)\n        {\n            if (t >= tmin)\n            {\n                if (t < tmax && t < hit.T)\n                {\n                    hit.T = t;\n                    hit.Point = GetPointOnRay(t);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = false;\n                    return true;\n                }\n                return false;\n            }\n            return false;\n        }\n\n        private readonly bool GetClosestHit(\n                float t1, float t2,\n                float tmin, float tmax,\n                ref RayHit3f hit)\n        {\n            return t1 < t2\n                  ? ProcessHits(t1, t2, tmin, tmax, ref hit)\n                  : ProcessHits(t2, t1, tmin, tmax, ref hit);\n        }\n\n\n        private readonly bool ProcessHits(\n                float t1, float t2,\n                float tmin, float tmax,\n                ref RayHit3f hit)\n        {\n            if (t1 >= tmin)\n            {\n                if (t1 < tmax && t1 < hit.T)\n                {\n                    hit.T = t1;\n                    hit.Point = GetPointOnRay(t1);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = false;\n                    return true;\n                }\n                return false;\n            }\n            if (t2 >= tmin)\n            {\n                if (t2 < tmax && t2 < hit.T)\n                {\n                    hit.T = t2;\n                    hit.Point = GetPointOnRay(t2);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = true;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region Ray-Ray hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        public readonly bool Hits(Ray3f ray, ref RayHit3f hit)\n            => HitsRay(ray, 0, float.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit.\n        /// </summary>\n        public readonly bool Hits(Ray3f ray, float tmin, float tmax, ref RayHit3f hit)\n            => HitsRay(ray, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit.\n        /// </summary>\n        public readonly bool HitsRay(Ray3f ray, float tmin, float tmax, ref RayHit3f hit)\n        {\n            V3f d = Origin - ray.Origin;\n            V3f u = Direction;\n            V3f v = ray.Direction;\n            V3f n = u.Cross(v);\n\n            if (Fun.IsTiny(d.Length)) return true;\n            else if (Fun.IsTiny(u.Cross(v).Length)) return false;\n            else\n            {\n                //-t0*u + t1*v + t2*n == d\n                //M = {-u,v,n}\n                //M*{t0,t1,t2}T == d\n                //{t0,t1,t2}T == M^-1 * d\n\n                M33f M = new M33f\n                {\n                    C0 = -u,\n                    C1 = v,\n                    C2 = n\n                };\n\n                if (M.Invertible)\n                {\n                    V3f t = M.Inverse * d;\n                    if (Fun.IsTiny(t.Z))\n                    {\n                        ProcessHits(t.X, float.MaxValue, tmin, tmax, ref hit);\n                        return true;\n                    }\n                    else return false;\n                }\n                else return false;\n            }\n        }\n\n        #endregion\n\n        #region Ray-Triangle hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Triangle3f triangle, ref RayHit3f hit)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                0, float.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Triangle3f triangle, out float t)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3f.MaxRange.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Triangle3f triangle, float tmin, float tmax, ref RayHit3f hit)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within [0, float.MaxValue]\n        /// and before the parameter value contained in the supplied hit. Detailed\n        /// information about the hit is returned in the supplied hit. In order to\n        /// obtain all potential hits, the supplied hit can be initialized with\n        /// RayHit3f.MaxRange. Degenerated triangles will not result in an intersection\n        /// even if any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(V3f p0, V3f p1, V3f p2, ref RayHit3f hit)\n            => HitsTriangle(p0, p1, p2, 0, float.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3f.MaxRange.\n        /// Degenerated triangles will not result in an intersection even if\n        /// any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(\n            V3f p0, V3f p1, V3f p2,\n            float tmin, float tmax,\n            ref RayHit3f hit\n            )\n        {\n            V3f edge01 = p1 - p0;\n            V3f edge02 = p2 - p0;\n            V3f plane = Vec.Cross(Direction, edge02);\n            float det = Vec.Dot(edge01, plane);\n            if (det > -1e-4f && det < 1e-4f) return false;\n            // ray ~= paralell / Triangle\n            V3f tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            float u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            float v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            float t = Vec.Dot(edge02, plane) * det;\n            if (t < tmin || t >= tmax || t >= hit.T) return false;\n            hit.T = t;\n            hit.Point = Origin + t * Direction;\n            hit.Coord.X = u; hit.Coord.Y = v;\n            hit.BackSide = (det < 0);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle. Degenerated triangles\n        /// will not result in an intersection even if any edge is hit exactly.\n        /// A hit with this overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsTriangle(V3f p0, V3f p1, V3f p2, out float t)\n            => HitsTriangle(p0, p1, p2, 0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval. Degenerated triangles will not result in an\n        /// intersection even if any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(\n            V3f p0, V3f p1, V3f p2,\n            float tmin, float tmax,\n            out float t\n            )\n        {\n            V3f edge01 = p1 - p0;\n            V3f edge02 = p2 - p0;\n            V3f plane = Vec.Cross(Direction, edge02);\n            float det = Vec.Dot(edge01, plane);\n            t = float.NaN;\n            if (det > -1e-4f && det < 1e-4f) return false;\n            // ray ~= paralell / Triangle\n            V3f tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            float u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            float v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            t = Vec.Dot(edge02, plane) * det;\n            return t >= tmin && t <= tmax;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3f.MaxRange.\n        /// </summary>\n        public readonly bool HitsTrianglePointAndEdges(\n            V3f p0, V3f edge01, V3f edge02,\n            float tmin, float tmax,\n            ref RayHit3f hit\n            )\n        {\n            V3f plane = Vec.Cross(Direction, edge02);\n            float det = Vec.Dot(edge01, plane);\n            if (det > -1e-4f && det < 1e-4f) return false;\n            // ray ~= paralell / Triangle\n            V3f tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            float u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            float v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            float t = Vec.Dot(edge02, plane) * det;\n            if (t < tmin || t >= tmax || t >= hit.T) return false;\n            hit.T = t;\n            hit.Point = Origin + t * Direction;\n            hit.Coord.X = u; hit.Coord.Y = v;\n            hit.BackSide = (det < 0);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3f.MaxRange.\n        /// </summary>\n        public readonly bool HitsTrianglePointAndEdges(\n            V3f p0, V3f edge01, V3f edge02,\n            float tmin, float tmax,\n            out float t\n            )\n        {\n            V3f plane = Vec.Cross(Direction, edge02);\n            float det = Vec.Dot(edge01, plane);\n            t = float.NaN;\n            if (det > -1e-4f && det < 1e-4f) return false;\n            // ray ~= paralell / Triangle\n            V3f tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            float u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            float v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            t = Vec.Dot(edge02, plane) * det;\n            return t >= tmin && t <= tmax;\n        }\n\n        #endregion\n\n        #region Ray-Quad hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the quad before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. In order to obtain all\n        /// potential hits, the supplied hit can be initialized with\n        /// RayHit3f.MaxRange. A hit with this overload is considered\n        /// for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Quad3f quad, ref RayHit3f hit) => HitsQuad(\n            quad.P0, quad.P1, quad.P2, quad.P3,\n            0, float.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3f.MaxRange.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Quad3f quad, float tmin, float tmax, ref RayHit3f hit) => HitsQuad(\n            quad.P0, quad.P1, quad.P2, quad.P3,\n            tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. The quad is considered to consist of the\n        /// two triangles [p0,p1,p2] and [p0,p2,p3]. Detailed information\n        /// about the hit is returned in the supplied hit. In order to obtain\n        /// all potential hits, the supplied hit can be initialized with\n        /// RayHit3f.MaxRange.\n        /// </summary>\n        public readonly bool HitsQuad(\n            V3f p0, V3f p1, V3f p2, V3f p3,\n            float tmin, float tmax,\n            ref RayHit3f hit\n            )\n        {\n            V3f e02 = p2 - p0;\n            bool result = false;\n            if (HitsTrianglePointAndEdges(p0, p1 - p0, e02, tmin, tmax,\n                                          ref hit))\n            {\n                hit.Coord.X += hit.Coord.Y;\n                result = true;\n            }\n            if (HitsTrianglePointAndEdges(p0, e02, p3 - p0, tmin, tmax,\n                                          ref hit))\n            {\n                hit.Coord.Y += hit.Coord.X;\n                result = true;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Quad3f quad, float tmin, float tmax, out float t)\n            => HitsQuad(quad.P0, quad.P1, quad.P2, quad.P3, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// A hit with this overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Quad3f quad, out float t)\n            => HitsQuad(quad.P0, quad.P1, quad.P2, quad.P3, 0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// A hit with this overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsQuad(V3f p0, V3f p1, V3f p2, V3f p3, out float t)\n            => HitsQuad(p0, p1, p2, p3, 0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// </summary>\n        public readonly bool HitsQuad(V3f p0, V3f p1, V3f p2, V3f p3, float tmin, float tmax, out float t)\n        {\n            V3f e02 = p2 - p0;\n            return HitsTrianglePointAndEdges(p0, p1 - p0, e02, tmin, tmax, out t)\n                || HitsTrianglePointAndEdges(p0, e02, p3 - p0, tmin, tmax, out t);\n        }\n\n        #endregion\n\n        #region Ray-Sphere hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the sphere given by center and\n        /// radius within the supplied parameter interval and before the\n        /// parameter value contained in the supplied hit. Note that a\n        /// hit is only registered if the front or the backsurface is\n        /// encountered within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        public readonly bool HitsSphere(\n                V3f center, float radius,\n                float tmin, float tmax,\n                ref RayHit3f hit)\n        {\n            V3f originSubCenter = Origin - center;\n            float a = Direction.LengthSquared;\n            float b = Direction.Dot(originSubCenter);\n            float c = originSubCenter.LengthSquared - radius * radius;\n\n            // --------------------- quadric equation : a t^2  + 2b t + c = 0\n            float d = b * b - a * c;           // factor 2 was eliminated\n\n            if (d < float.Epsilon)             // no root ?\n                return false;                   // then exit\n\n            if (b > 0)                        // stable way to calculate\n                d = -Fun.Sqrt(d) - b;           // the roots of a quadratic\n            else                                // equation\n                d = Fun.Sqrt(d) - b;\n\n            float t1 = d / a;\n            float t2 = c / d;  // Vieta : t1 * t2 == c/a\n\n            // typically two solutions, either both positive, both negative or mixed\n            // -> take closest (if valid) first\n            return t1.Abs() < t2.Abs()\n                    ? ProcessHits(t1, t2, tmin, tmax, ref hit)\n                    : ProcessHits(t2, t1, tmin, tmax, ref hit);\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval and before the parameter value\n        /// contained in the supplied hit. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Sphere3f sphere, float tmin, float tmax, ref RayHit3f hit)\n            => HitsSphere(sphere.Center, sphere.Radius, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval and before the parameter value\n        /// contained in the supplied hit. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned. A hit with this overload is\n        /// considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Sphere3f sphere, ref RayHit3f hit)\n            => HitsSphere(sphere.Center, sphere.Radius, 0, float.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Sphere3f sphere, float tmin, float tmax, out float t)\n            => HitsSphere(sphere.Center, sphere.Radius, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere. Note that a hit is\n        /// registered if the front or the backsurface is encountered. If there\n        /// are two valid solutions, the closest will be returned. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Sphere3f sphere, out float t)\n            => HitsSphere(sphere.Center, sphere.Radius, 0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the supplied parameter interval.\n        /// Note that a hit is registered if the front or the backsurface is encountered within the\n        /// interval. If there are two valid solutions, the closest will be returned. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        public readonly bool HitsSphere(V3f center, float radius, out float t)\n            => HitsSphere(center, radius, 0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the supplied parameter interval.\n        /// Note that a hit is registered if the front or the backsurface is encountered within the\n        /// interval. If there are two valid solutions, the closest will be returned.\n        /// </summary>\n        public readonly bool HitsSphere(V3f center, float radius, float tmin, float tmax, out float t)\n        {\n            var originSubCenter = Origin - center;\n            var a = Direction.LengthSquared;\n            var b = Direction.Dot(originSubCenter);\n            var c = originSubCenter.LengthSquared - radius * radius;\n\n            // --------------------- quadric equation : a t^2  + 2b t + c = 0\n            var d = b * b - a * c;              // factor 2 was eliminated\n\n            if (d >= float.Epsilon)            // no root ? -> exit\n            {\n                if (b > 0)                    // stable way to calculate\n                    d = -Fun.Sqrt(d) - b;       // the roots of a quadratic\n                else                            // equation\n                    d = Fun.Sqrt(d) - b;\n\n                var t1 = d / a;\n                var t2 = c / d;  // Vieta : t1 * t2 == c/a\n\n                // typically two solutions, either both positive, both negative or mixed\n                // -> take closest (if valid) first\n                if (t2.Abs() < t1.Abs())\n                    Fun.Swap(ref t1, ref t2);\n\n                if (t1 >= tmin)\n                {\n                    if (t1 < tmax)\n                    {\n                        t = t1;\n                        return true;\n                    }\n                    // return false\n                }\n                else if (t2 >= tmin)\n                {\n                    if (t2 < tmax)\n                    {\n                        t = t2;\n                        return true;\n                    }\n                    // return false\n                }\n            }\n\n            t = float.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region Ray-Plane hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsPlane(Plane3f plane, ref RayHit3f hit)\n            => HitsPlane(plane, 0, float.MaxValue, ref hit);\n\n        public readonly bool HitsPlane(Plane3f plane, float tmin, float tmax, ref RayHit3f hit)\n        {\n            var dc = plane.Normal.Dot(Direction);\n\n            // If parallel to plane\n            if (dc == 0)\n                return false;\n\n            var dw = plane.Distance - plane.Normal.Dot(Origin);\n            var t = dw / dc;\n            return ComputeHit(t, tmin, tmax, ref hit);\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsPlane(Plane3f plane, out float t)\n            => HitsPlane(plane, 0, float.MaxValue, out t);\n\n        public readonly bool HitsPlane(Plane3f plane, float tmin, float tmax, out float t)\n        {\n            var dc = plane.Normal.Dot(Direction);\n\n            // If parallel to plane\n            if (dc == 0)\n            {\n                t = float.NaN;\n                return false;\n            }\n\n            var dw = plane.Distance - plane.Normal.Dot(Origin);\n            t = dw / dc;\n            return t >= tmin && t <= tmax;\n        }\n\n        #endregion\n\n        #region Ray-Circle hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Circle3f circle, float tmin, float tmax, ref RayHit3f hit)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Circle3f circle, ref RayHit3f hit)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, 0, float.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCircle(V3f center, V3f normal, float radius, ref RayHit3f hit)\n            => HitsCircle(center, normal, radius, 0, float.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCircle(V3f center, V3f normal, float radius, float tmin, float tmax, ref RayHit3f hit)\n        {\n            var dc = normal.Dot(Direction);\n            var dw = normal.Dot(center - Origin);\n\n            // If parallel to plane\n            if (dc == 0)\n                return false;\n\n            var t = dw / dc;\n            if (!ComputeHit(t, tmin, tmax, ref hit))\n                return false;\n\n            if (Vec.DistanceSquared(hit.Point, center) > radius * radius)\n            {\n                hit.Point = V3f.NaN;\n                hit.T = tmax;\n                return false;\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Circle3f circle, float tmin, float tmax, out float t)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Circle3f circle, out float t)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, 0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCircle(V3f center, V3f normal, float radius, out float t)\n            => HitsCircle(center, normal, radius, 0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCircle(V3f center, V3f normal, float radius, float tmin, float tmax, out float t)\n        {\n            var dc = normal.Dot(Direction);\n            var dw = normal.Dot(center - Origin);\n\n            // If parallel to plane\n            if (dc == 0)\n            {\n                t = float.NaN;\n                return false;\n            }\n\n            t = dw / dc;\n            if (t < tmin || t > tmax)\n                return false;\n\n            var point = GetPointOnRay(t); // add point as out parameter?\n            return Vec.DistanceSquared(point, center) <= radius * radius;\n        }\n\n        #endregion\n\n        #region Ray-Cylinder hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCylinder(V3f p0, V3f p1, float radius,\n                float tmin, float tmax,\n                ref RayHit3f hit)\n        {\n            var axis = new Line3f(p0, p1);\n            var axisDir = axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - p0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            var t = -normal2.Dot(unitNormal) / normal.Length;\n\n            // between enitre rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                hit.T = t1;\n                hit.Point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new Plane3f(-axisDir, p0);\n                var topPlane = new Plane3f(axisDir, p1);\n                var heightBottom = bottomPlane.Height(hit.Point);\n                var heightTop = topPlane.Height(hit.Point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    hit.T = tmax;\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsPlane(topPlane, tmin, tmax, ref hit);\n\n                    // hit still close enough to cylinder axis?\n                    var distance = axis.Ray3f.GetMinimalDistanceTo(hit.Point);\n\n                    if (distance <= radius && (bottomHit || topHit))\n                        return true;\n                }\n                else\n                    return true;\n            }\n\n            hit.T = tmax;\n            hit.Point = V3f.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCylinder(V3f p0, V3f p1, float radius, ref RayHit3f hit)\n            => HitsCylinder(p0, p1, radius, 0, float.MaxValue, ref hit);\n\n        public readonly bool HitsCylinder(V3f p0, V3f p1, float radius,\n                float tmin, float tmax, out float t)\n        {\n            var axis = new Line3f(p0, p1);\n            var axisDir = axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - p0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            t = -normal2.Dot(unitNormal) / normal.Length;\n\n            // between entire rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                t = t1;\n                var point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new Plane3f(-axisDir, p0);\n                var topPlane = new Plane3f(axisDir, p1);\n                var heightBottom = bottomPlane.Height(point);\n                var heightTop = topPlane.Height(point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsCircle(p0, -axisDir, radius, tmin, tmax, out t);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsCircle(p1, axisDir, radius, tmin, tmax, out float ttop);\n\n                    if (topHit)\n                    {\n                        if (bottomHit)\n                        {\n                            if (ttop.Abs() < t)\n                                t = ttop;\n                        }\n                        else\n                            t = ttop;\n                    }\n\n                    return topHit || bottomHit;\n                }\n                else\n                    return true;\n            }\n\n            t = float.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCylinder(V3f p0, V3f p1, float radius, out float t)\n            => HitsCylinder(p0, p1, radius, 0, float.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Cylinder3f cylinder, float tmin, float tmax, ref RayHit3f hit)\n            => Hits(cylinder, tmin, tmax, 0, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool Hits(Cylinder3f cylinder, float tmin, float tmax, float distanceScale, ref RayHit3f hit)\n        {\n            var axisDir = cylinder.Axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - cylinder.P0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            var t = -normal2.Dot(unitNormal) / normal.Length;\n\n            var radius = cylinder.Radius;\n            if (distanceScale != 0)\n            {   // cylinder gets bigger, the further away it is\n                var pnt = GetPointOnRay(t);\n\n                var dis = Vec.Distance(pnt, this.Origin);\n                radius = ((cylinder.Radius / distanceScale) * dis) * 2;\n            }\n\n            // between enitre rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                hit.T = t1;\n                hit.Point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new Plane3f(cylinder.Circle0.Normal, cylinder.Circle0.Center);\n                var topPlane = new Plane3f(cylinder.Circle1.Normal, cylinder.Circle1.Center);\n                var heightBottom = bottomPlane.Height(hit.Point);\n                var heightTop = topPlane.Height(hit.Point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    hit.T = tmax;\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsPlane(topPlane, tmin, tmax, ref hit);\n\n                    // hit still close enough to cylinder axis?\n                    var distance = cylinder.Axis.Ray3f.GetMinimalDistanceTo(hit.Point);\n\n                    if (distance <= radius && (bottomHit || topHit))\n                        return true;\n                }\n                else\n                    return true;\n            }\n\n            hit.T = tmax;\n            hit.Point = V3f.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, float.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Cylinder3f cylinder, ref RayHit3f hit)\n            => Hits(cylinder, 0, float.MaxValue, ref hit);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Ray3f a, Ray3f b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Ray3f a, Ray3f b)\n            => !((a.Origin == b.Origin) && (a.Direction == b.Direction));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int LexicalCompare(Ray3f other)\n        {\n            var cmp = Origin.LexicalCompare(other.Origin);\n            if (cmp != 0) return cmp;\n            return Direction.LexicalCompare(other.Direction);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        /// <summary>\n        /// Calculates Hash-code of the given ray.\n        /// </summary>\n        /// <returns>Hash-code.</returns>\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Ray3f other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction);\n\n        public override readonly bool Equals(object other)\n            => (other is Ray3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Direction);\n\n        public static Ray3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Ray3f(V3f.Parse(x[0]), V3f.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f\n\n        public readonly Box3f BoundingBox3f => Box3f.FromPoints(Origin, Direction + Origin);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ray3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ray3f a, Ray3f b, float tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ray3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ray3f a, Ray3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region RayHit3f\n\n    /// <summary>\n    /// A ray hit represents the hit of a ray on a primitive object such as\n    /// a triangle. It stores the ray parameter of the hit, the hit point,\n    /// the hit point's coordinates, and a flag indicating if the backside\n    /// of the primitive was hit. Optionally the part field can be used to\n    /// store which part of a multi-part object was hit. If no multi-part\n    /// objects are used, this field remains 0.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct RayHit3f\n    {\n        [DataMember]\n        public float T;\n        [DataMember]\n        public V3f Point;\n        [DataMember]\n        public V2d Coord;\n        [DataMember]\n        public bool BackSide;\n        [DataMember]\n        public int Part;\n\n        #region Constructor\n\n        public RayHit3f(float tMax)\n        {\n            T = tMax;\n            Point = V3f.NaN;\n            Coord = V2d.NaN;\n            BackSide = false;\n            Part = 0;\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly RayHit3f MaxRange = new RayHit3f(float.MaxValue);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastRay3f\n\n    /// <summary>\n    /// A fast ray contains a ray and a number of precomputed flags and\n    /// fields for fast intersection computation with bounding boxes and\n    /// other axis-aligned sturctures such as kd-Trees.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly struct FastRay3f\n    {\n        [DataMember]\n        public readonly Ray3f Ray;\n        [DataMember]\n        public readonly DirFlags DirFlags;\n        [DataMember]\n        public readonly V3f InvDir;\n\n        #region Constructors\n\n        public FastRay3f(Ray3f ray)\n        {\n            Ray = ray;\n            DirFlags = ray.Direction.DirFlags();\n            InvDir = 1 / ray.Direction;\n        }\n\n        public FastRay3f(V3f origin, V3f direction)\n            : this(new Ray3f(origin, direction))\n        { }\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        public readonly bool Intersects(\n            Box3f box,\n            ref float tmin,\n            ref float tmax\n            )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                {\n                    float t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                {\n                    float t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    float t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if (Ray.Origin.Z < box.Min.Z || Ray.Origin.Z > box.Max.Z)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method only tests with the\n        /// faces of the box indicated by the supplied boxFlags.\n        /// </summary>\n        public readonly bool Intersects(\n            Box3f box,\n            Box.Flags boxFlags,\n            ref float tmin,\n            ref float tmax\n            )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0 && (Ray.Origin.X < box.Min.X) ||\n                    (boxFlags & Box.Flags.MaxX) != 0 && (Ray.Origin.X > box.Max.X))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0 && (Ray.Origin.Y < box.Min.Y) ||\n                    (boxFlags & Box.Flags.MaxY) != 0 && (Ray.Origin.Y > box.Max.Y))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    float t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    float t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    float t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    float t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0 && (Ray.Origin.Z < box.Min.Z) ||\n                    (boxFlags & Box.Flags.MaxZ) != 0 && (Ray.Origin.Z > box.Max.Z))\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method returns the affected\n        /// planes of the box if the box was hit.\n        /// </summary>\n        public readonly bool Intersects(\n            Box3f box,\n            ref float tmin,\n            ref float tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n            )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                {\n                    float t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxZ; }\n                }\n                {\n                    float t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinZ; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                {\n                    float t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinZ; }\n                }\n                {\n                    float t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxZ; }\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if (Ray.Origin.Z < box.Min.Z || Ray.Origin.Z > box.Max.Z)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method only tests with the\n        /// faces of the box indicated by the supplied boxFlags and\n        /// returns the affected planes of the box if the box was hit.\n        /// </summary>\n        public readonly bool Intersects(\n            Box3f box,\n            Box.Flags boxFlags,\n            ref float tmin,\n            ref float tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n            )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    float t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    float t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0 && (Ray.Origin.X < box.Min.X) ||\n                    (boxFlags & Box.Flags.MaxX) != 0 && (Ray.Origin.X > box.Max.X))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    float t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    float t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0 && (Ray.Origin.Y < box.Min.Y) ||\n                    (boxFlags & Box.Flags.MaxY) != 0 && (Ray.Origin.Y > box.Max.Y))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    float t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxZ; }\n                }\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    float t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinZ; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    float t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinZ; }\n                }\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    float t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxZ; }\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0 && (Ray.Origin.Z < box.Min.Z) ||\n                    (boxFlags & Box.Flags.MaxZ) != 0 && (Ray.Origin.Z > box.Max.Z))\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Ray3d\n\n    /// <summary>\n    /// A three-dimensional ray with an origin and a direction.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Ray3d : IEquatable<Ray3d>, IValidity, IBoundingBox3d\n    {\n        [DataMember]\n        public V3d Origin;\n        [DataMember]\n        public V3d Direction;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates Ray from origin point and directional vector\n        /// </summary>\n        public Ray3d(V3d origin, V3d direction)\n        {\n            Origin = origin;\n            Direction = direction;\n        }\n\n        public static Ray3d FromEndPoints(V3d origin, V3d target) => new Ray3d(origin, target - origin);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// An invalid ray has a zero direction.\n        /// </summary>\n        public static readonly Ray3d Invalid = new Ray3d(V3d.NaN, V3d.Zero);\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// A ray is valid if its direction is non-zero.\n        /// </summary>\n        public readonly bool IsValid { get { return Direction != V3d.Zero; } }\n\n        /// <summary>\n        /// A ray is invalid if its direction is zero.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Direction == V3d.Zero; } }\n\n        /// <summary>\n        /// Returns true if either the origin or the direction contains any NaN value.\n        /// </summary>\n        public readonly bool AnyNaN { get { return Origin.AnyNaN || Direction.AnyNaN; } }\n\n        /// <summary>\n        /// Line segment from origin to origin + direction.\n        /// </summary>\n        public readonly Line3d Line3d => new Line3d(Origin, Origin + Direction);\n\n        /// <summary>\n        /// Returns new ray with flipped direction.\n        /// </summary>\n        public readonly Ray3d Reversed => new Ray3d(Origin, -Direction);\n\n        /// <summary>\n        /// Returns the ray with its directional normalized.\n        /// </summary>\n        public readonly Ray3d Normalized => new(Origin, Direction.Normalized);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        /// <summary>\n        /// Gets the point on the ray that is t * Direction from Origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d GetPointOnRay(double t) => Origin + Direction * t;\n\n        /// <summary>\n        /// Gets the t for a point p on this ray.\n        /// </summary>\n        public readonly double GetT(V3d p)\n        {\n            var v = p - Origin;\n            var d = Direction.Abs();\n\n            if (d.X > d.Y)\n                return (d.X > d.Z) ? (v.X / Direction.X) : (v.Z / Direction.Z);\n            else\n                return (d.Y > d.Z) ? (v.Y / Direction.Y) : (v.Z / Direction.Z);\n        }\n\n        /// <summary>\n        /// Gets the t of the closest point on the ray for any point p.\n        /// </summary>\n        public readonly double GetTOfProjectedPoint(V3d p)\n        {\n            var v = p - Origin;\n            return v.Dot(Direction) / Direction.LengthSquared;\n        }\n\n        /// <summary>\n        /// Returns the ray transformed with the given matrix.\n        /// This method is only valid for similarity transformations (uniform scale).\n        /// </summary>\n        public readonly Ray3d Transformed(M44d mat)\n            => new(mat.TransformPos(Origin), mat.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        public readonly Ray3d Transformed(Rot3d transform)\n            => new(transform.Transform(Origin), transform.Transform(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        public readonly Ray3d Transformed(Scale3d transform)\n            => new(transform.Transform(Origin), transform.Transform(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        public readonly Ray3d Transformed(Shift3d transform)\n            => new(transform.Transform(Origin), Direction);\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        public readonly Ray3d Transformed(Euclidean3d transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        public readonly Ray3d Transformed(Similarity3d transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        public readonly Ray3d Transformed(Affine3d transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"Ray3d\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double AngleBetweenFast(Ray3d r)\n            => Direction.AngleBetweenFast(r.Direction);\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"Ray3d\"/> in radians using a numerically stable algorithm.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double AngleBetween(Ray3d r)\n            => Direction.AngleBetween(r.Direction);\n\n        #endregion\n\n        #region Ray hit intersections\n\n        #region Private functions\n\n        private readonly bool ComputeHit(\n              double t,\n              double tmin, double tmax,\n              ref RayHit3d hit)\n        {\n            if (t >= tmin)\n            {\n                if (t < tmax && t < hit.T)\n                {\n                    hit.T = t;\n                    hit.Point = GetPointOnRay(t);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = false;\n                    return true;\n                }\n                return false;\n            }\n            return false;\n        }\n\n        private readonly bool GetClosestHit(\n                double t1, double t2,\n                double tmin, double tmax,\n                ref RayHit3d hit)\n        {\n            return t1 < t2\n                  ? ProcessHits(t1, t2, tmin, tmax, ref hit)\n                  : ProcessHits(t2, t1, tmin, tmax, ref hit);\n        }\n\n\n        private readonly bool ProcessHits(\n                double t1, double t2,\n                double tmin, double tmax,\n                ref RayHit3d hit)\n        {\n            if (t1 >= tmin)\n            {\n                if (t1 < tmax && t1 < hit.T)\n                {\n                    hit.T = t1;\n                    hit.Point = GetPointOnRay(t1);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = false;\n                    return true;\n                }\n                return false;\n            }\n            if (t2 >= tmin)\n            {\n                if (t2 < tmax && t2 < hit.T)\n                {\n                    hit.T = t2;\n                    hit.Point = GetPointOnRay(t2);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = true;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region Ray-Ray hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        public readonly bool Hits(Ray3d ray, ref RayHit3d hit)\n            => HitsRay(ray, 0, double.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit.\n        /// </summary>\n        public readonly bool Hits(Ray3d ray, double tmin, double tmax, ref RayHit3d hit)\n            => HitsRay(ray, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit.\n        /// </summary>\n        public readonly bool HitsRay(Ray3d ray, double tmin, double tmax, ref RayHit3d hit)\n        {\n            V3d d = Origin - ray.Origin;\n            V3d u = Direction;\n            V3d v = ray.Direction;\n            V3d n = u.Cross(v);\n\n            if (Fun.IsTiny(d.Length)) return true;\n            else if (Fun.IsTiny(u.Cross(v).Length)) return false;\n            else\n            {\n                //-t0*u + t1*v + t2*n == d\n                //M = {-u,v,n}\n                //M*{t0,t1,t2}T == d\n                //{t0,t1,t2}T == M^-1 * d\n\n                M33d M = new M33d\n                {\n                    C0 = -u,\n                    C1 = v,\n                    C2 = n\n                };\n\n                if (M.Invertible)\n                {\n                    V3d t = M.Inverse * d;\n                    if (Fun.IsTiny(t.Z))\n                    {\n                        ProcessHits(t.X, double.MaxValue, tmin, tmax, ref hit);\n                        return true;\n                    }\n                    else return false;\n                }\n                else return false;\n            }\n        }\n\n        #endregion\n\n        #region Ray-Triangle hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Triangle3d triangle, ref RayHit3d hit)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                0, double.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Triangle3d triangle, out double t)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3d.MaxRange.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Triangle3d triangle, double tmin, double tmax, ref RayHit3d hit)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within [0, double.MaxValue]\n        /// and before the parameter value contained in the supplied hit. Detailed\n        /// information about the hit is returned in the supplied hit. In order to\n        /// obtain all potential hits, the supplied hit can be initialized with\n        /// RayHit3d.MaxRange. Degenerated triangles will not result in an intersection\n        /// even if any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(V3d p0, V3d p1, V3d p2, ref RayHit3d hit)\n            => HitsTriangle(p0, p1, p2, 0, double.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3d.MaxRange.\n        /// Degenerated triangles will not result in an intersection even if\n        /// any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(\n            V3d p0, V3d p1, V3d p2,\n            double tmin, double tmax,\n            ref RayHit3d hit\n            )\n        {\n            V3d edge01 = p1 - p0;\n            V3d edge02 = p2 - p0;\n            V3d plane = Vec.Cross(Direction, edge02);\n            double det = Vec.Dot(edge01, plane);\n            if (det > -1e-7 && det < 1e-7) return false;\n            // ray ~= paralell / Triangle\n            V3d tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            double u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            double v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            double t = Vec.Dot(edge02, plane) * det;\n            if (t < tmin || t >= tmax || t >= hit.T) return false;\n            hit.T = t;\n            hit.Point = Origin + t * Direction;\n            hit.Coord.X = u; hit.Coord.Y = v;\n            hit.BackSide = (det < 0);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle. Degenerated triangles\n        /// will not result in an intersection even if any edge is hit exactly.\n        /// A hit with this overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsTriangle(V3d p0, V3d p1, V3d p2, out double t)\n            => HitsTriangle(p0, p1, p2, 0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval. Degenerated triangles will not result in an\n        /// intersection even if any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(\n            V3d p0, V3d p1, V3d p2,\n            double tmin, double tmax,\n            out double t\n            )\n        {\n            V3d edge01 = p1 - p0;\n            V3d edge02 = p2 - p0;\n            V3d plane = Vec.Cross(Direction, edge02);\n            double det = Vec.Dot(edge01, plane);\n            t = double.NaN;\n            if (det > -1e-7 && det < 1e-7) return false;\n            // ray ~= paralell / Triangle\n            V3d tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            double u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            double v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            t = Vec.Dot(edge02, plane) * det;\n            return t >= tmin && t <= tmax;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3d.MaxRange.\n        /// </summary>\n        public readonly bool HitsTrianglePointAndEdges(\n            V3d p0, V3d edge01, V3d edge02,\n            double tmin, double tmax,\n            ref RayHit3d hit\n            )\n        {\n            V3d plane = Vec.Cross(Direction, edge02);\n            double det = Vec.Dot(edge01, plane);\n            if (det > -1e-7 && det < 1e-7) return false;\n            // ray ~= paralell / Triangle\n            V3d tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            double u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            double v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            double t = Vec.Dot(edge02, plane) * det;\n            if (t < tmin || t >= tmax || t >= hit.T) return false;\n            hit.T = t;\n            hit.Point = Origin + t * Direction;\n            hit.Coord.X = u; hit.Coord.Y = v;\n            hit.BackSide = (det < 0);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3d.MaxRange.\n        /// </summary>\n        public readonly bool HitsTrianglePointAndEdges(\n            V3d p0, V3d edge01, V3d edge02,\n            double tmin, double tmax,\n            out double t\n            )\n        {\n            V3d plane = Vec.Cross(Direction, edge02);\n            double det = Vec.Dot(edge01, plane);\n            t = double.NaN;\n            if (det > -1e-7 && det < 1e-7) return false;\n            // ray ~= paralell / Triangle\n            V3d tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            double u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            double v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            t = Vec.Dot(edge02, plane) * det;\n            return t >= tmin && t <= tmax;\n        }\n\n        #endregion\n\n        #region Ray-Quad hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the quad before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. In order to obtain all\n        /// potential hits, the supplied hit can be initialized with\n        /// RayHit3d.MaxRange. A hit with this overload is considered\n        /// for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Quad3d quad, ref RayHit3d hit) => HitsQuad(\n            quad.P0, quad.P1, quad.P2, quad.P3,\n            0, double.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with RayHit3d.MaxRange.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Quad3d quad, double tmin, double tmax, ref RayHit3d hit) => HitsQuad(\n            quad.P0, quad.P1, quad.P2, quad.P3,\n            tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. The quad is considered to consist of the\n        /// two triangles [p0,p1,p2] and [p0,p2,p3]. Detailed information\n        /// about the hit is returned in the supplied hit. In order to obtain\n        /// all potential hits, the supplied hit can be initialized with\n        /// RayHit3d.MaxRange.\n        /// </summary>\n        public readonly bool HitsQuad(\n            V3d p0, V3d p1, V3d p2, V3d p3,\n            double tmin, double tmax,\n            ref RayHit3d hit\n            )\n        {\n            V3d e02 = p2 - p0;\n            bool result = false;\n            if (HitsTrianglePointAndEdges(p0, p1 - p0, e02, tmin, tmax,\n                                          ref hit))\n            {\n                hit.Coord.X += hit.Coord.Y;\n                result = true;\n            }\n            if (HitsTrianglePointAndEdges(p0, e02, p3 - p0, tmin, tmax,\n                                          ref hit))\n            {\n                hit.Coord.Y += hit.Coord.X;\n                result = true;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Quad3d quad, double tmin, double tmax, out double t)\n            => HitsQuad(quad.P0, quad.P1, quad.P2, quad.P3, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// A hit with this overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Quad3d quad, out double t)\n            => HitsQuad(quad.P0, quad.P1, quad.P2, quad.P3, 0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// A hit with this overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsQuad(V3d p0, V3d p1, V3d p2, V3d p3, out double t)\n            => HitsQuad(p0, p1, p2, p3, 0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// </summary>\n        public readonly bool HitsQuad(V3d p0, V3d p1, V3d p2, V3d p3, double tmin, double tmax, out double t)\n        {\n            V3d e02 = p2 - p0;\n            return HitsTrianglePointAndEdges(p0, p1 - p0, e02, tmin, tmax, out t)\n                || HitsTrianglePointAndEdges(p0, e02, p3 - p0, tmin, tmax, out t);\n        }\n\n        #endregion\n\n        #region Ray-Sphere hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the sphere given by center and\n        /// radius within the supplied parameter interval and before the\n        /// parameter value contained in the supplied hit. Note that a\n        /// hit is only registered if the front or the backsurface is\n        /// encountered within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        public readonly bool HitsSphere(\n                V3d center, double radius,\n                double tmin, double tmax,\n                ref RayHit3d hit)\n        {\n            V3d originSubCenter = Origin - center;\n            double a = Direction.LengthSquared;\n            double b = Direction.Dot(originSubCenter);\n            double c = originSubCenter.LengthSquared - radius * radius;\n\n            // --------------------- quadric equation : a t^2  + 2b t + c = 0\n            double d = b * b - a * c;           // factor 2 was eliminated\n\n            if (d < double.Epsilon)             // no root ?\n                return false;                   // then exit\n\n            if (b > 0)                        // stable way to calculate\n                d = -Fun.Sqrt(d) - b;           // the roots of a quadratic\n            else                                // equation\n                d = Fun.Sqrt(d) - b;\n\n            double t1 = d / a;\n            double t2 = c / d;  // Vieta : t1 * t2 == c/a\n\n            // typically two solutions, either both positive, both negative or mixed\n            // -> take closest (if valid) first\n            return t1.Abs() < t2.Abs()\n                    ? ProcessHits(t1, t2, tmin, tmax, ref hit)\n                    : ProcessHits(t2, t1, tmin, tmax, ref hit);\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval and before the parameter value\n        /// contained in the supplied hit. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Sphere3d sphere, double tmin, double tmax, ref RayHit3d hit)\n            => HitsSphere(sphere.Center, sphere.Radius, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval and before the parameter value\n        /// contained in the supplied hit. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned. A hit with this overload is\n        /// considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Sphere3d sphere, ref RayHit3d hit)\n            => HitsSphere(sphere.Center, sphere.Radius, 0, double.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Sphere3d sphere, double tmin, double tmax, out double t)\n            => HitsSphere(sphere.Center, sphere.Radius, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere. Note that a hit is\n        /// registered if the front or the backsurface is encountered. If there\n        /// are two valid solutions, the closest will be returned. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Sphere3d sphere, out double t)\n            => HitsSphere(sphere.Center, sphere.Radius, 0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the supplied parameter interval.\n        /// Note that a hit is registered if the front or the backsurface is encountered within the\n        /// interval. If there are two valid solutions, the closest will be returned. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        public readonly bool HitsSphere(V3d center, double radius, out double t)\n            => HitsSphere(center, radius, 0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the supplied parameter interval.\n        /// Note that a hit is registered if the front or the backsurface is encountered within the\n        /// interval. If there are two valid solutions, the closest will be returned.\n        /// </summary>\n        public readonly bool HitsSphere(V3d center, double radius, double tmin, double tmax, out double t)\n        {\n            var originSubCenter = Origin - center;\n            var a = Direction.LengthSquared;\n            var b = Direction.Dot(originSubCenter);\n            var c = originSubCenter.LengthSquared - radius * radius;\n\n            // --------------------- quadric equation : a t^2  + 2b t + c = 0\n            var d = b * b - a * c;              // factor 2 was eliminated\n\n            if (d >= double.Epsilon)            // no root ? -> exit\n            {\n                if (b > 0)                    // stable way to calculate\n                    d = -Fun.Sqrt(d) - b;       // the roots of a quadratic\n                else                            // equation\n                    d = Fun.Sqrt(d) - b;\n\n                var t1 = d / a;\n                var t2 = c / d;  // Vieta : t1 * t2 == c/a\n\n                // typically two solutions, either both positive, both negative or mixed\n                // -> take closest (if valid) first\n                if (t2.Abs() < t1.Abs())\n                    Fun.Swap(ref t1, ref t2);\n\n                if (t1 >= tmin)\n                {\n                    if (t1 < tmax)\n                    {\n                        t = t1;\n                        return true;\n                    }\n                    // return false\n                }\n                else if (t2 >= tmin)\n                {\n                    if (t2 < tmax)\n                    {\n                        t = t2;\n                        return true;\n                    }\n                    // return false\n                }\n            }\n\n            t = double.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region Ray-Plane hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsPlane(Plane3d plane, ref RayHit3d hit)\n            => HitsPlane(plane, 0, double.MaxValue, ref hit);\n\n        public readonly bool HitsPlane(Plane3d plane, double tmin, double tmax, ref RayHit3d hit)\n        {\n            var dc = plane.Normal.Dot(Direction);\n\n            // If parallel to plane\n            if (dc == 0)\n                return false;\n\n            var dw = plane.Distance - plane.Normal.Dot(Origin);\n            var t = dw / dc;\n            return ComputeHit(t, tmin, tmax, ref hit);\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsPlane(Plane3d plane, out double t)\n            => HitsPlane(plane, 0, double.MaxValue, out t);\n\n        public readonly bool HitsPlane(Plane3d plane, double tmin, double tmax, out double t)\n        {\n            var dc = plane.Normal.Dot(Direction);\n\n            // If parallel to plane\n            if (dc == 0)\n            {\n                t = double.NaN;\n                return false;\n            }\n\n            var dw = plane.Distance - plane.Normal.Dot(Origin);\n            t = dw / dc;\n            return t >= tmin && t <= tmax;\n        }\n\n        #endregion\n\n        #region Ray-Circle hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Circle3d circle, double tmin, double tmax, ref RayHit3d hit)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Circle3d circle, ref RayHit3d hit)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, 0, double.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCircle(V3d center, V3d normal, double radius, ref RayHit3d hit)\n            => HitsCircle(center, normal, radius, 0, double.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCircle(V3d center, V3d normal, double radius, double tmin, double tmax, ref RayHit3d hit)\n        {\n            var dc = normal.Dot(Direction);\n            var dw = normal.Dot(center - Origin);\n\n            // If parallel to plane\n            if (dc == 0)\n                return false;\n\n            var t = dw / dc;\n            if (!ComputeHit(t, tmin, tmax, ref hit))\n                return false;\n\n            if (Vec.DistanceSquared(hit.Point, center) > radius * radius)\n            {\n                hit.Point = V3d.NaN;\n                hit.T = tmax;\n                return false;\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Circle3d circle, double tmin, double tmax, out double t)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Circle3d circle, out double t)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, 0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCircle(V3d center, V3d normal, double radius, out double t)\n            => HitsCircle(center, normal, radius, 0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCircle(V3d center, V3d normal, double radius, double tmin, double tmax, out double t)\n        {\n            var dc = normal.Dot(Direction);\n            var dw = normal.Dot(center - Origin);\n\n            // If parallel to plane\n            if (dc == 0)\n            {\n                t = double.NaN;\n                return false;\n            }\n\n            t = dw / dc;\n            if (t < tmin || t > tmax)\n                return false;\n\n            var point = GetPointOnRay(t); // add point as out parameter?\n            return Vec.DistanceSquared(point, center) <= radius * radius;\n        }\n\n        #endregion\n\n        #region Ray-Cylinder hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCylinder(V3d p0, V3d p1, double radius,\n                double tmin, double tmax,\n                ref RayHit3d hit)\n        {\n            var axis = new Line3d(p0, p1);\n            var axisDir = axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - p0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            var t = -normal2.Dot(unitNormal) / normal.Length;\n\n            // between enitre rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                hit.T = t1;\n                hit.Point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new Plane3d(-axisDir, p0);\n                var topPlane = new Plane3d(axisDir, p1);\n                var heightBottom = bottomPlane.Height(hit.Point);\n                var heightTop = topPlane.Height(hit.Point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    hit.T = tmax;\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsPlane(topPlane, tmin, tmax, ref hit);\n\n                    // hit still close enough to cylinder axis?\n                    var distance = axis.Ray3d.GetMinimalDistanceTo(hit.Point);\n\n                    if (distance <= radius && (bottomHit || topHit))\n                        return true;\n                }\n                else\n                    return true;\n            }\n\n            hit.T = tmax;\n            hit.Point = V3d.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCylinder(V3d p0, V3d p1, double radius, ref RayHit3d hit)\n            => HitsCylinder(p0, p1, radius, 0, double.MaxValue, ref hit);\n\n        public readonly bool HitsCylinder(V3d p0, V3d p1, double radius,\n                double tmin, double tmax, out double t)\n        {\n            var axis = new Line3d(p0, p1);\n            var axisDir = axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - p0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            t = -normal2.Dot(unitNormal) / normal.Length;\n\n            // between entire rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                t = t1;\n                var point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new Plane3d(-axisDir, p0);\n                var topPlane = new Plane3d(axisDir, p1);\n                var heightBottom = bottomPlane.Height(point);\n                var heightTop = topPlane.Height(point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsCircle(p0, -axisDir, radius, tmin, tmax, out t);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsCircle(p1, axisDir, radius, tmin, tmax, out double ttop);\n\n                    if (topHit)\n                    {\n                        if (bottomHit)\n                        {\n                            if (ttop.Abs() < t)\n                                t = ttop;\n                        }\n                        else\n                            t = ttop;\n                    }\n\n                    return topHit || bottomHit;\n                }\n                else\n                    return true;\n            }\n\n            t = double.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCylinder(V3d p0, V3d p1, double radius, out double t)\n            => HitsCylinder(p0, p1, radius, 0, double.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Cylinder3d cylinder, double tmin, double tmax, ref RayHit3d hit)\n            => Hits(cylinder, tmin, tmax, 0, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool Hits(Cylinder3d cylinder, double tmin, double tmax, double distanceScale, ref RayHit3d hit)\n        {\n            var axisDir = cylinder.Axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - cylinder.P0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            var t = -normal2.Dot(unitNormal) / normal.Length;\n\n            var radius = cylinder.Radius;\n            if (distanceScale != 0)\n            {   // cylinder gets bigger, the further away it is\n                var pnt = GetPointOnRay(t);\n\n                var dis = Vec.Distance(pnt, this.Origin);\n                radius = ((cylinder.Radius / distanceScale) * dis) * 2;\n            }\n\n            // between enitre rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                hit.T = t1;\n                hit.Point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new Plane3d(cylinder.Circle0.Normal, cylinder.Circle0.Center);\n                var topPlane = new Plane3d(cylinder.Circle1.Normal, cylinder.Circle1.Center);\n                var heightBottom = bottomPlane.Height(hit.Point);\n                var heightTop = topPlane.Height(hit.Point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    hit.T = tmax;\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsPlane(topPlane, tmin, tmax, ref hit);\n\n                    // hit still close enough to cylinder axis?\n                    var distance = cylinder.Axis.Ray3d.GetMinimalDistanceTo(hit.Point);\n\n                    if (distance <= radius && (bottomHit || topHit))\n                        return true;\n                }\n                else\n                    return true;\n            }\n\n            hit.T = tmax;\n            hit.Point = V3d.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, double.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(Cylinder3d cylinder, ref RayHit3d hit)\n            => Hits(cylinder, 0, double.MaxValue, ref hit);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Ray3d a, Ray3d b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Ray3d a, Ray3d b)\n            => !((a.Origin == b.Origin) && (a.Direction == b.Direction));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int LexicalCompare(Ray3d other)\n        {\n            var cmp = Origin.LexicalCompare(other.Origin);\n            if (cmp != 0) return cmp;\n            return Direction.LexicalCompare(other.Direction);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        /// <summary>\n        /// Calculates Hash-code of the given ray.\n        /// </summary>\n        /// <returns>Hash-code.</returns>\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Ray3d other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction);\n\n        public override readonly bool Equals(object other)\n            => (other is Ray3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Direction);\n\n        public static Ray3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Ray3d(V3d.Parse(x[0]), V3d.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d\n\n        public readonly Box3d BoundingBox3d => Box3d.FromPoints(Origin, Direction + Origin);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ray3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ray3d a, Ray3d b, double tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Ray3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Ray3d a, Ray3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region RayHit3d\n\n    /// <summary>\n    /// A ray hit represents the hit of a ray on a primitive object such as\n    /// a triangle. It stores the ray parameter of the hit, the hit point,\n    /// the hit point's coordinates, and a flag indicating if the backside\n    /// of the primitive was hit. Optionally the part field can be used to\n    /// store which part of a multi-part object was hit. If no multi-part\n    /// objects are used, this field remains 0.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct RayHit3d\n    {\n        [DataMember]\n        public double T;\n        [DataMember]\n        public V3d Point;\n        [DataMember]\n        public V2d Coord;\n        [DataMember]\n        public bool BackSide;\n        [DataMember]\n        public int Part;\n\n        #region Constructor\n\n        public RayHit3d(double tMax)\n        {\n            T = tMax;\n            Point = V3d.NaN;\n            Coord = V2d.NaN;\n            BackSide = false;\n            Part = 0;\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly RayHit3d MaxRange = new RayHit3d(double.MaxValue);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastRay3d\n\n    /// <summary>\n    /// A fast ray contains a ray and a number of precomputed flags and\n    /// fields for fast intersection computation with bounding boxes and\n    /// other axis-aligned sturctures such as kd-Trees.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly struct FastRay3d\n    {\n        [DataMember]\n        public readonly Ray3d Ray;\n        [DataMember]\n        public readonly DirFlags DirFlags;\n        [DataMember]\n        public readonly V3d InvDir;\n\n        #region Constructors\n\n        public FastRay3d(Ray3d ray)\n        {\n            Ray = ray;\n            DirFlags = ray.Direction.DirFlags();\n            InvDir = 1 / ray.Direction;\n        }\n\n        public FastRay3d(V3d origin, V3d direction)\n            : this(new Ray3d(origin, direction))\n        { }\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        public readonly bool Intersects(\n            Box3d box,\n            ref double tmin,\n            ref double tmax\n            )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                {\n                    double t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                {\n                    double t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    double t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if (Ray.Origin.Z < box.Min.Z || Ray.Origin.Z > box.Max.Z)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method only tests with the\n        /// faces of the box indicated by the supplied boxFlags.\n        /// </summary>\n        public readonly bool Intersects(\n            Box3d box,\n            Box.Flags boxFlags,\n            ref double tmin,\n            ref double tmax\n            )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0 && (Ray.Origin.X < box.Min.X) ||\n                    (boxFlags & Box.Flags.MaxX) != 0 && (Ray.Origin.X > box.Max.X))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0 && (Ray.Origin.Y < box.Min.Y) ||\n                    (boxFlags & Box.Flags.MaxY) != 0 && (Ray.Origin.Y > box.Max.Y))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    double t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    double t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    double t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    double t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0 && (Ray.Origin.Z < box.Min.Z) ||\n                    (boxFlags & Box.Flags.MaxZ) != 0 && (Ray.Origin.Z > box.Max.Z))\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method returns the affected\n        /// planes of the box if the box was hit.\n        /// </summary>\n        public readonly bool Intersects(\n            Box3d box,\n            ref double tmin,\n            ref double tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n            )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                {\n                    double t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxZ; }\n                }\n                {\n                    double t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinZ; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                {\n                    double t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinZ; }\n                }\n                {\n                    double t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxZ; }\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if (Ray.Origin.Z < box.Min.Z || Ray.Origin.Z > box.Max.Z)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method only tests with the\n        /// faces of the box indicated by the supplied boxFlags and\n        /// returns the affected planes of the box if the box was hit.\n        /// </summary>\n        public readonly bool Intersects(\n            Box3d box,\n            Box.Flags boxFlags,\n            ref double tmin,\n            ref double tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n            )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    double t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    double t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0 && (Ray.Origin.X < box.Min.X) ||\n                    (boxFlags & Box.Flags.MaxX) != 0 && (Ray.Origin.X > box.Max.X))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    double t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    double t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0 && (Ray.Origin.Y < box.Min.Y) ||\n                    (boxFlags & Box.Flags.MaxY) != 0 && (Ray.Origin.Y > box.Max.Y))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    double t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxZ; }\n                }\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    double t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinZ; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    double t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinZ; }\n                }\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    double t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxZ; }\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0 && (Ray.Origin.Z < box.Min.Z) ||\n                    (boxFlags & Box.Flags.MaxZ) != 0 && (Ray.Origin.Z > box.Max.Z))\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Ray/Ray3_template.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var ray3t = \"Ray3\" + tc;\n    //#   var ray3t2 = \"Ray3\" + tc2;\n    //#   var rayhit3t = \"RayHit3\" + tc;\n    //#   var rayhit3t2 = \"RayHit3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var m33t = \"M33\" + tc;\n    //#   var m44t = \"M44\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var line3t = \"Line3\" + tc;\n    //#   var triangle3t = \"Triangle3\" + tc;\n    //#   var quad3t = \"Quad3\" + tc;\n    //#   var sphere3t = \"Sphere3\" + tc;\n    //#   var circle3t = \"Circle3\" + tc;\n    //#   var cylinder3t = \"Cylinder3\" + tc;\n    //#   var iboundingbox = \"IBoundingBox3\" + tc;\n    //#   var rot3t = \"Rot3\" + tc;\n    //#   var scale3t = \"Scale3\" + tc;\n    //#   var shift3t = \"Shift3\" + tc;\n    //#   var euclidean3t = \"Euclidean3\" + tc;\n    //#   var similarity3t = \"Similarity3\" + tc;\n    //#   var affine3t = \"Affine3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var eps = isDouble ? \"1e-7\" : \"1e-4f\";\n    #region __ray3t__\n\n    /// <summary>\n    /// A three-dimensional ray with an origin and a direction.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __ray3t__ : IEquatable<__ray3t__>, IValidity, __iboundingbox__\n    {\n        [DataMember]\n        public __v3t__ Origin;\n        [DataMember]\n        public __v3t__ Direction;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates Ray from origin point and directional vector\n        /// </summary>\n        public __ray3t__(__v3t__ origin, __v3t__ direction)\n        {\n            Origin = origin;\n            Direction = direction;\n        }\n\n        public static __ray3t__ FromEndPoints(__v3t__ origin, __v3t__ target) => new __ray3t__(origin, target - origin);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// An invalid ray has a zero direction.\n        /// </summary>\n        public static readonly __ray3t__ Invalid = new __ray3t__(__v3t__.NaN, __v3t__.Zero);\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// A ray is valid if its direction is non-zero.\n        /// </summary>\n        public readonly bool IsValid { get { return Direction != __v3t__.Zero; } }\n\n        /// <summary>\n        /// A ray is invalid if its direction is zero.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Direction == __v3t__.Zero; } }\n\n        /// <summary>\n        /// Returns true if either the origin or the direction contains any NaN value.\n        /// </summary>\n        public readonly bool AnyNaN { get { return Origin.AnyNaN || Direction.AnyNaN; } }\n\n        /// <summary>\n        /// Line segment from origin to origin + direction.\n        /// </summary>\n        public readonly __line3t__ __line3t__ => new __line3t__(Origin, Origin + Direction);\n\n        /// <summary>\n        /// Returns new ray with flipped direction.\n        /// </summary>\n        public readonly __ray3t__ Reversed => new __ray3t__(Origin, -Direction);\n\n        /// <summary>\n        /// Returns the ray with its directional normalized.\n        /// </summary>\n        public readonly __ray3t__ Normalized => new(Origin, Direction.Normalized);\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        /// <summary>\n        /// Gets the point on the ray that is t * Direction from Origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __v3t__ GetPointOnRay(__ftype__ t) => Origin + Direction * t;\n\n        /// <summary>\n        /// Gets the t for a point p on this ray.\n        /// </summary>\n        public readonly __ftype__ GetT(__v3t__ p)\n        {\n            var v = p - Origin;\n            var d = Direction.Abs();\n\n            if (d.X > d.Y)\n                return (d.X > d.Z) ? (v.X / Direction.X) : (v.Z / Direction.Z);\n            else\n                return (d.Y > d.Z) ? (v.Y / Direction.Y) : (v.Z / Direction.Z);\n        }\n\n        /// <summary>\n        /// Gets the t of the closest point on the ray for any point p.\n        /// </summary>\n        public readonly __ftype__ GetTOfProjectedPoint(__v3t__ p)\n        {\n            var v = p - Origin;\n            return v.Dot(Direction) / Direction.LengthSquared;\n        }\n\n        /// <summary>\n        /// Returns the ray transformed with the given matrix.\n        /// This method is only valid for similarity transformations (uniform scale).\n        /// </summary>\n        public readonly __ray3t__ Transformed(__m44t__ mat)\n            => new(mat.TransformPos(Origin), mat.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"__rot3t__\"/> transformation.\n        /// </summary>\n        public readonly __ray3t__ Transformed(__rot3t__ transform)\n            => new(transform.Transform(Origin), transform.Transform(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"__scale3t__\"/> transformation.\n        /// </summary>\n        public readonly __ray3t__ Transformed(__scale3t__ transform)\n            => new(transform.Transform(Origin), transform.Transform(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"__shift3t__\"/> transformation.\n        /// </summary>\n        public readonly __ray3t__ Transformed(__shift3t__ transform)\n            => new(transform.Transform(Origin), Direction);\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"__euclidean3t__\"/> transformation.\n        /// </summary>\n        public readonly __ray3t__ Transformed(__euclidean3t__ transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"__similarity3t__\"/> transformation.\n        /// </summary>\n        public readonly __ray3t__ Transformed(__similarity3t__ transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the ray transformed with the given <see cref=\"__affine3t__\"/> transformation.\n        /// </summary>\n        public readonly __ray3t__ Transformed(__affine3t__ transform)\n            => new(transform.TransformPos(Origin), transform.TransformDir(Direction));\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"__ray3t__\"/> in radians.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ AngleBetweenFast(__ray3t__ r)\n            => Direction.AngleBetweenFast(r.Direction);\n\n        /// <summary>\n        /// Returns the angle between this and the given <see cref=\"__ray3t__\"/> in radians using a numerically stable algorithm.\n        /// The direction vectors of the input rays have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ AngleBetween(__ray3t__ r)\n            => Direction.AngleBetween(r.Direction);\n\n        #endregion\n\n        #region Ray hit intersections\n\n        #region Private functions\n\n        private readonly bool ComputeHit(\n              __ftype__ t,\n              __ftype__ tmin, __ftype__ tmax,\n              ref __rayhit3t__ hit)\n        {\n            if (t >= tmin)\n            {\n                if (t < tmax && t < hit.T)\n                {\n                    hit.T = t;\n                    hit.Point = GetPointOnRay(t);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = false;\n                    return true;\n                }\n                return false;\n            }\n            return false;\n        }\n\n        private readonly bool GetClosestHit(\n                __ftype__ t1, __ftype__ t2,\n                __ftype__ tmin, __ftype__ tmax,\n                ref __rayhit3t__ hit)\n        {\n            return t1 < t2\n                  ? ProcessHits(t1, t2, tmin, tmax, ref hit)\n                  : ProcessHits(t2, t1, tmin, tmax, ref hit);\n        }\n\n\n        private readonly bool ProcessHits(\n                __ftype__ t1, __ftype__ t2,\n                __ftype__ tmin, __ftype__ tmax,\n                ref __rayhit3t__ hit)\n        {\n            if (t1 >= tmin)\n            {\n                if (t1 < tmax && t1 < hit.T)\n                {\n                    hit.T = t1;\n                    hit.Point = GetPointOnRay(t1);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = false;\n                    return true;\n                }\n                return false;\n            }\n            if (t2 >= tmin)\n            {\n                if (t2 < tmax && t2 < hit.T)\n                {\n                    hit.T = t2;\n                    hit.Point = GetPointOnRay(t2);\n                    hit.Coord = V2d.NaN;\n                    hit.BackSide = true;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        #endregion\n\n        #region Ray-Ray hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        public readonly bool Hits(__ray3t__ ray, ref __rayhit3t__ hit)\n            => HitsRay(ray, 0, __ftype__.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit.\n        /// </summary>\n        public readonly bool Hits(__ray3t__ ray, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit)\n            => HitsRay(ray, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the other ray before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit.\n        /// </summary>\n        public readonly bool HitsRay(__ray3t__ ray, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit)\n        {\n            __v3t__ d = Origin - ray.Origin;\n            __v3t__ u = Direction;\n            __v3t__ v = ray.Direction;\n            __v3t__ n = u.Cross(v);\n\n            if (Fun.IsTiny(d.Length)) return true;\n            else if (Fun.IsTiny(u.Cross(v).Length)) return false;\n            else\n            {\n                //-t0*u + t1*v + t2*n == d\n                //M = {-u,v,n}\n                //M*{t0,t1,t2}T == d\n                //{t0,t1,t2}T == M^-1 * d\n\n                __m33t__ M = new __m33t__\n                {\n                    C0 = -u,\n                    C1 = v,\n                    C2 = n\n                };\n\n                if (M.Invertible)\n                {\n                    __v3t__ t = M.Inverse * d;\n                    if (Fun.IsTiny(t.Z))\n                    {\n                        ProcessHits(t.X, __ftype__.MaxValue, tmin, tmax, ref hit);\n                        return true;\n                    }\n                    else return false;\n                }\n                else return false;\n            }\n        }\n\n        #endregion\n\n        #region Ray-Triangle hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__triangle3t__ triangle, ref __rayhit3t__ hit)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                0, __ftype__.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__triangle3t__ triangle, out __ftype__ t)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with __rayhit3t__.MaxRange.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__triangle3t__ triangle, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit)\n            => HitsTrianglePointAndEdges(\n                triangle.P0, triangle.Edge01, triangle.Edge02,\n                tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within [0, __ftype__.MaxValue]\n        /// and before the parameter value contained in the supplied hit. Detailed\n        /// information about the hit is returned in the supplied hit. In order to\n        /// obtain all potential hits, the supplied hit can be initialized with\n        /// __rayhit3t__.MaxRange. Degenerated triangles will not result in an intersection\n        /// even if any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(__v3t__ p0, __v3t__ p1, __v3t__ p2, ref __rayhit3t__ hit)\n            => HitsTriangle(p0, p1, p2, 0, __ftype__.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with __rayhit3t__.MaxRange.\n        /// Degenerated triangles will not result in an intersection even if\n        /// any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(\n            __v3t__ p0, __v3t__ p1, __v3t__ p2,\n            __ftype__ tmin, __ftype__ tmax,\n            ref __rayhit3t__ hit\n            )\n        {\n            __v3t__ edge01 = p1 - p0;\n            __v3t__ edge02 = p2 - p0;\n            __v3t__ plane = Vec.Cross(Direction, edge02);\n            __ftype__ det = Vec.Dot(edge01, plane);\n            if (det > -__eps__ && det < __eps__) return false;\n            // ray ~= paralell / Triangle\n            __v3t__ tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            __ftype__ u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            __ftype__ v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            __ftype__ t = Vec.Dot(edge02, plane) * det;\n            if (t < tmin || t >= tmax || t >= hit.T) return false;\n            hit.T = t;\n            hit.Point = Origin + t * Direction;\n            hit.Coord.X = u; hit.Coord.Y = v;\n            hit.BackSide = (det < 0);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle. Degenerated triangles\n        /// will not result in an intersection even if any edge is hit exactly.\n        /// A hit with this overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsTriangle(__v3t__ p0, __v3t__ p1, __v3t__ p2, out __ftype__ t)\n            => HitsTriangle(p0, p1, p2, 0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval. Degenerated triangles will not result in an\n        /// intersection even if any edge is hit exactly.\n        /// </summary>\n        public readonly bool HitsTriangle(\n            __v3t__ p0, __v3t__ p1, __v3t__ p2,\n            __ftype__ tmin, __ftype__ tmax,\n            out __ftype__ t\n            )\n        {\n            __v3t__ edge01 = p1 - p0;\n            __v3t__ edge02 = p2 - p0;\n            __v3t__ plane = Vec.Cross(Direction, edge02);\n            __ftype__ det = Vec.Dot(edge01, plane);\n            t = __ftype__.NaN;\n            if (det > -__eps__ && det < __eps__) return false;\n            // ray ~= paralell / Triangle\n            __v3t__ tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            __ftype__ u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            __ftype__ v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            t = Vec.Dot(edge02, plane) * det;\n            return t >= tmin && t <= tmax;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with __rayhit3t__.MaxRange.\n        /// </summary>\n        public readonly bool HitsTrianglePointAndEdges(\n            __v3t__ p0, __v3t__ edge01, __v3t__ edge02,\n            __ftype__ tmin, __ftype__ tmax,\n            ref __rayhit3t__ hit\n            )\n        {\n            __v3t__ plane = Vec.Cross(Direction, edge02);\n            __ftype__ det = Vec.Dot(edge01, plane);\n            if (det > -__eps__ && det < __eps__) return false;\n            // ray ~= paralell / Triangle\n            __v3t__ tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            __ftype__ u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            __ftype__ v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            __ftype__ t = Vec.Dot(edge02, plane) * det;\n            if (t < tmin || t >= tmax || t >= hit.T) return false;\n            hit.T = t;\n            hit.Point = Origin + t * Direction;\n            hit.Coord.X = u; hit.Coord.Y = v;\n            hit.BackSide = (det < 0);\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the triangle within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with __rayhit3t__.MaxRange.\n        /// </summary>\n        public readonly bool HitsTrianglePointAndEdges(\n            __v3t__ p0, __v3t__ edge01, __v3t__ edge02,\n            __ftype__ tmin, __ftype__ tmax,\n            out __ftype__ t\n            )\n        {\n            __v3t__ plane = Vec.Cross(Direction, edge02);\n            __ftype__ det = Vec.Dot(edge01, plane);\n            t = __ftype__.NaN;\n            if (det > -__eps__ && det < __eps__) return false;\n            // ray ~= paralell / Triangle\n            __v3t__ tv = Origin - p0;\n            det = 1 / det;  // det is now inverse det\n            __ftype__ u = Vec.Dot(tv, plane) * det;\n            if (u < 0 || u > 1) return false;\n            plane = Vec.Cross(tv, edge01); // plane is now qv\n            __ftype__ v = Vec.Dot(Direction, plane) * det;\n            if (v < 0 || u + v > 1) return false;\n            t = Vec.Dot(edge02, plane) * det;\n            return t >= tmin && t <= tmax;\n        }\n\n        #endregion\n\n        #region Ray-Quad hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the quad before the parameter\n        /// value contained in the supplied hit. Detailed information about\n        /// the hit is returned in the supplied hit. In order to obtain all\n        /// potential hits, the supplied hit can be initialized with\n        /// __rayhit3t__.MaxRange. A hit with this overload is considered\n        /// for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__quad3t__ quad, ref __rayhit3t__ hit) => HitsQuad(\n            quad.P0, quad.P1, quad.P2, quad.P3,\n            0, __ftype__.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. Detailed information about the hit is\n        /// returned in the supplied hit. In order to obtain all potential\n        /// hits, the supplied hit can be initialized with __rayhit3t__.MaxRange.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__quad3t__ quad, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit) => HitsQuad(\n            quad.P0, quad.P1, quad.P2, quad.P3,\n            tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied\n        /// parameter interval and before the parameter value contained\n        /// in the supplied hit. The quad is considered to consist of the\n        /// two triangles [p0,p1,p2] and [p0,p2,p3]. Detailed information\n        /// about the hit is returned in the supplied hit. In order to obtain\n        /// all potential hits, the supplied hit can be initialized with\n        /// __rayhit3t__.MaxRange.\n        /// </summary>\n        public readonly bool HitsQuad(\n            __v3t__ p0, __v3t__ p1, __v3t__ p2, __v3t__ p3,\n            __ftype__ tmin, __ftype__ tmax,\n            ref __rayhit3t__ hit\n            )\n        {\n            __v3t__ e02 = p2 - p0;\n            bool result = false;\n            if (HitsTrianglePointAndEdges(p0, p1 - p0, e02, tmin, tmax,\n                                          ref hit))\n            {\n                hit.Coord.X += hit.Coord.Y;\n                result = true;\n            }\n            if (HitsTrianglePointAndEdges(p0, e02, p3 - p0, tmin, tmax,\n                                          ref hit))\n            {\n                hit.Coord.Y += hit.Coord.X;\n                result = true;\n            }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__quad3t__ quad, __ftype__ tmin, __ftype__ tmax, out __ftype__ t)\n            => HitsQuad(quad.P0, quad.P1, quad.P2, quad.P3, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// A hit with this overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__quad3t__ quad, out __ftype__ t)\n            => HitsQuad(quad.P0, quad.P1, quad.P2, quad.P3, 0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// A hit with this overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsQuad(__v3t__ p0, __v3t__ p1, __v3t__ p2, __v3t__ p3, out __ftype__ t)\n            => HitsQuad(p0, p1, p2, p3, 0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the quad within the supplied parameter interval.\n        /// </summary>\n        public readonly bool HitsQuad(__v3t__ p0, __v3t__ p1, __v3t__ p2, __v3t__ p3, __ftype__ tmin, __ftype__ tmax, out __ftype__ t)\n        {\n            __v3t__ e02 = p2 - p0;\n            return HitsTrianglePointAndEdges(p0, p1 - p0, e02, tmin, tmax, out t)\n                || HitsTrianglePointAndEdges(p0, e02, p3 - p0, tmin, tmax, out t);\n        }\n\n        #endregion\n\n        #region Ray-Sphere hit intersection\n\n        /// <summary>\n        /// Returns true if the ray hits the sphere given by center and\n        /// radius within the supplied parameter interval and before the\n        /// parameter value contained in the supplied hit. Note that a\n        /// hit is only registered if the front or the backsurface is\n        /// encountered within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        public readonly bool HitsSphere(\n                __v3t__ center, __ftype__ radius,\n                __ftype__ tmin, __ftype__ tmax,\n                ref __rayhit3t__ hit)\n        {\n            __v3t__ originSubCenter = Origin - center;\n            __ftype__ a = Direction.LengthSquared;\n            __ftype__ b = Direction.Dot(originSubCenter);\n            __ftype__ c = originSubCenter.LengthSquared - radius * radius;\n\n            // --------------------- quadric equation : a t^2  + 2b t + c = 0\n            __ftype__ d = b * b - a * c;           // factor 2 was eliminated\n\n            if (d < __ftype__.Epsilon)             // no root ?\n                return false;                   // then exit\n\n            if (b > 0)                        // stable way to calculate\n                d = -Fun.Sqrt(d) - b;           // the roots of a quadratic\n            else                                // equation\n                d = Fun.Sqrt(d) - b;\n\n            __ftype__ t1 = d / a;\n            __ftype__ t2 = c / d;  // Vieta : t1 * t2 == c/a\n\n            // typically two solutions, either both positive, both negative or mixed\n            // -> take closest (if valid) first\n            return t1.Abs() < t2.Abs()\n                    ? ProcessHits(t1, t2, tmin, tmax, ref hit)\n                    : ProcessHits(t2, t1, tmin, tmax, ref hit);\n        }\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval and before the parameter value\n        /// contained in the supplied hit. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__sphere3t__ sphere, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit)\n            => HitsSphere(sphere.Center, sphere.Radius, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval and before the parameter value\n        /// contained in the supplied hit. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned. A hit with this overload is\n        /// considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__sphere3t__ sphere, ref __rayhit3t__ hit)\n            => HitsSphere(sphere.Center, sphere.Radius, 0, __ftype__.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the\n        /// supplied parameter interval. Note that a hit is only\n        /// registered if the front or the backsurface is encountered\n        /// within the interval. If there are two valid solutions, the\n        /// closest will be returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__sphere3t__ sphere, __ftype__ tmin, __ftype__ tmax, out __ftype__ t)\n            => HitsSphere(sphere.Center, sphere.Radius, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere. Note that a hit is\n        /// registered if the front or the backsurface is encountered. If there\n        /// are two valid solutions, the closest will be returned. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__sphere3t__ sphere, out __ftype__ t)\n            => HitsSphere(sphere.Center, sphere.Radius, 0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the supplied parameter interval.\n        /// Note that a hit is registered if the front or the backsurface is encountered within the\n        /// interval. If there are two valid solutions, the closest will be returned. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        public readonly bool HitsSphere(__v3t__ center, __ftype__ radius, out __ftype__ t)\n            => HitsSphere(center, radius, 0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray hits the supplied sphere within the supplied parameter interval.\n        /// Note that a hit is registered if the front or the backsurface is encountered within the\n        /// interval. If there are two valid solutions, the closest will be returned.\n        /// </summary>\n        public readonly bool HitsSphere(__v3t__ center, __ftype__ radius, __ftype__ tmin, __ftype__ tmax, out __ftype__ t)\n        {\n            var originSubCenter = Origin - center;\n            var a = Direction.LengthSquared;\n            var b = Direction.Dot(originSubCenter);\n            var c = originSubCenter.LengthSquared - radius * radius;\n\n            // --------------------- quadric equation : a t^2  + 2b t + c = 0\n            var d = b * b - a * c;              // factor 2 was eliminated\n\n            if (d >= __ftype__.Epsilon)            // no root ? -> exit\n            {\n                if (b > 0)                    // stable way to calculate\n                    d = -Fun.Sqrt(d) - b;       // the roots of a quadratic\n                else                            // equation\n                    d = Fun.Sqrt(d) - b;\n\n                var t1 = d / a;\n                var t2 = c / d;  // Vieta : t1 * t2 == c/a\n\n                // typically two solutions, either both positive, both negative or mixed\n                // -> take closest (if valid) first\n                if (t2.Abs() < t1.Abs())\n                    Fun.Swap(ref t1, ref t2);\n\n                if (t1 >= tmin)\n                {\n                    if (t1 < tmax)\n                    {\n                        t = t1;\n                        return true;\n                    }\n                    // return false\n                }\n                else if (t2 >= tmin)\n                {\n                    if (t2 < tmax)\n                    {\n                        t = t2;\n                        return true;\n                    }\n                    // return false\n                }\n            }\n\n            t = __ftype__.NaN;\n            return false;\n        }\n\n        #endregion\n\n        #region Ray-Plane hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsPlane(__plane3t__ plane, ref __rayhit3t__ hit)\n            => HitsPlane(plane, 0, __ftype__.MaxValue, ref hit);\n\n        public readonly bool HitsPlane(__plane3t__ plane, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit)\n        {\n            var dc = plane.Normal.Dot(Direction);\n\n            // If parallel to plane\n            if (dc == 0)\n                return false;\n\n            var dw = plane.Distance - plane.Normal.Dot(Origin);\n            var t = dw / dc;\n            return ComputeHit(t, tmin, tmax, ref hit);\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsPlane(__plane3t__ plane, out __ftype__ t)\n            => HitsPlane(plane, 0, __ftype__.MaxValue, out t);\n\n        public readonly bool HitsPlane(__plane3t__ plane, __ftype__ tmin, __ftype__ tmax, out __ftype__ t)\n        {\n            var dc = plane.Normal.Dot(Direction);\n\n            // If parallel to plane\n            if (dc == 0)\n            {\n                t = __ftype__.NaN;\n                return false;\n            }\n\n            var dw = plane.Distance - plane.Normal.Dot(Origin);\n            t = dw / dc;\n            return t >= tmin && t <= tmax;\n        }\n\n        #endregion\n\n        #region Ray-Circle hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__circle3t__ circle, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, tmin, tmax, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__circle3t__ circle, ref __rayhit3t__ hit)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, 0, __ftype__.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCircle(__v3t__ center, __v3t__ normal, __ftype__ radius, ref __rayhit3t__ hit)\n            => HitsCircle(center, normal, radius, 0, __ftype__.MaxValue, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCircle(__v3t__ center, __v3t__ normal, __ftype__ radius, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit)\n        {\n            var dc = normal.Dot(Direction);\n            var dw = normal.Dot(center - Origin);\n\n            // If parallel to plane\n            if (dc == 0)\n                return false;\n\n            var t = dw / dc;\n            if (!ComputeHit(t, tmin, tmax, ref hit))\n                return false;\n\n            if (Vec.DistanceSquared(hit.Point, center) > radius * radius)\n            {\n                hit.Point = __v3t__.NaN;\n                hit.T = tmax;\n                return false;\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__circle3t__ circle, __ftype__ tmin, __ftype__ tmax, out __ftype__ t)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, tmin, tmax, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__circle3t__ circle, out __ftype__ t)\n            => HitsCircle(circle.Center, circle.Normal, circle.Radius, 0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCircle(__v3t__ center, __v3t__ normal, __ftype__ radius, out __ftype__ t)\n            => HitsCircle(center, normal, radius, 0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCircle(__v3t__ center, __v3t__ normal, __ftype__ radius, __ftype__ tmin, __ftype__ tmax, out __ftype__ t)\n        {\n            var dc = normal.Dot(Direction);\n            var dw = normal.Dot(center - Origin);\n\n            // If parallel to plane\n            if (dc == 0)\n            {\n                t = __ftype__.NaN;\n                return false;\n            }\n\n            t = dw / dc;\n            if (t < tmin || t > tmax)\n                return false;\n\n            var point = GetPointOnRay(t); // add point as out parameter?\n            return Vec.DistanceSquared(point, center) <= radius * radius;\n        }\n\n        #endregion\n\n        #region Ray-Cylinder hit intersection\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool HitsCylinder(__v3t__ p0, __v3t__ p1, __ftype__ radius,\n                __ftype__ tmin, __ftype__ tmax,\n                ref __rayhit3t__ hit)\n        {\n            var axis = new __line3t__(p0, p1);\n            var axisDir = axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - p0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            var t = -normal2.Dot(unitNormal) / normal.Length;\n\n            // between enitre rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                hit.T = t1;\n                hit.Point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new __plane3t__(-axisDir, p0);\n                var topPlane = new __plane3t__(axisDir, p1);\n                var heightBottom = bottomPlane.Height(hit.Point);\n                var heightTop = topPlane.Height(hit.Point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    hit.T = tmax;\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsPlane(topPlane, tmin, tmax, ref hit);\n\n                    // hit still close enough to cylinder axis?\n                    var distance = axis.__ray3t__.GetMinimalDistanceTo(hit.Point);\n\n                    if (distance <= radius && (bottomHit || topHit))\n                        return true;\n                }\n                else\n                    return true;\n            }\n\n            hit.T = tmax;\n            hit.Point = __v3t__.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCylinder(__v3t__ p0, __v3t__ p1, __ftype__ radius, ref __rayhit3t__ hit)\n            => HitsCylinder(p0, p1, radius, 0, __ftype__.MaxValue, ref hit);\n\n        public readonly bool HitsCylinder(__v3t__ p0, __v3t__ p1, __ftype__ radius,\n                __ftype__ tmin, __ftype__ tmax, out __ftype__ t)\n        {\n            var axis = new __line3t__(p0, p1);\n            var axisDir = axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - p0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            t = -normal2.Dot(unitNormal) / normal.Length;\n\n            // between entire rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                t = t1;\n                var point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new __plane3t__(-axisDir, p0);\n                var topPlane = new __plane3t__(axisDir, p1);\n                var heightBottom = bottomPlane.Height(point);\n                var heightTop = topPlane.Height(point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsCircle(p0, -axisDir, radius, tmin, tmax, out t);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsCircle(p1, axisDir, radius, tmin, tmax, out __ftype__ ttop);\n\n                    if (topHit)\n                    {\n                        if (bottomHit)\n                        {\n                            if (ttop.Abs() < t)\n                                t = ttop;\n                        }\n                        else\n                            t = ttop;\n                    }\n\n                    return topHit || bottomHit;\n                }\n                else\n                    return true;\n            }\n\n            t = __ftype__.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool HitsCylinder(__v3t__ p0, __v3t__ p1, __ftype__ radius, out __ftype__ t)\n            => HitsCylinder(p0, p1, radius, 0, __ftype__.MaxValue, out t);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__cylinder3t__ cylinder, __ftype__ tmin, __ftype__ tmax, ref __rayhit3t__ hit)\n            => Hits(cylinder, tmin, tmax, 0, ref hit);\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive.\n        /// </summary>\n        public readonly bool Hits(__cylinder3t__ cylinder, __ftype__ tmin, __ftype__ tmax, __ftype__ distanceScale, ref __rayhit3t__ hit)\n        {\n            var axisDir = cylinder.Axis.Direction.Normalized;\n\n            // Vector Cyl.P0 -> Ray.Origin\n            var op = Origin - cylinder.P0;\n\n            // normal RayDirection - CylinderAxis\n            var normal = Direction.Cross(axisDir);\n            var unitNormal = normal.Normalized;\n\n            // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis\n            var normal2 = op.Cross(axisDir);\n            var t = -normal2.Dot(unitNormal) / normal.Length;\n\n            var radius = cylinder.Radius;\n            if (distanceScale != 0)\n            {   // cylinder gets bigger, the further away it is\n                var pnt = GetPointOnRay(t);\n\n                var dis = Vec.Distance(pnt, this.Origin);\n                radius = ((cylinder.Radius / distanceScale) * dis) * 2;\n            }\n\n            // between enitre rays (caps are ignored)\n            var shortestDistance = Fun.Abs(op.Dot(unitNormal));\n            if (shortestDistance <= radius)\n            {\n                var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length);\n\n                var t1 = t - s; // first hit of Cylinder shell\n                var t2 = t + s; // second hit of Cylinder shell\n\n                if (t1 > tmin && t1 < tmax) tmin = t1;\n                if (t2 < tmax && t2 > tmin) tmax = t2;\n\n                hit.T = t1;\n                hit.Point = GetPointOnRay(t1);\n\n                // check if found point is outside of Cylinder Caps\n                var bottomPlane = new __plane3t__(cylinder.Circle0.Normal, cylinder.Circle0.Center);\n                var topPlane = new __plane3t__(cylinder.Circle1.Normal, cylinder.Circle1.Center);\n                var heightBottom = bottomPlane.Height(hit.Point);\n                var heightTop = topPlane.Height(hit.Point);\n                // t1 lies outside of caps => find closest cap hit\n                if (heightBottom > 0 || heightTop > 0)\n                {\n                    hit.T = tmax;\n                    // intersect with bottom Cylinder Cap\n                    var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit);\n                    // intersect with top Cylinder Cap\n                    var topHit = HitsPlane(topPlane, tmin, tmax, ref hit);\n\n                    // hit still close enough to cylinder axis?\n                    var distance = cylinder.Axis.__ray3t__.GetMinimalDistanceTo(hit.Point);\n\n                    if (distance <= radius && (bottomHit || topHit))\n                        return true;\n                }\n                else\n                    return true;\n            }\n\n            hit.T = tmax;\n            hit.Point = __v3t__.NaN;\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the ray intersects with the primitive. A hit with this\n        /// overload is considered for t in [0, __ftype__.MaxValue].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Hits(__cylinder3t__ cylinder, ref __rayhit3t__ hit)\n            => Hits(cylinder, 0, __ftype__.MaxValue, ref hit);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__ray3t__ a, __ray3t__ b)\n            => (a.Origin == b.Origin) && (a.Direction == b.Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__ray3t__ a, __ray3t__ b)\n            => !((a.Origin == b.Origin) && (a.Direction == b.Direction));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int LexicalCompare(__ray3t__ other)\n        {\n            var cmp = Origin.LexicalCompare(other.Origin);\n            if (cmp != 0) return cmp;\n            return Direction.LexicalCompare(other.Direction);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        /// <summary>\n        /// Calculates Hash-code of the given ray.\n        /// </summary>\n        /// <returns>Hash-code.</returns>\n        public override readonly int GetHashCode() => HashCode.GetCombined(Origin, Direction);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__ray3t__ other)\n            => Origin.Equals(other.Origin) && Direction.Equals(other.Direction);\n\n        public override readonly bool Equals(object other)\n            => (other is __ray3t__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Origin, Direction);\n\n        public static __ray3t__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __ray3t__(__v3t__.Parse(x[0]), __v3t__.Parse(x[1]));\n        }\n\n        #endregion\n\n        #region __iboundingbox__\n\n        public readonly __box3t__ BoundingBox3__tc__ => __box3t__.FromPoints(Origin, Direction + Origin);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ray3t__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __ray3t__ a, __ray3t__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Origin, b.Origin, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ray3t__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __ray3t__ a, __ray3t__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region __rayhit3t__\n\n    /// <summary>\n    /// A ray hit represents the hit of a ray on a primitive object such as\n    /// a triangle. It stores the ray parameter of the hit, the hit point,\n    /// the hit point's coordinates, and a flag indicating if the backside\n    /// of the primitive was hit. Optionally the part field can be used to\n    /// store which part of a multi-part object was hit. If no multi-part\n    /// objects are used, this field remains 0.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct __rayhit3t__\n    {\n        [DataMember]\n        public __ftype__ T;\n        [DataMember]\n        public __v3t__ Point;\n        [DataMember]\n        public V2d Coord;\n        [DataMember]\n        public bool BackSide;\n        [DataMember]\n        public int Part;\n\n        #region Constructor\n\n        public __rayhit3t__(__ftype__ tMax)\n        {\n            T = tMax;\n            Point = __v3t__.NaN;\n            Coord = V2d.NaN;\n            BackSide = false;\n            Part = 0;\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly __rayhit3t__ MaxRange = new __rayhit3t__(__ftype__.MaxValue);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Fast__ray3t__\n\n    /// <summary>\n    /// A fast ray contains a ray and a number of precomputed flags and\n    /// fields for fast intersection computation with bounding boxes and\n    /// other axis-aligned sturctures such as kd-Trees.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly struct Fast__ray3t__\n    {\n        [DataMember]\n        public readonly __ray3t__ Ray;\n        [DataMember]\n        public readonly DirFlags DirFlags;\n        [DataMember]\n        public readonly __v3t__ InvDir;\n\n        #region Constructors\n\n        public Fast__ray3t__(__ray3t__ ray)\n        {\n            Ray = ray;\n            DirFlags = ray.Direction.DirFlags();\n            InvDir = 1 / ray.Direction;\n        }\n\n        public Fast__ray3t__(__v3t__ origin, __v3t__ direction)\n            : this(new __ray3t__(origin, direction))\n        { }\n\n        #endregion\n\n        #region Ray Arithmetics\n\n        public readonly bool Intersects(\n            __box3t__ box,\n            ref __ftype__ tmin,\n            ref __ftype__ tmax\n            )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                {\n                    __ftype__ t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if (Ray.Origin.Z < box.Min.Z || Ray.Origin.Z > box.Max.Z)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method only tests with the\n        /// faces of the box indicated by the supplied boxFlags.\n        /// </summary>\n        public readonly bool Intersects(\n            __box3t__ box,\n            Box.Flags boxFlags,\n            ref __ftype__ tmin,\n            ref __ftype__ tmax\n            )\n        {\n            var dirFlags = DirFlags;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0 && (Ray.Origin.X < box.Min.X) ||\n                    (boxFlags & Box.Flags.MaxX) != 0 && (Ray.Origin.X > box.Max.X))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0 && (Ray.Origin.Y < box.Min.Y) ||\n                    (boxFlags & Box.Flags.MaxY) != 0 && (Ray.Origin.Y > box.Max.Y))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    __ftype__ t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    __ftype__ t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    __ftype__ t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) tmax = t;\n                }\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    __ftype__ t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) tmin = t;\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0 && (Ray.Origin.Z < box.Min.Z) ||\n                    (boxFlags & Box.Flags.MaxZ) != 0 && (Ray.Origin.Z > box.Max.Z))\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method returns the affected\n        /// planes of the box if the box was hit.\n        /// </summary>\n        public readonly bool Intersects(\n            __box3t__ box,\n            ref __ftype__ tmin,\n            ref __ftype__ tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n            )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if (Ray.Origin.X < box.Min.X || Ray.Origin.X > box.Max.X)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if (Ray.Origin.Y < box.Min.Y || Ray.Origin.Y > box.Max.Y)\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                {\n                    __ftype__ t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxZ; }\n                }\n                {\n                    __ftype__ t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinZ; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                {\n                    __ftype__ t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinZ; }\n                }\n                {\n                    __ftype__ t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxZ; }\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if (Ray.Origin.Z < box.Min.Z || Ray.Origin.Z > box.Max.Z)\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// This variant of the intersection method only tests with the\n        /// faces of the box indicated by the supplied boxFlags and\n        /// returns the affected planes of the box if the box was hit.\n        /// </summary>\n        public readonly bool Intersects(\n            __box3t__ box,\n            Box.Flags boxFlags,\n            ref __ftype__ tmin,\n            ref __ftype__ tmax,\n            out Box.Flags tminFlags,\n            out Box.Flags tmaxFlags\n            )\n        {\n            var dirFlags = DirFlags;\n            tminFlags = Box.Flags.None;\n            tmaxFlags = Box.Flags.None;\n\n            if ((dirFlags & DirFlags.PositiveX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxX; }\n                }\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinX; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeX) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0)\n                {\n                    __ftype__ t = (box.Min.X - Ray.Origin.X) * InvDir.X;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinX; }\n                }\n                if ((boxFlags & Box.Flags.MaxX) != 0)\n                {\n                    __ftype__ t = (box.Max.X - Ray.Origin.X) * InvDir.X;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxX; }\n                }\n            }\n            else\t// ray parallel to X-plane\n            {\n                if ((boxFlags & Box.Flags.MinX) != 0 && (Ray.Origin.X < box.Min.X) ||\n                    (boxFlags & Box.Flags.MaxX) != 0 && (Ray.Origin.X > box.Max.X))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxY; }\n                }\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinY; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeY) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0)\n                {\n                    __ftype__ t = (box.Min.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinY; }\n                }\n                if ((boxFlags & Box.Flags.MaxY) != 0)\n                {\n                    __ftype__ t = (box.Max.Y - Ray.Origin.Y) * InvDir.Y;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxY; }\n                }\n            }\n            else\t// ray parallel to Y-plane\n            {\n                if ((boxFlags & Box.Flags.MinY) != 0 && (Ray.Origin.Y < box.Min.Y) ||\n                    (boxFlags & Box.Flags.MaxY) != 0 && (Ray.Origin.Y > box.Max.Y))\n                    return false;\n            }\n\n            if ((dirFlags & DirFlags.PositiveZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    __ftype__ t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MaxZ; }\n                }\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    __ftype__ t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MinZ; }\n                }\n            }\n            else if ((dirFlags & DirFlags.NegativeZ) != 0)\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0)\n                {\n                    __ftype__ t = (box.Min.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t <= tmin) return false;\n                    if (t < tmax) { tmax = t; tmaxFlags = Box.Flags.MinZ; }\n                }\n                if ((boxFlags & Box.Flags.MaxZ) != 0)\n                {\n                    __ftype__ t = (box.Max.Z - Ray.Origin.Z) * InvDir.Z;\n                    if (t >= tmax) return false;\n                    if (t > tmin) { tmin = t; tminFlags = Box.Flags.MaxZ; }\n                }\n            }\n            else\t// ray parallel to Z-plane\n            {\n                if ((boxFlags & Box.Flags.MinZ) != 0 && (Ray.Origin.Z < box.Min.Z) ||\n                    (boxFlags & Box.Flags.MaxZ) != 0 && (Ray.Origin.Z > box.Max.Z))\n                    return false;\n            }\n\n            if (tmin > tmax) return false;\n\n            return true;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Sphere/Sphere3_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Sphere3f\n\n    /// <summary>\n    /// A three dimensional sphere represented by center and radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Sphere3f : IEquatable<Sphere3f>, IBoundingBox3f, IValidity\n    {\n        [DataMember]\n        public V3f Center;\n        [DataMember]\n        public float Radius;\n\n        #region Constructors\n\n        /// <summary>\n\t\t/// Initializes a new instance of the <see cref=\"Sphere3f\"/> class using center and radius values.\n\t\t/// </summary>\n\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3f(V3f center, float radius)\n\t\t{\n\t\t\tCenter = center;\n\t\t\tRadius = radius;\n\t\t}\n\n        /// <summary>\n        /// Creates a sphere from its center, and a point on its surface.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3f(V3f center, V3f pointOnSurface)\n        {\n            Center = center;\n            Radius = (pointOnSurface - center).Length;\n        }\n\n        /// <summary>\n        /// Uses the first 2 points in the sequence as the\n        /// sphere's center and a point on the sphere's surface.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3f(IEnumerable<V3f> points)\n        {\n            var va = points.TakeToArray(2);\n            Center = va[0];\n            Radius = (va[1] - va[0]).Length;\n        }\n\n        /// <summary>\n\t\t/// Initializes a new instance of the <see cref=\"Sphere3f\"/> class using values from another sphere instance.\n\t\t/// </summary>\n\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3f(Sphere3f sphere)\n\t\t{\n\t\t\tCenter = sphere.Center;\n\t\t\tRadius = sphere.Radius;\n\t\t}\n\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"Sphere3f\"/> class using values from a <see cref=\"Sphere3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3f(Sphere3d sphere)\n        {\n            Center = (V3f)sphere.Center;\n            Radius = (float)sphere.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Sphere3f(Sphere3d s)\n            => new Sphere3f(s);\n\n        #endregion\n\n        #region Static Factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Sphere3f FromRadius(float radius)\n            => new Sphere3f(V3f.Zero, radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Sphere3f FromCenterAndRadius(V3f center, float radius)\n            => new Sphere3f(center, radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Sphere3f FromPoints(IEnumerable<V3f> points)\n            => new Sphere3f(points);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0;\n        }\n\n        public readonly float RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius;\n        }\n\n        public readonly float SurfaceArea\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (4 * RadiusSquared * ConstantF.Pi);\n        }\n\n        public readonly float Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (4.0f / 3.0f) * ConstantF.Pi * Radius * Radius * Radius;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Sphere at origin with radius 0.\n        /// </summary>\n        public static Sphere3f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Sphere3f(V3f.Zero, 0);\n        }\n\n        /// <summary>\n        /// Sphere at origin with radius 1.\n        /// </summary>\n        public static Sphere3f Unit\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Sphere3f(V3f.Zero, 1);\n        }\n\n        /// <summary>\n        /// Sphere at NaN with radius -1.\n        /// </summary>\n        public static Sphere3f Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Sphere3f(V3f.NaN, -1);\n        }\n\n        #endregion\n\n        #region Comparison operators\n\n        /// <summary>\n        /// Tests whether two specified spheres are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Sphere3f a, Sphere3f b)\n            => (a.Center == b.Center) && (a.Radius == b.Radius);\n\n        /// <summary>\n        /// Tests whether two specified spheres are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Sphere3f a, Sphere3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Sphere3f other)\n            => Center.Equals(other.Center) && Radius.Equals(other.Radius);\n\n        public override readonly bool Equals(object other)\n            => (other is Sphere3f o) ? Equals(o) : false;\n\n        /// <summary>\n        /// Writes a sphere to String.\n        /// </summary>\n        /// <returns>String representing the sphere.</returns>\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Center, Radius);\n\n        public static Sphere3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Sphere3f(V3f.Parse(x[0]), float.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        public readonly Box3f BoundingBox3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Box3f(Center - Radius, Center + Radius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Sphere3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Sphere3f a, Sphere3f b, float tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Sphere3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Sphere3f a, Sphere3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Sphere3d\n\n    /// <summary>\n    /// A three dimensional sphere represented by center and radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Sphere3d : IEquatable<Sphere3d>, IBoundingBox3d, IValidity\n    {\n        [DataMember]\n        public V3d Center;\n        [DataMember]\n        public double Radius;\n\n        #region Constructors\n\n        /// <summary>\n\t\t/// Initializes a new instance of the <see cref=\"Sphere3d\"/> class using center and radius values.\n\t\t/// </summary>\n\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3d(V3d center, double radius)\n\t\t{\n\t\t\tCenter = center;\n\t\t\tRadius = radius;\n\t\t}\n\n        /// <summary>\n        /// Creates a sphere from its center, and a point on its surface.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3d(V3d center, V3d pointOnSurface)\n        {\n            Center = center;\n            Radius = (pointOnSurface - center).Length;\n        }\n\n        /// <summary>\n        /// Uses the first 2 points in the sequence as the\n        /// sphere's center and a point on the sphere's surface.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3d(IEnumerable<V3d> points)\n        {\n            var va = points.TakeToArray(2);\n            Center = va[0];\n            Radius = (va[1] - va[0]).Length;\n        }\n\n        /// <summary>\n\t\t/// Initializes a new instance of the <see cref=\"Sphere3d\"/> class using values from another sphere instance.\n\t\t/// </summary>\n\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3d(Sphere3d sphere)\n\t\t{\n\t\t\tCenter = sphere.Center;\n\t\t\tRadius = sphere.Radius;\n\t\t}\n\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"Sphere3d\"/> class using values from a <see cref=\"Sphere3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Sphere3d(Sphere3f sphere)\n        {\n            Center = (V3d)sphere.Center;\n            Radius = (double)sphere.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Sphere3d(Sphere3f s)\n            => new Sphere3d(s);\n\n        #endregion\n\n        #region Static Factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Sphere3d FromRadius(double radius)\n            => new Sphere3d(V3d.Zero, radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Sphere3d FromCenterAndRadius(V3d center, double radius)\n            => new Sphere3d(center, radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Sphere3d FromPoints(IEnumerable<V3d> points)\n            => new Sphere3d(points);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0;\n        }\n\n        public readonly double RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius;\n        }\n\n        public readonly double SurfaceArea\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (4 * RadiusSquared * Constant.Pi);\n        }\n\n        public readonly double Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (4.0 / 3.0) * Constant.Pi * Radius * Radius * Radius;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Sphere at origin with radius 0.\n        /// </summary>\n        public static Sphere3d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Sphere3d(V3d.Zero, 0);\n        }\n\n        /// <summary>\n        /// Sphere at origin with radius 1.\n        /// </summary>\n        public static Sphere3d Unit\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Sphere3d(V3d.Zero, 1);\n        }\n\n        /// <summary>\n        /// Sphere at NaN with radius -1.\n        /// </summary>\n        public static Sphere3d Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Sphere3d(V3d.NaN, -1);\n        }\n\n        #endregion\n\n        #region Comparison operators\n\n        /// <summary>\n        /// Tests whether two specified spheres are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Sphere3d a, Sphere3d b)\n            => (a.Center == b.Center) && (a.Radius == b.Radius);\n\n        /// <summary>\n        /// Tests whether two specified spheres are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Sphere3d a, Sphere3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Sphere3d other)\n            => Center.Equals(other.Center) && Radius.Equals(other.Radius);\n\n        public override readonly bool Equals(object other)\n            => (other is Sphere3d o) ? Equals(o) : false;\n\n        /// <summary>\n        /// Writes a sphere to String.\n        /// </summary>\n        /// <returns>String representing the sphere.</returns>\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Center, Radius);\n\n        public static Sphere3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Sphere3d(V3d.Parse(x[0]), double.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        public readonly Box3d BoundingBox3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Box3d(Center - Radius, Center + Radius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Sphere3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Sphere3d a, Sphere3d b, double tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Sphere3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Sphere3d a, Sphere3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Sphere/Sphere3_template.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Sphere3\" + tc;\n    //#   var type2 = \"Sphere3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var iboundingbox = \"IBoundingBox3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var fourbythree = isDouble ? \"(4.0 / 3.0)\" : \"(4.0f / 3.0f)\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    #region __type__\n\n    /// <summary>\n    /// A three dimensional sphere represented by center and radius.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, __iboundingbox__, IValidity\n    {\n        [DataMember]\n        public __v3t__ Center;\n        [DataMember]\n        public __ftype__ Radius;\n\n        #region Constructors\n\n        /// <summary>\n\t\t/// Initializes a new instance of the <see cref=\"__type__\"/> class using center and radius values.\n\t\t/// </summary>\n\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v3t__ center, __ftype__ radius)\n\t\t{\n\t\t\tCenter = center;\n\t\t\tRadius = radius;\n\t\t}\n\n        /// <summary>\n        /// Creates a sphere from its center, and a point on its surface.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v3t__ center, __v3t__ pointOnSurface)\n        {\n            Center = center;\n            Radius = (pointOnSurface - center).Length;\n        }\n\n        /// <summary>\n        /// Uses the first 2 points in the sequence as the\n        /// sphere's center and a point on the sphere's surface.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(IEnumerable<__v3t__> points)\n        {\n            var va = points.TakeToArray(2);\n            Center = va[0];\n            Radius = (va[1] - va[0]).Length;\n        }\n\n        /// <summary>\n\t\t/// Initializes a new instance of the <see cref=\"__type__\"/> class using values from another sphere instance.\n\t\t/// </summary>\n\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ sphere)\n\t\t{\n\t\t\tCenter = sphere.Center;\n\t\t\tRadius = sphere.Radius;\n\t\t}\n\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"__type__\"/> class using values from a <see cref=\"__type2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ sphere)\n        {\n            Center = (__v3t__)sphere.Center;\n            Radius = (__ftype__)sphere.Radius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ s)\n            => new __type__(s);\n\n        #endregion\n\n        #region Static Factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromRadius(__ftype__ radius)\n            => new __type__(__v3t__.Zero, radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromCenterAndRadius(__v3t__ center, __ftype__ radius)\n            => new __type__(center, radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromPoints(IEnumerable<__v3t__> points)\n            => new __type__(points);\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius < 0.0;\n        }\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius >= 0.0;\n        }\n\n        public readonly __ftype__ RadiusSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Radius * Radius;\n        }\n\n        public readonly __ftype__ SurfaceArea\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (4 * RadiusSquared * __pi__);\n        }\n\n        public readonly __ftype__ Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => __fourbythree__ * __pi__ * Radius * Radius * Radius;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Sphere at origin with radius 0.\n        /// </summary>\n        public static __type__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v3t__.Zero, 0);\n        }\n\n        /// <summary>\n        /// Sphere at origin with radius 1.\n        /// </summary>\n        public static __type__ Unit\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v3t__.Zero, 1);\n        }\n\n        /// <summary>\n        /// Sphere at NaN with radius -1.\n        /// </summary>\n        public static __type__ Invalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__v3t__.NaN, -1);\n        }\n\n        #endregion\n\n        #region Comparison operators\n\n        /// <summary>\n        /// Tests whether two specified spheres are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => (a.Center == b.Center) && (a.Radius == b.Radius);\n\n        /// <summary>\n        /// Tests whether two specified spheres are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode() => HashCode.GetCombined(Center, Radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Center.Equals(other.Center) && Radius.Equals(other.Radius);\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        /// <summary>\n        /// Writes a sphere to String.\n        /// </summary>\n        /// <returns>String representing the sphere.</returns>\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Center, Radius);\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__v3t__.Parse(x[0]), __ftype__.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n\n        #region __iboundingbox__ Members\n\n        public readonly __box3t__ BoundingBox3__tc__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __box3t__(Center - Radius, Center + Radius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Center, b.Center, tolerance) &&\n            ApproximateEquals(a.Radius, b.Radius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# }\n}"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Torus/Torus3_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Torus3f\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Torus3f : IEquatable<Torus3f>, IBoundingBox3f\n    {\n        [DataMember]\n        public V3f Position;\n        [DataMember]\n        public V3f Direction;\n        [DataMember]\n        public float MajorRadius;\n        [DataMember]\n        public float MinorRadius;\n\n        #region Constructor\n\n        public Torus3f(V3f position, V3f direction, float majorRadius, float minorRadius)\n        {\n            Position = position;\n            Direction = direction;\n            MinorRadius = minorRadius;\n            MajorRadius = majorRadius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Torus3f(Torus3f o)\n        {\n            Position = o.Position;\n            Direction = o.Direction;\n            MinorRadius = o.MinorRadius;\n            MajorRadius = o.MajorRadius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Torus3f(Torus3d o)\n        {\n            Position = (V3f)o.Position;\n            Direction = (V3f)o.Direction;\n            MinorRadius = (float)o.MinorRadius;\n            MajorRadius = (float)o.MajorRadius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Torus3f(Torus3d o)\n            => new Torus3f(o);\n\n        #endregion\n\n        #region Properties\n\n        public readonly Circle3f MajorCircle\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => GetMajorCircle();\n        }\n\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 4 * ConstantF.PiSquared * MajorRadius * MinorRadius;\n        }\n\n        public readonly float Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * ConstantF.PiSquared * MajorRadius * MinorRadius * MinorRadius;\n        }\n\n        #endregion\n\n        #region Operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Circle3f GetMajorCircle() => new Circle3f(Position, Direction, MajorRadius);\n\n        public readonly Circle3f GetMinorCircle(float angle)\n        {\n            var c = GetMajorCircle();\n            var p = c.GetPoint(angle);\n            var dir = (p - Position).Normalized.Cross(Direction).Normalized;\n            return new Circle3f(p, dir, MinorRadius);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float GetMinimalDistance(V3f p) => GetMinimalDistance(p, Position, Direction, MajorRadius, MinorRadius);\n\n        public static float GetMinimalDistance(V3f p, V3f position, V3f direction, float majorRadius, float minorRadius)\n        {\n            var plane = new Plane3f(direction, position);\n            var planePoint = p.GetClosestPointOn(plane);\n            var distanceOnPlane = (Vec.Distance(planePoint, position) - majorRadius).Abs();\n            var distanceToCircle = (Vec.DistanceSquared(planePoint, p) + distanceOnPlane.Square()).Sqrt();\n            return (distanceToCircle - minorRadius).Abs();\n        }\n\n        #endregion\n\n        #region Comparison operators\n\n        /// <summary>\n        /// Tests whether two specified spheres are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Torus3f a, Torus3f b) =>\n            (a.Position == b.Position) &&\n            (a.Direction == b.Direction) &&\n            (a.MajorRadius == b.MajorRadius) &&\n            (a.MinorRadius == b.MinorRadius);\n\n        /// <summary>\n        /// Tests whether two specified spheres are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Torus3f a, Torus3f b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Position, Direction, MajorRadius, MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Torus3f other) =>\n            Position.Equals(other.Position) &&\n            Direction.Equals(other.Direction) &&\n            MajorRadius.Equals(other.MajorRadius) &&\n            MinorRadius.Equals(other.MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Torus3f o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", Position, Direction, MajorRadius, MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Torus3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Torus3f(\n                V3f.Parse(x[0]),\n                V3f.Parse(x[1]),\n                float.Parse(x[2], CultureInfo.InvariantCulture),\n                float.Parse(x[3], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        readonly Box3f IBoundingBox3f.BoundingBox3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => GetMajorCircle().BoundingBox3f.EnlargedBy(MinorRadius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Torus3f\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Torus3f a, Torus3f b, float tolerance) =>\n            ApproximateEquals(a.Position, b.Position, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance) &&\n            ApproximateEquals(a.MajorRadius, b.MajorRadius, tolerance) &&\n            ApproximateEquals(a.MinorRadius, b.MinorRadius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Torus3f\"/> are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Torus3f a, Torus3f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    #region Torus3d\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Torus3d : IEquatable<Torus3d>, IBoundingBox3d\n    {\n        [DataMember]\n        public V3d Position;\n        [DataMember]\n        public V3d Direction;\n        [DataMember]\n        public double MajorRadius;\n        [DataMember]\n        public double MinorRadius;\n\n        #region Constructor\n\n        public Torus3d(V3d position, V3d direction, double majorRadius, double minorRadius)\n        {\n            Position = position;\n            Direction = direction;\n            MinorRadius = minorRadius;\n            MajorRadius = majorRadius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Torus3d(Torus3d o)\n        {\n            Position = o.Position;\n            Direction = o.Direction;\n            MinorRadius = o.MinorRadius;\n            MajorRadius = o.MajorRadius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Torus3d(Torus3f o)\n        {\n            Position = (V3d)o.Position;\n            Direction = (V3d)o.Direction;\n            MinorRadius = (double)o.MinorRadius;\n            MajorRadius = (double)o.MajorRadius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Torus3d(Torus3f o)\n            => new Torus3d(o);\n\n        #endregion\n\n        #region Properties\n\n        public readonly Circle3d MajorCircle\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => GetMajorCircle();\n        }\n\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 4 * Constant.PiSquared * MajorRadius * MinorRadius;\n        }\n\n        public readonly double Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * Constant.PiSquared * MajorRadius * MinorRadius * MinorRadius;\n        }\n\n        #endregion\n\n        #region Operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Circle3d GetMajorCircle() => new Circle3d(Position, Direction, MajorRadius);\n\n        public readonly Circle3d GetMinorCircle(double angle)\n        {\n            var c = GetMajorCircle();\n            var p = c.GetPoint(angle);\n            var dir = (p - Position).Normalized.Cross(Direction).Normalized;\n            return new Circle3d(p, dir, MinorRadius);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double GetMinimalDistance(V3d p) => GetMinimalDistance(p, Position, Direction, MajorRadius, MinorRadius);\n\n        public static double GetMinimalDistance(V3d p, V3d position, V3d direction, double majorRadius, double minorRadius)\n        {\n            var plane = new Plane3d(direction, position);\n            var planePoint = p.GetClosestPointOn(plane);\n            var distanceOnPlane = (Vec.Distance(planePoint, position) - majorRadius).Abs();\n            var distanceToCircle = (Vec.DistanceSquared(planePoint, p) + distanceOnPlane.Square()).Sqrt();\n            return (distanceToCircle - minorRadius).Abs();\n        }\n\n        #endregion\n\n        #region Comparison operators\n\n        /// <summary>\n        /// Tests whether two specified spheres are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Torus3d a, Torus3d b) =>\n            (a.Position == b.Position) &&\n            (a.Direction == b.Direction) &&\n            (a.MajorRadius == b.MajorRadius) &&\n            (a.MinorRadius == b.MinorRadius);\n\n        /// <summary>\n        /// Tests whether two specified spheres are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Torus3d a, Torus3d b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Position, Direction, MajorRadius, MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Torus3d other) =>\n            Position.Equals(other.Position) &&\n            Direction.Equals(other.Direction) &&\n            MajorRadius.Equals(other.MajorRadius) &&\n            MinorRadius.Equals(other.MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is Torus3d o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", Position, Direction, MajorRadius, MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Torus3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Torus3d(\n                V3d.Parse(x[0]),\n                V3d.Parse(x[1]),\n                double.Parse(x[2], CultureInfo.InvariantCulture),\n                double.Parse(x[3], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        readonly Box3d IBoundingBox3d.BoundingBox3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => GetMajorCircle().BoundingBox3d.EnlargedBy(MinorRadius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"Torus3d\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Torus3d a, Torus3d b, double tolerance) =>\n            ApproximateEquals(a.Position, b.Position, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance) &&\n            ApproximateEquals(a.MajorRadius, b.MajorRadius, tolerance) &&\n            ApproximateEquals(a.MinorRadius, b.MinorRadius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Torus3d\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Torus3d a, Torus3d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Torus/Torus3_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Torus3\" + tc;\n    //#   var type2 = \"Torus3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var circle3t = \"Circle3\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var trafo3t = \"Trafo3\" + tc;\n    //#   var iboundingbox3t = \"IBoundingBox3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var dotnine = isDouble ? \"0.9\" : \"0.9f\";\n    //#   var constant = isDouble ? \"Constant\" : \"ConstantF\";\n    #region __type__\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, __iboundingbox3t__\n    {\n        [DataMember]\n        public __v3t__ Position;\n        [DataMember]\n        public __v3t__ Direction;\n        [DataMember]\n        public __ftype__ MajorRadius;\n        [DataMember]\n        public __ftype__ MinorRadius;\n\n        #region Constructor\n\n        public __type__(__v3t__ position, __v3t__ direction, __ftype__ majorRadius, __ftype__ minorRadius)\n        {\n            Position = position;\n            Direction = direction;\n            MinorRadius = minorRadius;\n            MajorRadius = majorRadius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ o)\n        {\n            Position = o.Position;\n            Direction = o.Direction;\n            MinorRadius = o.MinorRadius;\n            MajorRadius = o.MajorRadius;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ o)\n        {\n            Position = (__v3t__)o.Position;\n            Direction = (__v3t__)o.Direction;\n            MinorRadius = (__ftype__)o.MinorRadius;\n            MajorRadius = (__ftype__)o.MajorRadius;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ o)\n            => new __type__(o);\n\n        #endregion\n\n        #region Properties\n\n        public readonly __circle3t__ MajorCircle\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => GetMajorCircle();\n        }\n\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 4 * __constant__.PiSquared * MajorRadius * MinorRadius;\n        }\n\n        public readonly __ftype__ Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => 2 * __constant__.PiSquared * MajorRadius * MinorRadius * MinorRadius;\n        }\n\n        #endregion\n\n        #region Operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __circle3t__ GetMajorCircle() => new __circle3t__(Position, Direction, MajorRadius);\n\n        public readonly __circle3t__ GetMinorCircle(__ftype__ angle)\n        {\n            var c = GetMajorCircle();\n            var p = c.GetPoint(angle);\n            var dir = (p - Position).Normalized.Cross(Direction).Normalized;\n            return new __circle3t__(p, dir, MinorRadius);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__ GetMinimalDistance(__v3t__ p) => GetMinimalDistance(p, Position, Direction, MajorRadius, MinorRadius);\n\n        public static __ftype__ GetMinimalDistance(__v3t__ p, __v3t__ position, __v3t__ direction, __ftype__ majorRadius, __ftype__ minorRadius)\n        {\n            var plane = new __plane3t__(direction, position);\n            var planePoint = p.GetClosestPointOn(plane);\n            var distanceOnPlane = (Vec.Distance(planePoint, position) - majorRadius).Abs();\n            var distanceToCircle = (Vec.DistanceSquared(planePoint, p) + distanceOnPlane.Square()).Sqrt();\n            return (distanceToCircle - minorRadius).Abs();\n        }\n\n        #endregion\n\n        #region Comparison operators\n\n        /// <summary>\n        /// Tests whether two specified spheres are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b) =>\n            (a.Position == b.Position) &&\n            (a.Direction == b.Direction) &&\n            (a.MajorRadius == b.MajorRadius) &&\n            (a.MinorRadius == b.MinorRadius);\n\n        /// <summary>\n        /// Tests whether two specified spheres are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode() => HashCode.GetCombined(Position, Direction, MajorRadius, MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other) =>\n            Position.Equals(other.Position) &&\n            Direction.Equals(other.Direction) &&\n            MajorRadius.Equals(other.MajorRadius) &&\n            MinorRadius.Equals(other.MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", Position, Direction, MajorRadius, MinorRadius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(\n                __v3t__.Parse(x[0]),\n                __v3t__.Parse(x[1]),\n                __ftype__.Parse(x[2], CultureInfo.InvariantCulture),\n                __ftype__.Parse(x[3], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n\n        #region __iboundingbox3t__ Members\n\n        readonly __box3t__ __iboundingbox3t__.BoundingBox3__tc__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => GetMajorCircle().BoundingBox3__tc__.EnlargedBy(MinorRadius);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance) =>\n            ApproximateEquals(a.Position, b.Position, tolerance) &&\n            ApproximateEquals(a.Direction, b.Direction, tolerance) &&\n            ApproximateEquals(a.MajorRadius, b.MajorRadius, tolerance) &&\n            ApproximateEquals(a.MinorRadius, b.MinorRadius, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> are equal within\n        /// Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Triangle/Triangle2_auto.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Triangle2f\n\n    /// <summary>\n    /// A two-dimensional triangle represented by its three points.\n    /// </summary>\n    public partial struct Triangle2f : IBoundingCircle2f\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area of the triangle.\n        /// </summary>\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Area(this);\n        }\n\n        /// <summary>\n        /// Returns whether the triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.IsDegenerated(this);\n        }\n\n        /// <summary>\n        /// Returns a negative value if the triangle has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        public readonly float WindingOrder\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.WindingOrder(this);\n        }\n\n        #endregion\n\n        #region CircumCircle\n\n        public readonly Circle2f CircumCircle\n        {\n            get\n            {\n                ComputeCircumCircleSquared(P0, P1, P2, out V2f center, out float radiusSquared);\n                return new Circle2f(center, radiusSquared.Sqrt());\n            }\n        }\n\n        public readonly Circle2f CircumCircleSquared\n        {\n            get\n            {\n                ComputeCircumCircleSquared(P0, P1, P2, out V2f center, out float radiusSquared);\n                return new Circle2f(center, radiusSquared);\n            }\n        }\n\n        public static void ComputeCircumCircleSquared(\n            V2f p0, V2f p1, V2f p2,\n            out V2f center, out float radiusSquared)\n        {\n            float y01abs = Fun.Abs(p0.Y - p1.Y);\n            float y12abs = Fun.Abs(p1.Y - p2.Y);\n\n            if (y01abs < Constant<float>.PositiveTinyValue\n                && y12abs < Constant<float>.PositiveTinyValue)\n            {\n                center = V2f.NaN; radiusSquared = -1; return;\n            }\n\n            float xc, yc;\n\n            if (y01abs < Constant<float>.PositiveTinyValue)\n            {\n                float m2 = (p1.X - p2.X) / (p2.Y - p1.Y);\n                float m12x = 0.5f * (p1.X + p2.X);\n                float m12y = 0.5f * (p1.Y + p2.Y);\n                xc = 0.5f * (p1.X + p0.X);\n                yc = m2 * (xc - m12x) + m12y;\n            }\n            else if (y12abs < Constant<float>.PositiveTinyValue)\n            {\n                float m1 = (p0.X - p1.X) / (p1.Y - p0.Y);\n                float m01x = 0.5f * (p0.X + p1.X);\n                float m01y = 0.5f * (p0.Y + p1.Y);\n                xc = 0.5f * (p2.X + p1.X);\n                yc = m1 * (xc - m01x) + m01y;\n            }\n            else\n            {\n                float m1 = (p0.X - p1.X) / (p1.Y - p0.Y);\n                float m2 = (p1.X - p2.X) / (p2.Y - p1.Y);\n                float m01x = 0.5f * (p0.X + p1.X);\n                float m01y = 0.5f * (p0.Y + p1.Y);\n                float m12x = 0.5f * (p1.X + p2.X);\n                float m12y = 0.5f * (p1.Y + p2.Y);\n                float m12 = m1 - m2;\n                if (Fun.Abs(m12) < Constant<float>.PositiveTinyValue)\n                {\n                    center = V2f.NaN; radiusSquared = -1; return;\n                }\n                xc = (m1 * m01x - m2 * m12x + m12y - m01y) / m12;\n                if (y01abs > y12abs)\n                {\n                    yc = m1 * (xc - m01x) + m01y;\n                }\n                else\n                {\n                    yc = m2 * (xc - m12x) + m12y;\n                }\n            }\n            center = new V2f(xc, yc);\n            radiusSquared = Vec.DistanceSquared(p0, center);\n        }\n\n        #endregion\n\n        #region IBoundingCircle2f Members\n\n        public readonly Circle2f BoundingCircle2f\n        {\n            get\n            {\n                var edge01 = P1 - P0;\n                var edge02 = P2 - P0;\n                float dot0101 = Vec.Dot(edge01, edge01);\n                float dot0102 = Vec.Dot(edge01, edge02);\n                float dot0202 = Vec.Dot(edge02, edge02);\n                float d = 2 * (dot0101 * dot0202 - dot0102 * dot0102);\n                if (d.Abs() <= 1e-4f) return Circle2f.Invalid;\n                float s = (dot0101 * dot0202 - dot0202 * dot0102) / d;\n                float t = (dot0202 * dot0101 - dot0101 * dot0102) / d;\n                var p = P0;\n                var cir = new Circle2f();\n                if (s <= 0)\n                    cir.Center = 0.5f * (P0 + P2);\n                else if (t <= 0)\n                    cir.Center = 0.5f * (P0 + P1);\n                else if (s + t >= 1)\n                {\n                    cir.Center = 0.5f * (P1 + P2);\n                    p = P1;\n                }\n                else\n                    cir.Center = P0 + s * edge01 + t * edge02;\n                cir.Radius = (cir.Center - p).Length;\n                return cir;\n            }\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods for triangles.\n    /// </summary>\n    public static partial class Triangle\n    {\n        #region Area\n\n        /// <summary>\n        /// Returns the area of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Area(V2f p0, V2f p1, V2f p2)\n            => WindingOrder(p0, p1, p2).Abs() * 0.5f;\n\n        /// <summary>\n        /// Returns the area of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Area(Triangle2f t)\n            => Area(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region IsDegenerated\n\n        /// <summary>\n        /// Returns whether the triangle defined by the give points is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(V2f p0, V2f p1, V2f p2)\n            => WindingOrder(p0, p1, p2).IsTiny();\n\n        /// <summary>\n        /// Returns whether the given triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(Triangle2f t)\n            => WindingOrder(t).IsTiny();\n\n        #endregion\n\n        #region WindingOrder\n\n        /// <summary>\n        /// Returns a negative value if the triangle defined by the given points has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float WindingOrder(V2f p0, V2f p1, V2f p2)\n            => (p1.X - p0.X) * (p2.Y - p0.Y) - (p2.X - p0.X) * (p1.Y - p0.Y);\n\n        /// <summary>\n        /// Returns a negative value if the given triangle has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float WindingOrder(Triangle2f t)\n            => WindingOrder(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Gets the distance between the closest point on the triangle [a, b, c] and the given query point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(V2f a, V2f b, V2f c, V2f query)\n        {\n            var cp = query.GetClosestPointOnTriangle(a, b, c);\n            return (cp - query).Length;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Triangle2d\n\n    /// <summary>\n    /// A two-dimensional triangle represented by its three points.\n    /// </summary>\n    public partial struct Triangle2d : IBoundingCircle2d\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area of the triangle.\n        /// </summary>\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Area(this);\n        }\n\n        /// <summary>\n        /// Returns whether the triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.IsDegenerated(this);\n        }\n\n        /// <summary>\n        /// Returns a negative value if the triangle has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        public readonly double WindingOrder\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.WindingOrder(this);\n        }\n\n        #endregion\n\n        #region CircumCircle\n\n        public readonly Circle2d CircumCircle\n        {\n            get\n            {\n                ComputeCircumCircleSquared(P0, P1, P2, out V2d center, out double radiusSquared);\n                return new Circle2d(center, radiusSquared.Sqrt());\n            }\n        }\n\n        public readonly Circle2d CircumCircleSquared\n        {\n            get\n            {\n                ComputeCircumCircleSquared(P0, P1, P2, out V2d center, out double radiusSquared);\n                return new Circle2d(center, radiusSquared);\n            }\n        }\n\n        public static void ComputeCircumCircleSquared(\n            V2d p0, V2d p1, V2d p2,\n            out V2d center, out double radiusSquared)\n        {\n            double y01abs = Fun.Abs(p0.Y - p1.Y);\n            double y12abs = Fun.Abs(p1.Y - p2.Y);\n\n            if (y01abs < Constant<double>.PositiveTinyValue\n                && y12abs < Constant<double>.PositiveTinyValue)\n            {\n                center = V2d.NaN; radiusSquared = -1; return;\n            }\n\n            double xc, yc;\n\n            if (y01abs < Constant<double>.PositiveTinyValue)\n            {\n                double m2 = (p1.X - p2.X) / (p2.Y - p1.Y);\n                double m12x = 0.5 * (p1.X + p2.X);\n                double m12y = 0.5 * (p1.Y + p2.Y);\n                xc = 0.5 * (p1.X + p0.X);\n                yc = m2 * (xc - m12x) + m12y;\n            }\n            else if (y12abs < Constant<double>.PositiveTinyValue)\n            {\n                double m1 = (p0.X - p1.X) / (p1.Y - p0.Y);\n                double m01x = 0.5 * (p0.X + p1.X);\n                double m01y = 0.5 * (p0.Y + p1.Y);\n                xc = 0.5 * (p2.X + p1.X);\n                yc = m1 * (xc - m01x) + m01y;\n            }\n            else\n            {\n                double m1 = (p0.X - p1.X) / (p1.Y - p0.Y);\n                double m2 = (p1.X - p2.X) / (p2.Y - p1.Y);\n                double m01x = 0.5 * (p0.X + p1.X);\n                double m01y = 0.5 * (p0.Y + p1.Y);\n                double m12x = 0.5 * (p1.X + p2.X);\n                double m12y = 0.5 * (p1.Y + p2.Y);\n                double m12 = m1 - m2;\n                if (Fun.Abs(m12) < Constant<double>.PositiveTinyValue)\n                {\n                    center = V2d.NaN; radiusSquared = -1; return;\n                }\n                xc = (m1 * m01x - m2 * m12x + m12y - m01y) / m12;\n                if (y01abs > y12abs)\n                {\n                    yc = m1 * (xc - m01x) + m01y;\n                }\n                else\n                {\n                    yc = m2 * (xc - m12x) + m12y;\n                }\n            }\n            center = new V2d(xc, yc);\n            radiusSquared = Vec.DistanceSquared(p0, center);\n        }\n\n        #endregion\n\n        #region IBoundingCircle2d Members\n\n        public readonly Circle2d BoundingCircle2d\n        {\n            get\n            {\n                var edge01 = P1 - P0;\n                var edge02 = P2 - P0;\n                double dot0101 = Vec.Dot(edge01, edge01);\n                double dot0102 = Vec.Dot(edge01, edge02);\n                double dot0202 = Vec.Dot(edge02, edge02);\n                double d = 2 * (dot0101 * dot0202 - dot0102 * dot0102);\n                if (d.Abs() <= 1e-6) return Circle2d.Invalid;\n                double s = (dot0101 * dot0202 - dot0202 * dot0102) / d;\n                double t = (dot0202 * dot0101 - dot0101 * dot0102) / d;\n                var p = P0;\n                var cir = new Circle2d();\n                if (s <= 0)\n                    cir.Center = 0.5 * (P0 + P2);\n                else if (t <= 0)\n                    cir.Center = 0.5 * (P0 + P1);\n                else if (s + t >= 1)\n                {\n                    cir.Center = 0.5 * (P1 + P2);\n                    p = P1;\n                }\n                else\n                    cir.Center = P0 + s * edge01 + t * edge02;\n                cir.Radius = (cir.Center - p).Length;\n                return cir;\n            }\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods for triangles.\n    /// </summary>\n    public static partial class Triangle\n    {\n        #region Area\n\n        /// <summary>\n        /// Returns the area of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Area(V2d p0, V2d p1, V2d p2)\n            => WindingOrder(p0, p1, p2).Abs() * 0.5;\n\n        /// <summary>\n        /// Returns the area of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Area(Triangle2d t)\n            => Area(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region IsDegenerated\n\n        /// <summary>\n        /// Returns whether the triangle defined by the give points is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(V2d p0, V2d p1, V2d p2)\n            => WindingOrder(p0, p1, p2).IsTiny();\n\n        /// <summary>\n        /// Returns whether the given triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(Triangle2d t)\n            => WindingOrder(t).IsTiny();\n\n        #endregion\n\n        #region WindingOrder\n\n        /// <summary>\n        /// Returns a negative value if the triangle defined by the given points has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double WindingOrder(V2d p0, V2d p1, V2d p2)\n            => (p1.X - p0.X) * (p2.Y - p0.Y) - (p2.X - p0.X) * (p1.Y - p0.Y);\n\n        /// <summary>\n        /// Returns a negative value if the given triangle has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double WindingOrder(Triangle2d t)\n            => WindingOrder(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Gets the distance between the closest point on the triangle [a, b, c] and the given query point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(V2d a, V2d b, V2d c, V2d query)\n        {\n            var cp = query.GetClosestPointOnTriangle(a, b, c);\n            return (cp - query).Length;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Triangle/Triangle2_template.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Triangle2\" + tc;\n    //#   var type2 = \"Triangle2\" + tc2;\n    //#   var v2t = \"V2\" + tc;\n    //#   var box2t = \"Box2\" + tc;\n    //#   var plane2t = \"Plane2\" + tc;\n    //#   var circle2t = \"Circle2\" + tc;\n    //#   var iboundingcircle2t = \"IBoundingCircle2\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#   var eps = isDouble ? \"1e-6\" : \"1e-4f\";\n    #region __type__\n\n    /// <summary>\n    /// A two-dimensional triangle represented by its three points.\n    /// </summary>\n    public partial struct __type__ : __iboundingcircle2t__\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area of the triangle.\n        /// </summary>\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Area(this);\n        }\n\n        /// <summary>\n        /// Returns whether the triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.IsDegenerated(this);\n        }\n\n        /// <summary>\n        /// Returns a negative value if the triangle has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        public readonly __ftype__ WindingOrder\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.WindingOrder(this);\n        }\n\n        #endregion\n\n        #region CircumCircle\n\n        public readonly __circle2t__ CircumCircle\n        {\n            get\n            {\n                ComputeCircumCircleSquared(P0, P1, P2, out __v2t__ center, out __ftype__ radiusSquared);\n                return new __circle2t__(center, radiusSquared.Sqrt());\n            }\n        }\n\n        public readonly __circle2t__ CircumCircleSquared\n        {\n            get\n            {\n                ComputeCircumCircleSquared(P0, P1, P2, out __v2t__ center, out __ftype__ radiusSquared);\n                return new __circle2t__(center, radiusSquared);\n            }\n        }\n\n        public static void ComputeCircumCircleSquared(\n            __v2t__ p0, __v2t__ p1, __v2t__ p2,\n            out __v2t__ center, out __ftype__ radiusSquared)\n        {\n            __ftype__ y01abs = Fun.Abs(p0.Y - p1.Y);\n            __ftype__ y12abs = Fun.Abs(p1.Y - p2.Y);\n\n            if (y01abs < Constant<__ftype__>.PositiveTinyValue\n                && y12abs < Constant<__ftype__>.PositiveTinyValue)\n            {\n                center = __v2t__.NaN; radiusSquared = -1; return;\n            }\n\n            __ftype__ xc, yc;\n\n            if (y01abs < Constant<__ftype__>.PositiveTinyValue)\n            {\n                __ftype__ m2 = (p1.X - p2.X) / (p2.Y - p1.Y);\n                __ftype__ m12x = __half__ * (p1.X + p2.X);\n                __ftype__ m12y = __half__ * (p1.Y + p2.Y);\n                xc = __half__ * (p1.X + p0.X);\n                yc = m2 * (xc - m12x) + m12y;\n            }\n            else if (y12abs < Constant<__ftype__>.PositiveTinyValue)\n            {\n                __ftype__ m1 = (p0.X - p1.X) / (p1.Y - p0.Y);\n                __ftype__ m01x = __half__ * (p0.X + p1.X);\n                __ftype__ m01y = __half__ * (p0.Y + p1.Y);\n                xc = __half__ * (p2.X + p1.X);\n                yc = m1 * (xc - m01x) + m01y;\n            }\n            else\n            {\n                __ftype__ m1 = (p0.X - p1.X) / (p1.Y - p0.Y);\n                __ftype__ m2 = (p1.X - p2.X) / (p2.Y - p1.Y);\n                __ftype__ m01x = __half__ * (p0.X + p1.X);\n                __ftype__ m01y = __half__ * (p0.Y + p1.Y);\n                __ftype__ m12x = __half__ * (p1.X + p2.X);\n                __ftype__ m12y = __half__ * (p1.Y + p2.Y);\n                __ftype__ m12 = m1 - m2;\n                if (Fun.Abs(m12) < Constant<__ftype__>.PositiveTinyValue)\n                {\n                    center = __v2t__.NaN; radiusSquared = -1; return;\n                }\n                xc = (m1 * m01x - m2 * m12x + m12y - m01y) / m12;\n                if (y01abs > y12abs)\n                {\n                    yc = m1 * (xc - m01x) + m01y;\n                }\n                else\n                {\n                    yc = m2 * (xc - m12x) + m12y;\n                }\n            }\n            center = new __v2t__(xc, yc);\n            radiusSquared = Vec.DistanceSquared(p0, center);\n        }\n\n        #endregion\n\n        #region __iboundingcircle2t__ Members\n\n        public readonly __circle2t__ BoundingCircle2__tc__\n        {\n            get\n            {\n                var edge01 = P1 - P0;\n                var edge02 = P2 - P0;\n                __ftype__ dot0101 = Vec.Dot(edge01, edge01);\n                __ftype__ dot0102 = Vec.Dot(edge01, edge02);\n                __ftype__ dot0202 = Vec.Dot(edge02, edge02);\n                __ftype__ d = 2 * (dot0101 * dot0202 - dot0102 * dot0102);\n                if (d.Abs() <= __eps__) return __circle2t__.Invalid;\n                __ftype__ s = (dot0101 * dot0202 - dot0202 * dot0102) / d;\n                __ftype__ t = (dot0202 * dot0101 - dot0101 * dot0102) / d;\n                var p = P0;\n                var cir = new __circle2t__();\n                if (s <= 0)\n                    cir.Center = __half__ * (P0 + P2);\n                else if (t <= 0)\n                    cir.Center = __half__ * (P0 + P1);\n                else if (s + t >= 1)\n                {\n                    cir.Center = __half__ * (P1 + P2);\n                    p = P1;\n                }\n                else\n                    cir.Center = P0 + s * edge01 + t * edge02;\n                cir.Radius = (cir.Center - p).Length;\n                return cir;\n            }\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods for triangles.\n    /// </summary>\n    public static partial class Triangle\n    {\n        #region Area\n\n        /// <summary>\n        /// Returns the area of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Area(__v2t__ p0, __v2t__ p1, __v2t__ p2)\n            => WindingOrder(p0, p1, p2).Abs() * __half__;\n\n        /// <summary>\n        /// Returns the area of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Area(__type__ t)\n            => Area(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region IsDegenerated\n\n        /// <summary>\n        /// Returns whether the triangle defined by the give points is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(__v2t__ p0, __v2t__ p1, __v2t__ p2)\n            => WindingOrder(p0, p1, p2).IsTiny();\n\n        /// <summary>\n        /// Returns whether the given triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(__type__ t)\n            => WindingOrder(t).IsTiny();\n\n        #endregion\n\n        #region WindingOrder\n\n        /// <summary>\n        /// Returns a negative value if the triangle defined by the given points has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ WindingOrder(__v2t__ p0, __v2t__ p1, __v2t__ p2)\n            => (p1.X - p0.X) * (p2.Y - p0.Y) - (p2.X - p0.X) * (p1.Y - p0.Y);\n\n        /// <summary>\n        /// Returns a negative value if the given triangle has a\n        /// counter-clockwise winding order, and a positive value if it has a clockwise winding-order.\n        /// The magnitude is twice the area of the triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ WindingOrder(__type__ t)\n            => WindingOrder(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Gets the distance between the closest point on the triangle [a, b, c] and the given query point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Distance(__v2t__ a, __v2t__ b, __v2t__ c, __v2t__ query)\n        {\n            var cp = query.GetClosestPointOnTriangle(a, b, c);\n            return (cp - query).Length;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Triangle/Triangle3_auto.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Triangle3f\n\n    /// <summary>\n    /// A three-dimensional triangle represented by its three points.\n    /// </summary>\n    public partial struct Triangle3f : IBoundingSphere3f\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area of the triangle.\n        /// </summary>\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Area(this);\n        }\n\n        /// <summary>\n        /// Returns whether the triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.IsDegenerated(this);\n        }\n\n        /// <summary>\n        /// Returns the normal of the triangle.\n        /// </summary>\n        public readonly V3f Normal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Normal(this);\n        }\n\n        /// <summary>\n        /// Returns the plane that contains the points of the triangle.\n        /// </summary>\n        public readonly Plane3f Plane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Plane(this);\n        }\n\n        #endregion\n\n        #region IBoundingSphere3f Members\n\n        /// <summary>\n        /// Returns the bounding sphere of the triangle.\n        /// </summary>\n        public readonly Sphere3f BoundingSphere3f\n        {\n            get\n            {\n                var edge01 = Edge01;\n                var edge02 = Edge02;\n                float dot0101 = Vec.Dot(edge01, edge01);\n                float dot0102 = Vec.Dot(edge01, edge02);\n                float dot0202 = Vec.Dot(edge02, edge02);\n                float d = 2 * (dot0101 * dot0202 - dot0102 * dot0102);\n                if (d.Abs() <= 1e-5f) return Sphere3f.Invalid;\n                float s = (dot0101 * dot0202 - dot0202 * dot0102) / d;\n                float t = (dot0202 * dot0101 - dot0101 * dot0102) / d;\n                var p = P0;\n                var sph = new Sphere3f();\n                if (s <= 0)\n                    sph.Center = 0.5f * (P0 + P2);\n                else if (t <= 0)\n                    sph.Center = 0.5f * (P0 + P1);\n                else if (s + t >= 1)\n                {\n                    sph.Center = 0.5f * (P1 + P2);\n                    p = P1;\n                }\n                else\n                    sph.Center = P0 + s * edge01 + t * edge02;\n                sph.Radius = (sph.Center - p).Length;\n                return sph;\n            }\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods for triangles.\n    /// </summary>\n    public static partial class Triangle\n    {\n        #region Area\n\n        /// <summary>\n        /// Returns the area of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Area(V3f p0, V3f p1, V3f p2)\n            => (p1 - p0).Cross(p2 - p0).Length * 0.5f;\n\n        /// <summary>\n        /// Returns the area of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Area(Triangle3f t)\n            => Area(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region IsDegenerated\n\n        /// <summary>\n        /// Returns whether the triangle defined by the give points is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(V3f p0, V3f p1, V3f p2)\n            => (p1 - p0).Cross(p2 - p0).AllTiny;\n\n        /// <summary>\n        /// Returns whether the given triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(Triangle3f t)\n            => IsDegenerated(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Normal\n\n        /// <summary>\n        /// Returns the normal of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Normal(V3f p0, V3f p1, V3f p2)\n            => (p1 - p0).Cross(p2 - p0).Normalized;\n\n        /// <summary>\n        /// Returns the normal of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Normal(Triangle3f t)\n            => Normal(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Plane\n\n        /// <summary>\n        /// Returns the plane that contains the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3f Plane(V3f p0, V3f p1, V3f p2)\n            => new Plane3f(Normal(p0, p1, p2), p0);\n\n        /// <summary>\n        /// Returns the plane that contains the points of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3f Plane(Triangle3f t)\n            => Plane(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region SolidAngle\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float SolidAngle(Triangle3f t)\n            => SolidAngle(t.P0, t.P1, t.P2);\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the origin.\n        ///\n        /// Van Oosterom, A., and Strackee, J. (1983). \n        /// The solid angle of a plane triangle.\n        /// IEEE transactions on Biomedical Engineering, (2), 125-126.\n        /// \n        /// https://en.wikipedia.org/wiki/Solid_angle#Tetrahedron\n        /// </summary>\n        public static float SolidAngle(V3f va, V3f vb, V3f vc)\n        {\n            var ma = va.Length;\n            var mb = vb.Length;\n            var mc = vc.Length;\n\n            var numerator = Fun.Abs(Vec.Dot(va, (Vec.Cross(vb, vc))));\n\n            var denom = ma * mb * mc + Vec.Dot(va, vb) * mc + Vec.Dot(va, vc) * mb + Vec.Dot(vb, vc) * ma;\n\n            var halfSA = Fun.Atan2(numerator, denom);\n\n            return 2 * (halfSA >= 0 ? halfSA : halfSA + ConstantF.Pi);\n        }\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float SolidAngle(V3f va, V3f vb, V3f vc, V3f p)\n            => SolidAngle(va - p, vb - p, vc - p);\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float SolidAngle(Triangle3f t, V3f p)\n            => SolidAngle(t.P0 - p, t.P1 - p, t.P2 - p);\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Gets the distance between the closest point on the triangle [a, b, c] and the given query point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(V3f a, V3f b, V3f c, V3f query)\n        {\n            var cp = query.GetClosestPointOnTriangle(a, b, c);\n            return (cp - query).Length;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Triangle3d\n\n    /// <summary>\n    /// A three-dimensional triangle represented by its three points.\n    /// </summary>\n    public partial struct Triangle3d : IBoundingSphere3d\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area of the triangle.\n        /// </summary>\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Area(this);\n        }\n\n        /// <summary>\n        /// Returns whether the triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.IsDegenerated(this);\n        }\n\n        /// <summary>\n        /// Returns the normal of the triangle.\n        /// </summary>\n        public readonly V3d Normal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Normal(this);\n        }\n\n        /// <summary>\n        /// Returns the plane that contains the points of the triangle.\n        /// </summary>\n        public readonly Plane3d Plane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Plane(this);\n        }\n\n        #endregion\n\n        #region IBoundingSphere3d Members\n\n        /// <summary>\n        /// Returns the bounding sphere of the triangle.\n        /// </summary>\n        public readonly Sphere3d BoundingSphere3d\n        {\n            get\n            {\n                var edge01 = Edge01;\n                var edge02 = Edge02;\n                double dot0101 = Vec.Dot(edge01, edge01);\n                double dot0102 = Vec.Dot(edge01, edge02);\n                double dot0202 = Vec.Dot(edge02, edge02);\n                double d = 2 * (dot0101 * dot0202 - dot0102 * dot0102);\n                if (d.Abs() <= 1e-9) return Sphere3d.Invalid;\n                double s = (dot0101 * dot0202 - dot0202 * dot0102) / d;\n                double t = (dot0202 * dot0101 - dot0101 * dot0102) / d;\n                var p = P0;\n                var sph = new Sphere3d();\n                if (s <= 0)\n                    sph.Center = 0.5 * (P0 + P2);\n                else if (t <= 0)\n                    sph.Center = 0.5 * (P0 + P1);\n                else if (s + t >= 1)\n                {\n                    sph.Center = 0.5 * (P1 + P2);\n                    p = P1;\n                }\n                else\n                    sph.Center = P0 + s * edge01 + t * edge02;\n                sph.Radius = (sph.Center - p).Length;\n                return sph;\n            }\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods for triangles.\n    /// </summary>\n    public static partial class Triangle\n    {\n        #region Area\n\n        /// <summary>\n        /// Returns the area of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Area(V3d p0, V3d p1, V3d p2)\n            => (p1 - p0).Cross(p2 - p0).Length * 0.5;\n\n        /// <summary>\n        /// Returns the area of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Area(Triangle3d t)\n            => Area(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region IsDegenerated\n\n        /// <summary>\n        /// Returns whether the triangle defined by the give points is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(V3d p0, V3d p1, V3d p2)\n            => (p1 - p0).Cross(p2 - p0).AllTiny;\n\n        /// <summary>\n        /// Returns whether the given triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(Triangle3d t)\n            => IsDegenerated(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Normal\n\n        /// <summary>\n        /// Returns the normal of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Normal(V3d p0, V3d p1, V3d p2)\n            => (p1 - p0).Cross(p2 - p0).Normalized;\n\n        /// <summary>\n        /// Returns the normal of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Normal(Triangle3d t)\n            => Normal(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Plane\n\n        /// <summary>\n        /// Returns the plane that contains the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3d Plane(V3d p0, V3d p1, V3d p2)\n            => new Plane3d(Normal(p0, p1, p2), p0);\n\n        /// <summary>\n        /// Returns the plane that contains the points of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Plane3d Plane(Triangle3d t)\n            => Plane(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region SolidAngle\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double SolidAngle(Triangle3d t)\n            => SolidAngle(t.P0, t.P1, t.P2);\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the origin.\n        ///\n        /// Van Oosterom, A., and Strackee, J. (1983). \n        /// The solid angle of a plane triangle.\n        /// IEEE transactions on Biomedical Engineering, (2), 125-126.\n        /// \n        /// https://en.wikipedia.org/wiki/Solid_angle#Tetrahedron\n        /// </summary>\n        public static double SolidAngle(V3d va, V3d vb, V3d vc)\n        {\n            var ma = va.Length;\n            var mb = vb.Length;\n            var mc = vc.Length;\n\n            var numerator = Fun.Abs(Vec.Dot(va, (Vec.Cross(vb, vc))));\n\n            var denom = ma * mb * mc + Vec.Dot(va, vb) * mc + Vec.Dot(va, vc) * mb + Vec.Dot(vb, vc) * ma;\n\n            var halfSA = Fun.Atan2(numerator, denom);\n\n            return 2 * (halfSA >= 0 ? halfSA : halfSA + Constant.Pi);\n        }\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double SolidAngle(V3d va, V3d vb, V3d vc, V3d p)\n            => SolidAngle(va - p, vb - p, vc - p);\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double SolidAngle(Triangle3d t, V3d p)\n            => SolidAngle(t.P0 - p, t.P1 - p, t.P2 - p);\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Gets the distance between the closest point on the triangle [a, b, c] and the given query point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(V3d a, V3d b, V3d c, V3d query)\n        {\n            var cp = query.GetClosestPointOnTriangle(a, b, c);\n            return (cp - query).Length;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Geometry/Types/Triangle/Triangle3_template.cs",
    "content": "using System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Triangle3\" + tc;\n    //#   var type2 = \"Triangle3\" + tc2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var box3t = \"Box3\" + tc;\n    //#   var plane3t = \"Plane3\" + tc;\n    //#   var sphere3t = \"Sphere3\" + tc;\n    //#   var iboundingsphere3t = \"IBoundingSphere3\" + tc;\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#   var eps = isDouble ? \"1e-9\" : \"1e-5f\";\n    #region __type__\n\n    /// <summary>\n    /// A three-dimensional triangle represented by its three points.\n    /// </summary>\n    public partial struct __type__ : __iboundingsphere3t__\n    {\n        #region Geometric Properties\n\n        /// <summary>\n        /// Returns the area of the triangle.\n        /// </summary>\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Area(this);\n        }\n\n        /// <summary>\n        /// Returns whether the triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        public readonly bool IsDegenerated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.IsDegenerated(this);\n        }\n\n        /// <summary>\n        /// Returns the normal of the triangle.\n        /// </summary>\n        public readonly __v3t__ Normal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Normal(this);\n        }\n\n        /// <summary>\n        /// Returns the plane that contains the points of the triangle.\n        /// </summary>\n        public readonly __plane3t__ Plane\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Triangle.Plane(this);\n        }\n\n        #endregion\n\n        #region __iboundingsphere3t__ Members\n\n        /// <summary>\n        /// Returns the bounding sphere of the triangle.\n        /// </summary>\n        public readonly __sphere3t__ BoundingSphere3__tc__\n        {\n            get\n            {\n                var edge01 = Edge01;\n                var edge02 = Edge02;\n                __ftype__ dot0101 = Vec.Dot(edge01, edge01);\n                __ftype__ dot0102 = Vec.Dot(edge01, edge02);\n                __ftype__ dot0202 = Vec.Dot(edge02, edge02);\n                __ftype__ d = 2 * (dot0101 * dot0202 - dot0102 * dot0102);\n                if (d.Abs() <= __eps__) return __sphere3t__.Invalid;\n                __ftype__ s = (dot0101 * dot0202 - dot0202 * dot0102) / d;\n                __ftype__ t = (dot0202 * dot0101 - dot0101 * dot0102) / d;\n                var p = P0;\n                var sph = new __sphere3t__();\n                if (s <= 0)\n                    sph.Center = __half__ * (P0 + P2);\n                else if (t <= 0)\n                    sph.Center = __half__ * (P0 + P1);\n                else if (s + t >= 1)\n                {\n                    sph.Center = __half__ * (P1 + P2);\n                    p = P1;\n                }\n                else\n                    sph.Center = P0 + s * edge01 + t * edge02;\n                sph.Radius = (sph.Center - p).Length;\n                return sph;\n            }\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods for triangles.\n    /// </summary>\n    public static partial class Triangle\n    {\n        #region Area\n\n        /// <summary>\n        /// Returns the area of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Area(__v3t__ p0, __v3t__ p1, __v3t__ p2)\n            => (p1 - p0).Cross(p2 - p0).Length * __half__;\n\n        /// <summary>\n        /// Returns the area of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Area(__type__ t)\n            => Area(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region IsDegenerated\n\n        /// <summary>\n        /// Returns whether the triangle defined by the give points is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(__v3t__ p0, __v3t__ p1, __v3t__ p2)\n            => (p1 - p0).Cross(p2 - p0).AllTiny;\n\n        /// <summary>\n        /// Returns whether the given triangle is degenerated, i.e. its area is zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsDegenerated(__type__ t)\n            => IsDegenerated(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Normal\n\n        /// <summary>\n        /// Returns the normal of the triangle defined by the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ Normal(__v3t__ p0, __v3t__ p1, __v3t__ p2)\n            => (p1 - p0).Cross(p2 - p0).Normalized;\n\n        /// <summary>\n        /// Returns the normal of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ Normal(__type__ t)\n            => Normal(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region Plane\n\n        /// <summary>\n        /// Returns the plane that contains the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __plane3t__ Plane(__v3t__ p0, __v3t__ p1, __v3t__ p2)\n            => new __plane3t__(Normal(p0, p1, p2), p0);\n\n        /// <summary>\n        /// Returns the plane that contains the points of the given triangle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __plane3t__ Plane(__type__ t)\n            => Plane(t.P0, t.P1, t.P2);\n\n        #endregion\n\n        #region SolidAngle\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the origin.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ SolidAngle(__type__ t)\n            => SolidAngle(t.P0, t.P1, t.P2);\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the origin.\n        ///\n        /// Van Oosterom, A., and Strackee, J. (1983). \n        /// The solid angle of a plane triangle.\n        /// IEEE transactions on Biomedical Engineering, (2), 125-126.\n        /// \n        /// https://en.wikipedia.org/wiki/Solid_angle#Tetrahedron\n        /// </summary>\n        public static __ftype__ SolidAngle(__v3t__ va, __v3t__ vb, __v3t__ vc)\n        {\n            var ma = va.Length;\n            var mb = vb.Length;\n            var mc = vc.Length;\n\n            var numerator = Fun.Abs(Vec.Dot(va, (Vec.Cross(vb, vc))));\n\n            var denom = ma * mb * mc + Vec.Dot(va, vb) * mc + Vec.Dot(va, vc) * mb + Vec.Dot(vb, vc) * ma;\n\n            var halfSA = Fun.Atan2(numerator, denom);\n\n            return 2 * (halfSA >= 0 ? halfSA : halfSA + __pi__);\n        }\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ SolidAngle(__v3t__ va, __v3t__ vb, __v3t__ vc, __v3t__ p)\n            => SolidAngle(va - p, vb - p, vc - p);\n\n        /// <summary>\n        /// Computes the solid angle for a planar triangle as seen from the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ SolidAngle(__type__ t, __v3t__ p)\n            => SolidAngle(t.P0 - p, t.P1 - p, t.P2 - p);\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Gets the distance between the closest point on the triangle [a, b, c] and the given query point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Distance(__v3t__ a, __v3t__ b, __v3t__ c, __v3t__ query)\n        {\n            var cp = query.GetClosestPointOnTriangle(a, b, c);\n            return (cp - query).Length;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Hashing/HashCode.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public static class HashCode\n    {\n        /*\n            Permission is hereby granted, free of charge, to any person or organization\n            obtaining a copy of the software and accompanying documentation covered by\n            this license (the \"Software\") to use, reproduce, display, distribute,\n            execute, and transmit the Software, and to prepare derivative works of the\n            Software, and to permit third-parties to whom the Software is furnished to\n            do so, all subject to the following:\n\n            The copyright notices in the Software and this entire statement, including\n            the above license grant, this restriction and the following disclaimer,\n            must be included in all copies of the Software, in whole or in part, and\n            all derivative works of the Software, unless such copies or derivative\n            works are solely in the form of machine-executable object code generated by\n            a source language processor.\n\n            THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n            FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n            SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n            FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n            ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n            DEALINGS IN THE SOFTWARE.\n        */\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint UCombine(int a, int b)\n            => (uint)a ^ (uint)b + 0x9e3779b9 + ((uint)a << 6) + ((uint)a >> 2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint UCombine(uint a, int b)\n            => a ^ (uint)b + 0x9e3779b9 + (a << 6) + (a >> 2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint UCombine(int a, uint b)\n            => (uint)a ^ (uint)b + 0x9e3779b9 + ((uint)a << 6) + ((uint)a >> 2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint UCombine(uint a, uint b)\n            => a ^ b + 0x9e3779b9 + (a << 6) + (a >> 2);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(uint a, uint b)\n            => (int)(a ^ b + 0x9e3779b9 + (a << 6) + (a >> 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, uint b)\n            => (int)((uint)a ^ b + 0x9e3779b9 + ((uint)a << 6) + ((uint)a >> 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(uint a, int b)\n            => (int)(a ^ (uint)b + 0x9e3779b9 + (a << 6) + (a >> 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, int b)\n            => (int)((uint)a ^ (uint)b + 0x9e3779b9 + ((uint)a << 6) + ((uint)a >> 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(long a, int b)\n            => Combine(UCombine((int)(a >> 32), (int)a), b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, long b)\n            => Combine(a, UCombine((int)(b >> 32), (int)b));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(long a, long b)\n            => Combine(UCombine((int)(a >> 32), (int)a),\n                       UCombine((int)(b >> 32), (int)b));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, int b, int c)\n        {\n            return Combine(UCombine(a, b), c);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, int b, int c, int d)\n        {\n            return Combine(UCombine(UCombine(a, b), c), d);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, int b, int c, int d, int e)\n        {\n            return Combine(UCombine(UCombine(UCombine(a, b), c), d), e);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, int b, int c, int d, int e, int f)\n        {\n            return Combine(UCombine(UCombine(UCombine(UCombine(a, b), c), d), e), f);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, int b, int c, int d, int e, int f, int g)\n        {\n            return Combine(UCombine(UCombine(UCombine(UCombine(UCombine(a, b), c), d), e), f), g);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, int b, int c, int d, int e, int f, int g, int h)\n        {\n            return Combine(UCombine(UCombine(UCombine(UCombine(UCombine(UCombine(a, b), c), d), e), f), g), h);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Combine(int a, int b, params int[] rest)\n        {\n            uint h = UCombine(a, b);\n            foreach (var i in rest) h = UCombine(h, i);\n            return (int)h;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombined<T0, T1>(T0 e0, T1 e1)\n            where T0 : struct\n            where T1 : struct\n            => Combine(e0.GetHashCode(), e1.GetHashCode());\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombined<T0, T1, T2>(T0 e0, T1 e1, T2 e2)\n            where T0 : struct\n            where T1 : struct\n            where T2 : struct\n            => Combine(UCombine(e0.GetHashCode(), e1.GetHashCode()), e2.GetHashCode());\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombined<T0, T1, T2, T3>(T0 e0, T1 e1, T2 e2, T3 e3)\n            where T0 : struct\n            where T1 : struct\n            where T2 : struct\n            where T3 : struct\n            => Combine(UCombine(UCombine(e0.GetHashCode(), e1.GetHashCode()), e2.GetHashCode()), e3.GetHashCode());\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombined<T0, T1, T2, T3, T4>(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n            where T0 : struct\n            where T1 : struct\n            where T2 : struct\n            where T3 : struct\n            where T4 : struct\n            => Combine(UCombine(UCombine(UCombine(e0.GetHashCode(),\n                e1.GetHashCode()), e2.GetHashCode()), e3.GetHashCode()), e4.GetHashCode());\n\n        /// <summary>\n        /// Compute the combined hash code of an IEnumerable of items.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombinedHashCode<T>(this IEnumerable<T> items)\n            where T : struct\n            => (int)items.Aggregate(0U, (h, i) => UCombine(h, i.GetHashCode()));\n\n        /// <summary>\n        /// Compute the combined hash code of an array of items (explicit\n        /// implementation in order to be faster than IEnumerable version).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombinedHashCode<T>(this T[] array)\n            where T : struct\n            => array.GetCombinedHashCode(array.LongLength);\n\n        /// <summary>\n        /// Compute the combined hash code of an array of items (explicit\n        /// implementation in order to be faster than IEnumerable version).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombinedHashCode<T>(this T[] array, long count)\n            where T : struct\n        {\n            if (count == 0) return 0;\n            var h = (uint)array[0].GetHashCode();\n            for (var i = 1; i < count; i++)\n                h = UCombine(h, array[i].GetHashCode());\n            return (int)h;\n        }\n\n        /// <summary>\n        /// Compute the combined hash code of an array of items (explicit\n        /// implementation in order to be faster than IEnumerable version).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombinedHashCode<T>(this T[] array, long first, long count)\n            where T : struct\n        {\n            if (count == 0) return 0;\n            var h = (uint)array[first].GetHashCode();\n            for (long i = first + 1, e = first + count; i < e; i++)\n                h = UCombine(h, array[i].GetHashCode());\n            return (int)h;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombinedWithDefaultZero<T0, T1>(T0 e0, T1 e1)\n            => Combine(e0.Equals(default(T0)) ? 0 : e0.GetHashCode(),\n                       e1.Equals(default(T1)) ? 0 : e1.GetHashCode());\n        \n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombinedWithDefaultZero<T0, T1, T2>(T0 e0, T1 e1, T2 e2)\n            => Combine(UCombine(e0.Equals(default(T0)) ? 0 : e0.GetHashCode(),\n                                e1.Equals(default(T1)) ? 0 : e1.GetHashCode()),\n                                e2.Equals(default(T2)) ? 0 : e2.GetHashCode());\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GetCombinedWithDefaultZero<T0, T1, T2, T3>(T0 e0, T1 e1, T2 e2, T3 e3)\n            => Combine(UCombine(UCombine(e0.Equals(default(T0)) ? 0 : e0.GetHashCode(),\n                                         e1.Equals(default(T1)) ? 0 : e1.GetHashCode()),\n                                         e2.Equals(default(T2)) ? 0 : e2.GetHashCode()),\n                                         e3.Equals(default(T3)) ? 0 : e3.GetHashCode());\n\n        /// <summary>\n        /// Compute the first of two possible hashcodes for hashing in a 1-D\n        /// unit grid. Add items with this function, retrieve with function\n        /// HashCode.Get2.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Get1of2(double x)\n        {\n            var xi = (long)Floor(x);\n            return (int)(xi >> 1);\n        }\n\n        /// <summary>\n        /// Compute all two possible hashcodes for hashing in a 1-D unit grid.\n        /// Retrive all items with the two hashodes written into the supplied\n        /// array. Items need to be added just with the first of the two\n        /// hashcodes (also computed by function HashCodeGet1of2).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Get2(double x, int[] hca)\n        {\n            var xi = (long)Floor(x);\n\n            int xh0 = (int)(xi >> 1);\n\n            hca[0] = xh0;\n            hca[1] = xh0 - 1 + ((int)(xi & 1) << 1);\n        }\n\n        /// <summary>\n        /// Compute the first of four possible hashcodes for hashing in a 2-D\n        /// unit grid. Add items with this function, retrieve with function\n        /// HashCode.Get4.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Get1of4(double x, double y)\n        {\n            var xi = (long)Floor(x);\n            var yi = (long)Floor(y);\n\n            return Combine((int)(xi >> 1), (int)(yi >> 1));\n        }\n\n        /// <summary>\n        /// Compute all four possible hashcodes for hashing in a 2-D unit grid.\n        /// Retrive all items with the four hashodes written into the supplied\n        /// array. Items need to be added just with the first of the four\n        /// hashcodes (also computed by function HashCodeGet1of4).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Get4(double x, double y, int[] hca)\n        {\n            var xi = (long)Floor(x);\n            var yi = (long)Floor(y);\n\n            int xh0 = (int)(xi >> 1), xh1 = xh0 - 1 + ((int)(xi & 1) << 1);\n            int yh0 = (int)(yi >> 1), yh1 = yh0 - 1 + ((int)(yi & 1) << 1);\n\n            hca[0] = Combine(xh0, yh0);\n            hca[1] = Combine(xh1, yh0);\n            hca[2] = Combine(xh0, yh1);\n            hca[3] = Combine(xh1, yh1);\n        }\n\n        /// <summary>\n        /// Compute the first of eight possible hashcodes for hashing in a 3-D\n        /// unit grid. Add items with this function, retrieve with function\n        /// HashCode.Get8.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Get1of8(double x, double y, double z)\n        {\n            var xi = (long)Floor(x);\n            var yi = (long)Floor(y);\n            var zi = (long)Floor(z);\n\n            return Combine((int)(xi >> 1), (int)(yi >> 1), (int)(zi >> 1));\n        }\n\n        /// <summary>\n        /// Compute all eight possible hashcodes for hashing in a 3-D unit grid.\n        /// Retrive all items with the eight hashodes written into the supplied\n        /// array. Items need to be added just with the first of the eight\n        /// hashcodes (also computed by function HashCodeGet1of2).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Get8(double x, double y, double z, int[] hca)\n        {\n            var xi = (long)Floor(x);\n            var yi = (long)Floor(y);\n            var zi = (long)Floor(z);\n\n            int xh0 = (int)(xi >> 1), xh1 = xh0 - 1 + ((int)(xi & 1) << 1);\n            int yh0 = (int)(yi >> 1), yh1 = yh0 - 1 + ((int)(yi & 1) << 1);\n            int zh0 = (int)(zi >> 1), zh1 = zh0 - 1 + ((int)(zi & 1) << 1);\n\n            hca[0] = Combine(xh0, yh0, zh0);\n            hca[1] = Combine(xh1, yh0, zh0);\n            hca[2] = Combine(xh0, yh1, zh0);\n            hca[3] = Combine(xh1, yh1, zh0);\n            hca[4] = Combine(xh0, yh0, zh1);\n            hca[5] = Combine(xh1, yh0, zh1);\n            hca[6] = Combine(xh0, yh1, zh1);\n            hca[7] = Combine(xh1, yh1, zh1);\n        }\n\n        /// <summary>\n        /// Compute the first of 16 possible hashcodes for hashing in a 4-D\n        /// unit grid. Add items with this function, retrieve with function\n        /// HashCode.Get16.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Get1of16(double x, double y, double z, double w)\n        {\n            var xi = (long)Floor(x);\n            var yi = (long)Floor(y);\n            var zi = (long)Floor(z);\n            var wi = (long)Floor(w);\n\n            return Combine((int)(xi >> 1), (int)(yi >> 1), (int)(zi >> 1), (int)(wi >> 1));\n        }\n\n        /// <summary>\n        /// Compute all 16 possible hashcodes for hashing in a 4-D unit grid.\n        /// Retrive all items with the 16 hashodes written into the supplied\n        /// array. Items need to be added just with the first of the 16\n        /// hashcodes (also computed by function HashCodeGet1of16).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Get16(double x, double y, double z, double w, int[] hca)\n        {\n            var xi = (long)Floor(x);\n            var yi = (long)Floor(y);\n            var zi = (long)Floor(z);\n            var wi = (long)Floor(w);\n\n            int xh0 = (int)(xi >> 1), xh1 = xh0 - 1 + ((int)(xi & 1) << 1);\n            int yh0 = (int)(yi >> 1), yh1 = yh0 - 1 + ((int)(yi & 1) << 1);\n            int zh0 = (int)(zi >> 1), zh1 = zh0 - 1 + ((int)(zi & 1) << 1);\n            int dh0 = (int)(wi >> 1), dh1 = dh0 - 1 + ((int)(wi & 1) << 1);\n\n            hca[0] = Combine(xh0, yh0, zh0, dh0);\n            hca[1] = Combine(xh1, yh0, zh0, dh0);\n            hca[2] = Combine(xh0, yh1, zh0, dh0);\n            hca[3] = Combine(xh1, yh1, zh0, dh0);\n            hca[4] = Combine(xh0, yh0, zh1, dh0);\n            hca[5] = Combine(xh1, yh0, zh1, dh0);\n            hca[6] = Combine(xh0, yh1, zh1, dh0);\n            hca[7] = Combine(xh1, yh1, zh1, dh0);\n            hca[8] = Combine(xh0, yh0, zh0, dh1);\n            hca[9] = Combine(xh1, yh0, zh0, dh1);\n            hca[10] = Combine(xh0, yh1, zh0, dh1);\n            hca[11] = Combine(xh1, yh1, zh0, dh1);\n            hca[12] = Combine(xh0, yh0, zh1, dh1);\n            hca[13] = Combine(xh1, yh0, zh1, dh1);\n            hca[14] = Combine(xh0, yh1, zh1, dh1);\n            hca[15] = Combine(xh1, yh1, zh1, dh1);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Introspection/Aardvark.cs",
    "content": "namespace Aardvark.Base;\n\nusing System;\nusing System.IO;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\n\n#if NET8_0_OR_GREATER\nusing System.Runtime.Loader;\n#endif\n\n// TODO: static class\n[Serializable]\npublic partial class Aardvark\n{\n    [Obsolete(\"Use static methods instead.\")]\n    public Aardvark()\n    {\n    }\n\n    private enum OS\n    {\n        Unknown = 0,\n        Win32 = 1,\n        Linux = 2,\n        MacOS = 3\n    }\n\n    private static bool TryParseOS(string os, out OS value)\n    {\n        value =\n            os?.ToLower() switch\n            {\n                \"win\" or \"win32\" or \"win64\" or \"windows\" => OS.Win32,\n                \"linux\" or \"nix\" or \"unix\"               => OS.Linux,\n                \"mac\" or \"macos\" or \"macosx\"             => OS.MacOS,\n                _ => OS.Unknown\n            };\n\n        return value != OS.Unknown;\n    }\n\n    private static OS GetOS()\n    {\n        return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? OS.Win32 :\n               RuntimeInformation.IsOSPlatform(OSPlatform.OSX)     ? OS.MacOS :\n               RuntimeInformation.IsOSPlatform(OSPlatform.Linux)   ? OS.Linux :\n               OS.Unknown;\n    }\n\n    /// <summary>\n    /// Gets the current operating system platform as an <see cref=\"OSPlatform\"/> value.\n    /// </summary>\n    /// <remarks>\n    /// The method checks <see cref=\"System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform)\"/>\n    /// and returns one of <see cref=\"OSPlatform.Windows\"/>, <see cref=\"OSPlatform.OSX\"/>, or <see cref=\"OSPlatform.Linux\"/>.\n    /// If none of these are detected, an <see cref=\"OSPlatform\"/> with the name \"UNKNOWN\" is returned via\n    /// <see cref=\"OSPlatform.Create(string)\"/>. This can happen on unsupported or future platforms.\n    /// </remarks>\n    /// <returns>\n    /// The current platform descriptor.\n    /// </returns>\n    public static OSPlatform GetOSPlatform()\n    {\n        return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? OSPlatform.Windows :\n               RuntimeInformation.IsOSPlatform(OSPlatform.OSX)     ? OSPlatform.OSX :\n               RuntimeInformation.IsOSPlatform(OSPlatform.Linux)   ? OSPlatform.Linux :\n               OSPlatform.Create(\"UNKNOWN\");\n    }\n\n    private static bool isInitialized;\n\n    public static void Init()\n    {\n        if (isInitialized) return;\n\n        Report.BeginTimed(\"Initializing Aardvark\");\n\n        const string framework =\n#if NET8_0\n            \".NET 8.0\";\n#elif NETSTANDARD2_0\n            \".NET Standard 2.0\";\n#endif\n\n        Report.Begin(\"System Information:\");\n        Report.Line(\"System:      {0}\", RuntimeInformation.OSDescription);\n        Report.Line(\"Processor:   {0} core {1}\", Environment.ProcessorCount, ArchitectureString(RuntimeInformation.OSArchitecture));\n        Report.Line(\"Process:     {0}\", ArchitectureString(RuntimeInformation.ProcessArchitecture));\n        Report.Line(\"Runtime:     {0}\", RuntimeInformation.FrameworkDescription);\n        Report.Line(\"Framework:   {0}\", framework);\n\n        if (RuntimeInformation.ProcessArchitecture != Architecture.X64)\n        {\n            Report.Error(\"{0} is not officially supported yet: some features may not work correctly\", ArchitectureString(RuntimeInformation.ProcessArchitecture));\n        }\n\n        Report.End();\n\n#if NETCOREAPP3_1_OR_GREATER\n        // Assembly loading via name fails if the assembly is not referenced as runtime or compile library.\n        // This happens when a plugin is not referenced but simply dropped next to the entry assembly (e.g. multiple projects share the same output folder).\n        // Here we just try to locate the assembly next to the entry path.\n        // See: https://github.com/Particular/Workshop/issues/64\n        AssemblyLoadContext.Default.Resolving += (ctx, name) =>\n        {\n            Report.Begin(4, $\"Trying to resolve assembly: {name.FullName}\");\n\n            try\n            {\n                var path = Path.Combine(IntrospectionProperties.CurrentEntryPath, name.Name + \".dll\");\n\n                if (File.Exists(path))\n                {\n                    var asm = ctx.LoadFromAssemblyPath(path);\n                    Report.End(4, $\" - success: {path}\");\n                    return asm;\n                }\n\n                Report.End(4, $\" - not found\");\n                return null;\n            }\n            catch (Exception e)\n            {\n                Report.End(4, $\" - failed: {e}\");\n                return null;\n            }\n        };\n\n        // Called whenever a native library cannot be resolved by the managed runtime.\n        // Note that this is only called for native libraries that are loaded from managed code.\n        // Dependencies of native libraries are resolved using the dynamic linker of the platform.\n        // On Linux, this can be problematic if an assembly has native dependencies consisting of\n        // multiple libraries (e.g., liba and libb will be unpacked to the same directory, where liba requires libb).\n        // In this case the libraries must be built with rpath set to $ORIGIN so that libb can be found next to liba.\n        AssemblyLoadContext.Default.ResolvingUnmanagedDll += (assembly, name) =>\n        {\n            Report.Begin(4, $\"Resolving native library '{name}'\");\n            var ptr = LoadLibrary(assembly, name, global: false, resolving: true);\n            Report.End(4);\n            return ptr;\n        };\n#endif\n        // Set error mode to SEM_FAILCRITICALERRORS:\n        // The system does not display the critical-error-handler message box.\n        // Instead, the system sends the error to the calling process.\n        if (GetOS() == OS.Win32) Kernel32.SetErrorMode(Kernel32.SEM_FAILCRITICALERRORS);\n\n        if (IntrospectionProperties.NativeLibraryUnpackingAllowed)\n        {\n            AppDomain.CurrentDomain.AssemblyLoad += (_, args) =>\n            {\n                LoadNativeDependencies(args.LoadedAssembly);\n            };\n\n            Report.BeginTimed(\"Loading native dependencies\");\n\n            foreach (var assmebly in AppDomain.CurrentDomain.GetAssemblies())\n            {\n                LoadNativeDependencies(assmebly);\n            }\n\n            Report.EndTimed();\n        }\n        else\n        {\n            Report.Line(4, \"Skipping native dependency loading since NativeLibraryUnpackingAllowed = false\");\n        }\n\n        if (IntrospectionProperties.PluginsEnabled)\n        {\n            Plugins.Init();\n        }\n        else\n        {\n            Report.Line(4, \"Skipping plugin loading since PluginsEnabled = false\");\n        }\n\n        Report.End();\n\n        isInitialized = true;\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Introspection/CachingProperties.cs",
    "content": "namespace Aardvark.Base;\n\nusing System;\nusing System.IO;\nusing System.Reflection;\n\npublic static class CachingProperties\n    {\n        /// <summary>\n        /// Naming schemes for cache files.\n        /// </summary>\n        public enum NamingScheme\n        {\n            /// <summary>\n            /// Name is based on the version of the assembly.\n            /// </summary>\n            Version,\n\n            /// <summary>\n            /// Name is based on the modification time of the assembly file.\n            /// </summary>\n            Timestamp\n        }\n\n        private static readonly Lazy<string> s_cacheDirectory = new(() =>\n        {\n            var path = CustomCacheDirectory;\n            if (string.IsNullOrWhiteSpace(path))\n            {\n                path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);\n                if (string.IsNullOrWhiteSpace(path))\n                {\n                    Report.Warn(\"Environment.SpecialFolder.LocalApplicationData does not exist!\");\n                    path = \"Cache\"; // using ./Cache\n                }\n                else\n                {\n                    path = Path.Combine(path, \"Aardvark\", \"Cache\");\n                }\n            }\n\n            Report.Line(4, $\"Cache directory: {path}\");\n\n            if (!Directory.Exists(path))\n            {\n                Directory.CreateDirectory(path);\n            }\n\n            return path;\n        });\n\n        /// <summary>\n        /// If set, determines the directory holding cache files. Otherwise, a default directory is used.\n        /// Must be set before <see cref=\"CacheDirectory\"/> is used.\n        /// </summary>\n        public static string CustomCacheDirectory { get; set; }\n\n        /// <summary>\n        /// Directory holding cache files, if <see cref=\"CustomCacheDirectory\"/> is not set, a default directory based on\n        /// <see cref=\"Environment.SpecialFolder.ApplicationData\"/> will be used instead.\n        /// </summary>\n        public static string CacheDirectory => s_cacheDirectory.Value;\n\n        /// <summary>\n        /// Gets or sets the naming scheme used for plugins cache files.\n        /// Default scheme is based on assembly version.\n        /// </summary>\n        public static NamingScheme PluginsCacheFileNaming { get; set; } = NamingScheme.Version;\n\n        /// <summary>\n        /// Gets or sets the naming scheme used for introspection cache files.\n        /// Default scheme is based on assembly version.\n        /// </summary>\n        public static NamingScheme IntrospectionCacheFileNaming { get; set; } = NamingScheme.Version;\n\n        internal static string GetIdentifier(this Assembly asm, NamingScheme scheme)\n        {\n            return scheme switch\n            {\n                NamingScheme.Version =>   asm.GetName()?.Version?.ToString() ?? \"0.0.0.0\",\n                NamingScheme.Timestamp => asm.GetLastWriteTimeSafe().ToBinary().ToString(),\n                _ => \"\"\n            };\n        }\n    }"
  },
  {
    "path": "src/Aardvark.Base/Introspection/Introspection.cs",
    "content": "﻿namespace Aardvark.Base;\r\n\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Diagnostics;\r\nusing System.Globalization;\r\nusing System.IO;\r\nusing System.Linq;\r\nusing System.Reflection;\r\n\r\npublic static class Introspection\r\n{\r\n    private static readonly CultureInfo s_cultureInfoEnUs = new(\"en-us\");\r\n    private static readonly Dictionary<string, Assembly> s_assemblies;\r\n    private static readonly HashSet<string> s_assembliesThatFailedToLoad = [];\r\n    private static readonly HashSet<Assembly> s_allAssemblies = [];\r\n\r\n    private static string InitializeCacheDirectory()\r\n    {\r\n        var path = Path.Combine(CachingProperties.CacheDirectory, \"Introspection\");\r\n\r\n        if (!Directory.Exists(path))\r\n        {\r\n            Directory.CreateDirectory(path);\r\n        }\r\n\r\n        return path;\r\n    }\r\n\r\n    private static readonly Lazy<string> s_cacheDirectory = new(InitializeCacheDirectory);\r\n\r\n    /// <summary>\r\n    /// Returns the directory of the introspection cache files.\r\n    /// </summary>\r\n    public static string CacheDirectory => s_cacheDirectory.Value;\r\n\r\n    /// <summary>\r\n    /// Registers an additional assembly at runtime to be\r\n    /// used for subsequent introspection queries. This\r\n    /// may be used for e.g. plugin scenarios.\r\n    /// All assemblies that are reachable from the entry\r\n    /// assembly are registered automatically at startup.\r\n    /// </summary>\r\n    public static void RegisterAssembly(Assembly assembly)\r\n    {\r\n        if (assembly != null) s_allAssemblies.Add(assembly);\r\n    }\r\n\r\n    /// <summary>\r\n    /// Enumerates all known assemblies.\r\n    /// </summary>\r\n    public static IEnumerable<Assembly> AllAssemblies => s_allAssemblies;\r\n\r\n    /// <summary>\r\n    /// Enumerates all classes implementing the specified interface.\r\n    /// </summary>\r\n    public static IEnumerable<Type> GetAllClassesImplementingInterface(Type interfaceType)\r\n        => AllAssemblies.SelectMany(a => GetAllClassesImplementingInterface(a, interfaceType));\r\n\r\n    /// <summary>\r\n    /// Enumerates all classes inheriting from the specified base class.\r\n    /// </summary>\r\n    public static IEnumerable<Type> GetAllClassesInheritingFrom(Type baseType)\r\n        => AllAssemblies.SelectMany(a => GetAllClassesInheritingFrom(a, baseType));\r\n\r\n    /// <summary>\r\n    /// Enumerates all types decorated with attribute T as tuples of type\r\n    /// and its one or more T-attributes.\r\n    /// </summary>\r\n    public static IEnumerable<(Type, T[])> GetAllTypesWithAttribute<T>()\r\n        => AllAssemblies.SelectMany(GetAllTypesWithAttribute<T>);\r\n\r\n    /// <summary>\r\n    /// Enumerates all methods decorated with attribute T as tuples of MethodInfo\r\n    /// and its one or more T-attributes.\r\n    /// </summary>\r\n    public static IEnumerable<(MethodInfo, T[])> GetAllMethodsWithAttribute<T>()\r\n        => AllAssemblies.SelectMany(GetAllMethodsWithAttribute<T>);\r\n\r\n    /// <summary>\r\n    /// Enumerates all classes from the specified assembly\r\n    /// implementing the specified interface.\r\n    /// </summary>\r\n    public static Type[] GetAllClassesImplementingInterface(Assembly assembly, Type interfaceType)\r\n        => GetAll___(assembly, interfaceType.FullName,\r\n            lines => lines.Select(Type.GetType),\r\n            types => types.Where(t => (t.IsClass || t.IsValueType) && t.GetInterfaces().Contains(interfaceType)),\r\n            result => result.Select(t => t.AssemblyQualifiedName)\r\n        );\r\n\r\n    /// <summary>\r\n    /// Enumerates all classes from the specified assembly\r\n    /// inheriting from the specified base class.\r\n    /// </summary>\r\n    public static Type[] GetAllClassesInheritingFrom(Assembly assembly, Type baseType)\r\n        => GetAll___(assembly, baseType.FullName,\r\n            lines => lines.Select(Type.GetType),\r\n            types => types.Where(t => t.IsSubclassOf(baseType)),\r\n            result => result.Select(t => t.AssemblyQualifiedName)\r\n        );\r\n\r\n    /// <summary>\r\n    /// Enumerates all types from the specified assembly\r\n    /// decorated with attribute T as tuples of type\r\n    /// and its one or more T-attributes.\r\n    /// </summary>\r\n    public static (Type, T[])[] GetAllTypesWithAttribute<T>(Assembly assembly)\r\n        => GetAll___<(Type, T[])>(assembly, typeof(T).FullName,\r\n           lines => lines.Select(Type.GetType)\r\n                    .Select(t => (t, TryGetCustomAttributes<T>(t))),\r\n           types => from t in types\r\n                    let attribs = TryGetCustomAttributes<T>(t)\r\n                    where attribs.Length > 0\r\n                    select (t, attribs),\r\n           result => result.Select(t => t.Item1.AssemblyQualifiedName)\r\n        );\r\n\r\n    private static T[] TryGetCustomAttributes<T>(Type type)\r\n    {\r\n        try\r\n        {\r\n            return type.GetCustomAttributes(typeof(T), false).Select(x => (T)x).ToArray();\r\n        }\r\n        catch (Exception e)\r\n        {\r\n            Report.Line(3, \"[Introspection] Failed to get custom attributes for {0}: {1} ({2})\", type.FullName, e.Message, e.GetType().Name);\r\n        }\r\n        return [];\r\n    }\r\n\r\n    private static T[] TryGetCustomAttributes<T>(MethodInfo mi)\r\n    {\r\n        try\r\n        {\r\n            return mi.GetCustomAttributes(typeof(T), false).Select(x => (T)x).ToArray();\r\n        }\r\n        catch (Exception e)\r\n        {\r\n            Report.Line(3, \"[Introspection] Failed to get custom attributes for {0}.{1}: {2} ({3})\", mi.DeclaringType?.FullName, mi.Name, e.Message, e.GetType().Name);\r\n        }\r\n        return [];\r\n    }\r\n\r\n    /// <summary>\r\n    /// Enumerates all methods from the specified assembly\r\n    /// decorated with attribute T as tuples of MethodInfo\r\n    /// and its one or more T-attributes.\r\n    /// </summary>\r\n    public static (MethodInfo, T[])[] GetAllMethodsWithAttribute<T>(Assembly assembly)\r\n        => GetAll___<(MethodInfo, T[])>(assembly, typeof(T).FullName,\r\n              lines => from line in lines\r\n                       let t = Type.GetType(line)\r\n                       where t != null\r\n                       from m in t.GetMethods()\r\n                       let attribs = TryGetCustomAttributes<T>(m)\r\n                       where attribs.Length > 0\r\n                       select (m, attribs),\r\n              types => from t in types\r\n                       where t != null\r\n                       from m in t.GetMethods()\r\n                       let attribs = TryGetCustomAttributes<T>(m)\r\n                       where attribs.Length > 0\r\n                       select (m, attribs),\r\n              result => result.SelectNotNull(m => m.Item1.DeclaringType?.AssemblyQualifiedName)\r\n        );\r\n\r\n    static Introspection()\r\n    {\r\n        Report.BeginTimed(\"Enumerating assemblies for introspection\");\r\n\r\n        // enumerating all assemblies reachable from entry assembly\r\n        s_assemblies = new Dictionary<string, Assembly>();\r\n\r\n        var entryAssembly = IntrospectionProperties.CurrentEntryAssembly ?? typeof(Aardvark).Assembly;\r\n\r\n        if (entryAssembly == null)\r\n        {\r\n            Report.Warn(\"[Introspection] Could not determine entry assembly\");\r\n            RegisterAllAssembliesInPath(IntrospectionProperties.CurrentEntryPath);\r\n        }\r\n        else\r\n        {\r\n            var location = IntrospectionProperties.CurrentEntryBundle ?? entryAssembly.GetLocationSafe();\r\n            if (location != null)\r\n                Report.Line(4, $\"[Introspection] Entry assembly: {entryAssembly.FullName} (path: {location})\");\r\n            else\r\n                Report.Line(4, $\"[Introspection] Entry assembly: {entryAssembly.FullName} (unknown location)\");\r\n\r\n            var name = entryAssembly.GetName().Name;\r\n            EnumerateAssemblies(name, entryAssembly);\r\n        }\r\n\r\n        Report.EndTimed();\r\n    }\r\n\r\n    /// <summary>\r\n    /// Tries to load and register all assemblies in given path.\r\n    /// </summary>\r\n    [DebuggerNonUserCode]\r\n    [Obsolete(\"Use overload without verbose parameter.\")]\r\n    public static void RegisterAllAssembliesInPath(string path, bool verbose)\r\n        => RegisterAllAssembliesInPath(path);\r\n\r\n    /// <summary>\r\n    /// Tries to load and register all assemblies in given path.\r\n    /// </summary>\r\n    [DebuggerNonUserCode]\r\n    public static void RegisterAllAssembliesInPath(string path)\r\n    {\r\n        Report.Begin(4, $\"[Introspection] Registering assemblies in: {path}\");\r\n\r\n        try\r\n        {\r\n            foreach (var file in DirectoryUtils.GetFilesSafe(path))\r\n            {\r\n                var ext = PathUtils.GetExtensionSafe(file)?.ToLowerInvariant();\r\n                if (ext != \".dll\" &&  ext != \".exe\") continue;\r\n\r\n                try\r\n                {\r\n                    var name = AssemblyName.GetAssemblyName(file);\r\n                    Report.Line(4, $\"{PathUtils.GetFileNameSafe(file)}\");\r\n                    EnumerateAssemblies(name.Name);\r\n                }\r\n                catch\r\n                {\r\n                }\r\n            }\r\n        }\r\n        catch (Exception e)\r\n        {\r\n            Report.Warn($\"Error while registering assemblies in '{path}': {e.Message}\");\r\n        }\r\n        finally\r\n        {\r\n            Report.End(4);\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// Note by hs: Since this function throws and catches exceptions in non-exceptional cases we\r\n    /// use [DebuggerNonUserCode] to deactive first chance exceptions here\r\n    /// at least if non-user code is deactivated in Options/Debugging.\r\n    /// </summary>\r\n    /// <param name=\"name\">the name of the entry assembly</param>\r\n    /// <param name=\"customAssembly\">If the root assembly is not the assembly which has been started\r\n    /// by the AppDomain a customAssembly is used alternatively.</param>\r\n    [DebuggerNonUserCode]\r\n    private static void EnumerateAssemblies(string name, Assembly customAssembly = null)\r\n    {\r\n        if (string.IsNullOrEmpty(name)) return;\r\n        if (s_assembliesThatFailedToLoad.Contains(name)) return;\r\n        if (s_assemblies.ContainsKey(name)) return;\r\n\r\n        if (!IntrospectionProperties.AssemblyFilter(name))\r\n        {\r\n            Report.Line(4, \"[Introspection] Ignoring assembly {0} due to filter\", name);\r\n            return;\r\n        }\r\n\r\n        try\r\n        {\r\n            var assembly = customAssembly ?? Assembly.Load(name);\r\n            s_assemblies[name] = assembly;\r\n            RegisterAssembly(assembly);\r\n            foreach (var a in assembly.GetReferencedAssemblies())\r\n            {\r\n                if (a.Name != null && !s_assemblies.ContainsKey(a.Name))\r\n                {\r\n                    EnumerateAssemblies(a.Name);\r\n                }\r\n            }\r\n        }\r\n        catch //(Exception e)\r\n        {\r\n            s_assembliesThatFailedToLoad.Add(name);\r\n            //Report.Warn(e.ToString());\r\n            //Report.Warn(\"{0}\", name);\r\n        }\r\n    }\r\n\r\n    private static string GetQueryCacheFilename(Assembly asm, Guid queryGuid)\r\n    {\r\n        var name = asm.GetName().Name;\r\n        var id = asm.GetIdentifier(CachingProperties.IntrospectionCacheFileNaming);\r\n        return Path.Combine(CacheDirectory, $\"{name}_{id}_{queryGuid}.query\");\r\n    }\r\n\r\n    private class CacheFileHeader\r\n    {\r\n        public int Version;\r\n        public DateTime TimeStampOfCachedFile;\r\n\r\n        public override string ToString()\r\n        {\r\n            if (Version <= 0) throw new ArgumentOutOfRangeException(nameof(Version));\r\n            return string.Format(s_cultureInfoEnUs, \"version {0} timestamp {1}\", Version, TimeStampOfCachedFile.ToBinary());\r\n        }\r\n\r\n        public static CacheFileHeader Parse(string s)\r\n        {\r\n            if (string.IsNullOrEmpty(s)) throw new ArgumentNullException(nameof(s));\r\n            if (!s.StartsWith(\"version\")) return null; // old file without header\r\n            var tokens = s.Split(' ');\r\n            if (tokens.Length != 4) throw new FormatException();\r\n            return new CacheFileHeader\r\n            {\r\n                Version = int.Parse(tokens[1]),\r\n                TimeStampOfCachedFile = DateTime.FromBinary(long.Parse(tokens[3]))\r\n            };\r\n        }\r\n    }\r\n    private static T[] GetAll___<T>(\r\n        Assembly a, string discriminator,\r\n        Func<IEnumerable<string>, IEnumerable<T>> decode,\r\n        Func<IEnumerable<Type>, IEnumerable<T>> createResult,\r\n        Func<T[], IEnumerable<string>> encode\r\n        )\r\n    {\r\n        var cacheFileName = \"\";\r\n        var assemblyTimeStamp = DateTime.MinValue;\r\n\r\n        // whatever happens, don't halt just because of caching... this actually happens for self-contained deployments https://github.com/aardvark-platform/aardvark.base/issues/65\r\n        try\r\n        {\r\n            cacheFileName = GetQueryCacheFilename(a, discriminator.ToGuid());\r\n            assemblyTimeStamp = a.GetLastWriteTimeSafe();\r\n\r\n            // for standalone deployments cacheFileNames cannot be retrieved robustly - we skip those\r\n            if (!string.IsNullOrEmpty(cacheFileName) && File.Exists(cacheFileName))\r\n            {\r\n                var lines = File.ReadAllLines(cacheFileName);\r\n                var header = lines.Length > 0 ? CacheFileHeader.Parse(lines[0]) : null;\r\n                if (header != null && header.TimeStampOfCachedFile == assemblyTimeStamp)\r\n                {\r\n                    // return cached types\r\n                    Report.Line(4, \"[cache hit ] {0}\", a);\r\n                    return decode(lines.Skip(1)).ToArray();\r\n                }\r\n            }\r\n        } catch(Exception e)\r\n        {\r\n            Report.Warn(\"Could not get cache for {1}: {0}\", e.Message, a.FullName);\r\n        }\r\n\r\n        Report.Line(4, \"[cache miss] {0}\", a);\r\n\r\n        // Notes by hs:\r\n        // previously (rev 19495) typeloadexception resulted in empty result set.\r\n        // even in case of typeloadexception there may be some successfully loaded\r\n        // types in result set. Just continue processing with these types\r\n        // effect: dlls with external unused dependencies don't have to be shipped.\r\n        Type[] ts;\r\n        try\r\n        {\r\n            ts = a.GetTypes();\r\n        }\r\n        catch (ReflectionTypeLoadException e)\r\n        {\r\n            Report.Begin(\"ReflectionTypeLoadException error in assembly {0}\", a.GetName().Name);\r\n            Report.Line(\"Full assembly name is {0}.\", a.FullName);\r\n            Report.Line(\"Exception is {0}\", e);\r\n            Report.Begin(\"Loader exceptions are\");\r\n            foreach (var x in e.LoaderExceptions)\r\n            {\r\n                Report.Line(\"{0}\", x);\r\n            }\r\n            Report.End();\r\n            Report.End();\r\n            ts = e.Types.Where(t => t != null).ToArray();\r\n        }\r\n\r\n        var result = createResult(ts).ToArray();\r\n\r\n\r\n        // whatever happens, don't halt everything just because caching fails\r\n        try\r\n        {\r\n            // for standalone deployments cacheFileNames cannot be retrieved robustly - we skip those\r\n            if (!string.IsNullOrEmpty(cacheFileName))\r\n            {\r\n\r\n                // write cache file\r\n                var headerLine =\r\n                    new CacheFileHeader { Version = 1, TimeStampOfCachedFile = assemblyTimeStamp }\r\n                    .ToString()\r\n                    .IntoIEnumerable();\r\n\r\n                File.WriteAllLines(cacheFileName, headerLine.Concat(encode(result)).ToArray());\r\n            }\r\n        }\r\n        catch(Exception e)\r\n        {\r\n            Report.Warn(\"Could not write cache for {1}: {0}\", e.Message, a.FullName);\r\n        }\r\n\r\n        return result;\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base/Introspection/IntrospectionProperties.cs",
    "content": "namespace Aardvark.Base;\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\n\npublic static class IntrospectionProperties\n{\n    /// <summary>\n    /// Introspection is based on Assembly.GetEntryAssembly which represents the managed\n    /// entry point (i.e. the first assembly that was executed by AppDomain.ExecuteAssembly).\n    /// However, started from an unmanaged entry point (like Visual Studio tests) Assembly.GetEntryAssembly\n    /// is null. To allow us to start from unmanaged hosting processes this alternative\n    /// has been implemented.\n    /// A second use case are managed interactive shells like fsi.exi. Here we want to\n    /// start our dependency walk at a custom assembly instead of the running assembly\n    /// which is the interactive shell host.\n    /// </summary>\n    public static Assembly CustomEntryAssembly { get; set; }\n\n    public static Assembly CurrentEntryAssembly => CustomEntryAssembly ?? Assembly.GetEntryAssembly();\n\n    /// <summary>\n    /// Whether plugin loading should be enabled\n    /// </summary>\n    public static bool PluginsEnabled = true;\n\n    /// <summary>\n    /// Whether Aardvark.Init should unpack native libraries\n    /// </summary>\n    public static bool NativeLibraryUnpackingAllowed = true;\n\n\n    public static string CurrentEntryPath\n    {\n        get\n        {\n            var location = CurrentEntryAssembly?.GetLocationSafe();\n            return PathUtils.GetDirectoryNameSafe(location) ?? AppDomain.CurrentDomain.BaseDirectory;\n        }\n    }\n\n    /// <summary>\n    /// Returns the path to the single file deployed entry bundle if it exists, null otherwise.\n    /// </summary>\n    public static string CurrentEntryBundle\n    {\n        get\n        {\n            var entryAssembly = CurrentEntryAssembly;\n\n            // If Location is empty or null, we might have a single-file application\n            if (entryAssembly != null && !entryAssembly.HasLocation())\n            {\n                var name = entryAssembly.GetName().Name;\n                var ext = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? \".exe\" : \"\";\n                var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name + ext);\n\n                if (File.Exists(path))\n                {\n                    return path;\n                }\n\n                Report.Warn($\"Could not find bundle executable: {path}\");\n            }\n\n            return null;\n        }\n    }\n\n    private static readonly HashSet<string> s_defaultAssemblyBlacklist =\n        [\n            \"ASift.CLI\",\n            \"CUDA.NET\",\n            \"Emgu.CV\",\n            \"levmarCLI\",\n            \"LSDCli\",\n            \"OpenNI.Net\",\n            \"OpenSURFcs\",\n            \"PdfSharp\",\n            \"PresentationFramework\",\n            \"PresentationCore\",\n            \"PrimitiveShapesCLI\",\n            \"SiftGpu.CLI\",\n            \"SlamToroCli\",\n            \"System\",\n            \"WindowsBase\",\n            \"OpenTK\",\n            \"Suave\",\n            \"Newtonsoft.Json\",\n            \"Aether\",\n            \"CommonMark\",\n            \"CSharp.Data.Adaptive\",\n            \"FSharp.Data.Adaptive\",\n            \"ICSharpCode.SharpZipLib\",\n            \"LibTessDotNet\",\n            \"SixLabors.ImageSharp\",\n            \"netstandard\",\n            \"FsPickler\",\n            \"WindowsFormsIntegration\",\n            \"Unofficial.Typography\"\n        ];\n\n    /// <summary>\n    /// Given an assembly name, should it be considered as plugin/native resource etc. This one by default excludes portions of clr base library\n    /// </summary>\n    public static bool DefaultAssemblyFilter(string name)\n    {\n        return !(s_defaultAssemblyBlacklist.Contains(name) ||\n                 name.StartsWith(\"System.\") ||\n                 name.StartsWith(\"VRLib.CLI\") ||\n                 name.StartsWith(\"Microsoft\") ||\n                 name.StartsWith(\"LidorSystems\") ||\n                 name.StartsWith(\"WeifenLuo.\") ||\n                 name.StartsWith(\"OpenCV\") && name != \"OpenCVSharp\" || // OpenCVSharp.dll contains native assemblies that need to be unpacked\n                 name.StartsWith(\"nunit.\") ||\n                 name.StartsWith(\"Extreme.Numerics\") ||\n                 name.StartsWith(\"fftwlib\") ||\n                 name.StartsWith(\"GraphCutsCLI\") ||\n                 name.StartsWith(\"Interop.MLApp\") ||\n                 name.StartsWith(\"IPP\") && name != \"IPP\" || // IPP.dll contains native assemblies that need to be unpacked\n                 name.StartsWith(\"IronRuby\") ||\n                 name.StartsWith(\"MapTools\") ||\n                 name.StartsWith(\"MetaDataExtractor\") ||\n                 name.StartsWith(\"mscorlib\") ||\n                 name.StartsWith(\"SlimDX\") ||\n                 name.StartsWith(\"TDx.TDxInput\") ||\n                 name.StartsWith(\"WiimoteLib\") ||\n                 name.StartsWith(\"OpenTK\") ||\n                 name.StartsWith(\"Kitware\") ||\n                 name.StartsWith(\"ICSharpCode\") ||\n                 name.StartsWith(\"Roslyn\") ||\n                 name.StartsWith(\"SharpDX\") ||\n                 name.StartsWith(\"Aardvark.Jynx.Native\") ||\n                 name.StartsWith(\"SurfaceQueueInteropHelper\") ||\n                 name.StartsWith(\"ScintillaNET\") ||\n                 name.StartsWith(\"IKVM\") ||\n                 name.StartsWith(\"Super\") ||\n                 name.StartsWith(\"Java\") ||\n                 name.StartsWith(\"PresentationFramework\") ||\n                 name.StartsWith(\"FShade\") ||\n                 name.StartsWith(\"Xceed\") ||\n                 name.StartsWith(\"UIAutomation\") ||\n                 name.StartsWith(\"Uncodium\")\n                 );\n    }\n\n    /// <summary>\n    /// Determines if the built-in assembly filter is ignored or applied (default: false).\n    /// </summary>\n    public static bool IgnoreDefaultAssemblyFilter { get; set; } = false;\n\n    /// <summary>\n    /// Filter function determining if an assembly with the given name (without extension) should be loaded or ignored.\n    /// <see cref=\"IgnoreDefaultAssemblyFilter\"/> determines if the function is applied on top of the built-in filter rules.\n    /// </summary>\n    public static Func<string, bool> CustomAssemblyFilter { get; set; } = (_) => true;\n\n    /// <summary>\n    /// Filters assemblies according to DefaultAssemblyFilter\n    /// </summary>\n    public static bool AssemblyFilter(string name)\n    {\n        return (IgnoreDefaultAssemblyFilter || DefaultAssemblyFilter(name)) && CustomAssemblyFilter(name);\n    }\n\n    /// <summary>\n    /// can be set from application code to disable native unpacking for specific assemblies. Per default, we use the same filter as for EnumerateAssemblies.\n    /// It is absolute crucial to prevent exceptions within this code because of mscorlib resource bug detection\n    /// </summary>\n    public static Func<Assembly, bool> UnpackNativeLibrariesFilter =\n        assembly =>\n        {\n            var name = assembly?.GetName()?.Name;\n            return name != null && AssemblyFilter(name);\n        };\n\n    [Obsolete]\n    public static string BundleEntryPoint = \"\";\n\n    [Obsolete]\n    public static Func<Assembly, DateTime> GetLastWriteTimeUtc =\n        assembly => assembly.GetLastWriteTimeSafe();\n}"
  },
  {
    "path": "src/Aardvark.Base/Introspection/Native.cs",
    "content": "namespace Aardvark.Base;\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Security.Cryptography;\nusing System.Xml.Linq;\n\npublic partial class Aardvark\n{\n    private static readonly Lazy<string> s_nativeLibraryCacheDirectory =\n        new(() => Path.Combine(CachingProperties.CacheDirectory, \"Native\"));\n\n    /// <summary>\n    /// Directory containing unpacked native dependencies.\n    /// </summary>\n    public static readonly string NativeLibraryCacheDirectory = s_nativeLibraryCacheDirectory.Value;\n\n    /// Specify if native libraries should be extracted each to its own sub folder or directory to the NativeLibraryPath\n    /// NOTE: When using global shared NativeLibraryPath, SeparateLibraryDirectories should not be set to false, as there might be version conflicts\n    public static bool SeparateLibraryDirectories = true;\n\n    #region Dependencies Unpacking\n\n    private static readonly Dictionary<Assembly, string> s_nativeDependenciesDirectory = new();\n    private static readonly Dictionary<Assembly, string[]> s_nativeLibraryPaths = new();\n\n    /// <summary>\n    /// Returns whether the file path appears to be a native library for the current platform.\n    /// </summary>\n    private static bool IsNativeLibrary(string path)\n        => RegexPatterns.NativeLibrary.Extension.IsMatch(path);\n\n    private static string PlatformString(OSPlatform platform)\n    {\n        return platform == OSPlatform.Windows ? \"windows\" :\n               platform == OSPlatform.OSX     ? \"mac\" :\n               platform == OSPlatform.Linux   ? \"linux\" :\n               \"unknown\";\n    }\n\n    private static string ArchitectureString(Architecture arch) =>\n        arch switch\n        {\n            Architecture.X86   => \"x86\",\n            Architecture.X64   => \"AMD64\",\n            Architecture.Arm   => \"ARM\",\n            Architecture.Arm64 => \"ARM64\",\n            _                  => arch.ToString()\n        };\n\n    #region DllMap\n\n    private static Dictionary<string, string> GetSymlinks(XDocument document)\n    {\n        var dict = new Dictionary<string, string>();\n        var myOs = GetOS();\n        var root = document.Element(XName.Get(\"configuration\"));\n        if(root != null)\n        {\n            foreach(var e in root.Elements(XName.Get(\"dllmap\")))\n            {\n                var src     = e.Attribute(XName.Get(\"dll\"));\n                var os      = e.Attribute(XName.Get(\"os\"));\n                var dst     = e.Attribute(XName.Get(\"target\"));\n\n                if(src != null && dst != null && os != null)\n                {\n                    var srcStr  = src.Value;\n                    var osStr   = os.Value;\n                    var dstStr  = dst.Value;\n\n                    if(!string.IsNullOrWhiteSpace(srcStr) && !string.IsNullOrWhiteSpace(dstStr) && TryParseOS(osStr, out var osVal))\n                    {\n                        if(myOs == osVal)\n                        {\n                            dict[srcStr] = dstStr;\n                        }\n                    }\n                }\n\n            }\n        }\n\n        return dict;\n    }\n\n    #endregion\n\n    #region Symlink\n\n#if NET8_0_OR_GREATER\n    private static void CreateSymlink(string src, string dst)\n        => File.CreateSymbolicLink(src, dst);\n#else\n    [DllImport(\"libc\")]\n    private static extern int symlink(string oldpath, string newpath);\n\n    private static void CreateSymlink(string src, string dst)\n    {\n        var ret = symlink(dst, src);\n        if (ret != 0) throw new Exception($\"symlink() failed (exit code = {ret})\");\n    }\n#endif\n\n    private static void CreateSymlink(string baseDir, string src, string dst)\n    {\n        var os = GetOS();\n        if (os is OS.Win32 or OS.Unknown) return;\n\n        Report.Begin(3, $\"Creating symlink '{src}' -> '{dst}'\");\n\n        try\n        {\n            var srcPath = Path.Combine(baseDir, src);\n            Report.Line(3, $\"Directory: {baseDir}\");\n\n            var dstPath = os is OS.Linux && LdConfig.TryGetPath(dst, out string resolvedPath) ? resolvedPath : Path.Combine(baseDir, dst);\n            Report.Line(3, $\"Target path: {dstPath}\");\n\n            if (!File.Exists(dstPath))\n            {\n                Report.End(3, \" - target not found\");\n                return;\n            }\n\n            if (File.Exists(srcPath))\n            {\n                File.Delete(srcPath);\n            }\n            else\n            {\n                var srcDir = PathUtils.GetDirectoryNameSafe(srcPath);\n                if (!Directory.Exists(srcDir)) Directory.CreateDirectory(srcDir);\n            }\n\n            CreateSymlink(srcPath, dstPath);\n            Report.End(3, \" - success\");\n        }\n        catch (Exception e)\n        {\n            Report.Line(3, $\"{e.GetType().Name}: {e.Message}\");\n            Report.End(3, \" - failure\");\n        }\n    }\n\n    #endregion\n\n    /// <summary>\n    /// Extracts native libraries embedded in the specified assembly and returns their relative file names.\n    /// </summary>\n    /// <param name=\"assembly\">The assembly whose embedded native dependencies should be unpacked. Dynamic assemblies are ignored.</param>\n    /// <param name=\"platform\">The target operating system platform used to select the appropriate files from the archive.</param>\n    /// <param name=\"architecture\">The target CPU architecture used to select the appropriate files from the archive.</param>\n    /// <param name=\"outputDir\">Destination directory where files are extracted. If <c>null</c> or empty, defaults to <see cref=\"IntrospectionProperties.CurrentEntryPath\"/>.</param>\n    /// <returns>\n    /// An array of relative paths (using the archive's internal folder structure) of the native libraries that were present\n    /// for the given platform/architecture combination. The returned paths are relative to <paramref name=\"outputDir\"/>.\n    /// </returns>\n    public static string[] UnpackAndListNativeDependencies(Assembly assembly, OSPlatform platform, Architecture architecture, string outputDir = null)\n    {\n        if (assembly.IsDynamic) return [];\n        if (outputDir.IsNullOrEmpty()) outputDir = IntrospectionProperties.CurrentEntryPath;\n\n        Report.Begin(3, $\"Unpacking native dependencies for {assembly.FullName}\");\n\n        try\n        {\n            Report.Line(3, $\"Output directory: {outputDir}\");\n\n            var info = assembly.GetManifestResourceInfo(\"native.zip\");\n            if (info == null)\n            {\n                Report.Line(3, $\"Assembly does not contain native dependencies.\");\n                return [];\n            }\n\n            var platformString = PlatformString(platform);\n            var architectureString = ArchitectureString(architecture);\n\n            string[] copyPaths = [ $\"{platformString}/{architectureString}/\", $\"{architectureString}/\" ];\n            List<string> libNames = [];\n            Dictionary<string, string> remap = [];\n\n            bool TryGetLocalName(string entryName, out string localName)\n            {\n                foreach(var prefix in copyPaths)\n                {\n                    if (entryName.StartsWith(prefix))\n                    {\n                        var name = entryName.Substring(prefix.Length);\n#if NET8_0_OR_GREATER\n                        var parts = name.Split('/', StringSplitOptions.RemoveEmptyEntries);\n#else\n                        var parts = name.Split(['/'], StringSplitOptions.RemoveEmptyEntries);\n#endif\n\n                        if (parts.Length > 0)\n                        {\n                            localName = Path.Combine(parts);\n                            return true;\n                        }\n                    }\n                }\n\n                localName = null;\n                return false;\n            }\n\n            using var stream = assembly.GetManifestResourceStream(\"native.zip\");\n            using var archive = new ZipArchive(stream);\n\n            foreach (var e in archive.Entries)\n            {\n                var entryName = e.FullName.Replace(Path.DirectorySeparatorChar, '/');\n\n                if (entryName == \"remap.xml\")\n                {\n                    using var es = e.Open();\n                    var doc = XDocument.Load(es);\n                    remap = GetSymlinks(doc);\n                }\n                else if (TryGetLocalName(entryName, out var localName))\n                {\n                    var dstPath = Path.Combine(outputDir, localName);\n                    var dstDir = PathUtils.GetDirectoryNameSafe(dstPath);\n\n                    if (!File.Exists(dstDir)) Directory.CreateDirectory(dstDir);\n\n                    if (!File.Exists(dstPath) || FileUtils.GetLastWriteTimeSafe(dstPath) < e.LastWriteTime.UtcDateTime)\n                    {\n                        Report.Line(3, $\"Unpacking: {localName}\");\n                        e.ExtractToFile(dstPath, true);\n                    }\n                    else\n                    {\n                        Report.Line(3, $\"Found: {localName}\");\n                    }\n\n                    if (IsNativeLibrary(localName)) libNames.Add(localName);\n                }\n            }\n\n            foreach (var kvp in remap)\n            {\n                CreateSymlink(outputDir, kvp.Key, kvp.Value);\n                if (IsNativeLibrary(kvp.Key)) libNames.Add(kvp.Key);\n            }\n\n            return libNames.ToArray();\n        }\n        catch (Exception e)\n        {\n            Report.Warn($\"Could not unpack native dependencies for {assembly.FullName}: {e.Message}\");\n            return [];\n        }\n        finally\n        {\n            Report.End(3);\n        }\n    }\n\n    /// <summary>\n    /// Extracts native libraries embedded in <paramref name=\"assembly\"/> for the current OS platform and process architecture.\n    /// </summary>\n    /// <param name=\"assembly\">The assembly whose embedded native dependencies should be unpacked.</param>\n    /// <param name=\"outputDir\">Destination directory where files are extracted. If <c>null</c> or empty, defaults to <see cref=\"IntrospectionProperties.CurrentEntryPath\"/>.</param>\n    /// <returns>\n    /// An array of relative paths of the native libraries that were present for the current platform and architecture.\n    /// The paths are relative to <paramref name=\"outputDir\"/>.\n    /// </returns>\n    public static string[] UnpackAndListNativeDependencies(Assembly assembly, string outputDir = null)\n        => UnpackAndListNativeDependencies(assembly, GetOSPlatform(), RuntimeInformation.ProcessArchitecture, outputDir);\n\n    /// <summary>\n    /// Extracts native libraries embedded in <paramref name=\"assembly\"/> for the specified platform and architecture.\n    /// </summary>\n    /// <param name=\"assembly\">The assembly whose embedded native dependencies should be unpacked.</param>\n    /// <param name=\"platform\">The target operating system platform used to select the appropriate files from the archive.</param>\n    /// <param name=\"architecture\">The target CPU architecture used to select the appropriate files from the archive.</param>\n    /// <param name=\"outputDir\">Destination directory where files are extracted. If <c>null</c> or empty, defaults to <see cref=\"IntrospectionProperties.CurrentEntryPath\"/>.</param>\n    public static void UnpackNativeDependencies(Assembly assembly, OSPlatform platform, Architecture architecture, string outputDir = null)\n        => UnpackAndListNativeDependencies(assembly, platform, architecture, outputDir);\n\n    /// <summary>\n    /// Extracts native libraries embedded in <paramref name=\"assembly\"/> for the current OS platform and process architecture.\n    /// </summary>\n    /// <param name=\"assembly\">The assembly whose embedded native dependencies should be unpacked.</param>\n    /// <param name=\"outputDir\">Destination directory where files are extracted. If <c>null</c> or empty, defaults to <see cref=\"IntrospectionProperties.CurrentEntryPath\"/>.</param>\n    public static void UnpackNativeDependencies(Assembly assembly, string outputDir)\n        => UnpackAndListNativeDependencies(assembly, outputDir);\n\n    /// <summary>\n    /// Extracts native libraries embedded in <paramref name=\"assembly\"/> to <see cref=\"IntrospectionProperties.CurrentEntryPath\"/>\n    /// using the current OS platform and process architecture.\n    /// </summary>\n    /// <param name=\"assembly\">The assembly whose embedded native dependencies should be unpacked.</param>\n    public static void UnpackNativeDependencies(Assembly assembly)\n        => UnpackAndListNativeDependencies(assembly);\n\n    /// <summary>\n    /// Returns the paths of the directories containing native dependencies of all assemblies.\n    /// </summary>\n    public static string[] GetNativeDependenciesDirectories()\n    {\n        lock(s_nativeDependenciesDirectory)\n        {\n            return s_nativeDependenciesDirectory.Values.Where(Directory.Exists).ToArray();\n        }\n    }\n\n    /// <summary>\n    /// Returns the path of the directory containing native dependencies of the given assembly.\n    /// </summary>\n    /// <param name=\"assembly\">Assembly with native dependencies.</param>\n    /// <param name=\"path\">Returns the path of the directory, if the assembly has native dependencies.</param>\n    /// <returns>True if the assembly has native dependencies, false otherwise.</returns>\n    public static bool TryGetNativeDependenciesDirectory(Assembly assembly, out string path)\n    {\n        var name = assembly?.GetName().Name;\n        if (assembly == null || assembly.IsDynamic || string.IsNullOrEmpty(name))\n        {\n            path = null;\n            return false;\n        }\n\n        lock (s_nativeDependenciesDirectory)\n        {\n            if (s_nativeDependenciesDirectory.TryGetValue(assembly, out path))\n            {\n                return path != null;\n            }\n\n            var info = assembly.GetManifestResourceInfo(\"native.zip\");\n            if (info == null)\n            {\n                s_nativeDependenciesDirectory[assembly] = null;\n                return false;\n            }\n\n            using var stream = assembly.GetManifestResourceStream(\"native.zip\");\n            string dstFolder = NativeLibraryCacheDirectory;\n\n            if (SeparateLibraryDirectories)\n            {\n#if NET8_0_OR_GREATER\n                var hash = SHA1.HashData(stream);\n                var guid = new Guid(hash.AsSpan(0, 16));\n#else\n                using var sha1 = SHA1.Create();\n                var hash = sha1.ComputeHash(stream);\n                Array.Resize(ref hash, 16);\n                var guid = new Guid(hash);\n#endif\n\n                var platform = PlatformString(GetOSPlatform());\n                var arch = ArchitectureString(RuntimeInformation.ProcessArchitecture);\n                dstFolder = Path.Combine(dstFolder, name, guid.ToString(), platform, arch);\n            }\n\n            s_nativeDependenciesDirectory[assembly] = dstFolder;\n            path = dstFolder;\n            return true;\n        }\n    }\n\n    private static bool ShouldUnpackNativeDependencies(Assembly assembly)\n    {\n        try\n        {\n            return IntrospectionProperties.UnpackNativeLibrariesFilter(assembly);\n        }\n        catch (Exception e)\n        {\n            Report.Warn($\"Error while invoking UnpackNativeLibrariesFilter for {assembly.FullName}: {e.Message}\");\n            return false;\n        }\n    }\n\n    public static void LoadNativeDependencies(Assembly assembly)\n    {\n        if (assembly == null) return;\n\n        if (!ShouldUnpackNativeDependencies(assembly))\n        {\n            Report.Line(4, $\"Skipped loading native dependencies for {assembly.FullName}\");\n            return;\n        }\n\n        if (TryGetNativeDependenciesDirectory(assembly, out string dstFolder))\n        {\n            try\n            {\n                Report.BeginTimed(3, $\"Loading native dependencies for {assembly.FullName}\");\n\n                var libraryNames = UnpackAndListNativeDependencies(assembly, dstFolder);\n                var libraryPaths = new List<string>(capacity: libraryNames.Length);\n\n                lock (s_nativeLibraryPaths)\n                {\n                    foreach (var libraryName in libraryNames)\n                    {\n                        var path = Path.Combine(dstFolder, libraryName);\n                        if (File.Exists(path)) libraryPaths.Add(path);\n                    }\n\n                    s_nativeLibraryPaths[assembly] = libraryPaths.ToArray();\n                }\n\n#if !NETCOREAPP3_1_OR_GREATER\n                // For .NET Standard 2.0, we don't have access to the ResolvingUnmanagedDll event (see Aardvark.Init())\n                // Instead we load all the native libraries preemptively after unpacking.\n                // Caveat: This does not work with symlinks (on Linux at least), but there is no reason to use the .NET Standard 2.0 build\n                // for non-Windows platforms anyway.\n                foreach (var libraryPath in libraryPaths)\n                {\n                    LoadLibrary(assembly, libraryPath, resolving: false, global: true);\n                }\n#endif\n            }\n            catch (Exception e)\n            {\n                Report.Warn($\"Could not load native dependencies for {assembly.FullName}: {e.Message}\");\n            }\n            finally\n            {\n                Report.EndTimed(3);\n            }\n        }\n    }\n\n    #endregion\n\n    #region Library Loading\n\n    private static string NativeLibraryExtension { get; } =\n        GetOS() switch\n        {\n            OS.Win32 => \".dll\",\n            OS.MacOS => \".dylib\",\n            _ => \".so\"\n        };\n\n\n    private static bool TryLoadNativeLibrary(string libraryName, bool global, out IntPtr handle)\n    {\n#if NETCOREAPP3_1_OR_GREATER\n        return NativeLibrary.TryLoad(libraryName, out handle);\n#else\n        try\n        {\n            if (GetOS() == OS.Win32)\n            {\n                var flags = Kernel32.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;\n                if (PathUtils.IsPathFullyQualified(libraryName)) flags |= Kernel32.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;\n                handle = Kernel32.LoadLibraryEx(libraryName, IntPtr.Zero, flags);\n                if (handle != IntPtr.Zero) return true;\n                var error = Marshal.GetLastWin32Error();\n                Report.Line(3, $\"Kernel32.LoadLibrary failed (error: {error})\");\n            }\n            else\n            {\n                var flags = global ? Dl.RTLD_NODELETE | Dl.RTLD_GLOBAL | Dl.RTLD_NOW : Dl.RTLD_LAZY;\n                handle = Dl.dlopen(libraryName, flags);\n            }\n        }\n        catch (Exception e)\n        {\n            Report.Line(3, $\"{e.GetType().Name}: {e.Message}\");\n            handle = IntPtr.Zero;\n        }\n\n        return handle != IntPtr.Zero;\n#endif\n    }\n\n    private static IEnumerable<string> GetNativeLibraryPaths(Assembly assembly)\n    {\n        var result = new List<string>(capacity: 1);\n\n        // Search in current / assembly directory\n        var currentDirectory = PathUtils.GetDirectoryNameSafe(assembly?.GetLocationSafe()) ?? IntrospectionProperties.CurrentEntryPath;\n        result.AddRange(DirectoryUtils.GetFilesSafe(currentDirectory));\n\n        lock (s_nativeLibraryPaths)\n        {\n            // Probe extracted native libraries\n            if (assembly != null && s_nativeLibraryPaths.TryGetValue(assembly, out var filePathsForAssembly))\n            {\n                result.AddRange(filePathsForAssembly);\n            }\n\n            // Probe extracted native libraries for other assemblies\n            foreach (var filePaths in s_nativeLibraryPaths.Values)\n                result.AddRange(filePaths);\n        }\n\n        return result.Distinct();\n    }\n\n    private static readonly Dictionary<(Assembly, string), string> s_nativeLibraryCache = new();\n\n    private static IntPtr LoadLibrary(Assembly assembly, string libraryNameOrPath, bool resolving, bool global)\n    {\n        if (string.IsNullOrEmpty(libraryNameOrPath)) return IntPtr.Zero;\n        assembly ??= IntrospectionProperties.CurrentEntryAssembly ?? Assembly.GetExecutingAssembly();\n\n        IntPtr ptr = IntPtr.Zero;\n\n        bool TryLoad(string probe)\n        {\n            using var _ = SetDllDirectory(probe);\n\n            if (TryLoadNativeLibrary(probe, global, out ptr))\n            {\n                Report.Line(4, $\"Loaded: {probe}\");\n                try { lock (s_nativeLibraryCache) { s_nativeLibraryCache[(assembly, libraryNameOrPath)] = probe; } } catch {}\n                return true;\n            }\n\n            Report.Line(4, $\"Failed to load: {probe}\");\n            return false;\n        }\n\n        Report.Begin(3, $\"Loading native library '{libraryNameOrPath}'\");\n        Report.Line(4, $\"Assembly: {assembly}\");\n\n        try\n        {\n            // If the input is a path (i.e., it has a directory part) just load as is.\n            if (PathUtils.HasDirectoryInformation(libraryNameOrPath))\n            {\n                if (!resolving) TryLoad(libraryNameOrPath);\n                return ptr;\n            }\n\n            // Lookup input in cache\n            Report.Begin(4, \"Looking up in cache\");\n\n            try\n            {\n                lock (s_nativeLibraryCache)\n                {\n                    var inCache = s_nativeLibraryCache.TryGetValue((assembly, libraryNameOrPath), out var path);\n                    if(inCache && File.Exists(path) && TryLoad(path)) return ptr;\n                }\n            }\n            finally\n            {\n                Report.End(4);\n            }\n\n            // Determine file names of library to search for\n            // If the file name has an unknown or no extension, we add the default library extenion for the current platform\n            var libraryFileNames = new List<string>(capacity: 4)\n            {\n                libraryNameOrPath,\n                $\"lib{libraryNameOrPath}\"\n            };\n\n            if (!string.Equals(PathUtils.GetExtensionSafe(libraryNameOrPath), NativeLibraryExtension, StringComparison.OrdinalIgnoreCase))\n            {\n                libraryFileNames.Add($\"{libraryNameOrPath}{NativeLibraryExtension}\");\n                libraryFileNames.Add($\"lib{libraryNameOrPath}{NativeLibraryExtension}\");\n            }\n\n            // Search in known locations (i.e., entry directory and extracted native directories).\n            Report.Begin(4, \"Searching library directories\");\n\n            try\n            {\n                foreach (var filePath in GetNativeLibraryPaths(assembly))\n                {\n                    var fileName = PathUtils.GetFileNameSafe(filePath);\n\n                    foreach (var libraryFileName in libraryFileNames)\n                    {\n                        if (string.Equals(fileName, libraryFileName, StringComparison.OrdinalIgnoreCase))\n                        {\n                            if (File.Exists(filePath) && TryLoad(filePath)) return ptr;\n                        }\n                    }\n                }\n            }\n            finally\n            {\n                Report.End(4);\n            }\n\n            // Did not find the library in any of the search directories.\n            // Try to load using the dynamic linker, i.e., only using the library name (and variants) instead of a path.\n            Report.Begin(4, \"Using dynamic linker\");\n\n            try\n            {\n                foreach (var libraryFileName in libraryFileNames)\n                {\n                    if (resolving && libraryFileName == libraryNameOrPath) continue;\n                    if (TryLoad(libraryFileName)) return ptr;\n                }\n            }\n            finally\n            {\n                Report.End(4);\n            }\n\n            // On Linux, as a final resort, we go over all the known libraries as returned by `ldconfig` and look for\n            // the library ignoring version numbers.\n            if (GetOS() == OS.Linux)\n            {\n                var libraryName = RegexPatterns.NativeLibrary.Extension.Replace(libraryNameOrPath, \"\");\n                if (!string.IsNullOrEmpty(libraryName))\n                {\n                    Report.Begin(4, \"Using ldconfig ignoring version numbers\");\n\n                    try\n                    {\n                        foreach (var filePath in LdConfig.AllPaths)\n                        {\n                            var fileName = PathUtils.GetFileNameSafe(filePath);\n\n                            if (!string.IsNullOrEmpty(fileName))\n                            {\n                                fileName = RegexPatterns.NativeLibrary.Extension.Replace(fileName, \"\");\n\n                                if (string.Equals(fileName, libraryName, StringComparison.OrdinalIgnoreCase) ||\n                                    string.Equals(fileName, $\"lib{libraryName}\", StringComparison.OrdinalIgnoreCase))\n                                {\n                                    if (File.Exists(filePath) && TryLoad(filePath)) return ptr;\n                                }\n                            }\n                        }\n                    }\n                    finally\n                    {\n                        Report.End(4);\n                    }\n                }\n            }\n\n            return IntPtr.Zero;\n        }\n        catch (Exception e)\n        {\n            Report.Warn($\"{e.GetType().Name} occurred while loading native library '{libraryNameOrPath}': {e.Message}\");\n            return IntPtr.Zero;\n        }\n        finally\n        {\n            Report.End(3, ptr != IntPtr.Zero ? $\" - success\" : \" - failed\");\n        }\n    }\n\n    /// <summary>\n    /// Loads the specified native library; the input can be a name or a file path.\n    /// </summary>\n    /// <remarks>\n    /// If <paramref name=\"libraryNameOrPath\"/> is a path (i.e., it contains a directory separator) the\n    /// platform's dynamic linker is invoked directly with that value. Otherwise, the function\n    /// tries to locate the library by:\n    /// <list type=\"number\">\n    /// <item>Searching the directory where the assembly is located.</item>\n    /// <item>Searching the directory of the native dependencies of the assembly.</item>\n    /// <item>Searching the directories of the native dependencies of all the other assemblies.</item>\n    /// <item>Invoking the dynamic linker.</item>\n    /// <item>Resolving the path by using `ldconfig` ignoring version information (Linux only).</item>\n    /// </list>\n    /// Library name comparison is case-insensitive and variants ('lib' prefix, platform-specific extension) are considered.\n    /// </remarks>\n    /// <param name=\"libraryNameOrPath\">Name or file path of the library to load.</param>\n    /// <param name=\"assembly\">Assembly loading the native library. If <c>null</c> the calling assembly is used.</param>\n    /// <returns>Handle of the loaded library on success, <see cref=\"IntPtr.Zero\"/> otherwise.</returns>\n    [MethodImpl(MethodImplOptions.NoInlining)]\n    public static IntPtr LoadLibrary(string libraryNameOrPath, Assembly assembly = null)\n        => LoadLibrary(assembly ?? Assembly.GetCallingAssembly(), libraryNameOrPath, resolving: false, global: false);\n\n    public static IntPtr GetProcAddress(IntPtr handle, string name)\n    {\n        if (handle == IntPtr.Zero) return IntPtr.Zero;\n\n#if NETCOREAPP3_1_OR_GREATER\n        return NativeLibrary.TryGetExport(handle, name, out var ptr) ? ptr : IntPtr.Zero;\n#else\n        return GetOS() == OS.Win32 ? Kernel32.GetProcAddress(handle, name) : Dl.dlsym(handle, name);\n#endif\n    }\n\n    #endregion\n\n    #region  Obsolete\n\n    [Obsolete(\"Use UnpackNativeDependencies instead.\")]\n    public static void UnpackNativeDependenciesToBaseDir(Assembly a, string baseDir)\n        => UnpackNativeDependencies(a, baseDir);\n\n    [Obsolete(\"using explicit native library path is no longer possble https://github.com/aardvark-platform/aardvark.base/issues/64\")]\n    public static string NativeLibraryPath = Path.Combine(Path.GetTempPath(), \"aardvark-native\");\n\n    [Obsolete(\"Use GetNativeDependenciesDirectories instead.\")]\n    public static string[] GetNativeLibraryPaths()\n        => GetNativeDependenciesDirectories();\n\n    [Obsolete(\"Use TryGetNativeDependenciesDirectory instead.\")]\n    public static bool TryGetNativeLibraryPath(Assembly assembly, out string path)\n        => TryGetNativeDependenciesDirectory(assembly, out path);\n\n    [MethodImpl(MethodImplOptions.NoInlining)]\n    [Obsolete(\"Use overload with optional 'assembly' parameter instead.\")]\n    public static IntPtr LoadLibrary(Assembly assembly, string libraryNameOrPath)\n        => LoadLibrary(assembly ?? Assembly.GetCallingAssembly(), libraryNameOrPath, resolving: false, global: false);\n\n    #endregion\n}"
  },
  {
    "path": "src/Aardvark.Base/Introspection/Platform/Dl.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace Aardvark.Base;\n\npublic partial class Aardvark\n{\n    internal static class Dl\n    {\n        public const int RTLD_LAZY         = 0x00001;\n        public const int RTLD_NOW          = 0x00002;\n        public const int RTLD_BINDING_MASK = 0x00003;\n        public const int RTLD_NOLOAD       = 0x00004;\n        public const int RTLD_DEEPBIND     = 0x00008;\n        public const int RTLD_GLOBAL       = 0x00100;\n        public const int RTLD_LOCAL        = 0x00000;\n        public const int RTLD_NODELETE     = 0x01000;\n\n        [DllImport(\"libc\", SetLastError = false, CharSet = CharSet.Ansi)]\n        public static extern IntPtr dlopen(string path, int flag);\n\n        [DllImport(\"libc\", SetLastError = true, CharSet = CharSet.Ansi)]\n        public static extern IntPtr dlsym(IntPtr handle, string name);\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Introspection/Platform/Kernel32.cs",
    "content": "namespace Aardvark.Base;\n\nusing System;\nusing System.Runtime.InteropServices;\n\npublic partial class Aardvark\n{\n    /// <summary>\n    /// Indicates whether the DLL directory is altered temporarily before loading a native library from a file.\n    /// The DLL directory is set to the directory of the library so that transitive dependencies in\n    /// the same folder can be found. This is usually not required as the dynamic linker should search the directory of\n    /// a library for its dependencies. However, some libraries (e.g., IPP) may use another loading mechanism that require\n    /// setting the DLL directory explicitly.\n    /// </summary>\n    /// <remarks>Only works on Windows, disabled by default.</remarks>\n    public static bool UseSetDllDirectory { get; set; } = false;\n\n    internal static class Kernel32\n    {\n        public const uint DONT_RESOLVE_DLL_REFERENCES = 0x00000001;\n        public const uint LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010;\n        public const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100;\n        public const uint LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200;\n        public const uint LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400;\n        public const uint LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800;\n        public const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000;\n        public const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;\n        public const int SEM_FAILCRITICALERRORS = 0x0001;\n\n        [DllImport(\"Kernel32.dll\", SetLastError = true, CharSet = CharSet.Auto)]\n        public static extern IntPtr LoadLibrary(string path);\n\n        [DllImport(\"Kernel32.dll\", SetLastError = true, CharSet = CharSet.Auto)]\n        public static extern IntPtr LoadLibraryEx(string path, IntPtr handle, uint dwFlags);\n\n        [DllImport(\"Kernel32.dll\", SetLastError = true, CharSet = CharSet.Auto)]\n        public static extern IntPtr AddDllDirectory(string path);\n\n        [DllImport(\"Kernel32.dll\", SetLastError = true, CharSet = CharSet.Auto)]\n        public static extern bool SetCurrentDirectory(string pathName);\n\n        [DllImport(\"Kernel32.dll\", SetLastError = true, CharSet = CharSet.Auto)]\n        public static extern bool SetDllDirectory(string pathName);\n\n        [DllImport(\"Kernel32.dll\", SetLastError = true, CharSet = CharSet.Auto)]\n        public static extern uint GetDllDirectory(uint nBufferLength, [Out] char[] lpPathName);\n\n        [DllImport(\"Kernel32.dll\", SetLastError = true, CharSet = CharSet.Ansi)]\n        public static extern IntPtr GetProcAddress(IntPtr handle, string name);\n\n        [DllImport(\"Kernel32.dll\", SetLastError = true, CharSet = CharSet.Ansi)]\n        public static extern uint SetErrorMode(uint mode);\n\n        public static int TryGetDllDirectory(out string path)\n        {\n            char[] buffer;\n            uint requiredSize = 128;\n\n            do\n            {\n                buffer = new char[(int)requiredSize + 1];\n                requiredSize = GetDllDirectory((uint)buffer.Length - 1, buffer);\n            } while (requiredSize > 0 && requiredSize > buffer.Length);\n\n            if (requiredSize == 0)\n            {\n                path = null;\n                return Marshal.GetLastWin32Error();\n            }\n\n            path = new string(buffer, 0, (int)requiredSize);\n            return 0;\n        }\n    }\n\n    private struct DllDirectoryDisposable(string previousPath) : IDisposable\n    {\n        private bool isActive = true;\n\n        public void Dispose()\n        {\n            if (isActive)\n            {\n                if (!Kernel32.SetDllDirectory(previousPath))\n                {\n                    var error = Marshal.GetLastWin32Error();\n                    Report.Line(4, $\"Failed to reset DLL directory to '{previousPath}' (error: {error})\");\n                }\n                isActive = false;\n            }\n        }\n    }\n\n    /// <seealso cref=\"Aardvark.UseSetDllDirectory\"/>\n    private static DllDirectoryDisposable SetDllDirectory(string libraryPath)\n    {\n        if (!UseSetDllDirectory || GetOS() != OS.Win32)\n        {\n            return new DllDirectoryDisposable();\n        }\n\n        var directoryPath = PathUtils.HasDirectoryInformation(libraryPath) ? PathUtils.GetDirectoryNameSafe(libraryPath) : null;\n        if (string.IsNullOrEmpty(directoryPath))\n        {\n            return new DllDirectoryDisposable();\n        }\n\n        Report.Begin(4, $\"Setting DLL directory to '{directoryPath}'\");\n\n        try\n        {\n            var result = Kernel32.TryGetDllDirectory(out var previousPath);\n            if (result != 0)\n            {\n                Report.Line(4, $\"Failed to retrieve current DLL directory (error: {result})\");\n            }\n            else if (previousPath != null)\n            {\n                Report.Line(4, $\"Previous path: {previousPath}\");\n            }\n\n            if (Kernel32.SetDllDirectory(directoryPath))\n            {\n                return new DllDirectoryDisposable(previousPath);\n            }\n\n            var error = Marshal.GetLastWin32Error();\n            Report.Line(4, $\"Failed to set DLL directory to '{directoryPath}' (error: {error})\");\n        }\n        catch (Exception e)\n        {\n            Report.Line(4, $\"{e.GetType().Name}: {e.Message}\");\n        }\n        finally\n        {\n            Report.End(4);\n        }\n\n        return new DllDirectoryDisposable();\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Introspection/Platform/LdConfig.cs",
    "content": "namespace Aardvark.Base;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\n\npublic partial class Aardvark\n{\n    private static class LdConfig\n    {\n        private static readonly Lazy<Dictionary<string, string>> s_lookup = new(Load);\n\n        static List<string> Run(string path)\n        {\n            Report.Begin(3, $\"{path} -p\");\n\n            try\n            {\n                using var p = new Process();\n                p.StartInfo.FileName = path;\n                p.StartInfo.Arguments = \"-p\";\n                p.StartInfo.RedirectStandardOutput = true;\n                p.StartInfo.RedirectStandardError = true;\n                p.StartInfo.UseShellExecute = false;\n                p.StartInfo.CreateNoWindow = true;\n\n                var result = new List<string>();\n\n                p.ErrorDataReceived += (_, _) => { };\n                p.OutputDataReceived += (_, args) =>\n                {\n                    lock (result)\n                    {\n                        if (args.Data != null) result.Add(args.Data);\n                    }\n                };\n\n                p.Start();\n                p.BeginOutputReadLine();\n                p.BeginErrorReadLine();\n                p.WaitForExit();\n\n                if (p.ExitCode == 0)\n                {\n                    Report.End(3, \" - success\");\n                    return result;\n                }\n\n                var output = string.Join(Environment.NewLine, result);\n                Report.Line(3, output);\n\n            }\n            catch (Exception e)\n            {\n                Report.Line(3, $\"{e.GetType().Name}: {e.Message}\");\n            }\n\n            Report.End(3, \" - failed\");\n            return null;\n        }\n\n        static Dictionary<string, string> Load()\n        {\n            var result = new Dictionary<string, string>();\n            Report.BeginTimed(3, \"Building shared library location cache\");\n\n            try\n            {\n                string[] commands = [\"/usr/sbin/ldconfig\", \"/sbin/ldconfig\", \"ldconfig\"];\n\n                List<string> output = null;\n                foreach (var command in commands)\n                {\n                    output = Run(command);\n                    if (output != null) break;\n                }\n\n                var directories = new HashSet<string>();\n\n                if (output != null)\n                {\n                    foreach (var data in output)\n                    {\n                        var m = RegexPatterns.LdConfig.Entry?.Match(data);\n                        if (m is { Success: true })\n                        {\n                            var name = m.Groups[\"name\"].Value.ToLowerInvariant();\n                            var path = m.Groups[\"path\"].Value;\n\n                            var directory = PathUtils.GetDirectoryNameSafe(path);\n                            if (directory != null) directories.Add(directory);\n\n                            result[name] = path;\n                        }\n                    }\n                }\n\n                // Find files in library directories that are not in cache\n                foreach (var directory in directories)\n                {\n                    foreach (var path in DirectoryUtils.GetFilesSafe(directory))\n                    {\n                        var name = PathUtils.GetFileNameSafe(path)?.ToLowerInvariant();\n\n                        if (name != null && IsNativeLibrary(name) && !result.ContainsKey(name))\n                        {\n                            result[name] = path;\n                        }\n                    }\n                }\n            }\n            catch (Exception e)\n            {\n                Report.Warn($\"{e.GetType().Name}: {e.Message}\");\n            }\n\n            Report.Line(3, $\"Found {result.Count} libraries\");\n            Report.EndTimed(3);\n\n            return result;\n        }\n\n        public static ICollection<string> AllPaths => s_lookup.Value.Values;\n\n        public static bool TryGetPath(string name, out string path)\n        {\n            if (name != null) return s_lookup.Value.TryGetValue(name.ToLowerInvariant(), out path);\n            path = null;\n            return false;\n        }\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Introspection/Plugins.cs",
    "content": "namespace Aardvark.Base;\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Reflection.Metadata;\nusing System.Reflection.PortableExecutable;\nusing System.Runtime.Serialization;\nusing System.Xml;\nusing BundleReader = SingleFileExtractor.Core.ExecutableReader;\nusing BundleFileEntry = SingleFileExtractor.Core.FileEntry;\n\n#if NET8_0_OR_GREATER\nusing System.Runtime.Loader;\n#endif\n\n[AttributeUsage(AttributeTargets.Method)]\npublic class OnAardvarkInitAttribute : Attribute;\n\npublic partial class Aardvark\n{\n    private static class Plugins\n    {\n        #region Paths\n\n        private static readonly Lazy<string> s_pluginsCacheDirectory =\n            new (() =>\n            {\n                var path = Path.Combine(CachingProperties.CacheDirectory, \"Plugins\");\n\n                if (!Directory.Exists(path))\n                {\n                    Directory.CreateDirectory(path);\n                }\n\n                return path;\n            });\n\n        private static readonly Lazy<string> s_pluginsCacheFile =\n            new(() =>\n            {\n                Assembly entryAssembly = IntrospectionProperties.CurrentEntryAssembly;\n                string entryAssemblyName = entryAssembly?.GetName().Name ?? \"unknown\";\n                string entryAssemblyId = entryAssembly?.GetIdentifier(CachingProperties.PluginsCacheFileNaming) ?? \"unknown\";\n                string fileName = $\"{entryAssemblyName}_{entryAssemblyId}_plugins.xml\";\n\n                return Path.Combine(CacheDirectory, fileName);\n            });\n\n        /// <summary>\n        /// Returns the directory of the plugins cache files.\n        /// </summary>\n        public static string CacheDirectory => s_pluginsCacheDirectory.Value;\n\n        /// <summary>\n        /// Returns the path of the plugins cache file.\n        /// </summary>\n        public static string CacheFile => s_pluginsCacheFile.Value;\n\n        #endregion\n\n        #region Assembly Source\n\n        private abstract class AssemblySource\n        {\n            public abstract string Path { get; }\n\n            public abstract DateTime LastModified { get; }\n\n            public abstract Stream OpenRead();\n\n            public abstract Assembly Load();\n        }\n\n        private class FileAssemblySource(string path) : AssemblySource\n        {\n            public override string Path { get; } = path;\n\n            public override DateTime LastModified { get; } = FileUtils.GetLastWriteTimeSafe(path);\n\n            public override Stream OpenRead()\n                => File.OpenRead(Path);\n\n            public override Assembly Load()\n            {\n    #if NETCOREAPP3_1_OR_GREATER\n                // In .NET core Assembly.LoadFile uses a separate context, resulting in assemblies being\n                // potentially loaded multiple times -> leads to problems with static fields in unit tests\n                // See: https://github.com/dotnet/runtime/issues/39783\n                return AssemblyLoadContext.Default.LoadFromAssemblyPath(Path);\n    #else\n                return Assembly.LoadFile(Path);\n    #endif\n            }\n        }\n\n        private class BundleAssemblySource : AssemblySource\n        {\n            private readonly BundleFileEntry m_entry;\n\n            private byte[] m_data;\n\n            public override string Path { get; }\n\n            public override DateTime LastModified { get; }\n\n            public BundleAssemblySource(BundleFileEntry entry)\n            {\n                var bundlePath = entry.ExecutableReader.FileName;\n                Path = System.IO.Path.Combine(bundlePath, entry.RelativePath);\n                LastModified = FileUtils.GetLastWriteTimeSafe(bundlePath);\n                m_entry = entry;\n            }\n\n            private byte[] GetData()\n            {\n                if (m_data == null)\n                {\n                    using var s = m_entry.AsStream();\n                    using var ms = new MemoryStream(s.CanSeek ? (int)s.Length : 0);\n                    s.CopyTo(ms);\n                    m_data = ms.GetBuffer();\n                }\n\n                return m_data;\n            }\n\n            public override Stream OpenRead()\n                => new MemoryStream(GetData());\n\n            public override Assembly Load()\n            {\n    #if NETCOREAPP3_1_OR_GREATER\n                using var s = OpenRead();\n                return AssemblyLoadContext.Default.LoadFromStream(s);\n    #else\n                return Assembly.Load(GetData());\n    #endif\n            }\n        }\n\n        private class AssemblySourceList : List<AssemblySource>, IDisposable\n        {\n            private BundleReader m_reader;\n\n            public void AddDirectory(string path)\n            {\n                foreach (var p in DirectoryUtils.GetFilesSafe(path))\n                {\n                    Add(new FileAssemblySource(p));\n                }\n            }\n\n            public void AddBundle(BundleReader reader)\n            {\n                if (m_reader != null)\n                    throw new InvalidOperationException(\"Cannot add multiple bundles.\");\n\n                m_reader = reader;\n\n                if (reader.IsSingleFile && reader.IsSupported)\n                {\n                    foreach (var e in reader.Bundle.Files)\n                    {\n                        Add(new BundleAssemblySource(e));\n                    }\n                }\n                else\n                {\n                    Report.Warn($\"Cannot read bundle executable: {reader.FileName}\");\n                }\n            }\n\n            public void Dispose()\n            {\n                m_reader?.Dispose();\n                m_reader = null;\n            }\n        }\n\n        #endregion\n\n        #region Cache\n\n        /// <summary>\n        /// Cache containing information about whether an assembly is an Aardvark plugin.\n        /// </summary>\n        [CollectionDataContract(Name = \"Plugins\", ItemName = \"Assembly\", KeyName = \"Path\", ValueName = \"Data\")]\n        private class PluginCache : Dictionary<string, PluginCache.Data>\n        {\n            [DataContract]\n            public struct Data(DateTime lastModified, bool isPlugin)\n            {\n                /// <summary>\n                /// Modification time stamp of the assembly when the cache was created.\n                /// Used to determine if the cache has been invalidated.\n                /// </summary>\n                [DataMember(IsRequired = true)]\n                public DateTime LastModified = lastModified;\n\n                /// <summary>\n                /// Indicates whether the assembly is an Aardvark plugin.\n                /// </summary>\n                [DataMember(IsRequired = true)]\n                public bool IsPlugin = isPlugin;\n            }\n\n            private static readonly DataContractSerializer serializer = new(typeof(PluginCache));\n\n            // Note: Used in unit test via reflection\n            private static PluginCache Deserialize(Stream stream)\n                => (PluginCache)serializer.ReadObject(stream);\n\n            private void Serialize(Stream stream)\n            {\n                using var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true });\n                serializer.WriteObject(writer, this);\n            }\n\n            public static PluginCache ReadFromFile()\n            {\n                if (File.Exists(CacheFile))\n                {\n                    try\n                    {\n                        using var stream = new FileStream(CacheFile, FileMode.Open);\n                        var result = Deserialize(stream);\n                        Report.Line(3, $\"Loaded plugins cache file: {CacheFile}\");\n                        return result;\n                    }\n                    catch (Exception e)\n                    {\n                        Report.Line(3, $\"Could not load plugins cache file '{CacheFile}': {e.Message}\");\n                        return new PluginCache();\n                    }\n                }\n\n                Report.Line(3, $\"Using new plugins cache file: {CacheFile}\");\n                return new PluginCache();\n            }\n\n            public void WriteToFile()\n            {\n                if (string.IsNullOrEmpty(CacheFile))\n                {\n                    Report.Warn(\"Could not write plugins cache file since Aardvark.Plugins.CacheFile is null or empty\");\n                }\n                else\n                {\n                    try\n                    {\n                        if (File.Exists(CacheFile)) File.Delete(CacheFile);\n\n                        using var stream = new FileStream(CacheFile, FileMode.CreateNew);\n                        Serialize(stream);\n                    }\n                    catch(Exception e)\n                    {\n                        Report.Warn($\"Could not write plugins cache file '{CacheFile}': {e.Message}\");\n                    }\n                }\n            }\n        }\n\n        #endregion\n\n        private static unsafe bool ProbeForPlugin(Stream stream)\n        {\n            using var v = new PEReader(stream, PEStreamOptions.LeaveOpen);\n\n            if (v.PEHeaders.CorHeader == null || !v.HasMetadata) return false;\n            var data = v.GetMetadata();\n            var m = new MetadataReader(data.Pointer, data.Length);\n\n            var assdef = m.GetAssemblyDefinition();\n            foreach (var att in assdef.GetCustomAttributes())\n            {\n                var attDef = m.GetCustomAttribute(att);\n                if (attDef.Constructor.Kind == HandleKind.MemberReference)\n                {\n                    var hh = (MemberReferenceHandle)attDef.Constructor;\n                    var e = m.GetMemberReference(hh);\n                    var pp = e.Parent;\n                    if (pp.Kind == HandleKind.TypeReference)\n                    {\n                        var attType = m.GetTypeReference((TypeReferenceHandle)pp);\n                        var nameStr = m.GetString(attType.Name);\n                        var nsStr = m.GetString(attType.Namespace);\n                        if (nsStr == \"System.Runtime.Versioning\" && nameStr == \"TargetFrameworkAttribute\")\n                        {\n                            var reader = m.GetBlobReader(attDef.Value);\n                            if (reader.ReadUInt16() == 1)\n                            {\n                                var version = reader.ReadSerializedString();\n                                var match = version != null ? RegexPatterns.Assembly.TargetFramework.Match(version) : null;\n                                if (match is { Success: true })\n                                {\n                                    var fwName = match.Groups[\"name\"].Value;\n                                    var isLoadable = fwName is \".NETCoreApp\" or \".NETStandard\";\n                                    if (!isLoadable) return false;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            foreach (var t in m.TypeDefinitions)\n            {\n                var def = m.GetTypeDefinition(t);\n                foreach (var meth in def.GetMethods())\n                {\n                    var mdef = m.GetMethodDefinition(meth);\n                    var hasInitAtt =\n                        mdef.GetCustomAttributes().Any(att =>\n                        {\n                            var attDef = m.GetCustomAttribute(att);\n                            if (attDef.Constructor.Kind == HandleKind.MemberReference)\n                            {\n                                var hh = (MemberReferenceHandle)attDef.Constructor;\n                                var e = m.GetMemberReference(hh);\n                                var pp = e.Parent;\n                                if (pp.Kind == HandleKind.TypeReference)\n                                {\n                                    var attType = m.GetTypeReference((TypeReferenceHandle)pp);\n                                    var nameStr = m.GetString(attType.Name);\n                                    var nsStr = m.GetString(attType.Namespace);\n                                    return nsStr == \"Aardvark.Base\" && nameStr == nameof(OnAardvarkInitAttribute);\n                                }\n                                else return false;\n                            }\n                            else return false;\n                        });\n\n                    if (hasInitAtt) return true;\n                }\n            }\n\n            return false;\n        }\n\n        private static AssemblySourceList FindAssemblySources()\n        {\n            var sources = new AssemblySourceList();\n\n            try\n            {\n                var bundlePath = IntrospectionProperties.CurrentEntryBundle;\n\n                if (bundlePath != null)\n                {\n                    try\n                    {\n                        var reader = new BundleReader(bundlePath);\n                        sources.AddBundle(reader);\n                    }\n                    catch (Exception e)\n                    {\n                        Report.Warn($\"Failed to get assemblies from single file application: {e.Message}\");\n                    }\n                }\n                else\n                {\n                    var rootPath = IntrospectionProperties.CurrentEntryPath;\n                    sources.AddDirectory(rootPath);\n                }\n            }\n            catch (Exception e)\n            {\n                Report.Warn($\"Error while locating plugin assemblies: {e}\");\n            }\n\n            return sources;\n        }\n\n        private static bool IsPlugin(AssemblySource source, PluginCache oldCache, PluginCache newCache)\n        {\n            var ext = PathUtils.GetExtensionSafe(source.Path)?.ToLowerInvariant();\n            if (ext != \".dll\" &&  ext != \".exe\") return false;\n\n            var name = Path.GetFileNameWithoutExtension(source.Path);\n            if (!IntrospectionProperties.AssemblyFilter(name))\n            {\n                Report.Line(4, $\"[IsPlugin] Ignoring assembly {name} due to filter\");\n                return false;\n            }\n\n            bool isPlugin = false;\n            bool exists = oldCache.TryGetValue(source.Path, out PluginCache.Data cacheValue);\n\n            if (exists && source.LastModified <= cacheValue.LastModified)\n            {\n                Report.Line(4, $\"[IsPlugin] Cache found for: {source.Path}\");\n                isPlugin = cacheValue.IsPlugin;\n            }\n            else\n            {\n                if (exists)\n                    Report.Line(4, $\"[IsPlugin] Retrying to load because cache is outdated: {source.Path}\");\n                else\n                    Report.Line(4, $\"[IsPlugin] Retrying to load because not in cache: {source.Path}\");\n\n                try\n                {\n                    using var s = source.OpenRead();\n                    isPlugin = ProbeForPlugin(s);\n                }\n                catch (Exception e)\n                {\n                    Report.Line(4, $\"[IsPlugin] Error while probing assembly '{source.Path}': {e.Message}\");\n                }\n            }\n\n            if (isPlugin) Report.Line(3, $\"[IsPlugin] Plugin found: {source.Path}\");\n            newCache[source.Path] = new PluginCache.Data(source.LastModified, isPlugin);\n            return isPlugin;\n        }\n\n        internal static List<Assembly> Find()\n        {\n            var oldCache = PluginCache.ReadFromFile();\n            var newCache = new PluginCache();\n\n            using var sources = FindAssemblySources();\n            List<Assembly> assemblies = [];\n\n            try\n            {\n                foreach (var source in sources)\n                {\n                    try\n                    {\n                        if (!IsPlugin(source, oldCache, newCache))\n                            continue;\n\n                        var asm = source.Load();\n                        assemblies.Add(asm);\n                    }\n                    catch (Exception e)\n                    {\n                        Report.Warn($\"Failed to load plugin assembly '{source.Path}': {e.Message}\");\n                    }\n                }\n            }\n            finally\n            {\n                newCache.WriteToFile();\n            }\n\n            return assemblies;\n        }\n\n        internal static void Init()\n        {\n            Report.BeginTimed(\"Loading plugins\");\n\n            try\n            {\n                List<Assembly> plugins;\n\n                Report.BeginTimed(\"Finding and loading assemblies\");\n                try\n                {\n                    plugins = Find();\n                }\n                finally\n                {\n                    Report.EndTimed();\n                }\n\n                foreach (var assembly in plugins ?? [])\n                {\n                    HashSet<MethodInfo> initMethods = [];\n                    try\n                    {\n                        var query = Introspection.GetAllMethodsWithAttribute<OnAardvarkInitAttribute>(assembly);\n                        foreach (var q in query) initMethods.Add(q.Item1);\n                    }\n                    catch (Exception e)\n                    {\n                        Report.Warn($\"Failed to query initialization methods for assembly '{assembly}': {e.Message}\");\n                    }\n\n                    foreach (var mi in initMethods)\n                    {\n                        var parameters = mi.GetParameters();\n\n                        Report.BeginTimed($\"Initializing {mi.DeclaringType?.Name ?? mi.Name}\");\n\n                        try\n                        {\n                            if (parameters.Length == 0)\n                                mi.Invoke(null, null);\n                            else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(IEnumerable<Assembly>))\n                                mi.Invoke(null, [Introspection.AllAssemblies]);\n                            else\n                                Report.Warn($\"Strange Aardvark init method found: {mi}, should be IEnumberable<Assembly> -> unit or unit -> unit\");\n                        }\n                        catch (Exception e)\n                        {\n                            Report.Warn($\"Failed: {e}\");\n                        }\n                        finally\n                        {\n                            Report.End();\n                        }\n                    }\n                }\n            }\n            catch (Exception e)\n            {\n                Report.Warn($\"{e.GetType().Name} occurred while loading plugins: {e.Message}\");\n            }\n\n            Report.EndTimed();\n        }\n    }\n\n    /// <summary>\n    /// Returns the directory of the plugins cache files.\n    /// </summary>\n    public static string PluginsCacheDirectory => Plugins.CacheDirectory;\n\n    /// <summary>\n    /// Returns the path of the plugins cache file.\n    /// </summary>\n    public static string PluginsCacheFile => Plugins.CacheFile;\n\n    #region Obsolete\n\n    [Obsolete(\"Use PluginsCacheDirectory instead.\")]\n    public static string CacheDirectory => PluginsCacheDirectory;\n\n    [Obsolete(\"Use PluginsCacheFile instead.\")]\n    public string CacheFile = string.Empty;\n\n    [Obsolete]\n    public static List<Assembly> LoadPlugins() => Plugins.Find();\n\n    #endregion\n}"
  },
  {
    "path": "src/Aardvark.Base/Introspection/RegexPatterns.cs",
    "content": "using System.Runtime.InteropServices;\nusing System.Text.RegularExpressions;\n\nnamespace Aardvark.Base;\n\npublic partial class Aardvark\n{\n    private partial class RegexPatterns\n    {\n        public static partial class NativeLibrary\n        {\n            private const string EXT_WIN32 = @\"\\.dll$\";\n            private const string EXT_MACOS = @\"\\.dylib$\";\n            private const string EXT_LINUX = @\"\\.so(?:\\.[0-9]+)*$\";\n\n#if NET8_0_OR_GREATER\n            [GeneratedRegex(EXT_WIN32, RegexOptions.IgnoreCase)]\n            private static partial Regex _ExtensionWin32();\n            private static Regex ExtensionWin32 => _ExtensionWin32();\n\n            [GeneratedRegex(EXT_MACOS, RegexOptions.IgnoreCase)]\n            private static partial Regex _ExtensionMacOS();\n            private static Regex ExtensionMacOS => _ExtensionMacOS();\n\n            [GeneratedRegex(EXT_LINUX, RegexOptions.IgnoreCase)]\n            private static partial Regex _ExtensionLinux();\n            private static Regex ExtensionLinux => _ExtensionLinux();\n#else\n            private static Regex ExtensionWin32 { get; } = new(EXT_WIN32, RegexOptions.IgnoreCase | RegexOptions.Compiled);\n            private static Regex ExtensionMacOS { get; } = new(EXT_MACOS, RegexOptions.IgnoreCase | RegexOptions.Compiled);\n            private static Regex ExtensionLinux { get; } = new(EXT_LINUX, RegexOptions.IgnoreCase | RegexOptions.Compiled);\n#endif\n            public static Regex Extension\n                => GetOS() switch\n                {\n                    OS.Win32 => ExtensionWin32,\n                    OS.MacOS => ExtensionMacOS,\n                    _ => ExtensionLinux\n                };\n        }\n\n        public static partial class LdConfig\n        {\n            private const string ENTRY_X64   = @\"[ \\t]*(?<name>[^ \\t]+)[ \\t]+\\((?<libc>[^,]+)\\,x86-64[^\\)]*\\)[ \\t]*\\=\\>[ \\t]*(?<path>.*)\";\n            private const string ENTRY_ARM64 = @\"[ \\t]*(?<name>[^ \\t]+)[ \\t]+\\((?<libc>[^,]+)\\,arm-64[^\\)]*\\)[ \\t]*\\=\\>[ \\t]*(?<path>.*)\";\n\n#if NET8_0_OR_GREATER\n            [GeneratedRegex(ENTRY_X64, RegexOptions.IgnoreCase)]\n            private static partial Regex _EntryX64();\n            private static Regex EntryX64 => _EntryX64();\n\n            [GeneratedRegex(ENTRY_ARM64, RegexOptions.IgnoreCase)]\n            private static partial Regex _EntryArm64();\n            private static Regex EntryArm64 => _EntryArm64();\n#else\n            private static Regex EntryX64   { get; } = new(ENTRY_X64,   RegexOptions.IgnoreCase | RegexOptions.Compiled);\n            private static Regex EntryArm64 { get; } = new(ENTRY_ARM64, RegexOptions.IgnoreCase | RegexOptions.Compiled);\n#endif\n\n            public static Regex Entry\n                => RuntimeInformation.ProcessArchitecture switch\n                {\n                    Architecture.X64   => EntryX64,\n                    Architecture.Arm64 => EntryArm64,\n                    _ => null\n                };\n        }\n\n        public static partial class Assembly\n        {\n            private const string TARGET_FRAMEWORK = @\"^[ \\t]*(?<name>[\\.A-Za-z_0-9]+)[ \\t]*,[ \\t]*(v|V)ersion[ \\t]*=[ \\t]*(?<version>[\\.A-Za-z_0-9]+)$\";\n\n#if NET8_0_OR_GREATER\n            [GeneratedRegex(TARGET_FRAMEWORK)]\n            private static partial Regex _TargetFramework();\n            public static Regex TargetFramework => _TargetFramework();\n#else\n            public static Regex TargetFramework { get; } = new(TARGET_FRAMEWORK, RegexOptions.Compiled);\n#endif\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Introspection/Utilities.cs",
    "content": "namespace Aardvark.Base;\n\nusing System;\nusing System.IO;\nusing System.Reflection;\n\n#if !NET8_0_OR_GREATER\nusing System.Linq;\n#endif\n\ninternal static class FileUtils\n{\n    public static DateTime GetLastWriteTimeSafe(string path)\n    {\n        try\n        {\n            return File.Exists(path) ? File.GetLastWriteTimeUtc(path) : DateTime.MaxValue;\n        }\n        catch (Exception)\n        {\n            Report.Warn($\"Could not get write time for: {path}\");\n            return DateTime.MaxValue;\n        }\n    }\n}\n\ninternal static class DirectoryUtils\n{\n    public static string[] GetFilesSafe(string directory)\n    {\n        try\n        {\n            return Directory.Exists(directory) ? Directory.GetFiles(directory) : [];\n        }\n        catch (Exception e)\n        {\n            Report.Warn($\"Failed to enumerate files in '{directory}': {e.Message}\");\n            return [];\n        }\n    }\n}\n\ninternal static class PathUtils\n{\n    public static bool HasDirectoryInformation(string path)\n        => path != null && (path.Contains(Path.DirectorySeparatorChar) || path.Contains(Path.AltDirectorySeparatorChar));\n\n    public static string GetDirectoryNameSafe(string path)\n    {\n        try\n        {\n            return !string.IsNullOrEmpty(path) ? Path.GetDirectoryName(path) : null;\n        }\n        catch\n        {\n            return null;\n        }\n    }\n\n    public static string GetFileNameSafe(string path)\n    {\n        try\n        {\n            return Path.GetFileName(path);\n        }\n        catch\n        {\n            return null;\n        }\n    }\n\n    public static string GetExtensionSafe(string path)\n    {\n        try\n        {\n            return Path.GetExtension(path);\n        }\n        catch\n        {\n            return null;\n        }\n    }\n\n#if !NET8_0_OR_GREATER\n    // See: https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/PathInternal.Windows.cs\n    private static bool IsValidDriveChar(char value)\n        => (uint)((value | 0x20) - 'a') <= (uint)('z' - 'a');\n\n    private static bool IsDirectorySeparator(char c)\n        => c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar;\n\n    private static bool IsPartiallyQualified(string path)\n    {\n        if (path.Length < 2)\n        {\n            // It isn't fixed, it must be relative.  There is no way to specify a fixed\n            // path with one character (or less).\n            return true;\n        }\n\n        if (IsDirectorySeparator(path[0]))\n        {\n            // There is no valid way to specify a relative path with two initial slashes or\n            // \\? as ? isn't valid for drive relative paths and \\??\\ is equivalent to \\\\?\\\n            return !(path[1] == '?' || IsDirectorySeparator(path[1]));\n        }\n\n        // The only way to specify a fixed path that doesn't begin with two slashes\n        // is the drive, colon, slash format- i.e. C:\\\n        return !((path.Length >= 3)\n                 && (path[1] == Path.VolumeSeparatorChar)\n                 && IsDirectorySeparator(path[2])\n                 // To match old behavior we'll check the drive character for validity as the path is technically\n                 // not qualified if you don't have a valid drive. \"=:\\\" is the \"=\" file's default data stream.\n                 && IsValidDriveChar(path[0]));\n    }\n\n    public static bool IsPathFullyQualified(string path) => !IsPartiallyQualified(path);\n#endif\n}\n\ninternal static class AssemblyExtenions\n{\n    public static string GetLocationSafe(this Assembly assembly)\n    {\n        try\n        {\n            var location = assembly.Location;\n            return location.IsNullOrEmpty() ? null : location;\n        }\n        catch\n        {\n            return null;\n        }\n    }\n\n    public static bool HasLocation(this Assembly assembly)\n        => assembly.GetLocationSafe() != null;\n\n    public static DateTime GetLastWriteTimeSafe(this Assembly assembly)\n    {\n        var location = assembly?.GetLocationSafe() ?? IntrospectionProperties.CurrentEntryBundle;\n        return FileUtils.GetLastWriteTimeSafe(location);\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Json/JsonConverters.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Runtime.CompilerServices;\nusing System.Text.Json;\nusing System.Text.Json.Serialization;\n\nnamespace Aardvark.Base\n{\n    public static class JsonConverterExtensions\n    {\n        private const string FLOAT_NEGATIVE_INFINITY = \"-Infinity\";\n        private const string FLOAT_POSITIVE_INFINITY = \"Infinity\";\n        private const string FLOAT_NAN = \"NaN\";\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void WriteFloatValue(this Utf8JsonWriter writer, double x)\n        {\n            if (double.IsNegativeInfinity(x)) writer.WriteStringValue(FLOAT_NEGATIVE_INFINITY);\n            else if (double.IsPositiveInfinity(x)) writer.WriteStringValue(FLOAT_POSITIVE_INFINITY);\n            else if (double.IsNaN(x)) writer.WriteStringValue(FLOAT_NAN);\n            else writer.WriteNumberValue(x);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void WriteFloatValue(this Utf8JsonWriter writer, float x)\n        {\n            if (float.IsNegativeInfinity(x)) writer.WriteStringValue(FLOAT_NEGATIVE_INFINITY);\n            else if (float.IsPositiveInfinity(x)) writer.WriteStringValue(FLOAT_POSITIVE_INFINITY);\n            else if (float.IsNaN(x)) writer.WriteStringValue(FLOAT_NAN);\n            else writer.WriteNumberValue(x);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void WriteFloat(this Utf8JsonWriter writer, string propertyName, double x)\n        {\n            if (double.IsNegativeInfinity(x)) writer.WriteString(propertyName, FLOAT_NEGATIVE_INFINITY);\n            else if (double.IsPositiveInfinity(x)) writer.WriteString(propertyName, FLOAT_POSITIVE_INFINITY);\n            else if (double.IsNaN(x)) writer.WriteString(propertyName, FLOAT_NAN);\n            else writer.WriteNumber(propertyName, x);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void WriteFloat(this Utf8JsonWriter writer, string propertyName, float x)\n        {\n            if (float.IsNegativeInfinity(x)) writer.WriteString(propertyName, FLOAT_NEGATIVE_INFINITY);\n            else if (float.IsPositiveInfinity(x)) writer.WriteString(propertyName, FLOAT_POSITIVE_INFINITY);\n            else if (float.IsNaN(x)) writer.WriteString(propertyName, FLOAT_NAN);\n            else writer.WriteNumber(propertyName, x);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetDoubleExtended(this ref Utf8JsonReader reader)\n        {\n            if (reader.TokenType == JsonTokenType.Number)\n            {\n                return reader.GetDouble();\n            }\n            else\n            {\n                return reader.GetString() switch\n                {\n                    FLOAT_NEGATIVE_INFINITY => double.NegativeInfinity,\n                    FLOAT_POSITIVE_INFINITY => double.PositiveInfinity,\n                    FLOAT_NAN => double.NaN,\n                    _ => throw new Exception($\"Invalid floating point value {reader.GetString()}. Error 2b204bf5-8b7e-471b-bdcf-beda7281251f.\")\n                };\n            }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetSingleExtended(this ref Utf8JsonReader reader)\n        {\n            if (reader.TokenType == JsonTokenType.Number)\n            {\n                return reader.GetSingle();\n            }\n            else\n            {\n                return reader.GetString() switch\n                {\n                    FLOAT_NEGATIVE_INFINITY => float.NegativeInfinity,\n                    FLOAT_POSITIVE_INFINITY => float.PositiveInfinity,\n                    FLOAT_NAN => float.NaN,\n                    _ => throw new Exception($\"Invalid floating point value {reader.GetString()}. Error 403b381c-ef85-4a49-8aef-fd0cac8f0735.\")\n                };\n            }\n        }\n\n        #region Colors\n\n        public static void W(this Utf8JsonWriter writer, in C3b value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3b value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetByte();\n                reader.Read(); value.G = reader.GetByte();\n                reader.Read(); value.B = reader.GetByte();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.R);\n            writer.WriteFloatValue(value.G);\n            writer.WriteFloatValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetDoubleExtended();\n                reader.Read(); value.G = reader.GetDoubleExtended();\n                reader.Read(); value.B = reader.GetDoubleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.R);\n            writer.WriteFloatValue(value.G);\n            writer.WriteFloatValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetSingleExtended();\n                reader.Read(); value.G = reader.GetSingleExtended();\n                reader.Read(); value.B = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C3ui value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3ui value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetUInt32();\n                reader.Read(); value.G = reader.GetUInt32();\n                reader.Read(); value.B = reader.GetUInt32();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C3us value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3us value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetUInt16();\n                reader.Read(); value.G = reader.GetUInt16();\n                reader.Read(); value.B = reader.GetUInt16();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in C4b value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteNumberValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4b value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetByte();\n                reader.Read(); value.G = reader.GetByte();\n                reader.Read(); value.B = reader.GetByte();\n                reader.Read(); value.A = reader.GetByte();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C4d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.R);\n            writer.WriteFloatValue(value.G);\n            writer.WriteFloatValue(value.B);\n            writer.WriteFloatValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetDoubleExtended();\n                reader.Read(); value.G = reader.GetDoubleExtended();\n                reader.Read(); value.B = reader.GetDoubleExtended();\n                reader.Read(); value.A = reader.GetDoubleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C4f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.R);\n            writer.WriteFloatValue(value.G);\n            writer.WriteFloatValue(value.B);\n            writer.WriteFloatValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetSingleExtended();\n                reader.Read(); value.G = reader.GetSingleExtended();\n                reader.Read(); value.B = reader.GetSingleExtended();\n                reader.Read(); value.A = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C4ui value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteNumberValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4ui value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetUInt32();\n                reader.Read(); value.G = reader.GetUInt32();\n                reader.Read(); value.B = reader.GetUInt32();\n                reader.Read(); value.A = reader.GetUInt32();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C4us value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteNumberValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4us value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetUInt16();\n                reader.Read(); value.G = reader.GetUInt16();\n                reader.Read(); value.B = reader.GetUInt16();\n                reader.Read(); value.A = reader.GetUInt16();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in CieLabf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.L);\n            writer.WriteFloatValue(value.a);\n            writer.WriteFloatValue(value.b);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CieLabf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.L = reader.GetSingleExtended();\n                reader.Read(); value.a = reader.GetSingleExtended();\n                reader.Read(); value.b = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in CieLuvf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.L);\n            writer.WriteFloatValue(value.u);\n            writer.WriteFloatValue(value.v);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CieLuvf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.L = reader.GetSingleExtended();\n                reader.Read(); value.u = reader.GetSingleExtended();\n                reader.Read(); value.v = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in CieXYZf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CieXYZf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetSingleExtended();\n                reader.Read(); value.Y = reader.GetSingleExtended();\n                reader.Read(); value.Z = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in CieYxyf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.x);\n            writer.WriteFloatValue(value.y);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CieYxyf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Y = reader.GetSingleExtended();\n                reader.Read(); value.x = reader.GetSingleExtended();\n                reader.Read(); value.y = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in CMYKf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.C);\n            writer.WriteFloatValue(value.M);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.K);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CMYKf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.C = reader.GetSingleExtended();\n                reader.Read(); value.M = reader.GetSingleExtended();\n                reader.Read(); value.Y = reader.GetSingleExtended();\n                reader.Read(); value.K = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in HSLf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.H);\n            writer.WriteFloatValue(value.S);\n            writer.WriteFloatValue(value.L);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out HSLf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.H = reader.GetSingleExtended();\n                reader.Read(); value.S = reader.GetSingleExtended();\n                reader.Read(); value.L = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in HSVf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.H);\n            writer.WriteFloatValue(value.S);\n            writer.WriteFloatValue(value.V);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out HSVf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.H = reader.GetSingleExtended();\n                reader.Read(); value.S = reader.GetSingleExtended();\n                reader.Read(); value.V = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Yuvf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.u);\n            writer.WriteFloatValue(value.v);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Yuvf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Y = reader.GetSingleExtended();\n                reader.Read(); value.u = reader.GetSingleExtended();\n                reader.Read(); value.v = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Euclidean\n\n        public static void W(this Utf8JsonWriter writer, in Euclidean2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Rot\"); writer.W(value.Rot, options);\n            writer.WritePropertyName(\"Trans\"); writer.W(value.Trans, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Euclidean2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"rot\": case \"Rot\": reader.R(out result.Rot, options); break;\n                        case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Euclidean2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Rot\"); writer.W(value.Rot, options);\n            writer.WritePropertyName(\"Trans\"); writer.W(value.Trans, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Euclidean2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"rot\": case \"Rot\": reader.R(out result.Rot, options); break;\n                        case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Euclidean3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Rot\"); writer.W(value.Rot, options);\n            writer.WritePropertyName(\"Trans\"); writer.W(value.Trans, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Euclidean3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"rot\": case \"Rot\": reader.R(out result.Rot, options); break;\n                        case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Euclidean3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Rot\"); writer.W(value.Rot, options);\n            writer.WritePropertyName(\"Trans\"); writer.W(value.Trans, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Euclidean3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"rot\": case \"Rot\": reader.R(out result.Rot, options); break;\n                        case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Lines\n\n        public static void W(this Utf8JsonWriter writer, in Line2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"P0\"); writer.W(value.P0, options);\n            writer.WritePropertyName(\"P1\"); writer.W(value.P1, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Line2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                        case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Line2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"P0\"); writer.W(value.P0, options);\n            writer.WritePropertyName(\"P1\"); writer.W(value.P1, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Line2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                        case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Line3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"P0\"); writer.W(value.P0, options);\n            writer.WritePropertyName(\"P1\"); writer.W(value.P1, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Line3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                        case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Line3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"P0\"); writer.W(value.P0, options);\n            writer.WritePropertyName(\"P1\"); writer.W(value.P1, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Line3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                        case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Matrices\n\n        public static void W(this Utf8JsonWriter writer, in M22d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M22d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new double[4];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetDoubleExtended();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M22d(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M22f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M22f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new float[4];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetSingleExtended();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M22f(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M33d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M33d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new double[9];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetDoubleExtended();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M33d(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M33f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M33f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new float[9];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetSingleExtended();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M33f(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M44d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M44d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new double[16];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetDoubleExtended();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M44d(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M44f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M44f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new float[16];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetSingleExtended();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M44f(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Planes\n\n        public static void W(this Utf8JsonWriter writer, in Plane2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Normal\");\n            writer.W(value.Normal, options);\n            writer.WriteFloat(\"Distance\", value.Distance);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                        case \"distance\": case \"Distance\": result.Distance = reader.GetDoubleExtended(); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Plane2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Normal\");\n            writer.W(value.Normal, options);\n            writer.WriteFloat(\"Distance\", value.Distance);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                        case \"distance\": case \"Distance\": result.Distance = reader.GetSingleExtended(); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Plane3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Normal\");\n            writer.W(value.Normal, options);\n            writer.WriteFloat(\"Distance\", value.Distance);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                        case \"distance\": case \"Distance\": result.Distance = reader.GetDoubleExtended(); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Plane3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Normal\");\n            writer.W(value.Normal, options);\n            writer.WriteFloat(\"Distance\", value.Distance);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                        case \"distance\": case \"Distance\": result.Distance = reader.GetSingleExtended(); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, IEnumerable<Plane2d> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane2d[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<Plane2d>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    var x = default(Plane2d);\n                    reader.R(ref x, options);\n                    xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<Plane2f> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane2f[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<Plane2f>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    var x = default(Plane2f);\n                    reader.R(ref x, options);\n                    xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<Plane3d> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane3d[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<Plane3d>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    var x = default(Plane3d);\n                    reader.R(ref x, options);\n                    xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<Plane3f> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane3f[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<Plane3f>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    var x = default(Plane3f);\n                    reader.R(ref x, options);\n                    xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Vectors\n\n        public static void W(this Utf8JsonWriter writer, in Range1b value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Min);\n            writer.WriteNumberValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1b value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetByte();\n                reader.Read(); value.Max = reader.GetByte();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.Min);\n            writer.WriteFloatValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetDoubleExtended();\n                reader.Read(); value.Max = reader.GetDoubleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.Min);\n            writer.WriteFloatValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetSingleExtended();\n                reader.Read(); value.Max = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1i value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Min);\n            writer.WriteNumberValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1i value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetInt32();\n                reader.Read(); value.Max = reader.GetInt32();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1l value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Min);\n            writer.WriteNumberValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1l value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetInt64();\n                reader.Read(); value.Max = reader.GetInt64();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1s value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Min);\n            writer.WriteNumberValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1s value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetInt16();\n                reader.Read(); value.Max = reader.GetInt16();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1sb value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Min);\n            writer.WriteNumberValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1sb value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetSByte();\n                reader.Read(); value.Max = reader.GetSByte();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1ui value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Min);\n            writer.WriteNumberValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1ui value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetUInt32();\n                reader.Read(); value.Max = reader.GetUInt32();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1ul value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Min);\n            writer.WriteNumberValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1ul value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetUInt64();\n                reader.Read(); value.Max = reader.GetUInt64();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Range1us value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Min);\n            writer.WriteNumberValue(value.Max);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Range1us value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Min = reader.GetUInt16();\n                reader.Read(); value.Max = reader.GetUInt16();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Rays\n\n        public static void W(this Utf8JsonWriter writer, in Ray2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Origin\"); writer.W(value.Origin, options);\n            writer.WritePropertyName(\"Direction\"); writer.W(value.Direction, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Ray2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                        case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Ray2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Origin\"); writer.W(value.Origin, options);\n            writer.WritePropertyName(\"Direction\"); writer.W(value.Direction, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Ray2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                        case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Ray3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Origin\"); writer.W(value.Origin, options);\n            writer.WritePropertyName(\"Direction\"); writer.W(value.Direction, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Ray3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                        case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Ray3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Origin\"); writer.W(value.Origin, options);\n            writer.WritePropertyName(\"Direction\"); writer.W(value.Direction, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Ray3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                        case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Rotations, Quaternions\n\n        public static void W(this Utf8JsonWriter writer, in Rot2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.Angle);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Rot2d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Angle = reader.GetDoubleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Rot2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.Angle);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Rot2f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Angle = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Rot3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.W);\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Rot3d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.W = reader.GetDoubleExtended();\n                reader.Read(); value.X = reader.GetDoubleExtended();\n                reader.Read(); value.Y = reader.GetDoubleExtended();\n                reader.Read(); value.Z = reader.GetDoubleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Rot3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.W);\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Rot3f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.W = reader.GetSingleExtended();\n                reader.Read(); value.X = reader.GetSingleExtended();\n                reader.Read(); value.Y = reader.GetSingleExtended();\n                reader.Read(); value.Z = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in QuaternionD value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.W);\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out QuaternionD value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.W = reader.GetDoubleExtended();\n                reader.Read(); value.X = reader.GetDoubleExtended();\n                reader.Read(); value.Y = reader.GetDoubleExtended();\n                reader.Read(); value.Z = reader.GetDoubleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in QuaternionF value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.W);\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out QuaternionF value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.W = reader.GetSingleExtended();\n                reader.Read(); value.X = reader.GetSingleExtended();\n                reader.Read(); value.Y = reader.GetSingleExtended();\n                reader.Read(); value.Z = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Similarity\n\n        public static void W(this Utf8JsonWriter writer, in Similarity2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WriteFloat(\"Scale\", value.Scale);\n            writer.WritePropertyName(\"Euclidean\"); writer.W(value.Euclidean, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Similarity2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"scale\": case \"Scale\": result.Scale = reader.GetDoubleExtended(); break;\n                        case \"euclidean\": case \"Euclidean\": reader.R(ref result.Euclidean, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Similarity2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WriteFloat(\"Scale\", value.Scale);\n            writer.WritePropertyName(\"Euclidean\"); writer.W(value.Euclidean, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Similarity2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"scale\": case \"Scale\": result.Scale = reader.GetSingleExtended(); break;\n                        case \"euclidean\": case \"Euclidean\": reader.R(ref result.Euclidean, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Similarity3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WriteFloat(\"Scale\", value.Scale);\n            writer.WritePropertyName(\"Euclidean\"); writer.W(value.Euclidean, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Similarity3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"scale\": case \"Scale\": result.Scale = reader.GetDoubleExtended(); break;\n                        case \"euclidean\": case \"Euclidean\": reader.R(ref result.Euclidean, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Similarity3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WriteFloat(\"Scale\", value.Scale);\n            writer.WritePropertyName(\"Euclidean\"); writer.W(value.Euclidean, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Similarity3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"scale\": case \"Scale\": result.Scale = reader.GetSingleExtended(); break;\n                        case \"euclidean\": case \"Euclidean\": reader.R(ref result.Euclidean, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Vectors\n\n        public static void W(this Utf8JsonWriter writer, in V2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out V2d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetDoubleExtended();\n                reader.Read(); value.Y = reader.GetDoubleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in V2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out V2f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetSingleExtended();\n                reader.Read(); value.Y = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in V3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out V3d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetDoubleExtended();\n                reader.Read(); value.Y = reader.GetDoubleExtended();\n                reader.Read(); value.Z = reader.GetDoubleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in V3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteFloatValue(value.X);\n            writer.WriteFloatValue(value.Y);\n            writer.WriteFloatValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out V3f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetSingleExtended();\n                reader.Read(); value.Y = reader.GetSingleExtended();\n                reader.Read(); value.Z = reader.GetSingleExtended();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, IEnumerable<V2d> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref V2d[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<V2d>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    reader.R(out V2d x, options); xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<V2f> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref V2f[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<V2f>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    reader.R(out V2f x, options); xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<V3d> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref V3d[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<V3d>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    reader.R(out V3d x, options); xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<V3f> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref V3f[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<V3f>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    reader.R(out V3f x, options); xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n    }\n\n    //[JsonConverter(typeof(Converter))]\n    //public partial struct _Template\n    //{\n    //}\n\n    #region Affine\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Affine2d\n    {\n        private class Converter : JsonConverter<Affine2d>\n        {\n            public override Affine2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Affine2d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"linear\": case \"Linear\": reader.R(out result.Linear, options); break;\n                            case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Affine2d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Linear\");\n                writer.W(value.Linear, options);\n                writer.WritePropertyName(\"Trans\");\n                writer.W(value.Trans, options);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Affine2f\n    {\n        private class Converter : JsonConverter<Affine2f>\n        {\n            public override Affine2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Affine2f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"linear\": case \"Linear\": reader.R(out result.Linear, options); break;\n                            case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Affine2f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Linear\");\n                writer.W(value.Linear, options);\n                writer.WritePropertyName(\"Trans\");\n                writer.W(value.Trans, options);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Affine3d\n    {\n        private class Converter : JsonConverter<Affine3d>\n        {\n            public override Affine3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Affine3d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"linear\": case \"Linear\": reader.R(out result.Linear, options); break;\n                            case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Affine3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Linear\");\n                writer.W(value.Linear, options);\n                writer.WritePropertyName(\"Trans\");\n                writer.W(value.Trans, options);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Affine3f\n    {\n        private class Converter : JsonConverter<Affine3f>\n        {\n            public override Affine3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Affine3f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"linear\": case \"Linear\": reader.R(out result.Linear, options); break;\n                            case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Affine3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Linear\");\n                writer.W(value.Linear, options);\n                writer.WritePropertyName(\"Trans\");\n                writer.W(value.Trans, options);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Box[23][dfil]\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Box2d\n    {\n        private class Converter : JsonConverter<Box2d>\n        {\n            public override Box2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var min = new V2d();\n                    reader.Read(); min.X = reader.GetDoubleExtended();\n                    reader.Read(); min.Y = reader.GetDoubleExtended();\n                    var max = new V2d();\n                    reader.Read(); max.X = reader.GetDoubleExtended();\n                    reader.Read(); max.Y = reader.GetDoubleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Box2d(min, max);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Box2d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.Min.X);\n                writer.WriteFloatValue(value.Min.Y);\n                writer.WriteFloatValue(value.Max.X);\n                writer.WriteFloatValue(value.Max.Y);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Box2f\n    {\n        private class Converter : JsonConverter<Box2f>\n        {\n            public override Box2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var min = new V2f();\n                    reader.Read(); min.X = reader.GetSingleExtended();\n                    reader.Read(); min.Y = reader.GetSingleExtended();\n                    var max = new V2f();\n                    reader.Read(); max.X = reader.GetSingleExtended();\n                    reader.Read(); max.Y = reader.GetSingleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Box2f(min, max);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Box2f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.Min.X);\n                writer.WriteFloatValue(value.Min.Y);\n                writer.WriteFloatValue(value.Max.X);\n                writer.WriteFloatValue(value.Max.Y);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Box2i\n    {\n        private class Converter : JsonConverter<Box2i>\n        {\n            public override Box2i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var min = new V2i();\n                    reader.Read(); min.X = reader.GetInt32();\n                    reader.Read(); min.Y = reader.GetInt32();\n                    var max = new V2i();\n                    reader.Read(); max.X = reader.GetInt32();\n                    reader.Read(); max.Y = reader.GetInt32();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Box2i(min, max);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Box2i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.Min.X);\n                writer.WriteNumberValue(value.Min.Y);\n                writer.WriteNumberValue(value.Max.X);\n                writer.WriteNumberValue(value.Max.Y);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Box2l\n    {\n        private class Converter : JsonConverter<Box2l>\n        {\n            public override Box2l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var min = new V2l();\n                    reader.Read(); min.X = reader.GetInt64();\n                    reader.Read(); min.Y = reader.GetInt64();\n                    var max = new V2l();\n                    reader.Read(); max.X = reader.GetInt64();\n                    reader.Read(); max.Y = reader.GetInt64();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Box2l(min, max);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Box2l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.Min.X);\n                writer.WriteNumberValue(value.Min.Y);\n                writer.WriteNumberValue(value.Max.X);\n                writer.WriteNumberValue(value.Max.Y);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Box3d\n    {\n        private class Converter : JsonConverter<Box3d>\n        {\n            public override Box3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var min = new V3d();\n                    reader.Read(); min.X = reader.GetDoubleExtended();\n                    reader.Read(); min.Y = reader.GetDoubleExtended();\n                    reader.Read(); min.Z = reader.GetDoubleExtended();\n                    var max = new V3d();\n                    reader.Read(); max.X = reader.GetDoubleExtended();\n                    reader.Read(); max.Y = reader.GetDoubleExtended();\n                    reader.Read(); max.Z = reader.GetDoubleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Box3d(min, max);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Box3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.Min.X);\n                writer.WriteFloatValue(value.Min.Y);\n                writer.WriteFloatValue(value.Min.Z);\n                writer.WriteFloatValue(value.Max.X);\n                writer.WriteFloatValue(value.Max.Y);\n                writer.WriteFloatValue(value.Max.Z);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Box3f\n    {\n        private class Converter : JsonConverter<Box3f>\n        {\n            public override Box3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var min = new V3f();\n                    reader.Read(); min.X = reader.GetSingleExtended();\n                    reader.Read(); min.Y = reader.GetSingleExtended();\n                    reader.Read(); min.Z = reader.GetSingleExtended();\n                    var max = new V3f();\n                    reader.Read(); max.X = reader.GetSingleExtended();\n                    reader.Read(); max.Y = reader.GetSingleExtended();\n                    reader.Read(); max.Z = reader.GetSingleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Box3f(min, max);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Box3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.Min.X);\n                writer.WriteFloatValue(value.Min.Y);\n                writer.WriteFloatValue(value.Min.Z);\n                writer.WriteFloatValue(value.Max.X);\n                writer.WriteFloatValue(value.Max.Y);\n                writer.WriteFloatValue(value.Max.Z);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Box3i\n    {\n        private class Converter : JsonConverter<Box3i>\n        {\n            public override Box3i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var min = new V3i();\n                    reader.Read(); min.X = reader.GetInt32();\n                    reader.Read(); min.Y = reader.GetInt32();\n                    reader.Read(); min.Z = reader.GetInt32();\n                    var max = new V3i();\n                    reader.Read(); max.X = reader.GetInt32();\n                    reader.Read(); max.Y = reader.GetInt32();\n                    reader.Read(); max.Z = reader.GetInt32();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Box3i(min, max);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Box3i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.Min.X);\n                writer.WriteNumberValue(value.Min.Y);\n                writer.WriteNumberValue(value.Min.Z);\n                writer.WriteNumberValue(value.Max.X);\n                writer.WriteNumberValue(value.Max.Y);\n                writer.WriteNumberValue(value.Max.Z);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Box3l\n    {\n        private class Converter : JsonConverter<Box3l>\n        {\n            public override Box3l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var min = new V3l();\n                    reader.Read(); min.X = reader.GetInt64();\n                    reader.Read(); min.Y = reader.GetInt64();\n                    reader.Read(); min.Z = reader.GetInt64();\n                    var max = new V3l();\n                    reader.Read(); max.X = reader.GetInt64();\n                    reader.Read(); max.Y = reader.GetInt64();\n                    reader.Read(); max.Z = reader.GetInt64();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Box3l(min, max);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Box3l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.Min.X);\n                writer.WriteNumberValue(value.Min.Y);\n                writer.WriteNumberValue(value.Min.Z);\n                writer.WriteNumberValue(value.Max.X);\n                writer.WriteNumberValue(value.Max.Y);\n                writer.WriteNumberValue(value.Max.Z);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Capsules\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Capsule3d\n    {\n        private class Converter : JsonConverter<Capsule3d>\n        {\n            public override Capsule3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Capsule3d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                            case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetDoubleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Capsule3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"P0\");\n                writer.W(value.P0, options);\n                writer.WritePropertyName(\"P1\");\n                writer.W(value.P1, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Capsule3f\n    {\n        private class Converter : JsonConverter<Capsule3f>\n        {\n            public override Capsule3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Capsule3f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                            case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetSingleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Capsule3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"P0\");\n                writer.W(value.P0, options);\n                writer.WritePropertyName(\"P1\");\n                writer.W(value.P1, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n\n    }\n\n    #endregion\n\n    #region Cell, Cell2d\n\n    [JsonConverter(typeof(Converter))]\n    public readonly partial struct Cell2d\n    {\n        private class Converter : JsonConverter<Cell2d>\n        {\n            public override Cell2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); \n                    var x = reader.GetInt64();\n\n                    reader.Read(); \n                    if (reader.TokenType == JsonTokenType.EndArray)\n                    {\n                        if (x == int.MinValue) return Invalid;\n                        if (x < int.MinValue) throw new JsonException(\n                            $\"Expected exponent < int.MinValue, but found {x}. \" +\n                            $\"Error e4fa77f3-e47b-47a2-8be7-9414f9715826.\"\n                            );\n                        return new Cell2d(exponent: (int)x);\n                    }\n                    var y = reader.GetInt64();\n\n                    reader.Read(); \n                    var e = reader.GetInt32();\n\n                    reader.Read(); \n                    if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Cell2d(x, y, e);\n                }\n                else if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    var x = 0L; var y = 0L; var e = 0;\n                    bool hasX = false, hasY = false, hasE = false;\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read(); Debug.Assert(reader.TokenType == JsonTokenType.Number);\n                        switch (p)\n                        {\n                            case \"x\": case \"X\": if (hasX) throw new JsonException(); x = reader.GetInt64(); hasX = true; break;\n                            case \"y\": case \"Y\": if (hasY) throw new JsonException(); y = reader.GetInt64(); hasY = true; break;\n                            case \"e\": case \"E\": if (hasE) throw new JsonException(); e = reader.GetInt32(); hasE = true; break;\n                            default: throw new JsonException($\"Invalid property {p}. Error 09514e99-055a-4f0a-8573-0e10bcb29446.\");\n                        }\n                    }\n\n                    if (e == int.MinValue)\n                    {\n                        if (hasX || hasY) throw new JsonException();\n                        return Invalid;\n                    }\n\n                    if (hasX == false || hasY == false || hasE == false)\n                    {\n                        if (hasE && !hasX && !hasY)\n                        {\n                            return new Cell2d(e);\n                        }\n                        else\n                        {\n                            throw new JsonException(\"Error 41366f74-f340-4229-8a24-ed6689c8685f.\");\n                        }\n                    }\n\n                    return new Cell2d(x, y, e);\n                }\n                else if (reader.TokenType == JsonTokenType.String)\n                {\n                    var s = reader.GetString();\n                    reader.Read();\n                    return Parse(s);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Cell2d value, JsonSerializerOptions options)\n            {\n                if (value.IsCenteredAtOrigin || value.IsInvalid)\n                {\n                    writer.WriteStartArray();\n                    writer.WriteNumberValue(value.Exponent);\n                    writer.WriteEndArray();\n                }\n                else\n                {\n                    writer.WriteStartArray();\n                    writer.WriteNumberValue(value.X);\n                    writer.WriteNumberValue(value.Y);\n                    writer.WriteNumberValue(value.Exponent);\n                    writer.WriteEndArray();\n                }\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public readonly partial struct Cell\n    {\n        private class Converter : JsonConverter<Cell>\n        {\n            public override Cell Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read();\n                    var x = reader.GetInt64();\n\n                    reader.Read();\n                    if (reader.TokenType == JsonTokenType.EndArray)\n                    {\n                        if (x == int.MinValue) return Invalid;\n                        if (x < int.MinValue) throw new JsonException(\n                            $\"Expected exponent < int.MinValue, but found {x}. \" +\n                            $\"Error c9f85be5-2856-405b-adf2-c499ad8107b6.\"\n                            );\n                        return new Cell(exponent: (int)x);\n                    }\n                    var y = reader.GetInt64();\n\n                    reader.Read();\n                    var z = reader.GetInt64();\n\n                    reader.Read();\n                    var e = reader.GetInt32();\n\n                    reader.Read();\n                    if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new Cell(x, y, z, e);\n                }\n                else if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    var x = 0L; var y = 0L; var z = 0L; var e = 0;\n                    bool hasX = false, hasY = false, hasZ = false, hasE = false;\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read(); Debug.Assert(reader.TokenType == JsonTokenType.Number);\n                        switch (p)\n                        {\n                            case \"x\": case \"X\": if (hasX) throw new JsonException(); x = reader.GetInt64(); hasX = true; break;\n                            case \"y\": case \"Y\": if (hasY) throw new JsonException(); y = reader.GetInt64(); hasY = true; break;\n                            case \"z\": case \"Z\": if (hasZ) throw new JsonException(); z = reader.GetInt64(); hasZ = true; break;\n                            case \"e\": case \"E\": if (hasE) throw new JsonException(); e = reader.GetInt32(); hasE = true; break;\n                            default: throw new JsonException($\"Invalid property {p}. Error 17d72803-3cee-4451-9768-81bdb8374c72.\");\n                        }\n                    }\n\n                    if (e == int.MinValue)\n                    {\n                        if (hasX || hasY || hasZ) throw new JsonException();\n                        return Invalid;\n                    }\n\n                    if (hasX == false || hasY == false || hasZ == false || hasE == false)\n                    {\n                        if (hasE && !hasX && !hasY && !hasZ)\n                        {\n                            return new Cell(e);\n                        }\n                        else\n                        {\n                            throw new JsonException(\"Error e4446e9c-0dd2-481c-8082-901400b231fa.\");\n                        }\n                    }\n\n                    return new Cell(x, y, z, e);\n                }\n                else if (reader.TokenType == JsonTokenType.String)\n                {\n                    var s = reader.GetString();\n                    reader.Read();\n                    return Parse(s);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, Cell value, JsonSerializerOptions options)\n            {\n                if (value.IsCenteredAtOrigin || value.IsInvalid)\n                {\n                    writer.WriteStartArray();\n                    writer.WriteNumberValue(value.Exponent);\n                    writer.WriteEndArray();\n                }\n                else\n                {\n                    writer.WriteStartArray();\n                    writer.WriteNumberValue(value.X);\n                    writer.WriteNumberValue(value.Y);\n                    writer.WriteNumberValue(value.Z);\n                    writer.WriteNumberValue(value.Exponent);\n                    writer.WriteEndArray();\n                }\n            }\n        }\n    }\n\n    #endregion\n\n    #region Circles\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Circle2d\n    {\n        private class Converter : JsonConverter<Circle2d>\n        {\n            public override Circle2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Circle2d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"center\": case \"Center\": reader.R(out result.Center, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetDoubleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Circle2d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Center\");\n                writer.W(value.Center, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Circle2f\n    {\n        private class Converter : JsonConverter<Circle2f>\n        {\n            public override Circle2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Circle2f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"center\": case \"Center\": reader.R(out result.Center, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetSingleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Circle2f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Center\");\n                writer.W(value.Center, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Circle3d\n    {\n        private class Converter : JsonConverter<Circle3d>\n        {\n            public override Circle3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Circle3d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"center\": case \"Center\": reader.R(out result.Center, options); break;\n                            case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetDoubleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Circle3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Center\");\n                writer.W(value.Center, options);\n                writer.WritePropertyName(\"Normal\");\n                writer.W(value.Normal, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Circle3f\n    {\n        private class Converter : JsonConverter<Circle3f>\n        {\n            public override Circle3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Circle3f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"center\": case \"Center\": reader.R(out result.Center, options); break;\n                            case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetSingleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Circle3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Center\");\n                writer.W(value.Center, options);\n                writer.WritePropertyName(\"Normal\");\n                writer.W(value.Normal, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Colors\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C3b\n    {\n        private class Converter : JsonConverter<C3b>\n        {\n            public override C3b Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out C3b value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C3b value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C3d\n    {\n        private class Converter : JsonConverter<C3d>\n        {\n            public override C3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out C3d value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C3d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C3f\n    {\n        private class Converter : JsonConverter<C3f>\n        {\n            public override C3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { C3f value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C3f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C3ui\n    {\n        private class Converter : JsonConverter<C3ui>\n        {\n            public override C3ui Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { C3ui value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C3ui value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C3us\n    {\n        private class Converter : JsonConverter<C3us>\n        {\n            public override C3us Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { C3us value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C3us value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C4b\n    {\n        private class Converter : JsonConverter<C4b>\n        {\n            public override C4b Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { C4b value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C4b value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C4d\n    {\n        private class Converter : JsonConverter<C4d>\n        {\n            public override C4d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { C4d value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C4d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C4f\n    {\n        private class Converter : JsonConverter<C4f>\n        {\n            public override C4f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { C4f value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C4f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C4ui\n    {\n        private class Converter : JsonConverter<C4ui>\n        {\n            public override C4ui Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { C4ui value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C4ui value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct C4us\n    {\n        private class Converter : JsonConverter<C4us>\n        {\n            public override C4us Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { C4us value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, C4us value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct CieLabf\n    {\n        private class Converter : JsonConverter<CieLabf>\n        {\n            public override CieLabf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { CieLabf value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, CieLabf value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct CieLuvf\n    {\n        private class Converter : JsonConverter<CieLuvf>\n        {\n            public override CieLuvf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { CieLuvf value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, CieLuvf value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct CieXYZf\n    {\n        private class Converter : JsonConverter<CieXYZf>\n        {\n            public override CieXYZf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { CieXYZf value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, CieXYZf value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct CieYxyf\n    {\n        private class Converter : JsonConverter<CieYxyf>\n        {\n            public override CieYxyf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { CieYxyf value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, CieYxyf value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct CMYKf\n    {\n        private class Converter : JsonConverter<CMYKf>\n        {\n            public override CMYKf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { CMYKf value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, CMYKf value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct HSLf\n    {\n        private class Converter : JsonConverter<HSLf>\n        {\n            public override HSLf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { HSLf value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, HSLf value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct HSVf\n    {\n        private class Converter : JsonConverter<HSVf>\n        {\n            public override HSVf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { HSVf value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, HSVf value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Yuvf\n    {\n        private class Converter : JsonConverter<Yuvf>\n        {\n            public override Yuvf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Yuvf value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Yuvf value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    #endregion\n\n    #region Cones\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Cone3d\n    {\n        private class Converter : JsonConverter<Cone3d>\n        {\n            public override Cone3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Cone3d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                            case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                            case \"angle\": case \"Angle\": result.Angle = reader.GetDoubleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Cone3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Origin\");\n                writer.W(value.Origin, options);\n                writer.WritePropertyName(\"Direction\");\n                writer.W(value.Direction, options);\n                writer.WriteFloat(\"Angle\", value.Angle);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Cone3f\n    {\n        private class Converter : JsonConverter<Cone3f>\n        {\n            public override Cone3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Cone3f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                            case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                            case \"angle\": case \"Angle\": result.Angle = reader.GetSingleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Cone3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Origin\");\n                writer.W(value.Origin, options);\n                writer.WritePropertyName(\"Direction\");\n                writer.W(value.Direction, options);\n                writer.WriteFloat(\"Angle\", value.Angle);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Cylinder\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Cylinder3d\n    {\n        private class Converter : JsonConverter<Cylinder3d>\n        {\n            public override Cylinder3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Cylinder3d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                            case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetDoubleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Cylinder3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"P0\");\n                writer.W(value.P0, options);\n                writer.WritePropertyName(\"P1\");\n                writer.W(value.P1, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Cylinder3f\n    {\n        private class Converter : JsonConverter<Cylinder3f>\n        {\n            public override Cylinder3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Cylinder3f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                            case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetSingleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Cylinder3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"P0\");\n                writer.W(value.P0, options);\n                writer.WritePropertyName(\"P1\");\n                writer.W(value.P1, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Euclideans\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Euclidean2d\n    {\n        private class Converter : JsonConverter<Euclidean2d>\n        {\n            public override Euclidean2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Euclidean2d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Euclidean2d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Euclidean2f\n    {\n        private class Converter : JsonConverter<Euclidean2f>\n        {\n            public override Euclidean2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Euclidean2f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Euclidean2f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Euclidean3d\n    {\n        private class Converter : JsonConverter<Euclidean3d>\n        {\n            public override Euclidean3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Euclidean3d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Euclidean3d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Euclidean3f\n    {\n        private class Converter : JsonConverter<Euclidean3f>\n        {\n            public override Euclidean3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Euclidean3f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Euclidean3f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    #endregion\n\n    #region Hulls\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Hull2d\n    {\n        private class Converter : JsonConverter<Hull2d>\n        {\n            public override Hull2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Hull2d value = default; reader.R(ref value.PlaneArray, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Hull2d value, JsonSerializerOptions options)\n                => writer.W(value.PlaneArray, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Hull2f\n    {\n        private class Converter : JsonConverter<Hull2f>\n        {\n            public override Hull2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Hull2f value = default; reader.R(ref value.PlaneArray, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Hull2f value, JsonSerializerOptions options)\n                => writer.W(value.PlaneArray, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Hull3d\n    {\n        private class Converter : JsonConverter<Hull3d>\n        {\n            public override Hull3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Hull3d value = default; reader.R(ref value.PlaneArray, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Hull3d value, JsonSerializerOptions options)\n                => writer.W(value.PlaneArray, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Hull3f\n    {\n        private class Converter : JsonConverter<Hull3f>\n        {\n            public override Hull3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Hull3f value = default; reader.R(ref value.PlaneArray, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Hull3f value, JsonSerializerOptions options)\n                => writer.W(value.PlaneArray, options);\n        }\n    }\n\n    #endregion\n\n    #region Lines\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Line2d\n    {\n        private class Converter : JsonConverter<Line2d>\n        {\n            public override Line2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Line2d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Line2d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Line2f\n    {\n        private class Converter : JsonConverter<Line2f>\n        {\n            public override Line2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Line2f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Line2f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Line3d\n    {\n        private class Converter : JsonConverter<Line3d>\n        {\n            public override Line3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Line3d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Line3d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Line3f\n    {\n        private class Converter : JsonConverter<Line3f>\n        {\n            public override Line3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Line3f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Line3f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    #endregion\n\n    #region M[22|23|33|34|44][dfil]\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct M22d\n    {\n        private class Converter : JsonConverter<M22d>\n        {\n            public override M22d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new double[4];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetDoubleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M22d(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M22d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M22f\n    {\n        private class Converter : JsonConverter<M22f>\n        {\n            public override M22f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new float[4];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetSingleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M22f(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M22f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M22i\n    {\n        private class Converter : JsonConverter<M22i>\n        {\n            public override M22i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new int[4];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt32();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M22i(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M22i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M22l\n    {\n        private class Converter : JsonConverter<M22l>\n        {\n            public override M22l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new long[4];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt64();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M22l(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M22l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct M23d\n    {\n        private class Converter : JsonConverter<M23d>\n        {\n            public override M23d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new double[6];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetDoubleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M23d(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M23d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M23f\n    {\n        private class Converter : JsonConverter<M23f>\n        {\n            public override M23f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new float[6];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetSingleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M23f(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M23f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M23i\n    {\n        private class Converter : JsonConverter<M23i>\n        {\n            public override M23i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new int[6];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt32();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M23i(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M23i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M23l\n    {\n        private class Converter : JsonConverter<M23l>\n        {\n            public override M23l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new long[6];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt64();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M23l(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M23l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct M33d\n    {\n        private class Converter : JsonConverter<M33d>\n        {\n            public override M33d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new double[9];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetDoubleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M33d(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M33d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M33f\n    {\n        private class Converter : JsonConverter<M33f>\n        {\n            public override M33f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new float[9];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetSingleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M33f(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M33f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M33i\n    {\n        private class Converter : JsonConverter<M33i>\n        {\n            public override M33i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new int[9];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt32();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M33i(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M33i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M33l\n    {\n        private class Converter : JsonConverter<M33l>\n        {\n            public override M33l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new long[9];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt64();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M33l(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M33l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct M34d\n    {\n        private class Converter : JsonConverter<M34d>\n        {\n            public override M34d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new double[12];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetDoubleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M34d(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M34d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M34f\n    {\n        private class Converter : JsonConverter<M34f>\n        {\n            public override M34f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new float[12];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetSingleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M34f(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M34f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M34i\n    {\n        private class Converter : JsonConverter<M34i>\n        {\n            public override M34i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new int[12];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt32();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M34i(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M34i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M34l\n    {\n        private class Converter : JsonConverter<M34l>\n        {\n            public override M34l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new long[12];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt64();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M34l(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M34l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct M44d\n    {\n        private class Converter : JsonConverter<M44d>\n        {\n            public override M44d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new double[16];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetDoubleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M44d(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M44d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M44f\n    {\n        private class Converter : JsonConverter<M44f>\n        {\n            public override M44f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new float[16];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetSingleExtended();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M44f(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M44f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteFloatValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M44i\n    {\n        private class Converter : JsonConverter<M44i>\n        {\n            public override M44i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new int[16];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt32();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M44i(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M44i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n    [JsonConverter(typeof(Converter))]\n    public partial struct M44l\n    {\n        private class Converter : JsonConverter<M44l>\n        {\n            public override M44l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    var xs = new long[16];\n                    for (var i = 0; i < xs.Length; i++)\n                    {\n                        reader.Read();\n                        xs[i] = reader.GetInt64();\n                    }\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new M44l(xs);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, M44l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                var xs = value.ToArray();\n                for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Planes\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Plane2d\n    {\n        private class Converter : JsonConverter<Plane2d>\n        {\n            public override Plane2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Plane2d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Plane2d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Plane2f\n    {\n        private class Converter : JsonConverter<Plane2f>\n        {\n            public override Plane2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Plane2f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Plane2f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Plane3d\n    {\n        private class Converter : JsonConverter<Plane3d>\n        {\n            public override Plane3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Plane3d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Plane3d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Plane3f\n    {\n        private class Converter : JsonConverter<Plane3f>\n        {\n            public override Plane3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Plane3f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Plane3f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    #endregion\n\n    #region Polygons\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Polygon2d\n    {\n        private class Converter : JsonConverter<Polygon2d>\n        {\n            public override Polygon2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V2d[] value = default; reader.R(ref value, options); return new Polygon2d(value); }\n            public override void Write(Utf8JsonWriter writer, Polygon2d value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Polygon2f\n    {\n        private class Converter : JsonConverter<Polygon2f>\n        {\n            public override Polygon2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V2f[] value = default; reader.R(ref value, options); return new Polygon2f(value); }\n            public override void Write(Utf8JsonWriter writer, Polygon2f value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Polygon3d\n    {\n        private class Converter : JsonConverter<Polygon3d>\n        {\n            public override Polygon3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V3d[] value = default; reader.R(ref value, options); return new Polygon3d(value); }\n            public override void Write(Utf8JsonWriter writer, Polygon3d value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Polygon3f\n    {\n        private class Converter : JsonConverter<Polygon3f>\n        {\n            public override Polygon3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V3f[] value = default; reader.R(ref value, options); return new Polygon3f(value); }\n            public override void Write(Utf8JsonWriter writer, Polygon3f value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    #endregion\n\n    #region Quads\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Quad2d\n    {\n        private class Converter : JsonConverter<Quad2d>\n        {\n            public override Quad2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V2d[] value = default; reader.R(ref value, options); return new Quad2d(value); }\n            public override void Write(Utf8JsonWriter writer, Quad2d value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Quad2f\n    {\n        private class Converter : JsonConverter<Quad2f>\n        {\n            public override Quad2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V2f[] value = default; reader.R(ref value, options); return new Quad2f(value); }\n            public override void Write(Utf8JsonWriter writer, Quad2f value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Quad3d\n    {\n        private class Converter : JsonConverter<Quad3d>\n        {\n            public override Quad3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V3d[] value = default; reader.R(ref value, options); return new Quad3d(value); }\n            public override void Write(Utf8JsonWriter writer, Quad3d value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Quad3f\n    {\n        private class Converter : JsonConverter<Quad3f>\n        {\n            public override Quad3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V3f[] value = default; reader.R(ref value, options); return new Quad3f(value); }\n            public override void Write(Utf8JsonWriter writer, Quad3f value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    #endregion\n\n    #region Ranges\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1b\n    {\n        private class Converter : JsonConverter<Range1b>\n        {\n            public override Range1b Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1b value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1b value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1d\n    {\n        private class Converter : JsonConverter<Range1d>\n        {\n            public override Range1d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1d value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1f\n    {\n        private class Converter : JsonConverter<Range1f>\n        {\n            public override Range1f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1f value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1i\n    {\n        private class Converter : JsonConverter<Range1i>\n        {\n            public override Range1i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1i value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1i value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1l\n    {\n        private class Converter : JsonConverter<Range1l>\n        {\n            public override Range1l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1l value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1l value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1s\n    {\n        private class Converter : JsonConverter<Range1s>\n        {\n            public override Range1s Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1s value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1s value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1sb\n    {\n        private class Converter : JsonConverter<Range1sb>\n        {\n            public override Range1sb Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1sb value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1sb value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1ui\n    {\n        private class Converter : JsonConverter<Range1ui>\n        {\n            public override Range1ui Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1ui value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1ui value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1ul\n    {\n        private class Converter : JsonConverter<Range1ul>\n        {\n            public override Range1ul Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1ul value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1ul value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Range1us\n    {\n        private class Converter : JsonConverter<Range1us>\n        {\n            public override Range1us Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Range1us value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Range1us value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    #endregion\n\n    #region Rays\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Ray2d\n    {\n        private class Converter : JsonConverter<Ray2d>\n        {\n            public override Ray2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Ray2d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Ray2d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Ray2f\n    {\n        private class Converter : JsonConverter<Ray2f>\n        {\n            public override Ray2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Ray2f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Ray2f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Ray3d\n    {\n        private class Converter : JsonConverter<Ray3d>\n        {\n            public override Ray3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Ray3d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Ray3d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Ray3f\n    {\n        private class Converter : JsonConverter<Ray3f>\n        {\n            public override Ray3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Ray3f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Ray3f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    #endregion\n\n    #region Rotations, Quaternions\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Rot2d\n    {\n        private class Converter : JsonConverter<Rot2d>\n        {\n            public override Rot2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Rot2d value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Rot2d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Rot2f\n    {\n        private class Converter : JsonConverter<Rot2f>\n        {\n            public override Rot2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Rot2f value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Rot2f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Rot3d\n    {\n        private class Converter : JsonConverter<Rot3d>\n        {\n            public override Rot3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Rot3d value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Rot3d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Rot3f\n    {\n        private class Converter : JsonConverter<Rot3f>\n        {\n            public override Rot3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Rot3f value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Rot3f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct QuaternionD\n    {\n        private class Converter : JsonConverter<QuaternionD>\n        {\n            public override QuaternionD Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { QuaternionD value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, QuaternionD value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct QuaternionF\n    {\n        private class Converter : JsonConverter<QuaternionF>\n        {\n            public override QuaternionF Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { QuaternionF value = default; reader.R(out value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, QuaternionF value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    #endregion\n\n    #region Scales\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Scale2d\n    {\n        private class Converter : JsonConverter<Scale2d>\n        {\n            public override Scale2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out V2d value, options); return new Scale2d(value); }\n            public override void Write(Utf8JsonWriter writer, Scale2d value, JsonSerializerOptions options)\n                => writer.W(value.V, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Scale2f\n    {\n        private class Converter : JsonConverter<Scale2f>\n        {\n            public override Scale2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out V2f value, options); return new Scale2f(value); }\n            public override void Write(Utf8JsonWriter writer, Scale2f value, JsonSerializerOptions options)\n                => writer.W(value.V, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Scale3d\n    {\n        private class Converter : JsonConverter<Scale3d>\n        {\n            public override Scale3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out V3d value, options); return new Scale3d(value); }\n            public override void Write(Utf8JsonWriter writer, Scale3d value, JsonSerializerOptions options)\n                => writer.W(value.V, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Scale3f\n    {\n        private class Converter : JsonConverter<Scale3f>\n        {\n            public override Scale3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out V3f value, options); return new Scale3f(value); }\n            public override void Write(Utf8JsonWriter writer, Scale3f value, JsonSerializerOptions options)\n                => writer.W(value.V, options);\n        }\n    }\n\n    #endregion\n\n    #region Shifts\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Shift2d\n    {\n        private class Converter : JsonConverter<Shift2d>\n        {\n            public override Shift2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out V2d value, options); return new Shift2d(value); }\n            public override void Write(Utf8JsonWriter writer, Shift2d value, JsonSerializerOptions options)\n                => writer.W(value.V, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Shift2f\n    {\n        private class Converter : JsonConverter<Shift2f>\n        {\n            public override Shift2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out V2f value, options); return new Shift2f(value); }\n            public override void Write(Utf8JsonWriter writer, Shift2f value, JsonSerializerOptions options)\n                => writer.W(value.V, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Shift3d\n    {\n        private class Converter : JsonConverter<Shift3d>\n        {\n            public override Shift3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out V3d value, options); return new Shift3d(value); }\n            public override void Write(Utf8JsonWriter writer, Shift3d value, JsonSerializerOptions options)\n                => writer.W(value.V, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Shift3f\n    {\n        private class Converter : JsonConverter<Shift3f>\n        {\n            public override Shift3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { reader.R(out V3f value, options); return new Shift3f(value); }\n            public override void Write(Utf8JsonWriter writer, Shift3f value, JsonSerializerOptions options)\n                => writer.W(value.V, options);\n        }\n    }\n\n    #endregion\n\n    #region Similarities\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Similarity2d\n    {\n        private class Converter : JsonConverter<Similarity2d>\n        {\n            public override Similarity2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Similarity2d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Similarity2d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Similarity2f\n    {\n        private class Converter : JsonConverter<Similarity2f>\n        {\n            public override Similarity2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Similarity2f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Similarity2f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Similarity3d\n    {\n        private class Converter : JsonConverter<Similarity3d>\n        {\n            public override Similarity3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Similarity3d value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Similarity3d value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Similarity3f\n    {\n        private class Converter : JsonConverter<Similarity3f>\n        {\n            public override Similarity3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { Similarity3f value = default; reader.R(ref value, options); return value; }\n            public override void Write(Utf8JsonWriter writer, Similarity3f value, JsonSerializerOptions options)\n                => writer.W(value, options);\n        }\n    }\n\n    #endregion\n\n    #region Spheres\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Sphere3d\n    {\n        private class Converter : JsonConverter<Sphere3d>\n        {\n            public override Sphere3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Sphere3d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"center\": case \"Center\": reader.R(out result.Center, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetDoubleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Sphere3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Center\");\n                writer.W(value.Center, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Sphere3f\n    {\n        private class Converter : JsonConverter<Sphere3f>\n        {\n            public override Sphere3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Sphere3f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"center\": case \"Center\": reader.R(out result.Center, options); break;\n                            case \"radius\": case \"Radius\": result.Radius = reader.GetSingleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Sphere3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Center\");\n                writer.W(value.Center, options);\n                writer.WriteFloat(\"Radius\", value.Radius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Tori\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Torus3d\n    {\n        private class Converter : JsonConverter<Torus3d>\n        {\n            public override Torus3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Torus3d result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"position\": case \"Position\": reader.R(out result.Position, options); break;\n                            case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                            case \"majorRadius\": case \"MajorRadius\": result.MajorRadius = reader.GetDoubleExtended(); break;\n                            case \"minorRadius\": case \"MinorRadius\": result.MinorRadius = reader.GetDoubleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Torus3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Position\");\n                writer.W(value.Position, options);\n                writer.WritePropertyName(\"Direction\");\n                writer.W(value.Direction, options);\n                writer.WriteFloat(\"MajorRadius\", value.MajorRadius);\n                writer.WriteFloat(\"MinorRadius\", value.MinorRadius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Torus3f\n    {\n        private class Converter : JsonConverter<Torus3f>\n        {\n            public override Torus3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartObject)\n                {\n                    Torus3f result = default;\n\n                    while (reader.Read())\n                    {\n                        if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                        Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                        var p = reader.GetString();\n                        reader.Read();\n                        switch (p)\n                        {\n                            case \"position\": case \"Position\": reader.R(out result.Position, options); break;\n                            case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                            case \"majorRadius\": case \"MajorRadius\": result.MajorRadius = reader.GetSingleExtended(); break;\n                            case \"minorRadius\": case \"MinorRadius\": result.MinorRadius = reader.GetSingleExtended(); break;\n                            default: throw new JsonException($\"Invalid property {p}.\");\n                        }\n                    }\n\n                    return result;\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n            public override void Write(Utf8JsonWriter writer, Torus3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartObject();\n                writer.WritePropertyName(\"Position\");\n                writer.W(value.Position, options);\n                writer.WritePropertyName(\"Direction\");\n                writer.W(value.Direction, options);\n                writer.WriteFloat(\"MajorRadius\", value.MajorRadius);\n                writer.WriteFloat(\"MinorRadius\", value.MinorRadius);\n                writer.WriteEndObject();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Trafos\n\n    [JsonConverter(typeof(Converter))]\n    public readonly partial struct Trafo2d\n    {\n        private class Converter : JsonConverter<Trafo2d>\n        {\n            public override Trafo2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                M33d forward;\n                M33d backward;\n                reader.Read(); if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException();\n                reader.R(out forward, options);\n                reader.Read(); if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException();\n                reader.R(out backward, options);\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                return new Trafo2d(forward, backward);\n            }\n            public override void Write(Utf8JsonWriter writer, Trafo2d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.W(value.Forward, options);\n                writer.W(value.Backward, options);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public readonly partial struct Trafo2f\n    {\n        private class Converter : JsonConverter<Trafo2f>\n        {\n            public override Trafo2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                M33f forward;\n                M33f backward;\n                reader.Read(); if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException();\n                reader.R(out forward, options);\n                reader.Read(); if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException();\n                reader.R(out backward, options);\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                return new Trafo2f(forward, backward);\n            }\n            public override void Write(Utf8JsonWriter writer, Trafo2f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.W(value.Forward, options);\n                writer.W(value.Backward, options);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public readonly partial struct Trafo3d\n    {\n        private class Converter : JsonConverter<Trafo3d>\n        {\n            public override Trafo3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                M44d forward;\n                M44d backward;\n                reader.Read(); if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException();\n                reader.R(out forward, options);\n                reader.Read(); if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException();\n                reader.R(out backward, options);\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                return new Trafo3d(forward, backward);\n            }\n            public override void Write(Utf8JsonWriter writer, Trafo3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.W(value.Forward, options);\n                writer.W(value.Backward, options);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public readonly partial struct Trafo3f\n    {\n        private class Converter : JsonConverter<Trafo3f>\n        {\n            public override Trafo3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                M44f forward;\n                M44f backward;\n                reader.Read(); if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException();\n                reader.R(out forward, options);\n                reader.Read(); if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException();\n                reader.R(out backward, options);\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                return new Trafo3f(forward, backward);\n            }\n            public override void Write(Utf8JsonWriter writer, Trafo3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.W(value.Forward, options);\n                writer.W(value.Backward, options);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    #endregion\n\n    #region Triangles\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Triangle2d\n    {\n        private class Converter : JsonConverter<Triangle2d>\n        {\n            public override Triangle2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V2d[] value = default; reader.R(ref value, options); return new Triangle2d(value); }\n            public override void Write(Utf8JsonWriter writer, Triangle2d value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Triangle2f\n    {\n        private class Converter : JsonConverter<Triangle2f>\n        {\n            public override Triangle2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V2f[] value = default; reader.R(ref value, options); return new Triangle2f(value); }\n            public override void Write(Utf8JsonWriter writer, Triangle2f value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Triangle3d\n    {\n        private class Converter : JsonConverter<Triangle3d>\n        {\n            public override Triangle3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V3d[] value = default; reader.R(ref value, options); return new Triangle3d(value); }\n            public override void Write(Utf8JsonWriter writer, Triangle3d value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct Triangle3f\n    {\n        private class Converter : JsonConverter<Triangle3f>\n        {\n            public override Triangle3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            { V3f[] value = default; reader.R(ref value, options); return new Triangle3f(value); }\n            public override void Write(Utf8JsonWriter writer, Triangle3f value, JsonSerializerOptions options)\n                => writer.W(value.Points, options);\n        }\n    }\n\n    #endregion\n\n    #region V[234][dfil]\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V2d\n    {\n        private class Converter : JsonConverter<V2d>\n        {\n            public override V2d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetDoubleExtended();\n                    reader.Read(); var y = reader.GetDoubleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V2d(x, y);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V2d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.X);\n                writer.WriteFloatValue(value.Y);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V2f\n    {\n        private class Converter : JsonConverter<V2f>\n        {\n            public override V2f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetSingleExtended();\n                    reader.Read(); var y = reader.GetSingleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V2f(x, y);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V2f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.X);\n                writer.WriteFloatValue(value.Y);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V2i\n    {\n        private class Converter : JsonConverter<V2i>\n        {\n            public override V2i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetInt32();\n                    reader.Read(); var y = reader.GetInt32();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V2i(x, y);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V2i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.X);\n                writer.WriteNumberValue(value.Y);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V2l\n    {\n        private class Converter : JsonConverter<V2l>\n        {\n            public override V2l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetInt64();\n                    reader.Read(); var y = reader.GetInt64();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V2l(x, y);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V2l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.X);\n                writer.WriteNumberValue(value.Y);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V3d\n    {\n        private class Converter : JsonConverter<V3d>\n        {\n            public override V3d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetDoubleExtended();\n                    reader.Read(); var y = reader.GetDoubleExtended();\n                    reader.Read(); var z = reader.GetDoubleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V3d(x, y, z);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V3d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.X);\n                writer.WriteFloatValue(value.Y);\n                writer.WriteFloatValue(value.Z);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V3f\n    {\n        private class Converter : JsonConverter<V3f>\n        {\n            public override V3f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetSingleExtended();\n                    reader.Read(); var y = reader.GetSingleExtended();\n                    reader.Read(); var z = reader.GetSingleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V3f(x, y, z);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V3f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.X);\n                writer.WriteFloatValue(value.Y);\n                writer.WriteFloatValue(value.Z);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V3i\n    {\n        private class Converter : JsonConverter<V3i>\n        {\n            public override V3i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetInt32();\n                    reader.Read(); var y = reader.GetInt32();\n                    reader.Read(); var z = reader.GetInt32();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V3i(x, y, z);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V3i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.X);\n                writer.WriteNumberValue(value.Y);\n                writer.WriteNumberValue(value.Z);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V3l\n    {\n        private class Converter : JsonConverter<V3l>\n        {\n            public override V3l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetInt64();\n                    reader.Read(); var y = reader.GetInt64();\n                    reader.Read(); var z = reader.GetInt64();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V3l(x, y, z);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V3l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.X);\n                writer.WriteNumberValue(value.Y);\n                writer.WriteNumberValue(value.Z);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V4d\n    {\n        private class Converter : JsonConverter<V4d>\n        {\n            public override V4d Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetDoubleExtended();\n                    reader.Read(); var y = reader.GetDoubleExtended();\n                    reader.Read(); var z = reader.GetDoubleExtended();\n                    reader.Read(); var w = reader.GetDoubleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V4d(x, y, z, w);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V4d value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.X);\n                writer.WriteFloatValue(value.Y);\n                writer.WriteFloatValue(value.Z);\n                writer.WriteFloatValue(value.W);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V4f\n    {\n        private class Converter : JsonConverter<V4f>\n        {\n            public override V4f Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetSingleExtended();\n                    reader.Read(); var y = reader.GetSingleExtended();\n                    reader.Read(); var z = reader.GetSingleExtended();\n                    reader.Read(); var w = reader.GetSingleExtended();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V4f(x, y, z, w);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V4f value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteFloatValue(value.X);\n                writer.WriteFloatValue(value.Y);\n                writer.WriteFloatValue(value.Z);\n                writer.WriteFloatValue(value.W);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V4i\n    {\n        private class Converter : JsonConverter<V4i>\n        {\n            public override V4i Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetInt32();\n                    reader.Read(); var y = reader.GetInt32();\n                    reader.Read(); var z = reader.GetInt32();\n                    reader.Read(); var w = reader.GetInt32();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V4i(x, y, z, w);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V4i value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.X);\n                writer.WriteNumberValue(value.Y);\n                writer.WriteNumberValue(value.Z);\n                writer.WriteNumberValue(value.W);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    [JsonConverter(typeof(Converter))]\n    public partial struct V4l\n    {\n        private class Converter : JsonConverter<V4l>\n        {\n            public override V4l Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n            {\n                if (reader.TokenType == JsonTokenType.StartArray)\n                {\n                    reader.Read(); var x = reader.GetInt64();\n                    reader.Read(); var y = reader.GetInt64();\n                    reader.Read(); var z = reader.GetInt64();\n                    reader.Read(); var w = reader.GetInt64();\n                    reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                    return new V4l(x, y, z, w);\n                }\n                else\n                {\n                    throw new JsonException();\n                }\n            }\n\n            public override void Write(Utf8JsonWriter writer, V4l value, JsonSerializerOptions options)\n            {\n                writer.WriteStartArray();\n                writer.WriteNumberValue(value.X);\n                writer.WriteNumberValue(value.Y);\n                writer.WriteNumberValue(value.Z);\n                writer.WriteNumberValue(value.W);\n                writer.WriteEndArray();\n            }\n        }\n    }\n\n    #endregion\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Adler32.cs",
    "content": "﻿using System;\nusing System.IO;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Computes Adler32 checksum for a stream of data. An Adler32\n    /// checksum is not as reliable as a CRC32 checksum, but a lot faster to\n    /// compute.\n    /// \n    /// The specification for Adler32 may be found in RFC 1950.\n    /// \n    /// \n    /// From that document:\n    /// \n    ///  \"ADLER32 (Adler-32 checksum)\n    ///   This contains a checksum value of the uncompressed data\n    ///   (excluding any dictionary data) computed according to Adler-32\n    ///   algorithm. This algorithm is a 32-bit extension and improvement\n    ///   of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073\n    ///   standard.\n    /// \n    ///   Adler-32 is composed of two sums accumulated per byte: s1 is\n    ///   the sum of all bytes, s2 is the sum of all s1 values. Both sums\n    ///   are done modulo 65521. s1 is initialized to 1, s2 to zero.  The\n    ///   Adler-32 checksum is stored as s2*65536 + s1 in most-\n    ///   significant-byte first (network) order.\"\n    /// \n    ///  \"8.2. The Adler-32 algorithm\n    /// \n    ///    The Adler-32 algorithm is much faster than the CRC32 algorithm yet\n    ///    still provides an extremely low probability of undetected errors.\n    /// \n    ///    The modulo on unsigned long accumulators can be delayed for 5552\n    ///    bytes, so the modulo operation time is negligible.  If the bytes\n    ///    are a, b, c, the second sum is 3a + 2b + c + 3, and so is position\n    ///    and order sensitive, unlike the first sum, which is just a\n    ///    checksum.  That 65521 is prime is important to avoid a possible\n    ///    large class of two-byte errors that leave the check unchanged.\n    ///    (The Fletcher checksum uses 255, which is not prime and which also\n    ///    makes the Fletcher check insensitive to single byte changes 0 -\n    ///    255.)\n    /// \n    ///    The sum s1 is initialized to 1 instead of zero to make the length\n    ///    of the sequence part of s2, so that the length does not have to be\n    ///    checked separately. (Any sequence of zeroes has a Fletcher\n    ///    checksum of zero.)\"\n    /// </summary>\n    public sealed class Adler32\n    {\n        private const uint BASE = 65521;\n        private uint m_checksum;\n\n        /// <summary>\n        /// Creates a new instance of the Adler32 class.\n        /// The checksum starts off with a value of 1.\n        /// </summary>\n        public Adler32()\n        {\n            Reset();\n        }\n\n        /// <summary>\n        /// Returns the Adler32 data checksum computed so far.\n        /// </summary>\n        public uint Checksum\n        {\n            get { return m_checksum; }\n        }\n\n        /// <summary>\n        /// Resets the Adler32 checksum to the initial value.\n        /// </summary>\n        public void Reset()\n        {\n            m_checksum = 1;\n        }\n\n        /// <summary>\n        /// Updates the checksum with the byte b.\n        /// </summary>\n        public void Update(byte bval)\n        {\n            uint s1 = m_checksum & 0xFFFF;\n            uint s2 = m_checksum >> 16;\n\n            s1 = (s1 + ((uint)bval & 0xFF)) % BASE;\n            s2 = (s1 + s2) % BASE;\n\n            m_checksum = (s2 << 16) + s1;\n        }\n\n        /// <summary>\n        /// Updates the checksum with the bytes taken from the stream.\n        /// </summary>\n        public void Update(Stream stream)\n        {\n            if (stream == null)\n            {\n                throw new ArgumentNullException(nameof(stream));\n            }\n\n            int count;\n            var buffer = new byte[1024];\n            while ((count = stream.Read(buffer, 0, 1024)) > 0)\n                Update(buffer, 0, count);\n        }\n\n        /// <summary>\n        /// Updates the checksum with the bytes taken from the array.\n        /// </summary>\n        public void Update(byte[] buffer)\n        {\n            if (buffer == null)\n            {\n                throw new ArgumentNullException(nameof(buffer));\n            }\n\n            Update(buffer, 0, buffer.Length);\n        }\n\n        /// <summary>\n        /// Updates the checksum with the bytes taken from the array.\n        /// </summary>\n        public void Update(byte[] buffer, int offset, int length)\n        {\n            if (buffer == null)\n            {\n                throw new ArgumentNullException(nameof(buffer));\n            }\n\n            if (offset < 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(offset));\n            }\n\n            if (length < 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(length));\n            }\n\n            if (offset > buffer.Length - length)\n            {\n                throw new ArgumentOutOfRangeException();\n            }\n\n            uint s1 = m_checksum & 0xFFFF;\n            uint s2 = m_checksum >> 16;\n\n            while (length > 0)\n            {\n                // We can defer the modulo operation:\n                // s1 maximally grows from 65521 to 65521 + 255 * 3800\n                // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31\n                int n = 3800;\n                if (n > length)  n = length;\n\n                length -= n;\n\n                while (--n >= 0)\n                {\n                    s1 = s1 + (uint)(buffer[offset++] & 0xFF);\n                    s2 = s2 + s1;\n                }\n\n                s1 %= BASE;\n                s2 %= BASE;\n            }\n            m_checksum = (s2 << 16) | s1;\n\n        }\n        \n        \n        /// <summary>\n        /// Updates the checksum with the bytes taken from the array.\n        /// </summary>\n        public void Update(ReadOnlySpan<byte> buffer)\n        {\n            if (buffer == null)\n            {\n                throw new ArgumentNullException(\"buffer\");\n            }\n\n            uint s1 = m_checksum & 0xFFFF;\n            uint s2 = m_checksum >> 16;\n            var offset = 0;\n            var length = buffer.Length;\n            \n            while (length > 0)\n            {\n                // We can defer the modulo operation:\n                // s1 maximally grows from 65521 to 65521 + 255 * 3800\n                // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31\n                int n = 3800;\n                if (n > length)  n = length;\n\n                length -= n;\n\n                while (--n >= 0)\n                {\n                    s1 = s1 + (uint)(buffer[offset++] & 0xFF);\n                    s2 = s2 + s1;\n                }\n\n                s1 %= BASE;\n                s2 %= BASE;\n            }\n            m_checksum = (s2 << 16) | s1;\n\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/AliasTable_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n\n    /// <summary>\n    /// Walker 1974: https://en.wikipedia.org/wiki/Alias_method\n    /// Algorithm to sample a discrete probability distribution function (PDF) in O(1).\n    /// The PDF does not need to be normalized, but the normalization factor \"1/Sum(pdf)\" needs to be supplied.\n    /// </summary>\n    public class AliasTableF\n    {\n        float[] _probablity; // U[i]\n        int[] _alias;         // K[i]\n\n        public float[] U => _probablity;\n        public int[] K => _alias;\n\n        /// <summary>\n        /// Creates an alias table from a genral PDF that does not integrate to 1.\n        /// The normalization factor will be calculated for the construction.\n        /// </summary>\n        public AliasTableF FromPdf(float[] pdf, IRandomUniform rnd = null)\n        {\n            return new AliasTableF(pdf, 1 / pdf.Sum(), rnd);\n        }\n\n        /// <summary>\n        /// Creates an alias table from an already normalized PDF (integrates to 1).\n        /// </summary>\n        public AliasTableF FromNormalizedPdf(float[] pdf, IRandomUniform rnd = null)\n        {\n            return new AliasTableF(pdf, 1, rnd);\n        }\n\n        /// <summary>\n        /// Create an alias table from a PDf and its normalization factor: 1.0 / Sum(pdf)\n        /// </summary>\n        public AliasTableF(float[] pdf, float pdfNorm, IRandomUniform rnd = null)\n        {\n            var n = pdf.Length;\n            _probablity = new float[n];\n            _alias = new int[n];\n            Update(pdf, pdfNorm, rnd);\n        }\n\n        /// <summary>\n        /// Updates the alias table with the given PDF and its norm.\n        /// The length of the PDF is expected to match the length of AliasTable.\n        /// </summary>\n        public void Update(float[] pdf, float pdfNorm, IRandomUniform rnd = null)\n        {\n            if (pdf.Length != _alias.Length) throw new ArgumentException(\"The length of the PDF does not match the length of the AliasTable!\");\n\n            if (rnd == null) rnd = new RandomSystem();\n\n            var n = pdf.Length;\n            var overfull = new List<int>(n);\n            var underfull = new List<int>(n);\n\n            for (int i = 0; i < n; i++)\n            {\n                var ui = pdf[i] * pdfNorm * n;\n                _probablity[i] = ui;\n                if (ui > 1) overfull.Add(i);\n                else if (ui < 1) underfull.Add(i);\n            }\n\n            while (overfull.Count > 0 && underfull.Count > 0)\n            {\n                var ii = rnd.UniformInt(overfull.Count);  // random overfull\n                var jj = rnd.UniformInt(underfull.Count); // random underfull\n                var ri = overfull[ii];\n                var rj = underfull[jj];\n                underfull[jj] = underfull[underfull.Count - 1];\n                underfull.RemoveAt(underfull.Count - 1);\n                // rj will become exactly full (with own probability + alias for remainder)\n                _alias[rj] = ri; // K[j] = i\n                var uri = _probablity[ri];\n                var urj = _probablity[rj];\n                var uinew = uri + urj - 1; // U[i] + U[j] - 1\n                _probablity[ri] = uinew;\n                if (uinew <= 1) // otherwise keep in overfull\n                {\n                    overfull[ii] = overfull[overfull.Count - 1];\n                    overfull.RemoveAt(overfull.Count - 1);\n                    if (uinew < 1)\n                        underfull.Add(ri);\n                }\n            }\n\n            while (underfull.Count > 0)\n            {\n                var i = underfull[underfull.Count - 1];\n                _probablity[i] = 1;\n                underfull.RemoveAt(underfull.Count - 1);\n            }\n\n            while (overfull.Count > 0)\n            {\n                var i = overfull[overfull.Count - 1];\n                _probablity[i] = 1;\n                overfull.RemoveAt(overfull.Count - 1);\n            }\n        }\n\n        /// <summary>\n        /// Sample pdf using the alias table with random variable x: [0, 1) in O(1).\n        /// NOTE: About x2-4 faster than sampling a CDF with a binary search.\n        /// </summary>\n        public int Sample(float x1)\n        {\n            var nx = _probablity.Length * x1;\n            var i = (int)nx;\n            var y = nx - i;\n            return y < _probablity[i] ? i : _alias[i];\n        }\n    }\n\n\n    /// <summary>\n    /// Walker 1974: https://en.wikipedia.org/wiki/Alias_method\n    /// Algorithm to sample a discrete probability distribution function (PDF) in O(1).\n    /// The PDF does not need to be normalized, but the normalization factor \"1/Sum(pdf)\" needs to be supplied.\n    /// </summary>\n    public class AliasTableD\n    {\n        double[] _probablity; // U[i]\n        int[] _alias;         // K[i]\n\n        public double[] U => _probablity;\n        public int[] K => _alias;\n\n        /// <summary>\n        /// Creates an alias table from a genral PDF that does not integrate to 1.\n        /// The normalization factor will be calculated for the construction.\n        /// </summary>\n        public AliasTableD FromPdf(double[] pdf, IRandomUniform rnd = null)\n        {\n            return new AliasTableD(pdf, 1 / pdf.Sum(), rnd);\n        }\n\n        /// <summary>\n        /// Creates an alias table from an already normalized PDF (integrates to 1).\n        /// </summary>\n        public AliasTableD FromNormalizedPdf(double[] pdf, IRandomUniform rnd = null)\n        {\n            return new AliasTableD(pdf, 1, rnd);\n        }\n\n        /// <summary>\n        /// Create an alias table from a PDf and its normalization factor: 1.0 / Sum(pdf)\n        /// </summary>\n        public AliasTableD(double[] pdf, double pdfNorm, IRandomUniform rnd = null)\n        {\n            var n = pdf.Length;\n            _probablity = new double[n];\n            _alias = new int[n];\n            Update(pdf, pdfNorm, rnd);\n        }\n\n        /// <summary>\n        /// Updates the alias table with the given PDF and its norm.\n        /// The length of the PDF is expected to match the length of AliasTable.\n        /// </summary>\n        public void Update(double[] pdf, double pdfNorm, IRandomUniform rnd = null)\n        {\n            if (pdf.Length != _alias.Length) throw new ArgumentException(\"The length of the PDF does not match the length of the AliasTable!\");\n\n            if (rnd == null) rnd = new RandomSystem();\n\n            var n = pdf.Length;\n            var overfull = new List<int>(n);\n            var underfull = new List<int>(n);\n\n            for (int i = 0; i < n; i++)\n            {\n                var ui = pdf[i] * pdfNorm * n;\n                _probablity[i] = ui;\n                if (ui > 1) overfull.Add(i);\n                else if (ui < 1) underfull.Add(i);\n            }\n\n            while (overfull.Count > 0 && underfull.Count > 0)\n            {\n                var ii = rnd.UniformInt(overfull.Count);  // random overfull\n                var jj = rnd.UniformInt(underfull.Count); // random underfull\n                var ri = overfull[ii];\n                var rj = underfull[jj];\n                underfull[jj] = underfull[underfull.Count - 1];\n                underfull.RemoveAt(underfull.Count - 1);\n                // rj will become exactly full (with own probability + alias for remainder)\n                _alias[rj] = ri; // K[j] = i\n                var uri = _probablity[ri];\n                var urj = _probablity[rj];\n                var uinew = uri + urj - 1; // U[i] + U[j] - 1\n                _probablity[ri] = uinew;\n                if (uinew <= 1) // otherwise keep in overfull\n                {\n                    overfull[ii] = overfull[overfull.Count - 1];\n                    overfull.RemoveAt(overfull.Count - 1);\n                    if (uinew < 1)\n                        underfull.Add(ri);\n                }\n            }\n\n            while (underfull.Count > 0)\n            {\n                var i = underfull[underfull.Count - 1];\n                _probablity[i] = 1;\n                underfull.RemoveAt(underfull.Count - 1);\n            }\n\n            while (overfull.Count > 0)\n            {\n                var i = overfull[overfull.Count - 1];\n                _probablity[i] = 1;\n                overfull.RemoveAt(overfull.Count - 1);\n            }\n        }\n\n        /// <summary>\n        /// Sample pdf using the alias table with random variable x: [0, 1) in O(1).\n        /// NOTE: About x2-4 faster than sampling a CDF with a binary search.\n        /// </summary>\n        public int Sample(double x1)\n        {\n            var nx = _probablity.Length * x1;\n            var i = (int)nx;\n            var y = nx - i;\n            return y < _probablity[i] ? i : _alias[i];\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/AliasTable_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#     var ftype = isDouble ? Meta.DoubleType : Meta.FloatType;\n    //#     var ft = ftype.Name;\n    //#     var at = isDouble ? \"AliasTableD\" : \"AliasTableF\";\n\n    /// <summary>\n    /// Walker 1974: https://en.wikipedia.org/wiki/Alias_method\n    /// Algorithm to sample a discrete probability distribution function (PDF) in O(1).\n    /// The PDF does not need to be normalized, but the normalization factor \"1/Sum(pdf)\" needs to be supplied.\n    /// </summary>\n    public class __at__\n    {\n        __ft__[] _probablity; // U[i]\n        int[] _alias;         // K[i]\n\n        public __ft__[] U => _probablity;\n        public int[] K => _alias;\n\n        /// <summary>\n        /// Creates an alias table from a genral PDF that does not integrate to 1.\n        /// The normalization factor will be calculated for the construction.\n        /// </summary>\n        public __at__ FromPdf(__ft__[] pdf, IRandomUniform rnd = null)\n        {\n            return new __at__(pdf, 1 / pdf.Sum(), rnd);\n        }\n\n        /// <summary>\n        /// Creates an alias table from an already normalized PDF (integrates to 1).\n        /// </summary>\n        public __at__ FromNormalizedPdf(__ft__[] pdf, IRandomUniform rnd = null)\n        {\n            return new __at__(pdf, 1, rnd);\n        }\n\n        /// <summary>\n        /// Create an alias table from a PDf and its normalization factor: 1.0 / Sum(pdf)\n        /// </summary>\n        public __at__(__ft__[] pdf, __ft__ pdfNorm, IRandomUniform rnd = null)\n        {\n            var n = pdf.Length;\n            _probablity = new __ft__[n];\n            _alias = new int[n];\n            Update(pdf, pdfNorm, rnd);\n        }\n\n        /// <summary>\n        /// Updates the alias table with the given PDF and its norm.\n        /// The length of the PDF is expected to match the length of AliasTable.\n        /// </summary>\n        public void Update(__ft__[] pdf, __ft__ pdfNorm, IRandomUniform rnd = null)\n        {\n            if (pdf.Length != _alias.Length) throw new ArgumentException(\"The length of the PDF does not match the length of the AliasTable!\");\n\n            if (rnd == null) rnd = new RandomSystem();\n\n            var n = pdf.Length;\n            var overfull = new List<int>(n);\n            var underfull = new List<int>(n);\n\n            for (int i = 0; i < n; i++)\n            {\n                var ui = pdf[i] * pdfNorm * n;\n                _probablity[i] = ui;\n                if (ui > 1) overfull.Add(i);\n                else if (ui < 1) underfull.Add(i);\n            }\n\n            while (overfull.Count > 0 && underfull.Count > 0)\n            {\n                var ii = rnd.UniformInt(overfull.Count);  // random overfull\n                var jj = rnd.UniformInt(underfull.Count); // random underfull\n                var ri = overfull[ii];\n                var rj = underfull[jj];\n                underfull[jj] = underfull[underfull.Count - 1];\n                underfull.RemoveAt(underfull.Count - 1);\n                // rj will become exactly full (with own probability + alias for remainder)\n                _alias[rj] = ri; // K[j] = i\n                var uri = _probablity[ri];\n                var urj = _probablity[rj];\n                var uinew = uri + urj - 1; // U[i] + U[j] - 1\n                _probablity[ri] = uinew;\n                if (uinew <= 1) // otherwise keep in overfull\n                {\n                    overfull[ii] = overfull[overfull.Count - 1];\n                    overfull.RemoveAt(overfull.Count - 1);\n                    if (uinew < 1)\n                        underfull.Add(ri);\n                }\n            }\n\n            while (underfull.Count > 0)\n            {\n                var i = underfull[underfull.Count - 1];\n                _probablity[i] = 1;\n                underfull.RemoveAt(underfull.Count - 1);\n            }\n\n            while (overfull.Count > 0)\n            {\n                var i = overfull[overfull.Count - 1];\n                _probablity[i] = 1;\n                overfull.RemoveAt(overfull.Count - 1);\n            }\n        }\n\n        /// <summary>\n        /// Sample pdf using the alias table with random variable x: [0, 1) in O(1).\n        /// NOTE: About x2-4 faster than sampling a CDF with a binary search.\n        /// </summary>\n        public int Sample(__ft__ x1)\n        {\n            var nx = _probablity.Length * x1;\n            var i = (int)nx;\n            var y = nx - i;\n            return y < _probablity[i] ? i : _alias[i];\n        }\n    }\n\n    //# } // isDouble\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Complex_auto.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Globalization;\nusing System.ComponentModel;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct ComplexF : IEquatable<ComplexF>\n    {\n        [DataMember]\n        public float Real;\n        [DataMember]\n        public float Imag;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"ComplexF\"/> from a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ComplexF(float real)\n        {\n            Real = real;\n            Imag = 0;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"ComplexF\"/> from a real and an imaginary part.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ComplexF(float real, float imag)\n        {\n            Real = real;\n            Imag = imag;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"ComplexF\"/> from a <see cref=\"ComplexD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ComplexF(ComplexD complex)\n        {\n            Real = (float)complex.Real;\n            Imag = (float)complex.Imag;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Returns 0 + 0i.\n        /// </summary>\n        public static ComplexF Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexF(0, 0);\n        }\n\n        /// <summary>\n        /// Returns 1 + 0i.\n        /// </summary>\n        public static ComplexF One\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexF(1, 0);\n        }\n\n        /// <summary>\n        /// Returns 0 + 1i.\n        /// </summary>\n        public static ComplexF I\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexF(0, 1);\n        }\n\n        /// <summary>\n        /// Returns ∞ + 0i.\n        /// </summary>\n        public static ComplexF PositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexF(float.PositiveInfinity);\n        }\n\n        /// <summary>\n        /// Returns -∞ + 0i.\n        /// </summary>\n        public static ComplexF NegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexF(float.NegativeInfinity);\n        }\n\n        /// <summary>\n        /// Returns 0 + ∞i.\n        /// </summary>\n        public static ComplexF PositiveInfinityI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexF(0, float.PositiveInfinity);\n        }\n\n        /// <summary>\n        /// Returns 0 - ∞i.\n        /// </summary>\n        public static ComplexF NegativeInfinityI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexF(0, float.NegativeInfinity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the conjugated of the complex number.\n        /// </summary>\n        public readonly ComplexF Conjugated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new ComplexF(Real, -Imag); }\n        }\n\n        /// <summary>\n        /// Returns the reciprocal of the complex number.\n        /// </summary>\n        public readonly ComplexF Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                float t = 1 / NormSquared;\n                return new ComplexF(Real * t, -Imag * t);\n            }\n        }\n\n        /// <summary>\n        /// Returns the squared Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        public readonly float NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real * Real + Imag * Imag; }\n        }\n\n        /// <summary>\n        /// Returns the Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [XmlIgnore]\n        public float Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Fun.Sqrt(Real * Real + Imag * Imag); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                float r = Norm;\n                Real = value * Real / r;\n                Imag = value * Imag / r;\n            }\n        }\n\n        /// <summary>\n        /// Retruns the argument of the complex number.\n        /// </summary>\n        [XmlIgnore]\n        public float Argument\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Fun.Atan2(Imag, Real); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                float r = Norm;\n\n                Real = r * Fun.Cos(value);\n                Imag = r * Fun.Sin(value);\n            }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has no imaginary part.\n        /// </summary>\n        public readonly bool IsReal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has no real part.\n        /// </summary>\n        public readonly bool IsImaginary\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is 1 + 0i.\n        /// </summary>\n        public readonly bool IsOne\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.ApproximateEquals(1) && Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is zero.\n        /// </summary>\n        public readonly bool IsZero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny() && Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is 0 + 1i.\n        /// </summary>\n        public readonly bool IsI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny(Real) && Imag.ApproximateEquals(1); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is NaN.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (float.IsNaN(Real) || float.IsNaN(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite (positive or negative).\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (float.IsInfinity(Real) || float.IsInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite and positive.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (float.IsPositiveInfinity(Real) || float.IsPositiveInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite and negative.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (float.IsNegativeInfinity(Real) || float.IsNegativeInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !(IsNaN || IsInfinity); }\n        }\n\n        #endregion\n\n        #region Static factories\n\n        /// <summary>\n        /// Creates a Radial Complex\n        /// </summary>\n        /// <param name=\"r\">Norm of the complex number</param>\n        /// <param name=\"phi\">Argument of the complex number</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF CreateRadial(float r, float phi)\n            => new ComplexF(r * Fun.Cos(phi), r * Fun.Sin(phi));\n\n        /// <summary>\n        /// Creates a Orthogonal Complex\n        /// </summary>\n        /// <param name=\"real\">Real-Part</param>\n        /// <param name=\"imag\">Imaginary-Part</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF CreateOrthogonal(float real, float imag)\n            => new ComplexF(real, imag);\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Acos(ComplexF x)\n            => x.Acos();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Acoshb(ComplexF x)\n            => x.Acosh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Cos(ComplexF x)\n            => x.Cos();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Cosh(ComplexF x)\n            => x.Cosh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Asin(ComplexF x)\n            => x.Asin();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Asinhb(ComplexF x)\n            => x.Asinh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Sin(ComplexF x)\n            => x.Sin();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Sinh(ComplexF x)\n            => x.Sinh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Atan(ComplexF x)\n            => x.Atan();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Atanhb(ComplexF x)\n            => x.Atanh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Tan(ComplexF x)\n            => x.Tan();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Tanh(ComplexF x)\n            => x.Tanh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Sqrt(ComplexF x)\n            => x.Sqrt();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF CubeRoot(ComplexF x)\n            => x.Cbrt();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Exp(ComplexF x)\n            => x.Exp();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Log(ComplexF x)\n            => x.Log();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF LogBinary(ComplexF x)\n            => x.Log2();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Log10(ComplexF x)\n            => x.Log10();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF DivideByInt(ComplexF x, int y)\n            => x / y;\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Conversion from a <see cref=\"ComplexF\"/> to a <see cref=\"ComplexD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ComplexD(ComplexF c)\n            => new ComplexD(c);\n\n        /// <summary>\n        /// Implicit conversion from a <see cref=\"float\"/> to a <see cref=\"ComplexF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator ComplexF(float a)\n            => new ComplexF(a);\n\n        /// <summary>\n        /// Adds two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator +(ComplexF a, ComplexF b)\n            => new ComplexF(a.Real + b.Real, a.Imag + b.Imag);\n\n        /// <summary>\n        /// Adds a complex number and a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator +(ComplexF a, float b)\n            => new ComplexF(a.Real + b, a.Imag);\n\n        /// <summary>\n        /// Adds a real number and a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator +(float a, ComplexF b)\n            => new ComplexF(a + b.Real, b.Imag);\n\n        /// <summary>\n        /// Subtracts two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator -(ComplexF a, ComplexF b)\n            => new ComplexF(a.Real - b.Real, a.Imag - b.Imag);\n\n        /// <summary>\n        /// Subtracts a real number from a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator -(ComplexF a, float b)\n            => new ComplexF(a.Real - b, a.Imag);\n\n        /// <summary>\n        /// Subtracts a complex number from a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator -(float a, ComplexF b)\n            => new ComplexF(a - b.Real, -b.Imag);\n\n        /// <summary>\n        /// Multiplies two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator *(ComplexF a, ComplexF b)\n            => new ComplexF(\n                a.Real * b.Real - a.Imag * b.Imag,\n                a.Real * b.Imag + a.Imag * b.Real);\n\n        /// <summary>\n        /// Multiplies a complex number and a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator *(ComplexF a, float b)\n            => new ComplexF(a.Real * b, a.Imag * b);\n\n        /// <summary>\n        /// Multiplies a real number and a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator *(float a, ComplexF b)\n            => new ComplexF(a * b.Real, a * b.Imag);\n\n        /// <summary>\n        /// Divides two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator /(ComplexF a, ComplexF b)\n        {\n            float t = 1 / b.NormSquared;\n            return new ComplexF(\n                t * (a.Real * b.Real + a.Imag * b.Imag),\n                t * (a.Imag * b.Real - a.Real * b.Imag));\n        }\n\n        /// <summary>\n        /// Divides a complex number by a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator /(ComplexF a, float b)\n            => new ComplexF(a.Real / b, a.Imag / b);\n\n        /// <summary>\n        /// Divides a real number by a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator /(float a, ComplexF b)\n        {\n            float t = 1 / b.NormSquared;\n            return new ComplexF(\n                t * (a * b.Real),\n                t * (-a * b.Imag));\n        }\n\n        /// <summary>\n        /// Negates a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator -(ComplexF a)\n            => new ComplexF(-a.Real, -a.Imag);\n\n        /// <summary>\n        /// Returns the conjugate of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF operator !(ComplexF a)\n            => a.Conjugated;\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Returns whether two <see cref=\"ComplexF\"/> are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(ComplexF a, ComplexF b)\n            => a.Real == b.Real && a.Imag == b.Imag;\n\n        /// <summary>\n        /// Returns whether two <see cref=\"ComplexF\"/> are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(ComplexF a, ComplexF b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(Real, Imag);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(ComplexF other)\n            => Real.Equals(other.Real) && Imag.Equals(other.Imag);\n\n        public override readonly bool Equals(object other)\n        {\n            if (other is ComplexF obj)\n                return Equals(obj);\n            else\n                return false;\n        }\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Real, Imag);\n        }\n\n        public static ComplexF Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray(2);\n            return new ComplexF(\n                float.Parse(x[0], CultureInfo.InvariantCulture),\n                float.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Complex\n    {\n        #region Conjugate\n\n        /// <summary>\n        /// Returns the conjugate of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Conjugated(ComplexF c)\n            => c.Conjugated;\n\n        #endregion\n\n        #region Norm\n\n        /// <summary>\n        /// Returns the squared Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormSquared(ComplexF c)\n            => c.NormSquared;\n\n        /// <summary>\n        /// Returns the Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(ComplexF c)\n            => c.Norm;\n\n        #endregion\n\n        #region Argument\n\n        /// <summary>\n        /// Retruns the argument of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Argument(ComplexF c)\n            => c.Argument;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Power\n\n        /// <summary>\n        /// Returns the complex number <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Pow(this ComplexF number, ComplexF exponent)\n        {\n            if (number.IsZero)\n                return ComplexF.Zero;\n            else if (exponent.IsZero)\n                return ComplexF.One;\n            else\n            {\n                float r = number.Norm;\n                float phi = number.Argument;\n\n                float a = exponent.Real;\n                float b = exponent.Imag;\n\n                return ComplexF.CreateRadial(Exp(Log(r) * a - b * phi), a * phi + b * Log(r));\n            }\n        }\n\n        /// <summary>\n        /// Returns the complex number <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Pow(this ComplexF number, float exponent)\n        {\n            if (number.IsZero)\n                return ComplexF.Zero;\n            else\n            {\n                float r = number.Norm;\n                float phi = number.Argument;\n                return ComplexF.CreateRadial(Pow(r, exponent), exponent * phi);\n            }\n        }\n\n        /// <summary>\n        /// Returns <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Pow(this float number, ComplexF exponent)\n        {\n            if (number == 0)\n                return ComplexF.Zero;\n            else\n            {\n                float a = exponent.Real;\n                float b = exponent.Imag;\n\n                if (number < 0)\n                {\n                    var phi = ConstantF.Pi;\n                    return ComplexF.CreateRadial(Exp(Log(-number) * a - b * phi), a * phi + b * Log(-number));\n                }\n                else\n                    return ComplexF.CreateRadial(Pow(number, a), b * Log(number));\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Power(this ComplexF number, ComplexF exponent)\n            => Pow(number, exponent);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Power(this ComplexF number, float exponent)\n            => Pow(number, exponent);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Power(this float number, ComplexF exponent)\n            => Pow(number, exponent);\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Returns the angle that is the arc cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Acos(this ComplexF x)\n        {\n            var t = Log(new ComplexF(-x.Imag, x.Real) + Sqrt(1 - x * x));\n            return new ComplexF(-t.Imag + ConstantF.PiHalf, t.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Acosh(this ComplexF x)\n            => Log(x + Sqrt(x * x - 1));\n\n        /// <summary>\n        /// Returns the cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Cos(this ComplexF x)\n            => (\n                Exp(new ComplexF(-x.Imag, x.Real)) +\n                Exp(new ComplexF(x.Imag, -x.Real))\n            ) * 0.5f;\n\n        /// <summary>\n        /// Returns the hyperbolic cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Cosh(this ComplexF x)\n            => Cos(new ComplexF(-x.Imag, x.Real));\n\n        /// <summary>\n        /// Returns the angle that is the arc sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Asin(this ComplexF x)\n        {\n            var t = Log(new ComplexF(-x.Imag, x.Real) + Sqrt(1 - x * x));\n            return new ComplexF(t.Imag, -t.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Asinh(this ComplexF x)\n            => Log(x + Sqrt(1 + x * x));\n\n        /// <summary>\n        /// Returns the sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Sin(this ComplexF x)\n        {\n            var a = Exp(new ComplexF(-x.Imag, x.Real)) - Exp(new ComplexF(x.Imag, -x.Real));\n            return new ComplexF(a.Imag, -a.Real) * 0.5f;\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Sinh(this ComplexF x)\n        {\n            var sin = Sin(new ComplexF(-x.Imag, x.Real));\n            return new ComplexF(sin.Imag, -sin.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the arc tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Atan(this ComplexF x)\n        {\n            if (x == ComplexF.I)\n                return ComplexF.PositiveInfinityI;\n            else if (x == -ComplexF.I)\n                return ComplexF.NegativeInfinityI;\n            else if (x == ComplexF.PositiveInfinity)\n                return new ComplexF(ConstantF.PiHalf);\n            else if (x == ComplexF.NegativeInfinity)\n                return new ComplexF(-ConstantF.PiHalf);\n            else\n                return new ComplexF(0, 0.5f) * Log((ComplexF.I + x) / (ComplexF.I - x));\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Atanh(this ComplexF x)\n        {\n            if (x == ComplexF.Zero)\n                return ComplexF.Zero;\n            else if (x == ComplexF.One)\n                return ComplexF.PositiveInfinity;\n            else if (x == ComplexF.PositiveInfinity)\n                return new ComplexF(0, -ConstantF.PiHalf);\n            else if (x == ComplexF.I)\n                return new ComplexF(0, ConstantF.PiQuarter);\n            else\n                return 0.5f * (Log(1 + x) - Log(1 - x));\n        }\n\n        /// <summary>\n        /// Returns the tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Tan(this ComplexF x)\n        {\n            if (x == ComplexF.PositiveInfinityI)\n                return ComplexF.I;\n            else if (x == ComplexF.NegativeInfinityI)\n                return -ComplexF.I;\n            else\n                return Sin(x) / Cos(x);\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Tanh(this ComplexF x)\n        {\n            var tan = Tan(new ComplexF(-x.Imag, x.Real));\n            return new ComplexF(tan.Imag, -tan.Real);\n        }\n\n        #endregion\n\n        #region Exp, Log\n\n        /// <summary>\n        /// Returns e raised to the power of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Exp(this ComplexF x)\n            => new ComplexF(Cos(x.Imag), Sin(x.Imag)) * Exp(x.Real);\n\n        /// <summary>\n        /// Returns the natural logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Log(this ComplexF x)\n            => new ComplexF(Log(x.Norm), x.Argument);\n\n        /// <summary>\n        /// Returns the logarithm of the complex number <paramref name=\"x\"/> in the given basis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Log(this ComplexF x, float basis)\n            => x.Log() / basis.Log();\n\n        /// <summary>\n        /// Returns the base-10 logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Log10(this ComplexF x)\n            => Log(x, 10);\n\n        /// <summary>\n        /// Returns the base-2 logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Log2(this ComplexF x)\n            => x.Log() * ConstantF.Ln2Inv;\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Returns the principal square root of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        // https://math.stackexchange.com/a/44500\n        // TODO: Check if this is actually better than the naive implementation\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Sqrt(this ComplexF x)\n        {\n            if (x.Imag == 0)\n            {\n                if (x.Real < 0)\n                    return new ComplexF(0, Sqrt(-x.Real));\n                else\n                    return new ComplexF(Sqrt(x.Real), 0);\n            }\n            else\n            {\n                var a = x.Norm;\n                var b = x + a;\n                return a.Sqrt() * (b / b.Norm);\n            }\n        }\n\n        /// <summary>\n        /// Returns the principal cubic root of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Cbrt(this ComplexF x)\n            => ComplexF.CreateRadial(Cbrt(x.Norm), x.Argument / 3);\n\n        /// <summary>\n        /// Returns the square root of the given real number and returns a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF Csqrt(this float number)\n        {\n            if (number >= 0)\n            {\n                return new ComplexF(Sqrt(number), 0);\n            }\n            else\n            {\n                return new ComplexF(0, Sqrt(-number));\n            }\n        }\n\n        /// <summary>\n        /// Calculates both square roots of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF[] Csqrt(this ComplexF number)\n        {\n            ComplexF res0 = ComplexF.CreateRadial(Sqrt(number.Norm), number.Argument / 2);\n            ComplexF res1 = ComplexF.CreateRadial(Sqrt(number.Norm), number.Argument / 2 + ConstantF.Pi);\n\n            return new ComplexF[2] { res0, res1 };\n        }\n\n        /// <summary>\n        /// Calculates the n-th root of a complex number and returns n solutions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexF[] Root(this ComplexF number, int n)\n        {\n            ComplexF[] values = new ComplexF[n];\n\n            float invN = 1 / (float)n;\n            float phi = number.Argument / n;\n            float dphi = ConstantF.PiTimesTwo * invN;\n            float r = Pow(number.Norm, invN);\n\n            for (int i = 0; i < n; i++)\n            {\n                values[i] = ComplexF.CreateRadial(r, phi + dphi * i);\n            }\n\n            return values;\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given complex numbers are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ComplexF a, ComplexF b, float tolerance)\n        {\n            return ApproximateEquals(a.Real, b.Real, tolerance) && ApproximateEquals(a.Imag, b.Imag, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given complex numbers are equal within\n        /// Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ComplexF a, ComplexF b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexF\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(ComplexF v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexF\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(ComplexF v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexF\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(ComplexF v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexF\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(ComplexF v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexF\"/> is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(ComplexF v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct ComplexD : IEquatable<ComplexD>\n    {\n        [DataMember]\n        public double Real;\n        [DataMember]\n        public double Imag;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"ComplexD\"/> from a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ComplexD(double real)\n        {\n            Real = real;\n            Imag = 0;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"ComplexD\"/> from a real and an imaginary part.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ComplexD(double real, double imag)\n        {\n            Real = real;\n            Imag = imag;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"ComplexD\"/> from a <see cref=\"ComplexF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public ComplexD(ComplexF complex)\n        {\n            Real = (double)complex.Real;\n            Imag = (double)complex.Imag;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Returns 0 + 0i.\n        /// </summary>\n        public static ComplexD Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexD(0, 0);\n        }\n\n        /// <summary>\n        /// Returns 1 + 0i.\n        /// </summary>\n        public static ComplexD One\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexD(1, 0);\n        }\n\n        /// <summary>\n        /// Returns 0 + 1i.\n        /// </summary>\n        public static ComplexD I\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexD(0, 1);\n        }\n\n        /// <summary>\n        /// Returns ∞ + 0i.\n        /// </summary>\n        public static ComplexD PositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexD(double.PositiveInfinity);\n        }\n\n        /// <summary>\n        /// Returns -∞ + 0i.\n        /// </summary>\n        public static ComplexD NegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexD(double.NegativeInfinity);\n        }\n\n        /// <summary>\n        /// Returns 0 + ∞i.\n        /// </summary>\n        public static ComplexD PositiveInfinityI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexD(0, double.PositiveInfinity);\n        }\n\n        /// <summary>\n        /// Returns 0 - ∞i.\n        /// </summary>\n        public static ComplexD NegativeInfinityI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new ComplexD(0, double.NegativeInfinity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the conjugated of the complex number.\n        /// </summary>\n        public readonly ComplexD Conjugated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new ComplexD(Real, -Imag); }\n        }\n\n        /// <summary>\n        /// Returns the reciprocal of the complex number.\n        /// </summary>\n        public readonly ComplexD Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                double t = 1 / NormSquared;\n                return new ComplexD(Real * t, -Imag * t);\n            }\n        }\n\n        /// <summary>\n        /// Returns the squared Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        public readonly double NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real * Real + Imag * Imag; }\n        }\n\n        /// <summary>\n        /// Returns the Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [XmlIgnore]\n        public double Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Fun.Sqrt(Real * Real + Imag * Imag); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                double r = Norm;\n                Real = value * Real / r;\n                Imag = value * Imag / r;\n            }\n        }\n\n        /// <summary>\n        /// Retruns the argument of the complex number.\n        /// </summary>\n        [XmlIgnore]\n        public double Argument\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Fun.Atan2(Imag, Real); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                double r = Norm;\n\n                Real = r * Fun.Cos(value);\n                Imag = r * Fun.Sin(value);\n            }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has no imaginary part.\n        /// </summary>\n        public readonly bool IsReal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has no real part.\n        /// </summary>\n        public readonly bool IsImaginary\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is 1 + 0i.\n        /// </summary>\n        public readonly bool IsOne\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.ApproximateEquals(1) && Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is zero.\n        /// </summary>\n        public readonly bool IsZero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny() && Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is 0 + 1i.\n        /// </summary>\n        public readonly bool IsI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny(Real) && Imag.ApproximateEquals(1); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is NaN.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (double.IsNaN(Real) || double.IsNaN(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite (positive or negative).\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (double.IsInfinity(Real) || double.IsInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite and positive.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (double.IsPositiveInfinity(Real) || double.IsPositiveInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite and negative.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (double.IsNegativeInfinity(Real) || double.IsNegativeInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !(IsNaN || IsInfinity); }\n        }\n\n        #endregion\n\n        #region Static factories\n\n        /// <summary>\n        /// Creates a Radial Complex\n        /// </summary>\n        /// <param name=\"r\">Norm of the complex number</param>\n        /// <param name=\"phi\">Argument of the complex number</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD CreateRadial(double r, double phi)\n            => new ComplexD(r * Fun.Cos(phi), r * Fun.Sin(phi));\n\n        /// <summary>\n        /// Creates a Orthogonal Complex\n        /// </summary>\n        /// <param name=\"real\">Real-Part</param>\n        /// <param name=\"imag\">Imaginary-Part</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD CreateOrthogonal(double real, double imag)\n            => new ComplexD(real, imag);\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Acos(ComplexD x)\n            => x.Acos();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Acoshb(ComplexD x)\n            => x.Acosh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Cos(ComplexD x)\n            => x.Cos();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Cosh(ComplexD x)\n            => x.Cosh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Asin(ComplexD x)\n            => x.Asin();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Asinhb(ComplexD x)\n            => x.Asinh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Sin(ComplexD x)\n            => x.Sin();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Sinh(ComplexD x)\n            => x.Sinh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Atan(ComplexD x)\n            => x.Atan();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Atanhb(ComplexD x)\n            => x.Atanh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Tan(ComplexD x)\n            => x.Tan();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Tanh(ComplexD x)\n            => x.Tanh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Sqrt(ComplexD x)\n            => x.Sqrt();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD CubeRoot(ComplexD x)\n            => x.Cbrt();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Exp(ComplexD x)\n            => x.Exp();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Log(ComplexD x)\n            => x.Log();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD LogBinary(ComplexD x)\n            => x.Log2();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Log10(ComplexD x)\n            => x.Log10();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD DivideByInt(ComplexD x, int y)\n            => x / y;\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Conversion from a <see cref=\"ComplexD\"/> to a <see cref=\"ComplexF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ComplexF(ComplexD c)\n            => new ComplexF(c);\n\n        /// <summary>\n        /// Implicit conversion from a <see cref=\"double\"/> to a <see cref=\"ComplexD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator ComplexD(double a)\n            => new ComplexD(a);\n\n        /// <summary>\n        /// Adds two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator +(ComplexD a, ComplexD b)\n            => new ComplexD(a.Real + b.Real, a.Imag + b.Imag);\n\n        /// <summary>\n        /// Adds a complex number and a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator +(ComplexD a, double b)\n            => new ComplexD(a.Real + b, a.Imag);\n\n        /// <summary>\n        /// Adds a real number and a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator +(double a, ComplexD b)\n            => new ComplexD(a + b.Real, b.Imag);\n\n        /// <summary>\n        /// Subtracts two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator -(ComplexD a, ComplexD b)\n            => new ComplexD(a.Real - b.Real, a.Imag - b.Imag);\n\n        /// <summary>\n        /// Subtracts a real number from a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator -(ComplexD a, double b)\n            => new ComplexD(a.Real - b, a.Imag);\n\n        /// <summary>\n        /// Subtracts a complex number from a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator -(double a, ComplexD b)\n            => new ComplexD(a - b.Real, -b.Imag);\n\n        /// <summary>\n        /// Multiplies two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator *(ComplexD a, ComplexD b)\n            => new ComplexD(\n                a.Real * b.Real - a.Imag * b.Imag,\n                a.Real * b.Imag + a.Imag * b.Real);\n\n        /// <summary>\n        /// Multiplies a complex number and a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator *(ComplexD a, double b)\n            => new ComplexD(a.Real * b, a.Imag * b);\n\n        /// <summary>\n        /// Multiplies a real number and a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator *(double a, ComplexD b)\n            => new ComplexD(a * b.Real, a * b.Imag);\n\n        /// <summary>\n        /// Divides two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator /(ComplexD a, ComplexD b)\n        {\n            double t = 1 / b.NormSquared;\n            return new ComplexD(\n                t * (a.Real * b.Real + a.Imag * b.Imag),\n                t * (a.Imag * b.Real - a.Real * b.Imag));\n        }\n\n        /// <summary>\n        /// Divides a complex number by a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator /(ComplexD a, double b)\n            => new ComplexD(a.Real / b, a.Imag / b);\n\n        /// <summary>\n        /// Divides a real number by a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator /(double a, ComplexD b)\n        {\n            double t = 1 / b.NormSquared;\n            return new ComplexD(\n                t * (a * b.Real),\n                t * (-a * b.Imag));\n        }\n\n        /// <summary>\n        /// Negates a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator -(ComplexD a)\n            => new ComplexD(-a.Real, -a.Imag);\n\n        /// <summary>\n        /// Returns the conjugate of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD operator !(ComplexD a)\n            => a.Conjugated;\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Returns whether two <see cref=\"ComplexD\"/> are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(ComplexD a, ComplexD b)\n            => a.Real == b.Real && a.Imag == b.Imag;\n\n        /// <summary>\n        /// Returns whether two <see cref=\"ComplexD\"/> are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(ComplexD a, ComplexD b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(Real, Imag);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(ComplexD other)\n            => Real.Equals(other.Real) && Imag.Equals(other.Imag);\n\n        public override readonly bool Equals(object other)\n        {\n            if (other is ComplexD obj)\n                return Equals(obj);\n            else\n                return false;\n        }\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Real, Imag);\n        }\n\n        public static ComplexD Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray(2);\n            return new ComplexD(\n                double.Parse(x[0], CultureInfo.InvariantCulture),\n                double.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Complex\n    {\n        #region Conjugate\n\n        /// <summary>\n        /// Returns the conjugate of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Conjugated(ComplexD c)\n            => c.Conjugated;\n\n        #endregion\n\n        #region Norm\n\n        /// <summary>\n        /// Returns the squared Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormSquared(ComplexD c)\n            => c.NormSquared;\n\n        /// <summary>\n        /// Returns the Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(ComplexD c)\n            => c.Norm;\n\n        #endregion\n\n        #region Argument\n\n        /// <summary>\n        /// Retruns the argument of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Argument(ComplexD c)\n            => c.Argument;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Power\n\n        /// <summary>\n        /// Returns the complex number <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Pow(this ComplexD number, ComplexD exponent)\n        {\n            if (number.IsZero)\n                return ComplexD.Zero;\n            else if (exponent.IsZero)\n                return ComplexD.One;\n            else\n            {\n                double r = number.Norm;\n                double phi = number.Argument;\n\n                double a = exponent.Real;\n                double b = exponent.Imag;\n\n                return ComplexD.CreateRadial(Exp(Log(r) * a - b * phi), a * phi + b * Log(r));\n            }\n        }\n\n        /// <summary>\n        /// Returns the complex number <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Pow(this ComplexD number, double exponent)\n        {\n            if (number.IsZero)\n                return ComplexD.Zero;\n            else\n            {\n                double r = number.Norm;\n                double phi = number.Argument;\n                return ComplexD.CreateRadial(Pow(r, exponent), exponent * phi);\n            }\n        }\n\n        /// <summary>\n        /// Returns <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Pow(this double number, ComplexD exponent)\n        {\n            if (number == 0)\n                return ComplexD.Zero;\n            else\n            {\n                double a = exponent.Real;\n                double b = exponent.Imag;\n\n                if (number < 0)\n                {\n                    var phi = Constant.Pi;\n                    return ComplexD.CreateRadial(Exp(Log(-number) * a - b * phi), a * phi + b * Log(-number));\n                }\n                else\n                    return ComplexD.CreateRadial(Pow(number, a), b * Log(number));\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Power(this ComplexD number, ComplexD exponent)\n            => Pow(number, exponent);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Power(this ComplexD number, double exponent)\n            => Pow(number, exponent);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Power(this double number, ComplexD exponent)\n            => Pow(number, exponent);\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Returns the angle that is the arc cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Acos(this ComplexD x)\n        {\n            var t = Log(new ComplexD(-x.Imag, x.Real) + Sqrt(1 - x * x));\n            return new ComplexD(-t.Imag + Constant.PiHalf, t.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Acosh(this ComplexD x)\n            => Log(x + Sqrt(x * x - 1));\n\n        /// <summary>\n        /// Returns the cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Cos(this ComplexD x)\n            => (\n                Exp(new ComplexD(-x.Imag, x.Real)) +\n                Exp(new ComplexD(x.Imag, -x.Real))\n            ) * 0.5;\n\n        /// <summary>\n        /// Returns the hyperbolic cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Cosh(this ComplexD x)\n            => Cos(new ComplexD(-x.Imag, x.Real));\n\n        /// <summary>\n        /// Returns the angle that is the arc sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Asin(this ComplexD x)\n        {\n            var t = Log(new ComplexD(-x.Imag, x.Real) + Sqrt(1 - x * x));\n            return new ComplexD(t.Imag, -t.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Asinh(this ComplexD x)\n            => Log(x + Sqrt(1 + x * x));\n\n        /// <summary>\n        /// Returns the sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Sin(this ComplexD x)\n        {\n            var a = Exp(new ComplexD(-x.Imag, x.Real)) - Exp(new ComplexD(x.Imag, -x.Real));\n            return new ComplexD(a.Imag, -a.Real) * 0.5;\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Sinh(this ComplexD x)\n        {\n            var sin = Sin(new ComplexD(-x.Imag, x.Real));\n            return new ComplexD(sin.Imag, -sin.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the arc tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Atan(this ComplexD x)\n        {\n            if (x == ComplexD.I)\n                return ComplexD.PositiveInfinityI;\n            else if (x == -ComplexD.I)\n                return ComplexD.NegativeInfinityI;\n            else if (x == ComplexD.PositiveInfinity)\n                return new ComplexD(Constant.PiHalf);\n            else if (x == ComplexD.NegativeInfinity)\n                return new ComplexD(-Constant.PiHalf);\n            else\n                return new ComplexD(0, 0.5) * Log((ComplexD.I + x) / (ComplexD.I - x));\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Atanh(this ComplexD x)\n        {\n            if (x == ComplexD.Zero)\n                return ComplexD.Zero;\n            else if (x == ComplexD.One)\n                return ComplexD.PositiveInfinity;\n            else if (x == ComplexD.PositiveInfinity)\n                return new ComplexD(0, -Constant.PiHalf);\n            else if (x == ComplexD.I)\n                return new ComplexD(0, Constant.PiQuarter);\n            else\n                return 0.5 * (Log(1 + x) - Log(1 - x));\n        }\n\n        /// <summary>\n        /// Returns the tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Tan(this ComplexD x)\n        {\n            if (x == ComplexD.PositiveInfinityI)\n                return ComplexD.I;\n            else if (x == ComplexD.NegativeInfinityI)\n                return -ComplexD.I;\n            else\n                return Sin(x) / Cos(x);\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Tanh(this ComplexD x)\n        {\n            var tan = Tan(new ComplexD(-x.Imag, x.Real));\n            return new ComplexD(tan.Imag, -tan.Real);\n        }\n\n        #endregion\n\n        #region Exp, Log\n\n        /// <summary>\n        /// Returns e raised to the power of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Exp(this ComplexD x)\n            => new ComplexD(Cos(x.Imag), Sin(x.Imag)) * Exp(x.Real);\n\n        /// <summary>\n        /// Returns the natural logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Log(this ComplexD x)\n            => new ComplexD(Log(x.Norm), x.Argument);\n\n        /// <summary>\n        /// Returns the logarithm of the complex number <paramref name=\"x\"/> in the given basis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Log(this ComplexD x, double basis)\n            => x.Log() / basis.Log();\n\n        /// <summary>\n        /// Returns the base-10 logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Log10(this ComplexD x)\n            => Log(x, 10);\n\n        /// <summary>\n        /// Returns the base-2 logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Log2(this ComplexD x)\n            => x.Log() * Constant.Ln2Inv;\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Returns the principal square root of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        // https://math.stackexchange.com/a/44500\n        // TODO: Check if this is actually better than the naive implementation\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Sqrt(this ComplexD x)\n        {\n            if (x.Imag == 0)\n            {\n                if (x.Real < 0)\n                    return new ComplexD(0, Sqrt(-x.Real));\n                else\n                    return new ComplexD(Sqrt(x.Real), 0);\n            }\n            else\n            {\n                var a = x.Norm;\n                var b = x + a;\n                return a.Sqrt() * (b / b.Norm);\n            }\n        }\n\n        /// <summary>\n        /// Returns the principal cubic root of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Cbrt(this ComplexD x)\n            => ComplexD.CreateRadial(Cbrt(x.Norm), x.Argument / 3);\n\n        /// <summary>\n        /// Returns the square root of the given real number and returns a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Csqrt(this sbyte number)\n        {\n            if (number >= 0)\n            {\n                return new ComplexD(Sqrt(number), 0);\n            }\n            else\n            {\n                return new ComplexD(0, Sqrt(-number));\n            }\n        }\n        /// <summary>\n        /// Returns the square root of the given real number and returns a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Csqrt(this short number)\n        {\n            if (number >= 0)\n            {\n                return new ComplexD(Sqrt(number), 0);\n            }\n            else\n            {\n                return new ComplexD(0, Sqrt(-number));\n            }\n        }\n        /// <summary>\n        /// Returns the square root of the given real number and returns a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Csqrt(this int number)\n        {\n            if (number >= 0)\n            {\n                return new ComplexD(Sqrt(number), 0);\n            }\n            else\n            {\n                return new ComplexD(0, Sqrt(-number));\n            }\n        }\n        /// <summary>\n        /// Returns the square root of the given real number and returns a complex number.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Csqrt(this long number)\n        {\n            if (number >= 0)\n            {\n                return new ComplexD(Sqrt(number), 0);\n            }\n            else\n            {\n                return new ComplexD(0, Sqrt(-number));\n            }\n        }\n        /// <summary>\n        /// Returns the square root of the given real number and returns a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD Csqrt(this double number)\n        {\n            if (number >= 0)\n            {\n                return new ComplexD(Sqrt(number), 0);\n            }\n            else\n            {\n                return new ComplexD(0, Sqrt(-number));\n            }\n        }\n\n        /// <summary>\n        /// Calculates both square roots of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD[] Csqrt(this ComplexD number)\n        {\n            ComplexD res0 = ComplexD.CreateRadial(Sqrt(number.Norm), number.Argument / 2);\n            ComplexD res1 = ComplexD.CreateRadial(Sqrt(number.Norm), number.Argument / 2 + Constant.Pi);\n\n            return new ComplexD[2] { res0, res1 };\n        }\n\n        /// <summary>\n        /// Calculates the n-th root of a complex number and returns n solutions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ComplexD[] Root(this ComplexD number, int n)\n        {\n            ComplexD[] values = new ComplexD[n];\n\n            double invN = 1 / (double)n;\n            double phi = number.Argument / n;\n            double dphi = Constant.PiTimesTwo * invN;\n            double r = Pow(number.Norm, invN);\n\n            for (int i = 0; i < n; i++)\n            {\n                values[i] = ComplexD.CreateRadial(r, phi + dphi * i);\n            }\n\n            return values;\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given complex numbers are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ComplexD a, ComplexD b, double tolerance)\n        {\n            return ApproximateEquals(a.Real, b.Real, tolerance) && ApproximateEquals(a.Imag, b.Imag, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given complex numbers are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ComplexD a, ComplexD b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexD\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(ComplexD v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexD\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(ComplexD v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexD\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(ComplexD v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexD\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(ComplexD v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"ComplexD\"/> is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(ComplexD v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Complex_template.cs",
    "content": "﻿using System;\nusing System.Linq;\nusing System.Globalization;\nusing System.ComponentModel;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    //# var signedtypes = Meta.SignedTypes;\n    //# var numtypes = Meta.StandardNumericTypes;\n    //# var dreptypes = Meta.DoubleRepresentableTypes;\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? Meta.DoubleType : Meta.FloatType;\n    //#   var ftype2 = isDouble ? Meta.FloatType : Meta.DoubleType;\n    //#   var ft = ftype.Name;\n    //#   var ft2 = ftype2.Name;\n    //#   var ct = isDouble ? \"ComplexD\" : \"ComplexF\";\n    //#   var ct2 = isDouble ? \"ComplexF\" : \"ComplexD\";\n    //#   var constant = isDouble ? \"Constant\" : \"ConstantF\";\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct __ct__ : IEquatable<__ct__>\n    {\n        [DataMember]\n        public __ft__ Real;\n        [DataMember]\n        public __ft__ Imag;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"__ct__\"/> from a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __ct__(__ft__ real)\n        {\n            Real = real;\n            Imag = 0;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__ct__\"/> from a real and an imaginary part.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __ct__(__ft__ real, __ft__ imag)\n        {\n            Real = real;\n            Imag = imag;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__ct__\"/> from a <see cref=\"__ct2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __ct__(__ct2__ complex)\n        {\n            Real = (__ft__)complex.Real;\n            Imag = (__ft__)complex.Imag;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Returns 0 + 0i.\n        /// </summary>\n        public static __ct__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ct__(0, 0);\n        }\n\n        /// <summary>\n        /// Returns 1 + 0i.\n        /// </summary>\n        public static __ct__ One\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ct__(1, 0);\n        }\n\n        /// <summary>\n        /// Returns 0 + 1i.\n        /// </summary>\n        public static __ct__ I\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ct__(0, 1);\n        }\n\n        /// <summary>\n        /// Returns ∞ + 0i.\n        /// </summary>\n        public static __ct__ PositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ct__(__ft__.PositiveInfinity);\n        }\n\n        /// <summary>\n        /// Returns -∞ + 0i.\n        /// </summary>\n        public static __ct__ NegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ct__(__ft__.NegativeInfinity);\n        }\n\n        /// <summary>\n        /// Returns 0 + ∞i.\n        /// </summary>\n        public static __ct__ PositiveInfinityI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ct__(0, __ft__.PositiveInfinity);\n        }\n\n        /// <summary>\n        /// Returns 0 - ∞i.\n        /// </summary>\n        public static __ct__ NegativeInfinityI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __ct__(0, __ft__.NegativeInfinity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the conjugated of the complex number.\n        /// </summary>\n        public readonly __ct__ Conjugated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new __ct__(Real, -Imag); }\n        }\n\n        /// <summary>\n        /// Returns the reciprocal of the complex number.\n        /// </summary>\n        public readonly __ct__ Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                __ft__ t = 1 / NormSquared;\n                return new __ct__(Real * t, -Imag * t);\n            }\n        }\n\n        /// <summary>\n        /// Returns the squared Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        public readonly __ft__ NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real * Real + Imag * Imag; }\n        }\n\n        /// <summary>\n        /// Returns the Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [XmlIgnore]\n        public __ft__ Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Fun.Sqrt(Real * Real + Imag * Imag); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                __ft__ r = Norm;\n                Real = value * Real / r;\n                Imag = value * Imag / r;\n            }\n        }\n\n        /// <summary>\n        /// Retruns the argument of the complex number.\n        /// </summary>\n        [XmlIgnore]\n        public __ft__ Argument\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Fun.Atan2(Imag, Real); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                __ft__ r = Norm;\n\n                Real = r * Fun.Cos(value);\n                Imag = r * Fun.Sin(value);\n            }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has no imaginary part.\n        /// </summary>\n        public readonly bool IsReal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has no real part.\n        /// </summary>\n        public readonly bool IsImaginary\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is 1 + 0i.\n        /// </summary>\n        public readonly bool IsOne\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.ApproximateEquals(1) && Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is zero.\n        /// </summary>\n        public readonly bool IsZero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny() && Imag.IsTiny(); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is 0 + 1i.\n        /// </summary>\n        public readonly bool IsI\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Real.IsTiny(Real) && Imag.ApproximateEquals(1); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is NaN.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (__ft__.IsNaN(Real) || __ft__.IsNaN(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite (positive or negative).\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (__ft__.IsInfinity(Real) || __ft__.IsInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite and positive.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (__ft__.IsPositiveInfinity(Real) || __ft__.IsPositiveInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number has a part that is infinite and negative.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (__ft__.IsNegativeInfinity(Real) || __ft__.IsNegativeInfinity(Imag)); }\n        }\n\n        /// <summary>\n        /// Returns whether the complex number is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !(IsNaN || IsInfinity); }\n        }\n\n        #endregion\n\n        #region Static factories\n\n        /// <summary>\n        /// Creates a Radial Complex\n        /// </summary>\n        /// <param name=\"r\">Norm of the complex number</param>\n        /// <param name=\"phi\">Argument of the complex number</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ CreateRadial(__ft__ r, __ft__ phi)\n            => new __ct__(r * Fun.Cos(phi), r * Fun.Sin(phi));\n\n        /// <summary>\n        /// Creates a Orthogonal Complex\n        /// </summary>\n        /// <param name=\"real\">Real-Part</param>\n        /// <param name=\"imag\">Imaginary-Part</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ CreateOrthogonal(__ft__ real, __ft__ imag)\n            => new __ct__(real, imag);\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Acos(__ct__ x)\n            => x.Acos();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Acoshb(__ct__ x)\n            => x.Acosh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Cos(__ct__ x)\n            => x.Cos();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Cosh(__ct__ x)\n            => x.Cosh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Asin(__ct__ x)\n            => x.Asin();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Asinhb(__ct__ x)\n            => x.Asinh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Sin(__ct__ x)\n            => x.Sin();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Sinh(__ct__ x)\n            => x.Sinh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Atan(__ct__ x)\n            => x.Atan();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Atanhb(__ct__ x)\n            => x.Atanh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Tan(__ct__ x)\n            => x.Tan();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Tanh(__ct__ x)\n            => x.Tanh();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Sqrt(__ct__ x)\n            => x.Sqrt();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ CubeRoot(__ct__ x)\n            => x.Cbrt();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Exp(__ct__ x)\n            => x.Exp();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Log(__ct__ x)\n            => x.Log();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ LogBinary(__ct__ x)\n            => x.Log2();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Log10(__ct__ x)\n            => x.Log10();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ DivideByInt(__ct__ x, int y)\n            => x / y;\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Conversion from a <see cref=\"__ct__\"/> to a <see cref=\"__ct2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __ct2__(__ct__ c)\n            => new __ct2__(c);\n\n        /// <summary>\n        /// Implicit conversion from a <see cref=\"__ft__\"/> to a <see cref=\"__ct__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator __ct__(__ft__ a)\n            => new __ct__(a);\n\n        /// <summary>\n        /// Adds two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator +(__ct__ a, __ct__ b)\n            => new __ct__(a.Real + b.Real, a.Imag + b.Imag);\n\n        /// <summary>\n        /// Adds a complex number and a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator +(__ct__ a, __ft__ b)\n            => new __ct__(a.Real + b, a.Imag);\n\n        /// <summary>\n        /// Adds a real number and a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator +(__ft__ a, __ct__ b)\n            => new __ct__(a + b.Real, b.Imag);\n\n        /// <summary>\n        /// Subtracts two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator -(__ct__ a, __ct__ b)\n            => new __ct__(a.Real - b.Real, a.Imag - b.Imag);\n\n        /// <summary>\n        /// Subtracts a real number from a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator -(__ct__ a, __ft__ b)\n            => new __ct__(a.Real - b, a.Imag);\n\n        /// <summary>\n        /// Subtracts a complex number from a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator -(__ft__ a, __ct__ b)\n            => new __ct__(a - b.Real, -b.Imag);\n\n        /// <summary>\n        /// Multiplies two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator *(__ct__ a, __ct__ b)\n            => new __ct__(\n                a.Real * b.Real - a.Imag * b.Imag,\n                a.Real * b.Imag + a.Imag * b.Real);\n\n        /// <summary>\n        /// Multiplies a complex number and a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator *(__ct__ a, __ft__ b)\n            => new __ct__(a.Real * b, a.Imag * b);\n\n        /// <summary>\n        /// Multiplies a real number and a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator *(__ft__ a, __ct__ b)\n            => new __ct__(a * b.Real, a * b.Imag);\n\n        /// <summary>\n        /// Divides two complex numbers.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator /(__ct__ a, __ct__ b)\n        {\n            __ft__ t = 1 / b.NormSquared;\n            return new __ct__(\n                t * (a.Real * b.Real + a.Imag * b.Imag),\n                t * (a.Imag * b.Real - a.Real * b.Imag));\n        }\n\n        /// <summary>\n        /// Divides a complex number by a real number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator /(__ct__ a, __ft__ b)\n            => new __ct__(a.Real / b, a.Imag / b);\n\n        /// <summary>\n        /// Divides a real number by a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator /(__ft__ a, __ct__ b)\n        {\n            __ft__ t = 1 / b.NormSquared;\n            return new __ct__(\n                t * (a * b.Real),\n                t * (-a * b.Imag));\n        }\n\n        /// <summary>\n        /// Negates a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator -(__ct__ a)\n            => new __ct__(-a.Real, -a.Imag);\n\n        /// <summary>\n        /// Returns the conjugate of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ operator !(__ct__ a)\n            => a.Conjugated;\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Returns whether two <see cref=\"__ct__\"/> are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__ct__ a, __ct__ b)\n            => a.Real == b.Real && a.Imag == b.Imag;\n\n        /// <summary>\n        /// Returns whether two <see cref=\"__ct__\"/> are not equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__ct__ a, __ct__ b)\n            => !(a == b);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n            => HashCode.GetCombined(Real, Imag);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__ct__ other)\n            => Real.Equals(other.Real) && Imag.Equals(other.Imag);\n\n        public override readonly bool Equals(object other)\n        {\n            if (other is __ct__ obj)\n                return Equals(obj);\n            else\n                return false;\n        }\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Real, Imag);\n        }\n\n        public static __ct__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray(2);\n            return new __ct__(\n                __ft__.Parse(x[0], CultureInfo.InvariantCulture),\n                __ft__.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Complex\n    {\n        #region Conjugate\n\n        /// <summary>\n        /// Returns the conjugate of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Conjugated(__ct__ c)\n            => c.Conjugated;\n\n        #endregion\n\n        #region Norm\n\n        /// <summary>\n        /// Returns the squared Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ft__ NormSquared(__ct__ c)\n            => c.NormSquared;\n\n        /// <summary>\n        /// Returns the Gaussian Norm (modulus) of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ft__ Norm(__ct__ c)\n            => c.Norm;\n\n        #endregion\n\n        #region Argument\n\n        /// <summary>\n        /// Retruns the argument of the complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ft__ Argument(__ct__ c)\n            => c.Argument;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Power\n\n        /// <summary>\n        /// Returns the complex number <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Pow(this __ct__ number, __ct__ exponent)\n        {\n            if (number.IsZero)\n                return __ct__.Zero;\n            else if (exponent.IsZero)\n                return __ct__.One;\n            else\n            {\n                __ft__ r = number.Norm;\n                __ft__ phi = number.Argument;\n\n                __ft__ a = exponent.Real;\n                __ft__ b = exponent.Imag;\n\n                return __ct__.CreateRadial(Exp(Log(r) * a - b * phi), a * phi + b * Log(r));\n            }\n        }\n\n        /// <summary>\n        /// Returns the complex number <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Pow(this __ct__ number, __ft__ exponent)\n        {\n            if (number.IsZero)\n                return __ct__.Zero;\n            else\n            {\n                __ft__ r = number.Norm;\n                __ft__ phi = number.Argument;\n                return __ct__.CreateRadial(Pow(r, exponent), exponent * phi);\n            }\n        }\n\n        /// <summary>\n        /// Returns <paramref name=\"number\"/> raised to the power of <paramref name=\"exponent\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Pow(this __ft__ number, __ct__ exponent)\n        {\n            if (number == 0)\n                return __ct__.Zero;\n            else\n            {\n                __ft__ a = exponent.Real;\n                __ft__ b = exponent.Imag;\n\n                if (number < 0)\n                {\n                    var phi = __constant__.Pi;\n                    return __ct__.CreateRadial(Exp(Log(-number) * a - b * phi), a * phi + b * Log(-number));\n                }\n                else\n                    return __ct__.CreateRadial(Pow(number, a), b * Log(number));\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Power(this __ct__ number, __ct__ exponent)\n            => Pow(number, exponent);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Power(this __ct__ number, __ft__ exponent)\n            => Pow(number, exponent);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Power(this __ft__ number, __ct__ exponent)\n            => Pow(number, exponent);\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Returns the angle that is the arc cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Acos(this __ct__ x)\n        {\n            var t = Log(new __ct__(-x.Imag, x.Real) + Sqrt(1 - x * x));\n            return new __ct__(-t.Imag + __constant__.PiHalf, t.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Acosh(this __ct__ x)\n            => Log(x + Sqrt(x * x - 1));\n\n        /// <summary>\n        /// Returns the cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Cos(this __ct__ x)\n            => (\n                Exp(new __ct__(-x.Imag, x.Real)) +\n                Exp(new __ct__(x.Imag, -x.Real))\n            ) * __half__;\n\n        /// <summary>\n        /// Returns the hyperbolic cosine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Cosh(this __ct__ x)\n            => Cos(new __ct__(-x.Imag, x.Real));\n\n        /// <summary>\n        /// Returns the angle that is the arc sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Asin(this __ct__ x)\n        {\n            var t = Log(new __ct__(-x.Imag, x.Real) + Sqrt(1 - x * x));\n            return new __ct__(t.Imag, -t.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Asinh(this __ct__ x)\n            => Log(x + Sqrt(1 + x * x));\n\n        /// <summary>\n        /// Returns the sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Sin(this __ct__ x)\n        {\n            var a = Exp(new __ct__(-x.Imag, x.Real)) - Exp(new __ct__(x.Imag, -x.Real));\n            return new __ct__(a.Imag, -a.Real) * __half__;\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic sine of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Sinh(this __ct__ x)\n        {\n            var sin = Sin(new __ct__(-x.Imag, x.Real));\n            return new __ct__(sin.Imag, -sin.Real);\n        }\n\n        /// <summary>\n        /// Returns the angle that is the arc tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Atan(this __ct__ x)\n        {\n            if (x == __ct__.I)\n                return __ct__.PositiveInfinityI;\n            else if (x == -__ct__.I)\n                return __ct__.NegativeInfinityI;\n            else if (x == __ct__.PositiveInfinity)\n                return new __ct__(__constant__.PiHalf);\n            else if (x == __ct__.NegativeInfinity)\n                return new __ct__(-__constant__.PiHalf);\n            else\n                return new __ct__(0, __half__) * Log((__ct__.I + x) / (__ct__.I - x));\n        }\n\n        /// <summary>\n        /// Returns the angle that is the hyperbolic arc tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Atanh(this __ct__ x)\n        {\n            if (x == __ct__.Zero)\n                return __ct__.Zero;\n            else if (x == __ct__.One)\n                return __ct__.PositiveInfinity;\n            else if (x == __ct__.PositiveInfinity)\n                return new __ct__(0, -__constant__.PiHalf);\n            else if (x == __ct__.I)\n                return new __ct__(0, __constant__.PiQuarter);\n            else\n                return __half__ * (Log(1 + x) - Log(1 - x));\n        }\n\n        /// <summary>\n        /// Returns the tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Tan(this __ct__ x)\n        {\n            if (x == __ct__.PositiveInfinityI)\n                return __ct__.I;\n            else if (x == __ct__.NegativeInfinityI)\n                return -__ct__.I;\n            else\n                return Sin(x) / Cos(x);\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic tangent of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Tanh(this __ct__ x)\n        {\n            var tan = Tan(new __ct__(-x.Imag, x.Real));\n            return new __ct__(tan.Imag, -tan.Real);\n        }\n\n        #endregion\n\n        #region Exp, Log\n\n        /// <summary>\n        /// Returns e raised to the power of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Exp(this __ct__ x)\n            => new __ct__(Cos(x.Imag), Sin(x.Imag)) * Exp(x.Real);\n\n        /// <summary>\n        /// Returns the natural logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Log(this __ct__ x)\n            => new __ct__(Log(x.Norm), x.Argument);\n\n        /// <summary>\n        /// Returns the logarithm of the complex number <paramref name=\"x\"/> in the given basis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Log(this __ct__ x, __ft__ basis)\n            => x.Log() / basis.Log();\n\n        /// <summary>\n        /// Returns the base-10 logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Log10(this __ct__ x)\n            => Log(x, 10);\n\n        /// <summary>\n        /// Returns the base-2 logarithm of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Log2(this __ct__ x)\n            => x.Log() * __constant__.Ln2Inv;\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Returns the principal square root of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        // https://math.stackexchange.com/a/44500\n        // TODO: Check if this is actually better than the naive implementation\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Sqrt(this __ct__ x)\n        {\n            if (x.Imag == 0)\n            {\n                if (x.Real < 0)\n                    return new __ct__(0, Sqrt(-x.Real));\n                else\n                    return new __ct__(Sqrt(x.Real), 0);\n            }\n            else\n            {\n                var a = x.Norm;\n                var b = x + a;\n                return a.Sqrt() * (b / b.Norm);\n            }\n        }\n\n        /// <summary>\n        /// Returns the principal cubic root of the complex number <paramref name=\"x\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Cbrt(this __ct__ x)\n            => __ct__.CreateRadial(Cbrt(x.Norm), x.Argument / 3);\n\n        //# signedtypes.ForEach(t => { if (t != Meta.DecimalType) {\n        //# if (ftype == Meta.DoubleType ^ t == Meta.FloatType) {\n        /// <summary>\n        /// Returns the square root of the given real number and returns a complex number.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__ Csqrt(this __t.Name__ number)\n        {\n            if (number >= 0)\n            {\n                return new __ct__(Sqrt(number), 0);\n            }\n            else\n            {\n                return new __ct__(0, Sqrt(-number));\n            }\n        }\n        //# }}});\n\n        /// <summary>\n        /// Calculates both square roots of a complex number.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__[] Csqrt(this __ct__ number)\n        {\n            __ct__ res0 = __ct__.CreateRadial(Sqrt(number.Norm), number.Argument / 2);\n            __ct__ res1 = __ct__.CreateRadial(Sqrt(number.Norm), number.Argument / 2 + __constant__.Pi);\n\n            return new __ct__[2] { res0, res1 };\n        }\n\n        /// <summary>\n        /// Calculates the n-th root of a complex number and returns n solutions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ct__[] Root(this __ct__ number, int n)\n        {\n            __ct__[] values = new __ct__[n];\n\n            __ft__ invN = 1 / (__ft__)n;\n            __ft__ phi = number.Argument / n;\n            __ft__ dphi = __constant__.PiTimesTwo * invN;\n            __ft__ r = Pow(number.Norm, invN);\n\n            for (int i = 0; i < n; i++)\n            {\n                values[i] = __ct__.CreateRadial(r, phi + dphi * i);\n            }\n\n            return values;\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given complex numbers are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __ct__ a, __ct__ b, __ft__ tolerance)\n        {\n            return ApproximateEquals(a.Real, b.Real, tolerance) && ApproximateEquals(a.Imag, b.Imag, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given complex numbers are equal within\n        /// Constant&lt;__ft__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __ct__ a, __ct__ b)\n        {\n            return ApproximateEquals(a, b, Constant<__ft__>.PositiveTinyValue);\n        }\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ct__\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(__ct__ v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ct__\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(__ct__ v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ct__\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(__ct__ v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ct__\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(__ct__ v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__ct__\"/> is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(__ct__ v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    //# } // isDouble\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Constant.cs",
    "content": "using System;\n\nnamespace Aardvark.Base\n{\n    public enum Metric\n    {\n        Manhattan = 1,\n        Euclidean = 2,\n        Maximum = int.MaxValue,\n\n        L1 = Manhattan,\n        L2 = Euclidean,\n        LInfinity = Maximum,\n    }\n\n    public static class Constant<T>\n    {\n        /// <summary>\n        /// A value that is or is close to the minimum value of the type, but\n        /// can be parsed back without exception.\n        /// </summary>\n        public static readonly T ParseableMinValue;\n\n        /// <summary>\n        /// A value that is or is close to the maximum value of the type, but\n        /// can be parsed back without exception.\n        /// </summary>\n        public static readonly T ParseableMaxValue;\n\n        /// <summary>\n        /// The smallest value that can be added to 1.0 for obtaining a result\n        /// that is different from 1.0.\n        /// </summary>\n        public static readonly T MachineEpsilon;\n\n        /// <summary>\n        /// Four times the MachineEpsilon of the type.\n        /// </summary>\n        public static readonly T PositiveTinyValue;\n\n        /// <summary>\n        /// Minus four times the MachineEpsilon of the type.\n        /// </summary>\n        public static readonly T NegativeTinyValue;\n\n        static Constant()\n        {\n            if (typeof(T) == typeof(byte))\n            {\n                ParseableMinValue = (T)(object)byte.MinValue;\n                ParseableMinValue = (T)(object)byte.MinValue;\n                ParseableMaxValue = (T)(object)byte.MaxValue;\n                MachineEpsilon    = (T)(object)(byte)1;\n                PositiveTinyValue = (T)(object)(byte)4;\n            }\n            else if (typeof(T) == typeof(ushort))\n            {\n                ParseableMinValue = (T)(object)ushort.MinValue;\n                ParseableMaxValue = (T)(object)ushort.MaxValue;\n                MachineEpsilon    = (T)(object)(ushort)1;\n                PositiveTinyValue = (T)(object)(ushort)4;\n            }\n            else if (typeof(T) == typeof(uint))\n            {\n                ParseableMinValue = (T)(object)uint.MinValue;\n                ParseableMaxValue = (T)(object)uint.MaxValue;\n                MachineEpsilon    = (T)(object)(uint)1;\n                PositiveTinyValue = (T)(object)(uint)4;\n            }\n            else if (typeof(T) == typeof(ulong))\n            {\n                ParseableMinValue = (T)(object)ulong.MinValue;\n                ParseableMaxValue = (T)(object)ulong.MaxValue;\n                MachineEpsilon    = (T)(object)(ulong)1;\n                PositiveTinyValue = (T)(object)(ulong)4;\n            }\n            else if (typeof(T) == typeof(sbyte))\n            {\n                ParseableMinValue = (T)(object)sbyte.MinValue;\n                ParseableMaxValue = (T)(object)sbyte.MaxValue;\n                MachineEpsilon    = (T)(object)(sbyte)1;\n                PositiveTinyValue = (T)(object)(sbyte)4;\n                NegativeTinyValue = (T)(object)(sbyte)-4;\n            }\n            else if (typeof(T) == typeof(short))\n            {\n                ParseableMinValue = (T)(object)short.MinValue;\n                ParseableMaxValue = (T)(object)short.MaxValue;\n                MachineEpsilon    = (T)(object)(short)1;\n                PositiveTinyValue = (T)(object)(short)4;\n                NegativeTinyValue = (T)(object)(short)-4;\n            }\n            else if (typeof(T) == typeof(int))\n            {\n                ParseableMinValue = (T)(object)int.MinValue;\n                ParseableMaxValue = (T)(object)int.MaxValue;\n                MachineEpsilon    = (T)(object)1;\n                PositiveTinyValue = (T)(object)4;\n                NegativeTinyValue = (T)(object)-4;\n            }\n            else if (typeof(T) == typeof(long))\n            {\n                ParseableMinValue = (T)(object)long.MinValue;\n                ParseableMaxValue = (T)(object)long.MaxValue;\n                MachineEpsilon    = (T)(object)1L;\n                PositiveTinyValue = (T)(object)4L;\n                NegativeTinyValue = (T)(object)-4L;\n            }\n            else if (typeof(T) == typeof(float))\n            {\n                float floatEps = Fun.FloatFromBits(Fun.FloatToBits(1.0f) + 1) - 1.0f;\n                ParseableMinValue = (T)(object)(float.MinValue * 0.999999f);\n                ParseableMaxValue = (T)(object)(float.MaxValue * 0.999999f);\n                MachineEpsilon    = (T)(object)floatEps;\n                PositiveTinyValue = (T)(object)(4 * floatEps);\n                NegativeTinyValue = (T)(object)(-4 * floatEps);\n            }\n            else if (typeof(T) == typeof(double))\n            {\n                double doubleEps = Fun.FloatFromBits(Fun.FloatToBits(1.0) + 1L) - 1.0;\n                ParseableMinValue = (T)(object)(double.MinValue * 0.999999995);\n                ParseableMaxValue = (T)(object)(double.MaxValue * 0.999999995);\n                MachineEpsilon    = (T)(object)doubleEps;\n                PositiveTinyValue = (T)(object)(4 * doubleEps);\n                NegativeTinyValue = (T)(object)(-4 * doubleEps);\n            }\n        }\n    }\n\n    [Obsolete]\n    static class Constants\n    {\n        public static void Init()\n        {\n            var ignore1 = Constant<double>.MachineEpsilon;\n            var ignore2 = Constant<float>.MachineEpsilon;\n            var ignore3 = Constant<byte>.MachineEpsilon;\n            var ignore4 = Constant<sbyte>.MachineEpsilon;\n            var ignore5 = Constant<short>.MachineEpsilon;\n            var ignore6 = Constant<ushort>.MachineEpsilon;\n            var ignore7 = Constant<uint>.MachineEpsilon;\n            var ignore8 = Constant<int>.MachineEpsilon;\n            var ignore9 = Constant<long>.MachineEpsilon;\n            var ignore0 = Constant<ulong>.MachineEpsilon;\n        }\n    }\n\n    /// <summary>\n    /// Mathematical constants.\n    /// </summary>\n    public static class Constant\n    {\n        /// <summary>\n        /// Ratio of a circle's circumference to its diameter\n        /// in Euclidean geometry. Also known as Archimedes' constant.\n        /// </summary>\n        public const double Pi = 3.1415926535897932384626433832795;\n\n        /// <summary>\n        /// One divided by Pi (1 / Pi).\n        /// </summary>\n        public const double PiInv = 0.318309886183790671537767526745028724068919291480912897495;\n\n        /// <summary>\n        /// Two times PI: the circumference of the unit circle.\n        /// </summary>\n        public const double PiTimesTwo = 6.283185307179586476925286766559;\n\n        /// <summary>\n        /// Three times PI.\n        /// </summary>\n        public const double PiTimesThree = 9.424777960769379715387930149839;\n\n        /// <summary>\n        /// Four times PI: the surface area of the unit sphere.\n        /// </summary>\n        public const double PiTimesFour = 12.56637061435917295385057353312;\n\n        /// <summary>\n        /// Half of PI.\n        /// </summary>\n        public const double PiHalf = 1.570796326794896619231321691640;\n\n        /// <summary>\n        /// Quarter of PI.\n        /// </summary>\n        public const double PiQuarter = 0.78539816339744830961566084581988;\n\n        /// <summary>\n        /// Square of PI.\n        /// </summary>\n        public const double PiSquared = 9.869604401089358618834490999876;\n\n        /// <summary>\n        /// Sqrt(2 * PI).\n        /// </summary>\n        public const double SqrtPiTimesTwo = 2.5066282746310005024157652848110;\n\n        /// <summary>\n        /// Base of the natural logarithm.\n        /// Also known as Euler's number.\n        /// </summary>\n        public const double E = Math.E;\n\n        /// <summary>\n        /// Golden Ratio.\n        /// The golden ratio expresses the relationship that\n        /// the sum of two quantities is to the larger quantity\n        /// as the larger is to the smaller.\n        /// It is defined as (1 + sqrt(5)) / 2).\n        /// </summary>\n        public const double Phi = 1.61803398874989484820458683;\n\n        /// <summary>\n        /// Square root of 2.\n        /// </summary>\n        public const double Sqrt2 = 1.414213562373095048801688724209;\n\n        /// <summary>\n        /// Square root of 0.5.\n        /// </summary>\n        public const double Sqrt2Half = 0.70710678118654752440084436210485;\n\n        /// <summary>\n        /// Square root of 3.\n        /// </summary>\n        public const double Sqrt3 = 1.732050807568877293527446341505;\n\n        /// <summary>\n        /// Square root of 5.\n        /// </summary>\n        public const double Sqrt5 = 2.236067977499789696409173668731;\n\n        /// <summary>\n        /// Natural logarithm (base e) of 2.\n        /// </summary>\n        public const double Ln2 = 0.69314718055994530941723212145818;\n\n        /// <summary>\n        /// 1 divided by logarithm of 2 (base e).\n        /// </summary>\n        public const double Ln2Inv = 1.4426950408889634073599246810023;\n\n        /// <summary>\n        /// 1 divided by 3.\n        /// </summary>\n        public const double OneThird = 0.33333333333333333333333333333333;\n\n        /// <summary>\n        /// Used to convert degrees to radians.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const double RadiansPerDegree = Pi / 180.0;\n\n        /// <summary>\n        /// Used to convert radians to degrees.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const double DegreesPerRadian = 180.0 / Pi;\n\n        /// <summary>\n        /// Used to convert gons to radians.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const double RadiansPerGon = Pi / 200.0;\n\n        /// <summary>\n        /// Used to convert radians to gons.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const double GonsPerRadian = 200.0 / Pi;\n\n        /// <summary>\n        /// Used to convert gons to degrees.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const double DegreesPerGon = 180.0 / 200.0;\n\n        /// <summary>\n        /// Used to convert degrees to gons.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const double GonsPerDegree = 200.0 / 180.0;\n\n        /// <summary>\n        /// One sixtieth (1/60) of one degree (in radians).\n        /// </summary>\n        public const double ArcMinute = Pi / (180 * 60);\n\n        /// <summary>\n        /// One sixtieth (1/60) of one arc minute (in radians).\n        /// </summary>\n        public const double ArcSecond = Pi / (180 * 60 * 60);\n\n        /// <summary>\n        /// The speed of light in meters per second.\n        /// </summary>\n        public const double SpeedOfLight = 299792458.0;\n    }\n\n    /// <summary>\n    /// Mathematical constants.\n    /// </summary>\n    public static class ConstantF\n    {\n        /// <summary>\n        /// Ratio of a circle's circumference to its diameter\n        /// in Euclidean geometry. Also known as Archimedes' constant.\n        /// </summary>\n        public const float Pi = (float)Constant.Pi;\n\n        /// <summary>\n        /// One divided by Pi (1 / Pi).\n        /// </summary>\n        public const float PiInv = (float)Constant.PiInv;\n\n        /// <summary>\n        /// Two times PI: the circumference of the unit circle.\n        /// </summary>\n        public const float PiTimesTwo = (float)Constant.PiTimesTwo;\n\n        /// <summary>\n        /// Twree times PI.\n        /// </summary>\n        public const float PiTimesThree = (float)Constant.PiTimesThree;\n\n        /// <summary>\n        /// Four times PI: the surface area of the unit sphere.\n        /// </summary>\n        public const float PiTimesFour = (float)Constant.PiTimesFour;\n\n        /// <summary>\n        /// Half of PI.\n        /// </summary>\n        public const float PiHalf = (float)Constant.PiHalf;\n\n        /// <summary>\n        /// Quarter of PI.\n        /// </summary>\n        public const float PiQuarter = (float)Constant.PiQuarter;\n\n        /// <summary>\n        /// Square of PI.\n        /// </summary>\n        public const float PiSquared = (float)Constant.PiSquared;\n\n        /// <summary>\n        /// Sqrt(2 * PI).\n        /// </summary>\n        public const float SqrtPiTimesTwo = (float)Constant.SqrtPiTimesTwo;\n\n        /// <summary>\n        /// Base of the natural logarithm.\n        /// Also known as Euler's number.\n        /// </summary>\n        public const float E = (float)Constant.E;\n\n        /// <summary>\n        /// Golden Ratio.\n        /// The golden ratio expresses the relationship that\n        /// the sum of two quantities is to the larger quantity\n        /// as the larger is to the smaller.\n        /// It is defined as (1 + sqrt(5)) / 2).\n        /// </summary>\n        public const float Phi = (float)Constant.Phi;\n\n        /// <summary>\n        /// Square root of 2.\n        /// </summary>\n        public const float Sqrt2 = (float)Constant.Sqrt2;\n\n        /// <summary>\n        /// Square root of 0.5.\n        /// </summary>\n        public const float Sqrt2Half = (float)Constant.Sqrt2Half;\n\n        /// <summary>\n        /// Square root of 3.\n        /// </summary>\n        public const float Sqrt3 = (float)Constant.Sqrt3;\n\n        /// <summary>\n        /// Square root of 5.\n        /// </summary>\n        public const float Sqrt5 = (float)Constant.Sqrt5;\n\n        /// <summary>\n        /// Natural logarithm (base e) of 2.\n        /// </summary>\n        public const float Ln2 = (float)Constant.Ln2;\n\n        /// <summary>\n        /// 1 divided by logarithm of 2 (base e).\n        /// </summary>\n        public const float Ln2Inv = (float)Constant.Ln2Inv;\n\n        /// <summary>\n        /// 1 divided by 3.\n        /// </summary>\n        public const float OneThird = (float)Constant.OneThird;\n\n        /// <summary>\n        /// Used to convert degrees to radians.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const float RadiansPerDegree = (float)Constant.RadiansPerDegree;\n\n        /// <summary>\n        /// Used to convert radians to degrees.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const float DegreesPerRadian = (float)Constant.DegreesPerRadian;\n        /// <summary>\n        /// Used to convert gons to radians.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const float RadiansPerGon = (float)Constant.RadiansPerGon;\n        /// <summary>\n        /// Used to convert radians to gons.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const float GonsPerRadian = (float)Constant.GonsPerRadian;\n        /// <summary>\n        /// Used to convert gons to degrees.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const float DegreesPerGon = (float)Constant.DegreesPerGon;\n\n        /// <summary>\n        /// Used to convert degrees to gons.\n        /// See also <see cref=\"Conversion\"/> class.\n        /// </summary>\n        public const float GonsPerDegree = (float)Constant.GonsPerDegree;\n\n        /// <summary>\n        /// One sixtieth (1/60) of one degree (in radians).\n        /// </summary>\n        public const float ArcMinute = (float)Constant.ArcMinute;\n\n        /// <summary>\n        /// One sixtieth (1/60) of one arc minute (in radians).\n        /// </summary>\n        public const float ArcSecond = (float)Constant.ArcSecond;\n\n        /// <summary>\n        /// The speed of light in meters per second.\n        /// </summary>\n        public const float SpeedOfLight = (float)Constant.SpeedOfLight;\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Conversion.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n\n    /// <summary>\n    /// Conversion routines.\n    /// </summary>\n    public static partial class Conversion\n    {\n        #region Spherical <-> Cartesian\n\n        /// <summary>\n        /// Returns unit vector in direction (phi, theta).\n        /// Phi is rotation in xy-plane (x-axis is 0, y-axis is pi/2, ...).\n        /// Positive theta rotates towards positive z-axis.\n        /// </summary>\n        public static V3d CartesianFromSpherical(double phi, double theta)\n        {\n            var s = theta.Cos();\n            return new V3d(phi.Cos() * s, phi.Sin() * s, theta.Sin());\n        }\n\n        /// <summary>\n        /// Returns unit vector in direction (phi, theta).\n        /// Phi is rotation in xy-plane (x-axis is 0, y-axis is pi/2, ...).\n        /// Positive theta rotates towards positive z-axis.\n        /// </summary>\n        public static V3d CartesianFromSpherical(this V2d phiAndTheta)\n        {\n            return CartesianFromSpherical(phiAndTheta.X, phiAndTheta.Y);\n        }\n\n        /// <summary>\n        /// Returns unit vector in direction phi.\n        /// Phi is rotation in xy-plane (x-axis is 0, y-axis is pi/2, ...).\n        /// </summary>\n        public static V2d CartesianFromSpherical(this double phi)\n        {\n            return new V2d(phi.Cos(), phi.Sin());\n        }\n\n        /// <summary>\n        /// Returns spherical direction (phi, theta) from Cartesian direction.\n        /// </summary>\n        public static V2d SphericalFromCartesian(this V3d v)\n        {\n            return new V2d(\n                Fun.Atan2(v.Y, v.X), // phi\n                Fun.Atan2(v.Z, v.XY.Length) // theta\n                );\n        }\n\n        /// <summary>\n        /// Returns spherical direction (phi) from Cartesian direction.\n        /// </summary>\n        public static double SphericalFromCartesian(this V2d v)\n        {\n            return Fun.Atan2(v.Y, v.X);\n        }\n\n        #endregion\n\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts an angle given in radians to degrees.\n        /// </summary>\n        public static float DegreesFromRadians(this float radians)\n        {\n            return radians * ConstantF.DegreesPerRadian;\n        }\n\n        /// <summary>\n        /// Converts an angle given in radians to degrees.\n        /// </summary>\n        public static double DegreesFromRadians(this double radians)\n        {\n            return radians * Constant.DegreesPerRadian;\n        }\n\n        /// <summary>\n        /// Converts an angle given in degrees to radians.\n        /// </summary>\n        public static float RadiansFromDegrees(this float degrees)\n        {\n            return degrees * ConstantF.RadiansPerDegree;\n        }\n\n        /// <summary>\n        /// Converts an angle given in degrees to radians.\n        /// </summary>\n        public static double RadiansFromDegrees(this double degrees)\n        {\n            return degrees * Constant.RadiansPerDegree;\n        }\n\n        /// <summary>\n        /// Converts an angle given in gons to degrees.\n        /// </summary>\n        public static float DegreesFromGons(this float gons)\n        {\n            return gons * ConstantF.DegreesPerGon;\n        }\n\n        /// <summary>\n        /// Converts an angle given in gons to degrees.\n        /// </summary>\n        public static double DegreesFromGons(this double gons)\n        {\n            return gons * Constant.DegreesPerGon;\n        }\n\n        /// <summary>\n        /// Converts an angle given in gons to radians.\n        /// </summary>\n        public static float RadiansFromGons(this float gons)\n        {\n            return gons * ConstantF.RadiansPerGon;\n        }\n\n        /// <summary>\n        /// Converts an angle given in gons to radians.\n        /// </summary>\n        public static double RadiansFromGons(this double gons)\n        {\n            return gons * Constant.RadiansPerGon;\n        }\n\n        /// <summary>\n        /// Converts an angle given in degrees to gons.\n        /// </summary>\n        public static float GonsFromDegrees(this float degrees)\n        {\n            return degrees * ConstantF.GonsPerDegree;\n        }\n\n        /// <summary>\n        /// Converts an angle given in degrees to gons.\n        /// </summary>\n        public static double GonsFromDegrees(this double degrees)\n        {\n            return degrees * Constant.GonsPerDegree;\n        }\n\n        /// <summary>\n        /// Converts an angle given in radians to gons.\n        /// </summary>\n        public static float GonsFromRadians(this float radians)\n        {\n            return radians * ConstantF.GonsPerRadian;\n        }\n\n        /// <summary>\n        /// Converts an angle given in radians to gons.\n        /// </summary>\n        public static double GonsFromRadians(this double radians)\n        {\n            return radians * Constant.GonsPerRadian;\n        }\n\n        #endregion\n\n        #region Temperature\n\n        /// <summary>\n        /// Converts a temperature given in Fahrenheit to Celsius.\n        /// </summary>\n        public static float CelsiusFromFahrenheit(this float fahrenheit)\n        {\n            return (fahrenheit - 32.0f) / 1.8f;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Fahrenheit to Celsius.\n        /// </summary>\n        public static double CelsiusFromFahrenheit(this double fahrenheit)\n        {\n            return (fahrenheit - 32.0) / 1.8;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Celsius to Fahrenheit.\n        /// </summary>\n        public static float FahrenheitFromCelsius(this float celsius)\n        {\n            return (celsius * 1.8f) + 32.0f;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Celsius to Fahrenheit.\n        /// </summary>\n        public static double FahrenheitFromCelsius(this double celsius)\n        {\n            return (celsius * 1.8) + 32.0;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Fahrenheit to Kelvin.\n        /// </summary>\n        public static float KelvinFromFahrenheit(this float fahrenheit)\n        {\n            return (fahrenheit + 459.67f) / 1.8f;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Fahrenheit to Kelvin.\n        /// </summary>\n        public static double KelvinFromFahrenheit(this double fahrenheit)\n        {\n            return (fahrenheit + 459.67) / 1.8;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Kelvin to Fahrenheit.\n        /// </summary>\n        public static float FahrenheitFromKelvin(this float kelvin)\n        {\n            return (kelvin * 1.8f) - 459.67f;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Kelvin to Fahrenheit.\n        /// </summary>\n        public static double FahrenheitFromKelvin(this double kelvin)\n        {\n            return (kelvin * 1.8) - 459.67;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Kelvin to Celsius.\n        /// </summary>\n        public static float CelsiusFromKelvin(this float kelvin)\n        {\n            return kelvin - 273.15f;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Kelvin to Celsius.\n        /// </summary>\n        public static double CelsiusFromKelvin(this double kelvin)\n        {\n            return kelvin - 273.15;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Celsius to Kelvin.\n        /// </summary>\n        public static float KelvinFromCelsius(this float celsius)\n        {\n            return celsius + 273.15f;\n        }\n\n        /// <summary>\n        /// Converts a temperature given in Celsius to Kelvin.\n        /// </summary>\n        public static double KelvinFromCelsius(this double celsius)\n        {\n            return celsius + 273.15;\n        }\n\n        #endregion\n\n        #region Byte order (little endian / big endian)\n\n        #region HostToNetworkOrder\n\n        public static byte[] HostToNetworkOrder(short x)\n        {\n            byte[] data = BitConverter.GetBytes(x);\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return data;\n        }\n\n        public static byte[] HostToNetworkOrder(ushort x)\n        {\n            byte[] data = BitConverter.GetBytes(x);\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return data;\n        }\n\n        public static byte[] HostToNetworkOrder(int x)\n        {\n            byte[] data = BitConverter.GetBytes(x);\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return data;\n        }\n\n        public static byte[] HostToNetworkOrder(uint x)\n        {\n            byte[] data = BitConverter.GetBytes(x);\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return data;\n        }\n\n        public static byte[] HostToNetworkOrder(long x)\n        {\n            byte[] data = BitConverter.GetBytes(x);\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return data;\n        }\n\n        public static byte[] HostToNetworkOrder(ulong x)\n        {\n            byte[] data = BitConverter.GetBytes(x);\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return data;\n        }\n\n        public static byte[] HostToNetworkOrder(float x)\n        {\n            byte[] data = BitConverter.GetBytes(x);\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return data;\n        }\n\n        public static byte[] HostToNetworkOrder(double x)\n        {\n            byte[] data = BitConverter.GetBytes(x);\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return data;\n        }\n\n        #endregion\n\n        #region NetworkToHostOrder\n\n        public static short NetworkToHostOrderInt16(byte[] data)\n        {\n            byte[] copy = (byte[])data.Clone();\n            if (BitConverter.IsLittleEndian) ReverseBytes(copy);\n            return BitConverter.ToInt16(copy, 0);\n        }\n\n        public static short NetworkToHostOrderInt16InPlace(byte[] data)\n        {\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return BitConverter.ToInt16(data, 0);\n        }\n\n        public static ushort NetworkToHostOrderUInt16(byte[] data)\n        {\n            byte[] copy = (byte[])data.Clone();\n            if (BitConverter.IsLittleEndian) ReverseBytes(copy);\n            return BitConverter.ToUInt16(copy, 0);\n        }\n\n        public static ushort NetworkToHostOrderUInt16InPlace(byte[] data)\n        {\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return BitConverter.ToUInt16(data, 0);\n        }\n\n        public static int NetworkToHostOrderInt32(byte[] data)\n        {\n            byte[] copy = (byte[])data.Clone();\n            if (BitConverter.IsLittleEndian) ReverseBytes(copy);\n            return BitConverter.ToInt32(copy, 0);\n        }\n\n        public static int NetworkToHostOrderInt32InPlace(byte[] data)\n        {\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return BitConverter.ToInt32(data, 0);\n        }\n\n        public static uint NetworkToHostOrderUInt32(byte[] data)\n        {\n            byte[] copy = (byte[])data.Clone();\n            if (BitConverter.IsLittleEndian) ReverseBytes(copy);\n            return BitConverter.ToUInt32(copy, 0);\n        }\n\n        public static uint NetworkToHostOrderUInt32InPlace(byte[] data)\n        {\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return BitConverter.ToUInt32(data, 0);\n        }\n\n        public static long NetworkToHostOrderInt64(byte[] data)\n        {\n            byte[] copy = (byte[])data.Clone();\n            if (BitConverter.IsLittleEndian) ReverseBytes(copy);\n            return BitConverter.ToInt64(copy, 0);\n        }\n\n        public static long NetworkToHostOrderInt64InPlace(byte[] data)\n        {\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return BitConverter.ToInt64(data, 0);\n        }\n\n        public static ulong NetworkToHostOrderUInt64(byte[] data)\n        {\n            byte[] copy = (byte[])data.Clone();\n            if (BitConverter.IsLittleEndian) ReverseBytes(copy);\n            return BitConverter.ToUInt64(copy, 0);\n        }\n\n        public static ulong NetworkToHostOrderUInt64InPlace(byte[] data)\n        {\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return BitConverter.ToUInt64(data, 0);\n        }\n\n        public static float NetworkToHostOrderSingle(byte[] data)\n        {\n            byte[] copy = (byte[])data.Clone();\n            if (BitConverter.IsLittleEndian) ReverseBytes(copy);\n            return BitConverter.ToSingle(copy, 0);\n        }\n\n        public static float NetworkToHostOrderSingleInPlace(byte[] data)\n        {\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return BitConverter.ToSingle(data, 0);\n        }\n\n        public static double NetworkToHostOrderDouble(byte[] data)\n        {\n            byte[] copy = (byte[])data.Clone();\n            if (BitConverter.IsLittleEndian) ReverseBytes(copy);\n            return BitConverter.ToDouble(copy, 0);\n        }\n\n        public static double NetworkToHostOrderDoubleInPlace(byte[] data)\n        {\n            if (BitConverter.IsLittleEndian) ReverseBytes(data);\n            return BitConverter.ToDouble(data, 0);\n        }\n\n        #endregion\n\n        /// <summary>\n        /// Reverses elements of given byte array.\n        /// </summary>\n        public static void ReverseBytes(byte[] data)\n        {\n            int length = data.Length;\n            int maxIndex = length - 1;\n            for (int i = 0; i < length / 2; i++)\n            {\n                int j = maxIndex - i;\n                byte tmp = data[i]; data[i] = data[j]; data[j] = tmp;\n            }\n        }\n\n        #endregion\n\n        #region Color\n\n        /// <summary>\n        /// Converts XYZ-color to Lab-color\n        /// </summary>\n        /// <param name=\"xyz\"></param>\n        /// <returns></returns>\n        public static C3f XYZToLab(this C3f xyz)\n        {\n            var X = xyz.R / XREF;\n            var Y = xyz.G / YREF;\n            var Z = xyz.B / ZREF;\n\n            var fx = f(X);\n            var fy = f(Y);\n            var fz = f(Z);\n\n            var L = (116 * fy) - 16;\n            var a = 500 * (fx - fy);\n            var b = 200 * (fy - fz);\n            return new C3f(L, a, b);\n        }\n\n        /// <summary>\n        /// converts Lab-color to XYZ-color\n        /// </summary>\n        /// <param name=\"lab\">L=[0,100], a=[-150,150], b=[-150,150]</param>\n        /// <returns></returns>\n        public static C3f LabToXYZ(this C3f lab)\n        {\n            var L = lab.R;\n            var a = lab.G;\n            var b = lab.B;\n\n            var d = (1.0f / 116.0f) * (L + 16);\n            var Y = YREF * fInv(d);\n            var X = XREF * fInv(d + a / 500.0f);\n            var Z = ZREF * fInv(d - b / 200.0f);\n            return new C3f(X, Y, Z);\n        }\n\n        private static float f(float t)\n        {\n            if (t > 0.008856)\n                return t.Pow(1.0f / 3.0f);\n            return (903.3f * t + 16f) / 116f;   //(1.0f / 3.0f) * (float)(29.0f / 6.0f).Square() * t + (4.0f / 29.0f);\n        }\n        private static float fInv(float t)\n        {\n            if (t > 0.20689) \n                return t.Pow(3);\n            return (t * 116f - 16) / 903.3f;  //3 * (float)(6.0f / 29.0f).Square() * (t - 4.0f / 29.0f);\n        }\n        private const float XREF = 0.95f; // Illuminant= D65\n        private const float YREF = 1f;\n        private const float ZREF = 1.09f;\n\n        #endregion\n    }\n\n    public static class ColorConversion\n    {\n        public static C3f FromYuvToYxy(this C3f Yuv)\n        {\n            var Y = Yuv.R;\n            var u = Yuv.G;\n            var v = Yuv.B;\n\n            return new C3f(Y,\n                           3 * u / (2 * u - 8 * v + 4),\n                           2 * v / (2 * u - 8 * v + 4));\n        }\n\n        public static C3f FromYxyToXYZ(this C3f Yxy)\n        {\n            double Y = Yxy.R;\n            double x = Yxy.G;\n            double y = Yxy.B;\n\n            //AZ: check for y == 0  needed - szabo: DONE\n            if (y == 0) y = double.Epsilon;\n\n            return new C3f((x * (Y / y)), Y, ((1 - x - y) * (Y / y)));\n        }\n\n        public static C3f FromXYZToYxy(this C3f XYZ)\n        {\n            double Y = XYZ.G;\n            double x = XYZ.R / (XYZ.R + XYZ.G + XYZ.B);\n            double y = XYZ.G / (XYZ.R + XYZ.G + XYZ.B);\n\n            return new C3f(Y, x, y);\n        }\n\n        /// <summary>\n        /// Returns the GamutMap represantion of the supplied C3f.\n        /// </summary>\n        public static C3f ToGamutMap(this C3f self)\n        {\n            return self.Clamped(0.0f, 1.0f);\n        }\n\n        /// <summary>\n        /// Returns the int representation of the supplied C3f color.\n        /// </summary>\n        public static int FromRgbToInt(this C3f self)\n        {\n            return Col.FloatToByte(self.R) << 16 |\n                   Col.FloatToByte(self.G) << 8 |\n                   Col.FloatToByte(self.B);\n\n\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/DistributionFunction.cs",
    "content": "﻿using System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Represents a discrete function that is represented by a probability density function (PDF)\n    /// and a cumulative distribution function (CDF).\n    /// </summary>\n    public class DistributionFunction\n    {\n        readonly double[] m_pdf;\n        readonly double[] m_cdf;\n\n        /// <summary>\n        /// Gets the input probability density function.\n        /// It is not necessarily normalized.\n        /// </summary>\n        public double[] PDF { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return m_pdf; } }\n\n        /// <summary>\n        /// Gets the calculated cumulative distribution function with +1 elements than the PDF.\n        /// It is not necessarily normalized.\n        /// </summary>\n        public double[] CDF { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return m_cdf; } }\n\n        /// <summary>\n        /// Returns the normalization factor of the PDF and CDF.\n        /// In case the supplied PDF is not normalized this factor will be != 1.0 and\n        /// needs to be considered when interpreting the raw PDF or CDF values.\n        /// </summary>\n        public double Norm { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return m_cdf[m_cdf.Length - 1]; } }\n\n        /// <summary>\n        /// Create distribution from a discrete probability distribution function (PDF).\n        /// The PDF does not need to be normalized.\n        /// </summary>\n        public DistributionFunction(double[] pdf)\n        {\n            m_pdf = pdf;\n            m_cdf = m_pdf.Integrated();\n        }\n\n        /// <summary>\n        /// Create distribution from a discrete probability distribution function (PDF) \n        /// and its cumulative distribution function (CDF).\n        /// The PDF does not need to be normalized.\n        /// </summary>\n        public DistributionFunction(double[] pdf, double[] cdf)\n        {\n            m_pdf = pdf;\n            m_cdf = cdf;\n        }\n\n        /// <summary>\n        /// Retrieve random index distributed proportional to probability density function.\n        /// Uses binary search O(log n).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public int Sample(IRandomUniform rnd)\n        {\n            return Sample(rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Retrieve index to the discrete PDF where its cumulative distribution matches the random variable x1 [0, 1].\n        /// Uses binary search O(log n).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public int Sample(double x1)\n        {\n            return SampleCDF(m_cdf, x1);\n        }\n\n        /// <summary>\n        /// Retrieve random index of a discretized PDF given its cumulative distribution function (CDF).\n        /// Uses binary search O(log n).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int SampleCDF(double[] cdf, IRandomUniform rnd)\n        {\n            return SampleCDF(cdf, rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Retrieve index of a discrete PDF given its cumulative distribution function (CDF) and a random variable x1 [0, 1].\n        /// Uses binary search O(log n).\n        /// </summary>\n        public static int SampleCDF(double[] cdf, double x1)\n        {\n            var range = cdf.Length;\n            var valueToFind = x1 * cdf[range - 1]; // x1 * sum -> CDF threshold to find\n\n            var i0 = 0;\n            // binary search\n            while (range > 0)\n            {\n                var halfRange = range >> 1;\n                var center = i0 + halfRange;\n\n                // check if value is left or right\n                if (cdf[center] <= valueToFind)\n                {\n                    // right half\n                    i0 = center + 1;\n                    range -= halfRange + 1;\n                }\n                else\n                {\n                    // left half\n                    range = halfRange;\n                }\n            }\n            return Fun.Clamp(i0 - 1, 0, cdf.Length - 2);\n        }\n\n        /// <summary>\n        /// Gets the normalized probability density function value at the supplied index.\n        /// The function is normalized to integrate to a value of 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public double PDFValue(int index)\n        {\n            return m_pdf[index] / this.Norm;\n        }\n\n        /// <summary>\n        /// Gets the normalized cumulative distribution function value at the supplied index.\n        /// The function is normalized to integrate to a value of 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public double CDFValue(int index)\n        {\n            return m_cdf[index] / this.Norm;\n        }\n\n        /// <summary>\n        /// Inplace update of the CDF by re-integerating the PDF.\n        /// </summary>\n        public void UpdateCDF()\n        {\n            var cdf = m_cdf;\n            var pdf = m_pdf;\n            cdf[0] = 0;\n            double acc = 0;\n            for (int i = 0; i < pdf.Length;)\n            {\n                acc += pdf[i++];\n                cdf[i] = acc;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Fraction.cs",
    "content": "﻿using System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Represents an integral fraction.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public struct Fraction\n    {\n        [DataMember]\n        public long Numerator;\n        [DataMember]\n        public long Denominator;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fraction(long value)\n        {\n            Numerator = value;\n            Denominator = 1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Fraction(long numerator, long denominator)\n        {\n            // ensure positive denominator\n            Numerator = denominator < 0 ? -numerator : numerator;\n            Denominator = Fun.Abs(denominator);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly double Value\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (double)Numerator / Denominator; }\n        }\n\n        public readonly Fraction Reduced\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                long gcd = Fun.GreatestCommonDivisor(Numerator, Denominator);\n                return new Fraction(Numerator / gcd, Denominator / gcd);\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction operator +(Fraction a)\n        {\n            return a;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction operator -(Fraction a)\n        {\n            return new Fraction(-a.Numerator, a.Denominator);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction operator +(Fraction a, Fraction b)\n        {\n            long gcd = Fun.GreatestCommonDivisor(a.Denominator, b.Denominator);\n            long aDenomDivGcd = a.Denominator / gcd;\n\n            return new Fraction(\n                a.Numerator * (b.Denominator / gcd)\n                + b.Numerator * aDenomDivGcd,\n                aDenomDivGcd * b.Denominator\n                );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction operator -(Fraction a, Fraction b)\n        {\n            return a + (-b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction operator *(Fraction a, Fraction b)\n        {\n            return new Fraction(\n                a.Numerator * b.Numerator,\n                a.Denominator * b.Denominator\n                );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction operator /(Fraction a, Fraction b)\n        {\n            if (b.Numerator < 0)        // ensure positive denominator\n                return new Fraction(\n                    -a.Numerator * b.Denominator,\n                    -b.Numerator * a.Denominator\n                    );\n\n            return new Fraction(\n                a.Numerator * b.Denominator,\n                a.Denominator * b.Numerator\n                );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator <(Fraction a, Fraction b)\n        {\n            return a.Value < b.Value;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator <=(Fraction a, Fraction b)\n        {\n            return a.Value <= b.Value;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Fraction a, Fraction b)\n        {\n            return a.Value == b.Value;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Fraction a, Fraction b)\n        {\n            return a.Value != b.Value;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator >=(Fraction a, Fraction b)\n        {\n            return a.Value >= b.Value;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator >(Fraction a, Fraction b)\n        {\n            return a.Value > b.Value;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets a <see cref=\"Fraction\"/> that evaluates to 0.\n        /// </summary>\n        public static Fraction Zero => new Fraction(0, 1);\n\n        /// <summary>\n        /// Gets a <see cref=\"Fraction\"/> that evaluates to 1.\n        /// </summary>\n        public static Fraction One => new Fraction(1, 1);\n\n        /// <summary>\n        /// Gets the smallest positive <see cref=\"Fraction\"/> value greater than zero.\n        /// </summary>\n        public static Fraction Epsilon => new Fraction(1, long.MaxValue);\n\n        /// <summary>\n        /// Gets the smallest possible value of a <see cref=\"Fraction\"/>.\n        /// </summary>\n        public static Fraction MinValue => new Fraction(long.MinValue, 1);\n\n        /// <summary>\n        /// Gets the largest possible value of a <see cref=\"Fraction\"/>.\n        /// </summary>\n        public static Fraction MaxValue => new Fraction(long.MaxValue, 1);\n\n        /// <summary>\n        /// Gets a value that is not a number (NaN).\n        /// </summary>\n        public static Fraction NaN => new Fraction(0, 0);\n\n        /// <summary>\n        /// Represents negative infinity.\n        /// </summary>\n        public static Fraction NegativeInfinity => new Fraction(-1, 0);\n       \n        /// <summary>\n        /// Represents positive infinity.\n        /// </summary>\n        public static Fraction PositiveInfinity => new Fraction(+1, 0);\n\n        #endregion\n\n        /// <summary>\n        /// Returns whether the specified <see cref=\"Fraction\"/>\n        /// evaluates to negative or positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(Fraction f)\n        {\n            return f.Denominator == 0;\n        }\n\n        /// <summary>\n        /// Returns whether the specified <see cref=\"Fraction\"/>\n        /// evaluates to negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(Fraction f)\n        {\n            return f.Denominator == 0 && f.Numerator < 0;\n        }\n\n        /// <summary>\n        /// Returns whether the specified <see cref=\"Fraction\"/>\n        /// evaluates to positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(Fraction f)\n        {\n            return f.Denominator == 0 && f.Numerator > 0;\n        }\n\n        /// <summary>\n        /// Returns whether the specified <see cref=\"Fraction\"/>\n        /// evaluates to a value that is not a number (Fraction.NaN).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(Fraction f)\n        {\n            return f.Denominator == 0;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Fraction other)\n            => Numerator.Equals(other.Numerator) && Denominator.Equals(other.Denominator);\n\n        public override readonly bool Equals(object obj)\n            => (obj is Fraction o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return Value.GetHashCode();\n        }\n\n        public override readonly string ToString()\n        {\n            return Numerator + \"/\" + Denominator;\n        }\n\n        public static Fraction Parse(string s)\n        {\n            int sep = s.IndexOf('/');\n            if (sep < 0) return new Fraction(long.Parse(s));\n            return new Fraction(\n                long.Parse(s.Substring(0, sep)),\n                long.Parse(s.Substring(sep+1, s.Length-sep-1))\n                );\n        }\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Fraction\"/> are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Fraction a, Fraction b, double tolerance)\n            => ApproximateEquals(a.Value, b.Value, tolerance);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"Fraction\"/> are equal within\n        /// Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Fraction a, Fraction b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Fun.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics.Contracts;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    public enum Winding\n    {\n        CCW = 0,\n        CW = 1,\n    }\n\n    /// <summary>\n    /// This enum can be used to store an aggregate sign classification\n    /// of multiple entities whose sign ccan be classified.\n    /// </summary>\n    [Flags]\n    public enum Signs\n    {\n        None = 0x00,\n        Zero = 0x01,\n        Negative = 0x02,\n        Positive = 0x04,\n\n        NonPositive = Negative | Zero,\n        NonNegative = Positive | Zero,\n    }\n\n    public static partial class Fun\n    {\n        public static T Identity<T>(T value) { return value; }\n\n        #region Array Indices of Certain Elements\n\n        /// <summary>\n        /// For an array of monotonically increasing values, returns\n        /// the index i of the largest value such that array[i] &lt;= x.\n        /// If x is smaller than the first value, then -1 is returned.\n        /// If x is greater than the last value, then a.Length is returned.\n        /// </summary>\n        public static int IndexOfLargestLessOrEqual<T>(this T[] a, T x)\n            where T : IComparable\n        {\n            var r = new Range1i(0, a.Length - 1);\n            if (x.CompareTo(a[0]) < 0) return -1;\n            if (x.CompareTo(a[r.Max]) > 0) return a.Length;\n            while (r.Size > 1)\n            {\n                var half = r.Center;\n                if (x.CompareTo(a[half]) < 0) r.Max = half; else r.Min = half;\n            }\n            return r.Min;\n        }\n\n        /// <summary>\n        /// For an array of monotonically increasing values, returns\n        /// the index i of the largest value such that array[i] &lt;= x.\n        /// If x is smaller than the first value, then -1 is returned.\n        /// If x is greater than the last value, then a.Length is returned.\n        /// </summary>\n        public static long LongIndexOfLargestLessOrEqual<T>(this T[] a, T x)\n            where T : IComparable\n        {\n            var r = new Range1l(0, a.Length - 1);\n            if (x.CompareTo(a[0]) < 0) return -1;\n            if (x.CompareTo(a[r.Max]) > 0) return a.Length;\n            while (r.Size > 1)\n            {\n                var half = r.Center;\n                if (x.CompareTo(a[half]) < 0) r.Max = half; else r.Min = half;\n            }\n            return r.Min;\n        }\n\n        /// <summary>\n        /// For a list of monotonically increasing values, returns\n        /// the index i of the largest value such that list[i] &lt;= x.\n        /// If x is smaller than the first value, then -1 is returned.\n        /// If x is greater than the last value, then a.Count is returned.\n        /// </summary>\n        public static int IndexOfLargestLessOrEqual<T>(this List<T> a, T x)\n            where T : IComparable\n        {\n            var r = new Range1i(0, a.Count - 1);\n            if (x.CompareTo(a[0]) < 0) return -1;\n            if (x.CompareTo(a[r.Max]) > 0) return a.Count;\n            while (r.Size > 1)\n            {\n                int half = r.Center;\n                if (x.CompareTo(a[half]) < 0) r.Max = half; else r.Min = half;\n            }\n            return r.Min;\n        }\n\n        #endregion\n\n        #region Bit Operations\n\n        public static int HighestBit(this int i)\n        {\n            if (i == 0) return -1;\n\n            int bit = 31;\n\n            if ((i & 0xFFFFFF00) == 0) { i <<= 24; bit = 7; }\n            else if ((i & 0xFFFF0000) == 0) { i <<= 16; bit = 15; }\n            else if ((i & 0xFF000000) == 0) { i <<= 8; bit = 23; }\n\n            if ((i & 0xF0000000) == 0) { i <<= 4; bit -= 4; }\n            while ((i & 0x80000000) == 0) { i <<= 1; bit--; }\n            return bit;\n        }\n\n        public static int TrailingZeroBitCount(this long x)\n        {\n            x &= -x;\n            int c = (x == 0) ? 1 : 0;\n            if ((x & 0x00000000ffffffffL) == 0) c += 32;\n            if ((x & 0x0000ffff0000ffffL) == 0) c += 16;\n            if ((x & 0x00ff00ff00ff00ffL) == 0) c += 8;\n            if ((x & 0x0f0f0f0f0f0f0f0fL) == 0) c += 4;\n            if ((x & 0x3333333333333333L) == 0) c += 2;\n            if ((x & 0x5555555555555555L) == 0) c += 1;\n            return c;\n        }\n\n        public static int TrailingZeroBitCount(this int x)\n        {\n            x &= -x;\n            int c = (x == 0) ? 1 : 0;\n            if ((x & 0x0000ffff) == 0) c += 16;\n            if ((x & 0x00ff00ff) == 0) c += 8;\n            if ((x & 0x0f0f0f0f) == 0) c += 4;\n            if ((x & 0x33333333) == 0) c += 2;\n            if ((x & 0x55555555) == 0) c += 1;\n            return c;\n        }\n\n        #endregion\n\n        #region Bitwise Rotation\n\n        /// <summary>\n        /// Bitwise circular left shift.\n        /// </summary>\n        public static int BitwiseRotateLeft(this int value, int numberOfBits)\n        {\n            return (value << numberOfBits) | (value >> (32 - numberOfBits));\n        }\n\n        /// <summary>\n        /// Bitwise circular left shift.\n        /// </summary>\n        public static uint BitwiseRotateLeft(this uint value, int numberOfBits)\n        {\n            return (value << numberOfBits) | (value >> (32 - numberOfBits));\n        }\n\n        /// <summary>\n        /// Bitwise circular left shift.\n        /// </summary>\n        public static long BitwiseRotateLeft(this long value, int numberOfBits)\n        {\n            return (value << numberOfBits) | (value >> (64 - numberOfBits));\n        }\n\n        /// <summary>\n        /// Bitwise circular left shift.\n        /// </summary>\n        public static ulong BitwiseRotateLeft(this ulong value, int numberOfBits)\n        {\n            return (value << numberOfBits) | (value >> (64 - numberOfBits));\n        }\n\n        #endregion\n\n        #region Digits Counts of Integer/Fractional Parts\n\n        public static int DigitCountOfIntegerPart(this double value)\n        {\n            var str = value.ToString(CultureInfo.InvariantCulture);\n            var x = str.Split('.');\n            return x[0].Length;\n        }\n\n        public static int DigitCountOfFractionalPart(this double value)\n        {\n            var str = value.ToString(CultureInfo.InvariantCulture);\n            var x = str.Split('.');\n            return x.Length < 2 ? 0 : x[1].Length;\n        }\n\n        public static int DigitCountOfIntegerPart(this float value)\n        {\n            return ((double)value).DigitCountOfIntegerPart();\n        }\n\n        public static int DigitCountOfFractionalPart(this float value)\n        {\n            return ((double)value).DigitCountOfFractionalPart();\n        }\n\n        #endregion\n\n        #region Monotony\n\n        public static bool IsMonotonicallyIncreasing<T>(this IEnumerable<T> self)\n            where T : IComparable\n        {\n            foreach (var p in self.PairChain())\n                if (p.Item1.CompareTo(p.Item2) > 0) return false;\n            return true;\n        }\n\n        public static bool IsStrictlyIncreasing<T>(this IEnumerable<T> self)\n            where T : IComparable\n        {\n            foreach (var p in self.PairChain())\n                if (p.Item1.CompareTo(p.Item2) >= 0) return false;\n            return true;\n        }\n\n        public static bool IsMonotonicallyDecreasing<T>(this IEnumerable<T> self)\n            where T : IComparable\n        {\n            foreach (var p in self.PairChain())\n                if (p.Item1.CompareTo(p.Item2) < 0) return false;\n            return true;\n        }\n\n        public static bool IsStrictlyDecreasing<T>(this IEnumerable<T> self)\n            where T : IComparable\n        {\n            foreach (var p in self.PairChain())\n                if (p.Item1.CompareTo(p.Item2) <= 0) return false;\n            return true;\n        }\n\n        #endregion\n\n        #region Outer Sum\n\n        public static Tup4<long> OuterSum(Tup2<long> x, Tup2<long> y)\n        {\n            return new Tup4<long>(x.E0 + y.E0, x.E1 + y.E0,\n                                  x.E0 + y.E1, x.E1 + y.E1);\n        }\n\n        public static Tup8<long> OuterSum(Tup2<long> x, Tup2<long> y, Tup2<long> z)\n        {\n            long y0z0 = y.E0 + z.E0, y1z0 = y.E1 + z.E0, y0z1 = y.E0 + z.E1, y1z1 = y.E1 + z.E1;\n            return new Tup8<long>(x.E0 + y0z0, x.E1 + y0z0, x.E0 + y1z0, x.E1 + y1z0,\n                                  x.E0 + y0z1, x.E1 + y0z1, x.E0 + y1z1, x.E1 + y1z1);\n        }\n\n        public static Tup16<long> OuterSum(Tup4<long> x, Tup4<long> y)\n        {\n            return new Tup16<long>(x.E0 + y.E0, x.E1 + y.E0, x.E2 + y.E0, x.E3 + y.E0,\n                                   x.E0 + y.E1, x.E1 + y.E1, x.E2 + y.E1, x.E3 + y.E1,\n                                   x.E0 + y.E2, x.E1 + y.E2, x.E2 + y.E2, x.E3 + y.E2,\n                                   x.E0 + y.E3, x.E1 + y.E3, x.E2 + y.E3, x.E3 + y.E3);\n        }\n\n        #endregion\n\n        #region Relative Epsilon\n\n        public static float PlusRelativeEps(this float value, float eps)\n        {\n            if (value > 0) return value + eps * value;\n            if (value < 0) return value - eps * value;\n            return eps > 0\n                    ? value + Constant<float>.PositiveTinyValue\n                    : value - Constant<float>.PositiveTinyValue;\n        }\n\n        public static float MinusRelativeEps(this float value, float eps)\n        {\n            if (value > 0) return value - eps * value;\n            if (value < 0) return value + eps * value;\n            return eps > 0\n                    ? value - Constant<float>.PositiveTinyValue\n                    : value + Constant<float>.PositiveTinyValue;\n        }\n\n        public static double PlusRelativeEps(this double value, float eps)\n        {\n            if (value > 0) return value + eps * value;\n            if (value < 0) return value - eps * value;\n            return eps > 0\n                    ? value + Constant<float>.PositiveTinyValue\n                    : value - Constant<float>.PositiveTinyValue;\n        }\n\n        public static double MinusRelativeEps(this double value, float eps)\n        {\n            if (value > 0) return value - eps * value;\n            if (value < 0) return value + eps * value;\n            return eps > 0\n                    ? value - Constant<double>.PositiveTinyValue\n                    : value + Constant<double>.PositiveTinyValue;\n        }\n\n\n        #endregion\n\n        #region Shannon Entropy\n\n        /// <summary>\n        /// Shannon entropy of values.\n        /// </summary>\n        public static double Entropy<T>(this IEnumerable<T> xs)\n        {\n            double total = xs.Count();\n            return xs.GroupBy(x => x)\n                .Select(g => { double p = g.Count() / total; return p * -p.Log2(); })\n                .Sum();\n        }\n\n        /// <summary>\n        /// Shannon entropy of bipartite set.\n        /// </summary>\n        public static double Entropy<T>(this bool[] xs)\n        {\n            if (xs == null) throw new ArgumentNullException(\"xs\");\n\n            var count = xs.Length;\n            var countPos = 0;\n            var countNeg = 0;\n\n            for (var i = 0; i < count; i++)\n            {\n                if (xs[i])\n                {\n                    countPos++;\n                }\n                else\n                {\n                    countNeg++;\n                }\n            }\n            if (countPos == 0 || countNeg == 0) return 0.0;\n\n            var pPos = countPos / (double)count;\n            var pNeg = countNeg / (double)count;\n            var hPos = -Math.Log(pPos, 2);\n            var hNeg = -Math.Log(pNeg, 2);\n            var H = pPos * hPos + pNeg * hNeg;\n            return H;\n        }\n\n        /// <summary>\n        /// Shannon entropy of weighted bipartite set.\n        /// </summary>\n        public static double Entropy(this bool[] xs, double[] weights)\n        {\n            if (weights == null) throw new ArgumentNullException(\"weights\");\n            if (xs == null) throw new ArgumentNullException(\"xs\");\n            if (weights.Length != xs.Length) throw new ArgumentException(\"weights.Length != xs.Length\");\n\n            var count = xs.Length;\n            var countPos = 0.0;\n            var countNeg = 0.0;\n\n            for (var i = 0; i < count; i++)\n            {\n                if (xs[i])\n                {\n                    countPos += weights[i];\n                }\n                else\n                {\n                    countNeg += weights[i];\n                }\n            }\n            if (countPos == 0 || countNeg == 0) return 0.0;\n\n            var pPos = countPos / (double)count;\n            var pNeg = countNeg / (double)count;\n            var hPos = -Math.Log(pPos, 2);\n            var hNeg = -Math.Log(pNeg, 2);\n            var H = pPos * hPos + pNeg * hNeg;\n            return H;\n        }\n\n        #endregion\n\n        #region Step\n\n        [Pure]\n        public static T Step<T>(this float x, T a, T b)\n        { return x < 0.5f ? a : b; }\n\n        [Pure]\n        public static T Step<T>(this double x, T a, T b)\n        { return x < 0.5 ? a : b; }\n\n        #endregion\n\n        #region Weight Functions for Interpolation\n\n        /// <summary>\n        /// Creates weight function for cubic interpolation according to\n        /// \"Comparison of Interpolating for Image Resampling\" by\n        /// J.A.Parker, R.V.Kenyon &amp; D.E.Troxel, IEEE Transactions on\n        /// Medical Imaging Vol. 2, 1983. Recommended values for a:\n        /// -0.5 for medical/astronomical images, -1.0 for other photos.\n        /// a = -0.5 exactly reconstructs second degree polynomials,\n        /// a = -0.75 results in a continuous second derivative of the \n        /// two polynomials used\n        /// a = -1.0 matches the slope of the sinc function at 1\n        /// (amplifying frequencies just below the cutoff frequency)\n        /// </summary>\n        public static Func<double, Tup4<double>> CreateCubicTup4d(double a)\n        {\n            double ap2 = a + 2;\n            double ap3 = a + 3;\n            return t =>\n            {\n                double tt = t * t;\n                double tastta = (t - tt) * a, ttasttta = t * tastta;\n                double ttap3stttap2 = tt * (ap3 - t * ap2);\n                return new Tup4<double>(tastta - ttasttta, 1 - ttap3stttap2,\n                                         ttap3stttap2 - tastta, ttasttta);\n                // Weights:\n                // a t^3 - 2 a t^2 + a t            = t ( a - a t (2 - t))\n                // (a+2) t^3 - (a+3) t^2 + 1        = 1 - t^2 ((a+3) - (a+2) t)\n                // -(a+2) t^3 + (2a+3) t^2 - a t    = t ( -a + t ((2a + 3) - (a+2) t))\n                // -a t^3 + a t^2                   = t^2 a (1 - t)\n            };\n        }\n\n        /// <summary>\n        /// Creates weight function for cubic interpolation according to\n        /// \"Comparison of Interpolating for Image Resampling\" by\n        /// J.A.Parker, R.V.Kenyon &amp; D.E.Troxel, IEEE Transactions on\n        /// Medical Imaging Vol. 2, 1983. Recommended values for a:\n        /// -0.5 for medical/astronomical images, -1.0 for other photos.\n        /// a = -0.5 exactly reconstructs second degree polynomials,\n        /// a = -0.75 results in a continuous second derivative of the \n        /// two polynomials used\n        /// a = -1.0 matches the slope of the sinc function at 1\n        /// (amplifying frequencies just below the cutoff frequency)\n        /// </summary>\n        public static Func<double, Tup4<Half>> CreateCubicTup4h(double a)\n        {\n            double ap2 = a + 2;\n            double ap3 = a + 3;\n            return t =>\n            {\n                double tt = t * t;\n                double tastta = (t - tt) * a, ttasttta = t * tastta;\n                double ttap3stttap2 = tt * (ap3 - t * ap2);\n                return new Tup4<Half>((Half)(tastta - ttasttta), (Half)(1 - ttap3stttap2),\n                                      (Half)(ttap3stttap2 - tastta), (Half)ttasttta);\n            };\n        }\n\n        /// <summary>\n        /// Creates weight function for cubic interpolation according to\n        /// \"Comparison of Interpolating for Image Resampling\" by\n        /// J.A.Parker, R.V.Kenyon &amp; D.E.Troxel, IEEE Transactions on\n        /// Medical Imaging Vol. 2, 1983. Recommended values for a:\n        /// -0.5 for medical/astronomical images, -1.0 for other photos.\n        /// a = -0.5 exactly reconstructs second degree polynomials,\n        /// a = -0.75 results in a continuous second derivative of the \n        /// two polynomials used\n        /// a = -1.0 matches the slope of the sinc function at 1\n        /// (amplifying frequencies just below the cutoff frequency)\n        /// </summary>\n        public static Func<double, Tup4<float>> CreateCubicTup4f(double a)\n        {\n            double ap2 = a + 2;\n            double ap3 = a + 3;\n            return t =>\n            {\n                double tt = t * t;\n                double tastta = (t - tt) * a, ttasttta = t * tastta;\n                double ttap3stttap2 = tt * (ap3 - t * ap2);\n                return new Tup4<float>((float)(tastta - ttasttta), (float)(1 - ttap3stttap2),\n                                       (float)(ttap3stttap2 - tastta), (float)ttasttta);\n            };\n        }\n\n        /// <summary>\n        /// Returns the weights of the cubic B-Spline function for four\n        /// equally distant function points to approximate. The supplied\n        /// parameter t in the range [0..1] traverses the approximation\n        /// between the two center points.\n        /// </summary>\n        public static Tup4<double> BSpline3d(double t) => new Tup4<double>(\n            t*(t*(t*(-1/6.0) + 3/6.0) - 3/6.0) + 1/6.0,\n            t*(t*(t*( 3/6.0) - 6/6.0)        ) + 4/6.0,\n            t*(t*(t*(-3/6.0) + 3/6.0) + 3/6.0) + 1/6.0,\n            t*(t*(t*( 1/6.0)        )        )        );\n\n        /// <summary>\n        /// Returns the weights of the cubic B-Spline function for four\n        /// equally distant function points to approximate. The supplied\n        /// parameter t in the range [0..1] traverses the approximation\n        /// between the two center points.\n        /// </summary>\n        public static Tup4<Half> BSpline3h(double t) => new Tup4<Half>(\n            (Half)(t*(t*(t*(-1/6.0) + 3/6.0) - 3/6.0) + 1/6.0),\n            (Half)(t*(t*(t*( 3/6.0) - 6/6.0)        ) + 4/6.0),\n            (Half)(t*(t*(t*(-3/6.0) + 3/6.0) + 3/6.0) + 1/6.0),\n            (Half)(t*(t*(t*( 1/6.0)        )        )        ));\n\n        /// <summary>\n        /// Returns the weights of the cubic B-Spline function for four\n        /// equally distant function points to approximate. The supplied\n        /// parameter t in the range [0..1] traverses the approximation\n        /// between the two center points.\n        /// </summary>\n        public static Tup4<float> BSpline3f(double t) => new Tup4<float>(\n            (float)(t*(t*(t*(-1/6.0) + 3/6.0) - 3/6.0) + 1/6.0),\n            (float)(t*(t*(t*( 3/6.0) - 6/6.0)        ) + 4/6.0),\n            (float)(t*(t*(t*(-3/6.0) + 3/6.0) + 3/6.0) + 1/6.0),\n            (float)(t*(t*(t*( 1/6.0)        )        )        ));\n\n        /// <summary>\n        /// Returns the weights of the order 5 B-Spline function for six\n        /// equally distant function points to approximate. The supplied\n        /// parameter t in the range [0..1] traverses the approximation\n        /// between the two center points.\n        /// </summary>\n        public static Tup6<double> BSpline5d(double t) => new Tup6<double>(\n            t*(t*(t*(t*(t*( -1/120.0)  +5/120.0) -10/120.0) +10/120.0)  -5/120.0)  +1/120.0,\n            t*(t*(t*(t*(t*(  5/120.0) -20/120.0) +20/120.0) +20/120.0) -50/120.0) +26/120.0,\n            t*(t*(t*(t*(t*(-10/120.0) +30/120.0)          ) -60/120.0)          ) +66/120.0,\n            t*(t*(t*(t*(t*( 10/120.0) -20/120.0) -20/120.0) +20/120.0) +50/120.0) +26/120.0,\n            t*(t*(t*(t*(t*( -5/120.0)  +5/120.0) +10/120.0) +10/120.0)  +5/120.0)  +1/120.0,\n            t*(t*(t*(t*(t*(  1/120.0) \t\t   ) \t\t  ) \t         ) \t        )          );\n\n        /// <summary>\n        /// Returns the weights of the order 5 B-Spline function for six\n        /// equally distant function points to approximate. The supplied\n        /// parameter t in the range [0..1] traverses the approximation\n        /// between the two center points.\n        /// </summary>\n        public static Tup6<Half> BSpline5h(double t) => new Tup6<Half>(\n            (Half)(t*(t*(t*(t*(t*( -1/120.0)  +5/120.0) -10/120.0) +10/120.0)  -5/120.0)  +1/120.0),\n            (Half)(t*(t*(t*(t*(t*(  5/120.0) -20/120.0) +20/120.0) +20/120.0) -50/120.0) +26/120.0),\n            (Half)(t*(t*(t*(t*(t*(-10/120.0) +30/120.0)          ) -60/120.0)          ) +66/120.0),\n            (Half)(t*(t*(t*(t*(t*( 10/120.0) -20/120.0) -20/120.0) +20/120.0) +50/120.0) +26/120.0),\n            (Half)(t*(t*(t*(t*(t*( -5/120.0)  +5/120.0) +10/120.0) +10/120.0)  +5/120.0)  +1/120.0),\n            (Half)(t*(t*(t*(t*(t*(  1/120.0) \t\t   ) \t\t  ) \t         ) \t        )          ));\n\n        /// <summary>\n        /// Returns the weights of the order 5 B-Spline function for six\n        /// equally distant function points to approximate. The supplied\n        /// parameter t in the range [0..1] traverses the approximation\n        /// between the two center points.\n        /// </summary>\n        public static Tup6<float> BSpline5f(double t) => new Tup6<float>(\n            (float)(t*(t*(t*(t*(t*( -1/120.0)  +5/120.0) -10/120.0) +10/120.0)  -5/120.0)  +1/120.0),\n            (float)(t*(t*(t*(t*(t*(  5/120.0) -20/120.0) +20/120.0) +20/120.0) -50/120.0) +26/120.0),\n            (float)(t*(t*(t*(t*(t*(-10/120.0) +30/120.0)          ) -60/120.0)          ) +66/120.0),\n            (float)(t*(t*(t*(t*(t*( 10/120.0) -20/120.0) -20/120.0) +20/120.0) +50/120.0) +26/120.0),\n            (float)(t*(t*(t*(t*(t*( -5/120.0)  +5/120.0) +10/120.0) +10/120.0)  +5/120.0)  +1/120.0),\n            (float)(t*(t*(t*(t*(t*(  1/120.0) \t\t   ) \t\t  ) \t         ) \t        )          ));\n\n        public static Tup6<double> Lanczos3d(double x)\n        {\n            const double a = 1.0/3.0;\n            double px = Constant.Pi * x, pxa = px * a;\n            if (pxa.IsTiny()) return new Tup6<double>(0.0, 0.0, 1.0, 0.0, 0.0, 0.0);\n            double p1mx = Constant.Pi - px, p1mxa = p1mx * a;\n            if (p1mxa.IsTiny()) return new Tup6<double>(0.0, 0.0, 0.0, 1.0, 0.0, 0.0);\n\n            double p1px = Constant.Pi + px, p2px = Constant.PiTimesTwo + px;\n            double p2mx = Constant.PiTimesTwo - px, p3mx = Constant.PiTimesThree - px;\n            double spx = Fun.Sin(px), spxa = Fun.Sin(pxa);\n            double sp1pxa = Fun.Sin(p1px * a), sp2pxa = Fun.Sin(p2px * a);\n\n            return new Tup6<double>(spx * sp2pxa / (p2px * p2px * a),\n                                    -spx * sp1pxa / (p1px * p1px * a),\n                                    (spx / px) * (spxa / pxa),\n                                    (spx / p1mx) * (sp2pxa / p1mxa),\n                                    -spx * sp1pxa / (p2mx * p2mx * a),\n                                    spx * spxa / (p3mx * p3mx * a));\n        }\n\n        public static Tup6<Half> Lanczos3h(double x)\n        {\n            const double a = 1.0 / 3.0;\n            double px = Constant.Pi * x, pxa = px * a;\n            if (pxa.IsTiny()) return new Tup6<Half>((Half)0.0f, (Half)0.0f, (Half)1.0f, (Half)0.0f, (Half)0.0f, (Half)0.0f);\n            double p1mx = Constant.Pi - px, p1mxa = p1mx * a;\n            if (p1mxa.IsTiny()) return new Tup6<Half>((Half)0.0f, (Half)0.0f, (Half)0.0f, (Half)1.0f, (Half)0.0f, (Half)0.0f);\n\n            double p1px =   Constant.Pi + px,           p2px =  Constant.PiTimesTwo + px;\n            double p2mx =   Constant.PiTimesTwo - px,   p3mx =  Constant.PiTimesThree - px;\n            double spx =    Fun.Sin(px),                spxa =  Fun.Sin(pxa);\n            double sp1pxa = Fun.Sin(p1px * a),          sp2pxa = Fun.Sin(p2px * a);\n\n            return new Tup6<Half>( (Half)(spx * sp2pxa / (p2px * p2px * a)),\n                                    (Half)(-spx * sp1pxa / (p1px * p1px * a)),\n                                    (Half)((spx / px) * (spxa / pxa)),\n                                    (Half)((spx / p1mx) * (sp2pxa / p1mxa)),\n                                    (Half)(-spx * sp1pxa / (p2mx * p2mx * a)),\n                                    (Half)(spx * spxa / (p3mx * p3mx * a)));\n        }\n\n        public static Tup6<float> Lanczos3f(double x)\n        {\n            const double a = 1.0 / 3.0;\n            double px = Constant.Pi * x, pxa = px * a;\n            if (pxa.IsTiny()) return new Tup6<float>(0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);\n            double p1mx = Constant.Pi - px, p1mxa = p1mx * a;\n            if (p1mxa.IsTiny()) return new Tup6<float>(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);\n\n            double p1px =   Constant.Pi + px,           p2px =  Constant.PiTimesTwo + px;\n            double p2mx =   Constant.PiTimesTwo - px,   p3mx =  Constant.PiTimesThree - px;\n            double spx =    Fun.Sin(px),                spxa =  Fun.Sin(pxa);\n            double sp1pxa = Fun.Sin(p1px * a),          sp2pxa = Fun.Sin(p2px * a);\n\n            return new Tup6<float>( (float)(spx * sp2pxa / (p2px * p2px * a)),\n                                    (float)(-spx * sp1pxa / (p1px * p1px * a)),\n                                    (float)((spx / px) * (spxa / pxa)),\n                                    (float)((spx / p1mx) * (sp2pxa / p1mxa)),\n                                    (float)(-spx * sp1pxa / (p2mx * p2mx * a)),\n                                    (float)(spx * spxa / (p3mx * p3mx * a)));\n        }\n\n        #endregion\n\n        #region Pythagoras\n\n        /// <summary>\n        /// Computes sqrt(a²+b²) without destructive underflow or overflow.\n        /// </summary>\n        public static double Pythag(double a, double b)\n        {\n            double at = a > 0 ? a : -a, bt = b > 0 ? b : -b, ct, result;\n\n            if (at > bt) { ct = bt / at; result = at * Math.Sqrt(1.0 + ct * ct); }\n            else if (bt > 0.0) { ct = at / bt; result = bt * Math.Sqrt(1.0 + ct * ct); }\n            else result = 0.0;\n            return result;\n        }\n\n        #endregion\n\n        #region Log2Int\n\n        /// <summary>\n        /// the number of bits used for storing the double-mantissa\n        /// </summary>\n        public const int DoubleMantissaBits = 52;\n\n        /// <summary>\n        /// the bitmask used for the double exponent\n        /// </summary>\n        public const ulong DoubleExponentMask = 0x7FF0000000000000;\n\n        /// <summary>\n        /// the bitmask used for the double mantissa\n        /// </summary>\n        public const ulong DoubleMantissaMask = 0x000FFFFFFFFFFFFF;\n\n        /// <summary>\n        /// the number of bits used for storing the float-mantissa\n        /// </summary>\n        public const int FloatMantissaBits = 23;\n\n        /// <summary>\n        /// the bitmask used for the float exponent\n        /// </summary>\n        public const uint FloatExponentMask = 0x7F800000;\n\n        /// <summary>\n        /// the bitmask used for the float mantissa\n        /// </summary>\n        public const uint FloatMantissaMask = 0x007FFFFF;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static unsafe int Log2IntRef(ref double v)\n        {\n            fixed (double* ptr = &v)\n            {\n                var a = (ulong*)ptr;\n                return (int)(((*a & DoubleExponentMask) >> DoubleMantissaBits)) - 1023;\n            }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static unsafe int Log2IntRef(ref float v)\n        {\n            fixed (float* ptr = &v)\n            {\n                var a = (uint*)ptr;\n                return (int)(((*a & FloatExponentMask) >> FloatMantissaBits)) - 127;\n            }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static unsafe int Log2CeilingIntRef(ref double v)\n        {\n            fixed (double* ptr = &v)\n            {\n                var a = (ulong*)ptr;\n                var shift = (*a & DoubleMantissaMask) > 0 ? 1022 : 1023;\n                return (int)(((*a & DoubleExponentMask) >> DoubleMantissaBits)) - shift;\n            }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static unsafe int Log2CeilingIntRef(ref float v)\n        {\n            fixed (float* ptr = &v)\n            {\n                var a = (uint*)ptr;\n                var shift = (*a & FloatMantissaMask) > 0 ? 126 : 127;\n                return (int)(((*a & FloatExponentMask) >> FloatMantissaBits)) - shift;\n            }\n        }\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2Int(this double v)\n            => Log2IntRef(ref v);\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2Int(this float v)\n            => Log2IntRef(ref v);\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2Int(this int v)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return System.Numerics.BitOperations.Log2((uint)v);\n            #else\n                return Log2Int((float)v);\n            #endif\n        }\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2Int(this uint v)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return System.Numerics.BitOperations.Log2(v);\n            #else\n                return Log2Int((float)v);\n            #endif\n        }\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2Int(this long v)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return System.Numerics.BitOperations.Log2((ulong)v);\n            #else\n                return Log2Int((double)v);\n            #endif\n        }\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2Int(this ulong v)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return System.Numerics.BitOperations.Log2(v);\n            #else\n                return Log2Int((double)v);\n            #endif\n        }\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2CeilingInt(this double v)\n            => Log2CeilingIntRef(ref v);\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2CeilingInt(this float v)\n            => Log2CeilingIntRef(ref v);\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2CeilingInt(this int v)\n            => Log2CeilingInt((float)v);\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2CeilingInt(this uint v)\n            => Log2CeilingInt((float)v);\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2CeilingInt(this long v)\n            => Log2CeilingInt((double)v);\n\n        /// <summary>\n        /// Efficiently computes the Log2 for the given value rounded to the next integer towards positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Log2CeilingInt(this ulong v)\n            => Log2CeilingInt((double)v);\n\n        #endregion\n\n        #region Mipmap levels\n\n        /// <summary>\n        /// Computes the number of 3D images in a mipmap chain with the given base size.\n        /// </summary>\n        /// <param name=\"baseSize\">The size of the image in the base level.</param>\n        /// <returns>The total number of levels.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MipmapLevels(V3i baseSize)\n            => 1 + Log2Int(baseSize.MaxElement);\n\n        /// <summary>\n        /// Computes the number of 2D images in a mipmap chain with the given base size.\n        /// </summary>\n        /// <param name=\"baseSize\">The size of the image in the base level.</param>\n        /// <returns>The total number of levels.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MipmapLevels(V2i baseSize)\n            => 1 + Log2Int(baseSize.MaxElement);\n\n        /// <summary>\n        /// Computes the number of 1D images in a mipmap chain with the given base size.\n        /// </summary>\n        /// <param name=\"baseSize\">The size of the image in the base level.</param>\n        /// <returns>The total number of levels.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MipmapLevels(int baseSize)\n            => 1 + Log2Int(baseSize);\n\n        /// <summary>\n        /// Computes the size of a 3D image in a mipmap chain.\n        /// </summary>\n        /// <param name=\"baseSize\">The size of the image in the base level.</param>\n        /// <param name=\"level\">The level of the queried image (base level = 0).</param>\n        /// <returns>The size of the image at the given level.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i MipmapLevelSize(V3i baseSize, int level)\n            => Max(baseSize >> level, 1);\n\n        /// <summary>\n        /// Computes the size of a 2D image in a mipmap chain.\n        /// </summary>\n        /// <param name=\"baseSize\">The size of the image in the base level.</param>\n        /// <param name=\"level\">The level of the queried image (base level = 0).</param>\n        /// <returns>The size of the image at the given level.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i MipmapLevelSize(V2i baseSize, int level)\n            => Max(baseSize >> level, 1);\n\n        /// <summary>\n        /// Computes the size of a 1D image in a mipmap chain.\n        /// </summary>\n        /// <param name=\"baseSize\">The size of the image in the base level.</param>\n        /// <param name=\"level\">The level of the queried image (base level = 0).</param>\n        /// <returns>The size of the image at the given level.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MipmapLevelSize(int baseSize, int level)\n            => Max(baseSize >> level, 1);\n\n        #endregion\n\n        #region Gaussian\n\n        /// <summary>\n        /// Returns the function value of the normalized Gaussian distribution\n        /// with the given standard deviation.\n        /// </summary>\n        public static double Gauss(double x, double stdDev)\n        {\n            var rcpS = 1.0 / stdDev;\n            return rcpS / Constant.SqrtPiTimesTwo * Fun.Exp(-0.5 * (x * stdDev).Square());\n        }\n\n        /// <summary>\n        /// Returns the function value of the normalized elliptical 2d Gaussian distribution\n        /// with different standard deviations in x and y.\n        /// </summary>\n        public static double Gauss2d(double x, double y, double sx, double sy)\n        {\n            return 1.0 / (sx * sy * Constant.PiTimesTwo) * Fun.Exp(-0.5 * ((x / sx).Square() + (y / sy).Square()));\n        }\n\n        /// <summary>\n        /// Returns the function value of the normalized elliptical 2d Gaussian distribution\n        /// with different standard deviations in x and y.\n        /// </summary>\n        public static double Gauss2d(V2d p, double sx, double sy)\n        {\n            return 1.0 / (sx * sy * Constant.PiTimesTwo) * Fun.Exp(-0.5 * ((p.X / sx).Square() + (p.Y / sy).Square()));\n        }\n\n        /// <summary>\n        /// Returns the function value of the normalized 2d Gaussian distribution with \n        /// given symmetrical standard deviation.\n        /// </summary>\n        public static double Gauss2d(double x, double y, double s)\n        {\n            var halfRcpS2 = 0.5 / s.Square();\n            return halfRcpS2 * Constant.PiInv * Fun.Exp(-(x * x + y * y) * halfRcpS2);\n        }\n\n        /// <summary>\n        /// Returns the function value of the normalized 2d Gaussian distribution with \n        /// given symmetrical standard deviation.\n        /// </summary>\n        public static double Gauss2d(V2d p, double s)\n        {\n            var halfRcpS2 = 0.5 / s.Square();\n            return halfRcpS2 * Constant.PiInv * Fun.Exp(-p.LengthSquared * halfRcpS2);\n        }\n\n        /// <summary>\n        /// Gaussian error function using a numerical approximation\n        /// https://www.johndcook.com/blog/csharp_erf/\n        /// </summary>\n        public static double Erf(double x)\n        {\n            // constants\n            double a1 =  0.254829592;\n            double a2 = -0.284496736;\n            double a3 =  1.421413741;\n            double a4 = -1.453152027;\n            double a5 =  1.061405429;\n            double p  =  0.3275911;\n\n            // Save the sign of x\n            int sign = 1;\n            if (x < 0)\n                sign = -1;\n            x = Math.Abs(x);\n\n            // A&S formula 7.1.26\n            double t = 1.0 / (1.0 + p * x);\n            double y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.Exp(-x * x);\n\n            return sign * y;\n        }\n\n        /// <summary>\n        /// Gaussian error function using a numerical approximation with \n        /// a maximum error of 1.2e-7\n        /// Wikipedia https://en.wikipedia.org/wiki/Error_function#Numerical_approximations\n        /// </summary>\n        public static double Erf2(double x)\n        {\n            // constants\n            double a = -1.26551223;\n            double b =  1.00002368;\n            double c =  0.37409196;\n            double d =  0.09678418;\n            double e = -0.18628806;\n            double f =  0.27886807;\n            double g = -1.13520398;\n            double h =  1.48851587;\n            double j = -0.82215223;\n            double k =  0.17087277;\n\n            var t = 1.0 / (1.0 + 0.5 * x.Abs());\n            var r = t * Fun.Exp(-x.Square() + a + t * (b + t * (c + t * (d + t * (e + t * (f + t * (g + t * (h + t * (j + t * k)))))))));\n\n            return x >= 0 ? 1 - r : r - 1;\n        }\n\n        #endregion\n    }\n\n    #region KahanSum\n\n    /// <summary>\n    /// A simple quadruple precision sum (around 108 bit) based on Kahan's\n    /// summation method. This is used in Stats, to maintain higher precision\n    /// sums for statistical moment computation.\n    /// </summary>\n    public struct KahanSum\n    {\n        private double m_sum;\n        private double m_carry;\n\n        public KahanSum(double sum, double carry)\n        {\n            m_sum = sum;\n            m_carry = carry;\n        }\n\n        public KahanSum(double sum)\n            : this(sum, 0.0)\n        { }\n\n        public void Add(double value)\n        {\n            double y = value - m_carry;\n            double t = m_sum + y;\n            m_carry = (t - m_sum) - y;\n            m_sum = t;\n        }\n\n        public void Sub(double value)\n        {\n            double y = -value - m_carry;\n            double t = m_sum + y;\n            m_carry = (t - m_sum) - y;\n            m_sum = t;\n        }\n\n        public void Add(KahanSum sum)\n        {\n            Sub(sum.m_carry);\n            Add(sum.m_sum);\n        }\n\n        public void Sub(KahanSum sum)\n        {\n            Add(sum.m_carry);\n            Sub(sum.m_sum);\n        }\n\n        public readonly double Value\n        {\n            get { return m_sum; }\n        }\n\n        public static KahanSum operator +(KahanSum sum, double value)\n        {\n            double y = value - sum.m_carry;\n            double t = sum.m_sum + y;\n            return new KahanSum(t, (t - sum.m_sum) - y);\n        }\n\n        public static KahanSum operator -(KahanSum sum, double value)\n        {\n            double y = -value - sum.m_carry;\n            double t = sum.m_sum + y;\n            return new KahanSum(t, (t - sum.m_sum) - y);\n        }\n\n        public static KahanSum operator +(KahanSum sum0, KahanSum sum1)\n        {\n            var r = sum0 - sum1.m_carry;\n            r.Add(sum1.m_sum);\n            return r;\n        }\n\n        public static KahanSum operator -(KahanSum sum0, KahanSum sum1)\n        {\n            var r = sum0 + sum1.m_carry;\n            r.Sub(sum1.m_sum);\n            return r;\n        }\n\n        public static readonly KahanSum Zero = new KahanSum(0.0);\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Fun_auto.cs",
    "content": "using System;\nusing System.ComponentModel;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Diagnostics.Contracts;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Min(this byte a, byte b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Max(this byte a, byte b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Min(this byte a, byte b, byte c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Max(this byte a, byte b, byte c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Min(this byte a, byte b, byte c, byte d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Max(this byte a, byte b, byte c, byte d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Min(this byte x, params byte[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Max(this byte x, params byte[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Min(this sbyte a, sbyte b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Max(this sbyte a, sbyte b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Min(this sbyte a, sbyte b, sbyte c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Max(this sbyte a, sbyte b, sbyte c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Min(this sbyte a, sbyte b, sbyte c, sbyte d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Max(this sbyte a, sbyte b, sbyte c, sbyte d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Min(this sbyte x, params sbyte[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Max(this sbyte x, params sbyte[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Min(this short a, short b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Max(this short a, short b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Min(this short a, short b, short c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Max(this short a, short b, short c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Min(this short a, short b, short c, short d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Max(this short a, short b, short c, short d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Min(this short x, params short[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Max(this short x, params short[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Min(this ushort a, ushort b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Max(this ushort a, ushort b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Min(this ushort a, ushort b, ushort c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Max(this ushort a, ushort b, ushort c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Min(this ushort a, ushort b, ushort c, ushort d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Max(this ushort a, ushort b, ushort c, ushort d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Min(this ushort x, params ushort[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Max(this ushort x, params ushort[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Min(this int a, int b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Max(this int a, int b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Min(this int a, int b, int c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Max(this int a, int b, int c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Min(this int a, int b, int c, int d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Max(this int a, int b, int c, int d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Min(this int x, params int[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Max(this int x, params int[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Min(this uint a, uint b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Max(this uint a, uint b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Min(this uint a, uint b, uint c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Max(this uint a, uint b, uint c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Min(this uint a, uint b, uint c, uint d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Max(this uint a, uint b, uint c, uint d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Min(this uint x, params uint[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Max(this uint x, params uint[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Min(this long a, long b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Max(this long a, long b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Min(this long a, long b, long c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Max(this long a, long b, long c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Min(this long a, long b, long c, long d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Max(this long a, long b, long c, long d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Min(this long x, params long[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Max(this long x, params long[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Min(this ulong a, ulong b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Max(this ulong a, ulong b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Min(this ulong a, ulong b, ulong c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Max(this ulong a, ulong b, ulong c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Min(this ulong a, ulong b, ulong c, ulong d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Max(this ulong a, ulong b, ulong c, ulong d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Min(this ulong x, params ulong[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Max(this ulong x, params ulong[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Min(this float a, float b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Max(this float a, float b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Min(this float a, float b, float c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Max(this float a, float b, float c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Min(this float a, float b, float c, float d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Max(this float a, float b, float c, float d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Min(this float x, params float[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Max(this float x, params float[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Min(this double a, double b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Max(this double a, double b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Min(this double a, double b, double c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Max(this double a, double b, double c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Min(this double a, double b, double c, double d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Max(this double a, double b, double c, double d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Min(this double x, params double[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Max(this double x, params double[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Min(this decimal a, decimal b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Max(this decimal a, decimal b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Min(this decimal a, decimal b, decimal c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Max(this decimal a, decimal b, decimal c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Min(this decimal a, decimal b, decimal c, decimal d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Max(this decimal a, decimal b, decimal c, decimal d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Min(this decimal x, params decimal[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Max(this decimal x, params decimal[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction Min(this Fraction a, Fraction b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction Max(this Fraction a, Fraction b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction Min(this Fraction a, Fraction b, Fraction c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction Max(this Fraction a, Fraction b, Fraction c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction Min(this Fraction a, Fraction b, Fraction c, Fraction d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction Max(this Fraction a, Fraction b, Fraction c, Fraction d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction Min(this Fraction x, params Fraction[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Fraction Max(this Fraction x, params Fraction[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DateTime Min(this DateTime a, DateTime b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DateTime Max(this DateTime a, DateTime b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DateTime Min(this DateTime a, DateTime b, DateTime c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DateTime Max(this DateTime a, DateTime b, DateTime c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DateTime Min(this DateTime a, DateTime b, DateTime c, DateTime d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DateTime Max(this DateTime a, DateTime b, DateTime c, DateTime d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DateTime Min(this DateTime x, params DateTime[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DateTime Max(this DateTime x, params DateTime[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static TimeSpan Min(this TimeSpan a, TimeSpan b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static TimeSpan Max(this TimeSpan a, TimeSpan b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static TimeSpan Min(this TimeSpan a, TimeSpan b, TimeSpan c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static TimeSpan Max(this TimeSpan a, TimeSpan b, TimeSpan c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static TimeSpan Min(this TimeSpan a, TimeSpan b, TimeSpan c, TimeSpan d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static TimeSpan Max(this TimeSpan a, TimeSpan b, TimeSpan c, TimeSpan d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static TimeSpan Min(this TimeSpan x, params TimeSpan[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static TimeSpan Max(this TimeSpan x, params TimeSpan[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Returns the absolute value of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Abs(this sbyte x)\n        {\n            return Math.Abs(x);\n        }\n\n        /// <summary>\n        /// Returns the absolute value of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Abs(this short x)\n        {\n            return Math.Abs(x);\n        }\n\n        /// <summary>\n        /// Returns the absolute value of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Abs(this int x)\n        {\n            return Math.Abs(x);\n        }\n\n        /// <summary>\n        /// Returns the absolute value of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Abs(this long x)\n        {\n            return Math.Abs(x);\n        }\n\n        /// <summary>\n        /// Returns the absolute value of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Abs(this float x)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.Abs(x);\n            #else\n                return Math.Abs(x);\n            #endif\n        }\n\n        /// <summary>\n        /// Returns the absolute value of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Abs(this double x)\n        {\n            return Math.Abs(x);\n        }\n\n        /// <summary>\n        /// Returns the absolute value of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Abs(this decimal x)\n        {\n            return Math.Abs(x);\n        }\n\n        #endregion\n\n        #region Angular Distance\n\n        /// <summary>\n        /// Returns the absolute difference between two angles in radians.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleDistance(this float alphaInRadians, float betaInRadians)\n        {\n            var phi = Abs(betaInRadians - alphaInRadians) % ConstantF.PiTimesTwo;\n            return (phi > ConstantF.Pi) ? ConstantF.PiTimesTwo - phi : phi;\n        }\n\n        /// <summary>\n        /// Returns the signed difference between two angles in radians.\n        /// The result is within the range of [-Pi, Pi).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleDifference(this float alphaInRadians, float betaInRadians)\n        {\n            var phi = (betaInRadians - alphaInRadians + ConstantF.Pi) % ConstantF.PiTimesTwo - ConstantF.Pi;\n            return (phi < -ConstantF.Pi) ? phi + ConstantF.PiTimesTwo : phi;\n        }\n\n        /// <summary>\n        /// Returns the absolute difference between two angles in radians.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleDistance(this double alphaInRadians, double betaInRadians)\n        {\n            var phi = Abs(betaInRadians - alphaInRadians) % Constant.PiTimesTwo;\n            return (phi > Constant.Pi) ? Constant.PiTimesTwo - phi : phi;\n        }\n\n        /// <summary>\n        /// Returns the signed difference between two angles in radians.\n        /// The result is within the range of [-Pi, Pi).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleDifference(this double alphaInRadians, double betaInRadians)\n        {\n            var phi = (betaInRadians - alphaInRadians + Constant.Pi) % Constant.PiTimesTwo - Constant.Pi;\n            return (phi < -Constant.Pi) ? phi + Constant.PiTimesTwo : phi;\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this byte x, byte y, byte epsilon)\n        {\n            return (x > y) ? ((x - y) <= epsilon) : ((y - x) <= epsilon);\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this sbyte x, sbyte y, sbyte epsilon)\n        {\n            return Abs(x - y) <= epsilon;\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this short x, short y, short epsilon)\n        {\n            return Abs(x - y) <= epsilon;\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ushort x, ushort y, ushort epsilon)\n        {\n            return (x > y) ? ((x - y) <= epsilon) : ((y - x) <= epsilon);\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this int x, int y, int epsilon)\n        {\n            return Abs(x - y) <= epsilon;\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this uint x, uint y, uint epsilon)\n        {\n            return (x > y) ? ((x - y) <= epsilon) : ((y - x) <= epsilon);\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this long x, long y, long epsilon)\n        {\n            return Abs(x - y) <= epsilon;\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this ulong x, ulong y, ulong epsilon)\n        {\n            return (x > y) ? ((x - y) <= epsilon) : ((y - x) <= epsilon);\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this float x, float y, float epsilon)\n        {\n            return Abs(x - y) <= epsilon;\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this double x, double y, double epsilon)\n        {\n            return Abs(x - y) <= epsilon;\n        }\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than\n        /// Constant{float}.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this float x, float y)\n            => ApproximateEquals(x, y, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than\n        /// Constant{double}.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this double x, double y)\n            => ApproximateEquals(x, y, Constant<double>.PositiveTinyValue);\n\n        #endregion\n\n        #region Floor\n\n        /// <summary>\n        /// Returns the largest integer less than or equal to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Floor(this float x)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.Floor(x);\n            #else\n                return (float) Math.Floor(x);\n            #endif\n        }\n\n        /// <summary>\n        /// Returns the largest integer less than or equal to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Floor(this double x)\n        {\n            return Math.Floor(x);\n        }\n\n        /// <summary>\n        /// Returns the largest integer less than or equal to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Floor(this decimal x)\n        {\n            return Decimal.Floor(x);\n        }\n\n        #endregion\n\n        #region Ceiling\n\n        /// <summary>\n        /// Returns the smallest integer greater than or equal to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Ceiling(this float x)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.Ceiling(x);\n            #else\n                return (float) Math.Ceiling(x);\n            #endif\n        }\n\n        /// <summary>\n        /// Returns the smallest integer greater than or equal to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Ceiling(this double x)\n        {\n            return Math.Ceiling(x);\n        }\n\n        /// <summary>\n        /// Returns the smallest integer greater than or equal to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Ceiling(this decimal x)\n        {\n            return Decimal.Ceiling(x);\n        }\n\n        #endregion\n\n        #region Round\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Round(this float x)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.Round(x);\n            #else\n                return (float) Math.Round(x);\n            #endif\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Round(this float x, MidpointRounding mode)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.Round(x, mode);\n            #else\n                return (float) Math.Round(x, mode);\n            #endif\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Round(this float x, int digits)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.Round(x, digits);\n            #else\n                return (float) Math.Round(x, digits);\n            #endif\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Round(this float x, int digits, MidpointRounding mode)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.Round(x, digits, mode);\n            #else\n                return (float) Math.Round(x, digits, mode);\n            #endif\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Round(this double x)\n        {\n            return Math.Round(x);\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Round(this double x, MidpointRounding mode)\n        {\n            return Math.Round(x, mode);\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Round(this double x, int digits)\n        {\n            return Math.Round(x, digits);\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Round(this double x, int digits, MidpointRounding mode)\n        {\n            return Math.Round(x, digits, mode);\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Round(this decimal x)\n        {\n            return Decimal.Round(x);\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Round(this decimal x, MidpointRounding mode)\n        {\n            return Decimal.Round(x, mode);\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Round(this decimal x, int digits)\n        {\n            return Decimal.Round(x, digits);\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Round(this decimal x, int digits, MidpointRounding mode)\n        {\n            return Decimal.Round(x, digits, mode);\n        }\n\n        #endregion\n\n        #region Truncate\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integar towards zero.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Truncate(this float x)\n        {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.Truncate(x);\n            #else\n                return (float) Math.Truncate(x);\n            #endif\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integar towards zero.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Truncate(this double x)\n        {\n            return Math.Truncate(x);\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integar towards zero.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Truncate(this decimal x)\n        {\n            return Decimal.Truncate(x);\n        }\n\n        #endregion\n\n        #region Frac\n\n        /// <summary>\n        /// Returns the fractional part of t. Calculated as t - floor(t).\n        /// The result is always positive and in [0, 1).\n        /// The fractional part of a negative input will be flipped (e.g. frac(-0.3) -> 0.7).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Frac(this float t)\n        {\n            var res = t - Floor(t);\n            return res == 1 ? 0 : res;\n        }\n\n        /// <summary>\n        /// Returns the fractional part of t. Calculated as t - floor(t).\n        /// The result is always positive and in [0, 1).\n        /// The fractional part of a negative input will be flipped (e.g. frac(-0.3) -> 0.7).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Frac(this double t)\n        {\n            var res = t - Floor(t);\n            return res == 1 ? 0 : res;\n        }\n\n        /// <summary>\n        /// Returns the fractional part of t. Calculated as t - floor(t).\n        /// The result is always positive and in [0, 1).\n        /// The fractional part of a negative input will be flipped (e.g. frac(-0.3) -> 0.7).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Frac(this decimal t)\n        {\n            var res = t - Floor(t);\n            return res == 1 ? 0 : res;\n        }\n\n        #endregion\n\n        #region Clamp\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Clamp(this byte x, byte a, byte b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Clamp(this sbyte x, sbyte a, sbyte b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Clamp(this short x, short a, short b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Clamp(this ushort x, ushort a, ushort b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Clamp(this int x, int a, int b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Clamp(this uint x, uint a, uint b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Clamp(this long x, long a, long b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Clamp(this ulong x, ulong a, ulong b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Clamp(this float x, float a, float b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Clamp(this double x, double a, double b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Clamp(this decimal x, decimal a, decimal b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Clamp(this int x, Range1i range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x > range.Max) return range.Max;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Clamp(this uint x, Range1ui range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x > range.Max) return range.Max;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Clamp(this long x, Range1l range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x > range.Max) return range.Max;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Clamp(this float x, Range1f range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x > range.Max) return range.Max;\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Clamp(this double x, Range1d range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x > range.Max) return range.Max;\n            return x;\n        }\n\n#endregion\n\n        #region ClampExcl\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ClampExcl(this byte x, byte a, byte b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (byte)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte ClampExcl(this sbyte x, sbyte a, sbyte b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (sbyte)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short ClampExcl(this short x, short a, short b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (short)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort ClampExcl(this ushort x, ushort a, ushort b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (ushort)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ClampExcl(this int x, int a, int b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (int)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint ClampExcl(this uint x, uint a, uint b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (uint)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ClampExcl(this long x, long a, long b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (long)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong ClampExcl(this ulong x, ulong a, ulong b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (ulong)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal ClampExcl(this decimal x, decimal a, decimal b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (decimal)(b - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ClampExcl(this int x, Range1i range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x >= range.Max) return (int)(range.Max - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint ClampExcl(this uint x, Range1ui range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x >= range.Max) return (uint)(range.Max - 1);\n            return x;\n        }\n\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ClampExcl(this long x, Range1l range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x >= range.Max) return (long)(range.Max - 1);\n            return x;\n        }\n\n        #endregion\n\n        #region ClampWrap\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ClampWrap(this byte x, byte a, byte b)\n            => (byte)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte ClampWrap(this sbyte x, sbyte a, sbyte b)\n            => (sbyte)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short ClampWrap(this short x, short a, short b)\n            => (short)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort ClampWrap(this ushort x, ushort a, ushort b)\n            => (ushort)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ClampWrap(this int x, int a, int b)\n            => (int)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint ClampWrap(this uint x, uint a, uint b)\n            => (uint)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ClampWrap(this long x, long a, long b)\n            => (long)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ClampWrap(this float x, float a, float b)\n            => (float)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ClampWrap(this double x, double a, double b)\n            => (double)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal ClampWrap(this decimal x, decimal a, decimal b)\n            => (decimal)(ModP(x - a, b - a) + a);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ClampWrap(this int x, Range1i range)\n            => (int)(ModP(x - range.Min, range.Max - range.Min) + range.Min);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint ClampWrap(this uint x, Range1ui range)\n            => (uint)(ModP(x - range.Min, range.Max - range.Min) + range.Min);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ClampWrap(this long x, Range1l range)\n            => (long)(ModP(x - range.Min, range.Max - range.Min) + range.Min);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ClampWrap(this float x, Range1f range)\n            => (float)(ModP(x - range.Min, range.Max - range.Min) + range.Min);\n\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ClampWrap(this double x, Range1d range)\n            => (double)(ModP(x - range.Min, range.Max - range.Min) + range.Min);\n\n        #endregion\n\n        #region WrapToPi\n\n        /// <summary>\n        /// Wraps the given angle to the [-Pi, Pi] range.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float WrapToPi(this float angleInRadians)\n        {\n            var x = angleInRadians % ConstantF.PiTimesTwo;\n            return (x.Abs() > ConstantF.Pi) ? x - ConstantF.PiTimesTwo * x.Signum() : x;\n        }\n\n        /// <summary>\n        /// Wraps the given angle to the [-Pi, Pi] range.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double WrapToPi(this double angleInRadians)\n        {\n            var x = angleInRadians % Constant.PiTimesTwo;\n            return (x.Abs() > Constant.Pi) ? x - Constant.PiTimesTwo * x.Signum() : x;\n        }\n\n        #endregion\n\n        #region Saturate\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Saturate(this byte x)\n            => Clamp(x, (byte)0, (byte)1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Saturate(this sbyte x)\n            => Clamp(x, (sbyte)0, (sbyte)1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Saturate(this short x)\n            => Clamp(x, (short)0, (short)1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Saturate(this ushort x)\n            => Clamp(x, (ushort)0, (ushort)1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Saturate(this int x)\n            => Clamp(x, 0, 1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Saturate(this uint x)\n            => Clamp(x, 0, 1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Saturate(this long x)\n            => Clamp(x, 0, 1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Saturate(this ulong x)\n            => Clamp(x, 0, 1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Saturate(this float x)\n            => Clamp(x, 0, 1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Saturate(this double x)\n            => Clamp(x, 0, 1);\n\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Saturate(this decimal x)\n            => Clamp(x, 0, 1);\n\n        #endregion\n\n        #region MapToUnitInterval\n\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// Values outside [0, tMax] are clamped - if t is greater than tMax\n        /// then 1 is returned, if t is less than 0 then 0 is returned.\n        /// If 'repeat' is true, then every interval [i * tMax, (i+1) * tMax]\n        /// (for i from integers) is mapped to [0, 1].\n        /// If 'mirror' is true, then every second interval is flipped, such\n        /// that [0, tMax) [tMax, 2*tMax) [2*tMax, 3*tMax] ... is mapped to\n        /// [0,1)[1,0)[0,1)...\n        /// </summary>\n        [Pure]\n        public static float MapToUnitInterval(\n            this float t, float tMax,\n            bool repeat, bool mirror\n            )\n        {\n            t = t / tMax;\n            if (!repeat)\n            {\n                if (t >= 1) return 1;\n                if (t <= 0) return 0;\n            }\n            if (mirror)\n            {\n                t = t - Floor(t * 0.5f) * 2;\n                return t < 1 ? t : 2 - t;\n            }\n            else\n            {\n                return t - Floor(t);\n            }\n        }\n\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// If 'repeat' is true, then every interval [i * tMax, (i+1) * tMax]\n        /// (for i from integers) is mapped to [0, 1].\n        /// </summary>\n        [Pure]\n        public static float MapToUnitInterval(this float t, float tMax, bool repeat)\n        {\n            t = t / tMax;\n            if (!repeat)\n            {\n                if (t >= 1) return 1;\n                if (t <= 0) return 0;\n            }\n            return t - Floor(t);\n        }\n\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// </summary>\n        [Pure]\n        public static float MapToUnitInterval(this float t, float tMax)\n        {\n            t = t / tMax;\n            if (t > 1) return 1;\n            if (t < 0) return 0;\n            return t;\n        }\n\n        /// <summary>\n        /// Maps value from interval [tMin, tMax] to interval [0, 1].\n        /// </summary>\n        [Pure]\n        public static float MapToUnitInterval(this float t, float tMin, float tMax)\n        {\n            t = (t - tMin) / (tMax - tMin);\n            if (t > 1) return 1;\n            if (t < 0) return 0;\n            return t;\n        }\n\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// Values outside [0, tMax] are clamped - if t is greater than tMax\n        /// then 1 is returned, if t is less than 0 then 0 is returned.\n        /// If 'repeat' is true, then every interval [i * tMax, (i+1) * tMax]\n        /// (for i from integers) is mapped to [0, 1].\n        /// If 'mirror' is true, then every second interval is flipped, such\n        /// that [0, tMax) [tMax, 2*tMax) [2*tMax, 3*tMax] ... is mapped to\n        /// [0,1)[1,0)[0,1)...\n        /// </summary>\n        [Pure]\n        public static double MapToUnitInterval(\n            this double t, double tMax,\n            bool repeat, bool mirror\n            )\n        {\n            t = t / tMax;\n            if (!repeat)\n            {\n                if (t >= 1) return 1;\n                if (t <= 0) return 0;\n            }\n            if (mirror)\n            {\n                t = t - Floor(t * 0.5) * 2;\n                return t < 1 ? t : 2 - t;\n            }\n            else\n            {\n                return t - Floor(t);\n            }\n        }\n\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// If 'repeat' is true, then every interval [i * tMax, (i+1) * tMax]\n        /// (for i from integers) is mapped to [0, 1].\n        /// </summary>\n        [Pure]\n        public static double MapToUnitInterval(this double t, double tMax, bool repeat)\n        {\n            t = t / tMax;\n            if (!repeat)\n            {\n                if (t >= 1) return 1;\n                if (t <= 0) return 0;\n            }\n            return t - Floor(t);\n        }\n\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// </summary>\n        [Pure]\n        public static double MapToUnitInterval(this double t, double tMax)\n        {\n            t = t / tMax;\n            if (t > 1) return 1;\n            if (t < 0) return 0;\n            return t;\n        }\n\n        /// <summary>\n        /// Maps value from interval [tMin, tMax] to interval [0, 1].\n        /// </summary>\n        [Pure]\n        public static double MapToUnitInterval(this double t, double tMin, double tMax)\n        {\n            t = (t - tMin) / (tMax - tMin);\n            if (t > 1) return 1;\n            if (t < 0) return 0;\n            return t;\n        }\n\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(this sbyte x)\n        {\n            return Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        // Same as Fun.Sign(), we need this for the F# generic math library!\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signumi(this sbyte x)\n            => Sign(x);\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Signum(this sbyte x)\n        {\n            return (sbyte) Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(this short x)\n        {\n            return Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        // Same as Fun.Sign(), we need this for the F# generic math library!\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signumi(this short x)\n            => Sign(x);\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Signum(this short x)\n        {\n            return (short) Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(this int x)\n        {\n            return Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        // Same as Fun.Sign(), we need this for the F# generic math library!\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signumi(this int x)\n            => Sign(x);\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signum(this int x)\n        {\n            return (int) Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(this long x)\n        {\n            return Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        // Same as Fun.Sign(), we need this for the F# generic math library!\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signumi(this long x)\n            => Sign(x);\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Signum(this long x)\n        {\n            return (long) Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Sign(x);\n#else\n                return Math.Sign(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        // Same as Fun.Sign(), we need this for the F# generic math library!\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signumi(this float x)\n            => Sign(x);\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Signum(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Sign(x);\n#else\n                return Math.Sign(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(this double x)\n        {\n            return Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        // Same as Fun.Sign(), we need this for the F# generic math library!\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signumi(this double x)\n            => Sign(x);\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Signum(this double x)\n        {\n            return (double) Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(this decimal x)\n        {\n            return Math.Sign(x);\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        // Same as Fun.Sign(), we need this for the F# generic math library!\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signumi(this decimal x)\n            => Sign(x);\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Signum(this decimal x)\n        {\n            return (decimal) Math.Sign(x);\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte MultiplyAdd(byte x, byte y, byte z)\n            => (byte)((x * y) + z);\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte MultiplyAdd(sbyte x, sbyte y, sbyte z)\n            => (sbyte)((x * y) + z);\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short MultiplyAdd(short x, short y, short z)\n            => (short)((x * y) + z);\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort MultiplyAdd(ushort x, ushort y, ushort z)\n            => (ushort)((x * y) + z);\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MultiplyAdd(int x, int y, int z)\n            => ((x * y) + z);\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint MultiplyAdd(uint x, uint y, uint z)\n            => ((x * y) + z);\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MultiplyAdd(long x, long y, long z)\n            => ((x * y) + z);\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong MultiplyAdd(ulong x, ulong y, ulong z)\n            => ((x * y) + z);\n\n#if NETCOREAPP3_1_OR_GREATER\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// Computes the result rounded as a single ternary operation.\n        /// </summary>\n#else\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n#endif\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MultiplyAdd(float x, float y, float z)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.FusedMultiplyAdd(x, y, z);\n#else\n                return (x * y) + z;\n#endif\n        }\n\n#if NETCOREAPP3_1_OR_GREATER\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// Computes the result rounded as a single ternary operation.\n        /// </summary>\n#else\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n#endif\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MultiplyAdd(double x, double y, double z)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.FusedMultiplyAdd(x, y, z);\n#else\n                return (x * y) + z;\n#endif\n        }\n\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal MultiplyAdd(decimal x, decimal y, decimal z)\n            => ((x * y) + z);\n\n        #endregion\n\n        #region Floating point bits\n\n#if NETSTANDARD2_0\n            /// <summary>\n            /// Returns the bit representation of the given <see cref=\"float\"/> value as a <see cref=\"int\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static unsafe int FloatToBits(this float x)\n                => *((int*)&x);\n\n            /// <summary>\n            /// Returns the <see cref=\"float\"/> value represented by the given <see cref=\"int\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static unsafe float FloatFromBits(this int x)\n                => *((float*)&x);\n#else\n            /// <summary>\n            /// Returns the bit representation of the given <see cref=\"float\"/> value as a <see cref=\"int\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static int FloatToBits(this float x)\n                => BitConverter.SingleToInt32Bits(x);\n\n            /// <summary>\n            /// Returns the <see cref=\"float\"/> value represented by the given <see cref=\"int\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static float FloatFromBits(this int x)\n                => BitConverter.Int32BitsToSingle(x);\n#endif\n\n        /// <summary>\n        /// Returns the bit representation of the given <see cref=\"float\"/> value as a <see cref=\"uint\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static unsafe uint FloatToUnsignedBits(this float x)\n            => *((uint*)&x);\n\n        /// <summary>\n        /// Returns the <see cref=\"float\"/> value represented by the given <see cref=\"uint\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static unsafe float FloatFromUnsignedBits(this uint x)\n            => *((float*)&x);\n\n#if NETSTANDARD2_0\n            /// <summary>\n            /// Returns the bit representation of the given <see cref=\"double\"/> value as a <see cref=\"long\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static unsafe long FloatToBits(this double x)\n                => *((long*)&x);\n\n            /// <summary>\n            /// Returns the <see cref=\"double\"/> value represented by the given <see cref=\"long\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static unsafe double FloatFromBits(this long x)\n                => *((double*)&x);\n#else\n            /// <summary>\n            /// Returns the bit representation of the given <see cref=\"double\"/> value as a <see cref=\"long\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static long FloatToBits(this double x)\n                => BitConverter.DoubleToInt64Bits(x);\n\n            /// <summary>\n            /// Returns the <see cref=\"double\"/> value represented by the given <see cref=\"long\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static double FloatFromBits(this long x)\n                => BitConverter.Int64BitsToDouble(x);\n#endif\n\n        /// <summary>\n        /// Returns the bit representation of the given <see cref=\"double\"/> value as a <see cref=\"ulong\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static unsafe ulong FloatToUnsignedBits(this double x)\n            => *((ulong*)&x);\n\n        /// <summary>\n        /// Returns the <see cref=\"double\"/> value represented by the given <see cref=\"ulong\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static unsafe double FloatFromUnsignedBits(this ulong x)\n            => *((double*)&x);\n\n        #endregion\n\n        #region Copy sign\n\n        /// <summary>\n        /// Returns a value with the maginute of <paramref name=\"value\"/> and the sign of <paramref name=\"sign\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float CopySign(float value, float sign)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.CopySign(value, sign);\n#else\n                var xbits = FloatToBits(value);\n                var ybits = FloatToBits(sign);\n\n                if ((xbits ^ ybits) < 0)\n                {\n                    return FloatFromBits(xbits ^ int.MinValue);\n                }\n\n                return value;\n#endif\n        }\n\n        /// <summary>\n        /// Returns a value with the maginute of <paramref name=\"value\"/> and the sign of <paramref name=\"sign\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double CopySign(double value, double sign)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.CopySign(value, sign);\n#else\n                var xbits = FloatToBits(value);\n                var ybits = FloatToBits(sign);\n\n                if ((xbits ^ ybits) < 0)\n                {\n                    return FloatFromBits(xbits ^ long.MinValue);\n                }\n\n                return value;\n#endif\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this byte x, byte epsilon)\n            => x < epsilon;\n\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this sbyte x, sbyte epsilon)\n            => x.Abs() < epsilon;\n\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this short x, short epsilon)\n            => x.Abs() < epsilon;\n\n        /// <summary>\n        /// Returns whether <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this ushort x, ushort epsilon)\n            => x < epsilon;\n\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this int x, int epsilon)\n            => x.Abs() < epsilon;\n\n        /// <summary>\n        /// Returns whether <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this uint x, uint epsilon)\n            => x < epsilon;\n\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this long x, long epsilon)\n            => x.Abs() < epsilon;\n\n        /// <summary>\n        /// Returns whether <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this ulong x, ulong epsilon)\n            => x < epsilon;\n\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this float x, float epsilon)\n            => x.Abs() < epsilon;\n\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this float x)\n            => x.Abs() < Constant<float>.PositiveTinyValue;\n\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this double x, double epsilon)\n            => x.Abs() < epsilon;\n\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this double x)\n            => x.Abs() < Constant<double>.PositiveTinyValue;\n\n        #endregion\n\n        #region AbsSum\n\n        /// <summary>\n        /// Returns the sum of the absolute values of the given numbers.\n        /// </summary>\n        [Pure]\n        public static int AbsSum(this IEnumerable<sbyte> array)\n        {\n            int sum = 0;\n            foreach (var i in array) sum += i.Abs();\n            return sum;\n        }\n\n        /// <summary>\n        /// Returns the sum of the absolute values of the given numbers.\n        /// </summary>\n        [Pure]\n        public static long AbsSum(this IEnumerable<short> array)\n        {\n            long sum = 0;\n            foreach (var i in array) sum += i.Abs();\n            return sum;\n        }\n\n        /// <summary>\n        /// Returns the sum of the absolute values of the given numbers.\n        /// </summary>\n        [Pure]\n        public static long AbsSum(this IEnumerable<int> array)\n        {\n            long sum = 0;\n            foreach (var i in array) sum += i.Abs();\n            return sum;\n        }\n\n        /// <summary>\n        /// Returns the sum of the absolute values of the given numbers.\n        /// </summary>\n        [Pure]\n        public static long AbsSum(this IEnumerable<long> array)\n        {\n            long sum = 0;\n            foreach (var i in array) sum += i.Abs();\n            return sum;\n        }\n\n        /// <summary>\n        /// Returns the sum of the absolute values of the given numbers.\n        /// </summary>\n        [Pure]\n        public static double AbsSum(this IEnumerable<float> array)\n        {\n            double sum = 0;\n            foreach (var i in array) sum += i.Abs();\n            return sum;\n        }\n\n        /// <summary>\n        /// Returns the sum of the absolute values of the given numbers.\n        /// </summary>\n        [Pure]\n        public static double AbsSum(this IEnumerable<double> array)\n        {\n            double sum = 0;\n            foreach (var i in array) sum += i.Abs();\n            return sum;\n        }\n\n        /// <summary>\n        /// Returns the sum of the absolute values of the given numbers.\n        /// </summary>\n        [Pure]\n        public static decimal AbsSum(this IEnumerable<decimal> array)\n        {\n            decimal sum = 0;\n            foreach (var i in array) sum += i.Abs();\n            return sum;\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this byte x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this sbyte x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this short x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this ushort x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this int x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this uint x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this long x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this ulong x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Root(this float x, int n)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(x, 1.0f / n);\n#else\n                return (float)Math.Pow(x, 1.0 / n);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Root(this double x, int n)\n        {\n            return Math.Pow(x, 1.0 / n);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this byte x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this sbyte x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this short x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this ushort x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this int x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this uint x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this long x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this ulong x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Sqrt(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Sqrt(x);\n#else\n                return (float)Math.Sqrt(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the square root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sqrt(this double x)\n        {\n            return Math.Sqrt(x);\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this byte x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return Math.Pow(x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this sbyte x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return x < 0 ? -Math.Pow(-x, Constant.OneThird)\n                             :  Math.Pow( x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this short x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return x < 0 ? -Math.Pow(-x, Constant.OneThird)\n                             :  Math.Pow( x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this ushort x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return Math.Pow(x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this int x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return x < 0 ? -Math.Pow(-x, Constant.OneThird)\n                             :  Math.Pow( x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this uint x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return Math.Pow(x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this long x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return x < 0 ? -Math.Pow(-x, Constant.OneThird)\n                             :  Math.Pow( x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this ulong x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return Math.Pow(x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Cbrt(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Cbrt(x);\n#else\n                return x < 0 ? (float)-Math.Pow(-x, Constant.OneThird)\n                             :  (float)Math.Pow( x, Constant.OneThird);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cbrt(this double x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Cbrt(x);\n#else\n                return x < 0 ? -Math.Pow(-x, Constant.OneThird)\n                             :  Math.Pow( x, Constant.OneThird);\n#endif\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Square(this byte x)\n            => (byte)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Square(this sbyte x)\n            => (sbyte)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Square(this short x)\n            => (short)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Square(this ushort x)\n            => (ushort)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Square(this int x)\n            => (int)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Square(this uint x)\n            => (uint)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Square(this long x)\n            => (long)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Square(this ulong x)\n            => (ulong)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Square(this float x)\n            => (float)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Square(this double x)\n            => (double)(x * x);\n\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Square(this decimal x)\n            => (decimal)(x * x);\n\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this byte x, float y)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(x, y);\n#else\n                return (float)Math.Pow(x, y);\n#endif\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this byte x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this byte x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this byte x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Pown(this byte x, byte y)\n        {\n            return (byte)Pown((uint)x, y);\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Pown(this byte x, int y)\n        {\n            return (byte)Pown((uint)x, y);\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this sbyte x, float y)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(x, y);\n#else\n                return (float)Math.Pow(x, y);\n#endif\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this sbyte x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this sbyte x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this sbyte x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Pown(this sbyte x, sbyte y)\n        {\n            return (sbyte)Pown((int)x, y);\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Pown(this sbyte x, int y)\n        {\n            return (sbyte)Pown((int)x, y);\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this short x, float y)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(x, y);\n#else\n                return (float)Math.Pow(x, y);\n#endif\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this short x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this short x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this short x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Pown(this short x, short y)\n        {\n            return (short)Pown((int)x, y);\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Pown(this short x, int y)\n        {\n            return (short)Pown((int)x, y);\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this ushort x, float y)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(x, y);\n#else\n                return (float)Math.Pow(x, y);\n#endif\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this ushort x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this ushort x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this ushort x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Pown(this ushort x, ushort y)\n        {\n            return (ushort)Pown((uint)x, y);\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Pown(this ushort x, int y)\n        {\n            return (ushort)Pown((uint)x, y);\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this int x, float y)\n        {\n            return (float)Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this int x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this int x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this int x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Pown(this int x, int y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this uint x, float y)\n        {\n            return (float)Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this uint x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this uint x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this uint x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Pown(this uint x, uint y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Pown(this uint x, int y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this long x, float y)\n        {\n            return (float)Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this long x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this long x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this long x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Pown(this long x, long y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Pown(this long x, int y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this ulong x, float y)\n        {\n            return (float)Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this ulong x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this ulong x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this ulong x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Pown(this ulong x, ulong y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Pown(this ulong x, int y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pow(this float x, float y)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(x, y);\n#else\n                return (float)Math.Pow(x, y);\n#endif\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Power(this float x, float y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Pown(this float x, int y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pow(this double x, double y)\n        {\n            return Math.Pow(x, y);\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Power(this double x, double y)\n            => Pow(x, y);\n\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Pown(this double x, int y)\n        {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n        }\n\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this byte x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this byte x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this byte x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this byte x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this byte x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this sbyte x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this sbyte x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this sbyte x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this sbyte x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this sbyte x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this short x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this short x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this short x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this short x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this short x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this ushort x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this ushort x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this ushort x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this ushort x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this ushort x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this int x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this int x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this int x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this int x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this int x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this uint x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this uint x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this uint x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this uint x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this uint x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this long x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this long x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this long x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this long x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// Note: This function uses a double representation internally, but not all long values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this long x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this ulong x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this ulong x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this ulong x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this ulong x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// Note: This function uses a double representation internally, but not all ulong values can be represented exactly as double.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this ulong x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Exp(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Exp(x);\n#else\n                return (float)Math.Exp(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Log(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Log(x);\n#else\n                return (float)Math.Log(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Log10(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Log10(x);\n#else\n                return (float)Math.Log10(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Log2(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                //return MathF.Log2(x); // MathF.Log2 actually uses a conversion to double internally and has bad perfromance, see Aardvark.Base.Benchmarks/Log2Int.cs\n                return x.Log() * ConstantF.Ln2Inv;\n#else\n                return x.Log() * ConstantF.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Log(this float x, float basis)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Log(x, basis);\n#else\n                return (float)Math.Log(x, basis);\n#endif\n        }\n\n        /// <summary>\n        /// Returns e raised to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Exp(this double x)\n        {\n            return Math.Exp(x);\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this double x)\n        {\n            return Math.Log(x);\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log10(this double x)\n        {\n            return Math.Log10(x);\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log2(this double x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Log2(x);\n#else\n                return x.Log() * Constant.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Log(this double x, double basis)\n        {\n            return Math.Log(x, basis);\n        }\n\n        #endregion\n\n        #region LinCom\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte LinCom(\n                byte p0, byte p1, byte p2, byte p3, ref Tup4<float> w)\n        {\n            return (byte)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (float)byte.MinValue, (float)byte.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                byte p0, byte p1, byte p2, byte p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte LinCom(\n                byte p0, byte p1, byte p2, byte p3, ref Tup4<double> w)\n        {\n            return (byte)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (double)byte.MinValue, (double)byte.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                byte p0, byte p1, byte p2, byte p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte LinCom(\n                byte p0, byte p1, byte p2, byte p3, byte p4, byte p5, ref Tup6<float> w)\n        {\n            return (byte)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (float)byte.MinValue, (float)byte.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                byte p0, byte p1, byte p2, byte p3, byte p4, byte p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte LinCom(\n                byte p0, byte p1, byte p2, byte p3, byte p4, byte p5, ref Tup6<double> w)\n        {\n            return (byte)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (double)byte.MinValue, (double)byte.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                byte p0, byte p1, byte p2, byte p3, byte p4, byte p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte LinCom(\n                sbyte p0, sbyte p1, sbyte p2, sbyte p3, ref Tup4<float> w)\n        {\n            return (sbyte)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (float)sbyte.MinValue, (float)sbyte.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                sbyte p0, sbyte p1, sbyte p2, sbyte p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte LinCom(\n                sbyte p0, sbyte p1, sbyte p2, sbyte p3, ref Tup4<double> w)\n        {\n            return (sbyte)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (double)sbyte.MinValue, (double)sbyte.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                sbyte p0, sbyte p1, sbyte p2, sbyte p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte LinCom(\n                sbyte p0, sbyte p1, sbyte p2, sbyte p3, sbyte p4, sbyte p5, ref Tup6<float> w)\n        {\n            return (sbyte)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (float)sbyte.MinValue, (float)sbyte.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                sbyte p0, sbyte p1, sbyte p2, sbyte p3, sbyte p4, sbyte p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte LinCom(\n                sbyte p0, sbyte p1, sbyte p2, sbyte p3, sbyte p4, sbyte p5, ref Tup6<double> w)\n        {\n            return (sbyte)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (double)sbyte.MinValue, (double)sbyte.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                sbyte p0, sbyte p1, sbyte p2, sbyte p3, sbyte p4, sbyte p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short LinCom(\n                short p0, short p1, short p2, short p3, ref Tup4<float> w)\n        {\n            return (short)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (float)short.MinValue, (float)short.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                short p0, short p1, short p2, short p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short LinCom(\n                short p0, short p1, short p2, short p3, ref Tup4<double> w)\n        {\n            return (short)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (double)short.MinValue, (double)short.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                short p0, short p1, short p2, short p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short LinCom(\n                short p0, short p1, short p2, short p3, short p4, short p5, ref Tup6<float> w)\n        {\n            return (short)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (float)short.MinValue, (float)short.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                short p0, short p1, short p2, short p3, short p4, short p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short LinCom(\n                short p0, short p1, short p2, short p3, short p4, short p5, ref Tup6<double> w)\n        {\n            return (short)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (double)short.MinValue, (double)short.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                short p0, short p1, short p2, short p3, short p4, short p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort LinCom(\n                ushort p0, ushort p1, ushort p2, ushort p3, ref Tup4<float> w)\n        {\n            return (ushort)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (float)ushort.MinValue, (float)ushort.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                ushort p0, ushort p1, ushort p2, ushort p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort LinCom(\n                ushort p0, ushort p1, ushort p2, ushort p3, ref Tup4<double> w)\n        {\n            return (ushort)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (double)ushort.MinValue, (double)ushort.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                ushort p0, ushort p1, ushort p2, ushort p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort LinCom(\n                ushort p0, ushort p1, ushort p2, ushort p3, ushort p4, ushort p5, ref Tup6<float> w)\n        {\n            return (ushort)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (float)ushort.MinValue, (float)ushort.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                ushort p0, ushort p1, ushort p2, ushort p3, ushort p4, ushort p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort LinCom(\n                ushort p0, ushort p1, ushort p2, ushort p3, ushort p4, ushort p5, ref Tup6<double> w)\n        {\n            return (ushort)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (double)ushort.MinValue, (double)ushort.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                ushort p0, ushort p1, ushort p2, ushort p3, ushort p4, ushort p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LinCom(\n                int p0, int p1, int p2, int p3, ref Tup4<float> w)\n        {\n            return (int)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (float)int.MinValue, (float)int.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                int p0, int p1, int p2, int p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LinCom(\n                int p0, int p1, int p2, int p3, ref Tup4<double> w)\n        {\n            return (int)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (double)int.MinValue, (double)int.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                int p0, int p1, int p2, int p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LinCom(\n                int p0, int p1, int p2, int p3, int p4, int p5, ref Tup6<float> w)\n        {\n            return (int)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (float)int.MinValue, (float)int.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                int p0, int p1, int p2, int p3, int p4, int p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LinCom(\n                int p0, int p1, int p2, int p3, int p4, int p5, ref Tup6<double> w)\n        {\n            return (int)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (double)int.MinValue, (double)int.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                int p0, int p1, int p2, int p3, int p4, int p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint LinCom(\n                uint p0, uint p1, uint p2, uint p3, ref Tup4<float> w)\n        {\n            return (uint)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (float)uint.MinValue, (float)uint.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                uint p0, uint p1, uint p2, uint p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint LinCom(\n                uint p0, uint p1, uint p2, uint p3, ref Tup4<double> w)\n        {\n            return (uint)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (double)uint.MinValue, (double)uint.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                uint p0, uint p1, uint p2, uint p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint LinCom(\n                uint p0, uint p1, uint p2, uint p3, uint p4, uint p5, ref Tup6<float> w)\n        {\n            return (uint)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (float)uint.MinValue, (float)uint.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                uint p0, uint p1, uint p2, uint p3, uint p4, uint p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint LinCom(\n                uint p0, uint p1, uint p2, uint p3, uint p4, uint p5, ref Tup6<double> w)\n        {\n            return (uint)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (double)uint.MinValue, (double)uint.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                uint p0, uint p1, uint p2, uint p3, uint p4, uint p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long LinCom(\n                long p0, long p1, long p2, long p3, ref Tup4<float> w)\n        {\n            return (long)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (float)long.MinValue, (float)long.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                long p0, long p1, long p2, long p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long LinCom(\n                long p0, long p1, long p2, long p3, ref Tup4<double> w)\n        {\n            return (long)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (double)long.MinValue, (double)long.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                long p0, long p1, long p2, long p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long LinCom(\n                long p0, long p1, long p2, long p3, long p4, long p5, ref Tup6<float> w)\n        {\n            return (long)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (float)long.MinValue, (float)long.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                long p0, long p1, long p2, long p3, long p4, long p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long LinCom(\n                long p0, long p1, long p2, long p3, long p4, long p5, ref Tup6<double> w)\n        {\n            return (long)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (double)long.MinValue, (double)long.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                long p0, long p1, long p2, long p3, long p4, long p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong LinCom(\n                ulong p0, ulong p1, ulong p2, ulong p3, ref Tup4<float> w)\n        {\n            return (ulong)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (float)ulong.MinValue, (float)ulong.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                ulong p0, ulong p1, ulong p2, ulong p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong LinCom(\n                ulong p0, ulong p1, ulong p2, ulong p3, ref Tup4<double> w)\n        {\n            return (ulong)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3, (double)ulong.MinValue, (double)ulong.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                ulong p0, ulong p1, ulong p2, ulong p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong LinCom(\n                ulong p0, ulong p1, ulong p2, ulong p3, ulong p4, ulong p5, ref Tup6<float> w)\n        {\n            return (ulong)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (float)ulong.MinValue, (float)ulong.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinComRawF(\n                ulong p0, ulong p1, ulong p2, ulong p3, ulong p4, ulong p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong LinCom(\n                ulong p0, ulong p1, ulong p2, ulong p3, ulong p4, ulong p5, ref Tup6<double> w)\n        {\n            return (ulong)Fun.Clamp(p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5, (double)ulong.MinValue, (double)ulong.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinComRawD(\n                ulong p0, ulong p1, ulong p2, ulong p3, ulong p4, ulong p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half LinCom(Half p0, Half p1, ref Tup2<Half> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinCom(float p0, float p1, ref Tup2<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinCom(double p0, double p1, ref Tup2<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half LinCom(Half p0, Half p1, Half p2, ref Tup3<Half> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinCom(float p0, float p1, float p2, ref Tup3<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinCom(double p0, double p1, double p2, ref Tup3<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half LinCom(Half p0, Half p1, Half p2, Half p3, ref Tup4<Half> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinCom(float p0, float p1, float p2, float p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinCom(double p0, double p1, double p2, double p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half LinCom(Half p0, Half p1, Half p2, Half p3, Half p4, ref Tup5<Half> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinCom(float p0, float p1, float p2, float p3, float p4, ref Tup5<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinCom(double p0, double p1, double p2, double p3, double p4, ref Tup5<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half LinCom(Half p0, Half p1, Half p2, Half p3, Half p4, Half p5, ref Tup6<Half> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinCom(float p0, float p1, float p2, float p3, float p4, float p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinCom(double p0, double p1, double p2, double p3, double p4, double p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half LinCom(Half p0, Half p1, Half p2, Half p3, Half p4, Half p5, Half p6, ref Tup7<Half> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinCom(float p0, float p1, float p2, float p3, float p4, float p5, float p6, ref Tup7<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LinCom(double p0, double p1, double p2, double p3, double p4, double p5, double p6, ref Tup7<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Returns the positive modulo operation a mod b giving values between [0,b[\n        /// instead of a % b giving values between ]-b,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte ModP(this sbyte a, sbyte b)\n        {\n            var m = a % b;\n            if (m < 0)\n                m += b;\n            return (sbyte)m;\n        }\n\n        /// <summary>\n        /// Returns the positive modulo operation a mod b giving values between [0,b[\n        /// instead of a % b giving values between ]-b,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short ModP(this short a, short b)\n        {\n            var m = a % b;\n            if (m < 0)\n                m += b;\n            return (short)m;\n        }\n\n        /// <summary>\n        /// Returns the positive modulo operation a mod b giving values between [0,b[\n        /// instead of a % b giving values between ]-b,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ModP(this int a, int b)\n        {\n            var m = a % b;\n            if (m < 0)\n                m += b;\n            return (int)m;\n        }\n\n        /// <summary>\n        /// Returns the positive modulo operation a mod b giving values between [0,b[\n        /// instead of a % b giving values between ]-b,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ModP(this long a, long b)\n        {\n            var m = a % b;\n            if (m < 0)\n                m += b;\n            return (long)m;\n        }\n\n        /// <summary>\n        /// Returns the positive modulo operation a mod b giving values between [0,b[\n        /// instead of a % b giving values between ]-b,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ModP(this float a, float b)\n        {\n            var m = a % b;\n            if (m < 0)\n                m += b;\n            return (float)m;\n        }\n\n        /// <summary>\n        /// Returns the positive modulo operation a mod b giving values between [0,b[\n        /// instead of a % b giving values between ]-b,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ModP(this double a, double b)\n        {\n            var m = a % b;\n            if (m < 0)\n                m += b;\n            return (double)m;\n        }\n\n        /// <summary>\n        /// Returns the positive modulo operation a mod b giving values between [0,b[\n        /// instead of a % b giving values between ]-b,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal ModP(this decimal a, decimal b)\n        {\n            var m = a % b;\n            if (m < 0)\n                m += b;\n            return (decimal)m;\n        }\n\n        #endregion\n\n        #region PowerOfTwo\n\n        /// <summary>\n        /// Returns true if the supplied number is 0 or a power of two.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPowerOfTwo(this int x) => (x & (x - 1)) == 0;\n\n        /// <summary>\n        /// Returns true if the supplied number is 0 or a power of two.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPowerOfTwo(this long x) => (x & (x - 1)) == 0;\n\n        /// <summary>\n        /// Returns true if the supplied number is 0 or a power of two.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPowerOfTwo(this uint x) => (x & (x - 1)) == 0;\n\n        /// <summary>\n        /// Returns true if the supplied number is 0 or a power of two.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPowerOfTwo(this ulong x) => (x & (x - 1)) == 0;\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// The exponent <paramref name=\"x\"/> must be less than 64.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this byte x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// The exponent <paramref name=\"x\"/> must be within [0, 64).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this sbyte x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// The exponent <paramref name=\"x\"/> must be within [0, 64).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this short x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// The exponent <paramref name=\"x\"/> must be less than 64.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this ushort x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// The exponent <paramref name=\"x\"/> must be within [0, 64).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this int x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// The exponent <paramref name=\"x\"/> must be less than 64.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this uint x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// The exponent <paramref name=\"x\"/> must be within [0, 64).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this long x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// The exponent <paramref name=\"x\"/> must be less than 64.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this ulong x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float PowerOfTwo(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(2, x);\n#else\n                return (float)Math.Pow(2, x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double PowerOfTwo(this double x)\n        {\n            return Math.Pow(2, x);\n        }\n\n        /// <summary>\n        /// Returns the nearest superior power of two of the value.\n        /// For x &lt;= 0, returns 0.\n        /// For x &gt; 2^30, returns int.MinValue.\n        /// E.g. x = 401 -> 512.\n        /// E.g. x = 256 -> 256.\n        /// </summary>\n        [Pure]\n        public static int NextPowerOfTwo(this int x)\n        {\n            --x;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            return ++x;\n        }\n\n        /// <summary>\n        /// Returns the nearest inferior power of two of the value.\n        /// For x &lt;= 0, returns 0.\n        /// E.g. x = 401 -> 256.\n        /// E.g. x = 512 -> 512.\n        /// </summary>\n        [Pure]\n        public static int PrevPowerOfTwo(this int x)\n        {\n            if (x <= 0) return 0;\n            x >>= 1;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            return ++x;\n        }\n\n        /// <summary>\n        /// Returns the nearest superior power of two of the value.\n        /// For x &lt;= 0, returns 0.\n        /// For x &gt; 2^62, returns long.MinValue.\n        /// E.g. x = 401 -> 512.\n        /// E.g. x = 256 -> 256.\n        /// </summary>\n        [Pure]\n        public static long NextPowerOfTwo(this long x)\n        {\n            --x;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            x |= x >> 32;\n            return ++x;\n        }\n\n        /// <summary>\n        /// Returns the nearest inferior power of two of the value.\n        /// For x &lt;= 0, returns 0.\n        /// E.g. x = 401 -> 256.\n        /// E.g. x = 512 -> 512.\n        /// </summary>\n        [Pure]\n        public static long PrevPowerOfTwo(this long x)\n        {\n            if (x <= 0) return 0;\n            x >>= 1;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            x |= x >> 32;\n            return ++x;\n        }\n\n        /// <summary>\n        /// Returns the nearest superior power of two of the value.\n        /// For x = 0 and x &gt; 2^31, returns 0.\n        /// E.g. x = 401 -> 512.\n        /// E.g. x = 256 -> 256.\n        /// </summary>\n        [Pure]\n        public static uint NextPowerOfTwo(this uint x)\n        {\n            --x;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            return ++x;\n        }\n\n        /// <summary>\n        /// Returns the nearest inferior power of two of the value.\n        /// For x &lt;= 0, returns 0.\n        /// E.g. x = 401 -> 256.\n        /// E.g. x = 512 -> 512.\n        /// </summary>\n        [Pure]\n        public static uint PrevPowerOfTwo(this uint x)\n        {\n            if (x == 0) return 0;\n            x >>= 1;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            return ++x;\n        }\n\n        /// <summary>\n        /// Returns the nearest superior power of two of the value.\n        /// For x = 0 and x &gt; 2^63, returns 0.\n        /// E.g. x = 401 -> 512.\n        /// E.g. x = 256 -> 256.\n        /// </summary>\n        [Pure]\n        public static ulong NextPowerOfTwo(this ulong x)\n        {\n            --x;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            x |= x >> 32;\n            return ++x;\n        }\n\n        /// <summary>\n        /// Returns the nearest inferior power of two of the value.\n        /// For x &lt;= 0, returns 0.\n        /// E.g. x = 401 -> 256.\n        /// E.g. x = 512 -> 512.\n        /// </summary>\n        [Pure]\n        public static ulong PrevPowerOfTwo(this ulong x)\n        {\n            if (x == 0) return 0;\n            x >>= 1;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            x |= x >> 32;\n            return ++x;\n        }\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Normalized sinc function.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Sinc(this float x)\n        {\n            // See unit test for determining eps\n            if (Abs(x) < 0.00017791694f)\n            {\n                return 1;\n            }\n            else\n            {\n#if NETCOREAPP3_1_OR_GREATER\n                    return MathF.Sin(ConstantF.Pi * x) / (ConstantF.Pi * x);\n#else\n                    return (float)Math.Sin(ConstantF.Pi * x) / (ConstantF.Pi * x);\n#endif\n            }\n        }\n\n        /// <summary>\n        /// Returns the sine of the specified angle in radians.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Sin(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Sin(x);\n#else\n                return (float)Math.Sin(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the cosine of the specified angle in radians.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Cos(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Cos(x);\n#else\n                return (float)Math.Cos(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the tangent of the specified angle in radians.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Tan(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Tan(x);\n#else\n                return (float)Math.Tan(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose sine is the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Asin(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Asin(x);\n#else\n                return (float)Math.Asin(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose sine is the specified number while clamping the input to [-1, 1] in order to avoid numerical problems.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AsinClamped(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Asin(Clamp(x, -1, 1));\n#else\n                return (float)Math.Asin(Clamp(x, -1, 1));\n#endif\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose cosine is the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Acos(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Acos(x);\n#else\n                return (float)Math.Acos(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose cosine is the specified number while clamping the input to [-1, 1] in order to avoid numerical problems.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AcosClamped(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Acos(Clamp(x, -1, 1));\n#else\n                return (float)Math.Acos(Clamp(x, -1, 1));\n#endif\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Atan(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Atan(x);\n#else\n                return (float)Math.Atan(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is\n        /// the quotient of the two specified numbers.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Atan2(float y, float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Atan2(y, x);\n#else\n                return (float)Math.Atan2(y, x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is\n        /// the quotient of the two specified numbers using\n        /// a faster algorithm than Math.Atan2.\n        /// NOTE: Accuracy untested\n        /// </summary>\n        [Pure]\n        public static float FastAtan2(float y, float x)\n        {\n            float angle;\n            double piThreeFourths = Constant.Pi * 3 / 4;\n            double yAbs = y.Abs() + Constant<double>.PositiveTinyValue; // prevent 0/0 condition\n            if (x >= 0)\n            {\n                double r = (x - yAbs) / (x + yAbs);\n                angle = (float)(Constant.PiQuarter * (1 - r));\n            }\n            else\n            {\n                double r = (x + yAbs) / (yAbs - x);\n                angle = (float)(piThreeFourths - Constant.PiQuarter * r);\n            }\n\n            return y < 0 ? -angle : angle; // negate if in quad III or IV\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic sine of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Sinh(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Sinh(x);\n#else\n                return (float)Math.Sinh(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic cosine of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Cosh(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Cosh(x);\n#else\n                return (float)Math.Cosh(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic tangent of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Tanh(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Tanh(x);\n#else\n                return (float)Math.Tanh(x);\n#endif\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic sine of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Asinh(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Asinh(x);\n#else\n                return Log(x + Sqrt(x * x + 1));\n#endif\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic cosine of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Acosh(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Acosh(x);\n#else\n                return Log(x + Sqrt(x * x - 1));\n#endif\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic tangent of the specified number.\n        /// Note that the absolute value of the argument must be smaller than 1.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Atanh(this float x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Atanh(x);\n#else\n                return 0.5f * Log((1 + x) / (1 - x));\n#endif\n        }\n\n        /// <summary>\n        /// Normalized sinc function.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sinc(this double x)\n        {\n            // See unit test for determining eps\n            if (Abs(x) < 6.840859302478615E-09)\n            {\n                return 1;\n            }\n            else\n            {\n                return Math.Sin(Constant.Pi * x) / (Constant.Pi * x);\n            }\n        }\n\n        /// <summary>\n        /// Returns the sine of the specified angle in radians.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sin(this double x)\n        {\n            return Math.Sin(x);\n        }\n\n        /// <summary>\n        /// Returns the cosine of the specified angle in radians.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cos(this double x)\n        {\n            return Math.Cos(x);\n        }\n\n        /// <summary>\n        /// Returns the tangent of the specified angle in radians.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Tan(this double x)\n        {\n            return Math.Tan(x);\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose sine is the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Asin(this double x)\n        {\n            return Math.Asin(x);\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose sine is the specified number while clamping the input to [-1, 1] in order to avoid numerical problems.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AsinClamped(this double x)\n        {\n            return Math.Asin(Clamp(x, -1, 1));\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose cosine is the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Acos(this double x)\n        {\n            return Math.Acos(x);\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose cosine is the specified number while clamping the input to [-1, 1] in order to avoid numerical problems.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AcosClamped(this double x)\n        {\n            return Math.Acos(Clamp(x, -1, 1));\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Atan(this double x)\n        {\n            return Math.Atan(x);\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is\n        /// the quotient of the two specified numbers.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Atan2(double y, double x)\n        {\n            return Math.Atan2(y, x);\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is\n        /// the quotient of the two specified numbers using\n        /// a faster algorithm than Math.Atan2.\n        /// NOTE: Accuracy untested\n        /// </summary>\n        [Pure]\n        public static double FastAtan2(double y, double x)\n        {\n            double angle;\n            double piThreeFourths = Constant.Pi * 3 / 4;\n            double yAbs = y.Abs() + Constant<double>.PositiveTinyValue; // prevent 0/0 condition\n            if (x >= 0)\n            {\n                double r = (x - yAbs) / (x + yAbs);\n                angle = (Constant.PiQuarter * (1 - r));\n            }\n            else\n            {\n                double r = (x + yAbs) / (yAbs - x);\n                angle = (piThreeFourths - Constant.PiQuarter * r);\n            }\n\n            return y < 0 ? -angle : angle; // negate if in quad III or IV\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic sine of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Sinh(this double x)\n        {\n            return Math.Sinh(x);\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic cosine of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Cosh(this double x)\n        {\n            return Math.Cosh(x);\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic tangent of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Tanh(this double x)\n        {\n            return Math.Tanh(x);\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic sine of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Asinh(this double x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Asinh(x);\n#else\n                return Log(x + Sqrt(x * x + 1));\n#endif\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic cosine of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Acosh(this double x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Acosh(x);\n#else\n                return Log(x + Sqrt(x * x - 1));\n#endif\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic tangent of the specified number.\n        /// Note that the absolute value of the argument must be smaller than 1.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Atanh(this double x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Math.Atanh(x);\n#else\n                return 0.5 * Log((1 + x) / (1 - x));\n#endif\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Step(this byte x, byte edge)\n            => x < edge ? (byte)0 : (byte)1;\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Step(this sbyte x, sbyte edge)\n            => x < edge ? (sbyte)0 : (sbyte)1;\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Step(this short x, short edge)\n            => x < edge ? (short)0 : (short)1;\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Step(this ushort x, ushort edge)\n            => x < edge ? (ushort)0 : (ushort)1;\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Step(this int x, int edge)\n            => x < edge ? 0 : 1;\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Step(this uint x, uint edge)\n            => x < edge ? (uint)0 : (uint)1;\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Step(this long x, long edge)\n            => x < edge ? 0 : 1;\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Step(this ulong x, ulong edge)\n            => x < edge ? (ulong)0 : (ulong)1;\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Step(this float x, float edge)\n            => x < edge ? 0 : 1;\n\n        /// <summary>\n        /// Inverse linear interpolation, clamped to [0, 1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Linearstep(this float x, float edge0, float edge1)\n            => Saturate(InvLerp(x, edge0, edge1));\n\n        /// <summary>\n        /// Performs smooth Hermite interpolation between 0 and 1 when edge0 &lt; x &lt; edge1.\n        /// </summary>\n        [Pure]\n        public static float Smoothstep(this float x, float edge0, float edge1)\n        {\n            var t = Linearstep(x, edge0, edge1);\n            return t * t * (3 - 2 * t);\n        }\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Step(this double x, double edge)\n            => x < edge ? 0 : 1;\n\n        /// <summary>\n        /// Inverse linear interpolation, clamped to [0, 1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Linearstep(this double x, double edge0, double edge1)\n            => Saturate(InvLerp(x, edge0, edge1));\n\n        /// <summary>\n        /// Performs smooth Hermite interpolation between 0 and 1 when edge0 &lt; x &lt; edge1.\n        /// </summary>\n        [Pure]\n        public static double Smoothstep(this double x, double edge0, double edge1)\n        {\n            var t = Linearstep(x, edge0, edge1);\n            return t * t * (3 - 2 * t);\n        }\n\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Step(this decimal x, decimal edge)\n            => x < edge ? 0 : 1;\n\n        /// <summary>\n        /// Inverse linear interpolation, clamped to [0, 1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Linearstep(this decimal x, decimal edge0, decimal edge1)\n            => Saturate(InvLerp(x, edge0, edge1));\n\n        /// <summary>\n        /// Performs smooth Hermite interpolation between 0 and 1 when edge0 &lt; x &lt; edge1.\n        /// </summary>\n        [Pure]\n        public static decimal Smoothstep(this decimal x, decimal edge0, decimal edge1)\n        {\n            var t = Linearstep(x, edge0, edge1);\n            return t * t * (3 - 2 * t);\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Lerp(this float t, byte a, byte b)\n            => (byte)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte Lerp(this double t, byte a, byte b)\n            => (byte)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this byte y, byte a, byte b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Lerp(this float t, sbyte a, sbyte b)\n            => (sbyte)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static sbyte Lerp(this double t, sbyte a, sbyte b)\n            => (sbyte)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this sbyte y, sbyte a, sbyte b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Lerp(this float t, short a, short b)\n            => (short)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static short Lerp(this double t, short a, short b)\n            => (short)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this short y, short a, short b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Lerp(this float t, ushort a, ushort b)\n            => (ushort)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort Lerp(this double t, ushort a, ushort b)\n            => (ushort)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this ushort y, ushort a, ushort b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Lerp(this float t, int a, int b)\n            => (int)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Lerp(this double t, int a, int b)\n            => (int)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this int y, int a, int b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Lerp(this float t, uint a, uint b)\n            => (uint)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Lerp(this double t, uint a, uint b)\n            => (uint)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this uint y, uint a, uint b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Lerp(this float t, long a, long b)\n            => (long)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Lerp(this double t, long a, long b)\n            => (long)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this long y, long a, long b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Lerp(this float t, ulong a, ulong b)\n            => (ulong)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong Lerp(this double t, ulong a, ulong b)\n            => (ulong)Round(a * (1 - t) + b * t);\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this ulong y, ulong a, ulong b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Lerp(this float t, float a, float b)\n            => a * (1 - t) + b * t;\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float InvLerp(this float y, float a, float b)\n            => (a - y) / (a - b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Lerp(this double t, double a, double b)\n            => a * (1 - t) + b * t;\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this double y, double a, double b)\n            => (a - y) / (a - b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal Lerp(this decimal t, decimal a, decimal b)\n            => a * (1 - t) + b * t;\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static decimal InvLerp(this decimal y, decimal a, decimal b)\n            => (a - y) / (a - b);\n\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Lerp(this Half t, Half a, Half b)\n            => a * (1 - t) + b * t;\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half InvLerp(this Half y, Half a, Half b)\n            => (a - y) / (a - b);\n\n\n        #endregion\n\n        #region Mean\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<byte> array)\n        {\n            int count = 0;\n            int sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<sbyte> array)\n        {\n            int count = 0;\n            int sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<short> array)\n        {\n            int count = 0;\n            long sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<ushort> array)\n        {\n            int count = 0;\n            long sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<int> array)\n        {\n            int count = 0;\n            long sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<uint> array)\n        {\n            int count = 0;\n            long sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<long> array)\n        {\n            int count = 0;\n            long sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<ulong> array)\n        {\n            int count = 0;\n            ulong sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<float> array)\n        {\n            int count = 0;\n            double sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<double> array)\n        {\n            int count = 0;\n            double sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        [Pure]\n        public static decimal Mean(this IEnumerable<decimal> array)\n        {\n            int count = 0; decimal sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (decimal)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean<T>(\n            this IEnumerable<T> array,\n            Func<T, double> selector\n            )\n        {\n            int count = 0; double sum = 0;\n            foreach (var x in array) { sum += selector(x); ++count; }\n            return sum / count;\n        }\n\n        #endregion\n\n        #region Variance & Standard Deviation\n\n        /// <summary>\n        /// Calculates the variance of given elements.\n        /// </summary>\n        [Pure]\n        public static double Variance(this IEnumerable<int> data)\n        {\n            int count = 0;\n            double sum = 0, mean = data.Mean();\n\n            foreach (var x in data)\n            {\n                sum += (x - mean).Square();\n                count++;\n            }\n\n            return sum / count;\n        }\n\n        /// <summary>\n        /// Calculates the standard deviation of given elements.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double StandardDeviation(this IEnumerable<int> data) => data.Variance().Sqrt();\n\n        /// <summary>\n        /// Calculates the variance of given elements.\n        /// </summary>\n        [Pure]\n        public static double Variance(this IEnumerable<long> data)\n        {\n            int count = 0;\n            double sum = 0, mean = data.Mean();\n\n            foreach (var x in data)\n            {\n                sum += (x - mean).Square();\n                count++;\n            }\n\n            return sum / count;\n        }\n\n        /// <summary>\n        /// Calculates the standard deviation of given elements.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double StandardDeviation(this IEnumerable<long> data) => data.Variance().Sqrt();\n\n        /// <summary>\n        /// Calculates the variance of given elements.\n        /// </summary>\n        [Pure]\n        public static double Variance(this IEnumerable<float> data)\n        {\n            int count = 0;\n            double sum = 0, mean = data.Mean();\n\n            foreach (var x in data)\n            {\n                sum += (x - mean).Square();\n                count++;\n            }\n\n            return sum / count;\n        }\n\n        /// <summary>\n        /// Calculates the standard deviation of given elements.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double StandardDeviation(this IEnumerable<float> data) => data.Variance().Sqrt();\n\n        /// <summary>\n        /// Calculates the variance of given elements.\n        /// </summary>\n        [Pure]\n        public static double Variance(this IEnumerable<double> data)\n        {\n            int count = 0;\n            double sum = 0, mean = data.Mean();\n\n            foreach (var x in data)\n            {\n                sum += (x - mean).Square();\n                count++;\n            }\n\n            return sum / count;\n        }\n\n        /// <summary>\n        /// Calculates the standard deviation of given elements.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double StandardDeviation(this IEnumerable<double> data) => data.Variance().Sqrt();\n\n        /// <summary>\n        /// Calculates the variance of given elements.\n        /// </summary>\n        [Pure]\n        public static double Variance<T>(\n            this IEnumerable<T> data,\n            Func<T, double> selector\n            )\n        {\n            int count = 0;\n            double sum = 0, mean = data.Mean(selector);\n\n            foreach (var x in data)\n            {\n                sum += (selector(x) - mean).Square();\n                count++;\n            }\n\n            return sum / count;\n        }\n\n        /// <summary>\n        /// Calculates the standard deviation of given elements.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double StandardDeviation<T>(this IEnumerable<T> data, Func<T, double> selector)\n            => data.Variance(selector).Sqrt();\n\n        #endregion\n\n        #region CountPositives\n\n        /// <summary>\n        /// Return the number of values greater than 0.\n        /// </summary>\n        [Pure]\n        public static int CountPositives(this IEnumerable<sbyte> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x > 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values greater than 0.\n        /// </summary>\n        [Pure]\n        public static int CountPositives(this IEnumerable<short> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x > 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values greater than 0.\n        /// </summary>\n        [Pure]\n        public static int CountPositives(this IEnumerable<int> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x > 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values greater than 0.\n        /// </summary>\n        [Pure]\n        public static int CountPositives(this IEnumerable<long> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x > 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values greater than 0.\n        /// </summary>\n        [Pure]\n        public static int CountPositives(this IEnumerable<float> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x > 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values greater than 0.\n        /// </summary>\n        [Pure]\n        public static int CountPositives(this IEnumerable<double> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x > 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values greater than 0.\n        /// </summary>\n        [Pure]\n        public static int CountPositives(this IEnumerable<decimal> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x > 0) ++count;\n            return count;\n        }\n\n\n        #endregion\n\n        #region CountNegatives\n\n        /// <summary>\n        /// Return the number of values less than 0.\n        /// </summary>\n        [Pure]\n        public static int CountNegatives(this IEnumerable<sbyte> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x < 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values less than 0.\n        /// </summary>\n        [Pure]\n        public static int CountNegatives(this IEnumerable<short> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x < 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values less than 0.\n        /// </summary>\n        [Pure]\n        public static int CountNegatives(this IEnumerable<int> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x < 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values less than 0.\n        /// </summary>\n        [Pure]\n        public static int CountNegatives(this IEnumerable<long> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x < 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values less than 0.\n        /// </summary>\n        [Pure]\n        public static int CountNegatives(this IEnumerable<float> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x < 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values less than 0.\n        /// </summary>\n        [Pure]\n        public static int CountNegatives(this IEnumerable<double> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x < 0) ++count;\n            return count;\n        }\n\n        /// <summary>\n        /// Return the number of values less than 0.\n        /// </summary>\n        [Pure]\n        public static int CountNegatives(this IEnumerable<decimal> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x < 0) ++count;\n            return count;\n        }\n\n        #endregion\n\n        #region Primes\n\n        /// <summary>\n        /// Checks if the given value is a prime number.\n        /// </summary>\n        /// <param name=\"value\">The number to check.</param>\n        /// <returns><c>True</c> if the number is a prime; otherwise, <c>False</c>.</returns>\n        [Pure]\n        public static bool IsPrime(this int value)\n        {\n            int imax = (int)Sqrt(value);\n\n            for (int i = 2; i <= imax; i++)\n                if (value % i == 0) return false;\n\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the given value is a prime number.\n        /// </summary>\n        /// <param name=\"value\">The number to check.</param>\n        /// <returns><c>True</c> if the number is a prime; otherwise, <c>False</c>.</returns>\n        [Pure]\n        public static bool IsPrime(this long value)\n        {\n            long imax = (long)Sqrt(value);\n\n            for (long i = 2; i <= imax; i++)\n                if (value % i == 0) return false;\n\n            return true;\n        }\n\n\n        #endregion\n\n        #region Swap\n\n        /// <summary>\n        /// Swaps <paramref name=\"a\"/> and <paramref name=\"b\"/>,\n        /// so that afterwards a=b and b=a.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Swap<T>(ref T a, ref T b)\n        {\n            T t = a; a = b; b = t;\n        }\n\n        /// <summary>\n        /// Rotates left <paramref name=\"a\"/>, <paramref name=\"b\"/>, and <paramref name=\"c\"/>,\n        /// so that afterwards a=b, b=c and c=a.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Rotate<T>(ref T a, ref T b, ref T c)\n        {\n            T t = a; a = b; b = c; c = t;\n        }\n\n        /// <summary>\n        /// Rotates left <paramref name=\"a\"/>, <paramref name=\"b\"/>, <paramref name=\"c\"/>, and <paramref name=\"d\"/>,\n        /// so that afterwards a=b, b=c, c=b and d=a.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Rotate<T>(ref T a, ref T b, ref T c, ref T d)\n        {\n            T t = a; a = b; b = c; c = d; d = t;\n        }\n\n        /// <summary>\n        /// Rotates left <paramref name=\"a\"/>, <paramref name=\"b\"/>, <paramref name=\"c\"/>, <paramref name=\"d\"/>, and <paramref name=\"e\"/>,\n        /// so that afterwards a=b, b=c, c=b and d=c and e=a.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Rotate<T>(ref T a, ref T b, ref T c, ref T d, ref T e)\n        {\n            T t = a; a = b; b = c; c = d; d = e; e = t;\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int GreatestCommonDivisor(this int a, int b)\n            => b == 0 ? a : GreatestCommonDivisor(b, a % b);\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LeastCommonMultiple(this int a, int b)\n            => a * b / GreatestCommonDivisor(a, b);\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long GreatestCommonDivisor(this long a, long b)\n            => b == 0 ? a : GreatestCommonDivisor(b, a % b);\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long LeastCommonMultiple(this long a, long b)\n            => a * b / GreatestCommonDivisor(a, b);\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint GreatestCommonDivisor(this uint a, uint b)\n            => b == 0 ? a : GreatestCommonDivisor(b, a % b);\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint LeastCommonMultiple(this uint a, uint b)\n            => a * b / GreatestCommonDivisor(a, b);\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong GreatestCommonDivisor(this ulong a, ulong b)\n            => b == 0 ? a : GreatestCommonDivisor(b, a % b);\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong LeastCommonMultiple(this ulong a, ulong b)\n            => a * b / GreatestCommonDivisor(a, b);\n\n        #endregion\n\n        #region Conversion\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ToInt(this float x) => (int)x;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ToLong(this float x) => (long)x;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ToInt(this double x) => (int)x;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ToLong(this double x) => (long)x;\n\n        #endregion\n\n        #region Weighted Sum\n\n        [Pure]\n        public static float WeightedSum(this float[] items, float[] weights)\n        {\n            float r = 0;\n            var count = weights.Length;\n            for (int i = 0; i < count; i++) r += weights[i] * items[i];\n            return r;\n        }\n\n        [Pure]\n        public static double WeightedSum(this double[] items, double[] weights)\n        {\n            double r = 0;\n            var count = weights.Length;\n            for (int i = 0; i < count; i++) r += weights[i] * items[i];\n            return r;\n        }\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"float\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(this float v)\n            => Single.IsNaN(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"float\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(this float v)\n            => Single.IsInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"float\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(this float v)\n            => Single.IsNegativeInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"float\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(this float v)\n            => Single.IsPositiveInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"float\"/> is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(this float v)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Single.IsFinite(v);\n#else\n                return !(IsNaN(v) || IsInfinity(v));\n#endif\n        }\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"double\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(this double v)\n            => Double.IsNaN(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"double\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(this double v)\n            => Double.IsInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"double\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(this double v)\n            => Double.IsNegativeInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"double\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(this double v)\n            => Double.IsPositiveInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"double\"/> is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(this double v)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return Double.IsFinite(v);\n#else\n                return !(IsNaN(v) || IsInfinity(v));\n#endif\n        }\n\n        #endregion\n\n        #region Signs\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Signs GetSigns(this float value, float epsilon)\n        {\n            if (value < -epsilon) return Signs.Negative;\n            if (value > +epsilon) return Signs.Positive;\n            return Signs.Zero;\n        }\n\n        public static void AggregateSigns(\n                this IEnumerable<float> values, float epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n        {\n            int nc = 0, zc = 0, pc = 0;\n            foreach (var v in values)\n            {\n                if (v < -epsilon) { ++nc; continue; }\n                if (v > +epsilon) { ++pc; continue; }\n                ++zc;\n            }\n            negativeCount = nc;\n            zeroCount = zc;\n            positiveCount = pc;\n        }\n\n        public static void AggregateSigns(\n                this (float, float) values, float epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static void AggregateSigns(\n                this (float, float, float) values, float epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static void AggregateSigns(\n                this (float, float, float, float) values, float epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3, values.Item4 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static Signs AggregateSigns(this IEnumerable<float> values, float epsilon)\n        {\n            var signs = Signs.None;\n            foreach (var v in values)\n            {\n                if (v < -epsilon) { signs |= Signs.Negative; continue; }\n                if (v > +epsilon) { signs |= Signs.Positive; continue; }\n                signs |= Signs.Zero;\n            }\n            return signs;\n        }\n\n        public static Signs AggregateSigns(this (float, float) values, float epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2 }, epsilon);\n\n        public static Signs AggregateSigns(this (float, float, float) values, float epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3 }, epsilon);\n\n        public static Signs AggregateSigns(this (float, float, float, float) values, float epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3, values.Item4 }, epsilon);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Signs GetSigns(this double value, double epsilon)\n        {\n            if (value < -epsilon) return Signs.Negative;\n            if (value > +epsilon) return Signs.Positive;\n            return Signs.Zero;\n        }\n\n        public static void AggregateSigns(\n                this IEnumerable<double> values, double epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n        {\n            int nc = 0, zc = 0, pc = 0;\n            foreach (var v in values)\n            {\n                if (v < -epsilon) { ++nc; continue; }\n                if (v > +epsilon) { ++pc; continue; }\n                ++zc;\n            }\n            negativeCount = nc;\n            zeroCount = zc;\n            positiveCount = pc;\n        }\n\n        public static void AggregateSigns(\n                this (double, double) values, double epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static void AggregateSigns(\n                this (double, double, double) values, double epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static void AggregateSigns(\n                this (double, double, double, double) values, double epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3, values.Item4 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static Signs AggregateSigns(this IEnumerable<double> values, double epsilon)\n        {\n            var signs = Signs.None;\n            foreach (var v in values)\n            {\n                if (v < -epsilon) { signs |= Signs.Negative; continue; }\n                if (v > +epsilon) { signs |= Signs.Positive; continue; }\n                signs |= Signs.Zero;\n            }\n            return signs;\n        }\n\n        public static Signs AggregateSigns(this (double, double) values, double epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2 }, epsilon);\n\n        public static Signs AggregateSigns(this (double, double, double) values, double epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3 }, epsilon);\n\n        public static Signs AggregateSigns(this (double, double, double, double) values, double epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3, values.Item4 }, epsilon);\n\n        #endregion\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Fun_template.cs",
    "content": "using System;\nusing System.ComponentModel;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Diagnostics.Contracts;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action add = () => Out(\" + \");\n    //# var inttypes = Meta.IntegerTypes;\n    //# var signedtypes = Meta.SignedTypes;\n    //# var unsignedtypes = Meta.UnsignedTypes;\n    //# var numtypes = Meta.StandardNumericTypes;\n    //# var numdectypes = Meta.BuiltInNumericTypes;\n    //# var numhdectypes = Meta.BuiltInNumericTypes.Concat(Meta.HalfType);\n    //# var reptypes = Meta.RealRepresentableTypes;\n    //# var freptypes = reptypes[Meta.FloatType];\n    //# var dreptypes = reptypes[Meta.DoubleType];\n    //# var modtypes = new [] { Meta.IntType, Meta.LongType, Meta.UIntType, Meta.ULongType };\n    //# var smalltypes = new [] { Meta.SByteType, Meta.ShortType, Meta.ByteType, Meta.UShortType };\n    //# var iltypes = new[] { Meta.IntType, Meta.LongType };\n    //# var fdtypes = new[] { Meta.FloatType, Meta.DoubleType };\n    //# var hfdtypes = new[] { Meta.HalfType, Meta.FloatType, Meta.DoubleType };\n    //# var fddectypes = new [] { Meta.FloatType, Meta.DoubleType, Meta.DecimalType };\n    //# var hfddectypes = new [] { Meta.HalfType, Meta.FloatType, Meta.DoubleType, Meta.DecimalType };\n    //# var ilfdtypes = Meta.VecFieldTypes;\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        //# Meta.ComparableTypes.ForEach(t => { var type = t.Name;\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Min(this __type__ a, __type__ b)\n            => a < b ? a : b;\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Max(this __type__ a, __type__ b)\n            => a > b ? a : b;\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Min(this __type__ a, __type__ b, __type__ c)\n            => a < b ? (a < c ? a : c) : (b < c ? b : c);\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Max(this __type__ a, __type__ b, __type__ c)\n            => a > b ? (a > c ? a : c) : (b > c ? b : c);\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Min(this __type__ a, __type__ b, __type__ c, __type__ d)\n            => Min(Min(a, b), Min(c, d));\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Max(this __type__ a, __type__ b, __type__ c, __type__ d)\n            => Max(Max(a, b), Max(c, d));\n\n        /// <summary>\n        /// Returns the minimum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Min(this __type__ x, params __type__[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Min(result, values[i]); }\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the maximum of the given values.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Max(this __type__ x, params __type__[] values)\n        {\n            var result = x;\n            for (var i = 0; i < values.Length; i++) { result = Max(result, values[i]); }\n            return result;\n        }\n\n        //# });\n        #endregion\n\n        #region Abs\n\n        //# signedtypes.ForEach(t => {\n        //# var fname = \"Abs\";\n        /// <summary>\n        /// Returns the absolute value of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Abs(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n            #else\n                return Math.__fname__(x);\n            #endif\n            //# }\n        }\n\n        //# });\n        #endregion\n\n        #region Angular Distance\n\n        //# fdtypes.ForEach(t => {\n        //# var constant = (t == Meta.DoubleType) ? \"Constant\" : \"ConstantF\";\n        /// <summary>\n        /// Returns the absolute difference between two angles in radians.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ AngleDistance(this __t.Name__ alphaInRadians, __t.Name__ betaInRadians)\n        {\n            var phi = Abs(betaInRadians - alphaInRadians) % __constant__.PiTimesTwo;\n            return (phi > __constant__.Pi) ? __constant__.PiTimesTwo - phi : phi;\n        }\n\n        /// <summary>\n        /// Returns the signed difference between two angles in radians.\n        /// The result is within the range of [-Pi, Pi).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ AngleDifference(this __t.Name__ alphaInRadians, __t.Name__ betaInRadians)\n        {\n            var phi = (betaInRadians - alphaInRadians + __constant__.Pi) % __constant__.PiTimesTwo - __constant__.Pi;\n            return (phi < -__constant__.Pi) ? phi + __constant__.PiTimesTwo : phi;\n        }\n\n        //# });\n        #endregion\n\n        #region ApproximateEquals\n\n        //# numtypes.ForEach(t => {\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than epsilon.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __t.Name__ x, __t.Name__ y, __t.Name__ epsilon)\n        {\n            //# if (signedtypes.Contains(t)) {\n            return Abs(x - y) <= epsilon;\n            //# } else {\n            return (x > y) ? ((x - y) <= epsilon) : ((y - x) <= epsilon);\n            //# }\n        }\n\n        //# });\n        //# fdtypes.ForEach(t => {\n        /// <summary>\n        /// Returns whether the distance between x and y is not more than\n        /// Constant{__t.Name__}.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __t.Name__ x, __t.Name__ y)\n            => ApproximateEquals(x, y, Constant<__t.Name__>.PositiveTinyValue);\n\n        //# });\n        #endregion\n\n        #region Floor\n\n        //# fddectypes.ForEach(t => {\n        //# var fname = \"Floor\";\n        /// <summary>\n        /// Returns the largest integer less than or equal to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Floor(this __t.Name__ x)\n        {\n            //# if (t == Meta.DecimalType) {\n            return Decimal.__fname__(x);\n            //# } else if (t == Meta.DoubleType) {\n            return Math.__fname__(x);\n            //# } else if (t == Meta.FloatType) {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n            #else\n                return (float) Math.__fname__(x);\n            #endif\n            //# }\n        }\n\n        //# });\n        #endregion\n\n        #region Ceiling\n\n        //# fddectypes.ForEach(t => {\n        //# var fname = \"Ceiling\";\n        /// <summary>\n        /// Returns the smallest integer greater than or equal to the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Ceiling(this __t.Name__ x)\n        {\n            //# if (t == Meta.DecimalType) {\n            return Decimal.__fname__(x);\n            //# } else if (t == Meta.DoubleType) {\n            return Math.__fname__(x);\n            //# } else if (t == Meta.FloatType) {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n            #else\n                return (float) Math.__fname__(x);\n            #endif\n            //# }\n        }\n\n        //# });\n        #endregion\n\n        #region Round\n\n        //# fddectypes.ForEach(t => {\n        //# var fname = \"Round\";\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Round(this __t.Name__ x)\n        {\n            //# if (t == Meta.DecimalType) {\n            return Decimal.__fname__(x);\n            //# } else if (t == Meta.DoubleType) {\n            return Math.__fname__(x);\n            //# } else if (t == Meta.FloatType) {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n            #else\n                return (float) Math.__fname__(x);\n            #endif\n            //# }\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Round(this __t.Name__ x, MidpointRounding mode)\n        {\n            //# if (t == Meta.DecimalType) {\n            return Decimal.__fname__(x, mode);\n            //# } else if (t == Meta.DoubleType) {\n            return Math.__fname__(x, mode);\n            //# } else if (t == Meta.FloatType) {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x, mode);\n            #else\n                return (float) Math.__fname__(x, mode);\n            #endif\n            //# }\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Round(this __t.Name__ x, int digits)\n        {\n            //# if (t == Meta.DecimalType) {\n            return Decimal.__fname__(x, digits);\n            //# } else if (t == Meta.DoubleType) {\n            return Math.__fname__(x, digits);\n            //# } else if (t == Meta.FloatType) {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x, digits);\n            #else\n                return (float) Math.__fname__(x, digits);\n            #endif\n            //# }\n        }\n\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integral value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Round(this __t.Name__ x, int digits, MidpointRounding mode)\n        {\n            //# if (t == Meta.DecimalType) {\n            return Decimal.__fname__(x, digits, mode);\n            //# } else if (t == Meta.DoubleType) {\n            return Math.__fname__(x, digits, mode);\n            //# } else if (t == Meta.FloatType) {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x, digits, mode);\n            #else\n                return (float) Math.__fname__(x, digits, mode);\n            #endif\n            //# }\n        }\n\n        //# });\n        #endregion\n\n        #region Truncate\n\n        //# fddectypes.ForEach(t => {\n        //# var fname = \"Truncate\";\n        /// <summary>\n        /// Rounds a floating-point value to the nearest integar towards zero.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Truncate(this __t.Name__ x)\n        {\n            //# if (t == Meta.DecimalType) {\n            return Decimal.__fname__(x);\n            //# } else if (t == Meta.DoubleType) {\n            return Math.__fname__(x);\n            //# } else if (t == Meta.FloatType) {\n            #if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n            #else\n                return (float) Math.__fname__(x);\n            #endif\n            //# }\n        }\n\n        //# });\n        #endregion\n\n        #region Frac\n\n        //# fddectypes.ForEach(t => {\n        /// <summary>\n        /// Returns the fractional part of t. Calculated as t - floor(t).\n        /// The result is always positive and in [0, 1).\n        /// The fractional part of a negative input will be flipped (e.g. frac(-0.3) -> 0.7).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Frac(this __t.Name__ t)\n        {\n            var res = t - Floor(t);\n            return res == 1 ? 0 : res;\n        }\n\n        //# });\n        #endregion\n\n        #region Clamp\n\n        //# numdectypes.ForEach(t => {\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Clamp(this __t.Name__ x, __t.Name__ a, __t.Name__ b)\n        {\n            if (x < a) return a;\n            if (x > b) return b;\n            return x;\n        }\n\n        //# });\n        //# ilfdtypes.ForEach(t => {\n        /// <summary>\n        /// Clamps value to interval [a,b].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Clamp(this __t.Name__ x, Range1__t.Char__ range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x > range.Max) return range.Max;\n            return x;\n        }\n\n        //# });\n#endregion\n\n        #region ClampExcl\n\n        //# numdectypes.Where(t => !t.IsReal).ForEach(t => {\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ ClampExcl(this __t.Name__ x, __t.Name__ a, __t.Name__ b)\n        {\n            if (x < a) return a;\n            if (x >= b) return (__t.Name__)(b - 1);\n            return x;\n        }\n\n        //# });\n        //# ilfdtypes.Where(t => !t.IsReal).ForEach(t => {\n        /// <summary>\n        /// Clamps value to interval [a,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ ClampExcl(this __t.Name__ x, Range1__t.Char__ range)\n        {\n            if (x < range.Min) return range.Min;\n            if (x >= range.Max) return (__t.Name__)(range.Max - 1);\n            return x;\n        }\n\n        //# });\n        #endregion\n\n        #region ClampWrap\n\n        //# numdectypes.Where(t => t.Name != \"ulong\").ForEach(t => { //ulong cannot be wrapped in a larger integer variable for subtraction\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ ClampWrap(this __t.Name__ x, __t.Name__ a, __t.Name__ b)\n            => (__t.Name__)(ModP(x - a, b - a) + a);\n\n        //# });\n        //# ilfdtypes.Where(t => t.Name != \"ulong\").ForEach(t => { //ulong cannot be wrapped in a larger integer variable for subtraction\n        /// <summary>\n        /// Clamps value to interval [a,b[ and cyclically wraps around values outside this interval.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ ClampWrap(this __t.Name__ x, Range1__t.Char__ range)\n            => (__t.Name__)(ModP(x - range.Min, range.Max - range.Min) + range.Min);\n\n        //# });\n        #endregion\n\n        #region WrapToPi\n\n        //# fdtypes.ForEach(t => {\n        //# var constant = (t == Meta.DoubleType) ? \"Constant\" : \"ConstantF\";\n        /// <summary>\n        /// Wraps the given angle to the [-Pi, Pi] range.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ WrapToPi(this __t.Name__ angleInRadians)\n        {\n            var x = angleInRadians % __constant__.PiTimesTwo;\n            return (x.Abs() > __constant__.Pi) ? x - __constant__.PiTimesTwo * x.Signum() : x;\n        }\n\n        //# });\n        #endregion\n\n        #region Saturate\n        //# numdectypes.ForEach(t => {\n        //# var cast = smalltypes.Contains(t) ? \"(\" + t.Name + \")\" : \"\";\n        /// <summary>\n        /// Clamps value to interval [0,1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Saturate(this __t.Name__ x)\n            => Clamp(x, __cast__0, __cast__1);\n\n        //# });\n        #endregion\n\n        #region MapToUnitInterval\n\n        //# fdtypes.ForEach(t => {\n        //# var half = (t != Meta.DoubleType) ? \"0.5f\" : \"0.5\";\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// Values outside [0, tMax] are clamped - if t is greater than tMax\n        /// then 1 is returned, if t is less than 0 then 0 is returned.\n        /// If 'repeat' is true, then every interval [i * tMax, (i+1) * tMax]\n        /// (for i from integers) is mapped to [0, 1].\n        /// If 'mirror' is true, then every second interval is flipped, such\n        /// that [0, tMax) [tMax, 2*tMax) [2*tMax, 3*tMax] ... is mapped to\n        /// [0,1)[1,0)[0,1)...\n        /// </summary>\n        [Pure]\n        public static __t.Name__ MapToUnitInterval(\n            this __t.Name__ t, __t.Name__ tMax,\n            bool repeat, bool mirror\n            )\n        {\n            t = t / tMax;\n            if (!repeat)\n            {\n                if (t >= 1) return 1;\n                if (t <= 0) return 0;\n            }\n            if (mirror)\n            {\n                t = t - Floor(t * __half__) * 2;\n                return t < 1 ? t : 2 - t;\n            }\n            else\n            {\n                return t - Floor(t);\n            }\n        }\n\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// If 'repeat' is true, then every interval [i * tMax, (i+1) * tMax]\n        /// (for i from integers) is mapped to [0, 1].\n        /// </summary>\n        [Pure]\n        public static __t.Name__ MapToUnitInterval(this __t.Name__ t, __t.Name__ tMax, bool repeat)\n        {\n            t = t / tMax;\n            if (!repeat)\n            {\n                if (t >= 1) return 1;\n                if (t <= 0) return 0;\n            }\n            return t - Floor(t);\n        }\n\n        /// <summary>\n        /// Maps value from interval [0, tMax] to interval [0, 1].\n        /// </summary>\n        [Pure]\n        public static __t.Name__ MapToUnitInterval(this __t.Name__ t, __t.Name__ tMax)\n        {\n            t = t / tMax;\n            if (t > 1) return 1;\n            if (t < 0) return 0;\n            return t;\n        }\n\n        /// <summary>\n        /// Maps value from interval [tMin, tMax] to interval [0, 1].\n        /// </summary>\n        [Pure]\n        public static __t.Name__ MapToUnitInterval(this __t.Name__ t, __t.Name__ tMin, __t.Name__ tMax)\n        {\n            t = (t - tMin) / (tMax - tMin);\n            if (t > 1) return 1;\n            if (t < 0) return 0;\n            return t;\n        }\n\n        //# });\n\n        #endregion\n\n        #region Sign\n\n        //# signedtypes.ForEach(t => {\n        //# var fname = \"Sign\";\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        // Same as Fun.Sign(), we need this for the F# generic math library!\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Signumi(this __t.Name__ x)\n            => Sign(x);\n\n        /// <summary>\n        /// Returns either -1, 0, or +1, indicating the sign of the specified value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Signum(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return (__t.Name__) Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        //# });\n        #endregion\n\n        #region Multiply-Add\n\n        //# numdectypes.ForEach(t => {\n        //# var type = t.Name;\n        //# var isDouble = (t == Meta.DoubleType);\n        //# if (fdtypes.Contains(t)) {\n#if NETCOREAPP3_1_OR_GREATER\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// Computes the result rounded as a single ternary operation.\n        /// </summary>\n#else\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n#endif\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ MultiplyAdd(__type__ x, __type__ y, __type__ z)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                //# if (isDouble) {\n                return Math.FusedMultiplyAdd(x, y, z);\n                //# } else {\n                return MathF.FusedMultiplyAdd(x, y, z);\n                //# }\n#else\n                return (x * y) + z;\n#endif\n        }\n\n        //# } else {\n        //# var cast = smalltypes.Contains(t) ? \"(\" + type + \")\" : \"\";\n        /// <summary>\n        /// Returns (x * y) + z.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ MultiplyAdd(__type__ x, __type__ y, __type__ z)\n            => __cast__((x * y) + z);\n\n        //# }\n        //# });\n        #endregion\n\n        #region Floating point bits\n\n        //# fdtypes.ForEach(t => {\n        //# var type = t.Name;\n        //# var isDouble = (t == Meta.DoubleType);\n        //# {\n        //# var toBits = isDouble ? \"DoubleToInt64Bits\" : \"SingleToInt32Bits\";\n        //# var fromBits = isDouble ? \"Int64BitsToDouble\" : \"Int32BitsToSingle\";\n        //# var bittype = isDouble ? \"long\" : \"int\";\n#if NETSTANDARD2_0\n            /// <summary>\n            /// Returns the bit representation of the given <see cref=\"__type__\"/> value as a <see cref=\"__bittype__\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static unsafe __bittype__ FloatToBits(this __type__ x)\n                => *((__bittype__*)&x);\n\n            /// <summary>\n            /// Returns the <see cref=\"__type__\"/> value represented by the given <see cref=\"__bittype__\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static unsafe __type__ FloatFromBits(this __bittype__ x)\n                => *((__type__*)&x);\n#else\n            /// <summary>\n            /// Returns the bit representation of the given <see cref=\"__type__\"/> value as a <see cref=\"__bittype__\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static __bittype__ FloatToBits(this __type__ x)\n                => BitConverter.__toBits__(x);\n\n            /// <summary>\n            /// Returns the <see cref=\"__type__\"/> value represented by the given <see cref=\"__bittype__\"/>.\n            /// </summary>\n            [Pure]\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static __type__ FloatFromBits(this __bittype__ x)\n                => BitConverter.__fromBits__(x);\n#endif\n        //# }\n\n        //# {\n        //# var bittype = isDouble ? \"ulong\" : \"uint\";\n        /// <summary>\n        /// Returns the bit representation of the given <see cref=\"__type__\"/> value as a <see cref=\"__bittype__\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static unsafe __bittype__ FloatToUnsignedBits(this __type__ x)\n            => *((__bittype__*)&x);\n\n        /// <summary>\n        /// Returns the <see cref=\"__type__\"/> value represented by the given <see cref=\"__bittype__\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static unsafe __type__ FloatFromUnsignedBits(this __bittype__ x)\n            => *((__type__*)&x);\n        //# }\n\n        //# });\n        #endregion\n\n        #region Copy sign\n\n        //# fdtypes.ForEach(t => {\n        //# var type = t.Name;\n        //# var fname = \"CopySign\";\n        //# var isDouble = (t == Meta.DoubleType);\n        //# var bittype = isDouble ? \"long\" : \"int\";\n        /// <summary>\n        /// Returns a value with the maginute of <paramref name=\"value\"/> and the sign of <paramref name=\"sign\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ __fname__(__type__ value, __type__ sign)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                //# if (t != Meta.FloatType) {\n                return Math.__fname__(value, sign);\n                //# } else {\n                return MathF.__fname__(value, sign);\n                //# }\n#else\n                var xbits = FloatToBits(value);\n                var ybits = FloatToBits(sign);\n\n                if ((xbits ^ ybits) < 0)\n                {\n                    return FloatFromBits(xbits ^ __bittype__.MinValue);\n                }\n\n                return value;\n#endif\n        }\n\n        //# });\n        #endregion\n\n        #region Comparisons\n\n        //# numtypes.ForEach(t => {\n        //# var abs = signedtypes.Contains(t) ? \".Abs()\" : \"\";\n        //# var absValue = signedtypes.Contains(t) ? \"the absolute value of \" : \"\";\n        /// <summary>\n        /// Returns whether __absValue__<paramref name=\"x\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this __t.Name__ x, __t.Name__ epsilon)\n            => x__abs__ < epsilon;\n\n        //# if (fdtypes.Contains(t)) {\n        /// <summary>\n        /// Returns whether the absolute value of <paramref name=\"x\"/> is smaller than Constant&lt;__t.Name__&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this __t.Name__ x)\n            => x__abs__ < Constant<__t.Name__>.PositiveTinyValue;\n\n        //# }\n        //# });\n        #endregion\n\n        #region AbsSum\n\n        //# signedtypes.ForEach(t => { var st = Meta.SummationTypeOf(t);\n        /// <summary>\n        /// Returns the sum of the absolute values of the given numbers.\n        /// </summary>\n        [Pure]\n        public static __st.Name__ AbsSum(this IEnumerable<__t.Name__> array)\n        {\n            __st.Name__ sum = 0;\n            foreach (var i in array) sum += i.Abs();\n            return sum;\n        }\n\n        //# });\n        #endregion\n\n        #region Roots\n\n        //# numtypes.ForEach(t => {\n        //# var fname = \"Pow\";\n        //# var rtype = (t != Meta.FloatType) ? Meta.DoubleType : Meta.FloatType;\n        /// <summary>\n        /// Returns the n-th root of the specified number.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype.Name__ Root(this __t.Name__ x, int n)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x, 1.0 / n);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x, 1.0f / n);\n#else\n                return (float)Math.__fname__(x, 1.0 / n);\n#endif\n            //# }\n        }\n\n        //# });\n        //# numtypes.ForEach(t => {\n        //# var fname = \"Sqrt\";\n        //# var rtype = (t != Meta.FloatType) ? Meta.DoubleType : Meta.FloatType;\n        /// <summary>\n        /// Returns the square root of the specified number.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype.Name__ Sqrt(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        //# });\n        //# numtypes.ForEach(t => {\n        //# var fname = \"Cbrt\";\n        //# var rtype = (t != Meta.FloatType) ? Meta.DoubleType : Meta.FloatType;\n        //# var rcast = (rtype != Meta.DoubleType) ? \"(\" + rtype.Name + \")\" : \"\";\n        /// <summary>\n        /// Returns the cubic root of the specified number.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype.Name__ Cbrt(this __t.Name__ x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                //# if (t != Meta.FloatType) {\n                return Math.__fname__(x);\n                //# } else {\n                return MathF.__fname__(x);\n                //# }\n#else\n                //# if (signedtypes.Contains(t)) {\n                return x < 0 ? __rcast__-Math.Pow(-x, Constant.OneThird)\n                             :  __rcast__Math.Pow( x, Constant.OneThird);\n                //# } else {\n                return __rcast__Math.Pow(x, Constant.OneThird);\n                //# }\n#endif\n        }\n\n        //# });\n        #endregion\n\n        #region Square\n\n        //# numdectypes.ForEach(t => {\n        /// <summary>\n        /// Returns the square of the specified number.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Square(this __t.Name__ x)\n            => (__t.Name__)(x * x);\n\n        //# });\n\n        #endregion\n\n        #region Power\n\n        //# numtypes.ForEach(t => {\n        //# fdtypes.ForEach(rt => {\n        //# var rcast = (rt != Meta.DoubleType) ? \"(\" + rt.Name + \")\" : \"\";\n        //# if (!fdtypes.Contains(t) || t == rt) {\n        /// <summary>\n        /// Returns the number raised to the specified power.\n        //# if (rt == Meta.DoubleType && !dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rt.Name__ Pow(this __t.Name__ x, __rt.Name__ y)\n        {\n            //# if (rt != Meta.FloatType || !freptypes.Contains(t)) {\n            return __rcast__Math.Pow(x, y);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(x, y);\n#else\n                return __rcast__Math.Pow(x, y);\n#endif\n            //# }\n        }\n\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rt.Name__ Power(this __t.Name__ x, __rt.Name__ y)\n            => Pow(x, y);\n\n        //# }\n        //# });\n        //# if (!fdtypes.Contains(t) && t != Meta.IntType) {\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        //# if (signedtypes.Contains(t)) {\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        //# }\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Pown(this __t.Name__ x, __t.Name__ y)\n        {\n            //# if (smalltypes.Contains(t)) {\n            //# var cast = Meta.UnsignedTypes.Contains(t) ? \"(uint)\" : \"(int)\";\n            return (__t.Name__)Pown(__cast__x, y);\n            //# } else {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n            //# }\n        }\n\n        //# }\n        /// <summary>\n        /// Returns the number raised to the specified integer power.\n        /// The exponent <paramref name=\"y\"/> must not be negative.\n        /// </summary>\n        // Based on the F# core library implementation (ComputePowerGenericInlined)\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Pown(this __t.Name__ x, int y)\n        {\n            //# if (smalltypes.Contains(t)) {\n            //# var cast = Meta.UnsignedTypes.Contains(t) ? \"(uint)\" : \"(int)\";\n            return (__t.Name__)Pown(__cast__x, y);\n            //# } else {\n            Debug.Assert(y >= 0);\n            if (y == 0) return 1;\n            if (y == 1) return x;\n            if (y == 2) return x * x;\n            if (y == 3) return x * x * x;\n            if (y == 4) { var xx = x * x; return xx * xx; }\n\n            var v = Pown(x, y / 2);\n            v *= v;\n            return (y % 2 == 0) ? v : v * x;\n            //# }\n        }\n\n        //# });\n\n        #endregion\n\n        #region Exp and Log\n\n        //# numtypes.ForEach(t => {\n        //# var rtype = (t != Meta.FloatType) ? Meta.DoubleType : Meta.FloatType;\n        //# var rconst = (rtype != Meta.DoubleType) ? \"ConstantF\" : \"Constant\";\n        /// <summary>\n        /// Returns e raised to the specified number.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        //# var fname = \"Exp\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the natural (base e) logarithm of the specified number.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        //# fname = \"Log\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the base 10 logarithm of the specified number.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        //# fname = \"Log10\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the base 2 logarithm of the specified number.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        //# fname = \"Log2\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype.Name__ __fname__(this __t.Name__ x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n            //# if (t != Meta.FloatType) {\n                return Math.__fname__(x);\n            //# } else {\n                //return MathF.__fname__(x); // MathF.Log2 actually uses a conversion to double internally and has bad perfromance, see Aardvark.Base.Benchmarks/Log2Int.cs\n                return x.Log() * __rconst__.Ln2Inv;\n            //# }\n#else\n                return x.Log() * __rconst__.Ln2Inv;\n#endif\n        }\n\n        /// <summary>\n        /// Returns the values logarithm of the specified basis.\n        //# if (!dreptypes.Contains(t)) {\n        /// Note: This function uses a double representation internally, but not all __t.Name__ values can be represented exactly as double.\n        //# }\n        /// </summary>\n        //# fname = \"Log\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype.Name__ __fname__(this __t.Name__ x, __rtype.Name__ basis)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x, basis);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x, basis);\n#else\n                return (float)Math.__fname__(x, basis);\n#endif\n            //# }\n        }\n\n        //# });\n        #endregion\n\n        #region LinCom\n\n        //# foreach (var it in Meta.IntegerTypes) { var itn = it.Name;\n        //# for (int tpc = 4; tpc < 7; tpc+=2) {\n        //# foreach (var rt in Meta.RealTypes) { var rtn = rt.Name; var rtc = rt.Caps[0];\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __itn__ LinCom(\n                /*# tpc.ForEach(i => { */__itn__ p__i__/*# }, comma); */, ref Tup__tpc__<__rtn__> w)\n        {\n            return (__itn__)Fun.Clamp(/*# tpc.ForEach(i => { */p__i__ * w.E__i__/*# }, add); */, (__rtn__)__itn__.MinValue, (__rtn__)__itn__.MaxValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtn__ LinComRaw__rtc__(\n                /*# tpc.ForEach(i => { */__itn__ p__i__/*# }, comma); */, ref Tup__tpc__<__rtn__> w)\n        {\n            return /*# tpc.ForEach(i => { */p__i__ * w.E__i__/*# }, add); */;\n        }\n\n        //# } // rt\n        //# } // tpc\n        //# } // it\n        //# for (int tpc = 2; tpc < 8; tpc++ ) {\n        //# foreach (var rt in hfdtypes) { var rtn = rt.Name;\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtn__ LinCom(/*# tpc.ForEach(i => { */__rtn__ p__i__/*# }, comma); */, ref Tup__tpc__<__rtn__> w)\n        {\n            return /*# tpc.ForEach(i => { */p__i__ * w.E__i__/*# }, add); */;\n        }\n\n        //# } // rt\n        //# } // tpc\n        #endregion\n\n        #region ModP\n\n        //# signedtypes.ForEach(t => {\n        /// <summary>\n        /// Returns the positive modulo operation a mod b giving values between [0,b[\n        /// instead of a % b giving values between ]-b,b[.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ ModP(this __t.Name__ a, __t.Name__ b)\n        {\n            var m = a % b;\n            if (m < 0)\n                m += b;\n            return (__t.Name__)m;\n        }\n\n        //# });\n        #endregion\n\n        #region PowerOfTwo\n\n        //# modtypes.ForEach(t => {\n        /// <summary>\n        /// Returns true if the supplied number is 0 or a power of two.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPowerOfTwo(this __t.Name__ x) => (x & (x - 1)) == 0;\n\n        //# });\n        //# inttypes.ForEach(t => {\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        //# if (signedtypes.Contains(t)) {\n        /// The exponent <paramref name=\"x\"/> must be within [0, 64).\n        //# } else {\n        /// The exponent <paramref name=\"x\"/> must be less than 64.\n        //# }\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ulong PowerOfTwo(this __t.Name__ x)\n        {\n            Debug.Assert(x >= 0 && x < 64);\n            return 1UL << (int)x;\n        }\n\n        //# });\n        //# fdtypes.ForEach(t => {\n        /// <summary>\n        /// Returns 2 raised to the power of the value.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ PowerOfTwo(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.Pow(2, x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.Pow(2, x);\n#else\n                return (float)Math.Pow(2, x);\n#endif\n            //# }\n        }\n\n        //# });\n        //# modtypes.ForEach(t => {\n        //# var limit = new Dictionary<Meta.SimpleType, string>\n        //#     {\n        //#         { Meta.IntType, \"30\" },\n        //#         { Meta.UIntType, \"31\" },\n        //#         { Meta.LongType, \"62\" },\n        //#         { Meta.ULongType, \"63\" }\n        //#     };\n        /// <summary>\n        /// Returns the nearest superior power of two of the value.\n        //# if (signedtypes.Contains(t)) {\n        /// For x &lt;= 0, returns 0.\n        /// For x &gt; 2^__limit[t]__, returns __t.Name__.MinValue.\n        //# } else {\n        /// For x = 0 and x &gt; 2^__limit[t]__, returns 0.\n        //# }\n        /// E.g. x = 401 -> 512.\n        /// E.g. x = 256 -> 256.\n        /// </summary>\n        [Pure]\n        public static __t.Name__ NextPowerOfTwo(this __t.Name__ x)\n        {\n            --x;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            //# if (t == Meta.LongType || t == Meta.ULongType) {\n            x |= x >> 32;\n            //# }\n            return ++x;\n        }\n\n        /// <summary>\n        /// Returns the nearest inferior power of two of the value.\n        /// For x &lt;= 0, returns 0.\n        /// E.g. x = 401 -> 256.\n        /// E.g. x = 512 -> 512.\n        /// </summary>\n        [Pure]\n        public static __t.Name__ PrevPowerOfTwo(this __t.Name__ x)\n        {\n            //# if (signedtypes.Contains(t)) {\n            if (x <= 0) return 0;\n            //# } else {\n            if (x == 0) return 0;\n            //# }\n            x >>= 1;\n            x |= x >> 1;\n            x |= x >> 2;\n            x |= x >> 4;\n            x |= x >> 8;\n            x |= x >> 16;\n            //# if (t == Meta.LongType || t == Meta.ULongType) {\n            x |= x >> 32;\n            //# }\n            return ++x;\n        }\n\n        //# });\n        #endregion\n\n        #region Trigonometry\n\n        //# fdtypes.ForEach(t => {\n        //# var cast = t != Meta.DoubleType ? \"(\" + t.Name + \")\" : \"\";\n        //# var half = (t == Meta.DoubleType) ? \"0.5\" : \"0.5f\";\n        //# var constant = (t == Meta.DoubleType) ? \"Constant\" : \"ConstantF\";\n        //# {\n        //# var eps = (t == Meta.DoubleType) ? \"6.840859302478615E-09\" : \"0.00017791694f\";\n        /// <summary>\n        /// Normalized sinc function.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Sinc(this __t.Name__ x)\n        {\n            // See unit test for determining eps\n            if (Abs(x) < __eps__)\n            {\n                return 1;\n            }\n            else\n            {\n                //# if (t != Meta.FloatType) {\n                return Math.Sin(__constant__.Pi * x) / (__constant__.Pi * x);\n                //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                    return MathF.Sin(__constant__.Pi * x) / (__constant__.Pi * x);\n#else\n                    return (float)Math.Sin(__constant__.Pi * x) / (__constant__.Pi * x);\n#endif\n                //# }\n            }\n        }\n        //# }\n\n        /// <summary>\n        /// Returns the sine of the specified angle in radians.\n        /// </summary>\n        //# var fname = \"Sin\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the cosine of the specified angle in radians.\n        /// </summary>\n        //# fname = \"Cos\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the tangent of the specified angle in radians.\n        /// </summary>\n        //# fname = \"Tan\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose sine is the specified number.\n        /// </summary>\n        //# fname = \"Asin\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose sine is the specified number while clamping the input to [-1, 1] in order to avoid numerical problems.\n        /// </summary>\n        //# fname = \"Asin\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__Clamped(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(Clamp(x, -1, 1));\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(Clamp(x, -1, 1));\n#else\n                return (float)Math.__fname__(Clamp(x, -1, 1));\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose cosine is the specified number.\n        /// </summary>\n        //# fname = \"Acos\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose cosine is the specified number while clamping the input to [-1, 1] in order to avoid numerical problems.\n        /// </summary>\n        //# fname = \"Acos\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__Clamped(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(Clamp(x, -1, 1));\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(Clamp(x, -1, 1));\n#else\n                return (float)Math.__fname__(Clamp(x, -1, 1));\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is the specified number.\n        /// </summary>\n        //# fname = \"Atan\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is\n        /// the quotient of the two specified numbers.\n        /// </summary>\n        //# fname = \"Atan2\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(__t.Name__ y, __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(y, x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(y, x);\n#else\n                return (float)Math.__fname__(y, x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the angle in radians whose tangent is\n        /// the quotient of the two specified numbers using\n        /// a faster algorithm than Math.Atan2.\n        /// NOTE: Accuracy untested\n        /// </summary>\n        [Pure]\n        public static __t.Name__ FastAtan2(__t.Name__ y, __t.Name__ x)\n        {\n            __t.Name__ angle;\n            double piThreeFourths = Constant.Pi * 3 / 4;\n            double yAbs = y.Abs() + Constant<double>.PositiveTinyValue; // prevent 0/0 condition\n            if (x >= 0)\n            {\n                double r = (x - yAbs) / (x + yAbs);\n                angle = __cast__(Constant.PiQuarter * (1 - r));\n            }\n            else\n            {\n                double r = (x + yAbs) / (yAbs - x);\n                angle = __cast__(piThreeFourths - Constant.PiQuarter * r);\n            }\n\n            return y < 0 ? -angle : angle; // negate if in quad III or IV\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic sine of the specified number.\n        /// </summary>\n        //# fname = \"Sinh\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic cosine of the specified number.\n        /// </summary>\n        //# fname = \"Cosh\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the hyperbolic tangent of the specified number.\n        /// </summary>\n        //# fname = \"Tanh\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n            //# if (t != Meta.FloatType) {\n            return Math.__fname__(x);\n            //# } else {\n#if NETCOREAPP3_1_OR_GREATER\n                return MathF.__fname__(x);\n#else\n                return (float)Math.__fname__(x);\n#endif\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic sine of the specified number.\n        /// </summary>\n        //# fname = \"Asinh\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n            //# if (t != Meta.FloatType) {\n                return Math.__fname__(x);\n            //# } else {\n                return MathF.__fname__(x);\n            //# }\n#else\n                return Log(x + Sqrt(x * x + 1));\n#endif\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic cosine of the specified number.\n        /// </summary>\n        //# fname = \"Acosh\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n            //# if (t != Meta.FloatType) {\n                return Math.__fname__(x);\n            //# } else {\n                return MathF.__fname__(x);\n            //# }\n#else\n                return Log(x + Sqrt(x * x - 1));\n#endif\n        }\n\n        /// <summary>\n        /// Returns the inverse hyperbolic tangent of the specified number.\n        /// Note that the absolute value of the argument must be smaller than 1.\n        /// </summary>\n        //# fname = \"Atanh\";\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ __fname__(this __t.Name__ x)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n            //# if (t != Meta.FloatType) {\n                return Math.__fname__(x);\n            //# } else {\n                return MathF.__fname__(x);\n            //# }\n#else\n                return __half__ * Log((1 + x) / (1 - x));\n#endif\n        }\n\n        //# });\n        #endregion\n\n        #region Step functions\n\n        //# numdectypes.ForEach(t => {\n        //# var cast = (smalltypes.Contains(t) || unsignedtypes.Contains(t)) ? \"(\" + t.Name + \")\" : \"\";\n        /// <summary>\n        /// Returns 0 if <paramref name=\"x\"/> &lt; <paramref name=\"edge\"/>, and 1 otherwise.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Step(this __t.Name__ x, __t.Name__ edge)\n            => x < edge ? __cast__0 : __cast__1;\n\n        //# if (fddectypes.Contains(t)) {\n        /// <summary>\n        /// Inverse linear interpolation, clamped to [0, 1].\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Linearstep(this __t.Name__ x, __t.Name__ edge0, __t.Name__ edge1)\n            => Saturate(InvLerp(x, edge0, edge1));\n\n        /// <summary>\n        /// Performs smooth Hermite interpolation between 0 and 1 when edge0 &lt; x &lt; edge1.\n        /// </summary>\n        [Pure]\n        public static __t.Name__ Smoothstep(this __t.Name__ x, __t.Name__ edge0, __t.Name__ edge1)\n        {\n            var t = Linearstep(x, edge0, edge1);\n            return t * t * (3 - 2 * t);\n        }\n\n        //# }\n        //# });\n        #endregion\n\n        #region Interpolation\n\n        //# numhdectypes.ForEach(t => {\n        //# if (hfddectypes.Contains(t)) {\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Lerp(this __t.Name__ t, __t.Name__ a, __t.Name__ b)\n            => a * (1 - t) + b * t;\n\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ InvLerp(this __t.Name__ y, __t.Name__ a, __t.Name__ b)\n            => (a - y) / (a - b);\n\n        //# } else {\n        //# fdtypes.ForEach(rt => {\n        //# var one = (rt != Meta.DoubleType) ? \"1.0f\" : \"1.0\";\n        /// <summary>\n        /// Linearly interpolates between a and b according to t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ Lerp(this __rt.Name__ t, __t.Name__ a, __t.Name__ b)\n            => (__t.Name__)Round(a * (1 - t) + b * t);\n\n        //# });\n        /// <summary>\n        /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double InvLerp(this __t.Name__ y, __t.Name__ a, __t.Name__ b)\n            => ((double)a - (double)y) / ((double)a - (double)b);\n\n        //# }\n        //# });\n\n        #endregion\n\n        #region Mean\n\n        //# numtypes.ForEach(t => { var st = Meta.SummationTypeOf(t);\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean(this IEnumerable<__t.Name__> array)\n        {\n            int count = 0;\n            __st.Name__ sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (double)sum / count;\n        }\n\n        //# });\n        [Pure]\n        public static decimal Mean(this IEnumerable<decimal> array)\n        {\n            int count = 0; decimal sum = 0;\n            foreach (var x in array) { sum += x; ++count; }\n            return (decimal)sum / count;\n        }\n\n        /// <summary>\n        /// Returns the mean of the given values.\n        /// </summary>\n        [Pure]\n        public static double Mean<T>(\n            this IEnumerable<T> array,\n            Func<T, double> selector\n            )\n        {\n            int count = 0; double sum = 0;\n            foreach (var x in array) { sum += selector(x); ++count; }\n            return sum / count;\n        }\n\n        #endregion\n\n        #region Variance & Standard Deviation\n\n        //# ilfdtypes.ForEach(t => { var type = t.Name;\n        //# if (Meta.UnsignedTypes.Contains(t)) return;\n        /// <summary>\n        /// Calculates the variance of given elements.\n        /// </summary>\n        [Pure]\n        public static double Variance(this IEnumerable<__type__> data)\n        {\n            int count = 0;\n            double sum = 0, mean = data.Mean();\n\n            foreach (var x in data)\n            {\n                sum += (x - mean).Square();\n                count++;\n            }\n\n            return sum / count;\n        }\n\n        /// <summary>\n        /// Calculates the standard deviation of given elements.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double StandardDeviation(this IEnumerable<__type__> data) => data.Variance().Sqrt();\n\n        //# });\n        /// <summary>\n        /// Calculates the variance of given elements.\n        /// </summary>\n        [Pure]\n        public static double Variance<T>(\n            this IEnumerable<T> data,\n            Func<T, double> selector\n            )\n        {\n            int count = 0;\n            double sum = 0, mean = data.Mean(selector);\n\n            foreach (var x in data)\n            {\n                sum += (selector(x) - mean).Square();\n                count++;\n            }\n\n            return sum / count;\n        }\n\n        /// <summary>\n        /// Calculates the standard deviation of given elements.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double StandardDeviation<T>(this IEnumerable<T> data, Func<T, double> selector)\n            => data.Variance(selector).Sqrt();\n\n        #endregion\n\n        #region CountPositives\n\n        //# signedtypes.ForEach(t => {\n        /// <summary>\n        /// Return the number of values greater than 0.\n        /// </summary>\n        [Pure]\n        public static int CountPositives(this IEnumerable<__t.Name__> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x > 0) ++count;\n            return count;\n        }\n\n        //# });\n\n        #endregion\n\n        #region CountNegatives\n\n        //# signedtypes.ForEach(t => {\n        /// <summary>\n        /// Return the number of values less than 0.\n        /// </summary>\n        [Pure]\n        public static int CountNegatives(this IEnumerable<__t.Name__> array)\n        {\n            int count = 0;\n            foreach (var x in array) if (x < 0) ++count;\n            return count;\n        }\n\n        //# });\n        #endregion\n\n        #region Primes\n\n        //# iltypes.ForEach(t => {\n        /// <summary>\n        /// Checks if the given value is a prime number.\n        /// </summary>\n        /// <param name=\"value\">The number to check.</param>\n        /// <returns><c>True</c> if the number is a prime; otherwise, <c>False</c>.</returns>\n        [Pure]\n        public static bool IsPrime(this __t.Name__ value)\n        {\n            __t.Name__ imax = (__t.Name__)Sqrt(value);\n\n            for (__t.Name__ i = 2; i <= imax; i++)\n                if (value % i == 0) return false;\n\n            return true;\n        }\n\n        //# });\n\n        #endregion\n\n        #region Swap\n\n        /// <summary>\n        /// Swaps <paramref name=\"a\"/> and <paramref name=\"b\"/>,\n        /// so that afterwards a=b and b=a.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Swap<T>(ref T a, ref T b)\n        {\n            T t = a; a = b; b = t;\n        }\n\n        /// <summary>\n        /// Rotates left <paramref name=\"a\"/>, <paramref name=\"b\"/>, and <paramref name=\"c\"/>,\n        /// so that afterwards a=b, b=c and c=a.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Rotate<T>(ref T a, ref T b, ref T c)\n        {\n            T t = a; a = b; b = c; c = t;\n        }\n\n        /// <summary>\n        /// Rotates left <paramref name=\"a\"/>, <paramref name=\"b\"/>, <paramref name=\"c\"/>, and <paramref name=\"d\"/>,\n        /// so that afterwards a=b, b=c, c=b and d=a.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Rotate<T>(ref T a, ref T b, ref T c, ref T d)\n        {\n            T t = a; a = b; b = c; c = d; d = t;\n        }\n\n        /// <summary>\n        /// Rotates left <paramref name=\"a\"/>, <paramref name=\"b\"/>, <paramref name=\"c\"/>, <paramref name=\"d\"/>, and <paramref name=\"e\"/>,\n        /// so that afterwards a=b, b=c, c=b and d=c and e=a.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Rotate<T>(ref T a, ref T b, ref T c, ref T d, ref T e)\n        {\n            T t = a; a = b; b = c; c = d; d = e; e = t;\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        //# modtypes.ForEach(t => {\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ GreatestCommonDivisor(this __t.Name__ a, __t.Name__ b)\n            => b == 0 ? a : GreatestCommonDivisor(b, a % b);\n\n        /// TODO: Handle negative inputs?\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __t.Name__ LeastCommonMultiple(this __t.Name__ a, __t.Name__ b)\n            => a * b / GreatestCommonDivisor(a, b);\n\n        //# });\n        #endregion\n\n        #region Conversion\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ToInt(this float x) => (int)x;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ToLong(this float x) => (long)x;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int ToInt(this double x) => (int)x;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long ToLong(this double x) => (long)x;\n\n        #endregion\n\n        #region Weighted Sum\n\n        //# fdtypes.ForEach(t => {\n        //# var type = t.Name;\n        [Pure]\n        public static __type__ WeightedSum(this __type__[] items, __type__[] weights)\n        {\n            __type__ r = 0;\n            var count = weights.Length;\n            for (int i = 0; i < count; i++) r += weights[i] * items[i];\n            return r;\n        }\n\n        //# });\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        //# fdtypes.ForEach(t => {\n        //# var type = t.Name;\n        //# var clsnm = (t == Meta.DoubleType) ? \"Double\" : \"Single\";\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(this __type__ v)\n            => __clsnm__.IsNaN(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(this __type__ v)\n            => __clsnm__.IsInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(this __type__ v)\n            => __clsnm__.IsNegativeInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(this __type__ v)\n            => __clsnm__.IsPositiveInfinity(v);\n\n        /// <summary>\n        /// Returns whether the given <see cref=\"__type__\"/> is finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(this __type__ v)\n        {\n#if NETCOREAPP3_1_OR_GREATER\n                return __clsnm__.IsFinite(v);\n#else\n                return !(IsNaN(v) || IsInfinity(v));\n#endif\n        }\n\n        //# });\n        #endregion\n\n        #region Signs\n\n        //# fdtypes.ForEach(t => {\n        //# var type = t.Name;\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Signs GetSigns(this __type__ value, __type__ epsilon)\n        {\n            if (value < -epsilon) return Signs.Negative;\n            if (value > +epsilon) return Signs.Positive;\n            return Signs.Zero;\n        }\n\n        public static void AggregateSigns(\n                this IEnumerable<__type__> values, __type__ epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n        {\n            int nc = 0, zc = 0, pc = 0;\n            foreach (var v in values)\n            {\n                if (v < -epsilon) { ++nc; continue; }\n                if (v > +epsilon) { ++pc; continue; }\n                ++zc;\n            }\n            negativeCount = nc;\n            zeroCount = zc;\n            positiveCount = pc;\n        }\n\n        public static void AggregateSigns(\n                this (__type__, __type__) values, __type__ epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static void AggregateSigns(\n                this (__type__, __type__, __type__) values, __type__ epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static void AggregateSigns(\n                this (__type__, __type__, __type__, __type__) values, __type__ epsilon,\n                out int negativeCount, out int zeroCount, out int positiveCount)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3, values.Item4 }, epsilon, out negativeCount, out zeroCount, out positiveCount);\n\n        public static Signs AggregateSigns(this IEnumerable<__type__> values, __type__ epsilon)\n        {\n            var signs = Signs.None;\n            foreach (var v in values)\n            {\n                if (v < -epsilon) { signs |= Signs.Negative; continue; }\n                if (v > +epsilon) { signs |= Signs.Positive; continue; }\n                signs |= Signs.Zero;\n            }\n            return signs;\n        }\n\n        public static Signs AggregateSigns(this (__type__, __type__) values, __type__ epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2 }, epsilon);\n\n        public static Signs AggregateSigns(this (__type__, __type__, __type__) values, __type__ epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3 }, epsilon);\n\n        public static Signs AggregateSigns(this (__type__, __type__, __type__, __type__) values, __type__ epsilon)\n            => AggregateSigns(new[] { values.Item1, values.Item2, values.Item3, values.Item4 }, epsilon);\n\n        //# });\n        #endregion\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Half.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\nnamespace Aardvark.Base\n{\n    // Code by Ladislav Lang: https://sourceforge.net/projects/csharp-half/\n    // Based on: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf\n\n    #region Helpers\n\n    /// <summary>\n    /// Helper class for Half conversions and some low level operations.\n    /// This class is internally used in the Half class.\n    /// </summary>\n    /// <remarks>\n    /// References:\n    ///     - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf\n    /// </remarks>\n    [ComVisible(false)]\n    internal static class HalfHelper\n    {\n        private static readonly uint[] mantissaTable = GenerateMantissaTable();\n        private static readonly uint[] exponentTable = GenerateExponentTable();\n        private static readonly ushort[] offsetTable = GenerateOffsetTable();\n        private static readonly ushort[] baseTable = GenerateBaseTable();\n        private static readonly sbyte[] shiftTable = GenerateShiftTable();\n\n        // Transforms the subnormal representation to a normalized one.\n        private static uint ConvertMantissa(int i)\n        {\n            uint m = (uint)(i << 13); // Zero pad mantissa bits\n            uint e = 0; // Zero exponent\n\n            // While not normalized\n            while ((m & 0x00800000) == 0)\n            {\n                e -= 0x00800000; // Decrement exponent (1<<23)\n                m <<= 1; // Shift mantissa\n            }\n            m &= unchecked((uint)~0x00800000); // Clear leading 1 bit\n            e += 0x38800000; // Adjust bias ((127-14)<<23)\n            return m | e; // Return combined number\n        }\n\n        private static uint[] GenerateMantissaTable()\n        {\n            uint[] mantissaTable = new uint[2048];\n            mantissaTable[0] = 0;\n            for (int i = 1; i < 1024; i++)\n            {\n                mantissaTable[i] = ConvertMantissa(i);\n            }\n            for (int i = 1024; i < 2048; i++)\n            {\n                mantissaTable[i] = (uint)(0x38000000 + ((i - 1024) << 13));\n            }\n\n            return mantissaTable;\n        }\n\n        private static uint[] GenerateExponentTable()\n        {\n            uint[] exponentTable = new uint[64];\n            exponentTable[0] = 0;\n            for (int i = 1; i < 31; i++)\n            {\n                exponentTable[i] = (uint)(i << 23);\n            }\n            exponentTable[31] = 0x47800000;\n            exponentTable[32] = 0x80000000;\n            for (int i = 33; i < 63; i++)\n            {\n                exponentTable[i] = (uint)(0x80000000 + ((i - 32) << 23));\n            }\n            exponentTable[63] = 0xc7800000;\n\n            return exponentTable;\n        }\n\n        private static ushort[] GenerateOffsetTable()\n        {\n            ushort[] offsetTable = new ushort[64];\n            offsetTable[0] = 0;\n            for (int i = 1; i < 32; i++)\n            {\n                offsetTable[i] = 1024;\n            }\n            offsetTable[32] = 0;\n            for (int i = 33; i < 64; i++)\n            {\n                offsetTable[i] = 1024;\n            }\n\n            return offsetTable;\n        }\n\n        private static ushort[] GenerateBaseTable()\n        {\n            ushort[] baseTable = new ushort[512];\n\n            for (int i = 0; i < 256; ++i)\n            {\n                int e = i - 127;\n                if (e < -24)\n                { // Very small numbers map to zero\n                    baseTable[i | 0x000] = 0x0000;\n                    baseTable[i | 0x100] = 0x8000;\n                }\n                else if (e < -14)\n                { // Small numbers map to denorms\n                    baseTable[i | 0x000] = (ushort)(0x0400 >> (-e - 14));\n                    baseTable[i | 0x100] = (ushort)((0x0400 >> (-e - 14)) | 0x8000);\n                }\n                else if (e <= 15)\n                { // Normal numbers just lose precision\n                    baseTable[i | 0x000] = (ushort)((e + 15) << 10);\n                    baseTable[i | 0x100] = (ushort)(((e + 15) << 10) | 0x8000);\n                }\n                else if (e < 128)\n                { // Large numbers map to Infinity\n                    baseTable[i | 0x000] = 0x7C00;\n                    baseTable[i | 0x100] = 0xFC00;\n                }\n                else\n                { // Infinity and NaN's stay Infinity and NaN's\n                    baseTable[i | 0x000] = 0x7C00;\n                    baseTable[i | 0x100] = 0xFC00;\n                }\n            }\n\n            return baseTable;\n\n            //ushort[] baseTable = new ushort[512];\n            //for (int i = 0; i < 256; ++i)\n            //{\n            //    sbyte e = (sbyte)(127 - i);\n            //    if (e > 24)\n            //    { // Very small numbers map to zero\n            //        baseTable[i | 0x000] = 0x0000;\n            //        baseTable[i | 0x100] = 0x8000;\n            //    }\n            //    else if (e > 14)\n            //    { // Small numbers map to denorms\n            //        baseTable[i | 0x000] = (ushort)(0x0400 >> (18 + e));\n            //        baseTable[i | 0x100] = (ushort)((0x0400 >> (18 + e)) | 0x8000);\n            //    }\n            //    else if (e >= -15)\n            //    { // Normal numbers just lose precision\n            //        baseTable[i | 0x000] = (ushort)((15 - e) << 10);\n            //        baseTable[i | 0x100] = (ushort)(((15 - e) << 10) | 0x8000);\n            //    }\n            //    else if (e > -128)\n            //    { // Large numbers map to Infinity\n            //        baseTable[i | 0x000] = 0x7c00;\n            //        baseTable[i | 0x100] = 0xfc00;\n            //    }\n            //    else\n            //    { // Infinity and NaN's stay Infinity and NaN's\n            //        baseTable[i | 0x000] = 0x7c00;\n            //        baseTable[i | 0x100] = 0xfc00;\n            //    }\n            //}\n\n            //return baseTable;\n        }\n\n        private static sbyte[] GenerateShiftTable()\n        {\n            sbyte[] shiftTable = new sbyte[512];\n\n            for (int i = 0; i < 256; ++i)\n            {\n                int e = i - 127;\n                if (e < -24)\n                { // Very small numbers map to zero\n                    shiftTable[i | 0x000] = 24;\n                    shiftTable[i | 0x100] = 24;\n                }\n                else if (e < -14)\n                { // Small numbers map to denorms\n                    shiftTable[i | 0x000] = (sbyte)(-e - 1);\n                    shiftTable[i | 0x100] = (sbyte)(-e - 1);\n                }\n                else if (e <= 15)\n                { // Normal numbers just lose precision\n                    shiftTable[i | 0x000] = 13;\n                    shiftTable[i | 0x100] = 13;\n                }\n                else if (e < 128)\n                { // Large numbers map to Infinity\n                    shiftTable[i | 0x000] = 24;\n                    shiftTable[i | 0x100] = 24;\n                }\n                else\n                { // Infinity and NaN's stay Infinity and NaN's\n                    shiftTable[i | 0x000] = 13;\n                    shiftTable[i | 0x100] = 13;\n                }\n            }\n\n            return shiftTable;\n\n            //sbyte[] shiftTable = new sbyte[512];\n            //for (int i = 0; i < 256; ++i)\n            //{\n            //    sbyte e = (sbyte)(127 - i);\n            //    if (e > 24)\n            //    { // Very small numbers map to zero\n            //        shiftTable[i | 0x000] = 24;\n            //        shiftTable[i | 0x100] = 24;\n            //    }\n            //    else if (e > 14)\n            //    { // Small numbers map to denorms\n            //        shiftTable[i | 0x000] = (sbyte)(e - 1);\n            //        shiftTable[i | 0x100] = (sbyte)(e - 1);\n            //    }\n            //    else if (e >= -15)\n            //    { // Normal numbers just lose precision\n            //        shiftTable[i | 0x000] = 13;\n            //        shiftTable[i | 0x100] = 13;\n            //    }\n            //    else if (e > -128)\n            //    { // Large numbers map to Infinity\n            //        shiftTable[i | 0x000] = 24;\n            //        shiftTable[i | 0x100] = 24;\n            //    }\n            //    else\n            //    { // Infinity and NaN's stay Infinity and NaN's\n            //        shiftTable[i | 0x000] = 13;\n            //        shiftTable[i | 0x100] = 13;\n            //    }\n            //}\n\n            //return shiftTable;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static unsafe float HalfToSingle(Half half)\n        {\n            uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];\n            return *((float*)&result);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static unsafe Half SingleToHalf(float single)\n        {\n            uint value = *((uint*)&single);\n\n            ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));\n            return Half.ToHalf(result);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Negate(Half half)\n            => Half.ToHalf((ushort)(half.value ^ 0x8000));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Abs(Half half)\n            => Half.ToHalf((ushort)(half.value & 0x7fff));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(Half half)\n            => ((half.value & 0x7fff) > 0x7c00);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(Half half)\n            => ((half.value & 0x7fff) == 0x7c00);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(Half half)\n            => (half.value == 0x7c00);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(Half half)\n           => (half.value == 0xfc00);\n    }\n\n    #endregion Helper\n\n    /// <summary>\n    /// Represents a half-precision floating point number.\n    /// </summary>\n    [Serializable]\n    public struct Half : IComparable, IFormattable, IConvertible, IComparable<Half>, IEquatable<Half>\n    {\n        /// <summary>\n        /// Internal representation of the half-precision floating-point number.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        internal ushort value;\n\n        #region Constants\n\n        /// <summary>\n        /// Represents a half value of zero.\n        /// </summary>\n        public static Half Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Half.ToHalf(0x0000);\n        }\n\n        /// <summary>\n        /// Represents a half value of one.\n        /// </summary>\n        public static Half One\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Half.ToHalf(0x3c00);\n        }\n\n        /// <summary>\n        /// Represents the smallest positive Half value greater than zero.\n        /// </summary>\n        public static Half Epsilon\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Half.ToHalf(0x0001);\n        }\n\n        /// <summary>\n        /// Represents the largest possible value of Half.\n        /// </summary>\n        public static Half MaxValue\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Half.ToHalf(0x7bff);\n        }\n\n        /// <summary>\n        /// Represents the smallest possible value of Half.\n        /// </summary>\n        public static Half MinValue\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Half.ToHalf(0xfbff);\n        }\n\n        /// <summary>\n        /// Represents not a number (NaN).\n        /// </summary>\n        public static Half NaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Half.ToHalf(0xfe00);\n        }\n\n        /// <summary>\n        /// Represents negative infinity.\n        /// </summary>\n        public static Half NegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Half.ToHalf(0xfc00);\n        }\n\n        /// <summary>\n        /// Represents positive infinity.\n        /// </summary>\n        public static Half PositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Half.ToHalf(0x7c00);\n        }\n\n        #endregion\n\n        #region Constructors\n\n        /// <summary>\n        /// Initializes a new instance of Half to the value of the specified single-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a Half.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Half(float value) { this = HalfHelper.SingleToHalf(value); }\n\n        /// <summary>\n        /// Initializes a new instance of Half to the value of the specified 32-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a Half.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Half(int value) : this((float)value) { }\n\n        /// <summary>\n        /// Initializes a new instance of Half to the value of the specified 64-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a Half.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Half(long value) : this((float)value) { }\n\n        /// <summary>\n        /// Initializes a new instance of Half to the value of the specified double-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a Half.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Half(double value) : this((float)value) { }\n\n        /// <summary>\n        /// Initializes a new instance of Half to the value of the specified decimal number.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a Half.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Half(decimal value) : this((float)value) { }\n\n        /// <summary>\n        /// Initializes a new instance of Half to the value of the specified 32-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a Half.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Half(uint value) : this((float)value) { }\n\n        /// <summary>\n        /// Initializes a new instance of Half to the value of the specified 64-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">The value to represent as a Half.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Half(ulong value) : this((float)value) { }\n\n        #endregion\n\n        #region Numeric operators\n\n        /// <summary>\n        /// Returns the result of multiplying the specified Half value by negative one.\n        /// </summary>\n        /// <param name=\"half\">A Half.</param>\n        /// <returns>A Half with the value of half, but the opposite sign. -or- Zero, if half is zero.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Negate(Half half) { return -half; }\n\n        /// <summary>\n        /// Adds two specified Half values.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>A Half value that is the sum of half1 and half2.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Add(Half half1, Half half2) { return half1 + half2; }\n\n        /// <summary>\n        /// Subtracts one specified Half value from another.\n        /// </summary>\n        /// <param name=\"half1\">A Half (the minuend).</param>\n        /// <param name=\"half2\">A Half (the subtrahend).</param>\n        /// <returns>The Half result of subtracting half2 from half1.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Subtract(Half half1, Half half2) { return half1 - half2; }\n\n        /// <summary>\n        /// Multiplies two specified Half values.\n        /// </summary>\n        /// <param name=\"half1\">A Half (the multiplicand).</param>\n        /// <param name=\"half2\">A Half (the multiplier).</param>\n        /// <returns>A Half that is the result of multiplying half1 and half2.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Multiply(Half half1, Half half2) { return half1 * half2; }\n\n        /// <summary>\n        /// Divides two specified Half values.\n        /// </summary>\n        /// <param name=\"half1\">A Half (the dividend).</param>\n        /// <param name=\"half2\">A Half (the divisor).</param>\n        /// <returns>The Half that is the result of dividing half1 by half2.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Divide(Half half1, Half half2) { return half1 / half2; }\n\n        /// <summary>\n        /// Returns the value of the Half operand (the sign of the operand is unchanged).\n        /// </summary>\n        /// <param name=\"half\">The Half operand.</param>\n        /// <returns>The value of the operand, half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half operator +(Half half) { return half; }\n\n        /// <summary>\n        /// Negates the value of the specified Half operand.\n        /// </summary>\n        /// <param name=\"half\">The Half operand.</param>\n        /// <returns>The result of half multiplied by negative one (-1).</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half operator -(Half half) { return HalfHelper.Negate(half); }\n\n        /// <summary>\n        /// Increments the Half operand by 1.\n        /// </summary>\n        /// <param name=\"half\">The Half operand.</param>\n        /// <returns>The value of half incremented by 1.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half operator ++(Half half) { return (Half)(half + 1f); }\n\n        /// <summary>\n        /// Decrements the Half operand by one.\n        /// </summary>\n        /// <param name=\"half\">The Half operand.</param>\n        /// <returns>The value of half decremented by 1.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half operator --(Half half) { return (Half)(half - 1f); }\n\n        /// <summary>\n        /// Adds two specified Half values.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>The Half result of adding half1 and half2.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half operator +(Half half1, Half half2) { return (Half)((float)half1 + (float)half2); }\n\n        /// <summary>\n        /// Subtracts two specified Half values.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>The Half result of subtracting half1 and half2.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half operator -(Half half1, Half half2) { return (Half)((float)half1 - (float)half2); }\n\n        /// <summary>\n        /// Multiplies two specified Half values.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>The Half result of multiplying half1 by half2.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half operator *(Half half1, Half half2) { return (Half)((float)half1 * (float)half2); }\n\n        /// <summary>\n        /// Divides two specified Half values.\n        /// </summary>\n        /// <param name=\"half1\">A Half (the dividend).</param>\n        /// <param name=\"half2\">A Half (the divisor).</param>\n        /// <returns>The Half result of half1 by half2.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half operator /(Half half1, Half half2) { return (Half)((float)half1 / (float)half2); }\n\n        /// <summary>\n        /// Returns a value indicating whether two instances of Half are equal.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>true if half1 and half2 are equal; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Half half1, Half half2) { return (!IsNaN(half1) && (half1.value == half2.value)); }\n\n        /// <summary>\n        /// Returns a value indicating whether two instances of Half are not equal.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>true if half1 and half2 are not equal; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Half half1, Half half2) { return !(half1.value == half2.value); }\n\n        /// <summary>\n        /// Returns a value indicating whether a specified Half is less than another specified Half.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>true if half1 is less than half1; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator <(Half half1, Half half2) { return (float)half1 < (float)half2; }\n\n        /// <summary>\n        /// Returns a value indicating whether a specified Half is greater than another specified Half.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>true if half1 is greater than half2; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator >(Half half1, Half half2) { return (float)half1 > (float)half2; }\n\n        /// <summary>\n        /// Returns a value indicating whether a specified Half is less than or equal to another specified Half.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>true if half1 is less than or equal to half2; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator <=(Half half1, Half half2) { return (half1 == half2) || (half1 < half2); }\n\n        /// <summary>\n        /// Returns a value indicating whether a specified Half is greater than or equal to another specified Half.\n        /// </summary>\n        /// <param name=\"half1\">A Half.</param>\n        /// <param name=\"half2\">A Half.</param>\n        /// <returns>true if half1 is greater than or equal to half2; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator >=(Half half1, Half half2) { return (half1 == half2) || (half1 > half2); }\n\n        #endregion\n\n        #region Type casting operators\n\n        /// <summary>\n        /// Converts an 8-bit unsigned integer to a Half.\n        /// </summary>\n        /// <param name=\"value\">An 8-bit unsigned integer.</param>\n        /// <returns>A Half that represents the converted 8-bit unsigned integer.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(byte value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a 16-bit signed integer to a Half.\n        /// </summary>\n        /// <param name=\"value\">A 16-bit signed integer.</param>\n        /// <returns>A Half that represents the converted 16-bit signed integer.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(short value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a Unicode character to a Half.\n        /// </summary>\n        /// <param name=\"value\">A Unicode character.</param>\n        /// <returns>A Half that represents the converted Unicode character.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(char value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a 32-bit signed integer to a Half.\n        /// </summary>\n        /// <param name=\"value\">A 32-bit signed integer.</param>\n        /// <returns>A Half that represents the converted 32-bit signed integer.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(int value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a 64-bit signed integer to a Half.\n        /// </summary>\n        /// <param name=\"value\">A 64-bit signed integer.</param>\n        /// <returns>A Half that represents the converted 64-bit signed integer.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(long value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a single-precision floating-point number to a Half.\n        /// </summary>\n        /// <param name=\"value\">A single-precision floating-point number.</param>\n        /// <returns>A Half that represents the converted single-precision floating point number.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Half(float value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a double-precision floating-point number to a Half.\n        /// </summary>\n        /// <param name=\"value\">A double-precision floating-point number.</param>\n        /// <returns>A Half that represents the converted double-precision floating point number.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Half(double value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a decimal number to a Half.\n        /// </summary>\n        /// <param name=\"value\">decimal number</param>\n        /// <returns>A Half that represents the converted decimal number.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Half(decimal value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a Half to an 8-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>An 8-bit unsigned integer that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte(Half value) { return (byte)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a Unicode character.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A Unicode character that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator char(Half value) { return (char)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a 16-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A 16-bit signed integer that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator short(Half value) { return (short)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a 32-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A 32-bit signed integer that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int(Half value) { return (int)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a 64-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A 64-bit signed integer that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long(Half value) { return (long)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a single-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A single-precision floating-point number that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator float(Half value) { return (float)HalfHelper.HalfToSingle(value); }\n\n        /// <summary>\n        /// Converts a Half to a double-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A double-precision floating-point number that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator double(Half value) { return (double)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a decimal number.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A decimal number that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator decimal(Half value) { return (decimal)(float)value; }\n\n        /// <summary>\n        /// Converts an 8-bit signed integer to a Half.\n        /// </summary>\n        /// <param name=\"value\">An 8-bit signed integer.</param>\n        /// <returns>A Half that represents the converted 8-bit signed integer.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(sbyte value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a 16-bit unsigned integer to a Half.\n        /// </summary>\n        /// <param name=\"value\">A 16-bit unsigned integer.</param>\n        /// <returns>A Half that represents the converted 16-bit unsigned integer.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(ushort value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a 32-bit unsigned integer to a Half.\n        /// </summary>\n        /// <param name=\"value\">A 32-bit unsigned integer.</param>\n        /// <returns>A Half that represents the converted 32-bit unsigned integer.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(uint value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a 64-bit unsigned integer to a Half.\n        /// </summary>\n        /// <param name=\"value\">A 64-bit unsigned integer.</param>\n        /// <returns>A Half that represents the converted 64-bit unsigned integer.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static implicit operator Half(ulong value) { return new Half((float)value); }\n\n        /// <summary>\n        /// Converts a Half to an 8-bit signed integer.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>An 8-bit signed integer that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator sbyte(Half value) { return (sbyte)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a 16-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A 16-bit unsigned integer that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort(Half value) { return (ushort)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a 32-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A 32-bit unsigned integer that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint(Half value) { return (uint)(float)value; }\n\n        /// <summary>\n        /// Converts a Half to a 64-bit unsigned integer.\n        /// </summary>\n        /// <param name=\"value\">A Half to convert.</param>\n        /// <returns>A 64-bit unsigned integer that represents the converted Half.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ulong(Half value) { return (ulong)(float)value; }\n\n        #endregion\n\n        #region Comparison\n\n        /// <summary>\n        /// Compares this instance to a specified Half object.\n        /// </summary>\n        /// <param name=\"other\">A Half object.</param>\n        /// <returns>\n        /// A signed number indicating the relative values of this instance and value.\n        /// Return Value Meaning Less than zero This instance is less than value. Zero\n        /// This instance is equal to value. Greater than zero This instance is greater than value.\n        /// </returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int CompareTo(Half other)\n        {\n            int result = 0;\n            if (this < other)\n            {\n                result = -1;\n            }\n            else if (this > other)\n            {\n                result = 1;\n            }\n            else if (this != other)\n            {\n                if (!IsNaN(this))\n                {\n                    result = 1;\n                }\n                else if (!IsNaN(other))\n                {\n                    result = -1;\n                }\n            }\n\n            return result;\n        }\n\n        /// <summary>\n        /// Compares this instance to a specified System.Object.\n        /// </summary>\n        /// <param name=\"obj\">An System.Object or null.</param>\n        /// <returns>\n        /// A signed number indicating the relative values of this instance and value.\n        /// Return Value Meaning Less than zero This instance is less than value. Zero\n        /// This instance is equal to value. Greater than zero This instance is greater\n        /// than value. -or- value is null.\n        /// </returns>\n        /// <exception cref=\"System.ArgumentException\">value is not a Half</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int CompareTo(object obj)\n        {\n            int result;\n            if (obj == null)\n            {\n                result = 1;\n            }\n            else\n            {\n                if (obj is Half half)\n                {\n                    result = CompareTo(half);\n                }\n                else\n                {\n                    throw new ArgumentException(\"Object must be of type Half.\");\n                }\n            }\n\n            return result;\n        }\n\n        /// <summary>\n        /// Returns a value indicating whether this instance and a specified Half object represent the same value.\n        /// </summary>\n        /// <param name=\"other\">A Half object to compare to this instance.</param>\n        /// <returns>true if value is equal to this instance; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Half other)\n        {\n            return ((other == this) || (IsNaN(other) && IsNaN(this)));\n        }\n\n        /// <summary>\n        /// Returns a value indicating whether this instance and a specified System.Object\n        /// represent the same type and value.\n        /// </summary>\n        /// <param name=\"obj\">An System.Object.</param>\n        /// <returns>true if value is a Half and equal to this instance; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly bool Equals(object obj)\n        {\n            bool result = false;\n            if (obj is Half half)\n            {\n                if ((half == this) || (IsNaN(half) && IsNaN(this)))\n                {\n                    result = true;\n                }\n            }\n\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the hash code for this instance.\n        /// </summary>\n        /// <returns>A 32-bit signed integer hash code.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly int GetHashCode()\n            => value.GetHashCode();\n\n        /// <summary>\n        /// Returns the System.TypeCode for value type Half.\n        /// </summary>\n        /// <returns>The enumerated constant (TypeCode)255.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly TypeCode GetTypeCode()\n            => (TypeCode)255;\n\n        #endregion\n\n        #region BitConverter & Math methods for Half\n\n        /// <summary>\n        /// Returns the specified half-precision floating point value as an array of bytes.\n        /// </summary>\n        /// <param name=\"value\">The number to convert.</param>\n        /// <returns>An array of bytes with length 2.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte[] GetBytes(Half value)\n            => BitConverter.GetBytes(value.value);\n\n        /// <summary>\n        /// Converts the value of a specified instance of Half to its equivalent binary representation.\n        /// </summary>\n        /// <param name=\"value\">A Half value.</param>\n        /// <returns>A 16-bit unsigned integer that contain the binary representation of value.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort GetBits(Half value)\n            => value.value;\n\n        /// <summary>\n        /// Returns a half-precision floating point number converted from two bytes\n        /// at a specified position in a byte array.\n        /// </summary>\n        /// <param name=\"value\">An array of bytes.</param>\n        /// <param name=\"startIndex\">The starting position within value.</param>\n        /// <returns>A half-precision floating point number formed by two bytes beginning at startIndex.</returns>\n        /// <exception cref=\"System.ArgumentException\">\n        /// startIndex is greater than or equal to the length of value minus 1, and is\n        /// less than or equal to the length of value minus 1.\n        /// </exception>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.ArgumentOutOfRangeException\">startIndex is less than zero or greater than the length of value minus 1.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half ToHalf(byte[] value, int startIndex)\n            => Half.ToHalf((ushort)BitConverter.ToInt16(value, startIndex));\n\n        /// <summary>\n        /// Returns a half-precision floating point number converted from its binary representation.\n        /// </summary>\n        /// <param name=\"bits\">Binary representation of Half value</param>\n        /// <returns>A half-precision floating point number formed by its binary representation.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half ToHalf(ushort bits)\n            => new Half { value = bits };\n\n        /// <summary>\n        /// Returns a value indicating the sign of a half-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">A signed number.</param>\n        /// <returns>\n        /// A number indicating the sign of value. Number Description -1 value is less\n        /// than zero. 0 value is equal to zero. 1 value is greater than zero.\n        /// </returns>\n        /// <exception cref=\"System.ArithmeticException\">value is equal to Half.NaN.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Sign(Half value)\n        {\n            if (value < 0)\n            {\n                return -1;\n            }\n            else if (value > 0)\n            {\n                return 1;\n            }\n            else\n            {\n                if (value != 0)\n                {\n                    throw new ArithmeticException(\"Function does not accept floating point Not-a-Number values.\");\n                }\n            }\n\n            return 0;\n        }\n        /// <summary>\n        /// Returns the absolute value of a half-precision floating-point number.\n        /// </summary>\n        /// <param name=\"value\">A number in the range Half.MinValue ≤ value ≤ Half.MaxValue.</param>\n        /// <returns>A half-precision floating-point number, x, such that 0 ≤ x ≤Half.MaxValue.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Abs(Half value)\n            => HalfHelper.Abs(value);\n\n        /// <summary>\n        /// Returns the larger of two half-precision floating-point numbers.\n        /// </summary>\n        /// <param name=\"value1\">The first of two half-precision floating-point numbers to compare.</param>\n        /// <param name=\"value2\">The second of two half-precision floating-point numbers to compare.</param>\n        /// <returns>\n        /// Parameter value1 or value2, whichever is larger. If value1, or value2, or both val1\n        /// and value2 are equal to Half.NaN, Half.NaN is returned.\n        /// </returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Max(Half value1, Half value2)\n            => (value1 < value2) ? value2 : value1;\n\n        /// <summary>\n        /// Returns the smaller of two half-precision floating-point numbers.\n        /// </summary>\n        /// <param name=\"value1\">The first of two half-precision floating-point numbers to compare.</param>\n        /// <param name=\"value2\">The second of two half-precision floating-point numbers to compare.</param>\n        /// <returns>\n        /// Parameter value1 or value2, whichever is smaller. If value1, or value2, or both val1\n        /// and value2 are equal to Half.NaN, Half.NaN is returned.\n        /// </returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Min(Half value1, Half value2)\n            => (value1 < value2) ? value1 : value2;\n\n        #endregion\n\n        #region Special value checks\n\n        /// <summary>\n        /// Returns a value indicating whether the specified number evaluates to not a number (Half.NaN).\n        /// </summary>\n        /// <param name=\"half\">A half-precision floating-point number.</param>\n        /// <returns>true if value evaluates to not a number (Half.NaN); otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(Half half)\n            => HalfHelper.IsNaN(half);\n\n        /// <summary>\n        /// Returns a value indicating whether the specified number evaluates to negative or positive infinity.\n        /// </summary>\n        /// <param name=\"half\">A half-precision floating-point number.</param>\n        /// <returns>true if half evaluates to Half.PositiveInfinity or Half.NegativeInfinity; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(Half half)\n            => HalfHelper.IsInfinity(half);\n\n        /// <summary>\n        /// Returns a value indicating whether the specified number evaluates to negative infinity.\n        /// </summary>\n        /// <param name=\"half\">A half-precision floating-point number.</param>\n        /// <returns>true if half evaluates to Half.NegativeInfinity; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(Half half)\n            => HalfHelper.IsNegativeInfinity(half);\n\n        /// <summary>\n        /// Returns a value indicating whether the specified number evaluates to positive infinity.\n        /// </summary>\n        /// <param name=\"half\">A half-precision floating-point number.</param>\n        /// <returns>true if half evaluates to Half.PositiveInfinity; otherwise, false.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(Half half)\n            => HalfHelper.IsPositiveInfinity(half);\n\n        #endregion\n\n        #region String operations (Parse and ToString)\n\n        /// <summary>\n        /// Converts the string representation of a number to its Half equivalent.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <returns>The Half number equivalent to the number contained in value.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.FormatException\">value is not in the correct format.</exception>\n        /// <exception cref=\"System.OverflowException\">value represents a number less than Half.MinValue or greater than Half.MaxValue.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Parse(string value)\n            => (Half)float.Parse(value, CultureInfo.InvariantCulture);\n\n        /// <summary>\n        /// Converts the string representation of a number to its Half equivalent\n        /// using the specified culture-specific format information.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"provider\">An System.IFormatProvider that supplies culture-specific parsing information about value.</param>\n        /// <returns>The Half number equivalent to the number contained in s as specified by provider.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.FormatException\">value is not in the correct format.</exception>\n        /// <exception cref=\"System.OverflowException\">value represents a number less than Half.MinValue or greater than Half.MaxValue.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Parse(string value, IFormatProvider provider)\n            =>(Half)float.Parse(value, provider);\n\n        /// <summary>\n        /// Converts the string representation of a number in a specified style to its Half equivalent.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"style\">\n        /// A bitwise combination of System.Globalization.NumberStyles values that indicates\n        /// the style elements that can be present in value. A typical value to specify is\n        /// System.Globalization.NumberStyles.Number.\n        /// </param>\n        /// <returns>The Half number equivalent to the number contained in s as specified by style.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.ArgumentException\">\n        /// style is not a System.Globalization.NumberStyles value. -or- style is the\n        /// System.Globalization.NumberStyles.AllowHexSpecifier value.\n        /// </exception>\n        /// <exception cref=\"System.FormatException\">value is not in the correct format.</exception>\n        /// <exception cref=\"System.OverflowException\">value represents a number less than Half.MinValue or greater than Half.MaxValue.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Parse(string value, NumberStyles style)\n            => (Half)float.Parse(value, style, CultureInfo.InvariantCulture);\n\n        /// <summary>\n        /// Converts the string representation of a number to its Half equivalent\n        /// using the specified style and culture-specific format.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"style\">\n        /// A bitwise combination of System.Globalization.NumberStyles values that indicates\n        /// the style elements that can be present in value. A typical value to specify is\n        /// System.Globalization.NumberStyles.Number.\n        /// </param>\n        /// <param name=\"provider\">An System.IFormatProvider object that supplies culture-specific information about the format of value.</param>\n        /// <returns>The Half number equivalent to the number contained in s as specified by style and provider.</returns>\n        /// <exception cref=\"System.ArgumentNullException\">value is null.</exception>\n        /// <exception cref=\"System.ArgumentException\">\n        /// style is not a System.Globalization.NumberStyles value. -or- style is the\n        /// System.Globalization.NumberStyles.AllowHexSpecifier value.\n        /// </exception>\n        /// <exception cref=\"System.FormatException\">value is not in the correct format.</exception>\n        /// <exception cref=\"System.OverflowException\">value represents a number less than Half.MinValue or greater than Half.MaxValue.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half Parse(string value, NumberStyles style, IFormatProvider provider)\n            => (Half)float.Parse(value, style, provider);\n\n        /// <summary>\n        /// Converts the string representation of a number to its Half equivalent.\n        /// A return value indicates whether the conversion succeeded or failed.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"result\">\n        /// When this method returns, contains the Half number that is equivalent\n        /// to the numeric value contained in value, if the conversion succeeded, or is zero\n        /// if the conversion failed. The conversion fails if the s parameter is null,\n        /// is not a number in a valid format, or represents a number less than Half.MinValue\n        /// or greater than Half.MaxValue. This parameter is passed uninitialized.\n        /// </param>\n        /// <returns>true if s was converted successfully; otherwise, false.</returns>\n        public static bool TryParse(string value, out Half result)\n        {\n            if (float.TryParse(value, out float f))\n            {\n                result = (Half)f;\n                return true;\n            }\n\n            result = new Half();\n            return false;\n        }\n\n        /// <summary>\n        /// Converts the string representation of a number to its Half equivalent\n        /// using the specified style and culture-specific format. A return value indicates\n        /// whether the conversion succeeded or failed.\n        /// </summary>\n        /// <param name=\"value\">The string representation of the number to convert.</param>\n        /// <param name=\"style\">\n        /// A bitwise combination of System.Globalization.NumberStyles values that indicates\n        /// the permitted format of value. A typical value to specify is System.Globalization.NumberStyles.Number.\n        /// </param>\n        /// <param name=\"provider\">An System.IFormatProvider object that supplies culture-specific parsing information about value.</param>\n        /// <param name=\"result\">\n        /// When this method returns, contains the Half number that is equivalent\n        /// to the numeric value contained in value, if the conversion succeeded, or is zero\n        /// if the conversion failed. The conversion fails if the s parameter is null,\n        /// is not in a format compliant with style, or represents a number less than\n        /// Half.MinValue or greater than Half.MaxValue. This parameter is passed uninitialized.\n        /// </param>\n        /// <returns>true if s was converted successfully; otherwise, false.</returns>\n        /// <exception cref=\"System.ArgumentException\">\n        /// style is not a System.Globalization.NumberStyles value. -or- style\n        /// is the System.Globalization.NumberStyles.AllowHexSpecifier value.\n        /// </exception>\n        public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out Half result)\n        {\n            bool parseResult = false;\n            if (float.TryParse(value, style, provider, out float f))\n            {\n                result = (Half)f;\n                parseResult = true;\n            }\n            else\n            {\n                result = new Half();\n            }\n\n            return parseResult;\n        }\n\n        /// <summary>\n        /// Converts the numeric value of this instance to its equivalent string representation.\n        /// </summary>\n        /// <returns>A string that represents the value of this instance.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public override readonly string ToString()\n            => ((float)this).ToString(CultureInfo.InvariantCulture);\n\n        /// <summary>\n        /// Converts the numeric value of this instance to its equivalent string representation\n        /// using the specified culture-specific format information.\n        /// </summary>\n        /// <param name=\"formatProvider\">An System.IFormatProvider that supplies culture-specific formatting information.</param>\n        /// <returns>The string representation of the value of this instance as specified by provider.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly string ToString(IFormatProvider formatProvider)\n            => ((float)this).ToString(formatProvider);\n\n        /// <summary>\n        /// Converts the numeric value of this instance to its equivalent string representation, using the specified format.\n        /// </summary>\n        /// <param name=\"format\">A numeric format string.</param>\n        /// <returns>The string representation of the value of this instance as specified by format.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly string ToString(string format)\n            => ((float)this).ToString(format, CultureInfo.InvariantCulture);\n\n        /// <summary>\n        /// Converts the numeric value of this instance to its equivalent string representation\n        /// using the specified format and culture-specific format information.\n        /// </summary>\n        /// <param name=\"format\">A numeric format string.</param>\n        /// <param name=\"formatProvider\">An System.IFormatProvider that supplies culture-specific formatting information.</param>\n        /// <returns>The string representation of the value of this instance as specified by format and provider.</returns>\n        /// <exception cref=\"System.FormatException\">format is invalid.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly string ToString(string format, IFormatProvider formatProvider)\n            => ((float)this).ToString(format, formatProvider);\n\n        #endregion\n\n        #region IConvertible Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly float IConvertible.ToSingle(IFormatProvider provider)\n            => (float)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly TypeCode IConvertible.GetTypeCode()\n            => GetTypeCode();\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly bool IConvertible.ToBoolean(IFormatProvider provider)\n            => Convert.ToBoolean((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly byte IConvertible.ToByte(IFormatProvider provider)\n            => Convert.ToByte((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly char IConvertible.ToChar(IFormatProvider provider)\n            => throw new InvalidCastException(string.Format(CultureInfo.CurrentCulture, \"Invalid cast from '{0}' to '{1}'.\", \"Half\", \"Char\"));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly DateTime IConvertible.ToDateTime(IFormatProvider provider)\n            => throw new InvalidCastException(string.Format(CultureInfo.CurrentCulture, \"Invalid cast from '{0}' to '{1}'.\", \"Half\", \"DateTime\"));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly decimal IConvertible.ToDecimal(IFormatProvider provider)\n            => Convert.ToDecimal((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly double IConvertible.ToDouble(IFormatProvider provider)\n            => Convert.ToDouble((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly short IConvertible.ToInt16(IFormatProvider provider)\n            => Convert.ToInt16((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly int IConvertible.ToInt32(IFormatProvider provider)\n            => Convert.ToInt32((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly long IConvertible.ToInt64(IFormatProvider provider)\n            => Convert.ToInt64((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly sbyte IConvertible.ToSByte(IFormatProvider provider)\n            => Convert.ToSByte((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly string IConvertible.ToString(IFormatProvider provider)\n            => Convert.ToString((float)this, CultureInfo.InvariantCulture);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly object IConvertible.ToType(Type conversionType, IFormatProvider provider)\n            => (((float)this) as IConvertible).ToType(conversionType, provider);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly ushort IConvertible.ToUInt16(IFormatProvider provider)\n            => Convert.ToUInt16((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly uint IConvertible.ToUInt32(IFormatProvider provider)\n            => Convert.ToUInt32((float)this);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        readonly ulong IConvertible.ToUInt64(IFormatProvider provider)\n            => Convert.ToUInt64((float)this);\n\n        #endregion\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/MedianWindow.cs",
    "content": "﻿using Aardvark.Base.Sorting;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Represents a moving median window of a sequence.\n    /// It builds the median of the last N inserted values.\n    /// </summary>\n    public class MedianWindow\n    {\n        double m_median = 0;\n        int m_write = -1;\n        int m_count = 0; // for case when buffer is not fully filled\n        readonly double[] m_buffer;\n        readonly int[] m_indices;\n\n        public MedianWindow(int count)\n        {\n            m_buffer = new double[count];\n            m_indices = new int[count].SetByIndex(i => i);\n        }\n\n        public double Insert(double value)\n        {\n            if (m_count < m_buffer.Length)\n                m_count++;\n\n            if (m_write > m_buffer.Length - 2)\n                m_write = 0;\n            else\n                m_write++;\n\n            m_buffer[m_write] = value;\n\n            // NOTE: indices are still sorted from last insert\n            m_indices.PermutationQuickSortAscending(m_buffer, 0, m_count);\n            m_median = m_buffer[m_indices[m_count >> 1]];\n\n            return m_median;\n        }\n\n        /// <summary>\n        /// Returns the history buffer. Contains zeroes if less elements than the window size have been inserted.\n        /// </summary>\n        public IReadOnlyList<double> History { get { return m_buffer; } }\n\n        public double Value { get { return m_median; } }\n\n        /// <summary>\n        /// Returns the last inserted valued.\n        /// In case no value has been inserted yet, 0 is returned.\n        /// </summary>\n        public double Last\n        {\n            get\n            {\n                // in the case that last is queried before any insert return 0\n                if (m_write >= m_count)\n                    return 0;\n\n                return m_buffer[m_write];\n            }\n        }\n\n        /// <summary>\n        /// Resets the median window.\n        /// </summary>\n        public void Reset()\n        {\n            m_median = 0;\n            m_write = -1;\n            m_count = 0;\n            m_indices.SetByIndex(i => i);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/PhysicsConsts.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class PhysicsConstant\n    {\n        /// <summary>\n        /// Age of universe in years.\n        /// </summary>\n        public const double AgeOfUniverse = 13.73e9;\n        public const double AgeOfUniverseRelativeStandardUncertainty = 8.8e-3;\n\n        /// <summary>\n        /// Angular velocity of the earth in radians/s.\n        /// </summary>\n        public const double AngularVelocityOfEarth = 7.2921159e-5;\n\n        /// <summary>\n        /// Astronomical unit in m.\n        /// </summary>\n        public const double AstronomicalUnit = 1.4959787066e11;\n        public const double AstronomicalUnitRelativeStandardUncertainty = 2.0e-11;\n\n        /// <summary>\n        /// Astronomical unit in m.\n        /// </summary>\n        public const double au = AstronomicalUnit;\n\n        /// <summary>\n        /// Atomic mass unit in kg.\n        /// </summary>\n        public const double AtomicMassUnit = 1.66053886e-27;\n        public const double AtomicMassUnitRelativeStandardUncertainty = 1.7e-7;\n\n        /// <summary>\n        /// Avogadro constant in mol^-1.\n        /// </summary>\n        public const double AvogadroConstant = 6.0221415e23;\n        public const double AvogadroConstantRelativeStandardUncertainty = 1.7e-7;\n\n        /// <summary>\n        /// Bohr magneton in J/T.\n        /// </summary>\n        public const double BohrMagneton = 927.400915e-26;\n        public const double BohrMagnetonRelativeStandardUncertainty = 2.5e-8;\n\n        /// <summary>\n        /// Bohr radius in m.\n        /// </summary>\n        public const double BohrRadius = 5.291772108e-11;\n        public const double BohrRadiusRelativeStandardUncertainty = 3.3e-9;\n\n        /// <summary>\n        /// Boltzmann constant k in J/K.\n        /// </summary>\n        public const double BoltzmannConstant = 1.3806504e-23;\n        public const double BoltzmannConstantRelativeStandardUncertainty = 1.8e-6;\n\n        /// <summary>\n        /// Boltzmann constant k in J/K.\n        /// </summary>\n        public const double k = BoltzmannConstant;\n\n        /// <summary>\n        /// Classical electron radius r_e in m.\n        /// </summary>\n        public const double ClassicalElectronRadius = 2.8179402894e-15;\n        public const double ClassicalElectronRadiusRelativeStandardUncertainty = 2.1e-9;\n\n        /// <summary>\n        /// Conductance quantum in S.\n        /// </summary>\n        public const double ConductanceQuantum = 7.7480917004e-5;\n        public const double ConductanceQuantumRelativeStandardUncertainty = 6.8e-10;\n\n        /// <summary>\n        /// Coulomb's constant in N * m^2 * C^-2. This is a defined value\n        /// with no uncertainty.\n        /// </summary>\n        public const double CoulombsConstant = 1.0 / (4.0 * Constant.Pi * epsilon0);\n\n        /// <summary>\n        /// Earth mass in kg.\n        /// </summary>\n        public const double EarthMass = 5.9737076e24;\n\n        /// <summary>\n        /// Earth equatorial radius in m.\n        /// </summary>\n        public const double EarthRadiusEquatorial = 6.378140e6;\n\n        /// <summary>\n        /// Electron rest mass in kg.\n        /// </summary>\n        public const double ElectronRestMass = 9.10938215e-31;\n        public const double ElectronRestMassRelativeStandardUncertainty = 5.0e-8;\n\n        /// <summary>\n        /// Elementary charge e in coulomb.\n        /// </summary>\n        public const double ElementaryCharge = 1.602176487e-19;\n        public const double ElementaryChargeRelativeStandardUncertainty = 2.5e-8;\n\n        /// <summary>\n        /// Faraday constant in C/mol.\n        /// </summary>\n        public const double FaradayConstant = 96485.3383;\n        public const double FaradayConstantRelativeStandardUncertainty = 8.6e-8;\n\n        /// <summary>\n        /// Fine structure constant (dimensionless).\n        /// </summary>\n        public const double FineStructureConstant = 7.2973525376e-3;\n        public const double FineStructureConstantRelativeStandardUncertainty = 6.8e-10;\n\n        /// <summary>\n        ///  Newtonian constant of gravitation G in m^3/(kg s^2).\n        /// </summary>\n        public const double GravitationalConstant = 6.67428e-11;\n        public const double GravitationalConstantRelativeStandardUncertainty = 1e-4;\n\n        /// <summary>\n        ///  Newtonian constant of gravitation G in m^3/(kg s^2).\n        /// </summary>\n        public const double G = GravitationalConstant;\n\n        /// <summary>\n        /// Ideal (molar) gas constant in J/(kg*mol).\n        /// </summary>\n        public const double IdealGasConstant = 8.314472;\n        public const double IdealGasConstantRelativeStandardUncertainty = 1.7e-6;\n\n        /// <summary>\n        /// Neutron rest mass in kg.\n        /// </summary>\n        public const double NeutronRestMass = 1.6749286e-27;\n\n        /// <summary>\n        /// Planck constant h in Js.\n        /// </summary>\n        public const double PlanckConstant = 6.62606896e-34;\n        public const double PlanckConstantRelativeStandardUncertainty = 5e-8;\n        public const double ReducedPlanckConstant = PlanckConstant / Constant.PiTimesTwo;\n\n        /// <summary>\n        /// Planck constant h in Js.\n        /// </summary>\n        public const double h = PlanckConstant;\n\n        /// <summary>\n        /// Planck mass in kg.\n        /// </summary>\n        public const double PlanckMass = 2.17644e-8;\n        public const double PlanckMassRelativeStandardUncertainty = 5.0e-5;\n\n        /// <summary>\n        /// Proton rest mass in kg.\n        /// </summary>\n        public const double ProtonRestMass = 1.672621637e-27;\n        public const double ProtonRestMassRelativeStandardUncertainty = 5.0e-8;\n\n        /// <summary>\n        /// Rydberg constat in m^-1.\n        /// </summary>\n        public const double RydbergConstant = 10973731.568525;\n        public const double RydbergConstantRelativeStandardUncertainty = 6.6e-12;\n\n        /// <summary>\n        /// Rydberg energy in eV.\n        /// </summary>\n        public const double RydbergEnergy = 13.605698140;\n\n        /// <summary>\n        /// Specific gas constant of dry air in J/(kg*K).\n        /// </summary>\n        public const double SpecificGasConstantOfDryAir = 287.05;\n\n        /// <summary>\n        /// Velocity of light in vacuum c in m/s. This is a defined value\n        /// with no uncertainty.\n        /// </summary>\n        public const double SpeedOfLight = 299792458;\n\n        /// <summary>\n        /// Velocity of light in vacuum c in m/s. This is a defined value\n        /// with no uncertainty.\n        /// </summary>\n        public const double c = SpeedOfLight;\n\n        /// <summary>\n        /// Standard acceleration of gravity g in m/s^2. This is a defined\n        /// value with no uncertainty.\n        /// </summary>\n        public const double StandardAccelerationOfGravity = 9.80665;\n\n        /// <summary>\n        /// Standard acceleration of gravity g in m/s^2. This is a defined\n        /// value with no uncertainty.\n        /// </summary>\n        public const double g = StandardAccelerationOfGravity;\n\n        /// <summary>\n        /// Standard atmosphere in Pa. This is a defined value with no\n        /// uncertainty.\n        /// </summary>\n        public const double StandardAtmosphere = 101325;\n\n        /// <summary>\n        /// Standard atmosphere in Pa. This is a defined value with no\n        /// uncertainty.\n        /// </summary>\n        public const double atm = StandardAtmosphere;\n\n        /// <summary>\n        /// Tropospheric temperature lapse rate in K/m.\n        /// Source: http://www.iupac.org/goldbook/T06266.pdf\n        /// </summary>\n        public const double TroposphericTemperatureLapseRate = 0.0065;\n\n        /// <summary>\n        /// The characteristic impedance of vacuum in Ohm. This is a\n        /// defined value with no uncertainty.\n        /// </summary>\n        public const double VacuumImpedance = my0 * c;\n\n        /// <summary>\n        /// The characteristic impedance of vacuum in Ohm. This is a\n        /// defined value with no uncertainty.\n        /// </summary>\n        public const double Z0 = VacuumImpedance;\n\n        /// <summary>\n        /// Vacuum Permittivity in (A^2 s^4)/(kg m^3). This is a defined\n        /// value with no uncertainty.\n        /// </summary>\n        public const double VacuumPermittivity = 1.0 / (my0 * c * c);\n\n        /// <summary>\n        /// Vacuum Permittivity in (A^2 s^4)/(kg m^3). This is a defined\n        /// value with no uncertainty.\n        /// </summary>\n        public const double epsilon0 = VacuumPermittivity;\n\n        /// <summary>\n        /// Vacuum Permeability in N/A^2. This is a defined value with no\n        /// uncertainty.\n        /// </summary>\n        public const double VacuumPermeability = 4.0E-7 * Constant.Pi;\n\n        /// <summary>\n        /// Vacuum Permeability in N/A^2. This is a defined value with no\n        /// uncertainty.\n        /// </summary>\n        public const double my0 = VacuumPermeability;\n\n        /// <summary>\n        /// Molar mass of dry air in kg/mol.\n        /// Source: http://en.wikipedia.org/wiki/Density_of_air\n        /// </summary>\n        public const double MolarMassOfDryAir = 0.0289644;\n\n        /// <summary>\n        /// Day, mean sidereal.\n        /// </summary>\n        public static readonly TimeSpan DayMeanSidereal = new TimeSpan(0, 23, 56, 4, 090);\n\n        /// <summary>\n        /// Light year in m.\n        /// </summary>\n        public const double LightYear = 9460730472580800.0;\n\n        /// <summary>\n        /// Parsec (au/arcsec) in m.\n        /// </summary>\n        public const double Parsec = 3.08567758074e16;\n\n        /// <summary>\n        /// Parsec (au/arcsec) in m.\n        /// </summary>\n        public const double pc = Parsec;\n\n        /// <summary>\n        /// Schwarzschild radius of Sun in m.\n        /// </summary>\n        public const double SchwarzschildRadiusOfSun = 2953.25008;\n\n        /// <summary>\n        /// Strong coupling constant.\n        /// </summary>\n        public const double StrongCouplingConstant = 0.1183;\n\n        /// <summary>\n        /// Sun distance from Core in m.\n        /// </summary>\n        public const double SunDistanceFromCore = 8.05 * Parsec;\n\n        /// <summary>\n        /// Sun luminosity in W.\n        /// </summary>\n        public const double SunLuminosity = 3.846e26;\n\n        /// <summary>\n        /// Sun mass in kg.\n        /// </summary>\n        public const double SunMass = 1.9889225e30;\n\n        /// <summary>\n        /// Sun radius (equatorial) in m.\n        /// </summary>\n        public const double SunRadiusEquatorial = 6.96e8;\n\n        /// <summary>\n        /// Sun speed around Core in m/s.\n        /// </summary>\n        public const double SunSpeedAroundCore = 22020000;\n\n        /// <summary>\n        /// Sun speed to cosmic background in m/s.\n        /// </summary>\n        public const double SunSpeedToCosmicBackground = 369500;\n\n        /// <summary>\n        /// Year, sideral (fixed star to fixed star, 1994) in s.\n        /// </summary>\n        public const double YearSideral = 31558149.8;\n\n        /// <summary>\n        /// Year, tropical (equinox to equinox, 1994) in s.\n        /// </summary>\n        public const double YearTropical = 31556925.2;\n\n        /// <summary>\n        /// Angstrom in m.\n        /// </summary>\n        public const double Angstrom = 10e-10;\n\n        /// <summary>\n        /// Electronvolt eV in J.\n        /// </summary>\n        public const double ElectronvoltInJoule = 1.60217733e-19;\n\n        /// <summary>\n        /// Nautical mile in m.\n        /// </summary>\n        public const double NauticalMile = 1852;\n\n        /// <summary>\n        /// Minute in seconds.\n        /// </summary>\n        public const double Minute = 60;\n\n        /// <summary>\n        /// Hour in seconds.\n        /// </summary>\n        public const double Hour = 60 * Minute;\n\n        /// <summary>\n        /// Day in seconds.\n        /// </summary>\n        public const double Day = 24 * Hour;\n\n        /// <summary>\n        /// Knot (1 nautical mile per hour) in m/s.\n        /// </summary>\n        public const double Knot = NauticalMile / Hour;\n\n        /// <summary>\n        /// Are in m^2.\n        /// </summary>\n        public const double Are = 100;\n\n        /// <summary>\n        /// Hectare in m^2.\n        /// </summary>\n        public const double Hectare = 10000;\n\n        /// <summary>\n        /// Barn in m^2.\n        /// </summary>\n        public const double Barn = 1e-28;\n\n        /// <summary>\n        /// Bar in Pa.\n        /// </summary>\n        public const double Bar = 10e5;\n\n        /// <summary>\n        /// Gal in m/s^2.\n        /// </summary>\n        public const double Gal = 10e-2;\n\n        /// <summary>\n        /// Curie Ci in Bq.\n        /// </summary>\n        public const double Curie = 3.7e10;\n\n        /// <summary>\n        /// Roentgen R in C/kg.\n        /// </summary>\n        public const double Roentgen = 2.58e-4;\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Quaternion_auto.cs",
    "content": "using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    #region QuaternionF\n\n    /// <summary>\n    /// Struct for general quaternions, for rotations in 3-dimensional space use <see cref=\"Rot3f\"/>.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct QuaternionF : IEquatable<QuaternionF>\n    {\n        /// <summary>\n        /// Scalar (real) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public float W;\n\n        /// <summary>\n        /// First component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public float X;\n\n        /// <summary>\n        /// Second component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public float Y;\n\n        /// <summary>\n        /// Third component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public float Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> (a, (a, a, a)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(float a)\n        {\n            W = a;\n            X = a; Y = a; Z = a;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> (w, (x, y, z)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(float w, float x, float y, float z)\n        {\n            W = w;\n            X = x; Y = y; Z = z;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> (v.x, (v.y, v.z, v.w)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(V4f v)\n        {\n            W = v.X;\n            X = v.Y; Y = v.Z; Z = v.W;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> (w, (v.x, v.y, v.z)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(float w, V3f v)\n        {\n            W = w;\n            X = v.X; Y = v.Y; Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a copy of the given <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(QuaternionF q)\n        {\n            W = q.W; X = q.X; Y = q.Y; Z = q.Z; \n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> from the given <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(QuaternionD q)\n        {\n            W = (float)q.W; X = (float)q.X; Y = (float)q.Y; Z = (float)q.Z; \n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> from the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(Rot3f r)\n        {\n            W = r.W; X = r.X; Y = r.Y; Z = r.Z; \n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> from the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(Rot3d r)\n        {\n            W = (float)r.W; X = (float)r.X; Y = (float)r.Y; Z = (float)r.Z; \n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> from an array.\n        /// (w = a[0], (x = a[1], y = a[2], z = a[3])).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(float[] a)\n        {\n            W = a[0];\n            X = a[1]; Y = a[2]; Z = a[3];\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionF\"/> from an array starting at specified index.\n        /// (w = a[start], (x = a[start+1], y = a[start+2], z = a[start+3])).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionF(float[] a, int start)\n        {\n            W = a[start];\n            X = a[start + 1]; Y = a[start + 2]; Z = a[start + 3];\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets or sets the vector part (x, y, z) of this <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [XmlIgnore]\n        public V3f V\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f(X, Y, Z); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n\n        /// <summary>\n        /// Gets the squared norm (or squared length) of this <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        public readonly float NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => W * W + X * X + Y * Y + Z * Z;\n        }\n\n        /// <summary>\n        /// Gets the norm (or length) of this <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        public readonly float Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => NormSquared.Sqrt();\n        }\n\n        /// <summary>\n        /// Gets normalized (unit) quaternion from this <see cref=\"QuaternionF\"/>\n        /// </summary>\n        public readonly QuaternionF Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new QuaternionF(this);\n                rs.Normalize();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this <see cref=\"QuaternionF\"/>.\n        /// The zero quaternion is returned, if this quaternion is zero.\n        /// </summary>\n        public readonly QuaternionF Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new QuaternionF(this);\n                rs.Invert();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the conjugate of this <see cref=\"QuaternionF\"/>.\n        /// For unit quaternions this is the same as its inverse.\n        /// </summary>\n        public readonly QuaternionF Conjugated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionF(W, -V);\n        }\n\n        /// <summary>\n        /// Gets if this <see cref=\"QuaternionF\"/> is zero.\n        /// </summary>\n        public readonly bool IsZero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (W == 0) && (X == 0) && (Y == 0) && (Z == 0);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionF\"/> with (0, (0, 0, 0)).\n        /// </summary>\n        public static QuaternionF Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionF(0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionF\"/> with (1, (0, 0, 0)).\n        /// </summary>\n        public static QuaternionF One\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionF(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets the identity <see cref=\"QuaternionF\"/> with (1, (0, 0, 0)).\n        /// </summary>\n        public static QuaternionF Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionF(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionF\"/> with (0, (1, 0, 0)).\n        /// </summary>\n        public static QuaternionF I\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionF(0, 1, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionF\"/> with (0, (0, 1, 0)).\n        /// </summary>\n        public static QuaternionF J\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionF(0, 0, 1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionF\"/> with (0, (0, 0, 1)).\n        /// </summary>\n        public static QuaternionF K\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionF(0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Returns the component-wise negation of a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator -(QuaternionF q)\n            => new QuaternionF(-q.W, -q.X, -q.Y, -q.Z);\n\n        /// <summary>\n        /// Returns the sum of two <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator +(QuaternionF a, QuaternionF b)\n            => new QuaternionF(a.W + b.W, a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"QuaternionF\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator +(QuaternionF q, float s)\n            => new QuaternionF(q.W + s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the sum of a real scalar and a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator +(float s, QuaternionF q)\n            => new QuaternionF(q.W + s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the difference between two <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator -(QuaternionF a, QuaternionF b)\n            => new QuaternionF(a.W - b.W, a.X - b.X, a.Y - b.Y, a.Z - b.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"QuaternionF\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator -(QuaternionF q, float s)\n            => new QuaternionF(q.W - s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the difference between a real scalar and a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator -(float s, QuaternionF q)\n            => new QuaternionF(s - q.W, -q.X, -q.Y, -q.Z);\n\n        /// <summary>\n        /// Returns the product of a <see cref=\"QuaternionF\"/> and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator *(QuaternionF q, float s)\n            => new QuaternionF(q.W * s, q.X * s, q.Y * s, q.Z * s);\n\n        /// <summary>\n        /// Returns the product of a scalar and a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator *(float s, QuaternionF q)\n            => new QuaternionF(q.W * s, q.X * s, q.Y * s, q.Z * s);\n\n        /// <summary>\n        /// Multiplies two <see cref=\"QuaternionF\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator *(QuaternionF a, QuaternionF b)\n        {\n            return new QuaternionF(\n                a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z,\n                a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,\n                a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,\n                a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X);\n        }\n\n        /// <summary>\n        /// Divides two <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator /(QuaternionF a, QuaternionF b)\n            => a * b.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"QuaternionF\"/> by a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator /(QuaternionF q, float s)\n            => new QuaternionF(q.W / s, q.X / s, q.Y / s, q.Z / s);\n\n        /// <summary>\n        /// Divides a scalar by a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator /(float s, QuaternionF q)\n            => new QuaternionF(s / q.W, s / q.X, s / q.Y, s / q.Z);\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"QuaternionF\"/> are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(QuaternionF q0, QuaternionF q1)\n            => q0.W == q1.W && q0.X == q1.X && q0.Y == q1.Y && q0.Z == q1.Z;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"QuaternionF\"/> are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(QuaternionF q0, QuaternionF q1)\n            => q0.W != q1.W || q0.X != q1.X || q0.Y != q1.Y || q0.Z != q1.Z;\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Conversion from a <see cref=\"QuaternionF\"/> to a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator QuaternionD(QuaternionF q)\n            => new QuaternionD(q);\n\n        /// <summary>\n        /// Returns this <see cref=\"QuaternionF\"/> as a 4x4 matrix. Quaternions are represented as matrices in such\n        /// a way that quaternion multiplication and addition is equivalent to matrix multiplication and addition.\n        /// Note that there are 48 distinct such matrix representations for a single quaternion.\n        /// </summary>\n        [Obsolete(\"Misleading conversion. Do you want a Rot3f to M44f conversion instead?\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(QuaternionF q)\n        {\n            return new M44f(\n                q.W, -q.X, -q.Y, -q.Z,\n                q.X,  q.W, -q.Z,  q.Y,\n                q.Y,  q.Z,  q.W, -q.X,\n                q.Z, -q.Y,  q.X,  q.W);\n        }\n\n        /// <summary>\n        /// Returns this <see cref=\"QuaternionF\"/> as a <see cref=\"V4f\"/> vector.\n        /// Note that the components are ordered (w, x, y, z).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(QuaternionF q)\n            => new V4f(q.W, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"QuaternionF\"/> instance\n        /// in a float[] array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](QuaternionF q)\n        {\n            float[] array = new float[4];\n            array[0] = q.W;\n            array[1] = q.X;\n            array[2] = q.Y;\n            array[3] = q.Z;\n            return array;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets or sets the <paramref name=\"i\"/>-th component of the <see cref=\"QuaternionF\"/> with components (w, (x, y, z)).\n        /// </summary>\n        public unsafe float this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &W) { return ptr[i]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &W) { ptr[i] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(W, X, Y, Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(QuaternionF other)\n            => W.Equals(other.W) && X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n\n        public override readonly bool Equals(object other)\n            => (other is QuaternionF o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", W, X, Y, Z);\n        }\n\n        public static QuaternionF Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new QuaternionF(float.Parse(x[0], CultureInfo.InvariantCulture), float.Parse(x[1], CultureInfo.InvariantCulture), float.Parse(x[2], CultureInfo.InvariantCulture), float.Parse(x[3], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n    }\n\n    public static partial class Quaternion\n    {\n        #region Invert, Normalize, Conjugate, Dot\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF Inverse(QuaternionF q)\n            => q.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref QuaternionF q)\n        {\n            var norm = q.NormSquared;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                q.W *= scale;\n                q.X *= -scale;\n                q.Y *= -scale;\n                q.Z *= -scale;\n            }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF Normalized(QuaternionF q)\n            => q.Normalized;\n\n        /// <summary>\n        /// Normalizes a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref QuaternionF q)\n        {\n            var norm = q.Norm;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                q.W *= scale;\n                q.X *= scale;\n                q.Y *= scale;\n                q.Z *= scale;\n            }\n        }\n\n        /// <summary>\n        /// Returns the conjugate of a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF Conjugated(QuaternionF q)\n            => q.Conjugated;\n\n        /// <summary>\n        /// Conjugates a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Conjugate(this ref QuaternionF q)\n        {\n            q.X = -q.X;\n            q.Y = -q.Y;\n            q.Z = -q.Z;\n        }\n\n        /// <summary>\n        /// Returns the dot product of two <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Dot(this QuaternionF a, QuaternionF b)\n        {\n            return a.W * b.W + a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        #endregion\n\n        #region Norm\n\n        /// <summary>\n        /// Gets the squared norm (or length) of a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormSquared(QuaternionF q)\n            => q.NormSquared;\n\n        /// <summary>\n        /// Gets the norm (or length) of a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(QuaternionF q)\n            => q.Norm;\n\n        #endregion\n\n        #region Spherical Linear Interpolation\n\n        /// <summary>\n        /// Spherical linear interpolation.\n        ///\n        /// Assumes q1 and q2 are normalized and that t in [0,1].\n        ///\n        /// This method interpolates along the shortest arc between q1 and q2.\n        /// </summary>\n        public static QuaternionF SlerpShortest(this QuaternionF q1, QuaternionF q2, float t)\n        {\n            QuaternionF q3 = q2;\n            float cosomega = Dot(q1, q3);\n\n            if (cosomega < 0)\n            {\n                cosomega = -cosomega;\n                q3 = -q3;\n            }\n\n            if (cosomega >= 1)\n            {\n                // Special case: q1 and q2 are the same, so just return one of them.\n                // This also catches the case where cosomega is very slightly > 1.0\n                return q1;\n            }\n\n            float sinomega = Fun.Sqrt(1 - cosomega * cosomega);\n\n            QuaternionF result;\n\n            if (sinomega * float.MaxValue > 1)\n            {\n                float omega = Fun.Acos(cosomega);\n                float s1 = Fun.Sin((1 - t) * omega) / sinomega;\n                float s2 = Fun.Sin(t * omega) / sinomega;\n\n                result = new QuaternionF(s1 * q1 + s2 * q3);\n            }\n            else if (cosomega > 0)\n            {\n                // omega == 0\n                float s1 = 1 - t;\n                float s2 = t;\n\n                result = new QuaternionF(s1 * q1 + s2 * q3);\n            }\n            else\n            {\n                // omega == -pi\n                result = new QuaternionF(q1.Z, -q1.Y, q1.X, -q1.W);\n\n                float s1 = Fun.Sin((0.5f - t) * ConstantF.Pi);\n                float s2 = Fun.Sin(t * ConstantF.Pi);\n\n                result = new QuaternionF(s1 * q1 + s2 * result);\n            }\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this QuaternionF q0, QuaternionF q1)\n        {\n            return ApproximateEquals(q0, q1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this QuaternionF q0, QuaternionF q1, float tolerance)\n        {\n            return ApproximateEquals(q0.W, q1.W, tolerance) && ApproximateEquals(q0.X, q1.X, tolerance) && ApproximateEquals(q0.Y, q1.Y, tolerance) && ApproximateEquals(q0.Z, q1.Z, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region QuaternionD\n\n    /// <summary>\n    /// Struct for general quaternions, for rotations in 3-dimensional space use <see cref=\"Rot3d\"/>.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct QuaternionD : IEquatable<QuaternionD>\n    {\n        /// <summary>\n        /// Scalar (real) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public double W;\n\n        /// <summary>\n        /// First component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public double X;\n\n        /// <summary>\n        /// Second component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public double Y;\n\n        /// <summary>\n        /// Third component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public double Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> (a, (a, a, a)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(double a)\n        {\n            W = a;\n            X = a; Y = a; Z = a;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> (w, (x, y, z)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(double w, double x, double y, double z)\n        {\n            W = w;\n            X = x; Y = y; Z = z;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> (v.x, (v.y, v.z, v.w)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(V4d v)\n        {\n            W = v.X;\n            X = v.Y; Y = v.Z; Z = v.W;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> (w, (v.x, v.y, v.z)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(double w, V3d v)\n        {\n            W = w;\n            X = v.X; Y = v.Y; Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a copy of the given <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(QuaternionD q)\n        {\n            W = q.W; X = q.X; Y = q.Y; Z = q.Z; \n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> from the given <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(QuaternionF q)\n        {\n            W = (double)q.W; X = (double)q.X; Y = (double)q.Y; Z = (double)q.Z; \n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> from the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(Rot3d r)\n        {\n            W = r.W; X = r.X; Y = r.Y; Z = r.Z; \n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> from the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(Rot3f r)\n        {\n            W = (double)r.W; X = (double)r.X; Y = (double)r.Y; Z = (double)r.Z; \n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> from an array.\n        /// (w = a[0], (x = a[1], y = a[2], z = a[3])).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(double[] a)\n        {\n            W = a[0];\n            X = a[1]; Y = a[2]; Z = a[3];\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"QuaternionD\"/> from an array starting at specified index.\n        /// (w = a[start], (x = a[start+1], y = a[start+2], z = a[start+3])).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public QuaternionD(double[] a, int start)\n        {\n            W = a[start];\n            X = a[start + 1]; Y = a[start + 2]; Z = a[start + 3];\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets or sets the vector part (x, y, z) of this <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [XmlIgnore]\n        public V3d V\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d(X, Y, Z); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n\n        /// <summary>\n        /// Gets the squared norm (or squared length) of this <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        public readonly double NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => W * W + X * X + Y * Y + Z * Z;\n        }\n\n        /// <summary>\n        /// Gets the norm (or length) of this <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        public readonly double Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => NormSquared.Sqrt();\n        }\n\n        /// <summary>\n        /// Gets normalized (unit) quaternion from this <see cref=\"QuaternionD\"/>\n        /// </summary>\n        public readonly QuaternionD Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new QuaternionD(this);\n                rs.Normalize();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this <see cref=\"QuaternionD\"/>.\n        /// The zero quaternion is returned, if this quaternion is zero.\n        /// </summary>\n        public readonly QuaternionD Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new QuaternionD(this);\n                rs.Invert();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the conjugate of this <see cref=\"QuaternionD\"/>.\n        /// For unit quaternions this is the same as its inverse.\n        /// </summary>\n        public readonly QuaternionD Conjugated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionD(W, -V);\n        }\n\n        /// <summary>\n        /// Gets if this <see cref=\"QuaternionD\"/> is zero.\n        /// </summary>\n        public readonly bool IsZero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => (W == 0) && (X == 0) && (Y == 0) && (Z == 0);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionD\"/> with (0, (0, 0, 0)).\n        /// </summary>\n        public static QuaternionD Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionD(0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionD\"/> with (1, (0, 0, 0)).\n        /// </summary>\n        public static QuaternionD One\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionD(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets the identity <see cref=\"QuaternionD\"/> with (1, (0, 0, 0)).\n        /// </summary>\n        public static QuaternionD Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionD(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionD\"/> with (0, (1, 0, 0)).\n        /// </summary>\n        public static QuaternionD I\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionD(0, 1, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionD\"/> with (0, (0, 1, 0)).\n        /// </summary>\n        public static QuaternionD J\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionD(0, 0, 1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"QuaternionD\"/> with (0, (0, 0, 1)).\n        /// </summary>\n        public static QuaternionD K\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new QuaternionD(0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Returns the component-wise negation of a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator -(QuaternionD q)\n            => new QuaternionD(-q.W, -q.X, -q.Y, -q.Z);\n\n        /// <summary>\n        /// Returns the sum of two <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator +(QuaternionD a, QuaternionD b)\n            => new QuaternionD(a.W + b.W, a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"QuaternionD\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator +(QuaternionD q, double s)\n            => new QuaternionD(q.W + s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the sum of a real scalar and a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator +(double s, QuaternionD q)\n            => new QuaternionD(q.W + s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the difference between two <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator -(QuaternionD a, QuaternionD b)\n            => new QuaternionD(a.W - b.W, a.X - b.X, a.Y - b.Y, a.Z - b.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"QuaternionD\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator -(QuaternionD q, double s)\n            => new QuaternionD(q.W - s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the difference between a real scalar and a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator -(double s, QuaternionD q)\n            => new QuaternionD(s - q.W, -q.X, -q.Y, -q.Z);\n\n        /// <summary>\n        /// Returns the product of a <see cref=\"QuaternionD\"/> and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator *(QuaternionD q, double s)\n            => new QuaternionD(q.W * s, q.X * s, q.Y * s, q.Z * s);\n\n        /// <summary>\n        /// Returns the product of a scalar and a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator *(double s, QuaternionD q)\n            => new QuaternionD(q.W * s, q.X * s, q.Y * s, q.Z * s);\n\n        /// <summary>\n        /// Multiplies two <see cref=\"QuaternionD\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator *(QuaternionD a, QuaternionD b)\n        {\n            return new QuaternionD(\n                a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z,\n                a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,\n                a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,\n                a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X);\n        }\n\n        /// <summary>\n        /// Divides two <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator /(QuaternionD a, QuaternionD b)\n            => a * b.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"QuaternionD\"/> by a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator /(QuaternionD q, double s)\n            => new QuaternionD(q.W / s, q.X / s, q.Y / s, q.Z / s);\n\n        /// <summary>\n        /// Divides a scalar by a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator /(double s, QuaternionD q)\n            => new QuaternionD(s / q.W, s / q.X, s / q.Y, s / q.Z);\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"QuaternionD\"/> are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(QuaternionD q0, QuaternionD q1)\n            => q0.W == q1.W && q0.X == q1.X && q0.Y == q1.Y && q0.Z == q1.Z;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"QuaternionD\"/> are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(QuaternionD q0, QuaternionD q1)\n            => q0.W != q1.W || q0.X != q1.X || q0.Y != q1.Y || q0.Z != q1.Z;\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Conversion from a <see cref=\"QuaternionD\"/> to a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator QuaternionF(QuaternionD q)\n            => new QuaternionF(q);\n\n        /// <summary>\n        /// Returns this <see cref=\"QuaternionD\"/> as a 4x4 matrix. Quaternions are represented as matrices in such\n        /// a way that quaternion multiplication and addition is equivalent to matrix multiplication and addition.\n        /// Note that there are 48 distinct such matrix representations for a single quaternion.\n        /// </summary>\n        [Obsolete(\"Misleading conversion. Do you want a Rot3d to M44d conversion instead?\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(QuaternionD q)\n        {\n            return new M44d(\n                q.W, -q.X, -q.Y, -q.Z,\n                q.X,  q.W, -q.Z,  q.Y,\n                q.Y,  q.Z,  q.W, -q.X,\n                q.Z, -q.Y,  q.X,  q.W);\n        }\n\n        /// <summary>\n        /// Returns this <see cref=\"QuaternionD\"/> as a <see cref=\"V4d\"/> vector.\n        /// Note that the components are ordered (w, x, y, z).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(QuaternionD q)\n            => new V4d(q.W, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"QuaternionD\"/> instance\n        /// in a double[] array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](QuaternionD q)\n        {\n            double[] array = new double[4];\n            array[0] = q.W;\n            array[1] = q.X;\n            array[2] = q.Y;\n            array[3] = q.Z;\n            return array;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets or sets the <paramref name=\"i\"/>-th component of the <see cref=\"QuaternionD\"/> with components (w, (x, y, z)).\n        /// </summary>\n        public unsafe double this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &W) { return ptr[i]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &W) { ptr[i] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(W, X, Y, Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(QuaternionD other)\n            => W.Equals(other.W) && X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n\n        public override readonly bool Equals(object other)\n            => (other is QuaternionD o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", W, X, Y, Z);\n        }\n\n        public static QuaternionD Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new QuaternionD(double.Parse(x[0], CultureInfo.InvariantCulture), double.Parse(x[1], CultureInfo.InvariantCulture), double.Parse(x[2], CultureInfo.InvariantCulture), double.Parse(x[3], CultureInfo.InvariantCulture));\n        }\n\n        #endregion\n    }\n\n    public static partial class Quaternion\n    {\n        #region Invert, Normalize, Conjugate, Dot\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD Inverse(QuaternionD q)\n            => q.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref QuaternionD q)\n        {\n            var norm = q.NormSquared;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                q.W *= scale;\n                q.X *= -scale;\n                q.Y *= -scale;\n                q.Z *= -scale;\n            }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD Normalized(QuaternionD q)\n            => q.Normalized;\n\n        /// <summary>\n        /// Normalizes a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref QuaternionD q)\n        {\n            var norm = q.Norm;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                q.W *= scale;\n                q.X *= scale;\n                q.Y *= scale;\n                q.Z *= scale;\n            }\n        }\n\n        /// <summary>\n        /// Returns the conjugate of a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD Conjugated(QuaternionD q)\n            => q.Conjugated;\n\n        /// <summary>\n        /// Conjugates a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Conjugate(this ref QuaternionD q)\n        {\n            q.X = -q.X;\n            q.Y = -q.Y;\n            q.Z = -q.Z;\n        }\n\n        /// <summary>\n        /// Returns the dot product of two <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Dot(this QuaternionD a, QuaternionD b)\n        {\n            return a.W * b.W + a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        #endregion\n\n        #region Norm\n\n        /// <summary>\n        /// Gets the squared norm (or length) of a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormSquared(QuaternionD q)\n            => q.NormSquared;\n\n        /// <summary>\n        /// Gets the norm (or length) of a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(QuaternionD q)\n            => q.Norm;\n\n        #endregion\n\n        #region Spherical Linear Interpolation\n\n        /// <summary>\n        /// Spherical linear interpolation.\n        ///\n        /// Assumes q1 and q2 are normalized and that t in [0,1].\n        ///\n        /// This method interpolates along the shortest arc between q1 and q2.\n        /// </summary>\n        public static QuaternionD SlerpShortest(this QuaternionD q1, QuaternionD q2, double t)\n        {\n            QuaternionD q3 = q2;\n            double cosomega = Dot(q1, q3);\n\n            if (cosomega < 0)\n            {\n                cosomega = -cosomega;\n                q3 = -q3;\n            }\n\n            if (cosomega >= 1)\n            {\n                // Special case: q1 and q2 are the same, so just return one of them.\n                // This also catches the case where cosomega is very slightly > 1.0\n                return q1;\n            }\n\n            double sinomega = Fun.Sqrt(1 - cosomega * cosomega);\n\n            QuaternionD result;\n\n            if (sinomega * double.MaxValue > 1)\n            {\n                double omega = Fun.Acos(cosomega);\n                double s1 = Fun.Sin((1 - t) * omega) / sinomega;\n                double s2 = Fun.Sin(t * omega) / sinomega;\n\n                result = new QuaternionD(s1 * q1 + s2 * q3);\n            }\n            else if (cosomega > 0)\n            {\n                // omega == 0\n                double s1 = 1 - t;\n                double s2 = t;\n\n                result = new QuaternionD(s1 * q1 + s2 * q3);\n            }\n            else\n            {\n                // omega == -pi\n                result = new QuaternionD(q1.Z, -q1.Y, q1.X, -q1.W);\n\n                double s1 = Fun.Sin((0.5 - t) * Constant.Pi);\n                double s2 = Fun.Sin(t * Constant.Pi);\n\n                result = new QuaternionD(s1 * q1 + s2 * result);\n            }\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this QuaternionD q0, QuaternionD q1)\n        {\n            return ApproximateEquals(q0, q1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this QuaternionD q0, QuaternionD q1, double tolerance)\n        {\n            return ApproximateEquals(q0.W, q1.W, tolerance) && ApproximateEquals(q0.X, q1.X, tolerance) && ApproximateEquals(q0.Y, q1.Y, tolerance) && ApproximateEquals(q0.Z, q1.Z, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Quaternion_template.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action and = () => Out(\" && \");\n    //# Action or = () => Out(\" || \");\n    //# Action andLit = () => Out(\" and \");\n    //# var qfields = new[] {\"W\", \"X\", \"Y\", \"Z\"};\n    //# var qfieldsL = new[] {\"w\", \"x\", \"y\", \"z\"};\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var tccaps = tc.ToUpper();\n    //#   var tccaps2 = tc2.ToUpper();\n    //#   var type = \"Quaternion\" + tccaps;\n    //#   var type2 = \"Quaternion\" + tccaps2;\n    //#   var v3t = \"V3\" + tc;\n    //#   var v4t = \"V4\" + tc;\n    //#   var m44t = \"M44\" + tc;\n    //#   var rot3t = \"Rot3\" + tc;\n    //#   var rot3t2 = \"Rot3\" + tc2;\n    //#   var getptr = \"&\" + qfields[0];\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#   var piHalf = isDouble ? \"Constant.PiHalf\" : \"ConstantF.PiHalf\";\n    #region __type__\n\n    /// <summary>\n    /// Struct for general quaternions, for rotations in 3-dimensional space use <see cref=\"Rot3__tc__\"/>.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>\n    {\n        /// <summary>\n        /// Scalar (real) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public __ftype__ W;\n\n        /// <summary>\n        /// First component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public __ftype__ X;\n\n        /// <summary>\n        /// Second component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public __ftype__ Y;\n\n        /// <summary>\n        /// Third component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public __ftype__ Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> (a, (a, a, a)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ a)\n        {\n            W = a;\n            X = a; Y = a; Z = a;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> (w, (x, y, z)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ w, __ftype__ x, __ftype__ y, __ftype__ z)\n        {\n            W = w;\n            X = x; Y = y; Z = z;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> (v.x, (v.y, v.z, v.w)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__v4t__ v)\n        {\n            W = v.X;\n            X = v.Y; Y = v.Z; Z = v.W;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> (w, (v.x, v.y, v.z)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ w, __v3t__ v)\n        {\n            W = w;\n            X = v.X; Y = v.Y; Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a copy of the given <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ q)\n        {\n            /*# qfields.ForEach(f => {*/__f__ = q.__f__; /*# });*/\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> from the given <see cref=\"__type2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ q)\n        {\n            /*# qfields.ForEach(f => {*/__f__ = (__ftype__)q.__f__; /*# });*/\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> from the given <see cref=\"__rot3t__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__rot3t__ r)\n        {\n            /*# qfields.ForEach(f => {*/__f__ = r.__f__; /*# });*/\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> from the given <see cref=\"__rot3t2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__rot3t2__ r)\n        {\n            /*# qfields.ForEach(f => {*/__f__ = (__ftype__)r.__f__; /*# });*/\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> from an array.\n        /// (w = a[0], (x = a[1], y = a[2], z = a[3])).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] a)\n        {\n            W = a[0];\n            X = a[1]; Y = a[2]; Z = a[3];\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> from an array starting at specified index.\n        /// (w = a[start], (x = a[start+1], y = a[start+2], z = a[start+3])).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] a, int start)\n        {\n            W = a[start];\n            X = a[start + 1]; Y = a[start + 2]; Z = a[start + 3];\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets or sets the vector part (x, y, z) of this <see cref=\"__type__\"/>.\n        /// </summary>\n        [XmlIgnore]\n        public __v3t__ V\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new __v3t__(X, Y, Z); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n\n        /// <summary>\n        /// Gets the squared norm (or squared length) of this <see cref=\"__type__\"/>.\n        /// </summary>\n        public readonly __ftype__ NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => /*# qfields.ForEach(f => {*/__f__ * __f__/*# }, add);*/;\n        }\n\n        /// <summary>\n        /// Gets the norm (or length) of this <see cref=\"__type__\"/>.\n        /// </summary>\n        public readonly __ftype__ Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => NormSquared.Sqrt();\n        }\n\n        /// <summary>\n        /// Gets normalized (unit) quaternion from this <see cref=\"__type__\"/>\n        /// </summary>\n        public readonly __type__ Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new __type__(this);\n                rs.Normalize();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this <see cref=\"__type__\"/>.\n        /// The zero quaternion is returned, if this quaternion is zero.\n        /// </summary>\n        public readonly __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new __type__(this);\n                rs.Invert();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the conjugate of this <see cref=\"__type__\"/>.\n        /// For unit quaternions this is the same as its inverse.\n        /// </summary>\n        public readonly __type__ Conjugated\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(W, -V);\n        }\n\n        /// <summary>\n        /// Gets if this <see cref=\"__type__\"/> is zero.\n        /// </summary>\n        public readonly bool IsZero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => /*# qfields.ForEach(f => {*/(__f__ == 0)/*# }, and);*/;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> with (0, (0, 0, 0)).\n        /// </summary>\n        public static __type__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> with (1, (0, 0, 0)).\n        /// </summary>\n        public static __type__ One\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets the identity <see cref=\"__type__\"/> with (1, (0, 0, 0)).\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> with (0, (1, 0, 0)).\n        /// </summary>\n        public static __type__ I\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(0, 1, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> with (0, (0, 1, 0)).\n        /// </summary>\n        public static __type__ J\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(0, 0, 1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> with (0, (0, 0, 1)).\n        /// </summary>\n        public static __type__ K\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Returns the component-wise negation of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ q)\n            => new __type__(/*# qfields.ForEach(f => {*/-q.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the sum of two <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator +(__type__ a, __type__ b)\n            => new __type__(/*# qfields.ForEach(f => {*/a.__f__ + b.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"__type__\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator +(__type__ q, __ftype__ s)\n            => new __type__(q.W + s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the sum of a real scalar and a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator +(__ftype__ s, __type__ q)\n            => new __type__(q.W + s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the difference between two <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ a, __type__ b)\n            => new __type__(/*# qfields.ForEach(f => {*/a.__f__ - b.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"__type__\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ q, __ftype__ s)\n            => new __type__(q.W - s, q.X, q.Y, q.Z);\n\n        /// <summary>\n        /// Returns the difference between a real scalar and a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__ftype__ s, __type__ q)\n            => new __type__(s - q.W, -q.X, -q.Y, -q.Z);\n\n        /// <summary>\n        /// Returns the product of a <see cref=\"__type__\"/> and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ q, __ftype__ s)\n            => new __type__(/*# qfields.ForEach(f => {*/q.__f__ * s/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the product of a scalar and a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__ftype__ s, __type__ q)\n            => new __type__(/*# qfields.ForEach(f => {*/q.__f__ * s/*# }, comma);*/);\n\n        /// <summary>\n        /// Multiplies two <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __type__ b)\n        {\n            return new __type__(\n                a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z,\n                a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,\n                a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,\n                a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X);\n        }\n\n        /// <summary>\n        /// Divides two <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__type__ a, __type__ b)\n            => a * b.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"__type__\"/> by a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__type__ q, __ftype__ s)\n            => new __type__(/*# qfields.ForEach(f => {*/q.__f__ / s/*# }, comma);*/);\n\n        /// <summary>\n        /// Divides a scalar by a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__ftype__ s, __type__ q)\n            => new __type__(/*# qfields.ForEach(f => {*/s / q.__f__/*# }, comma);*/);\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ q0, __type__ q1)\n            => /*# qfields.ForEach(f => {*/q0.__f__ == q1.__f__/*# }, and);*/;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ q0, __type__ q1)\n            => /*# qfields.ForEach(f => {*/q0.__f__ != q1.__f__/*# }, or);*/;\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Conversion from a <see cref=\"__type__\"/> to a <see cref=\"__type2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ q)\n            => new __type2__(q);\n\n        /// <summary>\n        /// Returns this <see cref=\"__type__\"/> as a 4x4 matrix. Quaternions are represented as matrices in such\n        /// a way that quaternion multiplication and addition is equivalent to matrix multiplication and addition.\n        /// Note that there are 48 distinct such matrix representations for a single quaternion.\n        /// </summary>\n        [Obsolete(\"Misleading conversion. Do you want a Rot3__tc__ to __m44t__ conversion instead?\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __m44t__(__type__ q)\n        {\n            return new __m44t__(\n                q.W, -q.X, -q.Y, -q.Z,\n                q.X,  q.W, -q.Z,  q.Y,\n                q.Y,  q.Z,  q.W, -q.X,\n                q.Z, -q.Y,  q.X,  q.W);\n        }\n\n        /// <summary>\n        /// Returns this <see cref=\"__type__\"/> as a <see cref=\"__v4t__\"/> vector.\n        /// Note that the components are ordered (w, x, y, z).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __v4t__(__type__ q)\n            => new __v4t__(/*# qfields.ForEach(f => {*/q.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"__type__\"/> instance\n        /// in a __ftype__[] array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __ftype__[](__type__ q)\n        {\n            __ftype__[] array = new __ftype__[__qfields.Length__];\n            /*# qfields.ForEach((f, i) => {*/array[__i__] = q.__f__;\n            /*# });*/return array;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets or sets the <paramref name=\"i\"/>-th component of the <see cref=\"__type__\"/> with components (w, (x, y, z)).\n        /// </summary>\n        public unsafe __ftype__ this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (__ftype__* ptr = __getptr__) { return ptr[i]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (__ftype__* ptr = __getptr__) { ptr[i] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(W, X, Y, Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => /*# qfields.ForEach(f => {*/__f__.Equals(other.__f__)/*# }, and);*/;\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}, {3}]\", W, X, Y, Z);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(/*# 4.ForEach(i => {*/__ftype__.Parse(x[__i__], CultureInfo.InvariantCulture)/*# }, comma);*/);\n        }\n\n        #endregion\n    }\n\n    public static partial class Quaternion\n    {\n        #region Invert, Normalize, Conjugate, Dot\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ q)\n            => q.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref __type__ q)\n        {\n            var norm = q.NormSquared;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                q.W *= scale;\n                q.X *= -scale;\n                q.Y *= -scale;\n                q.Z *= -scale;\n            }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Normalized(__type__ q)\n            => q.Normalized;\n\n        /// <summary>\n        /// Normalizes a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref __type__ q)\n        {\n            var norm = q.Norm;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                q.W *= scale;\n                q.X *= scale;\n                q.Y *= scale;\n                q.Z *= scale;\n            }\n        }\n\n        /// <summary>\n        /// Returns the conjugate of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Conjugated(__type__ q)\n            => q.Conjugated;\n\n        /// <summary>\n        /// Conjugates a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Conjugate(this ref __type__ q)\n        {\n            q.X = -q.X;\n            q.Y = -q.Y;\n            q.Z = -q.Z;\n        }\n\n        /// <summary>\n        /// Returns the dot product of two <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Dot(this __type__ a, __type__ b)\n        {\n            return a.W * b.W + a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        #endregion\n\n        #region Norm\n\n        /// <summary>\n        /// Gets the squared norm (or length) of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ NormSquared(__type__ q)\n            => q.NormSquared;\n\n        /// <summary>\n        /// Gets the norm (or length) of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Norm(__type__ q)\n            => q.Norm;\n\n        #endregion\n\n        #region Spherical Linear Interpolation\n\n        /// <summary>\n        /// Spherical linear interpolation.\n        ///\n        /// Assumes q1 and q2 are normalized and that t in [0,1].\n        ///\n        /// This method interpolates along the shortest arc between q1 and q2.\n        /// </summary>\n        public static __type__ SlerpShortest(this __type__ q1, __type__ q2, __ftype__ t)\n        {\n            __type__ q3 = q2;\n            __ftype__ cosomega = Dot(q1, q3);\n\n            if (cosomega < 0)\n            {\n                cosomega = -cosomega;\n                q3 = -q3;\n            }\n\n            if (cosomega >= 1)\n            {\n                // Special case: q1 and q2 are the same, so just return one of them.\n                // This also catches the case where cosomega is very slightly > 1.0\n                return q1;\n            }\n\n            __ftype__ sinomega = Fun.Sqrt(1 - cosomega * cosomega);\n\n            __type__ result;\n\n            if (sinomega * __ftype__.MaxValue > 1)\n            {\n                __ftype__ omega = Fun.Acos(cosomega);\n                __ftype__ s1 = Fun.Sin((1 - t) * omega) / sinomega;\n                __ftype__ s2 = Fun.Sin(t * omega) / sinomega;\n\n                result = new __type__(s1 * q1 + s2 * q3);\n            }\n            else if (cosomega > 0)\n            {\n                // omega == 0\n                __ftype__ s1 = 1 - t;\n                __ftype__ s2 = t;\n\n                result = new __type__(s1 * q1 + s2 * q3);\n            }\n            else\n            {\n                // omega == -pi\n                result = new __type__(q1.Z, -q1.Y, q1.X, -q1.W);\n\n                __ftype__ s1 = Fun.Sin((__half__ - t) * __pi__);\n                __ftype__ s2 = Fun.Sin(t * __pi__);\n\n                result = new __type__(s1 * q1 + s2 * result);\n            }\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ q0, __type__ q1)\n        {\n            return ApproximateEquals(q0, q1, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ q0, __type__ q1, __ftype__ tolerance)\n        {\n            return /*# qfields.ForEach(f => {*/ApproximateEquals(q0.__f__, q1.__f__, tolerance)/*# }, and);*/;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/SampleGrid2d.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public class SampleGrid2d\n    {\n        private V2l m_last;\n        private Box2d m_region;\n        private V2d m_delta;\n\n        public SampleGrid2d(V2l gridSize, Box2d region)\n        {\n            m_last = gridSize - new V2l(1, 1);\n            m_region = region;\n            m_delta = region.Size / (V2d)m_last;\n        }\n\n        public static void AdaptivelyFill(\n            Action<long, long, long, long, double, double> xMid,\n            Action<long, long, long, long, double, double> yMid,\n            Action<long, long, long, long, long, long,\n                    double, double, double, double> xyMid,\n            long x0, long x1, long y0, long y1\n            )\n        {\n            var dx = x1 - x0;\n            var dy = y1 - y0;\n            if ((dx < 2) && (dy < 2)) return;\n            long xm = 0, ym = 0;\n            double wx0 = 0.0, wx1 = 0.0, wy0 = 0.0, wy1 = 0.0;\n            if (dx > 1)\n            {\n                xm = (x1 + x0) / 2;\n                wx1 = (xm - x0) / (double)dx;\n                wx0 = (x1 - xm) / (double)dx;\n                xMid(x0, x1, y0, xm, wx0, wx1);\n                xMid(x0, x1, y1, xm, wx0, wx1);\n                if (dy < 2)\n                {\n                    AdaptivelyFill(xMid, yMid, xyMid, x0, xm, y0, y1);\n                    AdaptivelyFill(xMid, yMid, xyMid, xm, x1, y0, y1);\n                    return;\n                }\n            }\n            if (dy > 1)\n            {\n                ym = (y1 + y0) / 2;\n                wy1 = (ym - y0) / (double)dy;\n                wy0 = (y1 - ym) / (double)dy;\n                yMid(x0, y0, y1, ym, wy0, wy1);\n                yMid(x1, y0, y1, ym, wy0, wy1);\n                if (dx < 2)\n                {\n                    AdaptivelyFill(xMid, yMid, xyMid, x0, x1, y0, ym);\n                    AdaptivelyFill(xMid, yMid, xyMid, x0, x1, ym, y1);\n                    return;\n                }\n            }\n            if (dx > 1 && dy > 1)\n            {\n                xyMid(x0, x1, y0, y1, xm, ym, wx0, wx1, wy0, wy1);\n                AdaptivelyFill(xMid, yMid, xyMid, x0, xm, y0, ym);\n                AdaptivelyFill(xMid, yMid, xyMid, xm, x1, y0, ym);\n                AdaptivelyFill(xMid, yMid, xyMid, x0, xm, ym, y1);\n                AdaptivelyFill(xMid, yMid, xyMid, xm, x1, ym, y1);\n            }\n        }\n\n        public static void AdaptivelyFill(\n                    Action<int, long, long, long, long, double, double> xMid,\n                    Action<int, long, long, long, long, double, double> yMid,\n                    Action<int, long, long, long, long, long, long,\n                         double, double, double, double> xyMid,\n                    int depth, long x0, long x1, long y0, long y1\n                    )\n        {\n            var dx = x1 - x0;\n            var dy = y1 - y0;\n            if ((dx < 2) && (dy < 2)) return;\n            long xm = 0, ym = 0;\n            double wx0 = 0.0, wx1 = 0.0, wy0 = 0.0, wy1 = 0.0;\n            if (dx > 1)\n            {\n                xm = (x1 + x0) / 2;\n                wx1 = (xm - x0) / (double)dx;\n                wx0 = (x1 - xm) / (double)dx;\n                xMid(depth, x0, x1, y0, xm, wx0, wx1);\n                xMid(depth, x0, x1, y1, xm, wx0, wx1);\n                if (dy < 2)\n                {\n                    AdaptivelyFill(xMid, yMid, xyMid, depth + 1, x0, xm, y0, y1);\n                    AdaptivelyFill(xMid, yMid, xyMid, depth + 1, xm, x1, y0, y1);\n                    return;\n                }\n            }\n            if (dy > 1)\n            {\n                ym = (y1 + y0) / 2;\n                wy1 = (ym - y0) / (double)dy;\n                wy0 = (y1 - ym) / (double)dy;\n                yMid(depth, x0, y0, y1, ym, wy0, wy1);\n                yMid(depth, x1, y0, y1, ym, wy0, wy1);\n                if (dx < 2)\n                {\n                    AdaptivelyFill(xMid, yMid, xyMid, depth + 1, x0, x1, y0, ym);\n                    AdaptivelyFill(xMid, yMid, xyMid, depth + 1, x0, x1, ym, y1);\n                    return;\n                }\n            }\n            if (dx > 1 && dy > 1)\n            {\n                xyMid(depth, x0, x1, y0, y1, xm, ym, wx0, wx1, wy0, wy1);\n                AdaptivelyFill(xMid, yMid, xyMid, depth + 1, x0, xm, y0, ym);\n                AdaptivelyFill(xMid, yMid, xyMid, depth + 1, xm, x1, y0, ym);\n                AdaptivelyFill(xMid, yMid, xyMid, depth + 1, x0, xm, ym, y1);\n                AdaptivelyFill(xMid, yMid, xyMid, depth + 1, xm, x1, ym, y1);\n            }\n        }\n\n        public static void AdaptivelySample(\n                    Func<long, long, long, long,\n                         double, double, double, double, bool> similar,\n                    Action<long, long, double, double> sample,\n                    Action<long, long, long, long,\n                         double, double, double, double> region,\n                    Action<long, long, long, long,\n                         double, double, double, double> super,\n                    long x0, long x1, long y0, long y1,\n                    double xd0, double xd1, double yd0, double yd1\n                    )\n        {\n            var dx = x1 - x0;\n            var dy = y1 - y0;\n            if ((dx < 2) && (dy < 2))\n            {\n                super(x0, x1, y0, y1, xd0, xd1, yd0, yd1);\n                return;\n            }\n            if (similar(x0, x1, y0, y1, xd0, xd1, yd0, yd1))\n            {\n                region(x0, x1, y0, y1, xd0, xd1, yd0, yd1);\n                return;\n            }\n            if (dx > 1)\n            {\n                var xm = (x1 + x0) / 2;\n                var xdm = xd0 + (xd1 - xd0) * (xm - x0) / (double)dx;\n                sample(xm, y0, xdm, yd0);\n                sample(xm, y1, xdm, yd1);\n                if (dy > 1)\n                {\n                    var ym = (y1 + y0) / 2;\n                    var ydm = yd0 + (yd1 - yd0) * (ym - y0) / (double)dy;\n                    sample(x0, ym, xd0, ydm);\n                    sample(xm, ym, xdm, ydm);\n                    sample(x1, ym, xd1, ydm);\n                    AdaptivelySample(similar, sample, region, super,\n                                     x0, xm, y0, ym, xd0, xdm, yd0, ydm);\n                    AdaptivelySample(similar, sample, region, super,\n                                     xm, x1, y0, ym, xdm, xd1, yd0, ydm);\n                    AdaptivelySample(similar, sample, region, super,\n                                     x0, xm, ym, y1, xd0, xdm, ydm, yd1);\n                    AdaptivelySample(similar, sample, region, super,\n                                     xm, x1, ym, y1, xdm, xd1, ydm, yd1);\n                }\n                else\n                {\n                    AdaptivelySample(similar, sample, region, super,\n                                     x0, xm, y0, y1, xd0, xdm, yd0, yd1);\n                    AdaptivelySample(similar, sample, region, super,\n                                     xm, x1, y0, y1, xdm, xd1, yd0, yd1);\n                }\n            }\n            else\n            {\n                var ym = (y1 + y0) / 2;\n                var ydm = yd0 + (yd1 - yd0) * (ym - y0) / (double)dy;\n                sample(x0, ym, xd0, ydm);\n                sample(x1, ym, xd1, ydm);\n                AdaptivelySample(similar, sample, region, super,\n                                 x0, x1, y0, ym, xd0, xd1, yd0, ydm);\n                AdaptivelySample(similar, sample, region, super,\n                                 x0, x1, ym, y1, xd0, xd1, ydm, yd1);\n            }\n        }\n\n        public void Sample(V2l count,\n                            Action<long, long, double, double> sample)\n        {\n            V2d step = (V2d)m_last / (V2d)count;\n            double yd = 0.5;\n            for (int yi = 0; yi <= m_last.Y; yd += step.Y, yi = (int)yd)\n            {\n                double y = m_region.Min.Y + yi * m_delta.Y;\n                double xd = 0.5;\n                for (int xi = 0; xi <= m_last.X; xd += step.X, xi = (int)xd)\n                {\n                    double x = m_region.Min.X + xi * m_delta.X;\n                    sample(xi, yi, x, y);\n                }\n            }\n        }\n\n        public void Sample(V2l count,\n                    Action<long, long, long, long,\n                         double, double, double, double> region)\n        {\n            V2d step = (V2d)m_last / (V2d)count;\n            double y = m_region.Min.Y;\n            double yd = 0.5 + step.Y;\n            for (int yi = 0, nyi = (int)yd; yi < m_last.Y;\n                 yd += step.Y, yi = nyi, nyi = (int)yd)\n            {\n                double ny = m_region.Min.Y + nyi * m_delta.Y;\n                double x = m_region.Min.X;\n                double xd = 0.5 + step.X;\n                for (int xi = 0, nxi = (int)xd; xi < m_last.X;\n                     xd += step.X, xi = nxi, nxi = (int)xd)\n                {\n                    double nx = m_region.Min.X + nxi * m_delta.X;\n                    region(xi, nxi, yi, nyi, x, nx, y, ny);\n                    x = nx;\n                }\n                y = ny;\n            }\n        }\n            \n        /// <summary>\n        /// Perform the supplied action on grid elements that are separated\n        /// by a supplied step size. Only near the borders, the separation\n        /// may be smaller. The (possibly) smaller border separation is\n        /// distributed to all four borders.\n        /// </summary>\n        public void SampleRegular(V2l step, Action<long, long, double, double> sample)\n        {\n            V2l regularLast = (m_last / step) * step;\n            V2l offset = (m_last - regularLast) / 2;\n            regularLast += offset;\n\n            if (offset.Y > 0)\n            {\n                if (offset.X > 0)\n                    sample(0, 0, m_region.Min.X, m_region.Min.Y);\n                for (long xi = offset.X; xi <= regularLast.X; xi += step.X)\n                    sample(xi, 0, m_region.Min.X + xi * m_delta.X, m_region.Min.Y);\n                if (regularLast.X < m_last.X)\n                    sample(m_last.X, 0, m_region.Max.X, m_region.Min.Y);\n            }\n            for (long yi = offset.Y; yi <= regularLast.Y; yi += step.Y)\n            {\n                double y = m_region.Min.Y + yi * m_delta.Y;\n                if (offset.X > 0)\n                    sample(0, yi, m_region.Min.X, y);\n                for (long xi = offset.X; xi <= regularLast.X; xi += step.X)\n                    sample(xi, yi, m_region.Min.X + xi * m_delta.X, y);\n                if (regularLast.X < m_last.X)\n                    sample(m_last.X, yi, m_region.Max.X, y);\n            }\n            if (regularLast.Y < m_last.Y)\n            {\n                if (offset.X > 0)\n                    sample(0, m_last.Y, m_region.Min.X, m_region.Max.Y);\n                for (long xi = offset.X; xi <= regularLast.X; xi += step.X)\n                    sample(xi, m_last.Y, m_region.Min.X + xi * m_delta.X, m_region.Max.Y);\n                if (regularLast.X < m_last.X)\n                    sample(m_last.X, m_last.Y, m_region.Max.X, m_region.Max.Y);\n            }\n        }\n\n        /// <summary>\n        /// Perform the supplied action on grid regions of a supplied step\n        /// size. Only near the borders, the regions may be smaller. The\n        /// (possibly) smaller border region size is distributed to all four\n        /// borders.\n        /// </summary>\n        public void SampleRegular(V2l step,\n                    Action<long, long, long, long,\n                         double, double, double, double> region)\n        {\n            V2l regularLast = (m_last / step) * step;\n            V2l offset = (m_last - regularLast) / 2;\n            regularLast += offset;\n\n            if (offset.Y > 0)\n            {\n                double maxY = m_region.Min.Y + offset.Y * m_delta.Y;\n                if (offset.X > 0)\n                    region(0, offset.X, 0, offset.Y,\n                        m_region.Min.X,\n                        m_region.Min.X + offset.X * m_delta.X,\n                        m_region.Min.Y, maxY);\n                for (long xi = offset.X, nxi = xi + step.X;\n                     xi < regularLast.X; xi = nxi, nxi += step.X)\n                    region(xi, nxi, 0, offset.Y,\n                        m_region.Min.X + xi * m_delta.X,\n                        m_region.Min.X + nxi * m_delta.X,\n                        m_region.Min.Y, maxY);\n                if (regularLast.X < m_last.X)\n                    region(regularLast.X, m_last.X, 0, offset.Y,\n                        m_region.Min.X + regularLast.X * m_delta.X,\n                        m_region.Min.X + m_last.X * m_delta.X,\n                        m_region.Min.Y, maxY);\n            }\n\n            for (long yi = offset.Y, nyi = yi + step.Y;\n                 yi < regularLast.Y; yi = nyi, nyi += step.Y)\n            {\n                double minY = m_region.Min.Y + yi * m_delta.Y;\n                double maxY = minY + m_delta.Y;\n                if (offset.X > 0)\n                    region(0, offset.X, yi, nyi,\n                        m_region.Min.X,\n                        m_region.Min.X + offset.X * m_delta.X,\n                        minY, maxY);\n                for (long xi = offset.X, nxi = xi + step.X;\n                     xi < regularLast.X; xi = nxi, nxi += step.X)\n                {\n                    region(xi, nxi, yi, nyi,\n                        m_region.Min.X + xi * m_delta.X,\n                        m_region.Min.X + nxi * m_delta.X,\n                        minY, maxY);\n                }\n                if (regularLast.X < m_last.X)\n                    region(regularLast.X, m_last.X, yi, nyi,\n                        m_region.Min.X + regularLast.X * m_delta.X,\n                        m_region.Min.X + m_last.X * m_delta.X,\n                        minY, maxY);\n            }\n\n            if (regularLast.Y < m_last.Y)\n            {\n                double minY = m_region.Min.Y + regularLast.Y * m_delta.Y;\n                if (offset.X > 0)\n                    region(0, offset.X, regularLast.Y, m_last.Y,\n                        m_region.Min.X,\n                        m_region.Min.X + offset.X * m_delta.X,\n                        minY, m_region.Max.Y);\n                for (long xi = offset.X, nxi = xi + step.X;\n                     xi < regularLast.X; xi = nxi, nxi += step.X)\n                    region(xi, xi + step.X, regularLast.Y, m_last.Y,\n                        m_region.Min.X + xi * m_delta.X,\n                        m_region.Min.X + nxi * m_delta.X,\n                        minY, m_region.Max.Y);\n                if (regularLast.X < m_last.X)\n                    region(regularLast.X, m_last.X, regularLast.Y, m_last.Y,\n                        m_region.Min.X + regularLast.X * m_delta.X,\n                        m_region.Min.X + m_last.X * m_delta.X,\n                        minY, m_region.Max.Y);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/Statistics.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    #region Extremum<T>\n\n    /// <summary>\n    /// A structure that maintains the extreme Value and an associated Data field\n    /// as each value/data pair is added.\n    /// </summary>\n    public struct Extremum<T>\n    {\n        private double m_value;\n        private T m_data;\n\n        #region Constructor\n\n        public Extremum(double value, T data)\n        {\n            m_value = value;\n            m_data = data;\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Extremum<T> EmptyMin\n            = new Extremum<T>(Constant<double>.ParseableMaxValue, default(T));\n        public static readonly Extremum<T> EmptyMax\n            = new Extremum<T>(Constant<double>.ParseableMinValue, default(T));\n\n        #endregion\n\n        #region Properties\n\n        public readonly double Value { get { return m_value; } }\n        public readonly T Data { get { return m_data; } }\n\n        #endregion\n\n        #region Methods\n\n        public void AddMin(double value)\n        {\n            if (value < m_value) { m_value = value; }\n        }\n\n        public void AddMax(double value)\n        {\n            if (value > m_value) { m_value = value; }\n        }\n\n        public void AddMin(double value, T data)\n        {\n            if (value < m_value) { m_value = value; m_data = data; }\n        }\n\n        public void AddMax(double value, T data)\n        {\n            if (value > m_value) { m_value = value; m_data = data; }\n        }\n\n        public static Extremum<T> Max(Extremum<T> e0, Extremum<T> e1)\n        {\n            return e0.m_value >= e1.m_value ? e0 : e1;\n        }\n\n        public static Extremum<T> Min(Extremum<T> e0, Extremum<T> e1)\n        {\n            return e0.m_value < e1.m_value ? e0 : e1;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region StatsOptions\n\n    [Flags]\n    public enum StatsOptions\n    {\n        Count = 0x0001,\n        Sum = 0x0002,\n        Mean = 0x0004,\n        Min = 0x0010,\n        Max = 0x0020,\n        Range = 0x0030,\n        Variance = 0x0100,\n        StandardDeviation = 000200,\n        NeedsSumOfSquares = 0x0300,\n        All = 0x3fffffff,\n        MaxMean = Max | Mean,\n        MinMean = Min | Mean,\n        RangeMean = Range | Mean,\n        CountRange = Count | Range,\n    }\n\n    #endregion\n\n    #region Stats<T>\n\n    /// <summary>\n    /// A data structure for accumulating statistical moments. Currently only\n    /// Count/Sum/Min/Max/Mean/Variance is implemented. Extend as necessary.\n    /// </summary>\n    public struct Stats<T> : IReportable\n    {\n        long m_count;\n        KahanSum m_sum;\n        readonly StatsOptions m_options;\n        Extremum<T> m_min;\n        Extremum<T> m_max;\n        KahanSum m_sumOfSquares;\n\n        #region Constructor\n\n        public Stats(StatsOptions options)\n        {\n            m_options = options;\n            m_count = 0;\n            m_min = Extremum<T>.EmptyMin;\n            m_max = Extremum<T>.EmptyMax;\n            m_sum = KahanSum.Zero;\n            m_sumOfSquares = KahanSum.Zero;\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Stats<T> ComputeCountRange\n                = new Stats<T>(StatsOptions.Count | StatsOptions.Range);\n        public static readonly Stats<T> ComputeRange\n                = new Stats<T>(StatsOptions.Range);\n        public static readonly Stats<T> ComputeMinMean\n                = new Stats<T>(StatsOptions.Mean | StatsOptions.Min);\n        public static readonly Stats<T> ComputeMaxMean\n                = new Stats<T>(StatsOptions.Mean | StatsOptions.Max);\n        public static readonly Stats<T> ComputeRangeMean\n                = new Stats<T>(StatsOptions.Mean | StatsOptions.Range);\n        public static readonly Stats<T> ComputeCountMaxMean\n                = new Stats<T>(StatsOptions.Count | StatsOptions.Mean | StatsOptions.Max);\n        public static readonly Stats<T> ComputeCountRangeMean\n                = new Stats<T>(StatsOptions.Count | StatsOptions.Mean | StatsOptions.Range);\n        public static readonly Stats<T> ComputeAll\n                = new Stats<T>(StatsOptions.All);\n\n        #endregion\n\n        #region Properties\n\n        public readonly long Count { get { return m_count; } }\n\n        public readonly double Min { get { return m_min.Value; } }\n        public readonly double Max { get { return m_max.Value; } }\n        public readonly T MinData { get { return m_min.Data; } }\n        public readonly T MaxData { get { return m_max.Data; } }\n\n        public readonly double Sum { get { return m_sum.Value; } }\n        public readonly double SumOfSquares { get { return m_sumOfSquares.Value; } }\n        public readonly double Mean { get { return Sum / m_count; } }\n        public readonly double Variance { get { return (SumOfSquares - Sum * Mean)/ m_count; } }\n        public readonly double SampleVariance { get { return (SumOfSquares - Sum * Mean) / (m_count - 1); } }\n\n        #endregion\n\n        #region Methods\n\n        public void Add(double value)\n        {\n            Add(value, default(T));\n        }\n\n        public void Add(double value, T data)\n        {\n            ++m_count;\n            m_sum.Add(value);\n            if ((m_options & StatsOptions.Min) != 0) m_min.AddMin(value, data);\n            if ((m_options & StatsOptions.Max) != 0) m_max.AddMax(value, data);\n            if ((m_options & StatsOptions.NeedsSumOfSquares) != 0)\n                m_sumOfSquares.Add(Fun.Square(value));\n        }\n\n        public void Add(Stats<T> s)\n        {\n            if (s.m_options != m_options)\n                throw new ArgumentException(\"need matching options for adding\");\n\n            m_count += s.m_count;\n            m_sum.Add(s.m_sum);\n            m_min = Extremum<T>.Min(m_min, s.m_min);\n            m_max = Extremum<T>.Min(m_max, s.m_max);\n            m_sumOfSquares.Add(s.m_sumOfSquares);\n        }\n\n        public static Stats<T> operator+(Stats<T> s0, Stats<T> s1)\n        {\n            if (s0.m_options != s1.m_options)\n                throw new ArgumentException(\"need matching options for adding\");\n\n            return new Stats<T>(s0.m_options)\n            {\n                m_count = s0.m_count + s1.m_count,\n                m_sum = s0.m_sum + s1.m_sum,\n                m_min = Extremum<T>.Min(s0.m_min, s1.m_min),\n                m_max = Extremum<T>.Min(s0.m_max, s1.m_max),\n                m_sumOfSquares = s0.m_sumOfSquares + s1.m_sumOfSquares,\n            };\n        }\n\n        #endregion\n\n        #region IReportable Members\n\n        public readonly void ReportValue(int verbosity, string name)\n        {\n            using (Report.Job(verbosity, name))\n            {\n                if ((m_options & StatsOptions.Count) != 0)\n                    Report.Value(verbosity, \"count\", Count);\n                if ((m_options & StatsOptions.Sum) != 0)\n                    Report.Value(verbosity, \"sum\", Sum);\n                if ((m_options & StatsOptions.Min) != 0)\n                    Report.Value(verbosity, \"minimum\", Min);\n                if ((m_options & StatsOptions.Max) != 0)\n                    Report.Value(verbosity, \"maximum\", Max);\n                if ((m_options & StatsOptions.Mean) != 0)\n                {\n                    Report.Value(verbosity, \"mean\", Mean);\n                }\n                if ((m_options & StatsOptions.NeedsSumOfSquares) != 0)\n                {\n                    double variance = Variance;\n                    if ((m_options & StatsOptions.Variance) != 0)\n                        Report.Value(verbosity, \"variance\", variance);\n                    if ((m_options & StatsOptions.Variance) != 0)\n                        Report.Value(verbosity, \"standard deviation\", Fun.Sqrt(variance));\n                }\n            }\n        }\n\n        #endregion\n\n    }\n\n    public class StatsClass<T>\n    {\n        public Stats<T> Value;\n    }\n\n    #endregion\n\n    #region Histogram\n\n    /// <summary>\n    /// A data structure that maintains a histogram with a selectable number\n    /// of slots.\n    /// </summary>\n    public struct Histogram : IReportable\n    {\n        private Range1d m_slotRange;\n        private readonly double m_scale;\n        private long m_small;\n        private long m_large;\n        private Range1d m_dataRange;\n        private readonly long[] m_histo;\n\n        #region Constructor\n\n        public Histogram(double min, double max, int slotCount)\n            : this(new Range1d(min, max), slotCount)\n        {\n        }\n\n        public Histogram(Range1d range, int slotCount)\n        {\n            m_slotRange = range;\n            m_scale = slotCount / (range.Max - range.Min);\n            m_small = 0;\n            m_large = 0;\n            m_dataRange = Range1d.Invalid;\n            m_histo = new long[slotCount];\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly Range1d DataRange { get { return m_dataRange; } }\n        public readonly Range1d SlotRange { get { return m_slotRange; } }\n        public readonly long SmallCount { get { return m_small; } }\n        public readonly long LargeCount { get { return m_large; } }\n        public readonly int SlotCount { get { return m_histo.Length; } }\n        public readonly long this[int slot] { get { return m_histo[slot]; } }\n        public readonly long[] Slots { get { return m_histo; } }\n\n        #endregion\n\n        #region Methods\n\n        public void AddLog10(double value) { Add(Fun.Log10(value)); }\n\n        public void AddLog2(double value) { Add(Fun.Log2(value)); }\n\n        public void Add(double value)\n        {\n            m_dataRange.ExtendBy(value);\n            if (value >= m_slotRange.Max) { ++m_large; return; }\n            value -= m_slotRange.Min;\n            if (value < 0.0) { ++m_small; return; }\n            int slot = (int)(value * m_scale);\n            if (slot >= m_histo.Length) slot = m_histo.Length - 1;\n            m_histo[slot] += 1;\n        }\n\n        public void AddRange(IEnumerable<double> values)\n        {\n            foreach (var v in values)\n                Add(v);\n        }\n\n        public void Clear()\n        {\n            m_small = 0;\n            m_large = 0;\n            m_dataRange = Range1d.Invalid;\n            m_histo.Set(0);\n        }\n\n        public void Add(Histogram h)\n        {\n            if (m_dataRange != h.m_dataRange)\n                throw new ArgumentException(\"adding histograms requires identical data ranges\");\n            if (m_scale != h.m_scale || m_histo.Length != h.m_histo.Length)\n                throw new ArgumentException(\"adding histograms reuqires identical scales and slots\");\n\n            m_small += h.m_small;\n            m_large += h.m_large;\n            for (int i = 0; i < m_histo.Length; i++)\n                m_histo[i] += h.m_histo[i];\n        }\n\n        public static Histogram operator +(Histogram h0, Histogram h1)\n        {\n            if (h0.m_dataRange != h1.m_dataRange)\n                throw new ArgumentException(\"adding histograms requires identical data ranges\");\n            if (h0.m_scale != h1.m_scale || h0.m_histo.Length != h1.m_histo.Length)\n                throw new ArgumentException(\"adding histograms reuqires identical scales and slots\");\n\n            var h = new Histogram(h0.m_dataRange, h0.SlotCount);\n\n            h.m_small = h0.m_small + h1.m_small;\n            h.m_large = h0.m_large + h1.m_large;\n            for (int i = 0; i < h.m_histo.Length; i++)\n                h.m_histo[i] = h0.m_histo[i] + h1.m_histo[i];\n            return h;\n        }\n\n        #endregion\n\n        #region IReportable Members\n\n        private static void ReportRange(\n                int v, double min, double max, long count, bool outside)\n        {\n            string range = String.Format(\"[{0,9:g6} <= x < {1,-9:g6}]\", min, max);\n            if (outside)\n                Report.Values(v, range, \" \", count, \"***\");\n            else\n                Report.Value(v, range, count);\n        }\n\n        public readonly void ReportValue(int v, string name)\n        {\n            using (Report.Job(v, \"{0}:\", name))\n            {\n                if (m_small > 0) ReportRange(v, m_dataRange.Min, m_slotRange.Min, m_small, true);\n                double min = m_slotRange.Min;\n                double scale = (m_slotRange.Max - m_slotRange.Min) / (double)SlotCount;\n                for (int s = 0; s < SlotCount; s++)\n                {\n                    double max = m_slotRange.Min + (s + 1.0) * scale;\n                    ReportRange(v, min, max, m_histo[s], false);\n                    min = max;\n                }\n                if (m_large > 0) ReportRange(v, m_slotRange.Max, m_dataRange.Max, m_large, true);\n            }\n        }\n\n        #endregion\n\n    }\n\n    public class HistogramClass\n    {\n        public Histogram Value;\n    }\n\n    #endregion\n\n    #region HistogramAndStats<T>\n\n    public class HistogramAndStats<T>\n    {\n        public Histogram Histogram;\n        public Stats<T> Stats;\n\n        #region Constructors\n\n        public HistogramAndStats(Histogram histogram, Stats<T> stats)\n        {\n            Histogram = histogram;\n            Stats = stats;\n        }\n\n        public HistogramAndStats(double min, double max, int steps, StatsOptions options)\n            : this(new Histogram(min, max, steps), new Stats<T>(options))\n        { }\n\n        #endregion\n\n        #region Operations\n\n        public void AddLog10Hist(double value, T data)\n        {\n            Histogram.AddLog10(value);\n            Stats.Add(value, data);\n        }\n\n        public void AddLog2Hist(double value, T data)\n        {\n            Histogram.AddLog2(value);\n            Stats.Add(value, data);\n        }\n\n        public void Add(double value, T data)\n        {\n            Histogram.Add(value);\n            Stats.Add(value, data);\n        }\n\n        public void Add(HistogramAndStats<T> hs)\n        {\n            Histogram.Add(hs.Histogram);\n            Stats.Add(hs.Stats);\n        }\n\n        public static HistogramAndStats<T> operator +(HistogramAndStats<T> hs0, HistogramAndStats<T> hs1)\n        {\n            return new HistogramAndStats<T>(hs0.Histogram + hs1.Histogram, hs0.Stats + hs1.Stats);\n        }\n\n        #endregion\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Base/WeightedIndex.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// A structure holding a double weight and an index.\n    /// </summary>\n    public struct WeightedIndex\n    {\n        public double Weight;\n        public int Index;\n\n        #region Constructor\n\n        public WeightedIndex(double weight, int index)\n        {\n            Weight = weight;\n            Index = index;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Colors/Color.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Text.RegularExpressions;\n\nnamespace Aardvark.Base\n{\n    #region Col\n\n    /// <summary>\n    /// A static container class that provides functionality for dealing with\n    /// colors. It is intentionally named Col in order to avoid a collision\n    /// with the system provided Color class.\n    /// </summary>\n    [Serializable]\n    public static partial class Col\n    {\n        #region Space\n\n        [Serializable]\n        public enum Space\n        {\n            None,\n            SRGB,\n            LinearSRGB,\n            XYZ,\n        }\n\n        #endregion\n\n        #region Format\n\n        [Serializable]\n        public enum Format\n        {\n            None,\n            Alpha,\n            BW,\n            Gray,\n            GrayAlpha,\n            RGB,\n            BGR,\n            RGBA,\n            BGRA,\n\n            /// <summary>\n            /// RGB with premultiplied alpha.\n            /// </summary>\n            RGBP,\n\n            /// <summary>\n            /// BGR with premultiplied alpha.\n            /// </summary>\n            BGRP,\n\n            // TODO:\n\n            CieXYZ,\n            CieYxy,\n            CieLab,\n            CieLuv,\n            Yuv,\n\n            HSL,\n            HSV,\n\n            RG,\n        }\n\n        #endregion\n\n        #region Channel\n\n        [Serializable]\n        public enum Channel\n        {\n            BW,\n            Gray,\n            Red,\n            Green,\n            Blue,\n            Alpha,\n            PremultipliedAlpha,\n\n            // TODO:\n\n            CieX,\n            CieY,\n            CieZ,\n            Ciex,\n            Ciey,\n            Cieu,\n            Ciev,\n            CieL,\n            Ciea,\n            Cieb,\n            L,\n            H,\n            S,\n            V,\n            Y,\n            u,\n            v,\n        }\n\n        #endregion\n\n        #region Maximal Value Constants\n\n        public static class Info<T>\n        {\n            public static readonly T MaxValue;\n\n            static Info()\n            {\n                if (typeof(T) == typeof(bool))\n                {\n                    MaxValue = (T)(object)true;\n                }\n                else if (typeof(T) == typeof(byte))\n                {\n                    MaxValue = (T)(object)(byte)255;\n                }\n                else if (typeof(T) == typeof(ushort))\n                {\n                    MaxValue = (T)(object)ushort.MaxValue;\n                }\n                else if (typeof(T) == typeof(uint))\n                {\n                    MaxValue = (T)(object)uint.MaxValue;\n                }\n                else if (typeof(T) == typeof(float))\n                {\n                    MaxValue = (T)(object)1.0f;\n                }\n                else if (typeof(T) == typeof(double))\n                {\n                    MaxValue = (T)(object)1.0;\n                }\n            }\n        };\n\n        #endregion\n\n        #region Table-Driven Query Methods\n\n        public static class Name\n        {\n            public static readonly Symbol BW = \"BW\";\n            public static readonly Symbol Gray = \"Gray\";\n            public static readonly Symbol Alpha = \"Alpha\";\n\n            public static readonly Symbol GrayAlpha = \"GrayAlpha\";\n\n            public static readonly Symbol RG = \"RG\";\n            public static readonly Symbol RGB = \"RGB\";\n            public static readonly Symbol BGR = \"BGR\";\n            public static readonly Symbol RGBA = \"RGBA\";\n            public static readonly Symbol BGRA = \"BGRA\";\n            public static readonly Symbol RGBP = \"RGBP\";\n            public static readonly Symbol BGRP = \"BGRP\";\n\n            // TODO:\n\n            public static readonly Symbol CieXYZ = \"CieXYZ\";\n            public static readonly Symbol CieYxy = \"CieYxy\";\n            public static readonly Symbol CieLab = \"CieLab\";\n            public static readonly Symbol CieLuv = \"CieLuv\";\n            public static readonly Symbol Yuv = \"Yuv\";\n            public static readonly Symbol HSL = \"HSL\";\n            public static readonly Symbol HSV = \"HSV\";\n        };\n\n        public static class Intent\n        {\n            public static readonly Symbol BW = \"BW\";\n            public static readonly Symbol Gray = \"Gray\";\n            public static readonly Symbol Alpha = \"Alpha\";\n\n            public static readonly Symbol GrayAlpha = \"GrayAlpha\";\n\n            public static readonly Symbol RG = \"RG\";\n            public static readonly Symbol RGB = \"RGB\";\n            public static readonly Symbol BGR = \"BGR\";\n            public static readonly Symbol RGBA = \"RGBA\";\n            public static readonly Symbol BGRA = \"BGRA\";\n\n            // TODO:\n\n            public static readonly Symbol CieXYZ = \"CieXYZ\";\n            public static readonly Symbol CieYxy = \"CieYxy\";\n            public static readonly Symbol CieLab = \"CieLab\";\n            public static readonly Symbol CieLuv = \"CieLuv\";\n            public static readonly Symbol Yuv = \"Yuv\";\n            public static readonly Symbol HSL = \"HSL\";\n            public static readonly Symbol HSV = \"HSV\";\n        };\n\n        private static readonly (Col.Format, Symbol, Symbol, int)[] s_colFormatArray =\n            new[]\n            {\n                (Format.BW,   Name.BW,   Intent.BW,   1),\n                (Format.Gray, Name.Gray, Intent.Gray, 1),\n                (Format.Alpha, Name.Alpha, Intent.Alpha, 1),\n\n                (Format.GrayAlpha, Name.GrayAlpha, Intent.GrayAlpha, 2),\n\n                (Format.RG,   Name.RG,   Intent.RG,   2),\n                (Format.RGB,  Name.RGB,  Intent.RGB,  3),\n                (Format.BGR,  Name.BGR,  Intent.BGR,  3),\n                (Format.RGBA, Name.RGBA, Intent.RGBA, 4),\n                (Format.BGRA, Name.BGRA, Intent.BGRA, 4),\n                (Format.RGBP, Name.RGBP, Intent.RGBA, 4),\n                (Format.BGRP, Name.BGRP, Intent.BGRA, 4),\n\n                (Format.CieXYZ,  Name.CieXYZ,  Intent.CieXYZ,  3),\n                (Format.CieYxy,  Name.CieYxy,  Intent.CieYxy,  3),\n                (Format.CieLab,  Name.CieLab,  Intent.CieLab,  3),\n                (Format.CieLuv,  Name.CieLuv,  Intent.CieLuv,  3),\n                (Format.Yuv,  Name.Yuv,  Intent.Yuv,  3),\n                (Format.HSL,  Name.HSL,  Intent.HSL,  3),\n                (Format.HSV,  Name.HSV,  Intent.HSV,  3),\n\n            };\n\n        static Col()\n        {\n            var count = s_colFormatArray.Length;\n            s_nameOfFormat = new Dict<Format, Symbol>(count);\n            s_formatOfName = new SymbolDict<Format>(count);\n            s_intentOfFormat = new Dict<Format, Symbol>(count);\n            s_channelCountMap = new Dict<Format, int>(count);\n            foreach (var t in s_colFormatArray)\n            {\n                var format = t.Item1; var name = t.Item2; var intent = t.Item3; var channelCount = t.Item4;\n                s_nameOfFormat.Add(format, intent);\n                s_formatOfName.Add(name, format);\n                s_intentOfFormat.Add(format, intent);\n                s_channelCountMap.Add(format, channelCount);\n            }\n        }\n\n        private static readonly Dict<Format, Symbol> s_nameOfFormat = null;\n        private static readonly SymbolDict<Format> s_formatOfName = null;\n        private static readonly Dict<Format, Symbol> s_intentOfFormat = null;\n        private static readonly Dict<Format, int> s_channelCountMap = null;\n\n        public static Symbol GetName(this Format format)\n        {\n            return s_nameOfFormat[format];\n        }\n\n        public static Format FormatOfName(Symbol name)\n        {\n            return s_formatOfName[name];\n        }\n\n        public static Symbol GetIntent(this Format format)\n        {\n            return s_intentOfFormat[format];\n        }\n\n        public static bool IsPremultiplied(this Format format)\n        {\n            return format == Format.RGBP || format == Format.BGRP;\n        }\n\n        public static int ChannelCount(this Format format)\n        {\n            return s_channelCountMap[format];\n        }\n\n        private static readonly Dict<Format, Channel[]> s_formatChannelsMap =\n            new Dict<Format, Channel[]>()\n            {\n                { Format.BW, new[] { Channel.BW } },\n                { Format.Gray, new[] { Channel.Gray } },\n                { Format.Alpha, new[] { Channel.Alpha } },\n\n                { Format.GrayAlpha, new[] { Channel.Gray, Channel.Alpha } },\n\n                { Format.RG, new[] { Channel.Red, Channel.Green } },\n                { Format.RGB, new[] { Channel.Red, Channel.Green, Channel.Blue } },\n                { Format.BGR, new[] { Channel.Blue, Channel.Green, Channel.Red } },\n                { Format.RGBA, new[] { Channel.Red, Channel.Green, Channel.Blue, Channel.Alpha } },\n                { Format.BGRA, new[] { Channel.Blue, Channel.Green, Channel.Red, Channel.Alpha } },\n                { Format.RGBP, new[] { Channel.Red, Channel.Green, Channel.Blue, Channel.PremultipliedAlpha } },\n                { Format.BGRP, new[] { Channel.Blue, Channel.Green, Channel.Red, Channel.PremultipliedAlpha } },\n\n                { Format.CieXYZ, new[] { Channel.CieX, Channel.CieY, Channel.CieZ } },\n                { Format.CieYxy, new[] { Channel.CieY, Channel.Ciex, Channel.Ciey } },\n                { Format.CieLab, new[] { Channel.CieL, Channel.Ciea, Channel.Cieb } },\n                { Format.CieLuv, new[] { Channel.CieL, Channel.Cieu, Channel.Ciev } },\n\n                { Format.HSL, new[] { Channel.H, Channel.S, Channel.L } },\n                { Format.HSV, new[] { Channel.H, Channel.S, Channel.V } },\n                { Format.Yuv, new[] { Channel.Y, Channel.u, Channel.v } },\n            };\n\n        public static Channel[] ChannelsOfFormat(this Format format)\n        {\n            Channel[] channels;\n            if (s_formatChannelsMap.TryGetValue(format, out channels))\n                return channels;\n            throw new ArgumentException($\"Channels of format {format} not defined.\");\n        }\n\n        private static readonly Dict<Format, long[]> s_channelOrderMap =\n            new Dict<Format, long[]>()\n            {\n                { Format.BW, new[] { 0L } },\n                { Format.Gray, new[] { 0L } },\n                { Format.Alpha, new[] { 0L } },\n\n                { Format.GrayAlpha, new[] { 0L, 1L } },\n\n                { Format.RG, new[] { 0L, 1L } },\n                { Format.RGB, new[] { 0L, 1L, 2L } },\n                { Format.BGR, new[] { 2L, 1L, 0L } },\n                { Format.RGBA, new[] { 0L, 1L, 2L, 3L } },\n                { Format.BGRA, new[] { 2L, 1L, 0L, 3L } },\n                { Format.RGBP, new[] { 0L, 1L, 2L, 3L } },\n                { Format.BGRP, new[] { 2L, 1L, 0L, 3L } },\n\n                { Format.CieXYZ, new[] { 0L, 1L, 2L } },\n                { Format.CieYxy, new[] { 0L, 1L, 2L } },\n                { Format.CieLab, new[] { 0L, 1L, 2L } },\n                { Format.CieLuv, new[] { 0L, 1L, 2L } },\n\n                { Format.HSL, new[] { 0L, 1L, 2L } },\n                { Format.HSV, new[] { 0L, 1L, 2L } },\n                { Format.Yuv, new[] { 0L, 1L, 2L } },\n            };\n\n        public static long[] ChannelOrder(this Format format)\n        {\n            return s_channelOrderMap[format];\n        }\n\n        private static readonly Dict<(Format, Channel), long> s_channelIndexMap =\n            new Dict<(Format, Channel), long>()\n            {\n                { (Format.BW, Channel.BW), 0L },\n                { (Format.Gray, Channel.Gray), 0L },\n                { (Format.Alpha, Channel.Alpha), 0L },\n\n                { (Format.GrayAlpha, Channel.Gray), 0L },\n                { (Format.GrayAlpha, Channel.Alpha), 1L },\n\n                { (Format.RG, Channel.Red), 0L },\n                { (Format.RG, Channel.Green), 1L },\n\n                { (Format.RGB, Channel.Red), 0L },\n                { (Format.RGB, Channel.Green), 1L },\n                { (Format.RGB, Channel.Blue), 2L },\n\n                { (Format.BGR, Channel.Blue), 0L },\n                { (Format.BGR, Channel.Green), 1L },\n                { (Format.BGR, Channel.Red), 2L },\n\n                { (Format.RGBA, Channel.Red), 0L },\n                { (Format.RGBA, Channel.Green), 1L },\n                { (Format.RGBA, Channel.Blue), 2L },\n                { (Format.RGBA, Channel.Alpha), 3L },\n\n                { (Format.BGRA, Channel.Blue), 0L },\n                { (Format.BGRA, Channel.Green), 1L },\n                { (Format.BGRA, Channel.Red), 2L },\n                { (Format.BGRA, Channel.Alpha), 3L },\n\n                { (Format.RGBP, Channel.Red), 0L },\n                { (Format.RGBP, Channel.Green), 1L },\n                { (Format.RGBP, Channel.Blue), 2L },\n                { (Format.RGBP, Channel.PremultipliedAlpha), 3L },\n\n                { (Format.BGRP, Channel.Blue), 0L },\n                { (Format.BGRP, Channel.Green), 1L },\n                { (Format.BGRP, Channel.Red), 2L },\n                { (Format.BGRP, Channel.PremultipliedAlpha), 3L },\n\n                { (Format.CieXYZ, Channel.CieX), 0L },\n                { (Format.CieXYZ, Channel.CieY), 1L },\n                { (Format.CieXYZ, Channel.CieZ), 2L },\n\n                { (Format.CieYxy, Channel.CieY), 0L },\n                { (Format.CieYxy, Channel.Ciex), 1L },\n                { (Format.CieYxy, Channel.Ciey), 2L },\n\n                { (Format.CieLab, Channel.CieL), 0L },\n                { (Format.CieLab, Channel.Ciea), 1L },\n                { (Format.CieLab, Channel.Cieb), 2L },\n\n                { (Format.CieLuv, Channel.CieL), 0L },\n                { (Format.CieLuv, Channel.Cieu), 1L },\n                { (Format.CieLuv, Channel.Ciev), 2L },\n\n                { (Format.HSL, Channel.H), 0L },\n                { (Format.HSL, Channel.S), 1L },\n                { (Format.HSL, Channel.L), 2L },\n\n                { (Format.HSV, Channel.H), 0L },\n                { (Format.HSV, Channel.S), 1L },\n                { (Format.HSV, Channel.V), 2L },\n\n                { (Format.Yuv, Channel.Y), 0L },\n                { (Format.Yuv, Channel.u), 1L },\n                { (Format.Yuv, Channel.v), 2L },\n            };\n\n\n        public static long ChannelIndex(this Format format, Channel channel)\n        {\n            if (s_channelIndexMap.TryGetValue((format, channel),\n                                              out long index))\n                return index;\n            throw new ArgumentException($\"Format {format} does not contain channel {channel}.\");\n        }\n\n        public static long ChannelIndexNoThrow(this Format format, Channel channel)\n        {\n            long index;\n            if (s_channelIndexMap.TryGetValue((format, channel),\n                                              out index))\n                return index;\n            return -1;\n        }\n\n        public static Format FormatDefaultOf(this Type type, long channelCount)\n        {\n            return channelCount switch\n            {\n                1 => Format.Gray,\n                2 => Format.RG,\n                3 => (type == typeof(byte)) ? Format.BGR : Format.RGB,\n                4 => (type == typeof(byte)) ? Format.BGRA : Format.RGBA,\n                _ => throw new ArgumentException($\"No default format for {type} with {channelCount} channels\"),\n            };\n        }\n\n        #endregion\n\n        #region Color Channel Conversion Constants\n\n        private const float c_floatToByte = 255.9999f;\n        private const float c_byteToFloat = 1.0f / 255.0f;\n\n        private const double c_doubleToByte = 255.9999999999999;\n        private const double c_byteToDouble = 1.0 / 255.0;\n\n        private const float c_floatToUShort = 65535.99f;\n        private const float c_uShortToFloat = 1.0f / 65535.0f;\n\n        private const double c_doubleToUShort = 65535.99999999999;\n        private const double c_uShortToDouble = 1.0 / 65535.0;\n\n        private const double c_floatToUIntAsDouble = 4294967295.999999;\n        private const double c_uIntToFloatAsDouble = 1.0 / 4294967295.0;\n\n        private const double c_doubleToUInt = 4294967295.999999;\n        private const double c_uIntToDouble = 1.0 / 4294967295.0;\n\n        #endregion\n\n        #region Color Channel Conversions between Byte, UShort, UInt, float, and double\n\n        #region Byte\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort ByteToUShort(this byte b) => (ushort)(257 * b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint ByteToUInt(this byte b) => 0x1010101u * (uint)b;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half ByteToHalf(this byte b) => (Half)(c_byteToFloat * (float)b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ByteToFloat(this byte b) => c_byteToFloat * (float)b;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ByteToDouble(this byte b) => c_byteToDouble * (double)b;\n\n        #endregion\n\n        #region UShort\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte UShortToByte(this ushort us) => (byte)(us >> 8);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint UShortToUInt(this ushort us) => 65537u * (uint)us;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half UShortToHalf(this ushort us) => (Half)(c_uShortToFloat * (float)us);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float UShortToFloat(this ushort us) => c_uShortToFloat * (float)us;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double UShortToDouble(this ushort us) => c_uShortToDouble * (double)us;\n\n        #endregion\n\n        #region UInt\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte UIntToByte(this uint ui) => (byte)(ui >> 24);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort UIntToUShort(this uint ui) => (ushort)(ui >> 16);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half UIntToHalf(this uint ui) => (Half)(c_uIntToFloatAsDouble * ui);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float UIntToFloat(this uint ui) => (float)(c_uIntToFloatAsDouble * ui);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double UIntToDouble(this uint ui) => c_uIntToDouble * (double)ui;\n\n        #endregion\n\n        #region Half\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte HalfToByte(this Half f) => (byte)(c_floatToByte * f);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort HalfToUShort(this Half f) => (ushort)(c_floatToUShort * f);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint HalfToUInt(this Half f) => (uint)(c_floatToUIntAsDouble * f);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float HalfToFloat(this Half f) => (float)f;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double HalfToDouble(this Half f) => (double)f;\n\n        #endregion\n\n        #region Float\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte FloatToByte(this float f) => (byte)(c_floatToByte * f);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte FloatToByteClamped(this float f) => (byte)(c_floatToByte * f).Clamp(0, 255);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort FloatToUShort(this float f) => (ushort)(c_floatToUShort * f);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort FloatToUShortClamped(this float f) => (ushort)(c_floatToUShort * f).Clamp(0, 65535);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint FloatToUInt(this float f) => (uint)(c_floatToUIntAsDouble * f);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint FloatToUIntClamped(this float f) => (uint)(c_floatToUIntAsDouble * f).Clamp(0, 4294967295);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half FloatToHalf(this float f) => (Half)f;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double FloatToDouble(this float f) => (double)f;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double FloatToDoubleClamped(this float f) => ((double)f).Clamp(0, 1);\n\n        #endregion\n\n        #region Double\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte DoubleToByte(this double d) => (byte)(c_doubleToByte * d);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte DoubleToByteClamped(this double d) => (byte)(c_doubleToByte * d).Clamp(0, 255);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort DoubleToUShort(this double d) => (ushort)(c_doubleToUShort * d);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort DoubleToUShortClamped(this double d) => (ushort)(c_doubleToUShort * d).Clamp(0, 65535);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DoubleToUInt(this double d) => (uint)(c_doubleToUInt * d);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DoubleToUIntClamped(this double d) => (uint)(c_doubleToUInt * d).Clamp(0, 4294967295);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half DoubleToHalf(this double d) => (Half)d;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DoubleToFloat(this double d) => (float)d;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DoubleToFloatClamped(this double d) => ((float)d).Clamp(0, 1);\n\n        #endregion\n\n        #endregion\n\n        #region Special Color Channel Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ByteInIntToFloat(this int i) { return (float)i * c_byteToFloat; }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int FloatToByteInInt(this float f) { return (int)(f * c_floatToByte); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ByteInIntToDouble(this int i) { return (double)i * c_byteToDouble; }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DoubleToByteInInt(this double d) { return (int)(d * c_doubleToByte); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double UShortInIntToDouble(this int i) { return (double)i * c_uShortToDouble; }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DoubleToUShortInInt(this double d) { return (int)(d * c_doubleToUShort); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte BitInByteToByte(this byte b) { return (byte)(b * 255); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ByteToBitInByte(this byte b) { return (byte)(b >> 7); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ByteInFloatToByte(this float f) { return (byte)(f + 0.5f); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ByteInDoubleToByte(this double d) { return (byte)(d + 0.5); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort UShortInFloatToUShort(this float f) { return (ushort)(f + 0.5f); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort UShortInDoubleToUShort(this double d) { return (ushort)(d + 0.5); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint UIntInDoubleToUInt(this double d) { return (uint)(d + 0.5); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int FloatToByteInIntClamped(this float f) { return (int)(f * c_floatToByte).Clamp(0, 255); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DoubleToUShortInIntClamped(this double d) { return (int)(d * c_doubleToUShort).Clamp(0, 65535); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ByteInFloatToByteClamped(this float f) { return (byte)(f.Clamp(0.0f, 255.0f) + 0.5f); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ByteInDoubleToByteClamped(this double d) { return (byte)(d.Clamp(0.0, 255.0) + 0.5); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort UShortInFloatToUShortClamped(this float f) { return (ushort)(f.Clamp(0.0f, 65535.0f) + 0.5f); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort UShortInDoubleToUShortClamped(this double d) { return (ushort)(d.Clamp(0.0, 65535.0) + 0.5); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint UIntInDoubleToUIntClamped(this double d) { return (uint)(d.Clamp(0.0, (double)uint.MaxValue) + 0.5); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ByteInFloatToFloat(this float f) { return f * c_byteToFloat; }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float FloatToByteInFloat(this float f) { return f * c_floatToByte; }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ByteInDoubleToDouble(this double d) { return d * c_byteToDouble; }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DoubleToByteInDouble(this double d) { return d * c_doubleToByte; }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ByteInFloatToFloatClamped(this float f) { return f.ByteInFloatToFloat().Clamp(0, 1); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float FloatToByteInFloatClamped(this float f) { return f.FloatToByteInFloat().Clamp(0, 255); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ByteInDoubleToDoubleClamped(this double d) { return d.ByteInDoubleToDouble().Clamp(0, 1); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DoubleToByteInDoubleClamped(this double d) { return d.DoubleToByteInDouble().Clamp(0, 255); }\n\n        #endregion\n\n        #region Color to Gray Conversion Constants\n\n        private const double c_grayDoubleRed   = 0.2989;\n        private const double c_grayDoubleGreen = 0.5870;\n        private const double c_grayDoubleBlue  = 0.1140;\n\n        private const float c_grayFloatRed     = (float)c_grayDoubleRed;\n        private const float c_grayFloatGreen   = (float)c_grayDoubleGreen;\n        private const float c_grayFloatBlue    = (float)c_grayDoubleBlue;\n\n        // 65793 == 65536 * 255.99998/255\n        private const int c_grayByteRed   = (int)(65793 * c_grayDoubleRed);\n        private const int c_grayByteGreen = (int)(65793 * c_grayDoubleGreen);\n        private const int c_grayByteBlue  = (int)(65793 * c_grayDoubleBlue);\n\n        // 4295032833 == 4294967296 * 65535.99999999999/65535\n        private const long c_grayUShortRed   = (long)(4295032833L * c_grayDoubleRed);\n        private const long c_grayUShortGreen = (long)(4295032833L * c_grayDoubleGreen);\n        private const long c_grayUShortBlue  = (long)(4295032833L * c_grayDoubleBlue);\n\n        #endregion\n\n        #region Color to Gray Conversions\n\n        #region Byte\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ToGrayByte(byte r, byte g, byte b)\n            => (byte)((r * c_grayByteRed + g * c_grayByteGreen + b * c_grayByteBlue) >> 16);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ToGrayByte(this C3b c) => ToGrayByte(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static byte ToGrayByte(this C4b c) => ToGrayByte(c.R, c.G, c.B);\n\n        #endregion\n\n        #region UShort\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort ToGrayUShort(ushort r, ushort g, ushort b)\n            => (ushort)((r * c_grayUShortRed + g * c_grayUShortGreen + b * c_grayUShortBlue) >> 32);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort ToGrayUShort(this C3us c) => ToGrayUShort(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static ushort ToGrayUShort(this C4us c) => ToGrayUShort(c.R, c.G, c.B);\n\n        #endregion\n\n        #region UInt\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint ToGrayUInt(uint r, uint g, uint b)\n            => DoubleToUInt(ToGrayDoubleClamped(UIntToDouble(r), UIntToDouble(g), UIntToDouble(b)));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint ToGrayUInt(this C3ui c) => ToGrayUInt(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint ToGrayUInt(this C4ui c) => ToGrayUInt(c.R, c.G, c.B);\n\n        #endregion\n\n        #region Half\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half ToGrayHalf(Half r, Half g, Half b)\n            => (Half)ToGrayFloat(r, g, b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Half ToGrayHalfClamped(Half r, Half g, Half b)\n            => (Half)ToGrayFloatClamped(r, g, b);\n\n        #endregion\n\n        #region Float\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ToGrayFloat(float r, float g, float b)\n            => r * c_grayFloatRed + g * c_grayFloatGreen + b * c_grayFloatBlue;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ToGrayFloat(this C3f c) => ToGrayFloat(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ToGrayFloat(this C4f c) => ToGrayFloat(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ToGrayFloatClamped(float r, float g, float b)\n            => ToGrayFloat(r, g, b).Clamp(0, 1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ToGrayFloatClamped(this C3f c) => ToGrayFloatClamped(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ToGrayFloatClamped(C4f c) => ToGrayFloatClamped(c.R, c.G, c.B);\n\n        #endregion\n\n        #region Double\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ToGrayDouble(double r, double g, double b)\n            => r * c_grayDoubleRed + g * c_grayDoubleGreen + b * c_grayDoubleBlue;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ToGrayDouble(this C3d c) => ToGrayDouble(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ToGrayDouble(this C4d c) => ToGrayDouble(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ToGrayDoubleClamped(double r, double g, double b)\n            => ToGrayDouble(r, g, b).Clamp(0, 1);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ToGrayDoubleClamped(this C3d c) => ToGrayDoubleClamped(c.R, c.G, c.B);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double ToGrayDoubleClamped(C4d c) => ToGrayDoubleClamped(c.R, c.G, c.B);\n\n        #endregion\n\n        #endregion\n\n        #region Alpha to premultiplied Alpha and back\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b AlphaToPremultipliedAlpha(this C4b c)\n        {\n            var f = c_byteToDouble * (double)c.A;\n            return new C4b((byte)(f * c.R), (byte)(f * c.G), (byte)(f * c.B), c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b PremultipliedAlphaToAlpha(this C4b c)\n        {\n            if (c.A == 0) return new C4b(0, 0, 0, 0);\n            var f = 1.0 / (c_byteToDouble * (double)c.A);\n            return new C4b((byte)(f * c.R), (byte)(f * c.G), (byte)(f * c.B), c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us AlphaToPremultipliedAlpha(this C4us c)\n        {\n            var f = c_uShortToDouble * (double)c.A;\n            return new C4us((ushort)(f * c.R), (ushort)(f * c.G), (ushort)(f * c.B), c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us PremultipliedAlphaToAlpha(this C4us c)\n        {\n            if (c.A == 0) return new C4us(0, 0, 0, 0);\n            var f = 1.0 / (c_uShortToDouble * (double)c.A);\n            return new C4us((ushort)(f * c.R), (ushort)(f * c.G), (ushort)(f * c.B), c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui AlphaToPremultipliedAlpha(this C4ui c)\n        {\n            var f = c_uIntToDouble * (double)c.A;\n            return new C4ui((uint)(f * c.R), (uint)(f * c.G), (uint)(f * c.B), c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui PremultipliedAlphaToAlpha(this C4ui c)\n        {\n            if (c.A == 0) return new C4ui(0, 0, 0, 0);\n            var f = 1.0 / (c_uIntToDouble * (double)c.A);\n            return new C4ui((uint)(f * c.R), (uint)(f * c.G), (uint)(f * c.B), c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f AlphaToPremultipliedAlpha(this C4f c)\n        {\n            return new C4f(c.R * c.A, c.G * c.A, c.B * c.A, c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f PremultipliedAlphaToAlpha(this C4f c)\n        {\n            if (c.A == 0.0f) return new C4f(0.0f, 0.0f, 0.0f, 0.0f);\n            return new C4f(c.R / c.A, c.G / c.A, c.B / c.A, c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d AlphaToPremultipliedAlpha(this C4d c)\n        {\n            return new C4d(c.R * c.A, c.G * c.A, c.B * c.A, c.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d PremultipliedAlphaToAlpha(this C4d c)\n        {\n            if (c.A == 0.0) return new C4d(0.0, 0.0, 0.0, 0.0);\n            return new C4d(c.R / c.A, c.G / c.A, c.B / c.A, c.A);\n        }\n\n        #endregion\n\n        #region SRGB/Linear SRGB/CieXYZ/CieLab/CieYxy Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinearSRGBFloatToSRGBFloat(this float c)\n            => (float)(c <= 0.0031308 ? c * 12.92 : 1.055 * Fun.Pow(c, 1.0 / 2.4) - 0.055);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float SRGBFloatToLinearSRGBFloat(this float c)\n            => (float)(c <= 0.04045 ? c / 12.92 : Fun.Pow((c + 0.055) / 1.055, 2.4));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinearSRGBToSRGB(this C3f c)\n        {\n            return new C3f(c.R <= 0.0031308 ? c.R * 12.92 : 1.055 * Fun.Pow(c.R, 1.0 / 2.4) - 0.055,\n                           c.G <= 0.0031308 ? c.G * 12.92 : 1.055 * Fun.Pow(c.G, 1.0 / 2.4) - 0.055,\n                           c.B <= 0.0031308 ? c.B * 12.92 : 1.055 * Fun.Pow(c.B, 1.0 / 2.4) - 0.055);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinearSRGBAToSRGBA(this C4f c)\n        {\n            return new C4f(c.R <= 0.0031308 ? c.R * 12.92 : 1.055 * Fun.Pow(c.R, 1.0 / 2.4) - 0.055,\n                           c.G <= 0.0031308 ? c.G * 12.92 : 1.055 * Fun.Pow(c.G, 1.0 / 2.4) - 0.055,\n                           c.B <= 0.0031308 ? c.B * 12.92 : 1.055 * Fun.Pow(c.B, 1.0 / 2.4) - 0.055,\n                           c.A <= 0.0031308 ? c.A * 12.92 : 1.055 * Fun.Pow(c.A, 1.0 / 2.4) - 0.055);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f SRGBToLinearSRGB(this C3f c)\n        {\n            return new C3f(c.R <= 0.04045 ? c.R / 12.92 : Fun.Pow((c.R + 0.055) / 1.055, 2.4),\n                           c.G <= 0.04045 ? c.G / 12.92 : Fun.Pow((c.G + 0.055) / 1.055, 2.4),\n                           c.B <= 0.04045 ? c.B / 12.92 : Fun.Pow((c.B + 0.055) / 1.055, 2.4));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f SRGBAToLinearSRGBA(this C4f c)\n        {\n            return new C4f(c.R <= 0.04045 ? c.R / 12.92 : Fun.Pow((c.R + 0.055) / 1.055, 2.4),\n                           c.G <= 0.04045 ? c.G / 12.92 : Fun.Pow((c.G + 0.055) / 1.055, 2.4),\n                           c.B <= 0.04045 ? c.B / 12.92 : Fun.Pow((c.B + 0.055) / 1.055, 2.4),\n                           c.A <= 0.04045 ? c.A / 12.92 : Fun.Pow((c.A + 0.055) / 1.055, 2.4));\n        }\n\n        /// <summary>\n        /// Convert linear SRGB with channel values in the range [0.0, 1.0] to XYZ.\n        /// SRGB white (1, 1, 1) is converted to XYZ white (0.9505, 1.0000, 1.0890)\n        /// at D65 with unit luminance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinearSRGBToXYZinC3f(this C3f c)\n        {\n            return new C3f(0.4124 * c.R + 0.3576 * c.G + 0.1805 * c.B,\n                           0.2126 * c.R + 0.7152 * c.G + 0.0722 * c.B,\n                           0.0193 * c.R + 0.1192 * c.G + 0.9505 * c.B);\n        }\n\n        /// <summary>\n        /// Convert XYZ to linear SRGB with channel values in the range [0.0, 1.0].\n        /// XYZ white (0.9505, 1.0000, 1.0890) at D65 with unit luminance is\n        /// converted to SRGB white (1, 1, 1)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f XYZinC3fToLinearSRGB(this C3f c)\n        {\n            return new C3f(3.2406 * c.R - 1.5372 * c.G - 0.4986 * c.B,\n                          -0.9689 * c.R + 1.8758 * c.G + 0.0415 * c.B,\n                           0.0557 * c.R - 0.2040 * c.G + 1.0570 * c.B);\n        }\n\n        /// <summary>\n        /// Convert XYZ to CIE RGB with channel values in the range [0.0, 1.0].\n        /// XYZ white (1, 1, 1) is converted to (1, 1, 1).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f XYZinC3fToCIERGB(this C3f c)\n        {\n            return new C3f( 2.3706743 * c.R - 0.9000405 * c.G - 0.4706338 * c.B,\n                           -0.5138850 * c.R + 1.4253036 * c.G + 0.0885814 * c.B,\n                            0.0052982 * c.R - 0.0146949 * c.G + 1.0093968 * c.B);\n        }\n\n        /// <summary>\n        /// Convert SRGB with channel values in the range [0.0, 1.0] to XYZ.\n        /// SRGB white (1, 1, 1) is converted to XYZ white (0.9505, 1.0000, 1.0890)\n        /// at D65 with unit luminance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f SRGBToXYZinC3f(this C3f c) { return c.SRGBToLinearSRGB().LinearSRGBToXYZinC3f(); }\n\n        /// <summary>\n        /// Convert XYZ to SRGB with channel values in the range [0.0, 1.0].\n        /// XYZ white (0.9505, 1.0000, 1.0890) at D65 with unit luminance is\n        /// converted to SRGB white (1, 1, 1)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f XYZinC3fToSRGB(this C3f c) { return c.XYZinC3fToLinearSRGB().LinearSRGBToSRGB(); }\n\n        /// <summary>\n        /// Convert linear SRGBA with channel values in the range [0.0, 1.0] to XYZA.\n        /// SRGB white (1, 1, 1) is converted to XYZA white (0.9505, 1.0000, 1.0890)\n        /// at D65 with unit luminance. The alpha value is simply copied.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinearSRGBAToXYZAinC4f(this C4f c)\n        {\n            return new C4f(0.4124 * c.R + 0.3576 * c.G + 0.1805 * c.B,\n                           0.2126 * c.R + 0.7152 * c.G + 0.0722 * c.B,\n                           0.0193 * c.R + 0.1192 * c.G + 0.9505 * c.B,\n                           c.A);\n        }\n\n        /// <summary>\n        /// Convert XYZA to linear SRGBA with channel values in the range [0.0, 1.0].\n        /// XYZ white (0.9505, 1.0000, 1.0890) at D65 with unit luminance is\n        /// converted to SRGB white (1, 1, 1). The alpha value is simply copied.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f XYZAinC4fToLinearSRGBA(this C4f c)\n        {\n            return new C4f(3.2410 * c.R - 1.5374 * c.G - 0.4986 * c.B,\n                          -0.9692 * c.R + 1.876  * c.G + 0.0416 * c.B,\n                           0.0556 * c.R - 0.204  * c.G + 1.057  * c.B,\n                           c.A);\n        }\n\n        /// <summary>\n        /// Convert SRGBA with channel values in the range [0.0, 1.0] to XYZA.\n        /// SRGBA white (1, 1, 1) is converted to XYZA white (0.9505, 1.0000, 1.0890)\n        /// at D65 with unit luminance. The alpha value is subject to sRGB de-gamma\n        /// conversion.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f SRGBAToXYZAinC4f(this C4f c) { return c.SRGBAToLinearSRGBA().LinearSRGBAToXYZAinC4f(); }\n\n        /// <summary>\n        /// Convert XYZA to SRGBA with channel values in the range [0.0, 1.0].\n        /// XYZA white (0.9505, 1.0000, 1.0890) at D65 with unit luminance is\n        /// converted to SRGBA white (1, 1, 1). The alpha value is subject to\n        /// sRGB gamma conversion.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f XYZAinC4fToSRGBA(this C4f c) { return c.XYZAinC4fToLinearSRGBA().LinearSRGBAToSRGBA(); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf XYZinC3fToCieXYZf(this C3f c) { return new CieXYZf(c.R * 100.0, c.G * 100.0, c.B * 100.0); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf XYZAinC4fToCieXYZf(this C4f c) { return new CieXYZf(c.R * 100.0, c.G * 100.0, c.B * 100.0); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf LinearSRGBToCieXYZf(this C3f c) { return c.LinearSRGBToXYZinC3f().XYZinC3fToCieXYZf(); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf LinearSRGBAToCieXYZf(this C4f c) { return c.LinearSRGBAToXYZAinC4f().XYZAinC4fToCieXYZf(); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf SRGBToCieXYZf(this C3f c) { return c.SRGBToXYZinC3f().XYZinC3fToCieXYZf(); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf SRGBAToCieXYZf(this C4f c) { return c.SRGBAToXYZAinC4f().XYZAinC4fToCieXYZf(); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f ToXYZinC3f(this CieXYZf c) { return new C3f(c.X * 0.01f, c.Y * 0.01f, c.Z * 0.01f); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f ToXYZAinC4f(this CieXYZf c) { return new C4f(c.X * 0.01f, c.Y * 0.01f, c.Z * 0.01f); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f ToLinearSRGB(this CieXYZf c) { return c.ToXYZinC3f().XYZinC3fToLinearSRGB(); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f ToLinearSRGBA(this CieXYZf c) { return c.ToXYZAinC4f().XYZAinC4fToLinearSRGBA(); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f ToSRGB(this CieXYZf c) { return c. ToXYZinC3f().XYZinC3fToSRGB(); }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f ToSRGBA(this CieXYZf c) { return c.ToXYZAinC4f().XYZAinC4fToSRGBA(); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieYxyf ToCieYxyf(this CieXYZf c)\n        {\n            var s = c.X + c.Y + c.Z; return s > 0.0f ? new CieYxyf(c.Y, c.X / s, c.Y / s) : new CieYxyf(0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf ToCieXYZf(this CieYxyf c)\n        {\n            var s = c.y > 0.0 ? c.Y / c.y : 0.0; return new CieXYZf(s * c.x, c.Y, s * (1 - c.x - c.y));\n        }\n\n        private const double s_labF_t3 = (6 / 29.0) * (6 / 29.0) * (6 / 29.0);\n        private const double s_labF_t1 = (1 / 3.0) * (29 / 6.0) * (29 / 6.0);\n        private const double s_labF_t0 = 4 / 29.0;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static double s_labF(double t) { return t > s_labF_t3 ? Math.Pow(t, Constant.OneThird) : s_labF_t1 * t + s_labF_t0; }\n\n        private const double s_labFinv_t3 = 6 / 29.0;\n        private const double s_labFinv_t1 = 3.0 * (6 / 29.0) * (6 / 29.0);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static double s_labFinv(double t) { return t > s_labFinv_t3 ? t * t * t : s_labFinv_t1 * (t - s_labF_t0); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieLabf ToCieLabf(this CieXYZf c, CieXYZf white)\n        {\n            var fy = s_labF(c.Y / white.Y);\n            return new CieLabf( 116.0 * fy - 16.0, 500.0 * (s_labF(c.X / white.X) - fy), 200.0 * (fy - s_labF(c.Z / white.Z)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf ToCieXYZf(this CieLabf c, CieXYZf white)\n        {\n            var l = (c.L + 16.0) / 116.0;\n            return new CieXYZf(white.Y * s_labFinv(l), white.X * s_labFinv(l + c.a * 0.002), white.Z * s_labFinv(l - c.b * 0.005));\n        }\n\n        public static readonly Trafo2d ConeResponseDomain_XYZScaling = new Trafo2d(M33d.Identity, M33d.Identity);\n\n        public static readonly Trafo2d ConeResponseDomain_Bradford = new Trafo2d(new M33d(0.8951000, 0.2664000, -0.1614000,\n                                                                                         -0.7502000, 1.7135000, 0.0367000,\n                                                                                          0.0389000, -0.0685000, 1.0296000),\n                                                                                 new M33d(0.9869929, -0.1470543, 0.1599627,\n                                                                                          0.4323053, 0.5183603, 0.0492912,\n                                                                                         -0.0085287, 0.0400428, 0.9684867));\n\n        public static readonly Trafo2d ConeResponseDomain_VonKries = new Trafo2d(new M33d(0.4002400, 0.7076000, -0.0808100,\n                                                                                         -0.2263000, 1.1653200, 0.0457000,\n                                                                                          0.0000000, 0.0000000, 0.9182200),\n                                                                                 new M33d(1.8599364, -1.1293816, 0.2198974,\n                                                                                          0.3611914, 0.6388125, -0.0000064,\n                                                                                          0.0000000, 0.0000000, 1.0890636));\n\n        public static readonly CieXYZf CieXYZfAWhite = new CieXYZf(109.85, 100.0, 35.585);\n        public static readonly CieXYZf CieXYZfBWhite = new CieXYZf(99.072, 100.0, 85.223);\n        public static readonly CieXYZf CieXYZfCWhite = new CieXYZf(98.074, 100.0, 118.232);\n        public static readonly CieXYZf CieXYZfD50White = new CieXYZf(96.422, 100.0, 82.521);\n        public static readonly CieXYZf CieXYZfD55White = new CieXYZf(95.682, 100.0, 92.149);\n        public static readonly CieXYZf CieXYZfD65White = new CieXYZf(95.047, 100.0, 108.883);\n        public static readonly CieXYZf CieXYZfD75White = new CieXYZf(94.972, 100.0, 122.638);\n        public static readonly CieXYZf CieXYZfEWhite = new CieXYZf(100.0, 100.0, 100.0);\n        public static readonly CieXYZf CieXYZfF2White = new CieXYZf(99.186, 100.00, 67.393);\n        public static readonly CieXYZf CieXYZfF7White = new CieXYZf(95.041, 100.00, 108.747);\n        public static readonly CieXYZf CieXYZfF11White = new CieXYZf(100.962, 100.00, 64.350);\n\n        public static M33d BuildChromaticAdaptationMatrix(CieXYZf whiteFrom, CieXYZf whiteTo, Trafo2d coneResponseDomain)\n        {\n            // see: http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html\n\n            var responseSource = coneResponseDomain.Forward * new V3d(whiteFrom.X, whiteFrom.Y, whiteFrom.Z);\n            var responseTarget = coneResponseDomain.Forward * new V3d(whiteTo.X, whiteTo.Y, whiteTo.Z);\n            var det = responseTarget / responseSource;\n            var scaleMat = new M33d(det.X, 0, 0,\n                                    0, det.Y, 0,\n                                    0, 0, det.Z);\n            return coneResponseDomain.Backward * scaleMat * coneResponseDomain.Forward;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieLabf ToCieLabfD65(this CieXYZf c) { return ToCieLabf(c, CieXYZfD65White); }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static CieXYZf ToCieXYZfD65(this CieLabf c) { return ToCieXYZf(c, CieXYZfD65White); }\n\n        #endregion\n\n        #region HSL and HSV Conversions (see http://en.wikipedia.org/wiki/HSL_and_HSV)\n\n        public static HSLf ToHSLf(this C3f c)\n        {\n            double cr = 0.0, h6 = 0.0, l = 0.0;\n            if (c.R > c.G)\n            {\n                if (c.R > c.B)\n                {\n                    if (c.G > c.B)  { cr = c.R - c.B; l = 0.5 * (c.R + c.B); }  // R > G > B\n                    else            { cr = c.R - c.G; l = 0.5 * (c.R + c.G); }  // R > B >= G\n                    h6 = 0 + (c.G - c.B) / cr;\n                }\n                else                                                            // B >= R > G\n                {\n                    cr = c.B - c.G; l = 0.5 * (c.B + c.G);\n                    h6 = 4 + (c.R - c.G) / cr;\n                }\n            }\n            else                                                                // G >= R\n            {\n                if (c.G > c.B)\n                {\n                    if (c.R > c.B)  { cr = c.G - c.B; l = 0.5 * (c.G + c.B); }  // G >= R > B\n                    else            { cr = c.G - c.R; l = 0.5 * (c.G + c.R); }  // G > B >= R\n                    h6 = 2 + (c.B - c.R) / cr;\n                }\n                else                                                            // B >= G >= R\n                {\n                    cr = c.B - c.R; l = 0.5 * (c.B + c.R);\n                    if (cr > 0.0) h6 = 4 + (c.R - c.G) / cr;\n                }\n            }\n            return new HSLf(Fun.Frac(h6 * 1.0 / 6.0),\n                            cr > Constant<float>.PositiveTinyValue\n                                ? cr / (1.0 - Fun.Abs(2.0 * l - 1.0)) : 0.0,\n                            l);\n        }\n\n        public static HSVf ToHSVf(this C3f c)\n        {\n            double cr = 0.0, h6 = 0.0, v = 0.0;\n            if (c.R > c.G)\n            {\n                if (c.R > c.B)\n                {\n                    if (c.G > c.B)  cr = c.R - c.B;     // R > G > B\n                    else            cr = c.R - c.G;     // R > B >= G\n                    v = c.R; h6 = 0 + (c.G - c.B) / cr;\n                }\n                else                                    // B >= R > G\n                {\n                    cr = c.B - c.G; v = c.B;\n                    h6 = 4 + (c.R - c.G) / cr;\n                }\n            }\n            else                                        // G >= R\n            {\n                if (c.G > c.B)\n                {\n                    if (c.R > c.B)  cr = c.G - c.B;     // G >= R > B\n                    else            cr = c.G - c.R;     // G > B >= R\n                    v = c.G; h6 = 2 + (c.B - c.R) / cr;\n                }\n                else                                    // B >= G >= R\n                {\n                    cr = c.B - c.R; v = c.B;\n                    if (cr > 0.0) h6 = 4 + (c.R - c.G) / cr;\n                }\n            }\n            return new HSVf(Fun.Frac(h6 * 1.0 / 6.0),\n                            cr > Constant<float>.PositiveTinyValue ? cr / v : 0.0,\n                            v);\n        }\n\n        public static C3f ToC3f(this HSLf c)\n        {\n            double h = Fun.Frac(c.H);\n            var chr = (1.0 - Fun.Abs(2.0 * c.L - 1.0)) * c.S;\n            var x = chr * (1.0 - Fun.Abs(Fun.Frac(h * 3.0) * 2.0 - 1.0));\n            var m = c.L - 0.5 * chr;\n            switch ((int)(h * 6.0))\n            {\n                case 0: return new C3f(chr + m, x + m, m);\n                case 1: return new C3f(x + m, chr + m, m);\n                case 2: return new C3f(m, chr + m, x + m);\n                case 3: return new C3f(m, x + m, chr + m);\n                case 4: return new C3f(x + m, m, chr + m);\n                case 5: return new C3f(chr + m, m, x + m);\n                default: throw new ArgumentException(\"will never occur\");\n            }\n        }\n\n        public static C3f ToC3f(this HSVf c)\n        {\n            double h = Fun.Frac(c.H);\n            var chr = c.V * c.S;\n            var x = chr * (1.0 - Fun.Abs(Fun.Frac(h * 3.0) * 2.0 - 1.0));\n            var m = c.V - chr;\n            switch ((int)(h * 6.0))\n            {\n                case 0: return new C3f(chr + m, x + m, m);\n                case 1: return new C3f(x + m, chr + m, m);\n                case 2: return new C3f(m, chr + m, x + m);\n                case 3: return new C3f(m, x + m, chr + m);\n                case 4: return new C3f(x + m, m, chr + m);\n                case 5: return new C3f(chr + m, m, x + m);\n                default: throw new ArgumentException(\"will never occur\");\n            }\n        }\n\n        #endregion\n\n        #region Gamma Correction Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GammaFloatToLinearFloat(float c, double gamma)\n        {\n            return (float)Fun.Pow(c, gamma);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LinearFloatToGammaFloat(float c, double gamma)\n        {\n            double inverseGamma = 1.0 / gamma;\n            return (float)Fun.Pow(c, inverseGamma);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f GammaToLinear(this C3f c, double gamma)\n        {\n            return new C3f(Fun.Pow(c.R, gamma), Fun.Pow(c.G, gamma), Fun.Pow(c.B, gamma));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f GammaToLinear(this C4f c, double gamma)\n        {\n            return new C4f(Fun.Pow(c.R, gamma), Fun.Pow(c.G, gamma),\n                           Fun.Pow(c.B, gamma), Fun.Pow(c.A, gamma));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinearToGamma(this C3f c, double gamma)\n        {\n            double inv = 1.0 / gamma;\n            return new C3f(Fun.Pow(c.R, inv), Fun.Pow(c.G, inv), Fun.Pow(c.B, inv));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinearToGamma(this C4f c, double gamma)\n        {\n            double inv = 1.0 / gamma;\n            return new C4f(Fun.Pow(c.R, inv), Fun.Pow(c.G, inv),\n                           Fun.Pow(c.B, inv), Fun.Pow(c.A, inv));\n        }\n\n        #endregion\n\n        #region Color Temperature\n\n        public static C3f TemperatureToYuvInC3f(this double t)\n        {\n            // calculation from:\n            // http://en.wikipedia.org/wiki/Planckian_locus\n\n            var t2 = t.Square();\n            return new C3f(\n                100,\n                (0.860117757 + 1.54118254e-4 * t + 1.28641212e-7 * t2)\n                / (1 + 8.42420235e-4 * t + 7.08145163e-7 * t2),         // u: error within 8e-5 from 1000K < T < 15000K\n                (0.317398726 + 4.22806245e-5 * t + 4.20481691e-8 * t2)\n                / (1 - 2.89741816e-5 * t + 1.61456053e-7 * t2));        // v: error within 9e-5 from 1000K < T < 15000K\n        }\n\n        public static C3f TemperatureToYxyInC3f(this double t)\n        {\n            // calculation from:\n            // http://en.wikipedia.org/wiki/Planckian_locus\n            // defined from 1667 <= T <= 25000\n\n            if (t <= 0) return new C3f(0, 0, 0);\n\n            var t2 = t * t;\n            var t3 = t2 * t;\n            var x = t <= 4000 ? -0.2661239e9/t3 - 0.2343580e6/t2 + 0.8776956e3/t + 0.179910\n                              : -3.0258469e9/t3 + 2.1070379e6/t2 + 0.2226347e3/t + 0.240390;\n            var x2 = x * x;\n            var x3 = x2 * x;\n            var y = t <= 2222 ? -1.1063814*x3 - 1.34811020*x2 + 2.18555832*x - 0.20219683\n                  : t <= 4000 ? -0.9549476*x3 - 1.37418593*x2 + 2.09137015*x - 0.16748867\n                              : 3.0817580*x3 - 5.87338670*x2 + 3.75112997*x - 0.37001483;\n\n            return new C3f(100, x, y);\n        }\n\n        #endregion\n\n        #region Operations\n\n        public static C3b Average(this IEnumerable<C3b> items)\n        {\n            var sum = new C3d(0, 0, 0);\n            long count = 0;\n            foreach (var c in items) { sum.R += c.R; sum.G += c.G; sum.B += c.B; ++count; }\n            var scale = 1.0 / count;\n            return new C3b((byte)(sum.R * scale), (byte)(sum.G * scale), (byte)(sum.B * scale));\n        }\n\n        public static C4b Average(this IEnumerable<C4b> items)\n        {\n            var sum = new C4d(0, 0, 0);\n            long count = 0;\n            foreach (var c in items) { sum.R += c.R; sum.G += c.G; sum.B += c.B; sum.A += c.A; ++count; }\n            var scale = 1.0 / count;\n            return new C4b((byte)(sum.R * scale), (byte)(sum.G * scale), (byte)(sum.B * scale), (byte)(sum.A * scale));\n        }\n\n        public static C3f Average(this IEnumerable<C3f> items)\n        {\n            var sum = new C3d(0, 0, 0);\n            long count = 0;\n            foreach (var c in items) { sum.R += c.R; sum.G += c.G; sum.B += c.B; ++count; }\n            var scale = 1.0 / count;\n            return new C3f(sum.R * scale, sum.G * scale, sum.B * scale);\n        }\n\n        public static C4f Average(this IEnumerable<C4f> items)\n        {\n            var sum = new C4d(0, 0, 0, 0);\n            long count = 0;\n            foreach (var c in items) { sum.R += c.R; sum.G += c.G; sum.B += c.B; sum.A += c.A; ++count; }\n            var scale = 1.0 / count;\n            return new C4f(sum.R * scale, sum.B * scale, sum.G * scale, sum.A * scale);\n        }\n\n        #endregion\n\n        #region Hex Parsing\n\n        // See: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color\n        private static readonly Regex regexHexSgl = new Regex(\"^(?:#|0x)?(?<R>[0-9a-fA-F])(?<G>[0-9a-fA-F])(?<B>[0-9a-fA-F])(?<A>[0-9a-fA-F])?$\", RegexOptions.Compiled);\n        private static readonly Regex regexHexDbl = new Regex(\"^(?:#|0x)?(?<R>[0-9a-fA-F]{2})(?<G>[0-9a-fA-F]{2})(?<B>[0-9a-fA-F]{2})(?<A>[0-9a-fA-F]{2})?$\", RegexOptions.Compiled);\n\n        private static bool TryParseHex(Regex regex, string input, out C4b result)\n        {\n            var m = regex.Match(input);\n            if (m.Success)\n            {\n                string[] values = new string[4];\n                values[0] = m.Groups[\"R\"].Value;\n                values[1] = m.Groups[\"G\"].Value;\n                values[2] = m.Groups[\"B\"].Value;\n                values[3] = m.Groups[\"A\"].Success ? m.Groups[\"A\"].Value : \"FF\";\n\n                result =\n                    new C4b(values.Map((x) => {\n                        var value = x.Length == 1 ? new string(x[0], 2) : x;\n                        return byte.Parse(value, NumberStyles.AllowHexSpecifier);\n                    }));\n\n                return true;\n            }\n\n            result = C4b.Zero;\n            return false;\n        }\n\n        /// <summary>\n        /// Parses a hexadecimal color string with format RRGGBBAA or RGBA, where the alpha component is optional.\n        /// </summary>\n        /// <remarks>\n        /// For the single digit RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// The color string may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"input\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4b.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParseHex(Text input, out C4b result)\n        {\n            var str = input.WhiteSpaceTrimmed.ToString();\n            return TryParseHex(regexHexDbl, str, out result) || TryParseHex(regexHexSgl, str, out result);\n        }\n\n        /// <summary>\n        /// Parses a hexadecimal color string with format RRGGBBAA or RGBA, where the alpha component is optional.\n        /// </summary>\n        /// <remarks>\n        /// For the single digit RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// The color string may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"input\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4b.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParseHex(string input, out C4b result)\n            => TryParseHex(new Text(input), out result);\n\n        /// <summary>\n        /// Parses a hexadecimal color string with format RRGGBBAA or RGBA, where the alpha component is optional.\n        /// </summary>\n        /// <remarks>\n        /// For the single digit RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// The color string may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"input\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid hexadecimal color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b ParseHex(Text input)\n            => TryParseHex(input, out C4b result) ? result : throw new FormatException($\"{input} is not a valid hexadecimal color.\");\n\n        /// <summary>\n        /// Parses a hexadecimal color string with format RRGGBBAA or RGBA, where the alpha component is optional.\n        /// </summary>\n        /// <remarks>\n        /// For the single digit RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// The color string may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"input\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid hexadecimal color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b ParseHex(string input)\n            => ParseHex(new Text(input));\n\n        #endregion\n    }\n\n    #endregion\n\n    #region PixFormat\n\n    /// <summary>\n    /// The PixFormat encodes the channel type and the color format of an image.\n    /// </summary>\n    [DataContract]\n    [Serializable]\n    public readonly struct PixFormat : IEquatable<PixFormat>\n    {\n        [DataMember]\n        public readonly Type Type;\n        [DataMember]\n        public readonly Col.Format Format;\n\n        #region Constructor\n\n        public PixFormat(Type type, Col.Format format)\n        {\n            Type = type;\n            Format = format;\n        }\n\n        #endregion\n\n        #region Predefined PixFormats\n\n        public static readonly PixFormat ByteBW = new PixFormat(typeof(byte), Col.Format.BW);\n        public static readonly PixFormat ByteGray = new PixFormat(typeof(byte), Col.Format.Gray);\n        public static readonly PixFormat ByteGrayAlpha = new PixFormat(typeof(byte), Col.Format.GrayAlpha);\n        public static readonly PixFormat ByteRG = new PixFormat(typeof(byte), Col.Format.RG);\n        public static readonly PixFormat ByteBGR = new PixFormat(typeof(byte), Col.Format.BGR);\n        public static readonly PixFormat ByteRGB = new PixFormat(typeof(byte), Col.Format.RGB);\n        public static readonly PixFormat ByteBGRA = new PixFormat(typeof(byte), Col.Format.BGRA);\n        public static readonly PixFormat ByteRGBA = new PixFormat(typeof(byte), Col.Format.RGBA);\n        public static readonly PixFormat ByteBGRP = new PixFormat(typeof(byte), Col.Format.BGRP);\n        public static readonly PixFormat ByteRGBP = new PixFormat(typeof(byte), Col.Format.RGBP);\n\n        public static readonly PixFormat SByteBW = new PixFormat(typeof(sbyte), Col.Format.BW);\n        public static readonly PixFormat SByteGray = new PixFormat(typeof(sbyte), Col.Format.Gray);\n        public static readonly PixFormat SByteGrayAlpha = new PixFormat(typeof(sbyte), Col.Format.GrayAlpha);\n        public static readonly PixFormat SByteRG = new PixFormat(typeof(sbyte), Col.Format.RG);\n        public static readonly PixFormat SByteBGR = new PixFormat(typeof(sbyte), Col.Format.BGR);\n        public static readonly PixFormat SByteRGB = new PixFormat(typeof(sbyte), Col.Format.RGB);\n        public static readonly PixFormat SByteBGRA = new PixFormat(typeof(sbyte), Col.Format.BGRA);\n        public static readonly PixFormat SByteRGBA = new PixFormat(typeof(sbyte), Col.Format.RGBA);\n        public static readonly PixFormat SByteBGRP = new PixFormat(typeof(sbyte), Col.Format.BGRP);\n        public static readonly PixFormat SByteRGBP = new PixFormat(typeof(sbyte), Col.Format.RGBP);\n\n        public static readonly PixFormat UShortGray = new PixFormat(typeof(ushort), Col.Format.Gray);\n        public static readonly PixFormat UShortGrayAlpha = new PixFormat(typeof(ushort), Col.Format.GrayAlpha);\n        public static readonly PixFormat UShortRG = new PixFormat(typeof(ushort), Col.Format.RG);\n        public static readonly PixFormat UShortBGR = new PixFormat(typeof(ushort), Col.Format.BGR);\n        public static readonly PixFormat UShortRGB = new PixFormat(typeof(ushort), Col.Format.RGB);\n        public static readonly PixFormat UShortBGRA = new PixFormat(typeof(ushort), Col.Format.BGRA);\n        public static readonly PixFormat UShortRGBA = new PixFormat(typeof(ushort), Col.Format.RGBA);\n        public static readonly PixFormat UShortBGRP = new PixFormat(typeof(ushort), Col.Format.BGRP);\n        public static readonly PixFormat UShortRGBP = new PixFormat(typeof(ushort), Col.Format.RGBP);\n\n        public static readonly PixFormat ShortGray = new PixFormat(typeof(short), Col.Format.Gray);\n        public static readonly PixFormat ShortGrayAlpha = new PixFormat(typeof(short), Col.Format.GrayAlpha);\n        public static readonly PixFormat ShortRG = new PixFormat(typeof(short), Col.Format.RG);\n        public static readonly PixFormat ShortBGR = new PixFormat(typeof(short), Col.Format.BGR);\n        public static readonly PixFormat ShortRGB = new PixFormat(typeof(short), Col.Format.RGB);\n        public static readonly PixFormat ShortBGRA = new PixFormat(typeof(short), Col.Format.BGRA);\n        public static readonly PixFormat ShortRGBA = new PixFormat(typeof(short), Col.Format.RGBA);\n        public static readonly PixFormat ShortBGRP = new PixFormat(typeof(short), Col.Format.BGRP);\n        public static readonly PixFormat ShortRGBP = new PixFormat(typeof(short), Col.Format.RGBP);\n\n        public static readonly PixFormat UIntGray = new PixFormat(typeof(uint), Col.Format.Gray);\n        public static readonly PixFormat UIntGrayAlpha = new PixFormat(typeof(uint), Col.Format.GrayAlpha);\n        public static readonly PixFormat UIntRG = new PixFormat(typeof(uint), Col.Format.RG);\n        public static readonly PixFormat UIntBGR = new PixFormat(typeof(uint), Col.Format.BGR);\n        public static readonly PixFormat UIntRGB = new PixFormat(typeof(uint), Col.Format.RGB);\n        public static readonly PixFormat UIntBGRA = new PixFormat(typeof(uint), Col.Format.BGRA);\n        public static readonly PixFormat UIntRGBA = new PixFormat(typeof(uint), Col.Format.RGBA);\n        public static readonly PixFormat UIntBGRP = new PixFormat(typeof(uint), Col.Format.BGRP);\n        public static readonly PixFormat UIntRGBP = new PixFormat(typeof(uint), Col.Format.RGBP);\n\n        public static readonly PixFormat IntGray = new PixFormat(typeof(int), Col.Format.Gray);\n        public static readonly PixFormat IntGrayAlpha = new PixFormat(typeof(int), Col.Format.GrayAlpha);\n        public static readonly PixFormat IntRG = new PixFormat(typeof(int), Col.Format.RG);\n        public static readonly PixFormat IntBGR = new PixFormat(typeof(int), Col.Format.BGR);\n        public static readonly PixFormat IntRGB = new PixFormat(typeof(int), Col.Format.RGB);\n        public static readonly PixFormat IntBGRA = new PixFormat(typeof(int), Col.Format.BGRA);\n        public static readonly PixFormat IntRGBA = new PixFormat(typeof(int), Col.Format.RGBA);\n        public static readonly PixFormat IntBGRP = new PixFormat(typeof(int), Col.Format.BGRP);\n        public static readonly PixFormat IntRGBP = new PixFormat(typeof(int), Col.Format.RGBP);\n\n        public static readonly PixFormat HalfGray = new PixFormat(typeof(Half), Col.Format.Gray);\n        public static readonly PixFormat HalfGrayAlpha = new PixFormat(typeof(Half), Col.Format.GrayAlpha);\n        public static readonly PixFormat HalfRG = new PixFormat(typeof(Half), Col.Format.RG);\n        public static readonly PixFormat HalfBGR = new PixFormat(typeof(Half), Col.Format.BGR);\n        public static readonly PixFormat HalfRGB = new PixFormat(typeof(Half), Col.Format.RGB);\n        public static readonly PixFormat HalfBGRA = new PixFormat(typeof(Half), Col.Format.BGRA);\n        public static readonly PixFormat HalfRGBA = new PixFormat(typeof(Half), Col.Format.RGBA);\n        public static readonly PixFormat HalfBGRP = new PixFormat(typeof(Half), Col.Format.BGRP);\n        public static readonly PixFormat HalfRGBP = new PixFormat(typeof(Half), Col.Format.RGBP);\n\n        public static readonly PixFormat FloatGray = new PixFormat(typeof(float), Col.Format.Gray);\n        public static readonly PixFormat FloatGrayAlpha = new PixFormat(typeof(float), Col.Format.GrayAlpha);\n        public static readonly PixFormat FloatRG = new PixFormat(typeof(float), Col.Format.RG);\n        public static readonly PixFormat FloatBGR = new PixFormat(typeof(float), Col.Format.BGR);\n        public static readonly PixFormat FloatRGB = new PixFormat(typeof(float), Col.Format.RGB);\n        public static readonly PixFormat FloatBGRA = new PixFormat(typeof(float), Col.Format.BGRA);\n        public static readonly PixFormat FloatRGBA = new PixFormat(typeof(float), Col.Format.RGBA);\n        public static readonly PixFormat FloatBGRP = new PixFormat(typeof(float), Col.Format.BGRP);\n        public static readonly PixFormat FloatRGBP = new PixFormat(typeof(float), Col.Format.RGBP);\n\n        public static readonly PixFormat DoubleGray = new PixFormat(typeof(double), Col.Format.Gray);\n        public static readonly PixFormat DoubleGrayAlpha = new PixFormat(typeof(double), Col.Format.GrayAlpha);\n        public static readonly PixFormat DoubleRG = new PixFormat(typeof(double), Col.Format.RG);\n        public static readonly PixFormat DoubleBGR = new PixFormat(typeof(double), Col.Format.BGR);\n        public static readonly PixFormat DoubleRGB = new PixFormat(typeof(double), Col.Format.RGB);\n        public static readonly PixFormat DoubleBGRA = new PixFormat(typeof(double), Col.Format.BGRA);\n        public static readonly PixFormat DoubleRGBA = new PixFormat(typeof(double), Col.Format.RGBA);\n        public static readonly PixFormat DoubleBGRP = new PixFormat(typeof(double), Col.Format.BGRP);\n        public static readonly PixFormat DoubleRGBP = new PixFormat(typeof(double), Col.Format.RGBP);\n\n        #endregion\n\n        #region Properties\n\n        public int ChannelCount { get { return Format.ChannelCount(); } }\n\n        #endregion\n\n        #region Operators\n\n        public static bool operator ==(PixFormat a, PixFormat b)\n        {\n            return a.Type == b.Type && a.Format == b.Format;\n        }\n\n        public static bool operator !=(PixFormat a, PixFormat b)\n        {\n            return a.Type != b.Type || a.Format != b.Format;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override bool Equals(object obj)\n        {\n            return obj is PixFormat ? this == (PixFormat)obj : false;\n        }\n\n        public override int GetHashCode()\n        {\n            return HashCode.Combine(Type.GetHashCode(), Format.GetHashCode());\n        }\n\n        public override string ToString()\n            => $\"{Type.Name}{Format}\";\n\n        #endregion\n\n        #region IEquatable<PixFormat> Members\n\n        public bool Equals(PixFormat other)\n        {\n            return other.Type == Type && other.Format == Format;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C3b\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C3b\n    {\n        /// <summary>\n        /// Memory layout for intel-based little-endian argb-ints.\n        /// (DO NOT CHANGE!)\n        /// </summary>\n        [DataMember]\n        public byte B;\n        [DataMember]\n        public byte G;\n        [DataMember]\n        public byte R;\n    }\n\n    #endregion\n\n    #region C3us\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C3us\n    {\n        [DataMember]\n        public ushort R;\n        [DataMember]\n        public ushort G;\n        [DataMember]\n        public ushort B;\n    }\n\n    #endregion\n\n    #region C3ui\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C3ui\n    {\n        [DataMember]\n        public uint R;\n        [DataMember]\n        public uint G;\n        [DataMember]\n        public uint B;\n    }\n\n    #endregion\n\n    #region C3f\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C3f\n    {\n        [DataMember]\n        public float R;\n        [DataMember]\n        public float G;\n        [DataMember]\n        public float B;\n\n        /// <summary>\n        /// Creates an RGB representation from hue, saturation and value/brightness.\n        /// </summary>\n        /// <param name=\"hue\">Hue given in normalized angle [0,1] (may be larger than 1, wraps around), 0=1=red, 1/3=green, 2/3=blue.</param>\n        /// <param name=\"saturation\">Saturation [0,1], 0 = gray, 1 = fully saturated.</param>\n        /// <param name=\"value\">Value or Brightness [0,1], 0 = black, 1 = white.</param>\n        /// <returns>The RGB Color for the HSV values.</returns>\n        public static C3f FromHSV(float hue, float saturation, float value)\n        {\n            return new HSVf(hue, saturation, value).ToC3f();\n        }\n\n        /// <summary>\n        /// Creates an RGB representation from hue, saturation and lightness.\n        /// </summary>\n        /// <param name=\"hue\">Hue given in normalized angle [0,1] (may be larger than 1, wraps around), 0=1=red, 1/3=green, 2/3=blue.</param>\n        /// <param name=\"saturation\">Saturation [0,1], 0 = gray, 1 = fully saturated.</param>\n        /// <param name=\"lightness\">Lightness [0,1], 0 = black, 1 = white.</param>\n        /// <returns>The RGB Color for the HSV values.</returns>\n        public static C3f FromHSL(float hue, float saturation, float lightness)\n        {\n            return new HSLf(hue, saturation, lightness).ToC3f();\n        }\n\n        public readonly HSLf AsHSLf() { return new HSLf(R, G, B); }\n\n        public readonly HSVf AsHSVf() { return new HSVf(R, G, B); }\n\n    }\n\n    #endregion\n\n    #region C3d\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C3d\n    {\n        [DataMember]\n        public double R;\n        [DataMember]\n        public double G;\n        [DataMember]\n        public double B;\n    }\n\n    #endregion\n\n    #region C4b\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C4b\n    {\n        /// <summary>\n        /// Memory layout for intel-based little-endian argb-ints.\n        /// (DO NOT CHANGE!)\n        /// </summary>\n        [DataMember]\n        public byte B;\n        [DataMember]\n        public byte G;\n        [DataMember]\n        public byte R;\n        [DataMember]\n        public byte A;\n    }\n\n    #endregion\n\n    #region C4us\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C4us\n    {\n        [DataMember]\n        public ushort R;\n        [DataMember]\n        public ushort G;\n        [DataMember]\n        public ushort B;\n        [DataMember]\n        public ushort A;\n    }\n\n    #endregion\n\n    #region C4ui\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C4ui\n    {\n        [DataMember]\n        public uint R;\n        [DataMember]\n        public uint G;\n        [DataMember]\n        public uint B;\n        [DataMember]\n        public uint A;\n    }\n\n    #endregion\n\n    #region C4f\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C4f\n    {\n        [DataMember]\n        public float R;\n        [DataMember]\n        public float G;\n        [DataMember]\n        public float B;\n        [DataMember]\n        public float A;\n    }\n\n    #endregion\n\n    #region C4d\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct C4d\n    {\n        [DataMember]\n        public double R;\n        [DataMember]\n        public double G;\n        [DataMember]\n        public double B;\n        [DataMember]\n        public double A;\n    }\n\n    #endregion\n\n    #region CieLabf\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct CieLabf : IEquatable<CieLabf>\n    {\n        [DataMember]\n        public float L;\n        [DataMember]\n        public float a;\n        [DataMember]\n        public float b;\n\n        public CieLabf(float _L, float _a, float _b) { L = _L; a = _a; b = _b; }\n        public CieLabf(double _L, double _a, double _b) { L = (float)_L; a = (float)_a; b = (float)_b; }\n\n        public readonly bool Equals(CieLabf other) => L == other.L && a == other.a && b == other.b;\n        public override readonly bool Equals(object other) => (other is CieLabf o) ? Equals(o) : false;\n        public override readonly int GetHashCode() => HashCode.GetCombined(L, a, b);\n    }\n\n    #endregion\n\n    #region CieLuvf\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct CieLuvf : IEquatable<CieLuvf>\n    {\n        [DataMember]\n        public float L;\n        [DataMember]\n        public float u;\n        [DataMember]\n        public float v;\n\n        public CieLuvf(float _L, float _u, float _v) { L = _L; u = _u; v = _v; }\n        public CieLuvf(double _L, double _u, double _v) { L = (float)_L; u = (float)_u; v = (float)_v; }\n\n        public readonly C3f AsC3f() { return new C3f(L, u, v); }\n\n        public readonly bool Equals(CieLuvf other) => L == other.L && u == other.u && v == other.v;\n        public override readonly bool Equals(object other) => (other is CieLuvf o) ? Equals(o) : false;\n        public override readonly int GetHashCode() => HashCode.GetCombined(L, u, v);\n    }\n\n    #endregion\n\n    #region CieXYZf\n\n    /// <summary>\n    /// This structure holds Cie XYZ colors where Y should be in the range\n    /// [0,100] for reflective color values.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct CieXYZf : IEquatable<CieXYZf>\n    {\n        [DataMember]\n        public float X;\n        [DataMember]\n        public float Y;\n        [DataMember]\n        public float Z;\n\n        public CieXYZf(float _X, float _Y, float _Z) { X = _X; Y = _Y; Z = _Z; }\n        public CieXYZf(double _X, double _Y, double _Z) { X = (float)_X; Y = (float)_Y; Z = (float)_Z; }\n\n        public readonly bool Equals(CieXYZf other) => X == other.X && Y == other.Y && Z == other.Z;\n        public override readonly bool Equals(object other) => (other is CieXYZf o) ? Equals(o) : false;\n        public override readonly int GetHashCode() => HashCode.GetCombined(X, Y, Z);\n    }\n\n    #endregion\n\n    #region CieYxyf\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct CieYxyf : IEquatable<CieYxyf>\n    {\n        [DataMember]\n        public float Y;\n        [DataMember]\n        public float x;\n        [DataMember]\n        public float y;\n\n        public CieYxyf(float _Y, float _x, float _y) { Y = _Y; x = _x; y = _y; }\n        public CieYxyf(double _Y, double _x, double _y) { Y = (float)_Y; x = (float)_x; y = (float)_y; }\n\n        public readonly bool Equals(CieYxyf other) => Y == other.Y && x == other.x && y == other.y;\n        public override readonly bool Equals(object other) => (other is CieYxyf o) ? Equals(o) : false;\n        public override readonly int GetHashCode() => HashCode.GetCombined(Y, x, y);\n    }\n\n    #endregion\n\n    #region CMYKf\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct CMYKf : IEquatable<CMYKf>\n    {\n        [DataMember]\n        public float C;\n        [DataMember]\n        public float M;\n        [DataMember]\n        public float Y;\n        [DataMember]\n        public float K;\n\n        public CMYKf(float _C, float _M, float _Y, float _K) { C = _C; M = _M; Y = _Y; K = _K; }\n        public CMYKf(double _C, double _M, double _Y, double _K)\n                { C = (float)_C; M = (float)_M; Y = (float)_Y; K = (float)_K; }\n\n        public readonly bool Equals(CMYKf other) => C == other.C && M == other.M && Y == other.Y && K == other.K;\n        public override readonly bool Equals(object other) => (other is CMYKf o) ? Equals(o) : false;\n        public override readonly int GetHashCode() => HashCode.GetCombined(C, M, Y, K);\n    }\n\n    #endregion\n\n    #region HSLf\n\n    /// <summary>\n    /// Hue Saturation Value colors. All three components are defined in the range [0.0, 1.0].\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct HSLf : IEquatable<HSLf>\n    {\n        [DataMember]\n        public float H;\n        [DataMember]\n        public float S;\n        [DataMember]\n        public float L;\n\n        #region Constructors\n\n        public HSLf(float hue, float saturation, float lightness)\n            { H = hue; S = saturation; L = lightness; }\n\n        public HSLf(double hue, double saturation, double lightness)\n            { H = (float)hue; S = (float)saturation; L = (float)lightness; }\n\n        #endregion\n\n        #region Conversions\n\n        public static HSLf FromC3f(C3f col)\n        {\n            return col.ToHSLf();\n        }\n\n        public readonly C3f AsC3f() { return new C3f(H, S, L); }\n\n        #endregion\n\n        public readonly bool Equals(HSLf other) => H == other.H && S == other.S && L == other.L;\n        public override readonly bool Equals(object other) => (other is HSLf o) ? Equals(o) : false;\n        public override readonly int GetHashCode() => HashCode.GetCombined(H, S, L);\n    }\n\n    #endregion\n\n    #region HSVf\n\n    /// <summary>\n    /// Hue Saturation Lightness colors. All three components are defined in the range [0.0, 1.0].\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct HSVf : IEquatable<HSVf>\n    {\n        [DataMember]\n        public float H;\n        [DataMember]\n        public float S;\n        [DataMember]\n        public float V;\n\n        #region Constructors\n\n        public HSVf(float hue, float saturation, float value)\n        { H = hue; S = saturation; V = value; }\n\n        public HSVf(double hue, double saturation, double value)\n        { H = (float)hue; S = (float)saturation; V = (float)value; }\n\n        #endregion\n\n        #region Conversions\n\n        public static HSVf FromC3f(C3f col)\n        {\n            return col.ToHSVf();\n        }\n\n        public readonly C3f AsC3f() { return new C3f(H, S, V); }\n\n        #endregion\n\n        public readonly bool Equals(HSVf other) => H == other.H && S == other.S && V == other.V;\n        public override readonly bool Equals(object other) => (other is HSVf o) ? Equals(o) : false;\n        public override readonly int GetHashCode() => HashCode.GetCombined(H, S, V);\n    }\n\n    #endregion\n\n    #region Yuvf\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Yuvf : IEquatable<Yuvf>\n    {\n        [DataMember]\n        public float Y;\n        [DataMember]\n        public float u;\n        [DataMember]\n        public float v;\n\n        public Yuvf(float _Y, float _u, float _v) { Y = _Y; u = _u; v = _v; }\n        public Yuvf(double _Y, double _u, double _v) { Y = (float)_Y; u = (float)_u; v = (float)_v; }\n\n        public readonly C3f AsC3f() { return new C3f(Y, u, v); }\n\n        public readonly bool Equals(Yuvf other) => Y == other.Y && u == other.u && v == other.v;\n        public override readonly bool Equals(object other) => (other is Yuvf o) ? Equals(o) : false;\n        public override readonly int GetHashCode() => HashCode.GetCombined(Y, u, v);\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Colors/Color_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region C3b\n\n    /// <summary>\n    /// Represents an RGB color with each channel stored as a <see cref=\"byte\"/> value within [0, 255].\n    /// </summary>\n    [Serializable]\n    public partial struct C3b : IFormattable, IEquatable<C3b>, IRGB\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"byte\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(byte r, byte g, byte b)\n        {\n            R = r; G = g; B = b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> values.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(int r, int g, int b)\n        {\n            R = (byte)r; G = (byte)g; B = (byte)b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> values.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(long r, long g, long b)\n        {\n            R = (byte)r; G = (byte)g; B = (byte)b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(float r, float g, float b)\n        {\n            R = Col.FloatToByteClamped(r);\n            G = Col.FloatToByteClamped(g);\n            B = Col.FloatToByteClamped(b);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(double r, double g, double b)\n        {\n            R = Col.DoubleToByteClamped(r);\n            G = Col.DoubleToByteClamped(g);\n            B = Col.DoubleToByteClamped(b);\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"byte\"/> value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(byte gray)\n        {\n            R = gray; G = gray; B = gray;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(float gray)\n        {\n            var value = Col.FloatToByteClamped(gray);\n            R = value; G = value; B = value;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(double gray)\n        {\n            var value = Col.DoubleToByteClamped(gray);\n            R = value; G = value; B = value;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C3b color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C3us color)\n        {\n            R = Col.UShortToByte(color.R);\n            G = Col.UShortToByte(color.G);\n            B = Col.UShortToByte(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C3ui color)\n        {\n            R = Col.UIntToByte(color.R);\n            G = Col.UIntToByte(color.G);\n            B = Col.UIntToByte(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C3f color)\n        {\n            R = Col.FloatToByteClamped(color.R);\n            G = Col.FloatToByteClamped(color.G);\n            B = Col.FloatToByteClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C3d color)\n        {\n            R = Col.DoubleToByteClamped(color.R);\n            G = Col.DoubleToByteClamped(color.G);\n            B = Col.DoubleToByteClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C4b color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C4us color)\n        {\n            R = Col.UShortToByte(color.R);\n            G = Col.UShortToByte(color.G);\n            B = Col.UShortToByte(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C4ui color)\n        {\n            R = Col.UIntToByte(color.R);\n            G = Col.UIntToByte(color.G);\n            B = Col.UIntToByte(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C4f color)\n        {\n            R = Col.FloatToByteClamped(color.R);\n            G = Col.FloatToByteClamped(color.G);\n            B = Col.FloatToByteClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(C4d color)\n        {\n            R = Col.DoubleToByteClamped(color.R);\n            G = Col.DoubleToByteClamped(color.G);\n            B = Col.DoubleToByteClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V3i vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V3ui vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V3l vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V3f vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V3d vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V4i vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V4ui vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V4l vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V4f vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(V4d vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(Func<int, byte> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(byte[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(byte[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(ushort[] values)\n        {\n            R = Col.UShortToByte(values[0]);\n            G = Col.UShortToByte(values[1]);\n            B = Col.UShortToByte(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(ushort[] values, int start)\n        {\n            R = Col.UShortToByte(values[start + 0]);\n            G = Col.UShortToByte(values[start + 1]);\n            B = Col.UShortToByte(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(uint[] values)\n        {\n            R = Col.UIntToByte(values[0]);\n            G = Col.UIntToByte(values[1]);\n            B = Col.UIntToByte(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(uint[] values, int start)\n        {\n            R = Col.UIntToByte(values[start + 0]);\n            G = Col.UIntToByte(values[start + 1]);\n            B = Col.UIntToByte(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(float[] values)\n        {\n            R = Col.FloatToByteClamped(values[0]);\n            G = Col.FloatToByteClamped(values[1]);\n            B = Col.FloatToByteClamped(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(float[] values, int start)\n        {\n            R = Col.FloatToByteClamped(values[start + 0]);\n            G = Col.FloatToByteClamped(values[start + 1]);\n            B = Col.FloatToByteClamped(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(double[] values)\n        {\n            R = Col.DoubleToByteClamped(values[0]);\n            G = Col.DoubleToByteClamped(values[1]);\n            B = Col.DoubleToByteClamped(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3b(double[] values, int start)\n        {\n            R = Col.DoubleToByteClamped(values[start + 0]);\n            G = Col.DoubleToByteClamped(values[start + 1]);\n            B = Col.DoubleToByteClamped(values[start + 2]);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C3us color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC3us(C3us c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C3ui color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC3ui(C3ui c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C3f color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC3f(C3f c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C3d color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC3d(C3d c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3b\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C4b color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4b\"/> color.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C4b\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC4b(C4b c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C4us color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC4us(C4us c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C4ui color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC4ui(C4ui c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C4f color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC4f(C4f c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(C4d color)\n            => new C3b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromC4d(C4d c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3i\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V3i v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV3i(V3i c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V3ui v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV3ui(V3ui c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V3l v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV3l(V3l c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V3f v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV3f(V3f c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V3d v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV3d(V3d c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4i\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V4i v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV4i(V4i c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V4ui v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV4ui(V4ui c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V4l v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV4l(V4l c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V4f v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV4f(V4f c) => new C3b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(V4d v)\n            => new C3b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3b\"/> color from a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b FromV4d(V4d c) => new C3b(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(byte[] values)\n            => new C3b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C3b\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C3b color)\n            => new byte[] { (color.R), (color.G), (color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(ushort[] values)\n            => new C3b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C3b color)\n            => new ushort[] { Col.ByteToUShort(color.R), Col.ByteToUShort(color.G), Col.ByteToUShort(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(uint[] values)\n            => new C3b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C3b color)\n            => new uint[] { Col.ByteToUInt(color.R), Col.ByteToUInt(color.G), Col.ByteToUInt(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(float[] values)\n            => new C3b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C3b color)\n            => new float[] { Col.ByteToFloat(color.R), Col.ByteToFloat(color.G), Col.ByteToFloat(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3b(double[] values)\n            => new C3b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C3b color)\n            => new double[] { Col.ByteToDouble(color.R), Col.ByteToDouble(color.G), Col.ByteToDouble(color.B) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b Map(Func<byte, byte> channel_fun)\n        {\n            return new C3b(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us Map(Func<byte, ushort> channel_fun)\n        {\n            return new C3us(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui Map(Func<byte, uint> channel_fun)\n        {\n            return new C3ui(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f Map(Func<byte, float> channel_fun)\n        {\n            return new C3f(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d Map(Func<byte, double> channel_fun)\n        {\n            return new C3d(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<byte, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<byte, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly byte[] ToArray()\n            => (byte[])this;\n\n        #endregion\n\n        #region Indexer\n\n        // Byte colors have a different byte order (red and blue are swapped)\n        private static readonly byte[] IndexMapping = new byte[] { 2, 1, 0, 3 };\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe byte this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (byte* ptr = &B) { ptr[IndexMapping[i]] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (byte* ptr = &B) { return ptr[IndexMapping[i]]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C3b with all components zero.\n        /// </summary>\n        public static C3b Zero => new C3b(0, 0, 0);\n\n        // Web colors\n        public static C3b AliceBlue => new C3b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.972549), Col.DoubleToByteClamped(1));\n        public static C3b AntiqueWhite => new C3b(Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.921569), Col.DoubleToByteClamped(0.843137));\n        public static C3b Aqua => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C3b Aquamarine => new C3b(Col.DoubleToByteClamped(0.498039), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.831373));\n        public static C3b Azure => new C3b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C3b Beige => new C3b(Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.862745));\n        public static C3b Bisque => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.894118), Col.DoubleToByteClamped(0.768627));\n        public static C3b Black => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0));\n        public static C3b BlanchedAlmond => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.921569), Col.DoubleToByteClamped(0.803922));\n        public static C3b Blue => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1));\n        public static C3b BlueViolet => new C3b(Col.DoubleToByteClamped(0.541176), Col.DoubleToByteClamped(0.168627), Col.DoubleToByteClamped(0.886275));\n        public static C3b Brown => new C3b(Col.DoubleToByteClamped(0.647059), Col.DoubleToByteClamped(0.164706), Col.DoubleToByteClamped(0.164706));\n        public static C3b BurlyWood => new C3b(Col.DoubleToByteClamped(0.870588), Col.DoubleToByteClamped(0.721569), Col.DoubleToByteClamped(0.529412));\n        public static C3b CadetBlue => new C3b(Col.DoubleToByteClamped(0.372549), Col.DoubleToByteClamped(0.619608), Col.DoubleToByteClamped(0.627451));\n        public static C3b Chartreuse => new C3b(Col.DoubleToByteClamped(0.498039), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0));\n        public static C3b Chocolate => new C3b(Col.DoubleToByteClamped(0.823529), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.117647));\n        public static C3b Coral => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.498039), Col.DoubleToByteClamped(0.313725));\n        public static C3b CornflowerBlue => new C3b(Col.DoubleToByteClamped(0.392157), Col.DoubleToByteClamped(0.584314), Col.DoubleToByteClamped(0.929412));\n        public static C3b Cornsilk => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.972549), Col.DoubleToByteClamped(0.862745));\n        public static C3b Crimson => new C3b(Col.DoubleToByteClamped(0.862745), Col.DoubleToByteClamped(0.078431), Col.DoubleToByteClamped(0.235294));\n        public static C3b Cyan => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C3b DarkBlue => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.545098));\n        public static C3b DarkCyan => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0.545098));\n        public static C3b DarkGoldenRod => new C3b(Col.DoubleToByteClamped(0.721569), Col.DoubleToByteClamped(0.52549), Col.DoubleToByteClamped(0.043137));\n        public static C3b DarkGray => new C3b(Col.DoubleToByteClamped(0.662745), Col.DoubleToByteClamped(0.662745), Col.DoubleToByteClamped(0.662745));\n        public static C3b DarkGrey => new C3b(Col.DoubleToByteClamped(0.662745), Col.DoubleToByteClamped(0.662745), Col.DoubleToByteClamped(0.662745));\n        public static C3b DarkGreen => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.392157), Col.DoubleToByteClamped(0));\n        public static C3b DarkKhaki => new C3b(Col.DoubleToByteClamped(0.741176), Col.DoubleToByteClamped(0.717647), Col.DoubleToByteClamped(0.419608));\n        public static C3b DarkMagenta => new C3b(Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.545098));\n        public static C3b DarkOliveGreen => new C3b(Col.DoubleToByteClamped(0.333333), Col.DoubleToByteClamped(0.419608), Col.DoubleToByteClamped(0.184314));\n        public static C3b DarkOrange => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.54902), Col.DoubleToByteClamped(0));\n        public static C3b DarkOrchid => new C3b(Col.DoubleToByteClamped(0.6), Col.DoubleToByteClamped(0.196078), Col.DoubleToByteClamped(0.8));\n        public static C3b DarkRed => new C3b(Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0));\n        public static C3b DarkSalmon => new C3b(Col.DoubleToByteClamped(0.913725), Col.DoubleToByteClamped(0.588235), Col.DoubleToByteClamped(0.478431));\n        public static C3b DarkSeaGreen => new C3b(Col.DoubleToByteClamped(0.560784), Col.DoubleToByteClamped(0.737255), Col.DoubleToByteClamped(0.560784));\n        public static C3b DarkSlateBlue => new C3b(Col.DoubleToByteClamped(0.282353), Col.DoubleToByteClamped(0.239216), Col.DoubleToByteClamped(0.545098));\n        public static C3b DarkSlateGray => new C3b(Col.DoubleToByteClamped(0.184314), Col.DoubleToByteClamped(0.309804), Col.DoubleToByteClamped(0.309804));\n        public static C3b DarkSlateGrey => new C3b(Col.DoubleToByteClamped(0.184314), Col.DoubleToByteClamped(0.309804), Col.DoubleToByteClamped(0.309804));\n        public static C3b DarkTurquoise => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.807843), Col.DoubleToByteClamped(0.819608));\n        public static C3b DarkViolet => new C3b(Col.DoubleToByteClamped(0.580392), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.827451));\n        public static C3b DeepPink => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.078431), Col.DoubleToByteClamped(0.576471));\n        public static C3b DeepSkyBlue => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.74902), Col.DoubleToByteClamped(1));\n        public static C3b DimGray => new C3b(Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.411765));\n        public static C3b DimGrey => new C3b(Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.411765));\n        public static C3b DodgerBlue => new C3b(Col.DoubleToByteClamped(0.117647), Col.DoubleToByteClamped(0.564706), Col.DoubleToByteClamped(1));\n        public static C3b FireBrick => new C3b(Col.DoubleToByteClamped(0.698039), Col.DoubleToByteClamped(0.133333), Col.DoubleToByteClamped(0.133333));\n        public static C3b FloralWhite => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.941176));\n        public static C3b ForestGreen => new C3b(Col.DoubleToByteClamped(0.133333), Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0.133333));\n        public static C3b Fuchsia => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1));\n        public static C3b Gainsboro => new C3b(Col.DoubleToByteClamped(0.862745), Col.DoubleToByteClamped(0.862745), Col.DoubleToByteClamped(0.862745));\n        public static C3b GhostWhite => new C3b(Col.DoubleToByteClamped(0.972549), Col.DoubleToByteClamped(0.972549), Col.DoubleToByteClamped(1));\n        public static C3b Gold => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.843137), Col.DoubleToByteClamped(0));\n        public static C3b GoldenRod => new C3b(Col.DoubleToByteClamped(0.854902), Col.DoubleToByteClamped(0.647059), Col.DoubleToByteClamped(0.12549));\n        public static C3b Gray => new C3b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961));\n        public static C3b Grey => new C3b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961));\n        public static C3b Green => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0));\n        public static C3b GreenYellow => new C3b(Col.DoubleToByteClamped(0.678431), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.184314));\n        public static C3b HoneyDew => new C3b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.941176));\n        public static C3b HotPink => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.705882));\n        public static C3b IndianRed  => new C3b(Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.360784), Col.DoubleToByteClamped(0.360784));\n        public static C3b Indigo  => new C3b(Col.DoubleToByteClamped(0.294118), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.509804));\n        public static C3b Ivory => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.941176));\n        public static C3b Khaki => new C3b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.901961), Col.DoubleToByteClamped(0.54902));\n        public static C3b Lavender => new C3b(Col.DoubleToByteClamped(0.901961), Col.DoubleToByteClamped(0.901961), Col.DoubleToByteClamped(0.980392));\n        public static C3b LavenderBlush => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.960784));\n        public static C3b LawnGreen => new C3b(Col.DoubleToByteClamped(0.486275), Col.DoubleToByteClamped(0.988235), Col.DoubleToByteClamped(0));\n        public static C3b LemonChiffon => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.803922));\n        public static C3b LightBlue => new C3b(Col.DoubleToByteClamped(0.678431), Col.DoubleToByteClamped(0.847059), Col.DoubleToByteClamped(0.901961));\n        public static C3b LightCoral => new C3b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961));\n        public static C3b LightCyan => new C3b(Col.DoubleToByteClamped(0.878431), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C3b LightGoldenRodYellow => new C3b(Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.823529));\n        public static C3b LightGray => new C3b(Col.DoubleToByteClamped(0.827451), Col.DoubleToByteClamped(0.827451), Col.DoubleToByteClamped(0.827451));\n        public static C3b LightGrey => new C3b(Col.DoubleToByteClamped(0.827451), Col.DoubleToByteClamped(0.827451), Col.DoubleToByteClamped(0.827451));\n        public static C3b LightGreen => new C3b(Col.DoubleToByteClamped(0.564706), Col.DoubleToByteClamped(0.933333), Col.DoubleToByteClamped(0.564706));\n        public static C3b LightPink => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.713725), Col.DoubleToByteClamped(0.756863));\n        public static C3b LightSalmon => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.627451), Col.DoubleToByteClamped(0.478431));\n        public static C3b LightSeaGreen => new C3b(Col.DoubleToByteClamped(0.12549), Col.DoubleToByteClamped(0.698039), Col.DoubleToByteClamped(0.666667));\n        public static C3b LightSkyBlue => new C3b(Col.DoubleToByteClamped(0.529412), Col.DoubleToByteClamped(0.807843), Col.DoubleToByteClamped(0.980392));\n        public static C3b LightSlateGray => new C3b(Col.DoubleToByteClamped(0.466667), Col.DoubleToByteClamped(0.533333), Col.DoubleToByteClamped(0.6));\n        public static C3b LightSlateGrey => new C3b(Col.DoubleToByteClamped(0.466667), Col.DoubleToByteClamped(0.533333), Col.DoubleToByteClamped(0.6));\n        public static C3b LightSteelBlue => new C3b(Col.DoubleToByteClamped(0.690196), Col.DoubleToByteClamped(0.768627), Col.DoubleToByteClamped(0.870588));\n        public static C3b LightYellow => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.878431));\n        public static C3b Lime => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0));\n        public static C3b LimeGreen => new C3b(Col.DoubleToByteClamped(0.196078), Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.196078));\n        public static C3b Linen => new C3b(Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.901961));\n        public static C3b Magenta => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1));\n        public static C3b Maroon => new C3b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0));\n        public static C3b MediumAquaMarine => new C3b(Col.DoubleToByteClamped(0.4), Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.666667));\n        public static C3b MediumBlue => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.803922));\n        public static C3b MediumOrchid => new C3b(Col.DoubleToByteClamped(0.729412), Col.DoubleToByteClamped(0.333333), Col.DoubleToByteClamped(0.827451));\n        public static C3b MediumPurple => new C3b(Col.DoubleToByteClamped(0.576471), Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.847059));\n        public static C3b MediumSeaGreen => new C3b(Col.DoubleToByteClamped(0.235294), Col.DoubleToByteClamped(0.701961), Col.DoubleToByteClamped(0.443137));\n        public static C3b MediumSlateBlue => new C3b(Col.DoubleToByteClamped(0.482353), Col.DoubleToByteClamped(0.407843), Col.DoubleToByteClamped(0.933333));\n        public static C3b MediumSpringGreen => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.603922));\n        public static C3b MediumTurquoise => new C3b(Col.DoubleToByteClamped(0.282353), Col.DoubleToByteClamped(0.819608), Col.DoubleToByteClamped(0.8));\n        public static C3b MediumVioletRed => new C3b(Col.DoubleToByteClamped(0.780392), Col.DoubleToByteClamped(0.082353), Col.DoubleToByteClamped(0.521569));\n        public static C3b MidnightBlue => new C3b(Col.DoubleToByteClamped(0.098039), Col.DoubleToByteClamped(0.098039), Col.DoubleToByteClamped(0.439216));\n        public static C3b MintCream => new C3b(Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.980392));\n        public static C3b MistyRose => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.894118), Col.DoubleToByteClamped(0.882353));\n        public static C3b Moccasin => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.894118), Col.DoubleToByteClamped(0.709804));\n        public static C3b NavajoWhite => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.870588), Col.DoubleToByteClamped(0.678431));\n        public static C3b Navy => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.501961));\n        public static C3b OldLace => new C3b(Col.DoubleToByteClamped(0.992157), Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.901961));\n        public static C3b Olive => new C3b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0));\n        public static C3b OliveDrab => new C3b(Col.DoubleToByteClamped(0.419608), Col.DoubleToByteClamped(0.556863), Col.DoubleToByteClamped(0.137255));\n        public static C3b Orange => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.647059), Col.DoubleToByteClamped(0));\n        public static C3b OrangeRed => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.270588), Col.DoubleToByteClamped(0));\n        public static C3b Orchid => new C3b(Col.DoubleToByteClamped(0.854902), Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.839216));\n        public static C3b PaleGoldenRod => new C3b(Col.DoubleToByteClamped(0.933333), Col.DoubleToByteClamped(0.909804), Col.DoubleToByteClamped(0.666667));\n        public static C3b PaleGreen => new C3b(Col.DoubleToByteClamped(0.596078), Col.DoubleToByteClamped(0.984314), Col.DoubleToByteClamped(0.596078));\n        public static C3b PaleTurquoise => new C3b(Col.DoubleToByteClamped(0.686275), Col.DoubleToByteClamped(0.933333), Col.DoubleToByteClamped(0.933333));\n        public static C3b PaleVioletRed => new C3b(Col.DoubleToByteClamped(0.847059), Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.576471));\n        public static C3b PapayaWhip => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.937255), Col.DoubleToByteClamped(0.835294));\n        public static C3b PeachPuff => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.854902), Col.DoubleToByteClamped(0.72549));\n        public static C3b Peru => new C3b(Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.521569), Col.DoubleToByteClamped(0.247059));\n        public static C3b Pink => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.752941), Col.DoubleToByteClamped(0.796078));\n        public static C3b Plum => new C3b(Col.DoubleToByteClamped(0.866667), Col.DoubleToByteClamped(0.627451), Col.DoubleToByteClamped(0.866667));\n        public static C3b PowderBlue => new C3b(Col.DoubleToByteClamped(0.690196), Col.DoubleToByteClamped(0.878431), Col.DoubleToByteClamped(0.901961));\n        public static C3b Purple => new C3b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.501961));\n        public static C3b Red => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0));\n        public static C3b RosyBrown => new C3b(Col.DoubleToByteClamped(0.737255), Col.DoubleToByteClamped(0.560784), Col.DoubleToByteClamped(0.560784));\n        public static C3b RoyalBlue => new C3b(Col.DoubleToByteClamped(0.254902), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.882353));\n        public static C3b SaddleBrown => new C3b(Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0.270588), Col.DoubleToByteClamped(0.07451));\n        public static C3b Salmon => new C3b(Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.447059));\n        public static C3b SandyBrown => new C3b(Col.DoubleToByteClamped(0.956863), Col.DoubleToByteClamped(0.643137), Col.DoubleToByteClamped(0.376471));\n        public static C3b SeaGreen => new C3b(Col.DoubleToByteClamped(0.180392), Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0.341176));\n        public static C3b SeaShell => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.933333));\n        public static C3b Sienna => new C3b(Col.DoubleToByteClamped(0.627451), Col.DoubleToByteClamped(0.321569), Col.DoubleToByteClamped(0.176471));\n        public static C3b Silver => new C3b(Col.DoubleToByteClamped(0.752941), Col.DoubleToByteClamped(0.752941), Col.DoubleToByteClamped(0.752941));\n        public static C3b SkyBlue => new C3b(Col.DoubleToByteClamped(0.529412), Col.DoubleToByteClamped(0.807843), Col.DoubleToByteClamped(0.921569));\n        public static C3b SlateBlue => new C3b(Col.DoubleToByteClamped(0.415686), Col.DoubleToByteClamped(0.352941), Col.DoubleToByteClamped(0.803922));\n        public static C3b SlateGray => new C3b(Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.564706));\n        public static C3b SlateGrey => new C3b(Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.564706));\n        public static C3b Snow => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.980392));\n        public static C3b SpringGreen => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.498039));\n        public static C3b SteelBlue => new C3b(Col.DoubleToByteClamped(0.27451), Col.DoubleToByteClamped(0.509804), Col.DoubleToByteClamped(0.705882));\n        public static C3b Tan => new C3b(Col.DoubleToByteClamped(0.823529), Col.DoubleToByteClamped(0.705882), Col.DoubleToByteClamped(0.54902));\n        public static C3b Teal => new C3b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961));\n        public static C3b Thistle => new C3b(Col.DoubleToByteClamped(0.847059), Col.DoubleToByteClamped(0.74902), Col.DoubleToByteClamped(0.847059));\n        public static C3b Tomato => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.388235), Col.DoubleToByteClamped(0.278431));\n        public static C3b Turquoise => new C3b(Col.DoubleToByteClamped(0.25098), Col.DoubleToByteClamped(0.878431), Col.DoubleToByteClamped(0.815686));\n        public static C3b Violet => new C3b(Col.DoubleToByteClamped(0.933333), Col.DoubleToByteClamped(0.509804), Col.DoubleToByteClamped(0.933333));\n        public static C3b Wheat => new C3b(Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.870588), Col.DoubleToByteClamped(0.701961));\n        public static C3b White => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C3b WhiteSmoke => new C3b(Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.960784));\n        public static C3b Yellow => new C3b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0));\n        public static C3b YellowGreen => new C3b(Col.DoubleToByteClamped(0.603922), Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.196078));\n\n        public static C3b DarkYellow => Olive;\n\n        public static C3b VRVisGreen => new C3b(Col.DoubleToByteClamped(0.698), Col.DoubleToByteClamped(0.851), Col.DoubleToByteClamped(0.008));\n\n        public static C3b Gray10 => new C3b(Col.DoubleToByteClamped(0.1));\n        public static C3b Gray20 => new C3b(Col.DoubleToByteClamped(0.2));\n        public static C3b Gray30 => new C3b(Col.DoubleToByteClamped(0.3));\n        public static C3b Gray40 => new C3b(Col.DoubleToByteClamped(0.4));\n        public static C3b Gray50 => new C3b(Col.DoubleToByteClamped(0.5));\n        public static C3b Gray60 => new C3b(Col.DoubleToByteClamped(0.6));\n        public static C3b Gray70 => new C3b(Col.DoubleToByteClamped(0.7));\n        public static C3b Gray80 => new C3b(Col.DoubleToByteClamped(0.8));\n        public static C3b Gray90 => new C3b(Col.DoubleToByteClamped(0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C3b a, C3b b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C3b a, C3b b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator *(C3b col, float scalar)\n        {\n            return new C3b(\n                Col.FloatToByteClamped(Col.ByteToFloat(col.R) * scalar), \n                Col.FloatToByteClamped(Col.ByteToFloat(col.G) * scalar), \n                Col.FloatToByteClamped(Col.ByteToFloat(col.B) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator *(float scalar, C3b col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator /(C3b col, float scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator /(float scalar, C3b col)\n        {\n            return new C3b(\n                Col.FloatToByteClamped(scalar / Col.ByteToFloat(col.R)), \n                Col.FloatToByteClamped(scalar / Col.ByteToFloat(col.G)), \n                Col.FloatToByteClamped(scalar / Col.ByteToFloat(col.B)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator *(C3b col, double scalar)\n        {\n            return new C3b(\n                Col.DoubleToByteClamped(Col.ByteToDouble(col.R) * scalar), \n                Col.DoubleToByteClamped(Col.ByteToDouble(col.G) * scalar), \n                Col.DoubleToByteClamped(Col.ByteToDouble(col.B) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator *(double scalar, C3b col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator /(C3b col, double scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator /(double scalar, C3b col)\n        {\n            return new C3b(\n                Col.DoubleToByteClamped(scalar / Col.ByteToDouble(col.R)), \n                Col.DoubleToByteClamped(scalar / Col.ByteToDouble(col.G)), \n                Col.DoubleToByteClamped(scalar / Col.ByteToDouble(col.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator +(C3b c0, C3us c1)\n        {\n            return new C3b(\n                (byte)(c0.R + Col.UShortToByte(c1.R)), \n                (byte)(c0.G + Col.UShortToByte(c1.G)), \n                (byte)(c0.B + Col.UShortToByte(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator -(C3b c0, C3us c1)\n        {\n            return new C3b(\n                (byte)(c0.R - Col.UShortToByte(c1.R)), \n                (byte)(c0.G - Col.UShortToByte(c1.G)), \n                (byte)(c0.B - Col.UShortToByte(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator +(C3b c0, C3ui c1)\n        {\n            return new C3b(\n                (byte)(c0.R + Col.UIntToByte(c1.R)), \n                (byte)(c0.G + Col.UIntToByte(c1.G)), \n                (byte)(c0.B + Col.UIntToByte(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator -(C3b c0, C3ui c1)\n        {\n            return new C3b(\n                (byte)(c0.R - Col.UIntToByte(c1.R)), \n                (byte)(c0.G - Col.UIntToByte(c1.G)), \n                (byte)(c0.B - Col.UIntToByte(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator +(C3b c0, C3f c1)\n        {\n            return new C3b(\n                (byte)(c0.R + Col.FloatToByte(c1.R)), \n                (byte)(c0.G + Col.FloatToByte(c1.G)), \n                (byte)(c0.B + Col.FloatToByte(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator -(C3b c0, C3f c1)\n        {\n            return new C3b(\n                (byte)(c0.R - Col.FloatToByte(c1.R)), \n                (byte)(c0.G - Col.FloatToByte(c1.G)), \n                (byte)(c0.B - Col.FloatToByte(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator +(C3b c0, C3d c1)\n        {\n            return new C3b(\n                (byte)(c0.R + Col.DoubleToByte(c1.R)), \n                (byte)(c0.G + Col.DoubleToByte(c1.G)), \n                (byte)(c0.B + Col.DoubleToByte(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator -(C3b c0, C3d c1)\n        {\n            return new C3b(\n                (byte)(c0.R - Col.DoubleToByte(c1.R)), \n                (byte)(c0.G - Col.DoubleToByte(c1.G)), \n                (byte)(c0.B - Col.DoubleToByte(c1.B)));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator *(C3b col, byte scalar)\n        {\n            return new C3b((byte)(col.R * scalar), (byte)(col.G * scalar), (byte)(col.B * scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator *(byte scalar, C3b col)\n        {\n            return new C3b((byte)(scalar * col.R), (byte)(scalar * col.G), (byte)(scalar * col.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator /(C3b col, byte scalar)\n        {\n            return new C3b((byte)(col.R / scalar), (byte)(col.G / scalar), (byte)(col.B / scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator /(byte scalar, C3b col)\n        {\n            return new C3b((byte)(scalar / col.R), (byte)(scalar / col.G), (byte)(scalar / col.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator *(C3b c0, C3b c1)\n        {\n            return new C3b((byte)(c0.R * c1.R), (byte)(c0.G * c1.G), (byte)(c0.B * c1.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator /(C3b c0, C3b c1)\n        {\n            return new C3b((byte)(c0.R / c1.R), (byte)(c0.G / c1.G), (byte)(c0.B / c1.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator +(C3b c0, C3b c1)\n        {\n            return new C3b(\n                (255 - c0.R > c1.R) ? c0.R + c1.R : 255, \n                (255 - c0.G > c1.G) ? c0.G + c1.G : 255, \n                (255 - c0.B > c1.B) ? c0.B + c1.B : 255\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator +(C3b col, byte scalar)\n        {\n            return new C3b(\n                (255 - col.R > scalar) ? col.R + scalar : 255, \n                (255 - col.G > scalar) ? col.G + scalar : 255, \n                (255 - col.B > scalar) ? col.B + scalar : 255\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator +(byte scalar, C3b col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator -(C3b c0, C3b c1)\n        {\n            return new C3b(\n                (c0.R > c1.R) ? c0.R - c1.R : 0, \n                (c0.G > c1.G) ? c0.G - c1.G : 0, \n                (c0.B > c1.B) ? c0.B - c1.B : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator -(C3b col, byte scalar)\n        {\n            return new C3b(\n                (col.R > scalar) ? col.R - scalar : 0, \n                (col.G > scalar) ? col.G - scalar : 0, \n                (col.B > scalar) ? col.B - scalar : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b operator -(byte scalar, C3b col)\n        {\n            return new C3b(\n                (scalar > col.R) ? scalar - col.R : 0, \n                (scalar > col.G) ? scalar - col.G : 0, \n                (scalar > col.B) ? scalar - col.B : 0\n            );\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(byte min, byte max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b Clamped(byte min, byte max)\n        {\n            return new C3b(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max));\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. \n        /// </summary>\n        public readonly int Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return R + G + B; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). \n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). \n        /// </summary>\n        public readonly byte NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(R, G, B); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). \n        /// </summary>\n        public readonly byte NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(R, G, B); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C3b o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C3b, int, byte> Setter =\n            (ref C3b color, int i, byte value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b LinearInterp(float t, C3b a, C3b b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b LinearInterp(V3f t, C3b a, C3b b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b LinearInterp(double t, C3b a, C3b b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b LinearInterp(V3d t, C3b a, C3b b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b DivideByInt(C3b c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3b.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C3b result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC3b();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                byte[] values = new byte[4] { 255, 255, 255, 255 };\n\n                byte parse(Text t)\n                {\n                    if (!byte.TryParse(t.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out byte value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C3b(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3b.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C3b result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3b color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<byte>.Parse, C3b.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3b color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b Parse(Text t)\n            => TryParse(t, out C3b result) ? result : throw new FormatException($\"{t} is not a valid C3b color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C3b> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C3b other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return Col.ByteToDouble(R); }\n            set { R = Col.DoubleToByteClamped(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return Col.ByteToDouble(G); }\n            set { G = Col.DoubleToByteClamped(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return Col.ByteToDouble(B); }\n            set { B = Col.DoubleToByteClamped(value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3b Lerp(this float t, C3b a, C3b b)\n            => new C3b(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3b Lerp(this V3f t, C3b a, C3b b)\n            => new C3b(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3b Lerp(this double t, C3b a, C3b b)\n            => new C3b(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3b Lerp(this V3d t, C3b a, C3b b)\n            => new C3b(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C3b a, C3b b, byte tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3b\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C3b c, byte epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBB.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C3b c)\n            => $\"{c.R:X2}{c.G:X2}{c.B:X2}\";\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3b a, C3b b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3b col, byte s)\n        {\n            return (col.R < s && col.G < s && col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(byte s, C3b col)\n        {\n            return (s < col.R && s < col.G && s < col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3b a, C3b b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3b col, byte s)\n        {\n            return (col.R < s || col.G < s || col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(byte s, C3b col)\n        {\n            return (s < col.R || s < col.G || s < col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3b a, C3b b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3b col, byte s)\n        {\n            return (col.R > s && col.G > s && col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(byte s, C3b col)\n        {\n            return (s > col.R && s > col.G && s > col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3b a, C3b b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3b col, byte s)\n        {\n            return (col.R > s || col.G > s || col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(byte s, C3b col)\n        {\n            return (s > col.R || s > col.G || s > col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3b a, C3b b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3b col, byte s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(byte s, C3b col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3b a, C3b b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3b col, byte s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(byte s, C3b col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3b a, C3b b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3b col, byte s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(byte s, C3b col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3b a, C3b b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3b col, byte s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(byte s, C3b col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3b a, C3b b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3b col, byte s)\n        {\n            return (col.R == s && col.G == s && col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(byte s, C3b col)\n        {\n            return (s == col.R && s == col.G && s == col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3b a, C3b b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3b col, byte s)\n        {\n            return (col.R == s || col.G == s || col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(byte s, C3b col)\n        {\n            return (s == col.R || s == col.G || s == col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3b a, C3b b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3b col, byte s)\n        {\n            return (col.R != s && col.G != s && col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(byte s, C3b col)\n        {\n            return (s != col.R && s != col.G && s != col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3b a, C3b b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3b col, byte s)\n        {\n            return (col.R != s || col.G != s || col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(byte s, C3b col)\n        {\n            return (s != col.R || s != col.G || s != col.B);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b LinCom(\n            C3b p0, C3b p1, C3b p2, C3b p3, ref Tup4<float> w)\n        {\n            return new C3b(\n                Col.ByteInFloatToByteClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.ByteInFloatToByteClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.ByteInFloatToByteClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinComRawF(\n            C3b p0, C3b p1, C3b p2, C3b p3, ref Tup4<float> w)\n        {\n            return new C3f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b LinCom(\n            C3b p0, C3b p1, C3b p2, C3b p3, ref Tup4<double> w)\n        {\n            return new C3b(\n                Col.ByteInDoubleToByteClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.ByteInDoubleToByteClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.ByteInDoubleToByteClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinComRawD(\n            C3b p0, C3b p1, C3b p2, C3b p3, ref Tup4<double> w)\n        {\n            return new C3d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b LinCom(\n            C3b p0, C3b p1, C3b p2, C3b p3, C3b p4, C3b p5, ref Tup6<float> w)\n        {\n            return new C3b(\n                Col.ByteInFloatToByteClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.ByteInFloatToByteClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.ByteInFloatToByteClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinComRawF(\n            C3b p0, C3b p1, C3b p2, C3b p3, C3b p4, C3b p5, ref Tup6<float> w)\n        {\n            return new C3f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3b LinCom(\n            C3b p0, C3b p1, C3b p2, C3b p3, C3b p4, C3b p5, ref Tup6<double> w)\n        {\n            return new C3b(\n                Col.ByteInDoubleToByteClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.ByteInDoubleToByteClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.ByteInDoubleToByteClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinComRawD(\n            C3b p0, C3b p1, C3b p2, C3b p3, C3b p4, C3b p5, ref Tup6<double> w)\n        {\n            return new C3d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C3b\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C3b c, byte epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3b\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C3b c, byte epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C3us\n\n    /// <summary>\n    /// Represents an RGB color with each channel stored as a <see cref=\"ushort\"/> value within [0, 2^16 - 1].\n    /// </summary>\n    [Serializable]\n    public partial struct C3us : IFormattable, IEquatable<C3us>, IRGB\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"ushort\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(ushort r, ushort g, ushort b)\n        {\n            R = r; G = g; B = b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> values.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(int r, int g, int b)\n        {\n            R = (ushort)r; G = (ushort)g; B = (ushort)b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> values.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(long r, long g, long b)\n        {\n            R = (ushort)r; G = (ushort)g; B = (ushort)b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(float r, float g, float b)\n        {\n            R = Col.FloatToUShortClamped(r);\n            G = Col.FloatToUShortClamped(g);\n            B = Col.FloatToUShortClamped(b);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(double r, double g, double b)\n        {\n            R = Col.DoubleToUShortClamped(r);\n            G = Col.DoubleToUShortClamped(g);\n            B = Col.DoubleToUShortClamped(b);\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"ushort\"/> value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(ushort gray)\n        {\n            R = gray; G = gray; B = gray;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(float gray)\n        {\n            var value = Col.FloatToUShortClamped(gray);\n            R = value; G = value; B = value;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(double gray)\n        {\n            var value = Col.DoubleToUShortClamped(gray);\n            R = value; G = value; B = value;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C3b color)\n        {\n            R = Col.ByteToUShort(color.R);\n            G = Col.ByteToUShort(color.G);\n            B = Col.ByteToUShort(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C3us color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C3ui color)\n        {\n            R = Col.UIntToUShort(color.R);\n            G = Col.UIntToUShort(color.G);\n            B = Col.UIntToUShort(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C3f color)\n        {\n            R = Col.FloatToUShortClamped(color.R);\n            G = Col.FloatToUShortClamped(color.G);\n            B = Col.FloatToUShortClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C3d color)\n        {\n            R = Col.DoubleToUShortClamped(color.R);\n            G = Col.DoubleToUShortClamped(color.G);\n            B = Col.DoubleToUShortClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C4b color)\n        {\n            R = Col.ByteToUShort(color.R);\n            G = Col.ByteToUShort(color.G);\n            B = Col.ByteToUShort(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C4us color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C4ui color)\n        {\n            R = Col.UIntToUShort(color.R);\n            G = Col.UIntToUShort(color.G);\n            B = Col.UIntToUShort(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C4f color)\n        {\n            R = Col.FloatToUShortClamped(color.R);\n            G = Col.FloatToUShortClamped(color.G);\n            B = Col.FloatToUShortClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(C4d color)\n        {\n            R = Col.DoubleToUShortClamped(color.R);\n            G = Col.DoubleToUShortClamped(color.G);\n            B = Col.DoubleToUShortClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V3i vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V3ui vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V3l vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V3f vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V3d vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V4i vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V4ui vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V4l vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V4f vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(V4d vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(Func<int, ushort> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(byte[] values)\n        {\n            R = Col.ByteToUShort(values[0]);\n            G = Col.ByteToUShort(values[1]);\n            B = Col.ByteToUShort(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(byte[] values, int start)\n        {\n            R = Col.ByteToUShort(values[start + 0]);\n            G = Col.ByteToUShort(values[start + 1]);\n            B = Col.ByteToUShort(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(ushort[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(ushort[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(uint[] values)\n        {\n            R = Col.UIntToUShort(values[0]);\n            G = Col.UIntToUShort(values[1]);\n            B = Col.UIntToUShort(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(uint[] values, int start)\n        {\n            R = Col.UIntToUShort(values[start + 0]);\n            G = Col.UIntToUShort(values[start + 1]);\n            B = Col.UIntToUShort(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(float[] values)\n        {\n            R = Col.FloatToUShortClamped(values[0]);\n            G = Col.FloatToUShortClamped(values[1]);\n            B = Col.FloatToUShortClamped(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(float[] values, int start)\n        {\n            R = Col.FloatToUShortClamped(values[start + 0]);\n            G = Col.FloatToUShortClamped(values[start + 1]);\n            B = Col.FloatToUShortClamped(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(double[] values)\n        {\n            R = Col.DoubleToUShortClamped(values[0]);\n            G = Col.DoubleToUShortClamped(values[1]);\n            B = Col.DoubleToUShortClamped(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3us(double[] values, int start)\n        {\n            R = Col.DoubleToUShortClamped(values[start + 0]);\n            G = Col.DoubleToUShortClamped(values[start + 1]);\n            B = Col.DoubleToUShortClamped(values[start + 2]);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C3b color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC3b(C3b c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C3ui color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC3ui(C3ui c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C3f color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC3f(C3f c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C3d color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC3d(C3d c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C4b color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC4b(C4b c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3us\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C4us color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4us\"/> color.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C4us\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC4us(C4us c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C4ui color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC4ui(C4ui c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C4f color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC4f(C4f c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(C4d color)\n            => new C3us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromC4d(C4d c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3i\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V3i v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV3i(V3i c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V3ui v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV3ui(V3ui c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V3l v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV3l(V3l c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V3f v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV3f(V3f c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V3d v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV3d(V3d c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4i\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V4i v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV4i(V4i c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V4ui v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV4ui(V4ui c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V4l v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV4l(V4l c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V4f v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV4f(V4f c) => new C3us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(V4d v)\n            => new C3us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3us\"/> color from a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us FromV4d(V4d c) => new C3us(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(byte[] values)\n            => new C3us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C3us color)\n            => new byte[] { Col.UShortToByte(color.R), Col.UShortToByte(color.G), Col.UShortToByte(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(ushort[] values)\n            => new C3us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C3us\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C3us color)\n            => new ushort[] { (color.R), (color.G), (color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(uint[] values)\n            => new C3us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C3us color)\n            => new uint[] { Col.UShortToUInt(color.R), Col.UShortToUInt(color.G), Col.UShortToUInt(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(float[] values)\n            => new C3us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C3us color)\n            => new float[] { Col.UShortToFloat(color.R), Col.UShortToFloat(color.G), Col.UShortToFloat(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3us(double[] values)\n            => new C3us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C3us color)\n            => new double[] { Col.UShortToDouble(color.R), Col.UShortToDouble(color.G), Col.UShortToDouble(color.B) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b Map(Func<ushort, byte> channel_fun)\n        {\n            return new C3b(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us Map(Func<ushort, ushort> channel_fun)\n        {\n            return new C3us(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui Map(Func<ushort, uint> channel_fun)\n        {\n            return new C3ui(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f Map(Func<ushort, float> channel_fun)\n        {\n            return new C3f(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d Map(Func<ushort, double> channel_fun)\n        {\n            return new C3d(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<ushort, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<ushort, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly ushort[] ToArray()\n            => (ushort[])this;\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe ushort this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (ushort* ptr = &R) { ptr[i] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (ushort* ptr = &R) { return ptr[i]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C3us with all components zero.\n        /// </summary>\n        public static C3us Zero => new C3us(0, 0, 0);\n\n        // Web colors\n        public static C3us AliceBlue => new C3us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.972549), Col.DoubleToUShortClamped(1));\n        public static C3us AntiqueWhite => new C3us(Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.921569), Col.DoubleToUShortClamped(0.843137));\n        public static C3us Aqua => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C3us Aquamarine => new C3us(Col.DoubleToUShortClamped(0.498039), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.831373));\n        public static C3us Azure => new C3us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C3us Beige => new C3us(Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.862745));\n        public static C3us Bisque => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.894118), Col.DoubleToUShortClamped(0.768627));\n        public static C3us Black => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0));\n        public static C3us BlanchedAlmond => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.921569), Col.DoubleToUShortClamped(0.803922));\n        public static C3us Blue => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1));\n        public static C3us BlueViolet => new C3us(Col.DoubleToUShortClamped(0.541176), Col.DoubleToUShortClamped(0.168627), Col.DoubleToUShortClamped(0.886275));\n        public static C3us Brown => new C3us(Col.DoubleToUShortClamped(0.647059), Col.DoubleToUShortClamped(0.164706), Col.DoubleToUShortClamped(0.164706));\n        public static C3us BurlyWood => new C3us(Col.DoubleToUShortClamped(0.870588), Col.DoubleToUShortClamped(0.721569), Col.DoubleToUShortClamped(0.529412));\n        public static C3us CadetBlue => new C3us(Col.DoubleToUShortClamped(0.372549), Col.DoubleToUShortClamped(0.619608), Col.DoubleToUShortClamped(0.627451));\n        public static C3us Chartreuse => new C3us(Col.DoubleToUShortClamped(0.498039), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0));\n        public static C3us Chocolate => new C3us(Col.DoubleToUShortClamped(0.823529), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.117647));\n        public static C3us Coral => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.498039), Col.DoubleToUShortClamped(0.313725));\n        public static C3us CornflowerBlue => new C3us(Col.DoubleToUShortClamped(0.392157), Col.DoubleToUShortClamped(0.584314), Col.DoubleToUShortClamped(0.929412));\n        public static C3us Cornsilk => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.972549), Col.DoubleToUShortClamped(0.862745));\n        public static C3us Crimson => new C3us(Col.DoubleToUShortClamped(0.862745), Col.DoubleToUShortClamped(0.078431), Col.DoubleToUShortClamped(0.235294));\n        public static C3us Cyan => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C3us DarkBlue => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.545098));\n        public static C3us DarkCyan => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0.545098));\n        public static C3us DarkGoldenRod => new C3us(Col.DoubleToUShortClamped(0.721569), Col.DoubleToUShortClamped(0.52549), Col.DoubleToUShortClamped(0.043137));\n        public static C3us DarkGray => new C3us(Col.DoubleToUShortClamped(0.662745), Col.DoubleToUShortClamped(0.662745), Col.DoubleToUShortClamped(0.662745));\n        public static C3us DarkGrey => new C3us(Col.DoubleToUShortClamped(0.662745), Col.DoubleToUShortClamped(0.662745), Col.DoubleToUShortClamped(0.662745));\n        public static C3us DarkGreen => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.392157), Col.DoubleToUShortClamped(0));\n        public static C3us DarkKhaki => new C3us(Col.DoubleToUShortClamped(0.741176), Col.DoubleToUShortClamped(0.717647), Col.DoubleToUShortClamped(0.419608));\n        public static C3us DarkMagenta => new C3us(Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.545098));\n        public static C3us DarkOliveGreen => new C3us(Col.DoubleToUShortClamped(0.333333), Col.DoubleToUShortClamped(0.419608), Col.DoubleToUShortClamped(0.184314));\n        public static C3us DarkOrange => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.54902), Col.DoubleToUShortClamped(0));\n        public static C3us DarkOrchid => new C3us(Col.DoubleToUShortClamped(0.6), Col.DoubleToUShortClamped(0.196078), Col.DoubleToUShortClamped(0.8));\n        public static C3us DarkRed => new C3us(Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0));\n        public static C3us DarkSalmon => new C3us(Col.DoubleToUShortClamped(0.913725), Col.DoubleToUShortClamped(0.588235), Col.DoubleToUShortClamped(0.478431));\n        public static C3us DarkSeaGreen => new C3us(Col.DoubleToUShortClamped(0.560784), Col.DoubleToUShortClamped(0.737255), Col.DoubleToUShortClamped(0.560784));\n        public static C3us DarkSlateBlue => new C3us(Col.DoubleToUShortClamped(0.282353), Col.DoubleToUShortClamped(0.239216), Col.DoubleToUShortClamped(0.545098));\n        public static C3us DarkSlateGray => new C3us(Col.DoubleToUShortClamped(0.184314), Col.DoubleToUShortClamped(0.309804), Col.DoubleToUShortClamped(0.309804));\n        public static C3us DarkSlateGrey => new C3us(Col.DoubleToUShortClamped(0.184314), Col.DoubleToUShortClamped(0.309804), Col.DoubleToUShortClamped(0.309804));\n        public static C3us DarkTurquoise => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.807843), Col.DoubleToUShortClamped(0.819608));\n        public static C3us DarkViolet => new C3us(Col.DoubleToUShortClamped(0.580392), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.827451));\n        public static C3us DeepPink => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.078431), Col.DoubleToUShortClamped(0.576471));\n        public static C3us DeepSkyBlue => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.74902), Col.DoubleToUShortClamped(1));\n        public static C3us DimGray => new C3us(Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.411765));\n        public static C3us DimGrey => new C3us(Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.411765));\n        public static C3us DodgerBlue => new C3us(Col.DoubleToUShortClamped(0.117647), Col.DoubleToUShortClamped(0.564706), Col.DoubleToUShortClamped(1));\n        public static C3us FireBrick => new C3us(Col.DoubleToUShortClamped(0.698039), Col.DoubleToUShortClamped(0.133333), Col.DoubleToUShortClamped(0.133333));\n        public static C3us FloralWhite => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.941176));\n        public static C3us ForestGreen => new C3us(Col.DoubleToUShortClamped(0.133333), Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0.133333));\n        public static C3us Fuchsia => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1));\n        public static C3us Gainsboro => new C3us(Col.DoubleToUShortClamped(0.862745), Col.DoubleToUShortClamped(0.862745), Col.DoubleToUShortClamped(0.862745));\n        public static C3us GhostWhite => new C3us(Col.DoubleToUShortClamped(0.972549), Col.DoubleToUShortClamped(0.972549), Col.DoubleToUShortClamped(1));\n        public static C3us Gold => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.843137), Col.DoubleToUShortClamped(0));\n        public static C3us GoldenRod => new C3us(Col.DoubleToUShortClamped(0.854902), Col.DoubleToUShortClamped(0.647059), Col.DoubleToUShortClamped(0.12549));\n        public static C3us Gray => new C3us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961));\n        public static C3us Grey => new C3us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961));\n        public static C3us Green => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0));\n        public static C3us GreenYellow => new C3us(Col.DoubleToUShortClamped(0.678431), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.184314));\n        public static C3us HoneyDew => new C3us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.941176));\n        public static C3us HotPink => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.705882));\n        public static C3us IndianRed  => new C3us(Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.360784), Col.DoubleToUShortClamped(0.360784));\n        public static C3us Indigo  => new C3us(Col.DoubleToUShortClamped(0.294118), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.509804));\n        public static C3us Ivory => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.941176));\n        public static C3us Khaki => new C3us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.901961), Col.DoubleToUShortClamped(0.54902));\n        public static C3us Lavender => new C3us(Col.DoubleToUShortClamped(0.901961), Col.DoubleToUShortClamped(0.901961), Col.DoubleToUShortClamped(0.980392));\n        public static C3us LavenderBlush => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.960784));\n        public static C3us LawnGreen => new C3us(Col.DoubleToUShortClamped(0.486275), Col.DoubleToUShortClamped(0.988235), Col.DoubleToUShortClamped(0));\n        public static C3us LemonChiffon => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.803922));\n        public static C3us LightBlue => new C3us(Col.DoubleToUShortClamped(0.678431), Col.DoubleToUShortClamped(0.847059), Col.DoubleToUShortClamped(0.901961));\n        public static C3us LightCoral => new C3us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961));\n        public static C3us LightCyan => new C3us(Col.DoubleToUShortClamped(0.878431), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C3us LightGoldenRodYellow => new C3us(Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.823529));\n        public static C3us LightGray => new C3us(Col.DoubleToUShortClamped(0.827451), Col.DoubleToUShortClamped(0.827451), Col.DoubleToUShortClamped(0.827451));\n        public static C3us LightGrey => new C3us(Col.DoubleToUShortClamped(0.827451), Col.DoubleToUShortClamped(0.827451), Col.DoubleToUShortClamped(0.827451));\n        public static C3us LightGreen => new C3us(Col.DoubleToUShortClamped(0.564706), Col.DoubleToUShortClamped(0.933333), Col.DoubleToUShortClamped(0.564706));\n        public static C3us LightPink => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.713725), Col.DoubleToUShortClamped(0.756863));\n        public static C3us LightSalmon => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.627451), Col.DoubleToUShortClamped(0.478431));\n        public static C3us LightSeaGreen => new C3us(Col.DoubleToUShortClamped(0.12549), Col.DoubleToUShortClamped(0.698039), Col.DoubleToUShortClamped(0.666667));\n        public static C3us LightSkyBlue => new C3us(Col.DoubleToUShortClamped(0.529412), Col.DoubleToUShortClamped(0.807843), Col.DoubleToUShortClamped(0.980392));\n        public static C3us LightSlateGray => new C3us(Col.DoubleToUShortClamped(0.466667), Col.DoubleToUShortClamped(0.533333), Col.DoubleToUShortClamped(0.6));\n        public static C3us LightSlateGrey => new C3us(Col.DoubleToUShortClamped(0.466667), Col.DoubleToUShortClamped(0.533333), Col.DoubleToUShortClamped(0.6));\n        public static C3us LightSteelBlue => new C3us(Col.DoubleToUShortClamped(0.690196), Col.DoubleToUShortClamped(0.768627), Col.DoubleToUShortClamped(0.870588));\n        public static C3us LightYellow => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.878431));\n        public static C3us Lime => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0));\n        public static C3us LimeGreen => new C3us(Col.DoubleToUShortClamped(0.196078), Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.196078));\n        public static C3us Linen => new C3us(Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.901961));\n        public static C3us Magenta => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1));\n        public static C3us Maroon => new C3us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0));\n        public static C3us MediumAquaMarine => new C3us(Col.DoubleToUShortClamped(0.4), Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.666667));\n        public static C3us MediumBlue => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.803922));\n        public static C3us MediumOrchid => new C3us(Col.DoubleToUShortClamped(0.729412), Col.DoubleToUShortClamped(0.333333), Col.DoubleToUShortClamped(0.827451));\n        public static C3us MediumPurple => new C3us(Col.DoubleToUShortClamped(0.576471), Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.847059));\n        public static C3us MediumSeaGreen => new C3us(Col.DoubleToUShortClamped(0.235294), Col.DoubleToUShortClamped(0.701961), Col.DoubleToUShortClamped(0.443137));\n        public static C3us MediumSlateBlue => new C3us(Col.DoubleToUShortClamped(0.482353), Col.DoubleToUShortClamped(0.407843), Col.DoubleToUShortClamped(0.933333));\n        public static C3us MediumSpringGreen => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.603922));\n        public static C3us MediumTurquoise => new C3us(Col.DoubleToUShortClamped(0.282353), Col.DoubleToUShortClamped(0.819608), Col.DoubleToUShortClamped(0.8));\n        public static C3us MediumVioletRed => new C3us(Col.DoubleToUShortClamped(0.780392), Col.DoubleToUShortClamped(0.082353), Col.DoubleToUShortClamped(0.521569));\n        public static C3us MidnightBlue => new C3us(Col.DoubleToUShortClamped(0.098039), Col.DoubleToUShortClamped(0.098039), Col.DoubleToUShortClamped(0.439216));\n        public static C3us MintCream => new C3us(Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.980392));\n        public static C3us MistyRose => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.894118), Col.DoubleToUShortClamped(0.882353));\n        public static C3us Moccasin => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.894118), Col.DoubleToUShortClamped(0.709804));\n        public static C3us NavajoWhite => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.870588), Col.DoubleToUShortClamped(0.678431));\n        public static C3us Navy => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.501961));\n        public static C3us OldLace => new C3us(Col.DoubleToUShortClamped(0.992157), Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.901961));\n        public static C3us Olive => new C3us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0));\n        public static C3us OliveDrab => new C3us(Col.DoubleToUShortClamped(0.419608), Col.DoubleToUShortClamped(0.556863), Col.DoubleToUShortClamped(0.137255));\n        public static C3us Orange => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.647059), Col.DoubleToUShortClamped(0));\n        public static C3us OrangeRed => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.270588), Col.DoubleToUShortClamped(0));\n        public static C3us Orchid => new C3us(Col.DoubleToUShortClamped(0.854902), Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.839216));\n        public static C3us PaleGoldenRod => new C3us(Col.DoubleToUShortClamped(0.933333), Col.DoubleToUShortClamped(0.909804), Col.DoubleToUShortClamped(0.666667));\n        public static C3us PaleGreen => new C3us(Col.DoubleToUShortClamped(0.596078), Col.DoubleToUShortClamped(0.984314), Col.DoubleToUShortClamped(0.596078));\n        public static C3us PaleTurquoise => new C3us(Col.DoubleToUShortClamped(0.686275), Col.DoubleToUShortClamped(0.933333), Col.DoubleToUShortClamped(0.933333));\n        public static C3us PaleVioletRed => new C3us(Col.DoubleToUShortClamped(0.847059), Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.576471));\n        public static C3us PapayaWhip => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.937255), Col.DoubleToUShortClamped(0.835294));\n        public static C3us PeachPuff => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.854902), Col.DoubleToUShortClamped(0.72549));\n        public static C3us Peru => new C3us(Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.521569), Col.DoubleToUShortClamped(0.247059));\n        public static C3us Pink => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.752941), Col.DoubleToUShortClamped(0.796078));\n        public static C3us Plum => new C3us(Col.DoubleToUShortClamped(0.866667), Col.DoubleToUShortClamped(0.627451), Col.DoubleToUShortClamped(0.866667));\n        public static C3us PowderBlue => new C3us(Col.DoubleToUShortClamped(0.690196), Col.DoubleToUShortClamped(0.878431), Col.DoubleToUShortClamped(0.901961));\n        public static C3us Purple => new C3us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.501961));\n        public static C3us Red => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0));\n        public static C3us RosyBrown => new C3us(Col.DoubleToUShortClamped(0.737255), Col.DoubleToUShortClamped(0.560784), Col.DoubleToUShortClamped(0.560784));\n        public static C3us RoyalBlue => new C3us(Col.DoubleToUShortClamped(0.254902), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.882353));\n        public static C3us SaddleBrown => new C3us(Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0.270588), Col.DoubleToUShortClamped(0.07451));\n        public static C3us Salmon => new C3us(Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.447059));\n        public static C3us SandyBrown => new C3us(Col.DoubleToUShortClamped(0.956863), Col.DoubleToUShortClamped(0.643137), Col.DoubleToUShortClamped(0.376471));\n        public static C3us SeaGreen => new C3us(Col.DoubleToUShortClamped(0.180392), Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0.341176));\n        public static C3us SeaShell => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.933333));\n        public static C3us Sienna => new C3us(Col.DoubleToUShortClamped(0.627451), Col.DoubleToUShortClamped(0.321569), Col.DoubleToUShortClamped(0.176471));\n        public static C3us Silver => new C3us(Col.DoubleToUShortClamped(0.752941), Col.DoubleToUShortClamped(0.752941), Col.DoubleToUShortClamped(0.752941));\n        public static C3us SkyBlue => new C3us(Col.DoubleToUShortClamped(0.529412), Col.DoubleToUShortClamped(0.807843), Col.DoubleToUShortClamped(0.921569));\n        public static C3us SlateBlue => new C3us(Col.DoubleToUShortClamped(0.415686), Col.DoubleToUShortClamped(0.352941), Col.DoubleToUShortClamped(0.803922));\n        public static C3us SlateGray => new C3us(Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.564706));\n        public static C3us SlateGrey => new C3us(Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.564706));\n        public static C3us Snow => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.980392));\n        public static C3us SpringGreen => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.498039));\n        public static C3us SteelBlue => new C3us(Col.DoubleToUShortClamped(0.27451), Col.DoubleToUShortClamped(0.509804), Col.DoubleToUShortClamped(0.705882));\n        public static C3us Tan => new C3us(Col.DoubleToUShortClamped(0.823529), Col.DoubleToUShortClamped(0.705882), Col.DoubleToUShortClamped(0.54902));\n        public static C3us Teal => new C3us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961));\n        public static C3us Thistle => new C3us(Col.DoubleToUShortClamped(0.847059), Col.DoubleToUShortClamped(0.74902), Col.DoubleToUShortClamped(0.847059));\n        public static C3us Tomato => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.388235), Col.DoubleToUShortClamped(0.278431));\n        public static C3us Turquoise => new C3us(Col.DoubleToUShortClamped(0.25098), Col.DoubleToUShortClamped(0.878431), Col.DoubleToUShortClamped(0.815686));\n        public static C3us Violet => new C3us(Col.DoubleToUShortClamped(0.933333), Col.DoubleToUShortClamped(0.509804), Col.DoubleToUShortClamped(0.933333));\n        public static C3us Wheat => new C3us(Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.870588), Col.DoubleToUShortClamped(0.701961));\n        public static C3us White => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C3us WhiteSmoke => new C3us(Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.960784));\n        public static C3us Yellow => new C3us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0));\n        public static C3us YellowGreen => new C3us(Col.DoubleToUShortClamped(0.603922), Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.196078));\n\n        public static C3us DarkYellow => Olive;\n\n        public static C3us VRVisGreen => new C3us(Col.DoubleToUShortClamped(0.698), Col.DoubleToUShortClamped(0.851), Col.DoubleToUShortClamped(0.008));\n\n        public static C3us Gray10 => new C3us(Col.DoubleToUShortClamped(0.1));\n        public static C3us Gray20 => new C3us(Col.DoubleToUShortClamped(0.2));\n        public static C3us Gray30 => new C3us(Col.DoubleToUShortClamped(0.3));\n        public static C3us Gray40 => new C3us(Col.DoubleToUShortClamped(0.4));\n        public static C3us Gray50 => new C3us(Col.DoubleToUShortClamped(0.5));\n        public static C3us Gray60 => new C3us(Col.DoubleToUShortClamped(0.6));\n        public static C3us Gray70 => new C3us(Col.DoubleToUShortClamped(0.7));\n        public static C3us Gray80 => new C3us(Col.DoubleToUShortClamped(0.8));\n        public static C3us Gray90 => new C3us(Col.DoubleToUShortClamped(0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C3us a, C3us b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C3us a, C3us b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator *(C3us col, float scalar)\n        {\n            return new C3us(\n                Col.FloatToUShortClamped(Col.UShortToFloat(col.R) * scalar), \n                Col.FloatToUShortClamped(Col.UShortToFloat(col.G) * scalar), \n                Col.FloatToUShortClamped(Col.UShortToFloat(col.B) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator *(float scalar, C3us col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator /(C3us col, float scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator /(float scalar, C3us col)\n        {\n            return new C3us(\n                Col.FloatToUShortClamped(scalar / Col.UShortToFloat(col.R)), \n                Col.FloatToUShortClamped(scalar / Col.UShortToFloat(col.G)), \n                Col.FloatToUShortClamped(scalar / Col.UShortToFloat(col.B)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator *(C3us col, double scalar)\n        {\n            return new C3us(\n                Col.DoubleToUShortClamped(Col.UShortToDouble(col.R) * scalar), \n                Col.DoubleToUShortClamped(Col.UShortToDouble(col.G) * scalar), \n                Col.DoubleToUShortClamped(Col.UShortToDouble(col.B) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator *(double scalar, C3us col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator /(C3us col, double scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator /(double scalar, C3us col)\n        {\n            return new C3us(\n                Col.DoubleToUShortClamped(scalar / Col.UShortToDouble(col.R)), \n                Col.DoubleToUShortClamped(scalar / Col.UShortToDouble(col.G)), \n                Col.DoubleToUShortClamped(scalar / Col.UShortToDouble(col.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator +(C3us c0, C3b c1)\n        {\n            return new C3us(\n                (ushort)(c0.R + Col.ByteToUShort(c1.R)), \n                (ushort)(c0.G + Col.ByteToUShort(c1.G)), \n                (ushort)(c0.B + Col.ByteToUShort(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator -(C3us c0, C3b c1)\n        {\n            return new C3us(\n                (ushort)(c0.R - Col.ByteToUShort(c1.R)), \n                (ushort)(c0.G - Col.ByteToUShort(c1.G)), \n                (ushort)(c0.B - Col.ByteToUShort(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator +(C3us c0, C3ui c1)\n        {\n            return new C3us(\n                (ushort)(c0.R + Col.UIntToUShort(c1.R)), \n                (ushort)(c0.G + Col.UIntToUShort(c1.G)), \n                (ushort)(c0.B + Col.UIntToUShort(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator -(C3us c0, C3ui c1)\n        {\n            return new C3us(\n                (ushort)(c0.R - Col.UIntToUShort(c1.R)), \n                (ushort)(c0.G - Col.UIntToUShort(c1.G)), \n                (ushort)(c0.B - Col.UIntToUShort(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator +(C3us c0, C3f c1)\n        {\n            return new C3us(\n                (ushort)(c0.R + Col.FloatToUShort(c1.R)), \n                (ushort)(c0.G + Col.FloatToUShort(c1.G)), \n                (ushort)(c0.B + Col.FloatToUShort(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator -(C3us c0, C3f c1)\n        {\n            return new C3us(\n                (ushort)(c0.R - Col.FloatToUShort(c1.R)), \n                (ushort)(c0.G - Col.FloatToUShort(c1.G)), \n                (ushort)(c0.B - Col.FloatToUShort(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator +(C3us c0, C3d c1)\n        {\n            return new C3us(\n                (ushort)(c0.R + Col.DoubleToUShort(c1.R)), \n                (ushort)(c0.G + Col.DoubleToUShort(c1.G)), \n                (ushort)(c0.B + Col.DoubleToUShort(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator -(C3us c0, C3d c1)\n        {\n            return new C3us(\n                (ushort)(c0.R - Col.DoubleToUShort(c1.R)), \n                (ushort)(c0.G - Col.DoubleToUShort(c1.G)), \n                (ushort)(c0.B - Col.DoubleToUShort(c1.B)));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator *(C3us col, ushort scalar)\n        {\n            return new C3us((ushort)(col.R * scalar), (ushort)(col.G * scalar), (ushort)(col.B * scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator *(ushort scalar, C3us col)\n        {\n            return new C3us((ushort)(scalar * col.R), (ushort)(scalar * col.G), (ushort)(scalar * col.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator /(C3us col, ushort scalar)\n        {\n            return new C3us((ushort)(col.R / scalar), (ushort)(col.G / scalar), (ushort)(col.B / scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator /(ushort scalar, C3us col)\n        {\n            return new C3us((ushort)(scalar / col.R), (ushort)(scalar / col.G), (ushort)(scalar / col.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator *(C3us c0, C3us c1)\n        {\n            return new C3us((ushort)(c0.R * c1.R), (ushort)(c0.G * c1.G), (ushort)(c0.B * c1.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator /(C3us c0, C3us c1)\n        {\n            return new C3us((ushort)(c0.R / c1.R), (ushort)(c0.G / c1.G), (ushort)(c0.B / c1.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator +(C3us c0, C3us c1)\n        {\n            return new C3us(\n                (65535 - c0.R > c1.R) ? c0.R + c1.R : 65535, \n                (65535 - c0.G > c1.G) ? c0.G + c1.G : 65535, \n                (65535 - c0.B > c1.B) ? c0.B + c1.B : 65535\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator +(C3us col, ushort scalar)\n        {\n            return new C3us(\n                (65535 - col.R > scalar) ? col.R + scalar : 65535, \n                (65535 - col.G > scalar) ? col.G + scalar : 65535, \n                (65535 - col.B > scalar) ? col.B + scalar : 65535\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator +(ushort scalar, C3us col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator -(C3us c0, C3us c1)\n        {\n            return new C3us(\n                (c0.R > c1.R) ? c0.R - c1.R : 0, \n                (c0.G > c1.G) ? c0.G - c1.G : 0, \n                (c0.B > c1.B) ? c0.B - c1.B : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator -(C3us col, ushort scalar)\n        {\n            return new C3us(\n                (col.R > scalar) ? col.R - scalar : 0, \n                (col.G > scalar) ? col.G - scalar : 0, \n                (col.B > scalar) ? col.B - scalar : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us operator -(ushort scalar, C3us col)\n        {\n            return new C3us(\n                (scalar > col.R) ? scalar - col.R : 0, \n                (scalar > col.G) ? scalar - col.G : 0, \n                (scalar > col.B) ? scalar - col.B : 0\n            );\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(ushort min, ushort max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us Clamped(ushort min, ushort max)\n        {\n            return new C3us(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max));\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. \n        /// </summary>\n        public readonly int Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return R + G + B; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). \n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). \n        /// </summary>\n        public readonly ushort NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(R, G, B); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). \n        /// </summary>\n        public readonly ushort NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(R, G, B); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C3us o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C3us, int, ushort> Setter =\n            (ref C3us color, int i, ushort value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us LinearInterp(float t, C3us a, C3us b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us LinearInterp(V3f t, C3us a, C3us b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us LinearInterp(double t, C3us a, C3us b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us LinearInterp(V3d t, C3us a, C3us b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us DivideByInt(C3us c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3us.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C3us result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC3us();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                ushort[] values = new ushort[4] { 65535, 65535, 65535, 65535 };\n\n                ushort parse(Text t)\n                {\n                    if (!ushort.TryParse(t.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out ushort value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C3us(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3us.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C3us result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3us color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<ushort>.Parse, C3us.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3us color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us Parse(Text t)\n            => TryParse(t, out C3us result) ? result : throw new FormatException($\"{t} is not a valid C3us color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C3us> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C3us other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return Col.UShortToDouble(R); }\n            set { R = Col.DoubleToUShortClamped(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return Col.UShortToDouble(G); }\n            set { G = Col.DoubleToUShortClamped(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return Col.UShortToDouble(B); }\n            set { B = Col.DoubleToUShortClamped(value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3us Lerp(this float t, C3us a, C3us b)\n            => new C3us(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3us Lerp(this V3f t, C3us a, C3us b)\n            => new C3us(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3us Lerp(this double t, C3us a, C3us b)\n            => new C3us(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3us Lerp(this V3d t, C3us a, C3us b)\n            => new C3us(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C3us a, C3us b, ushort tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3us\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C3us c, ushort epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBB.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C3us c)\n            => c.ToC3b().ToHexString();\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3us a, C3us b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3us col, ushort s)\n        {\n            return (col.R < s && col.G < s && col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(ushort s, C3us col)\n        {\n            return (s < col.R && s < col.G && s < col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3us a, C3us b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3us col, ushort s)\n        {\n            return (col.R < s || col.G < s || col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(ushort s, C3us col)\n        {\n            return (s < col.R || s < col.G || s < col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3us a, C3us b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3us col, ushort s)\n        {\n            return (col.R > s && col.G > s && col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(ushort s, C3us col)\n        {\n            return (s > col.R && s > col.G && s > col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3us a, C3us b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3us col, ushort s)\n        {\n            return (col.R > s || col.G > s || col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(ushort s, C3us col)\n        {\n            return (s > col.R || s > col.G || s > col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3us a, C3us b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3us col, ushort s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(ushort s, C3us col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3us a, C3us b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3us col, ushort s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(ushort s, C3us col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3us a, C3us b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3us col, ushort s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(ushort s, C3us col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3us a, C3us b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3us col, ushort s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(ushort s, C3us col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3us a, C3us b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3us col, ushort s)\n        {\n            return (col.R == s && col.G == s && col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(ushort s, C3us col)\n        {\n            return (s == col.R && s == col.G && s == col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3us a, C3us b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3us col, ushort s)\n        {\n            return (col.R == s || col.G == s || col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(ushort s, C3us col)\n        {\n            return (s == col.R || s == col.G || s == col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3us a, C3us b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3us col, ushort s)\n        {\n            return (col.R != s && col.G != s && col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(ushort s, C3us col)\n        {\n            return (s != col.R && s != col.G && s != col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3us a, C3us b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3us col, ushort s)\n        {\n            return (col.R != s || col.G != s || col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(ushort s, C3us col)\n        {\n            return (s != col.R || s != col.G || s != col.B);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us LinCom(\n            C3us p0, C3us p1, C3us p2, C3us p3, ref Tup4<float> w)\n        {\n            return new C3us(\n                Col.UShortInFloatToUShortClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.UShortInFloatToUShortClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.UShortInFloatToUShortClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinComRawF(\n            C3us p0, C3us p1, C3us p2, C3us p3, ref Tup4<float> w)\n        {\n            return new C3f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us LinCom(\n            C3us p0, C3us p1, C3us p2, C3us p3, ref Tup4<double> w)\n        {\n            return new C3us(\n                Col.UShortInDoubleToUShortClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.UShortInDoubleToUShortClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.UShortInDoubleToUShortClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinComRawD(\n            C3us p0, C3us p1, C3us p2, C3us p3, ref Tup4<double> w)\n        {\n            return new C3d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us LinCom(\n            C3us p0, C3us p1, C3us p2, C3us p3, C3us p4, C3us p5, ref Tup6<float> w)\n        {\n            return new C3us(\n                Col.UShortInFloatToUShortClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.UShortInFloatToUShortClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.UShortInFloatToUShortClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinComRawF(\n            C3us p0, C3us p1, C3us p2, C3us p3, C3us p4, C3us p5, ref Tup6<float> w)\n        {\n            return new C3f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3us LinCom(\n            C3us p0, C3us p1, C3us p2, C3us p3, C3us p4, C3us p5, ref Tup6<double> w)\n        {\n            return new C3us(\n                Col.UShortInDoubleToUShortClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.UShortInDoubleToUShortClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.UShortInDoubleToUShortClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinComRawD(\n            C3us p0, C3us p1, C3us p2, C3us p3, C3us p4, C3us p5, ref Tup6<double> w)\n        {\n            return new C3d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C3us\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C3us c, ushort epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3us\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C3us c, ushort epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C3ui\n\n    /// <summary>\n    /// Represents an RGB color with each channel stored as a <see cref=\"uint\"/> value within [0, 2^32 - 1].\n    /// </summary>\n    [Serializable]\n    public partial struct C3ui : IFormattable, IEquatable<C3ui>, IRGB\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"uint\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(uint r, uint g, uint b)\n        {\n            R = r; G = g; B = b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> values.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(int r, int g, int b)\n        {\n            R = (uint)r; G = (uint)g; B = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> values.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(long r, long g, long b)\n        {\n            R = (uint)r; G = (uint)g; B = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(float r, float g, float b)\n        {\n            R = Col.FloatToUIntClamped(r);\n            G = Col.FloatToUIntClamped(g);\n            B = Col.FloatToUIntClamped(b);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(double r, double g, double b)\n        {\n            R = Col.DoubleToUIntClamped(r);\n            G = Col.DoubleToUIntClamped(g);\n            B = Col.DoubleToUIntClamped(b);\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"uint\"/> value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(uint gray)\n        {\n            R = gray; G = gray; B = gray;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(float gray)\n        {\n            var value = Col.FloatToUIntClamped(gray);\n            R = value; G = value; B = value;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(double gray)\n        {\n            var value = Col.DoubleToUIntClamped(gray);\n            R = value; G = value; B = value;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C3b color)\n        {\n            R = Col.ByteToUInt(color.R);\n            G = Col.ByteToUInt(color.G);\n            B = Col.ByteToUInt(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C3us color)\n        {\n            R = Col.UShortToUInt(color.R);\n            G = Col.UShortToUInt(color.G);\n            B = Col.UShortToUInt(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C3ui color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C3f color)\n        {\n            R = Col.FloatToUIntClamped(color.R);\n            G = Col.FloatToUIntClamped(color.G);\n            B = Col.FloatToUIntClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C3d color)\n        {\n            R = Col.DoubleToUIntClamped(color.R);\n            G = Col.DoubleToUIntClamped(color.G);\n            B = Col.DoubleToUIntClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C4b color)\n        {\n            R = Col.ByteToUInt(color.R);\n            G = Col.ByteToUInt(color.G);\n            B = Col.ByteToUInt(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C4us color)\n        {\n            R = Col.UShortToUInt(color.R);\n            G = Col.UShortToUInt(color.G);\n            B = Col.UShortToUInt(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C4ui color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C4f color)\n        {\n            R = Col.FloatToUIntClamped(color.R);\n            G = Col.FloatToUIntClamped(color.G);\n            B = Col.FloatToUIntClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(C4d color)\n        {\n            R = Col.DoubleToUIntClamped(color.R);\n            G = Col.DoubleToUIntClamped(color.G);\n            B = Col.DoubleToUIntClamped(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(V3ui vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(V3l vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(V3f vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(V3d vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(V4ui vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(V4l vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(V4f vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(V4d vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(Func<int, uint> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(byte[] values)\n        {\n            R = Col.ByteToUInt(values[0]);\n            G = Col.ByteToUInt(values[1]);\n            B = Col.ByteToUInt(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(byte[] values, int start)\n        {\n            R = Col.ByteToUInt(values[start + 0]);\n            G = Col.ByteToUInt(values[start + 1]);\n            B = Col.ByteToUInt(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(ushort[] values)\n        {\n            R = Col.UShortToUInt(values[0]);\n            G = Col.UShortToUInt(values[1]);\n            B = Col.UShortToUInt(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(ushort[] values, int start)\n        {\n            R = Col.UShortToUInt(values[start + 0]);\n            G = Col.UShortToUInt(values[start + 1]);\n            B = Col.UShortToUInt(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(uint[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(uint[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(float[] values)\n        {\n            R = Col.FloatToUIntClamped(values[0]);\n            G = Col.FloatToUIntClamped(values[1]);\n            B = Col.FloatToUIntClamped(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(float[] values, int start)\n        {\n            R = Col.FloatToUIntClamped(values[start + 0]);\n            G = Col.FloatToUIntClamped(values[start + 1]);\n            B = Col.FloatToUIntClamped(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(double[] values)\n        {\n            R = Col.DoubleToUIntClamped(values[0]);\n            G = Col.DoubleToUIntClamped(values[1]);\n            B = Col.DoubleToUIntClamped(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3ui(double[] values, int start)\n        {\n            R = Col.DoubleToUIntClamped(values[start + 0]);\n            G = Col.DoubleToUIntClamped(values[start + 1]);\n            B = Col.DoubleToUIntClamped(values[start + 2]);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C3b color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC3b(C3b c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C3us color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC3us(C3us c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C3f color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC3f(C3f c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C3d color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC3d(C3d c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C4b color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC4b(C4b c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C4us color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC4us(C4us c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C4ui color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC4ui(C4ui c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C4f color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC4f(C4f c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(C4d color)\n            => new C3ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromC4d(C4d c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(V3ui v)\n            => new C3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from a <see cref=\"V3ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromV3ui(V3ui c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(V3l v)\n            => new C3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromV3l(V3l c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(V3f v)\n            => new C3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromV3f(V3f c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(V3d v)\n            => new C3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromV3d(V3d c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(V4ui v)\n            => new C3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from a <see cref=\"V4ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromV4ui(V4ui c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(V4l v)\n            => new C3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromV4l(V4l c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(V4f v)\n            => new C3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromV4f(V4f c) => new C3ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(V4d v)\n            => new C3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3ui\"/> color from a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui FromV4d(V4d c) => new C3ui(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(byte[] values)\n            => new C3ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C3ui color)\n            => new byte[] { Col.UIntToByte(color.R), Col.UIntToByte(color.G), Col.UIntToByte(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(ushort[] values)\n            => new C3ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C3ui color)\n            => new ushort[] { Col.UIntToUShort(color.R), Col.UIntToUShort(color.G), Col.UIntToUShort(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(uint[] values)\n            => new C3ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C3ui color)\n            => new uint[] { (color.R), (color.G), (color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(float[] values)\n            => new C3ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C3ui color)\n            => new float[] { Col.UIntToFloat(color.R), Col.UIntToFloat(color.G), Col.UIntToFloat(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3ui(double[] values)\n            => new C3ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C3ui color)\n            => new double[] { Col.UIntToDouble(color.R), Col.UIntToDouble(color.G), Col.UIntToDouble(color.B) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b Map(Func<uint, byte> channel_fun)\n        {\n            return new C3b(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us Map(Func<uint, ushort> channel_fun)\n        {\n            return new C3us(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui Map(Func<uint, uint> channel_fun)\n        {\n            return new C3ui(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f Map(Func<uint, float> channel_fun)\n        {\n            return new C3f(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d Map(Func<uint, double> channel_fun)\n        {\n            return new C3d(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly uint[] ToArray()\n            => (uint[])this;\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe uint this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (uint* ptr = &R) { ptr[i] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (uint* ptr = &R) { return ptr[i]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C3ui with all components zero.\n        /// </summary>\n        public static C3ui Zero => new C3ui(0, 0, 0);\n\n        // Web colors\n        public static C3ui AliceBlue => new C3ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.972549), Col.DoubleToUIntClamped(1));\n        public static C3ui AntiqueWhite => new C3ui(Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.921569), Col.DoubleToUIntClamped(0.843137));\n        public static C3ui Aqua => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C3ui Aquamarine => new C3ui(Col.DoubleToUIntClamped(0.498039), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.831373));\n        public static C3ui Azure => new C3ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C3ui Beige => new C3ui(Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.862745));\n        public static C3ui Bisque => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.894118), Col.DoubleToUIntClamped(0.768627));\n        public static C3ui Black => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0));\n        public static C3ui BlanchedAlmond => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.921569), Col.DoubleToUIntClamped(0.803922));\n        public static C3ui Blue => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1));\n        public static C3ui BlueViolet => new C3ui(Col.DoubleToUIntClamped(0.541176), Col.DoubleToUIntClamped(0.168627), Col.DoubleToUIntClamped(0.886275));\n        public static C3ui Brown => new C3ui(Col.DoubleToUIntClamped(0.647059), Col.DoubleToUIntClamped(0.164706), Col.DoubleToUIntClamped(0.164706));\n        public static C3ui BurlyWood => new C3ui(Col.DoubleToUIntClamped(0.870588), Col.DoubleToUIntClamped(0.721569), Col.DoubleToUIntClamped(0.529412));\n        public static C3ui CadetBlue => new C3ui(Col.DoubleToUIntClamped(0.372549), Col.DoubleToUIntClamped(0.619608), Col.DoubleToUIntClamped(0.627451));\n        public static C3ui Chartreuse => new C3ui(Col.DoubleToUIntClamped(0.498039), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0));\n        public static C3ui Chocolate => new C3ui(Col.DoubleToUIntClamped(0.823529), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.117647));\n        public static C3ui Coral => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.498039), Col.DoubleToUIntClamped(0.313725));\n        public static C3ui CornflowerBlue => new C3ui(Col.DoubleToUIntClamped(0.392157), Col.DoubleToUIntClamped(0.584314), Col.DoubleToUIntClamped(0.929412));\n        public static C3ui Cornsilk => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.972549), Col.DoubleToUIntClamped(0.862745));\n        public static C3ui Crimson => new C3ui(Col.DoubleToUIntClamped(0.862745), Col.DoubleToUIntClamped(0.078431), Col.DoubleToUIntClamped(0.235294));\n        public static C3ui Cyan => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C3ui DarkBlue => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.545098));\n        public static C3ui DarkCyan => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0.545098));\n        public static C3ui DarkGoldenRod => new C3ui(Col.DoubleToUIntClamped(0.721569), Col.DoubleToUIntClamped(0.52549), Col.DoubleToUIntClamped(0.043137));\n        public static C3ui DarkGray => new C3ui(Col.DoubleToUIntClamped(0.662745), Col.DoubleToUIntClamped(0.662745), Col.DoubleToUIntClamped(0.662745));\n        public static C3ui DarkGrey => new C3ui(Col.DoubleToUIntClamped(0.662745), Col.DoubleToUIntClamped(0.662745), Col.DoubleToUIntClamped(0.662745));\n        public static C3ui DarkGreen => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.392157), Col.DoubleToUIntClamped(0));\n        public static C3ui DarkKhaki => new C3ui(Col.DoubleToUIntClamped(0.741176), Col.DoubleToUIntClamped(0.717647), Col.DoubleToUIntClamped(0.419608));\n        public static C3ui DarkMagenta => new C3ui(Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.545098));\n        public static C3ui DarkOliveGreen => new C3ui(Col.DoubleToUIntClamped(0.333333), Col.DoubleToUIntClamped(0.419608), Col.DoubleToUIntClamped(0.184314));\n        public static C3ui DarkOrange => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.54902), Col.DoubleToUIntClamped(0));\n        public static C3ui DarkOrchid => new C3ui(Col.DoubleToUIntClamped(0.6), Col.DoubleToUIntClamped(0.196078), Col.DoubleToUIntClamped(0.8));\n        public static C3ui DarkRed => new C3ui(Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0));\n        public static C3ui DarkSalmon => new C3ui(Col.DoubleToUIntClamped(0.913725), Col.DoubleToUIntClamped(0.588235), Col.DoubleToUIntClamped(0.478431));\n        public static C3ui DarkSeaGreen => new C3ui(Col.DoubleToUIntClamped(0.560784), Col.DoubleToUIntClamped(0.737255), Col.DoubleToUIntClamped(0.560784));\n        public static C3ui DarkSlateBlue => new C3ui(Col.DoubleToUIntClamped(0.282353), Col.DoubleToUIntClamped(0.239216), Col.DoubleToUIntClamped(0.545098));\n        public static C3ui DarkSlateGray => new C3ui(Col.DoubleToUIntClamped(0.184314), Col.DoubleToUIntClamped(0.309804), Col.DoubleToUIntClamped(0.309804));\n        public static C3ui DarkSlateGrey => new C3ui(Col.DoubleToUIntClamped(0.184314), Col.DoubleToUIntClamped(0.309804), Col.DoubleToUIntClamped(0.309804));\n        public static C3ui DarkTurquoise => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.807843), Col.DoubleToUIntClamped(0.819608));\n        public static C3ui DarkViolet => new C3ui(Col.DoubleToUIntClamped(0.580392), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.827451));\n        public static C3ui DeepPink => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.078431), Col.DoubleToUIntClamped(0.576471));\n        public static C3ui DeepSkyBlue => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.74902), Col.DoubleToUIntClamped(1));\n        public static C3ui DimGray => new C3ui(Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.411765));\n        public static C3ui DimGrey => new C3ui(Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.411765));\n        public static C3ui DodgerBlue => new C3ui(Col.DoubleToUIntClamped(0.117647), Col.DoubleToUIntClamped(0.564706), Col.DoubleToUIntClamped(1));\n        public static C3ui FireBrick => new C3ui(Col.DoubleToUIntClamped(0.698039), Col.DoubleToUIntClamped(0.133333), Col.DoubleToUIntClamped(0.133333));\n        public static C3ui FloralWhite => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.941176));\n        public static C3ui ForestGreen => new C3ui(Col.DoubleToUIntClamped(0.133333), Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0.133333));\n        public static C3ui Fuchsia => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1));\n        public static C3ui Gainsboro => new C3ui(Col.DoubleToUIntClamped(0.862745), Col.DoubleToUIntClamped(0.862745), Col.DoubleToUIntClamped(0.862745));\n        public static C3ui GhostWhite => new C3ui(Col.DoubleToUIntClamped(0.972549), Col.DoubleToUIntClamped(0.972549), Col.DoubleToUIntClamped(1));\n        public static C3ui Gold => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.843137), Col.DoubleToUIntClamped(0));\n        public static C3ui GoldenRod => new C3ui(Col.DoubleToUIntClamped(0.854902), Col.DoubleToUIntClamped(0.647059), Col.DoubleToUIntClamped(0.12549));\n        public static C3ui Gray => new C3ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961));\n        public static C3ui Grey => new C3ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961));\n        public static C3ui Green => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0));\n        public static C3ui GreenYellow => new C3ui(Col.DoubleToUIntClamped(0.678431), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.184314));\n        public static C3ui HoneyDew => new C3ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.941176));\n        public static C3ui HotPink => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.705882));\n        public static C3ui IndianRed  => new C3ui(Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.360784), Col.DoubleToUIntClamped(0.360784));\n        public static C3ui Indigo  => new C3ui(Col.DoubleToUIntClamped(0.294118), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.509804));\n        public static C3ui Ivory => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.941176));\n        public static C3ui Khaki => new C3ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.901961), Col.DoubleToUIntClamped(0.54902));\n        public static C3ui Lavender => new C3ui(Col.DoubleToUIntClamped(0.901961), Col.DoubleToUIntClamped(0.901961), Col.DoubleToUIntClamped(0.980392));\n        public static C3ui LavenderBlush => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.960784));\n        public static C3ui LawnGreen => new C3ui(Col.DoubleToUIntClamped(0.486275), Col.DoubleToUIntClamped(0.988235), Col.DoubleToUIntClamped(0));\n        public static C3ui LemonChiffon => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.803922));\n        public static C3ui LightBlue => new C3ui(Col.DoubleToUIntClamped(0.678431), Col.DoubleToUIntClamped(0.847059), Col.DoubleToUIntClamped(0.901961));\n        public static C3ui LightCoral => new C3ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961));\n        public static C3ui LightCyan => new C3ui(Col.DoubleToUIntClamped(0.878431), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C3ui LightGoldenRodYellow => new C3ui(Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.823529));\n        public static C3ui LightGray => new C3ui(Col.DoubleToUIntClamped(0.827451), Col.DoubleToUIntClamped(0.827451), Col.DoubleToUIntClamped(0.827451));\n        public static C3ui LightGrey => new C3ui(Col.DoubleToUIntClamped(0.827451), Col.DoubleToUIntClamped(0.827451), Col.DoubleToUIntClamped(0.827451));\n        public static C3ui LightGreen => new C3ui(Col.DoubleToUIntClamped(0.564706), Col.DoubleToUIntClamped(0.933333), Col.DoubleToUIntClamped(0.564706));\n        public static C3ui LightPink => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.713725), Col.DoubleToUIntClamped(0.756863));\n        public static C3ui LightSalmon => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.627451), Col.DoubleToUIntClamped(0.478431));\n        public static C3ui LightSeaGreen => new C3ui(Col.DoubleToUIntClamped(0.12549), Col.DoubleToUIntClamped(0.698039), Col.DoubleToUIntClamped(0.666667));\n        public static C3ui LightSkyBlue => new C3ui(Col.DoubleToUIntClamped(0.529412), Col.DoubleToUIntClamped(0.807843), Col.DoubleToUIntClamped(0.980392));\n        public static C3ui LightSlateGray => new C3ui(Col.DoubleToUIntClamped(0.466667), Col.DoubleToUIntClamped(0.533333), Col.DoubleToUIntClamped(0.6));\n        public static C3ui LightSlateGrey => new C3ui(Col.DoubleToUIntClamped(0.466667), Col.DoubleToUIntClamped(0.533333), Col.DoubleToUIntClamped(0.6));\n        public static C3ui LightSteelBlue => new C3ui(Col.DoubleToUIntClamped(0.690196), Col.DoubleToUIntClamped(0.768627), Col.DoubleToUIntClamped(0.870588));\n        public static C3ui LightYellow => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.878431));\n        public static C3ui Lime => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0));\n        public static C3ui LimeGreen => new C3ui(Col.DoubleToUIntClamped(0.196078), Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.196078));\n        public static C3ui Linen => new C3ui(Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.901961));\n        public static C3ui Magenta => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1));\n        public static C3ui Maroon => new C3ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0));\n        public static C3ui MediumAquaMarine => new C3ui(Col.DoubleToUIntClamped(0.4), Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.666667));\n        public static C3ui MediumBlue => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.803922));\n        public static C3ui MediumOrchid => new C3ui(Col.DoubleToUIntClamped(0.729412), Col.DoubleToUIntClamped(0.333333), Col.DoubleToUIntClamped(0.827451));\n        public static C3ui MediumPurple => new C3ui(Col.DoubleToUIntClamped(0.576471), Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.847059));\n        public static C3ui MediumSeaGreen => new C3ui(Col.DoubleToUIntClamped(0.235294), Col.DoubleToUIntClamped(0.701961), Col.DoubleToUIntClamped(0.443137));\n        public static C3ui MediumSlateBlue => new C3ui(Col.DoubleToUIntClamped(0.482353), Col.DoubleToUIntClamped(0.407843), Col.DoubleToUIntClamped(0.933333));\n        public static C3ui MediumSpringGreen => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.603922));\n        public static C3ui MediumTurquoise => new C3ui(Col.DoubleToUIntClamped(0.282353), Col.DoubleToUIntClamped(0.819608), Col.DoubleToUIntClamped(0.8));\n        public static C3ui MediumVioletRed => new C3ui(Col.DoubleToUIntClamped(0.780392), Col.DoubleToUIntClamped(0.082353), Col.DoubleToUIntClamped(0.521569));\n        public static C3ui MidnightBlue => new C3ui(Col.DoubleToUIntClamped(0.098039), Col.DoubleToUIntClamped(0.098039), Col.DoubleToUIntClamped(0.439216));\n        public static C3ui MintCream => new C3ui(Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.980392));\n        public static C3ui MistyRose => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.894118), Col.DoubleToUIntClamped(0.882353));\n        public static C3ui Moccasin => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.894118), Col.DoubleToUIntClamped(0.709804));\n        public static C3ui NavajoWhite => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.870588), Col.DoubleToUIntClamped(0.678431));\n        public static C3ui Navy => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.501961));\n        public static C3ui OldLace => new C3ui(Col.DoubleToUIntClamped(0.992157), Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.901961));\n        public static C3ui Olive => new C3ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0));\n        public static C3ui OliveDrab => new C3ui(Col.DoubleToUIntClamped(0.419608), Col.DoubleToUIntClamped(0.556863), Col.DoubleToUIntClamped(0.137255));\n        public static C3ui Orange => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.647059), Col.DoubleToUIntClamped(0));\n        public static C3ui OrangeRed => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.270588), Col.DoubleToUIntClamped(0));\n        public static C3ui Orchid => new C3ui(Col.DoubleToUIntClamped(0.854902), Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.839216));\n        public static C3ui PaleGoldenRod => new C3ui(Col.DoubleToUIntClamped(0.933333), Col.DoubleToUIntClamped(0.909804), Col.DoubleToUIntClamped(0.666667));\n        public static C3ui PaleGreen => new C3ui(Col.DoubleToUIntClamped(0.596078), Col.DoubleToUIntClamped(0.984314), Col.DoubleToUIntClamped(0.596078));\n        public static C3ui PaleTurquoise => new C3ui(Col.DoubleToUIntClamped(0.686275), Col.DoubleToUIntClamped(0.933333), Col.DoubleToUIntClamped(0.933333));\n        public static C3ui PaleVioletRed => new C3ui(Col.DoubleToUIntClamped(0.847059), Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.576471));\n        public static C3ui PapayaWhip => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.937255), Col.DoubleToUIntClamped(0.835294));\n        public static C3ui PeachPuff => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.854902), Col.DoubleToUIntClamped(0.72549));\n        public static C3ui Peru => new C3ui(Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.521569), Col.DoubleToUIntClamped(0.247059));\n        public static C3ui Pink => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.752941), Col.DoubleToUIntClamped(0.796078));\n        public static C3ui Plum => new C3ui(Col.DoubleToUIntClamped(0.866667), Col.DoubleToUIntClamped(0.627451), Col.DoubleToUIntClamped(0.866667));\n        public static C3ui PowderBlue => new C3ui(Col.DoubleToUIntClamped(0.690196), Col.DoubleToUIntClamped(0.878431), Col.DoubleToUIntClamped(0.901961));\n        public static C3ui Purple => new C3ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.501961));\n        public static C3ui Red => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0));\n        public static C3ui RosyBrown => new C3ui(Col.DoubleToUIntClamped(0.737255), Col.DoubleToUIntClamped(0.560784), Col.DoubleToUIntClamped(0.560784));\n        public static C3ui RoyalBlue => new C3ui(Col.DoubleToUIntClamped(0.254902), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.882353));\n        public static C3ui SaddleBrown => new C3ui(Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0.270588), Col.DoubleToUIntClamped(0.07451));\n        public static C3ui Salmon => new C3ui(Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.447059));\n        public static C3ui SandyBrown => new C3ui(Col.DoubleToUIntClamped(0.956863), Col.DoubleToUIntClamped(0.643137), Col.DoubleToUIntClamped(0.376471));\n        public static C3ui SeaGreen => new C3ui(Col.DoubleToUIntClamped(0.180392), Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0.341176));\n        public static C3ui SeaShell => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.933333));\n        public static C3ui Sienna => new C3ui(Col.DoubleToUIntClamped(0.627451), Col.DoubleToUIntClamped(0.321569), Col.DoubleToUIntClamped(0.176471));\n        public static C3ui Silver => new C3ui(Col.DoubleToUIntClamped(0.752941), Col.DoubleToUIntClamped(0.752941), Col.DoubleToUIntClamped(0.752941));\n        public static C3ui SkyBlue => new C3ui(Col.DoubleToUIntClamped(0.529412), Col.DoubleToUIntClamped(0.807843), Col.DoubleToUIntClamped(0.921569));\n        public static C3ui SlateBlue => new C3ui(Col.DoubleToUIntClamped(0.415686), Col.DoubleToUIntClamped(0.352941), Col.DoubleToUIntClamped(0.803922));\n        public static C3ui SlateGray => new C3ui(Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.564706));\n        public static C3ui SlateGrey => new C3ui(Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.564706));\n        public static C3ui Snow => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.980392));\n        public static C3ui SpringGreen => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.498039));\n        public static C3ui SteelBlue => new C3ui(Col.DoubleToUIntClamped(0.27451), Col.DoubleToUIntClamped(0.509804), Col.DoubleToUIntClamped(0.705882));\n        public static C3ui Tan => new C3ui(Col.DoubleToUIntClamped(0.823529), Col.DoubleToUIntClamped(0.705882), Col.DoubleToUIntClamped(0.54902));\n        public static C3ui Teal => new C3ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961));\n        public static C3ui Thistle => new C3ui(Col.DoubleToUIntClamped(0.847059), Col.DoubleToUIntClamped(0.74902), Col.DoubleToUIntClamped(0.847059));\n        public static C3ui Tomato => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.388235), Col.DoubleToUIntClamped(0.278431));\n        public static C3ui Turquoise => new C3ui(Col.DoubleToUIntClamped(0.25098), Col.DoubleToUIntClamped(0.878431), Col.DoubleToUIntClamped(0.815686));\n        public static C3ui Violet => new C3ui(Col.DoubleToUIntClamped(0.933333), Col.DoubleToUIntClamped(0.509804), Col.DoubleToUIntClamped(0.933333));\n        public static C3ui Wheat => new C3ui(Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.870588), Col.DoubleToUIntClamped(0.701961));\n        public static C3ui White => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C3ui WhiteSmoke => new C3ui(Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.960784));\n        public static C3ui Yellow => new C3ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0));\n        public static C3ui YellowGreen => new C3ui(Col.DoubleToUIntClamped(0.603922), Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.196078));\n\n        public static C3ui DarkYellow => Olive;\n\n        public static C3ui VRVisGreen => new C3ui(Col.DoubleToUIntClamped(0.698), Col.DoubleToUIntClamped(0.851), Col.DoubleToUIntClamped(0.008));\n\n        public static C3ui Gray10 => new C3ui(Col.DoubleToUIntClamped(0.1));\n        public static C3ui Gray20 => new C3ui(Col.DoubleToUIntClamped(0.2));\n        public static C3ui Gray30 => new C3ui(Col.DoubleToUIntClamped(0.3));\n        public static C3ui Gray40 => new C3ui(Col.DoubleToUIntClamped(0.4));\n        public static C3ui Gray50 => new C3ui(Col.DoubleToUIntClamped(0.5));\n        public static C3ui Gray60 => new C3ui(Col.DoubleToUIntClamped(0.6));\n        public static C3ui Gray70 => new C3ui(Col.DoubleToUIntClamped(0.7));\n        public static C3ui Gray80 => new C3ui(Col.DoubleToUIntClamped(0.8));\n        public static C3ui Gray90 => new C3ui(Col.DoubleToUIntClamped(0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C3ui a, C3ui b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C3ui a, C3ui b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator *(C3ui col, float scalar)\n        {\n            return new C3ui(\n                Col.FloatToUIntClamped(Col.UIntToFloat(col.R) * scalar), \n                Col.FloatToUIntClamped(Col.UIntToFloat(col.G) * scalar), \n                Col.FloatToUIntClamped(Col.UIntToFloat(col.B) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator *(float scalar, C3ui col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator /(C3ui col, float scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator /(float scalar, C3ui col)\n        {\n            return new C3ui(\n                Col.FloatToUIntClamped(scalar / Col.UIntToFloat(col.R)), \n                Col.FloatToUIntClamped(scalar / Col.UIntToFloat(col.G)), \n                Col.FloatToUIntClamped(scalar / Col.UIntToFloat(col.B)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator *(C3ui col, double scalar)\n        {\n            return new C3ui(\n                Col.DoubleToUIntClamped(Col.UIntToDouble(col.R) * scalar), \n                Col.DoubleToUIntClamped(Col.UIntToDouble(col.G) * scalar), \n                Col.DoubleToUIntClamped(Col.UIntToDouble(col.B) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator *(double scalar, C3ui col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator /(C3ui col, double scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator /(double scalar, C3ui col)\n        {\n            return new C3ui(\n                Col.DoubleToUIntClamped(scalar / Col.UIntToDouble(col.R)), \n                Col.DoubleToUIntClamped(scalar / Col.UIntToDouble(col.G)), \n                Col.DoubleToUIntClamped(scalar / Col.UIntToDouble(col.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator +(C3ui c0, C3b c1)\n        {\n            return new C3ui(\n                (uint)(c0.R + Col.ByteToUInt(c1.R)), \n                (uint)(c0.G + Col.ByteToUInt(c1.G)), \n                (uint)(c0.B + Col.ByteToUInt(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator -(C3ui c0, C3b c1)\n        {\n            return new C3ui(\n                (uint)(c0.R - Col.ByteToUInt(c1.R)), \n                (uint)(c0.G - Col.ByteToUInt(c1.G)), \n                (uint)(c0.B - Col.ByteToUInt(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator +(C3ui c0, C3us c1)\n        {\n            return new C3ui(\n                (uint)(c0.R + Col.UShortToUInt(c1.R)), \n                (uint)(c0.G + Col.UShortToUInt(c1.G)), \n                (uint)(c0.B + Col.UShortToUInt(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator -(C3ui c0, C3us c1)\n        {\n            return new C3ui(\n                (uint)(c0.R - Col.UShortToUInt(c1.R)), \n                (uint)(c0.G - Col.UShortToUInt(c1.G)), \n                (uint)(c0.B - Col.UShortToUInt(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator +(C3ui c0, C3f c1)\n        {\n            return new C3ui(\n                (uint)(c0.R + Col.FloatToUInt(c1.R)), \n                (uint)(c0.G + Col.FloatToUInt(c1.G)), \n                (uint)(c0.B + Col.FloatToUInt(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator -(C3ui c0, C3f c1)\n        {\n            return new C3ui(\n                (uint)(c0.R - Col.FloatToUInt(c1.R)), \n                (uint)(c0.G - Col.FloatToUInt(c1.G)), \n                (uint)(c0.B - Col.FloatToUInt(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator +(C3ui c0, C3d c1)\n        {\n            return new C3ui(\n                (uint)(c0.R + Col.DoubleToUInt(c1.R)), \n                (uint)(c0.G + Col.DoubleToUInt(c1.G)), \n                (uint)(c0.B + Col.DoubleToUInt(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator -(C3ui c0, C3d c1)\n        {\n            return new C3ui(\n                (uint)(c0.R - Col.DoubleToUInt(c1.R)), \n                (uint)(c0.G - Col.DoubleToUInt(c1.G)), \n                (uint)(c0.B - Col.DoubleToUInt(c1.B)));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator *(C3ui col, uint scalar)\n        {\n            return new C3ui((uint)(col.R * scalar), (uint)(col.G * scalar), (uint)(col.B * scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator *(uint scalar, C3ui col)\n        {\n            return new C3ui((uint)(scalar * col.R), (uint)(scalar * col.G), (uint)(scalar * col.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator /(C3ui col, uint scalar)\n        {\n            return new C3ui((uint)(col.R / scalar), (uint)(col.G / scalar), (uint)(col.B / scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator /(uint scalar, C3ui col)\n        {\n            return new C3ui((uint)(scalar / col.R), (uint)(scalar / col.G), (uint)(scalar / col.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator *(C3ui c0, C3ui c1)\n        {\n            return new C3ui((uint)(c0.R * c1.R), (uint)(c0.G * c1.G), (uint)(c0.B * c1.B));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator /(C3ui c0, C3ui c1)\n        {\n            return new C3ui((uint)(c0.R / c1.R), (uint)(c0.G / c1.G), (uint)(c0.B / c1.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator +(C3ui c0, C3ui c1)\n        {\n            return new C3ui(\n                (UInt32.MaxValue - c0.R > c1.R) ? c0.R + c1.R : UInt32.MaxValue, \n                (UInt32.MaxValue - c0.G > c1.G) ? c0.G + c1.G : UInt32.MaxValue, \n                (UInt32.MaxValue - c0.B > c1.B) ? c0.B + c1.B : UInt32.MaxValue\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator +(C3ui col, uint scalar)\n        {\n            return new C3ui(\n                (UInt32.MaxValue - col.R > scalar) ? col.R + scalar : UInt32.MaxValue, \n                (UInt32.MaxValue - col.G > scalar) ? col.G + scalar : UInt32.MaxValue, \n                (UInt32.MaxValue - col.B > scalar) ? col.B + scalar : UInt32.MaxValue\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator +(uint scalar, C3ui col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator -(C3ui c0, C3ui c1)\n        {\n            return new C3ui(\n                (c0.R > c1.R) ? c0.R - c1.R : 0, \n                (c0.G > c1.G) ? c0.G - c1.G : 0, \n                (c0.B > c1.B) ? c0.B - c1.B : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator -(C3ui col, uint scalar)\n        {\n            return new C3ui(\n                (col.R > scalar) ? col.R - scalar : 0, \n                (col.G > scalar) ? col.G - scalar : 0, \n                (col.B > scalar) ? col.B - scalar : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui operator -(uint scalar, C3ui col)\n        {\n            return new C3ui(\n                (scalar > col.R) ? scalar - col.R : 0, \n                (scalar > col.G) ? scalar - col.G : 0, \n                (scalar > col.B) ? scalar - col.B : 0\n            );\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(uint min, uint max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui Clamped(uint min, uint max)\n        {\n            return new C3ui(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max));\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. \n        /// </summary>\n        public readonly long Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return R + G + B; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). \n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). \n        /// </summary>\n        public readonly uint NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(R, G, B); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). \n        /// </summary>\n        public readonly uint NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(R, G, B); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C3ui o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C3ui, int, uint> Setter =\n            (ref C3ui color, int i, uint value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui LinearInterp(float t, C3ui a, C3ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui LinearInterp(V3f t, C3ui a, C3ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui LinearInterp(double t, C3ui a, C3ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui LinearInterp(V3d t, C3ui a, C3ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui DivideByInt(C3ui c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3ui.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C3ui result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC3ui();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                uint[] values = new uint[4] { UInt32.MaxValue, UInt32.MaxValue, UInt32.MaxValue, UInt32.MaxValue };\n\n                uint parse(Text t)\n                {\n                    if (!uint.TryParse(t.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out uint value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C3ui(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3ui.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C3ui result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3ui color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<uint>.Parse, C3ui.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3ui color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui Parse(Text t)\n            => TryParse(t, out C3ui result) ? result : throw new FormatException($\"{t} is not a valid C3ui color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C3ui> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C3ui other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return Col.UIntToDouble(R); }\n            set { R = Col.DoubleToUIntClamped(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return Col.UIntToDouble(G); }\n            set { G = Col.DoubleToUIntClamped(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return Col.UIntToDouble(B); }\n            set { B = Col.DoubleToUIntClamped(value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3ui Lerp(this float t, C3ui a, C3ui b)\n            => new C3ui(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3ui Lerp(this V3f t, C3ui a, C3ui b)\n            => new C3ui(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3ui Lerp(this double t, C3ui a, C3ui b)\n            => new C3ui(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3ui Lerp(this V3d t, C3ui a, C3ui b)\n            => new C3ui(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C3ui a, C3ui b, uint tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C3ui c, uint epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBB.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C3ui c)\n            => c.ToC3b().ToHexString();\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3ui a, C3ui b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3ui col, uint s)\n        {\n            return (col.R < s && col.G < s && col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(uint s, C3ui col)\n        {\n            return (s < col.R && s < col.G && s < col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3ui a, C3ui b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3ui col, uint s)\n        {\n            return (col.R < s || col.G < s || col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(uint s, C3ui col)\n        {\n            return (s < col.R || s < col.G || s < col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3ui a, C3ui b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3ui col, uint s)\n        {\n            return (col.R > s && col.G > s && col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(uint s, C3ui col)\n        {\n            return (s > col.R && s > col.G && s > col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3ui a, C3ui b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3ui col, uint s)\n        {\n            return (col.R > s || col.G > s || col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(uint s, C3ui col)\n        {\n            return (s > col.R || s > col.G || s > col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3ui a, C3ui b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3ui col, uint s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(uint s, C3ui col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3ui a, C3ui b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3ui col, uint s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(uint s, C3ui col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3ui a, C3ui b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3ui col, uint s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(uint s, C3ui col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3ui a, C3ui b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3ui col, uint s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(uint s, C3ui col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3ui a, C3ui b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3ui col, uint s)\n        {\n            return (col.R == s && col.G == s && col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(uint s, C3ui col)\n        {\n            return (s == col.R && s == col.G && s == col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3ui a, C3ui b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3ui col, uint s)\n        {\n            return (col.R == s || col.G == s || col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(uint s, C3ui col)\n        {\n            return (s == col.R || s == col.G || s == col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3ui a, C3ui b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3ui col, uint s)\n        {\n            return (col.R != s && col.G != s && col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(uint s, C3ui col)\n        {\n            return (s != col.R && s != col.G && s != col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3ui a, C3ui b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3ui col, uint s)\n        {\n            return (col.R != s || col.G != s || col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(uint s, C3ui col)\n        {\n            return (s != col.R || s != col.G || s != col.B);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui LinCom(\n            C3ui p0, C3ui p1, C3ui p2, C3ui p3, ref Tup4<float> w)\n        {\n            return new C3ui(\n                Col.UIntInDoubleToUIntClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.UIntInDoubleToUIntClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.UIntInDoubleToUIntClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinComRawF(\n            C3ui p0, C3ui p1, C3ui p2, C3ui p3, ref Tup4<float> w)\n        {\n            return new C3f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui LinCom(\n            C3ui p0, C3ui p1, C3ui p2, C3ui p3, ref Tup4<double> w)\n        {\n            return new C3ui(\n                Col.UIntInDoubleToUIntClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.UIntInDoubleToUIntClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.UIntInDoubleToUIntClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinComRawD(\n            C3ui p0, C3ui p1, C3ui p2, C3ui p3, ref Tup4<double> w)\n        {\n            return new C3d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui LinCom(\n            C3ui p0, C3ui p1, C3ui p2, C3ui p3, C3ui p4, C3ui p5, ref Tup6<float> w)\n        {\n            return new C3ui(\n                Col.UIntInDoubleToUIntClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.UIntInDoubleToUIntClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.UIntInDoubleToUIntClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinComRawF(\n            C3ui p0, C3ui p1, C3ui p2, C3ui p3, C3ui p4, C3ui p5, ref Tup6<float> w)\n        {\n            return new C3f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui LinCom(\n            C3ui p0, C3ui p1, C3ui p2, C3ui p3, C3ui p4, C3ui p5, ref Tup6<double> w)\n        {\n            return new C3ui(\n                Col.UIntInDoubleToUIntClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.UIntInDoubleToUIntClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.UIntInDoubleToUIntClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinComRawD(\n            C3ui p0, C3ui p1, C3ui p2, C3ui p3, C3ui p4, C3ui p5, ref Tup6<double> w)\n        {\n            return new C3d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C3ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C3ui c, uint epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C3ui c, uint epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformC3uiExtensions\n    {\n        #region IRandomUniform extensions for C3ui\n\n        /// <summary>\n        /// Uses UniformUInt() to generate the elements of a C3ui color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3ui UniformC3ui(this IRandomUniform rnd)\n        {\n            return new C3ui(rnd.UniformUInt(), rnd.UniformUInt(), rnd.UniformUInt());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C3f\n\n    /// <summary>\n    /// Represents an RGB color with each channel stored as a <see cref=\"float\"/> value within [0, 1].\n    /// </summary>\n    [Serializable]\n    public partial struct C3f : IFormattable, IEquatable<C3f>, IRGB\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(float r, float g, float b)\n        {\n            R = r; G = g; B = b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(double r, double g, double b)\n        {\n            R = (float)(r);\n            G = (float)(g);\n            B = (float)(b);\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(float gray)\n        {\n            R = gray; G = gray; B = gray;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(double gray)\n        {\n            var value = (float)(gray);\n            R = value; G = value; B = value;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C3b color)\n        {\n            R = Col.ByteToFloat(color.R);\n            G = Col.ByteToFloat(color.G);\n            B = Col.ByteToFloat(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C3us color)\n        {\n            R = Col.UShortToFloat(color.R);\n            G = Col.UShortToFloat(color.G);\n            B = Col.UShortToFloat(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C3ui color)\n        {\n            R = Col.UIntToFloat(color.R);\n            G = Col.UIntToFloat(color.G);\n            B = Col.UIntToFloat(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C3f color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C3d color)\n        {\n            R = Col.DoubleToFloat(color.R);\n            G = Col.DoubleToFloat(color.G);\n            B = Col.DoubleToFloat(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C4b color)\n        {\n            R = Col.ByteToFloat(color.R);\n            G = Col.ByteToFloat(color.G);\n            B = Col.ByteToFloat(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C4us color)\n        {\n            R = Col.UShortToFloat(color.R);\n            G = Col.UShortToFloat(color.G);\n            B = Col.UShortToFloat(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C4ui color)\n        {\n            R = Col.UIntToFloat(color.R);\n            G = Col.UIntToFloat(color.G);\n            B = Col.UIntToFloat(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C4f color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(C4d color)\n        {\n            R = Col.DoubleToFloat(color.R);\n            G = Col.DoubleToFloat(color.G);\n            B = Col.DoubleToFloat(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(V3f vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(V3d vec)\n        {\n            R = (float)(vec.X);\n            G = (float)(vec.Y);\n            B = (float)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(V4f vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(V4d vec)\n        {\n            R = (float)(vec.X);\n            G = (float)(vec.Y);\n            B = (float)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(Func<int, float> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(byte[] values)\n        {\n            R = Col.ByteToFloat(values[0]);\n            G = Col.ByteToFloat(values[1]);\n            B = Col.ByteToFloat(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(byte[] values, int start)\n        {\n            R = Col.ByteToFloat(values[start + 0]);\n            G = Col.ByteToFloat(values[start + 1]);\n            B = Col.ByteToFloat(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(ushort[] values)\n        {\n            R = Col.UShortToFloat(values[0]);\n            G = Col.UShortToFloat(values[1]);\n            B = Col.UShortToFloat(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(ushort[] values, int start)\n        {\n            R = Col.UShortToFloat(values[start + 0]);\n            G = Col.UShortToFloat(values[start + 1]);\n            B = Col.UShortToFloat(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(uint[] values)\n        {\n            R = Col.UIntToFloat(values[0]);\n            G = Col.UIntToFloat(values[1]);\n            B = Col.UIntToFloat(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(uint[] values, int start)\n        {\n            R = Col.UIntToFloat(values[start + 0]);\n            G = Col.UIntToFloat(values[start + 1]);\n            B = Col.UIntToFloat(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(float[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(float[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(double[] values)\n        {\n            R = Col.DoubleToFloat(values[0]);\n            G = Col.DoubleToFloat(values[1]);\n            B = Col.DoubleToFloat(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3f(double[] values, int start)\n        {\n            R = Col.DoubleToFloat(values[start + 0]);\n            G = Col.DoubleToFloat(values[start + 1]);\n            B = Col.DoubleToFloat(values[start + 2]);\n        }\n\n        #endregion\n\n        #region Properities\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(R) || float.IsNaN(G) || float.IsNaN(B);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(R) && float.IsNaN(G) && float.IsNaN(B);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(R) || float.IsInfinity(G) || float.IsInfinity(B);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(R) && float.IsInfinity(G) && float.IsInfinity(B);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(R) || float.IsPositiveInfinity(G) || float.IsPositiveInfinity(B);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(R) && float.IsPositiveInfinity(G) && float.IsPositiveInfinity(B);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(R) || float.IsNegativeInfinity(G) || float.IsNegativeInfinity(B);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(R) && float.IsNegativeInfinity(G) && float.IsNegativeInfinity(B);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(R) || Fun.IsTiny(G) || Fun.IsTiny(B);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(R) && Fun.IsTiny(G) && Fun.IsTiny(B);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the color is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the color are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C3b color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC3b(C3b c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C3us color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC3us(C3us c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C3ui color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC3ui(C3ui c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C3d color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC3d(C3d c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C4b color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC4b(C4b c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C4us color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC4us(C4us c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C4ui color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC4ui(C4ui c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C4f color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC4f(C4f c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(C4d color)\n            => new C3f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromC4d(C4d c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(V3f v)\n            => new C3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromV3f(V3f c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(V3d v)\n            => new C3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromV3d(V3d c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(V4f v)\n            => new C3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"V4f\"/> vector.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from a <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromV4f(V4f c) => new C3f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(V4d v)\n            => new C3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"V4d\"/> vector.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3f\"/> color from a <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f FromV4d(V4d c) => new C3f(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(byte[] values)\n            => new C3f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C3f color)\n            => new byte[] { Col.FloatToByteClamped(color.R), Col.FloatToByteClamped(color.G), Col.FloatToByteClamped(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(ushort[] values)\n            => new C3f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C3f color)\n            => new ushort[] { Col.FloatToUShortClamped(color.R), Col.FloatToUShortClamped(color.G), Col.FloatToUShortClamped(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(uint[] values)\n            => new C3f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C3f color)\n            => new uint[] { Col.FloatToUIntClamped(color.R), Col.FloatToUIntClamped(color.G), Col.FloatToUIntClamped(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(float[] values)\n            => new C3f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C3f color)\n            => new float[] { (color.R), (color.G), (color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3f(double[] values)\n            => new C3f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C3f color)\n            => new double[] { Col.FloatToDouble(color.R), Col.FloatToDouble(color.G), Col.FloatToDouble(color.B) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b Map(Func<float, byte> channel_fun)\n        {\n            return new C3b(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us Map(Func<float, ushort> channel_fun)\n        {\n            return new C3us(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui Map(Func<float, uint> channel_fun)\n        {\n            return new C3ui(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f Map(Func<float, float> channel_fun)\n        {\n            return new C3f(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d Map(Func<float, double> channel_fun)\n        {\n            return new C3d(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float[] ToArray()\n            => (float[])this;\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe float this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &R) { ptr[i] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &R) { return ptr[i]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C3f with all components zero.\n        /// </summary>\n        public static C3f Zero => new C3f(0.0f, 0.0f, 0.0f);\n\n        // Web colors\n        public static C3f AliceBlue => new C3f((float)(0.941176), (float)(0.972549), (float)(1));\n        public static C3f AntiqueWhite => new C3f((float)(0.980392), (float)(0.921569), (float)(0.843137));\n        public static C3f Aqua => new C3f((float)(0), (float)(1), (float)(1));\n        public static C3f Aquamarine => new C3f((float)(0.498039), (float)(1), (float)(0.831373));\n        public static C3f Azure => new C3f((float)(0.941176), (float)(1), (float)(1));\n        public static C3f Beige => new C3f((float)(0.960784), (float)(0.960784), (float)(0.862745));\n        public static C3f Bisque => new C3f((float)(1), (float)(0.894118), (float)(0.768627));\n        public static C3f Black => new C3f((float)(0), (float)(0), (float)(0));\n        public static C3f BlanchedAlmond => new C3f((float)(1), (float)(0.921569), (float)(0.803922));\n        public static C3f Blue => new C3f((float)(0), (float)(0), (float)(1));\n        public static C3f BlueViolet => new C3f((float)(0.541176), (float)(0.168627), (float)(0.886275));\n        public static C3f Brown => new C3f((float)(0.647059), (float)(0.164706), (float)(0.164706));\n        public static C3f BurlyWood => new C3f((float)(0.870588), (float)(0.721569), (float)(0.529412));\n        public static C3f CadetBlue => new C3f((float)(0.372549), (float)(0.619608), (float)(0.627451));\n        public static C3f Chartreuse => new C3f((float)(0.498039), (float)(1), (float)(0));\n        public static C3f Chocolate => new C3f((float)(0.823529), (float)(0.411765), (float)(0.117647));\n        public static C3f Coral => new C3f((float)(1), (float)(0.498039), (float)(0.313725));\n        public static C3f CornflowerBlue => new C3f((float)(0.392157), (float)(0.584314), (float)(0.929412));\n        public static C3f Cornsilk => new C3f((float)(1), (float)(0.972549), (float)(0.862745));\n        public static C3f Crimson => new C3f((float)(0.862745), (float)(0.078431), (float)(0.235294));\n        public static C3f Cyan => new C3f((float)(0), (float)(1), (float)(1));\n        public static C3f DarkBlue => new C3f((float)(0), (float)(0), (float)(0.545098));\n        public static C3f DarkCyan => new C3f((float)(0), (float)(0.545098), (float)(0.545098));\n        public static C3f DarkGoldenRod => new C3f((float)(0.721569), (float)(0.52549), (float)(0.043137));\n        public static C3f DarkGray => new C3f((float)(0.662745), (float)(0.662745), (float)(0.662745));\n        public static C3f DarkGrey => new C3f((float)(0.662745), (float)(0.662745), (float)(0.662745));\n        public static C3f DarkGreen => new C3f((float)(0), (float)(0.392157), (float)(0));\n        public static C3f DarkKhaki => new C3f((float)(0.741176), (float)(0.717647), (float)(0.419608));\n        public static C3f DarkMagenta => new C3f((float)(0.545098), (float)(0), (float)(0.545098));\n        public static C3f DarkOliveGreen => new C3f((float)(0.333333), (float)(0.419608), (float)(0.184314));\n        public static C3f DarkOrange => new C3f((float)(1), (float)(0.54902), (float)(0));\n        public static C3f DarkOrchid => new C3f((float)(0.6), (float)(0.196078), (float)(0.8));\n        public static C3f DarkRed => new C3f((float)(0.545098), (float)(0), (float)(0));\n        public static C3f DarkSalmon => new C3f((float)(0.913725), (float)(0.588235), (float)(0.478431));\n        public static C3f DarkSeaGreen => new C3f((float)(0.560784), (float)(0.737255), (float)(0.560784));\n        public static C3f DarkSlateBlue => new C3f((float)(0.282353), (float)(0.239216), (float)(0.545098));\n        public static C3f DarkSlateGray => new C3f((float)(0.184314), (float)(0.309804), (float)(0.309804));\n        public static C3f DarkSlateGrey => new C3f((float)(0.184314), (float)(0.309804), (float)(0.309804));\n        public static C3f DarkTurquoise => new C3f((float)(0), (float)(0.807843), (float)(0.819608));\n        public static C3f DarkViolet => new C3f((float)(0.580392), (float)(0), (float)(0.827451));\n        public static C3f DeepPink => new C3f((float)(1), (float)(0.078431), (float)(0.576471));\n        public static C3f DeepSkyBlue => new C3f((float)(0), (float)(0.74902), (float)(1));\n        public static C3f DimGray => new C3f((float)(0.411765), (float)(0.411765), (float)(0.411765));\n        public static C3f DimGrey => new C3f((float)(0.411765), (float)(0.411765), (float)(0.411765));\n        public static C3f DodgerBlue => new C3f((float)(0.117647), (float)(0.564706), (float)(1));\n        public static C3f FireBrick => new C3f((float)(0.698039), (float)(0.133333), (float)(0.133333));\n        public static C3f FloralWhite => new C3f((float)(1), (float)(0.980392), (float)(0.941176));\n        public static C3f ForestGreen => new C3f((float)(0.133333), (float)(0.545098), (float)(0.133333));\n        public static C3f Fuchsia => new C3f((float)(1), (float)(0), (float)(1));\n        public static C3f Gainsboro => new C3f((float)(0.862745), (float)(0.862745), (float)(0.862745));\n        public static C3f GhostWhite => new C3f((float)(0.972549), (float)(0.972549), (float)(1));\n        public static C3f Gold => new C3f((float)(1), (float)(0.843137), (float)(0));\n        public static C3f GoldenRod => new C3f((float)(0.854902), (float)(0.647059), (float)(0.12549));\n        public static C3f Gray => new C3f((float)(0.501961), (float)(0.501961), (float)(0.501961));\n        public static C3f Grey => new C3f((float)(0.501961), (float)(0.501961), (float)(0.501961));\n        public static C3f Green => new C3f((float)(0), (float)(0.501961), (float)(0));\n        public static C3f GreenYellow => new C3f((float)(0.678431), (float)(1), (float)(0.184314));\n        public static C3f HoneyDew => new C3f((float)(0.941176), (float)(1), (float)(0.941176));\n        public static C3f HotPink => new C3f((float)(1), (float)(0.411765), (float)(0.705882));\n        public static C3f IndianRed  => new C3f((float)(0.803922), (float)(0.360784), (float)(0.360784));\n        public static C3f Indigo  => new C3f((float)(0.294118), (float)(0), (float)(0.509804));\n        public static C3f Ivory => new C3f((float)(1), (float)(1), (float)(0.941176));\n        public static C3f Khaki => new C3f((float)(0.941176), (float)(0.901961), (float)(0.54902));\n        public static C3f Lavender => new C3f((float)(0.901961), (float)(0.901961), (float)(0.980392));\n        public static C3f LavenderBlush => new C3f((float)(1), (float)(0.941176), (float)(0.960784));\n        public static C3f LawnGreen => new C3f((float)(0.486275), (float)(0.988235), (float)(0));\n        public static C3f LemonChiffon => new C3f((float)(1), (float)(0.980392), (float)(0.803922));\n        public static C3f LightBlue => new C3f((float)(0.678431), (float)(0.847059), (float)(0.901961));\n        public static C3f LightCoral => new C3f((float)(0.941176), (float)(0.501961), (float)(0.501961));\n        public static C3f LightCyan => new C3f((float)(0.878431), (float)(1), (float)(1));\n        public static C3f LightGoldenRodYellow => new C3f((float)(0.980392), (float)(0.980392), (float)(0.823529));\n        public static C3f LightGray => new C3f((float)(0.827451), (float)(0.827451), (float)(0.827451));\n        public static C3f LightGrey => new C3f((float)(0.827451), (float)(0.827451), (float)(0.827451));\n        public static C3f LightGreen => new C3f((float)(0.564706), (float)(0.933333), (float)(0.564706));\n        public static C3f LightPink => new C3f((float)(1), (float)(0.713725), (float)(0.756863));\n        public static C3f LightSalmon => new C3f((float)(1), (float)(0.627451), (float)(0.478431));\n        public static C3f LightSeaGreen => new C3f((float)(0.12549), (float)(0.698039), (float)(0.666667));\n        public static C3f LightSkyBlue => new C3f((float)(0.529412), (float)(0.807843), (float)(0.980392));\n        public static C3f LightSlateGray => new C3f((float)(0.466667), (float)(0.533333), (float)(0.6));\n        public static C3f LightSlateGrey => new C3f((float)(0.466667), (float)(0.533333), (float)(0.6));\n        public static C3f LightSteelBlue => new C3f((float)(0.690196), (float)(0.768627), (float)(0.870588));\n        public static C3f LightYellow => new C3f((float)(1), (float)(1), (float)(0.878431));\n        public static C3f Lime => new C3f((float)(0), (float)(1), (float)(0));\n        public static C3f LimeGreen => new C3f((float)(0.196078), (float)(0.803922), (float)(0.196078));\n        public static C3f Linen => new C3f((float)(0.980392), (float)(0.941176), (float)(0.901961));\n        public static C3f Magenta => new C3f((float)(1), (float)(0), (float)(1));\n        public static C3f Maroon => new C3f((float)(0.501961), (float)(0), (float)(0));\n        public static C3f MediumAquaMarine => new C3f((float)(0.4), (float)(0.803922), (float)(0.666667));\n        public static C3f MediumBlue => new C3f((float)(0), (float)(0), (float)(0.803922));\n        public static C3f MediumOrchid => new C3f((float)(0.729412), (float)(0.333333), (float)(0.827451));\n        public static C3f MediumPurple => new C3f((float)(0.576471), (float)(0.439216), (float)(0.847059));\n        public static C3f MediumSeaGreen => new C3f((float)(0.235294), (float)(0.701961), (float)(0.443137));\n        public static C3f MediumSlateBlue => new C3f((float)(0.482353), (float)(0.407843), (float)(0.933333));\n        public static C3f MediumSpringGreen => new C3f((float)(0), (float)(0.980392), (float)(0.603922));\n        public static C3f MediumTurquoise => new C3f((float)(0.282353), (float)(0.819608), (float)(0.8));\n        public static C3f MediumVioletRed => new C3f((float)(0.780392), (float)(0.082353), (float)(0.521569));\n        public static C3f MidnightBlue => new C3f((float)(0.098039), (float)(0.098039), (float)(0.439216));\n        public static C3f MintCream => new C3f((float)(0.960784), (float)(1), (float)(0.980392));\n        public static C3f MistyRose => new C3f((float)(1), (float)(0.894118), (float)(0.882353));\n        public static C3f Moccasin => new C3f((float)(1), (float)(0.894118), (float)(0.709804));\n        public static C3f NavajoWhite => new C3f((float)(1), (float)(0.870588), (float)(0.678431));\n        public static C3f Navy => new C3f((float)(0), (float)(0), (float)(0.501961));\n        public static C3f OldLace => new C3f((float)(0.992157), (float)(0.960784), (float)(0.901961));\n        public static C3f Olive => new C3f((float)(0.501961), (float)(0.501961), (float)(0));\n        public static C3f OliveDrab => new C3f((float)(0.419608), (float)(0.556863), (float)(0.137255));\n        public static C3f Orange => new C3f((float)(1), (float)(0.647059), (float)(0));\n        public static C3f OrangeRed => new C3f((float)(1), (float)(0.270588), (float)(0));\n        public static C3f Orchid => new C3f((float)(0.854902), (float)(0.439216), (float)(0.839216));\n        public static C3f PaleGoldenRod => new C3f((float)(0.933333), (float)(0.909804), (float)(0.666667));\n        public static C3f PaleGreen => new C3f((float)(0.596078), (float)(0.984314), (float)(0.596078));\n        public static C3f PaleTurquoise => new C3f((float)(0.686275), (float)(0.933333), (float)(0.933333));\n        public static C3f PaleVioletRed => new C3f((float)(0.847059), (float)(0.439216), (float)(0.576471));\n        public static C3f PapayaWhip => new C3f((float)(1), (float)(0.937255), (float)(0.835294));\n        public static C3f PeachPuff => new C3f((float)(1), (float)(0.854902), (float)(0.72549));\n        public static C3f Peru => new C3f((float)(0.803922), (float)(0.521569), (float)(0.247059));\n        public static C3f Pink => new C3f((float)(1), (float)(0.752941), (float)(0.796078));\n        public static C3f Plum => new C3f((float)(0.866667), (float)(0.627451), (float)(0.866667));\n        public static C3f PowderBlue => new C3f((float)(0.690196), (float)(0.878431), (float)(0.901961));\n        public static C3f Purple => new C3f((float)(0.501961), (float)(0), (float)(0.501961));\n        public static C3f Red => new C3f((float)(1), (float)(0), (float)(0));\n        public static C3f RosyBrown => new C3f((float)(0.737255), (float)(0.560784), (float)(0.560784));\n        public static C3f RoyalBlue => new C3f((float)(0.254902), (float)(0.411765), (float)(0.882353));\n        public static C3f SaddleBrown => new C3f((float)(0.545098), (float)(0.270588), (float)(0.07451));\n        public static C3f Salmon => new C3f((float)(0.980392), (float)(0.501961), (float)(0.447059));\n        public static C3f SandyBrown => new C3f((float)(0.956863), (float)(0.643137), (float)(0.376471));\n        public static C3f SeaGreen => new C3f((float)(0.180392), (float)(0.545098), (float)(0.341176));\n        public static C3f SeaShell => new C3f((float)(1), (float)(0.960784), (float)(0.933333));\n        public static C3f Sienna => new C3f((float)(0.627451), (float)(0.321569), (float)(0.176471));\n        public static C3f Silver => new C3f((float)(0.752941), (float)(0.752941), (float)(0.752941));\n        public static C3f SkyBlue => new C3f((float)(0.529412), (float)(0.807843), (float)(0.921569));\n        public static C3f SlateBlue => new C3f((float)(0.415686), (float)(0.352941), (float)(0.803922));\n        public static C3f SlateGray => new C3f((float)(0.439216), (float)(0.501961), (float)(0.564706));\n        public static C3f SlateGrey => new C3f((float)(0.439216), (float)(0.501961), (float)(0.564706));\n        public static C3f Snow => new C3f((float)(1), (float)(0.980392), (float)(0.980392));\n        public static C3f SpringGreen => new C3f((float)(0), (float)(1), (float)(0.498039));\n        public static C3f SteelBlue => new C3f((float)(0.27451), (float)(0.509804), (float)(0.705882));\n        public static C3f Tan => new C3f((float)(0.823529), (float)(0.705882), (float)(0.54902));\n        public static C3f Teal => new C3f((float)(0), (float)(0.501961), (float)(0.501961));\n        public static C3f Thistle => new C3f((float)(0.847059), (float)(0.74902), (float)(0.847059));\n        public static C3f Tomato => new C3f((float)(1), (float)(0.388235), (float)(0.278431));\n        public static C3f Turquoise => new C3f((float)(0.25098), (float)(0.878431), (float)(0.815686));\n        public static C3f Violet => new C3f((float)(0.933333), (float)(0.509804), (float)(0.933333));\n        public static C3f Wheat => new C3f((float)(0.960784), (float)(0.870588), (float)(0.701961));\n        public static C3f White => new C3f((float)(1), (float)(1), (float)(1));\n        public static C3f WhiteSmoke => new C3f((float)(0.960784), (float)(0.960784), (float)(0.960784));\n        public static C3f Yellow => new C3f((float)(1), (float)(1), (float)(0));\n        public static C3f YellowGreen => new C3f((float)(0.603922), (float)(0.803922), (float)(0.196078));\n\n        public static C3f DarkYellow => Olive;\n\n        public static C3f VRVisGreen => new C3f((float)(0.698), (float)(0.851), (float)(0.008));\n\n        public static C3f Gray10 => new C3f((float)(0.1));\n        public static C3f Gray20 => new C3f((float)(0.2));\n        public static C3f Gray30 => new C3f((float)(0.3));\n        public static C3f Gray40 => new C3f((float)(0.4));\n        public static C3f Gray50 => new C3f((float)(0.5));\n        public static C3f Gray60 => new C3f((float)(0.6));\n        public static C3f Gray70 => new C3f((float)(0.7));\n        public static C3f Gray80 => new C3f((float)(0.8));\n        public static C3f Gray90 => new C3f((float)(0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C3f a, C3f b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C3f a, C3f b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator +(C3f c0, C3b c1)\n        {\n            return new C3f(\n                (float)(c0.R + Col.ByteToFloat(c1.R)), \n                (float)(c0.G + Col.ByteToFloat(c1.G)), \n                (float)(c0.B + Col.ByteToFloat(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator -(C3f c0, C3b c1)\n        {\n            return new C3f(\n                (float)(c0.R - Col.ByteToFloat(c1.R)), \n                (float)(c0.G - Col.ByteToFloat(c1.G)), \n                (float)(c0.B - Col.ByteToFloat(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator +(C3f c0, C3us c1)\n        {\n            return new C3f(\n                (float)(c0.R + Col.UShortToFloat(c1.R)), \n                (float)(c0.G + Col.UShortToFloat(c1.G)), \n                (float)(c0.B + Col.UShortToFloat(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator -(C3f c0, C3us c1)\n        {\n            return new C3f(\n                (float)(c0.R - Col.UShortToFloat(c1.R)), \n                (float)(c0.G - Col.UShortToFloat(c1.G)), \n                (float)(c0.B - Col.UShortToFloat(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator +(C3f c0, C3ui c1)\n        {\n            return new C3f(\n                (float)(c0.R + Col.UIntToFloat(c1.R)), \n                (float)(c0.G + Col.UIntToFloat(c1.G)), \n                (float)(c0.B + Col.UIntToFloat(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator -(C3f c0, C3ui c1)\n        {\n            return new C3f(\n                (float)(c0.R - Col.UIntToFloat(c1.R)), \n                (float)(c0.G - Col.UIntToFloat(c1.G)), \n                (float)(c0.B - Col.UIntToFloat(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator +(C3f c0, C3d c1)\n        {\n            return new C3f(\n                (float)(c0.R + (float)(c1.R)), \n                (float)(c0.G + (float)(c1.G)), \n                (float)(c0.B + (float)(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator -(C3f c0, C3d c1)\n        {\n            return new C3f(\n                (float)(c0.R - (float)(c1.R)), \n                (float)(c0.G - (float)(c1.G)), \n                (float)(c0.B - (float)(c1.B)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator *(C3f col, float scalar)\n        {\n            return new C3f((float)(col.R * scalar), (float)(col.G * scalar), (float)(col.B * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator *(float scalar, C3f col)\n        {\n            return new C3f((float)(scalar * col.R), (float)(scalar * col.G), (float)(scalar * col.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator /(C3f col, float scalar)\n        {\n            return new C3f((float)(col.R / scalar), (float)(col.G / scalar), (float)(col.B / scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator /(float scalar, C3f col)\n        {\n            return new C3f((float)(scalar / col.R), (float)(scalar / col.G), (float)(scalar / col.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator *(C3f c0, C3f c1)\n        {\n            return new C3f((float)(c0.R * c1.R), (float)(c0.G * c1.G), (float)(c0.B * c1.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator /(C3f c0, C3f c1)\n        {\n            return new C3f((float)(c0.R / c1.R), (float)(c0.G / c1.G), (float)(c0.B / c1.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator +(C3f c0, C3f c1)\n        {\n            return new C3f(c0.R + c1.R, c0.G + c1.G, c0.B + c1.B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator +(C3f col, float scalar)\n        {\n            return new C3f(col.R + scalar, col.G + scalar, col.B + scalar);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator +(float scalar, C3f col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator -(C3f c0, C3f c1)\n        {\n            return new C3f(c0.R - c1.R, c0.G - c1.G, c0.B - c1.B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator -(C3f col, float scalar)\n        {\n            return new C3f(col.R - scalar, col.G - scalar, col.B - scalar);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f operator -(float scalar, C3f col)\n        {\n            return new C3f(scalar - col.R, scalar - col.G, scalar - col.B);\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(float min, float max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f Clamped(float min, float max)\n        {\n            return new C3f(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max));\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. \n        /// </summary>\n        public readonly float Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(R) + Fun.Abs(G) + Fun.Abs(B); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). \n        /// </summary>\n        public readonly float Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). \n        /// </summary>\n        public readonly float NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(R), Fun.Abs(G), Fun.Abs(B)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). \n        /// </summary>\n        public readonly float NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(R), Fun.Abs(G), Fun.Abs(B)); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C3f o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C3f, int, float> Setter =\n            (ref C3f color, int i, float value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinearInterp(float t, C3f a, C3f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinearInterp(V3f t, C3f a, C3f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f DivideByInt(C3f c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3f.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C3f result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC3f();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                float[] values = new float[4] { 1.0f, 1.0f, 1.0f, 1.0f };\n\n                float parse(Text t)\n                {\n                    if (!float.TryParse(t.ToString(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out float value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C3f(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3f.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C3f result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3f color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<float>.Parse, C3f.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3f color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f Parse(Text t)\n            => TryParse(t, out C3f result) ? result : throw new FormatException($\"{t} is not a valid C3f color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C3f> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C3f other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return (double)(R); }\n            set { R = (float)(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return (double)(G); }\n            set { G = (float)(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return (double)(B); }\n            set { B = (float)(value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3f Lerp(this float t, C3f a, C3f b)\n            => new C3f(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3f Lerp(this V3f t, C3f a, C3f b)\n            => new C3f(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C3f a, C3f b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C3f a, C3f b, float tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C3f c, float epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(C3f c)\n            => c.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"C3f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(C3f c)\n            => c.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C3f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(C3f c)\n            => c.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C3f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(C3f c)\n            => c.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C3f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(C3f c)\n            => c.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"C3f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(C3f c)\n            => c.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBB.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C3f c)\n            => c.ToC3b().ToHexString();\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3f a, C3f b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3f col, float s)\n        {\n            return (col.R < s && col.G < s && col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, C3f col)\n        {\n            return (s < col.R && s < col.G && s < col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3f a, C3f b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3f col, float s)\n        {\n            return (col.R < s || col.G < s || col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, C3f col)\n        {\n            return (s < col.R || s < col.G || s < col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3f a, C3f b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3f col, float s)\n        {\n            return (col.R > s && col.G > s && col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, C3f col)\n        {\n            return (s > col.R && s > col.G && s > col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3f a, C3f b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3f col, float s)\n        {\n            return (col.R > s || col.G > s || col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, C3f col)\n        {\n            return (s > col.R || s > col.G || s > col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3f a, C3f b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3f col, float s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, C3f col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3f a, C3f b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3f col, float s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, C3f col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3f a, C3f b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3f col, float s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, C3f col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3f a, C3f b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3f col, float s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, C3f col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3f a, C3f b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3f col, float s)\n        {\n            return (col.R == s && col.G == s && col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, C3f col)\n        {\n            return (s == col.R && s == col.G && s == col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3f a, C3f b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3f col, float s)\n        {\n            return (col.R == s || col.G == s || col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, C3f col)\n        {\n            return (s == col.R || s == col.G || s == col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3f a, C3f b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3f col, float s)\n        {\n            return (col.R != s && col.G != s && col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, C3f col)\n        {\n            return (s != col.R && s != col.G && s != col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3f a, C3f b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3f col, float s)\n        {\n            return (col.R != s || col.G != s || col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, C3f col)\n        {\n            return (s != col.R || s != col.G || s != col.B);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinCom(\n            C3f p0, C3f p1, C3f p2, C3f p3, ref Tup4<float> w)\n        {\n            return new C3f(\n                (p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                (p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                (p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f LinCom(\n            C3f p0, C3f p1, C3f p2, C3f p3, C3f p4, C3f p5, ref Tup6<float> w)\n        {\n            return new C3f(\n                (p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                (p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                (p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C3f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C3f c, float epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C3f c, float epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(C3f c)\n            => c.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(C3f c)\n            => c.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(C3f c)\n            => c.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(C3f c)\n            => c.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(C3f c)\n            => c.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(C3f c)\n            => c.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(C3f c)\n            => c.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(C3f c)\n            => c.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(C3f c)\n            => c.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(C3f c)\n            => c.AllTiny;\n\n        #endregion\n    }\n\n    public static class IRandomUniformC3fExtensions\n    {\n        #region IRandomUniform extensions for C3f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of a C3f color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f UniformC3f(this IRandomUniform rnd)\n        {\n            return new C3f(rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of a C3f color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f UniformC3fClosed(this IRandomUniform rnd)\n        {\n            return new C3f(rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of a C3f color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3f UniformC3fOpen(this IRandomUniform rnd)\n        {\n            return new C3f(rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C3d\n\n    /// <summary>\n    /// Represents an RGB color with each channel stored as a <see cref=\"double\"/> value within [0, 1].\n    /// </summary>\n    [Serializable]\n    public partial struct C3d : IFormattable, IEquatable<C3d>, IRGB\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(double r, double g, double b)\n        {\n            R = r; G = g; B = b;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(float r, float g, float b)\n        {\n            R = (double)(r);\n            G = (double)(g);\n            B = (double)(b);\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(double gray)\n        {\n            R = gray; G = gray; B = gray;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(float gray)\n        {\n            var value = (double)(gray);\n            R = value; G = value; B = value;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C3b color)\n        {\n            R = Col.ByteToDouble(color.R);\n            G = Col.ByteToDouble(color.G);\n            B = Col.ByteToDouble(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C3us color)\n        {\n            R = Col.UShortToDouble(color.R);\n            G = Col.UShortToDouble(color.G);\n            B = Col.UShortToDouble(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C3ui color)\n        {\n            R = Col.UIntToDouble(color.R);\n            G = Col.UIntToDouble(color.G);\n            B = Col.UIntToDouble(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C3f color)\n        {\n            R = Col.FloatToDouble(color.R);\n            G = Col.FloatToDouble(color.G);\n            B = Col.FloatToDouble(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C3d color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C4b color)\n        {\n            R = Col.ByteToDouble(color.R);\n            G = Col.ByteToDouble(color.G);\n            B = Col.ByteToDouble(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C4us color)\n        {\n            R = Col.UShortToDouble(color.R);\n            G = Col.UShortToDouble(color.G);\n            B = Col.UShortToDouble(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C4ui color)\n        {\n            R = Col.UIntToDouble(color.R);\n            G = Col.UIntToDouble(color.G);\n            B = Col.UIntToDouble(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C4f color)\n        {\n            R = Col.FloatToDouble(color.R);\n            G = Col.FloatToDouble(color.G);\n            B = Col.FloatToDouble(color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(C4d color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(V3f vec)\n        {\n            R = (double)(vec.X);\n            G = (double)(vec.Y);\n            B = (double)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(V3d vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(V4f vec)\n        {\n            R = (double)(vec.X);\n            G = (double)(vec.Y);\n            B = (double)(vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(V4d vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(Func<int, double> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(byte[] values)\n        {\n            R = Col.ByteToDouble(values[0]);\n            G = Col.ByteToDouble(values[1]);\n            B = Col.ByteToDouble(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(byte[] values, int start)\n        {\n            R = Col.ByteToDouble(values[start + 0]);\n            G = Col.ByteToDouble(values[start + 1]);\n            B = Col.ByteToDouble(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(ushort[] values)\n        {\n            R = Col.UShortToDouble(values[0]);\n            G = Col.UShortToDouble(values[1]);\n            B = Col.UShortToDouble(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(ushort[] values, int start)\n        {\n            R = Col.UShortToDouble(values[start + 0]);\n            G = Col.UShortToDouble(values[start + 1]);\n            B = Col.UShortToDouble(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(uint[] values)\n        {\n            R = Col.UIntToDouble(values[0]);\n            G = Col.UIntToDouble(values[1]);\n            B = Col.UIntToDouble(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(uint[] values, int start)\n        {\n            R = Col.UIntToDouble(values[start + 0]);\n            G = Col.UIntToDouble(values[start + 1]);\n            B = Col.UIntToDouble(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(float[] values)\n        {\n            R = Col.FloatToDouble(values[0]);\n            G = Col.FloatToDouble(values[1]);\n            B = Col.FloatToDouble(values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(float[] values, int start)\n        {\n            R = Col.FloatToDouble(values[start + 0]);\n            G = Col.FloatToDouble(values[start + 1]);\n            B = Col.FloatToDouble(values[start + 2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(double[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C3d(double[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n        }\n\n        #endregion\n\n        #region Properities\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(R) || double.IsNaN(G) || double.IsNaN(B);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(R) && double.IsNaN(G) && double.IsNaN(B);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(R) || double.IsInfinity(G) || double.IsInfinity(B);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(R) && double.IsInfinity(G) && double.IsInfinity(B);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(R) || double.IsPositiveInfinity(G) || double.IsPositiveInfinity(B);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(R) && double.IsPositiveInfinity(G) && double.IsPositiveInfinity(B);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(R) || double.IsNegativeInfinity(G) || double.IsNegativeInfinity(B);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(R) && double.IsNegativeInfinity(G) && double.IsNegativeInfinity(B);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(R) || Fun.IsTiny(G) || Fun.IsTiny(B);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(R) && Fun.IsTiny(G) && Fun.IsTiny(B);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the color is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the color are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C3b color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC3b(C3b c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C3us color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC3us(C3us c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C3ui color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC3ui(C3ui c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C3f color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC3f(C3f c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C4b color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC4b(C4b c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C4us color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC4us(C4us c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C4ui color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC4ui(C4ui c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C4f color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC4f(C4f c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(C4d color)\n            => new C3d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromC4d(C4d c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(V3f v)\n            => new C3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromV3f(V3f c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(V3d v)\n            => new C3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromV3d(V3d c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(V4f v)\n            => new C3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"V4f\"/> vector.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from a <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromV4f(V4f c) => new C3d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(V4d v)\n            => new C3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"V4d\"/> vector.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C3d\"/> color from a <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d FromV4d(V4d c) => new C3d(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(byte[] values)\n            => new C3d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C3d color)\n            => new byte[] { Col.DoubleToByteClamped(color.R), Col.DoubleToByteClamped(color.G), Col.DoubleToByteClamped(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(ushort[] values)\n            => new C3d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C3d color)\n            => new ushort[] { Col.DoubleToUShortClamped(color.R), Col.DoubleToUShortClamped(color.G), Col.DoubleToUShortClamped(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(uint[] values)\n            => new C3d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C3d color)\n            => new uint[] { Col.DoubleToUIntClamped(color.R), Col.DoubleToUIntClamped(color.G), Col.DoubleToUIntClamped(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(float[] values)\n            => new C3d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C3d color)\n            => new float[] { Col.DoubleToFloat(color.R), Col.DoubleToFloat(color.G), Col.DoubleToFloat(color.B) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C3d(double[] values)\n            => new C3d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C3d color)\n            => new double[] { (color.R), (color.G), (color.B) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b Map(Func<double, byte> channel_fun)\n        {\n            return new C3b(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us Map(Func<double, ushort> channel_fun)\n        {\n            return new C3us(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui Map(Func<double, uint> channel_fun)\n        {\n            return new C3ui(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f Map(Func<double, float> channel_fun)\n        {\n            return new C3f(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d Map(Func<double, double> channel_fun)\n        {\n            return new C3d(channel_fun(R), channel_fun(G), channel_fun(B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double[] ToArray()\n            => (double[])this;\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe double this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &R) { ptr[i] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &R) { return ptr[i]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C3d with all components zero.\n        /// </summary>\n        public static C3d Zero => new C3d(0, 0, 0);\n\n        // Web colors\n        public static C3d AliceBlue => new C3d((0.941176), (0.972549), (1));\n        public static C3d AntiqueWhite => new C3d((0.980392), (0.921569), (0.843137));\n        public static C3d Aqua => new C3d((0), (1), (1));\n        public static C3d Aquamarine => new C3d((0.498039), (1), (0.831373));\n        public static C3d Azure => new C3d((0.941176), (1), (1));\n        public static C3d Beige => new C3d((0.960784), (0.960784), (0.862745));\n        public static C3d Bisque => new C3d((1), (0.894118), (0.768627));\n        public static C3d Black => new C3d((0), (0), (0));\n        public static C3d BlanchedAlmond => new C3d((1), (0.921569), (0.803922));\n        public static C3d Blue => new C3d((0), (0), (1));\n        public static C3d BlueViolet => new C3d((0.541176), (0.168627), (0.886275));\n        public static C3d Brown => new C3d((0.647059), (0.164706), (0.164706));\n        public static C3d BurlyWood => new C3d((0.870588), (0.721569), (0.529412));\n        public static C3d CadetBlue => new C3d((0.372549), (0.619608), (0.627451));\n        public static C3d Chartreuse => new C3d((0.498039), (1), (0));\n        public static C3d Chocolate => new C3d((0.823529), (0.411765), (0.117647));\n        public static C3d Coral => new C3d((1), (0.498039), (0.313725));\n        public static C3d CornflowerBlue => new C3d((0.392157), (0.584314), (0.929412));\n        public static C3d Cornsilk => new C3d((1), (0.972549), (0.862745));\n        public static C3d Crimson => new C3d((0.862745), (0.078431), (0.235294));\n        public static C3d Cyan => new C3d((0), (1), (1));\n        public static C3d DarkBlue => new C3d((0), (0), (0.545098));\n        public static C3d DarkCyan => new C3d((0), (0.545098), (0.545098));\n        public static C3d DarkGoldenRod => new C3d((0.721569), (0.52549), (0.043137));\n        public static C3d DarkGray => new C3d((0.662745), (0.662745), (0.662745));\n        public static C3d DarkGrey => new C3d((0.662745), (0.662745), (0.662745));\n        public static C3d DarkGreen => new C3d((0), (0.392157), (0));\n        public static C3d DarkKhaki => new C3d((0.741176), (0.717647), (0.419608));\n        public static C3d DarkMagenta => new C3d((0.545098), (0), (0.545098));\n        public static C3d DarkOliveGreen => new C3d((0.333333), (0.419608), (0.184314));\n        public static C3d DarkOrange => new C3d((1), (0.54902), (0));\n        public static C3d DarkOrchid => new C3d((0.6), (0.196078), (0.8));\n        public static C3d DarkRed => new C3d((0.545098), (0), (0));\n        public static C3d DarkSalmon => new C3d((0.913725), (0.588235), (0.478431));\n        public static C3d DarkSeaGreen => new C3d((0.560784), (0.737255), (0.560784));\n        public static C3d DarkSlateBlue => new C3d((0.282353), (0.239216), (0.545098));\n        public static C3d DarkSlateGray => new C3d((0.184314), (0.309804), (0.309804));\n        public static C3d DarkSlateGrey => new C3d((0.184314), (0.309804), (0.309804));\n        public static C3d DarkTurquoise => new C3d((0), (0.807843), (0.819608));\n        public static C3d DarkViolet => new C3d((0.580392), (0), (0.827451));\n        public static C3d DeepPink => new C3d((1), (0.078431), (0.576471));\n        public static C3d DeepSkyBlue => new C3d((0), (0.74902), (1));\n        public static C3d DimGray => new C3d((0.411765), (0.411765), (0.411765));\n        public static C3d DimGrey => new C3d((0.411765), (0.411765), (0.411765));\n        public static C3d DodgerBlue => new C3d((0.117647), (0.564706), (1));\n        public static C3d FireBrick => new C3d((0.698039), (0.133333), (0.133333));\n        public static C3d FloralWhite => new C3d((1), (0.980392), (0.941176));\n        public static C3d ForestGreen => new C3d((0.133333), (0.545098), (0.133333));\n        public static C3d Fuchsia => new C3d((1), (0), (1));\n        public static C3d Gainsboro => new C3d((0.862745), (0.862745), (0.862745));\n        public static C3d GhostWhite => new C3d((0.972549), (0.972549), (1));\n        public static C3d Gold => new C3d((1), (0.843137), (0));\n        public static C3d GoldenRod => new C3d((0.854902), (0.647059), (0.12549));\n        public static C3d Gray => new C3d((0.501961), (0.501961), (0.501961));\n        public static C3d Grey => new C3d((0.501961), (0.501961), (0.501961));\n        public static C3d Green => new C3d((0), (0.501961), (0));\n        public static C3d GreenYellow => new C3d((0.678431), (1), (0.184314));\n        public static C3d HoneyDew => new C3d((0.941176), (1), (0.941176));\n        public static C3d HotPink => new C3d((1), (0.411765), (0.705882));\n        public static C3d IndianRed  => new C3d((0.803922), (0.360784), (0.360784));\n        public static C3d Indigo  => new C3d((0.294118), (0), (0.509804));\n        public static C3d Ivory => new C3d((1), (1), (0.941176));\n        public static C3d Khaki => new C3d((0.941176), (0.901961), (0.54902));\n        public static C3d Lavender => new C3d((0.901961), (0.901961), (0.980392));\n        public static C3d LavenderBlush => new C3d((1), (0.941176), (0.960784));\n        public static C3d LawnGreen => new C3d((0.486275), (0.988235), (0));\n        public static C3d LemonChiffon => new C3d((1), (0.980392), (0.803922));\n        public static C3d LightBlue => new C3d((0.678431), (0.847059), (0.901961));\n        public static C3d LightCoral => new C3d((0.941176), (0.501961), (0.501961));\n        public static C3d LightCyan => new C3d((0.878431), (1), (1));\n        public static C3d LightGoldenRodYellow => new C3d((0.980392), (0.980392), (0.823529));\n        public static C3d LightGray => new C3d((0.827451), (0.827451), (0.827451));\n        public static C3d LightGrey => new C3d((0.827451), (0.827451), (0.827451));\n        public static C3d LightGreen => new C3d((0.564706), (0.933333), (0.564706));\n        public static C3d LightPink => new C3d((1), (0.713725), (0.756863));\n        public static C3d LightSalmon => new C3d((1), (0.627451), (0.478431));\n        public static C3d LightSeaGreen => new C3d((0.12549), (0.698039), (0.666667));\n        public static C3d LightSkyBlue => new C3d((0.529412), (0.807843), (0.980392));\n        public static C3d LightSlateGray => new C3d((0.466667), (0.533333), (0.6));\n        public static C3d LightSlateGrey => new C3d((0.466667), (0.533333), (0.6));\n        public static C3d LightSteelBlue => new C3d((0.690196), (0.768627), (0.870588));\n        public static C3d LightYellow => new C3d((1), (1), (0.878431));\n        public static C3d Lime => new C3d((0), (1), (0));\n        public static C3d LimeGreen => new C3d((0.196078), (0.803922), (0.196078));\n        public static C3d Linen => new C3d((0.980392), (0.941176), (0.901961));\n        public static C3d Magenta => new C3d((1), (0), (1));\n        public static C3d Maroon => new C3d((0.501961), (0), (0));\n        public static C3d MediumAquaMarine => new C3d((0.4), (0.803922), (0.666667));\n        public static C3d MediumBlue => new C3d((0), (0), (0.803922));\n        public static C3d MediumOrchid => new C3d((0.729412), (0.333333), (0.827451));\n        public static C3d MediumPurple => new C3d((0.576471), (0.439216), (0.847059));\n        public static C3d MediumSeaGreen => new C3d((0.235294), (0.701961), (0.443137));\n        public static C3d MediumSlateBlue => new C3d((0.482353), (0.407843), (0.933333));\n        public static C3d MediumSpringGreen => new C3d((0), (0.980392), (0.603922));\n        public static C3d MediumTurquoise => new C3d((0.282353), (0.819608), (0.8));\n        public static C3d MediumVioletRed => new C3d((0.780392), (0.082353), (0.521569));\n        public static C3d MidnightBlue => new C3d((0.098039), (0.098039), (0.439216));\n        public static C3d MintCream => new C3d((0.960784), (1), (0.980392));\n        public static C3d MistyRose => new C3d((1), (0.894118), (0.882353));\n        public static C3d Moccasin => new C3d((1), (0.894118), (0.709804));\n        public static C3d NavajoWhite => new C3d((1), (0.870588), (0.678431));\n        public static C3d Navy => new C3d((0), (0), (0.501961));\n        public static C3d OldLace => new C3d((0.992157), (0.960784), (0.901961));\n        public static C3d Olive => new C3d((0.501961), (0.501961), (0));\n        public static C3d OliveDrab => new C3d((0.419608), (0.556863), (0.137255));\n        public static C3d Orange => new C3d((1), (0.647059), (0));\n        public static C3d OrangeRed => new C3d((1), (0.270588), (0));\n        public static C3d Orchid => new C3d((0.854902), (0.439216), (0.839216));\n        public static C3d PaleGoldenRod => new C3d((0.933333), (0.909804), (0.666667));\n        public static C3d PaleGreen => new C3d((0.596078), (0.984314), (0.596078));\n        public static C3d PaleTurquoise => new C3d((0.686275), (0.933333), (0.933333));\n        public static C3d PaleVioletRed => new C3d((0.847059), (0.439216), (0.576471));\n        public static C3d PapayaWhip => new C3d((1), (0.937255), (0.835294));\n        public static C3d PeachPuff => new C3d((1), (0.854902), (0.72549));\n        public static C3d Peru => new C3d((0.803922), (0.521569), (0.247059));\n        public static C3d Pink => new C3d((1), (0.752941), (0.796078));\n        public static C3d Plum => new C3d((0.866667), (0.627451), (0.866667));\n        public static C3d PowderBlue => new C3d((0.690196), (0.878431), (0.901961));\n        public static C3d Purple => new C3d((0.501961), (0), (0.501961));\n        public static C3d Red => new C3d((1), (0), (0));\n        public static C3d RosyBrown => new C3d((0.737255), (0.560784), (0.560784));\n        public static C3d RoyalBlue => new C3d((0.254902), (0.411765), (0.882353));\n        public static C3d SaddleBrown => new C3d((0.545098), (0.270588), (0.07451));\n        public static C3d Salmon => new C3d((0.980392), (0.501961), (0.447059));\n        public static C3d SandyBrown => new C3d((0.956863), (0.643137), (0.376471));\n        public static C3d SeaGreen => new C3d((0.180392), (0.545098), (0.341176));\n        public static C3d SeaShell => new C3d((1), (0.960784), (0.933333));\n        public static C3d Sienna => new C3d((0.627451), (0.321569), (0.176471));\n        public static C3d Silver => new C3d((0.752941), (0.752941), (0.752941));\n        public static C3d SkyBlue => new C3d((0.529412), (0.807843), (0.921569));\n        public static C3d SlateBlue => new C3d((0.415686), (0.352941), (0.803922));\n        public static C3d SlateGray => new C3d((0.439216), (0.501961), (0.564706));\n        public static C3d SlateGrey => new C3d((0.439216), (0.501961), (0.564706));\n        public static C3d Snow => new C3d((1), (0.980392), (0.980392));\n        public static C3d SpringGreen => new C3d((0), (1), (0.498039));\n        public static C3d SteelBlue => new C3d((0.27451), (0.509804), (0.705882));\n        public static C3d Tan => new C3d((0.823529), (0.705882), (0.54902));\n        public static C3d Teal => new C3d((0), (0.501961), (0.501961));\n        public static C3d Thistle => new C3d((0.847059), (0.74902), (0.847059));\n        public static C3d Tomato => new C3d((1), (0.388235), (0.278431));\n        public static C3d Turquoise => new C3d((0.25098), (0.878431), (0.815686));\n        public static C3d Violet => new C3d((0.933333), (0.509804), (0.933333));\n        public static C3d Wheat => new C3d((0.960784), (0.870588), (0.701961));\n        public static C3d White => new C3d((1), (1), (1));\n        public static C3d WhiteSmoke => new C3d((0.960784), (0.960784), (0.960784));\n        public static C3d Yellow => new C3d((1), (1), (0));\n        public static C3d YellowGreen => new C3d((0.603922), (0.803922), (0.196078));\n\n        public static C3d DarkYellow => Olive;\n\n        public static C3d VRVisGreen => new C3d((0.698), (0.851), (0.008));\n\n        public static C3d Gray10 => new C3d((0.1));\n        public static C3d Gray20 => new C3d((0.2));\n        public static C3d Gray30 => new C3d((0.3));\n        public static C3d Gray40 => new C3d((0.4));\n        public static C3d Gray50 => new C3d((0.5));\n        public static C3d Gray60 => new C3d((0.6));\n        public static C3d Gray70 => new C3d((0.7));\n        public static C3d Gray80 => new C3d((0.8));\n        public static C3d Gray90 => new C3d((0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C3d a, C3d b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C3d a, C3d b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator +(C3d c0, C3b c1)\n        {\n            return new C3d(\n                (double)(c0.R + Col.ByteToDouble(c1.R)), \n                (double)(c0.G + Col.ByteToDouble(c1.G)), \n                (double)(c0.B + Col.ByteToDouble(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator -(C3d c0, C3b c1)\n        {\n            return new C3d(\n                (double)(c0.R - Col.ByteToDouble(c1.R)), \n                (double)(c0.G - Col.ByteToDouble(c1.G)), \n                (double)(c0.B - Col.ByteToDouble(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator +(C3d c0, C3us c1)\n        {\n            return new C3d(\n                (double)(c0.R + Col.UShortToDouble(c1.R)), \n                (double)(c0.G + Col.UShortToDouble(c1.G)), \n                (double)(c0.B + Col.UShortToDouble(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator -(C3d c0, C3us c1)\n        {\n            return new C3d(\n                (double)(c0.R - Col.UShortToDouble(c1.R)), \n                (double)(c0.G - Col.UShortToDouble(c1.G)), \n                (double)(c0.B - Col.UShortToDouble(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator +(C3d c0, C3ui c1)\n        {\n            return new C3d(\n                (double)(c0.R + Col.UIntToDouble(c1.R)), \n                (double)(c0.G + Col.UIntToDouble(c1.G)), \n                (double)(c0.B + Col.UIntToDouble(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator -(C3d c0, C3ui c1)\n        {\n            return new C3d(\n                (double)(c0.R - Col.UIntToDouble(c1.R)), \n                (double)(c0.G - Col.UIntToDouble(c1.G)), \n                (double)(c0.B - Col.UIntToDouble(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator +(C3d c0, C3f c1)\n        {\n            return new C3d(\n                (double)(c0.R + (double)(c1.R)), \n                (double)(c0.G + (double)(c1.G)), \n                (double)(c0.B + (double)(c1.B)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator -(C3d c0, C3f c1)\n        {\n            return new C3d(\n                (double)(c0.R - (double)(c1.R)), \n                (double)(c0.G - (double)(c1.G)), \n                (double)(c0.B - (double)(c1.B)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator *(C3d col, double scalar)\n        {\n            return new C3d((double)(col.R * scalar), (double)(col.G * scalar), (double)(col.B * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator *(double scalar, C3d col)\n        {\n            return new C3d((double)(scalar * col.R), (double)(scalar * col.G), (double)(scalar * col.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator /(C3d col, double scalar)\n        {\n            return new C3d((double)(col.R / scalar), (double)(col.G / scalar), (double)(col.B / scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator /(double scalar, C3d col)\n        {\n            return new C3d((double)(scalar / col.R), (double)(scalar / col.G), (double)(scalar / col.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator *(C3d c0, C3d c1)\n        {\n            return new C3d((double)(c0.R * c1.R), (double)(c0.G * c1.G), (double)(c0.B * c1.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator /(C3d c0, C3d c1)\n        {\n            return new C3d((double)(c0.R / c1.R), (double)(c0.G / c1.G), (double)(c0.B / c1.B));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator +(C3d c0, C3d c1)\n        {\n            return new C3d(c0.R + c1.R, c0.G + c1.G, c0.B + c1.B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator +(C3d col, double scalar)\n        {\n            return new C3d(col.R + scalar, col.G + scalar, col.B + scalar);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator +(double scalar, C3d col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator -(C3d c0, C3d c1)\n        {\n            return new C3d(c0.R - c1.R, c0.G - c1.G, c0.B - c1.B);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator -(C3d col, double scalar)\n        {\n            return new C3d(col.R - scalar, col.G - scalar, col.B - scalar);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d operator -(double scalar, C3d col)\n        {\n            return new C3d(scalar - col.R, scalar - col.G, scalar - col.B);\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(double min, double max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d Clamped(double min, double max)\n        {\n            return new C3d(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max));\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. \n        /// </summary>\n        public readonly double Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(R) + Fun.Abs(G) + Fun.Abs(B); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). \n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). \n        /// </summary>\n        public readonly double NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(R), Fun.Abs(G), Fun.Abs(B)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). \n        /// </summary>\n        public readonly double NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(R), Fun.Abs(G), Fun.Abs(B)); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C3d o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C3d, int, double> Setter =\n            (ref C3d color, int i, double value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinearInterp(double t, C3d a, C3d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinearInterp(V3d t, C3d a, C3d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d DivideByInt(C3d c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3d.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C3d result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC3d();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                double[] values = new double[4] { 1.0, 1.0, 1.0, 1.0 };\n\n                double parse(Text t)\n                {\n                    if (!double.TryParse(t.ToString(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out double value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C3d(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C3d.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C3d result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3d color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<double>.Parse, C3d.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional and discarded.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C3d color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d Parse(Text t)\n            => TryParse(t, out C3d result) ? result : throw new FormatException($\"{t} is not a valid C3d color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C3d> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C3d other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return (R); }\n            set { R = (value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return (G); }\n            set { G = (value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return (B); }\n            set { B = (value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3d Lerp(this double t, C3d a, C3d b)\n            => new C3d(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C3d Lerp(this V3d t, C3d a, C3d b)\n            => new C3d(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C3d a, C3d b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C3d a, C3d b, double tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C3d c, double epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(C3d c)\n            => c.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"C3d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(C3d c)\n            => c.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C3d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(C3d c)\n            => c.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C3d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(C3d c)\n            => c.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C3d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(C3d c)\n            => c.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"C3d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(C3d c)\n            => c.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBB.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C3d c)\n            => c.ToC3b().ToHexString();\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3d a, C3d b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C3d col, double s)\n        {\n            return (col.R < s && col.G < s && col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, C3d col)\n        {\n            return (s < col.R && s < col.G && s < col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3d a, C3d b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C3d col, double s)\n        {\n            return (col.R < s || col.G < s || col.B < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, C3d col)\n        {\n            return (s < col.R || s < col.G || s < col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3d a, C3d b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C3d col, double s)\n        {\n            return (col.R > s && col.G > s && col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, C3d col)\n        {\n            return (s > col.R && s > col.G && s > col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3d a, C3d b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C3d col, double s)\n        {\n            return (col.R > s || col.G > s || col.B > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, C3d col)\n        {\n            return (s > col.R || s > col.G || s > col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3d a, C3d b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C3d col, double s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, C3d col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3d a, C3d b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C3d col, double s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, C3d col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3d a, C3d b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C3d col, double s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, C3d col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3d a, C3d b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C3d col, double s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, C3d col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3d a, C3d b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C3d col, double s)\n        {\n            return (col.R == s && col.G == s && col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, C3d col)\n        {\n            return (s == col.R && s == col.G && s == col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3d a, C3d b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C3d col, double s)\n        {\n            return (col.R == s || col.G == s || col.B == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, C3d col)\n        {\n            return (s == col.R || s == col.G || s == col.B);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3d a, C3d b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C3d col, double s)\n        {\n            return (col.R != s && col.G != s && col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, C3d col)\n        {\n            return (s != col.R && s != col.G && s != col.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3d a, C3d b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C3d col, double s)\n        {\n            return (col.R != s || col.G != s || col.B != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, C3d col)\n        {\n            return (s != col.R || s != col.G || s != col.B);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinCom(\n            C3d p0, C3d p1, C3d p2, C3d p3, ref Tup4<double> w)\n        {\n            return new C3d(\n                (p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                (p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                (p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d LinCom(\n            C3d p0, C3d p1, C3d p2, C3d p3, C3d p4, C3d p5, ref Tup6<double> w)\n        {\n            return new C3d(\n                (p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                (p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                (p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C3d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C3d c, double epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C3d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C3d c, double epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(C3d c)\n            => c.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(C3d c)\n            => c.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(C3d c)\n            => c.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(C3d c)\n            => c.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(C3d c)\n            => c.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(C3d c)\n            => c.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(C3d c)\n            => c.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(C3d c)\n            => c.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(C3d c)\n            => c.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(C3d c)\n            => c.AllTiny;\n\n        #endregion\n    }\n\n    public static class IRandomUniformC3dExtensions\n    {\n        #region IRandomUniform extensions for C3d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of a C3d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d UniformC3d(this IRandomUniform rnd)\n        {\n            return new C3d(rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of a C3d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d UniformC3dClosed(this IRandomUniform rnd)\n        {\n            return new C3d(rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of a C3d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d UniformC3dOpen(this IRandomUniform rnd)\n        {\n            return new C3d(rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of a C3d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d UniformC3dFull(this IRandomUniform rnd)\n        {\n            return new C3d(rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of a C3d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d UniformC3dFullClosed(this IRandomUniform rnd)\n        {\n            return new C3d(rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of a C3d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C3d UniformC3dFullOpen(this IRandomUniform rnd)\n        {\n            return new C3d(rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C4b\n\n    /// <summary>\n    /// Represents an RGBA color with each channel stored as a <see cref=\"byte\"/> value within [0, 255].\n    /// </summary>\n    [Serializable]\n    public partial struct C4b : IFormattable, IEquatable<C4b>, IRGB, IOpacity\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"byte\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(byte r, byte g, byte b, byte a)\n        {\n            R = r; G = g; B = b; A = a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> values.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(int r, int g, int b, int a)\n        {\n            R = (byte)r; G = (byte)g; B = (byte)b; A = (byte)a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> values.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(long r, long g, long b, long a)\n        {\n            R = (byte)r; G = (byte)g; B = (byte)b; A = (byte)a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(float r, float g, float b, float a)\n        {\n            R = Col.FloatToByteClamped(r);\n            G = Col.FloatToByteClamped(g);\n            B = Col.FloatToByteClamped(b);\n            A = Col.FloatToByteClamped(a);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(double r, double g, double b, double a)\n        {\n            R = Col.DoubleToByteClamped(r);\n            G = Col.DoubleToByteClamped(g);\n            B = Col.DoubleToByteClamped(b);\n            A = Col.DoubleToByteClamped(a);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"byte\"/> RGB values.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(byte r, byte g, byte b)\n        {\n            R = r; G = g; B = b;\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> RGB values.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(int r, int g, int b)\n        {\n            R = (byte)r; G = (byte)g; B = (byte)b;\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> RGB values.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(long r, long g, long b)\n        {\n            R = (byte)r; G = (byte)g; B = (byte)b;\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> RGB values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(float r, float g, float b)\n        {\n            \n            R = Col.FloatToByteClamped(r); \n            G = Col.FloatToByteClamped(g); \n            B = Col.FloatToByteClamped(b);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> RGB values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(double r, double g, double b)\n        {\n            R = Col.DoubleToByteClamped(r); G = Col.DoubleToByteClamped(g); B = Col.DoubleToByteClamped(b);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"byte\"/> value.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(byte gray)\n        {\n            R = gray; G = gray; B = gray; A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(float gray)\n        {\n            var value = Col.FloatToByteClamped(gray);\n            R = value; G = value; B = value; A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(double gray)\n        {\n            var value = Col.DoubleToByteClamped(gray);\n            R = value; G = value; B = value; A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3b color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3b color, byte alpha)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3us color)\n        {\n            R = Col.UShortToByte(color.R);\n            G = Col.UShortToByte(color.G);\n            B = Col.UShortToByte(color.B);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3us color, byte alpha)\n        {\n            R = Col.UShortToByte(color.R);\n            G = Col.UShortToByte(color.G);\n            B = Col.UShortToByte(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3ui color)\n        {\n            R = Col.UIntToByte(color.R);\n            G = Col.UIntToByte(color.G);\n            B = Col.UIntToByte(color.B);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3ui color, byte alpha)\n        {\n            R = Col.UIntToByte(color.R);\n            G = Col.UIntToByte(color.G);\n            B = Col.UIntToByte(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3f color)\n        {\n            R = Col.FloatToByteClamped(color.R);\n            G = Col.FloatToByteClamped(color.G);\n            B = Col.FloatToByteClamped(color.B);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color and an alpha value.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3f color, byte alpha)\n        {\n            R = Col.FloatToByteClamped(color.R);\n            G = Col.FloatToByteClamped(color.G);\n            B = Col.FloatToByteClamped(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3d color)\n        {\n            R = Col.DoubleToByteClamped(color.R);\n            G = Col.DoubleToByteClamped(color.G);\n            B = Col.DoubleToByteClamped(color.B);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color and an alpha value.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C3d color, byte alpha)\n        {\n            R = Col.DoubleToByteClamped(color.R);\n            G = Col.DoubleToByteClamped(color.G);\n            B = Col.DoubleToByteClamped(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C4b color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = (color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C4us color)\n        {\n            R = Col.UShortToByte(color.R);\n            G = Col.UShortToByte(color.G);\n            B = Col.UShortToByte(color.B);\n            A = Col.UShortToByte(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C4ui color)\n        {\n            R = Col.UIntToByte(color.R);\n            G = Col.UIntToByte(color.G);\n            B = Col.UIntToByte(color.B);\n            A = Col.UIntToByte(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C4f color)\n        {\n            R = Col.FloatToByteClamped(color.R);\n            G = Col.FloatToByteClamped(color.G);\n            B = Col.FloatToByteClamped(color.B);\n            A = Col.FloatToByteClamped(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(C4d color)\n        {\n            R = Col.DoubleToByteClamped(color.R);\n            G = Col.DoubleToByteClamped(color.G);\n            B = Col.DoubleToByteClamped(color.B);\n            A = Col.DoubleToByteClamped(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3i vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3ui vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3l vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3f vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3d vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = 255;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V4i vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = (byte)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V4ui vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = (byte)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V4l vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = (byte)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V4f vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = (byte)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V4d vec)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = (byte)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3i\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3i vec, byte alpha)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3ui vec, byte alpha)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3l vec, byte alpha)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3f vec, byte alpha)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(V3d vec, byte alpha)\n        {\n            R = (byte)(vec.X);\n            G = (byte)(vec.Y);\n            B = (byte)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(Func<int, byte> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n            A = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(byte[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n            A = (values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(byte[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n            A = (values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(ushort[] values)\n        {\n            R = Col.UShortToByte(values[0]);\n            G = Col.UShortToByte(values[1]);\n            B = Col.UShortToByte(values[2]);\n            A = Col.UShortToByte(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(ushort[] values, int start)\n        {\n            R = Col.UShortToByte(values[start + 0]);\n            G = Col.UShortToByte(values[start + 1]);\n            B = Col.UShortToByte(values[start + 2]);\n            A = Col.UShortToByte(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(uint[] values)\n        {\n            R = Col.UIntToByte(values[0]);\n            G = Col.UIntToByte(values[1]);\n            B = Col.UIntToByte(values[2]);\n            A = Col.UIntToByte(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(uint[] values, int start)\n        {\n            R = Col.UIntToByte(values[start + 0]);\n            G = Col.UIntToByte(values[start + 1]);\n            B = Col.UIntToByte(values[start + 2]);\n            A = Col.UIntToByte(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(float[] values)\n        {\n            R = Col.FloatToByteClamped(values[0]);\n            G = Col.FloatToByteClamped(values[1]);\n            B = Col.FloatToByteClamped(values[2]);\n            A = Col.FloatToByteClamped(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(float[] values, int start)\n        {\n            R = Col.FloatToByteClamped(values[start + 0]);\n            G = Col.FloatToByteClamped(values[start + 1]);\n            B = Col.FloatToByteClamped(values[start + 2]);\n            A = Col.FloatToByteClamped(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(double[] values)\n        {\n            R = Col.DoubleToByteClamped(values[0]);\n            G = Col.DoubleToByteClamped(values[1]);\n            B = Col.DoubleToByteClamped(values[2]);\n            A = Col.DoubleToByteClamped(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4b(double[] values, int start)\n        {\n            R = Col.DoubleToByteClamped(values[start + 0]);\n            G = Col.DoubleToByteClamped(values[start + 1]);\n            B = Col.DoubleToByteClamped(values[start + 2]);\n            A = Col.DoubleToByteClamped(values[start + 3]);\n        }\n\n        #endregion\n\n        #region Properities\n\n        public readonly C3b RGB => (C3b)this;\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4b\"/> color.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C3b color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3b\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC3b(C3b c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C3us color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC3us(C3us c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C3ui color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC3ui(C3ui c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C3f color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC3f(C3f c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C3d color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC3d(C3d c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C4us color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC4us(C4us c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C4ui color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC4ui(C4ui c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C4f color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC4f(C4f c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(C4d color)\n            => new C4b(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromC4d(C4d c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3i\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V3i v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV3i(V3i c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V3ui v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV3ui(V3ui c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V3l v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV3l(V3l c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V3f v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV3f(V3f c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V3d v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV3d(V3d c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4i\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V4i v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV4i(V4i c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V4ui v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV4ui(V4ui c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V4l v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV4l(V4l c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V4f v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV4f(V4f c) => new C4b(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(V4d v)\n            => new C4b(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4b\"/> color from a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b FromV4d(V4d c) => new C4b(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(byte[] values)\n            => new C4b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C4b\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C4b color)\n            => new byte[] { (color.R), (color.G), (color.B), (color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(ushort[] values)\n            => new C4b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C4b color)\n            => new ushort[] { Col.ByteToUShort(color.R), Col.ByteToUShort(color.G), Col.ByteToUShort(color.B), Col.ByteToUShort(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(uint[] values)\n            => new C4b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C4b color)\n            => new uint[] { Col.ByteToUInt(color.R), Col.ByteToUInt(color.G), Col.ByteToUInt(color.B), Col.ByteToUInt(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(float[] values)\n            => new C4b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C4b color)\n            => new float[] { Col.ByteToFloat(color.R), Col.ByteToFloat(color.G), Col.ByteToFloat(color.B), Col.ByteToFloat(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4b(double[] values)\n            => new C4b(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C4b color)\n            => new double[] { Col.ByteToDouble(color.R), Col.ByteToDouble(color.G), Col.ByteToDouble(color.B), Col.ByteToDouble(color.A) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b Map(Func<byte, byte> channel_fun)\n        {\n            return new C4b(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us Map(Func<byte, ushort> channel_fun)\n        {\n            return new C4us(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui Map(Func<byte, uint> channel_fun)\n        {\n            return new C4ui(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f Map(Func<byte, float> channel_fun)\n        {\n            return new C4f(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d Map(Func<byte, double> channel_fun)\n        {\n            return new C4d(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<byte, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n            array[start + 3] = element_fun(A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<byte, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n            array[start + 3] = element_index_fun(A, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly byte[] ToArray()\n            => (byte[])this;\n\n        #endregion\n\n        #region Indexer\n\n        // Byte colors have a different byte order (red and blue are swapped)\n        private static readonly byte[] IndexMapping = new byte[] { 2, 1, 0, 3 };\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe byte this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (byte* ptr = &B) { ptr[IndexMapping[i]] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (byte* ptr = &B) { return ptr[IndexMapping[i]]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C4b with all components zero.\n        /// </summary>\n        public static C4b Zero => new C4b(0, 0, 0, 0);\n\n        // Web colors\n        public static C4b AliceBlue => new C4b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.972549), Col.DoubleToByteClamped(1));\n        public static C4b AntiqueWhite => new C4b(Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.921569), Col.DoubleToByteClamped(0.843137));\n        public static C4b Aqua => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C4b Aquamarine => new C4b(Col.DoubleToByteClamped(0.498039), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.831373));\n        public static C4b Azure => new C4b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C4b Beige => new C4b(Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.862745));\n        public static C4b Bisque => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.894118), Col.DoubleToByteClamped(0.768627));\n        public static C4b Black => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0));\n        public static C4b BlanchedAlmond => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.921569), Col.DoubleToByteClamped(0.803922));\n        public static C4b Blue => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1));\n        public static C4b BlueViolet => new C4b(Col.DoubleToByteClamped(0.541176), Col.DoubleToByteClamped(0.168627), Col.DoubleToByteClamped(0.886275));\n        public static C4b Brown => new C4b(Col.DoubleToByteClamped(0.647059), Col.DoubleToByteClamped(0.164706), Col.DoubleToByteClamped(0.164706));\n        public static C4b BurlyWood => new C4b(Col.DoubleToByteClamped(0.870588), Col.DoubleToByteClamped(0.721569), Col.DoubleToByteClamped(0.529412));\n        public static C4b CadetBlue => new C4b(Col.DoubleToByteClamped(0.372549), Col.DoubleToByteClamped(0.619608), Col.DoubleToByteClamped(0.627451));\n        public static C4b Chartreuse => new C4b(Col.DoubleToByteClamped(0.498039), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0));\n        public static C4b Chocolate => new C4b(Col.DoubleToByteClamped(0.823529), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.117647));\n        public static C4b Coral => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.498039), Col.DoubleToByteClamped(0.313725));\n        public static C4b CornflowerBlue => new C4b(Col.DoubleToByteClamped(0.392157), Col.DoubleToByteClamped(0.584314), Col.DoubleToByteClamped(0.929412));\n        public static C4b Cornsilk => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.972549), Col.DoubleToByteClamped(0.862745));\n        public static C4b Crimson => new C4b(Col.DoubleToByteClamped(0.862745), Col.DoubleToByteClamped(0.078431), Col.DoubleToByteClamped(0.235294));\n        public static C4b Cyan => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C4b DarkBlue => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.545098));\n        public static C4b DarkCyan => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0.545098));\n        public static C4b DarkGoldenRod => new C4b(Col.DoubleToByteClamped(0.721569), Col.DoubleToByteClamped(0.52549), Col.DoubleToByteClamped(0.043137));\n        public static C4b DarkGray => new C4b(Col.DoubleToByteClamped(0.662745), Col.DoubleToByteClamped(0.662745), Col.DoubleToByteClamped(0.662745));\n        public static C4b DarkGrey => new C4b(Col.DoubleToByteClamped(0.662745), Col.DoubleToByteClamped(0.662745), Col.DoubleToByteClamped(0.662745));\n        public static C4b DarkGreen => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.392157), Col.DoubleToByteClamped(0));\n        public static C4b DarkKhaki => new C4b(Col.DoubleToByteClamped(0.741176), Col.DoubleToByteClamped(0.717647), Col.DoubleToByteClamped(0.419608));\n        public static C4b DarkMagenta => new C4b(Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.545098));\n        public static C4b DarkOliveGreen => new C4b(Col.DoubleToByteClamped(0.333333), Col.DoubleToByteClamped(0.419608), Col.DoubleToByteClamped(0.184314));\n        public static C4b DarkOrange => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.54902), Col.DoubleToByteClamped(0));\n        public static C4b DarkOrchid => new C4b(Col.DoubleToByteClamped(0.6), Col.DoubleToByteClamped(0.196078), Col.DoubleToByteClamped(0.8));\n        public static C4b DarkRed => new C4b(Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0));\n        public static C4b DarkSalmon => new C4b(Col.DoubleToByteClamped(0.913725), Col.DoubleToByteClamped(0.588235), Col.DoubleToByteClamped(0.478431));\n        public static C4b DarkSeaGreen => new C4b(Col.DoubleToByteClamped(0.560784), Col.DoubleToByteClamped(0.737255), Col.DoubleToByteClamped(0.560784));\n        public static C4b DarkSlateBlue => new C4b(Col.DoubleToByteClamped(0.282353), Col.DoubleToByteClamped(0.239216), Col.DoubleToByteClamped(0.545098));\n        public static C4b DarkSlateGray => new C4b(Col.DoubleToByteClamped(0.184314), Col.DoubleToByteClamped(0.309804), Col.DoubleToByteClamped(0.309804));\n        public static C4b DarkSlateGrey => new C4b(Col.DoubleToByteClamped(0.184314), Col.DoubleToByteClamped(0.309804), Col.DoubleToByteClamped(0.309804));\n        public static C4b DarkTurquoise => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.807843), Col.DoubleToByteClamped(0.819608));\n        public static C4b DarkViolet => new C4b(Col.DoubleToByteClamped(0.580392), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.827451));\n        public static C4b DeepPink => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.078431), Col.DoubleToByteClamped(0.576471));\n        public static C4b DeepSkyBlue => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.74902), Col.DoubleToByteClamped(1));\n        public static C4b DimGray => new C4b(Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.411765));\n        public static C4b DimGrey => new C4b(Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.411765));\n        public static C4b DodgerBlue => new C4b(Col.DoubleToByteClamped(0.117647), Col.DoubleToByteClamped(0.564706), Col.DoubleToByteClamped(1));\n        public static C4b FireBrick => new C4b(Col.DoubleToByteClamped(0.698039), Col.DoubleToByteClamped(0.133333), Col.DoubleToByteClamped(0.133333));\n        public static C4b FloralWhite => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.941176));\n        public static C4b ForestGreen => new C4b(Col.DoubleToByteClamped(0.133333), Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0.133333));\n        public static C4b Fuchsia => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1));\n        public static C4b Gainsboro => new C4b(Col.DoubleToByteClamped(0.862745), Col.DoubleToByteClamped(0.862745), Col.DoubleToByteClamped(0.862745));\n        public static C4b GhostWhite => new C4b(Col.DoubleToByteClamped(0.972549), Col.DoubleToByteClamped(0.972549), Col.DoubleToByteClamped(1));\n        public static C4b Gold => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.843137), Col.DoubleToByteClamped(0));\n        public static C4b GoldenRod => new C4b(Col.DoubleToByteClamped(0.854902), Col.DoubleToByteClamped(0.647059), Col.DoubleToByteClamped(0.12549));\n        public static C4b Gray => new C4b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961));\n        public static C4b Grey => new C4b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961));\n        public static C4b Green => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0));\n        public static C4b GreenYellow => new C4b(Col.DoubleToByteClamped(0.678431), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.184314));\n        public static C4b HoneyDew => new C4b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.941176));\n        public static C4b HotPink => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.705882));\n        public static C4b IndianRed  => new C4b(Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.360784), Col.DoubleToByteClamped(0.360784));\n        public static C4b Indigo  => new C4b(Col.DoubleToByteClamped(0.294118), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.509804));\n        public static C4b Ivory => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.941176));\n        public static C4b Khaki => new C4b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.901961), Col.DoubleToByteClamped(0.54902));\n        public static C4b Lavender => new C4b(Col.DoubleToByteClamped(0.901961), Col.DoubleToByteClamped(0.901961), Col.DoubleToByteClamped(0.980392));\n        public static C4b LavenderBlush => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.960784));\n        public static C4b LawnGreen => new C4b(Col.DoubleToByteClamped(0.486275), Col.DoubleToByteClamped(0.988235), Col.DoubleToByteClamped(0));\n        public static C4b LemonChiffon => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.803922));\n        public static C4b LightBlue => new C4b(Col.DoubleToByteClamped(0.678431), Col.DoubleToByteClamped(0.847059), Col.DoubleToByteClamped(0.901961));\n        public static C4b LightCoral => new C4b(Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961));\n        public static C4b LightCyan => new C4b(Col.DoubleToByteClamped(0.878431), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C4b LightGoldenRodYellow => new C4b(Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.823529));\n        public static C4b LightGray => new C4b(Col.DoubleToByteClamped(0.827451), Col.DoubleToByteClamped(0.827451), Col.DoubleToByteClamped(0.827451));\n        public static C4b LightGrey => new C4b(Col.DoubleToByteClamped(0.827451), Col.DoubleToByteClamped(0.827451), Col.DoubleToByteClamped(0.827451));\n        public static C4b LightGreen => new C4b(Col.DoubleToByteClamped(0.564706), Col.DoubleToByteClamped(0.933333), Col.DoubleToByteClamped(0.564706));\n        public static C4b LightPink => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.713725), Col.DoubleToByteClamped(0.756863));\n        public static C4b LightSalmon => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.627451), Col.DoubleToByteClamped(0.478431));\n        public static C4b LightSeaGreen => new C4b(Col.DoubleToByteClamped(0.12549), Col.DoubleToByteClamped(0.698039), Col.DoubleToByteClamped(0.666667));\n        public static C4b LightSkyBlue => new C4b(Col.DoubleToByteClamped(0.529412), Col.DoubleToByteClamped(0.807843), Col.DoubleToByteClamped(0.980392));\n        public static C4b LightSlateGray => new C4b(Col.DoubleToByteClamped(0.466667), Col.DoubleToByteClamped(0.533333), Col.DoubleToByteClamped(0.6));\n        public static C4b LightSlateGrey => new C4b(Col.DoubleToByteClamped(0.466667), Col.DoubleToByteClamped(0.533333), Col.DoubleToByteClamped(0.6));\n        public static C4b LightSteelBlue => new C4b(Col.DoubleToByteClamped(0.690196), Col.DoubleToByteClamped(0.768627), Col.DoubleToByteClamped(0.870588));\n        public static C4b LightYellow => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.878431));\n        public static C4b Lime => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0));\n        public static C4b LimeGreen => new C4b(Col.DoubleToByteClamped(0.196078), Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.196078));\n        public static C4b Linen => new C4b(Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.941176), Col.DoubleToByteClamped(0.901961));\n        public static C4b Magenta => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1));\n        public static C4b Maroon => new C4b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0));\n        public static C4b MediumAquaMarine => new C4b(Col.DoubleToByteClamped(0.4), Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.666667));\n        public static C4b MediumBlue => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.803922));\n        public static C4b MediumOrchid => new C4b(Col.DoubleToByteClamped(0.729412), Col.DoubleToByteClamped(0.333333), Col.DoubleToByteClamped(0.827451));\n        public static C4b MediumPurple => new C4b(Col.DoubleToByteClamped(0.576471), Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.847059));\n        public static C4b MediumSeaGreen => new C4b(Col.DoubleToByteClamped(0.235294), Col.DoubleToByteClamped(0.701961), Col.DoubleToByteClamped(0.443137));\n        public static C4b MediumSlateBlue => new C4b(Col.DoubleToByteClamped(0.482353), Col.DoubleToByteClamped(0.407843), Col.DoubleToByteClamped(0.933333));\n        public static C4b MediumSpringGreen => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.603922));\n        public static C4b MediumTurquoise => new C4b(Col.DoubleToByteClamped(0.282353), Col.DoubleToByteClamped(0.819608), Col.DoubleToByteClamped(0.8));\n        public static C4b MediumVioletRed => new C4b(Col.DoubleToByteClamped(0.780392), Col.DoubleToByteClamped(0.082353), Col.DoubleToByteClamped(0.521569));\n        public static C4b MidnightBlue => new C4b(Col.DoubleToByteClamped(0.098039), Col.DoubleToByteClamped(0.098039), Col.DoubleToByteClamped(0.439216));\n        public static C4b MintCream => new C4b(Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.980392));\n        public static C4b MistyRose => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.894118), Col.DoubleToByteClamped(0.882353));\n        public static C4b Moccasin => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.894118), Col.DoubleToByteClamped(0.709804));\n        public static C4b NavajoWhite => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.870588), Col.DoubleToByteClamped(0.678431));\n        public static C4b Navy => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.501961));\n        public static C4b OldLace => new C4b(Col.DoubleToByteClamped(0.992157), Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.901961));\n        public static C4b Olive => new C4b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0));\n        public static C4b OliveDrab => new C4b(Col.DoubleToByteClamped(0.419608), Col.DoubleToByteClamped(0.556863), Col.DoubleToByteClamped(0.137255));\n        public static C4b Orange => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.647059), Col.DoubleToByteClamped(0));\n        public static C4b OrangeRed => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.270588), Col.DoubleToByteClamped(0));\n        public static C4b Orchid => new C4b(Col.DoubleToByteClamped(0.854902), Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.839216));\n        public static C4b PaleGoldenRod => new C4b(Col.DoubleToByteClamped(0.933333), Col.DoubleToByteClamped(0.909804), Col.DoubleToByteClamped(0.666667));\n        public static C4b PaleGreen => new C4b(Col.DoubleToByteClamped(0.596078), Col.DoubleToByteClamped(0.984314), Col.DoubleToByteClamped(0.596078));\n        public static C4b PaleTurquoise => new C4b(Col.DoubleToByteClamped(0.686275), Col.DoubleToByteClamped(0.933333), Col.DoubleToByteClamped(0.933333));\n        public static C4b PaleVioletRed => new C4b(Col.DoubleToByteClamped(0.847059), Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.576471));\n        public static C4b PapayaWhip => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.937255), Col.DoubleToByteClamped(0.835294));\n        public static C4b PeachPuff => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.854902), Col.DoubleToByteClamped(0.72549));\n        public static C4b Peru => new C4b(Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.521569), Col.DoubleToByteClamped(0.247059));\n        public static C4b Pink => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.752941), Col.DoubleToByteClamped(0.796078));\n        public static C4b Plum => new C4b(Col.DoubleToByteClamped(0.866667), Col.DoubleToByteClamped(0.627451), Col.DoubleToByteClamped(0.866667));\n        public static C4b PowderBlue => new C4b(Col.DoubleToByteClamped(0.690196), Col.DoubleToByteClamped(0.878431), Col.DoubleToByteClamped(0.901961));\n        public static C4b Purple => new C4b(Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.501961));\n        public static C4b Red => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0));\n        public static C4b RosyBrown => new C4b(Col.DoubleToByteClamped(0.737255), Col.DoubleToByteClamped(0.560784), Col.DoubleToByteClamped(0.560784));\n        public static C4b RoyalBlue => new C4b(Col.DoubleToByteClamped(0.254902), Col.DoubleToByteClamped(0.411765), Col.DoubleToByteClamped(0.882353));\n        public static C4b SaddleBrown => new C4b(Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0.270588), Col.DoubleToByteClamped(0.07451));\n        public static C4b Salmon => new C4b(Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.447059));\n        public static C4b SandyBrown => new C4b(Col.DoubleToByteClamped(0.956863), Col.DoubleToByteClamped(0.643137), Col.DoubleToByteClamped(0.376471));\n        public static C4b SeaGreen => new C4b(Col.DoubleToByteClamped(0.180392), Col.DoubleToByteClamped(0.545098), Col.DoubleToByteClamped(0.341176));\n        public static C4b SeaShell => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.933333));\n        public static C4b Sienna => new C4b(Col.DoubleToByteClamped(0.627451), Col.DoubleToByteClamped(0.321569), Col.DoubleToByteClamped(0.176471));\n        public static C4b Silver => new C4b(Col.DoubleToByteClamped(0.752941), Col.DoubleToByteClamped(0.752941), Col.DoubleToByteClamped(0.752941));\n        public static C4b SkyBlue => new C4b(Col.DoubleToByteClamped(0.529412), Col.DoubleToByteClamped(0.807843), Col.DoubleToByteClamped(0.921569));\n        public static C4b SlateBlue => new C4b(Col.DoubleToByteClamped(0.415686), Col.DoubleToByteClamped(0.352941), Col.DoubleToByteClamped(0.803922));\n        public static C4b SlateGray => new C4b(Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.564706));\n        public static C4b SlateGrey => new C4b(Col.DoubleToByteClamped(0.439216), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.564706));\n        public static C4b Snow => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.980392), Col.DoubleToByteClamped(0.980392));\n        public static C4b SpringGreen => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.498039));\n        public static C4b SteelBlue => new C4b(Col.DoubleToByteClamped(0.27451), Col.DoubleToByteClamped(0.509804), Col.DoubleToByteClamped(0.705882));\n        public static C4b Tan => new C4b(Col.DoubleToByteClamped(0.823529), Col.DoubleToByteClamped(0.705882), Col.DoubleToByteClamped(0.54902));\n        public static C4b Teal => new C4b(Col.DoubleToByteClamped(0), Col.DoubleToByteClamped(0.501961), Col.DoubleToByteClamped(0.501961));\n        public static C4b Thistle => new C4b(Col.DoubleToByteClamped(0.847059), Col.DoubleToByteClamped(0.74902), Col.DoubleToByteClamped(0.847059));\n        public static C4b Tomato => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0.388235), Col.DoubleToByteClamped(0.278431));\n        public static C4b Turquoise => new C4b(Col.DoubleToByteClamped(0.25098), Col.DoubleToByteClamped(0.878431), Col.DoubleToByteClamped(0.815686));\n        public static C4b Violet => new C4b(Col.DoubleToByteClamped(0.933333), Col.DoubleToByteClamped(0.509804), Col.DoubleToByteClamped(0.933333));\n        public static C4b Wheat => new C4b(Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.870588), Col.DoubleToByteClamped(0.701961));\n        public static C4b White => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1));\n        public static C4b WhiteSmoke => new C4b(Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.960784), Col.DoubleToByteClamped(0.960784));\n        public static C4b Yellow => new C4b(Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(1), Col.DoubleToByteClamped(0));\n        public static C4b YellowGreen => new C4b(Col.DoubleToByteClamped(0.603922), Col.DoubleToByteClamped(0.803922), Col.DoubleToByteClamped(0.196078));\n\n        public static C4b DarkYellow => Olive;\n\n        public static C4b VRVisGreen => new C4b(Col.DoubleToByteClamped(0.698), Col.DoubleToByteClamped(0.851), Col.DoubleToByteClamped(0.008));\n\n        public static C4b Gray10 => new C4b(Col.DoubleToByteClamped(0.1));\n        public static C4b Gray20 => new C4b(Col.DoubleToByteClamped(0.2));\n        public static C4b Gray30 => new C4b(Col.DoubleToByteClamped(0.3));\n        public static C4b Gray40 => new C4b(Col.DoubleToByteClamped(0.4));\n        public static C4b Gray50 => new C4b(Col.DoubleToByteClamped(0.5));\n        public static C4b Gray60 => new C4b(Col.DoubleToByteClamped(0.6));\n        public static C4b Gray70 => new C4b(Col.DoubleToByteClamped(0.7));\n        public static C4b Gray80 => new C4b(Col.DoubleToByteClamped(0.8));\n        public static C4b Gray90 => new C4b(Col.DoubleToByteClamped(0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C4b a, C4b b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C4b a, C4b b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator *(C4b col, float scalar)\n        {\n            return new C4b(\n                Col.FloatToByteClamped(Col.ByteToFloat(col.R) * scalar), \n                Col.FloatToByteClamped(Col.ByteToFloat(col.G) * scalar), \n                Col.FloatToByteClamped(Col.ByteToFloat(col.B) * scalar), \n                Col.FloatToByteClamped(Col.ByteToFloat(col.A) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator *(float scalar, C4b col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator /(C4b col, float scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator /(float scalar, C4b col)\n        {\n            return new C4b(\n                Col.FloatToByteClamped(scalar / Col.ByteToFloat(col.R)), \n                Col.FloatToByteClamped(scalar / Col.ByteToFloat(col.G)), \n                Col.FloatToByteClamped(scalar / Col.ByteToFloat(col.B)), \n                Col.FloatToByteClamped(scalar / Col.ByteToFloat(col.A)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator *(C4b col, double scalar)\n        {\n            return new C4b(\n                Col.DoubleToByteClamped(Col.ByteToDouble(col.R) * scalar), \n                Col.DoubleToByteClamped(Col.ByteToDouble(col.G) * scalar), \n                Col.DoubleToByteClamped(Col.ByteToDouble(col.B) * scalar), \n                Col.DoubleToByteClamped(Col.ByteToDouble(col.A) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator *(double scalar, C4b col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator /(C4b col, double scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator /(double scalar, C4b col)\n        {\n            return new C4b(\n                Col.DoubleToByteClamped(scalar / Col.ByteToDouble(col.R)), \n                Col.DoubleToByteClamped(scalar / Col.ByteToDouble(col.G)), \n                Col.DoubleToByteClamped(scalar / Col.ByteToDouble(col.B)), \n                Col.DoubleToByteClamped(scalar / Col.ByteToDouble(col.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator +(C4b c0, C4us c1)\n        {\n            return new C4b(\n                (byte)(c0.R + Col.UShortToByte(c1.R)), \n                (byte)(c0.G + Col.UShortToByte(c1.G)), \n                (byte)(c0.B + Col.UShortToByte(c1.B)), \n                (byte)(c0.A + Col.UShortToByte(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator -(C4b c0, C4us c1)\n        {\n            return new C4b(\n                (byte)(c0.R - Col.UShortToByte(c1.R)), \n                (byte)(c0.G - Col.UShortToByte(c1.G)), \n                (byte)(c0.B - Col.UShortToByte(c1.B)), \n                (byte)(c0.A - Col.UShortToByte(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator +(C4b c0, C4ui c1)\n        {\n            return new C4b(\n                (byte)(c0.R + Col.UIntToByte(c1.R)), \n                (byte)(c0.G + Col.UIntToByte(c1.G)), \n                (byte)(c0.B + Col.UIntToByte(c1.B)), \n                (byte)(c0.A + Col.UIntToByte(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator -(C4b c0, C4ui c1)\n        {\n            return new C4b(\n                (byte)(c0.R - Col.UIntToByte(c1.R)), \n                (byte)(c0.G - Col.UIntToByte(c1.G)), \n                (byte)(c0.B - Col.UIntToByte(c1.B)), \n                (byte)(c0.A - Col.UIntToByte(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator +(C4b c0, C4f c1)\n        {\n            return new C4b(\n                (byte)(c0.R + Col.FloatToByte(c1.R)), \n                (byte)(c0.G + Col.FloatToByte(c1.G)), \n                (byte)(c0.B + Col.FloatToByte(c1.B)), \n                (byte)(c0.A + Col.FloatToByte(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator -(C4b c0, C4f c1)\n        {\n            return new C4b(\n                (byte)(c0.R - Col.FloatToByte(c1.R)), \n                (byte)(c0.G - Col.FloatToByte(c1.G)), \n                (byte)(c0.B - Col.FloatToByte(c1.B)), \n                (byte)(c0.A - Col.FloatToByte(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator +(C4b c0, C4d c1)\n        {\n            return new C4b(\n                (byte)(c0.R + Col.DoubleToByte(c1.R)), \n                (byte)(c0.G + Col.DoubleToByte(c1.G)), \n                (byte)(c0.B + Col.DoubleToByte(c1.B)), \n                (byte)(c0.A + Col.DoubleToByte(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator -(C4b c0, C4d c1)\n        {\n            return new C4b(\n                (byte)(c0.R - Col.DoubleToByte(c1.R)), \n                (byte)(c0.G - Col.DoubleToByte(c1.G)), \n                (byte)(c0.B - Col.DoubleToByte(c1.B)), \n                (byte)(c0.A - Col.DoubleToByte(c1.A)));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator *(C4b col, byte scalar)\n        {\n            return new C4b((byte)(col.R * scalar), (byte)(col.G * scalar), (byte)(col.B * scalar), (byte)(col.A * scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator *(byte scalar, C4b col)\n        {\n            return new C4b((byte)(scalar * col.R), (byte)(scalar * col.G), (byte)(scalar * col.B), (byte)(scalar * col.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator /(C4b col, byte scalar)\n        {\n            return new C4b((byte)(col.R / scalar), (byte)(col.G / scalar), (byte)(col.B / scalar), (byte)(col.A / scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator /(byte scalar, C4b col)\n        {\n            return new C4b((byte)(scalar / col.R), (byte)(scalar / col.G), (byte)(scalar / col.B), (byte)(scalar / col.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator *(C4b c0, C4b c1)\n        {\n            return new C4b((byte)(c0.R * c1.R), (byte)(c0.G * c1.G), (byte)(c0.B * c1.B), (byte)(c0.A * c1.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator /(C4b c0, C4b c1)\n        {\n            return new C4b((byte)(c0.R / c1.R), (byte)(c0.G / c1.G), (byte)(c0.B / c1.B), (byte)(c0.A / c1.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator +(C4b c0, C4b c1)\n        {\n            return new C4b(\n                (255 - c0.R > c1.R) ? c0.R + c1.R : 255, \n                (255 - c0.G > c1.G) ? c0.G + c1.G : 255, \n                (255 - c0.B > c1.B) ? c0.B + c1.B : 255, \n                (255 - c0.A > c1.A) ? c0.A + c1.A : 255\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator +(C4b col, byte scalar)\n        {\n            return new C4b(\n                (255 - col.R > scalar) ? col.R + scalar : 255, \n                (255 - col.G > scalar) ? col.G + scalar : 255, \n                (255 - col.B > scalar) ? col.B + scalar : 255, \n                (255 - col.A > scalar) ? col.A + scalar : 255\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator +(byte scalar, C4b col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator -(C4b c0, C4b c1)\n        {\n            return new C4b(\n                (c0.R > c1.R) ? c0.R - c1.R : 0, \n                (c0.G > c1.G) ? c0.G - c1.G : 0, \n                (c0.B > c1.B) ? c0.B - c1.B : 0, \n                (c0.A > c1.A) ? c0.A - c1.A : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator -(C4b col, byte scalar)\n        {\n            return new C4b(\n                (col.R > scalar) ? col.R - scalar : 0, \n                (col.G > scalar) ? col.G - scalar : 0, \n                (col.B > scalar) ? col.B - scalar : 0, \n                (col.A > scalar) ? col.A - scalar : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b operator -(byte scalar, C4b col)\n        {\n            return new C4b(\n                (scalar > col.R) ? scalar - col.R : 0, \n                (scalar > col.G) ? scalar - col.G : 0, \n                (scalar > col.B) ? scalar - col.B : 0, \n                (scalar > col.A) ? scalar - col.A : 0\n            );\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(byte min, byte max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b Clamped(byte min, byte max)\n        {\n            return new C4b(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max), A);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. The alpha channel is ignored.\n        /// </summary>\n        public readonly int Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return R + G + B; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). The alpha channel is ignored.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly byte NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(R, G, B); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly byte NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(R, G, B); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C4b o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B, A);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + A.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C4b, int, byte> Setter =\n            (ref C4b color, int i, byte value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    case 3: color.A = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b LinearInterp(float t, C4b a, C4b b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b LinearInterp(V4f t, C4b a, C4b b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b LinearInterp(double t, C4b a, C4b b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b LinearInterp(V4d t, C4b a, C4b b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b DivideByInt(C4b c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4b.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C4b result)\n        {\n            if (Col.TryParseHex(t, out result))\n            {\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                byte[] values = new byte[4] { 255, 255, 255, 255 };\n\n                byte parse(Text t)\n                {\n                    if (!byte.TryParse(t.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out byte value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C4b(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4b.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C4b result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4b color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<byte>.Parse, C4b.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4b color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b Parse(Text t)\n            => TryParse(t, out C4b result) ? result : throw new FormatException($\"{t} is not a valid C4b color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + between + A.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C4b> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C4b other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return Col.ByteToDouble(R); }\n            set { R = Col.DoubleToByteClamped(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return Col.ByteToDouble(G); }\n            set { G = Col.DoubleToByteClamped(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return Col.ByteToDouble(B); }\n            set { B = Col.DoubleToByteClamped(value); }\n        }\n\n        #endregion\n\n        #region IOpacity Members\n\n        [XmlIgnore]\n        public double Opacity\n        {\n            readonly get { return Col.ByteToDouble(A); }\n            set { A = Col.DoubleToByteClamped(value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4b Lerp(this float t, C4b a, C4b b)\n            => new C4b(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B), Lerp(t, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4b Lerp(this V4f t, C4b a, C4b b)\n            => new C4b(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B), Lerp(t.W, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4b Lerp(this double t, C4b a, C4b b)\n            => new C4b(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B), Lerp(t, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4b Lerp(this V4d t, C4b a, C4b b)\n            => new C4b(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B), Lerp(t.W, a.A, b.A));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C4b a, C4b b, byte tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance) && ApproximateEquals(a.A, b.A, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4b\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C4b c, byte epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBBAA.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C4b c)\n            => $\"{c.R:X2}{c.G:X2}{c.B:X2}{c.A:X2}\";\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4b a, C4b b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B && a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4b col, byte s)\n        {\n            return (col.R < s && col.G < s && col.B < s && col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(byte s, C4b col)\n        {\n            return (s < col.R && s < col.G && s < col.B && s < col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4b a, C4b b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B || a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4b col, byte s)\n        {\n            return (col.R < s || col.G < s || col.B < s || col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(byte s, C4b col)\n        {\n            return (s < col.R || s < col.G || s < col.B || s < col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4b a, C4b b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B && a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4b col, byte s)\n        {\n            return (col.R > s && col.G > s && col.B > s && col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(byte s, C4b col)\n        {\n            return (s > col.R && s > col.G && s > col.B && s > col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4b a, C4b b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B || a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4b col, byte s)\n        {\n            return (col.R > s || col.G > s || col.B > s || col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(byte s, C4b col)\n        {\n            return (s > col.R || s > col.G || s > col.B || s > col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4b a, C4b b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B && a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4b col, byte s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s && col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(byte s, C4b col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B && s <= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4b a, C4b b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B || a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4b col, byte s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s || col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(byte s, C4b col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B || s <= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4b a, C4b b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B && a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4b col, byte s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s && col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(byte s, C4b col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B && s >= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4b a, C4b b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B || a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4b col, byte s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s || col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(byte s, C4b col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B || s >= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4b a, C4b b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4b col, byte s)\n        {\n            return (col.R == s && col.G == s && col.B == s && col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(byte s, C4b col)\n        {\n            return (s == col.R && s == col.G && s == col.B && s == col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4b a, C4b b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B || a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4b col, byte s)\n        {\n            return (col.R == s || col.G == s || col.B == s || col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(byte s, C4b col)\n        {\n            return (s == col.R || s == col.G || s == col.B || s == col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4b a, C4b b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B && a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4b col, byte s)\n        {\n            return (col.R != s && col.G != s && col.B != s && col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(byte s, C4b col)\n        {\n            return (s != col.R && s != col.G && s != col.B && s != col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4b a, C4b b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4b col, byte s)\n        {\n            return (col.R != s || col.G != s || col.B != s || col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(byte s, C4b col)\n        {\n            return (s != col.R || s != col.G || s != col.B || s != col.A);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b LinCom(\n            C4b p0, C4b p1, C4b p2, C4b p3, ref Tup4<float> w)\n        {\n            return new C4b(\n                Col.ByteInFloatToByteClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.ByteInFloatToByteClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.ByteInFloatToByteClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinComRawF(\n            C4b p0, C4b p1, C4b p2, C4b p3, ref Tup4<float> w)\n        {\n            return new C4f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b LinCom(\n            C4b p0, C4b p1, C4b p2, C4b p3, ref Tup4<double> w)\n        {\n            return new C4b(\n                Col.ByteInDoubleToByteClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.ByteInDoubleToByteClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.ByteInDoubleToByteClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinComRawD(\n            C4b p0, C4b p1, C4b p2, C4b p3, ref Tup4<double> w)\n        {\n            return new C4d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b LinCom(\n            C4b p0, C4b p1, C4b p2, C4b p3, C4b p4, C4b p5, ref Tup6<float> w)\n        {\n            return new C4b(\n                Col.ByteInFloatToByteClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.ByteInFloatToByteClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.ByteInFloatToByteClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinComRawF(\n            C4b p0, C4b p1, C4b p2, C4b p3, C4b p4, C4b p5, ref Tup6<float> w)\n        {\n            return new C4f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4b LinCom(\n            C4b p0, C4b p1, C4b p2, C4b p3, C4b p4, C4b p5, ref Tup6<double> w)\n        {\n            return new C4b(\n                Col.ByteInDoubleToByteClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.ByteInDoubleToByteClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.ByteInDoubleToByteClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinComRawD(\n            C4b p0, C4b p1, C4b p2, C4b p3, C4b p4, C4b p5, ref Tup6<double> w)\n        {\n            return new C4d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C4b\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C4b c, byte epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon) || c.A.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4b\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C4b c, byte epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon) && c.A.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C4us\n\n    /// <summary>\n    /// Represents an RGBA color with each channel stored as a <see cref=\"ushort\"/> value within [0, 2^16 - 1].\n    /// </summary>\n    [Serializable]\n    public partial struct C4us : IFormattable, IEquatable<C4us>, IRGB, IOpacity\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"ushort\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(ushort r, ushort g, ushort b, ushort a)\n        {\n            R = r; G = g; B = b; A = a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> values.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(int r, int g, int b, int a)\n        {\n            R = (ushort)r; G = (ushort)g; B = (ushort)b; A = (ushort)a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> values.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(long r, long g, long b, long a)\n        {\n            R = (ushort)r; G = (ushort)g; B = (ushort)b; A = (ushort)a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(float r, float g, float b, float a)\n        {\n            R = Col.FloatToUShortClamped(r);\n            G = Col.FloatToUShortClamped(g);\n            B = Col.FloatToUShortClamped(b);\n            A = Col.FloatToUShortClamped(a);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(double r, double g, double b, double a)\n        {\n            R = Col.DoubleToUShortClamped(r);\n            G = Col.DoubleToUShortClamped(g);\n            B = Col.DoubleToUShortClamped(b);\n            A = Col.DoubleToUShortClamped(a);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"ushort\"/> RGB values.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(ushort r, ushort g, ushort b)\n        {\n            R = r; G = g; B = b;\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> RGB values.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(int r, int g, int b)\n        {\n            R = (ushort)r; G = (ushort)g; B = (ushort)b;\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> RGB values.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(long r, long g, long b)\n        {\n            R = (ushort)r; G = (ushort)g; B = (ushort)b;\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> RGB values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(float r, float g, float b)\n        {\n            \n            R = Col.FloatToUShortClamped(r); \n            G = Col.FloatToUShortClamped(g); \n            B = Col.FloatToUShortClamped(b);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> RGB values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(double r, double g, double b)\n        {\n            R = Col.DoubleToUShortClamped(r); G = Col.DoubleToUShortClamped(g); B = Col.DoubleToUShortClamped(b);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"ushort\"/> value.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(ushort gray)\n        {\n            R = gray; G = gray; B = gray; A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(float gray)\n        {\n            var value = Col.FloatToUShortClamped(gray);\n            R = value; G = value; B = value; A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(double gray)\n        {\n            var value = Col.DoubleToUShortClamped(gray);\n            R = value; G = value; B = value; A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3b color)\n        {\n            R = Col.ByteToUShort(color.R);\n            G = Col.ByteToUShort(color.G);\n            B = Col.ByteToUShort(color.B);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3b color, ushort alpha)\n        {\n            R = Col.ByteToUShort(color.R);\n            G = Col.ByteToUShort(color.G);\n            B = Col.ByteToUShort(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3us color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3us color, ushort alpha)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3ui color)\n        {\n            R = Col.UIntToUShort(color.R);\n            G = Col.UIntToUShort(color.G);\n            B = Col.UIntToUShort(color.B);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3ui color, ushort alpha)\n        {\n            R = Col.UIntToUShort(color.R);\n            G = Col.UIntToUShort(color.G);\n            B = Col.UIntToUShort(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3f color)\n        {\n            R = Col.FloatToUShortClamped(color.R);\n            G = Col.FloatToUShortClamped(color.G);\n            B = Col.FloatToUShortClamped(color.B);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color and an alpha value.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3f color, ushort alpha)\n        {\n            R = Col.FloatToUShortClamped(color.R);\n            G = Col.FloatToUShortClamped(color.G);\n            B = Col.FloatToUShortClamped(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3d color)\n        {\n            R = Col.DoubleToUShortClamped(color.R);\n            G = Col.DoubleToUShortClamped(color.G);\n            B = Col.DoubleToUShortClamped(color.B);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color and an alpha value.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C3d color, ushort alpha)\n        {\n            R = Col.DoubleToUShortClamped(color.R);\n            G = Col.DoubleToUShortClamped(color.G);\n            B = Col.DoubleToUShortClamped(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C4b color)\n        {\n            R = Col.ByteToUShort(color.R);\n            G = Col.ByteToUShort(color.G);\n            B = Col.ByteToUShort(color.B);\n            A = Col.ByteToUShort(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C4us color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = (color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C4ui color)\n        {\n            R = Col.UIntToUShort(color.R);\n            G = Col.UIntToUShort(color.G);\n            B = Col.UIntToUShort(color.B);\n            A = Col.UIntToUShort(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C4f color)\n        {\n            R = Col.FloatToUShortClamped(color.R);\n            G = Col.FloatToUShortClamped(color.G);\n            B = Col.FloatToUShortClamped(color.B);\n            A = Col.FloatToUShortClamped(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(C4d color)\n        {\n            R = Col.DoubleToUShortClamped(color.R);\n            G = Col.DoubleToUShortClamped(color.G);\n            B = Col.DoubleToUShortClamped(color.B);\n            A = Col.DoubleToUShortClamped(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3i vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3ui vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3l vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3f vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3d vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = 65535;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V4i vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = (ushort)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V4ui vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = (ushort)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V4l vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = (ushort)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V4f vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = (ushort)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V4d vec)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = (ushort)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3i\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3i vec, ushort alpha)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3ui vec, ushort alpha)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3l vec, ushort alpha)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3f vec, ushort alpha)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(V3d vec, ushort alpha)\n        {\n            R = (ushort)(vec.X);\n            G = (ushort)(vec.Y);\n            B = (ushort)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(Func<int, ushort> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n            A = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(byte[] values)\n        {\n            R = Col.ByteToUShort(values[0]);\n            G = Col.ByteToUShort(values[1]);\n            B = Col.ByteToUShort(values[2]);\n            A = Col.ByteToUShort(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(byte[] values, int start)\n        {\n            R = Col.ByteToUShort(values[start + 0]);\n            G = Col.ByteToUShort(values[start + 1]);\n            B = Col.ByteToUShort(values[start + 2]);\n            A = Col.ByteToUShort(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(ushort[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n            A = (values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(ushort[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n            A = (values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(uint[] values)\n        {\n            R = Col.UIntToUShort(values[0]);\n            G = Col.UIntToUShort(values[1]);\n            B = Col.UIntToUShort(values[2]);\n            A = Col.UIntToUShort(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(uint[] values, int start)\n        {\n            R = Col.UIntToUShort(values[start + 0]);\n            G = Col.UIntToUShort(values[start + 1]);\n            B = Col.UIntToUShort(values[start + 2]);\n            A = Col.UIntToUShort(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(float[] values)\n        {\n            R = Col.FloatToUShortClamped(values[0]);\n            G = Col.FloatToUShortClamped(values[1]);\n            B = Col.FloatToUShortClamped(values[2]);\n            A = Col.FloatToUShortClamped(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(float[] values, int start)\n        {\n            R = Col.FloatToUShortClamped(values[start + 0]);\n            G = Col.FloatToUShortClamped(values[start + 1]);\n            B = Col.FloatToUShortClamped(values[start + 2]);\n            A = Col.FloatToUShortClamped(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(double[] values)\n        {\n            R = Col.DoubleToUShortClamped(values[0]);\n            G = Col.DoubleToUShortClamped(values[1]);\n            B = Col.DoubleToUShortClamped(values[2]);\n            A = Col.DoubleToUShortClamped(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4us(double[] values, int start)\n        {\n            R = Col.DoubleToUShortClamped(values[start + 0]);\n            G = Col.DoubleToUShortClamped(values[start + 1]);\n            B = Col.DoubleToUShortClamped(values[start + 2]);\n            A = Col.DoubleToUShortClamped(values[start + 3]);\n        }\n\n        #endregion\n\n        #region Properities\n\n        public readonly C3us RGB => (C3us)this;\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C3b color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC3b(C3b c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4us\"/> color.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C3us color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3us\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC3us(C3us c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C3ui color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC3ui(C3ui c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C3f color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC3f(C3f c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C3d color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC3d(C3d c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C4b color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC4b(C4b c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C4ui color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC4ui(C4ui c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C4f color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC4f(C4f c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(C4d color)\n            => new C4us(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromC4d(C4d c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3i\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V3i v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV3i(V3i c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V3ui v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV3ui(V3ui c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V3l v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV3l(V3l c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V3f v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV3f(V3f c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V3d v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV3d(V3d c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4i\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V4i v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV4i(V4i c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V4ui v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV4ui(V4ui c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V4l v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV4l(V4l c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V4f v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV4f(V4f c) => new C4us(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(V4d v)\n            => new C4us(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4us\"/> color from a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us FromV4d(V4d c) => new C4us(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(byte[] values)\n            => new C4us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C4us color)\n            => new byte[] { Col.UShortToByte(color.R), Col.UShortToByte(color.G), Col.UShortToByte(color.B), Col.UShortToByte(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(ushort[] values)\n            => new C4us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C4us\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C4us color)\n            => new ushort[] { (color.R), (color.G), (color.B), (color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(uint[] values)\n            => new C4us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C4us color)\n            => new uint[] { Col.UShortToUInt(color.R), Col.UShortToUInt(color.G), Col.UShortToUInt(color.B), Col.UShortToUInt(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(float[] values)\n            => new C4us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C4us color)\n            => new float[] { Col.UShortToFloat(color.R), Col.UShortToFloat(color.G), Col.UShortToFloat(color.B), Col.UShortToFloat(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4us(double[] values)\n            => new C4us(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C4us color)\n            => new double[] { Col.UShortToDouble(color.R), Col.UShortToDouble(color.G), Col.UShortToDouble(color.B), Col.UShortToDouble(color.A) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b Map(Func<ushort, byte> channel_fun)\n        {\n            return new C4b(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us Map(Func<ushort, ushort> channel_fun)\n        {\n            return new C4us(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui Map(Func<ushort, uint> channel_fun)\n        {\n            return new C4ui(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f Map(Func<ushort, float> channel_fun)\n        {\n            return new C4f(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d Map(Func<ushort, double> channel_fun)\n        {\n            return new C4d(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<ushort, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n            array[start + 3] = element_fun(A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<ushort, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n            array[start + 3] = element_index_fun(A, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly ushort[] ToArray()\n            => (ushort[])this;\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe ushort this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (ushort* ptr = &R) { ptr[i] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (ushort* ptr = &R) { return ptr[i]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C4us with all components zero.\n        /// </summary>\n        public static C4us Zero => new C4us(0, 0, 0, 0);\n\n        // Web colors\n        public static C4us AliceBlue => new C4us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.972549), Col.DoubleToUShortClamped(1));\n        public static C4us AntiqueWhite => new C4us(Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.921569), Col.DoubleToUShortClamped(0.843137));\n        public static C4us Aqua => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C4us Aquamarine => new C4us(Col.DoubleToUShortClamped(0.498039), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.831373));\n        public static C4us Azure => new C4us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C4us Beige => new C4us(Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.862745));\n        public static C4us Bisque => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.894118), Col.DoubleToUShortClamped(0.768627));\n        public static C4us Black => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0));\n        public static C4us BlanchedAlmond => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.921569), Col.DoubleToUShortClamped(0.803922));\n        public static C4us Blue => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1));\n        public static C4us BlueViolet => new C4us(Col.DoubleToUShortClamped(0.541176), Col.DoubleToUShortClamped(0.168627), Col.DoubleToUShortClamped(0.886275));\n        public static C4us Brown => new C4us(Col.DoubleToUShortClamped(0.647059), Col.DoubleToUShortClamped(0.164706), Col.DoubleToUShortClamped(0.164706));\n        public static C4us BurlyWood => new C4us(Col.DoubleToUShortClamped(0.870588), Col.DoubleToUShortClamped(0.721569), Col.DoubleToUShortClamped(0.529412));\n        public static C4us CadetBlue => new C4us(Col.DoubleToUShortClamped(0.372549), Col.DoubleToUShortClamped(0.619608), Col.DoubleToUShortClamped(0.627451));\n        public static C4us Chartreuse => new C4us(Col.DoubleToUShortClamped(0.498039), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0));\n        public static C4us Chocolate => new C4us(Col.DoubleToUShortClamped(0.823529), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.117647));\n        public static C4us Coral => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.498039), Col.DoubleToUShortClamped(0.313725));\n        public static C4us CornflowerBlue => new C4us(Col.DoubleToUShortClamped(0.392157), Col.DoubleToUShortClamped(0.584314), Col.DoubleToUShortClamped(0.929412));\n        public static C4us Cornsilk => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.972549), Col.DoubleToUShortClamped(0.862745));\n        public static C4us Crimson => new C4us(Col.DoubleToUShortClamped(0.862745), Col.DoubleToUShortClamped(0.078431), Col.DoubleToUShortClamped(0.235294));\n        public static C4us Cyan => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C4us DarkBlue => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.545098));\n        public static C4us DarkCyan => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0.545098));\n        public static C4us DarkGoldenRod => new C4us(Col.DoubleToUShortClamped(0.721569), Col.DoubleToUShortClamped(0.52549), Col.DoubleToUShortClamped(0.043137));\n        public static C4us DarkGray => new C4us(Col.DoubleToUShortClamped(0.662745), Col.DoubleToUShortClamped(0.662745), Col.DoubleToUShortClamped(0.662745));\n        public static C4us DarkGrey => new C4us(Col.DoubleToUShortClamped(0.662745), Col.DoubleToUShortClamped(0.662745), Col.DoubleToUShortClamped(0.662745));\n        public static C4us DarkGreen => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.392157), Col.DoubleToUShortClamped(0));\n        public static C4us DarkKhaki => new C4us(Col.DoubleToUShortClamped(0.741176), Col.DoubleToUShortClamped(0.717647), Col.DoubleToUShortClamped(0.419608));\n        public static C4us DarkMagenta => new C4us(Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.545098));\n        public static C4us DarkOliveGreen => new C4us(Col.DoubleToUShortClamped(0.333333), Col.DoubleToUShortClamped(0.419608), Col.DoubleToUShortClamped(0.184314));\n        public static C4us DarkOrange => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.54902), Col.DoubleToUShortClamped(0));\n        public static C4us DarkOrchid => new C4us(Col.DoubleToUShortClamped(0.6), Col.DoubleToUShortClamped(0.196078), Col.DoubleToUShortClamped(0.8));\n        public static C4us DarkRed => new C4us(Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0));\n        public static C4us DarkSalmon => new C4us(Col.DoubleToUShortClamped(0.913725), Col.DoubleToUShortClamped(0.588235), Col.DoubleToUShortClamped(0.478431));\n        public static C4us DarkSeaGreen => new C4us(Col.DoubleToUShortClamped(0.560784), Col.DoubleToUShortClamped(0.737255), Col.DoubleToUShortClamped(0.560784));\n        public static C4us DarkSlateBlue => new C4us(Col.DoubleToUShortClamped(0.282353), Col.DoubleToUShortClamped(0.239216), Col.DoubleToUShortClamped(0.545098));\n        public static C4us DarkSlateGray => new C4us(Col.DoubleToUShortClamped(0.184314), Col.DoubleToUShortClamped(0.309804), Col.DoubleToUShortClamped(0.309804));\n        public static C4us DarkSlateGrey => new C4us(Col.DoubleToUShortClamped(0.184314), Col.DoubleToUShortClamped(0.309804), Col.DoubleToUShortClamped(0.309804));\n        public static C4us DarkTurquoise => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.807843), Col.DoubleToUShortClamped(0.819608));\n        public static C4us DarkViolet => new C4us(Col.DoubleToUShortClamped(0.580392), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.827451));\n        public static C4us DeepPink => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.078431), Col.DoubleToUShortClamped(0.576471));\n        public static C4us DeepSkyBlue => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.74902), Col.DoubleToUShortClamped(1));\n        public static C4us DimGray => new C4us(Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.411765));\n        public static C4us DimGrey => new C4us(Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.411765));\n        public static C4us DodgerBlue => new C4us(Col.DoubleToUShortClamped(0.117647), Col.DoubleToUShortClamped(0.564706), Col.DoubleToUShortClamped(1));\n        public static C4us FireBrick => new C4us(Col.DoubleToUShortClamped(0.698039), Col.DoubleToUShortClamped(0.133333), Col.DoubleToUShortClamped(0.133333));\n        public static C4us FloralWhite => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.941176));\n        public static C4us ForestGreen => new C4us(Col.DoubleToUShortClamped(0.133333), Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0.133333));\n        public static C4us Fuchsia => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1));\n        public static C4us Gainsboro => new C4us(Col.DoubleToUShortClamped(0.862745), Col.DoubleToUShortClamped(0.862745), Col.DoubleToUShortClamped(0.862745));\n        public static C4us GhostWhite => new C4us(Col.DoubleToUShortClamped(0.972549), Col.DoubleToUShortClamped(0.972549), Col.DoubleToUShortClamped(1));\n        public static C4us Gold => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.843137), Col.DoubleToUShortClamped(0));\n        public static C4us GoldenRod => new C4us(Col.DoubleToUShortClamped(0.854902), Col.DoubleToUShortClamped(0.647059), Col.DoubleToUShortClamped(0.12549));\n        public static C4us Gray => new C4us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961));\n        public static C4us Grey => new C4us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961));\n        public static C4us Green => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0));\n        public static C4us GreenYellow => new C4us(Col.DoubleToUShortClamped(0.678431), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.184314));\n        public static C4us HoneyDew => new C4us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.941176));\n        public static C4us HotPink => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.705882));\n        public static C4us IndianRed  => new C4us(Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.360784), Col.DoubleToUShortClamped(0.360784));\n        public static C4us Indigo  => new C4us(Col.DoubleToUShortClamped(0.294118), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.509804));\n        public static C4us Ivory => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.941176));\n        public static C4us Khaki => new C4us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.901961), Col.DoubleToUShortClamped(0.54902));\n        public static C4us Lavender => new C4us(Col.DoubleToUShortClamped(0.901961), Col.DoubleToUShortClamped(0.901961), Col.DoubleToUShortClamped(0.980392));\n        public static C4us LavenderBlush => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.960784));\n        public static C4us LawnGreen => new C4us(Col.DoubleToUShortClamped(0.486275), Col.DoubleToUShortClamped(0.988235), Col.DoubleToUShortClamped(0));\n        public static C4us LemonChiffon => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.803922));\n        public static C4us LightBlue => new C4us(Col.DoubleToUShortClamped(0.678431), Col.DoubleToUShortClamped(0.847059), Col.DoubleToUShortClamped(0.901961));\n        public static C4us LightCoral => new C4us(Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961));\n        public static C4us LightCyan => new C4us(Col.DoubleToUShortClamped(0.878431), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C4us LightGoldenRodYellow => new C4us(Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.823529));\n        public static C4us LightGray => new C4us(Col.DoubleToUShortClamped(0.827451), Col.DoubleToUShortClamped(0.827451), Col.DoubleToUShortClamped(0.827451));\n        public static C4us LightGrey => new C4us(Col.DoubleToUShortClamped(0.827451), Col.DoubleToUShortClamped(0.827451), Col.DoubleToUShortClamped(0.827451));\n        public static C4us LightGreen => new C4us(Col.DoubleToUShortClamped(0.564706), Col.DoubleToUShortClamped(0.933333), Col.DoubleToUShortClamped(0.564706));\n        public static C4us LightPink => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.713725), Col.DoubleToUShortClamped(0.756863));\n        public static C4us LightSalmon => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.627451), Col.DoubleToUShortClamped(0.478431));\n        public static C4us LightSeaGreen => new C4us(Col.DoubleToUShortClamped(0.12549), Col.DoubleToUShortClamped(0.698039), Col.DoubleToUShortClamped(0.666667));\n        public static C4us LightSkyBlue => new C4us(Col.DoubleToUShortClamped(0.529412), Col.DoubleToUShortClamped(0.807843), Col.DoubleToUShortClamped(0.980392));\n        public static C4us LightSlateGray => new C4us(Col.DoubleToUShortClamped(0.466667), Col.DoubleToUShortClamped(0.533333), Col.DoubleToUShortClamped(0.6));\n        public static C4us LightSlateGrey => new C4us(Col.DoubleToUShortClamped(0.466667), Col.DoubleToUShortClamped(0.533333), Col.DoubleToUShortClamped(0.6));\n        public static C4us LightSteelBlue => new C4us(Col.DoubleToUShortClamped(0.690196), Col.DoubleToUShortClamped(0.768627), Col.DoubleToUShortClamped(0.870588));\n        public static C4us LightYellow => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.878431));\n        public static C4us Lime => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0));\n        public static C4us LimeGreen => new C4us(Col.DoubleToUShortClamped(0.196078), Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.196078));\n        public static C4us Linen => new C4us(Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.941176), Col.DoubleToUShortClamped(0.901961));\n        public static C4us Magenta => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1));\n        public static C4us Maroon => new C4us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0));\n        public static C4us MediumAquaMarine => new C4us(Col.DoubleToUShortClamped(0.4), Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.666667));\n        public static C4us MediumBlue => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.803922));\n        public static C4us MediumOrchid => new C4us(Col.DoubleToUShortClamped(0.729412), Col.DoubleToUShortClamped(0.333333), Col.DoubleToUShortClamped(0.827451));\n        public static C4us MediumPurple => new C4us(Col.DoubleToUShortClamped(0.576471), Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.847059));\n        public static C4us MediumSeaGreen => new C4us(Col.DoubleToUShortClamped(0.235294), Col.DoubleToUShortClamped(0.701961), Col.DoubleToUShortClamped(0.443137));\n        public static C4us MediumSlateBlue => new C4us(Col.DoubleToUShortClamped(0.482353), Col.DoubleToUShortClamped(0.407843), Col.DoubleToUShortClamped(0.933333));\n        public static C4us MediumSpringGreen => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.603922));\n        public static C4us MediumTurquoise => new C4us(Col.DoubleToUShortClamped(0.282353), Col.DoubleToUShortClamped(0.819608), Col.DoubleToUShortClamped(0.8));\n        public static C4us MediumVioletRed => new C4us(Col.DoubleToUShortClamped(0.780392), Col.DoubleToUShortClamped(0.082353), Col.DoubleToUShortClamped(0.521569));\n        public static C4us MidnightBlue => new C4us(Col.DoubleToUShortClamped(0.098039), Col.DoubleToUShortClamped(0.098039), Col.DoubleToUShortClamped(0.439216));\n        public static C4us MintCream => new C4us(Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.980392));\n        public static C4us MistyRose => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.894118), Col.DoubleToUShortClamped(0.882353));\n        public static C4us Moccasin => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.894118), Col.DoubleToUShortClamped(0.709804));\n        public static C4us NavajoWhite => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.870588), Col.DoubleToUShortClamped(0.678431));\n        public static C4us Navy => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.501961));\n        public static C4us OldLace => new C4us(Col.DoubleToUShortClamped(0.992157), Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.901961));\n        public static C4us Olive => new C4us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0));\n        public static C4us OliveDrab => new C4us(Col.DoubleToUShortClamped(0.419608), Col.DoubleToUShortClamped(0.556863), Col.DoubleToUShortClamped(0.137255));\n        public static C4us Orange => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.647059), Col.DoubleToUShortClamped(0));\n        public static C4us OrangeRed => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.270588), Col.DoubleToUShortClamped(0));\n        public static C4us Orchid => new C4us(Col.DoubleToUShortClamped(0.854902), Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.839216));\n        public static C4us PaleGoldenRod => new C4us(Col.DoubleToUShortClamped(0.933333), Col.DoubleToUShortClamped(0.909804), Col.DoubleToUShortClamped(0.666667));\n        public static C4us PaleGreen => new C4us(Col.DoubleToUShortClamped(0.596078), Col.DoubleToUShortClamped(0.984314), Col.DoubleToUShortClamped(0.596078));\n        public static C4us PaleTurquoise => new C4us(Col.DoubleToUShortClamped(0.686275), Col.DoubleToUShortClamped(0.933333), Col.DoubleToUShortClamped(0.933333));\n        public static C4us PaleVioletRed => new C4us(Col.DoubleToUShortClamped(0.847059), Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.576471));\n        public static C4us PapayaWhip => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.937255), Col.DoubleToUShortClamped(0.835294));\n        public static C4us PeachPuff => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.854902), Col.DoubleToUShortClamped(0.72549));\n        public static C4us Peru => new C4us(Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.521569), Col.DoubleToUShortClamped(0.247059));\n        public static C4us Pink => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.752941), Col.DoubleToUShortClamped(0.796078));\n        public static C4us Plum => new C4us(Col.DoubleToUShortClamped(0.866667), Col.DoubleToUShortClamped(0.627451), Col.DoubleToUShortClamped(0.866667));\n        public static C4us PowderBlue => new C4us(Col.DoubleToUShortClamped(0.690196), Col.DoubleToUShortClamped(0.878431), Col.DoubleToUShortClamped(0.901961));\n        public static C4us Purple => new C4us(Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.501961));\n        public static C4us Red => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0));\n        public static C4us RosyBrown => new C4us(Col.DoubleToUShortClamped(0.737255), Col.DoubleToUShortClamped(0.560784), Col.DoubleToUShortClamped(0.560784));\n        public static C4us RoyalBlue => new C4us(Col.DoubleToUShortClamped(0.254902), Col.DoubleToUShortClamped(0.411765), Col.DoubleToUShortClamped(0.882353));\n        public static C4us SaddleBrown => new C4us(Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0.270588), Col.DoubleToUShortClamped(0.07451));\n        public static C4us Salmon => new C4us(Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.447059));\n        public static C4us SandyBrown => new C4us(Col.DoubleToUShortClamped(0.956863), Col.DoubleToUShortClamped(0.643137), Col.DoubleToUShortClamped(0.376471));\n        public static C4us SeaGreen => new C4us(Col.DoubleToUShortClamped(0.180392), Col.DoubleToUShortClamped(0.545098), Col.DoubleToUShortClamped(0.341176));\n        public static C4us SeaShell => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.933333));\n        public static C4us Sienna => new C4us(Col.DoubleToUShortClamped(0.627451), Col.DoubleToUShortClamped(0.321569), Col.DoubleToUShortClamped(0.176471));\n        public static C4us Silver => new C4us(Col.DoubleToUShortClamped(0.752941), Col.DoubleToUShortClamped(0.752941), Col.DoubleToUShortClamped(0.752941));\n        public static C4us SkyBlue => new C4us(Col.DoubleToUShortClamped(0.529412), Col.DoubleToUShortClamped(0.807843), Col.DoubleToUShortClamped(0.921569));\n        public static C4us SlateBlue => new C4us(Col.DoubleToUShortClamped(0.415686), Col.DoubleToUShortClamped(0.352941), Col.DoubleToUShortClamped(0.803922));\n        public static C4us SlateGray => new C4us(Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.564706));\n        public static C4us SlateGrey => new C4us(Col.DoubleToUShortClamped(0.439216), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.564706));\n        public static C4us Snow => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.980392), Col.DoubleToUShortClamped(0.980392));\n        public static C4us SpringGreen => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.498039));\n        public static C4us SteelBlue => new C4us(Col.DoubleToUShortClamped(0.27451), Col.DoubleToUShortClamped(0.509804), Col.DoubleToUShortClamped(0.705882));\n        public static C4us Tan => new C4us(Col.DoubleToUShortClamped(0.823529), Col.DoubleToUShortClamped(0.705882), Col.DoubleToUShortClamped(0.54902));\n        public static C4us Teal => new C4us(Col.DoubleToUShortClamped(0), Col.DoubleToUShortClamped(0.501961), Col.DoubleToUShortClamped(0.501961));\n        public static C4us Thistle => new C4us(Col.DoubleToUShortClamped(0.847059), Col.DoubleToUShortClamped(0.74902), Col.DoubleToUShortClamped(0.847059));\n        public static C4us Tomato => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0.388235), Col.DoubleToUShortClamped(0.278431));\n        public static C4us Turquoise => new C4us(Col.DoubleToUShortClamped(0.25098), Col.DoubleToUShortClamped(0.878431), Col.DoubleToUShortClamped(0.815686));\n        public static C4us Violet => new C4us(Col.DoubleToUShortClamped(0.933333), Col.DoubleToUShortClamped(0.509804), Col.DoubleToUShortClamped(0.933333));\n        public static C4us Wheat => new C4us(Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.870588), Col.DoubleToUShortClamped(0.701961));\n        public static C4us White => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1));\n        public static C4us WhiteSmoke => new C4us(Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.960784), Col.DoubleToUShortClamped(0.960784));\n        public static C4us Yellow => new C4us(Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(1), Col.DoubleToUShortClamped(0));\n        public static C4us YellowGreen => new C4us(Col.DoubleToUShortClamped(0.603922), Col.DoubleToUShortClamped(0.803922), Col.DoubleToUShortClamped(0.196078));\n\n        public static C4us DarkYellow => Olive;\n\n        public static C4us VRVisGreen => new C4us(Col.DoubleToUShortClamped(0.698), Col.DoubleToUShortClamped(0.851), Col.DoubleToUShortClamped(0.008));\n\n        public static C4us Gray10 => new C4us(Col.DoubleToUShortClamped(0.1));\n        public static C4us Gray20 => new C4us(Col.DoubleToUShortClamped(0.2));\n        public static C4us Gray30 => new C4us(Col.DoubleToUShortClamped(0.3));\n        public static C4us Gray40 => new C4us(Col.DoubleToUShortClamped(0.4));\n        public static C4us Gray50 => new C4us(Col.DoubleToUShortClamped(0.5));\n        public static C4us Gray60 => new C4us(Col.DoubleToUShortClamped(0.6));\n        public static C4us Gray70 => new C4us(Col.DoubleToUShortClamped(0.7));\n        public static C4us Gray80 => new C4us(Col.DoubleToUShortClamped(0.8));\n        public static C4us Gray90 => new C4us(Col.DoubleToUShortClamped(0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C4us a, C4us b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C4us a, C4us b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator *(C4us col, float scalar)\n        {\n            return new C4us(\n                Col.FloatToUShortClamped(Col.UShortToFloat(col.R) * scalar), \n                Col.FloatToUShortClamped(Col.UShortToFloat(col.G) * scalar), \n                Col.FloatToUShortClamped(Col.UShortToFloat(col.B) * scalar), \n                Col.FloatToUShortClamped(Col.UShortToFloat(col.A) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator *(float scalar, C4us col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator /(C4us col, float scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator /(float scalar, C4us col)\n        {\n            return new C4us(\n                Col.FloatToUShortClamped(scalar / Col.UShortToFloat(col.R)), \n                Col.FloatToUShortClamped(scalar / Col.UShortToFloat(col.G)), \n                Col.FloatToUShortClamped(scalar / Col.UShortToFloat(col.B)), \n                Col.FloatToUShortClamped(scalar / Col.UShortToFloat(col.A)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator *(C4us col, double scalar)\n        {\n            return new C4us(\n                Col.DoubleToUShortClamped(Col.UShortToDouble(col.R) * scalar), \n                Col.DoubleToUShortClamped(Col.UShortToDouble(col.G) * scalar), \n                Col.DoubleToUShortClamped(Col.UShortToDouble(col.B) * scalar), \n                Col.DoubleToUShortClamped(Col.UShortToDouble(col.A) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator *(double scalar, C4us col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator /(C4us col, double scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator /(double scalar, C4us col)\n        {\n            return new C4us(\n                Col.DoubleToUShortClamped(scalar / Col.UShortToDouble(col.R)), \n                Col.DoubleToUShortClamped(scalar / Col.UShortToDouble(col.G)), \n                Col.DoubleToUShortClamped(scalar / Col.UShortToDouble(col.B)), \n                Col.DoubleToUShortClamped(scalar / Col.UShortToDouble(col.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator +(C4us c0, C4b c1)\n        {\n            return new C4us(\n                (ushort)(c0.R + Col.ByteToUShort(c1.R)), \n                (ushort)(c0.G + Col.ByteToUShort(c1.G)), \n                (ushort)(c0.B + Col.ByteToUShort(c1.B)), \n                (ushort)(c0.A + Col.ByteToUShort(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator -(C4us c0, C4b c1)\n        {\n            return new C4us(\n                (ushort)(c0.R - Col.ByteToUShort(c1.R)), \n                (ushort)(c0.G - Col.ByteToUShort(c1.G)), \n                (ushort)(c0.B - Col.ByteToUShort(c1.B)), \n                (ushort)(c0.A - Col.ByteToUShort(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator +(C4us c0, C4ui c1)\n        {\n            return new C4us(\n                (ushort)(c0.R + Col.UIntToUShort(c1.R)), \n                (ushort)(c0.G + Col.UIntToUShort(c1.G)), \n                (ushort)(c0.B + Col.UIntToUShort(c1.B)), \n                (ushort)(c0.A + Col.UIntToUShort(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator -(C4us c0, C4ui c1)\n        {\n            return new C4us(\n                (ushort)(c0.R - Col.UIntToUShort(c1.R)), \n                (ushort)(c0.G - Col.UIntToUShort(c1.G)), \n                (ushort)(c0.B - Col.UIntToUShort(c1.B)), \n                (ushort)(c0.A - Col.UIntToUShort(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator +(C4us c0, C4f c1)\n        {\n            return new C4us(\n                (ushort)(c0.R + Col.FloatToUShort(c1.R)), \n                (ushort)(c0.G + Col.FloatToUShort(c1.G)), \n                (ushort)(c0.B + Col.FloatToUShort(c1.B)), \n                (ushort)(c0.A + Col.FloatToUShort(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator -(C4us c0, C4f c1)\n        {\n            return new C4us(\n                (ushort)(c0.R - Col.FloatToUShort(c1.R)), \n                (ushort)(c0.G - Col.FloatToUShort(c1.G)), \n                (ushort)(c0.B - Col.FloatToUShort(c1.B)), \n                (ushort)(c0.A - Col.FloatToUShort(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator +(C4us c0, C4d c1)\n        {\n            return new C4us(\n                (ushort)(c0.R + Col.DoubleToUShort(c1.R)), \n                (ushort)(c0.G + Col.DoubleToUShort(c1.G)), \n                (ushort)(c0.B + Col.DoubleToUShort(c1.B)), \n                (ushort)(c0.A + Col.DoubleToUShort(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator -(C4us c0, C4d c1)\n        {\n            return new C4us(\n                (ushort)(c0.R - Col.DoubleToUShort(c1.R)), \n                (ushort)(c0.G - Col.DoubleToUShort(c1.G)), \n                (ushort)(c0.B - Col.DoubleToUShort(c1.B)), \n                (ushort)(c0.A - Col.DoubleToUShort(c1.A)));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator *(C4us col, ushort scalar)\n        {\n            return new C4us((ushort)(col.R * scalar), (ushort)(col.G * scalar), (ushort)(col.B * scalar), (ushort)(col.A * scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator *(ushort scalar, C4us col)\n        {\n            return new C4us((ushort)(scalar * col.R), (ushort)(scalar * col.G), (ushort)(scalar * col.B), (ushort)(scalar * col.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator /(C4us col, ushort scalar)\n        {\n            return new C4us((ushort)(col.R / scalar), (ushort)(col.G / scalar), (ushort)(col.B / scalar), (ushort)(col.A / scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator /(ushort scalar, C4us col)\n        {\n            return new C4us((ushort)(scalar / col.R), (ushort)(scalar / col.G), (ushort)(scalar / col.B), (ushort)(scalar / col.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator *(C4us c0, C4us c1)\n        {\n            return new C4us((ushort)(c0.R * c1.R), (ushort)(c0.G * c1.G), (ushort)(c0.B * c1.B), (ushort)(c0.A * c1.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator /(C4us c0, C4us c1)\n        {\n            return new C4us((ushort)(c0.R / c1.R), (ushort)(c0.G / c1.G), (ushort)(c0.B / c1.B), (ushort)(c0.A / c1.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator +(C4us c0, C4us c1)\n        {\n            return new C4us(\n                (65535 - c0.R > c1.R) ? c0.R + c1.R : 65535, \n                (65535 - c0.G > c1.G) ? c0.G + c1.G : 65535, \n                (65535 - c0.B > c1.B) ? c0.B + c1.B : 65535, \n                (65535 - c0.A > c1.A) ? c0.A + c1.A : 65535\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator +(C4us col, ushort scalar)\n        {\n            return new C4us(\n                (65535 - col.R > scalar) ? col.R + scalar : 65535, \n                (65535 - col.G > scalar) ? col.G + scalar : 65535, \n                (65535 - col.B > scalar) ? col.B + scalar : 65535, \n                (65535 - col.A > scalar) ? col.A + scalar : 65535\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator +(ushort scalar, C4us col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator -(C4us c0, C4us c1)\n        {\n            return new C4us(\n                (c0.R > c1.R) ? c0.R - c1.R : 0, \n                (c0.G > c1.G) ? c0.G - c1.G : 0, \n                (c0.B > c1.B) ? c0.B - c1.B : 0, \n                (c0.A > c1.A) ? c0.A - c1.A : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator -(C4us col, ushort scalar)\n        {\n            return new C4us(\n                (col.R > scalar) ? col.R - scalar : 0, \n                (col.G > scalar) ? col.G - scalar : 0, \n                (col.B > scalar) ? col.B - scalar : 0, \n                (col.A > scalar) ? col.A - scalar : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us operator -(ushort scalar, C4us col)\n        {\n            return new C4us(\n                (scalar > col.R) ? scalar - col.R : 0, \n                (scalar > col.G) ? scalar - col.G : 0, \n                (scalar > col.B) ? scalar - col.B : 0, \n                (scalar > col.A) ? scalar - col.A : 0\n            );\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(ushort min, ushort max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us Clamped(ushort min, ushort max)\n        {\n            return new C4us(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max), A);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. The alpha channel is ignored.\n        /// </summary>\n        public readonly int Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return R + G + B; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). The alpha channel is ignored.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly ushort NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(R, G, B); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly ushort NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(R, G, B); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C4us o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B, A);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + A.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C4us, int, ushort> Setter =\n            (ref C4us color, int i, ushort value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    case 3: color.A = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us LinearInterp(float t, C4us a, C4us b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us LinearInterp(V4f t, C4us a, C4us b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us LinearInterp(double t, C4us a, C4us b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us LinearInterp(V4d t, C4us a, C4us b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us DivideByInt(C4us c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4us.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C4us result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC4us();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                ushort[] values = new ushort[4] { 65535, 65535, 65535, 65535 };\n\n                ushort parse(Text t)\n                {\n                    if (!ushort.TryParse(t.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out ushort value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C4us(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4us.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C4us result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4us color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<ushort>.Parse, C4us.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4us color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us Parse(Text t)\n            => TryParse(t, out C4us result) ? result : throw new FormatException($\"{t} is not a valid C4us color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + between + A.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C4us> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C4us other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return Col.UShortToDouble(R); }\n            set { R = Col.DoubleToUShortClamped(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return Col.UShortToDouble(G); }\n            set { G = Col.DoubleToUShortClamped(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return Col.UShortToDouble(B); }\n            set { B = Col.DoubleToUShortClamped(value); }\n        }\n\n        #endregion\n\n        #region IOpacity Members\n\n        [XmlIgnore]\n        public double Opacity\n        {\n            readonly get { return Col.UShortToDouble(A); }\n            set { A = Col.DoubleToUShortClamped(value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4us Lerp(this float t, C4us a, C4us b)\n            => new C4us(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B), Lerp(t, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4us Lerp(this V4f t, C4us a, C4us b)\n            => new C4us(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B), Lerp(t.W, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4us Lerp(this double t, C4us a, C4us b)\n            => new C4us(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B), Lerp(t, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4us Lerp(this V4d t, C4us a, C4us b)\n            => new C4us(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B), Lerp(t.W, a.A, b.A));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C4us a, C4us b, ushort tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance) && ApproximateEquals(a.A, b.A, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4us\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C4us c, ushort epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBBAA.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C4us c)\n            => c.ToC4b().ToHexString();\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4us a, C4us b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B && a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4us col, ushort s)\n        {\n            return (col.R < s && col.G < s && col.B < s && col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(ushort s, C4us col)\n        {\n            return (s < col.R && s < col.G && s < col.B && s < col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4us a, C4us b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B || a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4us col, ushort s)\n        {\n            return (col.R < s || col.G < s || col.B < s || col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(ushort s, C4us col)\n        {\n            return (s < col.R || s < col.G || s < col.B || s < col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4us a, C4us b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B && a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4us col, ushort s)\n        {\n            return (col.R > s && col.G > s && col.B > s && col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(ushort s, C4us col)\n        {\n            return (s > col.R && s > col.G && s > col.B && s > col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4us a, C4us b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B || a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4us col, ushort s)\n        {\n            return (col.R > s || col.G > s || col.B > s || col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(ushort s, C4us col)\n        {\n            return (s > col.R || s > col.G || s > col.B || s > col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4us a, C4us b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B && a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4us col, ushort s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s && col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(ushort s, C4us col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B && s <= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4us a, C4us b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B || a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4us col, ushort s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s || col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(ushort s, C4us col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B || s <= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4us a, C4us b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B && a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4us col, ushort s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s && col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(ushort s, C4us col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B && s >= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4us a, C4us b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B || a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4us col, ushort s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s || col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(ushort s, C4us col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B || s >= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4us a, C4us b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4us col, ushort s)\n        {\n            return (col.R == s && col.G == s && col.B == s && col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(ushort s, C4us col)\n        {\n            return (s == col.R && s == col.G && s == col.B && s == col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4us a, C4us b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B || a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4us col, ushort s)\n        {\n            return (col.R == s || col.G == s || col.B == s || col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(ushort s, C4us col)\n        {\n            return (s == col.R || s == col.G || s == col.B || s == col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4us a, C4us b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B && a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4us col, ushort s)\n        {\n            return (col.R != s && col.G != s && col.B != s && col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(ushort s, C4us col)\n        {\n            return (s != col.R && s != col.G && s != col.B && s != col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4us a, C4us b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4us col, ushort s)\n        {\n            return (col.R != s || col.G != s || col.B != s || col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(ushort s, C4us col)\n        {\n            return (s != col.R || s != col.G || s != col.B || s != col.A);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us LinCom(\n            C4us p0, C4us p1, C4us p2, C4us p3, ref Tup4<float> w)\n        {\n            return new C4us(\n                Col.UShortInFloatToUShortClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.UShortInFloatToUShortClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.UShortInFloatToUShortClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinComRawF(\n            C4us p0, C4us p1, C4us p2, C4us p3, ref Tup4<float> w)\n        {\n            return new C4f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us LinCom(\n            C4us p0, C4us p1, C4us p2, C4us p3, ref Tup4<double> w)\n        {\n            return new C4us(\n                Col.UShortInDoubleToUShortClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.UShortInDoubleToUShortClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.UShortInDoubleToUShortClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinComRawD(\n            C4us p0, C4us p1, C4us p2, C4us p3, ref Tup4<double> w)\n        {\n            return new C4d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us LinCom(\n            C4us p0, C4us p1, C4us p2, C4us p3, C4us p4, C4us p5, ref Tup6<float> w)\n        {\n            return new C4us(\n                Col.UShortInFloatToUShortClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.UShortInFloatToUShortClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.UShortInFloatToUShortClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinComRawF(\n            C4us p0, C4us p1, C4us p2, C4us p3, C4us p4, C4us p5, ref Tup6<float> w)\n        {\n            return new C4f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4us LinCom(\n            C4us p0, C4us p1, C4us p2, C4us p3, C4us p4, C4us p5, ref Tup6<double> w)\n        {\n            return new C4us(\n                Col.UShortInDoubleToUShortClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.UShortInDoubleToUShortClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.UShortInDoubleToUShortClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinComRawD(\n            C4us p0, C4us p1, C4us p2, C4us p3, C4us p4, C4us p5, ref Tup6<double> w)\n        {\n            return new C4d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C4us\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C4us c, ushort epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon) || c.A.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4us\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C4us c, ushort epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon) && c.A.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C4ui\n\n    /// <summary>\n    /// Represents an RGBA color with each channel stored as a <see cref=\"uint\"/> value within [0, 2^32 - 1].\n    /// </summary>\n    [Serializable]\n    public partial struct C4ui : IFormattable, IEquatable<C4ui>, IRGB, IOpacity\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"uint\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(uint r, uint g, uint b, uint a)\n        {\n            R = r; G = g; B = b; A = a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> values.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(int r, int g, int b, int a)\n        {\n            R = (uint)r; G = (uint)g; B = (uint)b; A = (uint)a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> values.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(long r, long g, long b, long a)\n        {\n            R = (uint)r; G = (uint)g; B = (uint)b; A = (uint)a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(float r, float g, float b, float a)\n        {\n            R = Col.FloatToUIntClamped(r);\n            G = Col.FloatToUIntClamped(g);\n            B = Col.FloatToUIntClamped(b);\n            A = Col.FloatToUIntClamped(a);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(double r, double g, double b, double a)\n        {\n            R = Col.DoubleToUIntClamped(r);\n            G = Col.DoubleToUIntClamped(g);\n            B = Col.DoubleToUIntClamped(b);\n            A = Col.DoubleToUIntClamped(a);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"uint\"/> RGB values.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(uint r, uint g, uint b)\n        {\n            R = r; G = g; B = b;\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> RGB values.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(int r, int g, int b)\n        {\n            R = (uint)r; G = (uint)g; B = (uint)b;\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> RGB values.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(long r, long g, long b)\n        {\n            R = (uint)r; G = (uint)g; B = (uint)b;\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> RGB values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(float r, float g, float b)\n        {\n            \n            R = Col.FloatToUIntClamped(r); \n            G = Col.FloatToUIntClamped(g); \n            B = Col.FloatToUIntClamped(b);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> RGB values.\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(double r, double g, double b)\n        {\n            R = Col.DoubleToUIntClamped(r); G = Col.DoubleToUIntClamped(g); B = Col.DoubleToUIntClamped(b);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"uint\"/> value.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(uint gray)\n        {\n            R = gray; G = gray; B = gray; A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(float gray)\n        {\n            var value = Col.FloatToUIntClamped(gray);\n            R = value; G = value; B = value; A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(double gray)\n        {\n            var value = Col.DoubleToUIntClamped(gray);\n            R = value; G = value; B = value; A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3b color)\n        {\n            R = Col.ByteToUInt(color.R);\n            G = Col.ByteToUInt(color.G);\n            B = Col.ByteToUInt(color.B);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3b color, uint alpha)\n        {\n            R = Col.ByteToUInt(color.R);\n            G = Col.ByteToUInt(color.G);\n            B = Col.ByteToUInt(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3us color)\n        {\n            R = Col.UShortToUInt(color.R);\n            G = Col.UShortToUInt(color.G);\n            B = Col.UShortToUInt(color.B);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3us color, uint alpha)\n        {\n            R = Col.UShortToUInt(color.R);\n            G = Col.UShortToUInt(color.G);\n            B = Col.UShortToUInt(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3ui color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3ui color, uint alpha)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3f color)\n        {\n            R = Col.FloatToUIntClamped(color.R);\n            G = Col.FloatToUIntClamped(color.G);\n            B = Col.FloatToUIntClamped(color.B);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color and an alpha value.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3f color, uint alpha)\n        {\n            R = Col.FloatToUIntClamped(color.R);\n            G = Col.FloatToUIntClamped(color.G);\n            B = Col.FloatToUIntClamped(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3d color)\n        {\n            R = Col.DoubleToUIntClamped(color.R);\n            G = Col.DoubleToUIntClamped(color.G);\n            B = Col.DoubleToUIntClamped(color.B);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color and an alpha value.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C3d color, uint alpha)\n        {\n            R = Col.DoubleToUIntClamped(color.R);\n            G = Col.DoubleToUIntClamped(color.G);\n            B = Col.DoubleToUIntClamped(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C4b color)\n        {\n            R = Col.ByteToUInt(color.R);\n            G = Col.ByteToUInt(color.G);\n            B = Col.ByteToUInt(color.B);\n            A = Col.ByteToUInt(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C4us color)\n        {\n            R = Col.UShortToUInt(color.R);\n            G = Col.UShortToUInt(color.G);\n            B = Col.UShortToUInt(color.B);\n            A = Col.UShortToUInt(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C4ui color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = (color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C4f color)\n        {\n            R = Col.FloatToUIntClamped(color.R);\n            G = Col.FloatToUIntClamped(color.G);\n            B = Col.FloatToUIntClamped(color.B);\n            A = Col.FloatToUIntClamped(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(C4d color)\n        {\n            R = Col.DoubleToUIntClamped(color.R);\n            G = Col.DoubleToUIntClamped(color.G);\n            B = Col.DoubleToUIntClamped(color.B);\n            A = Col.DoubleToUIntClamped(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V3ui vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V3l vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V3f vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V3d vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V4ui vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = (vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V4l vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = (uint)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V4f vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = (uint)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V4d vec)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = (uint)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3ui\"/> vector and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V3ui vec, uint alpha)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3l\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V3l vec, uint alpha)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V3f vec, uint alpha)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector and an alpha value.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(V3d vec, uint alpha)\n        {\n            R = (uint)(vec.X);\n            G = (uint)(vec.Y);\n            B = (uint)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(Func<int, uint> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n            A = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(byte[] values)\n        {\n            R = Col.ByteToUInt(values[0]);\n            G = Col.ByteToUInt(values[1]);\n            B = Col.ByteToUInt(values[2]);\n            A = Col.ByteToUInt(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(byte[] values, int start)\n        {\n            R = Col.ByteToUInt(values[start + 0]);\n            G = Col.ByteToUInt(values[start + 1]);\n            B = Col.ByteToUInt(values[start + 2]);\n            A = Col.ByteToUInt(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(ushort[] values)\n        {\n            R = Col.UShortToUInt(values[0]);\n            G = Col.UShortToUInt(values[1]);\n            B = Col.UShortToUInt(values[2]);\n            A = Col.UShortToUInt(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(ushort[] values, int start)\n        {\n            R = Col.UShortToUInt(values[start + 0]);\n            G = Col.UShortToUInt(values[start + 1]);\n            B = Col.UShortToUInt(values[start + 2]);\n            A = Col.UShortToUInt(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(uint[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n            A = (values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(uint[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n            A = (values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(float[] values)\n        {\n            R = Col.FloatToUIntClamped(values[0]);\n            G = Col.FloatToUIntClamped(values[1]);\n            B = Col.FloatToUIntClamped(values[2]);\n            A = Col.FloatToUIntClamped(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(float[] values, int start)\n        {\n            R = Col.FloatToUIntClamped(values[start + 0]);\n            G = Col.FloatToUIntClamped(values[start + 1]);\n            B = Col.FloatToUIntClamped(values[start + 2]);\n            A = Col.FloatToUIntClamped(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(double[] values)\n        {\n            R = Col.DoubleToUIntClamped(values[0]);\n            G = Col.DoubleToUIntClamped(values[1]);\n            B = Col.DoubleToUIntClamped(values[2]);\n            A = Col.DoubleToUIntClamped(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4ui(double[] values, int start)\n        {\n            R = Col.DoubleToUIntClamped(values[start + 0]);\n            G = Col.DoubleToUIntClamped(values[start + 1]);\n            B = Col.DoubleToUIntClamped(values[start + 2]);\n            A = Col.DoubleToUIntClamped(values[start + 3]);\n        }\n\n        #endregion\n\n        #region Properities\n\n        public readonly C3ui RGB => (C3ui)this;\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C3b color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC3b(C3b c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C3us color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC3us(C3us c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C3ui color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC3ui(C3ui c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C3f color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3f\"/> color.\n        /// The values are mapped to the <see cref=\"C3f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C3f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC3f(C3f c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C3d color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C3d\"/> color.\n        /// The values are mapped to the <see cref=\"C3d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C3d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC3d(C3d c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C4b color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC4b(C4b c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C4us color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC4us(C4us c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C4f color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC4f(C4f c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(C4d color)\n            => new C4ui(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromC4d(C4d c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(V3ui v)\n            => new C4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from a <see cref=\"V3ui\"/> vector.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromV3ui(V3ui c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(V3l v)\n            => new C4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromV3l(V3l c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(V3f v)\n            => new C4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromV3f(V3f c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(V3d v)\n            => new C4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromV3d(V3d c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(V4ui v)\n            => new C4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from a <see cref=\"V4ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromV4ui(V4ui c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(V4l v)\n            => new C4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromV4l(V4l c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(V4f v)\n            => new C4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromV4f(V4f c) => new C4ui(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(V4d v)\n            => new C4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4ui\"/> color from a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui FromV4d(V4d c) => new C4ui(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(byte[] values)\n            => new C4ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C4ui color)\n            => new byte[] { Col.UIntToByte(color.R), Col.UIntToByte(color.G), Col.UIntToByte(color.B), Col.UIntToByte(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(ushort[] values)\n            => new C4ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C4ui color)\n            => new ushort[] { Col.UIntToUShort(color.R), Col.UIntToUShort(color.G), Col.UIntToUShort(color.B), Col.UIntToUShort(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(uint[] values)\n            => new C4ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C4ui color)\n            => new uint[] { (color.R), (color.G), (color.B), (color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(float[] values)\n            => new C4ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C4ui color)\n            => new float[] { Col.UIntToFloat(color.R), Col.UIntToFloat(color.G), Col.UIntToFloat(color.B), Col.UIntToFloat(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// The values are mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4ui(double[] values)\n            => new C4ui(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C4ui color)\n            => new double[] { Col.UIntToDouble(color.R), Col.UIntToDouble(color.G), Col.UIntToDouble(color.B), Col.UIntToDouble(color.A) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b Map(Func<uint, byte> channel_fun)\n        {\n            return new C4b(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us Map(Func<uint, ushort> channel_fun)\n        {\n            return new C4us(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui Map(Func<uint, uint> channel_fun)\n        {\n            return new C4ui(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f Map(Func<uint, float> channel_fun)\n        {\n            return new C4f(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d Map(Func<uint, double> channel_fun)\n        {\n            return new C4d(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n            array[start + 3] = element_fun(A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n            array[start + 3] = element_index_fun(A, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly uint[] ToArray()\n            => (uint[])this;\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe uint this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (uint* ptr = &R) { ptr[i] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (uint* ptr = &R) { return ptr[i]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C4ui with all components zero.\n        /// </summary>\n        public static C4ui Zero => new C4ui(0, 0, 0, 0);\n\n        // Web colors\n        public static C4ui AliceBlue => new C4ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.972549), Col.DoubleToUIntClamped(1));\n        public static C4ui AntiqueWhite => new C4ui(Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.921569), Col.DoubleToUIntClamped(0.843137));\n        public static C4ui Aqua => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C4ui Aquamarine => new C4ui(Col.DoubleToUIntClamped(0.498039), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.831373));\n        public static C4ui Azure => new C4ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C4ui Beige => new C4ui(Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.862745));\n        public static C4ui Bisque => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.894118), Col.DoubleToUIntClamped(0.768627));\n        public static C4ui Black => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0));\n        public static C4ui BlanchedAlmond => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.921569), Col.DoubleToUIntClamped(0.803922));\n        public static C4ui Blue => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1));\n        public static C4ui BlueViolet => new C4ui(Col.DoubleToUIntClamped(0.541176), Col.DoubleToUIntClamped(0.168627), Col.DoubleToUIntClamped(0.886275));\n        public static C4ui Brown => new C4ui(Col.DoubleToUIntClamped(0.647059), Col.DoubleToUIntClamped(0.164706), Col.DoubleToUIntClamped(0.164706));\n        public static C4ui BurlyWood => new C4ui(Col.DoubleToUIntClamped(0.870588), Col.DoubleToUIntClamped(0.721569), Col.DoubleToUIntClamped(0.529412));\n        public static C4ui CadetBlue => new C4ui(Col.DoubleToUIntClamped(0.372549), Col.DoubleToUIntClamped(0.619608), Col.DoubleToUIntClamped(0.627451));\n        public static C4ui Chartreuse => new C4ui(Col.DoubleToUIntClamped(0.498039), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0));\n        public static C4ui Chocolate => new C4ui(Col.DoubleToUIntClamped(0.823529), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.117647));\n        public static C4ui Coral => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.498039), Col.DoubleToUIntClamped(0.313725));\n        public static C4ui CornflowerBlue => new C4ui(Col.DoubleToUIntClamped(0.392157), Col.DoubleToUIntClamped(0.584314), Col.DoubleToUIntClamped(0.929412));\n        public static C4ui Cornsilk => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.972549), Col.DoubleToUIntClamped(0.862745));\n        public static C4ui Crimson => new C4ui(Col.DoubleToUIntClamped(0.862745), Col.DoubleToUIntClamped(0.078431), Col.DoubleToUIntClamped(0.235294));\n        public static C4ui Cyan => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C4ui DarkBlue => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.545098));\n        public static C4ui DarkCyan => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0.545098));\n        public static C4ui DarkGoldenRod => new C4ui(Col.DoubleToUIntClamped(0.721569), Col.DoubleToUIntClamped(0.52549), Col.DoubleToUIntClamped(0.043137));\n        public static C4ui DarkGray => new C4ui(Col.DoubleToUIntClamped(0.662745), Col.DoubleToUIntClamped(0.662745), Col.DoubleToUIntClamped(0.662745));\n        public static C4ui DarkGrey => new C4ui(Col.DoubleToUIntClamped(0.662745), Col.DoubleToUIntClamped(0.662745), Col.DoubleToUIntClamped(0.662745));\n        public static C4ui DarkGreen => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.392157), Col.DoubleToUIntClamped(0));\n        public static C4ui DarkKhaki => new C4ui(Col.DoubleToUIntClamped(0.741176), Col.DoubleToUIntClamped(0.717647), Col.DoubleToUIntClamped(0.419608));\n        public static C4ui DarkMagenta => new C4ui(Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.545098));\n        public static C4ui DarkOliveGreen => new C4ui(Col.DoubleToUIntClamped(0.333333), Col.DoubleToUIntClamped(0.419608), Col.DoubleToUIntClamped(0.184314));\n        public static C4ui DarkOrange => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.54902), Col.DoubleToUIntClamped(0));\n        public static C4ui DarkOrchid => new C4ui(Col.DoubleToUIntClamped(0.6), Col.DoubleToUIntClamped(0.196078), Col.DoubleToUIntClamped(0.8));\n        public static C4ui DarkRed => new C4ui(Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0));\n        public static C4ui DarkSalmon => new C4ui(Col.DoubleToUIntClamped(0.913725), Col.DoubleToUIntClamped(0.588235), Col.DoubleToUIntClamped(0.478431));\n        public static C4ui DarkSeaGreen => new C4ui(Col.DoubleToUIntClamped(0.560784), Col.DoubleToUIntClamped(0.737255), Col.DoubleToUIntClamped(0.560784));\n        public static C4ui DarkSlateBlue => new C4ui(Col.DoubleToUIntClamped(0.282353), Col.DoubleToUIntClamped(0.239216), Col.DoubleToUIntClamped(0.545098));\n        public static C4ui DarkSlateGray => new C4ui(Col.DoubleToUIntClamped(0.184314), Col.DoubleToUIntClamped(0.309804), Col.DoubleToUIntClamped(0.309804));\n        public static C4ui DarkSlateGrey => new C4ui(Col.DoubleToUIntClamped(0.184314), Col.DoubleToUIntClamped(0.309804), Col.DoubleToUIntClamped(0.309804));\n        public static C4ui DarkTurquoise => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.807843), Col.DoubleToUIntClamped(0.819608));\n        public static C4ui DarkViolet => new C4ui(Col.DoubleToUIntClamped(0.580392), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.827451));\n        public static C4ui DeepPink => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.078431), Col.DoubleToUIntClamped(0.576471));\n        public static C4ui DeepSkyBlue => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.74902), Col.DoubleToUIntClamped(1));\n        public static C4ui DimGray => new C4ui(Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.411765));\n        public static C4ui DimGrey => new C4ui(Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.411765));\n        public static C4ui DodgerBlue => new C4ui(Col.DoubleToUIntClamped(0.117647), Col.DoubleToUIntClamped(0.564706), Col.DoubleToUIntClamped(1));\n        public static C4ui FireBrick => new C4ui(Col.DoubleToUIntClamped(0.698039), Col.DoubleToUIntClamped(0.133333), Col.DoubleToUIntClamped(0.133333));\n        public static C4ui FloralWhite => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.941176));\n        public static C4ui ForestGreen => new C4ui(Col.DoubleToUIntClamped(0.133333), Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0.133333));\n        public static C4ui Fuchsia => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1));\n        public static C4ui Gainsboro => new C4ui(Col.DoubleToUIntClamped(0.862745), Col.DoubleToUIntClamped(0.862745), Col.DoubleToUIntClamped(0.862745));\n        public static C4ui GhostWhite => new C4ui(Col.DoubleToUIntClamped(0.972549), Col.DoubleToUIntClamped(0.972549), Col.DoubleToUIntClamped(1));\n        public static C4ui Gold => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.843137), Col.DoubleToUIntClamped(0));\n        public static C4ui GoldenRod => new C4ui(Col.DoubleToUIntClamped(0.854902), Col.DoubleToUIntClamped(0.647059), Col.DoubleToUIntClamped(0.12549));\n        public static C4ui Gray => new C4ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961));\n        public static C4ui Grey => new C4ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961));\n        public static C4ui Green => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0));\n        public static C4ui GreenYellow => new C4ui(Col.DoubleToUIntClamped(0.678431), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.184314));\n        public static C4ui HoneyDew => new C4ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.941176));\n        public static C4ui HotPink => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.705882));\n        public static C4ui IndianRed  => new C4ui(Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.360784), Col.DoubleToUIntClamped(0.360784));\n        public static C4ui Indigo  => new C4ui(Col.DoubleToUIntClamped(0.294118), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.509804));\n        public static C4ui Ivory => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.941176));\n        public static C4ui Khaki => new C4ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.901961), Col.DoubleToUIntClamped(0.54902));\n        public static C4ui Lavender => new C4ui(Col.DoubleToUIntClamped(0.901961), Col.DoubleToUIntClamped(0.901961), Col.DoubleToUIntClamped(0.980392));\n        public static C4ui LavenderBlush => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.960784));\n        public static C4ui LawnGreen => new C4ui(Col.DoubleToUIntClamped(0.486275), Col.DoubleToUIntClamped(0.988235), Col.DoubleToUIntClamped(0));\n        public static C4ui LemonChiffon => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.803922));\n        public static C4ui LightBlue => new C4ui(Col.DoubleToUIntClamped(0.678431), Col.DoubleToUIntClamped(0.847059), Col.DoubleToUIntClamped(0.901961));\n        public static C4ui LightCoral => new C4ui(Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961));\n        public static C4ui LightCyan => new C4ui(Col.DoubleToUIntClamped(0.878431), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C4ui LightGoldenRodYellow => new C4ui(Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.823529));\n        public static C4ui LightGray => new C4ui(Col.DoubleToUIntClamped(0.827451), Col.DoubleToUIntClamped(0.827451), Col.DoubleToUIntClamped(0.827451));\n        public static C4ui LightGrey => new C4ui(Col.DoubleToUIntClamped(0.827451), Col.DoubleToUIntClamped(0.827451), Col.DoubleToUIntClamped(0.827451));\n        public static C4ui LightGreen => new C4ui(Col.DoubleToUIntClamped(0.564706), Col.DoubleToUIntClamped(0.933333), Col.DoubleToUIntClamped(0.564706));\n        public static C4ui LightPink => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.713725), Col.DoubleToUIntClamped(0.756863));\n        public static C4ui LightSalmon => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.627451), Col.DoubleToUIntClamped(0.478431));\n        public static C4ui LightSeaGreen => new C4ui(Col.DoubleToUIntClamped(0.12549), Col.DoubleToUIntClamped(0.698039), Col.DoubleToUIntClamped(0.666667));\n        public static C4ui LightSkyBlue => new C4ui(Col.DoubleToUIntClamped(0.529412), Col.DoubleToUIntClamped(0.807843), Col.DoubleToUIntClamped(0.980392));\n        public static C4ui LightSlateGray => new C4ui(Col.DoubleToUIntClamped(0.466667), Col.DoubleToUIntClamped(0.533333), Col.DoubleToUIntClamped(0.6));\n        public static C4ui LightSlateGrey => new C4ui(Col.DoubleToUIntClamped(0.466667), Col.DoubleToUIntClamped(0.533333), Col.DoubleToUIntClamped(0.6));\n        public static C4ui LightSteelBlue => new C4ui(Col.DoubleToUIntClamped(0.690196), Col.DoubleToUIntClamped(0.768627), Col.DoubleToUIntClamped(0.870588));\n        public static C4ui LightYellow => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.878431));\n        public static C4ui Lime => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0));\n        public static C4ui LimeGreen => new C4ui(Col.DoubleToUIntClamped(0.196078), Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.196078));\n        public static C4ui Linen => new C4ui(Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.941176), Col.DoubleToUIntClamped(0.901961));\n        public static C4ui Magenta => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1));\n        public static C4ui Maroon => new C4ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0));\n        public static C4ui MediumAquaMarine => new C4ui(Col.DoubleToUIntClamped(0.4), Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.666667));\n        public static C4ui MediumBlue => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.803922));\n        public static C4ui MediumOrchid => new C4ui(Col.DoubleToUIntClamped(0.729412), Col.DoubleToUIntClamped(0.333333), Col.DoubleToUIntClamped(0.827451));\n        public static C4ui MediumPurple => new C4ui(Col.DoubleToUIntClamped(0.576471), Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.847059));\n        public static C4ui MediumSeaGreen => new C4ui(Col.DoubleToUIntClamped(0.235294), Col.DoubleToUIntClamped(0.701961), Col.DoubleToUIntClamped(0.443137));\n        public static C4ui MediumSlateBlue => new C4ui(Col.DoubleToUIntClamped(0.482353), Col.DoubleToUIntClamped(0.407843), Col.DoubleToUIntClamped(0.933333));\n        public static C4ui MediumSpringGreen => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.603922));\n        public static C4ui MediumTurquoise => new C4ui(Col.DoubleToUIntClamped(0.282353), Col.DoubleToUIntClamped(0.819608), Col.DoubleToUIntClamped(0.8));\n        public static C4ui MediumVioletRed => new C4ui(Col.DoubleToUIntClamped(0.780392), Col.DoubleToUIntClamped(0.082353), Col.DoubleToUIntClamped(0.521569));\n        public static C4ui MidnightBlue => new C4ui(Col.DoubleToUIntClamped(0.098039), Col.DoubleToUIntClamped(0.098039), Col.DoubleToUIntClamped(0.439216));\n        public static C4ui MintCream => new C4ui(Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.980392));\n        public static C4ui MistyRose => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.894118), Col.DoubleToUIntClamped(0.882353));\n        public static C4ui Moccasin => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.894118), Col.DoubleToUIntClamped(0.709804));\n        public static C4ui NavajoWhite => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.870588), Col.DoubleToUIntClamped(0.678431));\n        public static C4ui Navy => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.501961));\n        public static C4ui OldLace => new C4ui(Col.DoubleToUIntClamped(0.992157), Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.901961));\n        public static C4ui Olive => new C4ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0));\n        public static C4ui OliveDrab => new C4ui(Col.DoubleToUIntClamped(0.419608), Col.DoubleToUIntClamped(0.556863), Col.DoubleToUIntClamped(0.137255));\n        public static C4ui Orange => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.647059), Col.DoubleToUIntClamped(0));\n        public static C4ui OrangeRed => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.270588), Col.DoubleToUIntClamped(0));\n        public static C4ui Orchid => new C4ui(Col.DoubleToUIntClamped(0.854902), Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.839216));\n        public static C4ui PaleGoldenRod => new C4ui(Col.DoubleToUIntClamped(0.933333), Col.DoubleToUIntClamped(0.909804), Col.DoubleToUIntClamped(0.666667));\n        public static C4ui PaleGreen => new C4ui(Col.DoubleToUIntClamped(0.596078), Col.DoubleToUIntClamped(0.984314), Col.DoubleToUIntClamped(0.596078));\n        public static C4ui PaleTurquoise => new C4ui(Col.DoubleToUIntClamped(0.686275), Col.DoubleToUIntClamped(0.933333), Col.DoubleToUIntClamped(0.933333));\n        public static C4ui PaleVioletRed => new C4ui(Col.DoubleToUIntClamped(0.847059), Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.576471));\n        public static C4ui PapayaWhip => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.937255), Col.DoubleToUIntClamped(0.835294));\n        public static C4ui PeachPuff => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.854902), Col.DoubleToUIntClamped(0.72549));\n        public static C4ui Peru => new C4ui(Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.521569), Col.DoubleToUIntClamped(0.247059));\n        public static C4ui Pink => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.752941), Col.DoubleToUIntClamped(0.796078));\n        public static C4ui Plum => new C4ui(Col.DoubleToUIntClamped(0.866667), Col.DoubleToUIntClamped(0.627451), Col.DoubleToUIntClamped(0.866667));\n        public static C4ui PowderBlue => new C4ui(Col.DoubleToUIntClamped(0.690196), Col.DoubleToUIntClamped(0.878431), Col.DoubleToUIntClamped(0.901961));\n        public static C4ui Purple => new C4ui(Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.501961));\n        public static C4ui Red => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0));\n        public static C4ui RosyBrown => new C4ui(Col.DoubleToUIntClamped(0.737255), Col.DoubleToUIntClamped(0.560784), Col.DoubleToUIntClamped(0.560784));\n        public static C4ui RoyalBlue => new C4ui(Col.DoubleToUIntClamped(0.254902), Col.DoubleToUIntClamped(0.411765), Col.DoubleToUIntClamped(0.882353));\n        public static C4ui SaddleBrown => new C4ui(Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0.270588), Col.DoubleToUIntClamped(0.07451));\n        public static C4ui Salmon => new C4ui(Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.447059));\n        public static C4ui SandyBrown => new C4ui(Col.DoubleToUIntClamped(0.956863), Col.DoubleToUIntClamped(0.643137), Col.DoubleToUIntClamped(0.376471));\n        public static C4ui SeaGreen => new C4ui(Col.DoubleToUIntClamped(0.180392), Col.DoubleToUIntClamped(0.545098), Col.DoubleToUIntClamped(0.341176));\n        public static C4ui SeaShell => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.933333));\n        public static C4ui Sienna => new C4ui(Col.DoubleToUIntClamped(0.627451), Col.DoubleToUIntClamped(0.321569), Col.DoubleToUIntClamped(0.176471));\n        public static C4ui Silver => new C4ui(Col.DoubleToUIntClamped(0.752941), Col.DoubleToUIntClamped(0.752941), Col.DoubleToUIntClamped(0.752941));\n        public static C4ui SkyBlue => new C4ui(Col.DoubleToUIntClamped(0.529412), Col.DoubleToUIntClamped(0.807843), Col.DoubleToUIntClamped(0.921569));\n        public static C4ui SlateBlue => new C4ui(Col.DoubleToUIntClamped(0.415686), Col.DoubleToUIntClamped(0.352941), Col.DoubleToUIntClamped(0.803922));\n        public static C4ui SlateGray => new C4ui(Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.564706));\n        public static C4ui SlateGrey => new C4ui(Col.DoubleToUIntClamped(0.439216), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.564706));\n        public static C4ui Snow => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.980392), Col.DoubleToUIntClamped(0.980392));\n        public static C4ui SpringGreen => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.498039));\n        public static C4ui SteelBlue => new C4ui(Col.DoubleToUIntClamped(0.27451), Col.DoubleToUIntClamped(0.509804), Col.DoubleToUIntClamped(0.705882));\n        public static C4ui Tan => new C4ui(Col.DoubleToUIntClamped(0.823529), Col.DoubleToUIntClamped(0.705882), Col.DoubleToUIntClamped(0.54902));\n        public static C4ui Teal => new C4ui(Col.DoubleToUIntClamped(0), Col.DoubleToUIntClamped(0.501961), Col.DoubleToUIntClamped(0.501961));\n        public static C4ui Thistle => new C4ui(Col.DoubleToUIntClamped(0.847059), Col.DoubleToUIntClamped(0.74902), Col.DoubleToUIntClamped(0.847059));\n        public static C4ui Tomato => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0.388235), Col.DoubleToUIntClamped(0.278431));\n        public static C4ui Turquoise => new C4ui(Col.DoubleToUIntClamped(0.25098), Col.DoubleToUIntClamped(0.878431), Col.DoubleToUIntClamped(0.815686));\n        public static C4ui Violet => new C4ui(Col.DoubleToUIntClamped(0.933333), Col.DoubleToUIntClamped(0.509804), Col.DoubleToUIntClamped(0.933333));\n        public static C4ui Wheat => new C4ui(Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.870588), Col.DoubleToUIntClamped(0.701961));\n        public static C4ui White => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1));\n        public static C4ui WhiteSmoke => new C4ui(Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.960784), Col.DoubleToUIntClamped(0.960784));\n        public static C4ui Yellow => new C4ui(Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(1), Col.DoubleToUIntClamped(0));\n        public static C4ui YellowGreen => new C4ui(Col.DoubleToUIntClamped(0.603922), Col.DoubleToUIntClamped(0.803922), Col.DoubleToUIntClamped(0.196078));\n\n        public static C4ui DarkYellow => Olive;\n\n        public static C4ui VRVisGreen => new C4ui(Col.DoubleToUIntClamped(0.698), Col.DoubleToUIntClamped(0.851), Col.DoubleToUIntClamped(0.008));\n\n        public static C4ui Gray10 => new C4ui(Col.DoubleToUIntClamped(0.1));\n        public static C4ui Gray20 => new C4ui(Col.DoubleToUIntClamped(0.2));\n        public static C4ui Gray30 => new C4ui(Col.DoubleToUIntClamped(0.3));\n        public static C4ui Gray40 => new C4ui(Col.DoubleToUIntClamped(0.4));\n        public static C4ui Gray50 => new C4ui(Col.DoubleToUIntClamped(0.5));\n        public static C4ui Gray60 => new C4ui(Col.DoubleToUIntClamped(0.6));\n        public static C4ui Gray70 => new C4ui(Col.DoubleToUIntClamped(0.7));\n        public static C4ui Gray80 => new C4ui(Col.DoubleToUIntClamped(0.8));\n        public static C4ui Gray90 => new C4ui(Col.DoubleToUIntClamped(0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C4ui a, C4ui b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C4ui a, C4ui b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator *(C4ui col, float scalar)\n        {\n            return new C4ui(\n                Col.FloatToUIntClamped(Col.UIntToFloat(col.R) * scalar), \n                Col.FloatToUIntClamped(Col.UIntToFloat(col.G) * scalar), \n                Col.FloatToUIntClamped(Col.UIntToFloat(col.B) * scalar), \n                Col.FloatToUIntClamped(Col.UIntToFloat(col.A) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator *(float scalar, C4ui col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator /(C4ui col, float scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator /(float scalar, C4ui col)\n        {\n            return new C4ui(\n                Col.FloatToUIntClamped(scalar / Col.UIntToFloat(col.R)), \n                Col.FloatToUIntClamped(scalar / Col.UIntToFloat(col.G)), \n                Col.FloatToUIntClamped(scalar / Col.UIntToFloat(col.B)), \n                Col.FloatToUIntClamped(scalar / Col.UIntToFloat(col.A)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator *(C4ui col, double scalar)\n        {\n            return new C4ui(\n                Col.DoubleToUIntClamped(Col.UIntToDouble(col.R) * scalar), \n                Col.DoubleToUIntClamped(Col.UIntToDouble(col.G) * scalar), \n                Col.DoubleToUIntClamped(Col.UIntToDouble(col.B) * scalar), \n                Col.DoubleToUIntClamped(Col.UIntToDouble(col.A) * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator *(double scalar, C4ui col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator /(C4ui col, double scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator /(double scalar, C4ui col)\n        {\n            return new C4ui(\n                Col.DoubleToUIntClamped(scalar / Col.UIntToDouble(col.R)), \n                Col.DoubleToUIntClamped(scalar / Col.UIntToDouble(col.G)), \n                Col.DoubleToUIntClamped(scalar / Col.UIntToDouble(col.B)), \n                Col.DoubleToUIntClamped(scalar / Col.UIntToDouble(col.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator +(C4ui c0, C4b c1)\n        {\n            return new C4ui(\n                (uint)(c0.R + Col.ByteToUInt(c1.R)), \n                (uint)(c0.G + Col.ByteToUInt(c1.G)), \n                (uint)(c0.B + Col.ByteToUInt(c1.B)), \n                (uint)(c0.A + Col.ByteToUInt(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator -(C4ui c0, C4b c1)\n        {\n            return new C4ui(\n                (uint)(c0.R - Col.ByteToUInt(c1.R)), \n                (uint)(c0.G - Col.ByteToUInt(c1.G)), \n                (uint)(c0.B - Col.ByteToUInt(c1.B)), \n                (uint)(c0.A - Col.ByteToUInt(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator +(C4ui c0, C4us c1)\n        {\n            return new C4ui(\n                (uint)(c0.R + Col.UShortToUInt(c1.R)), \n                (uint)(c0.G + Col.UShortToUInt(c1.G)), \n                (uint)(c0.B + Col.UShortToUInt(c1.B)), \n                (uint)(c0.A + Col.UShortToUInt(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator -(C4ui c0, C4us c1)\n        {\n            return new C4ui(\n                (uint)(c0.R - Col.UShortToUInt(c1.R)), \n                (uint)(c0.G - Col.UShortToUInt(c1.G)), \n                (uint)(c0.B - Col.UShortToUInt(c1.B)), \n                (uint)(c0.A - Col.UShortToUInt(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator +(C4ui c0, C4f c1)\n        {\n            return new C4ui(\n                (uint)(c0.R + Col.FloatToUInt(c1.R)), \n                (uint)(c0.G + Col.FloatToUInt(c1.G)), \n                (uint)(c0.B + Col.FloatToUInt(c1.B)), \n                (uint)(c0.A + Col.FloatToUInt(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator -(C4ui c0, C4f c1)\n        {\n            return new C4ui(\n                (uint)(c0.R - Col.FloatToUInt(c1.R)), \n                (uint)(c0.G - Col.FloatToUInt(c1.G)), \n                (uint)(c0.B - Col.FloatToUInt(c1.B)), \n                (uint)(c0.A - Col.FloatToUInt(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator +(C4ui c0, C4d c1)\n        {\n            return new C4ui(\n                (uint)(c0.R + Col.DoubleToUInt(c1.R)), \n                (uint)(c0.G + Col.DoubleToUInt(c1.G)), \n                (uint)(c0.B + Col.DoubleToUInt(c1.B)), \n                (uint)(c0.A + Col.DoubleToUInt(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator -(C4ui c0, C4d c1)\n        {\n            return new C4ui(\n                (uint)(c0.R - Col.DoubleToUInt(c1.R)), \n                (uint)(c0.G - Col.DoubleToUInt(c1.G)), \n                (uint)(c0.B - Col.DoubleToUInt(c1.B)), \n                (uint)(c0.A - Col.DoubleToUInt(c1.A)));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator *(C4ui col, uint scalar)\n        {\n            return new C4ui((uint)(col.R * scalar), (uint)(col.G * scalar), (uint)(col.B * scalar), (uint)(col.A * scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator *(uint scalar, C4ui col)\n        {\n            return new C4ui((uint)(scalar * col.R), (uint)(scalar * col.G), (uint)(scalar * col.B), (uint)(scalar * col.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator /(C4ui col, uint scalar)\n        {\n            return new C4ui((uint)(col.R / scalar), (uint)(col.G / scalar), (uint)(col.B / scalar), (uint)(col.A / scalar));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator /(uint scalar, C4ui col)\n        {\n            return new C4ui((uint)(scalar / col.R), (uint)(scalar / col.G), (uint)(scalar / col.B), (uint)(scalar / col.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator *(C4ui c0, C4ui c1)\n        {\n            return new C4ui((uint)(c0.R * c1.R), (uint)(c0.G * c1.G), (uint)(c0.B * c1.B), (uint)(c0.A * c1.A));\n        }\n\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator /(C4ui c0, C4ui c1)\n        {\n            return new C4ui((uint)(c0.R / c1.R), (uint)(c0.G / c1.G), (uint)(c0.B / c1.B), (uint)(c0.A / c1.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator +(C4ui c0, C4ui c1)\n        {\n            return new C4ui(\n                (UInt32.MaxValue - c0.R > c1.R) ? c0.R + c1.R : UInt32.MaxValue, \n                (UInt32.MaxValue - c0.G > c1.G) ? c0.G + c1.G : UInt32.MaxValue, \n                (UInt32.MaxValue - c0.B > c1.B) ? c0.B + c1.B : UInt32.MaxValue, \n                (UInt32.MaxValue - c0.A > c1.A) ? c0.A + c1.A : UInt32.MaxValue\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator +(C4ui col, uint scalar)\n        {\n            return new C4ui(\n                (UInt32.MaxValue - col.R > scalar) ? col.R + scalar : UInt32.MaxValue, \n                (UInt32.MaxValue - col.G > scalar) ? col.G + scalar : UInt32.MaxValue, \n                (UInt32.MaxValue - col.B > scalar) ? col.B + scalar : UInt32.MaxValue, \n                (UInt32.MaxValue - col.A > scalar) ? col.A + scalar : UInt32.MaxValue\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator +(uint scalar, C4ui col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator -(C4ui c0, C4ui c1)\n        {\n            return new C4ui(\n                (c0.R > c1.R) ? c0.R - c1.R : 0, \n                (c0.G > c1.G) ? c0.G - c1.G : 0, \n                (c0.B > c1.B) ? c0.B - c1.B : 0, \n                (c0.A > c1.A) ? c0.A - c1.A : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator -(C4ui col, uint scalar)\n        {\n            return new C4ui(\n                (col.R > scalar) ? col.R - scalar : 0, \n                (col.G > scalar) ? col.G - scalar : 0, \n                (col.B > scalar) ? col.B - scalar : 0, \n                (col.A > scalar) ? col.A - scalar : 0\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui operator -(uint scalar, C4ui col)\n        {\n            return new C4ui(\n                (scalar > col.R) ? scalar - col.R : 0, \n                (scalar > col.G) ? scalar - col.G : 0, \n                (scalar > col.B) ? scalar - col.B : 0, \n                (scalar > col.A) ? scalar - col.A : 0\n            );\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(uint min, uint max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui Clamped(uint min, uint max)\n        {\n            return new C4ui(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max), A);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. The alpha channel is ignored.\n        /// </summary>\n        public readonly long Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return R + G + B; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). The alpha channel is ignored.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly uint NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(R, G, B); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly uint NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(R, G, B); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C4ui o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B, A);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + A.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C4ui, int, uint> Setter =\n            (ref C4ui color, int i, uint value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    case 3: color.A = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui LinearInterp(float t, C4ui a, C4ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui LinearInterp(V4f t, C4ui a, C4ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui LinearInterp(double t, C4ui a, C4ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui LinearInterp(V4d t, C4ui a, C4ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui DivideByInt(C4ui c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4ui.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C4ui result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC4ui();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                uint[] values = new uint[4] { UInt32.MaxValue, UInt32.MaxValue, UInt32.MaxValue, UInt32.MaxValue };\n\n                uint parse(Text t)\n                {\n                    if (!uint.TryParse(t.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out uint value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C4ui(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4ui.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C4ui result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4ui color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<uint>.Parse, C4ui.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4ui color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui Parse(Text t)\n            => TryParse(t, out C4ui result) ? result : throw new FormatException($\"{t} is not a valid C4ui color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + between + A.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C4ui> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C4ui other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return Col.UIntToDouble(R); }\n            set { R = Col.DoubleToUIntClamped(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return Col.UIntToDouble(G); }\n            set { G = Col.DoubleToUIntClamped(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return Col.UIntToDouble(B); }\n            set { B = Col.DoubleToUIntClamped(value); }\n        }\n\n        #endregion\n\n        #region IOpacity Members\n\n        [XmlIgnore]\n        public double Opacity\n        {\n            readonly get { return Col.UIntToDouble(A); }\n            set { A = Col.DoubleToUIntClamped(value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4ui Lerp(this float t, C4ui a, C4ui b)\n            => new C4ui(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B), Lerp(t, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4ui Lerp(this V4f t, C4ui a, C4ui b)\n            => new C4ui(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B), Lerp(t.W, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4ui Lerp(this double t, C4ui a, C4ui b)\n            => new C4ui(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B), Lerp(t, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4ui Lerp(this V4d t, C4ui a, C4ui b)\n            => new C4ui(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B), Lerp(t.W, a.A, b.A));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C4ui a, C4ui b, uint tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance) && ApproximateEquals(a.A, b.A, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C4ui c, uint epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBBAA.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C4ui c)\n            => c.ToC4b().ToHexString();\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4ui a, C4ui b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B && a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4ui col, uint s)\n        {\n            return (col.R < s && col.G < s && col.B < s && col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(uint s, C4ui col)\n        {\n            return (s < col.R && s < col.G && s < col.B && s < col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4ui a, C4ui b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B || a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4ui col, uint s)\n        {\n            return (col.R < s || col.G < s || col.B < s || col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(uint s, C4ui col)\n        {\n            return (s < col.R || s < col.G || s < col.B || s < col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4ui a, C4ui b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B && a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4ui col, uint s)\n        {\n            return (col.R > s && col.G > s && col.B > s && col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(uint s, C4ui col)\n        {\n            return (s > col.R && s > col.G && s > col.B && s > col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4ui a, C4ui b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B || a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4ui col, uint s)\n        {\n            return (col.R > s || col.G > s || col.B > s || col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(uint s, C4ui col)\n        {\n            return (s > col.R || s > col.G || s > col.B || s > col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4ui a, C4ui b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B && a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4ui col, uint s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s && col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(uint s, C4ui col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B && s <= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4ui a, C4ui b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B || a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4ui col, uint s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s || col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(uint s, C4ui col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B || s <= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4ui a, C4ui b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B && a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4ui col, uint s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s && col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(uint s, C4ui col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B && s >= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4ui a, C4ui b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B || a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4ui col, uint s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s || col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(uint s, C4ui col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B || s >= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4ui a, C4ui b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4ui col, uint s)\n        {\n            return (col.R == s && col.G == s && col.B == s && col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(uint s, C4ui col)\n        {\n            return (s == col.R && s == col.G && s == col.B && s == col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4ui a, C4ui b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B || a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4ui col, uint s)\n        {\n            return (col.R == s || col.G == s || col.B == s || col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(uint s, C4ui col)\n        {\n            return (s == col.R || s == col.G || s == col.B || s == col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4ui a, C4ui b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B && a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4ui col, uint s)\n        {\n            return (col.R != s && col.G != s && col.B != s && col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(uint s, C4ui col)\n        {\n            return (s != col.R && s != col.G && s != col.B && s != col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4ui a, C4ui b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4ui col, uint s)\n        {\n            return (col.R != s || col.G != s || col.B != s || col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(uint s, C4ui col)\n        {\n            return (s != col.R || s != col.G || s != col.B || s != col.A);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui LinCom(\n            C4ui p0, C4ui p1, C4ui p2, C4ui p3, ref Tup4<float> w)\n        {\n            return new C4ui(\n                Col.UIntInDoubleToUIntClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.UIntInDoubleToUIntClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.UIntInDoubleToUIntClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinComRawF(\n            C4ui p0, C4ui p1, C4ui p2, C4ui p3, ref Tup4<float> w)\n        {\n            return new C4f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui LinCom(\n            C4ui p0, C4ui p1, C4ui p2, C4ui p3, ref Tup4<double> w)\n        {\n            return new C4ui(\n                Col.UIntInDoubleToUIntClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                Col.UIntInDoubleToUIntClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                Col.UIntInDoubleToUIntClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinComRawD(\n            C4ui p0, C4ui p1, C4ui p2, C4ui p3, ref Tup4<double> w)\n        {\n            return new C4d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui LinCom(\n            C4ui p0, C4ui p1, C4ui p2, C4ui p3, C4ui p4, C4ui p5, ref Tup6<float> w)\n        {\n            return new C4ui(\n                Col.UIntInDoubleToUIntClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.UIntInDoubleToUIntClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.UIntInDoubleToUIntClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinComRawF(\n            C4ui p0, C4ui p1, C4ui p2, C4ui p3, C4ui p4, C4ui p5, ref Tup6<float> w)\n        {\n            return new C4f(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui LinCom(\n            C4ui p0, C4ui p1, C4ui p2, C4ui p3, C4ui p4, C4ui p5, ref Tup6<double> w)\n        {\n            return new C4ui(\n                Col.UIntInDoubleToUIntClamped(p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                Col.UIntInDoubleToUIntClamped(p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                Col.UIntInDoubleToUIntClamped(p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinComRawD(\n            C4ui p0, C4ui p1, C4ui p2, C4ui p3, C4ui p4, C4ui p5, ref Tup6<double> w)\n        {\n            return new C4d(\n                p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5, \n                p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5, \n                p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C4ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C4ui c, uint epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon) || c.A.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C4ui c, uint epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon) && c.A.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformC4uiExtensions\n    {\n        #region IRandomUniform extensions for C4ui\n\n        /// <summary>\n        /// Uses UniformUInt() to generate the elements of a C4ui color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4ui UniformC4ui(this IRandomUniform rnd)\n        {\n            return new C4ui(rnd.UniformUInt(), rnd.UniformUInt(), rnd.UniformUInt(), rnd.UniformUInt());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C4f\n\n    /// <summary>\n    /// Represents an RGBA color with each channel stored as a <see cref=\"float\"/> value within [0, 1].\n    /// </summary>\n    [Serializable]\n    public partial struct C4f : IFormattable, IEquatable<C4f>, IRGB, IOpacity\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(float r, float g, float b, float a)\n        {\n            R = r; G = g; B = b; A = a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(double r, double g, double b, double a)\n        {\n            R = (float)(r);\n            G = (float)(g);\n            B = (float)(b);\n            A = (float)(a);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> RGB values.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(float r, float g, float b)\n        {\n            R = r; G = g; B = b;\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> RGB values.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(double r, double g, double b)\n        {\n            R = (float)(r); G = (float)(g); B = (float)(b);\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(float gray)\n        {\n            R = gray; G = gray; B = gray; A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(double gray)\n        {\n            var value = (float)(gray);\n            R = value; G = value; B = value; A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3b color)\n        {\n            R = Col.ByteToFloat(color.R);\n            G = Col.ByteToFloat(color.G);\n            B = Col.ByteToFloat(color.B);\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3b color, float alpha)\n        {\n            R = Col.ByteToFloat(color.R);\n            G = Col.ByteToFloat(color.G);\n            B = Col.ByteToFloat(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3us color)\n        {\n            R = Col.UShortToFloat(color.R);\n            G = Col.UShortToFloat(color.G);\n            B = Col.UShortToFloat(color.B);\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3us color, float alpha)\n        {\n            R = Col.UShortToFloat(color.R);\n            G = Col.UShortToFloat(color.G);\n            B = Col.UShortToFloat(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3ui color)\n        {\n            R = Col.UIntToFloat(color.R);\n            G = Col.UIntToFloat(color.G);\n            B = Col.UIntToFloat(color.B);\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3ui color, float alpha)\n        {\n            R = Col.UIntToFloat(color.R);\n            G = Col.UIntToFloat(color.G);\n            B = Col.UIntToFloat(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3f color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3f color, float alpha)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3d color)\n        {\n            R = Col.DoubleToFloat(color.R);\n            G = Col.DoubleToFloat(color.G);\n            B = Col.DoubleToFloat(color.B);\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C3d color, float alpha)\n        {\n            R = Col.DoubleToFloat(color.R);\n            G = Col.DoubleToFloat(color.G);\n            B = Col.DoubleToFloat(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C4b color)\n        {\n            R = Col.ByteToFloat(color.R);\n            G = Col.ByteToFloat(color.G);\n            B = Col.ByteToFloat(color.B);\n            A = Col.ByteToFloat(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C4us color)\n        {\n            R = Col.UShortToFloat(color.R);\n            G = Col.UShortToFloat(color.G);\n            B = Col.UShortToFloat(color.B);\n            A = Col.UShortToFloat(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C4ui color)\n        {\n            R = Col.UIntToFloat(color.R);\n            G = Col.UIntToFloat(color.G);\n            B = Col.UIntToFloat(color.B);\n            A = Col.UIntToFloat(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C4f color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = (color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(C4d color)\n        {\n            R = Col.DoubleToFloat(color.R);\n            G = Col.DoubleToFloat(color.G);\n            B = Col.DoubleToFloat(color.B);\n            A = Col.DoubleToFloat(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(V3f vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(V3d vec)\n        {\n            R = (float)(vec.X);\n            G = (float)(vec.Y);\n            B = (float)(vec.Z);\n            A = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(V4f vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = (vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(V4d vec)\n        {\n            R = (float)(vec.X);\n            G = (float)(vec.Y);\n            B = (float)(vec.Z);\n            A = (float)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(V3f vec, float alpha)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(V3d vec, float alpha)\n        {\n            R = (float)(vec.X);\n            G = (float)(vec.Y);\n            B = (float)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(Func<int, float> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n            A = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(byte[] values)\n        {\n            R = Col.ByteToFloat(values[0]);\n            G = Col.ByteToFloat(values[1]);\n            B = Col.ByteToFloat(values[2]);\n            A = Col.ByteToFloat(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(byte[] values, int start)\n        {\n            R = Col.ByteToFloat(values[start + 0]);\n            G = Col.ByteToFloat(values[start + 1]);\n            B = Col.ByteToFloat(values[start + 2]);\n            A = Col.ByteToFloat(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(ushort[] values)\n        {\n            R = Col.UShortToFloat(values[0]);\n            G = Col.UShortToFloat(values[1]);\n            B = Col.UShortToFloat(values[2]);\n            A = Col.UShortToFloat(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(ushort[] values, int start)\n        {\n            R = Col.UShortToFloat(values[start + 0]);\n            G = Col.UShortToFloat(values[start + 1]);\n            B = Col.UShortToFloat(values[start + 2]);\n            A = Col.UShortToFloat(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(uint[] values)\n        {\n            R = Col.UIntToFloat(values[0]);\n            G = Col.UIntToFloat(values[1]);\n            B = Col.UIntToFloat(values[2]);\n            A = Col.UIntToFloat(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(uint[] values, int start)\n        {\n            R = Col.UIntToFloat(values[start + 0]);\n            G = Col.UIntToFloat(values[start + 1]);\n            B = Col.UIntToFloat(values[start + 2]);\n            A = Col.UIntToFloat(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(float[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n            A = (values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(float[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n            A = (values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(double[] values)\n        {\n            R = Col.DoubleToFloat(values[0]);\n            G = Col.DoubleToFloat(values[1]);\n            B = Col.DoubleToFloat(values[2]);\n            A = Col.DoubleToFloat(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4f(double[] values, int start)\n        {\n            R = Col.DoubleToFloat(values[start + 0]);\n            G = Col.DoubleToFloat(values[start + 1]);\n            B = Col.DoubleToFloat(values[start + 2]);\n            A = Col.DoubleToFloat(values[start + 3]);\n        }\n\n        #endregion\n\n        #region Properities\n\n        public readonly C3f RGB => (C3f)this;\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(R) || float.IsNaN(G) || float.IsNaN(B) || float.IsNaN(A);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(R) && float.IsNaN(G) && float.IsNaN(B) && float.IsNaN(A);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(R) || float.IsInfinity(G) || float.IsInfinity(B) || float.IsInfinity(A);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(R) && float.IsInfinity(G) && float.IsInfinity(B) && float.IsInfinity(A);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(R) || float.IsPositiveInfinity(G) || float.IsPositiveInfinity(B) || float.IsPositiveInfinity(A);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(R) && float.IsPositiveInfinity(G) && float.IsPositiveInfinity(B) && float.IsPositiveInfinity(A);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(R) || float.IsNegativeInfinity(G) || float.IsNegativeInfinity(B) || float.IsNegativeInfinity(A);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(R) && float.IsNegativeInfinity(G) && float.IsNegativeInfinity(B) && float.IsNegativeInfinity(A);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(R) || Fun.IsTiny(G) || Fun.IsTiny(B) || Fun.IsTiny(A);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(R) && Fun.IsTiny(G) && Fun.IsTiny(B) && Fun.IsTiny(A);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the color is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the color are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C3b color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC3b(C3b c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C3us color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC3us(C3us c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C3ui color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC3ui(C3ui c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C3f color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C3f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC3f(C3f c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C3d color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C3d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC3d(C3d c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C4b color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC4b(C4b c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C4us color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC4us(C4us c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C4f\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C4ui color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC4ui(C4ui c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(C4d color)\n            => new C4f(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromC4d(C4d c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(V3f v)\n            => new C4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from a <see cref=\"V3f\"/> vector.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromV3f(V3f c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(V3d v)\n            => new C4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from a <see cref=\"V3d\"/> vector.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromV3d(V3d c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(V4f v)\n            => new C4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from a <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromV4f(V4f c) => new C4f(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(V4d v)\n            => new C4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4f\"/> color from a <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f FromV4d(V4d c) => new C4f(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(byte[] values)\n            => new C4f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C4f color)\n            => new byte[] { Col.FloatToByteClamped(color.R), Col.FloatToByteClamped(color.G), Col.FloatToByteClamped(color.B), Col.FloatToByteClamped(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(ushort[] values)\n            => new C4f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C4f color)\n            => new ushort[] { Col.FloatToUShortClamped(color.R), Col.FloatToUShortClamped(color.G), Col.FloatToUShortClamped(color.B), Col.FloatToUShortClamped(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(uint[] values)\n            => new C4f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C4f\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C4f\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C4f color)\n            => new uint[] { Col.FloatToUIntClamped(color.R), Col.FloatToUIntClamped(color.G), Col.FloatToUIntClamped(color.B), Col.FloatToUIntClamped(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(float[] values)\n            => new C4f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C4f color)\n            => new float[] { (color.R), (color.G), (color.B), (color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4f(double[] values)\n            => new C4f(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C4f color)\n            => new double[] { Col.FloatToDouble(color.R), Col.FloatToDouble(color.G), Col.FloatToDouble(color.B), Col.FloatToDouble(color.A) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b Map(Func<float, byte> channel_fun)\n        {\n            return new C4b(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us Map(Func<float, ushort> channel_fun)\n        {\n            return new C4us(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui Map(Func<float, uint> channel_fun)\n        {\n            return new C4ui(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f Map(Func<float, float> channel_fun)\n        {\n            return new C4f(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d Map(Func<float, double> channel_fun)\n        {\n            return new C4d(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n            array[start + 3] = element_fun(A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n            array[start + 3] = element_index_fun(A, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float[] ToArray()\n            => (float[])this;\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe float this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &R) { ptr[i] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &R) { return ptr[i]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C4f with all components zero.\n        /// </summary>\n        public static C4f Zero => new C4f(0.0f, 0.0f, 0.0f, 0.0f);\n\n        // Web colors\n        public static C4f AliceBlue => new C4f((float)(0.941176), (float)(0.972549), (float)(1));\n        public static C4f AntiqueWhite => new C4f((float)(0.980392), (float)(0.921569), (float)(0.843137));\n        public static C4f Aqua => new C4f((float)(0), (float)(1), (float)(1));\n        public static C4f Aquamarine => new C4f((float)(0.498039), (float)(1), (float)(0.831373));\n        public static C4f Azure => new C4f((float)(0.941176), (float)(1), (float)(1));\n        public static C4f Beige => new C4f((float)(0.960784), (float)(0.960784), (float)(0.862745));\n        public static C4f Bisque => new C4f((float)(1), (float)(0.894118), (float)(0.768627));\n        public static C4f Black => new C4f((float)(0), (float)(0), (float)(0));\n        public static C4f BlanchedAlmond => new C4f((float)(1), (float)(0.921569), (float)(0.803922));\n        public static C4f Blue => new C4f((float)(0), (float)(0), (float)(1));\n        public static C4f BlueViolet => new C4f((float)(0.541176), (float)(0.168627), (float)(0.886275));\n        public static C4f Brown => new C4f((float)(0.647059), (float)(0.164706), (float)(0.164706));\n        public static C4f BurlyWood => new C4f((float)(0.870588), (float)(0.721569), (float)(0.529412));\n        public static C4f CadetBlue => new C4f((float)(0.372549), (float)(0.619608), (float)(0.627451));\n        public static C4f Chartreuse => new C4f((float)(0.498039), (float)(1), (float)(0));\n        public static C4f Chocolate => new C4f((float)(0.823529), (float)(0.411765), (float)(0.117647));\n        public static C4f Coral => new C4f((float)(1), (float)(0.498039), (float)(0.313725));\n        public static C4f CornflowerBlue => new C4f((float)(0.392157), (float)(0.584314), (float)(0.929412));\n        public static C4f Cornsilk => new C4f((float)(1), (float)(0.972549), (float)(0.862745));\n        public static C4f Crimson => new C4f((float)(0.862745), (float)(0.078431), (float)(0.235294));\n        public static C4f Cyan => new C4f((float)(0), (float)(1), (float)(1));\n        public static C4f DarkBlue => new C4f((float)(0), (float)(0), (float)(0.545098));\n        public static C4f DarkCyan => new C4f((float)(0), (float)(0.545098), (float)(0.545098));\n        public static C4f DarkGoldenRod => new C4f((float)(0.721569), (float)(0.52549), (float)(0.043137));\n        public static C4f DarkGray => new C4f((float)(0.662745), (float)(0.662745), (float)(0.662745));\n        public static C4f DarkGrey => new C4f((float)(0.662745), (float)(0.662745), (float)(0.662745));\n        public static C4f DarkGreen => new C4f((float)(0), (float)(0.392157), (float)(0));\n        public static C4f DarkKhaki => new C4f((float)(0.741176), (float)(0.717647), (float)(0.419608));\n        public static C4f DarkMagenta => new C4f((float)(0.545098), (float)(0), (float)(0.545098));\n        public static C4f DarkOliveGreen => new C4f((float)(0.333333), (float)(0.419608), (float)(0.184314));\n        public static C4f DarkOrange => new C4f((float)(1), (float)(0.54902), (float)(0));\n        public static C4f DarkOrchid => new C4f((float)(0.6), (float)(0.196078), (float)(0.8));\n        public static C4f DarkRed => new C4f((float)(0.545098), (float)(0), (float)(0));\n        public static C4f DarkSalmon => new C4f((float)(0.913725), (float)(0.588235), (float)(0.478431));\n        public static C4f DarkSeaGreen => new C4f((float)(0.560784), (float)(0.737255), (float)(0.560784));\n        public static C4f DarkSlateBlue => new C4f((float)(0.282353), (float)(0.239216), (float)(0.545098));\n        public static C4f DarkSlateGray => new C4f((float)(0.184314), (float)(0.309804), (float)(0.309804));\n        public static C4f DarkSlateGrey => new C4f((float)(0.184314), (float)(0.309804), (float)(0.309804));\n        public static C4f DarkTurquoise => new C4f((float)(0), (float)(0.807843), (float)(0.819608));\n        public static C4f DarkViolet => new C4f((float)(0.580392), (float)(0), (float)(0.827451));\n        public static C4f DeepPink => new C4f((float)(1), (float)(0.078431), (float)(0.576471));\n        public static C4f DeepSkyBlue => new C4f((float)(0), (float)(0.74902), (float)(1));\n        public static C4f DimGray => new C4f((float)(0.411765), (float)(0.411765), (float)(0.411765));\n        public static C4f DimGrey => new C4f((float)(0.411765), (float)(0.411765), (float)(0.411765));\n        public static C4f DodgerBlue => new C4f((float)(0.117647), (float)(0.564706), (float)(1));\n        public static C4f FireBrick => new C4f((float)(0.698039), (float)(0.133333), (float)(0.133333));\n        public static C4f FloralWhite => new C4f((float)(1), (float)(0.980392), (float)(0.941176));\n        public static C4f ForestGreen => new C4f((float)(0.133333), (float)(0.545098), (float)(0.133333));\n        public static C4f Fuchsia => new C4f((float)(1), (float)(0), (float)(1));\n        public static C4f Gainsboro => new C4f((float)(0.862745), (float)(0.862745), (float)(0.862745));\n        public static C4f GhostWhite => new C4f((float)(0.972549), (float)(0.972549), (float)(1));\n        public static C4f Gold => new C4f((float)(1), (float)(0.843137), (float)(0));\n        public static C4f GoldenRod => new C4f((float)(0.854902), (float)(0.647059), (float)(0.12549));\n        public static C4f Gray => new C4f((float)(0.501961), (float)(0.501961), (float)(0.501961));\n        public static C4f Grey => new C4f((float)(0.501961), (float)(0.501961), (float)(0.501961));\n        public static C4f Green => new C4f((float)(0), (float)(0.501961), (float)(0));\n        public static C4f GreenYellow => new C4f((float)(0.678431), (float)(1), (float)(0.184314));\n        public static C4f HoneyDew => new C4f((float)(0.941176), (float)(1), (float)(0.941176));\n        public static C4f HotPink => new C4f((float)(1), (float)(0.411765), (float)(0.705882));\n        public static C4f IndianRed  => new C4f((float)(0.803922), (float)(0.360784), (float)(0.360784));\n        public static C4f Indigo  => new C4f((float)(0.294118), (float)(0), (float)(0.509804));\n        public static C4f Ivory => new C4f((float)(1), (float)(1), (float)(0.941176));\n        public static C4f Khaki => new C4f((float)(0.941176), (float)(0.901961), (float)(0.54902));\n        public static C4f Lavender => new C4f((float)(0.901961), (float)(0.901961), (float)(0.980392));\n        public static C4f LavenderBlush => new C4f((float)(1), (float)(0.941176), (float)(0.960784));\n        public static C4f LawnGreen => new C4f((float)(0.486275), (float)(0.988235), (float)(0));\n        public static C4f LemonChiffon => new C4f((float)(1), (float)(0.980392), (float)(0.803922));\n        public static C4f LightBlue => new C4f((float)(0.678431), (float)(0.847059), (float)(0.901961));\n        public static C4f LightCoral => new C4f((float)(0.941176), (float)(0.501961), (float)(0.501961));\n        public static C4f LightCyan => new C4f((float)(0.878431), (float)(1), (float)(1));\n        public static C4f LightGoldenRodYellow => new C4f((float)(0.980392), (float)(0.980392), (float)(0.823529));\n        public static C4f LightGray => new C4f((float)(0.827451), (float)(0.827451), (float)(0.827451));\n        public static C4f LightGrey => new C4f((float)(0.827451), (float)(0.827451), (float)(0.827451));\n        public static C4f LightGreen => new C4f((float)(0.564706), (float)(0.933333), (float)(0.564706));\n        public static C4f LightPink => new C4f((float)(1), (float)(0.713725), (float)(0.756863));\n        public static C4f LightSalmon => new C4f((float)(1), (float)(0.627451), (float)(0.478431));\n        public static C4f LightSeaGreen => new C4f((float)(0.12549), (float)(0.698039), (float)(0.666667));\n        public static C4f LightSkyBlue => new C4f((float)(0.529412), (float)(0.807843), (float)(0.980392));\n        public static C4f LightSlateGray => new C4f((float)(0.466667), (float)(0.533333), (float)(0.6));\n        public static C4f LightSlateGrey => new C4f((float)(0.466667), (float)(0.533333), (float)(0.6));\n        public static C4f LightSteelBlue => new C4f((float)(0.690196), (float)(0.768627), (float)(0.870588));\n        public static C4f LightYellow => new C4f((float)(1), (float)(1), (float)(0.878431));\n        public static C4f Lime => new C4f((float)(0), (float)(1), (float)(0));\n        public static C4f LimeGreen => new C4f((float)(0.196078), (float)(0.803922), (float)(0.196078));\n        public static C4f Linen => new C4f((float)(0.980392), (float)(0.941176), (float)(0.901961));\n        public static C4f Magenta => new C4f((float)(1), (float)(0), (float)(1));\n        public static C4f Maroon => new C4f((float)(0.501961), (float)(0), (float)(0));\n        public static C4f MediumAquaMarine => new C4f((float)(0.4), (float)(0.803922), (float)(0.666667));\n        public static C4f MediumBlue => new C4f((float)(0), (float)(0), (float)(0.803922));\n        public static C4f MediumOrchid => new C4f((float)(0.729412), (float)(0.333333), (float)(0.827451));\n        public static C4f MediumPurple => new C4f((float)(0.576471), (float)(0.439216), (float)(0.847059));\n        public static C4f MediumSeaGreen => new C4f((float)(0.235294), (float)(0.701961), (float)(0.443137));\n        public static C4f MediumSlateBlue => new C4f((float)(0.482353), (float)(0.407843), (float)(0.933333));\n        public static C4f MediumSpringGreen => new C4f((float)(0), (float)(0.980392), (float)(0.603922));\n        public static C4f MediumTurquoise => new C4f((float)(0.282353), (float)(0.819608), (float)(0.8));\n        public static C4f MediumVioletRed => new C4f((float)(0.780392), (float)(0.082353), (float)(0.521569));\n        public static C4f MidnightBlue => new C4f((float)(0.098039), (float)(0.098039), (float)(0.439216));\n        public static C4f MintCream => new C4f((float)(0.960784), (float)(1), (float)(0.980392));\n        public static C4f MistyRose => new C4f((float)(1), (float)(0.894118), (float)(0.882353));\n        public static C4f Moccasin => new C4f((float)(1), (float)(0.894118), (float)(0.709804));\n        public static C4f NavajoWhite => new C4f((float)(1), (float)(0.870588), (float)(0.678431));\n        public static C4f Navy => new C4f((float)(0), (float)(0), (float)(0.501961));\n        public static C4f OldLace => new C4f((float)(0.992157), (float)(0.960784), (float)(0.901961));\n        public static C4f Olive => new C4f((float)(0.501961), (float)(0.501961), (float)(0));\n        public static C4f OliveDrab => new C4f((float)(0.419608), (float)(0.556863), (float)(0.137255));\n        public static C4f Orange => new C4f((float)(1), (float)(0.647059), (float)(0));\n        public static C4f OrangeRed => new C4f((float)(1), (float)(0.270588), (float)(0));\n        public static C4f Orchid => new C4f((float)(0.854902), (float)(0.439216), (float)(0.839216));\n        public static C4f PaleGoldenRod => new C4f((float)(0.933333), (float)(0.909804), (float)(0.666667));\n        public static C4f PaleGreen => new C4f((float)(0.596078), (float)(0.984314), (float)(0.596078));\n        public static C4f PaleTurquoise => new C4f((float)(0.686275), (float)(0.933333), (float)(0.933333));\n        public static C4f PaleVioletRed => new C4f((float)(0.847059), (float)(0.439216), (float)(0.576471));\n        public static C4f PapayaWhip => new C4f((float)(1), (float)(0.937255), (float)(0.835294));\n        public static C4f PeachPuff => new C4f((float)(1), (float)(0.854902), (float)(0.72549));\n        public static C4f Peru => new C4f((float)(0.803922), (float)(0.521569), (float)(0.247059));\n        public static C4f Pink => new C4f((float)(1), (float)(0.752941), (float)(0.796078));\n        public static C4f Plum => new C4f((float)(0.866667), (float)(0.627451), (float)(0.866667));\n        public static C4f PowderBlue => new C4f((float)(0.690196), (float)(0.878431), (float)(0.901961));\n        public static C4f Purple => new C4f((float)(0.501961), (float)(0), (float)(0.501961));\n        public static C4f Red => new C4f((float)(1), (float)(0), (float)(0));\n        public static C4f RosyBrown => new C4f((float)(0.737255), (float)(0.560784), (float)(0.560784));\n        public static C4f RoyalBlue => new C4f((float)(0.254902), (float)(0.411765), (float)(0.882353));\n        public static C4f SaddleBrown => new C4f((float)(0.545098), (float)(0.270588), (float)(0.07451));\n        public static C4f Salmon => new C4f((float)(0.980392), (float)(0.501961), (float)(0.447059));\n        public static C4f SandyBrown => new C4f((float)(0.956863), (float)(0.643137), (float)(0.376471));\n        public static C4f SeaGreen => new C4f((float)(0.180392), (float)(0.545098), (float)(0.341176));\n        public static C4f SeaShell => new C4f((float)(1), (float)(0.960784), (float)(0.933333));\n        public static C4f Sienna => new C4f((float)(0.627451), (float)(0.321569), (float)(0.176471));\n        public static C4f Silver => new C4f((float)(0.752941), (float)(0.752941), (float)(0.752941));\n        public static C4f SkyBlue => new C4f((float)(0.529412), (float)(0.807843), (float)(0.921569));\n        public static C4f SlateBlue => new C4f((float)(0.415686), (float)(0.352941), (float)(0.803922));\n        public static C4f SlateGray => new C4f((float)(0.439216), (float)(0.501961), (float)(0.564706));\n        public static C4f SlateGrey => new C4f((float)(0.439216), (float)(0.501961), (float)(0.564706));\n        public static C4f Snow => new C4f((float)(1), (float)(0.980392), (float)(0.980392));\n        public static C4f SpringGreen => new C4f((float)(0), (float)(1), (float)(0.498039));\n        public static C4f SteelBlue => new C4f((float)(0.27451), (float)(0.509804), (float)(0.705882));\n        public static C4f Tan => new C4f((float)(0.823529), (float)(0.705882), (float)(0.54902));\n        public static C4f Teal => new C4f((float)(0), (float)(0.501961), (float)(0.501961));\n        public static C4f Thistle => new C4f((float)(0.847059), (float)(0.74902), (float)(0.847059));\n        public static C4f Tomato => new C4f((float)(1), (float)(0.388235), (float)(0.278431));\n        public static C4f Turquoise => new C4f((float)(0.25098), (float)(0.878431), (float)(0.815686));\n        public static C4f Violet => new C4f((float)(0.933333), (float)(0.509804), (float)(0.933333));\n        public static C4f Wheat => new C4f((float)(0.960784), (float)(0.870588), (float)(0.701961));\n        public static C4f White => new C4f((float)(1), (float)(1), (float)(1));\n        public static C4f WhiteSmoke => new C4f((float)(0.960784), (float)(0.960784), (float)(0.960784));\n        public static C4f Yellow => new C4f((float)(1), (float)(1), (float)(0));\n        public static C4f YellowGreen => new C4f((float)(0.603922), (float)(0.803922), (float)(0.196078));\n\n        public static C4f DarkYellow => Olive;\n\n        public static C4f VRVisGreen => new C4f((float)(0.698), (float)(0.851), (float)(0.008));\n\n        public static C4f Gray10 => new C4f((float)(0.1));\n        public static C4f Gray20 => new C4f((float)(0.2));\n        public static C4f Gray30 => new C4f((float)(0.3));\n        public static C4f Gray40 => new C4f((float)(0.4));\n        public static C4f Gray50 => new C4f((float)(0.5));\n        public static C4f Gray60 => new C4f((float)(0.6));\n        public static C4f Gray70 => new C4f((float)(0.7));\n        public static C4f Gray80 => new C4f((float)(0.8));\n        public static C4f Gray90 => new C4f((float)(0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C4f a, C4f b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C4f a, C4f b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator +(C4f c0, C4b c1)\n        {\n            return new C4f(\n                (float)(c0.R + Col.ByteToFloat(c1.R)), \n                (float)(c0.G + Col.ByteToFloat(c1.G)), \n                (float)(c0.B + Col.ByteToFloat(c1.B)), \n                (float)(c0.A + Col.ByteToFloat(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator -(C4f c0, C4b c1)\n        {\n            return new C4f(\n                (float)(c0.R - Col.ByteToFloat(c1.R)), \n                (float)(c0.G - Col.ByteToFloat(c1.G)), \n                (float)(c0.B - Col.ByteToFloat(c1.B)), \n                (float)(c0.A - Col.ByteToFloat(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator +(C4f c0, C4us c1)\n        {\n            return new C4f(\n                (float)(c0.R + Col.UShortToFloat(c1.R)), \n                (float)(c0.G + Col.UShortToFloat(c1.G)), \n                (float)(c0.B + Col.UShortToFloat(c1.B)), \n                (float)(c0.A + Col.UShortToFloat(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator -(C4f c0, C4us c1)\n        {\n            return new C4f(\n                (float)(c0.R - Col.UShortToFloat(c1.R)), \n                (float)(c0.G - Col.UShortToFloat(c1.G)), \n                (float)(c0.B - Col.UShortToFloat(c1.B)), \n                (float)(c0.A - Col.UShortToFloat(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator +(C4f c0, C4ui c1)\n        {\n            return new C4f(\n                (float)(c0.R + Col.UIntToFloat(c1.R)), \n                (float)(c0.G + Col.UIntToFloat(c1.G)), \n                (float)(c0.B + Col.UIntToFloat(c1.B)), \n                (float)(c0.A + Col.UIntToFloat(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator -(C4f c0, C4ui c1)\n        {\n            return new C4f(\n                (float)(c0.R - Col.UIntToFloat(c1.R)), \n                (float)(c0.G - Col.UIntToFloat(c1.G)), \n                (float)(c0.B - Col.UIntToFloat(c1.B)), \n                (float)(c0.A - Col.UIntToFloat(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator +(C4f c0, C4d c1)\n        {\n            return new C4f(\n                (float)(c0.R + (float)(c1.R)), \n                (float)(c0.G + (float)(c1.G)), \n                (float)(c0.B + (float)(c1.B)), \n                (float)(c0.A + (float)(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator -(C4f c0, C4d c1)\n        {\n            return new C4f(\n                (float)(c0.R - (float)(c1.R)), \n                (float)(c0.G - (float)(c1.G)), \n                (float)(c0.B - (float)(c1.B)), \n                (float)(c0.A - (float)(c1.A)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator *(C4f col, float scalar)\n        {\n            return new C4f((float)(col.R * scalar), (float)(col.G * scalar), (float)(col.B * scalar), (float)(col.A * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator *(float scalar, C4f col)\n        {\n            return new C4f((float)(scalar * col.R), (float)(scalar * col.G), (float)(scalar * col.B), (float)(scalar * col.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator /(C4f col, float scalar)\n        {\n            return new C4f((float)(col.R / scalar), (float)(col.G / scalar), (float)(col.B / scalar), (float)(col.A / scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator /(float scalar, C4f col)\n        {\n            return new C4f((float)(scalar / col.R), (float)(scalar / col.G), (float)(scalar / col.B), (float)(scalar / col.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator *(C4f c0, C4f c1)\n        {\n            return new C4f((float)(c0.R * c1.R), (float)(c0.G * c1.G), (float)(c0.B * c1.B), (float)(c0.A * c1.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator /(C4f c0, C4f c1)\n        {\n            return new C4f((float)(c0.R / c1.R), (float)(c0.G / c1.G), (float)(c0.B / c1.B), (float)(c0.A / c1.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator +(C4f c0, C4f c1)\n        {\n            return new C4f(c0.R + c1.R, c0.G + c1.G, c0.B + c1.B, c0.A + c1.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator +(C4f col, float scalar)\n        {\n            return new C4f(col.R + scalar, col.G + scalar, col.B + scalar, col.A + scalar);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator +(float scalar, C4f col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator -(C4f c0, C4f c1)\n        {\n            return new C4f(c0.R - c1.R, c0.G - c1.G, c0.B - c1.B, c0.A - c1.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator -(C4f col, float scalar)\n        {\n            return new C4f(col.R - scalar, col.G - scalar, col.B - scalar, col.A - scalar);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f operator -(float scalar, C4f col)\n        {\n            return new C4f(scalar - col.R, scalar - col.G, scalar - col.B, scalar - col.A);\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(float min, float max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f Clamped(float min, float max)\n        {\n            return new C4f(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max), A);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. The alpha channel is ignored.\n        /// </summary>\n        public readonly float Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(R) + Fun.Abs(G) + Fun.Abs(B); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). The alpha channel is ignored.\n        /// </summary>\n        public readonly float Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly float NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(R), Fun.Abs(G), Fun.Abs(B)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly float NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(R), Fun.Abs(G), Fun.Abs(B)); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C4f o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B, A);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + A.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C4f, int, float> Setter =\n            (ref C4f color, int i, float value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    case 3: color.A = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinearInterp(float t, C4f a, C4f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinearInterp(V4f t, C4f a, C4f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f DivideByInt(C4f c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4f.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C4f result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC4f();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                float[] values = new float[4] { 1.0f, 1.0f, 1.0f, 1.0f };\n\n                float parse(Text t)\n                {\n                    if (!float.TryParse(t.ToString(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out float value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C4f(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4f.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C4f result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4f color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<float>.Parse, C4f.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4f color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f Parse(Text t)\n            => TryParse(t, out C4f result) ? result : throw new FormatException($\"{t} is not a valid C4f color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + between + A.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C4f> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C4f other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return (double)(R); }\n            set { R = (float)(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return (double)(G); }\n            set { G = (float)(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return (double)(B); }\n            set { B = (float)(value); }\n        }\n\n        #endregion\n\n        #region IOpacity Members\n\n        [XmlIgnore]\n        public double Opacity\n        {\n            readonly get { return (double)(A); }\n            set { A = (float)(value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4f Lerp(this float t, C4f a, C4f b)\n            => new C4f(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B), Lerp(t, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4f Lerp(this V4f t, C4f a, C4f b)\n            => new C4f(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B), Lerp(t.W, a.A, b.A));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C4f a, C4f b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C4f a, C4f b, float tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance) && ApproximateEquals(a.A, b.A, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C4f c, float epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(C4f c)\n            => c.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"C4f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(C4f c)\n            => c.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C4f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(C4f c)\n            => c.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C4f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(C4f c)\n            => c.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C4f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(C4f c)\n            => c.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"C4f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(C4f c)\n            => c.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBBAA.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C4f c)\n            => c.ToC4b().ToHexString();\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4f a, C4f b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B && a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4f col, float s)\n        {\n            return (col.R < s && col.G < s && col.B < s && col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, C4f col)\n        {\n            return (s < col.R && s < col.G && s < col.B && s < col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4f a, C4f b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B || a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4f col, float s)\n        {\n            return (col.R < s || col.G < s || col.B < s || col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, C4f col)\n        {\n            return (s < col.R || s < col.G || s < col.B || s < col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4f a, C4f b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B && a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4f col, float s)\n        {\n            return (col.R > s && col.G > s && col.B > s && col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, C4f col)\n        {\n            return (s > col.R && s > col.G && s > col.B && s > col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4f a, C4f b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B || a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4f col, float s)\n        {\n            return (col.R > s || col.G > s || col.B > s || col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, C4f col)\n        {\n            return (s > col.R || s > col.G || s > col.B || s > col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4f a, C4f b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B && a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4f col, float s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s && col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, C4f col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B && s <= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4f a, C4f b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B || a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4f col, float s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s || col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, C4f col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B || s <= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4f a, C4f b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B && a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4f col, float s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s && col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, C4f col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B && s >= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4f a, C4f b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B || a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4f col, float s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s || col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, C4f col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B || s >= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4f a, C4f b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4f col, float s)\n        {\n            return (col.R == s && col.G == s && col.B == s && col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, C4f col)\n        {\n            return (s == col.R && s == col.G && s == col.B && s == col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4f a, C4f b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B || a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4f col, float s)\n        {\n            return (col.R == s || col.G == s || col.B == s || col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, C4f col)\n        {\n            return (s == col.R || s == col.G || s == col.B || s == col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4f a, C4f b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B && a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4f col, float s)\n        {\n            return (col.R != s && col.G != s && col.B != s && col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, C4f col)\n        {\n            return (s != col.R && s != col.G && s != col.B && s != col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4f a, C4f b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4f col, float s)\n        {\n            return (col.R != s || col.G != s || col.B != s || col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, C4f col)\n        {\n            return (s != col.R || s != col.G || s != col.B || s != col.A);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinCom(\n            C4f p0, C4f p1, C4f p2, C4f p3, ref Tup4<float> w)\n        {\n            return new C4f(\n                (p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                (p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                (p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f LinCom(\n            C4f p0, C4f p1, C4f p2, C4f p3, C4f p4, C4f p5, ref Tup6<float> w)\n        {\n            return new C4f(\n                (p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                (p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                (p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C4f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C4f c, float epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon) || c.A.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C4f c, float epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon) && c.A.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(C4f c)\n            => c.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(C4f c)\n            => c.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(C4f c)\n            => c.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(C4f c)\n            => c.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(C4f c)\n            => c.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(C4f c)\n            => c.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(C4f c)\n            => c.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(C4f c)\n            => c.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(C4f c)\n            => c.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(C4f c)\n            => c.AllTiny;\n\n        #endregion\n    }\n\n    public static class IRandomUniformC4fExtensions\n    {\n        #region IRandomUniform extensions for C4f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of a C4f color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f UniformC4f(this IRandomUniform rnd)\n        {\n            return new C4f(rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of a C4f color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f UniformC4fClosed(this IRandomUniform rnd)\n        {\n            return new C4f(rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of a C4f color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4f UniformC4fOpen(this IRandomUniform rnd)\n        {\n            return new C4f(rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region C4d\n\n    /// <summary>\n    /// Represents an RGBA color with each channel stored as a <see cref=\"double\"/> value within [0, 1].\n    /// </summary>\n    [Serializable]\n    public partial struct C4d : IFormattable, IEquatable<C4d>, IRGB, IOpacity\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(double r, double g, double b, double a)\n        {\n            R = r; G = g; B = b; A = a;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(float r, float g, float b, float a)\n        {\n            R = (double)(r);\n            G = (double)(g);\n            B = (double)(b);\n            A = (double)(a);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> RGB values.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(double r, double g, double b)\n        {\n            R = r; G = g; B = b;\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> RGB values.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(float r, float g, float b)\n        {\n            \n            R = (double)(r); \n            G = (double)(g); \n            B = (double)(b);\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"double\"/> value.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(double gray)\n        {\n            R = gray; G = gray; B = gray; A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from a single <see cref=\"float\"/> value.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(float gray)\n        {\n            var value = (double)(gray);\n            R = value; G = value; B = value; A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3b color)\n        {\n            R = Col.ByteToDouble(color.R);\n            G = Col.ByteToDouble(color.G);\n            B = Col.ByteToDouble(color.B);\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3b\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3b color, double alpha)\n        {\n            R = Col.ByteToDouble(color.R);\n            G = Col.ByteToDouble(color.G);\n            B = Col.ByteToDouble(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3us color)\n        {\n            R = Col.UShortToDouble(color.R);\n            G = Col.UShortToDouble(color.G);\n            B = Col.UShortToDouble(color.B);\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3us\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3us color, double alpha)\n        {\n            R = Col.UShortToDouble(color.R);\n            G = Col.UShortToDouble(color.G);\n            B = Col.UShortToDouble(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3ui color)\n        {\n            R = Col.UIntToDouble(color.R);\n            G = Col.UIntToDouble(color.G);\n            B = Col.UIntToDouble(color.B);\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3ui\"/> color and an alpha value.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3ui color, double alpha)\n        {\n            R = Col.UIntToDouble(color.R);\n            G = Col.UIntToDouble(color.G);\n            B = Col.UIntToDouble(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3f color)\n        {\n            R = Col.FloatToDouble(color.R);\n            G = Col.FloatToDouble(color.G);\n            B = Col.FloatToDouble(color.B);\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3f\"/> color and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3f color, double alpha)\n        {\n            R = Col.FloatToDouble(color.R);\n            G = Col.FloatToDouble(color.G);\n            B = Col.FloatToDouble(color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3d color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C3d\"/> color and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C3d color, double alpha)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C4b color)\n        {\n            R = Col.ByteToDouble(color.R);\n            G = Col.ByteToDouble(color.G);\n            B = Col.ByteToDouble(color.B);\n            A = Col.ByteToDouble(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C4us color)\n        {\n            R = Col.UShortToDouble(color.R);\n            G = Col.UShortToDouble(color.G);\n            B = Col.UShortToDouble(color.B);\n            A = Col.UShortToDouble(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C4ui color)\n        {\n            R = Col.UIntToDouble(color.R);\n            G = Col.UIntToDouble(color.G);\n            B = Col.UIntToDouble(color.B);\n            A = Col.UIntToDouble(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C4f color)\n        {\n            R = Col.FloatToDouble(color.R);\n            G = Col.FloatToDouble(color.G);\n            B = Col.FloatToDouble(color.B);\n            A = Col.FloatToDouble(color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(C4d color)\n        {\n            R = (color.R);\n            G = (color.G);\n            B = (color.B);\n            A = (color.A);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(V3f vec)\n        {\n            R = (double)(vec.X);\n            G = (double)(vec.Y);\n            B = (double)(vec.Z);\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(V3d vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(V4f vec)\n        {\n            R = (double)(vec.X);\n            G = (double)(vec.Y);\n            B = (double)(vec.Z);\n            A = (double)(vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(V4d vec)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = (vec.W);\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3f\"/> vector and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(V3f vec, double alpha)\n        {\n            R = (double)(vec.X);\n            G = (double)(vec.Y);\n            B = (double)(vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"V3d\"/> vector and an alpha value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(V3d vec, double alpha)\n        {\n            R = (vec.X);\n            G = (vec.Y);\n            B = (vec.Z);\n            A = alpha;\n        }\n\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(Func<int, double> index_fun)\n        {\n            R = index_fun(0);\n            G = index_fun(1);\n            B = index_fun(2);\n            A = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(byte[] values)\n        {\n            R = Col.ByteToDouble(values[0]);\n            G = Col.ByteToDouble(values[1]);\n            B = Col.ByteToDouble(values[2]);\n            A = Col.ByteToDouble(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(byte[] values, int start)\n        {\n            R = Col.ByteToDouble(values[start + 0]);\n            G = Col.ByteToDouble(values[start + 1]);\n            B = Col.ByteToDouble(values[start + 2]);\n            A = Col.ByteToDouble(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(ushort[] values)\n        {\n            R = Col.UShortToDouble(values[0]);\n            G = Col.UShortToDouble(values[1]);\n            B = Col.UShortToDouble(values[2]);\n            A = Col.UShortToDouble(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(ushort[] values, int start)\n        {\n            R = Col.UShortToDouble(values[start + 0]);\n            G = Col.UShortToDouble(values[start + 1]);\n            B = Col.UShortToDouble(values[start + 2]);\n            A = Col.UShortToDouble(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(uint[] values)\n        {\n            R = Col.UIntToDouble(values[0]);\n            G = Col.UIntToDouble(values[1]);\n            B = Col.UIntToDouble(values[2]);\n            A = Col.UIntToDouble(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array, starting at the specified index.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(uint[] values, int start)\n        {\n            R = Col.UIntToDouble(values[start + 0]);\n            G = Col.UIntToDouble(values[start + 1]);\n            B = Col.UIntToDouble(values[start + 2]);\n            A = Col.UIntToDouble(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(float[] values)\n        {\n            R = Col.FloatToDouble(values[0]);\n            G = Col.FloatToDouble(values[1]);\n            B = Col.FloatToDouble(values[2]);\n            A = Col.FloatToDouble(values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(float[] values, int start)\n        {\n            R = Col.FloatToDouble(values[start + 0]);\n            G = Col.FloatToDouble(values[start + 1]);\n            B = Col.FloatToDouble(values[start + 2]);\n            A = Col.FloatToDouble(values[start + 3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(double[] values)\n        {\n            R = (values[0]);\n            G = (values[1]);\n            B = (values[2]);\n            A = (values[3]);\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array, starting at the specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public C4d(double[] values, int start)\n        {\n            R = (values[start + 0]);\n            G = (values[start + 1]);\n            B = (values[start + 2]);\n            A = (values[start + 3]);\n        }\n\n        #endregion\n\n        #region Properities\n\n        public readonly C3d RGB => (C3d)this;\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(R) || double.IsNaN(G) || double.IsNaN(B) || double.IsNaN(A);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(R) && double.IsNaN(G) && double.IsNaN(B) && double.IsNaN(A);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(R) || double.IsInfinity(G) || double.IsInfinity(B) || double.IsInfinity(A);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(R) && double.IsInfinity(G) && double.IsInfinity(B) && double.IsInfinity(A);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(R) || double.IsPositiveInfinity(G) || double.IsPositiveInfinity(B) || double.IsPositiveInfinity(A);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(R) && double.IsPositiveInfinity(G) && double.IsPositiveInfinity(B) && double.IsPositiveInfinity(A);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(R) || double.IsNegativeInfinity(G) || double.IsNegativeInfinity(B) || double.IsNegativeInfinity(A);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(R) && double.IsNegativeInfinity(G) && double.IsNegativeInfinity(B) && double.IsNegativeInfinity(A);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(R) || Fun.IsTiny(G) || Fun.IsTiny(B) || Fun.IsTiny(A);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(R) && Fun.IsTiny(G) && Fun.IsTiny(B) && Fun.IsTiny(A);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the color is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the color are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C3b color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C3b\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC3b(C3b c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C3us color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C3us\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC3us(C3us c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C3ui color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C3ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC3ui(C3ui c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"C4d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C3f color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C3f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC3f(C3f c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"C4d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C3d color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C3d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC3d(C3d c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C4b color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C4b\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C4b\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC4b(C4b c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C4us color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C4us\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C4us\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC4us(C4us c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"C4d\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C4ui color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C4ui\"/> color.\n        /// The values are mapped and clamped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C4ui\"/> color.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC4ui(C4ui c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(C4f color)\n            => new C4d(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromC4f(C4f c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(V3f v)\n            => new C4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from a <see cref=\"V3f\"/> vector.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromV3f(V3f c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(V3d v)\n            => new C4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from a <see cref=\"V3d\"/> vector.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromV3d(V3d c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(V4f v)\n            => new C4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from a <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromV4f(V4f c) => new C4d(c);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(V4d v)\n            => new C4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"C4d\"/> color from a <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d FromV4d(V4d c) => new C4d(c);\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"byte\"/> array.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(byte[] values)\n            => new C4d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"byte\"/> array from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator byte[](C4d color)\n            => new byte[] { Col.DoubleToByteClamped(color.R), Col.DoubleToByteClamped(color.G), Col.DoubleToByteClamped(color.B), Col.DoubleToByteClamped(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"ushort\"/> array.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(ushort[] values)\n            => new C4d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"ushort\"/> array from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator ushort[](C4d color)\n            => new ushort[] { Col.DoubleToUShortClamped(color.R), Col.DoubleToUShortClamped(color.G), Col.DoubleToUShortClamped(color.B), Col.DoubleToUShortClamped(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"uint\"/> array.\n        /// The values are mapped to the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(uint[] values)\n            => new C4d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"uint\"/> array from the given <see cref=\"C4d\"/> color.\n        /// The values are mapped and clamped from the <see cref=\"C4d\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](C4d color)\n            => new uint[] { Col.DoubleToUIntClamped(color.R), Col.DoubleToUIntClamped(color.G), Col.DoubleToUIntClamped(color.B), Col.DoubleToUIntClamped(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"float\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(float[] values)\n            => new C4d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"float\"/> array from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](C4d color)\n            => new float[] { Col.DoubleToFloat(color.R), Col.DoubleToFloat(color.G), Col.DoubleToFloat(color.B), Col.DoubleToFloat(color.A) };\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"double\"/> array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator C4d(double[] values)\n            => new C4d(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"double\"/> array from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](C4d color)\n            => new double[] { (color.R), (color.G), (color.B), (color.A) };\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b Map(Func<double, byte> channel_fun)\n        {\n            return new C4b(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us Map(Func<double, ushort> channel_fun)\n        {\n            return new C4us(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui Map(Func<double, uint> channel_fun)\n        {\n            return new C4ui(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f Map(Func<double, float> channel_fun)\n        {\n            return new C4f(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d Map(Func<double, double> channel_fun)\n        {\n            return new C4d(channel_fun(R), channel_fun(G), channel_fun(B), channel_fun(A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, T> element_fun)\n        {\n            array[start + 0] = element_fun(R);\n            array[start + 1] = element_fun(G);\n            array[start + 2] = element_fun(B);\n            array[start + 3] = element_fun(A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(R, 0);\n            array[start + 1] = element_index_fun(G, 1);\n            array[start + 2] = element_index_fun(B, 2);\n            array[start + 3] = element_index_fun(A, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double[] ToArray()\n            => (double[])this;\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe double this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &R) { ptr[i] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &R) { return ptr[i]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// C4d with all components zero.\n        /// </summary>\n        public static C4d Zero => new C4d(0, 0, 0, 0);\n\n        // Web colors\n        public static C4d AliceBlue => new C4d((0.941176), (0.972549), (1));\n        public static C4d AntiqueWhite => new C4d((0.980392), (0.921569), (0.843137));\n        public static C4d Aqua => new C4d((0), (1), (1));\n        public static C4d Aquamarine => new C4d((0.498039), (1), (0.831373));\n        public static C4d Azure => new C4d((0.941176), (1), (1));\n        public static C4d Beige => new C4d((0.960784), (0.960784), (0.862745));\n        public static C4d Bisque => new C4d((1), (0.894118), (0.768627));\n        public static C4d Black => new C4d((0), (0), (0));\n        public static C4d BlanchedAlmond => new C4d((1), (0.921569), (0.803922));\n        public static C4d Blue => new C4d((0), (0), (1));\n        public static C4d BlueViolet => new C4d((0.541176), (0.168627), (0.886275));\n        public static C4d Brown => new C4d((0.647059), (0.164706), (0.164706));\n        public static C4d BurlyWood => new C4d((0.870588), (0.721569), (0.529412));\n        public static C4d CadetBlue => new C4d((0.372549), (0.619608), (0.627451));\n        public static C4d Chartreuse => new C4d((0.498039), (1), (0));\n        public static C4d Chocolate => new C4d((0.823529), (0.411765), (0.117647));\n        public static C4d Coral => new C4d((1), (0.498039), (0.313725));\n        public static C4d CornflowerBlue => new C4d((0.392157), (0.584314), (0.929412));\n        public static C4d Cornsilk => new C4d((1), (0.972549), (0.862745));\n        public static C4d Crimson => new C4d((0.862745), (0.078431), (0.235294));\n        public static C4d Cyan => new C4d((0), (1), (1));\n        public static C4d DarkBlue => new C4d((0), (0), (0.545098));\n        public static C4d DarkCyan => new C4d((0), (0.545098), (0.545098));\n        public static C4d DarkGoldenRod => new C4d((0.721569), (0.52549), (0.043137));\n        public static C4d DarkGray => new C4d((0.662745), (0.662745), (0.662745));\n        public static C4d DarkGrey => new C4d((0.662745), (0.662745), (0.662745));\n        public static C4d DarkGreen => new C4d((0), (0.392157), (0));\n        public static C4d DarkKhaki => new C4d((0.741176), (0.717647), (0.419608));\n        public static C4d DarkMagenta => new C4d((0.545098), (0), (0.545098));\n        public static C4d DarkOliveGreen => new C4d((0.333333), (0.419608), (0.184314));\n        public static C4d DarkOrange => new C4d((1), (0.54902), (0));\n        public static C4d DarkOrchid => new C4d((0.6), (0.196078), (0.8));\n        public static C4d DarkRed => new C4d((0.545098), (0), (0));\n        public static C4d DarkSalmon => new C4d((0.913725), (0.588235), (0.478431));\n        public static C4d DarkSeaGreen => new C4d((0.560784), (0.737255), (0.560784));\n        public static C4d DarkSlateBlue => new C4d((0.282353), (0.239216), (0.545098));\n        public static C4d DarkSlateGray => new C4d((0.184314), (0.309804), (0.309804));\n        public static C4d DarkSlateGrey => new C4d((0.184314), (0.309804), (0.309804));\n        public static C4d DarkTurquoise => new C4d((0), (0.807843), (0.819608));\n        public static C4d DarkViolet => new C4d((0.580392), (0), (0.827451));\n        public static C4d DeepPink => new C4d((1), (0.078431), (0.576471));\n        public static C4d DeepSkyBlue => new C4d((0), (0.74902), (1));\n        public static C4d DimGray => new C4d((0.411765), (0.411765), (0.411765));\n        public static C4d DimGrey => new C4d((0.411765), (0.411765), (0.411765));\n        public static C4d DodgerBlue => new C4d((0.117647), (0.564706), (1));\n        public static C4d FireBrick => new C4d((0.698039), (0.133333), (0.133333));\n        public static C4d FloralWhite => new C4d((1), (0.980392), (0.941176));\n        public static C4d ForestGreen => new C4d((0.133333), (0.545098), (0.133333));\n        public static C4d Fuchsia => new C4d((1), (0), (1));\n        public static C4d Gainsboro => new C4d((0.862745), (0.862745), (0.862745));\n        public static C4d GhostWhite => new C4d((0.972549), (0.972549), (1));\n        public static C4d Gold => new C4d((1), (0.843137), (0));\n        public static C4d GoldenRod => new C4d((0.854902), (0.647059), (0.12549));\n        public static C4d Gray => new C4d((0.501961), (0.501961), (0.501961));\n        public static C4d Grey => new C4d((0.501961), (0.501961), (0.501961));\n        public static C4d Green => new C4d((0), (0.501961), (0));\n        public static C4d GreenYellow => new C4d((0.678431), (1), (0.184314));\n        public static C4d HoneyDew => new C4d((0.941176), (1), (0.941176));\n        public static C4d HotPink => new C4d((1), (0.411765), (0.705882));\n        public static C4d IndianRed  => new C4d((0.803922), (0.360784), (0.360784));\n        public static C4d Indigo  => new C4d((0.294118), (0), (0.509804));\n        public static C4d Ivory => new C4d((1), (1), (0.941176));\n        public static C4d Khaki => new C4d((0.941176), (0.901961), (0.54902));\n        public static C4d Lavender => new C4d((0.901961), (0.901961), (0.980392));\n        public static C4d LavenderBlush => new C4d((1), (0.941176), (0.960784));\n        public static C4d LawnGreen => new C4d((0.486275), (0.988235), (0));\n        public static C4d LemonChiffon => new C4d((1), (0.980392), (0.803922));\n        public static C4d LightBlue => new C4d((0.678431), (0.847059), (0.901961));\n        public static C4d LightCoral => new C4d((0.941176), (0.501961), (0.501961));\n        public static C4d LightCyan => new C4d((0.878431), (1), (1));\n        public static C4d LightGoldenRodYellow => new C4d((0.980392), (0.980392), (0.823529));\n        public static C4d LightGray => new C4d((0.827451), (0.827451), (0.827451));\n        public static C4d LightGrey => new C4d((0.827451), (0.827451), (0.827451));\n        public static C4d LightGreen => new C4d((0.564706), (0.933333), (0.564706));\n        public static C4d LightPink => new C4d((1), (0.713725), (0.756863));\n        public static C4d LightSalmon => new C4d((1), (0.627451), (0.478431));\n        public static C4d LightSeaGreen => new C4d((0.12549), (0.698039), (0.666667));\n        public static C4d LightSkyBlue => new C4d((0.529412), (0.807843), (0.980392));\n        public static C4d LightSlateGray => new C4d((0.466667), (0.533333), (0.6));\n        public static C4d LightSlateGrey => new C4d((0.466667), (0.533333), (0.6));\n        public static C4d LightSteelBlue => new C4d((0.690196), (0.768627), (0.870588));\n        public static C4d LightYellow => new C4d((1), (1), (0.878431));\n        public static C4d Lime => new C4d((0), (1), (0));\n        public static C4d LimeGreen => new C4d((0.196078), (0.803922), (0.196078));\n        public static C4d Linen => new C4d((0.980392), (0.941176), (0.901961));\n        public static C4d Magenta => new C4d((1), (0), (1));\n        public static C4d Maroon => new C4d((0.501961), (0), (0));\n        public static C4d MediumAquaMarine => new C4d((0.4), (0.803922), (0.666667));\n        public static C4d MediumBlue => new C4d((0), (0), (0.803922));\n        public static C4d MediumOrchid => new C4d((0.729412), (0.333333), (0.827451));\n        public static C4d MediumPurple => new C4d((0.576471), (0.439216), (0.847059));\n        public static C4d MediumSeaGreen => new C4d((0.235294), (0.701961), (0.443137));\n        public static C4d MediumSlateBlue => new C4d((0.482353), (0.407843), (0.933333));\n        public static C4d MediumSpringGreen => new C4d((0), (0.980392), (0.603922));\n        public static C4d MediumTurquoise => new C4d((0.282353), (0.819608), (0.8));\n        public static C4d MediumVioletRed => new C4d((0.780392), (0.082353), (0.521569));\n        public static C4d MidnightBlue => new C4d((0.098039), (0.098039), (0.439216));\n        public static C4d MintCream => new C4d((0.960784), (1), (0.980392));\n        public static C4d MistyRose => new C4d((1), (0.894118), (0.882353));\n        public static C4d Moccasin => new C4d((1), (0.894118), (0.709804));\n        public static C4d NavajoWhite => new C4d((1), (0.870588), (0.678431));\n        public static C4d Navy => new C4d((0), (0), (0.501961));\n        public static C4d OldLace => new C4d((0.992157), (0.960784), (0.901961));\n        public static C4d Olive => new C4d((0.501961), (0.501961), (0));\n        public static C4d OliveDrab => new C4d((0.419608), (0.556863), (0.137255));\n        public static C4d Orange => new C4d((1), (0.647059), (0));\n        public static C4d OrangeRed => new C4d((1), (0.270588), (0));\n        public static C4d Orchid => new C4d((0.854902), (0.439216), (0.839216));\n        public static C4d PaleGoldenRod => new C4d((0.933333), (0.909804), (0.666667));\n        public static C4d PaleGreen => new C4d((0.596078), (0.984314), (0.596078));\n        public static C4d PaleTurquoise => new C4d((0.686275), (0.933333), (0.933333));\n        public static C4d PaleVioletRed => new C4d((0.847059), (0.439216), (0.576471));\n        public static C4d PapayaWhip => new C4d((1), (0.937255), (0.835294));\n        public static C4d PeachPuff => new C4d((1), (0.854902), (0.72549));\n        public static C4d Peru => new C4d((0.803922), (0.521569), (0.247059));\n        public static C4d Pink => new C4d((1), (0.752941), (0.796078));\n        public static C4d Plum => new C4d((0.866667), (0.627451), (0.866667));\n        public static C4d PowderBlue => new C4d((0.690196), (0.878431), (0.901961));\n        public static C4d Purple => new C4d((0.501961), (0), (0.501961));\n        public static C4d Red => new C4d((1), (0), (0));\n        public static C4d RosyBrown => new C4d((0.737255), (0.560784), (0.560784));\n        public static C4d RoyalBlue => new C4d((0.254902), (0.411765), (0.882353));\n        public static C4d SaddleBrown => new C4d((0.545098), (0.270588), (0.07451));\n        public static C4d Salmon => new C4d((0.980392), (0.501961), (0.447059));\n        public static C4d SandyBrown => new C4d((0.956863), (0.643137), (0.376471));\n        public static C4d SeaGreen => new C4d((0.180392), (0.545098), (0.341176));\n        public static C4d SeaShell => new C4d((1), (0.960784), (0.933333));\n        public static C4d Sienna => new C4d((0.627451), (0.321569), (0.176471));\n        public static C4d Silver => new C4d((0.752941), (0.752941), (0.752941));\n        public static C4d SkyBlue => new C4d((0.529412), (0.807843), (0.921569));\n        public static C4d SlateBlue => new C4d((0.415686), (0.352941), (0.803922));\n        public static C4d SlateGray => new C4d((0.439216), (0.501961), (0.564706));\n        public static C4d SlateGrey => new C4d((0.439216), (0.501961), (0.564706));\n        public static C4d Snow => new C4d((1), (0.980392), (0.980392));\n        public static C4d SpringGreen => new C4d((0), (1), (0.498039));\n        public static C4d SteelBlue => new C4d((0.27451), (0.509804), (0.705882));\n        public static C4d Tan => new C4d((0.823529), (0.705882), (0.54902));\n        public static C4d Teal => new C4d((0), (0.501961), (0.501961));\n        public static C4d Thistle => new C4d((0.847059), (0.74902), (0.847059));\n        public static C4d Tomato => new C4d((1), (0.388235), (0.278431));\n        public static C4d Turquoise => new C4d((0.25098), (0.878431), (0.815686));\n        public static C4d Violet => new C4d((0.933333), (0.509804), (0.933333));\n        public static C4d Wheat => new C4d((0.960784), (0.870588), (0.701961));\n        public static C4d White => new C4d((1), (1), (1));\n        public static C4d WhiteSmoke => new C4d((0.960784), (0.960784), (0.960784));\n        public static C4d Yellow => new C4d((1), (1), (0));\n        public static C4d YellowGreen => new C4d((0.603922), (0.803922), (0.196078));\n\n        public static C4d DarkYellow => Olive;\n\n        public static C4d VRVisGreen => new C4d((0.698), (0.851), (0.008));\n\n        public static C4d Gray10 => new C4d((0.1));\n        public static C4d Gray20 => new C4d((0.2));\n        public static C4d Gray30 => new C4d((0.3));\n        public static C4d Gray40 => new C4d((0.4));\n        public static C4d Gray50 => new C4d((0.5));\n        public static C4d Gray60 => new C4d((0.6));\n        public static C4d Gray70 => new C4d((0.7));\n        public static C4d Gray80 => new C4d((0.8));\n        public static C4d Gray90 => new C4d((0.9));\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(C4d a, C4d b)\n        {\n            return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(C4d a, C4d b)\n        {\n            return a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator +(C4d c0, C4b c1)\n        {\n            return new C4d(\n                (double)(c0.R + Col.ByteToDouble(c1.R)), \n                (double)(c0.G + Col.ByteToDouble(c1.G)), \n                (double)(c0.B + Col.ByteToDouble(c1.B)), \n                (double)(c0.A + Col.ByteToDouble(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator -(C4d c0, C4b c1)\n        {\n            return new C4d(\n                (double)(c0.R - Col.ByteToDouble(c1.R)), \n                (double)(c0.G - Col.ByteToDouble(c1.G)), \n                (double)(c0.B - Col.ByteToDouble(c1.B)), \n                (double)(c0.A - Col.ByteToDouble(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator +(C4d c0, C4us c1)\n        {\n            return new C4d(\n                (double)(c0.R + Col.UShortToDouble(c1.R)), \n                (double)(c0.G + Col.UShortToDouble(c1.G)), \n                (double)(c0.B + Col.UShortToDouble(c1.B)), \n                (double)(c0.A + Col.UShortToDouble(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator -(C4d c0, C4us c1)\n        {\n            return new C4d(\n                (double)(c0.R - Col.UShortToDouble(c1.R)), \n                (double)(c0.G - Col.UShortToDouble(c1.G)), \n                (double)(c0.B - Col.UShortToDouble(c1.B)), \n                (double)(c0.A - Col.UShortToDouble(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator +(C4d c0, C4ui c1)\n        {\n            return new C4d(\n                (double)(c0.R + Col.UIntToDouble(c1.R)), \n                (double)(c0.G + Col.UIntToDouble(c1.G)), \n                (double)(c0.B + Col.UIntToDouble(c1.B)), \n                (double)(c0.A + Col.UIntToDouble(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator -(C4d c0, C4ui c1)\n        {\n            return new C4d(\n                (double)(c0.R - Col.UIntToDouble(c1.R)), \n                (double)(c0.G - Col.UIntToDouble(c1.G)), \n                (double)(c0.B - Col.UIntToDouble(c1.B)), \n                (double)(c0.A - Col.UIntToDouble(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator +(C4d c0, C4f c1)\n        {\n            return new C4d(\n                (double)(c0.R + (double)(c1.R)), \n                (double)(c0.G + (double)(c1.G)), \n                (double)(c0.B + (double)(c1.B)), \n                (double)(c0.A + (double)(c1.A)));\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator -(C4d c0, C4f c1)\n        {\n            return new C4d(\n                (double)(c0.R - (double)(c1.R)), \n                (double)(c0.G - (double)(c1.G)), \n                (double)(c0.B - (double)(c1.B)), \n                (double)(c0.A - (double)(c1.A)));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator *(C4d col, double scalar)\n        {\n            return new C4d((double)(col.R * scalar), (double)(col.G * scalar), (double)(col.B * scalar), (double)(col.A * scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator *(double scalar, C4d col)\n        {\n            return new C4d((double)(scalar * col.R), (double)(scalar * col.G), (double)(scalar * col.B), (double)(scalar * col.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator /(C4d col, double scalar)\n        {\n            return new C4d((double)(col.R / scalar), (double)(col.G / scalar), (double)(col.B / scalar), (double)(col.A / scalar));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator /(double scalar, C4d col)\n        {\n            return new C4d((double)(scalar / col.R), (double)(scalar / col.G), (double)(scalar / col.B), (double)(scalar / col.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator *(C4d c0, C4d c1)\n        {\n            return new C4d((double)(c0.R * c1.R), (double)(c0.G * c1.G), (double)(c0.B * c1.B), (double)(c0.A * c1.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator /(C4d c0, C4d c1)\n        {\n            return new C4d((double)(c0.R / c1.R), (double)(c0.G / c1.G), (double)(c0.B / c1.B), (double)(c0.A / c1.A));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator +(C4d c0, C4d c1)\n        {\n            return new C4d(c0.R + c1.R, c0.G + c1.G, c0.B + c1.B, c0.A + c1.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator +(C4d col, double scalar)\n        {\n            return new C4d(col.R + scalar, col.G + scalar, col.B + scalar, col.A + scalar);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator +(double scalar, C4d col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator -(C4d c0, C4d c1)\n        {\n            return new C4d(c0.R - c1.R, c0.G - c1.G, c0.B - c1.B, c0.A - c1.A);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator -(C4d col, double scalar)\n        {\n            return new C4d(col.R - scalar, col.G - scalar, col.B - scalar, col.A - scalar);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d operator -(double scalar, C4d col)\n        {\n            return new C4d(scalar - col.R, scalar - col.G, scalar - col.B, scalar - col.A);\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(double min, double max)\n        {\n            R = R.Clamp(min, max);\n            G = G.Clamp(min, max);\n            B = B.Clamp(min, max);\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d Clamped(double min, double max)\n        {\n            return new C4d(R.Clamp(min, max), G.Clamp(min, max), B.Clamp(min, max), A);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. The alpha channel is ignored.\n        /// </summary>\n        public readonly double Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(R) + Fun.Abs(G) + Fun.Abs(B); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). The alpha channel is ignored.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(R * R + G * G + B * B); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly double NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(R), Fun.Abs(G), Fun.Abs(B)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). The alpha channel is ignored.\n        /// </summary>\n        public readonly double NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(R), Fun.Abs(G), Fun.Abs(B)); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is C4d o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(R, G, B, A);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + R.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + G.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + B.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + A.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<C4d, int, double> Setter =\n            (ref C4d color, int i, double value) =>\n            {\n                switch (i)\n                {\n                    case 0: color.R = value; return;\n                    case 1: color.G = value; return;\n                    case 2: color.B = value; return;\n                    case 3: color.A = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinearInterp(double t, C4d a, C4d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinearInterp(V4d t, C4d a, C4d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d DivideByInt(C4d c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4d.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out C4d result)\n        {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.ToC4d();\n                return true;\n            }\n            else\n            {\n                bool success = true;\n                double[] values = new double[4] { 1.0, 1.0, 1.0, 1.0 };\n\n                double parse(Text t)\n                {\n                    if (!double.TryParse(t.ToString(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out double value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new C4d(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, C4d.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out C4d result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4d color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<double>.Parse, C4d.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid C4d color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d Parse(Text t)\n            => TryParse(t, out C4d result) ? result : throw new FormatException($\"{t} is not a valid C4d color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + R.ToString(format, fp)  + between + G.ToString(format, fp)  + between + B.ToString(format, fp)  + between + A.ToString(format, fp)  + end;\n        }\n\n        #endregion\n\n        #region IEquatable<C4d> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(C4d other)\n        {\n            return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return (R); }\n            set { R = (value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return (G); }\n            set { G = (value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return (B); }\n            set { B = (value); }\n        }\n\n        #endregion\n\n        #region IOpacity Members\n\n        [XmlIgnore]\n        public double Opacity\n        {\n            readonly get { return (A); }\n            set { A = (value); }\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4d Lerp(this double t, C4d a, C4d b)\n            => new C4d(Lerp(t, a.R, b.R), Lerp(t, a.G, b.G), Lerp(t, a.B, b.B), Lerp(t, a.A, b.A));\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static C4d Lerp(this V4d t, C4d a, C4d b)\n            => new C4d(Lerp(t.X, a.R, b.R), Lerp(t.Y, a.G, b.G), Lerp(t.Z, a.B, b.B), Lerp(t.W, a.A, b.A));\n\n        #endregion\n\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C4d a, C4d b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this C4d a, C4d b, double tolerance)\n        {\n            return ApproximateEquals(a.R, b.R, tolerance) && ApproximateEquals(a.G, b.G, tolerance) && ApproximateEquals(a.B, b.B, tolerance) && ApproximateEquals(a.A, b.A, tolerance);\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this C4d c, double epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(C4d c)\n            => c.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"C4d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(C4d c)\n            => c.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C4d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(C4d c)\n            => c.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C4d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(C4d c)\n            => c.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"C4d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(C4d c)\n            => c.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"C4d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(C4d c)\n            => c.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBBAA.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this C4d c)\n            => c.ToC4b().ToHexString();\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4d a, C4d b)\n        {\n            return (a.R < b.R && a.G < b.G && a.B < b.B && a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this C4d col, double s)\n        {\n            return (col.R < s && col.G < s && col.B < s && col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, C4d col)\n        {\n            return (s < col.R && s < col.G && s < col.B && s < col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4d a, C4d b)\n        {\n            return (a.R < b.R || a.G < b.G || a.B < b.B || a.A < b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this C4d col, double s)\n        {\n            return (col.R < s || col.G < s || col.B < s || col.A < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, C4d col)\n        {\n            return (s < col.R || s < col.G || s < col.B || s < col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4d a, C4d b)\n        {\n            return (a.R > b.R && a.G > b.G && a.B > b.B && a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this C4d col, double s)\n        {\n            return (col.R > s && col.G > s && col.B > s && col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, C4d col)\n        {\n            return (s > col.R && s > col.G && s > col.B && s > col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4d a, C4d b)\n        {\n            return (a.R > b.R || a.G > b.G || a.B > b.B || a.A > b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this C4d col, double s)\n        {\n            return (col.R > s || col.G > s || col.B > s || col.A > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, C4d col)\n        {\n            return (s > col.R || s > col.G || s > col.B || s > col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4d a, C4d b)\n        {\n            return (a.R <= b.R && a.G <= b.G && a.B <= b.B && a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this C4d col, double s)\n        {\n            return (col.R <= s && col.G <= s && col.B <= s && col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, C4d col)\n        {\n            return (s <= col.R && s <= col.G && s <= col.B && s <= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4d a, C4d b)\n        {\n            return (a.R <= b.R || a.G <= b.G || a.B <= b.B || a.A <= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this C4d col, double s)\n        {\n            return (col.R <= s || col.G <= s || col.B <= s || col.A <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, C4d col)\n        {\n            return (s <= col.R || s <= col.G || s <= col.B || s <= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4d a, C4d b)\n        {\n            return (a.R >= b.R && a.G >= b.G && a.B >= b.B && a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this C4d col, double s)\n        {\n            return (col.R >= s && col.G >= s && col.B >= s && col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, C4d col)\n        {\n            return (s >= col.R && s >= col.G && s >= col.B && s >= col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4d a, C4d b)\n        {\n            return (a.R >= b.R || a.G >= b.G || a.B >= b.B || a.A >= b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this C4d col, double s)\n        {\n            return (col.R >= s || col.G >= s || col.B >= s || col.A >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, C4d col)\n        {\n            return (s >= col.R || s >= col.G || s >= col.B || s >= col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4d a, C4d b)\n        {\n            return (a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this C4d col, double s)\n        {\n            return (col.R == s && col.G == s && col.B == s && col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, C4d col)\n        {\n            return (s == col.R && s == col.G && s == col.B && s == col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4d a, C4d b)\n        {\n            return (a.R == b.R || a.G == b.G || a.B == b.B || a.A == b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this C4d col, double s)\n        {\n            return (col.R == s || col.G == s || col.B == s || col.A == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, C4d col)\n        {\n            return (s == col.R || s == col.G || s == col.B || s == col.A);\n        }\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4d a, C4d b)\n        {\n            return (a.R != b.R && a.G != b.G && a.B != b.B && a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this C4d col, double s)\n        {\n            return (col.R != s && col.G != s && col.B != s && col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, C4d col)\n        {\n            return (s != col.R && s != col.G && s != col.B && s != col.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4d a, C4d b)\n        {\n            return (a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this C4d col, double s)\n        {\n            return (col.R != s || col.G != s || col.B != s || col.A != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of col.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, C4d col)\n        {\n            return (s != col.R || s != col.G || s != col.B || s != col.A);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinCom(\n            C4d p0, C4d p1, C4d p2, C4d p3, ref Tup4<double> w)\n        {\n            return new C4d(\n                (p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3), \n                (p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3), \n                (p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3));\n        }\n\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d LinCom(\n            C4d p0, C4d p1, C4d p2, C4d p3, C4d p4, C4d p5, ref Tup6<double> w)\n        {\n            return new C4d(\n                (p0.R * w.E0 + p1.R * w.E1 + p2.R * w.E2 + p3.R * w.E3 + p4.R * w.E4 + p5.R * w.E5), \n                (p0.G * w.E0 + p1.G * w.E1 + p2.G * w.E2 + p3.G * w.E3 + p4.G * w.E4 + p5.G * w.E5), \n                (p0.B * w.E0 + p1.B * w.E1 + p2.B * w.E2 + p3.B * w.E3 + p4.B * w.E4 + p5.B * w.E5));\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"C4d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this C4d c, double epsilon)\n            => c.R.IsTiny(epsilon) || c.G.IsTiny(epsilon) || c.B.IsTiny(epsilon) || c.A.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"C4d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this C4d c, double epsilon)\n            => c.R.IsTiny(epsilon) && c.G.IsTiny(epsilon) && c.B.IsTiny(epsilon) && c.A.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(C4d c)\n            => c.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(C4d c)\n            => c.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(C4d c)\n            => c.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(C4d c)\n            => c.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(C4d c)\n            => c.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(C4d c)\n            => c.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(C4d c)\n            => c.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(C4d c)\n            => c.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(C4d c)\n            => c.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(C4d c)\n            => c.AllTiny;\n\n        #endregion\n    }\n\n    public static class IRandomUniformC4dExtensions\n    {\n        #region IRandomUniform extensions for C4d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of a C4d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d UniformC4d(this IRandomUniform rnd)\n        {\n            return new C4d(rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of a C4d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d UniformC4dClosed(this IRandomUniform rnd)\n        {\n            return new C4d(rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of a C4d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d UniformC4dOpen(this IRandomUniform rnd)\n        {\n            return new C4d(rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of a C4d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d UniformC4dFull(this IRandomUniform rnd)\n        {\n            return new C4d(rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of a C4d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d UniformC4dFullClosed(this IRandomUniform rnd)\n        {\n            return new C4d(rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of a C4d color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static C4d UniformC4dFullOpen(this IRandomUniform rnd)\n        {\n            return new C4d(rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Colors/Color_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var ColorNames\n    //#    = new Dictionary<string, V3d>()\n    //#    {\n    //#        { \"AliceBlue\", new V3d(0.941176, 0.972549, 1.000000) },\n    //#        { \"AntiqueWhite\", new V3d(0.980392, 0.921569, 0.843137) },\n    //#        { \"Aqua\", new V3d(0.000000, 1.000000, 1.000000) },\n    //#        { \"Aquamarine\", new V3d(0.498039, 1.000000, 0.831373) },\n    //#        { \"Azure\", new V3d(0.941176, 1.000000, 1.000000) },\n    //#        { \"Beige\", new V3d(0.960784, 0.960784, 0.862745) },\n    //#        { \"Bisque\", new V3d(1.000000, 0.894118, 0.768627) },\n    //#        { \"Black\", new V3d(0.000000, 0.000000, 0.000000) },\n    //#        { \"BlanchedAlmond\", new V3d(1.000000, 0.921569, 0.803922) },\n    //#        { \"Blue\", new V3d(0.000000, 0.000000, 1.000000) },\n    //#        { \"BlueViolet\", new V3d(0.541176, 0.168627, 0.886275) },\n    //#        { \"Brown\", new V3d(0.647059, 0.164706, 0.164706) },\n    //#        { \"BurlyWood\", new V3d(0.870588, 0.721569, 0.529412) },\n    //#        { \"CadetBlue\", new V3d(0.372549, 0.619608, 0.627451) },\n    //#        { \"Chartreuse\", new V3d(0.498039, 1.000000, 0.000000) },\n    //#        { \"Chocolate\", new V3d(0.823529, 0.411765, 0.117647) },\n    //#        { \"Coral\", new V3d(1.000000, 0.498039, 0.313725) },\n    //#        { \"CornflowerBlue\", new V3d(0.392157, 0.584314, 0.929412) },\n    //#        { \"Cornsilk\", new V3d(1.000000, 0.972549, 0.862745) },\n    //#        { \"Crimson\", new V3d(0.862745, 0.078431, 0.235294) },\n    //#        { \"Cyan\", new V3d(0.000000, 1.000000, 1.000000) },\n    //#        { \"DarkBlue\", new V3d(0.000000, 0.000000, 0.545098) },\n    //#        { \"DarkCyan\", new V3d(0.000000, 0.545098, 0.545098) },\n    //#        { \"DarkGoldenRod\", new V3d(0.721569, 0.525490, 0.043137) },\n    //#        { \"DarkGray\", new V3d(0.662745, 0.662745, 0.662745) },\n    //#        { \"DarkGrey\", new V3d(0.662745, 0.662745, 0.662745) },\n    //#        { \"DarkGreen\", new V3d(0.000000, 0.392157, 0.000000) },\n    //#        { \"DarkKhaki\", new V3d(0.741176, 0.717647, 0.419608) },\n    //#        { \"DarkMagenta\", new V3d(0.545098, 0.000000, 0.545098) },\n    //#        { \"DarkOliveGreen\", new V3d(0.333333, 0.419608, 0.184314) },\n    //#        { \"DarkOrange\", new V3d(1.000000, 0.549020, 0.000000) },\n    //#        { \"DarkOrchid\", new V3d(0.600000, 0.196078, 0.800000) },\n    //#        { \"DarkRed\", new V3d(0.545098, 0.000000, 0.000000) },\n    //#        { \"DarkSalmon\", new V3d(0.913725, 0.588235, 0.478431) },\n    //#        { \"DarkSeaGreen\", new V3d(0.560784, 0.737255, 0.560784) },\n    //#        { \"DarkSlateBlue\", new V3d(0.282353, 0.239216, 0.545098) },\n    //#        { \"DarkSlateGray\", new V3d(0.184314, 0.309804, 0.309804) },\n    //#        { \"DarkSlateGrey\", new V3d(0.184314, 0.309804, 0.309804) },\n    //#        { \"DarkTurquoise\", new V3d(0.000000, 0.807843, 0.819608) },\n    //#        { \"DarkViolet\", new V3d(0.580392, 0.000000, 0.827451) },\n    //#        { \"DeepPink\", new V3d(1.000000, 0.078431, 0.576471) },\n    //#        { \"DeepSkyBlue\", new V3d(0.000000, 0.749020, 1.000000) },\n    //#        { \"DimGray\", new V3d(0.411765, 0.411765, 0.411765) },\n    //#        { \"DimGrey\", new V3d(0.411765, 0.411765, 0.411765) },\n    //#        { \"DodgerBlue\", new V3d(0.117647, 0.564706, 1.000000) },\n    //#        { \"FireBrick\", new V3d(0.698039, 0.133333, 0.133333) },\n    //#        { \"FloralWhite\", new V3d(1.000000, 0.980392, 0.941176) },\n    //#        { \"ForestGreen\", new V3d(0.133333, 0.545098, 0.133333) },\n    //#        { \"Fuchsia\", new V3d(1.000000, 0.000000, 1.000000) },\n    //#        { \"Gainsboro\", new V3d(0.862745, 0.862745, 0.862745) },\n    //#        { \"GhostWhite\", new V3d(0.972549, 0.972549, 1.000000) },\n    //#        { \"Gold\", new V3d(1.000000, 0.843137, 0.000000) },\n    //#        { \"GoldenRod\", new V3d(0.854902, 0.647059, 0.125490) },\n    //#        { \"Gray\", new V3d(0.501961, 0.501961, 0.501961) },\n    //#        { \"Grey\", new V3d(0.501961, 0.501961, 0.501961) },\n    //#        { \"Green\", new V3d(0.000000, 0.501961, 0.000000) },\n    //#        { \"GreenYellow\", new V3d(0.678431, 1.000000, 0.184314) },\n    //#        { \"HoneyDew\", new V3d(0.941176, 1.000000, 0.941176) },\n    //#        { \"HotPink\", new V3d(1.000000, 0.411765, 0.705882) },\n    //#        { \"IndianRed \", new V3d(0.803922, 0.360784, 0.360784) },\n    //#        { \"Indigo \", new V3d(0.294118, 0.000000, 0.509804) },\n    //#        { \"Ivory\", new V3d(1.000000, 1.000000, 0.941176) },\n    //#        { \"Khaki\", new V3d(0.941176, 0.901961, 0.549020) },\n    //#        { \"Lavender\", new V3d(0.901961, 0.901961, 0.980392) },\n    //#        { \"LavenderBlush\", new V3d(1.000000, 0.941176, 0.960784) },\n    //#        { \"LawnGreen\", new V3d(0.486275, 0.988235, 0.000000) },\n    //#        { \"LemonChiffon\", new V3d(1.000000, 0.980392, 0.803922) },\n    //#        { \"LightBlue\", new V3d(0.678431, 0.847059, 0.901961) },\n    //#        { \"LightCoral\", new V3d(0.941176, 0.501961, 0.501961) },\n    //#        { \"LightCyan\", new V3d(0.878431, 1.000000, 1.000000) },\n    //#        { \"LightGoldenRodYellow\", new V3d(0.980392, 0.980392, 0.823529) },\n    //#        { \"LightGray\", new V3d(0.827451, 0.827451, 0.827451) },\n    //#        { \"LightGrey\", new V3d(0.827451, 0.827451, 0.827451) },\n    //#        { \"LightGreen\", new V3d(0.564706, 0.933333, 0.564706) },\n    //#        { \"LightPink\", new V3d(1.000000, 0.713725, 0.756863) },\n    //#        { \"LightSalmon\", new V3d(1.000000, 0.627451, 0.478431) },\n    //#        { \"LightSeaGreen\", new V3d(0.125490, 0.698039, 0.666667) },\n    //#        { \"LightSkyBlue\", new V3d(0.529412, 0.807843, 0.980392) },\n    //#        { \"LightSlateGray\", new V3d(0.466667, 0.533333, 0.600000) },\n    //#        { \"LightSlateGrey\", new V3d(0.466667, 0.533333, 0.600000) },\n    //#        { \"LightSteelBlue\", new V3d(0.690196, 0.768627, 0.870588) },\n    //#        { \"LightYellow\", new V3d(1.000000, 1.000000, 0.878431) },\n    //#        { \"Lime\", new V3d(0.000000, 1.000000, 0.000000) },\n    //#        { \"LimeGreen\", new V3d(0.196078, 0.803922, 0.196078) },\n    //#        { \"Linen\", new V3d(0.980392, 0.941176, 0.901961) },\n    //#        { \"Magenta\", new V3d(1.000000, 0.000000, 1.000000) },\n    //#        { \"Maroon\", new V3d(0.501961, 0.000000, 0.000000) },\n    //#        { \"MediumAquaMarine\", new V3d(0.400000, 0.803922, 0.666667) },\n    //#        { \"MediumBlue\", new V3d(0.000000, 0.000000, 0.803922) },\n    //#        { \"MediumOrchid\", new V3d(0.729412, 0.333333, 0.827451) },\n    //#        { \"MediumPurple\", new V3d(0.576471, 0.439216, 0.847059) },\n    //#        { \"MediumSeaGreen\", new V3d(0.235294, 0.701961, 0.443137) },\n    //#        { \"MediumSlateBlue\", new V3d(0.482353, 0.407843, 0.933333) },\n    //#        { \"MediumSpringGreen\", new V3d(0.000000, 0.980392, 0.603922) },\n    //#        { \"MediumTurquoise\", new V3d(0.282353, 0.819608, 0.800000) },\n    //#        { \"MediumVioletRed\", new V3d(0.780392, 0.082353, 0.521569) },\n    //#        { \"MidnightBlue\", new V3d(0.098039, 0.098039, 0.439216) },\n    //#        { \"MintCream\", new V3d(0.960784, 1.000000, 0.980392) },\n    //#        { \"MistyRose\", new V3d(1.000000, 0.894118, 0.882353) },\n    //#        { \"Moccasin\", new V3d(1.000000, 0.894118, 0.709804) },\n    //#        { \"NavajoWhite\", new V3d(1.000000, 0.870588, 0.678431) },\n    //#        { \"Navy\", new V3d(0.000000, 0.000000, 0.501961) },\n    //#        { \"OldLace\", new V3d(0.992157, 0.960784, 0.901961) },\n    //#        { \"Olive\", new V3d(0.501961, 0.501961, 0.000000) },\n    //#        { \"OliveDrab\", new V3d(0.419608, 0.556863, 0.137255) },\n    //#        { \"Orange\", new V3d(1.000000, 0.647059, 0.000000) },\n    //#        { \"OrangeRed\", new V3d(1.000000, 0.270588, 0.000000) },\n    //#        { \"Orchid\", new V3d(0.854902, 0.439216, 0.839216) },\n    //#        { \"PaleGoldenRod\", new V3d(0.933333, 0.909804, 0.666667) },\n    //#        { \"PaleGreen\", new V3d(0.596078, 0.984314, 0.596078) },\n    //#        { \"PaleTurquoise\", new V3d(0.686275, 0.933333, 0.933333) },\n    //#        { \"PaleVioletRed\", new V3d(0.847059, 0.439216, 0.576471) },\n    //#        { \"PapayaWhip\", new V3d(1.000000, 0.937255, 0.835294) },\n    //#        { \"PeachPuff\", new V3d(1.000000, 0.854902, 0.725490) },\n    //#        { \"Peru\", new V3d(0.803922, 0.521569, 0.247059) },\n    //#        { \"Pink\", new V3d(1.000000, 0.752941, 0.796078) },\n    //#        { \"Plum\", new V3d(0.866667, 0.627451, 0.866667) },\n    //#        { \"PowderBlue\", new V3d(0.690196, 0.878431, 0.901961) },\n    //#        { \"Purple\", new V3d(0.501961, 0.000000, 0.501961) },\n    //#        { \"Red\", new V3d(1.000000, 0.000000, 0.000000) },\n    //#        { \"RosyBrown\", new V3d(0.737255, 0.560784, 0.560784) },\n    //#        { \"RoyalBlue\", new V3d(0.254902, 0.411765, 0.882353) },\n    //#        { \"SaddleBrown\", new V3d(0.545098, 0.270588, 0.074510) },\n    //#        { \"Salmon\", new V3d(0.980392, 0.501961, 0.447059) },\n    //#        { \"SandyBrown\", new V3d(0.956863, 0.643137, 0.376471) },\n    //#        { \"SeaGreen\", new V3d(0.180392, 0.545098, 0.341176) },\n    //#        { \"SeaShell\", new V3d(1.000000, 0.960784, 0.933333) },\n    //#        { \"Sienna\", new V3d(0.627451, 0.321569, 0.176471) },\n    //#        { \"Silver\", new V3d(0.752941, 0.752941, 0.752941) },\n    //#        { \"SkyBlue\", new V3d(0.529412, 0.807843, 0.921569) },\n    //#        { \"SlateBlue\", new V3d(0.415686, 0.352941, 0.803922) },\n    //#        { \"SlateGray\", new V3d(0.439216, 0.501961, 0.564706) },\n    //#        { \"SlateGrey\", new V3d(0.439216, 0.501961, 0.564706) },\n    //#        { \"Snow\", new V3d(1.000000, 0.980392, 0.980392) },\n    //#        { \"SpringGreen\", new V3d(0.000000, 1.000000, 0.498039) },\n    //#        { \"SteelBlue\", new V3d(0.274510, 0.509804, 0.705882) },\n    //#        { \"Tan\", new V3d(0.823529, 0.705882, 0.549020) },\n    //#        { \"Teal\", new V3d(0.000000, 0.501961, 0.501961) },\n    //#        { \"Thistle\", new V3d(0.847059, 0.749020, 0.847059) },\n    //#        { \"Tomato\", new V3d(1.000000, 0.388235, 0.278431) },\n    //#        { \"Turquoise\", new V3d(0.250980, 0.878431, 0.815686) },\n    //#        { \"Violet\", new V3d(0.933333, 0.509804, 0.933333) },\n    //#        { \"Wheat\", new V3d(0.960784, 0.870588, 0.701961) },\n    //#        { \"White\", new V3d(1.000000, 1.000000, 1.000000) },\n    //#        { \"WhiteSmoke\", new V3d(0.960784, 0.960784, 0.960784) },\n    //#        { \"Yellow\", new V3d(1.000000, 1.000000, 0.000000) },\n    //#        { \"YellowGreen\", new V3d(0.603922, 0.803922, 0.196078) },\n    //#    };\n    //#\n    //# Action andand = () => Out(\" && \");\n    //# Action add = () => Out(\" + \");\n    //# Action addbetween = () => Out(\" + between \");\n    //# Action addqcommaspace = () => Out(\" + \\\", \\\" \");\n    //# Action comma = () => Out(\", \");\n    //# Action oror = () => Out(\" || \");\n    //# Action semicolon = () => Out(\"; \");\n    //# Action xor = () => Out(\" ^ \");\n    //#\n    //# Func<Meta.SimpleType, Meta.SimpleType, bool> ismapped =\n    //#     (t1, t2) => (t1 != t2) && !(t1.IsReal && t2.IsReal);\n    //# Func<Meta.SimpleType, Meta.SimpleType, bool> isclamped =\n    //#     (t1, t2) => t1.IsReal && !t2.IsReal;\n    //#\n    //# Func<Meta.SimpleType, Meta.SimpleType, bool> coltovecsupported =\n    //#     (cft, vft) => (!cft.IsReal || vft.IsReal) && (cft != Meta.UIntType || vft != Meta.IntType);\n    //#\n    //# var f_to_ft_map = new Dictionary<Meta.SimpleType, string>\n    //#     {\n    //#         { Meta.ByteType,   \"Col.FloatToByteClamped\"   },\n    //#         { Meta.UShortType, \"Col.FloatToUShortClamped\" },\n    //#         { Meta.UIntType,   \"Col.FloatToUIntClamped\"   },\n    //#         { Meta.FloatType,  \"\"                         },\n    //#         { Meta.DoubleType, \"(double)\"                 },\n    //#     };\n    //# var d_to_ft_map = new Dictionary<Meta.SimpleType, string>\n    //#     {\n    //#         { Meta.ByteType,   \"Col.DoubleToByteClamped\"   },\n    //#         { Meta.UShortType, \"Col.DoubleToUShortClamped\" },\n    //#         { Meta.UIntType,   \"Col.DoubleToUIntClamped\"   },\n    //#         { Meta.FloatType,  \"(float)\"                   },\n    //#         { Meta.DoubleType, \"\"                          },\n    //#     };\n    //# var ft_to_f_map = new Dictionary<Meta.SimpleType, string>\n    //#     {\n    //#         { Meta.ByteType,   \"Col.ByteToFloat\"   },\n    //#         { Meta.UShortType, \"Col.UShortToFloat\" },\n    //#         { Meta.UIntType,   \"Col.UIntToFloat\"   },\n    //#         { Meta.FloatType,  \"\"                  },\n    //#         { Meta.DoubleType, \"(float)\"           },\n    //#     };\n    //# var ft_to_d_map = new Dictionary<Meta.SimpleType, string>\n    //#     {\n    //#         { Meta.ByteType,   \"Col.ByteToDouble\"   },\n    //#         { Meta.UShortType, \"Col.UShortToDouble\" },\n    //#         { Meta.UIntType,   \"Col.UIntToDouble\"   },\n    //#         { Meta.FloatType,  \"(double)\"           },\n    //#         { Meta.DoubleType, \"\"                   },\n    //#     };\n    //# var maxvalmap = new Dictionary<Meta.SimpleType, string>\n    //#     {\n    //#         { Meta.ByteType, \"255\" },\n    //#         { Meta.UShortType, \"2^16 - 1\" },\n    //#         { Meta.UIntType, \"2^32 - 1\" },\n    //#         { Meta.FloatType, \"1\" },\n    //#         { Meta.DoubleType, \"1\" },\n    //#     };\n    //# var fdtypes = new[] { Meta.FloatType, Meta.DoubleType };\n    //# foreach (var t in Meta.ColorTypes) {\n    //#     var type = t.Name;\n    //#     var ft = t.FieldType;\n    //#     var ht = (ft != Meta.FloatType) ? Meta.HighPrecisionTypeOf(ft) : ft;\n    //#     var ct = Meta.ComputationTypeOf(ft);\n    //#     var htype = ht.Name;\n    //#     var ctype = ct.Name;\n    //#     var hnd = ht != Meta.DoubleType; // high not double\n    //#     var dblt = Meta.ColorTypeOf(t.Len, Meta.DoubleType);\n    //#     var dbltype = dblt.Name;\n    //#     var fltt = Meta.ColorTypeOf(t.Len, Meta.FloatType);\n    //#     var flttype = fltt.Name;\n    //#     var isByte = ft == Meta.ByteType;\n    //#     var isUShort = ft == Meta.UShortType;\n    //#     var isFloat = ft == Meta.FloatType;\n    //#     var isDouble = ft == Meta.DoubleType;\n    //#     var isReal = ft.IsReal;\n    //#     var ftype = ft.Name;\n    //#     var fcaps = ft.Caps;\n    //#     var fields = t.Fields;\n    //#     var dim = fields.Length;\n    //#     var channels = t.Channels;\n    //#     var args = fields.ToLower();\n    //#     var cargs = channels.ToLower();\n    //#     var f_to_ft = f_to_ft_map[ft];\n    //#     var d_to_ft = d_to_ft_map[ft];\n    //#     var ft_to_f = ft_to_f_map[ft];\n    //#     var ft_to_d = ft_to_d_map[ft];\n    //#     var fabs_p = isReal ? \"Fun.Abs(\" : \"\";\n    //#     var q_fabs = isReal ? \")\" : \"\";\n    //#     var getptr = \"&\" + ((ft == Meta.ByteType) ? fields[2] : fields[0]);\n    //#     var rgba = t.HasAlpha ? \"RGBA\" : \"RGB\";\n    //#     var maxval = maxvalmap[ft];\n    //#     var parseNumberStyle = isReal ? \"NumberStyles.Float | NumberStyles.AllowThousands\" : \"NumberStyles.Integer\";\n    #region __type__\n\n    /// <summary>\n    /// Represents an __rgba__ color with each channel stored as a <see cref=\"__ftype__\"/> value within [0, __maxval__].\n    /// </summary>\n    [Serializable]\n    public partial struct __type__ : IFormattable, IEquatable<__type__>, IRGB/*# if (t.HasAlpha) { */, IOpacity/*# } */\n    {\n        #region Constructors\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"__ftype__\"/> values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# args.ForEach(a => { */__ftype__ __a__/*# }, comma); */)\n        {\n            /*# fields.ForEach(args, (f,a) => { */__f__ = __a__/*# }, semicolon); */;\n        }\n\n        //# if (!isReal) {\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> values.\n        /// The values are not mapped to the <see cref=\"__type__\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# args.ForEach(a => { */int __a__/*# }, comma); */)\n        {\n            /*# fields.ForEach(args, (f,a) => { */__f__ = (__ftype__)__a__/*# }, semicolon); */;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> values.\n        /// The values are not mapped to the <see cref=\"__type__\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# args.ForEach(a => { */long __a__/*# }, comma); */)\n        {\n            /*# fields.ForEach(args, (f,a) => { */__f__ = (__ftype__)__a__/*# }, semicolon); */;\n        }\n\n        //# }\n        //# if (!isFloat) {\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> values.\n        //# if (!isDouble) {\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"__type__\"/> color range.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# args.ForEach(a => { */float __a__/*# }, comma); */)\n        {\n            //# fields.ForEach(args, (f,a) => {\n            __f__ = __f_to_ft__(__a__);\n            //# });\n        }\n\n        //# }\n        //# if (!isDouble) {\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> values.\n        //# if (!isFloat) {\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"__type__\"/> color range.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# args.ForEach(a => { */double __a__/*# }, comma); */)\n        {\n            //# fields.ForEach(args, (f,a) => {\n            __f__ = __d_to_ft__(__a__);\n            //# });\n        }\n\n        //# }\n        //# if (t.HasAlpha) {\n        /// <summary>\n        /// Creates a color from the given <see cref=\"__ftype__\"/> RGB values.\n        /// The alpha channel is set to __maxval__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# cargs.ForEach(a => { */__ftype__ __a__/*# }, comma); */)\n        {\n            /*# channels.ForEach(args,\n                    (c, a) => { */__c__ = __a__/*# }, semicolon); */;\n            A = __t.MaxValue__;\n        }\n\n        //# if (!isReal) {\n        /// <summary>\n        /// Creates a color from the given <see cref=\"int\"/> RGB values.\n        /// The values are not mapped to the <see cref=\"__type__\"/> color range.\n        /// The alpha channel is set to __maxval__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# cargs.ForEach(a => { */int __a__/*# }, comma); */)\n        {\n            /*# channels.ForEach(args,\n                    (c, a) => { */__c__ = (__ftype__)__a__/*# }, semicolon); */;\n            A = __t.MaxValue__;\n        }\n\n        /// <summary>\n        /// Creates a color from the given <see cref=\"long\"/> RGB values.\n        /// The values are not mapped to the <see cref=\"__type__\"/> color range.\n        /// The alpha channel is set to __maxval__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# cargs.ForEach(a => { */long __a__/*# }, comma); */)\n        {\n            /*# channels.ForEach(args,\n                    (c, a) => { */__c__ = (__ftype__)__a__/*# }, semicolon); */;\n            A = __t.MaxValue__;\n        }\n\n        //# }\n        //# if (!isFloat) {\n        /// <summary>\n        /// Creates a color from the given <see cref=\"float\"/> RGB values.\n        //# if (!isDouble) {\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"__type__\"/> color range.\n        //# }\n        /// The alpha channel is set to __maxval__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# cargs.ForEach(a => { */float __a__/*# }, comma); */)\n        {\n            /*# channels.ForEach(args,\n                    (c,a) => { */\n            __c__ = __f_to_ft__(__a__)/*# }, semicolon); */;\n            A = __t.MaxValue__;\n        }\n\n        //# }\n        //# if (!isDouble) {\n        /// <summary>\n        /// Creates a color from the given <see cref=\"double\"/> RGB values.\n        //# if (!isFloat) {\n        /// The values are mapped and clamped from [0, 1] to the <see cref=\"__type__\"/> color range.\n        //# }\n        /// The alpha channel is set to __maxval__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# cargs.ForEach(a => { */double __a__/*# }, comma); */)\n        {\n            /*# channels.ForEach(args,\n                    (c,a) => { */__c__ = __d_to_ft__(__a__)/*# }, semicolon); */;\n            A = __t.MaxValue__;\n        }\n\n        //# }\n        //# } // t.HasAlpha\n        /// <summary>\n        /// Creates a color from a single <see cref=\"__ftype__\"/> value.\n        //# if (t.HasAlpha) {\n        /// The alpha channel is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ gray)\n        {\n            /*# channels.ForEach(\n                    c => { */__c__ = gray/*# },\n                    semicolon); if (t.HasAlpha) {*/; A = __t.MaxValue__/*# } */;\n        }\n\n        //# foreach (var ft1 in Meta.RealTypes) { if (ft != ft1) {\n        //#     var ftype1 = ft1.Name;\n        //#     var convert = (ft1 == Meta.DoubleType) ? d_to_ft : f_to_ft;\n        /// <summary>\n        /// Creates a color from a single <see cref=\"__ftype1__\"/> value.\n        //# if (ismapped(ft, ft1)) {\n        /// The value is mapped and clamped from [0, 1] to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# if (t.HasAlpha) {\n        /// The alpha channel is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype1__ gray)\n        {\n            var value = __convert__(gray);\n            /*# channels.ForEach(\n                    c => { */__c__ = value/*# },\n                    semicolon); if (t.HasAlpha) {*/; A = __t.MaxValue__/*# } */;\n        }\n\n        //# } }\n        //# foreach (var t1 in Meta.ColorTypes) {\n        //#     var ft1 = t1.FieldType;\n        //#     var convert = t.FieldType != t1.FieldType\n        //#         ? \"Col.\" + t1.FieldType.Caps + \"To\" + t.FieldType.Caps + (isclamped(ft1, ft) ? \"Clamped\" : \"\")\n        //#         : \"\";\n        /// <summary>\n        /// Creates a color from the given <see cref=\"__t1.Name__\"/> color.\n        //# if (ismapped(ft1, ft)) {\n        //# if (isclamped(ft1, ft)) {\n        /// The values are mapped and clamped to the <see cref=\"__type__\"/> color range.\n        //# } else {\n        /// The values are mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# }\n        //# if (t.HasAlpha && !t1.HasAlpha) {\n        /// The alpha channel is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__t1.Name__ color)\n        {\n            //# channels.ForEach(c => {\n            __c__ = __convert__(color.__c__);\n            //# });\n            //# if (t.HasAlpha) {\n            //#     if (t1.HasAlpha) {\n            A = __convert__(color.A);\n            //#     } else {\n            A = __t.MaxValue__;\n            //#     }\n            //# }\n        }\n\n        //#if (t.HasAlpha && !t1.HasAlpha) { // build constructor from Color3 with explicit alpha\n        /// <summary>\n        /// Creates a color from the given <see cref=\"__t1.Name__\"/> color and an alpha value.\n        //# if (ismapped(ft1, ft)) {\n        //# if (isclamped(ft1, ft)) {\n        /// The values are mapped and clamped to the <see cref=\"__type__\"/> color range.\n        //# } else {\n        /// The values are mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__t1.Name__ color, __ftype__ alpha)\n        {\n            //# channels.ForEach(Meta.VecFields, (c, vf) => {\n            __c__ = __convert__(color.__c__);\n            //# });\n            A = alpha;\n        }\n\n        //# }\n        //# } // end For\n        //# for (int d = 3; d <= 4; d++) {\n        //#     foreach (var vft in Meta.VecFieldTypes) { if (coltovecsupported(ft, vft)) {\n        //#         var vt = Meta.VecTypeOf(d, vft);\n        //#         var convert = ft != vft\n        //#             ? \"(\"+ ft.Name+\")\"\n        //#             : \"\";\n        /// <summary>\n        /// Creates a color from the given <see cref=\"__vt.Name__\"/> vector.\n        //# if (ismapped(ft, vft)) {\n        /// The values are not mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# if (d < dim) {\n        /// The alpha channel is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__vt.Name__ vec)\n        {\n            //# fields.ForEach(Meta.VecFields, (c, vf, i) => {\n            __c__ = /*# if (i < d) { */__convert__(vec.__vf__);/*# } else {*/__t.MaxValue__;/*# }*/\n            //# });\n        }\n\n        //# } } }\n        //# if (t.HasAlpha) {\n        //# foreach (var vft in Meta.VecFieldTypes) { if (coltovecsupported(ft, vft)) {\n        //#     var vt = Meta.VecTypeOf(3, vft);\n        //#     var convert = ft != vft\n        //#         ? \"(\"+ ft.Name+\")\"\n        //#         : \"\";\n        /// <summary>\n        /// Creates a color from the given <see cref=\"__vt.Name__\"/> vector and an alpha value.\n        //# if (ismapped(ft, vft)) {\n        /// The values are not mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__vt.Name__ vec, __ftype__ alpha)\n        {\n            //# channels.ForEach(Meta.VecFields, (c, vf) => {\n            __c__ = __convert__(vec.__vf__);\n            //# });\n            A = alpha;\n        }\n\n        //# } } }\n        /// <summary>\n        /// Creates a color from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(Func<int, __ftype__> index_fun)\n        {\n            //# fields.ForEach((f, fi) => {\n            __f__ = index_fun(__fi__);\n            //# });\n        }\n\n        //# foreach (var ft1 in Meta.ColorFieldTypes) {\n        //#     var ftype1 = ft1.Name;\n        //#     var convert = ft != ft1\n        //#         ? \"Col.\" + ft1.Caps + \"To\" + ft.Caps + (isclamped(ft1, ft) ? \"Clamped\" : \"\")\n        //#         : \"\";\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"__ftype1__\"/> array.\n        //# if (ismapped(ft1, ft)) {\n        //# if (isclamped(ft1, ft)) {\n        /// The values are mapped and clamped to the <see cref=\"__type__\"/> color range.\n        //# } else {\n        /// The values are mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype1__[] values)\n        {\n            //# fields.ForEach((f, i) => {\n            __f__ = __convert__(values[__i__]);\n            //# });\n        }\n\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"__ftype1__\"/> array, starting at the specified index.\n        //# if (ismapped(ft1, ft)) {\n        //# if (isclamped(ft1, ft)) {\n        /// The values are mapped and clamped to the <see cref=\"__type__\"/> color range.\n        //# } else {\n        /// The values are mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype1__[] values, int start)\n        {\n            //# fields.ForEach((f, i) => {\n            __f__ = __convert__(values[start + __i__]);\n            //# });\n        }\n\n        //# }\n        #endregion\n\n        //# if (t.HasAlpha || isReal) {\n        #region Properities\n\n        //# if (t.HasAlpha) {\n        //#     var t1 = Meta.ColorTypeOf(3, ft);\n        //#     var type1 = t1.Name;\n        public readonly __type1__ RGB => (__type1__)this;\n\n        //# }\n        //# if (isReal) {\n        //# var condArray = new[] { \"NaN\", \"Infinity\", \"PositiveInfinity\", \"NegativeInfinity\", \"Tiny\" };\n        //# var scopeArray = new[] { ftype, ftype, ftype, ftype, \"Fun\" };\n        //# var quantArray = new[] { \"Any\", \"All\" };\n        //# var actArray = new[] { oror, andand };\n        //# condArray.ForEach(scopeArray, (cond, scope) => {\n        //# quantArray.ForEach(actArray, (qant, act) => {\n        public readonly bool __qant____cond__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => /*# fields.ForEach((f, i) => { */__scope__.Is__cond__(__f__)/*# }, act); */;\n        }\n\n        //# }); // quantArray\n        //# }); // condArray\n        /// <summary>\n        /// Returns true if the absolute value of each component of the color is smaller than Constant&lt;__ftype__&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the color is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the color are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        //# } // isReal\n        #endregion\n\n        //# }\n        #region Conversions\n\n        //# foreach (var t1 in Meta.ColorTypes) if (t1 != t) {\n        //#     var type1 = t1.Name;\n        /// <summary>\n        /// Converts the given <see cref=\"__type1__\"/> color to a <see cref=\"__type__\"/> color.\n        //# if (ismapped(t1.FieldType, ft)) {\n        //# if (isclamped(t1.FieldType, ft)) {\n        /// The values are mapped and clamped to the <see cref=\"__type__\"/> color range.\n        //# } else {\n        /// The values are mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# }\n        //# if (t.HasAlpha && !t1.HasAlpha) {\n        /// The alpha channel is set to __maxvalmap[t.FieldType]__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type1__ color)\n            => new __type__(color);\n\n        /// <summary>\n        /// Converts the given <see cref=\"__type__\"/> color to a <see cref=\"__type1__\"/> color.\n        //# if (ismapped(ft, t1.FieldType)) {\n        //# if (isclamped(ft, t1.FieldType)) {\n        /// The values are mapped and clamped to the <see cref=\"__type1__\"/> color range.\n        //# } else {\n        /// The values are mapped to the <see cref=\"__type1__\"/> color range.\n        //# }\n        //# }\n        //# if (t1.HasAlpha && !t.HasAlpha) {\n        /// The alpha channel is set to __maxvalmap[t1.FieldType]__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type1__ To__type1__() => (__type1__)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> color from the given <see cref=\"__type1__\"/> color.\n        //# if (ismapped(t1.FieldType, ft)) {\n        //# if (isclamped(t1.FieldType, ft)) {\n        /// The values are mapped and clamped to the <see cref=\"__type__\"/> color range.\n        //# } else {\n        /// The values are mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# }\n        //# if (t.HasAlpha && !t1.HasAlpha) {\n        /// The alpha channel is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__type1__(__type1__ c) => new __type__(c);\n\n        //# }\n        //# for (int d = 3; d <= 4; d++) {\n        //#     foreach (var vft in Meta.VecFieldTypes) { if (coltovecsupported(ft, vft)) {\n        //#         var vt = Meta.VecTypeOf(d, vft);\n        //#         var vtype = vt.Name;\n        //#         var convert = ft != vft ? \"(\"+ vft.Name+\")\" : \"\";\n        /// <summary>\n        /// Converts the given <see cref=\"__vtype__\"/> vector to a <see cref=\"__type__\"/> color.\n        //# if (ismapped(ft, vft)) {\n        /// The values are not mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# if (d == 3 && t.HasAlpha) {\n        /// The alpha channel is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__vtype__ v)\n            => new __type__(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"__type__\"/> color to a <see cref=\"__vtype__\"/> vector.\n        //# if (ismapped(ft, vft)) {\n        /// The values are not mapped from the <see cref=\"__type__\"/> color range.\n        //# }\n        //# if (d == 4 && dim == 3) {\n        /// W is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vtype__ To__vtype__() => (__vtype__)this;\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> color from a <see cref=\"__vtype__\"/> vector.\n        //# if (ismapped(ft, vft)) {\n        /// The values are not mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        //# if (d == 3 && t.HasAlpha) {\n        /// The alpha channel is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__vtype__(__vtype__ c) => new __type__(c);\n\n        //#     } }\n        //# }\n        //# foreach (var ft1 in Meta.ColorFieldTypes) {\n        //#     var ftype1 = ft1.Name;\n        //#     var convert = ft != ft1\n        //#         ? \"Col.\" + ft.Caps + \"To\" + ft1.Caps + (isclamped(ft, ft1) ? \"Clamped\" : \"\")\n        //#         : \"\";\n        /// <summary>\n        /// Creates a new color from the given <see cref=\"__ftype1__\"/> array.\n        //# if (ismapped(ft, ft1)) {\n        /// The values are mapped to the <see cref=\"__type__\"/> color range.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__ftype1__[] values)\n            => new __type__(values);\n\n        /// <summary>\n        /// Creates a new <see cref=\"__ftype1__\"/> array from the given <see cref=\"__type__\"/> color.\n        //# if (ismapped(ft, ft1)) {\n        //# if (isclamped(ft, ft1)) {\n        /// The values are mapped and clamped from the <see cref=\"__type__\"/> color range.\n        //# } else {\n        /// The values are mapped from the <see cref=\"__type__\"/> color range.\n        //# }\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __ftype1__[](__type__ color)\n            => new __ftype1__[] { /*# fields.ForEach(f => {*/__convert__(color.__f__)/*# }, comma); */ };\n\n        //# }\n        //# foreach (var t1 in Meta.ColorTypes) {\n        //#     if (t.Fields.Length != t1.Fields.Length) continue;\n        //#     var type1 = t1.Name;\n        //#     var ftype1 = t1.FieldType.Name;\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type1__ Map(Func<__ftype__, __ftype1__> channel_fun)\n        {\n            return new __type1__(/*# fields.ForEach(f => { */channel_fun(__f__)/*# }, comma); */);\n        }\n\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<__ftype__, T> element_fun)\n        {\n            //# fields.ForEach((f, i) => {\n            array[start + __i__] = element_fun(__f__);\n            //# });\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<__ftype__, int, T> element_index_fun)\n        {\n            //# fields.ForEach((f, i) => {\n            array[start + __i__] = element_index_fun(__f__, __i__);\n            //# });\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__[] ToArray()\n            => (__ftype__[])this;\n\n        #endregion\n\n        #region Indexer\n\n        //# if (ft == Meta.ByteType) {\n        // Byte colors have a different byte order (red and blue are swapped)\n        private static readonly byte[] IndexMapping = new byte[] { 2, 1, 0, 3 };\n\n        //# }\n        /// <summary>\n        /// Indexer in canonical order 0=R, 1=G, 2=B, 3=A (availability depending on color type).\n        /// </summary>\n        public unsafe __ftype__ this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (__ftype__* ptr = __getptr__) { ptr[/*#if (ft == Meta.ByteType) {*/IndexMapping[i]/*# } else {*/i/*#}*/] = value; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (__ftype__* ptr = __getptr__) { return ptr[/*#if (ft == Meta.ByteType) {*/IndexMapping[i]/*# } else {*/i/*#}*/]; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// __type__ with all components zero.\n        /// </summary>\n        public static __type__ Zero => new __type__(/*# fields.ForEach(f => {*/__t.MinValue__/*#}, comma); */);\n\n        // Web colors\n        //# foreach(KeyValuePair<string, V3d> entry in ColorNames) {\n        //# var name = entry.Key;\n        //# var color = new C3d(entry.Value);\n        public static __type__ __name__ => new __type__(__d_to_ft__(__color.R__), __d_to_ft__(__color.G__), __d_to_ft__(__color.B__));\n        //# }\n\n        public static __type__ DarkYellow => Olive;\n\n        public static __type__ VRVisGreen => new __type__(__d_to_ft__(0.698), __d_to_ft__(0.851), __d_to_ft__(0.008));\n\n        //# for (int i = 1; i < 10; i++) {\n        //# var val = (double)(0.1m * i); int percent = 10 * i;\n        public static __type__ Gray__percent__ => new __type__(__d_to_ft__(__val__));\n        //# }\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n        {\n            return /*# fields.ForEach(f => { */a.__f__ == b.__f__/*# }, andand); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n        {\n            return /*# fields.ForEach(f => { */a.__f__ != b.__f__/*# }, oror); */;\n        }\n\n        #endregion\n\n        #region Color Arithmetic\n\n        //# if (!ft.IsReal) {\n        //# fdtypes.ForEach(rt => {\n        //# var rtype = rt.Name;\n        //# var ft_to_r = (rt == Meta.FloatType) ? ft_to_f : ft_to_d;\n        //# var r_to_ft = (rt == Meta.FloatType) ? f_to_ft : d_to_ft;\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ col, __rtype__ scalar)\n        {\n            return new __type__(/*# fields.ForEach(f => { */\n                __r_to_ft__(__ft_to_r__(col.__f__) * scalar)/*# }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__rtype__ scalar, __type__ col)\n            => col * scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__type__ col, __rtype__ scalar)\n            => col * (1 / scalar);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__rtype__ scalar, __type__ col)\n        {\n            return new __type__(/*# fields.ForEach(f => { */\n                __r_to_ft__(scalar / __ft_to_r__(col.__f__))/*# }, comma); */);\n        }\n\n        //# });\n        //# }\n        //# foreach (var t1 in Meta.ColorTypes) { if (t1.HasAlpha != t.HasAlpha) continue;\n        //#     if (t1 == t) continue;\n        //#     var type1 = t1.Name; var ft1 = t1.FieldType;\n        //#     var ft1_from_ft = t1 != t\n        //#         ? (ft.IsReal && ft1.IsReal ? \"(\" + ftype + \")\" : \"Col.\" + ft1.Caps + \"To\" + ft.Caps)\n        //#         : \"\";\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator +(__type__ c0, __type1__ c1)\n        {\n            return new __type__(/*# fields.ForEach(f => { */\n                (__ftype__)(c0.__f__ + __ft1_from_ft__(c1.__f__))/*# }, comma); */);\n        }\n\n        [Obsolete(\"Use operator with operands of same type instead.\")]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ c0, __type1__ c1)\n        {\n            return new __type__(/*# fields.ForEach(f => { */\n                (__ftype__)(c0.__f__ - __ft1_from_ft__(c1.__f__))/*# }, comma); */);\n        }\n\n        //# } // t1\n        //# if (!ft.IsReal) {\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ col, __ftype__ scalar)\n        {\n            return new __type__(/*# fields.ForEach(f => { */(__ftype__)(col.__f__ * scalar)/*# }, comma); */);\n        }\n\n        //# if (!ft.IsReal) {\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__ftype__ scalar, __type__ col)\n        {\n            return new __type__(/*# fields.ForEach(f => { */(__ftype__)(scalar * col.__f__)/*# }, comma); */);\n        }\n\n        //# if (!ft.IsReal) {\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__type__ col, __ftype__ scalar)\n        {\n            return new __type__(/*# fields.ForEach(f => { */(__ftype__)(col.__f__ / scalar)/*# }, comma); */);\n        }\n\n        //# if (!ft.IsReal) {\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__ftype__ scalar, __type__ col)\n        {\n            return new __type__(/*# fields.ForEach(f => { */(__ftype__)(scalar / col.__f__)/*# }, comma); */);\n        }\n\n        //# if (!ft.IsReal) {\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ c0, __type__ c1)\n        {\n            return new __type__(/*# fields.ForEach(f => { */(__ftype__)(c0.__f__ * c1.__f__)/*# }, comma); */);\n        }\n\n        //# if (!ft.IsReal) {\n        [Obsolete(\"Multiplication and division of integer-based colors is unreasonable.\")]\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__type__ c0, __type__ c1)\n        {\n            return new __type__(/*# fields.ForEach(f => { */(__ftype__)(c0.__f__ / c1.__f__)/*# }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator +(__type__ c0, __type__ c1)\n        {\n            //# if (ft.IsReal) {\n            return new __type__(/*# fields.ForEach(f => { */c0.__f__ + c1.__f__/*# }, comma); */);\n            //# } else {\n            return new __type__(/*# fields.ForEach(f => { */\n                (__t.MaxValue__ - c0.__f__ > c1.__f__) ? c0.__f__ + c1.__f__ : __t.MaxValue__/*# }, comma); */\n            );\n            //# }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator +(__type__ col, __ftype__ scalar)\n        {\n            //# if (ft.IsReal) {\n            return new __type__(/*# fields.ForEach(f => { */col.__f__ + scalar/*# }, comma); */);\n            //# } else {\n            return new __type__(/*# fields.ForEach(f => { */\n                (__t.MaxValue__ - col.__f__ > scalar) ? col.__f__ + scalar : __t.MaxValue__/*# }, comma); */\n            );\n            //# }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator +(__ftype__ scalar, __type__ col)\n            => col + scalar;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ c0, __type__ c1)\n        {\n            //# if (ft.IsReal) {\n            return new __type__(/*# fields.ForEach(f => { */c0.__f__ - c1.__f__/*# }, comma); */);\n            //# } else {\n            return new __type__(/*# fields.ForEach(f => { */\n                (c0.__f__ > c1.__f__) ? c0.__f__ - c1.__f__ : 0/*# }, comma); */\n            );\n            //# }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ col, __ftype__ scalar)\n        {\n            //# if (ft.IsReal) {\n            return new __type__(/*# fields.ForEach(f => { */col.__f__ - scalar/*# }, comma); */);\n            //# } else {\n            return new __type__(/*# fields.ForEach(f => { */\n                (col.__f__ > scalar) ? col.__f__ - scalar : 0/*# }, comma); */\n            );\n            //# }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__ftype__ scalar, __type__ col)\n        {\n            //# if (ft.IsReal) {\n            return new __type__(/*# fields.ForEach(f => { */scalar - col.__f__/*# }, comma); */);\n            //# } else {\n            return new __type__(/*# fields.ForEach(f => { */\n                (scalar > col.__f__) ? scalar - col.__f__ : 0/*# }, comma); */\n            );\n            //# }\n        }\n\n        /// <summary>\n        /// Clamps the color channels to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Clamp(__ftype__ min, __ftype__ max)\n        {\n            //# channels.ForEach(c => {\n            __c__ = __c__.Clamp(min, max);\n            //# });\n        }\n\n        /// <summary>\n        /// Returns a copy with the color channels clamped to the given bounds.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ Clamped(__ftype__ min, __ftype__ max)\n        {\n            return new __type__(/*# channels.ForEach(\n                c => { */__c__.Clamp(min, max)/*# }, comma);\n                if (t.HasAlpha) {*/, A/*# } */);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |R| + |G| + |B|. /*# if (t.HasAlpha) { */The alpha channel is ignored./*# } */\n        /// </summary>\n        public readonly __htype__ Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return /*# channels.ForEach(c => { */__fabs_p____c____q_fabs__/*# }, add); */; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the color. This is calculated\n        /// as sqrt(R^2 + G^2 + B^2). /*# if (t.HasAlpha) { */The alpha channel is ignored./*# } */\n        /// </summary>\n        public readonly __ctype__ Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(/*# channels.ForEach(c => { */__c__ * __c__/*# }, add); */); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the color. This is\n        /// calculated as max(|R|, |G|, |B|). /*# if (t.HasAlpha) { */The alpha channel is ignored./*# } */\n        /// </summary>\n        public readonly __ftype__ NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(/*# channels.ForEach(c => { */__fabs_p____c____q_fabs__/*# }, comma); */); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the color. This is calculated as\n        /// min(|R|, |G|, |B|). /*# if (t.HasAlpha) { */The alpha channel is ignored./*# } */\n        /// </summary>\n        public readonly __ftype__ NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(/*# channels.ForEach(c => { */__fabs_p____c____q_fabs__/*# }, comma); */); }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(/*# t.Fields.ForEach(f => { */__f__/*# }, comma); */);\n        }\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")/*# fields.ForEach(f => {*/\n                + __f__.ToString(null, CultureInfo.InvariantCulture) /*# }, addqcommaspace); */\n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<__type__, int, __ftype__> Setter =\n            (ref __type__ color, int i, __ftype__ value) =>\n            {\n                switch (i)\n                {\n                    //# fields.ForEach((f, i) => {\n                    case __i__: color.__f__ = value; return;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        //# foreach(var tt in fdtypes) {\n        //# if (ft.IsReal && tt != ft) continue;\n        //# var vtt = Meta.VecTypeOf(dim, tt);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ LinearInterp(__tt.Name__ t, __type__ a, __type__ b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ LinearInterp(__vtt.Name__ t, __type__ a, __type__ b)\n            => Fun.Lerp(t, a, b);\n\n        //#}\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ DivideByInt(__type__ c, int x)\n            => c / x;\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional/*# if (!t.HasAlpha) {*/ and discarded/*#}*/.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, __type__.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        public static bool TryParse(Text t, out __type__ result)\n        {\n            //# if (type == \"C4b\") {\n            if (Col.TryParseHex(t, out result))\n            {\n                return true;\n            }\n            //# } else {\n            if (Col.TryParseHex(t, out C4b tmp))\n            {\n                result = tmp.To__type__();\n                return true;\n            }\n            //# }\n            else\n            {\n                bool success = true;\n                __ftype__[] values = new __ftype__[4] { /*# 4.ForEach(p => { */__t.MaxValue__/*# }, comma);*/ };\n\n                __ftype__ parse(Text t)\n                {\n                    if (!__ftype__.TryParse(t.ToString(), __parseNumberStyle__, CultureInfo.InvariantCulture, out __ftype__ value))\n                        success = false;\n\n                    return value;\n                };\n\n                var count = t.NestedBracketSplitCount2(1);\n                if (count == 3 || count == 4)\n                    t.NestedBracketSplit(1, parse, () => values);\n                else\n                    success = false;\n\n                result = success ? new __type__(values) : Zero;\n                return success;\n            }\n        }\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional/*# if (!t.HasAlpha) {*/ and discarded/*#}*/.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <param name=\"result\">Contains the parsed color on success, __type__.Zero otherwise.</param>\n        /// <returns>True on success, false otherwise.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool TryParse(string s, out __type__ result)\n            => TryParse(new Text(s), out result);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional/*# if (!t.HasAlpha) {*/ and discarded/*#}*/.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"s\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid __type__ color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(string s)\n            => Parse(new Text(s));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(Text t, int bracketLevel = 1)\n            => t.NestedBracketSplit(bracketLevel, Text<__ftype__>.Parse, __type__.Setter);\n\n        /// <summary>\n        /// Parses a color string with decimal format [R, G, B, A], or hexadecimal formats RRGGBBAA or RGBA.\n        /// </summary>\n        /// <remarks>\n        /// The alpha component in any format is optional/*# if (!t.HasAlpha) {*/ and discarded/*#}*/.\n        /// For the single digit hexadecimal RGBA format, the components are duplicated (e.g. \"F\" is interpreted as \"FF\").\n        /// Color strings in a hexadecimal format may be prefixed by \"#\" or \"0x\".\n        /// </remarks>\n        /// <param name=\"t\">The string to be parsed.</param>\n        /// <returns>The parsed color.</returns>\n        /// <exception cref=\"FormatException\">the input does not represent a valid __type__ color.</exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Parse(Text t)\n            => TryParse(t, out __type__ result) ? result : throw new FormatException($\"{t} is not a valid __type__ color.\");\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin /*# fields.ForEach(f => {*/+ __f__.ToString(format, fp) /*# }, addbetween); */ + end;\n        }\n\n        #endregion\n\n        #region IEquatable<__type__> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n        {\n            return /*# fields.ForEach(f => { */__f__.Equals(other.__f__)/*# }, andand); */;\n        }\n\n        #endregion\n\n        #region IRGB Members\n\n        double IRGB.Red\n        {\n            readonly get { return __ft_to_d__(R); }\n            set { R = __d_to_ft__(value); }\n        }\n\n        double IRGB.Green\n        {\n            readonly get { return __ft_to_d__(G); }\n            set { G = __d_to_ft__(value); }\n        }\n\n        double IRGB.Blue\n        {\n            readonly get { return __ft_to_d__(B); }\n            set { B = __d_to_ft__(value); }\n        }\n\n        #endregion\n\n        //# if (t.HasAlpha) {\n        #region IOpacity Members\n\n        [XmlIgnore]\n        public double Opacity\n        {\n            readonly get { return __ft_to_d__(A); }\n            set { A = __d_to_ft__(value); }\n        }\n\n        #endregion\n\n        //# }\n    }\n\n    public static partial class Fun\n    {\n        #region Interpolation\n\n        //# foreach(var tt in fdtypes) {\n        //# if (ft.IsReal && tt != ft) continue;\n        //# var vtt = Meta.VecTypeOf(dim, tt);\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static __type__ Lerp(this __tt.Name__ t, __type__ a, __type__ b)\n            => new __type__(/*# fields.ForEach(f => {*/Lerp(t, a.__f__, b.__f__)/*#}, comma); */);\n\n        /// <summary>\n        /// Returns the linearly interpolated color between a and b.\n        /// </summary>\n        public static __type__ Lerp(this __vtt.Name__ t, __type__ a, __type__ b)\n            => new __type__(/*# fields.ForEach(Meta.VecFields, (cf, vf) => {*/Lerp(t.__vf__, a.__cf__, b.__cf__)/*#}, comma); */);\n\n        //#}\n        #endregion\n\n        #region ApproximateEquals\n\n        //# if (isReal) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n        {\n            return ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance)\n        {\n            return /*# fields.ForEach(f => {*/ApproximateEquals(a.__f__, b.__f__, tolerance)/*# }, andand);*/;\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"__type__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this __type__ c, __ftype__ epsilon)\n            => Col.AllTiny(c, epsilon);\n\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"__type__\"/> is smaller than Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(__type__ c)\n            => c.IsTiny;\n\n        //# }\n        #endregion\n        //# if (isReal) {\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"__type__\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(__type__ c)\n            => c.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"__type__\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(__type__ c)\n            => c.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"__type__\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(__type__ c)\n            => c.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"__type__\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(__type__ c)\n            => c.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"__type__\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(__type__ c)\n            => c.IsFinite;\n\n        #endregion\n        //# }\n    }\n\n    public static partial class Col\n    {\n        #region ToHexString\n\n        /// <summary>\n        /// Returns the hexadecimal representation with format RRGGBB/*# if (t.HasAlpha) {*/AA/*#}*/.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static string ToHexString(this __type__ c)\n            //# if (ft == Meta.ByteType) {\n            => /*# if (t.HasAlpha) {*/$\"{c.R:X2}{c.G:X2}{c.B:X2}{c.A:X2}\"/*# } else {*/$\"{c.R:X2}{c.G:X2}{c.B:X2}\"/*#}*/;\n            //# } else {\n            => c.ToC__t.Len__b().ToHexString();\n            //# }\n\n        #endregion\n\n        #region Comparisons\n\n        //# var bops = new[,] { { \"<\",  \"Smaller\"        }, { \">\" , \"Greater\"},\n        //#                     { \"<=\", \"SmallerOrEqual\" }, { \">=\", \"GreaterOrEqual\"},\n        //#                     { \"==\", \"Equal\" },          { \"!=\", \"Different\" } };\n        //# var attention = \"ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\";\n        //# for(int o = 0; o < bops.GetLength(0); o++) {\n        //#     string bop = \" \" + bops[o,0] + \" \", opName = bops[o,1];\n        /// <summary>\n        /// Returns whether ALL elements of a are __opName__ the corresponding element of b.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(this __type__ a, __type__ b)\n        {\n            return (/*# fields.ForEach(f => { */a.__f____bop__b.__f__/*# }, andand); */);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of col are __opName__ s.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(this __type__ col, __ftype__ s)\n        {\n            return (/*# fields.ForEach(f => { */col.__f____bop__s/*# }, andand); */);\n        }\n\n        /// <summary>\n        /// Returns whether a is __opName__ ALL elements of col.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(__ftype__ s, __type__ col)\n        {\n            return (/*# fields.ForEach(f => { */s__bop__col.__f__/*# }, andand); */);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is __opName__ the corresponding element of b.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(this __type__ a, __type__ b)\n        {\n            return (/*# fields.ForEach(f => { */a.__f____bop__b.__f__/*# }, oror); */);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of col is __opName__ s.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(this __type__ col, __ftype__ s)\n        {\n            return (/*# fields.ForEach(f => { */col.__f____bop__s/*# }, oror); */);\n        }\n\n        /// <summary>\n        /// Returns whether a is __opName__ AT LEAST ONE element of col.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(__ftype__ s, __type__ col)\n        {\n            return (/*# fields.ForEach(f => { */s__bop__col.__f__/*# }, oror); */);\n        }\n        //# }\n\n        #endregion\n\n        #region Linear Combination\n\n        //# for (int tpc = 4; tpc < 7; tpc+=2) {\n        //# foreach (var rt in new[] { fltt, dblt }) { var rtype = rt.Name; var wtype = rt.FieldType.Name; var rtc = rt.FieldType.Caps[0];\n        //#     var convert = ft.IsReal ? \"\"\n        //#        : \"Col.\" + ft.Caps + \"In\"\n        //#          + (ft.Name == \"uint\" ? \"Double\" : rt.FieldType.Caps)\n        //#          + \"To\" + ft.Caps + \"Clamped\";\n        //# if (!isReal || wtype == ftype) {\n        /// <summary>\n        /// A function that returns the linear combination fo the supplied parameters\n        /// with the referenced weight tuple.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ LinCom(\n            /*# tpc.ForEach(i => { */__type__ p__i__/*# }, comma); */, ref Tup__tpc__<__wtype__> w)\n        {\n            return new __type__(/*# channels.ForEach(ch => { */\n                __convert__(/*# tpc.ForEach(i => { */p__i__.__ch__ * w.E__i__/*# }, add); */)/*# }, comma); */);\n        }\n\n        //# }\n        //# if (!isReal) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ LinComRaw__rtc__(\n            /*# tpc.ForEach(i => { */__type__ p__i__/*# }, comma); */, ref Tup__tpc__<__wtype__> w)\n        {\n            return new __rtype__(/*# channels.ForEach(ch => { */\n                /*# tpc.ForEach(i => { */p__i__.__ch__ * w.E__i__/*# }, add); }, comma); */);\n        }\n\n        //# } // !isReal\n        //# } // rt\n        //# } // tpc\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"__type__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this __type__ c, __ftype__ epsilon)\n            => /*# fields.ForEach(f => { */c.__f__.IsTiny(epsilon)/*# }, oror);*/;\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"__type__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this __type__ c, __ftype__ epsilon)\n            => /*# fields.ForEach(f => { */c.__f__.IsTiny(epsilon)/*# }, andand);*/;\n\n        #endregion\n        //# if (isReal) {\n\n        #region Special Floating Point Value Checks\n\n        //# var condArray = new[] { \"NaN\", \"Infinity\", \"PositiveInfinity\", \"NegativeInfinity\", \"Tiny\" };\n        //# var scopeArray = new[] { ftype, ftype, ftype, ftype, \"Fun\" };\n        //# var quantArray = new[] { \"Any\", \"All\" };\n        //# var actArray = new[] { oror, andand };\n        //# condArray.ForEach(scopeArray, (cond, scope) => {\n        //# quantArray.ForEach(actArray, (qant, act) => {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool __qant____cond__(__type__ c)\n            => c.__qant____cond__;\n\n        //# }); // quantArray\n        //# }); // condArray\n        #endregion\n        //# }\n    }\n\n    //# if (ft != Meta.ByteType && ft != Meta.UShortType) {\n    public static class IRandomUniform__type__Extensions\n    {\n        #region IRandomUniform extensions for __type__\n\n        //# string[] variants;\n        //# if (ft == Meta.FloatType) {\n        //#     variants = new string[] { \"\", \"Closed\", \"Open\" };\n        //# } else if (ft == Meta.DoubleType) {\n        //#     variants = new string[] { \"\", \"Closed\", \"Open\", \"Full\", \"FullClosed\", \"FullOpen\" };\n        //# } else {\n        //#     variants = new string[] { \"\" };\n        //# }\n        //# foreach (var v in variants) {\n        /// <summary>\n        /// Uses Uniform__fcaps____v__() to generate the elements of a __type__ color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Uniform__type____v__(this IRandomUniform rnd)\n        {\n            return new __type__(/*# fields.ForEach(f => { */rnd.Uniform__fcaps____v__()/*#  }, comma); */);\n        }\n\n        //# }\n        #endregion\n    }\n\n    //# }\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Colors/Spectrum.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public class Spectrum\n    {\n        public double FirstWaveLength;\n        public double DeltaWaveLength;\n        public double[] Data;\n\n        public Spectrum(double firstWaveLength, double deltaWaveLength, double[] data)\n        {\n            FirstWaveLength = firstWaveLength;\n            DeltaWaveLength = deltaWaveLength;\n            Data = data;\n        }\n        \n        public static readonly Spectrum CieXYZ31X = new Spectrum(360, 1, SpectralData.CieXYZ31_X_360_830_1nm);\n        public static readonly Spectrum CieXYZ31Y = new Spectrum(360, 1, SpectralData.CieXYZ31_Y_360_830_1nm);\n        public static readonly Spectrum CieXYZ31Z = new Spectrum(360, 1, SpectralData.CieXYZ31_Z_360_830_1nm);\n\n        public static readonly Spectrum CieIlluminantA = new Spectrum(300, 1, SpectralData.CieIlluminantA_300_830_1nm);\n        public static readonly Spectrum CieIlluminantD65 = new Spectrum(300, 1, SpectralData.CieIlluminantD65_300_830_1nm);\n    }\n\n    public static class SpectralData\n    {\n        #region CIE XYZ 1931 Color Matching Functions 360-830nm in 1nm steps\n\n        public static readonly double[] CieXYZ31_X_360_830_1nm =\n        {\n            0.0001299, 0.000145847, 0.000163802, 0.000184004, 0.00020669, 0.0002321, 0.000260728, 0.000293075, 0.000329388, 0.000369914,\n            0.0004149, 0.000464159, 0.000518986, 0.000581854, 0.000655235, 0.0007416, 0.00084503, 0.000964527, 0.001094949, 0.001231154,\n            0.001368, 0.00150205, 0.001642328, 0.001802382, 0.001995757, 0.002236, 0.002535385, 0.002892603, 0.003300829, 0.003753236,\n            0.004243, 0.004762389, 0.005330048, 0.005978712, 0.006741117, 0.00765, 0.008751373, 0.01002888, 0.0114217, 0.01286901,\n            0.01431, 0.01570443, 0.01714744, 0.01878122, 0.02074801, 0.02319, 0.02620736, 0.02978248, 0.03388092, 0.03846824,\n            0.04351, 0.0489956, 0.0550226, 0.0617188, 0.069212, 0.07763, 0.08695811, 0.09717672, 0.1084063, 0.1207672,\n            0.13438, 0.1493582, 0.1653957, 0.1819831, 0.198611, 0.21477, 0.2301868, 0.2448797, 0.2587773, 0.2718079,\n            0.2839, 0.2949438, 0.3048965, 0.3137873, 0.3216454, 0.3285, 0.3343513, 0.3392101, 0.3431213, 0.3461296,\n            0.34828, 0.3495999, 0.3501474, 0.350013, 0.349287, 0.34806, 0.3463733, 0.3442624, 0.3418088, 0.3390941,\n            0.3362, 0.3331977, 0.3300411, 0.3266357, 0.3228868, 0.3187, 0.3140251, 0.308884, 0.3032904, 0.2972579,\n\n            0.2908, 0.2839701, 0.2767214, 0.2689178, 0.2604227, 0.2511, 0.2408475, 0.2298512, 0.2184072, 0.2068115,\n            0.19536, 0.1842136, 0.1733273, 0.1626881, 0.1522833, 0.1421, 0.1321786, 0.1225696, 0.1132752, 0.1042979,\n            0.09564, 0.08729955, 0.07930804, 0.07171776, 0.06458099, 0.05795001, 0.05186211, 0.04628152, 0.04115088, 0.03641283,\n            0.03201, 0.0279172, 0.0241444, 0.020687, 0.0175404, 0.0147, 0.01216179, 0.00991996, 0.00796724, 0.006296346,\n            0.0049, 0.003777173, 0.00294532, 0.00242488, 0.002236293, 0.0024, 0.00292552, 0.00383656, 0.00517484, 0.00698208,\n            0.0093, 0.01214949, 0.01553588, 0.01947752, 0.02399277, 0.0291, 0.03481485, 0.04112016, 0.04798504, 0.05537861,\n            0.06327, 0.07163501, 0.08046224, 0.08973996, 0.09945645, 0.1096, 0.1201674, 0.1311145, 0.1423679, 0.1538542,\n            0.1655, 0.1772571, 0.18914, 0.2011694, 0.2133658, 0.2257499, 0.2383209, 0.2510668, 0.2639922, 0.2771017,\n            0.2904, 0.3038912, 0.3175726, 0.3314384, 0.3454828, 0.3597, 0.3740839, 0.3886396, 0.4033784, 0.4183115,\n            0.4334499, 0.4487953, 0.464336, 0.480064, 0.4959713, 0.5120501, 0.5282959, 0.5446916, 0.5612094, 0.5778215,\n            \n            0.5945, 0.6112209, 0.6279758, 0.6447602, 0.6615697, 0.6784, 0.6952392, 0.7120586, 0.7288284, 0.7455188,\n            0.7621, 0.7785432, 0.7948256, 0.8109264, 0.8268248, 0.8425, 0.8579325, 0.8730816, 0.8878944, 0.9023181,\n            0.9163, 0.9297995, 0.9427984, 0.9552776, 0.9672179, 0.9786, 0.9893856, 0.9995488, 1.0090892, 1.0180064,\n            1.0263, 1.0339827, 1.040986, 1.047188, 1.0524667, 1.0567, 1.0597944, 1.0617992, 1.0628068, 1.0629096,\n            1.0622, 1.0607352, 1.0584436, 1.0552244, 1.0509768, 1.0456, 1.0390369, 1.0313608, 1.0226662, 1.0130477,\n            1.0026, 0.9913675, 0.9793314, 0.9664916, 0.9528479, 0.9384, 0.923194, 0.907244, 0.890502, 0.87292,\n            0.8544499, 0.835084, 0.814946, 0.794186, 0.772954, 0.7514, 0.7295836, 0.7075888, 0.6856022, 0.6638104,\n            0.6424, 0.6215149, 0.6011138, 0.5811052, 0.5613977, 0.5419, 0.5225995, 0.5035464, 0.4847436, 0.4661939,\n            0.4479, 0.4298613, 0.412098, 0.394644, 0.3775333, 0.3608, 0.3444563, 0.3285168, 0.3130192, 0.2980011,\n            0.2835, 0.2695448, 0.2561184, 0.2431896, 0.2307272, 0.2187, 0.2070971, 0.1959232, 0.1851708, 0.1748323,\n            \n            0.1649, 0.1553667, 0.14623, 0.13749, 0.1291467, 0.1212, 0.1136397, 0.106465, 0.09969044, 0.09333061,\n            0.0874, 0.08190096, 0.07680428, 0.07207712, 0.06768664, 0.0636, 0.05980685, 0.05628216, 0.05297104, 0.04981861,\n            0.04677, 0.04378405, 0.04087536, 0.03807264, 0.03540461, 0.0329, 0.03056419, 0.02838056, 0.02634484, 0.02445275,\n            0.0227, 0.02108429, 0.01959988, 0.01823732, 0.01698717, 0.01584, 0.01479064, 0.01383132, 0.01294868, 0.0121292,\n            0.01135916, 0.01062935, 0.009938846, 0.009288422, 0.008678854, 0.008110916, 0.007582388, 0.007088746, 0.006627313, 0.006195408,\n            0.005790346, 0.005409826, 0.005052583, 0.004717512, 0.004403507, 0.004109457, 0.003833913, 0.003575748, 0.003334342, 0.003109075,\n            0.002899327, 0.002704348, 0.00252302, 0.002354168, 0.002196616, 0.00204919, 0.00191096, 0.001781438, 0.00166011, 0.001546459,\n            0.001439971, 0.001340042, 0.001246275, 0.001158471, 0.00107643, 0.000999949, 0.000928736, 0.000862433, 0.00080075, 0.000743396,\n            0.000690079, 0.000640516, 0.000594502, 0.000551865, 0.000512429, 0.000476021, 0.000442454, 0.000411512, 0.000382981, 0.000356649,\n            0.000332301, 0.000309759, 0.000288887, 0.000269539, 0.000251568, 0.000234826, 0.000219171, 0.000204526, 0.000190841, 0.000178065,\n            \n            0.000166151, 0.000155024, 0.000144622, 0.00013491, 0.000125852, 0.000117413, 0.000109552, 0.000102225, 9.53945E-05, 8.90239E-05,\n            8.30753E-05, 7.75127E-05, 7.2313E-05, 6.74578E-05, 6.29284E-05, 5.87065E-05, 5.47703E-05, 5.10992E-05, 4.76765E-05, 4.44857E-05,\n            4.15099E-05, 3.87332E-05, 3.6142E-05, 3.37235E-05, 3.14649E-05, 2.93533E-05, 2.73757E-05, 2.55243E-05, 2.37938E-05, 2.21787E-05,\n            2.06738E-05, 1.92723E-05, 1.79664E-05, 1.67499E-05, 1.56165E-05, 1.45598E-05, 1.35739E-05, 1.26544E-05, 1.17972E-05, 1.09984E-05,\n            1.0254E-05, 9.55965E-06, 8.91204E-06, 8.30836E-06, 7.74577E-06, 7.22146E-06, 6.73248E-06, 6.27642E-06, 5.8513E-06, 5.45512E-06,\n            5.08587E-06, 4.74147E-06, 4.42024E-06, 4.12078E-06, 3.84172E-06, 3.58165E-06, 3.33913E-06, 3.11295E-06, 2.90212E-06, 2.70565E-06,\n            2.52253E-06, 2.35173E-06, 2.19242E-06, 2.0439E-06, 1.9055E-06, 1.77651E-06, 1.65622E-06, 1.54402E-06, 1.43944E-06, 1.34198E-06,\n            1.25114E-06\n\n        };\n\n        public static readonly double[] CieXYZ31_Y_360_830_1nm =\n        {\n            0.000003917, 4.39358E-06, 4.9296E-06, 5.53214E-06, 6.20825E-06, 0.000006965, 7.81322E-06, 8.76734E-06, 9.83984E-06, 1.10432E-05,\n            0.00001239, 1.38864E-05, 1.55573E-05, 1.7443E-05, 1.95838E-05, 0.00002202, 2.48397E-05, 2.80413E-05, 3.1531E-05, 3.52152E-05,\n            0.000039, 4.28264E-05, 4.69146E-05, 5.15896E-05, 5.71764E-05, 0.000064, 7.23442E-05, 8.22122E-05, 9.35082E-05, 0.000106136,\n            0.00012, 0.000134984, 0.000151492, 0.000170208, 0.000191816, 0.000217, 0.000246907, 0.00028124, 0.00031852, 0.000357267,\n            0.000396, 0.000433715, 0.000473024, 0.000517876, 0.000572219, 0.00064, 0.00072456, 0.0008255, 0.00094116, 0.00106988,\n            0.00121, 0.001362091, 0.001530752, 0.001720368, 0.001935323, 0.00218, 0.0024548, 0.002764, 0.0031178, 0.0035264,\n            0.004, 0.00454624, 0.00515932, 0.00582928, 0.00654616, 0.0073, 0.008086507, 0.00890872, 0.00976768, 0.01066443,\n            0.0116, 0.01257317, 0.01358272, 0.01462968, 0.01571509, 0.01684, 0.01800736, 0.01921448, 0.02045392, 0.02171824,\n            0.023, 0.02429461, 0.02561024, 0.02695857, 0.02835125, 0.0298, 0.03131083, 0.03288368, 0.03452112, 0.03622571,\n            0.038, 0.03984667, 0.041768, 0.043766, 0.04584267, 0.048, 0.05024368, 0.05257304, 0.05498056, 0.05745872,\n\n            0.06, 0.06260197, 0.06527752, 0.06804208, 0.07091109, 0.0739, 0.077016, 0.0802664, 0.0836668, 0.0872328,\n            0.09098, 0.09491755, 0.09904584, 0.1033674, 0.1078846, 0.1126, 0.117532, 0.1226744, 0.1279928, 0.1334528,\n            0.13902, 0.1446764, 0.1504693, 0.1564619, 0.1627177, 0.1693, 0.1762431, 0.1835581, 0.1912735, 0.199418,\n            0.20802, 0.2171199, 0.2267345, 0.2368571, 0.2474812, 0.2586, 0.2701849, 0.2822939, 0.2950505, 0.308578,\n            0.323, 0.3384021, 0.3546858, 0.3716986, 0.3892875, 0.4073, 0.4256299, 0.4443096, 0.4633944, 0.4829395,\n            0.503, 0.5235693, 0.544512, 0.56569, 0.5869653, 0.6082, 0.6293456, 0.6503068, 0.6708752, 0.6908424,\n            0.71, 0.7281852, 0.7454636, 0.7619694, 0.7778368, 0.7932, 0.8081104, 0.8224962, 0.8363068, 0.8494916,\n            0.862, 0.8738108, 0.8849624, 0.8954936, 0.9054432, 0.9148501, 0.9237348, 0.9320924, 0.9399226, 0.9472252,\n            0.954, 0.9602561, 0.9660074, 0.9712606, 0.9760225, 0.9803, 0.9840924, 0.9874182, 0.9903128, 0.9928116,\n            0.9949501, 0.9967108, 0.9980983, 0.999112, 0.9997482, 1, 0.9998567, 0.9993046, 0.9983255, 0.9968987,\n\n            0.995, 0.9926005, 0.9897426, 0.9864444, 0.9827241, 0.9786, 0.9740837, 0.9691712, 0.9638568, 0.9581349,\n            0.952, 0.9454504, 0.9384992, 0.9311628, 0.9234576, 0.9154, 0.9070064, 0.8982772, 0.8892048, 0.8797816,\n            0.87, 0.8598613, 0.849392, 0.838622, 0.8275813, 0.8163, 0.8047947, 0.793082, 0.781192, 0.7691547,\n            0.757, 0.7447541, 0.7324224, 0.7200036, 0.7074965, 0.6949, 0.6822192, 0.6694716, 0.6566744, 0.6438448,\n            0.631, 0.6181555, 0.6053144, 0.5924756, 0.5796379, 0.5668, 0.5539611, 0.5411372, 0.5283528, 0.5156323,\n            0.503, 0.4904688, 0.4780304, 0.4656776, 0.4534032, 0.4412, 0.42908, 0.417036, 0.405032, 0.393032,\n            0.381, 0.3689184, 0.3568272, 0.3447768, 0.3328176, 0.321, 0.3093381, 0.2978504, 0.2865936, 0.2756245,\n            0.265, 0.2547632, 0.2448896, 0.2353344, 0.2260528, 0.217, 0.2081616, 0.1995488, 0.1911552, 0.1829744,\n            0.175, 0.1672235, 0.1596464, 0.1522776, 0.1451259, 0.1382, 0.1315003, 0.1250248, 0.1187792, 0.1127691,\n            0.107, 0.1014762, 0.09618864, 0.09112296, 0.08626485, 0.0816, 0.07712064, 0.07282552, 0.06871008, 0.06476976,\n            \n            0.061, 0.05739621, 0.05395504, 0.05067376, 0.04754965, 0.04458, 0.04175872, 0.03908496, 0.03656384, 0.03420048,\n            0.032, 0.02996261, 0.02807664, 0.02632936, 0.02470805, 0.0232, 0.02180077, 0.02050112, 0.01928108, 0.01812069,\n            0.017, 0.01590379, 0.01483718, 0.01381068, 0.01283478, 0.01192, 0.01106831, 0.01027339, 0.009533311, 0.008846157,\n            0.00821, 0.007623781, 0.007085424, 0.006591476, 0.006138485, 0.005723, 0.005343059, 0.004995796, 0.004676404, 0.004380075,\n            0.004102, 0.003838453, 0.003589099, 0.003354219, 0.003134093, 0.002929, 0.002738139, 0.002559876, 0.002393244, 0.002237275,\n            0.002091, 0.001953587, 0.00182458, 0.00170358, 0.001590187, 0.001484, 0.001384496, 0.001291268, 0.001204092, 0.001122744,\n            0.001047, 0.00097659, 0.000911109, 0.000850133, 0.000793238, 0.00074, 0.000690083, 0.00064331, 0.000599496, 0.000558455,\n            0.00052, 0.000483914, 0.000450053, 0.000418345, 0.000388718, 0.0003611, 0.000335384, 0.00031144, 0.000289166, 0.000268454,\n            0.0002492, 0.000231302, 0.000214686, 0.000199288, 0.000185048, 0.0001719, 0.000159778, 0.000148604, 0.000138302, 0.000128793,\n            0.00012, 0.00011186, 0.000104322, 9.73356E-05, 9.08459E-05, 0.0000848, 7.91467E-05, 0.000073858, 0.000068916, 6.43027E-05,\n            \n            0.00006, 5.59819E-05, 5.22256E-05, 4.87184E-05, 4.54475E-05, 0.0000424, 3.9561E-05, 3.69151E-05, 3.44487E-05, 3.21482E-05,\n            0.00003, 2.79913E-05, 2.61136E-05, 2.43602E-05, 2.27246E-05, 0.0000212, 1.97786E-05, 1.84529E-05, 1.72169E-05, 1.60646E-05,\n            0.00001499, 1.39873E-05, 1.30516E-05, 1.21782E-05, 1.13625E-05, 0.0000106, 9.88588E-06, 9.2173E-06, 8.59236E-06, 8.00913E-06,\n            7.4657E-06, 6.95957E-06, 6.488E-06, 6.0487E-06, 5.6394E-06, 5.2578E-06, 4.90177E-06, 4.56972E-06, 4.26019E-06, 3.97174E-06,\n            3.7029E-06, 3.45216E-06, 3.2183E-06, 3.0003E-06, 2.79714E-06, 2.6078E-06, 2.43122E-06, 2.26653E-06, 2.11301E-06, 1.96994E-06,\n            1.8366E-06, 1.71223E-06, 1.59623E-06, 1.48809E-06, 1.38731E-06, 1.2934E-06, 1.20582E-06, 1.12414E-06, 1.04801E-06, 9.77058E-07,\n            9.1093E-07, 8.49251E-07, 7.91721E-07, 7.3809E-07, 6.8811E-07, 6.4153E-07, 5.9809E-07, 5.57575E-07, 5.19808E-07, 4.84612E-07,\n            4.5181E-07\n        };\n\n        public static readonly double[] CieXYZ31_Z_360_830_1nm =\n        {\n            0.0006061, 0.000680879, 0.000765146, 0.000860012, 0.000966593, 0.001086, 0.001220586, 0.001372729, 0.001543579, 0.001734286,\n            0.001946, 0.002177777, 0.002435809, 0.002731953, 0.003078064, 0.003486, 0.003975227, 0.00454088, 0.00515832, 0.005802907,\n            0.006450001, 0.007083216, 0.007745488, 0.008501152, 0.009414544, 0.01054999, 0.0119658, 0.01365587, 0.01558805, 0.01773015,\n            0.02005001, 0.02251136, 0.02520288, 0.02827972, 0.03189704, 0.03621, 0.04143771, 0.04750372, 0.05411988, 0.06099803,\n            0.06785001, 0.07448632, 0.08136156, 0.08915364, 0.09854048, 0.1102, 0.1246133, 0.1417017, 0.1613035, 0.1832568,\n            0.2074, 0.2336921, 0.2626114, 0.2947746, 0.3307985, 0.3713, 0.4162091, 0.4654642, 0.5196948, 0.5795303,\n            0.6456, 0.7184838, 0.7967133, 0.8778459, 0.959439, 1.0390501, 1.1153673, 1.1884971, 1.2581233, 1.3239296,\n            1.3856, 1.4426352, 1.4948035, 1.5421903, 1.5848807, 1.62296, 1.6564048, 1.6852959, 1.7098745, 1.7303821,\n            1.74706, 1.7600446, 1.7696233, 1.7762637, 1.7804334, 1.7826, 1.7829682, 1.7816998, 1.7791982, 1.7758671,\n            1.77211, 1.7682589, 1.764039, 1.7589438, 1.7524663, 1.7441, 1.7335595, 1.7208581, 1.7059369, 1.6887372,\n            \n            1.6692, 1.6475287, 1.6234127, 1.5960223, 1.564528, 1.5281, 1.4861114, 1.4395215, 1.3898799, 1.3387362,\n            1.28764, 1.2374223, 1.1878243, 1.1387611, 1.090148, 1.0419, 0.9941976, 0.9473473, 0.9014531, 0.8566193,\n            0.8129501, 0.7705173, 0.7294448, 0.6899136, 0.6521049, 0.6162, 0.5823286, 0.5504162, 0.5203376, 0.4919673,\n            0.46518, 0.4399246, 0.4161836, 0.3938822, 0.3729459, 0.3533, 0.3348578, 0.3175521, 0.3013375, 0.2861686,\n            0.272, 0.2588171, 0.2464838, 0.2347718, 0.2234533, 0.2123, 0.2011692, 0.1901196, 0.1792254, 0.1685608,\n            0.1582, 0.1481383, 0.1383758, 0.1289942, 0.1200751, 0.1117, 0.1039048, 0.09666748, 0.08998272, 0.08384531,\n            0.07824999, 0.07320899, 0.06867816, 0.06456784, 0.06078835, 0.05725001, 0.05390435, 0.05074664, 0.04775276, 0.04489859,\n            0.04216, 0.03950728, 0.03693564, 0.03445836, 0.03208872, 0.02984, 0.02771181, 0.02569444, 0.02378716, 0.02198925,\n            0.0203, 0.01871805, 0.01724036, 0.01586364, 0.01458461, 0.0134, 0.01230723, 0.01130188, 0.01037792, 0.009529306,\n            0.008749999, 0.0080352, 0.0073816, 0.0067854, 0.0062428, 0.005749999, 0.0053036, 0.0048998, 0.0045342, 0.0042024,\n            \n            0.0039, 0.0036232, 0.0033706, 0.0031414, 0.0029348, 0.002749999, 0.0025852, 0.0024386, 0.0023094, 0.0021968,\n            0.0021, 0.002017733, 0.0019482, 0.0018898, 0.001840933, 0.0018, 0.001766267, 0.0017378, 0.0017112, 0.001683067,\n            0.001650001, 0.001610133, 0.0015644, 0.0015136, 0.001458533, 0.0014, 0.001336667, 0.00127, 0.001205, 0.001146667,\n            0.0011, 0.0010688, 0.0010494, 0.0010356, 0.0010212, 0.001, 0.00096864, 0.00092992, 0.00088688, 0.00084256,\n            0.0008, 0.00076096, 0.00072368, 0.00068592, 0.00064544, 0.0006, 0.000547867, 0.0004916, 0.0004354, 0.000383467,\n            0.00034, 0.000307253, 0.00028316, 0.00026544, 0.000251813, 0.00024, 0.000229547, 0.00022064, 0.00021196, 0.000202187,\n            0.00019, 0.000174213, 0.00015564, 0.00013596, 0.000116853, 0.0001, 8.61333E-05, 0.0000746, 0.000065, 5.69333E-05,\n            5E-05, 0.00004416, 0.00003948, 0.00003572, 0.00003264, 0.00003, 2.76533E-05, 0.00002556, 0.00002364, 2.18133E-05,\n            0.00002, 1.81333E-05, 0.0000162, 0.0000142, 1.21333E-05, 0.00001, 7.73333E-06, 0.0000054, 0.0000032, 1.33333E-06,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            \n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n            0\n        };\n\n        #endregion\n\n        #region CIE Illuminant A Spectral Distribution 300-830nm in 1nm steps\n\n        public static readonly double[] CieIlluminantA_300_830_1nm =\n        {\n            0.930483, 0.967643, 1.00597, 1.04549, 1.08623, 1.12821, 1.17147, 1.21602, 1.26188, 1.3091,\n            1.35769, 1.40768, 1.4591, 1.51198, 1.56633, 1.62219, 1.67959, 1.73855, 1.7991, 1.86127,\n            1.92508, 1.99057, 2.05776, 2.12667, 2.19734, 2.2698, 2.34406, 2.42017, 2.49814, 2.57801,\n            2.65981, 2.74355, 2.82928, 2.91701, 3.00678, 3.09861, 3.19253, 3.28857, 3.38676, 3.48712,\n            3.58968, 3.69447, 3.80152, 3.91085, 4.0225, 4.13648, 4.25282, 4.37156, 4.49272, 4.61631,\n            4.74238, 4.87095, 5.00204, 5.13568, 5.27189, 5.4107, 5.55213, 5.69622, 5.84298, 5.99244,\n            6.14462, 6.29955, 6.45724, 6.61774, 6.78105, 6.9472, 7.11621, 7.28811, 7.46292, 7.64066,\n            7.82135, 8.00501, 8.19167, 8.38134, 8.57404, 8.7698, 8.96864, 9.17056, 9.37561, 9.58378,\n            9.7951, 10.0096, 10.2273, 10.4481, 10.6722, 10.8996, 11.1302, 11.364, 11.6012, 11.8416,\n            12.0853, 12.3324, 12.5828, 12.8366, 13.0938, 13.3543, 13.6182, 13.8855, 14.1563, 14.4304,\n            \n            14.708, 14.9891, 15.2736, 15.5616, 15.853, 16.148, 16.4464, 16.7484, 17.0538, 17.3628,\n            17.6753, 17.9913, 18.3108, 18.6339, 18.9605, 19.2907, 19.6244, 19.9617, 20.3026, 20.647,\n            20.995, 21.3465, 21.7016, 22.0603, 22.4225, 22.7883, 23.1577, 23.5307, 23.9072, 24.2873,\n            24.6709, 25.0581, 25.4489, 25.8432, 26.2411, 26.6425, 27.0475, 27.456, 27.8681, 28.2836,\n            28.7027, 29.1253, 29.5515, 29.9811, 30.4142, 30.8508, 31.2909, 31.7345, 32.1815, 32.632,\n            33.0859, 33.5432, 34.004, 34.4682, 34.9358, 35.4068, 35.8811, 36.3588, 36.8399, 37.3243,\n            37.8121, 38.3031, 38.7975, 39.2951, 39.796, 40.3002, 40.8076, 41.3182, 41.832, 42.3491,\n            42.8693, 43.3926, 43.9192, 44.4488, 44.9816, 45.5174, 46.0563, 46.5983, 47.1433, 47.6913,\n            48.2423, 48.7963, 49.3533, 49.9132, 50.476, 51.0418, 51.6104, 52.1818, 52.7561, 53.3332,\n            53.9132, 54.4958, 55.0813, 55.6694, 56.2603, 56.8539, 57.4501, 58.0489, 58.6504, 59.2545,\n            \n            59.8611, 60.4703, 61.082, 61.6962, 62.3128, 62.932, 63.5535, 64.1775, 64.8038, 65.4325,\n            66.0635, 66.6968, 67.3324, 67.9702, 68.6102, 69.2525, 69.8969, 70.5435, 71.1922, 71.843,\n            72.4959, 73.1508, 73.8077, 74.4666, 75.1275, 75.7903, 76.4551, 77.1217, 77.7902, 78.4605,\n            79.1326, 79.8065, 80.4821, 81.1595, 81.8386, 82.5193, 83.2017, 83.8856, 84.5712, 85.2584,\n            85.947, 86.6372, 87.3288, 88.0219, 88.7165, 89.4124, 90.1097, 90.8083, 91.5082, 92.2095,\n            92.912, 93.6157, 94.3206, 95.0267, 95.7339, 96.4423, 97.1518, 97.8623, 98.5739, 99.2864,\n            100, 100.715, 101.43, 102.146, 102.864, 103.582, 104.301, 105.02, 105.741, 106.462,\n            107.184, 107.906, 108.63, 109.354, 110.078, 110.803, 111.529, 112.255, 112.982, 113.709,\n            114.436, 115.164, 115.893, 116.622, 117.351, 118.08, 118.81, 119.54, 120.27, 121.001,\n            121.731, 122.462, 123.193, 123.924, 124.655, 125.386, 126.118, 126.849, 127.58, 128.312,\n            \n            129.043, 129.774, 130.505, 131.236, 131.966, 132.697, 133.427, 134.157, 134.887, 135.617,\n            136.346, 137.075, 137.804, 138.532, 139.26, 139.988, 140.715, 141.441, 142.167, 142.893,\n            143.618, 144.343, 145.067, 145.79, 146.513, 147.235, 147.957, 148.678, 149.398, 150.117,\n            150.836, 151.554, 152.271, 152.988, 153.704, 154.418, 155.132, 155.845, 156.558, 157.269,\n            157.979, 158.689, 159.397, 160.104, 160.811, 161.516, 162.221, 162.924, 163.626, 164.327,\n            165.028, 165.726, 166.424, 167.121, 167.816, 168.51, 169.203, 169.895, 170.586, 171.275,\n            171.963, 172.65, 173.335, 174.019, 174.702, 175.383, 176.063, 176.741, 177.419, 178.094,\n            178.769, 179.441, 180.113, 180.783, 181.451, 182.118, 182.783, 183.447, 184.109, 184.77,\n            185.429, 186.087, 186.743, 187.397, 188.05, 188.701, 189.35, 189.998, 190.644, 191.288,\n            191.931, 192.572, 193.211, 193.849, 194.484, 195.118, 195.75, 196.381, 197.009, 197.636,\n            \n            198.261, 198.884, 199.506, 200.125, 200.743, 201.359, 201.972, 202.584, 203.195, 203.803,\n            204.409, 205.013, 205.616, 206.216, 206.815, 207.411, 208.006, 208.599, 209.189, 209.778,\n            210.365, 210.949, 211.532, 212.112, 212.691, 213.268, 213.842, 214.415, 214.985, 215.553,\n            216.12, 216.684, 217.246, 217.806, 218.364, 218.92, 219.473, 220.025, 220.574, 221.122,\n            221.667, 222.21, 222.751, 223.29, 223.826, 224.361, 224.893, 225.423, 225.951, 226.477,\n            227, 227.522, 228.041, 228.558, 229.073, 229.585, 230.096, 230.604, 231.11, 231.614,\n            232.115, 232.615, 233.112, 233.606, 234.099, 234.589, 235.078, 235.564, 236.047, 236.529,\n            237.008, 237.485, 237.959, 238.432, 238.902, 239.37, 239.836, 240.299, 240.76, 241.219,\n            241.675, 242.13, 242.582, 243.031, 243.479, 243.924, 244.367, 244.808, 245.246, 245.682,\n            246.116, 246.548, 246.977, 247.404, 247.829, 248.251, 248.671, 249.089, 249.505, 249.918,\n            \n            250.329, 250.738, 251.144, 251.548, 251.95, 252.35, 252.747, 253.142, 253.535, 253.925,\n            254.314, 254.7, 255.083, 255.465, 255.844, 256.221, 256.595, 256.968, 257.338, 257.706,\n            258.071, 258.434, 258.795, 259.154, 259.511, 259.865, 260.217, 260.567, 260.914, 261.259,\n            261.602\n        };\n\n        #endregion\n\n        #region CIE Illuminant D65 Spectral Distribution 300-830nm in 1nm steps\n\n        public static readonly double[] CieIlluminantD65_300_830_1nm =\n        {\n            0.0341, 0.36014, 0.68618, 1.01222, 1.33826, 1.6643, 1.99034, 2.31638, 2.64242, 2.96846,\n            3.2945, 4.98865, 6.6828, 8.37695, 10.0711, 11.7652, 13.4594, 15.1535, 16.8477, 18.5418,\n            20.236, 21.9177, 23.5995, 25.2812, 26.963, 28.6447, 30.3265, 32.0082, 33.69, 35.3717,\n            37.0535, 37.343, 37.6326, 37.9221, 38.2116, 38.5011, 38.7907, 39.0802, 39.3697, 39.6593,\n            39.9488, 40.4451, 40.9414, 41.4377, 41.934, 42.4302, 42.9265, 43.4228, 43.9191, 44.4154,\n            44.9117, 45.0844, 45.257, 45.4297, 45.6023, 45.775, 45.9477, 46.1203, 46.293, 46.4656,\n            46.6383, 47.1834, 47.7285, 48.2735, 48.8186, 49.3637, 49.9088, 50.4539, 50.9989, 51.544,\n            52.0891, 51.8777, 51.6664, 51.455, 51.2437, 51.0323, 50.8209, 50.6096, 50.3982, 50.1869,\n            49.9755, 50.4428, 50.91, 51.3773, 51.8446, 52.3118, 52.7791, 53.2464, 53.7137, 54.1809,\n            54.6482, 57.4589, 60.2695, 63.0802, 65.8909, 68.7015, 71.5122, 74.3229, 77.1336, 79.9442,\n            \n            82.7549, 83.628, 84.5011, 85.3742, 86.2473, 87.1204, 87.9936, 88.8667, 89.7398, 90.6129,\n            91.486, 91.6806, 91.8752, 92.0697, 92.2643, 92.4589, 92.6535, 92.8481, 93.0426, 93.2372,\n            93.4318, 92.7568, 92.0819, 91.4069, 90.732, 90.057, 89.3821, 88.7071, 88.0322, 87.3572,\n            86.6823, 88.5006, 90.3188, 92.1371, 93.9554, 95.7736, 97.5919, 99.4102, 101.228, 103.047,\n            104.865, 106.079, 107.294, 108.508, 109.722, 110.936, 112.151, 113.365, 114.579, 115.794,\n            117.008, 117.088, 117.169, 117.249, 117.33, 117.41, 117.49, 117.571, 117.651, 117.732,\n            117.812, 117.517, 117.222, 116.927, 116.632, 116.336, 116.041, 115.746, 115.451, 115.156,\n            114.861, 114.967, 115.073, 115.18, 115.286, 115.392, 115.498, 115.604, 115.711, 115.817,\n            115.923, 115.212, 114.501, 113.789, 113.078, 112.367, 111.656, 110.945, 110.233, 109.522,\n            108.811, 108.865, 108.92, 108.974, 109.028, 109.082, 109.137, 109.191, 109.245, 109.3,\n\n            109.354, 109.199, 109.044, 108.888, 108.733, 108.578, 108.423, 108.268, 108.112, 107.957,\n            107.802, 107.501, 107.2, 106.898, 106.597, 106.296, 105.995, 105.694, 105.392, 105.091,\n            104.79, 105.08, 105.37, 105.66, 105.95, 106.239, 106.529, 106.819, 107.109, 107.399,\n            107.689, 107.361, 107.032, 106.704, 106.375, 106.047, 105.719, 105.39, 105.062, 104.733,\n            104.405, 104.369, 104.333, 104.297, 104.261, 104.225, 104.19, 104.154, 104.118, 104.082,\n            104.046, 103.641, 103.237, 102.832, 102.428, 102.023, 101.618, 101.214, 100.809, 100.405,\n            100, 99.6334, 99.2668, 98.9003, 98.5337, 98.1671, 97.8005, 97.4339, 97.0674, 96.7008,\n            96.3342, 96.2796, 96.225, 96.1703, 96.1157, 96.0611, 96.0065, 95.9519, 95.8972, 95.8426,\n            95.788, 95.0778, 94.3675, 93.6573, 92.947, 92.2368, 91.5266, 90.8163, 90.1061, 89.3958,\n            88.6856, 88.8177, 88.9497, 89.0818, 89.2138, 89.3459, 89.478, 89.61, 89.7421, 89.8741,\n            \n            90.0062, 89.9655, 89.9248, 89.8841, 89.8434, 89.8026, 89.7619, 89.7212, 89.6805, 89.6398,\n            89.5991, 89.4091, 89.219, 89.029, 88.8389, 88.6489, 88.4589, 88.2688, 88.0788, 87.8887,\n            87.6987, 87.2577, 86.8167, 86.3757, 85.9347, 85.4936, 85.0526, 84.6116, 84.1706, 83.7296,\n            83.2886, 83.3297, 83.3707, 83.4118, 83.4528, 83.4939, 83.535, 83.576, 83.6171, 83.6581,\n            83.6992, 83.332, 82.9647, 82.5975, 82.2302, 81.863, 81.4958, 81.1285, 80.7613, 80.394,\n            80.0268, 80.0456, 80.0644, 80.0831, 80.1019, 80.1207, 80.1395, 80.1583, 80.177, 80.1958,\n            80.2146, 80.4209, 80.6272, 80.8336, 81.0399, 81.2462, 81.4525, 81.6588, 81.8652, 82.0715,\n            82.2778, 81.8784, 81.4791, 81.0797, 80.6804, 80.281, 79.8816, 79.4823, 79.0829, 78.6836,\n            78.2842, 77.4279, 76.5716, 75.7153, 74.859, 74.0027, 73.1465, 72.2902, 71.4339, 70.5776,\n            69.7213, 69.9101, 70.0989, 70.2876, 70.4764, 70.6652, 70.854, 71.0428, 71.2315, 71.4203,\n            \n            71.6091, 71.8831, 72.1571, 72.4311, 72.7051, 72.979, 73.253, 73.527, 73.801, 74.075,\n            74.349, 73.0745, 71.8, 70.5255, 69.251, 67.9765, 66.702, 65.4275, 64.153, 62.8785,\n            61.604, 62.4322, 63.2603, 64.0885, 64.9166, 65.7448, 66.573, 67.4011, 68.2293, 69.0574,\n            69.8856, 70.4057, 70.9259, 71.446, 71.9662, 72.4863, 73.0064, 73.5266, 74.0467, 74.5669,\n            75.087, 73.9376, 72.7881, 71.6387, 70.4893, 69.3398, 68.1904, 67.041, 65.8916, 64.7421,\n            63.5927, 61.8752, 60.1578, 58.4403, 56.7229, 55.0054, 53.288, 51.5705, 49.8531, 48.1356,\n            46.4182, 48.4569, 50.4956, 52.5344, 54.5731, 56.6118, 58.6505, 60.6892, 62.728, 64.7667,\n            66.8054, 66.4631, 66.1209, 65.7786, 65.4364, 65.0941, 64.7518, 64.4096, 64.0673, 63.7251,\n            63.3828, 63.4749, 63.567, 63.6592, 63.7513, 63.8434, 63.9355, 64.0276, 64.1198, 64.2119,\n            64.304, 63.8188, 63.3336, 62.8484, 62.3632, 61.8779, 61.3927, 60.9075, 60.4223, 59.9371,\n            \n            59.4519, 58.7026, 57.9533, 57.204, 56.4547, 55.7054, 54.9562, 54.2069, 53.4576, 52.7083,\n            51.959, 52.5072, 53.0553, 53.6035, 54.1516, 54.6998, 55.248, 55.7961, 56.3443, 56.8924,\n            57.4406, 57.7278, 58.015, 58.3022, 58.5894, 58.8765, 59.1637, 59.4509, 59.7381, 60.0253,\n            60.3125\n        };\n\n        #endregion\n\n        #region Preetham Sky Spectrum to XYZ Conversion\n\n        /// <summary>\n        /// sun color spectrum S0 from 380 - 780nm in 10nm steps (taken from preetham Table 2)\n        /// </summary>\n        public static readonly double[] SpecS0_380_780_10nm =\n        {\n            63.4, 65.8, 94.8, 104.8, 105.9, 96.8, 113.9, 125.6,\n            125.5, 121.3, 121.3, 113.5, 113.1, 110.8, 106.5, 108.8,\n            105.3, 104.4, 100.0, 96.0, 95.1, 89.1, 90.5, 90.3,\n            88.4, 84.0, 85.1, 81.9, 82.6, 84.9, 81.3, 71.9,\n            74.3, 76.4, 63.3, 71.7, 77.0, 65.2, 47.7, 68.6,\n            65.0\n        };\n\n        /// <summary>\n        /// sun color spectrum S1 from 380 - 780nm in 10nm steps (taken from preetham Table 2)\n        /// </summary>\n        public static readonly double[] SpecS1_380_780_10nm =\n        {\n            38.5, 35.0, 43.4, 46.3, 43.9, 37.1, 36.7, 35.9,\n            32.6, 27.9, 24.3, 20.1, 16.2, 13.2, 8.6, 6.1,\n            4.2, 1.9, 0.0, -1.6, -3.5, -3.5, -5.8, -7.2,\n            -8.6, -9.5, -10.9, -10.7, -12.0, -14.0, -13.6, -12.0,\n            -13.3, -12.9, -10.6, -11.6, -12.2, -10.2, -7.8, -11.2,\n            -10.4\n        };\n\n        /// <summary>\n        /// sun color spectrum S2 from 380 - 780nm in 10nm steps (taken from preetham Table 2)\n        /// </summary>\n        public static readonly double[] SpecS2_380_780_10nm =\n        {\n            3.0, 1.2, -1.1, -0.5, -0.7, -1.2, -2.6, -2.9,\n            -2.8, -2.6, -2.6, -1.8, -1.5, -1.3, -1.2, -1.0,\n            -0.5, -0.3, 0.0, 0.2, 0.5, 2.1, 3.2, 4.1,\n            4.7, 5.1, 6.7, 7.3, 8.6, 9.8, 10.2, 8.3,\n            9.6, 8.5, 7.0, 7.6, 8.0, 6.7, 5.2, 7.4,\n            6.8\n        };\n\n        /// <summary>\n        /// CIE XYZ standard observer sensitivity function X in 10mn steps.\n        /// </summary>\n        public static readonly double[] Ciexyz31X_380_780_10nm = \n        {\n            0.001368000000, 0.004243000000, 0.014310000000, 0.043510000000, 0.134380000000,\n            0.283900000000, 0.348280000000, 0.336200000000, 0.290800000000, 0.195360000000,\n            0.095640000000, 0.032010000000, 0.004900000000, 0.009300000000, 0.063270000000,\n            0.165500000000, 0.290400000000, 0.433449900000, 0.594500000000, 0.762100000000,\n            0.916300000000, 1.026300000000, 1.062200000000, 1.002600000000, 0.854449900000,\n            0.642400000000, 0.447900000000, 0.283500000000, 0.164900000000, 0.087400000000,\n            0.046770000000, 0.022700000000, 0.011359160000, 0.005790346000, 0.002899327000,\n            0.001439971000, 0.000690078600, 0.000332301100, 0.000166150500, 0.000083075270,\n            0.000041509940\n        };\n\n        /// <summary>\n        /// CIE XYZ standard observer sensitivity function Y in 10mn steps.\n        /// </summary>\n        public static readonly double[] Ciexyz31Y_380_780_10nm = \n        {\n            0.000039000000, 0.000120000000, 0.000396000000, 0.001210000000, 0.004000000000,\n            0.011600000000, 0.023000000000, 0.038000000000, 0.060000000000, 0.090980000000,\n            0.139020000000, 0.208020000000, 0.323000000000, 0.503000000000, 0.710000000000,\n            0.862000000000, 0.954000000000, 0.994950100000, 0.995000000000, 0.952000000000,\n            0.870000000000, 0.757000000000, 0.631000000000, 0.503000000000, 0.381000000000,\n            0.265000000000, 0.175000000000, 0.107000000000, 0.061000000000, 0.032000000000,\n            0.017000000000, 0.008210000000, 0.004102000000, 0.002091000000, 0.001047000000,\n            0.000520000000, 0.000249200000, 0.000120000000, 0.000060000000, 0.000030000000,\n            0.000014990000\n        };\n\n        /// <summary>\n        /// CIE XYZ standard observer sensitivity function Z in 10mn steps.\n        /// </summary>\n        public static readonly double[] Ciexyz31Z_380_780_10nm = \n        {\n            0.006450001000, 0.020050010000, 0.067850010000, 0.207400000000, 0.645600000000,\n            1.385600000000, 1.747060000000, 1.772110000000, 1.669200000000, 1.287640000000,\n            0.812950100000, 0.465180000000, 0.272000000000, 0.158200000000, 0.078249990000,\n            0.042160000000, 0.020300000000, 0.008749999000, 0.003900000000, 0.002100000000,\n            0.001650001000, 0.001100000000, 0.000800000000, 0.000340000000, 0.000190000000,\n            0.000049999990, 0.000020000000, 0.000000000000, 0.000000000000, 0.000000000000,\n            0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,\n            0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000, 0.000000000000,\n            0.000000000000\n        };\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Curves/Curves.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    public static partial class Ipol\n    {\n        public static partial class CubicHermite\n        {\n            public static Func<double, V3d, V3d, V3d, V3d, V3d> Fun(int derivative)\n            {\n                if (derivative < 0) throw new IndexOutOfRangeException();\n                switch (derivative)\n                {\n                    case 0: return Eval;\n                    case 1: return EvalD1;\n                    case 2: return EvalD2;\n                    case 3: return EvalD3;\n                    default: return (t, a, b, tIn, tOut) => V3d.Zero;\n                }\n            }\n\n            public static double Eval(double t, double a, double b, double tIn, double tOut)\n            {\n                var w = Weights(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n            public static V2d Eval(double t, V2d a, V2d b, V2d tIn, V2d tOut)\n            {\n                var w = Weights(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n            public static V3d Eval(double t, V3d a, V3d b, V3d tIn, V3d tOut)\n            {\n                var w = Weights(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n\n            public static double EvalD1(double t, double a, double b, double tIn, double tOut)\n            {\n                var w = WeightsD1(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n            public static V2d EvalD1(double t, V2d a, V2d b, V2d tIn, V2d tOut)\n            {\n                var w = WeightsD1(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n            public static V3d EvalD1(double t, V3d a, V3d b, V3d tIn, V3d tOut)\n            {\n                var w = WeightsD1(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n\n            public static double EvalD2(double t, double a, double b, double tIn, double tOut)\n            {\n                var w = WeightsD2(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n            public static V2d EvalD2(double t, V2d a, V2d b, V2d tIn, V2d tOut)\n            {\n                var w = WeightsD2(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n            public static V3d EvalD2(double t, V3d a, V3d b, V3d tIn, V3d tOut)\n            {\n                var w = WeightsD2(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n\n            public static double EvalD3(double t, double a, double b, double tIn, double tOut)\n            {\n                var w = WeightsD3(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n            public static V2d EvalD3(double t, V2d a, V2d b, V2d tIn, V2d tOut)\n            {\n                var w = WeightsD3(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n            public static V3d EvalD3(double t, V3d a, V3d b, V3d tIn, V3d tOut)\n            {\n                var w = WeightsD3(t);\n                return w[0] * a + w[1] * tIn + w[2] * tOut + w[3] * b;\n            }\n\n            internal static double[] Weights(double t)\n            {\n                var tt = t * t; var ttt = tt * t;\n                var tt3 = tt * 3; var ttt2 = ttt * 2;\n                return new double[]\n                { ttt2 - tt3 + 1, ttt - 2 * tt + t, ttt - tt, -ttt2 + tt3 };\n            }\n            internal static double[] WeightsD1(double t)\n            {\n                var tt = t * t;\n                var tt6 = tt * 6; var tt3 = tt * 3; var t6 = t * 6;\n                return new double[]\n                { tt6 - t6, tt3 - 4 * t + 1, tt3 - 2 * t, -tt6 + t6 };\n            }\n            internal static double[] WeightsD2(double t)\n            {\n                var t12 = t * 12; var t6 = t * 6;\n                return new double[] { t12 - 6, t6 - 4, t6 - 2, -t12 + 6 };\n            }\n            internal static double[] WeightsD3(double t)\n            {\n                return new double[] { 12, 6, 6, -12 };\n            }\n        }\n\n        public static partial class CatmullRom\n        {\n            public static Func<double, V3d, V3d, V3d, V3d, V3d> Fun(int derivative)\n            {\n                if (derivative < 0) throw new IndexOutOfRangeException();\n                switch (derivative)\n                {\n                    case 0: return Eval;\n                    case 1: return EvalD1;\n                    case 2: return EvalD2;\n                    case 3: return EvalD3;\n                    default: return (t, p0, p1, p2, p3) => V3d.Zero;\n                }\n            }\n\n            public static double Eval(double t, double p0, double p1, double p2, double p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.Eval(t, p1, p2, m0, m1);\n            }\n            public static V2d Eval(double t, V2d p0, V2d p1, V2d p2, V2d p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.Eval(t, p1, p2, m0, m1);\n            }\n            public static V3d Eval(double t, V3d p0, V3d p1, V3d p2, V3d p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.Eval(t, p1, p2, m0, m1);\n            }\n\n            public static double EvalD1(double t, double p0, double p1, double p2, double p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD1(t, p1, p2, m0, m1);\n            }\n            public static V2d EvalD1(double t, V2d p0, V2d p1, V2d p2, V2d p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD1(t, p1, p2, m0, m1);\n            }\n            public static V3d EvalD1(double t, V3d p0, V3d p1, V3d p2, V3d p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD1(t, p1, p2, m0, m1);\n            }\n\n            public static double EvalD2(double t, double p0, double p1, double p2, double p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD2(t, p1, p2, m0, m1);\n            }\n            public static V2d EvalD2(double t, V2d p0, V2d p1, V2d p2, V2d p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD2(t, p1, p2, m0, m1);\n            }\n            public static V3d EvalD2(double t, V3d p0, V3d p1, V3d p2, V3d p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD2(t, p1, p2, m0, m1);\n            }\n\n            public static double EvalD3(double t, double p0, double p1, double p2, double p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD3(t, p1, p2, m0, m1);\n            }\n            public static V2d EvalD3(double t, V2d p0, V2d p1, V2d p2, V2d p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD3(t, p1, p2, m0, m1);\n            }\n            public static V3d EvalD3(double t, V3d p0, V3d p1, V3d p2, V3d p3)\n            {\n                var m0 = (p2 - p0) * 0.5;\n                var m1 = (p3 - p1) * 0.5;\n                return CubicHermite.EvalD3(t, p1, p2, m0, m1);\n            }\n        }\n\n        public static partial class KochanekBartels\n        {\n            public static Func<double, V3d, V3d, V3d, V3d, double, double, V3d> Fun(int derivative)\n            {\n                if (derivative < 0) throw new IndexOutOfRangeException();\n                switch (derivative)\n                {\n                    case 0: return Eval;\n                    case 1: return EvalD1;\n                    case 2: return EvalD2;\n                    case 3: return EvalD3;\n                    default: return (t, p0, p1, p2, p3, tension, bias) => V3d.Zero;\n                }\n            }\n\n            public static double Eval(double t,\n                double p0, double p1, double p2, double p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.Eval(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n            public static V2d Eval(double t,\n                V2d p0, V2d p1, V2d p2, V2d p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.Eval(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n            public static V3d Eval(double t,\n                V3d p0, V3d p1, V3d p2, V3d p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.Eval(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n\n            public static double EvalD1(double t,\n                double p0, double p1, double p2, double p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD1(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n            public static V2d EvalD1(double t,\n                V2d p0, V2d p1, V2d p2, V2d p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD1(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n            public static V3d EvalD1(double t,\n                V3d p0, V3d p1, V3d p2, V3d p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD1(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n\n            public static double EvalD2(double t,\n                double p0, double p1, double p2, double p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD2(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n            public static V2d EvalD2(double t,\n                V2d p0, V2d p1, V2d p2, V2d p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD2(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n            public static V3d EvalD2(double t,\n                V3d p0, V3d p1, V3d p2, V3d p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD2(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n\n            public static double EvalD3(double t,\n                double p0, double p1, double p2, double p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD3(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n            public static V2d EvalD3(double t,\n                V2d p0, V2d p1, V2d p2, V2d p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD3(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n            public static V3d EvalD3(double t,\n                V3d p0, V3d p1, V3d p2, V3d p3, double tension, double bias)\n            {\n                var tangents = Tangents(p0, p1, p2, p3, tension, bias);\n                return CubicHermite.EvalD3(t, p1, p2, tangents.Item1, tangents.Item2);\n            }\n\n            /// <summary>\n            /// Computes the bounding box for interval [0, 1] of the\n            /// Kochanek-Bartels spline defined by the specified points,\n            /// tension, and bias.\n            /// </summary>\n            public static Box3d Bounds(\n                V3d p0, V3d p1, V3d p2, V3d p3, double tension, double bias)\n            {\n                return Bounds(Range1d.Unit, p0, p1, p2, p3, tension, bias);\n            }\n\n            /// <summary>\n            /// Computes the bounding box for interval [0, 1] of the\n            /// Kochanek-Bartels spline defined by the specified points.\n            /// </summary>\n            public static Box3d Bounds(V3d p0, V3d p1, V3d p2, V3d p3)\n            {\n                return Bounds(Range1d.Unit, p0, p1, p2, p3, 0, 0);\n            }\n\n            /// <summary>\n            /// Computes the bounding box of the Kochanek-Bartels spline\n            /// defined by points the specified points, tension, and bias.\n            /// </summary>\n            public static Box3d Bounds(Range1d domain,\n                V3d p0, V3d p1, V3d p2, V3d p3, double tension, double bias)\n            {\n                var oneMinusTensionHalf = (1 - tension) * 0.5;\n                var x1 = oneMinusTensionHalf * (1 + bias);\n                var x2 = oneMinusTensionHalf * (1 - bias);\n                var s0 = p1 - p0; var s1 = p2 - p1; var s2 = p3 - p2;\n                var m0 = x1 * s0 + x2 * s1;\n                var m1 = x1 * s1 + x2 * s2;\n\n                var bb = Box3d.Invalid;\n                bb.ExtendBy(domain.Min > 0\n                    ? Eval(domain.Min, p0, p1, p2, p3, tension, bias)\n                    : p1);\n                bb.ExtendBy(domain.Max < 1\n                    ? Eval(domain.Max, p0, p1, p2, p3, tension, bias)\n                    : p2);\n\n                var a = 6 * p1 + 3 * m0 + 3 * m1 - 6 * p2;\n                var b = -6 * p1 - 4 * m0 - 2 * m1 + 6 * p2;\n                var c = m0;\n\n                for (int i = 0; i < 3; i++)\n                {\n                    var t = Polynomial.RealRootsOf(a[i], b[i], c[i]);\n                    var p0x = p0[i]; var p1x = p1[i]; var p2x = p2[i]; var p3x = p3[i];\n                    if (t.Item1 > domain.Min && t.Item1 < domain.Max) bb.ExtendDimBy(i,\n                        Eval(t.Item1, p0x, p1x, p2x, p3x, tension, bias)\n                        );\n                    if (t.Item2 > domain.Min && t.Item2 < domain.Max) bb.ExtendDimBy(i,\n                        Eval(t.Item2, p0x, p1x, p2x, p3x, tension, bias)\n                        );\n                }\n\n                return bb;\n            }\n\n            /// <summary>\n            /// Computes incoming (Item1) and outgoing (Item2) tangent.\n            /// </summary>\n            private static (double, double) Tangents(\n                double p0, double p1, double p2, double p3, double tension, double bias)\n            {\n                var oneMinusTensionHalf = (1 - tension) * 0.5;\n                var x1 = oneMinusTensionHalf * (1 + bias);\n                var x2 = oneMinusTensionHalf * (1 - bias);\n                var s0 = p1 - p0; var s1 = p2 - p1; var s2 = p3 - p2;\n                return (x1 * s0 + x2 * s1, x1 * s1 + x2 * s2);\n            }\n            /// <summary>\n            /// Computes incoming (Item1) and outgoing (Item2) tangent.\n            /// </summary>\n            private static (V2d, V2d) Tangents(\n                V2d p0, V2d p1, V2d p2, V2d p3, double tension, double bias)\n            {\n                var oneMinusTensionHalf = (1 - tension) * 0.5;\n                var x1 = oneMinusTensionHalf * (1 + bias);\n                var x2 = oneMinusTensionHalf * (1 - bias);\n                var s0 = p1 - p0; var s1 = p2 - p1; var s2 = p3 - p2;\n                return (x1 * s0 + x2 * s1, x1 * s1 + x2 * s2);\n            }\n            /// <summary>\n            /// Computes incoming (Item1) and outgoing (Item2) tangent.\n            /// </summary>\n            private static (V3d, V3d) Tangents(\n                V3d p0, V3d p1, V3d p2, V3d p3, double tension, double bias)\n            {\n                var oneMinusTensionHalf = (1 - tension) * 0.5;\n                var x1 = oneMinusTensionHalf * (1 + bias);\n                var x2 = oneMinusTensionHalf * (1 - bias);\n                var s0 = p1 - p0; var s1 = p2 - p1; var s2 = p3 - p2;\n                return (x1 * s0 + x2 * s1, x1 * s1 + x2 * s2);\n            }\n        }\n    }\n\n    public class CurvePoints<T>\n    {\n        private readonly double[] m_params;\n        private readonly T[] m_items;\n        private Range1i m_indexes;\n\n        public CurvePoints(double[] parameters, T[] items)\n        {\n            if (parameters.Length != items.Length) throw new ArgumentException();\n            if (!parameters.IsStrictlyIncreasing()) throw new ArgumentException();\n\n            m_params = parameters;\n            m_items = items;\n            Init();\n        }\n\n        public CurvePoints(IEnumerable<Tup<double, T>> items)\n        {\n            var ordered = items.OrderBy(item => item.E0).ToArray();\n            m_params = ordered.Select(x => x.E0).ToArray();\n            m_items = ordered.Select(x => x.E1).ToArray();\n            Init();\n        }\n\n        private void Init()\n        {\n            m_indexes = new Range1i(0, m_items.Length - 1);\n        }\n\n        public Tup<double, T>[] Neighbourhood(double t)\n        {\n            int i = m_params.IndexOfLargestLessOrEqual(t).Clamp(m_indexes);\n            int j = (i + 1).Clamp(m_indexes);\n            return new Tup<double, T>[]\n            {\n                new Tup<double, T>(m_params[i], m_items[i]),\n                new Tup<double, T>(m_params[j], m_items[j]),\n            };\n        }\n\n        public Tup<double, T>[] Neighbourhood(\n            double t, int extendLeft, int extendRight)\n        {\n            int floor = m_params.IndexOfLargestLessOrEqual(t).Clamp(m_indexes);\n            var result = new Tup<double, T>[2 + extendLeft + extendRight];\n            int imin = floor - extendLeft;\n            for (int i = imin; i <= floor + 1 + extendRight; i++)\n            {\n                int index = i.Clamp(m_indexes);\n                result[i - imin] = new Tup<double, T>(m_params[index], m_items[index]);\n            }\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/IMatrix.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n     /// Non-generic Interface for Dim.X x Dim.Y - dimensional matrices.\n     /// </summary>\n    public interface IMatrix\n    {\n        V2l Dim { get; }\n        object GetValue(long x, long y);\n        void SetValue(object value, long x, long y);\n        object GetValue(V2l v);\n        void SetValue(object value, V2l v);\n    }\n\n    /// <summary>\n    /// Generic Interface for NxM-dimensional matrix of Type T.\n    /// The indexer of this interface has arguments of type long.\n    /// </summary>\n    public interface IMatrix<T> : IMatrix\n    {\n        T this[long x, long y] { get; set; }\n        T this[V2l v] { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/IOpacity.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    public interface IOpacity\n    {\n        /// <summary>\n        /// In range [0,1], where 0 means fully transparent, and 1 is fully opaque.\n        /// </summary>\n        double Opacity { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/IRGB.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public interface IRGB\n    {\n        double Red { get; set; }\n        double Green { get; set; }\n        double Blue { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/IRange.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n\n    /// <summary>\n    /// IRange enforces a uniform design of all range types.\n    /// This non-generic interface contains all the methods and properties\n    /// that are independent of type. It serves as a base interface to\n    /// the generic IRange interface.\n    /// </summary>\n    public interface IRange : IValidity\n    {\n        bool IsEmpty { get; }\n        bool IsNonEmpty { get; }\n    }\n\n    /// <summary>\n    /// ISimpleRange enforces a uniform interface of range operations that\n    /// ony require comparison of boundaries.\n    /// </summary>\n    public interface ISimpleRange<TValue, TRange> : IRange\n    {\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        TRange Repair();\n\n        /// <summary>\n        /// Returns whether range contains given value.\n        /// </summary>\n        bool Contains(TValue value);\n\n        /// <summary>\n        /// Returns whether range completely contains given range.\n        /// </summary>\n        bool Contains(TRange range);\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        bool Intersects(TRange range);\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        TRange ExtendedBy(TValue value);\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// Returns this.\n        /// </summary>\n        TRange ExtendedBy(TRange range);\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        void ExtendBy(TValue value);\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        void ExtendBy(TRange range);\n\n    }\n\n    /// <summary>\n    /// IRange enforces a uniform design of all range types.\n    /// </summary>\n    /// <typeparam name=\"TValue\">Type of range boundaries.</typeparam>\n    /// <typeparam name=\"TDiff\">Type of differences of TValue.\n    /// Given values a and b of type TValue: typeof(TDiff) == typeof(a-b).</typeparam>\n    /// <typeparam name=\"TRange\">Type of the concrete (implementing) range type.</typeparam>\n    public interface IRange<TValue, TDiff, TRange> : IRange, IFormattable, ISimpleRange<TValue, TRange>\n    {\n        // TValue Minimum { get; set; }\n        // TValue Maximum { get; set; }\n        TValue Center { get; }\n        TDiff Size { get; }\n        TRange SplitRight(TValue splitValue);\n        TRange SplitLeft(TValue splitValue);\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        bool Intersects(TRange range, TDiff eps);\n\n        /// <summary>\n        /// Returns range enlarged by specified vector in BOTH directions.\n        /// </summary>\n        TRange EnlargedBy(TDiff v);\n\n        /// <summary>\n        /// Returns range by shrunk specified vector in BOTH directions.\n        /// The returned range may be invalid if vector is too large.\n        /// </summary>\n        TRange ShrunkBy(TDiff v);\n\n        /// <summary>\n        /// Returns range enlarged by given values (paddings).\n        /// </summary>\n        TRange EnlargedBy(TDiff left, TDiff right);\n\n        /// <summary>\n        /// Returns range shrunk by given values (paddings).\n        /// The returned range may be invalid if the paddings are too large.\n        /// </summary>\n        TRange ShrunkBy(TDiff left, TDiff right);\n\n        /// <summary>\n        /// Enlarges range by specified vector in BOTH directions.\n        /// </summary>\n        void EnlargeBy(TDiff v);\n\n        /// <summary>\n        /// Shrinks range by specified vector in BOTH directions.\n        /// Range may become invalid if vector is too large.\n        /// </summary>\n        void ShrinkBy(TDiff v);\n\n        /// <summary>\n        /// Enlarges range by given values (paddings).\n        /// </summary>\n        void EnlargeBy(TDiff left, TDiff right);\n\n        /// <summary>\n        /// Shrinks range by given values (paddings).\n        /// </summary>\n        void ShrinkBy(TDiff left, TDiff right);\n\n    }\n\n    /// <summary>\n    /// IRange enforces a uniform design of all range types.\n    /// </summary>\n    /// <typeparam name=\"TValue\">Type of min and max elements of the range.</typeparam>\n    /// <typeparam name=\"TRange\">Type of the concrete (implementing) range type.</typeparam>\n    public interface IRange<TValue, TRange> : IRange<TValue, TValue, TRange>\n    {\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/ISize_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    /// <summary>\n    /// A Size2i reprents the size of an object in two dimensions.\n    /// </summary>\n    public interface ISize2i\n    {\n        V2i Size2i { get; }\n    }\n\n    /// <summary>\n    /// A Size3i reprents the size of an object in three dimensions.\n    /// </summary>\n    public interface ISize3i\n    {\n        V3i Size3i { get; }\n    }\n\n    /// <summary>\n    /// A Size4d reprents the size of an object in four dimensions.\n    /// </summary>\n    public interface ISize4i\n    {\n        V4i Size4i { get; }\n    }\n\n    /// <summary>\n    /// A Size2ui reprents the size of an object in two dimensions.\n    /// </summary>\n    public interface ISize2ui\n    {\n        V2ui Size2ui { get; }\n    }\n\n    /// <summary>\n    /// A Size3ui reprents the size of an object in three dimensions.\n    /// </summary>\n    public interface ISize3ui\n    {\n        V3ui Size3ui { get; }\n    }\n\n    /// <summary>\n    /// A Size4d reprents the size of an object in four dimensions.\n    /// </summary>\n    public interface ISize4ui\n    {\n        V4ui Size4ui { get; }\n    }\n\n    /// <summary>\n    /// A Size2l reprents the size of an object in two dimensions.\n    /// </summary>\n    public interface ISize2l\n    {\n        V2l Size2l { get; }\n    }\n\n    /// <summary>\n    /// A Size3l reprents the size of an object in three dimensions.\n    /// </summary>\n    public interface ISize3l\n    {\n        V3l Size3l { get; }\n    }\n\n    /// <summary>\n    /// A Size4d reprents the size of an object in four dimensions.\n    /// </summary>\n    public interface ISize4l\n    {\n        V4l Size4l { get; }\n    }\n\n    /// <summary>\n    /// A Size2f reprents the size of an object in two dimensions.\n    /// </summary>\n    public interface ISize2f\n    {\n        V2f Size2f { get; }\n    }\n\n    /// <summary>\n    /// A Size3f reprents the size of an object in three dimensions.\n    /// </summary>\n    public interface ISize3f\n    {\n        V3f Size3f { get; }\n    }\n\n    /// <summary>\n    /// A Size4d reprents the size of an object in four dimensions.\n    /// </summary>\n    public interface ISize4f\n    {\n        V4f Size4f { get; }\n    }\n\n    /// <summary>\n    /// A Size2d reprents the size of an object in two dimensions.\n    /// </summary>\n    public interface ISize2d\n    {\n        V2d Size2d { get; }\n    }\n\n    /// <summary>\n    /// A Size3d reprents the size of an object in three dimensions.\n    /// </summary>\n    public interface ISize3d\n    {\n        V3d Size3d { get; }\n    }\n\n    /// <summary>\n    /// A Size4d reprents the size of an object in four dimensions.\n    /// </summary>\n    public interface ISize4d\n    {\n        V4d Size4d { get; }\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/ISize_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var ft in Meta.VecFieldTypes) {\n    //#   var ftype = ft.Name;\n    //#   var tc = ft.Char;\n    /// <summary>\n    /// A Size2__tc__ reprents the size of an object in two dimensions.\n    /// </summary>\n    public interface ISize2__tc__\n    {\n        V2__tc__ Size2__tc__ { get; }\n    }\n\n    /// <summary>\n    /// A Size3__tc__ reprents the size of an object in three dimensions.\n    /// </summary>\n    public interface ISize3__tc__\n    {\n        V3__tc__ Size3__tc__ { get; }\n    }\n\n    /// <summary>\n    /// A Size4d reprents the size of an object in four dimensions.\n    /// </summary>\n    public interface ISize4__tc__\n    {\n        V4__tc__ Size4__tc__ { get; }\n    }\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/ITensor.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// Non-generic Interface for Dim.X x Dim.Y x Dim.Z, Dim.W - dimensional volumes.\n    /// </summary>\n    public interface ITensor4\n    {\n        V4l Dim { get; }\n        object GetValue(long x, long y, long z, long w);\n        void SetValue(object value, long x, long y, long z, long w);\n        object GetValue(V4l v);\n        void SetValue(object value, V4l v);\n    }\n\n    /// <summary>\n    /// Non-generic Interface for arbitrarily sized tensors.\n    /// </summary>\n    public interface ITensor\n    {\n        long[] Dim { get; }\n        object GetValue(params long[] v);\n        void SetValue(object value, params long[] v);\n    }\n\n    /// <summary>\n    /// Generic Interface for NxMxLXK-dimensional volume of Type T.\n    /// The indexer of this interface has arguments of type long.\n    /// </summary>\n    public interface ITensor4<T> : ITensor4\n    {\n        T this[long x, long y, long z, long w] { get; set; }\n        T this[V4l v] { get; set; }\n    }\n\n    /// <summary>\n    /// Generic Interface for arbitrarily sized tensors of Type T.\n    /// The indexer of this interface has arguments of type long.\n    /// </summary>\n    public interface ITensor<T> : ITensor\n    {\n        int Rank { get; }\n        T this[params long[] v] { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/IValidity.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public interface IValidity\n    {\n        bool IsValid { get; }\n        bool IsInvalid { get; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/IVector.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Non-generic Interface for Dim - dimensional vectors.\n    /// \n    /// </summary>\n    public interface IVector\n    {\n        long Dim { get; }\n        object GetValue(long index);\n        void SetValue(object value, long index);\n    }\n\n    /// <summary>\n    /// Generic Interface for N-dimensional vector of Type T.\n    /// The indexer of this interface has arguments of type long.\n    /// </summary>\n    public interface IVector<T> : IVector\n    {\n        T this[long i] { get; set; }\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces/IVolume.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// Non-generic Interface for Dim.X x Dim.Y x Dim.Z - dimensional volumes.\n    /// </summary>\n    public interface IVolume\n    {\n        V3l Dim { get; }\n        object GetValue(long x, long y, long z);\n        void SetValue(object value, long x, long y, long z);\n        object GetValue(V3l v);\n        void SetValue(object value, V3l v);\n    }\n\n    /// <summary>\n    /// Generic Interface for NxMxL-dimensional volume of Type T.\n    /// The indexer of this interface has arguments of type long.\n    /// </summary>\n    public interface IVolume<T> : IVolume\n    {\n        T this[long x, long y, long z] { get; set; }\n        T this[V3l v] { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interfaces.cs",
    "content": "﻿//namespace Aardvark.Base\n//{\n//    #region IMutablePolygon<T>\n\n//    public interface IMutablePolygon<T> : IPolygon<T>\n//    {\n//        void Set(int index, T value);\n//    }\n\n//    #endregion\n//}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interpolation/Interpolation.cs",
    "content": "﻿using System;\nusing Ex = System.Linq.Expressions.Expression;\n\nnamespace Aardvark.Base\n{\n    #region Ipol\n\n    public static partial class Ipol\n    {\n        #region Generators\n\n        public static Func<U, T> Generate<T, U>(\n            T a, T b, Func<T, T, U, T> interpolator)\n        {\n            return Ipol<T, U>.Generate(a, b, interpolator);\n        }\n\n        public static Func<U, T> Generate<T, U>(\n            T a, T b, T c, T d, Func<T, T, T, T, U, T> interpolator)\n        {\n            return Ipol<T, U>.Generate(a, b, c, d, interpolator);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Ipol<T, U>\n\n    public static class Ipol<T, U>\n    {\n        internal static Func<T, T, U, T> s_lerpInterpolator;\n\n        #region Generators\n\n        public static Func<U, T> Generate(\n            T a, T b, Func<T, T, U, T> interpolator)\n        {\n            return x => interpolator(a, b, x);\n        }\n\n        public static Func<U, T> Generate(\n            T a, T b, T c, T d, Func<T, T, T, T, U, T> interpolator)\n        {\n            return x => interpolator(a, b, c, d, x);\n        }\n\n        #endregion\n\n        #region Linear Interpolation\n\n        /// <summary>\n        /// Gets a function that performs linear interpolation for values of T:\n        /// (T a, T b, U t) => a * (1 - t) + b * t.\n        /// For t = 0.0 the funtion will return a, and for t = 1.0 the function will return b.\n        /// </summary>\n        public static Func<T, T, U, T> Lerp\n        {\n            get\n            {\n                if (s_lerpInterpolator == null)\n                {\n                    var a = Ex.Parameter(typeof(T), \"a\");\n                    var b = Ex.Parameter(typeof(T), \"b\");\n                    var x = Ex.Parameter(typeof(U), \"x\");\n\n                    var expr = Ex.Lambda<Func<T, T, U, T>>(\n                        Ex.Add(\n                            Ex.Multiply(a, Ex.Subtract(Ex.Constant(1.0), x)),\n                            Ex.Multiply(b, x)\n                            ),\n\n                        a, b, x\n                        );\n                    s_lerpInterpolator = expr.Compile();\n                }\n\n                return s_lerpInterpolator;\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Interpolation/Mapping.cs",
    "content": "﻿using System;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public static class Mapping\n    {\n        /// <summary>\n        /// [-inf, +inf] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> Trunc = x => x < 0 ? 0 : (x > 1 ? 1 : x);\n\n        /// <summary>\n        /// [-inf, +inf] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> Repeat = x => x - Floor(x);\n\n        /// <summary>\n        /// [-inf, +inf] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> RepeatAndMirror = x =>\n        {\n            x = x - Floor(x * 0.5) * 2;\n            return x < 1 ? x : 2 - x;\n        };\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> Linear = x => x;\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> Cosine = x => (1 - Cos(x * PI)) * 0.5;\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> EaseIn = x => Pow(x, 1.3);\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> EaseOut = x => 1 - EaseIn(1 - x);\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> EaseInEaseOut = Cosine;\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> Min = x => 0;\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> Max = x => 1;\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> JumpStart = x => x > 0 ? 1 : 0;\n\n        /// <summary>\n        /// [0, 1] => [0, 1]\n        /// </summary>\n        public static readonly Func<double, double> JumpStop = x => x < 1 ? 0 : 1;\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/LuFactorization.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static partial class NumericExtensions\n    {\n        #region Partially pivoting LU factorization of float[,] arrays\n\n        // Note that this version of the LU factorization is mostly provided\n        // for studying the algorithm. In practice the Matrix<float> version\n        // is noticeably faster, since it performs incremental indexing.\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix, i.e A = inv(P) LU, so that any matrix equation A x = b\n        /// can be solved using LU x = P b. The permutation matrix P is\n        /// returns as permutation vector. WARNING: the supplied matrix A is\n        /// overwritten with its factorization LU, both in the parameter alu.\n        /// If the matrix is singular an ArgumentException is thrown.\n        /// </summary>\n        public static int[] LuFactorize(this float[,] alu)\n        {\n            int n = Fun.Min(alu.GetLength(0), alu.GetLength(1));\n            int[] perm = new int[n];\n            if (alu.LuFactorize(perm)) return perm;\n            throw new ArgumentException(\"singular matrix\");\n        }\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix, i.e A = inv(P) LU, so that any matrix equation A x = b\n        /// can be solved using LU x = P b. The permutation matrix P is\n        /// filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned.\n        /// </summary>\n        public static bool LuFactorize(this float[,] alu, int[] p)\n        {\n            int n = p.Length;\n            p.SetByIndex(i => i);\n            for (int k = 0; k < n - 1; k++)\n            {\n                int pi = k;\n                float pivot = alu[pi, k], absPivot = Fun.Abs(pivot);\n                for (int i = k + 1; i < n; i++)\n                {\n                    float value = alu[i, k], absValue = Fun.Abs(value);\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot)) return false;\n                if (pi != k)\n                {\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (int i = 0; i < n; i++)\n                        Fun.Swap(ref alu[pi, i], ref alu[k, i]);\n                }\n                for (int j = k + 1; j < n; j++)\n                {\n                    float factor = alu[j, k] / pivot;\n                    alu[j, k] = factor; // construct L\n                    for (int i = k + 1; i < n; i++)\n                        alu[j, i] -= alu[k, i] * factor;\n                }\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The returned x satisfies the equation.\n        /// </summary>\n        public static float[] LuSolve(this float[,] lu, int[] p, float[] b)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            if (n > b.GetLength(0)) throw new ArgumentException();\n            var x = new float[n];\n            lu.LuSolve(p, b, x);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The result vector that satisfies the\n        /// equation is filled into the supplied parameter x.\n        /// </summary>\n        public static void LuSolve(this float[,] lu, int[] p, float[] b, float[] x)\n        {\n            int n = p.Length;\n            for (int i = 0; i < n; i++) x[i] = b[p[i]];\n\n            for (int j = 1; j < n; j++)\n            {\n                float scalar = x[j];\n                for (int i = 0; i < j; i++) scalar -= lu[j, i] * x[i];\n                x[j] = scalar;\n            }\n\n            for (int j = n - 1; j >= 0; j--)\n            {\n                float scalar = x[j];\n                for (int i = j + 1; i < n; i++) scalar -= lu[j, i] * x[i];\n                x[j] = scalar / lu[j, j];\n            }\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The returned matrix x satisfies the equation.\n        /// </summary>\n        public static float[,] LuSolve(this float[,] lu, int[] p, float[,] b)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            if (n > b.GetLength(0)) throw new ArgumentException();\n            int m = b.GetLength(1);\n            float[,] x = new float[n, m];\n            lu.LuSolve(p, b, x);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The result matrix that satisfies the equation is filled into the\n        /// supplied parameter x.\n        /// </summary>\n        public static void LuSolve(this float[,] lu, int[] p, float[,] b, float[,] x)\n        {\n            int n = p.Length;\n            int m = b.GetLength(1);\n            for (int j = 0; j < n; j++)\n                for (int i = 0; i < m; i++)\n                    x[j, i] = b[p[j], i];\n\n            for (int k = 1; k < n; k++)\n                for (int j = 0; j < k; j++)\n                    for (int i = 0; i < m; i++)\n                        x[k, i] -= lu[k, j] * x[j, i];\n\n            for (int k = n - 1; k >= 0; k--)\n            {\n                for (int j = k + 1; j < n; j++)\n                    for (int i = 0; i < m; i++)\n                        x[k, i] -= lu[k, j] * x[j, i];\n                var factor = lu[k, k]; // storing the inverse would increase the mean error\n                for (int i = 0; i < m; i++)\n                    x[k, i] /= factor;\n            }\n        }\n\n        /// <summary>\n        /// Return the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p.\n        /// </summary>\n        public static float[,] LuInverse(this float[,] lu, int[] p)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            float[,] inv = new float[n, n];\n            lu.LuInverse(p, inv);\n            return inv;\n        }\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The result matrix is filled into the\n        /// supplied matrix.\n        /// </summary>\n        public static void LuInverse(this float[,] lu, int[] p, float[,] inv)\n        {\n            int n = p.Length;\n            for (int j = 0; j < n; j++)\n                for (int i = 0; i < n; i++)\n                    inv[j, i] = p[j] == i ? 1 : 0;\n\n            for (int k = 1; k < n; k++)\n                for (int j = 0; j < k; j++)\n                    for (int i = 0; i < n; i++)\n                        inv[k, i] -= lu[k, j] * inv[j, i];\n\n            for (int k = n - 1; k >= 0; k--)\n            {\n                for (int j = k + 1; j < n; j++)\n                    for (int i = 0; i < n; i++)\n                        inv[k, i] -= lu[k, j] * inv[j, i];\n                var factor = lu[k, k]; // storing the inverse would increase the mean error\n                for (int i = 0; i < n; i++)\n                    inv[k, i] /= factor;\n            }\n        }\n\n        #endregion\n\n        #region Partially pivoting LU factorization of float[] arrays with offset and strides\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned. No size checks are performed.\n        /// </summary>\n        public static bool LuFactorize(\n                this float[] alu, long a0, long ax, long ay, int[] p)\n        {\n            long n = p.LongLength;\n            p.SetByIndex(i => i);\n            for (long k = 0, ak = a0, a_k = 0; k < n - 1; k++, ak += ay, a_k += ax)\n            {\n                long pi = k;\n                float pivot = alu[ak + a_k], absPivot = Fun.Abs(pivot);\n                for (long i = k + 1, aik = ak + ay + a_k; i < n; i++, aik += ay)\n                {\n                    float value = alu[aik], absValue = Fun.Abs(value);\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot)) return false;\n                if (pi != k)\n                {\n                    long api = a0 + pi * ay;\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (long i = 0, apii = api, aki = ak; i < n; i++, apii += ax, aki += ax)\n                        Fun.Swap(ref alu[apii], ref alu[aki]);\n                }\n                for (long j = k + 1, aj = ak + ay, ajk = aj + a_k; j < n; j++, aj += ay, ajk += ay)\n                {\n                    float factor = alu[ajk] / pivot; alu[ajk] = factor;\n                    for (long i = k + 1, aji = ajk + ax, aki = ak + a_k + ax; i < n; i++, aji += ax, aki += ax)\n                        alu[aji] -= alu[aki] * factor;\n                }\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector starting at b0 with element to element\n        /// delta bD. The result vector that satisfies the equation is\n        /// filled into the supplied parameter x beginning at index x0\n        /// with element to element delta xD.\n        /// </summary>\n        public static void LuSolve(\n                this float[] lu, long l0, long lx, long ly, int[] p,\n                float[] b, long b0, long bd, float[] x, long x0, long xd)\n        {\n            long n = p.LongLength;\n            for (long i = 0, xi = x0; i < n; i++, xi += xd)\n                x[xi] = b[b0 + p[i] * bd];\n\n            for (long j = 1, xj = x0 + xd, lj = l0 + ly; j < n; j++, xj += xd, lj += ly)\n            {\n                float scalar = x[xj];\n                for (long i = 0, lji = lj, xi = x0; i < j; i++, lji += lx, xi += xd)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar;\n            }\n\n            for (long j = n - 1, xj = x0 + j * xd, lj = l0 + j * ly, ljj = lj + j * lx;\n                 j >= 0; j--, xj -= xd, lj -= ly, ljj -= ly + lx)\n            {\n                float scalar = x[xj];\n                for (long i = j + 1, xi = xj + xd, lji = ljj + lx; i < n; i++, xi += xd, lji += lx)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar / lu[ljj];\n            }\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The result matrix that satisfies the equation is filled into the\n        /// supplied parameter x.\n        /// </summary>\n        public static void LuSolve(\n                this float[] lu, long l0, long lx, long ly, int[] p,\n                long m, float[] b, long b0, long bx, long by,\n                float[] x, long x0, long xx, long xy)\n        {\n            int n = p.Length;\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, bpji = b0 + p[j] * by, xji = xj; i < m; i++, bpji += bx, xji += xx)\n                    x[xji] = b[bpji];\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < m; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < m; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < m; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The inverse matrix is filled into the\n        /// supplied matrix x.\n        /// </summary>\n        public static void LuInverse(\n                this float[] lu, long l0, long lx, long ly, int[] p,\n                float[] x, long x0, long xx, long xy)\n        {\n            int n = p.Length;\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, xji = xj; i < n; i++, xji += xx)\n                    x[xji] = p[j] == i ? 1 : 0;\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < n; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n        #endregion\n\n\n        #region Partially pivoting LU factorization of float* pointers with offset and strides\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned. No size checks are performed.\n        /// </summary>\n        public static unsafe bool LuFactorize(\n                float* alu, long a0, long ax, long ay, int* p, long n)\n        {\n            for (long i = 0; i < n; i++) p[i] = (int)i;\n\n            for (long k = 0, ak = a0, a_k = 0; k < n - 1; k++, ak += ay, a_k += ax)\n            {\n                long pi = k;\n                float pivot = alu[ak + a_k], absPivot = Fun.Abs(pivot);\n                for (long i = k + 1, aik = ak + ay + a_k; i < n; i++, aik += ay)\n                {\n                    float value = alu[aik], absValue = Fun.Abs(value);\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot)) return false;\n                if (pi != k)\n                {\n                    long api = a0 + pi * ay;\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (long i = 0, apii = api, aki = ak; i < n; i++, apii += ax, aki += ax)\n                        Fun.Swap(ref alu[apii], ref alu[aki]);\n                }\n                for (long j = k + 1, aj = ak + ay, ajk = aj + a_k; j < n; j++, aj += ay, ajk += ay)\n                {\n                    float factor = alu[ajk] / pivot; alu[ajk] = factor;\n                    for (long i = k + 1, aji = ajk + ax, aki = ak + a_k + ax; i < n; i++, aji += ax, aki += ax)\n                        alu[aji] -= alu[aki] * factor;\n                }\n            }\n            return true;\n        }\n\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector starting at b0 with element to element\n        /// delta bD. The result vector that satisfies the equation is\n        /// filled into the supplied parameter x beginning at index x0\n        /// with element to element delta xD.\n        /// </summary>\n        public static unsafe void LuSolve(\n                float* lu, long l0, long lx, long ly, int* p,\n                float* b, long b0, long bd, float* x, long x0, long xd, long n)\n        {\n            for (long i = 0, xi = x0; i < n; i++, xi += xd)\n                x[xi] = b[b0 + p[i] * bd];\n\n            for (long j = 1, xj = x0 + xd, lj = l0 + ly; j < n; j++, xj += xd, lj += ly)\n            {\n                float scalar = x[xj];\n                for (long i = 0, lji = lj, xi = x0; i < j; i++, lji += lx, xi += xd)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar;\n            }\n\n            for (long j = n - 1, xj = x0 + j * xd, lj = l0 + j * ly, ljj = lj + j * lx;\n                 j >= 0; j--, xj -= xd, lj -= ly, ljj -= ly + lx)\n            {\n                float scalar = x[xj];\n                for (long i = j + 1, xi = xj + xd, lji = ljj + lx; i < n; i++, xi += xd, lji += lx)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar / lu[ljj];\n            }\n        }\n\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The inverse matrix is filled into the\n        /// supplied matrix x.\n        /// </summary>\n        public static unsafe void LuInverse(\n                float* lu, long l0, long lx, long ly, int* p,\n                float* x, long x0, long xx, long xy, long n)\n        {\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, xji = xj; i < n; i++, xji += xx)\n                    x[xji] = p[j] == i ? 1 : 0;\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < n; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n\n        #endregion\n\n\n        #region Partially pivoting LU factorization of double[,] arrays\n\n        // Note that this version of the LU factorization is mostly provided\n        // for studying the algorithm. In practice the Matrix<double> version\n        // is noticeably faster, since it performs incremental indexing.\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix, i.e A = inv(P) LU, so that any matrix equation A x = b\n        /// can be solved using LU x = P b. The permutation matrix P is\n        /// returns as permutation vector. WARNING: the supplied matrix A is\n        /// overwritten with its factorization LU, both in the parameter alu.\n        /// If the matrix is singular an ArgumentException is thrown.\n        /// </summary>\n        public static int[] LuFactorize(this double[,] alu)\n        {\n            int n = Fun.Min(alu.GetLength(0), alu.GetLength(1));\n            int[] perm = new int[n];\n            if (alu.LuFactorize(perm)) return perm;\n            throw new ArgumentException(\"singular matrix\");\n        }\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix, i.e A = inv(P) LU, so that any matrix equation A x = b\n        /// can be solved using LU x = P b. The permutation matrix P is\n        /// filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned.\n        /// </summary>\n        public static bool LuFactorize(this double[,] alu, int[] p)\n        {\n            int n = p.Length;\n            p.SetByIndex(i => i);\n            for (int k = 0; k < n - 1; k++)\n            {\n                int pi = k;\n                double pivot = alu[pi, k], absPivot = Fun.Abs(pivot);\n                for (int i = k + 1; i < n; i++)\n                {\n                    double value = alu[i, k], absValue = Fun.Abs(value);\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot)) return false;\n                if (pi != k)\n                {\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (int i = 0; i < n; i++)\n                        Fun.Swap(ref alu[pi, i], ref alu[k, i]);\n                }\n                for (int j = k + 1; j < n; j++)\n                {\n                    double factor = alu[j, k] / pivot;\n                    alu[j, k] = factor; // construct L\n                    for (int i = k + 1; i < n; i++)\n                        alu[j, i] -= alu[k, i] * factor;\n                }\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The returned x satisfies the equation.\n        /// </summary>\n        public static double[] LuSolve(this double[,] lu, int[] p, double[] b)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            if (n > b.GetLength(0)) throw new ArgumentException();\n            var x = new double[n];\n            lu.LuSolve(p, b, x);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The result vector that satisfies the\n        /// equation is filled into the supplied parameter x.\n        /// </summary>\n        public static void LuSolve(this double[,] lu, int[] p, double[] b, double[] x)\n        {\n            int n = p.Length;\n            for (int i = 0; i < n; i++) x[i] = b[p[i]];\n\n            for (int j = 1; j < n; j++)\n            {\n                double scalar = x[j];\n                for (int i = 0; i < j; i++) scalar -= lu[j, i] * x[i];\n                x[j] = scalar;\n            }\n\n            for (int j = n - 1; j >= 0; j--)\n            {\n                double scalar = x[j];\n                for (int i = j + 1; i < n; i++) scalar -= lu[j, i] * x[i];\n                x[j] = scalar / lu[j, j];\n            }\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The returned matrix x satisfies the equation.\n        /// </summary>\n        public static double[,] LuSolve(this double[,] lu, int[] p, double[,] b)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            if (n > b.GetLength(0)) throw new ArgumentException();\n            int m = b.GetLength(1);\n            double[,] x = new double[n, m];\n            lu.LuSolve(p, b, x);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The result matrix that satisfies the equation is filled into the\n        /// supplied parameter x.\n        /// </summary>\n        public static void LuSolve(this double[,] lu, int[] p, double[,] b, double[,] x)\n        {\n            int n = p.Length;\n            int m = b.GetLength(1);\n            for (int j = 0; j < n; j++)\n                for (int i = 0; i < m; i++)\n                    x[j, i] = b[p[j], i];\n\n            for (int k = 1; k < n; k++)\n                for (int j = 0; j < k; j++)\n                    for (int i = 0; i < m; i++)\n                        x[k, i] -= lu[k, j] * x[j, i];\n\n            for (int k = n - 1; k >= 0; k--)\n            {\n                for (int j = k + 1; j < n; j++)\n                    for (int i = 0; i < m; i++)\n                        x[k, i] -= lu[k, j] * x[j, i];\n                var factor = lu[k, k]; // storing the inverse would increase the mean error\n                for (int i = 0; i < m; i++)\n                    x[k, i] /= factor;\n            }\n        }\n\n        /// <summary>\n        /// Return the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p.\n        /// </summary>\n        public static double[,] LuInverse(this double[,] lu, int[] p)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            double[,] inv = new double[n, n];\n            lu.LuInverse(p, inv);\n            return inv;\n        }\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The result matrix is filled into the\n        /// supplied matrix.\n        /// </summary>\n        public static void LuInverse(this double[,] lu, int[] p, double[,] inv)\n        {\n            int n = p.Length;\n            for (int j = 0; j < n; j++)\n                for (int i = 0; i < n; i++)\n                    inv[j, i] = p[j] == i ? 1 : 0;\n\n            for (int k = 1; k < n; k++)\n                for (int j = 0; j < k; j++)\n                    for (int i = 0; i < n; i++)\n                        inv[k, i] -= lu[k, j] * inv[j, i];\n\n            for (int k = n - 1; k >= 0; k--)\n            {\n                for (int j = k + 1; j < n; j++)\n                    for (int i = 0; i < n; i++)\n                        inv[k, i] -= lu[k, j] * inv[j, i];\n                var factor = lu[k, k]; // storing the inverse would increase the mean error\n                for (int i = 0; i < n; i++)\n                    inv[k, i] /= factor;\n            }\n        }\n\n        #endregion\n\n        #region Partially pivoting LU factorization of double[] arrays with offset and strides\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned. No size checks are performed.\n        /// </summary>\n        public static bool LuFactorize(\n                this double[] alu, long a0, long ax, long ay, int[] p)\n        {\n            long n = p.LongLength;\n            p.SetByIndex(i => i);\n            for (long k = 0, ak = a0, a_k = 0; k < n - 1; k++, ak += ay, a_k += ax)\n            {\n                long pi = k;\n                double pivot = alu[ak + a_k], absPivot = Fun.Abs(pivot);\n                for (long i = k + 1, aik = ak + ay + a_k; i < n; i++, aik += ay)\n                {\n                    double value = alu[aik], absValue = Fun.Abs(value);\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot)) return false;\n                if (pi != k)\n                {\n                    long api = a0 + pi * ay;\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (long i = 0, apii = api, aki = ak; i < n; i++, apii += ax, aki += ax)\n                        Fun.Swap(ref alu[apii], ref alu[aki]);\n                }\n                for (long j = k + 1, aj = ak + ay, ajk = aj + a_k; j < n; j++, aj += ay, ajk += ay)\n                {\n                    double factor = alu[ajk] / pivot; alu[ajk] = factor;\n                    for (long i = k + 1, aji = ajk + ax, aki = ak + a_k + ax; i < n; i++, aji += ax, aki += ax)\n                        alu[aji] -= alu[aki] * factor;\n                }\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector starting at b0 with element to element\n        /// delta bD. The result vector that satisfies the equation is\n        /// filled into the supplied parameter x beginning at index x0\n        /// with element to element delta xD.\n        /// </summary>\n        public static void LuSolve(\n                this double[] lu, long l0, long lx, long ly, int[] p,\n                double[] b, long b0, long bd, double[] x, long x0, long xd)\n        {\n            long n = p.LongLength;\n            for (long i = 0, xi = x0; i < n; i++, xi += xd)\n                x[xi] = b[b0 + p[i] * bd];\n\n            for (long j = 1, xj = x0 + xd, lj = l0 + ly; j < n; j++, xj += xd, lj += ly)\n            {\n                double scalar = x[xj];\n                for (long i = 0, lji = lj, xi = x0; i < j; i++, lji += lx, xi += xd)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar;\n            }\n\n            for (long j = n - 1, xj = x0 + j * xd, lj = l0 + j * ly, ljj = lj + j * lx;\n                 j >= 0; j--, xj -= xd, lj -= ly, ljj -= ly + lx)\n            {\n                double scalar = x[xj];\n                for (long i = j + 1, xi = xj + xd, lji = ljj + lx; i < n; i++, xi += xd, lji += lx)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar / lu[ljj];\n            }\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The result matrix that satisfies the equation is filled into the\n        /// supplied parameter x.\n        /// </summary>\n        public static void LuSolve(\n                this double[] lu, long l0, long lx, long ly, int[] p,\n                long m, double[] b, long b0, long bx, long by,\n                double[] x, long x0, long xx, long xy)\n        {\n            int n = p.Length;\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, bpji = b0 + p[j] * by, xji = xj; i < m; i++, bpji += bx, xji += xx)\n                    x[xji] = b[bpji];\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < m; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < m; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < m; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The inverse matrix is filled into the\n        /// supplied matrix x.\n        /// </summary>\n        public static void LuInverse(\n                this double[] lu, long l0, long lx, long ly, int[] p,\n                double[] x, long x0, long xx, long xy)\n        {\n            int n = p.Length;\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, xji = xj; i < n; i++, xji += xx)\n                    x[xji] = p[j] == i ? 1 : 0;\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < n; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n        #endregion\n\n\n        #region Partially pivoting LU factorization of double* pointers with offset and strides\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned. No size checks are performed.\n        /// </summary>\n        public static unsafe bool LuFactorize(\n                double* alu, long a0, long ax, long ay, int* p, long n)\n        {\n            for (long i = 0; i < n; i++) p[i] = (int)i;\n\n            for (long k = 0, ak = a0, a_k = 0; k < n - 1; k++, ak += ay, a_k += ax)\n            {\n                long pi = k;\n                double pivot = alu[ak + a_k], absPivot = Fun.Abs(pivot);\n                for (long i = k + 1, aik = ak + ay + a_k; i < n; i++, aik += ay)\n                {\n                    double value = alu[aik], absValue = Fun.Abs(value);\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot)) return false;\n                if (pi != k)\n                {\n                    long api = a0 + pi * ay;\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (long i = 0, apii = api, aki = ak; i < n; i++, apii += ax, aki += ax)\n                        Fun.Swap(ref alu[apii], ref alu[aki]);\n                }\n                for (long j = k + 1, aj = ak + ay, ajk = aj + a_k; j < n; j++, aj += ay, ajk += ay)\n                {\n                    double factor = alu[ajk] / pivot; alu[ajk] = factor;\n                    for (long i = k + 1, aji = ajk + ax, aki = ak + a_k + ax; i < n; i++, aji += ax, aki += ax)\n                        alu[aji] -= alu[aki] * factor;\n                }\n            }\n            return true;\n        }\n\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector starting at b0 with element to element\n        /// delta bD. The result vector that satisfies the equation is\n        /// filled into the supplied parameter x beginning at index x0\n        /// with element to element delta xD.\n        /// </summary>\n        public static unsafe void LuSolve(\n                double* lu, long l0, long lx, long ly, int* p,\n                double* b, long b0, long bd, double* x, long x0, long xd, long n)\n        {\n            for (long i = 0, xi = x0; i < n; i++, xi += xd)\n                x[xi] = b[b0 + p[i] * bd];\n\n            for (long j = 1, xj = x0 + xd, lj = l0 + ly; j < n; j++, xj += xd, lj += ly)\n            {\n                double scalar = x[xj];\n                for (long i = 0, lji = lj, xi = x0; i < j; i++, lji += lx, xi += xd)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar;\n            }\n\n            for (long j = n - 1, xj = x0 + j * xd, lj = l0 + j * ly, ljj = lj + j * lx;\n                 j >= 0; j--, xj -= xd, lj -= ly, ljj -= ly + lx)\n            {\n                double scalar = x[xj];\n                for (long i = j + 1, xi = xj + xd, lji = ljj + lx; i < n; i++, xi += xd, lji += lx)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar / lu[ljj];\n            }\n        }\n\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The inverse matrix is filled into the\n        /// supplied matrix x.\n        /// </summary>\n        public static unsafe void LuInverse(\n                double* lu, long l0, long lx, long ly, int* p,\n                double* x, long x0, long xx, long xy, long n)\n        {\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, xji = xj; i < n; i++, xji += xx)\n                    x[xji] = p[j] == i ? 1 : 0;\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < n; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n\n        #endregion\n\n\n\n        #region Partially pivoting LU factorization of ComplexD[,] arrays\n\n        // Note that this version of the LU factorization is mostly provided\n        // for studying the algorithm. In practice the Matrix<ComplexD> version\n        // is noticeably faster, since it performs incremental indexing.\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix, i.e A = inv(P) LU, so that any matrix equation A x = b\n        /// can be solved using LU x = P b. The permutation matrix P is\n        /// returns as permutation vector. WARNING: the supplied matrix A is\n        /// overwritten with its factorization LU, both in the parameter alu.\n        /// If the matrix is singular an ArgumentException is thrown.\n        /// </summary>\n        public static int[] LuFactorize(this ComplexD[,] alu)\n        {\n            int n = Fun.Min(alu.GetLength(0), alu.GetLength(1));\n            int[] perm = new int[n];\n            if (alu.LuFactorize(perm)) return perm;\n            throw new ArgumentException(\"singular matrix\");\n        }\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix, i.e A = inv(P) LU, so that any matrix equation A x = b\n        /// can be solved using LU x = P b. The permutation matrix P is\n        /// filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned.\n        /// </summary>\n        public static bool LuFactorize(this ComplexD[,] alu, int[] p)\n        {\n            int n = p.Length;\n            p.SetByIndex(i => i);\n            for (int k = 0; k < n - 1; k++)\n            {\n                int pi = k;\n                ComplexD pivot = alu[pi, k];\n                double absPivot = pivot.NormSquared;\n                for (int i = k + 1; i < n; i++)\n                {\n                    ComplexD value = alu[i, k];\n                    double absValue = value.NormSquared;\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot.Real) && Fun.IsTiny(pivot.Imag)) return false;\n                if (pi != k)\n                {\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (int i = 0; i < n; i++)\n                        Fun.Swap(ref alu[pi, i], ref alu[k, i]);\n                }\n                for (int j = k + 1; j < n; j++)\n                {\n                    ComplexD factor = alu[j, k] / pivot;\n                    alu[j, k] = factor; // construct L\n                    for (int i = k + 1; i < n; i++)\n                        alu[j, i] -= alu[k, i] * factor;\n                }\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The returned x satisfies the equation.\n        /// </summary>\n        public static ComplexD[] LuSolve(this ComplexD[,] lu, int[] p, ComplexD[] b)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            if (n > b.GetLength(0)) throw new ArgumentException();\n            var x = new ComplexD[n];\n            lu.LuSolve(p, b, x);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The result vector that satisfies the\n        /// equation is filled into the supplied parameter x.\n        /// </summary>\n        public static void LuSolve(this ComplexD[,] lu, int[] p, ComplexD[] b, ComplexD[] x)\n        {\n            int n = p.Length;\n            for (int i = 0; i < n; i++) x[i] = b[p[i]];\n\n            for (int j = 1; j < n; j++)\n            {\n                ComplexD scalar = x[j];\n                for (int i = 0; i < j; i++) scalar -= lu[j, i] * x[i];\n                x[j] = scalar;\n            }\n\n            for (int j = n - 1; j >= 0; j--)\n            {\n                ComplexD scalar = x[j];\n                for (int i = j + 1; i < n; i++) scalar -= lu[j, i] * x[i];\n                x[j] = scalar / lu[j, j];\n            }\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The returned matrix x satisfies the equation.\n        /// </summary>\n        public static ComplexD[,] LuSolve(this ComplexD[,] lu, int[] p, ComplexD[,] b)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            if (n > b.GetLength(0)) throw new ArgumentException();\n            int m = b.GetLength(1);\n            ComplexD[,] x = new ComplexD[n, m];\n            lu.LuSolve(p, b, x);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The result matrix that satisfies the equation is filled into the\n        /// supplied parameter x.\n        /// </summary>\n        public static void LuSolve(this ComplexD[,] lu, int[] p, ComplexD[,] b, ComplexD[,] x)\n        {\n            int n = p.Length;\n            int m = b.GetLength(1);\n            for (int j = 0; j < n; j++)\n                for (int i = 0; i < m; i++)\n                    x[j, i] = b[p[j], i];\n\n            for (int k = 1; k < n; k++)\n                for (int j = 0; j < k; j++)\n                    for (int i = 0; i < m; i++)\n                        x[k, i] -= lu[k, j] * x[j, i];\n\n            for (int k = n - 1; k >= 0; k--)\n            {\n                for (int j = k + 1; j < n; j++)\n                    for (int i = 0; i < m; i++)\n                        x[k, i] -= lu[k, j] * x[j, i];\n                var factor = lu[k, k]; // storing the inverse would increase the mean error\n                for (int i = 0; i < m; i++)\n                    x[k, i] /= factor;\n            }\n        }\n\n        /// <summary>\n        /// Return the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p.\n        /// </summary>\n        public static ComplexD[,] LuInverse(this ComplexD[,] lu, int[] p)\n        {\n            int n = Fun.Min(lu.GetLength(0), lu.GetLength(1));\n            if (n != p.GetLength(0)) throw new ArgumentException();\n            ComplexD[,] inv = new ComplexD[n, n];\n            lu.LuInverse(p, inv);\n            return inv;\n        }\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The result matrix is filled into the\n        /// supplied matrix.\n        /// </summary>\n        public static void LuInverse(this ComplexD[,] lu, int[] p, ComplexD[,] inv)\n        {\n            int n = p.Length;\n            for (int j = 0; j < n; j++)\n                for (int i = 0; i < n; i++)\n                    inv[j, i] = p[j] == i ? 1 : 0;\n\n            for (int k = 1; k < n; k++)\n                for (int j = 0; j < k; j++)\n                    for (int i = 0; i < n; i++)\n                        inv[k, i] -= lu[k, j] * inv[j, i];\n\n            for (int k = n - 1; k >= 0; k--)\n            {\n                for (int j = k + 1; j < n; j++)\n                    for (int i = 0; i < n; i++)\n                        inv[k, i] -= lu[k, j] * inv[j, i];\n                var factor = lu[k, k]; // storing the inverse would increase the mean error\n                for (int i = 0; i < n; i++)\n                    inv[k, i] /= factor;\n            }\n        }\n\n        #endregion\n\n        #region Partially pivoting LU factorization of ComplexD[] arrays with offset and strides\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned. No size checks are performed.\n        /// </summary>\n        public static bool LuFactorize(\n                this ComplexD[] alu, long a0, long ax, long ay, int[] p)\n        {\n            long n = p.LongLength;\n            p.SetByIndex(i => i);\n            for (long k = 0, ak = a0, a_k = 0; k < n - 1; k++, ak += ay, a_k += ax)\n            {\n                long pi = k;\n                ComplexD pivot = alu[ak + a_k];\n                double absPivot = pivot.NormSquared;\n                for (long i = k + 1, aik = ak + ay + a_k; i < n; i++, aik += ay)\n                {\n                    ComplexD value = alu[aik];\n                    double absValue = value.NormSquared;\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot.Real) && Fun.IsTiny(pivot.Imag)) return false;\n                if (pi != k)\n                {\n                    long api = a0 + pi * ay;\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (long i = 0, apii = api, aki = ak; i < n; i++, apii += ax, aki += ax)\n                        Fun.Swap(ref alu[apii], ref alu[aki]);\n                }\n                for (long j = k + 1, aj = ak + ay, ajk = aj + a_k; j < n; j++, aj += ay, ajk += ay)\n                {\n                    ComplexD factor = alu[ajk] / pivot; alu[ajk] = factor;\n                    for (long i = k + 1, aji = ajk + ax, aki = ak + a_k + ax; i < n; i++, aji += ax, aki += ax)\n                        alu[aji] -= alu[aki] * factor;\n                }\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector starting at b0 with element to element\n        /// delta bD. The result vector that satisfies the equation is\n        /// filled into the supplied parameter x beginning at index x0\n        /// with element to element delta xD.\n        /// </summary>\n        public static void LuSolve(\n                this ComplexD[] lu, long l0, long lx, long ly, int[] p,\n                ComplexD[] b, long b0, long bd, ComplexD[] x, long x0, long xd)\n        {\n            long n = p.LongLength;\n            for (long i = 0, xi = x0; i < n; i++, xi += xd)\n                x[xi] = b[b0 + p[i] * bd];\n\n            for (long j = 1, xj = x0 + xd, lj = l0 + ly; j < n; j++, xj += xd, lj += ly)\n            {\n                ComplexD scalar = x[xj];\n                for (long i = 0, lji = lj, xi = x0; i < j; i++, lji += lx, xi += xd)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar;\n            }\n\n            for (long j = n - 1, xj = x0 + j * xd, lj = l0 + j * ly, ljj = lj + j * lx;\n                 j >= 0; j--, xj -= xd, lj -= ly, ljj -= ly + lx)\n            {\n                ComplexD scalar = x[xj];\n                for (long i = j + 1, xi = xj + xd, lji = ljj + lx; i < n; i++, xi += xd, lji += lx)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar / lu[ljj];\n            }\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is a supplied matrix.\n        /// The result matrix that satisfies the equation is filled into the\n        /// supplied parameter x.\n        /// </summary>\n        public static void LuSolve(\n                this ComplexD[] lu, long l0, long lx, long ly, int[] p,\n                long m, ComplexD[] b, long b0, long bx, long by,\n                ComplexD[] x, long x0, long xx, long xy)\n        {\n            int n = p.Length;\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, bpji = b0 + p[j] * by, xji = xj; i < m; i++, bpji += bx, xji += xx)\n                    x[xji] = b[bpji];\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < m; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < m; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < m; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The inverse matrix is filled into the\n        /// supplied matrix x.\n        /// </summary>\n        public static void LuInverse(\n                this ComplexD[] lu, long l0, long lx, long ly, int[] p,\n                ComplexD[] x, long x0, long xx, long xy)\n        {\n            int n = p.Length;\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, xji = xj; i < n; i++, xji += xx)\n                    x[xji] = p[j] == i ? 1 : 0;\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < n; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n        #endregion\n\n        #region Partially pivoting LU factorization of ComplexD* pointers with offset and strides\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is filled into the supplied permutation vector p, and the supplied\n        /// matrix A is overwritten with its factorization LU, both in the\n        /// parameter alu. The function returns true if the factorization\n        /// is successful, otherwise the matrix is singular and false is\n        /// returned. No size checks are performed.\n        /// </summary>\n        public static unsafe bool LuFactorize(\n                ComplexD* alu, long a0, long ax, long ay, int* p, long n)\n        {\n            for (long i = 0; i < n; i++) p[i] = (int)i;\n\n            for (long k = 0, ak = a0, a_k = 0; k < n - 1; k++, ak += ay, a_k += ax)\n            {\n                long pi = k;\n                ComplexD pivot = alu[ak + a_k];\n                double absPivot = pivot.NormSquared;\n                for (long i = k + 1, aik = ak + ay + a_k; i < n; i++, aik += ay)\n                {\n                    ComplexD value = alu[aik];\n                    double absValue = value.NormSquared;\n                    if (absValue > absPivot)\n                    {\n                        pivot = value; absPivot = absValue; pi = i;\n                    }\n                }\n                if (Fun.IsTiny(pivot.Real) && Fun.IsTiny(pivot.Imag)) return false;\n                if (pi != k)\n                {\n                    long api = a0 + pi * ay;\n                    Fun.Swap(ref p[pi], ref p[k]);\n                    for (long i = 0, apii = api, aki = ak; i < n; i++, apii += ax, aki += ax)\n                        Fun.Swap(ref alu[apii], ref alu[aki]);\n                }\n                for (long j = k + 1, aj = ak + ay, ajk = aj + a_k; j < n; j++, aj += ay, ajk += ay)\n                {\n                    ComplexD factor = alu[ajk] / pivot; alu[ajk] = factor;\n                    for (long i = k + 1, aji = ajk + ax, aki = ak + a_k + ax; i < n; i++, aji += ax, aki += ax)\n                        alu[aji] -= alu[aki] * factor;\n                }\n            }\n            return true;\n        }\n\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector starting at b0 with element to element\n        /// delta bD. The result vector that satisfies the equation is\n        /// filled into the supplied parameter x beginning at index x0\n        /// with element to element delta xD.\n        /// </summary>\n        public static unsafe void LuSolve(\n                ComplexD* lu, long l0, long lx, long ly, int* p,\n                ComplexD* b, long b0, long bd, ComplexD* x, long x0, long xd, long n)\n        {\n            for (long i = 0, xi = x0; i < n; i++, xi += xd)\n                x[xi] = b[b0 + p[i] * bd];\n\n            for (long j = 1, xj = x0 + xd, lj = l0 + ly; j < n; j++, xj += xd, lj += ly)\n            {\n                ComplexD scalar = x[xj];\n                for (long i = 0, lji = lj, xi = x0; i < j; i++, lji += lx, xi += xd)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar;\n            }\n\n            for (long j = n - 1, xj = x0 + j * xd, lj = l0 + j * ly, ljj = lj + j * lx;\n                 j >= 0; j--, xj -= xd, lj -= ly, ljj -= ly + lx)\n            {\n                ComplexD scalar = x[xj];\n                for (long i = j + 1, xi = xj + xd, lji = ljj + lx; i < n; i++, xi += xd, lji += lx)\n                    scalar -= lu[lji] * x[xi];\n                x[xj] = scalar / lu[ljj];\n            }\n        }\n\n\n        /// <summary>\n        /// Compute the inverse inv(A) of a the supplied LU factorized matrix\n        /// lu, where A = inv(P) LU. The permuation matrix P is supplied as\n        /// the permutation vector p. The inverse matrix is filled into the\n        /// supplied matrix x.\n        /// </summary>\n        public static unsafe void LuInverse(\n                ComplexD* lu, long l0, long lx, long ly, int* p,\n                ComplexD* x, long x0, long xx, long xy, long n)\n        {\n            for (long j = 0, xj = x0; j < n; j++, xj += xy)\n                for (long i = 0, xji = xj; i < n; i++, xji += xx)\n                    x[xji] = p[j] == i ? 1 : 0;\n\n            for (long k = 1, xk = x0 + xy, lk = l0 + ly; k < n; k++, xk += xy, lk += ly)\n                for (long j = 0, xj = x0, lkj = lk; j < k; j++, xj += xy, lkj += lx)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n\n            for (long k = n - 1, xk = x0 + k * xy, lk = l0 + k * ly, lkk = lk + k * lx;\n                 k >= 0; k--, xk -= xy, lk -= ly, lkk -= ly + lx)\n            {\n                for (long j = k + 1, lkj = lkk + lx, xj = xk + xy; j < n; j++, lkj += lx, xj += xy)\n                    for (long i = 0, xki = xk, xji = xj; i < n; i++, xki += xx, xji += xx)\n                        x[xki] -= lu[lkj] * x[xji];\n                var factor = lu[lkk]; // storing the inverse would increase the mean error\n                for (long i = 0, xki = xk; i < n; i++, xki += xx)\n                    x[xki] /= factor;\n            }\n        }\n\n\n        #endregion\n\n\n\n\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Numerics/CovarianceMatrix.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Covariance matrix.\n    /// </summary>\n    public static class CovarianceMatrixExtensions\n    {\n        #region V3d\n\n        /// <summary>\n        /// Computes outer product (tensor product) of vector v with itself.\n        /// </summary>\n        public static M33d OuterProduct(this in V3d v) => new M33d(\n            v.X * v.X, v.X * v.Y, v.X * v.Z,\n            v.Y * v.X, v.Y * v.Y, v.Y * v.Z,\n            v.Z * v.X, v.Z * v.Y, v.Z * v.Z\n            );\n\n        /// <summary>\n        /// Adds outer product (tensor product) of vector v with itself to matrix m.\n        /// </summary>\n        public static void AddOuterProduct(this ref M33d m, in V3d v)\n        {\n            m.M00 += v.X * v.X; m.M01 += v.X * v.Y; m.M02 += v.X * v.Z;\n            m.M10 += v.Y * v.X; m.M11 += v.Y * v.Y; m.M12 += v.Y * v.Z;\n            m.M20 += v.Z * v.X; m.M21 += v.Z * v.Y; m.M22 += v.Z * v.Z;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix for given points.\n        /// </summary>\n        public static M33d ComputeCovarianceMatrix(this V3d[] points)\n        {\n            var cvm = M33d.Zero;\n            for (var i = 0; i < points.Length; i++) cvm.AddOuterProduct(points[i]);\n            return cvm / points.Length;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix for points given by indices into points array.\n        /// </summary>\n        public static M33d ComputeCovarianceMatrix(this V3d[] points, int[] indices)\n        {\n            var cvm = M33d.Zero;\n            for (var i = 0; i < indices.Length; i++) cvm.AddOuterProduct(points[indices[i]]);\n            return cvm / indices.Length;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix from points relative to given center.\n        /// </summary>\n        public static M33d ComputeCovarianceMatrix(this V3d[] points, V3d center)\n        {\n            var cvm = M33d.Zero;\n            for (var i = 0; i < points.Length; i++) cvm.AddOuterProduct(points[i] - center);\n            return cvm / points.Length;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix for points given by indices into points array, relative to given center.\n        /// </summary>\n        public static M33d ComputeCovarianceMatrix(this V3d[] points, int[] indices, V3d center)\n        {\n            var cvm = M33d.Zero;\n            for (var i = 0; i < indices.Length; i++) cvm.AddOuterProduct(points[indices[i]] - center);\n            return cvm / indices.Length;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix for given points.\n        /// </summary>\n        public static M33d ComputeCovarianceMatrix(this IEnumerable<V3d> points)\n        {\n            var count = 0;\n            var cvm = M33d.Zero;\n            foreach (var p in points) { cvm.AddOuterProduct(p); count++; }\n            return cvm / count;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix from points relative to given center.\n        /// </summary>\n        public static M33d ComputeCovarianceMatrix(this IEnumerable<V3d> points, V3d center)\n        {\n            var count = 0;\n            var cvm = M33d.Zero;\n            foreach (var p in points) { cvm.AddOuterProduct(p - center); count++; }\n            return cvm / count;\n        }\n\n        #endregion\n\n        #region V3f\n\n        /// <summary>\n        /// Computes outer product (tensor product) of vector v with itself.\n        /// </summary>\n        public static M33f OuterProduct(this in V3f v) => new M33f(\n            v.X * v.X, v.X * v.Y, v.X * v.Z,\n            v.Y * v.X, v.Y * v.Y, v.Y * v.Z,\n            v.Z * v.X, v.Z * v.Y, v.Z * v.Z\n            );\n\n        /// <summary>\n        /// Adds outer product (tensor product) of vector v with itself to matrix m.\n        /// </summary>\n        public static void AddOuterProduct(this ref M33f m, in V3f v)\n        {\n            m.M00 += v.X * v.X; m.M01 += v.X * v.Y; m.M02 += v.X * v.Z;\n            m.M10 += v.Y * v.X; m.M11 += v.Y * v.Y; m.M12 += v.Y * v.Z;\n            m.M20 += v.Z * v.X; m.M21 += v.Z * v.Y; m.M22 += v.Z * v.Z;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix for given points.\n        /// </summary>\n        public static M33f ComputeCovarianceMatrix(this V3f[] points)\n        {\n            var cvm = M33f.Zero;\n            for (var i = 0; i < points.Length; i++) cvm.AddOuterProduct(points[i]);\n            return cvm / points.Length;\n        }\n        \n        /// <summary>\n        /// Computes covariance matrix for points given by indices into points array.\n        /// </summary>\n        public static M33f ComputeCovarianceMatrix(this V3f[] points, int[] indices)\n        {\n            var cvm = M33f.Zero;\n            for (var i = 0; i < indices.Length; i++) cvm.AddOuterProduct(points[indices[i]]);\n            return cvm / indices.Length;\n        }\n        \n        /// <summary>\n        /// Computes covariance matrix from points relative to given center.\n        /// </summary>\n        public static M33f ComputeCovarianceMatrix(this V3f[] points, V3f center)\n        {\n            var cvm = M33f.Zero;\n            for (var i = 0; i < points.Length; i++) cvm.AddOuterProduct(points[i] - center);\n            return cvm / points.Length;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix for points given by indices into points array, relative to given center.\n        /// </summary>\n        public static M33f ComputeCovarianceMatrix(this V3f[] points, int[] indices, V3f center)\n        {\n            var cvm = M33f.Zero;\n            for (var i = 0; i < indices.Length; i++) cvm.AddOuterProduct(points[indices[i]] - center);\n            return cvm / indices.Length;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix for given points.\n        /// </summary>\n        public static M33f ComputeCovarianceMatrix(this IEnumerable<V3f> points)\n        {\n            var count = 0;\n            var cvm = M33f.Zero;\n            foreach (var p in points) { cvm.AddOuterProduct(p); count++; }\n            return cvm / count;\n        }\n\n        /// <summary>\n        /// Computes covariance matrix from points relative to given center.\n        /// </summary>\n        public static M33f ComputeCovarianceMatrix(this IEnumerable<V3f> points, V3f center)\n        {\n            var count = 0;\n            var cvm = M33f.Zero;\n            foreach (var p in points) { cvm.AddOuterProduct(p - center); count++; }\n            return cvm / count;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Numerics/Polynomial.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\n\nnamespace Aardvark.Base\n{\n    public static class Polynomial\n    {\n        /// <summary>\n        /// Return the polynomial derivative of the supplied polynomial that\n        /// is stored with ascending coefficients:\n        /// coeff[0] + coeff[1] x + coeff[2] x^2 + ... + coeff[n-1] x^(n-1)\n        /// </summary>\n        public static double[] Derivative(this double[] coeff)\n        {\n            int len = coeff.Length - 1;\n            if (len < 1) throw new ArgumentException();\n            var r = new double[len];\n            r[0] = coeff[1]; if (len < 2) return r;\n            for (int i = 1, j = 2; i < len; i = j++)\n                r[i] = j * coeff[j];\n            return r;\n        }\n\n        /// <summary>\n        /// Return the polynomial product of two polynomials that are supplied\n        /// with ascending coefficients:\n        /// ( c0[0] + c0[1] x + c0[2] x^2 + ... + c0[n-1] x^(n-1) )\n        /// * ( c1[0] + c1[1] x + c1[2] x^2 + ... + c1[n-1] x^(n-1) )\n        /// </summary>\n        public static double[] Multiply(this double[] c0, double[] c1)\n        {\n            int l0 = c0.Length;\n            int l1 = c1.Length;\n            var r = new double[l0 + l1 - 1].Set(0.0);\n            for (int i0 = 0; i0 < l0; i0++)\n                for (int i1 = 0; i1 < l1; i1++)\n                    r[i0 + i1] += c0[i0] * c1[i1];\n            return r;\n        }\n\n        /// <summary>\n        /// Evaluate the supplied polynomial that is stored with ascending\n        /// coefficients at the supplied agrument x:\n        /// coeff[0] + coeff[1] x + coeff[2] x^2 + ... + coeff[n-1] x^(n-1)\n        /// </summary>\n        public static double Evaluate(this double[] coeff, double x)\n        {\n            int i = coeff.Length - 1;\n            if (i < 0) throw new ArgumentException();\n            double value = coeff[i--];\n            while (i >= 0) value = x * value + coeff[i--];\n            return value;\n        }\n\n        /// <summary>\n        /// Evaluate the derivative of the supplied polynomial that is stored\n        /// with ascending coefficients at the supplied agrument x:\n        /// coeff[1] + 2 coeff[2] x + ... + (n-1) coeff[n-1] x^(n-2)\n        /// </summary>\n        public static double EvaluateDerivative(this double[] coeff, double x)\n        {\n            int i = coeff.Length - 1;\n            if (i < 0) throw new ArgumentException();\n            double value = i * coeff[i];\n            --i;\n            while (i > 0) { value = x * value + i * coeff[i]; --i; }\n            return value;\n        }\r\n\r\n#if !TRAVIS_CI\n        /// <summary>\n        /// Return the real roots of the supplied polynomial, that is stored\n        /// with ascending coefficients:\n        /// coeff[0] + coeff[1] x + coeff[2] x^2 + ... + coeff[n-1] x^(n-1)\n        /// Note that double and triple roots are returned as repeated values.\n        /// WARNING: currently only polynomials up to the 4th order can be solved.\n        /// </summary>\n        public static double[] RealRoots(this double[] coeff)\n        {\n            switch (coeff.Length)\n            {\n                case 0:\n                case 1:\n                        return Array.Empty<double>();\n                case 2: return RealRootOf(coeff[1], coeff[0]).NonNanToArray();\n                case 3: return RealRootsOf(coeff[2], coeff[1], coeff[0])\n                                       .NonNanToArray();\n                case 4: return RealRootsOf(coeff[3], coeff[2], coeff[1], coeff[0])\n                                       .NonNanToArray();\n                case 5: return RealRootsOf(coeff[4], coeff[3], coeff[2],\n                                       coeff[1], coeff[0]).NonNanToArray();\n                default: throw new NotImplementedException();\n            }\n        }\n\n        /// <summary>\n        /// Return the real roots of the supplied normalized polynomial, that\n        /// is stored with ascending coefficients:\n        /// coeff[0] + coeff[1] x + coeff[2] x^2 + coeff[3] x^3 ... + x^n\n        /// The last coefficient with value 1.0 must not be part of the\n        /// supplied array.\n        /// Note that double and triple roots are returned as repeated values.\n        /// WARNING: currently only polynomials up to the 4th order can be solved.\n        /// </summary>\n        public static double[] RealRootsNormed(this double[] coeff)\n        {\n            switch (coeff.Length)\n            {\n                case 0: return Array.Empty<double>();\n                case 1: return RealRootOfNormed(coeff[0]).IntoArray();\n                case 2: return RealRootsOfNormed(coeff[1], coeff[0])\n                                             .NonNanToArray();\n                case 3: return RealRootsOfNormed(coeff[2], coeff[1], coeff[0])\n                                             .NonNanToArray();\n                case 4: return RealRootsOfNormed(coeff[3], coeff[2], coeff[1],\n                                                 coeff[0]).NonNanToArray();\n                default: throw new NotImplementedException();\n            }\n        }\n#endif\n\r\n        private static double[] NonNanToArray(this double root)\n        {\n            if (double.IsNaN(root)) return Array.Empty<double>();\n            return new double[] { root };\n        }\n\n        private static double[] NonNanToArray(this (double, double) p)\n        {\n            if (double.IsNaN(p.Item1))\n            {\n                if (double.IsNaN(p.Item2)) return Array.Empty<double>();\n                return new double[] { p.Item2 };\n            }\n            if (double.IsNaN(p.Item2)) return new double[] { p.Item1 };\n            return new double[] { p.Item1, p.Item2 };\n        }\n\n        private static double[] NonNanToArray(this (double, double, double) t)\n        {\n            int c = 0;\n            bool v0 = !double.IsNaN(t.Item1); if (v0) c++;\n            bool v1 = !double.IsNaN(t.Item2); if (v1) c++;\n            bool v2 = !double.IsNaN(t.Item3); if (v2) c++;\n            var a = new double[c];\n            if (v2) a[--c] = t.Item3;\n            if (v1) a[--c] = t.Item2;\n            if (v0) a[--c] = t.Item1;\n            return a;\n        }\n\n        private static double[] NonNanToArray(this (double, double, double, double) q)\n        {\n            int c = 0;\n            bool v0 = !double.IsNaN(q.Item1); if (v0) c++;\n            bool v1 = !double.IsNaN(q.Item2); if (v1) c++;\n            bool v2 = !double.IsNaN(q.Item3); if (v2) c++;\n            bool v3 = !double.IsNaN(q.Item4); if (v3) c++;\n            var a = new double[c];\n            if (v3) a[--c] = q.Item4;\n            if (v2) a[--c] = q.Item3;\n            if (v1) a[--c] = q.Item2;\n            if (v0) a[--c] = q.Item1;\n            return a;\n        }\n\n        /// <summary>\n        /// Return root of the equation ax + b = 0.\n        /// Returns NaN if no root exists (a = 0).\n        /// </summary>\n        public static double RealRootOf(double a, double b)\n        {\n            if (Fun.IsTiny(a)) return double.NaN;\n            return -b / a;\n        }\n\n        /// <summary>\n        /// Return -p as the root of x + p = 0.\n        /// </summary>\n        public static double RealRootOfNormed(double p)\n        {\n            return -p;\n        }\n\n        /// <summary>\n        /// Return real roots of the equation ax^2 + bx + c = 0.\n        /// Double roots are returned as a pair of identical values.\n        /// If only one (linear) roots exists, it is stored in the first\n        /// entry and the second entry is NaN.\n        /// If no real roots exists, then both entries are NaN.\n        /// </summary>\n        public static (double, double) RealRootsOf(double a, double b, double c)\n        {\n            if (Fun.IsTiny(a))\n            {\n                if (Fun.IsTiny(b))\n                    return (double.NaN, double.NaN);\n                return (-c / b, double.NaN);\n            }\n            var r = b * b - 4 * a * c;\n            if (r < 0)\n                return (double.NaN, double.NaN);\n            if (b < 0)                                 // prevent cancellation\n            {\n                double d = -b + Fun.Sqrt(r);\n                return (2 * c / d, d / (2 * a));\n            }\n            else\n            {\n                double d = -b - Fun.Sqrt(r);\n                return (d / (2 * a), 2 * c / d);\n            }\n        }\n\n        /// <summary>\n        /// Return real roots of the equation x^2 + px + q = 0.\n        /// Double roots are returned as a pair of identical values.\n        /// If no real roots exists, then both entries are NaN.\n        /// </summary>\n        public static (double, double) RealRootsOfNormed(double p, double q)\n        {\n            double p2 = p / 2.0;\n            double d = p2 * p2 - q;\n\n            if (d < 0)\n                return (double.NaN, double.NaN);\n            if (p2 > 0.0)\t\t\t\t               // prevent cancellation\n            {\n                double r = -(p2 + Fun.Sqrt(d));\n                return (r, q / r);\n            }\n            else\n            {\n                double r = Fun.Sqrt(d) - p2;\n                return (q / r, r);\n            }\n        }\n\n        /// <summary>\n        /// Return real roots of the equation: a x^3 + b x^2 + c x + d = 0.\n        /// Double and triple solutions are returned as replicated values.\n        /// Imaginary and non existing solutions are returned as NaNs.\n        /// </summary>\n        public static (double, double, double) RealRootsOf(\n                double a, double b, double c, double d)\n        {\n            if (Fun.IsTiny(a))\n            {\n                var r = RealRootsOf(b, c, d);\n                return (r.Item1, r.Item2, double.NaN);\n            }\n            return RealRootsOfNormed(b / a, c / a, d / a);\n        }\n\n        /// <summary>\n        /// Return real roots of the equation: x^3 + c2 x^2 + c1 x + c0 = 0\n        /// Double and triple solutions are returned as replicated values.\n        /// Imaginary and non existing solutions are returned as NaNs.\n        /// </summary>\n        public static (double, double, double) RealRootsOfNormed(\n                double c2, double c1, double c0)\n        {\n            // ------ eliminate quadric term (x = y - c2/3): x^3 + p x + q = 0\n            double d = c2 * c2;\n            double p3 = 1/3.0 * /* p */(-1/3.0 * d + c1);\n            double q2 = 1/2.0 * /* q */((2/27.0 * d - 1/3.0 * c1) * c2 + c0);\n            double p3c = p3 * p3 * p3;\n            double shift = 1/3.0 * c2;\n            d = q2 * q2 + p3c;\n            if (d < 0)            // casus irreducibilis: three real solutions\n            {\n                double phi = 1 / 3.0 * Fun.Acos(-q2 / Fun.Sqrt(-p3c));\n                double t = 2 * Fun.Sqrt(-p3);\n                double r0 = t * Fun.Cos(phi) - shift;\n                double r1 = -t * Fun.Cos(phi + Constant.Pi / 3.0) - shift;\n                double r2 = -t * Fun.Cos(phi - Constant.Pi / 3.0) - shift;\n                return TupleExtensions.CreateAscending(r0, r1, r2);\n            }\n            // else if (Fun.IsTiny(q2))\t\t\t           // one triple root\n            // {                                           // too unlikely for\n            //     double r = -1/3.0 * c2;                 // special handling\n            //     return (r, r, r);                       // to pay off\n            // }\n            d = Fun.Sqrt(d);                 // one single and one double root\n            double uav = Fun.Cbrt(d - q2) - Fun.Cbrt(d + q2);\n            double s0 = uav - shift, s1 = -0.5 * uav - shift;\n            return s0 < s1  ? (s0, s1, s1) : (s1, s1, s0);\n        }\n\n        /// <summary>\n        /// Return real roots of the equation: x^3 + p x + q = 0\n        /// Double and triple solutions are returned as replicated values.\n        /// Imaginary and non existing solutions are returned as NaNs.\n        /// </summary>\n        public static (double, double, double) RealRootsOfDepressed(\n                double p, double q)\n        {\n            double p3 = 1/3.0 * p, q2 = 1/2.0 * q;\n            double p3c = p3 * p3 * p3, d = q2 * q2 + p3c;\n            if (d < 0) // ---------- casus irreducibilis: three real solutions\n            {\n                double phi = 1 / 3.0 * Fun.Acos(-q2 / Fun.Sqrt(-p3c));\n                double t = 2 * Fun.Sqrt(-p3);\n                double r0 = t * Fun.Cos(phi);\n                double r1 = -t * Fun.Cos(phi + Constant.Pi / 3.0);\n                double r2 = -t * Fun.Cos(phi - Constant.Pi / 3.0);\n                return TupleExtensions.CreateAscending(r0, r1, r2);\n            }\n            d = Fun.Sqrt(d);  // one triple root or a single and a double root\n            double s0 = Fun.Cbrt(d - q2) - Fun.Cbrt(d + q2);\n            double s1 = -0.5 * s0;\n            return s0 < s1  ? (s0, s1, s1) : (s1, s1, s0);\n        }\n\n        /// <summary>\n        /// One real root of the equation: x^3 + c2 x^2 + c1 x + c0 = 0.\n        /// </summary>\n        public static double OneRealRootOfNormed(\n            double c2, double c1, double c0\n            )\n        {\n            // ------ eliminate quadric term (x = y - c2/3): x^3 + p x + q = 0\n            double d = c2 * c2;\n            double p3 = 1/3.0 * /* p */(-1/3.0 * d + c1);\n            double q2 = 1/2.0 * /* q */((2/27.0 * d - 1/3.0 * c1) * c2 + c0);\n            double p3c = p3 * p3 * p3;\n            d = q2 * q2 + p3c;\n            if (d < 0) // -------------- casus irreducibilis: three real roots\n                return 2 * Fun.Sqrt(-p3) * Fun.Cos(1/3.0\n                              * Fun.Acos(-q2 / Fun.Sqrt(-p3c))) - 1/3.0 * c2;\n            d = Fun.Sqrt(d);  // one triple root or a single and a double root\n            return Fun.Cbrt(d - q2) - Fun.Cbrt(d + q2) - 1/3.0 * c2;\n        }\r\n#if !TRAVIS_CI\n        /// <summary>\n        /// Return real roots of: a x^4 + b x^3 + c x^2 + d x + e = 0\n        /// Double and triple solutions are returned as replicated values.\n        /// Imaginary and non existing solutions are returned as NaNs.\n        /// </summary>\n        public static (double, double, double, double) RealRootsOf(\n                double a, double b, double c, double d, double e)\n        {\n            if (Fun.IsTiny(a))\n            {\n                var r = RealRootsOf(b, c, d, e);\n                return (r.Item1, r.Item2, r.Item3, double.NaN);\n            }\n            return RealRootsOfNormed(b / a, c / a, d / a, e / a);\n        }\n\n        /// <summary>\n        /// Return real roots of: x^4 + c3 x^3 + c2 x^2 + c1 x + c0 = 0.\n        /// Double and triple solutions are returned as replicated values.\n        /// Imaginary and non existing solutions are returned as NaNs.\n        /// </summary>\n        public static (double, double, double, double) RealRootsOfNormed(\n                double c3, double c2, double c1, double c0)\n        {\n            // eliminate cubic term (x = y - c3/4):  x^4 + p x^2 + q x + r = 0\n            double e = c3 * c3;\n            double p = -3/8.0 * e + c2;\n            double q = (1/8.0 * e - 1/2.0 * c2) * c3 + c1;\n            double r = (1/16.0 * c2 - 3/256.0 * e) * e - 1/4.0 * c3 * c1 + c0;\n\n            if (Fun.IsTiny(r)) // ---- no absolute term: y (y^3 + p y + q) = 0\n                return MergeSortedAndShift(\n                            RealRootsOfDepressed(p, q), 0.0, -1/4.0 * c3);\n            // ----------------------- take one root of the resolvent cubic...\n            double z = OneRealRootOfNormed(\n                            -1/2.0 * p, -r, 1/2.0 * r * p - 1/8.0 * q * q);\n            // --------------------------- ...to build two quadratic equations\n            double u = z * z - r;\n            double v = 2.0 * z - p;\n            if (u < Constant<double>.PositiveTinyValue) // +tiny instead of 0\n                u = 0.0;                                // improves unique\n            else                                        // root accuracy by a\n                u = Fun.Sqrt(u);                        // factor of 10^5!\n            if (v < Constant<double>.PositiveTinyValue) // values greater than\n                v = 0.0;                                // +tiny == 4 * eps\n            else                                        // do not seem to\n                v = Fun.Sqrt(v);                        // improve accuraccy!\n            double q1 = q < 0 ? -v : v;\n            return MergeSortedAndShift(RealRootsOfNormed(q1, z - u),\n                               RealRootsOfNormed(-q1, z + u),\n                               -1/4.0 * c3);\n        }\r\n\n        static (double, double, double, double) MergeSortedAndShift(\n                (double, double, double) t, double d, double shift)\n        {\n            var q = (0.0, 0.0, 0.0, 0.0);\n            int tc = t.CountNonNaNs();\n            int i = 0, ti = 0;\n            while (ti < tc)\n            {\n                if (t.Get(ti) < d)\n                    q.Set(i++, t.Get(ti++) + shift);\n                else\n                {\n                    q.Set(i++, d + shift);\n                    break;\n                }\n            }\n            while (ti < tc) q.Set(i++, t.Get(ti++) + shift);\n            while (i < 4) q.Set(i++, double.NaN);\n            return q;\n        }\n\r\n        static (double, double, double, double) MergeSortedAndShift(\n                (double, double) p0, (double, double) p1, double shift)\n        {\n            var q = (0.0, 0.0, 0.0, 0.0);\n            int c0 = p0.CountNonNaNs();\n            int c1 = p1.CountNonNaNs();\n            int i = 0, i0 = 0, i1 = 0;\n            while (i0 < c0 && i1 < c1)\n            {\n                if (p0.Get(i0) < p1.Get(i1))\n                    q.Set(i++, p0.Get(i0++) + shift);\n                else\n                    q.Set(i++, p1.Get(i1++) + shift);\n            }\n            while (i0 < c0) q.Set(i++, p0.Get(i0++) + shift);\n            while (i1 < c1) q.Set(i++, p1.Get(i1++) + shift);\n            while (i < 4) q.Set(i++, double.NaN);\n            return q;\n        }\n#endif\n\n        /// <summary>\n        /// Returns a copy of an array of roots without any double roots with\n        /// an absolute difference that is smaller than the supplied epsilon.\n        /// Roots with odd multiplicity will be left as single roots.\n        /// </summary>\n        public static double[] WithoutDoubleRoots(\n                this double[] a, double epsilon)\n        {\n            int last = a.Length - 1;\n            if (last < 4) return WithoutDoubleRoots4(a, epsilon);\n            var r = new List<double>(last + 1);\n            int i = 0;\n            while (i < last)\n            {\n                int j = i + 1;\n                if (Fun.Abs(a[i] - a[j]) < epsilon) { i += 2; continue; }\n                r.Add(a[i]);\n                i = j;\n            }\n            if (i == last) r.Add(a[i]);\n            return r.ToArray();\n        }\n\n        private static double[] WithoutDoubleRoots4(double[] a, double eps)\n        {\n            int len = a.Length;\n            if (len < 2) return a;\n            if ((a[0] - a[1]).Abs() < eps)\n            {\n                if (len < 3) return Array.Empty<double>();\n                if (len < 4) return new double[] { a[2] };\n                if ((a[2] - a[3]).Abs() < eps)\n                    return Array.Empty<double>();\n                else\n                    return new double[] { a[2], a[3] };\n            }\n            else\n            {\n                if (len < 3) return a;\n                if ((a[1] - a[2]).Abs() < eps)\n                {\n                    if (len < 4) return new double[] { a[0] };\n                    return new double[] { a[0], a[3] };\n                }\n                else\n                {\n                    if (len < 4) return a;\n                    if ((a[2] - a[3]).Abs() < eps)\n                        return new double[] { a[0], a[1] };\n                    else\n                        return a;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/QrFactorization.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static class QRHelpers\n    {\n        #region Helpers\n\n        /// <summary>\n        /// L2 norm of matrix row elemnts including start and excluding end. \n        /// </summary>\n        public static double RowNorm2(\n                this double[] matrix, long m0, long mx, long my, long row, long start, long end)\n        {\n            m0 += row * my;\n            var norm = 0.0;\n            for (long mi = m0 + start * mx, me = m0 + end * mx; mi != me; mi += mx)\n                norm += matrix[mi] * matrix[mi];\n            return Fun.Sqrt(norm);\n        }\n\n        /// <summary>\n        /// L2 norm of matrix column elemnts including start and excluding end. \n        /// </summary>\n        public static double ColNorm2(\n                this double[] matrix, long m0, long mx, long my, long col, long start, long end)\n        {\n            m0 += col * mx;\n            var norm = 0.0;\n            for (long mi = m0 + start * my, me = m0 + end * my; mi != me; mi += my)\n                norm += matrix[mi] * matrix[mi];\n            return Fun.Sqrt(norm);\n        }\n\n        /// <summary>\n        /// Dot product of matrix row elements including start and excluding end.\n        /// </summary>\n        public static double RowDotRow(\n                this double[] matrix, long m0, long mx, long my, long row0, long row1, long start, long end)\n        {\n            m0 += start * mx;\n            var dot = 0.0;\n            for (long i0 = m0 + row0 * my, i1 = m0 + row1 * my, e0 = i0 + (end - start) * mx;\n                 i0 != e0; i0 += mx, i1 += mx)\n                dot += matrix[i0] * matrix[i1];\n            return dot;\n        }\n\n        /// <summary>\n        /// Dot product of matrix column elements including start and excluding end.\n        /// </summary>\n        public static double ColDotCol(\n                this double[] matrix, long m0, long mx, long my, long col0, long col1, long start, long end)\n        {\n            m0 += start * my;\n            var dot = 0.0;\n            for (long i0 = m0 + col0 * mx, i1 = m0 + col1 * mx, e0 = i0 + (end - start) * my;\n                 i0 != e0; i0 += my, i1 += my)\n                dot += matrix[i0] * matrix[i1];\n            return dot;\n        }\n\n        public static void FlipWithNormalizedColHouseholder(\n                this double[] vector, double[] matrix, long m0, long mx, long my, long col, long end)\n        {\n            m0 += col * (mx + my);\n            double p = 0.0;\n            for (long i = col, mi = m0; i < end; i++, mi += my) p += 2.0 * vector[i] * matrix[mi];\n            for (long i = col, mi = m0; i < end; i++, mi += my) vector[i] -= p * matrix[mi];\n        }\n\n        public static void FlipWithNormalizedRowHouseholder(\n                this double[] vector, long v0, long vd, double[] matrix, long m0, long mx, long my, long row, long end)\n        {\n            m0 += row * (mx + my);\n            double p = 0.0;\n            for (long i = row, vi = v0, mi = m0; i < end; i++, vi += vd, mi += mx) p += 2.0 * vector[vi] * matrix[mi];\n            for (long i = row, vi = v0, mi = m0; i < end; i++, vi += vd, mi += mx) vector[vi] -= p * matrix[mi];\n        }\n\n        #endregion\n    }\n\n    public static partial class NumericExtensions\n    {\n        #region double[,] array helpers\n\n        /// <summary>\n        /// L2 norm of complete matrix row.\n        /// </summary>\n        public static double RowNorm2(\n                this double[,] array, long row)\n        {\n            return array.RowNorm2(row, 0, array.GetLongLength(1));\n        }\n\n        /// <summary>\n        /// L2 norm of complete matrix column.\n        /// </summary>\n        public static double ColNorm2(\n                this double[,] array, long col)\n        {\n            return array.ColNorm2(col, 0, array.GetLongLength(0));\n        }\n\n        /// <summary>\n        /// L2 norm of matrix row elemnts including start and excluding end. \n        /// </summary>\n        public static double RowNorm2(\n                this double[,] array, long row, long start, long end)\n        {\n            double sum = 0.0;\n            for (long i = start; i < end; i++) sum += array[row, i] * array[row, i];\n            return Fun.Sqrt(sum);\n        }\n\n        /// <summary>\n        /// L2 norm of matrix column elemnts including start and excluding end. \n        /// </summary>\n        public static double ColNorm2(\n                this double[,] array, long col, long start, long end)\n        {\n            double sum = 0.0;\n            for (long i = start; i < end; i++) sum += array[i, col] * array[i, col];\n            return Fun.Sqrt(sum);\n        }\n\n        /// <summary>\n        /// Dot product of complete matrix rows.\n        /// </summary>\n        public static double RowDotRow(\n                this double[,] array, long r0, long r1)\n        {\n            return array.RowDotRow(r0, r1, 0, array.GetLongLength(1));\n        }\n\n        /// <summary>\n        /// Dot product of complete matrix columns.\n        /// </summary>\n        public static double ColDotCol(\n                this double[,] array, long c0, long c1)\n        {\n            return array.ColDotCol(c0, c1, 0, array.GetLongLength(0));\n        }\n\n        /// <summary>\n        /// Dot product of matrix row elements including start and excluding end.\n        /// </summary>\n        public static double RowDotRow(\n                this double[,] array, long r0, long r1, long start, long end)\n        {\n            double sum = 0.0;\n            for (long i = start; i < end; i++) sum += array[r0, i] * array[r1, i];\n            return sum;\n        }\n\n        /// <summary>\n        /// Dot product of matrix column elements including start and excluding end.\n        /// </summary>\n        public static double ColDotCol(\n                this double[,] array, long c0, long c1, long start, long end)\n        {\n            double sum = 0.0;\n            for (long i = start; i < end; i++) sum += array[i, c0] * array[i, c1];\n            return sum;\n        }\n\n        #endregion\n\n        #region QR factorization of double[,] arrays using Householder transformations\n\n        // Note that this version of the QR factorization is mostly provided\n        // for studying the algorithm. In practice the Matrix<double> version\n        // is noticeably faster, since it performs incremental indexing.\n\n        #region Helpers\n\n        private static void FlipWithNormalizedColHouseholder(\n                this double[] vector, double[,] A, int col, int end)\n        {\n            double p = 0.0;\n            for (int i = col; i < end; i++) p += 2.0 * vector[i] * A[i, col];\n            for (int i = col; i < end; i++) vector[i] -= p * A[i, col];\n        }\n\n        private static void FlipWithNormalizedRowHouseholder(\n                this double[] vector, double[,] A, int row, int end)\n        {\n            double p = 0.0;\n            for (int i = row; i < end; i++) p += 2.0 * vector[i] * A[row, i];\n            for (int i = row; i < end; i++) vector[i] -= p * A[row, i];\n        }\n\n        #endregion\n\n        private static void QrFactorize(this double[,] A, double[] diagonal)\n        {\n            int rows = A.GetLength(0);\n            int cols = A.GetLength(1);\n\n            if (rows < cols)\n            {\n                for (int r = 0; r < rows; r++)\n                {\n                    double alpha = -System.Math.Sign(A[r, r]) * A.RowNorm2(r, r, cols);\n                    double norm_v = System.Math.Sqrt(-2.0 * alpha * (A[r, r] - alpha));\n                    diagonal[r] = alpha;\n                    A[r, r] = (A[r, r] - alpha) / norm_v;\n\n                    for (int c = r + 1; c < cols; c++)\n                        A[r, c] /= norm_v;\n\n                    for (int j = r + 1; j < rows; j++)\n                    {\n                        double p_j = 2.0 * A.RowDotRow(r, j, r, cols);\n                        for (int c = r; c < cols; c++) A[j, c] -= p_j * A[r, c];\n                    }\n                }\n            }\n            else\n            {\n                for (int c = 0; c < cols; c++)\n                {\n                    double alpha = -System.Math.Sign(A[c, c]) * A.ColNorm2(c, c, rows);\n                    double norm_v = System.Math.Sqrt(-2.0 * alpha * (A[c, c] - alpha));\n                    diagonal[c] = alpha;\n                    A[c, c] = (A[c, c] - alpha) / norm_v;\n\n                    for (int r = c + 1; r < rows; r++)\n                        A[r, c] /= norm_v;\n\n                    for (int j = c + 1; j < cols; j++)\n                    {\n                        double p_j = 2.0 * A.ColDotCol(c, j, c, rows);\n                        for (int r = c; r < rows; r++) A[r, j] -= p_j * A[r, c];\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Perform a QR factorization of the supplied m x n matrix using\n        /// Householder transofmations, i.e. A = QR, where Q is orthogonal\n        /// (a product of n-2 Householder-Transformations) and R is a right\n        /// upper n x n triangular matrix. An array of the diagonal elements\n        /// of R is returned. WARNING: the supplied matrix A is overwritten\n        ///  with its factorization QR, both in the parameter aqr.\n        /// </summary>\n        public static double[] QrFactorize(this double[,] aqr)\n        {\n            double[] diag = new double[Fun.Min(aqr.GetLength(0), aqr.GetLength(1))];\n            aqr.QrFactorize(diag);\n            return diag;\n        }\n\n        /// <summary>\n        /// Solves the Equation QR x = b. QR must be a factorized matrix (QrFactorize).\n        /// diag provides the diagonal elements of R (QrFactorize)\n        /// If QR is not quadratic the x where |QR*x - b| == min is calculated\n        /// residual holds the minimal value of |QR*x - b|\n        /// </summary>\n        public static void QrSolve(\n                this double[,] qr, double[] diag, double[] b, double[] x, out double residual)\n        {\n            int rows = qr.GetLength(0);\n            int cols = qr.GetLength(1);\n\n            if (rows < cols)\n            {\n                for (int r = 0; r < rows; r++)\n                {\n                    var value = b[r];\n                    for (int j = 0; j < r; j++) value -= qr[r, j] * x[j];\n                    x[r] = value / diag[r];\n                }\n                for (int i = rows; i < cols; i++) x[i] = 0.0;\n\n                for (int c = rows - 1; c >= 0; c--)\n                    x.FlipWithNormalizedRowHouseholder(qr, c, cols);\n\n                residual = 0.0;\n            }\n            else\n            {\n                var c = b.Copy(rows);\n\n                for (int i = 0; i < cols; i++)\n                    c.FlipWithNormalizedColHouseholder(qr, i, rows);\n\n                for (int r = cols - 1; r >= 0; r--)\n                {\n                    var value = c[r];\n                    for (int j = r + 1; j < cols; j++) value -= qr[r, j] * x[j];\n                    x[r] = value / diag[r];\n                }\n\n                residual = 0.0;\n                if (cols < rows)\n                {\n                    for (int i = cols; i < b.Length; i++) residual += c[i] * c[i];\n                    residual = Fun.Sqrt(residual);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Solves the Equation QR*x = b. QR must be a factorized matrix (QRFactorize).\n        /// diag provides the diagonal elements of R (QRFactorize)\n        /// If QR is not quadratic the x where |QR*x - b| == min is calculated\n        /// </summary>\n        public static double[] QrSolve(\n                this double[,] qr, double[] diag, double[] b)\n        {\n            double unusedResidual;\n            double[] x = new double[qr.GetLength(1)];\n            QrSolve(qr, diag, b, x, out unusedResidual);\n            return x;\n        }\n\n        /// <summary>\n        /// Solves the Equation QR*x = b. QR must be a factorized matrix (QRFactorize).\n        /// diag provides the diagonal elements of R (QRFactorize)\n        /// If QR is not quadratic the x where |QR*x - b| == min is returned\n        /// residual holds the minimal value of |QR*x - b|\n        /// </summary>\n        public static double[] QrSolve(\n                this double[,] qr, double[] diag, double[] b, out double residual)\n        {\n            double[] x = new double[qr.GetLength(1)];\n            QrSolve(qr, diag, b, x, out residual);\n            return x;\n        }\n\n        public static void QrInverse(this double[,] QR, double[] diag, double[,] inv)\n        {\n            int m = QR.GetLength(0);\n            int n = QR.GetLength(1);\n            if (m != n) throw new ArgumentException(\"Can only invert quadratic matrices\");\n\n            double[] temp = new double[n];\n            double[] b = new double[n];\n            double err;\n\n            for (int i = 0; i < n; i++)\n            {\n                for (int j = 0; j < n; j++) b[j] = (i == j ? 1.0 : 0.0);\n\n                QR.QrSolve(diag, b, temp, out err);\n\n                for (int j = 0; j < n; j++)\n                    inv[j, i] = temp[j];\n            }\n        }\n\n        /// <summary>\n        /// Calculates the inverse Matrix to A using Householder-Transformations\n        /// A has to be Quadratic\n        /// </summary>\n        public static double[,] QrInverse(this double[,] matrix)\n        {\n            double[,] qr = (double[,])matrix.Clone();\n            double[] diag = qr.QrFactorize();\n            double[,] inv = new double[matrix.GetLength(1), matrix.GetLength(0)];\n            qr.QrInverse(diag, inv);\n            return inv;\n        }\n\n        #endregion\n\n        #region QR factorization of double[] with offset and strides using Householder transformations\n\n      \n\n        /// <summary>\n        /// Perform a QR factorization of the supplied m x n matrix using\n        /// Householder transofmations, i.e. A = QR, where Q is orthogonal\n        /// (a product of n-2 Householder-Transformations) and R is a right\n        /// upper n x n triangular matrix. The diagonal elements of R are\n        /// put in the supplied array diagonal. WARNING: the supplied\n        /// matrix A is overwritten with its factorization QR, both in the\n        /// parameter aqr.\n        /// </summary>\n        public static void QrFactorize(\n                this double[] aqr, long a0, long ax, long ay, long cols, long rows, double[] diagonal)\n        {\n            if (rows < cols)\n            {\n                for (long r = 0, arr = a0; r < rows; r++, arr += ax + ay)\n                {\n                    var value = aqr[arr];\n                    double alpha = -System.Math.Sign(value) * aqr.RowNorm2(a0, ax, ay, r, r, cols);\n                    value -= alpha;\n                    double norm_v = System.Math.Sqrt(-2.0 * alpha * value);\n                    diagonal[r] = alpha;\n                    aqr[arr] = value / norm_v;\n\n                    for (long c = r + 1, arc = arr + ax; c < cols; c++, arc += ax)\n                        aqr[arc] /= norm_v;\n                    for (long j = r + 1, aj_ = arr + ay; j < rows; j++, aj_ += ay)\n                    {\n                        double p_j = 2.0 * aqr.RowDotRow(a0, ax, ay, r, j, r, cols);\n                        for (long c = r, ajc = aj_, arc = arr; c < cols; c++, ajc += ax, arc += ax)\n                            aqr[ajc] -= p_j * aqr[arc];\n                    }\n                }\n            }\n            else\n            {\n                for (long c = 0, acc = a0; c < cols; c++, acc += ax + ay)\n                {\n                    var value = aqr[acc];\n                    double alpha = -System.Math.Sign(value) * aqr.ColNorm2(a0, ax, ay, c, c, rows);\n                    value -= alpha;\n                    double norm_v = System.Math.Sqrt(-2.0 * alpha * value);\n                    diagonal[c] = alpha;\n                    aqr[acc] = value / norm_v;\n\n                    for (long r = c + 1, arc = acc + ay; r < rows; r++, arc += ay)\n                        aqr[arc] /= norm_v;\n                    for (long j = c + 1, a_j = acc + ax; j < cols; j++, a_j += ax)\n                    {\n                        double p_j = 2.0 * aqr.ColDotCol(a0, ax, ay, c, j, c, rows);\n                        for (long r = c, arj = a_j, arc = acc; r < rows; r++, arj += ay, arc += ay)\n                            aqr[arj] -= p_j * aqr[arc];\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Solves the Equation QR x = b. QR must be a factorized matrix (QrFactorize).\n        /// diag provides the diagonal elements of R (QrFactorize)\n        /// If QR is not quadratic the x where |QR x - b| == min is calculated\n        /// residual holds the minimal value of |QR x - b|\n        /// </summary>\n        public static void QrSolve(\n                this double[] qr, long q0, long qx, long qy, long cols, long rows, double[] diag,\n                double[] b, long b0, long bd, double[] x, long x0, long xd, out double residual)\n        {\n            if (rows < cols)\n            {\n                var xr = x0;\n                for (long r = 0, br = b0, qr_ = q0; r < rows; r++, br += bd, qr_ += qy, xr += xd)\n                {\n                    var value = b[br];\n                    for (long j = 0, qrj = qr_, xj = x0; j < r; j++, qrj += qx, xj += xd)\n                        value -= qr[qrj] * x[xj];\n                    x[xr] = value / diag[r];\n                }\n                for (long i = rows; i < cols; i++, xr += xd)\n                    x[xr] = 0.0;\n                for (long c = rows - 1; c >= 0; c--)\n                    x.FlipWithNormalizedRowHouseholder(x0, xd, qr, q0, qx, qy, c, cols);\n                residual = 0.0;\n            }\n            else\n            {\n                double[] c = new double[rows];\n                for (long i = 0, bi = b0; i < rows; i++, bi += bd)\n                    c[i] = b[bi];\n                for (long i = 0; i < cols; i++)\n                    c.FlipWithNormalizedColHouseholder(qr, q0, qx, qy, i, rows);\n                for (long r = cols - 1, xr = x0 + r * xd, qr_ = q0 + r * qy;\n                     r >= 0; r--, xr -= xd, qr_ -= qy)\n                {\n                    var value = c[r];\n                    for (long j = r + 1, qrj = qr_ + j * qx, xj = x0 + j * xd;\n                         j < cols; j++, qrj += qx, xj += xd)\n                        value -= qr[qrj] * x[xj];\n                    x[xr] = value / diag[r];\n                }\n                residual = 0.0;\n                if (cols < rows)\n                {\n                    for (long i = cols; i < rows; i++) residual += c[i] * c[i];\n                    residual = Fun.Sqrt(residual);\n                }\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/RangesBoxes/Box.cs",
    "content": "using System.Runtime.Serialization;\n\nnamespace Aardvark.Base\n{\n    #region OctoBox2d\n\n    [DataContract]\n    public struct OctoBox2d\n    {\n        [DataMember]\n        public double PX, PY, NX, NY, PXPY, PXNY, NXPY, NXNY;\n\n        #region Constructors\n\n        public OctoBox2d(\n                double px, double py, double nx, double ny,\n                double pxpy, double pxny, double nxpy, double nxny)\n        {\n            PX = px; PY = py; NX = nx; NY = ny;\n            PXPY = pxpy; PXNY = pxny; NXPY = nxpy; NXNY = nxny;\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly OctoBox2d Invalid =\n                new OctoBox2d(double.MinValue, double.MinValue, double.MinValue, double.MinValue,\n                              double.MinValue, double.MinValue, double.MinValue, double.MinValue);\n\n        public static readonly OctoBox2d Zero =\n                new OctoBox2d(0, 0, 0, 0, 0, 0, 0, 0);\n\n        #endregion\n\n        #region Properties\n\n        public readonly double Area\n        {\n            get\n            {\n                return (PX + NX) * (PY + NY)\n                        - 0.5 * (Fun.Square(PX + PY - PXPY) + Fun.Square(PX + NY - PXNY)\n                                 + Fun.Square(NX + PY - NXPY) + Fun.Square(NX + NY - NXNY));\n            }\n        }\n\n        #endregion\n\n        #region Manipulation\n\n        public void ExtendBy(V2d p)\n        {\n            ExtendBy(p.X, p.Y);\n        }\n\n        public void ExtendBy(double x, double y)\n        {\n            if (x > PX) PX = x;\n            if (y > PY) PY = y;\n            var nx = -x; if (nx > NX) NX = nx;\n            var ny = -y; if (ny > NY) NY = ny;\n            var pxpy = x + y; if (pxpy > PXPY) PXPY = pxpy;\n            var pxny = x - y; if (pxny > PXNY) PXNY = pxny;\n            var nxpy = -x + y; if (nxpy > NXPY) NXPY = nxpy;\n            var nxny = -x - y; if (nxny > NXNY) NXNY = nxny;\n        }\n\n        #endregion\n    }\n\n    #endregion\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/RangesBoxes/Box_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    #region Flags\n\n    public static partial class Box\n    {\n        [Flags]\n        public enum Flags\n        {\n            None = 0x00000000,\n\n            /* ---------------------------------------------------------------\n                flags that mark the faces of a box\n            --------------------------------------------------------------- */\n            MinX0 = 0x00000001,\n            MinY0 = 0x00000002,\n            MinZ0 = 0x00000004,\n\n            MaxX0 = 0x00000008,\n            MaxY0 = 0x00000010,\n            MaxZ0 = 0x00000020,\n\n            Min0 = MinX0 | MinY0 | MinZ0,\n            Max0 = MaxX0 | MaxY0 | MaxZ0,\n\n            X0 = MinX0 | MaxX0,\n            Y0 = MinY0 | MaxY0,\n            Z0 = MinZ0 | MaxZ0,\n\n            All0 = Min0 | Max0,\n\n            /* ---------------------------------------------------------------\n                flags that mark the faces of a second, independent box\n            --------------------------------------------------------------- */\n            MinX1 = MinX0 << 6,\n            MinY1 = MinY0 << 6,\n            MinZ1 = MinZ0 << 6,\n            MaxX1 = MaxX0 << 6,\n            MaxY1 = MaxY0 << 6,\n            MaxZ1 = MaxZ0 << 6,\n            Min1 = Min0 << 6,\n            Max1 = Max0 << 6,\n            X1 = X0 << 6,\n            Y1 = Y0 << 6,\n            Z1 = Z0 << 6,\n            All1 = All0 << 6,\n\n            /* ---------------------------------------------------------------\n                flags that operate on both face bits together\n            --------------------------------------------------------------- */\n            MinX = MinX0 | MinX1,\n            MinY = MinY0 | MinY1,\n            MinZ = MinZ0 | MinZ1,\n            MaxX = MaxX0 | MaxX1,\n            MaxY = MaxY0 | MaxY1,\n            MaxZ = MaxZ0 | MaxZ1,\n            Min = Min0 | Min1,\n            Max = Max0 | Max1,\n            MinXMinY = MinX | MinY,\n            MinXMaxY = MinX | MaxY,\n            MaxXMinY = MaxX | MinY,\n            MaxXMaxY = MaxX | MaxY,\n            X = X0 | X1,\n            Y = Y0 | Y1,\n            Z = Z0 | Z1,\n            All = All0 | All1,\n\n            /* ---------------------------------------------------------------\n                flags that mark the edges of the box\n            --------------------------------------------------------------- */\n            Edge01 = 0x00001000,\n            Edge23 = 0x00002000,\n            Edge45 = 0x00004000,\n            Edge67 = 0x00008000,\n            Edge02 = 0x00010000,\n            Edge13 = 0x00020000,\n            Edge46 = 0x00040000,\n            Edge57 = 0x00080000,\n            Edge04 = 0x00100000,\n            Edge15 = 0x00200000,\n            Edge26 = 0x00400000,\n            Edge37 = 0x00800000,\n\n            /* ---------------------------------------------------------------\n                flags that mark the corners of the box\n            --------------------------------------------------------------- */\n            Corner0 = 0x01000000,\n            Corner1 = 0x02000000,\n            Corner2 = 0x04000000,\n            Corner3 = 0x08000000,\n            Corner4 = 0x10000000,\n            Corner5 = 0x20000000,\n            Corner6 = 0x40000000,\n            Corner7 = (int)-0x80000000,\n        }\n    }\n\n    #endregion\n\n    #region Range1b\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1b\n        : IEquatable<Range1b>, IRange<byte, Range1b>, IFormattable\n    {\n        [DataMember]\n        public byte Min;\n        [DataMember]\n        public byte Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1b from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1sb b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1b from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1s b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1b from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1us b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1b from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1i b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1b from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1ui b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1b from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1l b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1b from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1ul b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1b from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1f b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1b from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1d b)\n        {\n            Min = (byte) b.Min;\n            Max = (byte) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(byte min, byte max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(byte pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(byte p0, byte p1, byte p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(byte p0, byte p1, byte p2, byte p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1b range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1b b0, Range1b b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1b b0, Range1b b1, Range1b b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(Range1b b0, Range1b b1, Range1b b2, Range1b b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(byte[] values)\n        {\n            Min = byte.MaxValue;\n            Max = byte.MinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(byte[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = byte.MaxValue;\n                Max = byte.MinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b(IEnumerable<byte> values)\n        {\n            Min = byte.MaxValue;\n            Max = byte.MinValue;\n            if (values == null) return;\n            foreach (byte v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b FromMinAndSize(byte min, byte size)\n        {\n            return new Range1b(min, (byte)(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b FromCenterAndSize(byte center, byte size)\n        {\n            return new Range1b((byte)(center - size / 2), (byte)(center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1b(Range1d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1b Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(byte.MaxValue, byte.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1b Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(byte.MinValue, byte.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1b Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public byte Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (byte)(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (byte)(Min + value); }\n        }\n\n        public readonly byte Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (byte)((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<byte> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1b EnlargedBy(byte increment)\n        {\n            return new Range1b((byte)(Min - increment), (byte)(Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1b EnlargedBy(byte deltaMin, byte deltaMax)\n        {\n            return new Range1b((byte)(Min - deltaMin), (byte)(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1b ShrunkBy(byte delta)\n        {\n            return new Range1b((byte)(Min + delta), (byte)(Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1b ShrunkBy(byte deltaMin, byte deltaMax)\n        {\n            return new Range1b((byte)(Min + deltaMin), (byte)(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(byte delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(byte deltaMin, byte deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(byte delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(byte deltaMin, byte deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly byte Clamped(byte x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly byte Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly byte Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(byte y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1b SplitRight(byte splitValue)\n        {\n            if (splitValue > Max) return Range1b.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1b(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1b SplitLeft(byte splitValue)\n        {\n            if (splitValue < Min) return Range1b.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1b(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1b ExtendedBy(Range1b range)\n        {\n            return new Range1b(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1b ExtendedBy(byte value)\n        {\n            return new Range1b(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1b range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(byte value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(byte value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1b b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1b range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1b range, byte eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1b Repair()\n        {\n            if (this.Equals(Range1b.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1b a, Range1b b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1b a, Range1b b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b operator +(Range1b box, byte v)\n        {\n            return new Range1b((byte)(box.Min + v), (byte)(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b operator -(Range1b box, byte v)\n        {\n            return new Range1b((byte)(box.Min - v), (byte)(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1b other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1b o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1b, int, byte> Setter =\n            (ref Range1b box, int i, byte value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1b Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1b(byte.Parse(x[0], CultureInfo.InvariantCulture),\n                                byte.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1b Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<byte>.Parse, Range1b.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b Union(this Range1b a, Range1b b)\n        {\n            return new Range1b(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b Intersection(this Range1b a, Range1b b)\n        {\n            return new Range1b(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1b a, Range1b b, byte eps, out Range1b result)\n        {\n            result = Range1b.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1b(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    byte center = result.Center;\n                    result.Min = (byte)(center - eps);\n                    result.Max = (byte)(center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b GetBoundingRange(this byte[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b GetBoundingRange(this byte[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1b GetBoundingRange(\n                this byte[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1b.Invalid;\n            var box = new Range1b(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1b GetBoundingRange<T>(this T[] array, long start, long count, Func<T, byte> pointSelector)\n        {\n            if (count <= 0) return Range1b.Invalid;\n            var box = new Range1b(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b GetBoundingRange(this List<byte> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1b GetBoundingRange(this List<byte> pointList, int count)\n        {\n            if (count <= 0) return Range1b.Invalid;\n            var box = new Range1b(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b GetBoundingRange(this int[] indexArray, byte[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b GetBoundingRange(this int[] indexArray, int count, byte[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1b GetBoundingRange(this int[] indexArray, int start, int count, byte[] pointArray)\n        {\n            if (count <= 0) return Range1b.Invalid;\n            var box = new Range1b(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1b GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, byte> pointSelector)\n        {\n            if (count <= 0) return Range1b.Invalid;\n            var box = new Range1b(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b GetBoundingRange(this long[] indexArray, byte[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1b GetBoundingRange(this long[] indexArray, long count, byte[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1b GetBoundingRange(this long[] indexArray, long start, long count, byte[] pointArray)\n        {\n            if (count <= 0) return Range1b.Invalid;\n            var box = new Range1b(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1b GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, byte> pointSelector)\n        {\n            if (count <= 0) return Range1b.Invalid;\n            var box = new Range1b(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1b GetBoundingRange(this IEnumerable<byte> points)\n        {\n            var box = Range1b.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<byte> Range(this byte count)\n        {\n            for (byte i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<byte> UpTo(this byte self, byte upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<byte> UpTo(this byte self, byte upToInclusive, byte step)\n        {\n            for (byte i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<byte> UpToExclusive(this byte self, byte upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<byte> UpToExclusive(this byte self, byte upToExclusive, byte step)\n        {\n            for (byte i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<byte> DownTo(this byte self, byte downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<byte> DownTo(this byte self, byte downToInclusive, byte step)\n        {\n            for (byte i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1b a, Range1b b)\n        {\n            return ApproximateEquals(a, b, Constant<byte>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1b a, Range1b b, byte tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1sb\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1sb\n        : IEquatable<Range1sb>, IRange<sbyte, Range1sb>, IFormattable\n    {\n        [DataMember]\n        public sbyte Min;\n        [DataMember]\n        public sbyte Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1b b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1s b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1us b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1i b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1ui b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1l b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1ul b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1f b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1sb from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1d b)\n        {\n            Min = (sbyte) b.Min;\n            Max = (sbyte) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(sbyte min, sbyte max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(sbyte pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(sbyte p0, sbyte p1, sbyte p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(sbyte p0, sbyte p1, sbyte p2, sbyte p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1sb range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1sb b0, Range1sb b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1sb b0, Range1sb b1, Range1sb b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(Range1sb b0, Range1sb b1, Range1sb b2, Range1sb b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(sbyte[] values)\n        {\n            Min = sbyte.MaxValue;\n            Max = sbyte.MinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(sbyte[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = sbyte.MaxValue;\n                Max = sbyte.MinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb(IEnumerable<sbyte> values)\n        {\n            Min = sbyte.MaxValue;\n            Max = sbyte.MinValue;\n            if (values == null) return;\n            foreach (sbyte v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb FromMinAndSize(sbyte min, sbyte size)\n        {\n            return new Range1sb(min, (sbyte)(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb FromCenterAndSize(sbyte center, sbyte size)\n        {\n            return new Range1sb((sbyte)(center - size / 2), (sbyte)(center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1sb(Range1d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1sb Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(sbyte.MaxValue, sbyte.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1sb Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(sbyte.MinValue, sbyte.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1sb Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public sbyte Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (sbyte)(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (sbyte)(Min + value); }\n        }\n\n        public readonly sbyte Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (sbyte)((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<sbyte> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1sb EnlargedBy(sbyte increment)\n        {\n            return new Range1sb((sbyte)(Min - increment), (sbyte)(Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1sb EnlargedBy(sbyte deltaMin, sbyte deltaMax)\n        {\n            return new Range1sb((sbyte)(Min - deltaMin), (sbyte)(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1sb ShrunkBy(sbyte delta)\n        {\n            return new Range1sb((sbyte)(Min + delta), (sbyte)(Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1sb ShrunkBy(sbyte deltaMin, sbyte deltaMax)\n        {\n            return new Range1sb((sbyte)(Min + deltaMin), (sbyte)(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(sbyte delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(sbyte deltaMin, sbyte deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(sbyte delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(sbyte deltaMin, sbyte deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly sbyte Clamped(sbyte x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly sbyte Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly sbyte Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(sbyte y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1sb SplitRight(sbyte splitValue)\n        {\n            if (splitValue > Max) return Range1sb.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1sb(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1sb SplitLeft(sbyte splitValue)\n        {\n            if (splitValue < Min) return Range1sb.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1sb(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1sb ExtendedBy(Range1sb range)\n        {\n            return new Range1sb(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1sb ExtendedBy(sbyte value)\n        {\n            return new Range1sb(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1sb range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(sbyte value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(sbyte value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1sb b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1sb range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1sb range, sbyte eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1sb Repair()\n        {\n            if (this.Equals(Range1sb.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1sb a, Range1sb b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1sb a, Range1sb b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb operator +(Range1sb box, sbyte v)\n        {\n            return new Range1sb((sbyte)(box.Min + v), (sbyte)(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb operator -(Range1sb box, sbyte v)\n        {\n            return new Range1sb((sbyte)(box.Min - v), (sbyte)(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1sb other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1sb o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1sb, int, sbyte> Setter =\n            (ref Range1sb box, int i, sbyte value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1sb Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1sb(sbyte.Parse(x[0], CultureInfo.InvariantCulture),\n                                sbyte.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1sb Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<sbyte>.Parse, Range1sb.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb Union(this Range1sb a, Range1sb b)\n        {\n            return new Range1sb(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb Intersection(this Range1sb a, Range1sb b)\n        {\n            return new Range1sb(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1sb a, Range1sb b, sbyte eps, out Range1sb result)\n        {\n            result = Range1sb.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1sb(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    sbyte center = result.Center;\n                    result.Min = (sbyte)(center - eps);\n                    result.Max = (sbyte)(center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb GetBoundingRange(this sbyte[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb GetBoundingRange(this sbyte[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1sb GetBoundingRange(\n                this sbyte[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1sb.Invalid;\n            var box = new Range1sb(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1sb GetBoundingRange<T>(this T[] array, long start, long count, Func<T, sbyte> pointSelector)\n        {\n            if (count <= 0) return Range1sb.Invalid;\n            var box = new Range1sb(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb GetBoundingRange(this List<sbyte> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1sb GetBoundingRange(this List<sbyte> pointList, int count)\n        {\n            if (count <= 0) return Range1sb.Invalid;\n            var box = new Range1sb(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb GetBoundingRange(this int[] indexArray, sbyte[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb GetBoundingRange(this int[] indexArray, int count, sbyte[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1sb GetBoundingRange(this int[] indexArray, int start, int count, sbyte[] pointArray)\n        {\n            if (count <= 0) return Range1sb.Invalid;\n            var box = new Range1sb(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1sb GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, sbyte> pointSelector)\n        {\n            if (count <= 0) return Range1sb.Invalid;\n            var box = new Range1sb(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb GetBoundingRange(this long[] indexArray, sbyte[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1sb GetBoundingRange(this long[] indexArray, long count, sbyte[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1sb GetBoundingRange(this long[] indexArray, long start, long count, sbyte[] pointArray)\n        {\n            if (count <= 0) return Range1sb.Invalid;\n            var box = new Range1sb(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1sb GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, sbyte> pointSelector)\n        {\n            if (count <= 0) return Range1sb.Invalid;\n            var box = new Range1sb(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1sb GetBoundingRange(this IEnumerable<sbyte> points)\n        {\n            var box = Range1sb.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<sbyte> Range(this sbyte count)\n        {\n            for (sbyte i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<sbyte> UpTo(this sbyte self, sbyte upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<sbyte> UpTo(this sbyte self, sbyte upToInclusive, sbyte step)\n        {\n            for (sbyte i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<sbyte> UpToExclusive(this sbyte self, sbyte upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<sbyte> UpToExclusive(this sbyte self, sbyte upToExclusive, sbyte step)\n        {\n            for (sbyte i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<sbyte> DownTo(this sbyte self, sbyte downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<sbyte> DownTo(this sbyte self, sbyte downToInclusive, sbyte step)\n        {\n            for (sbyte i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1sb a, Range1sb b)\n        {\n            return ApproximateEquals(a, b, Constant<sbyte>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1sb a, Range1sb b, sbyte tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1s\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1s\n        : IEquatable<Range1s>, IRange<short, Range1s>, IFormattable\n    {\n        [DataMember]\n        public short Min;\n        [DataMember]\n        public short Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1s from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1b b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1s from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1sb b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1s from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1us b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1s from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1i b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1s from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1ui b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1s from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1l b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1s from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1ul b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1s from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1f b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1s from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1d b)\n        {\n            Min = (short) b.Min;\n            Max = (short) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(short min, short max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(short pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(short p0, short p1, short p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(short p0, short p1, short p2, short p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1s range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1s b0, Range1s b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1s b0, Range1s b1, Range1s b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(Range1s b0, Range1s b1, Range1s b2, Range1s b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(short[] values)\n        {\n            Min = short.MaxValue;\n            Max = short.MinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(short[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = short.MaxValue;\n                Max = short.MinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s(IEnumerable<short> values)\n        {\n            Min = short.MaxValue;\n            Max = short.MinValue;\n            if (values == null) return;\n            foreach (short v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s FromMinAndSize(short min, short size)\n        {\n            return new Range1s(min, (short)(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s FromCenterAndSize(short center, short size)\n        {\n            return new Range1s((short)(center - size / 2), (short)(center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1s(Range1d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1s Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(short.MaxValue, short.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1s Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(short.MinValue, short.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1s Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public short Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (short)(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (short)(Min + value); }\n        }\n\n        public readonly short Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (short)((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<short> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1s EnlargedBy(short increment)\n        {\n            return new Range1s((short)(Min - increment), (short)(Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1s EnlargedBy(short deltaMin, short deltaMax)\n        {\n            return new Range1s((short)(Min - deltaMin), (short)(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1s ShrunkBy(short delta)\n        {\n            return new Range1s((short)(Min + delta), (short)(Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1s ShrunkBy(short deltaMin, short deltaMax)\n        {\n            return new Range1s((short)(Min + deltaMin), (short)(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(short delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(short deltaMin, short deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(short delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(short deltaMin, short deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly short Clamped(short x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly short Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly short Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(short y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1s SplitRight(short splitValue)\n        {\n            if (splitValue > Max) return Range1s.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1s(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1s SplitLeft(short splitValue)\n        {\n            if (splitValue < Min) return Range1s.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1s(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1s ExtendedBy(Range1s range)\n        {\n            return new Range1s(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1s ExtendedBy(short value)\n        {\n            return new Range1s(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1s range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(short value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(short value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1s b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1s range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1s range, short eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1s Repair()\n        {\n            if (this.Equals(Range1s.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1s a, Range1s b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1s a, Range1s b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s operator +(Range1s box, short v)\n        {\n            return new Range1s((short)(box.Min + v), (short)(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s operator -(Range1s box, short v)\n        {\n            return new Range1s((short)(box.Min - v), (short)(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1s other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1s o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1s, int, short> Setter =\n            (ref Range1s box, int i, short value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1s Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1s(short.Parse(x[0], CultureInfo.InvariantCulture),\n                                short.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1s Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<short>.Parse, Range1s.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s Union(this Range1s a, Range1s b)\n        {\n            return new Range1s(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s Intersection(this Range1s a, Range1s b)\n        {\n            return new Range1s(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1s a, Range1s b, short eps, out Range1s result)\n        {\n            result = Range1s.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1s(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    short center = result.Center;\n                    result.Min = (short)(center - eps);\n                    result.Max = (short)(center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s GetBoundingRange(this short[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s GetBoundingRange(this short[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1s GetBoundingRange(\n                this short[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1s.Invalid;\n            var box = new Range1s(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1s GetBoundingRange<T>(this T[] array, long start, long count, Func<T, short> pointSelector)\n        {\n            if (count <= 0) return Range1s.Invalid;\n            var box = new Range1s(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s GetBoundingRange(this List<short> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1s GetBoundingRange(this List<short> pointList, int count)\n        {\n            if (count <= 0) return Range1s.Invalid;\n            var box = new Range1s(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s GetBoundingRange(this int[] indexArray, short[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s GetBoundingRange(this int[] indexArray, int count, short[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1s GetBoundingRange(this int[] indexArray, int start, int count, short[] pointArray)\n        {\n            if (count <= 0) return Range1s.Invalid;\n            var box = new Range1s(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1s GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, short> pointSelector)\n        {\n            if (count <= 0) return Range1s.Invalid;\n            var box = new Range1s(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s GetBoundingRange(this long[] indexArray, short[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1s GetBoundingRange(this long[] indexArray, long count, short[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1s GetBoundingRange(this long[] indexArray, long start, long count, short[] pointArray)\n        {\n            if (count <= 0) return Range1s.Invalid;\n            var box = new Range1s(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1s GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, short> pointSelector)\n        {\n            if (count <= 0) return Range1s.Invalid;\n            var box = new Range1s(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1s GetBoundingRange(this IEnumerable<short> points)\n        {\n            var box = Range1s.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<short> Range(this short count)\n        {\n            for (short i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<short> UpTo(this short self, short upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<short> UpTo(this short self, short upToInclusive, short step)\n        {\n            for (short i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<short> UpToExclusive(this short self, short upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<short> UpToExclusive(this short self, short upToExclusive, short step)\n        {\n            for (short i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<short> DownTo(this short self, short downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<short> DownTo(this short self, short downToInclusive, short step)\n        {\n            for (short i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1s a, Range1s b)\n        {\n            return ApproximateEquals(a, b, Constant<short>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1s a, Range1s b, short tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1us\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1us\n        : IEquatable<Range1us>, IRange<ushort, Range1us>, IFormattable\n    {\n        [DataMember]\n        public ushort Min;\n        [DataMember]\n        public ushort Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1us from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1b b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1us from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1sb b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1us from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1s b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1us from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1i b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1us from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1ui b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1us from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1l b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1us from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1ul b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1us from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1f b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1us from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1d b)\n        {\n            Min = (ushort) b.Min;\n            Max = (ushort) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(ushort min, ushort max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(ushort pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(ushort p0, ushort p1, ushort p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(ushort p0, ushort p1, ushort p2, ushort p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1us range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1us b0, Range1us b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1us b0, Range1us b1, Range1us b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(Range1us b0, Range1us b1, Range1us b2, Range1us b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(ushort[] values)\n        {\n            Min = ushort.MaxValue;\n            Max = ushort.MinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(ushort[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = ushort.MaxValue;\n                Max = ushort.MinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us(IEnumerable<ushort> values)\n        {\n            Min = ushort.MaxValue;\n            Max = ushort.MinValue;\n            if (values == null) return;\n            foreach (ushort v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us FromMinAndSize(ushort min, ushort size)\n        {\n            return new Range1us(min, (ushort)(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us FromCenterAndSize(ushort center, ushort size)\n        {\n            return new Range1us((ushort)(center - size / 2), (ushort)(center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1us(Range1d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1us Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(ushort.MaxValue, ushort.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1us Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(ushort.MinValue, ushort.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1us Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public ushort Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (ushort)(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (ushort)(Min + value); }\n        }\n\n        public readonly ushort Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (ushort)((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<ushort> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1us EnlargedBy(ushort increment)\n        {\n            return new Range1us((ushort)(Min - increment), (ushort)(Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1us EnlargedBy(ushort deltaMin, ushort deltaMax)\n        {\n            return new Range1us((ushort)(Min - deltaMin), (ushort)(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1us ShrunkBy(ushort delta)\n        {\n            return new Range1us((ushort)(Min + delta), (ushort)(Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1us ShrunkBy(ushort deltaMin, ushort deltaMax)\n        {\n            return new Range1us((ushort)(Min + deltaMin), (ushort)(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(ushort delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(ushort deltaMin, ushort deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(ushort delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(ushort deltaMin, ushort deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly ushort Clamped(ushort x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly ushort Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly ushort Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(ushort y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1us SplitRight(ushort splitValue)\n        {\n            if (splitValue > Max) return Range1us.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1us(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1us SplitLeft(ushort splitValue)\n        {\n            if (splitValue < Min) return Range1us.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1us(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1us ExtendedBy(Range1us range)\n        {\n            return new Range1us(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1us ExtendedBy(ushort value)\n        {\n            return new Range1us(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1us range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(ushort value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(ushort value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1us b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1us range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1us range, ushort eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1us Repair()\n        {\n            if (this.Equals(Range1us.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1us a, Range1us b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1us a, Range1us b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us operator +(Range1us box, ushort v)\n        {\n            return new Range1us((ushort)(box.Min + v), (ushort)(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us operator -(Range1us box, ushort v)\n        {\n            return new Range1us((ushort)(box.Min - v), (ushort)(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1us other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1us o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1us, int, ushort> Setter =\n            (ref Range1us box, int i, ushort value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1us Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1us(ushort.Parse(x[0], CultureInfo.InvariantCulture),\n                                ushort.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1us Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<ushort>.Parse, Range1us.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us Union(this Range1us a, Range1us b)\n        {\n            return new Range1us(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us Intersection(this Range1us a, Range1us b)\n        {\n            return new Range1us(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1us a, Range1us b, ushort eps, out Range1us result)\n        {\n            result = Range1us.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1us(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    ushort center = result.Center;\n                    result.Min = (ushort)(center - eps);\n                    result.Max = (ushort)(center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us GetBoundingRange(this ushort[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us GetBoundingRange(this ushort[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1us GetBoundingRange(\n                this ushort[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1us.Invalid;\n            var box = new Range1us(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1us GetBoundingRange<T>(this T[] array, long start, long count, Func<T, ushort> pointSelector)\n        {\n            if (count <= 0) return Range1us.Invalid;\n            var box = new Range1us(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us GetBoundingRange(this List<ushort> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1us GetBoundingRange(this List<ushort> pointList, int count)\n        {\n            if (count <= 0) return Range1us.Invalid;\n            var box = new Range1us(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us GetBoundingRange(this int[] indexArray, ushort[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us GetBoundingRange(this int[] indexArray, int count, ushort[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1us GetBoundingRange(this int[] indexArray, int start, int count, ushort[] pointArray)\n        {\n            if (count <= 0) return Range1us.Invalid;\n            var box = new Range1us(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1us GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, ushort> pointSelector)\n        {\n            if (count <= 0) return Range1us.Invalid;\n            var box = new Range1us(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us GetBoundingRange(this long[] indexArray, ushort[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1us GetBoundingRange(this long[] indexArray, long count, ushort[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1us GetBoundingRange(this long[] indexArray, long start, long count, ushort[] pointArray)\n        {\n            if (count <= 0) return Range1us.Invalid;\n            var box = new Range1us(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1us GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, ushort> pointSelector)\n        {\n            if (count <= 0) return Range1us.Invalid;\n            var box = new Range1us(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1us GetBoundingRange(this IEnumerable<ushort> points)\n        {\n            var box = Range1us.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<ushort> Range(this ushort count)\n        {\n            for (ushort i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<ushort> UpTo(this ushort self, ushort upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<ushort> UpTo(this ushort self, ushort upToInclusive, ushort step)\n        {\n            for (ushort i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<ushort> UpToExclusive(this ushort self, ushort upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<ushort> UpToExclusive(this ushort self, ushort upToExclusive, ushort step)\n        {\n            for (ushort i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<ushort> DownTo(this ushort self, ushort downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<ushort> DownTo(this ushort self, ushort downToInclusive, ushort step)\n        {\n            for (ushort i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1us a, Range1us b)\n        {\n            return ApproximateEquals(a, b, Constant<ushort>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1us a, Range1us b, ushort tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1i\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1i\n        : IEquatable<Range1i>, IRange<int, Range1i>, IFormattable\n    {\n        [DataMember]\n        public int Min;\n        [DataMember]\n        public int Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1i from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1b b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1sb b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1s b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1us b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1ui b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1l b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1ul b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1f b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1d b)\n        {\n            Min = (int) b.Min;\n            Max = (int) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1i from a V2i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(V2i v)\n        {\n            Min = v.X;\n            Max = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(int min, int max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(int pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(int p0, int p1, int p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(int p0, int p1, int p2, int p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1i range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1i b0, Range1i b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1i b0, Range1i b1, Range1i b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(Range1i b0, Range1i b1, Range1i b2, Range1i b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(int[] values)\n        {\n            Min = int.MaxValue;\n            Max = int.MinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(int[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = int.MaxValue;\n                Max = int.MinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i(IEnumerable<int> values)\n        {\n            Min = int.MaxValue;\n            Max = int.MinValue;\n            if (values == null) return;\n            foreach (int v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i FromMinAndSize(int min, int size)\n        {\n            return new Range1i(min, (min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i FromCenterAndSize(int center, int size)\n        {\n            return new Range1i((center - size / 2), (center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(Range1d b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1i(V2i v) => new(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(Range1i r) => new(r.Min, r.Max);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1i Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(int.MaxValue, int.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1i Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(int.MinValue, int.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1i Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public int Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly int Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1i EnlargedBy(int increment)\n        {\n            return new Range1i((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1i EnlargedBy(int deltaMin, int deltaMax)\n        {\n            return new Range1i((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1i ShrunkBy(int delta)\n        {\n            return new Range1i((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1i ShrunkBy(int deltaMin, int deltaMax)\n        {\n            return new Range1i((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(int delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(int deltaMin, int deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(int delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(int deltaMin, int deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Clamped(int x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(int y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1i SplitRight(int splitValue)\n        {\n            if (splitValue > Max) return Range1i.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1i(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1i SplitLeft(int splitValue)\n        {\n            if (splitValue < Min) return Range1i.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1i(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1i ExtendedBy(Range1i range)\n        {\n            return new Range1i(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1i ExtendedBy(int value)\n        {\n            return new Range1i(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1i range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(int value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(int value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1i b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1i range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1i range, int eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1i Repair()\n        {\n            if (this.Equals(Range1i.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1i a, Range1i b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1i a, Range1i b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i operator +(Range1i box, int v)\n        {\n            return new Range1i((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i operator -(Range1i box, int v)\n        {\n            return new Range1i((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1i other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1i o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1i, int, int> Setter =\n            (ref Range1i box, int i, int value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1i(int.Parse(x[0], CultureInfo.InvariantCulture),\n                                int.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1i Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<int>.Parse, Range1i.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i Union(this Range1i a, Range1i b)\n        {\n            return new Range1i(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i Intersection(this Range1i a, Range1i b)\n        {\n            return new Range1i(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1i a, Range1i b, int eps, out Range1i result)\n        {\n            result = Range1i.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1i(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    int center = result.Center;\n                    result.Min = (center - eps);\n                    result.Max = (center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i GetBoundingRange(this int[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i GetBoundingRange(this int[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1i GetBoundingRange(\n                this int[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1i.Invalid;\n            var box = new Range1i(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1i GetBoundingRange<T>(this T[] array, long start, long count, Func<T, int> pointSelector)\n        {\n            if (count <= 0) return Range1i.Invalid;\n            var box = new Range1i(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i GetBoundingRange(this List<int> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1i GetBoundingRange(this List<int> pointList, int count)\n        {\n            if (count <= 0) return Range1i.Invalid;\n            var box = new Range1i(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i GetBoundingRange(this int[] indexArray, int[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i GetBoundingRange(this int[] indexArray, int count, int[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1i GetBoundingRange(this int[] indexArray, int start, int count, int[] pointArray)\n        {\n            if (count <= 0) return Range1i.Invalid;\n            var box = new Range1i(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1i GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, int> pointSelector)\n        {\n            if (count <= 0) return Range1i.Invalid;\n            var box = new Range1i(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i GetBoundingRange(this long[] indexArray, int[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1i GetBoundingRange(this long[] indexArray, long count, int[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1i GetBoundingRange(this long[] indexArray, long start, long count, int[] pointArray)\n        {\n            if (count <= 0) return Range1i.Invalid;\n            var box = new Range1i(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1i GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, int> pointSelector)\n        {\n            if (count <= 0) return Range1i.Invalid;\n            var box = new Range1i(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1i GetBoundingRange(this IEnumerable<int> points)\n        {\n            var box = Range1i.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<int> Range(this int count)\n        {\n            for (int i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<int> UpTo(this int self, int upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<int> UpTo(this int self, int upToInclusive, int step)\n        {\n            for (int i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<int> UpToExclusive(this int self, int upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<int> UpToExclusive(this int self, int upToExclusive, int step)\n        {\n            for (int i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<int> DownTo(this int self, int downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<int> DownTo(this int self, int downToInclusive, int step)\n        {\n            for (int i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1i a, Range1i b)\n        {\n            return ApproximateEquals(a, b, Constant<int>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1i a, Range1i b, int tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1ui\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1ui\n        : IEquatable<Range1ui>, IRange<uint, Range1ui>, IFormattable\n    {\n        [DataMember]\n        public uint Min;\n        [DataMember]\n        public uint Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1b b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1sb b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1s b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1us b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1i b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1l b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1ul b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1f b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1d b)\n        {\n            Min = (uint) b.Min;\n            Max = (uint) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ui from a V2ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(V2ui v)\n        {\n            Min = v.X;\n            Max = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(uint min, uint max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(uint pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(uint p0, uint p1, uint p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(uint p0, uint p1, uint p2, uint p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1ui range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1ui b0, Range1ui b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1ui b0, Range1ui b1, Range1ui b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(Range1ui b0, Range1ui b1, Range1ui b2, Range1ui b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(uint[] values)\n        {\n            Min = uint.MaxValue;\n            Max = uint.MinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(uint[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = uint.MaxValue;\n                Max = uint.MinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui(IEnumerable<uint> values)\n        {\n            Min = uint.MaxValue;\n            Max = uint.MinValue;\n            if (values == null) return;\n            foreach (uint v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui FromMinAndSize(uint min, uint size)\n        {\n            return new Range1ui(min, (uint)(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui FromCenterAndSize(uint center, uint size)\n        {\n            return new Range1ui((uint)(center - size / 2), (uint)(center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(Range1d b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ui(V2ui v) => new(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(Range1ui r) => new(r.Min, r.Max);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1ui Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(uint.MaxValue, uint.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1ui Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(uint.MinValue, uint.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1ui Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public uint Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (uint)(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (uint)(Min + value); }\n        }\n\n        public readonly uint Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (uint)((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<uint> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ui EnlargedBy(uint increment)\n        {\n            return new Range1ui((uint)(Min - increment), (uint)(Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ui EnlargedBy(uint deltaMin, uint deltaMax)\n        {\n            return new Range1ui((uint)(Min - deltaMin), (uint)(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ui ShrunkBy(uint delta)\n        {\n            return new Range1ui((uint)(Min + delta), (uint)(Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ui ShrunkBy(uint deltaMin, uint deltaMax)\n        {\n            return new Range1ui((uint)(Min + deltaMin), (uint)(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(uint delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(uint deltaMin, uint deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(uint delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(uint deltaMin, uint deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly uint Clamped(uint x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly uint Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly uint Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(uint y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ui SplitRight(uint splitValue)\n        {\n            if (splitValue > Max) return Range1ui.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1ui(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ui SplitLeft(uint splitValue)\n        {\n            if (splitValue < Min) return Range1ui.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1ui(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ui ExtendedBy(Range1ui range)\n        {\n            return new Range1ui(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ui ExtendedBy(uint value)\n        {\n            return new Range1ui(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1ui range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(uint value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(uint value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1ui b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1ui range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1ui range, uint eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ui Repair()\n        {\n            if (this.Equals(Range1ui.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1ui a, Range1ui b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1ui a, Range1ui b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui operator +(Range1ui box, uint v)\n        {\n            return new Range1ui((uint)(box.Min + v), (uint)(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui operator -(Range1ui box, uint v)\n        {\n            return new Range1ui((uint)(box.Min - v), (uint)(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1ui other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1ui o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1ui, int, uint> Setter =\n            (ref Range1ui box, int i, uint value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1ui Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1ui(uint.Parse(x[0], CultureInfo.InvariantCulture),\n                                uint.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1ui Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<uint>.Parse, Range1ui.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui Union(this Range1ui a, Range1ui b)\n        {\n            return new Range1ui(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui Intersection(this Range1ui a, Range1ui b)\n        {\n            return new Range1ui(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1ui a, Range1ui b, uint eps, out Range1ui result)\n        {\n            result = Range1ui.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1ui(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    uint center = result.Center;\n                    result.Min = (uint)(center - eps);\n                    result.Max = (uint)(center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui GetBoundingRange(this uint[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui GetBoundingRange(this uint[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1ui GetBoundingRange(\n                this uint[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1ui.Invalid;\n            var box = new Range1ui(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1ui GetBoundingRange<T>(this T[] array, long start, long count, Func<T, uint> pointSelector)\n        {\n            if (count <= 0) return Range1ui.Invalid;\n            var box = new Range1ui(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui GetBoundingRange(this List<uint> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1ui GetBoundingRange(this List<uint> pointList, int count)\n        {\n            if (count <= 0) return Range1ui.Invalid;\n            var box = new Range1ui(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui GetBoundingRange(this int[] indexArray, uint[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui GetBoundingRange(this int[] indexArray, int count, uint[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1ui GetBoundingRange(this int[] indexArray, int start, int count, uint[] pointArray)\n        {\n            if (count <= 0) return Range1ui.Invalid;\n            var box = new Range1ui(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1ui GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, uint> pointSelector)\n        {\n            if (count <= 0) return Range1ui.Invalid;\n            var box = new Range1ui(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui GetBoundingRange(this long[] indexArray, uint[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ui GetBoundingRange(this long[] indexArray, long count, uint[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1ui GetBoundingRange(this long[] indexArray, long start, long count, uint[] pointArray)\n        {\n            if (count <= 0) return Range1ui.Invalid;\n            var box = new Range1ui(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1ui GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, uint> pointSelector)\n        {\n            if (count <= 0) return Range1ui.Invalid;\n            var box = new Range1ui(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1ui GetBoundingRange(this IEnumerable<uint> points)\n        {\n            var box = Range1ui.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<uint> Range(this uint count)\n        {\n            for (uint i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<uint> UpTo(this uint self, uint upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<uint> UpTo(this uint self, uint upToInclusive, uint step)\n        {\n            for (uint i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<uint> UpToExclusive(this uint self, uint upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<uint> UpToExclusive(this uint self, uint upToExclusive, uint step)\n        {\n            for (uint i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<uint> DownTo(this uint self, uint downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<uint> DownTo(this uint self, uint downToInclusive, uint step)\n        {\n            for (uint i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1ui a, Range1ui b)\n        {\n            return ApproximateEquals(a, b, Constant<uint>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1ui a, Range1ui b, uint tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1l\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1l\n        : IEquatable<Range1l>, IRange<long, Range1l>, IFormattable\n    {\n        [DataMember]\n        public long Min;\n        [DataMember]\n        public long Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1l from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1b b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1sb b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1s b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1us b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1i b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1ui b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1ul b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1f b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1d b)\n        {\n            Min = (long) b.Min;\n            Max = (long) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1l from a V2l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(V2l v)\n        {\n            Min = v.X;\n            Max = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(long min, long max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(long pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(long p0, long p1, long p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(long p0, long p1, long p2, long p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1l range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1l b0, Range1l b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1l b0, Range1l b1, Range1l b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(Range1l b0, Range1l b1, Range1l b2, Range1l b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(long[] values)\n        {\n            Min = long.MaxValue;\n            Max = long.MinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(long[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = long.MaxValue;\n                Max = long.MinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l(IEnumerable<long> values)\n        {\n            Min = long.MaxValue;\n            Max = long.MinValue;\n            if (values == null) return;\n            foreach (long v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l FromMinAndSize(long min, long size)\n        {\n            return new Range1l(min, (long)(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l FromCenterAndSize(long center, long size)\n        {\n            return new Range1l((long)(center - size / 2), (long)(center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(Range1d b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1l(V2l v) => new(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(Range1l r) => new(r.Min, r.Max);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1l Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(long.MaxValue, long.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1l Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(long.MinValue, long.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1l Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public long Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (long)(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (long)(Min + value); }\n        }\n\n        public readonly long Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (long)((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1l EnlargedBy(long increment)\n        {\n            return new Range1l((long)(Min - increment), (long)(Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1l EnlargedBy(long deltaMin, long deltaMax)\n        {\n            return new Range1l((long)(Min - deltaMin), (long)(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1l ShrunkBy(long delta)\n        {\n            return new Range1l((long)(Min + delta), (long)(Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1l ShrunkBy(long deltaMin, long deltaMax)\n        {\n            return new Range1l((long)(Min + deltaMin), (long)(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(long delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(long deltaMin, long deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(long delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(long deltaMin, long deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly long Clamped(long x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly long Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly long Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(long y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1l SplitRight(long splitValue)\n        {\n            if (splitValue > Max) return Range1l.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1l(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1l SplitLeft(long splitValue)\n        {\n            if (splitValue < Min) return Range1l.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1l(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1l ExtendedBy(Range1l range)\n        {\n            return new Range1l(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1l ExtendedBy(long value)\n        {\n            return new Range1l(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1l range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(long value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(long value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1l b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1l range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1l range, long eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1l Repair()\n        {\n            if (this.Equals(Range1l.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1l a, Range1l b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1l a, Range1l b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l operator +(Range1l box, long v)\n        {\n            return new Range1l((long)(box.Min + v), (long)(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l operator -(Range1l box, long v)\n        {\n            return new Range1l((long)(box.Min - v), (long)(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1l other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1l o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1l, int, long> Setter =\n            (ref Range1l box, int i, long value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1l(long.Parse(x[0], CultureInfo.InvariantCulture),\n                                long.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1l Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<long>.Parse, Range1l.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l Union(this Range1l a, Range1l b)\n        {\n            return new Range1l(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l Intersection(this Range1l a, Range1l b)\n        {\n            return new Range1l(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1l a, Range1l b, long eps, out Range1l result)\n        {\n            result = Range1l.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1l(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    long center = result.Center;\n                    result.Min = (long)(center - eps);\n                    result.Max = (long)(center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l GetBoundingRange(this long[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l GetBoundingRange(this long[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1l GetBoundingRange(\n                this long[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1l.Invalid;\n            var box = new Range1l(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1l GetBoundingRange<T>(this T[] array, long start, long count, Func<T, long> pointSelector)\n        {\n            if (count <= 0) return Range1l.Invalid;\n            var box = new Range1l(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l GetBoundingRange(this List<long> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1l GetBoundingRange(this List<long> pointList, int count)\n        {\n            if (count <= 0) return Range1l.Invalid;\n            var box = new Range1l(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l GetBoundingRange(this int[] indexArray, long[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l GetBoundingRange(this int[] indexArray, int count, long[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1l GetBoundingRange(this int[] indexArray, int start, int count, long[] pointArray)\n        {\n            if (count <= 0) return Range1l.Invalid;\n            var box = new Range1l(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1l GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, long> pointSelector)\n        {\n            if (count <= 0) return Range1l.Invalid;\n            var box = new Range1l(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l GetBoundingRange(this long[] indexArray, long[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1l GetBoundingRange(this long[] indexArray, long count, long[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1l GetBoundingRange(this long[] indexArray, long start, long count, long[] pointArray)\n        {\n            if (count <= 0) return Range1l.Invalid;\n            var box = new Range1l(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1l GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, long> pointSelector)\n        {\n            if (count <= 0) return Range1l.Invalid;\n            var box = new Range1l(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1l GetBoundingRange(this IEnumerable<long> points)\n        {\n            var box = Range1l.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<long> Range(this long count)\n        {\n            for (long i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<long> UpTo(this long self, long upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<long> UpTo(this long self, long upToInclusive, long step)\n        {\n            for (long i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<long> UpToExclusive(this long self, long upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<long> UpToExclusive(this long self, long upToExclusive, long step)\n        {\n            for (long i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<long> DownTo(this long self, long downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<long> DownTo(this long self, long downToInclusive, long step)\n        {\n            for (long i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1l a, Range1l b)\n        {\n            return ApproximateEquals(a, b, Constant<long>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1l a, Range1l b, long tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1ul\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1ul\n        : IEquatable<Range1ul>, IRange<ulong, Range1ul>, IFormattable\n    {\n        [DataMember]\n        public ulong Min;\n        [DataMember]\n        public ulong Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1b b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1sb b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1s b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1us b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1i b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1ui b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1l b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1f b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1ul from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1d b)\n        {\n            Min = (ulong) b.Min;\n            Max = (ulong) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(ulong min, ulong max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(ulong pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(ulong p0, ulong p1, ulong p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(ulong p0, ulong p1, ulong p2, ulong p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1ul range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1ul b0, Range1ul b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1ul b0, Range1ul b1, Range1ul b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(Range1ul b0, Range1ul b1, Range1ul b2, Range1ul b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(ulong[] values)\n        {\n            Min = ulong.MaxValue;\n            Max = ulong.MinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(ulong[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = ulong.MaxValue;\n                Max = ulong.MinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul(IEnumerable<ulong> values)\n        {\n            Min = ulong.MaxValue;\n            Max = ulong.MinValue;\n            if (values == null) return;\n            foreach (ulong v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul FromMinAndSize(ulong min, ulong size)\n        {\n            return new Range1ul(min, (ulong)(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul FromCenterAndSize(ulong center, ulong size)\n        {\n            return new Range1ul((ulong)(center - size / 2), (ulong)(center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1ul(Range1d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1ul Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(ulong.MaxValue, ulong.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1ul Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(ulong.MinValue, ulong.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1ul Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public ulong Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (ulong)(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (ulong)(Min + value); }\n        }\n\n        public readonly ulong Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (ulong)((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<ulong> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ul EnlargedBy(ulong increment)\n        {\n            return new Range1ul((ulong)(Min - increment), (ulong)(Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ul EnlargedBy(ulong deltaMin, ulong deltaMax)\n        {\n            return new Range1ul((ulong)(Min - deltaMin), (ulong)(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ul ShrunkBy(ulong delta)\n        {\n            return new Range1ul((ulong)(Min + delta), (ulong)(Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ul ShrunkBy(ulong deltaMin, ulong deltaMax)\n        {\n            return new Range1ul((ulong)(Min + deltaMin), (ulong)(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(ulong delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(ulong deltaMin, ulong deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(ulong delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(ulong deltaMin, ulong deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly ulong Clamped(ulong x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly ulong Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly ulong Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(ulong y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ul SplitRight(ulong splitValue)\n        {\n            if (splitValue > Max) return Range1ul.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1ul(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ul SplitLeft(ulong splitValue)\n        {\n            if (splitValue < Min) return Range1ul.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1ul(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ul ExtendedBy(Range1ul range)\n        {\n            return new Range1ul(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1ul ExtendedBy(ulong value)\n        {\n            return new Range1ul(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1ul range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(ulong value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(ulong value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1ul b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1ul range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1ul range, ulong eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1ul Repair()\n        {\n            if (this.Equals(Range1ul.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1ul a, Range1ul b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1ul a, Range1ul b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul operator +(Range1ul box, ulong v)\n        {\n            return new Range1ul((ulong)(box.Min + v), (ulong)(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul operator -(Range1ul box, ulong v)\n        {\n            return new Range1ul((ulong)(box.Min - v), (ulong)(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1ul other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1ul o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1ul, int, ulong> Setter =\n            (ref Range1ul box, int i, ulong value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1ul Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1ul(ulong.Parse(x[0], CultureInfo.InvariantCulture),\n                                ulong.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1ul Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<ulong>.Parse, Range1ul.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul Union(this Range1ul a, Range1ul b)\n        {\n            return new Range1ul(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul Intersection(this Range1ul a, Range1ul b)\n        {\n            return new Range1ul(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1ul a, Range1ul b, ulong eps, out Range1ul result)\n        {\n            result = Range1ul.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1ul(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    ulong center = result.Center;\n                    result.Min = (ulong)(center - eps);\n                    result.Max = (ulong)(center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul GetBoundingRange(this ulong[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul GetBoundingRange(this ulong[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1ul GetBoundingRange(\n                this ulong[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1ul.Invalid;\n            var box = new Range1ul(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1ul GetBoundingRange<T>(this T[] array, long start, long count, Func<T, ulong> pointSelector)\n        {\n            if (count <= 0) return Range1ul.Invalid;\n            var box = new Range1ul(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul GetBoundingRange(this List<ulong> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1ul GetBoundingRange(this List<ulong> pointList, int count)\n        {\n            if (count <= 0) return Range1ul.Invalid;\n            var box = new Range1ul(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul GetBoundingRange(this int[] indexArray, ulong[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul GetBoundingRange(this int[] indexArray, int count, ulong[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1ul GetBoundingRange(this int[] indexArray, int start, int count, ulong[] pointArray)\n        {\n            if (count <= 0) return Range1ul.Invalid;\n            var box = new Range1ul(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1ul GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, ulong> pointSelector)\n        {\n            if (count <= 0) return Range1ul.Invalid;\n            var box = new Range1ul(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul GetBoundingRange(this long[] indexArray, ulong[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1ul GetBoundingRange(this long[] indexArray, long count, ulong[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1ul GetBoundingRange(this long[] indexArray, long start, long count, ulong[] pointArray)\n        {\n            if (count <= 0) return Range1ul.Invalid;\n            var box = new Range1ul(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1ul GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, ulong> pointSelector)\n        {\n            if (count <= 0) return Range1ul.Invalid;\n            var box = new Range1ul(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1ul GetBoundingRange(this IEnumerable<ulong> points)\n        {\n            var box = Range1ul.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<ulong> Range(this ulong count)\n        {\n            for (ulong i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<ulong> UpTo(this ulong self, ulong upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<ulong> UpTo(this ulong self, ulong upToInclusive, ulong step)\n        {\n            for (ulong i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<ulong> UpToExclusive(this ulong self, ulong upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<ulong> UpToExclusive(this ulong self, ulong upToExclusive, ulong step)\n        {\n            for (ulong i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<ulong> DownTo(this ulong self, ulong downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<ulong> DownTo(this ulong self, ulong downToInclusive, ulong step)\n        {\n            for (ulong i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1ul a, Range1ul b)\n        {\n            return ApproximateEquals(a, b, Constant<ulong>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1ul a, Range1ul b, ulong tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1f\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1f\n        : IEquatable<Range1f>, IRange<float, Range1f>, IFormattable\n    {\n        [DataMember]\n        public float Min;\n        [DataMember]\n        public float Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1f from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1b b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1sb b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1s b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1us b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1i b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1ui b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1l b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1ul b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a Range1d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1d b)\n        {\n            Min = (float) b.Min;\n            Max = (float) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1f from a V2f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(V2f v)\n        {\n            Min = v.X;\n            Max = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(float min, float max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(float pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(float p0, float p1, float p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(float p0, float p1, float p2, float p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1f range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1f b0, Range1f b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1f b0, Range1f b1, Range1f b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(Range1f b0, Range1f b1, Range1f b2, Range1f b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(float[] values)\n        {\n            Min = Constant<float>.ParseableMaxValue;\n            Max = Constant<float>.ParseableMinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(float[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Constant<float>.ParseableMaxValue;\n                Max = Constant<float>.ParseableMinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f(IEnumerable<float> values)\n        {\n            Min = Constant<float>.ParseableMaxValue;\n            Max = Constant<float>.ParseableMinValue;\n            if (values == null) return;\n            foreach (float v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f FromMinAndSize(float min, float size)\n        {\n            return new Range1f(min, (float)(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f FromCenterAndSize(float center, float size)\n        {\n            return new Range1f((float)(center - size / 2), (float)(center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(Range1d b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1f(V2f v) => new(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(Range1f r) => new(r.Min, r.Max);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1f Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Constant<float>.ParseableMaxValue, Constant<float>.ParseableMinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1f Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Constant<float>.ParseableMinValue, Constant<float>.ParseableMaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1f Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public float Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (float)(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (float)(Min + value); }\n        }\n\n        public readonly float Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return (float)((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1f EnlargedBy(float increment)\n        {\n            return new Range1f((float)(Min - increment), (float)(Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1f EnlargedBy(float deltaMin, float deltaMax)\n        {\n            return new Range1f((float)(Min - deltaMin), (float)(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1f ShrunkBy(float delta)\n        {\n            return new Range1f((float)(Min + delta), (float)(Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1f ShrunkBy(float deltaMin, float deltaMax)\n        {\n            return new Range1f((float)(Min + deltaMin), (float)(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(float delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(float deltaMin, float deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(float delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(float deltaMin, float deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float Clamped(float x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float Lerp(float x)\n            => Fun.Lerp(x, Min, Max);\n\n        /// <summary>\n        /// Performs the inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float InvLerp(float x)\n            => Fun.InvLerp(x, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1f SplitRight(float splitValue)\n        {\n            if (splitValue > Max) return Range1f.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1f(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1f SplitLeft(float splitValue)\n        {\n            if (splitValue < Min) return Range1f.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1f(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1f ExtendedBy(Range1f range)\n        {\n            return new Range1f(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1f ExtendedBy(float value)\n        {\n            return new Range1f(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1f range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(float value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(float value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1f b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1f range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1f range, float eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1f Repair()\n        {\n            if (this.Equals(Range1f.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1f a, Range1f b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1f a, Range1f b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f operator +(Range1f box, float v)\n        {\n            return new Range1f((float)(box.Min + v), (float)(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f operator -(Range1f box, float v)\n        {\n            return new Range1f((float)(box.Min - v), (float)(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1f other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1f o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1f, int, float> Setter =\n            (ref Range1f box, int i, float value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1f(float.Parse(x[0], CultureInfo.InvariantCulture),\n                                float.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1f Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<float>.Parse, Range1f.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f Union(this Range1f a, Range1f b)\n        {\n            return new Range1f(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f Intersection(this Range1f a, Range1f b)\n        {\n            return new Range1f(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1f a, Range1f b, float eps, out Range1f result)\n        {\n            result = Range1f.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1f(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    float center = result.Center;\n                    result.Min = (float)(center - eps);\n                    result.Max = (float)(center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GetBoundingRange(this float[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GetBoundingRange(this float[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1f GetBoundingRange(\n                this float[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1f.Invalid;\n            var box = new Range1f(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1f GetBoundingRange<T>(this T[] array, long start, long count, Func<T, float> pointSelector)\n        {\n            if (count <= 0) return Range1f.Invalid;\n            var box = new Range1f(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GetBoundingRange(this List<float> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1f GetBoundingRange(this List<float> pointList, int count)\n        {\n            if (count <= 0) return Range1f.Invalid;\n            var box = new Range1f(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GetBoundingRange(this int[] indexArray, float[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GetBoundingRange(this int[] indexArray, int count, float[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1f GetBoundingRange(this int[] indexArray, int start, int count, float[] pointArray)\n        {\n            if (count <= 0) return Range1f.Invalid;\n            var box = new Range1f(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1f GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, float> pointSelector)\n        {\n            if (count <= 0) return Range1f.Invalid;\n            var box = new Range1f(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GetBoundingRange(this long[] indexArray, float[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GetBoundingRange(this long[] indexArray, long count, float[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1f GetBoundingRange(this long[] indexArray, long start, long count, float[] pointArray)\n        {\n            if (count <= 0) return Range1f.Invalid;\n            var box = new Range1f(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1f GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, float> pointSelector)\n        {\n            if (count <= 0) return Range1f.Invalid;\n            var box = new Range1f(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1f GetBoundingRange(this IEnumerable<float> points)\n        {\n            var box = Range1f.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts the angles given in degrees to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f RadiansFromDegrees(this Range1f degrees)\n            => new(degrees.Min.RadiansFromDegrees(), degrees.Max.RadiansFromDegrees());\n\n        /// <summary>\n        /// Converts the angles given in gons to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f RadiansFromGons(this Range1f gons)\n            => new(gons.Min.RadiansFromGons(), gons.Max.RadiansFromGons());\n\n        /// <summary>\n        /// Converts the angles given in radians to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f DegreesFromRadians(this Range1f radians)\n            => new(radians.Min.DegreesFromRadians(), radians.Max.DegreesFromRadians());\n\n        /// <summary>\n        /// Converts the angles given in gons to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f DegreesFromGons(this Range1f gons)\n            => new(gons.Min.DegreesFromGons(), gons.Max.DegreesFromGons());\n\n        /// <summary>\n        /// Converts the angles given in radians to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GonsFromRadians(this Range1f radians)\n            => new(radians.Min.GonsFromRadians(), radians.Max.GonsFromRadians());\n\n        /// <summary>\n        /// Converts the angles given in degrees to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1f GonsFromDegrees(this Range1f degrees)\n            => new(degrees.Min.GonsFromDegrees(), degrees.Max.GonsFromDegrees());\n\n        #endregion\n    }\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<float> Range(this float count)\n        {\n            for (float i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<float> UpTo(this float self, float upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<float> UpTo(this float self, float upToInclusive, float step)\n        {\n            for (float i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<float> UpToExclusive(this float self, float upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<float> UpToExclusive(this float self, float upToExclusive, float step)\n        {\n            for (float i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<float> DownTo(this float self, float downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<float> DownTo(this float self, float downToInclusive, float step)\n        {\n            for (float i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1f a, Range1f b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1f a, Range1f b, float tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Range1d\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Range1d\n        : IEquatable<Range1d>, IRange<double, Range1d>, IFormattable\n    {\n        [DataMember]\n        public double Min;\n        [DataMember]\n        public double Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Range1d from a Range1b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1b b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a Range1sb.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1sb b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a Range1s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1s b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a Range1us.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1us b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a Range1i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1i b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a Range1ui.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1ui b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a Range1l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1l b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a Range1ul.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1ul b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a Range1f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1f b)\n        {\n            Min = (double) b.Min;\n            Max = (double) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Range1d from a V2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(V2d v)\n        {\n            Min = v.X;\n            Max = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a range from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(double min, double max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(double pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a range from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(double p0, double p1, double p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a range from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(double p0, double p1, double p2, double p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1d range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1d b0, Range1d b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1d b0, Range1d b1, Range1d b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied ranges.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(Range1d b0, Range1d b1, Range1d b2, Range1d b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(double[] values)\n        {\n            Min = Constant<double>.ParseableMaxValue;\n            Max = Constant<double>.ParseableMinValue;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(double[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Constant<double>.ParseableMaxValue;\n                Max = Constant<double>.ParseableMinValue;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates range as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d(IEnumerable<double> values)\n        {\n            Min = Constant<double>.ParseableMaxValue;\n            Max = Constant<double>.ParseableMinValue;\n            if (values == null) return;\n            foreach (double v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d FromMinAndSize(double min, double size)\n        {\n            return new Range1d(min, (min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d FromCenterAndSize(double center, double size)\n        {\n            return new Range1d((center - size / 2), (center + size / 2));\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1b b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1sb b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1s b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1us b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1ui b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1ul b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(Range1f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Range1d(V2d v) => new(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(Range1d r) => new(r.Min, r.Max);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Range1d Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Constant<double>.ParseableMaxValue, Constant<double>.ParseableMinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Range1d Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(Constant<double>.ParseableMinValue, Constant<double>.ParseableMaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Range1d Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min >= Max; }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min <= Max; }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min > Max; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the range.\n        /// </summary>\n        [XmlIgnore]\n        public double Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly double Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return range enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1d EnlargedBy(double increment)\n        {\n            return new Range1d((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return range enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1d EnlargedBy(double deltaMin, double deltaMax)\n        {\n            return new Range1d((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1d ShrunkBy(double delta)\n        {\n            return new Range1d((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return range shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1d ShrunkBy(double deltaMin, double deltaMax)\n        {\n            return new Range1d((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(double delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(double deltaMin, double deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(double delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks range by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(double deltaMin, double deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Clamped(double x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Lerp(double x)\n            => Fun.Lerp(x, Min, Max);\n\n        /// <summary>\n        /// Performs the inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double InvLerp(double x)\n            => Fun.InvLerp(x, Min, Max);\n\n\n        /// <summary>\n        /// Returns the range with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1d SplitRight(double splitValue)\n        {\n            if (splitValue > Max) return Range1d.Invalid;\n            if (splitValue <= Min) return this;\n            return new Range1d(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the range with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1d SplitLeft(double splitValue)\n        {\n            if (splitValue < Min) return Range1d.Invalid;\n            if (splitValue >= Max) return this;\n            return new Range1d(Min, splitValue);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1d ExtendedBy(Range1d range)\n        {\n            return new Range1d(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the range extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Range1d ExtendedBy(double value)\n        {\n            return new Range1d(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Range1d range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the range to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(double value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(double value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Range1d b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1d range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Range1d range, double eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Range1d Repair()\n        {\n            if (this.Equals(Range1d.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Range1d a, Range1d b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Range1d a, Range1d b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d operator +(Range1d box, double v)\n        {\n            return new Range1d((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a range shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d operator -(Range1d box, double v)\n        {\n            return new Range1d((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Range1d other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Range1d o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Range1d, int, double> Setter =\n            (ref Range1d box, int i, double value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Range1d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Range1d(double.Parse(x[0], CultureInfo.InvariantCulture),\n                                double.Parse(x[1], CultureInfo.InvariantCulture));\n        }\n\n        public static Range1d Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<double>.Parse, Range1d.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return begin + Min.ToString(format, fp) + between + Max.ToString(format, fp) + end;\n        }\n\n        #endregion\n    }\n\n    public static partial class Range\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d Union(this Range1d a, Range1d b)\n        {\n            return new Range1d(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d Intersection(this Range1d a, Range1d b)\n        {\n            return new Range1d(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        /// <summary>\n        /// Checks if two ranges intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this Range1d a, Range1d b, double eps, out Range1d result)\n        {\n            result = Range1d.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new Range1d(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    double center = result.Center;\n                    result.Min = (center - eps);\n                    result.Max = (center + eps);\n                }\n                return true;\n            }\n        }\n\n        #endregion\n\n        #region Bounding range for arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GetBoundingRange(this double[] pointArray)\n        {\n            return pointArray.GetBoundingRange(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GetBoundingRange(this double[] pointArray, long count)\n        {\n            return pointArray.GetBoundingRange(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1d GetBoundingRange(\n                this double[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Range1d.Invalid;\n            var box = new Range1d(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of count elements of the array starting at start.\n        /// </summary>\n        public static Range1d GetBoundingRange<T>(this T[] array, long start, long count, Func<T, double> pointSelector)\n        {\n            if (count <= 0) return Range1d.Invalid;\n            var box = new Range1d(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for lists\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GetBoundingRange(this List<double> pointList)\n        {\n            return pointList.GetBoundingRange(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the first count elements of the list.\n        /// </summary>\n        public static Range1d GetBoundingRange(this List<double> pointList, int count)\n        {\n            if (count <= 0) return Range1d.Invalid;\n            var box = new Range1d(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GetBoundingRange(this int[] indexArray, double[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GetBoundingRange(this int[] indexArray, int count, double[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1d GetBoundingRange(this int[] indexArray, int start, int count, double[] pointArray)\n        {\n            if (count <= 0) return Range1d.Invalid;\n            var box = new Range1d(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1d GetBoundingRange<T>(this int[] indexArray, int start, int count, T[] array, Func<T, double> pointSelector)\n        {\n            if (count <= 0) return Range1d.Invalid;\n            var box = new Range1d(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GetBoundingRange(this long[] indexArray, double[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GetBoundingRange(this long[] indexArray, long count, double[] pointArray)\n        {\n            return indexArray.GetBoundingRange(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1d GetBoundingRange(this long[] indexArray, long start, long count, double[] pointArray)\n        {\n            if (count <= 0) return Range1d.Invalid;\n            var box = new Range1d(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding range of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Range1d GetBoundingRange<T>(this long[] indexArray, long start, long count, T[] array, Func<T, double> pointSelector)\n        {\n            if (count <= 0) return Range1d.Invalid;\n            var box = new Range1d(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding range for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding range of the elements of the collection.\n        /// </summary>\n        public static Range1d GetBoundingRange(this IEnumerable<double> points)\n        {\n            var box = Range1d.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    #region Range extensions\n\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts the angles given in degrees to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d RadiansFromDegrees(this Range1d degrees)\n            => new(degrees.Min.RadiansFromDegrees(), degrees.Max.RadiansFromDegrees());\n\n        /// <summary>\n        /// Converts the angles given in gons to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d RadiansFromGons(this Range1d gons)\n            => new(gons.Min.RadiansFromGons(), gons.Max.RadiansFromGons());\n\n        /// <summary>\n        /// Converts the angles given in radians to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d DegreesFromRadians(this Range1d radians)\n            => new(radians.Min.DegreesFromRadians(), radians.Max.DegreesFromRadians());\n\n        /// <summary>\n        /// Converts the angles given in gons to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d DegreesFromGons(this Range1d gons)\n            => new(gons.Min.DegreesFromGons(), gons.Max.DegreesFromGons());\n\n        /// <summary>\n        /// Converts the angles given in radians to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GonsFromRadians(this Range1d radians)\n            => new(radians.Min.GonsFromRadians(), radians.Max.GonsFromRadians());\n\n        /// <summary>\n        /// Converts the angles given in degrees to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Range1d GonsFromDegrees(this Range1d degrees)\n            => new(degrees.Min.GonsFromDegrees(), degrees.Max.GonsFromDegrees());\n\n        #endregion\n    }\n\n    public static partial class RangeExtensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<double> Range(this double count)\n        {\n            for (double i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<double> UpTo(this double self, double upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<double> UpTo(this double self, double upToInclusive, double step)\n        {\n            for (double i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<double> UpToExclusive(this double self, double upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<double> UpToExclusive(this double self, double upToExclusive, double step)\n        {\n            for (double i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<double> DownTo(this double self, double downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<double> DownTo(this double self, double downToInclusive, double step)\n        {\n            for (double i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1d a, Range1d b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Range1d a, Range1d b, double tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box2i\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Box2i\n        : IEquatable<Box2i>, IRange<V2i, Box2i>, IBoundingBox2i, ISize2i, IBoundingCircle2d, IFormattable\n    {\n        [DataMember]\n        public V2i Min;\n        [DataMember]\n        public V2i Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Box2i from a Box2l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(Box2l b)\n        {\n            Min = (V2i) b.Min;\n            Max = (V2i) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box2i from a Box2f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(Box2f b)\n        {\n            Min = (V2i) b.Min;\n            Max = (V2i) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box2i from a Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(Box2d b)\n        {\n            Min = (V2i) b.Min;\n            Max = (V2i) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(V2i min, V2i max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(int minX, int minY, int maxX, int maxY)\n        {\n            Min.X = minX;\n            Min.Y = minY;\n            Max.X = maxX;\n            Max.Y = maxY;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(V2i pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a box from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(V2i p0, V2i p1, V2i p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a box from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(V2i p0, V2i p1, V2i p2, V2i p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(Box2i range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(Box2i b0, Box2i b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(Box2i b0, Box2i b1, Box2i b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(Box2i b0, Box2i b1, Box2i b2, Box2i b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(V2i[] points) : this((ReadOnlySpan<V2i>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(ReadOnlySpan<V2i> points)\n        {\n            Min = V2i.MaxValue;\n            Max = V2i.MinValue;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(V2i[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i(IEnumerable<V2i> points)\n        {\n            Min = V2i.MaxValue;\n            Max = V2i.MinValue;\n            if (points == null) return;\n            foreach (V2i p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public Box2i(IEnumerable<Box2i> boxes)\n        {\n            Min = V2i.MaxValue;\n            Max = V2i.MinValue;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates box from a Range1 in each direction.\n        /// </summary>\n        public Box2i(Range1i rangeX, Range1i rangeY)\n        {\n            Min.X = rangeX.Min;\n            Max.X = rangeX.Max;\n            Min.Y = rangeY.Min;\n            Max.Y = rangeY.Max;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2i(Box2l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2i(Box2f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2i(Box2d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Box2i Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2i.MaxValue, V2i.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Box2i Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2i.MinValue, V2i.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Box2i Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2i.Zero, V2i.One); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreaterOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AllSmallerOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreater(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n        /// <summary>\n        /// Same as Min.X.\n        /// </summary>\n        [XmlIgnore]\n        public int Left\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.X.\n        /// </summary>\n        [XmlIgnore]\n        public int Right\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Min.Y.\n        /// </summary>\n        [XmlIgnore]\n        public int Top\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.Y = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.Y.\n        /// </summary>\n        [XmlIgnore]\n        public int Bottom\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = value; }\n        }\n\n        /// <summary>\n        /// Calculates size of the box.\n        /// </summary>\n        [XmlIgnore]\n        public V2i Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly V2i Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        [XmlIgnore]\n        public int SizeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X - Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = Min.X + value; }\n        }\n\n        public readonly Range1i RangeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1i(Min.X, Max.X); }\n        }\n\n        [XmlIgnore]\n        public int SizeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y - Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = Min.Y + value; }\n        }\n\n        public readonly Range1i RangeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1i(Min.Y, Max.Y); }\n        }\n\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY > SizeX ? 1 : 0; }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY < SizeX ? 1 : 0; }\n        }\n\n        public readonly int Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeX * SizeY; }\n        }\n\n        public readonly V2i OO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Min; } }\n        public readonly V2i IO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V2i(Max.X, Min.Y); } }\n        public readonly V2i OI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V2i(Min.X, Max.Y); } }\n        public readonly V2i II { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Max; } }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return box enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i EnlargedBy(V2i increment)\n        {\n            return new Box2i((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return box enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i EnlargedBy(V2i deltaMin, V2i deltaMax)\n        {\n            return new Box2i((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i ShrunkBy(V2i delta)\n        {\n            return new Box2i((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i ShrunkBy(V2i deltaMin, V2i deltaMax)\n        {\n            return new Box2i((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V2i delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V2i deltaMin, V2i deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V2i delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V2i deltaMin, V2i deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i EnlargedBy(int delta)\n        {\n            return new Box2i(\n                    new V2i(Min.X - delta, Min.Y - delta),\n                    new V2i(Max.X + delta, Max.Y + delta));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i ShrunkBy(int delta)\n        {\n            return new Box2i(\n                    new V2i(Min.X + delta, Min.Y + delta),\n                    new V2i(Max.X - delta, Max.Y - delta));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i EnlargedBy(\n                int deltaMinX, int deltaMaxX, \n                int deltaMinY, int deltaMaxY)\n        {\n            return new Box2i(\n                    new V2i(Min.X - deltaMinX, Min.Y - deltaMinY),\n                    new V2i(Max.X + deltaMaxX, Max.Y + deltaMaxY));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i ShrunkBy(\n                int deltaMinX, int deltaMaxX, \n                int deltaMinY, int deltaMaxY)\n        {\n            return new Box2i(\n                    new V2i(Min.X + deltaMinX, Min.Y + deltaMinY),\n                    new V2i(Max.X - deltaMaxX, Max.Y - deltaMaxY));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(int delta)\n        {\n            Min.X -= delta; Max.X += delta;\n            Min.Y -= delta; Max.Y += delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(int delta)\n        {\n            Min.X += delta; Max.X -= delta;\n            Min.Y += delta; Max.Y -= delta;\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(\n                int deltaMinX, int deltaMaxX, \n                int deltaMinY, int deltaMaxY)\n        {\n            Min.X -= deltaMinX; Max.X += deltaMaxX;\n            Min.Y -= deltaMinY; Max.Y += deltaMaxY;\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(\n                int deltaMinX, int deltaMaxX, \n                int deltaMinY, int deltaMaxY)\n        {\n            Min.X += deltaMinX; Max.X -= deltaMaxX;\n            Min.Y += deltaMinY; Max.Y -= deltaMaxY;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Clamped(V2i p)\n        {\n            return new V2i(\n                        p.X < Min.X ? Min.X : (p.X > Max.X ? Max.X : p.X), \n                        p.Y < Min.Y ? Min.Y : (p.Y > Max.Y ? Max.Y : p.Y));\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Lerp(V2f t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Lerp(V2d t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d InvLerp(V2i y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the box with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitRight(V2i splitValue)\n        {\n            var result = new Box2i(Min, Max);\n            if (splitValue.X > result.Min.X) result.Min.X = splitValue.X;\n            if (splitValue.Y > result.Min.Y) result.Min.Y = splitValue.Y;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitLeft(V2i splitValue)\n        {\n            var result = new Box2i(Min, Max);\n            if (splitValue.X < result.Max.X) result.Max.X = splitValue.X;\n            if (splitValue.Y < result.Max.Y) result.Max.Y = splitValue.Y;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Min.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitRight(int splitAtX)\n        {\n            if (splitAtX > Max.X) return Box2i.Invalid;\n            if (splitAtX <= Min.X) return this;\n            return new Box2i(new V2i(splitAtX, Min.Y), Max);\n        }\n\n        /// <summary>\n        /// Returns a box with Max.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitLeft(int splitAtX)\n        {\n            if (splitAtX < Min.X) return Box2i.Invalid;\n            if (splitAtX >= Max.X) return this;\n            return new Box2i(Min, new V2i(splitAtX, Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the box with Min.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitTop(int splitAtY)\n        {\n            if (splitAtY > Max.Y) return Box2i.Invalid;\n            if (splitAtY <= Min.Y) return this;\n            return new Box2i(new V2i(Min.X, splitAtY), Max);\n        }\n\n        /// <summary>\n        /// Returns the box with Max.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitBottom(int splitAtY)\n        {\n            if (splitAtY < Min.Y) return Box2i.Invalid;\n            if (splitAtY >= Max.Y) return this;\n            return new Box2i(Min, new V2i(Max.X, splitAtY));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitLeftBottom(V2i splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y < Min.Y) return Box2i.Invalid;\n            return new Box2i(Min, splitAt);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitRightBottom(V2i splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y < Min.Y) return Box2i.Invalid;\n            return new Box2i(new V2i(splitAt.X, Min.Y), new V2i(Max.X, splitAt.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitLeftTop(V2i splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y > Max.Y) return Box2i.Invalid;\n            return new Box2i(new V2i(Min.X, splitAt.Y), new V2i(splitAt.X, Max.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i SplitRightTop(V2i splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y > Max.Y) return Box2i.Invalid;\n            return new Box2i(splitAt, Max);\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i ExtendedBy(Box2i b)\n        {\n            return new Box2i(\n                    new V2i(\n                        b.Min.X < Min.X ? b.Min.X : Min.X, \n                        b.Min.Y < Min.Y ? b.Min.Y : Min.Y),\n                    new V2i(\n                        b.Max.X > Max.X ? b.Max.X : Max.X, \n                        b.Max.Y > Max.Y ? b.Max.Y : Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i ExtendedBy(V2i v)\n        {\n            return new Box2i(\n                    new V2i(\n                        v.X < Min.X ? v.X : Min.X, \n                        v.Y < Min.Y ? v.Y : Min.Y),\n                    new V2i(\n                        v.X > Max.X ? v.X : Max.X, \n                        v.Y > Max.Y ? v.Y : Max.Y));\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Box2i box)\n        {\n            if (box.Min.X < Min.X) Min.X = box.Min.X;\n            if (box.Max.X > Max.X) Max.X = box.Max.X;\n            if (box.Min.Y < Min.Y) Min.Y = box.Min.Y;\n            if (box.Max.Y > Max.Y) Max.Y = box.Max.Y;\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(V2i point)\n        {\n            if (point.X < Min.X) Min.X = point.X;\n            if (point.X > Max.X) Max.X = point.X;\n            if (point.Y < Min.Y) Min.Y = point.Y;\n            if (point.Y > Max.Y) Max.Y = point.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i ExtendXBy(int x)\n        {\n            if (x < Min.X) Min.X = x;\n            if (x > Max.X) Max.X = x;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i ExtendYBy(int y)\n        {\n            if (y < Min.Y) Min.Y = y;\n            if (y > Max.Y) Max.Y = y;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i ExtendDimBy(int dim, int x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(V2i p)\n        {\n            return\n                p.X >= Min.X && p.X <= Max.X && \n                p.Y >= Min.Y && p.Y <= Max.Y;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Box2i b)\n        {\n            return\n                b.Min.X >= Min.X && b.Max.X <= Max.X && \n                b.Min.Y >= Min.Y && b.Max.Y <= Max.Y;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i Repair()\n        {\n            if (Equals(Box2i.Invalid)) return this;\n            if (Min.X > Max.X) Fun.Swap(ref Min.X, ref Max.X);\n            if (Min.Y > Max.Y) Fun.Swap(ref Min.Y, ref Max.Y);\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2i box)\n        {\n            if (Min.X >= box.Max.X) return false;\n            if (Max.X <= box.Min.X) return false;\n            if (Min.Y >= box.Max.Y) return false;\n            if (Max.Y <= box.Min.Y) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2i box, V2i eps)\n        {\n            if (Min.X - eps.X >= box.Max.X) return false;\n            if (Max.X + eps.X <= box.Min.X) return false;\n            if (Min.Y - eps.Y >= box.Max.Y) return false;\n            if (Max.Y + eps.Y <= box.Min.Y) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2i box, int eps)\n        {\n            if (Min.X - eps >= box.Max.X) return false;\n            if (Max.X + eps <= box.Min.X) return false;\n            if (Min.Y - eps >= box.Max.Y) return false;\n            if (Max.Y + eps <= box.Min.Y) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2i Invalidate()\n        {\n            Min = V2i.MaxValue;\n            Max = V2i.MinValue;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(V2i p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (p0.X < Min.X) bf |= Box.Flags.MinX;\n            else if (p0.X > Max.X) bf |= Box.Flags.MaxX;\n            if (p0.Y < Min.Y) bf |= Box.Flags.MinY;\n            else if (p0.Y > Max.Y) bf |= Box.Flags.MaxY;\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(Box2i b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (b.Min.X < Min.X) bf |= Box.Flags.MinX;\n            if (b.Max.X > Max.X) bf |= Box.Flags.MaxX;\n            if (b.Min.Y < Min.Y) bf |= Box.Flags.MinY;\n            if (b.Max.Y > Max.Y) bf |= Box.Flags.MaxY;\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(V2i v, out V2i vMin, out V2i vMax)\n        {\n            vMin = V2i.MinValue;\n            vMax = V2i.MaxValue;\n            if (v.X >= 0)\n            {\n                vMin.X = Min.X;\n                vMax.X = Max.X;\n            }\n            else\n            {\n                vMin.X = Max.X;\n                vMax.X = Min.X;\n            }\n            if (v.Y >= 0)\n            {\n                vMin.Y = Min.Y;\n                vMax.Y = Max.Y;\n            }\n            else\n            {\n                vMin.Y = Max.Y;\n                vMax.Y = Min.Y;\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Box2i a, Box2i b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Box2i a, Box2i b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i operator +(Box2i box, V2i v)\n        {\n            return new Box2i((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i operator -(Box2i box, V2i v)\n        {\n            return new Box2i((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Box2i other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Box2i o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Box2i, int, V2i> Setter =\n            (ref Box2i box, int i, V2i value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Box2i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Box2i(V2i.Parse(x[0].ToString()),\n                                V2i.Parse(x[1].ToString()));\n        }\n\n        public static Box2i Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, V2i.Parse, Box2i.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginB, string betweenB, string endB, string beginV, string betweenV, string endV)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return beginB + Min.ToString(format, fp, beginV, betweenV, endV) + betweenB + Max.ToString(format, fp, beginV, betweenV, endV) + endB;\n        }\n\n        #endregion\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromSize(V2i size)\n        {\n            return new Box2i(V2i.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromMinAndSize(V2i min, V2i size)\n        {\n            return new Box2i(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromCenterAndSize(V2i center, V2i size)\n        {\n            return new Box2i(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromSize(ISize2i iSize)\n        {\n            return new Box2i(\n                V2i.Zero, iSize.Size2i);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromMinAndSize(V2i min, ISize2i iSize)\n        {\n            return new Box2i(\n                min, min + iSize.Size2i);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromCenterAndSize(V2i center, ISize2i iSize)\n        {\n            var size = iSize.Size2i;\n            return new Box2i(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromPoints(V2i p0, V2i p1)\n        {\n            return new Box2i(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromSize(int width, int height)\n        {\n            return Box2i.FromSize(new V2i(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromMinAndSize(V2i min, int width, int height)\n        {\n            return new Box2i(min, min + new V2i(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromMinAndSize(\n            int minX, int minY, int width, int height\n            )\n        {\n            return Box2i.FromMinAndSize(new V2i(minX, minY), new V2i(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromCenterAndSize(V2i center, int width, int height)\n        {\n            return FromCenterAndSize(center, new V2i(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i FromCenterAndSize(\n            int centerX, int centerY, int width, int height\n            )\n        {\n            return FromCenterAndSize(new V2i(centerX, centerY), new V2i(width, height));\n        }\n\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i Translated(V2i shift)\n        {\n            return IsInvalid ? Box2i.Invalid\n                             : new Box2i(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2i Scaled(V2i factor)\n        {\n            return IsInvalid ? Box2i.Invalid\n                             : new Box2i(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        public readonly Box2d Transformed(M33d trafo)\n        {\n            if (Min.X > Max.X || Min.Y > Max.Y) return Box2d.Invalid;\n            var t = new V2d(trafo.M02, trafo.M12);\n            var res = new Box2d(t, t);\n            double av, bv;\n            av = trafo.M00 * Min.X;\n            bv = trafo.M00 * Max.X;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M01 * Min.Y;\n            bv = trafo.M01 * Max.Y;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M10 * Min.X;\n            bv = trafo.M10 * Max.X;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M11 * Min.Y;\n            bv = trafo.M11 * Max.Y;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d Transformed(Trafo2d trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Corner(int index)\n        {\n            return\n                new V2i(\n                        (index & 1) == 0 ? Min.X : Max.X, \n                        (index & 2) == 0 ? Min.Y : Max.Y);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i[] ComputeCorners()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                new(Min.X, Max.Y),\n                Max\n            ];\n        }\n\n        // TODO: Comment and implement for dimensions other than 2.\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i[] ComputeCornersCCW()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                Max,\n                new(Min.X, Max.Y),\n            ];\n        }\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<V2i> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                yield return new V2i(Max.X, Min.Y);\n                yield return new V2i(Min.X, Max.Y);\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n\n        #endregion\n\n        #region Enumerators\n\n        /// <summary>\n        /// Returns all points from [Min,Max[ with X-Variable in the outer loop.\n        /// </summary>\n        public readonly IEnumerable<V2i> EnumerateInsidePoints()\n        {\n            var p = new V2i();\n            for (p.X = Min.X; p.X < Max.X; p.X++)\n            for (p.Y = Min.Y; p.Y < Max.Y; p.Y++)\n                yield return p;\n        }\n\n        #endregion\n\n        #region IBoundingBox2i Members\n\n        public readonly Box2i BoundingBox2i\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n\n        #region IBoundingCircle2d Members\n\n        public readonly Circle2d BoundingCircle2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Circle2d.Invalid : new Circle2d((V2d)Center, 0.5 * Size.Length);\n        }\n\n        #endregion\n\n        #region ISize2i Members\n\n        public readonly V2i Size2i\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n    }\n\n    public static partial class Box\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i Union(this Box2i a, Box2i b)\n        {\n            return new Box2i(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i Intersection(this Box2i a, Box2i b)\n        {\n            return new Box2i(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        #endregion\n\n        #region Bounding box for arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i GetBoundingBox(this V2i[] pointArray)\n        {\n            return pointArray.GetBoundingBox(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i GetBoundingBox(this V2i[] pointArray, long count)\n        {\n            return pointArray.GetBoundingBox(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box2i GetBoundingBox(\n                this V2i[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Box2i.Invalid;\n            var box = new Box2i(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box2i GetBoundingBox<T>(this T[] array, long start, long count, Func<T, V2i> pointSelector)\n        {\n            if (count <= 0) return Box2i.Invalid;\n            var box = new Box2i(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for lists\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i GetBoundingBox(this List<V2i> pointList)\n        {\n            return pointList.GetBoundingBox(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the list.\n        /// </summary>\n        public static Box2i GetBoundingBox(this List<V2i> pointList, int count)\n        {\n            if (count <= 0) return Box2i.Invalid;\n            var box = new Box2i(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i GetBoundingBox(this int[] indexArray, V2i[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i GetBoundingBox(this int[] indexArray, int count, V2i[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2i GetBoundingBox(this int[] indexArray, int start, int count, V2i[] pointArray)\n        {\n            if (count <= 0) return Box2i.Invalid;\n            var box = new Box2i(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2i GetBoundingBox<T>(this int[] indexArray, int start, int count, T[] array, Func<T, V2i> pointSelector)\n        {\n            if (count <= 0) return Box2i.Invalid;\n            var box = new Box2i(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i GetBoundingBox(this long[] indexArray, V2i[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2i GetBoundingBox(this long[] indexArray, long count, V2i[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2i GetBoundingBox(this long[] indexArray, long start, long count, V2i[] pointArray)\n        {\n            if (count <= 0) return Box2i.Invalid;\n            var box = new Box2i(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2i GetBoundingBox<T>(this long[] indexArray, long start, long count, T[] array, Func<T, V2i> pointSelector)\n        {\n            if (count <= 0) return Box2i.Invalid;\n            var box = new Box2i(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the collection.\n        /// </summary>\n        public static Box2i GetBoundingBox(this IEnumerable<V2i> points)\n        {\n            var box = Box2i.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box2i a, Box2i b)\n        {\n            return ApproximateEquals(a, b, Constant<int>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box2i a, Box2i b, int tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box2l\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Box2l\n        : IEquatable<Box2l>, IRange<V2l, Box2l>, IBoundingBox2l, ISize2l, IBoundingCircle2d, IFormattable\n    {\n        [DataMember]\n        public V2l Min;\n        [DataMember]\n        public V2l Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Box2l from a Box2i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(Box2i b)\n        {\n            Min = (V2l) b.Min;\n            Max = (V2l) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box2l from a Box2f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(Box2f b)\n        {\n            Min = (V2l) b.Min;\n            Max = (V2l) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box2l from a Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(Box2d b)\n        {\n            Min = (V2l) b.Min;\n            Max = (V2l) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(V2l min, V2l max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(long minX, long minY, long maxX, long maxY)\n        {\n            Min.X = minX;\n            Min.Y = minY;\n            Max.X = maxX;\n            Max.Y = maxY;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(V2l pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a box from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(V2l p0, V2l p1, V2l p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a box from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(V2l p0, V2l p1, V2l p2, V2l p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(Box2l range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(Box2l b0, Box2l b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(Box2l b0, Box2l b1, Box2l b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(Box2l b0, Box2l b1, Box2l b2, Box2l b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(V2l[] points) : this((ReadOnlySpan<V2l>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(ReadOnlySpan<V2l> points)\n        {\n            Min = V2l.MaxValue;\n            Max = V2l.MinValue;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(V2l[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l(IEnumerable<V2l> points)\n        {\n            Min = V2l.MaxValue;\n            Max = V2l.MinValue;\n            if (points == null) return;\n            foreach (V2l p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public Box2l(IEnumerable<Box2l> boxes)\n        {\n            Min = V2l.MaxValue;\n            Max = V2l.MinValue;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates box from a Range1 in each direction.\n        /// </summary>\n        public Box2l(Range1l rangeX, Range1l rangeY)\n        {\n            Min.X = rangeX.Min;\n            Max.X = rangeX.Max;\n            Min.Y = rangeY.Min;\n            Max.Y = rangeY.Max;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2l(Box2i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2l(Box2f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2l(Box2d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Box2l Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2l.MaxValue, V2l.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Box2l Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2l.MinValue, V2l.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Box2l Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2l.Zero, V2l.One); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreaterOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AllSmallerOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreater(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n        /// <summary>\n        /// Same as Min.X.\n        /// </summary>\n        [XmlIgnore]\n        public long Left\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.X.\n        /// </summary>\n        [XmlIgnore]\n        public long Right\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Min.Y.\n        /// </summary>\n        [XmlIgnore]\n        public long Top\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.Y = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.Y.\n        /// </summary>\n        [XmlIgnore]\n        public long Bottom\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = value; }\n        }\n\n        /// <summary>\n        /// Calculates size of the box.\n        /// </summary>\n        [XmlIgnore]\n        public V2l Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly V2l Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        [XmlIgnore]\n        public long SizeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X - Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = Min.X + value; }\n        }\n\n        public readonly Range1l RangeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1l(Min.X, Max.X); }\n        }\n\n        [XmlIgnore]\n        public long SizeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y - Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = Min.Y + value; }\n        }\n\n        public readonly Range1l RangeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1l(Min.Y, Max.Y); }\n        }\n\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY > SizeX ? 1 : 0; }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY < SizeX ? 1 : 0; }\n        }\n\n        public readonly long Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeX * SizeY; }\n        }\n\n        public readonly V2l OO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Min; } }\n        public readonly V2l IO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V2l(Max.X, Min.Y); } }\n        public readonly V2l OI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V2l(Min.X, Max.Y); } }\n        public readonly V2l II { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Max; } }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return box enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l EnlargedBy(V2l increment)\n        {\n            return new Box2l((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return box enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l EnlargedBy(V2l deltaMin, V2l deltaMax)\n        {\n            return new Box2l((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l ShrunkBy(V2l delta)\n        {\n            return new Box2l((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l ShrunkBy(V2l deltaMin, V2l deltaMax)\n        {\n            return new Box2l((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V2l delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V2l deltaMin, V2l deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V2l delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V2l deltaMin, V2l deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l EnlargedBy(long delta)\n        {\n            return new Box2l(\n                    new V2l(Min.X - delta, Min.Y - delta),\n                    new V2l(Max.X + delta, Max.Y + delta));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l ShrunkBy(long delta)\n        {\n            return new Box2l(\n                    new V2l(Min.X + delta, Min.Y + delta),\n                    new V2l(Max.X - delta, Max.Y - delta));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l EnlargedBy(\n                long deltaMinX, long deltaMaxX, \n                long deltaMinY, long deltaMaxY)\n        {\n            return new Box2l(\n                    new V2l(Min.X - deltaMinX, Min.Y - deltaMinY),\n                    new V2l(Max.X + deltaMaxX, Max.Y + deltaMaxY));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l ShrunkBy(\n                long deltaMinX, long deltaMaxX, \n                long deltaMinY, long deltaMaxY)\n        {\n            return new Box2l(\n                    new V2l(Min.X + deltaMinX, Min.Y + deltaMinY),\n                    new V2l(Max.X - deltaMaxX, Max.Y - deltaMaxY));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(long delta)\n        {\n            Min.X -= delta; Max.X += delta;\n            Min.Y -= delta; Max.Y += delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(long delta)\n        {\n            Min.X += delta; Max.X -= delta;\n            Min.Y += delta; Max.Y -= delta;\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(\n                long deltaMinX, long deltaMaxX, \n                long deltaMinY, long deltaMaxY)\n        {\n            Min.X -= deltaMinX; Max.X += deltaMaxX;\n            Min.Y -= deltaMinY; Max.Y += deltaMaxY;\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(\n                long deltaMinX, long deltaMaxX, \n                long deltaMinY, long deltaMaxY)\n        {\n            Min.X += deltaMinX; Max.X -= deltaMaxX;\n            Min.Y += deltaMinY; Max.Y -= deltaMaxY;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Clamped(V2l p)\n        {\n            return new V2l(\n                        p.X < Min.X ? Min.X : (p.X > Max.X ? Max.X : p.X), \n                        p.Y < Min.Y ? Min.Y : (p.Y > Max.Y ? Max.Y : p.Y));\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Lerp(V2f t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Lerp(V2d t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d InvLerp(V2l y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the box with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitRight(V2l splitValue)\n        {\n            var result = new Box2l(Min, Max);\n            if (splitValue.X > result.Min.X) result.Min.X = splitValue.X;\n            if (splitValue.Y > result.Min.Y) result.Min.Y = splitValue.Y;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitLeft(V2l splitValue)\n        {\n            var result = new Box2l(Min, Max);\n            if (splitValue.X < result.Max.X) result.Max.X = splitValue.X;\n            if (splitValue.Y < result.Max.Y) result.Max.Y = splitValue.Y;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Min.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitRight(long splitAtX)\n        {\n            if (splitAtX > Max.X) return Box2l.Invalid;\n            if (splitAtX <= Min.X) return this;\n            return new Box2l(new V2l(splitAtX, Min.Y), Max);\n        }\n\n        /// <summary>\n        /// Returns a box with Max.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitLeft(long splitAtX)\n        {\n            if (splitAtX < Min.X) return Box2l.Invalid;\n            if (splitAtX >= Max.X) return this;\n            return new Box2l(Min, new V2l(splitAtX, Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the box with Min.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitTop(long splitAtY)\n        {\n            if (splitAtY > Max.Y) return Box2l.Invalid;\n            if (splitAtY <= Min.Y) return this;\n            return new Box2l(new V2l(Min.X, splitAtY), Max);\n        }\n\n        /// <summary>\n        /// Returns the box with Max.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitBottom(long splitAtY)\n        {\n            if (splitAtY < Min.Y) return Box2l.Invalid;\n            if (splitAtY >= Max.Y) return this;\n            return new Box2l(Min, new V2l(Max.X, splitAtY));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitLeftBottom(V2l splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y < Min.Y) return Box2l.Invalid;\n            return new Box2l(Min, splitAt);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitRightBottom(V2l splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y < Min.Y) return Box2l.Invalid;\n            return new Box2l(new V2l(splitAt.X, Min.Y), new V2l(Max.X, splitAt.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitLeftTop(V2l splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y > Max.Y) return Box2l.Invalid;\n            return new Box2l(new V2l(Min.X, splitAt.Y), new V2l(splitAt.X, Max.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l SplitRightTop(V2l splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y > Max.Y) return Box2l.Invalid;\n            return new Box2l(splitAt, Max);\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l ExtendedBy(Box2l b)\n        {\n            return new Box2l(\n                    new V2l(\n                        b.Min.X < Min.X ? b.Min.X : Min.X, \n                        b.Min.Y < Min.Y ? b.Min.Y : Min.Y),\n                    new V2l(\n                        b.Max.X > Max.X ? b.Max.X : Max.X, \n                        b.Max.Y > Max.Y ? b.Max.Y : Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l ExtendedBy(V2l v)\n        {\n            return new Box2l(\n                    new V2l(\n                        v.X < Min.X ? v.X : Min.X, \n                        v.Y < Min.Y ? v.Y : Min.Y),\n                    new V2l(\n                        v.X > Max.X ? v.X : Max.X, \n                        v.Y > Max.Y ? v.Y : Max.Y));\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Box2l box)\n        {\n            if (box.Min.X < Min.X) Min.X = box.Min.X;\n            if (box.Max.X > Max.X) Max.X = box.Max.X;\n            if (box.Min.Y < Min.Y) Min.Y = box.Min.Y;\n            if (box.Max.Y > Max.Y) Max.Y = box.Max.Y;\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(V2l point)\n        {\n            if (point.X < Min.X) Min.X = point.X;\n            if (point.X > Max.X) Max.X = point.X;\n            if (point.Y < Min.Y) Min.Y = point.Y;\n            if (point.Y > Max.Y) Max.Y = point.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l ExtendXBy(long x)\n        {\n            if (x < Min.X) Min.X = x;\n            if (x > Max.X) Max.X = x;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l ExtendYBy(long y)\n        {\n            if (y < Min.Y) Min.Y = y;\n            if (y > Max.Y) Max.Y = y;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l ExtendDimBy(int dim, long x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(V2l p)\n        {\n            return\n                p.X >= Min.X && p.X <= Max.X && \n                p.Y >= Min.Y && p.Y <= Max.Y;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Box2l b)\n        {\n            return\n                b.Min.X >= Min.X && b.Max.X <= Max.X && \n                b.Min.Y >= Min.Y && b.Max.Y <= Max.Y;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l Repair()\n        {\n            if (Equals(Box2l.Invalid)) return this;\n            if (Min.X > Max.X) Fun.Swap(ref Min.X, ref Max.X);\n            if (Min.Y > Max.Y) Fun.Swap(ref Min.Y, ref Max.Y);\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2l box)\n        {\n            if (Min.X >= box.Max.X) return false;\n            if (Max.X <= box.Min.X) return false;\n            if (Min.Y >= box.Max.Y) return false;\n            if (Max.Y <= box.Min.Y) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2l box, V2l eps)\n        {\n            if (Min.X - eps.X >= box.Max.X) return false;\n            if (Max.X + eps.X <= box.Min.X) return false;\n            if (Min.Y - eps.Y >= box.Max.Y) return false;\n            if (Max.Y + eps.Y <= box.Min.Y) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2l box, long eps)\n        {\n            if (Min.X - eps >= box.Max.X) return false;\n            if (Max.X + eps <= box.Min.X) return false;\n            if (Min.Y - eps >= box.Max.Y) return false;\n            if (Max.Y + eps <= box.Min.Y) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2l Invalidate()\n        {\n            Min = V2l.MaxValue;\n            Max = V2l.MinValue;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(V2l p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (p0.X < Min.X) bf |= Box.Flags.MinX;\n            else if (p0.X > Max.X) bf |= Box.Flags.MaxX;\n            if (p0.Y < Min.Y) bf |= Box.Flags.MinY;\n            else if (p0.Y > Max.Y) bf |= Box.Flags.MaxY;\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(Box2l b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (b.Min.X < Min.X) bf |= Box.Flags.MinX;\n            if (b.Max.X > Max.X) bf |= Box.Flags.MaxX;\n            if (b.Min.Y < Min.Y) bf |= Box.Flags.MinY;\n            if (b.Max.Y > Max.Y) bf |= Box.Flags.MaxY;\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(V2l v, out V2l vMin, out V2l vMax)\n        {\n            vMin = V2l.MinValue;\n            vMax = V2l.MaxValue;\n            if (v.X >= 0)\n            {\n                vMin.X = Min.X;\n                vMax.X = Max.X;\n            }\n            else\n            {\n                vMin.X = Max.X;\n                vMax.X = Min.X;\n            }\n            if (v.Y >= 0)\n            {\n                vMin.Y = Min.Y;\n                vMax.Y = Max.Y;\n            }\n            else\n            {\n                vMin.Y = Max.Y;\n                vMax.Y = Min.Y;\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Box2l a, Box2l b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Box2l a, Box2l b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l operator +(Box2l box, V2l v)\n        {\n            return new Box2l((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l operator -(Box2l box, V2l v)\n        {\n            return new Box2l((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Box2l other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Box2l o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Box2l, int, V2l> Setter =\n            (ref Box2l box, int i, V2l value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Box2l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Box2l(V2l.Parse(x[0].ToString()),\n                                V2l.Parse(x[1].ToString()));\n        }\n\n        public static Box2l Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, V2l.Parse, Box2l.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginB, string betweenB, string endB, string beginV, string betweenV, string endV)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return beginB + Min.ToString(format, fp, beginV, betweenV, endV) + betweenB + Max.ToString(format, fp, beginV, betweenV, endV) + endB;\n        }\n\n        #endregion\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromSize(V2l size)\n        {\n            return new Box2l(V2l.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromMinAndSize(V2l min, V2l size)\n        {\n            return new Box2l(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromCenterAndSize(V2l center, V2l size)\n        {\n            return new Box2l(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromSize(ISize2l iSize)\n        {\n            return new Box2l(\n                V2l.Zero, iSize.Size2l);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromMinAndSize(V2l min, ISize2l iSize)\n        {\n            return new Box2l(\n                min, min + iSize.Size2l);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromCenterAndSize(V2l center, ISize2l iSize)\n        {\n            var size = iSize.Size2l;\n            return new Box2l(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromPoints(V2l p0, V2l p1)\n        {\n            return new Box2l(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromSize(long width, long height)\n        {\n            return Box2l.FromSize(new V2l(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromMinAndSize(V2l min, long width, long height)\n        {\n            return new Box2l(min, min + new V2l(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromMinAndSize(\n            long minX, long minY, long width, long height\n            )\n        {\n            return Box2l.FromMinAndSize(new V2l(minX, minY), new V2l(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromCenterAndSize(V2l center, long width, long height)\n        {\n            return FromCenterAndSize(center, new V2l(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l FromCenterAndSize(\n            long centerX, long centerY, long width, long height\n            )\n        {\n            return FromCenterAndSize(new V2l(centerX, centerY), new V2l(width, height));\n        }\n\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l Translated(V2l shift)\n        {\n            return IsInvalid ? Box2l.Invalid\n                             : new Box2l(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2l Scaled(V2l factor)\n        {\n            return IsInvalid ? Box2l.Invalid\n                             : new Box2l(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        public readonly Box2d Transformed(M33d trafo)\n        {\n            if (Min.X > Max.X || Min.Y > Max.Y) return Box2d.Invalid;\n            var t = new V2d(trafo.M02, trafo.M12);\n            var res = new Box2d(t, t);\n            double av, bv;\n            av = trafo.M00 * Min.X;\n            bv = trafo.M00 * Max.X;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M01 * Min.Y;\n            bv = trafo.M01 * Max.Y;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M10 * Min.X;\n            bv = trafo.M10 * Max.X;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M11 * Min.Y;\n            bv = trafo.M11 * Max.Y;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d Transformed(Trafo2d trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Corner(int index)\n        {\n            return\n                new V2l(\n                        (index & 1) == 0 ? Min.X : Max.X, \n                        (index & 2) == 0 ? Min.Y : Max.Y);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l[] ComputeCorners()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                new(Min.X, Max.Y),\n                Max\n            ];\n        }\n\n        // TODO: Comment and implement for dimensions other than 2.\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l[] ComputeCornersCCW()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                Max,\n                new(Min.X, Max.Y),\n            ];\n        }\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<V2l> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                yield return new V2l(Max.X, Min.Y);\n                yield return new V2l(Min.X, Max.Y);\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n\n        #endregion\n\n        #region Enumerators\n\n        /// <summary>\n        /// Returns all points from [Min,Max[ with X-Variable in the outer loop.\n        /// </summary>\n        public readonly IEnumerable<V2l> EnumerateInsidePoints()\n        {\n            var p = new V2l();\n            for (p.X = Min.X; p.X < Max.X; p.X++)\n            for (p.Y = Min.Y; p.Y < Max.Y; p.Y++)\n                yield return p;\n        }\n\n        #endregion\n\n        #region IBoundingBox2l Members\n\n        public readonly Box2l BoundingBox2l\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n\n        #region IBoundingCircle2d Members\n\n        public readonly Circle2d BoundingCircle2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Circle2d.Invalid : new Circle2d((V2d)Center, 0.5 * Size.Length);\n        }\n\n        #endregion\n\n        #region ISize2l Members\n\n        public readonly V2l Size2l\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n    }\n\n    public static partial class Box\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l Union(this Box2l a, Box2l b)\n        {\n            return new Box2l(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l Intersection(this Box2l a, Box2l b)\n        {\n            return new Box2l(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        #endregion\n\n        #region Bounding box for arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l GetBoundingBox(this V2l[] pointArray)\n        {\n            return pointArray.GetBoundingBox(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l GetBoundingBox(this V2l[] pointArray, long count)\n        {\n            return pointArray.GetBoundingBox(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box2l GetBoundingBox(\n                this V2l[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Box2l.Invalid;\n            var box = new Box2l(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box2l GetBoundingBox<T>(this T[] array, long start, long count, Func<T, V2l> pointSelector)\n        {\n            if (count <= 0) return Box2l.Invalid;\n            var box = new Box2l(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for lists\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l GetBoundingBox(this List<V2l> pointList)\n        {\n            return pointList.GetBoundingBox(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the list.\n        /// </summary>\n        public static Box2l GetBoundingBox(this List<V2l> pointList, int count)\n        {\n            if (count <= 0) return Box2l.Invalid;\n            var box = new Box2l(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l GetBoundingBox(this int[] indexArray, V2l[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l GetBoundingBox(this int[] indexArray, int count, V2l[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2l GetBoundingBox(this int[] indexArray, int start, int count, V2l[] pointArray)\n        {\n            if (count <= 0) return Box2l.Invalid;\n            var box = new Box2l(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2l GetBoundingBox<T>(this int[] indexArray, int start, int count, T[] array, Func<T, V2l> pointSelector)\n        {\n            if (count <= 0) return Box2l.Invalid;\n            var box = new Box2l(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l GetBoundingBox(this long[] indexArray, V2l[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2l GetBoundingBox(this long[] indexArray, long count, V2l[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2l GetBoundingBox(this long[] indexArray, long start, long count, V2l[] pointArray)\n        {\n            if (count <= 0) return Box2l.Invalid;\n            var box = new Box2l(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2l GetBoundingBox<T>(this long[] indexArray, long start, long count, T[] array, Func<T, V2l> pointSelector)\n        {\n            if (count <= 0) return Box2l.Invalid;\n            var box = new Box2l(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the collection.\n        /// </summary>\n        public static Box2l GetBoundingBox(this IEnumerable<V2l> points)\n        {\n            var box = Box2l.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box2l a, Box2l b)\n        {\n            return ApproximateEquals(a, b, Constant<long>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box2l a, Box2l b, long tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box2f\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Box2f\n        : IEquatable<Box2f>, IRange<V2f, Box2f>, IBoundingBox2f, ISize2f, IBoundingCircle2f, IFormattable\n    {\n        [DataMember]\n        public V2f Min;\n        [DataMember]\n        public V2f Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Box2f from a Box2i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(Box2i b)\n        {\n            Min = (V2f) b.Min;\n            Max = (V2f) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box2f from a Box2l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(Box2l b)\n        {\n            Min = (V2f) b.Min;\n            Max = (V2f) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box2f from a Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(Box2d b)\n        {\n            Min = (V2f) b.Min;\n            Max = (V2f) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(V2f min, V2f max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(float minX, float minY, float maxX, float maxY)\n        {\n            Min.X = minX;\n            Min.Y = minY;\n            Max.X = maxX;\n            Max.Y = maxY;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(V2f pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a box from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(V2f p0, V2f p1, V2f p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a box from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(V2f p0, V2f p1, V2f p2, V2f p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(Box2f range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(Box2f b0, Box2f b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(Box2f b0, Box2f b1, Box2f b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(Box2f b0, Box2f b1, Box2f b2, Box2f b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(V2f[] points) : this((ReadOnlySpan<V2f>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(ReadOnlySpan<V2f> points)\n        {\n            Min = V2f.MaxValue;\n            Max = V2f.MinValue;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(V2f[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f(IEnumerable<V2f> points)\n        {\n            Min = V2f.MaxValue;\n            Max = V2f.MinValue;\n            if (points == null) return;\n            foreach (V2f p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public Box2f(IEnumerable<Box2f> boxes)\n        {\n            Min = V2f.MaxValue;\n            Max = V2f.MinValue;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates box from a Range1 in each direction.\n        /// </summary>\n        public Box2f(Range1f rangeX, Range1f rangeY)\n        {\n            Min.X = rangeX.Min;\n            Max.X = rangeX.Max;\n            Min.Y = rangeY.Min;\n            Max.Y = rangeY.Max;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2f(Box2i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2f(Box2l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2f(Box2d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Box2f Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2f.MaxValue, V2f.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Box2f Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2f.MinValue, V2f.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Box2f Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2f.Zero, V2f.One); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreaterOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AllSmallerOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreater(Max) || Min.IsNaN || Max.IsNaN; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n        /// <summary>\n        /// Same as Min.X.\n        /// </summary>\n        [XmlIgnore]\n        public float Left\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.X.\n        /// </summary>\n        [XmlIgnore]\n        public float Right\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Min.Y.\n        /// </summary>\n        [XmlIgnore]\n        public float Top\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.Y = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.Y.\n        /// </summary>\n        [XmlIgnore]\n        public float Bottom\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = value; }\n        }\n\n        /// <summary>\n        /// Calculates size of the box.\n        /// </summary>\n        [XmlIgnore]\n        public V2f Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly V2f Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        [XmlIgnore]\n        public float SizeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X - Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = Min.X + value; }\n        }\n\n        public readonly Range1f RangeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1f(Min.X, Max.X); }\n        }\n\n        [XmlIgnore]\n        public float SizeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y - Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = Min.Y + value; }\n        }\n\n        public readonly Range1f RangeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1f(Min.Y, Max.Y); }\n        }\n\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY > SizeX ? 1 : 0; }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY < SizeX ? 1 : 0; }\n        }\n\n        public readonly float Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeX * SizeY; }\n        }\n\n        public readonly V2f OO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Min; } }\n        public readonly V2f IO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V2f(Max.X, Min.Y); } }\n        public readonly V2f OI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V2f(Min.X, Max.Y); } }\n        public readonly V2f II { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Max; } }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return box enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f EnlargedBy(V2f increment)\n        {\n            return new Box2f((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return box enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f EnlargedBy(V2f deltaMin, V2f deltaMax)\n        {\n            return new Box2f((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f ShrunkBy(V2f delta)\n        {\n            return new Box2f((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f ShrunkBy(V2f deltaMin, V2f deltaMax)\n        {\n            return new Box2f((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V2f delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V2f deltaMin, V2f deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V2f delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V2f deltaMin, V2f deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f EnlargedBy(float delta)\n        {\n            return new Box2f(\n                    new V2f(Min.X - delta, Min.Y - delta),\n                    new V2f(Max.X + delta, Max.Y + delta));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f ShrunkBy(float delta)\n        {\n            return new Box2f(\n                    new V2f(Min.X + delta, Min.Y + delta),\n                    new V2f(Max.X - delta, Max.Y - delta));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f EnlargedBy(\n                float deltaMinX, float deltaMaxX, \n                float deltaMinY, float deltaMaxY)\n        {\n            return new Box2f(\n                    new V2f(Min.X - deltaMinX, Min.Y - deltaMinY),\n                    new V2f(Max.X + deltaMaxX, Max.Y + deltaMaxY));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f ShrunkBy(\n                float deltaMinX, float deltaMaxX, \n                float deltaMinY, float deltaMaxY)\n        {\n            return new Box2f(\n                    new V2f(Min.X + deltaMinX, Min.Y + deltaMinY),\n                    new V2f(Max.X - deltaMaxX, Max.Y - deltaMaxY));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(float delta)\n        {\n            Min.X -= delta; Max.X += delta;\n            Min.Y -= delta; Max.Y += delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(float delta)\n        {\n            Min.X += delta; Max.X -= delta;\n            Min.Y += delta; Max.Y -= delta;\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(\n                float deltaMinX, float deltaMaxX, \n                float deltaMinY, float deltaMaxY)\n        {\n            Min.X -= deltaMinX; Max.X += deltaMaxX;\n            Min.Y -= deltaMinY; Max.Y += deltaMaxY;\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(\n                float deltaMinX, float deltaMaxX, \n                float deltaMinY, float deltaMaxY)\n        {\n            Min.X += deltaMinX; Max.X -= deltaMaxX;\n            Min.Y += deltaMinY; Max.Y -= deltaMaxY;\n        }\n\n        /// <summary>\n        /// Return box scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f ScaledFromCenterBy(float factor)\n        {\n            var size = Size;\n            var increment = (size * factor - size) / 2;\n            return new Box2f(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return box scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f ScaledFromCenterBy(V2f vectorFactor)\n        {\n            var size = Size;\n            var increment = (size * vectorFactor - size) / 2;\n            return new Box2f(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return a box enlarged in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f EnlargedByRelativeEps(float eps)\n        {\n            return EnlargedBy(eps * Size.Length);\n        }\n\n        /// <summary>\n        /// Enlarge the box in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeByRelativeEps(float eps)\n        {\n            EnlargeBy(eps * Size.Length);\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Clamped(V2f p)\n        {\n            return new V2f(\n                        p.X < Min.X ? Min.X : (p.X > Max.X ? Max.X : p.X), \n                        p.Y < Min.Y ? Min.Y : (p.Y > Max.Y ? Max.Y : p.Y));\n        }\n\n        /// <summary>\n        /// Returns the squared distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double DistanceSquared(V2f p)\n        {\n            return \n                (p.X < Min.X ? (Min.X - p.X) * (Min.X - p.X) : (p.X > Max.X ? (p.X - Max.X) * (p.X - Max.X) : 0.0)) + \n                (p.Y < Min.Y ? (Min.Y - p.Y) * (Min.Y - p.Y) : (p.Y > Max.Y ? (p.Y - Max.Y) * (p.Y - Max.Y) : 0.0));\n        }\n\n        /// <summary>\n        /// Returns the distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Distance(V2f p)\n        {\n            return Fun.Sqrt(\n                (p.X < Min.X ? (Min.X - p.X) * (Min.X - p.X) : (p.X > Max.X ? (p.X - Max.X) * (p.X - Max.X) : 0.0)) + \n                (p.Y < Min.Y ? (Min.Y - p.Y) * (Min.Y - p.Y) : (p.Y > Max.Y ? (p.Y - Max.Y) * (p.Y - Max.Y) : 0.0)));\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Lerp(float x)\n            => Fun.Lerp(x, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Lerp(V2f p)\n            => Fun.Lerp(p, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Lerp(float x, float y)\n            => Fun.Lerp(new V2f(x, y), Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f InvLerp(V2f p)\n            => Fun.InvLerp(p, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f InvLerp(float x, float y)\n            => Fun.InvLerp(new V2f(x, y), Min, Max);\n\n\n        /// <summary>\n        /// Returns the box with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitRight(V2f splitValue)\n        {\n            var result = new Box2f(Min, Max);\n            if (splitValue.X > result.Min.X) result.Min.X = splitValue.X;\n            if (splitValue.Y > result.Min.Y) result.Min.Y = splitValue.Y;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitLeft(V2f splitValue)\n        {\n            var result = new Box2f(Min, Max);\n            if (splitValue.X < result.Max.X) result.Max.X = splitValue.X;\n            if (splitValue.Y < result.Max.Y) result.Max.Y = splitValue.Y;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Min.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitRight(float splitAtX)\n        {\n            if (splitAtX > Max.X) return Box2f.Invalid;\n            if (splitAtX <= Min.X) return this;\n            return new Box2f(new V2f(splitAtX, Min.Y), Max);\n        }\n\n        /// <summary>\n        /// Returns a box with Max.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitLeft(float splitAtX)\n        {\n            if (splitAtX < Min.X) return Box2f.Invalid;\n            if (splitAtX >= Max.X) return this;\n            return new Box2f(Min, new V2f(splitAtX, Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the box with Min.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitTop(float splitAtY)\n        {\n            if (splitAtY > Max.Y) return Box2f.Invalid;\n            if (splitAtY <= Min.Y) return this;\n            return new Box2f(new V2f(Min.X, splitAtY), Max);\n        }\n\n        /// <summary>\n        /// Returns the box with Max.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitBottom(float splitAtY)\n        {\n            if (splitAtY < Min.Y) return Box2f.Invalid;\n            if (splitAtY >= Max.Y) return this;\n            return new Box2f(Min, new V2f(Max.X, splitAtY));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitLeftBottom(V2f splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y < Min.Y) return Box2f.Invalid;\n            return new Box2f(Min, splitAt);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitRightBottom(V2f splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y < Min.Y) return Box2f.Invalid;\n            return new Box2f(new V2f(splitAt.X, Min.Y), new V2f(Max.X, splitAt.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitLeftTop(V2f splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y > Max.Y) return Box2f.Invalid;\n            return new Box2f(new V2f(Min.X, splitAt.Y), new V2f(splitAt.X, Max.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f SplitRightTop(V2f splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y > Max.Y) return Box2f.Invalid;\n            return new Box2f(splitAt, Max);\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f ExtendedBy(Box2f b)\n        {\n            return new Box2f(\n                    new V2f(\n                        b.Min.X < Min.X ? b.Min.X : Min.X, \n                        b.Min.Y < Min.Y ? b.Min.Y : Min.Y),\n                    new V2f(\n                        b.Max.X > Max.X ? b.Max.X : Max.X, \n                        b.Max.Y > Max.Y ? b.Max.Y : Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f ExtendedBy(V2f v)\n        {\n            return new Box2f(\n                    new V2f(\n                        v.X < Min.X ? v.X : Min.X, \n                        v.Y < Min.Y ? v.Y : Min.Y),\n                    new V2f(\n                        v.X > Max.X ? v.X : Max.X, \n                        v.Y > Max.Y ? v.Y : Max.Y));\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Box2f box)\n        {\n            if (box.Min.X < Min.X) Min.X = box.Min.X;\n            if (box.Max.X > Max.X) Max.X = box.Max.X;\n            if (box.Min.Y < Min.Y) Min.Y = box.Min.Y;\n            if (box.Max.Y > Max.Y) Max.Y = box.Max.Y;\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(V2f point)\n        {\n            if (point.X < Min.X) Min.X = point.X;\n            if (point.X > Max.X) Max.X = point.X;\n            if (point.Y < Min.Y) Min.Y = point.Y;\n            if (point.Y > Max.Y) Max.Y = point.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f ExtendXBy(float x)\n        {\n            if (x < Min.X) Min.X = x;\n            if (x > Max.X) Max.X = x;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f ExtendYBy(float y)\n        {\n            if (y < Min.Y) Min.Y = y;\n            if (y > Max.Y) Max.Y = y;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f ExtendDimBy(int dim, float x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(V2f p)\n        {\n            return\n                p.X >= Min.X && p.X <= Max.X && \n                p.Y >= Min.Y && p.Y <= Max.Y;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Box2f b)\n        {\n            return\n                b.Min.X >= Min.X && b.Max.X <= Max.X && \n                b.Min.Y >= Min.Y && b.Max.Y <= Max.Y;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f Repair()\n        {\n            if (Equals(Box2f.Invalid)) return this;\n            if (Min.X > Max.X) Fun.Swap(ref Min.X, ref Max.X);\n            if (Min.Y > Max.Y) Fun.Swap(ref Min.Y, ref Max.Y);\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2f box)\n        {\n            if (Min.X >= box.Max.X) return false;\n            if (Max.X <= box.Min.X) return false;\n            if (Min.Y >= box.Max.Y) return false;\n            if (Max.Y <= box.Min.Y) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2f box, V2f eps)\n        {\n            if (Min.X - eps.X >= box.Max.X) return false;\n            if (Max.X + eps.X <= box.Min.X) return false;\n            if (Min.Y - eps.Y >= box.Max.Y) return false;\n            if (Max.Y + eps.Y <= box.Min.Y) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2f box, float eps)\n        {\n            if (Min.X - eps >= box.Max.X) return false;\n            if (Max.X + eps <= box.Min.X) return false;\n            if (Min.Y - eps >= box.Max.Y) return false;\n            if (Max.Y + eps <= box.Min.Y) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2f Invalidate()\n        {\n            Min = V2f.MaxValue;\n            Max = V2f.MinValue;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(V2f p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (p0.X < Min.X) bf |= Box.Flags.MinX;\n            else if (p0.X > Max.X) bf |= Box.Flags.MaxX;\n            if (p0.Y < Min.Y) bf |= Box.Flags.MinY;\n            else if (p0.Y > Max.Y) bf |= Box.Flags.MaxY;\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(Box2f b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (b.Min.X < Min.X) bf |= Box.Flags.MinX;\n            if (b.Max.X > Max.X) bf |= Box.Flags.MaxX;\n            if (b.Min.Y < Min.Y) bf |= Box.Flags.MinY;\n            if (b.Max.Y > Max.Y) bf |= Box.Flags.MaxY;\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(V2f v, out V2f vMin, out V2f vMax)\n        {\n            vMin = V2f.MinValue;\n            vMax = V2f.MaxValue;\n            if (v.X >= 0)\n            {\n                vMin.X = Min.X;\n                vMax.X = Max.X;\n            }\n            else\n            {\n                vMin.X = Max.X;\n                vMax.X = Min.X;\n            }\n            if (v.Y >= 0)\n            {\n                vMin.Y = Min.Y;\n                vMax.Y = Max.Y;\n            }\n            else\n            {\n                vMin.Y = Max.Y;\n                vMax.Y = Min.Y;\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Box2f a, Box2f b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Box2f a, Box2f b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f operator +(Box2f box, V2f v)\n        {\n            return new Box2f((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f operator -(Box2f box, V2f v)\n        {\n            return new Box2f((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Box2f other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Box2f o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Box2f, int, V2f> Setter =\n            (ref Box2f box, int i, V2f value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Box2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Box2f(V2f.Parse(x[0].ToString()),\n                                V2f.Parse(x[1].ToString()));\n        }\n\n        public static Box2f Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, V2f.Parse, Box2f.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginB, string betweenB, string endB, string beginV, string betweenV, string endV)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return beginB + Min.ToString(format, fp, beginV, betweenV, endV) + betweenB + Max.ToString(format, fp, beginV, betweenV, endV) + endB;\n        }\n\n        #endregion\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromSize(V2f size)\n        {\n            return new Box2f(V2f.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromMinAndSize(V2f min, V2f size)\n        {\n            return new Box2f(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromCenterAndSize(V2f center, V2f size)\n        {\n            return new Box2f(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromSize(ISize2f iSize)\n        {\n            return new Box2f(\n                V2f.Zero, iSize.Size2f);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromMinAndSize(V2f min, ISize2f iSize)\n        {\n            return new Box2f(\n                min, min + iSize.Size2f);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromCenterAndSize(V2f center, ISize2f iSize)\n        {\n            var size = iSize.Size2f;\n            return new Box2f(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromPoints(V2f p0, V2f p1)\n        {\n            return new Box2f(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromSize(float width, float height)\n        {\n            return Box2f.FromSize(new V2f(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromMinAndSize(V2f min, float width, float height)\n        {\n            return new Box2f(min, min + new V2f(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromMinAndSize(\n            float minX, float minY, float width, float height\n            )\n        {\n            return Box2f.FromMinAndSize(new V2f(minX, minY), new V2f(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromCenterAndSize(V2f center, float width, float height)\n        {\n            return FromCenterAndSize(center, new V2f(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f FromCenterAndSize(\n            float centerX, float centerY, float width, float height\n            )\n        {\n            return FromCenterAndSize(new V2f(centerX, centerY), new V2f(width, height));\n        }\n\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f Translated(V2f shift)\n        {\n            return IsInvalid ? Box2f.Invalid\n                             : new Box2f(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f Scaled(V2f factor)\n        {\n            return IsInvalid ? Box2f.Invalid\n                             : new Box2f(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        public readonly Box2f Transformed(M33f trafo)\n        {\n            if (Min.X > Max.X || Min.Y > Max.Y) return Box2f.Invalid;\n            var t = new V2f(trafo.M02, trafo.M12);\n            var res = new Box2f(t, t);\n            float av, bv;\n            av = trafo.M00 * Min.X;\n            bv = trafo.M00 * Max.X;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M01 * Min.Y;\n            bv = trafo.M01 * Max.Y;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M10 * Min.X;\n            bv = trafo.M10 * Max.X;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M11 * Min.Y;\n            bv = trafo.M11 * Max.Y;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2f Transformed(Trafo2f trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Corner(int index)\n        {\n            return\n                new V2f(\n                        (index & 1) == 0 ? Min.X : Max.X, \n                        (index & 2) == 0 ? Min.Y : Max.Y);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f[] ComputeCorners()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                new(Min.X, Max.Y),\n                Max\n            ];\n        }\n\n        // TODO: Comment and implement for dimensions other than 2.\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f[] ComputeCornersCCW()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                Max,\n                new(Min.X, Max.Y),\n            ];\n        }\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<V2f> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                yield return new V2f(Max.X, Min.Y);\n                yield return new V2f(Min.X, Max.Y);\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n\n        #endregion\n\n        #region Enumerators\n\n        #endregion\n\n        #region IBoundingBox2f Members\n\n        public readonly Box2f BoundingBox2f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n\n        #region IBoundingCircle2f Members\n\n        public readonly Circle2f BoundingCircle2f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Circle2f.Invalid : new Circle2f(Center, 0.5f * Size.Length);\n        }\n\n        #endregion\n\n        #region ISize2f Members\n\n        public readonly V2f Size2f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n    }\n\n    public static partial class Box\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f Union(this Box2f a, Box2f b)\n        {\n            return new Box2f(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f Intersection(this Box2f a, Box2f b)\n        {\n            return new Box2f(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        #endregion\n\n        #region Bounding box for arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f GetBoundingBox(this V2f[] pointArray)\n        {\n            return pointArray.GetBoundingBox(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f GetBoundingBox(this V2f[] pointArray, long count)\n        {\n            return pointArray.GetBoundingBox(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box2f GetBoundingBox(\n                this V2f[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Box2f.Invalid;\n            var box = new Box2f(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box2f GetBoundingBox<T>(this T[] array, long start, long count, Func<T, V2f> pointSelector)\n        {\n            if (count <= 0) return Box2f.Invalid;\n            var box = new Box2f(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for lists\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f GetBoundingBox(this List<V2f> pointList)\n        {\n            return pointList.GetBoundingBox(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the list.\n        /// </summary>\n        public static Box2f GetBoundingBox(this List<V2f> pointList, int count)\n        {\n            if (count <= 0) return Box2f.Invalid;\n            var box = new Box2f(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f GetBoundingBox(this int[] indexArray, V2f[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f GetBoundingBox(this int[] indexArray, int count, V2f[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2f GetBoundingBox(this int[] indexArray, int start, int count, V2f[] pointArray)\n        {\n            if (count <= 0) return Box2f.Invalid;\n            var box = new Box2f(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2f GetBoundingBox<T>(this int[] indexArray, int start, int count, T[] array, Func<T, V2f> pointSelector)\n        {\n            if (count <= 0) return Box2f.Invalid;\n            var box = new Box2f(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f GetBoundingBox(this long[] indexArray, V2f[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2f GetBoundingBox(this long[] indexArray, long count, V2f[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2f GetBoundingBox(this long[] indexArray, long start, long count, V2f[] pointArray)\n        {\n            if (count <= 0) return Box2f.Invalid;\n            var box = new Box2f(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2f GetBoundingBox<T>(this long[] indexArray, long start, long count, T[] array, Func<T, V2f> pointSelector)\n        {\n            if (count <= 0) return Box2f.Invalid;\n            var box = new Box2f(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the collection.\n        /// </summary>\n        public static Box2f GetBoundingBox(this IEnumerable<V2f> points)\n        {\n            var box = Box2f.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box2f a, Box2f b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box2f a, Box2f b, float tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box2d\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Box2d\n        : IEquatable<Box2d>, IRange<V2d, Box2d>, IBoundingBox2d, ISize2d, IBoundingCircle2d, IFormattable\n    {\n        [DataMember]\n        public V2d Min;\n        [DataMember]\n        public V2d Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Box2d from a Box2i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(Box2i b)\n        {\n            Min = (V2d) b.Min;\n            Max = (V2d) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box2d from a Box2l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(Box2l b)\n        {\n            Min = (V2d) b.Min;\n            Max = (V2d) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box2d from a Box2f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(Box2f b)\n        {\n            Min = (V2d) b.Min;\n            Max = (V2d) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(V2d min, V2d max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(double minX, double minY, double maxX, double maxY)\n        {\n            Min.X = minX;\n            Min.Y = minY;\n            Max.X = maxX;\n            Max.Y = maxY;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(V2d pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a box from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(V2d p0, V2d p1, V2d p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a box from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(V2d p0, V2d p1, V2d p2, V2d p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(Box2d range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(Box2d b0, Box2d b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(Box2d b0, Box2d b1, Box2d b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(Box2d b0, Box2d b1, Box2d b2, Box2d b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(V2d[] points) : this((ReadOnlySpan<V2d>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(ReadOnlySpan<V2d> points)\n        {\n            Min = V2d.MaxValue;\n            Max = V2d.MinValue;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(V2d[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d(IEnumerable<V2d> points)\n        {\n            Min = V2d.MaxValue;\n            Max = V2d.MinValue;\n            if (points == null) return;\n            foreach (V2d p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public Box2d(IEnumerable<Box2d> boxes)\n        {\n            Min = V2d.MaxValue;\n            Max = V2d.MinValue;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates box from a Range1 in each direction.\n        /// </summary>\n        public Box2d(Range1d rangeX, Range1d rangeY)\n        {\n            Min.X = rangeX.Min;\n            Max.X = rangeX.Max;\n            Min.Y = rangeY.Min;\n            Max.Y = rangeY.Max;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2d(Box2i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2d(Box2l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box2d(Box2f b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Box2d Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2d.MaxValue, V2d.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Box2d Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2d.MinValue, V2d.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Box2d Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V2d.Zero, V2d.One); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreaterOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AllSmallerOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreater(Max) || Min.IsNaN || Max.IsNaN; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n        /// <summary>\n        /// Same as Min.X.\n        /// </summary>\n        [XmlIgnore]\n        public double Left\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.X.\n        /// </summary>\n        [XmlIgnore]\n        public double Right\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Min.Y.\n        /// </summary>\n        [XmlIgnore]\n        public double Top\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.Y = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.Y.\n        /// </summary>\n        [XmlIgnore]\n        public double Bottom\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = value; }\n        }\n\n        /// <summary>\n        /// Calculates size of the box.\n        /// </summary>\n        [XmlIgnore]\n        public V2d Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly V2d Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        [XmlIgnore]\n        public double SizeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X - Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = Min.X + value; }\n        }\n\n        public readonly Range1d RangeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1d(Min.X, Max.X); }\n        }\n\n        [XmlIgnore]\n        public double SizeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y - Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = Min.Y + value; }\n        }\n\n        public readonly Range1d RangeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1d(Min.Y, Max.Y); }\n        }\n\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY > SizeX ? 1 : 0; }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY < SizeX ? 1 : 0; }\n        }\n\n        public readonly double Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeX * SizeY; }\n        }\n\n        public readonly V2d OO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Min; } }\n        public readonly V2d IO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V2d(Max.X, Min.Y); } }\n        public readonly V2d OI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V2d(Min.X, Max.Y); } }\n        public readonly V2d II { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Max; } }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return box enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d EnlargedBy(V2d increment)\n        {\n            return new Box2d((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return box enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d EnlargedBy(V2d deltaMin, V2d deltaMax)\n        {\n            return new Box2d((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d ShrunkBy(V2d delta)\n        {\n            return new Box2d((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d ShrunkBy(V2d deltaMin, V2d deltaMax)\n        {\n            return new Box2d((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V2d delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V2d deltaMin, V2d deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V2d delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V2d deltaMin, V2d deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d EnlargedBy(double delta)\n        {\n            return new Box2d(\n                    new V2d(Min.X - delta, Min.Y - delta),\n                    new V2d(Max.X + delta, Max.Y + delta));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d ShrunkBy(double delta)\n        {\n            return new Box2d(\n                    new V2d(Min.X + delta, Min.Y + delta),\n                    new V2d(Max.X - delta, Max.Y - delta));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d EnlargedBy(\n                double deltaMinX, double deltaMaxX, \n                double deltaMinY, double deltaMaxY)\n        {\n            return new Box2d(\n                    new V2d(Min.X - deltaMinX, Min.Y - deltaMinY),\n                    new V2d(Max.X + deltaMaxX, Max.Y + deltaMaxY));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d ShrunkBy(\n                double deltaMinX, double deltaMaxX, \n                double deltaMinY, double deltaMaxY)\n        {\n            return new Box2d(\n                    new V2d(Min.X + deltaMinX, Min.Y + deltaMinY),\n                    new V2d(Max.X - deltaMaxX, Max.Y - deltaMaxY));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(double delta)\n        {\n            Min.X -= delta; Max.X += delta;\n            Min.Y -= delta; Max.Y += delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(double delta)\n        {\n            Min.X += delta; Max.X -= delta;\n            Min.Y += delta; Max.Y -= delta;\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(\n                double deltaMinX, double deltaMaxX, \n                double deltaMinY, double deltaMaxY)\n        {\n            Min.X -= deltaMinX; Max.X += deltaMaxX;\n            Min.Y -= deltaMinY; Max.Y += deltaMaxY;\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(\n                double deltaMinX, double deltaMaxX, \n                double deltaMinY, double deltaMaxY)\n        {\n            Min.X += deltaMinX; Max.X -= deltaMaxX;\n            Min.Y += deltaMinY; Max.Y -= deltaMaxY;\n        }\n\n        /// <summary>\n        /// Return box scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d ScaledFromCenterBy(double factor)\n        {\n            var size = Size;\n            var increment = (size * factor - size) / 2;\n            return new Box2d(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return box scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d ScaledFromCenterBy(V2d vectorFactor)\n        {\n            var size = Size;\n            var increment = (size * vectorFactor - size) / 2;\n            return new Box2d(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return a box enlarged in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d EnlargedByRelativeEps(double eps)\n        {\n            return EnlargedBy(eps * Size.Length);\n        }\n\n        /// <summary>\n        /// Enlarge the box in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeByRelativeEps(double eps)\n        {\n            EnlargeBy(eps * Size.Length);\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Clamped(V2d p)\n        {\n            return new V2d(\n                        p.X < Min.X ? Min.X : (p.X > Max.X ? Max.X : p.X), \n                        p.Y < Min.Y ? Min.Y : (p.Y > Max.Y ? Max.Y : p.Y));\n        }\n\n        /// <summary>\n        /// Returns the squared distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double DistanceSquared(V2d p)\n        {\n            return \n                (p.X < Min.X ? (Min.X - p.X) * (Min.X - p.X) : (p.X > Max.X ? (p.X - Max.X) * (p.X - Max.X) : 0.0)) + \n                (p.Y < Min.Y ? (Min.Y - p.Y) * (Min.Y - p.Y) : (p.Y > Max.Y ? (p.Y - Max.Y) * (p.Y - Max.Y) : 0.0));\n        }\n\n        /// <summary>\n        /// Returns the distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Distance(V2d p)\n        {\n            return Fun.Sqrt(\n                (p.X < Min.X ? (Min.X - p.X) * (Min.X - p.X) : (p.X > Max.X ? (p.X - Max.X) * (p.X - Max.X) : 0.0)) + \n                (p.Y < Min.Y ? (Min.Y - p.Y) * (Min.Y - p.Y) : (p.Y > Max.Y ? (p.Y - Max.Y) * (p.Y - Max.Y) : 0.0)));\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Lerp(double x)\n            => Fun.Lerp(x, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Lerp(V2d p)\n            => Fun.Lerp(p, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Lerp(double x, double y)\n            => Fun.Lerp(new V2d(x, y), Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d InvLerp(V2d p)\n            => Fun.InvLerp(p, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d InvLerp(double x, double y)\n            => Fun.InvLerp(new V2d(x, y), Min, Max);\n\n\n        /// <summary>\n        /// Returns the box with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitRight(V2d splitValue)\n        {\n            var result = new Box2d(Min, Max);\n            if (splitValue.X > result.Min.X) result.Min.X = splitValue.X;\n            if (splitValue.Y > result.Min.Y) result.Min.Y = splitValue.Y;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitLeft(V2d splitValue)\n        {\n            var result = new Box2d(Min, Max);\n            if (splitValue.X < result.Max.X) result.Max.X = splitValue.X;\n            if (splitValue.Y < result.Max.Y) result.Max.Y = splitValue.Y;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Min.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitRight(double splitAtX)\n        {\n            if (splitAtX > Max.X) return Box2d.Invalid;\n            if (splitAtX <= Min.X) return this;\n            return new Box2d(new V2d(splitAtX, Min.Y), Max);\n        }\n\n        /// <summary>\n        /// Returns a box with Max.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitLeft(double splitAtX)\n        {\n            if (splitAtX < Min.X) return Box2d.Invalid;\n            if (splitAtX >= Max.X) return this;\n            return new Box2d(Min, new V2d(splitAtX, Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the box with Min.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitTop(double splitAtY)\n        {\n            if (splitAtY > Max.Y) return Box2d.Invalid;\n            if (splitAtY <= Min.Y) return this;\n            return new Box2d(new V2d(Min.X, splitAtY), Max);\n        }\n\n        /// <summary>\n        /// Returns the box with Max.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitBottom(double splitAtY)\n        {\n            if (splitAtY < Min.Y) return Box2d.Invalid;\n            if (splitAtY >= Max.Y) return this;\n            return new Box2d(Min, new V2d(Max.X, splitAtY));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitLeftBottom(V2d splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y < Min.Y) return Box2d.Invalid;\n            return new Box2d(Min, splitAt);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitRightBottom(V2d splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y < Min.Y) return Box2d.Invalid;\n            return new Box2d(new V2d(splitAt.X, Min.Y), new V2d(Max.X, splitAt.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitLeftTop(V2d splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y > Max.Y) return Box2d.Invalid;\n            return new Box2d(new V2d(Min.X, splitAt.Y), new V2d(splitAt.X, Max.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d SplitRightTop(V2d splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y > Max.Y) return Box2d.Invalid;\n            return new Box2d(splitAt, Max);\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d ExtendedBy(Box2d b)\n        {\n            return new Box2d(\n                    new V2d(\n                        b.Min.X < Min.X ? b.Min.X : Min.X, \n                        b.Min.Y < Min.Y ? b.Min.Y : Min.Y),\n                    new V2d(\n                        b.Max.X > Max.X ? b.Max.X : Max.X, \n                        b.Max.Y > Max.Y ? b.Max.Y : Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d ExtendedBy(V2d v)\n        {\n            return new Box2d(\n                    new V2d(\n                        v.X < Min.X ? v.X : Min.X, \n                        v.Y < Min.Y ? v.Y : Min.Y),\n                    new V2d(\n                        v.X > Max.X ? v.X : Max.X, \n                        v.Y > Max.Y ? v.Y : Max.Y));\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Box2d box)\n        {\n            if (box.Min.X < Min.X) Min.X = box.Min.X;\n            if (box.Max.X > Max.X) Max.X = box.Max.X;\n            if (box.Min.Y < Min.Y) Min.Y = box.Min.Y;\n            if (box.Max.Y > Max.Y) Max.Y = box.Max.Y;\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(V2d point)\n        {\n            if (point.X < Min.X) Min.X = point.X;\n            if (point.X > Max.X) Max.X = point.X;\n            if (point.Y < Min.Y) Min.Y = point.Y;\n            if (point.Y > Max.Y) Max.Y = point.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d ExtendXBy(double x)\n        {\n            if (x < Min.X) Min.X = x;\n            if (x > Max.X) Max.X = x;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d ExtendYBy(double y)\n        {\n            if (y < Min.Y) Min.Y = y;\n            if (y > Max.Y) Max.Y = y;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d ExtendDimBy(int dim, double x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(V2d p)\n        {\n            return\n                p.X >= Min.X && p.X <= Max.X && \n                p.Y >= Min.Y && p.Y <= Max.Y;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Box2d b)\n        {\n            return\n                b.Min.X >= Min.X && b.Max.X <= Max.X && \n                b.Min.Y >= Min.Y && b.Max.Y <= Max.Y;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d Repair()\n        {\n            if (Equals(Box2d.Invalid)) return this;\n            if (Min.X > Max.X) Fun.Swap(ref Min.X, ref Max.X);\n            if (Min.Y > Max.Y) Fun.Swap(ref Min.Y, ref Max.Y);\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2d box)\n        {\n            if (Min.X >= box.Max.X) return false;\n            if (Max.X <= box.Min.X) return false;\n            if (Min.Y >= box.Max.Y) return false;\n            if (Max.Y <= box.Min.Y) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2d box, V2d eps)\n        {\n            if (Min.X - eps.X >= box.Max.X) return false;\n            if (Max.X + eps.X <= box.Min.X) return false;\n            if (Min.Y - eps.Y >= box.Max.Y) return false;\n            if (Max.Y + eps.Y <= box.Min.Y) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box2d box, double eps)\n        {\n            if (Min.X - eps >= box.Max.X) return false;\n            if (Max.X + eps <= box.Min.X) return false;\n            if (Min.Y - eps >= box.Max.Y) return false;\n            if (Max.Y + eps <= box.Min.Y) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box2d Invalidate()\n        {\n            Min = V2d.MaxValue;\n            Max = V2d.MinValue;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(V2d p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (p0.X < Min.X) bf |= Box.Flags.MinX;\n            else if (p0.X > Max.X) bf |= Box.Flags.MaxX;\n            if (p0.Y < Min.Y) bf |= Box.Flags.MinY;\n            else if (p0.Y > Max.Y) bf |= Box.Flags.MaxY;\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(Box2d b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (b.Min.X < Min.X) bf |= Box.Flags.MinX;\n            if (b.Max.X > Max.X) bf |= Box.Flags.MaxX;\n            if (b.Min.Y < Min.Y) bf |= Box.Flags.MinY;\n            if (b.Max.Y > Max.Y) bf |= Box.Flags.MaxY;\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(V2d v, out V2d vMin, out V2d vMax)\n        {\n            vMin = V2d.MinValue;\n            vMax = V2d.MaxValue;\n            if (v.X >= 0)\n            {\n                vMin.X = Min.X;\n                vMax.X = Max.X;\n            }\n            else\n            {\n                vMin.X = Max.X;\n                vMax.X = Min.X;\n            }\n            if (v.Y >= 0)\n            {\n                vMin.Y = Min.Y;\n                vMax.Y = Max.Y;\n            }\n            else\n            {\n                vMin.Y = Max.Y;\n                vMax.Y = Min.Y;\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Box2d a, Box2d b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Box2d a, Box2d b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d operator +(Box2d box, V2d v)\n        {\n            return new Box2d((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d operator -(Box2d box, V2d v)\n        {\n            return new Box2d((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Box2d other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Box2d o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Box2d, int, V2d> Setter =\n            (ref Box2d box, int i, V2d value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Box2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Box2d(V2d.Parse(x[0].ToString()),\n                                V2d.Parse(x[1].ToString()));\n        }\n\n        public static Box2d Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, V2d.Parse, Box2d.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginB, string betweenB, string endB, string beginV, string betweenV, string endV)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return beginB + Min.ToString(format, fp, beginV, betweenV, endV) + betweenB + Max.ToString(format, fp, beginV, betweenV, endV) + endB;\n        }\n\n        #endregion\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromSize(V2d size)\n        {\n            return new Box2d(V2d.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromMinAndSize(V2d min, V2d size)\n        {\n            return new Box2d(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromCenterAndSize(V2d center, V2d size)\n        {\n            return new Box2d(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromSize(ISize2d iSize)\n        {\n            return new Box2d(\n                V2d.Zero, iSize.Size2d);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromMinAndSize(V2d min, ISize2d iSize)\n        {\n            return new Box2d(\n                min, min + iSize.Size2d);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromCenterAndSize(V2d center, ISize2d iSize)\n        {\n            var size = iSize.Size2d;\n            return new Box2d(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromPoints(V2d p0, V2d p1)\n        {\n            return new Box2d(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromSize(double width, double height)\n        {\n            return Box2d.FromSize(new V2d(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromMinAndSize(V2d min, double width, double height)\n        {\n            return new Box2d(min, min + new V2d(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromMinAndSize(\n            double minX, double minY, double width, double height\n            )\n        {\n            return Box2d.FromMinAndSize(new V2d(minX, minY), new V2d(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromCenterAndSize(V2d center, double width, double height)\n        {\n            return FromCenterAndSize(center, new V2d(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d FromCenterAndSize(\n            double centerX, double centerY, double width, double height\n            )\n        {\n            return FromCenterAndSize(new V2d(centerX, centerY), new V2d(width, height));\n        }\n\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d Translated(V2d shift)\n        {\n            return IsInvalid ? Box2d.Invalid\n                             : new Box2d(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d Scaled(V2d factor)\n        {\n            return IsInvalid ? Box2d.Invalid\n                             : new Box2d(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        public readonly Box2d Transformed(M33d trafo)\n        {\n            if (Min.X > Max.X || Min.Y > Max.Y) return Box2d.Invalid;\n            var t = new V2d(trafo.M02, trafo.M12);\n            var res = new Box2d(t, t);\n            double av, bv;\n            av = trafo.M00 * Min.X;\n            bv = trafo.M00 * Max.X;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M01 * Min.Y;\n            bv = trafo.M01 * Max.Y;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M10 * Min.X;\n            bv = trafo.M10 * Max.X;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M11 * Min.Y;\n            bv = trafo.M11 * Max.Y;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box2d Transformed(Trafo2d trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Corner(int index)\n        {\n            return\n                new V2d(\n                        (index & 1) == 0 ? Min.X : Max.X, \n                        (index & 2) == 0 ? Min.Y : Max.Y);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d[] ComputeCorners()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                new(Min.X, Max.Y),\n                Max\n            ];\n        }\n\n        // TODO: Comment and implement for dimensions other than 2.\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d[] ComputeCornersCCW()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                Max,\n                new(Min.X, Max.Y),\n            ];\n        }\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<V2d> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                yield return new V2d(Max.X, Min.Y);\n                yield return new V2d(Min.X, Max.Y);\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n\n        #endregion\n\n        #region Enumerators\n\n        #endregion\n\n        #region IBoundingBox2d Members\n\n        public readonly Box2d BoundingBox2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n\n        #region IBoundingCircle2d Members\n\n        public readonly Circle2d BoundingCircle2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Circle2d.Invalid : new Circle2d(Center, 0.5 * Size.Length);\n        }\n\n        #endregion\n\n        #region ISize2d Members\n\n        public readonly V2d Size2d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n    }\n\n    public static partial class Box\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d Union(this Box2d a, Box2d b)\n        {\n            return new Box2d(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d Intersection(this Box2d a, Box2d b)\n        {\n            return new Box2d(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        #endregion\n\n        #region Bounding box for arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d GetBoundingBox(this V2d[] pointArray)\n        {\n            return pointArray.GetBoundingBox(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d GetBoundingBox(this V2d[] pointArray, long count)\n        {\n            return pointArray.GetBoundingBox(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box2d GetBoundingBox(\n                this V2d[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Box2d.Invalid;\n            var box = new Box2d(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box2d GetBoundingBox<T>(this T[] array, long start, long count, Func<T, V2d> pointSelector)\n        {\n            if (count <= 0) return Box2d.Invalid;\n            var box = new Box2d(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for lists\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d GetBoundingBox(this List<V2d> pointList)\n        {\n            return pointList.GetBoundingBox(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the list.\n        /// </summary>\n        public static Box2d GetBoundingBox(this List<V2d> pointList, int count)\n        {\n            if (count <= 0) return Box2d.Invalid;\n            var box = new Box2d(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d GetBoundingBox(this int[] indexArray, V2d[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d GetBoundingBox(this int[] indexArray, int count, V2d[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2d GetBoundingBox(this int[] indexArray, int start, int count, V2d[] pointArray)\n        {\n            if (count <= 0) return Box2d.Invalid;\n            var box = new Box2d(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2d GetBoundingBox<T>(this int[] indexArray, int start, int count, T[] array, Func<T, V2d> pointSelector)\n        {\n            if (count <= 0) return Box2d.Invalid;\n            var box = new Box2d(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d GetBoundingBox(this long[] indexArray, V2d[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box2d GetBoundingBox(this long[] indexArray, long count, V2d[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2d GetBoundingBox(this long[] indexArray, long start, long count, V2d[] pointArray)\n        {\n            if (count <= 0) return Box2d.Invalid;\n            var box = new Box2d(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box2d GetBoundingBox<T>(this long[] indexArray, long start, long count, T[] array, Func<T, V2d> pointSelector)\n        {\n            if (count <= 0) return Box2d.Invalid;\n            var box = new Box2d(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the collection.\n        /// </summary>\n        public static Box2d GetBoundingBox(this IEnumerable<V2d> points)\n        {\n            var box = Box2d.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box2d a, Box2d b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box2d a, Box2d b, double tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box3i\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Box3i\n        : IEquatable<Box3i>, IRange<V3i, Box3i>, IBoundingBox3i, ISize3i, IBoundingSphere3d, IFormattable\n    {\n        [DataMember]\n        public V3i Min;\n        [DataMember]\n        public V3i Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Box3i from a Box3l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(Box3l b)\n        {\n            Min = (V3i) b.Min;\n            Max = (V3i) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box3i from a Box3f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(Box3f b)\n        {\n            Min = (V3i) b.Min;\n            Max = (V3i) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box3i from a Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(Box3d b)\n        {\n            Min = (V3i) b.Min;\n            Max = (V3i) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(V3i min, V3i max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(int minX, int minY, int minZ, int maxX, int maxY, int maxZ)\n        {\n            Min.X = minX;\n            Min.Y = minY;\n            Min.Z = minZ;\n            Max.X = maxX;\n            Max.Y = maxY;\n            Max.Z = maxZ;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(V3i pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a box from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(V3i p0, V3i p1, V3i p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a box from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(V3i p0, V3i p1, V3i p2, V3i p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(Box3i range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(Box3i b0, Box3i b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(Box3i b0, Box3i b1, Box3i b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(Box3i b0, Box3i b1, Box3i b2, Box3i b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(V3i[] points) : this((ReadOnlySpan<V3i>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(ReadOnlySpan<V3i> points)\n        {\n            Min = V3i.MaxValue;\n            Max = V3i.MinValue;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(V3i[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i(IEnumerable<V3i> points)\n        {\n            Min = V3i.MaxValue;\n            Max = V3i.MinValue;\n            if (points == null) return;\n            foreach (V3i p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public Box3i(IEnumerable<Box3i> boxes)\n        {\n            Min = V3i.MaxValue;\n            Max = V3i.MinValue;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates box from a Range1 in each direction.\n        /// </summary>\n        public Box3i(Range1i rangeX, Range1i rangeY, Range1i rangeZ)\n        {\n            Min.X = rangeX.Min;\n            Max.X = rangeX.Max;\n            Min.Y = rangeY.Min;\n            Max.Y = rangeY.Max;\n            Min.Z = rangeZ.Min;\n            Max.Z = rangeZ.Max;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3i(Box3l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3i(Box3f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3i(Box3d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Box3i Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3i.MaxValue, V3i.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Box3i Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3i.MinValue, V3i.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Box3i Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3i.Zero, V3i.One); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreaterOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AllSmallerOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreater(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the box.\n        /// </summary>\n        [XmlIgnore]\n        public V3i Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly V3i Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        [XmlIgnore]\n        public int SizeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X - Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = Min.X + value; }\n        }\n\n        public readonly Range1i RangeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1i(Min.X, Max.X); }\n        }\n\n        [XmlIgnore]\n        public int SizeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y - Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = Min.Y + value; }\n        }\n\n        public readonly Range1i RangeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1i(Min.Y, Max.Y); }\n        }\n\n        [XmlIgnore]\n        public int SizeZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Z - Min.Z; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Z = Min.Z + value; }\n        }\n\n        public readonly Range1i RangeZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1i(Min.Z, Max.Z); }\n        }\n\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int major = 0;\n                var s = Size;\n                if (s.Y > s.X) major = 1;\n                if (s.Z > s[major]) major = 2;\n                return major;\n            }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int minor = 0;\n                var s = Size;\n                if (s.Y < s.X) minor = 1;\n                if (s.Z < s[minor]) minor = 2;\n                return minor;\n            }\n        }\n\n        public readonly int SurfaceArea\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Size;\n                return (s.X * s.Y + s.X * s.Z + s.Y * s.Z) * 2;\n            }\n        }\n\n        public readonly int Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) return 0;\n                return SizeX * SizeY * SizeZ;\n            }\n        }\n\n        public readonly V3i OOO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Min; } }\n        public readonly V3i IOO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3i(Max.X, Min.Y, Min.Z); } }\n        public readonly V3i OIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3i(Min.X, Max.Y, Min.Z); } }\n        public readonly V3i IIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3i(Max.X, Max.Y, Min.Z); } }\n        public readonly V3i OOI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3i(Min.X, Min.Y, Max.Z); } }\n        public readonly V3i IOI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3i(Max.X, Min.Y, Max.Z); } }\n        public readonly V3i OII { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3i(Min.X, Max.Y, Max.Z); } }\n        public readonly V3i III { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Max; } }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return box enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i EnlargedBy(V3i increment)\n        {\n            return new Box3i((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return box enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i EnlargedBy(V3i deltaMin, V3i deltaMax)\n        {\n            return new Box3i((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i ShrunkBy(V3i delta)\n        {\n            return new Box3i((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i ShrunkBy(V3i deltaMin, V3i deltaMax)\n        {\n            return new Box3i((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V3i delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V3i deltaMin, V3i deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V3i delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V3i deltaMin, V3i deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i EnlargedBy(int delta)\n        {\n            return new Box3i(\n                    new V3i(Min.X - delta, Min.Y - delta, Min.Z - delta),\n                    new V3i(Max.X + delta, Max.Y + delta, Max.Z + delta));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i ShrunkBy(int delta)\n        {\n            return new Box3i(\n                    new V3i(Min.X + delta, Min.Y + delta, Min.Z + delta),\n                    new V3i(Max.X - delta, Max.Y - delta, Max.Z - delta));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i EnlargedBy(\n                int deltaMinX, int deltaMaxX, \n                int deltaMinY, int deltaMaxY, \n                int deltaMinZ, int deltaMaxZ)\n        {\n            return new Box3i(\n                    new V3i(Min.X - deltaMinX, Min.Y - deltaMinY, Min.Z - deltaMinZ),\n                    new V3i(Max.X + deltaMaxX, Max.Y + deltaMaxY, Max.Z + deltaMaxZ));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i ShrunkBy(\n                int deltaMinX, int deltaMaxX, \n                int deltaMinY, int deltaMaxY, \n                int deltaMinZ, int deltaMaxZ)\n        {\n            return new Box3i(\n                    new V3i(Min.X + deltaMinX, Min.Y + deltaMinY, Min.Z + deltaMinZ),\n                    new V3i(Max.X - deltaMaxX, Max.Y - deltaMaxY, Max.Z - deltaMaxZ));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(int delta)\n        {\n            Min.X -= delta; Max.X += delta;\n            Min.Y -= delta; Max.Y += delta;\n            Min.Z -= delta; Max.Z += delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(int delta)\n        {\n            Min.X += delta; Max.X -= delta;\n            Min.Y += delta; Max.Y -= delta;\n            Min.Z += delta; Max.Z -= delta;\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(\n                int deltaMinX, int deltaMaxX, \n                int deltaMinY, int deltaMaxY, \n                int deltaMinZ, int deltaMaxZ)\n        {\n            Min.X -= deltaMinX; Max.X += deltaMaxX;\n            Min.Y -= deltaMinY; Max.Y += deltaMaxY;\n            Min.Z -= deltaMinZ; Max.Z += deltaMaxZ;\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(\n                int deltaMinX, int deltaMaxX, \n                int deltaMinY, int deltaMaxY, \n                int deltaMinZ, int deltaMaxZ)\n        {\n            Min.X += deltaMinX; Max.X -= deltaMaxX;\n            Min.Y += deltaMinY; Max.Y -= deltaMaxY;\n            Min.Z += deltaMinZ; Max.Z -= deltaMaxZ;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Clamped(V3i p)\n        {\n            return new V3i(\n                        p.X < Min.X ? Min.X : (p.X > Max.X ? Max.X : p.X), \n                        p.Y < Min.Y ? Min.Y : (p.Y > Max.Y ? Max.Y : p.Y), \n                        p.Z < Min.Z ? Min.Z : (p.Z > Max.Z ? Max.Z : p.Z));\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Lerp(V3f t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Lerp(V3d t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d InvLerp(V3i y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the box with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i SplitRight(V3i splitValue)\n        {\n            var result = new Box3i(Min, Max);\n            if (splitValue.X > result.Min.X) result.Min.X = splitValue.X;\n            if (splitValue.Y > result.Min.Y) result.Min.Y = splitValue.Y;\n            if (splitValue.Z > result.Min.Z) result.Min.Z = splitValue.Z;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i SplitLeft(V3i splitValue)\n        {\n            var result = new Box3i(Min, Max);\n            if (splitValue.X < result.Max.X) result.Max.X = splitValue.X;\n            if (splitValue.Y < result.Max.Y) result.Max.Y = splitValue.Y;\n            if (splitValue.Z < result.Max.Z) result.Max.Z = splitValue.Z;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i ExtendedBy(Box3i b)\n        {\n            return new Box3i(\n                    new V3i(\n                        b.Min.X < Min.X ? b.Min.X : Min.X, \n                        b.Min.Y < Min.Y ? b.Min.Y : Min.Y, \n                        b.Min.Z < Min.Z ? b.Min.Z : Min.Z),\n                    new V3i(\n                        b.Max.X > Max.X ? b.Max.X : Max.X, \n                        b.Max.Y > Max.Y ? b.Max.Y : Max.Y, \n                        b.Max.Z > Max.Z ? b.Max.Z : Max.Z));\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i ExtendedBy(V3i v)\n        {\n            return new Box3i(\n                    new V3i(\n                        v.X < Min.X ? v.X : Min.X, \n                        v.Y < Min.Y ? v.Y : Min.Y, \n                        v.Z < Min.Z ? v.Z : Min.Z),\n                    new V3i(\n                        v.X > Max.X ? v.X : Max.X, \n                        v.Y > Max.Y ? v.Y : Max.Y, \n                        v.Z > Max.Z ? v.Z : Max.Z));\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Box3i box)\n        {\n            if (box.Min.X < Min.X) Min.X = box.Min.X;\n            if (box.Max.X > Max.X) Max.X = box.Max.X;\n            if (box.Min.Y < Min.Y) Min.Y = box.Min.Y;\n            if (box.Max.Y > Max.Y) Max.Y = box.Max.Y;\n            if (box.Min.Z < Min.Z) Min.Z = box.Min.Z;\n            if (box.Max.Z > Max.Z) Max.Z = box.Max.Z;\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(V3i point)\n        {\n            if (point.X < Min.X) Min.X = point.X;\n            if (point.X > Max.X) Max.X = point.X;\n            if (point.Y < Min.Y) Min.Y = point.Y;\n            if (point.Y > Max.Y) Max.Y = point.Y;\n            if (point.Z < Min.Z) Min.Z = point.Z;\n            if (point.Z > Max.Z) Max.Z = point.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i ExtendXBy(int x)\n        {\n            if (x < Min.X) Min.X = x;\n            if (x > Max.X) Max.X = x;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i ExtendYBy(int y)\n        {\n            if (y < Min.Y) Min.Y = y;\n            if (y > Max.Y) Max.Y = y;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i ExtendZBy(int z)\n        {\n            if (z < Min.Z) Min.Z = z;\n            if (z > Max.Z) Max.Z = z;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i ExtendDimBy(int dim, int x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(V3i p)\n        {\n            return\n                p.X >= Min.X && p.X <= Max.X && \n                p.Y >= Min.Y && p.Y <= Max.Y && \n                p.Z >= Min.Z && p.Z <= Max.Z;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Box3i b)\n        {\n            return\n                b.Min.X >= Min.X && b.Max.X <= Max.X && \n                b.Min.Y >= Min.Y && b.Max.Y <= Max.Y && \n                b.Min.Z >= Min.Z && b.Max.Z <= Max.Z;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i Repair()\n        {\n            if (Equals(Box3i.Invalid)) return this;\n            if (Min.X > Max.X) Fun.Swap(ref Min.X, ref Max.X);\n            if (Min.Y > Max.Y) Fun.Swap(ref Min.Y, ref Max.Y);\n            if (Min.Z > Max.Z) Fun.Swap(ref Min.Z, ref Max.Z);\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3i box)\n        {\n            if (Min.X >= box.Max.X) return false;\n            if (Max.X <= box.Min.X) return false;\n            if (Min.Y >= box.Max.Y) return false;\n            if (Max.Y <= box.Min.Y) return false;\n            if (Min.Z >= box.Max.Z) return false;\n            if (Max.Z <= box.Min.Z) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3i box, V3i eps)\n        {\n            if (Min.X - eps.X >= box.Max.X) return false;\n            if (Max.X + eps.X <= box.Min.X) return false;\n            if (Min.Y - eps.Y >= box.Max.Y) return false;\n            if (Max.Y + eps.Y <= box.Min.Y) return false;\n            if (Min.Z - eps.Z >= box.Max.Z) return false;\n            if (Max.Z + eps.Z <= box.Min.Z) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3i box, int eps)\n        {\n            if (Min.X - eps >= box.Max.X) return false;\n            if (Max.X + eps <= box.Min.X) return false;\n            if (Min.Y - eps >= box.Max.Y) return false;\n            if (Max.Y + eps <= box.Min.Y) return false;\n            if (Min.Z - eps >= box.Max.Z) return false;\n            if (Max.Z + eps <= box.Min.Z) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3i Invalidate()\n        {\n            Min = V3i.MaxValue;\n            Max = V3i.MinValue;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(V3i p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (p0.X < Min.X) bf |= Box.Flags.MinX;\n            else if (p0.X > Max.X) bf |= Box.Flags.MaxX;\n            if (p0.Y < Min.Y) bf |= Box.Flags.MinY;\n            else if (p0.Y > Max.Y) bf |= Box.Flags.MaxY;\n            if (p0.Z < Min.Z) bf |= Box.Flags.MinZ;\n            else if (p0.Z > Max.Z) bf |= Box.Flags.MaxZ;\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(Box3i b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (b.Min.X < Min.X) bf |= Box.Flags.MinX;\n            if (b.Max.X > Max.X) bf |= Box.Flags.MaxX;\n            if (b.Min.Y < Min.Y) bf |= Box.Flags.MinY;\n            if (b.Max.Y > Max.Y) bf |= Box.Flags.MaxY;\n            if (b.Min.Z < Min.Z) bf |= Box.Flags.MinZ;\n            if (b.Max.Z > Max.Z) bf |= Box.Flags.MaxZ;\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(V3i v, out V3i vMin, out V3i vMax)\n        {\n            vMin = V3i.MinValue;\n            vMax = V3i.MaxValue;\n            if (v.X >= 0)\n            {\n                vMin.X = Min.X;\n                vMax.X = Max.X;\n            }\n            else\n            {\n                vMin.X = Max.X;\n                vMax.X = Min.X;\n            }\n            if (v.Y >= 0)\n            {\n                vMin.Y = Min.Y;\n                vMax.Y = Max.Y;\n            }\n            else\n            {\n                vMin.Y = Max.Y;\n                vMax.Y = Min.Y;\n            }\n            if (v.Z >= 0)\n            {\n                vMin.Z = Min.Z;\n                vMax.Z = Max.Z;\n            }\n            else\n            {\n                vMin.Z = Max.Z;\n                vMax.Z = Min.Z;\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Box3i a, Box3i b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Box3i a, Box3i b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i operator +(Box3i box, V3i v)\n        {\n            return new Box3i((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i operator -(Box3i box, V3i v)\n        {\n            return new Box3i((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Box3i other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Box3i o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Box3i, int, V3i> Setter =\n            (ref Box3i box, int i, V3i value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Box3i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Box3i(V3i.Parse(x[0].ToString()),\n                                V3i.Parse(x[1].ToString()));\n        }\n\n        public static Box3i Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, V3i.Parse, Box3i.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginB, string betweenB, string endB, string beginV, string betweenV, string endV)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return beginB + Min.ToString(format, fp, beginV, betweenV, endV) + betweenB + Max.ToString(format, fp, beginV, betweenV, endV) + endB;\n        }\n\n        #endregion\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i FromSize(V3i size)\n        {\n            return new Box3i(V3i.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i FromMinAndSize(V3i min, V3i size)\n        {\n            return new Box3i(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i FromCenterAndSize(V3i center, V3i size)\n        {\n            return new Box3i(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i FromSize(ISize3i iSize)\n        {\n            return new Box3i(\n                V3i.Zero, iSize.Size3i);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i FromMinAndSize(V3i min, ISize3i iSize)\n        {\n            return new Box3i(\n                min, min + iSize.Size3i);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i FromCenterAndSize(V3i center, ISize3i iSize)\n        {\n            var size = iSize.Size3i;\n            return new Box3i(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i FromPoints(V3i p0, V3i p1)\n        {\n            return new Box3i(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i Translated(V3i shift)\n        {\n            return IsInvalid ? Box3i.Invalid\n                             : new Box3i(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3i Scaled(V3i factor)\n        {\n            return IsInvalid ? Box3i.Invalid\n                             : new Box3i(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        public readonly Box3d Transformed(M44d trafo)\n        {\n            if (Min.X > Max.X || Min.Y > Max.Y || Min.Z > Max.Z) return Box3d.Invalid;\n            var t = new V3d(trafo.M03, trafo.M13, trafo.M23);\n            var res = new Box3d(t, t);\n            double av, bv;\n            av = trafo.M00 * Min.X;\n            bv = trafo.M00 * Max.X;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M01 * Min.Y;\n            bv = trafo.M01 * Max.Y;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M02 * Min.Z;\n            bv = trafo.M02 * Max.Z;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M10 * Min.X;\n            bv = trafo.M10 * Max.X;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M11 * Min.Y;\n            bv = trafo.M11 * Max.Y;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M12 * Min.Z;\n            bv = trafo.M12 * Max.Z;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M20 * Min.X;\n            bv = trafo.M20 * Max.X;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            av = trafo.M21 * Min.Y;\n            bv = trafo.M21 * Max.Y;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            av = trafo.M22 * Min.Z;\n            bv = trafo.M22 * Max.Z;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d Transformed(Trafo3d trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Corner(int index)\n        {\n            return\n                new V3i(\n                        (index & 1) == 0 ? Min.X : Max.X, \n                        (index & 2) == 0 ? Min.Y : Max.Y, \n                        (index & 4) == 0 ? Min.Z : Max.Z);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i[] ComputeCorners()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y, Min.Z),\n                new(Min.X, Max.Y, Min.Z),\n                new(Max.X, Max.Y, Min.Z),\n                new(Min.X, Min.Y, Max.Z),\n                new(Max.X, Min.Y, Max.Z),\n                new(Min.X, Max.Y, Max.Z),\n                Max\n            ];\n        }\n\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<V3i> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                yield return new V3i(Max.X, Min.Y, Min.Z);\n                yield return new V3i(Min.X, Max.Y, Min.Z);\n                yield return new V3i(Max.X, Max.Y, Min.Z);\n                yield return new V3i(Min.X, Min.Y, Max.Z);\n                yield return new V3i(Max.X, Min.Y, Max.Z);\n                yield return new V3i(Min.X, Max.Y, Max.Z);\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n        // TODO: Implement for other dimensions\n        public readonly Range1i X { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1i(Min.X, Max.X); } }\n        public readonly Range1i Y { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1i(Min.Y, Max.Y); } }\n        public readonly Range1i Z { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1i(Min.Z, Max.Z); } }\n        public readonly Box2i XY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2i(Min.XY, Max.XY); } }\n        public readonly Box2i XZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2i(Min.XZ, Max.XZ); } }\n        public readonly Box2i YX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2i(Min.YX, Max.YX); } }\n        public readonly Box2i YZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2i(Min.YZ, Max.YZ); } }\n        public readonly Box2i ZX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2i(Min.ZX, Max.ZX); } }\n        public readonly Box2i ZY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2i(Min.ZY, Max.ZY); } }\n\n        #endregion\n\n        #region Enumerators\n\n        /// <summary>\n        /// Returns all points from [Min,Max[ with X-Variable in the outer loop.\n        /// </summary>\n        public readonly IEnumerable<V3i> EnumerateInsidePoints()\n        {\n            var p = new V3i();\n            for (p.X = Min.X; p.X < Max.X; p.X++)\n            for (p.Y = Min.Y; p.Y < Max.Y; p.Y++)\n            for (p.Z = Min.Z; p.Z < Max.Z; p.Z++)\n                yield return p;\n        }\n\n        #endregion\n\n        #region IBoundingBox3i Members\n\n        public readonly Box3i BoundingBox3i\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n\n        #region IBoundingSphere3d Members\n\n        public readonly Sphere3d BoundingSphere3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Sphere3d.Invalid : new Sphere3d((V3d)Center, 0.5 * Size.Length);\n        }\n\n        #endregion\n\n        #region ISize3i Members\n\n        public readonly V3i Size3i\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n    }\n\n    public static partial class Box\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i Union(this Box3i a, Box3i b)\n        {\n            return new Box3i(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i Intersection(this Box3i a, Box3i b)\n        {\n            return new Box3i(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        #endregion\n\n        #region Bounding box for arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i GetBoundingBox(this V3i[] pointArray)\n        {\n            return pointArray.GetBoundingBox(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i GetBoundingBox(this V3i[] pointArray, long count)\n        {\n            return pointArray.GetBoundingBox(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box3i GetBoundingBox(\n                this V3i[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Box3i.Invalid;\n            var box = new Box3i(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box3i GetBoundingBox<T>(this T[] array, long start, long count, Func<T, V3i> pointSelector)\n        {\n            if (count <= 0) return Box3i.Invalid;\n            var box = new Box3i(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for lists\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i GetBoundingBox(this List<V3i> pointList)\n        {\n            return pointList.GetBoundingBox(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the list.\n        /// </summary>\n        public static Box3i GetBoundingBox(this List<V3i> pointList, int count)\n        {\n            if (count <= 0) return Box3i.Invalid;\n            var box = new Box3i(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i GetBoundingBox(this int[] indexArray, V3i[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i GetBoundingBox(this int[] indexArray, int count, V3i[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3i GetBoundingBox(this int[] indexArray, int start, int count, V3i[] pointArray)\n        {\n            if (count <= 0) return Box3i.Invalid;\n            var box = new Box3i(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3i GetBoundingBox<T>(this int[] indexArray, int start, int count, T[] array, Func<T, V3i> pointSelector)\n        {\n            if (count <= 0) return Box3i.Invalid;\n            var box = new Box3i(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i GetBoundingBox(this long[] indexArray, V3i[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3i GetBoundingBox(this long[] indexArray, long count, V3i[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3i GetBoundingBox(this long[] indexArray, long start, long count, V3i[] pointArray)\n        {\n            if (count <= 0) return Box3i.Invalid;\n            var box = new Box3i(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3i GetBoundingBox<T>(this long[] indexArray, long start, long count, T[] array, Func<T, V3i> pointSelector)\n        {\n            if (count <= 0) return Box3i.Invalid;\n            var box = new Box3i(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the collection.\n        /// </summary>\n        public static Box3i GetBoundingBox(this IEnumerable<V3i> points)\n        {\n            var box = Box3i.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n\n        #region Get octant\n\n        /// <summary>\n        /// Octant 0-7.\n        /// 0th, 1st and 2nd bit encodes x-, y-, z-axis, respectively.\n        /// E.g. 0 is octant [box.Min, box.Center], 7 is octant [box.Center, box.Max].\n        /// </summary>\n        public static Box3i GetOctant(this Box3i box, int i)\n        {\n            if (i < 0 || i > 7) throw new IndexOutOfRangeException();\n\n            int x0, x1, y0, y1, z0, z1;\n            var c = box.Center;\n            if ((i & 1) == 0) { x0 = box.Min.X; x1 = c.X; } else { x0 = c.X; x1 = box.Max.X; }\n            if ((i & 2) == 0) { y0 = box.Min.Y; y1 = c.Y; } else { y0 = c.Y; y1 = box.Max.Y; }\n            if (i < 4) { z0 = box.Min.Z; z1 = c.Z; } else { z0 = c.Z; z1 = box.Max.Z; }\n            return new Box3i(new V3i(x0, y0, z0), new V3i(x1, y1, z1));\n        }\n\n        #endregion\n\n        #region Outline corners\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCCW(this Box3i box, V3i fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 4, 6, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 5, 7, 2];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 4, 6, 2];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 1, 3, 7, 6, 4];\n                }\n                    else\n                    { // +X -Y  Z\n                        return [0, 3, 7, 4];\n            }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 3, 2, 6, 4, 5];\n}\n                    else\n                    { // +X +Y  Z\n                        return [1, 2, 6, 5];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 2, 7, 5];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 3, 6, 4];\n}\n                    else\n                    { // +X  Y  Z\n                        return [1, 3, 7, 5];\n}\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 3, 5, 4];\n        }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 1, 7, 6];\n    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 1, 5, 4];\n}\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 6, 7, 1];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 4, 5, 3];\n}\n                    else\n                    { //  X +Y  Z\n                        return [2, 6, 7, 3];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 2, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 5, 7, 6];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCW(this Box3i box, V3i fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 3, 2, 6, 4, 5];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 2, 6, 5];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 1, 3, 7, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 3, 7, 4];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 3, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 2, 7, 5];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 2, 6, 4];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else\n                    { // +X -Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else\n                    { // +X +Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 5, 7, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 4, 6, 3];\n                    }\n                    else\n                    { // +X  Y  Z\n                        return [1, 5, 7, 3];\n                    }\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 4, 5, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 6, 7, 1];\n                    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 4, 5, 1];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 1, 7, 6];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 3, 5, 4];\n                    }\n                    else\n                    { //  X +Y  Z\n                        return [2, 3, 7, 6];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 1, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 6, 7, 5];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static V3i[] GetOutlineCornersCCW(this Box3i box, V3i fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static V3i[] GetOutlineCornersCW(this Box3i box, V3i fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box3i a, Box3i b)\n        {\n            return ApproximateEquals(a, b, Constant<int>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box3i a, Box3i b, int tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box3iAndFlags\n\n    [DataContract]\n    public struct Box3iAndFlags\n    {\n        [DataMember]\n        public Box.Flags BFlags;\n        [DataMember]\n        public Box3i BBox;\n\n        public Box3iAndFlags(Box3i union, Box3i box0, Box3i box1)\n        {\n            BFlags = 0;\n            BBox = union;\n            if (box0.Min.X > union.Min.X) { BBox.Min.X = box0.Min.X; BFlags |= Box.Flags.MinX0; }\n            if (box0.Min.Y > union.Min.Y) { BBox.Min.Y = box0.Min.Y; BFlags |= Box.Flags.MinY0; }\n            if (box0.Min.Z > union.Min.Z) { BBox.Min.Z = box0.Min.Z; BFlags |= Box.Flags.MinZ0; }\n            if (box0.Max.X < union.Max.X) { BBox.Max.X = box0.Max.X; BFlags |= Box.Flags.MaxX0; }\n            if (box0.Max.Y < union.Max.Y) { BBox.Max.Y = box0.Max.Y; BFlags |= Box.Flags.MaxY0; }\n            if (box0.Max.Z < union.Max.Z) { BBox.Max.Z = box0.Max.Z; BFlags |= Box.Flags.MaxZ0; }\n            if (box1.Min.X > union.Min.X) { BBox.Min.X = box1.Min.X; BFlags |= Box.Flags.MinX1; }\n            if (box1.Min.Y > union.Min.Y) { BBox.Min.Y = box1.Min.Y; BFlags |= Box.Flags.MinY1; }\n            if (box1.Min.Z > union.Min.Z) { BBox.Min.Z = box1.Min.Z; BFlags |= Box.Flags.MinZ1; }\n            if (box1.Max.X < union.Max.X) { BBox.Max.X = box1.Max.X; BFlags |= Box.Flags.MaxX1; }\n            if (box1.Max.Y < union.Max.Y) { BBox.Max.Y = box1.Max.Y; BFlags |= Box.Flags.MaxY1; }\n            if (box1.Max.Z < union.Max.Z) { BBox.Max.Z = box1.Max.Z; BFlags |= Box.Flags.MaxZ1; }\n        }\n    }\n\n    #endregion\n\n    #region Box3l\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Box3l\n        : IEquatable<Box3l>, IRange<V3l, Box3l>, IBoundingBox3l, ISize3l, IBoundingSphere3d, IFormattable\n    {\n        [DataMember]\n        public V3l Min;\n        [DataMember]\n        public V3l Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Box3l from a Box3i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(Box3i b)\n        {\n            Min = (V3l) b.Min;\n            Max = (V3l) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box3l from a Box3f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(Box3f b)\n        {\n            Min = (V3l) b.Min;\n            Max = (V3l) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box3l from a Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(Box3d b)\n        {\n            Min = (V3l) b.Min;\n            Max = (V3l) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(V3l min, V3l max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(long minX, long minY, long minZ, long maxX, long maxY, long maxZ)\n        {\n            Min.X = minX;\n            Min.Y = minY;\n            Min.Z = minZ;\n            Max.X = maxX;\n            Max.Y = maxY;\n            Max.Z = maxZ;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(V3l pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a box from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(V3l p0, V3l p1, V3l p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a box from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(V3l p0, V3l p1, V3l p2, V3l p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(Box3l range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(Box3l b0, Box3l b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(Box3l b0, Box3l b1, Box3l b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(Box3l b0, Box3l b1, Box3l b2, Box3l b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(V3l[] points) : this((ReadOnlySpan<V3l>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(ReadOnlySpan<V3l> points)\n        {\n            Min = V3l.MaxValue;\n            Max = V3l.MinValue;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(V3l[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l(IEnumerable<V3l> points)\n        {\n            Min = V3l.MaxValue;\n            Max = V3l.MinValue;\n            if (points == null) return;\n            foreach (V3l p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public Box3l(IEnumerable<Box3l> boxes)\n        {\n            Min = V3l.MaxValue;\n            Max = V3l.MinValue;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates box from a Range1 in each direction.\n        /// </summary>\n        public Box3l(Range1l rangeX, Range1l rangeY, Range1l rangeZ)\n        {\n            Min.X = rangeX.Min;\n            Max.X = rangeX.Max;\n            Min.Y = rangeY.Min;\n            Max.Y = rangeY.Max;\n            Min.Z = rangeZ.Min;\n            Max.Z = rangeZ.Max;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3l(Box3i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3l(Box3f b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3l(Box3d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Box3l Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3l.MaxValue, V3l.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Box3l Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3l.MinValue, V3l.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Box3l Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3l.Zero, V3l.One); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreaterOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AllSmallerOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreater(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the box.\n        /// </summary>\n        [XmlIgnore]\n        public V3l Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly V3l Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        [XmlIgnore]\n        public long SizeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X - Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = Min.X + value; }\n        }\n\n        public readonly Range1l RangeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1l(Min.X, Max.X); }\n        }\n\n        [XmlIgnore]\n        public long SizeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y - Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = Min.Y + value; }\n        }\n\n        public readonly Range1l RangeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1l(Min.Y, Max.Y); }\n        }\n\n        [XmlIgnore]\n        public long SizeZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Z - Min.Z; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Z = Min.Z + value; }\n        }\n\n        public readonly Range1l RangeZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1l(Min.Z, Max.Z); }\n        }\n\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int major = 0;\n                var s = Size;\n                if (s.Y > s.X) major = 1;\n                if (s.Z > s[major]) major = 2;\n                return major;\n            }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int minor = 0;\n                var s = Size;\n                if (s.Y < s.X) minor = 1;\n                if (s.Z < s[minor]) minor = 2;\n                return minor;\n            }\n        }\n\n        public readonly long SurfaceArea\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Size;\n                return (s.X * s.Y + s.X * s.Z + s.Y * s.Z) * 2;\n            }\n        }\n\n        public readonly long Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) return 0;\n                return SizeX * SizeY * SizeZ;\n            }\n        }\n\n        public readonly V3l OOO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Min; } }\n        public readonly V3l IOO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3l(Max.X, Min.Y, Min.Z); } }\n        public readonly V3l OIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3l(Min.X, Max.Y, Min.Z); } }\n        public readonly V3l IIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3l(Max.X, Max.Y, Min.Z); } }\n        public readonly V3l OOI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3l(Min.X, Min.Y, Max.Z); } }\n        public readonly V3l IOI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3l(Max.X, Min.Y, Max.Z); } }\n        public readonly V3l OII { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3l(Min.X, Max.Y, Max.Z); } }\n        public readonly V3l III { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Max; } }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return box enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l EnlargedBy(V3l increment)\n        {\n            return new Box3l((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return box enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l EnlargedBy(V3l deltaMin, V3l deltaMax)\n        {\n            return new Box3l((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l ShrunkBy(V3l delta)\n        {\n            return new Box3l((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l ShrunkBy(V3l deltaMin, V3l deltaMax)\n        {\n            return new Box3l((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V3l delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V3l deltaMin, V3l deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V3l delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V3l deltaMin, V3l deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l EnlargedBy(long delta)\n        {\n            return new Box3l(\n                    new V3l(Min.X - delta, Min.Y - delta, Min.Z - delta),\n                    new V3l(Max.X + delta, Max.Y + delta, Max.Z + delta));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l ShrunkBy(long delta)\n        {\n            return new Box3l(\n                    new V3l(Min.X + delta, Min.Y + delta, Min.Z + delta),\n                    new V3l(Max.X - delta, Max.Y - delta, Max.Z - delta));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l EnlargedBy(\n                long deltaMinX, long deltaMaxX, \n                long deltaMinY, long deltaMaxY, \n                long deltaMinZ, long deltaMaxZ)\n        {\n            return new Box3l(\n                    new V3l(Min.X - deltaMinX, Min.Y - deltaMinY, Min.Z - deltaMinZ),\n                    new V3l(Max.X + deltaMaxX, Max.Y + deltaMaxY, Max.Z + deltaMaxZ));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l ShrunkBy(\n                long deltaMinX, long deltaMaxX, \n                long deltaMinY, long deltaMaxY, \n                long deltaMinZ, long deltaMaxZ)\n        {\n            return new Box3l(\n                    new V3l(Min.X + deltaMinX, Min.Y + deltaMinY, Min.Z + deltaMinZ),\n                    new V3l(Max.X - deltaMaxX, Max.Y - deltaMaxY, Max.Z - deltaMaxZ));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(long delta)\n        {\n            Min.X -= delta; Max.X += delta;\n            Min.Y -= delta; Max.Y += delta;\n            Min.Z -= delta; Max.Z += delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(long delta)\n        {\n            Min.X += delta; Max.X -= delta;\n            Min.Y += delta; Max.Y -= delta;\n            Min.Z += delta; Max.Z -= delta;\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(\n                long deltaMinX, long deltaMaxX, \n                long deltaMinY, long deltaMaxY, \n                long deltaMinZ, long deltaMaxZ)\n        {\n            Min.X -= deltaMinX; Max.X += deltaMaxX;\n            Min.Y -= deltaMinY; Max.Y += deltaMaxY;\n            Min.Z -= deltaMinZ; Max.Z += deltaMaxZ;\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(\n                long deltaMinX, long deltaMaxX, \n                long deltaMinY, long deltaMaxY, \n                long deltaMinZ, long deltaMaxZ)\n        {\n            Min.X += deltaMinX; Max.X -= deltaMaxX;\n            Min.Y += deltaMinY; Max.Y -= deltaMaxY;\n            Min.Z += deltaMinZ; Max.Z -= deltaMaxZ;\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Clamped(V3l p)\n        {\n            return new V3l(\n                        p.X < Min.X ? Min.X : (p.X > Max.X ? Max.X : p.X), \n                        p.Y < Min.Y ? Min.Y : (p.Y > Max.Y ? Max.Y : p.Y), \n                        p.Z < Min.Z ? Min.Z : (p.Z > Max.Z ? Max.Z : p.Z));\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Lerp(float t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Lerp(V3f t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Lerp(double t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Lerp(V3d t)\n            => Fun.Lerp(t, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d InvLerp(V3l y)\n            => Fun.InvLerp(y, Min, Max);\n\n\n        /// <summary>\n        /// Returns the box with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l SplitRight(V3l splitValue)\n        {\n            var result = new Box3l(Min, Max);\n            if (splitValue.X > result.Min.X) result.Min.X = splitValue.X;\n            if (splitValue.Y > result.Min.Y) result.Min.Y = splitValue.Y;\n            if (splitValue.Z > result.Min.Z) result.Min.Z = splitValue.Z;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l SplitLeft(V3l splitValue)\n        {\n            var result = new Box3l(Min, Max);\n            if (splitValue.X < result.Max.X) result.Max.X = splitValue.X;\n            if (splitValue.Y < result.Max.Y) result.Max.Y = splitValue.Y;\n            if (splitValue.Z < result.Max.Z) result.Max.Z = splitValue.Z;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l ExtendedBy(Box3l b)\n        {\n            return new Box3l(\n                    new V3l(\n                        b.Min.X < Min.X ? b.Min.X : Min.X, \n                        b.Min.Y < Min.Y ? b.Min.Y : Min.Y, \n                        b.Min.Z < Min.Z ? b.Min.Z : Min.Z),\n                    new V3l(\n                        b.Max.X > Max.X ? b.Max.X : Max.X, \n                        b.Max.Y > Max.Y ? b.Max.Y : Max.Y, \n                        b.Max.Z > Max.Z ? b.Max.Z : Max.Z));\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l ExtendedBy(V3l v)\n        {\n            return new Box3l(\n                    new V3l(\n                        v.X < Min.X ? v.X : Min.X, \n                        v.Y < Min.Y ? v.Y : Min.Y, \n                        v.Z < Min.Z ? v.Z : Min.Z),\n                    new V3l(\n                        v.X > Max.X ? v.X : Max.X, \n                        v.Y > Max.Y ? v.Y : Max.Y, \n                        v.Z > Max.Z ? v.Z : Max.Z));\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Box3l box)\n        {\n            if (box.Min.X < Min.X) Min.X = box.Min.X;\n            if (box.Max.X > Max.X) Max.X = box.Max.X;\n            if (box.Min.Y < Min.Y) Min.Y = box.Min.Y;\n            if (box.Max.Y > Max.Y) Max.Y = box.Max.Y;\n            if (box.Min.Z < Min.Z) Min.Z = box.Min.Z;\n            if (box.Max.Z > Max.Z) Max.Z = box.Max.Z;\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(V3l point)\n        {\n            if (point.X < Min.X) Min.X = point.X;\n            if (point.X > Max.X) Max.X = point.X;\n            if (point.Y < Min.Y) Min.Y = point.Y;\n            if (point.Y > Max.Y) Max.Y = point.Y;\n            if (point.Z < Min.Z) Min.Z = point.Z;\n            if (point.Z > Max.Z) Max.Z = point.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l ExtendXBy(long x)\n        {\n            if (x < Min.X) Min.X = x;\n            if (x > Max.X) Max.X = x;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l ExtendYBy(long y)\n        {\n            if (y < Min.Y) Min.Y = y;\n            if (y > Max.Y) Max.Y = y;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l ExtendZBy(long z)\n        {\n            if (z < Min.Z) Min.Z = z;\n            if (z > Max.Z) Max.Z = z;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l ExtendDimBy(int dim, long x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(V3l p)\n        {\n            return\n                p.X >= Min.X && p.X <= Max.X && \n                p.Y >= Min.Y && p.Y <= Max.Y && \n                p.Z >= Min.Z && p.Z <= Max.Z;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Box3l b)\n        {\n            return\n                b.Min.X >= Min.X && b.Max.X <= Max.X && \n                b.Min.Y >= Min.Y && b.Max.Y <= Max.Y && \n                b.Min.Z >= Min.Z && b.Max.Z <= Max.Z;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l Repair()\n        {\n            if (Equals(Box3l.Invalid)) return this;\n            if (Min.X > Max.X) Fun.Swap(ref Min.X, ref Max.X);\n            if (Min.Y > Max.Y) Fun.Swap(ref Min.Y, ref Max.Y);\n            if (Min.Z > Max.Z) Fun.Swap(ref Min.Z, ref Max.Z);\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3l box)\n        {\n            if (Min.X >= box.Max.X) return false;\n            if (Max.X <= box.Min.X) return false;\n            if (Min.Y >= box.Max.Y) return false;\n            if (Max.Y <= box.Min.Y) return false;\n            if (Min.Z >= box.Max.Z) return false;\n            if (Max.Z <= box.Min.Z) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3l box, V3l eps)\n        {\n            if (Min.X - eps.X >= box.Max.X) return false;\n            if (Max.X + eps.X <= box.Min.X) return false;\n            if (Min.Y - eps.Y >= box.Max.Y) return false;\n            if (Max.Y + eps.Y <= box.Min.Y) return false;\n            if (Min.Z - eps.Z >= box.Max.Z) return false;\n            if (Max.Z + eps.Z <= box.Min.Z) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3l box, long eps)\n        {\n            if (Min.X - eps >= box.Max.X) return false;\n            if (Max.X + eps <= box.Min.X) return false;\n            if (Min.Y - eps >= box.Max.Y) return false;\n            if (Max.Y + eps <= box.Min.Y) return false;\n            if (Min.Z - eps >= box.Max.Z) return false;\n            if (Max.Z + eps <= box.Min.Z) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3l Invalidate()\n        {\n            Min = V3l.MaxValue;\n            Max = V3l.MinValue;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(V3l p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (p0.X < Min.X) bf |= Box.Flags.MinX;\n            else if (p0.X > Max.X) bf |= Box.Flags.MaxX;\n            if (p0.Y < Min.Y) bf |= Box.Flags.MinY;\n            else if (p0.Y > Max.Y) bf |= Box.Flags.MaxY;\n            if (p0.Z < Min.Z) bf |= Box.Flags.MinZ;\n            else if (p0.Z > Max.Z) bf |= Box.Flags.MaxZ;\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(Box3l b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (b.Min.X < Min.X) bf |= Box.Flags.MinX;\n            if (b.Max.X > Max.X) bf |= Box.Flags.MaxX;\n            if (b.Min.Y < Min.Y) bf |= Box.Flags.MinY;\n            if (b.Max.Y > Max.Y) bf |= Box.Flags.MaxY;\n            if (b.Min.Z < Min.Z) bf |= Box.Flags.MinZ;\n            if (b.Max.Z > Max.Z) bf |= Box.Flags.MaxZ;\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(V3l v, out V3l vMin, out V3l vMax)\n        {\n            vMin = V3l.MinValue;\n            vMax = V3l.MaxValue;\n            if (v.X >= 0)\n            {\n                vMin.X = Min.X;\n                vMax.X = Max.X;\n            }\n            else\n            {\n                vMin.X = Max.X;\n                vMax.X = Min.X;\n            }\n            if (v.Y >= 0)\n            {\n                vMin.Y = Min.Y;\n                vMax.Y = Max.Y;\n            }\n            else\n            {\n                vMin.Y = Max.Y;\n                vMax.Y = Min.Y;\n            }\n            if (v.Z >= 0)\n            {\n                vMin.Z = Min.Z;\n                vMax.Z = Max.Z;\n            }\n            else\n            {\n                vMin.Z = Max.Z;\n                vMax.Z = Min.Z;\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Box3l a, Box3l b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Box3l a, Box3l b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l operator +(Box3l box, V3l v)\n        {\n            return new Box3l((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l operator -(Box3l box, V3l v)\n        {\n            return new Box3l((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Box3l other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Box3l o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Box3l, int, V3l> Setter =\n            (ref Box3l box, int i, V3l value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Box3l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Box3l(V3l.Parse(x[0].ToString()),\n                                V3l.Parse(x[1].ToString()));\n        }\n\n        public static Box3l Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, V3l.Parse, Box3l.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginB, string betweenB, string endB, string beginV, string betweenV, string endV)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return beginB + Min.ToString(format, fp, beginV, betweenV, endV) + betweenB + Max.ToString(format, fp, beginV, betweenV, endV) + endB;\n        }\n\n        #endregion\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l FromSize(V3l size)\n        {\n            return new Box3l(V3l.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l FromMinAndSize(V3l min, V3l size)\n        {\n            return new Box3l(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l FromCenterAndSize(V3l center, V3l size)\n        {\n            return new Box3l(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l FromSize(ISize3l iSize)\n        {\n            return new Box3l(\n                V3l.Zero, iSize.Size3l);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l FromMinAndSize(V3l min, ISize3l iSize)\n        {\n            return new Box3l(\n                min, min + iSize.Size3l);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l FromCenterAndSize(V3l center, ISize3l iSize)\n        {\n            var size = iSize.Size3l;\n            return new Box3l(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l FromPoints(V3l p0, V3l p1)\n        {\n            return new Box3l(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l Translated(V3l shift)\n        {\n            return IsInvalid ? Box3l.Invalid\n                             : new Box3l(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3l Scaled(V3l factor)\n        {\n            return IsInvalid ? Box3l.Invalid\n                             : new Box3l(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        public readonly Box3d Transformed(M44d trafo)\n        {\n            if (Min.X > Max.X || Min.Y > Max.Y || Min.Z > Max.Z) return Box3d.Invalid;\n            var t = new V3d(trafo.M03, trafo.M13, trafo.M23);\n            var res = new Box3d(t, t);\n            double av, bv;\n            av = trafo.M00 * Min.X;\n            bv = trafo.M00 * Max.X;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M01 * Min.Y;\n            bv = trafo.M01 * Max.Y;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M02 * Min.Z;\n            bv = trafo.M02 * Max.Z;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M10 * Min.X;\n            bv = trafo.M10 * Max.X;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M11 * Min.Y;\n            bv = trafo.M11 * Max.Y;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M12 * Min.Z;\n            bv = trafo.M12 * Max.Z;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M20 * Min.X;\n            bv = trafo.M20 * Max.X;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            av = trafo.M21 * Min.Y;\n            bv = trafo.M21 * Max.Y;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            av = trafo.M22 * Min.Z;\n            bv = trafo.M22 * Max.Z;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d Transformed(Trafo3d trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Corner(int index)\n        {\n            return\n                new V3l(\n                        (index & 1) == 0 ? Min.X : Max.X, \n                        (index & 2) == 0 ? Min.Y : Max.Y, \n                        (index & 4) == 0 ? Min.Z : Max.Z);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l[] ComputeCorners()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y, Min.Z),\n                new(Min.X, Max.Y, Min.Z),\n                new(Max.X, Max.Y, Min.Z),\n                new(Min.X, Min.Y, Max.Z),\n                new(Max.X, Min.Y, Max.Z),\n                new(Min.X, Max.Y, Max.Z),\n                Max\n            ];\n        }\n\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<V3l> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                yield return new V3l(Max.X, Min.Y, Min.Z);\n                yield return new V3l(Min.X, Max.Y, Min.Z);\n                yield return new V3l(Max.X, Max.Y, Min.Z);\n                yield return new V3l(Min.X, Min.Y, Max.Z);\n                yield return new V3l(Max.X, Min.Y, Max.Z);\n                yield return new V3l(Min.X, Max.Y, Max.Z);\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n        // TODO: Implement for other dimensions\n        public readonly Range1l X { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1l(Min.X, Max.X); } }\n        public readonly Range1l Y { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1l(Min.Y, Max.Y); } }\n        public readonly Range1l Z { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1l(Min.Z, Max.Z); } }\n        public readonly Box2l XY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2l(Min.XY, Max.XY); } }\n        public readonly Box2l XZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2l(Min.XZ, Max.XZ); } }\n        public readonly Box2l YX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2l(Min.YX, Max.YX); } }\n        public readonly Box2l YZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2l(Min.YZ, Max.YZ); } }\n        public readonly Box2l ZX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2l(Min.ZX, Max.ZX); } }\n        public readonly Box2l ZY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2l(Min.ZY, Max.ZY); } }\n\n        #endregion\n\n        #region Enumerators\n\n        /// <summary>\n        /// Returns all points from [Min,Max[ with X-Variable in the outer loop.\n        /// </summary>\n        public readonly IEnumerable<V3l> EnumerateInsidePoints()\n        {\n            var p = new V3l();\n            for (p.X = Min.X; p.X < Max.X; p.X++)\n            for (p.Y = Min.Y; p.Y < Max.Y; p.Y++)\n            for (p.Z = Min.Z; p.Z < Max.Z; p.Z++)\n                yield return p;\n        }\n\n        #endregion\n\n        #region IBoundingBox3l Members\n\n        public readonly Box3l BoundingBox3l\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n\n        #region IBoundingSphere3d Members\n\n        public readonly Sphere3d BoundingSphere3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Sphere3d.Invalid : new Sphere3d((V3d)Center, 0.5 * Size.Length);\n        }\n\n        #endregion\n\n        #region ISize3l Members\n\n        public readonly V3l Size3l\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n    }\n\n    public static partial class Box\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l Union(this Box3l a, Box3l b)\n        {\n            return new Box3l(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l Intersection(this Box3l a, Box3l b)\n        {\n            return new Box3l(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        #endregion\n\n        #region Bounding box for arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l GetBoundingBox(this V3l[] pointArray)\n        {\n            return pointArray.GetBoundingBox(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l GetBoundingBox(this V3l[] pointArray, long count)\n        {\n            return pointArray.GetBoundingBox(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box3l GetBoundingBox(\n                this V3l[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Box3l.Invalid;\n            var box = new Box3l(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box3l GetBoundingBox<T>(this T[] array, long start, long count, Func<T, V3l> pointSelector)\n        {\n            if (count <= 0) return Box3l.Invalid;\n            var box = new Box3l(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for lists\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l GetBoundingBox(this List<V3l> pointList)\n        {\n            return pointList.GetBoundingBox(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the list.\n        /// </summary>\n        public static Box3l GetBoundingBox(this List<V3l> pointList, int count)\n        {\n            if (count <= 0) return Box3l.Invalid;\n            var box = new Box3l(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l GetBoundingBox(this int[] indexArray, V3l[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l GetBoundingBox(this int[] indexArray, int count, V3l[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3l GetBoundingBox(this int[] indexArray, int start, int count, V3l[] pointArray)\n        {\n            if (count <= 0) return Box3l.Invalid;\n            var box = new Box3l(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3l GetBoundingBox<T>(this int[] indexArray, int start, int count, T[] array, Func<T, V3l> pointSelector)\n        {\n            if (count <= 0) return Box3l.Invalid;\n            var box = new Box3l(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l GetBoundingBox(this long[] indexArray, V3l[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3l GetBoundingBox(this long[] indexArray, long count, V3l[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3l GetBoundingBox(this long[] indexArray, long start, long count, V3l[] pointArray)\n        {\n            if (count <= 0) return Box3l.Invalid;\n            var box = new Box3l(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3l GetBoundingBox<T>(this long[] indexArray, long start, long count, T[] array, Func<T, V3l> pointSelector)\n        {\n            if (count <= 0) return Box3l.Invalid;\n            var box = new Box3l(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the collection.\n        /// </summary>\n        public static Box3l GetBoundingBox(this IEnumerable<V3l> points)\n        {\n            var box = Box3l.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n\n        #region Get octant\n\n        /// <summary>\n        /// Octant 0-7.\n        /// 0th, 1st and 2nd bit encodes x-, y-, z-axis, respectively.\n        /// E.g. 0 is octant [box.Min, box.Center], 7 is octant [box.Center, box.Max].\n        /// </summary>\n        public static Box3l GetOctant(this Box3l box, int i)\n        {\n            if (i < 0 || i > 7) throw new IndexOutOfRangeException();\n\n            long x0, x1, y0, y1, z0, z1;\n            var c = box.Center;\n            if ((i & 1) == 0) { x0 = box.Min.X; x1 = c.X; } else { x0 = c.X; x1 = box.Max.X; }\n            if ((i & 2) == 0) { y0 = box.Min.Y; y1 = c.Y; } else { y0 = c.Y; y1 = box.Max.Y; }\n            if (i < 4) { z0 = box.Min.Z; z1 = c.Z; } else { z0 = c.Z; z1 = box.Max.Z; }\n            return new Box3l(new V3l(x0, y0, z0), new V3l(x1, y1, z1));\n        }\n\n        #endregion\n\n        #region Outline corners\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCCW(this Box3l box, V3l fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 4, 6, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 5, 7, 2];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 4, 6, 2];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 1, 3, 7, 6, 4];\n                }\n                    else\n                    { // +X -Y  Z\n                        return [0, 3, 7, 4];\n            }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 3, 2, 6, 4, 5];\n}\n                    else\n                    { // +X +Y  Z\n                        return [1, 2, 6, 5];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 2, 7, 5];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 3, 6, 4];\n}\n                    else\n                    { // +X  Y  Z\n                        return [1, 3, 7, 5];\n}\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 3, 5, 4];\n        }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 1, 7, 6];\n    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 1, 5, 4];\n}\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 6, 7, 1];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 4, 5, 3];\n}\n                    else\n                    { //  X +Y  Z\n                        return [2, 6, 7, 3];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 2, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 5, 7, 6];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCW(this Box3l box, V3l fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 3, 2, 6, 4, 5];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 2, 6, 5];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 1, 3, 7, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 3, 7, 4];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 3, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 2, 7, 5];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 2, 6, 4];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else\n                    { // +X -Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else\n                    { // +X +Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 5, 7, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 4, 6, 3];\n                    }\n                    else\n                    { // +X  Y  Z\n                        return [1, 5, 7, 3];\n                    }\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 4, 5, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 6, 7, 1];\n                    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 4, 5, 1];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 1, 7, 6];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 3, 5, 4];\n                    }\n                    else\n                    { //  X +Y  Z\n                        return [2, 3, 7, 6];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 1, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 6, 7, 5];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static V3l[] GetOutlineCornersCCW(this Box3l box, V3l fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static V3l[] GetOutlineCornersCW(this Box3l box, V3l fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box3l a, Box3l b)\n        {\n            return ApproximateEquals(a, b, Constant<long>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box3l a, Box3l b, long tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box3lAndFlags\n\n    [DataContract]\n    public struct Box3lAndFlags\n    {\n        [DataMember]\n        public Box.Flags BFlags;\n        [DataMember]\n        public Box3l BBox;\n\n        public Box3lAndFlags(Box3l union, Box3l box0, Box3l box1)\n        {\n            BFlags = 0;\n            BBox = union;\n            if (box0.Min.X > union.Min.X) { BBox.Min.X = box0.Min.X; BFlags |= Box.Flags.MinX0; }\n            if (box0.Min.Y > union.Min.Y) { BBox.Min.Y = box0.Min.Y; BFlags |= Box.Flags.MinY0; }\n            if (box0.Min.Z > union.Min.Z) { BBox.Min.Z = box0.Min.Z; BFlags |= Box.Flags.MinZ0; }\n            if (box0.Max.X < union.Max.X) { BBox.Max.X = box0.Max.X; BFlags |= Box.Flags.MaxX0; }\n            if (box0.Max.Y < union.Max.Y) { BBox.Max.Y = box0.Max.Y; BFlags |= Box.Flags.MaxY0; }\n            if (box0.Max.Z < union.Max.Z) { BBox.Max.Z = box0.Max.Z; BFlags |= Box.Flags.MaxZ0; }\n            if (box1.Min.X > union.Min.X) { BBox.Min.X = box1.Min.X; BFlags |= Box.Flags.MinX1; }\n            if (box1.Min.Y > union.Min.Y) { BBox.Min.Y = box1.Min.Y; BFlags |= Box.Flags.MinY1; }\n            if (box1.Min.Z > union.Min.Z) { BBox.Min.Z = box1.Min.Z; BFlags |= Box.Flags.MinZ1; }\n            if (box1.Max.X < union.Max.X) { BBox.Max.X = box1.Max.X; BFlags |= Box.Flags.MaxX1; }\n            if (box1.Max.Y < union.Max.Y) { BBox.Max.Y = box1.Max.Y; BFlags |= Box.Flags.MaxY1; }\n            if (box1.Max.Z < union.Max.Z) { BBox.Max.Z = box1.Max.Z; BFlags |= Box.Flags.MaxZ1; }\n        }\n    }\n\n    #endregion\n\n    #region Box3f\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Box3f\n        : IEquatable<Box3f>, IRange<V3f, Box3f>, IBoundingBox3f, ISize3f, IBoundingSphere3f, IFormattable\n    {\n        [DataMember]\n        public V3f Min;\n        [DataMember]\n        public V3f Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Box3f from a Box3i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(Box3i b)\n        {\n            Min = (V3f) b.Min;\n            Max = (V3f) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box3f from a Box3l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(Box3l b)\n        {\n            Min = (V3f) b.Min;\n            Max = (V3f) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box3f from a Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(Box3d b)\n        {\n            Min = (V3f) b.Min;\n            Max = (V3f) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(V3f min, V3f max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)\n        {\n            Min.X = minX;\n            Min.Y = minY;\n            Min.Z = minZ;\n            Max.X = maxX;\n            Max.Y = maxY;\n            Max.Z = maxZ;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(V3f pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a box from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(V3f p0, V3f p1, V3f p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a box from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(V3f p0, V3f p1, V3f p2, V3f p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(Box3f range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(Box3f b0, Box3f b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(Box3f b0, Box3f b1, Box3f b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(Box3f b0, Box3f b1, Box3f b2, Box3f b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(V3f[] points) : this((ReadOnlySpan<V3f>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(ReadOnlySpan<V3f> points)\n        {\n            Min = V3f.MaxValue;\n            Max = V3f.MinValue;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(V3f[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f(IEnumerable<V3f> points)\n        {\n            Min = V3f.MaxValue;\n            Max = V3f.MinValue;\n            if (points == null) return;\n            foreach (V3f p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public Box3f(IEnumerable<Box3f> boxes)\n        {\n            Min = V3f.MaxValue;\n            Max = V3f.MinValue;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates box from a Range1 in each direction.\n        /// </summary>\n        public Box3f(Range1f rangeX, Range1f rangeY, Range1f rangeZ)\n        {\n            Min.X = rangeX.Min;\n            Max.X = rangeX.Max;\n            Min.Y = rangeY.Min;\n            Max.Y = rangeY.Max;\n            Min.Z = rangeZ.Min;\n            Max.Z = rangeZ.Max;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3f(Box3i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3f(Box3l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3f(Box3d b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Box3f Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3f.MaxValue, V3f.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Box3f Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3f.MinValue, V3f.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Box3f Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3f.Zero, V3f.One); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreaterOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AllSmallerOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreater(Max) || Min.IsNaN || Max.IsNaN; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the box.\n        /// </summary>\n        [XmlIgnore]\n        public V3f Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly V3f Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        [XmlIgnore]\n        public float SizeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X - Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = Min.X + value; }\n        }\n\n        public readonly Range1f RangeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1f(Min.X, Max.X); }\n        }\n\n        [XmlIgnore]\n        public float SizeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y - Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = Min.Y + value; }\n        }\n\n        public readonly Range1f RangeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1f(Min.Y, Max.Y); }\n        }\n\n        [XmlIgnore]\n        public float SizeZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Z - Min.Z; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Z = Min.Z + value; }\n        }\n\n        public readonly Range1f RangeZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1f(Min.Z, Max.Z); }\n        }\n\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int major = 0;\n                var s = Size;\n                if (s.Y > s.X) major = 1;\n                if (s.Z > s[major]) major = 2;\n                return major;\n            }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int minor = 0;\n                var s = Size;\n                if (s.Y < s.X) minor = 1;\n                if (s.Z < s[minor]) minor = 2;\n                return minor;\n            }\n        }\n\n        public readonly float SurfaceArea\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Size;\n                return (s.X * s.Y + s.X * s.Z + s.Y * s.Z) * 2;\n            }\n        }\n\n        public readonly float Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) return 0;\n                return SizeX * SizeY * SizeZ;\n            }\n        }\n\n        public readonly V3f OOO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Min; } }\n        public readonly V3f IOO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3f(Max.X, Min.Y, Min.Z); } }\n        public readonly V3f OIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3f(Min.X, Max.Y, Min.Z); } }\n        public readonly V3f IIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3f(Max.X, Max.Y, Min.Z); } }\n        public readonly V3f OOI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3f(Min.X, Min.Y, Max.Z); } }\n        public readonly V3f IOI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3f(Max.X, Min.Y, Max.Z); } }\n        public readonly V3f OII { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3f(Min.X, Max.Y, Max.Z); } }\n        public readonly V3f III { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Max; } }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return box enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f EnlargedBy(V3f increment)\n        {\n            return new Box3f((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return box enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f EnlargedBy(V3f deltaMin, V3f deltaMax)\n        {\n            return new Box3f((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f ShrunkBy(V3f delta)\n        {\n            return new Box3f((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f ShrunkBy(V3f deltaMin, V3f deltaMax)\n        {\n            return new Box3f((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V3f delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V3f deltaMin, V3f deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V3f delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V3f deltaMin, V3f deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f EnlargedBy(float delta)\n        {\n            return new Box3f(\n                    new V3f(Min.X - delta, Min.Y - delta, Min.Z - delta),\n                    new V3f(Max.X + delta, Max.Y + delta, Max.Z + delta));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f ShrunkBy(float delta)\n        {\n            return new Box3f(\n                    new V3f(Min.X + delta, Min.Y + delta, Min.Z + delta),\n                    new V3f(Max.X - delta, Max.Y - delta, Max.Z - delta));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f EnlargedBy(\n                float deltaMinX, float deltaMaxX, \n                float deltaMinY, float deltaMaxY, \n                float deltaMinZ, float deltaMaxZ)\n        {\n            return new Box3f(\n                    new V3f(Min.X - deltaMinX, Min.Y - deltaMinY, Min.Z - deltaMinZ),\n                    new V3f(Max.X + deltaMaxX, Max.Y + deltaMaxY, Max.Z + deltaMaxZ));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f ShrunkBy(\n                float deltaMinX, float deltaMaxX, \n                float deltaMinY, float deltaMaxY, \n                float deltaMinZ, float deltaMaxZ)\n        {\n            return new Box3f(\n                    new V3f(Min.X + deltaMinX, Min.Y + deltaMinY, Min.Z + deltaMinZ),\n                    new V3f(Max.X - deltaMaxX, Max.Y - deltaMaxY, Max.Z - deltaMaxZ));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(float delta)\n        {\n            Min.X -= delta; Max.X += delta;\n            Min.Y -= delta; Max.Y += delta;\n            Min.Z -= delta; Max.Z += delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(float delta)\n        {\n            Min.X += delta; Max.X -= delta;\n            Min.Y += delta; Max.Y -= delta;\n            Min.Z += delta; Max.Z -= delta;\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(\n                float deltaMinX, float deltaMaxX, \n                float deltaMinY, float deltaMaxY, \n                float deltaMinZ, float deltaMaxZ)\n        {\n            Min.X -= deltaMinX; Max.X += deltaMaxX;\n            Min.Y -= deltaMinY; Max.Y += deltaMaxY;\n            Min.Z -= deltaMinZ; Max.Z += deltaMaxZ;\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(\n                float deltaMinX, float deltaMaxX, \n                float deltaMinY, float deltaMaxY, \n                float deltaMinZ, float deltaMaxZ)\n        {\n            Min.X += deltaMinX; Max.X -= deltaMaxX;\n            Min.Y += deltaMinY; Max.Y -= deltaMaxY;\n            Min.Z += deltaMinZ; Max.Z -= deltaMaxZ;\n        }\n\n        /// <summary>\n        /// Return box scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f ScaledFromCenterBy(float factor)\n        {\n            var size = Size;\n            var increment = (size * factor - size) / 2;\n            return new Box3f(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return box scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f ScaledFromCenterBy(V3f vectorFactor)\n        {\n            var size = Size;\n            var increment = (size * vectorFactor - size) / 2;\n            return new Box3f(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return a box enlarged in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f EnlargedByRelativeEps(float eps)\n        {\n            return EnlargedBy(eps * Size.Length);\n        }\n\n        /// <summary>\n        /// Enlarge the box in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeByRelativeEps(float eps)\n        {\n            EnlargeBy(eps * Size.Length);\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Clamped(V3f p)\n        {\n            return new V3f(\n                        p.X < Min.X ? Min.X : (p.X > Max.X ? Max.X : p.X), \n                        p.Y < Min.Y ? Min.Y : (p.Y > Max.Y ? Max.Y : p.Y), \n                        p.Z < Min.Z ? Min.Z : (p.Z > Max.Z ? Max.Z : p.Z));\n        }\n\n        /// <summary>\n        /// Returns the squared distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double DistanceSquared(V3f p)\n        {\n            return \n                (p.X < Min.X ? (Min.X - p.X) * (Min.X - p.X) : (p.X > Max.X ? (p.X - Max.X) * (p.X - Max.X) : 0.0)) + \n                (p.Y < Min.Y ? (Min.Y - p.Y) * (Min.Y - p.Y) : (p.Y > Max.Y ? (p.Y - Max.Y) * (p.Y - Max.Y) : 0.0)) + \n                (p.Z < Min.Z ? (Min.Z - p.Z) * (Min.Z - p.Z) : (p.Z > Max.Z ? (p.Z - Max.Z) * (p.Z - Max.Z) : 0.0));\n        }\n\n        /// <summary>\n        /// Returns the distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Distance(V3f p)\n        {\n            return Fun.Sqrt(\n                (p.X < Min.X ? (Min.X - p.X) * (Min.X - p.X) : (p.X > Max.X ? (p.X - Max.X) * (p.X - Max.X) : 0.0)) + \n                (p.Y < Min.Y ? (Min.Y - p.Y) * (Min.Y - p.Y) : (p.Y > Max.Y ? (p.Y - Max.Y) * (p.Y - Max.Y) : 0.0)) + \n                (p.Z < Min.Z ? (Min.Z - p.Z) * (Min.Z - p.Z) : (p.Z > Max.Z ? (p.Z - Max.Z) * (p.Z - Max.Z) : 0.0)));\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Lerp(float x)\n            => Fun.Lerp(x, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Lerp(V3f p)\n            => Fun.Lerp(p, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Lerp(float x, float y, float z)\n            => Fun.Lerp(new V3f(x, y, z), Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f InvLerp(V3f p)\n            => Fun.InvLerp(p, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f InvLerp(float x, float y, float z)\n            => Fun.InvLerp(new V3f(x, y, z), Min, Max);\n\n\n        /// <summary>\n        /// Returns the box with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f SplitRight(V3f splitValue)\n        {\n            var result = new Box3f(Min, Max);\n            if (splitValue.X > result.Min.X) result.Min.X = splitValue.X;\n            if (splitValue.Y > result.Min.Y) result.Min.Y = splitValue.Y;\n            if (splitValue.Z > result.Min.Z) result.Min.Z = splitValue.Z;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f SplitLeft(V3f splitValue)\n        {\n            var result = new Box3f(Min, Max);\n            if (splitValue.X < result.Max.X) result.Max.X = splitValue.X;\n            if (splitValue.Y < result.Max.Y) result.Max.Y = splitValue.Y;\n            if (splitValue.Z < result.Max.Z) result.Max.Z = splitValue.Z;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f ExtendedBy(Box3f b)\n        {\n            return new Box3f(\n                    new V3f(\n                        b.Min.X < Min.X ? b.Min.X : Min.X, \n                        b.Min.Y < Min.Y ? b.Min.Y : Min.Y, \n                        b.Min.Z < Min.Z ? b.Min.Z : Min.Z),\n                    new V3f(\n                        b.Max.X > Max.X ? b.Max.X : Max.X, \n                        b.Max.Y > Max.Y ? b.Max.Y : Max.Y, \n                        b.Max.Z > Max.Z ? b.Max.Z : Max.Z));\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f ExtendedBy(V3f v)\n        {\n            return new Box3f(\n                    new V3f(\n                        v.X < Min.X ? v.X : Min.X, \n                        v.Y < Min.Y ? v.Y : Min.Y, \n                        v.Z < Min.Z ? v.Z : Min.Z),\n                    new V3f(\n                        v.X > Max.X ? v.X : Max.X, \n                        v.Y > Max.Y ? v.Y : Max.Y, \n                        v.Z > Max.Z ? v.Z : Max.Z));\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Box3f box)\n        {\n            if (box.Min.X < Min.X) Min.X = box.Min.X;\n            if (box.Max.X > Max.X) Max.X = box.Max.X;\n            if (box.Min.Y < Min.Y) Min.Y = box.Min.Y;\n            if (box.Max.Y > Max.Y) Max.Y = box.Max.Y;\n            if (box.Min.Z < Min.Z) Min.Z = box.Min.Z;\n            if (box.Max.Z > Max.Z) Max.Z = box.Max.Z;\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(V3f point)\n        {\n            if (point.X < Min.X) Min.X = point.X;\n            if (point.X > Max.X) Max.X = point.X;\n            if (point.Y < Min.Y) Min.Y = point.Y;\n            if (point.Y > Max.Y) Max.Y = point.Y;\n            if (point.Z < Min.Z) Min.Z = point.Z;\n            if (point.Z > Max.Z) Max.Z = point.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f ExtendXBy(float x)\n        {\n            if (x < Min.X) Min.X = x;\n            if (x > Max.X) Max.X = x;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f ExtendYBy(float y)\n        {\n            if (y < Min.Y) Min.Y = y;\n            if (y > Max.Y) Max.Y = y;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f ExtendZBy(float z)\n        {\n            if (z < Min.Z) Min.Z = z;\n            if (z > Max.Z) Max.Z = z;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f ExtendDimBy(int dim, float x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(V3f p)\n        {\n            return\n                p.X >= Min.X && p.X <= Max.X && \n                p.Y >= Min.Y && p.Y <= Max.Y && \n                p.Z >= Min.Z && p.Z <= Max.Z;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Box3f b)\n        {\n            return\n                b.Min.X >= Min.X && b.Max.X <= Max.X && \n                b.Min.Y >= Min.Y && b.Max.Y <= Max.Y && \n                b.Min.Z >= Min.Z && b.Max.Z <= Max.Z;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f Repair()\n        {\n            if (Equals(Box3f.Invalid)) return this;\n            if (Min.X > Max.X) Fun.Swap(ref Min.X, ref Max.X);\n            if (Min.Y > Max.Y) Fun.Swap(ref Min.Y, ref Max.Y);\n            if (Min.Z > Max.Z) Fun.Swap(ref Min.Z, ref Max.Z);\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3f box)\n        {\n            if (Min.X >= box.Max.X) return false;\n            if (Max.X <= box.Min.X) return false;\n            if (Min.Y >= box.Max.Y) return false;\n            if (Max.Y <= box.Min.Y) return false;\n            if (Min.Z >= box.Max.Z) return false;\n            if (Max.Z <= box.Min.Z) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3f box, V3f eps)\n        {\n            if (Min.X - eps.X >= box.Max.X) return false;\n            if (Max.X + eps.X <= box.Min.X) return false;\n            if (Min.Y - eps.Y >= box.Max.Y) return false;\n            if (Max.Y + eps.Y <= box.Min.Y) return false;\n            if (Min.Z - eps.Z >= box.Max.Z) return false;\n            if (Max.Z + eps.Z <= box.Min.Z) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3f box, float eps)\n        {\n            if (Min.X - eps >= box.Max.X) return false;\n            if (Max.X + eps <= box.Min.X) return false;\n            if (Min.Y - eps >= box.Max.Y) return false;\n            if (Max.Y + eps <= box.Min.Y) return false;\n            if (Min.Z - eps >= box.Max.Z) return false;\n            if (Max.Z + eps <= box.Min.Z) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3f Invalidate()\n        {\n            Min = V3f.MaxValue;\n            Max = V3f.MinValue;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(V3f p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (p0.X < Min.X) bf |= Box.Flags.MinX;\n            else if (p0.X > Max.X) bf |= Box.Flags.MaxX;\n            if (p0.Y < Min.Y) bf |= Box.Flags.MinY;\n            else if (p0.Y > Max.Y) bf |= Box.Flags.MaxY;\n            if (p0.Z < Min.Z) bf |= Box.Flags.MinZ;\n            else if (p0.Z > Max.Z) bf |= Box.Flags.MaxZ;\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(Box3f b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (b.Min.X < Min.X) bf |= Box.Flags.MinX;\n            if (b.Max.X > Max.X) bf |= Box.Flags.MaxX;\n            if (b.Min.Y < Min.Y) bf |= Box.Flags.MinY;\n            if (b.Max.Y > Max.Y) bf |= Box.Flags.MaxY;\n            if (b.Min.Z < Min.Z) bf |= Box.Flags.MinZ;\n            if (b.Max.Z > Max.Z) bf |= Box.Flags.MaxZ;\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(V3f v, out V3f vMin, out V3f vMax)\n        {\n            vMin = V3f.MinValue;\n            vMax = V3f.MaxValue;\n            if (v.X >= 0)\n            {\n                vMin.X = Min.X;\n                vMax.X = Max.X;\n            }\n            else\n            {\n                vMin.X = Max.X;\n                vMax.X = Min.X;\n            }\n            if (v.Y >= 0)\n            {\n                vMin.Y = Min.Y;\n                vMax.Y = Max.Y;\n            }\n            else\n            {\n                vMin.Y = Max.Y;\n                vMax.Y = Min.Y;\n            }\n            if (v.Z >= 0)\n            {\n                vMin.Z = Min.Z;\n                vMax.Z = Max.Z;\n            }\n            else\n            {\n                vMin.Z = Max.Z;\n                vMax.Z = Min.Z;\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Box3f a, Box3f b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Box3f a, Box3f b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f operator +(Box3f box, V3f v)\n        {\n            return new Box3f((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f operator -(Box3f box, V3f v)\n        {\n            return new Box3f((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Box3f other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Box3f o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Box3f, int, V3f> Setter =\n            (ref Box3f box, int i, V3f value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Box3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Box3f(V3f.Parse(x[0].ToString()),\n                                V3f.Parse(x[1].ToString()));\n        }\n\n        public static Box3f Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, V3f.Parse, Box3f.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginB, string betweenB, string endB, string beginV, string betweenV, string endV)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return beginB + Min.ToString(format, fp, beginV, betweenV, endV) + betweenB + Max.ToString(format, fp, beginV, betweenV, endV) + endB;\n        }\n\n        #endregion\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f FromSize(V3f size)\n        {\n            return new Box3f(V3f.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f FromMinAndSize(V3f min, V3f size)\n        {\n            return new Box3f(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f FromCenterAndSize(V3f center, V3f size)\n        {\n            return new Box3f(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f FromSize(ISize3f iSize)\n        {\n            return new Box3f(\n                V3f.Zero, iSize.Size3f);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f FromMinAndSize(V3f min, ISize3f iSize)\n        {\n            return new Box3f(\n                min, min + iSize.Size3f);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f FromCenterAndSize(V3f center, ISize3f iSize)\n        {\n            var size = iSize.Size3f;\n            return new Box3f(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f FromPoints(V3f p0, V3f p1)\n        {\n            return new Box3f(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f Translated(V3f shift)\n        {\n            return IsInvalid ? Box3f.Invalid\n                             : new Box3f(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f Scaled(V3f factor)\n        {\n            return IsInvalid ? Box3f.Invalid\n                             : new Box3f(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        public readonly Box3f Transformed(M44f trafo)\n        {\n            if (Min.X > Max.X || Min.Y > Max.Y || Min.Z > Max.Z) return Box3f.Invalid;\n            var t = new V3f(trafo.M03, trafo.M13, trafo.M23);\n            var res = new Box3f(t, t);\n            float av, bv;\n            av = trafo.M00 * Min.X;\n            bv = trafo.M00 * Max.X;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M01 * Min.Y;\n            bv = trafo.M01 * Max.Y;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M02 * Min.Z;\n            bv = trafo.M02 * Max.Z;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M10 * Min.X;\n            bv = trafo.M10 * Max.X;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M11 * Min.Y;\n            bv = trafo.M11 * Max.Y;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M12 * Min.Z;\n            bv = trafo.M12 * Max.Z;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M20 * Min.X;\n            bv = trafo.M20 * Max.X;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            av = trafo.M21 * Min.Y;\n            bv = trafo.M21 * Max.Y;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            av = trafo.M22 * Min.Z;\n            bv = trafo.M22 * Max.Z;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3f Transformed(Trafo3f trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Corner(int index)\n        {\n            return\n                new V3f(\n                        (index & 1) == 0 ? Min.X : Max.X, \n                        (index & 2) == 0 ? Min.Y : Max.Y, \n                        (index & 4) == 0 ? Min.Z : Max.Z);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f[] ComputeCorners()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y, Min.Z),\n                new(Min.X, Max.Y, Min.Z),\n                new(Max.X, Max.Y, Min.Z),\n                new(Min.X, Min.Y, Max.Z),\n                new(Max.X, Min.Y, Max.Z),\n                new(Min.X, Max.Y, Max.Z),\n                Max\n            ];\n        }\n\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<V3f> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                yield return new V3f(Max.X, Min.Y, Min.Z);\n                yield return new V3f(Min.X, Max.Y, Min.Z);\n                yield return new V3f(Max.X, Max.Y, Min.Z);\n                yield return new V3f(Min.X, Min.Y, Max.Z);\n                yield return new V3f(Max.X, Min.Y, Max.Z);\n                yield return new V3f(Min.X, Max.Y, Max.Z);\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n        // TODO: Implement for other dimensions\n        public readonly Range1f X { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1f(Min.X, Max.X); } }\n        public readonly Range1f Y { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1f(Min.Y, Max.Y); } }\n        public readonly Range1f Z { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1f(Min.Z, Max.Z); } }\n        public readonly Box2f XY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2f(Min.XY, Max.XY); } }\n        public readonly Box2f XZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2f(Min.XZ, Max.XZ); } }\n        public readonly Box2f YX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2f(Min.YX, Max.YX); } }\n        public readonly Box2f YZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2f(Min.YZ, Max.YZ); } }\n        public readonly Box2f ZX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2f(Min.ZX, Max.ZX); } }\n        public readonly Box2f ZY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2f(Min.ZY, Max.ZY); } }\n\n        #endregion\n\n        #region Enumerators\n\n        #endregion\n\n        #region IBoundingBox3f Members\n\n        public readonly Box3f BoundingBox3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n\n        #region IBoundingSphere3f Members\n\n        public readonly Sphere3f BoundingSphere3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Sphere3f.Invalid : new Sphere3f(Center, 0.5f * Size.Length);\n        }\n\n        #endregion\n\n        #region ISize3f Members\n\n        public readonly V3f Size3f\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n    }\n\n    public static partial class Box\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f Union(this Box3f a, Box3f b)\n        {\n            return new Box3f(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f Intersection(this Box3f a, Box3f b)\n        {\n            return new Box3f(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        #endregion\n\n        #region Bounding box for arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f GetBoundingBox(this V3f[] pointArray)\n        {\n            return pointArray.GetBoundingBox(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f GetBoundingBox(this V3f[] pointArray, long count)\n        {\n            return pointArray.GetBoundingBox(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box3f GetBoundingBox(\n                this V3f[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Box3f.Invalid;\n            var box = new Box3f(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box3f GetBoundingBox<T>(this T[] array, long start, long count, Func<T, V3f> pointSelector)\n        {\n            if (count <= 0) return Box3f.Invalid;\n            var box = new Box3f(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for lists\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f GetBoundingBox(this List<V3f> pointList)\n        {\n            return pointList.GetBoundingBox(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the list.\n        /// </summary>\n        public static Box3f GetBoundingBox(this List<V3f> pointList, int count)\n        {\n            if (count <= 0) return Box3f.Invalid;\n            var box = new Box3f(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f GetBoundingBox(this int[] indexArray, V3f[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f GetBoundingBox(this int[] indexArray, int count, V3f[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3f GetBoundingBox(this int[] indexArray, int start, int count, V3f[] pointArray)\n        {\n            if (count <= 0) return Box3f.Invalid;\n            var box = new Box3f(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3f GetBoundingBox<T>(this int[] indexArray, int start, int count, T[] array, Func<T, V3f> pointSelector)\n        {\n            if (count <= 0) return Box3f.Invalid;\n            var box = new Box3f(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f GetBoundingBox(this long[] indexArray, V3f[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3f GetBoundingBox(this long[] indexArray, long count, V3f[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3f GetBoundingBox(this long[] indexArray, long start, long count, V3f[] pointArray)\n        {\n            if (count <= 0) return Box3f.Invalid;\n            var box = new Box3f(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3f GetBoundingBox<T>(this long[] indexArray, long start, long count, T[] array, Func<T, V3f> pointSelector)\n        {\n            if (count <= 0) return Box3f.Invalid;\n            var box = new Box3f(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the collection.\n        /// </summary>\n        public static Box3f GetBoundingBox(this IEnumerable<V3f> points)\n        {\n            var box = Box3f.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n\n        #region Get octant\n\n        /// <summary>\n        /// Octant 0-7.\n        /// 0th, 1st and 2nd bit encodes x-, y-, z-axis, respectively.\n        /// E.g. 0 is octant [box.Min, box.Center], 7 is octant [box.Center, box.Max].\n        /// </summary>\n        public static Box3f GetOctant(this Box3f box, int i)\n        {\n            if (i < 0 || i > 7) throw new IndexOutOfRangeException();\n\n            float x0, x1, y0, y1, z0, z1;\n            var c = box.Center;\n            if ((i & 1) == 0) { x0 = box.Min.X; x1 = c.X; } else { x0 = c.X; x1 = box.Max.X; }\n            if ((i & 2) == 0) { y0 = box.Min.Y; y1 = c.Y; } else { y0 = c.Y; y1 = box.Max.Y; }\n            if (i < 4) { z0 = box.Min.Z; z1 = c.Z; } else { z0 = c.Z; z1 = box.Max.Z; }\n            return new Box3f(new V3f(x0, y0, z0), new V3f(x1, y1, z1));\n        }\n\n        #endregion\n\n        #region Outline corners\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCCW(this Box3f box, V3f fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 4, 6, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 5, 7, 2];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 4, 6, 2];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 1, 3, 7, 6, 4];\n                }\n                    else\n                    { // +X -Y  Z\n                        return [0, 3, 7, 4];\n            }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 3, 2, 6, 4, 5];\n}\n                    else\n                    { // +X +Y  Z\n                        return [1, 2, 6, 5];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 2, 7, 5];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 3, 6, 4];\n}\n                    else\n                    { // +X  Y  Z\n                        return [1, 3, 7, 5];\n}\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 3, 5, 4];\n        }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 1, 7, 6];\n    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 1, 5, 4];\n}\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 6, 7, 1];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 4, 5, 3];\n}\n                    else\n                    { //  X +Y  Z\n                        return [2, 6, 7, 3];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 2, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 5, 7, 6];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCW(this Box3f box, V3f fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 3, 2, 6, 4, 5];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 2, 6, 5];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 1, 3, 7, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 3, 7, 4];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 3, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 2, 7, 5];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 2, 6, 4];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else\n                    { // +X -Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else\n                    { // +X +Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 5, 7, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 4, 6, 3];\n                    }\n                    else\n                    { // +X  Y  Z\n                        return [1, 5, 7, 3];\n                    }\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 4, 5, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 6, 7, 1];\n                    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 4, 5, 1];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 1, 7, 6];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 3, 5, 4];\n                    }\n                    else\n                    { //  X +Y  Z\n                        return [2, 3, 7, 6];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 1, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 6, 7, 5];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static V3f[] GetOutlineCornersCCW(this Box3f box, V3f fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static V3f[] GetOutlineCornersCW(this Box3f box, V3f fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box3f a, Box3f b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box3f a, Box3f b, float tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box3fAndFlags\n\n    [DataContract]\n    public struct Box3fAndFlags\n    {\n        [DataMember]\n        public Box.Flags BFlags;\n        [DataMember]\n        public Box3f BBox;\n\n        public Box3fAndFlags(Box3f union, Box3f box0, Box3f box1)\n        {\n            BFlags = 0;\n            BBox = union;\n            if (box0.Min.X > union.Min.X) { BBox.Min.X = box0.Min.X; BFlags |= Box.Flags.MinX0; }\n            if (box0.Min.Y > union.Min.Y) { BBox.Min.Y = box0.Min.Y; BFlags |= Box.Flags.MinY0; }\n            if (box0.Min.Z > union.Min.Z) { BBox.Min.Z = box0.Min.Z; BFlags |= Box.Flags.MinZ0; }\n            if (box0.Max.X < union.Max.X) { BBox.Max.X = box0.Max.X; BFlags |= Box.Flags.MaxX0; }\n            if (box0.Max.Y < union.Max.Y) { BBox.Max.Y = box0.Max.Y; BFlags |= Box.Flags.MaxY0; }\n            if (box0.Max.Z < union.Max.Z) { BBox.Max.Z = box0.Max.Z; BFlags |= Box.Flags.MaxZ0; }\n            if (box1.Min.X > union.Min.X) { BBox.Min.X = box1.Min.X; BFlags |= Box.Flags.MinX1; }\n            if (box1.Min.Y > union.Min.Y) { BBox.Min.Y = box1.Min.Y; BFlags |= Box.Flags.MinY1; }\n            if (box1.Min.Z > union.Min.Z) { BBox.Min.Z = box1.Min.Z; BFlags |= Box.Flags.MinZ1; }\n            if (box1.Max.X < union.Max.X) { BBox.Max.X = box1.Max.X; BFlags |= Box.Flags.MaxX1; }\n            if (box1.Max.Y < union.Max.Y) { BBox.Max.Y = box1.Max.Y; BFlags |= Box.Flags.MaxY1; }\n            if (box1.Max.Z < union.Max.Z) { BBox.Max.Z = box1.Max.Z; BFlags |= Box.Flags.MaxZ1; }\n        }\n    }\n\n    #endregion\n\n    #region Box3d\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Box3d\n        : IEquatable<Box3d>, IRange<V3d, Box3d>, IBoundingBox3d, ISize3d, IBoundingSphere3d, IFormattable\n    {\n        [DataMember]\n        public V3d Min;\n        [DataMember]\n        public V3d Max;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Box3d from a Box3i.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(Box3i b)\n        {\n            Min = (V3d) b.Min;\n            Max = (V3d) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box3d from a Box3l.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(Box3l b)\n        {\n            Min = (V3d) b.Min;\n            Max = (V3d) b.Max;\n        }\n\n        /// <summary>\n        /// Construct a Box3d from a Box3f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(Box3f b)\n        {\n            Min = (V3d) b.Min;\n            Max = (V3d) b.Max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(V3d min, V3d max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        /// <summary>\n        /// Creates a box from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(double minX, double minY, double minZ, double maxX, double maxY, double maxZ)\n        {\n            Min.X = minX;\n            Min.Y = minY;\n            Min.Z = minZ;\n            Max.X = maxX;\n            Max.Y = maxY;\n            Max.Z = maxZ;\n        }\n\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(V3d pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        /// <summary>\n        /// Creates a box from 3 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(V3d p0, V3d p1, V3d p2)\n        {\n            Min = Fun.Min(p0, p1, p2);\n            Max = Fun.Max(p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Creates a box from 4 points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(V3d p0, V3d p1, V3d p2, V3d p3)\n        {\n            Min = Fun.Min(p0, p1, p2, p3);\n            Max = Fun.Max(p0, p1, p2, p3);\n        }\n\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(Box3d range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(Box3d b0, Box3d b1)\n        {\n            Min = Fun.Min(b0.Min, b1.Min);\n            Max = Fun.Max(b0.Max, b1.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(Box3d b0, Box3d b1, Box3d b2)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max);\n        }\n\n        /// <summary>\n        /// Create a box containing all supplied boxs.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(Box3d b0, Box3d b1, Box3d b2, Box3d b3)\n        {\n            Min = Fun.Min(b0.Min, b1.Min, b2.Min, b3.Min);\n            Max = Fun.Max(b0.Max, b1.Max, b2.Max, b3.Max);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(V3d[] points) : this((ReadOnlySpan<V3d>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(ReadOnlySpan<V3d> points)\n        {\n            Min = V3d.MaxValue;\n            Max = V3d.MinValue;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(V3d[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d(IEnumerable<V3d> points)\n        {\n            Min = V3d.MaxValue;\n            Max = V3d.MinValue;\n            if (points == null) return;\n            foreach (V3d p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public Box3d(IEnumerable<Box3d> boxes)\n        {\n            Min = V3d.MaxValue;\n            Max = V3d.MinValue;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates box from a Range1 in each direction.\n        /// </summary>\n        public Box3d(Range1d rangeX, Range1d rangeY, Range1d rangeZ)\n        {\n            Min.X = rangeX.Min;\n            Max.X = rangeX.Max;\n            Min.Y = rangeY.Min;\n            Max.Y = rangeY.Max;\n            Min.Z = rangeZ.Min;\n            Max.Z = rangeZ.Max;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3d(Box3i b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3d(Box3l b) => new(b);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Box3d(Box3f b) => new(b);\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static Box3d Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3d.MaxValue, V3d.MinValue); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static Box3d Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3d.MinValue, V3d.MaxValue); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        public static Box3d Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(V3d.Zero, V3d.One); }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreaterOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AllSmallerOrEqual(Max); }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Min.AnyGreater(Max) || Min.IsNaN || Max.IsNaN; }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n\n        /// <summary>\n        /// Calculates size of the box.\n        /// </summary>\n        [XmlIgnore]\n        public V3d Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return (Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = (Min + value); }\n        }\n\n        public readonly V3d Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return ((Min + Max) / 2); }\n        }\n\n        [XmlIgnore]\n        public double SizeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X - Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = Min.X + value; }\n        }\n\n        public readonly Range1d RangeX\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1d(Min.X, Max.X); }\n        }\n\n        [XmlIgnore]\n        public double SizeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y - Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = Min.Y + value; }\n        }\n\n        public readonly Range1d RangeY\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1d(Min.Y, Max.Y); }\n        }\n\n        [XmlIgnore]\n        public double SizeZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Z - Min.Z; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Z = Min.Z + value; }\n        }\n\n        public readonly Range1d RangeZ\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1d(Min.Z, Max.Z); }\n        }\n\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int major = 0;\n                var s = Size;\n                if (s.Y > s.X) major = 1;\n                if (s.Z > s[major]) major = 2;\n                return major;\n            }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int minor = 0;\n                var s = Size;\n                if (s.Y < s.X) minor = 1;\n                if (s.Z < s[minor]) minor = 2;\n                return minor;\n            }\n        }\n\n        public readonly double SurfaceArea\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Size;\n                return (s.X * s.Y + s.X * s.Z + s.Y * s.Z) * 2;\n            }\n        }\n\n        public readonly double Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) return 0;\n                return SizeX * SizeY * SizeZ;\n            }\n        }\n\n        public readonly V3d OOO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Min; } }\n        public readonly V3d IOO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3d(Max.X, Min.Y, Min.Z); } }\n        public readonly V3d OIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3d(Min.X, Max.Y, Min.Z); } }\n        public readonly V3d IIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3d(Max.X, Max.Y, Min.Z); } }\n        public readonly V3d OOI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3d(Min.X, Min.Y, Max.Z); } }\n        public readonly V3d IOI { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3d(Max.X, Min.Y, Max.Z); } }\n        public readonly V3d OII { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new V3d(Min.X, Max.Y, Max.Z); } }\n        public readonly V3d III { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Max; } }\n\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return box enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d EnlargedBy(V3d increment)\n        {\n            return new Box3d((Min - increment), (Max + increment));\n        }\n\n        /// <summary>\n        /// Return box enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d EnlargedBy(V3d deltaMin, V3d deltaMax)\n        {\n            return new Box3d((Min - deltaMin), (Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d ShrunkBy(V3d delta)\n        {\n            return new Box3d((Min + delta), (Max - delta));\n        }\n\n        /// <summary>\n        /// Return box shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d ShrunkBy(V3d deltaMin, V3d deltaMax)\n        {\n            return new Box3d((Min + deltaMin), (Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V3d delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(V3d deltaMin, V3d deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V3d delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(V3d deltaMin, V3d deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d EnlargedBy(double delta)\n        {\n            return new Box3d(\n                    new V3d(Min.X - delta, Min.Y - delta, Min.Z - delta),\n                    new V3d(Max.X + delta, Max.Y + delta, Max.Z + delta));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d ShrunkBy(double delta)\n        {\n            return new Box3d(\n                    new V3d(Min.X + delta, Min.Y + delta, Min.Z + delta),\n                    new V3d(Max.X - delta, Max.Y - delta, Max.Z - delta));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d EnlargedBy(\n                double deltaMinX, double deltaMaxX, \n                double deltaMinY, double deltaMaxY, \n                double deltaMinZ, double deltaMaxZ)\n        {\n            return new Box3d(\n                    new V3d(Min.X - deltaMinX, Min.Y - deltaMinY, Min.Z - deltaMinZ),\n                    new V3d(Max.X + deltaMaxX, Max.Y + deltaMaxY, Max.Z + deltaMaxZ));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d ShrunkBy(\n                double deltaMinX, double deltaMaxX, \n                double deltaMinY, double deltaMaxY, \n                double deltaMinZ, double deltaMaxZ)\n        {\n            return new Box3d(\n                    new V3d(Min.X + deltaMinX, Min.Y + deltaMinY, Min.Z + deltaMinZ),\n                    new V3d(Max.X - deltaMaxX, Max.Y - deltaMaxY, Max.Z - deltaMaxZ));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(double delta)\n        {\n            Min.X -= delta; Max.X += delta;\n            Min.Y -= delta; Max.Y += delta;\n            Min.Z -= delta; Max.Z += delta;\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(double delta)\n        {\n            Min.X += delta; Max.X -= delta;\n            Min.Y += delta; Max.Y -= delta;\n            Min.Z += delta; Max.Z -= delta;\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(\n                double deltaMinX, double deltaMaxX, \n                double deltaMinY, double deltaMaxY, \n                double deltaMinZ, double deltaMaxZ)\n        {\n            Min.X -= deltaMinX; Max.X += deltaMaxX;\n            Min.Y -= deltaMinY; Max.Y += deltaMaxY;\n            Min.Z -= deltaMinZ; Max.Z += deltaMaxZ;\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(\n                double deltaMinX, double deltaMaxX, \n                double deltaMinY, double deltaMaxY, \n                double deltaMinZ, double deltaMaxZ)\n        {\n            Min.X += deltaMinX; Max.X -= deltaMaxX;\n            Min.Y += deltaMinY; Max.Y -= deltaMaxY;\n            Min.Z += deltaMinZ; Max.Z -= deltaMaxZ;\n        }\n\n        /// <summary>\n        /// Return box scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d ScaledFromCenterBy(double factor)\n        {\n            var size = Size;\n            var increment = (size * factor - size) / 2;\n            return new Box3d(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return box scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d ScaledFromCenterBy(V3d vectorFactor)\n        {\n            var size = Size;\n            var increment = (size * vectorFactor - size) / 2;\n            return new Box3d(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return a box enlarged in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d EnlargedByRelativeEps(double eps)\n        {\n            return EnlargedBy(eps * Size.Length);\n        }\n\n        /// <summary>\n        /// Enlarge the box in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeByRelativeEps(double eps)\n        {\n            EnlargeBy(eps * Size.Length);\n        }\n\n        #endregion\n\n        #region Box Arithmetics\n\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Clamped(V3d p)\n        {\n            return new V3d(\n                        p.X < Min.X ? Min.X : (p.X > Max.X ? Max.X : p.X), \n                        p.Y < Min.Y ? Min.Y : (p.Y > Max.Y ? Max.Y : p.Y), \n                        p.Z < Min.Z ? Min.Z : (p.Z > Max.Z ? Max.Z : p.Z));\n        }\n\n        /// <summary>\n        /// Returns the squared distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double DistanceSquared(V3d p)\n        {\n            return \n                (p.X < Min.X ? (Min.X - p.X) * (Min.X - p.X) : (p.X > Max.X ? (p.X - Max.X) * (p.X - Max.X) : 0.0)) + \n                (p.Y < Min.Y ? (Min.Y - p.Y) * (Min.Y - p.Y) : (p.Y > Max.Y ? (p.Y - Max.Y) * (p.Y - Max.Y) : 0.0)) + \n                (p.Z < Min.Z ? (Min.Z - p.Z) * (Min.Z - p.Z) : (p.Z > Max.Z ? (p.Z - Max.Z) * (p.Z - Max.Z) : 0.0));\n        }\n\n        /// <summary>\n        /// Returns the distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Distance(V3d p)\n        {\n            return Fun.Sqrt(\n                (p.X < Min.X ? (Min.X - p.X) * (Min.X - p.X) : (p.X > Max.X ? (p.X - Max.X) * (p.X - Max.X) : 0.0)) + \n                (p.Y < Min.Y ? (Min.Y - p.Y) * (Min.Y - p.Y) : (p.Y > Max.Y ? (p.Y - Max.Y) * (p.Y - Max.Y) : 0.0)) + \n                (p.Z < Min.Z ? (Min.Z - p.Z) * (Min.Z - p.Z) : (p.Z > Max.Z ? (p.Z - Max.Z) * (p.Z - Max.Z) : 0.0)));\n        }\n\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Lerp(double x)\n            => Fun.Lerp(x, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Lerp(V3d p)\n            => Fun.Lerp(p, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Lerp(double x, double y, double z)\n            => Fun.Lerp(new V3d(x, y, z), Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d InvLerp(V3d p)\n            => Fun.InvLerp(p, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d InvLerp(double x, double y, double z)\n            => Fun.InvLerp(new V3d(x, y, z), Min, Max);\n\n\n        /// <summary>\n        /// Returns the box with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d SplitRight(V3d splitValue)\n        {\n            var result = new Box3d(Min, Max);\n            if (splitValue.X > result.Min.X) result.Min.X = splitValue.X;\n            if (splitValue.Y > result.Min.Y) result.Min.Y = splitValue.Y;\n            if (splitValue.Z > result.Min.Z) result.Min.Z = splitValue.Z;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d SplitLeft(V3d splitValue)\n        {\n            var result = new Box3d(Min, Max);\n            if (splitValue.X < result.Max.X) result.Max.X = splitValue.X;\n            if (splitValue.Y < result.Max.Y) result.Max.Y = splitValue.Y;\n            if (splitValue.Z < result.Max.Z) result.Max.Z = splitValue.Z;\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d ExtendedBy(Box3d b)\n        {\n            return new Box3d(\n                    new V3d(\n                        b.Min.X < Min.X ? b.Min.X : Min.X, \n                        b.Min.Y < Min.Y ? b.Min.Y : Min.Y, \n                        b.Min.Z < Min.Z ? b.Min.Z : Min.Z),\n                    new V3d(\n                        b.Max.X > Max.X ? b.Max.X : Max.X, \n                        b.Max.Y > Max.Y ? b.Max.Y : Max.Y, \n                        b.Max.Z > Max.Z ? b.Max.Z : Max.Z));\n        }\n\n        /// <summary>\n        /// Returns the box extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d ExtendedBy(V3d v)\n        {\n            return new Box3d(\n                    new V3d(\n                        v.X < Min.X ? v.X : Min.X, \n                        v.Y < Min.Y ? v.Y : Min.Y, \n                        v.Z < Min.Z ? v.Z : Min.Z),\n                    new V3d(\n                        v.X > Max.X ? v.X : Max.X, \n                        v.Y > Max.Y ? v.Y : Max.Y, \n                        v.Z > Max.Z ? v.Z : Max.Z));\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(Box3d box)\n        {\n            if (box.Min.X < Min.X) Min.X = box.Min.X;\n            if (box.Max.X > Max.X) Max.X = box.Max.X;\n            if (box.Min.Y < Min.Y) Min.Y = box.Min.Y;\n            if (box.Max.Y > Max.Y) Max.Y = box.Max.Y;\n            if (box.Min.Z < Min.Z) Min.Z = box.Min.Z;\n            if (box.Max.Z > Max.Z) Max.Z = box.Max.Z;\n        }\n\n        /// <summary>\n        /// Extends the box to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(V3d point)\n        {\n            if (point.X < Min.X) Min.X = point.X;\n            if (point.X > Max.X) Max.X = point.X;\n            if (point.Y < Min.Y) Min.Y = point.Y;\n            if (point.Y > Max.Y) Max.Y = point.Y;\n            if (point.Z < Min.Z) Min.Z = point.Z;\n            if (point.Z > Max.Z) Max.Z = point.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d ExtendXBy(double x)\n        {\n            if (x < Min.X) Min.X = x;\n            if (x > Max.X) Max.X = x;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d ExtendYBy(double y)\n        {\n            if (y < Min.Y) Min.Y = y;\n            if (y > Max.Y) Max.Y = y;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d ExtendZBy(double z)\n        {\n            if (z < Min.Z) Min.Z = z;\n            if (z > Max.Z) Max.Z = z;\n            return this;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d ExtendDimBy(int dim, double x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(V3d p)\n        {\n            return\n                p.X >= Min.X && p.X <= Max.X && \n                p.Y >= Min.Y && p.Y <= Max.Y && \n                p.Z >= Min.Z && p.Z <= Max.Z;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(Box3d b)\n        {\n            return\n                b.Min.X >= Min.X && b.Max.X <= Max.X && \n                b.Min.Y >= Min.Y && b.Max.Y <= Max.Y && \n                b.Min.Z >= Min.Z && b.Max.Z <= Max.Z;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d Repair()\n        {\n            if (Equals(Box3d.Invalid)) return this;\n            if (Min.X > Max.X) Fun.Swap(ref Min.X, ref Max.X);\n            if (Min.Y > Max.Y) Fun.Swap(ref Min.Y, ref Max.Y);\n            if (Min.Z > Max.Z) Fun.Swap(ref Min.Z, ref Max.Z);\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3d box)\n        {\n            if (Min.X >= box.Max.X) return false;\n            if (Max.X <= box.Min.X) return false;\n            if (Min.Y >= box.Max.Y) return false;\n            if (Max.Y <= box.Min.Y) return false;\n            if (Min.Z >= box.Max.Z) return false;\n            if (Max.Z <= box.Min.Z) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3d box, V3d eps)\n        {\n            if (Min.X - eps.X >= box.Max.X) return false;\n            if (Max.X + eps.X <= box.Min.X) return false;\n            if (Min.Y - eps.Y >= box.Max.Y) return false;\n            if (Max.Y + eps.Y <= box.Min.Y) return false;\n            if (Min.Z - eps.Z >= box.Max.Z) return false;\n            if (Max.Z + eps.Z <= box.Min.Z) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(Box3d box, double eps)\n        {\n            if (Min.X - eps >= box.Max.X) return false;\n            if (Max.X + eps <= box.Min.X) return false;\n            if (Min.Y - eps >= box.Max.Y) return false;\n            if (Max.Y + eps <= box.Min.Y) return false;\n            if (Min.Z - eps >= box.Max.Z) return false;\n            if (Max.Z + eps <= box.Min.Z) return false;\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Box3d Invalidate()\n        {\n            Min = V3d.MaxValue;\n            Max = V3d.MinValue;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(V3d p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (p0.X < Min.X) bf |= Box.Flags.MinX;\n            else if (p0.X > Max.X) bf |= Box.Flags.MaxX;\n            if (p0.Y < Min.Y) bf |= Box.Flags.MinY;\n            else if (p0.Y > Max.Y) bf |= Box.Flags.MaxY;\n            if (p0.Z < Min.Z) bf |= Box.Flags.MinZ;\n            else if (p0.Z > Max.Z) bf |= Box.Flags.MaxZ;\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(Box3d b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            if (b.Min.X < Min.X) bf |= Box.Flags.MinX;\n            if (b.Max.X > Max.X) bf |= Box.Flags.MaxX;\n            if (b.Min.Y < Min.Y) bf |= Box.Flags.MinY;\n            if (b.Max.Y > Max.Y) bf |= Box.Flags.MaxY;\n            if (b.Min.Z < Min.Z) bf |= Box.Flags.MinZ;\n            if (b.Max.Z > Max.Z) bf |= Box.Flags.MaxZ;\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(V3d v, out V3d vMin, out V3d vMax)\n        {\n            vMin = V3d.MinValue;\n            vMax = V3d.MaxValue;\n            if (v.X >= 0)\n            {\n                vMin.X = Min.X;\n                vMax.X = Max.X;\n            }\n            else\n            {\n                vMin.X = Max.X;\n                vMax.X = Min.X;\n            }\n            if (v.Y >= 0)\n            {\n                vMin.Y = Min.Y;\n                vMax.Y = Max.Y;\n            }\n            else\n            {\n                vMin.Y = Max.Y;\n                vMax.Y = Min.Y;\n            }\n            if (v.Z >= 0)\n            {\n                vMin.Z = Min.Z;\n                vMax.Z = Max.Z;\n            }\n            else\n            {\n                vMin.Z = Max.Z;\n                vMax.Z = Min.Z;\n            }\n        }\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Box3d a, Box3d b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Box3d a, Box3d b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d operator +(Box3d box, V3d v)\n        {\n            return new Box3d((box.Min + v), (box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a box shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d operator -(Box3d box, V3d v)\n        {\n            return new Box3d((box.Min - v), (box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Box3d other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is Box3d o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<Box3d, int, V3d> Setter =\n            (ref Box3d box, int i, V3d value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static Box3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Box3d(V3d.Parse(x[0].ToString()),\n                                V3d.Parse(x[1].ToString()));\n        }\n\n        public static Box3d Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, V3d.Parse, Box3d.Setter);\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginB, string betweenB, string endB, string beginV, string betweenV, string endV)\n        {\n            fp ??= CultureInfo.InvariantCulture;\n            return beginB + Min.ToString(format, fp, beginV, betweenV, endV) + betweenB + Max.ToString(format, fp, beginV, betweenV, endV) + endB;\n        }\n\n        #endregion\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d FromSize(V3d size)\n        {\n            return new Box3d(V3d.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d FromMinAndSize(V3d min, V3d size)\n        {\n            return new Box3d(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d FromCenterAndSize(V3d center, V3d size)\n        {\n            return new Box3d(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d FromSize(ISize3d iSize)\n        {\n            return new Box3d(\n                V3d.Zero, iSize.Size3d);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d FromMinAndSize(V3d min, ISize3d iSize)\n        {\n            return new Box3d(\n                min, min + iSize.Size3d);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d FromCenterAndSize(V3d center, ISize3d iSize)\n        {\n            var size = iSize.Size3d;\n            return new Box3d(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d FromPoints(V3d p0, V3d p1)\n        {\n            return new Box3d(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d Translated(V3d shift)\n        {\n            return IsInvalid ? Box3d.Invalid\n                             : new Box3d(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d Scaled(V3d factor)\n        {\n            return IsInvalid ? Box3d.Invalid\n                             : new Box3d(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        public readonly Box3d Transformed(M44d trafo)\n        {\n            if (Min.X > Max.X || Min.Y > Max.Y || Min.Z > Max.Z) return Box3d.Invalid;\n            var t = new V3d(trafo.M03, trafo.M13, trafo.M23);\n            var res = new Box3d(t, t);\n            double av, bv;\n            av = trafo.M00 * Min.X;\n            bv = trafo.M00 * Max.X;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M01 * Min.Y;\n            bv = trafo.M01 * Max.Y;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M02 * Min.Z;\n            bv = trafo.M02 * Max.Z;\n            if (av < bv) { res.Min.X += av; res.Max.X += bv; }\n            else { res.Min.X += bv; res.Max.X += av; }\n            av = trafo.M10 * Min.X;\n            bv = trafo.M10 * Max.X;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M11 * Min.Y;\n            bv = trafo.M11 * Max.Y;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M12 * Min.Z;\n            bv = trafo.M12 * Max.Z;\n            if (av < bv) { res.Min.Y += av; res.Max.Y += bv; }\n            else { res.Min.Y += bv; res.Max.Y += av; }\n            av = trafo.M20 * Min.X;\n            bv = trafo.M20 * Max.X;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            av = trafo.M21 * Min.Y;\n            bv = trafo.M21 * Max.Y;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            av = trafo.M22 * Min.Z;\n            bv = trafo.M22 * Max.Z;\n            if (av < bv) { res.Min.Z += av; res.Max.Z += bv; }\n            else { res.Min.Z += bv; res.Max.Z += av; }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box3d Transformed(Trafo3d trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Corner(int index)\n        {\n            return\n                new V3d(\n                        (index & 1) == 0 ? Min.X : Max.X, \n                        (index & 2) == 0 ? Min.Y : Max.Y, \n                        (index & 4) == 0 ? Min.Z : Max.Z);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d[] ComputeCorners()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y, Min.Z),\n                new(Min.X, Max.Y, Min.Z),\n                new(Max.X, Max.Y, Min.Z),\n                new(Min.X, Min.Y, Max.Z),\n                new(Max.X, Min.Y, Max.Z),\n                new(Min.X, Max.Y, Max.Z),\n                Max\n            ];\n        }\n\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<V3d> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                yield return new V3d(Max.X, Min.Y, Min.Z);\n                yield return new V3d(Min.X, Max.Y, Min.Z);\n                yield return new V3d(Max.X, Max.Y, Min.Z);\n                yield return new V3d(Min.X, Min.Y, Max.Z);\n                yield return new V3d(Max.X, Min.Y, Max.Z);\n                yield return new V3d(Min.X, Max.Y, Max.Z);\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n        // TODO: Implement for other dimensions\n        public readonly Range1d X { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1d(Min.X, Max.X); } }\n        public readonly Range1d Y { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1d(Min.Y, Max.Y); } }\n        public readonly Range1d Z { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1d(Min.Z, Max.Z); } }\n        public readonly Box2d XY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2d(Min.XY, Max.XY); } }\n        public readonly Box2d XZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2d(Min.XZ, Max.XZ); } }\n        public readonly Box2d YX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2d(Min.YX, Max.YX); } }\n        public readonly Box2d YZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2d(Min.YZ, Max.YZ); } }\n        public readonly Box2d ZX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2d(Min.ZX, Max.ZX); } }\n        public readonly Box2d ZY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2d(Min.ZY, Max.ZY); } }\n\n        #endregion\n\n        #region Enumerators\n\n        #endregion\n\n        #region IBoundingBox3d Members\n\n        public readonly Box3d BoundingBox3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n\n        #region IBoundingSphere3d Members\n\n        public readonly Sphere3d BoundingSphere3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Sphere3d.Invalid : new Sphere3d(Center, 0.5 * Size.Length);\n        }\n\n        #endregion\n\n        #region ISize3d Members\n\n        public readonly V3d Size3d\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n    }\n\n    public static partial class Box\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d Union(this Box3d a, Box3d b)\n        {\n            return new Box3d(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d Intersection(this Box3d a, Box3d b)\n        {\n            return new Box3d(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n\n        #endregion\n\n        #region Bounding box for arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d GetBoundingBox(this V3d[] pointArray)\n        {\n            return pointArray.GetBoundingBox(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d GetBoundingBox(this V3d[] pointArray, long count)\n        {\n            return pointArray.GetBoundingBox(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box3d GetBoundingBox(\n                this V3d[] pointArray, long start, long count)\n        {\n            if (count <= 0) return Box3d.Invalid;\n            var box = new Box3d(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of count elements of the array starting at start.\n        /// </summary>\n        public static Box3d GetBoundingBox<T>(this T[] array, long start, long count, Func<T, V3d> pointSelector)\n        {\n            if (count <= 0) return Box3d.Invalid;\n            var box = new Box3d(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for lists\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d GetBoundingBox(this List<V3d> pointList)\n        {\n            return pointList.GetBoundingBox(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the first count elements of the list.\n        /// </summary>\n        public static Box3d GetBoundingBox(this List<V3d> pointList, int count)\n        {\n            if (count <= 0) return Box3d.Invalid;\n            var box = new Box3d(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for indexed arrays\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d GetBoundingBox(this int[] indexArray, V3d[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.Length, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d GetBoundingBox(this int[] indexArray, int count, V3d[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3d GetBoundingBox(this int[] indexArray, int start, int count, V3d[] pointArray)\n        {\n            if (count <= 0) return Box3d.Invalid;\n            var box = new Box3d(pointArray[indexArray[start]]);\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3d GetBoundingBox<T>(this int[] indexArray, int start, int count, T[] array, Func<T, V3d> pointSelector)\n        {\n            if (count <= 0) return Box3d.Invalid;\n            var box = new Box3d(pointSelector(array[indexArray[start]]));\n            for (int i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d GetBoundingBox(this long[] indexArray, V3d[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, indexArray.LongLength, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Box3d GetBoundingBox(this long[] indexArray, long count, V3d[] pointArray)\n        {\n            return indexArray.GetBoundingBox(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3d GetBoundingBox(this long[] indexArray, long start, long count, V3d[] pointArray)\n        {\n            if (count <= 0) return Box3d.Invalid;\n            var box = new Box3d(pointArray[indexArray[start]]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding box of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static Box3d GetBoundingBox<T>(this long[] indexArray, long start, long count, T[] array, Func<T, V3d> pointSelector)\n        {\n            if (count <= 0) return Box3d.Invalid;\n            var box = new Box3d(pointSelector(array[indexArray[start]]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding box for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding box of the elements of the collection.\n        /// </summary>\n        public static Box3d GetBoundingBox(this IEnumerable<V3d> points)\n        {\n            var box = Box3d.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n\n        #region Get octant\n\n        /// <summary>\n        /// Octant 0-7.\n        /// 0th, 1st and 2nd bit encodes x-, y-, z-axis, respectively.\n        /// E.g. 0 is octant [box.Min, box.Center], 7 is octant [box.Center, box.Max].\n        /// </summary>\n        public static Box3d GetOctant(this Box3d box, int i)\n        {\n            if (i < 0 || i > 7) throw new IndexOutOfRangeException();\n\n            double x0, x1, y0, y1, z0, z1;\n            var c = box.Center;\n            if ((i & 1) == 0) { x0 = box.Min.X; x1 = c.X; } else { x0 = c.X; x1 = box.Max.X; }\n            if ((i & 2) == 0) { y0 = box.Min.Y; y1 = c.Y; } else { y0 = c.Y; y1 = box.Max.Y; }\n            if (i < 4) { z0 = box.Min.Z; z1 = c.Z; } else { z0 = c.Z; z1 = box.Max.Z; }\n            return new Box3d(new V3d(x0, y0, z0), new V3d(x1, y1, z1));\n        }\n\n        #endregion\n\n        #region Outline corners\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCCW(this Box3d box, V3d fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 4, 6, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 5, 7, 2];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 4, 6, 2];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 1, 3, 7, 6, 4];\n                }\n                    else\n                    { // +X -Y  Z\n                        return [0, 3, 7, 4];\n            }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 3, 2, 6, 4, 5];\n}\n                    else\n                    { // +X +Y  Z\n                        return [1, 2, 6, 5];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 2, 7, 5];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 3, 6, 4];\n}\n                    else\n                    { // +X  Y  Z\n                        return [1, 3, 7, 5];\n}\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 3, 5, 4];\n        }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 1, 7, 6];\n    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 1, 5, 4];\n}\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 6, 7, 1];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 4, 5, 3];\n}\n                    else\n                    { //  X +Y  Z\n                        return [2, 6, 7, 3];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 2, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 5, 7, 6];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCW(this Box3d box, V3d fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 3, 2, 6, 4, 5];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 2, 6, 5];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 1, 3, 7, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 3, 7, 4];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 3, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 2, 7, 5];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 2, 6, 4];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else\n                    { // +X -Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else\n                    { // +X +Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 5, 7, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 4, 6, 3];\n                    }\n                    else\n                    { // +X  Y  Z\n                        return [1, 5, 7, 3];\n                    }\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 4, 5, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 6, 7, 1];\n                    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 4, 5, 1];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 1, 7, 6];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 3, 5, 4];\n                    }\n                    else\n                    { //  X +Y  Z\n                        return [2, 3, 7, 6];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 1, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 6, 7, 5];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static V3d[] GetOutlineCornersCCW(this Box3d box, V3d fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static V3d[] GetOutlineCornersCW(this Box3d box, V3d fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box3d a, Box3d b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Box3d a, Box3d b, double tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Box3dAndFlags\n\n    [DataContract]\n    public struct Box3dAndFlags\n    {\n        [DataMember]\n        public Box.Flags BFlags;\n        [DataMember]\n        public Box3d BBox;\n\n        public Box3dAndFlags(Box3d union, Box3d box0, Box3d box1)\n        {\n            BFlags = 0;\n            BBox = union;\n            if (box0.Min.X > union.Min.X) { BBox.Min.X = box0.Min.X; BFlags |= Box.Flags.MinX0; }\n            if (box0.Min.Y > union.Min.Y) { BBox.Min.Y = box0.Min.Y; BFlags |= Box.Flags.MinY0; }\n            if (box0.Min.Z > union.Min.Z) { BBox.Min.Z = box0.Min.Z; BFlags |= Box.Flags.MinZ0; }\n            if (box0.Max.X < union.Max.X) { BBox.Max.X = box0.Max.X; BFlags |= Box.Flags.MaxX0; }\n            if (box0.Max.Y < union.Max.Y) { BBox.Max.Y = box0.Max.Y; BFlags |= Box.Flags.MaxY0; }\n            if (box0.Max.Z < union.Max.Z) { BBox.Max.Z = box0.Max.Z; BFlags |= Box.Flags.MaxZ0; }\n            if (box1.Min.X > union.Min.X) { BBox.Min.X = box1.Min.X; BFlags |= Box.Flags.MinX1; }\n            if (box1.Min.Y > union.Min.Y) { BBox.Min.Y = box1.Min.Y; BFlags |= Box.Flags.MinY1; }\n            if (box1.Min.Z > union.Min.Z) { BBox.Min.Z = box1.Min.Z; BFlags |= Box.Flags.MinZ1; }\n            if (box1.Max.X < union.Max.X) { BBox.Max.X = box1.Max.X; BFlags |= Box.Flags.MaxX1; }\n            if (box1.Max.Y < union.Max.Y) { BBox.Max.Y = box1.Max.Y; BFlags |= Box.Flags.MaxY1; }\n            if (box1.Max.Z < union.Max.Z) { BBox.Max.Z = box1.Max.Z; BFlags |= Box.Flags.MaxZ1; }\n        }\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/RangesBoxes/Box_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    #region Flags\n\n    public static partial class Box\n    {\n        [Flags]\n        public enum Flags\n        {\n            None = 0x00000000,\n\n            /* ---------------------------------------------------------------\n                flags that mark the faces of a box\n            --------------------------------------------------------------- */\n            MinX0 = 0x00000001,\n            MinY0 = 0x00000002,\n            MinZ0 = 0x00000004,\n\n            MaxX0 = 0x00000008,\n            MaxY0 = 0x00000010,\n            MaxZ0 = 0x00000020,\n\n            Min0 = MinX0 | MinY0 | MinZ0,\n            Max0 = MaxX0 | MaxY0 | MaxZ0,\n\n            X0 = MinX0 | MaxX0,\n            Y0 = MinY0 | MaxY0,\n            Z0 = MinZ0 | MaxZ0,\n\n            All0 = Min0 | Max0,\n\n            /* ---------------------------------------------------------------\n                flags that mark the faces of a second, independent box\n            --------------------------------------------------------------- */\n            MinX1 = MinX0 << 6,\n            MinY1 = MinY0 << 6,\n            MinZ1 = MinZ0 << 6,\n            MaxX1 = MaxX0 << 6,\n            MaxY1 = MaxY0 << 6,\n            MaxZ1 = MaxZ0 << 6,\n            Min1 = Min0 << 6,\n            Max1 = Max0 << 6,\n            X1 = X0 << 6,\n            Y1 = Y0 << 6,\n            Z1 = Z0 << 6,\n            All1 = All0 << 6,\n\n            /* ---------------------------------------------------------------\n                flags that operate on both face bits together\n            --------------------------------------------------------------- */\n            MinX = MinX0 | MinX1,\n            MinY = MinY0 | MinY1,\n            MinZ = MinZ0 | MinZ1,\n            MaxX = MaxX0 | MaxX1,\n            MaxY = MaxY0 | MaxY1,\n            MaxZ = MaxZ0 | MaxZ1,\n            Min = Min0 | Min1,\n            Max = Max0 | Max1,\n            MinXMinY = MinX | MinY,\n            MinXMaxY = MinX | MaxY,\n            MaxXMinY = MaxX | MinY,\n            MaxXMaxY = MaxX | MaxY,\n            X = X0 | X1,\n            Y = Y0 | Y1,\n            Z = Z0 | Z1,\n            All = All0 | All1,\n\n            /* ---------------------------------------------------------------\n                flags that mark the edges of the box\n            --------------------------------------------------------------- */\n            Edge01 = 0x00001000,\n            Edge23 = 0x00002000,\n            Edge45 = 0x00004000,\n            Edge67 = 0x00008000,\n            Edge02 = 0x00010000,\n            Edge13 = 0x00020000,\n            Edge46 = 0x00040000,\n            Edge57 = 0x00080000,\n            Edge04 = 0x00100000,\n            Edge15 = 0x00200000,\n            Edge26 = 0x00400000,\n            Edge37 = 0x00800000,\n\n            /* ---------------------------------------------------------------\n                flags that mark the corners of the box\n            --------------------------------------------------------------- */\n            Corner0 = 0x01000000,\n            Corner1 = 0x02000000,\n            Corner2 = 0x04000000,\n            Corner3 = 0x08000000,\n            Corner4 = 0x10000000,\n            Corner5 = 0x20000000,\n            Corner6 = 0x40000000,\n            Corner7 = (int)-0x80000000,\n        }\n    }\n\n    #endregion\n\n    //# Action comma = () => Out(\", \");\n    //# Action add = () => Out(\" + \");\n    //# Action andand = () => Out(\" && \");\n    //# Action oror = () => Out(\" || \");\n    //# var fdtypes = new[] { Meta.FloatType, Meta.DoubleType };\n    //# foreach (var t in Meta.RangeAndBoxTypes) {\n    //#     var lt = t.LimitType; var vt = lt as Meta.VecType;\n    //#     int dim = vt != null ? vt.Len : 1;\n    //#     var dlt = dim > 1 ? Meta.VecTypeOf(dim, Meta.DoubleType) : Meta.DoubleType;\n    //#     var ft = dim > 1 ? vt.FieldType : lt;\n    //#     var vtrep = dim == 1 ? Meta.TryGetVecTypeOf(2, ft) : null;\n    //#     var vtype = vtrep?.Name;\n    //#     var ch = ft.Char;\n    //#     int dplus1 = dim + 1;\n    //#     var fields = dim > 1 ? vt.Fields : null;\n    //#     var args = dim > 1 ? fields.ToLower() : null;\n    //#     var ltype = lt.Name;\n    //#     var dltype = dlt.Name;\n    //#     var lcast = dim > 1 ? \"\" : ft == Meta.IntType || ft == Meta.DoubleType ? \"\" : \"(\" + ltype + \")\";\n    //#     var ftype = ft.Name;\n    //#     var fcast = dim > 1 ? \"\" : ft == Meta.IntType || ft == Meta.DoubleType ? \"\" : \"(\" + ftype + \")\";\n    //#     var bname = dim > 1 ? \"box\" : \"range\";\n    //#     var bnamecaps = dim > 1 ? \"Box\" : \"Range\";\n    //#     var type = t.Name;\n    //#     var ct = (ft == Meta.FloatType || ft == Meta.DoubleType) ? ft : Meta.ComputationTypeOf(ft);\n    //#     var ctype = ct.Name;\n    //#     var cch = ct.Char;\n    //#     var iboundingbox = \"IBoundingBox\" + dim + ch;\n    //#     var iboundingcircle = \"IBoundingCircle\" + dim + cch;\n    //#     var iboundingsphere = \"IBoundingSphere\" + dim + cch;\n    //#     var isize = \"ISize\" + dim + ch;\n    //#     var minvalue = dim > 1 ? ltype + \".MinValue\"\n    //#                            : lt.IsReal ? \"Constant<\" + ltype + \">.ParseableMinValue\" : ltype + \".MinValue\";\n    //#     var maxvalue = dim > 1 ? ltype + \".MaxValue\"\n    //#                            : lt.IsReal ? \"Constant<\" + ltype + \">.ParseableMaxValue\" : ltype + \".MaxValue\";\n    //#     var half = (ct == Meta.DoubleType) ? \"0.5\" : \"0.5f\";\n    #region __type__\n\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__\n        : IEquatable<__type__>, IRange<__ltype__, __type__>, /*# if (dim > 1) {\n                */__iboundingbox__, __isize__, /*# } if (dim == 2) {\n                */__iboundingcircle__, /*# } if (dim == 3) {\n                */__iboundingsphere__, /*# }*/IFormattable\n    {\n        [DataMember]\n        public __ltype__ Min;\n        [DataMember]\n        public __ltype__ Max;\n\n        #region Constructors\n\n        //# foreach (var t1 in  Meta.RangeAndBoxTypes) {\n        //#     var type1 = t1.Name;\n        //#     var lt1 = t1.LimitType; var vt1 = lt1 as Meta.VecType;\n        //#     int dim1 = vt1 != null ? vt1.Len : 1;\n        //#     if (t != t1 && dim == dim1) {\n        /// <summary>\n        /// Construct a __type__ from a __type1__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type1__ b)\n        {\n            Min = (__ltype__) b.Min;\n            Max = (__ltype__) b.Max;\n        }\n\n        //#     }\n        //# }\n        //# if (vtype != null) {\n        /// <summary>\n        /// Construct a __type__ from a __vtype__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__vtype__ v)\n        {\n            Min = v.X;\n            Max = v.Y;\n        }\n\n        //# }\n        /// <summary>\n        /// Creates a __bname__ from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ltype__ min, __ltype__ max)\n        {\n            Min = min;\n            Max = max;\n        }\n\n        //#if(dim > 1) {\n        //#var xyz = vt.Fields;\n        /// <summary>\n        /// Creates a __bname__ from minimum and maximum limits.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# xyz.ForEach(X => { */__ftype__ min__X__, /*# }); xyz.ForEach(X => { */__ftype__ max__X__/*# }, comma); */)\n        {\n            //# xyz.ForEach(X => {\n            Min.__X__ = min__X__;\n            //# });\n            //# xyz.ForEach(X => {\n            Max.__X__ = max__X__;\n            //# });\n        }\n\n        //# }\n        /// <summary>\n        /// Creates infinitesimal box from single point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ltype__ pnt)\n        {\n            Min = pnt;\n            Max = pnt;\n        }\n\n        //# for (int k = 3; k < 5; k++) {\n        /// <summary>\n        /// Creates a __bname__ from __k__ points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# k.ForEach(i => {*/__ltype__ p__i__/*#}, comma);*/)\n        {\n            Min = Fun.Min(/*# k.ForEach(i => {*/p__i__/*#}, comma);*/);\n            Max = Fun.Max(/*# k.ForEach(i => {*/p__i__/*#}, comma);*/);\n        }\n\n        //# }\n        /// <summary>\n        /// Creates copy of existing range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ range)\n        {\n            Min = range.Min;\n            Max = range.Max;\n        }\n\n        //# for (int k = 2; k < 5; k++) {\n        /// <summary>\n        /// Create a box containing all supplied __bname__s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# k.ForEach(i => {*/__type__ b__i__/*#}, comma);*/)\n        {\n            Min = Fun.Min(/*# k.ForEach(i => {*/b__i__.Min/*#}, comma);*/);\n            Max = Fun.Max(/*# k.ForEach(i => {*/b__i__.Max/*#}, comma);*/);\n        }\n\n        //# }\n        //# if (dim > 1) {\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ltype__[] points) : this((ReadOnlySpan<__ltype__>)points) { }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(ReadOnlySpan<__ltype__> points)\n        {\n            Min = __maxvalue__;\n            Max = __minvalue__;\n            if (points == null) return;\n            var count = points.Length;\n            for (var i = 0; i < count; i++) ExtendBy(points[i]);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ltype__[] points, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = Invalid.Min;\n                Max = Invalid.Max;\n            }\n            else\n            {\n                Min = Max = points[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(points[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(IEnumerable<__ltype__> points)\n        {\n            Min = __maxvalue__;\n            Max = __minvalue__;\n            if (points == null) return;\n            foreach (__ltype__ p in points) ExtendBy(p);\n        }\n\n        /// <summary>\n        /// Creates box as the bounding box of given boxes.\n        /// </summary>\n        public __type__(IEnumerable<__type__> boxes)\n        {\n            Min = __maxvalue__;\n            Max = __minvalue__;\n            if (boxes == null) return;\n            foreach (var box in boxes) ExtendBy(box);\n        }\n\n        /// <summary>\n        /// Creates __bname__ from a Range1 in each direction.\n        /// </summary>\n        public __type__(/*# fields.ForEach(f => {*/Range1__ch__ range__f__/*# }, comma);*/)\n        {\n            //# fields.ForEach(f => {\n            Min.__f__ = range__f__.Min;\n            Max.__f__ = range__f__.Max;\n            //# });\n        }\n\n        //# } // dim > 1\n        //# if (dim == 1) {\n        /// <summary>\n        /// Creates __bname__ as the bounding range of given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] values)\n        {\n            Min = __maxvalue__;\n            Max = __minvalue__;\n            if (values == null) return;\n            long count = values.LongLength;\n            for (long i = 0; i < count; i++) ExtendBy(values[i]);\n        }\n\n        /// <summary>\n        /// Creates __bname__ as the bounding range of count of the given points\n        /// starting at start.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] values, long start, long count)\n        {\n            if (count <= 0)\n            {\n                Min = __maxvalue__;\n                Max = __minvalue__;\n            }\n            else\n            {\n                Min = Max = values[start];\n                for (long i = start + 1, e = start + count; i < e; i++) ExtendBy(values[i]);\n            }\n        }\n\n        /// <summary>\n        /// Creates __bname__ as the bounding range of given values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(IEnumerable<__ftype__> values)\n        {\n            Min = __maxvalue__;\n            Max = __minvalue__;\n            if (values == null) return;\n            foreach (__ftype__ v in values) ExtendBy(v);\n        }\n\n        /// <summary>\n        /// Returns new range [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromMinAndSize(__ftype__ min, __ftype__ size)\n        {\n            return new __type__(min, __fcast__(min + size));\n        }\n\n        /// <summary>\n        /// Returns new range [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromCenterAndSize(__ftype__ center, __ftype__ size)\n        {\n            return new __type__(__fcast__(center - size / 2), __fcast__(center + size / 2));\n        }\n\n        //# }\n        #endregion\n\n        #region Conversions\n\n        //# foreach (var t1 in  Meta.RangeAndBoxTypes) {\n        //#     var type1 = t1.Name;\n        //#     var lt1 = t1.LimitType; var vt1 = lt1 as Meta.VecType;\n        //#     int dim1 = vt1 != null ? vt1.Len : 1;\n        //#     if (t != t1 && dim == dim1) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type1__ b) => new(b);\n\n        //#     }\n        //# }\n        //# if (vtype != null) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__vtype__ v) => new(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __vtype__(__type__ r) => new(r.Min, r.Max);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vtype__ To__vtype__() => (__vtype__)this;\n\n        //# }\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// A range with crossed limits.\n        /// </summary>\n        public static __type__ Invalid { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(__maxvalue__, __minvalue__); }\n\n        /// <summary>\n        /// The largest possible range.\n        /// </summary>\n        public static __type__ Infinite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(__minvalue__, __maxvalue__); }\n\n        /// <summary>\n        /// The unit interval [0, 1].\n        /// </summary>\n        //# if (dim == 1) {\n        public static __type__ Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(0, 1); }\n        //# } else {\n        public static __type__ Unit { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(__ltype__.Zero, __ltype__.One); }\n        //# }\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if the box is invalid or has a zero volume.\n        /// </summary>\n        public readonly bool IsEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return /*# if (dim == 1) { */Min >= Max;/*# } else { */Min.AnyGreaterOrEqual(Max);/*# } */ }\n        }\n\n        /// <summary>\n        /// True if the box has a non-zero volume.\n        /// </summary>\n        public readonly bool IsNonEmpty\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return !IsEmpty; }\n        }\n\n        /// <summary>\n        /// True if the box is valid.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return /*# if (dim == 1) { */Min <= Max;/*# } else { */Min.AllSmallerOrEqual(Max);/*# } */ }\n        }\n\n        /// <summary>\n        /// True if the box is invalid.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return /*# if (dim == 1) { */Min > Max;/*# } else { */Min.AnyGreater(Max)/*# if (ft.IsReal) {*/ || Min.IsNaN || Max.IsNaN/*# }*/;/*# } */ }\n        }\n\n        /// <summary>\n        /// True if the box is infinite.\n        /// </summary>\n        public readonly bool IsInfinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this == Infinite; }\n        }\n\n        //# if (dim == 2) {\n        /// <summary>\n        /// Same as Min.X.\n        /// </summary>\n        [XmlIgnore]\n        public __ftype__ Left\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.X.\n        /// </summary>\n        [XmlIgnore]\n        public __ftype__ Right\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.X = value; }\n        }\n\n        /// <summary>\n        /// Same as Min.Y.\n        /// </summary>\n        [XmlIgnore]\n        public __ftype__ Top\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Min.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Min.Y = value; }\n        }\n\n        /// <summary>\n        /// Same as Max.Y.\n        /// </summary>\n        [XmlIgnore]\n        public __ftype__ Bottom\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.Y = value; }\n        }\n        //# } // dim = 2\n\n        /// <summary>\n        /// Calculates size of the __bname__.\n        /// </summary>\n        [XmlIgnore]\n        public __ltype__ Size\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return __lcast__(Max - Min); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max = __lcast__(Min + value); }\n        }\n\n        public readonly __ltype__ Center\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return __lcast__((Min + Max) / 2); }\n        }\n\n        //# if (dim == 1) {\n        public readonly IEnumerable<__ltype__> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) yield break; //Todo: check should not be necessary\n                for (var i = Min; i <= Max; i++)\n                    yield return i;\n            }\n        }\n\n        //# } // dim == 1\n        //# if (dim > 1) {\n        //# fields.ForEach(f => {\n        [XmlIgnore]\n        public __ftype__ Size__f__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return Max.__f__ - Min.__f__; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { Max.__f__ = Min.__f__ + value; }\n        }\n\n        public readonly Range1__ch__ Range__f__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Range1__ch__(Min.__f__, Max.__f__); }\n        }\n\n        //# });\n        //# if (dim == 2) {\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY > SizeX ? 1 : 0; }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeY < SizeX ? 1 : 0; }\n        }\n\n        public readonly __ftype__ Area\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return SizeX * SizeY; }\n        }\n\n        //# } // dim == 2\n        //# if (dim == 3) {\n        /// <summary>\n        /// Index of the longest dimension of the box.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int major = 0;\n                var s = Size;\n                if (s.Y > s.X) major = 1;\n                if (s.Z > s[major]) major = 2;\n                return major;\n            }\n        }\n\n        /// <summary>\n        /// Index of the shortest dimension of the box.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                int minor = 0;\n                var s = Size;\n                if (s.Y < s.X) minor = 1;\n                if (s.Z < s[minor]) minor = 2;\n                return minor;\n            }\n        }\n\n        public readonly __ftype__ SurfaceArea\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Size;\n                return (s.X * s.Y + s.X * s.Z + s.Y * s.Z) * 2;\n            }\n        }\n\n        public readonly __ftype__ Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                if (IsInvalid) return 0;\n                return SizeX * SizeY * SizeZ;\n            }\n        }\n\n        //# } // dim == 3\n        //# for (int di = 0; di < (1 << dim); di++) {\n        //#     var pnt = dim.Range().Select(i => (di & (1 << i)) == 0 ? \"O\" : \"I\").Join();\n        //#     var arg = dim.Range().Select(i => ((di & (1 << i)) == 0 ? \"Min\" : \"Max\") + \".\" + fields[i]).Join(\", \");\n        public readonly __ltype__ __pnt__ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return /*# if (di == 0) {*/Min;/*#}\n                                                    else if (di == (1 << dim) - 1) {*/Max;/*#}\n                                                    else {*/new __ltype__(__arg__);/*#}*/ } }\n        //# }\n\n        //# } // dim > 1\n        #endregion\n\n        #region Size Manipulations\n\n        /// <summary>\n        /// Return __bname__ enlarged by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ EnlargedBy(__ltype__ increment)\n        {\n            return new __type__(__lcast__(Min - increment), __lcast__(Max + increment));\n        }\n\n        /// <summary>\n        /// Return __bname__ enlarged by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ EnlargedBy(__ltype__ deltaMin, __ltype__ deltaMax)\n        {\n            return new __type__(__lcast__(Min - deltaMin), __lcast__(Max + deltaMax));\n        }\n\n        /// <summary>\n        /// Return __bname__ shrunk by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ShrunkBy(__ltype__ delta)\n        {\n            return new __type__(__lcast__(Min + delta), __lcast__(Max - delta));\n        }\n\n        /// <summary>\n        /// Return __bname__ shrunk by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ShrunkBy(__ltype__ deltaMin, __ltype__ deltaMax)\n        {\n            return new __type__(__lcast__(Min + deltaMin), __lcast__(Max - deltaMax));\n        }\n\n        /// <summary>\n        /// Enlarges __bname__ by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(__ltype__ delta)\n        {\n            Min -= delta;\n            Max += delta;\n        }\n\n        /// <summary>\n        /// Enlarges __bname__ by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(__ltype__ deltaMin, __ltype__ deltaMax)\n        {\n            Min -= deltaMin;\n            Max += deltaMax;\n        }\n\n        /// <summary>\n        /// Shrinks __bname__ by the supplied value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(__ltype__ delta)\n        {\n            Min += delta;\n            Max -= delta;\n        }\n\n        /// <summary>\n        /// Shrinks __bname__ by the supplied values.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(__ltype__ deltaMin, __ltype__ deltaMax)\n        {\n            Min += deltaMin;\n            Max -= deltaMax;\n        }\n\n        //# if (dim > 1) {\n        /// <summary>\n        /// Returns a box enlarged by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ EnlargedBy(__ftype__ delta)\n        {\n            return new __type__(\n                    new __ltype__(/*# fields.ForEach(f => { */Min.__f__ - delta/*# }, comma);*/),\n                    new __ltype__(/*# fields.ForEach(f => { */Max.__f__ + delta/*# }, comma);*/));\n        }\n\n        /// <summary>\n        /// Returns a box shrunk by the specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ShrunkBy(__ftype__ delta)\n        {\n            return new __type__(\n                    new __ltype__(/*# fields.ForEach(f => { */Min.__f__ + delta/*# }, comma);*/),\n                    new __ltype__(/*# fields.ForEach(f => { */Max.__f__ - delta/*# }, comma);*/));\n        }\n\n        /// <summary>\n        /// Returns the box enlarged by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ EnlargedBy(/*# fields.ForEach(f => { */\n                __ftype__ deltaMin__f__, __ftype__ deltaMax__f__/*# }, comma);*/)\n        {\n            return new __type__(\n                    new __ltype__(/*# fields.ForEach(f => { */Min.__f__ - deltaMin__f__/*# }, comma);*/),\n                    new __ltype__(/*# fields.ForEach(f => { */Max.__f__ + deltaMax__f__/*# }, comma);*/));\n        }\n\n        /// <summary>\n        /// Returns the box shrunk by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ShrunkBy(/*# fields.ForEach(f => { */\n                __ftype__ deltaMin__f__, __ftype__ deltaMax__f__/*# }, comma);*/)\n        {\n            return new __type__(\n                    new __ltype__(/*# fields.ForEach(f => { */Min.__f__ + deltaMin__f__/*# }, comma);*/),\n                    new __ltype__(/*# fields.ForEach(f => { */Max.__f__ - deltaMax__f__/*# }, comma);*/));\n        }\n\n        /// <summary>\n        /// Enlarges box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(__ftype__ delta)\n        {\n            //# fields.ForEach(f => {\n            Min.__f__ -= delta; Max.__f__ += delta;\n            //# });\n        }\n\n        /// <summary>\n        /// Shrinks box by specified value in all directions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(__ftype__ delta)\n        {\n            //# fields.ForEach(f => {\n            Min.__f__ += delta; Max.__f__ -= delta;\n            //# });\n        }\n\n        /// <summary>\n        /// Enlarges the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeBy(/*# fields.ForEach(f => { */\n                __ftype__ deltaMin__f__, __ftype__ deltaMax__f__/*# }, comma);*/)\n        {\n            //# fields.ForEach(f => {\n            Min.__f__ -= deltaMin__f__; Max.__f__ += deltaMax__f__;\n            //# });\n        }\n\n        /// <summary>\n        /// Shrinks the box by the specified values (paddings).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ShrinkBy(/*# fields.ForEach(f => { */\n                __ftype__ deltaMin__f__, __ftype__ deltaMax__f__/*# }, comma);*/)\n        {\n            //# fields.ForEach(f => {\n            Min.__f__ += deltaMin__f__; Max.__f__ -= deltaMax__f__;\n            //# });\n        }\n\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Return __bname__ scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ScaledFromCenterBy(__ftype__ factor)\n        {\n            var size = Size;\n            var increment = (size * factor - size) / 2;\n            return new __type__(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return __bname__ scaled by the supplied factor around its center.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ScaledFromCenterBy(__ltype__ vectorFactor)\n        {\n            var size = Size;\n            var increment = (size * vectorFactor - size) / 2;\n            return new __type__(Min - increment, Max + increment);\n        }\n\n        /// <summary>\n        /// Return a box enlarged in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ EnlargedByRelativeEps(__ftype__ eps)\n        {\n            return EnlargedBy(eps * Size.Length);\n        }\n\n        /// <summary>\n        /// Enlarge the box in all directions by the supplied epsilon which is\n        /// measured with respect to the box diagonal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void EnlargeByRelativeEps(__ftype__ eps)\n        {\n            EnlargeBy(eps * Size.Length);\n        }\n\n        //# }\n        //# }\n        #endregion\n\n        #region Box Arithmetics\n\n        //# if (dim == 1) {\n        /// <summary>\n        /// Return the value in the Range that is closest to the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ Clamped(__ltype__ x)\n        {\n            return x < Min ? Min : (x > Max ? Max : x);\n        }\n\n        //# } else { // dim > 1\n        /// <summary>\n        /// Return the point in the Box that is closest to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ Clamped(__ltype__ p)\n        {\n            return new __ltype__(/*# fields.ForEach(f => { */\n                        p.__f__ < Min.__f__ ? Min.__f__ : (p.__f__ > Max.__f__ ? Max.__f__ : p.__f__)/*# }, comma); */);\n        }\n\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Returns the squared distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double DistanceSquared(__ltype__ p)\n        {\n            return /*# fields.ForEach(f => { */\n                (p.__f__ < Min.__f__ ? (Min.__f__ - p.__f__) * (Min.__f__ - p.__f__) : (p.__f__ > Max.__f__ ? (p.__f__ - Max.__f__) * (p.__f__ - Max.__f__) : 0.0))/*# }, add); */;\n        }\n\n        /// <summary>\n        /// Returns the distance to the supplied point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double Distance(__ltype__ p)\n        {\n            return Fun.Sqrt(/*# fields.ForEach(f => { */\n                (p.__f__ < Min.__f__ ? (Min.__f__ - p.__f__) * (Min.__f__ - p.__f__) : (p.__f__ > Max.__f__ ? (p.__f__ - Max.__f__) * (p.__f__ - Max.__f__) : 0.0))/*# }, add); */);\n        }\n\n        //# } // ft.IsReal\n        //# } // dim > 1\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ Lerp(__ftype__ x)\n            => Fun.Lerp(x, Min, Max);\n\n        //# if (dim == 1) {\n        /// <summary>\n        /// Performs the inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ InvLerp(__ltype__ x)\n            => Fun.InvLerp(x, Min, Max);\n\n        //# } else { // dim > 1\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ Lerp(__ltype__ p)\n            => Fun.Lerp(p, Min, Max);\n\n        /// <summary>\n        /// Interpolate linearly in each dimension.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ Lerp(/*# args.ForEach(a => { */__ftype__ __a__/*# }, comma); */)\n            => Fun.Lerp(new __ltype__(/*# args.ForEach(a => { */__a__/*# }, comma); */), Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ InvLerp(__ltype__ p)\n            => Fun.InvLerp(p, Min, Max);\n\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ InvLerp(/*# args.ForEach(a => { */__ftype__ __a__/*# }, comma); */)\n            => Fun.InvLerp(new __ltype__(/*# args.ForEach(a => { */__a__/*# }, comma); */), Min, Max);\n\n        //# } // dim > 1\n        //# } // ftype == \"float\" || ftype == \"double\"\n        //# else {\n        //# fdtypes.ForEach(tt => {\n        //# var ttype = tt.Name;\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ Lerp(__ttype__ t)\n            => Fun.Lerp(t, Min, Max);\n\n        //# if (dim > 1) {\n        //# var vtt = Meta.VecTypeOf(dim, tt);\n        //# var vttype = vtt.Name;\n        /// <summary>\n        /// Linearly interpolates between min and max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ Lerp(__vttype__ t)\n            => Fun.Lerp(t, Min, Max);\n\n        //# } // dim > 1\n        //# });\n        /// <summary>\n        /// Inverse of Lerp.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __dltype__ InvLerp(__ltype__ y)\n            => Fun.InvLerp(y, Min, Max);\n\n        //# } // not real\n\n        //# if (dim > 1) {\n        /// <summary>\n        /// Returns the __bname__ with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitRight(__ltype__ splitValue)\n        {\n            var result = new __type__(Min, Max);\n            //# fields.ForEach(f => {\n            if (splitValue.__f__ > result.Min.__f__) result.Min.__f__ = splitValue.__f__;\n            //# });\n            return result;\n        }\n\n        /// <summary>\n        /// Returns the __bname__ with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitLeft(__ltype__ splitValue)\n        {\n            var result = new __type__(Min, Max);\n            //# fields.ForEach(f => {\n            if (splitValue.__f__ < result.Max.__f__) result.Max.__f__ = splitValue.__f__;\n            //# });\n            return result;\n        }\n\n        //# }\n        //# if (dim == 1) {\n        /// <summary>\n        /// Returns the __bname__ with Min value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitRight(__ftype__ splitValue)\n        {\n            if (splitValue > Max) return __type__.Invalid;\n            if (splitValue <= Min) return this;\n            return new __type__(splitValue, Max);\n        }\n\n        /// <summary>\n        /// Returns the __bname__ with Max value clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitLeft(__ftype__ splitValue)\n        {\n            if (splitValue < Min) return __type__.Invalid;\n            if (splitValue >= Max) return this;\n            return new __type__(Min, splitValue);\n        }\n\n        //# }\n        //# if (dim == 2) {\n        /// <summary>\n        /// Returns the __bname__ with Min.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitRight(__ftype__ splitAtX)\n        {\n            if (splitAtX > Max.X) return __type__.Invalid;\n            if (splitAtX <= Min.X) return this;\n            return new __type__(new __ltype__(splitAtX, Min.Y), Max);\n        }\n\n        /// <summary>\n        /// Returns a __bname__ with Max.X clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitLeft(__ftype__ splitAtX)\n        {\n            if (splitAtX < Min.X) return __type__.Invalid;\n            if (splitAtX >= Max.X) return this;\n            return new __type__(Min, new __ltype__(splitAtX, Max.Y));\n        }\n\n        /// <summary>\n        /// Returns the __bname__ with Min.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitTop(__ftype__ splitAtY)\n        {\n            if (splitAtY > Max.Y) return __type__.Invalid;\n            if (splitAtY <= Min.Y) return this;\n            return new __type__(new __ltype__(Min.X, splitAtY), Max);\n        }\n\n        /// <summary>\n        /// Returns the __bname__ with Max.Y clamped to splitValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitBottom(__ftype__ splitAtY)\n        {\n            if (splitAtY < Min.Y) return __type__.Invalid;\n            if (splitAtY >= Max.Y) return this;\n            return new __type__(Min, new __ltype__(Max.X, splitAtY));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitLeftBottom(__ltype__ splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y < Min.Y) return __type__.Invalid;\n            return new __type__(Min, splitAt);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitRightBottom(__ltype__ splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y < Min.Y) return __type__.Invalid;\n            return new __type__(new __ltype__(splitAt.X, Min.Y), new __ltype__(Max.X, splitAt.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitLeftTop(__ltype__ splitAt)\n        {\n            if (splitAt.X < Min.X || splitAt.Y > Max.Y) return __type__.Invalid;\n            return new __type__(new __ltype__(Min.X, splitAt.Y), new __ltype__(splitAt.X, Max.Y));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ SplitRightTop(__ltype__ splitAt)\n        {\n            if (splitAt.X > Max.X || splitAt.Y > Max.Y) return __type__.Invalid;\n            return new __type__(splitAt, Max);\n        }\n\n        //# }\n        //# if ( dim == 1) {\n        /// <summary>\n        /// Returns the __bname__ extended to contain the supplied __bname__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ExtendedBy(__type__ range)\n        {\n            return new __type__(\n                            range.Min < Min ? range.Min : Min,\n                            range.Max > Max ? range.Max : Max);\n        }\n\n        /// <summary>\n        /// Returns the __bname__ extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ExtendedBy(__ftype__ value)\n        {\n            return new __type__(\n                            value < Min ? value : Min,\n                            value > Max ? value : Max);\n        }\n\n        /// <summary>\n        /// Extends the __bname__ to contain the supplied __bname__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(__type__ range)\n        {\n            if (range.Min < Min) Min = range.Min;\n            if (range.Max > Max) Max = range.Max;\n        }\n\n        /// <summary>\n        /// Extends the __bname__ to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(__ftype__ value)\n        {\n            if (value < Min) Min = value;\n            if (value > Max) Max = value;\n        }\n\n        //# }\n        //# if ( dim > 1) {\n        /// <summary>\n        /// Returns the __bname__ extended to contain the supplied __bname__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ExtendedBy(__type__ b)\n        {\n            return new __type__(\n                    new __ltype__(/*# fields.ForEach(f => {*/\n                        b.Min.__f__ < Min.__f__ ? b.Min.__f__ : Min.__f__/*# }, comma); */),\n                    new __ltype__(/*# fields.ForEach(f => {*/\n                        b.Max.__f__ > Max.__f__ ? b.Max.__f__ : Max.__f__/*# }, comma); */));\n        }\n\n        /// <summary>\n        /// Returns the __bname__ extended to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ ExtendedBy(__ltype__ v)\n        {\n            return new __type__(\n                    new __ltype__(/*# fields.ForEach(f => {*/\n                        v.__f__ < Min.__f__ ? v.__f__ : Min.__f__/*# }, comma); */),\n                    new __ltype__(/*# fields.ForEach(f => { */\n                        v.__f__ > Max.__f__ ? v.__f__ : Max.__f__/*# }, comma); */));\n        }\n\n        /// <summary>\n        /// Extends the __bname__ to contain the supplied __bname__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(__type__ box)\n        {\n            //# fields.ForEach(f => {\n            if (box.Min.__f__ < Min.__f__) Min.__f__ = box.Min.__f__;\n            if (box.Max.__f__ > Max.__f__) Max.__f__ = box.Max.__f__;\n            //# });\n        }\n\n        /// <summary>\n        /// Extends the __bname__ to contain the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ExtendBy(__ltype__ point)\n        {\n            //# fields.ForEach(f => {\n            if (point.__f__ < Min.__f__) Min.__f__ = point.__f__;\n            if (point.__f__ > Max.__f__) Max.__f__ = point.__f__;\n            //# });\n        }\n\n        //# }\n        //# if (dim == 1) {\n        /// <summary>\n        /// Returns true if the range contains the given value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(__ftype__ value)\n        {\n            return value >= Min && value <= Max;\n        }\n\n        /// <summary>\n        /// Returns true if the range completely contains the given range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(__type__ b)\n        {\n            return b.Min >= Min && b.Max <= Max;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(__type__ range)\n        {\n            if (Min >= range.Max) return false;\n            if (Max <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if 2 ranges intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(__type__ range, __ftype__ eps)\n        {\n            if (Min - eps >= range.Max) return false;\n            if (Max + eps <= range.Min) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Checks if the range is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__ Repair()\n        {\n            if (this.Equals(__type__.Invalid)) return this;\n            if (Min > Max) Fun.Swap(ref Min, ref Max);\n            return this;\n        }\n\n        //# }\n        //# if (dim > 1) {\n        //# fields.ForEach(args, (f, a) => {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__ Extend__f__By(__ftype__ __a__)\n        {\n            if (__a__ < Min.__f__) Min.__f__ = __a__;\n            if (__a__ > Max.__f__) Max.__f__ = __a__;\n            return this;\n        }\n\n        //# });\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__ ExtendDimBy(int dim, __ftype__ x)\n        {\n            if (x < Min[dim]) Min[dim] = x;\n            if (x > Max[dim]) Max[dim] = x;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if the box contains the given point.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(__ltype__ p)\n        {\n            return/*# fields.ForEach(f => {*/\n                p.__f__ >= Min.__f__ && p.__f__ <= Max.__f__/*# }, andand);*/;\n        }\n\n        /// <summary>\n        /// Returns true if the box completely contains the other box.\n        /// A box contains itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Contains(__type__ b)\n        {\n            return/*# fields.ForEach(f => {*/\n                b.Min.__f__ >= Min.__f__ && b.Max.__f__ <= Max.__f__/*# }, andand);*/;\n        }\n\n        /// <summary>\n        /// Checks if the box is still valid and repairs if not.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__ Repair()\n        {\n            if (Equals(__type__.Invalid)) return this;\n            //# fields.ForEach(f => {\n            if (Min.__f__ > Max.__f__) Fun.Swap(ref Min.__f__, ref Max.__f__);\n            //# });\n            return this;\n        }\n\n        /// <summary>\n        /// Returns true if two boxes intersect each other (or one contains the other).\n        /// Boxes DO NOT intersect if only touching from the outside.\n        /// A box intersects itself.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(__type__ box)\n        {\n            //# fields.ForEach(f => {\n            if (Min.__f__ >= box.Max.__f__) return false;\n            if (Max.__f__ <= box.Min.__f__) return false;\n            //# });\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(__type__ box, __ltype__ eps)\n        {\n            //# fields.ForEach(f => {\n            if (Min.__f__ - eps.__f__ >= box.Max.__f__) return false;\n            if (Max.__f__ + eps.__f__ <= box.Min.__f__) return false;\n            //# });\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if 2 boxes intersect each other with tolerance parameter.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Intersects(__type__ box, __ftype__ eps)\n        {\n            //# fields.ForEach(f => {\n            if (Min.__f__ - eps >= box.Max.__f__) return false;\n            if (Max.__f__ + eps <= box.Min.__f__) return false;\n            //# });\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__ Invalidate()\n        {\n            Min = __maxvalue__;\n            Max = __minvalue__;\n            return this;\n        }\n\n        /// <summary>\n        /// Returns where a points coordinates are outside a given box\n        /// </summary>\n        /// <returns>All outside Flags</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(__ltype__ p0)\n        {\n            Box.Flags bf = Box.Flags.None;\n            //# fields.ForEach(f => {\n            if (p0.__f__ < Min.__f__) bf |= Box.Flags.Min__f__;\n            else if (p0.__f__ > Max.__f__) bf |= Box.Flags.Max__f__;\n            //# });\n            return bf;\n        }\n\n        /// <summary>\n        /// Returns where the planes of the supplied box b are outside\n        /// of the box.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box.Flags OutsideFlags(__type__ b)\n        {\n            Box.Flags bf = Box.Flags.None;\n            //# fields.ForEach(f => {\n            if (b.Min.__f__ < Min.__f__) bf |= Box.Flags.Min__f__;\n            if (b.Max.__f__ > Max.__f__) bf |= Box.Flags.Max__f__;\n            //# });\n            return bf;\n        }\n\n        /// <summary>\n        /// Gets the minimal and maximal points of the box when seen from the\n        /// supplied direction vector v.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void GetMinMaxInDirection(__ltype__ v, out __ltype__ vMin, out __ltype__ vMax)\n        {\n            vMin = __minvalue__;\n            vMax = __maxvalue__;\n            //# fields.ForEach(f => {\n            if (v.__f__ >= 0)\n            {\n                vMin.__f__ = Min.__f__;\n                vMax.__f__ = Max.__f__;\n            }\n            else\n            {\n                vMin.__f__ = Max.__f__;\n                vMax.__f__ = Min.__f__;\n            }\n            //# });\n        }\n\n        //# }\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Checks if 2 boxes are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n        {\n            return (a.Min == b.Min) && (a.Max == b.Max);\n        }\n\n        /// <summary>\n        /// Checks if 2 boxes are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a, __type__ b)\n        {\n            return (a.Min != b.Min) || (a.Max != b.Max);\n        }\n\n        /// <summary>\n        /// Returns a __bname__ shifted by the supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator +(__type__ box, __ltype__ v)\n        {\n            return new __type__(__lcast__(box.Min + v), __lcast__(box.Max + v));\n        }\n\n        /// <summary>\n        /// Returns a __bname__ shifted by the negative supplied value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ box, __ltype__ v)\n        {\n            return new __type__(__lcast__(box.Min - v), __lcast__(box.Max - v));\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Min, Max);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Min.Equals(other.Min) && Max.Equals(other.Max);\n\n        public override readonly bool Equals(object obj) =>\n            (obj is __type__ o) && Equals(o);\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        #endregion\n\n        #region Static Methods\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<__type__, int, __ltype__> Setter =\n            (ref __type__ box, int i, __ltype__ value) =>\n            {\n                switch (i)\n                {\n                    case 0: box.Min = value; return;\n                    case 1: box.Max = value; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Parsing\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            //# if (dim > 1) {\n            return new __type__(__ltype__.Parse(x[0].ToString()),\n                                __ltype__.Parse(x[1].ToString()));\n            //# } else {\n            return new __type__(__ftype__.Parse(x[0], CultureInfo.InvariantCulture),\n                                __ftype__.Parse(x[1], CultureInfo.InvariantCulture));\n            //# }\n        }\n\n        public static __type__ Parse(Text t)\n        {\n            //# if (dim > 1) {\n            return t.NestedBracketSplit(1, __ltype__.Parse, __type__.Setter);\n            //# } else {\n            return t.NestedBracketSplit(1, Text<__ltype__>.Parse, __type__.Setter);\n            //# }\n        }\n\n        #endregion\n\n        #region IFormattable Members\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\"/*# if (dim > 1) {*/, \"[\", \", \", \"]\"/*# }*/);\n        }\n\n        /// <summary>\n        /// Outputs e.g. a Box2 in the form \"(beginB)(beginV)min.x(betweenV)min.y(endV)(betweenB)(beginV)max.x(betweenV)max.y(endV)(endB)\".\n        /// </summary>\n        //# var begin = \"begin\" + ((dim > 1) ? \"B\" : \"\");\n        //# var between = \"between\" + ((dim > 1) ? \"B\" : \"\");\n        //# var end = \"end\" + ((dim > 1) ? \"B\" : \"\");\n        public readonly string ToString(string format, IFormatProvider fp, string __begin__, string __between__, string __end__/*# if (dim > 1) {*/, string beginV, string betweenV, string endV/*# }*/)\n        {\n            //# var format = \"format, fp\" + (dim > 1 ? \", beginV, betweenV, endV\" : \"\");\n            fp ??= CultureInfo.InvariantCulture;\n            return __begin__ + Min.ToString(__format__) + __between__ + Max.ToString(__format__) + __end__;\n        }\n\n        #endregion\n        //# if (dim > 1) {\n\n        #region Static Factories\n\n        /// <summary>\n        /// Returns new box [0, size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromSize(__ltype__ size)\n        {\n            return new __type__(__ltype__.Zero, size);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + size].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromMinAndSize(__ltype__ min, __ltype__ size)\n        {\n            return new __type__(min, min + size);\n        }\n\n        /// <summary>\n        /// Returns new box [center - size / 2, center + size / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromCenterAndSize(__ltype__ center, __ltype__ size)\n        {\n            return new __type__(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Returns new box [0, iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromSize(ISize__dim____ch__ iSize)\n        {\n            return new __type__(\n                __ltype__.Zero, iSize.Size__dim____ch__);\n        }\n\n        /// <summary>\n        /// Returns new box [min, min + iSize].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromMinAndSize(__ltype__ min, ISize__dim____ch__ iSize)\n        {\n            return new __type__(\n                min, min + iSize.Size__dim____ch__);\n        }\n\n        /// <summary>\n        /// Returns new box [center - iSize / 2, center + iSize / 2].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromCenterAndSize(__ltype__ center, ISize__dim____ch__ iSize)\n        {\n            var size = iSize.Size__dim____ch__;\n            return new __type__(center - size / 2, center + size / 2);\n        }\n\n        /// <summary>\n        /// Creates box from 2 points which need not be Min and Max.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromPoints(__ltype__ p0, __ltype__ p1)\n        {\n            return new __type__(Fun.Min(p0, p1), Fun.Max(p0, p1));\n        }\n\n        //# if (dim == 2) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromSize(__ftype__ width, __ftype__ height)\n        {\n            return __type__.FromSize(new __ltype__(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromMinAndSize(__ltype__ min, __ftype__ width, __ftype__ height)\n        {\n            return new __type__(min, min + new __ltype__(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromMinAndSize(\n            __ftype__ minX, __ftype__ minY, __ftype__ width, __ftype__ height\n            )\n        {\n            return __type__.FromMinAndSize(new __ltype__(minX, minY), new __ltype__(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromCenterAndSize(__ltype__ center, __ftype__ width, __ftype__ height)\n        {\n            return FromCenterAndSize(center, new __ltype__(width, height));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromCenterAndSize(\n            __ftype__ centerX, __ftype__ centerY, __ftype__ width, __ftype__ height\n            )\n        {\n            return FromCenterAndSize(new __ltype__(centerX, centerY), new __ltype__(width, height));\n        }\n\n        //# }\n        #endregion\n\n        #region Transforms\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ Translated(__ltype__ shift)\n        {\n            return IsInvalid ? __type__.Invalid\n                             : new __type__(Min + shift, Max + shift);\n        }\n\n        /// <summary>\n        /// Returns a scaled box. WARNING: scaling is performed around the origin!\n        /// A negative scale factor will resut in an invalid box!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type__ Scaled(__ltype__ factor)\n        {\n            return IsInvalid ? __type__.Invalid\n                             : new __type__(Min * factor, Max * factor);\n        }\n\n        /// <summary>\n        /// Transforms the box by the given transformation matrix.\n        /// NOTE: Performs IsValid check at 10% CPU time overhead.\n        ///       -> Empty bounds (crossed min and max) will remain empty.\n        /// </summary>\n        //# {\n        //# var tc = (ft == Meta.FloatType) ? \"f\" : \"d\";\n        //# var tftype = (ft == Meta.FloatType) ? \"float\" : \"double\";\n        public readonly Box__dim____tc__ Transformed(M__dplus1____dplus1____tc__ trafo)\n        {\n            if (/*# fields.ForEach((f, i) => {*/Min.__f__ > Max.__f__/*#}, oror);*/) return Box__dim____tc__.Invalid;\n            var t = new V__dim____tc__(/*# fields.ForEach((f, i) => {*/trafo.M__i____dim__/*#}, comma);*/);\n            var res = new Box__dim____tc__(t, t);\n            __tftype__ av, bv;\n            //# for (int i = 0; i < dim; i++) { var fi = vt.Fields[i];\n            //# for (int j = 0; j < dim; j++) { var fj = vt.Fields[j];\n            av = trafo.M__i____j__ * Min.__fj__;\n            bv = trafo.M__i____j__ * Max.__fj__;\n            if (av < bv) { res.Min.__fi__ += av; res.Max.__fi__ += bv; }\n            else { res.Min.__fi__ += bv; res.Max.__fi__ += av; }\n            //# }\n            //# }\n            return res;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly Box__dim____tc__ Transformed(Trafo__dim____tc__ trafo)\n        {\n            return Transformed(trafo.Forward);\n        }\n        //# }\n\n        #endregion\n\n        #region Corners\n\n        /// <summary>\n        /// Return the corner of the box with the given index. The corner\n        /// index is constructed in such a way, that bit 0 enumerates the\n        /// x coordinate (0 ... min, 1 ... max), bit 1 enumerates the y\n        /// coordinate, and bit 2 enumerates the z coordinate.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__ Corner(int index)\n        {\n            return\n                new __ltype__(/*# fields.ForEach((f, i) => { var bit = 1 << i; */\n                        (index & __bit__) == 0 ? Min.__f__ : Max.__f__/*#}, comma);*/);\n        }\n\n        /// <summary>\n        /// Computes the corners of the box and returns them in an array.\n        /// The order of the corners is determined by their index which is\n        /// constructed as in the method <see cref=\"Corner\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__[] ComputeCorners()\n        {\n            return [\n                Min,\n                //# for (int i = 1; i < (1 << dim) - 1; i++) {\n                new(/*#\n                fields.ForEach((f, b) => { var bf = ((i & (1<<b)) == 0) ? \"Min\" : \"Max\";\n                                          */__bf__.__f__/*# }, comma); */),\n                //# }\n                Max\n            ];\n        }\n\n        //# if (dim == 2) {\n        // TODO: Comment and implement for dimensions other than 2.\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ltype__[] ComputeCornersCCW()\n        {\n            return [\n                Min,\n                new(Max.X, Min.Y),\n                Max,\n                new(Min.X, Max.Y),\n            ];\n        }\n        //# }\n\n        /// <summary>\n        /// Enumeration of the corners of the box.\n        /// </summary>\n        public readonly IEnumerable<__ltype__> Corners\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return Min;\n                //# for (int i = 1; i < (1 << dim) - 1; i++) {\n                yield return new __ltype__(/*#\n                fields.ForEach((f, b) => { var bf = ((i & (1<<b)) == 0) ? \"Min\" : \"Max\";\n                                          */__bf__.__f__/*# }, comma); */);\n                //# }\n                yield return Max;\n            }\n        }\n\n        #endregion\n\n        #region Swizzle methods\n\n        //# if (dim == 3) {\n        // TODO: Implement for other dimensions\n        public readonly Range1__ch__ X { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1__ch__(Min.X, Max.X); } }\n        public readonly Range1__ch__ Y { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1__ch__(Min.Y, Max.Y); } }\n        public readonly Range1__ch__ Z { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Range1__ch__(Min.Z, Max.Z); } }\n        public readonly Box2__ch__ XY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2__ch__(Min.XY, Max.XY); } }\n        public readonly Box2__ch__ XZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2__ch__(Min.XZ, Max.XZ); } }\n        public readonly Box2__ch__ YX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2__ch__(Min.YX, Max.YX); } }\n        public readonly Box2__ch__ YZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2__ch__(Min.YZ, Max.YZ); } }\n        public readonly Box2__ch__ ZX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2__ch__(Min.ZX, Max.ZX); } }\n        public readonly Box2__ch__ ZY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Box2__ch__(Min.ZY, Max.ZY); } }\n        //# }\n\n        #endregion\n\n        #region Enumerators\n\n        //# if (dim > 0 && !ft.IsReal) {\n        /// <summary>\n        /// Returns all points from [Min,Max[ with X-Variable in the outer loop.\n        /// </summary>\n        public readonly IEnumerable<__ltype__> EnumerateInsidePoints()\n        {\n            var p = new __ltype__();\n            //# fields.ForEach(f => {\n            for (p.__f__ = Min.__f__; p.__f__ < Max.__f__; p.__f__++)\n            //# });\n                yield return p;\n        }\n\n        //# }\n        #endregion\n\n        #region IBoundingBox__dim____ch__ Members\n\n        public readonly Box__dim____ch__ BoundingBox__dim____ch__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return this; }\n        }\n\n        #endregion\n        //# if (dim == 2) {\n\n        #region IBoundingCircle__dim____cch__ Members\n\n        public readonly Circle__dim____cch__ BoundingCircle__dim____cch__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Circle__dim____cch__.Invalid : new Circle__dim____cch__(/*# if (ft != ct) {*/(V__dim____cch__)/*# }*/Center, __half__ * Size.Length);\n        }\n\n        #endregion\n        //# }\n        //# if (dim == 3) {\n\n        #region IBoundingSphere__dim____cch__ Members\n\n        public readonly Sphere__dim____cch__ BoundingSphere__dim____cch__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => IsInvalid ? Sphere__dim____cch__.Invalid : new Sphere__dim____cch__(/*# if (ft != ct) {*/(V__dim____cch__)/*# }*/Center, __half__ * Size.Length);\n        }\n\n        #endregion\n        //# }\n\n        #region ISize__dim____ch__ Members\n\n        public readonly V__dim____ch__ Size__dim____ch__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Size; }\n        }\n\n        #endregion\n        //# }\n    }\n\n    public static partial class __bnamecaps__\n    {\n        #region Set operations\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Union(this __type__ a, __type__ b)\n        {\n            return new __type__(Fun.Min(a.Min, b.Min), Fun.Max(a.Max, b.Max));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Intersection(this __type__ a, __type__ b)\n        {\n            return new __type__(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n        }\n        //# if (dim == 1) {\n\n        /// <summary>\n        /// Checks if two __bname__s intersect each other with a tolerance parameter.\n        /// </summary>\n        // TODO: Implement for d > 2\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Intersects(this __type__ a, __type__ b, __ftype__ eps, out __type__ result)\n        {\n            result = __type__.Invalid;\n            if (a.Min - eps > b.Max) return false;\n            else if (a.Max + eps < b.Min) return false;\n            else\n            {\n                result = new __type__(Fun.Max(a.Min, b.Min), Fun.Min(a.Max, b.Max));\n                if (result.Size < eps)\n                {\n                    __ftype__ center = result.Center;\n                    result.Min = __lcast__(center - eps);\n                    result.Max = __lcast__(center + eps);\n                }\n                return true;\n            }\n        }\n        //# }\n\n        #endregion\n\n        #region Bounding __bname__ for arrays\n\n        /// <summary>\n        /// Returns the bounding __bname__ of the elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ GetBounding__bnamecaps__(this __ltype__[] pointArray)\n        {\n            return pointArray.GetBounding__bnamecaps__(0, pointArray.LongLength);\n        }\n\n        /// <summary>\n        /// Returns the bounding __bname__ of the first count elements of the array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ GetBounding__bnamecaps__(this __ltype__[] pointArray, long count)\n        {\n            return pointArray.GetBounding__bnamecaps__(0, count);\n        }\n\n        /// <summary>\n        /// Returns the bounding __bname__ of count elements of the array starting at start.\n        /// </summary>\n        public static __type__ GetBounding__bnamecaps__(\n                this __ltype__[] pointArray, long start, long count)\n        {\n            if (count <= 0) return __type__.Invalid;\n            var box = new __type__(pointArray[start]);\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[i]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding __bname__ of count elements of the array starting at start.\n        /// </summary>\n        public static __type__ GetBounding__bnamecaps__<T>(this T[] array, long start, long count, Func<T, __ltype__> pointSelector)\n        {\n            if (count <= 0) return __type__.Invalid;\n            var box = new __type__(pointSelector(array[start]));\n            for (long i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[i]));\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding __bname__ for lists\n\n        /// <summary>\n        /// Returns the bounding __bname__ of the elements of the list.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ GetBounding__bnamecaps__(this List<__ltype__> pointList)\n        {\n            return pointList.GetBounding__bnamecaps__(pointList.Count);\n        }\n\n        /// <summary>\n        /// Returns the bounding __bname__ of the first count elements of the list.\n        /// </summary>\n        public static __type__ GetBounding__bnamecaps__(this List<__ltype__> pointList, int count)\n        {\n            if (count <= 0) return __type__.Invalid;\n            var box = new __type__(pointList[0]);\n            for (int i = 1; i < count; i++)\n                box.ExtendBy(pointList[i]);\n            return box;\n        }\n\n        #endregion\n\n        #region Bounding __bname__ for indexed arrays\n\n        //# foreach (var itype in new[] { \"int\", \"long\" }) {\n        //#     var getlength = itype == \"int\" ? \"Length\" : \"LongLength\";\n        /// <summary>\n        /// Returns the bounding __bname__ of the elements of pointArray indexed by the indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ GetBounding__bnamecaps__(this __itype__[] indexArray, __ltype__[] pointArray)\n        {\n            return indexArray.GetBounding__bnamecaps__(0, indexArray.__getlength__, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding __bname__ of the elements of pointArray indexed by the first count indices in indexArray.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ GetBounding__bnamecaps__(this __itype__[] indexArray, __itype__ count, __ltype__[] pointArray)\n        {\n            return indexArray.GetBounding__bnamecaps__(0, count, pointArray);\n        }\n\n        /// <summary>\n        /// Returns the bounding __bname__ of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static __type__ GetBounding__bnamecaps__(this __itype__[] indexArray, __itype__ start, __itype__ count, __ltype__[] pointArray)\n        {\n            if (count <= 0) return __type__.Invalid;\n            var box = new __type__(pointArray[indexArray[start]]);\n            for (__itype__ i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointArray[indexArray[i]]);\n            return box;\n        }\n\n        /// <summary>\n        /// Returns the bounding __bname__ of the elements of pointArray indexed by count indices\n        /// in indexArray starting at start.\n        /// </summary>\n        public static __type__ GetBounding__bnamecaps__<T>(this __itype__[] indexArray, __itype__ start, __itype__ count, T[] array, Func<T, __ltype__> pointSelector)\n        {\n            if (count <= 0) return __type__.Invalid;\n            var box = new __type__(pointSelector(array[indexArray[start]]));\n            for (__itype__ i = start + 1, e = start + count; i < e; i++)\n                box.ExtendBy(pointSelector(array[indexArray[i]]));\n            return box;\n        }\n\n        //# }\n        #endregion\n\n        #region Bounding __bname__ for IEnumerable\n\n        /// <summary>\n        /// Returns the bounding __bname__ of the elements of the collection.\n        /// </summary>\n        public static __type__ GetBounding__bnamecaps__(this IEnumerable<__ltype__> points)\n        {\n            var box = __type__.Invalid;\n            foreach (var p in points) box.ExtendBy(p);\n            return box;\n        }\n\n        #endregion\n        //# if (dim == 3) {\n\n        #region Get octant\n\n        /// <summary>\n        /// Octant 0-7.\n        /// 0th, 1st and 2nd bit encodes x-, y-, z-axis, respectively.\n        /// E.g. 0 is octant [box.Min, box.Center], 7 is octant [box.Center, box.Max].\n        /// </summary>\n        public static __type__ GetOctant(this __type__ box, int i)\n        {\n            if (i < 0 || i > 7) throw new IndexOutOfRangeException();\n\n            __ftype__ x0, x1, y0, y1, z0, z1;\n            var c = box.Center;\n            if ((i & 1) == 0) { x0 = box.Min.X; x1 = c.X; } else { x0 = c.X; x1 = box.Max.X; }\n            if ((i & 2) == 0) { y0 = box.Min.Y; y1 = c.Y; } else { y0 = c.Y; y1 = box.Max.Y; }\n            if (i < 4) { z0 = box.Min.Z; z1 = c.Z; } else { z0 = c.Z; z1 = box.Max.Z; }\n            return new __type__(new __ltype__(x0, y0, z0), new __ltype__(x1, y1, z1));\n        }\n\n        #endregion\n\n        #region Outline corners\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCCW(this __type__ box, __ltype__ fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 4, 6, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 5, 7, 2];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 4, 6, 2];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 1, 3, 7, 6, 4];\n                }\n                    else\n                    { // +X -Y  Z\n                        return [0, 3, 7, 4];\n            }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 3, 2, 6, 4, 5];\n}\n                    else\n                    { // +X +Y  Z\n                        return [1, 2, 6, 5];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 2, 7, 5];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 3, 6, 4];\n}\n                    else\n                    { // +X  Y  Z\n                        return [1, 3, 7, 5];\n}\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 3, 5, 4];\n        }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 1, 7, 6];\n    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 1, 5, 4];\n}\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 6, 7, 1];\n    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 4, 5, 3];\n}\n                    else\n                    { //  X +Y  Z\n                        return [2, 6, 7, 3];\n}\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 2, 3, 1];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 5, 7, 6];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corner indices of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static int[] GetOutlineCornerIndicesCW(this __type__ box, __ltype__ fromPosition)\n        {\n            if (fromPosition.X < box.Min.X)\n            { //-X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X -Y -Z\n                        return [1, 3, 2, 6, 4, 5];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X -Y +Z\n                        return [0, 2, 6, 7, 5, 1];\n                    }\n                    else\n                    { // -X -Y  Z\n                        return [1, 2, 6, 5];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X +Y -Z\n                        return [0, 1, 3, 7, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X +Y +Z\n                        return [0, 2, 3, 7, 5, 4];\n                    }\n                    else\n                    { // -X +Y  Z\n                        return [0, 3, 7, 4];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // -X  Y -Z\n                        return [1, 3, 6, 4];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // -X  Y +Z\n                        return [0, 2, 7, 5];\n                    }\n                    else\n                    { // -X  Y  Z\n                        return [0, 2, 6, 4];\n                    }\n                }\n            }\n            else if (fromPosition.X > box.Max.X)\n            { // +X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X -Y -Z\n                        return [0, 4, 5, 7, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X -Y +Z\n                        return [0, 4, 6, 7, 3, 1];\n                    }\n                    else\n                    { // +X -Y  Z\n                        return [0, 4, 7, 3];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X +Y -Z\n                        return [0, 1, 5, 7, 6, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X +Y +Z\n                        return [1, 5, 4, 6, 2, 3];\n                    }\n                    else\n                    { // +X +Y  Z\n                        return [1, 5, 6, 2];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { // +X  Y -Z\n                        return [0, 5, 7, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { // +X  Y +Z\n                        return [1, 4, 6, 3];\n                    }\n                    else\n                    { // +X  Y  Z\n                        return [1, 5, 7, 3];\n                    }\n                }\n            }\n            else\n            { // X\n                if (fromPosition.Y < box.Min.Y)\n                { //-Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X -Y -Z\n                        return [2, 4, 5, 3];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X -Y +Z\n                        return [0, 6, 7, 1];\n                    }\n                    else\n                    { //  X -Y  Z\n                        return [0, 4, 5, 1];\n                    }\n                }\n                else if (fromPosition.Y > box.Max.Y)\n                { // +Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X +Y -Z\n                        return [0, 1, 7, 6];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X +Y +Z\n                        return [2, 3, 5, 4];\n                    }\n                    else\n                    { //  X +Y  Z\n                        return [2, 3, 7, 6];\n                    }\n                }\n                else\n                { // Y\n                    if (fromPosition.Z < box.Min.Z)\n                    { //  X  Y -Z\n                        return [0, 1, 3, 2];\n                    }\n                    else if (fromPosition.Z > box.Max.Z)\n                    { //  X  Y +Z\n                        return [4, 6, 7, 5];\n                    }\n                    else\n                    { //  X  Y  Z\n                        return null;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in counter-clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static __ltype__[] GetOutlineCornersCCW(this __type__ box, __ltype__ fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        /// <summary>\n        /// Gets outline corners of a box as seen from given position (in clockwise order).\n        /// Returns null if position is inside the box.\n        /// </summary>\n        public static __ltype__[] GetOutlineCornersCW(this __type__ box, __ltype__ fromPosition)\n        {\n            var cs = box.ComputeCorners();\n            return GetOutlineCornerIndicesCW(box, fromPosition)?.Map(i => cs[i]);\n        }\n\n        #endregion\n        //# }\n    }\n    //# if (dim == 1) {\n\n    #region Range extensions\n\n    //# if (ft.IsReal) {\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        //# var units = new[] { \"Radians\", \"Degrees\", \"Gons\" };\n        //# units.ForEach(u1 => {\n        //# units.ForEach(u2 => { if (u1 == u2) return;\n        //# var n1 = u1.ToLower();\n        //# var n2 = u2.ToLower();\n        /// <summary>\n        /// Converts the angles given in __n2__ to __n1__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ __u1__From__u2__(this __type__ __n2__)\n            => new(__n2__.Min.__u1__From__u2__(), __n2__.Max.__u1__From__u2__());\n\n        //# }); });\n        #endregion\n    }\n\n    //# }\n    public static partial class __bnamecaps__Extensions\n    {\n        /// <summary>\n        /// Returns the int sequence 0 ... count-1.\n        /// </summary>\n        public static IEnumerable<__ltype__> Range(this __ltype__ count)\n        {\n            for (__ltype__ i = 0; i < count; i++) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<__ltype__> UpTo(this __ltype__ self, __ltype__ upToInclusive)\n        {\n            return self.UpTo(upToInclusive, 1);\n        }\n\n        public static IEnumerable<__ltype__> UpTo(this __ltype__ self, __ltype__ upToInclusive, __ltype__ step)\n        {\n            for (__ltype__ i = self; i <= upToInclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<__ltype__> UpToExclusive(this __ltype__ self, __ltype__ upToExclusive)\n        {\n            return self.UpToExclusive(upToExclusive, 1);\n        }\n\n        public static IEnumerable<__ltype__> UpToExclusive(this __ltype__ self, __ltype__ upToExclusive, __ltype__ step)\n        {\n            for (__ltype__ i = self; i < upToExclusive; i += step) yield return i;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static IEnumerable<__ltype__> DownTo(this __ltype__ self, __ltype__ downToInclusive)\n        {\n            return self.DownTo(downToInclusive, 1);\n        }\n\n        public static IEnumerable<__ltype__> DownTo(this __ltype__ self, __ltype__ downToInclusive, __ltype__ step)\n        {\n            for (__ltype__ i = self; i >= downToInclusive; i -= step) yield return i;\n        }\n    }\n\n    #endregion\n    //# }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b)\n        {\n            return ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __ftype__ tolerance)\n            => ApproximateEquals(a.Min, b.Min, tolerance) && ApproximateEquals(a.Max, b.Max, tolerance);\n\n        #endregion\n    }\n\n    #endregion\n\n    //# if (dim == 3) {\n    #region __type__AndFlags\n\n    [DataContract]\n    public struct __type__AndFlags\n    {\n        [DataMember]\n        public Box.Flags BFlags;\n        [DataMember]\n        public __type__ BBox;\n\n        public __type__AndFlags(__type__ union, __type__ box0, __type__ box1)\n        {\n            BFlags = 0;\n            BBox = union;\n            if (box0.Min.X > union.Min.X) { BBox.Min.X = box0.Min.X; BFlags |= Box.Flags.MinX0; }\n            if (box0.Min.Y > union.Min.Y) { BBox.Min.Y = box0.Min.Y; BFlags |= Box.Flags.MinY0; }\n            if (box0.Min.Z > union.Min.Z) { BBox.Min.Z = box0.Min.Z; BFlags |= Box.Flags.MinZ0; }\n            if (box0.Max.X < union.Max.X) { BBox.Max.X = box0.Max.X; BFlags |= Box.Flags.MaxX0; }\n            if (box0.Max.Y < union.Max.Y) { BBox.Max.Y = box0.Max.Y; BFlags |= Box.Flags.MaxY0; }\n            if (box0.Max.Z < union.Max.Z) { BBox.Max.Z = box0.Max.Z; BFlags |= Box.Flags.MaxZ0; }\n            if (box1.Min.X > union.Min.X) { BBox.Min.X = box1.Min.X; BFlags |= Box.Flags.MinX1; }\n            if (box1.Min.Y > union.Min.Y) { BBox.Min.Y = box1.Min.Y; BFlags |= Box.Flags.MinY1; }\n            if (box1.Min.Z > union.Min.Z) { BBox.Min.Z = box1.Min.Z; BFlags |= Box.Flags.MinZ1; }\n            if (box1.Max.X < union.Max.X) { BBox.Max.X = box1.Max.X; BFlags |= Box.Flags.MaxX1; }\n            if (box1.Max.Y < union.Max.Y) { BBox.Max.Y = box1.Max.Y; BFlags |= Box.Flags.MaxY1; }\n            if (box1.Max.Z < union.Max.Z) { BBox.Max.Z = box1.Max.Z; BFlags |= Box.Flags.MaxZ1; }\n        }\n    }\n\n    #endregion\n\n    //# }\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/RangesBoxes/Cell.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Runtime.Serialization;\nusing System.Text.Json.Serialization;\n\nnamespace Aardvark.Base;\n\n/// <summary>\n/// An axis-aligned cube in a hierarchical spatial grid where all cells have power-of-two sizes.\n/// Position is (X,Y,Z) * 2^Exponent, size is 2^Exponent.\n/// </summary>\n[DataContract]\npublic readonly partial struct Cell : IEquatable<Cell>\n{\n    /// <summary>\n    /// Unit cell (0, 0, 0, 0) -> Box3d[(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]\n    /// </summary>\n    public static Cell Unit => new(0L, 0L, 0L, 0);\n\n    /// <summary>\n    /// Special value denoting \"invalid cell\".\n    /// </summary>\n    public static Cell Invalid => new(long.MinValue, long.MinValue, long.MinValue, int.MinValue);\n\n    /// <summary>\n    /// Grid coordinate at resolution 2^Exponent.\n    /// </summary>\n    [DataMember]\n    public readonly long X;\n\n    /// <summary>\n    /// Grid coordinate at resolution 2^Exponent.\n    /// </summary>\n    [DataMember]\n    public readonly long Y;\n\n    /// <summary>\n    /// Grid coordinate at resolution 2^Exponent.\n    /// </summary>\n    [DataMember]\n    public readonly long Z;\n\n    /// <summary>\n    /// Power of two defining both cell size and grid resolution.\n    /// </summary>\n    [DataMember(Name = \"E\")]\n    public readonly int Exponent;\n\n    #region constructors\n\n    /// <summary>\n    /// Creates a 2^exponent sized cube positioned at (x,y,z) * 2^exponent.\n    /// </summary>\n    public Cell(long x, long y, long z, int exponent)\n    {\n        X = x; Y = y; Z = z; Exponent = exponent;\n    }\n\n    /// <summary>\n    /// Creates copy of cell.\n    /// </summary>\n    public Cell(Cell cell)\n    {\n        X = cell.X; Y = cell.Y; Z = cell.Z; Exponent = cell.Exponent;\n    }\n\n    /// <summary>\n    /// Cell with min corner at index*2^exponent and size 2^exponent.\n    /// </summary>\n    public Cell(V3l index, int exponent) : this(index.X, index.Y, index.Z, exponent) { }\n\n    /// <summary>\n    /// Special cell, which is centered at origin, with size 2^exponent.\n    /// </summary>\n    public Cell(int exponent)\n    {\n        if (exponent == int.MinValue)\n        {\n            X = long.MinValue; Y = long.MinValue; Z = long.MinValue; Exponent = exponent;\n        }\n        else\n        {\n            X = long.MaxValue; Y = long.MaxValue; Z = long.MaxValue; Exponent = exponent;\n        }\n    }\n\n    /// <summary>\n    /// Smallest cell that contains given box.\n    /// </summary>\n    public Cell(Box3f box) : this(new Box3d(box)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell(V3f[] ps) : this(new Box3f(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell(ReadOnlySpan<V3f> ps) : this(new Box3f(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell(V3d[] ps) : this(new Box3d(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell(ReadOnlySpan<V3d> ps) : this(new Box3d(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell(IEnumerable<V3f> ps) : this(new Box3f(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell(IEnumerable<V3d> ps) : this(new Box3d(ps)) { }\n\n    /// <summary>\n    /// Smallest cell containing the given point.\n    /// </summary>\n    public Cell(V3d p) : this(new Box3d(p)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given box, \n    /// where box.Min and box.Max are both interpreted as inclusive\n    /// (whereas a cell's maximum is defined as exclusive).\n    /// </summary>\n    public Cell(Box3d box)\n    {\n        if (!box.IsValid) throw new InvalidOperationException();\n\n        // case 1: contains origin\n        if (box.Min.X < 0.0 && box.Max.X >= 0.0 ||\n            box.Min.Y < 0.0 && box.Max.Y >= 0.0 ||\n            box.Min.Z < 0.0 && box.Max.Z >= 0.0)\n        {\n            X = Y = Z = long.MaxValue;\n            Exponent = Math.Max(box.Min.NormMax, box.Max.NormMax).Log2CeilingInt() + 1;\n        }\n        else // case 2: doesn't contain origin\n        {\n            Exponent = (box.Min == box.Max)\n                    ? (box.Min.NormMax / (long.MaxValue >> 1)).Log2CeilingInt()\n                    : box.Size.NormMax.Log2CeilingInt()\n                    ;\n            var s = Math.Pow(2.0, Exponent);\n            var a = (box.Min * (1.0 / s)).Floor();\n\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)a.Z;\n\n            while (box.Max.X >= X * s + s || box.Max.Y >= Y * s + s || box.Max.Z >= Z * s + s)\n            {\n                X >>= 1; Y >>= 1; Z >>= 1; ++Exponent;\n                s *= 2.0;\n            }\n        }\n    }\n\n    /// <summary>\n    /// Common root of a and b.\n    /// </summary>\n    public Cell(Cell a, Cell b) : this(GetCommonRoot(a, b)) { }\n\n    /// <summary>\n    /// Common root of cells.\n    /// </summary>\n    public Cell(params Cell[] cells) : this(GetCommonRoot(cells)) { }\n\n    #endregion\n\n    /// <summary>\n    /// Grid coordinates as a vector.\n    /// </summary>\n    [JsonIgnore]\n    public V3l XYZ => new(X, Y, Z);\n\n    /// <summary>\n    /// True if special cell centered at the origin.\n    /// </summary>\n    [JsonIgnore]\n    public bool IsCenteredAtOrigin => X == long.MaxValue && Y == long.MaxValue && Z == long.MaxValue;\n\n    /// <summary>\n    /// Returns true if this is the special invalid cell.\n    /// </summary>\n    [JsonIgnore]\n    public bool IsInvalid => X == long.MinValue && Y == long.MinValue && Z == long.MinValue && Exponent == int.MinValue;\n\n    /// <summary>\n    /// Returns true if this is NOT the special invalid cell.\n    /// </summary>\n    [JsonIgnore]\n    public bool IsValid => X != long.MinValue || Y != long.MinValue || Z != long.MinValue || Exponent != int.MinValue;\n\n    /// <summary>\n    /// Returns true if the cell completely contains the other cell.\n    /// A cell contains itself.\n    /// </summary>\n    public bool Contains(Cell other)\n    {\n        if (other.Exponent > Exponent) return false;\n        if (other.Exponent == Exponent) return other.X == X && other.Y == Y && other.Z == Z;\n\n        // always true from here on:\n        //   Exponent > other.Exponent\n        //   other.Exponent < Exponent\n\n        if (IsCenteredAtOrigin)\n        {\n            if (other.IsCenteredAtOrigin)\n            {\n                return true;\n            }\n            else\n            {\n                // bring other into scale of this\n                var d = (Exponent - 1) - other.Exponent;\n\n                // right-shift with long argument only uses low-order 6 bits\n                // https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/operators/right-shift-operator\n                if (d > 63) d = 63;\n\n                var x = other.X >> d;\n                var y = other.Y >> d;\n                var z = other.Z >> d;\n                return x >= -1 && x <= 0 && y >= -1 && y <= 0 && z >= -1 && z <= 0;\n            }\n        }\n        else\n        {\n            if (other.IsCenteredAtOrigin)\n            {\n                return false;\n            }\n            else\n            {\n                // bring other into scale of this\n                var d = Exponent - other.Exponent;\n\n                // right-shift with long argument only uses low-order 6 bits\n                // https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/operators/right-shift-operator\n                if (d > 63) d = 63;\n\n                var x = other.X >> d;\n                var y = other.Y >> d;\n                var z = other.Z >> d;\n                return x == X && y == Y && z == Z;\n            }\n        }\n    }\n\n    /// <summary>\n    /// Returns true if two cells intersect each other (or one contains the other).\n    /// Cells DO NOT intersect if only touching from the outside.\n    /// A cell intersects itself.\n    /// </summary>\n    public bool Intersects(Cell other)\n    {\n        if (X == other.X && Y == other.Y && Z == other.Z && Exponent == other.Exponent) return true;\n        return BoundingBox.Intersects(other.BoundingBox);\n    }\n\n    /// <summary>\n    /// The 8 subcells created by splitting each axis in half.\n    /// </summary>\n    [JsonIgnore]\n    public Cell[] Children\n    {\n        get\n        {\n            var x0 = X << 1; var y0 = Y << 1; var z0 = Z << 1;\n            if (IsCenteredAtOrigin) { x0++; y0++; z0++; }\n            var x1 = x0 + 1; var y1 = y0 + 1; var z1 = z0 + 1;\n            var e = Exponent - 1;\n            return\n            [\n                new(x0, y0, z0, e),\n                new(x1, y0, z0, e),\n                new(x0, y1, z0, e),\n                new(x1, y1, z0, e),\n                new(x0, y0, z1, e),\n                new(x1, y0, z1, e),\n                new(x0, y1, z1, e),\n                new(x1, y1, z1, e),\n            ];\n        }\n    }\n\n    /// <summary>\n    /// Gets parent cell.\n    /// </summary>\n    [JsonIgnore]\n    public Cell Parent => IsCenteredAtOrigin ? new(Exponent + 1) : new(X >> 1, Y >> 1, Z >> 1, Exponent + 1);\n\n    /// <summary>\n    /// True if any corner of this cell is exactly at the origin.\n    /// </summary>\n    [JsonIgnore]\n    public bool TouchesOrigin => !IsCenteredAtOrigin && (X == -1 || X == 0) && (Y == -1 || Y == 0) && (Z == -1 || Z == 0);\n\n    /// <summary>\n    /// Cell's bounds as Box3d.\n    /// </summary>\n    [JsonIgnore]\n    public Box3d BoundingBox => ComputeBoundingBox(X, Y, Z, Exponent);\n\n    private static Box3d ComputeBoundingBox(long x, long y, long z, int e)\n    {\n        var d = Math.Pow(2.0, e);\n        var isCenteredAtOrigin = x == long.MaxValue && y == long.MaxValue && z == long.MaxValue;\n        var min = isCenteredAtOrigin ? new V3d(-0.5 * d) : new V3d(x * d, y * d, z * d);\n        return Box3d.FromMinAndSize(min, new V3d(d, d, d));\n    }\n\n    /// <summary>\n    /// Computes geometric center point of this cell.\n    /// </summary>\n    public V3d GetCenter() => BoundingBox.Center;\n\n    /// <summary>\n    /// Octant 0-7.\n    /// 0th, 1st and 2nd bit encodes x-, y-, z-axis, respectively.\n    /// E.g. 0 is octant at origin, 7 is octant oposite from origin.\n    /// </summary>\n    public Cell GetOctant(int i)\n    {\n        if (i < 0 || i > 7) throw new IndexOutOfRangeException();\n\n        if (IsCenteredAtOrigin)\n        {\n            return new(\n                (i & 1) == 0 ? -1 : 0,\n                (i & 2) == 0 ? -1 : 0,\n                (i & 4) == 0 ? -1 : 0,\n                Exponent - 1\n                );\n        }\n        else\n        {\n            return new(\n                (X << 1) + ((i & 1) == 0 ? 0 : 1),\n                (Y << 1) + ((i & 2) == 0 ? 0 : 1),\n                (Z << 1) + ((i & 4) == 0 ? 0 : 1),\n                Exponent - 1\n                );\n        }\n    }\n\n    /// <summary>\n    /// Returns the octant of this cell, in which the other cell is contained.\n    /// If the other cell is not contained in any octant, then no value is returned.\n    /// </summary>\n    public int? GetOctant(Cell other)\n    {\n        // if other cell is bigger or same size, \n        // then it cannot be contained in any octant\n        if (other.Exponent >= Exponent) return null;\n\n        if (IsCenteredAtOrigin)\n        {\n            if (other.IsCenteredAtOrigin) return null;\n\n            // scale up other to scale of this cell's octants\n            // where coord values 0 or 1 mean left or right,\n            // and all other values mean that the other cell is outside\n            other <<= Exponent - other.Exponent - 1;\n            var o = 0;\n            if (other.X == 0) o  = 1; else if (other.X != -1) return null;\n            if (other.Y == 0) o |= 2; else if (other.Y != -1) return null;\n            if (other.Z == 0) o |= 4; else if (other.Z != -1) return null;\n            return o;\n        }\n        else\n        {\n            if (other.IsCenteredAtOrigin) return null;\n\n            // scale up other to scale of this cell's octants,\n            // where coord values -1 or 0 mean left or right,\n            // and all other values mean that the other cell is outside\n            other <<= Exponent - other.Exponent - 1;\n            var x = X << 1;\n            var y = Y << 1;\n            var z = Z << 1;\n            var o = 0;\n            if (other.X == x + 1) o  = 1; else if (other.X != x) return null;\n            if (other.Y == y + 1) o |= 2; else if (other.Y != y) return null;\n            if (other.Z == z + 1) o |= 4; else if (other.Z != z) return null;\n            return o;\n        }\n    }\n\n    /// <summary>\n    /// Get the global octant this cell is located in, or no value if this is a centered cell.\n    /// </summary>\n    public int? Octant\n    {\n        get\n        {\n            if (IsCenteredAtOrigin) return null;\n\n            var o = 0;\n            if (X >= 0) o  = 1;\n            if (Y >= 0) o |= 2;\n            if (Z >= 0) o |= 4;\n            return o;\n        }\n    }\n\n    /// <summary>\n    /// Smallest cell that contains both input cells.\n    /// </summary>\n    public static Cell GetCommonRoot(Cell a, Cell b)\n    {\n        if (a == b) return a;\n\n        if (a.IsCenteredAtOrigin)\n        {\n            if (b.IsCenteredAtOrigin)\n            {\n                // if both are centered, then the larger cell is the result\n                return a.Exponent > b.Exponent ? a : b;\n            }\n            else\n            {\n                // if A is centered and B is not centered,\n                // then enlarge A until it contains B\n                while (!a.Contains(b)) a = a.Parent;\n                return a;\n            }\n        }\n        else\n        {\n            if (b.IsCenteredAtOrigin)\n            {\n                // if A is not centered and B is centered,\n                // then enlarge B until it contains A\n                while (!b.Contains(a)) b = b.Parent;\n                return b;\n            }\n            else\n            {\n                // if no cell is centered, ...\n                if (a.Octant == b.Octant)\n                {\n                    // and both cells are located in the same global octant,\n                    // then recursively grow smaller cell (take parent)\n                    // until a and b meet at their common root\n                    return a.Exponent > b.Exponent ? GetCommonRoot(a, b.Parent) : GetCommonRoot(a.Parent, b);\n                }\n                else\n                {\n                    // and each cell is located in a different global octant,\n                    // then take a centered cell and enlarge it until it contains both A and B\n                    var c = new Cell(Math.Max(a.Exponent, b.Exponent) + 1); // centered cell needs to be at least twice as large as the bigger one of A and B\n                    while (!c.Contains(a)) c = c.Parent;\n                    while (!c.Contains(b)) c = c.Parent;\n                    return c;\n                }\n            }\n        }\n    }\n\n    /// <summary>\n    /// Smallest cell that contains all input cells.\n    /// </summary>\n    public static Cell GetCommonRoot(params Cell[] cells)\n    {\n        if (cells == null || cells.Length == 0) throw new ArgumentException(\"No cells.\");\n        var r = cells[0];\n        for (var i = 1; i < cells.Length; i++) r = new(r, cells[i]);\n        return r;\n    }\n\n    #region operators\n\n    /// <summary>\n    /// Makes cell 2^d times smaller. Minimum corner stays at the same position.\n    /// </summary>\n    public static Cell operator >>(Cell a, int d)\n    {\n        if (d < 1) return a;\n\n        if (a.IsCenteredAtOrigin) return new(a.Exponent - d);\n\n        // right-shift with long argument only uses low-order 6 bits\n        // https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/operators/right-shift-operator\n        if (d > 63) d = 63;\n\n        return new(a.X << d, a.Y << d, a.Z << d, a.Exponent - d);\n    }\n\n    /// <summary>\n    /// Makes cell 2^d times larger. Minimum corner moves to the origin of the coarse cell containing it.\n    /// </summary>\n    public static Cell operator <<(Cell a, int d)\n    {\n        if (d < 1) return a;\n\n        if (a.IsCenteredAtOrigin) return new(a.Exponent + d);\n\n        // right-shift with long argument only uses low-order 6 bits\n        // https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/operators/right-shift-operator\n        if (d > 63) d = 63;\n\n        return new(a.X >> d, a.Y >> d, a.Z >> d, a.Exponent + d);\n    }\n\n    #endregion\n\n    #region equality and hashing\n\n    /// <summary>\n    /// </summary>\n    public bool Equals(Cell other) => this == other;\n\n    /// <summary>\n    /// </summary>\n    public static bool operator ==(Cell a, Cell b) => a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.Exponent == b.Exponent;\n\n    /// <summary>\n    /// </summary>\n    public static bool operator !=(Cell a, Cell b) => !(a == b);\n\n    /// <summary>\n    /// </summary>\n    public override bool Equals(object obj) => obj is Cell cell && this == cell;\n\n    /// <summary>\n    /// </summary>\n    public override int GetHashCode() => HashCode.GetCombined(X, Y, Z, Exponent);\n\n    #endregion\n\n    #region string serialization\n\n    /// <summary></summary>\n    public override string ToString()\n    {\n        if (IsCenteredAtOrigin || IsInvalid)\n        {\n            return $\"[{Exponent}]\";\n        }\n        else\n        {\n            return $\"[{X}, {Y}, {Z}, {Exponent}]\";\n        }\n    }\n\n    public static Cell Parse(string s)\n    {\n#if NETSTANDARD2_0\n        var xs = s.Substring(1, s.Length - 2).Split(',');\n#else\n        var xs = s[1..^1].Split(',');\n#endif\n        return xs.Length switch\n        {\n            1 => new(exponent: int.Parse(xs[0])),\n            4 => new(x: long.Parse(xs[0]), y: long.Parse(xs[1]), z: long.Parse(xs[2]), exponent: int.Parse(xs[3])),\n            _ => throw new FormatException(\n                $\"Expected [<x>,<y>,<z>,<exponent>], or [<exponent>], but found {s}. \" +\n                $\"Error 973f176d-6780-4f77-8736-0ed341adf136.\"\n                )\n        };\n    }\n\n#endregion\n\n    #region binary serialization\n\n    /// <summary>\n    /// </summary>\n    public byte[] ToByteArray()\n    {\n        var buffer = new byte[28];\n        using (var ms = new MemoryStream(buffer))\n        using (var bw = new BinaryWriter(ms))\n        {\n            bw.Write(X); bw.Write(Y); bw.Write(Z); bw.Write(Exponent);\n        }\n        return buffer;\n    }\n\n    /// <summary>\n    /// </summary>\n    public static Cell Parse(byte[] buffer)\n    {\n        using var ms = new MemoryStream(buffer, 0, 28);\n        using var br = new BinaryReader(ms);\n        var x = br.ReadInt64(); var y = br.ReadInt64(); var z = br.ReadInt64(); var e = br.ReadInt32();\n        return new(x, y, z, e);\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/RangesBoxes/Cell2d.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Runtime.Serialization;\nusing System.Text.Json.Serialization;\n\nnamespace Aardvark.Base;\n\n/// <summary>\n/// An axis-aligned square in a hierarchical spatial grid where all cells have power-of-two sizes.\n/// Position is (X,Y) * 2^Exponent, size is 2^Exponent.\n/// </summary>\n[DataContract]\npublic readonly partial struct Cell2d : IEquatable<Cell2d>\n{\n    /// <summary>\n    /// Unit cell (0, 0, 0) -> Box2d[(0.0, 0.0), (1.0, 1.0)]\n    /// </summary>\n    public static readonly Cell2d Unit = new(0L, 0L, 0);\n\n    /// <summary>\n    /// Special value denoting \"invalid cell\".\n    /// </summary>\n    public static Cell2d Invalid => new(long.MinValue, long.MinValue, int.MinValue);\n\n    /// <summary>\n    /// Grid coordinate at resolution 2^Exponent.\n    /// </summary>\n    [DataMember]\n    public readonly long X;\n\n    /// <summary>\n    /// Grid coordinate at resolution 2^Exponent.\n    /// </summary>\n    [DataMember]\n    public readonly long Y;\n\n    /// <summary>\n    /// Power of two defining both cell size and grid resolution.\n    /// </summary>\n    [DataMember(Name = \"E\")]\n    public readonly int Exponent;\n\n    #region constructors\n\n    /// <summary>\n    /// Creates a 2^exponent sized square positioned at (x,y) * 2^exponent.\n    /// </summary>\n    public Cell2d(long x, long y, int exponent)\n    {\n        X = x; Y = y; Exponent = exponent;\n    }\n\n    /// <summary>\n    /// Creates a 2^exponent sized square positioned at (x,y) * 2^exponent.\n    /// </summary>\n    public Cell2d(int x, int y, int exponent)\n    {\n        X = x; Y = y; Exponent = exponent;\n    }\n\n    /// <summary>\n    /// Creates copy of cell.\n    /// </summary>\n    public Cell2d(Cell2d cell)\n    {\n        X = cell.X; Y = cell.Y; Exponent = cell.Exponent;\n    }\n\n    /// <summary>\n    /// Cell with min corner at index*2^exponent and size 2^exponent.\n    /// </summary>\n    public Cell2d(V2l index, int exponent) : this(index.X, index.Y, exponent) { }\n\n    /// <summary>\n    /// Cell with min corner at index*2^exponent and size 2^exponent.\n    /// </summary>\n    public Cell2d(V2i index, int exponent) : this(index.X, index.Y, exponent) { }\n\n    /// <summary>\n    /// Special cell, which is centered at origin, with size 2^exponent.\n    /// </summary>\n    public Cell2d(int exponent)\n    {\n        if (exponent == int.MinValue)\n        {\n            X = long.MinValue; Y = long.MinValue; Exponent = exponent;\n        }\n        else\n        {\n            X = long.MaxValue; Y = long.MaxValue; Exponent = exponent;\n        }\n    }\n\n    /// <summary>\n    /// Smallest cell that contains given box.\n    /// </summary>\n    public Cell2d(Box2f box) : this(new Box2d(box)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell2d(V2f[] ps) : this(new Box2f(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell2d(ReadOnlySpan<V2f> ps) : this(new Box2f(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell2d(V2d[] ps) : this(new Box2d(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell2d(ReadOnlySpan<V2d> ps) : this(new Box2d(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell2d(IEnumerable<V2f> ps) : this(new Box2f(ps)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given points.\n    /// </summary>\n    public Cell2d(IEnumerable<V2d> ps) : this(new Box2d(ps)) { }\n\n    /// <summary>\n    /// Smallest cell containing the given point.\n    /// </summary>\n    public Cell2d(V2d p) : this(new Box2d(p)) { }\n\n    /// <summary>\n    /// Smallest cell that contains given box, \n    /// where box.Min and box.Max are both interpreted as inclusive\n    /// (whereas a cell's maximum is defined as exclusive).\n    /// </summary>\n    public Cell2d(Box2d box)\n    {\n        if (!box.IsValid) throw new InvalidOperationException();\n\n        // case 1: contains origin\n        if (box.Min.X < 0.0 && box.Max.X >= 0.0 ||\n            box.Min.Y < 0.0 && box.Max.Y >= 0.0)\n        {\n            X = Y = long.MaxValue;\n            Exponent = Math.Max(box.Min.NormMax, box.Max.NormMax).Log2CeilingInt() + 1;\n        }\n        else // case 2: doesn't contain origin\n        {\n            Exponent = (box.Min == box.Max)\n                    ? (box.Min.NormMax / (long.MaxValue >> 1)).Log2CeilingInt()\n                    : box.Size.NormMax.Log2CeilingInt()\n                    ;\n            var s = Math.Pow(2.0, Exponent);\n            var a = (box.Min * (1.0 / s)).Floor();\n\n            X = (long)a.X;\n            Y = (long)a.Y;\n\n            while (box.Max.X >= X * s + s || box.Max.Y >= Y * s + s)\n            {\n                X >>= 1; Y >>= 1; ++Exponent;\n                s *= 2.0;\n            }\n        }\n    }\n\n    /// <summary>\n    /// Common root of a and b.\n    /// </summary>\n    public Cell2d(Cell2d a, Cell2d b) : this(GetCommonRoot(a, b)) { }\n\n    /// <summary>\n    /// Common root of cells.\n    /// </summary>\n    public Cell2d(params Cell2d[] cells) : this(GetCommonRoot(cells)) { }\n\n    #endregion\n\n    /// <summary>\n    /// Grid coordinates as a vector.\n    /// </summary>\n    [JsonIgnore]\n    public V2l XY => new(X, Y);\n\n    /// <summary>\n    /// True if special cell centered at the origin.\n    /// </summary>\n    [JsonIgnore]\n    public bool IsCenteredAtOrigin => X == long.MaxValue && Y == long.MaxValue;\n\n    /// <summary>\n    /// Returns true if this is the special invalid cell.\n    /// </summary>\n    [JsonIgnore]\n    public bool IsInvalid => X == long.MinValue && Y == long.MinValue && Exponent == int.MinValue;\n\n    /// <summary>\n    /// Returns true if this is NOT the special invalid cell.\n    /// </summary>\n    [JsonIgnore]\n    public bool IsValid => X != long.MinValue || Y != long.MinValue || Exponent != int.MinValue;\n\n    /// <summary>\n    /// Returns true if the cell completely contains the other cell.\n    /// A cell contains itself.\n    /// </summary>\n    public bool Contains(Cell2d other)\n    {\n        if (other.Exponent > Exponent) return false;\n        if (other.Exponent == Exponent) return other.X == X && other.Y == Y;\n\n        // always true from here on:\n        //   Exponent > other.Exponent\n        //   other.Exponent < Exponent\n\n        if (IsCenteredAtOrigin)\n        {\n            if (other.IsCenteredAtOrigin)\n            {\n                return true;\n            }\n            else\n            {\n                // bring other into scale of this\n                var d = (Exponent - 1) - other.Exponent;\n\n                // right-shift with long argument only uses low-order 6 bits\n                // https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/operators/right-shift-operator\n                if (d > 63) d = 63;\n\n                var x = other.X >> d;\n                var y = other.Y >> d;\n                return x >= -1 && x <= 0 && y >= -1 && y <= 0;\n            }\n        }\n        else\n        {\n            if (other.IsCenteredAtOrigin)\n            {\n                return false;\n            }\n            else\n            {\n                // bring other into scale of this\n                var d = Exponent - other.Exponent;\n\n                // right-shift with long argument only uses low-order 6 bits\n                // https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/operators/right-shift-operator\n                if (d > 63) d = 63;\n\n                var x = other.X >> d;\n                var y = other.Y >> d;\n                return x == X && y == Y;\n            }\n        }\n    }\n\n    /// <summary>\n    /// Returns true if two cells intersect each other (or one contains the other).\n    /// Cells DO NOT intersect if only touching from the outside.\n    /// A cell intersects itself.\n    /// </summary>\n    public bool Intersects(Cell2d other)\n    {\n        if (X == other.X && Y == other.Y && Exponent == other.Exponent) return true;\n        return BoundingBox.Intersects(other.BoundingBox);\n    }\n\n    /// <summary>\n    /// Gets the 4 subcells.\n    /// Order is (0,0), (1,0), (0,1), (1,1).\n    /// </summary>\n    [JsonIgnore]\n    public Cell2d[] Children\n    {\n        get\n        {\n            var x0 = X << 1; var y0 = Y << 1;\n            if (IsCenteredAtOrigin) { x0++; y0++; }\n            var x1 = x0 + 1; var y1 = y0 + 1;\n            var e = Exponent - 1;\n            return\n            [\n                new(x0, y0, e),\n                new(x1, y0, e),\n                new(x0, y1, e),\n                new(x1, y1, e),\n            ];\n        }\n    }\n\n    /// <summary>\n    /// Gets parent cell.\n    /// </summary>\n    [JsonIgnore]\n    public Cell2d Parent => IsCenteredAtOrigin ? new(Exponent + 1) : new(X >> 1, Y >> 1, Exponent + 1);\n\n    /// <summary>\n    /// True if any corner of this cell is exactly at the origin.\n    /// </summary>\n    [JsonIgnore]\n    public bool TouchesOrigin => !IsCenteredAtOrigin && (X == -1 || X == 0) && (Y == -1 || Y == 0);\n\n    /// <summary>\n    /// Cell's bounds as Box2d.\n    /// </summary>\n    [JsonIgnore]\n    public Box2d BoundingBox => ComputeBoundingBox(X, Y, Exponent);\n\n    private static Box2d ComputeBoundingBox(long x, long y, int e)\n    {\n        var d = Math.Pow(2.0, e);\n        var isCenteredAtOrigin = x == long.MaxValue && y == long.MaxValue;\n        var min = isCenteredAtOrigin ? new V2d(-0.5 * d) : new V2d(x * d, y * d);\n        return Box2d.FromMinAndSize(min, new V2d(d, d));\n    }\n\n    /// <summary>\n    /// Computes cell's center.\n    /// </summary>\n    public V2d GetCenter() => BoundingBox.Center;\n\n    /// <summary>\n    /// Quadrant 0-3.\n    /// 0th and 1st bit encodes x-, y-axis, respectively.\n    /// E.g. 0 is quadrant at origin, 3 is quadrant oposite from origin.\n    /// </summary>\n    public Cell2d GetQuadrant(int i)\n    {\n        if (i < 0 || i > 3) throw new IndexOutOfRangeException();\n\n        if (IsCenteredAtOrigin)\n        {\n            return new(\n                (i & 1) == 0 ? -1 : 0,\n                (i & 2) == 0 ? -1 : 0,\n                Exponent - 1\n                );\n        }\n        else\n        {\n            return new(\n                (X << 1) + ((i & 1) == 0 ? 0 : 1),\n                (Y << 1) + ((i & 2) == 0 ? 0 : 1),\n                Exponent - 1\n                );\n        }\n    }\n\n    /// <summary>\n    /// Returns the quadrant of this cell, in which the other cell is contained.\n    /// If the other cell is not contained in any quadrant, then no value is returned.\n    /// </summary>\n    public int? GetQuadrant(Cell2d other)\n    {\n        // if other cell is bigger or same size, \n        // then it cannot be contained in any quadrant\n        if (other.Exponent >= Exponent) return null;\n\n        if (IsCenteredAtOrigin)\n        {\n            if (other.IsCenteredAtOrigin) return null;\n\n            // scale up other to scale of this cell's quadrants\n            // where coord values 0 or 1 mean left or right,\n            // and all other values mean that the other cell is outside\n            other <<= Exponent - other.Exponent - 1;\n            var o = 0;\n            if (other.X == 0) o = 1; else if (other.X != -1) return null;\n            if (other.Y == 0) o |= 2; else if (other.Y != -1) return null;\n            return o;\n        }\n        else\n        {\n            if (other.IsCenteredAtOrigin) return null;\n\n            // scale up other to scale of this cell's quadrants,\n            // where coord values -1 or 0 mean left or right,\n            // and all other values mean that the other cell is outside\n            other <<= Exponent - other.Exponent - 1;\n            var x = X << 1;\n            var y = Y << 1;\n            var o = 0;\n            if (other.X == x + 1) o = 1; else if (other.X != x) return null;\n            if (other.Y == y + 1) o |= 2; else if (other.Y != y) return null;\n            return o;\n        }\n    }\n\n    /// <summary>\n    /// Get the global quadtrant this cell is located in, or no value if this is a centered cell.\n    /// </summary>\n    public int? Quadrant\n    {\n        get\n        {\n            if (IsCenteredAtOrigin) return null;\n\n            var o = 0;\n            if (X >= 0) o = 1;\n            if (Y >= 0) o |= 2;\n            return o;\n        }\n    }\n\n    /// <summary>\n    /// Smallest cell that contains both input cells.\n    /// </summary>\n    public static Cell2d GetCommonRoot(Cell2d a, Cell2d b)\n    {\n        if (a == b) return a;\n\n        if (a.IsCenteredAtOrigin)\n        {\n            if (b.IsCenteredAtOrigin)\n            {\n                // if both are centered, then the larger cell is the result\n                return a.Exponent > b.Exponent ? a : b;\n            }\n            else\n            {\n                // if A is centered and B is not centered,\n                // then enlarge A until it contains B\n                while (!a.Contains(b)) a = a.Parent;\n                return a;\n            }\n        }\n        else\n        {\n            if (b.IsCenteredAtOrigin)\n            {\n                // if A is not centered and B is centered,\n                // then enlarge B until it contains A\n                while (!b.Contains(a)) b = b.Parent;\n                return b;\n            }\n            else\n            {\n                // if no cell is centered, ...\n                if (a.Quadrant == b.Quadrant)\n                {\n                    // and both cells are located in the same global quadrant,\n                    // then recursively grow smaller cell (take parent)\n                    // until a and b meet at their common root\n                    return a.Exponent > b.Exponent ? GetCommonRoot(a, b.Parent) : GetCommonRoot(a.Parent, b);\n                }\n                else\n                {\n                    // and each cell is located in a different global quadrant,\n                    // then take a centered cell and enlarge it until it contains both A and B\n                    var c = new Cell2d(Math.Max(a.Exponent, b.Exponent) + 1); // centered cell needs to be at least twice as large as the bigger one of A and B\n                    while (!c.Contains(a)) c = c.Parent;\n                    while (!c.Contains(b)) c = c.Parent;\n                    return c;\n                }\n            }\n        }\n    }\n\n    /// <summary>\n    /// Smallest cell that contains all input cells.\n    /// </summary>\n    public static Cell2d GetCommonRoot(params Cell2d[] cells)\n    {\n        if (cells == null || cells.Length == 0) throw new ArgumentException(\"No cells.\");\n        var r = cells[0];\n        for (var i = 1; i < cells.Length; i++) r = new(r, cells[i]);\n        return r;\n    }\n\n    #region operators\n\n    /// <summary>\n    /// Makes cell 2^d times smaller. Minimum corner stays at the same position.\n    /// </summary>\n    public static Cell2d operator >>(Cell2d a, int d)\n    {\n        if (d < 1) return a;\n\n        if (a.IsCenteredAtOrigin) return new(a.Exponent - d);\n\n        // right-shift with long argument only uses low-order 6 bits\n        // https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/operators/right-shift-operator\n        if (d > 63) d = 63;\n\n        return new(a.X << d, a.Y << d, a.Exponent - d);\n    }\n\n    /// <summary>\n    /// Makes cell 2^d times larger. Minimum corner moves to the origin of the coarse cell containing it.\n    /// </summary>\n    public static Cell2d operator <<(Cell2d a, int d)\n    {\n        if (d < 1) return a;\n\n        if (a.IsCenteredAtOrigin) return new(a.Exponent + d);\n\n        // right-shift with long argument only uses low-order 6 bits\n        // https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/operators/right-shift-operator\n        if (d > 63) d = 63;\n\n        return new(a.X >> d, a.Y >> d, a.Exponent + d);\n    }\n\n    #endregion\n\n    #region equality and hashing\n\n    /// <summary>\n    /// </summary>\n    public bool Equals(Cell2d other) => this == other;\n\n    /// <summary>\n    /// </summary>\n    public static bool operator ==(Cell2d a, Cell2d b) => a.X == b.X && a.Y == b.Y && a.Exponent == b.Exponent;\n\n    /// <summary>\n    /// </summary>\n    public static bool operator !=(Cell2d a, Cell2d b) => !(a == b);\n\n    /// <summary>\n    /// </summary>\n    public override bool Equals(object obj) => obj is Cell2d other && this == other;\n\n    /// <summary>\n    /// </summary>\n    public override int GetHashCode() => HashCode.GetCombined(X, Y, Exponent);\n\n    #endregion\n\n    #region binary serialization\n\n    /// <summary>\n    /// </summary>\n    public byte[] ToByteArray()\n    {\n        var buffer = new byte[20];\n        using var ms = new MemoryStream(buffer);\n        using var bw = new BinaryWriter(ms);\n        bw.Write(X); bw.Write(Y); bw.Write(Exponent);\n        return buffer;\n    }\n\n    /// <summary>\n    /// </summary>\n    public static Cell2d Parse(byte[] buffer)\n    {\n        using var ms = new MemoryStream(buffer, 0, 20);\n        using var br = new BinaryReader(ms);\n        var x = br.ReadInt64(); var y = br.ReadInt64(); var e = br.ReadInt32();\n        return new(x, y, e);\n    }\n\n    #endregion\n\n    #region string serialization\n\n    /// <summary></summary>\n    public override string ToString()\n    {\n        if (IsCenteredAtOrigin || IsInvalid)\n        {\n            return $\"[{Exponent}]\";\n        }\n        else\n        {\n            return $\"[{X}, {Y}, {Exponent}]\";\n        }\n    }\n\n    public static Cell2d Parse(string s)\n    {\n#if NETSTANDARD2_0\n        var xs = s.Substring(1, s.Length - 2).Split(',');\n#else\n        var xs = s[1..^1].Split(',');\n#endif\n        return xs.Length switch\n        {\n            1 => new(exponent: int.Parse(xs[0])),\n            3 => new(x: long.Parse(xs[0]), y: long.Parse(xs[1]), exponent: int.Parse(xs[2])),\n            _ => throw new FormatException(\n                $\"Expected [<x>,<y>,<exponent>], or [<exponent>], but found {s}. \" +\n                $\"Error 47575d6f-072a-4166-ac83-5c4effa33427.\"\n                )\n        };\n    }\n\n#endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/RangesBoxes/OrientedBox_auto.cs",
    "content": "using System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region OrientedBox2f\n\n    [DataContract]\n    public struct OrientedBox2f\n    {\n        [DataMember]\n        public Box2f Box;\n        [DataMember]\n        public Euclidean2f Trafo;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2f(OrientedBox2d box)\n        {\n            Box = (Box2f)box.Box;\n            Trafo = (Euclidean2f)box.Trafo;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2f(Box2f box)\n        {\n            Box = box;\n            Trafo = Euclidean2f.Identity;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2f(Box2f box, Rot2f rot)\n        {\n            Box = box;\n            Trafo = new Euclidean2f(rot, V2f.Zero);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2f(Box2f box, V2f trans)\n        {\n            Box = box;\n            Trafo = new Euclidean2f(Rot2f.Identity, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2f(Box2f box, Rot2f rot, V2f trans)\n        {\n            Box = box;\n            Trafo = new Euclidean2f(rot, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2f(Box2f box, Euclidean2f trafo)\n        {\n            Box = box;\n            Trafo = trafo;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator OrientedBox2f(OrientedBox2d b)\n            => new OrientedBox2f(b);\n\n        #endregion\n\n        #region Properties\n\n        public readonly Box2f AxisAlignedBox => Box.Transformed((M33f)Trafo);\n\n        public readonly V2f[] Corners\n        {\n            get\n            {\n                var m = (M33f)Trafo;\n                return Box.ComputeCorners().Map(p => m.TransformPos(p));\n            }\n        }\n\n        public readonly V2f[] CornersCCW\n        {\n            get\n            {\n                var m = (M33f)Trafo;\n                return Box.ComputeCornersCCW().Map(p => m.TransformPos(p));\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region OrientedBox3f\n\n    [DataContract]\n    public struct OrientedBox3f\n    {\n        [DataMember]\n        public Box3f Box;\n        [DataMember]\n        public Euclidean3f Trafo;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3f(OrientedBox3d box)\n        {\n            Box = (Box3f)box.Box;\n            Trafo = (Euclidean3f)box.Trafo;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3f(Box3f box)\n        {\n            Box = box;\n            Trafo = Euclidean3f.Identity;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3f(Box3f box, Rot3f rot)\n        {\n            Box = box;\n            Trafo = new Euclidean3f(rot, V3f.Zero);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3f(Box3f box, V3f trans)\n        {\n            Box = box;\n            Trafo = new Euclidean3f(Rot3f.Identity, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3f(Box3f box, Rot3f rot, V3f trans)\n        {\n            Box = box;\n            Trafo = new Euclidean3f(rot, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3f(Box3f box, Euclidean3f trafo)\n        {\n            Box = box;\n            Trafo = trafo;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator OrientedBox3f(OrientedBox3d b)\n            => new OrientedBox3f(b);\n\n        #endregion\n\n        #region Properties\n\n        public readonly Box3f AxisAlignedBox => Box.Transformed((M44f)Trafo);\n\n        public readonly V3f[] Corners\n        {\n            get\n            {\n                var m = (M44f)Trafo;\n                return Box.ComputeCorners().Map(p => m.TransformPos(p));\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region OrientedBox2d\n\n    [DataContract]\n    public struct OrientedBox2d\n    {\n        [DataMember]\n        public Box2d Box;\n        [DataMember]\n        public Euclidean2d Trafo;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2d(OrientedBox2f box)\n        {\n            Box = (Box2d)box.Box;\n            Trafo = (Euclidean2d)box.Trafo;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2d(Box2d box)\n        {\n            Box = box;\n            Trafo = Euclidean2d.Identity;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2d(Box2d box, Rot2d rot)\n        {\n            Box = box;\n            Trafo = new Euclidean2d(rot, V2d.Zero);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2d(Box2d box, V2d trans)\n        {\n            Box = box;\n            Trafo = new Euclidean2d(Rot2d.Identity, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2d(Box2d box, Rot2d rot, V2d trans)\n        {\n            Box = box;\n            Trafo = new Euclidean2d(rot, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox2d(Box2d box, Euclidean2d trafo)\n        {\n            Box = box;\n            Trafo = trafo;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator OrientedBox2d(OrientedBox2f b)\n            => new OrientedBox2d(b);\n\n        #endregion\n\n        #region Properties\n\n        public readonly Box2d AxisAlignedBox => Box.Transformed((M33d)Trafo);\n\n        public readonly V2d[] Corners\n        {\n            get\n            {\n                var m = (M33d)Trafo;\n                return Box.ComputeCorners().Map(p => m.TransformPos(p));\n            }\n        }\n\n        public readonly V2d[] CornersCCW\n        {\n            get\n            {\n                var m = (M33d)Trafo;\n                return Box.ComputeCornersCCW().Map(p => m.TransformPos(p));\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region OrientedBox3d\n\n    [DataContract]\n    public struct OrientedBox3d\n    {\n        [DataMember]\n        public Box3d Box;\n        [DataMember]\n        public Euclidean3d Trafo;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3d(OrientedBox3f box)\n        {\n            Box = (Box3d)box.Box;\n            Trafo = (Euclidean3d)box.Trafo;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3d(Box3d box)\n        {\n            Box = box;\n            Trafo = Euclidean3d.Identity;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3d(Box3d box, Rot3d rot)\n        {\n            Box = box;\n            Trafo = new Euclidean3d(rot, V3d.Zero);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3d(Box3d box, V3d trans)\n        {\n            Box = box;\n            Trafo = new Euclidean3d(Rot3d.Identity, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3d(Box3d box, Rot3d rot, V3d trans)\n        {\n            Box = box;\n            Trafo = new Euclidean3d(rot, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public OrientedBox3d(Box3d box, Euclidean3d trafo)\n        {\n            Box = box;\n            Trafo = trafo;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator OrientedBox3d(OrientedBox3f b)\n            => new OrientedBox3d(b);\n\n        #endregion\n\n        #region Properties\n\n        public readonly Box3d AxisAlignedBox => Box.Transformed((M44d)Trafo);\n\n        public readonly V3d[] Corners\n        {\n            get\n            {\n                var m = (M44d)Trafo;\n                return Box.ComputeCorners().Map(p => m.TransformPos(p));\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/RangesBoxes/OrientedBox_template.cs",
    "content": "﻿using System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var isDouble in new[] { false, true }) {\n    //# for (int n = 2; n <= 3; n++) {\n    //#   var m = n + 1;\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"OrientedBox\" + n + tc;\n    //#   var type2 = \"OrientedBox\"+ n + tc2;\n    //#   var vnt = \"V\" + n + tc;\n    //#   var boxnt = \"Box\" + n + tc;\n    //#   var rotnt = \"Rot\" + n + tc;\n    //#   var euclideannt = \"Euclidean\" + n + tc;\n    //#   var mmmt = \"M\" + m + m + tc;\n    #region __type__\n\n    [DataContract]\n    public struct __type__\n    {\n        [DataMember]\n        public __boxnt__ Box;\n        [DataMember]\n        public __euclideannt__ Trafo;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ box)\n        {\n            Box = (__boxnt__)box.Box;\n            Trafo = (__euclideannt__)box.Trafo;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__boxnt__ box)\n        {\n            Box = box;\n            Trafo = __euclideannt__.Identity;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__boxnt__ box, __rotnt__ rot)\n        {\n            Box = box;\n            Trafo = new __euclideannt__(rot, __vnt__.Zero);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__boxnt__ box, __vnt__ trans)\n        {\n            Box = box;\n            Trafo = new __euclideannt__(__rotnt__.Identity, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__boxnt__ box, __rotnt__ rot, __vnt__ trans)\n        {\n            Box = box;\n            Trafo = new __euclideannt__(rot, trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__boxnt__ box, __euclideannt__ trafo)\n        {\n            Box = box;\n            Trafo = trafo;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type__(__type2__ b)\n            => new __type__(b);\n\n        #endregion\n\n        #region Properties\n\n        public readonly __boxnt__ AxisAlignedBox => Box.Transformed((__mmmt__)Trafo);\n\n        public readonly __vnt__[] Corners\n        {\n            get\n            {\n                var m = (__mmmt__)Trafo;\n                return Box.ComputeCorners().Map(p => m.TransformPos(p));\n            }\n        }\n        //# if (n == 2) {\n\n        public readonly __vnt__[] CornersCCW\n        {\n            get\n            {\n                var m = (__mmmt__)Trafo;\n                return Box.ComputeCornersCCW().Map(p => m.TransformPos(p));\n            }\n        }\n        //# }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Affine_auto.cs",
    "content": "using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    #region Affine2f\n\n    /// <summary>\n    /// Struct to represent an affine transformation in 2-dimensional space. It consists of\n    /// a linear tranformation (invertible 2x2 matrix) and a translational component (2d vector).\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Affine2f : IEquatable<Affine2f>, IValidity\n    {\n        [DataMember]\n        public M22f Linear;\n        [DataMember]\n        public V2f Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2f(Affine2f affine)\n        {\n            Linear = affine.Linear;\n            Trans = affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Affine2f\"/> transformation from a <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2f(Affine2d affine)\n        {\n            Linear = (M22f)affine.Linear;\n            Trans = (V2f)affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2f(M22f linear, V2f translation)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = translation;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2f(M22f linear, float tX, float tY)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = new V2f(tX, tY);\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2f(M22f linear)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = V2f.Zero;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Affine2f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Affine2f(M22f.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets if this affine transformation is valid, i.e. if the linear map is invertible.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Linear.Invertible;\n        }\n\n        /// <summary>\n        /// Gets if this affine transformation is invalid, i.e. if the linear map is singular.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !IsValid;\n        }\n\n        /// <summary>\n        /// Gets the inverse of this affine transformation.\n        /// </summary>\n        public readonly Affine2f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new Affine2f(this);\n                rs.Invert();\n                return rs;\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two affine transformations.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Affine2f a, Affine2f b)\n        {\n            return new Affine2f(a.Linear * b.Linear, a.Linear * b.Trans + a.Trans);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by an affine transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(Affine2f a, V3f v)\n        {\n            return new V3f(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Trans.X * v.Z, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Trans.Y * v.Z,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2f\"/> (as a 3x3 matrix) and a <see cref=\"M33f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(Affine2f a, M33f m)\n        {\n            return new M33f(\n                a.Linear.M00 * m.M00 + a.Linear.M01 * m.M10 + a.Trans.X * m.M20, \n                a.Linear.M00 * m.M01 + a.Linear.M01 * m.M11 + a.Trans.X * m.M21, \n                a.Linear.M00 * m.M02 + a.Linear.M01 * m.M12 + a.Trans.X * m.M22,\n\n                a.Linear.M10 * m.M00 + a.Linear.M11 * m.M10 + a.Trans.Y * m.M20, \n                a.Linear.M10 * m.M01 + a.Linear.M11 * m.M11 + a.Trans.Y * m.M21, \n                a.Linear.M10 * m.M02 + a.Linear.M11 * m.M12 + a.Trans.Y * m.M22,\n\n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> and a <see cref=\"Affine2f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(M33f m, Affine2f a)\n        {\n            return new M33f(\n                m.M00 * a.Linear.M00 + m.M01 * a.Linear.M10, \n                m.M00 * a.Linear.M01 + m.M01 * a.Linear.M11,\n                m.M00 * a.Trans.X + m.M01 * a.Trans.Y + m.M02,\n\n                m.M10 * a.Linear.M00 + m.M11 * a.Linear.M10, \n                m.M10 * a.Linear.M01 + m.M11 * a.Linear.M11,\n                m.M10 * a.Trans.X + m.M11 * a.Trans.Y + m.M12,\n\n                m.M20 * a.Linear.M00 + m.M21 * a.Linear.M10, \n                m.M20 * a.Linear.M01 + m.M21 * a.Linear.M11,\n                m.M20 * a.Trans.X + m.M21 * a.Trans.Y + m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2f\"/> (as a 2x3 matrix) and a <see cref=\"M22f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Affine2f a, M22f m)\n            => new M23f(a.Linear * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22f\"/> and a <see cref=\"Affine2f\"/> (as a 2x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M22f m, Affine2f a)\n            => new M23f(m * a.Linear, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2f\"/> (as a 2x3 matrix) and a <see cref=\"M23f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Affine2f a, M23f m)\n        {\n            return new M23f(\n                a.Linear.M00 * m.M00 + a.Linear.M01 * m.M10, \n                a.Linear.M00 * m.M01 + a.Linear.M01 * m.M11,\n                a.Trans.X + a.Linear.M00 * m.M02 + a.Linear.M01 * m.M12,\n\n                a.Linear.M10 * m.M00 + a.Linear.M11 * m.M10, \n                a.Linear.M10 * m.M01 + a.Linear.M11 * m.M11,\n                a.Trans.Y + a.Linear.M10 * m.M02 + a.Linear.M11 * m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23f\"/> and a <see cref=\"Affine2f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M23f m, Affine2f a)\n        {\n            return new M23f(\n                m.M00 * a.Linear.M00 + m.M01 * a.Linear.M10, \n                m.M00 * a.Linear.M01 + m.M01 * a.Linear.M11,\n                m.M00 * a.Trans.X + m.M01 * a.Trans.Y + m.M02,\n\n                m.M10 * a.Linear.M00 + m.M11 * a.Linear.M10, \n                m.M10 * a.Linear.M01 + m.M11 * a.Linear.M11,\n                m.M10 * a.Trans.X + m.M11 * a.Trans.Y + m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2f\"/> and a <see cref=\"Euclidean2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Affine2f a, Euclidean2f e)\n            => a * (Affine2f)e;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2f\"/> and a <see cref=\"Affine2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Euclidean2f e, Affine2f a)\n            => (Affine2f)e * a;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2f\"/> and a <see cref=\"Rot2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Affine2f a, Rot2f r)\n            => new Affine2f(a.Linear * r, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> and a <see cref=\"Affine2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Rot2f r, Affine2f a)\n            => new Affine2f(r * a.Linear, r * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2f\"/> and a <see cref=\"Scale2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Affine2f a, Scale2f s)\n        {\n            return new Affine2f(new M22f(\n                a.Linear.M00 * s.X, a.Linear.M01 * s.Y, \n                a.Linear.M10 * s.X, a.Linear.M11 * s.Y),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> and a <see cref=\"Affine2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Scale2f s, Affine2f a)\n        {\n            return new Affine2f(new M22f(\n                a.Linear.M00 * s.X, a.Linear.M01 * s.X, \n                a.Linear.M10 * s.Y, a.Linear.M11 * s.Y),\n                a.Trans * s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2f\"/> and a <see cref=\"Shift2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Affine2f a, Shift2f s)\n        {\n            return new Affine2f(a.Linear, a.Linear * s.V + a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> and a <see cref=\"Affine2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Shift2f s, Affine2f a)\n        {\n            return new Affine2f(a.Linear, a.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2f\"/> and a <see cref=\"Similarity2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Affine2f a, Similarity2f s)\n            => a * (Affine2f)s;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2f\"/> and a <see cref=\"Affine2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Similarity2f s, Affine2f a)\n            => (Affine2f)s * a;\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Affine2f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Affine2f a0, Affine2f a1)\n            => (a0.Linear == a1.Linear) && (a0.Trans == a1.Trans);\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Affine2f\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Affine2f a0, Affine2f a1)\n            => (a0.Linear != a1.Linear) || (a0.Trans != a1.Trans);\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates an affine transformation from a 2x3 matrix.\n        /// The left 2x2 submatrix of <paramref name=\"matrix\"/> must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f FromM23f(M23f matrix, float epsilon = 1e-5f)\n        {\n            var linear = (M22f)matrix;\n            var trans = new V2f(matrix.M02, matrix.M12);\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new Affine2f(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a 3x3 matrix.\n        /// The matrix <paramref name=\"m\"/> has to be homogeneous and must not contain perspective components and its upper left 2x2 submatrix must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f FromM33f(M33f m, float epsilon = 1e-5f)\n        {\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            var linear = ((M22f)m) / m.M22;\n            var trans = new V2f(m.M02, m.M12) / m.M22;\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new Affine2f(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a <see cref=\"Trafo2f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must represent a valid affine transformation (e.g. it does not contain perspective components).\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f FromTrafo2f(Trafo2f trafo, float epsilon = 1e-5f)\n            => FromM33f(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine2f\"/> transformation with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Translation(float tX, float tY)\n            => new Affine2f(M22f.Identity, tX, tY);\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine2f\"/> transformation with the translational component given by a <see cref=\"V2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Translation(V2f vector)\n            => new Affine2f(M22f.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine2f\"/> transformation with the translational component given by a <see cref=\"Shift2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Translation(Shift2f shift)\n            => new Affine2f(M22f.Identity, shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Scale(float scaleFactor)\n            => new Affine2f(M22f.Scale(scaleFactor, scaleFactor));\n\n        /// <summary>\n        /// Creates a scaling transformation using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Scale(float sX, float sY)\n            => new Affine2f(M22f.Scale(sX, sY));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"V2f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Scale(V2f scaleFactors)\n            => new Affine2f(M22f.Scale(scaleFactors));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"Scale2f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Scale(Scale2f scale)\n            => new Affine2f(M22f.Scale(scale));\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Rotation(Rot2f rot)\n            => new Affine2f(M22f.Rotation(rot));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Rotation(float angleInRadians)\n            => new Affine2f(M22f.Rotation(angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f RotationInDegrees(float angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23f(Affine2f a)\n            => new M23f(a.Linear, a.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22f(Affine2f a)\n            => a.Linear;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Affine2f a)\n            => new M33f((M23f)a);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2f(Affine2f a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            var t = (M33f)a;\n            return new Trafo2f(t, t.Inverse);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2d(Affine2f a)\n            => new Affine2d((M22d)a.Linear, (V2d)a.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Linear, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Affine2f other)\n            => Linear.Equals(other.Linear) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is Affine2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Linear, Trans);\n        }\n\n        public static Affine2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Affine2f(M22f.Parse(x[0]), V2f.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Affine\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of an <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f Inverse(Affine2f a)\n            => a.Inverse;\n\n        /// <summary>\n        /// Inverts the given affine transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Affine2f a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            a.Linear.Invert();\n            a.Trans = -a.Linear * a.Trans;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> by an <see cref=\"Affine2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Affine2f a, V3f v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> position vector (v.Z is presumed 1) by an <see cref=\"Affine2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformPos(this Affine2f a, V2f v)\n        {\n            return new V2f(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Trans.X, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Trans.Y);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> direction vector (v.Z is presumed 0) by an <see cref=\"Affine2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformDir(this Affine2f a, V2f v)\n        {\n            return new V2f(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> by the transpose of an <see cref=\"Affine2f\"/> (as a 3x3 matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransposedTransform(this Affine2f a, V3f v)\n        {\n            return new V3f(\n                v.X * a.Linear.M00 + v.Y * a.Linear.M10, \n                v.X * a.Linear.M01 + v.Y * a.Linear.M11,\n                v.X * a.Trans.X + v.Y * a.Trans.Y + v.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> by the transpose of an <see cref=\"Affine2f\"/> (as a 3x3 matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransposedTransform(this Affine2f a, V2f v)\n        {\n            return new V2f(\n                v.X * a.Linear.M00 + v.Y * a.Linear.M10, \n                v.X * a.Linear.M01 + v.Y * a.Linear.M11);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> position vector (v.Z is presumed 1) by the transpose of an <see cref=\"Affine2f\"/> (as a 3x3 matrix).\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransposedTransformPosProj(this Affine2f a, V2f v)\n        {\n            var s = v.X * a.Trans.X + v.Y * a.Trans.Y + 1;\n            return TransposedTransform(a, v) * (1 / s);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Affine2f a0, Affine2f a1)\n        {\n            return ApproximateEquals(a0, a1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Affine2f a0, Affine2f a1, float tolerance)\n        {\n            return ApproximateEquals(a0.Linear, a1.Linear, tolerance) && ApproximateEquals(a0.Trans, a1.Trans, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Affine3f\n\n    /// <summary>\n    /// Struct to represent an affine transformation in 3-dimensional space. It consists of\n    /// a linear tranformation (invertible 3x3 matrix) and a translational component (3d vector).\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Affine3f : IEquatable<Affine3f>, IValidity\n    {\n        [DataMember]\n        public M33f Linear;\n        [DataMember]\n        public V3f Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3f(Affine3f affine)\n        {\n            Linear = affine.Linear;\n            Trans = affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Affine3f\"/> transformation from a <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3f(Affine3d affine)\n        {\n            Linear = (M33f)affine.Linear;\n            Trans = (V3f)affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3f(M33f linear, V3f translation)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = translation;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3f(M33f linear, float tX, float tY, float tZ)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = new V3f(tX, tY, tZ);\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3f(M33f linear)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = V3f.Zero;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Affine3f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Affine3f(M33f.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets if this affine transformation is valid, i.e. if the linear map is invertible.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Linear.Invertible;\n        }\n\n        /// <summary>\n        /// Gets if this affine transformation is invalid, i.e. if the linear map is singular.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !IsValid;\n        }\n\n        /// <summary>\n        /// Gets the inverse of this affine transformation.\n        /// </summary>\n        public readonly Affine3f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new Affine3f(this);\n                rs.Invert();\n                return rs;\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two affine transformations.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Affine3f a, Affine3f b)\n        {\n            return new Affine3f(a.Linear * b.Linear, a.Linear * b.Trans + a.Trans);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by an affine transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(Affine3f a, V4f v)\n        {\n            return new V4f(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Linear.M02 * v.Z + a.Trans.X * v.W, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Linear.M12 * v.Z + a.Trans.Y * v.W, \n                a.Linear.M20 * v.X + a.Linear.M21 * v.Y + a.Linear.M22 * v.Z + a.Trans.Z * v.W,\n                v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3f\"/> (as a 4x4 matrix) and a <see cref=\"M44f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(Affine3f a, M44f m)\n        {\n            return new M44f(\n                a.Linear.M00 * m.M00 + a.Linear.M01 * m.M10 + a.Linear.M02 * m.M20 + a.Trans.X * m.M30, \n                a.Linear.M00 * m.M01 + a.Linear.M01 * m.M11 + a.Linear.M02 * m.M21 + a.Trans.X * m.M31, \n                a.Linear.M00 * m.M02 + a.Linear.M01 * m.M12 + a.Linear.M02 * m.M22 + a.Trans.X * m.M32, \n                a.Linear.M00 * m.M03 + a.Linear.M01 * m.M13 + a.Linear.M02 * m.M23 + a.Trans.X * m.M33,\n\n                a.Linear.M10 * m.M00 + a.Linear.M11 * m.M10 + a.Linear.M12 * m.M20 + a.Trans.Y * m.M30, \n                a.Linear.M10 * m.M01 + a.Linear.M11 * m.M11 + a.Linear.M12 * m.M21 + a.Trans.Y * m.M31, \n                a.Linear.M10 * m.M02 + a.Linear.M11 * m.M12 + a.Linear.M12 * m.M22 + a.Trans.Y * m.M32, \n                a.Linear.M10 * m.M03 + a.Linear.M11 * m.M13 + a.Linear.M12 * m.M23 + a.Trans.Y * m.M33,\n\n                a.Linear.M20 * m.M00 + a.Linear.M21 * m.M10 + a.Linear.M22 * m.M20 + a.Trans.Z * m.M30, \n                a.Linear.M20 * m.M01 + a.Linear.M21 * m.M11 + a.Linear.M22 * m.M21 + a.Trans.Z * m.M31, \n                a.Linear.M20 * m.M02 + a.Linear.M21 * m.M12 + a.Linear.M22 * m.M22 + a.Trans.Z * m.M32, \n                a.Linear.M20 * m.M03 + a.Linear.M21 * m.M13 + a.Linear.M22 * m.M23 + a.Trans.Z * m.M33,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44f\"/> and a <see cref=\"Affine3f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(M44f m, Affine3f a)\n        {\n            return new M44f(\n                m.M00 * a.Linear.M00 + m.M01 * a.Linear.M10 + m.M02 * a.Linear.M20, \n                m.M00 * a.Linear.M01 + m.M01 * a.Linear.M11 + m.M02 * a.Linear.M21, \n                m.M00 * a.Linear.M02 + m.M01 * a.Linear.M12 + m.M02 * a.Linear.M22,\n                m.M00 * a.Trans.X + m.M01 * a.Trans.Y + m.M02 * a.Trans.Z + m.M03,\n\n                m.M10 * a.Linear.M00 + m.M11 * a.Linear.M10 + m.M12 * a.Linear.M20, \n                m.M10 * a.Linear.M01 + m.M11 * a.Linear.M11 + m.M12 * a.Linear.M21, \n                m.M10 * a.Linear.M02 + m.M11 * a.Linear.M12 + m.M12 * a.Linear.M22,\n                m.M10 * a.Trans.X + m.M11 * a.Trans.Y + m.M12 * a.Trans.Z + m.M13,\n\n                m.M20 * a.Linear.M00 + m.M21 * a.Linear.M10 + m.M22 * a.Linear.M20, \n                m.M20 * a.Linear.M01 + m.M21 * a.Linear.M11 + m.M22 * a.Linear.M21, \n                m.M20 * a.Linear.M02 + m.M21 * a.Linear.M12 + m.M22 * a.Linear.M22,\n                m.M20 * a.Trans.X + m.M21 * a.Trans.Y + m.M22 * a.Trans.Z + m.M23,\n\n                m.M30 * a.Linear.M00 + m.M31 * a.Linear.M10 + m.M32 * a.Linear.M20, \n                m.M30 * a.Linear.M01 + m.M31 * a.Linear.M11 + m.M32 * a.Linear.M21, \n                m.M30 * a.Linear.M02 + m.M31 * a.Linear.M12 + m.M32 * a.Linear.M22,\n                m.M30 * a.Trans.X + m.M31 * a.Trans.Y + m.M32 * a.Trans.Z + m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3f\"/> (as a 3x4 matrix) and a <see cref=\"M33f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Affine3f a, M33f m)\n            => new M34f(a.Linear * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> and a <see cref=\"Affine3f\"/> (as a 3x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M33f m, Affine3f a)\n            => new M34f(m * a.Linear, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3f\"/> (as a 3x4 matrix) and a <see cref=\"M34f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Affine3f a, M34f m)\n        {\n            return new M34f(\n                a.Linear.M00 * m.M00 + a.Linear.M01 * m.M10 + a.Linear.M02 * m.M20, \n                a.Linear.M00 * m.M01 + a.Linear.M01 * m.M11 + a.Linear.M02 * m.M21, \n                a.Linear.M00 * m.M02 + a.Linear.M01 * m.M12 + a.Linear.M02 * m.M22,\n                a.Trans.X + a.Linear.M00 * m.M03 + a.Linear.M01 * m.M13 + a.Linear.M02 * m.M23,\n\n                a.Linear.M10 * m.M00 + a.Linear.M11 * m.M10 + a.Linear.M12 * m.M20, \n                a.Linear.M10 * m.M01 + a.Linear.M11 * m.M11 + a.Linear.M12 * m.M21, \n                a.Linear.M10 * m.M02 + a.Linear.M11 * m.M12 + a.Linear.M12 * m.M22,\n                a.Trans.Y + a.Linear.M10 * m.M03 + a.Linear.M11 * m.M13 + a.Linear.M12 * m.M23,\n\n                a.Linear.M20 * m.M00 + a.Linear.M21 * m.M10 + a.Linear.M22 * m.M20, \n                a.Linear.M20 * m.M01 + a.Linear.M21 * m.M11 + a.Linear.M22 * m.M21, \n                a.Linear.M20 * m.M02 + a.Linear.M21 * m.M12 + a.Linear.M22 * m.M22,\n                a.Trans.Z + a.Linear.M20 * m.M03 + a.Linear.M21 * m.M13 + a.Linear.M22 * m.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34f\"/> and a <see cref=\"Affine3f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M34f m, Affine3f a)\n        {\n            return new M34f(\n                m.M00 * a.Linear.M00 + m.M01 * a.Linear.M10 + m.M02 * a.Linear.M20, \n                m.M00 * a.Linear.M01 + m.M01 * a.Linear.M11 + m.M02 * a.Linear.M21, \n                m.M00 * a.Linear.M02 + m.M01 * a.Linear.M12 + m.M02 * a.Linear.M22,\n                m.M00 * a.Trans.X + m.M01 * a.Trans.Y + m.M02 * a.Trans.Z + m.M03,\n\n                m.M10 * a.Linear.M00 + m.M11 * a.Linear.M10 + m.M12 * a.Linear.M20, \n                m.M10 * a.Linear.M01 + m.M11 * a.Linear.M11 + m.M12 * a.Linear.M21, \n                m.M10 * a.Linear.M02 + m.M11 * a.Linear.M12 + m.M12 * a.Linear.M22,\n                m.M10 * a.Trans.X + m.M11 * a.Trans.Y + m.M12 * a.Trans.Z + m.M13,\n\n                m.M20 * a.Linear.M00 + m.M21 * a.Linear.M10 + m.M22 * a.Linear.M20, \n                m.M20 * a.Linear.M01 + m.M21 * a.Linear.M11 + m.M22 * a.Linear.M21, \n                m.M20 * a.Linear.M02 + m.M21 * a.Linear.M12 + m.M22 * a.Linear.M22,\n                m.M20 * a.Trans.X + m.M21 * a.Trans.Y + m.M22 * a.Trans.Z + m.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3f\"/> and a <see cref=\"Euclidean3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Affine3f a, Euclidean3f e)\n            => a * (Affine3f)e;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3f\"/> and a <see cref=\"Affine3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Euclidean3f e, Affine3f a)\n            => (Affine3f)e * a;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3f\"/> and a <see cref=\"Rot3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Affine3f a, Rot3f r)\n            => new Affine3f(a.Linear * r, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> and a <see cref=\"Affine3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Rot3f r, Affine3f a)\n            => new Affine3f(r * a.Linear, r * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3f\"/> and a <see cref=\"Scale3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Affine3f a, Scale3f s)\n        {\n            return new Affine3f(new M33f(\n                a.Linear.M00 * s.X, a.Linear.M01 * s.Y, a.Linear.M02 * s.Z, \n                a.Linear.M10 * s.X, a.Linear.M11 * s.Y, a.Linear.M12 * s.Z, \n                a.Linear.M20 * s.X, a.Linear.M21 * s.Y, a.Linear.M22 * s.Z),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> and a <see cref=\"Affine3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Scale3f s, Affine3f a)\n        {\n            return new Affine3f(new M33f(\n                a.Linear.M00 * s.X, a.Linear.M01 * s.X, a.Linear.M02 * s.X, \n                a.Linear.M10 * s.Y, a.Linear.M11 * s.Y, a.Linear.M12 * s.Y, \n                a.Linear.M20 * s.Z, a.Linear.M21 * s.Z, a.Linear.M22 * s.Z),\n                a.Trans * s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3f\"/> and a <see cref=\"Shift3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Affine3f a, Shift3f s)\n        {\n            return new Affine3f(a.Linear, a.Linear * s.V + a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> and a <see cref=\"Affine3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Shift3f s, Affine3f a)\n        {\n            return new Affine3f(a.Linear, a.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3f\"/> and a <see cref=\"Similarity3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Affine3f a, Similarity3f s)\n            => a * (Affine3f)s;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3f\"/> and a <see cref=\"Affine3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Similarity3f s, Affine3f a)\n            => (Affine3f)s * a;\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Affine3f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Affine3f a0, Affine3f a1)\n            => (a0.Linear == a1.Linear) && (a0.Trans == a1.Trans);\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Affine3f\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Affine3f a0, Affine3f a1)\n            => (a0.Linear != a1.Linear) || (a0.Trans != a1.Trans);\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates an affine transformation from a 3x4 matrix.\n        /// The left 3x3 submatrix of <paramref name=\"matrix\"/> must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f FromM34f(M34f matrix, float epsilon = 1e-5f)\n        {\n            var linear = (M33f)matrix;\n            var trans = new V3f(matrix.M03, matrix.M13, matrix.M23);\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new Affine3f(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a 4x4 matrix.\n        /// The matrix <paramref name=\"m\"/> has to be homogeneous and must not contain perspective components and its upper left 3x3 submatrix must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f FromM44f(M44f m, float epsilon = 1e-5f)\n        {\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            var linear = ((M33f)m) / m.M33;\n            var trans = new V3f(m.M03, m.M13, m.M23) / m.M33;\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new Affine3f(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a <see cref=\"Trafo3f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must represent a valid affine transformation (e.g. it does not contain perspective components).\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f FromTrafo3f(Trafo3f trafo, float epsilon = 1e-5f)\n            => FromM44f(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine3f\"/> transformation with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Translation(float tX, float tY, float tZ)\n            => new Affine3f(M33f.Identity, tX, tY, tZ);\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine3f\"/> transformation with the translational component given by a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Translation(V3f vector)\n            => new Affine3f(M33f.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine3f\"/> transformation with the translational component given by a <see cref=\"Shift3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Translation(Shift3f shift)\n            => new Affine3f(M33f.Identity, shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Scale(float scaleFactor)\n            => new Affine3f(M33f.Scale(scaleFactor, scaleFactor, scaleFactor));\n\n        /// <summary>\n        /// Creates a scaling transformation using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Scale(float sX, float sY, float sZ)\n            => new Affine3f(M33f.Scale(sX, sY, sZ));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"V3f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Scale(V3f scaleFactors)\n            => new Affine3f(M33f.Scale(scaleFactors));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"Scale3f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Scale(Scale3f scale)\n            => new Affine3f(M33f.Scale(scale));\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Rotation(Rot3f rot)\n            => new Affine3f(M33f.Rotation(rot));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Rotation(V3f normalizedAxis, float angleRadians)\n            => new Affine3f(M33f.Rotation(normalizedAxis, angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationInDegrees(V3f normalizedAxis, float angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationEuler(float rollInRadians, float pitchInRadians, float yawInRadians)\n            => new Affine3f(M33f.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationEulerInDegrees(float rollInDegrees, float pitchInDegrees, float yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationEuler(V3f rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationEulerInDegrees(V3f rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotateInto(V3f from, V3f into)\n            => new Affine3f(M33f.RotateInto(from, into));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationX(float angleRadians)\n            => new Affine3f(M33f.RotationX(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationXInDegrees(float angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationY(float angleRadians)\n            => new Affine3f(M33f.RotationY(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationYInDegrees(float angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationZ(float angleRadians)\n            => new Affine3f(M33f.RotationZ(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f RotationZInDegrees(float angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Shear\n\n        /// <summary>\n        /// Creates a shear transformation along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f ShearXY(float factorX, float factorY)\n            => new Affine3f(M33f.ShearXY(factorX, factorY));\n\n        /// <summary>\n        /// Creates a shear transformation along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f ShearXZ(float factorX, float factorZ)\n            => new Affine3f(M33f.ShearXZ(factorX, factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f ShearYZ(float factorY, float factorZ)\n            => new Affine3f(M33f.ShearYZ(factorY, factorZ));\n\n        #endregion\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Affine3f a)\n            => new M34f(a.Linear, a.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Affine3f a)\n            => a.Linear;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Affine3f a)\n            => new M44f((M34f)a);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3f(Affine3f a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            var t = (M44f)a;\n            return new Trafo3f(t, t.Inverse);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3d(Affine3f a)\n            => new Affine3d((M33d)a.Linear, (V3d)a.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Linear, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Affine3f other)\n            => Linear.Equals(other.Linear) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is Affine3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Linear, Trans);\n        }\n\n        public static Affine3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Affine3f(M33f.Parse(x[0]), V3f.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Affine\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of an <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f Inverse(Affine3f a)\n            => a.Inverse;\n\n        /// <summary>\n        /// Inverts the given affine transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Affine3f a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            a.Linear.Invert();\n            a.Trans = -a.Linear * a.Trans;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> by an <see cref=\"Affine3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Affine3f a, V4f v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> position vector (v.W is presumed 1) by an <see cref=\"Affine3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformPos(this Affine3f a, V3f v)\n        {\n            return new V3f(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Linear.M02 * v.Z + a.Trans.X, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Linear.M12 * v.Z + a.Trans.Y, \n                a.Linear.M20 * v.X + a.Linear.M21 * v.Y + a.Linear.M22 * v.Z + a.Trans.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> direction vector (v.W is presumed 0) by an <see cref=\"Affine3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformDir(this Affine3f a, V3f v)\n        {\n            return new V3f(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Linear.M02 * v.Z, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Linear.M12 * v.Z, \n                a.Linear.M20 * v.X + a.Linear.M21 * v.Y + a.Linear.M22 * v.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> by the transpose of an <see cref=\"Affine3f\"/> (as a 4x4 matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f TransposedTransform(this Affine3f a, V4f v)\n        {\n            return new V4f(\n                v.X * a.Linear.M00 + v.Y * a.Linear.M10 + v.Z * a.Linear.M20, \n                v.X * a.Linear.M01 + v.Y * a.Linear.M11 + v.Z * a.Linear.M21, \n                v.X * a.Linear.M02 + v.Y * a.Linear.M12 + v.Z * a.Linear.M22,\n                v.X * a.Trans.X + v.Y * a.Trans.Y + v.Z * a.Trans.Z + v.W);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> by the transpose of an <see cref=\"Affine3f\"/> (as a 4x4 matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransposedTransform(this Affine3f a, V3f v)\n        {\n            return new V3f(\n                v.X * a.Linear.M00 + v.Y * a.Linear.M10 + v.Z * a.Linear.M20, \n                v.X * a.Linear.M01 + v.Y * a.Linear.M11 + v.Z * a.Linear.M21, \n                v.X * a.Linear.M02 + v.Y * a.Linear.M12 + v.Z * a.Linear.M22);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> position vector (v.W is presumed 1) by the transpose of an <see cref=\"Affine3f\"/> (as a 4x4 matrix).\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransposedTransformPosProj(this Affine3f a, V3f v)\n        {\n            var s = v.X * a.Trans.X + v.Y * a.Trans.Y + v.Z * a.Trans.Z + 1;\n            return TransposedTransform(a, v) * (1 / s);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Affine3f a0, Affine3f a1)\n        {\n            return ApproximateEquals(a0, a1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Affine3f a0, Affine3f a1, float tolerance)\n        {\n            return ApproximateEquals(a0.Linear, a1.Linear, tolerance) && ApproximateEquals(a0.Trans, a1.Trans, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Affine2d\n\n    /// <summary>\n    /// Struct to represent an affine transformation in 2-dimensional space. It consists of\n    /// a linear tranformation (invertible 2x2 matrix) and a translational component (2d vector).\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Affine2d : IEquatable<Affine2d>, IValidity\n    {\n        [DataMember]\n        public M22d Linear;\n        [DataMember]\n        public V2d Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2d(Affine2d affine)\n        {\n            Linear = affine.Linear;\n            Trans = affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Affine2d\"/> transformation from a <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2d(Affine2f affine)\n        {\n            Linear = (M22d)affine.Linear;\n            Trans = (V2d)affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2d(M22d linear, V2d translation)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = translation;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2d(M22d linear, double tX, double tY)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = new V2d(tX, tY);\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine2d(M22d linear)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = V2d.Zero;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Affine2d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Affine2d(M22d.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets if this affine transformation is valid, i.e. if the linear map is invertible.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Linear.Invertible;\n        }\n\n        /// <summary>\n        /// Gets if this affine transformation is invalid, i.e. if the linear map is singular.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !IsValid;\n        }\n\n        /// <summary>\n        /// Gets the inverse of this affine transformation.\n        /// </summary>\n        public readonly Affine2d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new Affine2d(this);\n                rs.Invert();\n                return rs;\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two affine transformations.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Affine2d a, Affine2d b)\n        {\n            return new Affine2d(a.Linear * b.Linear, a.Linear * b.Trans + a.Trans);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by an affine transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(Affine2d a, V3d v)\n        {\n            return new V3d(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Trans.X * v.Z, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Trans.Y * v.Z,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2d\"/> (as a 3x3 matrix) and a <see cref=\"M33d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(Affine2d a, M33d m)\n        {\n            return new M33d(\n                a.Linear.M00 * m.M00 + a.Linear.M01 * m.M10 + a.Trans.X * m.M20, \n                a.Linear.M00 * m.M01 + a.Linear.M01 * m.M11 + a.Trans.X * m.M21, \n                a.Linear.M00 * m.M02 + a.Linear.M01 * m.M12 + a.Trans.X * m.M22,\n\n                a.Linear.M10 * m.M00 + a.Linear.M11 * m.M10 + a.Trans.Y * m.M20, \n                a.Linear.M10 * m.M01 + a.Linear.M11 * m.M11 + a.Trans.Y * m.M21, \n                a.Linear.M10 * m.M02 + a.Linear.M11 * m.M12 + a.Trans.Y * m.M22,\n\n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> and a <see cref=\"Affine2d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(M33d m, Affine2d a)\n        {\n            return new M33d(\n                m.M00 * a.Linear.M00 + m.M01 * a.Linear.M10, \n                m.M00 * a.Linear.M01 + m.M01 * a.Linear.M11,\n                m.M00 * a.Trans.X + m.M01 * a.Trans.Y + m.M02,\n\n                m.M10 * a.Linear.M00 + m.M11 * a.Linear.M10, \n                m.M10 * a.Linear.M01 + m.M11 * a.Linear.M11,\n                m.M10 * a.Trans.X + m.M11 * a.Trans.Y + m.M12,\n\n                m.M20 * a.Linear.M00 + m.M21 * a.Linear.M10, \n                m.M20 * a.Linear.M01 + m.M21 * a.Linear.M11,\n                m.M20 * a.Trans.X + m.M21 * a.Trans.Y + m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2d\"/> (as a 2x3 matrix) and a <see cref=\"M22d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Affine2d a, M22d m)\n            => new M23d(a.Linear * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22d\"/> and a <see cref=\"Affine2d\"/> (as a 2x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M22d m, Affine2d a)\n            => new M23d(m * a.Linear, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2d\"/> (as a 2x3 matrix) and a <see cref=\"M23d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Affine2d a, M23d m)\n        {\n            return new M23d(\n                a.Linear.M00 * m.M00 + a.Linear.M01 * m.M10, \n                a.Linear.M00 * m.M01 + a.Linear.M01 * m.M11,\n                a.Trans.X + a.Linear.M00 * m.M02 + a.Linear.M01 * m.M12,\n\n                a.Linear.M10 * m.M00 + a.Linear.M11 * m.M10, \n                a.Linear.M10 * m.M01 + a.Linear.M11 * m.M11,\n                a.Trans.Y + a.Linear.M10 * m.M02 + a.Linear.M11 * m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23d\"/> and a <see cref=\"Affine2d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M23d m, Affine2d a)\n        {\n            return new M23d(\n                m.M00 * a.Linear.M00 + m.M01 * a.Linear.M10, \n                m.M00 * a.Linear.M01 + m.M01 * a.Linear.M11,\n                m.M00 * a.Trans.X + m.M01 * a.Trans.Y + m.M02,\n\n                m.M10 * a.Linear.M00 + m.M11 * a.Linear.M10, \n                m.M10 * a.Linear.M01 + m.M11 * a.Linear.M11,\n                m.M10 * a.Trans.X + m.M11 * a.Trans.Y + m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2d\"/> and a <see cref=\"Euclidean2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Affine2d a, Euclidean2d e)\n            => a * (Affine2d)e;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2d\"/> and a <see cref=\"Affine2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Euclidean2d e, Affine2d a)\n            => (Affine2d)e * a;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2d\"/> and a <see cref=\"Rot2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Affine2d a, Rot2d r)\n            => new Affine2d(a.Linear * r, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> and a <see cref=\"Affine2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Rot2d r, Affine2d a)\n            => new Affine2d(r * a.Linear, r * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2d\"/> and a <see cref=\"Scale2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Affine2d a, Scale2d s)\n        {\n            return new Affine2d(new M22d(\n                a.Linear.M00 * s.X, a.Linear.M01 * s.Y, \n                a.Linear.M10 * s.X, a.Linear.M11 * s.Y),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> and a <see cref=\"Affine2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Scale2d s, Affine2d a)\n        {\n            return new Affine2d(new M22d(\n                a.Linear.M00 * s.X, a.Linear.M01 * s.X, \n                a.Linear.M10 * s.Y, a.Linear.M11 * s.Y),\n                a.Trans * s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2d\"/> and a <see cref=\"Shift2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Affine2d a, Shift2d s)\n        {\n            return new Affine2d(a.Linear, a.Linear * s.V + a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> and a <see cref=\"Affine2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Shift2d s, Affine2d a)\n        {\n            return new Affine2d(a.Linear, a.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine2d\"/> and a <see cref=\"Similarity2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Affine2d a, Similarity2d s)\n            => a * (Affine2d)s;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2d\"/> and a <see cref=\"Affine2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Similarity2d s, Affine2d a)\n            => (Affine2d)s * a;\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Affine2d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Affine2d a0, Affine2d a1)\n            => (a0.Linear == a1.Linear) && (a0.Trans == a1.Trans);\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Affine2d\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Affine2d a0, Affine2d a1)\n            => (a0.Linear != a1.Linear) || (a0.Trans != a1.Trans);\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates an affine transformation from a 2x3 matrix.\n        /// The left 2x2 submatrix of <paramref name=\"matrix\"/> must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d FromM23d(M23d matrix, double epsilon = 1e-12)\n        {\n            var linear = (M22d)matrix;\n            var trans = new V2d(matrix.M02, matrix.M12);\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new Affine2d(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a 3x3 matrix.\n        /// The matrix <paramref name=\"m\"/> has to be homogeneous and must not contain perspective components and its upper left 2x2 submatrix must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d FromM33d(M33d m, double epsilon = 1e-12)\n        {\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            var linear = ((M22d)m) / m.M22;\n            var trans = new V2d(m.M02, m.M12) / m.M22;\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new Affine2d(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a <see cref=\"Trafo2d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must represent a valid affine transformation (e.g. it does not contain perspective components).\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d FromTrafo2d(Trafo2d trafo, double epsilon = 1e-12)\n            => FromM33d(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine2d\"/> transformation with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Translation(double tX, double tY)\n            => new Affine2d(M22d.Identity, tX, tY);\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine2d\"/> transformation with the translational component given by a <see cref=\"V2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Translation(V2d vector)\n            => new Affine2d(M22d.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine2d\"/> transformation with the translational component given by a <see cref=\"Shift2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Translation(Shift2d shift)\n            => new Affine2d(M22d.Identity, shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Scale(double scaleFactor)\n            => new Affine2d(M22d.Scale(scaleFactor, scaleFactor));\n\n        /// <summary>\n        /// Creates a scaling transformation using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Scale(double sX, double sY)\n            => new Affine2d(M22d.Scale(sX, sY));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"V2d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Scale(V2d scaleFactors)\n            => new Affine2d(M22d.Scale(scaleFactors));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"Scale2d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Scale(Scale2d scale)\n            => new Affine2d(M22d.Scale(scale));\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Rotation(Rot2d rot)\n            => new Affine2d(M22d.Rotation(rot));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Rotation(double angleInRadians)\n            => new Affine2d(M22d.Rotation(angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d RotationInDegrees(double angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23d(Affine2d a)\n            => new M23d(a.Linear, a.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22d(Affine2d a)\n            => a.Linear;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Affine2d a)\n            => new M33d((M23d)a);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2d(Affine2d a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            var t = (M33d)a;\n            return new Trafo2d(t, t.Inverse);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2f(Affine2d a)\n            => new Affine2f((M22f)a.Linear, (V2f)a.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Linear, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Affine2d other)\n            => Linear.Equals(other.Linear) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is Affine2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Linear, Trans);\n        }\n\n        public static Affine2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Affine2d(M22d.Parse(x[0]), V2d.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Affine\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of an <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d Inverse(Affine2d a)\n            => a.Inverse;\n\n        /// <summary>\n        /// Inverts the given affine transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Affine2d a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            a.Linear.Invert();\n            a.Trans = -a.Linear * a.Trans;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> by an <see cref=\"Affine2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Affine2d a, V3d v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> position vector (v.Z is presumed 1) by an <see cref=\"Affine2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformPos(this Affine2d a, V2d v)\n        {\n            return new V2d(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Trans.X, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Trans.Y);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> direction vector (v.Z is presumed 0) by an <see cref=\"Affine2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformDir(this Affine2d a, V2d v)\n        {\n            return new V2d(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> by the transpose of an <see cref=\"Affine2d\"/> (as a 3x3 matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransposedTransform(this Affine2d a, V3d v)\n        {\n            return new V3d(\n                v.X * a.Linear.M00 + v.Y * a.Linear.M10, \n                v.X * a.Linear.M01 + v.Y * a.Linear.M11,\n                v.X * a.Trans.X + v.Y * a.Trans.Y + v.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> by the transpose of an <see cref=\"Affine2d\"/> (as a 3x3 matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransposedTransform(this Affine2d a, V2d v)\n        {\n            return new V2d(\n                v.X * a.Linear.M00 + v.Y * a.Linear.M10, \n                v.X * a.Linear.M01 + v.Y * a.Linear.M11);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> position vector (v.Z is presumed 1) by the transpose of an <see cref=\"Affine2d\"/> (as a 3x3 matrix).\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransposedTransformPosProj(this Affine2d a, V2d v)\n        {\n            var s = v.X * a.Trans.X + v.Y * a.Trans.Y + 1;\n            return TransposedTransform(a, v) * (1 / s);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Affine2d a0, Affine2d a1)\n        {\n            return ApproximateEquals(a0, a1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Affine2d a0, Affine2d a1, double tolerance)\n        {\n            return ApproximateEquals(a0.Linear, a1.Linear, tolerance) && ApproximateEquals(a0.Trans, a1.Trans, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Affine3d\n\n    /// <summary>\n    /// Struct to represent an affine transformation in 3-dimensional space. It consists of\n    /// a linear tranformation (invertible 3x3 matrix) and a translational component (3d vector).\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Affine3d : IEquatable<Affine3d>, IValidity\n    {\n        [DataMember]\n        public M33d Linear;\n        [DataMember]\n        public V3d Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3d(Affine3d affine)\n        {\n            Linear = affine.Linear;\n            Trans = affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Affine3d\"/> transformation from a <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3d(Affine3f affine)\n        {\n            Linear = (M33d)affine.Linear;\n            Trans = (V3d)affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3d(M33d linear, V3d translation)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = translation;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3d(M33d linear, double tX, double tY, double tZ)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = new V3d(tX, tY, tZ);\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Affine3d(M33d linear)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = V3d.Zero;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Affine3d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Affine3d(M33d.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets if this affine transformation is valid, i.e. if the linear map is invertible.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Linear.Invertible;\n        }\n\n        /// <summary>\n        /// Gets if this affine transformation is invalid, i.e. if the linear map is singular.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !IsValid;\n        }\n\n        /// <summary>\n        /// Gets the inverse of this affine transformation.\n        /// </summary>\n        public readonly Affine3d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new Affine3d(this);\n                rs.Invert();\n                return rs;\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two affine transformations.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Affine3d a, Affine3d b)\n        {\n            return new Affine3d(a.Linear * b.Linear, a.Linear * b.Trans + a.Trans);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by an affine transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(Affine3d a, V4d v)\n        {\n            return new V4d(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Linear.M02 * v.Z + a.Trans.X * v.W, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Linear.M12 * v.Z + a.Trans.Y * v.W, \n                a.Linear.M20 * v.X + a.Linear.M21 * v.Y + a.Linear.M22 * v.Z + a.Trans.Z * v.W,\n                v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3d\"/> (as a 4x4 matrix) and a <see cref=\"M44d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(Affine3d a, M44d m)\n        {\n            return new M44d(\n                a.Linear.M00 * m.M00 + a.Linear.M01 * m.M10 + a.Linear.M02 * m.M20 + a.Trans.X * m.M30, \n                a.Linear.M00 * m.M01 + a.Linear.M01 * m.M11 + a.Linear.M02 * m.M21 + a.Trans.X * m.M31, \n                a.Linear.M00 * m.M02 + a.Linear.M01 * m.M12 + a.Linear.M02 * m.M22 + a.Trans.X * m.M32, \n                a.Linear.M00 * m.M03 + a.Linear.M01 * m.M13 + a.Linear.M02 * m.M23 + a.Trans.X * m.M33,\n\n                a.Linear.M10 * m.M00 + a.Linear.M11 * m.M10 + a.Linear.M12 * m.M20 + a.Trans.Y * m.M30, \n                a.Linear.M10 * m.M01 + a.Linear.M11 * m.M11 + a.Linear.M12 * m.M21 + a.Trans.Y * m.M31, \n                a.Linear.M10 * m.M02 + a.Linear.M11 * m.M12 + a.Linear.M12 * m.M22 + a.Trans.Y * m.M32, \n                a.Linear.M10 * m.M03 + a.Linear.M11 * m.M13 + a.Linear.M12 * m.M23 + a.Trans.Y * m.M33,\n\n                a.Linear.M20 * m.M00 + a.Linear.M21 * m.M10 + a.Linear.M22 * m.M20 + a.Trans.Z * m.M30, \n                a.Linear.M20 * m.M01 + a.Linear.M21 * m.M11 + a.Linear.M22 * m.M21 + a.Trans.Z * m.M31, \n                a.Linear.M20 * m.M02 + a.Linear.M21 * m.M12 + a.Linear.M22 * m.M22 + a.Trans.Z * m.M32, \n                a.Linear.M20 * m.M03 + a.Linear.M21 * m.M13 + a.Linear.M22 * m.M23 + a.Trans.Z * m.M33,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44d\"/> and a <see cref=\"Affine3d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(M44d m, Affine3d a)\n        {\n            return new M44d(\n                m.M00 * a.Linear.M00 + m.M01 * a.Linear.M10 + m.M02 * a.Linear.M20, \n                m.M00 * a.Linear.M01 + m.M01 * a.Linear.M11 + m.M02 * a.Linear.M21, \n                m.M00 * a.Linear.M02 + m.M01 * a.Linear.M12 + m.M02 * a.Linear.M22,\n                m.M00 * a.Trans.X + m.M01 * a.Trans.Y + m.M02 * a.Trans.Z + m.M03,\n\n                m.M10 * a.Linear.M00 + m.M11 * a.Linear.M10 + m.M12 * a.Linear.M20, \n                m.M10 * a.Linear.M01 + m.M11 * a.Linear.M11 + m.M12 * a.Linear.M21, \n                m.M10 * a.Linear.M02 + m.M11 * a.Linear.M12 + m.M12 * a.Linear.M22,\n                m.M10 * a.Trans.X + m.M11 * a.Trans.Y + m.M12 * a.Trans.Z + m.M13,\n\n                m.M20 * a.Linear.M00 + m.M21 * a.Linear.M10 + m.M22 * a.Linear.M20, \n                m.M20 * a.Linear.M01 + m.M21 * a.Linear.M11 + m.M22 * a.Linear.M21, \n                m.M20 * a.Linear.M02 + m.M21 * a.Linear.M12 + m.M22 * a.Linear.M22,\n                m.M20 * a.Trans.X + m.M21 * a.Trans.Y + m.M22 * a.Trans.Z + m.M23,\n\n                m.M30 * a.Linear.M00 + m.M31 * a.Linear.M10 + m.M32 * a.Linear.M20, \n                m.M30 * a.Linear.M01 + m.M31 * a.Linear.M11 + m.M32 * a.Linear.M21, \n                m.M30 * a.Linear.M02 + m.M31 * a.Linear.M12 + m.M32 * a.Linear.M22,\n                m.M30 * a.Trans.X + m.M31 * a.Trans.Y + m.M32 * a.Trans.Z + m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3d\"/> (as a 3x4 matrix) and a <see cref=\"M33d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Affine3d a, M33d m)\n            => new M34d(a.Linear * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> and a <see cref=\"Affine3d\"/> (as a 3x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M33d m, Affine3d a)\n            => new M34d(m * a.Linear, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3d\"/> (as a 3x4 matrix) and a <see cref=\"M34d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Affine3d a, M34d m)\n        {\n            return new M34d(\n                a.Linear.M00 * m.M00 + a.Linear.M01 * m.M10 + a.Linear.M02 * m.M20, \n                a.Linear.M00 * m.M01 + a.Linear.M01 * m.M11 + a.Linear.M02 * m.M21, \n                a.Linear.M00 * m.M02 + a.Linear.M01 * m.M12 + a.Linear.M02 * m.M22,\n                a.Trans.X + a.Linear.M00 * m.M03 + a.Linear.M01 * m.M13 + a.Linear.M02 * m.M23,\n\n                a.Linear.M10 * m.M00 + a.Linear.M11 * m.M10 + a.Linear.M12 * m.M20, \n                a.Linear.M10 * m.M01 + a.Linear.M11 * m.M11 + a.Linear.M12 * m.M21, \n                a.Linear.M10 * m.M02 + a.Linear.M11 * m.M12 + a.Linear.M12 * m.M22,\n                a.Trans.Y + a.Linear.M10 * m.M03 + a.Linear.M11 * m.M13 + a.Linear.M12 * m.M23,\n\n                a.Linear.M20 * m.M00 + a.Linear.M21 * m.M10 + a.Linear.M22 * m.M20, \n                a.Linear.M20 * m.M01 + a.Linear.M21 * m.M11 + a.Linear.M22 * m.M21, \n                a.Linear.M20 * m.M02 + a.Linear.M21 * m.M12 + a.Linear.M22 * m.M22,\n                a.Trans.Z + a.Linear.M20 * m.M03 + a.Linear.M21 * m.M13 + a.Linear.M22 * m.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34d\"/> and a <see cref=\"Affine3d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M34d m, Affine3d a)\n        {\n            return new M34d(\n                m.M00 * a.Linear.M00 + m.M01 * a.Linear.M10 + m.M02 * a.Linear.M20, \n                m.M00 * a.Linear.M01 + m.M01 * a.Linear.M11 + m.M02 * a.Linear.M21, \n                m.M00 * a.Linear.M02 + m.M01 * a.Linear.M12 + m.M02 * a.Linear.M22,\n                m.M00 * a.Trans.X + m.M01 * a.Trans.Y + m.M02 * a.Trans.Z + m.M03,\n\n                m.M10 * a.Linear.M00 + m.M11 * a.Linear.M10 + m.M12 * a.Linear.M20, \n                m.M10 * a.Linear.M01 + m.M11 * a.Linear.M11 + m.M12 * a.Linear.M21, \n                m.M10 * a.Linear.M02 + m.M11 * a.Linear.M12 + m.M12 * a.Linear.M22,\n                m.M10 * a.Trans.X + m.M11 * a.Trans.Y + m.M12 * a.Trans.Z + m.M13,\n\n                m.M20 * a.Linear.M00 + m.M21 * a.Linear.M10 + m.M22 * a.Linear.M20, \n                m.M20 * a.Linear.M01 + m.M21 * a.Linear.M11 + m.M22 * a.Linear.M21, \n                m.M20 * a.Linear.M02 + m.M21 * a.Linear.M12 + m.M22 * a.Linear.M22,\n                m.M20 * a.Trans.X + m.M21 * a.Trans.Y + m.M22 * a.Trans.Z + m.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3d\"/> and a <see cref=\"Euclidean3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Affine3d a, Euclidean3d e)\n            => a * (Affine3d)e;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3d\"/> and a <see cref=\"Affine3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Euclidean3d e, Affine3d a)\n            => (Affine3d)e * a;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3d\"/> and a <see cref=\"Rot3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Affine3d a, Rot3d r)\n            => new Affine3d(a.Linear * r, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> and a <see cref=\"Affine3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Rot3d r, Affine3d a)\n            => new Affine3d(r * a.Linear, r * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3d\"/> and a <see cref=\"Scale3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Affine3d a, Scale3d s)\n        {\n            return new Affine3d(new M33d(\n                a.Linear.M00 * s.X, a.Linear.M01 * s.Y, a.Linear.M02 * s.Z, \n                a.Linear.M10 * s.X, a.Linear.M11 * s.Y, a.Linear.M12 * s.Z, \n                a.Linear.M20 * s.X, a.Linear.M21 * s.Y, a.Linear.M22 * s.Z),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> and a <see cref=\"Affine3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Scale3d s, Affine3d a)\n        {\n            return new Affine3d(new M33d(\n                a.Linear.M00 * s.X, a.Linear.M01 * s.X, a.Linear.M02 * s.X, \n                a.Linear.M10 * s.Y, a.Linear.M11 * s.Y, a.Linear.M12 * s.Y, \n                a.Linear.M20 * s.Z, a.Linear.M21 * s.Z, a.Linear.M22 * s.Z),\n                a.Trans * s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3d\"/> and a <see cref=\"Shift3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Affine3d a, Shift3d s)\n        {\n            return new Affine3d(a.Linear, a.Linear * s.V + a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> and a <see cref=\"Affine3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Shift3d s, Affine3d a)\n        {\n            return new Affine3d(a.Linear, a.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Affine3d\"/> and a <see cref=\"Similarity3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Affine3d a, Similarity3d s)\n            => a * (Affine3d)s;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3d\"/> and a <see cref=\"Affine3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Similarity3d s, Affine3d a)\n            => (Affine3d)s * a;\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Affine3d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Affine3d a0, Affine3d a1)\n            => (a0.Linear == a1.Linear) && (a0.Trans == a1.Trans);\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Affine3d\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Affine3d a0, Affine3d a1)\n            => (a0.Linear != a1.Linear) || (a0.Trans != a1.Trans);\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates an affine transformation from a 3x4 matrix.\n        /// The left 3x3 submatrix of <paramref name=\"matrix\"/> must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d FromM34d(M34d matrix, double epsilon = 1e-12)\n        {\n            var linear = (M33d)matrix;\n            var trans = new V3d(matrix.M03, matrix.M13, matrix.M23);\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new Affine3d(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a 4x4 matrix.\n        /// The matrix <paramref name=\"m\"/> has to be homogeneous and must not contain perspective components and its upper left 3x3 submatrix must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d FromM44d(M44d m, double epsilon = 1e-12)\n        {\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            var linear = ((M33d)m) / m.M33;\n            var trans = new V3d(m.M03, m.M13, m.M23) / m.M33;\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new Affine3d(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a <see cref=\"Trafo3d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must represent a valid affine transformation (e.g. it does not contain perspective components).\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d FromTrafo3d(Trafo3d trafo, double epsilon = 1e-12)\n            => FromM44d(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine3d\"/> transformation with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Translation(double tX, double tY, double tZ)\n            => new Affine3d(M33d.Identity, tX, tY, tZ);\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine3d\"/> transformation with the translational component given by a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Translation(V3d vector)\n            => new Affine3d(M33d.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Affine3d\"/> transformation with the translational component given by a <see cref=\"Shift3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Translation(Shift3d shift)\n            => new Affine3d(M33d.Identity, shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Scale(double scaleFactor)\n            => new Affine3d(M33d.Scale(scaleFactor, scaleFactor, scaleFactor));\n\n        /// <summary>\n        /// Creates a scaling transformation using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Scale(double sX, double sY, double sZ)\n            => new Affine3d(M33d.Scale(sX, sY, sZ));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"V3d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Scale(V3d scaleFactors)\n            => new Affine3d(M33d.Scale(scaleFactors));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"Scale3d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Scale(Scale3d scale)\n            => new Affine3d(M33d.Scale(scale));\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Rotation(Rot3d rot)\n            => new Affine3d(M33d.Rotation(rot));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Rotation(V3d normalizedAxis, double angleRadians)\n            => new Affine3d(M33d.Rotation(normalizedAxis, angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationInDegrees(V3d normalizedAxis, double angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationEuler(double rollInRadians, double pitchInRadians, double yawInRadians)\n            => new Affine3d(M33d.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationEulerInDegrees(double rollInDegrees, double pitchInDegrees, double yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationEuler(V3d rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationEulerInDegrees(V3d rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotateInto(V3d from, V3d into)\n            => new Affine3d(M33d.RotateInto(from, into));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationX(double angleRadians)\n            => new Affine3d(M33d.RotationX(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationXInDegrees(double angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationY(double angleRadians)\n            => new Affine3d(M33d.RotationY(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationYInDegrees(double angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationZ(double angleRadians)\n            => new Affine3d(M33d.RotationZ(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d RotationZInDegrees(double angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Shear\n\n        /// <summary>\n        /// Creates a shear transformation along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d ShearXY(double factorX, double factorY)\n            => new Affine3d(M33d.ShearXY(factorX, factorY));\n\n        /// <summary>\n        /// Creates a shear transformation along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d ShearXZ(double factorX, double factorZ)\n            => new Affine3d(M33d.ShearXZ(factorX, factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d ShearYZ(double factorY, double factorZ)\n            => new Affine3d(M33d.ShearYZ(factorY, factorZ));\n\n        #endregion\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Affine3d a)\n            => new M34d(a.Linear, a.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Affine3d a)\n            => a.Linear;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Affine3d a)\n            => new M44d((M34d)a);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3d(Affine3d a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            var t = (M44d)a;\n            return new Trafo3d(t, t.Inverse);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3f(Affine3d a)\n            => new Affine3f((M33f)a.Linear, (V3f)a.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Linear, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Affine3d other)\n            => Linear.Equals(other.Linear) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is Affine3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Linear, Trans);\n        }\n\n        public static Affine3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Affine3d(M33d.Parse(x[0]), V3d.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Affine\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of an <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d Inverse(Affine3d a)\n            => a.Inverse;\n\n        /// <summary>\n        /// Inverts the given affine transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Affine3d a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            a.Linear.Invert();\n            a.Trans = -a.Linear * a.Trans;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> by an <see cref=\"Affine3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Affine3d a, V4d v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> position vector (v.W is presumed 1) by an <see cref=\"Affine3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformPos(this Affine3d a, V3d v)\n        {\n            return new V3d(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Linear.M02 * v.Z + a.Trans.X, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Linear.M12 * v.Z + a.Trans.Y, \n                a.Linear.M20 * v.X + a.Linear.M21 * v.Y + a.Linear.M22 * v.Z + a.Trans.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> direction vector (v.W is presumed 0) by an <see cref=\"Affine3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformDir(this Affine3d a, V3d v)\n        {\n            return new V3d(\n                a.Linear.M00 * v.X + a.Linear.M01 * v.Y + a.Linear.M02 * v.Z, \n                a.Linear.M10 * v.X + a.Linear.M11 * v.Y + a.Linear.M12 * v.Z, \n                a.Linear.M20 * v.X + a.Linear.M21 * v.Y + a.Linear.M22 * v.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> by the transpose of an <see cref=\"Affine3d\"/> (as a 4x4 matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d TransposedTransform(this Affine3d a, V4d v)\n        {\n            return new V4d(\n                v.X * a.Linear.M00 + v.Y * a.Linear.M10 + v.Z * a.Linear.M20, \n                v.X * a.Linear.M01 + v.Y * a.Linear.M11 + v.Z * a.Linear.M21, \n                v.X * a.Linear.M02 + v.Y * a.Linear.M12 + v.Z * a.Linear.M22,\n                v.X * a.Trans.X + v.Y * a.Trans.Y + v.Z * a.Trans.Z + v.W);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> by the transpose of an <see cref=\"Affine3d\"/> (as a 4x4 matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransposedTransform(this Affine3d a, V3d v)\n        {\n            return new V3d(\n                v.X * a.Linear.M00 + v.Y * a.Linear.M10 + v.Z * a.Linear.M20, \n                v.X * a.Linear.M01 + v.Y * a.Linear.M11 + v.Z * a.Linear.M21, \n                v.X * a.Linear.M02 + v.Y * a.Linear.M12 + v.Z * a.Linear.M22);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> position vector (v.W is presumed 1) by the transpose of an <see cref=\"Affine3d\"/> (as a 4x4 matrix).\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransposedTransformPosProj(this Affine3d a, V3d v)\n        {\n            var s = v.X * a.Trans.X + v.Y * a.Trans.Y + v.Z * a.Trans.Z + 1;\n            return TransposedTransform(a, v) * (1 / s);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Affine3d a0, Affine3d a1)\n        {\n            return ApproximateEquals(a0, a1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Affine3d a0, Affine3d a1, double tolerance)\n        {\n            return ApproximateEquals(a0.Linear, a1.Linear, tolerance) && ApproximateEquals(a0.Trans, a1.Trans, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Affine_template.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action and = () => Out(\" && \");\n    //# var fields = new[] {\"X\", \"Y\", \"Z\", \"W\"};\n    //# foreach (var isDouble in new[] { false, true }) {\n    //# for (int n = 2; n <= 3; n++) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var m = n + 1;\n    //#   var type = \"Affine\" + n + tc;\n    //#   var type2 = \"Affine\" + n + tc2;\n    //#   var trafont = \"Trafo\" + n + tc;\n    //#   var euclideannt = \"Euclidean\" + n + tc;\n    //#   var rotnt = \"Rot\" + n + tc;\n    //#   var scalent = \"Scale\" + n + tc;\n    //#   var shiftnt = \"Shift\" + n + tc;\n    //#   var similaritynt = \"Similarity\" + n + tc;\n    //#   var mnnt = \"M\" + n + n + tc;\n    //#   var mnnt2 = \"M\" + n + n + tc2;\n    //#   var mnmt = \"M\" + n + m + tc;\n    //#   var mmmt = \"M\" + m + m + tc;\n    //#   var vnt = \"V\" + n + tc;\n    //#   var vnt2 = \"V\" + n + tc2;\n    //#   var vmt = \"V\" + m + tc;\n    //#   var nfields = fields.Take(n).ToArray();\n    //#   var mfields = fields.Take(m).ToArray();\n    //#   var fn = fields[n];\n    //#   var eps = isDouble ? \"1e-12\" : \"1e-5f\";\n    #region __type__\n\n    /// <summary>\n    /// Struct to represent an affine transformation in __n__-dimensional space. It consists of\n    /// a linear tranformation (invertible __n__x__n__ matrix) and a translational component (__n__d vector).\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>, IValidity\n    {\n        [DataMember]\n        public __mnnt__ Linear;\n        [DataMember]\n        public __vnt__ Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ affine)\n        {\n            Linear = affine.Linear;\n            Trans = affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a <see cref=\"__type2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ affine)\n        {\n            Linear = (__mnnt__)affine.Linear;\n            Trans = (__vnt__)affine.Trans;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__mnnt__ linear, __vnt__ translation)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = translation;\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map and a translation.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__mnnt__ linear, /*# nfields.ForEach(f => { */__ftype__ t__f__/*# }, comma); */)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = new __vnt__(/*# nfields.ForEach(f => { */t__f__/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Constructs an affine transformation from a linear map.\n        /// The matrix <paramref name=\"linear\"/> must be invertible.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__mnnt__ linear)\n        {\n            Debug.Assert(linear.Invertible);\n            Linear = linear;\n            Trans = __vnt__.Zero;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__mnnt__.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets if this affine transformation is valid, i.e. if the linear map is invertible.\n        /// </summary>\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Linear.Invertible;\n        }\n\n        /// <summary>\n        /// Gets if this affine transformation is invalid, i.e. if the linear map is singular.\n        /// </summary>\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !IsValid;\n        }\n\n        /// <summary>\n        /// Gets the inverse of this affine transformation.\n        /// </summary>\n        public readonly __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new __type__(this);\n                rs.Invert();\n                return rs;\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two affine transformations.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __type__ b)\n        {\n            return new __type__(a.Linear * b.Linear, a.Linear * b.Trans + a.Trans);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> vector by an affine transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ operator *(__type__ a, __vmt__ v)\n        {\n            return new __vmt__(/*# nfields.ForEach((fi, i) => { */\n                /*# mfields.ForEach((fj, j) => {\n                var aij = (j < n) ? \"a.Linear.M\" + i + j : \"a.Trans.\" + fi;\n                */__aij__ * v.__fj__/*# }, add); }, comma);*/,\n                v.__fn__);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> (as a __m__x__m__ matrix) and a <see cref=\"__mmmt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mmmt__ operator *(__type__ a, __mmmt__ m)\n        {\n            return new __mmmt__(/*# nfields.ForEach((fi, i) => { mfields.ForEach((fj, j) => { */\n                /*# mfields.ForEach((fk, k) => {\n                var aik = (k < n) ? \"a.Linear.M\" + i + k : \"a.Trans.\" + fi;\n                */__aik__ * m.M__k____j__/*# }, add); }, comma); }, commaln);*/,\n\n                /*# mfields.ForEach((f, i) => { */m.M__n____i__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mmmt__\"/> and a <see cref=\"__type__\"/> (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mmmt__ operator *(__mmmt__ m, __type__ a)\n        {\n            return new __mmmt__(/*# mfields.ForEach((fi, i) => { nfields.ForEach((fj, j) => { */\n                /*# nfields.ForEach((fk, k) => {\n                */m.M__i____k__ * a.Linear.M__k____j__/*# }, add); }, comma);*/,\n                /*# nfields.ForEach((fk, k) => {\n                */m.M__i____k__ * a.Trans.__fk__/*# }, add);*/ + m.M__i____n__/*# }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> (as a __n__x__m__ matrix) and a <see cref=\"__mnnt__\"/> (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__type__ a, __mnnt__ m)\n            => new __mnmt__(a.Linear * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mnnt__\"/> and a <see cref=\"__type__\"/> (as a __n__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__mnnt__ m, __type__ a)\n            => new __mnmt__(m * a.Linear, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> (as a __n__x__m__ matrix) and a <see cref=\"__mnmt__\"/> (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__type__ a, __mnmt__ m)\n        {\n            return new __mnmt__(/*# nfields.ForEach((fi, i) => { nfields.ForEach((fj, j) => { */\n                /*# n.ForEach(k => {\n                */a.Linear.M__i____k__ * m.M__k____j__/*# }, add); }, comma);*/,\n                a.Trans.__fi__ + /*# n.ForEach(k => {*/a.Linear.M__i____k__ * m.M__k____n__/*# }, add); }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mnmt__\"/> and a <see cref=\"__type__\"/> (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__mnmt__ m, __type__ a)\n        {\n            return new __mnmt__(/*# nfields.ForEach((fi, i) => { nfields.ForEach((fj, j) => { */\n                /*# nfields.ForEach((fk, k) => {\n                */m.M__i____k__ * a.Linear.M__k____j__/*# }, add); }, comma);*/,\n                /*# nfields.ForEach((fk, k) => {\n                */m.M__i____k__ * a.Trans.__fk__/*# }, add);*/ + m.M__i____n__/*# }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__euclideannt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __euclideannt__ e)\n            => a * (__type__)e;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__euclideannt__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__euclideannt__ e, __type__ a)\n            => (__type__)e * a;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__rotnt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __rotnt__ r)\n            => new __type__(a.Linear * r, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__rotnt__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__rotnt__ r, __type__ a)\n            => new __type__(r * a.Linear, r * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__scalent__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __scalent__ s)\n        {\n            return new __type__(new __mnnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */a.Linear.M__i____j__ * s.__fj__/*# }, comma); }, comma);*/),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__scalent__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__scalent__ s, __type__ a)\n        {\n            return new __type__(new __mnnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */a.Linear.M__i____j__ * s.__fi__/*# }, comma); }, comma);*/),\n                a.Trans * s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__shiftnt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __shiftnt__ s)\n        {\n            return new __type__(a.Linear, a.Linear * s.V + a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__shiftnt__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__shiftnt__ s, __type__ a)\n        {\n            return new __type__(a.Linear, a.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__similaritynt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __similaritynt__ s)\n            => a * (__type__)s;\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__similaritynt__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__similaritynt__ s, __type__ a)\n            => (__type__)s * a;\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a0, __type__ a1)\n            => (a0.Linear == a1.Linear) && (a0.Trans == a1.Trans);\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ a0, __type__ a1)\n            => (a0.Linear != a1.Linear) || (a0.Trans != a1.Trans);\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates an affine transformation from a __n__x__m__ matrix.\n        /// The left __n__x__n__ submatrix of <paramref name=\"matrix\"/> must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mnmt__(__mnmt__ matrix, __ftype__ epsilon = __eps__)\n        {\n            var linear = (__mnnt__)matrix;\n            var trans = new __vnt__(/*# n.ForEach(i => { */matrix.M__i____n__/*# }, comma); */);\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new __type__(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a __m__x__m__ matrix.\n        /// The matrix <paramref name=\"m\"/> has to be homogeneous and must not contain perspective components and its upper left __n__x__n__ submatrix must be invertible.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mmmt__(__mmmt__ m, __ftype__ epsilon = __eps__)\n        {\n            if (!(/*#n.ForEach(j => {*/m.M__n____j__.IsTiny(epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M__n____n__.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            var linear = ((__mnnt__)m) / m.M__n____n__;\n            var trans = new __vnt__(/*# n.ForEach(i => { */m.M__i____n__/*# }, comma); */) / m.M__n____n__;\n\n            if (linear.Determinant.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix must be invertible\");\n\n            return new __type__(linear, trans);\n        }\n\n        /// <summary>\n        /// Creates an affine transformation from a <see cref=\"__trafont__\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must represent a valid affine transformation (e.g. it does not contain perspective components).\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__trafont__(__trafont__ trafo, __ftype__ epsilon = __eps__)\n            => From__mmmt__(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"__type__\"/> transformation with the translational component given by __n__ scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(/*# nfields.ForEach(f => { */__ftype__ t__f__/*# }, comma); */)\n            => new __type__(__mnnt__.Identity, /*# nfields.ForEach(f => { */t__f__/*# }, comma); */);\n\n        /// <summary>\n        /// Creates an <see cref=\"__type__\"/> transformation with the translational component given by a <see cref=\"__vnt__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(__vnt__ vector)\n            => new __type__(__mnnt__.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"__type__\"/> transformation with the translational component given by a <see cref=\"__shiftnt__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(__shiftnt__ shift)\n            => new __type__(__mnnt__.Identity, shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scale(__ftype__ scaleFactor)\n            => new __type__(__mnnt__.Scale(/*# nfields.ForEach(f => { */scaleFactor/*# }, comma); */));\n\n        /// <summary>\n        /// Creates a scaling transformation using __n__ scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scale(/*# nfields.ForEach(f => { */__ftype__ s__f__/*# }, comma); */)\n            => new __type__(__mnnt__.Scale(/*# nfields.ForEach(f => { */s__f__/*# }, comma); */));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"__vnt__\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scale(__vnt__ scaleFactors)\n            => new __type__(__mnnt__.Scale(scaleFactors));\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"__scalent__\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scale(__scalent__ scale)\n            => new __type__(__mnnt__.Scale(scale));\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"__rotnt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__rotnt__ rot)\n            => new __type__(__mnnt__.Rotation(rot));\n\n        //# if (n == 2) {\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__ftype__ angleInRadians)\n            => new __type__(__mnnt__.Rotation(angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__ftype__ angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        //# } else if (n == 3) {\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__vnt__ normalizedAxis, __ftype__ angleRadians)\n            => new __type__(__mnnt__.Rotation(normalizedAxis, angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__vnt__ normalizedAxis, __ftype__ angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__ftype__ rollInRadians, __ftype__ pitchInRadians, __ftype__ yawInRadians)\n            => new __type__(__mnnt__.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__ftype__ rollInDegrees, __ftype__ pitchInDegrees, __ftype__ yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__vnt__ rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__vnt__ rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotateInto(__vnt__ from, __vnt__ into)\n            => new __type__(__mnnt__.RotateInto(from, into));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationX(__ftype__ angleRadians)\n            => new __type__(__mnnt__.RotationX(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationXInDegrees(__ftype__ angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationY(__ftype__ angleRadians)\n            => new __type__(__mnnt__.RotationY(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationYInDegrees(__ftype__ angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZ(__ftype__ angleRadians)\n            => new __type__(__mnnt__.RotationZ(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZInDegrees(__ftype__ angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        //# }\n        #endregion\n\n        //# if (n == 3) {\n        #region Shear\n\n        /// <summary>\n        /// Creates a shear transformation along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ShearXY(__ftype__ factorX, __ftype__ factorY)\n            => new __type__(__mnnt__.ShearXY(factorX, factorY));\n\n        /// <summary>\n        /// Creates a shear transformation along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ShearXZ(__ftype__ factorX, __ftype__ factorZ)\n            => new __type__(__mnnt__.ShearXZ(factorX, factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ShearYZ(__ftype__ factorY, __ftype__ factorZ)\n            => new __type__(__mnnt__.ShearYZ(factorY, factorZ));\n\n        #endregion\n\n        //# }\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mnmt__(__type__ a)\n            => new __mnmt__(a.Linear, a.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mnnt__(__type__ a)\n            => a.Linear;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mmmt__(__type__ a)\n            => new __mmmt__((__mnmt__)a);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __trafont__(__type__ a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            var t = (__mmmt__)a;\n            return new __trafont__(t, t.Inverse);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ a)\n            => new __type2__((__mnnt2__)a.Linear, (__vnt2__)a.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Linear, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Linear.Equals(other.Linear) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Linear, Trans);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__mnnt__.Parse(x[0]), __vnt__.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Affine\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of an <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ a)\n            => a.Inverse;\n\n        /// <summary>\n        /// Inverts the given affine transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref __type__ a)\n        {\n            Debug.Assert(a.Linear.Invertible);\n            a.Linear.Invert();\n            a.Trans = -a.Linear * a.Trans;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> by an <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ Transform(this __type__ a, __vmt__ v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vnt__\"/> position vector (v.__fn__ is presumed 1) by an <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformPos(this __type__ a, __vnt__ v)\n        {\n            return new __vnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */a.Linear.M__i____j__ * v.__fj__/*# }, add);\n                */ + a.Trans.__fi__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vnt__\"/> direction vector (v.__fn__ is presumed 0) by an <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformDir(this __type__ a, __vnt__ v)\n        {\n            return new __vnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */a.Linear.M__i____j__ * v.__fj__/*# }, add); }, comma);*/);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> by the transpose of an <see cref=\"__type__\"/> (as a __m__x__m__ matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ TransposedTransform(this __type__ a, __vmt__ v)\n        {\n            return new __vmt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */v.__fj__ * a.Linear.M__j____i__/*# }, add); }, comma);*/,\n                /*# nfields.ForEach((f, i) => { */v.__f__ * a.Trans.__f__/*# }, add);*/ + v.__fn__);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vnt__\"/> by the transpose of an <see cref=\"__type__\"/> (as a __m__x__m__ matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransposedTransform(this __type__ a, __vnt__ v)\n        {\n            return new __vnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */v.__fj__ * a.Linear.M__j____i__/*# }, add); }, comma);*/);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vnt__\"/> position vector (v.__fn__ is presumed 1) by the transpose of an <see cref=\"__type__\"/> (as a __m__x__m__ matrix).\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransposedTransformPosProj(this __type__ a, __vnt__ v)\n        {\n            var s = /*# nfields.ForEach(f => {*/v.__f__ * a.Trans.__f__/*# }, add);*/ + 1;\n            return TransposedTransform(a, v) * (1 / s);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a0, __type__ a1)\n        {\n            return ApproximateEquals(a0, a1, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a0, __type__ a1, __ftype__ tolerance)\n        {\n            return ApproximateEquals(a0.Linear, a1.Linear, tolerance) && ApproximateEquals(a0.Trans, a1.Trans, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n    //# }\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/CoordTransforms.cs",
    "content": "﻿using static System.Math;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Various coordinate transformations.\n    /// \n    /// Abbreviations:\n    /// ll = lower left, lr = lower right, ul = upper left, ur = upper right\n    /// \n    /// 2D:\n    /// Normalized Image Pos:\n    /// Our coord-exchange format; Independent of reolution.\n    /// (0,0)=ul edge of sensor = ul edge of ul pixel, (1,1) = lr edge of sensor = lr edge of lr pixel.\n    /// \n    /// Pixel Center:\n    /// (0,0)=center of ul pixel, (w-1, h-1)=center of lr pixel.\n    /// \n    /// Pixel Edge:\n    /// (0,0)=ul edge of ul pixel, (w-1, h-1)= lr edge of lr pixel.\n    /// </summary>\n    public static class CoordTransforms\n    {\n        public static readonly V2d V2dHalf = new V2d(0.5, 0.5);\n\n        /// <summary>\n        /// Convert from pixel-center position to normalized image position [0,1][0,1].\n        /// (The inverse of toPixelCenter.)\n        /// </summary>\n        /// <param name=\"pos\">The pixel location defined in pixel space: (0,0)=center of upper left pixel, (w-1,h-1)=center of lower right pixel.</param>\n        /// <param name=\"imgSizeInPixel\">The size of the image (as V2d to safe lots of conversions).</param>\n        /// <returns>A normalized image position in [0,1][0,1].</returns>\n        public static V2d PixelCenterToNormalizedImgPos(V2d pos, V2d imgSizeInPixel)\n            => (pos + V2dHalf) / imgSizeInPixel;\n\n        public static V2d PixelCenterToNormalizedImgPos(V2i pos, V2d imgSizeInPixel)\n            => PixelCenterToNormalizedImgPos((V2d)pos, imgSizeInPixel);\n\n        public static V2d PixelCenterToNormalizedImgPos(int x, int y, V2d imgSizeInPixel)\n            => PixelCenterToNormalizedImgPos(new V2d(x, y), imgSizeInPixel);\n\n        /// <summary>\n        /// Returns a Matrix to \n        /// convert from pixel-center position to normalized image position [0,1][0,1].\n        /// (The inverse of toPixelCenter.)\n        /// </summary>\n        public static M33d PixelCenterToNormalizedImgMat(V2d imgSizeInPixel)\n            => M33d.Scale(V2d.II / imgSizeInPixel) * M33d.Translation(V2dHalf);\n\n        /// <summary>\n        /// Convert from normalized image position [0,1][0,1] to pixel-center position\n        /// (The inverse of toNormalizedImgPos.)\n        /// </summary>\n        /// <param name=\"pos\">The pixel location defined in pixel space: (0,0)=center of upper left pixel, (w-1,h-1)=center of lower right pixel.</param>\n        /// <param name=\"imgSizeInPixel\">The size of the image (as V2d to safe lots of conversions).</param>\n        /// <returns>A image position in [-0.5,imgSizeInPixel.X-0.5][-0.5,imgSizeInPixel.Y-0.5].</returns>\n        public static V2d NormalizedImagePosToPixelCenter(V2d pos, V2i imgSizeInPixel)\n            => new V2d(pos.X * imgSizeInPixel.X, pos.Y * imgSizeInPixel.Y) - V2dHalf;\n\n        /// <summary>\n        /// Convert from normalized image position [0,1][0,1] to pixel-center position\n        /// (The inverse of toNormalizedImgPos.)\n        /// </summary>\n        /// <param name=\"pos\">The pixel location defined in pixel space: (0,0)=center of upper left pixel, (w-1,h-1)=center of lower right pixel.</param>\n        /// <param name=\"imgSizeInPixel\">The size of the image (as V2d to safe lots of conversions).</param>\n        /// <returns>A image position in [-0.5,imgSizeInPixel.X-0.5][-0.5,imgSizeInPixel.Y-0.5].</returns>\n        public static V2d NormalizedImagePosToPixelCenter(V2d pos, V2l imgSizeInPixel)\n            => new V2d(pos.X * imgSizeInPixel.X, pos.Y * imgSizeInPixel.Y) - V2dHalf;\n\n        /// <summary>\n        /// Convert from normalized image position [0,1][0,1] to already rounded pixel-center position.\n        /// </summary>\n        /// <param name=\"pos\">The pixel location defined in pixel space: (0,0)=center of upper left pixel, (w-1,h-1)=center of lower right pixel.</param>\n        /// <param name=\"imgSizeInPixel\">The size of the image (as V2d to safe lots of conversions).</param>\n        /// <returns>A normalized image position in [0, imgSizeInPixel.X-1][0, imgSizeInPixel.Y-1].</returns>\n        public static V2i NormalizedImagePosToPixelCenterRound(V2d pos, V2i imgSizeInPixel)\n            => (V2i)NormalizedImagePosToPixelCenter(pos, imgSizeInPixel).Copy(v => Round(v));\n\n        /// <summary>\n        /// Convert from normalized image position [0,1][0,1] to already rounded pixel-center position.\n        /// </summary>\n        /// <param name=\"pos\">The pixel location defined in pixel space: (0,0)=center of upper left pixel, (w-1,h-1)=center of lower right pixel.</param>\n        /// <param name=\"imgSizeInPixel\">The size of the image (as V2d to safe lots of conversions).</param>\n        /// <returns>A normalized image position in [0, imgSizeInPixel.X-1][0, imgSizeInPixel.Y-1].</returns>\n        public static V2l NormalizedImagePosToPixelCenterRound(V2d pos, V2l imgSizeInPixel)\n            => (V2l)NormalizedImagePosToPixelCenter(pos, imgSizeInPixel).Copy(v => Round(v));\n\n        /// <summary>\n        /// Returns a Matrix to \n        /// convert from normalized image position [0,1][0,1] to pixel-center position\n        /// (The inverse of toNormalizedImgPos.)\n        /// </summary>\n        public static M33d NormalizedImagePosToPixelCenterMat(V2d imgSizeInPixel)\n            => M33d.Translation(-V2dHalf) * M33d.Scale(imgSizeInPixel);\n\n        //[ISSUE 20090819 andi] add docu\n        /////////////////////////\n        public static V2d PixelEdgeToNormalizedImgPos(V2d pos, V2d imgSizeInPixel)\n            => pos / (imgSizeInPixel-1);\n\n        public static V2d PixelEdgeToNormalizedImgPos(V2i pos, V2d imgSizeInPixel)\n            => PixelEdgeToNormalizedImgPos((V2d)pos, imgSizeInPixel);\n\n        public static M33d PixelEdgeToNormalizedImgMat(V2d imgSizeInPixel)\n            => M33d.Scale(V2d.II / (imgSizeInPixel-1));\n\n        public static V2d NormalizedImagePosToPixelEdge(V2d pos, V2d imgSizeInPixel)\n            => pos * (imgSizeInPixel-1);\n\n        public static V2i NormalizedImagePosToPixelEdgeRound(V2d pos, V2d imgSizeInPixel)\n            => (V2i)NormalizedImagePosToPixelEdge(pos, imgSizeInPixel).Copy(v => Round(v));\n\n        public static M33d NormalizedImagePosToPixelEdgeMat(V2d imgSizeInPixel)\n            => M33d.Scale(imgSizeInPixel-1);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/CoordinateSystem.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public static class CoordinateSystem\n    {\n        [Flags]\n        public enum Axis\n        {\n            X = 1,\n            Y = 2,\n            Z = 4\n        }\n\n        public enum Handedness\n        {\n            Left,\n            Right\n        }\n\n        public struct Info\n        {\n            public double UnitScale;\n            public Handedness Handedness;\n            public Axis UpVector;\n\n            public Info(double s, Handedness h, Axis u)\n            {\n                UnitScale = s;\n                Handedness = h;\n                UpVector = u;\n            }\n\n            public static readonly Info Vrml = new Info(1, Handedness.Right, Axis.Y);\n\n            public static readonly Info Aardvark = new Info(1, Handedness.Right, Axis.Z);\n\n            public readonly bool IsAardvark => Equals(Aardvark);\n\n            public override readonly int GetHashCode() => HashCode.GetCombined(UnitScale, Handedness, UpVector);\n\n            public override readonly bool Equals(object other) => (other is Info o)\n            ? UnitScale.Equals(o.UnitScale) && (Handedness == o.Handedness) && (UpVector == o.UpVector)\n            : false;\n\n            public static bool operator ==(Info a, Info b)\n                => a.UnitScale == b.UnitScale && a.Handedness == b.Handedness && a.UpVector == b.UpVector;\n\n            public static bool operator !=(Info a, Info b)\n                => a.UnitScale != b.UnitScale || a.Handedness != b.Handedness || a.UpVector != b.UpVector;\n        }\n\n        /// <summary>\n        /// Creates a transformation from the specified coordinate system\n        /// to the aardvark coordinate system (Meters, Right-Handed, Z-Up).\n        /// </summary>\n        public static Trafo3d ToAardvark(double scale, Handedness hand, Axis up)\n        {\n            var t = scale != 1 ? Trafo3d.Scale(scale) : Trafo3d.Identity;\n\n            if (hand != Handedness.Right)\n                t *= SwapHand;\n\n            if (up != Axis.Z)\n                t *= FromToRH(up, Axis.Z);\n\n            return t;\n        }\n\n        /// <summary>\n        /// Creates a transformation from the specified coordinate system\n        /// to the aardvark coordinate system (Meters, Right-Handed, Z-Up).\n        /// </summary>\n        public static Trafo3d ToAardvark(this Info from)\n            => ToAardvark(from.UnitScale, from.Handedness, from.UpVector);\n\n        /// <summary>\n        /// Creates a transformation from the specified coordinate system\n        /// to the aardvark coordinate system (Meters, Right-Handed, Z-Up).\n        /// </summary>\n        public static Trafo3d ToAardvark(Handedness hand, Axis up) => ToAardvark(1, hand, up);\n\n        /// <summary>\n        /// Creates a transformation from the specified coordinate system\n        /// to the aardvark coordinate system (Meters, Right-Handed, Z-Up).\n        /// </summary>\n        public static Trafo3d ToAardvark(Axis up) => ToAardvark(1, Handedness.Right, up);\n\n        /// <summary>\n        /// Creates a transformation from the specified coordinate system\n        /// to the aardvark coordinate system (Meters, Right-Handed, Z-Up).\n        /// </summary>\n        public static Trafo3d ToAardvark(Handedness hand) => ToAardvark(1, hand, Axis.Z);\n\n        /// <summary>\n        /// Gets the cooresponding vector for a given axis\n        /// </summary>\n        public static V3d GetAxisVector(this Axis ax)\n            => ax == Axis.X ? V3d.XAxis : (ax == Axis.Y ? V3d.YAxis : V3d.ZAxis);\n\n        /// <summary>\n        /// Builds transformation from one coordinate system to another.\n        /// </summary>\n        public static Trafo3d FromTo(Info from, Info to)\n        {\n            var t = Trafo3d.Identity;\n            if (from.UnitScale != to.UnitScale)\n                t = Trafo3d.Scale(to.UnitScale / from.UnitScale);\n\n            if (from.Handedness != to.Handedness)\n                t *= SwapHand;\n\n            if (from.UpVector != to.UpVector)\n                t *= FromToRH(from.UpVector, to.UpVector);\n\n            return t;\n        }\n\n        static Trafo3d FromTo(Axis from, Axis to, int s)\n        {\n            if (from == to)\n                return Trafo3d.Identity;\n\n            var axis = (from == Axis.X || to == Axis.X) ?\n                          (from == Axis.Y || to == Axis.Y) ?\n                              Axis.Z : Axis.Y : Axis.X;\n\n            var rotation = axis == Axis.X ? new M44d(1, 0, 0, 0,  0, 0,-s, 0,  0, s, 0, 0,  0, 0, 0, 1) :\n                           axis == Axis.Y ? new M44d(0, 0, s, 0,  0, 1, 0, 0, -s, 0, 0, 0,  0, 0, 0, 1) :\n                                            new M44d(0,-s, 0, 0,  s, 0, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1);\n\n            return new Trafo3d(rotation, rotation.Transposed);\n        }\n\n        public static Trafo3d FromToRH(Axis from, Axis to)\n        {\n            var s = Fun.Sign(((int)to) - ((int)from)); // +/- sin(90°)\n\n            return FromTo(from, to, s);\n        }\n\n        public static Trafo3d FromToLH(Axis from, Axis to)\n        {\n            var s = ((int)to) > ((int)from) ? -1 : 1; // +/- sin(90°)\n\n            return FromTo(from, to, s);\n        }\n\n        static M44d s_swapHand = new M44d(\n                                     1, 0, 0, 0,\n                                     0, 1, 0, 0,\n                                     0, 0,-1, 0,\n                                     0, 0, 0, 1);\n\n        public static readonly Trafo3d SwapHand = new Trafo3d(s_swapHand, s_swapHand);\n    }\n\n    public static class CoordinateSystemMatrixExtensions\n    {\n        /// <summary>\n        /// Returns the handedness of the given transformation matrix that is assumed to be row-major.\n        /// A right-handed coodinate system is given when\n        /// (X cross Y) dot Z is positive,\n        /// otherwise left-handed.\n        /// </summary>\n        public static CoordinateSystem.Handedness Handedness(this M44d mat)\n        {\n            var x = mat.R0.XYZ;\n            var y = mat.R1.XYZ;\n            var z = mat.R2.XYZ;\n            return x.Cross(y).Dot(z) > 0 ? CoordinateSystem.Handedness.Right : CoordinateSystem.Handedness.Left;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Euclidean_auto.cs",
    "content": "using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    #region Euclidean2f\n\n    /// <summary>\n    /// Represents a Rigid Transformation (or Rigid Body Transformation) in 2D that is composed of a\n    /// 2D rotation Rot and a subsequent translation by a 2D vector Trans.\n    /// This is also called an Euclidean Transformation and is a length preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Euclidean2f : IEquatable<Euclidean2f>\n    {\n        [DataMember]\n        public Rot2f Rot;\n        [DataMember]\n        public V2f Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2f(Euclidean2f e)\n        {\n            Rot = e.Rot;\n            Trans = e.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Euclidean2f\"/> transformation from a <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2f(Euclidean2d e)\n        {\n            Rot = (Rot2f)e.Rot;\n            Trans = (V2f)e.Trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2f(Rot2f rot)\n        {\n            Rot = rot;\n            Trans = V2f.Zero;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2f(V2f trans)\n        {\n            Rot = Rot2f.Identity;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2f(float tX, float tY)\n        {\n            Rot = Rot2f.Identity;\n            Trans = new V2f(tX, tY);\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2f(Rot2f rot, V2f trans)\n        {\n            Rot = rot;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2f(Rot2f rot, float tX, float tY)\n        {\n            Rot = rot;\n            Trans = new V2f(tX, tY);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Euclidean2f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Euclidean2f(Rot2f.Identity, V2f.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Euclidean transformation.\n        /// [Rot^T,-Rot^T Trans]\n        /// </summary>\n        public readonly Euclidean2f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newR = Rot.Inverse;\n                return new Euclidean2f(newR, -newR.Transform(Trans));\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Euclidean transformations.\n        /// This concatenates the two rigid transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f operator *(Euclidean2f a, Euclidean2f b)\n        {\n            //a.Rot * b.Rot, a.Trans + a.Rot * b.Trans\n            return new Euclidean2f(a.Rot * b.Rot, a.Trans + a.Rot.Transform(b.Trans));\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Euclidean2f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(Euclidean2f e, V3f v)\n        {\n            var rot = (M22f)e.Rot;\n            return new V3f(\n                rot.M00 * v.X + rot.M01 * v.Y + e.Trans.X * v.Z, \n                rot.M10 * v.X + rot.M11 * v.Y + e.Trans.Y * v.Z,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(Euclidean2f e, M33f m)\n        {\n            var t = (M23f)e;\n            return new M33f(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22,\n\n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> with a <see cref=\"Euclidean2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(M33f m, Euclidean2f e)\n        {\n            var t = (M23f)e;\n            return new M33f(\n                m.M00 * t.M00 + m.M01 * t.M10, \n                m.M00 * t.M01 + m.M01 * t.M11, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02,\n\n                m.M10 * t.M00 + m.M11 * t.M10, \n                m.M10 * t.M01 + m.M11 * t.M11, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12,\n\n                m.M20 * t.M00 + m.M21 * t.M10, \n                m.M20 * t.M01 + m.M21 * t.M11, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2f\"/> transformation (as a 2x3 matrix) with a <see cref=\"M23f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Euclidean2f e, M23f m)\n        {\n            var t = (M23f)e;\n            return new M23f(\n                t.M00 * m.M00 + t.M01 * m.M10, \n                t.M00 * m.M01 + t.M01 * m.M11, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02,\n\n                t.M10 * m.M00 + t.M11 * m.M10, \n                t.M10 * m.M01 + t.M11 * m.M11, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23f\"/> with a <see cref=\"Euclidean2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M23f m, Euclidean2f e)\n        {\n            var t = (M23f)e;\n            return new M23f(\n                m.M00 * t.M00 + m.M01 * t.M10, \n                m.M00 * t.M01 + m.M01 * t.M11, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02,\n\n                m.M10 * t.M00 + m.M11 * t.M10, \n                m.M10 * t.M01 + m.M11 * t.M11, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2f\"/> (as a 2x3 matrix) and a <see cref=\"M22f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Euclidean2f a, M22f m)\n            => new M23f(a.Rot * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22f\"/> and a <see cref=\"Euclidean2f\"/> (as a 2x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M22f m, Euclidean2f a)\n            => new M23f(m * a.Rot, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2f\"/> and a <see cref=\"Rot2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f operator *(Euclidean2f e, Rot2f r)\n            => new Euclidean2f(e.Rot * r, e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> and a <see cref=\"Euclidean2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f operator *(Rot2f r, Euclidean2f e)\n            => new Euclidean2f(r * e.Rot, r * e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2f\"/> and a <see cref=\"Shift2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f operator *(Euclidean2f e, Shift2f s)\n        {\n            return new Euclidean2f(e.Rot, e.Rot * s.V + e.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> and a <see cref=\"Euclidean2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f operator *(Shift2f s, Euclidean2f e)\n        {\n            return new Euclidean2f(e.Rot, e.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2f\"/> and a <see cref=\"Scale2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Euclidean2f r, Scale2f s)\n        {\n            var t = (M22f)r.Rot;\n            return new Affine2f(new M22f(\n                t.M00 * s.X, t.M01 * s.Y, \n                t.M10 * s.X, t.M11 * s.Y),\n                r.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> and a <see cref=\"Euclidean2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Scale2f s, Euclidean2f r)\n        {\n            var t = (M22f)r.Rot;\n            return new Affine2f(new M22f(\n                t.M00 * s.X, t.M01 * s.X, \n                t.M10 * s.Y, t.M11 * s.Y),\n                r.Trans * s.V);\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        public static bool operator ==(Euclidean2f r0, Euclidean2f r1)\n        {\n            return r0.Rot == r1.Rot && r0.Trans == r1.Trans;\n        }\n\n        public static bool operator !=(Euclidean2f r0, Euclidean2f r1)\n        {\n            return !(r0 == r1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2f\"/> transformation from a rotation matrix <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// The matrix <paramref name=\"rot\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f FromM22fAndV2f(M22f rot, V2f trans)\n            => new Euclidean2f(Rot2f.FromM22f(rot), trans);\n\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2f\"/> transformation from a <see cref=\"M33f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components and its upper left 2x2 submatrix must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f FromM33f(M33f m, float epsilon = 1e-5f)\n        {\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n            if (m.M22.IsTiny(epsilon)) throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM22fAndV2f(((M22f)m) / m.M22,\n                    m.C2.XY / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2f\"/> transformation from a <see cref=\"M23f\"/> matrix.\n        /// The left 2x2 submatrix of <paramref name=\"m\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f FromM23f(M23f m, float epsilon = 1e-5f)\n        {\n            return FromM22fAndV2f(((M22f)m),\n                    m.C2.XY);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2f\"/> transformation from a <see cref=\"Similarity2f\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f FromSimilarity2f(Similarity2f similarity, float epsilon = 1e-5f)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            return similarity.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2f\"/> transformation from an <see cref=\"Affine2f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f FromAffine2f(Affine2f affine, float epsilon = 1e-5f)\n            => FromM33f((M33f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2f\"/> transformation from a <see cref=\"Trafo2f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f FromTrafo2f(Trafo2f trafo, float epsilon = 1e-5f)\n            => FromM33f(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2f\"/> transformation with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f Translation(float tX, float tY)\n            => new Euclidean2f(tX, tY);\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2f\"/> transformation with the translational component given by a <see cref=\"V2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f Translation(V2f vector)\n            => new Euclidean2f(vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Euclidean2f\"/> transformation with the translational component given by a <see cref=\"Shift2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f Translation(Shift2f shift)\n            => new Euclidean2f(shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f Rotation(Rot2f rot)\n            => new Euclidean2f(rot);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f Rotation(float angleInRadians)\n            => new Euclidean2f(new Rot2f(angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f RotationInDegrees(float angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23f(Euclidean2f e)\n            => new M23f((M22f)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22f(Euclidean2f e)\n            => (M22f)e.Rot;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Euclidean2f e)\n        {\n            M33f rv = (M33f)e.Rot;\n            rv.C2 = e.Trans.XYI;\n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity2f(Euclidean2f e)\n            => new Similarity2f(1, e);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2f(Euclidean2f e)\n            => new Affine2f((M22f)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2f(Euclidean2f e)\n            => new Trafo2f((M33f)e, (M33f)e.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean2d(Euclidean2f e)\n            => new Euclidean2d((Rot2d)e.Rot, (V2d)e.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Rot, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Euclidean2f other)\n            => Rot.Equals(other.Rot) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is Euclidean2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Rot, Trans);\n        }\n\n        public static Euclidean2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Euclidean2f(Rot2f.Parse(x[0]), V2f.Parse(x[1]));\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Euclidean\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f Inverse(Euclidean2f r)\n            => r.Inverse;\n\n        /// <summary>\n        /// Inverts this rigid transformation (multiplicative inverse).\n        /// this = [Rot^T,-Rot^T Trans]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Euclidean2f r)\n        {\n            r.Rot.Invert();\n            r.Trans = -r.Rot.Transform(r.Trans);\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> by an <see cref=\"Euclidean2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Euclidean2f a, V3f v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformDir(this Euclidean2f r, V2f v)\n        {\n            return r.Rot.Transform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformPos(this Euclidean2f r, V2f p)\n        {\n            return r.Rot.Transform(p) + r.Trans;\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransformDir(this Euclidean2f r, V2f v)\n        {\n            return r.Rot.InvTransform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransformPos(this Euclidean2f r, V2f p)\n        {\n            return r.Rot.InvTransform(p - r.Trans);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean2f r0, Euclidean2f r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean2f r0, Euclidean2f r1, float tol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, tol) && r0.Rot.ApproximateEquals(r1.Rot, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean2f r0, Euclidean2f r1, float angleTol, float posTol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, posTol) && r0.Rot.ApproximateEquals(r1.Rot, angleTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Euclidean3f\n\n    /// <summary>\n    /// Represents a Rigid Transformation (or Rigid Body Transformation) in 3D that is composed of a\n    /// 3D rotation Rot and a subsequent translation by a 3D vector Trans.\n    /// This is also called an Euclidean Transformation and is a length preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Euclidean3f : IEquatable<Euclidean3f>\n    {\n        [DataMember]\n        public Rot3f Rot;\n        [DataMember]\n        public V3f Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3f(Euclidean3f e)\n        {\n            Rot = e.Rot;\n            Trans = e.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Euclidean3f\"/> transformation from a <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3f(Euclidean3d e)\n        {\n            Rot = (Rot3f)e.Rot;\n            Trans = (V3f)e.Trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3f(Rot3f rot)\n        {\n            Rot = rot;\n            Trans = V3f.Zero;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3f(V3f trans)\n        {\n            Rot = Rot3f.Identity;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>, <paramref name=\"tZ\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3f(float tX, float tY, float tZ)\n        {\n            Rot = Rot3f.Identity;\n            Trans = new V3f(tX, tY, tZ);\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3f(Rot3f rot, V3f trans)\n        {\n            Rot = rot;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>, <paramref name=\"tZ\"/>)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3f(Rot3f rot, float tX, float tY, float tZ)\n        {\n            Rot = rot;\n            Trans = new V3f(tX, tY, tZ);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Euclidean3f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Euclidean3f(Rot3f.Identity, V3f.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns a new version of this Euclidean transformation with a normalized rotation quaternion.\n        /// </summary>\n        public readonly Euclidean3f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Euclidean3f(Rot.Normalized, Trans);\n        }\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Euclidean transformation.\n        /// [Rot^T,-Rot^T Trans]\n        /// </summary>\n        public readonly Euclidean3f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newR = Rot.Inverse;\n                return new Euclidean3f(newR, -newR.Transform(Trans));\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Euclidean transformations.\n        /// This concatenates the two rigid transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f operator *(Euclidean3f a, Euclidean3f b)\n        {\n            //a.Rot * b.Rot, a.Trans + a.Rot * b.Trans\n            return new Euclidean3f(a.Rot * b.Rot, a.Trans + a.Rot.Transform(b.Trans));\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by a <see cref=\"Euclidean3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(Euclidean3f e, V4f v)\n        {\n            var rot = (M33f)e.Rot;\n            return new V4f(\n                rot.M00 * v.X + rot.M01 * v.Y + rot.M02 * v.Z + e.Trans.X * v.W, \n                rot.M10 * v.X + rot.M11 * v.Y + rot.M12 * v.Z + e.Trans.Y * v.W, \n                rot.M20 * v.X + rot.M21 * v.Y + rot.M22 * v.Z + e.Trans.Z * v.W,\n                v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3f\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(Euclidean3f e, M44f m)\n        {\n            var t = (M34f)e;\n            return new M44f(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20 + t.M03 * m.M30, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21 + t.M03 * m.M31, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22 + t.M03 * m.M32, \n                t.M00 * m.M03 + t.M01 * m.M13 + t.M02 * m.M23 + t.M03 * m.M33,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20 + t.M13 * m.M30, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21 + t.M13 * m.M31, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22 + t.M13 * m.M32, \n                t.M10 * m.M03 + t.M11 * m.M13 + t.M12 * m.M23 + t.M13 * m.M33,\n\n                t.M20 * m.M00 + t.M21 * m.M10 + t.M22 * m.M20 + t.M23 * m.M30, \n                t.M20 * m.M01 + t.M21 * m.M11 + t.M22 * m.M21 + t.M23 * m.M31, \n                t.M20 * m.M02 + t.M21 * m.M12 + t.M22 * m.M22 + t.M23 * m.M32, \n                t.M20 * m.M03 + t.M21 * m.M13 + t.M22 * m.M23 + t.M23 * m.M33,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44f\"/> with a <see cref=\"Euclidean3f\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(M44f m, Euclidean3f e)\n        {\n            var t = (M34f)e;\n            return new M44f(\n                m.M00 * t.M00 + m.M01 * t.M10 + m.M02 * t.M20, \n                m.M00 * t.M01 + m.M01 * t.M11 + m.M02 * t.M21, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02 * t.M22, \n                m.M00 * t.M03 + m.M01 * t.M13 + m.M02 * t.M23 + m.M03,\n\n                m.M10 * t.M00 + m.M11 * t.M10 + m.M12 * t.M20, \n                m.M10 * t.M01 + m.M11 * t.M11 + m.M12 * t.M21, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12 * t.M22, \n                m.M10 * t.M03 + m.M11 * t.M13 + m.M12 * t.M23 + m.M13,\n\n                m.M20 * t.M00 + m.M21 * t.M10 + m.M22 * t.M20, \n                m.M20 * t.M01 + m.M21 * t.M11 + m.M22 * t.M21, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22 * t.M22, \n                m.M20 * t.M03 + m.M21 * t.M13 + m.M22 * t.M23 + m.M23,\n\n                m.M30 * t.M00 + m.M31 * t.M10 + m.M32 * t.M20, \n                m.M30 * t.M01 + m.M31 * t.M11 + m.M32 * t.M21, \n                m.M30 * t.M02 + m.M31 * t.M12 + m.M32 * t.M22, \n                m.M30 * t.M03 + m.M31 * t.M13 + m.M32 * t.M23 + m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3f\"/> transformation (as a 3x4 matrix) with a <see cref=\"M34f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Euclidean3f e, M34f m)\n        {\n            var t = (M34f)e;\n            return new M34f(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22, \n                t.M00 * m.M03 + t.M01 * m.M13 + t.M02 * m.M23 + t.M03,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22, \n                t.M10 * m.M03 + t.M11 * m.M13 + t.M12 * m.M23 + t.M13,\n\n                t.M20 * m.M00 + t.M21 * m.M10 + t.M22 * m.M20, \n                t.M20 * m.M01 + t.M21 * m.M11 + t.M22 * m.M21, \n                t.M20 * m.M02 + t.M21 * m.M12 + t.M22 * m.M22, \n                t.M20 * m.M03 + t.M21 * m.M13 + t.M22 * m.M23 + t.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34f\"/> with a <see cref=\"Euclidean3f\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M34f m, Euclidean3f e)\n        {\n            var t = (M34f)e;\n            return new M34f(\n                m.M00 * t.M00 + m.M01 * t.M10 + m.M02 * t.M20, \n                m.M00 * t.M01 + m.M01 * t.M11 + m.M02 * t.M21, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02 * t.M22, \n                m.M00 * t.M03 + m.M01 * t.M13 + m.M02 * t.M23 + m.M03,\n\n                m.M10 * t.M00 + m.M11 * t.M10 + m.M12 * t.M20, \n                m.M10 * t.M01 + m.M11 * t.M11 + m.M12 * t.M21, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12 * t.M22, \n                m.M10 * t.M03 + m.M11 * t.M13 + m.M12 * t.M23 + m.M13,\n\n                m.M20 * t.M00 + m.M21 * t.M10 + m.M22 * t.M20, \n                m.M20 * t.M01 + m.M21 * t.M11 + m.M22 * t.M21, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22 * t.M22, \n                m.M20 * t.M03 + m.M21 * t.M13 + m.M22 * t.M23 + m.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3f\"/> (as a 3x4 matrix) and a <see cref=\"M33f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Euclidean3f a, M33f m)\n            => new M34f(a.Rot * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> and a <see cref=\"Euclidean3f\"/> (as a 3x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M33f m, Euclidean3f a)\n            => new M34f(m * a.Rot, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3f\"/> and a <see cref=\"Rot3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f operator *(Euclidean3f e, Rot3f r)\n            => new Euclidean3f(e.Rot * r, e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> and a <see cref=\"Euclidean3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f operator *(Rot3f r, Euclidean3f e)\n            => new Euclidean3f(r * e.Rot, r * e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3f\"/> and a <see cref=\"Shift3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f operator *(Euclidean3f e, Shift3f s)\n        {\n            return new Euclidean3f(e.Rot, e.Rot * s.V + e.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> and a <see cref=\"Euclidean3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f operator *(Shift3f s, Euclidean3f e)\n        {\n            return new Euclidean3f(e.Rot, e.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3f\"/> and a <see cref=\"Scale3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Euclidean3f r, Scale3f s)\n        {\n            var t = (M33f)r.Rot;\n            return new Affine3f(new M33f(\n                t.M00 * s.X, t.M01 * s.Y, t.M02 * s.Z, \n                t.M10 * s.X, t.M11 * s.Y, t.M12 * s.Z, \n                t.M20 * s.X, t.M21 * s.Y, t.M22 * s.Z),\n                r.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> and a <see cref=\"Euclidean3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Scale3f s, Euclidean3f r)\n        {\n            var t = (M33f)r.Rot;\n            return new Affine3f(new M33f(\n                t.M00 * s.X, t.M01 * s.X, t.M02 * s.X, \n                t.M10 * s.Y, t.M11 * s.Y, t.M12 * s.Y, \n                t.M20 * s.Z, t.M21 * s.Z, t.M22 * s.Z),\n                r.Trans * s.V);\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        public static bool operator ==(Euclidean3f r0, Euclidean3f r1)\n        {\n            return r0.Rot == r1.Rot && r0.Trans == r1.Trans;\n        }\n\n        public static bool operator !=(Euclidean3f r0, Euclidean3f r1)\n        {\n            return !(r0 == r1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3f\"/> transformation from a rotation matrix <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// The matrix <paramref name=\"rot\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f FromM33fAndV3f(M33f rot, V3f trans, float epsilon = 1e-5f)\n            => new Euclidean3f(Rot3f.FromM33f(rot, epsilon), trans);\n\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3f\"/> transformation from a <see cref=\"M44f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components and its upper left 3x3 submatrix must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f FromM44f(M44f m, float epsilon = 1e-5f)\n        {\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n            if (m.M33.IsTiny(epsilon)) throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM33fAndV3f(((M33f)m) / m.M33,\n                    m.C3.XYZ / m.M33,\n                    epsilon);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3f\"/> transformation from a <see cref=\"M34f\"/> matrix.\n        /// The left 3x3 submatrix of <paramref name=\"m\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f FromM34f(M34f m, float epsilon = 1e-5f)\n        {\n            return FromM33fAndV3f(((M33f)m),\n                    m.C3.XYZ,\n                    epsilon);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3f\"/> transformation from a <see cref=\"Similarity3f\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f FromSimilarity3f(Similarity3f similarity, float epsilon = 1e-5f)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            return similarity.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3f\"/> transformation from an <see cref=\"Affine3f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f FromAffine3f(Affine3f affine, float epsilon = 1e-5f)\n            => FromM44f((M44f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3f\"/> transformation from a <see cref=\"Trafo3f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f FromTrafo3f(Trafo3f trafo, float epsilon = 1e-5f)\n            => FromM44f(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3f\"/> transformation with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f Translation(float tX, float tY, float tZ)\n            => new Euclidean3f(tX, tY, tZ);\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3f\"/> transformation with the translational component given by a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f Translation(V3f vector)\n            => new Euclidean3f(vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Euclidean3f\"/> transformation with the translational component given by a <see cref=\"Shift3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f Translation(Shift3f shift)\n            => new Euclidean3f(shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f Rotation(Rot3f rot)\n            => new Euclidean3f(rot);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f Rotation(V3f normalizedAxis, float angleRadians)\n            => new Euclidean3f(Rot3f.Rotation(normalizedAxis, angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationInDegrees(V3f normalizedAxis, float angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationEuler(float rollInRadians, float pitchInRadians, float yawInRadians)\n            => new Euclidean3f(Rot3f.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationEulerInDegrees(float rollInDegrees, float pitchInDegrees, float yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationEuler(V3f rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationEulerInDegrees(V3f rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotateInto(V3f from, V3f into)\n            => new Euclidean3f(Rot3f.RotateInto(from, into));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationX(float angleRadians)\n            => new Euclidean3f(Rot3f.RotationX(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationXInDegrees(float angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationY(float angleRadians)\n            => new Euclidean3f(Rot3f.RotationY(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationYInDegrees(float angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationZ(float angleRadians)\n            => new Euclidean3f(Rot3f.RotationZ(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f RotationZInDegrees(float angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Euclidean3f e)\n            => new M34f((M33f)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Euclidean3f e)\n            => (M33f)e.Rot;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Euclidean3f e)\n        {\n            M44f rv = (M44f)e.Rot;\n            rv.C3 = e.Trans.XYZI;\n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity3f(Euclidean3f e)\n            => new Similarity3f(1, e);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3f(Euclidean3f e)\n            => new Affine3f((M33f)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3f(Euclidean3f e)\n            => new Trafo3f((M44f)e, (M44f)e.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean3d(Euclidean3f e)\n            => new Euclidean3d((Rot3d)e.Rot, (V3d)e.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Rot, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Euclidean3f other)\n            => Rot.Equals(other.Rot) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is Euclidean3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Rot, Trans);\n        }\n\n        public static Euclidean3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Euclidean3f(Rot3f.Parse(x[0]), V3f.Parse(x[1]));\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Euclidean\n    {\n        #region Normalize\n\n        /// <summary>\n        /// Returns a copy of a <see cref=\"Euclidean3f\"/> with its rotation quaternion normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f Normalized(Euclidean3f r)\n            => r.Normalized;\n\n        /// <summary>\n        /// Normalizes the rotation quaternion of a <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref Euclidean3f r)\n        {\n            r.Rot.Normalize();\n        }\n\n        #endregion\n\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f Inverse(Euclidean3f r)\n            => r.Inverse;\n\n        /// <summary>\n        /// Inverts this rigid transformation (multiplicative inverse).\n        /// this = [Rot^T,-Rot^T Trans]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Euclidean3f r)\n        {\n            r.Rot.Invert();\n            r.Trans = -r.Rot.Transform(r.Trans);\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> by an <see cref=\"Euclidean3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Euclidean3f a, V4f v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformDir(this Euclidean3f r, V3f v)\n        {\n            return r.Rot.Transform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformPos(this Euclidean3f r, V3f p)\n        {\n            return r.Rot.Transform(p) + r.Trans;\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformDir(this Euclidean3f r, V3f v)\n        {\n            return r.Rot.InvTransform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformPos(this Euclidean3f r, V3f p)\n        {\n            return r.Rot.InvTransform(p - r.Trans);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean3f r0, Euclidean3f r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean3f r0, Euclidean3f r1, float tol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, tol) && r0.Rot.ApproximateEquals(r1.Rot, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean3f r0, Euclidean3f r1, float angleTol, float posTol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, posTol) && r0.Rot.ApproximateEquals(r1.Rot, angleTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Euclidean2d\n\n    /// <summary>\n    /// Represents a Rigid Transformation (or Rigid Body Transformation) in 2D that is composed of a\n    /// 2D rotation Rot and a subsequent translation by a 2D vector Trans.\n    /// This is also called an Euclidean Transformation and is a length preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Euclidean2d : IEquatable<Euclidean2d>\n    {\n        [DataMember]\n        public Rot2d Rot;\n        [DataMember]\n        public V2d Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2d(Euclidean2d e)\n        {\n            Rot = e.Rot;\n            Trans = e.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Euclidean2d\"/> transformation from a <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2d(Euclidean2f e)\n        {\n            Rot = (Rot2d)e.Rot;\n            Trans = (V2d)e.Trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2d(Rot2d rot)\n        {\n            Rot = rot;\n            Trans = V2d.Zero;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2d(V2d trans)\n        {\n            Rot = Rot2d.Identity;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2d(double tX, double tY)\n        {\n            Rot = Rot2d.Identity;\n            Trans = new V2d(tX, tY);\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2d(Rot2d rot, V2d trans)\n        {\n            Rot = rot;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean2d(Rot2d rot, double tX, double tY)\n        {\n            Rot = rot;\n            Trans = new V2d(tX, tY);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Euclidean2d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Euclidean2d(Rot2d.Identity, V2d.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Euclidean transformation.\n        /// [Rot^T,-Rot^T Trans]\n        /// </summary>\n        public readonly Euclidean2d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newR = Rot.Inverse;\n                return new Euclidean2d(newR, -newR.Transform(Trans));\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Euclidean transformations.\n        /// This concatenates the two rigid transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d operator *(Euclidean2d a, Euclidean2d b)\n        {\n            //a.Rot * b.Rot, a.Trans + a.Rot * b.Trans\n            return new Euclidean2d(a.Rot * b.Rot, a.Trans + a.Rot.Transform(b.Trans));\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Euclidean2d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(Euclidean2d e, V3d v)\n        {\n            var rot = (M22d)e.Rot;\n            return new V3d(\n                rot.M00 * v.X + rot.M01 * v.Y + e.Trans.X * v.Z, \n                rot.M10 * v.X + rot.M11 * v.Y + e.Trans.Y * v.Z,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(Euclidean2d e, M33d m)\n        {\n            var t = (M23d)e;\n            return new M33d(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22,\n\n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> with a <see cref=\"Euclidean2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(M33d m, Euclidean2d e)\n        {\n            var t = (M23d)e;\n            return new M33d(\n                m.M00 * t.M00 + m.M01 * t.M10, \n                m.M00 * t.M01 + m.M01 * t.M11, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02,\n\n                m.M10 * t.M00 + m.M11 * t.M10, \n                m.M10 * t.M01 + m.M11 * t.M11, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12,\n\n                m.M20 * t.M00 + m.M21 * t.M10, \n                m.M20 * t.M01 + m.M21 * t.M11, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2d\"/> transformation (as a 2x3 matrix) with a <see cref=\"M23d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Euclidean2d e, M23d m)\n        {\n            var t = (M23d)e;\n            return new M23d(\n                t.M00 * m.M00 + t.M01 * m.M10, \n                t.M00 * m.M01 + t.M01 * m.M11, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02,\n\n                t.M10 * m.M00 + t.M11 * m.M10, \n                t.M10 * m.M01 + t.M11 * m.M11, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23d\"/> with a <see cref=\"Euclidean2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M23d m, Euclidean2d e)\n        {\n            var t = (M23d)e;\n            return new M23d(\n                m.M00 * t.M00 + m.M01 * t.M10, \n                m.M00 * t.M01 + m.M01 * t.M11, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02,\n\n                m.M10 * t.M00 + m.M11 * t.M10, \n                m.M10 * t.M01 + m.M11 * t.M11, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2d\"/> (as a 2x3 matrix) and a <see cref=\"M22d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Euclidean2d a, M22d m)\n            => new M23d(a.Rot * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22d\"/> and a <see cref=\"Euclidean2d\"/> (as a 2x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M22d m, Euclidean2d a)\n            => new M23d(m * a.Rot, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2d\"/> and a <see cref=\"Rot2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d operator *(Euclidean2d e, Rot2d r)\n            => new Euclidean2d(e.Rot * r, e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> and a <see cref=\"Euclidean2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d operator *(Rot2d r, Euclidean2d e)\n            => new Euclidean2d(r * e.Rot, r * e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2d\"/> and a <see cref=\"Shift2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d operator *(Euclidean2d e, Shift2d s)\n        {\n            return new Euclidean2d(e.Rot, e.Rot * s.V + e.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> and a <see cref=\"Euclidean2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d operator *(Shift2d s, Euclidean2d e)\n        {\n            return new Euclidean2d(e.Rot, e.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean2d\"/> and a <see cref=\"Scale2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Euclidean2d r, Scale2d s)\n        {\n            var t = (M22d)r.Rot;\n            return new Affine2d(new M22d(\n                t.M00 * s.X, t.M01 * s.Y, \n                t.M10 * s.X, t.M11 * s.Y),\n                r.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> and a <see cref=\"Euclidean2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Scale2d s, Euclidean2d r)\n        {\n            var t = (M22d)r.Rot;\n            return new Affine2d(new M22d(\n                t.M00 * s.X, t.M01 * s.X, \n                t.M10 * s.Y, t.M11 * s.Y),\n                r.Trans * s.V);\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        public static bool operator ==(Euclidean2d r0, Euclidean2d r1)\n        {\n            return r0.Rot == r1.Rot && r0.Trans == r1.Trans;\n        }\n\n        public static bool operator !=(Euclidean2d r0, Euclidean2d r1)\n        {\n            return !(r0 == r1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2d\"/> transformation from a rotation matrix <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// The matrix <paramref name=\"rot\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d FromM22dAndV2d(M22d rot, V2d trans)\n            => new Euclidean2d(Rot2d.FromM22d(rot), trans);\n\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2d\"/> transformation from a <see cref=\"M33d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components and its upper left 2x2 submatrix must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d FromM33d(M33d m, double epsilon = 1e-12)\n        {\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n            if (m.M22.IsTiny(epsilon)) throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM22dAndV2d(((M22d)m) / m.M22,\n                    m.C2.XY / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2d\"/> transformation from a <see cref=\"M23d\"/> matrix.\n        /// The left 2x2 submatrix of <paramref name=\"m\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d FromM23d(M23d m, double epsilon = 1e-12)\n        {\n            return FromM22dAndV2d(((M22d)m),\n                    m.C2.XY);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2d\"/> transformation from a <see cref=\"Similarity2d\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d FromSimilarity2d(Similarity2d similarity, double epsilon = 1e-12)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            return similarity.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2d\"/> transformation from an <see cref=\"Affine2d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d FromAffine2d(Affine2d affine, double epsilon = 1e-12)\n            => FromM33d((M33d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2d\"/> transformation from a <see cref=\"Trafo2d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d FromTrafo2d(Trafo2d trafo, double epsilon = 1e-12)\n            => FromM33d(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2d\"/> transformation with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d Translation(double tX, double tY)\n            => new Euclidean2d(tX, tY);\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean2d\"/> transformation with the translational component given by a <see cref=\"V2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d Translation(V2d vector)\n            => new Euclidean2d(vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Euclidean2d\"/> transformation with the translational component given by a <see cref=\"Shift2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d Translation(Shift2d shift)\n            => new Euclidean2d(shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d Rotation(Rot2d rot)\n            => new Euclidean2d(rot);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d Rotation(double angleInRadians)\n            => new Euclidean2d(new Rot2d(angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d RotationInDegrees(double angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23d(Euclidean2d e)\n            => new M23d((M22d)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22d(Euclidean2d e)\n            => (M22d)e.Rot;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Euclidean2d e)\n        {\n            M33d rv = (M33d)e.Rot;\n            rv.C2 = e.Trans.XYI;\n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity2d(Euclidean2d e)\n            => new Similarity2d(1, e);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2d(Euclidean2d e)\n            => new Affine2d((M22d)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2d(Euclidean2d e)\n            => new Trafo2d((M33d)e, (M33d)e.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean2f(Euclidean2d e)\n            => new Euclidean2f((Rot2f)e.Rot, (V2f)e.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Rot, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Euclidean2d other)\n            => Rot.Equals(other.Rot) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is Euclidean2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Rot, Trans);\n        }\n\n        public static Euclidean2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Euclidean2d(Rot2d.Parse(x[0]), V2d.Parse(x[1]));\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Euclidean\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d Inverse(Euclidean2d r)\n            => r.Inverse;\n\n        /// <summary>\n        /// Inverts this rigid transformation (multiplicative inverse).\n        /// this = [Rot^T,-Rot^T Trans]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Euclidean2d r)\n        {\n            r.Rot.Invert();\n            r.Trans = -r.Rot.Transform(r.Trans);\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> by an <see cref=\"Euclidean2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Euclidean2d a, V3d v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformDir(this Euclidean2d r, V2d v)\n        {\n            return r.Rot.Transform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformPos(this Euclidean2d r, V2d p)\n        {\n            return r.Rot.Transform(p) + r.Trans;\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransformDir(this Euclidean2d r, V2d v)\n        {\n            return r.Rot.InvTransform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransformPos(this Euclidean2d r, V2d p)\n        {\n            return r.Rot.InvTransform(p - r.Trans);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean2d r0, Euclidean2d r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean2d r0, Euclidean2d r1, double tol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, tol) && r0.Rot.ApproximateEquals(r1.Rot, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean2d r0, Euclidean2d r1, double angleTol, double posTol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, posTol) && r0.Rot.ApproximateEquals(r1.Rot, angleTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Euclidean3d\n\n    /// <summary>\n    /// Represents a Rigid Transformation (or Rigid Body Transformation) in 3D that is composed of a\n    /// 3D rotation Rot and a subsequent translation by a 3D vector Trans.\n    /// This is also called an Euclidean Transformation and is a length preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Euclidean3d : IEquatable<Euclidean3d>\n    {\n        [DataMember]\n        public Rot3d Rot;\n        [DataMember]\n        public V3d Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3d(Euclidean3d e)\n        {\n            Rot = e.Rot;\n            Trans = e.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Euclidean3d\"/> transformation from a <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3d(Euclidean3f e)\n        {\n            Rot = (Rot3d)e.Rot;\n            Trans = (V3d)e.Trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3d(Rot3d rot)\n        {\n            Rot = rot;\n            Trans = V3d.Zero;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3d(V3d trans)\n        {\n            Rot = Rot3d.Identity;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>, <paramref name=\"tZ\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3d(double tX, double tY, double tZ)\n        {\n            Rot = Rot3d.Identity;\n            Trans = new V3d(tX, tY, tZ);\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3d(Rot3d rot, V3d trans)\n        {\n            Rot = rot;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>, <paramref name=\"tZ\"/>)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Euclidean3d(Rot3d rot, double tX, double tY, double tZ)\n        {\n            Rot = rot;\n            Trans = new V3d(tX, tY, tZ);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Euclidean3d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Euclidean3d(Rot3d.Identity, V3d.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns a new version of this Euclidean transformation with a normalized rotation quaternion.\n        /// </summary>\n        public readonly Euclidean3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Euclidean3d(Rot.Normalized, Trans);\n        }\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Euclidean transformation.\n        /// [Rot^T,-Rot^T Trans]\n        /// </summary>\n        public readonly Euclidean3d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newR = Rot.Inverse;\n                return new Euclidean3d(newR, -newR.Transform(Trans));\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Euclidean transformations.\n        /// This concatenates the two rigid transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d operator *(Euclidean3d a, Euclidean3d b)\n        {\n            //a.Rot * b.Rot, a.Trans + a.Rot * b.Trans\n            return new Euclidean3d(a.Rot * b.Rot, a.Trans + a.Rot.Transform(b.Trans));\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by a <see cref=\"Euclidean3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(Euclidean3d e, V4d v)\n        {\n            var rot = (M33d)e.Rot;\n            return new V4d(\n                rot.M00 * v.X + rot.M01 * v.Y + rot.M02 * v.Z + e.Trans.X * v.W, \n                rot.M10 * v.X + rot.M11 * v.Y + rot.M12 * v.Z + e.Trans.Y * v.W, \n                rot.M20 * v.X + rot.M21 * v.Y + rot.M22 * v.Z + e.Trans.Z * v.W,\n                v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3d\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(Euclidean3d e, M44d m)\n        {\n            var t = (M34d)e;\n            return new M44d(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20 + t.M03 * m.M30, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21 + t.M03 * m.M31, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22 + t.M03 * m.M32, \n                t.M00 * m.M03 + t.M01 * m.M13 + t.M02 * m.M23 + t.M03 * m.M33,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20 + t.M13 * m.M30, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21 + t.M13 * m.M31, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22 + t.M13 * m.M32, \n                t.M10 * m.M03 + t.M11 * m.M13 + t.M12 * m.M23 + t.M13 * m.M33,\n\n                t.M20 * m.M00 + t.M21 * m.M10 + t.M22 * m.M20 + t.M23 * m.M30, \n                t.M20 * m.M01 + t.M21 * m.M11 + t.M22 * m.M21 + t.M23 * m.M31, \n                t.M20 * m.M02 + t.M21 * m.M12 + t.M22 * m.M22 + t.M23 * m.M32, \n                t.M20 * m.M03 + t.M21 * m.M13 + t.M22 * m.M23 + t.M23 * m.M33,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44d\"/> with a <see cref=\"Euclidean3d\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(M44d m, Euclidean3d e)\n        {\n            var t = (M34d)e;\n            return new M44d(\n                m.M00 * t.M00 + m.M01 * t.M10 + m.M02 * t.M20, \n                m.M00 * t.M01 + m.M01 * t.M11 + m.M02 * t.M21, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02 * t.M22, \n                m.M00 * t.M03 + m.M01 * t.M13 + m.M02 * t.M23 + m.M03,\n\n                m.M10 * t.M00 + m.M11 * t.M10 + m.M12 * t.M20, \n                m.M10 * t.M01 + m.M11 * t.M11 + m.M12 * t.M21, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12 * t.M22, \n                m.M10 * t.M03 + m.M11 * t.M13 + m.M12 * t.M23 + m.M13,\n\n                m.M20 * t.M00 + m.M21 * t.M10 + m.M22 * t.M20, \n                m.M20 * t.M01 + m.M21 * t.M11 + m.M22 * t.M21, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22 * t.M22, \n                m.M20 * t.M03 + m.M21 * t.M13 + m.M22 * t.M23 + m.M23,\n\n                m.M30 * t.M00 + m.M31 * t.M10 + m.M32 * t.M20, \n                m.M30 * t.M01 + m.M31 * t.M11 + m.M32 * t.M21, \n                m.M30 * t.M02 + m.M31 * t.M12 + m.M32 * t.M22, \n                m.M30 * t.M03 + m.M31 * t.M13 + m.M32 * t.M23 + m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3d\"/> transformation (as a 3x4 matrix) with a <see cref=\"M34d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Euclidean3d e, M34d m)\n        {\n            var t = (M34d)e;\n            return new M34d(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22, \n                t.M00 * m.M03 + t.M01 * m.M13 + t.M02 * m.M23 + t.M03,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22, \n                t.M10 * m.M03 + t.M11 * m.M13 + t.M12 * m.M23 + t.M13,\n\n                t.M20 * m.M00 + t.M21 * m.M10 + t.M22 * m.M20, \n                t.M20 * m.M01 + t.M21 * m.M11 + t.M22 * m.M21, \n                t.M20 * m.M02 + t.M21 * m.M12 + t.M22 * m.M22, \n                t.M20 * m.M03 + t.M21 * m.M13 + t.M22 * m.M23 + t.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34d\"/> with a <see cref=\"Euclidean3d\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M34d m, Euclidean3d e)\n        {\n            var t = (M34d)e;\n            return new M34d(\n                m.M00 * t.M00 + m.M01 * t.M10 + m.M02 * t.M20, \n                m.M00 * t.M01 + m.M01 * t.M11 + m.M02 * t.M21, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02 * t.M22, \n                m.M00 * t.M03 + m.M01 * t.M13 + m.M02 * t.M23 + m.M03,\n\n                m.M10 * t.M00 + m.M11 * t.M10 + m.M12 * t.M20, \n                m.M10 * t.M01 + m.M11 * t.M11 + m.M12 * t.M21, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12 * t.M22, \n                m.M10 * t.M03 + m.M11 * t.M13 + m.M12 * t.M23 + m.M13,\n\n                m.M20 * t.M00 + m.M21 * t.M10 + m.M22 * t.M20, \n                m.M20 * t.M01 + m.M21 * t.M11 + m.M22 * t.M21, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22 * t.M22, \n                m.M20 * t.M03 + m.M21 * t.M13 + m.M22 * t.M23 + m.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3d\"/> (as a 3x4 matrix) and a <see cref=\"M33d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Euclidean3d a, M33d m)\n            => new M34d(a.Rot * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> and a <see cref=\"Euclidean3d\"/> (as a 3x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M33d m, Euclidean3d a)\n            => new M34d(m * a.Rot, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3d\"/> and a <see cref=\"Rot3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d operator *(Euclidean3d e, Rot3d r)\n            => new Euclidean3d(e.Rot * r, e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> and a <see cref=\"Euclidean3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d operator *(Rot3d r, Euclidean3d e)\n            => new Euclidean3d(r * e.Rot, r * e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3d\"/> and a <see cref=\"Shift3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d operator *(Euclidean3d e, Shift3d s)\n        {\n            return new Euclidean3d(e.Rot, e.Rot * s.V + e.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> and a <see cref=\"Euclidean3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d operator *(Shift3d s, Euclidean3d e)\n        {\n            return new Euclidean3d(e.Rot, e.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Euclidean3d\"/> and a <see cref=\"Scale3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Euclidean3d r, Scale3d s)\n        {\n            var t = (M33d)r.Rot;\n            return new Affine3d(new M33d(\n                t.M00 * s.X, t.M01 * s.Y, t.M02 * s.Z, \n                t.M10 * s.X, t.M11 * s.Y, t.M12 * s.Z, \n                t.M20 * s.X, t.M21 * s.Y, t.M22 * s.Z),\n                r.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> and a <see cref=\"Euclidean3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Scale3d s, Euclidean3d r)\n        {\n            var t = (M33d)r.Rot;\n            return new Affine3d(new M33d(\n                t.M00 * s.X, t.M01 * s.X, t.M02 * s.X, \n                t.M10 * s.Y, t.M11 * s.Y, t.M12 * s.Y, \n                t.M20 * s.Z, t.M21 * s.Z, t.M22 * s.Z),\n                r.Trans * s.V);\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        public static bool operator ==(Euclidean3d r0, Euclidean3d r1)\n        {\n            return r0.Rot == r1.Rot && r0.Trans == r1.Trans;\n        }\n\n        public static bool operator !=(Euclidean3d r0, Euclidean3d r1)\n        {\n            return !(r0 == r1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3d\"/> transformation from a rotation matrix <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// The matrix <paramref name=\"rot\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d FromM33dAndV3d(M33d rot, V3d trans, double epsilon = 1e-12)\n            => new Euclidean3d(Rot3d.FromM33d(rot, epsilon), trans);\n\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3d\"/> transformation from a <see cref=\"M44d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components and its upper left 3x3 submatrix must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d FromM44d(M44d m, double epsilon = 1e-12)\n        {\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n            if (m.M33.IsTiny(epsilon)) throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM33dAndV3d(((M33d)m) / m.M33,\n                    m.C3.XYZ / m.M33,\n                    epsilon);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3d\"/> transformation from a <see cref=\"M34d\"/> matrix.\n        /// The left 3x3 submatrix of <paramref name=\"m\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d FromM34d(M34d m, double epsilon = 1e-12)\n        {\n            return FromM33dAndV3d(((M33d)m),\n                    m.C3.XYZ,\n                    epsilon);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3d\"/> transformation from a <see cref=\"Similarity3d\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d FromSimilarity3d(Similarity3d similarity, double epsilon = 1e-12)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            return similarity.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3d\"/> transformation from an <see cref=\"Affine3d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d FromAffine3d(Affine3d affine, double epsilon = 1e-12)\n            => FromM44d((M44d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3d\"/> transformation from a <see cref=\"Trafo3d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d FromTrafo3d(Trafo3d trafo, double epsilon = 1e-12)\n            => FromM44d(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3d\"/> transformation with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d Translation(double tX, double tY, double tZ)\n            => new Euclidean3d(tX, tY, tZ);\n\n        /// <summary>\n        /// Creates a <see cref=\"Euclidean3d\"/> transformation with the translational component given by a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d Translation(V3d vector)\n            => new Euclidean3d(vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Euclidean3d\"/> transformation with the translational component given by a <see cref=\"Shift3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d Translation(Shift3d shift)\n            => new Euclidean3d(shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d Rotation(Rot3d rot)\n            => new Euclidean3d(rot);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d Rotation(V3d normalizedAxis, double angleRadians)\n            => new Euclidean3d(Rot3d.Rotation(normalizedAxis, angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationInDegrees(V3d normalizedAxis, double angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationEuler(double rollInRadians, double pitchInRadians, double yawInRadians)\n            => new Euclidean3d(Rot3d.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationEulerInDegrees(double rollInDegrees, double pitchInDegrees, double yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationEuler(V3d rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationEulerInDegrees(V3d rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotateInto(V3d from, V3d into)\n            => new Euclidean3d(Rot3d.RotateInto(from, into));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationX(double angleRadians)\n            => new Euclidean3d(Rot3d.RotationX(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationXInDegrees(double angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationY(double angleRadians)\n            => new Euclidean3d(Rot3d.RotationY(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationYInDegrees(double angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationZ(double angleRadians)\n            => new Euclidean3d(Rot3d.RotationZ(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d RotationZInDegrees(double angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Euclidean3d e)\n            => new M34d((M33d)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Euclidean3d e)\n            => (M33d)e.Rot;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Euclidean3d e)\n        {\n            M44d rv = (M44d)e.Rot;\n            rv.C3 = e.Trans.XYZI;\n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity3d(Euclidean3d e)\n            => new Similarity3d(1, e);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3d(Euclidean3d e)\n            => new Affine3d((M33d)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3d(Euclidean3d e)\n            => new Trafo3d((M44d)e, (M44d)e.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean3f(Euclidean3d e)\n            => new Euclidean3f((Rot3f)e.Rot, (V3f)e.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Rot, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Euclidean3d other)\n            => Rot.Equals(other.Rot) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is Euclidean3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Rot, Trans);\n        }\n\n        public static Euclidean3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Euclidean3d(Rot3d.Parse(x[0]), V3d.Parse(x[1]));\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Euclidean\n    {\n        #region Normalize\n\n        /// <summary>\n        /// Returns a copy of a <see cref=\"Euclidean3d\"/> with its rotation quaternion normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d Normalized(Euclidean3d r)\n            => r.Normalized;\n\n        /// <summary>\n        /// Normalizes the rotation quaternion of a <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref Euclidean3d r)\n        {\n            r.Rot.Normalize();\n        }\n\n        #endregion\n\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d Inverse(Euclidean3d r)\n            => r.Inverse;\n\n        /// <summary>\n        /// Inverts this rigid transformation (multiplicative inverse).\n        /// this = [Rot^T,-Rot^T Trans]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Euclidean3d r)\n        {\n            r.Rot.Invert();\n            r.Trans = -r.Rot.Transform(r.Trans);\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> by an <see cref=\"Euclidean3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Euclidean3d a, V4d v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformDir(this Euclidean3d r, V3d v)\n        {\n            return r.Rot.Transform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformPos(this Euclidean3d r, V3d p)\n        {\n            return r.Rot.Transform(p) + r.Trans;\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformDir(this Euclidean3d r, V3d v)\n        {\n            return r.Rot.InvTransform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformPos(this Euclidean3d r, V3d p)\n        {\n            return r.Rot.InvTransform(p - r.Trans);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean3d r0, Euclidean3d r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean3d r0, Euclidean3d r1, double tol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, tol) && r0.Rot.ApproximateEquals(r1.Rot, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Euclidean3d r0, Euclidean3d r1, double angleTol, double posTol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, posTol) && r0.Rot.ApproximateEquals(r1.Rot, angleTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Euclidean_template.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action and = () => Out(\" && \");\n    //# Action or = () => Out(\" || \");\n    //# Action andLit = () => Out(\" and \");\n    //# var fields = new[] {\"X\", \"Y\", \"Z\", \"W\"};\n    //# foreach (var isDouble in new[] { false, true }) {\n    //# for (int n = 2; n <= 3; n++) {\n    //#   var m = n + 1;\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var xyz = \"XYZW\".Substring(0, n);\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Euclidean\" + n + tc;\n    //#   var type2 = \"Euclidean\" + n + tc2;\n    //#   var vnt = \"V\" + n + tc;\n    //#   var vnt2 = \"V\" + n + tc2;\n    //#   var vmt = \"V\" + m + tc;\n    //#   var mnnt = \"M\" + n + n + tc;\n    //#   var mmmt = \"M\" + m + m + tc;\n    //#   var mnmt = \"M\" + n + m + tc;\n    //#   var rotnt = \"Rot\" + n + tc;\n    //#   var rotnt2 = \"Rot\" + n + tc2;\n    //#   var trafont = \"Trafo\" + n + tc;\n    //#   var affinent = \"Affine\" + n + tc;\n    //#   var scalent = \"Scale\" + n + tc;\n    //#   var shiftnt = \"Shift\" + n + tc;\n    //#   var similaritynt = \"Similarity\" + n + tc;\n    //#   var nfields = fields.Take(n).ToArray();\n    //#   var mfields = fields.Take(m).ToArray();\n    //#   var fn = fields[n];\n    //#   var eps = isDouble ? \"1e-12\" : \"1e-5f\";\n    #region __type__\n\n    /// <summary>\n    /// Represents a Rigid Transformation (or Rigid Body Transformation) in __n__D that is composed of a\n    /// __n__D rotation Rot and a subsequent translation by a __n__D vector Trans.\n    /// This is also called an Euclidean Transformation and is a length preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>\n    {\n        [DataMember]\n        public __rotnt__ Rot;\n        [DataMember]\n        public __vnt__ Trans;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ e)\n        {\n            Rot = e.Rot;\n            Trans = e.Trans;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a <see cref=\"__type2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ e)\n        {\n            Rot = (__rotnt__)e.Rot;\n            Trans = (__vnt__)e.Trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__rotnt__ rot)\n        {\n            Rot = rot;\n            Trans = __vnt__.Zero;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__vnt__ trans)\n        {\n            Rot = __rotnt__.Identity;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a translation by (/*# nfields.ForEach(f => { */<paramref name=\"t__f__\"/>/*# }, comma);*/).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# nfields.ForEach(f => { */__ftype__ t__f__/*# }, comma);*/)\n        {\n            Rot = __rotnt__.Identity;\n            Trans = new __vnt__(/*# nfields.ForEach(f => { */t__f__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__rotnt__ rot, __vnt__ trans)\n        {\n            Rot = rot;\n            Trans = trans;\n        }\n\n        /// <summary>\n        /// Creates a rigid transformation from a rotation <paramref name=\"rot\"/> and a (subsequent) translation by (/*# nfields.ForEach(f => { */<paramref name=\"t__f__\"/>/*# }, comma);*/)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__rotnt__ rot, /*# nfields.ForEach(f => { */__ftype__ t__f__/*# }, comma);*/)\n        {\n            Rot = rot;\n            Trans = new __vnt__(/*# nfields.ForEach(f => { */t__f__/*# }, comma);*/);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__rotnt__.Identity, __vnt__.Zero);\n        }\n\n        #endregion\n\n        #region Properties\n\n        //# if (n > 2) {\n        /// <summary>\n        /// Returns a new version of this Euclidean transformation with a normalized rotation quaternion.\n        /// </summary>\n        public readonly __type__ Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(Rot.Normalized, Trans);\n        }\n        //# }\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Euclidean transformation.\n        /// [Rot^T,-Rot^T Trans]\n        /// </summary>\n        public readonly __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newR = Rot.Inverse;\n                return new __type__(newR, -newR.Transform(Trans));\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Euclidean transformations.\n        /// This concatenates the two rigid transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __type__ b)\n        {\n            //a.Rot * b.Rot, a.Trans + a.Rot * b.Trans\n            return new __type__(a.Rot * b.Rot, a.Trans + a.Rot.Transform(b.Trans));\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> vector by a <see cref=\"__type__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ operator *(__type__ e, __vmt__ v)\n        {\n            var rot = (__mnnt__)e.Rot;\n            return new __vmt__(/*# nfields.ForEach((fi, i) => { */\n                /*# mfields.ForEach((fj, j) => {\n                var aij = (j < n) ? \"rot.M\" + i + j : \"e.Trans.\" + fi;\n                */__aij__ * v.__fj__/*# }, add); }, comma);*/,\n                v.__fn__);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __m__x__m__ matrix) with a <see cref=\"__mmmt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mmmt__ operator *(__type__ e, __mmmt__ m)\n        {\n            var t = (__mnmt__)e;\n            return new __mmmt__(/*# n.ForEach(i => { m.ForEach(j => { */\n                /*# m.ForEach(k => {\n                */t.M__i____k__ * m.M__k____j__/*# }, add); }, comma); }, commaln);*/,\n\n                /*# m.ForEach(i => { */m.M__n____i__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mmmt__\"/> with a <see cref=\"__type__\"/> transformation (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mmmt__ operator *(__mmmt__ m, __type__ e)\n        {\n            var t = (__mnmt__)e;\n            return new __mmmt__(/*# m.ForEach(i => { m.ForEach(j => { */\n                /*# n.ForEach(k => {\n                */m.M__i____k__ * t.M__k____j__/*# }, add);\n                 if (j == n) {*/ + m.M__i____n__/*# } }, comma); }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __n__x__m__ matrix) with a <see cref=\"__mnmt__\"/> (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__type__ e, __mnmt__ m)\n        {\n            var t = (__mnmt__)e;\n            return new __mnmt__(/*# n.ForEach(i => { m.ForEach(j => { */\n                /*# n.ForEach(k => {\n                */t.M__i____k__ * m.M__k____j__/*# }, add);\n                 if (j == n) {*/ + t.M__i____n__/*# } }, comma); }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mnmt__\"/> with a <see cref=\"__type__\"/> transformation (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__mnmt__ m, __type__ e)\n        {\n            var t = (__mnmt__)e;\n            return new __mnmt__(/*# n.ForEach(i => { m.ForEach(j => { */\n                /*# n.ForEach(k => {\n                */m.M__i____k__ * t.M__k____j__/*# }, add);\n                 if (j == n) {*/ + m.M__i____n__/*# } }, comma); }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> (as a __n__x__m__ matrix) and a <see cref=\"__mnnt__\"/> (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__type__ a, __mnnt__ m)\n            => new __mnmt__(a.Rot * m, a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mnnt__\"/> and a <see cref=\"__type__\"/> (as a __n__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__mnnt__ m, __type__ a)\n            => new __mnmt__(m * a.Rot, m * a.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__rotnt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ e, __rotnt__ r)\n            => new __type__(e.Rot * r, e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__rotnt__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__rotnt__ r, __type__ e)\n            => new __type__(r * e.Rot, r * e.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__shiftnt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ e, __shiftnt__ s)\n        {\n            return new __type__(e.Rot, e.Rot * s.V + e.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__shiftnt__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__shiftnt__ s, __type__ e)\n        {\n            return new __type__(e.Rot, e.Trans + s.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__scalent__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affinent__ operator *(__type__ r, __scalent__ s)\n        {\n            var t = (__mnnt__)r.Rot;\n            return new __affinent__(new __mnnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */t.M__i____j__ * s.__fj__/*# }, comma); }, comma);*/),\n                r.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__scalent__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affinent__ operator *(__scalent__ s, __type__ r)\n        {\n            var t = (__mnnt__)r.Rot;\n            return new __affinent__(new __mnnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */t.M__i____j__ * s.__fi__/*# }, comma); }, comma);*/),\n                r.Trans * s.V);\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        public static bool operator ==(__type__ r0, __type__ r1)\n        {\n            return r0.Rot == r1.Rot && r0.Trans == r1.Trans;\n        }\n\n        public static bool operator !=(__type__ r0, __type__ r1)\n        {\n            return !(r0 == r1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a rotation matrix <paramref name=\"rot\"/> and a (subsequent) translation <paramref name=\"trans\"/>.\n        /// The matrix <paramref name=\"rot\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        //# if (n == 2) {\n        public static __type__ From__mnnt__And__vnt__(__mnnt__ rot, __vnt__ trans)\n            => new __type__(__rotnt__.From__mnnt__(rot), trans);\n\n        //# } else {\n        public static __type__ From__mnnt__And__vnt__(__mnnt__ rot, __vnt__ trans, __ftype__ epsilon = __eps__)\n            => new __type__(__rotnt__.From__mnnt__(rot, epsilon), trans);\n\n        //# }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__mmmt__\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components and its upper left __n__x__n__ submatrix must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mmmt__(__mmmt__ m, __ftype__ epsilon = __eps__)\n        {\n            if (!(/*#n.ForEach(j => {*/m.M__n____j__.IsTiny(epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n            if (m.M__n____n__.IsTiny(epsilon)) throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return From__mnnt__And__vnt__(((__mnnt__)m) / m.M__n____n__,\n                    m.C__n__.__xyz__ / m.M__n____n__/*# if (n > 2) {*/,\n                    epsilon/*# }*/);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__mnmt__\"/> matrix.\n        /// The left __n__x__n__ submatrix of <paramref name=\"m\"/> must be a valid rotation matrix.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mnmt__(__mnmt__ m, __ftype__ epsilon = __eps__)\n        {\n            return From__mnnt__And__vnt__(((__mnnt__)m),\n                    m.C__n__.__xyz__/*# if (n > 2) {*/,\n                    epsilon/*# }*/);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__similaritynt__\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__similaritynt__(__similaritynt__ similarity, __ftype__ epsilon = __eps__)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            return similarity.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from an <see cref=\"__affinent__\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__affinent__(__affinent__ affine, __ftype__ epsilon = __eps__)\n            => From__mmmt__((__mmmt__)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__trafont__\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__trafont__(__trafont__ trafo, __ftype__ epsilon = __eps__)\n            => From__mmmt__(trafo.Forward, epsilon);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation with the translational component given by __n__ scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(/*# nfields.ForEach(f => { */__ftype__ t__f__/*# }, comma); */)\n            => new __type__(/*# nfields.ForEach(f => { */t__f__/*# }, comma); */);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation with the translational component given by a <see cref=\"__vnt__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(__vnt__ vector)\n            => new __type__(vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"__type__\"/> transformation with the translational component given by a <see cref=\"__shiftnt__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(__shiftnt__ shift)\n            => new __type__(shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"__rotnt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__rotnt__ rot)\n            => new __type__(rot);\n\n        //# if (n == 2) {\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__ftype__ angleInRadians)\n            => new __type__(new __rotnt__(angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__ftype__ angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        //# } else if (n == 3) {\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__vnt__ normalizedAxis, __ftype__ angleRadians)\n            => new __type__(__rotnt__.Rotation(normalizedAxis, angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__vnt__ normalizedAxis, __ftype__ angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__ftype__ rollInRadians, __ftype__ pitchInRadians, __ftype__ yawInRadians)\n            => new __type__(__rotnt__.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__ftype__ rollInDegrees, __ftype__ pitchInDegrees, __ftype__ yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__vnt__ rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__vnt__ rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotateInto(__vnt__ from, __vnt__ into)\n            => new __type__(__rotnt__.RotateInto(from, into));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationX(__ftype__ angleRadians)\n            => new __type__(__rotnt__.RotationX(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationXInDegrees(__ftype__ angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationY(__ftype__ angleRadians)\n            => new __type__(__rotnt__.RotationY(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationYInDegrees(__ftype__ angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZ(__ftype__ angleRadians)\n            => new __type__(__rotnt__.RotationZ(angleRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZInDegrees(__ftype__ angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        //# }\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mnmt__(__type__ e)\n            => new __mnmt__((__mnnt__)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mnnt__(__type__ e)\n            => (__mnnt__)e.Rot;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mmmt__(__type__ e)\n        {\n            __mmmt__ rv = (__mmmt__)e.Rot;\n            rv.C__n__ = e.Trans.__xyz__I;\n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __similaritynt__(__type__ e)\n            => new __similaritynt__(1, e);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __affinent__(__type__ e)\n            => new __affinent__((__mnnt__)e.Rot, e.Trans);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __trafont__(__type__ e)\n            => new __trafont__((__mmmt__)e, (__mmmt__)e.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ e)\n            => new __type2__((__rotnt2__)e.Rot, (__vnt2__)e.Trans);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Rot, Trans);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Rot.Equals(other.Rot) && Trans.Equals(other.Trans);\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Rot, Trans);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__rotnt__.Parse(x[0]), __vnt__.Parse(x[1]));\n        }\n\n        #endregion\n\n    }\n\n    public static partial class Euclidean\n    {\n        //# if (n > 2) {\n        #region Normalize\n\n        /// <summary>\n        /// Returns a copy of a <see cref=\"__type__\"/> with its rotation quaternion normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Normalized(__type__ r)\n            => r.Normalized;\n\n        /// <summary>\n        /// Normalizes the rotation quaternion of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref __type__ r)\n        {\n            r.Rot.Normalize();\n        }\n\n        #endregion\n\n        //# }\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ r)\n            => r.Inverse;\n\n        /// <summary>\n        /// Inverts this rigid transformation (multiplicative inverse).\n        /// this = [Rot^T,-Rot^T Trans]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref __type__ r)\n        {\n            r.Rot.Invert();\n            r.Trans = -r.Rot.Transform(r.Trans);\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> by an <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ Transform(this __type__ a, __vmt__ v)\n            => a * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.__fn__ is presumed 0.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformDir(this __type__ r, __vnt__ v)\n        {\n            return r.Rot.Transform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformPos(this __type__ r, __vnt__ p)\n        {\n            return r.Rot.Transform(p) + r.Trans;\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.__fn__ is presumed 0.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ InvTransformDir(this __type__ r, __vnt__ v)\n        {\n            return r.Rot.InvTransform(v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by the inverse of the rigid transformation r.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ InvTransformPos(this __type__ r, __vnt__ p)\n        {\n            return r.Rot.InvTransform(p - r.Trans);\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ r0, __type__ r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ r0, __type__ r1, __ftype__ tol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, tol) && r0.Rot.ApproximateEquals(r1.Rot, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ r0, __type__ r1, __ftype__ angleTol, __ftype__ posTol)\n        {\n            return ApproximateEquals(r0.Trans, r1.Trans, posTol) && r0.Rot.ApproximateEquals(r1.Rot, angleTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/M33_auto.cs",
    "content": "using System;\nusing System.Text;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    public partial struct M33f\n    {\n        #region Coordinate-System Transforms\n\n        /// <summary>\n        /// Creates an orthonormal basis from the given normal as z-axis.\n        /// The resulting matrix transforms from the local to the global coordinate system.\n        /// The normal is expected to be normalized.\n        /// \n        /// The implementation is based on:\n        /// Building an Orthonormal Basis, Revisited, by Duff et al. 2017\n        /// </summary>\n        public static M33f NormalFrame(V3f n)\n        {\n            var sg = n.Z >= 0 ? 1 : -1; // original uses copysign(1.0, n.Z) -> not the same as sign where 0 -> 0\n            var a = -1 / (sg + n.Z);\n            var b = n.X * n.Y * a;\n            // column 0: [1 + sg * n.X * n.X * a, sg * b, -sg * n.X]\n            // column 1: [b, sg + n.Y * n.Y * a, -n.Y]\n            // column 2: n\n            return new M33f(1 + sg * n.X * n.X * a, b, n.X,\n                                 sg * b, sg + n.Y * n.Y * a, n.Y,\n                                 -sg * n.X, -n.Y, n.Z);\n        }        \n\n        /// <summary>\n        /// Computes from a <see cref=\"V3f\"/> normal the transformation matrix\n        /// from the local coordinate system where the normal is the z-axis to\n        /// the global coordinate system.\n        /// </summary>\n        /// <param name=\"normal\">The normal vector of the new ground plane.</param>\n        public static M33f NormalFrameLocal2Global(V3f normal)\n        {\n            V3f min;\n            double x = Fun.Abs(normal.X);\n            double y = Fun.Abs(normal.Y);\n            double z = Fun.Abs(normal.Z);\n\n            if (x < y)\n            {\n                if (x < z) { min = V3f.XAxis; } else { min = V3f.ZAxis; }\n            }\n            else\n            {\n                if (y < z) { min = V3f.YAxis; } else { min = V3f.ZAxis; }\n            }\n\n            var xVec = Vec.Cross(normal, min);\n            xVec.Normalize(); // this is now guaranteed to be normal to the input normal\n            var yVec = Vec.Cross(normal, xVec);\n            yVec.Normalize();\n            var zVec = normal;\n            zVec.Normalize();\n\n            return new M33f(xVec.X, yVec.X, zVec.X,\n                            xVec.Y, yVec.Y, zVec.Y,\n                            xVec.Z, yVec.Z, zVec.Z);\n        }\n\n        #endregion\n    }\n\n    public partial struct M33d\n    {\n        #region Coordinate-System Transforms\n\n        /// <summary>\n        /// Creates an orthonormal basis from the given normal as z-axis.\n        /// The resulting matrix transforms from the local to the global coordinate system.\n        /// The normal is expected to be normalized.\n        /// \n        /// The implementation is based on:\n        /// Building an Orthonormal Basis, Revisited, by Duff et al. 2017\n        /// </summary>\n        public static M33d NormalFrame(V3d n)\n        {\n            var sg = n.Z >= 0 ? 1 : -1; // original uses copysign(1.0, n.Z) -> not the same as sign where 0 -> 0\n            var a = -1 / (sg + n.Z);\n            var b = n.X * n.Y * a;\n            // column 0: [1 + sg * n.X * n.X * a, sg * b, -sg * n.X]\n            // column 1: [b, sg + n.Y * n.Y * a, -n.Y]\n            // column 2: n\n            return new M33d(1 + sg * n.X * n.X * a, b, n.X,\n                                 sg * b, sg + n.Y * n.Y * a, n.Y,\n                                 -sg * n.X, -n.Y, n.Z);\n        }        \n\n        /// <summary>\n        /// Computes from a <see cref=\"V3d\"/> normal the transformation matrix\n        /// from the local coordinate system where the normal is the z-axis to\n        /// the global coordinate system.\n        /// </summary>\n        /// <param name=\"normal\">The normal vector of the new ground plane.</param>\n        public static M33d NormalFrameLocal2Global(V3d normal)\n        {\n            V3d min;\n            double x = Fun.Abs(normal.X);\n            double y = Fun.Abs(normal.Y);\n            double z = Fun.Abs(normal.Z);\n\n            if (x < y)\n            {\n                if (x < z) { min = V3d.XAxis; } else { min = V3d.ZAxis; }\n            }\n            else\n            {\n                if (y < z) { min = V3d.YAxis; } else { min = V3d.ZAxis; }\n            }\n\n            var xVec = Vec.Cross(normal, min);\n            xVec.Normalize(); // this is now guaranteed to be normal to the input normal\n            var yVec = Vec.Cross(normal, xVec);\n            yVec.Normalize();\n            var zVec = normal;\n            zVec.Normalize();\n\n            return new M33d(xVec.X, yVec.X, zVec.X,\n                            xVec.Y, yVec.Y, zVec.Y,\n                            xVec.Z, yVec.Z, zVec.Z);\n        }\n\n        #endregion\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/M33_template.cs",
    "content": "using System;\nusing System.Text;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ft = isDouble ? \"double\" : \"float\";\n    //#   var x2t = isDouble ? \"2d\" : \"2f\";\n    //#   var x3t = isDouble ? \"3d\" : \"3f\";\n    //#   var x4t = isDouble ? \"4d\" : \"4f\";\n    public partial struct M3__x3t__\n    {\n        #region Coordinate-System Transforms\n\n        /// <summary>\n        /// Creates an orthonormal basis from the given normal as z-axis.\n        /// The resulting matrix transforms from the local to the global coordinate system.\n        /// The normal is expected to be normalized.\n        /// \n        /// The implementation is based on:\n        /// Building an Orthonormal Basis, Revisited, by Duff et al. 2017\n        /// </summary>\n        public static M3__x3t__ NormalFrame(V__x3t__ n)\n        {\n            var sg = n.Z >= 0 ? 1 : -1; // original uses copysign(1.0, n.Z) -> not the same as sign where 0 -> 0\n            var a = -1 / (sg + n.Z);\n            var b = n.X * n.Y * a;\n            // column 0: [1 + sg * n.X * n.X * a, sg * b, -sg * n.X]\n            // column 1: [b, sg + n.Y * n.Y * a, -n.Y]\n            // column 2: n\n            return new M3__x3t__(1 + sg * n.X * n.X * a, b, n.X,\n                                 sg * b, sg + n.Y * n.Y * a, n.Y,\n                                 -sg * n.X, -n.Y, n.Z);\n        }        \n\n        /// <summary>\n        /// Computes from a <see cref=\"V__x3t__\"/> normal the transformation matrix\n        /// from the local coordinate system where the normal is the z-axis to\n        /// the global coordinate system.\n        /// </summary>\n        /// <param name=\"normal\">The normal vector of the new ground plane.</param>\n        public static M3__x3t__ NormalFrameLocal2Global(V__x3t__ normal)\n        {\n            V__x3t__ min;\n            double x = Fun.Abs(normal.X);\n            double y = Fun.Abs(normal.Y);\n            double z = Fun.Abs(normal.Z);\n\n            if (x < y)\n            {\n                if (x < z) { min = V__x3t__.XAxis; } else { min = V__x3t__.ZAxis; }\n            }\n            else\n            {\n                if (y < z) { min = V__x3t__.YAxis; } else { min = V__x3t__.ZAxis; }\n            }\n\n            var xVec = Vec.Cross(normal, min);\n            xVec.Normalize(); // this is now guaranteed to be normal to the input normal\n            var yVec = Vec.Cross(normal, xVec);\n            yVec.Normalize();\n            var zVec = normal;\n            zVec.Normalize();\n\n            return new M3__x3t__(xVec.X, yVec.X, zVec.X,\n                            xVec.Y, yVec.Y, zVec.Y,\n                            xVec.Z, yVec.Z, zVec.Z);\n        }\n\n        #endregion\n    }\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/M44_auto.cs",
    "content": "using System;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    #region M44f\n\n    public partial struct M44f\n    {\n        #region Coordinate-System Transforms\n\n        /// <summary>\n        /// Computes from a <see cref=\"V3f\"/> point (origin) and\n        /// a <see cref=\"V3f\"/> normal the transformation matrix\n        /// and its inverse.\n        /// </summary>\n        /// <param name=\"origin\">The point which will become the new origin.</param>\n        /// <param name=\"normal\">The normal vector of the new ground plane.</param>\n        /// <param name=\"local2global\">A <see cref=\"M44f\"/>The trafo from local to global system.</param>\n        /// <param name=\"global2local\">A <see cref=\"M44f\"/>The trafofrom global to local system.</param>\n        public static void NormalFrame(V3f origin, V3f normal,\n            out M44f local2global, out M44f global2local\n            )\n        {\n            V3f min;\n            float x = Fun.Abs(normal.X);\n            float y = Fun.Abs(normal.Y);\n            float z = Fun.Abs(normal.Z);\n\n            if (x < y)\n            {\n                if (x < z) { min = V3f.XAxis; } else { min = V3f.ZAxis; }\n            }\n            else\n            {\n                if (y < z) { min = V3f.YAxis; } else { min = V3f.ZAxis; }\n            }\n\n            V3f xVec = Vec.Cross(normal, min);\n            xVec.Normalize(); // this is now guaranteed to be normal to the input normal\n            V3f yVec = Vec.Cross(normal, xVec);\n            yVec.Normalize();\n            V3f zVec = normal;\n            zVec.Normalize();\n\n            local2global = new M44f(xVec.X, yVec.X, zVec.X, origin.X,\n                                    xVec.Y, yVec.Y, zVec.Y, origin.Y,\n                                    xVec.Z, yVec.Z, zVec.Z, origin.Z,\n                                    0, 0, 0, 1);\n\n            M44f mat = new M44f(xVec.X, xVec.Y, xVec.Z, 0,\n                                yVec.X, yVec.Y, yVec.Z, 0,\n                                zVec.X, zVec.Y, zVec.Z, 0,\n                                0, 0, 0, 1);\n\n            var shift = M44f.Translation(-origin);\n            global2local = mat * shift;\n        }\n\n\n        /// <summary>\n        /// Computes a Coordiante Frame Transformation (Basis) from current CS into\n        /// the (X, Y, Z)-System at a given Origin.\n        /// Note: you can use it, to transform from RH to LH and vice-versa, all depending\n        /// how you will specifie your new basis-vectors.\n        /// </summary>\n        /// <param name=\"xVec\">New X Vector</param>\n        /// <param name=\"yVec\">New Y Vector</param>\n        /// <param name=\"zVec\">New Z vector</param>\n        /// <param name=\"oVec\">New Origin.</param>\n        /// <param name=\"viewTrafo\"></param>\n        /// <param name=\"viewTrafoInverse\"></param>\n        public static void CoordinateFrameTransform(V3f xVec, V3f yVec, V3f zVec, V3f oVec,\n            out M44f viewTrafo, out M44f viewTrafoInverse)\n        {\n            oVec = -oVec;\n            viewTrafo = new M44f(\n                xVec.X, xVec.Y, xVec.Z, xVec.X * oVec.X + xVec.Y * oVec.Y + xVec.Z * oVec.Z,\n                yVec.X, yVec.Y, yVec.Z, yVec.X * oVec.X + yVec.Y * oVec.Y + yVec.Z * oVec.Z,\n                zVec.X, zVec.Y, zVec.Z, zVec.X * oVec.X + zVec.Y * oVec.Y + zVec.Z * oVec.Z,\n                0, 0, 0, 1\n                );\n            viewTrafoInverse = new M44f(\n                xVec.X, yVec.X, zVec.X, -oVec.X,\n                xVec.Y, yVec.Y, zVec.Y, -oVec.Y,\n                xVec.Z, yVec.Z, zVec.Z, -oVec.Z,\n                0, 0, 0, 1\n                );\n        }\n\n        /// <summary>\n        ///  Provides perspective projection matrix in terms of the vertical field of view angle a and the aspect ratio r.\n        /// </summary>\n        public static M44f PerspectiveProjectionTransformRH(float a, float r, float n, float f)\n        {\n            //F / r     0      0      0\n            //  0       F      0      0\n            //  0       0      A      B\n            //  0       0      -1     0\n            float F = 1 / Fun.Tan(a / 2);\n            float A = f / (n - f);\n            float B = f * n / (n - f);\n\n            M44f P = new M44f(\n                F / r, 0, 0, 0,\n                0, F, 0, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        /// <summary>\n        ///  Provides perspective projection matrix. \n        ///  The parameters describe the dimensions of the view volume.\n        /// </summary>\n        public static M44f PerspectiveProjectionTransformRH(V2f size, float n, float f)\n        {\n            float w = size.X;\n            float h = size.Y;\n            // Fx      0      0      0\n            //  0      Fy     0      0\n            //  0      0      A      B\n            //  0      0      -1     0\n            float Fx = 2 * n / w;\n            float Fy = 2 * n / h;\n            float A = f / (n - f);\n            float B = n * f / (n - f);\n            M44f P = new M44f(\n                Fx, 0, 0, 0,\n                0, Fy, 0, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        /// <summary>\n        /// Builds a customized, right-handed perspective Off-Center projection matrix.\n        /// </summary>\n        public static M44f PerspectiveProjectionTransformRH(float l, float r, float t, float b, float n, float f)\n        {\n            // Fx      0      Sx     0\n            //  0      Fy     Sy     0\n            //  0      0      A      B\n            //  0      0      -1     0\n            float Fx = 2 * n / (r - l);\n            float Fy = 2 * n / (t - b);\n            float Sx = (l + r) / (r - l);\n            float Sy = (t + b) / (t - b);\n            float A = f / (n - f);\n            float B = n * f / (n - f);\n\n            M44f P = new M44f(\n                Fx, 0, Sx, 0,\n                0, Fy, Sy, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        #endregion\n\n        #region Static creators\n\n        /// <summary>\n        /// Returns the matrix that transforms from the coordinate system\n        /// specified by the basis into the world cordinate system.\n        /// </summary>\n        public static M44f FromBasis(V3f xAxis, V3f yAxis, V3f zAxis, V3f origin)\n        {\n            return new M44f(\n                xAxis.X, yAxis.X, zAxis.X, origin.X,\n                xAxis.Y, yAxis.Y, zAxis.Y, origin.Y,\n                xAxis.Z, yAxis.Z, zAxis.Z, origin.Z,\n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a view tranformation from the given vectors.\n        /// Transformation from world- into view-space.\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"right\">Right vector of the view-plane</param>\n        /// <param name=\"up\">Up vector of the view-plane</param>\n        /// <param name=\"normal\">Normal vector of the view-plane. This vector is suppsoed to point in view-direction for a left-handed view transformation and in opposit direction in the right-handed case.</param>\n        /// <returns>The view transformation</returns>\n        public static M44f ViewTrafo(V3f location, V3f right, V3f up, V3f normal)\n        {\n            return new M44f(\n                    right.X,  right.Y,  right.Z,  -location.Dot(right),\n                    up.X,     up.Y,     up.Z,     -location.Dot(up),\n                    normal.X, normal.Y, normal.Z, -location.Dot(normal),\n                    0,        0,        0,         1\n                );\n        }\n\n        /// <summary>\n        /// Creates a inverse view tranformation from the given vectors.\n        /// Transformation from view- into world-space.\n        /// The implementation is the same as FromBasis(right, up, normal, location)\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"right\">Right vector of the view-plane</param>\n        /// <param name=\"up\">Up vector of the view-plane</param>\n        /// <param name=\"normal\">Normal vector of the view-plane. This vector is suppsoed to point in view-direction for a left-handed view transformation and in opposit direction in the right-handed case.</param>\n        /// <returns>The inverse view transformation</returns>\n        public static M44f InvViewTrafo(V3f location, V3f right, V3f up, V3f normal)\n        {\n            return new M44f(\n                    right.X, up.X, normal.X, location.X,\n                    right.Y, up.Y, normal.Y, location.Y,\n                    right.Z, up.Z, normal.Z, location.Z,\n                    0, 0, 0, 1\n                );\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M44d\n\n    public partial struct M44d\n    {\n        #region Coordinate-System Transforms\n\n        /// <summary>\n        /// Computes from a <see cref=\"V3d\"/> point (origin) and\n        /// a <see cref=\"V3d\"/> normal the transformation matrix\n        /// and its inverse.\n        /// </summary>\n        /// <param name=\"origin\">The point which will become the new origin.</param>\n        /// <param name=\"normal\">The normal vector of the new ground plane.</param>\n        /// <param name=\"local2global\">A <see cref=\"M44d\"/>The trafo from local to global system.</param>\n        /// <param name=\"global2local\">A <see cref=\"M44d\"/>The trafofrom global to local system.</param>\n        public static void NormalFrame(V3d origin, V3d normal,\n            out M44d local2global, out M44d global2local\n            )\n        {\n            V3d min;\n            double x = Fun.Abs(normal.X);\n            double y = Fun.Abs(normal.Y);\n            double z = Fun.Abs(normal.Z);\n\n            if (x < y)\n            {\n                if (x < z) { min = V3d.XAxis; } else { min = V3d.ZAxis; }\n            }\n            else\n            {\n                if (y < z) { min = V3d.YAxis; } else { min = V3d.ZAxis; }\n            }\n\n            V3d xVec = Vec.Cross(normal, min);\n            xVec.Normalize(); // this is now guaranteed to be normal to the input normal\n            V3d yVec = Vec.Cross(normal, xVec);\n            yVec.Normalize();\n            V3d zVec = normal;\n            zVec.Normalize();\n\n            local2global = new M44d(xVec.X, yVec.X, zVec.X, origin.X,\n                                    xVec.Y, yVec.Y, zVec.Y, origin.Y,\n                                    xVec.Z, yVec.Z, zVec.Z, origin.Z,\n                                    0, 0, 0, 1);\n\n            M44d mat = new M44d(xVec.X, xVec.Y, xVec.Z, 0,\n                                yVec.X, yVec.Y, yVec.Z, 0,\n                                zVec.X, zVec.Y, zVec.Z, 0,\n                                0, 0, 0, 1);\n\n            var shift = M44d.Translation(-origin);\n            global2local = mat * shift;\n        }\n\n\n        /// <summary>\n        /// Computes a Coordiante Frame Transformation (Basis) from current CS into\n        /// the (X, Y, Z)-System at a given Origin.\n        /// Note: you can use it, to transform from RH to LH and vice-versa, all depending\n        /// how you will specifie your new basis-vectors.\n        /// </summary>\n        /// <param name=\"xVec\">New X Vector</param>\n        /// <param name=\"yVec\">New Y Vector</param>\n        /// <param name=\"zVec\">New Z vector</param>\n        /// <param name=\"oVec\">New Origin.</param>\n        /// <param name=\"viewTrafo\"></param>\n        /// <param name=\"viewTrafoInverse\"></param>\n        public static void CoordinateFrameTransform(V3d xVec, V3d yVec, V3d zVec, V3d oVec,\n            out M44d viewTrafo, out M44d viewTrafoInverse)\n        {\n            oVec = -oVec;\n            viewTrafo = new M44d(\n                xVec.X, xVec.Y, xVec.Z, xVec.X * oVec.X + xVec.Y * oVec.Y + xVec.Z * oVec.Z,\n                yVec.X, yVec.Y, yVec.Z, yVec.X * oVec.X + yVec.Y * oVec.Y + yVec.Z * oVec.Z,\n                zVec.X, zVec.Y, zVec.Z, zVec.X * oVec.X + zVec.Y * oVec.Y + zVec.Z * oVec.Z,\n                0, 0, 0, 1\n                );\n            viewTrafoInverse = new M44d(\n                xVec.X, yVec.X, zVec.X, -oVec.X,\n                xVec.Y, yVec.Y, zVec.Y, -oVec.Y,\n                xVec.Z, yVec.Z, zVec.Z, -oVec.Z,\n                0, 0, 0, 1\n                );\n        }\n\n        /// <summary>\n        ///  Provides perspective projection matrix in terms of the vertical field of view angle a and the aspect ratio r.\n        /// </summary>\n        public static M44d PerspectiveProjectionTransformRH(double a, double r, double n, double f)\n        {\n            //F / r     0      0      0\n            //  0       F      0      0\n            //  0       0      A      B\n            //  0       0      -1     0\n            double F = 1 / Fun.Tan(a / 2);\n            double A = f / (n - f);\n            double B = f * n / (n - f);\n\n            M44d P = new M44d(\n                F / r, 0, 0, 0,\n                0, F, 0, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        /// <summary>\n        ///  Provides perspective projection matrix. \n        ///  The parameters describe the dimensions of the view volume.\n        /// </summary>\n        public static M44d PerspectiveProjectionTransformRH(V2d size, double n, double f)\n        {\n            double w = size.X;\n            double h = size.Y;\n            // Fx      0      0      0\n            //  0      Fy     0      0\n            //  0      0      A      B\n            //  0      0      -1     0\n            double Fx = 2 * n / w;\n            double Fy = 2 * n / h;\n            double A = f / (n - f);\n            double B = n * f / (n - f);\n            M44d P = new M44d(\n                Fx, 0, 0, 0,\n                0, Fy, 0, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        /// <summary>\n        /// Builds a customized, right-handed perspective Off-Center projection matrix.\n        /// </summary>\n        public static M44d PerspectiveProjectionTransformRH(double l, double r, double t, double b, double n, double f)\n        {\n            // Fx      0      Sx     0\n            //  0      Fy     Sy     0\n            //  0      0      A      B\n            //  0      0      -1     0\n            double Fx = 2 * n / (r - l);\n            double Fy = 2 * n / (t - b);\n            double Sx = (l + r) / (r - l);\n            double Sy = (t + b) / (t - b);\n            double A = f / (n - f);\n            double B = n * f / (n - f);\n\n            M44d P = new M44d(\n                Fx, 0, Sx, 0,\n                0, Fy, Sy, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        #endregion\n\n        #region Static creators\n\n        /// <summary>\n        /// Returns the matrix that transforms from the coordinate system\n        /// specified by the basis into the world cordinate system.\n        /// </summary>\n        public static M44d FromBasis(V3d xAxis, V3d yAxis, V3d zAxis, V3d origin)\n        {\n            return new M44d(\n                xAxis.X, yAxis.X, zAxis.X, origin.X,\n                xAxis.Y, yAxis.Y, zAxis.Y, origin.Y,\n                xAxis.Z, yAxis.Z, zAxis.Z, origin.Z,\n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a view tranformation from the given vectors.\n        /// Transformation from world- into view-space.\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"right\">Right vector of the view-plane</param>\n        /// <param name=\"up\">Up vector of the view-plane</param>\n        /// <param name=\"normal\">Normal vector of the view-plane. This vector is suppsoed to point in view-direction for a left-handed view transformation and in opposit direction in the right-handed case.</param>\n        /// <returns>The view transformation</returns>\n        public static M44d ViewTrafo(V3d location, V3d right, V3d up, V3d normal)\n        {\n            return new M44d(\n                    right.X,  right.Y,  right.Z,  -location.Dot(right),\n                    up.X,     up.Y,     up.Z,     -location.Dot(up),\n                    normal.X, normal.Y, normal.Z, -location.Dot(normal),\n                    0,        0,        0,         1\n                );\n        }\n\n        /// <summary>\n        /// Creates a inverse view tranformation from the given vectors.\n        /// Transformation from view- into world-space.\n        /// The implementation is the same as FromBasis(right, up, normal, location)\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"right\">Right vector of the view-plane</param>\n        /// <param name=\"up\">Up vector of the view-plane</param>\n        /// <param name=\"normal\">Normal vector of the view-plane. This vector is suppsoed to point in view-direction for a left-handed view transformation and in opposit direction in the right-handed case.</param>\n        /// <returns>The inverse view transformation</returns>\n        public static M44d InvViewTrafo(V3d location, V3d right, V3d up, V3d normal)\n        {\n            return new M44d(\n                    right.X, up.X, normal.X, location.X,\n                    right.Y, up.Y, normal.Y, location.Y,\n                    right.Z, up.Z, normal.Z, location.Z,\n                    0, 0, 0, 1\n                );\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/M44_template.cs",
    "content": "﻿using System;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ft = isDouble ? \"double\" : \"float\";\n    //#   var x2t = isDouble ? \"2d\" : \"2f\";\n    //#   var x3t = isDouble ? \"3d\" : \"3f\";\n    //#   var x4t = isDouble ? \"4d\" : \"4f\";\n    #region M4__x4t__\n\n    public partial struct M4__x4t__\n    {\n        #region Coordinate-System Transforms\n\n        /// <summary>\n        /// Computes from a <see cref=\"V__x3t__\"/> point (origin) and\n        /// a <see cref=\"V__x3t__\"/> normal the transformation matrix\n        /// and its inverse.\n        /// </summary>\n        /// <param name=\"origin\">The point which will become the new origin.</param>\n        /// <param name=\"normal\">The normal vector of the new ground plane.</param>\n        /// <param name=\"local2global\">A <see cref=\"M4__x4t__\"/>The trafo from local to global system.</param>\n        /// <param name=\"global2local\">A <see cref=\"M4__x4t__\"/>The trafofrom global to local system.</param>\n        public static void NormalFrame(V__x3t__ origin, V__x3t__ normal,\n            out M4__x4t__ local2global, out M4__x4t__ global2local\n            )\n        {\n            V__x3t__ min;\n            __ft__ x = Fun.Abs(normal.X);\n            __ft__ y = Fun.Abs(normal.Y);\n            __ft__ z = Fun.Abs(normal.Z);\n\n            if (x < y)\n            {\n                if (x < z) { min = V__x3t__.XAxis; } else { min = V__x3t__.ZAxis; }\n            }\n            else\n            {\n                if (y < z) { min = V__x3t__.YAxis; } else { min = V__x3t__.ZAxis; }\n            }\n\n            V__x3t__ xVec = Vec.Cross(normal, min);\n            xVec.Normalize(); // this is now guaranteed to be normal to the input normal\n            V__x3t__ yVec = Vec.Cross(normal, xVec);\n            yVec.Normalize();\n            V__x3t__ zVec = normal;\n            zVec.Normalize();\n\n            local2global = new M4__x4t__(xVec.X, yVec.X, zVec.X, origin.X,\n                                    xVec.Y, yVec.Y, zVec.Y, origin.Y,\n                                    xVec.Z, yVec.Z, zVec.Z, origin.Z,\n                                    0, 0, 0, 1);\n\n            M4__x4t__ mat = new M4__x4t__(xVec.X, xVec.Y, xVec.Z, 0,\n                                yVec.X, yVec.Y, yVec.Z, 0,\n                                zVec.X, zVec.Y, zVec.Z, 0,\n                                0, 0, 0, 1);\n\n            var shift = M4__x4t__.Translation(-origin);\n            global2local = mat * shift;\n        }\n\n\n        /// <summary>\n        /// Computes a Coordiante Frame Transformation (Basis) from current CS into\n        /// the (X, Y, Z)-System at a given Origin.\n        /// Note: you can use it, to transform from RH to LH and vice-versa, all depending\n        /// how you will specifie your new basis-vectors.\n        /// </summary>\n        /// <param name=\"xVec\">New X Vector</param>\n        /// <param name=\"yVec\">New Y Vector</param>\n        /// <param name=\"zVec\">New Z vector</param>\n        /// <param name=\"oVec\">New Origin.</param>\n        /// <param name=\"viewTrafo\"></param>\n        /// <param name=\"viewTrafoInverse\"></param>\n        public static void CoordinateFrameTransform(V__x3t__ xVec, V__x3t__ yVec, V__x3t__ zVec, V__x3t__ oVec,\n            out M4__x4t__ viewTrafo, out M4__x4t__ viewTrafoInverse)\n        {\n            oVec = -oVec;\n            viewTrafo = new M4__x4t__(\n                xVec.X, xVec.Y, xVec.Z, xVec.X * oVec.X + xVec.Y * oVec.Y + xVec.Z * oVec.Z,\n                yVec.X, yVec.Y, yVec.Z, yVec.X * oVec.X + yVec.Y * oVec.Y + yVec.Z * oVec.Z,\n                zVec.X, zVec.Y, zVec.Z, zVec.X * oVec.X + zVec.Y * oVec.Y + zVec.Z * oVec.Z,\n                0, 0, 0, 1\n                );\n            viewTrafoInverse = new M4__x4t__(\n                xVec.X, yVec.X, zVec.X, -oVec.X,\n                xVec.Y, yVec.Y, zVec.Y, -oVec.Y,\n                xVec.Z, yVec.Z, zVec.Z, -oVec.Z,\n                0, 0, 0, 1\n                );\n        }\n\n        /// <summary>\n        ///  Provides perspective projection matrix in terms of the vertical field of view angle a and the aspect ratio r.\n        /// </summary>\n        public static M4__x4t__ PerspectiveProjectionTransformRH(__ft__ a, __ft__ r, __ft__ n, __ft__ f)\n        {\n            //F / r     0      0      0\n            //  0       F      0      0\n            //  0       0      A      B\n            //  0       0      -1     0\n            __ft__ F = 1 / Fun.Tan(a / 2);\n            __ft__ A = f / (n - f);\n            __ft__ B = f * n / (n - f);\n\n            M4__x4t__ P = new M4__x4t__(\n                F / r, 0, 0, 0,\n                0, F, 0, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        /// <summary>\n        ///  Provides perspective projection matrix. \n        ///  The parameters describe the dimensions of the view volume.\n        /// </summary>\n        public static M4__x4t__ PerspectiveProjectionTransformRH(V__x2t__ size, __ft__ n, __ft__ f)\n        {\n            __ft__ w = size.X;\n            __ft__ h = size.Y;\n            // Fx      0      0      0\n            //  0      Fy     0      0\n            //  0      0      A      B\n            //  0      0      -1     0\n            __ft__ Fx = 2 * n / w;\n            __ft__ Fy = 2 * n / h;\n            __ft__ A = f / (n - f);\n            __ft__ B = n * f / (n - f);\n            M4__x4t__ P = new M4__x4t__(\n                Fx, 0, 0, 0,\n                0, Fy, 0, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        /// <summary>\n        /// Builds a customized, right-handed perspective Off-Center projection matrix.\n        /// </summary>\n        public static M4__x4t__ PerspectiveProjectionTransformRH(__ft__ l, __ft__ r, __ft__ t, __ft__ b, __ft__ n, __ft__ f)\n        {\n            // Fx      0      Sx     0\n            //  0      Fy     Sy     0\n            //  0      0      A      B\n            //  0      0      -1     0\n            __ft__ Fx = 2 * n / (r - l);\n            __ft__ Fy = 2 * n / (t - b);\n            __ft__ Sx = (l + r) / (r - l);\n            __ft__ Sy = (t + b) / (t - b);\n            __ft__ A = f / (n - f);\n            __ft__ B = n * f / (n - f);\n\n            M4__x4t__ P = new M4__x4t__(\n                Fx, 0, Sx, 0,\n                0, Fy, Sy, 0,\n                0, 0, A, B,\n                0, 0, -1, 0);\n            return P;\n        }\n\n        #endregion\n\n        #region Static creators\n\n        /// <summary>\n        /// Returns the matrix that transforms from the coordinate system\n        /// specified by the basis into the world cordinate system.\n        /// </summary>\n        public static M4__x4t__ FromBasis(V__x3t__ xAxis, V__x3t__ yAxis, V__x3t__ zAxis, V__x3t__ origin)\n        {\n            return new M4__x4t__(\n                xAxis.X, yAxis.X, zAxis.X, origin.X,\n                xAxis.Y, yAxis.Y, zAxis.Y, origin.Y,\n                xAxis.Z, yAxis.Z, zAxis.Z, origin.Z,\n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a view tranformation from the given vectors.\n        /// Transformation from world- into view-space.\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"right\">Right vector of the view-plane</param>\n        /// <param name=\"up\">Up vector of the view-plane</param>\n        /// <param name=\"normal\">Normal vector of the view-plane. This vector is suppsoed to point in view-direction for a left-handed view transformation and in opposit direction in the right-handed case.</param>\n        /// <returns>The view transformation</returns>\n        public static M4__x4t__ ViewTrafo(V__x3t__ location, V__x3t__ right, V__x3t__ up, V__x3t__ normal)\n        {\n            return new M4__x4t__(\n                    right.X,  right.Y,  right.Z,  -location.Dot(right),\n                    up.X,     up.Y,     up.Z,     -location.Dot(up),\n                    normal.X, normal.Y, normal.Z, -location.Dot(normal),\n                    0,        0,        0,         1\n                );\n        }\n\n        /// <summary>\n        /// Creates a inverse view tranformation from the given vectors.\n        /// Transformation from view- into world-space.\n        /// The implementation is the same as FromBasis(right, up, normal, location)\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"right\">Right vector of the view-plane</param>\n        /// <param name=\"up\">Up vector of the view-plane</param>\n        /// <param name=\"normal\">Normal vector of the view-plane. This vector is suppsoed to point in view-direction for a left-handed view transformation and in opposit direction in the right-handed case.</param>\n        /// <returns>The inverse view transformation</returns>\n        public static M4__x4t__ InvViewTrafo(V__x3t__ location, V__x3t__ right, V__x3t__ up, V__x3t__ normal)\n        {\n            return new M4__x4t__(\n                    right.X, up.X, normal.X, location.X,\n                    right.Y, up.Y, normal.Y, location.Y,\n                    right.Z, up.Z, normal.Z, location.Z,\n                    0, 0, 0, 1\n                );\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } // isDouble\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/MatrixArrayExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class MatrixArrayExtensions\n    {\n        #region Transform position arrays and collections\n\n        public static void TransformPosArray(this M44d mat, V3d[] points)\n        {\n            for (var i = 0; i < points.Length; i++)\n                points[i] = mat.TransformPos(points[i]);\n        }\n\n        public static V3d[] TransformedPosArray(this M44d mat, ICollection<V3d> points)\n        {\n            var result = new V3d[points.Count];\n            var i = 0;\n            foreach (var p in points)\n                result[i++] = mat.TransformPos(p);\n            return result;\n        }\n\n        public static V3d[] TransformedDirArray(this M44d mat, V3d[] directions)\n        {\n            var result = new V3d[directions.Length];\n            for (var i = 0; i < directions.Length; i++)\n                result[i] = mat.TransformDir(directions[i]);\n            return result;\n        }\n\n        #endregion\n\n        #region Indexed Copy Operations\n\n        /// <summary>\n        /// Copies from the position array indexed by a backward map into\n        /// a target array, starting at the supplied offset, thereby\n        /// transforming all positions using the supplied matrix.\n        /// </summary>\n        /// <returns>target array</returns>\n        public static V3f[] BackwardIndexedTransformPosAndCopyTo(\n            this V3f[] source,\n            V3f[] target,\n            int[] backwardMap,\n            int offset,\n            M44d m44d)\n        {\n            var count = backwardMap.Length;\n            for (var i = 0; i < count; i++)\n                target[i + offset] = (V3f)m44d.TransformPos((V3d)source[backwardMap[i]]);\n            return target;\n        }\n\n        /// <summary>\n        /// Copies from the position array indexed by a backward map into\n        /// a target array, starting at the supplied offset, thereby\n        /// transforming all positions using the supplied matrix.\n        /// </summary>\n        /// <returns>target array</returns>\n        public static V3d[] BackwardIndexedTransformPosAndCopyTo(\n            this V3d[] source,\n            V3d[] target,\n            int[] backwardMap,\n            int offset,\n            M44d m44d)\n        {\n            var count = backwardMap.Length;\n            for (var i = 0; i < count; i++)\n                target[i + offset] = m44d.TransformPos(source[backwardMap[i]]);\n\n            return target;\n        }\n\n        public static Array BackwardIndexedTransformPosAndCopyTo(\n            this Array source, Array target,\n            int[] backwardMap, int offset,\n            M44d m44d)\n        {\n            var type = source.GetType();\n\n            if (type == typeof(V3f[]))\n                return BackwardIndexedTransformPosAndCopyTo((V3f[])source, (V3f[])target,\n                            backwardMap, offset, m44d);\n            if (type == typeof(V3d[]))\n                return BackwardIndexedTransformPosAndCopyTo((V3d[])source, (V3d[])target,\n                            backwardMap, offset, m44d);\n\n            throw new InvalidOperationException();\n        }\n\n        /// <summary>\n        /// Copies from the direction array indexed by a backward map into\n        /// a target array, starting at the supplied offset, thereby\n        /// transforming all directions using the supplied matrix.\n        /// </summary>\n        /// <returns>target array</returns>\n        public static V3f[] BackwardIndexedTransformDirAndCopyTo(\n            this V3f[] source,\n            V3f[] target,\n            int[] backwardMap,\n            int offset,\n            M44d m44d)\n        {\n            var count = backwardMap.Length;\n            for (var i = 0; i < count; i++)\n                target[i + offset] = (V3f)m44d.TransformDir((V3d)source[backwardMap[i]]);\n            return target;\n        }\n\n        /// <summary>\n        /// Copies from the direction array indexed by a backward map into\n        /// a target array, starting at the supplied offset, thereby\n        /// transforming all directions using the supplied matrix.\n        /// </summary>\n        /// <returns>target array</returns>\n        public static V3d[] BackwardIndexedTransformDirAndCopyTo(\n            this V3d[] source,\n            V3d[] target,\n            int[] backwardMap,\n            int offset,\n            M44d m44d)\n        {\n            var count = backwardMap.Length;\n            for (var i = 0; i < count; i++)\n                target[i + offset] = m44d.TransformDir(source[backwardMap[i]]);\n\n            return target;\n        }\n\n        public static Array BackwardIndexedTransformDirAndCopyTo(\n            this Array source, Array target,\n            int[] backwardMap, int offset,\n            M44d m44d)\n        {\n            var type = source.GetType();\n\n            if (type == typeof(V3f[]))\n                return BackwardIndexedTransformDirAndCopyTo((V3f[])source, (V3f[])target,\n                            backwardMap, offset, m44d);\n            if (type == typeof(V3d[]))\n                return BackwardIndexedTransformDirAndCopyTo((V3d[])source, (V3d[])target,\n                            backwardMap, offset, m44d);\n\n            throw new InvalidOperationException();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Matrix_auto.cs",
    "content": "using System;\nusing System.ComponentModel;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Xml.Serialization;\nusing System.Diagnostics;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    #region M22i\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M22i : IEquatable<M22i>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public int M00, M01;\n        [DataMember]\n        public int M10, M11;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(int value)\n        {\n            M00 = value; M01 = 0; \n            M10 = 0; M11 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(\n                int m00, int m01, \n                int m10, int m11)\n        {\n            M00 = m00; M01 = m01; \n            M10 = m10; M11 = m11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(int[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M10 = a[2];\n            M11 = a[3];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(int[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M10 = a[start + 2];\n            M11 = a[start + 3];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M23i m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M33i m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M34i m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M44i m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M22l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M23l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M33l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M34l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M44l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M22f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M23f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M33f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M34f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M44f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M22d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M23d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M33d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M34d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22i(M44d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; \n            M10 = (int)m.M10; M11 = (int)m.M11; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M22i(M23i m)\n        {\n            return new M22i {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M33i m)\n        {\n            return new M22i {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M34i m)\n        {\n            return new M22i {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M44i m)\n        {\n            return new M22i {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M22l m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M23l m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M33l m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M34l m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M44l m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M22f m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M23f m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M33f m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M34f m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M44f m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M22d m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M23d m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M33d m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M34d m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(M44d m)\n        {\n            return new M22i {\n                M00 = (int)m.M00, M01 = (int)m.M01, \n                M10 = (int)m.M10, M11 = (int)m.M11, \n            };\n        }\n\n        public static explicit operator M22i(int[] a)\n        {\n            return new M22i(\n                a[0], a[1], \n                a[2], a[3]);\n        }\n\n        public static explicit operator M22i(int[,] a)\n        {\n            return new M22i(\n                a[0, 0], a[0, 1], \n                a[1, 0], a[1, 1]);\n        }\n\n        public static explicit operator int[](M22i m)\n        {\n            return new int[] {\n                m.M00, m.M01, \n                m.M10, m.M11\n            };\n        }\n\n        public static explicit operator int[,](M22i m)\n        {\n            return new int[,] {\n                { m.M00, m.M01 }, \n                { m.M10, m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M10;\n            array[index + 3] = M11;\n        }\n\n        public static explicit operator M22i(long[] a)\n        {\n            return new M22i(\n                (int)a[0], (int)a[1], \n                (int)a[2], (int)a[3]);\n        }\n\n        public static explicit operator M22i(long[,] a)\n        {\n            return new M22i(\n                (int)a[0, 0], (int)a[0, 1], \n                (int)a[1, 0], (int)a[1, 1]);\n        }\n\n        public static explicit operator long[](M22i m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, \n                (long)m.M10, (long)m.M11\n            };\n        }\n\n        public static explicit operator long[,](M22i m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01 }, \n                { (long)m.M10, (long)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M10;\n            array[index + 3] = (long)M11;\n        }\n\n        public static explicit operator M22i(float[] a)\n        {\n            return new M22i(\n                (int)a[0], (int)a[1], \n                (int)a[2], (int)a[3]);\n        }\n\n        public static explicit operator M22i(float[,] a)\n        {\n            return new M22i(\n                (int)a[0, 0], (int)a[0, 1], \n                (int)a[1, 0], (int)a[1, 1]);\n        }\n\n        public static explicit operator float[](M22i m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, \n                (float)m.M10, (float)m.M11\n            };\n        }\n\n        public static explicit operator float[,](M22i m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01 }, \n                { (float)m.M10, (float)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M10;\n            array[index + 3] = (float)M11;\n        }\n\n        public static explicit operator M22i(double[] a)\n        {\n            return new M22i(\n                (int)a[0], (int)a[1], \n                (int)a[2], (int)a[3]);\n        }\n\n        public static explicit operator M22i(double[,] a)\n        {\n            return new M22i(\n                (int)a[0, 0], (int)a[0, 1], \n                (int)a[1, 0], (int)a[1, 1]);\n        }\n\n        public static explicit operator double[](M22i m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, \n                (double)m.M10, (double)m.M11\n            };\n        }\n\n        public static explicit operator double[,](M22i m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01 }, \n                { (double)m.M10, (double)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M10;\n            array[index + 3] = (double)M11;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22i Copy(Func<int, int> element_fun)\n        {\n            return new M22i(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22i Copy(Func<int, int, int, int> element_index0_index1_fun)\n        {\n            return new M22i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22l Copy(Func<int, long> element_fun)\n        {\n            return new M22l(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22l Copy(Func<int, int, int, long> element_index0_index1_fun)\n        {\n            return new M22l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22f Copy(Func<int, float> element_fun)\n        {\n            return new M22f(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22f Copy(Func<int, int, int, float> element_index0_index1_fun)\n        {\n            return new M22f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22d Copy(Func<int, double> element_fun)\n        {\n            return new M22d(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22d Copy(Func<int, int, int, double> element_index0_index1_fun)\n        {\n            return new M22d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        public readonly int[] ToArray()\n        {\n            var array = new int[4];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M10;\n            array[3] = M11;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i FromCols(V2i col0, V2i col1)\n        {\n            return new M22i(\n                col0.X, col1.X, \n                col0.Y, col1.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i FromRows(V2i row0, V2i row1)\n        {\n            return new M22i(\n                row0.X, row0.Y, \n                row1.X, row1.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i FromDiagonal(int value)\n        {\n            return new M22i(\n                value, 0, \n                0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i FromDiagonal(int m00, int m11)\n        {\n            return new M22i(\n                m00, 0, \n                0, m11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i FromDiagonal(V2i s)\n        {\n            return new M22i(\n                s.X, 0, \n                0, s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i FromAntiDiagonal(int value)\n        {\n            return new M22i(\n                 0, value, \n                 value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i FromAntiDiagonal(int m01, int m10)\n        {\n            return new M22i(\n                0, m01, \n                m10, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i FromAntiDiagonal(V2i s)\n        {\n            return new M22i(\n                0, s.X, \n                s.Y, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22i\"/> using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i Scale(int sX, int sY)\n            => FromDiagonal(sX, sY);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22i\"/> using a <see cref=\"V2i\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i Scale(V2i s)\n            => FromDiagonal(s);\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i DivideByInt(M22i m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M10;\n                yield return M11;\n            }\n        }\n\n        public readonly IEnumerable<V2i> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n            }\n        }\n\n        public readonly IEnumerable<V2i> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n            }\n        }\n\n        [XmlIgnore]\n        public V2i R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2i( M00,  M01); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2i R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2i( M10,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2i C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2i( M00,  M10); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2i C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2i( M01,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        public readonly V2i Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2i(M00, M11);\n        }\n\n        public readonly V2i AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2i(M01, M10);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly int MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M10, M11);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly int MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M10, M11);\n        }\n\n        public unsafe int this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe int this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[row * 2 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[row * 2 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 2;\n        public const int ColumnCount = 2;\n        public const int ElementCount = 2 * 2;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(2, 2);\n        }\n\n        public static M22i Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M22i(0);\n        }\n\n        public static M22i Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M22i(1, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly int Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + \n                    Fun.Abs(M10) + Fun.Abs(M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + \n                    M10 * M10 + M11 * M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator -(M22i m)\n        {\n            return new M22i(\n                -m.M00, -m.M01, \n                -m.M10, -m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  + (M22i a, M22i b)\n        {\n            return new M22i(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  + (M22i m, int s)\n        {\n            return new M22i(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  + (int s, M22i m)\n        {\n            return new M22i(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  + (M22i a, M22l b)\n        {\n            return new M22l(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  + (M22i m, long s)\n        {\n            return new M22l(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  + (long s, M22i m)\n        {\n            return new M22l(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (M22i a, M22f b)\n        {\n            return new M22f(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (M22i m, float s)\n        {\n            return new M22f(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (float s, M22i m)\n        {\n            return new M22f(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (M22i a, M22d b)\n        {\n            return new M22d(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (M22i m, double s)\n        {\n            return new M22d(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (double s, M22i m)\n        {\n            return new M22d(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  - (M22i a, M22i b)\n        {\n            return new M22i(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  - (M22i m, int s)\n        {\n            return new M22i(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  - (int s, M22i m)\n        {\n            return new M22i(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  - (M22i a, M22l b)\n        {\n            return new M22l(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  - (M22i m, long s)\n        {\n            return new M22l(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  - (long s, M22i m)\n        {\n            return new M22l(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (M22i a, M22f b)\n        {\n            return new M22f(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (M22i m, float s)\n        {\n            return new M22f(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (float s, M22i m)\n        {\n            return new M22f(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (M22i a, M22d b)\n        {\n            return new M22d(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (M22i m, double s)\n        {\n            return new M22d(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (double s, M22i m)\n        {\n            return new M22d(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  % (M22i a, M22i b)\n        {\n            return new M22i(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  % (M22i m, int s)\n        {\n            return new M22i(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  % (int s, M22i m)\n        {\n            return new M22i(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  % (M22i a, M22l b)\n        {\n            return new M22l(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  % (M22i m, long s)\n        {\n            return new M22l(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  % (long s, M22i m)\n        {\n            return new M22l(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (M22i a, M22f b)\n        {\n            return new M22f(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (M22i m, float s)\n        {\n            return new M22f(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (float s, M22i m)\n        {\n            return new M22f(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (M22i a, M22d b)\n        {\n            return new M22d(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (M22i m, double s)\n        {\n            return new M22d(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (double s, M22i m)\n        {\n            return new M22d(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  / (M22i a, M22i b)\n        {\n            return new M22i(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  / (M22i m, int s)\n        {\n            return new M22i(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  / (int s, M22i m)\n        {\n            return new M22i(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  / (M22i a, M22l b)\n        {\n            return new M22l(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  / (M22i m, long s)\n        {\n            return new M22l(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  / (long s, M22i m)\n        {\n            return new M22l(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (M22i a, M22f b)\n        {\n            return new M22f(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (M22i m, float s)\n        {\n            return new M22f(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (float s, M22i m)\n        {\n            return new M22f(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (M22i a, M22d b)\n        {\n            return new M22d(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (M22i m, double s)\n        {\n            return new M22d(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (double s, M22i m)\n        {\n            return new M22d(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  * (M22i m, int s)\n        {\n            return new M22i(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator  * (int s, M22i m)\n        {\n            return new M22i(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  * (M22i m, long s)\n        {\n            return new M22l(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  * (long s, M22i m)\n        {\n            return new M22l(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  * (M22i m, float s)\n        {\n            return new M22f(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  * (float s, M22i m)\n        {\n            return new M22f(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  * (M22i m, double s)\n        {\n            return new M22d(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  * (double s, M22i m)\n        {\n            return new M22d(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator ~(M22i m)\n        {\n            return new M22i(\n                ~m.M00, ~m.M01, \n                ~m.M10, ~m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator <<(M22i a, int s)\n        {\n            return new M22i(\n                a.M00 << s, a.M01 << s, \n                a.M10 << s, a.M11 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator >>(M22i a, int s)\n        {\n            return new M22i(\n                a.M00 >> s, a.M01 >> s, \n                a.M10 >> s, a.M11 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator &(M22i a, M22i b)\n        {\n            return new M22i(\n                a.M00 & b.M00, a.M01 & b.M01, \n                a.M10 & b.M10, a.M11 & b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator &(M22i a, int s)\n        {\n            return new M22i(\n                a.M00 & s, a.M01 & s, \n                a.M10 & s, a.M11 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator &(int s, M22i a)\n        {\n            return new M22i(\n                s & a.M00, s & a.M01, \n                s & a.M10, s & a.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator |(M22i a, M22i b)\n        {\n            return new M22i(\n                a.M00 | b.M00, a.M01 | b.M01, \n                a.M10 | b.M10, a.M11 | b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator |(M22i a, int s)\n        {\n            return new M22i(\n                a.M00 | s, a.M01 | s, \n                a.M10 | s, a.M11 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator |(int s, M22i a)\n        {\n            return new M22i(\n                s | a.M00, s | a.M01, \n                s | a.M10, s | a.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator ^(M22i a, M22i b)\n        {\n            return new M22i(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, \n                a.M10 ^ b.M10, a.M11 ^ b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator ^(M22i a, int s)\n        {\n            return new M22i(\n                a.M00 ^ s, a.M01 ^ s, \n                a.M10 ^ s, a.M11 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i operator ^(int s, M22i a)\n        {\n            return new M22i(\n                s ^ a.M00, s ^ a.M01, \n                s ^ a.M10, s ^ a.M11);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M22i matrix with a V2i column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator *(M22i m, V2i v)\n        {\n            return new V2i(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y);\n        }\n\n        /// <summary>\n        /// Multiplies a V2i row vector with a M22i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator *(V2i v, M22i m)\n        {\n            return new V2i(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M22i a, M22i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M22i a, int s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M10 == s && \n                a.M11 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(int s, M22i a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M10  && \n                s == a.M11 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M22i a, M22i b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M22i m, int s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(int s, M22i m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01),\n                        HashCode.GetCombined(M10, M11));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M22i other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && \n                M10.Equals(other.M10) && M11.Equals(other.M11);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M22i o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M22i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M22i.FromRows(\n                V2i.Parse(x[0]), \n                V2i.Parse(x[1])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M22i Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return new M22i(M11, -M10, -M01, M00);\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly int Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly int Determinant\n        {\n            get\n            {\n                return M00 * M11 - M10 * M01;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M22i Transposed\n        {\n            get\n            {\n                return new M22i {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    \n                    M10 = M01, \n                    M11 = M11\n                };\n            }\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M22i operator *(M22i a, M22i b)\n        {\n            return new M22i(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (int)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (int)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (int)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (int)value;\n        }\n\n        #endregion\n    }\n\n    public class M22iEqualityComparer : IEqualityComparer<M22i>\n    {\n        public static readonly M22iEqualityComparer Default\n            = new M22iEqualityComparer();\n\n        #region IEqualityComparer<M22i> Members\n\n        public bool Equals(M22i v0, M22i v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M22i v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M22i m)\n            => (m.C0.Length + m.C1.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector(this M22i m)\n            => new V2d(m.C0.Length, m.C1.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Norm1(M22i m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M22i m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMax(M22i m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMin(M22i m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M22i m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static int Distance1(this M22i a, M22i b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M22i a, M22i b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M22i a, M22i b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMax(this M22i a, M22i b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMin(this M22i a, M22i b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Transform(this M22i m, V2i v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Transform(this M22i m, V3i v)\n        {\n            return new V3i(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Transform(this M22i m, V4i v)\n        {\n            return new V4i(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y,\n                v.Z, v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i TransposedTransform(this M22i m, V2i v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i TransposedTransform(this M22i m, V3i v)\n        {\n            return new V3i(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i TransposedTransform(this M22i m, V4i v)\n        {\n            return new V4i(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11,\n                v.Z, v.W);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M22i\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static int Minor(this M22i m, int row, int column)\n        {\n            return m[1 - row, 1 - column];\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2i Row(this M22i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V2i(ptr[index * 2], ptr[index * 2 + 1]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2i Column(this M22i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V2i(ptr[index], ptr[index + 2]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Determinant(M22i m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i Transposed(M22i m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M22i m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M22i a, M22i b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M22i m, int s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M10 < s && \n                m.M11 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(int s, M22i m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M10 && \n                s < m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M22i a, M22i b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M22i m, int s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M10 < s || \n                m.M11 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(int s, M22i m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M10 || \n                s < m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M22i a, M22i b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M22i m, int s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M10 > s && \n                m.M11 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(int s, M22i m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M10 && \n                s > m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M22i a, M22i b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M22i m, int s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M10 > s || \n                m.M11 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(int s, M22i m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M10 || \n                s > m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M22i a, M22i b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M22i m, int s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M10 <= s && \n                m.M11 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(int s, M22i m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M10 && \n                s <= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M22i a, M22i b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M22i m, int s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M10 <= s || \n                m.M11 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(int s, M22i m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M10 || \n                s <= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M22i a, M22i b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M22i m, int s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M10 >= s && \n                m.M11 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(int s, M22i m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M10 && \n                s >= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M22i a, M22i b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M22i m, int s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M10 >= s || \n                m.M11 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(int s, M22i m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M10 || \n                s >= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M22i a, M22i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M22i m, int s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M10 == s && \n                m.M11 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(int s, M22i m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M10 && \n                s == m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M22i a, M22i b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M22i m, int s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M10 == s || \n                m.M11 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(int s, M22i m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M10 || \n                s == m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M22i a, M22i b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M22i m, int s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M10 != s && \n                m.M11 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(int s, M22i m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M10 && \n                s != m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M22i a, M22i b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M22i m, int s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M10 != s || \n                m.M11 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(int s, M22i m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M10 || \n                s != m.M11;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M22i m0, M22i m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M22i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MinElement(M22i m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M22i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MaxElement(M22i m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M22i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M22i m, int epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M22i m, int epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M22i a, M22i b, int epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M22i m, int epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM22iExtensions\n    {\n        #region IRandomUniform extensions for M22i\n\n        /// <summary>\n        /// Uses UniformInt() to generate the elements of an M22i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i UniformM22i(this IRandomUniform rnd)\n        {\n            return new M22i(\n                rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt());\n        }\n\n        /// <summary>\n        /// Uses UniformIntNonZero() to generate the elements of an M22i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i UniformM22iNonZero(this IRandomUniform rnd)\n        {\n            return new M22i(\n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M22i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i UniformM22i(this IRandomUniform rnd, int size)\n        {\n            return new M22i(\n                rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size));\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M22i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i UniformM22i(this IRandomUniform rnd, M22i size)\n        {\n            return new M22i(\n                rnd.UniformInt(size.M00), rnd.UniformInt(size.M01), \n                rnd.UniformInt(size.M10), rnd.UniformInt(size.M11));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M22l\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M22l : IEquatable<M22l>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public long M00, M01;\n        [DataMember]\n        public long M10, M11;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(long value)\n        {\n            M00 = value; M01 = 0; \n            M10 = 0; M11 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(\n                long m00, long m01, \n                long m10, long m11)\n        {\n            M00 = m00; M01 = m01; \n            M10 = m10; M11 = m11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(long[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M10 = a[2];\n            M11 = a[3];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(long[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M10 = a[start + 2];\n            M11 = a[start + 3];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M22i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M23i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M33i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M34i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M44i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M23l m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M33l m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M34l m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M44l m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M22f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M23f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M33f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M34f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M44f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M22d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M23d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M33d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M34d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22l(M44d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; \n            M10 = (long)m.M10; M11 = (long)m.M11; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M22l(M22i m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M23i m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M33i m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M34i m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M44i m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M23l m)\n        {\n            return new M22l {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M33l m)\n        {\n            return new M22l {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M34l m)\n        {\n            return new M22l {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M44l m)\n        {\n            return new M22l {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M22f m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M23f m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M33f m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M34f m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M44f m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M22d m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M23d m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M33d m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M34d m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(M44d m)\n        {\n            return new M22l {\n                M00 = (long)m.M00, M01 = (long)m.M01, \n                M10 = (long)m.M10, M11 = (long)m.M11, \n            };\n        }\n\n        public static explicit operator M22l(int[] a)\n        {\n            return new M22l(\n                (long)a[0], (long)a[1], \n                (long)a[2], (long)a[3]);\n        }\n\n        public static explicit operator M22l(int[,] a)\n        {\n            return new M22l(\n                (long)a[0, 0], (long)a[0, 1], \n                (long)a[1, 0], (long)a[1, 1]);\n        }\n\n        public static explicit operator int[](M22l m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, \n                (int)m.M10, (int)m.M11\n            };\n        }\n\n        public static explicit operator int[,](M22l m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01 }, \n                { (int)m.M10, (int)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M10;\n            array[index + 3] = (int)M11;\n        }\n\n        public static explicit operator M22l(long[] a)\n        {\n            return new M22l(\n                a[0], a[1], \n                a[2], a[3]);\n        }\n\n        public static explicit operator M22l(long[,] a)\n        {\n            return new M22l(\n                a[0, 0], a[0, 1], \n                a[1, 0], a[1, 1]);\n        }\n\n        public static explicit operator long[](M22l m)\n        {\n            return new long[] {\n                m.M00, m.M01, \n                m.M10, m.M11\n            };\n        }\n\n        public static explicit operator long[,](M22l m)\n        {\n            return new long[,] {\n                { m.M00, m.M01 }, \n                { m.M10, m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M10;\n            array[index + 3] = M11;\n        }\n\n        public static explicit operator M22l(float[] a)\n        {\n            return new M22l(\n                (long)a[0], (long)a[1], \n                (long)a[2], (long)a[3]);\n        }\n\n        public static explicit operator M22l(float[,] a)\n        {\n            return new M22l(\n                (long)a[0, 0], (long)a[0, 1], \n                (long)a[1, 0], (long)a[1, 1]);\n        }\n\n        public static explicit operator float[](M22l m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, \n                (float)m.M10, (float)m.M11\n            };\n        }\n\n        public static explicit operator float[,](M22l m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01 }, \n                { (float)m.M10, (float)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M10;\n            array[index + 3] = (float)M11;\n        }\n\n        public static explicit operator M22l(double[] a)\n        {\n            return new M22l(\n                (long)a[0], (long)a[1], \n                (long)a[2], (long)a[3]);\n        }\n\n        public static explicit operator M22l(double[,] a)\n        {\n            return new M22l(\n                (long)a[0, 0], (long)a[0, 1], \n                (long)a[1, 0], (long)a[1, 1]);\n        }\n\n        public static explicit operator double[](M22l m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, \n                (double)m.M10, (double)m.M11\n            };\n        }\n\n        public static explicit operator double[,](M22l m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01 }, \n                { (double)m.M10, (double)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M10;\n            array[index + 3] = (double)M11;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22i Copy(Func<long, int> element_fun)\n        {\n            return new M22i(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22i Copy(Func<long, int, int, int> element_index0_index1_fun)\n        {\n            return new M22i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22l Copy(Func<long, long> element_fun)\n        {\n            return new M22l(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22l Copy(Func<long, int, int, long> element_index0_index1_fun)\n        {\n            return new M22l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22f Copy(Func<long, float> element_fun)\n        {\n            return new M22f(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22f Copy(Func<long, int, int, float> element_index0_index1_fun)\n        {\n            return new M22f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22d Copy(Func<long, double> element_fun)\n        {\n            return new M22d(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22d Copy(Func<long, int, int, double> element_index0_index1_fun)\n        {\n            return new M22d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        public readonly long[] ToArray()\n        {\n            var array = new long[4];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M10;\n            array[3] = M11;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l FromCols(V2l col0, V2l col1)\n        {\n            return new M22l(\n                col0.X, col1.X, \n                col0.Y, col1.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l FromRows(V2l row0, V2l row1)\n        {\n            return new M22l(\n                row0.X, row0.Y, \n                row1.X, row1.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l FromDiagonal(long value)\n        {\n            return new M22l(\n                value, 0, \n                0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l FromDiagonal(long m00, long m11)\n        {\n            return new M22l(\n                m00, 0, \n                0, m11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l FromDiagonal(V2l s)\n        {\n            return new M22l(\n                s.X, 0, \n                0, s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l FromAntiDiagonal(long value)\n        {\n            return new M22l(\n                 0, value, \n                 value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l FromAntiDiagonal(long m01, long m10)\n        {\n            return new M22l(\n                0, m01, \n                m10, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l FromAntiDiagonal(V2l s)\n        {\n            return new M22l(\n                0, s.X, \n                s.Y, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22l\"/> using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l Scale(long sX, long sY)\n            => FromDiagonal(sX, sY);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22l\"/> using a <see cref=\"V2l\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l Scale(V2l s)\n            => FromDiagonal(s);\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l DivideByInt(M22l m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M10;\n                yield return M11;\n            }\n        }\n\n        public readonly IEnumerable<V2l> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n            }\n        }\n\n        public readonly IEnumerable<V2l> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n            }\n        }\n\n        [XmlIgnore]\n        public V2l R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2l( M00,  M01); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2l R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2l( M10,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2l C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2l( M00,  M10); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2l C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2l( M01,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        public readonly V2l Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(M00, M11);\n        }\n\n        public readonly V2l AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(M01, M10);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly long MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M10, M11);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly long MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M10, M11);\n        }\n\n        public unsafe long this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe long this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[row * 2 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[row * 2 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 2;\n        public const int ColumnCount = 2;\n        public const int ElementCount = 2 * 2;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(2, 2);\n        }\n\n        public static M22l Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M22l(0);\n        }\n\n        public static M22l Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M22l(1, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly long Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + \n                    Fun.Abs(M10) + Fun.Abs(M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + \n                    M10 * M10 + M11 * M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator -(M22l m)\n        {\n            return new M22l(\n                -m.M00, -m.M01, \n                -m.M10, -m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  + (M22l a, M22l b)\n        {\n            return new M22l(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  + (M22l m, long s)\n        {\n            return new M22l(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  + (long s, M22l m)\n        {\n            return new M22l(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (M22l a, M22f b)\n        {\n            return new M22f(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (M22l m, float s)\n        {\n            return new M22f(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (float s, M22l m)\n        {\n            return new M22f(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (M22l a, M22d b)\n        {\n            return new M22d(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (M22l m, double s)\n        {\n            return new M22d(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (double s, M22l m)\n        {\n            return new M22d(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  - (M22l a, M22l b)\n        {\n            return new M22l(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  - (M22l m, long s)\n        {\n            return new M22l(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  - (long s, M22l m)\n        {\n            return new M22l(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (M22l a, M22f b)\n        {\n            return new M22f(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (M22l m, float s)\n        {\n            return new M22f(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (float s, M22l m)\n        {\n            return new M22f(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (M22l a, M22d b)\n        {\n            return new M22d(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (M22l m, double s)\n        {\n            return new M22d(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (double s, M22l m)\n        {\n            return new M22d(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  % (M22l a, M22l b)\n        {\n            return new M22l(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  % (M22l m, long s)\n        {\n            return new M22l(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  % (long s, M22l m)\n        {\n            return new M22l(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (M22l a, M22f b)\n        {\n            return new M22f(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (M22l m, float s)\n        {\n            return new M22f(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (float s, M22l m)\n        {\n            return new M22f(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (M22l a, M22d b)\n        {\n            return new M22d(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (M22l m, double s)\n        {\n            return new M22d(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (double s, M22l m)\n        {\n            return new M22d(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  / (M22l a, M22l b)\n        {\n            return new M22l(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  / (M22l m, long s)\n        {\n            return new M22l(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  / (long s, M22l m)\n        {\n            return new M22l(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (M22l a, M22f b)\n        {\n            return new M22f(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (M22l m, float s)\n        {\n            return new M22f(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (float s, M22l m)\n        {\n            return new M22f(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (M22l a, M22d b)\n        {\n            return new M22d(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (M22l m, double s)\n        {\n            return new M22d(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (double s, M22l m)\n        {\n            return new M22d(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  * (M22l m, long s)\n        {\n            return new M22l(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator  * (long s, M22l m)\n        {\n            return new M22l(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  * (M22l m, float s)\n        {\n            return new M22f(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  * (float s, M22l m)\n        {\n            return new M22f(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  * (M22l m, double s)\n        {\n            return new M22d(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  * (double s, M22l m)\n        {\n            return new M22d(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator ~(M22l m)\n        {\n            return new M22l(\n                ~m.M00, ~m.M01, \n                ~m.M10, ~m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator <<(M22l a, int s)\n        {\n            return new M22l(\n                a.M00 << s, a.M01 << s, \n                a.M10 << s, a.M11 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator >>(M22l a, int s)\n        {\n            return new M22l(\n                a.M00 >> s, a.M01 >> s, \n                a.M10 >> s, a.M11 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator &(M22l a, M22l b)\n        {\n            return new M22l(\n                a.M00 & b.M00, a.M01 & b.M01, \n                a.M10 & b.M10, a.M11 & b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator &(M22l a, long s)\n        {\n            return new M22l(\n                a.M00 & s, a.M01 & s, \n                a.M10 & s, a.M11 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator &(long s, M22l a)\n        {\n            return new M22l(\n                s & a.M00, s & a.M01, \n                s & a.M10, s & a.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator |(M22l a, M22l b)\n        {\n            return new M22l(\n                a.M00 | b.M00, a.M01 | b.M01, \n                a.M10 | b.M10, a.M11 | b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator |(M22l a, long s)\n        {\n            return new M22l(\n                a.M00 | s, a.M01 | s, \n                a.M10 | s, a.M11 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator |(long s, M22l a)\n        {\n            return new M22l(\n                s | a.M00, s | a.M01, \n                s | a.M10, s | a.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator ^(M22l a, M22l b)\n        {\n            return new M22l(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, \n                a.M10 ^ b.M10, a.M11 ^ b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator ^(M22l a, long s)\n        {\n            return new M22l(\n                a.M00 ^ s, a.M01 ^ s, \n                a.M10 ^ s, a.M11 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l operator ^(long s, M22l a)\n        {\n            return new M22l(\n                s ^ a.M00, s ^ a.M01, \n                s ^ a.M10, s ^ a.M11);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M22l matrix with a V2l column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator *(M22l m, V2l v)\n        {\n            return new V2l(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y);\n        }\n\n        /// <summary>\n        /// Multiplies a V2l row vector with a M22l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator *(V2l v, M22l m)\n        {\n            return new V2l(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M22l a, M22l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M22l a, long s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M10 == s && \n                a.M11 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(long s, M22l a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M10  && \n                s == a.M11 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M22l a, M22l b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M22l m, long s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(long s, M22l m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01),\n                        HashCode.GetCombined(M10, M11));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M22l other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && \n                M10.Equals(other.M10) && M11.Equals(other.M11);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M22l o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M22l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M22l.FromRows(\n                V2l.Parse(x[0]), \n                V2l.Parse(x[1])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M22l Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return new M22l(M11, -M10, -M01, M00);\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly long Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly long Determinant\n        {\n            get\n            {\n                return M00 * M11 - M10 * M01;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M22l Transposed\n        {\n            get\n            {\n                return new M22l {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    \n                    M10 = M01, \n                    M11 = M11\n                };\n            }\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M22l operator *(M22l a, M22l b)\n        {\n            return new M22l(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (long)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (long)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (long)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (long)value;\n        }\n\n        #endregion\n    }\n\n    public class M22lEqualityComparer : IEqualityComparer<M22l>\n    {\n        public static readonly M22lEqualityComparer Default\n            = new M22lEqualityComparer();\n\n        #region IEqualityComparer<M22l> Members\n\n        public bool Equals(M22l v0, M22l v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M22l v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M22l m)\n            => (m.C0.Length + m.C1.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector(this M22l m)\n            => new V2d(m.C0.Length, m.C1.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Norm1(M22l m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M22l m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMax(M22l m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMin(M22l m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M22l m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static long Distance1(this M22l a, M22l b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M22l a, M22l b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M22l a, M22l b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMax(this M22l a, M22l b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMin(this M22l a, M22l b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Transform(this M22l m, V2l v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Transform(this M22l m, V3l v)\n        {\n            return new V3l(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Transform(this M22l m, V4l v)\n        {\n            return new V4l(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y,\n                v.Z, v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l TransposedTransform(this M22l m, V2l v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l TransposedTransform(this M22l m, V3l v)\n        {\n            return new V3l(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l TransposedTransform(this M22l m, V4l v)\n        {\n            return new V4l(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11,\n                v.Z, v.W);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M22l\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static long Minor(this M22l m, int row, int column)\n        {\n            return m[1 - row, 1 - column];\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2l Row(this M22l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V2l(ptr[index * 2], ptr[index * 2 + 1]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2l Column(this M22l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V2l(ptr[index], ptr[index + 2]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Determinant(M22l m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l Transposed(M22l m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M22l m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M22l a, M22l b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M22l m, long s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M10 < s && \n                m.M11 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(long s, M22l m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M10 && \n                s < m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M22l a, M22l b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M22l m, long s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M10 < s || \n                m.M11 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(long s, M22l m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M10 || \n                s < m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M22l a, M22l b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M22l m, long s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M10 > s && \n                m.M11 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(long s, M22l m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M10 && \n                s > m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M22l a, M22l b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M22l m, long s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M10 > s || \n                m.M11 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(long s, M22l m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M10 || \n                s > m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M22l a, M22l b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M22l m, long s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M10 <= s && \n                m.M11 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(long s, M22l m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M10 && \n                s <= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M22l a, M22l b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M22l m, long s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M10 <= s || \n                m.M11 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(long s, M22l m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M10 || \n                s <= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M22l a, M22l b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M22l m, long s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M10 >= s && \n                m.M11 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(long s, M22l m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M10 && \n                s >= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M22l a, M22l b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M22l m, long s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M10 >= s || \n                m.M11 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(long s, M22l m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M10 || \n                s >= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M22l a, M22l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M22l m, long s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M10 == s && \n                m.M11 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(long s, M22l m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M10 && \n                s == m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M22l a, M22l b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M22l m, long s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M10 == s || \n                m.M11 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(long s, M22l m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M10 || \n                s == m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M22l a, M22l b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M22l m, long s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M10 != s && \n                m.M11 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(long s, M22l m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M10 && \n                s != m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M22l a, M22l b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M22l m, long s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M10 != s || \n                m.M11 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(long s, M22l m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M10 || \n                s != m.M11;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M22l m0, M22l m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M22l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MinElement(M22l m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M22l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MaxElement(M22l m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M22l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M22l m, long epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M22l m, long epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M22l a, M22l b, long epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M22l m, long epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM22lExtensions\n    {\n        #region IRandomUniform extensions for M22l\n\n        /// <summary>\n        /// Uses UniformLong() to generate the elements of an M22l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l UniformM22l(this IRandomUniform rnd)\n        {\n            return new M22l(\n                rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong());\n        }\n\n        /// <summary>\n        /// Uses UniformLongNonZero() to generate the elements of an M22l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l UniformM22lNonZero(this IRandomUniform rnd)\n        {\n            return new M22l(\n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M22l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l UniformM22l(this IRandomUniform rnd, long size)\n        {\n            return new M22l(\n                rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size));\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M22l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l UniformM22l(this IRandomUniform rnd, M22l size)\n        {\n            return new M22l(\n                rnd.UniformLong(size.M00), rnd.UniformLong(size.M01), \n                rnd.UniformLong(size.M10), rnd.UniformLong(size.M11));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M22f\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M22f : IEquatable<M22f>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public float M00, M01;\n        [DataMember]\n        public float M10, M11;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(float value)\n        {\n            M00 = value; M01 = 0; \n            M10 = 0; M11 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(\n                float m00, float m01, \n                float m10, float m11)\n        {\n            M00 = m00; M01 = m01; \n            M10 = m10; M11 = m11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(float[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M10 = a[2];\n            M11 = a[3];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(float[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M10 = a[start + 2];\n            M11 = a[start + 3];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M22i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M23i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M33i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M34i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M44i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M22l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M23l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M33l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M34l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M44l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M23f m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M33f m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M34f m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M44f m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M22d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M23d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M33d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M34d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22f(M44d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; \n            M10 = (float)m.M10; M11 = (float)m.M11; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M22f(M22i m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M23i m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M33i m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M34i m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M44i m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M22l m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M23l m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M33l m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M34l m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M44l m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M23f m)\n        {\n            return new M22f {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M33f m)\n        {\n            return new M22f {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M34f m)\n        {\n            return new M22f {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M44f m)\n        {\n            return new M22f {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M22d m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M23d m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M33d m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M34d m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(M44d m)\n        {\n            return new M22f {\n                M00 = (float)m.M00, M01 = (float)m.M01, \n                M10 = (float)m.M10, M11 = (float)m.M11, \n            };\n        }\n\n        public static explicit operator M22f(int[] a)\n        {\n            return new M22f(\n                (float)a[0], (float)a[1], \n                (float)a[2], (float)a[3]);\n        }\n\n        public static explicit operator M22f(int[,] a)\n        {\n            return new M22f(\n                (float)a[0, 0], (float)a[0, 1], \n                (float)a[1, 0], (float)a[1, 1]);\n        }\n\n        public static explicit operator int[](M22f m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, \n                (int)m.M10, (int)m.M11\n            };\n        }\n\n        public static explicit operator int[,](M22f m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01 }, \n                { (int)m.M10, (int)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M10;\n            array[index + 3] = (int)M11;\n        }\n\n        public static explicit operator M22f(long[] a)\n        {\n            return new M22f(\n                (float)a[0], (float)a[1], \n                (float)a[2], (float)a[3]);\n        }\n\n        public static explicit operator M22f(long[,] a)\n        {\n            return new M22f(\n                (float)a[0, 0], (float)a[0, 1], \n                (float)a[1, 0], (float)a[1, 1]);\n        }\n\n        public static explicit operator long[](M22f m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, \n                (long)m.M10, (long)m.M11\n            };\n        }\n\n        public static explicit operator long[,](M22f m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01 }, \n                { (long)m.M10, (long)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M10;\n            array[index + 3] = (long)M11;\n        }\n\n        public static explicit operator M22f(float[] a)\n        {\n            return new M22f(\n                a[0], a[1], \n                a[2], a[3]);\n        }\n\n        public static explicit operator M22f(float[,] a)\n        {\n            return new M22f(\n                a[0, 0], a[0, 1], \n                a[1, 0], a[1, 1]);\n        }\n\n        public static explicit operator float[](M22f m)\n        {\n            return new float[] {\n                m.M00, m.M01, \n                m.M10, m.M11\n            };\n        }\n\n        public static explicit operator float[,](M22f m)\n        {\n            return new float[,] {\n                { m.M00, m.M01 }, \n                { m.M10, m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M10;\n            array[index + 3] = M11;\n        }\n\n        public static explicit operator M22f(double[] a)\n        {\n            return new M22f(\n                (float)a[0], (float)a[1], \n                (float)a[2], (float)a[3]);\n        }\n\n        public static explicit operator M22f(double[,] a)\n        {\n            return new M22f(\n                (float)a[0, 0], (float)a[0, 1], \n                (float)a[1, 0], (float)a[1, 1]);\n        }\n\n        public static explicit operator double[](M22f m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, \n                (double)m.M10, (double)m.M11\n            };\n        }\n\n        public static explicit operator double[,](M22f m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01 }, \n                { (double)m.M10, (double)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M10;\n            array[index + 3] = (double)M11;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22i Copy(Func<float, int> element_fun)\n        {\n            return new M22i(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22i Copy(Func<float, int, int, int> element_index0_index1_fun)\n        {\n            return new M22i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22l Copy(Func<float, long> element_fun)\n        {\n            return new M22l(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22l Copy(Func<float, int, int, long> element_index0_index1_fun)\n        {\n            return new M22l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22f Copy(Func<float, float> element_fun)\n        {\n            return new M22f(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22f Copy(Func<float, int, int, float> element_index0_index1_fun)\n        {\n            return new M22f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22d Copy(Func<float, double> element_fun)\n        {\n            return new M22d(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22d Copy(Func<float, int, int, double> element_index0_index1_fun)\n        {\n            return new M22d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        public readonly float[] ToArray()\n        {\n            var array = new float[4];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M10;\n            array[3] = M11;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f FromCols(V2f col0, V2f col1)\n        {\n            return new M22f(\n                col0.X, col1.X, \n                col0.Y, col1.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f FromRows(V2f row0, V2f row1)\n        {\n            return new M22f(\n                row0.X, row0.Y, \n                row1.X, row1.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f FromDiagonal(float value)\n        {\n            return new M22f(\n                value, 0, \n                0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f FromDiagonal(float m00, float m11)\n        {\n            return new M22f(\n                m00, 0, \n                0, m11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f FromDiagonal(V2f s)\n        {\n            return new M22f(\n                s.X, 0, \n                0, s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f FromAntiDiagonal(float value)\n        {\n            return new M22f(\n                 0, value, \n                 value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f FromAntiDiagonal(float m01, float m10)\n        {\n            return new M22f(\n                0, m01, \n                m10, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f FromAntiDiagonal(V2f s)\n        {\n            return new M22f(\n                0, s.X, \n                s.Y, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22f\"/> using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Scale(float sX, float sY)\n            => FromDiagonal(sX, sY);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22f\"/> using a <see cref=\"V2f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Scale(V2f s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22f\"/> from a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Scale(Scale2f s)\n        {\n            return new M22f(\n                s.X, 0, \n                0, s.Y);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Rotation(float angleInRadians)\n        {\n            var a = Fun.Cos(angleInRadians);\n            var b = Fun.Sin(angleInRadians);\n\n            return new M22f(\n                 a, -b, \n                 b,  a);\n        }\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f RotationInDegrees(float angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 2D rotation matrix from a <see cref=\"Rot2f\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Rotation(Rot2f r)\n            => (M22f)r;\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f DivideByInt(M22f m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M10;\n                yield return M11;\n            }\n        }\n\n        public readonly IEnumerable<V2f> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n            }\n        }\n\n        public readonly IEnumerable<V2f> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n            }\n        }\n\n        [XmlIgnore]\n        public V2f R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2f( M00,  M01); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2f R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2f( M10,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2f C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2f( M00,  M10); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2f C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2f( M01,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        public readonly V2f Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2f(M00, M11);\n        }\n\n        public readonly V2f AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2f(M01, M10);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly float MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M10, M11);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly float MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M10, M11);\n        }\n\n        public unsafe float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe float this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[row * 2 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[row * 2 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) || float.IsNaN(M01) || \n                    float.IsNaN(M10) || float.IsNaN(M11);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) && float.IsNaN(M01) && \n                    float.IsNaN(M10) && float.IsNaN(M11);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) || float.IsInfinity(M01) || \n                    float.IsInfinity(M10) || float.IsInfinity(M11);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) && float.IsInfinity(M01) && \n                    float.IsInfinity(M10) && float.IsInfinity(M11);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) || float.IsPositiveInfinity(M01) || \n                    float.IsPositiveInfinity(M10) || float.IsPositiveInfinity(M11);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) && float.IsPositiveInfinity(M01) && \n                    float.IsPositiveInfinity(M10) && float.IsPositiveInfinity(M11);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) || float.IsNegativeInfinity(M01) || \n                    float.IsNegativeInfinity(M10) || float.IsNegativeInfinity(M11);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) && float.IsNegativeInfinity(M01) && \n                    float.IsNegativeInfinity(M10) && float.IsNegativeInfinity(M11);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 2;\n        public const int ColumnCount = 2;\n        public const int ElementCount = 2 * 2;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(2, 2);\n        }\n\n        public static M22f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M22f(0);\n        }\n\n        public static M22f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M22f(1, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly float Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + \n                    Fun.Abs(M10) + Fun.Abs(M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly float Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + \n                    M10 * M10 + M11 * M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator -(M22f m)\n        {\n            return new M22f(\n                -m.M00, -m.M01, \n                -m.M10, -m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (M22f a, M22f b)\n        {\n            return new M22f(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (M22f m, float s)\n        {\n            return new M22f(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  + (float s, M22f m)\n        {\n            return new M22f(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (M22f a, M22d b)\n        {\n            return new M22d(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (M22f m, double s)\n        {\n            return new M22d(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (double s, M22f m)\n        {\n            return new M22d(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (M22f a, M22f b)\n        {\n            return new M22f(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (M22f m, float s)\n        {\n            return new M22f(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  - (float s, M22f m)\n        {\n            return new M22f(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (M22f a, M22d b)\n        {\n            return new M22d(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (M22f m, double s)\n        {\n            return new M22d(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (double s, M22f m)\n        {\n            return new M22d(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (M22f a, M22f b)\n        {\n            return new M22f(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (M22f m, float s)\n        {\n            return new M22f(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  % (float s, M22f m)\n        {\n            return new M22f(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (M22f a, M22d b)\n        {\n            return new M22d(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (M22f m, double s)\n        {\n            return new M22d(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (double s, M22f m)\n        {\n            return new M22d(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (M22f a, M22f b)\n        {\n            return new M22f(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (M22f m, float s)\n        {\n            return new M22f(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  / (float s, M22f m)\n        {\n            return new M22f(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (M22f a, M22d b)\n        {\n            return new M22d(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (M22f m, double s)\n        {\n            return new M22d(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (double s, M22f m)\n        {\n            return new M22d(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  * (M22f m, float s)\n        {\n            return new M22f(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator  * (float s, M22f m)\n        {\n            return new M22f(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  * (M22f m, double s)\n        {\n            return new M22d(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  * (double s, M22f m)\n        {\n            return new M22d(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M22f matrix with a V2f column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(M22f m, V2f v)\n        {\n            return new V2f(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y);\n        }\n\n        /// <summary>\n        /// Multiplies a V2f row vector with a M22f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(V2f v, M22f m)\n        {\n            return new V2f(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M22f a, M22f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M22f a, float s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M10 == s && \n                a.M11 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(float s, M22f a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M10  && \n                s == a.M11 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M22f a, M22f b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M22f m, float s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(float s, M22f m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01),\n                        HashCode.GetCombined(M10, M11));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M22f other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && \n                M10.Equals(other.M10) && M11.Equals(other.M11);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M22f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M22f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M22f.FromRows(\n                V2f.Parse(x[0]), \n                V2f.Parse(x[1])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M22f Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return new M22f(M11, -M10, -M01, M00);\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly float Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly float Determinant\n        {\n            get\n            {\n                return M00 * M11 - M10 * M01;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M22f Transposed\n        {\n            get\n            {\n                return new M22f {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    \n                    M10 = M01, \n                    M11 = M11\n                };\n            }\n        }\n\n        private static V2l s_luSize = new V2l(2, 2);\n        private static V2l s_luDelta = new V2l(1, 2);\n\n        /// <summary>\n        /// Inverts the given matrix using lu factorization in place. Returns true\n        /// if the matrix was invertible, otherwise the matrix remains unchanged.\n        /// </summary>\n        public bool LuInvert()\n        {\n            M22d dbl = (M22d)this;\n            if(dbl.LuInvert())\n            {\n                this = (M22f)dbl;\n                return true;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns the inverse of the matrix using lu factorization.\n        /// If the matrix is not invertible, M22f.Zero is returned.\n        /// </summary>\n        public readonly M22f LuInverse()\n        {\n            return (M22f)((M22d)this).LuInverse();\n        }\n\n        /// <summary>\n        /// Returns the inverse of this matrix. If the matrix is not invertible\n        /// M22f.Zero is returned.\n        /// </summary>\n        public readonly M22f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => LuInverse();\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M22f operator *(M22f a, M22f b)\n        {\n            return new M22f(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (float)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (float)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (float)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (float)value;\n        }\n\n        #endregion\n    }\n\n    public class M22fEqualityComparer : IEqualityComparer<M22f>\n    {\n        public static readonly M22fEqualityComparer Default\n            = new M22fEqualityComparer();\n\n        #region IEqualityComparer<M22f> Members\n\n        public bool Equals(M22f v0, M22f v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M22f v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Computes the (signed) angle in radians of a <see cref=\"M22f\"/> rotation matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetRotation(this M22f m)\n            => Fun.Atan2(m.M10, m.M00);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale(this M22f m)\n            => (m.C0.Length + m.C1.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetScaleVector(this M22f m)\n            => new V2f(m.C0.Length, m.C1.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm1(M22f m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm2(M22f m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMax(M22f m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMin(M22f m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(this M22f m, float p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static float Distance1(this M22f a, M22f b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static float Distance2(this M22f a, M22f b)\n        {\n            return (float)Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static float Distance(this M22f a, M22f b, float p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMax(this M22f a, M22f b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMin(this M22f a, M22f b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Transform(this M22f m, V2f v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this M22f m, V3f v)\n        {\n            return new V3f(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this M22f m, V4f v)\n        {\n            return new V4f(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y,\n                v.Z, v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransposedTransform(this M22f m, V2f v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransposedTransform(this M22f m, V3f v)\n        {\n            return new V3f(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f TransposedTransform(this M22f m, V4f v)\n        {\n            return new V4f(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11,\n                v.Z, v.W);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M22f\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static float Minor(this M22f m, int row, int column)\n        {\n            return m[1 - row, 1 - column];\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2f Row(this M22f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V2f(ptr[index * 2], ptr[index * 2 + 1]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2f Column(this M22f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V2f(ptr[index], ptr[index + 2]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Determinant(M22f m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Transposed(M22f m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M22f m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n        }\n\n        /// <summary>\n        /// Returns the inverse of the given matrix. If the matrix is not invertible\n        /// M22f.Zero is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Inverse(M22f m)\n            => m.Inverse;\n\n        /// <summary>\n        /// Inverts the given matrix in place. Returns true if the matrix was invertible,\n        /// otherwise the matrix remains unchanged.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Invert(this ref M22f m) { return m.LuInvert(); }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M22f m, float epsilon)\n        {\n            return Fun.ApproximateEquals(m, M22f.Identity, epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M22f m)\n            => IsIdentity(m, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M22f m, float epsilon)\n        {\n            var i = m * m.Transposed;\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M22f m)\n            => IsOrthonormal(m, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M22f m, float epsilon)\n        {\n            var i = m * m.Transposed;\n            for (int j = 0; j < 2; j++)\n                i[j, j] = 1; //inefficient implementation: just leave out the comparisons at the diagonal entries.\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M22f m)\n            => IsOrthogonal(m, Constant<float>.PositiveTinyValue);\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M22f a, M22f b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M22f m, float s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M10 < s && \n                m.M11 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, M22f m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M10 && \n                s < m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M22f a, M22f b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M22f m, float s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M10 < s || \n                m.M11 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, M22f m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M10 || \n                s < m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M22f a, M22f b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M22f m, float s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M10 > s && \n                m.M11 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, M22f m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M10 && \n                s > m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M22f a, M22f b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M22f m, float s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M10 > s || \n                m.M11 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, M22f m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M10 || \n                s > m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M22f a, M22f b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M22f m, float s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M10 <= s && \n                m.M11 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, M22f m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M10 && \n                s <= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M22f a, M22f b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M22f m, float s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M10 <= s || \n                m.M11 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, M22f m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M10 || \n                s <= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M22f a, M22f b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M22f m, float s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M10 >= s && \n                m.M11 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, M22f m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M10 && \n                s >= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M22f a, M22f b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M22f m, float s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M10 >= s || \n                m.M11 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, M22f m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M10 || \n                s >= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M22f a, M22f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M22f m, float s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M10 == s && \n                m.M11 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, M22f m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M10 && \n                s == m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M22f a, M22f b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M22f m, float s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M10 == s || \n                m.M11 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, M22f m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M10 || \n                s == m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M22f a, M22f b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M22f m, float s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M10 != s && \n                m.M11 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, M22f m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M10 && \n                s != m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M22f a, M22f b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M22f m, float s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M10 != s || \n                m.M11 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, M22f m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M10 || \n                s != m.M11;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M22f m0, M22f m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M22f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MinElement(M22f m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M22f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MaxElement(M22f m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region Orthogonalization\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M22f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthogonalize(this ref M22f matrix)\n        {\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n        }\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M22f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Orthogonalized(this M22f matrix)\n        {\n            M22f m = matrix;\n            Orthogonalize(ref m);\n            return m;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M22f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthonormalize(this ref M22f matrix)\n        {\n            matrix.C0 = matrix.C0.Normalized;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 = matrix.C1.Normalized;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M22f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Orthonormalized(this M22f matrix)\n        {\n            M22f m = matrix;\n            Orthonormalize(ref m);\n            return m;\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M22f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M22f m, float epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M22f m, float epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M22f m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M22f m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M22f m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M22f m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M22f m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M22f m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M22f m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M22f m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M22f m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M22f m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M22f m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M22f m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M22f a, M22f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M22f a, M22f b, float epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M22f m, float epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M22f m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M22f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M22f v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M22f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M22f v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M22f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M22f v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M22f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M22f v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M22f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M22f v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM22fExtensions\n    {\n        #region IRandomUniform extensions for M22f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of an M22f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f UniformM22f(this IRandomUniform rnd)\n        {\n            return new M22f(\n                rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of an M22f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f UniformM22fClosed(this IRandomUniform rnd)\n        {\n            return new M22f(\n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of an M22f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f UniformM22fOpen(this IRandomUniform rnd)\n        {\n            return new M22f(\n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M22d\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M22d : IEquatable<M22d>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public double M00, M01;\n        [DataMember]\n        public double M10, M11;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(double value)\n        {\n            M00 = value; M01 = 0; \n            M10 = 0; M11 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(\n                double m00, double m01, \n                double m10, double m11)\n        {\n            M00 = m00; M01 = m01; \n            M10 = m10; M11 = m11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(double[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M10 = a[2];\n            M11 = a[3];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(double[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M10 = a[start + 2];\n            M11 = a[start + 3];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M22i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M23i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M33i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M34i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M44i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M22l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M23l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M33l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M34l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M44l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M22f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M23f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M33f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M34f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M44f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; \n            M10 = (double)m.M10; M11 = (double)m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M23d m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M33d m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M34d m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M22d(M44d m)\n        {\n            M00 = m.M00; M01 = m.M01; \n            M10 = m.M10; M11 = m.M11; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M22d(M22i m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M23i m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M33i m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M34i m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M44i m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M22l m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M23l m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M33l m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M34l m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M44l m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M22f m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M23f m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M33f m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M34f m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M44f m)\n        {\n            return new M22d {\n                M00 = (double)m.M00, M01 = (double)m.M01, \n                M10 = (double)m.M10, M11 = (double)m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M23d m)\n        {\n            return new M22d {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M33d m)\n        {\n            return new M22d {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M34d m)\n        {\n            return new M22d {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22d(M44d m)\n        {\n            return new M22d {\n                M00 = m.M00, M01 = m.M01, \n                M10 = m.M10, M11 = m.M11, \n            };\n        }\n\n        public static explicit operator M22d(int[] a)\n        {\n            return new M22d(\n                (double)a[0], (double)a[1], \n                (double)a[2], (double)a[3]);\n        }\n\n        public static explicit operator M22d(int[,] a)\n        {\n            return new M22d(\n                (double)a[0, 0], (double)a[0, 1], \n                (double)a[1, 0], (double)a[1, 1]);\n        }\n\n        public static explicit operator int[](M22d m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, \n                (int)m.M10, (int)m.M11\n            };\n        }\n\n        public static explicit operator int[,](M22d m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01 }, \n                { (int)m.M10, (int)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M10;\n            array[index + 3] = (int)M11;\n        }\n\n        public static explicit operator M22d(long[] a)\n        {\n            return new M22d(\n                (double)a[0], (double)a[1], \n                (double)a[2], (double)a[3]);\n        }\n\n        public static explicit operator M22d(long[,] a)\n        {\n            return new M22d(\n                (double)a[0, 0], (double)a[0, 1], \n                (double)a[1, 0], (double)a[1, 1]);\n        }\n\n        public static explicit operator long[](M22d m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, \n                (long)m.M10, (long)m.M11\n            };\n        }\n\n        public static explicit operator long[,](M22d m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01 }, \n                { (long)m.M10, (long)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M10;\n            array[index + 3] = (long)M11;\n        }\n\n        public static explicit operator M22d(float[] a)\n        {\n            return new M22d(\n                (double)a[0], (double)a[1], \n                (double)a[2], (double)a[3]);\n        }\n\n        public static explicit operator M22d(float[,] a)\n        {\n            return new M22d(\n                (double)a[0, 0], (double)a[0, 1], \n                (double)a[1, 0], (double)a[1, 1]);\n        }\n\n        public static explicit operator float[](M22d m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, \n                (float)m.M10, (float)m.M11\n            };\n        }\n\n        public static explicit operator float[,](M22d m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01 }, \n                { (float)m.M10, (float)m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M10;\n            array[index + 3] = (float)M11;\n        }\n\n        public static explicit operator M22d(double[] a)\n        {\n            return new M22d(\n                a[0], a[1], \n                a[2], a[3]);\n        }\n\n        public static explicit operator M22d(double[,] a)\n        {\n            return new M22d(\n                a[0, 0], a[0, 1], \n                a[1, 0], a[1, 1]);\n        }\n\n        public static explicit operator double[](M22d m)\n        {\n            return new double[] {\n                m.M00, m.M01, \n                m.M10, m.M11\n            };\n        }\n\n        public static explicit operator double[,](M22d m)\n        {\n            return new double[,] {\n                { m.M00, m.M01 }, \n                { m.M10, m.M11 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M10;\n            array[index + 3] = M11;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22i Copy(Func<double, int> element_fun)\n        {\n            return new M22i(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22i Copy(Func<double, int, int, int> element_index0_index1_fun)\n        {\n            return new M22i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22l Copy(Func<double, long> element_fun)\n        {\n            return new M22l(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22l Copy(Func<double, int, int, long> element_index0_index1_fun)\n        {\n            return new M22l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22f Copy(Func<double, float> element_fun)\n        {\n            return new M22f(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22f Copy(Func<double, int, int, float> element_index0_index1_fun)\n        {\n            return new M22f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22d Copy(Func<double, double> element_fun)\n        {\n            return new M22d(\n                element_fun(M00), element_fun(M01), \n                element_fun(M10), element_fun(M11));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M22d Copy(Func<double, int, int, double> element_index0_index1_fun)\n        {\n            return new M22d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1));\n        }\n\n        public readonly double[] ToArray()\n        {\n            var array = new double[4];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M10;\n            array[3] = M11;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d FromCols(V2d col0, V2d col1)\n        {\n            return new M22d(\n                col0.X, col1.X, \n                col0.Y, col1.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d FromRows(V2d row0, V2d row1)\n        {\n            return new M22d(\n                row0.X, row0.Y, \n                row1.X, row1.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d FromDiagonal(double value)\n        {\n            return new M22d(\n                value, 0, \n                0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d FromDiagonal(double m00, double m11)\n        {\n            return new M22d(\n                m00, 0, \n                0, m11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d FromDiagonal(V2d s)\n        {\n            return new M22d(\n                s.X, 0, \n                0, s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d FromAntiDiagonal(double value)\n        {\n            return new M22d(\n                 0, value, \n                 value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d FromAntiDiagonal(double m01, double m10)\n        {\n            return new M22d(\n                0, m01, \n                m10, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d FromAntiDiagonal(V2d s)\n        {\n            return new M22d(\n                0, s.X, \n                s.Y, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22d\"/> using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Scale(double sX, double sY)\n            => FromDiagonal(sX, sY);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22d\"/> using a <see cref=\"V2d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Scale(V2d s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M22d\"/> from a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Scale(Scale2d s)\n        {\n            return new M22d(\n                s.X, 0, \n                0, s.Y);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Rotation(double angleInRadians)\n        {\n            var a = Fun.Cos(angleInRadians);\n            var b = Fun.Sin(angleInRadians);\n\n            return new M22d(\n                 a, -b, \n                 b,  a);\n        }\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d RotationInDegrees(double angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 2D rotation matrix from a <see cref=\"Rot2d\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Rotation(Rot2d r)\n            => (M22d)r;\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d DivideByInt(M22d m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M10;\n                yield return M11;\n            }\n        }\n\n        public readonly IEnumerable<V2d> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n            }\n        }\n\n        public readonly IEnumerable<V2d> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n            }\n        }\n\n        [XmlIgnore]\n        public V2d R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2d( M00,  M01); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2d R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2d( M10,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2d C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2d( M00,  M10); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2d C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2d( M01,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        public readonly V2d Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2d(M00, M11);\n        }\n\n        public readonly V2d AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2d(M01, M10);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly double MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M10, M11);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly double MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M10, M11);\n        }\n\n        public unsafe double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe double this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[row * 2 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[row * 2 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) || double.IsNaN(M01) || \n                    double.IsNaN(M10) || double.IsNaN(M11);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) && double.IsNaN(M01) && \n                    double.IsNaN(M10) && double.IsNaN(M11);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) || double.IsInfinity(M01) || \n                    double.IsInfinity(M10) || double.IsInfinity(M11);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) && double.IsInfinity(M01) && \n                    double.IsInfinity(M10) && double.IsInfinity(M11);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) || double.IsPositiveInfinity(M01) || \n                    double.IsPositiveInfinity(M10) || double.IsPositiveInfinity(M11);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) && double.IsPositiveInfinity(M01) && \n                    double.IsPositiveInfinity(M10) && double.IsPositiveInfinity(M11);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) || double.IsNegativeInfinity(M01) || \n                    double.IsNegativeInfinity(M10) || double.IsNegativeInfinity(M11);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) && double.IsNegativeInfinity(M01) && \n                    double.IsNegativeInfinity(M10) && double.IsNegativeInfinity(M11);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 2;\n        public const int ColumnCount = 2;\n        public const int ElementCount = 2 * 2;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(2, 2);\n        }\n\n        public static M22d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M22d(0);\n        }\n\n        public static M22d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M22d(1, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly double Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + \n                    Fun.Abs(M10) + Fun.Abs(M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + \n                    M10 * M10 + M11 * M11);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator -(M22d m)\n        {\n            return new M22d(\n                -m.M00, -m.M01, \n                -m.M10, -m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (M22d a, M22d b)\n        {\n            return new M22d(\n                a.M00 + b.M00, a.M01 + b.M01, \n                a.M10 + b.M10, a.M11 + b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (M22d m, double s)\n        {\n            return new M22d(\n                m.M00 + s, m.M01 + s, \n                m.M10 + s, m.M11 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  + (double s, M22d m)\n        {\n            return new M22d(\n                s + m.M00, s + m.M01, \n                s + m.M10, s + m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (M22d a, M22d b)\n        {\n            return new M22d(\n                a.M00 - b.M00, a.M01 - b.M01, \n                a.M10 - b.M10, a.M11 - b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (M22d m, double s)\n        {\n            return new M22d(\n                m.M00 - s, m.M01 - s, \n                m.M10 - s, m.M11 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  - (double s, M22d m)\n        {\n            return new M22d(\n                s - m.M00, s - m.M01, \n                s - m.M10, s - m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (M22d a, M22d b)\n        {\n            return new M22d(\n                a.M00 % b.M00, a.M01 % b.M01, \n                a.M10 % b.M10, a.M11 % b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (M22d m, double s)\n        {\n            return new M22d(\n                m.M00 % s, m.M01 % s, \n                m.M10 % s, m.M11 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  % (double s, M22d m)\n        {\n            return new M22d(\n                s % m.M00, s % m.M01, \n                s % m.M10, s % m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (M22d a, M22d b)\n        {\n            return new M22d(\n                a.M00 / b.M00, a.M01 / b.M01, \n                a.M10 / b.M10, a.M11 / b.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (M22d m, double s)\n        {\n            return new M22d(\n                m.M00 / s, m.M01 / s, \n                m.M10 / s, m.M11 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  / (double s, M22d m)\n        {\n            return new M22d(\n                s / m.M00, s / m.M01, \n                s / m.M10, s / m.M11);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  * (M22d m, double s)\n        {\n            return new M22d(\n                m.M00 * s, m.M01 * s, \n                m.M10 * s, m.M11 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator  * (double s, M22d m)\n        {\n            return new M22d(\n                s * m.M00, s * m.M01, \n                s * m.M10, s * m.M11);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M22d matrix with a V2d column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(M22d m, V2d v)\n        {\n            return new V2d(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y);\n        }\n\n        /// <summary>\n        /// Multiplies a V2d row vector with a M22d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(V2d v, M22d m)\n        {\n            return new V2d(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M22d a, M22d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M22d a, double s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M10 == s && \n                a.M11 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(double s, M22d a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M10  && \n                s == a.M11 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M22d a, M22d b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M22d m, double s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(double s, M22d m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01),\n                        HashCode.GetCombined(M10, M11));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M22d other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && \n                M10.Equals(other.M10) && M11.Equals(other.M11);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M22d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M22d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M22d.FromRows(\n                V2d.Parse(x[0]), \n                V2d.Parse(x[1])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M22d Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return new M22d(M11, -M10, -M01, M00);\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly double Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly double Determinant\n        {\n            get\n            {\n                return M00 * M11 - M10 * M01;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M22d Transposed\n        {\n            get\n            {\n                return new M22d {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    \n                    M10 = M01, \n                    M11 = M11\n                };\n            }\n        }\n\n        private static V2l s_luSize = new V2l(2, 2);\n        private static V2l s_luDelta = new V2l(1, 2);\n\n        /// <summary>\n        /// Inverts the given matrix using lu factorization in place. Returns true\n        /// if the matrix was invertible, otherwise the matrix remains unchanged.\n        /// </summary>\n        public unsafe bool LuInvert()\n        {\n            fixed (M22d* self = &this)\n            {\n                var lu = this;\n                V2i perm;\n                if (NumericExtensions.LuFactorize((double*)&lu, 0, 1, 2, (int*)&perm, 2))\n                {\n                    NumericExtensions.LuInverse((double*)&lu, 0, 1, 2, (int*)&perm, (double*)self, 0, 1, 2, 2);\n                    return true;\n                }\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns the inverse of the matrix using lu factorization.\n        /// If the matrix is not invertible, M22d.Zero is returned.\n        /// </summary>\n        public unsafe readonly M22d LuInverse()\n        {\n            var lu = this;\n            M22d res;\n            V2i perm;\n            if (NumericExtensions.LuFactorize((double*)&lu, 0, 1, 2, (int*)&perm, 2))\n            {\n                NumericExtensions.LuInverse((double*)&lu, 0, 1, 2, (int*)&perm, (double*)&res, 0, 1, 2, 2);\n                return res;\n            }\n            return M22d.Zero;\n        }\n\n        /// <summary>\n        /// Returns the inverse of this matrix. If the matrix is not invertible\n        /// M22d.Zero is returned.\n        /// </summary>\n        public readonly M22d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => LuInverse();\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M22d operator *(M22d a, M22d b)\n        {\n            return new M22d(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (double)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (double)value;\n        }\n\n        #endregion\n    }\n\n    public class M22dEqualityComparer : IEqualityComparer<M22d>\n    {\n        public static readonly M22dEqualityComparer Default\n            = new M22dEqualityComparer();\n\n        #region IEqualityComparer<M22d> Members\n\n        public bool Equals(M22d v0, M22d v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M22d v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Computes the (signed) angle in radians of a <see cref=\"M22d\"/> rotation matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetRotation(this M22d m)\n            => Fun.Atan2(m.M10, m.M00);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M22d m)\n            => (m.C0.Length + m.C1.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector(this M22d m)\n            => new V2d(m.C0.Length, m.C1.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm1(M22d m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M22d m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMax(M22d m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMin(M22d m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M22d m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static double Distance1(this M22d a, M22d b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M22d a, M22d b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M22d a, M22d b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMax(this M22d a, M22d b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMin(this M22d a, M22d b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Transform(this M22d m, V2d v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this M22d m, V3d v)\n        {\n            return new V3d(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this M22d m, V4d v)\n        {\n            return new V4d(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y,\n                v.Z, v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransposedTransform(this M22d m, V2d v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransposedTransform(this M22d m, V3d v)\n        {\n            return new V3d(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11,\n                v.Z);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d TransposedTransform(this M22d m, V4d v)\n        {\n            return new V4d(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11,\n                v.Z, v.W);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M22d\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static double Minor(this M22d m, int row, int column)\n        {\n            return m[1 - row, 1 - column];\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2d Row(this M22d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V2d(ptr[index * 2], ptr[index * 2 + 1]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2d Column(this M22d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V2d(ptr[index], ptr[index + 2]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Determinant(M22d m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Transposed(M22d m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M22d m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n        }\n\n        /// <summary>\n        /// Returns the inverse of the given matrix. If the matrix is not invertible\n        /// M22d.Zero is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Inverse(M22d m)\n            => m.Inverse;\n\n        /// <summary>\n        /// Inverts the given matrix in place. Returns true if the matrix was invertible,\n        /// otherwise the matrix remains unchanged.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Invert(this ref M22d m) { return m.LuInvert(); }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M22d m, double epsilon)\n        {\n            return Fun.ApproximateEquals(m, M22d.Identity, epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M22d m)\n            => IsIdentity(m, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M22d m, double epsilon)\n        {\n            var i = m * m.Transposed;\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M22d m)\n            => IsOrthonormal(m, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M22d m, double epsilon)\n        {\n            var i = m * m.Transposed;\n            for (int j = 0; j < 2; j++)\n                i[j, j] = 1; //inefficient implementation: just leave out the comparisons at the diagonal entries.\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M22d m)\n            => IsOrthogonal(m, Constant<double>.PositiveTinyValue);\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M22d a, M22d b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M22d m, double s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M10 < s && \n                m.M11 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, M22d m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M10 && \n                s < m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M22d a, M22d b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M22d m, double s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M10 < s || \n                m.M11 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, M22d m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M10 || \n                s < m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M22d a, M22d b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M22d m, double s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M10 > s && \n                m.M11 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, M22d m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M10 && \n                s > m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M22d a, M22d b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M22d m, double s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M10 > s || \n                m.M11 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, M22d m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M10 || \n                s > m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M22d a, M22d b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M22d m, double s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M10 <= s && \n                m.M11 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, M22d m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M10 && \n                s <= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M22d a, M22d b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M22d m, double s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M10 <= s || \n                m.M11 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, M22d m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M10 || \n                s <= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M22d a, M22d b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M22d m, double s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M10 >= s && \n                m.M11 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, M22d m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M10 && \n                s >= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M22d a, M22d b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M22d m, double s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M10 >= s || \n                m.M11 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, M22d m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M10 || \n                s >= m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M22d a, M22d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M22d m, double s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M10 == s && \n                m.M11 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, M22d m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M10 && \n                s == m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M22d a, M22d b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M22d m, double s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M10 == s || \n                m.M11 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, M22d m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M10 || \n                s == m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M22d a, M22d b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M22d m, double s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M10 != s && \n                m.M11 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, M22d m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M10 && \n                s != m.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M22d a, M22d b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M22d m, double s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M10 != s || \n                m.M11 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, M22d m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M10 || \n                s != m.M11;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M22d m0, M22d m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M22d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MinElement(M22d m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M22d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MaxElement(M22d m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region Orthogonalization\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M22d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthogonalize(this ref M22d matrix)\n        {\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n        }\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M22d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Orthogonalized(this M22d matrix)\n        {\n            M22d m = matrix;\n            Orthogonalize(ref m);\n            return m;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M22d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthonormalize(this ref M22d matrix)\n        {\n            matrix.C0 = matrix.C0.Normalized;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 = matrix.C1.Normalized;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M22d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Orthonormalized(this M22d matrix)\n        {\n            M22d m = matrix;\n            Orthonormalize(ref m);\n            return m;\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M22d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M22d m, double epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M22d m, double epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M22d m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M22d m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M22d m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M22d m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M22d m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M22d m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M22d m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M22d m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M22d m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M22d m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M22d m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M22d m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M22d a, M22d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M22d a, M22d b, double epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M22d m, double epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M22d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M22d m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M22d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M22d v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M22d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M22d v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M22d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M22d v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M22d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M22d v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M22d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M22d v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM22dExtensions\n    {\n        #region IRandomUniform extensions for M22d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of an M22d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d UniformM22d(this IRandomUniform rnd)\n        {\n            return new M22d(\n                rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of an M22d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d UniformM22dClosed(this IRandomUniform rnd)\n        {\n            return new M22d(\n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of an M22d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d UniformM22dOpen(this IRandomUniform rnd)\n        {\n            return new M22d(\n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of an M22d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d UniformM22dFull(this IRandomUniform rnd)\n        {\n            return new M22d(\n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of an M22d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d UniformM22dFullClosed(this IRandomUniform rnd)\n        {\n            return new M22d(\n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of an M22d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d UniformM22dFullOpen(this IRandomUniform rnd)\n        {\n            return new M22d(\n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M23i\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M23i : IEquatable<M23i>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public int M00, M01, M02;\n        [DataMember]\n        public int M10, M11, M12;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(int value)\n        {\n            M00 = value; M01 = 0; M02 = 0; \n            M10 = 0; M11 = value; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(\n                int m00, int m01, int m02, \n                int m10, int m11, int m12)\n        {\n            M00 = m00; M01 = m01; M02 = m02; \n            M10 = m10; M11 = m11; M12 = m12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(int[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M10 = a[3];\n            M11 = a[4];\n            M12 = a[5];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(int[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M10 = a[start + 3];\n            M11 = a[start + 4];\n            M12 = a[start + 5];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M22i m, V2i v)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = v.X; \n            M10 = m.M10; M11 = m.M11; M12 = v.Y; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M22i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M33i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M34i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M44i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M22l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M23l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M33l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M34l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M44l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M22f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M23f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M33f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M34f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M44f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M22d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M23d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M33d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M34d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23i(M44d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M23i(M22i m)\n        {\n            return new M23i {\n                M00 = m.M00, M01 = m.M01, M02 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23i(M33i m)\n        {\n            return new M23i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M34i m)\n        {\n            return new M23i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M44i m)\n        {\n            return new M23i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M22l m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23i(M23l m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M33l m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M34l m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M44l m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M22f m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23i(M23f m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M33f m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M34f m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M44f m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M22d m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23i(M23d m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M33d m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M34d m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(M44d m)\n        {\n            return new M23i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n            };\n        }\n\n        public static explicit operator M23i(int[] a)\n        {\n            return new M23i(\n                a[0], a[1], a[2], \n                a[3], a[4], a[5]);\n        }\n\n        public static explicit operator M23i(int[,] a)\n        {\n            return new M23i(\n                a[0, 0], a[0, 1], a[0, 2], \n                a[1, 0], a[1, 1], a[1, 2]);\n        }\n\n        public static explicit operator int[](M23i m)\n        {\n            return new int[] {\n                m.M00, m.M01, m.M02, \n                m.M10, m.M11, m.M12\n            };\n        }\n\n        public static explicit operator int[,](M23i m)\n        {\n            return new int[,] {\n                { m.M00, m.M01, m.M02 }, \n                { m.M10, m.M11, m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M10;\n            array[index + 4] = M11;\n            array[index + 5] = M12;\n        }\n\n        public static explicit operator M23i(long[] a)\n        {\n            return new M23i(\n                (int)a[0], (int)a[1], (int)a[2], \n                (int)a[3], (int)a[4], (int)a[5]);\n        }\n\n        public static explicit operator M23i(long[,] a)\n        {\n            return new M23i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2]);\n        }\n\n        public static explicit operator long[](M23i m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, \n                (long)m.M10, (long)m.M11, (long)m.M12\n            };\n        }\n\n        public static explicit operator long[,](M23i m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M10;\n            array[index + 4] = (long)M11;\n            array[index + 5] = (long)M12;\n        }\n\n        public static explicit operator M23i(float[] a)\n        {\n            return new M23i(\n                (int)a[0], (int)a[1], (int)a[2], \n                (int)a[3], (int)a[4], (int)a[5]);\n        }\n\n        public static explicit operator M23i(float[,] a)\n        {\n            return new M23i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2]);\n        }\n\n        public static explicit operator float[](M23i m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, \n                (float)m.M10, (float)m.M11, (float)m.M12\n            };\n        }\n\n        public static explicit operator float[,](M23i m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M10;\n            array[index + 4] = (float)M11;\n            array[index + 5] = (float)M12;\n        }\n\n        public static explicit operator M23i(double[] a)\n        {\n            return new M23i(\n                (int)a[0], (int)a[1], (int)a[2], \n                (int)a[3], (int)a[4], (int)a[5]);\n        }\n\n        public static explicit operator M23i(double[,] a)\n        {\n            return new M23i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2]);\n        }\n\n        public static explicit operator double[](M23i m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, \n                (double)m.M10, (double)m.M11, (double)m.M12\n            };\n        }\n\n        public static explicit operator double[,](M23i m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M10;\n            array[index + 4] = (double)M11;\n            array[index + 5] = (double)M12;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23i Copy(Func<int, int> element_fun)\n        {\n            return new M23i(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23i Copy(Func<int, int, int, int> element_index0_index1_fun)\n        {\n            return new M23i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23l Copy(Func<int, long> element_fun)\n        {\n            return new M23l(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23l Copy(Func<int, int, int, long> element_index0_index1_fun)\n        {\n            return new M23l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23f Copy(Func<int, float> element_fun)\n        {\n            return new M23f(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23f Copy(Func<int, int, int, float> element_index0_index1_fun)\n        {\n            return new M23f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23d Copy(Func<int, double> element_fun)\n        {\n            return new M23d(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23d Copy(Func<int, int, int, double> element_index0_index1_fun)\n        {\n            return new M23d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        public readonly int[] ToArray()\n        {\n            var array = new int[6];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M10;\n            array[4] = M11;\n            array[5] = M12;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i FromCols(V2i col0, V2i col1, V2i col2)\n        {\n            return new M23i(\n                col0.X, col1.X, col2.X, \n                col0.Y, col1.Y, col2.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i FromRows(V3i row0, V3i row1)\n        {\n            return new M23i(\n                row0.X, row0.Y, row0.Z, \n                row1.X, row1.Y, row1.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i FromDiagonal(int value)\n        {\n            return new M23i(\n                value, 0, 0, \n                0, value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i FromDiagonal(int m00, int m11)\n        {\n            return new M23i(\n                m00, 0, 0, \n                0, m11, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i FromDiagonal(V2i s)\n        {\n            return new M23i(\n                s.X, 0, 0, \n                0, s.Y, 0);\n        }\n\n        #region Scale\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23i\"/> with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i Translation(int tX, int tY)\n        {\n            return new M23i(\n                1, 0, tX, \n                0, 1, tY);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23i\"/> with the translational component given by a <see cref=\"V2i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i Translation(V2i t)\n        {\n            return new M23i(\n                1, 0, t.X, \n                0, 1, t.Y);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i DivideByInt(M23i m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n            }\n        }\n\n        public readonly IEnumerable<V3i> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n            }\n        }\n\n        public readonly IEnumerable<V2i> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M00,  M01,  M02); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M10,  M11,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V2i C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2i( M00,  M10); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2i C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2i( M01,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2i C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2i( M02,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n            }\n        }\n\n        public readonly V2i Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2i(M00, M11);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly int MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M10, M11, M12);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly int MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M10, M11, M12);\n        }\n\n        public unsafe int this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe int this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[row * 3 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[row * 3 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 2;\n        public const int ColumnCount = 3;\n        public const int ElementCount = 2 * 3;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(2, 3);\n        }\n\n        public static M23i Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M23i(0);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly int Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + \n                    M10 * M10 + M11 * M11 + M12 * M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator -(M23i m)\n        {\n            return new M23i(\n                -m.M00, -m.M01, -m.M02, \n                -m.M10, -m.M11, -m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  + (M23i a, M23i b)\n        {\n            return new M23i(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  + (M23i m, int s)\n        {\n            return new M23i(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  + (int s, M23i m)\n        {\n            return new M23i(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  + (M23i a, M23l b)\n        {\n            return new M23l(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  + (M23i m, long s)\n        {\n            return new M23l(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  + (long s, M23i m)\n        {\n            return new M23l(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (M23i a, M23f b)\n        {\n            return new M23f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (M23i m, float s)\n        {\n            return new M23f(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (float s, M23i m)\n        {\n            return new M23f(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (M23i a, M23d b)\n        {\n            return new M23d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (M23i m, double s)\n        {\n            return new M23d(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (double s, M23i m)\n        {\n            return new M23d(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  - (M23i a, M23i b)\n        {\n            return new M23i(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  - (M23i m, int s)\n        {\n            return new M23i(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  - (int s, M23i m)\n        {\n            return new M23i(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  - (M23i a, M23l b)\n        {\n            return new M23l(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  - (M23i m, long s)\n        {\n            return new M23l(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  - (long s, M23i m)\n        {\n            return new M23l(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (M23i a, M23f b)\n        {\n            return new M23f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (M23i m, float s)\n        {\n            return new M23f(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (float s, M23i m)\n        {\n            return new M23f(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (M23i a, M23d b)\n        {\n            return new M23d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (M23i m, double s)\n        {\n            return new M23d(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (double s, M23i m)\n        {\n            return new M23d(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  % (M23i a, M23i b)\n        {\n            return new M23i(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  % (M23i m, int s)\n        {\n            return new M23i(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  % (int s, M23i m)\n        {\n            return new M23i(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  % (M23i a, M23l b)\n        {\n            return new M23l(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  % (M23i m, long s)\n        {\n            return new M23l(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  % (long s, M23i m)\n        {\n            return new M23l(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (M23i a, M23f b)\n        {\n            return new M23f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (M23i m, float s)\n        {\n            return new M23f(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (float s, M23i m)\n        {\n            return new M23f(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (M23i a, M23d b)\n        {\n            return new M23d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (M23i m, double s)\n        {\n            return new M23d(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (double s, M23i m)\n        {\n            return new M23d(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  / (M23i a, M23i b)\n        {\n            return new M23i(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  / (M23i m, int s)\n        {\n            return new M23i(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  / (int s, M23i m)\n        {\n            return new M23i(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  / (M23i a, M23l b)\n        {\n            return new M23l(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  / (M23i m, long s)\n        {\n            return new M23l(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  / (long s, M23i m)\n        {\n            return new M23l(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (M23i a, M23f b)\n        {\n            return new M23f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (M23i m, float s)\n        {\n            return new M23f(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (float s, M23i m)\n        {\n            return new M23f(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (M23i a, M23d b)\n        {\n            return new M23d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (M23i m, double s)\n        {\n            return new M23d(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (double s, M23i m)\n        {\n            return new M23d(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  * (M23i m, int s)\n        {\n            return new M23i(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator  * (int s, M23i m)\n        {\n            return new M23i(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  * (M23i m, long s)\n        {\n            return new M23l(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  * (long s, M23i m)\n        {\n            return new M23l(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  * (M23i m, float s)\n        {\n            return new M23f(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  * (float s, M23i m)\n        {\n            return new M23f(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  * (M23i m, double s)\n        {\n            return new M23d(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  * (double s, M23i m)\n        {\n            return new M23d(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator ~(M23i m)\n        {\n            return new M23i(\n                ~m.M00, ~m.M01, ~m.M02, \n                ~m.M10, ~m.M11, ~m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator <<(M23i a, int s)\n        {\n            return new M23i(\n                a.M00 << s, a.M01 << s, a.M02 << s, \n                a.M10 << s, a.M11 << s, a.M12 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator >>(M23i a, int s)\n        {\n            return new M23i(\n                a.M00 >> s, a.M01 >> s, a.M02 >> s, \n                a.M10 >> s, a.M11 >> s, a.M12 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator &(M23i a, M23i b)\n        {\n            return new M23i(\n                a.M00 & b.M00, a.M01 & b.M01, a.M02 & b.M02, \n                a.M10 & b.M10, a.M11 & b.M11, a.M12 & b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator &(M23i a, int s)\n        {\n            return new M23i(\n                a.M00 & s, a.M01 & s, a.M02 & s, \n                a.M10 & s, a.M11 & s, a.M12 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator &(int s, M23i a)\n        {\n            return new M23i(\n                s & a.M00, s & a.M01, s & a.M02, \n                s & a.M10, s & a.M11, s & a.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator |(M23i a, M23i b)\n        {\n            return new M23i(\n                a.M00 | b.M00, a.M01 | b.M01, a.M02 | b.M02, \n                a.M10 | b.M10, a.M11 | b.M11, a.M12 | b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator |(M23i a, int s)\n        {\n            return new M23i(\n                a.M00 | s, a.M01 | s, a.M02 | s, \n                a.M10 | s, a.M11 | s, a.M12 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator |(int s, M23i a)\n        {\n            return new M23i(\n                s | a.M00, s | a.M01, s | a.M02, \n                s | a.M10, s | a.M11, s | a.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator ^(M23i a, M23i b)\n        {\n            return new M23i(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, a.M02 ^ b.M02, \n                a.M10 ^ b.M10, a.M11 ^ b.M11, a.M12 ^ b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator ^(M23i a, int s)\n        {\n            return new M23i(\n                a.M00 ^ s, a.M01 ^ s, a.M02 ^ s, \n                a.M10 ^ s, a.M11 ^ s, a.M12 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i operator ^(int s, M23i a)\n        {\n            return new M23i(\n                s ^ a.M00, s ^ a.M01, s ^ a.M02, \n                s ^ a.M10, s ^ a.M11, s ^ a.M12);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M23i matrix with a V3i column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator *(M23i m, V3i v)\n        {\n            return new V2i(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a V2i row vector with a M23i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator *(V2i v, M23i m)\n        {\n            return new V3i(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11, \n                v.X * m.M02 + v.Y * m.M12);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M23i a, M23i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M23i a, int s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(int s, M23i a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M23i a, M23i b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M23i m, int s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(int s, M23i m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02),\n                        HashCode.GetCombined(M10, M11, M12));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M23i other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M23i o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M23i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M23i.FromRows(\n                V3i.Parse(x[0]), \n                V3i.Parse(x[1])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M23i operator *(M22i a, M23i b)\n        {\n            return new M23i(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M00 * b.M02 + a.M01 * b.M12, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11, \n                a.M10 * b.M02 + a.M11 * b.M12\n             );\n        }\n\n        public static M23i operator *(M23i a, M33i b)\n        {\n            return new M23i(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (int)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (int)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (int)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (int)value;\n        }\n\n        #endregion\n    }\n\n    public class M23iEqualityComparer : IEqualityComparer<M23i>\n    {\n        public static readonly M23iEqualityComparer Default\n            = new M23iEqualityComparer();\n\n        #region IEqualityComparer<M23i> Members\n\n        public bool Equals(M23i v0, M23i v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M23i v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M23i m)\n            => (m.C0.Length + m.C1.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector(this M23i m)\n            => new V2d(m.C0.Length, m.C1.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Norm1(M23i m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M23i m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMax(M23i m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMin(M23i m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M23i m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static int Distance1(this M23i a, M23i b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M23i a, M23i b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M23i a, M23i b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMax(this M23i a, M23i b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMin(this M23i a, M23i b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Transform(this M23i m, V3i v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Transform(this M23i m, V4i v)\n        {\n            return new V3i(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i TransposedTransform(this M23i m, V2i v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V2i TransformDir(this M23i m, V2i v)\n        {\n            return new V2i(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by matrix m.\n        /// </summary>\n        public static V2i TransformPos(this M23i m, V2i p)\n        {\n            return new V2i(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12\n                );\n        }\n\n        /// <summary>\n        /// Multiplies two <see cref=\"M23i\"/> matrices as 3x3 matrices.\n        /// </summary>\n        public static M23i MultiplyAffine(this M23i a, M23i b)\n        {\n            return new M23i(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3i Row(this M23i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V3i(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2i Column(this M23i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V2i(ptr[index], ptr[index + 3]);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M23i a, M23i b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M23i m, int s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(int s, M23i m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M23i a, M23i b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M23i m, int s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(int s, M23i m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M23i a, M23i b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M23i m, int s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(int s, M23i m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M23i a, M23i b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M23i m, int s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(int s, M23i m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M23i a, M23i b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M23i m, int s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(int s, M23i m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M23i a, M23i b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M23i m, int s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(int s, M23i m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M23i a, M23i b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M23i m, int s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(int s, M23i m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M23i a, M23i b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M23i m, int s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(int s, M23i m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M23i a, M23i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M23i m, int s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(int s, M23i m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M23i a, M23i b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M23i m, int s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(int s, M23i m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M23i a, M23i b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M23i m, int s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(int s, M23i m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M23i a, M23i b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M23i m, int s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(int s, M23i m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M23i m0, M23i m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M23i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MinElement(M23i m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M23i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MaxElement(M23i m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M23i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M23i m, int epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M23i m, int epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M23i a, M23i b, int epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M23i m, int epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM23iExtensions\n    {\n        #region IRandomUniform extensions for M23i\n\n        /// <summary>\n        /// Uses UniformInt() to generate the elements of an M23i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i UniformM23i(this IRandomUniform rnd)\n        {\n            return new M23i(\n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt());\n        }\n\n        /// <summary>\n        /// Uses UniformIntNonZero() to generate the elements of an M23i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i UniformM23iNonZero(this IRandomUniform rnd)\n        {\n            return new M23i(\n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M23i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i UniformM23i(this IRandomUniform rnd, int size)\n        {\n            return new M23i(\n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size));\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M23i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23i UniformM23i(this IRandomUniform rnd, M23i size)\n        {\n            return new M23i(\n                rnd.UniformInt(size.M00), rnd.UniformInt(size.M01), rnd.UniformInt(size.M02), \n                rnd.UniformInt(size.M10), rnd.UniformInt(size.M11), rnd.UniformInt(size.M12));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M23l\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M23l : IEquatable<M23l>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public long M00, M01, M02;\n        [DataMember]\n        public long M10, M11, M12;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(long value)\n        {\n            M00 = value; M01 = 0; M02 = 0; \n            M10 = 0; M11 = value; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(\n                long m00, long m01, long m02, \n                long m10, long m11, long m12)\n        {\n            M00 = m00; M01 = m01; M02 = m02; \n            M10 = m10; M11 = m11; M12 = m12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(long[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M10 = a[3];\n            M11 = a[4];\n            M12 = a[5];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(long[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M10 = a[start + 3];\n            M11 = a[start + 4];\n            M12 = a[start + 5];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M22l m, V2l v)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = v.X; \n            M10 = m.M10; M11 = m.M11; M12 = v.Y; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M22i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M23i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M33i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M34i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M44i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M22l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M33l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M34l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M44l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M22f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M23f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M33f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M34f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M44f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M22d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M23d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M33d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M34d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23l(M44d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M23l(M22i m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23l(M23i m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M33i m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M34i m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M44i m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M22l m)\n        {\n            return new M23l {\n                M00 = m.M00, M01 = m.M01, M02 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23l(M33l m)\n        {\n            return new M23l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M34l m)\n        {\n            return new M23l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M44l m)\n        {\n            return new M23l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M22f m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23l(M23f m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M33f m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M34f m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M44f m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M22d m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23l(M23d m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M33d m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M34d m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(M44d m)\n        {\n            return new M23l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n            };\n        }\n\n        public static explicit operator M23l(int[] a)\n        {\n            return new M23l(\n                (long)a[0], (long)a[1], (long)a[2], \n                (long)a[3], (long)a[4], (long)a[5]);\n        }\n\n        public static explicit operator M23l(int[,] a)\n        {\n            return new M23l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2]);\n        }\n\n        public static explicit operator int[](M23l m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, \n                (int)m.M10, (int)m.M11, (int)m.M12\n            };\n        }\n\n        public static explicit operator int[,](M23l m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M10;\n            array[index + 4] = (int)M11;\n            array[index + 5] = (int)M12;\n        }\n\n        public static explicit operator M23l(long[] a)\n        {\n            return new M23l(\n                a[0], a[1], a[2], \n                a[3], a[4], a[5]);\n        }\n\n        public static explicit operator M23l(long[,] a)\n        {\n            return new M23l(\n                a[0, 0], a[0, 1], a[0, 2], \n                a[1, 0], a[1, 1], a[1, 2]);\n        }\n\n        public static explicit operator long[](M23l m)\n        {\n            return new long[] {\n                m.M00, m.M01, m.M02, \n                m.M10, m.M11, m.M12\n            };\n        }\n\n        public static explicit operator long[,](M23l m)\n        {\n            return new long[,] {\n                { m.M00, m.M01, m.M02 }, \n                { m.M10, m.M11, m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M10;\n            array[index + 4] = M11;\n            array[index + 5] = M12;\n        }\n\n        public static explicit operator M23l(float[] a)\n        {\n            return new M23l(\n                (long)a[0], (long)a[1], (long)a[2], \n                (long)a[3], (long)a[4], (long)a[5]);\n        }\n\n        public static explicit operator M23l(float[,] a)\n        {\n            return new M23l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2]);\n        }\n\n        public static explicit operator float[](M23l m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, \n                (float)m.M10, (float)m.M11, (float)m.M12\n            };\n        }\n\n        public static explicit operator float[,](M23l m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M10;\n            array[index + 4] = (float)M11;\n            array[index + 5] = (float)M12;\n        }\n\n        public static explicit operator M23l(double[] a)\n        {\n            return new M23l(\n                (long)a[0], (long)a[1], (long)a[2], \n                (long)a[3], (long)a[4], (long)a[5]);\n        }\n\n        public static explicit operator M23l(double[,] a)\n        {\n            return new M23l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2]);\n        }\n\n        public static explicit operator double[](M23l m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, \n                (double)m.M10, (double)m.M11, (double)m.M12\n            };\n        }\n\n        public static explicit operator double[,](M23l m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M10;\n            array[index + 4] = (double)M11;\n            array[index + 5] = (double)M12;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23i Copy(Func<long, int> element_fun)\n        {\n            return new M23i(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23i Copy(Func<long, int, int, int> element_index0_index1_fun)\n        {\n            return new M23i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23l Copy(Func<long, long> element_fun)\n        {\n            return new M23l(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23l Copy(Func<long, int, int, long> element_index0_index1_fun)\n        {\n            return new M23l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23f Copy(Func<long, float> element_fun)\n        {\n            return new M23f(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23f Copy(Func<long, int, int, float> element_index0_index1_fun)\n        {\n            return new M23f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23d Copy(Func<long, double> element_fun)\n        {\n            return new M23d(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23d Copy(Func<long, int, int, double> element_index0_index1_fun)\n        {\n            return new M23d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        public readonly long[] ToArray()\n        {\n            var array = new long[6];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M10;\n            array[4] = M11;\n            array[5] = M12;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l FromCols(V2l col0, V2l col1, V2l col2)\n        {\n            return new M23l(\n                col0.X, col1.X, col2.X, \n                col0.Y, col1.Y, col2.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l FromRows(V3l row0, V3l row1)\n        {\n            return new M23l(\n                row0.X, row0.Y, row0.Z, \n                row1.X, row1.Y, row1.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l FromDiagonal(long value)\n        {\n            return new M23l(\n                value, 0, 0, \n                0, value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l FromDiagonal(long m00, long m11)\n        {\n            return new M23l(\n                m00, 0, 0, \n                0, m11, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l FromDiagonal(V2l s)\n        {\n            return new M23l(\n                s.X, 0, 0, \n                0, s.Y, 0);\n        }\n\n        #region Scale\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23l\"/> with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l Translation(long tX, long tY)\n        {\n            return new M23l(\n                1, 0, tX, \n                0, 1, tY);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23l\"/> with the translational component given by a <see cref=\"V2l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l Translation(V2l t)\n        {\n            return new M23l(\n                1, 0, t.X, \n                0, 1, t.Y);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l DivideByInt(M23l m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n            }\n        }\n\n        public readonly IEnumerable<V3l> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n            }\n        }\n\n        public readonly IEnumerable<V2l> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M00,  M01,  M02); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M10,  M11,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V2l C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2l( M00,  M10); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2l C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2l( M01,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2l C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2l( M02,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n            }\n        }\n\n        public readonly V2l Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(M00, M11);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly long MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M10, M11, M12);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly long MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M10, M11, M12);\n        }\n\n        public unsafe long this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe long this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[row * 3 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[row * 3 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 2;\n        public const int ColumnCount = 3;\n        public const int ElementCount = 2 * 3;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(2, 3);\n        }\n\n        public static M23l Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M23l(0);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly long Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + \n                    M10 * M10 + M11 * M11 + M12 * M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator -(M23l m)\n        {\n            return new M23l(\n                -m.M00, -m.M01, -m.M02, \n                -m.M10, -m.M11, -m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  + (M23l a, M23l b)\n        {\n            return new M23l(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  + (M23l m, long s)\n        {\n            return new M23l(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  + (long s, M23l m)\n        {\n            return new M23l(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (M23l a, M23f b)\n        {\n            return new M23f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (M23l m, float s)\n        {\n            return new M23f(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (float s, M23l m)\n        {\n            return new M23f(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (M23l a, M23d b)\n        {\n            return new M23d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (M23l m, double s)\n        {\n            return new M23d(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (double s, M23l m)\n        {\n            return new M23d(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  - (M23l a, M23l b)\n        {\n            return new M23l(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  - (M23l m, long s)\n        {\n            return new M23l(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  - (long s, M23l m)\n        {\n            return new M23l(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (M23l a, M23f b)\n        {\n            return new M23f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (M23l m, float s)\n        {\n            return new M23f(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (float s, M23l m)\n        {\n            return new M23f(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (M23l a, M23d b)\n        {\n            return new M23d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (M23l m, double s)\n        {\n            return new M23d(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (double s, M23l m)\n        {\n            return new M23d(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  % (M23l a, M23l b)\n        {\n            return new M23l(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  % (M23l m, long s)\n        {\n            return new M23l(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  % (long s, M23l m)\n        {\n            return new M23l(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (M23l a, M23f b)\n        {\n            return new M23f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (M23l m, float s)\n        {\n            return new M23f(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (float s, M23l m)\n        {\n            return new M23f(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (M23l a, M23d b)\n        {\n            return new M23d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (M23l m, double s)\n        {\n            return new M23d(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (double s, M23l m)\n        {\n            return new M23d(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  / (M23l a, M23l b)\n        {\n            return new M23l(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  / (M23l m, long s)\n        {\n            return new M23l(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  / (long s, M23l m)\n        {\n            return new M23l(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (M23l a, M23f b)\n        {\n            return new M23f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (M23l m, float s)\n        {\n            return new M23f(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (float s, M23l m)\n        {\n            return new M23f(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (M23l a, M23d b)\n        {\n            return new M23d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (M23l m, double s)\n        {\n            return new M23d(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (double s, M23l m)\n        {\n            return new M23d(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  * (M23l m, long s)\n        {\n            return new M23l(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator  * (long s, M23l m)\n        {\n            return new M23l(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  * (M23l m, float s)\n        {\n            return new M23f(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  * (float s, M23l m)\n        {\n            return new M23f(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  * (M23l m, double s)\n        {\n            return new M23d(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  * (double s, M23l m)\n        {\n            return new M23d(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator ~(M23l m)\n        {\n            return new M23l(\n                ~m.M00, ~m.M01, ~m.M02, \n                ~m.M10, ~m.M11, ~m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator <<(M23l a, int s)\n        {\n            return new M23l(\n                a.M00 << s, a.M01 << s, a.M02 << s, \n                a.M10 << s, a.M11 << s, a.M12 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator >>(M23l a, int s)\n        {\n            return new M23l(\n                a.M00 >> s, a.M01 >> s, a.M02 >> s, \n                a.M10 >> s, a.M11 >> s, a.M12 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator &(M23l a, M23l b)\n        {\n            return new M23l(\n                a.M00 & b.M00, a.M01 & b.M01, a.M02 & b.M02, \n                a.M10 & b.M10, a.M11 & b.M11, a.M12 & b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator &(M23l a, long s)\n        {\n            return new M23l(\n                a.M00 & s, a.M01 & s, a.M02 & s, \n                a.M10 & s, a.M11 & s, a.M12 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator &(long s, M23l a)\n        {\n            return new M23l(\n                s & a.M00, s & a.M01, s & a.M02, \n                s & a.M10, s & a.M11, s & a.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator |(M23l a, M23l b)\n        {\n            return new M23l(\n                a.M00 | b.M00, a.M01 | b.M01, a.M02 | b.M02, \n                a.M10 | b.M10, a.M11 | b.M11, a.M12 | b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator |(M23l a, long s)\n        {\n            return new M23l(\n                a.M00 | s, a.M01 | s, a.M02 | s, \n                a.M10 | s, a.M11 | s, a.M12 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator |(long s, M23l a)\n        {\n            return new M23l(\n                s | a.M00, s | a.M01, s | a.M02, \n                s | a.M10, s | a.M11, s | a.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator ^(M23l a, M23l b)\n        {\n            return new M23l(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, a.M02 ^ b.M02, \n                a.M10 ^ b.M10, a.M11 ^ b.M11, a.M12 ^ b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator ^(M23l a, long s)\n        {\n            return new M23l(\n                a.M00 ^ s, a.M01 ^ s, a.M02 ^ s, \n                a.M10 ^ s, a.M11 ^ s, a.M12 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l operator ^(long s, M23l a)\n        {\n            return new M23l(\n                s ^ a.M00, s ^ a.M01, s ^ a.M02, \n                s ^ a.M10, s ^ a.M11, s ^ a.M12);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M23l matrix with a V3l column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator *(M23l m, V3l v)\n        {\n            return new V2l(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a V2l row vector with a M23l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator *(V2l v, M23l m)\n        {\n            return new V3l(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11, \n                v.X * m.M02 + v.Y * m.M12);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M23l a, M23l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M23l a, long s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(long s, M23l a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M23l a, M23l b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M23l m, long s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(long s, M23l m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02),\n                        HashCode.GetCombined(M10, M11, M12));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M23l other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M23l o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M23l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M23l.FromRows(\n                V3l.Parse(x[0]), \n                V3l.Parse(x[1])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M23l operator *(M22l a, M23l b)\n        {\n            return new M23l(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M00 * b.M02 + a.M01 * b.M12, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11, \n                a.M10 * b.M02 + a.M11 * b.M12\n             );\n        }\n\n        public static M23l operator *(M23l a, M33l b)\n        {\n            return new M23l(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (long)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (long)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (long)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (long)value;\n        }\n\n        #endregion\n    }\n\n    public class M23lEqualityComparer : IEqualityComparer<M23l>\n    {\n        public static readonly M23lEqualityComparer Default\n            = new M23lEqualityComparer();\n\n        #region IEqualityComparer<M23l> Members\n\n        public bool Equals(M23l v0, M23l v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M23l v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M23l m)\n            => (m.C0.Length + m.C1.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector(this M23l m)\n            => new V2d(m.C0.Length, m.C1.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Norm1(M23l m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M23l m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMax(M23l m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMin(M23l m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M23l m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static long Distance1(this M23l a, M23l b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M23l a, M23l b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M23l a, M23l b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMax(this M23l a, M23l b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMin(this M23l a, M23l b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Transform(this M23l m, V3l v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Transform(this M23l m, V4l v)\n        {\n            return new V3l(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l TransposedTransform(this M23l m, V2l v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V2l TransformDir(this M23l m, V2l v)\n        {\n            return new V2l(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by matrix m.\n        /// </summary>\n        public static V2l TransformPos(this M23l m, V2l p)\n        {\n            return new V2l(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12\n                );\n        }\n\n        /// <summary>\n        /// Multiplies two <see cref=\"M23l\"/> matrices as 3x3 matrices.\n        /// </summary>\n        public static M23l MultiplyAffine(this M23l a, M23l b)\n        {\n            return new M23l(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3l Row(this M23l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V3l(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2l Column(this M23l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V2l(ptr[index], ptr[index + 3]);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M23l a, M23l b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M23l m, long s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(long s, M23l m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M23l a, M23l b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M23l m, long s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(long s, M23l m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M23l a, M23l b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M23l m, long s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(long s, M23l m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M23l a, M23l b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M23l m, long s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(long s, M23l m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M23l a, M23l b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M23l m, long s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(long s, M23l m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M23l a, M23l b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M23l m, long s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(long s, M23l m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M23l a, M23l b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M23l m, long s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(long s, M23l m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M23l a, M23l b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M23l m, long s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(long s, M23l m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M23l a, M23l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M23l m, long s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(long s, M23l m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M23l a, M23l b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M23l m, long s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(long s, M23l m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M23l a, M23l b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M23l m, long s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(long s, M23l m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M23l a, M23l b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M23l m, long s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(long s, M23l m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M23l m0, M23l m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M23l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MinElement(M23l m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M23l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MaxElement(M23l m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M23l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M23l m, long epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M23l m, long epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M23l a, M23l b, long epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M23l m, long epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM23lExtensions\n    {\n        #region IRandomUniform extensions for M23l\n\n        /// <summary>\n        /// Uses UniformLong() to generate the elements of an M23l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l UniformM23l(this IRandomUniform rnd)\n        {\n            return new M23l(\n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong());\n        }\n\n        /// <summary>\n        /// Uses UniformLongNonZero() to generate the elements of an M23l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l UniformM23lNonZero(this IRandomUniform rnd)\n        {\n            return new M23l(\n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M23l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l UniformM23l(this IRandomUniform rnd, long size)\n        {\n            return new M23l(\n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size));\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M23l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23l UniformM23l(this IRandomUniform rnd, M23l size)\n        {\n            return new M23l(\n                rnd.UniformLong(size.M00), rnd.UniformLong(size.M01), rnd.UniformLong(size.M02), \n                rnd.UniformLong(size.M10), rnd.UniformLong(size.M11), rnd.UniformLong(size.M12));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M23f\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M23f : IEquatable<M23f>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public float M00, M01, M02;\n        [DataMember]\n        public float M10, M11, M12;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(float value)\n        {\n            M00 = value; M01 = 0; M02 = 0; \n            M10 = 0; M11 = value; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(\n                float m00, float m01, float m02, \n                float m10, float m11, float m12)\n        {\n            M00 = m00; M01 = m01; M02 = m02; \n            M10 = m10; M11 = m11; M12 = m12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(float[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M10 = a[3];\n            M11 = a[4];\n            M12 = a[5];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(float[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M10 = a[start + 3];\n            M11 = a[start + 4];\n            M12 = a[start + 5];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M22f m, V2f v)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = v.X; \n            M10 = m.M10; M11 = m.M11; M12 = v.Y; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M22i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M23i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M33i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M34i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M44i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M22l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M23l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M33l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M34l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M44l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M22f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M33f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M34f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M44f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M22d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M23d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M33d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M34d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23f(M44d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M23f(M22i m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23f(M23i m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M33i m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M34i m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M44i m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M22l m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23f(M23l m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M33l m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M34l m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M44l m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M22f m)\n        {\n            return new M23f {\n                M00 = m.M00, M01 = m.M01, M02 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23f(M33f m)\n        {\n            return new M23f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M34f m)\n        {\n            return new M23f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M44f m)\n        {\n            return new M23f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M22d m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23f(M23d m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M33d m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M34d m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(M44d m)\n        {\n            return new M23f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n            };\n        }\n\n        public static explicit operator M23f(int[] a)\n        {\n            return new M23f(\n                (float)a[0], (float)a[1], (float)a[2], \n                (float)a[3], (float)a[4], (float)a[5]);\n        }\n\n        public static explicit operator M23f(int[,] a)\n        {\n            return new M23f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2]);\n        }\n\n        public static explicit operator int[](M23f m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, \n                (int)m.M10, (int)m.M11, (int)m.M12\n            };\n        }\n\n        public static explicit operator int[,](M23f m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M10;\n            array[index + 4] = (int)M11;\n            array[index + 5] = (int)M12;\n        }\n\n        public static explicit operator M23f(long[] a)\n        {\n            return new M23f(\n                (float)a[0], (float)a[1], (float)a[2], \n                (float)a[3], (float)a[4], (float)a[5]);\n        }\n\n        public static explicit operator M23f(long[,] a)\n        {\n            return new M23f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2]);\n        }\n\n        public static explicit operator long[](M23f m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, \n                (long)m.M10, (long)m.M11, (long)m.M12\n            };\n        }\n\n        public static explicit operator long[,](M23f m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M10;\n            array[index + 4] = (long)M11;\n            array[index + 5] = (long)M12;\n        }\n\n        public static explicit operator M23f(float[] a)\n        {\n            return new M23f(\n                a[0], a[1], a[2], \n                a[3], a[4], a[5]);\n        }\n\n        public static explicit operator M23f(float[,] a)\n        {\n            return new M23f(\n                a[0, 0], a[0, 1], a[0, 2], \n                a[1, 0], a[1, 1], a[1, 2]);\n        }\n\n        public static explicit operator float[](M23f m)\n        {\n            return new float[] {\n                m.M00, m.M01, m.M02, \n                m.M10, m.M11, m.M12\n            };\n        }\n\n        public static explicit operator float[,](M23f m)\n        {\n            return new float[,] {\n                { m.M00, m.M01, m.M02 }, \n                { m.M10, m.M11, m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M10;\n            array[index + 4] = M11;\n            array[index + 5] = M12;\n        }\n\n        public static explicit operator M23f(double[] a)\n        {\n            return new M23f(\n                (float)a[0], (float)a[1], (float)a[2], \n                (float)a[3], (float)a[4], (float)a[5]);\n        }\n\n        public static explicit operator M23f(double[,] a)\n        {\n            return new M23f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2]);\n        }\n\n        public static explicit operator double[](M23f m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, \n                (double)m.M10, (double)m.M11, (double)m.M12\n            };\n        }\n\n        public static explicit operator double[,](M23f m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M10;\n            array[index + 4] = (double)M11;\n            array[index + 5] = (double)M12;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23i Copy(Func<float, int> element_fun)\n        {\n            return new M23i(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23i Copy(Func<float, int, int, int> element_index0_index1_fun)\n        {\n            return new M23i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23l Copy(Func<float, long> element_fun)\n        {\n            return new M23l(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23l Copy(Func<float, int, int, long> element_index0_index1_fun)\n        {\n            return new M23l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23f Copy(Func<float, float> element_fun)\n        {\n            return new M23f(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23f Copy(Func<float, int, int, float> element_index0_index1_fun)\n        {\n            return new M23f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23d Copy(Func<float, double> element_fun)\n        {\n            return new M23d(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23d Copy(Func<float, int, int, double> element_index0_index1_fun)\n        {\n            return new M23d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        public readonly float[] ToArray()\n        {\n            var array = new float[6];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M10;\n            array[4] = M11;\n            array[5] = M12;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f FromCols(V2f col0, V2f col1, V2f col2)\n        {\n            return new M23f(\n                col0.X, col1.X, col2.X, \n                col0.Y, col1.Y, col2.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f FromRows(V3f row0, V3f row1)\n        {\n            return new M23f(\n                row0.X, row0.Y, row0.Z, \n                row1.X, row1.Y, row1.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f FromDiagonal(float value)\n        {\n            return new M23f(\n                value, 0, 0, \n                0, value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f FromDiagonal(float m00, float m11)\n        {\n            return new M23f(\n                m00, 0, 0, \n                0, m11, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f FromDiagonal(V2f s)\n        {\n            return new M23f(\n                s.X, 0, 0, \n                0, s.Y, 0);\n        }\n\n        #region Scale\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23f\"/> with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f Translation(float tX, float tY)\n        {\n            return new M23f(\n                1, 0, tX, \n                0, 1, tY);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23f\"/> with the translational component given by a <see cref=\"V2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f Translation(V2f t)\n        {\n            return new M23f(\n                1, 0, t.X, \n                0, 1, t.Y);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23f\"/> from a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f Translation(Shift2f s)\n        {\n            return new M23f(\n                1, 0, s.X, \n                0, 1, s.Y);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f Rotation(float angleInRadians)\n        {\n            var a = Fun.Cos(angleInRadians);\n            var b = Fun.Sin(angleInRadians);\n\n            return new M23f(\n                 a, -b,  0, \n                 b,  a,  0);\n        }\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f RotationInDegrees(float angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 2D rotation matrix from a <see cref=\"Rot2f\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f Rotation(Rot2f r)\n            => (M23f)r;\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f DivideByInt(M23f m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n            }\n        }\n\n        public readonly IEnumerable<V3f> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n            }\n        }\n\n        public readonly IEnumerable<V2f> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M00,  M01,  M02); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M10,  M11,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V2f C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2f( M00,  M10); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2f C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2f( M01,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2f C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2f( M02,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n            }\n        }\n\n        public readonly V2f Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2f(M00, M11);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly float MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M10, M11, M12);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly float MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M10, M11, M12);\n        }\n\n        public unsafe float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe float this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[row * 3 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[row * 3 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || Fun.IsFinite(M02) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11) || Fun.IsFinite(M12);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && Fun.IsFinite(M02) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11) && Fun.IsFinite(M12);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) || float.IsNaN(M01) || float.IsNaN(M02) || \n                    float.IsNaN(M10) || float.IsNaN(M11) || float.IsNaN(M12);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) && float.IsNaN(M01) && float.IsNaN(M02) && \n                    float.IsNaN(M10) && float.IsNaN(M11) && float.IsNaN(M12);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) || float.IsInfinity(M01) || float.IsInfinity(M02) || \n                    float.IsInfinity(M10) || float.IsInfinity(M11) || float.IsInfinity(M12);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) && float.IsInfinity(M01) && float.IsInfinity(M02) && \n                    float.IsInfinity(M10) && float.IsInfinity(M11) && float.IsInfinity(M12);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) || float.IsPositiveInfinity(M01) || float.IsPositiveInfinity(M02) || \n                    float.IsPositiveInfinity(M10) || float.IsPositiveInfinity(M11) || float.IsPositiveInfinity(M12);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) && float.IsPositiveInfinity(M01) && float.IsPositiveInfinity(M02) && \n                    float.IsPositiveInfinity(M10) && float.IsPositiveInfinity(M11) && float.IsPositiveInfinity(M12);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) || float.IsNegativeInfinity(M01) || float.IsNegativeInfinity(M02) || \n                    float.IsNegativeInfinity(M10) || float.IsNegativeInfinity(M11) || float.IsNegativeInfinity(M12);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) && float.IsNegativeInfinity(M01) && float.IsNegativeInfinity(M02) && \n                    float.IsNegativeInfinity(M10) && float.IsNegativeInfinity(M11) && float.IsNegativeInfinity(M12);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || Fun.IsTiny(M02) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11) || Fun.IsTiny(M12);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && Fun.IsTiny(M02) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11) && Fun.IsTiny(M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 2;\n        public const int ColumnCount = 3;\n        public const int ElementCount = 2 * 3;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(2, 3);\n        }\n\n        public static M23f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M23f(0);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly float Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly float Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + \n                    M10 * M10 + M11 * M11 + M12 * M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator -(M23f m)\n        {\n            return new M23f(\n                -m.M00, -m.M01, -m.M02, \n                -m.M10, -m.M11, -m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (M23f a, M23f b)\n        {\n            return new M23f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (M23f m, float s)\n        {\n            return new M23f(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  + (float s, M23f m)\n        {\n            return new M23f(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (M23f a, M23d b)\n        {\n            return new M23d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (M23f m, double s)\n        {\n            return new M23d(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (double s, M23f m)\n        {\n            return new M23d(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (M23f a, M23f b)\n        {\n            return new M23f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (M23f m, float s)\n        {\n            return new M23f(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  - (float s, M23f m)\n        {\n            return new M23f(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (M23f a, M23d b)\n        {\n            return new M23d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (M23f m, double s)\n        {\n            return new M23d(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (double s, M23f m)\n        {\n            return new M23d(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (M23f a, M23f b)\n        {\n            return new M23f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (M23f m, float s)\n        {\n            return new M23f(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  % (float s, M23f m)\n        {\n            return new M23f(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (M23f a, M23d b)\n        {\n            return new M23d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (M23f m, double s)\n        {\n            return new M23d(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (double s, M23f m)\n        {\n            return new M23d(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (M23f a, M23f b)\n        {\n            return new M23f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (M23f m, float s)\n        {\n            return new M23f(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  / (float s, M23f m)\n        {\n            return new M23f(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (M23f a, M23d b)\n        {\n            return new M23d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (M23f m, double s)\n        {\n            return new M23d(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (double s, M23f m)\n        {\n            return new M23d(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  * (M23f m, float s)\n        {\n            return new M23f(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator  * (float s, M23f m)\n        {\n            return new M23f(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  * (M23f m, double s)\n        {\n            return new M23d(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  * (double s, M23f m)\n        {\n            return new M23d(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M23f matrix with a V3f column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(M23f m, V3f v)\n        {\n            return new V2f(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a V2f row vector with a M23f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(V2f v, M23f m)\n        {\n            return new V3f(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11, \n                v.X * m.M02 + v.Y * m.M12);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M23f a, M23f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M23f a, float s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(float s, M23f a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M23f a, M23f b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M23f m, float s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(float s, M23f m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02),\n                        HashCode.GetCombined(M10, M11, M12));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M23f other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M23f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M23f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M23f.FromRows(\n                V3f.Parse(x[0]), \n                V3f.Parse(x[1])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M23f operator *(M22f a, M23f b)\n        {\n            return new M23f(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M00 * b.M02 + a.M01 * b.M12, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11, \n                a.M10 * b.M02 + a.M11 * b.M12\n             );\n        }\n\n        public static M23f operator *(M23f a, M33f b)\n        {\n            return new M23f(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (float)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (float)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (float)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (float)value;\n        }\n\n        #endregion\n    }\n\n    public class M23fEqualityComparer : IEqualityComparer<M23f>\n    {\n        public static readonly M23fEqualityComparer Default\n            = new M23fEqualityComparer();\n\n        #region IEqualityComparer<M23f> Members\n\n        public bool Equals(M23f v0, M23f v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M23f v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Computes the (signed) angle in radians of a <see cref=\"M23f\"/> rotation matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetRotation(this M23f m)\n            => Fun.Atan2(m.M10, m.M00);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale(this M23f m)\n            => (m.C0.Length + m.C1.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetScaleVector(this M23f m)\n            => new V2f(m.C0.Length, m.C1.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm1(M23f m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm2(M23f m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMax(M23f m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMin(M23f m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(this M23f m, float p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static float Distance1(this M23f a, M23f b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static float Distance2(this M23f a, M23f b)\n        {\n            return (float)Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static float Distance(this M23f a, M23f b, float p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMax(this M23f a, M23f b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMin(this M23f a, M23f b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Transform(this M23f m, V3f v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this M23f m, V4f v)\n        {\n            return new V3f(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransposedTransform(this M23f m, V2f v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V2f TransformDir(this M23f m, V2f v)\n        {\n            return new V2f(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by matrix m.\n        /// </summary>\n        public static V2f TransformPos(this M23f m, V2f p)\n        {\n            return new V2f(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12\n                );\n        }\n\n        /// <summary>\n        /// Multiplies two <see cref=\"M23f\"/> matrices as 3x3 matrices.\n        /// </summary>\n        public static M23f MultiplyAffine(this M23f a, M23f b)\n        {\n            return new M23f(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3f Row(this M23f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V3f(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2f Column(this M23f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V2f(ptr[index], ptr[index + 3]);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M23f a, M23f b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M23f m, float s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, M23f m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M23f a, M23f b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M23f m, float s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, M23f m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M23f a, M23f b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M23f m, float s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, M23f m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M23f a, M23f b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M23f m, float s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, M23f m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M23f a, M23f b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M23f m, float s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, M23f m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M23f a, M23f b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M23f m, float s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, M23f m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M23f a, M23f b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M23f m, float s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, M23f m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M23f a, M23f b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M23f m, float s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, M23f m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M23f a, M23f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M23f m, float s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, M23f m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M23f a, M23f b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M23f m, float s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, M23f m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M23f a, M23f b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M23f m, float s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, M23f m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M23f a, M23f b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M23f m, float s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, M23f m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M23f m0, M23f m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M23f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MinElement(M23f m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M23f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MaxElement(M23f m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M23f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M23f m, float epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M23f m, float epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M23f m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M23f m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M23f m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M23f m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M23f m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M23f m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M23f m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M23f m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M23f m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M23f m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M23f m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M23f m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M23f a, M23f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M23f a, M23f b, float epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M23f m, float epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M23f m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M23f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M23f v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M23f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M23f v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M23f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M23f v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M23f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M23f v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M23f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M23f v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM23fExtensions\n    {\n        #region IRandomUniform extensions for M23f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of an M23f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f UniformM23f(this IRandomUniform rnd)\n        {\n            return new M23f(\n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of an M23f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f UniformM23fClosed(this IRandomUniform rnd)\n        {\n            return new M23f(\n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of an M23f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f UniformM23fOpen(this IRandomUniform rnd)\n        {\n            return new M23f(\n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M23d\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M23d : IEquatable<M23d>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public double M00, M01, M02;\n        [DataMember]\n        public double M10, M11, M12;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(double value)\n        {\n            M00 = value; M01 = 0; M02 = 0; \n            M10 = 0; M11 = value; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(\n                double m00, double m01, double m02, \n                double m10, double m11, double m12)\n        {\n            M00 = m00; M01 = m01; M02 = m02; \n            M10 = m10; M11 = m11; M12 = m12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(double[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M10 = a[3];\n            M11 = a[4];\n            M12 = a[5];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(double[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M10 = a[start + 3];\n            M11 = a[start + 4];\n            M12 = a[start + 5];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M22d m, V2d v)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = v.X; \n            M10 = m.M10; M11 = m.M11; M12 = v.Y; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M22i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M23i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M33i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M34i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M44i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M22l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M23l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M33l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M34l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M44l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M22f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M23f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M33f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M34f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M44f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M22d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M33d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M34d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M23d(M44d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M23d(M22i m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23d(M23i m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M33i m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M34i m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M44i m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M22l m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23d(M23l m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M33l m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M34l m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M44l m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M22f m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23d(M23f m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M33f m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M34f m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M44f m)\n        {\n            return new M23d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M22d m)\n        {\n            return new M23d {\n                M00 = m.M00, M01 = m.M01, M02 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, \n            };\n        }\n\n        public static explicit operator M23d(M33d m)\n        {\n            return new M23d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M34d m)\n        {\n            return new M23d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23d(M44d m)\n        {\n            return new M23d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n            };\n        }\n\n        public static explicit operator M23d(int[] a)\n        {\n            return new M23d(\n                (double)a[0], (double)a[1], (double)a[2], \n                (double)a[3], (double)a[4], (double)a[5]);\n        }\n\n        public static explicit operator M23d(int[,] a)\n        {\n            return new M23d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2]);\n        }\n\n        public static explicit operator int[](M23d m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, \n                (int)m.M10, (int)m.M11, (int)m.M12\n            };\n        }\n\n        public static explicit operator int[,](M23d m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M10;\n            array[index + 4] = (int)M11;\n            array[index + 5] = (int)M12;\n        }\n\n        public static explicit operator M23d(long[] a)\n        {\n            return new M23d(\n                (double)a[0], (double)a[1], (double)a[2], \n                (double)a[3], (double)a[4], (double)a[5]);\n        }\n\n        public static explicit operator M23d(long[,] a)\n        {\n            return new M23d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2]);\n        }\n\n        public static explicit operator long[](M23d m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, \n                (long)m.M10, (long)m.M11, (long)m.M12\n            };\n        }\n\n        public static explicit operator long[,](M23d m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M10;\n            array[index + 4] = (long)M11;\n            array[index + 5] = (long)M12;\n        }\n\n        public static explicit operator M23d(float[] a)\n        {\n            return new M23d(\n                (double)a[0], (double)a[1], (double)a[2], \n                (double)a[3], (double)a[4], (double)a[5]);\n        }\n\n        public static explicit operator M23d(float[,] a)\n        {\n            return new M23d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2]);\n        }\n\n        public static explicit operator float[](M23d m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, \n                (float)m.M10, (float)m.M11, (float)m.M12\n            };\n        }\n\n        public static explicit operator float[,](M23d m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M10;\n            array[index + 4] = (float)M11;\n            array[index + 5] = (float)M12;\n        }\n\n        public static explicit operator M23d(double[] a)\n        {\n            return new M23d(\n                a[0], a[1], a[2], \n                a[3], a[4], a[5]);\n        }\n\n        public static explicit operator M23d(double[,] a)\n        {\n            return new M23d(\n                a[0, 0], a[0, 1], a[0, 2], \n                a[1, 0], a[1, 1], a[1, 2]);\n        }\n\n        public static explicit operator double[](M23d m)\n        {\n            return new double[] {\n                m.M00, m.M01, m.M02, \n                m.M10, m.M11, m.M12\n            };\n        }\n\n        public static explicit operator double[,](M23d m)\n        {\n            return new double[,] {\n                { m.M00, m.M01, m.M02 }, \n                { m.M10, m.M11, m.M12 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M10;\n            array[index + 4] = M11;\n            array[index + 5] = M12;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23i Copy(Func<double, int> element_fun)\n        {\n            return new M23i(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23i Copy(Func<double, int, int, int> element_index0_index1_fun)\n        {\n            return new M23i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23l Copy(Func<double, long> element_fun)\n        {\n            return new M23l(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23l Copy(Func<double, int, int, long> element_index0_index1_fun)\n        {\n            return new M23l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23f Copy(Func<double, float> element_fun)\n        {\n            return new M23f(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23f Copy(Func<double, int, int, float> element_index0_index1_fun)\n        {\n            return new M23f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23d Copy(Func<double, double> element_fun)\n        {\n            return new M23d(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M23d Copy(Func<double, int, int, double> element_index0_index1_fun)\n        {\n            return new M23d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2));\n        }\n\n        public readonly double[] ToArray()\n        {\n            var array = new double[6];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M10;\n            array[4] = M11;\n            array[5] = M12;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d FromCols(V2d col0, V2d col1, V2d col2)\n        {\n            return new M23d(\n                col0.X, col1.X, col2.X, \n                col0.Y, col1.Y, col2.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d FromRows(V3d row0, V3d row1)\n        {\n            return new M23d(\n                row0.X, row0.Y, row0.Z, \n                row1.X, row1.Y, row1.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d FromDiagonal(double value)\n        {\n            return new M23d(\n                value, 0, 0, \n                0, value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d FromDiagonal(double m00, double m11)\n        {\n            return new M23d(\n                m00, 0, 0, \n                0, m11, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d FromDiagonal(V2d s)\n        {\n            return new M23d(\n                s.X, 0, 0, \n                0, s.Y, 0);\n        }\n\n        #region Scale\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23d\"/> with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d Translation(double tX, double tY)\n        {\n            return new M23d(\n                1, 0, tX, \n                0, 1, tY);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23d\"/> with the translational component given by a <see cref=\"V2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d Translation(V2d t)\n        {\n            return new M23d(\n                1, 0, t.X, \n                0, 1, t.Y);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M23d\"/> from a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d Translation(Shift2d s)\n        {\n            return new M23d(\n                1, 0, s.X, \n                0, 1, s.Y);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d Rotation(double angleInRadians)\n        {\n            var a = Fun.Cos(angleInRadians);\n            var b = Fun.Sin(angleInRadians);\n\n            return new M23d(\n                 a, -b,  0, \n                 b,  a,  0);\n        }\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d RotationInDegrees(double angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 2D rotation matrix from a <see cref=\"Rot2d\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d Rotation(Rot2d r)\n            => (M23d)r;\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d DivideByInt(M23d m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n            }\n        }\n\n        public readonly IEnumerable<V3d> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n            }\n        }\n\n        public readonly IEnumerable<V2d> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M00,  M01,  M02); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M10,  M11,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V2d C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2d( M00,  M10); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2d C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2d( M01,  M11); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n            }\n        }\n\n        [XmlIgnore]\n        public V2d C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V2d( M02,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n            }\n        }\n\n        public readonly V2d Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2d(M00, M11);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly double MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M10, M11, M12);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly double MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M10, M11, M12);\n        }\n\n        public unsafe double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe double this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[row * 3 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[row * 3 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || Fun.IsFinite(M02) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11) || Fun.IsFinite(M12);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && Fun.IsFinite(M02) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11) && Fun.IsFinite(M12);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) || double.IsNaN(M01) || double.IsNaN(M02) || \n                    double.IsNaN(M10) || double.IsNaN(M11) || double.IsNaN(M12);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) && double.IsNaN(M01) && double.IsNaN(M02) && \n                    double.IsNaN(M10) && double.IsNaN(M11) && double.IsNaN(M12);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) || double.IsInfinity(M01) || double.IsInfinity(M02) || \n                    double.IsInfinity(M10) || double.IsInfinity(M11) || double.IsInfinity(M12);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) && double.IsInfinity(M01) && double.IsInfinity(M02) && \n                    double.IsInfinity(M10) && double.IsInfinity(M11) && double.IsInfinity(M12);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) || double.IsPositiveInfinity(M01) || double.IsPositiveInfinity(M02) || \n                    double.IsPositiveInfinity(M10) || double.IsPositiveInfinity(M11) || double.IsPositiveInfinity(M12);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) && double.IsPositiveInfinity(M01) && double.IsPositiveInfinity(M02) && \n                    double.IsPositiveInfinity(M10) && double.IsPositiveInfinity(M11) && double.IsPositiveInfinity(M12);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) || double.IsNegativeInfinity(M01) || double.IsNegativeInfinity(M02) || \n                    double.IsNegativeInfinity(M10) || double.IsNegativeInfinity(M11) || double.IsNegativeInfinity(M12);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) && double.IsNegativeInfinity(M01) && double.IsNegativeInfinity(M02) && \n                    double.IsNegativeInfinity(M10) && double.IsNegativeInfinity(M11) && double.IsNegativeInfinity(M12);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || Fun.IsTiny(M02) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11) || Fun.IsTiny(M12);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && Fun.IsTiny(M02) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11) && Fun.IsTiny(M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 2;\n        public const int ColumnCount = 3;\n        public const int ElementCount = 2 * 3;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(2, 3);\n        }\n\n        public static M23d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M23d(0);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly double Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + \n                    M10 * M10 + M11 * M11 + M12 * M12);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator -(M23d m)\n        {\n            return new M23d(\n                -m.M00, -m.M01, -m.M02, \n                -m.M10, -m.M11, -m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (M23d a, M23d b)\n        {\n            return new M23d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (M23d m, double s)\n        {\n            return new M23d(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  + (double s, M23d m)\n        {\n            return new M23d(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (M23d a, M23d b)\n        {\n            return new M23d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (M23d m, double s)\n        {\n            return new M23d(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  - (double s, M23d m)\n        {\n            return new M23d(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (M23d a, M23d b)\n        {\n            return new M23d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (M23d m, double s)\n        {\n            return new M23d(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  % (double s, M23d m)\n        {\n            return new M23d(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (M23d a, M23d b)\n        {\n            return new M23d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (M23d m, double s)\n        {\n            return new M23d(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  / (double s, M23d m)\n        {\n            return new M23d(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  * (M23d m, double s)\n        {\n            return new M23d(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator  * (double s, M23d m)\n        {\n            return new M23d(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M23d matrix with a V3d column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(M23d m, V3d v)\n        {\n            return new V2d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a V2d row vector with a M23d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(V2d v, M23d m)\n        {\n            return new V3d(\n                v.X * m.M00 + v.Y * m.M10, \n                v.X * m.M01 + v.Y * m.M11, \n                v.X * m.M02 + v.Y * m.M12);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M23d a, M23d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M23d a, double s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(double s, M23d a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M23d a, M23d b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M23d m, double s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(double s, M23d m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02),\n                        HashCode.GetCombined(M10, M11, M12));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M23d other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M23d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M23d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M23d.FromRows(\n                V3d.Parse(x[0]), \n                V3d.Parse(x[1])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M23d operator *(M22d a, M23d b)\n        {\n            return new M23d(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M00 * b.M02 + a.M01 * b.M12, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11, \n                a.M10 * b.M02 + a.M11 * b.M12\n             );\n        }\n\n        public static M23d operator *(M23d a, M33d b)\n        {\n            return new M23d(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (double)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (double)value;\n        }\n\n        #endregion\n    }\n\n    public class M23dEqualityComparer : IEqualityComparer<M23d>\n    {\n        public static readonly M23dEqualityComparer Default\n            = new M23dEqualityComparer();\n\n        #region IEqualityComparer<M23d> Members\n\n        public bool Equals(M23d v0, M23d v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M23d v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Computes the (signed) angle in radians of a <see cref=\"M23d\"/> rotation matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetRotation(this M23d m)\n            => Fun.Atan2(m.M10, m.M00);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M23d m)\n            => (m.C0.Length + m.C1.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector(this M23d m)\n            => new V2d(m.C0.Length, m.C1.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm1(M23d m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M23d m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMax(M23d m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMin(M23d m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M23d m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static double Distance1(this M23d a, M23d b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M23d a, M23d b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M23d a, M23d b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMax(this M23d a, M23d b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMin(this M23d a, M23d b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Transform(this M23d m, V3d v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this M23d m, V4d v)\n        {\n            return new V3d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransposedTransform(this M23d m, V2d v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V2d TransformDir(this M23d m, V2d v)\n        {\n            return new V2d(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by matrix m.\n        /// </summary>\n        public static V2d TransformPos(this M23d m, V2d p)\n        {\n            return new V2d(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12\n                );\n        }\n\n        /// <summary>\n        /// Multiplies two <see cref=\"M23d\"/> matrices as 3x3 matrices.\n        /// </summary>\n        public static M23d MultiplyAffine(this M23d a, M23d b)\n        {\n            return new M23d(\n                a.M00 * b.M00 + a.M01 * b.M10, \n                a.M00 * b.M01 + a.M01 * b.M11, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02, \n                a.M10 * b.M00 + a.M11 * b.M10, \n                a.M10 * b.M01 + a.M11 * b.M11, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3d Row(this M23d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V3d(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V2d Column(this M23d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V2d(ptr[index], ptr[index + 3]);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M23d a, M23d b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M23d m, double s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, M23d m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M23d a, M23d b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M23d m, double s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, M23d m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M23d a, M23d b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M23d m, double s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, M23d m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M23d a, M23d b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M23d m, double s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, M23d m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M23d a, M23d b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M23d m, double s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, M23d m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M23d a, M23d b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M23d m, double s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, M23d m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M23d a, M23d b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M23d m, double s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, M23d m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M23d a, M23d b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M23d m, double s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, M23d m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M23d a, M23d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M23d m, double s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, M23d m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M23d a, M23d b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M23d m, double s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, M23d m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M23d a, M23d b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M23d m, double s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, M23d m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M23d a, M23d b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M23d m, double s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, M23d m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M23d m0, M23d m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M23d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MinElement(M23d m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M23d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MaxElement(M23d m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M23d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M23d m, double epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M23d m, double epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M23d m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M23d m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M23d m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M23d m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M23d m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M23d m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M23d m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M23d m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M23d m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M23d m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M23d m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M23d m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M23d a, M23d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M23d a, M23d b, double epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M23d m, double epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M23d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M23d m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M23d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M23d v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M23d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M23d v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M23d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M23d v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M23d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M23d v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M23d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M23d v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM23dExtensions\n    {\n        #region IRandomUniform extensions for M23d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of an M23d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d UniformM23d(this IRandomUniform rnd)\n        {\n            return new M23d(\n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of an M23d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d UniformM23dClosed(this IRandomUniform rnd)\n        {\n            return new M23d(\n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of an M23d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d UniformM23dOpen(this IRandomUniform rnd)\n        {\n            return new M23d(\n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of an M23d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d UniformM23dFull(this IRandomUniform rnd)\n        {\n            return new M23d(\n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of an M23d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d UniformM23dFullClosed(this IRandomUniform rnd)\n        {\n            return new M23d(\n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of an M23d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d UniformM23dFullOpen(this IRandomUniform rnd)\n        {\n            return new M23d(\n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M33i\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M33i : IEquatable<M33i>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public int M00, M01, M02;\n        [DataMember]\n        public int M10, M11, M12;\n        [DataMember]\n        public int M20, M21, M22;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(int value)\n        {\n            M00 = value; M01 = 0; M02 = 0; \n            M10 = 0; M11 = value; M12 = 0; \n            M20 = 0; M21 = 0; M22 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(\n                int m00, int m01, int m02, \n                int m10, int m11, int m12, \n                int m20, int m21, int m22)\n        {\n            M00 = m00; M01 = m01; M02 = m02; \n            M10 = m10; M11 = m11; M12 = m12; \n            M20 = m20; M21 = m21; M22 = m22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(int[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M10 = a[3];\n            M11 = a[4];\n            M12 = a[5];\n            M20 = a[6];\n            M21 = a[7];\n            M22 = a[8];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(int[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M10 = a[start + 3];\n            M11 = a[start + 4];\n            M12 = a[start + 5];\n            M20 = a[start + 6];\n            M21 = a[start + 7];\n            M22 = a[start + 8];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M22i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M23i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M34i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M44i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M22l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M23l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M33l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M34l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M44l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M22f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M23f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M33f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M34f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M44f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M22d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M23d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M33d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M34d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33i(M44d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M33i(M22i m)\n        {\n            return new M33i {\n                M00 = m.M00, M01 = m.M01, M02 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33i(M23i m)\n        {\n            return new M33i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33i(M34i m)\n        {\n            return new M33i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M44i m)\n        {\n            return new M33i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M22l m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33i(M23l m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33i(M33l m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M34l m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M44l m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M22f m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33i(M23f m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33i(M33f m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M34f m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M44f m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M22d m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33i(M23d m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33i(M33d m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M34d m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(M44d m)\n        {\n            return new M33i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, \n            };\n        }\n\n        public static explicit operator M33i(int[] a)\n        {\n            return new M33i(\n                a[0], a[1], a[2], \n                a[3], a[4], a[5], \n                a[6], a[7], a[8]);\n        }\n\n        public static explicit operator M33i(int[,] a)\n        {\n            return new M33i(\n                a[0, 0], a[0, 1], a[0, 2], \n                a[1, 0], a[1, 1], a[1, 2], \n                a[2, 0], a[2, 1], a[2, 2]);\n        }\n\n        public static explicit operator int[](M33i m)\n        {\n            return new int[] {\n                m.M00, m.M01, m.M02, \n                m.M10, m.M11, m.M12, \n                m.M20, m.M21, m.M22\n            };\n        }\n\n        public static explicit operator int[,](M33i m)\n        {\n            return new int[,] {\n                { m.M00, m.M01, m.M02 }, \n                { m.M10, m.M11, m.M12 }, \n                { m.M20, m.M21, m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M10;\n            array[index + 4] = M11;\n            array[index + 5] = M12;\n            array[index + 6] = M20;\n            array[index + 7] = M21;\n            array[index + 8] = M22;\n        }\n\n        public static explicit operator M33i(long[] a)\n        {\n            return new M33i(\n                (int)a[0], (int)a[1], (int)a[2], \n                (int)a[3], (int)a[4], (int)a[5], \n                (int)a[6], (int)a[7], (int)a[8]);\n        }\n\n        public static explicit operator M33i(long[,] a)\n        {\n            return new M33i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2]);\n        }\n\n        public static explicit operator long[](M33i m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, \n                (long)m.M10, (long)m.M11, (long)m.M12, \n                (long)m.M20, (long)m.M21, (long)m.M22\n            };\n        }\n\n        public static explicit operator long[,](M33i m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M10;\n            array[index + 4] = (long)M11;\n            array[index + 5] = (long)M12;\n            array[index + 6] = (long)M20;\n            array[index + 7] = (long)M21;\n            array[index + 8] = (long)M22;\n        }\n\n        public static explicit operator M33i(float[] a)\n        {\n            return new M33i(\n                (int)a[0], (int)a[1], (int)a[2], \n                (int)a[3], (int)a[4], (int)a[5], \n                (int)a[6], (int)a[7], (int)a[8]);\n        }\n\n        public static explicit operator M33i(float[,] a)\n        {\n            return new M33i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2]);\n        }\n\n        public static explicit operator float[](M33i m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, \n                (float)m.M10, (float)m.M11, (float)m.M12, \n                (float)m.M20, (float)m.M21, (float)m.M22\n            };\n        }\n\n        public static explicit operator float[,](M33i m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M10;\n            array[index + 4] = (float)M11;\n            array[index + 5] = (float)M12;\n            array[index + 6] = (float)M20;\n            array[index + 7] = (float)M21;\n            array[index + 8] = (float)M22;\n        }\n\n        public static explicit operator M33i(double[] a)\n        {\n            return new M33i(\n                (int)a[0], (int)a[1], (int)a[2], \n                (int)a[3], (int)a[4], (int)a[5], \n                (int)a[6], (int)a[7], (int)a[8]);\n        }\n\n        public static explicit operator M33i(double[,] a)\n        {\n            return new M33i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2]);\n        }\n\n        public static explicit operator double[](M33i m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, \n                (double)m.M10, (double)m.M11, (double)m.M12, \n                (double)m.M20, (double)m.M21, (double)m.M22\n            };\n        }\n\n        public static explicit operator double[,](M33i m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M10;\n            array[index + 4] = (double)M11;\n            array[index + 5] = (double)M12;\n            array[index + 6] = (double)M20;\n            array[index + 7] = (double)M21;\n            array[index + 8] = (double)M22;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33i Copy(Func<int, int> element_fun)\n        {\n            return new M33i(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33i Copy(Func<int, int, int, int> element_index0_index1_fun)\n        {\n            return new M33i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33l Copy(Func<int, long> element_fun)\n        {\n            return new M33l(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33l Copy(Func<int, int, int, long> element_index0_index1_fun)\n        {\n            return new M33l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33f Copy(Func<int, float> element_fun)\n        {\n            return new M33f(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33f Copy(Func<int, int, int, float> element_index0_index1_fun)\n        {\n            return new M33f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33d Copy(Func<int, double> element_fun)\n        {\n            return new M33d(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33d Copy(Func<int, int, int, double> element_index0_index1_fun)\n        {\n            return new M33d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly M22i UpperLeftM22()\n        {\n            return (M22i)this;\n        }\n\n        public readonly int[] ToArray()\n        {\n            var array = new int[9];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M10;\n            array[4] = M11;\n            array[5] = M12;\n            array[6] = M20;\n            array[7] = M21;\n            array[8] = M22;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i FromCols(V3i col0, V3i col1, V3i col2)\n        {\n            return new M33i(\n                col0.X, col1.X, col2.X, \n                col0.Y, col1.Y, col2.Y, \n                col0.Z, col1.Z, col2.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i FromRows(V3i row0, V3i row1, V3i row2)\n        {\n            return new M33i(\n                row0.X, row0.Y, row0.Z, \n                row1.X, row1.Y, row1.Z, \n                row2.X, row2.Y, row2.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i FromDiagonal(int value)\n        {\n            return new M33i(\n                value, 0, 0, \n                0, value, 0, \n                0, 0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i FromDiagonal(int m00, int m11, int m22)\n        {\n            return new M33i(\n                m00, 0, 0, \n                0, m11, 0, \n                0, 0, m22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i FromDiagonal(V3i s)\n        {\n            return new M33i(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, s.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i FromAntiDiagonal(int value)\n        {\n            return new M33i(\n                 0, 0, value, \n                 0, value, 0, \n                 value, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i FromAntiDiagonal(int m02, int m11, int m20)\n        {\n            return new M33i(\n                0, 0, m02, \n                0, m11, 0, \n                m20, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i FromAntiDiagonal(V3i s)\n        {\n            return new M33i(\n                0, 0, s.X, \n                0, s.Y, 0, \n                s.Z, 0, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33i\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Scale(int sX, int sY, int sZ)\n            => FromDiagonal(sX, sY, sZ);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33i\"/> using a <see cref=\"V3i\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Scale(V3i s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M33i\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Scale(int s)\n        {\n            return new M33i(\n                s, 0, 0, \n                0, s, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33i\"/> using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Scale(int sX, int sY)\n        {\n            return new M33i(\n                sX, 0, 0, \n                0, sY, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33i\"/> using a <see cref=\"V2i\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Scale(V2i s)\n        {\n            return new M33i(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, 1);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33i\"/> with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Translation(int tX, int tY)\n        {\n            return new M33i(\n                1, 0, tX, \n                0, 1, tY, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33i\"/> with the translational component given by a <see cref=\"V2i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Translation(V2i t)\n        {\n            return new M33i(\n                1, 0, t.X, \n                0, 1, t.Y, \n                0, 0, 1);\n        }\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i ShearXY(int factorX, int factorY)\n        {\n            return new M33i(\n                1, 0, factorX, \n                0, 1, factorY, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i ShearXZ(int factorX, int factorZ)\n        {\n            return new M33i(\n                1, factorX, 0, \n                0, 1, 0, \n                0, factorZ, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i ShearYZ(int factorY, int factorZ)\n        {\n            return new M33i(\n                1, 0, 0, \n                factorY, 1, 0, \n                factorZ, 0, 1);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i DivideByInt(M33i m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n            }\n        }\n\n        public readonly IEnumerable<V3i> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n            }\n        }\n\n        public readonly IEnumerable<V3i> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M00,  M01,  M02); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M10,  M11,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M20,  M21,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M00,  M10,  M20); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M01,  M11,  M21); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M02,  M12,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        public readonly V3i Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3i(M00, M11, M22);\n        }\n\n        public readonly V3i AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3i(M02, M11, M20);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly int MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M10, M11, M12, M20, M21, M22);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly int MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M10, M11, M12, M20, M21, M22);\n        }\n\n        public unsafe int this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe int this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[row * 3 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[row * 3 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 3;\n        public const int ColumnCount = 3;\n        public const int ElementCount = 3 * 3;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(3, 3);\n        }\n\n        public static M33i Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M33i(0);\n        }\n\n        public static M33i Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M33i(1, 0, 0, 0, 1, 0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly int Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + \n                    M20 * M20 + M21 * M21 + M22 * M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator -(M33i m)\n        {\n            return new M33i(\n                -m.M00, -m.M01, -m.M02, \n                -m.M10, -m.M11, -m.M12, \n                -m.M20, -m.M21, -m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  + (M33i a, M33i b)\n        {\n            return new M33i(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  + (M33i m, int s)\n        {\n            return new M33i(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  + (int s, M33i m)\n        {\n            return new M33i(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  + (M33i a, M33l b)\n        {\n            return new M33l(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  + (M33i m, long s)\n        {\n            return new M33l(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  + (long s, M33i m)\n        {\n            return new M33l(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (M33i a, M33f b)\n        {\n            return new M33f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (M33i m, float s)\n        {\n            return new M33f(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (float s, M33i m)\n        {\n            return new M33f(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (M33i a, M33d b)\n        {\n            return new M33d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (M33i m, double s)\n        {\n            return new M33d(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (double s, M33i m)\n        {\n            return new M33d(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  - (M33i a, M33i b)\n        {\n            return new M33i(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  - (M33i m, int s)\n        {\n            return new M33i(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  - (int s, M33i m)\n        {\n            return new M33i(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  - (M33i a, M33l b)\n        {\n            return new M33l(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  - (M33i m, long s)\n        {\n            return new M33l(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  - (long s, M33i m)\n        {\n            return new M33l(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (M33i a, M33f b)\n        {\n            return new M33f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (M33i m, float s)\n        {\n            return new M33f(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (float s, M33i m)\n        {\n            return new M33f(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (M33i a, M33d b)\n        {\n            return new M33d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (M33i m, double s)\n        {\n            return new M33d(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (double s, M33i m)\n        {\n            return new M33d(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  % (M33i a, M33i b)\n        {\n            return new M33i(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  % (M33i m, int s)\n        {\n            return new M33i(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  % (int s, M33i m)\n        {\n            return new M33i(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  % (M33i a, M33l b)\n        {\n            return new M33l(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  % (M33i m, long s)\n        {\n            return new M33l(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  % (long s, M33i m)\n        {\n            return new M33l(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (M33i a, M33f b)\n        {\n            return new M33f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (M33i m, float s)\n        {\n            return new M33f(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (float s, M33i m)\n        {\n            return new M33f(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (M33i a, M33d b)\n        {\n            return new M33d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (M33i m, double s)\n        {\n            return new M33d(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (double s, M33i m)\n        {\n            return new M33d(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  / (M33i a, M33i b)\n        {\n            return new M33i(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  / (M33i m, int s)\n        {\n            return new M33i(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  / (int s, M33i m)\n        {\n            return new M33i(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  / (M33i a, M33l b)\n        {\n            return new M33l(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  / (M33i m, long s)\n        {\n            return new M33l(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  / (long s, M33i m)\n        {\n            return new M33l(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (M33i a, M33f b)\n        {\n            return new M33f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (M33i m, float s)\n        {\n            return new M33f(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (float s, M33i m)\n        {\n            return new M33f(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (M33i a, M33d b)\n        {\n            return new M33d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (M33i m, double s)\n        {\n            return new M33d(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (double s, M33i m)\n        {\n            return new M33d(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  * (M33i m, int s)\n        {\n            return new M33i(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator  * (int s, M33i m)\n        {\n            return new M33i(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  * (M33i m, long s)\n        {\n            return new M33l(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  * (long s, M33i m)\n        {\n            return new M33l(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  * (M33i m, float s)\n        {\n            return new M33f(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  * (float s, M33i m)\n        {\n            return new M33f(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  * (M33i m, double s)\n        {\n            return new M33d(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  * (double s, M33i m)\n        {\n            return new M33d(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator ~(M33i m)\n        {\n            return new M33i(\n                ~m.M00, ~m.M01, ~m.M02, \n                ~m.M10, ~m.M11, ~m.M12, \n                ~m.M20, ~m.M21, ~m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator <<(M33i a, int s)\n        {\n            return new M33i(\n                a.M00 << s, a.M01 << s, a.M02 << s, \n                a.M10 << s, a.M11 << s, a.M12 << s, \n                a.M20 << s, a.M21 << s, a.M22 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator >>(M33i a, int s)\n        {\n            return new M33i(\n                a.M00 >> s, a.M01 >> s, a.M02 >> s, \n                a.M10 >> s, a.M11 >> s, a.M12 >> s, \n                a.M20 >> s, a.M21 >> s, a.M22 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator &(M33i a, M33i b)\n        {\n            return new M33i(\n                a.M00 & b.M00, a.M01 & b.M01, a.M02 & b.M02, \n                a.M10 & b.M10, a.M11 & b.M11, a.M12 & b.M12, \n                a.M20 & b.M20, a.M21 & b.M21, a.M22 & b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator &(M33i a, int s)\n        {\n            return new M33i(\n                a.M00 & s, a.M01 & s, a.M02 & s, \n                a.M10 & s, a.M11 & s, a.M12 & s, \n                a.M20 & s, a.M21 & s, a.M22 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator &(int s, M33i a)\n        {\n            return new M33i(\n                s & a.M00, s & a.M01, s & a.M02, \n                s & a.M10, s & a.M11, s & a.M12, \n                s & a.M20, s & a.M21, s & a.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator |(M33i a, M33i b)\n        {\n            return new M33i(\n                a.M00 | b.M00, a.M01 | b.M01, a.M02 | b.M02, \n                a.M10 | b.M10, a.M11 | b.M11, a.M12 | b.M12, \n                a.M20 | b.M20, a.M21 | b.M21, a.M22 | b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator |(M33i a, int s)\n        {\n            return new M33i(\n                a.M00 | s, a.M01 | s, a.M02 | s, \n                a.M10 | s, a.M11 | s, a.M12 | s, \n                a.M20 | s, a.M21 | s, a.M22 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator |(int s, M33i a)\n        {\n            return new M33i(\n                s | a.M00, s | a.M01, s | a.M02, \n                s | a.M10, s | a.M11, s | a.M12, \n                s | a.M20, s | a.M21, s | a.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator ^(M33i a, M33i b)\n        {\n            return new M33i(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, a.M02 ^ b.M02, \n                a.M10 ^ b.M10, a.M11 ^ b.M11, a.M12 ^ b.M12, \n                a.M20 ^ b.M20, a.M21 ^ b.M21, a.M22 ^ b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator ^(M33i a, int s)\n        {\n            return new M33i(\n                a.M00 ^ s, a.M01 ^ s, a.M02 ^ s, \n                a.M10 ^ s, a.M11 ^ s, a.M12 ^ s, \n                a.M20 ^ s, a.M21 ^ s, a.M22 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i operator ^(int s, M33i a)\n        {\n            return new M33i(\n                s ^ a.M00, s ^ a.M01, s ^ a.M02, \n                s ^ a.M10, s ^ a.M11, s ^ a.M12, \n                s ^ a.M20, s ^ a.M21, s ^ a.M22);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M33i matrix with a V3i column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator *(M33i m, V3i v)\n        {\n            return new V3i(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a V3i row vector with a M33i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator *(V3i v, M33i m)\n        {\n            return new V3i(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M33i a, M33i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M33i a, int s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(int s, M33i a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M33i a, M33i b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M33i m, int s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(int s, M33i m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02),\n                        HashCode.GetCombined(M10, M11, M12),\n                        HashCode.GetCombined(M20, M21, M22));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M33i other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M33i o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M33i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M33i.FromRows(\n                V3i.Parse(x[0]), \n                V3i.Parse(x[1]), \n                V3i.Parse(x[2])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M33i Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                M33i result = new M33i();\n                for (int row = 0; row < 3; row++)\n                {\n                    for (int col = 0; col < 3; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly int Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 + M22 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly int Determinant\n        {\n            get\n            {\n                if (M10 == 0 && M20 == 0 && M21 == 0)\n                {\n                    return M00 * M11 * M22;\n                }\n                return\n                M00 * M11 * M22 - M00 * M12 * M21 +\n                M01 * M12 * M20 - M01 * M10 * M22 +\n                M02 * M10 * M21 - M02 * M11 * M20;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M33i Transposed\n        {\n            get\n            {\n                return new M33i {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    M02 = M20, \n                    \n                    M10 = M01, \n                    M11 = M11, \n                    M12 = M21, \n                    \n                    M20 = M02, \n                    M21 = M12, \n                    M22 = M22\n                };\n            }\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M33i operator *(M33i a, M33i b)\n        {\n            return new M33i(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (int)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (int)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (int)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (int)value;\n        }\n\n        #endregion\n    }\n\n    public class M33iEqualityComparer : IEqualityComparer<M33i>\n    {\n        public static readonly M33iEqualityComparer Default\n            = new M33iEqualityComparer();\n\n        #region IEqualityComparer<M33i> Members\n\n        public bool Equals(M33i v0, M33i v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M33i v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M33i m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector(this M33i m)\n            => new V3d(m.C0.Length, m.C1.Length, m.C2.Length);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of 2D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale2(this M33i m)\n            => (m.C0.XY.Length + m.C1.XY.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the 2D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector2(this M33i m)\n            => new V2d(m.C0.XY.Length, m.C1.XY.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Norm1(M33i m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M33i m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMax(M33i m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMin(M33i m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M33i m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static int Distance1(this M33i a, M33i b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M33i a, M33i b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M33i a, M33i b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMax(this M33i a, M33i b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMin(this M33i a, M33i b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Transform(this M33i m, V3i v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Transform(this M33i m, V4i v)\n        {\n            return new V4i(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i TransposedTransform(this M33i m, V3i v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i TransposedTransform(this M33i m, V4i v)\n        {\n            return new V4i(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V2i TransformDir(this M33i m, V2i v)\n        {\n            return new V2i(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V2i TransformPos(this M33i m, V2i p)\n        {\n            return new V2i(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V2i TransformPosProj(this M33i m, V2i p)\n        {\n            int s = m.M20 * p.X + m.M21 * p.Y + m.M22;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V3i TransformPosProjFull(this M33i m, V2i p)\n        {\n            return new V3i(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12, \n                m.M20 * p.X + m.M21 * p.Y + m.M22\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static V2i TransposedTransformDir(this M33i m, V2i v)\n        {\n            return new V2i(\n                m.M00 * v.X + m.M10 * v.Y, \n                m.M01 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V2i TransposedTransformPos(this M33i m, V2i p)\n        {\n            return new V2i(\n                m.M00 * p.X + m.M10 * p.Y + m.M20, \n                m.M01 * p.X + m.M11 * p.Y + m.M21\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V2i TransposedTransformPosProj(this M33i m, V2i p)\n        {\n            var s = m.M02 * p.X + m.M12 * p.Y + m.M22;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static V2i TransposedTransformProj(this M33i m, V2i p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V3i TransposedTransformPosProjFull(this M33i m, V2i p)\n        {\n            return new V3i(\n                m.M00 * p.X + m.M10 * p.Y + m.M20, \n                m.M01 * p.X + m.M11 * p.Y + m.M21, \n                m.M02 * p.X + m.M12 * p.Y + m.M22\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static V3i TransposedTransformProjFull(this M33i m, V2i p)\n            => m.TransposedTransformPosProjFull(p);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M33i\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static M22i Minor(this M33i m, int row, int column)\n        {\n            M22i rs = new M22i();\n\n            for (int k = 0; k < 4; k++)\n            {\n                var i = k / 2;\n                var j = k % 2;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * 3 + jj];\n            }\n\n            return rs;\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3i Row(this M33i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V3i(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3i Column(this M33i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V3i(ptr[index], ptr[index + 3], ptr[index + 6]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Determinant(M33i m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Transposed(M33i m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M33i m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n            Fun.Swap(ref m.M20, ref m.M02);\n            Fun.Swap(ref m.M21, ref m.M12);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M33i a, M33i b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M33i m, int s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(int s, M33i m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M33i a, M33i b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M33i m, int s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(int s, M33i m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M33i a, M33i b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M33i m, int s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(int s, M33i m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M33i a, M33i b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M33i m, int s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(int s, M33i m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M33i a, M33i b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M33i m, int s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(int s, M33i m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M33i a, M33i b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M33i m, int s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(int s, M33i m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M33i a, M33i b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M33i m, int s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(int s, M33i m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M33i a, M33i b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M33i m, int s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(int s, M33i m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M33i a, M33i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M33i m, int s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(int s, M33i m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M33i a, M33i b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M33i m, int s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(int s, M33i m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M33i a, M33i b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M33i m, int s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(int s, M33i m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M33i a, M33i b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M33i m, int s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(int s, M33i m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M33i m0, M33i m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M33i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MinElement(M33i m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M33i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MaxElement(M33i m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M33i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M33i m, int epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M33i m, int epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M33i a, M33i b, int epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M33i m, int epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM33iExtensions\n    {\n        #region IRandomUniform extensions for M33i\n\n        /// <summary>\n        /// Uses UniformInt() to generate the elements of an M33i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i UniformM33i(this IRandomUniform rnd)\n        {\n            return new M33i(\n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt());\n        }\n\n        /// <summary>\n        /// Uses UniformIntNonZero() to generate the elements of an M33i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i UniformM33iNonZero(this IRandomUniform rnd)\n        {\n            return new M33i(\n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M33i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i UniformM33i(this IRandomUniform rnd, int size)\n        {\n            return new M33i(\n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size));\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M33i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i UniformM33i(this IRandomUniform rnd, M33i size)\n        {\n            return new M33i(\n                rnd.UniformInt(size.M00), rnd.UniformInt(size.M01), rnd.UniformInt(size.M02), \n                rnd.UniformInt(size.M10), rnd.UniformInt(size.M11), rnd.UniformInt(size.M12), \n                rnd.UniformInt(size.M20), rnd.UniformInt(size.M21), rnd.UniformInt(size.M22));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M33l\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M33l : IEquatable<M33l>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public long M00, M01, M02;\n        [DataMember]\n        public long M10, M11, M12;\n        [DataMember]\n        public long M20, M21, M22;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(long value)\n        {\n            M00 = value; M01 = 0; M02 = 0; \n            M10 = 0; M11 = value; M12 = 0; \n            M20 = 0; M21 = 0; M22 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(\n                long m00, long m01, long m02, \n                long m10, long m11, long m12, \n                long m20, long m21, long m22)\n        {\n            M00 = m00; M01 = m01; M02 = m02; \n            M10 = m10; M11 = m11; M12 = m12; \n            M20 = m20; M21 = m21; M22 = m22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(long[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M10 = a[3];\n            M11 = a[4];\n            M12 = a[5];\n            M20 = a[6];\n            M21 = a[7];\n            M22 = a[8];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(long[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M10 = a[start + 3];\n            M11 = a[start + 4];\n            M12 = a[start + 5];\n            M20 = a[start + 6];\n            M21 = a[start + 7];\n            M22 = a[start + 8];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M22i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M23i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M33i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M34i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M44i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M22l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M23l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M34l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M44l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M22f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M23f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M33f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M34f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M44f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M22d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M23d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M33d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M34d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33l(M44d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M33l(M22i m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33l(M23i m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33l(M33i m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M34i m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M44i m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M22l m)\n        {\n            return new M33l {\n                M00 = m.M00, M01 = m.M01, M02 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33l(M23l m)\n        {\n            return new M33l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33l(M34l m)\n        {\n            return new M33l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M44l m)\n        {\n            return new M33l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M22f m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33l(M23f m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33l(M33f m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M34f m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M44f m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M22d m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33l(M23d m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33l(M33d m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M34d m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(M44d m)\n        {\n            return new M33l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, \n            };\n        }\n\n        public static explicit operator M33l(int[] a)\n        {\n            return new M33l(\n                (long)a[0], (long)a[1], (long)a[2], \n                (long)a[3], (long)a[4], (long)a[5], \n                (long)a[6], (long)a[7], (long)a[8]);\n        }\n\n        public static explicit operator M33l(int[,] a)\n        {\n            return new M33l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2]);\n        }\n\n        public static explicit operator int[](M33l m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, \n                (int)m.M10, (int)m.M11, (int)m.M12, \n                (int)m.M20, (int)m.M21, (int)m.M22\n            };\n        }\n\n        public static explicit operator int[,](M33l m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M10;\n            array[index + 4] = (int)M11;\n            array[index + 5] = (int)M12;\n            array[index + 6] = (int)M20;\n            array[index + 7] = (int)M21;\n            array[index + 8] = (int)M22;\n        }\n\n        public static explicit operator M33l(long[] a)\n        {\n            return new M33l(\n                a[0], a[1], a[2], \n                a[3], a[4], a[5], \n                a[6], a[7], a[8]);\n        }\n\n        public static explicit operator M33l(long[,] a)\n        {\n            return new M33l(\n                a[0, 0], a[0, 1], a[0, 2], \n                a[1, 0], a[1, 1], a[1, 2], \n                a[2, 0], a[2, 1], a[2, 2]);\n        }\n\n        public static explicit operator long[](M33l m)\n        {\n            return new long[] {\n                m.M00, m.M01, m.M02, \n                m.M10, m.M11, m.M12, \n                m.M20, m.M21, m.M22\n            };\n        }\n\n        public static explicit operator long[,](M33l m)\n        {\n            return new long[,] {\n                { m.M00, m.M01, m.M02 }, \n                { m.M10, m.M11, m.M12 }, \n                { m.M20, m.M21, m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M10;\n            array[index + 4] = M11;\n            array[index + 5] = M12;\n            array[index + 6] = M20;\n            array[index + 7] = M21;\n            array[index + 8] = M22;\n        }\n\n        public static explicit operator M33l(float[] a)\n        {\n            return new M33l(\n                (long)a[0], (long)a[1], (long)a[2], \n                (long)a[3], (long)a[4], (long)a[5], \n                (long)a[6], (long)a[7], (long)a[8]);\n        }\n\n        public static explicit operator M33l(float[,] a)\n        {\n            return new M33l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2]);\n        }\n\n        public static explicit operator float[](M33l m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, \n                (float)m.M10, (float)m.M11, (float)m.M12, \n                (float)m.M20, (float)m.M21, (float)m.M22\n            };\n        }\n\n        public static explicit operator float[,](M33l m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M10;\n            array[index + 4] = (float)M11;\n            array[index + 5] = (float)M12;\n            array[index + 6] = (float)M20;\n            array[index + 7] = (float)M21;\n            array[index + 8] = (float)M22;\n        }\n\n        public static explicit operator M33l(double[] a)\n        {\n            return new M33l(\n                (long)a[0], (long)a[1], (long)a[2], \n                (long)a[3], (long)a[4], (long)a[5], \n                (long)a[6], (long)a[7], (long)a[8]);\n        }\n\n        public static explicit operator M33l(double[,] a)\n        {\n            return new M33l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2]);\n        }\n\n        public static explicit operator double[](M33l m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, \n                (double)m.M10, (double)m.M11, (double)m.M12, \n                (double)m.M20, (double)m.M21, (double)m.M22\n            };\n        }\n\n        public static explicit operator double[,](M33l m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M10;\n            array[index + 4] = (double)M11;\n            array[index + 5] = (double)M12;\n            array[index + 6] = (double)M20;\n            array[index + 7] = (double)M21;\n            array[index + 8] = (double)M22;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33i Copy(Func<long, int> element_fun)\n        {\n            return new M33i(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33i Copy(Func<long, int, int, int> element_index0_index1_fun)\n        {\n            return new M33i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33l Copy(Func<long, long> element_fun)\n        {\n            return new M33l(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33l Copy(Func<long, int, int, long> element_index0_index1_fun)\n        {\n            return new M33l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33f Copy(Func<long, float> element_fun)\n        {\n            return new M33f(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33f Copy(Func<long, int, int, float> element_index0_index1_fun)\n        {\n            return new M33f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33d Copy(Func<long, double> element_fun)\n        {\n            return new M33d(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33d Copy(Func<long, int, int, double> element_index0_index1_fun)\n        {\n            return new M33d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly M22l UpperLeftM22()\n        {\n            return (M22l)this;\n        }\n\n        public readonly long[] ToArray()\n        {\n            var array = new long[9];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M10;\n            array[4] = M11;\n            array[5] = M12;\n            array[6] = M20;\n            array[7] = M21;\n            array[8] = M22;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l FromCols(V3l col0, V3l col1, V3l col2)\n        {\n            return new M33l(\n                col0.X, col1.X, col2.X, \n                col0.Y, col1.Y, col2.Y, \n                col0.Z, col1.Z, col2.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l FromRows(V3l row0, V3l row1, V3l row2)\n        {\n            return new M33l(\n                row0.X, row0.Y, row0.Z, \n                row1.X, row1.Y, row1.Z, \n                row2.X, row2.Y, row2.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l FromDiagonal(long value)\n        {\n            return new M33l(\n                value, 0, 0, \n                0, value, 0, \n                0, 0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l FromDiagonal(long m00, long m11, long m22)\n        {\n            return new M33l(\n                m00, 0, 0, \n                0, m11, 0, \n                0, 0, m22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l FromDiagonal(V3l s)\n        {\n            return new M33l(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, s.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l FromAntiDiagonal(long value)\n        {\n            return new M33l(\n                 0, 0, value, \n                 0, value, 0, \n                 value, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l FromAntiDiagonal(long m02, long m11, long m20)\n        {\n            return new M33l(\n                0, 0, m02, \n                0, m11, 0, \n                m20, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l FromAntiDiagonal(V3l s)\n        {\n            return new M33l(\n                0, 0, s.X, \n                0, s.Y, 0, \n                s.Z, 0, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33l\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Scale(long sX, long sY, long sZ)\n            => FromDiagonal(sX, sY, sZ);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33l\"/> using a <see cref=\"V3l\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Scale(V3l s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M33l\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Scale(long s)\n        {\n            return new M33l(\n                s, 0, 0, \n                0, s, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33l\"/> using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Scale(long sX, long sY)\n        {\n            return new M33l(\n                sX, 0, 0, \n                0, sY, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33l\"/> using a <see cref=\"V2l\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Scale(V2l s)\n        {\n            return new M33l(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, 1);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33l\"/> with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Translation(long tX, long tY)\n        {\n            return new M33l(\n                1, 0, tX, \n                0, 1, tY, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33l\"/> with the translational component given by a <see cref=\"V2l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Translation(V2l t)\n        {\n            return new M33l(\n                1, 0, t.X, \n                0, 1, t.Y, \n                0, 0, 1);\n        }\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l ShearXY(long factorX, long factorY)\n        {\n            return new M33l(\n                1, 0, factorX, \n                0, 1, factorY, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l ShearXZ(long factorX, long factorZ)\n        {\n            return new M33l(\n                1, factorX, 0, \n                0, 1, 0, \n                0, factorZ, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l ShearYZ(long factorY, long factorZ)\n        {\n            return new M33l(\n                1, 0, 0, \n                factorY, 1, 0, \n                factorZ, 0, 1);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l DivideByInt(M33l m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n            }\n        }\n\n        public readonly IEnumerable<V3l> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n            }\n        }\n\n        public readonly IEnumerable<V3l> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M00,  M01,  M02); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M10,  M11,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M20,  M21,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M00,  M10,  M20); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M01,  M11,  M21); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M02,  M12,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        public readonly V3l Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3l(M00, M11, M22);\n        }\n\n        public readonly V3l AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3l(M02, M11, M20);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly long MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M10, M11, M12, M20, M21, M22);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly long MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M10, M11, M12, M20, M21, M22);\n        }\n\n        public unsafe long this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe long this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[row * 3 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[row * 3 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 3;\n        public const int ColumnCount = 3;\n        public const int ElementCount = 3 * 3;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(3, 3);\n        }\n\n        public static M33l Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M33l(0);\n        }\n\n        public static M33l Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M33l(1, 0, 0, 0, 1, 0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly long Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + \n                    M20 * M20 + M21 * M21 + M22 * M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator -(M33l m)\n        {\n            return new M33l(\n                -m.M00, -m.M01, -m.M02, \n                -m.M10, -m.M11, -m.M12, \n                -m.M20, -m.M21, -m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  + (M33l a, M33l b)\n        {\n            return new M33l(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  + (M33l m, long s)\n        {\n            return new M33l(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  + (long s, M33l m)\n        {\n            return new M33l(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (M33l a, M33f b)\n        {\n            return new M33f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (M33l m, float s)\n        {\n            return new M33f(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (float s, M33l m)\n        {\n            return new M33f(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (M33l a, M33d b)\n        {\n            return new M33d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (M33l m, double s)\n        {\n            return new M33d(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (double s, M33l m)\n        {\n            return new M33d(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  - (M33l a, M33l b)\n        {\n            return new M33l(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  - (M33l m, long s)\n        {\n            return new M33l(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  - (long s, M33l m)\n        {\n            return new M33l(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (M33l a, M33f b)\n        {\n            return new M33f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (M33l m, float s)\n        {\n            return new M33f(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (float s, M33l m)\n        {\n            return new M33f(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (M33l a, M33d b)\n        {\n            return new M33d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (M33l m, double s)\n        {\n            return new M33d(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (double s, M33l m)\n        {\n            return new M33d(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  % (M33l a, M33l b)\n        {\n            return new M33l(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  % (M33l m, long s)\n        {\n            return new M33l(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  % (long s, M33l m)\n        {\n            return new M33l(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (M33l a, M33f b)\n        {\n            return new M33f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (M33l m, float s)\n        {\n            return new M33f(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (float s, M33l m)\n        {\n            return new M33f(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (M33l a, M33d b)\n        {\n            return new M33d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (M33l m, double s)\n        {\n            return new M33d(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (double s, M33l m)\n        {\n            return new M33d(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  / (M33l a, M33l b)\n        {\n            return new M33l(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  / (M33l m, long s)\n        {\n            return new M33l(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  / (long s, M33l m)\n        {\n            return new M33l(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (M33l a, M33f b)\n        {\n            return new M33f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (M33l m, float s)\n        {\n            return new M33f(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (float s, M33l m)\n        {\n            return new M33f(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (M33l a, M33d b)\n        {\n            return new M33d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (M33l m, double s)\n        {\n            return new M33d(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (double s, M33l m)\n        {\n            return new M33d(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  * (M33l m, long s)\n        {\n            return new M33l(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator  * (long s, M33l m)\n        {\n            return new M33l(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  * (M33l m, float s)\n        {\n            return new M33f(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  * (float s, M33l m)\n        {\n            return new M33f(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  * (M33l m, double s)\n        {\n            return new M33d(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  * (double s, M33l m)\n        {\n            return new M33d(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator ~(M33l m)\n        {\n            return new M33l(\n                ~m.M00, ~m.M01, ~m.M02, \n                ~m.M10, ~m.M11, ~m.M12, \n                ~m.M20, ~m.M21, ~m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator <<(M33l a, int s)\n        {\n            return new M33l(\n                a.M00 << s, a.M01 << s, a.M02 << s, \n                a.M10 << s, a.M11 << s, a.M12 << s, \n                a.M20 << s, a.M21 << s, a.M22 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator >>(M33l a, int s)\n        {\n            return new M33l(\n                a.M00 >> s, a.M01 >> s, a.M02 >> s, \n                a.M10 >> s, a.M11 >> s, a.M12 >> s, \n                a.M20 >> s, a.M21 >> s, a.M22 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator &(M33l a, M33l b)\n        {\n            return new M33l(\n                a.M00 & b.M00, a.M01 & b.M01, a.M02 & b.M02, \n                a.M10 & b.M10, a.M11 & b.M11, a.M12 & b.M12, \n                a.M20 & b.M20, a.M21 & b.M21, a.M22 & b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator &(M33l a, long s)\n        {\n            return new M33l(\n                a.M00 & s, a.M01 & s, a.M02 & s, \n                a.M10 & s, a.M11 & s, a.M12 & s, \n                a.M20 & s, a.M21 & s, a.M22 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator &(long s, M33l a)\n        {\n            return new M33l(\n                s & a.M00, s & a.M01, s & a.M02, \n                s & a.M10, s & a.M11, s & a.M12, \n                s & a.M20, s & a.M21, s & a.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator |(M33l a, M33l b)\n        {\n            return new M33l(\n                a.M00 | b.M00, a.M01 | b.M01, a.M02 | b.M02, \n                a.M10 | b.M10, a.M11 | b.M11, a.M12 | b.M12, \n                a.M20 | b.M20, a.M21 | b.M21, a.M22 | b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator |(M33l a, long s)\n        {\n            return new M33l(\n                a.M00 | s, a.M01 | s, a.M02 | s, \n                a.M10 | s, a.M11 | s, a.M12 | s, \n                a.M20 | s, a.M21 | s, a.M22 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator |(long s, M33l a)\n        {\n            return new M33l(\n                s | a.M00, s | a.M01, s | a.M02, \n                s | a.M10, s | a.M11, s | a.M12, \n                s | a.M20, s | a.M21, s | a.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator ^(M33l a, M33l b)\n        {\n            return new M33l(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, a.M02 ^ b.M02, \n                a.M10 ^ b.M10, a.M11 ^ b.M11, a.M12 ^ b.M12, \n                a.M20 ^ b.M20, a.M21 ^ b.M21, a.M22 ^ b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator ^(M33l a, long s)\n        {\n            return new M33l(\n                a.M00 ^ s, a.M01 ^ s, a.M02 ^ s, \n                a.M10 ^ s, a.M11 ^ s, a.M12 ^ s, \n                a.M20 ^ s, a.M21 ^ s, a.M22 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l operator ^(long s, M33l a)\n        {\n            return new M33l(\n                s ^ a.M00, s ^ a.M01, s ^ a.M02, \n                s ^ a.M10, s ^ a.M11, s ^ a.M12, \n                s ^ a.M20, s ^ a.M21, s ^ a.M22);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M33l matrix with a V3l column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator *(M33l m, V3l v)\n        {\n            return new V3l(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a V3l row vector with a M33l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator *(V3l v, M33l m)\n        {\n            return new V3l(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M33l a, M33l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M33l a, long s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(long s, M33l a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M33l a, M33l b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M33l m, long s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(long s, M33l m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02),\n                        HashCode.GetCombined(M10, M11, M12),\n                        HashCode.GetCombined(M20, M21, M22));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M33l other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M33l o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M33l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M33l.FromRows(\n                V3l.Parse(x[0]), \n                V3l.Parse(x[1]), \n                V3l.Parse(x[2])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M33l Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                M33l result = new M33l();\n                for (int row = 0; row < 3; row++)\n                {\n                    for (int col = 0; col < 3; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly long Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 + M22 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly long Determinant\n        {\n            get\n            {\n                if (M10 == 0 && M20 == 0 && M21 == 0)\n                {\n                    return M00 * M11 * M22;\n                }\n                return\n                M00 * M11 * M22 - M00 * M12 * M21 +\n                M01 * M12 * M20 - M01 * M10 * M22 +\n                M02 * M10 * M21 - M02 * M11 * M20;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M33l Transposed\n        {\n            get\n            {\n                return new M33l {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    M02 = M20, \n                    \n                    M10 = M01, \n                    M11 = M11, \n                    M12 = M21, \n                    \n                    M20 = M02, \n                    M21 = M12, \n                    M22 = M22\n                };\n            }\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M33l operator *(M33l a, M33l b)\n        {\n            return new M33l(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (long)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (long)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (long)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (long)value;\n        }\n\n        #endregion\n    }\n\n    public class M33lEqualityComparer : IEqualityComparer<M33l>\n    {\n        public static readonly M33lEqualityComparer Default\n            = new M33lEqualityComparer();\n\n        #region IEqualityComparer<M33l> Members\n\n        public bool Equals(M33l v0, M33l v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M33l v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M33l m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector(this M33l m)\n            => new V3d(m.C0.Length, m.C1.Length, m.C2.Length);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of 2D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale2(this M33l m)\n            => (m.C0.XY.Length + m.C1.XY.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the 2D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector2(this M33l m)\n            => new V2d(m.C0.XY.Length, m.C1.XY.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Norm1(M33l m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M33l m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMax(M33l m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMin(M33l m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M33l m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static long Distance1(this M33l a, M33l b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M33l a, M33l b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M33l a, M33l b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMax(this M33l a, M33l b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMin(this M33l a, M33l b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Transform(this M33l m, V3l v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Transform(this M33l m, V4l v)\n        {\n            return new V4l(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l TransposedTransform(this M33l m, V3l v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l TransposedTransform(this M33l m, V4l v)\n        {\n            return new V4l(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V2l TransformDir(this M33l m, V2l v)\n        {\n            return new V2l(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V2l TransformPos(this M33l m, V2l p)\n        {\n            return new V2l(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V2l TransformPosProj(this M33l m, V2l p)\n        {\n            long s = m.M20 * p.X + m.M21 * p.Y + m.M22;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V3l TransformPosProjFull(this M33l m, V2l p)\n        {\n            return new V3l(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12, \n                m.M20 * p.X + m.M21 * p.Y + m.M22\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static V2l TransposedTransformDir(this M33l m, V2l v)\n        {\n            return new V2l(\n                m.M00 * v.X + m.M10 * v.Y, \n                m.M01 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V2l TransposedTransformPos(this M33l m, V2l p)\n        {\n            return new V2l(\n                m.M00 * p.X + m.M10 * p.Y + m.M20, \n                m.M01 * p.X + m.M11 * p.Y + m.M21\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V2l TransposedTransformPosProj(this M33l m, V2l p)\n        {\n            var s = m.M02 * p.X + m.M12 * p.Y + m.M22;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static V2l TransposedTransformProj(this M33l m, V2l p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V3l TransposedTransformPosProjFull(this M33l m, V2l p)\n        {\n            return new V3l(\n                m.M00 * p.X + m.M10 * p.Y + m.M20, \n                m.M01 * p.X + m.M11 * p.Y + m.M21, \n                m.M02 * p.X + m.M12 * p.Y + m.M22\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static V3l TransposedTransformProjFull(this M33l m, V2l p)\n            => m.TransposedTransformPosProjFull(p);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M33l\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static M22l Minor(this M33l m, int row, int column)\n        {\n            M22l rs = new M22l();\n\n            for (int k = 0; k < 4; k++)\n            {\n                var i = k / 2;\n                var j = k % 2;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * 3 + jj];\n            }\n\n            return rs;\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3l Row(this M33l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V3l(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3l Column(this M33l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V3l(ptr[index], ptr[index + 3], ptr[index + 6]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Determinant(M33l m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Transposed(M33l m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M33l m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n            Fun.Swap(ref m.M20, ref m.M02);\n            Fun.Swap(ref m.M21, ref m.M12);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M33l a, M33l b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M33l m, long s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(long s, M33l m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M33l a, M33l b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M33l m, long s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(long s, M33l m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M33l a, M33l b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M33l m, long s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(long s, M33l m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M33l a, M33l b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M33l m, long s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(long s, M33l m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M33l a, M33l b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M33l m, long s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(long s, M33l m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M33l a, M33l b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M33l m, long s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(long s, M33l m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M33l a, M33l b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M33l m, long s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(long s, M33l m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M33l a, M33l b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M33l m, long s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(long s, M33l m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M33l a, M33l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M33l m, long s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(long s, M33l m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M33l a, M33l b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M33l m, long s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(long s, M33l m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M33l a, M33l b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M33l m, long s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(long s, M33l m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M33l a, M33l b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M33l m, long s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(long s, M33l m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M33l m0, M33l m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M33l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MinElement(M33l m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M33l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MaxElement(M33l m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M33l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M33l m, long epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M33l m, long epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M33l a, M33l b, long epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M33l m, long epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM33lExtensions\n    {\n        #region IRandomUniform extensions for M33l\n\n        /// <summary>\n        /// Uses UniformLong() to generate the elements of an M33l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l UniformM33l(this IRandomUniform rnd)\n        {\n            return new M33l(\n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong());\n        }\n\n        /// <summary>\n        /// Uses UniformLongNonZero() to generate the elements of an M33l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l UniformM33lNonZero(this IRandomUniform rnd)\n        {\n            return new M33l(\n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M33l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l UniformM33l(this IRandomUniform rnd, long size)\n        {\n            return new M33l(\n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size));\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M33l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l UniformM33l(this IRandomUniform rnd, M33l size)\n        {\n            return new M33l(\n                rnd.UniformLong(size.M00), rnd.UniformLong(size.M01), rnd.UniformLong(size.M02), \n                rnd.UniformLong(size.M10), rnd.UniformLong(size.M11), rnd.UniformLong(size.M12), \n                rnd.UniformLong(size.M20), rnd.UniformLong(size.M21), rnd.UniformLong(size.M22));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M33f\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M33f : IEquatable<M33f>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public float M00, M01, M02;\n        [DataMember]\n        public float M10, M11, M12;\n        [DataMember]\n        public float M20, M21, M22;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(float value)\n        {\n            M00 = value; M01 = 0; M02 = 0; \n            M10 = 0; M11 = value; M12 = 0; \n            M20 = 0; M21 = 0; M22 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(\n                float m00, float m01, float m02, \n                float m10, float m11, float m12, \n                float m20, float m21, float m22)\n        {\n            M00 = m00; M01 = m01; M02 = m02; \n            M10 = m10; M11 = m11; M12 = m12; \n            M20 = m20; M21 = m21; M22 = m22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(float[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M10 = a[3];\n            M11 = a[4];\n            M12 = a[5];\n            M20 = a[6];\n            M21 = a[7];\n            M22 = a[8];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(float[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M10 = a[start + 3];\n            M11 = a[start + 4];\n            M12 = a[start + 5];\n            M20 = a[start + 6];\n            M21 = a[start + 7];\n            M22 = a[start + 8];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M22i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M23i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M33i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M34i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M44i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M22l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M23l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M33l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M34l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M44l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M22f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M23f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M34f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M44f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M22d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M23d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M33d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M34d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33f(M44d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M33f(M22i m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33f(M23i m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33f(M33i m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M34i m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M44i m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M22l m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33f(M23l m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33f(M33l m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M34l m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M44l m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M22f m)\n        {\n            return new M33f {\n                M00 = m.M00, M01 = m.M01, M02 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33f(M23f m)\n        {\n            return new M33f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33f(M34f m)\n        {\n            return new M33f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M44f m)\n        {\n            return new M33f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M22d m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33f(M23d m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33f(M33d m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M34d m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(M44d m)\n        {\n            return new M33f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, \n            };\n        }\n\n        public static explicit operator M33f(int[] a)\n        {\n            return new M33f(\n                (float)a[0], (float)a[1], (float)a[2], \n                (float)a[3], (float)a[4], (float)a[5], \n                (float)a[6], (float)a[7], (float)a[8]);\n        }\n\n        public static explicit operator M33f(int[,] a)\n        {\n            return new M33f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2]);\n        }\n\n        public static explicit operator int[](M33f m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, \n                (int)m.M10, (int)m.M11, (int)m.M12, \n                (int)m.M20, (int)m.M21, (int)m.M22\n            };\n        }\n\n        public static explicit operator int[,](M33f m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M10;\n            array[index + 4] = (int)M11;\n            array[index + 5] = (int)M12;\n            array[index + 6] = (int)M20;\n            array[index + 7] = (int)M21;\n            array[index + 8] = (int)M22;\n        }\n\n        public static explicit operator M33f(long[] a)\n        {\n            return new M33f(\n                (float)a[0], (float)a[1], (float)a[2], \n                (float)a[3], (float)a[4], (float)a[5], \n                (float)a[6], (float)a[7], (float)a[8]);\n        }\n\n        public static explicit operator M33f(long[,] a)\n        {\n            return new M33f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2]);\n        }\n\n        public static explicit operator long[](M33f m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, \n                (long)m.M10, (long)m.M11, (long)m.M12, \n                (long)m.M20, (long)m.M21, (long)m.M22\n            };\n        }\n\n        public static explicit operator long[,](M33f m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M10;\n            array[index + 4] = (long)M11;\n            array[index + 5] = (long)M12;\n            array[index + 6] = (long)M20;\n            array[index + 7] = (long)M21;\n            array[index + 8] = (long)M22;\n        }\n\n        public static explicit operator M33f(float[] a)\n        {\n            return new M33f(\n                a[0], a[1], a[2], \n                a[3], a[4], a[5], \n                a[6], a[7], a[8]);\n        }\n\n        public static explicit operator M33f(float[,] a)\n        {\n            return new M33f(\n                a[0, 0], a[0, 1], a[0, 2], \n                a[1, 0], a[1, 1], a[1, 2], \n                a[2, 0], a[2, 1], a[2, 2]);\n        }\n\n        public static explicit operator float[](M33f m)\n        {\n            return new float[] {\n                m.M00, m.M01, m.M02, \n                m.M10, m.M11, m.M12, \n                m.M20, m.M21, m.M22\n            };\n        }\n\n        public static explicit operator float[,](M33f m)\n        {\n            return new float[,] {\n                { m.M00, m.M01, m.M02 }, \n                { m.M10, m.M11, m.M12 }, \n                { m.M20, m.M21, m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M10;\n            array[index + 4] = M11;\n            array[index + 5] = M12;\n            array[index + 6] = M20;\n            array[index + 7] = M21;\n            array[index + 8] = M22;\n        }\n\n        public static explicit operator M33f(double[] a)\n        {\n            return new M33f(\n                (float)a[0], (float)a[1], (float)a[2], \n                (float)a[3], (float)a[4], (float)a[5], \n                (float)a[6], (float)a[7], (float)a[8]);\n        }\n\n        public static explicit operator M33f(double[,] a)\n        {\n            return new M33f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2]);\n        }\n\n        public static explicit operator double[](M33f m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, \n                (double)m.M10, (double)m.M11, (double)m.M12, \n                (double)m.M20, (double)m.M21, (double)m.M22\n            };\n        }\n\n        public static explicit operator double[,](M33f m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M10;\n            array[index + 4] = (double)M11;\n            array[index + 5] = (double)M12;\n            array[index + 6] = (double)M20;\n            array[index + 7] = (double)M21;\n            array[index + 8] = (double)M22;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33i Copy(Func<float, int> element_fun)\n        {\n            return new M33i(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33i Copy(Func<float, int, int, int> element_index0_index1_fun)\n        {\n            return new M33i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33l Copy(Func<float, long> element_fun)\n        {\n            return new M33l(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33l Copy(Func<float, int, int, long> element_index0_index1_fun)\n        {\n            return new M33l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33f Copy(Func<float, float> element_fun)\n        {\n            return new M33f(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33f Copy(Func<float, int, int, float> element_index0_index1_fun)\n        {\n            return new M33f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33d Copy(Func<float, double> element_fun)\n        {\n            return new M33d(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33d Copy(Func<float, int, int, double> element_index0_index1_fun)\n        {\n            return new M33d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly M22f UpperLeftM22()\n        {\n            return (M22f)this;\n        }\n\n        public readonly float[] ToArray()\n        {\n            var array = new float[9];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M10;\n            array[4] = M11;\n            array[5] = M12;\n            array[6] = M20;\n            array[7] = M21;\n            array[8] = M22;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f FromCols(V3f col0, V3f col1, V3f col2)\n        {\n            return new M33f(\n                col0.X, col1.X, col2.X, \n                col0.Y, col1.Y, col2.Y, \n                col0.Z, col1.Z, col2.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f FromRows(V3f row0, V3f row1, V3f row2)\n        {\n            return new M33f(\n                row0.X, row0.Y, row0.Z, \n                row1.X, row1.Y, row1.Z, \n                row2.X, row2.Y, row2.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f FromDiagonal(float value)\n        {\n            return new M33f(\n                value, 0, 0, \n                0, value, 0, \n                0, 0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f FromDiagonal(float m00, float m11, float m22)\n        {\n            return new M33f(\n                m00, 0, 0, \n                0, m11, 0, \n                0, 0, m22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f FromDiagonal(V3f s)\n        {\n            return new M33f(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, s.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f FromAntiDiagonal(float value)\n        {\n            return new M33f(\n                 0, 0, value, \n                 0, value, 0, \n                 value, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f FromAntiDiagonal(float m02, float m11, float m20)\n        {\n            return new M33f(\n                0, 0, m02, \n                0, m11, 0, \n                m20, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f FromAntiDiagonal(V3f s)\n        {\n            return new M33f(\n                0, 0, s.X, \n                0, s.Y, 0, \n                s.Z, 0, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33f\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Scale(float sX, float sY, float sZ)\n            => FromDiagonal(sX, sY, sZ);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33f\"/> using a <see cref=\"V3f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Scale(V3f s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33f\"/> from a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Scale(Scale3f s)\n        {\n            return new M33f(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, s.Z);\n        }\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M33f\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Scale(float s)\n        {\n            return new M33f(\n                s, 0, 0, \n                0, s, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33f\"/> using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Scale(float sX, float sY)\n        {\n            return new M33f(\n                sX, 0, 0, \n                0, sY, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33f\"/> using a <see cref=\"V2f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Scale(V2f s)\n        {\n            return new M33f(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation <see cref=\"M33f\"/> from a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Scale(Scale2f s)\n        {\n            return new M33f(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, 1);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33f\"/> with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Translation(float tX, float tY)\n        {\n            return new M33f(\n                1, 0, tX, \n                0, 1, tY, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33f\"/> with the translational component given by a <see cref=\"V2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Translation(V2f t)\n        {\n            return new M33f(\n                1, 0, t.X, \n                0, 1, t.Y, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33f\"/> from a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Translation(Shift2f s)\n        {\n            return new M33f(\n                1, 0, s.X, \n                0, 1, s.Y, \n                0, 0, 1);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Rotation(float angleInRadians)\n        {\n            var a = Fun.Cos(angleInRadians);\n            var b = Fun.Sin(angleInRadians);\n\n            return new M33f(\n                 a, -b,  0, \n                 b,  a,  0, \n                 0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationInDegrees(float angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from a <see cref=\"Rot3f\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Rotation(Rot3f r)\n            => (M33f)r;\n\n        /// <summary>\n        /// Creates a 2D rotation matrix from a <see cref=\"Rot2f\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Rotation(Rot2f r)\n            => (M33f)r;\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Rotation(V3f normalizedAxis, float angleInRadians)\n        {\n            Debug.Assert(normalizedAxis.LengthSquared.ApproximateEquals(1, 1e-5f));\n            return (M33f)(Rot3f.Rotation(normalizedAxis, angleInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationInDegrees(V3f normalizedAxis, float angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationEuler(float rollInRadians, float pitchInRadians, float yawInRadians)\n        {\n            return (M33f)(Rot3f.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationEulerInDegrees(float rollInDegrees, float pitchInDegrees, float yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationEuler(V3f rollPitchYawInRadians)\n            => RotationEuler(\n                rollPitchYawInRadians.X,\n                rollPitchYawInRadians.Y,\n                rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationEulerInDegrees(V3f rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotateInto(V3f from, V3f into)\n        {\n            Debug.Assert(from.LengthSquared.ApproximateEquals(1, 1e-5f));\n            Debug.Assert(into.LengthSquared.ApproximateEquals(1, 1e-5f));\n            return (M33f)(Rot3f.RotateInto(from, into));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationX(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M33f(\n                 1,  0,  0, \n                 0,  a, -b, \n                 0,  b,  a);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationXInDegrees(float angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationY(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M33f(\n                 a,  0,  b, \n                 0,  1,  0, \n                -b,  0,  a);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationYInDegrees(float angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationZ(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M33f(\n                 a, -b,  0, \n                 b,  a,  0, \n                 0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f RotationZInDegrees(float angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f ShearXY(float factorX, float factorY)\n        {\n            return new M33f(\n                1, 0, factorX, \n                0, 1, factorY, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f ShearXZ(float factorX, float factorZ)\n        {\n            return new M33f(\n                1, factorX, 0, \n                0, 1, 0, \n                0, factorZ, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f ShearYZ(float factorY, float factorZ)\n        {\n            return new M33f(\n                1, 0, 0, \n                factorY, 1, 0, \n                factorZ, 0, 1);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f DivideByInt(M33f m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n            }\n        }\n\n        public readonly IEnumerable<V3f> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n            }\n        }\n\n        public readonly IEnumerable<V3f> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M00,  M01,  M02); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M10,  M11,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M20,  M21,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M00,  M10,  M20); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M01,  M11,  M21); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M02,  M12,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        public readonly V3f Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3f(M00, M11, M22);\n        }\n\n        public readonly V3f AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3f(M02, M11, M20);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly float MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M10, M11, M12, M20, M21, M22);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly float MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M10, M11, M12, M20, M21, M22);\n        }\n\n        public unsafe float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe float this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[row * 3 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[row * 3 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || Fun.IsFinite(M02) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11) || Fun.IsFinite(M12) || \n                    Fun.IsFinite(M20) || Fun.IsFinite(M21) || Fun.IsFinite(M22);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && Fun.IsFinite(M02) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11) && Fun.IsFinite(M12) && \n                    Fun.IsFinite(M20) && Fun.IsFinite(M21) && Fun.IsFinite(M22);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) || float.IsNaN(M01) || float.IsNaN(M02) || \n                    float.IsNaN(M10) || float.IsNaN(M11) || float.IsNaN(M12) || \n                    float.IsNaN(M20) || float.IsNaN(M21) || float.IsNaN(M22);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) && float.IsNaN(M01) && float.IsNaN(M02) && \n                    float.IsNaN(M10) && float.IsNaN(M11) && float.IsNaN(M12) && \n                    float.IsNaN(M20) && float.IsNaN(M21) && float.IsNaN(M22);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) || float.IsInfinity(M01) || float.IsInfinity(M02) || \n                    float.IsInfinity(M10) || float.IsInfinity(M11) || float.IsInfinity(M12) || \n                    float.IsInfinity(M20) || float.IsInfinity(M21) || float.IsInfinity(M22);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) && float.IsInfinity(M01) && float.IsInfinity(M02) && \n                    float.IsInfinity(M10) && float.IsInfinity(M11) && float.IsInfinity(M12) && \n                    float.IsInfinity(M20) && float.IsInfinity(M21) && float.IsInfinity(M22);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) || float.IsPositiveInfinity(M01) || float.IsPositiveInfinity(M02) || \n                    float.IsPositiveInfinity(M10) || float.IsPositiveInfinity(M11) || float.IsPositiveInfinity(M12) || \n                    float.IsPositiveInfinity(M20) || float.IsPositiveInfinity(M21) || float.IsPositiveInfinity(M22);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) && float.IsPositiveInfinity(M01) && float.IsPositiveInfinity(M02) && \n                    float.IsPositiveInfinity(M10) && float.IsPositiveInfinity(M11) && float.IsPositiveInfinity(M12) && \n                    float.IsPositiveInfinity(M20) && float.IsPositiveInfinity(M21) && float.IsPositiveInfinity(M22);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) || float.IsNegativeInfinity(M01) || float.IsNegativeInfinity(M02) || \n                    float.IsNegativeInfinity(M10) || float.IsNegativeInfinity(M11) || float.IsNegativeInfinity(M12) || \n                    float.IsNegativeInfinity(M20) || float.IsNegativeInfinity(M21) || float.IsNegativeInfinity(M22);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) && float.IsNegativeInfinity(M01) && float.IsNegativeInfinity(M02) && \n                    float.IsNegativeInfinity(M10) && float.IsNegativeInfinity(M11) && float.IsNegativeInfinity(M12) && \n                    float.IsNegativeInfinity(M20) && float.IsNegativeInfinity(M21) && float.IsNegativeInfinity(M22);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || Fun.IsTiny(M02) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11) || Fun.IsTiny(M12) || \n                    Fun.IsTiny(M20) || Fun.IsTiny(M21) || Fun.IsTiny(M22);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && Fun.IsTiny(M02) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11) && Fun.IsTiny(M12) && \n                    Fun.IsTiny(M20) && Fun.IsTiny(M21) && Fun.IsTiny(M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 3;\n        public const int ColumnCount = 3;\n        public const int ElementCount = 3 * 3;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(3, 3);\n        }\n\n        public static M33f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M33f(0);\n        }\n\n        public static M33f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M33f(1, 0, 0, 0, 1, 0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly float Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly float Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + \n                    M20 * M20 + M21 * M21 + M22 * M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator -(M33f m)\n        {\n            return new M33f(\n                -m.M00, -m.M01, -m.M02, \n                -m.M10, -m.M11, -m.M12, \n                -m.M20, -m.M21, -m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (M33f a, M33f b)\n        {\n            return new M33f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (M33f m, float s)\n        {\n            return new M33f(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  + (float s, M33f m)\n        {\n            return new M33f(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (M33f a, M33d b)\n        {\n            return new M33d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (M33f m, double s)\n        {\n            return new M33d(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (double s, M33f m)\n        {\n            return new M33d(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (M33f a, M33f b)\n        {\n            return new M33f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (M33f m, float s)\n        {\n            return new M33f(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  - (float s, M33f m)\n        {\n            return new M33f(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (M33f a, M33d b)\n        {\n            return new M33d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (M33f m, double s)\n        {\n            return new M33d(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (double s, M33f m)\n        {\n            return new M33d(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (M33f a, M33f b)\n        {\n            return new M33f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (M33f m, float s)\n        {\n            return new M33f(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  % (float s, M33f m)\n        {\n            return new M33f(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (M33f a, M33d b)\n        {\n            return new M33d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (M33f m, double s)\n        {\n            return new M33d(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (double s, M33f m)\n        {\n            return new M33d(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (M33f a, M33f b)\n        {\n            return new M33f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (M33f m, float s)\n        {\n            return new M33f(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  / (float s, M33f m)\n        {\n            return new M33f(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (M33f a, M33d b)\n        {\n            return new M33d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (M33f m, double s)\n        {\n            return new M33d(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (double s, M33f m)\n        {\n            return new M33d(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  * (M33f m, float s)\n        {\n            return new M33f(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator  * (float s, M33f m)\n        {\n            return new M33f(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  * (M33f m, double s)\n        {\n            return new M33d(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  * (double s, M33f m)\n        {\n            return new M33d(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M33f matrix with a V3f column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(M33f m, V3f v)\n        {\n            return new V3f(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a V3f row vector with a M33f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(V3f v, M33f m)\n        {\n            return new V3f(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M33f a, M33f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M33f a, float s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(float s, M33f a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M33f a, M33f b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M33f m, float s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(float s, M33f m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02),\n                        HashCode.GetCombined(M10, M11, M12),\n                        HashCode.GetCombined(M20, M21, M22));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M33f other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M33f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M33f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M33f.FromRows(\n                V3f.Parse(x[0]), \n                V3f.Parse(x[1]), \n                V3f.Parse(x[2])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M33f Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                M33f result = new M33f();\n                for (int row = 0; row < 3; row++)\n                {\n                    for (int col = 0; col < 3; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly float Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 + M22 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly float Determinant\n        {\n            get\n            {\n                if (M10 == 0 && M20 == 0 && M21 == 0)\n                {\n                    return M00 * M11 * M22;\n                }\n                return\n                M00 * M11 * M22 - M00 * M12 * M21 +\n                M01 * M12 * M20 - M01 * M10 * M22 +\n                M02 * M10 * M21 - M02 * M11 * M20;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M33f Transposed\n        {\n            get\n            {\n                return new M33f {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    M02 = M20, \n                    \n                    M10 = M01, \n                    M11 = M11, \n                    M12 = M21, \n                    \n                    M20 = M02, \n                    M21 = M12, \n                    M22 = M22\n                };\n            }\n        }\n\n        private static V2l s_luSize = new V2l(3, 3);\n        private static V2l s_luDelta = new V2l(1, 3);\n\n        /// <summary>\n        /// Inverts the given matrix using lu factorization in place. Returns true\n        /// if the matrix was invertible, otherwise the matrix remains unchanged.\n        /// </summary>\n        public bool LuInvert()\n        {\n            M33d dbl = (M33d)this;\n            if(dbl.LuInvert())\n            {\n                this = (M33f)dbl;\n                return true;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns the inverse of the matrix using lu factorization.\n        /// If the matrix is not invertible, M33f.Zero is returned.\n        /// </summary>\n        public readonly M33f LuInverse()\n        {\n            return (M33f)((M33d)this).LuInverse();\n        }\n\n        /// <summary>\n        /// Returns the inverse of this matrix. If the matrix is not invertible\n        /// M33f.Zero is returned.\n        /// </summary>\n        public readonly M33f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => LuInverse();\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M33f operator *(M33f a, M33f b)\n        {\n            return new M33f(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (float)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (float)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (float)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (float)value;\n        }\n\n        #endregion\n    }\n\n    public class M33fEqualityComparer : IEqualityComparer<M33f>\n    {\n        public static readonly M33fEqualityComparer Default\n            = new M33fEqualityComparer();\n\n        #region IEqualityComparer<M33f> Members\n\n        public bool Equals(M33f v0, M33f v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M33f v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale(this M33f m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetScaleVector(this M33f m)\n            => new V3f(m.C0.Length, m.C1.Length, m.C2.Length);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of 2D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale2(this M33f m)\n            => (m.C0.XY.Length + m.C1.XY.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the 2D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetScaleVector2(this M33f m)\n            => new V2f(m.C0.XY.Length, m.C1.XY.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm1(M33f m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm2(M33f m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMax(M33f m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMin(M33f m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(this M33f m, float p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static float Distance1(this M33f a, M33f b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static float Distance2(this M33f a, M33f b)\n        {\n            return (float)Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static float Distance(this M33f a, M33f b, float p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMax(this M33f a, M33f b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMin(this M33f a, M33f b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this M33f m, V3f v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this M33f m, V4f v)\n        {\n            return new V4f(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransposedTransform(this M33f m, V3f v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f TransposedTransform(this M33f m, V4f v)\n        {\n            return new V4f(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V2f TransformDir(this M33f m, V2f v)\n        {\n            return new V2f(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V2f TransformPos(this M33f m, V2f p)\n        {\n            return new V2f(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V2f TransformPosProj(this M33f m, V2f p)\n        {\n            float s = m.M20 * p.X + m.M21 * p.Y + m.M22;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V3f TransformPosProjFull(this M33f m, V2f p)\n        {\n            return new V3f(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12, \n                m.M20 * p.X + m.M21 * p.Y + m.M22\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static V2f TransposedTransformDir(this M33f m, V2f v)\n        {\n            return new V2f(\n                m.M00 * v.X + m.M10 * v.Y, \n                m.M01 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V2f TransposedTransformPos(this M33f m, V2f p)\n        {\n            return new V2f(\n                m.M00 * p.X + m.M10 * p.Y + m.M20, \n                m.M01 * p.X + m.M11 * p.Y + m.M21\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V2f TransposedTransformPosProj(this M33f m, V2f p)\n        {\n            var s = m.M02 * p.X + m.M12 * p.Y + m.M22;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static V2f TransposedTransformProj(this M33f m, V2f p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V3f TransposedTransformPosProjFull(this M33f m, V2f p)\n        {\n            return new V3f(\n                m.M00 * p.X + m.M10 * p.Y + m.M20, \n                m.M01 * p.X + m.M11 * p.Y + m.M21, \n                m.M02 * p.X + m.M12 * p.Y + m.M22\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static V3f TransposedTransformProjFull(this M33f m, V2f p)\n            => m.TransposedTransformPosProjFull(p);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M33f\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static M22f Minor(this M33f m, int row, int column)\n        {\n            M22f rs = new M22f();\n\n            for (int k = 0; k < 4; k++)\n            {\n                var i = k / 2;\n                var j = k % 2;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * 3 + jj];\n            }\n\n            return rs;\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3f Row(this M33f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V3f(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3f Column(this M33f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V3f(ptr[index], ptr[index + 3], ptr[index + 6]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Determinant(M33f m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Transposed(M33f m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M33f m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n            Fun.Swap(ref m.M20, ref m.M02);\n            Fun.Swap(ref m.M21, ref m.M12);\n        }\n\n        /// <summary>\n        /// Returns the inverse of the given matrix. If the matrix is not invertible\n        /// M33f.Zero is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Inverse(M33f m)\n            => m.Inverse;\n\n        /// <summary>\n        /// Inverts the given matrix in place. Returns true if the matrix was invertible,\n        /// otherwise the matrix remains unchanged.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Invert(this ref M33f m) { return m.LuInvert(); }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M33f m, float epsilon)\n        {\n            return Fun.ApproximateEquals(m, M33f.Identity, epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M33f m)\n            => IsIdentity(m, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M33f m, float epsilon)\n        {\n            var i = m * m.Transposed;\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M33f m)\n            => IsOrthonormal(m, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M33f m, float epsilon)\n        {\n            var i = m * m.Transposed;\n            for (int j = 0; j < 3; j++)\n                i[j, j] = 1; //inefficient implementation: just leave out the comparisons at the diagonal entries.\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M33f m)\n            => IsOrthogonal(m, Constant<float>.PositiveTinyValue);\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M33f a, M33f b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M33f m, float s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, M33f m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M33f a, M33f b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M33f m, float s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, M33f m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M33f a, M33f b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M33f m, float s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, M33f m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M33f a, M33f b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M33f m, float s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, M33f m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M33f a, M33f b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M33f m, float s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, M33f m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M33f a, M33f b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M33f m, float s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, M33f m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M33f a, M33f b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M33f m, float s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, M33f m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M33f a, M33f b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M33f m, float s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, M33f m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M33f a, M33f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M33f m, float s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, M33f m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M33f a, M33f b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M33f m, float s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, M33f m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M33f a, M33f b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M33f m, float s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, M33f m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M33f a, M33f b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M33f m, float s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, M33f m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M33f m0, M33f m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M33f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MinElement(M33f m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M33f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MaxElement(M33f m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region Orthogonalization\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M33f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthogonalize(this ref M33f matrix)\n        {\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n        }\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M33f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Orthogonalized(this M33f matrix)\n        {\n            M33f m = matrix;\n            Orthogonalize(ref m);\n            return m;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M33f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthonormalize(this ref M33f matrix)\n        {\n            matrix.C0 = matrix.C0.Normalized;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 = matrix.C1.Normalized;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 = matrix.C2.Normalized;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M33f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Orthonormalized(this M33f matrix)\n        {\n            M33f m = matrix;\n            Orthonormalize(ref m);\n            return m;\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M33f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M33f m, float epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M33f m, float epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M33f m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M33f m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M33f m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M33f m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M33f m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M33f m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M33f m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M33f m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M33f m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M33f m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M33f m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M33f m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M33f a, M33f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M33f a, M33f b, float epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M33f m, float epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M33f m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M33f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M33f v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M33f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M33f v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M33f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M33f v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M33f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M33f v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M33f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M33f v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM33fExtensions\n    {\n        #region IRandomUniform extensions for M33f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of an M33f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f UniformM33f(this IRandomUniform rnd)\n        {\n            return new M33f(\n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of an M33f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f UniformM33fClosed(this IRandomUniform rnd)\n        {\n            return new M33f(\n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of an M33f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f UniformM33fOpen(this IRandomUniform rnd)\n        {\n            return new M33f(\n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M33d\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M33d : IEquatable<M33d>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public double M00, M01, M02;\n        [DataMember]\n        public double M10, M11, M12;\n        [DataMember]\n        public double M20, M21, M22;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(double value)\n        {\n            M00 = value; M01 = 0; M02 = 0; \n            M10 = 0; M11 = value; M12 = 0; \n            M20 = 0; M21 = 0; M22 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(\n                double m00, double m01, double m02, \n                double m10, double m11, double m12, \n                double m20, double m21, double m22)\n        {\n            M00 = m00; M01 = m01; M02 = m02; \n            M10 = m10; M11 = m11; M12 = m12; \n            M20 = m20; M21 = m21; M22 = m22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(double[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M10 = a[3];\n            M11 = a[4];\n            M12 = a[5];\n            M20 = a[6];\n            M21 = a[7];\n            M22 = a[8];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(double[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M10 = a[start + 3];\n            M11 = a[start + 4];\n            M12 = a[start + 5];\n            M20 = a[start + 6];\n            M21 = a[start + 7];\n            M22 = a[start + 8];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M22i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M23i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M33i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M34i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M44i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M22l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M23l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M33l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M34l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M44l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M22f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M23f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M33f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M34f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M44f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M22d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M23d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = 0; M21 = 0; M22 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M34d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M33d(M44d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M33d(M22i m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33d(M23i m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33d(M33i m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M34i m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M44i m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M22l m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33d(M23l m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33d(M33l m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M34l m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M44l m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M22f m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33d(M23f m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33d(M33f m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M34f m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M44f m)\n        {\n            return new M33d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M22d m)\n        {\n            return new M33d {\n                M00 = m.M00, M01 = m.M01, M02 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33d(M23d m)\n        {\n            return new M33d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = 0, M21 = 0, M22 = 1, \n            };\n        }\n\n        public static explicit operator M33d(M34d m)\n        {\n            return new M33d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, \n            };\n        }\n\n        public static explicit operator M33d(M44d m)\n        {\n            return new M33d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, \n            };\n        }\n\n        public static explicit operator M33d(int[] a)\n        {\n            return new M33d(\n                (double)a[0], (double)a[1], (double)a[2], \n                (double)a[3], (double)a[4], (double)a[5], \n                (double)a[6], (double)a[7], (double)a[8]);\n        }\n\n        public static explicit operator M33d(int[,] a)\n        {\n            return new M33d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2]);\n        }\n\n        public static explicit operator int[](M33d m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, \n                (int)m.M10, (int)m.M11, (int)m.M12, \n                (int)m.M20, (int)m.M21, (int)m.M22\n            };\n        }\n\n        public static explicit operator int[,](M33d m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M10;\n            array[index + 4] = (int)M11;\n            array[index + 5] = (int)M12;\n            array[index + 6] = (int)M20;\n            array[index + 7] = (int)M21;\n            array[index + 8] = (int)M22;\n        }\n\n        public static explicit operator M33d(long[] a)\n        {\n            return new M33d(\n                (double)a[0], (double)a[1], (double)a[2], \n                (double)a[3], (double)a[4], (double)a[5], \n                (double)a[6], (double)a[7], (double)a[8]);\n        }\n\n        public static explicit operator M33d(long[,] a)\n        {\n            return new M33d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2]);\n        }\n\n        public static explicit operator long[](M33d m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, \n                (long)m.M10, (long)m.M11, (long)m.M12, \n                (long)m.M20, (long)m.M21, (long)m.M22\n            };\n        }\n\n        public static explicit operator long[,](M33d m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M10;\n            array[index + 4] = (long)M11;\n            array[index + 5] = (long)M12;\n            array[index + 6] = (long)M20;\n            array[index + 7] = (long)M21;\n            array[index + 8] = (long)M22;\n        }\n\n        public static explicit operator M33d(float[] a)\n        {\n            return new M33d(\n                (double)a[0], (double)a[1], (double)a[2], \n                (double)a[3], (double)a[4], (double)a[5], \n                (double)a[6], (double)a[7], (double)a[8]);\n        }\n\n        public static explicit operator M33d(float[,] a)\n        {\n            return new M33d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2]);\n        }\n\n        public static explicit operator float[](M33d m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, \n                (float)m.M10, (float)m.M11, (float)m.M12, \n                (float)m.M20, (float)m.M21, (float)m.M22\n            };\n        }\n\n        public static explicit operator float[,](M33d m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M10;\n            array[index + 4] = (float)M11;\n            array[index + 5] = (float)M12;\n            array[index + 6] = (float)M20;\n            array[index + 7] = (float)M21;\n            array[index + 8] = (float)M22;\n        }\n\n        public static explicit operator M33d(double[] a)\n        {\n            return new M33d(\n                a[0], a[1], a[2], \n                a[3], a[4], a[5], \n                a[6], a[7], a[8]);\n        }\n\n        public static explicit operator M33d(double[,] a)\n        {\n            return new M33d(\n                a[0, 0], a[0, 1], a[0, 2], \n                a[1, 0], a[1, 1], a[1, 2], \n                a[2, 0], a[2, 1], a[2, 2]);\n        }\n\n        public static explicit operator double[](M33d m)\n        {\n            return new double[] {\n                m.M00, m.M01, m.M02, \n                m.M10, m.M11, m.M12, \n                m.M20, m.M21, m.M22\n            };\n        }\n\n        public static explicit operator double[,](M33d m)\n        {\n            return new double[,] {\n                { m.M00, m.M01, m.M02 }, \n                { m.M10, m.M11, m.M12 }, \n                { m.M20, m.M21, m.M22 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M10;\n            array[index + 4] = M11;\n            array[index + 5] = M12;\n            array[index + 6] = M20;\n            array[index + 7] = M21;\n            array[index + 8] = M22;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33i Copy(Func<double, int> element_fun)\n        {\n            return new M33i(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33i Copy(Func<double, int, int, int> element_index0_index1_fun)\n        {\n            return new M33i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33l Copy(Func<double, long> element_fun)\n        {\n            return new M33l(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33l Copy(Func<double, int, int, long> element_index0_index1_fun)\n        {\n            return new M33l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33f Copy(Func<double, float> element_fun)\n        {\n            return new M33f(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33f Copy(Func<double, int, int, float> element_index0_index1_fun)\n        {\n            return new M33f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33d Copy(Func<double, double> element_fun)\n        {\n            return new M33d(\n                element_fun(M00), element_fun(M01), element_fun(M02), \n                element_fun(M10), element_fun(M11), element_fun(M12), \n                element_fun(M20), element_fun(M21), element_fun(M22));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M33d Copy(Func<double, int, int, double> element_index0_index1_fun)\n        {\n            return new M33d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2));\n        }\n\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly M22d UpperLeftM22()\n        {\n            return (M22d)this;\n        }\n\n        public readonly double[] ToArray()\n        {\n            var array = new double[9];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M10;\n            array[4] = M11;\n            array[5] = M12;\n            array[6] = M20;\n            array[7] = M21;\n            array[8] = M22;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d FromCols(V3d col0, V3d col1, V3d col2)\n        {\n            return new M33d(\n                col0.X, col1.X, col2.X, \n                col0.Y, col1.Y, col2.Y, \n                col0.Z, col1.Z, col2.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d FromRows(V3d row0, V3d row1, V3d row2)\n        {\n            return new M33d(\n                row0.X, row0.Y, row0.Z, \n                row1.X, row1.Y, row1.Z, \n                row2.X, row2.Y, row2.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d FromDiagonal(double value)\n        {\n            return new M33d(\n                value, 0, 0, \n                0, value, 0, \n                0, 0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d FromDiagonal(double m00, double m11, double m22)\n        {\n            return new M33d(\n                m00, 0, 0, \n                0, m11, 0, \n                0, 0, m22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d FromDiagonal(V3d s)\n        {\n            return new M33d(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, s.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d FromAntiDiagonal(double value)\n        {\n            return new M33d(\n                 0, 0, value, \n                 0, value, 0, \n                 value, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d FromAntiDiagonal(double m02, double m11, double m20)\n        {\n            return new M33d(\n                0, 0, m02, \n                0, m11, 0, \n                m20, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d FromAntiDiagonal(V3d s)\n        {\n            return new M33d(\n                0, 0, s.X, \n                0, s.Y, 0, \n                s.Z, 0, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33d\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Scale(double sX, double sY, double sZ)\n            => FromDiagonal(sX, sY, sZ);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33d\"/> using a <see cref=\"V3d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Scale(V3d s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33d\"/> from a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Scale(Scale3d s)\n        {\n            return new M33d(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, s.Z);\n        }\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M33d\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Scale(double s)\n        {\n            return new M33d(\n                s, 0, 0, \n                0, s, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33d\"/> using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Scale(double sX, double sY)\n        {\n            return new M33d(\n                sX, 0, 0, \n                0, sY, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33d\"/> using a <see cref=\"V2d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Scale(V2d s)\n        {\n            return new M33d(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation <see cref=\"M33d\"/> from a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Scale(Scale2d s)\n        {\n            return new M33d(\n                s.X, 0, 0, \n                0, s.Y, 0, \n                0, 0, 1);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33d\"/> with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Translation(double tX, double tY)\n        {\n            return new M33d(\n                1, 0, tX, \n                0, 1, tY, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33d\"/> with the translational component given by a <see cref=\"V2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Translation(V2d t)\n        {\n            return new M33d(\n                1, 0, t.X, \n                0, 1, t.Y, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M33d\"/> from a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Translation(Shift2d s)\n        {\n            return new M33d(\n                1, 0, s.X, \n                0, 1, s.Y, \n                0, 0, 1);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Rotation(double angleInRadians)\n        {\n            var a = Fun.Cos(angleInRadians);\n            var b = Fun.Sin(angleInRadians);\n\n            return new M33d(\n                 a, -b,  0, \n                 b,  a,  0, \n                 0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationInDegrees(double angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from a <see cref=\"Rot3d\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Rotation(Rot3d r)\n            => (M33d)r;\n\n        /// <summary>\n        /// Creates a 2D rotation matrix from a <see cref=\"Rot2d\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Rotation(Rot2d r)\n            => (M33d)r;\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Rotation(V3d normalizedAxis, double angleInRadians)\n        {\n            Debug.Assert(normalizedAxis.LengthSquared.ApproximateEquals(1, 1e-10));\n            return (M33d)(Rot3d.Rotation(normalizedAxis, angleInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationInDegrees(V3d normalizedAxis, double angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationEuler(double rollInRadians, double pitchInRadians, double yawInRadians)\n        {\n            return (M33d)(Rot3d.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationEulerInDegrees(double rollInDegrees, double pitchInDegrees, double yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationEuler(V3d rollPitchYawInRadians)\n            => RotationEuler(\n                rollPitchYawInRadians.X,\n                rollPitchYawInRadians.Y,\n                rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationEulerInDegrees(V3d rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotateInto(V3d from, V3d into)\n        {\n            Debug.Assert(from.LengthSquared.ApproximateEquals(1, 1e-10));\n            Debug.Assert(into.LengthSquared.ApproximateEquals(1, 1e-10));\n            return (M33d)(Rot3d.RotateInto(from, into));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationX(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M33d(\n                 1,  0,  0, \n                 0,  a, -b, \n                 0,  b,  a);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationXInDegrees(double angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationY(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M33d(\n                 a,  0,  b, \n                 0,  1,  0, \n                -b,  0,  a);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationYInDegrees(double angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationZ(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M33d(\n                 a, -b,  0, \n                 b,  a,  0, \n                 0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d RotationZInDegrees(double angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d ShearXY(double factorX, double factorY)\n        {\n            return new M33d(\n                1, 0, factorX, \n                0, 1, factorY, \n                0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d ShearXZ(double factorX, double factorZ)\n        {\n            return new M33d(\n                1, factorX, 0, \n                0, 1, 0, \n                0, factorZ, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d ShearYZ(double factorY, double factorZ)\n        {\n            return new M33d(\n                1, 0, 0, \n                factorY, 1, 0, \n                factorZ, 0, 1);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d DivideByInt(M33d m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n            }\n        }\n\n        public readonly IEnumerable<V3d> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n            }\n        }\n\n        public readonly IEnumerable<V3d> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M00,  M01,  M02); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M10,  M11,  M12); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M20,  M21,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M00,  M10,  M20); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M01,  M11,  M21); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M02,  M12,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        public readonly V3d Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3d(M00, M11, M22);\n        }\n\n        public readonly V3d AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3d(M02, M11, M20);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly double MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M10, M11, M12, M20, M21, M22);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly double MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M10, M11, M12, M20, M21, M22);\n        }\n\n        public unsafe double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe double this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[row * 3 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[row * 3 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || Fun.IsFinite(M02) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11) || Fun.IsFinite(M12) || \n                    Fun.IsFinite(M20) || Fun.IsFinite(M21) || Fun.IsFinite(M22);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && Fun.IsFinite(M02) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11) && Fun.IsFinite(M12) && \n                    Fun.IsFinite(M20) && Fun.IsFinite(M21) && Fun.IsFinite(M22);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) || double.IsNaN(M01) || double.IsNaN(M02) || \n                    double.IsNaN(M10) || double.IsNaN(M11) || double.IsNaN(M12) || \n                    double.IsNaN(M20) || double.IsNaN(M21) || double.IsNaN(M22);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) && double.IsNaN(M01) && double.IsNaN(M02) && \n                    double.IsNaN(M10) && double.IsNaN(M11) && double.IsNaN(M12) && \n                    double.IsNaN(M20) && double.IsNaN(M21) && double.IsNaN(M22);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) || double.IsInfinity(M01) || double.IsInfinity(M02) || \n                    double.IsInfinity(M10) || double.IsInfinity(M11) || double.IsInfinity(M12) || \n                    double.IsInfinity(M20) || double.IsInfinity(M21) || double.IsInfinity(M22);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) && double.IsInfinity(M01) && double.IsInfinity(M02) && \n                    double.IsInfinity(M10) && double.IsInfinity(M11) && double.IsInfinity(M12) && \n                    double.IsInfinity(M20) && double.IsInfinity(M21) && double.IsInfinity(M22);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) || double.IsPositiveInfinity(M01) || double.IsPositiveInfinity(M02) || \n                    double.IsPositiveInfinity(M10) || double.IsPositiveInfinity(M11) || double.IsPositiveInfinity(M12) || \n                    double.IsPositiveInfinity(M20) || double.IsPositiveInfinity(M21) || double.IsPositiveInfinity(M22);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) && double.IsPositiveInfinity(M01) && double.IsPositiveInfinity(M02) && \n                    double.IsPositiveInfinity(M10) && double.IsPositiveInfinity(M11) && double.IsPositiveInfinity(M12) && \n                    double.IsPositiveInfinity(M20) && double.IsPositiveInfinity(M21) && double.IsPositiveInfinity(M22);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) || double.IsNegativeInfinity(M01) || double.IsNegativeInfinity(M02) || \n                    double.IsNegativeInfinity(M10) || double.IsNegativeInfinity(M11) || double.IsNegativeInfinity(M12) || \n                    double.IsNegativeInfinity(M20) || double.IsNegativeInfinity(M21) || double.IsNegativeInfinity(M22);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) && double.IsNegativeInfinity(M01) && double.IsNegativeInfinity(M02) && \n                    double.IsNegativeInfinity(M10) && double.IsNegativeInfinity(M11) && double.IsNegativeInfinity(M12) && \n                    double.IsNegativeInfinity(M20) && double.IsNegativeInfinity(M21) && double.IsNegativeInfinity(M22);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || Fun.IsTiny(M02) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11) || Fun.IsTiny(M12) || \n                    Fun.IsTiny(M20) || Fun.IsTiny(M21) || Fun.IsTiny(M22);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && Fun.IsTiny(M02) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11) && Fun.IsTiny(M12) && \n                    Fun.IsTiny(M20) && Fun.IsTiny(M21) && Fun.IsTiny(M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 3;\n        public const int ColumnCount = 3;\n        public const int ElementCount = 3 * 3;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(3, 3);\n        }\n\n        public static M33d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M33d(0);\n        }\n\n        public static M33d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M33d(1, 0, 0, 0, 1, 0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly double Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + \n                    M20 * M20 + M21 * M21 + M22 * M22);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator -(M33d m)\n        {\n            return new M33d(\n                -m.M00, -m.M01, -m.M02, \n                -m.M10, -m.M11, -m.M12, \n                -m.M20, -m.M21, -m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (M33d a, M33d b)\n        {\n            return new M33d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (M33d m, double s)\n        {\n            return new M33d(\n                m.M00 + s, m.M01 + s, m.M02 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  + (double s, M33d m)\n        {\n            return new M33d(\n                s + m.M00, s + m.M01, s + m.M02, \n                s + m.M10, s + m.M11, s + m.M12, \n                s + m.M20, s + m.M21, s + m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (M33d a, M33d b)\n        {\n            return new M33d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (M33d m, double s)\n        {\n            return new M33d(\n                m.M00 - s, m.M01 - s, m.M02 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  - (double s, M33d m)\n        {\n            return new M33d(\n                s - m.M00, s - m.M01, s - m.M02, \n                s - m.M10, s - m.M11, s - m.M12, \n                s - m.M20, s - m.M21, s - m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (M33d a, M33d b)\n        {\n            return new M33d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (M33d m, double s)\n        {\n            return new M33d(\n                m.M00 % s, m.M01 % s, m.M02 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  % (double s, M33d m)\n        {\n            return new M33d(\n                s % m.M00, s % m.M01, s % m.M02, \n                s % m.M10, s % m.M11, s % m.M12, \n                s % m.M20, s % m.M21, s % m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (M33d a, M33d b)\n        {\n            return new M33d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (M33d m, double s)\n        {\n            return new M33d(\n                m.M00 / s, m.M01 / s, m.M02 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  / (double s, M33d m)\n        {\n            return new M33d(\n                s / m.M00, s / m.M01, s / m.M02, \n                s / m.M10, s / m.M11, s / m.M12, \n                s / m.M20, s / m.M21, s / m.M22);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  * (M33d m, double s)\n        {\n            return new M33d(\n                m.M00 * s, m.M01 * s, m.M02 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator  * (double s, M33d m)\n        {\n            return new M33d(\n                s * m.M00, s * m.M01, s * m.M02, \n                s * m.M10, s * m.M11, s * m.M12, \n                s * m.M20, s * m.M21, s * m.M22);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M33d matrix with a V3d column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(M33d m, V3d v)\n        {\n            return new V3d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a V3d row vector with a M33d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(V3d v, M33d m)\n        {\n            return new V3d(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M33d a, M33d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M33d a, double s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(double s, M33d a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M33d a, M33d b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M33d m, double s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(double s, M33d m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02),\n                        HashCode.GetCombined(M10, M11, M12),\n                        HashCode.GetCombined(M20, M21, M22));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M33d other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M33d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M33d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M33d.FromRows(\n                V3d.Parse(x[0]), \n                V3d.Parse(x[1]), \n                V3d.Parse(x[2])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M33d Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                M33d result = new M33d();\n                for (int row = 0; row < 3; row++)\n                {\n                    for (int col = 0; col < 3; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly double Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 + M22 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly double Determinant\n        {\n            get\n            {\n                if (M10 == 0 && M20 == 0 && M21 == 0)\n                {\n                    return M00 * M11 * M22;\n                }\n                return\n                M00 * M11 * M22 - M00 * M12 * M21 +\n                M01 * M12 * M20 - M01 * M10 * M22 +\n                M02 * M10 * M21 - M02 * M11 * M20;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M33d Transposed\n        {\n            get\n            {\n                return new M33d {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    M02 = M20, \n                    \n                    M10 = M01, \n                    M11 = M11, \n                    M12 = M21, \n                    \n                    M20 = M02, \n                    M21 = M12, \n                    M22 = M22\n                };\n            }\n        }\n\n        private static V2l s_luSize = new V2l(3, 3);\n        private static V2l s_luDelta = new V2l(1, 3);\n\n        /// <summary>\n        /// Inverts the given matrix using lu factorization in place. Returns true\n        /// if the matrix was invertible, otherwise the matrix remains unchanged.\n        /// </summary>\n        public unsafe bool LuInvert()\n        {\n            fixed (M33d* self = &this)\n            {\n                var lu = this;\n                V3i perm;\n                if (NumericExtensions.LuFactorize((double*)&lu, 0, 1, 3, (int*)&perm, 3))\n                {\n                    NumericExtensions.LuInverse((double*)&lu, 0, 1, 3, (int*)&perm, (double*)self, 0, 1, 3, 3);\n                    return true;\n                }\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns the inverse of the matrix using lu factorization.\n        /// If the matrix is not invertible, M33d.Zero is returned.\n        /// </summary>\n        public unsafe readonly M33d LuInverse()\n        {\n            var lu = this;\n            M33d res;\n            V3i perm;\n            if (NumericExtensions.LuFactorize((double*)&lu, 0, 1, 3, (int*)&perm, 3))\n            {\n                NumericExtensions.LuInverse((double*)&lu, 0, 1, 3, (int*)&perm, (double*)&res, 0, 1, 3, 3);\n                return res;\n            }\n            return M33d.Zero;\n        }\n\n        /// <summary>\n        /// Returns the inverse of this matrix. If the matrix is not invertible\n        /// M33d.Zero is returned.\n        /// </summary>\n        public readonly M33d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => LuInverse();\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M33d operator *(M33d a, M33d b)\n        {\n            return new M33d(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (double)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (double)value;\n        }\n\n        #endregion\n    }\n\n    public class M33dEqualityComparer : IEqualityComparer<M33d>\n    {\n        public static readonly M33dEqualityComparer Default\n            = new M33dEqualityComparer();\n\n        #region IEqualityComparer<M33d> Members\n\n        public bool Equals(M33d v0, M33d v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M33d v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M33d m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector(this M33d m)\n            => new V3d(m.C0.Length, m.C1.Length, m.C2.Length);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of 2D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale2(this M33d m)\n            => (m.C0.XY.Length + m.C1.XY.Length) / 2;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the 2D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector2(this M33d m)\n            => new V2d(m.C0.XY.Length, m.C1.XY.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm1(M33d m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M33d m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMax(M33d m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMin(M33d m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M33d m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static double Distance1(this M33d a, M33d b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M33d a, M33d b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M33d a, M33d b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMax(this M33d a, M33d b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMin(this M33d a, M33d b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this M33d m, V3d v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this M33d m, V4d v)\n        {\n            return new V4d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransposedTransform(this M33d m, V3d v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d TransposedTransform(this M33d m, V4d v)\n        {\n            return new V4d(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22,\n                v.W);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V2d TransformDir(this M33d m, V2d v)\n        {\n            return new V2d(\n                m.M00 * v.X + m.M01 * v.Y, \n                m.M10 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V2d TransformPos(this M33d m, V2d p)\n        {\n            return new V2d(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V2d TransformPosProj(this M33d m, V2d p)\n        {\n            double s = m.M20 * p.X + m.M21 * p.Y + m.M22;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V3d TransformPosProjFull(this M33d m, V2d p)\n        {\n            return new V3d(\n                m.M00 * p.X + m.M01 * p.Y + m.M02, \n                m.M10 * p.X + m.M11 * p.Y + m.M12, \n                m.M20 * p.X + m.M21 * p.Y + m.M22\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static V2d TransposedTransformDir(this M33d m, V2d v)\n        {\n            return new V2d(\n                m.M00 * v.X + m.M10 * v.Y, \n                m.M01 * v.X + m.M11 * v.Y\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V2d TransposedTransformPos(this M33d m, V2d p)\n        {\n            return new V2d(\n                m.M00 * p.X + m.M10 * p.Y + m.M20, \n                m.M01 * p.X + m.M11 * p.Y + m.M21\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V2d TransposedTransformPosProj(this M33d m, V2d p)\n        {\n            var s = m.M02 * p.X + m.M12 * p.Y + m.M22;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static V2d TransposedTransformProj(this M33d m, V2d p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.Z is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V3d TransposedTransformPosProjFull(this M33d m, V2d p)\n        {\n            return new V3d(\n                m.M00 * p.X + m.M10 * p.Y + m.M20, \n                m.M01 * p.X + m.M11 * p.Y + m.M21, \n                m.M02 * p.X + m.M12 * p.Y + m.M22\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static V3d TransposedTransformProjFull(this M33d m, V2d p)\n            => m.TransposedTransformPosProjFull(p);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M33d\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static M22d Minor(this M33d m, int row, int column)\n        {\n            M22d rs = new M22d();\n\n            for (int k = 0; k < 4; k++)\n            {\n                var i = k / 2;\n                var j = k % 2;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * 3 + jj];\n            }\n\n            return rs;\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3d Row(this M33d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V3d(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3d Column(this M33d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V3d(ptr[index], ptr[index + 3], ptr[index + 6]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Determinant(M33d m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Transposed(M33d m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M33d m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n            Fun.Swap(ref m.M20, ref m.M02);\n            Fun.Swap(ref m.M21, ref m.M12);\n        }\n\n        /// <summary>\n        /// Returns the inverse of the given matrix. If the matrix is not invertible\n        /// M33d.Zero is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Inverse(M33d m)\n            => m.Inverse;\n\n        /// <summary>\n        /// Inverts the given matrix in place. Returns true if the matrix was invertible,\n        /// otherwise the matrix remains unchanged.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Invert(this ref M33d m) { return m.LuInvert(); }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M33d m, double epsilon)\n        {\n            return Fun.ApproximateEquals(m, M33d.Identity, epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M33d m)\n            => IsIdentity(m, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M33d m, double epsilon)\n        {\n            var i = m * m.Transposed;\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M33d m)\n            => IsOrthonormal(m, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M33d m, double epsilon)\n        {\n            var i = m * m.Transposed;\n            for (int j = 0; j < 3; j++)\n                i[j, j] = 1; //inefficient implementation: just leave out the comparisons at the diagonal entries.\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M33d m)\n            => IsOrthogonal(m, Constant<double>.PositiveTinyValue);\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M33d a, M33d b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M33d m, double s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, M33d m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M33d a, M33d b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M33d m, double s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, M33d m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M33d a, M33d b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M33d m, double s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, M33d m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M33d a, M33d b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M33d m, double s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, M33d m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M33d a, M33d b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M33d m, double s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, M33d m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M33d a, M33d b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M33d m, double s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, M33d m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M33d a, M33d b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M33d m, double s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, M33d m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M33d a, M33d b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M33d m, double s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, M33d m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M33d a, M33d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M33d m, double s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, M33d m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M33d a, M33d b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M33d m, double s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, M33d m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M33d a, M33d b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M33d m, double s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, M33d m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M33d a, M33d b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M33d m, double s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, M33d m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M33d m0, M33d m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M33d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MinElement(M33d m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M33d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MaxElement(M33d m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region Orthogonalization\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M33d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthogonalize(this ref M33d matrix)\n        {\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n        }\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M33d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Orthogonalized(this M33d matrix)\n        {\n            M33d m = matrix;\n            Orthogonalize(ref m);\n            return m;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M33d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthonormalize(this ref M33d matrix)\n        {\n            matrix.C0 = matrix.C0.Normalized;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 = matrix.C1.Normalized;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 = matrix.C2.Normalized;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M33d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Orthonormalized(this M33d matrix)\n        {\n            M33d m = matrix;\n            Orthonormalize(ref m);\n            return m;\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M33d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M33d m, double epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M33d m, double epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M33d m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M33d m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M33d m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M33d m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M33d m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M33d m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M33d m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M33d m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M33d m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M33d m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M33d m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M33d m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M33d a, M33d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M33d a, M33d b, double epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M33d m, double epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M33d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M33d m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M33d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M33d v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M33d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M33d v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M33d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M33d v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M33d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M33d v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M33d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M33d v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM33dExtensions\n    {\n        #region IRandomUniform extensions for M33d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of an M33d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d UniformM33d(this IRandomUniform rnd)\n        {\n            return new M33d(\n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of an M33d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d UniformM33dClosed(this IRandomUniform rnd)\n        {\n            return new M33d(\n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of an M33d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d UniformM33dOpen(this IRandomUniform rnd)\n        {\n            return new M33d(\n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of an M33d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d UniformM33dFull(this IRandomUniform rnd)\n        {\n            return new M33d(\n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of an M33d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d UniformM33dFullClosed(this IRandomUniform rnd)\n        {\n            return new M33d(\n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of an M33d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d UniformM33dFullOpen(this IRandomUniform rnd)\n        {\n            return new M33d(\n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M34i\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M34i : IEquatable<M34i>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public int M00, M01, M02, M03;\n        [DataMember]\n        public int M10, M11, M12, M13;\n        [DataMember]\n        public int M20, M21, M22, M23;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(int value)\n        {\n            M00 = value; M01 = 0; M02 = 0; M03 = 0; \n            M10 = 0; M11 = value; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = value; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(\n                int m00, int m01, int m02, int m03, \n                int m10, int m11, int m12, int m13, \n                int m20, int m21, int m22, int m23)\n        {\n            M00 = m00; M01 = m01; M02 = m02; M03 = m03; \n            M10 = m10; M11 = m11; M12 = m12; M13 = m13; \n            M20 = m20; M21 = m21; M22 = m22; M23 = m23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(int[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M03 = a[3];\n            M10 = a[4];\n            M11 = a[5];\n            M12 = a[6];\n            M13 = a[7];\n            M20 = a[8];\n            M21 = a[9];\n            M22 = a[10];\n            M23 = a[11];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(int[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M03 = a[start + 3];\n            M10 = a[start + 4];\n            M11 = a[start + 5];\n            M12 = a[start + 6];\n            M13 = a[start + 7];\n            M20 = a[start + 8];\n            M21 = a[start + 9];\n            M22 = a[start + 10];\n            M23 = a[start + 11];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M33i m, V3i v)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = v.X; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = v.Y; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = v.Z; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M22i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M23i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M33i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M44i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = m.M03; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = m.M13; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M22l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M23l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M33l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M34l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M44l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M22f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M23f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M33f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M34f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M44f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M22d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M23d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M33d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M34d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34i(M44d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M34i(M22i m)\n        {\n            return new M34i {\n                M00 = m.M00, M01 = m.M01, M02 = 0, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M23i m)\n        {\n            return new M34i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M33i m)\n        {\n            return new M34i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M44i m)\n        {\n            return new M34i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = m.M03, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = m.M13, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = m.M23, \n            };\n        }\n\n        public static explicit operator M34i(M22l m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M23l m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M33l m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M34l m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n            };\n        }\n\n        public static explicit operator M34i(M44l m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n            };\n        }\n\n        public static explicit operator M34i(M22f m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M23f m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M33f m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M34f m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n            };\n        }\n\n        public static explicit operator M34i(M44f m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n            };\n        }\n\n        public static explicit operator M34i(M22d m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M23d m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M33d m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34i(M34d m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n            };\n        }\n\n        public static explicit operator M34i(M44d m)\n        {\n            return new M34i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n            };\n        }\n\n        public static explicit operator M34i(int[] a)\n        {\n            return new M34i(\n                a[0], a[1], a[2], a[3], \n                a[4], a[5], a[6], a[7], \n                a[8], a[9], a[10], a[11]);\n        }\n\n        public static explicit operator M34i(int[,] a)\n        {\n            return new M34i(\n                a[0, 0], a[0, 1], a[0, 2], a[0, 3], \n                a[1, 0], a[1, 1], a[1, 2], a[1, 3], \n                a[2, 0], a[2, 1], a[2, 2], a[2, 3]);\n        }\n\n        public static explicit operator int[](M34i m)\n        {\n            return new int[] {\n                m.M00, m.M01, m.M02, m.M03, \n                m.M10, m.M11, m.M12, m.M13, \n                m.M20, m.M21, m.M22, m.M23\n            };\n        }\n\n        public static explicit operator int[,](M34i m)\n        {\n            return new int[,] {\n                { m.M00, m.M01, m.M02, m.M03 }, \n                { m.M10, m.M11, m.M12, m.M13 }, \n                { m.M20, m.M21, m.M22, m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M03;\n            array[index + 4] = M10;\n            array[index + 5] = M11;\n            array[index + 6] = M12;\n            array[index + 7] = M13;\n            array[index + 8] = M20;\n            array[index + 9] = M21;\n            array[index + 10] = M22;\n            array[index + 11] = M23;\n        }\n\n        public static explicit operator M34i(long[] a)\n        {\n            return new M34i(\n                (int)a[0], (int)a[1], (int)a[2], (int)a[3], \n                (int)a[4], (int)a[5], (int)a[6], (int)a[7], \n                (int)a[8], (int)a[9], (int)a[10], (int)a[11]);\n        }\n\n        public static explicit operator M34i(long[,] a)\n        {\n            return new M34i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], (int)a[0, 3], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], (int)a[1, 3], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2], (int)a[2, 3]);\n        }\n\n        public static explicit operator long[](M34i m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03, \n                (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13, \n                (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23\n            };\n        }\n\n        public static explicit operator long[,](M34i m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M03;\n            array[index + 4] = (long)M10;\n            array[index + 5] = (long)M11;\n            array[index + 6] = (long)M12;\n            array[index + 7] = (long)M13;\n            array[index + 8] = (long)M20;\n            array[index + 9] = (long)M21;\n            array[index + 10] = (long)M22;\n            array[index + 11] = (long)M23;\n        }\n\n        public static explicit operator M34i(float[] a)\n        {\n            return new M34i(\n                (int)a[0], (int)a[1], (int)a[2], (int)a[3], \n                (int)a[4], (int)a[5], (int)a[6], (int)a[7], \n                (int)a[8], (int)a[9], (int)a[10], (int)a[11]);\n        }\n\n        public static explicit operator M34i(float[,] a)\n        {\n            return new M34i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], (int)a[0, 3], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], (int)a[1, 3], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2], (int)a[2, 3]);\n        }\n\n        public static explicit operator float[](M34i m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03, \n                (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13, \n                (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23\n            };\n        }\n\n        public static explicit operator float[,](M34i m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M03;\n            array[index + 4] = (float)M10;\n            array[index + 5] = (float)M11;\n            array[index + 6] = (float)M12;\n            array[index + 7] = (float)M13;\n            array[index + 8] = (float)M20;\n            array[index + 9] = (float)M21;\n            array[index + 10] = (float)M22;\n            array[index + 11] = (float)M23;\n        }\n\n        public static explicit operator M34i(double[] a)\n        {\n            return new M34i(\n                (int)a[0], (int)a[1], (int)a[2], (int)a[3], \n                (int)a[4], (int)a[5], (int)a[6], (int)a[7], \n                (int)a[8], (int)a[9], (int)a[10], (int)a[11]);\n        }\n\n        public static explicit operator M34i(double[,] a)\n        {\n            return new M34i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], (int)a[0, 3], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], (int)a[1, 3], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2], (int)a[2, 3]);\n        }\n\n        public static explicit operator double[](M34i m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03, \n                (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13, \n                (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23\n            };\n        }\n\n        public static explicit operator double[,](M34i m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M03;\n            array[index + 4] = (double)M10;\n            array[index + 5] = (double)M11;\n            array[index + 6] = (double)M12;\n            array[index + 7] = (double)M13;\n            array[index + 8] = (double)M20;\n            array[index + 9] = (double)M21;\n            array[index + 10] = (double)M22;\n            array[index + 11] = (double)M23;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34i Copy(Func<int, int> element_fun)\n        {\n            return new M34i(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34i Copy(Func<int, int, int, int> element_index0_index1_fun)\n        {\n            return new M34i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34l Copy(Func<int, long> element_fun)\n        {\n            return new M34l(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34l Copy(Func<int, int, int, long> element_index0_index1_fun)\n        {\n            return new M34l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34f Copy(Func<int, float> element_fun)\n        {\n            return new M34f(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34f Copy(Func<int, int, int, float> element_index0_index1_fun)\n        {\n            return new M34f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34d Copy(Func<int, double> element_fun)\n        {\n            return new M34d(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34d Copy(Func<int, int, int, double> element_index0_index1_fun)\n        {\n            return new M34d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        public readonly int[] ToArray()\n        {\n            var array = new int[12];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M03;\n            array[4] = M10;\n            array[5] = M11;\n            array[6] = M12;\n            array[7] = M13;\n            array[8] = M20;\n            array[9] = M21;\n            array[10] = M22;\n            array[11] = M23;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i FromCols(V3i col0, V3i col1, V3i col2, V3i col3)\n        {\n            return new M34i(\n                col0.X, col1.X, col2.X, col3.X, \n                col0.Y, col1.Y, col2.Y, col3.Y, \n                col0.Z, col1.Z, col2.Z, col3.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i FromRows(V4i row0, V4i row1, V4i row2)\n        {\n            return new M34i(\n                row0.X, row0.Y, row0.Z, row0.W, \n                row1.X, row1.Y, row1.Z, row1.W, \n                row2.X, row2.Y, row2.Z, row2.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i FromDiagonal(int value)\n        {\n            return new M34i(\n                value, 0, 0, 0, \n                0, value, 0, 0, \n                0, 0, value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i FromDiagonal(int m00, int m11, int m22)\n        {\n            return new M34i(\n                m00, 0, 0, 0, \n                0, m11, 0, 0, \n                0, 0, m22, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i FromDiagonal(V3i s)\n        {\n            return new M34i(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M34i\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i Scale(int s)\n        {\n            return new M34i(\n                s, 0, 0, 0, \n                0, s, 0, 0, \n                0, 0, s, 0);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34i\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i Scale(int sX, int sY, int sZ)\n        {\n            return new M34i(\n                sX, 0, 0, 0, \n                0, sY, 0, 0, \n                0, 0, sZ, 0);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34i\"/> using a <see cref=\"V3i\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i Scale(V3i s)\n        {\n            return new M34i(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34i\"/> with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i Translation(int tX, int tY, int tZ)\n        {\n            return new M34i(\n                1, 0, 0, tX, \n                0, 1, 0, tY, \n                0, 0, 1, tZ);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34i\"/> with the translational component given by a <see cref=\"V3i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i Translation(V3i t)\n        {\n            return new M34i(\n                1, 0, 0, t.X, \n                0, 1, 0, t.Y, \n                0, 0, 1, t.Z);\n        }\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i ShearXY(int factorX, int factorY)\n        {\n            return new M34i(\n                1, 0, factorX, 0, \n                0, 1, factorY, 0, \n                0, 0, 1, 0);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i ShearXZ(int factorX, int factorZ)\n        {\n            return new M34i(\n                1, factorX, 0, 0, \n                0, 1, 0, 0, \n                0, factorZ, 1, 0);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i ShearYZ(int factorY, int factorZ)\n        {\n            return new M34i(\n                1, 0, 0, 0, \n                factorY, 1, 0, 0, \n                factorZ, 0, 1, 0);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i DivideByInt(M34i m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M03;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M13;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n                yield return M23;\n            }\n        }\n\n        public readonly IEnumerable<V4i> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n            }\n        }\n\n        public readonly IEnumerable<V3i> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n                yield return C3;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M00,  M01,  M02,  M03); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n                M03 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M10,  M11,  M12,  M13); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n                M13 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M20,  M21,  M22,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n                M23 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M00,  M10,  M20); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M01,  M11,  M21); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M02,  M12,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3i C3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3i( M03,  M13,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M03 = value.X;\n                M13 = value.Y;\n                M23 = value.Z;\n            }\n        }\n\n        public readonly V3i Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3i(M00, M11, M22);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly int MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly int MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23);\n        }\n\n        public unsafe int this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe int this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[row * 4 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[row * 4 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 3;\n        public const int ColumnCount = 4;\n        public const int ElementCount = 3 * 4;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(3, 4);\n        }\n\n        public static M34i Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M34i(0);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly int Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + Fun.Abs(M03) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + Fun.Abs(M13) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22) + Fun.Abs(M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + M03 * M03 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + M13 * M13 + \n                    M20 * M20 + M21 * M21 + M22 * M22 + M23 * M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator -(M34i m)\n        {\n            return new M34i(\n                -m.M00, -m.M01, -m.M02, -m.M03, \n                -m.M10, -m.M11, -m.M12, -m.M13, \n                -m.M20, -m.M21, -m.M22, -m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  + (M34i a, M34i b)\n        {\n            return new M34i(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  + (M34i m, int s)\n        {\n            return new M34i(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  + (int s, M34i m)\n        {\n            return new M34i(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  + (M34i a, M34l b)\n        {\n            return new M34l(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  + (M34i m, long s)\n        {\n            return new M34l(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  + (long s, M34i m)\n        {\n            return new M34l(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (M34i a, M34f b)\n        {\n            return new M34f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (M34i m, float s)\n        {\n            return new M34f(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (float s, M34i m)\n        {\n            return new M34f(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (M34i a, M34d b)\n        {\n            return new M34d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (M34i m, double s)\n        {\n            return new M34d(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (double s, M34i m)\n        {\n            return new M34d(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  - (M34i a, M34i b)\n        {\n            return new M34i(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  - (M34i m, int s)\n        {\n            return new M34i(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  - (int s, M34i m)\n        {\n            return new M34i(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  - (M34i a, M34l b)\n        {\n            return new M34l(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  - (M34i m, long s)\n        {\n            return new M34l(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  - (long s, M34i m)\n        {\n            return new M34l(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (M34i a, M34f b)\n        {\n            return new M34f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (M34i m, float s)\n        {\n            return new M34f(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (float s, M34i m)\n        {\n            return new M34f(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (M34i a, M34d b)\n        {\n            return new M34d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (M34i m, double s)\n        {\n            return new M34d(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (double s, M34i m)\n        {\n            return new M34d(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  % (M34i a, M34i b)\n        {\n            return new M34i(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  % (M34i m, int s)\n        {\n            return new M34i(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  % (int s, M34i m)\n        {\n            return new M34i(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  % (M34i a, M34l b)\n        {\n            return new M34l(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  % (M34i m, long s)\n        {\n            return new M34l(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  % (long s, M34i m)\n        {\n            return new M34l(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (M34i a, M34f b)\n        {\n            return new M34f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (M34i m, float s)\n        {\n            return new M34f(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (float s, M34i m)\n        {\n            return new M34f(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (M34i a, M34d b)\n        {\n            return new M34d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (M34i m, double s)\n        {\n            return new M34d(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (double s, M34i m)\n        {\n            return new M34d(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  / (M34i a, M34i b)\n        {\n            return new M34i(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  / (M34i m, int s)\n        {\n            return new M34i(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  / (int s, M34i m)\n        {\n            return new M34i(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  / (M34i a, M34l b)\n        {\n            return new M34l(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  / (M34i m, long s)\n        {\n            return new M34l(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  / (long s, M34i m)\n        {\n            return new M34l(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (M34i a, M34f b)\n        {\n            return new M34f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (M34i m, float s)\n        {\n            return new M34f(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (float s, M34i m)\n        {\n            return new M34f(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (M34i a, M34d b)\n        {\n            return new M34d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (M34i m, double s)\n        {\n            return new M34d(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (double s, M34i m)\n        {\n            return new M34d(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  * (M34i m, int s)\n        {\n            return new M34i(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator  * (int s, M34i m)\n        {\n            return new M34i(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  * (M34i m, long s)\n        {\n            return new M34l(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  * (long s, M34i m)\n        {\n            return new M34l(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  * (M34i m, float s)\n        {\n            return new M34f(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  * (float s, M34i m)\n        {\n            return new M34f(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  * (M34i m, double s)\n        {\n            return new M34d(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  * (double s, M34i m)\n        {\n            return new M34d(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator ~(M34i m)\n        {\n            return new M34i(\n                ~m.M00, ~m.M01, ~m.M02, ~m.M03, \n                ~m.M10, ~m.M11, ~m.M12, ~m.M13, \n                ~m.M20, ~m.M21, ~m.M22, ~m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator <<(M34i a, int s)\n        {\n            return new M34i(\n                a.M00 << s, a.M01 << s, a.M02 << s, a.M03 << s, \n                a.M10 << s, a.M11 << s, a.M12 << s, a.M13 << s, \n                a.M20 << s, a.M21 << s, a.M22 << s, a.M23 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator >>(M34i a, int s)\n        {\n            return new M34i(\n                a.M00 >> s, a.M01 >> s, a.M02 >> s, a.M03 >> s, \n                a.M10 >> s, a.M11 >> s, a.M12 >> s, a.M13 >> s, \n                a.M20 >> s, a.M21 >> s, a.M22 >> s, a.M23 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator &(M34i a, M34i b)\n        {\n            return new M34i(\n                a.M00 & b.M00, a.M01 & b.M01, a.M02 & b.M02, a.M03 & b.M03, \n                a.M10 & b.M10, a.M11 & b.M11, a.M12 & b.M12, a.M13 & b.M13, \n                a.M20 & b.M20, a.M21 & b.M21, a.M22 & b.M22, a.M23 & b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator &(M34i a, int s)\n        {\n            return new M34i(\n                a.M00 & s, a.M01 & s, a.M02 & s, a.M03 & s, \n                a.M10 & s, a.M11 & s, a.M12 & s, a.M13 & s, \n                a.M20 & s, a.M21 & s, a.M22 & s, a.M23 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator &(int s, M34i a)\n        {\n            return new M34i(\n                s & a.M00, s & a.M01, s & a.M02, s & a.M03, \n                s & a.M10, s & a.M11, s & a.M12, s & a.M13, \n                s & a.M20, s & a.M21, s & a.M22, s & a.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator |(M34i a, M34i b)\n        {\n            return new M34i(\n                a.M00 | b.M00, a.M01 | b.M01, a.M02 | b.M02, a.M03 | b.M03, \n                a.M10 | b.M10, a.M11 | b.M11, a.M12 | b.M12, a.M13 | b.M13, \n                a.M20 | b.M20, a.M21 | b.M21, a.M22 | b.M22, a.M23 | b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator |(M34i a, int s)\n        {\n            return new M34i(\n                a.M00 | s, a.M01 | s, a.M02 | s, a.M03 | s, \n                a.M10 | s, a.M11 | s, a.M12 | s, a.M13 | s, \n                a.M20 | s, a.M21 | s, a.M22 | s, a.M23 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator |(int s, M34i a)\n        {\n            return new M34i(\n                s | a.M00, s | a.M01, s | a.M02, s | a.M03, \n                s | a.M10, s | a.M11, s | a.M12, s | a.M13, \n                s | a.M20, s | a.M21, s | a.M22, s | a.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator ^(M34i a, M34i b)\n        {\n            return new M34i(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, a.M02 ^ b.M02, a.M03 ^ b.M03, \n                a.M10 ^ b.M10, a.M11 ^ b.M11, a.M12 ^ b.M12, a.M13 ^ b.M13, \n                a.M20 ^ b.M20, a.M21 ^ b.M21, a.M22 ^ b.M22, a.M23 ^ b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator ^(M34i a, int s)\n        {\n            return new M34i(\n                a.M00 ^ s, a.M01 ^ s, a.M02 ^ s, a.M03 ^ s, \n                a.M10 ^ s, a.M11 ^ s, a.M12 ^ s, a.M13 ^ s, \n                a.M20 ^ s, a.M21 ^ s, a.M22 ^ s, a.M23 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i operator ^(int s, M34i a)\n        {\n            return new M34i(\n                s ^ a.M00, s ^ a.M01, s ^ a.M02, s ^ a.M03, \n                s ^ a.M10, s ^ a.M11, s ^ a.M12, s ^ a.M13, \n                s ^ a.M20, s ^ a.M21, s ^ a.M22, s ^ a.M23);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M34i matrix with a V4i column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator *(M34i m, V4i v)\n        {\n            return new V3i(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z + m.M03 * v.W, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z + m.M13 * v.W, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z + m.M23 * v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a V3i row vector with a M34i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator *(V3i v, M34i m)\n        {\n            return new V4i(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22, \n                v.X * m.M03 + v.Y * m.M13 + v.Z * m.M23);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M34i a, M34i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M34i a, int s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M03 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M13 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s && \n                a.M23 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(int s, M34i a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M03  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M13  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22  && \n                s == a.M23 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M34i a, M34i b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M34i m, int s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(int s, M34i m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02, M03),\n                        HashCode.GetCombined(M10, M11, M12, M13),\n                        HashCode.GetCombined(M20, M21, M22, M23));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M34i other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && M03.Equals(other.M03) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && M13.Equals(other.M13) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22) && M23.Equals(other.M23);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M34i o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M34i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M34i.FromRows(\n                V4i.Parse(x[0]), \n                V4i.Parse(x[1]), \n                V4i.Parse(x[2])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M34i operator *(M33i a, M34i b)\n        {\n            return new M34i(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23\n             );\n        }\n\n        public static M34i operator *(M34i a, M44i b)\n        {\n            return new M34i(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20 + a.M03 * b.M30, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21 + a.M03 * b.M31, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22 + a.M03 * b.M32, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03 * b.M33, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20 + a.M13 * b.M30, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20 + a.M23 * b.M30, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (int)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (int)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (int)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (int)value;\n        }\n\n        #endregion\n    }\n\n    public class M34iEqualityComparer : IEqualityComparer<M34i>\n    {\n        public static readonly M34iEqualityComparer Default\n            = new M34iEqualityComparer();\n\n        #region IEqualityComparer<M34i> Members\n\n        public bool Equals(M34i v0, M34i v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M34i v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M34i m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector(this M34i m)\n            => new V3d(m.C0.Length, m.C1.Length, m.C2.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Norm1(M34i m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M34i m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMax(M34i m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMin(M34i m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M34i m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M03).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M13).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p) + \n                Fun.Abs(m.M23).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static int Distance1(this M34i a, M34i b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M03 - a.M03) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M13 - a.M13) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22) + \n                Fun.Abs(b.M23 - a.M23);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M34i a, M34i b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M03 - a.M03) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M13 - a.M13) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22) + \n                        Fun.Square(b.M23 - a.M23));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M34i a, M34i b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M03 - a.M03).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M13 - a.M13).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p) + \n                Fun.Abs(b.M23 - a.M23).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMax(this M34i a, M34i b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMin(this M34i a, M34i b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Transform(this M34i m, V4i v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i TransposedTransform(this M34i m, V3i v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V3i TransformDir(this M34i m, V3i v)\n        {\n            return new V3i(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by matrix m.\n        /// </summary>\n        public static V3i TransformPos(this M34i m, V3i p)\n        {\n            return new V3i(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23\n                );\n        }\n\n        /// <summary>\n        /// Multiplies two <see cref=\"M34i\"/> matrices as 4x4 matrices.\n        /// </summary>\n        public static M34i MultiplyAffine(this M34i a, M34i b)\n        {\n            return new M34i(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4i Row(this M34i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V4i(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3i Column(this M34i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V3i(ptr[index], ptr[index + 4], ptr[index + 8]);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M34i a, M34i b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M03 < b.M03 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M13 < b.M13 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22 && \n                a.M23 < b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M34i m, int s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M03 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M13 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s && \n                m.M23 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(int s, M34i m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M03 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M13 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22 && \n                s < m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M34i a, M34i b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M03 < b.M03 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M13 < b.M13 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22 || \n                a.M23 < b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M34i m, int s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M03 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M13 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s || \n                m.M23 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(int s, M34i m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M03 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M13 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22 || \n                s < m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M34i a, M34i b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M03 > b.M03 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M13 > b.M13 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22 && \n                a.M23 > b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M34i m, int s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M03 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M13 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s && \n                m.M23 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(int s, M34i m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M03 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M13 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22 && \n                s > m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M34i a, M34i b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M03 > b.M03 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M13 > b.M13 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22 || \n                a.M23 > b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M34i m, int s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M03 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M13 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s || \n                m.M23 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(int s, M34i m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M03 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M13 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22 || \n                s > m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M34i a, M34i b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M03 <= b.M03 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M13 <= b.M13 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22 && \n                a.M23 <= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M34i m, int s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M03 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M13 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s && \n                m.M23 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(int s, M34i m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M03 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M13 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22 && \n                s <= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M34i a, M34i b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M03 <= b.M03 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M13 <= b.M13 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22 || \n                a.M23 <= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M34i m, int s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M03 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M13 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s || \n                m.M23 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(int s, M34i m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M03 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M13 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22 || \n                s <= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M34i a, M34i b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M03 >= b.M03 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M13 >= b.M13 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22 && \n                a.M23 >= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M34i m, int s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M03 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M13 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s && \n                m.M23 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(int s, M34i m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M03 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M13 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22 && \n                s >= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M34i a, M34i b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M03 >= b.M03 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M13 >= b.M13 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22 || \n                a.M23 >= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M34i m, int s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M03 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M13 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s || \n                m.M23 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(int s, M34i m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M03 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M13 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22 || \n                s >= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M34i a, M34i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M34i m, int s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M03 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M13 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s && \n                m.M23 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(int s, M34i m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M03 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M13 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22 && \n                s == m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M34i a, M34i b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M03 == b.M03 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M13 == b.M13 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22 || \n                a.M23 == b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M34i m, int s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M03 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M13 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s || \n                m.M23 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(int s, M34i m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M03 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M13 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22 || \n                s == m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M34i a, M34i b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M03 != b.M03 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M13 != b.M13 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22 && \n                a.M23 != b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M34i m, int s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M03 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M13 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s && \n                m.M23 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(int s, M34i m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M03 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M13 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22 && \n                s != m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M34i a, M34i b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M03 != b.M03 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M13 != b.M13 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22 || \n                a.M23 != b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M34i m, int s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M03 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M13 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s || \n                m.M23 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(int s, M34i m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M03 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M13 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22 || \n                s != m.M23;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M34i m0, M34i m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M03 < m1.M03) return -1;\n            if (m0.M03 > m1.M03) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M13 < m1.M13) return -1;\n            if (m0.M13 > m1.M13) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            if (m0.M23 < m1.M23) return -1;\n            if (m0.M23 > m1.M23) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M34i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MinElement(M34i m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M34i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MaxElement(M34i m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M34i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M34i m, int epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M03.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M13.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon) || m.M23.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M34i m, int epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M03.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M13.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon) && m.M23.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M34i a, M34i b, int epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M34i m, int epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM34iExtensions\n    {\n        #region IRandomUniform extensions for M34i\n\n        /// <summary>\n        /// Uses UniformInt() to generate the elements of an M34i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i UniformM34i(this IRandomUniform rnd)\n        {\n            return new M34i(\n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt());\n        }\n\n        /// <summary>\n        /// Uses UniformIntNonZero() to generate the elements of an M34i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i UniformM34iNonZero(this IRandomUniform rnd)\n        {\n            return new M34i(\n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M34i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i UniformM34i(this IRandomUniform rnd, int size)\n        {\n            return new M34i(\n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size));\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M34i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34i UniformM34i(this IRandomUniform rnd, M34i size)\n        {\n            return new M34i(\n                rnd.UniformInt(size.M00), rnd.UniformInt(size.M01), rnd.UniformInt(size.M02), rnd.UniformInt(size.M03), \n                rnd.UniformInt(size.M10), rnd.UniformInt(size.M11), rnd.UniformInt(size.M12), rnd.UniformInt(size.M13), \n                rnd.UniformInt(size.M20), rnd.UniformInt(size.M21), rnd.UniformInt(size.M22), rnd.UniformInt(size.M23));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M34l\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M34l : IEquatable<M34l>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public long M00, M01, M02, M03;\n        [DataMember]\n        public long M10, M11, M12, M13;\n        [DataMember]\n        public long M20, M21, M22, M23;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(long value)\n        {\n            M00 = value; M01 = 0; M02 = 0; M03 = 0; \n            M10 = 0; M11 = value; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = value; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(\n                long m00, long m01, long m02, long m03, \n                long m10, long m11, long m12, long m13, \n                long m20, long m21, long m22, long m23)\n        {\n            M00 = m00; M01 = m01; M02 = m02; M03 = m03; \n            M10 = m10; M11 = m11; M12 = m12; M13 = m13; \n            M20 = m20; M21 = m21; M22 = m22; M23 = m23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(long[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M03 = a[3];\n            M10 = a[4];\n            M11 = a[5];\n            M12 = a[6];\n            M13 = a[7];\n            M20 = a[8];\n            M21 = a[9];\n            M22 = a[10];\n            M23 = a[11];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(long[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M03 = a[start + 3];\n            M10 = a[start + 4];\n            M11 = a[start + 5];\n            M12 = a[start + 6];\n            M13 = a[start + 7];\n            M20 = a[start + 8];\n            M21 = a[start + 9];\n            M22 = a[start + 10];\n            M23 = a[start + 11];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M33l m, V3l v)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = v.X; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = v.Y; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = v.Z; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M22i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M23i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M33i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M34i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M44i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M22l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M23l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M33l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M44l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = m.M03; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = m.M13; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M22f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M23f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M33f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M34f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M44f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M22d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M23d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M33d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M34d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34l(M44d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M34l(M22i m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M23i m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M33i m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M34i m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n            };\n        }\n\n        public static explicit operator M34l(M44i m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n            };\n        }\n\n        public static explicit operator M34l(M22l m)\n        {\n            return new M34l {\n                M00 = m.M00, M01 = m.M01, M02 = 0, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M23l m)\n        {\n            return new M34l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M33l m)\n        {\n            return new M34l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M44l m)\n        {\n            return new M34l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = m.M03, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = m.M13, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = m.M23, \n            };\n        }\n\n        public static explicit operator M34l(M22f m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M23f m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M33f m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M34f m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n            };\n        }\n\n        public static explicit operator M34l(M44f m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n            };\n        }\n\n        public static explicit operator M34l(M22d m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M23d m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M33d m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34l(M34d m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n            };\n        }\n\n        public static explicit operator M34l(M44d m)\n        {\n            return new M34l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n            };\n        }\n\n        public static explicit operator M34l(int[] a)\n        {\n            return new M34l(\n                (long)a[0], (long)a[1], (long)a[2], (long)a[3], \n                (long)a[4], (long)a[5], (long)a[6], (long)a[7], \n                (long)a[8], (long)a[9], (long)a[10], (long)a[11]);\n        }\n\n        public static explicit operator M34l(int[,] a)\n        {\n            return new M34l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], (long)a[0, 3], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], (long)a[1, 3], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2], (long)a[2, 3]);\n        }\n\n        public static explicit operator int[](M34l m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03, \n                (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13, \n                (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23\n            };\n        }\n\n        public static explicit operator int[,](M34l m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M03;\n            array[index + 4] = (int)M10;\n            array[index + 5] = (int)M11;\n            array[index + 6] = (int)M12;\n            array[index + 7] = (int)M13;\n            array[index + 8] = (int)M20;\n            array[index + 9] = (int)M21;\n            array[index + 10] = (int)M22;\n            array[index + 11] = (int)M23;\n        }\n\n        public static explicit operator M34l(long[] a)\n        {\n            return new M34l(\n                a[0], a[1], a[2], a[3], \n                a[4], a[5], a[6], a[7], \n                a[8], a[9], a[10], a[11]);\n        }\n\n        public static explicit operator M34l(long[,] a)\n        {\n            return new M34l(\n                a[0, 0], a[0, 1], a[0, 2], a[0, 3], \n                a[1, 0], a[1, 1], a[1, 2], a[1, 3], \n                a[2, 0], a[2, 1], a[2, 2], a[2, 3]);\n        }\n\n        public static explicit operator long[](M34l m)\n        {\n            return new long[] {\n                m.M00, m.M01, m.M02, m.M03, \n                m.M10, m.M11, m.M12, m.M13, \n                m.M20, m.M21, m.M22, m.M23\n            };\n        }\n\n        public static explicit operator long[,](M34l m)\n        {\n            return new long[,] {\n                { m.M00, m.M01, m.M02, m.M03 }, \n                { m.M10, m.M11, m.M12, m.M13 }, \n                { m.M20, m.M21, m.M22, m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M03;\n            array[index + 4] = M10;\n            array[index + 5] = M11;\n            array[index + 6] = M12;\n            array[index + 7] = M13;\n            array[index + 8] = M20;\n            array[index + 9] = M21;\n            array[index + 10] = M22;\n            array[index + 11] = M23;\n        }\n\n        public static explicit operator M34l(float[] a)\n        {\n            return new M34l(\n                (long)a[0], (long)a[1], (long)a[2], (long)a[3], \n                (long)a[4], (long)a[5], (long)a[6], (long)a[7], \n                (long)a[8], (long)a[9], (long)a[10], (long)a[11]);\n        }\n\n        public static explicit operator M34l(float[,] a)\n        {\n            return new M34l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], (long)a[0, 3], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], (long)a[1, 3], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2], (long)a[2, 3]);\n        }\n\n        public static explicit operator float[](M34l m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03, \n                (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13, \n                (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23\n            };\n        }\n\n        public static explicit operator float[,](M34l m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M03;\n            array[index + 4] = (float)M10;\n            array[index + 5] = (float)M11;\n            array[index + 6] = (float)M12;\n            array[index + 7] = (float)M13;\n            array[index + 8] = (float)M20;\n            array[index + 9] = (float)M21;\n            array[index + 10] = (float)M22;\n            array[index + 11] = (float)M23;\n        }\n\n        public static explicit operator M34l(double[] a)\n        {\n            return new M34l(\n                (long)a[0], (long)a[1], (long)a[2], (long)a[3], \n                (long)a[4], (long)a[5], (long)a[6], (long)a[7], \n                (long)a[8], (long)a[9], (long)a[10], (long)a[11]);\n        }\n\n        public static explicit operator M34l(double[,] a)\n        {\n            return new M34l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], (long)a[0, 3], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], (long)a[1, 3], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2], (long)a[2, 3]);\n        }\n\n        public static explicit operator double[](M34l m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03, \n                (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13, \n                (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23\n            };\n        }\n\n        public static explicit operator double[,](M34l m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M03;\n            array[index + 4] = (double)M10;\n            array[index + 5] = (double)M11;\n            array[index + 6] = (double)M12;\n            array[index + 7] = (double)M13;\n            array[index + 8] = (double)M20;\n            array[index + 9] = (double)M21;\n            array[index + 10] = (double)M22;\n            array[index + 11] = (double)M23;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34i Copy(Func<long, int> element_fun)\n        {\n            return new M34i(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34i Copy(Func<long, int, int, int> element_index0_index1_fun)\n        {\n            return new M34i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34l Copy(Func<long, long> element_fun)\n        {\n            return new M34l(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34l Copy(Func<long, int, int, long> element_index0_index1_fun)\n        {\n            return new M34l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34f Copy(Func<long, float> element_fun)\n        {\n            return new M34f(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34f Copy(Func<long, int, int, float> element_index0_index1_fun)\n        {\n            return new M34f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34d Copy(Func<long, double> element_fun)\n        {\n            return new M34d(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34d Copy(Func<long, int, int, double> element_index0_index1_fun)\n        {\n            return new M34d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        public readonly long[] ToArray()\n        {\n            var array = new long[12];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M03;\n            array[4] = M10;\n            array[5] = M11;\n            array[6] = M12;\n            array[7] = M13;\n            array[8] = M20;\n            array[9] = M21;\n            array[10] = M22;\n            array[11] = M23;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l FromCols(V3l col0, V3l col1, V3l col2, V3l col3)\n        {\n            return new M34l(\n                col0.X, col1.X, col2.X, col3.X, \n                col0.Y, col1.Y, col2.Y, col3.Y, \n                col0.Z, col1.Z, col2.Z, col3.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l FromRows(V4l row0, V4l row1, V4l row2)\n        {\n            return new M34l(\n                row0.X, row0.Y, row0.Z, row0.W, \n                row1.X, row1.Y, row1.Z, row1.W, \n                row2.X, row2.Y, row2.Z, row2.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l FromDiagonal(long value)\n        {\n            return new M34l(\n                value, 0, 0, 0, \n                0, value, 0, 0, \n                0, 0, value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l FromDiagonal(long m00, long m11, long m22)\n        {\n            return new M34l(\n                m00, 0, 0, 0, \n                0, m11, 0, 0, \n                0, 0, m22, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l FromDiagonal(V3l s)\n        {\n            return new M34l(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M34l\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l Scale(long s)\n        {\n            return new M34l(\n                s, 0, 0, 0, \n                0, s, 0, 0, \n                0, 0, s, 0);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34l\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l Scale(long sX, long sY, long sZ)\n        {\n            return new M34l(\n                sX, 0, 0, 0, \n                0, sY, 0, 0, \n                0, 0, sZ, 0);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34l\"/> using a <see cref=\"V3l\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l Scale(V3l s)\n        {\n            return new M34l(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34l\"/> with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l Translation(long tX, long tY, long tZ)\n        {\n            return new M34l(\n                1, 0, 0, tX, \n                0, 1, 0, tY, \n                0, 0, 1, tZ);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34l\"/> with the translational component given by a <see cref=\"V3l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l Translation(V3l t)\n        {\n            return new M34l(\n                1, 0, 0, t.X, \n                0, 1, 0, t.Y, \n                0, 0, 1, t.Z);\n        }\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l ShearXY(long factorX, long factorY)\n        {\n            return new M34l(\n                1, 0, factorX, 0, \n                0, 1, factorY, 0, \n                0, 0, 1, 0);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l ShearXZ(long factorX, long factorZ)\n        {\n            return new M34l(\n                1, factorX, 0, 0, \n                0, 1, 0, 0, \n                0, factorZ, 1, 0);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l ShearYZ(long factorY, long factorZ)\n        {\n            return new M34l(\n                1, 0, 0, 0, \n                factorY, 1, 0, 0, \n                factorZ, 0, 1, 0);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l DivideByInt(M34l m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M03;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M13;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n                yield return M23;\n            }\n        }\n\n        public readonly IEnumerable<V4l> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n            }\n        }\n\n        public readonly IEnumerable<V3l> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n                yield return C3;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M00,  M01,  M02,  M03); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n                M03 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M10,  M11,  M12,  M13); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n                M13 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M20,  M21,  M22,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n                M23 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M00,  M10,  M20); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M01,  M11,  M21); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M02,  M12,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3l C3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3l( M03,  M13,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M03 = value.X;\n                M13 = value.Y;\n                M23 = value.Z;\n            }\n        }\n\n        public readonly V3l Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3l(M00, M11, M22);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly long MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly long MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23);\n        }\n\n        public unsafe long this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe long this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[row * 4 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[row * 4 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 3;\n        public const int ColumnCount = 4;\n        public const int ElementCount = 3 * 4;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(3, 4);\n        }\n\n        public static M34l Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M34l(0);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly long Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + Fun.Abs(M03) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + Fun.Abs(M13) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22) + Fun.Abs(M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + M03 * M03 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + M13 * M13 + \n                    M20 * M20 + M21 * M21 + M22 * M22 + M23 * M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator -(M34l m)\n        {\n            return new M34l(\n                -m.M00, -m.M01, -m.M02, -m.M03, \n                -m.M10, -m.M11, -m.M12, -m.M13, \n                -m.M20, -m.M21, -m.M22, -m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  + (M34l a, M34l b)\n        {\n            return new M34l(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  + (M34l m, long s)\n        {\n            return new M34l(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  + (long s, M34l m)\n        {\n            return new M34l(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (M34l a, M34f b)\n        {\n            return new M34f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (M34l m, float s)\n        {\n            return new M34f(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (float s, M34l m)\n        {\n            return new M34f(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (M34l a, M34d b)\n        {\n            return new M34d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (M34l m, double s)\n        {\n            return new M34d(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (double s, M34l m)\n        {\n            return new M34d(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  - (M34l a, M34l b)\n        {\n            return new M34l(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  - (M34l m, long s)\n        {\n            return new M34l(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  - (long s, M34l m)\n        {\n            return new M34l(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (M34l a, M34f b)\n        {\n            return new M34f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (M34l m, float s)\n        {\n            return new M34f(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (float s, M34l m)\n        {\n            return new M34f(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (M34l a, M34d b)\n        {\n            return new M34d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (M34l m, double s)\n        {\n            return new M34d(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (double s, M34l m)\n        {\n            return new M34d(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  % (M34l a, M34l b)\n        {\n            return new M34l(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  % (M34l m, long s)\n        {\n            return new M34l(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  % (long s, M34l m)\n        {\n            return new M34l(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (M34l a, M34f b)\n        {\n            return new M34f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (M34l m, float s)\n        {\n            return new M34f(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (float s, M34l m)\n        {\n            return new M34f(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (M34l a, M34d b)\n        {\n            return new M34d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (M34l m, double s)\n        {\n            return new M34d(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (double s, M34l m)\n        {\n            return new M34d(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  / (M34l a, M34l b)\n        {\n            return new M34l(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  / (M34l m, long s)\n        {\n            return new M34l(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  / (long s, M34l m)\n        {\n            return new M34l(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (M34l a, M34f b)\n        {\n            return new M34f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (M34l m, float s)\n        {\n            return new M34f(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (float s, M34l m)\n        {\n            return new M34f(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (M34l a, M34d b)\n        {\n            return new M34d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (M34l m, double s)\n        {\n            return new M34d(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (double s, M34l m)\n        {\n            return new M34d(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  * (M34l m, long s)\n        {\n            return new M34l(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator  * (long s, M34l m)\n        {\n            return new M34l(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  * (M34l m, float s)\n        {\n            return new M34f(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  * (float s, M34l m)\n        {\n            return new M34f(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  * (M34l m, double s)\n        {\n            return new M34d(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  * (double s, M34l m)\n        {\n            return new M34d(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator ~(M34l m)\n        {\n            return new M34l(\n                ~m.M00, ~m.M01, ~m.M02, ~m.M03, \n                ~m.M10, ~m.M11, ~m.M12, ~m.M13, \n                ~m.M20, ~m.M21, ~m.M22, ~m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator <<(M34l a, int s)\n        {\n            return new M34l(\n                a.M00 << s, a.M01 << s, a.M02 << s, a.M03 << s, \n                a.M10 << s, a.M11 << s, a.M12 << s, a.M13 << s, \n                a.M20 << s, a.M21 << s, a.M22 << s, a.M23 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator >>(M34l a, int s)\n        {\n            return new M34l(\n                a.M00 >> s, a.M01 >> s, a.M02 >> s, a.M03 >> s, \n                a.M10 >> s, a.M11 >> s, a.M12 >> s, a.M13 >> s, \n                a.M20 >> s, a.M21 >> s, a.M22 >> s, a.M23 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator &(M34l a, M34l b)\n        {\n            return new M34l(\n                a.M00 & b.M00, a.M01 & b.M01, a.M02 & b.M02, a.M03 & b.M03, \n                a.M10 & b.M10, a.M11 & b.M11, a.M12 & b.M12, a.M13 & b.M13, \n                a.M20 & b.M20, a.M21 & b.M21, a.M22 & b.M22, a.M23 & b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator &(M34l a, long s)\n        {\n            return new M34l(\n                a.M00 & s, a.M01 & s, a.M02 & s, a.M03 & s, \n                a.M10 & s, a.M11 & s, a.M12 & s, a.M13 & s, \n                a.M20 & s, a.M21 & s, a.M22 & s, a.M23 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator &(long s, M34l a)\n        {\n            return new M34l(\n                s & a.M00, s & a.M01, s & a.M02, s & a.M03, \n                s & a.M10, s & a.M11, s & a.M12, s & a.M13, \n                s & a.M20, s & a.M21, s & a.M22, s & a.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator |(M34l a, M34l b)\n        {\n            return new M34l(\n                a.M00 | b.M00, a.M01 | b.M01, a.M02 | b.M02, a.M03 | b.M03, \n                a.M10 | b.M10, a.M11 | b.M11, a.M12 | b.M12, a.M13 | b.M13, \n                a.M20 | b.M20, a.M21 | b.M21, a.M22 | b.M22, a.M23 | b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator |(M34l a, long s)\n        {\n            return new M34l(\n                a.M00 | s, a.M01 | s, a.M02 | s, a.M03 | s, \n                a.M10 | s, a.M11 | s, a.M12 | s, a.M13 | s, \n                a.M20 | s, a.M21 | s, a.M22 | s, a.M23 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator |(long s, M34l a)\n        {\n            return new M34l(\n                s | a.M00, s | a.M01, s | a.M02, s | a.M03, \n                s | a.M10, s | a.M11, s | a.M12, s | a.M13, \n                s | a.M20, s | a.M21, s | a.M22, s | a.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator ^(M34l a, M34l b)\n        {\n            return new M34l(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, a.M02 ^ b.M02, a.M03 ^ b.M03, \n                a.M10 ^ b.M10, a.M11 ^ b.M11, a.M12 ^ b.M12, a.M13 ^ b.M13, \n                a.M20 ^ b.M20, a.M21 ^ b.M21, a.M22 ^ b.M22, a.M23 ^ b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator ^(M34l a, long s)\n        {\n            return new M34l(\n                a.M00 ^ s, a.M01 ^ s, a.M02 ^ s, a.M03 ^ s, \n                a.M10 ^ s, a.M11 ^ s, a.M12 ^ s, a.M13 ^ s, \n                a.M20 ^ s, a.M21 ^ s, a.M22 ^ s, a.M23 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l operator ^(long s, M34l a)\n        {\n            return new M34l(\n                s ^ a.M00, s ^ a.M01, s ^ a.M02, s ^ a.M03, \n                s ^ a.M10, s ^ a.M11, s ^ a.M12, s ^ a.M13, \n                s ^ a.M20, s ^ a.M21, s ^ a.M22, s ^ a.M23);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M34l matrix with a V4l column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator *(M34l m, V4l v)\n        {\n            return new V3l(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z + m.M03 * v.W, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z + m.M13 * v.W, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z + m.M23 * v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a V3l row vector with a M34l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator *(V3l v, M34l m)\n        {\n            return new V4l(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22, \n                v.X * m.M03 + v.Y * m.M13 + v.Z * m.M23);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M34l a, M34l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M34l a, long s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M03 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M13 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s && \n                a.M23 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(long s, M34l a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M03  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M13  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22  && \n                s == a.M23 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M34l a, M34l b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M34l m, long s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(long s, M34l m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02, M03),\n                        HashCode.GetCombined(M10, M11, M12, M13),\n                        HashCode.GetCombined(M20, M21, M22, M23));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M34l other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && M03.Equals(other.M03) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && M13.Equals(other.M13) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22) && M23.Equals(other.M23);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M34l o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M34l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M34l.FromRows(\n                V4l.Parse(x[0]), \n                V4l.Parse(x[1]), \n                V4l.Parse(x[2])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M34l operator *(M33l a, M34l b)\n        {\n            return new M34l(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23\n             );\n        }\n\n        public static M34l operator *(M34l a, M44l b)\n        {\n            return new M34l(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20 + a.M03 * b.M30, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21 + a.M03 * b.M31, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22 + a.M03 * b.M32, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03 * b.M33, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20 + a.M13 * b.M30, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20 + a.M23 * b.M30, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (long)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (long)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (long)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (long)value;\n        }\n\n        #endregion\n    }\n\n    public class M34lEqualityComparer : IEqualityComparer<M34l>\n    {\n        public static readonly M34lEqualityComparer Default\n            = new M34lEqualityComparer();\n\n        #region IEqualityComparer<M34l> Members\n\n        public bool Equals(M34l v0, M34l v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M34l v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M34l m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector(this M34l m)\n            => new V3d(m.C0.Length, m.C1.Length, m.C2.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Norm1(M34l m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M34l m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMax(M34l m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMin(M34l m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M34l m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M03).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M13).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p) + \n                Fun.Abs(m.M23).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static long Distance1(this M34l a, M34l b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M03 - a.M03) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M13 - a.M13) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22) + \n                Fun.Abs(b.M23 - a.M23);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M34l a, M34l b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M03 - a.M03) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M13 - a.M13) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22) + \n                        Fun.Square(b.M23 - a.M23));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M34l a, M34l b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M03 - a.M03).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M13 - a.M13).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p) + \n                Fun.Abs(b.M23 - a.M23).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMax(this M34l a, M34l b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMin(this M34l a, M34l b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Transform(this M34l m, V4l v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l TransposedTransform(this M34l m, V3l v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V3l TransformDir(this M34l m, V3l v)\n        {\n            return new V3l(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by matrix m.\n        /// </summary>\n        public static V3l TransformPos(this M34l m, V3l p)\n        {\n            return new V3l(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23\n                );\n        }\n\n        /// <summary>\n        /// Multiplies two <see cref=\"M34l\"/> matrices as 4x4 matrices.\n        /// </summary>\n        public static M34l MultiplyAffine(this M34l a, M34l b)\n        {\n            return new M34l(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4l Row(this M34l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V4l(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3l Column(this M34l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V3l(ptr[index], ptr[index + 4], ptr[index + 8]);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M34l a, M34l b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M03 < b.M03 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M13 < b.M13 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22 && \n                a.M23 < b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M34l m, long s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M03 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M13 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s && \n                m.M23 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(long s, M34l m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M03 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M13 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22 && \n                s < m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M34l a, M34l b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M03 < b.M03 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M13 < b.M13 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22 || \n                a.M23 < b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M34l m, long s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M03 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M13 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s || \n                m.M23 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(long s, M34l m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M03 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M13 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22 || \n                s < m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M34l a, M34l b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M03 > b.M03 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M13 > b.M13 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22 && \n                a.M23 > b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M34l m, long s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M03 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M13 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s && \n                m.M23 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(long s, M34l m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M03 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M13 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22 && \n                s > m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M34l a, M34l b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M03 > b.M03 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M13 > b.M13 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22 || \n                a.M23 > b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M34l m, long s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M03 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M13 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s || \n                m.M23 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(long s, M34l m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M03 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M13 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22 || \n                s > m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M34l a, M34l b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M03 <= b.M03 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M13 <= b.M13 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22 && \n                a.M23 <= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M34l m, long s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M03 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M13 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s && \n                m.M23 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(long s, M34l m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M03 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M13 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22 && \n                s <= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M34l a, M34l b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M03 <= b.M03 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M13 <= b.M13 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22 || \n                a.M23 <= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M34l m, long s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M03 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M13 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s || \n                m.M23 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(long s, M34l m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M03 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M13 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22 || \n                s <= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M34l a, M34l b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M03 >= b.M03 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M13 >= b.M13 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22 && \n                a.M23 >= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M34l m, long s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M03 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M13 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s && \n                m.M23 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(long s, M34l m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M03 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M13 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22 && \n                s >= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M34l a, M34l b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M03 >= b.M03 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M13 >= b.M13 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22 || \n                a.M23 >= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M34l m, long s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M03 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M13 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s || \n                m.M23 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(long s, M34l m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M03 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M13 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22 || \n                s >= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M34l a, M34l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M34l m, long s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M03 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M13 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s && \n                m.M23 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(long s, M34l m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M03 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M13 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22 && \n                s == m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M34l a, M34l b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M03 == b.M03 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M13 == b.M13 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22 || \n                a.M23 == b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M34l m, long s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M03 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M13 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s || \n                m.M23 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(long s, M34l m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M03 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M13 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22 || \n                s == m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M34l a, M34l b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M03 != b.M03 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M13 != b.M13 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22 && \n                a.M23 != b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M34l m, long s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M03 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M13 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s && \n                m.M23 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(long s, M34l m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M03 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M13 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22 && \n                s != m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M34l a, M34l b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M03 != b.M03 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M13 != b.M13 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22 || \n                a.M23 != b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M34l m, long s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M03 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M13 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s || \n                m.M23 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(long s, M34l m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M03 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M13 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22 || \n                s != m.M23;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M34l m0, M34l m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M03 < m1.M03) return -1;\n            if (m0.M03 > m1.M03) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M13 < m1.M13) return -1;\n            if (m0.M13 > m1.M13) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            if (m0.M23 < m1.M23) return -1;\n            if (m0.M23 > m1.M23) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M34l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MinElement(M34l m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M34l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MaxElement(M34l m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M34l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M34l m, long epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M03.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M13.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon) || m.M23.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M34l m, long epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M03.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M13.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon) && m.M23.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M34l a, M34l b, long epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M34l m, long epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM34lExtensions\n    {\n        #region IRandomUniform extensions for M34l\n\n        /// <summary>\n        /// Uses UniformLong() to generate the elements of an M34l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l UniformM34l(this IRandomUniform rnd)\n        {\n            return new M34l(\n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong());\n        }\n\n        /// <summary>\n        /// Uses UniformLongNonZero() to generate the elements of an M34l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l UniformM34lNonZero(this IRandomUniform rnd)\n        {\n            return new M34l(\n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M34l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l UniformM34l(this IRandomUniform rnd, long size)\n        {\n            return new M34l(\n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size));\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M34l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34l UniformM34l(this IRandomUniform rnd, M34l size)\n        {\n            return new M34l(\n                rnd.UniformLong(size.M00), rnd.UniformLong(size.M01), rnd.UniformLong(size.M02), rnd.UniformLong(size.M03), \n                rnd.UniformLong(size.M10), rnd.UniformLong(size.M11), rnd.UniformLong(size.M12), rnd.UniformLong(size.M13), \n                rnd.UniformLong(size.M20), rnd.UniformLong(size.M21), rnd.UniformLong(size.M22), rnd.UniformLong(size.M23));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M34f\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M34f : IEquatable<M34f>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public float M00, M01, M02, M03;\n        [DataMember]\n        public float M10, M11, M12, M13;\n        [DataMember]\n        public float M20, M21, M22, M23;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(float value)\n        {\n            M00 = value; M01 = 0; M02 = 0; M03 = 0; \n            M10 = 0; M11 = value; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = value; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(\n                float m00, float m01, float m02, float m03, \n                float m10, float m11, float m12, float m13, \n                float m20, float m21, float m22, float m23)\n        {\n            M00 = m00; M01 = m01; M02 = m02; M03 = m03; \n            M10 = m10; M11 = m11; M12 = m12; M13 = m13; \n            M20 = m20; M21 = m21; M22 = m22; M23 = m23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(float[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M03 = a[3];\n            M10 = a[4];\n            M11 = a[5];\n            M12 = a[6];\n            M13 = a[7];\n            M20 = a[8];\n            M21 = a[9];\n            M22 = a[10];\n            M23 = a[11];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(float[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M03 = a[start + 3];\n            M10 = a[start + 4];\n            M11 = a[start + 5];\n            M12 = a[start + 6];\n            M13 = a[start + 7];\n            M20 = a[start + 8];\n            M21 = a[start + 9];\n            M22 = a[start + 10];\n            M23 = a[start + 11];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M33f m, V3f v)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = v.X; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = v.Y; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = v.Z; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M22i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M23i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M33i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M34i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M44i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M22l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M23l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M33l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M34l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M44l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M22f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M23f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M33f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M44f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = m.M03; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = m.M13; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M22d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M23d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M33d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M34d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34f(M44d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M34f(M22i m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M23i m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M33i m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M34i m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n            };\n        }\n\n        public static explicit operator M34f(M44i m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n            };\n        }\n\n        public static explicit operator M34f(M22l m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M23l m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M33l m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M34l m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n            };\n        }\n\n        public static explicit operator M34f(M44l m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n            };\n        }\n\n        public static explicit operator M34f(M22f m)\n        {\n            return new M34f {\n                M00 = m.M00, M01 = m.M01, M02 = 0, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M23f m)\n        {\n            return new M34f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M33f m)\n        {\n            return new M34f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M44f m)\n        {\n            return new M34f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = m.M03, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = m.M13, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = m.M23, \n            };\n        }\n\n        public static explicit operator M34f(M22d m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M23d m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M33d m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34f(M34d m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n            };\n        }\n\n        public static explicit operator M34f(M44d m)\n        {\n            return new M34f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n            };\n        }\n\n        public static explicit operator M34f(int[] a)\n        {\n            return new M34f(\n                (float)a[0], (float)a[1], (float)a[2], (float)a[3], \n                (float)a[4], (float)a[5], (float)a[6], (float)a[7], \n                (float)a[8], (float)a[9], (float)a[10], (float)a[11]);\n        }\n\n        public static explicit operator M34f(int[,] a)\n        {\n            return new M34f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], (float)a[0, 3], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], (float)a[1, 3], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2], (float)a[2, 3]);\n        }\n\n        public static explicit operator int[](M34f m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03, \n                (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13, \n                (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23\n            };\n        }\n\n        public static explicit operator int[,](M34f m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M03;\n            array[index + 4] = (int)M10;\n            array[index + 5] = (int)M11;\n            array[index + 6] = (int)M12;\n            array[index + 7] = (int)M13;\n            array[index + 8] = (int)M20;\n            array[index + 9] = (int)M21;\n            array[index + 10] = (int)M22;\n            array[index + 11] = (int)M23;\n        }\n\n        public static explicit operator M34f(long[] a)\n        {\n            return new M34f(\n                (float)a[0], (float)a[1], (float)a[2], (float)a[3], \n                (float)a[4], (float)a[5], (float)a[6], (float)a[7], \n                (float)a[8], (float)a[9], (float)a[10], (float)a[11]);\n        }\n\n        public static explicit operator M34f(long[,] a)\n        {\n            return new M34f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], (float)a[0, 3], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], (float)a[1, 3], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2], (float)a[2, 3]);\n        }\n\n        public static explicit operator long[](M34f m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03, \n                (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13, \n                (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23\n            };\n        }\n\n        public static explicit operator long[,](M34f m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M03;\n            array[index + 4] = (long)M10;\n            array[index + 5] = (long)M11;\n            array[index + 6] = (long)M12;\n            array[index + 7] = (long)M13;\n            array[index + 8] = (long)M20;\n            array[index + 9] = (long)M21;\n            array[index + 10] = (long)M22;\n            array[index + 11] = (long)M23;\n        }\n\n        public static explicit operator M34f(float[] a)\n        {\n            return new M34f(\n                a[0], a[1], a[2], a[3], \n                a[4], a[5], a[6], a[7], \n                a[8], a[9], a[10], a[11]);\n        }\n\n        public static explicit operator M34f(float[,] a)\n        {\n            return new M34f(\n                a[0, 0], a[0, 1], a[0, 2], a[0, 3], \n                a[1, 0], a[1, 1], a[1, 2], a[1, 3], \n                a[2, 0], a[2, 1], a[2, 2], a[2, 3]);\n        }\n\n        public static explicit operator float[](M34f m)\n        {\n            return new float[] {\n                m.M00, m.M01, m.M02, m.M03, \n                m.M10, m.M11, m.M12, m.M13, \n                m.M20, m.M21, m.M22, m.M23\n            };\n        }\n\n        public static explicit operator float[,](M34f m)\n        {\n            return new float[,] {\n                { m.M00, m.M01, m.M02, m.M03 }, \n                { m.M10, m.M11, m.M12, m.M13 }, \n                { m.M20, m.M21, m.M22, m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M03;\n            array[index + 4] = M10;\n            array[index + 5] = M11;\n            array[index + 6] = M12;\n            array[index + 7] = M13;\n            array[index + 8] = M20;\n            array[index + 9] = M21;\n            array[index + 10] = M22;\n            array[index + 11] = M23;\n        }\n\n        public static explicit operator M34f(double[] a)\n        {\n            return new M34f(\n                (float)a[0], (float)a[1], (float)a[2], (float)a[3], \n                (float)a[4], (float)a[5], (float)a[6], (float)a[7], \n                (float)a[8], (float)a[9], (float)a[10], (float)a[11]);\n        }\n\n        public static explicit operator M34f(double[,] a)\n        {\n            return new M34f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], (float)a[0, 3], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], (float)a[1, 3], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2], (float)a[2, 3]);\n        }\n\n        public static explicit operator double[](M34f m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03, \n                (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13, \n                (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23\n            };\n        }\n\n        public static explicit operator double[,](M34f m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M03;\n            array[index + 4] = (double)M10;\n            array[index + 5] = (double)M11;\n            array[index + 6] = (double)M12;\n            array[index + 7] = (double)M13;\n            array[index + 8] = (double)M20;\n            array[index + 9] = (double)M21;\n            array[index + 10] = (double)M22;\n            array[index + 11] = (double)M23;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34i Copy(Func<float, int> element_fun)\n        {\n            return new M34i(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34i Copy(Func<float, int, int, int> element_index0_index1_fun)\n        {\n            return new M34i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34l Copy(Func<float, long> element_fun)\n        {\n            return new M34l(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34l Copy(Func<float, int, int, long> element_index0_index1_fun)\n        {\n            return new M34l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34f Copy(Func<float, float> element_fun)\n        {\n            return new M34f(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34f Copy(Func<float, int, int, float> element_index0_index1_fun)\n        {\n            return new M34f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34d Copy(Func<float, double> element_fun)\n        {\n            return new M34d(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34d Copy(Func<float, int, int, double> element_index0_index1_fun)\n        {\n            return new M34d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        public readonly float[] ToArray()\n        {\n            var array = new float[12];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M03;\n            array[4] = M10;\n            array[5] = M11;\n            array[6] = M12;\n            array[7] = M13;\n            array[8] = M20;\n            array[9] = M21;\n            array[10] = M22;\n            array[11] = M23;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f FromCols(V3f col0, V3f col1, V3f col2, V3f col3)\n        {\n            return new M34f(\n                col0.X, col1.X, col2.X, col3.X, \n                col0.Y, col1.Y, col2.Y, col3.Y, \n                col0.Z, col1.Z, col2.Z, col3.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f FromRows(V4f row0, V4f row1, V4f row2)\n        {\n            return new M34f(\n                row0.X, row0.Y, row0.Z, row0.W, \n                row1.X, row1.Y, row1.Z, row1.W, \n                row2.X, row2.Y, row2.Z, row2.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f FromDiagonal(float value)\n        {\n            return new M34f(\n                value, 0, 0, 0, \n                0, value, 0, 0, \n                0, 0, value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f FromDiagonal(float m00, float m11, float m22)\n        {\n            return new M34f(\n                m00, 0, 0, 0, \n                0, m11, 0, 0, \n                0, 0, m22, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f FromDiagonal(V3f s)\n        {\n            return new M34f(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M34f\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f Scale(float s)\n        {\n            return new M34f(\n                s, 0, 0, 0, \n                0, s, 0, 0, \n                0, 0, s, 0);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34f\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f Scale(float sX, float sY, float sZ)\n        {\n            return new M34f(\n                sX, 0, 0, 0, \n                0, sY, 0, 0, \n                0, 0, sZ, 0);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34f\"/> using a <see cref=\"V3f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f Scale(V3f s)\n        {\n            return new M34f(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation <see cref=\"M34f\"/> from a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f Scale(Scale3f s)\n        {\n            return new M34f(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34f\"/> with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f Translation(float tX, float tY, float tZ)\n        {\n            return new M34f(\n                1, 0, 0, tX, \n                0, 1, 0, tY, \n                0, 0, 1, tZ);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34f\"/> with the translational component given by a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f Translation(V3f t)\n        {\n            return new M34f(\n                1, 0, 0, t.X, \n                0, 1, 0, t.Y, \n                0, 0, 1, t.Z);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34f\"/> from a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f Translation(Shift3f s)\n        {\n            return new M34f(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, s.Z);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f Rotation(V3f normalizedAxis, float angleInRadians)\n        {\n            Debug.Assert(normalizedAxis.LengthSquared.ApproximateEquals(1, 1e-5f));\n            return (M34f)(Rot3f.Rotation(normalizedAxis, angleInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationInDegrees(V3f normalizedAxis, float angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationEuler(float rollInRadians, float pitchInRadians, float yawInRadians)\n        {\n            return (M34f)(Rot3f.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationEulerInDegrees(float rollInDegrees, float pitchInDegrees, float yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationEuler(V3f rollPitchYawInRadians)\n            => RotationEuler(\n                rollPitchYawInRadians.X,\n                rollPitchYawInRadians.Y,\n                rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationEulerInDegrees(V3f rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotateInto(V3f from, V3f into)\n        {\n            Debug.Assert(from.LengthSquared.ApproximateEquals(1, 1e-5f));\n            Debug.Assert(into.LengthSquared.ApproximateEquals(1, 1e-5f));\n            return (M34f)(Rot3f.RotateInto(from, into));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationX(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M34f(\n                 1,  0,  0,  0, \n                 0,  a, -b,  0, \n                 0,  b,  a,  0);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationXInDegrees(float angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationY(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M34f(\n                 a,  0,  b,  0, \n                 0,  1,  0,  0, \n                -b,  0,  a,  0);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationYInDegrees(float angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationZ(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M34f(\n                 a, -b,  0,  0, \n                 b,  a,  0,  0, \n                 0,  0,  1,  0);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f RotationZInDegrees(float angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f ShearXY(float factorX, float factorY)\n        {\n            return new M34f(\n                1, 0, factorX, 0, \n                0, 1, factorY, 0, \n                0, 0, 1, 0);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f ShearXZ(float factorX, float factorZ)\n        {\n            return new M34f(\n                1, factorX, 0, 0, \n                0, 1, 0, 0, \n                0, factorZ, 1, 0);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f ShearYZ(float factorY, float factorZ)\n        {\n            return new M34f(\n                1, 0, 0, 0, \n                factorY, 1, 0, 0, \n                factorZ, 0, 1, 0);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f DivideByInt(M34f m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M03;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M13;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n                yield return M23;\n            }\n        }\n\n        public readonly IEnumerable<V4f> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n            }\n        }\n\n        public readonly IEnumerable<V3f> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n                yield return C3;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M00,  M01,  M02,  M03); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n                M03 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M10,  M11,  M12,  M13); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n                M13 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M20,  M21,  M22,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n                M23 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M00,  M10,  M20); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M01,  M11,  M21); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M02,  M12,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3f C3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f( M03,  M13,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M03 = value.X;\n                M13 = value.Y;\n                M23 = value.Z;\n            }\n        }\n\n        public readonly V3f Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3f(M00, M11, M22);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly float MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly float MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23);\n        }\n\n        public unsafe float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe float this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[row * 4 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[row * 4 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || Fun.IsFinite(M02) || Fun.IsFinite(M03) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11) || Fun.IsFinite(M12) || Fun.IsFinite(M13) || \n                    Fun.IsFinite(M20) || Fun.IsFinite(M21) || Fun.IsFinite(M22) || Fun.IsFinite(M23);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && Fun.IsFinite(M02) && Fun.IsFinite(M03) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11) && Fun.IsFinite(M12) && Fun.IsFinite(M13) && \n                    Fun.IsFinite(M20) && Fun.IsFinite(M21) && Fun.IsFinite(M22) && Fun.IsFinite(M23);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) || float.IsNaN(M01) || float.IsNaN(M02) || float.IsNaN(M03) || \n                    float.IsNaN(M10) || float.IsNaN(M11) || float.IsNaN(M12) || float.IsNaN(M13) || \n                    float.IsNaN(M20) || float.IsNaN(M21) || float.IsNaN(M22) || float.IsNaN(M23);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) && float.IsNaN(M01) && float.IsNaN(M02) && float.IsNaN(M03) && \n                    float.IsNaN(M10) && float.IsNaN(M11) && float.IsNaN(M12) && float.IsNaN(M13) && \n                    float.IsNaN(M20) && float.IsNaN(M21) && float.IsNaN(M22) && float.IsNaN(M23);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) || float.IsInfinity(M01) || float.IsInfinity(M02) || float.IsInfinity(M03) || \n                    float.IsInfinity(M10) || float.IsInfinity(M11) || float.IsInfinity(M12) || float.IsInfinity(M13) || \n                    float.IsInfinity(M20) || float.IsInfinity(M21) || float.IsInfinity(M22) || float.IsInfinity(M23);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) && float.IsInfinity(M01) && float.IsInfinity(M02) && float.IsInfinity(M03) && \n                    float.IsInfinity(M10) && float.IsInfinity(M11) && float.IsInfinity(M12) && float.IsInfinity(M13) && \n                    float.IsInfinity(M20) && float.IsInfinity(M21) && float.IsInfinity(M22) && float.IsInfinity(M23);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) || float.IsPositiveInfinity(M01) || float.IsPositiveInfinity(M02) || float.IsPositiveInfinity(M03) || \n                    float.IsPositiveInfinity(M10) || float.IsPositiveInfinity(M11) || float.IsPositiveInfinity(M12) || float.IsPositiveInfinity(M13) || \n                    float.IsPositiveInfinity(M20) || float.IsPositiveInfinity(M21) || float.IsPositiveInfinity(M22) || float.IsPositiveInfinity(M23);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) && float.IsPositiveInfinity(M01) && float.IsPositiveInfinity(M02) && float.IsPositiveInfinity(M03) && \n                    float.IsPositiveInfinity(M10) && float.IsPositiveInfinity(M11) && float.IsPositiveInfinity(M12) && float.IsPositiveInfinity(M13) && \n                    float.IsPositiveInfinity(M20) && float.IsPositiveInfinity(M21) && float.IsPositiveInfinity(M22) && float.IsPositiveInfinity(M23);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) || float.IsNegativeInfinity(M01) || float.IsNegativeInfinity(M02) || float.IsNegativeInfinity(M03) || \n                    float.IsNegativeInfinity(M10) || float.IsNegativeInfinity(M11) || float.IsNegativeInfinity(M12) || float.IsNegativeInfinity(M13) || \n                    float.IsNegativeInfinity(M20) || float.IsNegativeInfinity(M21) || float.IsNegativeInfinity(M22) || float.IsNegativeInfinity(M23);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) && float.IsNegativeInfinity(M01) && float.IsNegativeInfinity(M02) && float.IsNegativeInfinity(M03) && \n                    float.IsNegativeInfinity(M10) && float.IsNegativeInfinity(M11) && float.IsNegativeInfinity(M12) && float.IsNegativeInfinity(M13) && \n                    float.IsNegativeInfinity(M20) && float.IsNegativeInfinity(M21) && float.IsNegativeInfinity(M22) && float.IsNegativeInfinity(M23);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || Fun.IsTiny(M02) || Fun.IsTiny(M03) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11) || Fun.IsTiny(M12) || Fun.IsTiny(M13) || \n                    Fun.IsTiny(M20) || Fun.IsTiny(M21) || Fun.IsTiny(M22) || Fun.IsTiny(M23);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && Fun.IsTiny(M02) && Fun.IsTiny(M03) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11) && Fun.IsTiny(M12) && Fun.IsTiny(M13) && \n                    Fun.IsTiny(M20) && Fun.IsTiny(M21) && Fun.IsTiny(M22) && Fun.IsTiny(M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 3;\n        public const int ColumnCount = 4;\n        public const int ElementCount = 3 * 4;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(3, 4);\n        }\n\n        public static M34f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M34f(0);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly float Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + Fun.Abs(M03) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + Fun.Abs(M13) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22) + Fun.Abs(M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly float Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + M03 * M03 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + M13 * M13 + \n                    M20 * M20 + M21 * M21 + M22 * M22 + M23 * M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator -(M34f m)\n        {\n            return new M34f(\n                -m.M00, -m.M01, -m.M02, -m.M03, \n                -m.M10, -m.M11, -m.M12, -m.M13, \n                -m.M20, -m.M21, -m.M22, -m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (M34f a, M34f b)\n        {\n            return new M34f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (M34f m, float s)\n        {\n            return new M34f(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  + (float s, M34f m)\n        {\n            return new M34f(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (M34f a, M34d b)\n        {\n            return new M34d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (M34f m, double s)\n        {\n            return new M34d(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (double s, M34f m)\n        {\n            return new M34d(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (M34f a, M34f b)\n        {\n            return new M34f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (M34f m, float s)\n        {\n            return new M34f(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  - (float s, M34f m)\n        {\n            return new M34f(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (M34f a, M34d b)\n        {\n            return new M34d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (M34f m, double s)\n        {\n            return new M34d(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (double s, M34f m)\n        {\n            return new M34d(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (M34f a, M34f b)\n        {\n            return new M34f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (M34f m, float s)\n        {\n            return new M34f(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  % (float s, M34f m)\n        {\n            return new M34f(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (M34f a, M34d b)\n        {\n            return new M34d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (M34f m, double s)\n        {\n            return new M34d(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (double s, M34f m)\n        {\n            return new M34d(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (M34f a, M34f b)\n        {\n            return new M34f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (M34f m, float s)\n        {\n            return new M34f(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  / (float s, M34f m)\n        {\n            return new M34f(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (M34f a, M34d b)\n        {\n            return new M34d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (M34f m, double s)\n        {\n            return new M34d(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (double s, M34f m)\n        {\n            return new M34d(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  * (M34f m, float s)\n        {\n            return new M34f(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator  * (float s, M34f m)\n        {\n            return new M34f(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  * (M34f m, double s)\n        {\n            return new M34d(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  * (double s, M34f m)\n        {\n            return new M34d(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M34f matrix with a V4f column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(M34f m, V4f v)\n        {\n            return new V3f(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z + m.M03 * v.W, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z + m.M13 * v.W, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z + m.M23 * v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a V3f row vector with a M34f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(V3f v, M34f m)\n        {\n            return new V4f(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22, \n                v.X * m.M03 + v.Y * m.M13 + v.Z * m.M23);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M34f a, M34f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M34f a, float s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M03 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M13 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s && \n                a.M23 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(float s, M34f a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M03  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M13  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22  && \n                s == a.M23 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M34f a, M34f b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M34f m, float s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(float s, M34f m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02, M03),\n                        HashCode.GetCombined(M10, M11, M12, M13),\n                        HashCode.GetCombined(M20, M21, M22, M23));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M34f other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && M03.Equals(other.M03) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && M13.Equals(other.M13) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22) && M23.Equals(other.M23);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M34f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M34f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M34f.FromRows(\n                V4f.Parse(x[0]), \n                V4f.Parse(x[1]), \n                V4f.Parse(x[2])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M34f operator *(M33f a, M34f b)\n        {\n            return new M34f(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23\n             );\n        }\n\n        public static M34f operator *(M34f a, M44f b)\n        {\n            return new M34f(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20 + a.M03 * b.M30, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21 + a.M03 * b.M31, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22 + a.M03 * b.M32, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03 * b.M33, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20 + a.M13 * b.M30, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20 + a.M23 * b.M30, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (float)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (float)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (float)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (float)value;\n        }\n\n        #endregion\n    }\n\n    public class M34fEqualityComparer : IEqualityComparer<M34f>\n    {\n        public static readonly M34fEqualityComparer Default\n            = new M34fEqualityComparer();\n\n        #region IEqualityComparer<M34f> Members\n\n        public bool Equals(M34f v0, M34f v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M34f v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale(this M34f m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetScaleVector(this M34f m)\n            => new V3f(m.C0.Length, m.C1.Length, m.C2.Length);\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A left-handed coordinates system transformation is expected,\n        /// where the view-space z-axis points in forward direction.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetViewDirectionLH(this M34f m)\n            => m.R2.XYZ.Normalized;\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A right-handed coordinates system transformation is expected, where\n        /// the view-space z-axis points opposit the forward vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetViewDirectionRH(this M34f m)\n            => -m.R2.XYZ.Normalized;\n\n        /// <summary>\n        /// Extracts the translation component of the given transformation matrix, which when given\n        /// a model transformation represents the model origin in world position.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetModelOrigin(this M34f m)\n            => m.C3;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm1(M34f m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm2(M34f m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMax(M34f m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMin(M34f m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(this M34f m, float p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M03).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M13).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p) + \n                Fun.Abs(m.M23).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static float Distance1(this M34f a, M34f b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M03 - a.M03) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M13 - a.M13) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22) + \n                Fun.Abs(b.M23 - a.M23);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static float Distance2(this M34f a, M34f b)\n        {\n            return (float)Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M03 - a.M03) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M13 - a.M13) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22) + \n                        Fun.Square(b.M23 - a.M23));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static float Distance(this M34f a, M34f b, float p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M03 - a.M03).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M13 - a.M13).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p) + \n                Fun.Abs(b.M23 - a.M23).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMax(this M34f a, M34f b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMin(this M34f a, M34f b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this M34f m, V4f v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f TransposedTransform(this M34f m, V3f v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V3f TransformDir(this M34f m, V3f v)\n        {\n            return new V3f(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by matrix m.\n        /// </summary>\n        public static V3f TransformPos(this M34f m, V3f p)\n        {\n            return new V3f(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23\n                );\n        }\n\n        /// <summary>\n        /// Multiplies two <see cref=\"M34f\"/> matrices as 4x4 matrices.\n        /// </summary>\n        public static M34f MultiplyAffine(this M34f a, M34f b)\n        {\n            return new M34f(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4f Row(this M34f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V4f(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3f Column(this M34f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V3f(ptr[index], ptr[index + 4], ptr[index + 8]);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M34f a, M34f b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M03 < b.M03 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M13 < b.M13 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22 && \n                a.M23 < b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M34f m, float s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M03 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M13 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s && \n                m.M23 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, M34f m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M03 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M13 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22 && \n                s < m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M34f a, M34f b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M03 < b.M03 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M13 < b.M13 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22 || \n                a.M23 < b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M34f m, float s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M03 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M13 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s || \n                m.M23 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, M34f m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M03 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M13 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22 || \n                s < m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M34f a, M34f b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M03 > b.M03 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M13 > b.M13 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22 && \n                a.M23 > b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M34f m, float s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M03 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M13 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s && \n                m.M23 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, M34f m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M03 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M13 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22 && \n                s > m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M34f a, M34f b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M03 > b.M03 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M13 > b.M13 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22 || \n                a.M23 > b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M34f m, float s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M03 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M13 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s || \n                m.M23 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, M34f m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M03 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M13 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22 || \n                s > m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M34f a, M34f b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M03 <= b.M03 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M13 <= b.M13 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22 && \n                a.M23 <= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M34f m, float s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M03 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M13 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s && \n                m.M23 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, M34f m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M03 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M13 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22 && \n                s <= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M34f a, M34f b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M03 <= b.M03 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M13 <= b.M13 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22 || \n                a.M23 <= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M34f m, float s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M03 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M13 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s || \n                m.M23 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, M34f m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M03 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M13 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22 || \n                s <= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M34f a, M34f b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M03 >= b.M03 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M13 >= b.M13 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22 && \n                a.M23 >= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M34f m, float s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M03 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M13 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s && \n                m.M23 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, M34f m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M03 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M13 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22 && \n                s >= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M34f a, M34f b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M03 >= b.M03 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M13 >= b.M13 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22 || \n                a.M23 >= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M34f m, float s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M03 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M13 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s || \n                m.M23 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, M34f m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M03 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M13 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22 || \n                s >= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M34f a, M34f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M34f m, float s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M03 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M13 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s && \n                m.M23 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, M34f m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M03 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M13 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22 && \n                s == m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M34f a, M34f b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M03 == b.M03 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M13 == b.M13 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22 || \n                a.M23 == b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M34f m, float s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M03 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M13 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s || \n                m.M23 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, M34f m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M03 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M13 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22 || \n                s == m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M34f a, M34f b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M03 != b.M03 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M13 != b.M13 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22 && \n                a.M23 != b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M34f m, float s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M03 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M13 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s && \n                m.M23 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, M34f m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M03 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M13 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22 && \n                s != m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M34f a, M34f b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M03 != b.M03 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M13 != b.M13 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22 || \n                a.M23 != b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M34f m, float s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M03 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M13 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s || \n                m.M23 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, M34f m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M03 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M13 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22 || \n                s != m.M23;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M34f m0, M34f m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M03 < m1.M03) return -1;\n            if (m0.M03 > m1.M03) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M13 < m1.M13) return -1;\n            if (m0.M13 > m1.M13) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            if (m0.M23 < m1.M23) return -1;\n            if (m0.M23 > m1.M23) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M34f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MinElement(M34f m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M34f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MaxElement(M34f m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M34f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M34f m, float epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M03.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M13.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon) || m.M23.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M34f m, float epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M03.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M13.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon) && m.M23.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M34f m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M34f m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M34f m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M34f m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M34f m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M34f m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M34f m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M34f m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M34f m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M34f m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M34f m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M34f m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M34f a, M34f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M34f a, M34f b, float epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M34f m, float epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M34f m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M34f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M34f v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M34f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M34f v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M34f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M34f v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M34f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M34f v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M34f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M34f v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM34fExtensions\n    {\n        #region IRandomUniform extensions for M34f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of an M34f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f UniformM34f(this IRandomUniform rnd)\n        {\n            return new M34f(\n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of an M34f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f UniformM34fClosed(this IRandomUniform rnd)\n        {\n            return new M34f(\n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of an M34f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f UniformM34fOpen(this IRandomUniform rnd)\n        {\n            return new M34f(\n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M34d\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M34d : IEquatable<M34d>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public double M00, M01, M02, M03;\n        [DataMember]\n        public double M10, M11, M12, M13;\n        [DataMember]\n        public double M20, M21, M22, M23;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(double value)\n        {\n            M00 = value; M01 = 0; M02 = 0; M03 = 0; \n            M10 = 0; M11 = value; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = value; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(\n                double m00, double m01, double m02, double m03, \n                double m10, double m11, double m12, double m13, \n                double m20, double m21, double m22, double m23)\n        {\n            M00 = m00; M01 = m01; M02 = m02; M03 = m03; \n            M10 = m10; M11 = m11; M12 = m12; M13 = m13; \n            M20 = m20; M21 = m21; M22 = m22; M23 = m23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(double[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M03 = a[3];\n            M10 = a[4];\n            M11 = a[5];\n            M12 = a[6];\n            M13 = a[7];\n            M20 = a[8];\n            M21 = a[9];\n            M22 = a[10];\n            M23 = a[11];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(double[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M03 = a[start + 3];\n            M10 = a[start + 4];\n            M11 = a[start + 5];\n            M12 = a[start + 6];\n            M13 = a[start + 7];\n            M20 = a[start + 8];\n            M21 = a[start + 9];\n            M22 = a[start + 10];\n            M23 = a[start + 11];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M33d m, V3d v)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = v.X; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = v.Y; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = v.Z; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M22i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M23i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M33i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M34i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M44i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M22l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M23l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M33l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M34l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M44l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M22f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M23f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M33f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M34f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M44f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M22d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M23d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M33d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = 0; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M34d(M44d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = m.M03; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = m.M13; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = m.M23; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M34d(M22i m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M23i m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M33i m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M34i m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n            };\n        }\n\n        public static explicit operator M34d(M44i m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n            };\n        }\n\n        public static explicit operator M34d(M22l m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M23l m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M33l m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M34l m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n            };\n        }\n\n        public static explicit operator M34d(M44l m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n            };\n        }\n\n        public static explicit operator M34d(M22f m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M23f m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M33f m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M34f m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n            };\n        }\n\n        public static explicit operator M34d(M44f m)\n        {\n            return new M34d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n            };\n        }\n\n        public static explicit operator M34d(M22d m)\n        {\n            return new M34d {\n                M00 = m.M00, M01 = m.M01, M02 = 0, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M23d m)\n        {\n            return new M34d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M33d m)\n        {\n            return new M34d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = 0, \n            };\n        }\n\n        public static explicit operator M34d(M44d m)\n        {\n            return new M34d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = m.M03, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = m.M13, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = m.M23, \n            };\n        }\n\n        public static explicit operator M34d(int[] a)\n        {\n            return new M34d(\n                (double)a[0], (double)a[1], (double)a[2], (double)a[3], \n                (double)a[4], (double)a[5], (double)a[6], (double)a[7], \n                (double)a[8], (double)a[9], (double)a[10], (double)a[11]);\n        }\n\n        public static explicit operator M34d(int[,] a)\n        {\n            return new M34d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], (double)a[0, 3], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], (double)a[1, 3], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2], (double)a[2, 3]);\n        }\n\n        public static explicit operator int[](M34d m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03, \n                (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13, \n                (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23\n            };\n        }\n\n        public static explicit operator int[,](M34d m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M03;\n            array[index + 4] = (int)M10;\n            array[index + 5] = (int)M11;\n            array[index + 6] = (int)M12;\n            array[index + 7] = (int)M13;\n            array[index + 8] = (int)M20;\n            array[index + 9] = (int)M21;\n            array[index + 10] = (int)M22;\n            array[index + 11] = (int)M23;\n        }\n\n        public static explicit operator M34d(long[] a)\n        {\n            return new M34d(\n                (double)a[0], (double)a[1], (double)a[2], (double)a[3], \n                (double)a[4], (double)a[5], (double)a[6], (double)a[7], \n                (double)a[8], (double)a[9], (double)a[10], (double)a[11]);\n        }\n\n        public static explicit operator M34d(long[,] a)\n        {\n            return new M34d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], (double)a[0, 3], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], (double)a[1, 3], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2], (double)a[2, 3]);\n        }\n\n        public static explicit operator long[](M34d m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03, \n                (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13, \n                (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23\n            };\n        }\n\n        public static explicit operator long[,](M34d m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M03;\n            array[index + 4] = (long)M10;\n            array[index + 5] = (long)M11;\n            array[index + 6] = (long)M12;\n            array[index + 7] = (long)M13;\n            array[index + 8] = (long)M20;\n            array[index + 9] = (long)M21;\n            array[index + 10] = (long)M22;\n            array[index + 11] = (long)M23;\n        }\n\n        public static explicit operator M34d(float[] a)\n        {\n            return new M34d(\n                (double)a[0], (double)a[1], (double)a[2], (double)a[3], \n                (double)a[4], (double)a[5], (double)a[6], (double)a[7], \n                (double)a[8], (double)a[9], (double)a[10], (double)a[11]);\n        }\n\n        public static explicit operator M34d(float[,] a)\n        {\n            return new M34d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], (double)a[0, 3], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], (double)a[1, 3], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2], (double)a[2, 3]);\n        }\n\n        public static explicit operator float[](M34d m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03, \n                (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13, \n                (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23\n            };\n        }\n\n        public static explicit operator float[,](M34d m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M03;\n            array[index + 4] = (float)M10;\n            array[index + 5] = (float)M11;\n            array[index + 6] = (float)M12;\n            array[index + 7] = (float)M13;\n            array[index + 8] = (float)M20;\n            array[index + 9] = (float)M21;\n            array[index + 10] = (float)M22;\n            array[index + 11] = (float)M23;\n        }\n\n        public static explicit operator M34d(double[] a)\n        {\n            return new M34d(\n                a[0], a[1], a[2], a[3], \n                a[4], a[5], a[6], a[7], \n                a[8], a[9], a[10], a[11]);\n        }\n\n        public static explicit operator M34d(double[,] a)\n        {\n            return new M34d(\n                a[0, 0], a[0, 1], a[0, 2], a[0, 3], \n                a[1, 0], a[1, 1], a[1, 2], a[1, 3], \n                a[2, 0], a[2, 1], a[2, 2], a[2, 3]);\n        }\n\n        public static explicit operator double[](M34d m)\n        {\n            return new double[] {\n                m.M00, m.M01, m.M02, m.M03, \n                m.M10, m.M11, m.M12, m.M13, \n                m.M20, m.M21, m.M22, m.M23\n            };\n        }\n\n        public static explicit operator double[,](M34d m)\n        {\n            return new double[,] {\n                { m.M00, m.M01, m.M02, m.M03 }, \n                { m.M10, m.M11, m.M12, m.M13 }, \n                { m.M20, m.M21, m.M22, m.M23 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M03;\n            array[index + 4] = M10;\n            array[index + 5] = M11;\n            array[index + 6] = M12;\n            array[index + 7] = M13;\n            array[index + 8] = M20;\n            array[index + 9] = M21;\n            array[index + 10] = M22;\n            array[index + 11] = M23;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34i Copy(Func<double, int> element_fun)\n        {\n            return new M34i(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34i Copy(Func<double, int, int, int> element_index0_index1_fun)\n        {\n            return new M34i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34l Copy(Func<double, long> element_fun)\n        {\n            return new M34l(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34l Copy(Func<double, int, int, long> element_index0_index1_fun)\n        {\n            return new M34l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34f Copy(Func<double, float> element_fun)\n        {\n            return new M34f(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34f Copy(Func<double, int, int, float> element_index0_index1_fun)\n        {\n            return new M34f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34d Copy(Func<double, double> element_fun)\n        {\n            return new M34d(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M34d Copy(Func<double, int, int, double> element_index0_index1_fun)\n        {\n            return new M34d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3));\n        }\n\n        public readonly double[] ToArray()\n        {\n            var array = new double[12];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M03;\n            array[4] = M10;\n            array[5] = M11;\n            array[6] = M12;\n            array[7] = M13;\n            array[8] = M20;\n            array[9] = M21;\n            array[10] = M22;\n            array[11] = M23;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d FromCols(V3d col0, V3d col1, V3d col2, V3d col3)\n        {\n            return new M34d(\n                col0.X, col1.X, col2.X, col3.X, \n                col0.Y, col1.Y, col2.Y, col3.Y, \n                col0.Z, col1.Z, col2.Z, col3.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d FromRows(V4d row0, V4d row1, V4d row2)\n        {\n            return new M34d(\n                row0.X, row0.Y, row0.Z, row0.W, \n                row1.X, row1.Y, row1.Z, row1.W, \n                row2.X, row2.Y, row2.Z, row2.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d FromDiagonal(double value)\n        {\n            return new M34d(\n                value, 0, 0, 0, \n                0, value, 0, 0, \n                0, 0, value, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d FromDiagonal(double m00, double m11, double m22)\n        {\n            return new M34d(\n                m00, 0, 0, 0, \n                0, m11, 0, 0, \n                0, 0, m22, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d FromDiagonal(V3d s)\n        {\n            return new M34d(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M34d\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d Scale(double s)\n        {\n            return new M34d(\n                s, 0, 0, 0, \n                0, s, 0, 0, \n                0, 0, s, 0);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34d\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d Scale(double sX, double sY, double sZ)\n        {\n            return new M34d(\n                sX, 0, 0, 0, \n                0, sY, 0, 0, \n                0, 0, sZ, 0);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34d\"/> using a <see cref=\"V3d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d Scale(V3d s)\n        {\n            return new M34d(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation <see cref=\"M34d\"/> from a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d Scale(Scale3d s)\n        {\n            return new M34d(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34d\"/> with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d Translation(double tX, double tY, double tZ)\n        {\n            return new M34d(\n                1, 0, 0, tX, \n                0, 1, 0, tY, \n                0, 0, 1, tZ);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34d\"/> with the translational component given by a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d Translation(V3d t)\n        {\n            return new M34d(\n                1, 0, 0, t.X, \n                0, 1, 0, t.Y, \n                0, 0, 1, t.Z);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M34d\"/> from a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d Translation(Shift3d s)\n        {\n            return new M34d(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, s.Z);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d Rotation(V3d normalizedAxis, double angleInRadians)\n        {\n            Debug.Assert(normalizedAxis.LengthSquared.ApproximateEquals(1, 1e-10));\n            return (M34d)(Rot3d.Rotation(normalizedAxis, angleInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationInDegrees(V3d normalizedAxis, double angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationEuler(double rollInRadians, double pitchInRadians, double yawInRadians)\n        {\n            return (M34d)(Rot3d.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationEulerInDegrees(double rollInDegrees, double pitchInDegrees, double yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationEuler(V3d rollPitchYawInRadians)\n            => RotationEuler(\n                rollPitchYawInRadians.X,\n                rollPitchYawInRadians.Y,\n                rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationEulerInDegrees(V3d rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotateInto(V3d from, V3d into)\n        {\n            Debug.Assert(from.LengthSquared.ApproximateEquals(1, 1e-10));\n            Debug.Assert(into.LengthSquared.ApproximateEquals(1, 1e-10));\n            return (M34d)(Rot3d.RotateInto(from, into));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationX(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M34d(\n                 1,  0,  0,  0, \n                 0,  a, -b,  0, \n                 0,  b,  a,  0);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationXInDegrees(double angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationY(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M34d(\n                 a,  0,  b,  0, \n                 0,  1,  0,  0, \n                -b,  0,  a,  0);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationYInDegrees(double angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationZ(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M34d(\n                 a, -b,  0,  0, \n                 b,  a,  0,  0, \n                 0,  0,  1,  0);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d RotationZInDegrees(double angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d ShearXY(double factorX, double factorY)\n        {\n            return new M34d(\n                1, 0, factorX, 0, \n                0, 1, factorY, 0, \n                0, 0, 1, 0);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d ShearXZ(double factorX, double factorZ)\n        {\n            return new M34d(\n                1, factorX, 0, 0, \n                0, 1, 0, 0, \n                0, factorZ, 1, 0);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d ShearYZ(double factorY, double factorZ)\n        {\n            return new M34d(\n                1, 0, 0, 0, \n                factorY, 1, 0, 0, \n                factorZ, 0, 1, 0);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d DivideByInt(M34d m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M03;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M13;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n                yield return M23;\n            }\n        }\n\n        public readonly IEnumerable<V4d> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n            }\n        }\n\n        public readonly IEnumerable<V3d> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n                yield return C3;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M00,  M01,  M02,  M03); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n                M03 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M10,  M11,  M12,  M13); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n                M13 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M20,  M21,  M22,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n                M23 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M00,  M10,  M20); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M01,  M11,  M21); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M02,  M12,  M22); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n            }\n        }\n\n        [XmlIgnore]\n        public V3d C3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d( M03,  M13,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M03 = value.X;\n                M13 = value.Y;\n                M23 = value.Z;\n            }\n        }\n\n        public readonly V3d Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V3d(M00, M11, M22);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly double MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly double MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23);\n        }\n\n        public unsafe double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe double this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[row * 4 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[row * 4 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || Fun.IsFinite(M02) || Fun.IsFinite(M03) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11) || Fun.IsFinite(M12) || Fun.IsFinite(M13) || \n                    Fun.IsFinite(M20) || Fun.IsFinite(M21) || Fun.IsFinite(M22) || Fun.IsFinite(M23);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && Fun.IsFinite(M02) && Fun.IsFinite(M03) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11) && Fun.IsFinite(M12) && Fun.IsFinite(M13) && \n                    Fun.IsFinite(M20) && Fun.IsFinite(M21) && Fun.IsFinite(M22) && Fun.IsFinite(M23);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) || double.IsNaN(M01) || double.IsNaN(M02) || double.IsNaN(M03) || \n                    double.IsNaN(M10) || double.IsNaN(M11) || double.IsNaN(M12) || double.IsNaN(M13) || \n                    double.IsNaN(M20) || double.IsNaN(M21) || double.IsNaN(M22) || double.IsNaN(M23);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) && double.IsNaN(M01) && double.IsNaN(M02) && double.IsNaN(M03) && \n                    double.IsNaN(M10) && double.IsNaN(M11) && double.IsNaN(M12) && double.IsNaN(M13) && \n                    double.IsNaN(M20) && double.IsNaN(M21) && double.IsNaN(M22) && double.IsNaN(M23);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) || double.IsInfinity(M01) || double.IsInfinity(M02) || double.IsInfinity(M03) || \n                    double.IsInfinity(M10) || double.IsInfinity(M11) || double.IsInfinity(M12) || double.IsInfinity(M13) || \n                    double.IsInfinity(M20) || double.IsInfinity(M21) || double.IsInfinity(M22) || double.IsInfinity(M23);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) && double.IsInfinity(M01) && double.IsInfinity(M02) && double.IsInfinity(M03) && \n                    double.IsInfinity(M10) && double.IsInfinity(M11) && double.IsInfinity(M12) && double.IsInfinity(M13) && \n                    double.IsInfinity(M20) && double.IsInfinity(M21) && double.IsInfinity(M22) && double.IsInfinity(M23);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) || double.IsPositiveInfinity(M01) || double.IsPositiveInfinity(M02) || double.IsPositiveInfinity(M03) || \n                    double.IsPositiveInfinity(M10) || double.IsPositiveInfinity(M11) || double.IsPositiveInfinity(M12) || double.IsPositiveInfinity(M13) || \n                    double.IsPositiveInfinity(M20) || double.IsPositiveInfinity(M21) || double.IsPositiveInfinity(M22) || double.IsPositiveInfinity(M23);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) && double.IsPositiveInfinity(M01) && double.IsPositiveInfinity(M02) && double.IsPositiveInfinity(M03) && \n                    double.IsPositiveInfinity(M10) && double.IsPositiveInfinity(M11) && double.IsPositiveInfinity(M12) && double.IsPositiveInfinity(M13) && \n                    double.IsPositiveInfinity(M20) && double.IsPositiveInfinity(M21) && double.IsPositiveInfinity(M22) && double.IsPositiveInfinity(M23);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) || double.IsNegativeInfinity(M01) || double.IsNegativeInfinity(M02) || double.IsNegativeInfinity(M03) || \n                    double.IsNegativeInfinity(M10) || double.IsNegativeInfinity(M11) || double.IsNegativeInfinity(M12) || double.IsNegativeInfinity(M13) || \n                    double.IsNegativeInfinity(M20) || double.IsNegativeInfinity(M21) || double.IsNegativeInfinity(M22) || double.IsNegativeInfinity(M23);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) && double.IsNegativeInfinity(M01) && double.IsNegativeInfinity(M02) && double.IsNegativeInfinity(M03) && \n                    double.IsNegativeInfinity(M10) && double.IsNegativeInfinity(M11) && double.IsNegativeInfinity(M12) && double.IsNegativeInfinity(M13) && \n                    double.IsNegativeInfinity(M20) && double.IsNegativeInfinity(M21) && double.IsNegativeInfinity(M22) && double.IsNegativeInfinity(M23);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || Fun.IsTiny(M02) || Fun.IsTiny(M03) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11) || Fun.IsTiny(M12) || Fun.IsTiny(M13) || \n                    Fun.IsTiny(M20) || Fun.IsTiny(M21) || Fun.IsTiny(M22) || Fun.IsTiny(M23);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && Fun.IsTiny(M02) && Fun.IsTiny(M03) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11) && Fun.IsTiny(M12) && Fun.IsTiny(M13) && \n                    Fun.IsTiny(M20) && Fun.IsTiny(M21) && Fun.IsTiny(M22) && Fun.IsTiny(M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 3;\n        public const int ColumnCount = 4;\n        public const int ElementCount = 3 * 4;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(3, 4);\n        }\n\n        public static M34d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M34d(0);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly double Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + Fun.Abs(M03) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + Fun.Abs(M13) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22) + Fun.Abs(M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + M03 * M03 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + M13 * M13 + \n                    M20 * M20 + M21 * M21 + M22 * M22 + M23 * M23);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator -(M34d m)\n        {\n            return new M34d(\n                -m.M00, -m.M01, -m.M02, -m.M03, \n                -m.M10, -m.M11, -m.M12, -m.M13, \n                -m.M20, -m.M21, -m.M22, -m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (M34d a, M34d b)\n        {\n            return new M34d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (M34d m, double s)\n        {\n            return new M34d(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  + (double s, M34d m)\n        {\n            return new M34d(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (M34d a, M34d b)\n        {\n            return new M34d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (M34d m, double s)\n        {\n            return new M34d(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  - (double s, M34d m)\n        {\n            return new M34d(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (M34d a, M34d b)\n        {\n            return new M34d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (M34d m, double s)\n        {\n            return new M34d(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  % (double s, M34d m)\n        {\n            return new M34d(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (M34d a, M34d b)\n        {\n            return new M34d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (M34d m, double s)\n        {\n            return new M34d(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  / (double s, M34d m)\n        {\n            return new M34d(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  * (M34d m, double s)\n        {\n            return new M34d(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator  * (double s, M34d m)\n        {\n            return new M34d(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M34d matrix with a V4d column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(M34d m, V4d v)\n        {\n            return new V3d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z + m.M03 * v.W, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z + m.M13 * v.W, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z + m.M23 * v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a V3d row vector with a M34d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(V3d v, M34d m)\n        {\n            return new V4d(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22, \n                v.X * m.M03 + v.Y * m.M13 + v.Z * m.M23);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M34d a, M34d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M34d a, double s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M03 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M13 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s && \n                a.M23 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(double s, M34d a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M03  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M13  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22  && \n                s == a.M23 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M34d a, M34d b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M34d m, double s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(double s, M34d m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02, M03),\n                        HashCode.GetCombined(M10, M11, M12, M13),\n                        HashCode.GetCombined(M20, M21, M22, M23));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M34d other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && M03.Equals(other.M03) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && M13.Equals(other.M13) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22) && M23.Equals(other.M23);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M34d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M34d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M34d.FromRows(\n                V4d.Parse(x[0]), \n                V4d.Parse(x[1]), \n                V4d.Parse(x[2])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M34d operator *(M33d a, M34d b)\n        {\n            return new M34d(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23\n             );\n        }\n\n        public static M34d operator *(M34d a, M44d b)\n        {\n            return new M34d(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20 + a.M03 * b.M30, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21 + a.M03 * b.M31, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22 + a.M03 * b.M32, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03 * b.M33, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20 + a.M13 * b.M30, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20 + a.M23 * b.M30, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (double)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (double)value;\n        }\n\n        #endregion\n    }\n\n    public class M34dEqualityComparer : IEqualityComparer<M34d>\n    {\n        public static readonly M34dEqualityComparer Default\n            = new M34dEqualityComparer();\n\n        #region IEqualityComparer<M34d> Members\n\n        public bool Equals(M34d v0, M34d v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M34d v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M34d m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector(this M34d m)\n            => new V3d(m.C0.Length, m.C1.Length, m.C2.Length);\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A left-handed coordinates system transformation is expected,\n        /// where the view-space z-axis points in forward direction.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetViewDirectionLH(this M34d m)\n            => m.R2.XYZ.Normalized;\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A right-handed coordinates system transformation is expected, where\n        /// the view-space z-axis points opposit the forward vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetViewDirectionRH(this M34d m)\n            => -m.R2.XYZ.Normalized;\n\n        /// <summary>\n        /// Extracts the translation component of the given transformation matrix, which when given\n        /// a model transformation represents the model origin in world position.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetModelOrigin(this M34d m)\n            => m.C3;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm1(M34d m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M34d m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMax(M34d m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMin(M34d m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M34d m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M03).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M13).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p) + \n                Fun.Abs(m.M23).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static double Distance1(this M34d a, M34d b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M03 - a.M03) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M13 - a.M13) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22) + \n                Fun.Abs(b.M23 - a.M23);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M34d a, M34d b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M03 - a.M03) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M13 - a.M13) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22) + \n                        Fun.Square(b.M23 - a.M23));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M34d a, M34d b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M03 - a.M03).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M13 - a.M13).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p) + \n                Fun.Abs(b.M23 - a.M23).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMax(this M34d a, M34d b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMin(this M34d a, M34d b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this M34d m, V4d v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d TransposedTransform(this M34d m, V3d v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V3d TransformDir(this M34d m, V3d v)\n        {\n            return new V3d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by matrix m.\n        /// </summary>\n        public static V3d TransformPos(this M34d m, V3d p)\n        {\n            return new V3d(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23\n                );\n        }\n\n        /// <summary>\n        /// Multiplies two <see cref=\"M34d\"/> matrices as 4x4 matrices.\n        /// </summary>\n        public static M34d MultiplyAffine(this M34d a, M34d b)\n        {\n            return new M34d(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23\n            );\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4d Row(this M34d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V4d(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V3d Column(this M34d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V3d(ptr[index], ptr[index + 4], ptr[index + 8]);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M34d a, M34d b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M03 < b.M03 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M13 < b.M13 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22 && \n                a.M23 < b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M34d m, double s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M03 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M13 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s && \n                m.M23 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, M34d m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M03 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M13 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22 && \n                s < m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M34d a, M34d b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M03 < b.M03 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M13 < b.M13 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22 || \n                a.M23 < b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M34d m, double s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M03 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M13 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s || \n                m.M23 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, M34d m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M03 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M13 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22 || \n                s < m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M34d a, M34d b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M03 > b.M03 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M13 > b.M13 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22 && \n                a.M23 > b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M34d m, double s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M03 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M13 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s && \n                m.M23 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, M34d m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M03 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M13 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22 && \n                s > m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M34d a, M34d b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M03 > b.M03 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M13 > b.M13 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22 || \n                a.M23 > b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M34d m, double s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M03 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M13 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s || \n                m.M23 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, M34d m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M03 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M13 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22 || \n                s > m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M34d a, M34d b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M03 <= b.M03 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M13 <= b.M13 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22 && \n                a.M23 <= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M34d m, double s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M03 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M13 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s && \n                m.M23 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, M34d m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M03 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M13 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22 && \n                s <= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M34d a, M34d b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M03 <= b.M03 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M13 <= b.M13 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22 || \n                a.M23 <= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M34d m, double s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M03 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M13 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s || \n                m.M23 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, M34d m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M03 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M13 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22 || \n                s <= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M34d a, M34d b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M03 >= b.M03 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M13 >= b.M13 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22 && \n                a.M23 >= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M34d m, double s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M03 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M13 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s && \n                m.M23 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, M34d m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M03 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M13 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22 && \n                s >= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M34d a, M34d b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M03 >= b.M03 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M13 >= b.M13 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22 || \n                a.M23 >= b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M34d m, double s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M03 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M13 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s || \n                m.M23 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, M34d m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M03 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M13 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22 || \n                s >= m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M34d a, M34d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M34d m, double s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M03 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M13 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s && \n                m.M23 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, M34d m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M03 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M13 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22 && \n                s == m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M34d a, M34d b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M03 == b.M03 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M13 == b.M13 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22 || \n                a.M23 == b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M34d m, double s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M03 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M13 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s || \n                m.M23 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, M34d m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M03 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M13 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22 || \n                s == m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M34d a, M34d b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M03 != b.M03 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M13 != b.M13 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22 && \n                a.M23 != b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M34d m, double s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M03 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M13 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s && \n                m.M23 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, M34d m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M03 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M13 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22 && \n                s != m.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M34d a, M34d b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M03 != b.M03 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M13 != b.M13 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22 || \n                a.M23 != b.M23;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M34d m, double s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M03 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M13 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s || \n                m.M23 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, M34d m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M03 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M13 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22 || \n                s != m.M23;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M34d m0, M34d m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M03 < m1.M03) return -1;\n            if (m0.M03 > m1.M03) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M13 < m1.M13) return -1;\n            if (m0.M13 > m1.M13) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            if (m0.M23 < m1.M23) return -1;\n            if (m0.M23 > m1.M23) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M34d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MinElement(M34d m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M34d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MaxElement(M34d m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M34d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M34d m, double epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M03.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M13.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon) || m.M23.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M34d m, double epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M03.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M13.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon) && m.M23.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M34d m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M34d m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M34d m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M34d m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M34d m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M34d m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M34d m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M34d m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M34d m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M34d m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M34d m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M34d m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M34d a, M34d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M34d a, M34d b, double epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M34d m, double epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M34d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M34d m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M34d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M34d v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M34d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M34d v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M34d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M34d v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M34d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M34d v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M34d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M34d v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM34dExtensions\n    {\n        #region IRandomUniform extensions for M34d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of an M34d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d UniformM34d(this IRandomUniform rnd)\n        {\n            return new M34d(\n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of an M34d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d UniformM34dClosed(this IRandomUniform rnd)\n        {\n            return new M34d(\n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of an M34d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d UniformM34dOpen(this IRandomUniform rnd)\n        {\n            return new M34d(\n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of an M34d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d UniformM34dFull(this IRandomUniform rnd)\n        {\n            return new M34d(\n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of an M34d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d UniformM34dFullClosed(this IRandomUniform rnd)\n        {\n            return new M34d(\n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of an M34d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d UniformM34dFullOpen(this IRandomUniform rnd)\n        {\n            return new M34d(\n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M44i\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M44i : IEquatable<M44i>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public int M00, M01, M02, M03;\n        [DataMember]\n        public int M10, M11, M12, M13;\n        [DataMember]\n        public int M20, M21, M22, M23;\n        [DataMember]\n        public int M30, M31, M32, M33;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(int value)\n        {\n            M00 = value; M01 = 0; M02 = 0; M03 = 0; \n            M10 = 0; M11 = value; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = value; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(\n                int m00, int m01, int m02, int m03, \n                int m10, int m11, int m12, int m13, \n                int m20, int m21, int m22, int m23, \n                int m30, int m31, int m32, int m33)\n        {\n            M00 = m00; M01 = m01; M02 = m02; M03 = m03; \n            M10 = m10; M11 = m11; M12 = m12; M13 = m13; \n            M20 = m20; M21 = m21; M22 = m22; M23 = m23; \n            M30 = m30; M31 = m31; M32 = m32; M33 = m33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(int[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M03 = a[3];\n            M10 = a[4];\n            M11 = a[5];\n            M12 = a[6];\n            M13 = a[7];\n            M20 = a[8];\n            M21 = a[9];\n            M22 = a[10];\n            M23 = a[11];\n            M30 = a[12];\n            M31 = a[13];\n            M32 = a[14];\n            M33 = a[15];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(int[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M03 = a[start + 3];\n            M10 = a[start + 4];\n            M11 = a[start + 5];\n            M12 = a[start + 6];\n            M13 = a[start + 7];\n            M20 = a[start + 8];\n            M21 = a[start + 9];\n            M22 = a[start + 10];\n            M23 = a[start + 11];\n            M30 = a[start + 12];\n            M31 = a[start + 13];\n            M32 = a[start + 14];\n            M33 = a[start + 15];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M22i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M23i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M33i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M34i m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = m.M03; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = m.M13; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M22l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M23l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M33l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M34l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M44l m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n            M30 = (int)m.M30; M31 = (int)m.M31; M32 = (int)m.M32; M33 = (int)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M22f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M23f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M33f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M34f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M44f m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n            M30 = (int)m.M30; M31 = (int)m.M31; M32 = (int)m.M32; M33 = (int)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M22d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = 0; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M23d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M33d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = 0; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = 0; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M34d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44i(M44d m)\n        {\n            M00 = (int)m.M00; M01 = (int)m.M01; M02 = (int)m.M02; M03 = (int)m.M03; \n            M10 = (int)m.M10; M11 = (int)m.M11; M12 = (int)m.M12; M13 = (int)m.M13; \n            M20 = (int)m.M20; M21 = (int)m.M21; M22 = (int)m.M22; M23 = (int)m.M23; \n            M30 = (int)m.M30; M31 = (int)m.M31; M32 = (int)m.M32; M33 = (int)m.M33; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M44i(M22i m)\n        {\n            return new M44i {\n                M00 = m.M00, M01 = m.M01, M02 = 0, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M23i m)\n        {\n            return new M44i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M33i m)\n        {\n            return new M44i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M34i m)\n        {\n            return new M44i {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = m.M03, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = m.M13, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M22l m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M23l m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M33l m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M34l m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M44l m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n                M30 = (int)m.M30, M31 = (int)m.M31, M32 = (int)m.M32, M33 = (int)m.M33, \n            };\n        }\n\n        public static explicit operator M44i(M22f m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M23f m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M33f m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M34f m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M44f m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n                M30 = (int)m.M30, M31 = (int)m.M31, M32 = (int)m.M32, M33 = (int)m.M33, \n            };\n        }\n\n        public static explicit operator M44i(M22d m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = 0, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M23d m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M33d m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = 0, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = 0, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M34d m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44i(M44d m)\n        {\n            return new M44i {\n                M00 = (int)m.M00, M01 = (int)m.M01, M02 = (int)m.M02, M03 = (int)m.M03, \n                M10 = (int)m.M10, M11 = (int)m.M11, M12 = (int)m.M12, M13 = (int)m.M13, \n                M20 = (int)m.M20, M21 = (int)m.M21, M22 = (int)m.M22, M23 = (int)m.M23, \n                M30 = (int)m.M30, M31 = (int)m.M31, M32 = (int)m.M32, M33 = (int)m.M33, \n            };\n        }\n\n        public static explicit operator M44i(int[] a)\n        {\n            return new M44i(\n                a[0], a[1], a[2], a[3], \n                a[4], a[5], a[6], a[7], \n                a[8], a[9], a[10], a[11], \n                a[12], a[13], a[14], a[15]);\n        }\n\n        public static explicit operator M44i(int[,] a)\n        {\n            return new M44i(\n                a[0, 0], a[0, 1], a[0, 2], a[0, 3], \n                a[1, 0], a[1, 1], a[1, 2], a[1, 3], \n                a[2, 0], a[2, 1], a[2, 2], a[2, 3], \n                a[3, 0], a[3, 1], a[3, 2], a[3, 3]);\n        }\n\n        public static explicit operator int[](M44i m)\n        {\n            return new int[] {\n                m.M00, m.M01, m.M02, m.M03, \n                m.M10, m.M11, m.M12, m.M13, \n                m.M20, m.M21, m.M22, m.M23, \n                m.M30, m.M31, m.M32, m.M33\n            };\n        }\n\n        public static explicit operator int[,](M44i m)\n        {\n            return new int[,] {\n                { m.M00, m.M01, m.M02, m.M03 }, \n                { m.M10, m.M11, m.M12, m.M13 }, \n                { m.M20, m.M21, m.M22, m.M23 }, \n                { m.M30, m.M31, m.M32, m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M03;\n            array[index + 4] = M10;\n            array[index + 5] = M11;\n            array[index + 6] = M12;\n            array[index + 7] = M13;\n            array[index + 8] = M20;\n            array[index + 9] = M21;\n            array[index + 10] = M22;\n            array[index + 11] = M23;\n            array[index + 12] = M30;\n            array[index + 13] = M31;\n            array[index + 14] = M32;\n            array[index + 15] = M33;\n        }\n\n        public static explicit operator M44i(long[] a)\n        {\n            return new M44i(\n                (int)a[0], (int)a[1], (int)a[2], (int)a[3], \n                (int)a[4], (int)a[5], (int)a[6], (int)a[7], \n                (int)a[8], (int)a[9], (int)a[10], (int)a[11], \n                (int)a[12], (int)a[13], (int)a[14], (int)a[15]);\n        }\n\n        public static explicit operator M44i(long[,] a)\n        {\n            return new M44i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], (int)a[0, 3], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], (int)a[1, 3], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2], (int)a[2, 3], \n                (int)a[3, 0], (int)a[3, 1], (int)a[3, 2], (int)a[3, 3]);\n        }\n\n        public static explicit operator long[](M44i m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03, \n                (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13, \n                (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23, \n                (long)m.M30, (long)m.M31, (long)m.M32, (long)m.M33\n            };\n        }\n\n        public static explicit operator long[,](M44i m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23 }, \n                { (long)m.M30, (long)m.M31, (long)m.M32, (long)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M03;\n            array[index + 4] = (long)M10;\n            array[index + 5] = (long)M11;\n            array[index + 6] = (long)M12;\n            array[index + 7] = (long)M13;\n            array[index + 8] = (long)M20;\n            array[index + 9] = (long)M21;\n            array[index + 10] = (long)M22;\n            array[index + 11] = (long)M23;\n            array[index + 12] = (long)M30;\n            array[index + 13] = (long)M31;\n            array[index + 14] = (long)M32;\n            array[index + 15] = (long)M33;\n        }\n\n        public static explicit operator M44i(float[] a)\n        {\n            return new M44i(\n                (int)a[0], (int)a[1], (int)a[2], (int)a[3], \n                (int)a[4], (int)a[5], (int)a[6], (int)a[7], \n                (int)a[8], (int)a[9], (int)a[10], (int)a[11], \n                (int)a[12], (int)a[13], (int)a[14], (int)a[15]);\n        }\n\n        public static explicit operator M44i(float[,] a)\n        {\n            return new M44i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], (int)a[0, 3], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], (int)a[1, 3], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2], (int)a[2, 3], \n                (int)a[3, 0], (int)a[3, 1], (int)a[3, 2], (int)a[3, 3]);\n        }\n\n        public static explicit operator float[](M44i m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03, \n                (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13, \n                (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23, \n                (float)m.M30, (float)m.M31, (float)m.M32, (float)m.M33\n            };\n        }\n\n        public static explicit operator float[,](M44i m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23 }, \n                { (float)m.M30, (float)m.M31, (float)m.M32, (float)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M03;\n            array[index + 4] = (float)M10;\n            array[index + 5] = (float)M11;\n            array[index + 6] = (float)M12;\n            array[index + 7] = (float)M13;\n            array[index + 8] = (float)M20;\n            array[index + 9] = (float)M21;\n            array[index + 10] = (float)M22;\n            array[index + 11] = (float)M23;\n            array[index + 12] = (float)M30;\n            array[index + 13] = (float)M31;\n            array[index + 14] = (float)M32;\n            array[index + 15] = (float)M33;\n        }\n\n        public static explicit operator M44i(double[] a)\n        {\n            return new M44i(\n                (int)a[0], (int)a[1], (int)a[2], (int)a[3], \n                (int)a[4], (int)a[5], (int)a[6], (int)a[7], \n                (int)a[8], (int)a[9], (int)a[10], (int)a[11], \n                (int)a[12], (int)a[13], (int)a[14], (int)a[15]);\n        }\n\n        public static explicit operator M44i(double[,] a)\n        {\n            return new M44i(\n                (int)a[0, 0], (int)a[0, 1], (int)a[0, 2], (int)a[0, 3], \n                (int)a[1, 0], (int)a[1, 1], (int)a[1, 2], (int)a[1, 3], \n                (int)a[2, 0], (int)a[2, 1], (int)a[2, 2], (int)a[2, 3], \n                (int)a[3, 0], (int)a[3, 1], (int)a[3, 2], (int)a[3, 3]);\n        }\n\n        public static explicit operator double[](M44i m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03, \n                (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13, \n                (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23, \n                (double)m.M30, (double)m.M31, (double)m.M32, (double)m.M33\n            };\n        }\n\n        public static explicit operator double[,](M44i m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23 }, \n                { (double)m.M30, (double)m.M31, (double)m.M32, (double)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M03;\n            array[index + 4] = (double)M10;\n            array[index + 5] = (double)M11;\n            array[index + 6] = (double)M12;\n            array[index + 7] = (double)M13;\n            array[index + 8] = (double)M20;\n            array[index + 9] = (double)M21;\n            array[index + 10] = (double)M22;\n            array[index + 11] = (double)M23;\n            array[index + 12] = (double)M30;\n            array[index + 13] = (double)M31;\n            array[index + 14] = (double)M32;\n            array[index + 15] = (double)M33;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44i Copy(Func<int, int> element_fun)\n        {\n            return new M44i(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44i Copy(Func<int, int, int, int> element_index0_index1_fun)\n        {\n            return new M44i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44l Copy(Func<int, long> element_fun)\n        {\n            return new M44l(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44l Copy(Func<int, int, int, long> element_index0_index1_fun)\n        {\n            return new M44l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44f Copy(Func<int, float> element_fun)\n        {\n            return new M44f(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44f Copy(Func<int, int, int, float> element_index0_index1_fun)\n        {\n            return new M44f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44d Copy(Func<int, double> element_fun)\n        {\n            return new M44d(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44d Copy(Func<int, int, int, double> element_index0_index1_fun)\n        {\n            return new M44d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly M33i UpperLeftM33()\n        {\n            return (M33i)this;\n        }\n\n        public readonly int[] ToArray()\n        {\n            var array = new int[16];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M03;\n            array[4] = M10;\n            array[5] = M11;\n            array[6] = M12;\n            array[7] = M13;\n            array[8] = M20;\n            array[9] = M21;\n            array[10] = M22;\n            array[11] = M23;\n            array[12] = M30;\n            array[13] = M31;\n            array[14] = M32;\n            array[15] = M33;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i FromCols(V4i col0, V4i col1, V4i col2, V4i col3)\n        {\n            return new M44i(\n                col0.X, col1.X, col2.X, col3.X, \n                col0.Y, col1.Y, col2.Y, col3.Y, \n                col0.Z, col1.Z, col2.Z, col3.Z, \n                col0.W, col1.W, col2.W, col3.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i FromRows(V4i row0, V4i row1, V4i row2, V4i row3)\n        {\n            return new M44i(\n                row0.X, row0.Y, row0.Z, row0.W, \n                row1.X, row1.Y, row1.Z, row1.W, \n                row2.X, row2.Y, row2.Z, row2.W, \n                row3.X, row3.Y, row3.Z, row3.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i FromDiagonal(int value)\n        {\n            return new M44i(\n                value, 0, 0, 0, \n                0, value, 0, 0, \n                0, 0, value, 0, \n                0, 0, 0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i FromDiagonal(int m00, int m11, int m22, int m33)\n        {\n            return new M44i(\n                m00, 0, 0, 0, \n                0, m11, 0, 0, \n                0, 0, m22, 0, \n                0, 0, 0, m33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i FromDiagonal(V4i s)\n        {\n            return new M44i(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, s.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i FromAntiDiagonal(int value)\n        {\n            return new M44i(\n                 0, 0, 0, value, \n                 0, 0, value, 0, \n                 0, value, 0, 0, \n                 value, 0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i FromAntiDiagonal(int m03, int m12, int m21, int m30)\n        {\n            return new M44i(\n                0, 0, 0, m03, \n                0, 0, m12, 0, \n                0, m21, 0, 0, \n                m30, 0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i FromAntiDiagonal(V4i s)\n        {\n            return new M44i(\n                0, 0, 0, s.X, \n                0, 0, s.Y, 0, \n                0, s.Z, 0, 0, \n                s.W, 0, 0, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44i\"/> using 4 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Scale(int sX, int sY, int sZ, int sW)\n            => FromDiagonal(sX, sY, sZ, sW);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44i\"/> using a <see cref=\"V4i\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Scale(V4i s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M44i\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Scale(int s)\n        {\n            return new M44i(\n                s, 0, 0, 0, \n                0, s, 0, 0, \n                0, 0, s, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44i\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Scale(int sX, int sY, int sZ)\n        {\n            return new M44i(\n                sX, 0, 0, 0, \n                0, sY, 0, 0, \n                0, 0, sZ, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44i\"/> using a <see cref=\"V3i\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Scale(V3i s)\n        {\n            return new M44i(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44i\"/> with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Translation(int tX, int tY, int tZ)\n        {\n            return new M44i(\n                1, 0, 0, tX, \n                0, 1, 0, tY, \n                0, 0, 1, tZ, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44i\"/> with the translational component given by a <see cref=\"V3i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Translation(V3i t)\n        {\n            return new M44i(\n                1, 0, 0, t.X, \n                0, 1, 0, t.Y, \n                0, 0, 1, t.Z, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i ShearXY(int factorX, int factorY)\n        {\n            return new M44i(\n                1, 0, factorX, 0, \n                0, 1, factorY, 0, \n                0, 0, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i ShearXZ(int factorX, int factorZ)\n        {\n            return new M44i(\n                1, factorX, 0, 0, \n                0, 1, 0, 0, \n                0, factorZ, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i ShearYZ(int factorY, int factorZ)\n        {\n            return new M44i(\n                1, 0, 0, 0, \n                factorY, 1, 0, 0, \n                factorZ, 0, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i DivideByInt(M44i m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M03;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M13;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n                yield return M23;\n                yield return M30;\n                yield return M31;\n                yield return M32;\n                yield return M33;\n            }\n        }\n\n        public readonly IEnumerable<V4i> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n                yield return R3;\n            }\n        }\n\n        public readonly IEnumerable<V4i> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n                yield return C3;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M00,  M01,  M02,  M03); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n                M03 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M10,  M11,  M12,  M13); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n                M13 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M20,  M21,  M22,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n                M23 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i R3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M30,  M31,  M32,  M33); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M30 = value.X;\n                M31 = value.Y;\n                M32 = value.Z;\n                M33 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M00,  M10,  M20,  M30); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n                M30 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M01,  M11,  M21,  M31); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n                M31 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M02,  M12,  M22,  M32); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n                M32 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4i C3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4i( M03,  M13,  M23,  M33); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M03 = value.X;\n                M13 = value.Y;\n                M23 = value.Z;\n                M33 = value.W;\n            }\n        }\n\n        public readonly V4i Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4i(M00, M11, M22, M33);\n        }\n\n        public readonly V4i AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4i(M03, M12, M21, M30);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly int MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly int MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33);\n        }\n\n        public unsafe int this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe int this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &M00) { return ptr[row * 4 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &M00) { ptr[row * 4 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 4;\n        public const int ColumnCount = 4;\n        public const int ElementCount = 4 * 4;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(4, 4);\n        }\n\n        public static M44i Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M44i(0);\n        }\n\n        public static M44i Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M44i(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly int Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + Fun.Abs(M03) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + Fun.Abs(M13) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22) + Fun.Abs(M23) + \n                    Fun.Abs(M30) + Fun.Abs(M31) + Fun.Abs(M32) + Fun.Abs(M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + M03 * M03 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + M13 * M13 + \n                    M20 * M20 + M21 * M21 + M22 * M22 + M23 * M23 + \n                    M30 * M30 + M31 * M31 + M32 * M32 + M33 * M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)), \n                            Fun.Max(\n                                Fun.Abs(M30), \n                                Fun.Abs(M31), \n                                Fun.Abs(M32), \n                                Fun.Abs(M33)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly int NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)), \n                            Fun.Min(\n                                Fun.Abs(M30), \n                                Fun.Abs(M31), \n                                Fun.Abs(M32), \n                                Fun.Abs(M33)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator -(M44i m)\n        {\n            return new M44i(\n                -m.M00, -m.M01, -m.M02, -m.M03, \n                -m.M10, -m.M11, -m.M12, -m.M13, \n                -m.M20, -m.M21, -m.M22, -m.M23, \n                -m.M30, -m.M31, -m.M32, -m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  + (M44i a, M44i b)\n        {\n            return new M44i(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  + (M44i m, int s)\n        {\n            return new M44i(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  + (int s, M44i m)\n        {\n            return new M44i(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  + (M44i a, M44l b)\n        {\n            return new M44l(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  + (M44i m, long s)\n        {\n            return new M44l(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  + (long s, M44i m)\n        {\n            return new M44l(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (M44i a, M44f b)\n        {\n            return new M44f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (M44i m, float s)\n        {\n            return new M44f(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (float s, M44i m)\n        {\n            return new M44f(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (M44i a, M44d b)\n        {\n            return new M44d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (M44i m, double s)\n        {\n            return new M44d(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (double s, M44i m)\n        {\n            return new M44d(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  - (M44i a, M44i b)\n        {\n            return new M44i(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  - (M44i m, int s)\n        {\n            return new M44i(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  - (int s, M44i m)\n        {\n            return new M44i(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  - (M44i a, M44l b)\n        {\n            return new M44l(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  - (M44i m, long s)\n        {\n            return new M44l(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  - (long s, M44i m)\n        {\n            return new M44l(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (M44i a, M44f b)\n        {\n            return new M44f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (M44i m, float s)\n        {\n            return new M44f(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (float s, M44i m)\n        {\n            return new M44f(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (M44i a, M44d b)\n        {\n            return new M44d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (M44i m, double s)\n        {\n            return new M44d(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (double s, M44i m)\n        {\n            return new M44d(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  % (M44i a, M44i b)\n        {\n            return new M44i(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  % (M44i m, int s)\n        {\n            return new M44i(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  % (int s, M44i m)\n        {\n            return new M44i(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  % (M44i a, M44l b)\n        {\n            return new M44l(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  % (M44i m, long s)\n        {\n            return new M44l(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  % (long s, M44i m)\n        {\n            return new M44l(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (M44i a, M44f b)\n        {\n            return new M44f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (M44i m, float s)\n        {\n            return new M44f(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (float s, M44i m)\n        {\n            return new M44f(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (M44i a, M44d b)\n        {\n            return new M44d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (M44i m, double s)\n        {\n            return new M44d(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (double s, M44i m)\n        {\n            return new M44d(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  / (M44i a, M44i b)\n        {\n            return new M44i(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  / (M44i m, int s)\n        {\n            return new M44i(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  / (int s, M44i m)\n        {\n            return new M44i(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  / (M44i a, M44l b)\n        {\n            return new M44l(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  / (M44i m, long s)\n        {\n            return new M44l(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  / (long s, M44i m)\n        {\n            return new M44l(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (M44i a, M44f b)\n        {\n            return new M44f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (M44i m, float s)\n        {\n            return new M44f(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (float s, M44i m)\n        {\n            return new M44f(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (M44i a, M44d b)\n        {\n            return new M44d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (M44i m, double s)\n        {\n            return new M44d(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (double s, M44i m)\n        {\n            return new M44d(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  * (M44i m, int s)\n        {\n            return new M44i(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator  * (int s, M44i m)\n        {\n            return new M44i(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  * (M44i m, long s)\n        {\n            return new M44l(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  * (long s, M44i m)\n        {\n            return new M44l(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  * (M44i m, float s)\n        {\n            return new M44f(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  * (float s, M44i m)\n        {\n            return new M44f(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  * (M44i m, double s)\n        {\n            return new M44d(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  * (double s, M44i m)\n        {\n            return new M44d(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator ~(M44i m)\n        {\n            return new M44i(\n                ~m.M00, ~m.M01, ~m.M02, ~m.M03, \n                ~m.M10, ~m.M11, ~m.M12, ~m.M13, \n                ~m.M20, ~m.M21, ~m.M22, ~m.M23, \n                ~m.M30, ~m.M31, ~m.M32, ~m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator <<(M44i a, int s)\n        {\n            return new M44i(\n                a.M00 << s, a.M01 << s, a.M02 << s, a.M03 << s, \n                a.M10 << s, a.M11 << s, a.M12 << s, a.M13 << s, \n                a.M20 << s, a.M21 << s, a.M22 << s, a.M23 << s, \n                a.M30 << s, a.M31 << s, a.M32 << s, a.M33 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator >>(M44i a, int s)\n        {\n            return new M44i(\n                a.M00 >> s, a.M01 >> s, a.M02 >> s, a.M03 >> s, \n                a.M10 >> s, a.M11 >> s, a.M12 >> s, a.M13 >> s, \n                a.M20 >> s, a.M21 >> s, a.M22 >> s, a.M23 >> s, \n                a.M30 >> s, a.M31 >> s, a.M32 >> s, a.M33 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator &(M44i a, M44i b)\n        {\n            return new M44i(\n                a.M00 & b.M00, a.M01 & b.M01, a.M02 & b.M02, a.M03 & b.M03, \n                a.M10 & b.M10, a.M11 & b.M11, a.M12 & b.M12, a.M13 & b.M13, \n                a.M20 & b.M20, a.M21 & b.M21, a.M22 & b.M22, a.M23 & b.M23, \n                a.M30 & b.M30, a.M31 & b.M31, a.M32 & b.M32, a.M33 & b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator &(M44i a, int s)\n        {\n            return new M44i(\n                a.M00 & s, a.M01 & s, a.M02 & s, a.M03 & s, \n                a.M10 & s, a.M11 & s, a.M12 & s, a.M13 & s, \n                a.M20 & s, a.M21 & s, a.M22 & s, a.M23 & s, \n                a.M30 & s, a.M31 & s, a.M32 & s, a.M33 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator &(int s, M44i a)\n        {\n            return new M44i(\n                s & a.M00, s & a.M01, s & a.M02, s & a.M03, \n                s & a.M10, s & a.M11, s & a.M12, s & a.M13, \n                s & a.M20, s & a.M21, s & a.M22, s & a.M23, \n                s & a.M30, s & a.M31, s & a.M32, s & a.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator |(M44i a, M44i b)\n        {\n            return new M44i(\n                a.M00 | b.M00, a.M01 | b.M01, a.M02 | b.M02, a.M03 | b.M03, \n                a.M10 | b.M10, a.M11 | b.M11, a.M12 | b.M12, a.M13 | b.M13, \n                a.M20 | b.M20, a.M21 | b.M21, a.M22 | b.M22, a.M23 | b.M23, \n                a.M30 | b.M30, a.M31 | b.M31, a.M32 | b.M32, a.M33 | b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator |(M44i a, int s)\n        {\n            return new M44i(\n                a.M00 | s, a.M01 | s, a.M02 | s, a.M03 | s, \n                a.M10 | s, a.M11 | s, a.M12 | s, a.M13 | s, \n                a.M20 | s, a.M21 | s, a.M22 | s, a.M23 | s, \n                a.M30 | s, a.M31 | s, a.M32 | s, a.M33 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator |(int s, M44i a)\n        {\n            return new M44i(\n                s | a.M00, s | a.M01, s | a.M02, s | a.M03, \n                s | a.M10, s | a.M11, s | a.M12, s | a.M13, \n                s | a.M20, s | a.M21, s | a.M22, s | a.M23, \n                s | a.M30, s | a.M31, s | a.M32, s | a.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator ^(M44i a, M44i b)\n        {\n            return new M44i(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, a.M02 ^ b.M02, a.M03 ^ b.M03, \n                a.M10 ^ b.M10, a.M11 ^ b.M11, a.M12 ^ b.M12, a.M13 ^ b.M13, \n                a.M20 ^ b.M20, a.M21 ^ b.M21, a.M22 ^ b.M22, a.M23 ^ b.M23, \n                a.M30 ^ b.M30, a.M31 ^ b.M31, a.M32 ^ b.M32, a.M33 ^ b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator ^(M44i a, int s)\n        {\n            return new M44i(\n                a.M00 ^ s, a.M01 ^ s, a.M02 ^ s, a.M03 ^ s, \n                a.M10 ^ s, a.M11 ^ s, a.M12 ^ s, a.M13 ^ s, \n                a.M20 ^ s, a.M21 ^ s, a.M22 ^ s, a.M23 ^ s, \n                a.M30 ^ s, a.M31 ^ s, a.M32 ^ s, a.M33 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i operator ^(int s, M44i a)\n        {\n            return new M44i(\n                s ^ a.M00, s ^ a.M01, s ^ a.M02, s ^ a.M03, \n                s ^ a.M10, s ^ a.M11, s ^ a.M12, s ^ a.M13, \n                s ^ a.M20, s ^ a.M21, s ^ a.M22, s ^ a.M23, \n                s ^ a.M30, s ^ a.M31, s ^ a.M32, s ^ a.M33);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M44i matrix with a V4i column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator *(M44i m, V4i v)\n        {\n            return new V4i(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z + m.M03 * v.W, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z + m.M13 * v.W, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z + m.M23 * v.W, \n                m.M30 * v.X + m.M31 * v.Y + m.M32 * v.Z + m.M33 * v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a V4i row vector with a M44i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator *(V4i v, M44i m)\n        {\n            return new V4i(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20 + v.W * m.M30, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21 + v.W * m.M31, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22 + v.W * m.M32, \n                v.X * m.M03 + v.Y * m.M13 + v.Z * m.M23 + v.W * m.M33);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M44i a, M44i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23 && \n                a.M30 == b.M30 && \n                a.M31 == b.M31 && \n                a.M32 == b.M32 && \n                a.M33 == b.M33;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M44i a, int s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M03 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M13 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s && \n                a.M23 == s && \n                a.M30 == s && \n                a.M31 == s && \n                a.M32 == s && \n                a.M33 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(int s, M44i a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M03  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M13  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22  && \n                s == a.M23  && \n                s == a.M30  && \n                s == a.M31  && \n                s == a.M32  && \n                s == a.M33 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M44i a, M44i b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M44i m, int s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(int s, M44i m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02, M03),\n                        HashCode.GetCombined(M10, M11, M12, M13),\n                        HashCode.GetCombined(M20, M21, M22, M23),\n                        HashCode.GetCombined(M30, M31, M32, M33));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M44i other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && M03.Equals(other.M03) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && M13.Equals(other.M13) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22) && M23.Equals(other.M23) && \n                M30.Equals(other.M30) && M31.Equals(other.M31) && M32.Equals(other.M32) && M33.Equals(other.M33);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M44i o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R3.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M44i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M44i.FromRows(\n                V4i.Parse(x[0]), \n                V4i.Parse(x[1]), \n                V4i.Parse(x[2]), \n                V4i.Parse(x[3])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M44i Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                M44i result = new M44i();\n                for (int row = 0; row < 4; row++)\n                {\n                    for (int col = 0; col < 4; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly int Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 + M22 + M33 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly int Determinant\n        {\n            get\n            {\n                // using bottom row because elements M30, M31, and M32\n                // are zero most of the time.\n                int d = 0;\n                if (M30 != 0.0f) d -= M30 * (\n                M01 * M12 * M23 + M02 * M13 * M21 + M03 * M11 * M22\n                - M21 * M12 * M03 - M22 * M13 * M01 - M23 * M11 * M02\n                );\n                if (M31 != 0.0f) d += M31 * (\n                M00 * M12 * M23 + M02 * M13 * M20 + M03 * M10 * M22\n                - M20 * M12 * M03 - M22 * M13 * M00 - M23 * M10 * M02\n                );\n                if (M32 != 0.0f) d -= M32 * (\n                M00 * M11 * M23 + M01 * M13 * M20 + M03 * M10 * M21\n                - M20 * M11 * M03 - M21 * M13 * M00 - M23 * M10 * M01\n                );\n                if (M33 != 0.0f) d += M33 * (\n                M00 * M11 * M22 + M01 * M12 * M20 + M02 * M10 * M21\n                - M20 * M11 * M02 - M21 * M12 * M00 - M22 * M10 * M01\n                );\n                return d;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M44i Transposed\n        {\n            get\n            {\n                return new M44i {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    M02 = M20, \n                    M03 = M30, \n                    \n                    M10 = M01, \n                    M11 = M11, \n                    M12 = M21, \n                    M13 = M31, \n                    \n                    M20 = M02, \n                    M21 = M12, \n                    M22 = M22, \n                    M23 = M32, \n                    \n                    M30 = M03, \n                    M31 = M13, \n                    M32 = M23, \n                    M33 = M33\n                };\n            }\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M44i operator *(M44i a, M44i b)\n        {\n            return new M44i(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20 + a.M03 * b.M30, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21 + a.M03 * b.M31, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22 + a.M03 * b.M32, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03 * b.M33, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20 + a.M13 * b.M30, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20 + a.M23 * b.M30, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33, \n                a.M30 * b.M00 + a.M31 * b.M10 + a.M32 * b.M20 + a.M33 * b.M30, \n                a.M30 * b.M01 + a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31, \n                a.M30 * b.M02 + a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32, \n                a.M30 * b.M03 + a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (int)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (int)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (int)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (int)value;\n        }\n\n        #endregion\n    }\n\n    public class M44iEqualityComparer : IEqualityComparer<M44i>\n    {\n        public static readonly M44iEqualityComparer Default\n            = new M44iEqualityComparer();\n\n        #region IEqualityComparer<M44i> Members\n\n        public bool Equals(M44i v0, M44i v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M44i v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M44i m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length + m.C3.Length) / 4;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d GetScaleVector(this M44i m)\n            => new V4d(m.C0.Length, m.C1.Length, m.C2.Length, m.C3.Length);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of 3D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale3(this M44i m)\n            => (m.C0.XYZ.Length + m.C1.XYZ.Length + m.C2.XYZ.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the 3D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector3(this M44i m)\n            => new V3d(m.C0.XYZ.Length, m.C1.XYZ.Length, m.C2.XYZ.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Norm1(M44i m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M44i m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMax(M44i m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMin(M44i m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M44i m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M03).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M13).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p) + \n                Fun.Abs(m.M23).Pow(p) + \n                Fun.Abs(m.M30).Pow(p) + \n                Fun.Abs(m.M31).Pow(p) + \n                Fun.Abs(m.M32).Pow(p) + \n                Fun.Abs(m.M33).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static int Distance1(this M44i a, M44i b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M03 - a.M03) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M13 - a.M13) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22) + \n                Fun.Abs(b.M23 - a.M23) + \n                Fun.Abs(b.M30 - a.M30) + \n                Fun.Abs(b.M31 - a.M31) + \n                Fun.Abs(b.M32 - a.M32) + \n                Fun.Abs(b.M33 - a.M33);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M44i a, M44i b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M03 - a.M03) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M13 - a.M13) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22) + \n                        Fun.Square(b.M23 - a.M23) + \n                        Fun.Square(b.M30 - a.M30) + \n                        Fun.Square(b.M31 - a.M31) + \n                        Fun.Square(b.M32 - a.M32) + \n                        Fun.Square(b.M33 - a.M33));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M44i a, M44i b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M03 - a.M03).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M13 - a.M13).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p) + \n                Fun.Abs(b.M23 - a.M23).Pow(p) + \n                Fun.Abs(b.M30 - a.M30).Pow(p) + \n                Fun.Abs(b.M31 - a.M31).Pow(p) + \n                Fun.Abs(b.M32 - a.M32).Pow(p) + \n                Fun.Abs(b.M33 - a.M33).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMax(this M44i a, M44i b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)), \n                        Fun.Max(\n                            Fun.Abs(b.M30 - a.M30), \n                            Fun.Abs(b.M31 - a.M31), \n                            Fun.Abs(b.M32 - a.M32), \n                            Fun.Abs(b.M33 - a.M33)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static int DistanceMin(this M44i a, M44i b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)), \n                        Fun.Min(\n                            Fun.Abs(b.M30 - a.M30), \n                            Fun.Abs(b.M31 - a.M31), \n                            Fun.Abs(b.M32 - a.M32), \n                            Fun.Abs(b.M33 - a.M33)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Transform(this M44i m, V4i v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i TransposedTransform(this M44i m, V4i v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V3i TransformDir(this M44i m, V3i v)\n        {\n            return new V3i(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V3i TransformPos(this M44i m, V3i p)\n        {\n            return new V3i(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V3i TransformPosProj(this M44i m, V3i p)\n        {\n            int s = m.M30 * p.X + m.M31 * p.Y + m.M32 * p.Z + m.M33;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V4i TransformPosProjFull(this M44i m, V3i p)\n        {\n            return new V4i(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23, \n                m.M30 * p.X + m.M31 * p.Y + m.M32 * p.Z + m.M33\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static V3i TransposedTransformDir(this M44i m, V3i v)\n        {\n            return new V3i(\n                m.M00 * v.X + m.M10 * v.Y + m.M20 * v.Z, \n                m.M01 * v.X + m.M11 * v.Y + m.M21 * v.Z, \n                m.M02 * v.X + m.M12 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V3i TransposedTransformPos(this M44i m, V3i p)\n        {\n            return new V3i(\n                m.M00 * p.X + m.M10 * p.Y + m.M20 * p.Z + m.M30, \n                m.M01 * p.X + m.M11 * p.Y + m.M21 * p.Z + m.M31, \n                m.M02 * p.X + m.M12 * p.Y + m.M22 * p.Z + m.M32\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V3i TransposedTransformPosProj(this M44i m, V3i p)\n        {\n            var s = m.M03 * p.X + m.M13 * p.Y + m.M23 * p.Z + m.M33;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static V3i TransposedTransformProj(this M44i m, V3i p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V4i TransposedTransformPosProjFull(this M44i m, V3i p)\n        {\n            return new V4i(\n                m.M00 * p.X + m.M10 * p.Y + m.M20 * p.Z + m.M30, \n                m.M01 * p.X + m.M11 * p.Y + m.M21 * p.Z + m.M31, \n                m.M02 * p.X + m.M12 * p.Y + m.M22 * p.Z + m.M32, \n                m.M03 * p.X + m.M13 * p.Y + m.M23 * p.Z + m.M33\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static V4i TransposedTransformProjFull(this M44i m, V3i p)\n            => m.TransposedTransformPosProjFull(p);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M44i\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static M33i Minor(this M44i m, int row, int column)\n        {\n            M33i rs = new M33i();\n\n            for (int k = 0; k < 9; k++)\n            {\n                var i = k / 3;\n                var j = k % 3;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * 4 + jj];\n            }\n\n            return rs;\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4i Row(this M44i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V4i(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4i Column(this M44i m, int index)\n        {\n            int* ptr = &m.M00;\n            return new V4i(ptr[index], ptr[index + 4], ptr[index + 8], ptr[index + 12]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Determinant(M44i m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Transposed(M44i m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M44i m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n            Fun.Swap(ref m.M20, ref m.M02);\n            Fun.Swap(ref m.M21, ref m.M12);\n            Fun.Swap(ref m.M30, ref m.M03);\n            Fun.Swap(ref m.M31, ref m.M13);\n            Fun.Swap(ref m.M32, ref m.M23);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M44i a, M44i b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M03 < b.M03 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M13 < b.M13 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22 && \n                a.M23 < b.M23 && \n                a.M30 < b.M30 && \n                a.M31 < b.M31 && \n                a.M32 < b.M32 && \n                a.M33 < b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M44i m, int s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M03 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M13 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s && \n                m.M23 < s && \n                m.M30 < s && \n                m.M31 < s && \n                m.M32 < s && \n                m.M33 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(int s, M44i m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M03 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M13 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22 && \n                s < m.M23 && \n                s < m.M30 && \n                s < m.M31 && \n                s < m.M32 && \n                s < m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M44i a, M44i b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M03 < b.M03 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M13 < b.M13 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22 || \n                a.M23 < b.M23 || \n                a.M30 < b.M30 || \n                a.M31 < b.M31 || \n                a.M32 < b.M32 || \n                a.M33 < b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M44i m, int s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M03 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M13 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s || \n                m.M23 < s || \n                m.M30 < s || \n                m.M31 < s || \n                m.M32 < s || \n                m.M33 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(int s, M44i m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M03 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M13 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22 || \n                s < m.M23 || \n                s < m.M30 || \n                s < m.M31 || \n                s < m.M32 || \n                s < m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M44i a, M44i b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M03 > b.M03 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M13 > b.M13 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22 && \n                a.M23 > b.M23 && \n                a.M30 > b.M30 && \n                a.M31 > b.M31 && \n                a.M32 > b.M32 && \n                a.M33 > b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M44i m, int s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M03 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M13 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s && \n                m.M23 > s && \n                m.M30 > s && \n                m.M31 > s && \n                m.M32 > s && \n                m.M33 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(int s, M44i m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M03 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M13 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22 && \n                s > m.M23 && \n                s > m.M30 && \n                s > m.M31 && \n                s > m.M32 && \n                s > m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M44i a, M44i b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M03 > b.M03 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M13 > b.M13 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22 || \n                a.M23 > b.M23 || \n                a.M30 > b.M30 || \n                a.M31 > b.M31 || \n                a.M32 > b.M32 || \n                a.M33 > b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M44i m, int s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M03 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M13 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s || \n                m.M23 > s || \n                m.M30 > s || \n                m.M31 > s || \n                m.M32 > s || \n                m.M33 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(int s, M44i m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M03 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M13 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22 || \n                s > m.M23 || \n                s > m.M30 || \n                s > m.M31 || \n                s > m.M32 || \n                s > m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M44i a, M44i b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M03 <= b.M03 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M13 <= b.M13 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22 && \n                a.M23 <= b.M23 && \n                a.M30 <= b.M30 && \n                a.M31 <= b.M31 && \n                a.M32 <= b.M32 && \n                a.M33 <= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M44i m, int s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M03 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M13 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s && \n                m.M23 <= s && \n                m.M30 <= s && \n                m.M31 <= s && \n                m.M32 <= s && \n                m.M33 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(int s, M44i m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M03 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M13 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22 && \n                s <= m.M23 && \n                s <= m.M30 && \n                s <= m.M31 && \n                s <= m.M32 && \n                s <= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M44i a, M44i b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M03 <= b.M03 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M13 <= b.M13 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22 || \n                a.M23 <= b.M23 || \n                a.M30 <= b.M30 || \n                a.M31 <= b.M31 || \n                a.M32 <= b.M32 || \n                a.M33 <= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M44i m, int s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M03 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M13 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s || \n                m.M23 <= s || \n                m.M30 <= s || \n                m.M31 <= s || \n                m.M32 <= s || \n                m.M33 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(int s, M44i m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M03 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M13 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22 || \n                s <= m.M23 || \n                s <= m.M30 || \n                s <= m.M31 || \n                s <= m.M32 || \n                s <= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M44i a, M44i b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M03 >= b.M03 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M13 >= b.M13 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22 && \n                a.M23 >= b.M23 && \n                a.M30 >= b.M30 && \n                a.M31 >= b.M31 && \n                a.M32 >= b.M32 && \n                a.M33 >= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M44i m, int s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M03 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M13 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s && \n                m.M23 >= s && \n                m.M30 >= s && \n                m.M31 >= s && \n                m.M32 >= s && \n                m.M33 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(int s, M44i m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M03 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M13 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22 && \n                s >= m.M23 && \n                s >= m.M30 && \n                s >= m.M31 && \n                s >= m.M32 && \n                s >= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M44i a, M44i b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M03 >= b.M03 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M13 >= b.M13 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22 || \n                a.M23 >= b.M23 || \n                a.M30 >= b.M30 || \n                a.M31 >= b.M31 || \n                a.M32 >= b.M32 || \n                a.M33 >= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M44i m, int s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M03 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M13 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s || \n                m.M23 >= s || \n                m.M30 >= s || \n                m.M31 >= s || \n                m.M32 >= s || \n                m.M33 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(int s, M44i m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M03 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M13 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22 || \n                s >= m.M23 || \n                s >= m.M30 || \n                s >= m.M31 || \n                s >= m.M32 || \n                s >= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M44i a, M44i b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23 && \n                a.M30 == b.M30 && \n                a.M31 == b.M31 && \n                a.M32 == b.M32 && \n                a.M33 == b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M44i m, int s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M03 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M13 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s && \n                m.M23 == s && \n                m.M30 == s && \n                m.M31 == s && \n                m.M32 == s && \n                m.M33 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(int s, M44i m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M03 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M13 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22 && \n                s == m.M23 && \n                s == m.M30 && \n                s == m.M31 && \n                s == m.M32 && \n                s == m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M44i a, M44i b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M03 == b.M03 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M13 == b.M13 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22 || \n                a.M23 == b.M23 || \n                a.M30 == b.M30 || \n                a.M31 == b.M31 || \n                a.M32 == b.M32 || \n                a.M33 == b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M44i m, int s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M03 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M13 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s || \n                m.M23 == s || \n                m.M30 == s || \n                m.M31 == s || \n                m.M32 == s || \n                m.M33 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(int s, M44i m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M03 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M13 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22 || \n                s == m.M23 || \n                s == m.M30 || \n                s == m.M31 || \n                s == m.M32 || \n                s == m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M44i a, M44i b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M03 != b.M03 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M13 != b.M13 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22 && \n                a.M23 != b.M23 && \n                a.M30 != b.M30 && \n                a.M31 != b.M31 && \n                a.M32 != b.M32 && \n                a.M33 != b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M44i m, int s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M03 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M13 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s && \n                m.M23 != s && \n                m.M30 != s && \n                m.M31 != s && \n                m.M32 != s && \n                m.M33 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(int s, M44i m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M03 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M13 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22 && \n                s != m.M23 && \n                s != m.M30 && \n                s != m.M31 && \n                s != m.M32 && \n                s != m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M44i a, M44i b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M03 != b.M03 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M13 != b.M13 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22 || \n                a.M23 != b.M23 || \n                a.M30 != b.M30 || \n                a.M31 != b.M31 || \n                a.M32 != b.M32 || \n                a.M33 != b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M44i m, int s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M03 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M13 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s || \n                m.M23 != s || \n                m.M30 != s || \n                m.M31 != s || \n                m.M32 != s || \n                m.M33 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(int s, M44i m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M03 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M13 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22 || \n                s != m.M23 || \n                s != m.M30 || \n                s != m.M31 || \n                s != m.M32 || \n                s != m.M33;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M44i m0, M44i m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M03 < m1.M03) return -1;\n            if (m0.M03 > m1.M03) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M13 < m1.M13) return -1;\n            if (m0.M13 > m1.M13) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            if (m0.M23 < m1.M23) return -1;\n            if (m0.M23 > m1.M23) return +1;\n            if (m0.M30 < m1.M30) return -1;\n            if (m0.M30 > m1.M30) return +1;\n            if (m0.M31 < m1.M31) return -1;\n            if (m0.M31 > m1.M31) return +1;\n            if (m0.M32 < m1.M32) return -1;\n            if (m0.M32 > m1.M32) return +1;\n            if (m0.M33 < m1.M33) return -1;\n            if (m0.M33 > m1.M33) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M44i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MinElement(M44i m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M44i\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MaxElement(M44i m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M44i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M44i m, int epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M03.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M13.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon) || m.M23.IsTiny(epsilon) || m.M30.IsTiny(epsilon) || m.M31.IsTiny(epsilon) || m.M32.IsTiny(epsilon) || m.M33.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M44i m, int epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M03.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M13.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon) && m.M23.IsTiny(epsilon) && m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon) && m.M33.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M44i a, M44i b, int epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M44i m, int epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM44iExtensions\n    {\n        #region IRandomUniform extensions for M44i\n\n        /// <summary>\n        /// Uses UniformInt() to generate the elements of an M44i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i UniformM44i(this IRandomUniform rnd)\n        {\n            return new M44i(\n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), \n                rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt());\n        }\n\n        /// <summary>\n        /// Uses UniformIntNonZero() to generate the elements of an M44i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i UniformM44iNonZero(this IRandomUniform rnd)\n        {\n            return new M44i(\n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), \n                rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M44i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i UniformM44i(this IRandomUniform rnd, int size)\n        {\n            return new M44i(\n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), \n                rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size));\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of an M44i matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i UniformM44i(this IRandomUniform rnd, M44i size)\n        {\n            return new M44i(\n                rnd.UniformInt(size.M00), rnd.UniformInt(size.M01), rnd.UniformInt(size.M02), rnd.UniformInt(size.M03), \n                rnd.UniformInt(size.M10), rnd.UniformInt(size.M11), rnd.UniformInt(size.M12), rnd.UniformInt(size.M13), \n                rnd.UniformInt(size.M20), rnd.UniformInt(size.M21), rnd.UniformInt(size.M22), rnd.UniformInt(size.M23), \n                rnd.UniformInt(size.M30), rnd.UniformInt(size.M31), rnd.UniformInt(size.M32), rnd.UniformInt(size.M33));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M44l\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M44l : IEquatable<M44l>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public long M00, M01, M02, M03;\n        [DataMember]\n        public long M10, M11, M12, M13;\n        [DataMember]\n        public long M20, M21, M22, M23;\n        [DataMember]\n        public long M30, M31, M32, M33;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(long value)\n        {\n            M00 = value; M01 = 0; M02 = 0; M03 = 0; \n            M10 = 0; M11 = value; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = value; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(\n                long m00, long m01, long m02, long m03, \n                long m10, long m11, long m12, long m13, \n                long m20, long m21, long m22, long m23, \n                long m30, long m31, long m32, long m33)\n        {\n            M00 = m00; M01 = m01; M02 = m02; M03 = m03; \n            M10 = m10; M11 = m11; M12 = m12; M13 = m13; \n            M20 = m20; M21 = m21; M22 = m22; M23 = m23; \n            M30 = m30; M31 = m31; M32 = m32; M33 = m33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(long[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M03 = a[3];\n            M10 = a[4];\n            M11 = a[5];\n            M12 = a[6];\n            M13 = a[7];\n            M20 = a[8];\n            M21 = a[9];\n            M22 = a[10];\n            M23 = a[11];\n            M30 = a[12];\n            M31 = a[13];\n            M32 = a[14];\n            M33 = a[15];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(long[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M03 = a[start + 3];\n            M10 = a[start + 4];\n            M11 = a[start + 5];\n            M12 = a[start + 6];\n            M13 = a[start + 7];\n            M20 = a[start + 8];\n            M21 = a[start + 9];\n            M22 = a[start + 10];\n            M23 = a[start + 11];\n            M30 = a[start + 12];\n            M31 = a[start + 13];\n            M32 = a[start + 14];\n            M33 = a[start + 15];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M22i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M23i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M33i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M34i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M44i m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n            M30 = (long)m.M30; M31 = (long)m.M31; M32 = (long)m.M32; M33 = (long)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M22l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M23l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M33l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M34l m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = m.M03; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = m.M13; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M22f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M23f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M33f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M34f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M44f m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n            M30 = (long)m.M30; M31 = (long)m.M31; M32 = (long)m.M32; M33 = (long)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M22d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = 0; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M23d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M33d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = 0; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = 0; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M34d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44l(M44d m)\n        {\n            M00 = (long)m.M00; M01 = (long)m.M01; M02 = (long)m.M02; M03 = (long)m.M03; \n            M10 = (long)m.M10; M11 = (long)m.M11; M12 = (long)m.M12; M13 = (long)m.M13; \n            M20 = (long)m.M20; M21 = (long)m.M21; M22 = (long)m.M22; M23 = (long)m.M23; \n            M30 = (long)m.M30; M31 = (long)m.M31; M32 = (long)m.M32; M33 = (long)m.M33; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M44l(M22i m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M23i m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M33i m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M34i m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M44i m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n                M30 = (long)m.M30, M31 = (long)m.M31, M32 = (long)m.M32, M33 = (long)m.M33, \n            };\n        }\n\n        public static explicit operator M44l(M22l m)\n        {\n            return new M44l {\n                M00 = m.M00, M01 = m.M01, M02 = 0, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M23l m)\n        {\n            return new M44l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M33l m)\n        {\n            return new M44l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M34l m)\n        {\n            return new M44l {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = m.M03, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = m.M13, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M22f m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M23f m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M33f m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M34f m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M44f m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n                M30 = (long)m.M30, M31 = (long)m.M31, M32 = (long)m.M32, M33 = (long)m.M33, \n            };\n        }\n\n        public static explicit operator M44l(M22d m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = 0, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M23d m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M33d m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = 0, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = 0, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M34d m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44l(M44d m)\n        {\n            return new M44l {\n                M00 = (long)m.M00, M01 = (long)m.M01, M02 = (long)m.M02, M03 = (long)m.M03, \n                M10 = (long)m.M10, M11 = (long)m.M11, M12 = (long)m.M12, M13 = (long)m.M13, \n                M20 = (long)m.M20, M21 = (long)m.M21, M22 = (long)m.M22, M23 = (long)m.M23, \n                M30 = (long)m.M30, M31 = (long)m.M31, M32 = (long)m.M32, M33 = (long)m.M33, \n            };\n        }\n\n        public static explicit operator M44l(int[] a)\n        {\n            return new M44l(\n                (long)a[0], (long)a[1], (long)a[2], (long)a[3], \n                (long)a[4], (long)a[5], (long)a[6], (long)a[7], \n                (long)a[8], (long)a[9], (long)a[10], (long)a[11], \n                (long)a[12], (long)a[13], (long)a[14], (long)a[15]);\n        }\n\n        public static explicit operator M44l(int[,] a)\n        {\n            return new M44l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], (long)a[0, 3], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], (long)a[1, 3], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2], (long)a[2, 3], \n                (long)a[3, 0], (long)a[3, 1], (long)a[3, 2], (long)a[3, 3]);\n        }\n\n        public static explicit operator int[](M44l m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03, \n                (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13, \n                (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23, \n                (int)m.M30, (int)m.M31, (int)m.M32, (int)m.M33\n            };\n        }\n\n        public static explicit operator int[,](M44l m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23 }, \n                { (int)m.M30, (int)m.M31, (int)m.M32, (int)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M03;\n            array[index + 4] = (int)M10;\n            array[index + 5] = (int)M11;\n            array[index + 6] = (int)M12;\n            array[index + 7] = (int)M13;\n            array[index + 8] = (int)M20;\n            array[index + 9] = (int)M21;\n            array[index + 10] = (int)M22;\n            array[index + 11] = (int)M23;\n            array[index + 12] = (int)M30;\n            array[index + 13] = (int)M31;\n            array[index + 14] = (int)M32;\n            array[index + 15] = (int)M33;\n        }\n\n        public static explicit operator M44l(long[] a)\n        {\n            return new M44l(\n                a[0], a[1], a[2], a[3], \n                a[4], a[5], a[6], a[7], \n                a[8], a[9], a[10], a[11], \n                a[12], a[13], a[14], a[15]);\n        }\n\n        public static explicit operator M44l(long[,] a)\n        {\n            return new M44l(\n                a[0, 0], a[0, 1], a[0, 2], a[0, 3], \n                a[1, 0], a[1, 1], a[1, 2], a[1, 3], \n                a[2, 0], a[2, 1], a[2, 2], a[2, 3], \n                a[3, 0], a[3, 1], a[3, 2], a[3, 3]);\n        }\n\n        public static explicit operator long[](M44l m)\n        {\n            return new long[] {\n                m.M00, m.M01, m.M02, m.M03, \n                m.M10, m.M11, m.M12, m.M13, \n                m.M20, m.M21, m.M22, m.M23, \n                m.M30, m.M31, m.M32, m.M33\n            };\n        }\n\n        public static explicit operator long[,](M44l m)\n        {\n            return new long[,] {\n                { m.M00, m.M01, m.M02, m.M03 }, \n                { m.M10, m.M11, m.M12, m.M13 }, \n                { m.M20, m.M21, m.M22, m.M23 }, \n                { m.M30, m.M31, m.M32, m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M03;\n            array[index + 4] = M10;\n            array[index + 5] = M11;\n            array[index + 6] = M12;\n            array[index + 7] = M13;\n            array[index + 8] = M20;\n            array[index + 9] = M21;\n            array[index + 10] = M22;\n            array[index + 11] = M23;\n            array[index + 12] = M30;\n            array[index + 13] = M31;\n            array[index + 14] = M32;\n            array[index + 15] = M33;\n        }\n\n        public static explicit operator M44l(float[] a)\n        {\n            return new M44l(\n                (long)a[0], (long)a[1], (long)a[2], (long)a[3], \n                (long)a[4], (long)a[5], (long)a[6], (long)a[7], \n                (long)a[8], (long)a[9], (long)a[10], (long)a[11], \n                (long)a[12], (long)a[13], (long)a[14], (long)a[15]);\n        }\n\n        public static explicit operator M44l(float[,] a)\n        {\n            return new M44l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], (long)a[0, 3], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], (long)a[1, 3], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2], (long)a[2, 3], \n                (long)a[3, 0], (long)a[3, 1], (long)a[3, 2], (long)a[3, 3]);\n        }\n\n        public static explicit operator float[](M44l m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03, \n                (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13, \n                (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23, \n                (float)m.M30, (float)m.M31, (float)m.M32, (float)m.M33\n            };\n        }\n\n        public static explicit operator float[,](M44l m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23 }, \n                { (float)m.M30, (float)m.M31, (float)m.M32, (float)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M03;\n            array[index + 4] = (float)M10;\n            array[index + 5] = (float)M11;\n            array[index + 6] = (float)M12;\n            array[index + 7] = (float)M13;\n            array[index + 8] = (float)M20;\n            array[index + 9] = (float)M21;\n            array[index + 10] = (float)M22;\n            array[index + 11] = (float)M23;\n            array[index + 12] = (float)M30;\n            array[index + 13] = (float)M31;\n            array[index + 14] = (float)M32;\n            array[index + 15] = (float)M33;\n        }\n\n        public static explicit operator M44l(double[] a)\n        {\n            return new M44l(\n                (long)a[0], (long)a[1], (long)a[2], (long)a[3], \n                (long)a[4], (long)a[5], (long)a[6], (long)a[7], \n                (long)a[8], (long)a[9], (long)a[10], (long)a[11], \n                (long)a[12], (long)a[13], (long)a[14], (long)a[15]);\n        }\n\n        public static explicit operator M44l(double[,] a)\n        {\n            return new M44l(\n                (long)a[0, 0], (long)a[0, 1], (long)a[0, 2], (long)a[0, 3], \n                (long)a[1, 0], (long)a[1, 1], (long)a[1, 2], (long)a[1, 3], \n                (long)a[2, 0], (long)a[2, 1], (long)a[2, 2], (long)a[2, 3], \n                (long)a[3, 0], (long)a[3, 1], (long)a[3, 2], (long)a[3, 3]);\n        }\n\n        public static explicit operator double[](M44l m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03, \n                (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13, \n                (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23, \n                (double)m.M30, (double)m.M31, (double)m.M32, (double)m.M33\n            };\n        }\n\n        public static explicit operator double[,](M44l m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23 }, \n                { (double)m.M30, (double)m.M31, (double)m.M32, (double)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M03;\n            array[index + 4] = (double)M10;\n            array[index + 5] = (double)M11;\n            array[index + 6] = (double)M12;\n            array[index + 7] = (double)M13;\n            array[index + 8] = (double)M20;\n            array[index + 9] = (double)M21;\n            array[index + 10] = (double)M22;\n            array[index + 11] = (double)M23;\n            array[index + 12] = (double)M30;\n            array[index + 13] = (double)M31;\n            array[index + 14] = (double)M32;\n            array[index + 15] = (double)M33;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44i Copy(Func<long, int> element_fun)\n        {\n            return new M44i(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44i Copy(Func<long, int, int, int> element_index0_index1_fun)\n        {\n            return new M44i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44l Copy(Func<long, long> element_fun)\n        {\n            return new M44l(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44l Copy(Func<long, int, int, long> element_index0_index1_fun)\n        {\n            return new M44l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44f Copy(Func<long, float> element_fun)\n        {\n            return new M44f(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44f Copy(Func<long, int, int, float> element_index0_index1_fun)\n        {\n            return new M44f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44d Copy(Func<long, double> element_fun)\n        {\n            return new M44d(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44d Copy(Func<long, int, int, double> element_index0_index1_fun)\n        {\n            return new M44d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly M33l UpperLeftM33()\n        {\n            return (M33l)this;\n        }\n\n        public readonly long[] ToArray()\n        {\n            var array = new long[16];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M03;\n            array[4] = M10;\n            array[5] = M11;\n            array[6] = M12;\n            array[7] = M13;\n            array[8] = M20;\n            array[9] = M21;\n            array[10] = M22;\n            array[11] = M23;\n            array[12] = M30;\n            array[13] = M31;\n            array[14] = M32;\n            array[15] = M33;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l FromCols(V4l col0, V4l col1, V4l col2, V4l col3)\n        {\n            return new M44l(\n                col0.X, col1.X, col2.X, col3.X, \n                col0.Y, col1.Y, col2.Y, col3.Y, \n                col0.Z, col1.Z, col2.Z, col3.Z, \n                col0.W, col1.W, col2.W, col3.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l FromRows(V4l row0, V4l row1, V4l row2, V4l row3)\n        {\n            return new M44l(\n                row0.X, row0.Y, row0.Z, row0.W, \n                row1.X, row1.Y, row1.Z, row1.W, \n                row2.X, row2.Y, row2.Z, row2.W, \n                row3.X, row3.Y, row3.Z, row3.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l FromDiagonal(long value)\n        {\n            return new M44l(\n                value, 0, 0, 0, \n                0, value, 0, 0, \n                0, 0, value, 0, \n                0, 0, 0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l FromDiagonal(long m00, long m11, long m22, long m33)\n        {\n            return new M44l(\n                m00, 0, 0, 0, \n                0, m11, 0, 0, \n                0, 0, m22, 0, \n                0, 0, 0, m33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l FromDiagonal(V4l s)\n        {\n            return new M44l(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, s.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l FromAntiDiagonal(long value)\n        {\n            return new M44l(\n                 0, 0, 0, value, \n                 0, 0, value, 0, \n                 0, value, 0, 0, \n                 value, 0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l FromAntiDiagonal(long m03, long m12, long m21, long m30)\n        {\n            return new M44l(\n                0, 0, 0, m03, \n                0, 0, m12, 0, \n                0, m21, 0, 0, \n                m30, 0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l FromAntiDiagonal(V4l s)\n        {\n            return new M44l(\n                0, 0, 0, s.X, \n                0, 0, s.Y, 0, \n                0, s.Z, 0, 0, \n                s.W, 0, 0, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44l\"/> using 4 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Scale(long sX, long sY, long sZ, long sW)\n            => FromDiagonal(sX, sY, sZ, sW);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44l\"/> using a <see cref=\"V4l\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Scale(V4l s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M44l\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Scale(long s)\n        {\n            return new M44l(\n                s, 0, 0, 0, \n                0, s, 0, 0, \n                0, 0, s, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44l\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Scale(long sX, long sY, long sZ)\n        {\n            return new M44l(\n                sX, 0, 0, 0, \n                0, sY, 0, 0, \n                0, 0, sZ, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44l\"/> using a <see cref=\"V3l\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Scale(V3l s)\n        {\n            return new M44l(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44l\"/> with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Translation(long tX, long tY, long tZ)\n        {\n            return new M44l(\n                1, 0, 0, tX, \n                0, 1, 0, tY, \n                0, 0, 1, tZ, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44l\"/> with the translational component given by a <see cref=\"V3l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Translation(V3l t)\n        {\n            return new M44l(\n                1, 0, 0, t.X, \n                0, 1, 0, t.Y, \n                0, 0, 1, t.Z, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l ShearXY(long factorX, long factorY)\n        {\n            return new M44l(\n                1, 0, factorX, 0, \n                0, 1, factorY, 0, \n                0, 0, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l ShearXZ(long factorX, long factorZ)\n        {\n            return new M44l(\n                1, factorX, 0, 0, \n                0, 1, 0, 0, \n                0, factorZ, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l ShearYZ(long factorY, long factorZ)\n        {\n            return new M44l(\n                1, 0, 0, 0, \n                factorY, 1, 0, 0, \n                factorZ, 0, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l DivideByInt(M44l m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M03;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M13;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n                yield return M23;\n                yield return M30;\n                yield return M31;\n                yield return M32;\n                yield return M33;\n            }\n        }\n\n        public readonly IEnumerable<V4l> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n                yield return R3;\n            }\n        }\n\n        public readonly IEnumerable<V4l> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n                yield return C3;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M00,  M01,  M02,  M03); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n                M03 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M10,  M11,  M12,  M13); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n                M13 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M20,  M21,  M22,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n                M23 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l R3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M30,  M31,  M32,  M33); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M30 = value.X;\n                M31 = value.Y;\n                M32 = value.Z;\n                M33 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M00,  M10,  M20,  M30); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n                M30 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M01,  M11,  M21,  M31); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n                M31 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M02,  M12,  M22,  M32); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n                M32 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4l C3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4l( M03,  M13,  M23,  M33); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M03 = value.X;\n                M13 = value.Y;\n                M23 = value.Z;\n                M33 = value.W;\n            }\n        }\n\n        public readonly V4l Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4l(M00, M11, M22, M33);\n        }\n\n        public readonly V4l AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4l(M03, M12, M21, M30);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly long MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly long MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33);\n        }\n\n        public unsafe long this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe long this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &M00) { return ptr[row * 4 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &M00) { ptr[row * 4 + column] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 4;\n        public const int ColumnCount = 4;\n        public const int ElementCount = 4 * 4;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(4, 4);\n        }\n\n        public static M44l Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M44l(0);\n        }\n\n        public static M44l Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M44l(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly long Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + Fun.Abs(M03) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + Fun.Abs(M13) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22) + Fun.Abs(M23) + \n                    Fun.Abs(M30) + Fun.Abs(M31) + Fun.Abs(M32) + Fun.Abs(M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + M03 * M03 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + M13 * M13 + \n                    M20 * M20 + M21 * M21 + M22 * M22 + M23 * M23 + \n                    M30 * M30 + M31 * M31 + M32 * M32 + M33 * M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)), \n                            Fun.Max(\n                                Fun.Abs(M30), \n                                Fun.Abs(M31), \n                                Fun.Abs(M32), \n                                Fun.Abs(M33)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly long NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)), \n                            Fun.Min(\n                                Fun.Abs(M30), \n                                Fun.Abs(M31), \n                                Fun.Abs(M32), \n                                Fun.Abs(M33)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator -(M44l m)\n        {\n            return new M44l(\n                -m.M00, -m.M01, -m.M02, -m.M03, \n                -m.M10, -m.M11, -m.M12, -m.M13, \n                -m.M20, -m.M21, -m.M22, -m.M23, \n                -m.M30, -m.M31, -m.M32, -m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  + (M44l a, M44l b)\n        {\n            return new M44l(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  + (M44l m, long s)\n        {\n            return new M44l(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  + (long s, M44l m)\n        {\n            return new M44l(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (M44l a, M44f b)\n        {\n            return new M44f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (M44l m, float s)\n        {\n            return new M44f(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (float s, M44l m)\n        {\n            return new M44f(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (M44l a, M44d b)\n        {\n            return new M44d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (M44l m, double s)\n        {\n            return new M44d(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (double s, M44l m)\n        {\n            return new M44d(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  - (M44l a, M44l b)\n        {\n            return new M44l(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  - (M44l m, long s)\n        {\n            return new M44l(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  - (long s, M44l m)\n        {\n            return new M44l(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (M44l a, M44f b)\n        {\n            return new M44f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (M44l m, float s)\n        {\n            return new M44f(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (float s, M44l m)\n        {\n            return new M44f(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (M44l a, M44d b)\n        {\n            return new M44d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (M44l m, double s)\n        {\n            return new M44d(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (double s, M44l m)\n        {\n            return new M44d(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  % (M44l a, M44l b)\n        {\n            return new M44l(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  % (M44l m, long s)\n        {\n            return new M44l(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  % (long s, M44l m)\n        {\n            return new M44l(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (M44l a, M44f b)\n        {\n            return new M44f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (M44l m, float s)\n        {\n            return new M44f(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (float s, M44l m)\n        {\n            return new M44f(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (M44l a, M44d b)\n        {\n            return new M44d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (M44l m, double s)\n        {\n            return new M44d(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (double s, M44l m)\n        {\n            return new M44d(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  / (M44l a, M44l b)\n        {\n            return new M44l(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  / (M44l m, long s)\n        {\n            return new M44l(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  / (long s, M44l m)\n        {\n            return new M44l(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (M44l a, M44f b)\n        {\n            return new M44f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (M44l m, float s)\n        {\n            return new M44f(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (float s, M44l m)\n        {\n            return new M44f(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (M44l a, M44d b)\n        {\n            return new M44d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (M44l m, double s)\n        {\n            return new M44d(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (double s, M44l m)\n        {\n            return new M44d(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  * (M44l m, long s)\n        {\n            return new M44l(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator  * (long s, M44l m)\n        {\n            return new M44l(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  * (M44l m, float s)\n        {\n            return new M44f(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  * (float s, M44l m)\n        {\n            return new M44f(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  * (M44l m, double s)\n        {\n            return new M44d(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  * (double s, M44l m)\n        {\n            return new M44d(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        #endregion\n\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator ~(M44l m)\n        {\n            return new M44l(\n                ~m.M00, ~m.M01, ~m.M02, ~m.M03, \n                ~m.M10, ~m.M11, ~m.M12, ~m.M13, \n                ~m.M20, ~m.M21, ~m.M22, ~m.M23, \n                ~m.M30, ~m.M31, ~m.M32, ~m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator <<(M44l a, int s)\n        {\n            return new M44l(\n                a.M00 << s, a.M01 << s, a.M02 << s, a.M03 << s, \n                a.M10 << s, a.M11 << s, a.M12 << s, a.M13 << s, \n                a.M20 << s, a.M21 << s, a.M22 << s, a.M23 << s, \n                a.M30 << s, a.M31 << s, a.M32 << s, a.M33 << s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator >>(M44l a, int s)\n        {\n            return new M44l(\n                a.M00 >> s, a.M01 >> s, a.M02 >> s, a.M03 >> s, \n                a.M10 >> s, a.M11 >> s, a.M12 >> s, a.M13 >> s, \n                a.M20 >> s, a.M21 >> s, a.M22 >> s, a.M23 >> s, \n                a.M30 >> s, a.M31 >> s, a.M32 >> s, a.M33 >> s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator &(M44l a, M44l b)\n        {\n            return new M44l(\n                a.M00 & b.M00, a.M01 & b.M01, a.M02 & b.M02, a.M03 & b.M03, \n                a.M10 & b.M10, a.M11 & b.M11, a.M12 & b.M12, a.M13 & b.M13, \n                a.M20 & b.M20, a.M21 & b.M21, a.M22 & b.M22, a.M23 & b.M23, \n                a.M30 & b.M30, a.M31 & b.M31, a.M32 & b.M32, a.M33 & b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator &(M44l a, long s)\n        {\n            return new M44l(\n                a.M00 & s, a.M01 & s, a.M02 & s, a.M03 & s, \n                a.M10 & s, a.M11 & s, a.M12 & s, a.M13 & s, \n                a.M20 & s, a.M21 & s, a.M22 & s, a.M23 & s, \n                a.M30 & s, a.M31 & s, a.M32 & s, a.M33 & s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator &(long s, M44l a)\n        {\n            return new M44l(\n                s & a.M00, s & a.M01, s & a.M02, s & a.M03, \n                s & a.M10, s & a.M11, s & a.M12, s & a.M13, \n                s & a.M20, s & a.M21, s & a.M22, s & a.M23, \n                s & a.M30, s & a.M31, s & a.M32, s & a.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator |(M44l a, M44l b)\n        {\n            return new M44l(\n                a.M00 | b.M00, a.M01 | b.M01, a.M02 | b.M02, a.M03 | b.M03, \n                a.M10 | b.M10, a.M11 | b.M11, a.M12 | b.M12, a.M13 | b.M13, \n                a.M20 | b.M20, a.M21 | b.M21, a.M22 | b.M22, a.M23 | b.M23, \n                a.M30 | b.M30, a.M31 | b.M31, a.M32 | b.M32, a.M33 | b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator |(M44l a, long s)\n        {\n            return new M44l(\n                a.M00 | s, a.M01 | s, a.M02 | s, a.M03 | s, \n                a.M10 | s, a.M11 | s, a.M12 | s, a.M13 | s, \n                a.M20 | s, a.M21 | s, a.M22 | s, a.M23 | s, \n                a.M30 | s, a.M31 | s, a.M32 | s, a.M33 | s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator |(long s, M44l a)\n        {\n            return new M44l(\n                s | a.M00, s | a.M01, s | a.M02, s | a.M03, \n                s | a.M10, s | a.M11, s | a.M12, s | a.M13, \n                s | a.M20, s | a.M21, s | a.M22, s | a.M23, \n                s | a.M30, s | a.M31, s | a.M32, s | a.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator ^(M44l a, M44l b)\n        {\n            return new M44l(\n                a.M00 ^ b.M00, a.M01 ^ b.M01, a.M02 ^ b.M02, a.M03 ^ b.M03, \n                a.M10 ^ b.M10, a.M11 ^ b.M11, a.M12 ^ b.M12, a.M13 ^ b.M13, \n                a.M20 ^ b.M20, a.M21 ^ b.M21, a.M22 ^ b.M22, a.M23 ^ b.M23, \n                a.M30 ^ b.M30, a.M31 ^ b.M31, a.M32 ^ b.M32, a.M33 ^ b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator ^(M44l a, long s)\n        {\n            return new M44l(\n                a.M00 ^ s, a.M01 ^ s, a.M02 ^ s, a.M03 ^ s, \n                a.M10 ^ s, a.M11 ^ s, a.M12 ^ s, a.M13 ^ s, \n                a.M20 ^ s, a.M21 ^ s, a.M22 ^ s, a.M23 ^ s, \n                a.M30 ^ s, a.M31 ^ s, a.M32 ^ s, a.M33 ^ s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l operator ^(long s, M44l a)\n        {\n            return new M44l(\n                s ^ a.M00, s ^ a.M01, s ^ a.M02, s ^ a.M03, \n                s ^ a.M10, s ^ a.M11, s ^ a.M12, s ^ a.M13, \n                s ^ a.M20, s ^ a.M21, s ^ a.M22, s ^ a.M23, \n                s ^ a.M30, s ^ a.M31, s ^ a.M32, s ^ a.M33);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M44l matrix with a V4l column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator *(M44l m, V4l v)\n        {\n            return new V4l(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z + m.M03 * v.W, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z + m.M13 * v.W, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z + m.M23 * v.W, \n                m.M30 * v.X + m.M31 * v.Y + m.M32 * v.Z + m.M33 * v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a V4l row vector with a M44l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator *(V4l v, M44l m)\n        {\n            return new V4l(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20 + v.W * m.M30, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21 + v.W * m.M31, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22 + v.W * m.M32, \n                v.X * m.M03 + v.Y * m.M13 + v.Z * m.M23 + v.W * m.M33);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M44l a, M44l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23 && \n                a.M30 == b.M30 && \n                a.M31 == b.M31 && \n                a.M32 == b.M32 && \n                a.M33 == b.M33;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M44l a, long s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M03 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M13 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s && \n                a.M23 == s && \n                a.M30 == s && \n                a.M31 == s && \n                a.M32 == s && \n                a.M33 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(long s, M44l a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M03  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M13  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22  && \n                s == a.M23  && \n                s == a.M30  && \n                s == a.M31  && \n                s == a.M32  && \n                s == a.M33 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M44l a, M44l b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M44l m, long s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(long s, M44l m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02, M03),\n                        HashCode.GetCombined(M10, M11, M12, M13),\n                        HashCode.GetCombined(M20, M21, M22, M23),\n                        HashCode.GetCombined(M30, M31, M32, M33));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M44l other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && M03.Equals(other.M03) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && M13.Equals(other.M13) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22) && M23.Equals(other.M23) && \n                M30.Equals(other.M30) && M31.Equals(other.M31) && M32.Equals(other.M32) && M33.Equals(other.M33);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M44l o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R3.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M44l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M44l.FromRows(\n                V4l.Parse(x[0]), \n                V4l.Parse(x[1]), \n                V4l.Parse(x[2]), \n                V4l.Parse(x[3])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M44l Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                M44l result = new M44l();\n                for (int row = 0; row < 4; row++)\n                {\n                    for (int col = 0; col < 4; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly long Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 + M22 + M33 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly long Determinant\n        {\n            get\n            {\n                // using bottom row because elements M30, M31, and M32\n                // are zero most of the time.\n                long d = 0;\n                if (M30 != 0.0f) d -= M30 * (\n                M01 * M12 * M23 + M02 * M13 * M21 + M03 * M11 * M22\n                - M21 * M12 * M03 - M22 * M13 * M01 - M23 * M11 * M02\n                );\n                if (M31 != 0.0f) d += M31 * (\n                M00 * M12 * M23 + M02 * M13 * M20 + M03 * M10 * M22\n                - M20 * M12 * M03 - M22 * M13 * M00 - M23 * M10 * M02\n                );\n                if (M32 != 0.0f) d -= M32 * (\n                M00 * M11 * M23 + M01 * M13 * M20 + M03 * M10 * M21\n                - M20 * M11 * M03 - M21 * M13 * M00 - M23 * M10 * M01\n                );\n                if (M33 != 0.0f) d += M33 * (\n                M00 * M11 * M22 + M01 * M12 * M20 + M02 * M10 * M21\n                - M20 * M11 * M02 - M21 * M12 * M00 - M22 * M10 * M01\n                );\n                return d;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M44l Transposed\n        {\n            get\n            {\n                return new M44l {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    M02 = M20, \n                    M03 = M30, \n                    \n                    M10 = M01, \n                    M11 = M11, \n                    M12 = M21, \n                    M13 = M31, \n                    \n                    M20 = M02, \n                    M21 = M12, \n                    M22 = M22, \n                    M23 = M32, \n                    \n                    M30 = M03, \n                    M31 = M13, \n                    M32 = M23, \n                    M33 = M33\n                };\n            }\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M44l operator *(M44l a, M44l b)\n        {\n            return new M44l(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20 + a.M03 * b.M30, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21 + a.M03 * b.M31, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22 + a.M03 * b.M32, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03 * b.M33, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20 + a.M13 * b.M30, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20 + a.M23 * b.M30, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33, \n                a.M30 * b.M00 + a.M31 * b.M10 + a.M32 * b.M20 + a.M33 * b.M30, \n                a.M30 * b.M01 + a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31, \n                a.M30 * b.M02 + a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32, \n                a.M30 * b.M03 + a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (long)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (long)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (long)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (long)value;\n        }\n\n        #endregion\n    }\n\n    public class M44lEqualityComparer : IEqualityComparer<M44l>\n    {\n        public static readonly M44lEqualityComparer Default\n            = new M44lEqualityComparer();\n\n        #region IEqualityComparer<M44l> Members\n\n        public bool Equals(M44l v0, M44l v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M44l v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M44l m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length + m.C3.Length) / 4;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d GetScaleVector(this M44l m)\n            => new V4d(m.C0.Length, m.C1.Length, m.C2.Length, m.C3.Length);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of 3D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale3(this M44l m)\n            => (m.C0.XYZ.Length + m.C1.XYZ.Length + m.C2.XYZ.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the 3D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector3(this M44l m)\n            => new V3d(m.C0.XYZ.Length, m.C1.XYZ.Length, m.C2.XYZ.Length);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Norm1(M44l m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M44l m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMax(M44l m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMin(M44l m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M44l m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M03).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M13).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p) + \n                Fun.Abs(m.M23).Pow(p) + \n                Fun.Abs(m.M30).Pow(p) + \n                Fun.Abs(m.M31).Pow(p) + \n                Fun.Abs(m.M32).Pow(p) + \n                Fun.Abs(m.M33).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static long Distance1(this M44l a, M44l b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M03 - a.M03) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M13 - a.M13) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22) + \n                Fun.Abs(b.M23 - a.M23) + \n                Fun.Abs(b.M30 - a.M30) + \n                Fun.Abs(b.M31 - a.M31) + \n                Fun.Abs(b.M32 - a.M32) + \n                Fun.Abs(b.M33 - a.M33);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M44l a, M44l b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M03 - a.M03) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M13 - a.M13) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22) + \n                        Fun.Square(b.M23 - a.M23) + \n                        Fun.Square(b.M30 - a.M30) + \n                        Fun.Square(b.M31 - a.M31) + \n                        Fun.Square(b.M32 - a.M32) + \n                        Fun.Square(b.M33 - a.M33));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M44l a, M44l b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M03 - a.M03).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M13 - a.M13).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p) + \n                Fun.Abs(b.M23 - a.M23).Pow(p) + \n                Fun.Abs(b.M30 - a.M30).Pow(p) + \n                Fun.Abs(b.M31 - a.M31).Pow(p) + \n                Fun.Abs(b.M32 - a.M32).Pow(p) + \n                Fun.Abs(b.M33 - a.M33).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMax(this M44l a, M44l b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)), \n                        Fun.Max(\n                            Fun.Abs(b.M30 - a.M30), \n                            Fun.Abs(b.M31 - a.M31), \n                            Fun.Abs(b.M32 - a.M32), \n                            Fun.Abs(b.M33 - a.M33)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static long DistanceMin(this M44l a, M44l b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)), \n                        Fun.Min(\n                            Fun.Abs(b.M30 - a.M30), \n                            Fun.Abs(b.M31 - a.M31), \n                            Fun.Abs(b.M32 - a.M32), \n                            Fun.Abs(b.M33 - a.M33)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Transform(this M44l m, V4l v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l TransposedTransform(this M44l m, V4l v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V3l TransformDir(this M44l m, V3l v)\n        {\n            return new V3l(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V3l TransformPos(this M44l m, V3l p)\n        {\n            return new V3l(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V3l TransformPosProj(this M44l m, V3l p)\n        {\n            long s = m.M30 * p.X + m.M31 * p.Y + m.M32 * p.Z + m.M33;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V4l TransformPosProjFull(this M44l m, V3l p)\n        {\n            return new V4l(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23, \n                m.M30 * p.X + m.M31 * p.Y + m.M32 * p.Z + m.M33\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static V3l TransposedTransformDir(this M44l m, V3l v)\n        {\n            return new V3l(\n                m.M00 * v.X + m.M10 * v.Y + m.M20 * v.Z, \n                m.M01 * v.X + m.M11 * v.Y + m.M21 * v.Z, \n                m.M02 * v.X + m.M12 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V3l TransposedTransformPos(this M44l m, V3l p)\n        {\n            return new V3l(\n                m.M00 * p.X + m.M10 * p.Y + m.M20 * p.Z + m.M30, \n                m.M01 * p.X + m.M11 * p.Y + m.M21 * p.Z + m.M31, \n                m.M02 * p.X + m.M12 * p.Y + m.M22 * p.Z + m.M32\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V3l TransposedTransformPosProj(this M44l m, V3l p)\n        {\n            var s = m.M03 * p.X + m.M13 * p.Y + m.M23 * p.Z + m.M33;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static V3l TransposedTransformProj(this M44l m, V3l p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V4l TransposedTransformPosProjFull(this M44l m, V3l p)\n        {\n            return new V4l(\n                m.M00 * p.X + m.M10 * p.Y + m.M20 * p.Z + m.M30, \n                m.M01 * p.X + m.M11 * p.Y + m.M21 * p.Z + m.M31, \n                m.M02 * p.X + m.M12 * p.Y + m.M22 * p.Z + m.M32, \n                m.M03 * p.X + m.M13 * p.Y + m.M23 * p.Z + m.M33\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static V4l TransposedTransformProjFull(this M44l m, V3l p)\n            => m.TransposedTransformPosProjFull(p);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M44l\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static M33l Minor(this M44l m, int row, int column)\n        {\n            M33l rs = new M33l();\n\n            for (int k = 0; k < 9; k++)\n            {\n                var i = k / 3;\n                var j = k % 3;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * 4 + jj];\n            }\n\n            return rs;\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4l Row(this M44l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V4l(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4l Column(this M44l m, int index)\n        {\n            long* ptr = &m.M00;\n            return new V4l(ptr[index], ptr[index + 4], ptr[index + 8], ptr[index + 12]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Determinant(M44l m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Transposed(M44l m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M44l m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n            Fun.Swap(ref m.M20, ref m.M02);\n            Fun.Swap(ref m.M21, ref m.M12);\n            Fun.Swap(ref m.M30, ref m.M03);\n            Fun.Swap(ref m.M31, ref m.M13);\n            Fun.Swap(ref m.M32, ref m.M23);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M44l a, M44l b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M03 < b.M03 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M13 < b.M13 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22 && \n                a.M23 < b.M23 && \n                a.M30 < b.M30 && \n                a.M31 < b.M31 && \n                a.M32 < b.M32 && \n                a.M33 < b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M44l m, long s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M03 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M13 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s && \n                m.M23 < s && \n                m.M30 < s && \n                m.M31 < s && \n                m.M32 < s && \n                m.M33 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(long s, M44l m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M03 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M13 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22 && \n                s < m.M23 && \n                s < m.M30 && \n                s < m.M31 && \n                s < m.M32 && \n                s < m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M44l a, M44l b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M03 < b.M03 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M13 < b.M13 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22 || \n                a.M23 < b.M23 || \n                a.M30 < b.M30 || \n                a.M31 < b.M31 || \n                a.M32 < b.M32 || \n                a.M33 < b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M44l m, long s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M03 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M13 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s || \n                m.M23 < s || \n                m.M30 < s || \n                m.M31 < s || \n                m.M32 < s || \n                m.M33 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(long s, M44l m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M03 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M13 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22 || \n                s < m.M23 || \n                s < m.M30 || \n                s < m.M31 || \n                s < m.M32 || \n                s < m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M44l a, M44l b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M03 > b.M03 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M13 > b.M13 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22 && \n                a.M23 > b.M23 && \n                a.M30 > b.M30 && \n                a.M31 > b.M31 && \n                a.M32 > b.M32 && \n                a.M33 > b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M44l m, long s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M03 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M13 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s && \n                m.M23 > s && \n                m.M30 > s && \n                m.M31 > s && \n                m.M32 > s && \n                m.M33 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(long s, M44l m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M03 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M13 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22 && \n                s > m.M23 && \n                s > m.M30 && \n                s > m.M31 && \n                s > m.M32 && \n                s > m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M44l a, M44l b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M03 > b.M03 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M13 > b.M13 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22 || \n                a.M23 > b.M23 || \n                a.M30 > b.M30 || \n                a.M31 > b.M31 || \n                a.M32 > b.M32 || \n                a.M33 > b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M44l m, long s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M03 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M13 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s || \n                m.M23 > s || \n                m.M30 > s || \n                m.M31 > s || \n                m.M32 > s || \n                m.M33 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(long s, M44l m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M03 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M13 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22 || \n                s > m.M23 || \n                s > m.M30 || \n                s > m.M31 || \n                s > m.M32 || \n                s > m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M44l a, M44l b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M03 <= b.M03 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M13 <= b.M13 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22 && \n                a.M23 <= b.M23 && \n                a.M30 <= b.M30 && \n                a.M31 <= b.M31 && \n                a.M32 <= b.M32 && \n                a.M33 <= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M44l m, long s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M03 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M13 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s && \n                m.M23 <= s && \n                m.M30 <= s && \n                m.M31 <= s && \n                m.M32 <= s && \n                m.M33 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(long s, M44l m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M03 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M13 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22 && \n                s <= m.M23 && \n                s <= m.M30 && \n                s <= m.M31 && \n                s <= m.M32 && \n                s <= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M44l a, M44l b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M03 <= b.M03 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M13 <= b.M13 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22 || \n                a.M23 <= b.M23 || \n                a.M30 <= b.M30 || \n                a.M31 <= b.M31 || \n                a.M32 <= b.M32 || \n                a.M33 <= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M44l m, long s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M03 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M13 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s || \n                m.M23 <= s || \n                m.M30 <= s || \n                m.M31 <= s || \n                m.M32 <= s || \n                m.M33 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(long s, M44l m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M03 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M13 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22 || \n                s <= m.M23 || \n                s <= m.M30 || \n                s <= m.M31 || \n                s <= m.M32 || \n                s <= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M44l a, M44l b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M03 >= b.M03 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M13 >= b.M13 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22 && \n                a.M23 >= b.M23 && \n                a.M30 >= b.M30 && \n                a.M31 >= b.M31 && \n                a.M32 >= b.M32 && \n                a.M33 >= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M44l m, long s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M03 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M13 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s && \n                m.M23 >= s && \n                m.M30 >= s && \n                m.M31 >= s && \n                m.M32 >= s && \n                m.M33 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(long s, M44l m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M03 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M13 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22 && \n                s >= m.M23 && \n                s >= m.M30 && \n                s >= m.M31 && \n                s >= m.M32 && \n                s >= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M44l a, M44l b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M03 >= b.M03 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M13 >= b.M13 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22 || \n                a.M23 >= b.M23 || \n                a.M30 >= b.M30 || \n                a.M31 >= b.M31 || \n                a.M32 >= b.M32 || \n                a.M33 >= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M44l m, long s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M03 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M13 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s || \n                m.M23 >= s || \n                m.M30 >= s || \n                m.M31 >= s || \n                m.M32 >= s || \n                m.M33 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(long s, M44l m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M03 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M13 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22 || \n                s >= m.M23 || \n                s >= m.M30 || \n                s >= m.M31 || \n                s >= m.M32 || \n                s >= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M44l a, M44l b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23 && \n                a.M30 == b.M30 && \n                a.M31 == b.M31 && \n                a.M32 == b.M32 && \n                a.M33 == b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M44l m, long s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M03 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M13 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s && \n                m.M23 == s && \n                m.M30 == s && \n                m.M31 == s && \n                m.M32 == s && \n                m.M33 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(long s, M44l m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M03 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M13 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22 && \n                s == m.M23 && \n                s == m.M30 && \n                s == m.M31 && \n                s == m.M32 && \n                s == m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M44l a, M44l b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M03 == b.M03 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M13 == b.M13 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22 || \n                a.M23 == b.M23 || \n                a.M30 == b.M30 || \n                a.M31 == b.M31 || \n                a.M32 == b.M32 || \n                a.M33 == b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M44l m, long s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M03 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M13 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s || \n                m.M23 == s || \n                m.M30 == s || \n                m.M31 == s || \n                m.M32 == s || \n                m.M33 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(long s, M44l m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M03 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M13 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22 || \n                s == m.M23 || \n                s == m.M30 || \n                s == m.M31 || \n                s == m.M32 || \n                s == m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M44l a, M44l b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M03 != b.M03 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M13 != b.M13 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22 && \n                a.M23 != b.M23 && \n                a.M30 != b.M30 && \n                a.M31 != b.M31 && \n                a.M32 != b.M32 && \n                a.M33 != b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M44l m, long s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M03 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M13 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s && \n                m.M23 != s && \n                m.M30 != s && \n                m.M31 != s && \n                m.M32 != s && \n                m.M33 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(long s, M44l m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M03 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M13 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22 && \n                s != m.M23 && \n                s != m.M30 && \n                s != m.M31 && \n                s != m.M32 && \n                s != m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M44l a, M44l b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M03 != b.M03 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M13 != b.M13 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22 || \n                a.M23 != b.M23 || \n                a.M30 != b.M30 || \n                a.M31 != b.M31 || \n                a.M32 != b.M32 || \n                a.M33 != b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M44l m, long s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M03 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M13 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s || \n                m.M23 != s || \n                m.M30 != s || \n                m.M31 != s || \n                m.M32 != s || \n                m.M33 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(long s, M44l m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M03 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M13 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22 || \n                s != m.M23 || \n                s != m.M30 || \n                s != m.M31 || \n                s != m.M32 || \n                s != m.M33;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M44l m0, M44l m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M03 < m1.M03) return -1;\n            if (m0.M03 > m1.M03) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M13 < m1.M13) return -1;\n            if (m0.M13 > m1.M13) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            if (m0.M23 < m1.M23) return -1;\n            if (m0.M23 > m1.M23) return +1;\n            if (m0.M30 < m1.M30) return -1;\n            if (m0.M30 > m1.M30) return +1;\n            if (m0.M31 < m1.M31) return -1;\n            if (m0.M31 > m1.M31) return +1;\n            if (m0.M32 < m1.M32) return -1;\n            if (m0.M32 > m1.M32) return +1;\n            if (m0.M33 < m1.M33) return -1;\n            if (m0.M33 > m1.M33) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M44l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MinElement(M44l m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M44l\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MaxElement(M44l m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M44l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M44l m, long epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M03.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M13.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon) || m.M23.IsTiny(epsilon) || m.M30.IsTiny(epsilon) || m.M31.IsTiny(epsilon) || m.M32.IsTiny(epsilon) || m.M33.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M44l m, long epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M03.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M13.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon) && m.M23.IsTiny(epsilon) && m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon) && m.M33.IsTiny(epsilon);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M44l a, M44l b, long epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M44l m, long epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        #endregion\n    }\n\n    public static class IRandomUniformM44lExtensions\n    {\n        #region IRandomUniform extensions for M44l\n\n        /// <summary>\n        /// Uses UniformLong() to generate the elements of an M44l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l UniformM44l(this IRandomUniform rnd)\n        {\n            return new M44l(\n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), \n                rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong());\n        }\n\n        /// <summary>\n        /// Uses UniformLongNonZero() to generate the elements of an M44l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l UniformM44lNonZero(this IRandomUniform rnd)\n        {\n            return new M44l(\n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), \n                rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M44l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l UniformM44l(this IRandomUniform rnd, long size)\n        {\n            return new M44l(\n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), \n                rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size));\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of an M44l matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l UniformM44l(this IRandomUniform rnd, M44l size)\n        {\n            return new M44l(\n                rnd.UniformLong(size.M00), rnd.UniformLong(size.M01), rnd.UniformLong(size.M02), rnd.UniformLong(size.M03), \n                rnd.UniformLong(size.M10), rnd.UniformLong(size.M11), rnd.UniformLong(size.M12), rnd.UniformLong(size.M13), \n                rnd.UniformLong(size.M20), rnd.UniformLong(size.M21), rnd.UniformLong(size.M22), rnd.UniformLong(size.M23), \n                rnd.UniformLong(size.M30), rnd.UniformLong(size.M31), rnd.UniformLong(size.M32), rnd.UniformLong(size.M33));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M44f\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M44f : IEquatable<M44f>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public float M00, M01, M02, M03;\n        [DataMember]\n        public float M10, M11, M12, M13;\n        [DataMember]\n        public float M20, M21, M22, M23;\n        [DataMember]\n        public float M30, M31, M32, M33;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(float value)\n        {\n            M00 = value; M01 = 0; M02 = 0; M03 = 0; \n            M10 = 0; M11 = value; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = value; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(\n                float m00, float m01, float m02, float m03, \n                float m10, float m11, float m12, float m13, \n                float m20, float m21, float m22, float m23, \n                float m30, float m31, float m32, float m33)\n        {\n            M00 = m00; M01 = m01; M02 = m02; M03 = m03; \n            M10 = m10; M11 = m11; M12 = m12; M13 = m13; \n            M20 = m20; M21 = m21; M22 = m22; M23 = m23; \n            M30 = m30; M31 = m31; M32 = m32; M33 = m33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(float[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M03 = a[3];\n            M10 = a[4];\n            M11 = a[5];\n            M12 = a[6];\n            M13 = a[7];\n            M20 = a[8];\n            M21 = a[9];\n            M22 = a[10];\n            M23 = a[11];\n            M30 = a[12];\n            M31 = a[13];\n            M32 = a[14];\n            M33 = a[15];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(float[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M03 = a[start + 3];\n            M10 = a[start + 4];\n            M11 = a[start + 5];\n            M12 = a[start + 6];\n            M13 = a[start + 7];\n            M20 = a[start + 8];\n            M21 = a[start + 9];\n            M22 = a[start + 10];\n            M23 = a[start + 11];\n            M30 = a[start + 12];\n            M31 = a[start + 13];\n            M32 = a[start + 14];\n            M33 = a[start + 15];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M22i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M23i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M33i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M34i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M44i m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n            M30 = (float)m.M30; M31 = (float)m.M31; M32 = (float)m.M32; M33 = (float)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M22l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M23l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M33l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M34l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M44l m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n            M30 = (float)m.M30; M31 = (float)m.M31; M32 = (float)m.M32; M33 = (float)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M22f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M23f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M33f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M34f m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = m.M03; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = m.M13; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M22d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = 0; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M23d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M33d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = 0; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = 0; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M34d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44f(M44d m)\n        {\n            M00 = (float)m.M00; M01 = (float)m.M01; M02 = (float)m.M02; M03 = (float)m.M03; \n            M10 = (float)m.M10; M11 = (float)m.M11; M12 = (float)m.M12; M13 = (float)m.M13; \n            M20 = (float)m.M20; M21 = (float)m.M21; M22 = (float)m.M22; M23 = (float)m.M23; \n            M30 = (float)m.M30; M31 = (float)m.M31; M32 = (float)m.M32; M33 = (float)m.M33; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M44f(M22i m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M23i m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M33i m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M34i m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M44i m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n                M30 = (float)m.M30, M31 = (float)m.M31, M32 = (float)m.M32, M33 = (float)m.M33, \n            };\n        }\n\n        public static explicit operator M44f(M22l m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M23l m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M33l m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M34l m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M44l m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n                M30 = (float)m.M30, M31 = (float)m.M31, M32 = (float)m.M32, M33 = (float)m.M33, \n            };\n        }\n\n        public static explicit operator M44f(M22f m)\n        {\n            return new M44f {\n                M00 = m.M00, M01 = m.M01, M02 = 0, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M23f m)\n        {\n            return new M44f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M33f m)\n        {\n            return new M44f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M34f m)\n        {\n            return new M44f {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = m.M03, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = m.M13, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M22d m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = 0, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M23d m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M33d m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = 0, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = 0, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M34d m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44f(M44d m)\n        {\n            return new M44f {\n                M00 = (float)m.M00, M01 = (float)m.M01, M02 = (float)m.M02, M03 = (float)m.M03, \n                M10 = (float)m.M10, M11 = (float)m.M11, M12 = (float)m.M12, M13 = (float)m.M13, \n                M20 = (float)m.M20, M21 = (float)m.M21, M22 = (float)m.M22, M23 = (float)m.M23, \n                M30 = (float)m.M30, M31 = (float)m.M31, M32 = (float)m.M32, M33 = (float)m.M33, \n            };\n        }\n\n        public static explicit operator M44f(int[] a)\n        {\n            return new M44f(\n                (float)a[0], (float)a[1], (float)a[2], (float)a[3], \n                (float)a[4], (float)a[5], (float)a[6], (float)a[7], \n                (float)a[8], (float)a[9], (float)a[10], (float)a[11], \n                (float)a[12], (float)a[13], (float)a[14], (float)a[15]);\n        }\n\n        public static explicit operator M44f(int[,] a)\n        {\n            return new M44f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], (float)a[0, 3], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], (float)a[1, 3], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2], (float)a[2, 3], \n                (float)a[3, 0], (float)a[3, 1], (float)a[3, 2], (float)a[3, 3]);\n        }\n\n        public static explicit operator int[](M44f m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03, \n                (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13, \n                (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23, \n                (int)m.M30, (int)m.M31, (int)m.M32, (int)m.M33\n            };\n        }\n\n        public static explicit operator int[,](M44f m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23 }, \n                { (int)m.M30, (int)m.M31, (int)m.M32, (int)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M03;\n            array[index + 4] = (int)M10;\n            array[index + 5] = (int)M11;\n            array[index + 6] = (int)M12;\n            array[index + 7] = (int)M13;\n            array[index + 8] = (int)M20;\n            array[index + 9] = (int)M21;\n            array[index + 10] = (int)M22;\n            array[index + 11] = (int)M23;\n            array[index + 12] = (int)M30;\n            array[index + 13] = (int)M31;\n            array[index + 14] = (int)M32;\n            array[index + 15] = (int)M33;\n        }\n\n        public static explicit operator M44f(long[] a)\n        {\n            return new M44f(\n                (float)a[0], (float)a[1], (float)a[2], (float)a[3], \n                (float)a[4], (float)a[5], (float)a[6], (float)a[7], \n                (float)a[8], (float)a[9], (float)a[10], (float)a[11], \n                (float)a[12], (float)a[13], (float)a[14], (float)a[15]);\n        }\n\n        public static explicit operator M44f(long[,] a)\n        {\n            return new M44f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], (float)a[0, 3], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], (float)a[1, 3], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2], (float)a[2, 3], \n                (float)a[3, 0], (float)a[3, 1], (float)a[3, 2], (float)a[3, 3]);\n        }\n\n        public static explicit operator long[](M44f m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03, \n                (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13, \n                (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23, \n                (long)m.M30, (long)m.M31, (long)m.M32, (long)m.M33\n            };\n        }\n\n        public static explicit operator long[,](M44f m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23 }, \n                { (long)m.M30, (long)m.M31, (long)m.M32, (long)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M03;\n            array[index + 4] = (long)M10;\n            array[index + 5] = (long)M11;\n            array[index + 6] = (long)M12;\n            array[index + 7] = (long)M13;\n            array[index + 8] = (long)M20;\n            array[index + 9] = (long)M21;\n            array[index + 10] = (long)M22;\n            array[index + 11] = (long)M23;\n            array[index + 12] = (long)M30;\n            array[index + 13] = (long)M31;\n            array[index + 14] = (long)M32;\n            array[index + 15] = (long)M33;\n        }\n\n        public static explicit operator M44f(float[] a)\n        {\n            return new M44f(\n                a[0], a[1], a[2], a[3], \n                a[4], a[5], a[6], a[7], \n                a[8], a[9], a[10], a[11], \n                a[12], a[13], a[14], a[15]);\n        }\n\n        public static explicit operator M44f(float[,] a)\n        {\n            return new M44f(\n                a[0, 0], a[0, 1], a[0, 2], a[0, 3], \n                a[1, 0], a[1, 1], a[1, 2], a[1, 3], \n                a[2, 0], a[2, 1], a[2, 2], a[2, 3], \n                a[3, 0], a[3, 1], a[3, 2], a[3, 3]);\n        }\n\n        public static explicit operator float[](M44f m)\n        {\n            return new float[] {\n                m.M00, m.M01, m.M02, m.M03, \n                m.M10, m.M11, m.M12, m.M13, \n                m.M20, m.M21, m.M22, m.M23, \n                m.M30, m.M31, m.M32, m.M33\n            };\n        }\n\n        public static explicit operator float[,](M44f m)\n        {\n            return new float[,] {\n                { m.M00, m.M01, m.M02, m.M03 }, \n                { m.M10, m.M11, m.M12, m.M13 }, \n                { m.M20, m.M21, m.M22, m.M23 }, \n                { m.M30, m.M31, m.M32, m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M03;\n            array[index + 4] = M10;\n            array[index + 5] = M11;\n            array[index + 6] = M12;\n            array[index + 7] = M13;\n            array[index + 8] = M20;\n            array[index + 9] = M21;\n            array[index + 10] = M22;\n            array[index + 11] = M23;\n            array[index + 12] = M30;\n            array[index + 13] = M31;\n            array[index + 14] = M32;\n            array[index + 15] = M33;\n        }\n\n        public static explicit operator M44f(double[] a)\n        {\n            return new M44f(\n                (float)a[0], (float)a[1], (float)a[2], (float)a[3], \n                (float)a[4], (float)a[5], (float)a[6], (float)a[7], \n                (float)a[8], (float)a[9], (float)a[10], (float)a[11], \n                (float)a[12], (float)a[13], (float)a[14], (float)a[15]);\n        }\n\n        public static explicit operator M44f(double[,] a)\n        {\n            return new M44f(\n                (float)a[0, 0], (float)a[0, 1], (float)a[0, 2], (float)a[0, 3], \n                (float)a[1, 0], (float)a[1, 1], (float)a[1, 2], (float)a[1, 3], \n                (float)a[2, 0], (float)a[2, 1], (float)a[2, 2], (float)a[2, 3], \n                (float)a[3, 0], (float)a[3, 1], (float)a[3, 2], (float)a[3, 3]);\n        }\n\n        public static explicit operator double[](M44f m)\n        {\n            return new double[] {\n                (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03, \n                (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13, \n                (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23, \n                (double)m.M30, (double)m.M31, (double)m.M32, (double)m.M33\n            };\n        }\n\n        public static explicit operator double[,](M44f m)\n        {\n            return new double[,] {\n                { (double)m.M00, (double)m.M01, (double)m.M02, (double)m.M03 }, \n                { (double)m.M10, (double)m.M11, (double)m.M12, (double)m.M13 }, \n                { (double)m.M20, (double)m.M21, (double)m.M22, (double)m.M23 }, \n                { (double)m.M30, (double)m.M31, (double)m.M32, (double)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = (double)M00;\n            array[index + 1] = (double)M01;\n            array[index + 2] = (double)M02;\n            array[index + 3] = (double)M03;\n            array[index + 4] = (double)M10;\n            array[index + 5] = (double)M11;\n            array[index + 6] = (double)M12;\n            array[index + 7] = (double)M13;\n            array[index + 8] = (double)M20;\n            array[index + 9] = (double)M21;\n            array[index + 10] = (double)M22;\n            array[index + 11] = (double)M23;\n            array[index + 12] = (double)M30;\n            array[index + 13] = (double)M31;\n            array[index + 14] = (double)M32;\n            array[index + 15] = (double)M33;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44i Copy(Func<float, int> element_fun)\n        {\n            return new M44i(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44i Copy(Func<float, int, int, int> element_index0_index1_fun)\n        {\n            return new M44i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44l Copy(Func<float, long> element_fun)\n        {\n            return new M44l(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44l Copy(Func<float, int, int, long> element_index0_index1_fun)\n        {\n            return new M44l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44f Copy(Func<float, float> element_fun)\n        {\n            return new M44f(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44f Copy(Func<float, int, int, float> element_index0_index1_fun)\n        {\n            return new M44f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44d Copy(Func<float, double> element_fun)\n        {\n            return new M44d(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44d Copy(Func<float, int, int, double> element_index0_index1_fun)\n        {\n            return new M44d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly M33f UpperLeftM33()\n        {\n            return (M33f)this;\n        }\n\n        public readonly float[] ToArray()\n        {\n            var array = new float[16];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M03;\n            array[4] = M10;\n            array[5] = M11;\n            array[6] = M12;\n            array[7] = M13;\n            array[8] = M20;\n            array[9] = M21;\n            array[10] = M22;\n            array[11] = M23;\n            array[12] = M30;\n            array[13] = M31;\n            array[14] = M32;\n            array[15] = M33;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f FromCols(V4f col0, V4f col1, V4f col2, V4f col3)\n        {\n            return new M44f(\n                col0.X, col1.X, col2.X, col3.X, \n                col0.Y, col1.Y, col2.Y, col3.Y, \n                col0.Z, col1.Z, col2.Z, col3.Z, \n                col0.W, col1.W, col2.W, col3.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f FromRows(V4f row0, V4f row1, V4f row2, V4f row3)\n        {\n            return new M44f(\n                row0.X, row0.Y, row0.Z, row0.W, \n                row1.X, row1.Y, row1.Z, row1.W, \n                row2.X, row2.Y, row2.Z, row2.W, \n                row3.X, row3.Y, row3.Z, row3.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f FromDiagonal(float value)\n        {\n            return new M44f(\n                value, 0, 0, 0, \n                0, value, 0, 0, \n                0, 0, value, 0, \n                0, 0, 0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f FromDiagonal(float m00, float m11, float m22, float m33)\n        {\n            return new M44f(\n                m00, 0, 0, 0, \n                0, m11, 0, 0, \n                0, 0, m22, 0, \n                0, 0, 0, m33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f FromDiagonal(V4f s)\n        {\n            return new M44f(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, s.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f FromAntiDiagonal(float value)\n        {\n            return new M44f(\n                 0, 0, 0, value, \n                 0, 0, value, 0, \n                 0, value, 0, 0, \n                 value, 0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f FromAntiDiagonal(float m03, float m12, float m21, float m30)\n        {\n            return new M44f(\n                0, 0, 0, m03, \n                0, 0, m12, 0, \n                0, m21, 0, 0, \n                m30, 0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f FromAntiDiagonal(V4f s)\n        {\n            return new M44f(\n                0, 0, 0, s.X, \n                0, 0, s.Y, 0, \n                0, s.Z, 0, 0, \n                s.W, 0, 0, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44f\"/> using 4 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Scale(float sX, float sY, float sZ, float sW)\n            => FromDiagonal(sX, sY, sZ, sW);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44f\"/> using a <see cref=\"V4f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Scale(V4f s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M44f\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Scale(float s)\n        {\n            return new M44f(\n                s, 0, 0, 0, \n                0, s, 0, 0, \n                0, 0, s, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44f\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Scale(float sX, float sY, float sZ)\n        {\n            return new M44f(\n                sX, 0, 0, 0, \n                0, sY, 0, 0, \n                0, 0, sZ, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44f\"/> using a <see cref=\"V3f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Scale(V3f s)\n        {\n            return new M44f(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation <see cref=\"M44f\"/> from a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Scale(Scale3f s)\n        {\n            return new M44f(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44f\"/> with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Translation(float tX, float tY, float tZ)\n        {\n            return new M44f(\n                1, 0, 0, tX, \n                0, 1, 0, tY, \n                0, 0, 1, tZ, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44f\"/> with the translational component given by a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Translation(V3f t)\n        {\n            return new M44f(\n                1, 0, 0, t.X, \n                0, 1, 0, t.Y, \n                0, 0, 1, t.Z, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44f\"/> from a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Translation(Shift3f s)\n        {\n            return new M44f(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, s.Z, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from a <see cref=\"Rot3f\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Rotation(Rot3f r)\n            => (M44f)r;\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Rotation(V3f normalizedAxis, float angleInRadians)\n        {\n            Debug.Assert(normalizedAxis.LengthSquared.ApproximateEquals(1, 1e-5f));\n            return (M44f)(Rot3f.Rotation(normalizedAxis, angleInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationInDegrees(V3f normalizedAxis, float angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationEuler(float rollInRadians, float pitchInRadians, float yawInRadians)\n        {\n            return (M44f)(Rot3f.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationEulerInDegrees(float rollInDegrees, float pitchInDegrees, float yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationEuler(V3f rollPitchYawInRadians)\n            => RotationEuler(\n                rollPitchYawInRadians.X,\n                rollPitchYawInRadians.Y,\n                rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationEulerInDegrees(V3f rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotateInto(V3f from, V3f into)\n        {\n            Debug.Assert(from.LengthSquared.ApproximateEquals(1, 1e-5f));\n            Debug.Assert(into.LengthSquared.ApproximateEquals(1, 1e-5f));\n            return (M44f)(Rot3f.RotateInto(from, into));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationX(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M44f(\n                 1,  0,  0,  0, \n                 0,  a, -b,  0, \n                 0,  b,  a,  0, \n                 0,  0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationXInDegrees(float angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationY(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M44f(\n                 a,  0,  b,  0, \n                 0,  1,  0,  0, \n                -b,  0,  a,  0, \n                 0,  0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationYInDegrees(float angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationZ(float angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M44f(\n                 a, -b,  0,  0, \n                 b,  a,  0,  0, \n                 0,  0,  1,  0, \n                 0,  0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f RotationZInDegrees(float angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f ShearXY(float factorX, float factorY)\n        {\n            return new M44f(\n                1, 0, factorX, 0, \n                0, 1, factorY, 0, \n                0, 0, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f ShearXZ(float factorX, float factorZ)\n        {\n            return new M44f(\n                1, factorX, 0, 0, \n                0, 1, 0, 0, \n                0, factorZ, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f ShearYZ(float factorY, float factorZ)\n        {\n            return new M44f(\n                1, 0, 0, 0, \n                factorY, 1, 0, 0, \n                factorZ, 0, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f DivideByInt(M44f m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M03;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M13;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n                yield return M23;\n                yield return M30;\n                yield return M31;\n                yield return M32;\n                yield return M33;\n            }\n        }\n\n        public readonly IEnumerable<V4f> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n                yield return R3;\n            }\n        }\n\n        public readonly IEnumerable<V4f> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n                yield return C3;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M00,  M01,  M02,  M03); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n                M03 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M10,  M11,  M12,  M13); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n                M13 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M20,  M21,  M22,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n                M23 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f R3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M30,  M31,  M32,  M33); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M30 = value.X;\n                M31 = value.Y;\n                M32 = value.Z;\n                M33 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M00,  M10,  M20,  M30); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n                M30 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M01,  M11,  M21,  M31); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n                M31 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M02,  M12,  M22,  M32); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n                M32 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4f C3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4f( M03,  M13,  M23,  M33); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M03 = value.X;\n                M13 = value.Y;\n                M23 = value.Z;\n                M33 = value.W;\n            }\n        }\n\n        public readonly V4f Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4f(M00, M11, M22, M33);\n        }\n\n        public readonly V4f AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4f(M03, M12, M21, M30);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly float MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly float MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33);\n        }\n\n        public unsafe float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe float this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &M00) { return ptr[row * 4 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &M00) { ptr[row * 4 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || Fun.IsFinite(M02) || Fun.IsFinite(M03) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11) || Fun.IsFinite(M12) || Fun.IsFinite(M13) || \n                    Fun.IsFinite(M20) || Fun.IsFinite(M21) || Fun.IsFinite(M22) || Fun.IsFinite(M23) || \n                    Fun.IsFinite(M30) || Fun.IsFinite(M31) || Fun.IsFinite(M32) || Fun.IsFinite(M33);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && Fun.IsFinite(M02) && Fun.IsFinite(M03) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11) && Fun.IsFinite(M12) && Fun.IsFinite(M13) && \n                    Fun.IsFinite(M20) && Fun.IsFinite(M21) && Fun.IsFinite(M22) && Fun.IsFinite(M23) && \n                    Fun.IsFinite(M30) && Fun.IsFinite(M31) && Fun.IsFinite(M32) && Fun.IsFinite(M33);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) || float.IsNaN(M01) || float.IsNaN(M02) || float.IsNaN(M03) || \n                    float.IsNaN(M10) || float.IsNaN(M11) || float.IsNaN(M12) || float.IsNaN(M13) || \n                    float.IsNaN(M20) || float.IsNaN(M21) || float.IsNaN(M22) || float.IsNaN(M23) || \n                    float.IsNaN(M30) || float.IsNaN(M31) || float.IsNaN(M32) || float.IsNaN(M33);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNaN(M00) && float.IsNaN(M01) && float.IsNaN(M02) && float.IsNaN(M03) && \n                    float.IsNaN(M10) && float.IsNaN(M11) && float.IsNaN(M12) && float.IsNaN(M13) && \n                    float.IsNaN(M20) && float.IsNaN(M21) && float.IsNaN(M22) && float.IsNaN(M23) && \n                    float.IsNaN(M30) && float.IsNaN(M31) && float.IsNaN(M32) && float.IsNaN(M33);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) || float.IsInfinity(M01) || float.IsInfinity(M02) || float.IsInfinity(M03) || \n                    float.IsInfinity(M10) || float.IsInfinity(M11) || float.IsInfinity(M12) || float.IsInfinity(M13) || \n                    float.IsInfinity(M20) || float.IsInfinity(M21) || float.IsInfinity(M22) || float.IsInfinity(M23) || \n                    float.IsInfinity(M30) || float.IsInfinity(M31) || float.IsInfinity(M32) || float.IsInfinity(M33);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsInfinity(M00) && float.IsInfinity(M01) && float.IsInfinity(M02) && float.IsInfinity(M03) && \n                    float.IsInfinity(M10) && float.IsInfinity(M11) && float.IsInfinity(M12) && float.IsInfinity(M13) && \n                    float.IsInfinity(M20) && float.IsInfinity(M21) && float.IsInfinity(M22) && float.IsInfinity(M23) && \n                    float.IsInfinity(M30) && float.IsInfinity(M31) && float.IsInfinity(M32) && float.IsInfinity(M33);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) || float.IsPositiveInfinity(M01) || float.IsPositiveInfinity(M02) || float.IsPositiveInfinity(M03) || \n                    float.IsPositiveInfinity(M10) || float.IsPositiveInfinity(M11) || float.IsPositiveInfinity(M12) || float.IsPositiveInfinity(M13) || \n                    float.IsPositiveInfinity(M20) || float.IsPositiveInfinity(M21) || float.IsPositiveInfinity(M22) || float.IsPositiveInfinity(M23) || \n                    float.IsPositiveInfinity(M30) || float.IsPositiveInfinity(M31) || float.IsPositiveInfinity(M32) || float.IsPositiveInfinity(M33);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsPositiveInfinity(M00) && float.IsPositiveInfinity(M01) && float.IsPositiveInfinity(M02) && float.IsPositiveInfinity(M03) && \n                    float.IsPositiveInfinity(M10) && float.IsPositiveInfinity(M11) && float.IsPositiveInfinity(M12) && float.IsPositiveInfinity(M13) && \n                    float.IsPositiveInfinity(M20) && float.IsPositiveInfinity(M21) && float.IsPositiveInfinity(M22) && float.IsPositiveInfinity(M23) && \n                    float.IsPositiveInfinity(M30) && float.IsPositiveInfinity(M31) && float.IsPositiveInfinity(M32) && float.IsPositiveInfinity(M33);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) || float.IsNegativeInfinity(M01) || float.IsNegativeInfinity(M02) || float.IsNegativeInfinity(M03) || \n                    float.IsNegativeInfinity(M10) || float.IsNegativeInfinity(M11) || float.IsNegativeInfinity(M12) || float.IsNegativeInfinity(M13) || \n                    float.IsNegativeInfinity(M20) || float.IsNegativeInfinity(M21) || float.IsNegativeInfinity(M22) || float.IsNegativeInfinity(M23) || \n                    float.IsNegativeInfinity(M30) || float.IsNegativeInfinity(M31) || float.IsNegativeInfinity(M32) || float.IsNegativeInfinity(M33);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    float.IsNegativeInfinity(M00) && float.IsNegativeInfinity(M01) && float.IsNegativeInfinity(M02) && float.IsNegativeInfinity(M03) && \n                    float.IsNegativeInfinity(M10) && float.IsNegativeInfinity(M11) && float.IsNegativeInfinity(M12) && float.IsNegativeInfinity(M13) && \n                    float.IsNegativeInfinity(M20) && float.IsNegativeInfinity(M21) && float.IsNegativeInfinity(M22) && float.IsNegativeInfinity(M23) && \n                    float.IsNegativeInfinity(M30) && float.IsNegativeInfinity(M31) && float.IsNegativeInfinity(M32) && float.IsNegativeInfinity(M33);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || Fun.IsTiny(M02) || Fun.IsTiny(M03) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11) || Fun.IsTiny(M12) || Fun.IsTiny(M13) || \n                    Fun.IsTiny(M20) || Fun.IsTiny(M21) || Fun.IsTiny(M22) || Fun.IsTiny(M23) || \n                    Fun.IsTiny(M30) || Fun.IsTiny(M31) || Fun.IsTiny(M32) || Fun.IsTiny(M33);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && Fun.IsTiny(M02) && Fun.IsTiny(M03) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11) && Fun.IsTiny(M12) && Fun.IsTiny(M13) && \n                    Fun.IsTiny(M20) && Fun.IsTiny(M21) && Fun.IsTiny(M22) && Fun.IsTiny(M23) && \n                    Fun.IsTiny(M30) && Fun.IsTiny(M31) && Fun.IsTiny(M32) && Fun.IsTiny(M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 4;\n        public const int ColumnCount = 4;\n        public const int ElementCount = 4 * 4;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(4, 4);\n        }\n\n        public static M44f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M44f(0);\n        }\n\n        public static M44f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M44f(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly float Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + Fun.Abs(M03) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + Fun.Abs(M13) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22) + Fun.Abs(M23) + \n                    Fun.Abs(M30) + Fun.Abs(M31) + Fun.Abs(M32) + Fun.Abs(M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly float Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + M03 * M03 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + M13 * M13 + \n                    M20 * M20 + M21 * M21 + M22 * M22 + M23 * M23 + \n                    M30 * M30 + M31 * M31 + M32 * M32 + M33 * M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)), \n                            Fun.Max(\n                                Fun.Abs(M30), \n                                Fun.Abs(M31), \n                                Fun.Abs(M32), \n                                Fun.Abs(M33)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly float NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)), \n                            Fun.Min(\n                                Fun.Abs(M30), \n                                Fun.Abs(M31), \n                                Fun.Abs(M32), \n                                Fun.Abs(M33)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator -(M44f m)\n        {\n            return new M44f(\n                -m.M00, -m.M01, -m.M02, -m.M03, \n                -m.M10, -m.M11, -m.M12, -m.M13, \n                -m.M20, -m.M21, -m.M22, -m.M23, \n                -m.M30, -m.M31, -m.M32, -m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (M44f a, M44f b)\n        {\n            return new M44f(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (M44f m, float s)\n        {\n            return new M44f(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  + (float s, M44f m)\n        {\n            return new M44f(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (M44f a, M44d b)\n        {\n            return new M44d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (M44f m, double s)\n        {\n            return new M44d(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (double s, M44f m)\n        {\n            return new M44d(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (M44f a, M44f b)\n        {\n            return new M44f(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (M44f m, float s)\n        {\n            return new M44f(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  - (float s, M44f m)\n        {\n            return new M44f(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (M44f a, M44d b)\n        {\n            return new M44d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (M44f m, double s)\n        {\n            return new M44d(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (double s, M44f m)\n        {\n            return new M44d(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (M44f a, M44f b)\n        {\n            return new M44f(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (M44f m, float s)\n        {\n            return new M44f(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  % (float s, M44f m)\n        {\n            return new M44f(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (M44f a, M44d b)\n        {\n            return new M44d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (M44f m, double s)\n        {\n            return new M44d(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (double s, M44f m)\n        {\n            return new M44d(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (M44f a, M44f b)\n        {\n            return new M44f(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (M44f m, float s)\n        {\n            return new M44f(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  / (float s, M44f m)\n        {\n            return new M44f(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (M44f a, M44d b)\n        {\n            return new M44d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (M44f m, double s)\n        {\n            return new M44d(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (double s, M44f m)\n        {\n            return new M44d(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  * (M44f m, float s)\n        {\n            return new M44f(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator  * (float s, M44f m)\n        {\n            return new M44f(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  * (M44f m, double s)\n        {\n            return new M44d(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  * (double s, M44f m)\n        {\n            return new M44d(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M44f matrix with a V4f column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(M44f m, V4f v)\n        {\n            return new V4f(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z + m.M03 * v.W, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z + m.M13 * v.W, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z + m.M23 * v.W, \n                m.M30 * v.X + m.M31 * v.Y + m.M32 * v.Z + m.M33 * v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a V4f row vector with a M44f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(V4f v, M44f m)\n        {\n            return new V4f(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20 + v.W * m.M30, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21 + v.W * m.M31, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22 + v.W * m.M32, \n                v.X * m.M03 + v.Y * m.M13 + v.Z * m.M23 + v.W * m.M33);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M44f a, M44f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23 && \n                a.M30 == b.M30 && \n                a.M31 == b.M31 && \n                a.M32 == b.M32 && \n                a.M33 == b.M33;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M44f a, float s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M03 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M13 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s && \n                a.M23 == s && \n                a.M30 == s && \n                a.M31 == s && \n                a.M32 == s && \n                a.M33 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(float s, M44f a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M03  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M13  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22  && \n                s == a.M23  && \n                s == a.M30  && \n                s == a.M31  && \n                s == a.M32  && \n                s == a.M33 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M44f a, M44f b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M44f m, float s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(float s, M44f m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02, M03),\n                        HashCode.GetCombined(M10, M11, M12, M13),\n                        HashCode.GetCombined(M20, M21, M22, M23),\n                        HashCode.GetCombined(M30, M31, M32, M33));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M44f other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && M03.Equals(other.M03) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && M13.Equals(other.M13) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22) && M23.Equals(other.M23) && \n                M30.Equals(other.M30) && M31.Equals(other.M31) && M32.Equals(other.M32) && M33.Equals(other.M33);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M44f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R3.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M44f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M44f.FromRows(\n                V4f.Parse(x[0]), \n                V4f.Parse(x[1]), \n                V4f.Parse(x[2]), \n                V4f.Parse(x[3])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M44f Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                M44f result = new M44f();\n                for (int row = 0; row < 4; row++)\n                {\n                    for (int col = 0; col < 4; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly float Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 + M22 + M33 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly float Determinant\n        {\n            get\n            {\n                // using bottom row because elements M30, M31, and M32\n                // are zero most of the time.\n                float d = 0;\n                if (M30 != 0.0f) d -= M30 * (\n                M01 * M12 * M23 + M02 * M13 * M21 + M03 * M11 * M22\n                - M21 * M12 * M03 - M22 * M13 * M01 - M23 * M11 * M02\n                );\n                if (M31 != 0.0f) d += M31 * (\n                M00 * M12 * M23 + M02 * M13 * M20 + M03 * M10 * M22\n                - M20 * M12 * M03 - M22 * M13 * M00 - M23 * M10 * M02\n                );\n                if (M32 != 0.0f) d -= M32 * (\n                M00 * M11 * M23 + M01 * M13 * M20 + M03 * M10 * M21\n                - M20 * M11 * M03 - M21 * M13 * M00 - M23 * M10 * M01\n                );\n                if (M33 != 0.0f) d += M33 * (\n                M00 * M11 * M22 + M01 * M12 * M20 + M02 * M10 * M21\n                - M20 * M11 * M02 - M21 * M12 * M00 - M22 * M10 * M01\n                );\n                return d;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M44f Transposed\n        {\n            get\n            {\n                return new M44f {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    M02 = M20, \n                    M03 = M30, \n                    \n                    M10 = M01, \n                    M11 = M11, \n                    M12 = M21, \n                    M13 = M31, \n                    \n                    M20 = M02, \n                    M21 = M12, \n                    M22 = M22, \n                    M23 = M32, \n                    \n                    M30 = M03, \n                    M31 = M13, \n                    M32 = M23, \n                    M33 = M33\n                };\n            }\n        }\n\n        private static V2l s_luSize = new V2l(4, 4);\n        private static V2l s_luDelta = new V2l(1, 4);\n\n        /// <summary>\n        /// Inverts the given matrix using lu factorization in place. Returns true\n        /// if the matrix was invertible, otherwise the matrix remains unchanged.\n        /// </summary>\n        public bool LuInvert()\n        {\n            M44d dbl = (M44d)this;\n            if(dbl.LuInvert())\n            {\n                this = (M44f)dbl;\n                return true;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns the inverse of the matrix using lu factorization.\n        /// If the matrix is not invertible, M44f.Zero is returned.\n        /// </summary>\n        public readonly M44f LuInverse()\n        {\n            return (M44f)((M44d)this).LuInverse();\n        }\n\n        /// <summary>\n        /// Returns the inverse of this matrix. If the matrix is not invertible\n        /// M44f.Zero is returned.\n        /// </summary>\n        public readonly M44f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => LuInverse();\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M44f operator *(M44f a, M44f b)\n        {\n            return new M44f(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20 + a.M03 * b.M30, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21 + a.M03 * b.M31, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22 + a.M03 * b.M32, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03 * b.M33, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20 + a.M13 * b.M30, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20 + a.M23 * b.M30, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33, \n                a.M30 * b.M00 + a.M31 * b.M10 + a.M32 * b.M20 + a.M33 * b.M30, \n                a.M30 * b.M01 + a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31, \n                a.M30 * b.M02 + a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32, \n                a.M30 * b.M03 + a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return (double)this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = (float)value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return (double)this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = (float)value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (float)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (float)value;\n        }\n\n        #endregion\n    }\n\n    public class M44fEqualityComparer : IEqualityComparer<M44f>\n    {\n        public static readonly M44fEqualityComparer Default\n            = new M44fEqualityComparer();\n\n        #region IEqualityComparer<M44f> Members\n\n        public bool Equals(M44f v0, M44f v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M44f v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale(this M44f m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length + m.C3.Length) / 4;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f GetScaleVector(this M44f m)\n            => new V4f(m.C0.Length, m.C1.Length, m.C2.Length, m.C3.Length);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of 3D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale3(this M44f m)\n            => (m.C0.XYZ.Length + m.C1.XYZ.Length + m.C2.XYZ.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the 3D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetScaleVector3(this M44f m)\n            => new V3f(m.C0.XYZ.Length, m.C1.XYZ.Length, m.C2.XYZ.Length);\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A left-handed coordinates system transformation is expected,\n        /// where the view-space z-axis points in forward direction.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetViewDirectionLH(this M44f m)\n            => m.R2.XYZ.Normalized;\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A right-handed coordinates system transformation is expected, where\n        /// the view-space z-axis points opposit the forward vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetViewDirectionRH(this M44f m)\n            => -m.R2.XYZ.Normalized;\n\n        /// <summary>\n        /// Extracts the translation component of the given transformation matrix, which when given\n        /// a model transformation represents the model origin in world position.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetModelOrigin(this M44f m)\n            => m.C3.XYZ;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm1(M44f m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm2(M44f m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMax(M44f m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMin(M44f m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(this M44f m, float p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M03).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M13).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p) + \n                Fun.Abs(m.M23).Pow(p) + \n                Fun.Abs(m.M30).Pow(p) + \n                Fun.Abs(m.M31).Pow(p) + \n                Fun.Abs(m.M32).Pow(p) + \n                Fun.Abs(m.M33).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static float Distance1(this M44f a, M44f b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M03 - a.M03) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M13 - a.M13) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22) + \n                Fun.Abs(b.M23 - a.M23) + \n                Fun.Abs(b.M30 - a.M30) + \n                Fun.Abs(b.M31 - a.M31) + \n                Fun.Abs(b.M32 - a.M32) + \n                Fun.Abs(b.M33 - a.M33);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static float Distance2(this M44f a, M44f b)\n        {\n            return (float)Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M03 - a.M03) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M13 - a.M13) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22) + \n                        Fun.Square(b.M23 - a.M23) + \n                        Fun.Square(b.M30 - a.M30) + \n                        Fun.Square(b.M31 - a.M31) + \n                        Fun.Square(b.M32 - a.M32) + \n                        Fun.Square(b.M33 - a.M33));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static float Distance(this M44f a, M44f b, float p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M03 - a.M03).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M13 - a.M13).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p) + \n                Fun.Abs(b.M23 - a.M23).Pow(p) + \n                Fun.Abs(b.M30 - a.M30).Pow(p) + \n                Fun.Abs(b.M31 - a.M31).Pow(p) + \n                Fun.Abs(b.M32 - a.M32).Pow(p) + \n                Fun.Abs(b.M33 - a.M33).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMax(this M44f a, M44f b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)), \n                        Fun.Max(\n                            Fun.Abs(b.M30 - a.M30), \n                            Fun.Abs(b.M31 - a.M31), \n                            Fun.Abs(b.M32 - a.M32), \n                            Fun.Abs(b.M33 - a.M33)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static float DistanceMin(this M44f a, M44f b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)), \n                        Fun.Min(\n                            Fun.Abs(b.M30 - a.M30), \n                            Fun.Abs(b.M31 - a.M31), \n                            Fun.Abs(b.M32 - a.M32), \n                            Fun.Abs(b.M33 - a.M33)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this M44f m, V4f v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f TransposedTransform(this M44f m, V4f v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V3f TransformDir(this M44f m, V3f v)\n        {\n            return new V3f(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V3f TransformPos(this M44f m, V3f p)\n        {\n            return new V3f(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V3f TransformPosProj(this M44f m, V3f p)\n        {\n            float s = m.M30 * p.X + m.M31 * p.Y + m.M32 * p.Z + m.M33;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V4f TransformPosProjFull(this M44f m, V3f p)\n        {\n            return new V4f(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23, \n                m.M30 * p.X + m.M31 * p.Y + m.M32 * p.Z + m.M33\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static V3f TransposedTransformDir(this M44f m, V3f v)\n        {\n            return new V3f(\n                m.M00 * v.X + m.M10 * v.Y + m.M20 * v.Z, \n                m.M01 * v.X + m.M11 * v.Y + m.M21 * v.Z, \n                m.M02 * v.X + m.M12 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V3f TransposedTransformPos(this M44f m, V3f p)\n        {\n            return new V3f(\n                m.M00 * p.X + m.M10 * p.Y + m.M20 * p.Z + m.M30, \n                m.M01 * p.X + m.M11 * p.Y + m.M21 * p.Z + m.M31, \n                m.M02 * p.X + m.M12 * p.Y + m.M22 * p.Z + m.M32\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V3f TransposedTransformPosProj(this M44f m, V3f p)\n        {\n            var s = m.M03 * p.X + m.M13 * p.Y + m.M23 * p.Z + m.M33;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static V3f TransposedTransformProj(this M44f m, V3f p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V4f TransposedTransformPosProjFull(this M44f m, V3f p)\n        {\n            return new V4f(\n                m.M00 * p.X + m.M10 * p.Y + m.M20 * p.Z + m.M30, \n                m.M01 * p.X + m.M11 * p.Y + m.M21 * p.Z + m.M31, \n                m.M02 * p.X + m.M12 * p.Y + m.M22 * p.Z + m.M32, \n                m.M03 * p.X + m.M13 * p.Y + m.M23 * p.Z + m.M33\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static V4f TransposedTransformProjFull(this M44f m, V3f p)\n            => m.TransposedTransformPosProjFull(p);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M44f\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static M33f Minor(this M44f m, int row, int column)\n        {\n            M33f rs = new M33f();\n\n            for (int k = 0; k < 9; k++)\n            {\n                var i = k / 3;\n                var j = k % 3;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * 4 + jj];\n            }\n\n            return rs;\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4f Row(this M44f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V4f(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4f Column(this M44f m, int index)\n        {\n            float* ptr = &m.M00;\n            return new V4f(ptr[index], ptr[index + 4], ptr[index + 8], ptr[index + 12]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Determinant(M44f m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Transposed(M44f m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M44f m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n            Fun.Swap(ref m.M20, ref m.M02);\n            Fun.Swap(ref m.M21, ref m.M12);\n            Fun.Swap(ref m.M30, ref m.M03);\n            Fun.Swap(ref m.M31, ref m.M13);\n            Fun.Swap(ref m.M32, ref m.M23);\n        }\n\n        /// <summary>\n        /// Returns the inverse of the given matrix. If the matrix is not invertible\n        /// M44f.Zero is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Inverse(M44f m)\n            => m.Inverse;\n\n        /// <summary>\n        /// Inverts the given matrix in place. Returns true if the matrix was invertible,\n        /// otherwise the matrix remains unchanged.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Invert(this ref M44f m) { return m.LuInvert(); }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M44f m, float epsilon)\n        {\n            return Fun.ApproximateEquals(m, M44f.Identity, epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M44f m)\n            => IsIdentity(m, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M44f m, float epsilon)\n        {\n            var i = m * m.Transposed;\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M44f m)\n            => IsOrthonormal(m, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M44f m, float epsilon)\n        {\n            var i = m * m.Transposed;\n            for (int j = 0; j < 4; j++)\n                i[j, j] = 1; //inefficient implementation: just leave out the comparisons at the diagonal entries.\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M44f m)\n            => IsOrthogonal(m, Constant<float>.PositiveTinyValue);\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M44f a, M44f b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M03 < b.M03 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M13 < b.M13 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22 && \n                a.M23 < b.M23 && \n                a.M30 < b.M30 && \n                a.M31 < b.M31 && \n                a.M32 < b.M32 && \n                a.M33 < b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M44f m, float s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M03 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M13 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s && \n                m.M23 < s && \n                m.M30 < s && \n                m.M31 < s && \n                m.M32 < s && \n                m.M33 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, M44f m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M03 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M13 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22 && \n                s < m.M23 && \n                s < m.M30 && \n                s < m.M31 && \n                s < m.M32 && \n                s < m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M44f a, M44f b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M03 < b.M03 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M13 < b.M13 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22 || \n                a.M23 < b.M23 || \n                a.M30 < b.M30 || \n                a.M31 < b.M31 || \n                a.M32 < b.M32 || \n                a.M33 < b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M44f m, float s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M03 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M13 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s || \n                m.M23 < s || \n                m.M30 < s || \n                m.M31 < s || \n                m.M32 < s || \n                m.M33 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, M44f m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M03 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M13 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22 || \n                s < m.M23 || \n                s < m.M30 || \n                s < m.M31 || \n                s < m.M32 || \n                s < m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M44f a, M44f b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M03 > b.M03 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M13 > b.M13 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22 && \n                a.M23 > b.M23 && \n                a.M30 > b.M30 && \n                a.M31 > b.M31 && \n                a.M32 > b.M32 && \n                a.M33 > b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M44f m, float s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M03 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M13 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s && \n                m.M23 > s && \n                m.M30 > s && \n                m.M31 > s && \n                m.M32 > s && \n                m.M33 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, M44f m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M03 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M13 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22 && \n                s > m.M23 && \n                s > m.M30 && \n                s > m.M31 && \n                s > m.M32 && \n                s > m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M44f a, M44f b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M03 > b.M03 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M13 > b.M13 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22 || \n                a.M23 > b.M23 || \n                a.M30 > b.M30 || \n                a.M31 > b.M31 || \n                a.M32 > b.M32 || \n                a.M33 > b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M44f m, float s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M03 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M13 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s || \n                m.M23 > s || \n                m.M30 > s || \n                m.M31 > s || \n                m.M32 > s || \n                m.M33 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, M44f m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M03 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M13 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22 || \n                s > m.M23 || \n                s > m.M30 || \n                s > m.M31 || \n                s > m.M32 || \n                s > m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M44f a, M44f b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M03 <= b.M03 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M13 <= b.M13 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22 && \n                a.M23 <= b.M23 && \n                a.M30 <= b.M30 && \n                a.M31 <= b.M31 && \n                a.M32 <= b.M32 && \n                a.M33 <= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M44f m, float s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M03 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M13 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s && \n                m.M23 <= s && \n                m.M30 <= s && \n                m.M31 <= s && \n                m.M32 <= s && \n                m.M33 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, M44f m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M03 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M13 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22 && \n                s <= m.M23 && \n                s <= m.M30 && \n                s <= m.M31 && \n                s <= m.M32 && \n                s <= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M44f a, M44f b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M03 <= b.M03 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M13 <= b.M13 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22 || \n                a.M23 <= b.M23 || \n                a.M30 <= b.M30 || \n                a.M31 <= b.M31 || \n                a.M32 <= b.M32 || \n                a.M33 <= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M44f m, float s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M03 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M13 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s || \n                m.M23 <= s || \n                m.M30 <= s || \n                m.M31 <= s || \n                m.M32 <= s || \n                m.M33 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, M44f m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M03 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M13 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22 || \n                s <= m.M23 || \n                s <= m.M30 || \n                s <= m.M31 || \n                s <= m.M32 || \n                s <= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M44f a, M44f b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M03 >= b.M03 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M13 >= b.M13 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22 && \n                a.M23 >= b.M23 && \n                a.M30 >= b.M30 && \n                a.M31 >= b.M31 && \n                a.M32 >= b.M32 && \n                a.M33 >= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M44f m, float s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M03 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M13 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s && \n                m.M23 >= s && \n                m.M30 >= s && \n                m.M31 >= s && \n                m.M32 >= s && \n                m.M33 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, M44f m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M03 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M13 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22 && \n                s >= m.M23 && \n                s >= m.M30 && \n                s >= m.M31 && \n                s >= m.M32 && \n                s >= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M44f a, M44f b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M03 >= b.M03 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M13 >= b.M13 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22 || \n                a.M23 >= b.M23 || \n                a.M30 >= b.M30 || \n                a.M31 >= b.M31 || \n                a.M32 >= b.M32 || \n                a.M33 >= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M44f m, float s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M03 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M13 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s || \n                m.M23 >= s || \n                m.M30 >= s || \n                m.M31 >= s || \n                m.M32 >= s || \n                m.M33 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, M44f m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M03 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M13 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22 || \n                s >= m.M23 || \n                s >= m.M30 || \n                s >= m.M31 || \n                s >= m.M32 || \n                s >= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M44f a, M44f b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23 && \n                a.M30 == b.M30 && \n                a.M31 == b.M31 && \n                a.M32 == b.M32 && \n                a.M33 == b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M44f m, float s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M03 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M13 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s && \n                m.M23 == s && \n                m.M30 == s && \n                m.M31 == s && \n                m.M32 == s && \n                m.M33 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, M44f m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M03 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M13 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22 && \n                s == m.M23 && \n                s == m.M30 && \n                s == m.M31 && \n                s == m.M32 && \n                s == m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M44f a, M44f b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M03 == b.M03 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M13 == b.M13 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22 || \n                a.M23 == b.M23 || \n                a.M30 == b.M30 || \n                a.M31 == b.M31 || \n                a.M32 == b.M32 || \n                a.M33 == b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M44f m, float s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M03 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M13 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s || \n                m.M23 == s || \n                m.M30 == s || \n                m.M31 == s || \n                m.M32 == s || \n                m.M33 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, M44f m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M03 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M13 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22 || \n                s == m.M23 || \n                s == m.M30 || \n                s == m.M31 || \n                s == m.M32 || \n                s == m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M44f a, M44f b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M03 != b.M03 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M13 != b.M13 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22 && \n                a.M23 != b.M23 && \n                a.M30 != b.M30 && \n                a.M31 != b.M31 && \n                a.M32 != b.M32 && \n                a.M33 != b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M44f m, float s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M03 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M13 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s && \n                m.M23 != s && \n                m.M30 != s && \n                m.M31 != s && \n                m.M32 != s && \n                m.M33 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, M44f m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M03 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M13 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22 && \n                s != m.M23 && \n                s != m.M30 && \n                s != m.M31 && \n                s != m.M32 && \n                s != m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M44f a, M44f b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M03 != b.M03 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M13 != b.M13 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22 || \n                a.M23 != b.M23 || \n                a.M30 != b.M30 || \n                a.M31 != b.M31 || \n                a.M32 != b.M32 || \n                a.M33 != b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M44f m, float s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M03 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M13 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s || \n                m.M23 != s || \n                m.M30 != s || \n                m.M31 != s || \n                m.M32 != s || \n                m.M33 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, M44f m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M03 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M13 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22 || \n                s != m.M23 || \n                s != m.M30 || \n                s != m.M31 || \n                s != m.M32 || \n                s != m.M33;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M44f m0, M44f m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M03 < m1.M03) return -1;\n            if (m0.M03 > m1.M03) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M13 < m1.M13) return -1;\n            if (m0.M13 > m1.M13) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            if (m0.M23 < m1.M23) return -1;\n            if (m0.M23 > m1.M23) return +1;\n            if (m0.M30 < m1.M30) return -1;\n            if (m0.M30 > m1.M30) return +1;\n            if (m0.M31 < m1.M31) return -1;\n            if (m0.M31 > m1.M31) return +1;\n            if (m0.M32 < m1.M32) return -1;\n            if (m0.M32 > m1.M32) return +1;\n            if (m0.M33 < m1.M33) return -1;\n            if (m0.M33 > m1.M33) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M44f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MinElement(M44f m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M44f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MaxElement(M44f m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region Orthogonalization\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M44f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthogonalize(this ref M44f matrix)\n        {\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C0, matrix.C3) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C3 -= (Vec.Dot(matrix.C1, matrix.C3) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C2, matrix.C3) / Vec.Dot(matrix.C2, matrix.C2)) * matrix.C2;\n            matrix.C3 -= (Vec.Dot(matrix.C0, matrix.C3) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C3 -= (Vec.Dot(matrix.C1, matrix.C3) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C2, matrix.C3) / Vec.Dot(matrix.C2, matrix.C2)) * matrix.C2;\n        }\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M44f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Orthogonalized(this M44f matrix)\n        {\n            M44f m = matrix;\n            Orthogonalize(ref m);\n            return m;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M44f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthonormalize(this ref M44f matrix)\n        {\n            matrix.C0 = matrix.C0.Normalized;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 = matrix.C1.Normalized;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 = matrix.C2.Normalized;\n            matrix.C3 -= (Vec.Dot(matrix.C0, matrix.C3) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C3 -= (Vec.Dot(matrix.C1, matrix.C3) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C2, matrix.C3) / Vec.Dot(matrix.C2, matrix.C2)) * matrix.C2;\n            matrix.C3 -= (Vec.Dot(matrix.C0, matrix.C3) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C3 -= (Vec.Dot(matrix.C1, matrix.C3) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C2, matrix.C3) / Vec.Dot(matrix.C2, matrix.C2)) * matrix.C2;\n            matrix.C3 = matrix.C3.Normalized;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M44f\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Orthonormalized(this M44f matrix)\n        {\n            M44f m = matrix;\n            Orthonormalize(ref m);\n            return m;\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M44f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M44f m, float epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M03.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M13.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon) || m.M23.IsTiny(epsilon) || m.M30.IsTiny(epsilon) || m.M31.IsTiny(epsilon) || m.M32.IsTiny(epsilon) || m.M33.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M44f m, float epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M03.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M13.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon) && m.M23.IsTiny(epsilon) && m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon) && m.M33.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M44f m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M44f m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M44f m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M44f m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M44f m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M44f m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M44f m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M44f m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M44f m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M44f m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M44f m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M44f m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M44f a, M44f b)\n            => ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M44f a, M44f b, float epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M44f m, float epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M44f m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M44f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M44f v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M44f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M44f v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M44f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M44f v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M44f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M44f v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M44f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M44f v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM44fExtensions\n    {\n        #region IRandomUniform extensions for M44f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of an M44f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f UniformM44f(this IRandomUniform rnd)\n        {\n            return new M44f(\n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), \n                rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of an M44f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f UniformM44fClosed(this IRandomUniform rnd)\n        {\n            return new M44f(\n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), \n                rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of an M44f matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f UniformM44fOpen(this IRandomUniform rnd)\n        {\n            return new M44f(\n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), \n                rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region M44d\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct M44d : IEquatable<M44d>, IValidity, IMatrix<double>\n    {\n        [DataMember]\n        public double M00, M01, M02, M03;\n        [DataMember]\n        public double M10, M11, M12, M13;\n        [DataMember]\n        public double M20, M21, M22, M23;\n        [DataMember]\n        public double M30, M31, M32, M33;\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(double value)\n        {\n            M00 = value; M01 = 0; M02 = 0; M03 = 0; \n            M10 = 0; M11 = value; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = value; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = value; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(\n                double m00, double m01, double m02, double m03, \n                double m10, double m11, double m12, double m13, \n                double m20, double m21, double m22, double m23, \n                double m30, double m31, double m32, double m33)\n        {\n            M00 = m00; M01 = m01; M02 = m02; M03 = m03; \n            M10 = m10; M11 = m11; M12 = m12; M13 = m13; \n            M20 = m20; M21 = m21; M22 = m22; M23 = m23; \n            M30 = m30; M31 = m31; M32 = m32; M33 = m33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(double[] a)\n        {\n            M00 = a[0];\n            M01 = a[1];\n            M02 = a[2];\n            M03 = a[3];\n            M10 = a[4];\n            M11 = a[5];\n            M12 = a[6];\n            M13 = a[7];\n            M20 = a[8];\n            M21 = a[9];\n            M22 = a[10];\n            M23 = a[11];\n            M30 = a[12];\n            M31 = a[13];\n            M32 = a[14];\n            M33 = a[15];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(double[] a, int start)\n        {\n            M00 = a[start + 0];\n            M01 = a[start + 1];\n            M02 = a[start + 2];\n            M03 = a[start + 3];\n            M10 = a[start + 4];\n            M11 = a[start + 5];\n            M12 = a[start + 6];\n            M13 = a[start + 7];\n            M20 = a[start + 8];\n            M21 = a[start + 9];\n            M22 = a[start + 10];\n            M23 = a[start + 11];\n            M30 = a[start + 12];\n            M31 = a[start + 13];\n            M32 = a[start + 14];\n            M33 = a[start + 15];\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M22i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M23i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M33i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M34i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M44i m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n            M30 = (double)m.M30; M31 = (double)m.M31; M32 = (double)m.M32; M33 = (double)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M22l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M23l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M33l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M34l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M44l m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n            M30 = (double)m.M30; M31 = (double)m.M31; M32 = (double)m.M32; M33 = (double)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M22f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = 0; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M23f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M33f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = 0; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = 0; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M34f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M44f m)\n        {\n            M00 = (double)m.M00; M01 = (double)m.M01; M02 = (double)m.M02; M03 = (double)m.M03; \n            M10 = (double)m.M10; M11 = (double)m.M11; M12 = (double)m.M12; M13 = (double)m.M13; \n            M20 = (double)m.M20; M21 = (double)m.M21; M22 = (double)m.M22; M23 = (double)m.M23; \n            M30 = (double)m.M30; M31 = (double)m.M31; M32 = (double)m.M32; M33 = (double)m.M33; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M22d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = 0; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = 0; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M23d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = 0; M21 = 0; M22 = 1; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M33d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = 0; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = 0; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = 0; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public M44d(M34d m)\n        {\n            M00 = m.M00; M01 = m.M01; M02 = m.M02; M03 = m.M03; \n            M10 = m.M10; M11 = m.M11; M12 = m.M12; M13 = m.M13; \n            M20 = m.M20; M21 = m.M21; M22 = m.M22; M23 = m.M23; \n            M30 = 0; M31 = 0; M32 = 0; M33 = 1; \n        }\n\n        #endregion\n\n        #region Conversions\n\n        public static explicit operator M44d(M22i m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M23i m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M33i m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M34i m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M44i m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n                M30 = (double)m.M30, M31 = (double)m.M31, M32 = (double)m.M32, M33 = (double)m.M33, \n            };\n        }\n\n        public static explicit operator M44d(M22l m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M23l m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M33l m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M34l m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M44l m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n                M30 = (double)m.M30, M31 = (double)m.M31, M32 = (double)m.M32, M33 = (double)m.M33, \n            };\n        }\n\n        public static explicit operator M44d(M22f m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = 0, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M23f m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M33f m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = 0, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = 0, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M34f m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M44f m)\n        {\n            return new M44d {\n                M00 = (double)m.M00, M01 = (double)m.M01, M02 = (double)m.M02, M03 = (double)m.M03, \n                M10 = (double)m.M10, M11 = (double)m.M11, M12 = (double)m.M12, M13 = (double)m.M13, \n                M20 = (double)m.M20, M21 = (double)m.M21, M22 = (double)m.M22, M23 = (double)m.M23, \n                M30 = (double)m.M30, M31 = (double)m.M31, M32 = (double)m.M32, M33 = (double)m.M33, \n            };\n        }\n\n        public static explicit operator M44d(M22d m)\n        {\n            return new M44d {\n                M00 = m.M00, M01 = m.M01, M02 = 0, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = 0, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M23d m)\n        {\n            return new M44d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = 0, M21 = 0, M22 = 1, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M33d m)\n        {\n            return new M44d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = 0, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = 0, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = 0, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(M34d m)\n        {\n            return new M44d {\n                M00 = m.M00, M01 = m.M01, M02 = m.M02, M03 = m.M03, \n                M10 = m.M10, M11 = m.M11, M12 = m.M12, M13 = m.M13, \n                M20 = m.M20, M21 = m.M21, M22 = m.M22, M23 = m.M23, \n                M30 = 0, M31 = 0, M32 = 0, M33 = 1, \n            };\n        }\n\n        public static explicit operator M44d(int[] a)\n        {\n            return new M44d(\n                (double)a[0], (double)a[1], (double)a[2], (double)a[3], \n                (double)a[4], (double)a[5], (double)a[6], (double)a[7], \n                (double)a[8], (double)a[9], (double)a[10], (double)a[11], \n                (double)a[12], (double)a[13], (double)a[14], (double)a[15]);\n        }\n\n        public static explicit operator M44d(int[,] a)\n        {\n            return new M44d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], (double)a[0, 3], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], (double)a[1, 3], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2], (double)a[2, 3], \n                (double)a[3, 0], (double)a[3, 1], (double)a[3, 2], (double)a[3, 3]);\n        }\n\n        public static explicit operator int[](M44d m)\n        {\n            return new int[] {\n                (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03, \n                (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13, \n                (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23, \n                (int)m.M30, (int)m.M31, (int)m.M32, (int)m.M33\n            };\n        }\n\n        public static explicit operator int[,](M44d m)\n        {\n            return new int[,] {\n                { (int)m.M00, (int)m.M01, (int)m.M02, (int)m.M03 }, \n                { (int)m.M10, (int)m.M11, (int)m.M12, (int)m.M13 }, \n                { (int)m.M20, (int)m.M21, (int)m.M22, (int)m.M23 }, \n                { (int)m.M30, (int)m.M31, (int)m.M32, (int)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(int[] array, long index)\n        {\n            array[index + 0] = (int)M00;\n            array[index + 1] = (int)M01;\n            array[index + 2] = (int)M02;\n            array[index + 3] = (int)M03;\n            array[index + 4] = (int)M10;\n            array[index + 5] = (int)M11;\n            array[index + 6] = (int)M12;\n            array[index + 7] = (int)M13;\n            array[index + 8] = (int)M20;\n            array[index + 9] = (int)M21;\n            array[index + 10] = (int)M22;\n            array[index + 11] = (int)M23;\n            array[index + 12] = (int)M30;\n            array[index + 13] = (int)M31;\n            array[index + 14] = (int)M32;\n            array[index + 15] = (int)M33;\n        }\n\n        public static explicit operator M44d(long[] a)\n        {\n            return new M44d(\n                (double)a[0], (double)a[1], (double)a[2], (double)a[3], \n                (double)a[4], (double)a[5], (double)a[6], (double)a[7], \n                (double)a[8], (double)a[9], (double)a[10], (double)a[11], \n                (double)a[12], (double)a[13], (double)a[14], (double)a[15]);\n        }\n\n        public static explicit operator M44d(long[,] a)\n        {\n            return new M44d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], (double)a[0, 3], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], (double)a[1, 3], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2], (double)a[2, 3], \n                (double)a[3, 0], (double)a[3, 1], (double)a[3, 2], (double)a[3, 3]);\n        }\n\n        public static explicit operator long[](M44d m)\n        {\n            return new long[] {\n                (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03, \n                (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13, \n                (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23, \n                (long)m.M30, (long)m.M31, (long)m.M32, (long)m.M33\n            };\n        }\n\n        public static explicit operator long[,](M44d m)\n        {\n            return new long[,] {\n                { (long)m.M00, (long)m.M01, (long)m.M02, (long)m.M03 }, \n                { (long)m.M10, (long)m.M11, (long)m.M12, (long)m.M13 }, \n                { (long)m.M20, (long)m.M21, (long)m.M22, (long)m.M23 }, \n                { (long)m.M30, (long)m.M31, (long)m.M32, (long)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(long[] array, long index)\n        {\n            array[index + 0] = (long)M00;\n            array[index + 1] = (long)M01;\n            array[index + 2] = (long)M02;\n            array[index + 3] = (long)M03;\n            array[index + 4] = (long)M10;\n            array[index + 5] = (long)M11;\n            array[index + 6] = (long)M12;\n            array[index + 7] = (long)M13;\n            array[index + 8] = (long)M20;\n            array[index + 9] = (long)M21;\n            array[index + 10] = (long)M22;\n            array[index + 11] = (long)M23;\n            array[index + 12] = (long)M30;\n            array[index + 13] = (long)M31;\n            array[index + 14] = (long)M32;\n            array[index + 15] = (long)M33;\n        }\n\n        public static explicit operator M44d(float[] a)\n        {\n            return new M44d(\n                (double)a[0], (double)a[1], (double)a[2], (double)a[3], \n                (double)a[4], (double)a[5], (double)a[6], (double)a[7], \n                (double)a[8], (double)a[9], (double)a[10], (double)a[11], \n                (double)a[12], (double)a[13], (double)a[14], (double)a[15]);\n        }\n\n        public static explicit operator M44d(float[,] a)\n        {\n            return new M44d(\n                (double)a[0, 0], (double)a[0, 1], (double)a[0, 2], (double)a[0, 3], \n                (double)a[1, 0], (double)a[1, 1], (double)a[1, 2], (double)a[1, 3], \n                (double)a[2, 0], (double)a[2, 1], (double)a[2, 2], (double)a[2, 3], \n                (double)a[3, 0], (double)a[3, 1], (double)a[3, 2], (double)a[3, 3]);\n        }\n\n        public static explicit operator float[](M44d m)\n        {\n            return new float[] {\n                (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03, \n                (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13, \n                (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23, \n                (float)m.M30, (float)m.M31, (float)m.M32, (float)m.M33\n            };\n        }\n\n        public static explicit operator float[,](M44d m)\n        {\n            return new float[,] {\n                { (float)m.M00, (float)m.M01, (float)m.M02, (float)m.M03 }, \n                { (float)m.M10, (float)m.M11, (float)m.M12, (float)m.M13 }, \n                { (float)m.M20, (float)m.M21, (float)m.M22, (float)m.M23 }, \n                { (float)m.M30, (float)m.M31, (float)m.M32, (float)m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(float[] array, long index)\n        {\n            array[index + 0] = (float)M00;\n            array[index + 1] = (float)M01;\n            array[index + 2] = (float)M02;\n            array[index + 3] = (float)M03;\n            array[index + 4] = (float)M10;\n            array[index + 5] = (float)M11;\n            array[index + 6] = (float)M12;\n            array[index + 7] = (float)M13;\n            array[index + 8] = (float)M20;\n            array[index + 9] = (float)M21;\n            array[index + 10] = (float)M22;\n            array[index + 11] = (float)M23;\n            array[index + 12] = (float)M30;\n            array[index + 13] = (float)M31;\n            array[index + 14] = (float)M32;\n            array[index + 15] = (float)M33;\n        }\n\n        public static explicit operator M44d(double[] a)\n        {\n            return new M44d(\n                a[0], a[1], a[2], a[3], \n                a[4], a[5], a[6], a[7], \n                a[8], a[9], a[10], a[11], \n                a[12], a[13], a[14], a[15]);\n        }\n\n        public static explicit operator M44d(double[,] a)\n        {\n            return new M44d(\n                a[0, 0], a[0, 1], a[0, 2], a[0, 3], \n                a[1, 0], a[1, 1], a[1, 2], a[1, 3], \n                a[2, 0], a[2, 1], a[2, 2], a[2, 3], \n                a[3, 0], a[3, 1], a[3, 2], a[3, 3]);\n        }\n\n        public static explicit operator double[](M44d m)\n        {\n            return new double[] {\n                m.M00, m.M01, m.M02, m.M03, \n                m.M10, m.M11, m.M12, m.M13, \n                m.M20, m.M21, m.M22, m.M23, \n                m.M30, m.M31, m.M32, m.M33\n            };\n        }\n\n        public static explicit operator double[,](M44d m)\n        {\n            return new double[,] {\n                { m.M00, m.M01, m.M02, m.M03 }, \n                { m.M10, m.M11, m.M12, m.M13 }, \n                { m.M20, m.M21, m.M22, m.M23 }, \n                { m.M30, m.M31, m.M32, m.M33 }\n            };\n        }\n\n        public readonly void CopyTo(double[] array, long index)\n        {\n            array[index + 0] = M00;\n            array[index + 1] = M01;\n            array[index + 2] = M02;\n            array[index + 3] = M03;\n            array[index + 4] = M10;\n            array[index + 5] = M11;\n            array[index + 6] = M12;\n            array[index + 7] = M13;\n            array[index + 8] = M20;\n            array[index + 9] = M21;\n            array[index + 10] = M22;\n            array[index + 11] = M23;\n            array[index + 12] = M30;\n            array[index + 13] = M31;\n            array[index + 14] = M32;\n            array[index + 15] = M33;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44i Copy(Func<double, int> element_fun)\n        {\n            return new M44i(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44i Copy(Func<double, int, int, int> element_index0_index1_fun)\n        {\n            return new M44i(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44l Copy(Func<double, long> element_fun)\n        {\n            return new M44l(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44l Copy(Func<double, int, int, long> element_index0_index1_fun)\n        {\n            return new M44l(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44f Copy(Func<double, float> element_fun)\n        {\n            return new M44f(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44f Copy(Func<double, int, int, float> element_index0_index1_fun)\n        {\n            return new M44f(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44d Copy(Func<double, double> element_fun)\n        {\n            return new M44d(\n                element_fun(M00), element_fun(M01), element_fun(M02), element_fun(M03), \n                element_fun(M10), element_fun(M11), element_fun(M12), element_fun(M13), \n                element_fun(M20), element_fun(M21), element_fun(M22), element_fun(M23), \n                element_fun(M30), element_fun(M31), element_fun(M32), element_fun(M33));\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly M44d Copy(Func<double, int, int, double> element_index0_index1_fun)\n        {\n            return new M44d(\n                element_index0_index1_fun(M00, 0, 0), element_index0_index1_fun(M01, 0, 1), element_index0_index1_fun(M02, 0, 2), element_index0_index1_fun(M03, 0, 3), \n                element_index0_index1_fun(M10, 1, 0), element_index0_index1_fun(M11, 1, 1), element_index0_index1_fun(M12, 1, 2), element_index0_index1_fun(M13, 1, 3), \n                element_index0_index1_fun(M20, 2, 0), element_index0_index1_fun(M21, 2, 1), element_index0_index1_fun(M22, 2, 2), element_index0_index1_fun(M23, 2, 3), \n                element_index0_index1_fun(M30, 3, 0), element_index0_index1_fun(M31, 3, 1), element_index0_index1_fun(M32, 3, 2), element_index0_index1_fun(M33, 3, 3));\n        }\n\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly M33d UpperLeftM33()\n        {\n            return (M33d)this;\n        }\n\n        public readonly double[] ToArray()\n        {\n            var array = new double[16];\n            array[0] = M00;\n            array[1] = M01;\n            array[2] = M02;\n            array[3] = M03;\n            array[4] = M10;\n            array[5] = M11;\n            array[6] = M12;\n            array[7] = M13;\n            array[8] = M20;\n            array[9] = M21;\n            array[10] = M22;\n            array[11] = M23;\n            array[12] = M30;\n            array[13] = M31;\n            array[14] = M32;\n            array[15] = M33;\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d FromCols(V4d col0, V4d col1, V4d col2, V4d col3)\n        {\n            return new M44d(\n                col0.X, col1.X, col2.X, col3.X, \n                col0.Y, col1.Y, col2.Y, col3.Y, \n                col0.Z, col1.Z, col2.Z, col3.Z, \n                col0.W, col1.W, col2.W, col3.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d FromRows(V4d row0, V4d row1, V4d row2, V4d row3)\n        {\n            return new M44d(\n                row0.X, row0.Y, row0.Z, row0.W, \n                row1.X, row1.Y, row1.Z, row1.W, \n                row2.X, row2.Y, row2.Z, row2.W, \n                row3.X, row3.Y, row3.Z, row3.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d FromDiagonal(double value)\n        {\n            return new M44d(\n                value, 0, 0, 0, \n                0, value, 0, 0, \n                0, 0, value, 0, \n                0, 0, 0, value);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d FromDiagonal(double m00, double m11, double m22, double m33)\n        {\n            return new M44d(\n                m00, 0, 0, 0, \n                0, m11, 0, 0, \n                0, 0, m22, 0, \n                0, 0, 0, m33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d FromDiagonal(V4d s)\n        {\n            return new M44d(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, s.W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d FromAntiDiagonal(double value)\n        {\n            return new M44d(\n                 0, 0, 0, value, \n                 0, 0, value, 0, \n                 0, value, 0, 0, \n                 value, 0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d FromAntiDiagonal(double m03, double m12, double m21, double m30)\n        {\n            return new M44d(\n                0, 0, 0, m03, \n                0, 0, m12, 0, \n                0, m21, 0, 0, \n                m30, 0, 0, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d FromAntiDiagonal(V4d s)\n        {\n            return new M44d(\n                0, 0, 0, s.X, \n                0, 0, s.Y, 0, \n                0, s.Z, 0, 0, \n                s.W, 0, 0, 0);\n        }\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44d\"/> using 4 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Scale(double sX, double sY, double sZ, double sW)\n            => FromDiagonal(sX, sY, sZ, sW);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44d\"/> using a <see cref=\"V4d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Scale(V4d s)\n            => FromDiagonal(s);\n\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"M44d\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Scale(double s)\n        {\n            return new M44d(\n                s, 0, 0, 0, \n                0, s, 0, 0, \n                0, 0, s, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44d\"/> using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Scale(double sX, double sY, double sZ)\n        {\n            return new M44d(\n                sX, 0, 0, 0, \n                0, sY, 0, 0, \n                0, 0, sZ, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44d\"/> using a <see cref=\"V3d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Scale(V3d s)\n        {\n            return new M44d(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation <see cref=\"M44d\"/> from a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Scale(Scale3d s)\n        {\n            return new M44d(\n                s.X, 0, 0, 0, \n                0, s.Y, 0, 0, \n                0, 0, s.Z, 0, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44d\"/> with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Translation(double tX, double tY, double tZ)\n        {\n            return new M44d(\n                1, 0, 0, tX, \n                0, 1, 0, tY, \n                0, 0, 1, tZ, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44d\"/> with the translational component given by a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Translation(V3d t)\n        {\n            return new M44d(\n                1, 0, 0, t.X, \n                0, 1, 0, t.Y, \n                0, 0, 1, t.Z, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"M44d\"/> from a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Translation(Shift3d s)\n        {\n            return new M44d(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, s.Z, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from a <see cref=\"Rot3d\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Rotation(Rot3d r)\n            => (M44d)r;\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Rotation(V3d normalizedAxis, double angleInRadians)\n        {\n            Debug.Assert(normalizedAxis.LengthSquared.ApproximateEquals(1, 1e-10));\n            return (M44d)(Rot3d.Rotation(normalizedAxis, angleInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationInDegrees(V3d normalizedAxis, double angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationEuler(double rollInRadians, double pitchInRadians, double yawInRadians)\n        {\n            return (M44d)(Rot3d.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationEulerInDegrees(double rollInDegrees, double pitchInDegrees, double yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationEuler(V3d rollPitchYawInRadians)\n            => RotationEuler(\n                rollPitchYawInRadians.X,\n                rollPitchYawInRadians.Y,\n                rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationEulerInDegrees(V3d rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotateInto(V3d from, V3d into)\n        {\n            Debug.Assert(from.LengthSquared.ApproximateEquals(1, 1e-10));\n            Debug.Assert(into.LengthSquared.ApproximateEquals(1, 1e-10));\n            return (M44d)(Rot3d.RotateInto(from, into));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationX(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M44d(\n                 1,  0,  0,  0, \n                 0,  a, -b,  0, \n                 0,  b,  a,  0, \n                 0,  0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationXInDegrees(double angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationY(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M44d(\n                 a,  0,  b,  0, \n                 0,  1,  0,  0, \n                -b,  0,  a,  0, \n                 0,  0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationYInDegrees(double angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationZ(double angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new M44d(\n                 a, -b,  0,  0, \n                 b,  a,  0,  0, \n                 0,  0,  1,  0, \n                 0,  0,  0,  1);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d RotationZInDegrees(double angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d ShearXY(double factorX, double factorY)\n        {\n            return new M44d(\n                1, 0, factorX, 0, \n                0, 1, factorY, 0, \n                0, 0, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d ShearXZ(double factorX, double factorZ)\n        {\n            return new M44d(\n                1, factorX, 0, 0, \n                0, 1, 0, 0, \n                0, factorZ, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d ShearYZ(double factorY, double factorZ)\n        {\n            return new M44d(\n                1, 0, 0, 0, \n                factorY, 1, 0, 0, \n                factorZ, 0, 1, 0, \n                0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d DivideByInt(M44d m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return M00;\n                yield return M01;\n                yield return M02;\n                yield return M03;\n                yield return M10;\n                yield return M11;\n                yield return M12;\n                yield return M13;\n                yield return M20;\n                yield return M21;\n                yield return M22;\n                yield return M23;\n                yield return M30;\n                yield return M31;\n                yield return M32;\n                yield return M33;\n            }\n        }\n\n        public readonly IEnumerable<V4d> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return R0;\n                yield return R1;\n                yield return R2;\n                yield return R3;\n            }\n        }\n\n        public readonly IEnumerable<V4d> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return C0;\n                yield return C1;\n                yield return C2;\n                yield return C3;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d R0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M00,  M01,  M02,  M03); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M01 = value.Y;\n                M02 = value.Z;\n                M03 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d R1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M10,  M11,  M12,  M13); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M10 = value.X;\n                M11 = value.Y;\n                M12 = value.Z;\n                M13 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d R2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M20,  M21,  M22,  M23); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M20 = value.X;\n                M21 = value.Y;\n                M22 = value.Z;\n                M23 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d R3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M30,  M31,  M32,  M33); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M30 = value.X;\n                M31 = value.Y;\n                M32 = value.Z;\n                M33 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d C0\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M00,  M10,  M20,  M30); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M00 = value.X;\n                M10 = value.Y;\n                M20 = value.Z;\n                M30 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d C1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M01,  M11,  M21,  M31); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M01 = value.X;\n                M11 = value.Y;\n                M21 = value.Z;\n                M31 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d C2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M02,  M12,  M22,  M32); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M02 = value.X;\n                M12 = value.Y;\n                M22 = value.Z;\n                M32 = value.W;\n            }\n        }\n\n        [XmlIgnore]\n        public V4d C3\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V4d( M03,  M13,  M23,  M33); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                M03 = value.X;\n                M13 = value.Y;\n                M23 = value.Z;\n                M33 = value.W;\n            }\n        }\n\n        public readonly V4d Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4d(M00, M11, M22, M33);\n        }\n\n        public readonly V4d AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V4d(M03, M12, M21, M30);\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly double MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly double MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33);\n        }\n\n        public unsafe double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe double this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &M00) { return ptr[row * 4 + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &M00) { ptr[row * 4 + column] = value; }\n            }\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) || Fun.IsFinite(M01) || Fun.IsFinite(M02) || Fun.IsFinite(M03) || \n                    Fun.IsFinite(M10) || Fun.IsFinite(M11) || Fun.IsFinite(M12) || Fun.IsFinite(M13) || \n                    Fun.IsFinite(M20) || Fun.IsFinite(M21) || Fun.IsFinite(M22) || Fun.IsFinite(M23) || \n                    Fun.IsFinite(M30) || Fun.IsFinite(M31) || Fun.IsFinite(M32) || Fun.IsFinite(M33);\n            }\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsFinite(M00) && Fun.IsFinite(M01) && Fun.IsFinite(M02) && Fun.IsFinite(M03) && \n                    Fun.IsFinite(M10) && Fun.IsFinite(M11) && Fun.IsFinite(M12) && Fun.IsFinite(M13) && \n                    Fun.IsFinite(M20) && Fun.IsFinite(M21) && Fun.IsFinite(M22) && Fun.IsFinite(M23) && \n                    Fun.IsFinite(M30) && Fun.IsFinite(M31) && Fun.IsFinite(M32) && Fun.IsFinite(M33);\n            }\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) || double.IsNaN(M01) || double.IsNaN(M02) || double.IsNaN(M03) || \n                    double.IsNaN(M10) || double.IsNaN(M11) || double.IsNaN(M12) || double.IsNaN(M13) || \n                    double.IsNaN(M20) || double.IsNaN(M21) || double.IsNaN(M22) || double.IsNaN(M23) || \n                    double.IsNaN(M30) || double.IsNaN(M31) || double.IsNaN(M32) || double.IsNaN(M33);\n            }\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNaN(M00) && double.IsNaN(M01) && double.IsNaN(M02) && double.IsNaN(M03) && \n                    double.IsNaN(M10) && double.IsNaN(M11) && double.IsNaN(M12) && double.IsNaN(M13) && \n                    double.IsNaN(M20) && double.IsNaN(M21) && double.IsNaN(M22) && double.IsNaN(M23) && \n                    double.IsNaN(M30) && double.IsNaN(M31) && double.IsNaN(M32) && double.IsNaN(M33);\n            }\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) || double.IsInfinity(M01) || double.IsInfinity(M02) || double.IsInfinity(M03) || \n                    double.IsInfinity(M10) || double.IsInfinity(M11) || double.IsInfinity(M12) || double.IsInfinity(M13) || \n                    double.IsInfinity(M20) || double.IsInfinity(M21) || double.IsInfinity(M22) || double.IsInfinity(M23) || \n                    double.IsInfinity(M30) || double.IsInfinity(M31) || double.IsInfinity(M32) || double.IsInfinity(M33);\n            }\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsInfinity(M00) && double.IsInfinity(M01) && double.IsInfinity(M02) && double.IsInfinity(M03) && \n                    double.IsInfinity(M10) && double.IsInfinity(M11) && double.IsInfinity(M12) && double.IsInfinity(M13) && \n                    double.IsInfinity(M20) && double.IsInfinity(M21) && double.IsInfinity(M22) && double.IsInfinity(M23) && \n                    double.IsInfinity(M30) && double.IsInfinity(M31) && double.IsInfinity(M32) && double.IsInfinity(M33);\n            }\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) || double.IsPositiveInfinity(M01) || double.IsPositiveInfinity(M02) || double.IsPositiveInfinity(M03) || \n                    double.IsPositiveInfinity(M10) || double.IsPositiveInfinity(M11) || double.IsPositiveInfinity(M12) || double.IsPositiveInfinity(M13) || \n                    double.IsPositiveInfinity(M20) || double.IsPositiveInfinity(M21) || double.IsPositiveInfinity(M22) || double.IsPositiveInfinity(M23) || \n                    double.IsPositiveInfinity(M30) || double.IsPositiveInfinity(M31) || double.IsPositiveInfinity(M32) || double.IsPositiveInfinity(M33);\n            }\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsPositiveInfinity(M00) && double.IsPositiveInfinity(M01) && double.IsPositiveInfinity(M02) && double.IsPositiveInfinity(M03) && \n                    double.IsPositiveInfinity(M10) && double.IsPositiveInfinity(M11) && double.IsPositiveInfinity(M12) && double.IsPositiveInfinity(M13) && \n                    double.IsPositiveInfinity(M20) && double.IsPositiveInfinity(M21) && double.IsPositiveInfinity(M22) && double.IsPositiveInfinity(M23) && \n                    double.IsPositiveInfinity(M30) && double.IsPositiveInfinity(M31) && double.IsPositiveInfinity(M32) && double.IsPositiveInfinity(M33);\n            }\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) || double.IsNegativeInfinity(M01) || double.IsNegativeInfinity(M02) || double.IsNegativeInfinity(M03) || \n                    double.IsNegativeInfinity(M10) || double.IsNegativeInfinity(M11) || double.IsNegativeInfinity(M12) || double.IsNegativeInfinity(M13) || \n                    double.IsNegativeInfinity(M20) || double.IsNegativeInfinity(M21) || double.IsNegativeInfinity(M22) || double.IsNegativeInfinity(M23) || \n                    double.IsNegativeInfinity(M30) || double.IsNegativeInfinity(M31) || double.IsNegativeInfinity(M32) || double.IsNegativeInfinity(M33);\n            }\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    double.IsNegativeInfinity(M00) && double.IsNegativeInfinity(M01) && double.IsNegativeInfinity(M02) && double.IsNegativeInfinity(M03) && \n                    double.IsNegativeInfinity(M10) && double.IsNegativeInfinity(M11) && double.IsNegativeInfinity(M12) && double.IsNegativeInfinity(M13) && \n                    double.IsNegativeInfinity(M20) && double.IsNegativeInfinity(M21) && double.IsNegativeInfinity(M22) && double.IsNegativeInfinity(M23) && \n                    double.IsNegativeInfinity(M30) && double.IsNegativeInfinity(M31) && double.IsNegativeInfinity(M32) && double.IsNegativeInfinity(M33);\n            }\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) || Fun.IsTiny(M01) || Fun.IsTiny(M02) || Fun.IsTiny(M03) || \n                    Fun.IsTiny(M10) || Fun.IsTiny(M11) || Fun.IsTiny(M12) || Fun.IsTiny(M13) || \n                    Fun.IsTiny(M20) || Fun.IsTiny(M21) || Fun.IsTiny(M22) || Fun.IsTiny(M23) || \n                    Fun.IsTiny(M30) || Fun.IsTiny(M31) || Fun.IsTiny(M32) || Fun.IsTiny(M33);\n            }\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return \n                    Fun.IsTiny(M00) && Fun.IsTiny(M01) && Fun.IsTiny(M02) && Fun.IsTiny(M03) && \n                    Fun.IsTiny(M10) && Fun.IsTiny(M11) && Fun.IsTiny(M12) && Fun.IsTiny(M13) && \n                    Fun.IsTiny(M20) && Fun.IsTiny(M21) && Fun.IsTiny(M22) && Fun.IsTiny(M23) && \n                    Fun.IsTiny(M30) && Fun.IsTiny(M31) && Fun.IsTiny(M32) && Fun.IsTiny(M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = 4;\n        public const int ColumnCount = 4;\n        public const int ElementCount = 4 * 4;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(4, 4);\n        }\n\n        public static M44d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M44d(0);\n        }\n\n        public static M44d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new M44d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly double Norm1\n        {\n            get\n            {\n                return \n                    Fun.Abs(M00) + Fun.Abs(M01) + Fun.Abs(M02) + Fun.Abs(M03) + \n                    Fun.Abs(M10) + Fun.Abs(M11) + Fun.Abs(M12) + Fun.Abs(M13) + \n                    Fun.Abs(M20) + Fun.Abs(M21) + Fun.Abs(M22) + Fun.Abs(M23) + \n                    Fun.Abs(M30) + Fun.Abs(M31) + Fun.Abs(M32) + Fun.Abs(M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly double Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(\n                    M00 * M00 + M01 * M01 + M02 * M02 + M03 * M03 + \n                    M10 * M10 + M11 * M11 + M12 * M12 + M13 * M13 + \n                    M20 * M20 + M21 * M21 + M22 * M22 + M23 * M23 + \n                    M30 * M30 + M31 * M31 + M32 * M32 + M33 * M33);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMax\n        {\n            get\n            {\n                return Fun.Max(\n                            Fun.Max(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Max(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Max(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)), \n                            Fun.Max(\n                                Fun.Abs(M30), \n                                Fun.Abs(M31), \n                                Fun.Abs(M32), \n                                Fun.Abs(M33)));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly double NormMin\n        {\n            get\n            {\n                return Fun.Min(\n                            Fun.Min(\n                                Fun.Abs(M00), \n                                Fun.Abs(M01), \n                                Fun.Abs(M02), \n                                Fun.Abs(M03)), \n                            Fun.Min(\n                                Fun.Abs(M10), \n                                Fun.Abs(M11), \n                                Fun.Abs(M12), \n                                Fun.Abs(M13)), \n                            Fun.Min(\n                                Fun.Abs(M20), \n                                Fun.Abs(M21), \n                                Fun.Abs(M22), \n                                Fun.Abs(M23)), \n                            Fun.Min(\n                                Fun.Abs(M30), \n                                Fun.Abs(M31), \n                                Fun.Abs(M32), \n                                Fun.Abs(M33)));\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator -(M44d m)\n        {\n            return new M44d(\n                -m.M00, -m.M01, -m.M02, -m.M03, \n                -m.M10, -m.M11, -m.M12, -m.M13, \n                -m.M20, -m.M21, -m.M22, -m.M23, \n                -m.M30, -m.M31, -m.M32, -m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (M44d a, M44d b)\n        {\n            return new M44d(\n                a.M00 + b.M00, a.M01 + b.M01, a.M02 + b.M02, a.M03 + b.M03, \n                a.M10 + b.M10, a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, \n                a.M20 + b.M20, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, \n                a.M30 + b.M30, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (M44d m, double s)\n        {\n            return new M44d(\n                m.M00 + s, m.M01 + s, m.M02 + s, m.M03 + s, \n                m.M10 + s, m.M11 + s, m.M12 + s, m.M13 + s, \n                m.M20 + s, m.M21 + s, m.M22 + s, m.M23 + s, \n                m.M30 + s, m.M31 + s, m.M32 + s, m.M33 + s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  + (double s, M44d m)\n        {\n            return new M44d(\n                s + m.M00, s + m.M01, s + m.M02, s + m.M03, \n                s + m.M10, s + m.M11, s + m.M12, s + m.M13, \n                s + m.M20, s + m.M21, s + m.M22, s + m.M23, \n                s + m.M30, s + m.M31, s + m.M32, s + m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (M44d a, M44d b)\n        {\n            return new M44d(\n                a.M00 - b.M00, a.M01 - b.M01, a.M02 - b.M02, a.M03 - b.M03, \n                a.M10 - b.M10, a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, \n                a.M20 - b.M20, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, \n                a.M30 - b.M30, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (M44d m, double s)\n        {\n            return new M44d(\n                m.M00 - s, m.M01 - s, m.M02 - s, m.M03 - s, \n                m.M10 - s, m.M11 - s, m.M12 - s, m.M13 - s, \n                m.M20 - s, m.M21 - s, m.M22 - s, m.M23 - s, \n                m.M30 - s, m.M31 - s, m.M32 - s, m.M33 - s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  - (double s, M44d m)\n        {\n            return new M44d(\n                s - m.M00, s - m.M01, s - m.M02, s - m.M03, \n                s - m.M10, s - m.M11, s - m.M12, s - m.M13, \n                s - m.M20, s - m.M21, s - m.M22, s - m.M23, \n                s - m.M30, s - m.M31, s - m.M32, s - m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (M44d a, M44d b)\n        {\n            return new M44d(\n                a.M00 % b.M00, a.M01 % b.M01, a.M02 % b.M02, a.M03 % b.M03, \n                a.M10 % b.M10, a.M11 % b.M11, a.M12 % b.M12, a.M13 % b.M13, \n                a.M20 % b.M20, a.M21 % b.M21, a.M22 % b.M22, a.M23 % b.M23, \n                a.M30 % b.M30, a.M31 % b.M31, a.M32 % b.M32, a.M33 % b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (M44d m, double s)\n        {\n            return new M44d(\n                m.M00 % s, m.M01 % s, m.M02 % s, m.M03 % s, \n                m.M10 % s, m.M11 % s, m.M12 % s, m.M13 % s, \n                m.M20 % s, m.M21 % s, m.M22 % s, m.M23 % s, \n                m.M30 % s, m.M31 % s, m.M32 % s, m.M33 % s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  % (double s, M44d m)\n        {\n            return new M44d(\n                s % m.M00, s % m.M01, s % m.M02, s % m.M03, \n                s % m.M10, s % m.M11, s % m.M12, s % m.M13, \n                s % m.M20, s % m.M21, s % m.M22, s % m.M23, \n                s % m.M30, s % m.M31, s % m.M32, s % m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (M44d a, M44d b)\n        {\n            return new M44d(\n                a.M00 / b.M00, a.M01 / b.M01, a.M02 / b.M02, a.M03 / b.M03, \n                a.M10 / b.M10, a.M11 / b.M11, a.M12 / b.M12, a.M13 / b.M13, \n                a.M20 / b.M20, a.M21 / b.M21, a.M22 / b.M22, a.M23 / b.M23, \n                a.M30 / b.M30, a.M31 / b.M31, a.M32 / b.M32, a.M33 / b.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (M44d m, double s)\n        {\n            return new M44d(\n                m.M00 / s, m.M01 / s, m.M02 / s, m.M03 / s, \n                m.M10 / s, m.M11 / s, m.M12 / s, m.M13 / s, \n                m.M20 / s, m.M21 / s, m.M22 / s, m.M23 / s, \n                m.M30 / s, m.M31 / s, m.M32 / s, m.M33 / s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  / (double s, M44d m)\n        {\n            return new M44d(\n                s / m.M00, s / m.M01, s / m.M02, s / m.M03, \n                s / m.M10, s / m.M11, s / m.M12, s / m.M13, \n                s / m.M20, s / m.M21, s / m.M22, s / m.M23, \n                s / m.M30, s / m.M31, s / m.M32, s / m.M33);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  * (M44d m, double s)\n        {\n            return new M44d(\n                m.M00 * s, m.M01 * s, m.M02 * s, m.M03 * s, \n                m.M10 * s, m.M11 * s, m.M12 * s, m.M13 * s, \n                m.M20 * s, m.M21 * s, m.M22 * s, m.M23 * s, \n                m.M30 * s, m.M31 * s, m.M32 * s, m.M33 * s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator  * (double s, M44d m)\n        {\n            return new M44d(\n                s * m.M00, s * m.M01, s * m.M02, s * m.M03, \n                s * m.M10, s * m.M11, s * m.M12, s * m.M13, \n                s * m.M20, s * m.M21, s * m.M22, s * m.M23, \n                s * m.M30, s * m.M31, s * m.M32, s * m.M33);\n        }\n\n        #endregion\n\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a M44d matrix with a V4d column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(M44d m, V4d v)\n        {\n            return new V4d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z + m.M03 * v.W, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z + m.M13 * v.W, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z + m.M23 * v.W, \n                m.M30 * v.X + m.M31 * v.Y + m.M32 * v.Z + m.M33 * v.W);\n        }\n\n        /// <summary>\n        /// Multiplies a V4d row vector with a M44d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(V4d v, M44d m)\n        {\n            return new V4d(\n                v.X * m.M00 + v.Y * m.M10 + v.Z * m.M20 + v.W * m.M30, \n                v.X * m.M01 + v.Y * m.M11 + v.Z * m.M21 + v.W * m.M31, \n                v.X * m.M02 + v.Y * m.M12 + v.Z * m.M22 + v.W * m.M32, \n                v.X * m.M03 + v.Y * m.M13 + v.Z * m.M23 + v.W * m.M33);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M44d a, M44d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23 && \n                a.M30 == b.M30 && \n                a.M31 == b.M31 && \n                a.M32 == b.M32 && \n                a.M33 == b.M33;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(M44d a, double s)\n        {\n            return\n                a.M00 == s && \n                a.M01 == s && \n                a.M02 == s && \n                a.M03 == s && \n                a.M10 == s && \n                a.M11 == s && \n                a.M12 == s && \n                a.M13 == s && \n                a.M20 == s && \n                a.M21 == s && \n                a.M22 == s && \n                a.M23 == s && \n                a.M30 == s && \n                a.M31 == s && \n                a.M32 == s && \n                a.M33 == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(double s, M44d a)\n        {\n            return\n                s == a.M00  && \n                s == a.M01  && \n                s == a.M02  && \n                s == a.M03  && \n                s == a.M10  && \n                s == a.M11  && \n                s == a.M12  && \n                s == a.M13  && \n                s == a.M20  && \n                s == a.M21  && \n                s == a.M22  && \n                s == a.M23  && \n                s == a.M30  && \n                s == a.M31  && \n                s == a.M32  && \n                s == a.M33 ;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M44d a, M44d b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(M44d m, double s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(double s, M44d m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(\n                        HashCode.GetCombined(M00, M01, M02, M03),\n                        HashCode.GetCombined(M10, M11, M12, M13),\n                        HashCode.GetCombined(M20, M21, M22, M23),\n                        HashCode.GetCombined(M30, M31, M32, M33));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(M44d other)\n        {\n            return \n                M00.Equals(other.M00) && M01.Equals(other.M01) && M02.Equals(other.M02) && M03.Equals(other.M03) && \n                M10.Equals(other.M10) && M11.Equals(other.M11) && M12.Equals(other.M12) && M13.Equals(other.M13) && \n                M20.Equals(other.M20) && M21.Equals(other.M21) && M22.Equals(other.M22) && M23.Equals(other.M23) && \n                M30.Equals(other.M30) && M31.Equals(other.M31) && M32.Equals(other.M32) && M33.Equals(other.M33);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is M44d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM\n                + R0.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R1.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R2.ToString(format, fp, beginR, betweenR, endR)  + betweenM \n                + R3.ToString(format, fp, beginR, betweenR, endR) \n            + endM;\n        }\n\n        public static M44d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return M44d.FromRows(\n                V4d.Parse(x[0]), \n                V4d.Parse(x[1]), \n                V4d.Parse(x[2]), \n                V4d.Parse(x[3])\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly M44d Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                M44d result = new M44d();\n                for (int row = 0; row < 4; row++)\n                {\n                    for (int col = 0; col < 4; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly double Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return M00 + M11 + M22 + M33 ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly double Determinant\n        {\n            get\n            {\n                // using bottom row because elements M30, M31, and M32\n                // are zero most of the time.\n                double d = 0;\n                if (M30 != 0.0f) d -= M30 * (\n                M01 * M12 * M23 + M02 * M13 * M21 + M03 * M11 * M22\n                - M21 * M12 * M03 - M22 * M13 * M01 - M23 * M11 * M02\n                );\n                if (M31 != 0.0f) d += M31 * (\n                M00 * M12 * M23 + M02 * M13 * M20 + M03 * M10 * M22\n                - M20 * M12 * M03 - M22 * M13 * M00 - M23 * M10 * M02\n                );\n                if (M32 != 0.0f) d -= M32 * (\n                M00 * M11 * M23 + M01 * M13 * M20 + M03 * M10 * M21\n                - M20 * M11 * M03 - M21 * M13 * M00 - M23 * M10 * M01\n                );\n                if (M33 != 0.0f) d += M33 * (\n                M00 * M11 * M22 + M01 * M12 * M20 + M02 * M10 * M21\n                - M20 * M11 * M02 - M21 * M12 * M00 - M22 * M10 * M01\n                );\n                return d;\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly M44d Transposed\n        {\n            get\n            {\n                return new M44d {\n                    \n                    M00 = M00, \n                    M01 = M10, \n                    M02 = M20, \n                    M03 = M30, \n                    \n                    M10 = M01, \n                    M11 = M11, \n                    M12 = M21, \n                    M13 = M31, \n                    \n                    M20 = M02, \n                    M21 = M12, \n                    M22 = M22, \n                    M23 = M32, \n                    \n                    M30 = M03, \n                    M31 = M13, \n                    M32 = M23, \n                    M33 = M33\n                };\n            }\n        }\n\n        private static V2l s_luSize = new V2l(4, 4);\n        private static V2l s_luDelta = new V2l(1, 4);\n\n        /// <summary>\n        /// Inverts the given matrix using lu factorization in place. Returns true\n        /// if the matrix was invertible, otherwise the matrix remains unchanged.\n        /// </summary>\n        public unsafe bool LuInvert()\n        {\n            fixed (M44d* self = &this)\n            {\n                var lu = this;\n                V4i perm;\n                if (NumericExtensions.LuFactorize((double*)&lu, 0, 1, 4, (int*)&perm, 4))\n                {\n                    NumericExtensions.LuInverse((double*)&lu, 0, 1, 4, (int*)&perm, (double*)self, 0, 1, 4, 4);\n                    return true;\n                }\n                return false;\n            }\n        }\n\n        /// <summary>\n        /// Returns the inverse of the matrix using lu factorization.\n        /// If the matrix is not invertible, M44d.Zero is returned.\n        /// </summary>\n        public unsafe readonly M44d LuInverse()\n        {\n            var lu = this;\n            M44d res;\n            V4i perm;\n            if (NumericExtensions.LuFactorize((double*)&lu, 0, 1, 4, (int*)&perm, 4))\n            {\n                NumericExtensions.LuInverse((double*)&lu, 0, 1, 4, (int*)&perm, (double*)&res, 0, 1, 4, 4);\n                return res;\n            }\n            return M44d.Zero;\n        }\n\n        /// <summary>\n        /// Returns the inverse of this matrix. If the matrix is not invertible\n        /// M44d.Zero is returned.\n        /// </summary>\n        public readonly M44d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => LuInverse();\n        }\n\n        #endregion\n\n        #region Matrix Multiplication\n\n        public static M44d operator *(M44d a, M44d b)\n        {\n            return new M44d(\n                a.M00 * b.M00 + a.M01 * b.M10 + a.M02 * b.M20 + a.M03 * b.M30, \n                a.M00 * b.M01 + a.M01 * b.M11 + a.M02 * b.M21 + a.M03 * b.M31, \n                a.M00 * b.M02 + a.M01 * b.M12 + a.M02 * b.M22 + a.M03 * b.M32, \n                a.M00 * b.M03 + a.M01 * b.M13 + a.M02 * b.M23 + a.M03 * b.M33, \n                a.M10 * b.M00 + a.M11 * b.M10 + a.M12 * b.M20 + a.M13 * b.M30, \n                a.M10 * b.M01 + a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31, \n                a.M10 * b.M02 + a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32, \n                a.M10 * b.M03 + a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33, \n                a.M20 * b.M00 + a.M21 * b.M10 + a.M22 * b.M20 + a.M23 * b.M30, \n                a.M20 * b.M01 + a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31, \n                a.M20 * b.M02 + a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32, \n                a.M20 * b.M03 + a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33, \n                a.M30 * b.M00 + a.M31 * b.M10 + a.M32 * b.M20 + a.M33 * b.M30, \n                a.M30 * b.M01 + a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31, \n                a.M30 * b.M02 + a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32, \n                a.M30 * b.M03 + a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33\n             );\n        }\n\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (double)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (double)value;\n        }\n\n        #endregion\n    }\n\n    public class M44dEqualityComparer : IEqualityComparer<M44d>\n    {\n        public static readonly M44dEqualityComparer Default\n            = new M44dEqualityComparer();\n\n        #region IEqualityComparer<M44d> Members\n\n        public bool Equals(M44d v0, M44d v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(M44d v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this M44d m)\n            => (m.C0.Length + m.C1.Length + m.C2.Length + m.C3.Length) / 4;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d GetScaleVector(this M44d m)\n            => new V4d(m.C0.Length, m.C1.Length, m.C2.Length, m.C3.Length);\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of 3D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale3(this M44d m)\n            => (m.C0.XYZ.Length + m.C1.XYZ.Length + m.C2.XYZ.Length) / 3;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the 3D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector3(this M44d m)\n            => new V3d(m.C0.XYZ.Length, m.C1.XYZ.Length, m.C2.XYZ.Length);\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A left-handed coordinates system transformation is expected,\n        /// where the view-space z-axis points in forward direction.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetViewDirectionLH(this M44d m)\n            => m.R2.XYZ.Normalized;\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A right-handed coordinates system transformation is expected, where\n        /// the view-space z-axis points opposit the forward vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetViewDirectionRH(this M44d m)\n            => -m.R2.XYZ.Normalized;\n\n        /// <summary>\n        /// Extracts the translation component of the given transformation matrix, which when given\n        /// a model transformation represents the model origin in world position.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetModelOrigin(this M44d m)\n            => m.C3.XYZ;\n\n        /// <summary>\n        /// Builds a hull from the given view-projection transformation matrix (left, right, bottom, top, near, far).\n        /// The view volume is assumed to be [-1, -1, -1] [1, 1, 1].\n        /// The normals of the hull planes point to the outside and are normalized.\n        /// A point inside the visual hull will has negative height to all planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Hull3d GetVisualHull(this M44d viewProj)\n        {\n            var r0 = viewProj.R0;\n            var r1 = viewProj.R1;\n            var r2 = viewProj.R2;\n            var r3 = viewProj.R3;\n\n            return new Hull3d(new[]\n            {\n                new Plane3d((-(r3 + r0))).Normalized, // left\n                new Plane3d((-(r3 - r0))).Normalized, // right\n                new Plane3d((-(r3 + r1))).Normalized, // bottom\n                new Plane3d((-(r3 - r1))).Normalized, // top\n                new Plane3d((-(r3 + r2))).Normalized, // near\n                new Plane3d((-(r3 - r2))).Normalized, // far\n            });\n        }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm1(M44d m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(M44d m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMax(M44d m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMin(M44d m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this M44d m, double p)\n        {\n            return (\n                Fun.Abs(m.M00).Pow(p) + \n                Fun.Abs(m.M01).Pow(p) + \n                Fun.Abs(m.M02).Pow(p) + \n                Fun.Abs(m.M03).Pow(p) + \n                Fun.Abs(m.M10).Pow(p) + \n                Fun.Abs(m.M11).Pow(p) + \n                Fun.Abs(m.M12).Pow(p) + \n                Fun.Abs(m.M13).Pow(p) + \n                Fun.Abs(m.M20).Pow(p) + \n                Fun.Abs(m.M21).Pow(p) + \n                Fun.Abs(m.M22).Pow(p) + \n                Fun.Abs(m.M23).Pow(p) + \n                Fun.Abs(m.M30).Pow(p) + \n                Fun.Abs(m.M31).Pow(p) + \n                Fun.Abs(m.M32).Pow(p) + \n                Fun.Abs(m.M33).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static double Distance1(this M44d a, M44d b)\n        {\n            return\n                Fun.Abs(b.M00 - a.M00) + \n                Fun.Abs(b.M01 - a.M01) + \n                Fun.Abs(b.M02 - a.M02) + \n                Fun.Abs(b.M03 - a.M03) + \n                Fun.Abs(b.M10 - a.M10) + \n                Fun.Abs(b.M11 - a.M11) + \n                Fun.Abs(b.M12 - a.M12) + \n                Fun.Abs(b.M13 - a.M13) + \n                Fun.Abs(b.M20 - a.M20) + \n                Fun.Abs(b.M21 - a.M21) + \n                Fun.Abs(b.M22 - a.M22) + \n                Fun.Abs(b.M23 - a.M23) + \n                Fun.Abs(b.M30 - a.M30) + \n                Fun.Abs(b.M31 - a.M31) + \n                Fun.Abs(b.M32 - a.M32) + \n                Fun.Abs(b.M33 - a.M33);\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static double Distance2(this M44d a, M44d b)\n        {\n            return Fun.Sqrt(\n                        Fun.Square(b.M00 - a.M00) + \n                        Fun.Square(b.M01 - a.M01) + \n                        Fun.Square(b.M02 - a.M02) + \n                        Fun.Square(b.M03 - a.M03) + \n                        Fun.Square(b.M10 - a.M10) + \n                        Fun.Square(b.M11 - a.M11) + \n                        Fun.Square(b.M12 - a.M12) + \n                        Fun.Square(b.M13 - a.M13) + \n                        Fun.Square(b.M20 - a.M20) + \n                        Fun.Square(b.M21 - a.M21) + \n                        Fun.Square(b.M22 - a.M22) + \n                        Fun.Square(b.M23 - a.M23) + \n                        Fun.Square(b.M30 - a.M30) + \n                        Fun.Square(b.M31 - a.M31) + \n                        Fun.Square(b.M32 - a.M32) + \n                        Fun.Square(b.M33 - a.M33));\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static double Distance(this M44d a, M44d b, double p)\n        {\n            return (\n                Fun.Abs(b.M00 - a.M00).Pow(p) + \n                Fun.Abs(b.M01 - a.M01).Pow(p) + \n                Fun.Abs(b.M02 - a.M02).Pow(p) + \n                Fun.Abs(b.M03 - a.M03).Pow(p) + \n                Fun.Abs(b.M10 - a.M10).Pow(p) + \n                Fun.Abs(b.M11 - a.M11).Pow(p) + \n                Fun.Abs(b.M12 - a.M12).Pow(p) + \n                Fun.Abs(b.M13 - a.M13).Pow(p) + \n                Fun.Abs(b.M20 - a.M20).Pow(p) + \n                Fun.Abs(b.M21 - a.M21).Pow(p) + \n                Fun.Abs(b.M22 - a.M22).Pow(p) + \n                Fun.Abs(b.M23 - a.M23).Pow(p) + \n                Fun.Abs(b.M30 - a.M30).Pow(p) + \n                Fun.Abs(b.M31 - a.M31).Pow(p) + \n                Fun.Abs(b.M32 - a.M32).Pow(p) + \n                Fun.Abs(b.M33 - a.M33).Pow(p)\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMax(this M44d a, M44d b)\n        {\n            return Fun.Max(\n                        Fun.Max(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Max(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Max(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)), \n                        Fun.Max(\n                            Fun.Abs(b.M30 - a.M30), \n                            Fun.Abs(b.M31 - a.M31), \n                            Fun.Abs(b.M32 - a.M32), \n                            Fun.Abs(b.M33 - a.M33)));\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static double DistanceMin(this M44d a, M44d b)\n        {\n            return Fun.Min(\n                        Fun.Min(\n                            Fun.Abs(b.M00 - a.M00), \n                            Fun.Abs(b.M01 - a.M01), \n                            Fun.Abs(b.M02 - a.M02), \n                            Fun.Abs(b.M03 - a.M03)), \n                        Fun.Min(\n                            Fun.Abs(b.M10 - a.M10), \n                            Fun.Abs(b.M11 - a.M11), \n                            Fun.Abs(b.M12 - a.M12), \n                            Fun.Abs(b.M13 - a.M13)), \n                        Fun.Min(\n                            Fun.Abs(b.M20 - a.M20), \n                            Fun.Abs(b.M21 - a.M21), \n                            Fun.Abs(b.M22 - a.M22), \n                            Fun.Abs(b.M23 - a.M23)), \n                        Fun.Min(\n                            Fun.Abs(b.M30 - a.M30), \n                            Fun.Abs(b.M31 - a.M31), \n                            Fun.Abs(b.M32 - a.M32), \n                            Fun.Abs(b.M33 - a.M33)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this M44d m, V4d v)\n            => m * v;\n\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d TransposedTransform(this M44d m, V4d v)\n            => v * m;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by matrix m.\n        /// </summary>\n        public static V3d TransformDir(this M44d m, V3d v)\n        {\n            return new V3d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z, \n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z, \n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V3d TransformPos(this M44d m, V3d p)\n        {\n            return new V3d(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V3d TransformPosProj(this M44d m, V3d p)\n        {\n            double s = m.M30 * p.X + m.M31 * p.Y + m.M32 * p.Z + m.M33;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V4d TransformPosProjFull(this M44d m, V3d p)\n        {\n            return new V4d(\n                m.M00 * p.X + m.M01 * p.Y + m.M02 * p.Z + m.M03, \n                m.M10 * p.X + m.M11 * p.Y + m.M12 * p.Z + m.M13, \n                m.M20 * p.X + m.M21 * p.Y + m.M22 * p.Z + m.M23, \n                m.M30 * p.X + m.M31 * p.Y + m.M32 * p.Z + m.M33\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static V3d TransposedTransformDir(this M44d m, V3d v)\n        {\n            return new V3d(\n                m.M00 * v.X + m.M10 * v.Y + m.M20 * v.Z, \n                m.M01 * v.X + m.M11 * v.Y + m.M21 * v.Z, \n                m.M02 * v.X + m.M12 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static V3d TransposedTransformPos(this M44d m, V3d p)\n        {\n            return new V3d(\n                m.M00 * p.X + m.M10 * p.Y + m.M20 * p.Z + m.M30, \n                m.M01 * p.X + m.M11 * p.Y + m.M21 * p.Z + m.M31, \n                m.M02 * p.X + m.M12 * p.Y + m.M22 * p.Z + m.M32\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static V3d TransposedTransformPosProj(this M44d m, V3d p)\n        {\n            var s = m.M03 * p.X + m.M13 * p.Y + m.M23 * p.Z + m.M33;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static V3d TransposedTransformProj(this M44d m, V3d p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.W is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static V4d TransposedTransformPosProjFull(this M44d m, V3d p)\n        {\n            return new V4d(\n                m.M00 * p.X + m.M10 * p.Y + m.M20 * p.Z + m.M30, \n                m.M01 * p.X + m.M11 * p.Y + m.M21 * p.Z + m.M31, \n                m.M02 * p.X + m.M12 * p.Y + m.M22 * p.Z + m.M32, \n                m.M03 * p.X + m.M13 * p.Y + m.M23 * p.Z + m.M33\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static V4d TransposedTransformProjFull(this M44d m, V3d p)\n            => m.TransposedTransformPosProjFull(p);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the given <see cref=\"M44d\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static M33d Minor(this M44d m, int row, int column)\n        {\n            M33d rs = new M33d();\n\n            for (int k = 0; k < 9; k++)\n            {\n                var i = k / 3;\n                var j = k % 3;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * 4 + jj];\n            }\n\n            return rs;\n        }\n\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4d Row(this M44d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V4d(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static V4d Column(this M44d m, int index)\n        {\n            double* ptr = &m.M00;\n            return new V4d(ptr[index], ptr[index + 4], ptr[index + 8], ptr[index + 12]);\n        }\n\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Determinant(M44d m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Transposed(M44d m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref M44d m)\n        {\n            Fun.Swap(ref m.M10, ref m.M01);\n            Fun.Swap(ref m.M20, ref m.M02);\n            Fun.Swap(ref m.M21, ref m.M12);\n            Fun.Swap(ref m.M30, ref m.M03);\n            Fun.Swap(ref m.M31, ref m.M13);\n            Fun.Swap(ref m.M32, ref m.M23);\n        }\n\n        /// <summary>\n        /// Returns the inverse of the given matrix. If the matrix is not invertible\n        /// M44d.Zero is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Inverse(M44d m)\n            => m.Inverse;\n\n        /// <summary>\n        /// Inverts the given matrix in place. Returns true if the matrix was invertible,\n        /// otherwise the matrix remains unchanged.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Invert(this ref M44d m) { return m.LuInvert(); }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M44d m, double epsilon)\n        {\n            return Fun.ApproximateEquals(m, M44d.Identity, epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this M44d m)\n            => IsIdentity(m, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M44d m, double epsilon)\n        {\n            var i = m * m.Transposed;\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this M44d m)\n            => IsOrthonormal(m, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M44d m, double epsilon)\n        {\n            var i = m * m.Transposed;\n            for (int j = 0; j < 4; j++)\n                i[j, j] = 1; //inefficient implementation: just leave out the comparisons at the diagonal entries.\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this M44d m)\n            => IsOrthogonal(m, Constant<double>.PositiveTinyValue);\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M44d a, M44d b)\n        {\n            return\n                a.M00 < b.M00 && \n                a.M01 < b.M01 && \n                a.M02 < b.M02 && \n                a.M03 < b.M03 && \n                a.M10 < b.M10 && \n                a.M11 < b.M11 && \n                a.M12 < b.M12 && \n                a.M13 < b.M13 && \n                a.M20 < b.M20 && \n                a.M21 < b.M21 && \n                a.M22 < b.M22 && \n                a.M23 < b.M23 && \n                a.M30 < b.M30 && \n                a.M31 < b.M31 && \n                a.M32 < b.M32 && \n                a.M33 < b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this M44d m, double s)\n        {\n            return\n                m.M00 < s && \n                m.M01 < s && \n                m.M02 < s && \n                m.M03 < s && \n                m.M10 < s && \n                m.M11 < s && \n                m.M12 < s && \n                m.M13 < s && \n                m.M20 < s && \n                m.M21 < s && \n                m.M22 < s && \n                m.M23 < s && \n                m.M30 < s && \n                m.M31 < s && \n                m.M32 < s && \n                m.M33 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, M44d m)\n        {\n            return\n                s < m.M00 && \n                s < m.M01 && \n                s < m.M02 && \n                s < m.M03 && \n                s < m.M10 && \n                s < m.M11 && \n                s < m.M12 && \n                s < m.M13 && \n                s < m.M20 && \n                s < m.M21 && \n                s < m.M22 && \n                s < m.M23 && \n                s < m.M30 && \n                s < m.M31 && \n                s < m.M32 && \n                s < m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M44d a, M44d b)\n        {\n            return\n                a.M00 < b.M00 || \n                a.M01 < b.M01 || \n                a.M02 < b.M02 || \n                a.M03 < b.M03 || \n                a.M10 < b.M10 || \n                a.M11 < b.M11 || \n                a.M12 < b.M12 || \n                a.M13 < b.M13 || \n                a.M20 < b.M20 || \n                a.M21 < b.M21 || \n                a.M22 < b.M22 || \n                a.M23 < b.M23 || \n                a.M30 < b.M30 || \n                a.M31 < b.M31 || \n                a.M32 < b.M32 || \n                a.M33 < b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this M44d m, double s)\n        {\n            return\n                m.M00 < s || \n                m.M01 < s || \n                m.M02 < s || \n                m.M03 < s || \n                m.M10 < s || \n                m.M11 < s || \n                m.M12 < s || \n                m.M13 < s || \n                m.M20 < s || \n                m.M21 < s || \n                m.M22 < s || \n                m.M23 < s || \n                m.M30 < s || \n                m.M31 < s || \n                m.M32 < s || \n                m.M33 < s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, M44d m)\n        {\n            return\n                s < m.M00 || \n                s < m.M01 || \n                s < m.M02 || \n                s < m.M03 || \n                s < m.M10 || \n                s < m.M11 || \n                s < m.M12 || \n                s < m.M13 || \n                s < m.M20 || \n                s < m.M21 || \n                s < m.M22 || \n                s < m.M23 || \n                s < m.M30 || \n                s < m.M31 || \n                s < m.M32 || \n                s < m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M44d a, M44d b)\n        {\n            return\n                a.M00 > b.M00 && \n                a.M01 > b.M01 && \n                a.M02 > b.M02 && \n                a.M03 > b.M03 && \n                a.M10 > b.M10 && \n                a.M11 > b.M11 && \n                a.M12 > b.M12 && \n                a.M13 > b.M13 && \n                a.M20 > b.M20 && \n                a.M21 > b.M21 && \n                a.M22 > b.M22 && \n                a.M23 > b.M23 && \n                a.M30 > b.M30 && \n                a.M31 > b.M31 && \n                a.M32 > b.M32 && \n                a.M33 > b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this M44d m, double s)\n        {\n            return\n                m.M00 > s && \n                m.M01 > s && \n                m.M02 > s && \n                m.M03 > s && \n                m.M10 > s && \n                m.M11 > s && \n                m.M12 > s && \n                m.M13 > s && \n                m.M20 > s && \n                m.M21 > s && \n                m.M22 > s && \n                m.M23 > s && \n                m.M30 > s && \n                m.M31 > s && \n                m.M32 > s && \n                m.M33 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, M44d m)\n        {\n            return\n                s > m.M00 && \n                s > m.M01 && \n                s > m.M02 && \n                s > m.M03 && \n                s > m.M10 && \n                s > m.M11 && \n                s > m.M12 && \n                s > m.M13 && \n                s > m.M20 && \n                s > m.M21 && \n                s > m.M22 && \n                s > m.M23 && \n                s > m.M30 && \n                s > m.M31 && \n                s > m.M32 && \n                s > m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M44d a, M44d b)\n        {\n            return\n                a.M00 > b.M00 || \n                a.M01 > b.M01 || \n                a.M02 > b.M02 || \n                a.M03 > b.M03 || \n                a.M10 > b.M10 || \n                a.M11 > b.M11 || \n                a.M12 > b.M12 || \n                a.M13 > b.M13 || \n                a.M20 > b.M20 || \n                a.M21 > b.M21 || \n                a.M22 > b.M22 || \n                a.M23 > b.M23 || \n                a.M30 > b.M30 || \n                a.M31 > b.M31 || \n                a.M32 > b.M32 || \n                a.M33 > b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this M44d m, double s)\n        {\n            return\n                m.M00 > s || \n                m.M01 > s || \n                m.M02 > s || \n                m.M03 > s || \n                m.M10 > s || \n                m.M11 > s || \n                m.M12 > s || \n                m.M13 > s || \n                m.M20 > s || \n                m.M21 > s || \n                m.M22 > s || \n                m.M23 > s || \n                m.M30 > s || \n                m.M31 > s || \n                m.M32 > s || \n                m.M33 > s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, M44d m)\n        {\n            return\n                s > m.M00 || \n                s > m.M01 || \n                s > m.M02 || \n                s > m.M03 || \n                s > m.M10 || \n                s > m.M11 || \n                s > m.M12 || \n                s > m.M13 || \n                s > m.M20 || \n                s > m.M21 || \n                s > m.M22 || \n                s > m.M23 || \n                s > m.M30 || \n                s > m.M31 || \n                s > m.M32 || \n                s > m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M44d a, M44d b)\n        {\n            return\n                a.M00 <= b.M00 && \n                a.M01 <= b.M01 && \n                a.M02 <= b.M02 && \n                a.M03 <= b.M03 && \n                a.M10 <= b.M10 && \n                a.M11 <= b.M11 && \n                a.M12 <= b.M12 && \n                a.M13 <= b.M13 && \n                a.M20 <= b.M20 && \n                a.M21 <= b.M21 && \n                a.M22 <= b.M22 && \n                a.M23 <= b.M23 && \n                a.M30 <= b.M30 && \n                a.M31 <= b.M31 && \n                a.M32 <= b.M32 && \n                a.M33 <= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this M44d m, double s)\n        {\n            return\n                m.M00 <= s && \n                m.M01 <= s && \n                m.M02 <= s && \n                m.M03 <= s && \n                m.M10 <= s && \n                m.M11 <= s && \n                m.M12 <= s && \n                m.M13 <= s && \n                m.M20 <= s && \n                m.M21 <= s && \n                m.M22 <= s && \n                m.M23 <= s && \n                m.M30 <= s && \n                m.M31 <= s && \n                m.M32 <= s && \n                m.M33 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, M44d m)\n        {\n            return\n                s <= m.M00 && \n                s <= m.M01 && \n                s <= m.M02 && \n                s <= m.M03 && \n                s <= m.M10 && \n                s <= m.M11 && \n                s <= m.M12 && \n                s <= m.M13 && \n                s <= m.M20 && \n                s <= m.M21 && \n                s <= m.M22 && \n                s <= m.M23 && \n                s <= m.M30 && \n                s <= m.M31 && \n                s <= m.M32 && \n                s <= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M44d a, M44d b)\n        {\n            return\n                a.M00 <= b.M00 || \n                a.M01 <= b.M01 || \n                a.M02 <= b.M02 || \n                a.M03 <= b.M03 || \n                a.M10 <= b.M10 || \n                a.M11 <= b.M11 || \n                a.M12 <= b.M12 || \n                a.M13 <= b.M13 || \n                a.M20 <= b.M20 || \n                a.M21 <= b.M21 || \n                a.M22 <= b.M22 || \n                a.M23 <= b.M23 || \n                a.M30 <= b.M30 || \n                a.M31 <= b.M31 || \n                a.M32 <= b.M32 || \n                a.M33 <= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this M44d m, double s)\n        {\n            return\n                m.M00 <= s || \n                m.M01 <= s || \n                m.M02 <= s || \n                m.M03 <= s || \n                m.M10 <= s || \n                m.M11 <= s || \n                m.M12 <= s || \n                m.M13 <= s || \n                m.M20 <= s || \n                m.M21 <= s || \n                m.M22 <= s || \n                m.M23 <= s || \n                m.M30 <= s || \n                m.M31 <= s || \n                m.M32 <= s || \n                m.M33 <= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, M44d m)\n        {\n            return\n                s <= m.M00 || \n                s <= m.M01 || \n                s <= m.M02 || \n                s <= m.M03 || \n                s <= m.M10 || \n                s <= m.M11 || \n                s <= m.M12 || \n                s <= m.M13 || \n                s <= m.M20 || \n                s <= m.M21 || \n                s <= m.M22 || \n                s <= m.M23 || \n                s <= m.M30 || \n                s <= m.M31 || \n                s <= m.M32 || \n                s <= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M44d a, M44d b)\n        {\n            return\n                a.M00 >= b.M00 && \n                a.M01 >= b.M01 && \n                a.M02 >= b.M02 && \n                a.M03 >= b.M03 && \n                a.M10 >= b.M10 && \n                a.M11 >= b.M11 && \n                a.M12 >= b.M12 && \n                a.M13 >= b.M13 && \n                a.M20 >= b.M20 && \n                a.M21 >= b.M21 && \n                a.M22 >= b.M22 && \n                a.M23 >= b.M23 && \n                a.M30 >= b.M30 && \n                a.M31 >= b.M31 && \n                a.M32 >= b.M32 && \n                a.M33 >= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this M44d m, double s)\n        {\n            return\n                m.M00 >= s && \n                m.M01 >= s && \n                m.M02 >= s && \n                m.M03 >= s && \n                m.M10 >= s && \n                m.M11 >= s && \n                m.M12 >= s && \n                m.M13 >= s && \n                m.M20 >= s && \n                m.M21 >= s && \n                m.M22 >= s && \n                m.M23 >= s && \n                m.M30 >= s && \n                m.M31 >= s && \n                m.M32 >= s && \n                m.M33 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, M44d m)\n        {\n            return\n                s >= m.M00 && \n                s >= m.M01 && \n                s >= m.M02 && \n                s >= m.M03 && \n                s >= m.M10 && \n                s >= m.M11 && \n                s >= m.M12 && \n                s >= m.M13 && \n                s >= m.M20 && \n                s >= m.M21 && \n                s >= m.M22 && \n                s >= m.M23 && \n                s >= m.M30 && \n                s >= m.M31 && \n                s >= m.M32 && \n                s >= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M44d a, M44d b)\n        {\n            return\n                a.M00 >= b.M00 || \n                a.M01 >= b.M01 || \n                a.M02 >= b.M02 || \n                a.M03 >= b.M03 || \n                a.M10 >= b.M10 || \n                a.M11 >= b.M11 || \n                a.M12 >= b.M12 || \n                a.M13 >= b.M13 || \n                a.M20 >= b.M20 || \n                a.M21 >= b.M21 || \n                a.M22 >= b.M22 || \n                a.M23 >= b.M23 || \n                a.M30 >= b.M30 || \n                a.M31 >= b.M31 || \n                a.M32 >= b.M32 || \n                a.M33 >= b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this M44d m, double s)\n        {\n            return\n                m.M00 >= s || \n                m.M01 >= s || \n                m.M02 >= s || \n                m.M03 >= s || \n                m.M10 >= s || \n                m.M11 >= s || \n                m.M12 >= s || \n                m.M13 >= s || \n                m.M20 >= s || \n                m.M21 >= s || \n                m.M22 >= s || \n                m.M23 >= s || \n                m.M30 >= s || \n                m.M31 >= s || \n                m.M32 >= s || \n                m.M33 >= s;\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, M44d m)\n        {\n            return\n                s >= m.M00 || \n                s >= m.M01 || \n                s >= m.M02 || \n                s >= m.M03 || \n                s >= m.M10 || \n                s >= m.M11 || \n                s >= m.M12 || \n                s >= m.M13 || \n                s >= m.M20 || \n                s >= m.M21 || \n                s >= m.M22 || \n                s >= m.M23 || \n                s >= m.M30 || \n                s >= m.M31 || \n                s >= m.M32 || \n                s >= m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M44d a, M44d b)\n        {\n            return\n                a.M00 == b.M00 && \n                a.M01 == b.M01 && \n                a.M02 == b.M02 && \n                a.M03 == b.M03 && \n                a.M10 == b.M10 && \n                a.M11 == b.M11 && \n                a.M12 == b.M12 && \n                a.M13 == b.M13 && \n                a.M20 == b.M20 && \n                a.M21 == b.M21 && \n                a.M22 == b.M22 && \n                a.M23 == b.M23 && \n                a.M30 == b.M30 && \n                a.M31 == b.M31 && \n                a.M32 == b.M32 && \n                a.M33 == b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this M44d m, double s)\n        {\n            return\n                m.M00 == s && \n                m.M01 == s && \n                m.M02 == s && \n                m.M03 == s && \n                m.M10 == s && \n                m.M11 == s && \n                m.M12 == s && \n                m.M13 == s && \n                m.M20 == s && \n                m.M21 == s && \n                m.M22 == s && \n                m.M23 == s && \n                m.M30 == s && \n                m.M31 == s && \n                m.M32 == s && \n                m.M33 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, M44d m)\n        {\n            return\n                s == m.M00 && \n                s == m.M01 && \n                s == m.M02 && \n                s == m.M03 && \n                s == m.M10 && \n                s == m.M11 && \n                s == m.M12 && \n                s == m.M13 && \n                s == m.M20 && \n                s == m.M21 && \n                s == m.M22 && \n                s == m.M23 && \n                s == m.M30 && \n                s == m.M31 && \n                s == m.M32 && \n                s == m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M44d a, M44d b)\n        {\n            return\n                a.M00 == b.M00 || \n                a.M01 == b.M01 || \n                a.M02 == b.M02 || \n                a.M03 == b.M03 || \n                a.M10 == b.M10 || \n                a.M11 == b.M11 || \n                a.M12 == b.M12 || \n                a.M13 == b.M13 || \n                a.M20 == b.M20 || \n                a.M21 == b.M21 || \n                a.M22 == b.M22 || \n                a.M23 == b.M23 || \n                a.M30 == b.M30 || \n                a.M31 == b.M31 || \n                a.M32 == b.M32 || \n                a.M33 == b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this M44d m, double s)\n        {\n            return\n                m.M00 == s || \n                m.M01 == s || \n                m.M02 == s || \n                m.M03 == s || \n                m.M10 == s || \n                m.M11 == s || \n                m.M12 == s || \n                m.M13 == s || \n                m.M20 == s || \n                m.M21 == s || \n                m.M22 == s || \n                m.M23 == s || \n                m.M30 == s || \n                m.M31 == s || \n                m.M32 == s || \n                m.M33 == s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, M44d m)\n        {\n            return\n                s == m.M00 || \n                s == m.M01 || \n                s == m.M02 || \n                s == m.M03 || \n                s == m.M10 || \n                s == m.M11 || \n                s == m.M12 || \n                s == m.M13 || \n                s == m.M20 || \n                s == m.M21 || \n                s == m.M22 || \n                s == m.M23 || \n                s == m.M30 || \n                s == m.M31 || \n                s == m.M32 || \n                s == m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M44d a, M44d b)\n        {\n            return\n                a.M00 != b.M00 && \n                a.M01 != b.M01 && \n                a.M02 != b.M02 && \n                a.M03 != b.M03 && \n                a.M10 != b.M10 && \n                a.M11 != b.M11 && \n                a.M12 != b.M12 && \n                a.M13 != b.M13 && \n                a.M20 != b.M20 && \n                a.M21 != b.M21 && \n                a.M22 != b.M22 && \n                a.M23 != b.M23 && \n                a.M30 != b.M30 && \n                a.M31 != b.M31 && \n                a.M32 != b.M32 && \n                a.M33 != b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this M44d m, double s)\n        {\n            return\n                m.M00 != s && \n                m.M01 != s && \n                m.M02 != s && \n                m.M03 != s && \n                m.M10 != s && \n                m.M11 != s && \n                m.M12 != s && \n                m.M13 != s && \n                m.M20 != s && \n                m.M21 != s && \n                m.M22 != s && \n                m.M23 != s && \n                m.M30 != s && \n                m.M31 != s && \n                m.M32 != s && \n                m.M33 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, M44d m)\n        {\n            return\n                s != m.M00 && \n                s != m.M01 && \n                s != m.M02 && \n                s != m.M03 && \n                s != m.M10 && \n                s != m.M11 && \n                s != m.M12 && \n                s != m.M13 && \n                s != m.M20 && \n                s != m.M21 && \n                s != m.M22 && \n                s != m.M23 && \n                s != m.M30 && \n                s != m.M31 && \n                s != m.M32 && \n                s != m.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M44d a, M44d b)\n        {\n            return\n                a.M00 != b.M00 || \n                a.M01 != b.M01 || \n                a.M02 != b.M02 || \n                a.M03 != b.M03 || \n                a.M10 != b.M10 || \n                a.M11 != b.M11 || \n                a.M12 != b.M12 || \n                a.M13 != b.M13 || \n                a.M20 != b.M20 || \n                a.M21 != b.M21 || \n                a.M22 != b.M22 || \n                a.M23 != b.M23 || \n                a.M30 != b.M30 || \n                a.M31 != b.M31 || \n                a.M32 != b.M32 || \n                a.M33 != b.M33;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this M44d m, double s)\n        {\n            return\n                m.M00 != s || \n                m.M01 != s || \n                m.M02 != s || \n                m.M03 != s || \n                m.M10 != s || \n                m.M11 != s || \n                m.M12 != s || \n                m.M13 != s || \n                m.M20 != s || \n                m.M21 != s || \n                m.M22 != s || \n                m.M23 != s || \n                m.M30 != s || \n                m.M31 != s || \n                m.M32 != s || \n                m.M33 != s;\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of m.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, M44d m)\n        {\n            return\n                s != m.M00 || \n                s != m.M01 || \n                s != m.M02 || \n                s != m.M03 || \n                s != m.M10 || \n                s != m.M11 || \n                s != m.M12 || \n                s != m.M13 || \n                s != m.M20 || \n                s != m.M21 || \n                s != m.M22 || \n                s != m.M23 || \n                s != m.M30 || \n                s != m.M31 || \n                s != m.M32 || \n                s != m.M33;\n        }\n\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this M44d m0, M44d m1)\n        {\n            \n            if (m0.M00 < m1.M00) return -1;\n            if (m0.M00 > m1.M00) return +1;\n            if (m0.M01 < m1.M01) return -1;\n            if (m0.M01 > m1.M01) return +1;\n            if (m0.M02 < m1.M02) return -1;\n            if (m0.M02 > m1.M02) return +1;\n            if (m0.M03 < m1.M03) return -1;\n            if (m0.M03 > m1.M03) return +1;\n            if (m0.M10 < m1.M10) return -1;\n            if (m0.M10 > m1.M10) return +1;\n            if (m0.M11 < m1.M11) return -1;\n            if (m0.M11 > m1.M11) return +1;\n            if (m0.M12 < m1.M12) return -1;\n            if (m0.M12 > m1.M12) return +1;\n            if (m0.M13 < m1.M13) return -1;\n            if (m0.M13 > m1.M13) return +1;\n            if (m0.M20 < m1.M20) return -1;\n            if (m0.M20 > m1.M20) return +1;\n            if (m0.M21 < m1.M21) return -1;\n            if (m0.M21 > m1.M21) return +1;\n            if (m0.M22 < m1.M22) return -1;\n            if (m0.M22 > m1.M22) return +1;\n            if (m0.M23 < m1.M23) return -1;\n            if (m0.M23 > m1.M23) return +1;\n            if (m0.M30 < m1.M30) return -1;\n            if (m0.M30 > m1.M30) return +1;\n            if (m0.M31 < m1.M31) return -1;\n            if (m0.M31 > m1.M31) return +1;\n            if (m0.M32 < m1.M32) return -1;\n            if (m0.M32 > m1.M32) return +1;\n            if (m0.M33 < m1.M33) return -1;\n            if (m0.M33 > m1.M33) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"M44d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MinElement(M44d m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"M44d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MaxElement(M44d m)\n            => m.MaxElement;\n\n        #endregion\n\n        #region Orthogonalization\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M44d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthogonalize(this ref M44d matrix)\n        {\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C0, matrix.C3) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C3 -= (Vec.Dot(matrix.C1, matrix.C3) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C2, matrix.C3) / Vec.Dot(matrix.C2, matrix.C2)) * matrix.C2;\n            matrix.C3 -= (Vec.Dot(matrix.C0, matrix.C3) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C3 -= (Vec.Dot(matrix.C1, matrix.C3) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C2, matrix.C3) / Vec.Dot(matrix.C2, matrix.C2)) * matrix.C2;\n        }\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"M44d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Orthogonalized(this M44d matrix)\n        {\n            M44d m = matrix;\n            Orthogonalize(ref m);\n            return m;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M44d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthonormalize(this ref M44d matrix)\n        {\n            matrix.C0 = matrix.C0.Normalized;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 -= (Vec.Dot(matrix.C0, matrix.C1) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C1 = matrix.C1.Normalized;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 -= (Vec.Dot(matrix.C0, matrix.C2) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C2 -= (Vec.Dot(matrix.C1, matrix.C2) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C2 = matrix.C2.Normalized;\n            matrix.C3 -= (Vec.Dot(matrix.C0, matrix.C3) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C3 -= (Vec.Dot(matrix.C1, matrix.C3) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C2, matrix.C3) / Vec.Dot(matrix.C2, matrix.C2)) * matrix.C2;\n            matrix.C3 -= (Vec.Dot(matrix.C0, matrix.C3) / Vec.Dot(matrix.C0, matrix.C0)) * matrix.C0;\n            matrix.C3 -= (Vec.Dot(matrix.C1, matrix.C3) / Vec.Dot(matrix.C1, matrix.C1)) * matrix.C1;\n            matrix.C3 -= (Vec.Dot(matrix.C2, matrix.C3) / Vec.Dot(matrix.C2, matrix.C2)) * matrix.C2;\n            matrix.C3 = matrix.C3.Normalized;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"M44d\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Orthonormalized(this M44d matrix)\n        {\n            M44d m = matrix;\n            Orthonormalize(ref m);\n            return m;\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"M44d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this M44d m, double epsilon)\n            => m.M00.IsTiny(epsilon) || m.M01.IsTiny(epsilon) || m.M02.IsTiny(epsilon) || m.M03.IsTiny(epsilon) || m.M10.IsTiny(epsilon) || m.M11.IsTiny(epsilon) || m.M12.IsTiny(epsilon) || m.M13.IsTiny(epsilon) || m.M20.IsTiny(epsilon) || m.M21.IsTiny(epsilon) || m.M22.IsTiny(epsilon) || m.M23.IsTiny(epsilon) || m.M30.IsTiny(epsilon) || m.M31.IsTiny(epsilon) || m.M32.IsTiny(epsilon) || m.M33.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this M44d m, double epsilon)\n            => m.M00.IsTiny(epsilon) && m.M01.IsTiny(epsilon) && m.M02.IsTiny(epsilon) && m.M03.IsTiny(epsilon) && m.M10.IsTiny(epsilon) && m.M11.IsTiny(epsilon) && m.M12.IsTiny(epsilon) && m.M13.IsTiny(epsilon) && m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon) && m.M22.IsTiny(epsilon) && m.M23.IsTiny(epsilon) && m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon) && m.M33.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(M44d m)\n            => m.AnyFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(M44d m)\n            => m.AllFinite;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(M44d m)\n            => m.AnyNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(M44d m)\n            => m.AllNaN;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(M44d m)\n            => m.AnyInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(M44d m)\n            => m.AllInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(M44d m)\n            => m.AnyPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(M44d m)\n            => m.AllPositiveInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(M44d m)\n            => m.AnyNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(M44d m)\n            => m.AllNegativeInfinity;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(M44d m)\n            => m.AnyTiny;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(M44d m)\n            => m.AllTiny;\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M44d a, M44d b)\n            => ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this M44d a, M44d b, double epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this M44d m, double epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"M44d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(M44d m)\n            => m.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M44d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(M44d v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M44d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(M44d v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M44d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(M44d v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"M44d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(M44d v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"M44d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(M44d v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static class IRandomUniformM44dExtensions\n    {\n        #region IRandomUniform extensions for M44d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of an M44d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d UniformM44d(this IRandomUniform rnd)\n        {\n            return new M44d(\n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), \n                rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of an M44d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d UniformM44dClosed(this IRandomUniform rnd)\n        {\n            return new M44d(\n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), \n                rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of an M44d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d UniformM44dOpen(this IRandomUniform rnd)\n        {\n            return new M44d(\n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), \n                rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of an M44d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d UniformM44dFull(this IRandomUniform rnd)\n        {\n            return new M44d(\n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), \n                rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of an M44d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d UniformM44dFullClosed(this IRandomUniform rnd)\n        {\n            return new M44d(\n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), \n                rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of an M44d matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d UniformM44dFullOpen(this IRandomUniform rnd)\n        {\n            return new M44d(\n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), \n                rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Matrix_template.cs",
    "content": "﻿using System;\nusing System.ComponentModel;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Xml.Serialization;\nusing System.Diagnostics;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action add = () => Out(\" + \");\n    //# Action xor = () => Out(\" ^ \");\n    //# Action andLit = () => Out(\" and \");\n    //# Action andand = () => Out(\" && \");\n    //# Action oror = () => Out(\" || \");\n    //# Action addqcomma = () => Out(\" + \\\",\\\" \");\n    //# Action addbetweenM = () => Out(\" + betweenM \");\n    //# Action el = () => Out(\"else \");\n    //# Action bracketComma = () => Out(\"),\");\n    //# var tcharA = new[] { \"i\", \"l\", \"f\", \"d\" };\n    //# var ftypeA = new[] { \"int\", \"long\", \"float\", \"double\" };\n    //# var fcapsA = new[] { \"Int\", \"Long\", \"Float\", \"Double\" };\n    //# var ctypeA = new[] { \"double\", \"double\", \"float\", \"double\" }; // computation types\n    //# var fields = new[] {\"X\", \"Y\", \"Z\", \"W\"};\n    //# var ops = new[] {\" + \", \" - \", \" % \", \" / \", \" * \"};\n    //# var bwops = new[] { \"&\", \"|\", \"^\" };\n    //# for (int n = 2; n <= 4; n++) {\n    //# for (int m = n; m <= (n+1) && m < 5; m++) {\n    //# for (int t = 0; t < tcharA.Length; t++) {\n    //#     var msub1 = m - 1;\n    //#     var msub2 = m - 2;\n    //#     var nsub1 = n - 1;\n    //#     var tchar = tcharA[t];\n    //#     var nm = n * m;\n    //#     var nmtype = \"M\" + n + m + tchar;        // Matrix type\n    //#     var nntype = \"M\" + n + n + tchar;\n    //#     var mmtype = \"M\" + m + m + tchar;\n    //#     var vmtype = \"V\"+ m + tchar;\n    //#     var vmsub1type = \"V\"+ msub1 + tchar;\n    //#     var vntype = \"V\"+ n + tchar;\n    //#     var vnitype = \"V\"+ n + \"i\";\n    //#     var vnsub1type = \"V\"+ nsub1 + tchar;\n    //#     var scalent = \"Scale\" + n + tchar;\n    //#     var scalemt = \"Scale\" + m + tchar;\n    //#     var scalensub1t = \"Scale\" + (n - 1) + tchar;\n    //#     var scalemsub1t = \"Scale\" + (m - 1) + tchar;\n    //#     var shiftmsub1t = \"Shift\" + (m - 1) + tchar;\n    //#     var rotnt = \"Rot\" + n + tchar;\n    //#     var rotnsub1t = \"Rot\" + (n - 1) + tchar;\n    //#     var nfields = fields.Take(n).ToArray();\n    //#     var mfields = fields.Take(m).ToArray();\n    //#     var isReal = t > 1;\n    //#     var ftype = ftypeA[t];\n    //#     var fcaps = fcapsA[t];\n    //#     var ctype = ctypeA[t];\n    //#     var vnctype = \"V\"+ n + ctype[0];\n    //#     var vnsub1ctype = \"V\"+ nsub1 + ctype[0];\n    //#     var x2t = 2 + tchar;\n    //#     var x3t = 3 + tchar;\n    //#     var x4t = 4 + tchar;\n    //#     var xyznsub1 = \"XYZW\".Substring(0, nsub1);\n    //#     var xyzmsub1 = \"XYZW\".Substring(0, msub1);\n    //#     var getptr = \"&M00\";\n    //#     var isDouble = (ftype == \"double\");\n    //#     var assertEps = isDouble ? \"1e-10\" : \"1e-5f\";\n    #region __nmtype__\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __nmtype__ : IEquatable<__nmtype__>, IValidity, IMatrix<double>\n    {\n        //# n.ForEach(j => {\n        [DataMember]\n        public __ftype__ /*# m.ForEach(k => { */M__j____k__/*# }, comma); */;\n        //# });\n\n        #region Constructors\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __nmtype__(__ftype__ value)\n        {\n            //# n.ForEach(r => {\n            /*# m.ForEach(s => { var v = r == s ? \"value\" : \"0\"; */M__r____s__ = __v__; /*# }); */\n            //# });\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => {*/__ftype__ m__r____s__/*#}, comma);}, comma); */)\n        {\n            //# n.ForEach(r => {\n            /*# m.ForEach(s => { */M__r____s__ = m__r____s__; /*# }); */\n            //# });\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __nmtype__(__ftype__[] a)\n        {\n            //# int l = 0;\n            //# n.ForEach(r => { m.ForEach(s => {\n            M__r____s__ = a[__l__];\n            //# l++; }); });\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __nmtype__(__ftype__[] a, int start)\n        {\n            //# l = 0;\n            //# n.ForEach(r => { m.ForEach(s => {\n            M__r____s__ = a[start + __l__];\n            //# l++; }); });\n        }\n\n        //# if (n == m - 1) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __nmtype__(__nntype__ m, __vntype__ v)\n        {\n            //# n.ForEach(r => {\n            /*# m.ForEach(s => { var value = (s < n) ? \"m.M\" + r + s : \"v.\" + nfields[r]; */M__r____s__ = __value__; /*# });*/\n            //# });\n        }\n\n        //# }\n        //# for (int t1 = 0; t1 < tcharA.Length; t1++) {\n        //#     for (int a = 2; a <= 4; a++) {\n        //#         for (int b = a; b <= (a+1) && b < 5; b++) {\n        //#             var MabType1 = \"M\" + a + b + tcharA[t1];\n        //#             if (n != a || m != b || t1 != t)  {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __nmtype__(__MabType1__ m)\n        {\n            //# n.ForEach(r => {\n            /*# m.ForEach(s => { if (r >= a || s >= b) { if (r != s) {*/M__r____s__ = 0; /*#} else if ( r == s) {*/M__r____s__ = 1; /*#}} if((r < a) && ( s < b)) {*/M__r____s__ = /*# if (t != t1) {*/(__ftype__)/*#}*/m.M__r____s__; /*#} }); */\n            //# });\n        }\n\n        //#             }\n        //#         }\n        //#     }\n        //# }\n        #endregion\n\n        #region Conversions\n\n        //# for (int t1 = 0; t1 < tcharA.Length; t1++) {\n        //#     for (int a = 2; a <= 4; a++) {\n        //#         for (int b = a; b <= (a+1) && b < 5; b++) {\n        //#             var MabType1 = \"M\" + a + b + tcharA[t1];\n        //#             if (n != a || m != b || t1 != t)  {\n        public static explicit operator __nmtype__(__MabType1__ m)\n        {\n            return new __nmtype__ {\n                //# n.ForEach(r => {\n                /*# m.ForEach(s => { if (r >= a || s >= b) { if (r != s) {*/M__r____s__ = 0, /*#} else if ( r == s) {*/M__r____s__ = 1, /*#}} if((r < a) && ( s < b)) {*/M__r____s__ = /*# if (t != t1) {*/(__ftype__)/*#}*/m.M__r____s__, /*#} }); */\n                //# });\n            };\n        }\n\n        //#             }\n        //#         }\n        //#     }\n        //# }\n        //# for (int t1 = 0; t1 < tcharA.Length; t1++) {\n        //#     var ftype1 = ftypeA[t1];\n        public static explicit operator __nmtype__(__ftype1__[] a)\n        {\n            return new __nmtype__(/*# { int c = 0; n.ForEach(r => { */\n                /*# m.ForEach(s => { if (t != t1) { */(__ftype__)/*# } */a[__c__]/*# ++c; }, comma); }, comma); } */);\n        }\n\n        public static explicit operator __nmtype__(__ftype1__[,] a)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { if (t != t1) { */(__ftype__)/*# } */a[__r__, __s__]/*# }, comma); }, comma); */);\n        }\n\n        public static explicit operator __ftype1__[](__nmtype__ m)\n        {\n            return new __ftype1__[] {/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { if (t != t1) { */(__ftype1__)/*# } */m.M__r____s__/*# }, comma); }, comma); */\n            };\n        }\n\n        public static explicit operator __ftype1__[,](__nmtype__ m)\n        {\n            return new __ftype1__[,] {/*# n.ForEach(r => { */\n                { /*# m.ForEach(s => { if (t != t1) { */(__ftype1__)/*# } */m.M__r____s__/*# }, comma); */ }/*# }, comma); */\n            };\n        }\n\n        public readonly void CopyTo(__ftype1__[] array, long index)\n        {\n            //# n.ForEach(j => { m.ForEach(k => { var jk = j * m + k;\n            array[index + __jk__] = /*#  if (t != t1) { */(__ftype1__)/*# } */M__j____k__;\n            //# });});\n        }\n\n        //# }\n        //# for (int t1 = 0; t1 < tcharA.Length; t1++) {\n        //#     var nmtype1 = \"M\" + n + m + tcharA[t1];\n        //#     var ftype1 = ftypeA[t1];\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly __nmtype1__ Copy(Func<__ftype__, __ftype1__> element_fun)\n        {\n            return new __nmtype1__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */element_fun(M__r____s__)/*# }, comma); }, comma); */);\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        public readonly __nmtype1__ Copy(Func<__ftype__, int, int, __ftype1__> element_index0_index1_fun)\n        {\n            return new __nmtype1__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */element_index0_index1_fun(M__r____s__, __r__, __s__)/*# }, comma); }, comma); */);\n        }\n\n        //# }\n        //# if (m == n && m >= 3) {\n        //#     var nmtype1x = \"M\" + (n-1) + (m-1);\n        //#     var nmtype1 = nmtype1x + tchar;\n        /// <summary>\n        /// Returns a copy of the upper left sub matrix.\n        /// </summary>\n        public readonly __nmtype1__ UpperLeft__nmtype1x__()\n        {\n            return (__nmtype1__)this;\n        }\n\n        //# }\n        public readonly __ftype__[] ToArray()\n        {\n            var array = new __ftype__[__nm__];\n            //# n.ForEach(j => { m.ForEach(k => { var jk = j * m + k;\n            array[__jk__] = M__j____k__;\n            //# });});\n            return array;\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ FromCols(/*# m.ForEach(r => {*/__vntype__ col__r__/*#}, comma); */)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(c => { var rf = fields[r]; */col__c__.__rf__/*#}, comma);}, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ FromRows(/*# n.ForEach(r => {*/__vmtype__ row__r__/*#}, comma); */)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# mfields.ForEach(f => {*/row__r__.__f__/*#}, comma);}, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ FromDiagonal(__ftype__ value)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = i == j ? \"value\" : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ FromDiagonal(/*# n.ForEach(i => {*/__ftype__ m__i____i__/*#}, comma); */)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = i == j ? \"m\" + i + i : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ FromDiagonal(__vntype__ s)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = i == j ? \"s.\" + fields[i] : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        //# if (n == m) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ FromAntiDiagonal(__ftype__ value)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                 /*# m.ForEach(j => {\n                  var v = (i + j == n - 1) ? \"value\" : \"0\";\n                  */__v__/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ FromAntiDiagonal(/*# n.ForEach(i => { var j = n - 1 - i; */__ftype__ m__i____j__/*#}, comma); */)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                 var v = (i + j == n - 1) ? \"m\" + i + (n - 1 - i) : \"0\";\n                 */__v__/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ FromAntiDiagonal(__vntype__ s)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = (i + j == n - 1) ? \"s.\" + fields[i] : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        //# }\n        #region Scale\n\n        //# if (n == m) {\n        /// <summary>\n        /// Creates a transformation <see cref=\"__nmtype__\"/> using __m__ scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Scale(/*# mfields.ForEach(f => { */__ftype__ s__f__/*# }, comma); */)\n            => FromDiagonal(/*# mfields.ForEach(f => { */s__f__/*# }, comma); */);\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"__nmtype__\"/> using a <see cref=\"__vmtype__\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Scale(__vmtype__ s)\n            => FromDiagonal(s);\n\n        //# if (t > 1 && n < 4) {\n        /// <summary>\n        /// Creates a transformation <see cref=\"__nmtype__\"/> from a <see cref=\"__scalent__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Scale(__scalemt__ s)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = (i == j) ? \"s.\" + fields[i] : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        //# } // isReal\n        //# }\n        //# if (n > 2 && Math.Abs(n-m) <= 1) {\n        /// <summary>\n        /// Creates a homogenous transformation <see cref=\"__nmtype__\"/> using a uniform scale.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Scale(__ftype__ s)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = i == j ? ((i == m-1) ? \"1\" : \"s\") : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"__nmtype__\"/> using __msub1__ scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Scale(/*# nfields.Take(m - 1).ForEach(f => { */__ftype__ s__f__/*# }, comma); */)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = (i == j) ? ((i < m - 1) ? \"s\" + fields[i] : \"1\") : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"__nmtype__\"/> using a <see cref=\"__vmsub1type__\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Scale(__vmsub1type__ s)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = (i == j) ? ((i < m - 1) ? \"s.\" + fields[i] : \"1\") : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        //# if (t > 1) {\n        /// <summary>\n        /// Creates a scaling transformation <see cref=\"__nmtype__\"/> from a <see cref=\"__scalemsub1t__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Scale(__scalemsub1t__ s)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = (i == j) ? ((i < m - 1) ? \"s.\" + fields[i] : \"1\") : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        //# } // isReal\n        //# }\n        #endregion\n\n        //# if (m > 2) {\n        #region Translation\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"__nmtype__\"/> with the translational component given by __msub1__ scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Translation(/*# fields.Take(m - 1).ForEach(f => { */__ftype__ t__f__/*# }, comma); */)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = i == j ? \"1\" : (j == m - 1) ? \"t\" + fields[i] : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        /// <summary>\n        /// Creates a transformation <see cref=\"__nmtype__\"/> with the translational component given by a <see cref=\"__vmsub1type__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Translation(__vmsub1type__ t)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = i == j ? \"1\" : (j == m - 1) ? \"t.\" + fields[i] : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        //# if (t > 1) {\n        /// <summary>\n        /// Creates a transformation <see cref=\"__nmtype__\"/> from a <see cref=\"__shiftmsub1t__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Translation(__shiftmsub1t__ s)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => { var v = i == j ? \"1\" : (j == m - 1) ? \"s.\" + fields[i] : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        //# }\n        #endregion\n\n        //# }\n        //# if (t > 1) {\n        #region Rotation\n\n        //# if (m < 4) {\n        //# var val = new string[,] { { \" a\", \"-b\" }, { \" b\", \" a\" } };\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Rotation(__ftype__ angleInRadians)\n        {\n            var a = Fun.Cos(angleInRadians);\n            var b = Fun.Sin(angleInRadians);\n\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var x = (i < 2 && j < 2) ? val[i, j] : ((i == j) ? \" 1\" : \" 0\");\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a 2D rotation matrix with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationInDegrees(__ftype__ angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a __n__D rotation matrix from a <see cref=\"__rotnt__\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Rotation(__rotnt__ r)\n            => (__nmtype__)r;\n\n        //# }\n        //# if (n > 2) {\n        //# if (n == m) {\n        /// <summary>\n        /// Creates a __nsub1__D rotation matrix from a <see cref=\"__rotnsub1t__\"/>\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Rotation(__rotnsub1t__ r)\n            => (__nmtype__)r;\n\n        //# }\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Rotation(V__x3t__ normalizedAxis, __ftype__ angleInRadians)\n        {\n            Debug.Assert(normalizedAxis.LengthSquared.ApproximateEquals(1, __assertEps__));\n            return (__nmtype__)(Rot__x3t__.Rotation(normalizedAxis, angleInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationInDegrees(V__x3t__ normalizedAxis, __ftype__ angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationEuler(__ftype__ rollInRadians, __ftype__ pitchInRadians, __ftype__ yawInRadians)\n        {\n            return (__nmtype__)(Rot__x3t__.RotationEuler(rollInRadians, pitchInRadians, yawInRadians));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationEulerInDegrees(__ftype__ rollInDegrees, __ftype__ pitchInDegrees, __ftype__ yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationEuler(V__x3t__ rollPitchYawInRadians)\n            => RotationEuler(\n                rollPitchYawInRadians.X,\n                rollPitchYawInRadians.Y,\n                rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationEulerInDegrees(V__x3t__ rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a 3D rotation matrix which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotateInto(V__x3t__ from, V__x3t__ into)\n        {\n            Debug.Assert(from.LengthSquared.ApproximateEquals(1, __assertEps__));\n            Debug.Assert(into.LengthSquared.ApproximateEquals(1, __assertEps__));\n            return (__nmtype__)(Rot__x3t__.RotateInto(from, into));\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationX(__ftype__ angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var val = new string[,] { {\" 1\", \" 0\", \" 0\" }, {\" 0\", \" a\", \"-b\"}, {\" 0\", \" b\", \" a\"} };\n                   var x = (i < 3 && j < 3) ? val[i, j] : ((i == j) ? \" 1\" : \" 0\");\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationXInDegrees(__ftype__ angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationY(__ftype__ angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var val = new string[,] { {\" a\", \" 0\", \" b\" }, {\" 0\", \" 1\", \" 0\"}, {\"-b\", \" 0\", \" a\"} };\n                   var x = (i < 3 && j < 3) ? val[i, j] : ((i == j) ? \" 1\" : \" 0\");\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationYInDegrees(__ftype__ angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationZ(__ftype__ angleRadians)\n        {\n            var a = Fun.Cos(angleRadians);\n            var b = Fun.Sin(angleRadians);\n\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var val = new string[,] { {\" a\", \"-b\"}, {\" b\", \" a\"} };\n                   var x = (i < 2 && j < 2) ? val[i, j] : ((i == j) ? \" 1\" : \" 0\");\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a 3D rotation matrix for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ RotationZInDegrees(__ftype__ angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        //# }\n        #endregion\n\n        //# }\n        //# if (n > 2) {\n        #region Shearing\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ ShearXY(__ftype__ factorX, __ftype__ factorY)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var val = new string[,] { {\"1\", \"0\", \"factorX\" }, {\"0\", \"1\", \"factorY\"}, {\"0\", \"0\", \"1\"} };\n                   var x = (i < 3 && j < 3) ? val[i, j] : ((i == j) ? \"1\" : \"0\");\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ ShearXZ(__ftype__ factorX, __ftype__ factorZ)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var val = new string[,] { {\"1\", \"factorX\", \"0\" }, {\"0\", \"1\", \"0\"}, {\"0\", \"factorZ\", \"1\"} };\n                   var x = (i < 3 && j < 3) ? val[i, j] : ((i == j) ? \"1\" : \"0\");\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a shear transformation matrix along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ ShearYZ(__ftype__ factorY, __ftype__ factorZ)\n        {\n            return new __nmtype__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var val = new string[,] { {\"1\", \"0\", \"0\" }, {\"factorY\", \"1\", \"0\"}, {\"factorZ\", \"0\", \"1\"} };\n                   var x = (i < 3 && j < 3) ? val[i, j] : ((i == j) ? \"1\" : \"0\");\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        #endregion\n\n        //# }\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        /// <summary>\n        /// Returns the given matrix, with each element divided by <paramref name=\"x\"/>.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ DivideByInt(__nmtype__ m, int x)\n            => m / x;\n\n        #endregion\n\n        #region Properties and Indexers\n\n        public readonly bool IsValid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => true;\n        }\n\n        public readonly bool IsInvalid\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => false;\n        }\n\n        public readonly IEnumerable<__ftype__> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                //# n.ForEach(j => { m.ForEach(k => {\n                yield return M__j____k__;\n                //# });});\n            }\n        }\n\n        public readonly IEnumerable<__vmtype__> Rows\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                //# n.ForEach(k => {\n                yield return R__k__;\n                //# });\n            }\n        }\n\n        public readonly IEnumerable<__vntype__> Columns\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                //# m.ForEach(k => {\n                yield return C__k__;\n                //# });\n            }\n        }\n\n        //# n.ForEach(k => {\n        [XmlIgnore]\n        public __vmtype__ R__k__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new __vmtype__(/*# m.ForEach(f => {*/ M__k____f__/*#}, comma); */); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                //# mfields.ForEach((f, j) => {\n                M__k____j__ = value.__f__;\n                //# });\n            }\n        }\n\n        //# });\n        //# m.ForEach(k => {\n        [XmlIgnore]\n        public __vntype__ C__k__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new __vntype__(/*# n.ForEach(f => {*/ M__f____k__/*#}, comma); */); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                //# nfields.ForEach((f, j) => {\n                M__j____k__ = value.__f__;\n                //# });\n            }\n        }\n\n        //# });\n        public readonly __vntype__ Diagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __vntype__(/*# n.ForEach(i => {*/M__i____i__/*#}, comma); */);\n        }\n\n        //# if (n == m) {\n        public readonly __vntype__ AntiDiagonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __vntype__(/*# n.ForEach(i => { var j = n - 1 - i; */M__i____j__/*#}, comma); */);\n        }\n\n        //# }\n        /// <summary>\n        /// Returns the minimum element of the matrix.\n        /// </summary>\n        public readonly __ftype__ MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(/*# n.ForEach(r => { m.ForEach(s => {*/M__r____s__/*#}, comma);}, comma); */);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the matrix.\n        /// </summary>\n        public readonly __ftype__ MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(/*# n.ForEach(r => { m.ForEach(s => {*/M__r____s__/*#}, comma);}, comma); */);\n        }\n\n        public unsafe __ftype__ this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (__ftype__* ptr = __getptr__) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (__ftype__* ptr = __getptr__) { ptr[index] = value; }\n            }\n        }\n\n        public unsafe __ftype__ this[int row, int column]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (__ftype__* ptr = __getptr__) { return ptr[row * __m__ + column]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (__ftype__* ptr = __getptr__) { ptr[row * __m__ + column] = value; }\n            }\n        }\n\n        //# if (isReal) {\n        //# var condArray = new[] { \"Finite\", \"NaN\", \"Infinity\", \"PositiveInfinity\", \"NegativeInfinity\", \"Tiny\" };\n        //# var scopeArray = new[] { \"Fun\", ftype, ftype, ftype, ftype, \"Fun\" };\n        //# var quantArray = new[] { \"Any\", \"All\" };\n        //# var actArray = new[] { oror, andand };\n        //# condArray.ForEach(scopeArray, (cond, scope) => {\n        //# quantArray.ForEach(actArray, (qant, act) => {\n        public readonly bool __qant____cond__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return /*# n.ForEach(i => {*/\n                    /*#m.ForEach(j => { */__scope__.Is__cond__(M__i____j__)/*# }, act); }, act); */;\n            }\n        }\n\n        //# }); // quantArray\n        //# }); // condArray\n        /// <summary>\n        /// Returns true if the absolute value of each element of the matrix is smaller than Constant&lt;__ftype__&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any element of the matrix is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all elements of the matrix are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        //# } // isReal\n        #endregion\n\n        #region Constants\n\n        public const int RowCount = __n__;\n        public const int ColumnCount = __m__;\n        public const int ElementCount = __n__ * __m__;\n\n        public static V2l Dimensions\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new V2l(__n__, __m__);\n        }\n\n        public static __nmtype__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __nmtype__(0);\n        }\n\n        //# if (n == m) {\n        public static __nmtype__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __nmtype__(/*# n.ForEach(i => { m.ForEach(j => { var v = i == j ? \"1\" : \"0\"; */__v__/*# }, comma); }, comma); */);\n        }\n\n        //# }\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        public readonly __ftype__ Norm1\n        {\n            get\n            {\n                return /*# n.ForEach(i => { */\n                    /*# m.ForEach(j => { */Fun.Abs(M__i____j__)/*# }, add); }, add); */;\n            }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        public readonly __ctype__ Norm2\n        {\n            get\n            {\n                return Fun.Sqrt(/*# n.ForEach(i => { */\n                    /*# m.ForEach(j => { */M__i____j__ * M__i____j__/*# }, add); }, add); */);\n            }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly __ftype__ NormMax\n        {\n            get\n            {\n                return Fun.Max(/*# n.ForEach(i => { */\n                            Fun.Max(/*# m.ForEach(j => { */\n                                Fun.Abs(M__i____j__)/*# }, comma); */)/*# }, comma); */);\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        public readonly __ftype__ NormMin\n        {\n            get\n            {\n                return Fun.Min(/*# n.ForEach(i => { */\n                            Fun.Min(/*# m.ForEach(j => { */\n                                Fun.Abs(M__i____j__)/*# }, comma); */)/*# }, comma); */);\n            }\n        }\n\n        #endregion\n\n        #region Mathematical Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ operator -(__nmtype__ m)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */-m.M__r____s__/*# }, comma); }, comma); */);\n        }\n\n        //# for (int o = 0; o < ops.Length; o++) { var op = ops[o]; var opact = \"operator \" + op;\n        //#     for (int t1 = t; t1 < tcharA.Length; t1++) {\n        //#         var nmtype1 = \"M\" + n + m + tcharA[t1];\n        //#         var ftype1 = ftypeA[t1];\n        //#         if (o != ops.Length-1) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype1__ __opact__(__nmtype__ a, __nmtype1__ b)\n        {\n            return new __nmtype1__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */a.M__r____s____op__b.M__r____s__/*# }, comma); }, comma); */);\n        }\n\n        //#             }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype1__ __opact__(__nmtype__ m, __ftype1__ s)\n        {\n            return new __nmtype1__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */m.M__r____s____op__s/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype1__ __opact__(__ftype1__ s, __nmtype__ m)\n        {\n            return new __nmtype1__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */s__op__m.M__r____s__/*# }, comma); }, comma); */);\n        }\n\n        //#     }\n        //# }\n        #endregion\n\n        //# if (!isReal) {\n        #region Bitwise Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ operator ~(__nmtype__ m)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */~m.M__r____s__/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ operator <<(__nmtype__ a, int s)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */a.M__r____s__ << s/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ operator >>(__nmtype__ a, int s)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */a.M__r____s__ >> s/*# }, comma); }, comma); */);\n        }\n\n        //# foreach (var op in bwops) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ operator __op__(__nmtype__ a, __nmtype__ b)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */a.M__r____s__ __op__ b.M__r____s__/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ operator __op__(__nmtype__ a, __ftype__ s)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */a.M__r____s__ __op__ s/*# }, comma); }, comma); */);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ operator __op__(__ftype__ s, __nmtype__ a)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(s => { */s __op__ a.M__r____s__/*# }, comma); }, comma); */);\n        }\n\n        //# }\n        #endregion\n\n        //# }\n        #region Matrix/Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a __nmtype__ matrix with a __vmtype__ column vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vntype__ operator *(__nmtype__ m, __vmtype__ v)\n        {\n            return new __vntype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(q => { var f = fields[q]; */m.M__r____q__ * v.__f__/*# }, add); }, comma); */);\n        }\n\n        /// <summary>\n        /// Multiplies a __vntype__ row vector with a __nmtype__ matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmtype__ operator *(__vntype__ v, __nmtype__ m)\n        {\n            return new __vmtype__(/*# m.ForEach(q => { */\n                /*# n.ForEach(r => { var f = fields[r]; */v.__f__ * m.M__r____q__/*# }, add); }, comma); */);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__nmtype__ a, __nmtype__ b)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                a.M__i____j__ == b.M__i____j__/*#}, andand);}, andand);*/;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__nmtype__ a, __ftype__ s)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                a.M__i____j__ == s/*# }, andand); }, andand); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__ftype__ s, __nmtype__ a)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                s == a.M__i____j__ /*# }, andand); }, andand); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__nmtype__ a, __nmtype__ b)\n        {\n            return !(a == b);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__nmtype__ m, __ftype__ s)\n        {\n            return !(m == s);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__ftype__ s, __nmtype__ m)\n        {\n            return !(s == m);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(/*# n.ForEach(r => { */\n                        HashCode.GetCombined(/*# m.ForEach(s => {*/M__r____s__/*# }, comma); }, bracketComma); */));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__nmtype__ other)\n        {\n            return /*# n.ForEach(i => { */\n                /*# m.ForEach(j => { */M__i____j__.Equals(other.M__i____j__)/*#}, andand);}, andand);*/;\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is __nmtype__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\", \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 2x2-Matrix in the form \"(beginM)(beginR)m00(betweenR)m01(endR)(betweenM)(beginR)m10(betweenR)m11(endR)(endM)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string beginM, string betweenM, string endM, string beginR, string betweenR, string endR)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return beginM/*# n.ForEach(r => {*/\n                + R__r__.ToString(format, fp, beginR, betweenR, endR) /*# }, addbetweenM); */\n            + endM;\n        }\n\n        public static __nmtype__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return __nmtype__.FromRows(/*# n.ForEach(i => { */\n                __vmtype__.Parse(x[__i__])/*# }, comma); */\n            );\n        }\n\n        #endregion\n\n        #region Matrix Operations\n\n        //# if(m == n) {\n        /// <summary>\n        /// Returns adjoint of this matrix.\n        /// </summary>\n        public readonly __nmtype__ Adjoint\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                //# if (n == 2) {\n                return new __nmtype__(M11, -M10, -M01, M00);\n                //# } else {\n                __nmtype__ result = new __nmtype__();\n                for (int row = 0; row < __n__; row++)\n                {\n                    for (int col = 0; col < __m__; col++)\n                    {\n                        if (((col + row) % 2) == 0)\n                            result[col, row] = this.Minor(row, col).Determinant;\n                        else\n                            result[col, row] = -this.Minor(row, col).Determinant;\n                    }\n                }\n\n                return result;\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Returns the trace of this matrix.\n        /// The trace is defined as the sum of the diagonal elements,\n        /// and is only defined for square matrices.\n        /// </summary>\n        public readonly __ftype__ Trace\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return /*# n.ForEach(r => {*/M__r____r__/*# }, add);*/ ; }\n        }\n\n        /// <summary>\n        /// Gets the determinant of this matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        public readonly __ftype__ Determinant\n        {\n            get\n            {\n                //# if (n == 2) {\n                return M00 * M11 - M10 * M01;\n                //# }\n                //# if (n == 3) {\n                if (M10 == 0 && M20 == 0 && M21 == 0)\n                {\n                    return M00 * M11 * M22;\n                }\n                return\n                M00 * M11 * M22 - M00 * M12 * M21 +\n                M01 * M12 * M20 - M01 * M10 * M22 +\n                M02 * M10 * M21 - M02 * M11 * M20;\n                //# }\n                //# if (n == 4) {\n                // using bottom row because elements M30, M31, and M32\n                // are zero most of the time.\n                __ftype__ d = 0;\n                if (M30 != 0.0f) d -= M30 * (\n                M01 * M12 * M23 + M02 * M13 * M21 + M03 * M11 * M22\n                - M21 * M12 * M03 - M22 * M13 * M01 - M23 * M11 * M02\n                );\n                if (M31 != 0.0f) d += M31 * (\n                M00 * M12 * M23 + M02 * M13 * M20 + M03 * M10 * M22\n                - M20 * M12 * M03 - M22 * M13 * M00 - M23 * M10 * M02\n                );\n                if (M32 != 0.0f) d -= M32 * (\n                M00 * M11 * M23 + M01 * M13 * M20 + M03 * M10 * M21\n                - M20 * M11 * M03 - M21 * M13 * M00 - M23 * M10 * M01\n                );\n                if (M33 != 0.0f) d += M33 * (\n                M00 * M11 * M22 + M01 * M12 * M20 + M02 * M10 * M21\n                - M20 * M11 * M02 - M21 * M12 * M00 - M22 * M10 * M01\n                );\n                return d;\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is invertible.\n        /// A matrix is invertible if its determinant is not zero.\n        /// </summary>\n        public readonly bool Invertible\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant != 0; }\n        }\n\n        /// <summary>\n        /// Returns whether this matrix is singular.\n        /// A matrix is singular if its determinant is zero.\n        /// </summary>\n        public readonly bool Singular\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Determinant == 0; }\n        }\n\n        /// <summary>\n        /// Gets transpose of this matrix.\n        /// </summary>\n        public readonly __nmtype__ Transposed\n        {\n            get\n            {\n                return new __nmtype__ {/*# n.ForEach(r => { */\n                    /*# m.ForEach(s => { */\n                    M__r____s__ = M__s____r__/*# }, comma); }, comma); */\n                };\n            }\n        }\n\n        //# if (t > 1) {\n        private static V2l s_luSize = new V2l(__n__, __n__);\n        private static V2l s_luDelta = new V2l(1, __n__);\n\n        /// <summary>\n        /// Inverts the given matrix using lu factorization in place. Returns true\n        /// if the matrix was invertible, otherwise the matrix remains unchanged.\n        /// </summary>\n        public/*# if(ftype == \"double\") { Out(\" unsafe\"); } */ bool LuInvert()\n        {\n            //# if (ftype == \"double\") {\n            fixed (__nmtype__* self = &this)\n            {\n                var lu = this;\n                __vnitype__ perm;\n                if (NumericExtensions.LuFactorize((__ftype__*)&lu, 0, 1, __n__, (int*)&perm, __n__))\n                {\n                    NumericExtensions.LuInverse((__ftype__*)&lu, 0, 1, __n__, (int*)&perm, (__ftype__*)self, 0, 1, __n__, __n__);\n                    return true;\n                }\n                return false;\n            }\n            //# } else {\n            M__n____n__d dbl = (M__n____n__d)this;\n            if(dbl.LuInvert())\n            {\n                this = (__nmtype__)dbl;\n                return true;\n            }\n            return false;\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the inverse of the matrix using lu factorization.\n        /// If the matrix is not invertible, __nmtype__.Zero is returned.\n        /// </summary>\n        public/*# if(ftype == \"double\") { Out(\" unsafe\"); } */ readonly __nmtype__ LuInverse()\n        {\n            //# if (ftype == \"double\") {\n            var lu = this;\n            __nmtype__ res;\n            __vnitype__ perm;\n            if (NumericExtensions.LuFactorize((__ftype__*)&lu, 0, 1, __n__, (int*)&perm, __n__))\n            {\n                NumericExtensions.LuInverse((__ftype__*)&lu, 0, 1, __n__, (int*)&perm, (__ftype__*)&res, 0, 1, __n__, __n__);\n                return res;\n            }\n            return __nmtype__.Zero;\n            //# } else {\n            return (__nmtype__)((M__n____n__d)this).LuInverse();\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the inverse of this matrix. If the matrix is not invertible\n        /// __nmtype__.Zero is returned.\n        /// </summary>\n        public readonly __nmtype__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => LuInverse();\n        }\n\n        //# }\n        //# }\n        #endregion\n\n        #region Matrix Multiplication\n\n        //# for (int a = n; a <= n+1 && a < 5; a++) {\n        //# if(a == m) {\n        public static M__n____a____tchar__ operator *(M__n____a____tchar__ a, M__a____a____tchar__ b)\n        {\n            return new M__n____a____tchar__(/*# n.ForEach(r => { *//*# a.ForEach(s => { */\n                /*# a.ForEach(u => {*/a.M__r____u__ * b.M__u____s__/*# }, add);}, comma);}, comma); */\n             );\n        }\n\n        //# }\n        //# if ((a == n) && (a < 4)) {\n        //#     int b = a+1;\n        //#     if( b == m) {\n        public static M__n____b____tchar__ operator *(M__n____a____tchar__ a, M__a____b____tchar__ b)\n        {\n            return new M__n____b____tchar__(/*# n.ForEach(r => { *//*# b.ForEach(s => { */\n                /*# a.ForEach(u => {*/a.M__r____u__ * b.M__u____s__/*# }, add);}, comma);}, comma); */\n             );\n        }\n\n        //#         }\n        //#     }\n        //#  }\n        #endregion\n\n        #region IMatrix<double>\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[long x, long y]\n        {\n            readonly get\n            {\n                return /*# if (ftype != \"double\") { */(double)/*# } */this[(int)y, (int)x];\n            }\n            set\n            {\n                this[(int)y, (int)x] = /*# if (ftype != \"double\") { */(__ftype__)/*# } */value;\n            }\n        }\n\n        /// <summary>\n        /// NOTE: this indexer has reversed order of coordinates with respect to\n        /// the default indexer!!!\n        /// </summary>\n        public double this[V2l v]\n        {\n            readonly get\n            {\n                return /*# if (ftype != \"double\") { */(double)/*# } */this[(int)v.Y, (int)v.X];\n            }\n            set\n            {\n                this[(int)v.Y, (int)v.X] = /*# if (ftype != \"double\") { */(__ftype__)/*# } */value;\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        public readonly V2l Dim\n        {\n            get { return Dimensions; }\n        }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[(int)x, (int)y];\n        }\n\n        public void SetValue(object value, long x, long y)\n        {\n            this[(int)x, (int)y] = (__ftype__)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[(int)(v.X), (int)(v.Y)];\n        }\n\n        public void SetValue(object value, V2l v)\n        {\n            this[(int)(v.X), (int)(v.Y)] = (__ftype__)value;\n        }\n\n        #endregion\n    }\n\n    public class __nmtype__EqualityComparer : IEqualityComparer<__nmtype__>\n    {\n        public static readonly __nmtype__EqualityComparer Default\n            = new __nmtype__EqualityComparer();\n\n        #region IEqualityComparer<__nmtype__> Members\n\n        public bool Equals(__nmtype__ v0, __nmtype__ v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(__nmtype__ v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods.\n    /// </summary>\n    public static partial class Mat\n    {\n        #region Transformation Extraction\n\n        //# if (t > 1 && n == 2) {\n        /// <summary>\n        /// Computes the (signed) angle in radians of a <see cref=\"__nmtype__\"/> rotation matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ GetRotation(this __nmtype__ m)\n            => Fun.Atan2(m.M10, m.M00);\n\n        //# }\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ GetScale(this __nmtype__ m)\n            => (/*# n.ForEach(i => {*/m.C__i__.Length/*# }, add);*/) / __n__;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnctype__ GetScaleVector(this __nmtype__ m)\n            => new __vnctype__(/*# n.ForEach(i => {*/m.C__i__.Length/*# }, comma);*/);\n\n        //# if (n > 2 && n == m) {\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation matrix (average length of __nsub1__D basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ GetScale__nsub1__(this __nmtype__ m)\n            => (/*# nsub1.ForEach(i => {*/m.C__i__.__xyznsub1__.Length/*# }, add);*/) / __nsub1__;\n\n        /// <summary>\n        /// Extracts a scale vector from the given matrix by calculating the lengths of the __nsub1__D basis vectors.\n        /// NOTE: The extraction only gives absolute value (negative scale will be ignored)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnsub1ctype__ GetScaleVector__nsub1__(this __nmtype__ m)\n            => new __vnsub1ctype__(/*# nsub1.ForEach(i => {*/m.C__i__.__xyznsub1__.Length/*# }, comma);*/);\n\n        //# }\n        //# if (t > 1 && m == 4) {\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A left-handed coordinates system transformation is expected,\n        /// where the view-space z-axis points in forward direction.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmsub1type__ GetViewDirectionLH(this __nmtype__ m)\n            => m.R__msub2__.__xyzmsub1__.Normalized;\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation matrix.\n        /// NOTE: A right-handed coordinates system transformation is expected, where\n        /// the view-space z-axis points opposit the forward vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmsub1type__ GetViewDirectionRH(this __nmtype__ m)\n            => -m.R__msub2__.__xyzmsub1__.Normalized;\n\n        /// <summary>\n        /// Extracts the translation component of the given transformation matrix, which when given\n        /// a model transformation represents the model origin in world position.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmsub1type__ GetModelOrigin(this __nmtype__ m)\n            => m.C__msub1__/*# if (n != msub1) {*/.__xyzmsub1__/*#} */;\n\n        //# }\n        //# if (t == 3 && n == 4 && n == m) {\n        /// <summary>\n        /// Builds a hull from the given view-projection transformation matrix (left, right, bottom, top, near, far).\n        /// The view volume is assumed to be [-1, -1, -1] [1, 1, 1].\n        /// The normals of the hull planes point to the outside and are normalized.\n        /// A point inside the visual hull will has negative height to all planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Hull3d GetVisualHull(this __nmtype__ viewProj)\n        {\n            var r0 = viewProj.R0;\n            var r1 = viewProj.R1;\n            var r2 = viewProj.R2;\n            var r3 = viewProj.R3;\n\n            return new Hull3d(new[]\n            {\n                new Plane3d((-(r3 + r0))).Normalized, // left\n                new Plane3d((-(r3 - r0))).Normalized, // right\n                new Plane3d((-(r3 + r1))).Normalized, // bottom\n                new Plane3d((-(r3 - r1))).Normalized, // top\n                new Plane3d((-(r3 + r2))).Normalized, // near\n                new Plane3d((-(r3 - r2))).Normalized, // far\n            });\n        }\n\n        //# }\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the matrix. This is\n        /// calculated as |M00| + |M01| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Norm1(__nmtype__ m)\n            => m.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the matrix. This is\n        /// calculated as Sqrt(M00 * M00 + M01 * M01 + ... )\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ Norm2(__nmtype__ m)\n            => m.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the matrix. This is\n        /// calculated as max(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ NormMax(__nmtype__ m)\n            => m.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the matrix. This is calculated as\n        /// min(|M00|, |M01|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ NormMin(__nmtype__ m)\n            => m.NormMin;\n\n        /// <summary>\n        /// Returns the p-norm of the matrix. This is calculated as\n        /// (|M00|^p + |M01|^p + ... )^(1/p)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ Norm(this __nmtype__ m, __ctype__ p)\n        {\n            return (/*# n.ForEach(i => { m.ForEach(j => { */\n                Fun.Abs(m.M__i____j__).Pow(p)/*# }, add); }, add); */\n            ).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two matrices.\n        /// </summary>\n        public static __ftype__ Distance1(this __nmtype__ a, __nmtype__ b)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                Fun.Abs(b.M__i____j__ - a.M__i____j__)/*# }, add); }, add); */;\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) distance between two matrices.\n        /// </summary>\n        public static __ctype__ Distance2(this __nmtype__ a, __nmtype__ b)\n        {\n            return /*# if (ctype != \"double\") {*/(__ctype__)/*# } */Fun.Sqrt(/*# n.ForEach(i => { m.ForEach(j => { */\n                        Fun.Square(b.M__i____j__ - a.M__i____j__)/*# }, add); }, add); */);\n        }\n\n        /// <summary>\n        /// Returns the p-distance between two matrices.\n        /// </summary>\n        public static __ctype__ Distance(this __nmtype__ a, __nmtype__ b, __ctype__ p)\n        {\n            return (/*# n.ForEach(i => { m.ForEach(j => { */\n                Fun.Abs(b.M__i____j__ - a.M__i____j__).Pow(p)/*# }, add); }, add); */\n            ).Pow(1 / p);\n        }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static __ftype__ DistanceMax(this __nmtype__ a, __nmtype__ b)\n        {\n            return Fun.Max(/*# n.ForEach(i => { */\n                        Fun.Max(/*# m.ForEach(j => { */\n                            Fun.Abs(b.M__i____j__ - a.M__i____j__)/*#\n                                                }, comma); */)/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two matrices.\n        /// </summary>\n        public static __ftype__ DistanceMin(this __nmtype__ a, __nmtype__ b)\n        {\n            return Fun.Min(/*# n.ForEach(i => { */\n                        Fun.Min(/*# m.ForEach(j => { */\n                            Fun.Abs(b.M__i____j__ - a.M__i____j__)/*#\n                                                }, comma); */)/*# }, comma); */);\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vntype__ Transform(this __nmtype__ m, __vmtype__ v)\n            => m * v;\n\n        //# for (int k = m + 1; k <= 4; k++) {\n        //# var d = k - m;\n        //# var vktype = \"V\" + k + tchar;\n        //# var vrettype = \"V\" + (n + d) + tchar;\n        //# var constfields = fields.Skip(m).Take(d);\n        //# var isare = (d > 1) ? \"are\" : \"is\";\n        /// <summary>\n        /// Transforms vector v by matrix m.\n        /// /*# constfields.ForEach(f => {*/v.__f__/*# }, andLit); */ __isare__ not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vrettype__ Transform(this __nmtype__ m, __vktype__ v)\n        {\n            return new __vrettype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(q => { var f = fields[q]; */m.M__r____q__ * v.__f__/*# }, add); }, comma); */,\n                /*# constfields.ForEach(f => { */v.__f__/*# }, comma);*/);\n        }\n\n        //# }\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmtype__ TransposedTransform(this __nmtype__ m, __vntype__ v)\n            => v * m;\n\n        //# if (n == m) {\n        //# for (int k = n + 1; k <= 4; k++) {\n        //# var d = k - n;\n        //# var vktype = \"V\" + k + tchar;\n        //# var vrettype = \"V\" + (m + d) + tchar;\n        //# var constfields = fields.Skip(n).Take(d);\n        //# var isare = (d > 1) ? \"are\" : \"is\";\n        /// <summary>\n        /// Transforms vector v by the transpose of matrix m.\n        /// /*# constfields.ForEach(f => {*/v.__f__/*# }, andLit); */ __isare__ not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vrettype__ TransposedTransform(this __nmtype__ m, __vktype__ v)\n        {\n            return new __vrettype__(/*# m.ForEach(q => { */\n                /*# n.ForEach(r => { var f = fields[r]; */v.__f__ * m.M__r____q__/*# }, add); }, comma); */,\n                /*# constfields.ForEach(f => { */v.__f__/*# }, comma);*/);\n        }\n\n        //# } }\n        //# if (m > 2) {\n        /// <summary>\n        /// Transforms direction vector v (v.__fields[m-1]__ is presumed 0.0) by matrix m.\n        /// </summary>\n        public static __vmsub1type__ TransformDir(this __nmtype__ m, __vmsub1type__ v)\n        {\n            return new __vmsub1type__(/*# msub1.ForEach(s => { */\n                /*# mfields.Take(msub1).ForEach((fr, r) => { */m.M__s____r__ * v.__fr__/*# }, add); }, comma); */\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.__fields[m-1]__ is presumed 1.0) by matrix m./*# if (n == m) {*/\n        /// No projective transform is performed./*# }*/\n        /// </summary>\n        public static __vmsub1type__ TransformPos(this __nmtype__ m, __vmsub1type__ p)\n        {\n            return new __vmsub1type__(/*# msub1.ForEach(s => { */\n                /*# mfields.Take(msub1).ForEach((fr, r) => { */m.M__s____r__ * p.__fr__/*# }, add); */ + m.M__s____msub1__/*# }, comma); */\n                );\n        }\n\n        //# if (n == m) {\n        /// <summary>\n        /// Transforms point p (p.__fields[m-1]__ is presumed 1.0) by matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static __vmsub1type__ TransformPosProj(this __nmtype__ m, __vmsub1type__ p)\n        {\n            __ftype__ s = /*# mfields.Take(msub1).ForEach((fr, r) => { */m.M__msub1____r__ * p.__fr__/*#}, add);*/ + m.M__msub1____msub1__;\n            return TransformPos(m, p) * (1 / s);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.__fields[m-1]__ is presumed 1.0) by matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static __vmtype__ TransformPosProjFull(this __nmtype__ m, __vmsub1type__ p)\n        {\n            return new __vmtype__(/*# m.ForEach(s => { */\n                /*# mfields.Take(msub1).ForEach((fr, r) => { */m.M__s____r__ * p.__fr__/*#}, add);*/ + m.M__s____msub1__/*#}, comma);*/\n                );\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.__fields[m-1]__ is presumed 0.0) by transposed version of matrix m.\n        /// </summary>\n        public static __vmsub1type__ TransposedTransformDir(this __nmtype__ m, __vmsub1type__ v)\n        {\n            return new __vmsub1type__(/*# msub1.ForEach(s => { */\n                /*# mfields.Take(msub1).ForEach((fr, r) => { */m.M__r____s__ * v.__fr__/*# }, add); }, comma); */\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.__fields[m-1]__ is presumed 1.0) by transposed version of matrix m.\n        /// No projective transform is performed.\n        /// </summary>\n        public static __vmsub1type__ TransposedTransformPos(this __nmtype__ m, __vmsub1type__ p)\n        {\n            return new __vmsub1type__(/*# msub1.ForEach(s => { */\n                /*# mfields.Take(msub1).ForEach((fr, r) => { */m.M__r____s__ * p.__fr__/*# }, add); */ + m.M__msub1____s__/*# }, comma); */\n                );\n        }\n\n        /// <summary>\n        /// Transforms point p (v.__fields[m-1]__ is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        public static __vmsub1type__ TransposedTransformPosProj(this __nmtype__ m, __vmsub1type__ p)\n        {\n            var s = /*# mfields.Take(msub1).ForEach((fr, r) => { */m.M__r____msub1__ * p.__fr__/*#}, add);*/ + m.M__msub1____msub1__;\n            return TransposedTransformPos(m, p) * (1 / s);\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProj instead.\")]\n        public static __vmsub1type__ TransposedTransformProj(this __nmtype__ m, __vmsub1type__ p)\n            => m.TransposedTransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (v.__fields[m-1]__ is presumed 1.0) by transposed version of matrix m.\n        /// Projective transform is performed.\n        /// </summary>\n        public static __vmtype__ TransposedTransformPosProjFull(this __nmtype__ m, __vmsub1type__ p)\n        {\n            return new __vmtype__(/*# m.ForEach(s => { */\n                /*# mfields.Take(msub1).ForEach((fr, r) => { */m.M__r____s__ * p.__fr__/*#}, add);*/ + m.M__msub1____s__/*#}, comma);*/\n                );\n        }\n\n        [Obsolete(\"Use TransposedTransformPosProjFull instead.\")]\n        public static __vmtype__ TransposedTransformProjFull(this __nmtype__ m, __vmsub1type__ p)\n            => m.TransposedTransformPosProjFull(p);\n\n        //# } // n != m\n        //# } // m > 2\n        //# if (m == n + 1) {\n        /// <summary>\n        /// Multiplies two <see cref=\"__nmtype__\"/> matrices as __m__x__m__ matrices.\n        /// </summary>\n        public static __nmtype__ MultiplyAffine(this __nmtype__ a, __nmtype__ b)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { m.ForEach(c => { */\n                /*# n.ForEach(j => {*/a.M__r____j__ * b.M__j____c__/*# }, add);\n                  if (c == m - 1) {*/ + a.M__r____c__/*# }\n                  }, comma);}, comma); */\n            );\n        }\n\n        //# }\n        #endregion\n\n        #region Operations\n\n        //# if (n == m) {\n        //# var rettype = (n > 2) ? \"M\" + nsub1 + msub1 + tchar : ftype;\n        //# var size = nsub1 * nsub1;\n        /// <summary>\n        /// Returns the given <see cref=\"__nmtype__\"/> to a deleting the\n        /// specified row and column.\n        /// </summary>\n        public static __rettype__ Minor(this __nmtype__ m, int row, int column)\n        {\n            //# if (n == 2) {\n            return m[1 - row, 1 - column];\n            //# } else {\n            __rettype__ rs = new __rettype__();\n\n            for (int k = 0; k < __size__; k++)\n            {\n                var i = k / __nsub1__;\n                var j = k % __nsub1__;\n                var ii = (i < row) ? i : i + 1;\n                var jj = (j < column) ? j : j + 1;\n\n                rs[k] = m[ii * __n__ + jj];\n            }\n\n            return rs;\n            //# }\n        }\n\n        //# }\n        /// <summary>\n        /// Returns index-th row of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static __vmtype__ Row(this __nmtype__ m, int index)\n        {\n            __ftype__* ptr = &m.M00;\n            return new __vmtype__(/*# m.ForEach(j => {\n                */ptr[index * __m__/*#\n                if (j > 0) {*/ + __j__/*#\n                }*/]/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Returns index-th column of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public unsafe static __vntype__ Column(this __nmtype__ m, int index)\n        {\n            __ftype__* ptr = &m.M00;\n            return new __vntype__(/*# n.ForEach(i => {\n                var offset = i * m;\n                */ptr[index/*#\n                if (offset > 0) {*/ + __offset__/*#\n                }*/]/*# }, comma);*/);\n        }\n\n        //# if( m == n) {\n        /// <summary>\n        /// Returns the determinant of the given matrix.\n        /// The determinant is only defined for square matrices.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Determinant(__nmtype__ m)\n            => m.Determinant;\n\n        /// <summary>\n        /// Returns the transpose of the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Transposed(__nmtype__ m)\n            => m.Transposed;\n\n        /// <summary>\n        /// Transposes the given matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Transpose(this ref __nmtype__ m)\n        {\n            //# for (int r = 1; r < n; r++) { r.ForEach(s => {\n            Fun.Swap(ref m.M__r____s__, ref m.M__s____r__);\n            //# }); }\n        }\n\n        //# if (isReal) {\n        /// <summary>\n        /// Returns the inverse of the given matrix. If the matrix is not invertible\n        /// __nmtype__.Zero is returned.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Inverse(__nmtype__ m)\n            => m.Inverse;\n\n        /// <summary>\n        /// Inverts the given matrix in place. Returns true if the matrix was invertible,\n        /// otherwise the matrix remains unchanged.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Invert(this ref __nmtype__ m) { return m.LuInvert(); }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this __nmtype__ m, __ftype__ epsilon)\n        {\n            return Fun.ApproximateEquals(m, __nmtype__.Identity, epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is the identity matrix I.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsIdentity(this __nmtype__ m)\n            => IsIdentity(m, Constant<__ftype__>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this __nmtype__ m, __ftype__ epsilon)\n        {\n            var i = m * m.Transposed;\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthonormal (i.e. M * M^t == I)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthonormal(this __nmtype__ m)\n            => IsOrthonormal(m, Constant<__ftype__>.PositiveTinyValue);\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this __nmtype__ m, __ftype__ epsilon)\n        {\n            var i = m * m.Transposed;\n            for (int j = 0; j < __n__; j++)\n                i[j, j] = 1; //inefficient implementation: just leave out the comparisons at the diagonal entries.\n            return i.IsIdentity(epsilon);\n        }\n\n        /// <summary>\n        /// Returns if the given matrix is orthogonal (i.e. all non-diagonal entries of M * M^t == 0)\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsOrthogonal(this __nmtype__ m)\n            => IsOrthogonal(m, Constant<__ftype__>.PositiveTinyValue);\n\n        //# }\n        //# }\n        #endregion\n\n        #region Comparisons\n\n        //# var bops = new[,] { { \"<\",  \"Smaller\"        }, { \">\" , \"Greater\"},\n        //#                     { \"<=\", \"SmallerOrEqual\" }, { \">=\", \"GreaterOrEqual\"},\n        //#                     { \"==\", \"Equal\" },          { \"!=\", \"Different\" } };\n        //# var attention = \"ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\";\n        //# for(int o = 0; o < bops.GetLength(0); o++) {\n        //#     string bop = \" \" + bops[o,0] + \" \", opName = bops[o,1];\n        /// <summary>\n        /// Returns whether ALL elements of a are __opName__ the corresponding element of b.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(this __nmtype__ a, __nmtype__ b)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                a.M__i____j____bop__b.M__i____j__/*#}, andand);}, andand);*/;\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of m are __opName__ s.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(this __nmtype__ m, __ftype__ s)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                m.M__i____j____bop__s/*#}, andand);}, andand);*/;\n        }\n\n        /// <summary>\n        /// Returns whether a is __opName__ ALL elements of m.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(__ftype__ s, __nmtype__ m)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                s__bop__m.M__i____j__/*#}, andand);}, andand);*/;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is __opName__ the corresponding element of b.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(this __nmtype__ a, __nmtype__ b)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                a.M__i____j____bop__b.M__i____j__/*#}, oror);}, oror);*/;\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of m is __opName__ s.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(this __nmtype__ m, __ftype__ s)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                m.M__i____j____bop__s/*#}, oror);}, oror);*/;\n        }\n\n        /// <summary>\n        /// Returns whether a is __opName__ AT LEAST ONE element of m.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(__ftype__ s, __nmtype__ m)\n        {\n            return/*# n.ForEach(i => { m.ForEach(j => { */\n                s__bop__m.M__i____j__/*#}, oror);}, oror);*/;\n        }\n\n        //# }\n\n        /// <summary>\n        /// Compare first element of first row before second element of first row, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this __nmtype__ m0, __nmtype__ m1)\n        {\n            /*# n.ForEach(i => { m.ForEach(j => { */\n            if (m0.M__i____j__ < m1.M__i____j__) return -1;\n            if (m0.M__i____j__ > m1.M__i____j__) return +1;/*#});});*/\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"__nmtype__\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ MinElement(__nmtype__ m)\n            => m.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"__nmtype__\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ MaxElement(__nmtype__ m)\n            => m.MaxElement;\n\n        #endregion\n        //# if (m == n && isReal) {\n\n        #region Orthogonalization\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"__nmtype__\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthogonalize(this ref __nmtype__ matrix)\n        {\n            //# for (int j = 1; j < n; j++) {\n            //# for (int i = 0; i < 2; i++) {\n            //# for (int k = 0; k < j; k++) {\n            matrix.C__j__ -= (Vec.Dot(matrix.C__k__, matrix.C__j__) / Vec.Dot(matrix.C__k__, matrix.C__k__)) * matrix.C__k__;\n            //# }\n            //# }\n            //# }\n        }\n\n        /// <summary>\n        /// Orthogonalizes the columns of the given <see cref=\"__nmtype__\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Orthogonalized(this __nmtype__ matrix)\n        {\n            __nmtype__ m = matrix;\n            Orthogonalize(ref m);\n            return m;\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"__nmtype__\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        public static void Orthonormalize(this ref __nmtype__ matrix)\n        {\n            matrix.C0 = matrix.C0.Normalized;\n            //# for (int j = 1; j < n; j++) {\n            //# for (int i = 0; i < 2; i++) {\n            //# for (int k = 0; k < j; k++) {\n            matrix.C__j__ -= (Vec.Dot(matrix.C__k__, matrix.C__j__) / Vec.Dot(matrix.C__k__, matrix.C__k__)) * matrix.C__k__;\n            //# }\n            //# }\n            matrix.C__j__ = matrix.C__j__.Normalized;\n            //# }\n        }\n\n        /// <summary>\n        /// Orthonormalizes the columns of the given <see cref=\"__nmtype__\"/> using the (modified) Gram-Schmidt algorithm with\n        /// an additional reorthogonalization step.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Orthonormalized(this __nmtype__ matrix)\n        {\n            __nmtype__ m = matrix;\n            Orthonormalize(ref m);\n            return m;\n        }\n\n        #endregion\n        //# }\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any element of the given <see cref=\"__nmtype__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this __nmtype__ m, __ftype__ epsilon)\n            => /*# n.ForEach(r => { m.ForEach(s => {*/m.M__r____s__.IsTiny(epsilon)/*# }, oror); }, oror);*/;\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"__nmtype__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this __nmtype__ m, __ftype__ epsilon)\n            => /*# n.ForEach(r => { m.ForEach(s => {*/m.M__r____s__.IsTiny(epsilon)/*# }, andand); }, andand);*/;\n\n        #endregion\n        //# if (isReal) {\n\n        #region Special Floating Point Value Checks\n\n        //# var condArray = new[] { \"Finite\", \"NaN\", \"Infinity\", \"PositiveInfinity\", \"NegativeInfinity\", \"Tiny\" };\n        //# var quantArray = new[] { \"Any\", \"All\" };\n        //# condArray.ForEach(cond => {\n        //# quantArray.ForEach(qant => {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool __qant____cond__(__nmtype__ m)\n            => m.__qant____cond__;\n\n        //# }); // quantArray\n        //# }); // condArray\n        #endregion\n        //# } // isReal\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        //# if (isReal) {\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __nmtype__ a, __nmtype__ b)\n            => ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n\n        //# }\n        /// <summary>\n        /// Returns if all entries in the matrix a are approximately equal to the respective entries in matrix b.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __nmtype__ a, __nmtype__ b, __ftype__ epsilon)\n        {\n            return Mat.DistanceMax(a, b) <= epsilon; //Inefficient implementation, no early exit of comparisons.\n        }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"__nmtype__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this __nmtype__ m, __ftype__ epsilon)\n            => Mat.AllTiny(m, epsilon);\n\n        //# if (isReal) {\n        /// <summary>\n        /// Returns whether the absolute value of each element of the given <see cref=\"__nmtype__\"/> is smaller than Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(__nmtype__ m)\n            => m.IsTiny;\n\n        //# }\n        #endregion\n        //# if (isReal) {\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"__nmtype__\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(__nmtype__ v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"__nmtype__\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(__nmtype__ v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"__nmtype__\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(__nmtype__ v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any element of the given <see cref=\"__nmtype__\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(__nmtype__ v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all elements of the given <see cref=\"__nmtype__\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(__nmtype__ v)\n            => v.IsFinite;\n\n        #endregion\n        //# }\n    }\n\n    public static class IRandomUniform__nmtype__Extensions\n    {\n        #region IRandomUniform extensions for __nmtype__\n\n        //# string[] variants;\n        //# if (t == 2) {\n        //#     variants = new string[] { \"\", \"Closed\", \"Open\" };\n        //# } else if (t == 3) {\n        //#     variants = new string[] { \"\", \"Closed\", \"Open\", \"Full\", \"FullClosed\", \"FullOpen\" };\n        //# } else {\n        //#     variants = new string[] { \"\", \"NonZero\" };\n        //# }\n        //# foreach (var v in variants) {\n        /// <summary>\n        /// Uses Uniform__fcaps____v__() to generate the elements of an __nmtype__ matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Uniform__nmtype____v__(this IRandomUniform rnd)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(c => { var rf = fields[r]; */rnd.Uniform__fcaps____v__()/*#}, comma);}, comma); */);\n        }\n\n        //# }\n        //# if (!isReal) {\n        /// <summary>\n        /// Uses Uniform__fcaps__(__ftype__) to generate the elements of an __nmtype__ matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Uniform__nmtype__(this IRandomUniform rnd, __ftype__ size)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(c => { var rf = fields[r]; */rnd.Uniform__fcaps__(size)/*#}, comma);}, comma); */);\n        }\n\n        /// <summary>\n        /// Uses Uniform__fcaps__(__ftype__) to generate the elements of an __nmtype__ matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __nmtype__ Uniform__nmtype__(this IRandomUniform rnd, __nmtype__ size)\n        {\n            return new __nmtype__(/*# n.ForEach(r => { */\n                /*# m.ForEach(c => { var rf = fields[r]; */rnd.Uniform__fcaps__(size.M__r____c__)/*#}, comma);}, comma); */);\n        }\n\n        //# }\n        #endregion\n    }\n\n    #endregion\n\n    //# } // t\n    //# } // m\n    //# } // n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Rot2_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    #region Rot2f\n\n    /// <summary>\n    /// Represents a 2D rotation counterclockwise around the origin.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Rot2f : IEquatable<Rot2f>\n    {\n        [DataMember]\n        public float Angle;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot2f\"/> transformation given a rotation angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot2f(float angleInRadians)\n        {\n            Angle = angleInRadians;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot2f(Rot2f r)\n        {\n            Angle = r.Angle;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot2f\"/> transformation from a <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot2f(Rot2d r)\n        {\n            Angle = (float)r.Angle;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        public static Rot2f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Rot2f(0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Rot2f\"/> tranformation.\n        /// </summary>\n        public readonly Rot2f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Rot2f(-Angle);\n        }\n\n        #endregion\n\n        #region Arithmetic operators\n\n        /// <summary>\n        /// Multiplies two <see cref=\"Rot2f\"/> transformations.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f operator *(Rot2f r0, Rot2f r1)\n        {\n            return new Rot2f(r0.Angle + r1.Angle);\n        }\n\n        #region Rot / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> transformation with a <see cref=\"V2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(Rot2f rot, V2f vec)\n        {\n            float a = Fun.Cos(rot.Angle);\n            float b = Fun.Sin(rot.Angle);\n\n            return new V2f(a * vec.X + -b * vec.Y, b * vec.X + a * vec.Y);\n        }\n\n        #endregion\n\n        #region Rot / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> transformation (as a 2x2 matrix) with a <see cref=\"M22f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator *(Rot2f r, M22f m)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M22f(\n                a * m.M00 + -b * m.M10, \n                a * m.M01 + -b * m.M11,\n\n                b * m.M00 + a * m.M10, \n                b * m.M01 + a * m.M11);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22f\"/> with a <see cref=\"Rot2f\"/> transformation (as a 2x2 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator *(M22f m, Rot2f r)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M22f(\n                m.M00 * a + m.M01 * b, \n                m.M00 * -b + m.M01 * a,\n\n                m.M10 * a + m.M11 * b, \n                m.M10 * -b + m.M11 * a);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> transformation (as a 2x2 matrix) with a <see cref=\"M23f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Rot2f r, M23f m)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M23f(\n                a * m.M00 + -b * m.M10, \n                a * m.M01 + -b * m.M11, \n                a * m.M02 + -b * m.M12,\n\n                b * m.M00 + a * m.M10, \n                b * m.M01 + a * m.M11, \n                b * m.M02 + a * m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23f\"/> with a <see cref=\"Rot2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M23f m, Rot2f r)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M23f(\n                m.M00 * a + m.M01 * b, \n                m.M00 * -b + m.M01 * a,\n                m.M02,\n\n                m.M10 * a + m.M11 * b, \n                m.M10 * -b + m.M11 * a,\n                m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(Rot2f r, M33f m)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M33f(\n                a * m.M00 + -b * m.M10, \n                a * m.M01 + -b * m.M11, \n                a * m.M02 + -b * m.M12,\n\n                b * m.M00 + a * m.M10, \n                b * m.M01 + a * m.M11, \n                b * m.M02 + a * m.M12,\n                \n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> with a <see cref=\"Rot2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(M33f m, Rot2f r)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M33f(\n                m.M00 * a + m.M01 * b, \n                m.M00 * -b + m.M01 * a,\n                m.M02,\n\n                m.M10 * a + m.M11 * b, \n                m.M10 * -b + m.M11 * a,\n                m.M12,\n\n                m.M20 * a + m.M21 * b, \n                m.M20 * -b + m.M21 * a,\n                m.M22);\n        }\n\n        #endregion\n\n        #region Rot / Shift, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> transformation with a <see cref=\"Shift2f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f operator *(Rot2f a, Shift2f b)\n            => new Euclidean2f(a, a * b.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> transformation with a <see cref=\"Scale2f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Rot2f a, Scale2f b)\n            => new Affine2f((M22f)a * (M22f)b);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks if 2 rotations are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Rot2f rotation1, Rot2f rotation2)\n            => Rot.Distance(rotation1, rotation2) == 0;\n\n        /// <summary>\n        /// Checks if 2 rotations are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Rot2f rotation1, Rot2f rotation2)\n            => Rot.Distance(rotation1, rotation2) != 0;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2f\"/> transformation from a <see cref=\"M22f\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f FromM22f(M22f m)\n        {\n            return new Rot2f(m.GetRotation());\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2f\"/> transformation from a <see cref=\"M33f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f FromM33f(M33f m, float epsilon = 1e-5f)\n        {\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C2.XY.ApproximateEquals(V2f.Zero, epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM22f(((M22f)m) / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2f\"/> transformation from a <see cref=\"Euclidean2f\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f FromEuclidean2f(Euclidean2f euclidean, float epsilon = 1e-5f)\n        {\n            if (!euclidean.Trans.ApproximateEquals(V2f.Zero, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains translational component\");\n\n            return euclidean.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2f\"/> transformation from a <see cref=\"Similarity2f\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f FromSimilarity2f(Similarity2f similarity, float epsilon = 1e-5f)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Trans.ApproximateEquals(V2f.Zero, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            return similarity.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2f\"/> transformation from an <see cref=\"Affine2f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f FromAffine2f(Affine2f affine, float epsilon = 1e-5f)\n            => FromM33f((M33f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2f\"/> transformation from a <see cref=\"Trafo2f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f FromTrafo2f(Trafo2f trafo, float epsilon = 1e-5f)\n            => FromM33f(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2f\"/> transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f FromRadians(float angleInRadians)\n            => new Rot2f(angleInRadians);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2f\"/> transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f FromDegrees(float angleInDegrees)\n            => new Rot2f(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Conversion Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22f(Rot2f r)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M22f(\n                 a, -b, \n                 b,  a);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23f(Rot2f r)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M23f(\n                 a, -b,  0, \n                 b,  a,  0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Rot2f r)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M33f(\n                 a, -b,  0, \n                 b,  a,  0, \n                 0,  0,  1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Rot2f r)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M34f(\n                 a, -b,  0,  0, \n                 b,  a,  0,  0, \n                 0,  0,  1,  0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Rot2f r)\n        {\n            float a = Fun.Cos(r.Angle);\n            float b = Fun.Sin(r.Angle);\n\n            return new M44f(\n                 a, -b,  0,  0, \n                 b,  a,  0,  0, \n                 0,  0,  1,  0, \n                 0,  0,  0,  1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean2f(Rot2f r)\n            => new Euclidean2f(r, V2f.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity2f(Rot2f r)\n            => new Similarity2f(1, r, V2f.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2f(Rot2f r)\n            => new Affine2f((M22f)r);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2f(Rot2f r)\n            => new Trafo2f((M33f)r, (M33f)r.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Rot2d(Rot2f r)\n            => new Rot2d((double)r.Angle);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return Angle.GetHashCode();\n        }\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}]\", Angle);\n        }\n\n        public static Rot2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Rot2f(\n                float.Parse(x[0], CultureInfo.InvariantCulture)\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Rot2f other)\n            => Rot.Distance(this, other) == 0;\n\n        public override readonly bool Equals(object other)\n            => (other is Rot2f o) ? Equals(o) : false;\n\n        #endregion\n    }\n\n    public static partial class Rot\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2f Inverse(Rot2f rot)\n            => rot.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Rot2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Rot2f rot)\n        {\n            rot.Angle = -rot.Angle;\n        }\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"Rot2f\"/> rotations.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(this Rot2f r1, Rot2f r2)\n            => Fun.AngleDistance(r1.Angle, r2.Angle);\n\n        /// <summary>\n        /// Returns the signed difference in radians between two <see cref=\"Rot2f\"/> rotations.\n        /// The result is within the range of [-Pi, Pi).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Difference(this Rot2f r1, Rot2f r2)\n            => Fun.AngleDifference(r1.Angle, r2.Angle);\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> vector by a <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Transform(this Rot2f rot, V2f v)\n        {\n            return rot * v;\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Rot2f\"/> transformation.\n        /// The z coordinate of the vector is unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Rot2f rot, V3f v)\n        {\n            float a = Fun.Cos(rot.Angle);\n            float b = Fun.Sin(rot.Angle);\n\n            return new V3f(a * v.X + -b * v.Y,\n                        b * v.X + a * v.Y,\n                        v.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by a <see cref=\"Rot2f\"/> transformation.\n        /// The z and w coordinates of the vector are unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Rot2f rot, V4f v)\n        {\n            float a = Fun.Cos(rot.Angle);\n            float b = Fun.Sin(rot.Angle);\n\n            return new V4f(a * v.X + -b * v.Y,\n                        b * v.X + a * v.Y,\n                        v.Z, v.W);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> vector by the inverse of a <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransform(this Rot2f rot, V2f v)\n        {\n            float a = Fun.Cos(-rot.Angle);\n            float b = Fun.Sin(-rot.Angle);\n\n            return new V2f(a * v.X + -b * v.Y, b * v.X + a * v.Y);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by the inverse of a <see cref=\"Rot2f\"/> transformation.\n        /// The z coordinate of the vector is unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransform(this Rot2f rot, V3f v)\n            => Transform(rot.Inverse, v);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by the inverse of a <see cref=\"Rot2f\"/> transformation.\n        /// The z and w coordinates of the vector are unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f InvTransform(this Rot2f rot, V4f v)\n            => Transform(rot.Inverse, v);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Rot2f r0, Rot2f r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Rot2f r0, Rot2f r1, float tolerance)\n        {\n            return Rot.Distance(r0, r1) <= tolerance;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Rot2d\n\n    /// <summary>\n    /// Represents a 2D rotation counterclockwise around the origin.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Rot2d : IEquatable<Rot2d>\n    {\n        [DataMember]\n        public double Angle;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot2d\"/> transformation given a rotation angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot2d(double angleInRadians)\n        {\n            Angle = angleInRadians;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot2d(Rot2d r)\n        {\n            Angle = r.Angle;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot2d\"/> transformation from a <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot2d(Rot2f r)\n        {\n            Angle = (double)r.Angle;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        public static Rot2d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Rot2d(0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Rot2d\"/> tranformation.\n        /// </summary>\n        public readonly Rot2d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Rot2d(-Angle);\n        }\n\n        #endregion\n\n        #region Arithmetic operators\n\n        /// <summary>\n        /// Multiplies two <see cref=\"Rot2d\"/> transformations.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d operator *(Rot2d r0, Rot2d r1)\n        {\n            return new Rot2d(r0.Angle + r1.Angle);\n        }\n\n        #region Rot / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> transformation with a <see cref=\"V2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(Rot2d rot, V2d vec)\n        {\n            double a = Fun.Cos(rot.Angle);\n            double b = Fun.Sin(rot.Angle);\n\n            return new V2d(a * vec.X + -b * vec.Y, b * vec.X + a * vec.Y);\n        }\n\n        #endregion\n\n        #region Rot / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> transformation (as a 2x2 matrix) with a <see cref=\"M22d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator *(Rot2d r, M22d m)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M22d(\n                a * m.M00 + -b * m.M10, \n                a * m.M01 + -b * m.M11,\n\n                b * m.M00 + a * m.M10, \n                b * m.M01 + a * m.M11);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22d\"/> with a <see cref=\"Rot2d\"/> transformation (as a 2x2 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator *(M22d m, Rot2d r)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M22d(\n                m.M00 * a + m.M01 * b, \n                m.M00 * -b + m.M01 * a,\n\n                m.M10 * a + m.M11 * b, \n                m.M10 * -b + m.M11 * a);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> transformation (as a 2x2 matrix) with a <see cref=\"M23d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Rot2d r, M23d m)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M23d(\n                a * m.M00 + -b * m.M10, \n                a * m.M01 + -b * m.M11, \n                a * m.M02 + -b * m.M12,\n\n                b * m.M00 + a * m.M10, \n                b * m.M01 + a * m.M11, \n                b * m.M02 + a * m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23d\"/> with a <see cref=\"Rot2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M23d m, Rot2d r)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M23d(\n                m.M00 * a + m.M01 * b, \n                m.M00 * -b + m.M01 * a,\n                m.M02,\n\n                m.M10 * a + m.M11 * b, \n                m.M10 * -b + m.M11 * a,\n                m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(Rot2d r, M33d m)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M33d(\n                a * m.M00 + -b * m.M10, \n                a * m.M01 + -b * m.M11, \n                a * m.M02 + -b * m.M12,\n\n                b * m.M00 + a * m.M10, \n                b * m.M01 + a * m.M11, \n                b * m.M02 + a * m.M12,\n                \n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> with a <see cref=\"Rot2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(M33d m, Rot2d r)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M33d(\n                m.M00 * a + m.M01 * b, \n                m.M00 * -b + m.M01 * a,\n                m.M02,\n\n                m.M10 * a + m.M11 * b, \n                m.M10 * -b + m.M11 * a,\n                m.M12,\n\n                m.M20 * a + m.M21 * b, \n                m.M20 * -b + m.M21 * a,\n                m.M22);\n        }\n\n        #endregion\n\n        #region Rot / Shift, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> transformation with a <see cref=\"Shift2d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d operator *(Rot2d a, Shift2d b)\n            => new Euclidean2d(a, a * b.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> transformation with a <see cref=\"Scale2d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Rot2d a, Scale2d b)\n            => new Affine2d((M22d)a * (M22d)b);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks if 2 rotations are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Rot2d rotation1, Rot2d rotation2)\n            => Rot.Distance(rotation1, rotation2) == 0;\n\n        /// <summary>\n        /// Checks if 2 rotations are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Rot2d rotation1, Rot2d rotation2)\n            => Rot.Distance(rotation1, rotation2) != 0;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2d\"/> transformation from a <see cref=\"M22d\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d FromM22d(M22d m)\n        {\n            return new Rot2d(m.GetRotation());\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2d\"/> transformation from a <see cref=\"M33d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d FromM33d(M33d m, double epsilon = 1e-12)\n        {\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C2.XY.ApproximateEquals(V2d.Zero, epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM22d(((M22d)m) / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2d\"/> transformation from a <see cref=\"Euclidean2d\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d FromEuclidean2d(Euclidean2d euclidean, double epsilon = 1e-12)\n        {\n            if (!euclidean.Trans.ApproximateEquals(V2d.Zero, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains translational component\");\n\n            return euclidean.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2d\"/> transformation from a <see cref=\"Similarity2d\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d FromSimilarity2d(Similarity2d similarity, double epsilon = 1e-12)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Trans.ApproximateEquals(V2d.Zero, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            return similarity.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2d\"/> transformation from an <see cref=\"Affine2d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d FromAffine2d(Affine2d affine, double epsilon = 1e-12)\n            => FromM33d((M33d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2d\"/> transformation from a <see cref=\"Trafo2d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d FromTrafo2d(Trafo2d trafo, double epsilon = 1e-12)\n            => FromM33d(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2d\"/> transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d FromRadians(double angleInRadians)\n            => new Rot2d(angleInRadians);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot2d\"/> transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d FromDegrees(double angleInDegrees)\n            => new Rot2d(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Conversion Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22d(Rot2d r)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M22d(\n                 a, -b, \n                 b,  a);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23d(Rot2d r)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M23d(\n                 a, -b,  0, \n                 b,  a,  0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Rot2d r)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M33d(\n                 a, -b,  0, \n                 b,  a,  0, \n                 0,  0,  1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Rot2d r)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M34d(\n                 a, -b,  0,  0, \n                 b,  a,  0,  0, \n                 0,  0,  1,  0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Rot2d r)\n        {\n            double a = Fun.Cos(r.Angle);\n            double b = Fun.Sin(r.Angle);\n\n            return new M44d(\n                 a, -b,  0,  0, \n                 b,  a,  0,  0, \n                 0,  0,  1,  0, \n                 0,  0,  0,  1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean2d(Rot2d r)\n            => new Euclidean2d(r, V2d.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity2d(Rot2d r)\n            => new Similarity2d(1, r, V2d.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2d(Rot2d r)\n            => new Affine2d((M22d)r);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2d(Rot2d r)\n            => new Trafo2d((M33d)r, (M33d)r.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Rot2f(Rot2d r)\n            => new Rot2f((float)r.Angle);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return Angle.GetHashCode();\n        }\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}]\", Angle);\n        }\n\n        public static Rot2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Rot2d(\n                double.Parse(x[0], CultureInfo.InvariantCulture)\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Rot2d other)\n            => Rot.Distance(this, other) == 0;\n\n        public override readonly bool Equals(object other)\n            => (other is Rot2d o) ? Equals(o) : false;\n\n        #endregion\n    }\n\n    public static partial class Rot\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot2d Inverse(Rot2d rot)\n            => rot.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Rot2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Rot2d rot)\n        {\n            rot.Angle = -rot.Angle;\n        }\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"Rot2d\"/> rotations.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this Rot2d r1, Rot2d r2)\n            => Fun.AngleDistance(r1.Angle, r2.Angle);\n\n        /// <summary>\n        /// Returns the signed difference in radians between two <see cref=\"Rot2d\"/> rotations.\n        /// The result is within the range of [-Pi, Pi).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Difference(this Rot2d r1, Rot2d r2)\n            => Fun.AngleDifference(r1.Angle, r2.Angle);\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> vector by a <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Transform(this Rot2d rot, V2d v)\n        {\n            return rot * v;\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Rot2d\"/> transformation.\n        /// The z coordinate of the vector is unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Rot2d rot, V3d v)\n        {\n            double a = Fun.Cos(rot.Angle);\n            double b = Fun.Sin(rot.Angle);\n\n            return new V3d(a * v.X + -b * v.Y,\n                        b * v.X + a * v.Y,\n                        v.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by a <see cref=\"Rot2d\"/> transformation.\n        /// The z and w coordinates of the vector are unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Rot2d rot, V4d v)\n        {\n            double a = Fun.Cos(rot.Angle);\n            double b = Fun.Sin(rot.Angle);\n\n            return new V4d(a * v.X + -b * v.Y,\n                        b * v.X + a * v.Y,\n                        v.Z, v.W);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> vector by the inverse of a <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransform(this Rot2d rot, V2d v)\n        {\n            double a = Fun.Cos(-rot.Angle);\n            double b = Fun.Sin(-rot.Angle);\n\n            return new V2d(a * v.X + -b * v.Y, b * v.X + a * v.Y);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by the inverse of a <see cref=\"Rot2d\"/> transformation.\n        /// The z coordinate of the vector is unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransform(this Rot2d rot, V3d v)\n            => Transform(rot.Inverse, v);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by the inverse of a <see cref=\"Rot2d\"/> transformation.\n        /// The z and w coordinates of the vector are unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvTransform(this Rot2d rot, V4d v)\n            => Transform(rot.Inverse, v);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Rot2d r0, Rot2d r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Rot2d r0, Rot2d r1, double tolerance)\n        {\n            return Rot.Distance(r0, r1) <= tolerance;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Rot2_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action and = () => Out(\" && \");\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var v2t = \"V2\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var v4t = \"V4\" + tc;\n    //#   var type = \"Rot2\" + tc;\n    //#   var type2 = \"Rot2\" + tc2;\n    //#   var rot3t = \"Rot3\" + tc;\n    //#   var scale2t = \"Scale2\" + tc;\n    //#   var shift2t = \"Shift2\" + tc;\n    //#   var affine2t = \"Affine2\" + tc;\n    //#   var similarity2t = \"Similarity2\" + tc;\n    //#   var euclidean2t = \"Euclidean2\" + tc;\n    //#   var trafo2t = \"Trafo2\" + tc;\n    //#   var m22t = \"M22\" + tc;\n    //#   var m23t = \"M23\" + tc;\n    //#   var m33t = \"M33\" + tc;\n    //#   var m34t = \"M34\" + tc;\n    //#   var m44t = \"M44\" + tc;\n    //#   var eps = isDouble ? \"1e-12\" : \"1e-5f\";\n    #region __type__\n\n    /// <summary>\n    /// Represents a 2D rotation counterclockwise around the origin.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>\n    {\n        [DataMember]\n        public __ftype__ Angle;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation given a rotation angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ angleInRadians)\n        {\n            Angle = angleInRadians;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ r)\n        {\n            Angle = r.Angle;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a <see cref=\"__type2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ r)\n        {\n            Angle = (__ftype__)r.Angle;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(0);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"__type__\"/> tranformation.\n        /// </summary>\n        public readonly __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(-Angle);\n        }\n\n        #endregion\n\n        #region Arithmetic operators\n\n        /// <summary>\n        /// Multiplies two <see cref=\"__type__\"/> transformations.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ r0, __type__ r1)\n        {\n            return new __type__(r0.Angle + r1.Angle);\n        }\n\n        #region Rot / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__v2t__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ operator *(__type__ rot, __v2t__ vec)\n        {\n            __ftype__ a = Fun.Cos(rot.Angle);\n            __ftype__ b = Fun.Sin(rot.Angle);\n\n            return new __v2t__(a * vec.X + -b * vec.Y, b * vec.X + a * vec.Y);\n        }\n\n        #endregion\n\n        #region Rot / Matrix Multiplication\n\n        //# for (int n = 2; n <= 3; n++) {\n        //# for (int m = n; m <= (n+1) && m <= 3; m++) {\n        //#     var mat = \"M\" + n + m + tc;\n        //#     var nsub2 = n - 2;\n        //#     var msub2 = m - 2;\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __n__x__n__ matrix) with a <see cref=\"__mat__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mat__ operator *(__type__ r, __mat__ m)\n        {\n            __ftype__ a = Fun.Cos(r.Angle);\n            __ftype__ b = Fun.Sin(r.Angle);\n\n            return new __mat__(/*# 2.ForEach(i => { m.ForEach(j => { */\n                //# var x = (i == 0) ? \"a\" : \"b\";\n                //# var y = (i == 0) ? \"-b\" :  \"a\";\n                __x__ * m.M0__j__ + __y__ * m.M1__j__/*# }, comma); }, commaln); if (nsub2 > 0) {*/,\n                /*# nsub2.ForEach(i => { var ip2 = i + 2; */\n                /*# m.ForEach(j => { */m.M__ip2____j__/*# }, comma); }, comma); }*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mat__\"/> with a <see cref=\"__type__\"/> transformation (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mat__ operator *(__mat__ m, __type__ r)\n        {\n            __ftype__ a = Fun.Cos(r.Angle);\n            __ftype__ b = Fun.Sin(r.Angle);\n\n            return new __mat__(/*# n.ForEach(i => { 2.ForEach(j => { */\n                //# var x = (j == 0) ? \"a\" : \"-b\";\n                //# var y = (j == 0) ? \"b\" :  \"a\";\n                m.M__i__0 * __x__ + m.M__i__1 * __y__/*# }, comma); if (msub2 > 0) {*/,\n                /*# msub2.ForEach(jj => { var jjp2 = jj + 2; */m.M__i____jjp2__/*# }, comma); } }, commaln);*/);\n        }\n\n        //# } }\n        #endregion\n\n        #region Rot / Shift, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__shift2t__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __euclidean2t__ operator *(__type__ a, __shift2t__ b)\n            => new __euclidean2t__(a, a * b.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__scale2t__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affine2t__ operator *(__type__ a, __scale2t__ b)\n            => new __affine2t__((__m22t__)a * (__m22t__)b);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks if 2 rotations are equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ rotation1, __type__ rotation2)\n            => Rot.Distance(rotation1, rotation2) == 0;\n\n        /// <summary>\n        /// Checks if 2 rotations are not equal.\n        /// </summary>\n        /// <returns>Result of comparison.</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ rotation1, __type__ rotation2)\n            => Rot.Distance(rotation1, rotation2) != 0;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__m22t__\"/> matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__m22t__(__m22t__ m)\n        {\n            return new __type__(m.GetRotation());\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__m33t__\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__m33t__(__m33t__ m, __ftype__ epsilon = __eps__)\n        {\n            if (!(/*#2.ForEach(j => {*/m.M2__j__.IsTiny(epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C2.XY.ApproximateEquals(__v2t__.Zero, epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return From__m22t__(((__m22t__)m) / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__euclidean2t__\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__euclidean2t__(__euclidean2t__ euclidean, __ftype__ epsilon = __eps__)\n        {\n            if (!euclidean.Trans.ApproximateEquals(__v2t__.Zero, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains translational component\");\n\n            return euclidean.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__similarity2t__\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__similarity2t__(__similarity2t__ similarity, __ftype__ epsilon = __eps__)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Trans.ApproximateEquals(__v2t__.Zero, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            return similarity.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from an <see cref=\"__affine2t__\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__affine2t__(__affine2t__ affine, __ftype__ epsilon = __eps__)\n            => From__m33t__((__m33t__)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__trafo2t__\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__trafo2t__(__trafo2t__ trafo, __ftype__ epsilon = __eps__)\n            => From__m33t__(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromRadians(__ftype__ angleInRadians)\n            => new __type__(angleInRadians);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromDegrees(__ftype__ angleInDegrees)\n            => new __type__(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #region Conversion Operators\n\n        //# for (int n = 2; n <= 4; n++) {\n        //# for (int m = n; m <= (n+1) && m <= 4; m++) {\n        //#     var mat = \"M\" + n + m + tc;\n        //#     string[,] val = new string[,] {{\" a\", \"-b\"}, {\" b\", \" a\"}};\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mat__(__type__ r)\n        {\n            __ftype__ a = Fun.Cos(r.Angle);\n            __ftype__ b = Fun.Sin(r.Angle);\n\n            return new __mat__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var x = (i < 2 && j < 2) ? val[i, j] : ((i == j) ? \" 1\" : \" 0\");\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        //# } }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __euclidean2t__(__type__ r)\n            => new __euclidean2t__(r, __v2t__.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __similarity2t__(__type__ r)\n            => new __similarity2t__(1, r, __v2t__.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __affine2t__(__type__ r)\n            => new __affine2t__((__m22t__)r);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __trafo2t__(__type__ r)\n            => new __trafo2t__((__m33t__)r, (__m33t__)r.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ r)\n            => new __type2__((__ftype2__)r.Angle);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return Angle.GetHashCode();\n        }\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}]\", Angle);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(\n                __ftype__.Parse(x[0], CultureInfo.InvariantCulture)\n            );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Rot.Distance(this, other) == 0;\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        #endregion\n    }\n\n    public static partial class Rot\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ rot)\n            => rot.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref __type__ rot)\n        {\n            rot.Angle = -rot.Angle;\n        }\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"__type__\"/> rotations.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Distance(this __type__ r1, __type__ r2)\n            => Fun.AngleDistance(r1.Angle, r2.Angle);\n\n        /// <summary>\n        /// Returns the signed difference in radians between two <see cref=\"__type__\"/> rotations.\n        /// The result is within the range of [-Pi, Pi).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Difference(this __type__ r1, __type__ r2)\n            => Fun.AngleDifference(r1.Angle, r2.Angle);\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v2t__\"/> vector by a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ Transform(this __type__ rot, __v2t__ v)\n        {\n            return rot * v;\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v3t__\"/> vector by a <see cref=\"__type__\"/> transformation.\n        /// The z coordinate of the vector is unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ Transform(this __type__ rot, __v3t__ v)\n        {\n            __ftype__ a = Fun.Cos(rot.Angle);\n            __ftype__ b = Fun.Sin(rot.Angle);\n\n            return new __v3t__(a * v.X + -b * v.Y,\n                        b * v.X + a * v.Y,\n                        v.Z);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v4t__\"/> vector by a <see cref=\"__type__\"/> transformation.\n        /// The z and w coordinates of the vector are unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v4t__ Transform(this __type__ rot, __v4t__ v)\n        {\n            __ftype__ a = Fun.Cos(rot.Angle);\n            __ftype__ b = Fun.Sin(rot.Angle);\n\n            return new __v4t__(a * v.X + -b * v.Y,\n                        b * v.X + a * v.Y,\n                        v.Z, v.W);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v2t__\"/> vector by the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v2t__ InvTransform(this __type__ rot, __v2t__ v)\n        {\n            __ftype__ a = Fun.Cos(-rot.Angle);\n            __ftype__ b = Fun.Sin(-rot.Angle);\n\n            return new __v2t__(a * v.X + -b * v.Y, b * v.X + a * v.Y);\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v3t__\"/> vector by the inverse of a <see cref=\"__type__\"/> transformation.\n        /// The z coordinate of the vector is unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ InvTransform(this __type__ rot, __v3t__ v)\n            => Transform(rot.Inverse, v);\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v4t__\"/> vector by the inverse of a <see cref=\"__type__\"/> transformation.\n        /// The z and w coordinates of the vector are unaffected.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v4t__ InvTransform(this __type__ rot, __v4t__ v)\n            => Transform(rot.Inverse, v);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ r0, __type__ r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ r0, __type__ r1, __ftype__ tolerance)\n        {\n            return Rot.Distance(r0, r1) <= tolerance;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Rot3_auto.cs",
    "content": "using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    #region Rot3f\n\n    /// <summary>\n    /// Represents a rotation in three dimensions using a unit quaternion.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Rot3f : IEquatable<Rot3f>\n    {\n        /// <summary>\n        /// Scalar (real) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public float W;\n\n        /// <summary>\n        /// First component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public float X;\n\n        /// <summary>\n        /// Second component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public float Y;\n\n        /// <summary>\n        /// Third component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public float Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3f\"/> transformation from the quaternion (w, (x, y, z)).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3f(float w, float x, float y, float z)\n        {\n            W = w;\n            X = x; Y = y; Z = z;\n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3f\"/> transformation from the quaternion (w, (v.x, v.y, v.z)).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3f(float w, V3f v)\n        {\n            W = w;\n            X = v.X; Y = v.Y; Z = v.Z;\n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3f\"/> transformation from the quaternion <paramref name=\"q\"/>.\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3f(QuaternionF q)\n        {\n            W = q.W; X = q.X; Y = q.Y; Z = q.Z; \n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3f\"/> transformation from the quaternion <paramref name=\"q\"/>.\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3f(QuaternionD q)\n        {\n            W = (float)q.W; X = (float)q.X; Y = (float)q.Y; Z = (float)q.Z; \n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3f(Rot3f r)\n        {\n            W = r.W; X = r.X; Y = r.Y; Z = r.Z; \n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3f\"/> transformation from a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3f(Rot3d r)\n        {\n            W = (float)r.W; X = (float)r.X; Y = (float)r.Y; Z = (float)r.Z; \n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3f\"/> transformation from the quaternion (a[0], (a[1], a[2], a[3])).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3f(float[] a)\n        {\n            W = a[0];\n            X = a[1]; Y = a[2]; Z = a[3];\n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3f\"/> transformation from the quaternion (a[start], (a[start + 1], a[start + 2], a[start + 3])).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3f(float[] a, int start)\n        {\n            W = a[start];\n            X = a[start + 1]; Y = a[start + 2]; Z = a[start + 3];\n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets or sets the vector part (x, y, z) of this <see cref=\"Rot3f\"/> unit quaternion.\n        /// </summary>\n        [XmlIgnore]\n        public V3f V\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3f(X, Y, Z); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n\n        /// <summary>\n        /// Gets the squared norm (or squared length) of this <see cref=\"Rot3f\"/>.\n        /// May not be exactly 1, due to numerical inaccuracy.\n        /// </summary>\n        public readonly float NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => W * W + X * X + Y * Y + Z * Z;\n        }\n\n        /// <summary>\n        /// Gets the norm (or length) of this <see cref=\"Rot3f\"/>.\n        /// May not be exactly 1, due to numerical inaccuracy.\n        /// </summary>\n        public readonly float Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => NormSquared.Sqrt();\n        }\n\n        /// <summary>\n        /// Gets normalized (unit) quaternion from this <see cref=\"Rot3f\"/>\n        /// </summary>\n        public readonly Rot3f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new Rot3f(this);\n                rs.Normalize();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        public readonly Rot3f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-5f));\n                return new Rot3f(W, -X, -Y, -Z);\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Rot3f\"/>.\n        /// </summary>\n        public static Rot3f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Rot3f(1, 0, 0, 0);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Returns the component-wise negation of a <see cref=\"Rot3f\"/> unit quaternion.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f operator -(Rot3f q)\n            => new Rot3f(-q.W, -q.X, -q.Y, -q.Z);\n\n        /// <summary>\n        /// Multiplies two <see cref=\"Rot3f\"/> transformations.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f operator *(Rot3f a, Rot3f b)\n        {\n            return new Rot3f(\n                a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z,\n                a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,\n                a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,\n                a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X);\n        }\n\n        #region Rot / Vector Multiplication\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Rot3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(Rot3f r, V3f v)\n        {\n            var w = -r.X * v.X - r.Y * v.Y - r.Z * v.Z;\n            var x = r.W * v.X + r.Y * v.Z - r.Z * v.Y;\n            var y = r.W * v.Y + r.Z * v.X - r.X * v.Z;\n            var z = r.W * v.Z + r.X * v.Y - r.Y * v.X;\n\n            return new V3f(\n                -w * r.X + x * r.W - y * r.Z + z * r.Y,\n                -w * r.Y + y * r.W - z * r.X + x * r.Z,\n                -w * r.Z + z * r.W - x * r.Y + y * r.X);\n        }\n\n        #endregion\n\n        #region Rot / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(Rot3f rot, M33f m)\n        {\n            return (M33f)rot * m;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> with a <see cref=\"Rot3f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(M33f m, Rot3f rot)\n        {\n            return m * (M33f)rot;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(Rot3f rot, M44f m)\n        {\n            var r = (M33f)rot;\n            return new M44f(\n                r.M00 * m.M00 + r.M01 * m.M10 + r.M02 * m.M20, \n                r.M00 * m.M01 + r.M01 * m.M11 + r.M02 * m.M21, \n                r.M00 * m.M02 + r.M01 * m.M12 + r.M02 * m.M22, \n                r.M00 * m.M03 + r.M01 * m.M13 + r.M02 * m.M23,\n\n                r.M10 * m.M00 + r.M11 * m.M10 + r.M12 * m.M20, \n                r.M10 * m.M01 + r.M11 * m.M11 + r.M12 * m.M21, \n                r.M10 * m.M02 + r.M11 * m.M12 + r.M12 * m.M22, \n                r.M10 * m.M03 + r.M11 * m.M13 + r.M12 * m.M23,\n\n                r.M20 * m.M00 + r.M21 * m.M10 + r.M22 * m.M20, \n                r.M20 * m.M01 + r.M21 * m.M11 + r.M22 * m.M21, \n                r.M20 * m.M02 + r.M21 * m.M12 + r.M22 * m.M22, \n                r.M20 * m.M03 + r.M21 * m.M13 + r.M22 * m.M23,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44f\"/> with a <see cref=\"Rot3f\"/> transformation (as a 4x4 matrix) .\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(M44f m, Rot3f rot)\n        {\n            var r = (M33f)rot;\n            return new M44f(\n                m.M00 * r.M00 + m.M01 * r.M10 + m.M02 * r.M20, \n                m.M00 * r.M01 + m.M01 * r.M11 + m.M02 * r.M21, \n                m.M00 * r.M02 + m.M01 * r.M12 + m.M02 * r.M22,\n                m.M03,\n\n                m.M10 * r.M00 + m.M11 * r.M10 + m.M12 * r.M20, \n                m.M10 * r.M01 + m.M11 * r.M11 + m.M12 * r.M21, \n                m.M10 * r.M02 + m.M11 * r.M12 + m.M12 * r.M22,\n                m.M13,\n\n                m.M20 * r.M00 + m.M21 * r.M10 + m.M22 * r.M20, \n                m.M20 * r.M01 + m.M21 * r.M11 + m.M22 * r.M21, \n                m.M20 * r.M02 + m.M21 * r.M12 + m.M22 * r.M22,\n                m.M23,\n\n                m.M30 * r.M00 + m.M31 * r.M10 + m.M32 * r.M20, \n                m.M30 * r.M01 + m.M31 * r.M11 + m.M32 * r.M21, \n                m.M30 * r.M02 + m.M31 * r.M12 + m.M32 * r.M22,\n                m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M34f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Rot3f rot, M34f m)\n        {\n            return (M33f)rot * m;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34f\"/> with a <see cref=\"Rot3f\"/> transformation (as a 4x4 matrix) .\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M34f m, Rot3f rot)\n        {\n            var r = (M33f)rot;\n            return new M34f(\n                m.M00 * r.M00 + m.M01 * r.M10 + m.M02 * r.M20, \n                m.M00 * r.M01 + m.M01 * r.M11 + m.M02 * r.M21, \n                m.M00 * r.M02 + m.M01 * r.M12 + m.M02 * r.M22,\n                m.M03,\n\n                m.M10 * r.M00 + m.M11 * r.M10 + m.M12 * r.M20, \n                m.M10 * r.M01 + m.M11 * r.M11 + m.M12 * r.M21, \n                m.M10 * r.M02 + m.M11 * r.M12 + m.M12 * r.M22,\n                m.M13,\n\n                m.M20 * r.M00 + m.M21 * r.M10 + m.M22 * r.M20, \n                m.M20 * r.M01 + m.M21 * r.M11 + m.M22 * r.M21, \n                m.M20 * r.M02 + m.M21 * r.M12 + m.M22 * r.M22,\n                m.M23);\n        }\n\n        #endregion\n\n        #region Rot / Quaternion arithmetics\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"Rot3f\"/> and a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator +(Rot3f r, QuaternionF q)\n            => new QuaternionF(r.W + q.W, r.X + q.X, r.Y + q.Y, r.Z + q.Z);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"QuaternionF\"/> and a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator +(QuaternionF q, Rot3f r)\n            => new QuaternionF(q.W + r.W, q.X + r.X, q.Y + r.Y, q.Z + r.Z);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"Rot3f\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator +(Rot3f r, float s)\n            => new QuaternionF(r.W + s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the sum of a real scalar and a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator +(float s, Rot3f r)\n            => new QuaternionF(r.W + s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"Rot3f\"/> and a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator -(Rot3f r, QuaternionF q)\n            => new QuaternionF(r.W - q.W, r.X - q.X, r.Y - q.Y, r.Z - q.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"QuaternionF\"/> and a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator -(QuaternionF q, Rot3f r)\n            => new QuaternionF(q.W - r.W, q.X - r.X, q.Y - r.Y, q.Z - r.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"Rot3f\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator -(Rot3f r, float s)\n            => new QuaternionF(r.W - s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the difference between a real scalar and a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator -(float s, Rot3f r)\n            => new QuaternionF(s - r.W, -r.X, -r.Y, -r.Z);\n\n        /// <summary>\n        /// Returns the product of a <see cref=\"Rot3f\"/> and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator *(Rot3f r, float s)\n            => new QuaternionF(r.W * s, r.X * s, r.Y * s, r.Z * s);\n\n        /// <summary>\n        /// Returns the product of a scalar and a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator *(float s, Rot3f r)\n            => new QuaternionF(r.W * s, r.X * s, r.Y * s, r.Z * s);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> with a <see cref=\"QuaternionF\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator *(Rot3f r, QuaternionF q)\n        {\n            return new QuaternionF(\n                r.W * q.W - r.X * q.X - r.Y * q.Y - r.Z * q.Z,\n                r.W * q.X + r.X * q.W + r.Y * q.Z - r.Z * q.Y,\n                r.W * q.Y + r.Y * q.W + r.Z * q.X - r.X * q.Z,\n                r.W * q.Z + r.Z * q.W + r.X * q.Y - r.Y * q.X);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"QuaternionF\"/> with a <see cref=\"Rot3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator *(QuaternionF q, Rot3f r)\n        {\n            return new QuaternionF(\n                q.W * r.W - q.X * r.X - q.Y * r.Y - q.Z * r.Z,\n                q.W * r.X + q.X * r.W + q.Y * r.Z - q.Z * r.Y,\n                q.W * r.Y + q.Y * r.W + q.Z * r.X - q.X * r.Z,\n                q.W * r.Z + q.Z * r.W + q.X * r.Y - q.Y * r.X);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Rot3f\"/> by a <see cref=\"QuaternionF\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator /(Rot3f r, QuaternionF q)\n            => r * q.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"QuaternionF\"/> by a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator /(QuaternionF q, Rot3f r)\n            => q * r.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"Rot3f\"/> by a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator /(Rot3f r, float s)\n            => new QuaternionF(r.W / s, r.X / s, r.Y / s, r.Z / s);\n\n        /// <summary>\n        /// Divides a scalar by a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionF operator /(float s, Rot3f r)\n            => new QuaternionF(s / r.W, s / r.X, s / r.Y, s / r.Z);\n\n        #endregion\n\n        #region Rot / Shift, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> transformation with a <see cref=\"Shift3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f operator *(Rot3f a, Shift3f b)\n            => new Euclidean3f(a, a * b.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> transformation with a <see cref=\"Scale3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Rot3f a, Scale3f b)\n            => new Affine3f((M33f)a * (M33f)b);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Rot3f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Rot3f r0, Rot3f r1)\n            => Rot.Distance(r0, r1) == 0;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Rot3f\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Rot3f r0, Rot3f r1)\n            => !(r0 == r1);\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation from an orthonormal basis.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f FromFrame(V3f x, V3f y, V3f z)\n        {\n            return FromM33f(M33f.FromCols(x, y, z));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation from a Rodrigues axis-angle vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f FromAngleAxis(V3f angleAxis)\n        {\n            float theta2 = angleAxis.LengthSquared;\n            if (theta2 > Constant<float>.PositiveTinyValue)\n            {\n                var theta = Fun.Sqrt(theta2);\n                var thetaHalf = theta / 2;\n                var k = Fun.Sin(thetaHalf) / theta;\n                return new Rot3f(Fun.Cos(thetaHalf), k * angleAxis);\n            }\n            else\n                return new Rot3f(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation from a rotation matrix.\n        /// The matrix must be orthonormal.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        public static Rot3f FromM33f(M33f m, float epsilon = (float)1e-6)\n        {\n            if (!m.IsOrthonormal(epsilon)) throw new ArgumentException(\"Matrix is not orthonormal.\");\n            var tr = m.M00 + m.M11 + m.M22;\n\n            if (tr > 0)\n            {\n                float s = (tr + 1).Sqrt() * 2;\n                float x = (m.M21 - m.M12) / s;\n                float y = (m.M02 - m.M20) / s;\n                float z = (m.M10 - m.M01) / s;\n                float w = s / 4;\n                return new Rot3f(new QuaternionF(w, x, y, z).Normalized);\n            }\n            else if (m.M00 > m.M11 && m.M00 > m.M22)\n            {\n                float s = Fun.Sqrt(1 + m.M00 - m.M11 - m.M22) * 2;\n                float x = s / 4;\n                float y = (m.M01 + m.M10) / s;\n                float z = (m.M02 + m.M20) / s;\n                float w = (m.M21 - m.M12) / s;\n                return new Rot3f(new QuaternionF(w, x, y, z).Normalized);\n            }\n            else if (m.M11 > m.M22)\n            {\n                float s = Fun.Sqrt(1 + m.M11 - m.M00 - m.M22) * 2;\n                float x = (m.M01 + m.M10) / s;\n                float y = s / 4;\n                float z = (m.M12 + m.M21) / s;\n                float w = (m.M02 - m.M20) / s;\n                return new Rot3f(new QuaternionF(w, x, y, z).Normalized);\n            }\n            else\n            {\n                float s = Fun.Sqrt(1 + m.M22 - m.M00 - m.M11) * 2;\n                float x = (m.M02 + m.M20) / s;\n                float y = (m.M12 + m.M21) / s;\n                float z = s / 4;\n                float w = (m.M10 - m.M01) / s;\n                return new Rot3f(new QuaternionF(w, x, y, z).Normalized);\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation from a <see cref=\"M44f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f FromM44f(M44f m, float epsilon = 1e-5f)\n        {\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C3.XYZ.ApproximateEquals(V3f.Zero, epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM33f(((M33f)m) / m.M33);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation from a <see cref=\"Euclidean3f\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f FromEuclidean3f(Euclidean3f euclidean, float epsilon = 1e-5f)\n        {\n            if (!euclidean.Trans.ApproximateEquals(V3f.Zero, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains translational component\");\n\n            return euclidean.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation from a <see cref=\"Similarity3f\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f FromSimilarity3f(Similarity3f similarity, float epsilon = 1e-5f)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Trans.ApproximateEquals(V3f.Zero, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            return similarity.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation from an <see cref=\"Affine3f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f FromAffine3f(Affine3f affine, float epsilon = 1e-5f)\n            => FromM44f((M44f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation from a <see cref=\"Trafo3f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f FromTrafo3f(Trafo3f trafo, float epsilon = 1e-5f)\n            => FromM44f(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation representing a rotation around\n        /// an axis by an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f Rotation(V3f normalizedAxis, float angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            var halfAngleSin = halfAngle.Sin();\n\n            return new Rot3f(halfAngle.Cos(), normalizedAxis * halfAngleSin);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation representing a rotation around\n        /// an axis by an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationInDegrees(V3f normalizedAxis, float angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation representing a rotation from one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotateInto(V3f from, V3f into)\n        {\n            var d = Vec.Dot(from, into);\n\n            if (d.ApproximateEquals(-1))\n                return new Rot3f(0, from.AxisAlignedNormal());\n            else\n            {\n                QuaternionF q = new QuaternionF(d + 1, Vec.Cross(from, into));\n                return new Rot3f(q.Normalized);\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationX(float angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new Rot3f(halfAngle.Cos(), new V3f(halfAngle.Sin(), 0, 0));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation by <paramref name=\"angleInDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationXInDegrees(float angleInDegrees)\n            => RotationX(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationY(float angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new Rot3f(halfAngle.Cos(), new V3f(0, halfAngle.Sin(), 0));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation by <paramref name=\"angleInDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationYInDegrees(float angleInDegrees)\n            => RotationY(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationZ(float angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new Rot3f(halfAngle.Cos(), new V3f(0, 0, halfAngle.Sin()));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3f\"/> transformation by <paramref name=\"angleInDegrees\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationZInDegrees(float angleInDegrees)\n            => RotationZ(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationEuler(float rollInRadians, float pitchInRadians, float yawInRadians)\n        {\n            float rollHalf = rollInRadians / 2;\n            float cr = Fun.Cos(rollHalf);\n            float sr = Fun.Sin(rollHalf);\n            float pitchHalf = pitchInRadians / 2;\n            float cp = Fun.Cos(pitchHalf);\n            float sp = Fun.Sin(pitchHalf);\n            float yawHalf = yawInRadians / 2;\n            float cy = Fun.Cos(yawHalf);\n            float sy = Fun.Sin(yawHalf);\n\n            return new Rot3f(\n                cy * cp * cr + sy * sp * sr,\n                cy * cp * sr - sy * sp * cr,\n                sy * cp * sr + cy * sp * cr,\n                sy * cp * cr - cy * sp * sr);\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationEulerInDegrees(float rollInDegrees, float pitchInDegrees, float yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationEuler(V3f rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f RotationEulerInDegrees(V3f rollPitchYawInDegrees)\n            => RotationEulerInDegrees(rollPitchYawInDegrees.X, rollPitchYawInDegrees.Y, rollPitchYawInDegrees.Z);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Rot3f r)\n        {\n            //speed up by computing the multiplications only once (each is used 2 times below)\n            float xx = r.X * r.X;\n            float yy = r.Y * r.Y;\n            float zz = r.Z * r.Z;\n            float xy = r.X * r.Y;\n            float xz = r.X * r.Z;\n            float yz = r.Y * r.Z;\n            float xw = r.X * r.W;\n            float yw = r.Y * r.W;\n            float zw = r.Z * r.W;\n            return new M33f(\n                1 - 2 * (yy + zz),\n                2 * (xy - zw),\n                2 * (xz + yw),\n                \n                2 * (xy + zw),\n                1 - 2 * (zz + xx),\n                2 * (yz - xw),\n                \n                2 * (xz - yw),\n                2 * (yz + xw),\n                1 - 2 * (yy + xx));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Rot3f r)\n        {\n            //speed up by computing the multiplications only once (each is used 2 times below)\n            float xx = r.X * r.X;\n            float yy = r.Y * r.Y;\n            float zz = r.Z * r.Z;\n            float xy = r.X * r.Y;\n            float xz = r.X * r.Z;\n            float yz = r.Y * r.Z;\n            float xw = r.X * r.W;\n            float yw = r.Y * r.W;\n            float zw = r.Z * r.W;\n            return new M34f(\n                1 - 2 * (yy + zz),\n                2 * (xy - zw),\n                2 * (xz + yw),\n                0,\n                \n                2 * (xy + zw),\n                1 - 2 * (zz + xx),\n                2 * (yz - xw),\n                0,\n                \n                2 * (xz - yw),\n                2 * (yz + xw),\n                1 - 2 * (yy + xx),\n                0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Rot3f r)\n        {\n            //speed up by computing the multiplications only once (each is used 2 times below)\n            float xx = r.X * r.X;\n            float yy = r.Y * r.Y;\n            float zz = r.Z * r.Z;\n            float xy = r.X * r.Y;\n            float xz = r.X * r.Z;\n            float yz = r.Y * r.Z;\n            float xw = r.X * r.W;\n            float yw = r.Y * r.W;\n            float zw = r.Z * r.W;\n            return new M44f(\n                1 - 2 * (yy + zz),\n                2 * (xy - zw),\n                2 * (xz + yw),\n                0,\n                \n                2 * (xy + zw),\n                1 - 2 * (zz + xx),\n                2 * (yz - xw),\n                0,\n                \n                2 * (xz - yw),\n                2 * (yz + xw),\n                1 - 2 * (yy + xx),\n                0,\n\n                0, 0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](Rot3f r)\n        {\n            float[] array = new float[4];\n            array[0] = r.W;\n            array[1] = r.X;\n            array[2] = r.Y;\n            array[3] = r.Z;\n            return array;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean3f(Rot3f r)\n            => new Euclidean3f(r, V3f.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity3f(Rot3f r)\n            => new Similarity3f(1, r, V3f.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3f(Rot3f r)\n            => new Affine3f((M33f)r);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3f(Rot3f r)\n            => new Trafo3f((M44f)r, (M44f)r.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Rot3d(Rot3f r)\n            => new Rot3d((double)r.W, (double)r.X, (double)r.Y, (double)r.Z);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator QuaternionF(Rot3f r)\n            => new QuaternionF(r.W, r.X, r.Y, r.Z);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator QuaternionD(Rot3f r)\n            => new QuaternionD((double)r.W, (double)r.X, (double)r.Y, (double)r.Z);\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets or sets the <paramref name=\"i\"/>-th component of the <see cref=\"Rot3f\"/> unit quaternion with components (W, (X, Y, Z)).\n        /// </summary>\n        public unsafe float this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &W) { return ptr[i]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &W) { ptr[i] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(W, V);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Rot3f other)\n            => Rot.Distance(this, other) == 0;\n\n        public override readonly bool Equals(object other)\n            => (other is Rot3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", W, V);\n        }\n\n        public static Rot3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Rot3f(float.Parse(x[0], CultureInfo.InvariantCulture), V3f.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Rot\n    {\n        #region Dot\n\n        /// <summary>\n        /// Returns the dot product of two <see cref=\"Rot3f\"/> unit quaternions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Dot(this Rot3f a, Rot3f b)\n        {\n            return a.W * b.W + a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"Rot3f\"/> rotations.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceFast(this Rot3f r1, Rot3f r2)\n        {\n            var d = Dot(r1, r2);\n            return 2 * Fun.AcosClamped((d < 0) ? -d : d);\n        }\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"Rot3f\"/> rotations\n        /// using a numerically stable algorithm.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(this Rot3f r1, Rot3f r2)\n        {\n            var q = r1.Inverse * r2;\n            return 2 * Fun.Atan2(q.V.Length, (q.W < 0) ? -q.W : q.W);\n        }\n\n        #endregion\n\n        #region Invert, Normalize\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f Inverse(Rot3f r)\n            => r.Inverse;\n\n        /// <summary>\n        /// Inverts the given <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Rot3f r)\n        {\n            r.X = -r.X;\n            r.Y = -r.Y;\n            r.Z = -r.Z;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3f Normalized(Rot3f r)\n            => r.Normalized;\n\n        /// <summary>\n        /// Normalizes a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref Rot3f r)\n        {\n            var norm = r.Norm;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                \n                r.W *= scale;\n                r.X *= scale;\n                r.Y *= scale;\n                r.Z *= scale;\n            }\n        }\n\n        #endregion\n\n        #region Conversion\n\n        /// <summary>\n        /// Returns the Rodrigues angle-axis vector of a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f ToAngleAxis(this Rot3f r)\n        {\n            var sinTheta2 = r.V.LengthSquared;\n            if (sinTheta2 > Constant<float>.PositiveTinyValue)\n            {\n                float sinTheta = Fun.Sqrt(sinTheta2);\n                float cosTheta = r.W;\n                float twoTheta = 2 * (cosTheta < 0 ? Fun.Atan2(-sinTheta, -cosTheta)\n                                                    : Fun.Atan2(sinTheta, cosTheta));\n                return r.V * (twoTheta / sinTheta);\n            }\n            else\n                return V3f.Zero;\n        }\n\n        /// <summary>\n        /// Returns the axis-angle representation of a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        /// <param name=\"r\">A <see cref=\"Rot3f\"/> transformation.</param>\n        /// <param name=\"axis\">Output of normalized axis of rotation.</param>\n        /// <param name=\"angleInRadians\">Output of angle of rotation in radians about axis (Right Hand Rule).</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ToAxisAngle(this Rot3f r, ref V3f axis, ref float angleInRadians)\n        {\n            angleInRadians = 2 * Fun.Acos(r.W);\n            var s = Fun.Sqrt(1 - r.W * r.W); // assuming quaternion normalised then w is less than 1, so term always positive.\n            if (s < 0.001)\n            { // test to avoid divide by zero, s is always positive due to sqrt\n                // if s close to zero then direction of axis not important\n                axis.X = r.X; // if it is important that axis is normalised then replace with x=1; y=z=0;\n                axis.Y = r.Y;\n                axis.Z = r.Z;\n            }\n            else\n            {\n                axis.X = r.X / s; // normalise axis\n                axis.Y = r.Y / s;\n                axis.Z = r.Z / s;\n            }\n        }\n\n        #endregion\n\n        #region Euler Angles\n\n        /// <summary>\n        /// Returns the Euler-Angles from the given <see cref=\"Rot3f\"/> as a <see cref=\"V3f\"/> vector.\n        /// The vector components represent [roll (X), pitch (Y), yaw (Z)] with rotation order is Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetEulerAngles(this Rot3f r)\n        {\n            var test = r.W * r.Y - r.X * r.Z;\n            if (test > 0.5f - Constant<float>.PositiveTinyValue) // singularity at north pole\n            {\n                return new V3f(\n                    2 * Fun.Atan2(r.X, r.W),\n                    ConstantF.PiHalf,\n                    0);\n            }\n            if (test < -0.5f + Constant<float>.PositiveTinyValue) // singularity at south pole\n            {\n                return new V3f(\n                    2 * Fun.Atan2(r.X, r.W),\n                    -ConstantF.PiHalf,\n                    0);\n            }\n            // From Wikipedia, conversion between quaternions and Euler angles.\n            return new V3f(\n                        Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                  1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                        Fun.AsinClamped(2 * test),\n                        Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                  1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Rot3f r, V3f v)\n            => r * v;\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by the inverse of a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransform(this Rot3f r, V3f v)\n        {\n            var w = r.X * v.X + r.Y * v.Y + r.Z * v.Z;\n            var x = r.W * v.X - r.Y * v.Z + r.Z * v.Y;\n            var y = r.W * v.Y - r.Z * v.X + r.X * v.Z;\n            var z = r.W * v.Z - r.X * v.Y + r.Y * v.X;\n\n            return new V3f(\n                w * r.X + x * r.W + y * r.Z - z * r.Y,\n                w * r.Y + y * r.W + z * r.X - x * r.Z,\n                w * r.Z + z * r.W + x * r.Y - y * r.X\n                );\n        }\n\n        #endregion\n\n        #region Spherical Linear Interpolation\n\n        /// <summary>\n        /// Spherical linear interpolation.\n        ///\n        /// Assumes q1 and q2 are normalized and that t in [0,1].\n        ///\n        /// This method interpolates along the shortest arc between q1 and q2.\n        /// </summary>\n        public static Rot3f SlerpShortest(this Rot3f q1, Rot3f q2, float t)\n        {\n            Rot3f q3 = q2;\n            float cosomega = Dot(q1, q3);\n\n            if (cosomega < 0)\n            {\n                cosomega = -cosomega;\n                q3 = -q3;\n            }\n\n            if (cosomega >= 1)\n            {\n                // Special case: q1 and q2 are the same, so just return one of them.\n                // This also catches the case where cosomega is very slightly > 1.0\n                return q1;\n            }\n\n            float sinomega = Fun.Sqrt(1 - cosomega * cosomega);\n\n            Rot3f result;\n\n            if (sinomega * float.MaxValue > 1)\n            {\n                float omega = Fun.Acos(cosomega);\n                float s1 = Fun.Sin((1 - t) * omega) / sinomega;\n                float s2 = Fun.Sin(t * omega) / sinomega;\n\n                result = new Rot3f(s1 * q1 + s2 * q3);\n            }\n            else if (cosomega > 0)\n            {\n                // omega == 0\n                float s1 = 1 - t;\n                float s2 = t;\n\n                result = new Rot3f(s1 * q1 + s2 * q3);\n            }\n            else\n            {\n                // omega == -pi\n                result = new Rot3f(q1.Z, -q1.Y, q1.X, -q1.W);\n\n                float s1 = Fun.Sin((0.5f - t) * ConstantF.Pi);\n                float s2 = Fun.Sin(t * ConstantF.Pi);\n\n                result = new Rot3f(s1 * q1 + s2 * result);\n            }\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Rot3f r0, Rot3f r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Rot3f r0, Rot3f r1, float tolerance)\n        {\n            return Rot.Distance(r0, r1) <= tolerance;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Rot3d\n\n    /// <summary>\n    /// Represents a rotation in three dimensions using a unit quaternion.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Rot3d : IEquatable<Rot3d>\n    {\n        /// <summary>\n        /// Scalar (real) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public double W;\n\n        /// <summary>\n        /// First component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public double X;\n\n        /// <summary>\n        /// Second component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public double Y;\n\n        /// <summary>\n        /// Third component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public double Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3d\"/> transformation from the quaternion (w, (x, y, z)).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3d(double w, double x, double y, double z)\n        {\n            W = w;\n            X = x; Y = y; Z = z;\n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3d\"/> transformation from the quaternion (w, (v.x, v.y, v.z)).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3d(double w, V3d v)\n        {\n            W = w;\n            X = v.X; Y = v.Y; Z = v.Z;\n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3d\"/> transformation from the quaternion <paramref name=\"q\"/>.\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3d(QuaternionD q)\n        {\n            W = q.W; X = q.X; Y = q.Y; Z = q.Z; \n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3d\"/> transformation from the quaternion <paramref name=\"q\"/>.\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3d(QuaternionF q)\n        {\n            W = (double)q.W; X = (double)q.X; Y = (double)q.Y; Z = (double)q.Z; \n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3d(Rot3d r)\n        {\n            W = r.W; X = r.X; Y = r.Y; Z = r.Z; \n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3d\"/> transformation from a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3d(Rot3f r)\n        {\n            W = (double)r.W; X = (double)r.X; Y = (double)r.Y; Z = (double)r.Z; \n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3d\"/> transformation from the quaternion (a[0], (a[1], a[2], a[3])).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3d(double[] a)\n        {\n            W = a[0];\n            X = a[1]; Y = a[2]; Z = a[3];\n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Rot3d\"/> transformation from the quaternion (a[start], (a[start + 1], a[start + 2], a[start + 3])).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Rot3d(double[] a, int start)\n        {\n            W = a[start];\n            X = a[start + 1]; Y = a[start + 2]; Z = a[start + 3];\n            Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets or sets the vector part (x, y, z) of this <see cref=\"Rot3d\"/> unit quaternion.\n        /// </summary>\n        [XmlIgnore]\n        public V3d V\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new V3d(X, Y, Z); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n\n        /// <summary>\n        /// Gets the squared norm (or squared length) of this <see cref=\"Rot3d\"/>.\n        /// May not be exactly 1, due to numerical inaccuracy.\n        /// </summary>\n        public readonly double NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => W * W + X * X + Y * Y + Z * Z;\n        }\n\n        /// <summary>\n        /// Gets the norm (or length) of this <see cref=\"Rot3d\"/>.\n        /// May not be exactly 1, due to numerical inaccuracy.\n        /// </summary>\n        public readonly double Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => NormSquared.Sqrt();\n        }\n\n        /// <summary>\n        /// Gets normalized (unit) quaternion from this <see cref=\"Rot3d\"/>\n        /// </summary>\n        public readonly Rot3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new Rot3d(this);\n                rs.Normalize();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        public readonly Rot3d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, 1e-10));\n                return new Rot3d(W, -X, -Y, -Z);\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Rot3d\"/>.\n        /// </summary>\n        public static Rot3d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Rot3d(1, 0, 0, 0);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Returns the component-wise negation of a <see cref=\"Rot3d\"/> unit quaternion.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d operator -(Rot3d q)\n            => new Rot3d(-q.W, -q.X, -q.Y, -q.Z);\n\n        /// <summary>\n        /// Multiplies two <see cref=\"Rot3d\"/> transformations.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d operator *(Rot3d a, Rot3d b)\n        {\n            return new Rot3d(\n                a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z,\n                a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,\n                a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,\n                a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X);\n        }\n\n        #region Rot / Vector Multiplication\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Rot3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(Rot3d r, V3d v)\n        {\n            var w = -r.X * v.X - r.Y * v.Y - r.Z * v.Z;\n            var x = r.W * v.X + r.Y * v.Z - r.Z * v.Y;\n            var y = r.W * v.Y + r.Z * v.X - r.X * v.Z;\n            var z = r.W * v.Z + r.X * v.Y - r.Y * v.X;\n\n            return new V3d(\n                -w * r.X + x * r.W - y * r.Z + z * r.Y,\n                -w * r.Y + y * r.W - z * r.X + x * r.Z,\n                -w * r.Z + z * r.W - x * r.Y + y * r.X);\n        }\n\n        #endregion\n\n        #region Rot / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(Rot3d rot, M33d m)\n        {\n            return (M33d)rot * m;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> with a <see cref=\"Rot3d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(M33d m, Rot3d rot)\n        {\n            return m * (M33d)rot;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(Rot3d rot, M44d m)\n        {\n            var r = (M33d)rot;\n            return new M44d(\n                r.M00 * m.M00 + r.M01 * m.M10 + r.M02 * m.M20, \n                r.M00 * m.M01 + r.M01 * m.M11 + r.M02 * m.M21, \n                r.M00 * m.M02 + r.M01 * m.M12 + r.M02 * m.M22, \n                r.M00 * m.M03 + r.M01 * m.M13 + r.M02 * m.M23,\n\n                r.M10 * m.M00 + r.M11 * m.M10 + r.M12 * m.M20, \n                r.M10 * m.M01 + r.M11 * m.M11 + r.M12 * m.M21, \n                r.M10 * m.M02 + r.M11 * m.M12 + r.M12 * m.M22, \n                r.M10 * m.M03 + r.M11 * m.M13 + r.M12 * m.M23,\n\n                r.M20 * m.M00 + r.M21 * m.M10 + r.M22 * m.M20, \n                r.M20 * m.M01 + r.M21 * m.M11 + r.M22 * m.M21, \n                r.M20 * m.M02 + r.M21 * m.M12 + r.M22 * m.M22, \n                r.M20 * m.M03 + r.M21 * m.M13 + r.M22 * m.M23,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44d\"/> with a <see cref=\"Rot3d\"/> transformation (as a 4x4 matrix) .\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(M44d m, Rot3d rot)\n        {\n            var r = (M33d)rot;\n            return new M44d(\n                m.M00 * r.M00 + m.M01 * r.M10 + m.M02 * r.M20, \n                m.M00 * r.M01 + m.M01 * r.M11 + m.M02 * r.M21, \n                m.M00 * r.M02 + m.M01 * r.M12 + m.M02 * r.M22,\n                m.M03,\n\n                m.M10 * r.M00 + m.M11 * r.M10 + m.M12 * r.M20, \n                m.M10 * r.M01 + m.M11 * r.M11 + m.M12 * r.M21, \n                m.M10 * r.M02 + m.M11 * r.M12 + m.M12 * r.M22,\n                m.M13,\n\n                m.M20 * r.M00 + m.M21 * r.M10 + m.M22 * r.M20, \n                m.M20 * r.M01 + m.M21 * r.M11 + m.M22 * r.M21, \n                m.M20 * r.M02 + m.M21 * r.M12 + m.M22 * r.M22,\n                m.M23,\n\n                m.M30 * r.M00 + m.M31 * r.M10 + m.M32 * r.M20, \n                m.M30 * r.M01 + m.M31 * r.M11 + m.M32 * r.M21, \n                m.M30 * r.M02 + m.M31 * r.M12 + m.M32 * r.M22,\n                m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M34d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Rot3d rot, M34d m)\n        {\n            return (M33d)rot * m;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34d\"/> with a <see cref=\"Rot3d\"/> transformation (as a 4x4 matrix) .\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M34d m, Rot3d rot)\n        {\n            var r = (M33d)rot;\n            return new M34d(\n                m.M00 * r.M00 + m.M01 * r.M10 + m.M02 * r.M20, \n                m.M00 * r.M01 + m.M01 * r.M11 + m.M02 * r.M21, \n                m.M00 * r.M02 + m.M01 * r.M12 + m.M02 * r.M22,\n                m.M03,\n\n                m.M10 * r.M00 + m.M11 * r.M10 + m.M12 * r.M20, \n                m.M10 * r.M01 + m.M11 * r.M11 + m.M12 * r.M21, \n                m.M10 * r.M02 + m.M11 * r.M12 + m.M12 * r.M22,\n                m.M13,\n\n                m.M20 * r.M00 + m.M21 * r.M10 + m.M22 * r.M20, \n                m.M20 * r.M01 + m.M21 * r.M11 + m.M22 * r.M21, \n                m.M20 * r.M02 + m.M21 * r.M12 + m.M22 * r.M22,\n                m.M23);\n        }\n\n        #endregion\n\n        #region Rot / Quaternion arithmetics\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"Rot3d\"/> and a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator +(Rot3d r, QuaternionD q)\n            => new QuaternionD(r.W + q.W, r.X + q.X, r.Y + q.Y, r.Z + q.Z);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"QuaternionD\"/> and a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator +(QuaternionD q, Rot3d r)\n            => new QuaternionD(q.W + r.W, q.X + r.X, q.Y + r.Y, q.Z + r.Z);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"Rot3d\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator +(Rot3d r, double s)\n            => new QuaternionD(r.W + s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the sum of a real scalar and a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator +(double s, Rot3d r)\n            => new QuaternionD(r.W + s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"Rot3d\"/> and a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator -(Rot3d r, QuaternionD q)\n            => new QuaternionD(r.W - q.W, r.X - q.X, r.Y - q.Y, r.Z - q.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"QuaternionD\"/> and a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator -(QuaternionD q, Rot3d r)\n            => new QuaternionD(q.W - r.W, q.X - r.X, q.Y - r.Y, q.Z - r.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"Rot3d\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator -(Rot3d r, double s)\n            => new QuaternionD(r.W - s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the difference between a real scalar and a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator -(double s, Rot3d r)\n            => new QuaternionD(s - r.W, -r.X, -r.Y, -r.Z);\n\n        /// <summary>\n        /// Returns the product of a <see cref=\"Rot3d\"/> and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator *(Rot3d r, double s)\n            => new QuaternionD(r.W * s, r.X * s, r.Y * s, r.Z * s);\n\n        /// <summary>\n        /// Returns the product of a scalar and a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator *(double s, Rot3d r)\n            => new QuaternionD(r.W * s, r.X * s, r.Y * s, r.Z * s);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> with a <see cref=\"QuaternionD\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator *(Rot3d r, QuaternionD q)\n        {\n            return new QuaternionD(\n                r.W * q.W - r.X * q.X - r.Y * q.Y - r.Z * q.Z,\n                r.W * q.X + r.X * q.W + r.Y * q.Z - r.Z * q.Y,\n                r.W * q.Y + r.Y * q.W + r.Z * q.X - r.X * q.Z,\n                r.W * q.Z + r.Z * q.W + r.X * q.Y - r.Y * q.X);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"QuaternionD\"/> with a <see cref=\"Rot3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator *(QuaternionD q, Rot3d r)\n        {\n            return new QuaternionD(\n                q.W * r.W - q.X * r.X - q.Y * r.Y - q.Z * r.Z,\n                q.W * r.X + q.X * r.W + q.Y * r.Z - q.Z * r.Y,\n                q.W * r.Y + q.Y * r.W + q.Z * r.X - q.X * r.Z,\n                q.W * r.Z + q.Z * r.W + q.X * r.Y - q.Y * r.X);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Rot3d\"/> by a <see cref=\"QuaternionD\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator /(Rot3d r, QuaternionD q)\n            => r * q.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"QuaternionD\"/> by a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator /(QuaternionD q, Rot3d r)\n            => q * r.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"Rot3d\"/> by a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator /(Rot3d r, double s)\n            => new QuaternionD(r.W / s, r.X / s, r.Y / s, r.Z / s);\n\n        /// <summary>\n        /// Divides a scalar by a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static QuaternionD operator /(double s, Rot3d r)\n            => new QuaternionD(s / r.W, s / r.X, s / r.Y, s / r.Z);\n\n        #endregion\n\n        #region Rot / Shift, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> transformation with a <see cref=\"Shift3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d operator *(Rot3d a, Shift3d b)\n            => new Euclidean3d(a, a * b.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> transformation with a <see cref=\"Scale3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Rot3d a, Scale3d b)\n            => new Affine3d((M33d)a * (M33d)b);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Rot3d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Rot3d r0, Rot3d r1)\n            => Rot.Distance(r0, r1) == 0;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Rot3d\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Rot3d r0, Rot3d r1)\n            => !(r0 == r1);\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation from an orthonormal basis.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d FromFrame(V3d x, V3d y, V3d z)\n        {\n            return FromM33d(M33d.FromCols(x, y, z));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation from a Rodrigues axis-angle vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d FromAngleAxis(V3d angleAxis)\n        {\n            double theta2 = angleAxis.LengthSquared;\n            if (theta2 > Constant<double>.PositiveTinyValue)\n            {\n                var theta = Fun.Sqrt(theta2);\n                var thetaHalf = theta / 2;\n                var k = Fun.Sin(thetaHalf) / theta;\n                return new Rot3d(Fun.Cos(thetaHalf), k * angleAxis);\n            }\n            else\n                return new Rot3d(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation from a rotation matrix.\n        /// The matrix must be orthonormal.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        public static Rot3d FromM33d(M33d m, double epsilon = (double)1e-6)\n        {\n            if (!m.IsOrthonormal(epsilon)) throw new ArgumentException(\"Matrix is not orthonormal.\");\n            var tr = m.M00 + m.M11 + m.M22;\n\n            if (tr > 0)\n            {\n                double s = (tr + 1).Sqrt() * 2;\n                double x = (m.M21 - m.M12) / s;\n                double y = (m.M02 - m.M20) / s;\n                double z = (m.M10 - m.M01) / s;\n                double w = s / 4;\n                return new Rot3d(new QuaternionD(w, x, y, z).Normalized);\n            }\n            else if (m.M00 > m.M11 && m.M00 > m.M22)\n            {\n                double s = Fun.Sqrt(1 + m.M00 - m.M11 - m.M22) * 2;\n                double x = s / 4;\n                double y = (m.M01 + m.M10) / s;\n                double z = (m.M02 + m.M20) / s;\n                double w = (m.M21 - m.M12) / s;\n                return new Rot3d(new QuaternionD(w, x, y, z).Normalized);\n            }\n            else if (m.M11 > m.M22)\n            {\n                double s = Fun.Sqrt(1 + m.M11 - m.M00 - m.M22) * 2;\n                double x = (m.M01 + m.M10) / s;\n                double y = s / 4;\n                double z = (m.M12 + m.M21) / s;\n                double w = (m.M02 - m.M20) / s;\n                return new Rot3d(new QuaternionD(w, x, y, z).Normalized);\n            }\n            else\n            {\n                double s = Fun.Sqrt(1 + m.M22 - m.M00 - m.M11) * 2;\n                double x = (m.M02 + m.M20) / s;\n                double y = (m.M12 + m.M21) / s;\n                double z = s / 4;\n                double w = (m.M10 - m.M01) / s;\n                return new Rot3d(new QuaternionD(w, x, y, z).Normalized);\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation from a <see cref=\"M44d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d FromM44d(M44d m, double epsilon = 1e-12)\n        {\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C3.XYZ.ApproximateEquals(V3d.Zero, epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM33d(((M33d)m) / m.M33);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation from a <see cref=\"Euclidean3d\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d FromEuclidean3d(Euclidean3d euclidean, double epsilon = 1e-12)\n        {\n            if (!euclidean.Trans.ApproximateEquals(V3d.Zero, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains translational component\");\n\n            return euclidean.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation from a <see cref=\"Similarity3d\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d FromSimilarity3d(Similarity3d similarity, double epsilon = 1e-12)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Trans.ApproximateEquals(V3d.Zero, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            return similarity.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation from an <see cref=\"Affine3d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d FromAffine3d(Affine3d affine, double epsilon = 1e-12)\n            => FromM44d((M44d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation from a <see cref=\"Trafo3d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d FromTrafo3d(Trafo3d trafo, double epsilon = 1e-12)\n            => FromM44d(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation representing a rotation around\n        /// an axis by an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d Rotation(V3d normalizedAxis, double angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            var halfAngleSin = halfAngle.Sin();\n\n            return new Rot3d(halfAngle.Cos(), normalizedAxis * halfAngleSin);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation representing a rotation around\n        /// an axis by an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationInDegrees(V3d normalizedAxis, double angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation representing a rotation from one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotateInto(V3d from, V3d into)\n        {\n            var d = Vec.Dot(from, into);\n\n            if (d.ApproximateEquals(-1))\n                return new Rot3d(0, from.AxisAlignedNormal());\n            else\n            {\n                QuaternionD q = new QuaternionD(d + 1, Vec.Cross(from, into));\n                return new Rot3d(q.Normalized);\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationX(double angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new Rot3d(halfAngle.Cos(), new V3d(halfAngle.Sin(), 0, 0));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation by <paramref name=\"angleInDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationXInDegrees(double angleInDegrees)\n            => RotationX(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationY(double angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new Rot3d(halfAngle.Cos(), new V3d(0, halfAngle.Sin(), 0));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation by <paramref name=\"angleInDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationYInDegrees(double angleInDegrees)\n            => RotationY(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationZ(double angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new Rot3d(halfAngle.Cos(), new V3d(0, 0, halfAngle.Sin()));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Rot3d\"/> transformation by <paramref name=\"angleInDegrees\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationZInDegrees(double angleInDegrees)\n            => RotationZ(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationEuler(double rollInRadians, double pitchInRadians, double yawInRadians)\n        {\n            double rollHalf = rollInRadians / 2;\n            double cr = Fun.Cos(rollHalf);\n            double sr = Fun.Sin(rollHalf);\n            double pitchHalf = pitchInRadians / 2;\n            double cp = Fun.Cos(pitchHalf);\n            double sp = Fun.Sin(pitchHalf);\n            double yawHalf = yawInRadians / 2;\n            double cy = Fun.Cos(yawHalf);\n            double sy = Fun.Sin(yawHalf);\n\n            return new Rot3d(\n                cy * cp * cr + sy * sp * sr,\n                cy * cp * sr - sy * sp * cr,\n                sy * cp * sr + cy * sp * cr,\n                sy * cp * cr - cy * sp * sr);\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationEulerInDegrees(double rollInDegrees, double pitchInDegrees, double yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationEuler(V3d rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d RotationEulerInDegrees(V3d rollPitchYawInDegrees)\n            => RotationEulerInDegrees(rollPitchYawInDegrees.X, rollPitchYawInDegrees.Y, rollPitchYawInDegrees.Z);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Rot3d r)\n        {\n            //speed up by computing the multiplications only once (each is used 2 times below)\n            double xx = r.X * r.X;\n            double yy = r.Y * r.Y;\n            double zz = r.Z * r.Z;\n            double xy = r.X * r.Y;\n            double xz = r.X * r.Z;\n            double yz = r.Y * r.Z;\n            double xw = r.X * r.W;\n            double yw = r.Y * r.W;\n            double zw = r.Z * r.W;\n            return new M33d(\n                1 - 2 * (yy + zz),\n                2 * (xy - zw),\n                2 * (xz + yw),\n                \n                2 * (xy + zw),\n                1 - 2 * (zz + xx),\n                2 * (yz - xw),\n                \n                2 * (xz - yw),\n                2 * (yz + xw),\n                1 - 2 * (yy + xx));\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Rot3d r)\n        {\n            //speed up by computing the multiplications only once (each is used 2 times below)\n            double xx = r.X * r.X;\n            double yy = r.Y * r.Y;\n            double zz = r.Z * r.Z;\n            double xy = r.X * r.Y;\n            double xz = r.X * r.Z;\n            double yz = r.Y * r.Z;\n            double xw = r.X * r.W;\n            double yw = r.Y * r.W;\n            double zw = r.Z * r.W;\n            return new M34d(\n                1 - 2 * (yy + zz),\n                2 * (xy - zw),\n                2 * (xz + yw),\n                0,\n                \n                2 * (xy + zw),\n                1 - 2 * (zz + xx),\n                2 * (yz - xw),\n                0,\n                \n                2 * (xz - yw),\n                2 * (yz + xw),\n                1 - 2 * (yy + xx),\n                0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Rot3d r)\n        {\n            //speed up by computing the multiplications only once (each is used 2 times below)\n            double xx = r.X * r.X;\n            double yy = r.Y * r.Y;\n            double zz = r.Z * r.Z;\n            double xy = r.X * r.Y;\n            double xz = r.X * r.Z;\n            double yz = r.Y * r.Z;\n            double xw = r.X * r.W;\n            double yw = r.Y * r.W;\n            double zw = r.Z * r.W;\n            return new M44d(\n                1 - 2 * (yy + zz),\n                2 * (xy - zw),\n                2 * (xz + yw),\n                0,\n                \n                2 * (xy + zw),\n                1 - 2 * (zz + xx),\n                2 * (yz - xw),\n                0,\n                \n                2 * (xz - yw),\n                2 * (yz + xw),\n                1 - 2 * (yy + xx),\n                0,\n\n                0, 0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](Rot3d r)\n        {\n            double[] array = new double[4];\n            array[0] = r.W;\n            array[1] = r.X;\n            array[2] = r.Y;\n            array[3] = r.Z;\n            return array;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean3d(Rot3d r)\n            => new Euclidean3d(r, V3d.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity3d(Rot3d r)\n            => new Similarity3d(1, r, V3d.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3d(Rot3d r)\n            => new Affine3d((M33d)r);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3d(Rot3d r)\n            => new Trafo3d((M44d)r, (M44d)r.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Rot3f(Rot3d r)\n            => new Rot3f((float)r.W, (float)r.X, (float)r.Y, (float)r.Z);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator QuaternionD(Rot3d r)\n            => new QuaternionD(r.W, r.X, r.Y, r.Z);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator QuaternionF(Rot3d r)\n            => new QuaternionF((float)r.W, (float)r.X, (float)r.Y, (float)r.Z);\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets or sets the <paramref name=\"i\"/>-th component of the <see cref=\"Rot3d\"/> unit quaternion with components (W, (X, Y, Z)).\n        /// </summary>\n        public unsafe double this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &W) { return ptr[i]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &W) { ptr[i] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(W, V);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Rot3d other)\n            => Rot.Distance(this, other) == 0;\n\n        public override readonly bool Equals(object other)\n            => (other is Rot3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", W, V);\n        }\n\n        public static Rot3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Rot3d(double.Parse(x[0], CultureInfo.InvariantCulture), V3d.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Rot\n    {\n        #region Dot\n\n        /// <summary>\n        /// Returns the dot product of two <see cref=\"Rot3d\"/> unit quaternions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Dot(this Rot3d a, Rot3d b)\n        {\n            return a.W * b.W + a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"Rot3d\"/> rotations.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceFast(this Rot3d r1, Rot3d r2)\n        {\n            var d = Dot(r1, r2);\n            return 2 * Fun.AcosClamped((d < 0) ? -d : d);\n        }\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"Rot3d\"/> rotations\n        /// using a numerically stable algorithm.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this Rot3d r1, Rot3d r2)\n        {\n            var q = r1.Inverse * r2;\n            return 2 * Fun.Atan2(q.V.Length, (q.W < 0) ? -q.W : q.W);\n        }\n\n        #endregion\n\n        #region Invert, Normalize\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d Inverse(Rot3d r)\n            => r.Inverse;\n\n        /// <summary>\n        /// Inverts the given <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Rot3d r)\n        {\n            r.X = -r.X;\n            r.Y = -r.Y;\n            r.Z = -r.Z;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Rot3d Normalized(Rot3d r)\n            => r.Normalized;\n\n        /// <summary>\n        /// Normalizes a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref Rot3d r)\n        {\n            var norm = r.Norm;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                \n                r.W *= scale;\n                r.X *= scale;\n                r.Y *= scale;\n                r.Z *= scale;\n            }\n        }\n\n        #endregion\n\n        #region Conversion\n\n        /// <summary>\n        /// Returns the Rodrigues angle-axis vector of a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d ToAngleAxis(this Rot3d r)\n        {\n            var sinTheta2 = r.V.LengthSquared;\n            if (sinTheta2 > Constant<double>.PositiveTinyValue)\n            {\n                double sinTheta = Fun.Sqrt(sinTheta2);\n                double cosTheta = r.W;\n                double twoTheta = 2 * (cosTheta < 0 ? Fun.Atan2(-sinTheta, -cosTheta)\n                                                    : Fun.Atan2(sinTheta, cosTheta));\n                return r.V * (twoTheta / sinTheta);\n            }\n            else\n                return V3d.Zero;\n        }\n\n        /// <summary>\n        /// Returns the axis-angle representation of a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        /// <param name=\"r\">A <see cref=\"Rot3d\"/> transformation.</param>\n        /// <param name=\"axis\">Output of normalized axis of rotation.</param>\n        /// <param name=\"angleInRadians\">Output of angle of rotation in radians about axis (Right Hand Rule).</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ToAxisAngle(this Rot3d r, ref V3d axis, ref double angleInRadians)\n        {\n            angleInRadians = 2 * Fun.Acos(r.W);\n            var s = Fun.Sqrt(1 - r.W * r.W); // assuming quaternion normalised then w is less than 1, so term always positive.\n            if (s < 0.001)\n            { // test to avoid divide by zero, s is always positive due to sqrt\n                // if s close to zero then direction of axis not important\n                axis.X = r.X; // if it is important that axis is normalised then replace with x=1; y=z=0;\n                axis.Y = r.Y;\n                axis.Z = r.Z;\n            }\n            else\n            {\n                axis.X = r.X / s; // normalise axis\n                axis.Y = r.Y / s;\n                axis.Z = r.Z / s;\n            }\n        }\n\n        #endregion\n\n        #region Euler Angles\n\n        /// <summary>\n        /// Returns the Euler-Angles from the given <see cref=\"Rot3d\"/> as a <see cref=\"V3d\"/> vector.\n        /// The vector components represent [roll (X), pitch (Y), yaw (Z)] with rotation order is Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetEulerAngles(this Rot3d r)\n        {\n            var test = r.W * r.Y - r.X * r.Z;\n            if (test > 0.5 - Constant<double>.PositiveTinyValue) // singularity at north pole\n            {\n                return new V3d(\n                    2 * Fun.Atan2(r.X, r.W),\n                    Constant.PiHalf,\n                    0);\n            }\n            if (test < -0.5 + Constant<double>.PositiveTinyValue) // singularity at south pole\n            {\n                return new V3d(\n                    2 * Fun.Atan2(r.X, r.W),\n                    -Constant.PiHalf,\n                    0);\n            }\n            // From Wikipedia, conversion between quaternions and Euler angles.\n            return new V3d(\n                        Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                  1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                        Fun.AsinClamped(2 * test),\n                        Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                  1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Rot3d r, V3d v)\n            => r * v;\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by the inverse of a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransform(this Rot3d r, V3d v)\n        {\n            var w = r.X * v.X + r.Y * v.Y + r.Z * v.Z;\n            var x = r.W * v.X - r.Y * v.Z + r.Z * v.Y;\n            var y = r.W * v.Y - r.Z * v.X + r.X * v.Z;\n            var z = r.W * v.Z - r.X * v.Y + r.Y * v.X;\n\n            return new V3d(\n                w * r.X + x * r.W + y * r.Z - z * r.Y,\n                w * r.Y + y * r.W + z * r.X - x * r.Z,\n                w * r.Z + z * r.W + x * r.Y - y * r.X\n                );\n        }\n\n        #endregion\n\n        #region Spherical Linear Interpolation\n\n        /// <summary>\n        /// Spherical linear interpolation.\n        ///\n        /// Assumes q1 and q2 are normalized and that t in [0,1].\n        ///\n        /// This method interpolates along the shortest arc between q1 and q2.\n        /// </summary>\n        public static Rot3d SlerpShortest(this Rot3d q1, Rot3d q2, double t)\n        {\n            Rot3d q3 = q2;\n            double cosomega = Dot(q1, q3);\n\n            if (cosomega < 0)\n            {\n                cosomega = -cosomega;\n                q3 = -q3;\n            }\n\n            if (cosomega >= 1)\n            {\n                // Special case: q1 and q2 are the same, so just return one of them.\n                // This also catches the case where cosomega is very slightly > 1.0\n                return q1;\n            }\n\n            double sinomega = Fun.Sqrt(1 - cosomega * cosomega);\n\n            Rot3d result;\n\n            if (sinomega * double.MaxValue > 1)\n            {\n                double omega = Fun.Acos(cosomega);\n                double s1 = Fun.Sin((1 - t) * omega) / sinomega;\n                double s2 = Fun.Sin(t * omega) / sinomega;\n\n                result = new Rot3d(s1 * q1 + s2 * q3);\n            }\n            else if (cosomega > 0)\n            {\n                // omega == 0\n                double s1 = 1 - t;\n                double s2 = t;\n\n                result = new Rot3d(s1 * q1 + s2 * q3);\n            }\n            else\n            {\n                // omega == -pi\n                result = new Rot3d(q1.Z, -q1.Y, q1.X, -q1.W);\n\n                double s1 = Fun.Sin((0.5 - t) * Constant.Pi);\n                double s2 = Fun.Sin(t * Constant.Pi);\n\n                result = new Rot3d(s1 * q1 + s2 * result);\n            }\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Rot3d r0, Rot3d r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Rot3d r0, Rot3d r1, double tolerance)\n        {\n            return Rot.Distance(r0, r1) <= tolerance;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Rot3_template.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action and = () => Out(\" && \");\n    //# Action or = () => Out(\" || \");\n    //# Action andLit = () => Out(\" and \");\n    //# var qfields = new[] {\"W\", \"X\", \"Y\", \"Z\"};\n    //# var qfieldsL = new[] {\"w\", \"x\", \"y\", \"z\"};\n    //# foreach (var isDouble in new[] { false, true }) {\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Rot3\" + tc;\n    //#   var type2 = \"Rot3\" + tc2;\n    //#   var quatt = \"Quaternion\" + tc.ToUpper();\n    //#   var quatt2 = \"Quaternion\" + tc2.ToUpper();\n    //#   var v2t = \"V2\" + tc;\n    //#   var v3t = \"V3\" + tc;\n    //#   var v4t = \"V4\" + tc;\n    //#   var rot2t = \"Rot2\" + tc;\n    //#   var scale3t = \"Scale3\" + tc;\n    //#   var shift3t = \"Shift3\" + tc;\n    //#   var affine3t = \"Affine3\" + tc;\n    //#   var similarity3t = \"Similarity3\" + tc;\n    //#   var euclidean3t = \"Euclidean3\" + tc;\n    //#   var trafo3t = \"Trafo3\" + tc;\n    //#   var m22t = \"M22\" + tc;\n    //#   var m23t = \"M23\" + tc;\n    //#   var m33t = \"M33\" + tc;\n    //#   var m34t = \"M34\" + tc;\n    //#   var m44t = \"M44\" + tc;\n    //#   var assertEps = isDouble ? \"1e-10\" : \"1e-5f\";\n    //#   var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#   var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#   var piHalf = isDouble ? \"Constant.PiHalf\" : \"ConstantF.PiHalf\";\n    //#   var assertNorm = \"Debug.Assert(Fun.ApproximateEquals(NormSquared, 1, \" + assertEps + \"))\";\n    //#   var eps = isDouble ? \"1e-12\" : \"1e-5f\";\n    //#   var getptr = \"&\" + qfields[0];\n    #region __type__\n\n    /// <summary>\n    /// Represents a rotation in three dimensions using a unit quaternion.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>\n    {\n        /// <summary>\n        /// Scalar (real) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public __ftype__ W;\n\n        /// <summary>\n        /// First component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public __ftype__ X;\n\n        /// <summary>\n        /// Second component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public __ftype__ Y;\n\n        /// <summary>\n        /// Third component of vector (imaginary) part of the quaternion.\n        /// </summary>\n        [DataMember]\n        public __ftype__ Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from the quaternion (w, (x, y, z)).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ w, __ftype__ x, __ftype__ y, __ftype__ z)\n        {\n            W = w;\n            X = x; Y = y; Z = z;\n            __assertNorm__;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from the quaternion (w, (v.x, v.y, v.z)).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ w, __v3t__ v)\n        {\n            W = w;\n            X = v.X; Y = v.Y; Z = v.Z;\n            __assertNorm__;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from the quaternion <paramref name=\"q\"/>.\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__quatt__ q)\n        {\n            /*# qfields.ForEach(f => {*/__f__ = q.__f__; /*# });*/\n            __assertNorm__;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from the quaternion <paramref name=\"q\"/>.\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__quatt2__ q)\n        {\n            /*# qfields.ForEach(f => {*/__f__ = (__ftype__)q.__f__; /*# });*/\n            __assertNorm__;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ r)\n        {\n            /*# qfields.ForEach(f => {*/__f__ = r.__f__; /*# });*/\n            __assertNorm__;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a <see cref=\"__type2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ r)\n        {\n            /*# qfields.ForEach(f => {*/__f__ = (__ftype__)r.__f__; /*# });*/\n            __assertNorm__;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from the quaternion (a[0], (a[1], a[2], a[3])).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] a)\n        {\n            W = a[0];\n            X = a[1]; Y = a[2]; Z = a[3];\n            __assertNorm__;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from the quaternion (a[start], (a[start + 1], a[start + 2], a[start + 3])).\n        /// The quaternion must be of unit length.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] a, int start)\n        {\n            W = a[start];\n            X = a[start + 1]; Y = a[start + 2]; Z = a[start + 3];\n            __assertNorm__;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets or sets the vector part (x, y, z) of this <see cref=\"__type__\"/> unit quaternion.\n        /// </summary>\n        [XmlIgnore]\n        public __v3t__ V\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return new __v3t__(X, Y, Z); }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n\n        /// <summary>\n        /// Gets the squared norm (or squared length) of this <see cref=\"__type__\"/>.\n        /// May not be exactly 1, due to numerical inaccuracy.\n        /// </summary>\n        public readonly __ftype__ NormSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => /*# qfields.ForEach(f => {*/__f__ * __f__/*# }, add);*/;\n        }\n\n        /// <summary>\n        /// Gets the norm (or length) of this <see cref=\"__type__\"/>.\n        /// May not be exactly 1, due to numerical inaccuracy.\n        /// </summary>\n        public readonly __ftype__ Norm\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => NormSquared.Sqrt();\n        }\n\n        /// <summary>\n        /// Gets normalized (unit) quaternion from this <see cref=\"__type__\"/>\n        /// </summary>\n        public readonly __type__ Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var rs = new __type__(this);\n                rs.Normalize();\n                return rs;\n            }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public readonly __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                __assertNorm__;\n                return new __type__(W, -X, -Y, -Z);\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"__type__\"/>.\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(1, 0, 0, 0);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Returns the component-wise negation of a <see cref=\"__type__\"/> unit quaternion.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ q)\n            => new __type__(/*# qfields.ForEach(f => {*/-q.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Multiplies two <see cref=\"__type__\"/> transformations.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __type__ b)\n        {\n            return new __type__(\n                a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z,\n                a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,\n                a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,\n                a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X);\n        }\n\n        #region Rot / Vector Multiplication\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v3t__\"/> vector by a <see cref=\"__type__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ operator *(__type__ r, __v3t__ v)\n        {\n            var w = -r.X * v.X - r.Y * v.Y - r.Z * v.Z;\n            var x = r.W * v.X + r.Y * v.Z - r.Z * v.Y;\n            var y = r.W * v.Y + r.Z * v.X - r.X * v.Z;\n            var z = r.W * v.Z + r.X * v.Y - r.Y * v.X;\n\n            return new __v3t__(\n                -w * r.X + x * r.W - y * r.Z + z * r.Y,\n                -w * r.Y + y * r.W - z * r.X + x * r.Z,\n                -w * r.Z + z * r.W - x * r.Y + y * r.X);\n        }\n\n        #endregion\n\n        #region Rot / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a 3x3 matrix) with a <see cref=\"__m33t__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __m33t__ operator *(__type__ rot, __m33t__ m)\n        {\n            return (__m33t__)rot * m;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__m33t__\"/> with a <see cref=\"__type__\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __m33t__ operator *(__m33t__ m, __type__ rot)\n        {\n            return m * (__m33t__)rot;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a 4x4 matrix) with a <see cref=\"__m44t__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __m44t__ operator *(__type__ rot, __m44t__ m)\n        {\n            var r = (__m33t__)rot;\n            return new __m44t__(/*# 3.ForEach(i => { 4.ForEach(j => {*/\n                /*# 3.ForEach(k => {*/r.M__i____k__ * m.M__k____j__/*# }, add); }, comma); }, commaln);*/,\n\n                /*# 4.ForEach(j => {*/m.M__3____j__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__m44t__\"/> with a <see cref=\"__type__\"/> transformation (as a 4x4 matrix) .\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __m44t__ operator *(__m44t__ m, __type__ rot)\n        {\n            var r = (__m33t__)rot;\n            return new __m44t__(/*# 4.ForEach(i => { 3.ForEach(j => {*/\n                /*# 3.ForEach(k => {*/m.M__i____k__ * r.M__k____j__/*# }, add); }, comma);*/,\n                m.M__i____3__/*# }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a 3x3 matrix) with a <see cref=\"__m34t__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __m34t__ operator *(__type__ rot, __m34t__ m)\n        {\n            return (__m33t__)rot * m;\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__m34t__\"/> with a <see cref=\"__type__\"/> transformation (as a 4x4 matrix) .\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __m34t__ operator *(__m34t__ m, __type__ rot)\n        {\n            var r = (__m33t__)rot;\n            return new __m34t__(/*# 3.ForEach(i => { 3.ForEach(j => {*/\n                /*# 3.ForEach(k => {*/m.M__i____k__ * r.M__k____j__/*# }, add); }, comma);*/,\n                m.M__i____3__/*# }, commaln);*/);\n        }\n\n        #endregion\n\n        #region Rot / Quaternion arithmetics\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"__type__\"/> and a <see cref=\"__quatt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator +(__type__ r, __quatt__ q)\n            => new __quatt__(/*# qfields.ForEach(f => {*/r.__f__ + q.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"__quatt__\"/> and a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator +(__quatt__ q, __type__ r)\n            => new __quatt__(/*# qfields.ForEach(f => {*/q.__f__ + r.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the sum of a <see cref=\"__type__\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator +(__type__ r, __ftype__ s)\n            => new __quatt__(r.W + s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the sum of a real scalar and a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator +(__ftype__ s, __type__ r)\n            => new __quatt__(r.W + s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"__type__\"/> and a <see cref=\"__quatt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator -(__type__ r, __quatt__ q)\n            => new __quatt__(/*# qfields.ForEach(f => {*/r.__f__ - q.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"__quatt__\"/> and a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator -(__quatt__ q, __type__ r)\n            => new __quatt__(/*# qfields.ForEach(f => {*/q.__f__ - r.__f__/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the difference between a <see cref=\"__type__\"/> and a real scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator -(__type__ r, __ftype__ s)\n            => new __quatt__(r.W - s, r.X, r.Y, r.Z);\n\n        /// <summary>\n        /// Returns the difference between a real scalar and a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator -(__ftype__ s, __type__ r)\n            => new __quatt__(s - r.W, -r.X, -r.Y, -r.Z);\n\n        /// <summary>\n        /// Returns the product of a <see cref=\"__type__\"/> and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator *(__type__ r, __ftype__ s)\n            => new __quatt__(/*# qfields.ForEach(f => {*/r.__f__ * s/*# }, comma);*/);\n\n        /// <summary>\n        /// Returns the product of a scalar and a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator *(__ftype__ s, __type__ r)\n            => new __quatt__(/*# qfields.ForEach(f => {*/r.__f__ * s/*# }, comma);*/);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> with a <see cref=\"__quatt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator *(__type__ r, __quatt__ q)\n        {\n            return new __quatt__(\n                r.W * q.W - r.X * q.X - r.Y * q.Y - r.Z * q.Z,\n                r.W * q.X + r.X * q.W + r.Y * q.Z - r.Z * q.Y,\n                r.W * q.Y + r.Y * q.W + r.Z * q.X - r.X * q.Z,\n                r.W * q.Z + r.Z * q.W + r.X * q.Y - r.Y * q.X);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__quatt__\"/> with a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator *(__quatt__ q, __type__ r)\n        {\n            return new __quatt__(\n                q.W * r.W - q.X * r.X - q.Y * r.Y - q.Z * r.Z,\n                q.W * r.X + q.X * r.W + q.Y * r.Z - q.Z * r.Y,\n                q.W * r.Y + q.Y * r.W + q.Z * r.X - q.X * r.Z,\n                q.W * r.Z + q.Z * r.W + q.X * r.Y - q.Y * r.X);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"__type__\"/> by a <see cref=\"__quatt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator /(__type__ r, __quatt__ q)\n            => r * q.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"__quatt__\"/> by a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator /(__quatt__ q, __type__ r)\n            => q * r.Inverse;\n\n        /// <summary>\n        /// Divides a <see cref=\"__type__\"/> by a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator /(__type__ r, __ftype__ s)\n            => new __quatt__(/*# qfields.ForEach(f => {*/r.__f__ / s/*# }, comma);*/);\n\n        /// <summary>\n        /// Divides a scalar by a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __quatt__ operator /(__ftype__ s, __type__ r)\n            => new __quatt__(/*# qfields.ForEach(f => {*/s / r.__f__/*# }, comma);*/);\n\n        #endregion\n\n        #region Rot / Shift, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__shift3t__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __euclidean3t__ operator *(__type__ a, __shift3t__ b)\n            => new __euclidean3t__(a, a * b.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__scale3t__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affine3t__ operator *(__type__ a, __scale3t__ b)\n            => new __affine3t__((__m33t__)a * (__m33t__)b);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ r0, __type__ r1)\n            => Rot.Distance(r0, r1) == 0;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ r0, __type__ r1)\n            => !(r0 == r1);\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from an orthonormal basis.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromFrame(__v3t__ x, __v3t__ y, __v3t__ z)\n        {\n            return From__m33t__(__m33t__.FromCols(x, y, z));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a Rodrigues axis-angle vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromAngleAxis(__v3t__ angleAxis)\n        {\n            __ftype__ theta2 = angleAxis.LengthSquared;\n            if (theta2 > Constant<__ftype__>.PositiveTinyValue)\n            {\n                var theta = Fun.Sqrt(theta2);\n                var thetaHalf = theta / 2;\n                var k = Fun.Sin(thetaHalf) / theta;\n                return new __type__(Fun.Cos(thetaHalf), k * angleAxis);\n            }\n            else\n                return new __type__(1, 0, 0, 0);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a rotation matrix.\n        /// The matrix must be orthonormal.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        public static __type__ From__m33t__(__m33t__ m, __ftype__ epsilon = (__ftype__)1e-6)\n        {\n            if (!m.IsOrthonormal(epsilon)) throw new ArgumentException(\"Matrix is not orthonormal.\");\n            var tr = m.M00 + m.M11 + m.M22;\n\n            if (tr > 0)\n            {\n                __ftype__ s = (tr + 1).Sqrt() * 2;\n                __ftype__ x = (m.M21 - m.M12) / s;\n                __ftype__ y = (m.M02 - m.M20) / s;\n                __ftype__ z = (m.M10 - m.M01) / s;\n                __ftype__ w = s / 4;\n                return new __type__(new __quatt__(w, x, y, z).Normalized);\n            }\n            else if (m.M00 > m.M11 && m.M00 > m.M22)\n            {\n                __ftype__ s = Fun.Sqrt(1 + m.M00 - m.M11 - m.M22) * 2;\n                __ftype__ x = s / 4;\n                __ftype__ y = (m.M01 + m.M10) / s;\n                __ftype__ z = (m.M02 + m.M20) / s;\n                __ftype__ w = (m.M21 - m.M12) / s;\n                return new __type__(new __quatt__(w, x, y, z).Normalized);\n            }\n            else if (m.M11 > m.M22)\n            {\n                __ftype__ s = Fun.Sqrt(1 + m.M11 - m.M00 - m.M22) * 2;\n                __ftype__ x = (m.M01 + m.M10) / s;\n                __ftype__ y = s / 4;\n                __ftype__ z = (m.M12 + m.M21) / s;\n                __ftype__ w = (m.M02 - m.M20) / s;\n                return new __type__(new __quatt__(w, x, y, z).Normalized);\n            }\n            else\n            {\n                __ftype__ s = Fun.Sqrt(1 + m.M22 - m.M00 - m.M11) * 2;\n                __ftype__ x = (m.M02 + m.M20) / s;\n                __ftype__ y = (m.M12 + m.M21) / s;\n                __ftype__ z = s / 4;\n                __ftype__ w = (m.M10 - m.M01) / s;\n                return new __type__(new __quatt__(w, x, y, z).Normalized);\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__m44t__\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__m44t__(__m44t__ m, __ftype__ epsilon = __eps__)\n        {\n            if (!(/*#3.ForEach(j => {*/m.M3__j__.IsTiny(epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C3.XYZ.ApproximateEquals(__v3t__.Zero, epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return From__m33t__(((__m33t__)m) / m.M33);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__euclidean3t__\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__euclidean3t__(__euclidean3t__ euclidean, __ftype__ epsilon = __eps__)\n        {\n            if (!euclidean.Trans.ApproximateEquals(__v3t__.Zero, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains translational component\");\n\n            return euclidean.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__similarity3t__\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__similarity3t__(__similarity3t__ similarity, __ftype__ epsilon = __eps__)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Trans.ApproximateEquals(__v3t__.Zero, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            return similarity.Rot;\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from an <see cref=\"__affine3t__\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__affine3t__(__affine3t__ affine, __ftype__ epsilon = __eps__)\n            => From__m44t__((__m44t__)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__trafo3t__\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a rotation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__trafo3t__(__trafo3t__ trafo, __ftype__ epsilon = __eps__)\n            => From__m44t__(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation representing a rotation around\n        /// an axis by an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__v3t__ normalizedAxis, __ftype__ angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            var halfAngleSin = halfAngle.Sin();\n\n            return new __type__(halfAngle.Cos(), normalizedAxis * halfAngleSin);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation representing a rotation around\n        /// an axis by an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__v3t__ normalizedAxis, __ftype__ angleInDegrees)\n            => Rotation(normalizedAxis, angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation representing a rotation from one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotateInto(__v3t__ from, __v3t__ into)\n        {\n            var d = Vec.Dot(from, into);\n\n            if (d.ApproximateEquals(-1))\n                return new __type__(0, from.AxisAlignedNormal());\n            else\n            {\n                __quatt__ q = new __quatt__(d + 1, Vec.Cross(from, into));\n                return new __type__(q.Normalized);\n            }\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationX(__ftype__ angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new __type__(halfAngle.Cos(), new __v3t__(halfAngle.Sin(), 0, 0));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation by <paramref name=\"angleInDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationXInDegrees(__ftype__ angleInDegrees)\n            => RotationX(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationY(__ftype__ angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new __type__(halfAngle.Cos(), new __v3t__(0, halfAngle.Sin(), 0));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation by <paramref name=\"angleInDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationYInDegrees(__ftype__ angleInDegrees)\n            => RotationY(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation by <paramref name=\"angleInRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZ(__ftype__ angleInRadians)\n        {\n            var halfAngle = angleInRadians / 2;\n            return new __type__(halfAngle.Cos(), new __v3t__(0, 0, halfAngle.Sin()));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation by <paramref name=\"angleInDegrees\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZInDegrees(__ftype__ angleInDegrees)\n            => RotationZ(angleInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__ftype__ rollInRadians, __ftype__ pitchInRadians, __ftype__ yawInRadians)\n        {\n            __ftype__ rollHalf = rollInRadians / 2;\n            __ftype__ cr = Fun.Cos(rollHalf);\n            __ftype__ sr = Fun.Sin(rollHalf);\n            __ftype__ pitchHalf = pitchInRadians / 2;\n            __ftype__ cp = Fun.Cos(pitchHalf);\n            __ftype__ sp = Fun.Sin(pitchHalf);\n            __ftype__ yawHalf = yawInRadians / 2;\n            __ftype__ cy = Fun.Cos(yawHalf);\n            __ftype__ sy = Fun.Sin(yawHalf);\n\n            return new __type__(\n                cy * cp * cr + sy * sp * sr,\n                cy * cp * sr - sy * sp * cr,\n                sy * cp * sr + cy * sp * cr,\n                sy * cp * cr - cy * sp * sr);\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__ftype__ rollInDegrees, __ftype__ pitchInDegrees, __ftype__ yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__v3t__ rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__v3t__ rollPitchYawInDegrees)\n            => RotationEulerInDegrees(rollPitchYawInDegrees.X, rollPitchYawInDegrees.Y, rollPitchYawInDegrees.Z);\n\n        #endregion\n\n        #region Conversion\n\n        //# for (int n = 3; n <= 4; n++) {\n        //# for (int m = n; m <= (n+1) && m <= 4; m++) {\n        //#     var mat = \"M\" + n + m + tc;\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mat__(__type__ r)\n        {\n            //speed up by computing the multiplications only once (each is used 2 times below)\n            __ftype__ xx = r.X * r.X;\n            __ftype__ yy = r.Y * r.Y;\n            __ftype__ zz = r.Z * r.Z;\n            __ftype__ xy = r.X * r.Y;\n            __ftype__ xz = r.X * r.Z;\n            __ftype__ yz = r.Y * r.Z;\n            __ftype__ xw = r.X * r.W;\n            __ftype__ yw = r.Y * r.W;\n            __ftype__ zw = r.Z * r.W;\n            return new __mat__(\n                1 - 2 * (yy + zz),\n                2 * (xy - zw),\n                2 * (xz + yw),\n                /*# if (m == 4) {*/0,\n                /*# }*/\n                2 * (xy + zw),\n                1 - 2 * (zz + xx),\n                2 * (yz - xw),\n                /*# if (m == 4) {*/0,\n                /*# }*/\n                2 * (xz - yw),\n                2 * (yz + xw),\n                1 - 2 * (yy + xx)/*# if (m == 4) {*/,\n                0/*# } if (n == 4) {*/,\n\n                /*# m.ForEach(i => { var x = (i == m - 1) ? 1 : 0; */__x__/*# }, comma); }*/);\n        }\n\n        //# } }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __ftype__[](__type__ r)\n        {\n            __ftype__[] array = new __ftype__[__qfields.Length__];\n            /*# qfields.ForEach((f, i) => {*/array[__i__] = r.__f__;\n            /*# });*/return array;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __euclidean3t__(__type__ r)\n            => new __euclidean3t__(r, __v3t__.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __similarity3t__(__type__ r)\n            => new __similarity3t__(1, r, __v3t__.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __affine3t__(__type__ r)\n            => new __affine3t__((__m33t__)r);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __trafo3t__(__type__ r)\n            => new __trafo3t__((__m44t__)r, (__m44t__)r.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ r)\n            => new __type2__(/*# qfields.ForEach(f => {*/(__ftype2__)r.__f__/*# }, comma);*/);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __quatt__(__type__ r)\n            => new __quatt__(/*# qfields.ForEach(f => {*/r.__f__/*# }, comma);*/);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __quatt2__(__type__ r)\n            => new __quatt2__(/*# qfields.ForEach(f => {*/(__ftype2__)r.__f__/*# }, comma);*/);\n\n        #endregion\n\n        #region Indexing\n\n        /// <summary>\n        /// Gets or sets the <paramref name=\"i\"/>-th component of the <see cref=\"__type__\"/> unit quaternion with components (W, (X, Y, Z)).\n        /// </summary>\n        public unsafe __ftype__ this[int i]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (__ftype__* ptr = __getptr__) { return ptr[i]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (__ftype__* ptr = __getptr__) { ptr[i] = value; }\n            }\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(W, V);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Rot.Distance(this, other) == 0;\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", W, V);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__ftype__.Parse(x[0], CultureInfo.InvariantCulture), __v3t__.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Rot\n    {\n        #region Dot\n\n        /// <summary>\n        /// Returns the dot product of two <see cref=\"__type__\"/> unit quaternions.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Dot(this __type__ a, __type__ b)\n        {\n            return a.W * b.W + a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        #endregion\n\n        #region Distance\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"__type__\"/> rotations.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ DistanceFast(this __type__ r1, __type__ r2)\n        {\n            var d = Dot(r1, r2);\n            return 2 * Fun.AcosClamped((d < 0) ? -d : d);\n        }\n\n        /// <summary>\n        /// Returns the absolute difference in radians between two <see cref=\"__type__\"/> rotations\n        /// using a numerically stable algorithm.\n        /// The result is within the range of [0, Pi].\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Distance(this __type__ r1, __type__ r2)\n        {\n            var q = r1.Inverse * r2;\n            return 2 * Fun.Atan2(q.V.Length, (q.W < 0) ? -q.W : q.W);\n        }\n\n        #endregion\n\n        #region Invert, Normalize\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ r)\n            => r.Inverse;\n\n        /// <summary>\n        /// Inverts the given <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref __type__ r)\n        {\n            r.X = -r.X;\n            r.Y = -r.Y;\n            r.Z = -r.Z;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Normalized(__type__ r)\n            => r.Normalized;\n\n        /// <summary>\n        /// Normalizes a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref __type__ r)\n        {\n            var norm = r.Norm;\n            if (norm > 0)\n            {\n                var scale = 1 / norm;\n                /*# qfields.ForEach(f => {*/\n                r.__f__ *= scale;/*# });*/\n            }\n        }\n\n        #endregion\n\n        #region Conversion\n\n        /// <summary>\n        /// Returns the Rodrigues angle-axis vector of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ ToAngleAxis(this __type__ r)\n        {\n            var sinTheta2 = r.V.LengthSquared;\n            if (sinTheta2 > Constant<__ftype__>.PositiveTinyValue)\n            {\n                __ftype__ sinTheta = Fun.Sqrt(sinTheta2);\n                __ftype__ cosTheta = r.W;\n                __ftype__ twoTheta = 2 * (cosTheta < 0 ? Fun.Atan2(-sinTheta, -cosTheta)\n                                                    : Fun.Atan2(sinTheta, cosTheta));\n                return r.V * (twoTheta / sinTheta);\n            }\n            else\n                return __v3t__.Zero;\n        }\n\n        /// <summary>\n        /// Returns the axis-angle representation of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        /// <param name=\"r\">A <see cref=\"__type__\"/> transformation.</param>\n        /// <param name=\"axis\">Output of normalized axis of rotation.</param>\n        /// <param name=\"angleInRadians\">Output of angle of rotation in radians about axis (Right Hand Rule).</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void ToAxisAngle(this __type__ r, ref __v3t__ axis, ref __ftype__ angleInRadians)\n        {\n            angleInRadians = 2 * Fun.Acos(r.W);\n            var s = Fun.Sqrt(1 - r.W * r.W); // assuming quaternion normalised then w is less than 1, so term always positive.\n            if (s < 0.001)\n            { // test to avoid divide by zero, s is always positive due to sqrt\n                // if s close to zero then direction of axis not important\n                axis.X = r.X; // if it is important that axis is normalised then replace with x=1; y=z=0;\n                axis.Y = r.Y;\n                axis.Z = r.Z;\n            }\n            else\n            {\n                axis.X = r.X / s; // normalise axis\n                axis.Y = r.Y / s;\n                axis.Z = r.Z / s;\n            }\n        }\n\n        #endregion\n\n        #region Euler Angles\n\n        /// <summary>\n        /// Returns the Euler-Angles from the given <see cref=\"__type__\"/> as a <see cref=\"__v3t__\"/> vector.\n        /// The vector components represent [roll (X), pitch (Y), yaw (Z)] with rotation order is Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ GetEulerAngles(this __type__ r)\n        {\n            var test = r.W * r.Y - r.X * r.Z;\n            if (test > __half__ - Constant<__ftype__>.PositiveTinyValue) // singularity at north pole\n            {\n                return new __v3t__(\n                    2 * Fun.Atan2(r.X, r.W),\n                    __piHalf__,\n                    0);\n            }\n            if (test < -__half__ + Constant<__ftype__>.PositiveTinyValue) // singularity at south pole\n            {\n                return new __v3t__(\n                    2 * Fun.Atan2(r.X, r.W),\n                    -__piHalf__,\n                    0);\n            }\n            // From Wikipedia, conversion between quaternions and Euler angles.\n            return new __v3t__(\n                        Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                  1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                        Fun.AsinClamped(2 * test),\n                        Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                  1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v3t__\"/> vector by a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ Transform(this __type__ r, __v3t__ v)\n            => r * v;\n\n        /// <summary>\n        /// Transforms a <see cref=\"__v3t__\"/> vector by the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __v3t__ InvTransform(this __type__ r, __v3t__ v)\n        {\n            var w = r.X * v.X + r.Y * v.Y + r.Z * v.Z;\n            var x = r.W * v.X - r.Y * v.Z + r.Z * v.Y;\n            var y = r.W * v.Y - r.Z * v.X + r.X * v.Z;\n            var z = r.W * v.Z - r.X * v.Y + r.Y * v.X;\n\n            return new __v3t__(\n                w * r.X + x * r.W + y * r.Z - z * r.Y,\n                w * r.Y + y * r.W + z * r.X - x * r.Z,\n                w * r.Z + z * r.W + x * r.Y - y * r.X\n                );\n        }\n\n        #endregion\n\n        #region Spherical Linear Interpolation\n\n        /// <summary>\n        /// Spherical linear interpolation.\n        ///\n        /// Assumes q1 and q2 are normalized and that t in [0,1].\n        ///\n        /// This method interpolates along the shortest arc between q1 and q2.\n        /// </summary>\n        public static __type__ SlerpShortest(this __type__ q1, __type__ q2, __ftype__ t)\n        {\n            __type__ q3 = q2;\n            __ftype__ cosomega = Dot(q1, q3);\n\n            if (cosomega < 0)\n            {\n                cosomega = -cosomega;\n                q3 = -q3;\n            }\n\n            if (cosomega >= 1)\n            {\n                // Special case: q1 and q2 are the same, so just return one of them.\n                // This also catches the case where cosomega is very slightly > 1.0\n                return q1;\n            }\n\n            __ftype__ sinomega = Fun.Sqrt(1 - cosomega * cosomega);\n\n            __type__ result;\n\n            if (sinomega * __ftype__.MaxValue > 1)\n            {\n                __ftype__ omega = Fun.Acos(cosomega);\n                __ftype__ s1 = Fun.Sin((1 - t) * omega) / sinomega;\n                __ftype__ s2 = Fun.Sin(t * omega) / sinomega;\n\n                result = new __type__(s1 * q1 + s2 * q3);\n            }\n            else if (cosomega > 0)\n            {\n                // omega == 0\n                __ftype__ s1 = 1 - t;\n                __ftype__ s2 = t;\n\n                result = new __type__(s1 * q1 + s2 * q3);\n            }\n            else\n            {\n                // omega == -pi\n                result = new __type__(q1.Z, -q1.Y, q1.X, -q1.W);\n\n                __ftype__ s1 = Fun.Sin((__half__ - t) * __pi__);\n                __ftype__ s2 = Fun.Sin(t * __pi__);\n\n                result = new __type__(s1 * q1 + s2 * result);\n            }\n\n            return result;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ r0, __type__ r1)\n        {\n            return ApproximateEquals(r0, r1, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ r0, __type__ r1, __ftype__ tolerance)\n        {\n            return Rot.Distance(r0, r1) <= tolerance;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Scale_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    #region Scale2f\n\n    /// <summary>\n    /// A 2-dimensional scaling transform with different scaling values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Scale2f : IEquatable<Scale2f>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public V2f V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2f\"/> transformation from 2 floats.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2f(float sX, float sY)\n        {\n            V = new V2f(sX, sY);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2f\"/> from 2 scaling factors provided as <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2f(V2f scalingFactors)\n        {\n            V = scalingFactors;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2f\"/> transformation from a uniform float value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2f(float uniform)\n        {\n            V = new V2f(uniform, uniform);\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2f(Scale2f scale)\n        {\n            V = scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2f\"/> transformation from a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2f(Scale2d scale)\n        {\n            V = (V2f)scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2f\"/> transformation from a float-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2f(float[] array)\n        {\n            V = new V2f(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2f\"/> transformation from a float-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2f(float[] array, int start)\n        {\n            V = new V2f(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets and sets the X coordinate.\n        /// </summary>\n        public float X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.X = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Y coordinate.\n        /// </summary>\n        public float Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Y = value; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        public readonly Scale2f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2f(1 / X, 1 / Y);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        public static Scale2f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2f(1, 1);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale2f\"/> transformation with all components set to zero.\n        /// </summary>\n        public static Scale2f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2f(0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale2f\"/> transformation with scaling factors (1, 0).\n        /// </summary>\n        public static Scale2f XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2f(1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale2f\"/> transformation with scaling factors (0, 1).\n        /// </summary>\n        public static Scale2f YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2f(0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f operator -(Scale2f scale)\n        {\n            return new Scale2f(-scale.X, -scale.Y);\n        }\n\n        #region Scale / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation with a float scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f operator *(Scale2f scale, float scalar)\n        {\n            return new Scale2f(scale.X * scalar, scale.Y * scalar);\n        }\n\n        /// <summary>\n        /// Multiplies a float scalar with a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f operator *(float scalar, Scale2f scale)\n        {\n            return new Scale2f(scale.X * scalar, scale.Y * scalar);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Scale2f\"/> transformation by a float scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f operator /(Scale2f scale, float scalar)\n        {\n            return new Scale2f(scale.X / scalar, scale.Y / scalar);\n        }\n\n        /// <summary>\n        /// Divides a float scalar by a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f operator /(float scalar, Scale2f scale)\n        {\n            return new Scale2f(scalar / scale.X, scalar / scale.Y);\n        }\n\n        #endregion\n\n        #region Scale / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation with a <see cref=\"V2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(Scale2f scale, V2f vector)\n        {\n            return new V2f(vector.X * scale.X, vector.Y * scale.Y);\n        }\n\n        #endregion\n\n        #region Scale / Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation with a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f operator *(Scale2f a, Scale2f b)\n            => new Scale2f(a.X * b.X, a.Y * b.Y);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation with a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f operator *(Scale2f a, Scale3f b)\n            => new Scale3f(a.X * b.X, a.Y * b.Y, b.Z);\n\n        #endregion\n\n        #region Scale / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation (as a 2x2 matrix) with a <see cref=\"M22f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator *(Scale2f scale, M22f matrix)\n        {\n            return new M22f(\n                scale.X * matrix.M00, scale.X * matrix.M01, \n                scale.Y * matrix.M10, scale.Y * matrix.M11);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22f\"/> with a <see cref=\"Scale2f\"/> transformation (as a 2x2 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f operator *(M22f matrix, Scale2f scale)\n        {\n            return new M22f(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation (as a 2x2 matrix) with a <see cref=\"M23f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Scale2f scale, M23f matrix)\n        {\n            return new M23f(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23f\"/> with a <see cref=\"Scale2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M23f matrix, Scale2f scale)\n        {\n            return new M23f(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(Scale2f scale, M33f matrix)\n        {\n            return new M33f(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12, \n                matrix.M20, matrix.M21, matrix.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> with a <see cref=\"Scale2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(M33f matrix, Scale2f scale)\n        {\n            return new M33f(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12, \n                matrix.M20 * scale.X, matrix.M21 * scale.Y, matrix.M22);\n        }\n\n        #endregion\n\n        #region Scale / Rot, Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation with a <see cref=\"Rot2f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Scale2f a, Rot2f b)\n            => new Affine2f((M22f)a * (M22f)b);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> transformation with a <see cref=\"Shift2f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Scale2f a, Shift2f b)\n            => new Affine2f((M22f)a, a * b.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Scale2f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Scale2f s0, Scale2f s1)\n            => s0.X == s1.X && s0.Y == s1.Y;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Scale2f\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Scale2f s0, Scale2f s1)\n            => s0.X != s1.X || s0.Y != s1.Y;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2f\"/> transformation from a <see cref=\"M22f\"/> matrix.\n        /// The matrix must only contain scaling components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f FromM22f(M22f m, float epsilon = (float)1e-6)\n        {\n            if (!(Fun.IsTiny(m.C0 * V2f.OI, epsilon) && Fun.IsTiny(m.C1 * V2f.IO, epsilon)))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            return new Scale2f(m.M00, m.M11);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2f\"/> transformation from a scaling <see cref=\"M33f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f FromM33f(M33f m, float epsilon = (float)1e-6)\n        {\n            if (!(Fun.IsTiny(m.C0.XY * V2f.OI, epsilon) && Fun.IsTiny(m.C1.XY * V2f.IO, epsilon)))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C2.XY.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new Scale2f(m.M00 / m.M22, m.M11 / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2f\"/> transformation from a <see cref=\"Similarity2f\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f FromSimilarity2f(Similarity2f similarity, float epsilon = 1e-5f)\n        {\n            if (!similarity.Trans.IsTiny(epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            if (!similarity.Rot.ApproximateEquals(Rot2f.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new Scale2f(similarity.Scale);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2f\"/> transformation from an <see cref=\"Affine2f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f FromAffine2f(Affine2f affine, float epsilon = 1e-5f)\n            => FromM33f((M33f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2f\"/> transformation from a <see cref=\"Trafo2f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f FromTrafo2f(Trafo2f trafo, float epsilon = 1e-5f)\n            => FromM33f(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22f(Scale2f s)\n        {\n            return new M22f(\n                s.X, 0  , \n                0  , s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23f(Scale2f s)\n        {\n            return new M23f(\n                s.X, 0  , 0  , \n                0  , s.Y, 0  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Scale2f s)\n        {\n            return new M33f(\n                s.X, 0  , 0  , \n                0  , s.Y, 0  , \n                0  , 0  , 1  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Scale2f s)\n        {\n            return new M34f(\n                s.X, 0  , 0  , 0  , \n                0  , s.Y, 0  , 0  , \n                0  , 0  , 1  , 0  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Scale2f s)\n        {\n            return new M44f(\n                s.X, 0  , 0  , 0  , \n                0  , s.Y, 0  , 0  , \n                0  , 0  , 1  , 0  , \n                0  , 0  , 0  , 1  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2f(Scale2f s)\n            => new Affine2f((M22f)s, V2f.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2f(Scale2f s)\n            => new Trafo2f((M33f)s, (M33f)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Scale2d(Scale2f s)\n            => new Scale2d((V2d)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"Scale2f\"/> instance\n        /// in a float[] array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](Scale2f s)\n            => (float[])s.V;\n\n        #endregion\n\n        #region Indexing\n\n        public float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Scale2f other)\n            => X.Equals(other.X) && Y.Equals(other.Y);\n\n        public override readonly bool Equals(object other)\n            => (other is Scale2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", X, Y);\n        }\n\n        public static Scale2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Scale2f(\n                float.Parse(x[0], CultureInfo.InvariantCulture), \n                float.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Scale\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2f Inverse(Scale2f scale)\n            => scale.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Scale2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Scale2f scale)\n        {\n            scale.V.X = 1 / scale.V.X;\n            scale.V.Y = 1 / scale.V.Y;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> vector by a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Transform(this Scale2f s, V2f v)\n            => new V2f(v.X * s.X, v.Y * s.Y);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> vector by the inverse of a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransform(this Scale2f s, V2f v)\n            => new V2f(v.X / s.X, v.Y / s.Y);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Scale2f\"/> transformation.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Scale2f s, V3f v)\n            => new V3f(v.X * s.X, v.Y * s.Y, v.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by the inverse of a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransform(this Scale2f s, V3f v)\n            => new V3f(v.X / s.X, v.Y / s.Y, v.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by a <see cref=\"Scale2f\"/> transformation.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Scale2f s, V4f v)\n            => new V4f(v.X * s.X, v.Y * s.Y, v.Z, v.W);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by the inverse of a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f InvTransform(this Scale2f s, V4f v)\n            => new V4f(v.X / s.X, v.Y / s.Y, v.Z, v.W);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Scale2f s0, Scale2f s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Scale2f s0, Scale2f s1, float tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Scale3f\n\n    /// <summary>\n    /// A 3-dimensional scaling transform with different scaling values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Scale3f : IEquatable<Scale3f>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public V3f V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3f\"/> transformation from 3 floats.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3f(float sX, float sY, float sZ)\n        {\n            V = new V3f(sX, sY, sZ);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3f\"/> from 3 scaling factors provided as <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3f(V3f scalingFactors)\n        {\n            V = scalingFactors;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3f\"/> transformation from a uniform float value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3f(float uniform)\n        {\n            V = new V3f(uniform, uniform, uniform);\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3f(Scale3f scale)\n        {\n            V = scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3f\"/> transformation from a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3f(Scale3d scale)\n        {\n            V = (V3f)scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3f\"/> transformation from a float-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3f(float[] array)\n        {\n            V = new V3f(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3f\"/> transformation from a float-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3f(float[] array, int start)\n        {\n            V = new V3f(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets and sets the X coordinate.\n        /// </summary>\n        public float X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.X = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Y coordinate.\n        /// </summary>\n        public float Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Y = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Z coordinate.\n        /// </summary>\n        public float Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Z; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Z = value; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        public readonly Scale3f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3f(1 / X, 1 / Y, 1 / Z);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        public static Scale3f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3f(1, 1, 1);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale3f\"/> transformation with all components set to zero.\n        /// </summary>\n        public static Scale3f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3f(0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale3f\"/> transformation with scaling factors (1, 0, 0).\n        /// </summary>\n        public static Scale3f XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3f(1, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale3f\"/> transformation with scaling factors (0, 1, 0).\n        /// </summary>\n        public static Scale3f YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3f(0, 1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale3f\"/> transformation with scaling factors (0, 0, 1).\n        /// </summary>\n        public static Scale3f ZAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3f(0, 0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f operator -(Scale3f scale)\n        {\n            return new Scale3f(-scale.X, -scale.Y, -scale.Z);\n        }\n\n        #region Scale / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation with a float scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f operator *(Scale3f scale, float scalar)\n        {\n            return new Scale3f(scale.X * scalar, scale.Y * scalar, scale.Z * scalar);\n        }\n\n        /// <summary>\n        /// Multiplies a float scalar with a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f operator *(float scalar, Scale3f scale)\n        {\n            return new Scale3f(scale.X * scalar, scale.Y * scalar, scale.Z * scalar);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Scale3f\"/> transformation by a float scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f operator /(Scale3f scale, float scalar)\n        {\n            return new Scale3f(scale.X / scalar, scale.Y / scalar, scale.Z / scalar);\n        }\n\n        /// <summary>\n        /// Divides a float scalar by a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f operator /(float scalar, Scale3f scale)\n        {\n            return new Scale3f(scalar / scale.X, scalar / scale.Y, scalar / scale.Z);\n        }\n\n        #endregion\n\n        #region Scale / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation with a <see cref=\"V3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(Scale3f scale, V3f vector)\n        {\n            return new V3f(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z);\n        }\n\n        #endregion\n\n        #region Scale / Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation with a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f operator *(Scale3f a, Scale2f b)\n            => new Scale3f(a.X * b.X, a.Y * b.Y, a.Z);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation with a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f operator *(Scale3f a, Scale3f b)\n            => new Scale3f(a.X * b.X, a.Y * b.Y, a.Z * b.Z);\n\n        #endregion\n\n        #region Scale / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(Scale3f scale, M33f matrix)\n        {\n            return new M33f(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12, \n                scale.Z * matrix.M20, scale.Z * matrix.M21, scale.Z * matrix.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> with a <see cref=\"Scale3f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(M33f matrix, Scale3f scale)\n        {\n            return new M33f(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02 * scale.Z, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12 * scale.Z, \n                matrix.M20 * scale.X, matrix.M21 * scale.Y, matrix.M22 * scale.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M34f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Scale3f scale, M34f matrix)\n        {\n            return new M34f(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, scale.X * matrix.M03, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12, scale.Y * matrix.M13, \n                scale.Z * matrix.M20, scale.Z * matrix.M21, scale.Z * matrix.M22, scale.Z * matrix.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34f\"/> with a <see cref=\"Scale3f\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M34f matrix, Scale3f scale)\n        {\n            return new M34f(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02 * scale.Z, matrix.M03, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12 * scale.Z, matrix.M13, \n                matrix.M20 * scale.X, matrix.M21 * scale.Y, matrix.M22 * scale.Z, matrix.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(Scale3f scale, M44f matrix)\n        {\n            return new M44f(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, scale.X * matrix.M03, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12, scale.Y * matrix.M13, \n                scale.Z * matrix.M20, scale.Z * matrix.M21, scale.Z * matrix.M22, scale.Z * matrix.M23, \n                matrix.M30, matrix.M31, matrix.M32, matrix.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44f\"/> with a <see cref=\"Scale3f\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(M44f matrix, Scale3f scale)\n        {\n            return new M44f(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02 * scale.Z, matrix.M03, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12 * scale.Z, matrix.M13, \n                matrix.M20 * scale.X, matrix.M21 * scale.Y, matrix.M22 * scale.Z, matrix.M23, \n                matrix.M30 * scale.X, matrix.M31 * scale.Y, matrix.M32 * scale.Z, matrix.M33);\n        }\n\n        #endregion\n\n        #region Scale / Rot, Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation with a <see cref=\"Rot3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Scale3f a, Rot3f b)\n            => new Affine3f((M33f)a * (M33f)b);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> transformation with a <see cref=\"Shift3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Scale3f a, Shift3f b)\n            => new Affine3f((M33f)a, a * b.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Scale3f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Scale3f s0, Scale3f s1)\n            => s0.X == s1.X && s0.Y == s1.Y && s0.Z == s1.Z;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Scale3f\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Scale3f s0, Scale3f s1)\n            => s0.X != s1.X || s0.Y != s1.Y || s0.Z != s1.Z;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3f\"/> transformation from a <see cref=\"M33f\"/> matrix.\n        /// The matrix must only contain scaling components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f FromM33f(M33f m, float epsilon = (float)1e-6)\n        {\n            if (!(Fun.IsTiny(m.C0 * V3f.OII, epsilon) && Fun.IsTiny(m.C1 * V3f.IOI, epsilon) && Fun.IsTiny(m.C2 * V3f.IIO, epsilon)))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            return new Scale3f(m.M00, m.M11, m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3f\"/> transformation from a scaling <see cref=\"M44f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f FromM44f(M44f m, float epsilon = (float)1e-6)\n        {\n            if (!(Fun.IsTiny(m.C0.XYZ * V3f.OII, epsilon) && Fun.IsTiny(m.C1.XYZ * V3f.IOI, epsilon) && Fun.IsTiny(m.C2.XYZ * V3f.IIO, epsilon)))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C3.XYZ.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new Scale3f(m.M00 / m.M33, m.M11 / m.M33, m.M22 / m.M33);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3f\"/> transformation from a <see cref=\"Similarity3f\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f FromSimilarity3f(Similarity3f similarity, float epsilon = 1e-5f)\n        {\n            if (!similarity.Trans.IsTiny(epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            if (!similarity.Rot.ApproximateEquals(Rot3f.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new Scale3f(similarity.Scale);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3f\"/> transformation from an <see cref=\"Affine3f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f FromAffine3f(Affine3f affine, float epsilon = 1e-5f)\n            => FromM44f((M44f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3f\"/> transformation from a <see cref=\"Trafo3f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f FromTrafo3f(Trafo3f trafo, float epsilon = 1e-5f)\n            => FromM44f(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22f(Scale3f s)\n        {\n            return new M22f(\n                s.X, 0  , \n                0  , s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23f(Scale3f s)\n        {\n            return new M23f(\n                s.X, 0  , 0  , \n                0  , s.Y, 0  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Scale3f s)\n        {\n            return new M33f(\n                s.X, 0  , 0  , \n                0  , s.Y, 0  , \n                0  , 0  , s.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Scale3f s)\n        {\n            return new M34f(\n                s.X, 0  , 0  , 0  , \n                0  , s.Y, 0  , 0  , \n                0  , 0  , s.Z, 0  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Scale3f s)\n        {\n            return new M44f(\n                s.X, 0  , 0  , 0  , \n                0  , s.Y, 0  , 0  , \n                0  , 0  , s.Z, 0  , \n                0  , 0  , 0  , 1  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3f(Scale3f s)\n            => new Affine3f((M33f)s, V3f.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3f(Scale3f s)\n            => new Trafo3f((M44f)s, (M44f)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Scale3d(Scale3f s)\n            => new Scale3d((V3d)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"Scale3f\"/> instance\n        /// in a float[] array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](Scale3f s)\n            => (float[])s.V;\n\n        #endregion\n\n        #region Indexing\n\n        public float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Scale3f other)\n            => X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n\n        public override readonly bool Equals(object other)\n            => (other is Scale3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", X, Y, Z);\n        }\n\n        public static Scale3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Scale3f(\n                float.Parse(x[0], CultureInfo.InvariantCulture), \n                float.Parse(x[1], CultureInfo.InvariantCulture), \n                float.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Scale\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3f Inverse(Scale3f scale)\n            => scale.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Scale3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Scale3f scale)\n        {\n            scale.V.X = 1 / scale.V.X;\n            scale.V.Y = 1 / scale.V.Y;\n            scale.V.Z = 1 / scale.V.Z;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Scale3f s, V3f v)\n            => new V3f(v.X * s.X, v.Y * s.Y, v.Z * s.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by the inverse of a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransform(this Scale3f s, V3f v)\n            => new V3f(v.X / s.X, v.Y / s.Y, v.Z / s.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by a <see cref=\"Scale3f\"/> transformation.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Scale3f s, V4f v)\n            => new V4f(v.X * s.X, v.Y * s.Y, v.Z * s.Z, v.W);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by the inverse of a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f InvTransform(this Scale3f s, V4f v)\n            => new V4f(v.X / s.X, v.Y / s.Y, v.Z / s.Z, v.W);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Scale3f s0, Scale3f s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Scale3f s0, Scale3f s1, float tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Scale2d\n\n    /// <summary>\n    /// A 2-dimensional scaling transform with different scaling values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Scale2d : IEquatable<Scale2d>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public V2d V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2d\"/> transformation from 2 doubles.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2d(double sX, double sY)\n        {\n            V = new V2d(sX, sY);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2d\"/> from 2 scaling factors provided as <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2d(V2d scalingFactors)\n        {\n            V = scalingFactors;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2d\"/> transformation from a uniform double value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2d(double uniform)\n        {\n            V = new V2d(uniform, uniform);\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2d(Scale2d scale)\n        {\n            V = scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2d\"/> transformation from a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2d(Scale2f scale)\n        {\n            V = (V2d)scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2d\"/> transformation from a double-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2d(double[] array)\n        {\n            V = new V2d(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale2d\"/> transformation from a double-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale2d(double[] array, int start)\n        {\n            V = new V2d(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets and sets the X coordinate.\n        /// </summary>\n        public double X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.X = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Y coordinate.\n        /// </summary>\n        public double Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Y = value; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        public readonly Scale2d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2d(1 / X, 1 / Y);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        public static Scale2d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2d(1, 1);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale2d\"/> transformation with all components set to zero.\n        /// </summary>\n        public static Scale2d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2d(0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale2d\"/> transformation with scaling factors (1, 0).\n        /// </summary>\n        public static Scale2d XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2d(1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale2d\"/> transformation with scaling factors (0, 1).\n        /// </summary>\n        public static Scale2d YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale2d(0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d operator -(Scale2d scale)\n        {\n            return new Scale2d(-scale.X, -scale.Y);\n        }\n\n        #region Scale / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation with a double scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d operator *(Scale2d scale, double scalar)\n        {\n            return new Scale2d(scale.X * scalar, scale.Y * scalar);\n        }\n\n        /// <summary>\n        /// Multiplies a double scalar with a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d operator *(double scalar, Scale2d scale)\n        {\n            return new Scale2d(scale.X * scalar, scale.Y * scalar);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Scale2d\"/> transformation by a double scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d operator /(Scale2d scale, double scalar)\n        {\n            return new Scale2d(scale.X / scalar, scale.Y / scalar);\n        }\n\n        /// <summary>\n        /// Divides a double scalar by a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d operator /(double scalar, Scale2d scale)\n        {\n            return new Scale2d(scalar / scale.X, scalar / scale.Y);\n        }\n\n        #endregion\n\n        #region Scale / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation with a <see cref=\"V2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(Scale2d scale, V2d vector)\n        {\n            return new V2d(vector.X * scale.X, vector.Y * scale.Y);\n        }\n\n        #endregion\n\n        #region Scale / Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation with a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d operator *(Scale2d a, Scale2d b)\n            => new Scale2d(a.X * b.X, a.Y * b.Y);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation with a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d operator *(Scale2d a, Scale3d b)\n            => new Scale3d(a.X * b.X, a.Y * b.Y, b.Z);\n\n        #endregion\n\n        #region Scale / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation (as a 2x2 matrix) with a <see cref=\"M22d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator *(Scale2d scale, M22d matrix)\n        {\n            return new M22d(\n                scale.X * matrix.M00, scale.X * matrix.M01, \n                scale.Y * matrix.M10, scale.Y * matrix.M11);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22d\"/> with a <see cref=\"Scale2d\"/> transformation (as a 2x2 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d operator *(M22d matrix, Scale2d scale)\n        {\n            return new M22d(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation (as a 2x2 matrix) with a <see cref=\"M23d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Scale2d scale, M23d matrix)\n        {\n            return new M23d(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23d\"/> with a <see cref=\"Scale2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M23d matrix, Scale2d scale)\n        {\n            return new M23d(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(Scale2d scale, M33d matrix)\n        {\n            return new M33d(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12, \n                matrix.M20, matrix.M21, matrix.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> with a <see cref=\"Scale2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(M33d matrix, Scale2d scale)\n        {\n            return new M33d(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12, \n                matrix.M20 * scale.X, matrix.M21 * scale.Y, matrix.M22);\n        }\n\n        #endregion\n\n        #region Scale / Rot, Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation with a <see cref=\"Rot2d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Scale2d a, Rot2d b)\n            => new Affine2d((M22d)a * (M22d)b);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> transformation with a <see cref=\"Shift2d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Scale2d a, Shift2d b)\n            => new Affine2d((M22d)a, a * b.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Scale2d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Scale2d s0, Scale2d s1)\n            => s0.X == s1.X && s0.Y == s1.Y;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Scale2d\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Scale2d s0, Scale2d s1)\n            => s0.X != s1.X || s0.Y != s1.Y;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2d\"/> transformation from a <see cref=\"M22d\"/> matrix.\n        /// The matrix must only contain scaling components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d FromM22d(M22d m, double epsilon = (double)1e-6)\n        {\n            if (!(Fun.IsTiny(m.C0 * V2d.OI, epsilon) && Fun.IsTiny(m.C1 * V2d.IO, epsilon)))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            return new Scale2d(m.M00, m.M11);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2d\"/> transformation from a scaling <see cref=\"M33d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d FromM33d(M33d m, double epsilon = (double)1e-6)\n        {\n            if (!(Fun.IsTiny(m.C0.XY * V2d.OI, epsilon) && Fun.IsTiny(m.C1.XY * V2d.IO, epsilon)))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C2.XY.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new Scale2d(m.M00 / m.M22, m.M11 / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2d\"/> transformation from a <see cref=\"Similarity2d\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d FromSimilarity2d(Similarity2d similarity, double epsilon = 1e-12)\n        {\n            if (!similarity.Trans.IsTiny(epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            if (!similarity.Rot.ApproximateEquals(Rot2d.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new Scale2d(similarity.Scale);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2d\"/> transformation from an <see cref=\"Affine2d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d FromAffine2d(Affine2d affine, double epsilon = 1e-12)\n            => FromM33d((M33d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale2d\"/> transformation from a <see cref=\"Trafo2d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d FromTrafo2d(Trafo2d trafo, double epsilon = 1e-12)\n            => FromM33d(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22d(Scale2d s)\n        {\n            return new M22d(\n                s.X, 0  , \n                0  , s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23d(Scale2d s)\n        {\n            return new M23d(\n                s.X, 0  , 0  , \n                0  , s.Y, 0  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Scale2d s)\n        {\n            return new M33d(\n                s.X, 0  , 0  , \n                0  , s.Y, 0  , \n                0  , 0  , 1  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Scale2d s)\n        {\n            return new M34d(\n                s.X, 0  , 0  , 0  , \n                0  , s.Y, 0  , 0  , \n                0  , 0  , 1  , 0  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Scale2d s)\n        {\n            return new M44d(\n                s.X, 0  , 0  , 0  , \n                0  , s.Y, 0  , 0  , \n                0  , 0  , 1  , 0  , \n                0  , 0  , 0  , 1  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2d(Scale2d s)\n            => new Affine2d((M22d)s, V2d.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2d(Scale2d s)\n            => new Trafo2d((M33d)s, (M33d)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Scale2f(Scale2d s)\n            => new Scale2f((V2f)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"Scale2d\"/> instance\n        /// in a double[] array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](Scale2d s)\n            => (double[])s.V;\n\n        #endregion\n\n        #region Indexing\n\n        public double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Scale2d other)\n            => X.Equals(other.X) && Y.Equals(other.Y);\n\n        public override readonly bool Equals(object other)\n            => (other is Scale2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", X, Y);\n        }\n\n        public static Scale2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Scale2d(\n                double.Parse(x[0], CultureInfo.InvariantCulture), \n                double.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Scale\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale2d Inverse(Scale2d scale)\n            => scale.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Scale2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Scale2d scale)\n        {\n            scale.V.X = 1 / scale.V.X;\n            scale.V.Y = 1 / scale.V.Y;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> vector by a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Transform(this Scale2d s, V2d v)\n            => new V2d(v.X * s.X, v.Y * s.Y);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> vector by the inverse of a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransform(this Scale2d s, V2d v)\n            => new V2d(v.X / s.X, v.Y / s.Y);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Scale2d\"/> transformation.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Scale2d s, V3d v)\n            => new V3d(v.X * s.X, v.Y * s.Y, v.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by the inverse of a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransform(this Scale2d s, V3d v)\n            => new V3d(v.X / s.X, v.Y / s.Y, v.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by a <see cref=\"Scale2d\"/> transformation.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Scale2d s, V4d v)\n            => new V4d(v.X * s.X, v.Y * s.Y, v.Z, v.W);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by the inverse of a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvTransform(this Scale2d s, V4d v)\n            => new V4d(v.X / s.X, v.Y / s.Y, v.Z, v.W);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Scale2d s0, Scale2d s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Scale2d s0, Scale2d s1, double tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Scale3d\n\n    /// <summary>\n    /// A 3-dimensional scaling transform with different scaling values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Scale3d : IEquatable<Scale3d>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public V3d V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3d\"/> transformation from 3 doubles.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3d(double sX, double sY, double sZ)\n        {\n            V = new V3d(sX, sY, sZ);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3d\"/> from 3 scaling factors provided as <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3d(V3d scalingFactors)\n        {\n            V = scalingFactors;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3d\"/> transformation from a uniform double value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3d(double uniform)\n        {\n            V = new V3d(uniform, uniform, uniform);\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3d(Scale3d scale)\n        {\n            V = scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3d\"/> transformation from a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3d(Scale3f scale)\n        {\n            V = (V3d)scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3d\"/> transformation from a double-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3d(double[] array)\n        {\n            V = new V3d(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Scale3d\"/> transformation from a double-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Scale3d(double[] array, int start)\n        {\n            V = new V3d(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets and sets the X coordinate.\n        /// </summary>\n        public double X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.X = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Y coordinate.\n        /// </summary>\n        public double Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Y = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Z coordinate.\n        /// </summary>\n        public double Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Z; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Z = value; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        public readonly Scale3d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3d(1 / X, 1 / Y, 1 / Z);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        public static Scale3d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3d(1, 1, 1);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale3d\"/> transformation with all components set to zero.\n        /// </summary>\n        public static Scale3d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3d(0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale3d\"/> transformation with scaling factors (1, 0, 0).\n        /// </summary>\n        public static Scale3d XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3d(1, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale3d\"/> transformation with scaling factors (0, 1, 0).\n        /// </summary>\n        public static Scale3d YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3d(0, 1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Scale3d\"/> transformation with scaling factors (0, 0, 1).\n        /// </summary>\n        public static Scale3d ZAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Scale3d(0, 0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d operator -(Scale3d scale)\n        {\n            return new Scale3d(-scale.X, -scale.Y, -scale.Z);\n        }\n\n        #region Scale / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation with a double scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d operator *(Scale3d scale, double scalar)\n        {\n            return new Scale3d(scale.X * scalar, scale.Y * scalar, scale.Z * scalar);\n        }\n\n        /// <summary>\n        /// Multiplies a double scalar with a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d operator *(double scalar, Scale3d scale)\n        {\n            return new Scale3d(scale.X * scalar, scale.Y * scalar, scale.Z * scalar);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Scale3d\"/> transformation by a double scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d operator /(Scale3d scale, double scalar)\n        {\n            return new Scale3d(scale.X / scalar, scale.Y / scalar, scale.Z / scalar);\n        }\n\n        /// <summary>\n        /// Divides a double scalar by a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d operator /(double scalar, Scale3d scale)\n        {\n            return new Scale3d(scalar / scale.X, scalar / scale.Y, scalar / scale.Z);\n        }\n\n        #endregion\n\n        #region Scale / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation with a <see cref=\"V3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(Scale3d scale, V3d vector)\n        {\n            return new V3d(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z);\n        }\n\n        #endregion\n\n        #region Scale / Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation with a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d operator *(Scale3d a, Scale2d b)\n            => new Scale3d(a.X * b.X, a.Y * b.Y, a.Z);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation with a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d operator *(Scale3d a, Scale3d b)\n            => new Scale3d(a.X * b.X, a.Y * b.Y, a.Z * b.Z);\n\n        #endregion\n\n        #region Scale / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(Scale3d scale, M33d matrix)\n        {\n            return new M33d(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12, \n                scale.Z * matrix.M20, scale.Z * matrix.M21, scale.Z * matrix.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> with a <see cref=\"Scale3d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(M33d matrix, Scale3d scale)\n        {\n            return new M33d(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02 * scale.Z, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12 * scale.Z, \n                matrix.M20 * scale.X, matrix.M21 * scale.Y, matrix.M22 * scale.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M34d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Scale3d scale, M34d matrix)\n        {\n            return new M34d(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, scale.X * matrix.M03, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12, scale.Y * matrix.M13, \n                scale.Z * matrix.M20, scale.Z * matrix.M21, scale.Z * matrix.M22, scale.Z * matrix.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34d\"/> with a <see cref=\"Scale3d\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M34d matrix, Scale3d scale)\n        {\n            return new M34d(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02 * scale.Z, matrix.M03, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12 * scale.Z, matrix.M13, \n                matrix.M20 * scale.X, matrix.M21 * scale.Y, matrix.M22 * scale.Z, matrix.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(Scale3d scale, M44d matrix)\n        {\n            return new M44d(\n                scale.X * matrix.M00, scale.X * matrix.M01, scale.X * matrix.M02, scale.X * matrix.M03, \n                scale.Y * matrix.M10, scale.Y * matrix.M11, scale.Y * matrix.M12, scale.Y * matrix.M13, \n                scale.Z * matrix.M20, scale.Z * matrix.M21, scale.Z * matrix.M22, scale.Z * matrix.M23, \n                matrix.M30, matrix.M31, matrix.M32, matrix.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44d\"/> with a <see cref=\"Scale3d\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(M44d matrix, Scale3d scale)\n        {\n            return new M44d(\n                matrix.M00 * scale.X, matrix.M01 * scale.Y, matrix.M02 * scale.Z, matrix.M03, \n                matrix.M10 * scale.X, matrix.M11 * scale.Y, matrix.M12 * scale.Z, matrix.M13, \n                matrix.M20 * scale.X, matrix.M21 * scale.Y, matrix.M22 * scale.Z, matrix.M23, \n                matrix.M30 * scale.X, matrix.M31 * scale.Y, matrix.M32 * scale.Z, matrix.M33);\n        }\n\n        #endregion\n\n        #region Scale / Rot, Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation with a <see cref=\"Rot3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Scale3d a, Rot3d b)\n            => new Affine3d((M33d)a * (M33d)b);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> transformation with a <see cref=\"Shift3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Scale3d a, Shift3d b)\n            => new Affine3d((M33d)a, a * b.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Scale3d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Scale3d s0, Scale3d s1)\n            => s0.X == s1.X && s0.Y == s1.Y && s0.Z == s1.Z;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Scale3d\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Scale3d s0, Scale3d s1)\n            => s0.X != s1.X || s0.Y != s1.Y || s0.Z != s1.Z;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3d\"/> transformation from a <see cref=\"M33d\"/> matrix.\n        /// The matrix must only contain scaling components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d FromM33d(M33d m, double epsilon = (double)1e-6)\n        {\n            if (!(Fun.IsTiny(m.C0 * V3d.OII, epsilon) && Fun.IsTiny(m.C1 * V3d.IOI, epsilon) && Fun.IsTiny(m.C2 * V3d.IIO, epsilon)))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            return new Scale3d(m.M00, m.M11, m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3d\"/> transformation from a scaling <see cref=\"M44d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d FromM44d(M44d m, double epsilon = (double)1e-6)\n        {\n            if (!(Fun.IsTiny(m.C0.XYZ * V3d.OII, epsilon) && Fun.IsTiny(m.C1.XYZ * V3d.IOI, epsilon) && Fun.IsTiny(m.C2.XYZ * V3d.IIO, epsilon)))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C3.XYZ.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new Scale3d(m.M00 / m.M33, m.M11 / m.M33, m.M22 / m.M33);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3d\"/> transformation from a <see cref=\"Similarity3d\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d FromSimilarity3d(Similarity3d similarity, double epsilon = 1e-12)\n        {\n            if (!similarity.Trans.IsTiny(epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            if (!similarity.Rot.ApproximateEquals(Rot3d.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new Scale3d(similarity.Scale);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3d\"/> transformation from an <see cref=\"Affine3d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d FromAffine3d(Affine3d affine, double epsilon = 1e-12)\n            => FromM44d((M44d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Scale3d\"/> transformation from a <see cref=\"Trafo3d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d FromTrafo3d(Trafo3d trafo, double epsilon = 1e-12)\n            => FromM44d(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22d(Scale3d s)\n        {\n            return new M22d(\n                s.X, 0  , \n                0  , s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23d(Scale3d s)\n        {\n            return new M23d(\n                s.X, 0  , 0  , \n                0  , s.Y, 0  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Scale3d s)\n        {\n            return new M33d(\n                s.X, 0  , 0  , \n                0  , s.Y, 0  , \n                0  , 0  , s.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Scale3d s)\n        {\n            return new M34d(\n                s.X, 0  , 0  , 0  , \n                0  , s.Y, 0  , 0  , \n                0  , 0  , s.Z, 0  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Scale3d s)\n        {\n            return new M44d(\n                s.X, 0  , 0  , 0  , \n                0  , s.Y, 0  , 0  , \n                0  , 0  , s.Z, 0  , \n                0  , 0  , 0  , 1  );\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3d(Scale3d s)\n            => new Affine3d((M33d)s, V3d.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3d(Scale3d s)\n            => new Trafo3d((M44d)s, (M44d)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Scale3f(Scale3d s)\n            => new Scale3f((V3f)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"Scale3d\"/> instance\n        /// in a double[] array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](Scale3d s)\n            => (double[])s.V;\n\n        #endregion\n\n        #region Indexing\n\n        public double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Scale3d other)\n            => X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n\n        public override readonly bool Equals(object other)\n            => (other is Scale3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", X, Y, Z);\n        }\n\n        public static Scale3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Scale3d(\n                double.Parse(x[0], CultureInfo.InvariantCulture), \n                double.Parse(x[1], CultureInfo.InvariantCulture), \n                double.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Scale\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Scale3d Inverse(Scale3d scale)\n            => scale.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Scale3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Scale3d scale)\n        {\n            scale.V.X = 1 / scale.V.X;\n            scale.V.Y = 1 / scale.V.Y;\n            scale.V.Z = 1 / scale.V.Z;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Scale3d s, V3d v)\n            => new V3d(v.X * s.X, v.Y * s.Y, v.Z * s.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by the inverse of a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransform(this Scale3d s, V3d v)\n            => new V3d(v.X / s.X, v.Y / s.Y, v.Z / s.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by a <see cref=\"Scale3d\"/> transformation.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Scale3d s, V4d v)\n            => new V4d(v.X * s.X, v.Y * s.Y, v.Z * s.Z, v.W);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by the inverse of a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvTransform(this Scale3d s, V4d v)\n            => new V4d(v.X / s.X, v.Y / s.Y, v.Z / s.Z, v.W);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Scale3d s0, Scale3d s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Scale3d s0, Scale3d s1, double tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Scale_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action endl = () => Out(Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action and = () => Out(\" && \");\n    //# Action or = () => Out(\" || \");\n    //# Action andLit = () => Out(\" and \");\n    //# var fields = new[] {\"X\", \"Y\", \"Z\", \"W\"};\n    //# foreach (var isDouble in new[] { false, true }) {\n    //# for (int d = 2; d <= 3; d++) {\n    //#   var d1 = d + 1;\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var xyz = \"XYZW\".Substring(0, d);\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Scale\" + d + tc;\n    //#   var type2 = \"Scale\" + d + tc2;\n    //#   var trafodt = \"Trafo\" + d + tc;\n    //#   var affinedt = \"Affine\" + d + tc;\n    //#   var euclideandt = \"Euclidean\" + d + tc;\n    //#   var rotdt = \"Rot\" + d + tc;\n    //#   var shiftdt = \"Shift\" + d + tc;\n    //#   var similaritydt = \"Similarity\" + d + tc;\n    //#   var mddt = \"M\" + d + d + tc;\n    //#   var md1d1t = \"M\" + d1 + d1 + tc;\n    //#   var vdt = \"V\" + d + tc;\n    //#   var vdt2 = \"V\" + d + tc2;\n    //#   var dfields = fields.Take(d).ToArray();\n    //#   var fd = fields[d];\n    //#   var eps = isDouble ? \"1e-12\" : \"1e-5f\";\n    //#   var getptr = \"&\" + dfields[0];\n    #region __type__\n\n    /// <summary>\n    /// A __d__-dimensional scaling transform with different scaling values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public __vdt__ V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from __d__ __ftype__s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# dfields.ForEach(f => { */__ftype__ s__f__/*# }, comma); */)\n        {\n            V = new __vdt__(/*# dfields.ForEach(f => { */s__f__/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from __d__ scaling factors provided as <see cref=\"__vdt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__vdt__ scalingFactors)\n        {\n            V = scalingFactors;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a uniform __ftype__ value.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ uniform)\n        {\n            V = new __vdt__(/*# dfields.ForEach(f => { */uniform/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ scale)\n        {\n            V = scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a <see cref=\"__type2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ scale)\n        {\n            V = (__vdt__)scale.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a __ftype__-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] array)\n        {\n            V = new __vdt__(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a __ftype__-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] array, int start)\n        {\n            V = new __vdt__(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        //# dfields.ForEach(f => {\n        /// <summary>\n        /// Gets and sets the __f__ coordinate.\n        /// </summary>\n        public __ftype__ __f__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.__f__; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.__f__ = value; }\n        }\n\n        //# });\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public readonly __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(/*# dfields.ForEach(f => { */1 / __f__/*# }, comma); */);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(/*# dfields.ForEach(f => { */1/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> transformation with all components set to zero.\n        /// </summary>\n        public static __type__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(/*# dfields.ForEach(f => { */0/*# }, comma); */);\n        }\n\n        //# dfields.ForEach((fi, i) => {\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> transformation with scaling factors (/*# dfields.ForEach((fj, j) => { var val = (i != j) ? \"0\" : \"1\"; */__val__/*# }, comma); */).\n        /// </summary>\n        public static __type__ __fi__Axis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(/*# dfields.ForEach((fj, j) => { var val = (i != j) ? \"0\" : \"1\"; */__val__/*# }, comma); */);\n        }\n\n        //# });\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ scale)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */-scale.__f__/*# }, comma); */);\n        }\n\n        #region Scale / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a __ftype__ scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ scale, __ftype__ scalar)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */scale.__f__ * scalar/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Multiplies a __ftype__ scalar with a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__ftype__ scalar, __type__ scale)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */scale.__f__ * scalar/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"__type__\"/> transformation by a __ftype__ scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__type__ scale, __ftype__ scalar)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */scale.__f__ / scalar/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Divides a __ftype__ scalar by a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__ftype__ scalar, __type__ scale)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */scalar / scale.__f__/*# }, comma); */);\n        }\n\n        #endregion\n\n        #region Scale / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__vdt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vdt__ operator *(__type__ scale, __vdt__ vector)\n        {\n            return new __vdt__(/*# dfields.ForEach(f => { */vector.__f__ * scale.__f__/*# }, comma); */);\n        }\n\n        #endregion\n\n        #region Scale / Scale Multiplication\n\n        //# for (int n = 2; n <= 3; n++) {\n        //# var r = (d > n) ? d : n;\n        //# var m = (d < n) ? d : n;\n        //# var mfields = fields.Take(m);\n        //# var rem = r - m;\n        //# var ntype = \"Scale\" + n + tc;\n        //# var rtype = \"Scale\" + r + tc;\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__ntype__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ operator *(__type__ a, __ntype__ b)\n            => new __rtype__(/*# mfields.ForEach(f => {*/a.__f__ * b.__f__/*# }, comma);\n                if (r > m) {*/, /*# rem.ForEach(i => {\n                var x = (d > n) ? \"a\" : \"b\";\n                var f = fields[m + i]; */__x__.__f__/*#}, comma); } */);\n\n        //# }\n        #endregion\n\n        #region Scale / Matrix Multiplication\n\n        //# for (int n = d; n <= d+1; n++) {\n        //# for (int m = n; m <= (n + 1) && m <= d+1; m++) {\n        //#     var mat = \"M\" + n + m + tc;\n        //#     var nfields = dfields.Take(n);\n        //#     var mfields = dfields.Take(m);\n        //#     var nrem = n - d;\n        //#     var mrem = m - d;\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __n__x__n__ matrix) with a <see cref=\"__mat__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mat__ operator *(__type__ scale, __mat__ matrix)\n        {\n            return new __mat__(/*# nfields.ForEach((fi, i) => { */\n                /*# m.ForEach(j => { */scale.__fi__ * matrix.M__i____j__/*# }, comma); }, comma);\n                 if (nrem > 0) {*/, /*# nrem.ForEach(i => { */\n                /*# var ipd = i + d; m.ForEach(j => { */matrix.M__ipd____j__/*# }, comma); }, comma); }*/);\n        }\n\n        //# var rem = m - d;\n        /// <summary>\n        /// Multiplies a <see cref=\"__mat__\"/> with a <see cref=\"__type__\"/> transformation (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mat__ operator *(__mat__ matrix, __type__ scale)\n        {\n            return new __mat__(/*# n.ForEach(i => { */\n                /*# mfields.ForEach((fj, j) => { */matrix.M__i____j__ * scale.__fj__/*# }, comma);\n                  if (mrem > 0) {*/, /*# mrem.ForEach(j => {\n                  var jpd = j + d; */matrix.M__i____jpd__/*# }, comma); } }, comma);*/);\n        }\n\n        //# } }\n        #endregion\n\n        #region Scale / Rot, Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__rotdt__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affinedt__ operator *(__type__ a, __rotdt__ b)\n            => new __affinedt__((__mddt__)a * (__mddt__)b);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__shiftdt__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affinedt__ operator *(__type__ a, __shiftdt__ b)\n            => new __affinedt__((__mddt__)a, a * b.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ s0, __type__ s1)\n            => /*# dfields.ForEach(f => {*/s0.__f__ == s1.__f__/*# }, and);*/;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ s0, __type__ s1)\n            => /*# dfields.ForEach(f => {*/s0.__f__ != s1.__f__/*# }, or);*/;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__mddt__\"/> matrix.\n        /// The matrix must only contain scaling components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mddt__(__mddt__ m, __ftype__ epsilon = (__ftype__)1e-6)\n        {\n            if (!(/*# d.ForEach(i => {*/Fun.IsTiny(m.C__i__ * __vdt__./*#\n                      d.ForEach(j => { var x = (i == j) ? \"O\" : \"I\"; */__x__/*# });*/, epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            return new __type__(/*# d.ForEach(i => {*/m.M__i____i__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a scaling <see cref=\"__md1d1t__\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__md1d1t__(__md1d1t__ m, __ftype__ epsilon = (__ftype__)1e-6)\n        {\n            if (!(/*# d.ForEach(i => {*/Fun.IsTiny(m.C__i__.__xyz__ * __vdt__./*#\n                      d.ForEach(j => { var x = (i == j) ? \"O\" : \"I\"; */__x__/*# });*/, epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix is not a pure scaling matrix.\");\n\n            if (!(/*#d.ForEach(j => {*/m.M__d____j__.IsTiny(epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (!m.C__d__.__xyz__.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix contains translational component.\");\n\n            if (m.M__d____d__.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new __type__(/*# d.ForEach(i => {*/m.M__i____i__ / m.M__d____d__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__similaritydt__\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__similaritydt__(__similaritydt__ similarity, __ftype__ epsilon = __eps__)\n        {\n            if (!similarity.Trans.IsTiny(epsilon))\n                throw new ArgumentException(\"Similarity transformation contains translational component\");\n\n            if (!similarity.Rot.ApproximateEquals(__rotdt__.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new __type__(similarity.Scale);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from an <see cref=\"__affinedt__\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__affinedt__(__affinedt__ affine, __ftype__ epsilon = __eps__)\n            => From__md1d1t__((__md1d1t__)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__trafodt__\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__trafodt__(__trafodt__ trafo, __ftype__ epsilon = __eps__)\n            => From__md1d1t__(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        //# for (int n = 2; n <= 4; n++) {\n        //# for (int m = n; m <= (n+1) && m <= 4; m++) {\n        //#     var mat = \"M\" + n + m + tc;\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mat__(__type__ s)\n        {\n            return new __mat__(/*# n.ForEach(i => { */\n                /*# m.ForEach(j => {\n                   var x = (i == j) ? ((i < d) ? \"s.\" + fields[i] : \"1  \") : \"0  \";\n                */__x__/*# }, comma); }, comma);*/);\n        }\n\n        //# } }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __affinedt__(__type__ s)\n            => new __affinedt__((__mddt__)s, __vdt__.Zero);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __trafodt__(__type__ s)\n            => new __trafodt__((__md1d1t__)s, (__md1d1t__)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ s)\n            => new __type2__((__vdt2__)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"__type__\"/> instance\n        /// in a __ftype__[] array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __ftype__[](__type__ s)\n            => (__ftype__[])s.V;\n\n        #endregion\n\n        #region Indexing\n\n        public __ftype__ this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => /*# dfields.ForEach(f => {*/__f__.Equals(other.__f__)/*# }, and);*/;\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[/*# d.ForEach(i => {*/{__i__}/*# }, comma);*/]\", /*# dfields.ForEach(f => {*/__f__/*#}, comma);*/);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(/*# d.ForEach(i => {*/\n                __ftype__.Parse(x[__i__], CultureInfo.InvariantCulture)/*# }, comma);*/\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Scale\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ scale)\n            => scale.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref __type__ scale)\n        {\n            //# dfields.ForEach(f => {\n            scale.V.__f__ = 1 / scale.V.__f__;\n            //# });\n        }\n\n        #endregion\n\n        #region Transformations\n\n        //# for (int n = d; n <= 4; n++) {\n        //# var vec = \"V\" + n + tc;\n        //# var rem = n - d;\n        //# var constfields = fields.Skip(d).Take(rem);\n        //# var isare = (rem > 1) ? \"are\" : \"is\";\n        /// <summary>\n        /// Transforms a <see cref=\"__vec__\"/> vector by a <see cref=\"__type__\"/> transformation./*# if (rem > 0) { */\n        /// /*# constfields.ForEach(f => {*/v.__f__/*# }, andLit); */ __isare__ not modified./*# }*/\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vec__ Transform(this __type__ s, __vec__ v)\n            => new __vec__(/*# dfields.ForEach(f => {*/v.__f__ * s.__f__/*# }, comma);\n                if (rem > 0) {*/, /*# rem.ForEach(i => {\n                var f = fields[d + i]; */v.__f__/*#}, comma); } */);\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vec__\"/> vector by the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vec__ InvTransform(this __type__ s, __vec__ v)\n            => new __vec__(/*# dfields.ForEach(f => {*/v.__f__ / s.__f__/*# }, comma);\n                if (rem > 0) {*/, /*# rem.ForEach(i => {\n                var f = fields[d + i]; */v.__f__/*#}, comma); } */);\n\n        //# }\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ s0, __type__ s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ s0, __type__ s1, __ftype__ tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Shift_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    #region Shift2f\n\n    /// <summary>\n    /// A 2-dimensional translational transform with different translation values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Shift2f : IEquatable<Shift2f>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public V2f V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2f\"/> transformation from 2 floats.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2f(float x, float y)\n        {\n            V = new V2f(x, y);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2f\"/> from a <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2f(V2f v)\n        {\n            V = v;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2f(Shift2f s)\n        {\n            V = s.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2f\"/> transformation from a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2f(Shift2d shift)\n        {\n            V = (V2f)shift.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2f\"/> transformation from a float-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2f(float[] array)\n        {\n            V = new V2f(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2f\"/> transformation from a float-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2f(float[] array, int start)\n        {\n            V = new V2f(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets and sets the X coordinate.\n        /// </summary>\n        public float X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.X = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Y coordinate.\n        /// </summary>\n        public float Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Y = value; }\n        }\n\n        /// <summary>\n        /// Gets the length of this <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        public readonly float Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.Length; }\n        }\n\n        /// <summary>\n        /// Gets the squared length of this <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        public readonly float LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.LengthSquared; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        public readonly Shift2f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Shift2f(-V); }\n        }\n\n        /// <summary>\n        /// Gets the reciprocal of this <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        public readonly Shift2f Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift2f(1 / V);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        public static Shift2f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift2f(0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift2f\"/> transformation with all components set to zero.\n        /// Note: Equivalent to Identity.\n        /// </summary>\n        public static Shift2f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Identity;\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift2f\"/> transformation with components (1, 0).\n        /// </summary>\n        public static Shift2f XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift2f(1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift2f\"/> transformation with components (0, 1).\n        /// </summary>\n        public static Shift2f YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift2f(0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f operator -(Shift2f shift)\n        {\n            return new Shift2f(-shift.X, -shift.Y);\n        }\n\n        #region Shift / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation with a float scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f operator *(Shift2f shift, float scalar)\n        {\n            return new Shift2f(shift.X * scalar, shift.Y * scalar);\n        }\n\n        /// <summary>\n        /// Multiplies a float scalar with a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f operator *(float scalar, Shift2f shift)\n        {\n            return new Shift2f(shift.X * scalar, shift.Y * scalar);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Shift2f\"/> transformation by a float scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f operator /(Shift2f shift, float scalar)\n        {\n            return new Shift2f(shift.X / scalar, shift.Y / scalar);\n        }\n\n        /// <summary>\n        /// Divides a float scalar by a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f operator /(float scalar, Shift2f shift)\n        {\n            return new Shift2f(scalar / shift.X, scalar / shift.Y);\n        }\n\n        #endregion\n\n        #region Shift / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation with a <see cref=\"V2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(Shift2f shift, V2f vector)\n        {\n            return new V2f(vector.X + shift.X, vector.Y + shift.Y);\n        }\n\n        #endregion\n\n        #region Shift / Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation with a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f operator *(Shift2f a, Shift2f b)\n            => new Shift2f(a.X + b.X, a.Y + b.Y);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation with a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f operator *(Shift2f a, Shift3f b)\n            => new Shift3f(a.X + b.X, a.Y + b.Y, b.Z);\n\n        #endregion\n\n        #region Shift / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation (as a 2x3 matrix) with a <see cref=\"M22f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Shift2f shift, M22f matrix)\n        {\n            return new M23f(matrix, shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22f\"/> with a <see cref=\"Shift2f\"/> transformation (as a 2x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M22f matrix, Shift2f shift)\n        {\n            return new M23f(matrix, matrix * shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(Shift2f s, M33f m)\n        {\n            return new M33f(\n                m.M00 + s.X * m.M20, \n                m.M01 + s.X * m.M21, \n                m.M02 + s.X * m.M22,\n\n                m.M10 + s.Y * m.M20, \n                m.M11 + s.Y * m.M21, \n                m.M12 + s.Y * m.M22,\n\n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> with a <see cref=\"Shift2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(M33f m, Shift2f s)\n        {\n            return new M33f(\n                m.M00, \n                m.M01,\n                s.X * m.M00 + s.Y * m.M01 + m.M02,\n\n                m.M10, \n                m.M11,\n                s.X * m.M10 + s.Y * m.M11 + m.M12,\n\n                m.M20, \n                m.M21,\n                s.X * m.M20 + s.Y * m.M21 + m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation (as a 2x3 matrix) with a <see cref=\"M23f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Shift2f s, M23f m)\n        {\n            return new M23f(\n                m.M00, m.M01, m.M02 + s.X, \n                m.M10, m.M11, m.M12 + s.Y);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23f\"/> with a <see cref=\"Shift2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M23f m, Shift2f s)\n        {\n            return new M23f(\n                m.M00, \n                m.M01,\n                s.X * m.M00 + s.Y * m.M01 + m.M02,\n\n                m.M10, \n                m.M11,\n                s.X * m.M10 + s.Y * m.M11 + m.M12);\n        }\n\n        #endregion\n\n        #region Shift / Rot, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation with a <see cref=\"Rot2f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2f operator *(Shift2f a, Rot2f b)\n            => new Euclidean2f(b, a.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> transformation with a <see cref=\"Scale2f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Shift2f a, Scale2f b)\n            => new Affine2f((M22f)b, a.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Shift2f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Shift2f s0, Shift2f s1)\n            => s0.X == s1.X && s0.Y == s1.Y;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Shift2f\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Shift2f s0, Shift2f s1)\n            => s0.X != s1.X || s0.Y != s1.Y;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2f\"/> transformation from a <see cref=\"M23f\"/> matrix.\n        /// The matrix must only contain translation components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f FromM23f(M23f m, float epsilon = (float)1e-6)\n        {\n            if (!M22f.Identity.ApproximateEquals((M22f)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            return new Shift2f(m.C2);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2f\"/> transformation from a translation <see cref=\"M33f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f FromM33f(M33f m, float epsilon = (float)1e-6)\n        {\n            if (!M22f.Identity.ApproximateEquals((M22f)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new Shift2f(m.C2.XY / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2f\"/> transformation from a <see cref=\"Euclidean2f\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f FromEuclidean2f(Euclidean2f euclidean, float epsilon = 1e-5f)\n        {\n            if (!euclidean.Rot.ApproximateEquals(Rot2f.Identity, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains rotational component\");\n\n            return new Shift2f(euclidean.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2f\"/> transformation from a <see cref=\"Similarity2f\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f FromSimilarity2f(Similarity2f similarity, float epsilon = 1e-5f)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Rot.ApproximateEquals(Rot2f.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new Shift2f(similarity.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2f\"/> transformation from an <see cref=\"Affine2f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f FromAffine2f(Affine2f affine, float epsilon = 1e-5f)\n            => FromM33f((M33f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2f\"/> transformation from a <see cref=\"Trafo2f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f FromTrafo2f(Trafo2f trafo, float epsilon = 1e-5f)\n            => FromM33f(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Shift2f s)\n        {\n            return new M33f(\n                1, 0, s.X, \n                0, 1, s.Y,\n                0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23f(Shift2f s)\n        {\n            return new M23f(\n                1, 0, s.X, \n                0, 1, s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Shift2f s)\n        {\n            return new M44f(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, 0,\n                0, 0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Shift2f s)\n        {\n            return new M34f(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean2f(Shift2f s)\n            => new Euclidean2f(Rot2f.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity2f(Shift2f s)\n            => new Similarity2f(1, Rot2f.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2f(Shift2f s)\n            => new Affine2f(M22f.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2f(Shift2f s)\n            => new Trafo2f((M33f)s, (M33f)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Shift2d(Shift2f s)\n            => new Shift2d((V2d)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"Shift2f\"/> instance\n        /// in a float[] array.\n        /// </summary>\n        public static explicit operator float[](Shift2f shift)\n        {\n            float[] array = new float[2];\n            array[0] = shift.X;\n            array[1] = shift.Y;\n            return array;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Shift2f other)\n            => X.Equals(other.X) && Y.Equals(other.Y);\n\n        public override readonly bool Equals(object other)\n            => (other is Shift2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", X, Y);\n        }\n\n        public static Shift2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Shift2f(\n                float.Parse(x[0], CultureInfo.InvariantCulture), \n                float.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Shift\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2f Inverse(Shift2f shift)\n            => shift.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Shift2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Shift2f shift)\n        {\n            shift.V.X = -shift.V.X;\n            shift.V.Y = -shift.V.Y;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> vector by a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Transform(this Shift2f s, V2f v)\n            => new V2f(v.X + s.X, v.Y + s.Y);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2f\"/> vector by the inverse of a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransform(this Shift2f s, V2f v)\n            => new V2f(v.X - s.X, v.Y - s.Y);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Shift2f\"/> transformation.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Shift2f s, V3f v)\n            => new V3f(v.X + s.X, v.Y + s.Y, v.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by the inverse of a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransform(this Shift2f s, V3f v)\n            => new V3f(v.X - s.X, v.Y - s.Y, v.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by a <see cref=\"Shift2f\"/> transformation.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Shift2f s, V4f v)\n            => new V4f(v.X + s.X, v.Y + s.Y, v.Z, v.W);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by the inverse of a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f InvTransform(this Shift2f s, V4f v)\n            => new V4f(v.X - s.X, v.Y - s.Y, v.Z, v.W);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Shift2f s0, Shift2f s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Shift2f s0, Shift2f s1, float tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Shift3f\n\n    /// <summary>\n    /// A 3-dimensional translational transform with different translation values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Shift3f : IEquatable<Shift3f>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public V3f V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3f\"/> transformation from 3 floats.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3f(float x, float y, float z)\n        {\n            V = new V3f(x, y, z);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3f\"/> from a <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3f(V3f v)\n        {\n            V = v;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3f(Shift3f s)\n        {\n            V = s.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3f\"/> transformation from a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3f(Shift3d shift)\n        {\n            V = (V3f)shift.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3f\"/> transformation from a float-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3f(float[] array)\n        {\n            V = new V3f(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3f\"/> transformation from a float-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3f(float[] array, int start)\n        {\n            V = new V3f(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets and sets the X coordinate.\n        /// </summary>\n        public float X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.X = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Y coordinate.\n        /// </summary>\n        public float Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Y = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Z coordinate.\n        /// </summary>\n        public float Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Z; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Z = value; }\n        }\n\n        /// <summary>\n        /// Gets the length of this <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        public readonly float Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.Length; }\n        }\n\n        /// <summary>\n        /// Gets the squared length of this <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        public readonly float LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.LengthSquared; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        public readonly Shift3f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Shift3f(-V); }\n        }\n\n        /// <summary>\n        /// Gets the reciprocal of this <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        public readonly Shift3f Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3f(1 / V);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        public static Shift3f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3f(0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift3f\"/> transformation with all components set to zero.\n        /// Note: Equivalent to Identity.\n        /// </summary>\n        public static Shift3f Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Identity;\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift3f\"/> transformation with components (1, 0, 0).\n        /// </summary>\n        public static Shift3f XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3f(1, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift3f\"/> transformation with components (0, 1, 0).\n        /// </summary>\n        public static Shift3f YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3f(0, 1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift3f\"/> transformation with components (0, 0, 1).\n        /// </summary>\n        public static Shift3f ZAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3f(0, 0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f operator -(Shift3f shift)\n        {\n            return new Shift3f(-shift.X, -shift.Y, -shift.Z);\n        }\n\n        #region Shift / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation with a float scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f operator *(Shift3f shift, float scalar)\n        {\n            return new Shift3f(shift.X * scalar, shift.Y * scalar, shift.Z * scalar);\n        }\n\n        /// <summary>\n        /// Multiplies a float scalar with a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f operator *(float scalar, Shift3f shift)\n        {\n            return new Shift3f(shift.X * scalar, shift.Y * scalar, shift.Z * scalar);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Shift3f\"/> transformation by a float scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f operator /(Shift3f shift, float scalar)\n        {\n            return new Shift3f(shift.X / scalar, shift.Y / scalar, shift.Z / scalar);\n        }\n\n        /// <summary>\n        /// Divides a float scalar by a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f operator /(float scalar, Shift3f shift)\n        {\n            return new Shift3f(scalar / shift.X, scalar / shift.Y, scalar / shift.Z);\n        }\n\n        #endregion\n\n        #region Shift / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation with a <see cref=\"V3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(Shift3f shift, V3f vector)\n        {\n            return new V3f(vector.X + shift.X, vector.Y + shift.Y, vector.Z + shift.Z);\n        }\n\n        #endregion\n\n        #region Shift / Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation with a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f operator *(Shift3f a, Shift2f b)\n            => new Shift3f(a.X + b.X, a.Y + b.Y, a.Z);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation with a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f operator *(Shift3f a, Shift3f b)\n            => new Shift3f(a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        #endregion\n\n        #region Shift / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation (as a 3x4 matrix) with a <see cref=\"M33f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Shift3f shift, M33f matrix)\n        {\n            return new M34f(matrix, shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> with a <see cref=\"Shift3f\"/> transformation (as a 3x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M33f matrix, Shift3f shift)\n        {\n            return new M34f(matrix, matrix * shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(Shift3f s, M44f m)\n        {\n            return new M44f(\n                m.M00 + s.X * m.M30, \n                m.M01 + s.X * m.M31, \n                m.M02 + s.X * m.M32, \n                m.M03 + s.X * m.M33,\n\n                m.M10 + s.Y * m.M30, \n                m.M11 + s.Y * m.M31, \n                m.M12 + s.Y * m.M32, \n                m.M13 + s.Y * m.M33,\n\n                m.M20 + s.Z * m.M30, \n                m.M21 + s.Z * m.M31, \n                m.M22 + s.Z * m.M32, \n                m.M23 + s.Z * m.M33,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44f\"/> with a <see cref=\"Shift3f\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(M44f m, Shift3f s)\n        {\n            return new M44f(\n                m.M00, \n                m.M01, \n                m.M02,\n                s.X * m.M00 + s.Y * m.M01 + s.Z * m.M02 + m.M03,\n\n                m.M10, \n                m.M11, \n                m.M12,\n                s.X * m.M10 + s.Y * m.M11 + s.Z * m.M12 + m.M13,\n\n                m.M20, \n                m.M21, \n                m.M22,\n                s.X * m.M20 + s.Y * m.M21 + s.Z * m.M22 + m.M23,\n\n                m.M30, \n                m.M31, \n                m.M32,\n                s.X * m.M30 + s.Y * m.M31 + s.Z * m.M32 + m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation (as a 3x4 matrix) with a <see cref=\"M34f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Shift3f s, M34f m)\n        {\n            return new M34f(\n                m.M00, m.M01, m.M02, m.M03 + s.X, \n                m.M10, m.M11, m.M12, m.M13 + s.Y, \n                m.M20, m.M21, m.M22, m.M23 + s.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34f\"/> with a <see cref=\"Shift3f\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M34f m, Shift3f s)\n        {\n            return new M34f(\n                m.M00, \n                m.M01, \n                m.M02,\n                s.X * m.M00 + s.Y * m.M01 + s.Z * m.M02 + m.M03,\n\n                m.M10, \n                m.M11, \n                m.M12,\n                s.X * m.M10 + s.Y * m.M11 + s.Z * m.M12 + m.M13,\n\n                m.M20, \n                m.M21, \n                m.M22,\n                s.X * m.M20 + s.Y * m.M21 + s.Z * m.M22 + m.M23);\n        }\n\n        #endregion\n\n        #region Shift / Rot, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation with a <see cref=\"Rot3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3f operator *(Shift3f a, Rot3f b)\n            => new Euclidean3f(b, a.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> transformation with a <see cref=\"Scale3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Shift3f a, Scale3f b)\n            => new Affine3f((M33f)b, a.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Shift3f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Shift3f s0, Shift3f s1)\n            => s0.X == s1.X && s0.Y == s1.Y && s0.Z == s1.Z;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Shift3f\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Shift3f s0, Shift3f s1)\n            => s0.X != s1.X || s0.Y != s1.Y || s0.Z != s1.Z;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3f\"/> transformation from a <see cref=\"M34f\"/> matrix.\n        /// The matrix must only contain translation components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f FromM34f(M34f m, float epsilon = (float)1e-6)\n        {\n            if (!M33f.Identity.ApproximateEquals((M33f)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            return new Shift3f(m.C3);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3f\"/> transformation from a translation <see cref=\"M44f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f FromM44f(M44f m, float epsilon = (float)1e-6)\n        {\n            if (!M33f.Identity.ApproximateEquals((M33f)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new Shift3f(m.C3.XYZ / m.M33);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3f\"/> transformation from a <see cref=\"Euclidean3f\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f FromEuclidean3f(Euclidean3f euclidean, float epsilon = 1e-5f)\n        {\n            if (!euclidean.Rot.ApproximateEquals(Rot3f.Identity, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains rotational component\");\n\n            return new Shift3f(euclidean.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3f\"/> transformation from a <see cref=\"Similarity3f\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f FromSimilarity3f(Similarity3f similarity, float epsilon = 1e-5f)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Rot.ApproximateEquals(Rot3f.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new Shift3f(similarity.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3f\"/> transformation from an <see cref=\"Affine3f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f FromAffine3f(Affine3f affine, float epsilon = 1e-5f)\n            => FromM44f((M44f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3f\"/> transformation from a <see cref=\"Trafo3f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f FromTrafo3f(Trafo3f trafo, float epsilon = 1e-5f)\n            => FromM44f(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Shift3f s)\n        {\n            return new M33f(\n                1, 0, s.X, \n                0, 1, s.Y,\n                0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23f(Shift3f s)\n        {\n            return new M23f(\n                1, 0, s.X, \n                0, 1, s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Shift3f s)\n        {\n            return new M44f(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, s.Z,\n                0, 0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Shift3f s)\n        {\n            return new M34f(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, s.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean3f(Shift3f s)\n            => new Euclidean3f(Rot3f.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity3f(Shift3f s)\n            => new Similarity3f(1, Rot3f.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3f(Shift3f s)\n            => new Affine3f(M33f.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3f(Shift3f s)\n            => new Trafo3f((M44f)s, (M44f)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Shift3d(Shift3f s)\n            => new Shift3d((V3d)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"Shift3f\"/> instance\n        /// in a float[] array.\n        /// </summary>\n        public static explicit operator float[](Shift3f shift)\n        {\n            float[] array = new float[3];\n            array[0] = shift.X;\n            array[1] = shift.Y;\n            array[2] = shift.Z;\n            return array;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Shift3f other)\n            => X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n\n        public override readonly bool Equals(object other)\n            => (other is Shift3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", X, Y, Z);\n        }\n\n        public static Shift3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Shift3f(\n                float.Parse(x[0], CultureInfo.InvariantCulture), \n                float.Parse(x[1], CultureInfo.InvariantCulture), \n                float.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Shift\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3f Inverse(Shift3f shift)\n            => shift.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Shift3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Shift3f shift)\n        {\n            shift.V.X = -shift.V.X;\n            shift.V.Y = -shift.V.Y;\n            shift.V.Z = -shift.V.Z;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Shift3f s, V3f v)\n            => new V3f(v.X + s.X, v.Y + s.Y, v.Z + s.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by the inverse of a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransform(this Shift3f s, V3f v)\n            => new V3f(v.X - s.X, v.Y - s.Y, v.Z - s.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by a <see cref=\"Shift3f\"/> transformation.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Shift3f s, V4f v)\n            => new V4f(v.X + s.X, v.Y + s.Y, v.Z + s.Z, v.W);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by the inverse of a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f InvTransform(this Shift3f s, V4f v)\n            => new V4f(v.X - s.X, v.Y - s.Y, v.Z - s.Z, v.W);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Shift3f s0, Shift3f s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Shift3f s0, Shift3f s1, float tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Shift2d\n\n    /// <summary>\n    /// A 2-dimensional translational transform with different translation values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Shift2d : IEquatable<Shift2d>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public V2d V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2d\"/> transformation from 2 doubles.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2d(double x, double y)\n        {\n            V = new V2d(x, y);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2d\"/> from a <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2d(V2d v)\n        {\n            V = v;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2d(Shift2d s)\n        {\n            V = s.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2d\"/> transformation from a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2d(Shift2f shift)\n        {\n            V = (V2d)shift.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2d\"/> transformation from a double-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2d(double[] array)\n        {\n            V = new V2d(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift2d\"/> transformation from a double-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift2d(double[] array, int start)\n        {\n            V = new V2d(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets and sets the X coordinate.\n        /// </summary>\n        public double X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.X = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Y coordinate.\n        /// </summary>\n        public double Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Y = value; }\n        }\n\n        /// <summary>\n        /// Gets the length of this <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.Length; }\n        }\n\n        /// <summary>\n        /// Gets the squared length of this <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        public readonly double LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.LengthSquared; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        public readonly Shift2d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Shift2d(-V); }\n        }\n\n        /// <summary>\n        /// Gets the reciprocal of this <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        public readonly Shift2d Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift2d(1 / V);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        public static Shift2d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift2d(0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift2d\"/> transformation with all components set to zero.\n        /// Note: Equivalent to Identity.\n        /// </summary>\n        public static Shift2d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Identity;\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift2d\"/> transformation with components (1, 0).\n        /// </summary>\n        public static Shift2d XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift2d(1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift2d\"/> transformation with components (0, 1).\n        /// </summary>\n        public static Shift2d YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift2d(0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d operator -(Shift2d shift)\n        {\n            return new Shift2d(-shift.X, -shift.Y);\n        }\n\n        #region Shift / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation with a double scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d operator *(Shift2d shift, double scalar)\n        {\n            return new Shift2d(shift.X * scalar, shift.Y * scalar);\n        }\n\n        /// <summary>\n        /// Multiplies a double scalar with a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d operator *(double scalar, Shift2d shift)\n        {\n            return new Shift2d(shift.X * scalar, shift.Y * scalar);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Shift2d\"/> transformation by a double scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d operator /(Shift2d shift, double scalar)\n        {\n            return new Shift2d(shift.X / scalar, shift.Y / scalar);\n        }\n\n        /// <summary>\n        /// Divides a double scalar by a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d operator /(double scalar, Shift2d shift)\n        {\n            return new Shift2d(scalar / shift.X, scalar / shift.Y);\n        }\n\n        #endregion\n\n        #region Shift / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation with a <see cref=\"V2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(Shift2d shift, V2d vector)\n        {\n            return new V2d(vector.X + shift.X, vector.Y + shift.Y);\n        }\n\n        #endregion\n\n        #region Shift / Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation with a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d operator *(Shift2d a, Shift2d b)\n            => new Shift2d(a.X + b.X, a.Y + b.Y);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation with a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d operator *(Shift2d a, Shift3d b)\n            => new Shift3d(a.X + b.X, a.Y + b.Y, b.Z);\n\n        #endregion\n\n        #region Shift / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation (as a 2x3 matrix) with a <see cref=\"M22d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Shift2d shift, M22d matrix)\n        {\n            return new M23d(matrix, shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22d\"/> with a <see cref=\"Shift2d\"/> transformation (as a 2x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M22d matrix, Shift2d shift)\n        {\n            return new M23d(matrix, matrix * shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(Shift2d s, M33d m)\n        {\n            return new M33d(\n                m.M00 + s.X * m.M20, \n                m.M01 + s.X * m.M21, \n                m.M02 + s.X * m.M22,\n\n                m.M10 + s.Y * m.M20, \n                m.M11 + s.Y * m.M21, \n                m.M12 + s.Y * m.M22,\n\n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> with a <see cref=\"Shift2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(M33d m, Shift2d s)\n        {\n            return new M33d(\n                m.M00, \n                m.M01,\n                s.X * m.M00 + s.Y * m.M01 + m.M02,\n\n                m.M10, \n                m.M11,\n                s.X * m.M10 + s.Y * m.M11 + m.M12,\n\n                m.M20, \n                m.M21,\n                s.X * m.M20 + s.Y * m.M21 + m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation (as a 2x3 matrix) with a <see cref=\"M23d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Shift2d s, M23d m)\n        {\n            return new M23d(\n                m.M00, m.M01, m.M02 + s.X, \n                m.M10, m.M11, m.M12 + s.Y);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23d\"/> with a <see cref=\"Shift2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M23d m, Shift2d s)\n        {\n            return new M23d(\n                m.M00, \n                m.M01,\n                s.X * m.M00 + s.Y * m.M01 + m.M02,\n\n                m.M10, \n                m.M11,\n                s.X * m.M10 + s.Y * m.M11 + m.M12);\n        }\n\n        #endregion\n\n        #region Shift / Rot, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation with a <see cref=\"Rot2d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean2d operator *(Shift2d a, Rot2d b)\n            => new Euclidean2d(b, a.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> transformation with a <see cref=\"Scale2d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Shift2d a, Scale2d b)\n            => new Affine2d((M22d)b, a.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Shift2d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Shift2d s0, Shift2d s1)\n            => s0.X == s1.X && s0.Y == s1.Y;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Shift2d\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Shift2d s0, Shift2d s1)\n            => s0.X != s1.X || s0.Y != s1.Y;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2d\"/> transformation from a <see cref=\"M23d\"/> matrix.\n        /// The matrix must only contain translation components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d FromM23d(M23d m, double epsilon = (double)1e-6)\n        {\n            if (!M22d.Identity.ApproximateEquals((M22d)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            return new Shift2d(m.C2);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2d\"/> transformation from a translation <see cref=\"M33d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d FromM33d(M33d m, double epsilon = (double)1e-6)\n        {\n            if (!M22d.Identity.ApproximateEquals((M22d)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new Shift2d(m.C2.XY / m.M22);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2d\"/> transformation from a <see cref=\"Euclidean2d\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d FromEuclidean2d(Euclidean2d euclidean, double epsilon = 1e-12)\n        {\n            if (!euclidean.Rot.ApproximateEquals(Rot2d.Identity, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains rotational component\");\n\n            return new Shift2d(euclidean.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2d\"/> transformation from a <see cref=\"Similarity2d\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d FromSimilarity2d(Similarity2d similarity, double epsilon = 1e-12)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Rot.ApproximateEquals(Rot2d.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new Shift2d(similarity.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2d\"/> transformation from an <see cref=\"Affine2d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d FromAffine2d(Affine2d affine, double epsilon = 1e-12)\n            => FromM33d((M33d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift2d\"/> transformation from a <see cref=\"Trafo2d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d FromTrafo2d(Trafo2d trafo, double epsilon = 1e-12)\n            => FromM33d(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Shift2d s)\n        {\n            return new M33d(\n                1, 0, s.X, \n                0, 1, s.Y,\n                0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23d(Shift2d s)\n        {\n            return new M23d(\n                1, 0, s.X, \n                0, 1, s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Shift2d s)\n        {\n            return new M44d(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, 0,\n                0, 0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Shift2d s)\n        {\n            return new M34d(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean2d(Shift2d s)\n            => new Euclidean2d(Rot2d.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity2d(Shift2d s)\n            => new Similarity2d(1, Rot2d.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2d(Shift2d s)\n            => new Affine2d(M22d.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2d(Shift2d s)\n            => new Trafo2d((M33d)s, (M33d)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Shift2f(Shift2d s)\n            => new Shift2f((V2f)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"Shift2d\"/> instance\n        /// in a double[] array.\n        /// </summary>\n        public static explicit operator double[](Shift2d shift)\n        {\n            double[] array = new double[2];\n            array[0] = shift.X;\n            array[1] = shift.Y;\n            return array;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Shift2d other)\n            => X.Equals(other.X) && Y.Equals(other.Y);\n\n        public override readonly bool Equals(object other)\n            => (other is Shift2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", X, Y);\n        }\n\n        public static Shift2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Shift2d(\n                double.Parse(x[0], CultureInfo.InvariantCulture), \n                double.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Shift\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift2d Inverse(Shift2d shift)\n            => shift.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Shift2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Shift2d shift)\n        {\n            shift.V.X = -shift.V.X;\n            shift.V.Y = -shift.V.Y;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> vector by a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Transform(this Shift2d s, V2d v)\n            => new V2d(v.X + s.X, v.Y + s.Y);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V2d\"/> vector by the inverse of a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransform(this Shift2d s, V2d v)\n            => new V2d(v.X - s.X, v.Y - s.Y);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Shift2d\"/> transformation.\n        /// v.Z is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Shift2d s, V3d v)\n            => new V3d(v.X + s.X, v.Y + s.Y, v.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by the inverse of a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransform(this Shift2d s, V3d v)\n            => new V3d(v.X - s.X, v.Y - s.Y, v.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by a <see cref=\"Shift2d\"/> transformation.\n        /// v.Z and v.W are not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Shift2d s, V4d v)\n            => new V4d(v.X + s.X, v.Y + s.Y, v.Z, v.W);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by the inverse of a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvTransform(this Shift2d s, V4d v)\n            => new V4d(v.X - s.X, v.Y - s.Y, v.Z, v.W);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Shift2d s0, Shift2d s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Shift2d s0, Shift2d s1, double tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Shift3d\n\n    /// <summary>\n    /// A 3-dimensional translational transform with different translation values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Shift3d : IEquatable<Shift3d>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public V3d V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3d\"/> transformation from 3 doubles.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3d(double x, double y, double z)\n        {\n            V = new V3d(x, y, z);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3d\"/> from a <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3d(V3d v)\n        {\n            V = v;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3d(Shift3d s)\n        {\n            V = s.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3d\"/> transformation from a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3d(Shift3f shift)\n        {\n            V = (V3d)shift.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3d\"/> transformation from a double-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3d(double[] array)\n        {\n            V = new V3d(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Shift3d\"/> transformation from a double-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Shift3d(double[] array, int start)\n        {\n            V = new V3d(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets and sets the X coordinate.\n        /// </summary>\n        public double X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.X; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.X = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Y coordinate.\n        /// </summary>\n        public double Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Y; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Y = value; }\n        }\n\n        /// <summary>\n        /// Gets and sets the Z coordinate.\n        /// </summary>\n        public double Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.Z; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.Z = value; }\n        }\n\n        /// <summary>\n        /// Gets the length of this <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.Length; }\n        }\n\n        /// <summary>\n        /// Gets the squared length of this <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        public readonly double LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.LengthSquared; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        public readonly Shift3d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new Shift3d(-V); }\n        }\n\n        /// <summary>\n        /// Gets the reciprocal of this <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        public readonly Shift3d Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3d(1 / V);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        public static Shift3d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3d(0, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift3d\"/> transformation with all components set to zero.\n        /// Note: Equivalent to Identity.\n        /// </summary>\n        public static Shift3d Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Identity;\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift3d\"/> transformation with components (1, 0, 0).\n        /// </summary>\n        public static Shift3d XAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3d(1, 0, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift3d\"/> transformation with components (0, 1, 0).\n        /// </summary>\n        public static Shift3d YAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3d(0, 1, 0);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"Shift3d\"/> transformation with components (0, 0, 1).\n        /// </summary>\n        public static Shift3d ZAxis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Shift3d(0, 0, 1);\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d operator -(Shift3d shift)\n        {\n            return new Shift3d(-shift.X, -shift.Y, -shift.Z);\n        }\n\n        #region Shift / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation with a double scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d operator *(Shift3d shift, double scalar)\n        {\n            return new Shift3d(shift.X * scalar, shift.Y * scalar, shift.Z * scalar);\n        }\n\n        /// <summary>\n        /// Multiplies a double scalar with a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d operator *(double scalar, Shift3d shift)\n        {\n            return new Shift3d(shift.X * scalar, shift.Y * scalar, shift.Z * scalar);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"Shift3d\"/> transformation by a double scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d operator /(Shift3d shift, double scalar)\n        {\n            return new Shift3d(shift.X / scalar, shift.Y / scalar, shift.Z / scalar);\n        }\n\n        /// <summary>\n        /// Divides a double scalar by a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d operator /(double scalar, Shift3d shift)\n        {\n            return new Shift3d(scalar / shift.X, scalar / shift.Y, scalar / shift.Z);\n        }\n\n        #endregion\n\n        #region Shift / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation with a <see cref=\"V3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(Shift3d shift, V3d vector)\n        {\n            return new V3d(vector.X + shift.X, vector.Y + shift.Y, vector.Z + shift.Z);\n        }\n\n        #endregion\n\n        #region Shift / Shift Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation with a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d operator *(Shift3d a, Shift2d b)\n            => new Shift3d(a.X + b.X, a.Y + b.Y, a.Z);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation with a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d operator *(Shift3d a, Shift3d b)\n            => new Shift3d(a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        #endregion\n\n        #region Shift / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation (as a 3x4 matrix) with a <see cref=\"M33d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Shift3d shift, M33d matrix)\n        {\n            return new M34d(matrix, shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> with a <see cref=\"Shift3d\"/> transformation (as a 3x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M33d matrix, Shift3d shift)\n        {\n            return new M34d(matrix, matrix * shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(Shift3d s, M44d m)\n        {\n            return new M44d(\n                m.M00 + s.X * m.M30, \n                m.M01 + s.X * m.M31, \n                m.M02 + s.X * m.M32, \n                m.M03 + s.X * m.M33,\n\n                m.M10 + s.Y * m.M30, \n                m.M11 + s.Y * m.M31, \n                m.M12 + s.Y * m.M32, \n                m.M13 + s.Y * m.M33,\n\n                m.M20 + s.Z * m.M30, \n                m.M21 + s.Z * m.M31, \n                m.M22 + s.Z * m.M32, \n                m.M23 + s.Z * m.M33,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44d\"/> with a <see cref=\"Shift3d\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(M44d m, Shift3d s)\n        {\n            return new M44d(\n                m.M00, \n                m.M01, \n                m.M02,\n                s.X * m.M00 + s.Y * m.M01 + s.Z * m.M02 + m.M03,\n\n                m.M10, \n                m.M11, \n                m.M12,\n                s.X * m.M10 + s.Y * m.M11 + s.Z * m.M12 + m.M13,\n\n                m.M20, \n                m.M21, \n                m.M22,\n                s.X * m.M20 + s.Y * m.M21 + s.Z * m.M22 + m.M23,\n\n                m.M30, \n                m.M31, \n                m.M32,\n                s.X * m.M30 + s.Y * m.M31 + s.Z * m.M32 + m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation (as a 3x4 matrix) with a <see cref=\"M34d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Shift3d s, M34d m)\n        {\n            return new M34d(\n                m.M00, m.M01, m.M02, m.M03 + s.X, \n                m.M10, m.M11, m.M12, m.M13 + s.Y, \n                m.M20, m.M21, m.M22, m.M23 + s.Z);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34d\"/> with a <see cref=\"Shift3d\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M34d m, Shift3d s)\n        {\n            return new M34d(\n                m.M00, \n                m.M01, \n                m.M02,\n                s.X * m.M00 + s.Y * m.M01 + s.Z * m.M02 + m.M03,\n\n                m.M10, \n                m.M11, \n                m.M12,\n                s.X * m.M10 + s.Y * m.M11 + s.Z * m.M12 + m.M13,\n\n                m.M20, \n                m.M21, \n                m.M22,\n                s.X * m.M20 + s.Y * m.M21 + s.Z * m.M22 + m.M23);\n        }\n\n        #endregion\n\n        #region Shift / Rot, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation with a <see cref=\"Rot3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Euclidean3d operator *(Shift3d a, Rot3d b)\n            => new Euclidean3d(b, a.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> transformation with a <see cref=\"Scale3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Shift3d a, Scale3d b)\n            => new Affine3d((M33d)b, a.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Shift3d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Shift3d s0, Shift3d s1)\n            => s0.X == s1.X && s0.Y == s1.Y && s0.Z == s1.Z;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"Shift3d\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Shift3d s0, Shift3d s1)\n            => s0.X != s1.X || s0.Y != s1.Y || s0.Z != s1.Z;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3d\"/> transformation from a <see cref=\"M34d\"/> matrix.\n        /// The matrix must only contain translation components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d FromM34d(M34d m, double epsilon = (double)1e-6)\n        {\n            if (!M33d.Identity.ApproximateEquals((M33d)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            return new Shift3d(m.C3);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3d\"/> transformation from a translation <see cref=\"M44d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d FromM44d(M44d m, double epsilon = (double)1e-6)\n        {\n            if (!M33d.Identity.ApproximateEquals((M33d)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new Shift3d(m.C3.XYZ / m.M33);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3d\"/> transformation from a <see cref=\"Euclidean3d\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d FromEuclidean3d(Euclidean3d euclidean, double epsilon = 1e-12)\n        {\n            if (!euclidean.Rot.ApproximateEquals(Rot3d.Identity, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains rotational component\");\n\n            return new Shift3d(euclidean.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3d\"/> transformation from a <see cref=\"Similarity3d\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d FromSimilarity3d(Similarity3d similarity, double epsilon = 1e-12)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Rot.ApproximateEquals(Rot3d.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new Shift3d(similarity.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3d\"/> transformation from an <see cref=\"Affine3d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d FromAffine3d(Affine3d affine, double epsilon = 1e-12)\n            => FromM44d((M44d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Shift3d\"/> transformation from a <see cref=\"Trafo3d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d FromTrafo3d(Trafo3d trafo, double epsilon = 1e-12)\n            => FromM44d(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Shift3d s)\n        {\n            return new M33d(\n                1, 0, s.X, \n                0, 1, s.Y,\n                0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23d(Shift3d s)\n        {\n            return new M23d(\n                1, 0, s.X, \n                0, 1, s.Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Shift3d s)\n        {\n            return new M44d(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, s.Z,\n                0, 0, 0, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Shift3d s)\n        {\n            return new M34d(\n                1, 0, 0, s.X, \n                0, 1, 0, s.Y, \n                0, 0, 1, s.Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Euclidean3d(Shift3d s)\n            => new Euclidean3d(Rot3d.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity3d(Shift3d s)\n            => new Similarity3d(1, Rot3d.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3d(Shift3d s)\n            => new Affine3d(M33d.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3d(Shift3d s)\n            => new Trafo3d((M44d)s, (M44d)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Shift3f(Shift3d s)\n            => new Shift3f((V3f)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"Shift3d\"/> instance\n        /// in a double[] array.\n        /// </summary>\n        public static explicit operator double[](Shift3d shift)\n        {\n            double[] array = new double[3];\n            array[0] = shift.X;\n            array[1] = shift.Y;\n            array[2] = shift.Z;\n            return array;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Shift3d other)\n            => X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n\n        public override readonly bool Equals(object other)\n            => (other is Shift3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}, {2}]\", X, Y, Z);\n        }\n\n        public static Shift3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Shift3d(\n                double.Parse(x[0], CultureInfo.InvariantCulture), \n                double.Parse(x[1], CultureInfo.InvariantCulture), \n                double.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Shift\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Shift3d Inverse(Shift3d shift)\n            => shift.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"Shift3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Shift3d shift)\n        {\n            shift.V.X = -shift.V.X;\n            shift.V.Y = -shift.V.Y;\n            shift.V.Z = -shift.V.Z;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Shift3d s, V3d v)\n            => new V3d(v.X + s.X, v.Y + s.Y, v.Z + s.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by the inverse of a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransform(this Shift3d s, V3d v)\n            => new V3d(v.X - s.X, v.Y - s.Y, v.Z - s.Z);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by a <see cref=\"Shift3d\"/> transformation.\n        /// v.W is not modified.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Shift3d s, V4d v)\n            => new V4d(v.X + s.X, v.Y + s.Y, v.Z + s.Z, v.W);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by the inverse of a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvTransform(this Shift3d s, V4d v)\n            => new V4d(v.X - s.X, v.Y - s.Y, v.Z - s.Z, v.W);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Shift3d s0, Shift3d s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Shift3d s0, Shift3d s1, double tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Shift_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\nusing System.Xml.Serialization;\n\nnamespace Aardvark.Base\n{\n    // AUTOGENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action and = () => Out(\" && \");\n    //# Action or = () => Out(\" || \");\n    //# Action andLit = () => Out(\" and \");\n    //# var fields = new[] {\"X\", \"Y\", \"Z\", \"W\"};\n    //# var fieldsL = new[] {\"x\", \"y\", \"z\", \"w\"};\n    //# foreach (var isDouble in new[] { false, true }) {\n    //# for (int d = 2; d <= 3; d++) {\n    //#   var d1 = d + 1;\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var xyz = \"XYZW\".Substring(0, d);\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Shift\" + d + tc;\n    //#   var type2 = \"Shift\" + d + tc2;\n    //#   var trafodt = \"Trafo\" + d + tc;\n    //#   var affinedt = \"Affine\" + d + tc;\n    //#   var euclideandt = \"Euclidean\" + d + tc;\n    //#   var rotdt = \"Rot\" + d + tc;\n    //#   var shiftdt = \"Shift\" + d + tc;\n    //#   var scaledt = \"Scale\" + d + tc;\n    //#   var similaritydt = \"Similarity\" + d + tc;\n    //#   var mddt = \"M\" + d + d + tc;\n    //#   var md1d1t = \"M\" + (d + 1) + (d + 1) + tc;\n    //#   var mdd1t = \"M\" + d + (d + 1) + tc;\n    //#   var vdt = \"V\" + d + tc;\n    //#   var vdt2 = \"V\" + d + tc2;\n    //#   var dfields = fields.Take(d).ToArray();\n    //#   var dfieldsL = fieldsL.Take(d).ToArray();\n    //#   var fd = fields[d];\n    //#   var eps = isDouble ? \"1e-12\" : \"1e-5f\";\n    #region __type__\n\n    /// <summary>\n    /// A __d__-dimensional translational transform with different translation values\n    /// in each dimension.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>\n    {\n        [DataMember]\n        [XmlIgnore]\n        public __vdt__ V;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from __d__ __ftype__s.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(/*# dfieldsL.ForEach(f => { */__ftype__ __f__/*# }, comma); */)\n        {\n            V = new __vdt__(/*# dfieldsL.ForEach(f => { */__f__/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from a <see cref=\"__vdt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__vdt__ v)\n        {\n            V = v;\n        }\n\n        /// <summary>\n        /// Constructs a copy of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ s)\n        {\n            V = s.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a <see cref=\"__type2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ shift)\n        {\n            V = (__vdt__)shift.V;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a __ftype__-array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] array)\n        {\n            V = new __vdt__(array);\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a __ftype__-array starting from the given index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__[] array, int start)\n        {\n            V = new __vdt__(array, start);\n        }\n\n        #endregion\n\n        #region Properties\n\n        //# dfields.ForEach(f => {\n        /// <summary>\n        /// Gets and sets the __f__ coordinate.\n        /// </summary>\n        public __ftype__ __f__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get { return V.__f__; }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set { V.__f__ = value; }\n        }\n\n        //# });\n        /// <summary>\n        /// Gets the length of this <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public readonly __ftype__ Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.Length; }\n        }\n\n        /// <summary>\n        /// Gets the squared length of this <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public readonly __ftype__ LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return V.LengthSquared; }\n        }\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public readonly __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new __type__(-V); }\n        }\n\n        /// <summary>\n        /// Gets the reciprocal of this <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public readonly __type__ Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(1 / V);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(/*# dfields.ForEach(f => { */0/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> transformation with all components set to zero.\n        /// Note: Equivalent to Identity.\n        /// </summary>\n        public static __type__ Zero\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Identity;\n        }\n\n        //# dfields.ForEach((fi, i) => {\n        /// <summary>\n        /// Gets a <see cref=\"__type__\"/> transformation with components (/*# dfields.ForEach((fj, j) => { var val = (i != j) ? \"0\" : \"1\"; */__val__/*# }, comma); */).\n        /// </summary>\n        public static __type__ __fi__Axis\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(/*# dfields.ForEach((fj, j) => { var val = (i != j) ? \"0\" : \"1\"; */__val__/*# }, comma); */);\n        }\n\n        //# });\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Negates the values of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator -(__type__ shift)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */-shift.__f__/*# }, comma); */);\n        }\n\n        #region Shift / Scalar\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a __ftype__ scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ shift, __ftype__ scalar)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */shift.__f__ * scalar/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Multiplies a __ftype__ scalar with a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__ftype__ scalar, __type__ shift)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */shift.__f__ * scalar/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Divides a <see cref=\"__type__\"/> transformation by a __ftype__ scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__type__ shift, __ftype__ scalar)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */shift.__f__ / scalar/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Divides a __ftype__ scalar by a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator /(__ftype__ scalar, __type__ shift)\n        {\n            return new __type__(/*# dfields.ForEach(f => { */scalar / shift.__f__/*# }, comma); */);\n        }\n\n        #endregion\n\n        #region Shift / Vector Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__vdt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vdt__ operator *(__type__ shift, __vdt__ vector)\n        {\n            return new __vdt__(/*# dfields.ForEach(f => { */vector.__f__ + shift.__f__/*# }, comma); */);\n        }\n\n        #endregion\n\n        #region Shift / Shift Multiplication\n\n        //# for (int n = 2; n <= 3; n++) {\n        //# var r = (d > n) ? d : n;\n        //# var m = (d < n) ? d : n;\n        //# var mfields = fields.Take(m);\n        //# var rem = r - m;\n        //# var ntype = \"Shift\" + n + tc;\n        //# var rtype = \"Shift\" + r + tc;\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__ntype__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ operator *(__type__ a, __ntype__ b)\n            => new __rtype__(/*# mfields.ForEach(f => {*/a.__f__ + b.__f__/*# }, comma);\n                if (r > m) {*/, /*# rem.ForEach(i => {\n                var x = (d > n) ? \"a\" : \"b\";\n                var f = fields[m + i]; */__x__.__f__/*#}, comma); } */);\n\n        //# }\n        #endregion\n\n        #region Shift / Matrix Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __d__x__d1__ matrix) with a <see cref=\"__mddt__\"/> (as a __d1__x__d1__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mdd1t__ operator *(__type__ shift, __mddt__ matrix)\n        {\n            return new __mdd1t__(matrix, shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mddt__\"/> with a <see cref=\"__type__\"/> transformation (as a __d__x__d1__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mdd1t__ operator *(__mddt__ matrix, __type__ shift)\n        {\n            return new __mdd1t__(matrix, matrix * shift.V);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __d1__x__d1__ matrix) with a <see cref=\"__md1d1t__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __md1d1t__ operator *(__type__ s, __md1d1t__ m)\n        {\n            return new __md1d1t__(/*# dfields.ForEach((fi, i) => { d1.ForEach(j => { */\n                m.M__i____j__ + s.__fi__ * m.M__d____j__/*# }, comma); }, commaln);*/,\n\n                /*# d1.ForEach(j => {*/m.M__d____j__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__md1d1t__\"/> with a <see cref=\"__type__\"/> transformation (as a __d1__x__d1__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __md1d1t__ operator *(__md1d1t__ m, __type__ s)\n        {\n            return new __md1d1t__(/*# d1.ForEach(i => { dfields.ForEach((fj, j) => { */\n                m.M__i____j__/*# }, comma);*/,\n                /*# dfields.ForEach((fj, j) => {\n                */s.__fj__ * m.M__i____j__/*# }, add);\n                */ + m.M__i____d__/*# }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __d__x__d1__ matrix) with a <see cref=\"__mdd1t__\"/> (as a __d1__x__d1__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mdd1t__ operator *(__type__ s, __mdd1t__ m)\n        {\n            return new __mdd1t__(/*# dfields.ForEach((fi, i) => { */\n                /*# dfields.ForEach((fj, j) => {*/m.M__i____j__/*# }, comma);*/, m.M__i____d__ + s.__fi__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mdd1t__\"/> with a <see cref=\"__type__\"/> transformation (as a __d1__x__d1__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mdd1t__ operator *(__mdd1t__ m, __type__ s)\n        {\n            return new __mdd1t__(/*# d.ForEach(i => { dfields.ForEach((fj, j) => { */\n                m.M__i____j__/*# }, comma);*/,\n                /*# dfields.ForEach((fj, j) => {\n                */s.__fj__ * m.M__i____j__/*# }, add);\n                */ + m.M__i____d__/*# }, commaln);*/);\n        }\n\n        #endregion\n\n        #region Shift / Rot, Scale Multiplication\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__rotdt__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __euclideandt__ operator *(__type__ a, __rotdt__ b)\n            => new __euclideandt__(b, a.V);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation with a <see cref=\"__scaledt__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affinedt__ operator *(__type__ a, __scaledt__ b)\n            => new __affinedt__((__mddt__)b, a.V);\n\n        #endregion\n\n        #endregion\n\n        #region Comparison Operators\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ s0, __type__ s1)\n            => /*# dfields.ForEach(f => {*/s0.__f__ == s1.__f__/*# }, and);*/;\n\n        /// <summary>\n        /// Checks whether two <see cref=\"__type__\"/> transformations are different.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ s0, __type__ s1)\n            => /*# dfields.ForEach(f => {*/s0.__f__ != s1.__f__/*# }, or);*/;\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__mdd1t__\"/> matrix.\n        /// The matrix must only contain translation components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mdd1t__(__mdd1t__ m, __ftype__ epsilon = (__ftype__)1e-6)\n        {\n            if (!__mddt__.Identity.ApproximateEquals((__mddt__)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            return new __type__(m.C__d__);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a translation <see cref=\"__md1d1t__\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__md1d1t__(__md1d1t__ m, __ftype__ epsilon = (__ftype__)1e-6)\n        {\n            if (!__mddt__.Identity.ApproximateEquals((__mddt__)m, epsilon))\n                throw new ArgumentException(\"Matrix is not a pure translation matrix.\");\n\n            if (!(/*#d.ForEach(j => {*/m.M__d____j__.IsTiny(epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M__d____d__.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return new __type__(m.C__d__.__xyz__ / m.M__d____d__);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__euclideandt__\"/>.\n        /// The transformation <paramref name=\"euclidean\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__euclideandt__(__euclideandt__ euclidean, __ftype__ epsilon = __eps__)\n        {\n            if (!euclidean.Rot.ApproximateEquals(__rotdt__.Identity, epsilon))\n                throw new ArgumentException(\"Euclidean transformation contains rotational component\");\n\n            return new __type__(euclidean.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__similaritydt__\"/>.\n        /// The transformation <paramref name=\"similarity\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__similaritydt__(__similaritydt__ similarity, __ftype__ epsilon = __eps__)\n        {\n            if (!similarity.Scale.ApproximateEquals(1, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains scaling component\");\n\n            if (!similarity.Rot.ApproximateEquals(__rotdt__.Identity, epsilon))\n                throw new ArgumentException(\"Similarity transformation contains rotational component\");\n\n            return new __type__(similarity.Trans);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from an <see cref=\"__affinedt__\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__affinedt__(__affinedt__ affine, __ftype__ epsilon = __eps__)\n            => From__md1d1t__((__md1d1t__)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__trafodt__\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__trafodt__(__trafodt__ trafo, __ftype__ epsilon = __eps__)\n            => From__md1d1t__(trafo.Forward, epsilon);\n\n        #endregion\n\n        #region Conversion\n\n        //# for (int n = 3; n <= 4; n++) {\n        //#     var m = n - 1;\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M__n____n____tc__(__type__ s)\n        {\n            return new M__n____n____tc__(/*# fields.Take(m).ForEach((fi, i) => { */\n                /*# var f = (i < d) ? \"s.\" + fi : \"0\";\n                   m.ForEach(j => {\n                   var x = (i == j) ? \"1\" : \"0\";\n                */__x__/*# }, comma);*/, __f__/*# }, comma);*/,\n                /*# m.ForEach(i => { */0/*# }, comma);*/, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M__m____n____tc__(__type__ s)\n        {\n            return new M__m____n____tc__(/*# fields.Take(m).ForEach((fi, i) => { */\n                /*# var f = (i < d) ? \"s.\" + fi : \"0\";\n                   m.ForEach(j => {\n                   var x = (i == j) ? \"1\" : \"0\";\n                */__x__/*# }, comma);*/, __f__/*# }, comma);*/);\n        }\n\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __euclideandt__(__type__ s)\n            => new __euclideandt__(__rotdt__.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __similaritydt__(__type__ s)\n            => new __similaritydt__(1, __rotdt__.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __affinedt__(__type__ s)\n            => new __affinedt__(__mddt__.Identity, s.V);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __trafodt__(__type__ s)\n            => new __trafodt__((__md1d1t__)s, (__md1d1t__)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ s)\n            => new __type2__((__vdt2__)s.V);\n\n        /// <summary>\n        /// Returns all values of a <see cref=\"__type__\"/> instance\n        /// in a __ftype__[] array.\n        /// </summary>\n        public static explicit operator __ftype__[](__type__ shift)\n        {\n            __ftype__[] array = new __ftype__[__d__];\n            /*# dfields.ForEach((f, i) => {*/array[__i__] = shift.__f__;\n            /*# });*/return array;\n        }\n\n        #endregion\n\n        #region Indexing\n\n        public __ftype__ this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get => V[index];\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set => V[index] = value;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return V.GetHashCode();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => /*# dfields.ForEach(f => {*/__f__.Equals(other.__f__)/*# }, and);*/;\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[/*# d.ForEach(i => {*/{__i__}/*# }, comma);*/]\", /*# dfields.ForEach(f => {*/__f__/*#}, comma);*/);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(/*# d.ForEach(i => {*/\n                __ftype__.Parse(x[__i__], CultureInfo.InvariantCulture)/*# }, comma);*/\n            );\n        }\n\n        #endregion\n    }\n\n    public static partial class Shift\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ shift)\n            => shift.Inverse;\n\n        /// <summary>\n        /// Inverts a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref __type__ shift)\n        {\n            //# dfields.ForEach(f => {\n            shift.V.__f__ = -shift.V.__f__;\n            //# });\n        }\n\n        #endregion\n\n        #region Transformations\n\n        //# for (int n = d; n <= 4; n++) {\n        //# var vec = \"V\" + n + tc;\n        //# var rem = n - d;\n        //# var constfields = fields.Skip(d).Take(rem);\n        //# var isare = (rem > 1) ? \"are\" : \"is\";\n        /// <summary>\n        /// Transforms a <see cref=\"__vec__\"/> vector by a <see cref=\"__type__\"/> transformation./*# if (rem > 0) { */\n        /// /*# constfields.ForEach(f => {*/v.__f__/*# }, andLit); */ __isare__ not modified./*# }*/\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vec__ Transform(this __type__ s, __vec__ v)\n            => new __vec__(/*# dfields.ForEach(f => {*/v.__f__ + s.__f__/*# }, comma);\n                if (rem > 0) {*/, /*# rem.ForEach(i => {\n                var f = fields[d + i]; */v.__f__/*#}, comma); } */);\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vec__\"/> vector by the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vec__ InvTransform(this __type__ s, __vec__ v)\n            => new __vec__(/*# dfields.ForEach(f => {*/v.__f__ - s.__f__/*# }, comma);\n                if (rem > 0) {*/, /*# rem.ForEach(i => {\n                var f = fields[d + i]; */v.__f__/*#}, comma); } */);\n\n        //# }\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ s0, __type__ s1)\n        {\n            return ApproximateEquals(s0.V, s1.V, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ s0, __type__ s1, __ftype__ tolerance)\n        {\n            return ApproximateEquals(s0.V, s1.V, tolerance);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Similarity_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    #region Similarity2f\n\n    /// <summary>\n    /// Represents a Similarity Transformation in 2D that is composed of a\n    /// Uniform Scale and a subsequent Euclidean transformation (2D rotation Rot and a subsequent translation by a 2D vector Trans).\n    /// This is an angle preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Similarity2f : IEquatable<Similarity2f>\n    {\n        [DataMember]\n        public float Scale;\n        [DataMember]\n        public Euclidean2f Euclidean;\n\n        /// <summary>\n        /// Gets the rotational component of this <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        public readonly Rot2f Rot\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Rot; }\n        }\n\n        /// <summary>\n        /// Gets the translational component of this <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        public readonly V2f Trans\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Trans; }\n        }\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(Similarity2f s)\n        {\n            Scale = s.Scale;\n            Euclidean = s.Euclidean;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Similarity2f\"/> transformation from a <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(Similarity2d s)\n        {\n            Scale = (float)s.Scale;\n            Euclidean = (Euclidean2f)s.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from an uniform scale by factor <paramref name=\"scale\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(float scale)\n        {\n            Scale = scale;\n            Euclidean = Euclidean2f.Identity;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(Euclidean2f euclideanTransformation)\n        {\n            Scale = 1;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(Rot2f rotation, V2f translation)\n        {\n            Scale = 1;\n            Euclidean = new Euclidean2f(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(Rot2f rotation, float tX, float tY)\n        {\n            Scale = 1;\n            Euclidean = new Euclidean2f(rotation, tX, tY);\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(float scale, Euclidean2f euclideanTransformation)\n        {\n            Scale = scale;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(float scale, Rot2f rotation, V2f translation)\n        {\n            Scale = scale;\n            Euclidean = new Euclidean2f(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and and translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2f(float scale, Rot2f rotation, float tX, float tY)\n        {\n            Scale = scale;\n            Euclidean = new Euclidean2f(rotation, tX, tY);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Similarity2f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Similarity2f(1, Euclidean2f.Identity);\n        }\n\n        #endregion\n\n        #region Similarity Transformation Arithmetics\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Similarity transformation.\n        /// [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        public readonly Similarity2f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newS = 1 / Scale;\n                var newR = Euclidean.Inverse;\n                newR.Trans *= newS;\n                return new Similarity2f(newS, newR);\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Similarity transformations.\n        /// This concatenates the two similarity transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f operator *(Similarity2f a, Similarity2f b)\n        {\n            //a.Scale * b.Scale, a.Rot * b.Rot, a.Trans + a.Rot * a.Scale * b.Trans\n            return new Similarity2f(a.Scale * b.Scale, new Euclidean2f(\n                a.Rot * b.Rot,\n                a.Trans + a.Rot.Transform(a.Scale * b.Trans))\n                );\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> vector by a <see cref=\"Similarity2f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(Similarity2f s, V3f v)\n            => s.Euclidean * new V3f(s.Scale * v.X, s.Scale * v.Y, v.Z);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2f\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(Similarity2f s, M33f m)\n        {\n            var t = (M23f)s;\n            return new M33f(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22,\n\n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> with a <see cref=\"Similarity2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f operator *(M33f m, Similarity2f s)\n        {\n            var t = (M23f)s;\n            return new M33f(\n                m.M00 * t.M00 + m.M01 * t.M10, \n                m.M00 * t.M01 + m.M01 * t.M11, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02,\n\n                m.M10 * t.M00 + m.M11 * t.M10, \n                m.M10 * t.M01 + m.M11 * t.M11, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12,\n\n                m.M20 * t.M00 + m.M21 * t.M10, \n                m.M20 * t.M01 + m.M21 * t.M11, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2f\"/> transformation (as a 2x3 matrix) with a <see cref=\"M23f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Similarity2f s, M23f m)\n        {\n            var t = (M23f)s;\n            return new M23f(\n                t.M00 * m.M00 + t.M01 * m.M10, \n                t.M00 * m.M01 + t.M01 * m.M11, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02,\n\n                t.M10 * m.M00 + t.M11 * m.M10, \n                t.M10 * m.M01 + t.M11 * m.M11, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23f\"/> with a <see cref=\"Similarity2f\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M23f m, Similarity2f s)\n        {\n            var t = (M23f)s;\n            return new M23f(\n                m.M00 * t.M00 + m.M01 * t.M10, \n                m.M00 * t.M01 + m.M01 * t.M11, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02,\n\n                m.M10 * t.M00 + m.M11 * t.M10, \n                m.M10 * t.M01 + m.M11 * t.M11, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2f\"/> (as a 2x3 matrix) and a <see cref=\"M22f\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(Similarity2f s, M22f m)\n            => new M23f(s.Rot * m * s.Scale, s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22f\"/> and a <see cref=\"Similarity2f\"/> (as a 2x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23f operator *(M22f m, Similarity2f s)\n            => new M23f(s.Scale * m * s.Rot, m * s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2f\"/> and a <see cref=\"Rot2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f operator *(Similarity2f s, Rot2f r)\n            => new Similarity2f(s.Scale, s.Euclidean * r);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2f\"/> and a <see cref=\"Similarity2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f operator *(Rot2f r, Similarity2f s)\n               => new Similarity2f(s.Scale, r * s.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2f\"/> and a <see cref=\"Shift2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f operator *(Similarity2f a, Shift2f b)\n            => new Similarity2f(a.Scale, a.Euclidean * (a.Scale * b));\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2f\"/> and a <see cref=\"Similarity2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f operator *(Shift2f a, Similarity2f b)\n            => new Similarity2f(b.Scale, a * b.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2f\"/> and a <see cref=\"Scale2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Similarity2f a, Scale2f b)\n        {\n            var t = (M22f)a;\n            return new Affine2f(new M22f(\n                t.M00 * b.X, t.M01 * b.Y, \n                t.M10 * b.X, t.M11 * b.Y),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2f\"/> and a <see cref=\"Similarity2f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2f operator *(Scale2f a, Similarity2f b)\n        {\n            var t = (M22f)b;\n            return new Affine2f(new M22f(\n                t.M00 * a.X, t.M01 * a.X, \n                t.M10 * a.Y, t.M11 * a.Y),\n                b.Trans * a.V);\n        }\n\n        /// <summary>\n        /// Multiplies an Euclidean transformation by a Similarity transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f operator *(Euclidean2f a, Similarity2f b)\n        {\n            return new Similarity2f(b.Scale, a * b.Euclidean);\n            //return (Similarity2f)a * b;\n        }\n\n        /// <summary>\n        /// Multiplies a Similarity transformation by an Euclidean transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f operator *(Similarity2f a, Euclidean2f b)\n        {\n            return a * (Similarity2f)b;\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Similarity2f t0, Similarity2f t1)\n        {\n            return t0.Scale == t1.Scale && t0.Euclidean == t1.Euclidean;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Similarity2f t0, Similarity2f t1)\n        {\n            return !(t0 == t1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2f\"/> transformation from a <see cref=\"M22f\"/> matrix and a translation <see cref=\"V2f\"/>.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f FromM22fAndV2f(M22f m, V2f trans, float epsilon = 1e-5f)\n        {\n            var s0 = m.C0.Norm2;\n            var s1 = m.C1.Norm2;\n            var s = (s0 * s1).Pow(1.0f / 2); //geometric mean of scale\n\n            if (!((s0 / s - 1).IsTiny(epsilon) && (s1 / s - 1).IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            m /= s;\n            return new Similarity2f(s, Euclidean2f.FromM22fAndV2f(m, trans));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2f\"/> transformation from a <see cref=\"M23f\"/> matrix.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f FromM23f(M23f m, float epsilon = 1e-5f)\n            => FromM22fAndV2f((M22f)m, m.C2);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2f\"/> transformation from a <see cref=\"M33f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components or\n        /// a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f FromM33f(M33f m, float epsilon = 1e-5f)\n        {\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM22fAndV2f(((M22f)m) / m.M22, m.C2.XY);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2f\"/> transformation from an <see cref=\"Scale2f\"/>.\n        /// The transformation <paramref name=\"scale\"/> must represent a uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f FromScale2f(Scale2f scale, float epsilon = 1e-5f)\n        {\n            var s = (scale.X * scale.Y).Pow(1.0f / 2);\n\n            if (!scale.ApproximateEquals(new Scale2f(s), epsilon))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            return new Similarity2f(s, Euclidean2f.Identity);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2f\"/> transformation from an <see cref=\"Affine2f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f FromAffine2f(Affine2f affine, float epsilon = 1e-5f)\n            => FromM33f((M33f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2f\"/> transformation from a <see cref=\"Trafo2f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f FromTrafo2f(Trafo2f trafo, float epsilon = 1e-5f)\n            => FromM33f(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f Scaling(float scaleFactor)\n            => new Similarity2f(scaleFactor);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2f\"/> transformation with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f Translation(float tX, float tY)\n            => new Similarity2f(Rot2f.Identity, tX, tY);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2f\"/> transformation with the translational component given by a <see cref=\"V2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f Translation(V2f vector)\n            => new Similarity2f(Rot2f.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Similarity2f\"/> transformation with the translational component given by a <see cref=\"Shift2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f Translation(Shift2f shift)\n            => new Similarity2f(Rot2f.Identity, shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f Rotation(Rot2f rot)\n            => new Similarity2f(rot, V2f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f Rotation(float angleInRadians)\n            => new Similarity2f(new Rot2f(angleInRadians), V2f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f RotationInDegrees(float angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23f(Similarity2f s)\n        {\n            M23f rv = (M23f)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22f(Similarity2f s)\n        {\n            M22f rv = (M22f)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Similarity2f s)\n        {\n            M33f rv = (M33f)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2f(Similarity2f s)\n        {\n            var m = (M23f)s;\n            return new Affine2f((M22f)m, m.C2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2f(Similarity2f s)\n            => new Trafo2f((M33f)s, (M33f)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity2d(Similarity2f s)\n            => new Similarity2d((double)s.Scale, (Euclidean2d)s.Euclidean);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Scale, Euclidean);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Similarity2f other)\n            => Scale.Equals(other.Scale) && Euclidean.Equals(other.Euclidean);\n\n        public override readonly bool Equals(object other)\n            => (other is Similarity2f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Scale, Euclidean);\n        }\n\n        public static Similarity2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Similarity2f(float.Parse(x[0], CultureInfo.InvariantCulture), Euclidean2f.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Similarity\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2f Inverse(Similarity2f s)\n            => s.Inverse;\n\n        /// <summary>\n        /// Inverts the similarity transformation (multiplicative inverse).\n        /// this = [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Similarity2f t)\n        {\n            t.Scale = 1 / t.Scale;\n            t.Euclidean.Invert();\n            t.Euclidean.Trans *= t.Scale;\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> by a <see cref=\"Similarity2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Similarity2f s, V3f v)\n            => s * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformDir(this Similarity2f t, V2f v)\n        {\n            return t.Euclidean.TransformDir(t.Scale * v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformPos(this Similarity2f t, V2f p)\n        {\n            return t.Euclidean.TransformPos(t.Scale * p);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransformDir(this Similarity2f t, V2f v)\n        {\n            return t.Euclidean.InvTransformDir(v) / t.Scale;\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransformPos(this Similarity2f t, V2f p)\n        {\n            return t.Euclidean.InvTransformPos(p) / t.Scale;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity2f t0, Similarity2f t1)\n        {\n            return ApproximateEquals(t0, t1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity2f t0, Similarity2f t1, float tol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, tol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity2f t0, Similarity2f t1, float angleTol, float posTol, float scaleTol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, scaleTol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, angleTol, posTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Similarity3f\n\n    /// <summary>\n    /// Represents a Similarity Transformation in 3D that is composed of a\n    /// Uniform Scale and a subsequent Euclidean transformation (3D rotation Rot and a subsequent translation by a 3D vector Trans).\n    /// This is an angle preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Similarity3f : IEquatable<Similarity3f>\n    {\n        [DataMember]\n        public float Scale;\n        [DataMember]\n        public Euclidean3f Euclidean;\n\n        /// <summary>\n        /// Gets the rotational component of this <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        public readonly Rot3f Rot\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Rot; }\n        }\n\n        /// <summary>\n        /// Gets the translational component of this <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        public readonly V3f Trans\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Trans; }\n        }\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(Similarity3f s)\n        {\n            Scale = s.Scale;\n            Euclidean = s.Euclidean;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Similarity3f\"/> transformation from a <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(Similarity3d s)\n        {\n            Scale = (float)s.Scale;\n            Euclidean = (Euclidean3f)s.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from an uniform scale by factor <paramref name=\"scale\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(float scale)\n        {\n            Scale = scale;\n            Euclidean = Euclidean3f.Identity;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(Euclidean3f euclideanTransformation)\n        {\n            Scale = 1;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(Rot3f rotation, V3f translation)\n        {\n            Scale = 1;\n            Euclidean = new Euclidean3f(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>, <paramref name=\"tZ\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(Rot3f rotation, float tX, float tY, float tZ)\n        {\n            Scale = 1;\n            Euclidean = new Euclidean3f(rotation, tX, tY, tZ);\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(float scale, Euclidean3f euclideanTransformation)\n        {\n            Scale = scale;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(float scale, Rot3f rotation, V3f translation)\n        {\n            Scale = scale;\n            Euclidean = new Euclidean3f(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and and translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>, <paramref name=\"tZ\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3f(float scale, Rot3f rotation, float tX, float tY, float tZ)\n        {\n            Scale = scale;\n            Euclidean = new Euclidean3f(rotation, tX, tY, tZ);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Similarity3f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Similarity3f(1, Euclidean3f.Identity);\n        }\n\n        #endregion\n\n        #region Similarity Transformation Arithmetics\n\n        /// <summary>\n        /// Returns a new version of this Similarity transformation with a normalized rotation quaternion.\n        /// </summary>\n        public readonly Similarity3f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Similarity3f(Scale, Euclidean.Normalized);\n        }\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Similarity transformation.\n        /// [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        public readonly Similarity3f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newS = 1 / Scale;\n                var newR = Euclidean.Inverse;\n                newR.Trans *= newS;\n                return new Similarity3f(newS, newR);\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Similarity transformations.\n        /// This concatenates the two similarity transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f operator *(Similarity3f a, Similarity3f b)\n        {\n            //a.Scale * b.Scale, a.Rot * b.Rot, a.Trans + a.Rot * a.Scale * b.Trans\n            return new Similarity3f(a.Scale * b.Scale, new Euclidean3f(\n                a.Rot * b.Rot,\n                a.Trans + a.Rot.Transform(a.Scale * b.Trans))\n                );\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> vector by a <see cref=\"Similarity3f\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(Similarity3f s, V4f v)\n            => s.Euclidean * new V4f(s.Scale * v.X, s.Scale * v.Y, s.Scale * v.Z, v.W);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3f\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(Similarity3f s, M44f m)\n        {\n            var t = (M34f)s;\n            return new M44f(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20 + t.M03 * m.M30, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21 + t.M03 * m.M31, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22 + t.M03 * m.M32, \n                t.M00 * m.M03 + t.M01 * m.M13 + t.M02 * m.M23 + t.M03 * m.M33,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20 + t.M13 * m.M30, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21 + t.M13 * m.M31, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22 + t.M13 * m.M32, \n                t.M10 * m.M03 + t.M11 * m.M13 + t.M12 * m.M23 + t.M13 * m.M33,\n\n                t.M20 * m.M00 + t.M21 * m.M10 + t.M22 * m.M20 + t.M23 * m.M30, \n                t.M20 * m.M01 + t.M21 * m.M11 + t.M22 * m.M21 + t.M23 * m.M31, \n                t.M20 * m.M02 + t.M21 * m.M12 + t.M22 * m.M22 + t.M23 * m.M32, \n                t.M20 * m.M03 + t.M21 * m.M13 + t.M22 * m.M23 + t.M23 * m.M33,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44f\"/> with a <see cref=\"Similarity3f\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f operator *(M44f m, Similarity3f s)\n        {\n            var t = (M34f)s;\n            return new M44f(\n                m.M00 * t.M00 + m.M01 * t.M10 + m.M02 * t.M20, \n                m.M00 * t.M01 + m.M01 * t.M11 + m.M02 * t.M21, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02 * t.M22, \n                m.M00 * t.M03 + m.M01 * t.M13 + m.M02 * t.M23 + m.M03,\n\n                m.M10 * t.M00 + m.M11 * t.M10 + m.M12 * t.M20, \n                m.M10 * t.M01 + m.M11 * t.M11 + m.M12 * t.M21, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12 * t.M22, \n                m.M10 * t.M03 + m.M11 * t.M13 + m.M12 * t.M23 + m.M13,\n\n                m.M20 * t.M00 + m.M21 * t.M10 + m.M22 * t.M20, \n                m.M20 * t.M01 + m.M21 * t.M11 + m.M22 * t.M21, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22 * t.M22, \n                m.M20 * t.M03 + m.M21 * t.M13 + m.M22 * t.M23 + m.M23,\n\n                m.M30 * t.M00 + m.M31 * t.M10 + m.M32 * t.M20, \n                m.M30 * t.M01 + m.M31 * t.M11 + m.M32 * t.M21, \n                m.M30 * t.M02 + m.M31 * t.M12 + m.M32 * t.M22, \n                m.M30 * t.M03 + m.M31 * t.M13 + m.M32 * t.M23 + m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3f\"/> transformation (as a 3x4 matrix) with a <see cref=\"M34f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Similarity3f s, M34f m)\n        {\n            var t = (M34f)s;\n            return new M34f(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22, \n                t.M00 * m.M03 + t.M01 * m.M13 + t.M02 * m.M23 + t.M03,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22, \n                t.M10 * m.M03 + t.M11 * m.M13 + t.M12 * m.M23 + t.M13,\n\n                t.M20 * m.M00 + t.M21 * m.M10 + t.M22 * m.M20, \n                t.M20 * m.M01 + t.M21 * m.M11 + t.M22 * m.M21, \n                t.M20 * m.M02 + t.M21 * m.M12 + t.M22 * m.M22, \n                t.M20 * m.M03 + t.M21 * m.M13 + t.M22 * m.M23 + t.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34f\"/> with a <see cref=\"Similarity3f\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M34f m, Similarity3f s)\n        {\n            var t = (M34f)s;\n            return new M34f(\n                m.M00 * t.M00 + m.M01 * t.M10 + m.M02 * t.M20, \n                m.M00 * t.M01 + m.M01 * t.M11 + m.M02 * t.M21, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02 * t.M22, \n                m.M00 * t.M03 + m.M01 * t.M13 + m.M02 * t.M23 + m.M03,\n\n                m.M10 * t.M00 + m.M11 * t.M10 + m.M12 * t.M20, \n                m.M10 * t.M01 + m.M11 * t.M11 + m.M12 * t.M21, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12 * t.M22, \n                m.M10 * t.M03 + m.M11 * t.M13 + m.M12 * t.M23 + m.M13,\n\n                m.M20 * t.M00 + m.M21 * t.M10 + m.M22 * t.M20, \n                m.M20 * t.M01 + m.M21 * t.M11 + m.M22 * t.M21, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22 * t.M22, \n                m.M20 * t.M03 + m.M21 * t.M13 + m.M22 * t.M23 + m.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3f\"/> (as a 3x4 matrix) and a <see cref=\"M33f\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(Similarity3f s, M33f m)\n            => new M34f(s.Rot * m * s.Scale, s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33f\"/> and a <see cref=\"Similarity3f\"/> (as a 3x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34f operator *(M33f m, Similarity3f s)\n            => new M34f(s.Scale * m * s.Rot, m * s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3f\"/> and a <see cref=\"Rot3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f operator *(Similarity3f s, Rot3f r)\n            => new Similarity3f(s.Scale, s.Euclidean * r);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3f\"/> and a <see cref=\"Similarity3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f operator *(Rot3f r, Similarity3f s)\n               => new Similarity3f(s.Scale, r * s.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3f\"/> and a <see cref=\"Shift3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f operator *(Similarity3f a, Shift3f b)\n            => new Similarity3f(a.Scale, a.Euclidean * (a.Scale * b));\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3f\"/> and a <see cref=\"Similarity3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f operator *(Shift3f a, Similarity3f b)\n            => new Similarity3f(b.Scale, a * b.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3f\"/> and a <see cref=\"Scale3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Similarity3f a, Scale3f b)\n        {\n            var t = (M33f)a;\n            return new Affine3f(new M33f(\n                t.M00 * b.X, t.M01 * b.Y, t.M02 * b.Z, \n                t.M10 * b.X, t.M11 * b.Y, t.M12 * b.Z, \n                t.M20 * b.X, t.M21 * b.Y, t.M22 * b.Z),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3f\"/> and a <see cref=\"Similarity3f\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3f operator *(Scale3f a, Similarity3f b)\n        {\n            var t = (M33f)b;\n            return new Affine3f(new M33f(\n                t.M00 * a.X, t.M01 * a.X, t.M02 * a.X, \n                t.M10 * a.Y, t.M11 * a.Y, t.M12 * a.Y, \n                t.M20 * a.Z, t.M21 * a.Z, t.M22 * a.Z),\n                b.Trans * a.V);\n        }\n\n        /// <summary>\n        /// Multiplies an Euclidean transformation by a Similarity transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f operator *(Euclidean3f a, Similarity3f b)\n        {\n            return new Similarity3f(b.Scale, a * b.Euclidean);\n            //return (Similarity3f)a * b;\n        }\n\n        /// <summary>\n        /// Multiplies a Similarity transformation by an Euclidean transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f operator *(Similarity3f a, Euclidean3f b)\n        {\n            return a * (Similarity3f)b;\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Similarity3f t0, Similarity3f t1)\n        {\n            return t0.Scale == t1.Scale && t0.Euclidean == t1.Euclidean;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Similarity3f t0, Similarity3f t1)\n        {\n            return !(t0 == t1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3f\"/> transformation from a <see cref=\"M33f\"/> matrix and a translation <see cref=\"V3f\"/>.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f FromM33fAndV3f(M33f m, V3f trans, float epsilon = 1e-5f)\n        {\n            var s0 = m.C0.Norm2;\n            var s1 = m.C1.Norm2;\n            var s2 = m.C2.Norm2;\n            var s = (s0 * s1 * s2).Pow(1.0f / 3); //geometric mean of scale\n\n            if (!((s0 / s - 1).IsTiny(epsilon) && (s1 / s - 1).IsTiny(epsilon) && (s2 / s - 1).IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            m /= s;\n            return new Similarity3f(s, Euclidean3f.FromM33fAndV3f(m, trans, epsilon));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3f\"/> transformation from a <see cref=\"M34f\"/> matrix.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f FromM34f(M34f m, float epsilon = 1e-5f)\n            => FromM33fAndV3f((M33f)m, m.C3, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3f\"/> transformation from a <see cref=\"M44f\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components or\n        /// a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f FromM44f(M44f m, float epsilon = 1e-5f)\n        {\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM33fAndV3f(((M33f)m) / m.M33, m.C3.XYZ, epsilon);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3f\"/> transformation from an <see cref=\"Scale3f\"/>.\n        /// The transformation <paramref name=\"scale\"/> must represent a uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f FromScale3f(Scale3f scale, float epsilon = 1e-5f)\n        {\n            var s = (scale.X * scale.Y * scale.Z).Pow(1.0f / 3);\n\n            if (!scale.ApproximateEquals(new Scale3f(s), epsilon))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            return new Similarity3f(s, Euclidean3f.Identity);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3f\"/> transformation from an <see cref=\"Affine3f\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f FromAffine3f(Affine3f affine, float epsilon = 1e-5f)\n            => FromM44f((M44f)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3f\"/> transformation from a <see cref=\"Trafo3f\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f FromTrafo3f(Trafo3f trafo, float epsilon = 1e-5f)\n            => FromM44f(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f Scaling(float scaleFactor)\n            => new Similarity3f(scaleFactor);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3f\"/> transformation with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f Translation(float tX, float tY, float tZ)\n            => new Similarity3f(Rot3f.Identity, tX, tY, tZ);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3f\"/> transformation with the translational component given by a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f Translation(V3f vector)\n            => new Similarity3f(Rot3f.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Similarity3f\"/> transformation with the translational component given by a <see cref=\"Shift3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f Translation(Shift3f shift)\n            => new Similarity3f(Rot3f.Identity, shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f Rotation(Rot3f rot)\n            => new Similarity3f(rot, V3f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f Rotation(V3f normalizedAxis, float angleRadians)\n            => new Similarity3f(Rot3f.Rotation(normalizedAxis, angleRadians), V3f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationInDegrees(V3f normalizedAxis, float angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationEuler(float rollInRadians, float pitchInRadians, float yawInRadians)\n            => new Similarity3f(Rot3f.RotationEuler(rollInRadians, pitchInRadians, yawInRadians), V3f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationEulerInDegrees(float rollInDegrees, float pitchInDegrees, float yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationEuler(V3f rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationEulerInDegrees(V3f rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotateInto(V3f from, V3f into)\n            => new Similarity3f(Rot3f.RotateInto(from, into), V3f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationX(float angleRadians)\n            => new Similarity3f(Rot3f.RotationX(angleRadians), V3f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationXInDegrees(float angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationY(float angleRadians)\n            => new Similarity3f(Rot3f.RotationY(angleRadians), V3f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationYInDegrees(float angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationZ(float angleRadians)\n            => new Similarity3f(Rot3f.RotationZ(angleRadians), V3f.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f RotationZInDegrees(float angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34f(Similarity3f s)\n        {\n            M34f rv = (M34f)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; rv.M02 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; rv.M12 *= s.Scale; \n            rv.M20 *= s.Scale; rv.M21 *= s.Scale; rv.M22 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33f(Similarity3f s)\n        {\n            M33f rv = (M33f)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; rv.M02 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; rv.M12 *= s.Scale; \n            rv.M20 *= s.Scale; rv.M21 *= s.Scale; rv.M22 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44f(Similarity3f s)\n        {\n            M44f rv = (M44f)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; rv.M02 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; rv.M12 *= s.Scale; \n            rv.M20 *= s.Scale; rv.M21 *= s.Scale; rv.M22 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3f(Similarity3f s)\n        {\n            var m = (M34f)s;\n            return new Affine3f((M33f)m, m.C3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3f(Similarity3f s)\n            => new Trafo3f((M44f)s, (M44f)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity3d(Similarity3f s)\n            => new Similarity3d((double)s.Scale, (Euclidean3d)s.Euclidean);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Scale, Euclidean);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Similarity3f other)\n            => Scale.Equals(other.Scale) && Euclidean.Equals(other.Euclidean);\n\n        public override readonly bool Equals(object other)\n            => (other is Similarity3f o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Scale, Euclidean);\n        }\n\n        public static Similarity3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Similarity3f(float.Parse(x[0], CultureInfo.InvariantCulture), Euclidean3f.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Similarity\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f Inverse(Similarity3f s)\n            => s.Inverse;\n\n        /// <summary>\n        /// Inverts the similarity transformation (multiplicative inverse).\n        /// this = [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Similarity3f t)\n        {\n            t.Scale = 1 / t.Scale;\n            t.Euclidean.Invert();\n            t.Euclidean.Trans *= t.Scale;\n        }\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a copy of a <see cref=\"Similarity3f\"/> with its rotation quaternion normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3f Normalized(Similarity3f s)\n            => s.Normalized;\n\n        /// <summary>\n        /// Normalizes the rotation quaternion of a <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref Similarity3f t)\n        {\n            t.Euclidean.Normalize();\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> by a <see cref=\"Similarity3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Similarity3f s, V4f v)\n            => s * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformDir(this Similarity3f t, V3f v)\n        {\n            return t.Euclidean.TransformDir(t.Scale * v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformPos(this Similarity3f t, V3f p)\n        {\n            return t.Euclidean.TransformPos(t.Scale * p);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformDir(this Similarity3f t, V3f v)\n        {\n            return t.Euclidean.InvTransformDir(v) / t.Scale;\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformPos(this Similarity3f t, V3f p)\n        {\n            return t.Euclidean.InvTransformPos(p) / t.Scale;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity3f t0, Similarity3f t1)\n        {\n            return ApproximateEquals(t0, t1, Constant<float>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity3f t0, Similarity3f t1, float tol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, tol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity3f t0, Similarity3f t1, float angleTol, float posTol, float scaleTol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, scaleTol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, angleTol, posTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Similarity2d\n\n    /// <summary>\n    /// Represents a Similarity Transformation in 2D that is composed of a\n    /// Uniform Scale and a subsequent Euclidean transformation (2D rotation Rot and a subsequent translation by a 2D vector Trans).\n    /// This is an angle preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Similarity2d : IEquatable<Similarity2d>\n    {\n        [DataMember]\n        public double Scale;\n        [DataMember]\n        public Euclidean2d Euclidean;\n\n        /// <summary>\n        /// Gets the rotational component of this <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        public readonly Rot2d Rot\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Rot; }\n        }\n\n        /// <summary>\n        /// Gets the translational component of this <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        public readonly V2d Trans\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Trans; }\n        }\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(Similarity2d s)\n        {\n            Scale = s.Scale;\n            Euclidean = s.Euclidean;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Similarity2d\"/> transformation from a <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(Similarity2f s)\n        {\n            Scale = (double)s.Scale;\n            Euclidean = (Euclidean2d)s.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from an uniform scale by factor <paramref name=\"scale\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(double scale)\n        {\n            Scale = scale;\n            Euclidean = Euclidean2d.Identity;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(Euclidean2d euclideanTransformation)\n        {\n            Scale = 1;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(Rot2d rotation, V2d translation)\n        {\n            Scale = 1;\n            Euclidean = new Euclidean2d(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(Rot2d rotation, double tX, double tY)\n        {\n            Scale = 1;\n            Euclidean = new Euclidean2d(rotation, tX, tY);\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(double scale, Euclidean2d euclideanTransformation)\n        {\n            Scale = scale;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(double scale, Rot2d rotation, V2d translation)\n        {\n            Scale = scale;\n            Euclidean = new Euclidean2d(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and and translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity2d(double scale, Rot2d rotation, double tX, double tY)\n        {\n            Scale = scale;\n            Euclidean = new Euclidean2d(rotation, tX, tY);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Similarity2d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Similarity2d(1, Euclidean2d.Identity);\n        }\n\n        #endregion\n\n        #region Similarity Transformation Arithmetics\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Similarity transformation.\n        /// [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        public readonly Similarity2d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newS = 1 / Scale;\n                var newR = Euclidean.Inverse;\n                newR.Trans *= newS;\n                return new Similarity2d(newS, newR);\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Similarity transformations.\n        /// This concatenates the two similarity transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d operator *(Similarity2d a, Similarity2d b)\n        {\n            //a.Scale * b.Scale, a.Rot * b.Rot, a.Trans + a.Rot * a.Scale * b.Trans\n            return new Similarity2d(a.Scale * b.Scale, new Euclidean2d(\n                a.Rot * b.Rot,\n                a.Trans + a.Rot.Transform(a.Scale * b.Trans))\n                );\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> vector by a <see cref=\"Similarity2d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(Similarity2d s, V3d v)\n            => s.Euclidean * new V3d(s.Scale * v.X, s.Scale * v.Y, v.Z);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2d\"/> transformation (as a 3x3 matrix) with a <see cref=\"M33d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(Similarity2d s, M33d m)\n        {\n            var t = (M23d)s;\n            return new M33d(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22,\n\n                m.M20, m.M21, m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> with a <see cref=\"Similarity2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d operator *(M33d m, Similarity2d s)\n        {\n            var t = (M23d)s;\n            return new M33d(\n                m.M00 * t.M00 + m.M01 * t.M10, \n                m.M00 * t.M01 + m.M01 * t.M11, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02,\n\n                m.M10 * t.M00 + m.M11 * t.M10, \n                m.M10 * t.M01 + m.M11 * t.M11, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12,\n\n                m.M20 * t.M00 + m.M21 * t.M10, \n                m.M20 * t.M01 + m.M21 * t.M11, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2d\"/> transformation (as a 2x3 matrix) with a <see cref=\"M23d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Similarity2d s, M23d m)\n        {\n            var t = (M23d)s;\n            return new M23d(\n                t.M00 * m.M00 + t.M01 * m.M10, \n                t.M00 * m.M01 + t.M01 * m.M11, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02,\n\n                t.M10 * m.M00 + t.M11 * m.M10, \n                t.M10 * m.M01 + t.M11 * m.M11, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M23d\"/> with a <see cref=\"Similarity2d\"/> transformation (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M23d m, Similarity2d s)\n        {\n            var t = (M23d)s;\n            return new M23d(\n                m.M00 * t.M00 + m.M01 * t.M10, \n                m.M00 * t.M01 + m.M01 * t.M11, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02,\n\n                m.M10 * t.M00 + m.M11 * t.M10, \n                m.M10 * t.M01 + m.M11 * t.M11, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2d\"/> (as a 2x3 matrix) and a <see cref=\"M22d\"/> (as a 3x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(Similarity2d s, M22d m)\n            => new M23d(s.Rot * m * s.Scale, s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M22d\"/> and a <see cref=\"Similarity2d\"/> (as a 2x3 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M23d operator *(M22d m, Similarity2d s)\n            => new M23d(s.Scale * m * s.Rot, m * s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2d\"/> and a <see cref=\"Rot2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d operator *(Similarity2d s, Rot2d r)\n            => new Similarity2d(s.Scale, s.Euclidean * r);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot2d\"/> and a <see cref=\"Similarity2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d operator *(Rot2d r, Similarity2d s)\n               => new Similarity2d(s.Scale, r * s.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2d\"/> and a <see cref=\"Shift2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d operator *(Similarity2d a, Shift2d b)\n            => new Similarity2d(a.Scale, a.Euclidean * (a.Scale * b));\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift2d\"/> and a <see cref=\"Similarity2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d operator *(Shift2d a, Similarity2d b)\n            => new Similarity2d(b.Scale, a * b.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity2d\"/> and a <see cref=\"Scale2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Similarity2d a, Scale2d b)\n        {\n            var t = (M22d)a;\n            return new Affine2d(new M22d(\n                t.M00 * b.X, t.M01 * b.Y, \n                t.M10 * b.X, t.M11 * b.Y),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale2d\"/> and a <see cref=\"Similarity2d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine2d operator *(Scale2d a, Similarity2d b)\n        {\n            var t = (M22d)b;\n            return new Affine2d(new M22d(\n                t.M00 * a.X, t.M01 * a.X, \n                t.M10 * a.Y, t.M11 * a.Y),\n                b.Trans * a.V);\n        }\n\n        /// <summary>\n        /// Multiplies an Euclidean transformation by a Similarity transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d operator *(Euclidean2d a, Similarity2d b)\n        {\n            return new Similarity2d(b.Scale, a * b.Euclidean);\n            //return (Similarity2d)a * b;\n        }\n\n        /// <summary>\n        /// Multiplies a Similarity transformation by an Euclidean transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d operator *(Similarity2d a, Euclidean2d b)\n        {\n            return a * (Similarity2d)b;\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Similarity2d t0, Similarity2d t1)\n        {\n            return t0.Scale == t1.Scale && t0.Euclidean == t1.Euclidean;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Similarity2d t0, Similarity2d t1)\n        {\n            return !(t0 == t1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2d\"/> transformation from a <see cref=\"M22d\"/> matrix and a translation <see cref=\"V2d\"/>.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d FromM22dAndV2d(M22d m, V2d trans, double epsilon = 1e-12)\n        {\n            var s0 = m.C0.Norm2;\n            var s1 = m.C1.Norm2;\n            var s = (s0 * s1).Pow(1.0 / 2); //geometric mean of scale\n\n            if (!((s0 / s - 1).IsTiny(epsilon) && (s1 / s - 1).IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            m /= s;\n            return new Similarity2d(s, Euclidean2d.FromM22dAndV2d(m, trans));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2d\"/> transformation from a <see cref=\"M23d\"/> matrix.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d FromM23d(M23d m, double epsilon = 1e-12)\n            => FromM22dAndV2d((M22d)m, m.C2);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2d\"/> transformation from a <see cref=\"M33d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components or\n        /// a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d FromM33d(M33d m, double epsilon = 1e-12)\n        {\n            if (!(m.M20.IsTiny(epsilon) && m.M21.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M22.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM22dAndV2d(((M22d)m) / m.M22, m.C2.XY);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2d\"/> transformation from an <see cref=\"Scale2d\"/>.\n        /// The transformation <paramref name=\"scale\"/> must represent a uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d FromScale2d(Scale2d scale, double epsilon = 1e-12)\n        {\n            var s = (scale.X * scale.Y).Pow(1.0 / 2);\n\n            if (!scale.ApproximateEquals(new Scale2d(s), epsilon))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            return new Similarity2d(s, Euclidean2d.Identity);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2d\"/> transformation from an <see cref=\"Affine2d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d FromAffine2d(Affine2d affine, double epsilon = 1e-12)\n            => FromM33d((M33d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2d\"/> transformation from a <see cref=\"Trafo2d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d FromTrafo2d(Trafo2d trafo, double epsilon = 1e-12)\n            => FromM33d(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d Scaling(double scaleFactor)\n            => new Similarity2d(scaleFactor);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2d\"/> transformation with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d Translation(double tX, double tY)\n            => new Similarity2d(Rot2d.Identity, tX, tY);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity2d\"/> transformation with the translational component given by a <see cref=\"V2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d Translation(V2d vector)\n            => new Similarity2d(Rot2d.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Similarity2d\"/> transformation with the translational component given by a <see cref=\"Shift2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d Translation(Shift2d shift)\n            => new Similarity2d(Rot2d.Identity, shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d Rotation(Rot2d rot)\n            => new Similarity2d(rot, V2d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d Rotation(double angleInRadians)\n            => new Similarity2d(new Rot2d(angleInRadians), V2d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d RotationInDegrees(double angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M23d(Similarity2d s)\n        {\n            M23d rv = (M23d)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M22d(Similarity2d s)\n        {\n            M22d rv = (M22d)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Similarity2d s)\n        {\n            M33d rv = (M33d)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine2d(Similarity2d s)\n        {\n            var m = (M23d)s;\n            return new Affine2d((M22d)m, m.C2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2d(Similarity2d s)\n            => new Trafo2d((M33d)s, (M33d)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity2f(Similarity2d s)\n            => new Similarity2f((float)s.Scale, (Euclidean2f)s.Euclidean);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Scale, Euclidean);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Similarity2d other)\n            => Scale.Equals(other.Scale) && Euclidean.Equals(other.Euclidean);\n\n        public override readonly bool Equals(object other)\n            => (other is Similarity2d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Scale, Euclidean);\n        }\n\n        public static Similarity2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Similarity2d(double.Parse(x[0], CultureInfo.InvariantCulture), Euclidean2d.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Similarity\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity2d Inverse(Similarity2d s)\n            => s.Inverse;\n\n        /// <summary>\n        /// Inverts the similarity transformation (multiplicative inverse).\n        /// this = [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Similarity2d t)\n        {\n            t.Scale = 1 / t.Scale;\n            t.Euclidean.Invert();\n            t.Euclidean.Trans *= t.Scale;\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> by a <see cref=\"Similarity2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Similarity2d s, V3d v)\n            => s * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformDir(this Similarity2d t, V2d v)\n        {\n            return t.Euclidean.TransformDir(t.Scale * v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformPos(this Similarity2d t, V2d p)\n        {\n            return t.Euclidean.TransformPos(t.Scale * p);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransformDir(this Similarity2d t, V2d v)\n        {\n            return t.Euclidean.InvTransformDir(v) / t.Scale;\n        }\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransformPos(this Similarity2d t, V2d p)\n        {\n            return t.Euclidean.InvTransformPos(p) / t.Scale;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity2d t0, Similarity2d t1)\n        {\n            return ApproximateEquals(t0, t1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity2d t0, Similarity2d t1, double tol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, tol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity2d t0, Similarity2d t1, double angleTol, double posTol, double scaleTol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, scaleTol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, angleTol, posTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Similarity3d\n\n    /// <summary>\n    /// Represents a Similarity Transformation in 3D that is composed of a\n    /// Uniform Scale and a subsequent Euclidean transformation (3D rotation Rot and a subsequent translation by a 3D vector Trans).\n    /// This is an angle preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct Similarity3d : IEquatable<Similarity3d>\n    {\n        [DataMember]\n        public double Scale;\n        [DataMember]\n        public Euclidean3d Euclidean;\n\n        /// <summary>\n        /// Gets the rotational component of this <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        public readonly Rot3d Rot\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Rot; }\n        }\n\n        /// <summary>\n        /// Gets the translational component of this <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        public readonly V3d Trans\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Trans; }\n        }\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(Similarity3d s)\n        {\n            Scale = s.Scale;\n            Euclidean = s.Euclidean;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Similarity3d\"/> transformation from a <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(Similarity3f s)\n        {\n            Scale = (double)s.Scale;\n            Euclidean = (Euclidean3d)s.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from an uniform scale by factor <paramref name=\"scale\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(double scale)\n        {\n            Scale = scale;\n            Euclidean = Euclidean3d.Identity;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(Euclidean3d euclideanTransformation)\n        {\n            Scale = 1;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(Rot3d rotation, V3d translation)\n        {\n            Scale = 1;\n            Euclidean = new Euclidean3d(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>, <paramref name=\"tZ\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(Rot3d rotation, double tX, double tY, double tZ)\n        {\n            Scale = 1;\n            Euclidean = new Euclidean3d(rotation, tX, tY, tZ);\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(double scale, Euclidean3d euclideanTransformation)\n        {\n            Scale = scale;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(double scale, Rot3d rotation, V3d translation)\n        {\n            Scale = scale;\n            Euclidean = new Euclidean3d(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and and translation by (<paramref name=\"tX\"/>, <paramref name=\"tY\"/>, <paramref name=\"tZ\"/>).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Similarity3d(double scale, Rot3d rotation, double tX, double tY, double tZ)\n        {\n            Scale = scale;\n            Euclidean = new Euclidean3d(rotation, tX, tY, tZ);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Similarity3d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Similarity3d(1, Euclidean3d.Identity);\n        }\n\n        #endregion\n\n        #region Similarity Transformation Arithmetics\n\n        /// <summary>\n        /// Returns a new version of this Similarity transformation with a normalized rotation quaternion.\n        /// </summary>\n        public readonly Similarity3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Similarity3d(Scale, Euclidean.Normalized);\n        }\n\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Similarity transformation.\n        /// [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        public readonly Similarity3d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newS = 1 / Scale;\n                var newR = Euclidean.Inverse;\n                newR.Trans *= newS;\n                return new Similarity3d(newS, newR);\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Similarity transformations.\n        /// This concatenates the two similarity transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d operator *(Similarity3d a, Similarity3d b)\n        {\n            //a.Scale * b.Scale, a.Rot * b.Rot, a.Trans + a.Rot * a.Scale * b.Trans\n            return new Similarity3d(a.Scale * b.Scale, new Euclidean3d(\n                a.Rot * b.Rot,\n                a.Trans + a.Rot.Transform(a.Scale * b.Trans))\n                );\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> vector by a <see cref=\"Similarity3d\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(Similarity3d s, V4d v)\n            => s.Euclidean * new V4d(s.Scale * v.X, s.Scale * v.Y, s.Scale * v.Z, v.W);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3d\"/> transformation (as a 4x4 matrix) with a <see cref=\"M44d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(Similarity3d s, M44d m)\n        {\n            var t = (M34d)s;\n            return new M44d(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20 + t.M03 * m.M30, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21 + t.M03 * m.M31, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22 + t.M03 * m.M32, \n                t.M00 * m.M03 + t.M01 * m.M13 + t.M02 * m.M23 + t.M03 * m.M33,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20 + t.M13 * m.M30, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21 + t.M13 * m.M31, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22 + t.M13 * m.M32, \n                t.M10 * m.M03 + t.M11 * m.M13 + t.M12 * m.M23 + t.M13 * m.M33,\n\n                t.M20 * m.M00 + t.M21 * m.M10 + t.M22 * m.M20 + t.M23 * m.M30, \n                t.M20 * m.M01 + t.M21 * m.M11 + t.M22 * m.M21 + t.M23 * m.M31, \n                t.M20 * m.M02 + t.M21 * m.M12 + t.M22 * m.M22 + t.M23 * m.M32, \n                t.M20 * m.M03 + t.M21 * m.M13 + t.M22 * m.M23 + t.M23 * m.M33,\n\n                m.M30, m.M31, m.M32, m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M44d\"/> with a <see cref=\"Similarity3d\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d operator *(M44d m, Similarity3d s)\n        {\n            var t = (M34d)s;\n            return new M44d(\n                m.M00 * t.M00 + m.M01 * t.M10 + m.M02 * t.M20, \n                m.M00 * t.M01 + m.M01 * t.M11 + m.M02 * t.M21, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02 * t.M22, \n                m.M00 * t.M03 + m.M01 * t.M13 + m.M02 * t.M23 + m.M03,\n\n                m.M10 * t.M00 + m.M11 * t.M10 + m.M12 * t.M20, \n                m.M10 * t.M01 + m.M11 * t.M11 + m.M12 * t.M21, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12 * t.M22, \n                m.M10 * t.M03 + m.M11 * t.M13 + m.M12 * t.M23 + m.M13,\n\n                m.M20 * t.M00 + m.M21 * t.M10 + m.M22 * t.M20, \n                m.M20 * t.M01 + m.M21 * t.M11 + m.M22 * t.M21, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22 * t.M22, \n                m.M20 * t.M03 + m.M21 * t.M13 + m.M22 * t.M23 + m.M23,\n\n                m.M30 * t.M00 + m.M31 * t.M10 + m.M32 * t.M20, \n                m.M30 * t.M01 + m.M31 * t.M11 + m.M32 * t.M21, \n                m.M30 * t.M02 + m.M31 * t.M12 + m.M32 * t.M22, \n                m.M30 * t.M03 + m.M31 * t.M13 + m.M32 * t.M23 + m.M33);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3d\"/> transformation (as a 3x4 matrix) with a <see cref=\"M34d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Similarity3d s, M34d m)\n        {\n            var t = (M34d)s;\n            return new M34d(\n                t.M00 * m.M00 + t.M01 * m.M10 + t.M02 * m.M20, \n                t.M00 * m.M01 + t.M01 * m.M11 + t.M02 * m.M21, \n                t.M00 * m.M02 + t.M01 * m.M12 + t.M02 * m.M22, \n                t.M00 * m.M03 + t.M01 * m.M13 + t.M02 * m.M23 + t.M03,\n\n                t.M10 * m.M00 + t.M11 * m.M10 + t.M12 * m.M20, \n                t.M10 * m.M01 + t.M11 * m.M11 + t.M12 * m.M21, \n                t.M10 * m.M02 + t.M11 * m.M12 + t.M12 * m.M22, \n                t.M10 * m.M03 + t.M11 * m.M13 + t.M12 * m.M23 + t.M13,\n\n                t.M20 * m.M00 + t.M21 * m.M10 + t.M22 * m.M20, \n                t.M20 * m.M01 + t.M21 * m.M11 + t.M22 * m.M21, \n                t.M20 * m.M02 + t.M21 * m.M12 + t.M22 * m.M22, \n                t.M20 * m.M03 + t.M21 * m.M13 + t.M22 * m.M23 + t.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M34d\"/> with a <see cref=\"Similarity3d\"/> transformation (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M34d m, Similarity3d s)\n        {\n            var t = (M34d)s;\n            return new M34d(\n                m.M00 * t.M00 + m.M01 * t.M10 + m.M02 * t.M20, \n                m.M00 * t.M01 + m.M01 * t.M11 + m.M02 * t.M21, \n                m.M00 * t.M02 + m.M01 * t.M12 + m.M02 * t.M22, \n                m.M00 * t.M03 + m.M01 * t.M13 + m.M02 * t.M23 + m.M03,\n\n                m.M10 * t.M00 + m.M11 * t.M10 + m.M12 * t.M20, \n                m.M10 * t.M01 + m.M11 * t.M11 + m.M12 * t.M21, \n                m.M10 * t.M02 + m.M11 * t.M12 + m.M12 * t.M22, \n                m.M10 * t.M03 + m.M11 * t.M13 + m.M12 * t.M23 + m.M13,\n\n                m.M20 * t.M00 + m.M21 * t.M10 + m.M22 * t.M20, \n                m.M20 * t.M01 + m.M21 * t.M11 + m.M22 * t.M21, \n                m.M20 * t.M02 + m.M21 * t.M12 + m.M22 * t.M22, \n                m.M20 * t.M03 + m.M21 * t.M13 + m.M22 * t.M23 + m.M23);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3d\"/> (as a 3x4 matrix) and a <see cref=\"M33d\"/> (as a 4x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(Similarity3d s, M33d m)\n            => new M34d(s.Rot * m * s.Scale, s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"M33d\"/> and a <see cref=\"Similarity3d\"/> (as a 3x4 matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M34d operator *(M33d m, Similarity3d s)\n            => new M34d(s.Scale * m * s.Rot, m * s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3d\"/> and a <see cref=\"Rot3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d operator *(Similarity3d s, Rot3d r)\n            => new Similarity3d(s.Scale, s.Euclidean * r);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Rot3d\"/> and a <see cref=\"Similarity3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d operator *(Rot3d r, Similarity3d s)\n               => new Similarity3d(s.Scale, r * s.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3d\"/> and a <see cref=\"Shift3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d operator *(Similarity3d a, Shift3d b)\n            => new Similarity3d(a.Scale, a.Euclidean * (a.Scale * b));\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Shift3d\"/> and a <see cref=\"Similarity3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d operator *(Shift3d a, Similarity3d b)\n            => new Similarity3d(b.Scale, a * b.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Similarity3d\"/> and a <see cref=\"Scale3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Similarity3d a, Scale3d b)\n        {\n            var t = (M33d)a;\n            return new Affine3d(new M33d(\n                t.M00 * b.X, t.M01 * b.Y, t.M02 * b.Z, \n                t.M10 * b.X, t.M11 * b.Y, t.M12 * b.Z, \n                t.M20 * b.X, t.M21 * b.Y, t.M22 * b.Z),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"Scale3d\"/> and a <see cref=\"Similarity3d\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Affine3d operator *(Scale3d a, Similarity3d b)\n        {\n            var t = (M33d)b;\n            return new Affine3d(new M33d(\n                t.M00 * a.X, t.M01 * a.X, t.M02 * a.X, \n                t.M10 * a.Y, t.M11 * a.Y, t.M12 * a.Y, \n                t.M20 * a.Z, t.M21 * a.Z, t.M22 * a.Z),\n                b.Trans * a.V);\n        }\n\n        /// <summary>\n        /// Multiplies an Euclidean transformation by a Similarity transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d operator *(Euclidean3d a, Similarity3d b)\n        {\n            return new Similarity3d(b.Scale, a * b.Euclidean);\n            //return (Similarity3d)a * b;\n        }\n\n        /// <summary>\n        /// Multiplies a Similarity transformation by an Euclidean transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d operator *(Similarity3d a, Euclidean3d b)\n        {\n            return a * (Similarity3d)b;\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Similarity3d t0, Similarity3d t1)\n        {\n            return t0.Scale == t1.Scale && t0.Euclidean == t1.Euclidean;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(Similarity3d t0, Similarity3d t1)\n        {\n            return !(t0 == t1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3d\"/> transformation from a <see cref=\"M33d\"/> matrix and a translation <see cref=\"V3d\"/>.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d FromM33dAndV3d(M33d m, V3d trans, double epsilon = 1e-12)\n        {\n            var s0 = m.C0.Norm2;\n            var s1 = m.C1.Norm2;\n            var s2 = m.C2.Norm2;\n            var s = (s0 * s1 * s2).Pow(1.0 / 3); //geometric mean of scale\n\n            if (!((s0 / s - 1).IsTiny(epsilon) && (s1 / s - 1).IsTiny(epsilon) && (s2 / s - 1).IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            m /= s;\n            return new Similarity3d(s, Euclidean3d.FromM33dAndV3d(m, trans, epsilon));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3d\"/> transformation from a <see cref=\"M34d\"/> matrix.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d FromM34d(M34d m, double epsilon = 1e-12)\n            => FromM33dAndV3d((M33d)m, m.C3, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3d\"/> transformation from a <see cref=\"M44d\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components or\n        /// a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d FromM44d(M44d m, double epsilon = 1e-12)\n        {\n            if (!(m.M30.IsTiny(epsilon) && m.M31.IsTiny(epsilon) && m.M32.IsTiny(epsilon)))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M33.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return FromM33dAndV3d(((M33d)m) / m.M33, m.C3.XYZ, epsilon);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3d\"/> transformation from an <see cref=\"Scale3d\"/>.\n        /// The transformation <paramref name=\"scale\"/> must represent a uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d FromScale3d(Scale3d scale, double epsilon = 1e-12)\n        {\n            var s = (scale.X * scale.Y * scale.Z).Pow(1.0 / 3);\n\n            if (!scale.ApproximateEquals(new Scale3d(s), epsilon))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            return new Similarity3d(s, Euclidean3d.Identity);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3d\"/> transformation from an <see cref=\"Affine3d\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d FromAffine3d(Affine3d affine, double epsilon = 1e-12)\n            => FromM44d((M44d)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3d\"/> transformation from a <see cref=\"Trafo3d\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d FromTrafo3d(Trafo3d trafo, double epsilon = 1e-12)\n            => FromM44d(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d Scaling(double scaleFactor)\n            => new Similarity3d(scaleFactor);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3d\"/> transformation with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d Translation(double tX, double tY, double tZ)\n            => new Similarity3d(Rot3d.Identity, tX, tY, tZ);\n\n        /// <summary>\n        /// Creates a <see cref=\"Similarity3d\"/> transformation with the translational component given by a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d Translation(V3d vector)\n            => new Similarity3d(Rot3d.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"Similarity3d\"/> transformation with the translational component given by a <see cref=\"Shift3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d Translation(Shift3d shift)\n            => new Similarity3d(Rot3d.Identity, shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d Rotation(Rot3d rot)\n            => new Similarity3d(rot, V3d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d Rotation(V3d normalizedAxis, double angleRadians)\n            => new Similarity3d(Rot3d.Rotation(normalizedAxis, angleRadians), V3d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationInDegrees(V3d normalizedAxis, double angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationEuler(double rollInRadians, double pitchInRadians, double yawInRadians)\n            => new Similarity3d(Rot3d.RotationEuler(rollInRadians, pitchInRadians, yawInRadians), V3d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationEulerInDegrees(double rollInDegrees, double pitchInDegrees, double yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationEuler(V3d rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationEulerInDegrees(V3d rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotateInto(V3d from, V3d into)\n            => new Similarity3d(Rot3d.RotateInto(from, into), V3d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationX(double angleRadians)\n            => new Similarity3d(Rot3d.RotationX(angleRadians), V3d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationXInDegrees(double angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationY(double angleRadians)\n            => new Similarity3d(Rot3d.RotationY(angleRadians), V3d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationYInDegrees(double angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationZ(double angleRadians)\n            => new Similarity3d(Rot3d.RotationZ(angleRadians), V3d.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d RotationZInDegrees(double angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M34d(Similarity3d s)\n        {\n            M34d rv = (M34d)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; rv.M02 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; rv.M12 *= s.Scale; \n            rv.M20 *= s.Scale; rv.M21 *= s.Scale; rv.M22 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M33d(Similarity3d s)\n        {\n            M33d rv = (M33d)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; rv.M02 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; rv.M12 *= s.Scale; \n            rv.M20 *= s.Scale; rv.M21 *= s.Scale; rv.M22 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator M44d(Similarity3d s)\n        {\n            M44d rv = (M44d)s.Euclidean;\n            rv.M00 *= s.Scale; rv.M01 *= s.Scale; rv.M02 *= s.Scale; \n            rv.M10 *= s.Scale; rv.M11 *= s.Scale; rv.M12 *= s.Scale; \n            rv.M20 *= s.Scale; rv.M21 *= s.Scale; rv.M22 *= s.Scale; \n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Affine3d(Similarity3d s)\n        {\n            var m = (M34d)s;\n            return new Affine3d((M33d)m, m.C3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3d(Similarity3d s)\n            => new Trafo3d((M44d)s, (M44d)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Similarity3f(Similarity3d s)\n            => new Similarity3f((float)s.Scale, (Euclidean3f)s.Euclidean);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Scale, Euclidean);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(Similarity3d other)\n            => Scale.Equals(other.Scale) && Euclidean.Equals(other.Euclidean);\n\n        public override readonly bool Equals(object other)\n            => (other is Similarity3d o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Scale, Euclidean);\n        }\n\n        public static Similarity3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Similarity3d(double.Parse(x[0], CultureInfo.InvariantCulture), Euclidean3d.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Similarity\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d Inverse(Similarity3d s)\n            => s.Inverse;\n\n        /// <summary>\n        /// Inverts the similarity transformation (multiplicative inverse).\n        /// this = [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref Similarity3d t)\n        {\n            t.Scale = 1 / t.Scale;\n            t.Euclidean.Invert();\n            t.Euclidean.Trans *= t.Scale;\n        }\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a copy of a <see cref=\"Similarity3d\"/> with its rotation quaternion normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Similarity3d Normalized(Similarity3d s)\n            => s.Normalized;\n\n        /// <summary>\n        /// Normalizes the rotation quaternion of a <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref Similarity3d t)\n        {\n            t.Euclidean.Normalize();\n        }\n\n        #endregion\n\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> by a <see cref=\"Similarity3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Similarity3d s, V4d v)\n            => s * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformDir(this Similarity3d t, V3d v)\n        {\n            return t.Euclidean.TransformDir(t.Scale * v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformPos(this Similarity3d t, V3d p)\n        {\n            return t.Euclidean.TransformPos(t.Scale * p);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformDir(this Similarity3d t, V3d v)\n        {\n            return t.Euclidean.InvTransformDir(v) / t.Scale;\n        }\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformPos(this Similarity3d t, V3d p)\n        {\n            return t.Euclidean.InvTransformPos(p) / t.Scale;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity3d t0, Similarity3d t1)\n        {\n            return ApproximateEquals(t0, t1, Constant<double>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity3d t0, Similarity3d t1, double tol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, tol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Similarity3d t0, Similarity3d t1, double angleTol, double posTol, double scaleTol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, scaleTol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, angleTol, posTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Similarity_template.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action mul = () => Out(\" * \");\n    //# Action and = () => Out(\" && \");\n    //# Action or = () => Out(\" || \");\n    //# Action andLit = () => Out(\" and \");\n    //# var fields = new[] {\"X\", \"Y\", \"Z\", \"W\"};\n    //# foreach (var isDouble in new[] { false, true }) {\n    //# for (int n = 2; n <= 3; n++) {\n    //#   var m = n + 1;\n    //#   var ftype = isDouble ? \"double\" : \"float\";\n    //#   var ftype2 = isDouble ? \"float\" : \"double\";\n    //#   var one = isDouble ? \"1.0\" : \"1.0f\";\n    //#   var xyz = \"XYZW\".Substring(0, n);\n    //#   var tc = isDouble ? \"d\" : \"f\";\n    //#   var tc2 = isDouble ? \"f\" : \"d\";\n    //#   var type = \"Similarity\" + n + tc;\n    //#   var type2 = \"Similarity\" + n + tc2;\n    //#   var vnt = \"V\" + n + tc;\n    //#   var vmt = \"V\" + m + tc;\n    //#   var mnnt = \"M\" + n + n + tc;\n    //#   var mmmt = \"M\" + m + m + tc;\n    //#   var mnmt = \"M\" + n + m + tc;\n    //#   var rotnt = \"Rot\" + n + tc;\n    //#   var trafont = \"Trafo\" + n + tc;\n    //#   var affinent = \"Affine\" + n + tc;\n    //#   var scalent = \"Scale\" + n + tc;\n    //#   var shiftnt = \"Shift\" + n + tc;\n    //#   var euclideannt = \"Euclidean\" + n + tc;\n    //#   var euclideannt2 = \"Euclidean\" + n + tc2;\n    //#   var nfields = fields.Take(n).ToArray();\n    //#   var mfields = fields.Take(m).ToArray();\n    //#   var fn = fields[n];\n    //#   var eps = isDouble ? \"1e-12\" : \"1e-5f\";\n    #region __type__\n\n    /// <summary>\n    /// Represents a Similarity Transformation in __n__D that is composed of a\n    /// Uniform Scale and a subsequent Euclidean transformation (__n__D rotation Rot and a subsequent translation by a __n__D vector Trans).\n    /// This is an angle preserving Transformation.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __type__ : IEquatable<__type__>\n    {\n        [DataMember]\n        public __ftype__ Scale;\n        [DataMember]\n        public __euclideannt__ Euclidean;\n\n        /// <summary>\n        /// Gets the rotational component of this <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public readonly __rotnt__ Rot\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Rot; }\n        }\n\n        /// <summary>\n        /// Gets the translational component of this <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        public readonly __vnt__ Trans\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Euclidean.Trans; }\n        }\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a copy of an <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ s)\n        {\n            Scale = s.Scale;\n            Euclidean = s.Euclidean;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> transformation from a <see cref=\"__type2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ s)\n        {\n            Scale = (__ftype__)s.Scale;\n            Euclidean = (__euclideannt__)s.Euclidean;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from an uniform scale by factor <paramref name=\"scale\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ scale)\n        {\n            Scale = scale;\n            Euclidean = __euclideannt__.Identity;\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__euclideannt__ euclideanTransformation)\n        {\n            Scale = 1;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__rotnt__ rotation, __vnt__ translation)\n        {\n            Scale = 1;\n            Euclidean = new __euclideannt__(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a rotation <paramref name=\"rotation\"/> and translation by (/*# nfields.ForEach(f => { */<paramref name=\"t__f__\"/>/*# }, comma);*/).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__rotnt__ rotation, /*# nfields.ForEach(f => { */__ftype__ t__f__/*# }, comma);*/)\n        {\n            Scale = 1;\n            Euclidean = new __euclideannt__(rotation, /*# nfields.ForEach(f => { */t__f__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Creates a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rigid transformation <paramref name=\"euclideanTransformation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ scale, __euclideannt__ euclideanTransformation)\n        {\n            Scale = scale;\n            Euclidean = euclideanTransformation;\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and translation <paramref name=\"translation\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ scale, __rotnt__ rotation, __vnt__ translation)\n        {\n            Scale = scale;\n            Euclidean = new __euclideannt__(rotation, translation);\n        }\n\n        /// <summary>\n        /// Constructs a similarity transformation from a uniform scale by factor <paramref name=\"scale\"/>, and a (subsequent) rotation <paramref name=\"rotation\"/> and and translation by (/*# nfields.ForEach(f => { */<paramref name=\"t__f__\"/>/*# }, comma);*/).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__ftype__ scale, __rotnt__ rotation, /*# nfields.ForEach(f => { */__ftype__ t__f__/*# }, comma);*/)\n        {\n            Scale = scale;\n            Euclidean = new __euclideannt__(rotation, /*# nfields.ForEach(f => { */t__f__/*# }, comma);*/);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(1, __euclideannt__.Identity);\n        }\n\n        #endregion\n\n        #region Similarity Transformation Arithmetics\n\n        //# if (n > 2) {\n        /// <summary>\n        /// Returns a new version of this Similarity transformation with a normalized rotation quaternion.\n        /// </summary>\n        public readonly __type__ Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(Scale, Euclidean.Normalized);\n        }\n\n        //# }\n        /// <summary>\n        /// Gets the (multiplicative) inverse of this Similarity transformation.\n        /// [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        public readonly __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var newS = 1 / Scale;\n                var newR = Euclidean.Inverse;\n                newR.Trans *= newS;\n                return new __type__(newS, newR);\n            }\n        }\n\n        #endregion\n\n        #region Arithmetic Operators\n\n        /// <summary>\n        /// Multiplies two Similarity transformations.\n        /// This concatenates the two similarity transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __type__ b)\n        {\n            //a.Scale * b.Scale, a.Rot * b.Rot, a.Trans + a.Rot * a.Scale * b.Trans\n            return new __type__(a.Scale * b.Scale, new __euclideannt__(\n                a.Rot * b.Rot,\n                a.Trans + a.Rot.Transform(a.Scale * b.Trans))\n                );\n        }\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> vector by a <see cref=\"__type__\"/> transformation.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ operator *(__type__ s, __vmt__ v)\n            => s.Euclidean * new __vmt__(/*# nfields.ForEach(f => {*/s.Scale * v.__f__/*#}, comma);*/, v.__fn__);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __m__x__m__ matrix) with a <see cref=\"__mmmt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mmmt__ operator *(__type__ s, __mmmt__ m)\n        {\n            var t = (__mnmt__)s;\n            return new __mmmt__(/*# n.ForEach(i => { m.ForEach(j => { */\n                /*# m.ForEach(k => {\n                */t.M__i____k__ * m.M__k____j__/*# }, add); }, comma); }, commaln);*/,\n\n                /*# m.ForEach(i => { */m.M__n____i__/*# }, comma);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mmmt__\"/> with a <see cref=\"__type__\"/> transformation (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mmmt__ operator *(__mmmt__ m, __type__ s)\n        {\n            var t = (__mnmt__)s;\n            return new __mmmt__(/*# m.ForEach(i => { m.ForEach(j => { */\n                /*# n.ForEach(k => {\n                */m.M__i____k__ * t.M__k____j__/*# }, add);\n                 if (j == n) {*/ + m.M__i____n__/*# } }, comma); }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> transformation (as a __n__x__m__ matrix) with a <see cref=\"__mnmt__\"/> (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__type__ s, __mnmt__ m)\n        {\n            var t = (__mnmt__)s;\n            return new __mnmt__(/*# n.ForEach(i => { m.ForEach(j => { */\n                /*# n.ForEach(k => {\n                */t.M__i____k__ * m.M__k____j__/*# }, add);\n                 if (j == n) {*/ + t.M__i____n__/*# } }, comma); }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mnmt__\"/> with a <see cref=\"__type__\"/> transformation (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__mnmt__ m, __type__ s)\n        {\n            var t = (__mnmt__)s;\n            return new __mnmt__(/*# n.ForEach(i => { m.ForEach(j => { */\n                /*# n.ForEach(k => {\n                */m.M__i____k__ * t.M__k____j__/*# }, add);\n                 if (j == n) {*/ + m.M__i____n__/*# } }, comma); }, commaln);*/);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> (as a __n__x__m__ matrix) and a <see cref=\"__mnnt__\"/> (as a __m__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__type__ s, __mnnt__ m)\n            => new __mnmt__(s.Rot * m * s.Scale, s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__mnnt__\"/> and a <see cref=\"__type__\"/> (as a __n__x__m__ matrix).\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mnmt__ operator *(__mnnt__ m, __type__ s)\n            => new __mnmt__(s.Scale * m * s.Rot, m * s.Trans);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__rotnt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ s, __rotnt__ r)\n            => new __type__(s.Scale, s.Euclidean * r);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__rotnt__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__rotnt__ r, __type__ s)\n               => new __type__(s.Scale, r * s.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__shiftnt__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __shiftnt__ b)\n            => new __type__(a.Scale, a.Euclidean * (a.Scale * b));\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__shiftnt__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__shiftnt__ a, __type__ b)\n            => new __type__(b.Scale, a * b.Euclidean);\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__type__\"/> and a <see cref=\"__scalent__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affinent__ operator *(__type__ a, __scalent__ b)\n        {\n            var t = (__mnnt__)a;\n            return new __affinent__(new __mnnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */t.M__i____j__ * b.__fj__/*# }, comma); }, comma);*/),\n                a.Trans);\n        }\n\n        /// <summary>\n        /// Multiplies a <see cref=\"__scalent__\"/> and a <see cref=\"__type__\"/>.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __affinent__ operator *(__scalent__ a, __type__ b)\n        {\n            var t = (__mnnt__)b;\n            return new __affinent__(new __mnnt__(/*# nfields.ForEach((fi, i) => { */\n                /*# nfields.ForEach((fj, j) => { */t.M__i____j__ * a.__fi__/*# }, comma); }, comma);*/),\n                b.Trans * a.V);\n        }\n\n        /// <summary>\n        /// Multiplies an Euclidean transformation by a Similarity transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__euclideannt__ a, __type__ b)\n        {\n            return new __type__(b.Scale, a * b.Euclidean);\n            //return (__type__)a * b;\n        }\n\n        /// <summary>\n        /// Multiplies a Similarity transformation by an Euclidean transformation.\n        /// This concatenates the two transformations into a single one, first b is applied, then a.\n        /// Attention: Multiplication is NOT commutative!\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ operator *(__type__ a, __euclideannt__ b)\n        {\n            return a * (__type__)b;\n        }\n\n        #endregion\n\n        #region Comparison Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ t0, __type__ t1)\n        {\n            return t0.Scale == t1.Scale && t0.Euclidean == t1.Euclidean;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__type__ t0, __type__ t1)\n        {\n            return !(t0 == t1);\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__mnnt__\"/> matrix and a translation <see cref=\"__vnt__\"/>.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mnnt__And__vnt__(__mnnt__ m, __vnt__ trans, __ftype__ epsilon = __eps__)\n        {\n            //# n.ForEach(i => {\n            var s__i__ = m.C__i__.Norm2;\n            //# });\n            var s = (/*# n.ForEach(i => {*/s__i__/*# }, mul);*/).Pow(__one__ / __n__); //geometric mean of scale\n\n            if (!(/*#n.ForEach(i => {*/(s__i__ / s - 1).IsTiny(epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            m /= s;\n            return new __type__(s, __euclideannt__.From__mnnt__And__vnt__(m, trans/*# if (n > 2) {*/, epsilon/*# }*/));\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__mnmt__\"/> matrix.\n        /// The matrix must not contain a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mnmt__(__mnmt__ m, __ftype__ epsilon = __eps__)\n            => From__mnnt__And__vnt__((__mnnt__)m, m.C__n__/*# if (n > 2) {*/, epsilon/*# }*/);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__mmmt__\"/> matrix.\n        /// The matrix has to be homogeneous and must not contain perspective components or\n        /// a non-uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__mmmt__(__mmmt__ m, __ftype__ epsilon = __eps__)\n        {\n            if (!(/*#n.ForEach(j => {*/m.M__n____j__.IsTiny(epsilon)/*# }, and);*/))\n                throw new ArgumentException(\"Matrix contains perspective components.\");\n\n            if (m.M__n____n__.IsTiny(epsilon))\n                throw new ArgumentException(\"Matrix is not homogeneous.\");\n\n            return From__mnnt__And__vnt__(((__mnnt__)m) / m.M__n____n__, m.C__n__.__xyz__/*# if (n > 2) {*/, epsilon/*# }*/);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from an <see cref=\"__scalent__\"/>.\n        /// The transformation <paramref name=\"scale\"/> must represent a uniform scaling.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__scalent__(__scalent__ scale, __ftype__ epsilon = __eps__)\n        {\n            var s = (/*# nfields.ForEach(f => {*/scale.__f__/*# }, mul);*/).Pow(__one__ / __n__);\n\n            if (!scale.ApproximateEquals(new __scalent__(s), epsilon))\n                throw new ArgumentException(\"Matrix features non-uniform scaling\");\n\n            return new __type__(s, __euclideannt__.Identity);\n        }\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from an <see cref=\"__affinent__\"/>.\n        /// The transformation <paramref name=\"affine\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__affinent__(__affinent__ affine, __ftype__ epsilon = __eps__)\n            => From__mmmt__((__mmmt__)affine, epsilon);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation from a <see cref=\"__trafont__\"/>.\n        /// The transformation <paramref name=\"trafo\"/> must only consist of a uniform scale, rotation, and translation.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\"></exception>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ From__trafont__(__trafont__ trafo, __ftype__ epsilon = __eps__)\n            => From__mmmt__(trafo.Forward, epsilon);\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scaling(__ftype__ scaleFactor)\n            => new __type__(scaleFactor);\n\n        #region Translation\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation with the translational component given by __n__ scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(/*# nfields.ForEach(f => { */__ftype__ t__f__/*# }, comma); */)\n            => new __type__(__rotnt__.Identity, /*# nfields.ForEach(f => { */t__f__/*# }, comma); */);\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation with the translational component given by a <see cref=\"__vnt__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(__vnt__ vector)\n            => new __type__(__rotnt__.Identity, vector);\n\n        /// <summary>\n        /// Creates an <see cref=\"__type__\"/> transformation with the translational component given by a <see cref=\"__shiftnt__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(__shiftnt__ shift)\n            => new __type__(__rotnt__.Identity, shift.V);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"__rotnt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__rotnt__ rot)\n            => new __type__(rot, __vnt__.Zero);\n\n        //# if (n == 2) {\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__ftype__ angleInRadians)\n            => new __type__(new __rotnt__(angleInRadians), __vnt__.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__ftype__ angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        //# } else if (n == 3) {\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__vnt__ normalizedAxis, __ftype__ angleRadians)\n            => new __type__(__rotnt__.Rotation(normalizedAxis, angleRadians), __vnt__.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__vnt__ normalizedAxis, __ftype__ angleDegrees)\n            => Rotation(normalizedAxis, angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__ftype__ rollInRadians, __ftype__ pitchInRadians, __ftype__ yawInRadians)\n            => new __type__(__rotnt__.RotationEuler(rollInRadians, pitchInRadians, yawInRadians), __vnt__.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__ftype__ rollInDegrees, __ftype__ pitchInDegrees, __ftype__ yawInDegrees)\n            => RotationEuler(\n                rollInDegrees.RadiansFromDegrees(),\n                pitchInDegrees.RadiansFromDegrees(),\n                yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__vnt__ rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__vnt__ rollPitchYawInDegrees)\n            => RotationEulerInDegrees(\n                rollPitchYawInDegrees.X,\n                rollPitchYawInDegrees.Y,\n                rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotateInto(__vnt__ from, __vnt__ into)\n            => new __type__(__rotnt__.RotateInto(from, into), __vnt__.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationX(__ftype__ angleRadians)\n            => new __type__(__rotnt__.RotationX(angleRadians), __vnt__.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationXInDegrees(__ftype__ angleDegrees)\n            => RotationX(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationY(__ftype__ angleRadians)\n            => new __type__(__rotnt__.RotationY(angleRadians), __vnt__.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationYInDegrees(__ftype__ angleDegrees)\n            => RotationY(angleDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZ(__ftype__ angleRadians)\n            => new __type__(__rotnt__.RotationZ(angleRadians), __vnt__.Zero);\n\n        /// <summary>\n        /// Creates a rotation transformation for <paramref name=\"angleDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZInDegrees(__ftype__ angleDegrees)\n            => RotationZ(angleDegrees.RadiansFromDegrees());\n\n        //# }\n        #endregion\n\n        #endregion\n\n        #region Conversion\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mnmt__(__type__ s)\n        {\n            __mnmt__ rv = (__mnmt__)s.Euclidean;\n            //# n.ForEach(i => {\n            /*# n.ForEach(j => {*/rv.M__i____j__ *= s.Scale; /*# });*/\n            //# });\n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mnnt__(__type__ s)\n        {\n            __mnnt__ rv = (__mnnt__)s.Euclidean;\n            //# n.ForEach(i => {\n            /*# n.ForEach(j => {*/rv.M__i____j__ *= s.Scale; /*# });*/\n            //# });\n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __mmmt__(__type__ s)\n        {\n            __mmmt__ rv = (__mmmt__)s.Euclidean;\n            //# n.ForEach(i => {\n            /*# n.ForEach(j => {*/rv.M__i____j__ *= s.Scale; /*# });*/\n            //# });\n            return rv;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __affinent__(__type__ s)\n        {\n            var m = (__mnmt__)s;\n            return new __affinent__((__mnnt__)m, m.C__n__);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __trafont__(__type__ s)\n            => new __trafont__((__mmmt__)s, (__mmmt__)s.Inverse);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ s)\n            => new __type2__((__ftype2__)s.Scale, (__euclideannt2__)s.Euclidean);\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(Scale, Euclidean);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__type__ other)\n            => Scale.Equals(other.Scale) && Euclidean.Equals(other.Euclidean);\n\n        public override readonly bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override readonly string ToString()\n        {\n            return string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Scale, Euclidean);\n        }\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(__ftype__.Parse(x[0], CultureInfo.InvariantCulture), __euclideannt__.Parse(x[1]));\n        }\n\n        #endregion\n    }\n\n    public static partial class Similarity\n    {\n        #region Invert\n\n        /// <summary>\n        /// Returns the inverse of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ s)\n            => s.Inverse;\n\n        /// <summary>\n        /// Inverts the similarity transformation (multiplicative inverse).\n        /// this = [1/Scale, Rot^T,-Rot^T Trans/Scale]\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Invert(this ref __type__ t)\n        {\n            t.Scale = 1 / t.Scale;\n            t.Euclidean.Invert();\n            t.Euclidean.Trans *= t.Scale;\n        }\n\n        #endregion\n\n        //# if (n > 2) {\n        #region Normalize\n\n        /// <summary>\n        /// Returns a copy of a <see cref=\"__type__\"/> with its rotation quaternion normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Normalized(__type__ s)\n            => s.Normalized;\n\n        /// <summary>\n        /// Normalizes the rotation quaternion of a <see cref=\"__type__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref __type__ t)\n        {\n            t.Euclidean.Normalize();\n        }\n\n        #endregion\n\n        //# }\n        #region Transform\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> by a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ Transform(this __type__ s, __vmt__ v)\n            => s * v;\n\n        /// <summary>\n        /// Transforms direction vector v (v.__fn__ is presumed 0.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformDir(this __type__ t, __vnt__ v)\n        {\n            return t.Euclidean.TransformDir(t.Scale * v);\n        }\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformPos(this __type__ t, __vnt__ p)\n        {\n            return t.Euclidean.TransformPos(t.Scale * p);\n        }\n\n        /// <summary>\n        /// Transforms direction vector v (v.__fn__ is presumed 0.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ InvTransformDir(this __type__ t, __vnt__ v)\n        {\n            return t.Euclidean.InvTransformDir(v) / t.Scale;\n        }\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by the inverse of the similarity transformation <paramref name=\"t\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ InvTransformPos(this __type__ t, __vnt__ p)\n        {\n            return t.Euclidean.InvTransformPos(p) / t.Scale;\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ t0, __type__ t1)\n        {\n            return ApproximateEquals(t0, t1, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ t0, __type__ t1, __ftype__ tol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, tol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, tol);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ t0, __type__ t1, __ftype__ angleTol, __ftype__ posTol, __ftype__ scaleTol)\n        {\n            return t0.Scale.ApproximateEquals(t1.Scale, scaleTol) && t0.Euclidean.ApproximateEquals(t1.Euclidean, angleTol, posTol);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Trafo_auto.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Trafo2f\n\n    /// <summary>\n    /// A trafo is a container for a forward and a backward matrix.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct Trafo2f : IEquatable<Trafo2f>\n    {\n        [DataMember]\n        public readonly M33f Forward;\n        [DataMember]\n        public readonly M33f Backward;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from a forward and backward transformation <see cref=\"M33f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(M33f forward, M33f backward)\n        {\n            Forward = forward;\n            Backward = backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from another <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(Trafo2f trafo)\n        {\n            Forward = trafo.Forward;\n            Backward = trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from a <see cref=\"Trafo2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(Trafo2d trafo)\n        {\n            Forward = (M33f)trafo.Forward;\n            Backward = (M33f)trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from an <see cref=\"Affine2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(Affine2f trafo)\n        {\n            Forward = (M33f)trafo;\n            Backward = (M33f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from a <see cref=\"Euclidean2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(Euclidean2f trafo)\n        {\n            Forward = (M33f)trafo;\n            Backward = (M33f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from a <see cref=\"Similarity2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(Similarity2f trafo)\n        {\n            Forward = (M33f)trafo;\n            Backward = (M33f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from a <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(Rot2f trafo)\n        {\n            Forward = (M33f)trafo;\n            Backward = (M33f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from a <see cref=\"Scale2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(Scale2f trafo)\n        {\n            Forward = (M33f)trafo;\n            Backward = (M33f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2f\"/> from a <see cref=\"Shift2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2f(Shift2f trafo)\n        {\n            Forward = (M33f)trafo;\n            Backward = (M33f)trafo.Inverse;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Trafo2f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Trafo2f(M33f.Identity, M33f.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        public Trafo2f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Trafo2f(Backward, Forward);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override int GetHashCode() => HashCode.GetCombined(Forward, Backward);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public bool Equals(Trafo2f other)\n            => Forward.Equals(other.Forward) && Backward.Equals(other.Backward);\n\n        public override bool Equals(object other)\n            => (other is Trafo2f o) ? Equals(o) : false;\n\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Forward, Backward);\n\n        public static Trafo2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Trafo2f(\n                M33f.Parse(x[0].ToString()),\n                M33f.Parse(x[1].ToString())\n            );\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Builds a transformation matrix using the scale, rotation (in radians) and translation components.\n        /// NOTE: Uses the Scale * Rotation * Translation notion.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f FromComponents(V2f scale, float rotationInRadians, V2f translation)\n            => Scale(scale) * Rotation(rotationInRadians) * Translation(translation);\n\n        /// <summary>\n        /// Returns the <see cref=\"Trafo2f\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f FromBasis(V2f xAxis, V2f yAxis, V2f origin)\n        {\n            var mat = new M33f(\n                            xAxis.X, yAxis.X, origin.X, \n                            xAxis.Y, yAxis.Y, origin.Y,\n                            0, 0, 1);\n\n            return new Trafo2f(mat, mat.Inverse);\n        }\n\n        /// <summary>\n        /// Returns the <see cref=\"Trafo2f\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// Note that the axes MUST be normalized and normal to each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f FromOrthoNormalBasis(V2f xAxis, V2f yAxis)\n        {\n            return new Trafo2f(\n                        new M33f(\n                            xAxis.X, yAxis.X, 0, \n                            xAxis.Y, yAxis.Y, 0,\n                            0, 0, 1),\n                        new M33f(\n                            xAxis.X, xAxis.Y, 0, \n                            yAxis.X, yAxis.Y, 0,\n                            0, 0, 1)\n                        );\n        }\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"Trafo2f\"/> transformation with the translational component given by a <see cref=\"V2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Translation(V2f v)\n            => new Trafo2f(M33f.Translation(v), M33f.Translation(-v));\n\n        /// <summary>\n        /// Creates a <see cref=\"Trafo2f\"/> transformation with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Translation(float tX, float tY)\n            => Translation(new V2f(tX, tY));\n\n        /// <summary>\n        /// Creates an <see cref=\"Trafo2f\"/> transformation with the translational component given by a <see cref=\"Shift2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Translation(Shift2f shift)\n            => Translation(shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"V2f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Scale(V2f v) \n            => new Trafo2f(M33f.Scale(v), M33f.Scale(1 / v));\n\n        /// <summary>\n        /// Creates a scaling transformation using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Scale(float sX, float sY)\n            => new Trafo2f(M33f.Scale(sX, sY),\n                           M33f.Scale(1 / sX, 1 / sY));\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Scale(float s)\n        {\n            var t = 1 / s;\n            return new Trafo2f(M33f.Scale(s), M33f.Scale(t));\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"Scale2f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Scale(Scale2f scale)\n            => new Trafo2f(scale);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Rotation(Rot2f rotation)\n            => new Trafo2f(rotation);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Rotation(float angleInRadians)\n            => new Trafo2f(M33f.Rotation(angleInRadians), M33f.Rotation(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f RotationInDegrees(float angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2d(Trafo2f r)\n            => new Trafo2d(r);\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Returns whether two <see cref=\"Trafo2f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Trafo2f a, Trafo2f b)\n            => a.Forward == b.Forward && a.Backward == b.Backward;\n\n        /// <summary>\n        /// Returns whether two <see cref=\"Trafo2f\"/> transformations are different.\n        /// </summary>\n        public static bool operator !=(Trafo2f a, Trafo2f b)\n            => a.Forward != b.Forward || a.Backward != b.Backward;\n\n        /// <summary>\n        /// The order of operation of Trafo2f multiplicaition is backward\n        /// with respect to M33f multiplication in order to provide\n        /// natural postfix notation.\n        /// </summary>\n        public static Trafo2f operator *(Trafo2f t0, Trafo2f t1)\n            => new Trafo2f(t1.Forward * t0.Forward, t0.Backward * t1.Backward);\n\n        #endregion \n    }\n\n    public static partial class Trafo\n    {\n        #region Operations\n\n        /// <summary>\n        /// Returns the inverse of the given <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2f Inverse(Trafo2f trafo)\n            => trafo.Inverse;\n\n        /// <summary>\n        /// Returns the forward matrix the given <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Forward(Trafo2f trafo)\n            => trafo.Forward;\n\n        /// <summary>\n        /// Returns the backward matrix the given <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Backward(Trafo2f trafo)\n            => trafo.Backward;\n\n        #endregion\n\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale(this Trafo2f trafo)\n            => trafo.Forward.GetScale2();\n\n        /// <summary>\n        /// Extracts a scale vector from the given transformation by calculating the lengths of the basis vectors. \n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GetScaleVector(this Trafo2f trafo)\n            => trafo.Forward.GetScaleVector2();\n\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> by a <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Transform(this Trafo2f r, V3f v)\n            => r.Forward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by a <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformDir(this Trafo2f r, V2f v)\n            => r.Forward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by a <see cref=\"Trafo2f\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformPos(this Trafo2f r, V2f p)\n            => r.Forward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by a <see cref=\"Trafo2f\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformPosProj(this Trafo2f r, V2f p)\n            => r.Forward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by a <see cref=\"Trafo2f\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformPosProjFull(this Trafo2f r, V2f p)\n            => r.Forward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.Z is presumed 0.0) by a <see cref=\"Trafo2f\"/>\n        /// (i.e. by its transposed backward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f TransformNormal(this Trafo2f r, V2f n)\n            => r.Backward.TransposedTransformDir(n);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3f\"/> by the inverse of a <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransform(this Trafo2f r, V3f v)\n            => r.Backward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by the inverse of a <see cref=\"Trafo2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransformDir(this Trafo2f r, V2f v)\n            => r.Backward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of a <see cref=\"Trafo2f\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransformPos(this Trafo2f r, V2f p)\n            => r.Backward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of a <see cref=\"Trafo2f\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransformPosProj(this Trafo2f r, V2f p)\n            => r.Backward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of a <see cref=\"Trafo2f\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformPosProjFull(this Trafo2f r, V2f p)\n            => r.Backward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.Z is presumed 0.0) by the inverse of a <see cref=\"Trafo2f\"/>\n        /// (i.e. by its transposed forward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvTransformNormal(this Trafo2f r, V2f n)\n            => r.Forward.TransposedTransformDir(n);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if two <see cref=\"Trafo2f\"/> transformations are equal with regard to a threshold <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Trafo2f a, Trafo2f b, float epsilon)\n            => a.Forward.ApproximateEquals(b.Forward, epsilon) && a.Backward.ApproximateEquals(b.Backward, epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Trafo3f\n\n    /// <summary>\n    /// A trafo is a container for a forward and a backward matrix.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct Trafo3f : IEquatable<Trafo3f>\n    {\n        [DataMember]\n        public readonly M44f Forward;\n        [DataMember]\n        public readonly M44f Backward;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from a forward and backward transformation <see cref=\"M44f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(M44f forward, M44f backward)\n        {\n            Forward = forward;\n            Backward = backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from another <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(Trafo3f trafo)\n        {\n            Forward = trafo.Forward;\n            Backward = trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from a <see cref=\"Trafo3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(Trafo3d trafo)\n        {\n            Forward = (M44f)trafo.Forward;\n            Backward = (M44f)trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from an <see cref=\"Affine3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(Affine3f trafo)\n        {\n            Forward = (M44f)trafo;\n            Backward = (M44f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from a <see cref=\"Euclidean3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(Euclidean3f trafo)\n        {\n            Forward = (M44f)trafo;\n            Backward = (M44f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from a <see cref=\"Similarity3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(Similarity3f trafo)\n        {\n            Forward = (M44f)trafo;\n            Backward = (M44f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(Rot3f trafo)\n        {\n            Forward = (M44f)trafo;\n            Backward = (M44f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from a <see cref=\"Scale3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(Scale3f trafo)\n        {\n            Forward = (M44f)trafo;\n            Backward = (M44f)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3f\"/> from a <see cref=\"Shift3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3f(Shift3f trafo)\n        {\n            Forward = (M44f)trafo;\n            Backward = (M44f)trafo.Inverse;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Trafo3f Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Trafo3f(M44f.Identity, M44f.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        public Trafo3f Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Trafo3f(Backward, Forward);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override int GetHashCode() => HashCode.GetCombined(Forward, Backward);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public bool Equals(Trafo3f other)\n            => Forward.Equals(other.Forward) && Backward.Equals(other.Backward);\n\n        public override bool Equals(object other)\n            => (other is Trafo3f o) ? Equals(o) : false;\n\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Forward, Backward);\n\n        public static Trafo3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Trafo3f(\n                M44f.Parse(x[0].ToString()),\n                M44f.Parse(x[1].ToString())\n            );\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f FromNormalFrame(V3f origin, V3f normal)\n        {\n            M44f.NormalFrame(origin, normal, out M44f forward, out M44f backward);\n            return new Trafo3f(forward, backward);\n        }\n\n        /// <summary>\n        /// Builds a transformation matrix using the scale, rotation and translation components.\n        /// NOTE: Uses the Scale * Rotation * Translation notion. \n        ///       The rotation is in Euler-Angles (roll, pitch, yaw) in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f FromComponents(V3f scale, V3f rotationInRadians, V3f translation)\n            => Scale(scale) * RotationEuler(rotationInRadians) * Translation(translation);\n\n        /// <summary>\n        /// Returns the <see cref=\"Trafo3f\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f FromBasis(V3f xAxis, V3f yAxis, V3f zAxis, V3f origin)\n        {\n            var mat = new M44f(\n                            xAxis.X, yAxis.X, zAxis.X, origin.X, \n                            xAxis.Y, yAxis.Y, zAxis.Y, origin.Y, \n                            xAxis.Z, yAxis.Z, zAxis.Z, origin.Z,\n                            0, 0, 0, 1);\n\n            return new Trafo3f(mat, mat.Inverse);\n        }\n\n        /// <summary>\n        /// Returns the <see cref=\"Trafo3f\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// Note that the axes MUST be normalized and normal to each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f FromOrthoNormalBasis(V3f xAxis, V3f yAxis, V3f zAxis)\n        {\n            return new Trafo3f(\n                        new M44f(\n                            xAxis.X, yAxis.X, zAxis.X, 0, \n                            xAxis.Y, yAxis.Y, zAxis.Y, 0, \n                            xAxis.Z, yAxis.Z, zAxis.Z, 0,\n                            0, 0, 0, 1),\n                        new M44f(\n                            xAxis.X, xAxis.Y, xAxis.Z, 0, \n                            yAxis.X, yAxis.Y, yAxis.Z, 0, \n                            zAxis.X, zAxis.Y, zAxis.Z, 0,\n                            0, 0, 0, 1)\n                        );\n        }\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"Trafo3f\"/> transformation with the translational component given by a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Translation(V3f v)\n            => new Trafo3f(M44f.Translation(v), M44f.Translation(-v));\n\n        /// <summary>\n        /// Creates a <see cref=\"Trafo3f\"/> transformation with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Translation(float tX, float tY, float tZ)\n            => Translation(new V3f(tX, tY, tZ));\n\n        /// <summary>\n        /// Creates an <see cref=\"Trafo3f\"/> transformation with the translational component given by a <see cref=\"Shift3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Translation(Shift3f shift)\n            => Translation(shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"V3f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Scale(V3f v) \n            => new Trafo3f(M44f.Scale(v), M44f.Scale(1 / v));\n\n        /// <summary>\n        /// Creates a scaling transformation using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Scale(float sX, float sY, float sZ)\n            => new Trafo3f(M44f.Scale(sX, sY, sZ),\n                           M44f.Scale(1 / sX, 1 / sY, 1 / sZ));\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Scale(float s)\n        {\n            var t = 1 / s;\n            return new Trafo3f(M44f.Scale(s), M44f.Scale(t));\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"Scale3f\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Scale(Scale3f scale)\n            => new Trafo3f(scale);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Rotation(Rot3f rotation)\n            => new Trafo3f(rotation);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Rotation(V3f normalizedAxis, float angleInRadians)\n            => new Trafo3f(M44f.Rotation(normalizedAxis, angleInRadians),\n                           M44f.Rotation(normalizedAxis, -angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationInDegrees(V3f normalizedAxis, float angleInDegrees)\n            => Rotation(normalizedAxis, Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians. \n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationEuler(float rollInRadians, float pitchInRadians, float yawInRadians)\n        {\n            var m = M44f.RotationEuler(rollInRadians, pitchInRadians, yawInRadians);\n            return new Trafo3f(m, m.Transposed); //transposed is equal but faster to inverted on orthonormal matrices like rotations.\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees. \n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationEulerInDegrees(float rollInDegrees, float pitchInDegrees, float yawInDegrees)\n            => RotationEuler(rollInDegrees.RadiansFromDegrees(), pitchInDegrees.RadiansFromDegrees(), yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationEuler(V3f rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationEulerInDegrees(V3f rollPitchYawInDegrees)\n            => RotationEulerInDegrees(rollPitchYawInDegrees.X, rollPitchYawInDegrees.Y, rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotateInto(V3f from, V3f into)\n        {\n            var rot = Rot3f.RotateInto(from, into);\n            var inv = rot.Inverse;\n            return new Trafo3f((M44f)rot, (M44f)inv);\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationX(float angleInRadians)\n            => new Trafo3f(M44f.RotationX(angleInRadians),\n                           M44f.RotationX(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationXInDegrees(float angleInDegrees)\n            => RotationX(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationY(float angleInRadians)\n            => new Trafo3f(M44f.RotationY(angleInRadians),\n                           M44f.RotationY(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationYInDegrees(float angleInDegrees)\n            => RotationY(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationZ(float angleInRadians)\n            => new Trafo3f(M44f.RotationZ(angleInRadians),\n                           M44f.RotationZ(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f RotationZInDegrees(float angleInDegrees)\n            => RotationZ(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        #endregion\n\n        #region Shear\n\n        /// <summary>\n        /// Creates a shear transformation along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f ShearYZ(float factorY, float factorZ)\n            => new Trafo3f(M44f.ShearYZ(factorY, factorZ),\n                           M44f.ShearYZ(-factorY, -factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f ShearXZ(float factorX, float factorZ)\n            => new Trafo3f(M44f.ShearXZ(factorX, factorZ),\n                           M44f.ShearXZ(-factorX, -factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f ShearXY(float factorX, float factorY)\n            => new Trafo3f(M44f.ShearXY(factorX, factorY),\n                           M44f.ShearXY(-factorX, -factorY));\n\n        #endregion\n\n        #region View transformation\n\n        /// <summary>\n        /// Creates a view transformation from the given vectors.\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"u\">Right vector of the view-plane</param>\n        /// <param name=\"v\">Up vector of the view-plane</param>\n        /// <param name=\"z\">Normal vector of the view-plane. This vector is supposed to point in view-direction for a left-handed view transformation and in opposite direction in the right-handed case.</param>\n        /// <returns>The view transformation</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f ViewTrafo(V3f location, V3f u, V3f v, V3f z)\n        {\n            return new Trafo3f(\n                new M44f(\n                    u.X, u.Y, u.Z, -Vec.Dot(u, location),\n                    v.X, v.Y, v.Z, -Vec.Dot(v, location),\n                    z.X, z.Y, z.Z, -Vec.Dot(z, location),\n                    0, 0, 0, 1\n                ),\n                new M44f(\n                    u.X, v.X, z.X, location.X,\n                    u.Y, v.Y, z.Y, location.Y,\n                    u.Z, v.Z, z.Z, location.Z,\n                    0, 0, 0, 1\n                ));\n        }\n\n        /// <summary>\n        /// Creates a right-handed view trafo, where z-negative points into the scene.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f ViewTrafoRH(V3f location, V3f up, V3f forward)\n            => ViewTrafo(location, forward.Cross(up), up, -forward);\n\n        /// <summary>\n        /// Creates a left-handed view trafo, where z-positive points into the scene.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f ViewTrafoLH(V3f location, V3f up, V3f forward)\n            => ViewTrafo(location, up.Cross(forward), up, forward);\n\n        #endregion\n\n        #region Projection transformation\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f PerspectiveProjectionRH(float l, float r, float b, float t, float n, float f = float.PositiveInfinity)\n        {\n            float m22, m23, m32i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = -1;\n                m23  = -n;\n                m32i = -1 / n;\n            }\n            else\n            {\n                m22  = f / (n - f);\n                m23  = (f * n) / (n - f);\n                m32i = (n - f) / (f * n);\n            }\n\n            return new Trafo3f(\n                new M44f(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                     0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                     0,\n                                    0,                     0,                   m22,                   m23,\n                                    0,                     0,                    -1,                     0\n                    ),\n                new M44f(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                  m32i,                 1 / n\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f PerspectiveProjectionRH(float horizontalFovInRadians, float aspect, float n, float f = float.PositiveInfinity)\n        {\n            float d = Fun.Tan(0.5f * horizontalFovInRadians) * n;\n            return Trafo3f.PerspectiveProjectionRH(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, 0)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f PerspectiveProjectionReversedRH(float l, float r, float b, float t, float n, float f = float.PositiveInfinity)\n        {\n            float m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = 0;\n                m23  = n;\n                m32i = 1 / n;\n                m33i = 0;\n            }\n            else\n            {\n                m22  = n / (f - n);\n                m23  = (f * n) / (f - n);\n                m32i = (f - n) / (f * n);\n                m33i = 1 / f;\n            }\n\n            return new Trafo3f(\n                new M44f(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                     0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                     0,\n                                    0,                     0,                   m22,                   m23,\n                                    0,                     0,                    -1,                     0\n                    ),\n                new M44f(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                  m32i,                  m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, 0)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f PerspectiveProjectionReversedRH(float horizontalFovInRadians, float aspect, float n, float f = float.PositiveInfinity)\n        {\n            float d = Fun.Tan(0.5f * horizontalFovInRadians) * n;\n            return Trafo3f.PerspectiveProjectionReversedRH(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f PerspectiveProjectionGL(float l, float r, float b, float t, float n, float f = float.PositiveInfinity)\n        {\n            float m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = -1;\n                m23  = -2 * n;\n                m32i = -1 / (2 * n);\n                m33i = -m32i;\n            }\n            else\n            {\n                m22  = (f + n) / (n - f);\n                m23  = (2 * f * n) / (n - f);\n                m32i = (n - f) / (2 * f * n);\n                m33i = (f + n) / (2 * f * n);\n            }\n\n            return new Trafo3f(\n                new M44f(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                      0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                      0,\n                                    0,                     0,                   m22,                    m23,\n                                    0,                     0,                    -1,                      0\n                    ),\n                new M44f(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                   m32i,                 m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f PerspectiveProjectionGL(float horizontalFovInRadians, float aspect, float n, float f = float.PositiveInfinity)\n        {\n            float d = Fun.Tan(0.5f * horizontalFovInRadians) * n;\n            return Trafo3f.PerspectiveProjectionGL(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, -1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f PerspectiveProjectionReversedGL(float l, float r, float b, float t, float n, float f = float.PositiveInfinity)\n        {\n            float m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = 1;\n                m23  = 2 * n;\n                m32i = 1 / (2 * n);\n                m33i = m32i;\n            }\n            else\n            {\n                m22  = (f + n) / (f - n);\n                m23  = (2 * f * n) / (f - n);\n                m32i = (f - n) / (2 * f * n);\n                m33i = (f + n) / (2 * f * n);\n            }\n\n            return new Trafo3f(\n                new M44f(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                      0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                      0,\n                                    0,                     0,                   m22,                    m23,\n                                    0,                     0,                    -1,                      0\n                    ),\n                new M44f(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                   m32i,                 m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, -1)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f PerspectiveProjectionReversedGL(float horizontalFovInRadians, float aspect, float n, float f = float.PositiveInfinity)\n        {\n            float d = Fun.Tan(0.5f * horizontalFovInRadians) * n;\n            return Trafo3f.PerspectiveProjectionReversedGL(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed orthographic projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f OrthoProjectionRH(float l, float r, float b, float t, float n, float f)\n        {\n            return new Trafo3f(\n                new M44f(\n                    2 / (r - l),               0,               0,     (l + r) / (l - r),\n                              0,     2 / (t - b),               0,     (b + t) / (b - t),\n                              0,               0,     1 / (n - f),           n / (n - f),\n                              0,               0,               0,                     1\n                    ),\n                new M44f(\n                    (r - l) / 2,               0,               0,           (l + r) / 2,\n                              0,     (t - b) / 2,               0,           (b + t) / 2,\n                              0,               0,           n - f,                    -n,\n                              0,               0,               0,                     1\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed orthographic projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f OrthoProjectionGL(float l, float r, float b, float t, float n, float f)\n        {\n            return new Trafo3f(\n                new M44f(\n                    2 / (r - l),               0,               0,     (l + r) / (l - r),\n                              0,     2 / (t - b),               0,     (b + t) / (b - t),\n                              0,               0,     2 / (n - f),     (f + n) / (n - f),\n                              0,               0,               0,                     1\n                    ),\n                new M44f(\n                    (r - l) / 2,               0,               0,           (l + r) / 2,\n                              0,     (t - b) / 2,               0,           (b + t) / 2,\n                              0,               0,     (n - f) / 2,          -(f + n) / 2,\n                              0,               0,               0,                     1\n                    )\n                );\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Conversion Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3d(Trafo3f r)\n            => new Trafo3d(r);\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Returns whether two <see cref=\"Trafo3f\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Trafo3f a, Trafo3f b)\n            => a.Forward == b.Forward && a.Backward == b.Backward;\n\n        /// <summary>\n        /// Returns whether two <see cref=\"Trafo3f\"/> transformations are different.\n        /// </summary>\n        public static bool operator !=(Trafo3f a, Trafo3f b)\n            => a.Forward != b.Forward || a.Backward != b.Backward;\n\n        /// <summary>\n        /// The order of operation of Trafo3f multiplicaition is backward\n        /// with respect to M44f multiplication in order to provide\n        /// natural postfix notation.\n        /// </summary>\n        public static Trafo3f operator *(Trafo3f t0, Trafo3f t1)\n            => new Trafo3f(t1.Forward * t0.Forward, t0.Backward * t1.Backward);\n\n        #endregion \n    }\n\n    public static partial class Trafo\n    {\n        #region Operations\n\n        /// <summary>\n        /// Returns the inverse of the given <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f Inverse(Trafo3f trafo)\n            => trafo.Inverse;\n\n        /// <summary>\n        /// Returns the forward matrix the given <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Forward(Trafo3f trafo)\n            => trafo.Forward;\n\n        /// <summary>\n        /// Returns the backward matrix the given <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Backward(Trafo3f trafo)\n            => trafo.Backward;\n\n        #endregion\n\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float GetScale(this Trafo3f trafo)\n            => trafo.Forward.GetScale3();\n\n        /// <summary>\n        /// Extracts a scale vector from the given transformation by calculating the lengths of the basis vectors. \n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetScaleVector(this Trafo3f trafo)\n            => trafo.Forward.GetScaleVector3();\n\n        /// <summary>\n        /// Extracts the inverse/backward translation component of the given transformation, which when given \n        /// a view transformation represents the location of the camera in world space.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetViewPosition(this Trafo3f trafo)\n            => trafo.Backward.C3.XYZ;\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation.\n        /// NOTE: A left-handed coordinates system transformation is expected, \n        /// where the view-space z-axis points in forward direction.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetViewDirectionLH(this Trafo3f trafo)\n            => trafo.Forward.GetViewDirectionLH();\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation.\n        /// NOTE: A right-handed coordinates system transformation is expected, where \n        /// the view-space z-axis points opposit the forward vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetViewDirectionRH(this Trafo3f trafo)\n            => trafo.Forward.GetViewDirectionRH();\n\n        /// <summary>\n        /// Extracts the translation component of the given transformation, which when given \n        /// a model transformation represents the model origin in world position.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GetModelOrigin(this Trafo3f trafo)\n            => trafo.Forward.GetModelOrigin();\n\n        /// <summary>\n        /// Builds an ortho-normal orientation transformation form the given transform.\n        /// Scale and Translation will be removed and basis vectors will be ortho-normalized.\n        /// NOTE: The x-axis is untouched and y/z are forced to a normal-angle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3f GetOrthoNormalOrientation(this Trafo3f trafo)\n        {\n            var x = trafo.Forward.C0.XYZ.Normalized;\n            var z = trafo.Forward.C2.XYZ;\n\n            var y = z.Cross(x).Normalized;\n            z = x.Cross(y).Normalized;\n\n            return Trafo3f.FromOrthoNormalBasis(x, y, z);\n        }\n\n        /// <summary>\n        /// Decomposes a transformation into a scale, rotation and translation component.\n        /// NOTE: The input is assumed to be a valid affine transformation.\n        ///       The rotation output is a vector with Euler-Angles [roll (X), pitch (Y), yaw (Z)] in radians of rotation order Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Decompose(this Trafo3f trafo, out V3f scale, out V3f rotationInRadians, out V3f translation)\n        {\n            translation = trafo.GetModelOrigin();\n            \n            var rt = trafo.GetOrthoNormalOrientation();\n            if (rt.Forward.Determinant.IsTiny())\n            {\n                rotationInRadians = V3f.Zero;\n            }\n            else\n            {\n                var rot = Rot3f.FromFrame(rt.Forward.C0.XYZ, rt.Forward.C1.XYZ, rt.Forward.C2.XYZ);\n                rotationInRadians = rot.GetEulerAngles();\n            }\n\n            scale = trafo.GetScaleVector();\n\n            // if matrix is left-handed there must be some negative scale\n            // since rotation remains the x-axis, the y-axis must be flipped\n            if (trafo.Forward.Determinant < 0)\n                scale.Y = -scale.Y;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> by a <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Transform(this Trafo3f r, V4f v)\n            => r.Forward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by a <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformDir(this Trafo3f r, V3f v)\n            => r.Forward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by a <see cref=\"Trafo3f\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformPos(this Trafo3f r, V3f p)\n            => r.Forward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by a <see cref=\"Trafo3f\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformPosProj(this Trafo3f r, V3f p)\n            => r.Forward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by a <see cref=\"Trafo3f\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f TransformPosProjFull(this Trafo3f r, V3f p)\n            => r.Forward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.W is presumed 0.0) by a <see cref=\"Trafo3f\"/>\n        /// (i.e. by its transposed backward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f TransformNormal(this Trafo3f r, V3f n)\n            => r.Backward.TransposedTransformDir(n);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4f\"/> by the inverse of a <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f InvTransform(this Trafo3f r, V4f v)\n            => r.Backward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by the inverse of a <see cref=\"Trafo3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformDir(this Trafo3f r, V3f v)\n            => r.Backward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of a <see cref=\"Trafo3f\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformPos(this Trafo3f r, V3f p)\n            => r.Backward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of a <see cref=\"Trafo3f\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformPosProj(this Trafo3f r, V3f p)\n            => r.Backward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of a <see cref=\"Trafo3f\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f InvTransformPosProjFull(this Trafo3f r, V3f p)\n            => r.Backward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.W is presumed 0.0) by the inverse of a <see cref=\"Trafo3f\"/>\n        /// (i.e. by its transposed forward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvTransformNormal(this Trafo3f r, V3f n)\n            => r.Forward.TransposedTransformDir(n);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if two <see cref=\"Trafo3f\"/> transformations are equal with regard to a threshold <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Trafo3f a, Trafo3f b, float epsilon)\n            => a.Forward.ApproximateEquals(b.Forward, epsilon) && a.Backward.ApproximateEquals(b.Backward, epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Trafo2d\n\n    /// <summary>\n    /// A trafo is a container for a forward and a backward matrix.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct Trafo2d : IEquatable<Trafo2d>\n    {\n        [DataMember]\n        public readonly M33d Forward;\n        [DataMember]\n        public readonly M33d Backward;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from a forward and backward transformation <see cref=\"M33d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(M33d forward, M33d backward)\n        {\n            Forward = forward;\n            Backward = backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from another <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(Trafo2d trafo)\n        {\n            Forward = trafo.Forward;\n            Backward = trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from a <see cref=\"Trafo2f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(Trafo2f trafo)\n        {\n            Forward = (M33d)trafo.Forward;\n            Backward = (M33d)trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from an <see cref=\"Affine2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(Affine2d trafo)\n        {\n            Forward = (M33d)trafo;\n            Backward = (M33d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from a <see cref=\"Euclidean2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(Euclidean2d trafo)\n        {\n            Forward = (M33d)trafo;\n            Backward = (M33d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from a <see cref=\"Similarity2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(Similarity2d trafo)\n        {\n            Forward = (M33d)trafo;\n            Backward = (M33d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from a <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(Rot2d trafo)\n        {\n            Forward = (M33d)trafo;\n            Backward = (M33d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from a <see cref=\"Scale2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(Scale2d trafo)\n        {\n            Forward = (M33d)trafo;\n            Backward = (M33d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo2d\"/> from a <see cref=\"Shift2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo2d(Shift2d trafo)\n        {\n            Forward = (M33d)trafo;\n            Backward = (M33d)trafo.Inverse;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Trafo2d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Trafo2d(M33d.Identity, M33d.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        public Trafo2d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Trafo2d(Backward, Forward);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override int GetHashCode() => HashCode.GetCombined(Forward, Backward);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public bool Equals(Trafo2d other)\n            => Forward.Equals(other.Forward) && Backward.Equals(other.Backward);\n\n        public override bool Equals(object other)\n            => (other is Trafo2d o) ? Equals(o) : false;\n\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Forward, Backward);\n\n        public static Trafo2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Trafo2d(\n                M33d.Parse(x[0].ToString()),\n                M33d.Parse(x[1].ToString())\n            );\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        /// <summary>\n        /// Builds a transformation matrix using the scale, rotation (in radians) and translation components.\n        /// NOTE: Uses the Scale * Rotation * Translation notion.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d FromComponents(V2d scale, double rotationInRadians, V2d translation)\n            => Scale(scale) * Rotation(rotationInRadians) * Translation(translation);\n\n        /// <summary>\n        /// Returns the <see cref=\"Trafo2d\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d FromBasis(V2d xAxis, V2d yAxis, V2d origin)\n        {\n            var mat = new M33d(\n                            xAxis.X, yAxis.X, origin.X, \n                            xAxis.Y, yAxis.Y, origin.Y,\n                            0, 0, 1);\n\n            return new Trafo2d(mat, mat.Inverse);\n        }\n\n        /// <summary>\n        /// Returns the <see cref=\"Trafo2d\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// Note that the axes MUST be normalized and normal to each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d FromOrthoNormalBasis(V2d xAxis, V2d yAxis)\n        {\n            return new Trafo2d(\n                        new M33d(\n                            xAxis.X, yAxis.X, 0, \n                            xAxis.Y, yAxis.Y, 0,\n                            0, 0, 1),\n                        new M33d(\n                            xAxis.X, xAxis.Y, 0, \n                            yAxis.X, yAxis.Y, 0,\n                            0, 0, 1)\n                        );\n        }\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"Trafo2d\"/> transformation with the translational component given by a <see cref=\"V2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Translation(V2d v)\n            => new Trafo2d(M33d.Translation(v), M33d.Translation(-v));\n\n        /// <summary>\n        /// Creates a <see cref=\"Trafo2d\"/> transformation with the translational component given by 2 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Translation(double tX, double tY)\n            => Translation(new V2d(tX, tY));\n\n        /// <summary>\n        /// Creates an <see cref=\"Trafo2d\"/> transformation with the translational component given by a <see cref=\"Shift2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Translation(Shift2d shift)\n            => Translation(shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"V2d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Scale(V2d v) \n            => new Trafo2d(M33d.Scale(v), M33d.Scale(1 / v));\n\n        /// <summary>\n        /// Creates a scaling transformation using 2 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Scale(double sX, double sY)\n            => new Trafo2d(M33d.Scale(sX, sY),\n                           M33d.Scale(1 / sX, 1 / sY));\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Scale(double s)\n        {\n            var t = 1 / s;\n            return new Trafo2d(M33d.Scale(s), M33d.Scale(t));\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"Scale2d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Scale(Scale2d scale)\n            => new Trafo2d(scale);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot2d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Rotation(Rot2d rotation)\n            => new Trafo2d(rotation);\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Rotation(double angleInRadians)\n            => new Trafo2d(M33d.Rotation(angleInRadians), M33d.Rotation(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d RotationInDegrees(double angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        #endregion\n\n        #endregion\n\n        #region Conversion Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo2f(Trafo2d r)\n            => new Trafo2f(r);\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Returns whether two <see cref=\"Trafo2d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Trafo2d a, Trafo2d b)\n            => a.Forward == b.Forward && a.Backward == b.Backward;\n\n        /// <summary>\n        /// Returns whether two <see cref=\"Trafo2d\"/> transformations are different.\n        /// </summary>\n        public static bool operator !=(Trafo2d a, Trafo2d b)\n            => a.Forward != b.Forward || a.Backward != b.Backward;\n\n        /// <summary>\n        /// The order of operation of Trafo2d multiplicaition is backward\n        /// with respect to M33d multiplication in order to provide\n        /// natural postfix notation.\n        /// </summary>\n        public static Trafo2d operator *(Trafo2d t0, Trafo2d t1)\n            => new Trafo2d(t1.Forward * t0.Forward, t0.Backward * t1.Backward);\n\n        #endregion \n    }\n\n    public static partial class Trafo\n    {\n        #region Operations\n\n        /// <summary>\n        /// Returns the inverse of the given <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo2d Inverse(Trafo2d trafo)\n            => trafo.Inverse;\n\n        /// <summary>\n        /// Returns the forward matrix the given <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Forward(Trafo2d trafo)\n            => trafo.Forward;\n\n        /// <summary>\n        /// Returns the backward matrix the given <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Backward(Trafo2d trafo)\n            => trafo.Backward;\n\n        #endregion\n\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this Trafo2d trafo)\n            => trafo.Forward.GetScale2();\n\n        /// <summary>\n        /// Extracts a scale vector from the given transformation by calculating the lengths of the basis vectors. \n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GetScaleVector(this Trafo2d trafo)\n            => trafo.Forward.GetScaleVector2();\n\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> by a <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Transform(this Trafo2d r, V3d v)\n            => r.Forward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by a <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformDir(this Trafo2d r, V2d v)\n            => r.Forward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by a <see cref=\"Trafo2d\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformPos(this Trafo2d r, V2d p)\n            => r.Forward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by a <see cref=\"Trafo2d\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformPosProj(this Trafo2d r, V2d p)\n            => r.Forward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by a <see cref=\"Trafo2d\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformPosProjFull(this Trafo2d r, V2d p)\n            => r.Forward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.Z is presumed 0.0) by a <see cref=\"Trafo2d\"/>\n        /// (i.e. by its transposed backward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d TransformNormal(this Trafo2d r, V2d n)\n            => r.Backward.TransposedTransformDir(n);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V3d\"/> by the inverse of a <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransform(this Trafo2d r, V3d v)\n            => r.Backward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.Z is presumed 0.0) by the inverse of a <see cref=\"Trafo2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransformDir(this Trafo2d r, V2d v)\n            => r.Backward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of a <see cref=\"Trafo2d\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransformPos(this Trafo2d r, V2d p)\n            => r.Backward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of a <see cref=\"Trafo2d\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransformPosProj(this Trafo2d r, V2d p)\n            => r.Backward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.Z is presumed 1.0) by the inverse of a <see cref=\"Trafo2d\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformPosProjFull(this Trafo2d r, V2d p)\n            => r.Backward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.Z is presumed 0.0) by the inverse of a <see cref=\"Trafo2d\"/>\n        /// (i.e. by its transposed forward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvTransformNormal(this Trafo2d r, V2d n)\n            => r.Forward.TransposedTransformDir(n);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if two <see cref=\"Trafo2d\"/> transformations are equal with regard to a threshold <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Trafo2d a, Trafo2d b, double epsilon)\n            => a.Forward.ApproximateEquals(b.Forward, epsilon) && a.Backward.ApproximateEquals(b.Backward, epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Trafo3d\n\n    /// <summary>\n    /// A trafo is a container for a forward and a backward matrix.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct Trafo3d : IEquatable<Trafo3d>\n    {\n        [DataMember]\n        public readonly M44d Forward;\n        [DataMember]\n        public readonly M44d Backward;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from a forward and backward transformation <see cref=\"M44d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(M44d forward, M44d backward)\n        {\n            Forward = forward;\n            Backward = backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from another <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(Trafo3d trafo)\n        {\n            Forward = trafo.Forward;\n            Backward = trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from a <see cref=\"Trafo3f\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(Trafo3f trafo)\n        {\n            Forward = (M44d)trafo.Forward;\n            Backward = (M44d)trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from an <see cref=\"Affine3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(Affine3d trafo)\n        {\n            Forward = (M44d)trafo;\n            Backward = (M44d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from a <see cref=\"Euclidean3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(Euclidean3d trafo)\n        {\n            Forward = (M44d)trafo;\n            Backward = (M44d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from a <see cref=\"Similarity3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(Similarity3d trafo)\n        {\n            Forward = (M44d)trafo;\n            Backward = (M44d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(Rot3d trafo)\n        {\n            Forward = (M44d)trafo;\n            Backward = (M44d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from a <see cref=\"Scale3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(Scale3d trafo)\n        {\n            Forward = (M44d)trafo;\n            Backward = (M44d)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"Trafo3d\"/> from a <see cref=\"Shift3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Trafo3d(Shift3d trafo)\n        {\n            Forward = (M44d)trafo;\n            Backward = (M44d)trafo.Inverse;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static Trafo3d Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Trafo3d(M44d.Identity, M44d.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        public Trafo3d Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new Trafo3d(Backward, Forward);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override int GetHashCode() => HashCode.GetCombined(Forward, Backward);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public bool Equals(Trafo3d other)\n            => Forward.Equals(other.Forward) && Backward.Equals(other.Backward);\n\n        public override bool Equals(object other)\n            => (other is Trafo3d o) ? Equals(o) : false;\n\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Forward, Backward);\n\n        public static Trafo3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new Trafo3d(\n                M44d.Parse(x[0].ToString()),\n                M44d.Parse(x[1].ToString())\n            );\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d FromNormalFrame(V3d origin, V3d normal)\n        {\n            M44d.NormalFrame(origin, normal, out M44d forward, out M44d backward);\n            return new Trafo3d(forward, backward);\n        }\n\n        /// <summary>\n        /// Builds a transformation matrix using the scale, rotation and translation components.\n        /// NOTE: Uses the Scale * Rotation * Translation notion. \n        ///       The rotation is in Euler-Angles (roll, pitch, yaw) in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d FromComponents(V3d scale, V3d rotationInRadians, V3d translation)\n            => Scale(scale) * RotationEuler(rotationInRadians) * Translation(translation);\n\n        /// <summary>\n        /// Returns the <see cref=\"Trafo3d\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d FromBasis(V3d xAxis, V3d yAxis, V3d zAxis, V3d origin)\n        {\n            var mat = new M44d(\n                            xAxis.X, yAxis.X, zAxis.X, origin.X, \n                            xAxis.Y, yAxis.Y, zAxis.Y, origin.Y, \n                            xAxis.Z, yAxis.Z, zAxis.Z, origin.Z,\n                            0, 0, 0, 1);\n\n            return new Trafo3d(mat, mat.Inverse);\n        }\n\n        /// <summary>\n        /// Returns the <see cref=\"Trafo3d\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// Note that the axes MUST be normalized and normal to each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d FromOrthoNormalBasis(V3d xAxis, V3d yAxis, V3d zAxis)\n        {\n            return new Trafo3d(\n                        new M44d(\n                            xAxis.X, yAxis.X, zAxis.X, 0, \n                            xAxis.Y, yAxis.Y, zAxis.Y, 0, \n                            xAxis.Z, yAxis.Z, zAxis.Z, 0,\n                            0, 0, 0, 1),\n                        new M44d(\n                            xAxis.X, xAxis.Y, xAxis.Z, 0, \n                            yAxis.X, yAxis.Y, yAxis.Z, 0, \n                            zAxis.X, zAxis.Y, zAxis.Z, 0,\n                            0, 0, 0, 1)\n                        );\n        }\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"Trafo3d\"/> transformation with the translational component given by a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Translation(V3d v)\n            => new Trafo3d(M44d.Translation(v), M44d.Translation(-v));\n\n        /// <summary>\n        /// Creates a <see cref=\"Trafo3d\"/> transformation with the translational component given by 3 scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Translation(double tX, double tY, double tZ)\n            => Translation(new V3d(tX, tY, tZ));\n\n        /// <summary>\n        /// Creates an <see cref=\"Trafo3d\"/> transformation with the translational component given by a <see cref=\"Shift3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Translation(Shift3d shift)\n            => Translation(shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"V3d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Scale(V3d v) \n            => new Trafo3d(M44d.Scale(v), M44d.Scale(1 / v));\n\n        /// <summary>\n        /// Creates a scaling transformation using 3 scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Scale(double sX, double sY, double sZ)\n            => new Trafo3d(M44d.Scale(sX, sY, sZ),\n                           M44d.Scale(1 / sX, 1 / sY, 1 / sZ));\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Scale(double s)\n        {\n            var t = 1 / s;\n            return new Trafo3d(M44d.Scale(s), M44d.Scale(t));\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"Scale3d\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Scale(Scale3d scale)\n            => new Trafo3d(scale);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"Rot3d\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Rotation(Rot3d rotation)\n            => new Trafo3d(rotation);\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Rotation(V3d normalizedAxis, double angleInRadians)\n            => new Trafo3d(M44d.Rotation(normalizedAxis, angleInRadians),\n                           M44d.Rotation(normalizedAxis, -angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationInDegrees(V3d normalizedAxis, double angleInDegrees)\n            => Rotation(normalizedAxis, Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians. \n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationEuler(double rollInRadians, double pitchInRadians, double yawInRadians)\n        {\n            var m = M44d.RotationEuler(rollInRadians, pitchInRadians, yawInRadians);\n            return new Trafo3d(m, m.Transposed); //transposed is equal but faster to inverted on orthonormal matrices like rotations.\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees. \n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationEulerInDegrees(double rollInDegrees, double pitchInDegrees, double yawInDegrees)\n            => RotationEuler(rollInDegrees.RadiansFromDegrees(), pitchInDegrees.RadiansFromDegrees(), yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationEuler(V3d rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationEulerInDegrees(V3d rollPitchYawInDegrees)\n            => RotationEulerInDegrees(rollPitchYawInDegrees.X, rollPitchYawInDegrees.Y, rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotateInto(V3d from, V3d into)\n        {\n            var rot = Rot3d.RotateInto(from, into);\n            var inv = rot.Inverse;\n            return new Trafo3d((M44d)rot, (M44d)inv);\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationX(double angleInRadians)\n            => new Trafo3d(M44d.RotationX(angleInRadians),\n                           M44d.RotationX(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationXInDegrees(double angleInDegrees)\n            => RotationX(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationY(double angleInRadians)\n            => new Trafo3d(M44d.RotationY(angleInRadians),\n                           M44d.RotationY(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationYInDegrees(double angleInDegrees)\n            => RotationY(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationZ(double angleInRadians)\n            => new Trafo3d(M44d.RotationZ(angleInRadians),\n                           M44d.RotationZ(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d RotationZInDegrees(double angleInDegrees)\n            => RotationZ(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        #endregion\n\n        #region Shear\n\n        /// <summary>\n        /// Creates a shear transformation along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d ShearYZ(double factorY, double factorZ)\n            => new Trafo3d(M44d.ShearYZ(factorY, factorZ),\n                           M44d.ShearYZ(-factorY, -factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d ShearXZ(double factorX, double factorZ)\n            => new Trafo3d(M44d.ShearXZ(factorX, factorZ),\n                           M44d.ShearXZ(-factorX, -factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d ShearXY(double factorX, double factorY)\n            => new Trafo3d(M44d.ShearXY(factorX, factorY),\n                           M44d.ShearXY(-factorX, -factorY));\n\n        #endregion\n\n        #region View transformation\n\n        /// <summary>\n        /// Creates a view transformation from the given vectors.\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"u\">Right vector of the view-plane</param>\n        /// <param name=\"v\">Up vector of the view-plane</param>\n        /// <param name=\"z\">Normal vector of the view-plane. This vector is supposed to point in view-direction for a left-handed view transformation and in opposite direction in the right-handed case.</param>\n        /// <returns>The view transformation</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d ViewTrafo(V3d location, V3d u, V3d v, V3d z)\n        {\n            return new Trafo3d(\n                new M44d(\n                    u.X, u.Y, u.Z, -Vec.Dot(u, location),\n                    v.X, v.Y, v.Z, -Vec.Dot(v, location),\n                    z.X, z.Y, z.Z, -Vec.Dot(z, location),\n                    0, 0, 0, 1\n                ),\n                new M44d(\n                    u.X, v.X, z.X, location.X,\n                    u.Y, v.Y, z.Y, location.Y,\n                    u.Z, v.Z, z.Z, location.Z,\n                    0, 0, 0, 1\n                ));\n        }\n\n        /// <summary>\n        /// Creates a right-handed view trafo, where z-negative points into the scene.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d ViewTrafoRH(V3d location, V3d up, V3d forward)\n            => ViewTrafo(location, forward.Cross(up), up, -forward);\n\n        /// <summary>\n        /// Creates a left-handed view trafo, where z-positive points into the scene.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d ViewTrafoLH(V3d location, V3d up, V3d forward)\n            => ViewTrafo(location, up.Cross(forward), up, forward);\n\n        #endregion\n\n        #region Projection transformation\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d PerspectiveProjectionRH(double l, double r, double b, double t, double n, double f = double.PositiveInfinity)\n        {\n            double m22, m23, m32i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = -1;\n                m23  = -n;\n                m32i = -1 / n;\n            }\n            else\n            {\n                m22  = f / (n - f);\n                m23  = (f * n) / (n - f);\n                m32i = (n - f) / (f * n);\n            }\n\n            return new Trafo3d(\n                new M44d(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                     0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                     0,\n                                    0,                     0,                   m22,                   m23,\n                                    0,                     0,                    -1,                     0\n                    ),\n                new M44d(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                  m32i,                 1 / n\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d PerspectiveProjectionRH(double horizontalFovInRadians, double aspect, double n, double f = double.PositiveInfinity)\n        {\n            double d = Fun.Tan(0.5 * horizontalFovInRadians) * n;\n            return Trafo3d.PerspectiveProjectionRH(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, 0)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d PerspectiveProjectionReversedRH(double l, double r, double b, double t, double n, double f = double.PositiveInfinity)\n        {\n            double m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = 0;\n                m23  = n;\n                m32i = 1 / n;\n                m33i = 0;\n            }\n            else\n            {\n                m22  = n / (f - n);\n                m23  = (f * n) / (f - n);\n                m32i = (f - n) / (f * n);\n                m33i = 1 / f;\n            }\n\n            return new Trafo3d(\n                new M44d(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                     0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                     0,\n                                    0,                     0,                   m22,                   m23,\n                                    0,                     0,                    -1,                     0\n                    ),\n                new M44d(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                  m32i,                  m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, 0)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d PerspectiveProjectionReversedRH(double horizontalFovInRadians, double aspect, double n, double f = double.PositiveInfinity)\n        {\n            double d = Fun.Tan(0.5 * horizontalFovInRadians) * n;\n            return Trafo3d.PerspectiveProjectionReversedRH(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d PerspectiveProjectionGL(double l, double r, double b, double t, double n, double f = double.PositiveInfinity)\n        {\n            double m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = -1;\n                m23  = -2 * n;\n                m32i = -1 / (2 * n);\n                m33i = -m32i;\n            }\n            else\n            {\n                m22  = (f + n) / (n - f);\n                m23  = (2 * f * n) / (n - f);\n                m32i = (n - f) / (2 * f * n);\n                m33i = (f + n) / (2 * f * n);\n            }\n\n            return new Trafo3d(\n                new M44d(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                      0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                      0,\n                                    0,                     0,                   m22,                    m23,\n                                    0,                     0,                    -1,                      0\n                    ),\n                new M44d(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                   m32i,                 m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d PerspectiveProjectionGL(double horizontalFovInRadians, double aspect, double n, double f = double.PositiveInfinity)\n        {\n            double d = Fun.Tan(0.5 * horizontalFovInRadians) * n;\n            return Trafo3d.PerspectiveProjectionGL(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, -1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d PerspectiveProjectionReversedGL(double l, double r, double b, double t, double n, double f = double.PositiveInfinity)\n        {\n            double m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = 1;\n                m23  = 2 * n;\n                m32i = 1 / (2 * n);\n                m33i = m32i;\n            }\n            else\n            {\n                m22  = (f + n) / (f - n);\n                m23  = (2 * f * n) / (f - n);\n                m32i = (f - n) / (2 * f * n);\n                m33i = (f + n) / (2 * f * n);\n            }\n\n            return new Trafo3d(\n                new M44d(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                      0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                      0,\n                                    0,                     0,                   m22,                    m23,\n                                    0,                     0,                    -1,                      0\n                    ),\n                new M44d(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                   m32i,                 m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, -1)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d PerspectiveProjectionReversedGL(double horizontalFovInRadians, double aspect, double n, double f = double.PositiveInfinity)\n        {\n            double d = Fun.Tan(0.5 * horizontalFovInRadians) * n;\n            return Trafo3d.PerspectiveProjectionReversedGL(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed orthographic projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d OrthoProjectionRH(double l, double r, double b, double t, double n, double f)\n        {\n            return new Trafo3d(\n                new M44d(\n                    2 / (r - l),               0,               0,     (l + r) / (l - r),\n                              0,     2 / (t - b),               0,     (b + t) / (b - t),\n                              0,               0,     1 / (n - f),           n / (n - f),\n                              0,               0,               0,                     1\n                    ),\n                new M44d(\n                    (r - l) / 2,               0,               0,           (l + r) / 2,\n                              0,     (t - b) / 2,               0,           (b + t) / 2,\n                              0,               0,           n - f,                    -n,\n                              0,               0,               0,                     1\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed orthographic projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d OrthoProjectionGL(double l, double r, double b, double t, double n, double f)\n        {\n            return new Trafo3d(\n                new M44d(\n                    2 / (r - l),               0,               0,     (l + r) / (l - r),\n                              0,     2 / (t - b),               0,     (b + t) / (b - t),\n                              0,               0,     2 / (n - f),     (f + n) / (n - f),\n                              0,               0,               0,                     1\n                    ),\n                new M44d(\n                    (r - l) / 2,               0,               0,           (l + r) / 2,\n                              0,     (t - b) / 2,               0,           (b + t) / 2,\n                              0,               0,     (n - f) / 2,          -(f + n) / 2,\n                              0,               0,               0,                     1\n                    )\n                );\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Conversion Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator Trafo3f(Trafo3d r)\n            => new Trafo3f(r);\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Returns whether two <see cref=\"Trafo3d\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(Trafo3d a, Trafo3d b)\n            => a.Forward == b.Forward && a.Backward == b.Backward;\n\n        /// <summary>\n        /// Returns whether two <see cref=\"Trafo3d\"/> transformations are different.\n        /// </summary>\n        public static bool operator !=(Trafo3d a, Trafo3d b)\n            => a.Forward != b.Forward || a.Backward != b.Backward;\n\n        /// <summary>\n        /// The order of operation of Trafo3d multiplicaition is backward\n        /// with respect to M44d multiplication in order to provide\n        /// natural postfix notation.\n        /// </summary>\n        public static Trafo3d operator *(Trafo3d t0, Trafo3d t1)\n            => new Trafo3d(t1.Forward * t0.Forward, t0.Backward * t1.Backward);\n\n        #endregion \n    }\n\n    public static partial class Trafo\n    {\n        #region Operations\n\n        /// <summary>\n        /// Returns the inverse of the given <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d Inverse(Trafo3d trafo)\n            => trafo.Inverse;\n\n        /// <summary>\n        /// Returns the forward matrix the given <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Forward(Trafo3d trafo)\n            => trafo.Forward;\n\n        /// <summary>\n        /// Returns the backward matrix the given <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Backward(Trafo3d trafo)\n            => trafo.Backward;\n\n        #endregion\n\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double GetScale(this Trafo3d trafo)\n            => trafo.Forward.GetScale3();\n\n        /// <summary>\n        /// Extracts a scale vector from the given transformation by calculating the lengths of the basis vectors. \n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetScaleVector(this Trafo3d trafo)\n            => trafo.Forward.GetScaleVector3();\n\n        /// <summary>\n        /// Extracts the inverse/backward translation component of the given transformation, which when given \n        /// a view transformation represents the location of the camera in world space.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetViewPosition(this Trafo3d trafo)\n            => trafo.Backward.C3.XYZ;\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation.\n        /// NOTE: A left-handed coordinates system transformation is expected, \n        /// where the view-space z-axis points in forward direction.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetViewDirectionLH(this Trafo3d trafo)\n            => trafo.Forward.GetViewDirectionLH();\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation.\n        /// NOTE: A right-handed coordinates system transformation is expected, where \n        /// the view-space z-axis points opposit the forward vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetViewDirectionRH(this Trafo3d trafo)\n            => trafo.Forward.GetViewDirectionRH();\n\n        /// <summary>\n        /// Extracts the translation component of the given transformation, which when given \n        /// a model transformation represents the model origin in world position.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GetModelOrigin(this Trafo3d trafo)\n            => trafo.Forward.GetModelOrigin();\n\n        /// <summary>\n        /// Builds a hull from the given view-projection transformation (left, right, bottom, top, near, far).\n        /// The view volume is assumed to be [-1, -1, -1] [1, 1, 1].\n        /// The normals of the hull planes point to the outside and are normalized. \n        /// A point inside the visual hull will has negative height to all planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Hull3d GetVisualHull(this Trafo3d viewProj)\n            => viewProj.Forward.GetVisualHull();\n\n        /// <summary>\n        /// Builds an ortho-normal orientation transformation form the given transform.\n        /// Scale and Translation will be removed and basis vectors will be ortho-normalized.\n        /// NOTE: The x-axis is untouched and y/z are forced to a normal-angle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Trafo3d GetOrthoNormalOrientation(this Trafo3d trafo)\n        {\n            var x = trafo.Forward.C0.XYZ.Normalized;\n            var z = trafo.Forward.C2.XYZ;\n\n            var y = z.Cross(x).Normalized;\n            z = x.Cross(y).Normalized;\n\n            return Trafo3d.FromOrthoNormalBasis(x, y, z);\n        }\n\n        /// <summary>\n        /// Decomposes a transformation into a scale, rotation and translation component.\n        /// NOTE: The input is assumed to be a valid affine transformation.\n        ///       The rotation output is a vector with Euler-Angles [roll (X), pitch (Y), yaw (Z)] in radians of rotation order Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Decompose(this Trafo3d trafo, out V3d scale, out V3d rotationInRadians, out V3d translation)\n        {\n            translation = trafo.GetModelOrigin();\n            \n            var rt = trafo.GetOrthoNormalOrientation();\n            if (rt.Forward.Determinant.IsTiny())\n            {\n                rotationInRadians = V3d.Zero;\n            }\n            else\n            {\n                var rot = Rot3d.FromFrame(rt.Forward.C0.XYZ, rt.Forward.C1.XYZ, rt.Forward.C2.XYZ);\n                rotationInRadians = rot.GetEulerAngles();\n            }\n\n            scale = trafo.GetScaleVector();\n\n            // if matrix is left-handed there must be some negative scale\n            // since rotation remains the x-axis, the y-axis must be flipped\n            if (trafo.Forward.Determinant < 0)\n                scale.Y = -scale.Y;\n        }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> by a <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Transform(this Trafo3d r, V4d v)\n            => r.Forward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by a <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformDir(this Trafo3d r, V3d v)\n            => r.Forward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by a <see cref=\"Trafo3d\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformPos(this Trafo3d r, V3d p)\n            => r.Forward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by a <see cref=\"Trafo3d\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformPosProj(this Trafo3d r, V3d p)\n            => r.Forward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by a <see cref=\"Trafo3d\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d TransformPosProjFull(this Trafo3d r, V3d p)\n            => r.Forward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.W is presumed 0.0) by a <see cref=\"Trafo3d\"/>\n        /// (i.e. by its transposed backward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d TransformNormal(this Trafo3d r, V3d n)\n            => r.Backward.TransposedTransformDir(n);\n\n        /// <summary>\n        /// Transforms a <see cref=\"V4d\"/> by the inverse of a <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvTransform(this Trafo3d r, V4d v)\n            => r.Backward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.W is presumed 0.0) by the inverse of a <see cref=\"Trafo3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformDir(this Trafo3d r, V3d v)\n            => r.Backward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of a <see cref=\"Trafo3d\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformPos(this Trafo3d r, V3d p)\n            => r.Backward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of a <see cref=\"Trafo3d\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformPosProj(this Trafo3d r, V3d p)\n            => r.Backward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.W is presumed 1.0) by the inverse of a <see cref=\"Trafo3d\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvTransformPosProjFull(this Trafo3d r, V3d p)\n            => r.Backward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.W is presumed 0.0) by the inverse of a <see cref=\"Trafo3d\"/>\n        /// (i.e. by its transposed forward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvTransformNormal(this Trafo3d r, V3d n)\n            => r.Forward.TransposedTransformDir(n);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if two <see cref=\"Trafo3d\"/> transformations are equal with regard to a threshold <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this Trafo3d a, Trafo3d b, double epsilon)\n            => a.Forward.ApproximateEquals(b.Forward, epsilon) && a.Backward.ApproximateEquals(b.Backward, epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Trafos/Trafo_template.cs",
    "content": "using System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action commaln = () => Out(\",\" + Environment.NewLine);\n    //# Action add = () => Out(\" + \");\n    //# Action and = () => Out(\" && \");\n    //# var fields = new[] {\"X\", \"Y\", \"Z\", \"W\"};\n    //# var fieldsL = new[] {\"x\", \"y\", \"z\", \"w\"};\n    //# foreach (var rt in Meta.RealTypes) {\n    //# for (int n = 2; n <= 3; n++) {\n    //#     var m = n + 1;\n    //#     var rt2 = (rt == Meta.DoubleType) ? Meta.FloatType : Meta.DoubleType;\n    //#     var rtype = rt.Name;\n    //#     var rtype2 = rt2.Name;\n    //#     var tc = rt.Char;\n    //#     var tc2 = rt2.Char;\n    //#     var type = \"Trafo\" + n + tc;\n    //#     var type2 = \"Trafo\" + n + tc2;\n    //#     var mnnt = \"M\" + n + n + tc;\n    //#     var mnnt2 = \"M\" + n + n + tc2;\n    //#     var mmmt = \"M\" + m + m + tc;\n    //#     var mmmt2 = \"M\" + m + m + tc2;\n    //#     var rotnt = \"Rot\" + n + tc;\n    //#     var euclideannt = \"Euclidean\" + n + tc;\n    //#     var similaritynt = \"Similarity\" + n + tc;\n    //#     var affinent = \"Affine\" + n + tc;\n    //#     var shiftnt = \"Shift\" + n + tc;\n    //#     var scalent = \"Scale\" + n + tc;\n    //#     var vnt = \"V\" + n + tc;\n    //#     var vmt = \"V\" + m + tc;\n    //#     var nfields = fields.Take(n).ToArray();\n    //#     var nfieldsL = fieldsL.Take(n).ToArray();\n    //#     var fn = fields[n];\n    //#     var isDouble = (rt == Meta.DoubleType);\n    //#     var half = (rt != Meta.DoubleType) ? \"0.5f\" : \"0.5\";\n    #region __type__\n\n    /// <summary>\n    /// A trafo is a container for a forward and a backward matrix.\n    /// </summary>\n    [DataContract]\n    [StructLayout(LayoutKind.Sequential)]\n    public readonly partial struct __type__ : IEquatable<__type__>\n    {\n        [DataMember]\n        public readonly __mmmt__ Forward;\n        [DataMember]\n        public readonly __mmmt__ Backward;\n\n        #region Constructors\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from a forward and backward transformation <see cref=\"__mmmt__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__mmmt__ forward, __mmmt__ backward)\n        {\n            Forward = forward;\n            Backward = backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from another <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type__ trafo)\n        {\n            Forward = trafo.Forward;\n            Backward = trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from a <see cref=\"__type2__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__type2__ trafo)\n        {\n            Forward = (__mmmt__)trafo.Forward;\n            Backward = (__mmmt__)trafo.Backward;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from an <see cref=\"__affinent__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__affinent__ trafo)\n        {\n            Forward = (__mmmt__)trafo;\n            Backward = (__mmmt__)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from a <see cref=\"__euclideannt__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__euclideannt__ trafo)\n        {\n            Forward = (__mmmt__)trafo;\n            Backward = (__mmmt__)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from a <see cref=\"__similaritynt__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__similaritynt__ trafo)\n        {\n            Forward = (__mmmt__)trafo;\n            Backward = (__mmmt__)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from a <see cref=\"__rotnt__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__rotnt__ trafo)\n        {\n            Forward = (__mmmt__)trafo;\n            Backward = (__mmmt__)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from a <see cref=\"__scalent__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__scalent__ trafo)\n        {\n            Forward = (__mmmt__)trafo;\n            Backward = (__mmmt__)trafo.Inverse;\n        }\n\n        /// <summary>\n        /// Constructs a <see cref=\"__type__\"/> from a <see cref=\"__shiftnt__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __type__(__shiftnt__ trafo)\n        {\n            Forward = (__mmmt__)trafo;\n            Backward = (__mmmt__)trafo.Inverse;\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Gets the identity transformation.\n        /// </summary>\n        public static __type__ Identity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(__mmmt__.Identity, __mmmt__.Identity);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the inverse of this <see cref=\"__type__\"/>.\n        /// </summary>\n        public __type__ Inverse\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => new __type__(Backward, Forward);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override int GetHashCode() => HashCode.GetCombined(Forward, Backward);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public bool Equals(__type__ other)\n            => Forward.Equals(other.Forward) && Backward.Equals(other.Backward);\n\n        public override bool Equals(object other)\n            => (other is __type__ o) ? Equals(o) : false;\n\n        public override string ToString()\n            => string.Format(CultureInfo.InvariantCulture, \"[{0}, {1}]\", Forward, Backward);\n\n        public static __type__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __type__(\n                __mmmt__.Parse(x[0].ToString()),\n                __mmmt__.Parse(x[1].ToString())\n            );\n        }\n\n        #endregion\n\n        #region Static Creators\n\n        //# if (n == 3) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromNormalFrame(__vnt__ origin, __vnt__ normal)\n        {\n            __mmmt__.NormalFrame(origin, normal, out __mmmt__ forward, out __mmmt__ backward);\n            return new __type__(forward, backward);\n        }\n\n        //# }\n        //# if (n == 2) {\n        /// <summary>\n        /// Builds a transformation matrix using the scale, rotation (in radians) and translation components.\n        /// NOTE: Uses the Scale * Rotation * Translation notion.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromComponents(__vnt__ scale, __rtype__ rotationInRadians, __vnt__ translation)\n            => Scale(scale) * Rotation(rotationInRadians) * Translation(translation);\n\n        //# } else {\n        /// <summary>\n        /// Builds a transformation matrix using the scale, rotation and translation components.\n        /// NOTE: Uses the Scale * Rotation * Translation notion. \n        ///       The rotation is in Euler-Angles (roll, pitch, yaw) in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromComponents(__vnt__ scale, __vnt__ rotationInRadians, __vnt__ translation)\n            => Scale(scale) * RotationEuler(rotationInRadians) * Translation(translation);\n\n        //# }\n        /// <summary>\n        /// Returns the <see cref=\"__type__\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromBasis(/*# nfieldsL.ForEach(f => {*/__vnt__ __f__Axis/*# }, comma);*/, __vnt__ origin)\n        {\n            var mat = new __mmmt__(/*# nfields.ForEach(fi => {*/\n                            /*# nfieldsL.ForEach(fj => {*/__fj__Axis.__fi__/*# }, comma);*/, origin.__fi__/*#}, comma);*/,\n                            /*# n.ForEach(j => {*/0/*# }, comma);*/, 1);\n\n            return new __type__(mat, mat.Inverse);\n        }\n\n        /// <summary>\n        /// Returns the <see cref=\"__type__\"/> that transforms from the coordinate system\n        /// specified by the basis into the world coordinate system.\n        /// Note that the axes MUST be normalized and normal to each other.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ FromOrthoNormalBasis(/*# nfieldsL.ForEach(f => {*/__vnt__ __f__Axis/*# }, comma);*/)\n        {\n            return new __type__(\n                        new __mmmt__(/*# nfields.ForEach(fi => {*/\n                            /*# nfieldsL.ForEach(fj => {*/__fj__Axis.__fi__/*# }, comma);*/, 0/*#}, comma);*/,\n                            /*# n.ForEach(j => {*/0/*# }, comma);*/, 1),\n                        new __mmmt__(/*# nfieldsL.ForEach(fi => {*/\n                            /*# nfields.ForEach(fj => {*/__fi__Axis.__fj__/*# }, comma);*/, 0/*#}, comma);*/,\n                            /*# n.ForEach(j => {*/0/*# }, comma);*/, 1)\n                        );\n        }\n\n        #region Translation\n\n        /// <summary>\n        /// Creates an <see cref=\"__type__\"/> transformation with the translational component given by a <see cref=\"__vnt__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(__vnt__ v)\n            => new __type__(__mmmt__.Translation(v), __mmmt__.Translation(-v));\n\n        /// <summary>\n        /// Creates a <see cref=\"__type__\"/> transformation with the translational component given by __n__ scalars.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(/*# nfields.ForEach(f => { */__rtype__ t__f__/*# }, comma); */)\n            => Translation(new __vnt__(/*# nfields.ForEach(f => { */t__f__/*# }, comma); */));\n\n        /// <summary>\n        /// Creates an <see cref=\"__type__\"/> transformation with the translational component given by a <see cref=\"__shiftnt__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Translation(__shiftnt__ shift)\n            => Translation(shift.V);\n\n        #endregion\n\n        #region Scale\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"__vnt__\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scale(__vnt__ v) \n            => new __type__(__mmmt__.Scale(v), __mmmt__.Scale(1 / v));\n\n        /// <summary>\n        /// Creates a scaling transformation using __n__ scalars as scaling factors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scale(/*# nfields.ForEach(f => { */__rtype__ s__f__/*# }, comma); */)\n            => new __type__(__mmmt__.Scale(/*# nfields.ForEach(f => { */s__f__/*# }, comma); */),\n                           __mmmt__.Scale(/*# nfields.ForEach(f => { */1 / s__f__/*# }, comma); */));\n\n        /// <summary>\n        /// Creates a scaling transformation using a uniform scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scale(__rtype__ s)\n        {\n            var t = 1 / s;\n            return new __type__(__mmmt__.Scale(s), __mmmt__.Scale(t));\n        }\n\n        /// <summary>\n        /// Creates a scaling transformation using a <see cref=\"__scalent__\"/> as scaling factor.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Scale(__scalent__ scale)\n            => new __type__(scale);\n\n        #endregion\n\n        #region Rotation\n\n        /// <summary>\n        /// Creates a rotation transformation from a <see cref=\"__rotnt__\"/> transformation.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__rotnt__ rotation)\n            => new __type__(rotation);\n\n        //# if (n == 2) {\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__rtype__ angleInRadians)\n            => new __type__(__mmmt__.Rotation(angleInRadians), __mmmt__.Rotation(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation with the specified angle in degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__rtype__ angleInDegrees)\n            => Rotation(angleInDegrees.RadiansFromDegrees());\n\n        //# } else if (n == 3) {\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in radians.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Rotation(__vnt__ normalizedAxis, __rtype__ angleInRadians)\n            => new __type__(__mmmt__.Rotation(normalizedAxis, angleInRadians),\n                           __mmmt__.Rotation(normalizedAxis, -angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation from an axis vector and an angle in degrees.\n        /// The axis vector has to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationInDegrees(__vnt__ normalizedAxis, __rtype__ angleInDegrees)\n            => Rotation(normalizedAxis, Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in radians. \n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__rtype__ rollInRadians, __rtype__ pitchInRadians, __rtype__ yawInRadians)\n        {\n            var m = __mmmt__.RotationEuler(rollInRadians, pitchInRadians, yawInRadians);\n            return new __type__(m, m.Transposed); //transposed is equal but faster to inverted on orthonormal matrices like rotations.\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) in degrees. \n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__rtype__ rollInDegrees, __rtype__ pitchInDegrees, __rtype__ yawInDegrees)\n            => RotationEuler(rollInDegrees.RadiansFromDegrees(), pitchInDegrees.RadiansFromDegrees(), yawInDegrees.RadiansFromDegrees());\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in radians.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEuler(__vnt__ rollPitchYawInRadians)\n            => RotationEuler(rollPitchYawInRadians.X, rollPitchYawInRadians.Y, rollPitchYawInRadians.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation from roll (X), pitch (Y), and yaw (Z) vector in degrees.\n        /// The rotation order is: Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationEulerInDegrees(__vnt__ rollPitchYawInDegrees)\n            => RotationEulerInDegrees(rollPitchYawInDegrees.X, rollPitchYawInDegrees.Y, rollPitchYawInDegrees.Z);\n\n        /// <summary>\n        /// Creates a rotation transformation which rotates one vector into another.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotateInto(__vnt__ from, __vnt__ into)\n        {\n            var rot = __rotnt__.RotateInto(from, into);\n            var inv = rot.Inverse;\n            return new __type__((__mmmt__)rot, (__mmmt__)inv);\n        }\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationX(__rtype__ angleInRadians)\n            => new __type__(__mmmt__.RotationX(angleInRadians),\n                           __mmmt__.RotationX(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationXInDegrees(__rtype__ angleInDegrees)\n            => RotationX(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationY(__rtype__ angleInRadians)\n            => new __type__(__mmmt__.RotationY(angleInRadians),\n                           __mmmt__.RotationY(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationYInDegrees(__rtype__ angleInDegrees)\n            => RotationY(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInRadians\"/> radians around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZ(__rtype__ angleInRadians)\n            => new __type__(__mmmt__.RotationZ(angleInRadians),\n                           __mmmt__.RotationZ(-angleInRadians));\n\n        /// <summary>\n        /// Creates a rotation transformation by <paramref name=\"angleInDegrees\"/> degrees around the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ RotationZInDegrees(__rtype__ angleInDegrees)\n            => RotationZ(Conversion.RadiansFromDegrees(angleInDegrees));\n\n        //# }\n        #endregion\n\n        //# if (n == 3) {\n        #region Shear\n\n        /// <summary>\n        /// Creates a shear transformation along the x-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ShearYZ(__rtype__ factorY, __rtype__ factorZ)\n            => new __type__(__mmmt__.ShearYZ(factorY, factorZ),\n                           __mmmt__.ShearYZ(-factorY, -factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the y-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ShearXZ(__rtype__ factorX, __rtype__ factorZ)\n            => new __type__(__mmmt__.ShearXZ(factorX, factorZ),\n                           __mmmt__.ShearXZ(-factorX, -factorZ));\n\n        /// <summary>\n        /// Creates a shear transformation along the z-axis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ShearXY(__rtype__ factorX, __rtype__ factorY)\n            => new __type__(__mmmt__.ShearXY(factorX, factorY),\n                           __mmmt__.ShearXY(-factorX, -factorY));\n\n        #endregion\n\n        #region View transformation\n\n        /// <summary>\n        /// Creates a view transformation from the given vectors.\n        /// </summary>\n        /// <param name=\"location\">Origin of the view</param>\n        /// <param name=\"u\">Right vector of the view-plane</param>\n        /// <param name=\"v\">Up vector of the view-plane</param>\n        /// <param name=\"z\">Normal vector of the view-plane. This vector is supposed to point in view-direction for a left-handed view transformation and in opposite direction in the right-handed case.</param>\n        /// <returns>The view transformation</returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ViewTrafo(__vnt__ location, __vnt__ u, __vnt__ v, __vnt__ z)\n        {\n            return new __type__(\n                new __mmmt__(\n                    u.X, u.Y, u.Z, -Vec.Dot(u, location),\n                    v.X, v.Y, v.Z, -Vec.Dot(v, location),\n                    z.X, z.Y, z.Z, -Vec.Dot(z, location),\n                    0, 0, 0, 1\n                ),\n                new __mmmt__(\n                    u.X, v.X, z.X, location.X,\n                    u.Y, v.Y, z.Y, location.Y,\n                    u.Z, v.Z, z.Z, location.Z,\n                    0, 0, 0, 1\n                ));\n        }\n\n        /// <summary>\n        /// Creates a right-handed view trafo, where z-negative points into the scene.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ViewTrafoRH(__vnt__ location, __vnt__ up, __vnt__ forward)\n            => ViewTrafo(location, forward.Cross(up), up, -forward);\n\n        /// <summary>\n        /// Creates a left-handed view trafo, where z-positive points into the scene.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ ViewTrafoLH(__vnt__ location, __vnt__ up, __vnt__ forward)\n            => ViewTrafo(location, up.Cross(forward), up, forward);\n\n        #endregion\n\n        #region Projection transformation\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ PerspectiveProjectionRH(__rtype__ l, __rtype__ r, __rtype__ b, __rtype__ t, __rtype__ n, __rtype__ f = __rtype__.PositiveInfinity)\n        {\n            __rtype__ m22, m23, m32i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = -1;\n                m23  = -n;\n                m32i = -1 / n;\n            }\n            else\n            {\n                m22  = f / (n - f);\n                m23  = (f * n) / (n - f);\n                m32i = (n - f) / (f * n);\n            }\n\n            return new __type__(\n                new __mmmt__(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                     0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                     0,\n                                    0,                     0,                   m22,                   m23,\n                                    0,                     0,                    -1,                     0\n                    ),\n                new __mmmt__(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                  m32i,                 1 / n\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ PerspectiveProjectionRH(__rtype__ horizontalFovInRadians, __rtype__ aspect, __rtype__ n, __rtype__ f = __rtype__.PositiveInfinity)\n        {\n            __rtype__ d = Fun.Tan(__half__ * horizontalFovInRadians) * n;\n            return __type__.PerspectiveProjectionRH(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, 0)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ PerspectiveProjectionReversedRH(__rtype__ l, __rtype__ r, __rtype__ b, __rtype__ t, __rtype__ n, __rtype__ f = __rtype__.PositiveInfinity)\n        {\n            __rtype__ m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = 0;\n                m23  = n;\n                m32i = 1 / n;\n                m33i = 0;\n            }\n            else\n            {\n                m22  = n / (f - n);\n                m23  = (f * n) / (f - n);\n                m32i = (f - n) / (f * n);\n                m33i = 1 / f;\n            }\n\n            return new __type__(\n                new __mmmt__(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                     0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                     0,\n                                    0,                     0,                   m22,                   m23,\n                                    0,                     0,                    -1,                     0\n                    ),\n                new __mmmt__(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                  m32i,                  m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, 0)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ PerspectiveProjectionReversedRH(__rtype__ horizontalFovInRadians, __rtype__ aspect, __rtype__ n, __rtype__ f = __rtype__.PositiveInfinity)\n        {\n            __rtype__ d = Fun.Tan(__half__ * horizontalFovInRadians) * n;\n            return __type__.PerspectiveProjectionReversedRH(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ PerspectiveProjectionGL(__rtype__ l, __rtype__ r, __rtype__ b, __rtype__ t, __rtype__ n, __rtype__ f = __rtype__.PositiveInfinity)\n        {\n            __rtype__ m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = -1;\n                m23  = -2 * n;\n                m32i = -1 / (2 * n);\n                m33i = -m32i;\n            }\n            else\n            {\n                m22  = (f + n) / (n - f);\n                m23  = (2 * f * n) / (n - f);\n                m32i = (n - f) / (2 * f * n);\n                m33i = (f + n) / (2 * f * n);\n            }\n\n            return new __type__(\n                new __mmmt__(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                      0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                      0,\n                                    0,                     0,                   m22,                    m23,\n                                    0,                     0,                    -1,                      0\n                    ),\n                new __mmmt__(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                   m32i,                 m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ PerspectiveProjectionGL(__rtype__ horizontalFovInRadians, __rtype__ aspect, __rtype__ n, __rtype__ f = __rtype__.PositiveInfinity)\n        {\n            __rtype__ d = Fun.Tan(__half__ * horizontalFovInRadians) * n;\n            return __type__.PerspectiveProjectionGL(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, -1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume. Can be infinite.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ PerspectiveProjectionReversedGL(__rtype__ l, __rtype__ r, __rtype__ b, __rtype__ t, __rtype__ n, __rtype__ f = __rtype__.PositiveInfinity)\n        {\n            __rtype__ m22, m23, m32i, m33i;\n\n            if (f.IsPositiveInfinity())\n            {\n                m22  = 1;\n                m23  = 2 * n;\n                m32i = 1 / (2 * n);\n                m33i = m32i;\n            }\n            else\n            {\n                m22  = (f + n) / (f - n);\n                m23  = (2 * f * n) / (f - n);\n                m32i = (f - n) / (2 * f * n);\n                m33i = (f + n) / (2 * f * n);\n            }\n\n            return new __type__(\n                new __mmmt__(\n                    (2 * n) / (r - l),                     0,     (r + l) / (r - l),                      0,\n                                    0,     (2 * n) / (t - b),     (t + b) / (t - b),                      0,\n                                    0,                     0,                   m22,                    m23,\n                                    0,                     0,                    -1,                      0\n                    ),\n                new __mmmt__(\n                    (r - l) / (2 * n),                     0,                     0,     (r + l) / (2 * n),\n                                    0,     (t - b) / (2 * n),                     0,     (t + b) / (2 * n),\n                                    0,                     0,                     0,                    -1,\n                                    0,                     0,                   m32i,                 m33i\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed reversed perspective projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, +1), (+1, +1, -1)].\n        /// </summary>\n        /// <param name=\"horizontalFovInRadians\">Horizontal field of view in radians.</param>\n        /// <param name=\"aspect\">Aspect ratio, defined as view space width divided by height.</param>\n        /// <param name=\"n\">Z-value of the near view-plane.</param>\n        /// <param name=\"f\">Z-value of the far view-plane. Can be infinite.</param>\n        /// <returns></returns>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ PerspectiveProjectionReversedGL(__rtype__ horizontalFovInRadians, __rtype__ aspect, __rtype__ n, __rtype__ f = __rtype__.PositiveInfinity)\n        {\n            __rtype__ d = Fun.Tan(__half__ * horizontalFovInRadians) * n;\n            return __type__.PerspectiveProjectionReversedGL(-d, d, -d / aspect, d / aspect, n, f);\n        }\n\n        /// <summary>\n        /// Creates a right-handed orthographic projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, 0), (+1, +1, +1)].\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ OrthoProjectionRH(__rtype__ l, __rtype__ r, __rtype__ b, __rtype__ t, __rtype__ n, __rtype__ f)\n        {\n            return new __type__(\n                new __mmmt__(\n                    2 / (r - l),               0,               0,     (l + r) / (l - r),\n                              0,     2 / (t - b),               0,     (b + t) / (b - t),\n                              0,               0,     1 / (n - f),           n / (n - f),\n                              0,               0,               0,                     1\n                    ),\n                new __mmmt__(\n                    (r - l) / 2,               0,               0,           (l + r) / 2,\n                              0,     (t - b) / 2,               0,           (b + t) / 2,\n                              0,               0,           n - f,                    -n,\n                              0,               0,               0,                     1\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Creates a right-handed orthographic projection transform, where z-negative points into the scene.\n        /// The resulting canonical view volume is [(-1, -1, -1), (+1, +1, +1)] and left-handed (handedness flip between view and NDC space).\n        /// </summary>\n        /// <param name=\"l\">Minimum x-value of the view volume.</param>\n        /// <param name=\"r\">Maximum x-value of the view volume.</param>\n        /// <param name=\"b\">Minimum y-value of the view volume.</param>\n        /// <param name=\"t\">Maximum y-value of the view volume.</param>\n        /// <param name=\"n\">Minimum z-value of the view volume.</param>\n        /// <param name=\"f\">Maximum z-value of the view volume.</param>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ OrthoProjectionGL(__rtype__ l, __rtype__ r, __rtype__ b, __rtype__ t, __rtype__ n, __rtype__ f)\n        {\n            return new __type__(\n                new __mmmt__(\n                    2 / (r - l),               0,               0,     (l + r) / (l - r),\n                              0,     2 / (t - b),               0,     (b + t) / (b - t),\n                              0,               0,     2 / (n - f),     (f + n) / (n - f),\n                              0,               0,               0,                     1\n                    ),\n                new __mmmt__(\n                    (r - l) / 2,               0,               0,           (l + r) / 2,\n                              0,     (t - b) / 2,               0,           (b + t) / 2,\n                              0,               0,     (n - f) / 2,          -(f + n) / 2,\n                              0,               0,               0,                     1\n                    )\n                );\n        }\n\n        #endregion\n\n        //# }\n        #endregion\n\n        #region Conversion Operators\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __type2__(__type__ r)\n            => new __type2__(r);\n\n        #endregion\n\n        #region Operators\n\n        /// <summary>\n        /// Returns whether two <see cref=\"__type__\"/> transformations are equal.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__type__ a, __type__ b)\n            => a.Forward == b.Forward && a.Backward == b.Backward;\n\n        /// <summary>\n        /// Returns whether two <see cref=\"__type__\"/> transformations are different.\n        /// </summary>\n        public static bool operator !=(__type__ a, __type__ b)\n            => a.Forward != b.Forward || a.Backward != b.Backward;\n\n        /// <summary>\n        /// The order of operation of __type__ multiplicaition is backward\n        /// with respect to __mmmt__ multiplication in order to provide\n        /// natural postfix notation.\n        /// </summary>\n        public static __type__ operator *(__type__ t0, __type__ t1)\n            => new __type__(t1.Forward * t0.Forward, t0.Backward * t1.Backward);\n\n        #endregion \n    }\n\n    public static partial class Trafo\n    {\n        #region Operations\n\n        /// <summary>\n        /// Returns the inverse of the given <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ Inverse(__type__ trafo)\n            => trafo.Inverse;\n\n        /// <summary>\n        /// Returns the forward matrix the given <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mmmt__ Forward(__type__ trafo)\n            => trafo.Forward;\n\n        /// <summary>\n        /// Returns the backward matrix the given <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mmmt__ Backward(__type__ trafo)\n            => trafo.Backward;\n\n        #endregion\n\n        #region Transformation Extraction\n\n        /// <summary>\n        /// Approximates the uniform scale value of the given transformation (average length of basis vectors).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __rtype__ GetScale(this __type__ trafo)\n            => trafo.Forward.GetScale__n__();\n\n        /// <summary>\n        /// Extracts a scale vector from the given transformation by calculating the lengths of the basis vectors. \n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ GetScaleVector(this __type__ trafo)\n            => trafo.Forward.GetScaleVector__n__();\n\n        //# if (n == 3) {\n        /// <summary>\n        /// Extracts the inverse/backward translation component of the given transformation, which when given \n        /// a view transformation represents the location of the camera in world space.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ GetViewPosition(this __type__ trafo)\n            => trafo.Backward.C3.XYZ;\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation.\n        /// NOTE: A left-handed coordinates system transformation is expected, \n        /// where the view-space z-axis points in forward direction.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ GetViewDirectionLH(this __type__ trafo)\n            => trafo.Forward.GetViewDirectionLH();\n\n        /// <summary>\n        /// Extracts the forward vector from the given view transformation.\n        /// NOTE: A right-handed coordinates system transformation is expected, where \n        /// the view-space z-axis points opposit the forward vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ GetViewDirectionRH(this __type__ trafo)\n            => trafo.Forward.GetViewDirectionRH();\n\n        /// <summary>\n        /// Extracts the translation component of the given transformation, which when given \n        /// a model transformation represents the model origin in world position.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ GetModelOrigin(this __type__ trafo)\n            => trafo.Forward.GetModelOrigin();\n\n        //# if (isDouble) {\n        /// <summary>\n        /// Builds a hull from the given view-projection transformation (left, right, bottom, top, near, far).\n        /// The view volume is assumed to be [-1, -1, -1] [1, 1, 1].\n        /// The normals of the hull planes point to the outside and are normalized. \n        /// A point inside the visual hull will has negative height to all planes.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Hull3d GetVisualHull(this __type__ viewProj)\n            => viewProj.Forward.GetVisualHull();\n\n        //# }\n        /// <summary>\n        /// Builds an ortho-normal orientation transformation form the given transform.\n        /// Scale and Translation will be removed and basis vectors will be ortho-normalized.\n        /// NOTE: The x-axis is untouched and y/z are forced to a normal-angle.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __type__ GetOrthoNormalOrientation(this __type__ trafo)\n        {\n            var x = trafo.Forward.C0.XYZ.Normalized;\n            var z = trafo.Forward.C2.XYZ;\n\n            var y = z.Cross(x).Normalized;\n            z = x.Cross(y).Normalized;\n\n            return __type__.FromOrthoNormalBasis(x, y, z);\n        }\n\n        /// <summary>\n        /// Decomposes a transformation into a scale, rotation and translation component.\n        /// NOTE: The input is assumed to be a valid affine transformation.\n        ///       The rotation output is a vector with Euler-Angles [roll (X), pitch (Y), yaw (Z)] in radians of rotation order Z, Y, X.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Decompose(this __type__ trafo, out __vnt__ scale, out __vnt__ rotationInRadians, out __vnt__ translation)\n        {\n            translation = trafo.GetModelOrigin();\n            \n            var rt = trafo.GetOrthoNormalOrientation();\n            if (rt.Forward.Determinant.IsTiny())\n            {\n                rotationInRadians = __vnt__.Zero;\n            }\n            else\n            {\n                var rot = __rotnt__.FromFrame(rt.Forward.C0.XYZ, rt.Forward.C1.XYZ, rt.Forward.C2.XYZ);\n                rotationInRadians = rot.GetEulerAngles();\n            }\n\n            scale = trafo.GetScaleVector();\n\n            // if matrix is left-handed there must be some negative scale\n            // since rotation remains the x-axis, the y-axis must be flipped\n            if (trafo.Forward.Determinant < 0)\n                scale.Y = -scale.Y;\n        }\n        //# }\n\n        #endregion\n\n        #region Transformations\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> by a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ Transform(this __type__ r, __vmt__ v)\n            => r.Forward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.__fn__ is presumed 0.0) by a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformDir(this __type__ r, __vnt__ v)\n            => r.Forward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by a <see cref=\"__type__\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformPos(this __type__ r, __vnt__ p)\n            => r.Forward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by a <see cref=\"__type__\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformPosProj(this __type__ r, __vnt__ p)\n            => r.Forward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by a <see cref=\"__type__\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ TransformPosProjFull(this __type__ r, __vnt__ p)\n            => r.Forward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.__fn__ is presumed 0.0) by a <see cref=\"__type__\"/>\n        /// (i.e. by its transposed backward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ TransformNormal(this __type__ r, __vnt__ n)\n            => r.Backward.TransposedTransformDir(n);\n\n        /// <summary>\n        /// Transforms a <see cref=\"__vmt__\"/> by the inverse of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ InvTransform(this __type__ r, __vmt__ v)\n            => r.Backward.Transform(v);\n\n        /// <summary>\n        /// Transforms direction vector v (v.__fn__ is presumed 0.0) by the inverse of a <see cref=\"__type__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ InvTransformDir(this __type__ r, __vnt__ v)\n            => r.Backward.TransformDir(v);\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by the inverse of a <see cref=\"__type__\"/>.\n        /// No projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ InvTransformPos(this __type__ r, __vnt__ p)\n            => r.Backward.TransformPos(p);\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by the inverse of a <see cref=\"__type__\"/>.\n        /// Projective transform is performed. Perspective Division is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ InvTransformPosProj(this __type__ r, __vnt__ p)\n            => r.Backward.TransformPosProj(p);\n\n        /// <summary>\n        /// Transforms point p (p.__fn__ is presumed 1.0) by the inverse of a <see cref=\"__type__\"/>.\n        /// Projective transform is performed.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vmt__ InvTransformPosProjFull(this __type__ r, __vnt__ p)\n            => r.Backward.TransformPosProjFull(p);\n\n        /// <summary>\n        /// Transforms normal vector n (n.__fn__ is presumed 0.0) by the inverse of a <see cref=\"__type__\"/>\n        /// (i.e. by its transposed forward matrix).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vnt__ InvTransformNormal(this __type__ r, __vnt__ n)\n            => r.Forward.TransposedTransformDir(n);\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns if two <see cref=\"__type__\"/> transformations are equal with regard to a threshold <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __type__ a, __type__ b, __rtype__ epsilon)\n            => a.Forward.ApproximateEquals(b.Forward, epsilon) && a.Backward.ApproximateEquals(b.Backward, epsilon);\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/HashCode.cs",
    "content": "﻿using static Aardvark.Base.HashCode;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public static class VectorHashCodeExtensions\n    {\n        /// <summary>\n        /// Compute the first of four possible hashcodes for hashing in a 2-D\n        /// unit grid. Add items with this function, retrieve with function\n        /// HashCode.Get4.\n        /// </summary>\n        public static int Get1of4(V2d point)\n        {\n            var xi = (long)Floor(point.X);\n            var yi = (long)Floor(point.Y);\n\n            return Combine((int)(xi >> 1), (int)(yi >> 1));\n        }\n\n        /// <summary>\n        /// Compute all four possible hashcodes for hashing in a 2-D unit grid.\n        /// Retrive all items with the four hashodes written into the supplied\n        /// array. Items need to be added just with the first of the four\n        /// hashcodes (also computed by function HashCodeGet1of4).\n        /// </summary>\n        public static void Get4(V2d point, int[] hca)\n        {\n            var xi = (long)Floor(point.X);\n            var yi = (long)Floor(point.Y);\n\n            int xh0 = (int)(xi >> 1), xh1 = xh0 - 1 + ((int)(xi & 1) << 1);\n            int yh0 = (int)(yi >> 1), yh1 = yh0 - 1 + ((int)(yi & 1) << 1);\n\n            hca[0] = Combine(xh0, yh0);\n            hca[1] = Combine(xh1, yh0);\n            hca[2] = Combine(xh0, yh1);\n            hca[3] = Combine(xh1, yh1);\n        }\n\n        /// <summary>\n        /// Compute the first of eight possible hashcodes for hashing in a 3-D\n        /// unit grid. Add items with this function, retrieve with function\n        /// HashCode.Get8.\n        /// </summary>\n        public static int Get1of8(V3d point)\n        {\n            var xi = (long)Floor(point.X);\n            var yi = (long)Floor(point.Y);\n            var zi = (long)Floor(point.Z);\n\n            return Combine((int)(xi >> 1), (int)(yi >> 1), (int)(zi >> 1));\n        }\n\n        /// <summary>\n        /// Compute all eight possible hashcodes for hashing in a 3-D unit grid.\n        /// Retrive all items with the eight hashodes written into the supplied\n        /// array. Items need to be added just with the first of the eight\n        /// hashcodes (also computed by function HashCodeGet1of2).\n        /// </summary>\n        public static void Get8(V3d point, int[] hca)\n        {\n            var xi = (long)Floor(point.X);\n            var yi = (long)Floor(point.Y);\n            var zi = (long)Floor(point.Z);\n\n            int xh0 = (int)(xi >> 1), xh1 = xh0 - 1 + ((int)(xi & 1) << 1);\n            int yh0 = (int)(yi >> 1), yh1 = yh0 - 1 + ((int)(yi & 1) << 1);\n            int zh0 = (int)(zi >> 1), zh1 = zh0 - 1 + ((int)(zi & 1) << 1);\n\n            hca[0] = Combine(xh0, yh0, zh0);\n            hca[1] = Combine(xh1, yh0, zh0);\n            hca[2] = Combine(xh0, yh1, zh0);\n            hca[3] = Combine(xh1, yh1, zh0);\n            hca[4] = Combine(xh0, yh0, zh1);\n            hca[5] = Combine(xh1, yh0, zh1);\n            hca[6] = Combine(xh0, yh1, zh1);\n            hca[7] = Combine(xh1, yh1, zh1);\n        }\n\n        /// <summary>\n        /// Compute the first of 16 possible hashcodes for hashing in a 4-D\n        /// unit grid. Add items with this function, retrieve with function\n        /// HashCode.Get16.\n        /// </summary>\n        public static int Get1of16(V4d point)\n        {\n            var xi = (long)Floor(point.X);\n            var yi = (long)Floor(point.Y);\n            var zi = (long)Floor(point.Z);\n            var wi = (long)Floor(point.W);\n\n            return Combine((int)(xi >> 1), (int)(yi >> 1), (int)(zi >> 1), (int)(wi >> 1));\n        }\n\n        /// <summary>\n        /// Compute all 16 possible hashcodes for hashing in a 4-D unit grid.\n        /// Retrive all items with the 16 hashodes written into the supplied\n        /// array. Items need to be added just with the first of the 16\n        /// hashcodes (also computed by function HashCodeGet1of16).\n        /// </summary>\n        public static void Get16(V4d point, int[] hca)\n        {\n            var xi = (long)Floor(point.X);\n            var yi = (long)Floor(point.Y);\n            var zi = (long)Floor(point.Z);\n            var wi = (long)Floor(point.W);\n\n            int xh0 = (int)(xi >> 1), xh1 = xh0 - 1 + ((int)(xi & 1) << 1);\n            int yh0 = (int)(yi >> 1), yh1 = yh0 - 1 + ((int)(yi & 1) << 1);\n            int zh0 = (int)(zi >> 1), zh1 = zh0 - 1 + ((int)(zi & 1) << 1);\n            int dh0 = (int)(wi >> 1), dh1 = dh0 - 1 + ((int)(wi & 1) << 1);\n\n            hca[0] = Combine(xh0, yh0, zh0, dh0);\n            hca[1] = Combine(xh1, yh0, zh0, dh0);\n            hca[2] = Combine(xh0, yh1, zh0, dh0);\n            hca[3] = Combine(xh1, yh1, zh0, dh0);\n            hca[4] = Combine(xh0, yh0, zh1, dh0);\n            hca[5] = Combine(xh1, yh0, zh1, dh0);\n            hca[6] = Combine(xh0, yh1, zh1, dh0);\n            hca[7] = Combine(xh1, yh1, zh1, dh0);\n            hca[8] = Combine(xh0, yh0, zh0, dh1);\n            hca[9] = Combine(xh1, yh0, zh0, dh1);\n            hca[10] = Combine(xh0, yh1, zh0, dh1);\n            hca[11] = Combine(xh1, yh1, zh0, dh1);\n            hca[12] = Combine(xh0, yh0, zh1, dh1);\n            hca[13] = Combine(xh1, yh0, zh1, dh1);\n            hca[14] = Combine(xh0, yh1, zh1, dh1);\n            hca[15] = Combine(xh1, yh1, zh1, dh1);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/V3fCoder.cs",
    "content": "// The decode table would grow to large for 64bit codes, and should not\n// be used in this case. However it is very likely that the 64 bit version\n// does not work as of yet.\n// The actual savings by using a table are small enough, that it is\n// normally not worth the associated initialization cost.\n// #define V3FCODER_DECODE_TABLE\n// The following option is mostly for debugging:\n// #define V3FCODER_NO_WARP\nusing System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// A V3fCoder can be used to encode direction vectors in unsigned\n    /// integers.\n    /// </summary>\n    public class V3fCoder\n    {\n        // private uint m_raster;\n        private readonly uint m_r2Sub1;\n        private readonly double m_doubleRaster;\n        private readonly double m_invDoubleRaster;\n        private readonly uint m_edgeBasis;\n        private readonly uint m_cornerBasis;\n        #if V3FCODER_DECODE_TABLE\n        private double[] m_unWarpTable;\n        #endif\n        private readonly double m_dRp05;\n\n        #region Constructor\n\n        /// <summary>\n        /// Create a V3fCoder with supplied raster. The raster defines the\n        /// number of discretized directons along an octant of one of the\n        /// major circumferences of the sphere. Thus on each of the 3 major\n        /// circumferences of the sphere 8 * raster evenly spaced different\n        /// directions are encoded.\n        /// </summary>\n        /// <param name=\"raster\"></param>\n        public V3fCoder(uint raster)\n        {\n            // m_raster = raster;\n            m_r2Sub1 = 2 * raster - 1;\n            m_doubleRaster = (double)raster;\n            m_invDoubleRaster = 1.0/m_doubleRaster;\n            m_edgeBasis = 6 * m_r2Sub1 * m_r2Sub1;\n            m_cornerBasis = m_edgeBasis + 12  * m_r2Sub1;\n            \n            m_dRp05 = m_doubleRaster + 0.5;\n\n\n            #if V3FCODER_DECODE_TABLE\n            // build a table for slightly faster decoding\n            m_unWarpTable = new double[m_r2Sub1];\n            \n            for (int i = 0; i < m_r2Sub1; i++)\n            {\n                double u = (i+1) * m_invDoubleRaster - 1.0;\n                #if (!V3FCODER_NO_WARP)\n                u = SphericalOfBox(u);\n                #endif\n                m_unWarpTable[i] = u;\n            }\n            #endif\n        }\n\n        #endregion\n\n        #region Static Creator\n\n        public static V3fCoder ForBits(int bits)\n        {\n            if (bits < 5) return null;\n            if (bits > 32) bits = 32;\n            return s_coderForBits[bits];\n        }\n\n        #endregion\n\n        #region Constants\n\n        static readonly uint[] s_rasterForBitsTable =\n        {\n            // bits       raster,    used bits\n            /*    0 */         0,\n            /*    1 */         0,\n            /*    2 */         0,\n            /*    3 */         0,\n            /*    4 */         0,\n            /*    5 */         1, //  4.7004397181\n            /*    6 */         1, //  4.7004397181\n            /*    7 */         2, //  6.6147098441\n            /*    8 */         3, //  7.7681843248\n            /*    9 */         4, //  8.5924570373\n            /*   10 */         6, //  9.7582232147\n            /*   11 */         9, // 10.9262959948\n            /*   12 */        13, // 11.9865531498\n            /*   13 */        18, // 12.9251835194\n            /*   14 */        26, // 13.9860197731\n            /*   15 */        36, // 14.9249052665\n            /*   16 */        52, // 15.9858863980\n            /*   17 */        73, // 16.9646341787\n            /*   18 */       104, // 17.9858530524\n            /*   19 */       147, // 18.9843127540\n            /*   20 */       209, // 19.9996835172\n            /*   21 */       295, // 20.9941061707\n            /*   22 */       418, // 21.9996814530\n            /*   23 */       591, // 22.9989914853\n            /*   24 */       836, // 23.9996809369\n            /*   25 */      1182, // 24.9989912271\n            /*   26 */      1672, // 25.9996808079\n            /*   27 */      2364, // 26.9989911626\n            /*   28 */      3344, // 27.9996807756\n            /*   29 */      4729, // 28.9996013590\n            /*   30 */      6688, // 29.9996807676\n            /*   31 */      9459, // 30.9999064129\n            /*   32 */     13377, // 31.9998964715\n            \n            /*\n                For the following codes to work, the algorithm\n                has to be changed to 64-bit ints.\n            */\n            \n            /*   33 */     18918, // 32.9999064119\n            /*   34 */     26754, // 33.9998964710\n            /*   35 */     37837, // 34.9999826710\n            /*   36 */     53509, // 35.9999503948\n            /*   37 */     75674, // 36.9999826710\n            /*   38 */    107019, // 37.9999773564\n            /*   39 */    151348, // 38.9999826710\n            /*   40 */    214039, // 39.9999908371\n            /*   41 */    302697, // 40.9999922033\n            /*   42 */    428079, // 41.9999975774\n            /*   43 */    605395, // 42.9999969694\n            /*   44 */    856158, // 43.9999975774\n            /*   45 */   1210791, // 44.9999993524\n            /*   46 */   1712317, // 45.9999992625\n            /*   47 */   2421582, // 46.9999993524\n            /*   48 */   3424634, // 47.9999992625\n            /*   49 */   4843165, // 48.9999999482\n            /*   50 */   6849269, // 49.9999996837\n            /*   51 */   9686330, // 50.9999999482\n            /*   52 */  13698539, // 51.9999998944\n            /*   53 */  19372660, // 52.9999999482\n            /*   54 */  27397079, // 53.9999999997\n            /*   55 */  38745320, // 54.9999999482\n            /*   56 */  54794158, // 55.9999999997\n            /*   57 */  77490641, // 56.9999999854\n            /*   58 */ 109588316, // 57.9999999997\n            /*   59 */ 154981282, // 58.9999999854\n            /*   60 */ 219176632, // 59.9999999997\n            /*   61 */ 309962565, // 60.9999999948\n            /*   62 */ 438353264, // 61.9999999997\n            /*   63 */ 619925131, // 62.9999999994\n            /*   64 */ 876706528, // 63.9999999997\n        };\n\n        const double c_piOver4 = Constant.Pi * 0.25;\n        const double c_4OverPi = 4.0 / Constant.Pi;\n\n        private static readonly V3fCoder[] s_coderForBits =\n            new V3fCoder[33];\n\n        static V3fCoder()\n        {\n            for (int bits = 5; bits < 33; bits++)\n                s_coderForBits[bits] = new V3fCoder(RasterForBits(bits));\n        }\n\n        #endregion\n\n        #region Encoding Helpers\n\n        public static double SphericalOfBox(double x)\n        { return System.Math.Tan(x * c_piOver4); }\n        public static double BoxOfSpherical(double x)\n        { return System.Math.Atan(x) * c_4OverPi; }\n\n        #if (!V3FCODER_DECODE_TABLE)\n        #if (V3FCODER_NO_WARP)\n        private double Unwarp(uint u)\n        { return (u+1) * m_invDoubleRaster - 1.0; }\n        #else\n        private double Unwarp(uint u)\n        { return System.Math.Tan(((u + 1) * m_invDoubleRaster - 1.0) * c_piOver4); }\n        #endif\n        #else\n        private double Unwarp(uint u)  { return m_unWarpTable[u]; }\n        #endif\n\n        /*\n            The directions are coded based on the faces, edges, and corners\n            of a cube of size 2, centered at the origin. Within an uint the\n            first codes are for the faces, then the edges and finally the\n            corners. The coding within these three groups is performed\n            according to the following table:\n        \n                faces:\n                 0: -1  u  v\n                 1:  v -1  u\n                 2:  u  v -1\n                 3: +1  u  v\n                 4:  v +1  u\n                 5:  u  v +1\n\n                 edges:\n                 0:  u -1 -1    faces 1,-,u  2,u,-      corners 0, 1\n                 1:  u +1 -1    faces 4,-,u  2,u,+      corners 2, 3\n                 2:  u -1 +1    faces 1,+,u  5,u,-      corners 4, 5\n                 3:  u +1 +1    faces 4,+,u  5,u,+      corners 6, 7\n                 4: -1  u -1    faces 2,-,u  0,u,-      corners 0, 2\n                 5: +1  u -1    faces 2,+,u  3,u,-      corners 1, 3\n                 6: -1  u +1    faces 5,-,u  0,u,+      corners 4, 6\n                 7: +1  u +1    faces 5,+,u  3,u,+      corners 5, 7\n                 8: -1 -1  u    faces 0,-,u  1,u,-      corners 0, 4\n                 9: +1 -1  u    faces 3,-,u  1,u,+      corners 1, 5\n                10: -1 +1  u    faces 0,+,u  4,u,-      corners 2, 6\n                11: +1 +1  u    faces 3,+,u  4,u,+      corners 3, 7\n                \n                corners:\n                 0: -1 -1 -1    edges  0,  4,  8    faces 0, 1, 2\n                 1: +1 -1 -1    edges  0,  5,  9\n                 2: -1 +1 -1    edges  1,  4, 10\n                 3: +1 +1 -1    edges  1,  5, 11\n                 4: -1 -1 +1    edges  2,  6,  8\n                 5: +1 -1 +1    edges  2,  7,  9\n                 6: -1 +1 +1    edges  3,  6, 10\n                 7: +1 +1 +1    edges  3,  7, 11\n            \n        */\n\n        uint EncodeCornerIndex(uint corner)\n        {\n            return m_cornerBasis + corner;\n        }\n\n        static readonly uint[] s_edgeNegCorner = new uint[]\n                    { 0, 2, 4, 6, 0, 1, 4, 5, 0, 1, 2, 3 };\n        static readonly uint[] s_edgePosCorner = new uint[]\n                    { 1, 3, 5, 7, 2, 3, 6, 7, 4, 5, 6, 7 };\n\n        uint EncodeEdgeIndex(uint edge, int iu)\n        {\n            if (iu < 0) return m_cornerBasis + s_edgeNegCorner[edge];\n            if (iu >= m_r2Sub1) return m_cornerBasis + s_edgePosCorner[edge];\n            return m_edgeBasis + (uint)(edge  * m_r2Sub1 + iu);\n        }\n\n        uint RawEncodeEdgeIndex(uint edge, int iu)\n        {\n            return m_edgeBasis + (uint)(edge * m_r2Sub1 + iu);\n        } \n\n        static readonly uint[] s_faceNegUedge = new uint[] { 8, 0, 4, 9, 1, 6 };\n        static readonly uint[] s_facePosUedge = new uint[] { 10, 2, 5, 11, 3, 7 };\n        static readonly uint[] s_faceNegVedge = new uint[] { 4, 8, 0, 5, 10, 2 };\n        static readonly uint[] s_facePosVedge = new uint[] { 6, 9, 1, 7, 11, 3 };\n\n        uint EncodeFaceIndex(uint face, int iu, int iv)\n        {\n            if (iu < 0) return EncodeEdgeIndex(s_faceNegUedge[face], iv);\n            if (iu >= m_r2Sub1) return EncodeEdgeIndex(s_facePosUedge[face], iv);\n            if (iv < 0) return EncodeEdgeIndex(s_faceNegVedge[face], iu);\n            if (iv >= m_r2Sub1) return EncodeEdgeIndex(s_facePosVedge[face], iu);\n            return (uint)((face * m_r2Sub1 + iv ) * m_r2Sub1 + iu);\n        }\n\n        uint RawEncodeFaceIndex(uint face, int iu, int iv)\n        {\n            return (uint)((face * m_r2Sub1 + iv) * m_r2Sub1 + iu);\n        }\n\n        #endregion\n\n        #region Encoding\n\n        /// <summary>\n        /// Encode the given direction in an unsigned integer. The direction\n        /// does not need to be normalized!\n        /// </summary>\n        /// <param name=\"dir\">The direction to encode.</param>\n        /// <returns></returns>\n        public uint Encode(V3f dir)\n        {\n            int mAxis;\n            double aX = System.Math.Abs(dir.X);\n            double aY = System.Math.Abs(dir.Y);\n            double aZ = System.Math.Abs(dir.Z);\n            double u, v;\n            if (aX > aY)\n            {\n                if (aX > aZ)\n                {\n                    double invSize = 1.0/aX; mAxis = 0;\n                    u = dir.Y * invSize; v = dir.Z * invSize;\n                }\n                else\n                {\n                    double invSize = 1.0/aZ; mAxis = 2;\n                    u = dir.X * invSize; v = dir.Y * invSize;\n                }\n            }\n            else\n            {\n                if (aY > aZ)\n                {\n                    double invSize = 1.0/aY; mAxis = 1;\n                    u = dir.Z * invSize; v = dir.X * invSize;\n                }\n                else\n                {\n                    double invSize = 1.0/aZ; mAxis = 2;\n                    u = dir.X * invSize; v = dir.Y * invSize;\n                }\n            }\n            #if (!V3FCODER_NO_WARP)\n            u = BoxOfSpherical(u);\n            v = BoxOfSpherical(v);\n            #endif\n            uint face = (uint)(mAxis + (dir[mAxis] < 0 ? 0 : 3));\n            return EncodeFaceIndex(face,\n                                   (int)(u * m_doubleRaster + m_dRp05) - 1,\n                                   (int)(v * m_doubleRaster + m_dRp05) - 1);\n        }\n\n        #endregion\n\n        #region Decoding Helpers\n\n        static readonly V3f[] s_vecToCornerTableNonNormalized =\n        {\n            new V3f( -1.0f, -1.0f, -1.0f ),\n            new V3f( +1.0f, -1.0f, -1.0f ),\n            new V3f( -1.0f, +1.0f, -1.0f ),\n            new V3f( +1.0f, +1.0f, -1.0f ),\n            new V3f( -1.0f, -1.0f, +1.0f ),\n            new V3f( +1.0f, -1.0f, +1.0f ),\n            new V3f( -1.0f, +1.0f, +1.0f ),\n            new V3f( +1.0f, +1.0f, +1.0f )\n        };\n\n        const float c_oneOverSqrt3 = 0.57735026918962584f;\n        static readonly V3f[] s_vecToCornerTable =\n        {\n            new V3f( -c_oneOverSqrt3, -c_oneOverSqrt3, -c_oneOverSqrt3 ),\n            new V3f( +c_oneOverSqrt3, -c_oneOverSqrt3, -c_oneOverSqrt3 ),\n            new V3f( -c_oneOverSqrt3, +c_oneOverSqrt3, -c_oneOverSqrt3 ),\n            new V3f( +c_oneOverSqrt3, +c_oneOverSqrt3, -c_oneOverSqrt3 ),\n            new V3f( -c_oneOverSqrt3, -c_oneOverSqrt3, +c_oneOverSqrt3 ),\n            new V3f( +c_oneOverSqrt3, -c_oneOverSqrt3, +c_oneOverSqrt3 ),\n            new V3f( -c_oneOverSqrt3, +c_oneOverSqrt3, +c_oneOverSqrt3 ),\n            new V3f( +c_oneOverSqrt3, +c_oneOverSqrt3, +c_oneOverSqrt3 )\n        };\n\n        static readonly double[] s_uSignOfEdge = { -1, +1, -1, +1 };\n        static readonly double[] s_vSignOfEdge = { -1, -1, +1, +1 };\n        static readonly int[] s_uAxis = { 1, 0, 0 };\n        static readonly int[] s_vAxis = { 2, 2, 1 };\n\n        #endregion\n\n        #region Decoding\n\n        /// <summary>\n        /// Decode the unsigned integer direction code. \n        /// </summary>\n        /// <param name=\"code\"></param>\n        /// <returns>A normalized direction.</returns>\n        public V3f Decode(uint code)\n        {\n            if (code < m_edgeBasis) // face number is code\n            {\n                double u = Unwarp(code % m_r2Sub1);\n                code /= m_r2Sub1;\n                double v = Unwarp(code % m_r2Sub1);\n                code /= m_r2Sub1;\n                double scale = 1.0 / System.Math.Sqrt(1.0 + u * u + v * v);\n                switch (code)\n                {\n                    case 0: return new V3f(-scale, u * scale, v * scale);\n                    case 1: return new V3f(v * scale, -scale, u * scale);\n                    case 2: return new V3f(u * scale, v * scale, -scale);\n                    case 3: return new V3f(+scale, u * scale, v * scale);\n                    case 4: return new V3f(v * scale, +scale, u * scale);\n                    case 5: return new V3f(u * scale, v * scale, +scale);\n                    default: throw new ArgumentException();\n                }\n            }\n            else if (code < m_cornerBasis)\n            {\n                code -= m_edgeBasis;\n                double u = Unwarp(code % m_r2Sub1);\n                code /= m_r2Sub1;      // edge number in code\n                double scale = 1.0 / System.Math.Sqrt(2.0 + u * u);\n                uint edge = code & 3; code >>= 2;\n                V3f dir = new V3f(0, 0, 0); // init to make compiler happy\n                dir[(int)code] = (float)(u * scale);\n                dir[s_uAxis[code]] = (float)(s_uSignOfEdge[edge] * scale);\n                dir[s_vAxis[code]] = (float)(s_vSignOfEdge[edge] * scale);\n                return dir;\n#if NEVERMORE\n                float edgeOne = (code & 1) == 0 ? -scale : scale;\n                float edgeTwo = (code & 2) == 0 ? -scale : scale;\n                switch (code >> 2)\n                {\n                    case 0: return new V3f((float)(u * scale), edgeOne, edgeTwo);\n                    case 1: return new V3f(edgeOne, (float)(u * scale), edgeTwo);\n                    case 2: return new V3f(edgeOne, edgeTwo, (float)(u * scale));\n                    default: throw new ArgumentException();\n                }\n#endif\n            }\n            else\n                return s_vecToCornerTable[code - m_cornerBasis];\n        }\n\n        public V3f DecodeOnCube(uint code, bool warped)\n        {\n            if (code < m_edgeBasis) // face number is code\n            {\n\n                double u = warped\n                    ? Unwarp(code % m_r2Sub1)\n                    : (code % m_r2Sub1 + 1) * m_invDoubleRaster - 1.0;\n\n                code /= m_r2Sub1;\n                double v = warped\n                    ? Unwarp(code % m_r2Sub1)\n                    : (code % m_r2Sub1 + 1) * m_invDoubleRaster - 1.0;\n                code /= m_r2Sub1;\n\n                switch (code)\n                {\n                    case 0: return new V3f(-1, u, v);\n                    case 1: return new V3f(v, -1, u);\n                    case 2: return new V3f(u, v, -1);\n                    case 3: return new V3f(+1, u, v);\n                    case 4: return new V3f(v, +1, u);\n                    case 5: return new V3f(u, v, +1);\n                    default: throw new ArgumentException();\n                }\n            }\n            else if (code < m_cornerBasis)\n            {\n                code -= m_edgeBasis;\n                double u = warped\n                    ? Unwarp(code % m_r2Sub1)\n                    : (code % m_r2Sub1+1) * m_invDoubleRaster - 1.0;\n                code /= m_r2Sub1;      // edge number in code\n                uint edge = code & 3; code >>= 2;\n                V3f dir = new V3f(0, 0, 0); // init to make compiler happy\n                dir[(int)code] = (float)u;\n                dir[s_uAxis[code]] = (float)(s_uSignOfEdge[edge]);\n                dir[s_vAxis[code]] = (float)(s_vSignOfEdge[edge]);\n                return dir;\n#if NEVERMORE\n                float edgeOne = (code & 1) == 0 ? -1.0f : 1.0f;\n                float edgeTwo = (code & 2) == 0 ? -1.0f : 1.0f;\n                switch (code >> 2)\n                {\n                    case 0: return new V3f((float)u, edgeOne, edgeTwo);\n                    case 1: return new V3f(edgeOne, (float)u, edgeTwo);\n                    case 2: return new V3f(edgeOne, edgeTwo, (float)u);\n                    default: throw new ArgumentException();\n                }\n#endif\n            }\n            else\n                return s_vecToCornerTableNonNormalized[code - m_cornerBasis];\n        }\n\n        #endregion\n\n        #region Neighbours Helpers\n\n        static readonly uint[] s_edgeFace0\n                = new uint[] { 1, 4, 1, 4, 2, 2, 5, 5, 0, 3, 0, 3 };\n        static readonly int[] s_edgeFace0u\n                = new int[] { 0, 0, 1, 1, 0, 1, 0, 1, 0 ,0, 1, 1 };\n        static readonly uint[] s_edgeFace1\n                = new uint[] { 2, 2, 5, 5, 0, 3, 0, 3, 1, 1, 4, 4 };\n        static readonly int[] s_edgeFace1v\n                = new int[] { 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1 };\n\n        #endregion\n\n        #region Neigbours\n\n        /// <summary>\n        /// Fills the array neighbourCodes with the codes of all neigbouring\n        /// cells of the code discretization.\n        /// </summary>\n        /// <param name=\"code\">The code for which to calculate all\n        /// neighbours.</param>\n        /// <param name=\"neighbourCodes\">The array that is filled with\n        /// the neighbourcodes</param>\n        /// <returns>The number of neigbouring cells (maximal 8).</returns>\n        public uint NeighbourCodes(uint code, uint[] neighbourCodes)\n        {\n            if (code < m_edgeBasis) // face number is code\n            {\n                int iu = (int)(code % m_r2Sub1);\n                code /= m_r2Sub1;\n                int iv = (int)(code % m_r2Sub1);\n                code /= m_r2Sub1;\n\n                if (iu > 0 && iu < m_r2Sub1 - 1 && iv > 0 && iv < m_r2Sub1 - 1)\n                {\n                    neighbourCodes[0] = RawEncodeFaceIndex(code, iu - 1, iv - 1);\n                    neighbourCodes[1] = RawEncodeFaceIndex(code, iu - 1, iv);\n                    neighbourCodes[2] = RawEncodeFaceIndex(code, iu - 1, iv + 1);\n                    neighbourCodes[3] = RawEncodeFaceIndex(code, iu, iv - 1);\n                    neighbourCodes[4] = RawEncodeFaceIndex(code, iu, iv + 1);\n                    neighbourCodes[5] = RawEncodeFaceIndex(code, iu + 1, iv - 1);\n                    neighbourCodes[6] = RawEncodeFaceIndex(code, iu + 1, iv);\n                    neighbourCodes[7] = RawEncodeFaceIndex(code, iu + 1, iv + 1);\n                }\n                else\n                {\n                    neighbourCodes[0] = EncodeFaceIndex(code, iu - 1, iv - 1);\n                    neighbourCodes[1] = EncodeFaceIndex(code, iu - 1, iv);\n                    neighbourCodes[2] = EncodeFaceIndex(code, iu - 1, iv + 1);\n                    neighbourCodes[3] = EncodeFaceIndex(code, iu, iv - 1);\n                    neighbourCodes[4] = EncodeFaceIndex(code, iu, iv + 1);\n                    neighbourCodes[5] = EncodeFaceIndex(code, iu + 1, iv - 1);\n                    neighbourCodes[6] = EncodeFaceIndex(code, iu + 1, iv);\n                    neighbourCodes[7] = EncodeFaceIndex(code, iu + 1, iv + 1);\n                }\n              \n                return 8;\n            }\n            if (code < m_cornerBasis)\n            {\n                int nc = 0;\n                code -= m_edgeBasis;\n                int iu = (int)(code % m_r2Sub1);\n                code /= m_r2Sub1;      // edge number in code\n                neighbourCodes[nc++] = EncodeEdgeIndex(code, iu - 1);\n                neighbourCodes[nc++] = EncodeEdgeIndex(code, iu + 1);\n\n                int m = ((int)m_r2Sub1 - 1);\n\n                for (int i = -1; i < 2; i++)\n                {\n                    neighbourCodes[nc++] = EncodeFaceIndex(\n                        s_edgeFace0[code], s_edgeFace0u[code] * m, iu + i);\n                    neighbourCodes[nc++] = EncodeFaceIndex(\n                        s_edgeFace1[code], iu + i, s_edgeFace1v[code] * m);\n                }\n                return 8;\n            }\n            else\n            {\n                code -= m_cornerBasis;\n                int m = (int)m_r2Sub1 - 1;\n                switch (code)\n                {\n                    case 0:\n                        neighbourCodes[0] = RawEncodeFaceIndex(0, 0, 0);\n                        neighbourCodes[1] = RawEncodeFaceIndex(1, 0, 0);\n                        neighbourCodes[2] = RawEncodeFaceIndex(2, 0, 0);\n                        neighbourCodes[3] = RawEncodeEdgeIndex(0, 0);\n                        neighbourCodes[4] = RawEncodeEdgeIndex(4, 0);\n                        neighbourCodes[5] = RawEncodeEdgeIndex(8, 0);\n                        break;\n                    case 1:\n                        neighbourCodes[0] = RawEncodeEdgeIndex(0, m);\n                        neighbourCodes[1] = RawEncodeFaceIndex(1, 0, m);\n                        neighbourCodes[2] = RawEncodeFaceIndex(2, m, 0);\n                        neighbourCodes[3] = RawEncodeFaceIndex(3, 0, 0);\n                        neighbourCodes[4] = RawEncodeEdgeIndex(5, 0);\n                        neighbourCodes[5] = RawEncodeEdgeIndex(9, 0);\n                        break;\n                    case 2:\n                        neighbourCodes[0] = RawEncodeFaceIndex(0, m, 0);\n                        neighbourCodes[1] = RawEncodeEdgeIndex(4, m);\n                        neighbourCodes[2] = RawEncodeFaceIndex(2, 0, m);\n                        neighbourCodes[3] = RawEncodeEdgeIndex(1, 0);\n                        neighbourCodes[4] = RawEncodeFaceIndex(4, 0, 0);\n                        neighbourCodes[5] = RawEncodeEdgeIndex(10, 0);\n                        break;\n                    case 3:\n                        neighbourCodes[0] = RawEncodeEdgeIndex(1, m);\n                        neighbourCodes[1] = RawEncodeEdgeIndex(5, m);\n                        neighbourCodes[2] = RawEncodeFaceIndex(2, m, m);\n                        neighbourCodes[3] = RawEncodeFaceIndex(3, m, 0);\n                        neighbourCodes[4] = RawEncodeFaceIndex(4, 0, m);\n                        neighbourCodes[5] = RawEncodeEdgeIndex(11, 0);\n                        break;\n                    case 4:\n                        neighbourCodes[0] = RawEncodeFaceIndex(0, 0, m);\n                        neighbourCodes[1] = RawEncodeFaceIndex(1, m, 0);\n                        neighbourCodes[2] = RawEncodeEdgeIndex(8, m);\n                        neighbourCodes[3] = RawEncodeEdgeIndex(2, 0);\n                        neighbourCodes[4] = RawEncodeEdgeIndex(6, 0);\n                        neighbourCodes[5] = RawEncodeFaceIndex(5, 0, 0);\n                        break;\n                    case 5:\n                        neighbourCodes[0] = RawEncodeEdgeIndex(2, m);\n                        neighbourCodes[1] = RawEncodeFaceIndex(1, m, m);\n                        neighbourCodes[2] = RawEncodeEdgeIndex(9, m);\n                        neighbourCodes[3] = RawEncodeFaceIndex(3, 0, m);\n                        neighbourCodes[4] = RawEncodeEdgeIndex(7, 0);\n                        neighbourCodes[5] = RawEncodeFaceIndex(5, m, 0);\n                        break;\n                    case 6:\n                        neighbourCodes[0] = RawEncodeFaceIndex(0, m, m);\n                        neighbourCodes[1] = RawEncodeEdgeIndex(6, m);\n                        neighbourCodes[2] = RawEncodeEdgeIndex(10, m);\n                        neighbourCodes[3] = RawEncodeEdgeIndex(3, 0);\n                        neighbourCodes[4] = RawEncodeFaceIndex(4, m, 0);\n                        neighbourCodes[5] = RawEncodeFaceIndex(5, 0, m);\n                        break;\n                    case 7:\n                        neighbourCodes[0] = RawEncodeEdgeIndex(3, m);\n                        neighbourCodes[1] = RawEncodeEdgeIndex(7, m);\n                        neighbourCodes[2] = RawEncodeEdgeIndex(11, m);\n                        neighbourCodes[3] = RawEncodeFaceIndex(3, m, m);\n                        neighbourCodes[4] = RawEncodeFaceIndex(4, m, m);\n                        neighbourCodes[5] = RawEncodeFaceIndex(5, m, m);\n                        break;\n                }\n                return 6;\n            }\n        }\n\n        #endregion\n\n        #region Info Methods\n\n        /// <summary>\n        /// Calculate the maximal raster for a given number of bits.\n        /// Currently maximal 32 bits are supported.\n        /// </summary>\n        /// <param name=\"bits\">The number of bits.</param>\n        /// <returns>The maximal possible raster value.</returns>\n        public static uint RasterForBits(int bits)\n        {\n            if (bits < 5) return 0;\n            if (bits > 32) bits = 32;\n            return s_rasterForBitsTable[bits];\n        }\n\n        /// <summary>\n        /// Calculate the number of different codes that are available.\n        /// </summary>\n        /// <returns></returns>\n        public uint Count\n        {\n            get { return m_cornerBasis + 8; }\n        }\n        \n        /// <summary>\n        /// Calculate all directions that are exactly encoded.\n        /// </summary>\n        /// <returns>An array of directions.</returns>\n        public V3f[] GenerateTable()\n        {\n            uint dirCount = Count;\n            V3f[] directionTable = new V3f[dirCount];\n            for (uint dc = 0; dc < dirCount; dc++)\n            {\n                directionTable[dc] = Decode(dc);\n            }\n            return directionTable;\n        }\n\n        #endregion\n\n        #region Code Generator\n\n        /// <summary>\n        /// Code generation.\n        /// </summary>\n        public void WriteCode(uint code)\n        {\n            if (code < m_edgeBasis) // face number is code\n            {\n                uint iu = code % m_r2Sub1;\n                code /= m_r2Sub1;\n                uint iv = code % m_r2Sub1;\n                code /= m_r2Sub1;\n\n                string u = iu == 0 ? \"0\" : (iu == m_r2Sub1 - 1 ? \"m\" : \"u\");\n                string v = iv == 0 ? \"0\" : (iv == m_r2Sub1 - 1 ? \"m\" : \"v\");\n\n                Console.WriteLine(\"EncodeFaceIndex({0}, {1}, {2});\", code, u, v);\n            }\n            else if (code < m_cornerBasis)\n            {\n                code -= m_edgeBasis;\n                uint iu = code % m_r2Sub1;\n                code /= m_r2Sub1;      // edge number in code\n                string u = iu == 0 ? \"0\" : (iu == m_r2Sub1 - 1 ? \"m\" : \"u\");\n                Console.WriteLine(\"EncodeEdgeIndex({0}, {1});\", code, u);\n            }\n            else\n                Console.WriteLine(\"EncodeCornerIndex({0});\", code - m_cornerBasis);\n        }\n\n        /// <summary>\n        /// Code generation.\n        /// </summary>\n        public void WriteCornerNeighbours(uint corner)\n        {\n            V3f v = s_vecToCornerTableNonNormalized[corner];\n\n            string f = \"    neighbourCodes[{0}] = \";\n            float s = (float)m_invDoubleRaster;\n            Console.Write(f, 0); WriteCode(Encode(v + s * new V3f(-1, 0, 0)));\n            Console.Write(f, 1); WriteCode(Encode(v + s * new V3f(0, -1, 0)));\n            Console.Write(f, 2); WriteCode(Encode(v + s * new V3f(0, 0, -1)));\n            Console.Write(f, 3); WriteCode(Encode(v + s * new V3f(1, 0, 0)));\n            Console.Write(f, 4); WriteCode(Encode(v + s * new V3f(0, 1, 0)));\n            Console.Write(f, 5); WriteCode(Encode(v + s * new V3f(0, 0, 1)));\n        }\n\n        /// <summary>\n        /// Code generation.\n        /// </summary>\n        public void WriteAllCornerNeighbours()\n        {\n            for (uint c = 0; c < 8; c++)\n            {\n                Console.WriteLine(\"case {0}:\", c);\n                WriteCornerNeighbours(c);\n                Console.WriteLine(\"    break;\");\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/VectorArrayExtensions.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    #region ArrayVectorExtensions\n\n    public static class ArrayVectorExtensions // this *must not* be named 'ArrayExtensions'\n    {\n        public static float Lerp(this float[] array, WeightedIndex[] wia)\n        {\n            var result = default(float);\n            foreach (var wi in wia) result += (float)wi.Weight * array[wi.Index];\n            return result;\n        }\n        public static double Lerp(this double[] array, WeightedIndex[] wia)\n        {\n            var result = default(double);\n            foreach (var wi in wia) result += wi.Weight * array[wi.Index];\n            return result;\n        }\n        public static C3b Lerp(this C3b[] array, WeightedIndex[] wia)\n        {\n            var result = default(V3d);\n            foreach (var wi in wia) result += wi.Weight * (V3d)array[wi.Index];\n            return (C3b)result;\n        }\n        public static C3us Lerp(this C3us[] array, WeightedIndex[] wia)\n        {\n            var result = default(V3d);\n            foreach (var wi in wia) result += wi.Weight * (V3d)array[wi.Index];\n            return (C3us)result;\n        }\n        public static C3ui Lerp(this C3ui[] array, WeightedIndex[] wia)\n        {\n            var result = default(V3d);\n            foreach (var wi in wia) result += wi.Weight * (V3d)array[wi.Index];\n            return (C3ui)result;\n        }\n        public static C3f Lerp(this C3f[] array, WeightedIndex[] wia)\n        {\n            var result = default(V3d);\n            foreach (var wi in wia) result += wi.Weight * (V3d)array[wi.Index];\n            return (C3f)result;\n        }\n        public static C3d Lerp(this C3d[] array, WeightedIndex[] wia)\n        {\n            var result = default(V3d);\n            foreach (var wi in wia) result += wi.Weight * (V3d)array[wi.Index];\n            return (C3d)result;\n        }\n        public static C4b Lerp(this C4b[] array, WeightedIndex[] wia)\n        {\n            var result = default(V4d);\n            foreach (var wi in wia) result += wi.Weight * (V4d)array[wi.Index];\n            return (C4b)result;\n        }\n        public static C4us Lerp(this C4us[] array, WeightedIndex[] wia)\n        {\n            var result = default(V4d);\n            foreach (var wi in wia) result += wi.Weight * (V4d)array[wi.Index];\n            return (C4us)result;\n        }\n        public static C4ui Lerp(this C4ui[] array, WeightedIndex[] wia)\n        {\n            var result = default(V4d);\n            foreach (var wi in wia) result += wi.Weight * (V4d)array[wi.Index];\n            return (C4ui)result;\n        }\n        public static C4f Lerp(this C4f[] array, WeightedIndex[] wia)\n        {\n            var result = default(V4d);\n            foreach (var wi in wia) result += wi.Weight * (V4d)array[wi.Index];\n            return (C4f)result;\n        }\n        public static C4d Lerp(this C4d[] array, WeightedIndex[] wia)\n        {\n            var result = default(V4d);\n            foreach (var wi in wia) result += wi.Weight * (V4d)array[wi.Index];\n            return (C4d)result;\n        }\n        public static V2f Lerp(this V2f[] array, WeightedIndex[] wia)\n        {\n            var result = default(V2d);\n            foreach (var wi in wia) result += wi.Weight * (V2d)array[wi.Index];\n            return (V2f)result;\n        }\n        public static V2d Lerp(this V2d[] array, WeightedIndex[] wia)\n        {\n            var result = default(V2d);\n            foreach (var wi in wia) result += wi.Weight * array[wi.Index];\n            return result;\n        }\n        public static V3f Lerp(this V3f[] array, WeightedIndex[] wia)\n        {\n            var result = default(V3d);\n            foreach (var wi in wia) result += wi.Weight * (V3d)array[wi.Index];\n            return (V3f)result;\n        }\n        public static V3d Lerp(this V3d[] array, WeightedIndex[] wia)\n        {\n            var result = default(V3d);\n            foreach (var wi in wia) result += wi.Weight * array[wi.Index];\n            return result;\n        }\n        public static V4f Lerp(this V4f[] array, WeightedIndex[] wia)\n        {\n            var result = default(V4d);\n            foreach (var wi in wia) result += wi.Weight * (V4d)array[wi.Index];\n            return (V4f)result;\n        }\n        public static V4d Lerp(this V4d[] array, WeightedIndex[] wia)\n        {\n            var result = default(V4d);\n            foreach (var wi in wia) result += wi.Weight * array[wi.Index];\n            return result;\n        }\n\n        static readonly Dictionary<Type, Func<Array, int[], Dictionary<int, Line1iPoint>, Array>>\n            s_backwardIndexedLerpMap\n            = new Dictionary<Type, Func<Array, int[], Dictionary<int, Line1iPoint>, Array>>\n            {\n                { typeof(float[]), (a, bm, im) => (Array)BackwardIndexedCopy((float[])a, bm, im, (t, u, v) => Fun.Lerp((float) t, u, v)) },\n                { typeof(double[]), (a, bm, im) => (Array)BackwardIndexedCopy((double[])a, bm, im, Fun.Lerp) },\n                { typeof(C3b[]), (a, bm, im) => (Array)BackwardIndexedCopy((C3b[])a, bm, im, Fun.Lerp) },\n                { typeof(C3us[]), (a, bm, im) => (Array)BackwardIndexedCopy((C3us[])a, bm, im, Fun.Lerp) },\n                { typeof(C3ui[]), (a, bm, im) => (Array)BackwardIndexedCopy((C3ui[])a, bm, im, Fun.Lerp) },\n                { typeof(C3f[]), (a, bm, im) => (Array)BackwardIndexedCopy((C3f[])a, bm, im, (t, u, v) => Fun.Lerp((float) t, u, v)) },\n                { typeof(C3d[]), (a, bm, im) => (Array)BackwardIndexedCopy((C3d[])a, bm, im, Fun.Lerp) },\n                { typeof(C4b[]), (a, bm, im) => (Array)BackwardIndexedCopy((C4b[])a, bm, im, Fun.Lerp) },\n                { typeof(C4us[]), (a, bm, im) => (Array)BackwardIndexedCopy((C4us[])a, bm, im, Fun.Lerp) },\n                { typeof(C4ui[]), (a, bm, im) => (Array)BackwardIndexedCopy((C4ui[])a, bm, im, Fun.Lerp) },\n                { typeof(C4f[]), (a, bm, im) => (Array)BackwardIndexedCopy((C4f[])a, bm, im, (t, u, v) => Fun.Lerp((float) t, u, v)) },\n                { typeof(C4d[]), (a, bm, im) => (Array)BackwardIndexedCopy((C4d[])a, bm, im, Fun.Lerp) },\n                { typeof(V2f[]), (a, bm, im) => (Array)BackwardIndexedCopy((V2f[])a, bm, im, (t, u, v) => Fun.Lerp((float) t, u, v)) },\n                { typeof(V2d[]), (a, bm, im) => (Array)BackwardIndexedCopy((V2d[])a, bm, im, Fun.Lerp) },\n                { typeof(V3f[]), (a, bm, im) => (Array)BackwardIndexedCopy((V3f[])a, bm, im, (t, u, v) => Fun.Lerp((float) t, u, v)) },\n                { typeof(V3d[]), (a, bm, im) => (Array)BackwardIndexedCopy((V3d[])a, bm, im, Fun.Lerp) },\n                { typeof(V4f[]), (a, bm, im) => (Array)BackwardIndexedCopy((V4f[])a, bm, im, (t, u, v) => Fun.Lerp((float) t, u, v)) },\n                { typeof(V4d[]), (a, bm, im) => (Array)BackwardIndexedCopy((V4d[])a, bm, im, Fun.Lerp) },\n            };\n\n\n        public static Array BackwardIndexedLerpCopy(\n            this Array array,\n            int[] backwardMap,\n            Dictionary<int, Line1iPoint> interpolationMap)\n        {\n            var type = array.GetType();\n            return s_backwardIndexedLerpMap[type](\n                            array, backwardMap, interpolationMap);\n        }\n\n\n        static readonly Dictionary<Type, Func<Array, int[], Dictionary<int, Line1iPoint>, Array>>\n            s_backwardIndexedNormalMap\n            = new Dictionary<Type, Func<Array, int[], Dictionary<int, Line1iPoint>, Array>>\n            {\n                { typeof(V3f[]), (a, bm, im) =>\n                    (Array)BackwardIndexedCopy(\n                            (V3f[])a, bm, im, (t, v0, v1) => Fun.Lerp((float) t, v0, v1).Normalized) },\n                { typeof(V3d[]), (a, bm, im) =>\n                    (Array)BackwardIndexedCopy(\n                            (V3d[])a, bm, im, (t, v0, v1) => Fun.Lerp((float) t, v0, v1).Normalized) },\n            };\n\n        public static Array BackwardIndexedNormalCopy(\n            this Array array,\n            int[] backwardMap,\n            Dictionary<int, Line1iPoint> interpolationMap)\n        {\n            var type = array.GetType();\n            return s_backwardIndexedNormalMap[type](\n                            array, backwardMap, interpolationMap);\n        }\n\n        public static T[] BackwardIndexedCopy<T>(\n            this T[] array,\n            int[] backwardMap,\n            Dictionary<int, Line1iPoint> interpolationMap,\n            Func<double, T, T, T> interpolator)\n        {\n            int length = backwardMap.Length;\n            T[] result = new T[length];\n            for (int i = 0; i < length; i++)\n            {\n                int si = backwardMap[i];\n                if (si < 0)\n                {\n                    var sp = interpolationMap[i];\n                    result[i] = interpolator(sp.T,\n                        array[sp.Line.I0], array[sp.Line.I1]);\n                }\n                else\n                    result[i] = array[si];\n            }\n            return result;\n        }\n\n        public static void CombineTo<T>(\n                this T[] source, IEnumerable<WeightedIndex[]> weightedIndexArrays,\n                Func<T[], WeightedIndex[], T> combine,\n                T[] target, int offset, int length)\n        {\n            length += offset;\n            foreach (var wia in weightedIndexArrays)\n            {\n                target[offset++] = combine(source, wia);\n                if (offset == length) break;\n            }\n        }\n\n        private static readonly Dictionary<Type,\n            Action<Array, IEnumerable<WeightedIndex[]>, Array, int, int>>\n                s_lerpToOffsetMap =\n            new Dictionary<Type,\n                    Action<Array, IEnumerable<WeightedIndex[]>, Array, int, int>>\n            {\n                { typeof(float[]), (s, w, t, o, l) => CombineTo((float[])s, w, Lerp, (float[])t, o, l) },\n                { typeof(double[]), (s, w, t, o, l) => CombineTo((double[])s, w, Lerp, (double[])t, o, l) },\n                { typeof(C3b[]), (s, w, t, o, l) => CombineTo((C3b[])s, w, Lerp, (C3b[])t, o, l) },\n                { typeof(C3us[]), (s, w, t, o, l) => CombineTo((C3us[])s, w, Lerp, (C3us[])t, o, l) },\n                { typeof(C3ui[]), (s, w, t, o, l) => CombineTo((C3ui[])s, w, Lerp, (C3ui[])t, o, l) },\n                { typeof(C3f[]), (s, w, t, o, l) => CombineTo((C3f[])s, w, Lerp, (C3f[])t, o, l) },\n                { typeof(C3d[]), (s, w, t, o, l) => CombineTo((C3d[])s, w, Lerp, (C3d[])t, o, l) },\n                { typeof(C4b[]), (s, w, t, o, l) => CombineTo((C4b[])s, w, Lerp, (C4b[])t, o, l) },\n                { typeof(C4us[]), (s, w, t, o, l) => CombineTo((C4us[])s, w, Lerp, (C4us[])t, o, l) },\n                { typeof(C4ui[]), (s, w, t, o, l) => CombineTo((C4ui[])s, w, Lerp, (C4ui[])t, o, l) },\n                { typeof(C4f[]), (s, w, t, o, l) => CombineTo((C4f[])s, w, Lerp, (C4f[])t, o, l) },\n                { typeof(C4d[]), (s, w, t, o, l) => CombineTo((C4d[])s, w, Lerp, (C4d[])t, o, l) },\n                { typeof(V2f[]), (s, w, t, o, l) => CombineTo((V2f[])s, w, Lerp, (V2f[])t, o, l) },\n                { typeof(V2d[]), (s, w, t, o, l) => CombineTo((V2d[])s, w, Lerp, (V2d[])t, o, l) },\n                { typeof(V3f[]), (s, w, t, o, l) => CombineTo((V3f[])s, w, Lerp, (V3f[])t, o, l) },\n                { typeof(V3d[]), (s, w, t, o, l) => CombineTo((V3d[])s, w, Lerp, (V3d[])t, o, l) },\n                { typeof(V4f[]), (s, w, t, o, l) => CombineTo((V4f[])s, w, Lerp, (V4f[])t, o, l) },\n                { typeof(V4d[]), (s, w, t, o, l) => CombineTo((V4d[])s, w, Lerp, (V4d[])t, o, l) },\n            };\n\n        /// <summary>\n        /// Fills the target array starting at offset for length entries\n        /// with Lerp/weighted combinations of the source array.\n        /// </summary>\n        public static Array LerpTo(\n                this Array source,\n                IEnumerable<WeightedIndex[]> weightedIndexArrays,\n                Array target, int offset, int length)\n        {\n            var type = source.GetType();\n            s_lerpToOffsetMap[type](\n                    source, weightedIndexArrays, target, offset, length);\n            return target;\n        }\n\n        /// <summary>\n        /// Fills the target array starting at offset with Lerp/weighted\n        /// combinations of the source array.\n        /// </summary>\n        public static Array LerpTo(\n                this Array source,\n                IEnumerable<WeightedIndex[]> weightedIndexArrays,\n                Array target, int offset)\n        {\n            int length = Fun.Min(weightedIndexArrays.Count(), target.Length - offset);\n            return source.LerpTo(weightedIndexArrays, target, offset, length);\n        }\n\n        private static readonly Dictionary<Type, Action<Array, IEnumerable<WeightedIndex[]>,\n                                             Array, int, int>> s_lerpAndNormalizeToOffsetMap =\n            new Dictionary<Type, Action<Array, IEnumerable<WeightedIndex[]>, Array, int, int>>\n            {\n                { typeof(V3f[]), (s, w, t, o, l) =>\n                    CombineTo((V3f[])s, w, (wi,sa) => Lerp(wi,sa).Normalized, (V3f[])t, o, l) },\n                { typeof(V3d[]), (s, w, t, o, l) =>\n                    CombineTo((V3d[])s, w, (wi,sa) => Lerp(wi,sa).Normalized, (V3d[])t, o, l) },\n            };\n\n        /// <summary>\n        /// Fills the target array starting at offset for length entries\n        /// with normalized Lerp/weighted combinations of the source array.\n        /// </summary>\n        public static Array LerpAndNormalizeTo(\n                this Array source,\n                IEnumerable<WeightedIndex[]> weightedIndexArrays,\n                Array target, int offset, int length)\n        {\n            var type = source.GetType();\n            s_lerpAndNormalizeToOffsetMap[type](\n                    source, weightedIndexArrays, target, offset, length);\n            return target;\n        }\n\n        /// <summary>\n        /// Fills the target array starting at offset with normalized\n        /// Lerp/weighted combinations of the source array.\n        /// </summary>\n        public static Array LerpAndNormalizeTo(\n                this Array source,\n                IEnumerable<WeightedIndex[]> weightedIndexArrays,\n                Array target, int offset)\n        {\n            int length = Fun.Min(weightedIndexArrays.Count(), target.Length - offset);\n            return source.LerpAndNormalizeTo(weightedIndexArrays, target, offset, length);\n        }\n\n        public static V3d[] Transformed(this V3d[] points, M33d matrix)\n        {\n            return points.Map(p => matrix.Transform(p));\n        }\n\n        public static V3d[] TransformedPos(this V3d[] points, M44d matrix)\n        {\n            return points.Map(p => matrix.TransformPos(p));\n        }\n    }\n\n    public static class V2dArrayExtensions\n    {\n        #region Transformations\n\n        /// <summary>\n        /// Returns a version of the point array scaled by a factor of s about\n        /// the supplied center.\n        /// </summary>\n        public static V2d[] Scaled(this V2d[] pointArray, V2d center, double s)\n        {\n            long count = pointArray.LongLength;\n            var pa = new V2d[count];\n            for (long i = 0; i < count; i++) pa[i] = center + (pointArray[i] - center) * s;\n            return pa;\n        }\n\n        /// <summary>\n        /// Returns a version of the point array scaled by a factor of s about\n        /// the supplied center.\n        /// </summary>\n        public static V2d[] ScaledAboutCentroid(this V2d[] pointArray, double s)\n        {\n            return pointArray.Scaled(VectorIEnumerableExtensions.ComputeCentroid(pointArray), s);\n        }\n\n        /// <summary>\n        /// Returns new array containing transformed points.\n        /// </summary>\n        public static V2d[] Transformed(this V2d[] pointArray, M22d m)\n        {\n            return new V2d[pointArray.LongLength].SetByIndexLong(i => m.Transform(pointArray[i]));\n        }\n\n        /// <summary>\n        /// Returns new array containing transformed points.\n        /// </summary>\n        public static V2d[] TransformedPos(this V2d[] pointArray, M33d m)\n        {\n            return new V2d[pointArray.LongLength].SetByIndexLong(i => m.TransformPos(pointArray[i]));\n        }\n\n        /// <summary>\n        /// Returns new array containing transformed points.\n        /// </summary>\n        public static V2d[] TransformedDir(this V2d[] pointArray, M33d m)\n        {\n            return new V2d[pointArray.LongLength].SetByIndexLong(i => m.TransformDir(pointArray[i]));\n        }\n\n        #endregion\n    }\n\n    #endregion\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/VectorIEnumerableExtensions_auto.cs",
    "content": "using System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class VectorIEnumerableExtensions\n    {\n        #region V2i\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V2is.\n        /// </summary>\n        public static V2i Sum(this IEnumerable<V2i> vectors)\n        {\n            V2i sum = V2i.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V2is.\n        /// </summary>\n        public static V2i Sum(this V2i[] vectors)\n        {\n            V2i sum = V2i.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V2is.\n        /// </summary>\n        public static V2d ComputeCentroid(this IEnumerable<V2i> vectors)\n        { \n            V2d sum = V2d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V2d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2is.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2i[] vectors)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V2d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2is.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2i[] vectors, int[] indices)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V2d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V2is.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2i[] vectors, double[] weights)\n        {\n            V2d sum = V2d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V2d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V2d ComputeCentroid(this V2i[] vectors, double[] weights, int[] indices)\n        {\n            V2d sum = V2d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V2d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V3i\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V3is.\n        /// </summary>\n        public static V3i Sum(this IEnumerable<V3i> vectors)\n        {\n            V3i sum = V3i.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V3is.\n        /// </summary>\n        public static V3i Sum(this V3i[] vectors)\n        {\n            V3i sum = V3i.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V3is.\n        /// </summary>\n        public static V3d ComputeCentroid(this IEnumerable<V3i> vectors)\n        { \n            V3d sum = V3d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V3d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3is.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3i[] vectors)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V3d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3is.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3i[] vectors, int[] indices)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V3d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V3is.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3i[] vectors, double[] weights)\n        {\n            V3d sum = V3d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V3d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V3d ComputeCentroid(this V3i[] vectors, double[] weights, int[] indices)\n        {\n            V3d sum = V3d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V3d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V4i\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V4is.\n        /// </summary>\n        public static V4i Sum(this IEnumerable<V4i> vectors)\n        {\n            V4i sum = V4i.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V4is.\n        /// </summary>\n        public static V4i Sum(this V4i[] vectors)\n        {\n            V4i sum = V4i.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V4is.\n        /// </summary>\n        public static V4d ComputeCentroid(this IEnumerable<V4i> vectors)\n        { \n            V4d sum = V4d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V4d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4is.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4i[] vectors)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V4d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4is.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4i[] vectors, int[] indices)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V4d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V4is.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4i[] vectors, double[] weights)\n        {\n            V4d sum = V4d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V4d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V4d ComputeCentroid(this V4i[] vectors, double[] weights, int[] indices)\n        {\n            V4d sum = V4d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V4d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V2ui\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V2uis.\n        /// </summary>\n        public static V2ui Sum(this IEnumerable<V2ui> vectors)\n        {\n            V2ui sum = V2ui.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V2uis.\n        /// </summary>\n        public static V2ui Sum(this V2ui[] vectors)\n        {\n            V2ui sum = V2ui.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V2uis.\n        /// </summary>\n        public static V2d ComputeCentroid(this IEnumerable<V2ui> vectors)\n        { \n            V2d sum = V2d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V2d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2uis.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2ui[] vectors)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V2d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2uis.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2ui[] vectors, int[] indices)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V2d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V2uis.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2ui[] vectors, double[] weights)\n        {\n            V2d sum = V2d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V2d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V2d ComputeCentroid(this V2ui[] vectors, double[] weights, int[] indices)\n        {\n            V2d sum = V2d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V2d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V3ui\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V3uis.\n        /// </summary>\n        public static V3ui Sum(this IEnumerable<V3ui> vectors)\n        {\n            V3ui sum = V3ui.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V3uis.\n        /// </summary>\n        public static V3ui Sum(this V3ui[] vectors)\n        {\n            V3ui sum = V3ui.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V3uis.\n        /// </summary>\n        public static V3d ComputeCentroid(this IEnumerable<V3ui> vectors)\n        { \n            V3d sum = V3d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V3d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3uis.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3ui[] vectors)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V3d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3uis.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3ui[] vectors, int[] indices)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V3d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V3uis.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3ui[] vectors, double[] weights)\n        {\n            V3d sum = V3d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V3d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V3d ComputeCentroid(this V3ui[] vectors, double[] weights, int[] indices)\n        {\n            V3d sum = V3d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V3d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V4ui\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V4uis.\n        /// </summary>\n        public static V4ui Sum(this IEnumerable<V4ui> vectors)\n        {\n            V4ui sum = V4ui.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V4uis.\n        /// </summary>\n        public static V4ui Sum(this V4ui[] vectors)\n        {\n            V4ui sum = V4ui.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V4uis.\n        /// </summary>\n        public static V4d ComputeCentroid(this IEnumerable<V4ui> vectors)\n        { \n            V4d sum = V4d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V4d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4uis.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4ui[] vectors)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V4d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4uis.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4ui[] vectors, int[] indices)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V4d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V4uis.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4ui[] vectors, double[] weights)\n        {\n            V4d sum = V4d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V4d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V4d ComputeCentroid(this V4ui[] vectors, double[] weights, int[] indices)\n        {\n            V4d sum = V4d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V4d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V2l\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V2ls.\n        /// </summary>\n        public static V2l Sum(this IEnumerable<V2l> vectors)\n        {\n            V2l sum = V2l.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V2ls.\n        /// </summary>\n        public static V2l Sum(this V2l[] vectors)\n        {\n            V2l sum = V2l.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V2ls.\n        /// </summary>\n        public static V2d ComputeCentroid(this IEnumerable<V2l> vectors)\n        { \n            V2d sum = V2d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V2d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2ls.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2l[] vectors)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V2d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2ls.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2l[] vectors, int[] indices)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V2d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V2ls.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2l[] vectors, double[] weights)\n        {\n            V2d sum = V2d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V2d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V2d ComputeCentroid(this V2l[] vectors, double[] weights, int[] indices)\n        {\n            V2d sum = V2d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V2d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V3l\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V3ls.\n        /// </summary>\n        public static V3l Sum(this IEnumerable<V3l> vectors)\n        {\n            V3l sum = V3l.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V3ls.\n        /// </summary>\n        public static V3l Sum(this V3l[] vectors)\n        {\n            V3l sum = V3l.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V3ls.\n        /// </summary>\n        public static V3d ComputeCentroid(this IEnumerable<V3l> vectors)\n        { \n            V3d sum = V3d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V3d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3ls.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3l[] vectors)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V3d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3ls.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3l[] vectors, int[] indices)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V3d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V3ls.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3l[] vectors, double[] weights)\n        {\n            V3d sum = V3d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V3d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V3d ComputeCentroid(this V3l[] vectors, double[] weights, int[] indices)\n        {\n            V3d sum = V3d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V3d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V4l\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V4ls.\n        /// </summary>\n        public static V4l Sum(this IEnumerable<V4l> vectors)\n        {\n            V4l sum = V4l.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V4ls.\n        /// </summary>\n        public static V4l Sum(this V4l[] vectors)\n        {\n            V4l sum = V4l.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V4ls.\n        /// </summary>\n        public static V4d ComputeCentroid(this IEnumerable<V4l> vectors)\n        { \n            V4d sum = V4d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += (V4d)e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4ls.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4l[] vectors)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += (V4d)vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4ls.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4l[] vectors, int[] indices)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += (V4d)vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V4ls.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4l[] vectors, double[] weights)\n        {\n            V4d sum = V4d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * (V4d)vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V4d ComputeCentroid(this V4l[] vectors, double[] weights, int[] indices)\n        {\n            V4d sum = V4d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * (V4d)vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V2f\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V2fs.\n        /// </summary>\n        public static V2f Sum(this IEnumerable<V2f> vectors)\n        {\n            V2f sum = V2f.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V2fs.\n        /// </summary>\n        public static V2f Sum(this V2f[] vectors)\n        {\n            V2f sum = V2f.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V2fs.\n        /// </summary>\n        public static V2f ComputeCentroid(this IEnumerable<V2f> vectors)\n        { \n            V2f sum = V2f.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n                count++;\n            }\n\n            return sum / (float)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2fs.\n        /// </summary>\n        public static V2f ComputeCentroid(this V2f[] vectors)\n        {\n            V2f sum = V2f.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum / (float)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2fs.\n        /// </summary>\n        public static V2f ComputeCentroid(this V2f[] vectors, int[] indices)\n        {\n            V2f sum = V2f.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += vectors[indices[i]];\n            }\n\n            return sum / (float)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V2fs.\n        /// </summary>\n        public static V2f ComputeCentroid(this V2f[] vectors, float[] weights)\n        {\n            V2f sum = V2f.Zero;\n            float weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V2f ComputeCentroid(this V2f[] vectors, float[] weights, int[] indices)\n        {\n            V2f sum = V2f.Zero;\n            float weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V3f\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V3fs.\n        /// </summary>\n        public static V3f Sum(this IEnumerable<V3f> vectors)\n        {\n            V3f sum = V3f.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V3fs.\n        /// </summary>\n        public static V3f Sum(this V3f[] vectors)\n        {\n            V3f sum = V3f.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V3fs.\n        /// </summary>\n        public static V3f ComputeCentroid(this IEnumerable<V3f> vectors)\n        { \n            V3f sum = V3f.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n                count++;\n            }\n\n            return sum / (float)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3fs.\n        /// </summary>\n        public static V3f ComputeCentroid(this V3f[] vectors)\n        {\n            V3f sum = V3f.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum / (float)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3fs.\n        /// </summary>\n        public static V3f ComputeCentroid(this V3f[] vectors, int[] indices)\n        {\n            V3f sum = V3f.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += vectors[indices[i]];\n            }\n\n            return sum / (float)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V3fs.\n        /// </summary>\n        public static V3f ComputeCentroid(this V3f[] vectors, float[] weights)\n        {\n            V3f sum = V3f.Zero;\n            float weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V3f ComputeCentroid(this V3f[] vectors, float[] weights, int[] indices)\n        {\n            V3f sum = V3f.Zero;\n            float weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V4f\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V4fs.\n        /// </summary>\n        public static V4f Sum(this IEnumerable<V4f> vectors)\n        {\n            V4f sum = V4f.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V4fs.\n        /// </summary>\n        public static V4f Sum(this V4f[] vectors)\n        {\n            V4f sum = V4f.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V4fs.\n        /// </summary>\n        public static V4f ComputeCentroid(this IEnumerable<V4f> vectors)\n        { \n            V4f sum = V4f.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n                count++;\n            }\n\n            return sum / (float)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4fs.\n        /// </summary>\n        public static V4f ComputeCentroid(this V4f[] vectors)\n        {\n            V4f sum = V4f.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum / (float)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4fs.\n        /// </summary>\n        public static V4f ComputeCentroid(this V4f[] vectors, int[] indices)\n        {\n            V4f sum = V4f.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += vectors[indices[i]];\n            }\n\n            return sum / (float)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V4fs.\n        /// </summary>\n        public static V4f ComputeCentroid(this V4f[] vectors, float[] weights)\n        {\n            V4f sum = V4f.Zero;\n            float weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V4f ComputeCentroid(this V4f[] vectors, float[] weights, int[] indices)\n        {\n            V4f sum = V4f.Zero;\n            float weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V2d\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V2ds.\n        /// </summary>\n        public static V2d Sum(this IEnumerable<V2d> vectors)\n        {\n            V2d sum = V2d.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V2ds.\n        /// </summary>\n        public static V2d Sum(this V2d[] vectors)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V2ds.\n        /// </summary>\n        public static V2d ComputeCentroid(this IEnumerable<V2d> vectors)\n        { \n            V2d sum = V2d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2ds.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2d[] vectors)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V2ds.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2d[] vectors, int[] indices)\n        {\n            V2d sum = V2d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V2ds.\n        /// </summary>\n        public static V2d ComputeCentroid(this V2d[] vectors, double[] weights)\n        {\n            V2d sum = V2d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V2d ComputeCentroid(this V2d[] vectors, double[] weights, int[] indices)\n        {\n            V2d sum = V2d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V3d\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V3ds.\n        /// </summary>\n        public static V3d Sum(this IEnumerable<V3d> vectors)\n        {\n            V3d sum = V3d.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V3ds.\n        /// </summary>\n        public static V3d Sum(this V3d[] vectors)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V3ds.\n        /// </summary>\n        public static V3d ComputeCentroid(this IEnumerable<V3d> vectors)\n        { \n            V3d sum = V3d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3ds.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3d[] vectors)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V3ds.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3d[] vectors, int[] indices)\n        {\n            V3d sum = V3d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V3ds.\n        /// </summary>\n        public static V3d ComputeCentroid(this V3d[] vectors, double[] weights)\n        {\n            V3d sum = V3d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V3d ComputeCentroid(this V3d[] vectors, double[] weights, int[] indices)\n        {\n            V3d sum = V3d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region V4d\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of V4ds.\n        /// </summary>\n        public static V4d Sum(this IEnumerable<V4d> vectors)\n        {\n            V4d sum = V4d.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of V4ds.\n        /// </summary>\n        public static V4d Sum(this V4d[] vectors)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of V4ds.\n        /// </summary>\n        public static V4d ComputeCentroid(this IEnumerable<V4d> vectors)\n        { \n            V4d sum = V4d.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n                count++;\n            }\n\n            return sum / (double)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4ds.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4d[] vectors)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum / (double)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of V4ds.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4d[] vectors, int[] indices)\n        {\n            V4d sum = V4d.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += vectors[indices[i]];\n            }\n\n            return sum / (double)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of V4ds.\n        /// </summary>\n        public static V4d ComputeCentroid(this V4d[] vectors, double[] weights)\n        {\n            V4d sum = V4d.Zero;\n            double weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static V4d ComputeCentroid(this V4d[] vectors, double[] weights, int[] indices)\n        {\n            V4d sum = V4d.Zero;\n            double weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/VectorIEnumerableExtensions_template.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class VectorIEnumerableExtensions\n    {\n        //# foreach(var scalar in Meta.VecFieldTypes)\n        //# {\n        //# foreach(var dim in Meta.VecTypeDimensions)\n        //# {\n        //#     var inputVecType = Meta.VecTypeOf(dim, scalar).Name;\n        //#     var outputVecType = scalar.IsReal ? inputVecType : Meta.VecTypeOf(dim, Meta.DoubleType).Name;\n        //#     var scalarType = scalar.IsReal ? scalar.Name :  Meta.DoubleType.Name;\n        //#     var cast = scalar.IsReal ? \"\" : \"(\" + outputVecType + \")\";\n        #region __inputVecType__\n\n        #region Sum\n        /// <summary>\n        /// Calculates the sum for a given set of __inputVecType__s.\n        /// </summary>\n        public static __inputVecType__ Sum(this IEnumerable<__inputVecType__> vectors)\n        {\n            __inputVecType__ sum = __inputVecType__.Zero;\n\n            foreach (var e in vectors)\n            {\n                sum += e;\n            }\n\n            return sum;\n        }\n\n        /// <summary>\n        /// Calculates the sum for a given set of __inputVecType__s.\n        /// </summary>\n        public static __inputVecType__ Sum(this __inputVecType__[] vectors)\n        {\n            __inputVecType__ sum = __inputVecType__.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += vectors[i];\n            }\n\n            return sum;\n        }\n\n        #endregion\n\n        #region Centroid\n        /// <summary>\n        /// Calculates the centroid for a given set of __inputVecType__s.\n        /// </summary>\n        public static __outputVecType__ ComputeCentroid(this IEnumerable<__inputVecType__> vectors)\n        { \n            __outputVecType__ sum = __outputVecType__.Zero;\n            int count = 0;\n\n            foreach (var e in vectors)\n            {\n                sum += __cast__e;\n                count++;\n            }\n\n            return sum / (__scalarType__)count;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of __inputVecType__s.\n        /// </summary>\n        public static __outputVecType__ ComputeCentroid(this __inputVecType__[] vectors)\n        {\n            __outputVecType__ sum = __outputVecType__.Zero;\n\n            for (var i = 0; i < vectors.Length; i++)\n            {\n                sum += __cast__vectors[i];\n            }\n\n            return sum / (__scalarType__)vectors.Length;\n        }\n\n        /// <summary>\n        /// Calculates the centroid for a given set of __inputVecType__s.\n        /// </summary>\n        public static __outputVecType__ ComputeCentroid(this __inputVecType__[] vectors, int[] indices)\n        {\n            __outputVecType__ sum = __outputVecType__.Zero;\n\n            for (var i = 0; i < indices.Length; i++)\n            {\n                sum += __cast__vectors[indices[i]];\n            }\n\n            return sum / (__scalarType__)indices.Length;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for a given array of __inputVecType__s.\n        /// </summary>\n        public static __outputVecType__ ComputeCentroid(this __inputVecType__[] vectors, __scalarType__[] weights)\n        {\n            __outputVecType__ sum = __outputVecType__.Zero;\n            __scalarType__ weightSum = 0;\n\n            for(int i = 0; i < vectors.Length; i++)\n            {\n                sum += weights[i] * __cast__vectors[i];\n                weightSum += weights[i];\n            }\n\n            return sum / weightSum;\n        }\n\n        /// <summary>\n        /// Calculates a weighted centroid for vectors and weights given by indices.\n        /// Sum(vectors[indices[i]] * weights[indices[i]]) / Sum(weights[indices[i]].\n        /// </summary>\n        public static __outputVecType__ ComputeCentroid(this __inputVecType__[] vectors, __scalarType__[] weights, int[] indices)\n        {\n            __outputVecType__ sum = __outputVecType__.Zero;\n            __scalarType__ weightSum = 0;\n\n            for (int i = 0; i < indices.Length; i++)\n            {\n                var w = weights[indices[i]];\n                sum += w * __cast__vectors[indices[i]];\n                weightSum += w;\n            }\n\n            return sum / weightSum;\n        }\n\n        #endregion\n\n        #endregion\n\n        //# } ///foreach(Meta.VecTypeDimensions);\n        //# } ///foreach(Meta.VecTypes)\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/VectorTypeConverter_auto.cs",
    "content": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.ComponentModel.Design.Serialization;\nusing System.Globalization;\nusing System.Reflection;\nusing System.Text;\n\n// AUTO-GENERATED CODE - DO NOT EDIT!\n\nnamespace Aardvark.Base\n{\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 2\n    //   primitive type is int\n    //   vector type is V2i\n    \n    [TypeConverter(typeof(V2iConverter))]\n    public partial struct V2i { }\n\n    public class V2iConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V2i((V2i)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V2i(\n                    (int)propertyValues[\"X0\"], \n                    (int)propertyValues[\"X1\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V2i, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 2)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (int)Convert.ToDouble(parms[0]);\n                        var x1 = (int)Convert.ToDouble(parms[1]);\n\n                        // And finally create the object\n\n                        retVal = new V2i(x0, x1);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V2i)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[2];\n\n                argTypes[0] = typeof(int);\n                argTypes[1] = typeof(int);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V2i).GetConstructor(argTypes);\n\n                var arguments = new object[2];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[2];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(int));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 2\n    //   primitive type is long\n    //   vector type is V2l\n    \n    [TypeConverter(typeof(V2lConverter))]\n    public partial struct V2l { }\n\n    public class V2lConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V2l((V2l)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V2l(\n                    (long)propertyValues[\"X0\"], \n                    (long)propertyValues[\"X1\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V2l, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 2)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (long)Convert.ToDouble(parms[0]);\n                        var x1 = (long)Convert.ToDouble(parms[1]);\n\n                        // And finally create the object\n\n                        retVal = new V2l(x0, x1);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V2l)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[2];\n\n                argTypes[0] = typeof(long);\n                argTypes[1] = typeof(long);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V2l).GetConstructor(argTypes);\n\n                var arguments = new object[2];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[2];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(long));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 2\n    //   primitive type is float\n    //   vector type is V2f\n    \n    [TypeConverter(typeof(V2fConverter))]\n    public partial struct V2f { }\n\n    public class V2fConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V2f((V2f)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V2f(\n                    (float)propertyValues[\"X0\"], \n                    (float)propertyValues[\"X1\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V2f, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 2)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (float)Convert.ToDouble(parms[0]);\n                        var x1 = (float)Convert.ToDouble(parms[1]);\n\n                        // And finally create the object\n\n                        retVal = new V2f(x0, x1);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V2f)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[2];\n\n                argTypes[0] = typeof(float);\n                argTypes[1] = typeof(float);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V2f).GetConstructor(argTypes);\n\n                var arguments = new object[2];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[2];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(float));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 2\n    //   primitive type is double\n    //   vector type is V2d\n    \n    [TypeConverter(typeof(V2dConverter))]\n    public partial struct V2d { }\n\n    public class V2dConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V2d((V2d)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V2d(\n                    (double)propertyValues[\"X0\"], \n                    (double)propertyValues[\"X1\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V2d, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 2)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (double)Convert.ToDouble(parms[0]);\n                        var x1 = (double)Convert.ToDouble(parms[1]);\n\n                        // And finally create the object\n\n                        retVal = new V2d(x0, x1);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V2d)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[2];\n\n                argTypes[0] = typeof(double);\n                argTypes[1] = typeof(double);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V2d).GetConstructor(argTypes);\n\n                var arguments = new object[2];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[2];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(double));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 3\n    //   primitive type is int\n    //   vector type is V3i\n    \n    [TypeConverter(typeof(V3iConverter))]\n    public partial struct V3i { }\n\n    public class V3iConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V3i((V3i)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V3i(\n                    (int)propertyValues[\"X0\"], \n                    (int)propertyValues[\"X1\"], \n                    (int)propertyValues[\"X2\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V3i, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 3)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (int)Convert.ToDouble(parms[0]);\n                        var x1 = (int)Convert.ToDouble(parms[1]);\n                        var x2 = (int)Convert.ToDouble(parms[2]);\n\n                        // And finally create the object\n\n                        retVal = new V3i(x0, x1, x2);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V3i)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[3];\n\n                argTypes[0] = typeof(int);\n                argTypes[1] = typeof(int);\n                argTypes[2] = typeof(int);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V3i).GetConstructor(argTypes);\n\n                var arguments = new object[3];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n                arguments[2] = v[2];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[3];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(int));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n                values[2] = numberConverter.ConvertToString(context, culture, v[2]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 3\n    //   primitive type is long\n    //   vector type is V3l\n    \n    [TypeConverter(typeof(V3lConverter))]\n    public partial struct V3l { }\n\n    public class V3lConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V3l((V3l)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V3l(\n                    (long)propertyValues[\"X0\"], \n                    (long)propertyValues[\"X1\"], \n                    (long)propertyValues[\"X2\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V3l, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 3)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (long)Convert.ToDouble(parms[0]);\n                        var x1 = (long)Convert.ToDouble(parms[1]);\n                        var x2 = (long)Convert.ToDouble(parms[2]);\n\n                        // And finally create the object\n\n                        retVal = new V3l(x0, x1, x2);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V3l)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[3];\n\n                argTypes[0] = typeof(long);\n                argTypes[1] = typeof(long);\n                argTypes[2] = typeof(long);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V3l).GetConstructor(argTypes);\n\n                var arguments = new object[3];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n                arguments[2] = v[2];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[3];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(long));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n                values[2] = numberConverter.ConvertToString(context, culture, v[2]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 3\n    //   primitive type is float\n    //   vector type is V3f\n    \n    [TypeConverter(typeof(V3fConverter))]\n    public partial struct V3f { }\n\n    public class V3fConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V3f((V3f)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V3f(\n                    (float)propertyValues[\"X0\"], \n                    (float)propertyValues[\"X1\"], \n                    (float)propertyValues[\"X2\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V3f, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 3)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (float)Convert.ToDouble(parms[0]);\n                        var x1 = (float)Convert.ToDouble(parms[1]);\n                        var x2 = (float)Convert.ToDouble(parms[2]);\n\n                        // And finally create the object\n\n                        retVal = new V3f(x0, x1, x2);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V3f)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[3];\n\n                argTypes[0] = typeof(float);\n                argTypes[1] = typeof(float);\n                argTypes[2] = typeof(float);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V3f).GetConstructor(argTypes);\n\n                var arguments = new object[3];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n                arguments[2] = v[2];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[3];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(float));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n                values[2] = numberConverter.ConvertToString(context, culture, v[2]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 3\n    //   primitive type is double\n    //   vector type is V3d\n    \n    [TypeConverter(typeof(V3dConverter))]\n    public partial struct V3d { }\n\n    public class V3dConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V3d((V3d)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V3d(\n                    (double)propertyValues[\"X0\"], \n                    (double)propertyValues[\"X1\"], \n                    (double)propertyValues[\"X2\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V3d, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 3)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (double)Convert.ToDouble(parms[0]);\n                        var x1 = (double)Convert.ToDouble(parms[1]);\n                        var x2 = (double)Convert.ToDouble(parms[2]);\n\n                        // And finally create the object\n\n                        retVal = new V3d(x0, x1, x2);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V3d)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[3];\n\n                argTypes[0] = typeof(double);\n                argTypes[1] = typeof(double);\n                argTypes[2] = typeof(double);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V3d).GetConstructor(argTypes);\n\n                var arguments = new object[3];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n                arguments[2] = v[2];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[3];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(double));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n                values[2] = numberConverter.ConvertToString(context, culture, v[2]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 4\n    //   primitive type is int\n    //   vector type is V4i\n    \n    [TypeConverter(typeof(V4iConverter))]\n    public partial struct V4i { }\n\n    public class V4iConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V4i((V4i)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V4i(\n                    (int)propertyValues[\"X0\"], \n                    (int)propertyValues[\"X1\"], \n                    (int)propertyValues[\"X2\"], \n                    (int)propertyValues[\"X3\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V4i, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 4)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (int)Convert.ToDouble(parms[0]);\n                        var x1 = (int)Convert.ToDouble(parms[1]);\n                        var x2 = (int)Convert.ToDouble(parms[2]);\n                        var x3 = (int)Convert.ToDouble(parms[3]);\n\n                        // And finally create the object\n\n                        retVal = new V4i(x0, x1, x2, x3);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V4i)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[4];\n\n                argTypes[0] = typeof(int);\n                argTypes[1] = typeof(int);\n                argTypes[2] = typeof(int);\n                argTypes[3] = typeof(int);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V4i).GetConstructor(argTypes);\n\n                var arguments = new object[4];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n                arguments[2] = v[2];\n                arguments[3] = v[3];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[4];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(int));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n                values[2] = numberConverter.ConvertToString(context, culture, v[2]);\n                values[3] = numberConverter.ConvertToString(context, culture, v[3]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 4\n    //   primitive type is long\n    //   vector type is V4l\n    \n    [TypeConverter(typeof(V4lConverter))]\n    public partial struct V4l { }\n\n    public class V4lConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V4l((V4l)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V4l(\n                    (long)propertyValues[\"X0\"], \n                    (long)propertyValues[\"X1\"], \n                    (long)propertyValues[\"X2\"], \n                    (long)propertyValues[\"X3\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V4l, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 4)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (long)Convert.ToDouble(parms[0]);\n                        var x1 = (long)Convert.ToDouble(parms[1]);\n                        var x2 = (long)Convert.ToDouble(parms[2]);\n                        var x3 = (long)Convert.ToDouble(parms[3]);\n\n                        // And finally create the object\n\n                        retVal = new V4l(x0, x1, x2, x3);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V4l)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[4];\n\n                argTypes[0] = typeof(long);\n                argTypes[1] = typeof(long);\n                argTypes[2] = typeof(long);\n                argTypes[3] = typeof(long);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V4l).GetConstructor(argTypes);\n\n                var arguments = new object[4];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n                arguments[2] = v[2];\n                arguments[3] = v[3];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[4];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(long));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n                values[2] = numberConverter.ConvertToString(context, culture, v[2]);\n                values[3] = numberConverter.ConvertToString(context, culture, v[3]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 4\n    //   primitive type is float\n    //   vector type is V4f\n    \n    [TypeConverter(typeof(V4fConverter))]\n    public partial struct V4f { }\n\n    public class V4fConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V4f((V4f)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V4f(\n                    (float)propertyValues[\"X0\"], \n                    (float)propertyValues[\"X1\"], \n                    (float)propertyValues[\"X2\"], \n                    (float)propertyValues[\"X3\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V4f, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 4)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (float)Convert.ToDouble(parms[0]);\n                        var x1 = (float)Convert.ToDouble(parms[1]);\n                        var x2 = (float)Convert.ToDouble(parms[2]);\n                        var x3 = (float)Convert.ToDouble(parms[3]);\n\n                        // And finally create the object\n\n                        retVal = new V4f(x0, x1, x2, x3);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V4f)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[4];\n\n                argTypes[0] = typeof(float);\n                argTypes[1] = typeof(float);\n                argTypes[2] = typeof(float);\n                argTypes[3] = typeof(float);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V4f).GetConstructor(argTypes);\n\n                var arguments = new object[4];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n                arguments[2] = v[2];\n                arguments[3] = v[3];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[4];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(float));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n                values[2] = numberConverter.ConvertToString(context, culture, v[2]);\n                values[3] = numberConverter.ConvertToString(context, culture, v[3]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is 4\n    //   primitive type is double\n    //   vector type is V4d\n    \n    [TypeConverter(typeof(V4dConverter))]\n    public partial struct V4d { }\n\n    public class V4dConverter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new V4d((V4d)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new V4d(\n                    (double)propertyValues[\"X0\"], \n                    (double)propertyValues[\"X1\"], \n                    (double)propertyValues[\"X2\"], \n                    (double)propertyValues[\"X3\"]\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a V4d, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == 4)\n                    {\n                        // Should have an integer and a string.\n                        var x0 = (double)Convert.ToDouble(parms[0]);\n                        var x1 = (double)Convert.ToDouble(parms[1]);\n                        var x2 = (double)Convert.ToDouble(parms[2]);\n                        var x3 = (double)Convert.ToDouble(parms[3]);\n\n                        // And finally create the object\n\n                        retVal = new V4d(x0, x1, x2, x3);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (V4d)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[4];\n\n                argTypes[0] = typeof(double);\n                argTypes[1] = typeof(double);\n                argTypes[2] = typeof(double);\n                argTypes[3] = typeof(double);\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(V4d).GetConstructor(argTypes);\n\n                var arguments = new object[4];\n\n                arguments[0] = v[0];\n                arguments[1] = v[1];\n                arguments[2] = v[2];\n                arguments[3] = v[3];\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[4];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(double));\n                values[0] = numberConverter.ConvertToString(context, culture, v[0]);\n                values[1] = numberConverter.ConvertToString(context, culture, v[1]);\n                values[2] = numberConverter.ConvertToString(context, culture, v[2]);\n                values[3] = numberConverter.ConvertToString(context, culture, v[3]);\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/VectorTypeConverter_template.cs",
    "content": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.ComponentModel.Design.Serialization;\nusing System.Globalization;\nusing System.Reflection;\nusing System.Text;\n\n// AUTO-GENERATED CODE - DO NOT EDIT!\n\nnamespace Aardvark.Base\n{\n/*#\nfor (int Dim = 2; Dim <= 4; Dim++)\n{\n    foreach (var TPrimitive in new string[] { \"int\", \"long\", \"float\", \"double\" })\n    {\n        var TVector = \"V\" + Dim + TPrimitive[0];\n*/    \n    /////////////////////////////////////////////////////////////////////\n    //   dimension is __Dim__\n    //   primitive type is __TPrimitive__\n    //   vector type is __TVector__\n    \n    [TypeConverter(typeof(__TVector__Converter))]\n    public partial struct __TVector__ { }\n\n    public class __TVector__Converter : TypeConverter\n    {\n\n        /// <summary>\n        /// Can the framework call CreateInstance?\n        /// </summary>\n        public override bool GetCreateInstanceSupported(\n            ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Satisfy the CreateInstance call by reading data from the\n        /// propertyValues dictionary\n        /// </summary>\n        public override object CreateInstance(\n            ITypeDescriptorContext context, IDictionary propertyValues\n            )\n        {\n            if (propertyValues.Contains(\"Value\"))\n            {\n                var v = new __TVector__((__TVector__)(propertyValues[\"Value\"]));\n                return v;\n            }\n            else\n            {\n                return new __TVector__(\n//# for (int i = 0; i < Dim; i++) {\n                    (__TPrimitive__)propertyValues[\"X__i__\"]__(i < Dim-1)?\", \":\"\"__\n//# }\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Does this struct expose properties?\n        /// </summary>\n        public override bool GetPropertiesSupported(ITypeDescriptorContext context)\n        {\n            return true;\n        }\n\n        /// <summary>\n        /// Return the properties of this struct\n        /// </summary>\n        public override PropertyDescriptorCollection GetProperties(\n            ITypeDescriptorContext context, object value, Attribute[] attributes\n            )\n        {\n            return TypeDescriptor.GetProperties(value, attributes);\n        }\n\n        /// <summary>\n        /// Check what this type can be created from\n        /// </summary>\n        public override bool CanConvertFrom(\n            ITypeDescriptorContext context, System.Type sourceType\n            )\n        {\n            // Just strings for now\n            bool canConvert = (sourceType == typeof(string));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, sourceType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert from a specified type to a __TVector__, if possible\n        /// </summary>\n        public override object ConvertFrom(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value\n            )\n        {\n            string sValue = value as string;\n            object retVal = null;\n\n            if (sValue != null)\n            {\n                // Check that the string actually has something in it...\n                sValue = sValue.Trim();\n\n                if (sValue.Length != 0)\n                {\n                    // Parse the string\n                    if (null == culture)\n                        culture = CultureInfo.CurrentCulture;\n\n                    // Split the string based on the cultures list separator\n                    var parms = sValue.Split(\n                        new char[] { culture.TextInfo.ListSeparator[0] }\n                        );\n\n                    if (parms.Length == __Dim__)\n                    {\n                        // Should have an integer and a string.\n//# for (int i = 0; i < Dim; i++) {\n                        var x__i__ = (__TPrimitive__)Convert.ToDouble(parms[__i__]);\n//# }\n\n                        // And finally create the object\n/*#\n    var elements = new List<string>();\n    for (int i = 0; i < Dim; i++) elements.Add(\"x\" + i);\n*/\n                        retVal = new __TVector__(__elements.Join(\", \")__);\n                    }\n                }\n            }\n            else\n            {\n                retVal = base.ConvertFrom(context, culture, value);\n            }\n\n            return retVal;\n        }\n\n        /// <summary>\n        /// Check what the type can be converted to\n        /// </summary>\n        public override bool CanConvertTo(\n            ITypeDescriptorContext context, Type destinationType\n            )\n        {\n            // InstanceDescriptor is used in the code behind\n            bool canConvert = (destinationType == typeof(InstanceDescriptor));\n\n            if (!canConvert)\n                canConvert = base.CanConvertFrom(context, destinationType);\n\n            return canConvert;\n        }\n\n        /// <summary>\n        /// Convert to a specified type\n        /// </summary>\n        public override object ConvertTo(\n            ITypeDescriptorContext context,\n            CultureInfo culture, object value,\n            Type destinationType\n            )\n        {\n            object retVal = null;\n            var v = (__TVector__)value;\n\n            // If this is an instance descriptor...\n            if (destinationType == typeof(InstanceDescriptor))\n            {\n                var argTypes = new System.Type[__Dim__];\n\n//# for (int i = 0; i < Dim; i++) {\n                argTypes[__i__] = typeof(__TPrimitive__);\n//# }\n\n                // Lookup the appropriate $TVector$ constructor\n                ConstructorInfo constructor = typeof(__TVector__).GetConstructor(argTypes);\n\n                var arguments = new object[__Dim__];\n\n//# for (int i = 0; i < Dim; i++) {\n                arguments[__i__] = v[__i__];\n//# }\n\n                // And return an instance descriptor to the caller.\n                // Will fill in the CodeBehind stuff in VS.Net\n                retVal = new InstanceDescriptor(constructor, arguments);\n            }\n            else if (destinationType == typeof(string))\n            {\n                // If it's a string, return one to the caller\n                if (null == culture)\n                    culture = CultureInfo.CurrentCulture;\n\n                var values = new string[__Dim__];\n\n                // I'm a bit of a culture vulture - do it properly!\n                TypeConverter numberConverter =\n                    TypeDescriptor.GetConverter(typeof(__TPrimitive__));\n//# for (int i = 0; i < Dim; i++) {\n                values[__i__] = numberConverter.ConvertToString(context, culture, v[__i__]);\n//# }\n\n                // A useful method - join an array of strings using a separator, in this instance the culture specific one\n                retVal = String.Join(culture.TextInfo.ListSeparator + \" \", values);\n            }\n            else\n                retVal = base.ConvertTo(context, culture, value, destinationType);\n\n            return retVal;\n        }\n\n    }\n\n//#     }\n//# }\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/Vector_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Diagnostics.Contracts;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Xml.Serialization;\n#if NETCOREAPP3_1_OR_GREATER\nusing System.Runtime.Intrinsics.X86;\nusing System.Runtime.Intrinsics;\n#endif\n\nusing Aardbase = Aardvark.Base;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    [Flags]\n    public enum DirFlags\n    {\n        None = 0x00,\n        NegativeX = 0x01,\n        PositiveX = 0x02,\n        NegativeY = 0x04,\n        PositiveY = 0x08,\n        NegativeZ = 0x10,\n        PositiveZ = 0x20,\n        NegativeW = 0x40,\n        PositiveW = 0x80,\n\n        X = NegativeX | PositiveX,\n        Y = NegativeY | PositiveY,\n        Z = NegativeZ | PositiveZ,\n    };\n\n    #region V2i\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V2i : IVector<double>, ISize2i, IFormattable, IEquatable<V2i>\n    {\n        [DataMember]\n        public int X;\n        [DataMember]\n        public int Y;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(int x, int y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(int v)\n        {\n            X = v;\n            Y = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(int[] a)\n        {\n            X = a[0];\n            Y = a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(int[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(uint x, uint y)\n        {\n            X = (int)x;\n            Y = (int)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(uint v)\n        {\n            X = (int)v;\n            Y = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(uint[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(uint[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(long x, long y)\n        {\n            X = (int)x;\n            Y = (int)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(long v)\n        {\n            X = (int)v;\n            Y = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(long[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(long[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(float x, float y)\n        {\n            X = (int)x;\n            Y = (int)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(float v)\n        {\n            X = (int)v;\n            Y = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(float[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(float[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(double x, double y)\n        {\n            X = (int)x;\n            Y = (int)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(double v)\n        {\n            X = (int)v;\n            Y = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(double[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(double[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(Func<int, int> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;int&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 2.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(IVector<double> v)\n            : this(v[0], v[1])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V2i v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V2ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V2l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V2f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V2d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V3i v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V3ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V3l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V3f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V3d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V4i v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V4ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V4l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V4f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2i(V4d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V2ui v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V2l v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V2f v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V2d v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V3i v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V3ui v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V3l v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V3f v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V3d v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V4i v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V4ui v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V4l v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V4f v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(V4d v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V2i v)\n            => new int[] { v.X, v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(int[] v)\n            => new V2i(v[0], v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V2i v)\n            => new uint[] { (uint)v.X, (uint)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(uint[] v)\n            => new V2i((int)v[0], (int)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V2i v)\n            => new long[] { (long)v.X, (long)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(long[] v)\n            => new V2i((int)v[0], (int)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V2i v)\n            => new float[] { (float)v.X, (float)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(float[] v)\n            => new V2i((int)v[0], (int)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V2i v)\n            => new double[] { (double)v.X, (double)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2i(double[] v)\n            => new V2i((int)v[0], (int)v[1]);\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<int, int> element_fun)\n            => new V2i(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<int, int, int> element_index_fun)\n            => new V2i(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<int, uint> element_fun)\n            => new V2ui(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<int, int, uint> element_index_fun)\n            => new V2ui(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<int, long> element_fun)\n            => new V2l(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<int, int, long> element_index_fun)\n            => new V2l(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<int, float> element_fun)\n            => new V2f(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<int, int, float> element_index_fun)\n            => new V2f(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<int, double> element_fun)\n            => new V2d(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<int, int, double> element_index_fun)\n            => new V2d(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<int, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<int, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int[] ToArray()\n            => new int[] { X, Y };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe int this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly int MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly int MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 2;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V2i Zero\n        {\n            get { return new V2i(0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V2i One\n        {\n            get { return new V2i(1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V2i MaxValue\n        {\n            get { return new V2i(Constant<int>.ParseableMaxValue, Constant<int>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V2i MinValue\n        {\n            get { return new V2i(Constant<int>.ParseableMinValue, Constant<int>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V2i XAxis\n        {\n            get { return new V2i(1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V2i YAxis\n        {\n            get { return new V2i(0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V2i, int>[] SelectorArray =\n            new Func<V2i, int>[] { v => v.X, v => v.Y };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V2i, int, int> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V2i, int, int> Setter =\n            (ref V2i v, int i, int s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V2i, long, int> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V2i, long, int> LongSetter =\n            (ref V2i v, long i, int s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i FromV2ui(V2ui v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i FromV2l(V2l v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i FromV2f(V2f v)\n            => new V2i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i FromV2d(V2d v)\n            => new V2i(v);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly int LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly int Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly int NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly int NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V2d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V2d.Zero;\n                s = 1 / s;\n                return new V2d(X * s, Y * s);\n            }\n        }\n\n        /// <summary>\n        /// Vector rotated 90° counter clockwise: (-Y, X)\n        /// </summary>\n        public readonly V2i Rot90\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2i(-Y, X); }\n        }\n\n        /// <summary>\n        /// Vector rotated 180° counter clockwise: (-X, -Y)\n        /// </summary>\n        public readonly V2i Rot180\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2i(-X, -Y); }\n        }\n\n        /// <summary>\n        /// Vector rotated 270° counter clockwise: (Y, -X)\n        /// </summary>\n        public readonly V2i Rot270\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2i(Y, -X); }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Abs(V2i v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i LinearInterp(float t, V2i a, V2i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i LinearInterp(V2f t, V2i a, V2i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i LinearInterp(double t, V2i a, V2i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i LinearInterp(V2d t, V2i a, V2i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Min(V2i v0, V2i v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Min(V2i v, int x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Max(V2i v0, V2i v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Max(V2i v, int x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Saturate(V2i v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i DivideByInt(V2i v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y)\n        {\n            X = (int)x;\n            Y = (int)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y)\n        {\n            X = (int)x;\n            Y = (int)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y)\n        {\n            X = (int)x;\n            Y = (int)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y)\n        {\n            X = (int)x;\n            Y = (int)y;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator -(V2i v)\n            => new V2i(-v.X, -v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator ~(V2i v)\n            => new V2i(~v.X, ~v.Y);\n\n        /// <summary>\n        /// Returns a vector that is orthogonal to this one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        public readonly V2i Orthogonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2i(-Y, X); }\n        }\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator +(V2i a, V2i b)\n            => new V2i(a.X + b.X, a.Y + b.Y);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator +(V2i v, int s)\n            => new V2i(v.X + s, v.Y + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator +(int s, V2i v)\n            => new V2i(s + v.X, s + v.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator -(V2i a, V2i b)\n            => new V2i(a.X - b.X, a.Y - b.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator -(V2i v, int s)\n            => new V2i(v.X - s, v.Y - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator -(int s, V2i v)\n            => new V2i(s - v.X, s - v.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator *(V2i a, V2i b)\n            => new V2i(a.X * b.X, a.Y * b.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator *(V2i v, int s)\n            => new V2i(v.X * s, v.Y * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator *(int s, V2i v)\n            => new V2i(s * v.X, s * v.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator /(V2i a, V2i b)\n            => new V2i(a.X / b.X, a.Y / b.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator /(V2i v, int s)\n            => new V2i(v.X / s, v.Y / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator /(int s, V2i v)\n            => new V2i(s / v.X, s / v.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator %(V2i a, V2i b)\n            => new V2i(a.X % b.X, a.Y % b.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator %(V2i v, int s)\n            => new V2i(v.X % s, v.Y % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator %(int s, V2i v)\n            => new V2i(s % v.X, s % v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator &(V2i a, V2i b)\n            => new V2i(a.X & b.X, a.Y & b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator &(V2i v, int s)\n            => new V2i(v.X & s, v.Y & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator &(int s, V2i v)\n            => new V2i(s & v.X, s & v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator |(V2i a, V2i b)\n            => new V2i(a.X | b.X, a.Y | b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator |(V2i v, int s)\n            => new V2i(v.X | s, v.Y | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator |(int s, V2i v)\n            => new V2i(s | v.X, s | v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator ^(V2i a, V2i b)\n            => new V2i(a.X ^ b.X, a.Y ^ b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator ^(V2i v, int s)\n            => new V2i(v.X ^ s, v.Y ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator ^(int s, V2i v)\n            => new V2i(s ^ v.X, s ^ v.Y);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator <<(V2i v, int s)\n            => new V2i(v.X << s, v.Y << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i operator >>(V2i v, int s)\n            => new V2i(v.X >> s, v.Y >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2i a, V2i b)\n        {\n            return a.X == b.X && a.Y == b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2i v, int s)\n        {\n            return v.X == s && v.Y == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(int s, V2i v)\n        {\n            return s == v.X && s == v.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2i a, V2i b)\n        {\n            return a.X != b.X || a.Y != b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2i v, int s)\n        {\n            return v.X != s || v.Y != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(int s, V2i v)\n        {\n            return s != v.X || s != v.Y;\n        }\n\n        #endregion\n\n        #region IEquatable<V2i> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V2i other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V2i o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V2i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V2i(\n                int.Parse(x[0], CultureInfo.InvariantCulture), \n                int.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V2i Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<int>.Parse, V2i.Setter);\n        }\n\n        public static V2i Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<int>.Parse, V2i.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i OO => new V2i(0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i OI => new V2i(0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i ON => new V2i(0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OX => new V2i(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OY => new V2i(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i IO => new V2i(1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i II => new V2i(1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i PN => new V2i(1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IX => new V2i(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IY => new V2i(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i NO => new V2i(-1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i NP => new V2i(-1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2i NN => new V2i(-1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NX => new V2i(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NY => new V2i(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XO => new V2i(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XI => new V2i(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XN => new V2i(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XX => new V2i(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i XY\n        {\n            readonly get => new V2i(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YO => new V2i(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YI => new V2i(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YN => new V2i(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i YX\n        {\n            readonly get => new V2i(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YY => new V2i(Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOX => new V3i(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOY => new V3i(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIX => new V3i(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIY => new V3i(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONX => new V3i(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONY => new V3i(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXO => new V3i(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXI => new V3i(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXN => new V3i(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXX => new V3i(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXY => new V3i(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYO => new V3i(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYI => new V3i(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYN => new V3i(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYX => new V3i(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYY => new V3i(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOX => new V3i(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOY => new V3i(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIX => new V3i(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIY => new V3i(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNX => new V3i(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNY => new V3i(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXO => new V3i(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXI => new V3i(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PXN => new V3i(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXX => new V3i(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXY => new V3i(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYO => new V3i(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYI => new V3i(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PYN => new V3i(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYX => new V3i(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYY => new V3i(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOX => new V3i(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOY => new V3i(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPX => new V3i(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPY => new V3i(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNX => new V3i(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNY => new V3i(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXO => new V3i(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXP => new V3i(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXN => new V3i(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXX => new V3i(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXY => new V3i(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYO => new V3i(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYP => new V3i(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYN => new V3i(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYX => new V3i(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYY => new V3i(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOO => new V3i(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOI => new V3i(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XON => new V3i(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOX => new V3i(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOY => new V3i(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIO => new V3i(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XII => new V3i(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XPN => new V3i(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIX => new V3i(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIY => new V3i(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNO => new V3i(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNP => new V3i(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNN => new V3i(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNX => new V3i(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNY => new V3i(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXO => new V3i(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXI => new V3i(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXN => new V3i(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXX => new V3i(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXY => new V3i(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYO => new V3i(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYI => new V3i(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYN => new V3i(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYX => new V3i(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYY => new V3i(X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOO => new V3i(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOI => new V3i(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YON => new V3i(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOX => new V3i(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOY => new V3i(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIO => new V3i(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YII => new V3i(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YPN => new V3i(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIX => new V3i(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIY => new V3i(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNO => new V3i(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNP => new V3i(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNN => new V3i(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNX => new V3i(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNY => new V3i(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXO => new V3i(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXI => new V3i(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXN => new V3i(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXX => new V3i(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXY => new V3i(Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYO => new V3i(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYI => new V3i(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYN => new V3i(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYX => new V3i(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYY => new V3i(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOX => new V4i(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOY => new V4i(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIX => new V4i(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIY => new V4i(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONX => new V4i(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONY => new V4i(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXO => new V4i(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXI => new V4i(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXN => new V4i(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXX => new V4i(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXY => new V4i(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYO => new V4i(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYI => new V4i(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYN => new V4i(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYX => new V4i(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYY => new V4i(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOX => new V4i(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOY => new V4i(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIX => new V4i(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIY => new V4i(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNX => new V4i(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNY => new V4i(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXO => new V4i(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXI => new V4i(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPXN => new V4i(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXX => new V4i(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXY => new V4i(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYO => new V4i(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYI => new V4i(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPYN => new V4i(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYX => new V4i(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYY => new V4i(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOX => new V4i(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOY => new V4i(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPX => new V4i(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPY => new V4i(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNX => new V4i(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNY => new V4i(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXO => new V4i(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXP => new V4i(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXN => new V4i(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXX => new V4i(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXY => new V4i(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYO => new V4i(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYP => new V4i(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYN => new V4i(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYX => new V4i(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYY => new V4i(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOO => new V4i(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOI => new V4i(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXON => new V4i(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOX => new V4i(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOY => new V4i(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIO => new V4i(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXII => new V4i(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXPN => new V4i(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIX => new V4i(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIY => new V4i(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNO => new V4i(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNP => new V4i(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNN => new V4i(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNX => new V4i(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNY => new V4i(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXO => new V4i(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXI => new V4i(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXN => new V4i(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXX => new V4i(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXY => new V4i(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYO => new V4i(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYI => new V4i(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYN => new V4i(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYX => new V4i(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYY => new V4i(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOO => new V4i(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOI => new V4i(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYON => new V4i(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOX => new V4i(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOY => new V4i(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIO => new V4i(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYII => new V4i(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYPN => new V4i(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIX => new V4i(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIY => new V4i(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNO => new V4i(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNP => new V4i(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNN => new V4i(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNX => new V4i(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNY => new V4i(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXO => new V4i(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXI => new V4i(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXN => new V4i(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXX => new V4i(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXY => new V4i(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYO => new V4i(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYI => new V4i(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYN => new V4i(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYX => new V4i(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYY => new V4i(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOX => new V4i(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOY => new V4i(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIX => new V4i(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIY => new V4i(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONX => new V4i(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONY => new V4i(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXO => new V4i(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXI => new V4i(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POXN => new V4i(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXX => new V4i(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXY => new V4i(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYO => new V4i(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYI => new V4i(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POYN => new V4i(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYX => new V4i(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYY => new V4i(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOX => new V4i(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOY => new V4i(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIX => new V4i(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIY => new V4i(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNX => new V4i(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNY => new V4i(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXO => new V4i(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXI => new V4i(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPXN => new V4i(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXX => new V4i(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXY => new V4i(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYO => new V4i(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYI => new V4i(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPYN => new V4i(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYX => new V4i(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYY => new V4i(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOX => new V4i(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOY => new V4i(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPX => new V4i(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPY => new V4i(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNX => new V4i(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNY => new V4i(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXO => new V4i(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXP => new V4i(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXN => new V4i(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXX => new V4i(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXY => new V4i(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYO => new V4i(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYP => new V4i(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYN => new V4i(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYX => new V4i(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYY => new V4i(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOO => new V4i(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOI => new V4i(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXON => new V4i(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOX => new V4i(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOY => new V4i(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIO => new V4i(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXII => new V4i(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXPN => new V4i(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIX => new V4i(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIY => new V4i(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNO => new V4i(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNP => new V4i(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNN => new V4i(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNX => new V4i(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNY => new V4i(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXO => new V4i(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXI => new V4i(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXXN => new V4i(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXX => new V4i(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXY => new V4i(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYO => new V4i(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYI => new V4i(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXYN => new V4i(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYX => new V4i(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYY => new V4i(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOO => new V4i(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOI => new V4i(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYON => new V4i(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOX => new V4i(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOY => new V4i(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIO => new V4i(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYII => new V4i(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYPN => new V4i(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIX => new V4i(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIY => new V4i(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNO => new V4i(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNP => new V4i(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNN => new V4i(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNX => new V4i(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNY => new V4i(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXO => new V4i(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXI => new V4i(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYXN => new V4i(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXX => new V4i(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXY => new V4i(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYO => new V4i(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYI => new V4i(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYYN => new V4i(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYX => new V4i(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYY => new V4i(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOX => new V4i(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOY => new V4i(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPX => new V4i(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPY => new V4i(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONX => new V4i(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONY => new V4i(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXO => new V4i(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXP => new V4i(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXN => new V4i(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXX => new V4i(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXY => new V4i(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYO => new V4i(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYP => new V4i(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYN => new V4i(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYX => new V4i(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYY => new V4i(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOX => new V4i(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOY => new V4i(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPX => new V4i(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPY => new V4i(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNX => new V4i(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNY => new V4i(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXO => new V4i(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXP => new V4i(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXN => new V4i(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXX => new V4i(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXY => new V4i(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYO => new V4i(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYP => new V4i(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYN => new V4i(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYX => new V4i(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYY => new V4i(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOX => new V4i(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOY => new V4i(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPX => new V4i(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPY => new V4i(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNX => new V4i(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNY => new V4i(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXO => new V4i(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXP => new V4i(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXN => new V4i(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXX => new V4i(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXY => new V4i(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYO => new V4i(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYP => new V4i(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYN => new V4i(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYX => new V4i(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYY => new V4i(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOO => new V4i(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOP => new V4i(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXON => new V4i(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOX => new V4i(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOY => new V4i(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPO => new V4i(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPP => new V4i(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPN => new V4i(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPX => new V4i(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPY => new V4i(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNO => new V4i(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNP => new V4i(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNN => new V4i(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNX => new V4i(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNY => new V4i(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXO => new V4i(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXP => new V4i(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXN => new V4i(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXX => new V4i(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXY => new V4i(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYO => new V4i(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYP => new V4i(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYN => new V4i(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYX => new V4i(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYY => new V4i(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOO => new V4i(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOP => new V4i(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYON => new V4i(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOX => new V4i(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOY => new V4i(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPO => new V4i(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPP => new V4i(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPN => new V4i(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPX => new V4i(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPY => new V4i(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNO => new V4i(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNP => new V4i(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNN => new V4i(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNX => new V4i(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNY => new V4i(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXO => new V4i(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXP => new V4i(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXN => new V4i(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXX => new V4i(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXY => new V4i(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYO => new V4i(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYP => new V4i(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYN => new V4i(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYX => new V4i(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYY => new V4i(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOO => new V4i(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOI => new V4i(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOON => new V4i(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOX => new V4i(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOY => new V4i(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIO => new V4i(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOII => new V4i(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOPN => new V4i(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIX => new V4i(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIY => new V4i(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONO => new V4i(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONP => new V4i(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONN => new V4i(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONX => new V4i(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONY => new V4i(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXO => new V4i(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXI => new V4i(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXN => new V4i(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXX => new V4i(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXY => new V4i(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYO => new V4i(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYI => new V4i(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYN => new V4i(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYX => new V4i(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYY => new V4i(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOO => new V4i(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOI => new V4i(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPON => new V4i(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOX => new V4i(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOY => new V4i(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIO => new V4i(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIII => new V4i(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPPN => new V4i(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIX => new V4i(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIY => new V4i(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNO => new V4i(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNP => new V4i(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNN => new V4i(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNX => new V4i(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNY => new V4i(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXO => new V4i(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXI => new V4i(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPXN => new V4i(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXX => new V4i(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXY => new V4i(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYO => new V4i(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYI => new V4i(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPYN => new V4i(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYX => new V4i(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYY => new V4i(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOO => new V4i(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOP => new V4i(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNON => new V4i(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOX => new V4i(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOY => new V4i(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPO => new V4i(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPP => new V4i(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPN => new V4i(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPX => new V4i(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPY => new V4i(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNO => new V4i(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNP => new V4i(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNN => new V4i(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNX => new V4i(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNY => new V4i(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXO => new V4i(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXP => new V4i(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXN => new V4i(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXX => new V4i(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXY => new V4i(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYO => new V4i(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYP => new V4i(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYN => new V4i(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYX => new V4i(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYY => new V4i(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOO => new V4i(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOI => new V4i(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXON => new V4i(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOX => new V4i(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOY => new V4i(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIO => new V4i(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXII => new V4i(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXPN => new V4i(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIX => new V4i(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIY => new V4i(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNO => new V4i(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNP => new V4i(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNN => new V4i(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNX => new V4i(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNY => new V4i(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXO => new V4i(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXI => new V4i(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXN => new V4i(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXX => new V4i(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXY => new V4i(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYO => new V4i(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYI => new V4i(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYN => new V4i(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYX => new V4i(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYY => new V4i(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOO => new V4i(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOI => new V4i(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYON => new V4i(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOX => new V4i(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOY => new V4i(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIO => new V4i(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYII => new V4i(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYPN => new V4i(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIX => new V4i(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIY => new V4i(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNO => new V4i(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNP => new V4i(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNN => new V4i(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNX => new V4i(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNY => new V4i(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXO => new V4i(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXI => new V4i(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXN => new V4i(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXX => new V4i(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXY => new V4i(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYO => new V4i(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYI => new V4i(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYN => new V4i(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYX => new V4i(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYY => new V4i(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOO => new V4i(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOI => new V4i(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOON => new V4i(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOX => new V4i(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOY => new V4i(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIO => new V4i(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOII => new V4i(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOPN => new V4i(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIX => new V4i(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIY => new V4i(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONO => new V4i(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONP => new V4i(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONN => new V4i(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONX => new V4i(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONY => new V4i(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXO => new V4i(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXI => new V4i(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXN => new V4i(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXX => new V4i(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXY => new V4i(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYO => new V4i(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYI => new V4i(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYN => new V4i(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYX => new V4i(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYY => new V4i(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOO => new V4i(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOI => new V4i(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPON => new V4i(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOX => new V4i(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOY => new V4i(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIO => new V4i(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIII => new V4i(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPPN => new V4i(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIX => new V4i(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIY => new V4i(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNO => new V4i(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNP => new V4i(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNN => new V4i(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNX => new V4i(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNY => new V4i(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXO => new V4i(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXI => new V4i(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPXN => new V4i(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXX => new V4i(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXY => new V4i(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYO => new V4i(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYI => new V4i(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPYN => new V4i(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYX => new V4i(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYY => new V4i(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOO => new V4i(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOP => new V4i(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNON => new V4i(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOX => new V4i(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOY => new V4i(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPO => new V4i(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPP => new V4i(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPN => new V4i(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPX => new V4i(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPY => new V4i(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNO => new V4i(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNP => new V4i(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNN => new V4i(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNX => new V4i(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNY => new V4i(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXO => new V4i(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXP => new V4i(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXN => new V4i(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXX => new V4i(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXY => new V4i(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYO => new V4i(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYP => new V4i(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYN => new V4i(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYX => new V4i(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYY => new V4i(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOO => new V4i(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOI => new V4i(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXON => new V4i(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOX => new V4i(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOY => new V4i(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIO => new V4i(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXII => new V4i(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXPN => new V4i(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIX => new V4i(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIY => new V4i(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNO => new V4i(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNP => new V4i(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNN => new V4i(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNX => new V4i(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNY => new V4i(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXO => new V4i(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXI => new V4i(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXN => new V4i(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXX => new V4i(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXY => new V4i(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYO => new V4i(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYI => new V4i(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYN => new V4i(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYX => new V4i(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYY => new V4i(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOO => new V4i(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOI => new V4i(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYON => new V4i(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOX => new V4i(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOY => new V4i(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIO => new V4i(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYII => new V4i(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYPN => new V4i(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIX => new V4i(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIY => new V4i(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNO => new V4i(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNP => new V4i(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNN => new V4i(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNX => new V4i(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNY => new V4i(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXO => new V4i(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXI => new V4i(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXN => new V4i(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXX => new V4i(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXY => new V4i(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYO => new V4i(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYI => new V4i(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYN => new V4i(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYX => new V4i(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYY => new V4i(Y, Y, Y, Y);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (int)value; }\n        }\n\n        #endregion\n\n        #region ISize2i Members\n\n        public readonly V2i Size2i { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 2; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (int)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V2iEqualityComparer : IEqualityComparer<V2i>\n    {\n        public static V2iEqualityComparer Default\n            => new V2iEqualityComparer();\n\n        #region IEqualityComparer<V2i> Members\n\n        public bool Equals(V2i v0, V2i v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V2i v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Min(this V2i a, V2i b)\n        {\n            return new V2i(Min(a.X, b.X), Min(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Min(this V2i a, int b)\n        {\n            return new V2i(Min(a.X, b), Min(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Min(this int a, V2i b)\n        {\n            return new V2i(Min(a, b.X), Min(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Max(this V2i a, V2i b)\n        {\n            return new V2i(Max(a.X, b.X), Max(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Max(this V2i a, int b)\n        {\n            return new V2i(Max(a.X, b), Max(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Max(this int a, V2i b)\n        {\n            return new V2i(Max(a, b.X), Max(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Min(this V2i a, V2i b, V2i c)\n        {\n            return new V2i(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Max(this V2i a, V2i b, V2i c)\n        {\n            return new V2i(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Min(this V2i a, V2i b, V2i c, V2i d)\n        {\n            return new V2i(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Max(this V2i a, V2i b, V2i c, V2i d)\n        {\n            return new V2i(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Min(this V2i x, params V2i[] values)\n        {\n            return new V2i(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Max(this V2i x, params V2i[] values)\n        {\n            return new V2i(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Abs(this V2i x)\n        {\n            return new V2i(Abs(x.X), Abs(x.Y));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Clamp(this V2i x, V2i a, V2i b)\n        {\n            return new V2i(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Clamp(this V2i x, int a, int b)\n        {\n            return new V2i(Clamp(x.X, a, b), Clamp(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i ClampExcl(this V2i x, V2i a, V2i b)\n        {\n            return new V2i(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i ClampExcl(this V2i x, int a, int b)\n        {\n            return new V2i(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i ClampWrap(this V2i x, V2i a, V2i b)\n        {\n            return new V2i(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i ClampWrap(this V2i x, int a, int b)\n        {\n            return new V2i(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Saturate(this V2i x)\n        {\n            return new V2i(Saturate(x.X), Saturate(x.Y));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Sign(this V2i x)\n        {\n            return new V2i(Sign(x.X), Sign(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Signumi(this V2i x)\n        {\n            return new V2i(Signumi(x.X), Signumi(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Signum(this V2i x)\n        {\n            return new V2i(Signum(x.X), Signum(x.Y));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i MultiplyAdd(V2i x, V2i y, V2i z)\n        {\n            return new V2i(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i MultiplyAdd(V2i x, int y, V2i z)\n        {\n            return new V2i(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i MultiplyAdd(int x, V2i y, V2i z)\n        {\n            return new V2i(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sqrt(this V2i x)\n        {\n            return new V2d(Sqrt(x.X), Sqrt(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Cbrt(this V2i x)\n        {\n            return new V2d(Cbrt(x.X), Cbrt(x.Y));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Square(this V2i x)\n        {\n            return new V2i(Square(x.X), Square(x.Y));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Pown(this V2i x, V2i y)\n        {\n            return new V2i(Pown(x.X, y.X), Pown(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Pown(this V2i x, int y)\n        {\n            return new V2i(Pown(x.X, y), Pown(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Pown(this int x, V2i y)\n        {\n            return new V2i(Pown(x, y.X), Pown(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this V2i x, V2f y)\n        {\n            return new V2f(Pow(x.X, y.X), Pow(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this V2i x, float y)\n        {\n            return new V2f(Pow(x.X, y), Pow(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this int x, V2f y)\n        {\n            return new V2f(Pow(x, y.X), Pow(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this V2i x, V2d y)\n        {\n            return new V2d(Pow(x.X, y.X), Pow(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this V2i x, double y)\n        {\n            return new V2d(Pow(x.X, y), Pow(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this int x, V2d y)\n        {\n            return new V2d(Pow(x, y.X), Pow(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this V2i x, V2f y)\n        {\n            return new V2f(Power(x.X, y.X), Power(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this V2i x, float y)\n        {\n            return new V2f(Power(x.X, y), Power(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this int x, V2f y)\n        {\n            return new V2f(Power(x, y.X), Power(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this V2i x, V2d y)\n        {\n            return new V2d(Power(x.X, y.X), Power(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this V2i x, double y)\n        {\n            return new V2d(Power(x.X, y), Power(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this int x, V2d y)\n        {\n            return new V2d(Power(x, y.X), Power(x, y.Y));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Exp(this V2i x)\n        {\n            return new V2d(Exp(x.X), Exp(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(this V2i x)\n        {\n            return new V2d(Log(x.X), Log(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log2(this V2i x)\n        {\n            return new V2d(Log2(x.X), Log2(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Log2Int(this V2i x)\n        {\n            return new V2i(Log2Int(x.X), Log2Int(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log10(this V2i x)\n        {\n            return new V2d(Log10(x.X), Log10(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(this V2i x, double basis)\n        {\n            return new V2d(Log(x.X, basis), Log(x.Y, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i ModP(this V2i a, V2i b)\n        {\n            return new V2i(ModP(a.X, b.X), ModP(a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l PowerOfTwo(this V2i x)\n        {\n            return new V2l(PowerOfTwo(x.X), PowerOfTwo(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.NextPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i NextPowerOfTwo(this V2i x)\n        {\n            return new V2i(NextPowerOfTwo(x.X), NextPowerOfTwo(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.PrevPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i PrevPowerOfTwo(this V2i x)\n        {\n            return new V2i(PrevPowerOfTwo(x.X), PrevPowerOfTwo(x.Y));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Step(this V2i x, V2i edge)\n        {\n            return new V2i(Step(x.X, edge.X), Step(x.Y, edge.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Step(this V2i x, int edge)\n        {\n            return new V2i(Step(x.X, edge), Step(x.Y, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Lerp(this float t, V2i a, V2i b)\n        {\n            return new V2i(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Lerp(this V2f t, V2i a, V2i b)\n        {\n            return new V2i(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Lerp(this double t, V2i a, V2i b)\n        {\n            return new V2i(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Lerp(this V2d t, V2i a, V2i b)\n        {\n            return new V2i(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvLerp(this V2i y, V2i a, V2i b)\n        {\n            return new V2d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i GreatestCommonDivisor(this V2i a, V2i b)\n        {\n            return new V2i(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i LeastCommonMultiple(this V2i a, V2i b)\n        {\n            return new V2i(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FloatFromBits(this V2i x)\n        {\n            return new V2f(FloatFromBits(x.X), FloatFromBits(x.Y));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V2i a, V2i b, int tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V2i v, int epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LengthSquared(V2i v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V2i v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Normalized(V2i v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Norm1(V2i v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V2i v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMax(V2i v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMin(V2i v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V2i v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceSquared(this V2i a, V2i b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V2i a, V2i b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Distance1(this V2i a, V2i b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V2i a, V2i b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceMax(this V2i a, V2i b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceMin(this V2i a, V2i b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V2i query, V2i p0, V2i p1)\n        {\n            return DistanceToLine((V2d) query, (V2d) p0, (V2d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V2i query, V2i p0, V2i p1)\n        {\n            return DistanceToInfiniteLine((V2d) query, (V2d) p0, (V2d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V2i query, V2i p0, V2i p1, out double t)\n        {\n            return DistanceToLine((V2d) query, (V2d) p0, (V2d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V2i query, V2i p0, V2i p1, out double t)\n        {\n            return DistanceToInfiniteLine((V2d) query, (V2d) p0, (V2d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns a vector that is orthogonal to the given one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Orthogonal(V2i v)\n            => v.Orthogonal;\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V2i v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 2x2 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22i Outer(this V2i a, V2i b)\n        {\n            return new M22i(\n                        a.X * b.X, a.X * b.Y, \n                        a.Y * b.X, a.Y * b.Y);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Dot(this V2i a, V2i b)\n        {\n            return a.X * b.X + a.Y * b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V2i v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the cross product of vector a.\n        /// In 2D the cross product is simply a vector that is normal\n        /// to the given vector (i.e. {x,y} -> {-y,x})\n        /// </summary>\n        public static V2i Cross(this V2i a)\n        {\n            return new V2i(-a.Y, a.X);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2i a, V2i b)\n        {\n            return (a.X < b.X && a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2i v, int s)\n        {\n            return (v.X < s && v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(int s, V2i v)\n        {\n            return (s < v.X && s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2i a, V2i b)\n        {\n            return (a.X < b.X || a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2i v, int s)\n        {\n            return (v.X < s || v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(int s, V2i v)\n        {\n            return (s < v.X || s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2i a, V2i b)\n        {\n            return (a.X > b.X && a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2i v, int s)\n        {\n            return (v.X > s && v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(int s, V2i v)\n        {\n            return (s > v.X && s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2i a, V2i b)\n        {\n            return (a.X > b.X || a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2i v, int s)\n        {\n            return (v.X > s || v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(int s, V2i v)\n        {\n            return (s > v.X || s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2i a, V2i b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2i v, int s)\n        {\n            return (v.X <= s && v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(int s, V2i v)\n        {\n            return (s <= v.X && s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2i a, V2i b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2i v, int s)\n        {\n            return (v.X <= s || v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(int s, V2i v)\n        {\n            return (s <= v.X || s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2i a, V2i b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2i v, int s)\n        {\n            return (v.X >= s && v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(int s, V2i v)\n        {\n            return (s >= v.X && s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2i a, V2i b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2i v, int s)\n        {\n            return (v.X >= s || v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(int s, V2i v)\n        {\n            return (s >= v.X || s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2i a, V2i b)\n        {\n            return (a.X == b.X && a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2i v, int s)\n        {\n            return (v.X == s && v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(int s, V2i v)\n        {\n            return (s == v.X && s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2i a, V2i b)\n        {\n            return (a.X == b.X || a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2i v, int s)\n        {\n            return (v.X == s || v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(int s, V2i v)\n        {\n            return (s == v.X || s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2i a, V2i b)\n        {\n            return (a.X != b.X && a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2i v, int s)\n        {\n            return (v.X != s && v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(int s, V2i v)\n        {\n            return (s != v.X && s != v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2i a, V2i b)\n        {\n            return (a.X != b.X || a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2i v, int s)\n        {\n            return (v.X != s || v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(int s, V2i v)\n        {\n            return (s != v.X || s != v.Y);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V2i v0, V2i v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V2i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MinElement(V2i v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V2i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MaxElement(V2i v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V2i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V2i v, int epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V2i v, int epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V2i[] pointArray, V2i point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V2i[] array, int start, int count,\n                V2i point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V2i> pointSelector, V2i point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V2i[] pointArray, V2i point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V2i[] array, long start, long count,\n                V2i point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V2i> pointSelector, V2i point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V2i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V2i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V2i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V2i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V2i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V2i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V2i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V2i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V2i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V2i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V2i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V2i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static int[] CopyCoord(this V2i[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV2iExtensions\n    {\n        #region IRandomUniform extensions for V2i\n\n        /// <summary>\n        /// Uses UniformInt() to generate the elements of a V2i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i UniformV2i(this IRandomUniform rnd)\n        {\n            return new V2i(rnd.UniformInt(), rnd.UniformInt());\n        }\n\n        /// <summary>\n        /// Uses UniformIntNonZero() to generate the elements of a V2i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i UniformV2iNonZero(this IRandomUniform rnd)\n        {\n            return new V2i(rnd.UniformIntNonZero(), rnd.UniformIntNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of a V2i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i UniformV2i(this IRandomUniform rnd, int size)\n        {\n            return new V2i(rnd.UniformInt(size), rnd.UniformInt(size));\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of a V2i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i UniformV2i(this IRandomUniform rnd, V2i size)\n        {\n            return new V2i(rnd.UniformInt(size.X), rnd.UniformInt(size.Y));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V2ui\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V2ui : IVector<double>, ISize2ui, IFormattable, IEquatable<V2ui>\n    {\n        [DataMember]\n        public uint X;\n        [DataMember]\n        public uint Y;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(int x, int y)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(int v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(int[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(int[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(uint x, uint y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(uint v)\n        {\n            X = v;\n            Y = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(uint[] a)\n        {\n            X = a[0];\n            Y = a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(uint[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(long x, long y)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(long v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(long[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(long[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(float x, float y)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(float v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(float[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(float[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(double x, double y)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(double v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(double[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(double[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(Func<int, uint> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;uint&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 2.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(IVector<double> v)\n            : this(v[0], v[1])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V2i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V2ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V2l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V2f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V2d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V3i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V3ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V3l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V3f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V3d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V4i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V4ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V4l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V4f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2ui(V4d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V2i v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V2l v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V2f v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V2d v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V3i v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V3ui v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V3l v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V3f v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V3d v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V4i v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V4ui v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V4l v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V4f v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(V4d v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V2ui v)\n            => new int[] { (int)v.X, (int)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(int[] v)\n            => new V2ui((uint)v[0], (uint)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V2ui v)\n            => new uint[] { v.X, v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(uint[] v)\n            => new V2ui(v[0], v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V2ui v)\n            => new long[] { (long)v.X, (long)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(long[] v)\n            => new V2ui((uint)v[0], (uint)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V2ui v)\n            => new float[] { (float)v.X, (float)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(float[] v)\n            => new V2ui((uint)v[0], (uint)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V2ui v)\n            => new double[] { (double)v.X, (double)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2ui(double[] v)\n            => new V2ui((uint)v[0], (uint)v[1]);\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<uint, int> element_fun)\n            => new V2i(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<uint, int, int> element_index_fun)\n            => new V2i(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<uint, uint> element_fun)\n            => new V2ui(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<uint, int, uint> element_index_fun)\n            => new V2ui(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<uint, long> element_fun)\n            => new V2l(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<uint, int, long> element_index_fun)\n            => new V2l(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<uint, float> element_fun)\n            => new V2f(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<uint, int, float> element_index_fun)\n            => new V2f(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<uint, double> element_fun)\n            => new V2d(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<uint, int, double> element_index_fun)\n            => new V2d(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly uint[] ToArray()\n            => new uint[] { X, Y };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<uint> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe uint this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (uint* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (uint* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly uint MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly uint MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 2;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V2ui Zero\n        {\n            get { return new V2ui(0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V2ui One\n        {\n            get { return new V2ui(1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V2ui MaxValue\n        {\n            get { return new V2ui(Constant<uint>.ParseableMaxValue, Constant<uint>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V2ui MinValue\n        {\n            get { return new V2ui(Constant<uint>.ParseableMinValue, Constant<uint>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V2ui XAxis\n        {\n            get { return new V2ui(1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V2ui YAxis\n        {\n            get { return new V2ui(0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V2ui, uint>[] SelectorArray =\n            new Func<V2ui, uint>[] { v => v.X, v => v.Y };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V2ui, int, uint> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V2ui, int, uint> Setter =\n            (ref V2ui v, int i, uint s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V2ui, long, uint> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V2ui, long, uint> LongSetter =\n            (ref V2ui v, long i, uint s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui FromV2i(V2i v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui FromV2l(V2l v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui FromV2f(V2f v)\n            => new V2ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui FromV2d(V2d v)\n            => new V2ui(v);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly uint LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly uint Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X + Y; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly uint NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(X, Y); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly uint NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(X, Y); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V2d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V2d.Zero;\n                s = 1 / s;\n                return new V2d(X * s, Y * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui LinearInterp(float t, V2ui a, V2ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui LinearInterp(V2f t, V2ui a, V2ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui LinearInterp(double t, V2ui a, V2ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui LinearInterp(V2d t, V2ui a, V2ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Min(V2ui v0, V2ui v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Min(V2ui v, uint x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Max(V2ui v0, V2ui v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Max(V2ui v, uint x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Saturate(V2ui v)\n            => Fun.Saturate(v);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n        }\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator ~(V2ui v)\n            => new V2ui(~v.X, ~v.Y);\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator +(V2ui a, V2ui b)\n            => new V2ui(a.X + b.X, a.Y + b.Y);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator +(V2ui v, uint s)\n            => new V2ui(v.X + s, v.Y + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator +(uint s, V2ui v)\n            => new V2ui(s + v.X, s + v.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator -(V2ui a, V2ui b)\n            => new V2ui(a.X - b.X, a.Y - b.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator -(V2ui v, uint s)\n            => new V2ui(v.X - s, v.Y - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator -(uint s, V2ui v)\n            => new V2ui(s - v.X, s - v.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator *(V2ui a, V2ui b)\n            => new V2ui(a.X * b.X, a.Y * b.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator *(V2ui v, uint s)\n            => new V2ui(v.X * s, v.Y * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator *(uint s, V2ui v)\n            => new V2ui(s * v.X, s * v.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator /(V2ui a, V2ui b)\n            => new V2ui(a.X / b.X, a.Y / b.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator /(V2ui v, uint s)\n            => new V2ui(v.X / s, v.Y / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator /(uint s, V2ui v)\n            => new V2ui(s / v.X, s / v.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator %(V2ui a, V2ui b)\n            => new V2ui(a.X % b.X, a.Y % b.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator %(V2ui v, uint s)\n            => new V2ui(v.X % s, v.Y % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator %(uint s, V2ui v)\n            => new V2ui(s % v.X, s % v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator &(V2ui a, V2ui b)\n            => new V2ui(a.X & b.X, a.Y & b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator &(V2ui v, uint s)\n            => new V2ui(v.X & s, v.Y & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator &(uint s, V2ui v)\n            => new V2ui(s & v.X, s & v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator |(V2ui a, V2ui b)\n            => new V2ui(a.X | b.X, a.Y | b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator |(V2ui v, uint s)\n            => new V2ui(v.X | s, v.Y | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator |(uint s, V2ui v)\n            => new V2ui(s | v.X, s | v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator ^(V2ui a, V2ui b)\n            => new V2ui(a.X ^ b.X, a.Y ^ b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator ^(V2ui v, uint s)\n            => new V2ui(v.X ^ s, v.Y ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator ^(uint s, V2ui v)\n            => new V2ui(s ^ v.X, s ^ v.Y);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator <<(V2ui v, int s)\n            => new V2ui(v.X << s, v.Y << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui operator >>(V2ui v, int s)\n            => new V2ui(v.X >> s, v.Y >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2ui a, V2ui b)\n        {\n            return a.X == b.X && a.Y == b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2ui v, uint s)\n        {\n            return v.X == s && v.Y == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(uint s, V2ui v)\n        {\n            return s == v.X && s == v.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2ui a, V2ui b)\n        {\n            return a.X != b.X || a.Y != b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2ui v, uint s)\n        {\n            return v.X != s || v.Y != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(uint s, V2ui v)\n        {\n            return s != v.X || s != v.Y;\n        }\n\n        #endregion\n\n        #region IEquatable<V2ui> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V2ui other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V2ui o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V2ui Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V2ui(\n                uint.Parse(x[0], CultureInfo.InvariantCulture), \n                uint.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V2ui Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<uint>.Parse, V2ui.Setter);\n        }\n\n        public static V2ui Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<uint>.Parse, V2ui.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2ui OO => new V2ui(0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2ui OI => new V2ui(0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OX => new V2ui(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OY => new V2ui(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2ui IO => new V2ui(1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2ui II => new V2ui(1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IX => new V2ui(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IY => new V2ui(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XO => new V2ui(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XI => new V2ui(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XX => new V2ui(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui XY\n        {\n            readonly get => new V2ui(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YO => new V2ui(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YI => new V2ui(Y, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui YX\n        {\n            readonly get => new V2ui(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YY => new V2ui(Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOX => new V3ui(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOY => new V3ui(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIX => new V3ui(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIY => new V3ui(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXO => new V3ui(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXI => new V3ui(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXX => new V3ui(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXY => new V3ui(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYO => new V3ui(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYI => new V3ui(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYX => new V3ui(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYY => new V3ui(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOX => new V3ui(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOY => new V3ui(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIX => new V3ui(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIY => new V3ui(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXO => new V3ui(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXI => new V3ui(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXX => new V3ui(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXY => new V3ui(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYO => new V3ui(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYI => new V3ui(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYX => new V3ui(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYY => new V3ui(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOO => new V3ui(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOI => new V3ui(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOX => new V3ui(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOY => new V3ui(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIO => new V3ui(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XII => new V3ui(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIX => new V3ui(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIY => new V3ui(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXO => new V3ui(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXI => new V3ui(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXX => new V3ui(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXY => new V3ui(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYO => new V3ui(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYI => new V3ui(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYX => new V3ui(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYY => new V3ui(X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOO => new V3ui(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOI => new V3ui(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOX => new V3ui(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOY => new V3ui(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIO => new V3ui(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YII => new V3ui(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIX => new V3ui(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIY => new V3ui(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXO => new V3ui(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXI => new V3ui(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXX => new V3ui(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXY => new V3ui(Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYO => new V3ui(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYI => new V3ui(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYX => new V3ui(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYY => new V3ui(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOX => new V4ui(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOY => new V4ui(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIX => new V4ui(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIY => new V4ui(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXO => new V4ui(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXI => new V4ui(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXX => new V4ui(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXY => new V4ui(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYO => new V4ui(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYI => new V4ui(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYX => new V4ui(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYY => new V4ui(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOX => new V4ui(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOY => new V4ui(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIX => new V4ui(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIY => new V4ui(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXO => new V4ui(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXI => new V4ui(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXX => new V4ui(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXY => new V4ui(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYO => new V4ui(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYI => new V4ui(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYX => new V4ui(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYY => new V4ui(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOO => new V4ui(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOI => new V4ui(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOX => new V4ui(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOY => new V4ui(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIO => new V4ui(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXII => new V4ui(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIX => new V4ui(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIY => new V4ui(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXO => new V4ui(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXI => new V4ui(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXX => new V4ui(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXY => new V4ui(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYO => new V4ui(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYI => new V4ui(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYX => new V4ui(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYY => new V4ui(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOO => new V4ui(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOI => new V4ui(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOX => new V4ui(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOY => new V4ui(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIO => new V4ui(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYII => new V4ui(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIX => new V4ui(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIY => new V4ui(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXO => new V4ui(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXI => new V4ui(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXX => new V4ui(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXY => new V4ui(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYO => new V4ui(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYI => new V4ui(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYX => new V4ui(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYY => new V4ui(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOX => new V4ui(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOY => new V4ui(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIX => new V4ui(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIY => new V4ui(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXO => new V4ui(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXI => new V4ui(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXX => new V4ui(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXY => new V4ui(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYO => new V4ui(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYI => new V4ui(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYX => new V4ui(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYY => new V4ui(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOX => new V4ui(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOY => new V4ui(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIX => new V4ui(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIY => new V4ui(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXO => new V4ui(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXI => new V4ui(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXX => new V4ui(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXY => new V4ui(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYO => new V4ui(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYI => new V4ui(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYX => new V4ui(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYY => new V4ui(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOO => new V4ui(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOI => new V4ui(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOX => new V4ui(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOY => new V4ui(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIO => new V4ui(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXII => new V4ui(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIX => new V4ui(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIY => new V4ui(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXO => new V4ui(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXI => new V4ui(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXX => new V4ui(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXY => new V4ui(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYO => new V4ui(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYI => new V4ui(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYX => new V4ui(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYY => new V4ui(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOO => new V4ui(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOI => new V4ui(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOX => new V4ui(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOY => new V4ui(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIO => new V4ui(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYII => new V4ui(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIX => new V4ui(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIY => new V4ui(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXO => new V4ui(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXI => new V4ui(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXX => new V4ui(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXY => new V4ui(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYO => new V4ui(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYI => new V4ui(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYX => new V4ui(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYY => new V4ui(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOO => new V4ui(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOI => new V4ui(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOX => new V4ui(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOY => new V4ui(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIO => new V4ui(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOII => new V4ui(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIX => new V4ui(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIY => new V4ui(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXO => new V4ui(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXI => new V4ui(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXX => new V4ui(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXY => new V4ui(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYO => new V4ui(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYI => new V4ui(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYX => new V4ui(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYY => new V4ui(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOO => new V4ui(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOI => new V4ui(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOX => new V4ui(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOY => new V4ui(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIO => new V4ui(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIII => new V4ui(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIX => new V4ui(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIY => new V4ui(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXO => new V4ui(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXI => new V4ui(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXX => new V4ui(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXY => new V4ui(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYO => new V4ui(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYI => new V4ui(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYX => new V4ui(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYY => new V4ui(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOO => new V4ui(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOI => new V4ui(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOX => new V4ui(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOY => new V4ui(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIO => new V4ui(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXII => new V4ui(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIX => new V4ui(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIY => new V4ui(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXO => new V4ui(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXI => new V4ui(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXX => new V4ui(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXY => new V4ui(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYO => new V4ui(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYI => new V4ui(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYX => new V4ui(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYY => new V4ui(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOO => new V4ui(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOI => new V4ui(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOX => new V4ui(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOY => new V4ui(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIO => new V4ui(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYII => new V4ui(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIX => new V4ui(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIY => new V4ui(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXO => new V4ui(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXI => new V4ui(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXX => new V4ui(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXY => new V4ui(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYO => new V4ui(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYI => new V4ui(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYX => new V4ui(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYY => new V4ui(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOO => new V4ui(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOI => new V4ui(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOX => new V4ui(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOY => new V4ui(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIO => new V4ui(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOII => new V4ui(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIX => new V4ui(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIY => new V4ui(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXO => new V4ui(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXI => new V4ui(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXX => new V4ui(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXY => new V4ui(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYO => new V4ui(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYI => new V4ui(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYX => new V4ui(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYY => new V4ui(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOO => new V4ui(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOI => new V4ui(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOX => new V4ui(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOY => new V4ui(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIO => new V4ui(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIII => new V4ui(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIX => new V4ui(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIY => new V4ui(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXO => new V4ui(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXI => new V4ui(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXX => new V4ui(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXY => new V4ui(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYO => new V4ui(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYI => new V4ui(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYX => new V4ui(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYY => new V4ui(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOO => new V4ui(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOI => new V4ui(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOX => new V4ui(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOY => new V4ui(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIO => new V4ui(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXII => new V4ui(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIX => new V4ui(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIY => new V4ui(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXO => new V4ui(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXI => new V4ui(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXX => new V4ui(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXY => new V4ui(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYO => new V4ui(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYI => new V4ui(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYX => new V4ui(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYY => new V4ui(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOO => new V4ui(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOI => new V4ui(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOX => new V4ui(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOY => new V4ui(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIO => new V4ui(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYII => new V4ui(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIX => new V4ui(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIY => new V4ui(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXO => new V4ui(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXI => new V4ui(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXX => new V4ui(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXY => new V4ui(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYO => new V4ui(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYI => new V4ui(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYX => new V4ui(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYY => new V4ui(Y, Y, Y, Y);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (uint)value; }\n        }\n\n        #endregion\n\n        #region ISize2ui Members\n\n        public readonly V2ui Size2ui { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 2; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (uint)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V2uiEqualityComparer : IEqualityComparer<V2ui>\n    {\n        public static V2uiEqualityComparer Default\n            => new V2uiEqualityComparer();\n\n        #region IEqualityComparer<V2ui> Members\n\n        public bool Equals(V2ui v0, V2ui v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V2ui v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Min(this V2ui a, V2ui b)\n        {\n            return new V2ui(Min(a.X, b.X), Min(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Min(this V2ui a, uint b)\n        {\n            return new V2ui(Min(a.X, b), Min(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Min(this uint a, V2ui b)\n        {\n            return new V2ui(Min(a, b.X), Min(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Max(this V2ui a, V2ui b)\n        {\n            return new V2ui(Max(a.X, b.X), Max(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Max(this V2ui a, uint b)\n        {\n            return new V2ui(Max(a.X, b), Max(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Max(this uint a, V2ui b)\n        {\n            return new V2ui(Max(a, b.X), Max(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Min(this V2ui a, V2ui b, V2ui c)\n        {\n            return new V2ui(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Max(this V2ui a, V2ui b, V2ui c)\n        {\n            return new V2ui(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Min(this V2ui a, V2ui b, V2ui c, V2ui d)\n        {\n            return new V2ui(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Max(this V2ui a, V2ui b, V2ui c, V2ui d)\n        {\n            return new V2ui(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Min(this V2ui x, params V2ui[] values)\n        {\n            return new V2ui(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Max(this V2ui x, params V2ui[] values)\n        {\n            return new V2ui(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Clamp(this V2ui x, V2ui a, V2ui b)\n        {\n            return new V2ui(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Clamp(this V2ui x, uint a, uint b)\n        {\n            return new V2ui(Clamp(x.X, a, b), Clamp(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui ClampExcl(this V2ui x, V2ui a, V2ui b)\n        {\n            return new V2ui(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui ClampExcl(this V2ui x, uint a, uint b)\n        {\n            return new V2ui(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui ClampWrap(this V2ui x, V2ui a, V2ui b)\n        {\n            return new V2ui(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui ClampWrap(this V2ui x, uint a, uint b)\n        {\n            return new V2ui(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Saturate(this V2ui x)\n        {\n            return new V2ui(Saturate(x.X), Saturate(x.Y));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui MultiplyAdd(V2ui x, V2ui y, V2ui z)\n        {\n            return new V2ui(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui MultiplyAdd(V2ui x, uint y, V2ui z)\n        {\n            return new V2ui(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui MultiplyAdd(uint x, V2ui y, V2ui z)\n        {\n            return new V2ui(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sqrt(this V2ui x)\n        {\n            return new V2d(Sqrt(x.X), Sqrt(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Cbrt(this V2ui x)\n        {\n            return new V2d(Cbrt(x.X), Cbrt(x.Y));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Square(this V2ui x)\n        {\n            return new V2ui(Square(x.X), Square(x.Y));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Pown(this V2ui x, V2ui y)\n        {\n            return new V2ui(Pown(x.X, y.X), Pown(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Pown(this V2ui x, uint y)\n        {\n            return new V2ui(Pown(x.X, y), Pown(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Pown(this uint x, V2ui y)\n        {\n            return new V2ui(Pown(x, y.X), Pown(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Pown(this V2ui x, V2i y)\n        {\n            return new V2ui(Pown(x.X, y.X), Pown(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Pown(this V2ui x, int y)\n        {\n            return new V2ui(Pown(x.X, y), Pown(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Pown(this uint x, V2i y)\n        {\n            return new V2ui(Pown(x, y.X), Pown(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this V2ui x, V2f y)\n        {\n            return new V2f(Pow(x.X, y.X), Pow(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this V2ui x, float y)\n        {\n            return new V2f(Pow(x.X, y), Pow(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this uint x, V2f y)\n        {\n            return new V2f(Pow(x, y.X), Pow(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this V2ui x, V2d y)\n        {\n            return new V2d(Pow(x.X, y.X), Pow(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this V2ui x, double y)\n        {\n            return new V2d(Pow(x.X, y), Pow(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this uint x, V2d y)\n        {\n            return new V2d(Pow(x, y.X), Pow(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this V2ui x, V2f y)\n        {\n            return new V2f(Power(x.X, y.X), Power(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this V2ui x, float y)\n        {\n            return new V2f(Power(x.X, y), Power(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this uint x, V2f y)\n        {\n            return new V2f(Power(x, y.X), Power(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this V2ui x, V2d y)\n        {\n            return new V2d(Power(x.X, y.X), Power(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this V2ui x, double y)\n        {\n            return new V2d(Power(x.X, y), Power(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this uint x, V2d y)\n        {\n            return new V2d(Power(x, y.X), Power(x, y.Y));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Exp(this V2ui x)\n        {\n            return new V2d(Exp(x.X), Exp(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(this V2ui x)\n        {\n            return new V2d(Log(x.X), Log(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log2(this V2ui x)\n        {\n            return new V2d(Log2(x.X), Log2(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Log2Int(this V2ui x)\n        {\n            return new V2i(Log2Int(x.X), Log2Int(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log10(this V2ui x)\n        {\n            return new V2d(Log10(x.X), Log10(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(this V2ui x, double basis)\n        {\n            return new V2d(Log(x.X, basis), Log(x.Y, basis));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Step(this V2ui x, V2ui edge)\n        {\n            return new V2ui(Step(x.X, edge.X), Step(x.Y, edge.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Step(this V2ui x, uint edge)\n        {\n            return new V2ui(Step(x.X, edge), Step(x.Y, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Lerp(this float t, V2ui a, V2ui b)\n        {\n            return new V2ui(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Lerp(this V2f t, V2ui a, V2ui b)\n        {\n            return new V2ui(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Lerp(this double t, V2ui a, V2ui b)\n        {\n            return new V2ui(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui Lerp(this V2d t, V2ui a, V2ui b)\n        {\n            return new V2ui(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvLerp(this V2ui y, V2ui a, V2ui b)\n        {\n            return new V2d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui GreatestCommonDivisor(this V2ui a, V2ui b)\n        {\n            return new V2ui(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui LeastCommonMultiple(this V2ui a, V2ui b)\n        {\n            return new V2ui(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromUnsignedBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FloatFromUnsignedBits(this V2ui x)\n        {\n            return new V2f(FloatFromUnsignedBits(x.X), FloatFromUnsignedBits(x.Y));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V2ui a, V2ui b, uint tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V2ui v, uint epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint LengthSquared(V2ui v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V2ui v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Normalized(V2ui v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Norm1(V2ui v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V2ui v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint NormMax(V2ui v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint NormMin(V2ui v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V2ui v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceSquared(this V2ui a, V2ui b)\n            => Fun.Square((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)) + Fun.Square((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y));\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V2ui a, V2ui b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Distance1(this V2ui a, V2ui b)\n            => ((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)) + ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y));\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V2ui a, V2ui b, double p)\n            => (((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)).Pow(p) + ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceMax(this V2ui a, V2ui b)\n            => Fun.Max(((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)), ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceMin(this V2ui a, V2ui b)\n            => Fun.Min(((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)), ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V2ui query, V2ui p0, V2ui p1)\n        {\n            return DistanceToLine((V2d) query, (V2d) p0, (V2d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V2ui query, V2ui p0, V2ui p1)\n        {\n            return DistanceToInfiniteLine((V2d) query, (V2d) p0, (V2d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V2ui query, V2ui p0, V2ui p1, out double t)\n        {\n            return DistanceToLine((V2d) query, (V2d) p0, (V2d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V2ui query, V2ui p0, V2ui p1, out double t)\n        {\n            return DistanceToInfiniteLine((V2d) query, (V2d) p0, (V2d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Dot(this V2ui a, V2ui b)\n        {\n            return a.X * b.X + a.Y * b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V2ui v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            return flags;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2ui a, V2ui b)\n        {\n            return (a.X < b.X && a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2ui v, uint s)\n        {\n            return (v.X < s && v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(uint s, V2ui v)\n        {\n            return (s < v.X && s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2ui a, V2ui b)\n        {\n            return (a.X < b.X || a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2ui v, uint s)\n        {\n            return (v.X < s || v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(uint s, V2ui v)\n        {\n            return (s < v.X || s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2ui a, V2ui b)\n        {\n            return (a.X > b.X && a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2ui v, uint s)\n        {\n            return (v.X > s && v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(uint s, V2ui v)\n        {\n            return (s > v.X && s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2ui a, V2ui b)\n        {\n            return (a.X > b.X || a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2ui v, uint s)\n        {\n            return (v.X > s || v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(uint s, V2ui v)\n        {\n            return (s > v.X || s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2ui a, V2ui b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2ui v, uint s)\n        {\n            return (v.X <= s && v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(uint s, V2ui v)\n        {\n            return (s <= v.X && s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2ui a, V2ui b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2ui v, uint s)\n        {\n            return (v.X <= s || v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(uint s, V2ui v)\n        {\n            return (s <= v.X || s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2ui a, V2ui b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2ui v, uint s)\n        {\n            return (v.X >= s && v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(uint s, V2ui v)\n        {\n            return (s >= v.X && s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2ui a, V2ui b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2ui v, uint s)\n        {\n            return (v.X >= s || v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(uint s, V2ui v)\n        {\n            return (s >= v.X || s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2ui a, V2ui b)\n        {\n            return (a.X == b.X && a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2ui v, uint s)\n        {\n            return (v.X == s && v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(uint s, V2ui v)\n        {\n            return (s == v.X && s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2ui a, V2ui b)\n        {\n            return (a.X == b.X || a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2ui v, uint s)\n        {\n            return (v.X == s || v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(uint s, V2ui v)\n        {\n            return (s == v.X || s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2ui a, V2ui b)\n        {\n            return (a.X != b.X && a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2ui v, uint s)\n        {\n            return (v.X != s && v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(uint s, V2ui v)\n        {\n            return (s != v.X && s != v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2ui a, V2ui b)\n        {\n            return (a.X != b.X || a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2ui v, uint s)\n        {\n            return (v.X != s || v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(uint s, V2ui v)\n        {\n            return (s != v.X || s != v.Y);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V2ui v0, V2ui v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V2ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint MinElement(V2ui v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V2ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint MaxElement(V2ui v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V2ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V2ui v, uint epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V2ui v, uint epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V2ui[] pointArray, V2ui point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V2ui[] array, int start, int count,\n                V2ui point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V2ui> pointSelector, V2ui point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V2ui[] pointArray, V2ui point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V2ui[] array, long start, long count,\n                V2ui point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V2ui> pointSelector, V2ui point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V2ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V2ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V2ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V2ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V2ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V2ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V2ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V2ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V2ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V2ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V2ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V2ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static uint[] CopyCoord(this V2ui[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV2uiExtensions\n    {\n        #region IRandomUniform extensions for V2ui\n\n        /// <summary>\n        /// Uses UniformUInt() to generate the elements of a V2ui vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui UniformV2ui(this IRandomUniform rnd)\n        {\n            return new V2ui(rnd.UniformUInt(), rnd.UniformUInt());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V2l\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V2l : IVector<double>, ISize2l, IFormattable, IEquatable<V2l>\n    {\n        [DataMember]\n        public long X;\n        [DataMember]\n        public long Y;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(int x, int y)\n        {\n            X = (long)x;\n            Y = (long)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(int v)\n        {\n            X = (long)v;\n            Y = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(int[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(int[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(uint x, uint y)\n        {\n            X = (long)x;\n            Y = (long)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(uint v)\n        {\n            X = (long)v;\n            Y = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(uint[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(uint[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(long x, long y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(long v)\n        {\n            X = v;\n            Y = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(long[] a)\n        {\n            X = a[0];\n            Y = a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(long[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(float x, float y)\n        {\n            X = (long)x;\n            Y = (long)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(float v)\n        {\n            X = (long)v;\n            Y = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(float[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(float[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(double x, double y)\n        {\n            X = (long)x;\n            Y = (long)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(double v)\n        {\n            X = (long)v;\n            Y = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(double[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(double[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(Func<int, long> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;long&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 2.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(IVector<double> v)\n            : this(v[0], v[1])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V2i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V2ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V2l v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V2f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V2d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V3i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V3ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V3l v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V3f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V3d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V4i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V4ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V4l v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V4f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2l(V4d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V2i v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V2ui v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V2f v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V2d v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V3i v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V3ui v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V3l v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V3f v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V3d v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V4i v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V4ui v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V4l v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V4f v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(V4d v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V2l v)\n            => new int[] { (int)v.X, (int)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(int[] v)\n            => new V2l((long)v[0], (long)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V2l v)\n            => new uint[] { (uint)v.X, (uint)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(uint[] v)\n            => new V2l((long)v[0], (long)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V2l v)\n            => new long[] { v.X, v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(long[] v)\n            => new V2l(v[0], v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V2l v)\n            => new float[] { (float)v.X, (float)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(float[] v)\n            => new V2l((long)v[0], (long)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V2l v)\n            => new double[] { (double)v.X, (double)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2l(double[] v)\n            => new V2l((long)v[0], (long)v[1]);\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<long, int> element_fun)\n            => new V2i(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<long, int, int> element_index_fun)\n            => new V2i(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<long, uint> element_fun)\n            => new V2ui(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<long, int, uint> element_index_fun)\n            => new V2ui(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<long, long> element_fun)\n            => new V2l(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<long, int, long> element_index_fun)\n            => new V2l(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<long, float> element_fun)\n            => new V2f(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<long, int, float> element_index_fun)\n            => new V2f(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<long, double> element_fun)\n            => new V2d(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<long, int, double> element_index_fun)\n            => new V2d(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<long, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<long, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly long[] ToArray()\n            => new long[] { X, Y };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe long this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly long MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly long MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 2;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V2l Zero\n        {\n            get { return new V2l(0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V2l One\n        {\n            get { return new V2l(1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V2l MaxValue\n        {\n            get { return new V2l(Constant<long>.ParseableMaxValue, Constant<long>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V2l MinValue\n        {\n            get { return new V2l(Constant<long>.ParseableMinValue, Constant<long>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V2l XAxis\n        {\n            get { return new V2l(1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V2l YAxis\n        {\n            get { return new V2l(0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V2l, long>[] SelectorArray =\n            new Func<V2l, long>[] { v => v.X, v => v.Y };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V2l, int, long> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V2l, int, long> Setter =\n            (ref V2l v, int i, long s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V2l, long, long> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V2l, long, long> LongSetter =\n            (ref V2l v, long i, long s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l FromV2i(V2i v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l FromV2ui(V2ui v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l FromV2f(V2f v)\n            => new V2l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l FromV2d(V2d v)\n            => new V2l(v);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly long LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly long Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly long NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly long NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V2d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V2d.Zero;\n                s = 1 / s;\n                return new V2d(X * s, Y * s);\n            }\n        }\n\n        /// <summary>\n        /// Vector rotated 90° counter clockwise: (-Y, X)\n        /// </summary>\n        public readonly V2l Rot90\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2l(-Y, X); }\n        }\n\n        /// <summary>\n        /// Vector rotated 180° counter clockwise: (-X, -Y)\n        /// </summary>\n        public readonly V2l Rot180\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2l(-X, -Y); }\n        }\n\n        /// <summary>\n        /// Vector rotated 270° counter clockwise: (Y, -X)\n        /// </summary>\n        public readonly V2l Rot270\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2l(Y, -X); }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Abs(V2l v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l LinearInterp(float t, V2l a, V2l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l LinearInterp(V2f t, V2l a, V2l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l LinearInterp(double t, V2l a, V2l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l LinearInterp(V2d t, V2l a, V2l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Min(V2l v0, V2l v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Min(V2l v, long x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Max(V2l v0, V2l v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Max(V2l v, long x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Saturate(V2l v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l DivideByInt(V2l v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y)\n        {\n            X = (long)x;\n            Y = (long)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y)\n        {\n            X = (long)x;\n            Y = (long)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y)\n        {\n            X = (long)x;\n            Y = (long)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y)\n        {\n            X = (long)x;\n            Y = (long)y;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator -(V2l v)\n            => new V2l(-v.X, -v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator ~(V2l v)\n            => new V2l(~v.X, ~v.Y);\n\n        /// <summary>\n        /// Returns a vector that is orthogonal to this one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        public readonly V2l Orthogonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2l(-Y, X); }\n        }\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator +(V2l a, V2l b)\n            => new V2l(a.X + b.X, a.Y + b.Y);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator +(V2l v, long s)\n            => new V2l(v.X + s, v.Y + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator +(long s, V2l v)\n            => new V2l(s + v.X, s + v.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator -(V2l a, V2l b)\n            => new V2l(a.X - b.X, a.Y - b.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator -(V2l v, long s)\n            => new V2l(v.X - s, v.Y - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator -(long s, V2l v)\n            => new V2l(s - v.X, s - v.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator *(V2l a, V2l b)\n            => new V2l(a.X * b.X, a.Y * b.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator *(V2l v, long s)\n            => new V2l(v.X * s, v.Y * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator *(long s, V2l v)\n            => new V2l(s * v.X, s * v.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator /(V2l a, V2l b)\n            => new V2l(a.X / b.X, a.Y / b.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator /(V2l v, long s)\n            => new V2l(v.X / s, v.Y / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator /(long s, V2l v)\n            => new V2l(s / v.X, s / v.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator %(V2l a, V2l b)\n            => new V2l(a.X % b.X, a.Y % b.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator %(V2l v, long s)\n            => new V2l(v.X % s, v.Y % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator %(long s, V2l v)\n            => new V2l(s % v.X, s % v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator &(V2l a, V2l b)\n            => new V2l(a.X & b.X, a.Y & b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator &(V2l v, long s)\n            => new V2l(v.X & s, v.Y & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator &(long s, V2l v)\n            => new V2l(s & v.X, s & v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator |(V2l a, V2l b)\n            => new V2l(a.X | b.X, a.Y | b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator |(V2l v, long s)\n            => new V2l(v.X | s, v.Y | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator |(long s, V2l v)\n            => new V2l(s | v.X, s | v.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator ^(V2l a, V2l b)\n            => new V2l(a.X ^ b.X, a.Y ^ b.Y);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator ^(V2l v, long s)\n            => new V2l(v.X ^ s, v.Y ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator ^(long s, V2l v)\n            => new V2l(s ^ v.X, s ^ v.Y);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator <<(V2l v, int s)\n            => new V2l(v.X << s, v.Y << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l operator >>(V2l v, int s)\n            => new V2l(v.X >> s, v.Y >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2l a, V2l b)\n        {\n            return a.X == b.X && a.Y == b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2l v, long s)\n        {\n            return v.X == s && v.Y == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(long s, V2l v)\n        {\n            return s == v.X && s == v.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2l a, V2l b)\n        {\n            return a.X != b.X || a.Y != b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2l v, long s)\n        {\n            return v.X != s || v.Y != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(long s, V2l v)\n        {\n            return s != v.X || s != v.Y;\n        }\n\n        #endregion\n\n        #region IEquatable<V2l> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V2l other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V2l o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V2l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V2l(\n                long.Parse(x[0], CultureInfo.InvariantCulture), \n                long.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V2l Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<long>.Parse, V2l.Setter);\n        }\n\n        public static V2l Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<long>.Parse, V2l.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l OO => new V2l(0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l OI => new V2l(0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l ON => new V2l(0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OX => new V2l(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OY => new V2l(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l IO => new V2l(1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l II => new V2l(1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l PN => new V2l(1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IX => new V2l(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IY => new V2l(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l NO => new V2l(-1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l NP => new V2l(-1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2l NN => new V2l(-1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NX => new V2l(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NY => new V2l(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XO => new V2l(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XI => new V2l(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XN => new V2l(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XX => new V2l(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l XY\n        {\n            readonly get => new V2l(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YO => new V2l(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YI => new V2l(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YN => new V2l(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l YX\n        {\n            readonly get => new V2l(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YY => new V2l(Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOX => new V3l(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOY => new V3l(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIX => new V3l(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIY => new V3l(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONX => new V3l(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONY => new V3l(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXO => new V3l(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXI => new V3l(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXN => new V3l(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXX => new V3l(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXY => new V3l(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYO => new V3l(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYI => new V3l(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYN => new V3l(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYX => new V3l(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYY => new V3l(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOX => new V3l(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOY => new V3l(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIX => new V3l(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIY => new V3l(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNX => new V3l(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNY => new V3l(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXO => new V3l(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXI => new V3l(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PXN => new V3l(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXX => new V3l(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXY => new V3l(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYO => new V3l(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYI => new V3l(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PYN => new V3l(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYX => new V3l(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYY => new V3l(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOX => new V3l(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOY => new V3l(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPX => new V3l(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPY => new V3l(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNX => new V3l(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNY => new V3l(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXO => new V3l(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXP => new V3l(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXN => new V3l(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXX => new V3l(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXY => new V3l(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYO => new V3l(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYP => new V3l(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYN => new V3l(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYX => new V3l(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYY => new V3l(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOO => new V3l(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOI => new V3l(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XON => new V3l(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOX => new V3l(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOY => new V3l(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIO => new V3l(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XII => new V3l(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XPN => new V3l(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIX => new V3l(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIY => new V3l(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNO => new V3l(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNP => new V3l(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNN => new V3l(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNX => new V3l(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNY => new V3l(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXO => new V3l(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXI => new V3l(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXN => new V3l(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXX => new V3l(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXY => new V3l(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYO => new V3l(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYI => new V3l(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYN => new V3l(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYX => new V3l(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYY => new V3l(X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOO => new V3l(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOI => new V3l(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YON => new V3l(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOX => new V3l(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOY => new V3l(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIO => new V3l(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YII => new V3l(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YPN => new V3l(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIX => new V3l(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIY => new V3l(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNO => new V3l(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNP => new V3l(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNN => new V3l(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNX => new V3l(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNY => new V3l(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXO => new V3l(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXI => new V3l(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXN => new V3l(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXX => new V3l(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXY => new V3l(Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYO => new V3l(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYI => new V3l(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYN => new V3l(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYX => new V3l(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYY => new V3l(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOX => new V4l(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOY => new V4l(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIX => new V4l(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIY => new V4l(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONX => new V4l(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONY => new V4l(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXO => new V4l(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXI => new V4l(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXN => new V4l(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXX => new V4l(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXY => new V4l(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYO => new V4l(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYI => new V4l(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYN => new V4l(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYX => new V4l(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYY => new V4l(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOX => new V4l(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOY => new V4l(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIX => new V4l(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIY => new V4l(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNX => new V4l(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNY => new V4l(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXO => new V4l(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXI => new V4l(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPXN => new V4l(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXX => new V4l(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXY => new V4l(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYO => new V4l(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYI => new V4l(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPYN => new V4l(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYX => new V4l(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYY => new V4l(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOX => new V4l(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOY => new V4l(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPX => new V4l(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPY => new V4l(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNX => new V4l(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNY => new V4l(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXO => new V4l(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXP => new V4l(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXN => new V4l(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXX => new V4l(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXY => new V4l(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYO => new V4l(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYP => new V4l(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYN => new V4l(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYX => new V4l(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYY => new V4l(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOO => new V4l(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOI => new V4l(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXON => new V4l(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOX => new V4l(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOY => new V4l(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIO => new V4l(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXII => new V4l(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXPN => new V4l(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIX => new V4l(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIY => new V4l(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNO => new V4l(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNP => new V4l(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNN => new V4l(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNX => new V4l(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNY => new V4l(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXO => new V4l(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXI => new V4l(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXN => new V4l(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXX => new V4l(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXY => new V4l(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYO => new V4l(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYI => new V4l(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYN => new V4l(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYX => new V4l(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYY => new V4l(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOO => new V4l(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOI => new V4l(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYON => new V4l(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOX => new V4l(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOY => new V4l(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIO => new V4l(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYII => new V4l(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYPN => new V4l(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIX => new V4l(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIY => new V4l(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNO => new V4l(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNP => new V4l(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNN => new V4l(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNX => new V4l(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNY => new V4l(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXO => new V4l(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXI => new V4l(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXN => new V4l(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXX => new V4l(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXY => new V4l(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYO => new V4l(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYI => new V4l(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYN => new V4l(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYX => new V4l(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYY => new V4l(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOX => new V4l(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOY => new V4l(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIX => new V4l(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIY => new V4l(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONX => new V4l(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONY => new V4l(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXO => new V4l(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXI => new V4l(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POXN => new V4l(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXX => new V4l(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXY => new V4l(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYO => new V4l(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYI => new V4l(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POYN => new V4l(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYX => new V4l(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYY => new V4l(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOX => new V4l(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOY => new V4l(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIX => new V4l(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIY => new V4l(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNX => new V4l(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNY => new V4l(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXO => new V4l(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXI => new V4l(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPXN => new V4l(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXX => new V4l(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXY => new V4l(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYO => new V4l(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYI => new V4l(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPYN => new V4l(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYX => new V4l(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYY => new V4l(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOX => new V4l(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOY => new V4l(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPX => new V4l(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPY => new V4l(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNX => new V4l(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNY => new V4l(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXO => new V4l(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXP => new V4l(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXN => new V4l(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXX => new V4l(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXY => new V4l(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYO => new V4l(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYP => new V4l(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYN => new V4l(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYX => new V4l(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYY => new V4l(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOO => new V4l(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOI => new V4l(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXON => new V4l(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOX => new V4l(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOY => new V4l(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIO => new V4l(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXII => new V4l(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXPN => new V4l(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIX => new V4l(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIY => new V4l(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNO => new V4l(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNP => new V4l(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNN => new V4l(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNX => new V4l(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNY => new V4l(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXO => new V4l(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXI => new V4l(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXXN => new V4l(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXX => new V4l(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXY => new V4l(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYO => new V4l(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYI => new V4l(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXYN => new V4l(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYX => new V4l(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYY => new V4l(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOO => new V4l(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOI => new V4l(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYON => new V4l(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOX => new V4l(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOY => new V4l(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIO => new V4l(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYII => new V4l(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYPN => new V4l(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIX => new V4l(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIY => new V4l(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNO => new V4l(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNP => new V4l(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNN => new V4l(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNX => new V4l(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNY => new V4l(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXO => new V4l(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXI => new V4l(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYXN => new V4l(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXX => new V4l(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXY => new V4l(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYO => new V4l(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYI => new V4l(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYYN => new V4l(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYX => new V4l(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYY => new V4l(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOX => new V4l(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOY => new V4l(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPX => new V4l(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPY => new V4l(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONX => new V4l(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONY => new V4l(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXO => new V4l(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXP => new V4l(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXN => new V4l(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXX => new V4l(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXY => new V4l(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYO => new V4l(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYP => new V4l(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYN => new V4l(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYX => new V4l(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYY => new V4l(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOX => new V4l(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOY => new V4l(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPX => new V4l(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPY => new V4l(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNX => new V4l(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNY => new V4l(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXO => new V4l(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXP => new V4l(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXN => new V4l(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXX => new V4l(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXY => new V4l(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYO => new V4l(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYP => new V4l(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYN => new V4l(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYX => new V4l(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYY => new V4l(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOX => new V4l(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOY => new V4l(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPX => new V4l(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPY => new V4l(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNX => new V4l(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNY => new V4l(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXO => new V4l(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXP => new V4l(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXN => new V4l(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXX => new V4l(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXY => new V4l(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYO => new V4l(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYP => new V4l(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYN => new V4l(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYX => new V4l(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYY => new V4l(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOO => new V4l(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOP => new V4l(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXON => new V4l(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOX => new V4l(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOY => new V4l(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPO => new V4l(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPP => new V4l(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPN => new V4l(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPX => new V4l(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPY => new V4l(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNO => new V4l(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNP => new V4l(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNN => new V4l(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNX => new V4l(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNY => new V4l(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXO => new V4l(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXP => new V4l(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXN => new V4l(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXX => new V4l(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXY => new V4l(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYO => new V4l(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYP => new V4l(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYN => new V4l(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYX => new V4l(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYY => new V4l(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOO => new V4l(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOP => new V4l(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYON => new V4l(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOX => new V4l(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOY => new V4l(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPO => new V4l(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPP => new V4l(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPN => new V4l(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPX => new V4l(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPY => new V4l(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNO => new V4l(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNP => new V4l(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNN => new V4l(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNX => new V4l(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNY => new V4l(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXO => new V4l(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXP => new V4l(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXN => new V4l(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXX => new V4l(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXY => new V4l(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYO => new V4l(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYP => new V4l(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYN => new V4l(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYX => new V4l(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYY => new V4l(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOO => new V4l(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOI => new V4l(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOON => new V4l(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOX => new V4l(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOY => new V4l(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIO => new V4l(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOII => new V4l(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOPN => new V4l(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIX => new V4l(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIY => new V4l(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONO => new V4l(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONP => new V4l(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONN => new V4l(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONX => new V4l(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONY => new V4l(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXO => new V4l(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXI => new V4l(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXN => new V4l(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXX => new V4l(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXY => new V4l(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYO => new V4l(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYI => new V4l(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYN => new V4l(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYX => new V4l(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYY => new V4l(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOO => new V4l(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOI => new V4l(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPON => new V4l(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOX => new V4l(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOY => new V4l(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIO => new V4l(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIII => new V4l(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPPN => new V4l(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIX => new V4l(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIY => new V4l(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNO => new V4l(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNP => new V4l(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNN => new V4l(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNX => new V4l(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNY => new V4l(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXO => new V4l(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXI => new V4l(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPXN => new V4l(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXX => new V4l(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXY => new V4l(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYO => new V4l(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYI => new V4l(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPYN => new V4l(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYX => new V4l(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYY => new V4l(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOO => new V4l(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOP => new V4l(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNON => new V4l(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOX => new V4l(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOY => new V4l(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPO => new V4l(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPP => new V4l(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPN => new V4l(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPX => new V4l(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPY => new V4l(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNO => new V4l(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNP => new V4l(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNN => new V4l(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNX => new V4l(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNY => new V4l(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXO => new V4l(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXP => new V4l(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXN => new V4l(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXX => new V4l(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXY => new V4l(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYO => new V4l(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYP => new V4l(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYN => new V4l(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYX => new V4l(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYY => new V4l(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOO => new V4l(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOI => new V4l(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXON => new V4l(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOX => new V4l(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOY => new V4l(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIO => new V4l(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXII => new V4l(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXPN => new V4l(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIX => new V4l(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIY => new V4l(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNO => new V4l(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNP => new V4l(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNN => new V4l(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNX => new V4l(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNY => new V4l(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXO => new V4l(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXI => new V4l(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXN => new V4l(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXX => new V4l(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXY => new V4l(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYO => new V4l(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYI => new V4l(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYN => new V4l(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYX => new V4l(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYY => new V4l(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOO => new V4l(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOI => new V4l(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYON => new V4l(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOX => new V4l(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOY => new V4l(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIO => new V4l(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYII => new V4l(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYPN => new V4l(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIX => new V4l(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIY => new V4l(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNO => new V4l(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNP => new V4l(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNN => new V4l(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNX => new V4l(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNY => new V4l(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXO => new V4l(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXI => new V4l(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXN => new V4l(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXX => new V4l(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXY => new V4l(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYO => new V4l(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYI => new V4l(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYN => new V4l(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYX => new V4l(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYY => new V4l(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOO => new V4l(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOI => new V4l(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOON => new V4l(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOX => new V4l(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOY => new V4l(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIO => new V4l(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOII => new V4l(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOPN => new V4l(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIX => new V4l(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIY => new V4l(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONO => new V4l(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONP => new V4l(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONN => new V4l(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONX => new V4l(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONY => new V4l(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXO => new V4l(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXI => new V4l(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXN => new V4l(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXX => new V4l(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXY => new V4l(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYO => new V4l(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYI => new V4l(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYN => new V4l(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYX => new V4l(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYY => new V4l(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOO => new V4l(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOI => new V4l(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPON => new V4l(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOX => new V4l(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOY => new V4l(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIO => new V4l(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIII => new V4l(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPPN => new V4l(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIX => new V4l(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIY => new V4l(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNO => new V4l(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNP => new V4l(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNN => new V4l(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNX => new V4l(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNY => new V4l(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXO => new V4l(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXI => new V4l(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPXN => new V4l(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXX => new V4l(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXY => new V4l(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYO => new V4l(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYI => new V4l(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPYN => new V4l(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYX => new V4l(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYY => new V4l(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOO => new V4l(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOP => new V4l(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNON => new V4l(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOX => new V4l(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOY => new V4l(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPO => new V4l(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPP => new V4l(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPN => new V4l(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPX => new V4l(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPY => new V4l(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNO => new V4l(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNP => new V4l(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNN => new V4l(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNX => new V4l(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNY => new V4l(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXO => new V4l(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXP => new V4l(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXN => new V4l(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXX => new V4l(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXY => new V4l(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYO => new V4l(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYP => new V4l(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYN => new V4l(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYX => new V4l(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYY => new V4l(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOO => new V4l(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOI => new V4l(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXON => new V4l(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOX => new V4l(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOY => new V4l(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIO => new V4l(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXII => new V4l(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXPN => new V4l(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIX => new V4l(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIY => new V4l(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNO => new V4l(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNP => new V4l(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNN => new V4l(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNX => new V4l(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNY => new V4l(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXO => new V4l(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXI => new V4l(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXN => new V4l(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXX => new V4l(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXY => new V4l(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYO => new V4l(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYI => new V4l(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYN => new V4l(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYX => new V4l(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYY => new V4l(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOO => new V4l(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOI => new V4l(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYON => new V4l(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOX => new V4l(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOY => new V4l(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIO => new V4l(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYII => new V4l(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYPN => new V4l(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIX => new V4l(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIY => new V4l(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNO => new V4l(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNP => new V4l(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNN => new V4l(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNX => new V4l(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNY => new V4l(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXO => new V4l(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXI => new V4l(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXN => new V4l(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXX => new V4l(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXY => new V4l(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYO => new V4l(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYI => new V4l(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYN => new V4l(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYX => new V4l(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYY => new V4l(Y, Y, Y, Y);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (long)value; }\n        }\n\n        #endregion\n\n        #region ISize2l Members\n\n        public readonly V2l Size2l { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 2; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (long)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V2lEqualityComparer : IEqualityComparer<V2l>\n    {\n        public static V2lEqualityComparer Default\n            => new V2lEqualityComparer();\n\n        #region IEqualityComparer<V2l> Members\n\n        public bool Equals(V2l v0, V2l v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V2l v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Min(this V2l a, V2l b)\n        {\n            return new V2l(Min(a.X, b.X), Min(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Min(this V2l a, long b)\n        {\n            return new V2l(Min(a.X, b), Min(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Min(this long a, V2l b)\n        {\n            return new V2l(Min(a, b.X), Min(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Max(this V2l a, V2l b)\n        {\n            return new V2l(Max(a.X, b.X), Max(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Max(this V2l a, long b)\n        {\n            return new V2l(Max(a.X, b), Max(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Max(this long a, V2l b)\n        {\n            return new V2l(Max(a, b.X), Max(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Min(this V2l a, V2l b, V2l c)\n        {\n            return new V2l(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Max(this V2l a, V2l b, V2l c)\n        {\n            return new V2l(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Min(this V2l a, V2l b, V2l c, V2l d)\n        {\n            return new V2l(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Max(this V2l a, V2l b, V2l c, V2l d)\n        {\n            return new V2l(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Min(this V2l x, params V2l[] values)\n        {\n            return new V2l(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Max(this V2l x, params V2l[] values)\n        {\n            return new V2l(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Abs(this V2l x)\n        {\n            return new V2l(Abs(x.X), Abs(x.Y));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Clamp(this V2l x, V2l a, V2l b)\n        {\n            return new V2l(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Clamp(this V2l x, long a, long b)\n        {\n            return new V2l(Clamp(x.X, a, b), Clamp(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l ClampExcl(this V2l x, V2l a, V2l b)\n        {\n            return new V2l(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l ClampExcl(this V2l x, long a, long b)\n        {\n            return new V2l(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l ClampWrap(this V2l x, V2l a, V2l b)\n        {\n            return new V2l(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l ClampWrap(this V2l x, long a, long b)\n        {\n            return new V2l(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Saturate(this V2l x)\n        {\n            return new V2l(Saturate(x.X), Saturate(x.Y));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Sign(this V2l x)\n        {\n            return new V2i(Sign(x.X), Sign(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Signumi(this V2l x)\n        {\n            return new V2i(Signumi(x.X), Signumi(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Signum(this V2l x)\n        {\n            return new V2l(Signum(x.X), Signum(x.Y));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l MultiplyAdd(V2l x, V2l y, V2l z)\n        {\n            return new V2l(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l MultiplyAdd(V2l x, long y, V2l z)\n        {\n            return new V2l(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l MultiplyAdd(long x, V2l y, V2l z)\n        {\n            return new V2l(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sqrt(this V2l x)\n        {\n            return new V2d(Sqrt(x.X), Sqrt(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Cbrt(this V2l x)\n        {\n            return new V2d(Cbrt(x.X), Cbrt(x.Y));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Square(this V2l x)\n        {\n            return new V2l(Square(x.X), Square(x.Y));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Pown(this V2l x, V2l y)\n        {\n            return new V2l(Pown(x.X, y.X), Pown(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Pown(this V2l x, long y)\n        {\n            return new V2l(Pown(x.X, y), Pown(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Pown(this long x, V2l y)\n        {\n            return new V2l(Pown(x, y.X), Pown(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Pown(this V2l x, V2i y)\n        {\n            return new V2l(Pown(x.X, y.X), Pown(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Pown(this V2l x, int y)\n        {\n            return new V2l(Pown(x.X, y), Pown(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Pown(this long x, V2i y)\n        {\n            return new V2l(Pown(x, y.X), Pown(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this V2l x, V2f y)\n        {\n            return new V2f(Pow(x.X, y.X), Pow(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this V2l x, float y)\n        {\n            return new V2f(Pow(x.X, y), Pow(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this long x, V2f y)\n        {\n            return new V2f(Pow(x, y.X), Pow(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this V2l x, V2d y)\n        {\n            return new V2d(Pow(x.X, y.X), Pow(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this V2l x, double y)\n        {\n            return new V2d(Pow(x.X, y), Pow(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this long x, V2d y)\n        {\n            return new V2d(Pow(x, y.X), Pow(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this V2l x, V2f y)\n        {\n            return new V2f(Power(x.X, y.X), Power(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this V2l x, float y)\n        {\n            return new V2f(Power(x.X, y), Power(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this long x, V2f y)\n        {\n            return new V2f(Power(x, y.X), Power(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this V2l x, V2d y)\n        {\n            return new V2d(Power(x.X, y.X), Power(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this V2l x, double y)\n        {\n            return new V2d(Power(x.X, y), Power(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this long x, V2d y)\n        {\n            return new V2d(Power(x, y.X), Power(x, y.Y));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Exp(this V2l x)\n        {\n            return new V2d(Exp(x.X), Exp(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(this V2l x)\n        {\n            return new V2d(Log(x.X), Log(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log2(this V2l x)\n        {\n            return new V2d(Log2(x.X), Log2(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Log2Int(this V2l x)\n        {\n            return new V2i(Log2Int(x.X), Log2Int(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log10(this V2l x)\n        {\n            return new V2d(Log10(x.X), Log10(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(this V2l x, double basis)\n        {\n            return new V2d(Log(x.X, basis), Log(x.Y, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l ModP(this V2l a, V2l b)\n        {\n            return new V2l(ModP(a.X, b.X), ModP(a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l PowerOfTwo(this V2l x)\n        {\n            return new V2l(PowerOfTwo(x.X), PowerOfTwo(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.NextPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l NextPowerOfTwo(this V2l x)\n        {\n            return new V2l(NextPowerOfTwo(x.X), NextPowerOfTwo(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.PrevPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l PrevPowerOfTwo(this V2l x)\n        {\n            return new V2l(PrevPowerOfTwo(x.X), PrevPowerOfTwo(x.Y));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Step(this V2l x, V2l edge)\n        {\n            return new V2l(Step(x.X, edge.X), Step(x.Y, edge.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Step(this V2l x, long edge)\n        {\n            return new V2l(Step(x.X, edge), Step(x.Y, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Lerp(this float t, V2l a, V2l b)\n        {\n            return new V2l(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Lerp(this V2f t, V2l a, V2l b)\n        {\n            return new V2l(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Lerp(this double t, V2l a, V2l b)\n        {\n            return new V2l(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Lerp(this V2d t, V2l a, V2l b)\n        {\n            return new V2l(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvLerp(this V2l y, V2l a, V2l b)\n        {\n            return new V2d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l GreatestCommonDivisor(this V2l a, V2l b)\n        {\n            return new V2l(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l LeastCommonMultiple(this V2l a, V2l b)\n        {\n            return new V2l(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d FloatFromBits(this V2l x)\n        {\n            return new V2d(FloatFromBits(x.X), FloatFromBits(x.Y));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V2l a, V2l b, long tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V2l v, long epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long LengthSquared(V2l v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V2l v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Normalized(V2l v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Norm1(V2l v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V2l v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMax(V2l v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMin(V2l v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V2l v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceSquared(this V2l a, V2l b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V2l a, V2l b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Distance1(this V2l a, V2l b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V2l a, V2l b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceMax(this V2l a, V2l b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceMin(this V2l a, V2l b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V2l query, V2l p0, V2l p1)\n        {\n            return DistanceToLine((V2d) query, (V2d) p0, (V2d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V2l query, V2l p0, V2l p1)\n        {\n            return DistanceToInfiniteLine((V2d) query, (V2d) p0, (V2d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V2l query, V2l p0, V2l p1, out double t)\n        {\n            return DistanceToLine((V2d) query, (V2d) p0, (V2d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V2l query, V2l p0, V2l p1, out double t)\n        {\n            return DistanceToInfiniteLine((V2d) query, (V2d) p0, (V2d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns a vector that is orthogonal to the given one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l Orthogonal(V2l v)\n            => v.Orthogonal;\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V2l v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 2x2 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22l Outer(this V2l a, V2l b)\n        {\n            return new M22l(\n                        a.X * b.X, a.X * b.Y, \n                        a.Y * b.X, a.Y * b.Y);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Dot(this V2l a, V2l b)\n        {\n            return a.X * b.X + a.Y * b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V2l v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the cross product of vector a.\n        /// In 2D the cross product is simply a vector that is normal\n        /// to the given vector (i.e. {x,y} -> {-y,x})\n        /// </summary>\n        public static V2l Cross(this V2l a)\n        {\n            return new V2l(-a.Y, a.X);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2l a, V2l b)\n        {\n            return (a.X < b.X && a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2l v, long s)\n        {\n            return (v.X < s && v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(long s, V2l v)\n        {\n            return (s < v.X && s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2l a, V2l b)\n        {\n            return (a.X < b.X || a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2l v, long s)\n        {\n            return (v.X < s || v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(long s, V2l v)\n        {\n            return (s < v.X || s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2l a, V2l b)\n        {\n            return (a.X > b.X && a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2l v, long s)\n        {\n            return (v.X > s && v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(long s, V2l v)\n        {\n            return (s > v.X && s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2l a, V2l b)\n        {\n            return (a.X > b.X || a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2l v, long s)\n        {\n            return (v.X > s || v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(long s, V2l v)\n        {\n            return (s > v.X || s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2l a, V2l b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2l v, long s)\n        {\n            return (v.X <= s && v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(long s, V2l v)\n        {\n            return (s <= v.X && s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2l a, V2l b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2l v, long s)\n        {\n            return (v.X <= s || v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(long s, V2l v)\n        {\n            return (s <= v.X || s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2l a, V2l b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2l v, long s)\n        {\n            return (v.X >= s && v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(long s, V2l v)\n        {\n            return (s >= v.X && s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2l a, V2l b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2l v, long s)\n        {\n            return (v.X >= s || v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(long s, V2l v)\n        {\n            return (s >= v.X || s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2l a, V2l b)\n        {\n            return (a.X == b.X && a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2l v, long s)\n        {\n            return (v.X == s && v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(long s, V2l v)\n        {\n            return (s == v.X && s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2l a, V2l b)\n        {\n            return (a.X == b.X || a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2l v, long s)\n        {\n            return (v.X == s || v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(long s, V2l v)\n        {\n            return (s == v.X || s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2l a, V2l b)\n        {\n            return (a.X != b.X && a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2l v, long s)\n        {\n            return (v.X != s && v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(long s, V2l v)\n        {\n            return (s != v.X && s != v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2l a, V2l b)\n        {\n            return (a.X != b.X || a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2l v, long s)\n        {\n            return (v.X != s || v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(long s, V2l v)\n        {\n            return (s != v.X || s != v.Y);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V2l v0, V2l v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V2l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MinElement(V2l v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V2l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MaxElement(V2l v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V2l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V2l v, long epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V2l v, long epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V2l[] pointArray, V2l point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V2l[] array, int start, int count,\n                V2l point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V2l> pointSelector, V2l point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V2l[] pointArray, V2l point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V2l[] array, long start, long count,\n                V2l point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V2l> pointSelector, V2l point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V2l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V2l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V2l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V2l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V2l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V2l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V2l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V2l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V2l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V2l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V2l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V2l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static long[] CopyCoord(this V2l[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV2lExtensions\n    {\n        #region IRandomUniform extensions for V2l\n\n        /// <summary>\n        /// Uses UniformLong() to generate the elements of a V2l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l UniformV2l(this IRandomUniform rnd)\n        {\n            return new V2l(rnd.UniformLong(), rnd.UniformLong());\n        }\n\n        /// <summary>\n        /// Uses UniformLongNonZero() to generate the elements of a V2l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l UniformV2lNonZero(this IRandomUniform rnd)\n        {\n            return new V2l(rnd.UniformLongNonZero(), rnd.UniformLongNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of a V2l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l UniformV2l(this IRandomUniform rnd, long size)\n        {\n            return new V2l(rnd.UniformLong(size), rnd.UniformLong(size));\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of a V2l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l UniformV2l(this IRandomUniform rnd, V2l size)\n        {\n            return new V2l(rnd.UniformLong(size.X), rnd.UniformLong(size.Y));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V2f\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V2f : IVector<double>, ISize2f, IFormattable, IEquatable<V2f>\n    {\n        [DataMember]\n        public float X;\n        [DataMember]\n        public float Y;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(int x, int y)\n        {\n            X = (float)x;\n            Y = (float)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(int v)\n        {\n            X = (float)v;\n            Y = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(int[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(int[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(uint x, uint y)\n        {\n            X = (float)x;\n            Y = (float)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(uint v)\n        {\n            X = (float)v;\n            Y = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(uint[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(uint[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(long x, long y)\n        {\n            X = (float)x;\n            Y = (float)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(long v)\n        {\n            X = (float)v;\n            Y = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(long[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(long[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(float x, float y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(float v)\n        {\n            X = v;\n            Y = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(float[] a)\n        {\n            X = a[0];\n            Y = a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(float[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(double x, double y)\n        {\n            X = (float)x;\n            Y = (float)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(double v)\n        {\n            X = (float)v;\n            Y = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(double[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(double[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(Func<int, float> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;float&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 2.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(IVector<double> v)\n            : this(v[0], v[1])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V2i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V2ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V2l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V2f v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V2d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V3i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V3ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V3l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V3f v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V3d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V4i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V4ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V4l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V4f v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2f(V4d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V2i v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V2ui v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V2l v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V2d v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V3i v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V3ui v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V3l v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V3f v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V3d v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V4i v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V4ui v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V4l v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V4f v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(V4d v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V2f v)\n            => new int[] { (int)v.X, (int)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(int[] v)\n            => new V2f((float)v[0], (float)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V2f v)\n            => new uint[] { (uint)v.X, (uint)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(uint[] v)\n            => new V2f((float)v[0], (float)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V2f v)\n            => new long[] { (long)v.X, (long)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(long[] v)\n            => new V2f((float)v[0], (float)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V2f v)\n            => new float[] { v.X, v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(float[] v)\n            => new V2f(v[0], v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V2f v)\n            => new double[] { (double)v.X, (double)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2f(double[] v)\n            => new V2f((float)v[0], (float)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToFloorV2i()\n            => new V2i((int)Fun.Floor(X), (int)Fun.Floor(Y));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToCeilingV2i()\n            => new V2i((int)Fun.Ceiling(X), (int)Fun.Ceiling(Y));\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3iHomo()\n            => new V3i(X, Y, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3uiHomo()\n            => new V3ui(X, Y, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3lHomo()\n            => new V3l(X, Y, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3fHomo()\n            => new V3f(X, Y, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3dHomo()\n            => new V3d(X, Y, 1);\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<float, int> element_fun)\n            => new V2i(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<float, int, int> element_index_fun)\n            => new V2i(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<float, uint> element_fun)\n            => new V2ui(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<float, int, uint> element_index_fun)\n            => new V2ui(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<float, long> element_fun)\n            => new V2l(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<float, int, long> element_index_fun)\n            => new V2l(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<float, float> element_fun)\n            => new V2f(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<float, int, float> element_index_fun)\n            => new V2f(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<float, double> element_fun)\n            => new V2d(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<float, int, double> element_index_fun)\n            => new V2d(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float[] ToArray()\n            => new float[] { X, Y };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly float MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly float MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y);\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) || Fun.IsFinite(Y);\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) && Fun.IsFinite(Y);\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(X) || float.IsNaN(Y);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(X) && float.IsNaN(Y);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(X) || float.IsInfinity(Y);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(X) && float.IsInfinity(Y);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(X) || float.IsPositiveInfinity(Y);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(X) && float.IsPositiveInfinity(Y);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(X) || float.IsNegativeInfinity(Y);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(X) && float.IsNegativeInfinity(Y);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) || Fun.IsTiny(Y);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) && Fun.IsTiny(Y);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the vector is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the vector are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 2;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V2f Zero\n        {\n            get { return new V2f(0, 0); }\n        }\n\n        /// <summary>\n        /// All elements half.\n        /// </summary>\n        public static V2f Half\n        {\n            get { return new V2f(0.5, 0.5); }\n        }\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V2f One\n        {\n            get { return new V2f(1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V2f MaxValue\n        {\n            get { return new V2f(Constant<float>.ParseableMaxValue, Constant<float>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V2f MinValue\n        {\n            get { return new V2f(Constant<float>.ParseableMinValue, Constant<float>.ParseableMinValue); }\n        }\n\n         /// <summary>\n        /// All elements set to negative infinity.\n        /// </summary>\n        public static V2f NegativeInfinity\n        {\n            get { return new V2f(float.NegativeInfinity, float.NegativeInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to positive infinity.\n        /// </summary>\n        public static V2f PositiveInfinity\n        {\n            get { return new V2f(float.PositiveInfinity, float.PositiveInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to NaN.\n        /// </summary>\n        public static V2f NaN\n        {\n            get { return new V2f(float.NaN, float.NaN); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V2f XAxis\n        {\n            get { return new V2f(1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V2f YAxis\n        {\n            get { return new V2f(0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V2f, float>[] SelectorArray =\n            new Func<V2f, float>[] { v => v.X, v => v.Y };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V2f, int, float> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V2f, int, float> Setter =\n            (ref V2f v, int i, float s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V2f, long, float> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V2f, long, float> LongSetter =\n            (ref V2f v, long i, float s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FromV2i(V2i v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FromV2ui(V2ui v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FromV2l(V2l v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FromV2d(V2d v)\n            => new V2f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FromPolar(float angleInRadians, float radius)\n            => new V2f(Fun.Cos(angleInRadians) * radius, Fun.Sin(angleInRadians) * radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FromPolar(float angleInRadians)\n            => new V2f(Fun.Cos(angleInRadians), Fun.Sin(angleInRadians));\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly float LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly float Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly float Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly float Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly float NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly float NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V2f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V2f.Zero;\n                s = 1 / s;\n                return new V2f(X * s, Y * s);\n            }\n        }\n\n        /// <summary>\n        /// Vector rotated 90° counter clockwise: (-Y, X)\n        /// </summary>\n        public readonly V2f Rot90\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2f(-Y, X); }\n        }\n\n        /// <summary>\n        /// Vector rotated 180° counter clockwise: (-X, -Y)\n        /// </summary>\n        public readonly V2f Rot180\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2f(-X, -Y); }\n        }\n\n        /// <summary>\n        /// Vector rotated 270° counter clockwise: (Y, -X)\n        /// </summary>\n        public readonly V2f Rot270\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2f(Y, -X); }\n        }\n\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered square with side length 2.\n        /// </summary>\n        public readonly V2f CubeMapped\n        {\n            get\n            {\n                float x = Fun.Abs(X);\n                float y = Fun.Abs(Y);\n                return x > y\n                        ? new V2f(Fun.Sign(X), Y / x)\n                        : new V2f(X / y, Fun.Sign(Y));\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Abs(V2f v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Floor(V2f v)\n            => v.Floor();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Ceiling(V2f v)\n            => v.Ceiling();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Round(V2f v)\n            => v.Round();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Truncate(V2f v)\n            => v.Truncate();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Acos(V2f v)\n            => Fun.Acos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Acoshb(V2f v)\n            => Fun.Acosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Cos(V2f v)\n            => Fun.Cos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Cosh(V2f v)\n            => Fun.Cosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Asin(V2f v)\n            => Fun.Asin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Asinhb(V2f v)\n            => Fun.Asinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Sin(V2f v)\n            => Fun.Sin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Sinh(V2f v)\n            => Fun.Sinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Atan(V2f v)\n            => Fun.Atan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Atanhb(V2f v)\n            => Fun.Atanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Atan2(V2f a, V2f b)\n            => Fun.Atan2(a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Tan(V2f v)\n            => Fun.Tan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Tanh(V2f v)\n            => Fun.Tanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Sqrt(V2f v)\n            => Fun.Sqrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f CubeRoot(V2f v)\n            => Fun.Cbrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Exp(V2f v)\n            => Fun.Exp(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Log(V2f v)\n            => Fun.Log(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LogBinary(V2f v)\n            => Fun.Log2(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Log10(V2f v)\n            => Fun.Log10(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f CopySgn(V2f value, V2f sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f CopySgn(V2f value, float sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LinearInterp(float t, V2f a, V2f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LinearInterp(V2f t, V2f a, V2f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Min(V2f v0, V2f v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Min(V2f v, float x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Max(V2f v0, V2f v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Max(V2f v, float x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Saturate(V2f v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f DivideByInt(V2f v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y)\n        {\n            X = (float)x;\n            Y = (float)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y)\n        {\n            X = (float)x;\n            Y = (float)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y)\n        {\n            X = (float)x;\n            Y = (float)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y)\n        {\n            X = (float)x;\n            Y = (float)y;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator -(V2f v)\n            => new V2f(-v.X, -v.Y);\n\n        /// <summary>\n        /// Returns a vector that is orthogonal to this one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        public readonly V2f Orthogonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2f(-Y, X); }\n        }\n\n        /// <summary>\n        /// Gets a copy of this vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        public readonly V2f Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2f(1 / X, 1 / Y); }\n        }\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator +(V2f a, V2f b)\n            => new V2f(a.X + b.X, a.Y + b.Y);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator +(V2f v, float s)\n            => new V2f(v.X + s, v.Y + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator +(float s, V2f v)\n            => new V2f(s + v.X, s + v.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator -(V2f a, V2f b)\n            => new V2f(a.X - b.X, a.Y - b.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator -(V2f v, float s)\n            => new V2f(v.X - s, v.Y - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator -(float s, V2f v)\n            => new V2f(s - v.X, s - v.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(V2f a, V2f b)\n            => new V2f(a.X * b.X, a.Y * b.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(V2f v, float s)\n            => new V2f(v.X * s, v.Y * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator *(float s, V2f v)\n            => new V2f(s * v.X, s * v.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator /(V2f a, V2f b)\n            => new V2f(a.X / b.X, a.Y / b.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator /(V2f v, float s)\n            => new V2f(v.X / s, v.Y / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator /(float s, V2f v)\n            => new V2f(s / v.X, s / v.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator %(V2f a, V2f b)\n            => new V2f(a.X % b.X, a.Y % b.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator %(V2f v, float s)\n            => new V2f(v.X % s, v.Y % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f operator %(float s, V2f v)\n            => new V2f(s % v.X, s % v.Y);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2f a, V2f b)\n        {\n            return a.X == b.X && a.Y == b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2f v, float s)\n        {\n            return v.X == s && v.Y == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(float s, V2f v)\n        {\n            return s == v.X && s == v.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2f a, V2f b)\n        {\n            return a.X != b.X || a.Y != b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2f v, float s)\n        {\n            return v.X != s || v.Y != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(float s, V2f v)\n        {\n            return s != v.X || s != v.Y;\n        }\n\n        #endregion\n\n        #region IEquatable<V2f> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V2f other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V2f o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V2f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V2f(\n                float.Parse(x[0], CultureInfo.InvariantCulture), \n                float.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V2f Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<float>.Parse, V2f.Setter);\n        }\n\n        public static V2f Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<float>.Parse, V2f.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f OO => new V2f(0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f OI => new V2f(0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f ON => new V2f(0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OX => new V2f(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OY => new V2f(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f IO => new V2f(1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f II => new V2f(1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f PN => new V2f(1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IX => new V2f(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IY => new V2f(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f NO => new V2f(-1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f NP => new V2f(-1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2f NN => new V2f(-1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NX => new V2f(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NY => new V2f(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XO => new V2f(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XI => new V2f(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XN => new V2f(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XX => new V2f(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f XY\n        {\n            readonly get => new V2f(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YO => new V2f(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YI => new V2f(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YN => new V2f(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f YX\n        {\n            readonly get => new V2f(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YY => new V2f(Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOX => new V3f(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOY => new V3f(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIX => new V3f(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIY => new V3f(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONX => new V3f(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONY => new V3f(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXO => new V3f(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXI => new V3f(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXN => new V3f(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXX => new V3f(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXY => new V3f(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYO => new V3f(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYI => new V3f(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYN => new V3f(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYX => new V3f(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYY => new V3f(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOX => new V3f(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOY => new V3f(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIX => new V3f(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIY => new V3f(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNX => new V3f(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNY => new V3f(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXO => new V3f(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXI => new V3f(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PXN => new V3f(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXX => new V3f(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXY => new V3f(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYO => new V3f(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYI => new V3f(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PYN => new V3f(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYX => new V3f(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYY => new V3f(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOX => new V3f(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOY => new V3f(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPX => new V3f(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPY => new V3f(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNX => new V3f(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNY => new V3f(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXO => new V3f(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXP => new V3f(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXN => new V3f(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXX => new V3f(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXY => new V3f(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYO => new V3f(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYP => new V3f(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYN => new V3f(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYX => new V3f(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYY => new V3f(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOO => new V3f(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOI => new V3f(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XON => new V3f(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOX => new V3f(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOY => new V3f(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIO => new V3f(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XII => new V3f(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XPN => new V3f(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIX => new V3f(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIY => new V3f(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNO => new V3f(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNP => new V3f(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNN => new V3f(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNX => new V3f(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNY => new V3f(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXO => new V3f(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXI => new V3f(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXN => new V3f(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXX => new V3f(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXY => new V3f(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYO => new V3f(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYI => new V3f(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYN => new V3f(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYX => new V3f(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYY => new V3f(X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOO => new V3f(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOI => new V3f(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YON => new V3f(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOX => new V3f(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOY => new V3f(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIO => new V3f(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YII => new V3f(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YPN => new V3f(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIX => new V3f(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIY => new V3f(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNO => new V3f(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNP => new V3f(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNN => new V3f(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNX => new V3f(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNY => new V3f(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXO => new V3f(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXI => new V3f(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXN => new V3f(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXX => new V3f(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXY => new V3f(Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYO => new V3f(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYI => new V3f(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYN => new V3f(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYX => new V3f(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYY => new V3f(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOX => new V4f(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOY => new V4f(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIX => new V4f(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIY => new V4f(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONX => new V4f(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONY => new V4f(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXO => new V4f(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXI => new V4f(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXN => new V4f(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXX => new V4f(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXY => new V4f(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYO => new V4f(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYI => new V4f(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYN => new V4f(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYX => new V4f(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYY => new V4f(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOX => new V4f(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOY => new V4f(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIX => new V4f(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIY => new V4f(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNX => new V4f(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNY => new V4f(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXO => new V4f(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXI => new V4f(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPXN => new V4f(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXX => new V4f(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXY => new V4f(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYO => new V4f(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYI => new V4f(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPYN => new V4f(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYX => new V4f(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYY => new V4f(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOX => new V4f(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOY => new V4f(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPX => new V4f(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPY => new V4f(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNX => new V4f(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNY => new V4f(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXO => new V4f(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXP => new V4f(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXN => new V4f(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXX => new V4f(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXY => new V4f(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYO => new V4f(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYP => new V4f(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYN => new V4f(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYX => new V4f(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYY => new V4f(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOO => new V4f(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOI => new V4f(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXON => new V4f(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOX => new V4f(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOY => new V4f(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIO => new V4f(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXII => new V4f(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXPN => new V4f(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIX => new V4f(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIY => new V4f(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNO => new V4f(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNP => new V4f(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNN => new V4f(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNX => new V4f(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNY => new V4f(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXO => new V4f(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXI => new V4f(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXN => new V4f(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXX => new V4f(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXY => new V4f(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYO => new V4f(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYI => new V4f(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYN => new V4f(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYX => new V4f(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYY => new V4f(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOO => new V4f(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOI => new V4f(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYON => new V4f(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOX => new V4f(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOY => new V4f(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIO => new V4f(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYII => new V4f(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYPN => new V4f(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIX => new V4f(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIY => new V4f(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNO => new V4f(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNP => new V4f(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNN => new V4f(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNX => new V4f(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNY => new V4f(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXO => new V4f(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXI => new V4f(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXN => new V4f(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXX => new V4f(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXY => new V4f(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYO => new V4f(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYI => new V4f(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYN => new V4f(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYX => new V4f(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYY => new V4f(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOX => new V4f(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOY => new V4f(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIX => new V4f(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIY => new V4f(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONX => new V4f(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONY => new V4f(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXO => new V4f(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXI => new V4f(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POXN => new V4f(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXX => new V4f(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXY => new V4f(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYO => new V4f(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYI => new V4f(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POYN => new V4f(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYX => new V4f(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYY => new V4f(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOX => new V4f(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOY => new V4f(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIX => new V4f(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIY => new V4f(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNX => new V4f(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNY => new V4f(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXO => new V4f(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXI => new V4f(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPXN => new V4f(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXX => new V4f(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXY => new V4f(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYO => new V4f(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYI => new V4f(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPYN => new V4f(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYX => new V4f(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYY => new V4f(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOX => new V4f(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOY => new V4f(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPX => new V4f(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPY => new V4f(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNX => new V4f(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNY => new V4f(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXO => new V4f(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXP => new V4f(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXN => new V4f(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXX => new V4f(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXY => new V4f(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYO => new V4f(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYP => new V4f(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYN => new V4f(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYX => new V4f(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYY => new V4f(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOO => new V4f(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOI => new V4f(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXON => new V4f(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOX => new V4f(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOY => new V4f(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIO => new V4f(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXII => new V4f(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXPN => new V4f(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIX => new V4f(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIY => new V4f(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNO => new V4f(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNP => new V4f(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNN => new V4f(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNX => new V4f(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNY => new V4f(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXO => new V4f(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXI => new V4f(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXXN => new V4f(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXX => new V4f(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXY => new V4f(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYO => new V4f(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYI => new V4f(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXYN => new V4f(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYX => new V4f(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYY => new V4f(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOO => new V4f(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOI => new V4f(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYON => new V4f(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOX => new V4f(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOY => new V4f(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIO => new V4f(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYII => new V4f(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYPN => new V4f(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIX => new V4f(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIY => new V4f(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNO => new V4f(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNP => new V4f(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNN => new V4f(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNX => new V4f(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNY => new V4f(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXO => new V4f(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXI => new V4f(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYXN => new V4f(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXX => new V4f(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXY => new V4f(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYO => new V4f(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYI => new V4f(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYYN => new V4f(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYX => new V4f(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYY => new V4f(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOX => new V4f(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOY => new V4f(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPX => new V4f(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPY => new V4f(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONX => new V4f(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONY => new V4f(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXO => new V4f(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXP => new V4f(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXN => new V4f(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXX => new V4f(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXY => new V4f(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYO => new V4f(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYP => new V4f(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYN => new V4f(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYX => new V4f(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYY => new V4f(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOX => new V4f(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOY => new V4f(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPX => new V4f(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPY => new V4f(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNX => new V4f(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNY => new V4f(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXO => new V4f(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXP => new V4f(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXN => new V4f(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXX => new V4f(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXY => new V4f(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYO => new V4f(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYP => new V4f(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYN => new V4f(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYX => new V4f(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYY => new V4f(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOX => new V4f(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOY => new V4f(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPX => new V4f(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPY => new V4f(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNX => new V4f(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNY => new V4f(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXO => new V4f(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXP => new V4f(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXN => new V4f(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXX => new V4f(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXY => new V4f(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYO => new V4f(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYP => new V4f(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYN => new V4f(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYX => new V4f(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYY => new V4f(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOO => new V4f(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOP => new V4f(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXON => new V4f(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOX => new V4f(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOY => new V4f(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPO => new V4f(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPP => new V4f(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPN => new V4f(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPX => new V4f(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPY => new V4f(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNO => new V4f(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNP => new V4f(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNN => new V4f(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNX => new V4f(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNY => new V4f(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXO => new V4f(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXP => new V4f(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXN => new V4f(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXX => new V4f(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXY => new V4f(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYO => new V4f(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYP => new V4f(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYN => new V4f(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYX => new V4f(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYY => new V4f(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOO => new V4f(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOP => new V4f(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYON => new V4f(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOX => new V4f(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOY => new V4f(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPO => new V4f(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPP => new V4f(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPN => new V4f(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPX => new V4f(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPY => new V4f(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNO => new V4f(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNP => new V4f(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNN => new V4f(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNX => new V4f(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNY => new V4f(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXO => new V4f(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXP => new V4f(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXN => new V4f(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXX => new V4f(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXY => new V4f(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYO => new V4f(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYP => new V4f(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYN => new V4f(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYX => new V4f(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYY => new V4f(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOO => new V4f(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOI => new V4f(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOON => new V4f(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOX => new V4f(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOY => new V4f(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIO => new V4f(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOII => new V4f(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOPN => new V4f(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIX => new V4f(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIY => new V4f(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONO => new V4f(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONP => new V4f(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONN => new V4f(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONX => new V4f(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONY => new V4f(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXO => new V4f(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXI => new V4f(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXN => new V4f(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXX => new V4f(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXY => new V4f(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYO => new V4f(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYI => new V4f(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYN => new V4f(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYX => new V4f(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYY => new V4f(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOO => new V4f(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOI => new V4f(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPON => new V4f(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOX => new V4f(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOY => new V4f(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIO => new V4f(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIII => new V4f(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPPN => new V4f(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIX => new V4f(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIY => new V4f(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNO => new V4f(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNP => new V4f(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNN => new V4f(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNX => new V4f(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNY => new V4f(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXO => new V4f(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXI => new V4f(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPXN => new V4f(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXX => new V4f(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXY => new V4f(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYO => new V4f(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYI => new V4f(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPYN => new V4f(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYX => new V4f(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYY => new V4f(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOO => new V4f(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOP => new V4f(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNON => new V4f(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOX => new V4f(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOY => new V4f(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPO => new V4f(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPP => new V4f(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPN => new V4f(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPX => new V4f(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPY => new V4f(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNO => new V4f(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNP => new V4f(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNN => new V4f(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNX => new V4f(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNY => new V4f(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXO => new V4f(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXP => new V4f(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXN => new V4f(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXX => new V4f(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXY => new V4f(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYO => new V4f(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYP => new V4f(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYN => new V4f(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYX => new V4f(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYY => new V4f(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOO => new V4f(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOI => new V4f(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXON => new V4f(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOX => new V4f(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOY => new V4f(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIO => new V4f(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXII => new V4f(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXPN => new V4f(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIX => new V4f(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIY => new V4f(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNO => new V4f(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNP => new V4f(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNN => new V4f(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNX => new V4f(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNY => new V4f(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXO => new V4f(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXI => new V4f(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXN => new V4f(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXX => new V4f(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXY => new V4f(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYO => new V4f(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYI => new V4f(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYN => new V4f(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYX => new V4f(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYY => new V4f(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOO => new V4f(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOI => new V4f(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYON => new V4f(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOX => new V4f(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOY => new V4f(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIO => new V4f(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYII => new V4f(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYPN => new V4f(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIX => new V4f(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIY => new V4f(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNO => new V4f(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNP => new V4f(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNN => new V4f(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNX => new V4f(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNY => new V4f(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXO => new V4f(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXI => new V4f(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXN => new V4f(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXX => new V4f(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXY => new V4f(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYO => new V4f(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYI => new V4f(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYN => new V4f(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYX => new V4f(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYY => new V4f(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOO => new V4f(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOI => new V4f(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOON => new V4f(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOX => new V4f(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOY => new V4f(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIO => new V4f(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOII => new V4f(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOPN => new V4f(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIX => new V4f(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIY => new V4f(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONO => new V4f(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONP => new V4f(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONN => new V4f(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONX => new V4f(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONY => new V4f(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXO => new V4f(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXI => new V4f(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXN => new V4f(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXX => new V4f(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXY => new V4f(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYO => new V4f(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYI => new V4f(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYN => new V4f(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYX => new V4f(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYY => new V4f(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOO => new V4f(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOI => new V4f(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPON => new V4f(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOX => new V4f(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOY => new V4f(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIO => new V4f(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIII => new V4f(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPPN => new V4f(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIX => new V4f(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIY => new V4f(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNO => new V4f(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNP => new V4f(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNN => new V4f(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNX => new V4f(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNY => new V4f(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXO => new V4f(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXI => new V4f(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPXN => new V4f(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXX => new V4f(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXY => new V4f(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYO => new V4f(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYI => new V4f(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPYN => new V4f(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYX => new V4f(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYY => new V4f(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOO => new V4f(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOP => new V4f(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNON => new V4f(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOX => new V4f(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOY => new V4f(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPO => new V4f(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPP => new V4f(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPN => new V4f(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPX => new V4f(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPY => new V4f(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNO => new V4f(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNP => new V4f(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNN => new V4f(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNX => new V4f(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNY => new V4f(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXO => new V4f(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXP => new V4f(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXN => new V4f(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXX => new V4f(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXY => new V4f(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYO => new V4f(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYP => new V4f(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYN => new V4f(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYX => new V4f(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYY => new V4f(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOO => new V4f(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOI => new V4f(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXON => new V4f(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOX => new V4f(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOY => new V4f(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIO => new V4f(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXII => new V4f(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXPN => new V4f(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIX => new V4f(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIY => new V4f(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNO => new V4f(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNP => new V4f(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNN => new V4f(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNX => new V4f(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNY => new V4f(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXO => new V4f(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXI => new V4f(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXN => new V4f(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXX => new V4f(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXY => new V4f(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYO => new V4f(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYI => new V4f(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYN => new V4f(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYX => new V4f(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYY => new V4f(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOO => new V4f(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOI => new V4f(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYON => new V4f(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOX => new V4f(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOY => new V4f(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIO => new V4f(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYII => new V4f(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYPN => new V4f(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIX => new V4f(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIY => new V4f(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNO => new V4f(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNP => new V4f(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNN => new V4f(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNX => new V4f(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNY => new V4f(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXO => new V4f(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXI => new V4f(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXN => new V4f(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXX => new V4f(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXY => new V4f(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYO => new V4f(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYI => new V4f(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYN => new V4f(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYX => new V4f(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYY => new V4f(Y, Y, Y, Y);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (float)value; }\n        }\n\n        #endregion\n\n        #region ISize2f Members\n\n        public readonly V2f Size2f { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 2; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (float)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V2fEqualityComparer : IEqualityComparer<V2f>\n    {\n        public static V2fEqualityComparer Default\n            => new V2fEqualityComparer();\n\n        #region IEqualityComparer<V2f> Members\n\n        public bool Equals(V2f v0, V2f v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V2f v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Min(this V2f a, V2f b)\n        {\n            return new V2f(Min(a.X, b.X), Min(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Min(this V2f a, float b)\n        {\n            return new V2f(Min(a.X, b), Min(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Min(this float a, V2f b)\n        {\n            return new V2f(Min(a, b.X), Min(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Max(this V2f a, V2f b)\n        {\n            return new V2f(Max(a.X, b.X), Max(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Max(this V2f a, float b)\n        {\n            return new V2f(Max(a.X, b), Max(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Max(this float a, V2f b)\n        {\n            return new V2f(Max(a, b.X), Max(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Min(this V2f a, V2f b, V2f c)\n        {\n            return new V2f(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Max(this V2f a, V2f b, V2f c)\n        {\n            return new V2f(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Min(this V2f a, V2f b, V2f c, V2f d)\n        {\n            return new V2f(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Max(this V2f a, V2f b, V2f c, V2f d)\n        {\n            return new V2f(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Min(this V2f x, params V2f[] values)\n        {\n            return new V2f(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Max(this V2f x, params V2f[] values)\n        {\n            return new V2f(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Abs(this V2f x)\n        {\n            return new V2f(Abs(x.X), Abs(x.Y));\n        }\n\n        #endregion\n\n        #region Rounding\n\n        /// <summary>\n        /// Applies Fun.Floor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Floor(this V2f x)\n        {\n            return new V2f(Floor(x.X), Floor(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Ceiling to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Ceiling(this V2f x)\n        {\n            return new V2f(Ceiling(x.X), Ceiling(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Round(this V2f x)\n        {\n            return new V2f(Round(x.X), Round(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Round(this V2f x, MidpointRounding mode)\n        {\n            return new V2f(Round(x.X, mode), Round(x.Y, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Round(this V2f x, int digits)\n        {\n            return new V2f(Round(x.X, digits), Round(x.Y, digits));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Round(this V2f x, int digits, MidpointRounding mode)\n        {\n            return new V2f(Round(x.X, digits, mode), Round(x.Y, digits, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Truncate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Truncate(this V2f x)\n        {\n            return new V2f(Truncate(x.X), Truncate(x.Y));\n        }\n\n        #endregion\n\n        #region Frac\n\n        /// <summary>\n        /// Applies Fun.Frac to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Frac(this V2f x)\n        {\n            return new V2f(Frac(x.X), Frac(x.Y));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Clamp(this V2f x, V2f a, V2f b)\n        {\n            return new V2f(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Clamp(this V2f x, float a, float b)\n        {\n            return new V2f(Clamp(x.X, a, b), Clamp(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f ClampWrap(this V2f x, V2f a, V2f b)\n        {\n            return new V2f(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f ClampWrap(this V2f x, float a, float b)\n        {\n            return new V2f(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Saturate(this V2f x)\n        {\n            return new V2f(Saturate(x.X), Saturate(x.Y));\n        }\n\n        #endregion\n\n        #region MapToUnitInterval\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f MapToUnitInterval(this V2f t, V2f tMax, bool repeat, bool mirror)\n        {\n            return new V2f(MapToUnitInterval(t.X, tMax.X, repeat, mirror), MapToUnitInterval(t.Y, tMax.Y, repeat, mirror));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f MapToUnitInterval(this V2f t, V2f tMax, bool repeat)\n        {\n            return new V2f(MapToUnitInterval(t.X, tMax.X, repeat), MapToUnitInterval(t.Y, tMax.Y, repeat));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f MapToUnitInterval(this V2f t, V2f tMax)\n        {\n            return new V2f(MapToUnitInterval(t.X, tMax.X), MapToUnitInterval(t.Y, tMax.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f MapToUnitInterval(this V2f t, V2f tMin, V2f tMax)\n        {\n            return new V2f(MapToUnitInterval(t.X, tMin.X, tMax.X), MapToUnitInterval(t.Y, tMin.Y, tMax.Y));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Sign(this V2f x)\n        {\n            return new V2i(Sign(x.X), Sign(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Signumi(this V2f x)\n        {\n            return new V2i(Signumi(x.X), Signumi(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Signum(this V2f x)\n        {\n            return new V2f(Signum(x.X), Signum(x.Y));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f MultiplyAdd(V2f x, V2f y, V2f z)\n        {\n            return new V2f(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f MultiplyAdd(V2f x, float y, V2f z)\n        {\n            return new V2f(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f MultiplyAdd(float x, V2f y, V2f z)\n        {\n            return new V2f(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y));\n        }\n\n        #endregion\n\n        #region Copy sign\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f CopySign(V2f value, V2f sign)\n        {\n            return new V2f(CopySign(value.X, sign.X), CopySign(value.Y, sign.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f CopySign(float value, V2f sign)\n        {\n            return new V2f(CopySign(value, sign.X), CopySign(value, sign.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f CopySign(V2f value, float sign)\n        {\n            return new V2f(CopySign(value.X, sign), CopySign(value.Y, sign));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Sqrt(this V2f x)\n        {\n            return new V2f(Sqrt(x.X), Sqrt(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Cbrt(this V2f x)\n        {\n            return new V2f(Cbrt(x.X), Cbrt(x.Y));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Square(this V2f x)\n        {\n            return new V2f(Square(x.X), Square(x.Y));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pown(this V2f x, V2i y)\n        {\n            return new V2f(Pown(x.X, y.X), Pown(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pown(this V2f x, int y)\n        {\n            return new V2f(Pown(x.X, y), Pown(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pown(this float x, V2i y)\n        {\n            return new V2f(Pown(x, y.X), Pown(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this V2f x, V2f y)\n        {\n            return new V2f(Pow(x.X, y.X), Pow(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this V2f x, float y)\n        {\n            return new V2f(Pow(x.X, y), Pow(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Pow(this float x, V2f y)\n        {\n            return new V2f(Pow(x, y.X), Pow(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this V2f x, V2f y)\n        {\n            return new V2f(Power(x.X, y.X), Power(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this V2f x, float y)\n        {\n            return new V2f(Power(x.X, y), Power(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Power(this float x, V2f y)\n        {\n            return new V2f(Power(x, y.X), Power(x, y.Y));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Exp(this V2f x)\n        {\n            return new V2f(Exp(x.X), Exp(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Log(this V2f x)\n        {\n            return new V2f(Log(x.X), Log(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Log2(this V2f x)\n        {\n            return new V2f(Log2(x.X), Log2(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Log2Int(this V2f x)\n        {\n            return new V2i(Log2Int(x.X), Log2Int(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Log10(this V2f x)\n        {\n            return new V2f(Log10(x.X), Log10(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Log(this V2f x, float basis)\n        {\n            return new V2f(Log(x.X, basis), Log(x.Y, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f ModP(this V2f a, V2f b)\n        {\n            return new V2f(ModP(a.X, b.X), ModP(a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f PowerOfTwo(this V2f x)\n        {\n            return new V2f(PowerOfTwo(x.X), PowerOfTwo(x.Y));\n        }\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Applies Fun.Sin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Sin(this V2f x)\n        {\n            return new V2f(Sin(x.X), Sin(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Cos(this V2f x)\n        {\n            return new V2f(Cos(x.X), Cos(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Tan(this V2f x)\n        {\n            return new V2f(Tan(x.X), Tan(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Asin(this V2f x)\n        {\n            return new V2f(Asin(x.X), Asin(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.AsinClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f AsinClamped(this V2f x)\n        {\n            return new V2f(AsinClamped(x.X), AsinClamped(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Acos(this V2f x)\n        {\n            return new V2f(Acos(x.X), Acos(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.AcosClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f AcosClamped(this V2f x)\n        {\n            return new V2f(AcosClamped(x.X), AcosClamped(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Atan(this V2f x)\n        {\n            return new V2f(Atan(x.X), Atan(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Atan2(V2f y, V2f x)\n        {\n            return new V2f(Atan2(y.X, x.X), Atan2(y.Y, x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.FastAtan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f FastAtan2(V2f y, V2f x)\n        {\n            return new V2f(FastAtan2(y.X, x.X), FastAtan2(y.Y, x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Sinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Sinh(this V2f x)\n        {\n            return new V2f(Sinh(x.X), Sinh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Cosh(this V2f x)\n        {\n            return new V2f(Cosh(x.X), Cosh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Tanh(this V2f x)\n        {\n            return new V2f(Tanh(x.X), Tanh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Asinh(this V2f x)\n        {\n            return new V2f(Asinh(x.X), Asinh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Acosh(this V2f x)\n        {\n            return new V2f(Acosh(x.X), Acosh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Atanh(this V2f x)\n        {\n            return new V2f(Atanh(x.X), Atanh(x.Y));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Step(this V2f x, V2f edge)\n        {\n            return new V2f(Step(x.X, edge.X), Step(x.Y, edge.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Step(this V2f x, float edge)\n        {\n            return new V2f(Step(x.X, edge), Step(x.Y, edge));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Linearstep(this V2f x, V2f edge0, V2f edge1)\n        {\n            return new V2f(Linearstep(x.X, edge0.X, edge1.X), Linearstep(x.Y, edge0.Y, edge1.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Linearstep(this V2f x, float edge0, float edge1)\n        {\n            return new V2f(Linearstep(x.X, edge0, edge1), Linearstep(x.Y, edge0, edge1));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Smoothstep(this V2f x, V2f edge0, V2f edge1)\n        {\n            return new V2f(Smoothstep(x.X, edge0.X, edge1.X), Smoothstep(x.Y, edge0.Y, edge1.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Smoothstep(this V2f x, float edge0, float edge1)\n        {\n            return new V2f(Smoothstep(x.X, edge0, edge1), Smoothstep(x.Y, edge0, edge1));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Lerp(this float t, V2f a, V2f b)\n        {\n            return new V2f(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Lerp(this V2f t, V2f a, V2f b)\n        {\n            return new V2f(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f InvLerp(this V2f y, V2f a, V2f b)\n        {\n            return new V2f(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatToBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i FloatToBits(this V2f x)\n        {\n            return new V2i(FloatToBits(x.X), FloatToBits(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.FloatToUnsignedBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2ui FloatToUnsignedBits(this V2f x)\n        {\n            return new V2ui(FloatToUnsignedBits(x.X), FloatToUnsignedBits(x.Y));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V2f a, V2f b, float tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within\n        /// Constant{float}.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V2f a, V2f b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V2f v, float epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(V2f v)\n            => v.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"V2f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(V2f v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V2f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(V2f v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V2f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(V2f v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V2f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(V2f v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"V2f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(V2f v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts the angles given in degrees to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f RadiansFromDegrees(this V2f degrees)\n            => new V2f(\n                   RadiansFromDegrees(degrees.X), \n                   RadiansFromDegrees(degrees.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f RadiansFromGons(this V2f gons)\n            => new V2f(\n                   RadiansFromGons(gons.X), \n                   RadiansFromGons(gons.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f DegreesFromRadians(this V2f radians)\n            => new V2f(\n                   DegreesFromRadians(radians.X), \n                   DegreesFromRadians(radians.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f DegreesFromGons(this V2f gons)\n            => new V2f(\n                   DegreesFromGons(gons.X), \n                   DegreesFromGons(gons.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GonsFromRadians(this V2f radians)\n            => new V2f(\n                   GonsFromRadians(radians.X), \n                   GonsFromRadians(radians.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in degrees to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f GonsFromDegrees(this V2f degrees)\n            => new V2f(\n                   GonsFromDegrees(degrees.X), \n                   GonsFromDegrees(degrees.Y)\n               );\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LengthSquared(V2f v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Length(V2f v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Normalizes the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref V2f v)\n        {\n            var s = v.Length; if (s == 0) return;\n            s = 1 / s;\n            v.X *= s;\n            v.Y *= s;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Normalized(V2f v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm1(V2f v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm2(V2f v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMax(V2f v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMin(V2f v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(this V2f v, float p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceSquared(this V2f a, V2f b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(this V2f a, V2f b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance1(this V2f a, V2f b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(this V2f a, V2f b, float p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceMax(this V2f a, V2f b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceMin(this V2f a, V2f b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToLine(\n                this V2f query, V2f p0, V2f p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            if (t <= 0) { return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToInfiniteLine(\n                this V2f query, V2f p0, V2f p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToLine(\n                this V2f query, V2f p0, V2f p1, out float t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            if (t <= 0) { t = 0; return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { t = 1; return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToInfiniteLine(\n                this V2f query, V2f p0, V2f p1, out float t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns a vector that is orthogonal to the given one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Orthogonal(V2f v)\n            => v.Orthogonal;\n\n        /// <summary>\n        /// Gets a copy of the given vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Reciprocal(V2f v)\n            => v.Reciprocal;\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V2f v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 2x2 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22f Outer(this V2f a, V2f b)\n        {\n            return new M22f(\n                        a.X * b.X, a.X * b.Y, \n                        a.Y * b.X, a.Y * b.Y);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Dot(this V2f a, V2f b)\n        {\n            return a.X * b.X + a.Y * b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V2f v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeY;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the reflection direction of the given vector v (pointing to the surface) for the given normal (should be normalized).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Reflect(this V2f v, V2f normal)\n        {\n            return v - 2 * v.Dot(normal) * normal;\n        }\n\n        /// <summary>\n        /// Returns the refraction direction of the given vector v (pointing to the surface) for the given normal and ratio of refraction indices (n_out / n_in).\n        /// Both the input vectors should be normalized.\n        /// Returns a zero-vector in case of total internal reflection.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f Refract(this V2f v, V2f normal, float eta)\n        {\n            var t = v.Dot(normal);\n            var k = 1 - eta * eta * (1 - t * t);\n\n            if (k < 0)\n            {\n                return V2f.Zero;\n            }\n            else\n            {\n                return eta * v - (eta * t + Fun.Sqrt(k)) * normal;\n            }\n        }\n\n        /// <summary>\n        /// Returns the cross product of vector a.\n        /// In 2D the cross product is simply a vector that is normal\n        /// to the given vector (i.e. {x,y} -> {-y,x})\n        /// </summary>\n        public static V2f Cross(this V2f a)\n        {\n            return new V2f(-a.Y, a.X);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2f a, V2f b)\n        {\n            return (a.X < b.X && a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2f v, float s)\n        {\n            return (v.X < s && v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, V2f v)\n        {\n            return (s < v.X && s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2f a, V2f b)\n        {\n            return (a.X < b.X || a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2f v, float s)\n        {\n            return (v.X < s || v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, V2f v)\n        {\n            return (s < v.X || s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2f a, V2f b)\n        {\n            return (a.X > b.X && a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2f v, float s)\n        {\n            return (v.X > s && v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, V2f v)\n        {\n            return (s > v.X && s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2f a, V2f b)\n        {\n            return (a.X > b.X || a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2f v, float s)\n        {\n            return (v.X > s || v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, V2f v)\n        {\n            return (s > v.X || s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2f a, V2f b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2f v, float s)\n        {\n            return (v.X <= s && v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, V2f v)\n        {\n            return (s <= v.X && s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2f a, V2f b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2f v, float s)\n        {\n            return (v.X <= s || v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, V2f v)\n        {\n            return (s <= v.X || s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2f a, V2f b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2f v, float s)\n        {\n            return (v.X >= s && v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, V2f v)\n        {\n            return (s >= v.X && s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2f a, V2f b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2f v, float s)\n        {\n            return (v.X >= s || v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, V2f v)\n        {\n            return (s >= v.X || s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2f a, V2f b)\n        {\n            return (a.X == b.X && a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2f v, float s)\n        {\n            return (v.X == s && v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, V2f v)\n        {\n            return (s == v.X && s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2f a, V2f b)\n        {\n            return (a.X == b.X || a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2f v, float s)\n        {\n            return (v.X == s || v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, V2f v)\n        {\n            return (s == v.X || s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2f a, V2f b)\n        {\n            return (a.X != b.X && a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2f v, float s)\n        {\n            return (v.X != s && v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, V2f v)\n        {\n            return (s != v.X && s != v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2f a, V2f b)\n        {\n            return (a.X != b.X || a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2f v, float s)\n        {\n            return (v.X != s || v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, V2f v)\n        {\n            return (s != v.X || s != v.Y);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V2f v0, V2f v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MinElement(V2f v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V2f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MaxElement(V2f v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region Angle between two vectors\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleBetweenFast(this V2f x, V2f y)\n        {\n            return Fun.AcosClamped(x.Dot(y));\n        }\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians using a numerically stable algorithm.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        // https://scicomp.stackexchange.com/a/27769\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleBetween(this V2f x, V2f y)\n        {\n            var a = x + y;\n            var b = x - y;\n            return 2 * Fun.Atan2(b.Length, a.Length);\n        }\n\n        /// <summary>\n        /// Computes the signed angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleBetweenSigned(this V2f x, V2f y)\n        {\n            var a = x.X * y.Y - x.Y * y.X;\n            var b = x.X * y.X + x.Y * y.Y;\n            return Fun.Atan2(a, b);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V2f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V2f v, float epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V2f v, float epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(V2f v)\n            => v.AnyFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(V2f v)\n            => v.AllFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(V2f v)\n            => v.AnyNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(V2f v)\n            => v.AllNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(V2f v)\n            => v.AnyInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(V2f v)\n            => v.AllInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(V2f v)\n            => v.AnyPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(V2f v)\n            => v.AllPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(V2f v)\n            => v.AnyNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(V2f v)\n            => v.AllNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(V2f v)\n            => v.AnyTiny;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(V2f v)\n            => v.AllTiny;\n\n        #endregion\n\n        #region 2D Vector Arithmetics\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 90 degrees counterclockwise.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Dot90(this V2f v, V2f dir)\n        {\n            return v.Y * dir.X - v.X * dir.Y;\n        }\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 180 degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Dot180(this V2f v, V2f dir)\n        {\n            return -(v.X * dir.X + v.Y * dir.Y);\n        }\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 270 degrees counterclockwise.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Dot270(this V2f v, V2f dir)\n        {\n            return v.X * dir.Y - v.Y * dir.X;\n        }\n\n        /// <summary>\n        /// Returns the left value of the direction v with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DirLeftOfLineValue(this V2f v, V2f p0, V2f p1)\n        {\n            return v.X * (p0.Y - p1.Y) + v.Y * (p1.X - p0.X);\n        }\n\n        /// <summary>\n        /// Returns the right value of the direction v with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DirRightOfLineValue(this V2f v, V2f p0, V2f p1)\n        {\n            return v.X * (p1.Y - p0.Y) + v.Y * (p0.X - p1.X);\n        }\n\n        /// <summary>\n        /// Returns the left value of the point p with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float PosLeftOfLineValue(this V2f p, V2f p0, V2f p1)\n        {\n            return (p.X - p0.X) * (p0.Y - p1.Y) + (p.Y - p0.Y) * (p1.X - p0.X);\n        }\n\n        /// <summary>\n        /// Returns the right value of the point p with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float PosRightOfLineValue(this V2f p, V2f p0, V2f p1)\n        {\n            return (p.X - p0.X) * (p1.Y - p0.Y) + (p.Y - p0.Y) * (p0.X - p1.X);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LinCom(V2f p0, V2f p1, ref Tup2<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LinCom(V2f p0, V2f p1, V2f p2, ref Tup3<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LinCom(V2f p0, V2f p1, V2f p2, V2f p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LinCom(V2f p0, V2f p1, V2f p2, V2f p3, V2f p4, ref Tup5<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LinCom(V2f p0, V2f p1, V2f p2, V2f p3, V2f p4, V2f p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f LinCom(V2f p0, V2f p1, V2f p2, V2f p3, V2f p4, V2f p5, V2f p6, ref Tup7<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V2f[] pointArray, V2f point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V2f[] array, int start, int count,\n                V2f point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V2f> pointSelector, V2f point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V2f[] pointArray, V2f point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V2f[] array, long start, long count,\n                V2f point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V2f> pointSelector, V2f point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V2f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V2f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V2f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V2f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V2f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V2f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V2f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V2f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V2f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V2f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V2f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V2f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static float[] CopyCoord(this V2f[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        public static V2f WeightedSum(\n                this V2f[] vectorArray, float[] weightArray)\n        {\n            var r = V2f.Zero;\n            var count = vectorArray.LongLength;\n            for (long i = 0; i < count; i++) r += vectorArray[i] * weightArray[i];\n            return r;\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV2fExtensions\n    {\n        #region IRandomUniform extensions for V2f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of a V2f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f UniformV2f(this IRandomUniform rnd)\n        {\n            return new V2f(rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of a V2f\n        /// vector within the given Box2f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f UniformV2f(this IRandomUniform rnd, Box2f box)\n        {\n            return new V2f(box.Min.X + rnd.UniformFloat() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformFloat() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of a V2f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f UniformV2fClosed(this IRandomUniform rnd)\n        {\n            return new V2f(rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of a V2f\n        /// vector within the given Box2f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f UniformV2fClosed(this IRandomUniform rnd, Box2f box)\n        {\n            return new V2f(box.Min.X + rnd.UniformFloatClosed() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformFloatClosed() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of a V2f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f UniformV2fOpen(this IRandomUniform rnd)\n        {\n            return new V2f(rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of a V2f\n        /// vector within the given Box2f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f UniformV2fOpen(this IRandomUniform rnd, Box2f box)\n        {\n            return new V2f(box.Min.X + rnd.UniformFloatOpen() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformFloatOpen() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the unit circle). Uses UniformFloat() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2f UniformV2fDirection(this IRandomUniform rnd)\n        {\n            float phi = rnd.UniformFloat() * ConstantF.PiTimesTwo;\n            return new V2f(Fun.Cos(phi), Fun.Sin(phi));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V2d\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V2d : IVector<double>, ISize2d, IFormattable, IEquatable<V2d>\n    {\n        [DataMember]\n        public double X;\n        [DataMember]\n        public double Y;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(int x, int y)\n        {\n            X = (double)x;\n            Y = (double)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(int v)\n        {\n            X = (double)v;\n            Y = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(int[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(int[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(uint x, uint y)\n        {\n            X = (double)x;\n            Y = (double)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(uint v)\n        {\n            X = (double)v;\n            Y = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(uint[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(uint[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(long x, long y)\n        {\n            X = (double)x;\n            Y = (double)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(long v)\n        {\n            X = (double)v;\n            Y = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(long[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(long[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(float x, float y)\n        {\n            X = (double)x;\n            Y = (double)y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(float v)\n        {\n            X = (double)v;\n            Y = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(float[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(float[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(double x, double y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(double v)\n        {\n            X = v;\n            Y = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(double[] a)\n        {\n            X = a[0];\n            Y = a[1];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(double[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(Func<int, double> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;double&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 2.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(IVector<double> v)\n            : this(v[0], v[1])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V2i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V2ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V2l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V2f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V2d v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V3i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V3ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V3l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V3f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// v.Z is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V3d v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V4i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V4ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V4l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V4f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.Z, v.W are ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V2d(V4d v)\n        {\n            X = v.X;\n            Y = v.Y;\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V2i v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V2ui v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V2l v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V2f v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V3i v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V3ui v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V3l v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V3f v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V3d v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V4i v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V4ui v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V4l v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V4f v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(V4d v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V2d v)\n            => new int[] { (int)v.X, (int)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(int[] v)\n            => new V2d((double)v[0], (double)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V2d v)\n            => new uint[] { (uint)v.X, (uint)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(uint[] v)\n            => new V2d((double)v[0], (double)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V2d v)\n            => new long[] { (long)v.X, (long)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(long[] v)\n            => new V2d((double)v[0], (double)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V2d v)\n            => new float[] { (float)v.X, (float)v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(float[] v)\n            => new V2d((double)v[0], (double)v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V2d v)\n            => new double[] { v.X, v.Y };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V2d(double[] v)\n            => new V2d(v[0], v[1]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToFloorV2l()\n            => new V2l((long)Fun.Floor(X), (long)Fun.Floor(Y));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToCeilingV2l()\n            => new V2l((long)Fun.Ceiling(X), (long)Fun.Ceiling(Y));\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3iHomo()\n            => new V3i(X, Y, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3uiHomo()\n            => new V3ui(X, Y, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3lHomo()\n            => new V3l(X, Y, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3fHomo()\n            => new V3f(X, Y, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3dHomo()\n            => new V3d(X, Y, 1);\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<double, int> element_fun)\n            => new V2i(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i Copy(Func<double, int, int> element_index_fun)\n            => new V2i(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<double, uint> element_fun)\n            => new V2ui(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui Copy(Func<double, int, uint> element_index_fun)\n            => new V2ui(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<double, long> element_fun)\n            => new V2l(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l Copy(Func<double, int, long> element_index_fun)\n            => new V2l(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<double, float> element_fun)\n            => new V2f(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f Copy(Func<double, int, float> element_index_fun)\n            => new V2f(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<double, double> element_fun)\n            => new V2d(element_fun(X), element_fun(Y));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d Copy(Func<double, int, double> element_index_fun)\n            => new V2d(element_index_fun(X, 0), element_index_fun(Y, 1));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double[] ToArray()\n            => new double[] { X, Y };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? 0 : 1;\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly double MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly double MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y);\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) || Fun.IsFinite(Y);\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) && Fun.IsFinite(Y);\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(X) || double.IsNaN(Y);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(X) && double.IsNaN(Y);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(X) || double.IsInfinity(Y);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(X) && double.IsInfinity(Y);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(X) || double.IsPositiveInfinity(Y);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(X) && double.IsPositiveInfinity(Y);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(X) || double.IsNegativeInfinity(Y);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(X) && double.IsNegativeInfinity(Y);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) || Fun.IsTiny(Y);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) && Fun.IsTiny(Y);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the vector is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the vector are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 2;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V2d Zero\n        {\n            get { return new V2d(0, 0); }\n        }\n\n        /// <summary>\n        /// All elements half.\n        /// </summary>\n        public static V2d Half\n        {\n            get { return new V2d(0.5, 0.5); }\n        }\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V2d One\n        {\n            get { return new V2d(1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V2d MaxValue\n        {\n            get { return new V2d(Constant<double>.ParseableMaxValue, Constant<double>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V2d MinValue\n        {\n            get { return new V2d(Constant<double>.ParseableMinValue, Constant<double>.ParseableMinValue); }\n        }\n\n         /// <summary>\n        /// All elements set to negative infinity.\n        /// </summary>\n        public static V2d NegativeInfinity\n        {\n            get { return new V2d(double.NegativeInfinity, double.NegativeInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to positive infinity.\n        /// </summary>\n        public static V2d PositiveInfinity\n        {\n            get { return new V2d(double.PositiveInfinity, double.PositiveInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to NaN.\n        /// </summary>\n        public static V2d NaN\n        {\n            get { return new V2d(double.NaN, double.NaN); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V2d XAxis\n        {\n            get { return new V2d(1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V2d YAxis\n        {\n            get { return new V2d(0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V2d, double>[] SelectorArray =\n            new Func<V2d, double>[] { v => v.X, v => v.Y };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V2d, int, double> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V2d, int, double> Setter =\n            (ref V2d v, int i, double s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V2d, long, double> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V2d, long, double> LongSetter =\n            (ref V2d v, long i, double s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d FromV2i(V2i v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d FromV2ui(V2ui v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d FromV2l(V2l v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d FromV2f(V2f v)\n            => new V2d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d FromPolar(double angleInRadians, double radius)\n            => new V2d(Fun.Cos(angleInRadians) * radius, Fun.Sin(angleInRadians) * radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d FromPolar(double angleInRadians)\n            => new V2d(Fun.Cos(angleInRadians), Fun.Sin(angleInRadians));\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly double LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly double Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly double NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly double NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V2d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V2d.Zero;\n                s = 1 / s;\n                return new V2d(X * s, Y * s);\n            }\n        }\n\n        /// <summary>\n        /// Vector rotated 90° counter clockwise: (-Y, X)\n        /// </summary>\n        public readonly V2d Rot90\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2d(-Y, X); }\n        }\n\n        /// <summary>\n        /// Vector rotated 180° counter clockwise: (-X, -Y)\n        /// </summary>\n        public readonly V2d Rot180\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2d(-X, -Y); }\n        }\n\n        /// <summary>\n        /// Vector rotated 270° counter clockwise: (Y, -X)\n        /// </summary>\n        public readonly V2d Rot270\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2d(Y, -X); }\n        }\n\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered square with side length 2.\n        /// </summary>\n        public readonly V2d CubeMapped\n        {\n            get\n            {\n                double x = Fun.Abs(X);\n                double y = Fun.Abs(Y);\n                return x > y\n                        ? new V2d(Fun.Sign(X), Y / x)\n                        : new V2d(X / y, Fun.Sign(Y));\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Abs(V2d v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Floor(V2d v)\n            => v.Floor();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Ceiling(V2d v)\n            => v.Ceiling();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Round(V2d v)\n            => v.Round();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Truncate(V2d v)\n            => v.Truncate();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Acos(V2d v)\n            => Fun.Acos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Acoshb(V2d v)\n            => Fun.Acosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Cos(V2d v)\n            => Fun.Cos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Cosh(V2d v)\n            => Fun.Cosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Asin(V2d v)\n            => Fun.Asin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Asinhb(V2d v)\n            => Fun.Asinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sin(V2d v)\n            => Fun.Sin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sinh(V2d v)\n            => Fun.Sinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Atan(V2d v)\n            => Fun.Atan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Atanhb(V2d v)\n            => Fun.Atanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Atan2(V2d a, V2d b)\n            => Fun.Atan2(a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Tan(V2d v)\n            => Fun.Tan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Tanh(V2d v)\n            => Fun.Tanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sqrt(V2d v)\n            => Fun.Sqrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d CubeRoot(V2d v)\n            => Fun.Cbrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Exp(V2d v)\n            => Fun.Exp(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(V2d v)\n            => Fun.Log(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LogBinary(V2d v)\n            => Fun.Log2(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log10(V2d v)\n            => Fun.Log10(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d CopySgn(V2d value, V2d sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d CopySgn(V2d value, double sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LinearInterp(double t, V2d a, V2d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LinearInterp(V2d t, V2d a, V2d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Min(V2d v0, V2d v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Min(V2d v, double x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Max(V2d v0, V2d v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Max(V2d v, double x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Saturate(V2d v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d DivideByInt(V2d v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y)\n        {\n            X = (double)x;\n            Y = (double)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y)\n        {\n            X = (double)x;\n            Y = (double)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y)\n        {\n            X = (double)x;\n            Y = (double)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y)\n        {\n            X = (double)x;\n            Y = (double)y;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y)\n        {\n            X = x;\n            Y = y;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator -(V2d v)\n            => new V2d(-v.X, -v.Y);\n\n        /// <summary>\n        /// Returns a vector that is orthogonal to this one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        public readonly V2d Orthogonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2d(-Y, X); }\n        }\n\n        /// <summary>\n        /// Gets a copy of this vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        public readonly V2d Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V2d(1 / X, 1 / Y); }\n        }\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator +(V2d a, V2d b)\n            => new V2d(a.X + b.X, a.Y + b.Y);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator +(V2d v, double s)\n            => new V2d(v.X + s, v.Y + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator +(double s, V2d v)\n            => new V2d(s + v.X, s + v.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator -(V2d a, V2d b)\n            => new V2d(a.X - b.X, a.Y - b.Y);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator -(V2d v, double s)\n            => new V2d(v.X - s, v.Y - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator -(double s, V2d v)\n            => new V2d(s - v.X, s - v.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(V2d a, V2d b)\n            => new V2d(a.X * b.X, a.Y * b.Y);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(V2d v, double s)\n            => new V2d(v.X * s, v.Y * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator *(double s, V2d v)\n            => new V2d(s * v.X, s * v.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator /(V2d a, V2d b)\n            => new V2d(a.X / b.X, a.Y / b.Y);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator /(V2d v, double s)\n            => new V2d(v.X / s, v.Y / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator /(double s, V2d v)\n            => new V2d(s / v.X, s / v.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator %(V2d a, V2d b)\n            => new V2d(a.X % b.X, a.Y % b.Y);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator %(V2d v, double s)\n            => new V2d(v.X % s, v.Y % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d operator %(double s, V2d v)\n            => new V2d(s % v.X, s % v.Y);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2d a, V2d b)\n        {\n            return a.X == b.X && a.Y == b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V2d v, double s)\n        {\n            return v.X == s && v.Y == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(double s, V2d v)\n        {\n            return s == v.X && s == v.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2d a, V2d b)\n        {\n            return a.X != b.X || a.Y != b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V2d v, double s)\n        {\n            return v.X != s || v.Y != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(double s, V2d v)\n        {\n            return s != v.X || s != v.Y;\n        }\n\n        #endregion\n\n        #region IEquatable<V2d> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V2d other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V2d o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V2d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V2d(\n                double.Parse(x[0], CultureInfo.InvariantCulture), \n                double.Parse(x[1], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V2d Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<double>.Parse, V2d.Setter);\n        }\n\n        public static V2d Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<double>.Parse, V2d.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d OO => new V2d(0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d OI => new V2d(0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d ON => new V2d(0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OX => new V2d(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OY => new V2d(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d IO => new V2d(1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d II => new V2d(1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d PN => new V2d(1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IX => new V2d(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IY => new V2d(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d NO => new V2d(-1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d NP => new V2d(-1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V2d NN => new V2d(-1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NX => new V2d(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NY => new V2d(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XO => new V2d(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XI => new V2d(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XN => new V2d(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XX => new V2d(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d XY\n        {\n            readonly get => new V2d(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YO => new V2d(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YI => new V2d(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YN => new V2d(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d YX\n        {\n            readonly get => new V2d(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YY => new V2d(Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOX => new V3d(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOY => new V3d(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIX => new V3d(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIY => new V3d(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONX => new V3d(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONY => new V3d(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXO => new V3d(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXI => new V3d(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXN => new V3d(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXX => new V3d(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXY => new V3d(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYO => new V3d(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYI => new V3d(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYN => new V3d(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYX => new V3d(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYY => new V3d(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOX => new V3d(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOY => new V3d(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIX => new V3d(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIY => new V3d(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNX => new V3d(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNY => new V3d(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXO => new V3d(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXI => new V3d(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PXN => new V3d(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXX => new V3d(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXY => new V3d(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYO => new V3d(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYI => new V3d(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PYN => new V3d(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYX => new V3d(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYY => new V3d(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOX => new V3d(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOY => new V3d(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPX => new V3d(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPY => new V3d(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNX => new V3d(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNY => new V3d(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXO => new V3d(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXP => new V3d(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXN => new V3d(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXX => new V3d(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXY => new V3d(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYO => new V3d(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYP => new V3d(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYN => new V3d(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYX => new V3d(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYY => new V3d(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOO => new V3d(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOI => new V3d(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XON => new V3d(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOX => new V3d(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOY => new V3d(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIO => new V3d(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XII => new V3d(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XPN => new V3d(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIX => new V3d(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIY => new V3d(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNO => new V3d(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNP => new V3d(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNN => new V3d(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNX => new V3d(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNY => new V3d(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXO => new V3d(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXI => new V3d(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXN => new V3d(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXX => new V3d(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXY => new V3d(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYO => new V3d(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYI => new V3d(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYN => new V3d(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYX => new V3d(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYY => new V3d(X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOO => new V3d(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOI => new V3d(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YON => new V3d(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOX => new V3d(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOY => new V3d(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIO => new V3d(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YII => new V3d(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YPN => new V3d(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIX => new V3d(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIY => new V3d(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNO => new V3d(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNP => new V3d(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNN => new V3d(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNX => new V3d(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNY => new V3d(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXO => new V3d(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXI => new V3d(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXN => new V3d(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXX => new V3d(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXY => new V3d(Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYO => new V3d(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYI => new V3d(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYN => new V3d(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYX => new V3d(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYY => new V3d(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOX => new V4d(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOY => new V4d(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIX => new V4d(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIY => new V4d(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONX => new V4d(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONY => new V4d(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXO => new V4d(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXI => new V4d(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXN => new V4d(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXX => new V4d(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXY => new V4d(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYO => new V4d(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYI => new V4d(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYN => new V4d(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYX => new V4d(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYY => new V4d(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOX => new V4d(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOY => new V4d(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIX => new V4d(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIY => new V4d(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNX => new V4d(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNY => new V4d(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXO => new V4d(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXI => new V4d(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPXN => new V4d(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXX => new V4d(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXY => new V4d(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYO => new V4d(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYI => new V4d(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPYN => new V4d(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYX => new V4d(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYY => new V4d(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOX => new V4d(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOY => new V4d(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPX => new V4d(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPY => new V4d(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNX => new V4d(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNY => new V4d(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXO => new V4d(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXP => new V4d(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXN => new V4d(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXX => new V4d(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXY => new V4d(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYO => new V4d(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYP => new V4d(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYN => new V4d(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYX => new V4d(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYY => new V4d(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOO => new V4d(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOI => new V4d(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXON => new V4d(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOX => new V4d(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOY => new V4d(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIO => new V4d(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXII => new V4d(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXPN => new V4d(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIX => new V4d(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIY => new V4d(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNO => new V4d(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNP => new V4d(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNN => new V4d(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNX => new V4d(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNY => new V4d(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXO => new V4d(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXI => new V4d(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXN => new V4d(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXX => new V4d(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXY => new V4d(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYO => new V4d(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYI => new V4d(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYN => new V4d(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYX => new V4d(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYY => new V4d(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOO => new V4d(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOI => new V4d(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYON => new V4d(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOX => new V4d(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOY => new V4d(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIO => new V4d(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYII => new V4d(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYPN => new V4d(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIX => new V4d(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIY => new V4d(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNO => new V4d(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNP => new V4d(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNN => new V4d(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNX => new V4d(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNY => new V4d(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXO => new V4d(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXI => new V4d(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXN => new V4d(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXX => new V4d(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXY => new V4d(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYO => new V4d(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYI => new V4d(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYN => new V4d(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYX => new V4d(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYY => new V4d(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOX => new V4d(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOY => new V4d(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIX => new V4d(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIY => new V4d(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONX => new V4d(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONY => new V4d(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXO => new V4d(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXI => new V4d(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POXN => new V4d(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXX => new V4d(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXY => new V4d(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYO => new V4d(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYI => new V4d(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POYN => new V4d(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYX => new V4d(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYY => new V4d(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOX => new V4d(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOY => new V4d(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIX => new V4d(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIY => new V4d(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNX => new V4d(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNY => new V4d(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXO => new V4d(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXI => new V4d(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPXN => new V4d(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXX => new V4d(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXY => new V4d(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYO => new V4d(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYI => new V4d(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPYN => new V4d(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYX => new V4d(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYY => new V4d(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOX => new V4d(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOY => new V4d(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPX => new V4d(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPY => new V4d(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNX => new V4d(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNY => new V4d(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXO => new V4d(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXP => new V4d(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXN => new V4d(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXX => new V4d(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXY => new V4d(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYO => new V4d(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYP => new V4d(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYN => new V4d(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYX => new V4d(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYY => new V4d(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOO => new V4d(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOI => new V4d(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXON => new V4d(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOX => new V4d(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOY => new V4d(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIO => new V4d(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXII => new V4d(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXPN => new V4d(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIX => new V4d(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIY => new V4d(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNO => new V4d(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNP => new V4d(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNN => new V4d(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNX => new V4d(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNY => new V4d(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXO => new V4d(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXI => new V4d(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXXN => new V4d(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXX => new V4d(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXY => new V4d(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYO => new V4d(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYI => new V4d(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXYN => new V4d(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYX => new V4d(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYY => new V4d(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOO => new V4d(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOI => new V4d(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYON => new V4d(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOX => new V4d(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOY => new V4d(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIO => new V4d(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYII => new V4d(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYPN => new V4d(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIX => new V4d(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIY => new V4d(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNO => new V4d(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNP => new V4d(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNN => new V4d(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNX => new V4d(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNY => new V4d(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXO => new V4d(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXI => new V4d(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYXN => new V4d(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXX => new V4d(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXY => new V4d(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYO => new V4d(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYI => new V4d(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYYN => new V4d(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYX => new V4d(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYY => new V4d(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOX => new V4d(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOY => new V4d(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPX => new V4d(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPY => new V4d(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONX => new V4d(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONY => new V4d(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXO => new V4d(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXP => new V4d(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXN => new V4d(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXX => new V4d(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXY => new V4d(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYO => new V4d(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYP => new V4d(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYN => new V4d(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYX => new V4d(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYY => new V4d(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOX => new V4d(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOY => new V4d(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPX => new V4d(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPY => new V4d(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNX => new V4d(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNY => new V4d(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXO => new V4d(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXP => new V4d(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXN => new V4d(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXX => new V4d(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXY => new V4d(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYO => new V4d(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYP => new V4d(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYN => new V4d(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYX => new V4d(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYY => new V4d(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOX => new V4d(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOY => new V4d(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPX => new V4d(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPY => new V4d(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNX => new V4d(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNY => new V4d(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXO => new V4d(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXP => new V4d(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXN => new V4d(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXX => new V4d(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXY => new V4d(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYO => new V4d(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYP => new V4d(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYN => new V4d(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYX => new V4d(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYY => new V4d(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOO => new V4d(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOP => new V4d(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXON => new V4d(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOX => new V4d(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOY => new V4d(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPO => new V4d(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPP => new V4d(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPN => new V4d(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPX => new V4d(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPY => new V4d(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNO => new V4d(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNP => new V4d(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNN => new V4d(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNX => new V4d(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNY => new V4d(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXO => new V4d(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXP => new V4d(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXN => new V4d(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXX => new V4d(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXY => new V4d(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYO => new V4d(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYP => new V4d(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYN => new V4d(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYX => new V4d(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYY => new V4d(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOO => new V4d(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOP => new V4d(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYON => new V4d(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOX => new V4d(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOY => new V4d(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPO => new V4d(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPP => new V4d(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPN => new V4d(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPX => new V4d(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPY => new V4d(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNO => new V4d(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNP => new V4d(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNN => new V4d(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNX => new V4d(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNY => new V4d(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXO => new V4d(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXP => new V4d(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXN => new V4d(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXX => new V4d(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXY => new V4d(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYO => new V4d(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYP => new V4d(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYN => new V4d(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYX => new V4d(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYY => new V4d(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOO => new V4d(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOI => new V4d(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOON => new V4d(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOX => new V4d(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOY => new V4d(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIO => new V4d(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOII => new V4d(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOPN => new V4d(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIX => new V4d(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIY => new V4d(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONO => new V4d(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONP => new V4d(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONN => new V4d(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONX => new V4d(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONY => new V4d(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXO => new V4d(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXI => new V4d(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXN => new V4d(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXX => new V4d(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXY => new V4d(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYO => new V4d(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYI => new V4d(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYN => new V4d(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYX => new V4d(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYY => new V4d(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOO => new V4d(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOI => new V4d(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPON => new V4d(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOX => new V4d(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOY => new V4d(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIO => new V4d(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIII => new V4d(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPPN => new V4d(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIX => new V4d(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIY => new V4d(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNO => new V4d(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNP => new V4d(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNN => new V4d(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNX => new V4d(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNY => new V4d(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXO => new V4d(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXI => new V4d(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPXN => new V4d(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXX => new V4d(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXY => new V4d(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYO => new V4d(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYI => new V4d(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPYN => new V4d(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYX => new V4d(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYY => new V4d(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOO => new V4d(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOP => new V4d(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNON => new V4d(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOX => new V4d(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOY => new V4d(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPO => new V4d(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPP => new V4d(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPN => new V4d(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPX => new V4d(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPY => new V4d(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNO => new V4d(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNP => new V4d(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNN => new V4d(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNX => new V4d(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNY => new V4d(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXO => new V4d(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXP => new V4d(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXN => new V4d(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXX => new V4d(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXY => new V4d(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYO => new V4d(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYP => new V4d(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYN => new V4d(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYX => new V4d(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYY => new V4d(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOO => new V4d(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOI => new V4d(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXON => new V4d(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOX => new V4d(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOY => new V4d(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIO => new V4d(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXII => new V4d(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXPN => new V4d(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIX => new V4d(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIY => new V4d(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNO => new V4d(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNP => new V4d(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNN => new V4d(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNX => new V4d(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNY => new V4d(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXO => new V4d(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXI => new V4d(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXN => new V4d(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXX => new V4d(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXY => new V4d(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYO => new V4d(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYI => new V4d(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYN => new V4d(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYX => new V4d(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYY => new V4d(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOO => new V4d(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOI => new V4d(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYON => new V4d(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOX => new V4d(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOY => new V4d(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIO => new V4d(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYII => new V4d(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYPN => new V4d(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIX => new V4d(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIY => new V4d(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNO => new V4d(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNP => new V4d(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNN => new V4d(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNX => new V4d(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNY => new V4d(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXO => new V4d(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXI => new V4d(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXN => new V4d(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXX => new V4d(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXY => new V4d(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYO => new V4d(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYI => new V4d(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYN => new V4d(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYX => new V4d(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYY => new V4d(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOO => new V4d(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOI => new V4d(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOON => new V4d(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOX => new V4d(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOY => new V4d(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIO => new V4d(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOII => new V4d(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOPN => new V4d(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIX => new V4d(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIY => new V4d(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONO => new V4d(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONP => new V4d(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONN => new V4d(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONX => new V4d(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONY => new V4d(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXO => new V4d(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXI => new V4d(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXN => new V4d(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXX => new V4d(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXY => new V4d(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYO => new V4d(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYI => new V4d(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYN => new V4d(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYX => new V4d(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYY => new V4d(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOO => new V4d(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOI => new V4d(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPON => new V4d(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOX => new V4d(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOY => new V4d(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIO => new V4d(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIII => new V4d(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPPN => new V4d(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIX => new V4d(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIY => new V4d(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNO => new V4d(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNP => new V4d(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNN => new V4d(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNX => new V4d(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNY => new V4d(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXO => new V4d(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXI => new V4d(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPXN => new V4d(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXX => new V4d(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXY => new V4d(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYO => new V4d(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYI => new V4d(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPYN => new V4d(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYX => new V4d(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYY => new V4d(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOO => new V4d(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOP => new V4d(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNON => new V4d(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOX => new V4d(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOY => new V4d(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPO => new V4d(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPP => new V4d(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPN => new V4d(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPX => new V4d(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPY => new V4d(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNO => new V4d(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNP => new V4d(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNN => new V4d(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNX => new V4d(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNY => new V4d(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXO => new V4d(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXP => new V4d(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXN => new V4d(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXX => new V4d(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXY => new V4d(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYO => new V4d(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYP => new V4d(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYN => new V4d(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYX => new V4d(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYY => new V4d(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOO => new V4d(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOI => new V4d(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXON => new V4d(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOX => new V4d(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOY => new V4d(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIO => new V4d(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXII => new V4d(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXPN => new V4d(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIX => new V4d(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIY => new V4d(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNO => new V4d(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNP => new V4d(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNN => new V4d(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNX => new V4d(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNY => new V4d(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXO => new V4d(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXI => new V4d(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXN => new V4d(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXX => new V4d(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXY => new V4d(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYO => new V4d(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYI => new V4d(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYN => new V4d(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYX => new V4d(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYY => new V4d(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOO => new V4d(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOI => new V4d(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYON => new V4d(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOX => new V4d(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOY => new V4d(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIO => new V4d(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYII => new V4d(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYPN => new V4d(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIX => new V4d(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIY => new V4d(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNO => new V4d(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNP => new V4d(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNN => new V4d(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNX => new V4d(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNY => new V4d(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXO => new V4d(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXI => new V4d(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXN => new V4d(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXX => new V4d(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXY => new V4d(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYO => new V4d(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYI => new V4d(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYN => new V4d(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYX => new V4d(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYY => new V4d(Y, Y, Y, Y);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (double)value; }\n        }\n\n        #endregion\n\n        #region ISize2d Members\n\n        public readonly V2d Size2d { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 2; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (double)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V2dEqualityComparer : IEqualityComparer<V2d>\n    {\n        public static V2dEqualityComparer Default\n            => new V2dEqualityComparer();\n\n        #region IEqualityComparer<V2d> Members\n\n        public bool Equals(V2d v0, V2d v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V2d v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Min(this V2d a, V2d b)\n        {\n            return new V2d(Min(a.X, b.X), Min(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Min(this V2d a, double b)\n        {\n            return new V2d(Min(a.X, b), Min(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Min(this double a, V2d b)\n        {\n            return new V2d(Min(a, b.X), Min(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Max(this V2d a, V2d b)\n        {\n            return new V2d(Max(a.X, b.X), Max(a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Max(this V2d a, double b)\n        {\n            return new V2d(Max(a.X, b), Max(a.Y, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Max(this double a, V2d b)\n        {\n            return new V2d(Max(a, b.X), Max(a, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Min(this V2d a, V2d b, V2d c)\n        {\n            return new V2d(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Max(this V2d a, V2d b, V2d c)\n        {\n            return new V2d(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Min(this V2d a, V2d b, V2d c, V2d d)\n        {\n            return new V2d(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Max(this V2d a, V2d b, V2d c, V2d d)\n        {\n            return new V2d(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Min(this V2d x, params V2d[] values)\n        {\n            return new V2d(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Max(this V2d x, params V2d[] values)\n        {\n            return new V2d(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Abs(this V2d x)\n        {\n            return new V2d(Abs(x.X), Abs(x.Y));\n        }\n\n        #endregion\n\n        #region Rounding\n\n        /// <summary>\n        /// Applies Fun.Floor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Floor(this V2d x)\n        {\n            return new V2d(Floor(x.X), Floor(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Ceiling to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Ceiling(this V2d x)\n        {\n            return new V2d(Ceiling(x.X), Ceiling(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Round(this V2d x)\n        {\n            return new V2d(Round(x.X), Round(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Round(this V2d x, MidpointRounding mode)\n        {\n            return new V2d(Round(x.X, mode), Round(x.Y, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Round(this V2d x, int digits)\n        {\n            return new V2d(Round(x.X, digits), Round(x.Y, digits));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Round(this V2d x, int digits, MidpointRounding mode)\n        {\n            return new V2d(Round(x.X, digits, mode), Round(x.Y, digits, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Truncate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Truncate(this V2d x)\n        {\n            return new V2d(Truncate(x.X), Truncate(x.Y));\n        }\n\n        #endregion\n\n        #region Frac\n\n        /// <summary>\n        /// Applies Fun.Frac to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Frac(this V2d x)\n        {\n            return new V2d(Frac(x.X), Frac(x.Y));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Clamp(this V2d x, V2d a, V2d b)\n        {\n            return new V2d(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Clamp(this V2d x, double a, double b)\n        {\n            return new V2d(Clamp(x.X, a, b), Clamp(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d ClampWrap(this V2d x, V2d a, V2d b)\n        {\n            return new V2d(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d ClampWrap(this V2d x, double a, double b)\n        {\n            return new V2d(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Saturate(this V2d x)\n        {\n            return new V2d(Saturate(x.X), Saturate(x.Y));\n        }\n\n        #endregion\n\n        #region MapToUnitInterval\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d MapToUnitInterval(this V2d t, V2d tMax, bool repeat, bool mirror)\n        {\n            return new V2d(MapToUnitInterval(t.X, tMax.X, repeat, mirror), MapToUnitInterval(t.Y, tMax.Y, repeat, mirror));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d MapToUnitInterval(this V2d t, V2d tMax, bool repeat)\n        {\n            return new V2d(MapToUnitInterval(t.X, tMax.X, repeat), MapToUnitInterval(t.Y, tMax.Y, repeat));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d MapToUnitInterval(this V2d t, V2d tMax)\n        {\n            return new V2d(MapToUnitInterval(t.X, tMax.X), MapToUnitInterval(t.Y, tMax.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d MapToUnitInterval(this V2d t, V2d tMin, V2d tMax)\n        {\n            return new V2d(MapToUnitInterval(t.X, tMin.X, tMax.X), MapToUnitInterval(t.Y, tMin.Y, tMax.Y));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Sign(this V2d x)\n        {\n            return new V2i(Sign(x.X), Sign(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Signumi(this V2d x)\n        {\n            return new V2i(Signumi(x.X), Signumi(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Signum(this V2d x)\n        {\n            return new V2d(Signum(x.X), Signum(x.Y));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d MultiplyAdd(V2d x, V2d y, V2d z)\n        {\n            return new V2d(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d MultiplyAdd(V2d x, double y, V2d z)\n        {\n            return new V2d(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d MultiplyAdd(double x, V2d y, V2d z)\n        {\n            return new V2d(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y));\n        }\n\n        #endregion\n\n        #region Copy sign\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d CopySign(V2d value, V2d sign)\n        {\n            return new V2d(CopySign(value.X, sign.X), CopySign(value.Y, sign.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d CopySign(double value, V2d sign)\n        {\n            return new V2d(CopySign(value, sign.X), CopySign(value, sign.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d CopySign(V2d value, double sign)\n        {\n            return new V2d(CopySign(value.X, sign), CopySign(value.Y, sign));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sqrt(this V2d x)\n        {\n            return new V2d(Sqrt(x.X), Sqrt(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Cbrt(this V2d x)\n        {\n            return new V2d(Cbrt(x.X), Cbrt(x.Y));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Square(this V2d x)\n        {\n            return new V2d(Square(x.X), Square(x.Y));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pown(this V2d x, V2i y)\n        {\n            return new V2d(Pown(x.X, y.X), Pown(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pown(this V2d x, int y)\n        {\n            return new V2d(Pown(x.X, y), Pown(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pown(this double x, V2i y)\n        {\n            return new V2d(Pown(x, y.X), Pown(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this V2d x, V2d y)\n        {\n            return new V2d(Pow(x.X, y.X), Pow(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this V2d x, double y)\n        {\n            return new V2d(Pow(x.X, y), Pow(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Pow(this double x, V2d y)\n        {\n            return new V2d(Pow(x, y.X), Pow(x, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this V2d x, V2d y)\n        {\n            return new V2d(Power(x.X, y.X), Power(x.Y, y.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this V2d x, double y)\n        {\n            return new V2d(Power(x.X, y), Power(x.Y, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Power(this double x, V2d y)\n        {\n            return new V2d(Power(x, y.X), Power(x, y.Y));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Exp(this V2d x)\n        {\n            return new V2d(Exp(x.X), Exp(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(this V2d x)\n        {\n            return new V2d(Log(x.X), Log(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log2(this V2d x)\n        {\n            return new V2d(Log2(x.X), Log2(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2i Log2Int(this V2d x)\n        {\n            return new V2i(Log2Int(x.X), Log2Int(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log10(this V2d x)\n        {\n            return new V2d(Log10(x.X), Log10(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Log(this V2d x, double basis)\n        {\n            return new V2d(Log(x.X, basis), Log(x.Y, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d ModP(this V2d a, V2d b)\n        {\n            return new V2d(ModP(a.X, b.X), ModP(a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d PowerOfTwo(this V2d x)\n        {\n            return new V2d(PowerOfTwo(x.X), PowerOfTwo(x.Y));\n        }\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Applies Fun.Sin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sin(this V2d x)\n        {\n            return new V2d(Sin(x.X), Sin(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Cos(this V2d x)\n        {\n            return new V2d(Cos(x.X), Cos(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Tan(this V2d x)\n        {\n            return new V2d(Tan(x.X), Tan(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Asin(this V2d x)\n        {\n            return new V2d(Asin(x.X), Asin(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.AsinClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d AsinClamped(this V2d x)\n        {\n            return new V2d(AsinClamped(x.X), AsinClamped(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Acos(this V2d x)\n        {\n            return new V2d(Acos(x.X), Acos(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.AcosClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d AcosClamped(this V2d x)\n        {\n            return new V2d(AcosClamped(x.X), AcosClamped(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Atan(this V2d x)\n        {\n            return new V2d(Atan(x.X), Atan(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Atan2(V2d y, V2d x)\n        {\n            return new V2d(Atan2(y.X, x.X), Atan2(y.Y, x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.FastAtan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d FastAtan2(V2d y, V2d x)\n        {\n            return new V2d(FastAtan2(y.X, x.X), FastAtan2(y.Y, x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Sinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Sinh(this V2d x)\n        {\n            return new V2d(Sinh(x.X), Sinh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Cosh(this V2d x)\n        {\n            return new V2d(Cosh(x.X), Cosh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Tanh(this V2d x)\n        {\n            return new V2d(Tanh(x.X), Tanh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Asinh(this V2d x)\n        {\n            return new V2d(Asinh(x.X), Asinh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Acosh(this V2d x)\n        {\n            return new V2d(Acosh(x.X), Acosh(x.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Atanh(this V2d x)\n        {\n            return new V2d(Atanh(x.X), Atanh(x.Y));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Step(this V2d x, V2d edge)\n        {\n            return new V2d(Step(x.X, edge.X), Step(x.Y, edge.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Step(this V2d x, double edge)\n        {\n            return new V2d(Step(x.X, edge), Step(x.Y, edge));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Linearstep(this V2d x, V2d edge0, V2d edge1)\n        {\n            return new V2d(Linearstep(x.X, edge0.X, edge1.X), Linearstep(x.Y, edge0.Y, edge1.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Linearstep(this V2d x, double edge0, double edge1)\n        {\n            return new V2d(Linearstep(x.X, edge0, edge1), Linearstep(x.Y, edge0, edge1));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Smoothstep(this V2d x, V2d edge0, V2d edge1)\n        {\n            return new V2d(Smoothstep(x.X, edge0.X, edge1.X), Smoothstep(x.Y, edge0.Y, edge1.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Smoothstep(this V2d x, double edge0, double edge1)\n        {\n            return new V2d(Smoothstep(x.X, edge0, edge1), Smoothstep(x.Y, edge0, edge1));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Lerp(this double t, V2d a, V2d b)\n        {\n            return new V2d(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Lerp(this V2d t, V2d a, V2d b)\n        {\n            return new V2d(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d InvLerp(this V2d y, V2d a, V2d b)\n        {\n            return new V2d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatToBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2l FloatToBits(this V2d x)\n        {\n            return new V2l(FloatToBits(x.X), FloatToBits(x.Y));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V2d a, V2d b, double tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within\n        /// Constant{double}.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V2d a, V2d b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V2d v, double epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(V2d v)\n            => v.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"V2d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(V2d v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V2d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(V2d v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V2d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(V2d v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V2d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(V2d v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"V2d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(V2d v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts the angles given in degrees to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d RadiansFromDegrees(this V2d degrees)\n            => new V2d(\n                   RadiansFromDegrees(degrees.X), \n                   RadiansFromDegrees(degrees.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d RadiansFromGons(this V2d gons)\n            => new V2d(\n                   RadiansFromGons(gons.X), \n                   RadiansFromGons(gons.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d DegreesFromRadians(this V2d radians)\n            => new V2d(\n                   DegreesFromRadians(radians.X), \n                   DegreesFromRadians(radians.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d DegreesFromGons(this V2d gons)\n            => new V2d(\n                   DegreesFromGons(gons.X), \n                   DegreesFromGons(gons.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GonsFromRadians(this V2d radians)\n            => new V2d(\n                   GonsFromRadians(radians.X), \n                   GonsFromRadians(radians.Y)\n               );\n\n        /// <summary>\n        /// Converts the angles given in degrees to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d GonsFromDegrees(this V2d degrees)\n            => new V2d(\n                   GonsFromDegrees(degrees.X), \n                   GonsFromDegrees(degrees.Y)\n               );\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LengthSquared(V2d v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V2d v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Normalizes the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref V2d v)\n        {\n            var s = v.Length; if (s == 0) return;\n            s = 1 / s;\n            v.X *= s;\n            v.Y *= s;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Normalized(V2d v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm1(V2d v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V2d v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMax(V2d v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMin(V2d v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V2d v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceSquared(this V2d a, V2d b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V2d a, V2d b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance1(this V2d a, V2d b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V2d a, V2d b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceMax(this V2d a, V2d b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceMin(this V2d a, V2d b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V2d query, V2d p0, V2d p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            if (t <= 0) { return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V2d query, V2d p0, V2d p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V2d query, V2d p0, V2d p1, out double t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            if (t <= 0) { t = 0; return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { t = 1; return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V2d query, V2d p0, V2d p1, out double t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns a vector that is orthogonal to the given one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Orthogonal(V2d v)\n            => v.Orthogonal;\n\n        /// <summary>\n        /// Gets a copy of the given vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Reciprocal(V2d v)\n            => v.Reciprocal;\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V2d v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 2x2 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M22d Outer(this V2d a, V2d b)\n        {\n            return new M22d(\n                        a.X * b.X, a.X * b.Y, \n                        a.Y * b.X, a.Y * b.Y);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Dot(this V2d a, V2d b)\n        {\n            return a.X * b.X + a.Y * b.Y;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V2d v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeY;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the reflection direction of the given vector v (pointing to the surface) for the given normal (should be normalized).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Reflect(this V2d v, V2d normal)\n        {\n            return v - 2 * v.Dot(normal) * normal;\n        }\n\n        /// <summary>\n        /// Returns the refraction direction of the given vector v (pointing to the surface) for the given normal and ratio of refraction indices (n_out / n_in).\n        /// Both the input vectors should be normalized.\n        /// Returns a zero-vector in case of total internal reflection.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d Refract(this V2d v, V2d normal, double eta)\n        {\n            var t = v.Dot(normal);\n            var k = 1 - eta * eta * (1 - t * t);\n\n            if (k < 0)\n            {\n                return V2d.Zero;\n            }\n            else\n            {\n                return eta * v - (eta * t + Fun.Sqrt(k)) * normal;\n            }\n        }\n\n        /// <summary>\n        /// Returns the cross product of vector a.\n        /// In 2D the cross product is simply a vector that is normal\n        /// to the given vector (i.e. {x,y} -> {-y,x})\n        /// </summary>\n        public static V2d Cross(this V2d a)\n        {\n            return new V2d(-a.Y, a.X);\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2d a, V2d b)\n        {\n            return (a.X < b.X && a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V2d v, double s)\n        {\n            return (v.X < s && v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, V2d v)\n        {\n            return (s < v.X && s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2d a, V2d b)\n        {\n            return (a.X < b.X || a.Y < b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V2d v, double s)\n        {\n            return (v.X < s || v.Y < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, V2d v)\n        {\n            return (s < v.X || s < v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2d a, V2d b)\n        {\n            return (a.X > b.X && a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V2d v, double s)\n        {\n            return (v.X > s && v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, V2d v)\n        {\n            return (s > v.X && s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2d a, V2d b)\n        {\n            return (a.X > b.X || a.Y > b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V2d v, double s)\n        {\n            return (v.X > s || v.Y > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, V2d v)\n        {\n            return (s > v.X || s > v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2d a, V2d b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V2d v, double s)\n        {\n            return (v.X <= s && v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, V2d v)\n        {\n            return (s <= v.X && s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2d a, V2d b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V2d v, double s)\n        {\n            return (v.X <= s || v.Y <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, V2d v)\n        {\n            return (s <= v.X || s <= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2d a, V2d b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V2d v, double s)\n        {\n            return (v.X >= s && v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, V2d v)\n        {\n            return (s >= v.X && s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2d a, V2d b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V2d v, double s)\n        {\n            return (v.X >= s || v.Y >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, V2d v)\n        {\n            return (s >= v.X || s >= v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2d a, V2d b)\n        {\n            return (a.X == b.X && a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V2d v, double s)\n        {\n            return (v.X == s && v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, V2d v)\n        {\n            return (s == v.X && s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2d a, V2d b)\n        {\n            return (a.X == b.X || a.Y == b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V2d v, double s)\n        {\n            return (v.X == s || v.Y == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, V2d v)\n        {\n            return (s == v.X || s == v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2d a, V2d b)\n        {\n            return (a.X != b.X && a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V2d v, double s)\n        {\n            return (v.X != s && v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, V2d v)\n        {\n            return (s != v.X && s != v.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2d a, V2d b)\n        {\n            return (a.X != b.X || a.Y != b.Y);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V2d v, double s)\n        {\n            return (v.X != s || v.Y != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, V2d v)\n        {\n            return (s != v.X || s != v.Y);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V2d v0, V2d v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MinElement(V2d v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V2d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MaxElement(V2d v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region Angle between two vectors\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleBetweenFast(this V2d x, V2d y)\n        {\n            return Fun.AcosClamped(x.Dot(y));\n        }\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians using a numerically stable algorithm.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        // https://scicomp.stackexchange.com/a/27769\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleBetween(this V2d x, V2d y)\n        {\n            var a = x + y;\n            var b = x - y;\n            return 2 * Fun.Atan2(b.Length, a.Length);\n        }\n\n        /// <summary>\n        /// Computes the signed angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleBetweenSigned(this V2d x, V2d y)\n        {\n            var a = x.X * y.Y - x.Y * y.X;\n            var b = x.X * y.X + x.Y * y.Y;\n            return Fun.Atan2(a, b);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V2d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V2d v, double epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V2d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V2d v, double epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(V2d v)\n            => v.AnyFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(V2d v)\n            => v.AllFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(V2d v)\n            => v.AnyNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(V2d v)\n            => v.AllNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(V2d v)\n            => v.AnyInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(V2d v)\n            => v.AllInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(V2d v)\n            => v.AnyPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(V2d v)\n            => v.AllPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(V2d v)\n            => v.AnyNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(V2d v)\n            => v.AllNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(V2d v)\n            => v.AnyTiny;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(V2d v)\n            => v.AllTiny;\n\n        #endregion\n\n        #region 2D Vector Arithmetics\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 90 degrees counterclockwise.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Dot90(this V2d v, V2d dir)\n        {\n            return v.Y * dir.X - v.X * dir.Y;\n        }\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 180 degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Dot180(this V2d v, V2d dir)\n        {\n            return -(v.X * dir.X + v.Y * dir.Y);\n        }\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 270 degrees counterclockwise.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Dot270(this V2d v, V2d dir)\n        {\n            return v.X * dir.Y - v.Y * dir.X;\n        }\n\n        /// <summary>\n        /// Returns the left value of the direction v with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DirLeftOfLineValue(this V2d v, V2d p0, V2d p1)\n        {\n            return v.X * (p0.Y - p1.Y) + v.Y * (p1.X - p0.X);\n        }\n\n        /// <summary>\n        /// Returns the right value of the direction v with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DirRightOfLineValue(this V2d v, V2d p0, V2d p1)\n        {\n            return v.X * (p1.Y - p0.Y) + v.Y * (p0.X - p1.X);\n        }\n\n        /// <summary>\n        /// Returns the left value of the point p with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double PosLeftOfLineValue(this V2d p, V2d p0, V2d p1)\n        {\n            return (p.X - p0.X) * (p0.Y - p1.Y) + (p.Y - p0.Y) * (p1.X - p0.X);\n        }\n\n        /// <summary>\n        /// Returns the right value of the point p with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double PosRightOfLineValue(this V2d p, V2d p0, V2d p1)\n        {\n            return (p.X - p0.X) * (p1.Y - p0.Y) + (p.Y - p0.Y) * (p0.X - p1.X);\n        }\n\n        #endregion\n\n        #region Linear Combination\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LinCom(V2d p0, V2d p1, ref Tup2<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LinCom(V2d p0, V2d p1, V2d p2, ref Tup3<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LinCom(V2d p0, V2d p1, V2d p2, V2d p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LinCom(V2d p0, V2d p1, V2d p2, V2d p3, V2d p4, ref Tup5<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LinCom(V2d p0, V2d p1, V2d p2, V2d p3, V2d p4, V2d p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d LinCom(V2d p0, V2d p1, V2d p2, V2d p3, V2d p4, V2d p5, V2d p6, ref Tup7<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V2d[] pointArray, V2d point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V2d[] array, int start, int count,\n                V2d point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V2d> pointSelector, V2d point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V2d[] pointArray, V2d point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V2d[] array, long start, long count,\n                V2d point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V2d> pointSelector, V2d point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V2d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V2d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V2d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V2d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V2d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V2d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V2d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V2d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V2d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V2d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V2d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V2d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static double[] CopyCoord(this V2d[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        public static V2d WeightedSum(\n                this V2d[] vectorArray, double[] weightArray)\n        {\n            var r = V2d.Zero;\n            var count = vectorArray.LongLength;\n            for (long i = 0; i < count; i++) r += vectorArray[i] * weightArray[i];\n            return r;\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV2dExtensions\n    {\n        #region IRandomUniform extensions for V2d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of a V2d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2d(this IRandomUniform rnd)\n        {\n            return new V2d(rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of a V2d\n        /// vector within the given Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2d(this IRandomUniform rnd, Box2d box)\n        {\n            return new V2d(box.Min.X + rnd.UniformDouble() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDouble() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of a V2d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dClosed(this IRandomUniform rnd)\n        {\n            return new V2d(rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of a V2d\n        /// vector within the given Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dClosed(this IRandomUniform rnd, Box2d box)\n        {\n            return new V2d(box.Min.X + rnd.UniformDoubleClosed() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleClosed() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of a V2d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dOpen(this IRandomUniform rnd)\n        {\n            return new V2d(rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of a V2d\n        /// vector within the given Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dOpen(this IRandomUniform rnd, Box2d box)\n        {\n            return new V2d(box.Min.X + rnd.UniformDoubleOpen() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleOpen() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of a V2d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dFull(this IRandomUniform rnd)\n        {\n            return new V2d(rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of a V2d\n        /// vector within the given Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dFull(this IRandomUniform rnd, Box2d box)\n        {\n            return new V2d(box.Min.X + rnd.UniformDoubleFull() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleFull() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of a V2d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dFullClosed(this IRandomUniform rnd)\n        {\n            return new V2d(rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of a V2d\n        /// vector within the given Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dFullClosed(this IRandomUniform rnd, Box2d box)\n        {\n            return new V2d(box.Min.X + rnd.UniformDoubleFullClosed() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleFullClosed() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of a V2d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dFullOpen(this IRandomUniform rnd)\n        {\n            return new V2d(rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of a V2d\n        /// vector within the given Box2d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dFullOpen(this IRandomUniform rnd, Box2d box)\n        {\n            return new V2d(box.Min.X + rnd.UniformDoubleFullOpen() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleFullOpen() * (box.Max.Y - box.Min.Y));\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the unit circle). Uses UniformDouble() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dDirection(this IRandomUniform rnd)\n        {\n            double phi = rnd.UniformDouble() * Constant.PiTimesTwo;\n            return new V2d(Fun.Cos(phi), Fun.Sin(phi));\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the unit circle). Uses UniformDoubleFull() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V2d UniformV2dFullDirection(this IRandomUniform rnd)\n        {\n            double phi = rnd.UniformDoubleFull() * Constant.PiTimesTwo;\n            return new V2d(Fun.Cos(phi), Fun.Sin(phi));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V3i\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V3i : IVector<double>, ISize3i, IFormattable, IEquatable<V3i>\n    {\n        [DataMember]\n        public int X;\n        [DataMember]\n        public int Y;\n        [DataMember]\n        public int Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(int x, int y, int z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(int v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(int[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(int[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(int a, V2i b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2i a, int b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(uint x, uint y, uint z)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(uint v)\n        {\n            X = (int)v;\n            Y = (int)v;\n            Z = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(uint[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n            Z = (int)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(uint[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n            Z = (int)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(uint a, V2ui b)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2ui a, uint b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(long x, long y, long z)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(long v)\n        {\n            X = (int)v;\n            Y = (int)v;\n            Z = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(long[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n            Z = (int)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(long[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n            Z = (int)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(long a, V2l b)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2l a, long b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(float x, float y, float z)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(float v)\n        {\n            X = (int)v;\n            Y = (int)v;\n            Z = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(float[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n            Z = (int)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(float[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n            Z = (int)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(float a, V2f b)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2f a, float b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(double x, double y, double z)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(double v)\n        {\n            X = (int)v;\n            Y = (int)v;\n            Z = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(double[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n            Z = (int)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(double[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n            Z = (int)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(double a, V2d b)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2d a, double b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(Func<int, int> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;int&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 3.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(IVector<double> v)\n            : this(v[0], v[1], v[2])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2i v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V2d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V3i v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V3ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V3l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V3f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V3d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V4i v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V4ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V4l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V4f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(V4d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(C3b c)\n        {\n            X = (int)(c.R);\n            Y = (int)(c.G);\n            Z = (int)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(C3us c)\n        {\n            X = (int)(c.R);\n            Y = (int)(c.G);\n            Z = (int)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(C4b c)\n        {\n            X = (int)(c.R);\n            Y = (int)(c.G);\n            Z = (int)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3i(C4us c)\n        {\n            X = (int)(c.R);\n            Y = (int)(c.G);\n            Z = (int)(c.B);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V2i v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V2ui v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V2l v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V2f v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V2d v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V3ui v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V3l v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V3f v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V3d v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V4i v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V4ui v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V4l v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V4f v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(V4d v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V3i v)\n            => new int[] { v.X, v.Y, v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(int[] v)\n            => new V3i(v[0], v[1], v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V3i v)\n            => new uint[] { (uint)v.X, (uint)v.Y, (uint)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(uint[] v)\n            => new V3i((int)v[0], (int)v[1], (int)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V3i v)\n            => new long[] { (long)v.X, (long)v.Y, (long)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(long[] v)\n            => new V3i((int)v[0], (int)v[1], (int)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V3i v)\n            => new float[] { (float)v.X, (float)v.Y, (float)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(float[] v)\n            => new V3i((int)v[0], (int)v[1], (int)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V3i v)\n            => new double[] { (double)v.X, (double)v.Y, (double)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(double[] v)\n            => new V3i((int)v[0], (int)v[1], (int)v[2]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(C3b v)\n            => new V3i(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3i\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(C3us v)\n            => new V3i(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3i\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(C4b v)\n            => new V3i(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3i\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3i(C4us v)\n            => new V3i(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3i\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<int, int> element_fun)\n            => new V3i(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<int, int, int> element_index_fun)\n            => new V3i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<int, uint> element_fun)\n            => new V3ui(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<int, int, uint> element_index_fun)\n            => new V3ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n            array[start + 2] = (uint)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<int, long> element_fun)\n            => new V3l(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<int, int, long> element_index_fun)\n            => new V3l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n            array[start + 2] = (long)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<int, float> element_fun)\n            => new V3f(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<int, int, float> element_index_fun)\n            => new V3f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n            array[start + 2] = (float)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<int, double> element_fun)\n            => new V3d(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<int, int, double> element_index_fun)\n            => new V3d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n            array[start + 2] = (double)Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<int, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<int, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int[] ToArray()\n            => new int[] { X, Y, Z };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe int this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? (X >= Z ? 0 : 2) : (Y >= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? (X <= Z ? 0 : 2) : (Y <= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly int MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly int MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 3;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V3i Zero\n        {\n            get { return new V3i(0, 0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V3i One\n        {\n            get { return new V3i(1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V3i MaxValue\n        {\n            get { return new V3i(Constant<int>.ParseableMaxValue, Constant<int>.ParseableMaxValue, Constant<int>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V3i MinValue\n        {\n            get { return new V3i(Constant<int>.ParseableMinValue, Constant<int>.ParseableMinValue, Constant<int>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V3i XAxis\n        {\n            get { return new V3i(1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V3i YAxis\n        {\n            get { return new V3i(0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V3i ZAxis\n        {\n            get { return new V3i(0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V3i, int>[] SelectorArray =\n            new Func<V3i, int>[] { v => v.X, v => v.Y, v => v.Z };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V3i, int, int> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V3i, int, int> Setter =\n            (ref V3i v, int i, int s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V3i, long, int> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V3i, long, int> LongSetter =\n            (ref V3i v, long i, int s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FromV3ui(V3ui v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FromV3l(V3l v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FromV3f(V3f v)\n            => new V3i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FromV3d(V3d v)\n            => new V3i(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FromC3b(C3b c) => new V3i(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FromC3us(C3us c) => new V3i(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FromC4b(C4b c) => new V3i(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FromC4us(C4us c) => new V3i(c);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly int LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly int Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y) + Fun.Abs(Z); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly int NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly int NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V3d.Zero;\n                s = 1 / s;\n                return new V3d(X * s, Y * s, Z * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Abs(V3i v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i LinearInterp(float t, V3i a, V3i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i LinearInterp(V3f t, V3i a, V3i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i LinearInterp(double t, V3i a, V3i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i LinearInterp(V3d t, V3i a, V3i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Min(V3i v0, V3i v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Min(V3i v, int x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Max(V3i v0, V3i v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Max(V3i v, int x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Saturate(V3i v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i DivideByInt(V3i v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator -(V3i v)\n            => new V3i(-v.X, -v.Y, -v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator ~(V3i v)\n            => new V3i(~v.X, ~v.Y, ~v.Z);\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator +(V3i a, V3i b)\n            => new V3i(a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator +(V3i v, int s)\n            => new V3i(v.X + s, v.Y + s, v.Z + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator +(int s, V3i v)\n            => new V3i(s + v.X, s + v.Y, s + v.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator -(V3i a, V3i b)\n            => new V3i(a.X - b.X, a.Y - b.Y, a.Z - b.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator -(V3i v, int s)\n            => new V3i(v.X - s, v.Y - s, v.Z - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator -(int s, V3i v)\n            => new V3i(s - v.X, s - v.Y, s - v.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator *(V3i a, V3i b)\n            => new V3i(a.X * b.X, a.Y * b.Y, a.Z * b.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator *(V3i v, int s)\n            => new V3i(v.X * s, v.Y * s, v.Z * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator *(int s, V3i v)\n            => new V3i(s * v.X, s * v.Y, s * v.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator /(V3i a, V3i b)\n            => new V3i(a.X / b.X, a.Y / b.Y, a.Z / b.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator /(V3i v, int s)\n            => new V3i(v.X / s, v.Y / s, v.Z / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator /(int s, V3i v)\n            => new V3i(s / v.X, s / v.Y, s / v.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator %(V3i a, V3i b)\n            => new V3i(a.X % b.X, a.Y % b.Y, a.Z % b.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator %(V3i v, int s)\n            => new V3i(v.X % s, v.Y % s, v.Z % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator %(int s, V3i v)\n            => new V3i(s % v.X, s % v.Y, s % v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator &(V3i a, V3i b)\n            => new V3i(a.X & b.X, a.Y & b.Y, a.Z & b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator &(V3i v, int s)\n            => new V3i(v.X & s, v.Y & s, v.Z & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator &(int s, V3i v)\n            => new V3i(s & v.X, s & v.Y, s & v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator |(V3i a, V3i b)\n            => new V3i(a.X | b.X, a.Y | b.Y, a.Z | b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator |(V3i v, int s)\n            => new V3i(v.X | s, v.Y | s, v.Z | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator |(int s, V3i v)\n            => new V3i(s | v.X, s | v.Y, s | v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator ^(V3i a, V3i b)\n            => new V3i(a.X ^ b.X, a.Y ^ b.Y, a.Z ^ b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator ^(V3i v, int s)\n            => new V3i(v.X ^ s, v.Y ^ s, v.Z ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator ^(int s, V3i v)\n            => new V3i(s ^ v.X, s ^ v.Y, s ^ v.Z);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator <<(V3i v, int s)\n            => new V3i(v.X << s, v.Y << s, v.Z << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i operator >>(V3i v, int s)\n            => new V3i(v.X >> s, v.Y >> s, v.Z >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3i a, V3i b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3i v, int s)\n        {\n            return v.X == s && v.Y == s && v.Z == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(int s, V3i v)\n        {\n            return s == v.X && s == v.Y && s == v.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3i a, V3i b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3i v, int s)\n        {\n            return v.X != s || v.Y != s || v.Z != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(int s, V3i v)\n        {\n            return s != v.X || s != v.Y || s != v.Z;\n        }\n\n        #endregion\n\n        #region IEquatable<V3i> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V3i other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V3i o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V3i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V3i(\n                int.Parse(x[0], CultureInfo.InvariantCulture), \n                int.Parse(x[1], CultureInfo.InvariantCulture), \n                int.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V3i Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<int>.Parse, V3i.Setter);\n        }\n\n        public static V3i Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<int>.Parse, V3i.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OX => new V2i(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OY => new V2i(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OZ => new V2i(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IX => new V2i(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IY => new V2i(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IZ => new V2i(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NX => new V2i(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NY => new V2i(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NZ => new V2i(-1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XO => new V2i(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XI => new V2i(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XN => new V2i(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XX => new V2i(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i XY\n        {\n            readonly get => new V2i(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i XZ\n        {\n            readonly get => new V2i(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YO => new V2i(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YI => new V2i(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YN => new V2i(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i YX\n        {\n            readonly get => new V2i(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YY => new V2i(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i YZ\n        {\n            readonly get => new V2i(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i ZO => new V2i(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i ZI => new V2i(Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i ZN => new V2i(Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i ZX\n        {\n            readonly get => new V2i(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i ZY\n        {\n            readonly get => new V2i(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i ZZ => new V2i(Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i OOO => new V3i(0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i OOI => new V3i(0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i OON => new V3i(0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOX => new V3i(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOY => new V3i(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOZ => new V3i(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i OIO => new V3i(0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i OII => new V3i(0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i OPN => new V3i(0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIX => new V3i(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIY => new V3i(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIZ => new V3i(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i ONO => new V3i(0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i ONP => new V3i(0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i ONN => new V3i(0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONX => new V3i(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONY => new V3i(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONZ => new V3i(0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXO => new V3i(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXI => new V3i(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXN => new V3i(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXX => new V3i(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXY => new V3i(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXZ => new V3i(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYO => new V3i(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYI => new V3i(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYN => new V3i(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYX => new V3i(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYY => new V3i(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYZ => new V3i(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZO => new V3i(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZI => new V3i(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZN => new V3i(0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZX => new V3i(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZY => new V3i(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZZ => new V3i(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i IOO => new V3i(1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i IOI => new V3i(1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i PON => new V3i(1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOX => new V3i(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOY => new V3i(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOZ => new V3i(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i IIO => new V3i(1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i III => new V3i(1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i PPN => new V3i(1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIX => new V3i(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIY => new V3i(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIZ => new V3i(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i PNO => new V3i(1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i PNP => new V3i(1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i PNN => new V3i(1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNX => new V3i(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNY => new V3i(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNZ => new V3i(1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXO => new V3i(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXI => new V3i(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PXN => new V3i(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXX => new V3i(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXY => new V3i(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXZ => new V3i(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYO => new V3i(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYI => new V3i(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PYN => new V3i(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYX => new V3i(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYY => new V3i(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYZ => new V3i(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZO => new V3i(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZI => new V3i(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PZN => new V3i(1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZX => new V3i(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZY => new V3i(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZZ => new V3i(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NOO => new V3i(-1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NOP => new V3i(-1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NON => new V3i(-1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOX => new V3i(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOY => new V3i(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOZ => new V3i(-1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NPO => new V3i(-1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NPP => new V3i(-1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NPN => new V3i(-1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPX => new V3i(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPY => new V3i(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPZ => new V3i(-1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NNO => new V3i(-1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NNP => new V3i(-1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3i NNN => new V3i(-1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNX => new V3i(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNY => new V3i(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNZ => new V3i(-1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXO => new V3i(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXP => new V3i(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXN => new V3i(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXX => new V3i(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXY => new V3i(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXZ => new V3i(-1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYO => new V3i(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYP => new V3i(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYN => new V3i(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYX => new V3i(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYY => new V3i(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYZ => new V3i(-1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZO => new V3i(-1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZP => new V3i(-1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZN => new V3i(-1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZX => new V3i(-1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZY => new V3i(-1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZZ => new V3i(-1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOO => new V3i(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOI => new V3i(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XON => new V3i(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOX => new V3i(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOY => new V3i(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOZ => new V3i(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIO => new V3i(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XII => new V3i(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XPN => new V3i(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIX => new V3i(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIY => new V3i(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIZ => new V3i(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNO => new V3i(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNP => new V3i(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNN => new V3i(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNX => new V3i(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNY => new V3i(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNZ => new V3i(X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXO => new V3i(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXI => new V3i(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXN => new V3i(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXX => new V3i(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXY => new V3i(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXZ => new V3i(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYO => new V3i(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYI => new V3i(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYN => new V3i(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYX => new V3i(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYY => new V3i(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i XYZ\n        {\n            readonly get => new V3i(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZO => new V3i(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZI => new V3i(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZN => new V3i(X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZX => new V3i(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i XZY\n        {\n            readonly get => new V3i(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZZ => new V3i(X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOO => new V3i(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOI => new V3i(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YON => new V3i(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOX => new V3i(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOY => new V3i(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOZ => new V3i(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIO => new V3i(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YII => new V3i(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YPN => new V3i(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIX => new V3i(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIY => new V3i(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIZ => new V3i(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNO => new V3i(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNP => new V3i(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNN => new V3i(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNX => new V3i(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNY => new V3i(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNZ => new V3i(Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXO => new V3i(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXI => new V3i(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXN => new V3i(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXX => new V3i(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXY => new V3i(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i YXZ\n        {\n            readonly get => new V3i(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYO => new V3i(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYI => new V3i(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYN => new V3i(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYX => new V3i(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYY => new V3i(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYZ => new V3i(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZO => new V3i(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZI => new V3i(Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZN => new V3i(Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i YZX\n        {\n            readonly get => new V3i(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZY => new V3i(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZZ => new V3i(Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOO => new V3i(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOI => new V3i(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZON => new V3i(Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOX => new V3i(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOY => new V3i(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOZ => new V3i(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIO => new V3i(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZII => new V3i(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZPN => new V3i(Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIX => new V3i(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIY => new V3i(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIZ => new V3i(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNO => new V3i(Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNP => new V3i(Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNN => new V3i(Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNX => new V3i(Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNY => new V3i(Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNZ => new V3i(Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXO => new V3i(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXI => new V3i(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXN => new V3i(Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXX => new V3i(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i ZXY\n        {\n            readonly get => new V3i(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXZ => new V3i(Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYO => new V3i(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYI => new V3i(Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYN => new V3i(Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i ZYX\n        {\n            readonly get => new V3i(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYY => new V3i(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYZ => new V3i(Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZO => new V3i(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZI => new V3i(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZN => new V3i(Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZX => new V3i(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZY => new V3i(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZZ => new V3i(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOX => new V4i(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOY => new V4i(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOZ => new V4i(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIX => new V4i(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIY => new V4i(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIZ => new V4i(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONX => new V4i(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONY => new V4i(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONZ => new V4i(0, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXO => new V4i(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXI => new V4i(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXN => new V4i(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXX => new V4i(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXY => new V4i(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXZ => new V4i(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYO => new V4i(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYI => new V4i(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYN => new V4i(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYX => new V4i(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYY => new V4i(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYZ => new V4i(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZO => new V4i(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZI => new V4i(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZN => new V4i(0, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZX => new V4i(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZY => new V4i(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZZ => new V4i(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOX => new V4i(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOY => new V4i(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOZ => new V4i(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIX => new V4i(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIY => new V4i(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIZ => new V4i(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNX => new V4i(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNY => new V4i(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNZ => new V4i(0, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXO => new V4i(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXI => new V4i(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPXN => new V4i(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXX => new V4i(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXY => new V4i(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXZ => new V4i(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYO => new V4i(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYI => new V4i(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPYN => new V4i(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYX => new V4i(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYY => new V4i(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYZ => new V4i(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZO => new V4i(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZI => new V4i(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPZN => new V4i(0, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZX => new V4i(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZY => new V4i(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZZ => new V4i(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOX => new V4i(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOY => new V4i(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOZ => new V4i(0, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPX => new V4i(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPY => new V4i(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPZ => new V4i(0, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNX => new V4i(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNY => new V4i(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNZ => new V4i(0, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXO => new V4i(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXP => new V4i(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXN => new V4i(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXX => new V4i(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXY => new V4i(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXZ => new V4i(0, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYO => new V4i(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYP => new V4i(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYN => new V4i(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYX => new V4i(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYY => new V4i(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYZ => new V4i(0, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZO => new V4i(0, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZP => new V4i(0, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZN => new V4i(0, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZX => new V4i(0, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZY => new V4i(0, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZZ => new V4i(0, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOO => new V4i(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOI => new V4i(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXON => new V4i(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOX => new V4i(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOY => new V4i(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOZ => new V4i(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIO => new V4i(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXII => new V4i(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXPN => new V4i(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIX => new V4i(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIY => new V4i(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIZ => new V4i(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNO => new V4i(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNP => new V4i(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNN => new V4i(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNX => new V4i(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNY => new V4i(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNZ => new V4i(0, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXO => new V4i(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXI => new V4i(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXN => new V4i(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXX => new V4i(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXY => new V4i(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXZ => new V4i(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYO => new V4i(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYI => new V4i(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYN => new V4i(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYX => new V4i(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYY => new V4i(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYZ => new V4i(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZO => new V4i(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZI => new V4i(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZN => new V4i(0, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZX => new V4i(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZY => new V4i(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZZ => new V4i(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOO => new V4i(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOI => new V4i(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYON => new V4i(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOX => new V4i(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOY => new V4i(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOZ => new V4i(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIO => new V4i(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYII => new V4i(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYPN => new V4i(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIX => new V4i(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIY => new V4i(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIZ => new V4i(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNO => new V4i(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNP => new V4i(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNN => new V4i(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNX => new V4i(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNY => new V4i(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNZ => new V4i(0, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXO => new V4i(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXI => new V4i(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXN => new V4i(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXX => new V4i(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXY => new V4i(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXZ => new V4i(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYO => new V4i(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYI => new V4i(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYN => new V4i(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYX => new V4i(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYY => new V4i(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYZ => new V4i(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZO => new V4i(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZI => new V4i(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZN => new V4i(0, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZX => new V4i(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZY => new V4i(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZZ => new V4i(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOO => new V4i(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOI => new V4i(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZON => new V4i(0, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOX => new V4i(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOY => new V4i(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOZ => new V4i(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIO => new V4i(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZII => new V4i(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZPN => new V4i(0, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIX => new V4i(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIY => new V4i(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIZ => new V4i(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNO => new V4i(0, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNP => new V4i(0, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNN => new V4i(0, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNX => new V4i(0, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNY => new V4i(0, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNZ => new V4i(0, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXO => new V4i(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXI => new V4i(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXN => new V4i(0, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXX => new V4i(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXY => new V4i(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXZ => new V4i(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYO => new V4i(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYI => new V4i(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYN => new V4i(0, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYX => new V4i(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYY => new V4i(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYZ => new V4i(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZO => new V4i(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZI => new V4i(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZN => new V4i(0, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZX => new V4i(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZY => new V4i(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZZ => new V4i(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOX => new V4i(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOY => new V4i(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOZ => new V4i(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIX => new V4i(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIY => new V4i(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIZ => new V4i(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONX => new V4i(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONY => new V4i(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONZ => new V4i(1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXO => new V4i(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXI => new V4i(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POXN => new V4i(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXX => new V4i(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXY => new V4i(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXZ => new V4i(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYO => new V4i(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYI => new V4i(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POYN => new V4i(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYX => new V4i(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYY => new V4i(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYZ => new V4i(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZO => new V4i(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZI => new V4i(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POZN => new V4i(1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZX => new V4i(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZY => new V4i(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZZ => new V4i(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOX => new V4i(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOY => new V4i(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOZ => new V4i(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIX => new V4i(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIY => new V4i(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIZ => new V4i(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNX => new V4i(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNY => new V4i(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNZ => new V4i(1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXO => new V4i(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXI => new V4i(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPXN => new V4i(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXX => new V4i(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXY => new V4i(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXZ => new V4i(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYO => new V4i(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYI => new V4i(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPYN => new V4i(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYX => new V4i(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYY => new V4i(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYZ => new V4i(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZO => new V4i(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZI => new V4i(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPZN => new V4i(1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZX => new V4i(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZY => new V4i(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZZ => new V4i(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOX => new V4i(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOY => new V4i(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOZ => new V4i(1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPX => new V4i(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPY => new V4i(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPZ => new V4i(1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNX => new V4i(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNY => new V4i(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNZ => new V4i(1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXO => new V4i(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXP => new V4i(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXN => new V4i(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXX => new V4i(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXY => new V4i(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXZ => new V4i(1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYO => new V4i(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYP => new V4i(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYN => new V4i(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYX => new V4i(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYY => new V4i(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYZ => new V4i(1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZO => new V4i(1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZP => new V4i(1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZN => new V4i(1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZX => new V4i(1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZY => new V4i(1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZZ => new V4i(1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOO => new V4i(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOI => new V4i(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXON => new V4i(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOX => new V4i(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOY => new V4i(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOZ => new V4i(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIO => new V4i(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXII => new V4i(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXPN => new V4i(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIX => new V4i(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIY => new V4i(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIZ => new V4i(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNO => new V4i(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNP => new V4i(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNN => new V4i(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNX => new V4i(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNY => new V4i(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNZ => new V4i(1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXO => new V4i(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXI => new V4i(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXXN => new V4i(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXX => new V4i(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXY => new V4i(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXZ => new V4i(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYO => new V4i(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYI => new V4i(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXYN => new V4i(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYX => new V4i(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYY => new V4i(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYZ => new V4i(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZO => new V4i(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZI => new V4i(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXZN => new V4i(1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZX => new V4i(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZY => new V4i(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZZ => new V4i(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOO => new V4i(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOI => new V4i(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYON => new V4i(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOX => new V4i(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOY => new V4i(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOZ => new V4i(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIO => new V4i(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYII => new V4i(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYPN => new V4i(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIX => new V4i(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIY => new V4i(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIZ => new V4i(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNO => new V4i(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNP => new V4i(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNN => new V4i(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNX => new V4i(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNY => new V4i(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNZ => new V4i(1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXO => new V4i(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXI => new V4i(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYXN => new V4i(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXX => new V4i(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXY => new V4i(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXZ => new V4i(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYO => new V4i(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYI => new V4i(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYYN => new V4i(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYX => new V4i(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYY => new V4i(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYZ => new V4i(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZO => new V4i(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZI => new V4i(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYZN => new V4i(1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZX => new V4i(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZY => new V4i(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZZ => new V4i(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOO => new V4i(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOI => new V4i(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZON => new V4i(1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOX => new V4i(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOY => new V4i(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOZ => new V4i(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIO => new V4i(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZII => new V4i(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZPN => new V4i(1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIX => new V4i(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIY => new V4i(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIZ => new V4i(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNO => new V4i(1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNP => new V4i(1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNN => new V4i(1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNX => new V4i(1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNY => new V4i(1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNZ => new V4i(1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXO => new V4i(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXI => new V4i(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZXN => new V4i(1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXX => new V4i(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXY => new V4i(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXZ => new V4i(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYO => new V4i(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYI => new V4i(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZYN => new V4i(1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYX => new V4i(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYY => new V4i(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYZ => new V4i(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZO => new V4i(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZI => new V4i(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZZN => new V4i(1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZX => new V4i(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZY => new V4i(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZZ => new V4i(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOX => new V4i(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOY => new V4i(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOZ => new V4i(-1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPX => new V4i(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPY => new V4i(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPZ => new V4i(-1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONX => new V4i(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONY => new V4i(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONZ => new V4i(-1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXO => new V4i(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXP => new V4i(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXN => new V4i(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXX => new V4i(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXY => new V4i(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXZ => new V4i(-1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYO => new V4i(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYP => new V4i(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYN => new V4i(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYX => new V4i(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYY => new V4i(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYZ => new V4i(-1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZO => new V4i(-1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZP => new V4i(-1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZN => new V4i(-1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZX => new V4i(-1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZY => new V4i(-1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZZ => new V4i(-1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOX => new V4i(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOY => new V4i(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOZ => new V4i(-1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPX => new V4i(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPY => new V4i(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPZ => new V4i(-1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNX => new V4i(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNY => new V4i(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNZ => new V4i(-1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXO => new V4i(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXP => new V4i(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXN => new V4i(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXX => new V4i(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXY => new V4i(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXZ => new V4i(-1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYO => new V4i(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYP => new V4i(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYN => new V4i(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYX => new V4i(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYY => new V4i(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYZ => new V4i(-1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZO => new V4i(-1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZP => new V4i(-1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZN => new V4i(-1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZX => new V4i(-1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZY => new V4i(-1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZZ => new V4i(-1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOX => new V4i(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOY => new V4i(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOZ => new V4i(-1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPX => new V4i(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPY => new V4i(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPZ => new V4i(-1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNX => new V4i(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNY => new V4i(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNZ => new V4i(-1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXO => new V4i(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXP => new V4i(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXN => new V4i(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXX => new V4i(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXY => new V4i(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXZ => new V4i(-1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYO => new V4i(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYP => new V4i(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYN => new V4i(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYX => new V4i(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYY => new V4i(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYZ => new V4i(-1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZO => new V4i(-1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZP => new V4i(-1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZN => new V4i(-1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZX => new V4i(-1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZY => new V4i(-1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZZ => new V4i(-1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOO => new V4i(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOP => new V4i(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXON => new V4i(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOX => new V4i(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOY => new V4i(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOZ => new V4i(-1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPO => new V4i(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPP => new V4i(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPN => new V4i(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPX => new V4i(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPY => new V4i(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPZ => new V4i(-1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNO => new V4i(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNP => new V4i(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNN => new V4i(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNX => new V4i(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNY => new V4i(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNZ => new V4i(-1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXO => new V4i(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXP => new V4i(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXN => new V4i(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXX => new V4i(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXY => new V4i(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXZ => new V4i(-1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYO => new V4i(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYP => new V4i(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYN => new V4i(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYX => new V4i(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYY => new V4i(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYZ => new V4i(-1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZO => new V4i(-1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZP => new V4i(-1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZN => new V4i(-1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZX => new V4i(-1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZY => new V4i(-1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZZ => new V4i(-1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOO => new V4i(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOP => new V4i(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYON => new V4i(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOX => new V4i(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOY => new V4i(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOZ => new V4i(-1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPO => new V4i(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPP => new V4i(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPN => new V4i(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPX => new V4i(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPY => new V4i(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPZ => new V4i(-1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNO => new V4i(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNP => new V4i(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNN => new V4i(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNX => new V4i(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNY => new V4i(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNZ => new V4i(-1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXO => new V4i(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXP => new V4i(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXN => new V4i(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXX => new V4i(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXY => new V4i(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXZ => new V4i(-1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYO => new V4i(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYP => new V4i(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYN => new V4i(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYX => new V4i(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYY => new V4i(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYZ => new V4i(-1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZO => new V4i(-1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZP => new V4i(-1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZN => new V4i(-1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZX => new V4i(-1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZY => new V4i(-1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZZ => new V4i(-1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOO => new V4i(-1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOP => new V4i(-1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZON => new V4i(-1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOX => new V4i(-1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOY => new V4i(-1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOZ => new V4i(-1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPO => new V4i(-1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPP => new V4i(-1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPN => new V4i(-1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPX => new V4i(-1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPY => new V4i(-1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPZ => new V4i(-1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNO => new V4i(-1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNP => new V4i(-1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNN => new V4i(-1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNX => new V4i(-1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNY => new V4i(-1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNZ => new V4i(-1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXO => new V4i(-1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXP => new V4i(-1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXN => new V4i(-1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXX => new V4i(-1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXY => new V4i(-1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXZ => new V4i(-1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYO => new V4i(-1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYP => new V4i(-1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYN => new V4i(-1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYX => new V4i(-1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYY => new V4i(-1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYZ => new V4i(-1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZO => new V4i(-1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZP => new V4i(-1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZN => new V4i(-1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZX => new V4i(-1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZY => new V4i(-1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZZ => new V4i(-1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOO => new V4i(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOI => new V4i(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOON => new V4i(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOX => new V4i(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOY => new V4i(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOZ => new V4i(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIO => new V4i(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOII => new V4i(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOPN => new V4i(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIX => new V4i(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIY => new V4i(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIZ => new V4i(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONO => new V4i(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONP => new V4i(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONN => new V4i(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONX => new V4i(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONY => new V4i(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONZ => new V4i(X, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXO => new V4i(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXI => new V4i(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXN => new V4i(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXX => new V4i(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXY => new V4i(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXZ => new V4i(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYO => new V4i(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYI => new V4i(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYN => new V4i(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYX => new V4i(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYY => new V4i(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYZ => new V4i(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZO => new V4i(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZI => new V4i(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZN => new V4i(X, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZX => new V4i(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZY => new V4i(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZZ => new V4i(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOO => new V4i(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOI => new V4i(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPON => new V4i(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOX => new V4i(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOY => new V4i(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOZ => new V4i(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIO => new V4i(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIII => new V4i(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPPN => new V4i(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIX => new V4i(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIY => new V4i(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIZ => new V4i(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNO => new V4i(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNP => new V4i(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNN => new V4i(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNX => new V4i(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNY => new V4i(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNZ => new V4i(X, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXO => new V4i(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXI => new V4i(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPXN => new V4i(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXX => new V4i(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXY => new V4i(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXZ => new V4i(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYO => new V4i(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYI => new V4i(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPYN => new V4i(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYX => new V4i(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYY => new V4i(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYZ => new V4i(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZO => new V4i(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZI => new V4i(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPZN => new V4i(X, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZX => new V4i(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZY => new V4i(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZZ => new V4i(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOO => new V4i(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOP => new V4i(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNON => new V4i(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOX => new V4i(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOY => new V4i(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOZ => new V4i(X, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPO => new V4i(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPP => new V4i(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPN => new V4i(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPX => new V4i(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPY => new V4i(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPZ => new V4i(X, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNO => new V4i(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNP => new V4i(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNN => new V4i(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNX => new V4i(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNY => new V4i(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNZ => new V4i(X, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXO => new V4i(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXP => new V4i(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXN => new V4i(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXX => new V4i(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXY => new V4i(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXZ => new V4i(X, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYO => new V4i(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYP => new V4i(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYN => new V4i(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYX => new V4i(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYY => new V4i(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYZ => new V4i(X, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZO => new V4i(X, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZP => new V4i(X, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZN => new V4i(X, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZX => new V4i(X, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZY => new V4i(X, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZZ => new V4i(X, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOO => new V4i(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOI => new V4i(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXON => new V4i(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOX => new V4i(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOY => new V4i(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOZ => new V4i(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIO => new V4i(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXII => new V4i(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXPN => new V4i(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIX => new V4i(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIY => new V4i(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIZ => new V4i(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNO => new V4i(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNP => new V4i(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNN => new V4i(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNX => new V4i(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNY => new V4i(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNZ => new V4i(X, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXO => new V4i(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXI => new V4i(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXN => new V4i(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXX => new V4i(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXY => new V4i(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXZ => new V4i(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYO => new V4i(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYI => new V4i(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYN => new V4i(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYX => new V4i(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYY => new V4i(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYZ => new V4i(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZO => new V4i(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZI => new V4i(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZN => new V4i(X, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZX => new V4i(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZY => new V4i(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZZ => new V4i(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOO => new V4i(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOI => new V4i(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYON => new V4i(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOX => new V4i(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOY => new V4i(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOZ => new V4i(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIO => new V4i(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYII => new V4i(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYPN => new V4i(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIX => new V4i(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIY => new V4i(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIZ => new V4i(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNO => new V4i(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNP => new V4i(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNN => new V4i(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNX => new V4i(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNY => new V4i(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNZ => new V4i(X, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXO => new V4i(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXI => new V4i(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXN => new V4i(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXX => new V4i(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXY => new V4i(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXZ => new V4i(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYO => new V4i(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYI => new V4i(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYN => new V4i(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYX => new V4i(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYY => new V4i(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYZ => new V4i(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZO => new V4i(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZI => new V4i(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZN => new V4i(X, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZX => new V4i(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZY => new V4i(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZZ => new V4i(X, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOO => new V4i(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOI => new V4i(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZON => new V4i(X, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOX => new V4i(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOY => new V4i(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOZ => new V4i(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIO => new V4i(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZII => new V4i(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZPN => new V4i(X, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIX => new V4i(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIY => new V4i(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIZ => new V4i(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNO => new V4i(X, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNP => new V4i(X, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNN => new V4i(X, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNX => new V4i(X, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNY => new V4i(X, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNZ => new V4i(X, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXO => new V4i(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXI => new V4i(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXN => new V4i(X, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXX => new V4i(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXY => new V4i(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXZ => new V4i(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYO => new V4i(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYI => new V4i(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYN => new V4i(X, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYX => new V4i(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYY => new V4i(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYZ => new V4i(X, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZO => new V4i(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZI => new V4i(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZN => new V4i(X, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZX => new V4i(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZY => new V4i(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZZ => new V4i(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOO => new V4i(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOI => new V4i(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOON => new V4i(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOX => new V4i(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOY => new V4i(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOZ => new V4i(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIO => new V4i(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOII => new V4i(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOPN => new V4i(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIX => new V4i(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIY => new V4i(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIZ => new V4i(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONO => new V4i(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONP => new V4i(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONN => new V4i(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONX => new V4i(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONY => new V4i(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONZ => new V4i(Y, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXO => new V4i(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXI => new V4i(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXN => new V4i(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXX => new V4i(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXY => new V4i(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXZ => new V4i(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYO => new V4i(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYI => new V4i(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYN => new V4i(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYX => new V4i(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYY => new V4i(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYZ => new V4i(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZO => new V4i(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZI => new V4i(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZN => new V4i(Y, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZX => new V4i(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZY => new V4i(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZZ => new V4i(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOO => new V4i(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOI => new V4i(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPON => new V4i(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOX => new V4i(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOY => new V4i(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOZ => new V4i(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIO => new V4i(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIII => new V4i(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPPN => new V4i(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIX => new V4i(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIY => new V4i(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIZ => new V4i(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNO => new V4i(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNP => new V4i(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNN => new V4i(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNX => new V4i(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNY => new V4i(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNZ => new V4i(Y, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXO => new V4i(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXI => new V4i(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPXN => new V4i(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXX => new V4i(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXY => new V4i(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXZ => new V4i(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYO => new V4i(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYI => new V4i(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPYN => new V4i(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYX => new V4i(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYY => new V4i(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYZ => new V4i(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZO => new V4i(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZI => new V4i(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPZN => new V4i(Y, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZX => new V4i(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZY => new V4i(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZZ => new V4i(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOO => new V4i(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOP => new V4i(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNON => new V4i(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOX => new V4i(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOY => new V4i(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOZ => new V4i(Y, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPO => new V4i(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPP => new V4i(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPN => new V4i(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPX => new V4i(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPY => new V4i(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPZ => new V4i(Y, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNO => new V4i(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNP => new V4i(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNN => new V4i(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNX => new V4i(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNY => new V4i(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNZ => new V4i(Y, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXO => new V4i(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXP => new V4i(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXN => new V4i(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXX => new V4i(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXY => new V4i(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXZ => new V4i(Y, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYO => new V4i(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYP => new V4i(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYN => new V4i(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYX => new V4i(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYY => new V4i(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYZ => new V4i(Y, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZO => new V4i(Y, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZP => new V4i(Y, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZN => new V4i(Y, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZX => new V4i(Y, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZY => new V4i(Y, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZZ => new V4i(Y, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOO => new V4i(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOI => new V4i(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXON => new V4i(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOX => new V4i(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOY => new V4i(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOZ => new V4i(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIO => new V4i(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXII => new V4i(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXPN => new V4i(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIX => new V4i(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIY => new V4i(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIZ => new V4i(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNO => new V4i(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNP => new V4i(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNN => new V4i(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNX => new V4i(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNY => new V4i(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNZ => new V4i(Y, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXO => new V4i(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXI => new V4i(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXN => new V4i(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXX => new V4i(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXY => new V4i(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXZ => new V4i(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYO => new V4i(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYI => new V4i(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYN => new V4i(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYX => new V4i(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYY => new V4i(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYZ => new V4i(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZO => new V4i(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZI => new V4i(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZN => new V4i(Y, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZX => new V4i(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZY => new V4i(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZZ => new V4i(Y, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOO => new V4i(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOI => new V4i(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYON => new V4i(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOX => new V4i(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOY => new V4i(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOZ => new V4i(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIO => new V4i(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYII => new V4i(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYPN => new V4i(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIX => new V4i(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIY => new V4i(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIZ => new V4i(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNO => new V4i(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNP => new V4i(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNN => new V4i(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNX => new V4i(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNY => new V4i(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNZ => new V4i(Y, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXO => new V4i(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXI => new V4i(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXN => new V4i(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXX => new V4i(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXY => new V4i(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXZ => new V4i(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYO => new V4i(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYI => new V4i(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYN => new V4i(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYX => new V4i(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYY => new V4i(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYZ => new V4i(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZO => new V4i(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZI => new V4i(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZN => new V4i(Y, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZX => new V4i(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZY => new V4i(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZZ => new V4i(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOO => new V4i(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOI => new V4i(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZON => new V4i(Y, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOX => new V4i(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOY => new V4i(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOZ => new V4i(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIO => new V4i(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZII => new V4i(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZPN => new V4i(Y, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIX => new V4i(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIY => new V4i(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIZ => new V4i(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNO => new V4i(Y, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNP => new V4i(Y, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNN => new V4i(Y, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNX => new V4i(Y, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNY => new V4i(Y, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNZ => new V4i(Y, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXO => new V4i(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXI => new V4i(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXN => new V4i(Y, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXX => new V4i(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXY => new V4i(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXZ => new V4i(Y, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYO => new V4i(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYI => new V4i(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYN => new V4i(Y, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYX => new V4i(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYY => new V4i(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYZ => new V4i(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZO => new V4i(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZI => new V4i(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZN => new V4i(Y, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZX => new V4i(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZY => new V4i(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZZ => new V4i(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOO => new V4i(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOI => new V4i(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOON => new V4i(Z, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOX => new V4i(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOY => new V4i(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOZ => new V4i(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIO => new V4i(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOII => new V4i(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOPN => new V4i(Z, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIX => new V4i(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIY => new V4i(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIZ => new V4i(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONO => new V4i(Z, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONP => new V4i(Z, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONN => new V4i(Z, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONX => new V4i(Z, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONY => new V4i(Z, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONZ => new V4i(Z, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXO => new V4i(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXI => new V4i(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXN => new V4i(Z, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXX => new V4i(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXY => new V4i(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXZ => new V4i(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYO => new V4i(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYI => new V4i(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYN => new V4i(Z, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYX => new V4i(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYY => new V4i(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYZ => new V4i(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZO => new V4i(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZI => new V4i(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZN => new V4i(Z, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZX => new V4i(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZY => new V4i(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZZ => new V4i(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOO => new V4i(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOI => new V4i(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPON => new V4i(Z, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOX => new V4i(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOY => new V4i(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOZ => new V4i(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIO => new V4i(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIII => new V4i(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPPN => new V4i(Z, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIX => new V4i(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIY => new V4i(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIZ => new V4i(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNO => new V4i(Z, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNP => new V4i(Z, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNN => new V4i(Z, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNX => new V4i(Z, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNY => new V4i(Z, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNZ => new V4i(Z, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXO => new V4i(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXI => new V4i(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPXN => new V4i(Z, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXX => new V4i(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXY => new V4i(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXZ => new V4i(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYO => new V4i(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYI => new V4i(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPYN => new V4i(Z, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYX => new V4i(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYY => new V4i(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYZ => new V4i(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZO => new V4i(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZI => new V4i(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPZN => new V4i(Z, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZX => new V4i(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZY => new V4i(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZZ => new V4i(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOO => new V4i(Z, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOP => new V4i(Z, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNON => new V4i(Z, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOX => new V4i(Z, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOY => new V4i(Z, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOZ => new V4i(Z, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPO => new V4i(Z, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPP => new V4i(Z, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPN => new V4i(Z, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPX => new V4i(Z, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPY => new V4i(Z, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPZ => new V4i(Z, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNO => new V4i(Z, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNP => new V4i(Z, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNN => new V4i(Z, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNX => new V4i(Z, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNY => new V4i(Z, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNZ => new V4i(Z, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXO => new V4i(Z, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXP => new V4i(Z, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXN => new V4i(Z, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXX => new V4i(Z, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXY => new V4i(Z, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXZ => new V4i(Z, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYO => new V4i(Z, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYP => new V4i(Z, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYN => new V4i(Z, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYX => new V4i(Z, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYY => new V4i(Z, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYZ => new V4i(Z, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZO => new V4i(Z, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZP => new V4i(Z, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZN => new V4i(Z, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZX => new V4i(Z, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZY => new V4i(Z, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZZ => new V4i(Z, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOO => new V4i(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOI => new V4i(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXON => new V4i(Z, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOX => new V4i(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOY => new V4i(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOZ => new V4i(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIO => new V4i(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXII => new V4i(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXPN => new V4i(Z, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIX => new V4i(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIY => new V4i(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIZ => new V4i(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNO => new V4i(Z, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNP => new V4i(Z, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNN => new V4i(Z, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNX => new V4i(Z, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNY => new V4i(Z, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNZ => new V4i(Z, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXO => new V4i(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXI => new V4i(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXN => new V4i(Z, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXX => new V4i(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXY => new V4i(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXZ => new V4i(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYO => new V4i(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYI => new V4i(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYN => new V4i(Z, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYX => new V4i(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYY => new V4i(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYZ => new V4i(Z, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZO => new V4i(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZI => new V4i(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZN => new V4i(Z, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZX => new V4i(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZY => new V4i(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZZ => new V4i(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOO => new V4i(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOI => new V4i(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYON => new V4i(Z, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOX => new V4i(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOY => new V4i(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOZ => new V4i(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIO => new V4i(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYII => new V4i(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYPN => new V4i(Z, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIX => new V4i(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIY => new V4i(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIZ => new V4i(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNO => new V4i(Z, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNP => new V4i(Z, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNN => new V4i(Z, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNX => new V4i(Z, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNY => new V4i(Z, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNZ => new V4i(Z, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXO => new V4i(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXI => new V4i(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXN => new V4i(Z, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXX => new V4i(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXY => new V4i(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXZ => new V4i(Z, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYO => new V4i(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYI => new V4i(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYN => new V4i(Z, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYX => new V4i(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYY => new V4i(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYZ => new V4i(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZO => new V4i(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZI => new V4i(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZN => new V4i(Z, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZX => new V4i(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZY => new V4i(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZZ => new V4i(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOO => new V4i(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOI => new V4i(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZON => new V4i(Z, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOX => new V4i(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOY => new V4i(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOZ => new V4i(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIO => new V4i(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZII => new V4i(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZPN => new V4i(Z, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIX => new V4i(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIY => new V4i(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIZ => new V4i(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNO => new V4i(Z, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNP => new V4i(Z, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNN => new V4i(Z, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNX => new V4i(Z, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNY => new V4i(Z, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNZ => new V4i(Z, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXO => new V4i(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXI => new V4i(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXN => new V4i(Z, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXX => new V4i(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXY => new V4i(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXZ => new V4i(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYO => new V4i(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYI => new V4i(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYN => new V4i(Z, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYX => new V4i(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYY => new V4i(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYZ => new V4i(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZO => new V4i(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZI => new V4i(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZN => new V4i(Z, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZX => new V4i(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZY => new V4i(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZZ => new V4i(Z, Z, Z, Z);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (int)value; }\n        }\n\n        #endregion\n\n        #region ISize3i Members\n\n        public readonly V3i Size3i { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 3; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (int)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V3iEqualityComparer : IEqualityComparer<V3i>\n    {\n        public static V3iEqualityComparer Default\n            => new V3iEqualityComparer();\n\n        #region IEqualityComparer<V3i> Members\n\n        public bool Equals(V3i v0, V3i v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V3i v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Min(this V3i a, V3i b)\n        {\n            return new V3i(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Min(this V3i a, int b)\n        {\n            return new V3i(Min(a.X, b), Min(a.Y, b), Min(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Min(this int a, V3i b)\n        {\n            return new V3i(Min(a, b.X), Min(a, b.Y), Min(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Max(this V3i a, V3i b)\n        {\n            return new V3i(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Max(this V3i a, int b)\n        {\n            return new V3i(Max(a.X, b), Max(a.Y, b), Max(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Max(this int a, V3i b)\n        {\n            return new V3i(Max(a, b.X), Max(a, b.Y), Max(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Min(this V3i a, V3i b, V3i c)\n        {\n            return new V3i(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Max(this V3i a, V3i b, V3i c)\n        {\n            return new V3i(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Min(this V3i a, V3i b, V3i c, V3i d)\n        {\n            return new V3i(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Max(this V3i a, V3i b, V3i c, V3i d)\n        {\n            return new V3i(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Min(this V3i x, params V3i[] values)\n        {\n            return new V3i(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Max(this V3i x, params V3i[] values)\n        {\n            return new V3i(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Abs(this V3i x)\n        {\n            return new V3i(Abs(x.X), Abs(x.Y), Abs(x.Z));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Clamp(this V3i x, V3i a, V3i b)\n        {\n            return new V3i(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Clamp(this V3i x, int a, int b)\n        {\n            return new V3i(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i ClampExcl(this V3i x, V3i a, V3i b)\n        {\n            return new V3i(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y), ClampExcl(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i ClampExcl(this V3i x, int a, int b)\n        {\n            return new V3i(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b), ClampExcl(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i ClampWrap(this V3i x, V3i a, V3i b)\n        {\n            return new V3i(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i ClampWrap(this V3i x, int a, int b)\n        {\n            return new V3i(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Saturate(this V3i x)\n        {\n            return new V3i(Saturate(x.X), Saturate(x.Y), Saturate(x.Z));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Sign(this V3i x)\n        {\n            return new V3i(Sign(x.X), Sign(x.Y), Sign(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Signumi(this V3i x)\n        {\n            return new V3i(Signumi(x.X), Signumi(x.Y), Signumi(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Signum(this V3i x)\n        {\n            return new V3i(Signum(x.X), Signum(x.Y), Signum(x.Z));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i MultiplyAdd(V3i x, V3i y, V3i z)\n        {\n            return new V3i(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i MultiplyAdd(V3i x, int y, V3i z)\n        {\n            return new V3i(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i MultiplyAdd(int x, V3i y, V3i z)\n        {\n            return new V3i(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sqrt(this V3i x)\n        {\n            return new V3d(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cbrt(this V3i x)\n        {\n            return new V3d(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Square(this V3i x)\n        {\n            return new V3i(Square(x.X), Square(x.Y), Square(x.Z));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Pown(this V3i x, V3i y)\n        {\n            return new V3i(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Pown(this V3i x, int y)\n        {\n            return new V3i(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Pown(this int x, V3i y)\n        {\n            return new V3i(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this V3i x, V3f y)\n        {\n            return new V3f(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this V3i x, float y)\n        {\n            return new V3f(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this int x, V3f y)\n        {\n            return new V3f(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this V3i x, V3d y)\n        {\n            return new V3d(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this V3i x, double y)\n        {\n            return new V3d(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this int x, V3d y)\n        {\n            return new V3d(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this V3i x, V3f y)\n        {\n            return new V3f(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this V3i x, float y)\n        {\n            return new V3f(Power(x.X, y), Power(x.Y, y), Power(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this int x, V3f y)\n        {\n            return new V3f(Power(x, y.X), Power(x, y.Y), Power(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this V3i x, V3d y)\n        {\n            return new V3d(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this V3i x, double y)\n        {\n            return new V3d(Power(x.X, y), Power(x.Y, y), Power(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this int x, V3d y)\n        {\n            return new V3d(Power(x, y.X), Power(x, y.Y), Power(x, y.Z));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Exp(this V3i x)\n        {\n            return new V3d(Exp(x.X), Exp(x.Y), Exp(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(this V3i x)\n        {\n            return new V3d(Log(x.X), Log(x.Y), Log(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log2(this V3i x)\n        {\n            return new V3d(Log2(x.X), Log2(x.Y), Log2(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Log2Int(this V3i x)\n        {\n            return new V3i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log10(this V3i x)\n        {\n            return new V3d(Log10(x.X), Log10(x.Y), Log10(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(this V3i x, double basis)\n        {\n            return new V3d(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i ModP(this V3i a, V3i b)\n        {\n            return new V3i(ModP(a.X, b.X), ModP(a.Y, b.Y), ModP(a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l PowerOfTwo(this V3i x)\n        {\n            return new V3l(PowerOfTwo(x.X), PowerOfTwo(x.Y), PowerOfTwo(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.NextPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i NextPowerOfTwo(this V3i x)\n        {\n            return new V3i(NextPowerOfTwo(x.X), NextPowerOfTwo(x.Y), NextPowerOfTwo(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.PrevPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i PrevPowerOfTwo(this V3i x)\n        {\n            return new V3i(PrevPowerOfTwo(x.X), PrevPowerOfTwo(x.Y), PrevPowerOfTwo(x.Z));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Step(this V3i x, V3i edge)\n        {\n            return new V3i(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Step(this V3i x, int edge)\n        {\n            return new V3i(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Lerp(this float t, V3i a, V3i b)\n        {\n            return new V3i(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Lerp(this V3f t, V3i a, V3i b)\n        {\n            return new V3i(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Lerp(this double t, V3i a, V3i b)\n        {\n            return new V3i(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Lerp(this V3d t, V3i a, V3i b)\n        {\n            return new V3i(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvLerp(this V3i y, V3i a, V3i b)\n        {\n            return new V3d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i GreatestCommonDivisor(this V3i a, V3i b)\n        {\n            return new V3i(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y), GreatestCommonDivisor(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i LeastCommonMultiple(this V3i a, V3i b)\n        {\n            return new V3i(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y), LeastCommonMultiple(a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FloatFromBits(this V3i x)\n        {\n            return new V3f(FloatFromBits(x.X), FloatFromBits(x.Y), FloatFromBits(x.Z));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V3i a, V3i b, int tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V3i v, int epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LengthSquared(V3i v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V3i v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Normalized(V3i v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Norm1(V3i v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V3i v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMax(V3i v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMin(V3i v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V3i v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceSquared(this V3i a, V3i b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y) + Fun.Square(b.Z - a.Z);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V3i a, V3i b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Distance1(this V3i a, V3i b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y) + Fun.Abs(b.Z - a.Z);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V3i a, V3i b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p) + Fun.Abs(b.Z - a.Z).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceMax(this V3i a, V3i b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceMin(this V3i a, V3i b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V3i query, V3i p0, V3i p1)\n        {\n            return DistanceToLine((V3d) query, (V3d) p0, (V3d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V3i query, V3i p0, V3i p1)\n        {\n            return DistanceToInfiniteLine((V3d) query, (V3d) p0, (V3d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V3i query, V3i p0, V3i p1, out double t)\n        {\n            return DistanceToLine((V3d) query, (V3d) p0, (V3d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V3i query, V3i p0, V3i p1, out double t)\n        {\n            return DistanceToInfiniteLine((V3d) query, (V3d) p0, (V3d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V3i v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n            v.Z = -v.Z;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 3x3 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33i Outer(this V3i a, V3i b)\n        {\n            return new M33i(\n                        a.X * b.X, a.X * b.Y, a.X * b.Z, \n                        a.Y * b.X, a.Y * b.Y, a.Y * b.Z, \n                        a.Z * b.X, a.Z * b.Y, a.Z * b.Z);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Dot(this V3i a, V3i b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        /// <summary>\n        /// Returns the skew-symmetric \"cross\" matrix (A^T = -A) of the vector v.\n        /// </summary>\n        public static M33i CrossMatrix(this V3i v)\n        {\n            return new M33i(0, -v.Z, +v.Y,\n                            +v.Z, 0, -v.X,\n                            -v.Y, +v.X, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V3i v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > 0) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < 0) flags |= Aardbase.DirFlags.NegativeZ;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the cross product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Cross(this V3i a, V3i b)\n        {\n            return new V3i(\n            a.Y * b.Z - a.Z * b.Y,\n            a.Z * b.X - a.X * b.Z,\n            a.X * b.Y - a.Y * b.X\n            );\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3i a, V3i b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3i v, int s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(int s, V3i v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3i a, V3i b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3i v, int s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(int s, V3i v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3i a, V3i b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3i v, int s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(int s, V3i v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3i a, V3i b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3i v, int s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(int s, V3i v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3i a, V3i b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3i v, int s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(int s, V3i v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3i a, V3i b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3i v, int s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(int s, V3i v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3i a, V3i b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3i v, int s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(int s, V3i v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3i a, V3i b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3i v, int s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(int s, V3i v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3i a, V3i b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3i v, int s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(int s, V3i v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3i a, V3i b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3i v, int s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(int s, V3i v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3i a, V3i b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3i v, int s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(int s, V3i v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3i a, V3i b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3i v, int s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(int s, V3i v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V3i v0, V3i v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V3i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MinElement(V3i v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V3i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MaxElement(V3i v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V3i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V3i v, int epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V3i v, int epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V3i[] pointArray, V3i point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V3i[] array, int start, int count,\n                V3i point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V3i> pointSelector, V3i point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V3i[] pointArray, V3i point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V3i[] array, long start, long count,\n                V3i point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V3i> pointSelector, V3i point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V3i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V3i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V3i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V3i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V3i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V3i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V3i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V3i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V3i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V3i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V3i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V3i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V3i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V3i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V3i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V3i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V3i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V3i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static int[] CopyCoord(this V3i[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV3iExtensions\n    {\n        #region IRandomUniform extensions for V3i\n\n        /// <summary>\n        /// Uses UniformInt() to generate the elements of a V3i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i UniformV3i(this IRandomUniform rnd)\n        {\n            return new V3i(rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt());\n        }\n\n        /// <summary>\n        /// Uses UniformIntNonZero() to generate the elements of a V3i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i UniformV3iNonZero(this IRandomUniform rnd)\n        {\n            return new V3i(rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of a V3i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i UniformV3i(this IRandomUniform rnd, int size)\n        {\n            return new V3i(rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size));\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of a V3i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i UniformV3i(this IRandomUniform rnd, V3i size)\n        {\n            return new V3i(rnd.UniformInt(size.X), rnd.UniformInt(size.Y), rnd.UniformInt(size.Z));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V3ui\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V3ui : IVector<double>, ISize3ui, IFormattable, IEquatable<V3ui>\n    {\n        [DataMember]\n        public uint X;\n        [DataMember]\n        public uint Y;\n        [DataMember]\n        public uint Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(int x, int y, int z)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(int v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n            Z = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(int[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n            Z = (uint)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(int[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n            Z = (uint)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(int a, V2i b)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2i a, int b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(uint x, uint y, uint z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(uint v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(uint[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(uint[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(uint a, V2ui b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2ui a, uint b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(long x, long y, long z)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(long v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n            Z = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(long[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n            Z = (uint)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(long[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n            Z = (uint)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(long a, V2l b)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2l a, long b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(float x, float y, float z)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(float v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n            Z = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(float[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n            Z = (uint)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(float[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n            Z = (uint)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(float a, V2f b)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2f a, float b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(double x, double y, double z)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(double v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n            Z = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(double[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n            Z = (uint)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(double[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n            Z = (uint)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(double a, V2d b)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2d a, double b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(Func<int, uint> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;uint&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 3.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(IVector<double> v)\n            : this(v[0], v[1], v[2])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V2d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V3i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V3ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V3l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V3f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V3d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V4i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V4ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V4l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V4f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(V4d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(C3b c)\n        {\n            X = (uint)(c.R);\n            Y = (uint)(c.G);\n            Z = (uint)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(C3us c)\n        {\n            X = (uint)(c.R);\n            Y = (uint)(c.G);\n            Z = (uint)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(C3ui c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(C4b c)\n        {\n            X = (uint)(c.R);\n            Y = (uint)(c.G);\n            Z = (uint)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(C4us c)\n        {\n            X = (uint)(c.R);\n            Y = (uint)(c.G);\n            Z = (uint)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3ui(C4ui c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V2i v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V2ui v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V2l v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V2f v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V2d v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V3i v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V3l v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V3f v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V3d v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V4i v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V4ui v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V4l v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V4f v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(V4d v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V3ui v)\n            => new int[] { (int)v.X, (int)v.Y, (int)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(int[] v)\n            => new V3ui((uint)v[0], (uint)v[1], (uint)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V3ui v)\n            => new uint[] { v.X, v.Y, v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(uint[] v)\n            => new V3ui(v[0], v[1], v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V3ui v)\n            => new long[] { (long)v.X, (long)v.Y, (long)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(long[] v)\n            => new V3ui((uint)v[0], (uint)v[1], (uint)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V3ui v)\n            => new float[] { (float)v.X, (float)v.Y, (float)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(float[] v)\n            => new V3ui((uint)v[0], (uint)v[1], (uint)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V3ui v)\n            => new double[] { (double)v.X, (double)v.Y, (double)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(double[] v)\n            => new V3ui((uint)v[0], (uint)v[1], (uint)v[2]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(C3b v)\n            => new V3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(C3us v)\n            => new V3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(C3ui v)\n            => new V3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(C4b v)\n            => new V3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(C4us v)\n            => new V3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V3ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3ui(C4ui v)\n            => new V3ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3ui\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<uint, int> element_fun)\n            => new V3i(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<uint, int, int> element_index_fun)\n            => new V3i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n            array[start + 2] = (int)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<uint, uint> element_fun)\n            => new V3ui(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<uint, int, uint> element_index_fun)\n            => new V3ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<uint, long> element_fun)\n            => new V3l(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<uint, int, long> element_index_fun)\n            => new V3l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n            array[start + 2] = (long)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<uint, float> element_fun)\n            => new V3f(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<uint, int, float> element_index_fun)\n            => new V3f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n            array[start + 2] = (float)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<uint, double> element_fun)\n            => new V3d(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<uint, int, double> element_index_fun)\n            => new V3d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n            array[start + 2] = (double)Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly uint[] ToArray()\n            => new uint[] { X, Y, Z };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<uint> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe uint this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (uint* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (uint* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? (X >= Z ? 0 : 2) : (Y >= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? (X <= Z ? 0 : 2) : (Y <= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly uint MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly uint MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 3;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V3ui Zero\n        {\n            get { return new V3ui(0, 0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V3ui One\n        {\n            get { return new V3ui(1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V3ui MaxValue\n        {\n            get { return new V3ui(Constant<uint>.ParseableMaxValue, Constant<uint>.ParseableMaxValue, Constant<uint>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V3ui MinValue\n        {\n            get { return new V3ui(Constant<uint>.ParseableMinValue, Constant<uint>.ParseableMinValue, Constant<uint>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V3ui XAxis\n        {\n            get { return new V3ui(1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V3ui YAxis\n        {\n            get { return new V3ui(0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V3ui ZAxis\n        {\n            get { return new V3ui(0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V3ui, uint>[] SelectorArray =\n            new Func<V3ui, uint>[] { v => v.X, v => v.Y, v => v.Z };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V3ui, int, uint> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V3ui, int, uint> Setter =\n            (ref V3ui v, int i, uint s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V3ui, long, uint> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V3ui, long, uint> LongSetter =\n            (ref V3ui v, long i, uint s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromV3i(V3i v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromV3l(V3l v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromV3f(V3f v)\n            => new V3ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromV3d(V3d v)\n            => new V3ui(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromC3b(C3b c) => new V3ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromC3us(C3us c) => new V3ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromC3ui(C3ui c) => new V3ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromC4b(C4b c) => new V3ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromC4us(C4us c) => new V3ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FromC4ui(C4ui c) => new V3ui(c);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly uint LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly uint Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X + Y + Z; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly uint NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(X, Y, Z); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly uint NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(X, Y, Z); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V3d.Zero;\n                s = 1 / s;\n                return new V3d(X * s, Y * s, Z * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui LinearInterp(float t, V3ui a, V3ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui LinearInterp(V3f t, V3ui a, V3ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui LinearInterp(double t, V3ui a, V3ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui LinearInterp(V3d t, V3ui a, V3ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Min(V3ui v0, V3ui v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Min(V3ui v, uint x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Max(V3ui v0, V3ui v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Max(V3ui v, uint x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Saturate(V3ui v)\n            => Fun.Saturate(v);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n        }\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator ~(V3ui v)\n            => new V3ui(~v.X, ~v.Y, ~v.Z);\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator +(V3ui a, V3ui b)\n            => new V3ui(a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator +(V3ui v, uint s)\n            => new V3ui(v.X + s, v.Y + s, v.Z + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator +(uint s, V3ui v)\n            => new V3ui(s + v.X, s + v.Y, s + v.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator -(V3ui a, V3ui b)\n            => new V3ui(a.X - b.X, a.Y - b.Y, a.Z - b.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator -(V3ui v, uint s)\n            => new V3ui(v.X - s, v.Y - s, v.Z - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator -(uint s, V3ui v)\n            => new V3ui(s - v.X, s - v.Y, s - v.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator *(V3ui a, V3ui b)\n            => new V3ui(a.X * b.X, a.Y * b.Y, a.Z * b.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator *(V3ui v, uint s)\n            => new V3ui(v.X * s, v.Y * s, v.Z * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator *(uint s, V3ui v)\n            => new V3ui(s * v.X, s * v.Y, s * v.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator /(V3ui a, V3ui b)\n            => new V3ui(a.X / b.X, a.Y / b.Y, a.Z / b.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator /(V3ui v, uint s)\n            => new V3ui(v.X / s, v.Y / s, v.Z / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator /(uint s, V3ui v)\n            => new V3ui(s / v.X, s / v.Y, s / v.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator %(V3ui a, V3ui b)\n            => new V3ui(a.X % b.X, a.Y % b.Y, a.Z % b.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator %(V3ui v, uint s)\n            => new V3ui(v.X % s, v.Y % s, v.Z % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator %(uint s, V3ui v)\n            => new V3ui(s % v.X, s % v.Y, s % v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator &(V3ui a, V3ui b)\n            => new V3ui(a.X & b.X, a.Y & b.Y, a.Z & b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator &(V3ui v, uint s)\n            => new V3ui(v.X & s, v.Y & s, v.Z & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator &(uint s, V3ui v)\n            => new V3ui(s & v.X, s & v.Y, s & v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator |(V3ui a, V3ui b)\n            => new V3ui(a.X | b.X, a.Y | b.Y, a.Z | b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator |(V3ui v, uint s)\n            => new V3ui(v.X | s, v.Y | s, v.Z | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator |(uint s, V3ui v)\n            => new V3ui(s | v.X, s | v.Y, s | v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator ^(V3ui a, V3ui b)\n            => new V3ui(a.X ^ b.X, a.Y ^ b.Y, a.Z ^ b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator ^(V3ui v, uint s)\n            => new V3ui(v.X ^ s, v.Y ^ s, v.Z ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator ^(uint s, V3ui v)\n            => new V3ui(s ^ v.X, s ^ v.Y, s ^ v.Z);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator <<(V3ui v, int s)\n            => new V3ui(v.X << s, v.Y << s, v.Z << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui operator >>(V3ui v, int s)\n            => new V3ui(v.X >> s, v.Y >> s, v.Z >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3ui a, V3ui b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3ui v, uint s)\n        {\n            return v.X == s && v.Y == s && v.Z == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(uint s, V3ui v)\n        {\n            return s == v.X && s == v.Y && s == v.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3ui a, V3ui b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3ui v, uint s)\n        {\n            return v.X != s || v.Y != s || v.Z != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(uint s, V3ui v)\n        {\n            return s != v.X || s != v.Y || s != v.Z;\n        }\n\n        #endregion\n\n        #region IEquatable<V3ui> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V3ui other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V3ui o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V3ui Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V3ui(\n                uint.Parse(x[0], CultureInfo.InvariantCulture), \n                uint.Parse(x[1], CultureInfo.InvariantCulture), \n                uint.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V3ui Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<uint>.Parse, V3ui.Setter);\n        }\n\n        public static V3ui Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<uint>.Parse, V3ui.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OX => new V2ui(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OY => new V2ui(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OZ => new V2ui(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IX => new V2ui(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IY => new V2ui(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IZ => new V2ui(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XO => new V2ui(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XI => new V2ui(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XX => new V2ui(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui XY\n        {\n            readonly get => new V2ui(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui XZ\n        {\n            readonly get => new V2ui(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YO => new V2ui(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YI => new V2ui(Y, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui YX\n        {\n            readonly get => new V2ui(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YY => new V2ui(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui YZ\n        {\n            readonly get => new V2ui(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui ZO => new V2ui(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui ZI => new V2ui(Z, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui ZX\n        {\n            readonly get => new V2ui(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui ZY\n        {\n            readonly get => new V2ui(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui ZZ => new V2ui(Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3ui OOO => new V3ui(0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3ui OOI => new V3ui(0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOX => new V3ui(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOY => new V3ui(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOZ => new V3ui(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3ui OIO => new V3ui(0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3ui OII => new V3ui(0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIX => new V3ui(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIY => new V3ui(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIZ => new V3ui(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXO => new V3ui(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXI => new V3ui(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXX => new V3ui(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXY => new V3ui(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXZ => new V3ui(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYO => new V3ui(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYI => new V3ui(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYX => new V3ui(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYY => new V3ui(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYZ => new V3ui(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZO => new V3ui(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZI => new V3ui(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZX => new V3ui(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZY => new V3ui(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZZ => new V3ui(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3ui IOO => new V3ui(1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3ui IOI => new V3ui(1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOX => new V3ui(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOY => new V3ui(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOZ => new V3ui(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3ui IIO => new V3ui(1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3ui III => new V3ui(1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIX => new V3ui(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIY => new V3ui(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIZ => new V3ui(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXO => new V3ui(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXI => new V3ui(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXX => new V3ui(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXY => new V3ui(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXZ => new V3ui(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYO => new V3ui(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYI => new V3ui(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYX => new V3ui(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYY => new V3ui(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYZ => new V3ui(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZO => new V3ui(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZI => new V3ui(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZX => new V3ui(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZY => new V3ui(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZZ => new V3ui(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOO => new V3ui(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOI => new V3ui(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOX => new V3ui(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOY => new V3ui(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOZ => new V3ui(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIO => new V3ui(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XII => new V3ui(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIX => new V3ui(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIY => new V3ui(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIZ => new V3ui(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXO => new V3ui(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXI => new V3ui(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXX => new V3ui(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXY => new V3ui(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXZ => new V3ui(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYO => new V3ui(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYI => new V3ui(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYX => new V3ui(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYY => new V3ui(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui XYZ\n        {\n            readonly get => new V3ui(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XZO => new V3ui(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XZI => new V3ui(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XZX => new V3ui(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui XZY\n        {\n            readonly get => new V3ui(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XZZ => new V3ui(X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOO => new V3ui(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOI => new V3ui(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOX => new V3ui(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOY => new V3ui(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOZ => new V3ui(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIO => new V3ui(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YII => new V3ui(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIX => new V3ui(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIY => new V3ui(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIZ => new V3ui(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXO => new V3ui(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXI => new V3ui(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXX => new V3ui(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXY => new V3ui(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui YXZ\n        {\n            readonly get => new V3ui(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYO => new V3ui(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYI => new V3ui(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYX => new V3ui(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYY => new V3ui(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYZ => new V3ui(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YZO => new V3ui(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YZI => new V3ui(Y, Z, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui YZX\n        {\n            readonly get => new V3ui(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YZY => new V3ui(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YZZ => new V3ui(Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOO => new V3ui(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOI => new V3ui(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOX => new V3ui(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOY => new V3ui(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOZ => new V3ui(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIO => new V3ui(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZII => new V3ui(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIX => new V3ui(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIY => new V3ui(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIZ => new V3ui(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZXO => new V3ui(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZXI => new V3ui(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZXX => new V3ui(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui ZXY\n        {\n            readonly get => new V3ui(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZXZ => new V3ui(Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZYO => new V3ui(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZYI => new V3ui(Z, Y, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui ZYX\n        {\n            readonly get => new V3ui(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZYY => new V3ui(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZYZ => new V3ui(Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZO => new V3ui(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZI => new V3ui(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZX => new V3ui(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZY => new V3ui(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZZ => new V3ui(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOX => new V4ui(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOY => new V4ui(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOZ => new V4ui(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIX => new V4ui(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIY => new V4ui(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIZ => new V4ui(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXO => new V4ui(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXI => new V4ui(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXX => new V4ui(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXY => new V4ui(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXZ => new V4ui(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYO => new V4ui(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYI => new V4ui(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYX => new V4ui(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYY => new V4ui(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYZ => new V4ui(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZO => new V4ui(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZI => new V4ui(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZX => new V4ui(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZY => new V4ui(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZZ => new V4ui(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOX => new V4ui(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOY => new V4ui(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOZ => new V4ui(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIX => new V4ui(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIY => new V4ui(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIZ => new V4ui(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXO => new V4ui(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXI => new V4ui(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXX => new V4ui(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXY => new V4ui(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXZ => new V4ui(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYO => new V4ui(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYI => new V4ui(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYX => new V4ui(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYY => new V4ui(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYZ => new V4ui(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZO => new V4ui(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZI => new V4ui(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZX => new V4ui(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZY => new V4ui(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZZ => new V4ui(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOO => new V4ui(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOI => new V4ui(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOX => new V4ui(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOY => new V4ui(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOZ => new V4ui(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIO => new V4ui(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXII => new V4ui(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIX => new V4ui(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIY => new V4ui(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIZ => new V4ui(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXO => new V4ui(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXI => new V4ui(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXX => new V4ui(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXY => new V4ui(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXZ => new V4ui(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYO => new V4ui(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYI => new V4ui(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYX => new V4ui(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYY => new V4ui(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYZ => new V4ui(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZO => new V4ui(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZI => new V4ui(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZX => new V4ui(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZY => new V4ui(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZZ => new V4ui(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOO => new V4ui(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOI => new V4ui(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOX => new V4ui(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOY => new V4ui(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOZ => new V4ui(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIO => new V4ui(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYII => new V4ui(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIX => new V4ui(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIY => new V4ui(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIZ => new V4ui(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXO => new V4ui(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXI => new V4ui(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXX => new V4ui(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXY => new V4ui(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXZ => new V4ui(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYO => new V4ui(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYI => new V4ui(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYX => new V4ui(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYY => new V4ui(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYZ => new V4ui(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZO => new V4ui(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZI => new V4ui(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZX => new V4ui(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZY => new V4ui(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZZ => new V4ui(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOO => new V4ui(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOI => new V4ui(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOX => new V4ui(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOY => new V4ui(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOZ => new V4ui(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIO => new V4ui(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZII => new V4ui(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIX => new V4ui(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIY => new V4ui(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIZ => new V4ui(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXO => new V4ui(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXI => new V4ui(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXX => new V4ui(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXY => new V4ui(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXZ => new V4ui(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYO => new V4ui(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYI => new V4ui(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYX => new V4ui(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYY => new V4ui(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYZ => new V4ui(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZO => new V4ui(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZI => new V4ui(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZX => new V4ui(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZY => new V4ui(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZZ => new V4ui(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOX => new V4ui(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOY => new V4ui(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOZ => new V4ui(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIX => new V4ui(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIY => new V4ui(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIZ => new V4ui(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXO => new V4ui(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXI => new V4ui(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXX => new V4ui(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXY => new V4ui(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXZ => new V4ui(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYO => new V4ui(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYI => new V4ui(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYX => new V4ui(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYY => new V4ui(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYZ => new V4ui(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZO => new V4ui(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZI => new V4ui(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZX => new V4ui(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZY => new V4ui(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZZ => new V4ui(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOX => new V4ui(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOY => new V4ui(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOZ => new V4ui(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIX => new V4ui(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIY => new V4ui(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIZ => new V4ui(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXO => new V4ui(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXI => new V4ui(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXX => new V4ui(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXY => new V4ui(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXZ => new V4ui(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYO => new V4ui(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYI => new V4ui(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYX => new V4ui(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYY => new V4ui(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYZ => new V4ui(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZO => new V4ui(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZI => new V4ui(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZX => new V4ui(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZY => new V4ui(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZZ => new V4ui(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOO => new V4ui(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOI => new V4ui(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOX => new V4ui(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOY => new V4ui(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOZ => new V4ui(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIO => new V4ui(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXII => new V4ui(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIX => new V4ui(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIY => new V4ui(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIZ => new V4ui(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXO => new V4ui(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXI => new V4ui(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXX => new V4ui(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXY => new V4ui(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXZ => new V4ui(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYO => new V4ui(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYI => new V4ui(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYX => new V4ui(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYY => new V4ui(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYZ => new V4ui(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZO => new V4ui(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZI => new V4ui(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZX => new V4ui(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZY => new V4ui(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZZ => new V4ui(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOO => new V4ui(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOI => new V4ui(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOX => new V4ui(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOY => new V4ui(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOZ => new V4ui(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIO => new V4ui(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYII => new V4ui(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIX => new V4ui(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIY => new V4ui(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIZ => new V4ui(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXO => new V4ui(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXI => new V4ui(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXX => new V4ui(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXY => new V4ui(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXZ => new V4ui(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYO => new V4ui(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYI => new V4ui(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYX => new V4ui(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYY => new V4ui(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYZ => new V4ui(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZO => new V4ui(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZI => new V4ui(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZX => new V4ui(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZY => new V4ui(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZZ => new V4ui(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOO => new V4ui(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOI => new V4ui(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOX => new V4ui(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOY => new V4ui(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOZ => new V4ui(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIO => new V4ui(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZII => new V4ui(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIX => new V4ui(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIY => new V4ui(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIZ => new V4ui(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXO => new V4ui(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXI => new V4ui(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXX => new V4ui(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXY => new V4ui(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXZ => new V4ui(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYO => new V4ui(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYI => new V4ui(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYX => new V4ui(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYY => new V4ui(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYZ => new V4ui(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZO => new V4ui(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZI => new V4ui(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZX => new V4ui(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZY => new V4ui(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZZ => new V4ui(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOO => new V4ui(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOI => new V4ui(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOX => new V4ui(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOY => new V4ui(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOZ => new V4ui(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIO => new V4ui(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOII => new V4ui(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIX => new V4ui(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIY => new V4ui(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIZ => new V4ui(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXO => new V4ui(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXI => new V4ui(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXX => new V4ui(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXY => new V4ui(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXZ => new V4ui(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYO => new V4ui(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYI => new V4ui(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYX => new V4ui(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYY => new V4ui(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYZ => new V4ui(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZO => new V4ui(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZI => new V4ui(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZX => new V4ui(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZY => new V4ui(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZZ => new V4ui(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOO => new V4ui(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOI => new V4ui(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOX => new V4ui(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOY => new V4ui(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOZ => new V4ui(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIO => new V4ui(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIII => new V4ui(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIX => new V4ui(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIY => new V4ui(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIZ => new V4ui(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXO => new V4ui(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXI => new V4ui(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXX => new V4ui(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXY => new V4ui(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXZ => new V4ui(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYO => new V4ui(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYI => new V4ui(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYX => new V4ui(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYY => new V4ui(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYZ => new V4ui(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZO => new V4ui(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZI => new V4ui(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZX => new V4ui(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZY => new V4ui(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZZ => new V4ui(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOO => new V4ui(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOI => new V4ui(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOX => new V4ui(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOY => new V4ui(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOZ => new V4ui(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIO => new V4ui(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXII => new V4ui(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIX => new V4ui(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIY => new V4ui(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIZ => new V4ui(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXO => new V4ui(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXI => new V4ui(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXX => new V4ui(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXY => new V4ui(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXZ => new V4ui(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYO => new V4ui(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYI => new V4ui(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYX => new V4ui(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYY => new V4ui(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYZ => new V4ui(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZO => new V4ui(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZI => new V4ui(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZX => new V4ui(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZY => new V4ui(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZZ => new V4ui(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOO => new V4ui(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOI => new V4ui(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOX => new V4ui(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOY => new V4ui(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOZ => new V4ui(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIO => new V4ui(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYII => new V4ui(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIX => new V4ui(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIY => new V4ui(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIZ => new V4ui(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXO => new V4ui(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXI => new V4ui(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXX => new V4ui(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXY => new V4ui(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXZ => new V4ui(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYO => new V4ui(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYI => new V4ui(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYX => new V4ui(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYY => new V4ui(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYZ => new V4ui(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZO => new V4ui(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZI => new V4ui(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZX => new V4ui(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZY => new V4ui(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZZ => new V4ui(X, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOO => new V4ui(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOI => new V4ui(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOX => new V4ui(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOY => new V4ui(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOZ => new V4ui(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIO => new V4ui(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZII => new V4ui(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIX => new V4ui(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIY => new V4ui(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIZ => new V4ui(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXO => new V4ui(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXI => new V4ui(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXX => new V4ui(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXY => new V4ui(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXZ => new V4ui(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYO => new V4ui(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYI => new V4ui(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYX => new V4ui(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYY => new V4ui(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYZ => new V4ui(X, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZO => new V4ui(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZI => new V4ui(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZX => new V4ui(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZY => new V4ui(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZZ => new V4ui(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOO => new V4ui(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOI => new V4ui(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOX => new V4ui(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOY => new V4ui(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOZ => new V4ui(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIO => new V4ui(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOII => new V4ui(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIX => new V4ui(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIY => new V4ui(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIZ => new V4ui(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXO => new V4ui(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXI => new V4ui(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXX => new V4ui(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXY => new V4ui(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXZ => new V4ui(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYO => new V4ui(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYI => new V4ui(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYX => new V4ui(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYY => new V4ui(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYZ => new V4ui(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZO => new V4ui(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZI => new V4ui(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZX => new V4ui(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZY => new V4ui(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZZ => new V4ui(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOO => new V4ui(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOI => new V4ui(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOX => new V4ui(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOY => new V4ui(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOZ => new V4ui(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIO => new V4ui(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIII => new V4ui(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIX => new V4ui(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIY => new V4ui(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIZ => new V4ui(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXO => new V4ui(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXI => new V4ui(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXX => new V4ui(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXY => new V4ui(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXZ => new V4ui(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYO => new V4ui(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYI => new V4ui(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYX => new V4ui(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYY => new V4ui(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYZ => new V4ui(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZO => new V4ui(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZI => new V4ui(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZX => new V4ui(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZY => new V4ui(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZZ => new V4ui(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOO => new V4ui(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOI => new V4ui(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOX => new V4ui(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOY => new V4ui(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOZ => new V4ui(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIO => new V4ui(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXII => new V4ui(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIX => new V4ui(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIY => new V4ui(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIZ => new V4ui(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXO => new V4ui(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXI => new V4ui(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXX => new V4ui(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXY => new V4ui(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXZ => new V4ui(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYO => new V4ui(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYI => new V4ui(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYX => new V4ui(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYY => new V4ui(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYZ => new V4ui(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZO => new V4ui(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZI => new V4ui(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZX => new V4ui(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZY => new V4ui(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZZ => new V4ui(Y, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOO => new V4ui(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOI => new V4ui(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOX => new V4ui(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOY => new V4ui(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOZ => new V4ui(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIO => new V4ui(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYII => new V4ui(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIX => new V4ui(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIY => new V4ui(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIZ => new V4ui(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXO => new V4ui(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXI => new V4ui(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXX => new V4ui(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXY => new V4ui(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXZ => new V4ui(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYO => new V4ui(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYI => new V4ui(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYX => new V4ui(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYY => new V4ui(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYZ => new V4ui(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZO => new V4ui(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZI => new V4ui(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZX => new V4ui(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZY => new V4ui(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZZ => new V4ui(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOO => new V4ui(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOI => new V4ui(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOX => new V4ui(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOY => new V4ui(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOZ => new V4ui(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIO => new V4ui(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZII => new V4ui(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIX => new V4ui(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIY => new V4ui(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIZ => new V4ui(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXO => new V4ui(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXI => new V4ui(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXX => new V4ui(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXY => new V4ui(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXZ => new V4ui(Y, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYO => new V4ui(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYI => new V4ui(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYX => new V4ui(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYY => new V4ui(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYZ => new V4ui(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZO => new V4ui(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZI => new V4ui(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZX => new V4ui(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZY => new V4ui(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZZ => new V4ui(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOO => new V4ui(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOI => new V4ui(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOX => new V4ui(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOY => new V4ui(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOZ => new V4ui(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIO => new V4ui(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOII => new V4ui(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIX => new V4ui(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIY => new V4ui(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIZ => new V4ui(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXO => new V4ui(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXI => new V4ui(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXX => new V4ui(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXY => new V4ui(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXZ => new V4ui(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYO => new V4ui(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYI => new V4ui(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYX => new V4ui(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYY => new V4ui(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYZ => new V4ui(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZO => new V4ui(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZI => new V4ui(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZX => new V4ui(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZY => new V4ui(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZZ => new V4ui(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOO => new V4ui(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOI => new V4ui(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOX => new V4ui(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOY => new V4ui(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOZ => new V4ui(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIO => new V4ui(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIII => new V4ui(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIX => new V4ui(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIY => new V4ui(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIZ => new V4ui(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXO => new V4ui(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXI => new V4ui(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXX => new V4ui(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXY => new V4ui(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXZ => new V4ui(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYO => new V4ui(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYI => new V4ui(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYX => new V4ui(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYY => new V4ui(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYZ => new V4ui(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZO => new V4ui(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZI => new V4ui(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZX => new V4ui(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZY => new V4ui(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZZ => new V4ui(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOO => new V4ui(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOI => new V4ui(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOX => new V4ui(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOY => new V4ui(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOZ => new V4ui(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIO => new V4ui(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXII => new V4ui(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIX => new V4ui(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIY => new V4ui(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIZ => new V4ui(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXO => new V4ui(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXI => new V4ui(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXX => new V4ui(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXY => new V4ui(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXZ => new V4ui(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYO => new V4ui(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYI => new V4ui(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYX => new V4ui(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYY => new V4ui(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYZ => new V4ui(Z, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZO => new V4ui(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZI => new V4ui(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZX => new V4ui(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZY => new V4ui(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZZ => new V4ui(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOO => new V4ui(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOI => new V4ui(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOX => new V4ui(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOY => new V4ui(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOZ => new V4ui(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIO => new V4ui(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYII => new V4ui(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIX => new V4ui(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIY => new V4ui(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIZ => new V4ui(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXO => new V4ui(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXI => new V4ui(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXX => new V4ui(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXY => new V4ui(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXZ => new V4ui(Z, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYO => new V4ui(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYI => new V4ui(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYX => new V4ui(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYY => new V4ui(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYZ => new V4ui(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZO => new V4ui(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZI => new V4ui(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZX => new V4ui(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZY => new V4ui(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZZ => new V4ui(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOO => new V4ui(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOI => new V4ui(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOX => new V4ui(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOY => new V4ui(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOZ => new V4ui(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIO => new V4ui(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZII => new V4ui(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIX => new V4ui(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIY => new V4ui(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIZ => new V4ui(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXO => new V4ui(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXI => new V4ui(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXX => new V4ui(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXY => new V4ui(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXZ => new V4ui(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYO => new V4ui(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYI => new V4ui(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYX => new V4ui(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYY => new V4ui(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYZ => new V4ui(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZO => new V4ui(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZI => new V4ui(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZX => new V4ui(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZY => new V4ui(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZZ => new V4ui(Z, Z, Z, Z);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (uint)value; }\n        }\n\n        #endregion\n\n        #region ISize3ui Members\n\n        public readonly V3ui Size3ui { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 3; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (uint)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V3uiEqualityComparer : IEqualityComparer<V3ui>\n    {\n        public static V3uiEqualityComparer Default\n            => new V3uiEqualityComparer();\n\n        #region IEqualityComparer<V3ui> Members\n\n        public bool Equals(V3ui v0, V3ui v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V3ui v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Min(this V3ui a, V3ui b)\n        {\n            return new V3ui(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Min(this V3ui a, uint b)\n        {\n            return new V3ui(Min(a.X, b), Min(a.Y, b), Min(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Min(this uint a, V3ui b)\n        {\n            return new V3ui(Min(a, b.X), Min(a, b.Y), Min(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Max(this V3ui a, V3ui b)\n        {\n            return new V3ui(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Max(this V3ui a, uint b)\n        {\n            return new V3ui(Max(a.X, b), Max(a.Y, b), Max(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Max(this uint a, V3ui b)\n        {\n            return new V3ui(Max(a, b.X), Max(a, b.Y), Max(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Min(this V3ui a, V3ui b, V3ui c)\n        {\n            return new V3ui(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Max(this V3ui a, V3ui b, V3ui c)\n        {\n            return new V3ui(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Min(this V3ui a, V3ui b, V3ui c, V3ui d)\n        {\n            return new V3ui(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Max(this V3ui a, V3ui b, V3ui c, V3ui d)\n        {\n            return new V3ui(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Min(this V3ui x, params V3ui[] values)\n        {\n            return new V3ui(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Max(this V3ui x, params V3ui[] values)\n        {\n            return new V3ui(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Clamp(this V3ui x, V3ui a, V3ui b)\n        {\n            return new V3ui(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Clamp(this V3ui x, uint a, uint b)\n        {\n            return new V3ui(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui ClampExcl(this V3ui x, V3ui a, V3ui b)\n        {\n            return new V3ui(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y), ClampExcl(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui ClampExcl(this V3ui x, uint a, uint b)\n        {\n            return new V3ui(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b), ClampExcl(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui ClampWrap(this V3ui x, V3ui a, V3ui b)\n        {\n            return new V3ui(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui ClampWrap(this V3ui x, uint a, uint b)\n        {\n            return new V3ui(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Saturate(this V3ui x)\n        {\n            return new V3ui(Saturate(x.X), Saturate(x.Y), Saturate(x.Z));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui MultiplyAdd(V3ui x, V3ui y, V3ui z)\n        {\n            return new V3ui(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui MultiplyAdd(V3ui x, uint y, V3ui z)\n        {\n            return new V3ui(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui MultiplyAdd(uint x, V3ui y, V3ui z)\n        {\n            return new V3ui(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sqrt(this V3ui x)\n        {\n            return new V3d(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cbrt(this V3ui x)\n        {\n            return new V3d(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Square(this V3ui x)\n        {\n            return new V3ui(Square(x.X), Square(x.Y), Square(x.Z));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Pown(this V3ui x, V3ui y)\n        {\n            return new V3ui(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Pown(this V3ui x, uint y)\n        {\n            return new V3ui(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Pown(this uint x, V3ui y)\n        {\n            return new V3ui(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Pown(this V3ui x, V3i y)\n        {\n            return new V3ui(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Pown(this V3ui x, int y)\n        {\n            return new V3ui(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Pown(this uint x, V3i y)\n        {\n            return new V3ui(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this V3ui x, V3f y)\n        {\n            return new V3f(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this V3ui x, float y)\n        {\n            return new V3f(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this uint x, V3f y)\n        {\n            return new V3f(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this V3ui x, V3d y)\n        {\n            return new V3d(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this V3ui x, double y)\n        {\n            return new V3d(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this uint x, V3d y)\n        {\n            return new V3d(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this V3ui x, V3f y)\n        {\n            return new V3f(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this V3ui x, float y)\n        {\n            return new V3f(Power(x.X, y), Power(x.Y, y), Power(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this uint x, V3f y)\n        {\n            return new V3f(Power(x, y.X), Power(x, y.Y), Power(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this V3ui x, V3d y)\n        {\n            return new V3d(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this V3ui x, double y)\n        {\n            return new V3d(Power(x.X, y), Power(x.Y, y), Power(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this uint x, V3d y)\n        {\n            return new V3d(Power(x, y.X), Power(x, y.Y), Power(x, y.Z));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Exp(this V3ui x)\n        {\n            return new V3d(Exp(x.X), Exp(x.Y), Exp(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(this V3ui x)\n        {\n            return new V3d(Log(x.X), Log(x.Y), Log(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log2(this V3ui x)\n        {\n            return new V3d(Log2(x.X), Log2(x.Y), Log2(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Log2Int(this V3ui x)\n        {\n            return new V3i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log10(this V3ui x)\n        {\n            return new V3d(Log10(x.X), Log10(x.Y), Log10(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(this V3ui x, double basis)\n        {\n            return new V3d(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Step(this V3ui x, V3ui edge)\n        {\n            return new V3ui(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Step(this V3ui x, uint edge)\n        {\n            return new V3ui(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Lerp(this float t, V3ui a, V3ui b)\n        {\n            return new V3ui(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Lerp(this V3f t, V3ui a, V3ui b)\n        {\n            return new V3ui(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Lerp(this double t, V3ui a, V3ui b)\n        {\n            return new V3ui(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui Lerp(this V3d t, V3ui a, V3ui b)\n        {\n            return new V3ui(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvLerp(this V3ui y, V3ui a, V3ui b)\n        {\n            return new V3d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui GreatestCommonDivisor(this V3ui a, V3ui b)\n        {\n            return new V3ui(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y), GreatestCommonDivisor(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui LeastCommonMultiple(this V3ui a, V3ui b)\n        {\n            return new V3ui(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y), LeastCommonMultiple(a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromUnsignedBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FloatFromUnsignedBits(this V3ui x)\n        {\n            return new V3f(FloatFromUnsignedBits(x.X), FloatFromUnsignedBits(x.Y), FloatFromUnsignedBits(x.Z));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V3ui a, V3ui b, uint tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V3ui v, uint epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint LengthSquared(V3ui v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V3ui v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Normalized(V3ui v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Norm1(V3ui v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V3ui v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint NormMax(V3ui v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint NormMin(V3ui v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V3ui v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceSquared(this V3ui a, V3ui b)\n            => Fun.Square((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)) + Fun.Square((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)) + Fun.Square((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z));\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V3ui a, V3ui b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Distance1(this V3ui a, V3ui b)\n            => ((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)) + ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)) + ((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z));\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V3ui a, V3ui b, double p)\n            => (((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)).Pow(p) + ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)).Pow(p) + ((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z)).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceMax(this V3ui a, V3ui b)\n            => Fun.Max(((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)), ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)), ((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z)));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceMin(this V3ui a, V3ui b)\n            => Fun.Min(((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)), ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)), ((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z)));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V3ui query, V3ui p0, V3ui p1)\n        {\n            return DistanceToLine((V3d) query, (V3d) p0, (V3d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V3ui query, V3ui p0, V3ui p1)\n        {\n            return DistanceToInfiniteLine((V3d) query, (V3d) p0, (V3d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V3ui query, V3ui p0, V3ui p1, out double t)\n        {\n            return DistanceToLine((V3d) query, (V3d) p0, (V3d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V3ui query, V3ui p0, V3ui p1, out double t)\n        {\n            return DistanceToInfiniteLine((V3d) query, (V3d) p0, (V3d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Dot(this V3ui a, V3ui b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V3ui v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > 0) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < 0) flags |= Aardbase.DirFlags.NegativeZ;\n            return flags;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3ui a, V3ui b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3ui v, uint s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(uint s, V3ui v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3ui a, V3ui b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3ui v, uint s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(uint s, V3ui v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3ui a, V3ui b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3ui v, uint s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(uint s, V3ui v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3ui a, V3ui b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3ui v, uint s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(uint s, V3ui v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3ui a, V3ui b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3ui v, uint s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(uint s, V3ui v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3ui a, V3ui b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3ui v, uint s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(uint s, V3ui v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3ui a, V3ui b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3ui v, uint s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(uint s, V3ui v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3ui a, V3ui b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3ui v, uint s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(uint s, V3ui v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3ui a, V3ui b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3ui v, uint s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(uint s, V3ui v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3ui a, V3ui b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3ui v, uint s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(uint s, V3ui v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3ui a, V3ui b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3ui v, uint s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(uint s, V3ui v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3ui a, V3ui b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3ui v, uint s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(uint s, V3ui v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V3ui v0, V3ui v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V3ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint MinElement(V3ui v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V3ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint MaxElement(V3ui v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V3ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V3ui v, uint epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V3ui v, uint epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V3ui[] pointArray, V3ui point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V3ui[] array, int start, int count,\n                V3ui point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V3ui> pointSelector, V3ui point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V3ui[] pointArray, V3ui point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V3ui[] array, long start, long count,\n                V3ui point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V3ui> pointSelector, V3ui point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V3ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V3ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V3ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V3ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V3ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V3ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V3ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V3ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V3ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V3ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V3ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V3ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V3ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V3ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V3ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V3ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V3ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V3ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static uint[] CopyCoord(this V3ui[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV3uiExtensions\n    {\n        #region IRandomUniform extensions for V3ui\n\n        /// <summary>\n        /// Uses UniformUInt() to generate the elements of a V3ui vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui UniformV3ui(this IRandomUniform rnd)\n        {\n            return new V3ui(rnd.UniformUInt(), rnd.UniformUInt(), rnd.UniformUInt());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V3l\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V3l : IVector<double>, ISize3l, IFormattable, IEquatable<V3l>\n    {\n        [DataMember]\n        public long X;\n        [DataMember]\n        public long Y;\n        [DataMember]\n        public long Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(int x, int y, int z)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(int v)\n        {\n            X = (long)v;\n            Y = (long)v;\n            Z = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(int[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n            Z = (long)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(int[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n            Z = (long)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(int a, V2i b)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2i a, int b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(uint x, uint y, uint z)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(uint v)\n        {\n            X = (long)v;\n            Y = (long)v;\n            Z = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(uint[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n            Z = (long)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(uint[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n            Z = (long)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(uint a, V2ui b)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2ui a, uint b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(long x, long y, long z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(long v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(long[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(long[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(long a, V2l b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2l a, long b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(float x, float y, float z)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(float v)\n        {\n            X = (long)v;\n            Y = (long)v;\n            Z = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(float[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n            Z = (long)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(float[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n            Z = (long)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(float a, V2f b)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2f a, float b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(double x, double y, double z)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(double v)\n        {\n            X = (long)v;\n            Y = (long)v;\n            Z = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(double[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n            Z = (long)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(double[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n            Z = (long)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(double a, V2d b)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2d a, double b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(Func<int, long> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;long&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 3.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(IVector<double> v)\n            : this(v[0], v[1], v[2])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2l v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V2d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V3i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V3ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V3l v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V3f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V3d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V4i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V4ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V4l v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V4f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(V4d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(C3b c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(C3us c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(C3ui c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(C4b c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(C4us c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3l(C4ui c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V2i v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V2ui v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V2l v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V2f v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V2d v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V3i v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V3ui v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V3f v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V3d v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V4i v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V4ui v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V4l v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V4f v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(V4d v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V3l v)\n            => new int[] { (int)v.X, (int)v.Y, (int)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(int[] v)\n            => new V3l((long)v[0], (long)v[1], (long)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V3l v)\n            => new uint[] { (uint)v.X, (uint)v.Y, (uint)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(uint[] v)\n            => new V3l((long)v[0], (long)v[1], (long)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V3l v)\n            => new long[] { v.X, v.Y, v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(long[] v)\n            => new V3l(v[0], v[1], v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V3l v)\n            => new float[] { (float)v.X, (float)v.Y, (float)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(float[] v)\n            => new V3l((long)v[0], (long)v[1], (long)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V3l v)\n            => new double[] { (double)v.X, (double)v.Y, (double)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(double[] v)\n            => new V3l((long)v[0], (long)v[1], (long)v[2]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(C3b v)\n            => new V3l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(C3us v)\n            => new V3l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(C3ui v)\n            => new V3l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(C4b v)\n            => new V3l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(C4us v)\n            => new V3l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V3l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3l(C4ui v)\n            => new V3l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3l\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<long, int> element_fun)\n            => new V3i(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<long, int, int> element_index_fun)\n            => new V3i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n            array[start + 2] = (int)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<long, uint> element_fun)\n            => new V3ui(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<long, int, uint> element_index_fun)\n            => new V3ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n            array[start + 2] = (uint)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<long, long> element_fun)\n            => new V3l(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<long, int, long> element_index_fun)\n            => new V3l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<long, float> element_fun)\n            => new V3f(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<long, int, float> element_index_fun)\n            => new V3f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n            array[start + 2] = (float)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<long, double> element_fun)\n            => new V3d(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<long, int, double> element_index_fun)\n            => new V3d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n            array[start + 2] = (double)Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<long, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<long, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly long[] ToArray()\n            => new long[] { X, Y, Z };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe long this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? (X >= Z ? 0 : 2) : (Y >= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? (X <= Z ? 0 : 2) : (Y <= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly long MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly long MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 3;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V3l Zero\n        {\n            get { return new V3l(0, 0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V3l One\n        {\n            get { return new V3l(1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V3l MaxValue\n        {\n            get { return new V3l(Constant<long>.ParseableMaxValue, Constant<long>.ParseableMaxValue, Constant<long>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V3l MinValue\n        {\n            get { return new V3l(Constant<long>.ParseableMinValue, Constant<long>.ParseableMinValue, Constant<long>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V3l XAxis\n        {\n            get { return new V3l(1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V3l YAxis\n        {\n            get { return new V3l(0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V3l ZAxis\n        {\n            get { return new V3l(0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V3l, long>[] SelectorArray =\n            new Func<V3l, long>[] { v => v.X, v => v.Y, v => v.Z };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V3l, int, long> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V3l, int, long> Setter =\n            (ref V3l v, int i, long s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V3l, long, long> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V3l, long, long> LongSetter =\n            (ref V3l v, long i, long s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromV3i(V3i v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromV3ui(V3ui v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromV3f(V3f v)\n            => new V3l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromV3d(V3d v)\n            => new V3l(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromC3b(C3b c) => new V3l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromC3us(C3us c) => new V3l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromC3ui(C3ui c) => new V3l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromC4b(C4b c) => new V3l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromC4us(C4us c) => new V3l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FromC4ui(C4ui c) => new V3l(c);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly long LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly long Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y) + Fun.Abs(Z); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly long NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly long NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V3d.Zero;\n                s = 1 / s;\n                return new V3d(X * s, Y * s, Z * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Abs(V3l v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l LinearInterp(float t, V3l a, V3l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l LinearInterp(V3f t, V3l a, V3l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l LinearInterp(double t, V3l a, V3l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l LinearInterp(V3d t, V3l a, V3l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Min(V3l v0, V3l v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Min(V3l v, long x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Max(V3l v0, V3l v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Max(V3l v, long x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Saturate(V3l v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l DivideByInt(V3l v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator -(V3l v)\n            => new V3l(-v.X, -v.Y, -v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator ~(V3l v)\n            => new V3l(~v.X, ~v.Y, ~v.Z);\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator +(V3l a, V3l b)\n            => new V3l(a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator +(V3l v, long s)\n            => new V3l(v.X + s, v.Y + s, v.Z + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator +(long s, V3l v)\n            => new V3l(s + v.X, s + v.Y, s + v.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator -(V3l a, V3l b)\n            => new V3l(a.X - b.X, a.Y - b.Y, a.Z - b.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator -(V3l v, long s)\n            => new V3l(v.X - s, v.Y - s, v.Z - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator -(long s, V3l v)\n            => new V3l(s - v.X, s - v.Y, s - v.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator *(V3l a, V3l b)\n            => new V3l(a.X * b.X, a.Y * b.Y, a.Z * b.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator *(V3l v, long s)\n            => new V3l(v.X * s, v.Y * s, v.Z * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator *(long s, V3l v)\n            => new V3l(s * v.X, s * v.Y, s * v.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator /(V3l a, V3l b)\n            => new V3l(a.X / b.X, a.Y / b.Y, a.Z / b.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator /(V3l v, long s)\n            => new V3l(v.X / s, v.Y / s, v.Z / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator /(long s, V3l v)\n            => new V3l(s / v.X, s / v.Y, s / v.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator %(V3l a, V3l b)\n            => new V3l(a.X % b.X, a.Y % b.Y, a.Z % b.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator %(V3l v, long s)\n            => new V3l(v.X % s, v.Y % s, v.Z % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator %(long s, V3l v)\n            => new V3l(s % v.X, s % v.Y, s % v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator &(V3l a, V3l b)\n            => new V3l(a.X & b.X, a.Y & b.Y, a.Z & b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator &(V3l v, long s)\n            => new V3l(v.X & s, v.Y & s, v.Z & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator &(long s, V3l v)\n            => new V3l(s & v.X, s & v.Y, s & v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator |(V3l a, V3l b)\n            => new V3l(a.X | b.X, a.Y | b.Y, a.Z | b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator |(V3l v, long s)\n            => new V3l(v.X | s, v.Y | s, v.Z | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator |(long s, V3l v)\n            => new V3l(s | v.X, s | v.Y, s | v.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator ^(V3l a, V3l b)\n            => new V3l(a.X ^ b.X, a.Y ^ b.Y, a.Z ^ b.Z);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator ^(V3l v, long s)\n            => new V3l(v.X ^ s, v.Y ^ s, v.Z ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator ^(long s, V3l v)\n            => new V3l(s ^ v.X, s ^ v.Y, s ^ v.Z);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator <<(V3l v, int s)\n            => new V3l(v.X << s, v.Y << s, v.Z << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l operator >>(V3l v, int s)\n            => new V3l(v.X >> s, v.Y >> s, v.Z >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3l a, V3l b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3l v, long s)\n        {\n            return v.X == s && v.Y == s && v.Z == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(long s, V3l v)\n        {\n            return s == v.X && s == v.Y && s == v.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3l a, V3l b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3l v, long s)\n        {\n            return v.X != s || v.Y != s || v.Z != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(long s, V3l v)\n        {\n            return s != v.X || s != v.Y || s != v.Z;\n        }\n\n        #endregion\n\n        #region IEquatable<V3l> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V3l other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V3l o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V3l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V3l(\n                long.Parse(x[0], CultureInfo.InvariantCulture), \n                long.Parse(x[1], CultureInfo.InvariantCulture), \n                long.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V3l Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<long>.Parse, V3l.Setter);\n        }\n\n        public static V3l Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<long>.Parse, V3l.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OX => new V2l(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OY => new V2l(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OZ => new V2l(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IX => new V2l(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IY => new V2l(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IZ => new V2l(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NX => new V2l(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NY => new V2l(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NZ => new V2l(-1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XO => new V2l(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XI => new V2l(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XN => new V2l(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XX => new V2l(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l XY\n        {\n            readonly get => new V2l(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l XZ\n        {\n            readonly get => new V2l(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YO => new V2l(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YI => new V2l(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YN => new V2l(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l YX\n        {\n            readonly get => new V2l(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YY => new V2l(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l YZ\n        {\n            readonly get => new V2l(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l ZO => new V2l(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l ZI => new V2l(Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l ZN => new V2l(Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l ZX\n        {\n            readonly get => new V2l(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l ZY\n        {\n            readonly get => new V2l(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l ZZ => new V2l(Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l OOO => new V3l(0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l OOI => new V3l(0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l OON => new V3l(0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOX => new V3l(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOY => new V3l(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOZ => new V3l(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l OIO => new V3l(0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l OII => new V3l(0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l OPN => new V3l(0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIX => new V3l(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIY => new V3l(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIZ => new V3l(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l ONO => new V3l(0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l ONP => new V3l(0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l ONN => new V3l(0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONX => new V3l(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONY => new V3l(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONZ => new V3l(0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXO => new V3l(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXI => new V3l(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXN => new V3l(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXX => new V3l(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXY => new V3l(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXZ => new V3l(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYO => new V3l(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYI => new V3l(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYN => new V3l(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYX => new V3l(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYY => new V3l(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYZ => new V3l(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZO => new V3l(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZI => new V3l(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZN => new V3l(0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZX => new V3l(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZY => new V3l(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZZ => new V3l(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l IOO => new V3l(1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l IOI => new V3l(1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l PON => new V3l(1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOX => new V3l(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOY => new V3l(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOZ => new V3l(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l IIO => new V3l(1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l III => new V3l(1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l PPN => new V3l(1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIX => new V3l(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIY => new V3l(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIZ => new V3l(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l PNO => new V3l(1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l PNP => new V3l(1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l PNN => new V3l(1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNX => new V3l(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNY => new V3l(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNZ => new V3l(1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXO => new V3l(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXI => new V3l(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PXN => new V3l(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXX => new V3l(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXY => new V3l(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXZ => new V3l(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYO => new V3l(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYI => new V3l(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PYN => new V3l(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYX => new V3l(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYY => new V3l(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYZ => new V3l(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZO => new V3l(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZI => new V3l(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PZN => new V3l(1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZX => new V3l(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZY => new V3l(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZZ => new V3l(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NOO => new V3l(-1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NOP => new V3l(-1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NON => new V3l(-1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOX => new V3l(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOY => new V3l(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOZ => new V3l(-1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NPO => new V3l(-1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NPP => new V3l(-1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NPN => new V3l(-1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPX => new V3l(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPY => new V3l(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPZ => new V3l(-1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NNO => new V3l(-1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NNP => new V3l(-1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3l NNN => new V3l(-1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNX => new V3l(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNY => new V3l(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNZ => new V3l(-1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXO => new V3l(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXP => new V3l(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXN => new V3l(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXX => new V3l(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXY => new V3l(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXZ => new V3l(-1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYO => new V3l(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYP => new V3l(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYN => new V3l(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYX => new V3l(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYY => new V3l(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYZ => new V3l(-1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZO => new V3l(-1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZP => new V3l(-1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZN => new V3l(-1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZX => new V3l(-1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZY => new V3l(-1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZZ => new V3l(-1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOO => new V3l(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOI => new V3l(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XON => new V3l(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOX => new V3l(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOY => new V3l(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOZ => new V3l(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIO => new V3l(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XII => new V3l(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XPN => new V3l(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIX => new V3l(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIY => new V3l(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIZ => new V3l(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNO => new V3l(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNP => new V3l(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNN => new V3l(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNX => new V3l(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNY => new V3l(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNZ => new V3l(X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXO => new V3l(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXI => new V3l(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXN => new V3l(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXX => new V3l(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXY => new V3l(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXZ => new V3l(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYO => new V3l(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYI => new V3l(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYN => new V3l(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYX => new V3l(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYY => new V3l(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l XYZ\n        {\n            readonly get => new V3l(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZO => new V3l(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZI => new V3l(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZN => new V3l(X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZX => new V3l(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l XZY\n        {\n            readonly get => new V3l(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZZ => new V3l(X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOO => new V3l(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOI => new V3l(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YON => new V3l(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOX => new V3l(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOY => new V3l(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOZ => new V3l(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIO => new V3l(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YII => new V3l(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YPN => new V3l(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIX => new V3l(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIY => new V3l(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIZ => new V3l(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNO => new V3l(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNP => new V3l(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNN => new V3l(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNX => new V3l(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNY => new V3l(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNZ => new V3l(Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXO => new V3l(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXI => new V3l(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXN => new V3l(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXX => new V3l(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXY => new V3l(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l YXZ\n        {\n            readonly get => new V3l(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYO => new V3l(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYI => new V3l(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYN => new V3l(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYX => new V3l(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYY => new V3l(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYZ => new V3l(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZO => new V3l(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZI => new V3l(Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZN => new V3l(Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l YZX\n        {\n            readonly get => new V3l(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZY => new V3l(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZZ => new V3l(Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOO => new V3l(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOI => new V3l(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZON => new V3l(Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOX => new V3l(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOY => new V3l(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOZ => new V3l(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIO => new V3l(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZII => new V3l(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZPN => new V3l(Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIX => new V3l(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIY => new V3l(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIZ => new V3l(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNO => new V3l(Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNP => new V3l(Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNN => new V3l(Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNX => new V3l(Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNY => new V3l(Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNZ => new V3l(Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXO => new V3l(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXI => new V3l(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXN => new V3l(Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXX => new V3l(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l ZXY\n        {\n            readonly get => new V3l(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXZ => new V3l(Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYO => new V3l(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYI => new V3l(Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYN => new V3l(Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l ZYX\n        {\n            readonly get => new V3l(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYY => new V3l(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYZ => new V3l(Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZO => new V3l(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZI => new V3l(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZN => new V3l(Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZX => new V3l(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZY => new V3l(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZZ => new V3l(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOX => new V4l(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOY => new V4l(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOZ => new V4l(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIX => new V4l(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIY => new V4l(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIZ => new V4l(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONX => new V4l(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONY => new V4l(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONZ => new V4l(0, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXO => new V4l(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXI => new V4l(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXN => new V4l(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXX => new V4l(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXY => new V4l(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXZ => new V4l(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYO => new V4l(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYI => new V4l(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYN => new V4l(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYX => new V4l(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYY => new V4l(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYZ => new V4l(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZO => new V4l(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZI => new V4l(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZN => new V4l(0, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZX => new V4l(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZY => new V4l(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZZ => new V4l(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOX => new V4l(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOY => new V4l(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOZ => new V4l(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIX => new V4l(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIY => new V4l(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIZ => new V4l(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNX => new V4l(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNY => new V4l(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNZ => new V4l(0, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXO => new V4l(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXI => new V4l(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPXN => new V4l(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXX => new V4l(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXY => new V4l(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXZ => new V4l(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYO => new V4l(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYI => new V4l(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPYN => new V4l(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYX => new V4l(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYY => new V4l(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYZ => new V4l(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZO => new V4l(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZI => new V4l(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPZN => new V4l(0, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZX => new V4l(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZY => new V4l(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZZ => new V4l(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOX => new V4l(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOY => new V4l(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOZ => new V4l(0, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPX => new V4l(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPY => new V4l(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPZ => new V4l(0, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNX => new V4l(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNY => new V4l(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNZ => new V4l(0, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXO => new V4l(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXP => new V4l(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXN => new V4l(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXX => new V4l(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXY => new V4l(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXZ => new V4l(0, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYO => new V4l(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYP => new V4l(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYN => new V4l(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYX => new V4l(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYY => new V4l(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYZ => new V4l(0, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZO => new V4l(0, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZP => new V4l(0, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZN => new V4l(0, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZX => new V4l(0, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZY => new V4l(0, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZZ => new V4l(0, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOO => new V4l(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOI => new V4l(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXON => new V4l(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOX => new V4l(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOY => new V4l(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOZ => new V4l(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIO => new V4l(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXII => new V4l(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXPN => new V4l(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIX => new V4l(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIY => new V4l(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIZ => new V4l(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNO => new V4l(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNP => new V4l(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNN => new V4l(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNX => new V4l(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNY => new V4l(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNZ => new V4l(0, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXO => new V4l(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXI => new V4l(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXN => new V4l(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXX => new V4l(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXY => new V4l(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXZ => new V4l(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYO => new V4l(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYI => new V4l(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYN => new V4l(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYX => new V4l(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYY => new V4l(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYZ => new V4l(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZO => new V4l(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZI => new V4l(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZN => new V4l(0, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZX => new V4l(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZY => new V4l(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZZ => new V4l(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOO => new V4l(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOI => new V4l(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYON => new V4l(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOX => new V4l(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOY => new V4l(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOZ => new V4l(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIO => new V4l(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYII => new V4l(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYPN => new V4l(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIX => new V4l(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIY => new V4l(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIZ => new V4l(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNO => new V4l(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNP => new V4l(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNN => new V4l(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNX => new V4l(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNY => new V4l(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNZ => new V4l(0, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXO => new V4l(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXI => new V4l(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXN => new V4l(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXX => new V4l(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXY => new V4l(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXZ => new V4l(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYO => new V4l(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYI => new V4l(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYN => new V4l(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYX => new V4l(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYY => new V4l(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYZ => new V4l(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZO => new V4l(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZI => new V4l(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZN => new V4l(0, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZX => new V4l(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZY => new V4l(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZZ => new V4l(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOO => new V4l(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOI => new V4l(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZON => new V4l(0, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOX => new V4l(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOY => new V4l(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOZ => new V4l(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIO => new V4l(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZII => new V4l(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZPN => new V4l(0, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIX => new V4l(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIY => new V4l(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIZ => new V4l(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNO => new V4l(0, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNP => new V4l(0, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNN => new V4l(0, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNX => new V4l(0, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNY => new V4l(0, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNZ => new V4l(0, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXO => new V4l(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXI => new V4l(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXN => new V4l(0, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXX => new V4l(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXY => new V4l(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXZ => new V4l(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYO => new V4l(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYI => new V4l(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYN => new V4l(0, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYX => new V4l(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYY => new V4l(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYZ => new V4l(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZO => new V4l(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZI => new V4l(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZN => new V4l(0, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZX => new V4l(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZY => new V4l(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZZ => new V4l(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOX => new V4l(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOY => new V4l(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOZ => new V4l(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIX => new V4l(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIY => new V4l(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIZ => new V4l(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONX => new V4l(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONY => new V4l(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONZ => new V4l(1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXO => new V4l(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXI => new V4l(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POXN => new V4l(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXX => new V4l(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXY => new V4l(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXZ => new V4l(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYO => new V4l(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYI => new V4l(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POYN => new V4l(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYX => new V4l(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYY => new V4l(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYZ => new V4l(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZO => new V4l(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZI => new V4l(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POZN => new V4l(1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZX => new V4l(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZY => new V4l(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZZ => new V4l(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOX => new V4l(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOY => new V4l(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOZ => new V4l(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIX => new V4l(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIY => new V4l(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIZ => new V4l(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNX => new V4l(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNY => new V4l(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNZ => new V4l(1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXO => new V4l(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXI => new V4l(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPXN => new V4l(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXX => new V4l(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXY => new V4l(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXZ => new V4l(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYO => new V4l(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYI => new V4l(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPYN => new V4l(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYX => new V4l(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYY => new V4l(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYZ => new V4l(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZO => new V4l(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZI => new V4l(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPZN => new V4l(1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZX => new V4l(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZY => new V4l(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZZ => new V4l(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOX => new V4l(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOY => new V4l(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOZ => new V4l(1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPX => new V4l(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPY => new V4l(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPZ => new V4l(1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNX => new V4l(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNY => new V4l(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNZ => new V4l(1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXO => new V4l(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXP => new V4l(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXN => new V4l(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXX => new V4l(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXY => new V4l(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXZ => new V4l(1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYO => new V4l(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYP => new V4l(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYN => new V4l(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYX => new V4l(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYY => new V4l(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYZ => new V4l(1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZO => new V4l(1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZP => new V4l(1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZN => new V4l(1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZX => new V4l(1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZY => new V4l(1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZZ => new V4l(1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOO => new V4l(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOI => new V4l(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXON => new V4l(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOX => new V4l(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOY => new V4l(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOZ => new V4l(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIO => new V4l(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXII => new V4l(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXPN => new V4l(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIX => new V4l(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIY => new V4l(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIZ => new V4l(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNO => new V4l(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNP => new V4l(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNN => new V4l(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNX => new V4l(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNY => new V4l(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNZ => new V4l(1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXO => new V4l(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXI => new V4l(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXXN => new V4l(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXX => new V4l(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXY => new V4l(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXZ => new V4l(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYO => new V4l(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYI => new V4l(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXYN => new V4l(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYX => new V4l(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYY => new V4l(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYZ => new V4l(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZO => new V4l(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZI => new V4l(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXZN => new V4l(1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZX => new V4l(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZY => new V4l(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZZ => new V4l(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOO => new V4l(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOI => new V4l(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYON => new V4l(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOX => new V4l(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOY => new V4l(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOZ => new V4l(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIO => new V4l(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYII => new V4l(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYPN => new V4l(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIX => new V4l(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIY => new V4l(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIZ => new V4l(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNO => new V4l(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNP => new V4l(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNN => new V4l(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNX => new V4l(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNY => new V4l(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNZ => new V4l(1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXO => new V4l(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXI => new V4l(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYXN => new V4l(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXX => new V4l(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXY => new V4l(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXZ => new V4l(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYO => new V4l(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYI => new V4l(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYYN => new V4l(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYX => new V4l(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYY => new V4l(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYZ => new V4l(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZO => new V4l(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZI => new V4l(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYZN => new V4l(1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZX => new V4l(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZY => new V4l(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZZ => new V4l(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOO => new V4l(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOI => new V4l(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZON => new V4l(1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOX => new V4l(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOY => new V4l(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOZ => new V4l(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIO => new V4l(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZII => new V4l(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZPN => new V4l(1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIX => new V4l(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIY => new V4l(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIZ => new V4l(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNO => new V4l(1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNP => new V4l(1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNN => new V4l(1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNX => new V4l(1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNY => new V4l(1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNZ => new V4l(1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXO => new V4l(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXI => new V4l(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZXN => new V4l(1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXX => new V4l(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXY => new V4l(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXZ => new V4l(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYO => new V4l(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYI => new V4l(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZYN => new V4l(1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYX => new V4l(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYY => new V4l(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYZ => new V4l(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZO => new V4l(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZI => new V4l(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZZN => new V4l(1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZX => new V4l(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZY => new V4l(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZZ => new V4l(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOX => new V4l(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOY => new V4l(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOZ => new V4l(-1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPX => new V4l(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPY => new V4l(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPZ => new V4l(-1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONX => new V4l(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONY => new V4l(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONZ => new V4l(-1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXO => new V4l(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXP => new V4l(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXN => new V4l(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXX => new V4l(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXY => new V4l(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXZ => new V4l(-1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYO => new V4l(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYP => new V4l(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYN => new V4l(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYX => new V4l(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYY => new V4l(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYZ => new V4l(-1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZO => new V4l(-1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZP => new V4l(-1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZN => new V4l(-1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZX => new V4l(-1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZY => new V4l(-1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZZ => new V4l(-1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOX => new V4l(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOY => new V4l(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOZ => new V4l(-1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPX => new V4l(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPY => new V4l(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPZ => new V4l(-1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNX => new V4l(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNY => new V4l(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNZ => new V4l(-1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXO => new V4l(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXP => new V4l(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXN => new V4l(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXX => new V4l(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXY => new V4l(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXZ => new V4l(-1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYO => new V4l(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYP => new V4l(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYN => new V4l(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYX => new V4l(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYY => new V4l(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYZ => new V4l(-1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZO => new V4l(-1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZP => new V4l(-1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZN => new V4l(-1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZX => new V4l(-1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZY => new V4l(-1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZZ => new V4l(-1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOX => new V4l(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOY => new V4l(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOZ => new V4l(-1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPX => new V4l(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPY => new V4l(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPZ => new V4l(-1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNX => new V4l(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNY => new V4l(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNZ => new V4l(-1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXO => new V4l(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXP => new V4l(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXN => new V4l(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXX => new V4l(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXY => new V4l(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXZ => new V4l(-1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYO => new V4l(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYP => new V4l(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYN => new V4l(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYX => new V4l(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYY => new V4l(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYZ => new V4l(-1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZO => new V4l(-1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZP => new V4l(-1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZN => new V4l(-1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZX => new V4l(-1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZY => new V4l(-1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZZ => new V4l(-1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOO => new V4l(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOP => new V4l(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXON => new V4l(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOX => new V4l(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOY => new V4l(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOZ => new V4l(-1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPO => new V4l(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPP => new V4l(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPN => new V4l(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPX => new V4l(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPY => new V4l(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPZ => new V4l(-1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNO => new V4l(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNP => new V4l(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNN => new V4l(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNX => new V4l(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNY => new V4l(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNZ => new V4l(-1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXO => new V4l(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXP => new V4l(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXN => new V4l(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXX => new V4l(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXY => new V4l(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXZ => new V4l(-1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYO => new V4l(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYP => new V4l(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYN => new V4l(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYX => new V4l(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYY => new V4l(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYZ => new V4l(-1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZO => new V4l(-1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZP => new V4l(-1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZN => new V4l(-1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZX => new V4l(-1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZY => new V4l(-1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZZ => new V4l(-1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOO => new V4l(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOP => new V4l(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYON => new V4l(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOX => new V4l(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOY => new V4l(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOZ => new V4l(-1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPO => new V4l(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPP => new V4l(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPN => new V4l(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPX => new V4l(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPY => new V4l(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPZ => new V4l(-1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNO => new V4l(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNP => new V4l(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNN => new V4l(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNX => new V4l(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNY => new V4l(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNZ => new V4l(-1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXO => new V4l(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXP => new V4l(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXN => new V4l(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXX => new V4l(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXY => new V4l(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXZ => new V4l(-1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYO => new V4l(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYP => new V4l(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYN => new V4l(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYX => new V4l(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYY => new V4l(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYZ => new V4l(-1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZO => new V4l(-1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZP => new V4l(-1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZN => new V4l(-1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZX => new V4l(-1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZY => new V4l(-1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZZ => new V4l(-1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOO => new V4l(-1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOP => new V4l(-1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZON => new V4l(-1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOX => new V4l(-1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOY => new V4l(-1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOZ => new V4l(-1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPO => new V4l(-1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPP => new V4l(-1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPN => new V4l(-1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPX => new V4l(-1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPY => new V4l(-1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPZ => new V4l(-1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNO => new V4l(-1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNP => new V4l(-1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNN => new V4l(-1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNX => new V4l(-1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNY => new V4l(-1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNZ => new V4l(-1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXO => new V4l(-1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXP => new V4l(-1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXN => new V4l(-1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXX => new V4l(-1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXY => new V4l(-1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXZ => new V4l(-1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYO => new V4l(-1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYP => new V4l(-1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYN => new V4l(-1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYX => new V4l(-1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYY => new V4l(-1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYZ => new V4l(-1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZO => new V4l(-1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZP => new V4l(-1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZN => new V4l(-1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZX => new V4l(-1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZY => new V4l(-1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZZ => new V4l(-1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOO => new V4l(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOI => new V4l(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOON => new V4l(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOX => new V4l(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOY => new V4l(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOZ => new V4l(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIO => new V4l(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOII => new V4l(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOPN => new V4l(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIX => new V4l(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIY => new V4l(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIZ => new V4l(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONO => new V4l(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONP => new V4l(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONN => new V4l(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONX => new V4l(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONY => new V4l(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONZ => new V4l(X, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXO => new V4l(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXI => new V4l(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXN => new V4l(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXX => new V4l(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXY => new V4l(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXZ => new V4l(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYO => new V4l(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYI => new V4l(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYN => new V4l(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYX => new V4l(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYY => new V4l(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYZ => new V4l(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZO => new V4l(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZI => new V4l(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZN => new V4l(X, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZX => new V4l(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZY => new V4l(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZZ => new V4l(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOO => new V4l(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOI => new V4l(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPON => new V4l(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOX => new V4l(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOY => new V4l(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOZ => new V4l(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIO => new V4l(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIII => new V4l(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPPN => new V4l(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIX => new V4l(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIY => new V4l(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIZ => new V4l(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNO => new V4l(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNP => new V4l(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNN => new V4l(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNX => new V4l(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNY => new V4l(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNZ => new V4l(X, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXO => new V4l(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXI => new V4l(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPXN => new V4l(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXX => new V4l(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXY => new V4l(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXZ => new V4l(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYO => new V4l(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYI => new V4l(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPYN => new V4l(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYX => new V4l(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYY => new V4l(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYZ => new V4l(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZO => new V4l(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZI => new V4l(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPZN => new V4l(X, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZX => new V4l(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZY => new V4l(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZZ => new V4l(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOO => new V4l(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOP => new V4l(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNON => new V4l(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOX => new V4l(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOY => new V4l(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOZ => new V4l(X, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPO => new V4l(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPP => new V4l(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPN => new V4l(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPX => new V4l(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPY => new V4l(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPZ => new V4l(X, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNO => new V4l(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNP => new V4l(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNN => new V4l(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNX => new V4l(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNY => new V4l(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNZ => new V4l(X, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXO => new V4l(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXP => new V4l(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXN => new V4l(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXX => new V4l(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXY => new V4l(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXZ => new V4l(X, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYO => new V4l(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYP => new V4l(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYN => new V4l(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYX => new V4l(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYY => new V4l(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYZ => new V4l(X, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZO => new V4l(X, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZP => new V4l(X, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZN => new V4l(X, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZX => new V4l(X, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZY => new V4l(X, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZZ => new V4l(X, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOO => new V4l(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOI => new V4l(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXON => new V4l(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOX => new V4l(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOY => new V4l(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOZ => new V4l(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIO => new V4l(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXII => new V4l(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXPN => new V4l(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIX => new V4l(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIY => new V4l(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIZ => new V4l(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNO => new V4l(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNP => new V4l(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNN => new V4l(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNX => new V4l(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNY => new V4l(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNZ => new V4l(X, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXO => new V4l(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXI => new V4l(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXN => new V4l(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXX => new V4l(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXY => new V4l(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXZ => new V4l(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYO => new V4l(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYI => new V4l(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYN => new V4l(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYX => new V4l(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYY => new V4l(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYZ => new V4l(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZO => new V4l(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZI => new V4l(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZN => new V4l(X, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZX => new V4l(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZY => new V4l(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZZ => new V4l(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOO => new V4l(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOI => new V4l(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYON => new V4l(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOX => new V4l(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOY => new V4l(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOZ => new V4l(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIO => new V4l(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYII => new V4l(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYPN => new V4l(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIX => new V4l(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIY => new V4l(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIZ => new V4l(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNO => new V4l(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNP => new V4l(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNN => new V4l(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNX => new V4l(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNY => new V4l(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNZ => new V4l(X, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXO => new V4l(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXI => new V4l(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXN => new V4l(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXX => new V4l(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXY => new V4l(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXZ => new V4l(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYO => new V4l(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYI => new V4l(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYN => new V4l(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYX => new V4l(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYY => new V4l(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYZ => new V4l(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZO => new V4l(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZI => new V4l(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZN => new V4l(X, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZX => new V4l(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZY => new V4l(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZZ => new V4l(X, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOO => new V4l(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOI => new V4l(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZON => new V4l(X, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOX => new V4l(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOY => new V4l(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOZ => new V4l(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIO => new V4l(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZII => new V4l(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZPN => new V4l(X, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIX => new V4l(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIY => new V4l(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIZ => new V4l(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNO => new V4l(X, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNP => new V4l(X, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNN => new V4l(X, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNX => new V4l(X, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNY => new V4l(X, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNZ => new V4l(X, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXO => new V4l(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXI => new V4l(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXN => new V4l(X, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXX => new V4l(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXY => new V4l(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXZ => new V4l(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYO => new V4l(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYI => new V4l(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYN => new V4l(X, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYX => new V4l(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYY => new V4l(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYZ => new V4l(X, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZO => new V4l(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZI => new V4l(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZN => new V4l(X, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZX => new V4l(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZY => new V4l(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZZ => new V4l(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOO => new V4l(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOI => new V4l(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOON => new V4l(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOX => new V4l(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOY => new V4l(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOZ => new V4l(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIO => new V4l(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOII => new V4l(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOPN => new V4l(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIX => new V4l(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIY => new V4l(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIZ => new V4l(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONO => new V4l(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONP => new V4l(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONN => new V4l(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONX => new V4l(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONY => new V4l(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONZ => new V4l(Y, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXO => new V4l(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXI => new V4l(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXN => new V4l(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXX => new V4l(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXY => new V4l(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXZ => new V4l(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYO => new V4l(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYI => new V4l(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYN => new V4l(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYX => new V4l(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYY => new V4l(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYZ => new V4l(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZO => new V4l(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZI => new V4l(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZN => new V4l(Y, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZX => new V4l(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZY => new V4l(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZZ => new V4l(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOO => new V4l(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOI => new V4l(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPON => new V4l(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOX => new V4l(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOY => new V4l(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOZ => new V4l(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIO => new V4l(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIII => new V4l(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPPN => new V4l(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIX => new V4l(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIY => new V4l(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIZ => new V4l(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNO => new V4l(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNP => new V4l(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNN => new V4l(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNX => new V4l(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNY => new V4l(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNZ => new V4l(Y, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXO => new V4l(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXI => new V4l(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPXN => new V4l(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXX => new V4l(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXY => new V4l(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXZ => new V4l(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYO => new V4l(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYI => new V4l(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPYN => new V4l(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYX => new V4l(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYY => new V4l(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYZ => new V4l(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZO => new V4l(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZI => new V4l(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPZN => new V4l(Y, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZX => new V4l(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZY => new V4l(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZZ => new V4l(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOO => new V4l(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOP => new V4l(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNON => new V4l(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOX => new V4l(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOY => new V4l(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOZ => new V4l(Y, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPO => new V4l(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPP => new V4l(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPN => new V4l(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPX => new V4l(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPY => new V4l(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPZ => new V4l(Y, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNO => new V4l(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNP => new V4l(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNN => new V4l(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNX => new V4l(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNY => new V4l(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNZ => new V4l(Y, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXO => new V4l(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXP => new V4l(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXN => new V4l(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXX => new V4l(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXY => new V4l(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXZ => new V4l(Y, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYO => new V4l(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYP => new V4l(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYN => new V4l(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYX => new V4l(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYY => new V4l(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYZ => new V4l(Y, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZO => new V4l(Y, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZP => new V4l(Y, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZN => new V4l(Y, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZX => new V4l(Y, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZY => new V4l(Y, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZZ => new V4l(Y, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOO => new V4l(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOI => new V4l(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXON => new V4l(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOX => new V4l(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOY => new V4l(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOZ => new V4l(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIO => new V4l(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXII => new V4l(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXPN => new V4l(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIX => new V4l(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIY => new V4l(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIZ => new V4l(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNO => new V4l(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNP => new V4l(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNN => new V4l(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNX => new V4l(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNY => new V4l(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNZ => new V4l(Y, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXO => new V4l(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXI => new V4l(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXN => new V4l(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXX => new V4l(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXY => new V4l(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXZ => new V4l(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYO => new V4l(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYI => new V4l(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYN => new V4l(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYX => new V4l(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYY => new V4l(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYZ => new V4l(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZO => new V4l(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZI => new V4l(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZN => new V4l(Y, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZX => new V4l(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZY => new V4l(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZZ => new V4l(Y, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOO => new V4l(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOI => new V4l(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYON => new V4l(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOX => new V4l(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOY => new V4l(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOZ => new V4l(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIO => new V4l(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYII => new V4l(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYPN => new V4l(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIX => new V4l(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIY => new V4l(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIZ => new V4l(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNO => new V4l(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNP => new V4l(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNN => new V4l(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNX => new V4l(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNY => new V4l(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNZ => new V4l(Y, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXO => new V4l(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXI => new V4l(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXN => new V4l(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXX => new V4l(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXY => new V4l(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXZ => new V4l(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYO => new V4l(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYI => new V4l(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYN => new V4l(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYX => new V4l(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYY => new V4l(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYZ => new V4l(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZO => new V4l(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZI => new V4l(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZN => new V4l(Y, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZX => new V4l(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZY => new V4l(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZZ => new V4l(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOO => new V4l(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOI => new V4l(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZON => new V4l(Y, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOX => new V4l(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOY => new V4l(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOZ => new V4l(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIO => new V4l(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZII => new V4l(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZPN => new V4l(Y, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIX => new V4l(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIY => new V4l(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIZ => new V4l(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNO => new V4l(Y, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNP => new V4l(Y, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNN => new V4l(Y, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNX => new V4l(Y, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNY => new V4l(Y, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNZ => new V4l(Y, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXO => new V4l(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXI => new V4l(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXN => new V4l(Y, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXX => new V4l(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXY => new V4l(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXZ => new V4l(Y, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYO => new V4l(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYI => new V4l(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYN => new V4l(Y, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYX => new V4l(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYY => new V4l(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYZ => new V4l(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZO => new V4l(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZI => new V4l(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZN => new V4l(Y, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZX => new V4l(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZY => new V4l(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZZ => new V4l(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOO => new V4l(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOI => new V4l(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOON => new V4l(Z, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOX => new V4l(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOY => new V4l(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOZ => new V4l(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIO => new V4l(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOII => new V4l(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOPN => new V4l(Z, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIX => new V4l(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIY => new V4l(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIZ => new V4l(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONO => new V4l(Z, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONP => new V4l(Z, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONN => new V4l(Z, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONX => new V4l(Z, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONY => new V4l(Z, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONZ => new V4l(Z, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXO => new V4l(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXI => new V4l(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXN => new V4l(Z, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXX => new V4l(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXY => new V4l(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXZ => new V4l(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYO => new V4l(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYI => new V4l(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYN => new V4l(Z, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYX => new V4l(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYY => new V4l(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYZ => new V4l(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZO => new V4l(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZI => new V4l(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZN => new V4l(Z, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZX => new V4l(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZY => new V4l(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZZ => new V4l(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOO => new V4l(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOI => new V4l(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPON => new V4l(Z, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOX => new V4l(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOY => new V4l(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOZ => new V4l(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIO => new V4l(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIII => new V4l(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPPN => new V4l(Z, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIX => new V4l(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIY => new V4l(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIZ => new V4l(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNO => new V4l(Z, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNP => new V4l(Z, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNN => new V4l(Z, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNX => new V4l(Z, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNY => new V4l(Z, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNZ => new V4l(Z, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXO => new V4l(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXI => new V4l(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPXN => new V4l(Z, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXX => new V4l(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXY => new V4l(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXZ => new V4l(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYO => new V4l(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYI => new V4l(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPYN => new V4l(Z, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYX => new V4l(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYY => new V4l(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYZ => new V4l(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZO => new V4l(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZI => new V4l(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPZN => new V4l(Z, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZX => new V4l(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZY => new V4l(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZZ => new V4l(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOO => new V4l(Z, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOP => new V4l(Z, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNON => new V4l(Z, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOX => new V4l(Z, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOY => new V4l(Z, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOZ => new V4l(Z, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPO => new V4l(Z, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPP => new V4l(Z, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPN => new V4l(Z, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPX => new V4l(Z, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPY => new V4l(Z, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPZ => new V4l(Z, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNO => new V4l(Z, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNP => new V4l(Z, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNN => new V4l(Z, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNX => new V4l(Z, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNY => new V4l(Z, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNZ => new V4l(Z, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXO => new V4l(Z, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXP => new V4l(Z, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXN => new V4l(Z, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXX => new V4l(Z, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXY => new V4l(Z, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXZ => new V4l(Z, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYO => new V4l(Z, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYP => new V4l(Z, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYN => new V4l(Z, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYX => new V4l(Z, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYY => new V4l(Z, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYZ => new V4l(Z, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZO => new V4l(Z, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZP => new V4l(Z, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZN => new V4l(Z, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZX => new V4l(Z, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZY => new V4l(Z, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZZ => new V4l(Z, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOO => new V4l(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOI => new V4l(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXON => new V4l(Z, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOX => new V4l(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOY => new V4l(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOZ => new V4l(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIO => new V4l(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXII => new V4l(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXPN => new V4l(Z, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIX => new V4l(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIY => new V4l(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIZ => new V4l(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNO => new V4l(Z, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNP => new V4l(Z, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNN => new V4l(Z, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNX => new V4l(Z, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNY => new V4l(Z, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNZ => new V4l(Z, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXO => new V4l(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXI => new V4l(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXN => new V4l(Z, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXX => new V4l(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXY => new V4l(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXZ => new V4l(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYO => new V4l(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYI => new V4l(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYN => new V4l(Z, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYX => new V4l(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYY => new V4l(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYZ => new V4l(Z, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZO => new V4l(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZI => new V4l(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZN => new V4l(Z, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZX => new V4l(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZY => new V4l(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZZ => new V4l(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOO => new V4l(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOI => new V4l(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYON => new V4l(Z, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOX => new V4l(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOY => new V4l(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOZ => new V4l(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIO => new V4l(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYII => new V4l(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYPN => new V4l(Z, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIX => new V4l(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIY => new V4l(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIZ => new V4l(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNO => new V4l(Z, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNP => new V4l(Z, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNN => new V4l(Z, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNX => new V4l(Z, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNY => new V4l(Z, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNZ => new V4l(Z, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXO => new V4l(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXI => new V4l(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXN => new V4l(Z, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXX => new V4l(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXY => new V4l(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXZ => new V4l(Z, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYO => new V4l(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYI => new V4l(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYN => new V4l(Z, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYX => new V4l(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYY => new V4l(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYZ => new V4l(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZO => new V4l(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZI => new V4l(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZN => new V4l(Z, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZX => new V4l(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZY => new V4l(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZZ => new V4l(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOO => new V4l(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOI => new V4l(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZON => new V4l(Z, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOX => new V4l(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOY => new V4l(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOZ => new V4l(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIO => new V4l(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZII => new V4l(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZPN => new V4l(Z, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIX => new V4l(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIY => new V4l(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIZ => new V4l(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNO => new V4l(Z, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNP => new V4l(Z, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNN => new V4l(Z, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNX => new V4l(Z, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNY => new V4l(Z, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNZ => new V4l(Z, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXO => new V4l(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXI => new V4l(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXN => new V4l(Z, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXX => new V4l(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXY => new V4l(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXZ => new V4l(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYO => new V4l(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYI => new V4l(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYN => new V4l(Z, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYX => new V4l(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYY => new V4l(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYZ => new V4l(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZO => new V4l(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZI => new V4l(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZN => new V4l(Z, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZX => new V4l(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZY => new V4l(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZZ => new V4l(Z, Z, Z, Z);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (long)value; }\n        }\n\n        #endregion\n\n        #region ISize3l Members\n\n        public readonly V3l Size3l { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 3; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (long)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V3lEqualityComparer : IEqualityComparer<V3l>\n    {\n        public static V3lEqualityComparer Default\n            => new V3lEqualityComparer();\n\n        #region IEqualityComparer<V3l> Members\n\n        public bool Equals(V3l v0, V3l v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V3l v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Min(this V3l a, V3l b)\n        {\n            return new V3l(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Min(this V3l a, long b)\n        {\n            return new V3l(Min(a.X, b), Min(a.Y, b), Min(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Min(this long a, V3l b)\n        {\n            return new V3l(Min(a, b.X), Min(a, b.Y), Min(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Max(this V3l a, V3l b)\n        {\n            return new V3l(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Max(this V3l a, long b)\n        {\n            return new V3l(Max(a.X, b), Max(a.Y, b), Max(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Max(this long a, V3l b)\n        {\n            return new V3l(Max(a, b.X), Max(a, b.Y), Max(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Min(this V3l a, V3l b, V3l c)\n        {\n            return new V3l(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Max(this V3l a, V3l b, V3l c)\n        {\n            return new V3l(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Min(this V3l a, V3l b, V3l c, V3l d)\n        {\n            return new V3l(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Max(this V3l a, V3l b, V3l c, V3l d)\n        {\n            return new V3l(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Min(this V3l x, params V3l[] values)\n        {\n            return new V3l(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Max(this V3l x, params V3l[] values)\n        {\n            return new V3l(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Abs(this V3l x)\n        {\n            return new V3l(Abs(x.X), Abs(x.Y), Abs(x.Z));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Clamp(this V3l x, V3l a, V3l b)\n        {\n            return new V3l(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Clamp(this V3l x, long a, long b)\n        {\n            return new V3l(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l ClampExcl(this V3l x, V3l a, V3l b)\n        {\n            return new V3l(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y), ClampExcl(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l ClampExcl(this V3l x, long a, long b)\n        {\n            return new V3l(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b), ClampExcl(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l ClampWrap(this V3l x, V3l a, V3l b)\n        {\n            return new V3l(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l ClampWrap(this V3l x, long a, long b)\n        {\n            return new V3l(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Saturate(this V3l x)\n        {\n            return new V3l(Saturate(x.X), Saturate(x.Y), Saturate(x.Z));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Sign(this V3l x)\n        {\n            return new V3i(Sign(x.X), Sign(x.Y), Sign(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Signumi(this V3l x)\n        {\n            return new V3i(Signumi(x.X), Signumi(x.Y), Signumi(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Signum(this V3l x)\n        {\n            return new V3l(Signum(x.X), Signum(x.Y), Signum(x.Z));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l MultiplyAdd(V3l x, V3l y, V3l z)\n        {\n            return new V3l(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l MultiplyAdd(V3l x, long y, V3l z)\n        {\n            return new V3l(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l MultiplyAdd(long x, V3l y, V3l z)\n        {\n            return new V3l(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sqrt(this V3l x)\n        {\n            return new V3d(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cbrt(this V3l x)\n        {\n            return new V3d(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Square(this V3l x)\n        {\n            return new V3l(Square(x.X), Square(x.Y), Square(x.Z));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Pown(this V3l x, V3l y)\n        {\n            return new V3l(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Pown(this V3l x, long y)\n        {\n            return new V3l(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Pown(this long x, V3l y)\n        {\n            return new V3l(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Pown(this V3l x, V3i y)\n        {\n            return new V3l(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Pown(this V3l x, int y)\n        {\n            return new V3l(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Pown(this long x, V3i y)\n        {\n            return new V3l(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this V3l x, V3f y)\n        {\n            return new V3f(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this V3l x, float y)\n        {\n            return new V3f(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this long x, V3f y)\n        {\n            return new V3f(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this V3l x, V3d y)\n        {\n            return new V3d(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this V3l x, double y)\n        {\n            return new V3d(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this long x, V3d y)\n        {\n            return new V3d(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this V3l x, V3f y)\n        {\n            return new V3f(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this V3l x, float y)\n        {\n            return new V3f(Power(x.X, y), Power(x.Y, y), Power(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this long x, V3f y)\n        {\n            return new V3f(Power(x, y.X), Power(x, y.Y), Power(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this V3l x, V3d y)\n        {\n            return new V3d(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this V3l x, double y)\n        {\n            return new V3d(Power(x.X, y), Power(x.Y, y), Power(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this long x, V3d y)\n        {\n            return new V3d(Power(x, y.X), Power(x, y.Y), Power(x, y.Z));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Exp(this V3l x)\n        {\n            return new V3d(Exp(x.X), Exp(x.Y), Exp(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(this V3l x)\n        {\n            return new V3d(Log(x.X), Log(x.Y), Log(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log2(this V3l x)\n        {\n            return new V3d(Log2(x.X), Log2(x.Y), Log2(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Log2Int(this V3l x)\n        {\n            return new V3i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log10(this V3l x)\n        {\n            return new V3d(Log10(x.X), Log10(x.Y), Log10(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(this V3l x, double basis)\n        {\n            return new V3d(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l ModP(this V3l a, V3l b)\n        {\n            return new V3l(ModP(a.X, b.X), ModP(a.Y, b.Y), ModP(a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l PowerOfTwo(this V3l x)\n        {\n            return new V3l(PowerOfTwo(x.X), PowerOfTwo(x.Y), PowerOfTwo(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.NextPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l NextPowerOfTwo(this V3l x)\n        {\n            return new V3l(NextPowerOfTwo(x.X), NextPowerOfTwo(x.Y), NextPowerOfTwo(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.PrevPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l PrevPowerOfTwo(this V3l x)\n        {\n            return new V3l(PrevPowerOfTwo(x.X), PrevPowerOfTwo(x.Y), PrevPowerOfTwo(x.Z));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Step(this V3l x, V3l edge)\n        {\n            return new V3l(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Step(this V3l x, long edge)\n        {\n            return new V3l(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Lerp(this float t, V3l a, V3l b)\n        {\n            return new V3l(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Lerp(this V3f t, V3l a, V3l b)\n        {\n            return new V3l(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Lerp(this double t, V3l a, V3l b)\n        {\n            return new V3l(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Lerp(this V3d t, V3l a, V3l b)\n        {\n            return new V3l(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvLerp(this V3l y, V3l a, V3l b)\n        {\n            return new V3d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l GreatestCommonDivisor(this V3l a, V3l b)\n        {\n            return new V3l(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y), GreatestCommonDivisor(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l LeastCommonMultiple(this V3l a, V3l b)\n        {\n            return new V3l(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y), LeastCommonMultiple(a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FloatFromBits(this V3l x)\n        {\n            return new V3d(FloatFromBits(x.X), FloatFromBits(x.Y), FloatFromBits(x.Z));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V3l a, V3l b, long tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V3l v, long epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long LengthSquared(V3l v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V3l v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Normalized(V3l v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Norm1(V3l v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V3l v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMax(V3l v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMin(V3l v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V3l v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceSquared(this V3l a, V3l b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y) + Fun.Square(b.Z - a.Z);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V3l a, V3l b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Distance1(this V3l a, V3l b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y) + Fun.Abs(b.Z - a.Z);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V3l a, V3l b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p) + Fun.Abs(b.Z - a.Z).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceMax(this V3l a, V3l b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceMin(this V3l a, V3l b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V3l query, V3l p0, V3l p1)\n        {\n            return DistanceToLine((V3d) query, (V3d) p0, (V3d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V3l query, V3l p0, V3l p1)\n        {\n            return DistanceToInfiniteLine((V3d) query, (V3d) p0, (V3d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V3l query, V3l p0, V3l p1, out double t)\n        {\n            return DistanceToLine((V3d) query, (V3d) p0, (V3d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V3l query, V3l p0, V3l p1, out double t)\n        {\n            return DistanceToInfiniteLine((V3d) query, (V3d) p0, (V3d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V3l v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n            v.Z = -v.Z;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 3x3 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33l Outer(this V3l a, V3l b)\n        {\n            return new M33l(\n                        a.X * b.X, a.X * b.Y, a.X * b.Z, \n                        a.Y * b.X, a.Y * b.Y, a.Y * b.Z, \n                        a.Z * b.X, a.Z * b.Y, a.Z * b.Z);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Dot(this V3l a, V3l b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        /// <summary>\n        /// Returns the skew-symmetric \"cross\" matrix (A^T = -A) of the vector v.\n        /// </summary>\n        public static M33l CrossMatrix(this V3l v)\n        {\n            return new M33l(0, -v.Z, +v.Y,\n                            +v.Z, 0, -v.X,\n                            -v.Y, +v.X, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V3l v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > 0) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < 0) flags |= Aardbase.DirFlags.NegativeZ;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the cross product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l Cross(this V3l a, V3l b)\n        {\n            return new V3l(\n            a.Y * b.Z - a.Z * b.Y,\n            a.Z * b.X - a.X * b.Z,\n            a.X * b.Y - a.Y * b.X\n            );\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3l a, V3l b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3l v, long s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(long s, V3l v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3l a, V3l b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3l v, long s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(long s, V3l v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3l a, V3l b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3l v, long s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(long s, V3l v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3l a, V3l b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3l v, long s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(long s, V3l v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3l a, V3l b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3l v, long s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(long s, V3l v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3l a, V3l b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3l v, long s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(long s, V3l v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3l a, V3l b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3l v, long s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(long s, V3l v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3l a, V3l b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3l v, long s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(long s, V3l v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3l a, V3l b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3l v, long s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(long s, V3l v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3l a, V3l b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3l v, long s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(long s, V3l v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3l a, V3l b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3l v, long s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(long s, V3l v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3l a, V3l b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3l v, long s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(long s, V3l v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V3l v0, V3l v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V3l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MinElement(V3l v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V3l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MaxElement(V3l v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V3l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V3l v, long epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V3l v, long epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V3l[] pointArray, V3l point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V3l[] array, int start, int count,\n                V3l point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V3l> pointSelector, V3l point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V3l[] pointArray, V3l point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V3l[] array, long start, long count,\n                V3l point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V3l> pointSelector, V3l point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V3l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V3l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V3l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V3l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V3l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V3l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V3l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V3l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V3l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V3l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V3l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V3l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V3l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V3l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V3l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V3l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V3l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V3l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static long[] CopyCoord(this V3l[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV3lExtensions\n    {\n        #region IRandomUniform extensions for V3l\n\n        /// <summary>\n        /// Uses UniformLong() to generate the elements of a V3l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l UniformV3l(this IRandomUniform rnd)\n        {\n            return new V3l(rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong());\n        }\n\n        /// <summary>\n        /// Uses UniformLongNonZero() to generate the elements of a V3l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l UniformV3lNonZero(this IRandomUniform rnd)\n        {\n            return new V3l(rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of a V3l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l UniformV3l(this IRandomUniform rnd, long size)\n        {\n            return new V3l(rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size));\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of a V3l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l UniformV3l(this IRandomUniform rnd, V3l size)\n        {\n            return new V3l(rnd.UniformLong(size.X), rnd.UniformLong(size.Y), rnd.UniformLong(size.Z));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V3f\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V3f : IVector<double>, ISize3f, IFormattable, IEquatable<V3f>\n    {\n        [DataMember]\n        public float X;\n        [DataMember]\n        public float Y;\n        [DataMember]\n        public float Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(int x, int y, int z)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(int v)\n        {\n            X = (float)v;\n            Y = (float)v;\n            Z = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(int[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n            Z = (float)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(int[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n            Z = (float)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(int a, V2i b)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2i a, int b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(uint x, uint y, uint z)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(uint v)\n        {\n            X = (float)v;\n            Y = (float)v;\n            Z = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(uint[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n            Z = (float)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(uint[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n            Z = (float)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(uint a, V2ui b)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2ui a, uint b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(long x, long y, long z)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(long v)\n        {\n            X = (float)v;\n            Y = (float)v;\n            Z = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(long[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n            Z = (float)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(long[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n            Z = (float)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(long a, V2l b)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2l a, long b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(float x, float y, float z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(float v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(float[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(float[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(float a, V2f b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2f a, float b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(double x, double y, double z)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(double v)\n        {\n            X = (float)v;\n            Y = (float)v;\n            Z = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(double[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n            Z = (float)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(double[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n            Z = (float)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(double a, V2d b)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2d a, double b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(Func<int, float> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;float&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 3.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(IVector<double> v)\n            : this(v[0], v[1], v[2])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2f v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V2d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V3i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V3ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V3l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V3f v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V3d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V4i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V4ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V4l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V4f v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(V4d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C3b c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C3us c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C3ui c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C3f c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C3d c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C4b c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C4us c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C4ui c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C4f c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3f(C4d c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V2i v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V2ui v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V2l v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V2f v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V2d v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V3i v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V3ui v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V3l v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V3d v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V4i v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V4ui v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V4l v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V4f v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(V4d v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V3f v)\n            => new int[] { (int)v.X, (int)v.Y, (int)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(int[] v)\n            => new V3f((float)v[0], (float)v[1], (float)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V3f v)\n            => new uint[] { (uint)v.X, (uint)v.Y, (uint)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(uint[] v)\n            => new V3f((float)v[0], (float)v[1], (float)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V3f v)\n            => new long[] { (long)v.X, (long)v.Y, (long)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(long[] v)\n            => new V3f((float)v[0], (float)v[1], (float)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V3f v)\n            => new float[] { v.X, v.Y, v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(float[] v)\n            => new V3f(v[0], v[1], v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V3f v)\n            => new double[] { (double)v.X, (double)v.Y, (double)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(double[] v)\n            => new V3f((float)v[0], (float)v[1], (float)v[2]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C3b v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C3us v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C3ui v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C3f v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C3d v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C4b v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C4us v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V3f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C4ui v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C4f v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3f(C4d v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3f\"/> vector to a <see cref=\"C4d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToFloorV3i()\n            => new V3i((int)Fun.Floor(X), (int)Fun.Floor(Y), (int)Fun.Floor(Z));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToCeilingV3i()\n            => new V3i((int)Fun.Ceiling(X), (int)Fun.Ceiling(Y), (int)Fun.Ceiling(Z));\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2iInhomo()\n        {\n            var div = 1 / Z;\n            return new V2i(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2uiInhomo()\n        {\n            var div = 1 / Z;\n            return new V2ui(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2lInhomo()\n        {\n            var div = 1 / Z;\n            return new V2l(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2fInhomo()\n        {\n            var div = 1 / Z;\n            return new V2f(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2dInhomo()\n        {\n            var div = 1 / Z;\n            return new V2d(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4iHomo()\n            => new V4i(X, Y, Z, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4uiHomo()\n            => new V4ui(X, Y, Z, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4lHomo()\n            => new V4l(X, Y, Z, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4fHomo()\n            => new V4f(X, Y, Z, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4dHomo()\n            => new V4d(X, Y, Z, 1);\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<float, int> element_fun)\n            => new V3i(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<float, int, int> element_index_fun)\n            => new V3i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n            array[start + 2] = (int)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<float, uint> element_fun)\n            => new V3ui(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<float, int, uint> element_index_fun)\n            => new V3ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n            array[start + 2] = (uint)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<float, long> element_fun)\n            => new V3l(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<float, int, long> element_index_fun)\n            => new V3l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n            array[start + 2] = (long)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<float, float> element_fun)\n            => new V3f(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<float, int, float> element_index_fun)\n            => new V3f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<float, double> element_fun)\n            => new V3d(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<float, int, double> element_index_fun)\n            => new V3d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n            array[start + 2] = (double)Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float[] ToArray()\n            => new float[] { X, Y, Z };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? (X >= Z ? 0 : 2) : (Y >= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? (X <= Z ? 0 : 2) : (Y <= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly float MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly float MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z);\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) || Fun.IsFinite(Y) || Fun.IsFinite(Z);\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) && Fun.IsFinite(Y) && Fun.IsFinite(Z);\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(X) || float.IsNaN(Y) || float.IsNaN(Z);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(X) && float.IsNaN(Y) && float.IsNaN(Z);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(X) || float.IsInfinity(Y) || float.IsInfinity(Z);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(X) && float.IsInfinity(Y) && float.IsInfinity(Z);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(X) || float.IsPositiveInfinity(Y) || float.IsPositiveInfinity(Z);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(X) && float.IsPositiveInfinity(Y) && float.IsPositiveInfinity(Z);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(X) || float.IsNegativeInfinity(Y) || float.IsNegativeInfinity(Z);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(X) && float.IsNegativeInfinity(Y) && float.IsNegativeInfinity(Z);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) || Fun.IsTiny(Y) || Fun.IsTiny(Z);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) && Fun.IsTiny(Y) && Fun.IsTiny(Z);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the vector is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the vector are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 3;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V3f Zero\n        {\n            get { return new V3f(0, 0, 0); }\n        }\n\n        /// <summary>\n        /// All elements half.\n        /// </summary>\n        public static V3f Half\n        {\n            get { return new V3f(0.5, 0.5, 0.5); }\n        }\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V3f One\n        {\n            get { return new V3f(1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V3f MaxValue\n        {\n            get { return new V3f(Constant<float>.ParseableMaxValue, Constant<float>.ParseableMaxValue, Constant<float>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V3f MinValue\n        {\n            get { return new V3f(Constant<float>.ParseableMinValue, Constant<float>.ParseableMinValue, Constant<float>.ParseableMinValue); }\n        }\n\n         /// <summary>\n        /// All elements set to negative infinity.\n        /// </summary>\n        public static V3f NegativeInfinity\n        {\n            get { return new V3f(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to positive infinity.\n        /// </summary>\n        public static V3f PositiveInfinity\n        {\n            get { return new V3f(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to NaN.\n        /// </summary>\n        public static V3f NaN\n        {\n            get { return new V3f(float.NaN, float.NaN, float.NaN); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V3f XAxis\n        {\n            get { return new V3f(1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V3f YAxis\n        {\n            get { return new V3f(0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V3f ZAxis\n        {\n            get { return new V3f(0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V3f, float>[] SelectorArray =\n            new Func<V3f, float>[] { v => v.X, v => v.Y, v => v.Z };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V3f, int, float> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V3f, int, float> Setter =\n            (ref V3f v, int i, float s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V3f, long, float> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V3f, long, float> LongSetter =\n            (ref V3f v, long i, float s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromV3i(V3i v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromV3ui(V3ui v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromV3l(V3l v)\n            => new V3f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromV3d(V3d v)\n            => new V3f(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC3b(C3b c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC3us(C3us c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC3ui(C3ui c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC3f(C3f c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC3d(C3d c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC4b(C4b c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC4us(C4us c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC4ui(C4ui c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC4f(C4f c) => new V3f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromC4d(C4d c) => new V3f(c);\n\n        private static readonly V3f[] s_fromCubeCode =\n            new V3f[] { -V3f.XAxis, -V3f.YAxis, -V3f.ZAxis,\n                        V3f.XAxis, V3f.YAxis, V3f.ZAxis };\n\n        /// <summary>\n        /// Return the vector for the supplied cube face code.\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FromCubeFaceCode(int i) { return s_fromCubeCode[i]; }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly float LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly float Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly float Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y) + Fun.Abs(Z); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly float Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly float NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly float NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V3f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V3f.Zero;\n                s = 1 / s;\n                return new V3f(X * s, Y * s, Z * s);\n            }\n        }\n\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered cube with side length 2.\n        /// </summary>\n        public readonly V3f CubeMapped\n        {\n            get\n            {\n                float x = Fun.Abs(X);\n                float y = Fun.Abs(Y);\n                float z = Fun.Abs(Z);\n                if (x > y)\n                {\n                    if (x > z)\n                    {\n                        double s = 1 / x;\n                        return new V3f(Fun.Sign(X), Y * s, Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z;\n                        return new V3f(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n                else\n                {\n                    if (y > z)\n                    {\n                        double s = 1 / y;\n                        return new V3f(X * s, Fun.Sign(Y), Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z;\n                        return new V3f(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered cube with side length 2.\n        /// The out parameter face indicate which face the vector was mapped to:\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        /// </summary>\n        public readonly V3f CubeMappedOnFace(out int face)\n        {\n                float x = Fun.Abs(X);\n                float y = Fun.Abs(Y);\n                float z = Fun.Abs(Z);\n                if (x > y)\n                {\n                    if (x > z)\n                    {\n                        double s = 1 / x; face = X < 0 ? 0 : 3;\n                        return new V3f(Fun.Sign(X), Y * s, Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z; face = Z < 0 ? 2 : 5;\n                        return new V3f(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n                else\n                {\n                    if (y > z)\n                    {\n                        double s = 1 / y; face = Y < 0 ? 1 : 4;\n                        return new V3f(X * s, Fun.Sign(Y), Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z; face = Z < 0 ? 2 : 5;\n                        return new V3f(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n        }\n\n        /// <summary>\n        /// Return an index for the cube face onto which the vector points.\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        /// </summary>\n        public readonly int CubeFaceCode\n        {\n            get\n            {\n                double x = Fun.Abs(X);\n                double y = Fun.Abs(Y);\n                double z = Fun.Abs(Z);\n                int c;\n                double v;\n                if (x > y)\n                {\n                    if (x > z) { c = 0; v = X; } else { c = 2; v = Z; }\n                }\n                else\n                {\n                    if (y > z) { c = 1; v = Y; } else { c = 2; v = Z; }\n                }\n                return v < 0 ? c : c + 3;\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Abs(V3f v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Floor(V3f v)\n            => v.Floor();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Ceiling(V3f v)\n            => v.Ceiling();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Round(V3f v)\n            => v.Round();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Truncate(V3f v)\n            => v.Truncate();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Acos(V3f v)\n            => Fun.Acos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Acoshb(V3f v)\n            => Fun.Acosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Cos(V3f v)\n            => Fun.Cos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Cosh(V3f v)\n            => Fun.Cosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Asin(V3f v)\n            => Fun.Asin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Asinhb(V3f v)\n            => Fun.Asinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Sin(V3f v)\n            => Fun.Sin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Sinh(V3f v)\n            => Fun.Sinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Atan(V3f v)\n            => Fun.Atan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Atanhb(V3f v)\n            => Fun.Atanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Atan2(V3f a, V3f b)\n            => Fun.Atan2(a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Tan(V3f v)\n            => Fun.Tan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Tanh(V3f v)\n            => Fun.Tanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Sqrt(V3f v)\n            => Fun.Sqrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f CubeRoot(V3f v)\n            => Fun.Cbrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Exp(V3f v)\n            => Fun.Exp(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Log(V3f v)\n            => Fun.Log(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LogBinary(V3f v)\n            => Fun.Log2(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Log10(V3f v)\n            => Fun.Log10(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f CopySgn(V3f value, V3f sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f CopySgn(V3f value, float sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LinearInterp(float t, V3f a, V3f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LinearInterp(V3f t, V3f a, V3f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Min(V3f v0, V3f v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Min(V3f v, float x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Max(V3f v0, V3f v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Max(V3f v, float x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Saturate(V3f v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f DivideByInt(V3f v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator -(V3f v)\n            => new V3f(-v.X, -v.Y, -v.Z);\n\n        /// <summary>\n        /// Gets a copy of this vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        public readonly V3f Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V3f(1 / X, 1 / Y, 1 / Z); }\n        }\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator +(V3f a, V3f b)\n            => new V3f(a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator +(V3f v, float s)\n            => new V3f(v.X + s, v.Y + s, v.Z + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator +(float s, V3f v)\n            => new V3f(s + v.X, s + v.Y, s + v.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator -(V3f a, V3f b)\n            => new V3f(a.X - b.X, a.Y - b.Y, a.Z - b.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator -(V3f v, float s)\n            => new V3f(v.X - s, v.Y - s, v.Z - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator -(float s, V3f v)\n            => new V3f(s - v.X, s - v.Y, s - v.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(V3f a, V3f b)\n            => new V3f(a.X * b.X, a.Y * b.Y, a.Z * b.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(V3f v, float s)\n            => new V3f(v.X * s, v.Y * s, v.Z * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator *(float s, V3f v)\n            => new V3f(s * v.X, s * v.Y, s * v.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator /(V3f a, V3f b)\n            => new V3f(a.X / b.X, a.Y / b.Y, a.Z / b.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator /(V3f v, float s)\n            => new V3f(v.X / s, v.Y / s, v.Z / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator /(float s, V3f v)\n            => new V3f(s / v.X, s / v.Y, s / v.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator %(V3f a, V3f b)\n            => new V3f(a.X % b.X, a.Y % b.Y, a.Z % b.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator %(V3f v, float s)\n            => new V3f(v.X % s, v.Y % s, v.Z % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f operator %(float s, V3f v)\n            => new V3f(s % v.X, s % v.Y, s % v.Z);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3f a, V3f b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3f v, float s)\n        {\n            return v.X == s && v.Y == s && v.Z == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(float s, V3f v)\n        {\n            return s == v.X && s == v.Y && s == v.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3f a, V3f b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3f v, float s)\n        {\n            return v.X != s || v.Y != s || v.Z != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(float s, V3f v)\n        {\n            return s != v.X || s != v.Y || s != v.Z;\n        }\n\n        #endregion\n\n        #region IEquatable<V3f> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V3f other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V3f o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V3f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V3f(\n                float.Parse(x[0], CultureInfo.InvariantCulture), \n                float.Parse(x[1], CultureInfo.InvariantCulture), \n                float.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V3f Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<float>.Parse, V3f.Setter);\n        }\n\n        public static V3f Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<float>.Parse, V3f.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OX => new V2f(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OY => new V2f(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OZ => new V2f(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IX => new V2f(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IY => new V2f(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IZ => new V2f(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NX => new V2f(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NY => new V2f(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NZ => new V2f(-1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XO => new V2f(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XI => new V2f(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XN => new V2f(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XX => new V2f(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f XY\n        {\n            readonly get => new V2f(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f XZ\n        {\n            readonly get => new V2f(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YO => new V2f(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YI => new V2f(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YN => new V2f(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f YX\n        {\n            readonly get => new V2f(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YY => new V2f(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f YZ\n        {\n            readonly get => new V2f(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f ZO => new V2f(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f ZI => new V2f(Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f ZN => new V2f(Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f ZX\n        {\n            readonly get => new V2f(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f ZY\n        {\n            readonly get => new V2f(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f ZZ => new V2f(Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f OOO => new V3f(0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f OOI => new V3f(0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f OON => new V3f(0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOX => new V3f(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOY => new V3f(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOZ => new V3f(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f OIO => new V3f(0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f OII => new V3f(0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f OPN => new V3f(0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIX => new V3f(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIY => new V3f(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIZ => new V3f(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f ONO => new V3f(0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f ONP => new V3f(0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f ONN => new V3f(0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONX => new V3f(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONY => new V3f(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONZ => new V3f(0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXO => new V3f(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXI => new V3f(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXN => new V3f(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXX => new V3f(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXY => new V3f(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXZ => new V3f(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYO => new V3f(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYI => new V3f(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYN => new V3f(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYX => new V3f(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYY => new V3f(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYZ => new V3f(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZO => new V3f(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZI => new V3f(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZN => new V3f(0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZX => new V3f(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZY => new V3f(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZZ => new V3f(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f IOO => new V3f(1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f IOI => new V3f(1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f PON => new V3f(1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOX => new V3f(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOY => new V3f(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOZ => new V3f(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f IIO => new V3f(1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f III => new V3f(1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f PPN => new V3f(1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIX => new V3f(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIY => new V3f(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIZ => new V3f(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f PNO => new V3f(1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f PNP => new V3f(1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f PNN => new V3f(1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNX => new V3f(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNY => new V3f(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNZ => new V3f(1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXO => new V3f(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXI => new V3f(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PXN => new V3f(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXX => new V3f(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXY => new V3f(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXZ => new V3f(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYO => new V3f(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYI => new V3f(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PYN => new V3f(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYX => new V3f(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYY => new V3f(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYZ => new V3f(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZO => new V3f(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZI => new V3f(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PZN => new V3f(1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZX => new V3f(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZY => new V3f(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZZ => new V3f(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NOO => new V3f(-1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NOP => new V3f(-1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NON => new V3f(-1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOX => new V3f(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOY => new V3f(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOZ => new V3f(-1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NPO => new V3f(-1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NPP => new V3f(-1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NPN => new V3f(-1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPX => new V3f(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPY => new V3f(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPZ => new V3f(-1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NNO => new V3f(-1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NNP => new V3f(-1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3f NNN => new V3f(-1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNX => new V3f(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNY => new V3f(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNZ => new V3f(-1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXO => new V3f(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXP => new V3f(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXN => new V3f(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXX => new V3f(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXY => new V3f(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXZ => new V3f(-1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYO => new V3f(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYP => new V3f(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYN => new V3f(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYX => new V3f(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYY => new V3f(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYZ => new V3f(-1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZO => new V3f(-1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZP => new V3f(-1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZN => new V3f(-1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZX => new V3f(-1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZY => new V3f(-1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZZ => new V3f(-1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOO => new V3f(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOI => new V3f(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XON => new V3f(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOX => new V3f(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOY => new V3f(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOZ => new V3f(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIO => new V3f(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XII => new V3f(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XPN => new V3f(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIX => new V3f(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIY => new V3f(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIZ => new V3f(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNO => new V3f(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNP => new V3f(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNN => new V3f(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNX => new V3f(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNY => new V3f(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNZ => new V3f(X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXO => new V3f(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXI => new V3f(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXN => new V3f(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXX => new V3f(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXY => new V3f(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXZ => new V3f(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYO => new V3f(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYI => new V3f(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYN => new V3f(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYX => new V3f(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYY => new V3f(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f XYZ\n        {\n            readonly get => new V3f(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZO => new V3f(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZI => new V3f(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZN => new V3f(X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZX => new V3f(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f XZY\n        {\n            readonly get => new V3f(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZZ => new V3f(X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOO => new V3f(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOI => new V3f(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YON => new V3f(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOX => new V3f(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOY => new V3f(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOZ => new V3f(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIO => new V3f(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YII => new V3f(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YPN => new V3f(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIX => new V3f(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIY => new V3f(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIZ => new V3f(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNO => new V3f(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNP => new V3f(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNN => new V3f(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNX => new V3f(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNY => new V3f(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNZ => new V3f(Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXO => new V3f(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXI => new V3f(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXN => new V3f(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXX => new V3f(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXY => new V3f(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f YXZ\n        {\n            readonly get => new V3f(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYO => new V3f(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYI => new V3f(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYN => new V3f(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYX => new V3f(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYY => new V3f(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYZ => new V3f(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZO => new V3f(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZI => new V3f(Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZN => new V3f(Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f YZX\n        {\n            readonly get => new V3f(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZY => new V3f(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZZ => new V3f(Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOO => new V3f(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOI => new V3f(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZON => new V3f(Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOX => new V3f(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOY => new V3f(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOZ => new V3f(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIO => new V3f(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZII => new V3f(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZPN => new V3f(Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIX => new V3f(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIY => new V3f(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIZ => new V3f(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNO => new V3f(Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNP => new V3f(Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNN => new V3f(Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNX => new V3f(Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNY => new V3f(Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNZ => new V3f(Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXO => new V3f(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXI => new V3f(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXN => new V3f(Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXX => new V3f(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f ZXY\n        {\n            readonly get => new V3f(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXZ => new V3f(Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYO => new V3f(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYI => new V3f(Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYN => new V3f(Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f ZYX\n        {\n            readonly get => new V3f(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYY => new V3f(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYZ => new V3f(Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZO => new V3f(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZI => new V3f(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZN => new V3f(Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZX => new V3f(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZY => new V3f(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZZ => new V3f(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOX => new V4f(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOY => new V4f(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOZ => new V4f(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIX => new V4f(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIY => new V4f(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIZ => new V4f(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONX => new V4f(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONY => new V4f(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONZ => new V4f(0, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXO => new V4f(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXI => new V4f(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXN => new V4f(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXX => new V4f(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXY => new V4f(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXZ => new V4f(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYO => new V4f(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYI => new V4f(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYN => new V4f(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYX => new V4f(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYY => new V4f(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYZ => new V4f(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZO => new V4f(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZI => new V4f(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZN => new V4f(0, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZX => new V4f(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZY => new V4f(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZZ => new V4f(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOX => new V4f(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOY => new V4f(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOZ => new V4f(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIX => new V4f(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIY => new V4f(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIZ => new V4f(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNX => new V4f(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNY => new V4f(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNZ => new V4f(0, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXO => new V4f(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXI => new V4f(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPXN => new V4f(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXX => new V4f(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXY => new V4f(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXZ => new V4f(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYO => new V4f(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYI => new V4f(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPYN => new V4f(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYX => new V4f(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYY => new V4f(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYZ => new V4f(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZO => new V4f(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZI => new V4f(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPZN => new V4f(0, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZX => new V4f(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZY => new V4f(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZZ => new V4f(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOX => new V4f(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOY => new V4f(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOZ => new V4f(0, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPX => new V4f(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPY => new V4f(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPZ => new V4f(0, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNX => new V4f(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNY => new V4f(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNZ => new V4f(0, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXO => new V4f(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXP => new V4f(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXN => new V4f(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXX => new V4f(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXY => new V4f(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXZ => new V4f(0, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYO => new V4f(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYP => new V4f(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYN => new V4f(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYX => new V4f(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYY => new V4f(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYZ => new V4f(0, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZO => new V4f(0, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZP => new V4f(0, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZN => new V4f(0, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZX => new V4f(0, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZY => new V4f(0, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZZ => new V4f(0, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOO => new V4f(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOI => new V4f(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXON => new V4f(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOX => new V4f(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOY => new V4f(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOZ => new V4f(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIO => new V4f(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXII => new V4f(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXPN => new V4f(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIX => new V4f(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIY => new V4f(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIZ => new V4f(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNO => new V4f(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNP => new V4f(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNN => new V4f(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNX => new V4f(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNY => new V4f(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNZ => new V4f(0, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXO => new V4f(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXI => new V4f(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXN => new V4f(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXX => new V4f(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXY => new V4f(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXZ => new V4f(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYO => new V4f(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYI => new V4f(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYN => new V4f(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYX => new V4f(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYY => new V4f(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYZ => new V4f(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZO => new V4f(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZI => new V4f(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZN => new V4f(0, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZX => new V4f(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZY => new V4f(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZZ => new V4f(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOO => new V4f(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOI => new V4f(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYON => new V4f(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOX => new V4f(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOY => new V4f(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOZ => new V4f(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIO => new V4f(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYII => new V4f(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYPN => new V4f(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIX => new V4f(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIY => new V4f(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIZ => new V4f(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNO => new V4f(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNP => new V4f(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNN => new V4f(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNX => new V4f(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNY => new V4f(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNZ => new V4f(0, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXO => new V4f(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXI => new V4f(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXN => new V4f(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXX => new V4f(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXY => new V4f(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXZ => new V4f(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYO => new V4f(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYI => new V4f(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYN => new V4f(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYX => new V4f(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYY => new V4f(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYZ => new V4f(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZO => new V4f(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZI => new V4f(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZN => new V4f(0, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZX => new V4f(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZY => new V4f(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZZ => new V4f(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOO => new V4f(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOI => new V4f(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZON => new V4f(0, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOX => new V4f(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOY => new V4f(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOZ => new V4f(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIO => new V4f(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZII => new V4f(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZPN => new V4f(0, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIX => new V4f(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIY => new V4f(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIZ => new V4f(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNO => new V4f(0, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNP => new V4f(0, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNN => new V4f(0, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNX => new V4f(0, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNY => new V4f(0, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNZ => new V4f(0, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXO => new V4f(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXI => new V4f(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXN => new V4f(0, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXX => new V4f(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXY => new V4f(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXZ => new V4f(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYO => new V4f(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYI => new V4f(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYN => new V4f(0, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYX => new V4f(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYY => new V4f(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYZ => new V4f(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZO => new V4f(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZI => new V4f(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZN => new V4f(0, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZX => new V4f(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZY => new V4f(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZZ => new V4f(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOX => new V4f(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOY => new V4f(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOZ => new V4f(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIX => new V4f(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIY => new V4f(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIZ => new V4f(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONX => new V4f(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONY => new V4f(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONZ => new V4f(1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXO => new V4f(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXI => new V4f(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POXN => new V4f(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXX => new V4f(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXY => new V4f(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXZ => new V4f(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYO => new V4f(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYI => new V4f(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POYN => new V4f(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYX => new V4f(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYY => new V4f(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYZ => new V4f(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZO => new V4f(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZI => new V4f(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POZN => new V4f(1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZX => new V4f(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZY => new V4f(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZZ => new V4f(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOX => new V4f(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOY => new V4f(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOZ => new V4f(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIX => new V4f(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIY => new V4f(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIZ => new V4f(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNX => new V4f(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNY => new V4f(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNZ => new V4f(1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXO => new V4f(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXI => new V4f(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPXN => new V4f(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXX => new V4f(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXY => new V4f(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXZ => new V4f(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYO => new V4f(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYI => new V4f(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPYN => new V4f(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYX => new V4f(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYY => new V4f(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYZ => new V4f(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZO => new V4f(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZI => new V4f(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPZN => new V4f(1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZX => new V4f(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZY => new V4f(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZZ => new V4f(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOX => new V4f(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOY => new V4f(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOZ => new V4f(1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPX => new V4f(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPY => new V4f(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPZ => new V4f(1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNX => new V4f(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNY => new V4f(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNZ => new V4f(1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXO => new V4f(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXP => new V4f(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXN => new V4f(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXX => new V4f(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXY => new V4f(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXZ => new V4f(1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYO => new V4f(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYP => new V4f(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYN => new V4f(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYX => new V4f(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYY => new V4f(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYZ => new V4f(1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZO => new V4f(1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZP => new V4f(1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZN => new V4f(1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZX => new V4f(1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZY => new V4f(1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZZ => new V4f(1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOO => new V4f(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOI => new V4f(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXON => new V4f(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOX => new V4f(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOY => new V4f(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOZ => new V4f(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIO => new V4f(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXII => new V4f(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXPN => new V4f(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIX => new V4f(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIY => new V4f(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIZ => new V4f(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNO => new V4f(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNP => new V4f(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNN => new V4f(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNX => new V4f(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNY => new V4f(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNZ => new V4f(1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXO => new V4f(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXI => new V4f(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXXN => new V4f(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXX => new V4f(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXY => new V4f(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXZ => new V4f(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYO => new V4f(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYI => new V4f(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXYN => new V4f(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYX => new V4f(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYY => new V4f(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYZ => new V4f(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZO => new V4f(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZI => new V4f(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXZN => new V4f(1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZX => new V4f(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZY => new V4f(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZZ => new V4f(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOO => new V4f(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOI => new V4f(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYON => new V4f(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOX => new V4f(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOY => new V4f(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOZ => new V4f(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIO => new V4f(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYII => new V4f(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYPN => new V4f(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIX => new V4f(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIY => new V4f(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIZ => new V4f(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNO => new V4f(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNP => new V4f(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNN => new V4f(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNX => new V4f(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNY => new V4f(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNZ => new V4f(1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXO => new V4f(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXI => new V4f(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYXN => new V4f(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXX => new V4f(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXY => new V4f(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXZ => new V4f(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYO => new V4f(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYI => new V4f(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYYN => new V4f(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYX => new V4f(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYY => new V4f(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYZ => new V4f(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZO => new V4f(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZI => new V4f(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYZN => new V4f(1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZX => new V4f(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZY => new V4f(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZZ => new V4f(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOO => new V4f(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOI => new V4f(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZON => new V4f(1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOX => new V4f(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOY => new V4f(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOZ => new V4f(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIO => new V4f(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZII => new V4f(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZPN => new V4f(1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIX => new V4f(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIY => new V4f(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIZ => new V4f(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNO => new V4f(1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNP => new V4f(1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNN => new V4f(1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNX => new V4f(1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNY => new V4f(1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNZ => new V4f(1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXO => new V4f(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXI => new V4f(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZXN => new V4f(1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXX => new V4f(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXY => new V4f(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXZ => new V4f(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYO => new V4f(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYI => new V4f(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZYN => new V4f(1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYX => new V4f(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYY => new V4f(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYZ => new V4f(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZO => new V4f(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZI => new V4f(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZZN => new V4f(1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZX => new V4f(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZY => new V4f(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZZ => new V4f(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOX => new V4f(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOY => new V4f(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOZ => new V4f(-1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPX => new V4f(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPY => new V4f(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPZ => new V4f(-1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONX => new V4f(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONY => new V4f(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONZ => new V4f(-1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXO => new V4f(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXP => new V4f(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXN => new V4f(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXX => new V4f(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXY => new V4f(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXZ => new V4f(-1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYO => new V4f(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYP => new V4f(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYN => new V4f(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYX => new V4f(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYY => new V4f(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYZ => new V4f(-1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZO => new V4f(-1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZP => new V4f(-1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZN => new V4f(-1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZX => new V4f(-1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZY => new V4f(-1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZZ => new V4f(-1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOX => new V4f(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOY => new V4f(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOZ => new V4f(-1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPX => new V4f(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPY => new V4f(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPZ => new V4f(-1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNX => new V4f(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNY => new V4f(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNZ => new V4f(-1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXO => new V4f(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXP => new V4f(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXN => new V4f(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXX => new V4f(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXY => new V4f(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXZ => new V4f(-1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYO => new V4f(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYP => new V4f(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYN => new V4f(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYX => new V4f(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYY => new V4f(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYZ => new V4f(-1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZO => new V4f(-1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZP => new V4f(-1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZN => new V4f(-1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZX => new V4f(-1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZY => new V4f(-1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZZ => new V4f(-1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOX => new V4f(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOY => new V4f(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOZ => new V4f(-1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPX => new V4f(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPY => new V4f(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPZ => new V4f(-1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNX => new V4f(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNY => new V4f(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNZ => new V4f(-1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXO => new V4f(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXP => new V4f(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXN => new V4f(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXX => new V4f(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXY => new V4f(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXZ => new V4f(-1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYO => new V4f(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYP => new V4f(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYN => new V4f(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYX => new V4f(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYY => new V4f(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYZ => new V4f(-1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZO => new V4f(-1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZP => new V4f(-1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZN => new V4f(-1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZX => new V4f(-1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZY => new V4f(-1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZZ => new V4f(-1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOO => new V4f(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOP => new V4f(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXON => new V4f(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOX => new V4f(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOY => new V4f(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOZ => new V4f(-1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPO => new V4f(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPP => new V4f(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPN => new V4f(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPX => new V4f(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPY => new V4f(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPZ => new V4f(-1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNO => new V4f(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNP => new V4f(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNN => new V4f(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNX => new V4f(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNY => new V4f(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNZ => new V4f(-1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXO => new V4f(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXP => new V4f(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXN => new V4f(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXX => new V4f(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXY => new V4f(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXZ => new V4f(-1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYO => new V4f(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYP => new V4f(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYN => new V4f(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYX => new V4f(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYY => new V4f(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYZ => new V4f(-1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZO => new V4f(-1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZP => new V4f(-1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZN => new V4f(-1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZX => new V4f(-1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZY => new V4f(-1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZZ => new V4f(-1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOO => new V4f(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOP => new V4f(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYON => new V4f(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOX => new V4f(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOY => new V4f(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOZ => new V4f(-1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPO => new V4f(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPP => new V4f(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPN => new V4f(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPX => new V4f(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPY => new V4f(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPZ => new V4f(-1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNO => new V4f(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNP => new V4f(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNN => new V4f(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNX => new V4f(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNY => new V4f(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNZ => new V4f(-1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXO => new V4f(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXP => new V4f(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXN => new V4f(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXX => new V4f(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXY => new V4f(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXZ => new V4f(-1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYO => new V4f(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYP => new V4f(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYN => new V4f(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYX => new V4f(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYY => new V4f(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYZ => new V4f(-1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZO => new V4f(-1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZP => new V4f(-1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZN => new V4f(-1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZX => new V4f(-1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZY => new V4f(-1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZZ => new V4f(-1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOO => new V4f(-1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOP => new V4f(-1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZON => new V4f(-1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOX => new V4f(-1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOY => new V4f(-1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOZ => new V4f(-1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPO => new V4f(-1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPP => new V4f(-1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPN => new V4f(-1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPX => new V4f(-1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPY => new V4f(-1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPZ => new V4f(-1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNO => new V4f(-1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNP => new V4f(-1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNN => new V4f(-1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNX => new V4f(-1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNY => new V4f(-1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNZ => new V4f(-1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXO => new V4f(-1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXP => new V4f(-1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXN => new V4f(-1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXX => new V4f(-1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXY => new V4f(-1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXZ => new V4f(-1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYO => new V4f(-1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYP => new V4f(-1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYN => new V4f(-1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYX => new V4f(-1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYY => new V4f(-1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYZ => new V4f(-1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZO => new V4f(-1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZP => new V4f(-1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZN => new V4f(-1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZX => new V4f(-1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZY => new V4f(-1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZZ => new V4f(-1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOO => new V4f(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOI => new V4f(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOON => new V4f(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOX => new V4f(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOY => new V4f(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOZ => new V4f(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIO => new V4f(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOII => new V4f(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOPN => new V4f(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIX => new V4f(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIY => new V4f(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIZ => new V4f(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONO => new V4f(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONP => new V4f(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONN => new V4f(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONX => new V4f(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONY => new V4f(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONZ => new V4f(X, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXO => new V4f(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXI => new V4f(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXN => new V4f(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXX => new V4f(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXY => new V4f(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXZ => new V4f(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYO => new V4f(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYI => new V4f(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYN => new V4f(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYX => new V4f(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYY => new V4f(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYZ => new V4f(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZO => new V4f(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZI => new V4f(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZN => new V4f(X, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZX => new V4f(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZY => new V4f(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZZ => new V4f(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOO => new V4f(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOI => new V4f(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPON => new V4f(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOX => new V4f(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOY => new V4f(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOZ => new V4f(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIO => new V4f(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIII => new V4f(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPPN => new V4f(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIX => new V4f(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIY => new V4f(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIZ => new V4f(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNO => new V4f(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNP => new V4f(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNN => new V4f(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNX => new V4f(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNY => new V4f(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNZ => new V4f(X, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXO => new V4f(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXI => new V4f(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPXN => new V4f(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXX => new V4f(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXY => new V4f(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXZ => new V4f(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYO => new V4f(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYI => new V4f(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPYN => new V4f(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYX => new V4f(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYY => new V4f(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYZ => new V4f(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZO => new V4f(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZI => new V4f(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPZN => new V4f(X, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZX => new V4f(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZY => new V4f(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZZ => new V4f(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOO => new V4f(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOP => new V4f(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNON => new V4f(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOX => new V4f(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOY => new V4f(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOZ => new V4f(X, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPO => new V4f(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPP => new V4f(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPN => new V4f(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPX => new V4f(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPY => new V4f(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPZ => new V4f(X, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNO => new V4f(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNP => new V4f(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNN => new V4f(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNX => new V4f(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNY => new V4f(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNZ => new V4f(X, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXO => new V4f(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXP => new V4f(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXN => new V4f(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXX => new V4f(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXY => new V4f(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXZ => new V4f(X, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYO => new V4f(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYP => new V4f(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYN => new V4f(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYX => new V4f(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYY => new V4f(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYZ => new V4f(X, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZO => new V4f(X, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZP => new V4f(X, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZN => new V4f(X, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZX => new V4f(X, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZY => new V4f(X, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZZ => new V4f(X, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOO => new V4f(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOI => new V4f(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXON => new V4f(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOX => new V4f(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOY => new V4f(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOZ => new V4f(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIO => new V4f(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXII => new V4f(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXPN => new V4f(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIX => new V4f(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIY => new V4f(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIZ => new V4f(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNO => new V4f(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNP => new V4f(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNN => new V4f(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNX => new V4f(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNY => new V4f(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNZ => new V4f(X, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXO => new V4f(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXI => new V4f(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXN => new V4f(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXX => new V4f(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXY => new V4f(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXZ => new V4f(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYO => new V4f(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYI => new V4f(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYN => new V4f(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYX => new V4f(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYY => new V4f(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYZ => new V4f(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZO => new V4f(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZI => new V4f(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZN => new V4f(X, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZX => new V4f(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZY => new V4f(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZZ => new V4f(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOO => new V4f(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOI => new V4f(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYON => new V4f(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOX => new V4f(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOY => new V4f(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOZ => new V4f(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIO => new V4f(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYII => new V4f(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYPN => new V4f(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIX => new V4f(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIY => new V4f(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIZ => new V4f(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNO => new V4f(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNP => new V4f(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNN => new V4f(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNX => new V4f(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNY => new V4f(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNZ => new V4f(X, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXO => new V4f(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXI => new V4f(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXN => new V4f(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXX => new V4f(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXY => new V4f(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXZ => new V4f(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYO => new V4f(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYI => new V4f(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYN => new V4f(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYX => new V4f(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYY => new V4f(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYZ => new V4f(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZO => new V4f(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZI => new V4f(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZN => new V4f(X, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZX => new V4f(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZY => new V4f(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZZ => new V4f(X, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOO => new V4f(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOI => new V4f(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZON => new V4f(X, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOX => new V4f(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOY => new V4f(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOZ => new V4f(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIO => new V4f(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZII => new V4f(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZPN => new V4f(X, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIX => new V4f(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIY => new V4f(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIZ => new V4f(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNO => new V4f(X, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNP => new V4f(X, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNN => new V4f(X, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNX => new V4f(X, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNY => new V4f(X, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNZ => new V4f(X, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXO => new V4f(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXI => new V4f(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXN => new V4f(X, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXX => new V4f(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXY => new V4f(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXZ => new V4f(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYO => new V4f(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYI => new V4f(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYN => new V4f(X, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYX => new V4f(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYY => new V4f(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYZ => new V4f(X, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZO => new V4f(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZI => new V4f(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZN => new V4f(X, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZX => new V4f(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZY => new V4f(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZZ => new V4f(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOO => new V4f(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOI => new V4f(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOON => new V4f(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOX => new V4f(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOY => new V4f(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOZ => new V4f(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIO => new V4f(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOII => new V4f(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOPN => new V4f(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIX => new V4f(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIY => new V4f(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIZ => new V4f(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONO => new V4f(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONP => new V4f(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONN => new V4f(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONX => new V4f(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONY => new V4f(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONZ => new V4f(Y, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXO => new V4f(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXI => new V4f(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXN => new V4f(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXX => new V4f(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXY => new V4f(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXZ => new V4f(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYO => new V4f(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYI => new V4f(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYN => new V4f(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYX => new V4f(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYY => new V4f(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYZ => new V4f(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZO => new V4f(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZI => new V4f(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZN => new V4f(Y, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZX => new V4f(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZY => new V4f(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZZ => new V4f(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOO => new V4f(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOI => new V4f(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPON => new V4f(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOX => new V4f(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOY => new V4f(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOZ => new V4f(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIO => new V4f(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIII => new V4f(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPPN => new V4f(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIX => new V4f(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIY => new V4f(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIZ => new V4f(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNO => new V4f(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNP => new V4f(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNN => new V4f(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNX => new V4f(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNY => new V4f(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNZ => new V4f(Y, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXO => new V4f(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXI => new V4f(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPXN => new V4f(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXX => new V4f(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXY => new V4f(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXZ => new V4f(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYO => new V4f(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYI => new V4f(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPYN => new V4f(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYX => new V4f(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYY => new V4f(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYZ => new V4f(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZO => new V4f(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZI => new V4f(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPZN => new V4f(Y, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZX => new V4f(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZY => new V4f(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZZ => new V4f(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOO => new V4f(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOP => new V4f(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNON => new V4f(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOX => new V4f(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOY => new V4f(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOZ => new V4f(Y, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPO => new V4f(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPP => new V4f(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPN => new V4f(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPX => new V4f(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPY => new V4f(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPZ => new V4f(Y, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNO => new V4f(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNP => new V4f(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNN => new V4f(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNX => new V4f(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNY => new V4f(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNZ => new V4f(Y, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXO => new V4f(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXP => new V4f(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXN => new V4f(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXX => new V4f(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXY => new V4f(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXZ => new V4f(Y, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYO => new V4f(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYP => new V4f(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYN => new V4f(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYX => new V4f(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYY => new V4f(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYZ => new V4f(Y, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZO => new V4f(Y, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZP => new V4f(Y, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZN => new V4f(Y, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZX => new V4f(Y, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZY => new V4f(Y, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZZ => new V4f(Y, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOO => new V4f(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOI => new V4f(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXON => new V4f(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOX => new V4f(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOY => new V4f(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOZ => new V4f(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIO => new V4f(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXII => new V4f(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXPN => new V4f(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIX => new V4f(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIY => new V4f(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIZ => new V4f(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNO => new V4f(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNP => new V4f(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNN => new V4f(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNX => new V4f(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNY => new V4f(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNZ => new V4f(Y, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXO => new V4f(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXI => new V4f(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXN => new V4f(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXX => new V4f(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXY => new V4f(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXZ => new V4f(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYO => new V4f(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYI => new V4f(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYN => new V4f(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYX => new V4f(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYY => new V4f(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYZ => new V4f(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZO => new V4f(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZI => new V4f(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZN => new V4f(Y, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZX => new V4f(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZY => new V4f(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZZ => new V4f(Y, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOO => new V4f(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOI => new V4f(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYON => new V4f(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOX => new V4f(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOY => new V4f(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOZ => new V4f(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIO => new V4f(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYII => new V4f(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYPN => new V4f(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIX => new V4f(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIY => new V4f(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIZ => new V4f(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNO => new V4f(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNP => new V4f(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNN => new V4f(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNX => new V4f(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNY => new V4f(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNZ => new V4f(Y, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXO => new V4f(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXI => new V4f(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXN => new V4f(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXX => new V4f(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXY => new V4f(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXZ => new V4f(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYO => new V4f(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYI => new V4f(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYN => new V4f(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYX => new V4f(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYY => new V4f(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYZ => new V4f(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZO => new V4f(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZI => new V4f(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZN => new V4f(Y, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZX => new V4f(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZY => new V4f(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZZ => new V4f(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOO => new V4f(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOI => new V4f(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZON => new V4f(Y, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOX => new V4f(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOY => new V4f(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOZ => new V4f(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIO => new V4f(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZII => new V4f(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZPN => new V4f(Y, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIX => new V4f(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIY => new V4f(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIZ => new V4f(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNO => new V4f(Y, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNP => new V4f(Y, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNN => new V4f(Y, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNX => new V4f(Y, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNY => new V4f(Y, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNZ => new V4f(Y, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXO => new V4f(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXI => new V4f(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXN => new V4f(Y, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXX => new V4f(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXY => new V4f(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXZ => new V4f(Y, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYO => new V4f(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYI => new V4f(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYN => new V4f(Y, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYX => new V4f(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYY => new V4f(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYZ => new V4f(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZO => new V4f(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZI => new V4f(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZN => new V4f(Y, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZX => new V4f(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZY => new V4f(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZZ => new V4f(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOO => new V4f(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOI => new V4f(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOON => new V4f(Z, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOX => new V4f(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOY => new V4f(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOZ => new V4f(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIO => new V4f(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOII => new V4f(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOPN => new V4f(Z, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIX => new V4f(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIY => new V4f(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIZ => new V4f(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONO => new V4f(Z, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONP => new V4f(Z, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONN => new V4f(Z, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONX => new V4f(Z, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONY => new V4f(Z, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONZ => new V4f(Z, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXO => new V4f(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXI => new V4f(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXN => new V4f(Z, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXX => new V4f(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXY => new V4f(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXZ => new V4f(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYO => new V4f(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYI => new V4f(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYN => new V4f(Z, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYX => new V4f(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYY => new V4f(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYZ => new V4f(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZO => new V4f(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZI => new V4f(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZN => new V4f(Z, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZX => new V4f(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZY => new V4f(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZZ => new V4f(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOO => new V4f(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOI => new V4f(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPON => new V4f(Z, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOX => new V4f(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOY => new V4f(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOZ => new V4f(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIO => new V4f(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIII => new V4f(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPPN => new V4f(Z, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIX => new V4f(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIY => new V4f(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIZ => new V4f(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNO => new V4f(Z, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNP => new V4f(Z, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNN => new V4f(Z, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNX => new V4f(Z, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNY => new V4f(Z, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNZ => new V4f(Z, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXO => new V4f(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXI => new V4f(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPXN => new V4f(Z, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXX => new V4f(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXY => new V4f(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXZ => new V4f(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYO => new V4f(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYI => new V4f(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPYN => new V4f(Z, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYX => new V4f(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYY => new V4f(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYZ => new V4f(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZO => new V4f(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZI => new V4f(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPZN => new V4f(Z, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZX => new V4f(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZY => new V4f(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZZ => new V4f(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOO => new V4f(Z, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOP => new V4f(Z, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNON => new V4f(Z, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOX => new V4f(Z, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOY => new V4f(Z, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOZ => new V4f(Z, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPO => new V4f(Z, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPP => new V4f(Z, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPN => new V4f(Z, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPX => new V4f(Z, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPY => new V4f(Z, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPZ => new V4f(Z, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNO => new V4f(Z, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNP => new V4f(Z, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNN => new V4f(Z, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNX => new V4f(Z, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNY => new V4f(Z, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNZ => new V4f(Z, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXO => new V4f(Z, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXP => new V4f(Z, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXN => new V4f(Z, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXX => new V4f(Z, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXY => new V4f(Z, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXZ => new V4f(Z, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYO => new V4f(Z, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYP => new V4f(Z, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYN => new V4f(Z, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYX => new V4f(Z, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYY => new V4f(Z, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYZ => new V4f(Z, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZO => new V4f(Z, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZP => new V4f(Z, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZN => new V4f(Z, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZX => new V4f(Z, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZY => new V4f(Z, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZZ => new V4f(Z, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOO => new V4f(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOI => new V4f(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXON => new V4f(Z, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOX => new V4f(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOY => new V4f(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOZ => new V4f(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIO => new V4f(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXII => new V4f(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXPN => new V4f(Z, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIX => new V4f(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIY => new V4f(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIZ => new V4f(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNO => new V4f(Z, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNP => new V4f(Z, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNN => new V4f(Z, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNX => new V4f(Z, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNY => new V4f(Z, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNZ => new V4f(Z, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXO => new V4f(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXI => new V4f(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXN => new V4f(Z, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXX => new V4f(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXY => new V4f(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXZ => new V4f(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYO => new V4f(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYI => new V4f(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYN => new V4f(Z, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYX => new V4f(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYY => new V4f(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYZ => new V4f(Z, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZO => new V4f(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZI => new V4f(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZN => new V4f(Z, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZX => new V4f(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZY => new V4f(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZZ => new V4f(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOO => new V4f(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOI => new V4f(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYON => new V4f(Z, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOX => new V4f(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOY => new V4f(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOZ => new V4f(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIO => new V4f(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYII => new V4f(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYPN => new V4f(Z, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIX => new V4f(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIY => new V4f(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIZ => new V4f(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNO => new V4f(Z, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNP => new V4f(Z, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNN => new V4f(Z, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNX => new V4f(Z, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNY => new V4f(Z, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNZ => new V4f(Z, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXO => new V4f(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXI => new V4f(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXN => new V4f(Z, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXX => new V4f(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXY => new V4f(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXZ => new V4f(Z, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYO => new V4f(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYI => new V4f(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYN => new V4f(Z, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYX => new V4f(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYY => new V4f(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYZ => new V4f(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZO => new V4f(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZI => new V4f(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZN => new V4f(Z, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZX => new V4f(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZY => new V4f(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZZ => new V4f(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOO => new V4f(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOI => new V4f(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZON => new V4f(Z, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOX => new V4f(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOY => new V4f(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOZ => new V4f(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIO => new V4f(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZII => new V4f(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZPN => new V4f(Z, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIX => new V4f(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIY => new V4f(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIZ => new V4f(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNO => new V4f(Z, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNP => new V4f(Z, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNN => new V4f(Z, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNX => new V4f(Z, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNY => new V4f(Z, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNZ => new V4f(Z, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXO => new V4f(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXI => new V4f(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXN => new V4f(Z, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXX => new V4f(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXY => new V4f(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXZ => new V4f(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYO => new V4f(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYI => new V4f(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYN => new V4f(Z, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYX => new V4f(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYY => new V4f(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYZ => new V4f(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZO => new V4f(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZI => new V4f(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZN => new V4f(Z, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZX => new V4f(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZY => new V4f(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZZ => new V4f(Z, Z, Z, Z);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (float)value; }\n        }\n\n        #endregion\n\n        #region ISize3f Members\n\n        public readonly V3f Size3f { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 3; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (float)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V3fEqualityComparer : IEqualityComparer<V3f>\n    {\n        public static V3fEqualityComparer Default\n            => new V3fEqualityComparer();\n\n        #region IEqualityComparer<V3f> Members\n\n        public bool Equals(V3f v0, V3f v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V3f v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Min(this V3f a, V3f b)\n        {\n            return new V3f(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Min(this V3f a, float b)\n        {\n            return new V3f(Min(a.X, b), Min(a.Y, b), Min(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Min(this float a, V3f b)\n        {\n            return new V3f(Min(a, b.X), Min(a, b.Y), Min(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Max(this V3f a, V3f b)\n        {\n            return new V3f(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Max(this V3f a, float b)\n        {\n            return new V3f(Max(a.X, b), Max(a.Y, b), Max(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Max(this float a, V3f b)\n        {\n            return new V3f(Max(a, b.X), Max(a, b.Y), Max(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Min(this V3f a, V3f b, V3f c)\n        {\n            return new V3f(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Max(this V3f a, V3f b, V3f c)\n        {\n            return new V3f(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Min(this V3f a, V3f b, V3f c, V3f d)\n        {\n            return new V3f(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Max(this V3f a, V3f b, V3f c, V3f d)\n        {\n            return new V3f(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Min(this V3f x, params V3f[] values)\n        {\n            return new V3f(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Max(this V3f x, params V3f[] values)\n        {\n            return new V3f(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Abs(this V3f x)\n        {\n            return new V3f(Abs(x.X), Abs(x.Y), Abs(x.Z));\n        }\n\n        #endregion\n\n        #region Rounding\n\n        /// <summary>\n        /// Applies Fun.Floor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Floor(this V3f x)\n        {\n            return new V3f(Floor(x.X), Floor(x.Y), Floor(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Ceiling to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Ceiling(this V3f x)\n        {\n            return new V3f(Ceiling(x.X), Ceiling(x.Y), Ceiling(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Round(this V3f x)\n        {\n            return new V3f(Round(x.X), Round(x.Y), Round(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Round(this V3f x, MidpointRounding mode)\n        {\n            return new V3f(Round(x.X, mode), Round(x.Y, mode), Round(x.Z, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Round(this V3f x, int digits)\n        {\n            return new V3f(Round(x.X, digits), Round(x.Y, digits), Round(x.Z, digits));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Round(this V3f x, int digits, MidpointRounding mode)\n        {\n            return new V3f(Round(x.X, digits, mode), Round(x.Y, digits, mode), Round(x.Z, digits, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Truncate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Truncate(this V3f x)\n        {\n            return new V3f(Truncate(x.X), Truncate(x.Y), Truncate(x.Z));\n        }\n\n        #endregion\n\n        #region Frac\n\n        /// <summary>\n        /// Applies Fun.Frac to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Frac(this V3f x)\n        {\n            return new V3f(Frac(x.X), Frac(x.Y), Frac(x.Z));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Clamp(this V3f x, V3f a, V3f b)\n        {\n            return new V3f(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Clamp(this V3f x, float a, float b)\n        {\n            return new V3f(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f ClampWrap(this V3f x, V3f a, V3f b)\n        {\n            return new V3f(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f ClampWrap(this V3f x, float a, float b)\n        {\n            return new V3f(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Saturate(this V3f x)\n        {\n            return new V3f(Saturate(x.X), Saturate(x.Y), Saturate(x.Z));\n        }\n\n        #endregion\n\n        #region MapToUnitInterval\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f MapToUnitInterval(this V3f t, V3f tMax, bool repeat, bool mirror)\n        {\n            return new V3f(MapToUnitInterval(t.X, tMax.X, repeat, mirror), MapToUnitInterval(t.Y, tMax.Y, repeat, mirror), MapToUnitInterval(t.Z, tMax.Z, repeat, mirror));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f MapToUnitInterval(this V3f t, V3f tMax, bool repeat)\n        {\n            return new V3f(MapToUnitInterval(t.X, tMax.X, repeat), MapToUnitInterval(t.Y, tMax.Y, repeat), MapToUnitInterval(t.Z, tMax.Z, repeat));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f MapToUnitInterval(this V3f t, V3f tMax)\n        {\n            return new V3f(MapToUnitInterval(t.X, tMax.X), MapToUnitInterval(t.Y, tMax.Y), MapToUnitInterval(t.Z, tMax.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f MapToUnitInterval(this V3f t, V3f tMin, V3f tMax)\n        {\n            return new V3f(MapToUnitInterval(t.X, tMin.X, tMax.X), MapToUnitInterval(t.Y, tMin.Y, tMax.Y), MapToUnitInterval(t.Z, tMin.Z, tMax.Z));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Sign(this V3f x)\n        {\n            return new V3i(Sign(x.X), Sign(x.Y), Sign(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Signumi(this V3f x)\n        {\n            return new V3i(Signumi(x.X), Signumi(x.Y), Signumi(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Signum(this V3f x)\n        {\n            return new V3f(Signum(x.X), Signum(x.Y), Signum(x.Z));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f MultiplyAdd(V3f x, V3f y, V3f z)\n        {\n            return new V3f(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f MultiplyAdd(V3f x, float y, V3f z)\n        {\n            return new V3f(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f MultiplyAdd(float x, V3f y, V3f z)\n        {\n            return new V3f(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z));\n        }\n\n        #endregion\n\n        #region Copy sign\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f CopySign(V3f value, V3f sign)\n        {\n            return new V3f(CopySign(value.X, sign.X), CopySign(value.Y, sign.Y), CopySign(value.Z, sign.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f CopySign(float value, V3f sign)\n        {\n            return new V3f(CopySign(value, sign.X), CopySign(value, sign.Y), CopySign(value, sign.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f CopySign(V3f value, float sign)\n        {\n            return new V3f(CopySign(value.X, sign), CopySign(value.Y, sign), CopySign(value.Z, sign));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Sqrt(this V3f x)\n        {\n            return new V3f(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Cbrt(this V3f x)\n        {\n            return new V3f(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Square(this V3f x)\n        {\n            return new V3f(Square(x.X), Square(x.Y), Square(x.Z));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pown(this V3f x, V3i y)\n        {\n            return new V3f(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pown(this V3f x, int y)\n        {\n            return new V3f(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pown(this float x, V3i y)\n        {\n            return new V3f(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this V3f x, V3f y)\n        {\n            return new V3f(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this V3f x, float y)\n        {\n            return new V3f(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Pow(this float x, V3f y)\n        {\n            return new V3f(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this V3f x, V3f y)\n        {\n            return new V3f(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this V3f x, float y)\n        {\n            return new V3f(Power(x.X, y), Power(x.Y, y), Power(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Power(this float x, V3f y)\n        {\n            return new V3f(Power(x, y.X), Power(x, y.Y), Power(x, y.Z));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Exp(this V3f x)\n        {\n            return new V3f(Exp(x.X), Exp(x.Y), Exp(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Log(this V3f x)\n        {\n            return new V3f(Log(x.X), Log(x.Y), Log(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Log2(this V3f x)\n        {\n            return new V3f(Log2(x.X), Log2(x.Y), Log2(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Log2Int(this V3f x)\n        {\n            return new V3i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Log10(this V3f x)\n        {\n            return new V3f(Log10(x.X), Log10(x.Y), Log10(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Log(this V3f x, float basis)\n        {\n            return new V3f(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f ModP(this V3f a, V3f b)\n        {\n            return new V3f(ModP(a.X, b.X), ModP(a.Y, b.Y), ModP(a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f PowerOfTwo(this V3f x)\n        {\n            return new V3f(PowerOfTwo(x.X), PowerOfTwo(x.Y), PowerOfTwo(x.Z));\n        }\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Applies Fun.Sin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Sin(this V3f x)\n        {\n            return new V3f(Sin(x.X), Sin(x.Y), Sin(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Cos(this V3f x)\n        {\n            return new V3f(Cos(x.X), Cos(x.Y), Cos(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Tan(this V3f x)\n        {\n            return new V3f(Tan(x.X), Tan(x.Y), Tan(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Asin(this V3f x)\n        {\n            return new V3f(Asin(x.X), Asin(x.Y), Asin(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.AsinClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f AsinClamped(this V3f x)\n        {\n            return new V3f(AsinClamped(x.X), AsinClamped(x.Y), AsinClamped(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Acos(this V3f x)\n        {\n            return new V3f(Acos(x.X), Acos(x.Y), Acos(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.AcosClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f AcosClamped(this V3f x)\n        {\n            return new V3f(AcosClamped(x.X), AcosClamped(x.Y), AcosClamped(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Atan(this V3f x)\n        {\n            return new V3f(Atan(x.X), Atan(x.Y), Atan(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Atan2(V3f y, V3f x)\n        {\n            return new V3f(Atan2(y.X, x.X), Atan2(y.Y, x.Y), Atan2(y.Z, x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.FastAtan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f FastAtan2(V3f y, V3f x)\n        {\n            return new V3f(FastAtan2(y.X, x.X), FastAtan2(y.Y, x.Y), FastAtan2(y.Z, x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Sinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Sinh(this V3f x)\n        {\n            return new V3f(Sinh(x.X), Sinh(x.Y), Sinh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Cosh(this V3f x)\n        {\n            return new V3f(Cosh(x.X), Cosh(x.Y), Cosh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Tanh(this V3f x)\n        {\n            return new V3f(Tanh(x.X), Tanh(x.Y), Tanh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Asinh(this V3f x)\n        {\n            return new V3f(Asinh(x.X), Asinh(x.Y), Asinh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Acosh(this V3f x)\n        {\n            return new V3f(Acosh(x.X), Acosh(x.Y), Acosh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Atanh(this V3f x)\n        {\n            return new V3f(Atanh(x.X), Atanh(x.Y), Atanh(x.Z));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Step(this V3f x, V3f edge)\n        {\n            return new V3f(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Step(this V3f x, float edge)\n        {\n            return new V3f(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Linearstep(this V3f x, V3f edge0, V3f edge1)\n        {\n            return new V3f(Linearstep(x.X, edge0.X, edge1.X), Linearstep(x.Y, edge0.Y, edge1.Y), Linearstep(x.Z, edge0.Z, edge1.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Linearstep(this V3f x, float edge0, float edge1)\n        {\n            return new V3f(Linearstep(x.X, edge0, edge1), Linearstep(x.Y, edge0, edge1), Linearstep(x.Z, edge0, edge1));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Smoothstep(this V3f x, V3f edge0, V3f edge1)\n        {\n            return new V3f(Smoothstep(x.X, edge0.X, edge1.X), Smoothstep(x.Y, edge0.Y, edge1.Y), Smoothstep(x.Z, edge0.Z, edge1.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Smoothstep(this V3f x, float edge0, float edge1)\n        {\n            return new V3f(Smoothstep(x.X, edge0, edge1), Smoothstep(x.Y, edge0, edge1), Smoothstep(x.Z, edge0, edge1));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Lerp(this float t, V3f a, V3f b)\n        {\n            return new V3f(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Lerp(this V3f t, V3f a, V3f b)\n        {\n            return new V3f(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f InvLerp(this V3f y, V3f a, V3f b)\n        {\n            return new V3f(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatToBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i FloatToBits(this V3f x)\n        {\n            return new V3i(FloatToBits(x.X), FloatToBits(x.Y), FloatToBits(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.FloatToUnsignedBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3ui FloatToUnsignedBits(this V3f x)\n        {\n            return new V3ui(FloatToUnsignedBits(x.X), FloatToUnsignedBits(x.Y), FloatToUnsignedBits(x.Z));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V3f a, V3f b, float tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within\n        /// Constant{float}.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V3f a, V3f b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V3f v, float epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(V3f v)\n            => v.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"V3f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(V3f v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V3f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(V3f v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V3f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(V3f v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V3f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(V3f v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"V3f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(V3f v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts the angles given in degrees to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f RadiansFromDegrees(this V3f degrees)\n            => new V3f(\n                   RadiansFromDegrees(degrees.X), \n                   RadiansFromDegrees(degrees.Y), \n                   RadiansFromDegrees(degrees.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f RadiansFromGons(this V3f gons)\n            => new V3f(\n                   RadiansFromGons(gons.X), \n                   RadiansFromGons(gons.Y), \n                   RadiansFromGons(gons.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f DegreesFromRadians(this V3f radians)\n            => new V3f(\n                   DegreesFromRadians(radians.X), \n                   DegreesFromRadians(radians.Y), \n                   DegreesFromRadians(radians.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f DegreesFromGons(this V3f gons)\n            => new V3f(\n                   DegreesFromGons(gons.X), \n                   DegreesFromGons(gons.Y), \n                   DegreesFromGons(gons.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GonsFromRadians(this V3f radians)\n            => new V3f(\n                   GonsFromRadians(radians.X), \n                   GonsFromRadians(radians.Y), \n                   GonsFromRadians(radians.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in degrees to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f GonsFromDegrees(this V3f degrees)\n            => new V3f(\n                   GonsFromDegrees(degrees.X), \n                   GonsFromDegrees(degrees.Y), \n                   GonsFromDegrees(degrees.Z)\n               );\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LengthSquared(V3f v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Length(V3f v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Normalizes the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref V3f v)\n        {\n            var s = v.Length; if (s == 0) return;\n            s = 1 / s;\n            v.X *= s;\n            v.Y *= s;\n            v.Z *= s;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Normalized(V3f v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm1(V3f v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm2(V3f v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMax(V3f v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMin(V3f v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(this V3f v, float p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceSquared(this V3f a, V3f b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y) + Fun.Square(b.Z - a.Z);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(this V3f a, V3f b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance1(this V3f a, V3f b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y) + Fun.Abs(b.Z - a.Z);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(this V3f a, V3f b, float p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p) + Fun.Abs(b.Z - a.Z).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceMax(this V3f a, V3f b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceMin(this V3f a, V3f b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToLine(\n                this V3f query, V3f p0, V3f p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            if (t <= 0) { return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToInfiniteLine(\n                this V3f query, V3f p0, V3f p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToLine(\n                this V3f query, V3f p0, V3f p1, out float t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            if (t <= 0) { t = 0; return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { t = 1; return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToInfiniteLine(\n                this V3f query, V3f p0, V3f p1, out float t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Gets a copy of the given vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Reciprocal(V3f v)\n            => v.Reciprocal;\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V3f v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n            v.Z = -v.Z;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 3x3 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33f Outer(this V3f a, V3f b)\n        {\n            return new M33f(\n                        a.X * b.X, a.X * b.Y, a.X * b.Z, \n                        a.Y * b.X, a.Y * b.Y, a.Y * b.Z, \n                        a.Z * b.X, a.Z * b.Y, a.Z * b.Z);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Dot(this V3f a, V3f b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        /// <summary>\n        /// Returns the skew-symmetric \"cross\" matrix (A^T = -A) of the vector v.\n        /// </summary>\n        public static M33f CrossMatrix(this V3f v)\n        {\n            return new M33f(0, -v.Z, +v.Y,\n                            +v.Z, 0, -v.X,\n                            -v.Y, +v.X, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V3f v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeZ;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the reflection direction of the given vector v (pointing to the surface) for the given normal (should be normalized).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Reflect(this V3f v, V3f normal)\n        {\n            return v - 2 * v.Dot(normal) * normal;\n        }\n\n        /// <summary>\n        /// Returns the refraction direction of the given vector v (pointing to the surface) for the given normal and ratio of refraction indices (n_out / n_in).\n        /// Both the input vectors should be normalized.\n        /// Returns a zero-vector in case of total internal reflection.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Refract(this V3f v, V3f normal, float eta)\n        {\n            var t = v.Dot(normal);\n            var k = 1 - eta * eta * (1 - t * t);\n\n            if (k < 0)\n            {\n                return V3f.Zero;\n            }\n            else\n            {\n                return eta * v - (eta * t + Fun.Sqrt(k)) * normal;\n            }\n        }\n\n        /// <summary>\n        /// Returns the cross product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f Cross(this V3f a, V3f b)\n        {\n            return new V3f(\n            a.Y * b.Z - a.Z * b.Y,\n            a.Z * b.X - a.X * b.Z,\n            a.X * b.Y - a.Y * b.X\n            );\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3f a, V3f b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3f v, float s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, V3f v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3f a, V3f b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3f v, float s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, V3f v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3f a, V3f b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3f v, float s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, V3f v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3f a, V3f b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3f v, float s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, V3f v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3f a, V3f b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3f v, float s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, V3f v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3f a, V3f b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3f v, float s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, V3f v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3f a, V3f b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3f v, float s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, V3f v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3f a, V3f b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3f v, float s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, V3f v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3f a, V3f b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3f v, float s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, V3f v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3f a, V3f b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3f v, float s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, V3f v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3f a, V3f b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3f v, float s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, V3f v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3f a, V3f b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3f v, float s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, V3f v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V3f v0, V3f v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MinElement(V3f v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V3f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MaxElement(V3f v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region Axis aligned normal\n\n        /// <summary>\n        /// Returns an arbitrary normal vector, which\n        /// is also normal to either the x, y or z-axis.\n        /// </summary>\n        public static V3f AxisAlignedNormal(this V3f v)\n        {\n            V3f vector;\n            float x = v.X.Abs();\n            float y = v.Y.Abs();\n            float z = v.Z.Abs();\n\n            if (x < y)\n            {\n                if (x < z)\n                    vector = V3f.XAxis;\n                else\n                    vector = V3f.ZAxis;\n            }\n            else\n            {\n                if (y < z)\n                    vector = V3f.YAxis;\n                else\n                    vector = V3f.ZAxis;\n            }\n\n            return v.Cross(vector).Normalized;\n        }\n\n        #endregion\n\n        #region Angle between two vectors\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleBetweenFast(this V3f x, V3f y)\n        {\n            return Fun.AcosClamped(x.Dot(y));\n        }\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians using a numerically stable algorithm.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        // https://scicomp.stackexchange.com/a/27769\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleBetween(this V3f x, V3f y)\n        {\n            var a = x + y;\n            var b = x - y;\n            return 2 * Fun.Atan2(b.Length, a.Length);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V3f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V3f v, float epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V3f v, float epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(V3f v)\n            => v.AnyFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(V3f v)\n            => v.AllFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(V3f v)\n            => v.AnyNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(V3f v)\n            => v.AllNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(V3f v)\n            => v.AnyInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(V3f v)\n            => v.AllInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(V3f v)\n            => v.AnyPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(V3f v)\n            => v.AllPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(V3f v)\n            => v.AnyNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(V3f v)\n            => v.AllNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(V3f v)\n            => v.AnyTiny;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(V3f v)\n            => v.AllTiny;\n\n        #endregion\n\n        #region Linear Combination\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LinCom(V3f p0, V3f p1, ref Tup2<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LinCom(V3f p0, V3f p1, V3f p2, ref Tup3<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LinCom(V3f p0, V3f p1, V3f p2, V3f p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LinCom(V3f p0, V3f p1, V3f p2, V3f p3, V3f p4, ref Tup5<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LinCom(V3f p0, V3f p1, V3f p2, V3f p3, V3f p4, V3f p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f LinCom(V3f p0, V3f p1, V3f p2, V3f p3, V3f p4, V3f p5, V3f p6, ref Tup7<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V3f[] pointArray, V3f point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V3f[] array, int start, int count,\n                V3f point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V3f> pointSelector, V3f point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V3f[] pointArray, V3f point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V3f[] array, long start, long count,\n                V3f point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V3f> pointSelector, V3f point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V3f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V3f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V3f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V3f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V3f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V3f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V3f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V3f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V3f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V3f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V3f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V3f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V3f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V3f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V3f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V3f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V3f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V3f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static float[] CopyCoord(this V3f[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        public static V3f WeightedSum(\n                this V3f[] vectorArray, float[] weightArray)\n        {\n            var r = V3f.Zero;\n            var count = vectorArray.LongLength;\n            for (long i = 0; i < count; i++) r += vectorArray[i] * weightArray[i];\n            return r;\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV3fExtensions\n    {\n        #region IRandomUniform extensions for V3f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of a V3f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3f(this IRandomUniform rnd)\n        {\n            return new V3f(rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of a V3f\n        /// vector within the given Box3f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3f(this IRandomUniform rnd, Box3f box)\n        {\n            return new V3f(box.Min.X + rnd.UniformFloat() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformFloat() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformFloat() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of a V3f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3fClosed(this IRandomUniform rnd)\n        {\n            return new V3f(rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of a V3f\n        /// vector within the given Box3f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3fClosed(this IRandomUniform rnd, Box3f box)\n        {\n            return new V3f(box.Min.X + rnd.UniformFloatClosed() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformFloatClosed() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformFloatClosed() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of a V3f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3fOpen(this IRandomUniform rnd)\n        {\n            return new V3f(rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of a V3f\n        /// vector within the given Box3f.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3fOpen(this IRandomUniform rnd, Box3f box)\n        {\n            return new V3f(box.Min.X + rnd.UniformFloatOpen() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformFloatOpen() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformFloatOpen() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the surface of the unit sphere).\n        /// Note however, that the returned vector will never be equal to\n        /// [0, 0, -1]. Uses UniformFloat() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3fDirection(this IRandomUniform rnd)\n        {\n            float phi = rnd.UniformFloat() * ConstantF.PiTimesTwo;\n            float z = 1 - rnd.UniformFloat() * 2;\n            float s = Fun.Sqrt(1 - z * z);\n            return new V3f(Fun.Cos(phi) * s, Fun.Sin(phi) * s, z);\n        }\n\n        /// <summary>\n        /// Uniform vector in the closed unit sphere (i.e vectors to\n        /// the surface of the sphere may be generated). Uses UniformV3fClosed() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3fClosedSphere(this IRandomUniform rnd)\n        {\n            float r2;\n            V3f p;\n            V3f c_shift = -V3f.Half;\n            do\n            {\n                p = (rnd.UniformV3fClosed() + c_shift) * 2;\n                r2 = p.LengthSquared;\n            }\n            while (r2 >= 1);\n            return p;\n        }\n\n        /// <summary>\n        /// Uniform vector inside the open unit sphere (i.e. no vector\n        /// ends on the surface of the sphere). Uses UniformV3fOpen() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3f UniformV3fOpenSphere(this IRandomUniform rnd)\n        {\n            float r2;\n            V3f p;\n            V3f c_shift = -V3f.Half;\n            do\n            {\n                p = (rnd.UniformV3fOpen() + c_shift) * 2;\n                r2 = p.LengthSquared;\n            }\n            while (r2 >= 1);\n            return p;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V3d\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V3d : IVector<double>, ISize3d, IFormattable, IEquatable<V3d>\n    {\n        [DataMember]\n        public double X;\n        [DataMember]\n        public double Y;\n        [DataMember]\n        public double Z;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(int x, int y, int z)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(int v)\n        {\n            X = (double)v;\n            Y = (double)v;\n            Z = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(int[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n            Z = (double)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(int[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n            Z = (double)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(int a, V2i b)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2i a, int b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(uint x, uint y, uint z)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(uint v)\n        {\n            X = (double)v;\n            Y = (double)v;\n            Z = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(uint[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n            Z = (double)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(uint[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n            Z = (double)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(uint a, V2ui b)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2ui a, uint b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(long x, long y, long z)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(long v)\n        {\n            X = (double)v;\n            Y = (double)v;\n            Z = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(long[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n            Z = (double)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(long[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n            Z = (double)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(long a, V2l b)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2l a, long b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(float x, float y, float z)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(float v)\n        {\n            X = (double)v;\n            Y = (double)v;\n            Z = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(float[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n            Z = (double)a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(float[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n            Z = (double)a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(float a, V2f b)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2f a, float b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(double x, double y, double z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(double v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(double[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(double[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(double a, V2d b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2d a, double b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(Func<int, double> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;double&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 3.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(IVector<double> v)\n            : this(v[0], v[1], v[2])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V2d v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V3i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V3ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V3l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V3f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V3d v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V4i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V4ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V4l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V4f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// v.W is ignored.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(V4d v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C3b c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C3us c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C3ui c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C3f c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C3d c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C4b c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C4us c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C4ui c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C4f c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V3d(C4d c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V2i v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V2ui v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V2l v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V2f v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V2d v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V3i v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V3ui v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V3l v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V3f v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V4i v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V4ui v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V4l v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V4f v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(V4d v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V3d v)\n            => new int[] { (int)v.X, (int)v.Y, (int)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(int[] v)\n            => new V3d((double)v[0], (double)v[1], (double)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V3d v)\n            => new uint[] { (uint)v.X, (uint)v.Y, (uint)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(uint[] v)\n            => new V3d((double)v[0], (double)v[1], (double)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V3d v)\n            => new long[] { (long)v.X, (long)v.Y, (long)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(long[] v)\n            => new V3d((double)v[0], (double)v[1], (double)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V3d v)\n            => new float[] { (float)v.X, (float)v.Y, (float)v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(float[] v)\n            => new V3d((double)v[0], (double)v[1], (double)v[2]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V3d v)\n            => new double[] { v.X, v.Y, v.Z };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(double[] v)\n            => new V3d(v[0], v[1], v[2]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C3b v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C3us v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C3ui v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C3f v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C3d v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C4b v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// The alpha channel is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C4us v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// The alpha channel is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V3d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C4ui v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// The alpha channel is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C4f v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4f\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V3d(C4d v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V3d\"/> vector to a <see cref=\"C4d\"/> color.\n        /// The alpha channel is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToFloorV3l()\n            => new V3l((long)Fun.Floor(X), (long)Fun.Floor(Y), (long)Fun.Floor(Z));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToCeilingV3l()\n            => new V3l((long)Fun.Ceiling(X), (long)Fun.Ceiling(Y), (long)Fun.Ceiling(Z));\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2iInhomo()\n        {\n            var div = 1 / Z;\n            return new V2i(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2uiInhomo()\n        {\n            var div = 1 / Z;\n            return new V2ui(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2lInhomo()\n        {\n            var div = 1 / Z;\n            return new V2l(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2fInhomo()\n        {\n            var div = 1 / Z;\n            return new V2f(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2dInhomo()\n        {\n            var div = 1 / Z;\n            return new V2d(X * div, Y * div);\n        }\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4iHomo()\n            => new V4i(X, Y, Z, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4uiHomo()\n            => new V4ui(X, Y, Z, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4lHomo()\n            => new V4l(X, Y, Z, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4fHomo()\n            => new V4f(X, Y, Z, 1);\n\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4dHomo()\n            => new V4d(X, Y, Z, 1);\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<double, int> element_fun)\n            => new V3i(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i Copy(Func<double, int, int> element_index_fun)\n            => new V3i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n            array[start + 2] = (int)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<double, uint> element_fun)\n            => new V3ui(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui Copy(Func<double, int, uint> element_index_fun)\n            => new V3ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n            array[start + 2] = (uint)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<double, long> element_fun)\n            => new V3l(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l Copy(Func<double, int, long> element_index_fun)\n            => new V3l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n            array[start + 2] = (long)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<double, float> element_fun)\n            => new V3f(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f Copy(Func<double, int, float> element_index_fun)\n            => new V3f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n            array[start + 2] = (float)Z;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<double, double> element_fun)\n            => new V3d(element_fun(X), element_fun(Y), element_fun(Z));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d Copy(Func<double, int, double> element_index_fun)\n            => new V3d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double[] ToArray()\n            => new double[] { X, Y, Z };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y ? (X >= Z ? 0 : 2) : (Y >= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y ? (X <= Z ? 0 : 2) : (Y <= Z ? 1 : 2);\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly double MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly double MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z);\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) || Fun.IsFinite(Y) || Fun.IsFinite(Z);\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) && Fun.IsFinite(Y) && Fun.IsFinite(Z);\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(X) || double.IsNaN(Y) || double.IsNaN(Z);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(X) && double.IsNaN(Y) && double.IsNaN(Z);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(X) || double.IsInfinity(Y) || double.IsInfinity(Z);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(X) && double.IsInfinity(Y) && double.IsInfinity(Z);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(X) || double.IsPositiveInfinity(Y) || double.IsPositiveInfinity(Z);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(X) && double.IsPositiveInfinity(Y) && double.IsPositiveInfinity(Z);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(X) || double.IsNegativeInfinity(Y) || double.IsNegativeInfinity(Z);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(X) && double.IsNegativeInfinity(Y) && double.IsNegativeInfinity(Z);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) || Fun.IsTiny(Y) || Fun.IsTiny(Z);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) && Fun.IsTiny(Y) && Fun.IsTiny(Z);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the vector is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the vector are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 3;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V3d Zero\n        {\n            get { return new V3d(0, 0, 0); }\n        }\n\n        /// <summary>\n        /// All elements half.\n        /// </summary>\n        public static V3d Half\n        {\n            get { return new V3d(0.5, 0.5, 0.5); }\n        }\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V3d One\n        {\n            get { return new V3d(1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V3d MaxValue\n        {\n            get { return new V3d(Constant<double>.ParseableMaxValue, Constant<double>.ParseableMaxValue, Constant<double>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V3d MinValue\n        {\n            get { return new V3d(Constant<double>.ParseableMinValue, Constant<double>.ParseableMinValue, Constant<double>.ParseableMinValue); }\n        }\n\n         /// <summary>\n        /// All elements set to negative infinity.\n        /// </summary>\n        public static V3d NegativeInfinity\n        {\n            get { return new V3d(double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to positive infinity.\n        /// </summary>\n        public static V3d PositiveInfinity\n        {\n            get { return new V3d(double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to NaN.\n        /// </summary>\n        public static V3d NaN\n        {\n            get { return new V3d(double.NaN, double.NaN, double.NaN); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V3d XAxis\n        {\n            get { return new V3d(1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V3d YAxis\n        {\n            get { return new V3d(0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V3d ZAxis\n        {\n            get { return new V3d(0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V3d, double>[] SelectorArray =\n            new Func<V3d, double>[] { v => v.X, v => v.Y, v => v.Z };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V3d, int, double> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V3d, int, double> Setter =\n            (ref V3d v, int i, double s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V3d, long, double> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V3d, long, double> LongSetter =\n            (ref V3d v, long i, double s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromV3i(V3i v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromV3ui(V3ui v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromV3l(V3l v)\n            => new V3d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromV3f(V3f v)\n            => new V3d(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC3b(C3b c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC3us(C3us c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC3ui(C3ui c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC3f(C3f c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC3d(C3d c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC4b(C4b c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC4us(C4us c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC4ui(C4ui c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC4f(C4f c) => new V3d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromC4d(C4d c) => new V3d(c);\n\n        private static readonly V3d[] s_fromCubeCode =\n            new V3d[] { -V3d.XAxis, -V3d.YAxis, -V3d.ZAxis,\n                        V3d.XAxis, V3d.YAxis, V3d.ZAxis };\n\n        /// <summary>\n        /// Return the vector for the supplied cube face code.\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FromCubeFaceCode(int i) { return s_fromCubeCode[i]; }\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly double LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly double Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y) + Fun.Abs(Z); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly double NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly double NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V3d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V3d.Zero;\n                s = 1 / s;\n                return new V3d(X * s, Y * s, Z * s);\n            }\n        }\n\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered cube with side length 2.\n        /// </summary>\n        public readonly V3d CubeMapped\n        {\n            get\n            {\n                double x = Fun.Abs(X);\n                double y = Fun.Abs(Y);\n                double z = Fun.Abs(Z);\n                if (x > y)\n                {\n                    if (x > z)\n                    {\n                        double s = 1 / x;\n                        return new V3d(Fun.Sign(X), Y * s, Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z;\n                        return new V3d(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n                else\n                {\n                    if (y > z)\n                    {\n                        double s = 1 / y;\n                        return new V3d(X * s, Fun.Sign(Y), Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z;\n                        return new V3d(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered cube with side length 2.\n        /// The out parameter face indicate which face the vector was mapped to:\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        /// </summary>\n        public readonly V3d CubeMappedOnFace(out int face)\n        {\n                double x = Fun.Abs(X);\n                double y = Fun.Abs(Y);\n                double z = Fun.Abs(Z);\n                if (x > y)\n                {\n                    if (x > z)\n                    {\n                        double s = 1 / x; face = X < 0 ? 0 : 3;\n                        return new V3d(Fun.Sign(X), Y * s, Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z; face = Z < 0 ? 2 : 5;\n                        return new V3d(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n                else\n                {\n                    if (y > z)\n                    {\n                        double s = 1 / y; face = Y < 0 ? 1 : 4;\n                        return new V3d(X * s, Fun.Sign(Y), Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z; face = Z < 0 ? 2 : 5;\n                        return new V3d(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n        }\n\n        /// <summary>\n        /// Return an index for the cube face onto which the vector points.\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        /// </summary>\n        public readonly int CubeFaceCode\n        {\n            get\n            {\n                double x = Fun.Abs(X);\n                double y = Fun.Abs(Y);\n                double z = Fun.Abs(Z);\n                int c;\n                double v;\n                if (x > y)\n                {\n                    if (x > z) { c = 0; v = X; } else { c = 2; v = Z; }\n                }\n                else\n                {\n                    if (y > z) { c = 1; v = Y; } else { c = 2; v = Z; }\n                }\n                return v < 0 ? c : c + 3;\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Abs(V3d v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Floor(V3d v)\n            => v.Floor();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Ceiling(V3d v)\n            => v.Ceiling();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Round(V3d v)\n            => v.Round();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Truncate(V3d v)\n            => v.Truncate();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Acos(V3d v)\n            => Fun.Acos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Acoshb(V3d v)\n            => Fun.Acosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cos(V3d v)\n            => Fun.Cos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cosh(V3d v)\n            => Fun.Cosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Asin(V3d v)\n            => Fun.Asin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Asinhb(V3d v)\n            => Fun.Asinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sin(V3d v)\n            => Fun.Sin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sinh(V3d v)\n            => Fun.Sinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Atan(V3d v)\n            => Fun.Atan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Atanhb(V3d v)\n            => Fun.Atanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Atan2(V3d a, V3d b)\n            => Fun.Atan2(a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Tan(V3d v)\n            => Fun.Tan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Tanh(V3d v)\n            => Fun.Tanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sqrt(V3d v)\n            => Fun.Sqrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d CubeRoot(V3d v)\n            => Fun.Cbrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Exp(V3d v)\n            => Fun.Exp(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(V3d v)\n            => Fun.Log(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LogBinary(V3d v)\n            => Fun.Log2(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log10(V3d v)\n            => Fun.Log10(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d CopySgn(V3d value, V3d sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d CopySgn(V3d value, double sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LinearInterp(double t, V3d a, V3d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LinearInterp(V3d t, V3d a, V3d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Min(V3d v0, V3d v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Min(V3d v, double x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Max(V3d v0, V3d v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Max(V3d v, double x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Saturate(V3d v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d DivideByInt(V3d v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator -(V3d v)\n            => new V3d(-v.X, -v.Y, -v.Z);\n\n        /// <summary>\n        /// Gets a copy of this vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        public readonly V3d Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V3d(1 / X, 1 / Y, 1 / Z); }\n        }\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator +(V3d a, V3d b)\n            => new V3d(a.X + b.X, a.Y + b.Y, a.Z + b.Z);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator +(V3d v, double s)\n            => new V3d(v.X + s, v.Y + s, v.Z + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator +(double s, V3d v)\n            => new V3d(s + v.X, s + v.Y, s + v.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator -(V3d a, V3d b)\n            => new V3d(a.X - b.X, a.Y - b.Y, a.Z - b.Z);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator -(V3d v, double s)\n            => new V3d(v.X - s, v.Y - s, v.Z - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator -(double s, V3d v)\n            => new V3d(s - v.X, s - v.Y, s - v.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(V3d a, V3d b)\n            => new V3d(a.X * b.X, a.Y * b.Y, a.Z * b.Z);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(V3d v, double s)\n            => new V3d(v.X * s, v.Y * s, v.Z * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator *(double s, V3d v)\n            => new V3d(s * v.X, s * v.Y, s * v.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator /(V3d a, V3d b)\n            => new V3d(a.X / b.X, a.Y / b.Y, a.Z / b.Z);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator /(V3d v, double s)\n            => new V3d(v.X / s, v.Y / s, v.Z / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator /(double s, V3d v)\n            => new V3d(s / v.X, s / v.Y, s / v.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator %(V3d a, V3d b)\n            => new V3d(a.X % b.X, a.Y % b.Y, a.Z % b.Z);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator %(V3d v, double s)\n            => new V3d(v.X % s, v.Y % s, v.Z % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d operator %(double s, V3d v)\n            => new V3d(s % v.X, s % v.Y, s % v.Z);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3d a, V3d b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V3d v, double s)\n        {\n            return v.X == s && v.Y == s && v.Z == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(double s, V3d v)\n        {\n            return s == v.X && s == v.Y && s == v.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3d a, V3d b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V3d v, double s)\n        {\n            return v.X != s || v.Y != s || v.Z != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(double s, V3d v)\n        {\n            return s != v.X || s != v.Y || s != v.Z;\n        }\n\n        #endregion\n\n        #region IEquatable<V3d> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V3d other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V3d o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V3d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V3d(\n                double.Parse(x[0], CultureInfo.InvariantCulture), \n                double.Parse(x[1], CultureInfo.InvariantCulture), \n                double.Parse(x[2], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V3d Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<double>.Parse, V3d.Setter);\n        }\n\n        public static V3d Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<double>.Parse, V3d.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OX => new V2d(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OY => new V2d(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OZ => new V2d(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IX => new V2d(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IY => new V2d(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IZ => new V2d(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NX => new V2d(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NY => new V2d(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NZ => new V2d(-1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XO => new V2d(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XI => new V2d(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XN => new V2d(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XX => new V2d(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d XY\n        {\n            readonly get => new V2d(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d XZ\n        {\n            readonly get => new V2d(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YO => new V2d(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YI => new V2d(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YN => new V2d(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d YX\n        {\n            readonly get => new V2d(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YY => new V2d(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d YZ\n        {\n            readonly get => new V2d(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d ZO => new V2d(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d ZI => new V2d(Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d ZN => new V2d(Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d ZX\n        {\n            readonly get => new V2d(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d ZY\n        {\n            readonly get => new V2d(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d ZZ => new V2d(Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d OOO => new V3d(0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d OOI => new V3d(0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d OON => new V3d(0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOX => new V3d(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOY => new V3d(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOZ => new V3d(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d OIO => new V3d(0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d OII => new V3d(0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d OPN => new V3d(0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIX => new V3d(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIY => new V3d(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIZ => new V3d(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d ONO => new V3d(0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d ONP => new V3d(0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d ONN => new V3d(0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONX => new V3d(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONY => new V3d(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONZ => new V3d(0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXO => new V3d(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXI => new V3d(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXN => new V3d(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXX => new V3d(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXY => new V3d(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXZ => new V3d(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYO => new V3d(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYI => new V3d(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYN => new V3d(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYX => new V3d(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYY => new V3d(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYZ => new V3d(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZO => new V3d(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZI => new V3d(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZN => new V3d(0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZX => new V3d(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZY => new V3d(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZZ => new V3d(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d IOO => new V3d(1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d IOI => new V3d(1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d PON => new V3d(1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOX => new V3d(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOY => new V3d(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOZ => new V3d(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d IIO => new V3d(1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d III => new V3d(1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d PPN => new V3d(1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIX => new V3d(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIY => new V3d(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIZ => new V3d(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d PNO => new V3d(1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d PNP => new V3d(1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d PNN => new V3d(1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNX => new V3d(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNY => new V3d(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNZ => new V3d(1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXO => new V3d(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXI => new V3d(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PXN => new V3d(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXX => new V3d(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXY => new V3d(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXZ => new V3d(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYO => new V3d(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYI => new V3d(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PYN => new V3d(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYX => new V3d(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYY => new V3d(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYZ => new V3d(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZO => new V3d(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZI => new V3d(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PZN => new V3d(1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZX => new V3d(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZY => new V3d(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZZ => new V3d(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NOO => new V3d(-1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NOP => new V3d(-1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NON => new V3d(-1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOX => new V3d(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOY => new V3d(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOZ => new V3d(-1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NPO => new V3d(-1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NPP => new V3d(-1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NPN => new V3d(-1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPX => new V3d(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPY => new V3d(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPZ => new V3d(-1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NNO => new V3d(-1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NNP => new V3d(-1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V3d NNN => new V3d(-1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNX => new V3d(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNY => new V3d(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNZ => new V3d(-1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXO => new V3d(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXP => new V3d(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXN => new V3d(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXX => new V3d(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXY => new V3d(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXZ => new V3d(-1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYO => new V3d(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYP => new V3d(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYN => new V3d(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYX => new V3d(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYY => new V3d(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYZ => new V3d(-1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZO => new V3d(-1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZP => new V3d(-1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZN => new V3d(-1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZX => new V3d(-1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZY => new V3d(-1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZZ => new V3d(-1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOO => new V3d(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOI => new V3d(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XON => new V3d(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOX => new V3d(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOY => new V3d(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOZ => new V3d(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIO => new V3d(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XII => new V3d(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XPN => new V3d(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIX => new V3d(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIY => new V3d(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIZ => new V3d(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNO => new V3d(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNP => new V3d(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNN => new V3d(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNX => new V3d(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNY => new V3d(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNZ => new V3d(X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXO => new V3d(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXI => new V3d(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXN => new V3d(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXX => new V3d(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXY => new V3d(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXZ => new V3d(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYO => new V3d(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYI => new V3d(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYN => new V3d(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYX => new V3d(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYY => new V3d(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d XYZ\n        {\n            readonly get => new V3d(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZO => new V3d(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZI => new V3d(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZN => new V3d(X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZX => new V3d(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d XZY\n        {\n            readonly get => new V3d(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZZ => new V3d(X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOO => new V3d(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOI => new V3d(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YON => new V3d(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOX => new V3d(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOY => new V3d(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOZ => new V3d(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIO => new V3d(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YII => new V3d(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YPN => new V3d(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIX => new V3d(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIY => new V3d(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIZ => new V3d(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNO => new V3d(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNP => new V3d(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNN => new V3d(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNX => new V3d(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNY => new V3d(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNZ => new V3d(Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXO => new V3d(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXI => new V3d(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXN => new V3d(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXX => new V3d(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXY => new V3d(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d YXZ\n        {\n            readonly get => new V3d(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYO => new V3d(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYI => new V3d(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYN => new V3d(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYX => new V3d(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYY => new V3d(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYZ => new V3d(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZO => new V3d(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZI => new V3d(Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZN => new V3d(Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d YZX\n        {\n            readonly get => new V3d(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZY => new V3d(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZZ => new V3d(Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOO => new V3d(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOI => new V3d(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZON => new V3d(Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOX => new V3d(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOY => new V3d(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOZ => new V3d(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIO => new V3d(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZII => new V3d(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZPN => new V3d(Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIX => new V3d(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIY => new V3d(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIZ => new V3d(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNO => new V3d(Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNP => new V3d(Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNN => new V3d(Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNX => new V3d(Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNY => new V3d(Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNZ => new V3d(Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXO => new V3d(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXI => new V3d(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXN => new V3d(Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXX => new V3d(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d ZXY\n        {\n            readonly get => new V3d(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXZ => new V3d(Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYO => new V3d(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYI => new V3d(Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYN => new V3d(Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d ZYX\n        {\n            readonly get => new V3d(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYY => new V3d(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYZ => new V3d(Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZO => new V3d(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZI => new V3d(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZN => new V3d(Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZX => new V3d(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZY => new V3d(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZZ => new V3d(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOX => new V4d(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOY => new V4d(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOZ => new V4d(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIX => new V4d(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIY => new V4d(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIZ => new V4d(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONX => new V4d(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONY => new V4d(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONZ => new V4d(0, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXO => new V4d(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXI => new V4d(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXN => new V4d(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXX => new V4d(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXY => new V4d(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXZ => new V4d(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYO => new V4d(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYI => new V4d(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYN => new V4d(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYX => new V4d(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYY => new V4d(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYZ => new V4d(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZO => new V4d(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZI => new V4d(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZN => new V4d(0, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZX => new V4d(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZY => new V4d(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZZ => new V4d(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOX => new V4d(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOY => new V4d(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOZ => new V4d(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIX => new V4d(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIY => new V4d(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIZ => new V4d(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNX => new V4d(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNY => new V4d(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNZ => new V4d(0, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXO => new V4d(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXI => new V4d(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPXN => new V4d(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXX => new V4d(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXY => new V4d(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXZ => new V4d(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYO => new V4d(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYI => new V4d(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPYN => new V4d(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYX => new V4d(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYY => new V4d(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYZ => new V4d(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZO => new V4d(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZI => new V4d(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPZN => new V4d(0, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZX => new V4d(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZY => new V4d(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZZ => new V4d(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOX => new V4d(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOY => new V4d(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOZ => new V4d(0, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPX => new V4d(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPY => new V4d(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPZ => new V4d(0, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNX => new V4d(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNY => new V4d(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNZ => new V4d(0, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXO => new V4d(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXP => new V4d(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXN => new V4d(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXX => new V4d(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXY => new V4d(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXZ => new V4d(0, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYO => new V4d(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYP => new V4d(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYN => new V4d(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYX => new V4d(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYY => new V4d(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYZ => new V4d(0, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZO => new V4d(0, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZP => new V4d(0, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZN => new V4d(0, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZX => new V4d(0, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZY => new V4d(0, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZZ => new V4d(0, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOO => new V4d(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOI => new V4d(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXON => new V4d(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOX => new V4d(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOY => new V4d(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOZ => new V4d(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIO => new V4d(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXII => new V4d(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXPN => new V4d(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIX => new V4d(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIY => new V4d(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIZ => new V4d(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNO => new V4d(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNP => new V4d(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNN => new V4d(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNX => new V4d(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNY => new V4d(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNZ => new V4d(0, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXO => new V4d(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXI => new V4d(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXN => new V4d(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXX => new V4d(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXY => new V4d(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXZ => new V4d(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYO => new V4d(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYI => new V4d(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYN => new V4d(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYX => new V4d(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYY => new V4d(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYZ => new V4d(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZO => new V4d(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZI => new V4d(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZN => new V4d(0, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZX => new V4d(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZY => new V4d(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZZ => new V4d(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOO => new V4d(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOI => new V4d(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYON => new V4d(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOX => new V4d(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOY => new V4d(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOZ => new V4d(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIO => new V4d(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYII => new V4d(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYPN => new V4d(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIX => new V4d(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIY => new V4d(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIZ => new V4d(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNO => new V4d(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNP => new V4d(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNN => new V4d(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNX => new V4d(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNY => new V4d(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNZ => new V4d(0, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXO => new V4d(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXI => new V4d(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXN => new V4d(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXX => new V4d(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXY => new V4d(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXZ => new V4d(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYO => new V4d(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYI => new V4d(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYN => new V4d(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYX => new V4d(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYY => new V4d(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYZ => new V4d(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZO => new V4d(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZI => new V4d(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZN => new V4d(0, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZX => new V4d(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZY => new V4d(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZZ => new V4d(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOO => new V4d(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOI => new V4d(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZON => new V4d(0, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOX => new V4d(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOY => new V4d(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOZ => new V4d(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIO => new V4d(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZII => new V4d(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZPN => new V4d(0, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIX => new V4d(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIY => new V4d(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIZ => new V4d(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNO => new V4d(0, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNP => new V4d(0, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNN => new V4d(0, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNX => new V4d(0, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNY => new V4d(0, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNZ => new V4d(0, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXO => new V4d(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXI => new V4d(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXN => new V4d(0, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXX => new V4d(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXY => new V4d(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXZ => new V4d(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYO => new V4d(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYI => new V4d(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYN => new V4d(0, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYX => new V4d(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYY => new V4d(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYZ => new V4d(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZO => new V4d(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZI => new V4d(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZN => new V4d(0, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZX => new V4d(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZY => new V4d(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZZ => new V4d(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOX => new V4d(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOY => new V4d(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOZ => new V4d(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIX => new V4d(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIY => new V4d(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIZ => new V4d(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONX => new V4d(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONY => new V4d(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONZ => new V4d(1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXO => new V4d(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXI => new V4d(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POXN => new V4d(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXX => new V4d(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXY => new V4d(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXZ => new V4d(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYO => new V4d(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYI => new V4d(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POYN => new V4d(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYX => new V4d(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYY => new V4d(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYZ => new V4d(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZO => new V4d(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZI => new V4d(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POZN => new V4d(1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZX => new V4d(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZY => new V4d(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZZ => new V4d(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOX => new V4d(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOY => new V4d(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOZ => new V4d(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIX => new V4d(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIY => new V4d(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIZ => new V4d(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNX => new V4d(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNY => new V4d(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNZ => new V4d(1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXO => new V4d(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXI => new V4d(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPXN => new V4d(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXX => new V4d(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXY => new V4d(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXZ => new V4d(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYO => new V4d(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYI => new V4d(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPYN => new V4d(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYX => new V4d(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYY => new V4d(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYZ => new V4d(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZO => new V4d(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZI => new V4d(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPZN => new V4d(1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZX => new V4d(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZY => new V4d(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZZ => new V4d(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOX => new V4d(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOY => new V4d(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOZ => new V4d(1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPX => new V4d(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPY => new V4d(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPZ => new V4d(1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNX => new V4d(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNY => new V4d(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNZ => new V4d(1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXO => new V4d(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXP => new V4d(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXN => new V4d(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXX => new V4d(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXY => new V4d(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXZ => new V4d(1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYO => new V4d(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYP => new V4d(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYN => new V4d(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYX => new V4d(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYY => new V4d(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYZ => new V4d(1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZO => new V4d(1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZP => new V4d(1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZN => new V4d(1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZX => new V4d(1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZY => new V4d(1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZZ => new V4d(1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOO => new V4d(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOI => new V4d(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXON => new V4d(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOX => new V4d(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOY => new V4d(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOZ => new V4d(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIO => new V4d(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXII => new V4d(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXPN => new V4d(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIX => new V4d(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIY => new V4d(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIZ => new V4d(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNO => new V4d(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNP => new V4d(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNN => new V4d(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNX => new V4d(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNY => new V4d(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNZ => new V4d(1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXO => new V4d(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXI => new V4d(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXXN => new V4d(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXX => new V4d(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXY => new V4d(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXZ => new V4d(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYO => new V4d(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYI => new V4d(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXYN => new V4d(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYX => new V4d(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYY => new V4d(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYZ => new V4d(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZO => new V4d(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZI => new V4d(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXZN => new V4d(1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZX => new V4d(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZY => new V4d(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZZ => new V4d(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOO => new V4d(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOI => new V4d(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYON => new V4d(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOX => new V4d(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOY => new V4d(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOZ => new V4d(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIO => new V4d(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYII => new V4d(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYPN => new V4d(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIX => new V4d(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIY => new V4d(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIZ => new V4d(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNO => new V4d(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNP => new V4d(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNN => new V4d(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNX => new V4d(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNY => new V4d(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNZ => new V4d(1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXO => new V4d(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXI => new V4d(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYXN => new V4d(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXX => new V4d(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXY => new V4d(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXZ => new V4d(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYO => new V4d(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYI => new V4d(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYYN => new V4d(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYX => new V4d(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYY => new V4d(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYZ => new V4d(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZO => new V4d(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZI => new V4d(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYZN => new V4d(1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZX => new V4d(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZY => new V4d(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZZ => new V4d(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOO => new V4d(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOI => new V4d(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZON => new V4d(1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOX => new V4d(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOY => new V4d(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOZ => new V4d(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIO => new V4d(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZII => new V4d(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZPN => new V4d(1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIX => new V4d(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIY => new V4d(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIZ => new V4d(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNO => new V4d(1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNP => new V4d(1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNN => new V4d(1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNX => new V4d(1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNY => new V4d(1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNZ => new V4d(1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXO => new V4d(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXI => new V4d(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZXN => new V4d(1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXX => new V4d(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXY => new V4d(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXZ => new V4d(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYO => new V4d(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYI => new V4d(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZYN => new V4d(1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYX => new V4d(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYY => new V4d(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYZ => new V4d(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZO => new V4d(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZI => new V4d(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZZN => new V4d(1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZX => new V4d(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZY => new V4d(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZZ => new V4d(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOX => new V4d(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOY => new V4d(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOZ => new V4d(-1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPX => new V4d(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPY => new V4d(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPZ => new V4d(-1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONX => new V4d(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONY => new V4d(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONZ => new V4d(-1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXO => new V4d(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXP => new V4d(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXN => new V4d(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXX => new V4d(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXY => new V4d(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXZ => new V4d(-1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYO => new V4d(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYP => new V4d(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYN => new V4d(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYX => new V4d(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYY => new V4d(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYZ => new V4d(-1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZO => new V4d(-1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZP => new V4d(-1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZN => new V4d(-1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZX => new V4d(-1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZY => new V4d(-1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZZ => new V4d(-1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOX => new V4d(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOY => new V4d(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOZ => new V4d(-1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPX => new V4d(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPY => new V4d(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPZ => new V4d(-1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNX => new V4d(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNY => new V4d(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNZ => new V4d(-1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXO => new V4d(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXP => new V4d(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXN => new V4d(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXX => new V4d(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXY => new V4d(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXZ => new V4d(-1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYO => new V4d(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYP => new V4d(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYN => new V4d(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYX => new V4d(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYY => new V4d(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYZ => new V4d(-1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZO => new V4d(-1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZP => new V4d(-1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZN => new V4d(-1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZX => new V4d(-1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZY => new V4d(-1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZZ => new V4d(-1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOX => new V4d(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOY => new V4d(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOZ => new V4d(-1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPX => new V4d(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPY => new V4d(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPZ => new V4d(-1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNX => new V4d(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNY => new V4d(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNZ => new V4d(-1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXO => new V4d(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXP => new V4d(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXN => new V4d(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXX => new V4d(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXY => new V4d(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXZ => new V4d(-1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYO => new V4d(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYP => new V4d(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYN => new V4d(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYX => new V4d(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYY => new V4d(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYZ => new V4d(-1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZO => new V4d(-1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZP => new V4d(-1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZN => new V4d(-1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZX => new V4d(-1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZY => new V4d(-1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZZ => new V4d(-1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOO => new V4d(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOP => new V4d(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXON => new V4d(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOX => new V4d(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOY => new V4d(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOZ => new V4d(-1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPO => new V4d(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPP => new V4d(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPN => new V4d(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPX => new V4d(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPY => new V4d(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPZ => new V4d(-1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNO => new V4d(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNP => new V4d(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNN => new V4d(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNX => new V4d(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNY => new V4d(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNZ => new V4d(-1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXO => new V4d(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXP => new V4d(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXN => new V4d(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXX => new V4d(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXY => new V4d(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXZ => new V4d(-1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYO => new V4d(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYP => new V4d(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYN => new V4d(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYX => new V4d(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYY => new V4d(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYZ => new V4d(-1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZO => new V4d(-1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZP => new V4d(-1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZN => new V4d(-1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZX => new V4d(-1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZY => new V4d(-1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZZ => new V4d(-1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOO => new V4d(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOP => new V4d(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYON => new V4d(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOX => new V4d(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOY => new V4d(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOZ => new V4d(-1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPO => new V4d(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPP => new V4d(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPN => new V4d(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPX => new V4d(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPY => new V4d(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPZ => new V4d(-1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNO => new V4d(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNP => new V4d(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNN => new V4d(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNX => new V4d(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNY => new V4d(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNZ => new V4d(-1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXO => new V4d(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXP => new V4d(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXN => new V4d(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXX => new V4d(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXY => new V4d(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXZ => new V4d(-1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYO => new V4d(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYP => new V4d(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYN => new V4d(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYX => new V4d(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYY => new V4d(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYZ => new V4d(-1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZO => new V4d(-1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZP => new V4d(-1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZN => new V4d(-1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZX => new V4d(-1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZY => new V4d(-1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZZ => new V4d(-1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOO => new V4d(-1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOP => new V4d(-1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZON => new V4d(-1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOX => new V4d(-1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOY => new V4d(-1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOZ => new V4d(-1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPO => new V4d(-1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPP => new V4d(-1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPN => new V4d(-1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPX => new V4d(-1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPY => new V4d(-1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPZ => new V4d(-1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNO => new V4d(-1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNP => new V4d(-1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNN => new V4d(-1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNX => new V4d(-1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNY => new V4d(-1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNZ => new V4d(-1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXO => new V4d(-1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXP => new V4d(-1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXN => new V4d(-1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXX => new V4d(-1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXY => new V4d(-1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXZ => new V4d(-1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYO => new V4d(-1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYP => new V4d(-1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYN => new V4d(-1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYX => new V4d(-1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYY => new V4d(-1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYZ => new V4d(-1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZO => new V4d(-1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZP => new V4d(-1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZN => new V4d(-1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZX => new V4d(-1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZY => new V4d(-1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZZ => new V4d(-1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOO => new V4d(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOI => new V4d(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOON => new V4d(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOX => new V4d(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOY => new V4d(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOZ => new V4d(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIO => new V4d(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOII => new V4d(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOPN => new V4d(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIX => new V4d(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIY => new V4d(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIZ => new V4d(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONO => new V4d(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONP => new V4d(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONN => new V4d(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONX => new V4d(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONY => new V4d(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONZ => new V4d(X, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXO => new V4d(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXI => new V4d(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXN => new V4d(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXX => new V4d(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXY => new V4d(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXZ => new V4d(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYO => new V4d(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYI => new V4d(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYN => new V4d(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYX => new V4d(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYY => new V4d(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYZ => new V4d(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZO => new V4d(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZI => new V4d(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZN => new V4d(X, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZX => new V4d(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZY => new V4d(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZZ => new V4d(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOO => new V4d(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOI => new V4d(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPON => new V4d(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOX => new V4d(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOY => new V4d(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOZ => new V4d(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIO => new V4d(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIII => new V4d(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPPN => new V4d(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIX => new V4d(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIY => new V4d(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIZ => new V4d(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNO => new V4d(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNP => new V4d(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNN => new V4d(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNX => new V4d(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNY => new V4d(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNZ => new V4d(X, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXO => new V4d(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXI => new V4d(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPXN => new V4d(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXX => new V4d(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXY => new V4d(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXZ => new V4d(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYO => new V4d(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYI => new V4d(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPYN => new V4d(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYX => new V4d(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYY => new V4d(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYZ => new V4d(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZO => new V4d(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZI => new V4d(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPZN => new V4d(X, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZX => new V4d(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZY => new V4d(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZZ => new V4d(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOO => new V4d(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOP => new V4d(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNON => new V4d(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOX => new V4d(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOY => new V4d(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOZ => new V4d(X, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPO => new V4d(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPP => new V4d(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPN => new V4d(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPX => new V4d(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPY => new V4d(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPZ => new V4d(X, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNO => new V4d(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNP => new V4d(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNN => new V4d(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNX => new V4d(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNY => new V4d(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNZ => new V4d(X, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXO => new V4d(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXP => new V4d(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXN => new V4d(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXX => new V4d(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXY => new V4d(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXZ => new V4d(X, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYO => new V4d(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYP => new V4d(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYN => new V4d(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYX => new V4d(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYY => new V4d(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYZ => new V4d(X, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZO => new V4d(X, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZP => new V4d(X, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZN => new V4d(X, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZX => new V4d(X, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZY => new V4d(X, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZZ => new V4d(X, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOO => new V4d(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOI => new V4d(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXON => new V4d(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOX => new V4d(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOY => new V4d(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOZ => new V4d(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIO => new V4d(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXII => new V4d(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXPN => new V4d(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIX => new V4d(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIY => new V4d(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIZ => new V4d(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNO => new V4d(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNP => new V4d(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNN => new V4d(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNX => new V4d(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNY => new V4d(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNZ => new V4d(X, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXO => new V4d(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXI => new V4d(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXN => new V4d(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXX => new V4d(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXY => new V4d(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXZ => new V4d(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYO => new V4d(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYI => new V4d(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYN => new V4d(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYX => new V4d(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYY => new V4d(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYZ => new V4d(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZO => new V4d(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZI => new V4d(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZN => new V4d(X, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZX => new V4d(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZY => new V4d(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZZ => new V4d(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOO => new V4d(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOI => new V4d(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYON => new V4d(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOX => new V4d(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOY => new V4d(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOZ => new V4d(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIO => new V4d(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYII => new V4d(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYPN => new V4d(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIX => new V4d(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIY => new V4d(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIZ => new V4d(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNO => new V4d(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNP => new V4d(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNN => new V4d(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNX => new V4d(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNY => new V4d(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNZ => new V4d(X, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXO => new V4d(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXI => new V4d(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXN => new V4d(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXX => new V4d(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXY => new V4d(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXZ => new V4d(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYO => new V4d(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYI => new V4d(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYN => new V4d(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYX => new V4d(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYY => new V4d(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYZ => new V4d(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZO => new V4d(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZI => new V4d(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZN => new V4d(X, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZX => new V4d(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZY => new V4d(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZZ => new V4d(X, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOO => new V4d(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOI => new V4d(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZON => new V4d(X, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOX => new V4d(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOY => new V4d(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOZ => new V4d(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIO => new V4d(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZII => new V4d(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZPN => new V4d(X, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIX => new V4d(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIY => new V4d(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIZ => new V4d(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNO => new V4d(X, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNP => new V4d(X, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNN => new V4d(X, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNX => new V4d(X, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNY => new V4d(X, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNZ => new V4d(X, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXO => new V4d(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXI => new V4d(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXN => new V4d(X, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXX => new V4d(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXY => new V4d(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXZ => new V4d(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYO => new V4d(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYI => new V4d(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYN => new V4d(X, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYX => new V4d(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYY => new V4d(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYZ => new V4d(X, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZO => new V4d(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZI => new V4d(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZN => new V4d(X, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZX => new V4d(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZY => new V4d(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZZ => new V4d(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOO => new V4d(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOI => new V4d(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOON => new V4d(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOX => new V4d(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOY => new V4d(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOZ => new V4d(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIO => new V4d(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOII => new V4d(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOPN => new V4d(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIX => new V4d(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIY => new V4d(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIZ => new V4d(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONO => new V4d(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONP => new V4d(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONN => new V4d(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONX => new V4d(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONY => new V4d(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONZ => new V4d(Y, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXO => new V4d(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXI => new V4d(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXN => new V4d(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXX => new V4d(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXY => new V4d(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXZ => new V4d(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYO => new V4d(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYI => new V4d(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYN => new V4d(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYX => new V4d(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYY => new V4d(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYZ => new V4d(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZO => new V4d(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZI => new V4d(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZN => new V4d(Y, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZX => new V4d(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZY => new V4d(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZZ => new V4d(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOO => new V4d(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOI => new V4d(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPON => new V4d(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOX => new V4d(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOY => new V4d(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOZ => new V4d(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIO => new V4d(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIII => new V4d(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPPN => new V4d(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIX => new V4d(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIY => new V4d(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIZ => new V4d(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNO => new V4d(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNP => new V4d(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNN => new V4d(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNX => new V4d(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNY => new V4d(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNZ => new V4d(Y, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXO => new V4d(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXI => new V4d(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPXN => new V4d(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXX => new V4d(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXY => new V4d(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXZ => new V4d(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYO => new V4d(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYI => new V4d(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPYN => new V4d(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYX => new V4d(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYY => new V4d(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYZ => new V4d(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZO => new V4d(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZI => new V4d(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPZN => new V4d(Y, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZX => new V4d(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZY => new V4d(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZZ => new V4d(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOO => new V4d(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOP => new V4d(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNON => new V4d(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOX => new V4d(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOY => new V4d(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOZ => new V4d(Y, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPO => new V4d(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPP => new V4d(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPN => new V4d(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPX => new V4d(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPY => new V4d(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPZ => new V4d(Y, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNO => new V4d(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNP => new V4d(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNN => new V4d(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNX => new V4d(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNY => new V4d(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNZ => new V4d(Y, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXO => new V4d(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXP => new V4d(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXN => new V4d(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXX => new V4d(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXY => new V4d(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXZ => new V4d(Y, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYO => new V4d(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYP => new V4d(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYN => new V4d(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYX => new V4d(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYY => new V4d(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYZ => new V4d(Y, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZO => new V4d(Y, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZP => new V4d(Y, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZN => new V4d(Y, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZX => new V4d(Y, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZY => new V4d(Y, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZZ => new V4d(Y, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOO => new V4d(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOI => new V4d(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXON => new V4d(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOX => new V4d(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOY => new V4d(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOZ => new V4d(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIO => new V4d(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXII => new V4d(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXPN => new V4d(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIX => new V4d(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIY => new V4d(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIZ => new V4d(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNO => new V4d(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNP => new V4d(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNN => new V4d(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNX => new V4d(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNY => new V4d(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNZ => new V4d(Y, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXO => new V4d(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXI => new V4d(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXN => new V4d(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXX => new V4d(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXY => new V4d(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXZ => new V4d(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYO => new V4d(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYI => new V4d(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYN => new V4d(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYX => new V4d(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYY => new V4d(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYZ => new V4d(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZO => new V4d(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZI => new V4d(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZN => new V4d(Y, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZX => new V4d(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZY => new V4d(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZZ => new V4d(Y, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOO => new V4d(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOI => new V4d(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYON => new V4d(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOX => new V4d(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOY => new V4d(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOZ => new V4d(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIO => new V4d(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYII => new V4d(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYPN => new V4d(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIX => new V4d(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIY => new V4d(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIZ => new V4d(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNO => new V4d(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNP => new V4d(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNN => new V4d(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNX => new V4d(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNY => new V4d(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNZ => new V4d(Y, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXO => new V4d(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXI => new V4d(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXN => new V4d(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXX => new V4d(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXY => new V4d(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXZ => new V4d(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYO => new V4d(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYI => new V4d(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYN => new V4d(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYX => new V4d(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYY => new V4d(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYZ => new V4d(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZO => new V4d(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZI => new V4d(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZN => new V4d(Y, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZX => new V4d(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZY => new V4d(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZZ => new V4d(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOO => new V4d(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOI => new V4d(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZON => new V4d(Y, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOX => new V4d(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOY => new V4d(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOZ => new V4d(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIO => new V4d(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZII => new V4d(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZPN => new V4d(Y, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIX => new V4d(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIY => new V4d(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIZ => new V4d(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNO => new V4d(Y, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNP => new V4d(Y, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNN => new V4d(Y, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNX => new V4d(Y, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNY => new V4d(Y, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNZ => new V4d(Y, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXO => new V4d(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXI => new V4d(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXN => new V4d(Y, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXX => new V4d(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXY => new V4d(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXZ => new V4d(Y, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYO => new V4d(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYI => new V4d(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYN => new V4d(Y, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYX => new V4d(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYY => new V4d(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYZ => new V4d(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZO => new V4d(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZI => new V4d(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZN => new V4d(Y, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZX => new V4d(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZY => new V4d(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZZ => new V4d(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOO => new V4d(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOI => new V4d(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOON => new V4d(Z, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOX => new V4d(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOY => new V4d(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOZ => new V4d(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIO => new V4d(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOII => new V4d(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOPN => new V4d(Z, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIX => new V4d(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIY => new V4d(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIZ => new V4d(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONO => new V4d(Z, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONP => new V4d(Z, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONN => new V4d(Z, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONX => new V4d(Z, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONY => new V4d(Z, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONZ => new V4d(Z, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXO => new V4d(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXI => new V4d(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXN => new V4d(Z, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXX => new V4d(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXY => new V4d(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXZ => new V4d(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYO => new V4d(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYI => new V4d(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYN => new V4d(Z, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYX => new V4d(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYY => new V4d(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYZ => new V4d(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZO => new V4d(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZI => new V4d(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZN => new V4d(Z, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZX => new V4d(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZY => new V4d(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZZ => new V4d(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOO => new V4d(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOI => new V4d(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPON => new V4d(Z, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOX => new V4d(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOY => new V4d(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOZ => new V4d(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIO => new V4d(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIII => new V4d(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPPN => new V4d(Z, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIX => new V4d(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIY => new V4d(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIZ => new V4d(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNO => new V4d(Z, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNP => new V4d(Z, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNN => new V4d(Z, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNX => new V4d(Z, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNY => new V4d(Z, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNZ => new V4d(Z, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXO => new V4d(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXI => new V4d(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPXN => new V4d(Z, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXX => new V4d(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXY => new V4d(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXZ => new V4d(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYO => new V4d(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYI => new V4d(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPYN => new V4d(Z, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYX => new V4d(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYY => new V4d(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYZ => new V4d(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZO => new V4d(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZI => new V4d(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPZN => new V4d(Z, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZX => new V4d(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZY => new V4d(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZZ => new V4d(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOO => new V4d(Z, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOP => new V4d(Z, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNON => new V4d(Z, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOX => new V4d(Z, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOY => new V4d(Z, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOZ => new V4d(Z, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPO => new V4d(Z, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPP => new V4d(Z, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPN => new V4d(Z, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPX => new V4d(Z, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPY => new V4d(Z, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPZ => new V4d(Z, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNO => new V4d(Z, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNP => new V4d(Z, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNN => new V4d(Z, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNX => new V4d(Z, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNY => new V4d(Z, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNZ => new V4d(Z, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXO => new V4d(Z, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXP => new V4d(Z, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXN => new V4d(Z, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXX => new V4d(Z, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXY => new V4d(Z, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXZ => new V4d(Z, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYO => new V4d(Z, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYP => new V4d(Z, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYN => new V4d(Z, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYX => new V4d(Z, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYY => new V4d(Z, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYZ => new V4d(Z, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZO => new V4d(Z, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZP => new V4d(Z, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZN => new V4d(Z, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZX => new V4d(Z, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZY => new V4d(Z, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZZ => new V4d(Z, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOO => new V4d(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOI => new V4d(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXON => new V4d(Z, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOX => new V4d(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOY => new V4d(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOZ => new V4d(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIO => new V4d(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXII => new V4d(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXPN => new V4d(Z, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIX => new V4d(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIY => new V4d(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIZ => new V4d(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNO => new V4d(Z, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNP => new V4d(Z, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNN => new V4d(Z, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNX => new V4d(Z, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNY => new V4d(Z, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNZ => new V4d(Z, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXO => new V4d(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXI => new V4d(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXN => new V4d(Z, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXX => new V4d(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXY => new V4d(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXZ => new V4d(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYO => new V4d(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYI => new V4d(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYN => new V4d(Z, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYX => new V4d(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYY => new V4d(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYZ => new V4d(Z, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZO => new V4d(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZI => new V4d(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZN => new V4d(Z, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZX => new V4d(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZY => new V4d(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZZ => new V4d(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOO => new V4d(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOI => new V4d(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYON => new V4d(Z, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOX => new V4d(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOY => new V4d(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOZ => new V4d(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIO => new V4d(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYII => new V4d(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYPN => new V4d(Z, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIX => new V4d(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIY => new V4d(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIZ => new V4d(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNO => new V4d(Z, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNP => new V4d(Z, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNN => new V4d(Z, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNX => new V4d(Z, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNY => new V4d(Z, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNZ => new V4d(Z, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXO => new V4d(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXI => new V4d(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXN => new V4d(Z, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXX => new V4d(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXY => new V4d(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXZ => new V4d(Z, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYO => new V4d(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYI => new V4d(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYN => new V4d(Z, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYX => new V4d(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYY => new V4d(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYZ => new V4d(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZO => new V4d(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZI => new V4d(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZN => new V4d(Z, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZX => new V4d(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZY => new V4d(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZZ => new V4d(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOO => new V4d(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOI => new V4d(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZON => new V4d(Z, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOX => new V4d(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOY => new V4d(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOZ => new V4d(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIO => new V4d(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZII => new V4d(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZPN => new V4d(Z, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIX => new V4d(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIY => new V4d(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIZ => new V4d(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNO => new V4d(Z, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNP => new V4d(Z, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNN => new V4d(Z, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNX => new V4d(Z, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNY => new V4d(Z, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNZ => new V4d(Z, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXO => new V4d(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXI => new V4d(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXN => new V4d(Z, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXX => new V4d(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXY => new V4d(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXZ => new V4d(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYO => new V4d(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYI => new V4d(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYN => new V4d(Z, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYX => new V4d(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYY => new V4d(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYZ => new V4d(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZO => new V4d(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZI => new V4d(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZN => new V4d(Z, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZX => new V4d(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZY => new V4d(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZZ => new V4d(Z, Z, Z, Z);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (double)value; }\n        }\n\n        #endregion\n\n        #region ISize3d Members\n\n        public readonly V3d Size3d { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 3; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (double)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V3dEqualityComparer : IEqualityComparer<V3d>\n    {\n        public static V3dEqualityComparer Default\n            => new V3dEqualityComparer();\n\n        #region IEqualityComparer<V3d> Members\n\n        public bool Equals(V3d v0, V3d v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V3d v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Min(this V3d a, V3d b)\n        {\n            return new V3d(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Min(this V3d a, double b)\n        {\n            return new V3d(Min(a.X, b), Min(a.Y, b), Min(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Min(this double a, V3d b)\n        {\n            return new V3d(Min(a, b.X), Min(a, b.Y), Min(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Max(this V3d a, V3d b)\n        {\n            return new V3d(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Max(this V3d a, double b)\n        {\n            return new V3d(Max(a.X, b), Max(a.Y, b), Max(a.Z, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Max(this double a, V3d b)\n        {\n            return new V3d(Max(a, b.X), Max(a, b.Y), Max(a, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Min(this V3d a, V3d b, V3d c)\n        {\n            return new V3d(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Max(this V3d a, V3d b, V3d c)\n        {\n            return new V3d(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Min(this V3d a, V3d b, V3d c, V3d d)\n        {\n            return new V3d(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Max(this V3d a, V3d b, V3d c, V3d d)\n        {\n            return new V3d(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Min(this V3d x, params V3d[] values)\n        {\n            return new V3d(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Max(this V3d x, params V3d[] values)\n        {\n            return new V3d(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Abs(this V3d x)\n        {\n            return new V3d(Abs(x.X), Abs(x.Y), Abs(x.Z));\n        }\n\n        #endregion\n\n        #region Rounding\n\n        /// <summary>\n        /// Applies Fun.Floor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Floor(this V3d x)\n        {\n            return new V3d(Floor(x.X), Floor(x.Y), Floor(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Ceiling to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Ceiling(this V3d x)\n        {\n            return new V3d(Ceiling(x.X), Ceiling(x.Y), Ceiling(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Round(this V3d x)\n        {\n            return new V3d(Round(x.X), Round(x.Y), Round(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Round(this V3d x, MidpointRounding mode)\n        {\n            return new V3d(Round(x.X, mode), Round(x.Y, mode), Round(x.Z, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Round(this V3d x, int digits)\n        {\n            return new V3d(Round(x.X, digits), Round(x.Y, digits), Round(x.Z, digits));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Round(this V3d x, int digits, MidpointRounding mode)\n        {\n            return new V3d(Round(x.X, digits, mode), Round(x.Y, digits, mode), Round(x.Z, digits, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Truncate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Truncate(this V3d x)\n        {\n            return new V3d(Truncate(x.X), Truncate(x.Y), Truncate(x.Z));\n        }\n\n        #endregion\n\n        #region Frac\n\n        /// <summary>\n        /// Applies Fun.Frac to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Frac(this V3d x)\n        {\n            return new V3d(Frac(x.X), Frac(x.Y), Frac(x.Z));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Clamp(this V3d x, V3d a, V3d b)\n        {\n            return new V3d(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Clamp(this V3d x, double a, double b)\n        {\n            return new V3d(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d ClampWrap(this V3d x, V3d a, V3d b)\n        {\n            return new V3d(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d ClampWrap(this V3d x, double a, double b)\n        {\n            return new V3d(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Saturate(this V3d x)\n        {\n            return new V3d(Saturate(x.X), Saturate(x.Y), Saturate(x.Z));\n        }\n\n        #endregion\n\n        #region MapToUnitInterval\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d MapToUnitInterval(this V3d t, V3d tMax, bool repeat, bool mirror)\n        {\n            return new V3d(MapToUnitInterval(t.X, tMax.X, repeat, mirror), MapToUnitInterval(t.Y, tMax.Y, repeat, mirror), MapToUnitInterval(t.Z, tMax.Z, repeat, mirror));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d MapToUnitInterval(this V3d t, V3d tMax, bool repeat)\n        {\n            return new V3d(MapToUnitInterval(t.X, tMax.X, repeat), MapToUnitInterval(t.Y, tMax.Y, repeat), MapToUnitInterval(t.Z, tMax.Z, repeat));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d MapToUnitInterval(this V3d t, V3d tMax)\n        {\n            return new V3d(MapToUnitInterval(t.X, tMax.X), MapToUnitInterval(t.Y, tMax.Y), MapToUnitInterval(t.Z, tMax.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d MapToUnitInterval(this V3d t, V3d tMin, V3d tMax)\n        {\n            return new V3d(MapToUnitInterval(t.X, tMin.X, tMax.X), MapToUnitInterval(t.Y, tMin.Y, tMax.Y), MapToUnitInterval(t.Z, tMin.Z, tMax.Z));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Sign(this V3d x)\n        {\n            return new V3i(Sign(x.X), Sign(x.Y), Sign(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Signumi(this V3d x)\n        {\n            return new V3i(Signumi(x.X), Signumi(x.Y), Signumi(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Signum(this V3d x)\n        {\n            return new V3d(Signum(x.X), Signum(x.Y), Signum(x.Z));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d MultiplyAdd(V3d x, V3d y, V3d z)\n        {\n            return new V3d(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d MultiplyAdd(V3d x, double y, V3d z)\n        {\n            return new V3d(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d MultiplyAdd(double x, V3d y, V3d z)\n        {\n            return new V3d(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z));\n        }\n\n        #endregion\n\n        #region Copy sign\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d CopySign(V3d value, V3d sign)\n        {\n            return new V3d(CopySign(value.X, sign.X), CopySign(value.Y, sign.Y), CopySign(value.Z, sign.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d CopySign(double value, V3d sign)\n        {\n            return new V3d(CopySign(value, sign.X), CopySign(value, sign.Y), CopySign(value, sign.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d CopySign(V3d value, double sign)\n        {\n            return new V3d(CopySign(value.X, sign), CopySign(value.Y, sign), CopySign(value.Z, sign));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sqrt(this V3d x)\n        {\n            return new V3d(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cbrt(this V3d x)\n        {\n            return new V3d(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Square(this V3d x)\n        {\n            return new V3d(Square(x.X), Square(x.Y), Square(x.Z));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pown(this V3d x, V3i y)\n        {\n            return new V3d(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pown(this V3d x, int y)\n        {\n            return new V3d(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pown(this double x, V3i y)\n        {\n            return new V3d(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this V3d x, V3d y)\n        {\n            return new V3d(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this V3d x, double y)\n        {\n            return new V3d(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Pow(this double x, V3d y)\n        {\n            return new V3d(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this V3d x, V3d y)\n        {\n            return new V3d(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this V3d x, double y)\n        {\n            return new V3d(Power(x.X, y), Power(x.Y, y), Power(x.Z, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Power(this double x, V3d y)\n        {\n            return new V3d(Power(x, y.X), Power(x, y.Y), Power(x, y.Z));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Exp(this V3d x)\n        {\n            return new V3d(Exp(x.X), Exp(x.Y), Exp(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(this V3d x)\n        {\n            return new V3d(Log(x.X), Log(x.Y), Log(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log2(this V3d x)\n        {\n            return new V3d(Log2(x.X), Log2(x.Y), Log2(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3i Log2Int(this V3d x)\n        {\n            return new V3i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log10(this V3d x)\n        {\n            return new V3d(Log10(x.X), Log10(x.Y), Log10(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Log(this V3d x, double basis)\n        {\n            return new V3d(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d ModP(this V3d a, V3d b)\n        {\n            return new V3d(ModP(a.X, b.X), ModP(a.Y, b.Y), ModP(a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d PowerOfTwo(this V3d x)\n        {\n            return new V3d(PowerOfTwo(x.X), PowerOfTwo(x.Y), PowerOfTwo(x.Z));\n        }\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Applies Fun.Sin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sin(this V3d x)\n        {\n            return new V3d(Sin(x.X), Sin(x.Y), Sin(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cos(this V3d x)\n        {\n            return new V3d(Cos(x.X), Cos(x.Y), Cos(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Tan(this V3d x)\n        {\n            return new V3d(Tan(x.X), Tan(x.Y), Tan(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Asin(this V3d x)\n        {\n            return new V3d(Asin(x.X), Asin(x.Y), Asin(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.AsinClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d AsinClamped(this V3d x)\n        {\n            return new V3d(AsinClamped(x.X), AsinClamped(x.Y), AsinClamped(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Acos(this V3d x)\n        {\n            return new V3d(Acos(x.X), Acos(x.Y), Acos(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.AcosClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d AcosClamped(this V3d x)\n        {\n            return new V3d(AcosClamped(x.X), AcosClamped(x.Y), AcosClamped(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Atan(this V3d x)\n        {\n            return new V3d(Atan(x.X), Atan(x.Y), Atan(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Atan2(V3d y, V3d x)\n        {\n            return new V3d(Atan2(y.X, x.X), Atan2(y.Y, x.Y), Atan2(y.Z, x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.FastAtan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d FastAtan2(V3d y, V3d x)\n        {\n            return new V3d(FastAtan2(y.X, x.X), FastAtan2(y.Y, x.Y), FastAtan2(y.Z, x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Sinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Sinh(this V3d x)\n        {\n            return new V3d(Sinh(x.X), Sinh(x.Y), Sinh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cosh(this V3d x)\n        {\n            return new V3d(Cosh(x.X), Cosh(x.Y), Cosh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Tanh(this V3d x)\n        {\n            return new V3d(Tanh(x.X), Tanh(x.Y), Tanh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Asinh(this V3d x)\n        {\n            return new V3d(Asinh(x.X), Asinh(x.Y), Asinh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Acosh(this V3d x)\n        {\n            return new V3d(Acosh(x.X), Acosh(x.Y), Acosh(x.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Atanh(this V3d x)\n        {\n            return new V3d(Atanh(x.X), Atanh(x.Y), Atanh(x.Z));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Step(this V3d x, V3d edge)\n        {\n            return new V3d(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Step(this V3d x, double edge)\n        {\n            return new V3d(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Linearstep(this V3d x, V3d edge0, V3d edge1)\n        {\n            return new V3d(Linearstep(x.X, edge0.X, edge1.X), Linearstep(x.Y, edge0.Y, edge1.Y), Linearstep(x.Z, edge0.Z, edge1.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Linearstep(this V3d x, double edge0, double edge1)\n        {\n            return new V3d(Linearstep(x.X, edge0, edge1), Linearstep(x.Y, edge0, edge1), Linearstep(x.Z, edge0, edge1));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Smoothstep(this V3d x, V3d edge0, V3d edge1)\n        {\n            return new V3d(Smoothstep(x.X, edge0.X, edge1.X), Smoothstep(x.Y, edge0.Y, edge1.Y), Smoothstep(x.Z, edge0.Z, edge1.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Smoothstep(this V3d x, double edge0, double edge1)\n        {\n            return new V3d(Smoothstep(x.X, edge0, edge1), Smoothstep(x.Y, edge0, edge1), Smoothstep(x.Z, edge0, edge1));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Lerp(this double t, V3d a, V3d b)\n        {\n            return new V3d(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Lerp(this V3d t, V3d a, V3d b)\n        {\n            return new V3d(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d InvLerp(this V3d y, V3d a, V3d b)\n        {\n            return new V3d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatToBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3l FloatToBits(this V3d x)\n        {\n            return new V3l(FloatToBits(x.X), FloatToBits(x.Y), FloatToBits(x.Z));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V3d a, V3d b, double tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within\n        /// Constant{double}.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V3d a, V3d b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V3d v, double epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(V3d v)\n            => v.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"V3d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(V3d v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V3d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(V3d v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V3d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(V3d v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V3d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(V3d v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"V3d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(V3d v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts the angles given in degrees to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d RadiansFromDegrees(this V3d degrees)\n            => new V3d(\n                   RadiansFromDegrees(degrees.X), \n                   RadiansFromDegrees(degrees.Y), \n                   RadiansFromDegrees(degrees.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d RadiansFromGons(this V3d gons)\n            => new V3d(\n                   RadiansFromGons(gons.X), \n                   RadiansFromGons(gons.Y), \n                   RadiansFromGons(gons.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d DegreesFromRadians(this V3d radians)\n            => new V3d(\n                   DegreesFromRadians(radians.X), \n                   DegreesFromRadians(radians.Y), \n                   DegreesFromRadians(radians.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d DegreesFromGons(this V3d gons)\n            => new V3d(\n                   DegreesFromGons(gons.X), \n                   DegreesFromGons(gons.Y), \n                   DegreesFromGons(gons.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GonsFromRadians(this V3d radians)\n            => new V3d(\n                   GonsFromRadians(radians.X), \n                   GonsFromRadians(radians.Y), \n                   GonsFromRadians(radians.Z)\n               );\n\n        /// <summary>\n        /// Converts the angles given in degrees to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d GonsFromDegrees(this V3d degrees)\n            => new V3d(\n                   GonsFromDegrees(degrees.X), \n                   GonsFromDegrees(degrees.Y), \n                   GonsFromDegrees(degrees.Z)\n               );\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LengthSquared(V3d v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V3d v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Normalizes the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref V3d v)\n        {\n            var s = v.Length; if (s == 0) return;\n            s = 1 / s;\n            v.X *= s;\n            v.Y *= s;\n            v.Z *= s;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Normalized(V3d v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm1(V3d v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V3d v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMax(V3d v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMin(V3d v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V3d v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceSquared(this V3d a, V3d b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y) + Fun.Square(b.Z - a.Z);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V3d a, V3d b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance1(this V3d a, V3d b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y) + Fun.Abs(b.Z - a.Z);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V3d a, V3d b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p) + Fun.Abs(b.Z - a.Z).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceMax(this V3d a, V3d b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceMin(this V3d a, V3d b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V3d query, V3d p0, V3d p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            if (t <= 0) { return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V3d query, V3d p0, V3d p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V3d query, V3d p0, V3d p1, out double t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            if (t <= 0) { t = 0; return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { t = 1; return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V3d query, V3d p0, V3d p1, out double t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Gets a copy of the given vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Reciprocal(V3d v)\n            => v.Reciprocal;\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V3d v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n            v.Z = -v.Z;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 3x3 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M33d Outer(this V3d a, V3d b)\n        {\n            return new M33d(\n                        a.X * b.X, a.X * b.Y, a.X * b.Z, \n                        a.Y * b.X, a.Y * b.Y, a.Y * b.Z, \n                        a.Z * b.X, a.Z * b.Y, a.Z * b.Z);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Dot(this V3d a, V3d b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z;\n        }\n\n        /// <summary>\n        /// Returns the skew-symmetric \"cross\" matrix (A^T = -A) of the vector v.\n        /// </summary>\n        public static M33d CrossMatrix(this V3d v)\n        {\n            return new M33d(0, -v.Z, +v.Y,\n                            +v.Z, 0, -v.X,\n                            -v.Y, +v.X, 0);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V3d v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeZ;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the reflection direction of the given vector v (pointing to the surface) for the given normal (should be normalized).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Reflect(this V3d v, V3d normal)\n        {\n            return v - 2 * v.Dot(normal) * normal;\n        }\n\n        /// <summary>\n        /// Returns the refraction direction of the given vector v (pointing to the surface) for the given normal and ratio of refraction indices (n_out / n_in).\n        /// Both the input vectors should be normalized.\n        /// Returns a zero-vector in case of total internal reflection.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Refract(this V3d v, V3d normal, double eta)\n        {\n            var t = v.Dot(normal);\n            var k = 1 - eta * eta * (1 - t * t);\n\n            if (k < 0)\n            {\n                return V3d.Zero;\n            }\n            else\n            {\n                return eta * v - (eta * t + Fun.Sqrt(k)) * normal;\n            }\n        }\n\n        /// <summary>\n        /// Returns the cross product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d Cross(this V3d a, V3d b)\n        {\n            return new V3d(\n            a.Y * b.Z - a.Z * b.Y,\n            a.Z * b.X - a.X * b.Z,\n            a.X * b.Y - a.Y * b.X\n            );\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3d a, V3d b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V3d v, double s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, V3d v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3d a, V3d b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V3d v, double s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, V3d v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3d a, V3d b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V3d v, double s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, V3d v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3d a, V3d b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V3d v, double s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, V3d v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3d a, V3d b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V3d v, double s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, V3d v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3d a, V3d b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V3d v, double s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, V3d v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3d a, V3d b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V3d v, double s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, V3d v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3d a, V3d b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V3d v, double s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, V3d v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3d a, V3d b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V3d v, double s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, V3d v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3d a, V3d b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V3d v, double s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, V3d v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3d a, V3d b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V3d v, double s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, V3d v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3d a, V3d b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V3d v, double s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, V3d v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V3d v0, V3d v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MinElement(V3d v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V3d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MaxElement(V3d v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region Axis aligned normal\n\n        /// <summary>\n        /// Returns an arbitrary normal vector, which\n        /// is also normal to either the x, y or z-axis.\n        /// </summary>\n        public static V3d AxisAlignedNormal(this V3d v)\n        {\n            V3d vector;\n            double x = v.X.Abs();\n            double y = v.Y.Abs();\n            double z = v.Z.Abs();\n\n            if (x < y)\n            {\n                if (x < z)\n                    vector = V3d.XAxis;\n                else\n                    vector = V3d.ZAxis;\n            }\n            else\n            {\n                if (y < z)\n                    vector = V3d.YAxis;\n                else\n                    vector = V3d.ZAxis;\n            }\n\n            return v.Cross(vector).Normalized;\n        }\n\n        #endregion\n\n        #region Angle between two vectors\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleBetweenFast(this V3d x, V3d y)\n        {\n            return Fun.AcosClamped(x.Dot(y));\n        }\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians using a numerically stable algorithm.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        // https://scicomp.stackexchange.com/a/27769\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleBetween(this V3d x, V3d y)\n        {\n            var a = x + y;\n            var b = x - y;\n            return 2 * Fun.Atan2(b.Length, a.Length);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V3d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V3d v, double epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V3d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V3d v, double epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(V3d v)\n            => v.AnyFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(V3d v)\n            => v.AllFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(V3d v)\n            => v.AnyNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(V3d v)\n            => v.AllNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(V3d v)\n            => v.AnyInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(V3d v)\n            => v.AllInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(V3d v)\n            => v.AnyPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(V3d v)\n            => v.AllPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(V3d v)\n            => v.AnyNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(V3d v)\n            => v.AllNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(V3d v)\n            => v.AnyTiny;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(V3d v)\n            => v.AllTiny;\n\n        #endregion\n\n        #region Linear Combination\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LinCom(V3d p0, V3d p1, ref Tup2<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LinCom(V3d p0, V3d p1, V3d p2, ref Tup3<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LinCom(V3d p0, V3d p1, V3d p2, V3d p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LinCom(V3d p0, V3d p1, V3d p2, V3d p3, V3d p4, ref Tup5<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LinCom(V3d p0, V3d p1, V3d p2, V3d p3, V3d p4, V3d p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d LinCom(V3d p0, V3d p1, V3d p2, V3d p3, V3d p4, V3d p5, V3d p6, ref Tup7<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V3d[] pointArray, V3d point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V3d[] array, int start, int count,\n                V3d point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V3d> pointSelector, V3d point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V3d[] pointArray, V3d point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V3d[] array, long start, long count,\n                V3d point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V3d> pointSelector, V3d point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V3d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V3d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V3d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V3d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V3d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V3d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V3d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V3d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V3d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V3d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V3d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V3d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V3d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V3d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V3d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V3d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V3d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V3d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static double[] CopyCoord(this V3d[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        public static V3d WeightedSum(\n                this V3d[] vectorArray, double[] weightArray)\n        {\n            var r = V3d.Zero;\n            var count = vectorArray.LongLength;\n            for (long i = 0; i < count; i++) r += vectorArray[i] * weightArray[i];\n            return r;\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV3dExtensions\n    {\n        #region IRandomUniform extensions for V3d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of a V3d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3d(this IRandomUniform rnd)\n        {\n            return new V3d(rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of a V3d\n        /// vector within the given Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3d(this IRandomUniform rnd, Box3d box)\n        {\n            return new V3d(box.Min.X + rnd.UniformDouble() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDouble() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformDouble() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of a V3d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dClosed(this IRandomUniform rnd)\n        {\n            return new V3d(rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of a V3d\n        /// vector within the given Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dClosed(this IRandomUniform rnd, Box3d box)\n        {\n            return new V3d(box.Min.X + rnd.UniformDoubleClosed() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleClosed() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformDoubleClosed() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of a V3d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dOpen(this IRandomUniform rnd)\n        {\n            return new V3d(rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of a V3d\n        /// vector within the given Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dOpen(this IRandomUniform rnd, Box3d box)\n        {\n            return new V3d(box.Min.X + rnd.UniformDoubleOpen() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleOpen() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformDoubleOpen() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of a V3d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFull(this IRandomUniform rnd)\n        {\n            return new V3d(rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of a V3d\n        /// vector within the given Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFull(this IRandomUniform rnd, Box3d box)\n        {\n            return new V3d(box.Min.X + rnd.UniformDoubleFull() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleFull() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformDoubleFull() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of a V3d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFullClosed(this IRandomUniform rnd)\n        {\n            return new V3d(rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of a V3d\n        /// vector within the given Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFullClosed(this IRandomUniform rnd, Box3d box)\n        {\n            return new V3d(box.Min.X + rnd.UniformDoubleFullClosed() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleFullClosed() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformDoubleFullClosed() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of a V3d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFullOpen(this IRandomUniform rnd)\n        {\n            return new V3d(rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of a V3d\n        /// vector within the given Box3d.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFullOpen(this IRandomUniform rnd, Box3d box)\n        {\n            return new V3d(box.Min.X + rnd.UniformDoubleFullOpen() * (box.Max.X - box.Min.X), box.Min.Y + rnd.UniformDoubleFullOpen() * (box.Max.Y - box.Min.Y), box.Min.Z + rnd.UniformDoubleFullOpen() * (box.Max.Z - box.Min.Z));\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the surface of the unit sphere).\n        /// Note however, that the returned vector will never be equal to\n        /// [0, 0, -1]. Uses UniformDouble() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dDirection(this IRandomUniform rnd)\n        {\n            double phi = rnd.UniformDouble() * Constant.PiTimesTwo;\n            double z = 1 - rnd.UniformDouble() * 2;\n            double s = Fun.Sqrt(1 - z * z);\n            return new V3d(Fun.Cos(phi) * s, Fun.Sin(phi) * s, z);\n        }\n\n        /// <summary>\n        /// Uniform vector in the closed unit sphere (i.e vectors to\n        /// the surface of the sphere may be generated). Uses UniformV3dClosed() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dClosedSphere(this IRandomUniform rnd)\n        {\n            double r2;\n            V3d p;\n            V3d c_shift = -V3d.Half;\n            do\n            {\n                p = (rnd.UniformV3dClosed() + c_shift) * 2;\n                r2 = p.LengthSquared;\n            }\n            while (r2 >= 1);\n            return p;\n        }\n\n        /// <summary>\n        /// Uniform vector inside the open unit sphere (i.e. no vector\n        /// ends on the surface of the sphere). Uses UniformV3dOpen() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dOpenSphere(this IRandomUniform rnd)\n        {\n            double r2;\n            V3d p;\n            V3d c_shift = -V3d.Half;\n            do\n            {\n                p = (rnd.UniformV3dOpen() + c_shift) * 2;\n                r2 = p.LengthSquared;\n            }\n            while (r2 >= 1);\n            return p;\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the surface of the unit sphere).\n        /// Note however, that the returned vector will never be equal to\n        /// [0, 0, -1]. Uses UniformDoubleFull() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFullDirection(this IRandomUniform rnd)\n        {\n            double phi = rnd.UniformDoubleFull() * Constant.PiTimesTwo;\n            double z = 1 - rnd.UniformDoubleFull() * 2;\n            double s = Fun.Sqrt(1 - z * z);\n            return new V3d(Fun.Cos(phi) * s, Fun.Sin(phi) * s, z);\n        }\n\n        /// <summary>\n        /// Uniform vector in the closed unit sphere (i.e vectors to\n        /// the surface of the sphere may be generated). Uses UniformV3dClosed() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFullClosedSphere(this IRandomUniform rnd)\n        {\n            double r2;\n            V3d p;\n            V3d c_shift = -V3d.Half;\n            do\n            {\n                p = (rnd.UniformV3dClosed() + c_shift) * 2;\n                r2 = p.LengthSquared;\n            }\n            while (r2 >= 1);\n            return p;\n        }\n\n        /// <summary>\n        /// Uniform vector inside the open unit sphere (i.e. no vector\n        /// ends on the surface of the sphere). Uses UniformV3dOpen() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V3d UniformV3dFullOpenSphere(this IRandomUniform rnd)\n        {\n            double r2;\n            V3d p;\n            V3d c_shift = -V3d.Half;\n            do\n            {\n                p = (rnd.UniformV3dOpen() + c_shift) * 2;\n                r2 = p.LengthSquared;\n            }\n            while (r2 >= 1);\n            return p;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V4i\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V4i : IVector<double>, ISize4i, IFormattable, IEquatable<V4i>\n    {\n        [DataMember]\n        public int X;\n        [DataMember]\n        public int Y;\n        [DataMember]\n        public int Z;\n        [DataMember]\n        public int W;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(int x, int y, int z, int w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(int v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n            W = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(int[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n            W = a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(int[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n            W = a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(int a, V3i b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2i a, V2i b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b.X;\n            W = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3i a, int b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = a.Z;\n            W = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/>, <see cref=\"int\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2i a, int b, int c)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"V2i\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(int a, V2i b, int c)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"int\"/>, and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(int a, int b, V2i c)\n        {\n            X = a;\n            Y = b;\n            Z = c.X;\n            W = c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(uint x, uint y, uint z, uint w)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n            W = (int)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(uint v)\n        {\n            X = (int)v;\n            Y = (int)v;\n            Z = (int)v;\n            W = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(uint[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n            Z = (int)a[2];\n            W = (int)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(uint[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n            Z = (int)a[start + 2];\n            W = (int)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(uint a, V3ui b)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n            W = (int)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2ui a, V2ui b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b.X;\n            W = (int)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3ui a, uint b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)a.Z;\n            W = (int)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/>, <see cref=\"uint\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2ui a, uint b, uint c)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b;\n            W = (int)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"V2ui\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(uint a, V2ui b, uint c)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n            W = (int)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"uint\"/>, and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(uint a, uint b, V2ui c)\n        {\n            X = (int)a;\n            Y = (int)b;\n            Z = (int)c.X;\n            W = (int)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(long x, long y, long z, long w)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n            W = (int)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(long v)\n        {\n            X = (int)v;\n            Y = (int)v;\n            Z = (int)v;\n            W = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(long[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n            Z = (int)a[2];\n            W = (int)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(long[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n            Z = (int)a[start + 2];\n            W = (int)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(long a, V3l b)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n            W = (int)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2l a, V2l b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b.X;\n            W = (int)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3l a, long b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)a.Z;\n            W = (int)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/>, <see cref=\"long\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2l a, long b, long c)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b;\n            W = (int)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"V2l\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(long a, V2l b, long c)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n            W = (int)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"long\"/>, and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(long a, long b, V2l c)\n        {\n            X = (int)a;\n            Y = (int)b;\n            Z = (int)c.X;\n            W = (int)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(float x, float y, float z, float w)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n            W = (int)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(float v)\n        {\n            X = (int)v;\n            Y = (int)v;\n            Z = (int)v;\n            W = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(float[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n            Z = (int)a[2];\n            W = (int)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(float[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n            Z = (int)a[start + 2];\n            W = (int)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(float a, V3f b)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n            W = (int)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2f a, V2f b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b.X;\n            W = (int)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3f a, float b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)a.Z;\n            W = (int)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/>, <see cref=\"float\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2f a, float b, float c)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b;\n            W = (int)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"V2f\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(float a, V2f b, float c)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n            W = (int)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"float\"/>, and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(float a, float b, V2f c)\n        {\n            X = (int)a;\n            Y = (int)b;\n            Z = (int)c.X;\n            W = (int)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(double x, double y, double z, double w)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n            W = (int)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(double v)\n        {\n            X = (int)v;\n            Y = (int)v;\n            Z = (int)v;\n            W = (int)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(double[] a)\n        {\n            X = (int)a[0];\n            Y = (int)a[1];\n            Z = (int)a[2];\n            W = (int)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(double[] a, int start)\n        {\n            X = (int)a[start + 0];\n            Y = (int)a[start + 1];\n            Z = (int)a[start + 2];\n            W = (int)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(double a, V3d b)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n            W = (int)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2d a, V2d b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b.X;\n            W = (int)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3d a, double b)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)a.Z;\n            W = (int)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/>, <see cref=\"double\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2d a, double b, double c)\n        {\n            X = (int)a.X;\n            Y = (int)a.Y;\n            Z = (int)b;\n            W = (int)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"V2d\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(double a, V2d b, double c)\n        {\n            X = (int)a;\n            Y = (int)b.X;\n            Z = (int)b.Y;\n            W = (int)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"double\"/>, and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(double a, double b, V2d c)\n        {\n            X = (int)a;\n            Y = (int)b;\n            Z = (int)c.X;\n            W = (int)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(Func<int, int> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n            W = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;int&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 4.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(IVector<double> v)\n            : this(v[0], v[1], v[2], v[3])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2i v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V2d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3i v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V3d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V4i v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V4ui v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n            W = (int)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V4l v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n            W = (int)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V4f v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n            W = (int)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(V4d v)\n        {\n            X = (int)v.X;\n            Y = (int)v.Y;\n            Z = (int)v.Z;\n            W = (int)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(C3b c)\n        {\n            X = (int)(c.R);\n            Y = (int)(c.G);\n            Z = (int)(c.B);\n            W = (int)255;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(C3us c)\n        {\n            X = (int)(c.R);\n            Y = (int)(c.G);\n            Z = (int)(c.B);\n            W = (int)65535;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(C4b c)\n        {\n            X = (int)(c.R);\n            Y = (int)(c.G);\n            Z = (int)(c.B);\n            W = (int)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4i(C4us c)\n        {\n            X = (int)(c.R);\n            Y = (int)(c.G);\n            Z = (int)(c.B);\n            W = (int)(c.A);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V2i v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V2ui v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V2l v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V2f v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V2d v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V3i v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V3ui v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V3l v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V3f v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V3d v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V4ui v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V4l v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V4f v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(V4d v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V4i v)\n            => new int[] { v.X, v.Y, v.Z, v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(int[] v)\n            => new V4i(v[0], v[1], v[2], v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V4i v)\n            => new uint[] { (uint)v.X, (uint)v.Y, (uint)v.Z, (uint)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(uint[] v)\n            => new V4i((int)v[0], (int)v[1], (int)v[2], (int)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V4i v)\n            => new long[] { (long)v.X, (long)v.Y, (long)v.Z, (long)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(long[] v)\n            => new V4i((int)v[0], (int)v[1], (int)v[2], (int)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V4i v)\n            => new float[] { (float)v.X, (float)v.Y, (float)v.Z, (float)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(float[] v)\n            => new V4i((int)v[0], (int)v[1], (int)v[2], (int)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V4i v)\n            => new double[] { (double)v.X, (double)v.Y, (double)v.Z, (double)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(double[] v)\n            => new V4i((int)v[0], (int)v[1], (int)v[2], (int)v[3]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(C3b v)\n            => new V4i(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4i\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(C3us v)\n            => new V4i(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4i\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(C4b v)\n            => new V4i(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4i\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4i\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4i(C4us v)\n            => new V4i(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4i\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<int, int> element_fun)\n            => new V4i(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<int, int, int> element_index_fun)\n            => new V4i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n            array[start + 3] = W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<int, uint> element_fun)\n            => new V4ui(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<int, int, uint> element_index_fun)\n            => new V4ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n            array[start + 2] = (uint)Z;\n            array[start + 3] = (uint)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<int, long> element_fun)\n            => new V4l(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<int, int, long> element_index_fun)\n            => new V4l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n            array[start + 2] = (long)Z;\n            array[start + 3] = (long)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<int, float> element_fun)\n            => new V4f(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<int, int, float> element_index_fun)\n            => new V4f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n            array[start + 2] = (float)Z;\n            array[start + 3] = (float)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<int, double> element_fun)\n            => new V4d(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<int, int, double> element_index_fun)\n            => new V4d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n            array[start + 2] = (double)Z;\n            array[start + 3] = (double)W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<int, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n            array[start + 3] = element_fun(W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<int, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n            array[start + 3] = element_index_fun(W, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly int[] ToArray()\n            => new int[] { X, Y, Z, W };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field W.\n        /// Useful when properties are required, but the field W is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public int P_W\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return W;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                W = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<int> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n                yield return W;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe int this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (int* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (int* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y\n                        ? (X >= Z ? (X >= W ? 0 : 3) : (Z >= W ? 2 : 3))\n                        : (Y >= Z ? (Y >= W ? 1 : 3) : (Z >= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y\n                        ? (X <= Z ? (X <= W ? 0 : 3) : (Z <= W ? 2 : 3))\n                        : (Y <= Z ? (Y <= W ? 1 : 3) : (Z <= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly int MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z, W);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly int MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z, W);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 4;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V4i Zero\n        {\n            get { return new V4i(0, 0, 0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V4i One\n        {\n            get { return new V4i(1, 1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V4i MaxValue\n        {\n            get { return new V4i(Constant<int>.ParseableMaxValue, Constant<int>.ParseableMaxValue, Constant<int>.ParseableMaxValue, Constant<int>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V4i MinValue\n        {\n            get { return new V4i(Constant<int>.ParseableMinValue, Constant<int>.ParseableMinValue, Constant<int>.ParseableMinValue, Constant<int>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V4i XAxis\n        {\n            get { return new V4i(1, 0, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V4i YAxis\n        {\n            get { return new V4i(0, 1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V4i ZAxis\n        {\n            get { return new V4i(0, 0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized W-axis.\n        /// </summary>\n        public static V4i WAxis\n        {\n            get { return new V4i(0, 0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V4i, int>[] SelectorArray =\n            new Func<V4i, int>[] { v => v.X, v => v.Y, v => v.Z, v => v.W };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V4i, int, int> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V4i, int, int> Setter =\n            (ref V4i v, int i, int s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V4i, long, int> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V4i, long, int> LongSetter =\n            (ref V4i v, long i, int s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FromV4ui(V4ui v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FromV4l(V4l v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FromV4f(V4f v)\n            => new V4i(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FromV4d(V4d v)\n            => new V4i(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FromC3b(C3b c) => new V4i(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FromC3us(C3us c) => new V4i(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FromC4b(C4b c) => new V4i(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FromC4us(C4us c) => new V4i(c);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly int LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z  + W * W ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z  + W * W );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly int Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y) + Fun.Abs(Z) + Fun.Abs(W); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z + W * W); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly int NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly int NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V4d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V4d.Zero;\n                s = 1 / s;\n                return new V4d(X * s, Y * s, Z * s, W * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Abs(V4i v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i LinearInterp(float t, V4i a, V4i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i LinearInterp(V4f t, V4i a, V4i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i LinearInterp(double t, V4i a, V4i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i LinearInterp(V4d t, V4i a, V4i b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Min(V4i v0, V4i v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Min(V4i v, int x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Max(V4i v0, V4i v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Max(V4i v, int x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Saturate(V4i v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i DivideByInt(V4i v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z, int w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z, uint w)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n            W = (int)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z, long w)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n            W = (int)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z, float w)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n            W = (int)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z, double w)\n        {\n            X = (int)x;\n            Y = (int)y;\n            Z = (int)z;\n            W = (int)w;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator -(V4i v)\n            => new V4i(-v.X, -v.Y, -v.Z, -v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator ~(V4i v)\n            => new V4i(~v.X, ~v.Y, ~v.Z, ~v.W);\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator +(V4i a, V4i b)\n            => new V4i(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator +(V4i v, int s)\n            => new V4i(v.X + s, v.Y + s, v.Z + s, v.W + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator +(int s, V4i v)\n            => new V4i(s + v.X, s + v.Y, s + v.Z, s + v.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator -(V4i a, V4i b)\n            => new V4i(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator -(V4i v, int s)\n            => new V4i(v.X - s, v.Y - s, v.Z - s, v.W - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator -(int s, V4i v)\n            => new V4i(s - v.X, s - v.Y, s - v.Z, s - v.W);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator *(V4i a, V4i b)\n            => new V4i(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator *(V4i v, int s)\n            => new V4i(v.X * s, v.Y * s, v.Z * s, v.W * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator *(int s, V4i v)\n            => new V4i(s * v.X, s * v.Y, s * v.Z, s * v.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator /(V4i a, V4i b)\n            => new V4i(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator /(V4i v, int s)\n            => new V4i(v.X / s, v.Y / s, v.Z / s, v.W / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator /(int s, V4i v)\n            => new V4i(s / v.X, s / v.Y, s / v.Z, s / v.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator %(V4i a, V4i b)\n            => new V4i(a.X % b.X, a.Y % b.Y, a.Z % b.Z, a.W % b.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator %(V4i v, int s)\n            => new V4i(v.X % s, v.Y % s, v.Z % s, v.W % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator %(int s, V4i v)\n            => new V4i(s % v.X, s % v.Y, s % v.Z, s % v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator &(V4i a, V4i b)\n            => new V4i(a.X & b.X, a.Y & b.Y, a.Z & b.Z, a.W & b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator &(V4i v, int s)\n            => new V4i(v.X & s, v.Y & s, v.Z & s, v.W & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator &(int s, V4i v)\n            => new V4i(s & v.X, s & v.Y, s & v.Z, s & v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator |(V4i a, V4i b)\n            => new V4i(a.X | b.X, a.Y | b.Y, a.Z | b.Z, a.W | b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator |(V4i v, int s)\n            => new V4i(v.X | s, v.Y | s, v.Z | s, v.W | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator |(int s, V4i v)\n            => new V4i(s | v.X, s | v.Y, s | v.Z, s | v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator ^(V4i a, V4i b)\n            => new V4i(a.X ^ b.X, a.Y ^ b.Y, a.Z ^ b.Z, a.W ^ b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator ^(V4i v, int s)\n            => new V4i(v.X ^ s, v.Y ^ s, v.Z ^ s, v.W ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator ^(int s, V4i v)\n            => new V4i(s ^ v.X, s ^ v.Y, s ^ v.Z, s ^ v.W);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator <<(V4i v, int s)\n            => new V4i(v.X << s, v.Y << s, v.Z << s, v.W << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i operator >>(V4i v, int s)\n            => new V4i(v.X >> s, v.Y >> s, v.Z >> s, v.W >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4i a, V4i b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4i v, int s)\n        {\n            return v.X == s && v.Y == s && v.Z == s && v.W == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(int s, V4i v)\n        {\n            return s == v.X && s == v.Y && s == v.Z && s == v.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4i a, V4i b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4i v, int s)\n        {\n            return v.X != s || v.Y != s || v.Z != s || v.W != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(int s, V4i v)\n        {\n            return s != v.X || s != v.Y || s != v.Z || s != v.W;\n        }\n\n        #endregion\n\n        #region IEquatable<V4i> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V4i other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + between + W.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z, W);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V4i o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + W.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V4i Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V4i(\n                int.Parse(x[0], CultureInfo.InvariantCulture), \n                int.Parse(x[1], CultureInfo.InvariantCulture), \n                int.Parse(x[2], CultureInfo.InvariantCulture), \n                int.Parse(x[3], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V4i Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<int>.Parse, V4i.Setter);\n        }\n\n        public static V4i Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<int>.Parse, V4i.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OX => new V2i(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OY => new V2i(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OZ => new V2i(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i OW => new V2i(0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IX => new V2i(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IY => new V2i(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IZ => new V2i(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i IW => new V2i(1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NX => new V2i(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NY => new V2i(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NZ => new V2i(-1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i NW => new V2i(-1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XO => new V2i(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XI => new V2i(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XN => new V2i(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i XX => new V2i(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i XY\n        {\n            readonly get => new V2i(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i XZ\n        {\n            readonly get => new V2i(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i XW\n        {\n            readonly get => new V2i(X, W);\n            set { X = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YO => new V2i(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YI => new V2i(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YN => new V2i(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i YX\n        {\n            readonly get => new V2i(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i YY => new V2i(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i YZ\n        {\n            readonly get => new V2i(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i YW\n        {\n            readonly get => new V2i(Y, W);\n            set { Y = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i ZO => new V2i(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i ZI => new V2i(Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i ZN => new V2i(Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i ZX\n        {\n            readonly get => new V2i(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i ZY\n        {\n            readonly get => new V2i(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i ZZ => new V2i(Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i ZW\n        {\n            readonly get => new V2i(Z, W);\n            set { Z = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i WO => new V2i(W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i WI => new V2i(W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i WN => new V2i(W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i WX\n        {\n            readonly get => new V2i(W, X);\n            set { W = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i WY\n        {\n            readonly get => new V2i(W, Y);\n            set { W = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2i WZ\n        {\n            readonly get => new V2i(W, Z);\n            set { W = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2i WW => new V2i(W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOX => new V3i(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOY => new V3i(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOZ => new V3i(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OOW => new V3i(0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIX => new V3i(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIY => new V3i(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIZ => new V3i(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OIW => new V3i(0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONX => new V3i(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONY => new V3i(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONZ => new V3i(0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ONW => new V3i(0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXO => new V3i(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXI => new V3i(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXN => new V3i(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXX => new V3i(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXY => new V3i(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXZ => new V3i(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OXW => new V3i(0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYO => new V3i(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYI => new V3i(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYN => new V3i(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYX => new V3i(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYY => new V3i(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYZ => new V3i(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OYW => new V3i(0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZO => new V3i(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZI => new V3i(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZN => new V3i(0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZX => new V3i(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZY => new V3i(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZZ => new V3i(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OZW => new V3i(0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OWO => new V3i(0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OWI => new V3i(0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OWN => new V3i(0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OWX => new V3i(0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OWY => new V3i(0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OWZ => new V3i(0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i OWW => new V3i(0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOX => new V3i(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOY => new V3i(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOZ => new V3i(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IOW => new V3i(1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIX => new V3i(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIY => new V3i(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIZ => new V3i(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IIW => new V3i(1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNX => new V3i(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNY => new V3i(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNZ => new V3i(1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PNW => new V3i(1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXO => new V3i(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXI => new V3i(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PXN => new V3i(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXX => new V3i(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXY => new V3i(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXZ => new V3i(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IXW => new V3i(1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYO => new V3i(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYI => new V3i(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PYN => new V3i(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYX => new V3i(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYY => new V3i(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYZ => new V3i(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IYW => new V3i(1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZO => new V3i(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZI => new V3i(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PZN => new V3i(1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZX => new V3i(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZY => new V3i(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZZ => new V3i(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IZW => new V3i(1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IWO => new V3i(1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IWI => new V3i(1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i PWN => new V3i(1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IWX => new V3i(1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IWY => new V3i(1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IWZ => new V3i(1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i IWW => new V3i(1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOX => new V3i(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOY => new V3i(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOZ => new V3i(-1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NOW => new V3i(-1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPX => new V3i(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPY => new V3i(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPZ => new V3i(-1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NPW => new V3i(-1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNX => new V3i(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNY => new V3i(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNZ => new V3i(-1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NNW => new V3i(-1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXO => new V3i(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXP => new V3i(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXN => new V3i(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXX => new V3i(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXY => new V3i(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXZ => new V3i(-1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NXW => new V3i(-1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYO => new V3i(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYP => new V3i(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYN => new V3i(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYX => new V3i(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYY => new V3i(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYZ => new V3i(-1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NYW => new V3i(-1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZO => new V3i(-1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZP => new V3i(-1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZN => new V3i(-1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZX => new V3i(-1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZY => new V3i(-1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZZ => new V3i(-1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NZW => new V3i(-1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NWO => new V3i(-1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NWP => new V3i(-1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NWN => new V3i(-1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NWX => new V3i(-1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NWY => new V3i(-1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NWZ => new V3i(-1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i NWW => new V3i(-1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOO => new V3i(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOI => new V3i(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XON => new V3i(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOX => new V3i(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOY => new V3i(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOZ => new V3i(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XOW => new V3i(X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIO => new V3i(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XII => new V3i(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XPN => new V3i(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIX => new V3i(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIY => new V3i(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIZ => new V3i(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XIW => new V3i(X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNO => new V3i(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNP => new V3i(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNN => new V3i(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNX => new V3i(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNY => new V3i(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNZ => new V3i(X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XNW => new V3i(X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXO => new V3i(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXI => new V3i(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXN => new V3i(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXX => new V3i(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXY => new V3i(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXZ => new V3i(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XXW => new V3i(X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYO => new V3i(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYI => new V3i(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYN => new V3i(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYX => new V3i(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XYY => new V3i(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i XYZ\n        {\n            readonly get => new V3i(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i XYW\n        {\n            readonly get => new V3i(X, Y, W);\n            set { X = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZO => new V3i(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZI => new V3i(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZN => new V3i(X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZX => new V3i(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i XZY\n        {\n            readonly get => new V3i(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XZZ => new V3i(X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i XZW\n        {\n            readonly get => new V3i(X, Z, W);\n            set { X = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XWO => new V3i(X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XWI => new V3i(X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XWN => new V3i(X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XWX => new V3i(X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i XWY\n        {\n            readonly get => new V3i(X, W, Y);\n            set { X = value.X; W = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i XWZ\n        {\n            readonly get => new V3i(X, W, Z);\n            set { X = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i XWW => new V3i(X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOO => new V3i(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOI => new V3i(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YON => new V3i(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOX => new V3i(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOY => new V3i(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOZ => new V3i(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YOW => new V3i(Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIO => new V3i(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YII => new V3i(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YPN => new V3i(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIX => new V3i(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIY => new V3i(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIZ => new V3i(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YIW => new V3i(Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNO => new V3i(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNP => new V3i(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNN => new V3i(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNX => new V3i(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNY => new V3i(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNZ => new V3i(Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YNW => new V3i(Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXO => new V3i(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXI => new V3i(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXN => new V3i(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXX => new V3i(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YXY => new V3i(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i YXZ\n        {\n            readonly get => new V3i(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i YXW\n        {\n            readonly get => new V3i(Y, X, W);\n            set { Y = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYO => new V3i(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYI => new V3i(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYN => new V3i(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYX => new V3i(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYY => new V3i(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYZ => new V3i(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YYW => new V3i(Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZO => new V3i(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZI => new V3i(Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZN => new V3i(Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i YZX\n        {\n            readonly get => new V3i(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZY => new V3i(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YZZ => new V3i(Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i YZW\n        {\n            readonly get => new V3i(Y, Z, W);\n            set { Y = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YWO => new V3i(Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YWI => new V3i(Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YWN => new V3i(Y, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i YWX\n        {\n            readonly get => new V3i(Y, W, X);\n            set { Y = value.X; W = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YWY => new V3i(Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i YWZ\n        {\n            readonly get => new V3i(Y, W, Z);\n            set { Y = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i YWW => new V3i(Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOO => new V3i(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOI => new V3i(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZON => new V3i(Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOX => new V3i(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOY => new V3i(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOZ => new V3i(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZOW => new V3i(Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIO => new V3i(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZII => new V3i(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZPN => new V3i(Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIX => new V3i(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIY => new V3i(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIZ => new V3i(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZIW => new V3i(Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNO => new V3i(Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNP => new V3i(Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNN => new V3i(Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNX => new V3i(Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNY => new V3i(Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNZ => new V3i(Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZNW => new V3i(Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXO => new V3i(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXI => new V3i(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXN => new V3i(Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXX => new V3i(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i ZXY\n        {\n            readonly get => new V3i(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZXZ => new V3i(Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i ZXW\n        {\n            readonly get => new V3i(Z, X, W);\n            set { Z = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYO => new V3i(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYI => new V3i(Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYN => new V3i(Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i ZYX\n        {\n            readonly get => new V3i(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYY => new V3i(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZYZ => new V3i(Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i ZYW\n        {\n            readonly get => new V3i(Z, Y, W);\n            set { Z = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZO => new V3i(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZI => new V3i(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZN => new V3i(Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZX => new V3i(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZY => new V3i(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZZ => new V3i(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZZW => new V3i(Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZWO => new V3i(Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZWI => new V3i(Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZWN => new V3i(Z, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i ZWX\n        {\n            readonly get => new V3i(Z, W, X);\n            set { Z = value.X; W = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i ZWY\n        {\n            readonly get => new V3i(Z, W, Y);\n            set { Z = value.X; W = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZWZ => new V3i(Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i ZWW => new V3i(Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WOO => new V3i(W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WOI => new V3i(W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WON => new V3i(W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WOX => new V3i(W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WOY => new V3i(W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WOZ => new V3i(W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WOW => new V3i(W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WIO => new V3i(W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WII => new V3i(W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WPN => new V3i(W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WIX => new V3i(W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WIY => new V3i(W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WIZ => new V3i(W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WIW => new V3i(W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WNO => new V3i(W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WNP => new V3i(W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WNN => new V3i(W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WNX => new V3i(W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WNY => new V3i(W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WNZ => new V3i(W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WNW => new V3i(W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WXO => new V3i(W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WXI => new V3i(W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WXN => new V3i(W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WXX => new V3i(W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i WXY\n        {\n            readonly get => new V3i(W, X, Y);\n            set { W = value.X; X = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i WXZ\n        {\n            readonly get => new V3i(W, X, Z);\n            set { W = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WXW => new V3i(W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WYO => new V3i(W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WYI => new V3i(W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WYN => new V3i(W, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i WYX\n        {\n            readonly get => new V3i(W, Y, X);\n            set { W = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WYY => new V3i(W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i WYZ\n        {\n            readonly get => new V3i(W, Y, Z);\n            set { W = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WYW => new V3i(W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WZO => new V3i(W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WZI => new V3i(W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WZN => new V3i(W, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i WZX\n        {\n            readonly get => new V3i(W, Z, X);\n            set { W = value.X; Z = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3i WZY\n        {\n            readonly get => new V3i(W, Z, Y);\n            set { W = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WZZ => new V3i(W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WZW => new V3i(W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WWO => new V3i(W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WWI => new V3i(W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WWN => new V3i(W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WWX => new V3i(W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WWY => new V3i(W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WWZ => new V3i(W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3i WWW => new V3i(W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OOOO => new V4i(0, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OOOI => new V4i(0, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OOON => new V4i(0, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOX => new V4i(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOY => new V4i(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOZ => new V4i(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOOW => new V4i(0, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OOIO => new V4i(0, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OOII => new V4i(0, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OOPN => new V4i(0, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIX => new V4i(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIY => new V4i(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIZ => new V4i(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOIW => new V4i(0, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OONO => new V4i(0, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OONP => new V4i(0, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OONN => new V4i(0, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONX => new V4i(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONY => new V4i(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONZ => new V4i(0, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OONW => new V4i(0, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXO => new V4i(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXI => new V4i(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXN => new V4i(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXX => new V4i(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXY => new V4i(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXZ => new V4i(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOXW => new V4i(0, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYO => new V4i(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYI => new V4i(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYN => new V4i(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYX => new V4i(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYY => new V4i(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYZ => new V4i(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOYW => new V4i(0, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZO => new V4i(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZI => new V4i(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZN => new V4i(0, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZX => new V4i(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZY => new V4i(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZZ => new V4i(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOZW => new V4i(0, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOWO => new V4i(0, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOWI => new V4i(0, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOWN => new V4i(0, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOWX => new V4i(0, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOWY => new V4i(0, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOWZ => new V4i(0, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OOWW => new V4i(0, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OIOO => new V4i(0, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OIOI => new V4i(0, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OPON => new V4i(0, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOX => new V4i(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOY => new V4i(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOZ => new V4i(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIOW => new V4i(0, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OIIO => new V4i(0, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OIII => new V4i(0, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OPPN => new V4i(0, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIX => new V4i(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIY => new V4i(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIZ => new V4i(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIIW => new V4i(0, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OPNO => new V4i(0, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OPNP => new V4i(0, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i OPNN => new V4i(0, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNX => new V4i(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNY => new V4i(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNZ => new V4i(0, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPNW => new V4i(0, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXO => new V4i(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXI => new V4i(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPXN => new V4i(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXX => new V4i(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXY => new V4i(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXZ => new V4i(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIXW => new V4i(0, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYO => new V4i(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYI => new V4i(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPYN => new V4i(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYX => new V4i(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYY => new V4i(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYZ => new V4i(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIYW => new V4i(0, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZO => new V4i(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZI => new V4i(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPZN => new V4i(0, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZX => new V4i(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZY => new V4i(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZZ => new V4i(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIZW => new V4i(0, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIWO => new V4i(0, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIWI => new V4i(0, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OPWN => new V4i(0, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIWX => new V4i(0, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIWY => new V4i(0, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIWZ => new V4i(0, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OIWW => new V4i(0, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONOO => new V4i(0, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONOP => new V4i(0, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONON => new V4i(0, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOX => new V4i(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOY => new V4i(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOZ => new V4i(0, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONOW => new V4i(0, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONPO => new V4i(0, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONPP => new V4i(0, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONPN => new V4i(0, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPX => new V4i(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPY => new V4i(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPZ => new V4i(0, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONPW => new V4i(0, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONNO => new V4i(0, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONNP => new V4i(0, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i ONNN => new V4i(0, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNX => new V4i(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNY => new V4i(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNZ => new V4i(0, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONNW => new V4i(0, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXO => new V4i(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXP => new V4i(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXN => new V4i(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXX => new V4i(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXY => new V4i(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXZ => new V4i(0, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONXW => new V4i(0, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYO => new V4i(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYP => new V4i(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYN => new V4i(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYX => new V4i(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYY => new V4i(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYZ => new V4i(0, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONYW => new V4i(0, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZO => new V4i(0, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZP => new V4i(0, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZN => new V4i(0, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZX => new V4i(0, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZY => new V4i(0, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZZ => new V4i(0, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONZW => new V4i(0, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONWO => new V4i(0, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONWP => new V4i(0, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONWN => new V4i(0, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONWX => new V4i(0, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONWY => new V4i(0, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONWZ => new V4i(0, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ONWW => new V4i(0, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOO => new V4i(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOI => new V4i(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXON => new V4i(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOX => new V4i(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOY => new V4i(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOZ => new V4i(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXOW => new V4i(0, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIO => new V4i(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXII => new V4i(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXPN => new V4i(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIX => new V4i(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIY => new V4i(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIZ => new V4i(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXIW => new V4i(0, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNO => new V4i(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNP => new V4i(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNN => new V4i(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNX => new V4i(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNY => new V4i(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNZ => new V4i(0, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXNW => new V4i(0, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXO => new V4i(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXI => new V4i(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXN => new V4i(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXX => new V4i(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXY => new V4i(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXZ => new V4i(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXXW => new V4i(0, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYO => new V4i(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYI => new V4i(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYN => new V4i(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYX => new V4i(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYY => new V4i(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYZ => new V4i(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXYW => new V4i(0, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZO => new V4i(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZI => new V4i(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZN => new V4i(0, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZX => new V4i(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZY => new V4i(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZZ => new V4i(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXZW => new V4i(0, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXWO => new V4i(0, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXWI => new V4i(0, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXWN => new V4i(0, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXWX => new V4i(0, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXWY => new V4i(0, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXWZ => new V4i(0, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OXWW => new V4i(0, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOO => new V4i(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOI => new V4i(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYON => new V4i(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOX => new V4i(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOY => new V4i(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOZ => new V4i(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYOW => new V4i(0, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIO => new V4i(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYII => new V4i(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYPN => new V4i(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIX => new V4i(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIY => new V4i(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIZ => new V4i(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYIW => new V4i(0, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNO => new V4i(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNP => new V4i(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNN => new V4i(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNX => new V4i(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNY => new V4i(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNZ => new V4i(0, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYNW => new V4i(0, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXO => new V4i(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXI => new V4i(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXN => new V4i(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXX => new V4i(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXY => new V4i(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXZ => new V4i(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYXW => new V4i(0, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYO => new V4i(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYI => new V4i(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYN => new V4i(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYX => new V4i(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYY => new V4i(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYZ => new V4i(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYYW => new V4i(0, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZO => new V4i(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZI => new V4i(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZN => new V4i(0, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZX => new V4i(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZY => new V4i(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZZ => new V4i(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYZW => new V4i(0, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYWO => new V4i(0, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYWI => new V4i(0, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYWN => new V4i(0, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYWX => new V4i(0, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYWY => new V4i(0, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYWZ => new V4i(0, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OYWW => new V4i(0, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOO => new V4i(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOI => new V4i(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZON => new V4i(0, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOX => new V4i(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOY => new V4i(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOZ => new V4i(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZOW => new V4i(0, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIO => new V4i(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZII => new V4i(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZPN => new V4i(0, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIX => new V4i(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIY => new V4i(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIZ => new V4i(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZIW => new V4i(0, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNO => new V4i(0, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNP => new V4i(0, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNN => new V4i(0, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNX => new V4i(0, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNY => new V4i(0, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNZ => new V4i(0, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZNW => new V4i(0, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXO => new V4i(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXI => new V4i(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXN => new V4i(0, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXX => new V4i(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXY => new V4i(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXZ => new V4i(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZXW => new V4i(0, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYO => new V4i(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYI => new V4i(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYN => new V4i(0, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYX => new V4i(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYY => new V4i(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYZ => new V4i(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZYW => new V4i(0, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZO => new V4i(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZI => new V4i(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZN => new V4i(0, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZX => new V4i(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZY => new V4i(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZZ => new V4i(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZZW => new V4i(0, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZWO => new V4i(0, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZWI => new V4i(0, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZWN => new V4i(0, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZWX => new V4i(0, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZWY => new V4i(0, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZWZ => new V4i(0, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OZWW => new V4i(0, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWOO => new V4i(0, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWOI => new V4i(0, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWON => new V4i(0, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWOX => new V4i(0, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWOY => new V4i(0, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWOZ => new V4i(0, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWOW => new V4i(0, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWIO => new V4i(0, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWII => new V4i(0, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWPN => new V4i(0, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWIX => new V4i(0, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWIY => new V4i(0, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWIZ => new V4i(0, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWIW => new V4i(0, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWNO => new V4i(0, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWNP => new V4i(0, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWNN => new V4i(0, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWNX => new V4i(0, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWNY => new V4i(0, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWNZ => new V4i(0, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWNW => new V4i(0, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWXO => new V4i(0, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWXI => new V4i(0, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWXN => new V4i(0, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWXX => new V4i(0, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWXY => new V4i(0, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWXZ => new V4i(0, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWXW => new V4i(0, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWYO => new V4i(0, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWYI => new V4i(0, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWYN => new V4i(0, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWYX => new V4i(0, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWYY => new V4i(0, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWYZ => new V4i(0, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWYW => new V4i(0, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWZO => new V4i(0, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWZI => new V4i(0, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWZN => new V4i(0, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWZX => new V4i(0, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWZY => new V4i(0, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWZZ => new V4i(0, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWZW => new V4i(0, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWWO => new V4i(0, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWWI => new V4i(0, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWWN => new V4i(0, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWWX => new V4i(0, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWWY => new V4i(0, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWWZ => new V4i(0, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i OWWW => new V4i(0, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i IOOO => new V4i(1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i IOOI => new V4i(1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i POON => new V4i(1, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOX => new V4i(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOY => new V4i(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOZ => new V4i(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOOW => new V4i(1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i IOIO => new V4i(1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i IOII => new V4i(1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i POPN => new V4i(1, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIX => new V4i(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIY => new V4i(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIZ => new V4i(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOIW => new V4i(1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PONO => new V4i(1, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PONP => new V4i(1, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PONN => new V4i(1, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONX => new V4i(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONY => new V4i(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONZ => new V4i(1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PONW => new V4i(1, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXO => new V4i(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXI => new V4i(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POXN => new V4i(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXX => new V4i(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXY => new V4i(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXZ => new V4i(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOXW => new V4i(1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYO => new V4i(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYI => new V4i(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POYN => new V4i(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYX => new V4i(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYY => new V4i(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYZ => new V4i(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOYW => new V4i(1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZO => new V4i(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZI => new V4i(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POZN => new V4i(1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZX => new V4i(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZY => new V4i(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZZ => new V4i(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOZW => new V4i(1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOWO => new V4i(1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOWI => new V4i(1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i POWN => new V4i(1, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOWX => new V4i(1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOWY => new V4i(1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOWZ => new V4i(1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IOWW => new V4i(1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i IIOO => new V4i(1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i IIOI => new V4i(1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PPON => new V4i(1, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOX => new V4i(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOY => new V4i(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOZ => new V4i(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIOW => new V4i(1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i IIIO => new V4i(1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i IIII => new V4i(1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PPPN => new V4i(1, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIX => new V4i(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIY => new V4i(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIZ => new V4i(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIIW => new V4i(1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PPNO => new V4i(1, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PPNP => new V4i(1, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PPNN => new V4i(1, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNX => new V4i(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNY => new V4i(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNZ => new V4i(1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPNW => new V4i(1, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXO => new V4i(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXI => new V4i(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPXN => new V4i(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXX => new V4i(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXY => new V4i(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXZ => new V4i(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIXW => new V4i(1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYO => new V4i(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYI => new V4i(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPYN => new V4i(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYX => new V4i(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYY => new V4i(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYZ => new V4i(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIYW => new V4i(1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZO => new V4i(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZI => new V4i(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPZN => new V4i(1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZX => new V4i(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZY => new V4i(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZZ => new V4i(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIZW => new V4i(1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIWO => new V4i(1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIWI => new V4i(1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PPWN => new V4i(1, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIWX => new V4i(1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIWY => new V4i(1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIWZ => new V4i(1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IIWW => new V4i(1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNOO => new V4i(1, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNOP => new V4i(1, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNON => new V4i(1, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOX => new V4i(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOY => new V4i(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOZ => new V4i(1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNOW => new V4i(1, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNPO => new V4i(1, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNPP => new V4i(1, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNPN => new V4i(1, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPX => new V4i(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPY => new V4i(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPZ => new V4i(1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNPW => new V4i(1, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNNO => new V4i(1, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNNP => new V4i(1, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i PNNN => new V4i(1, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNX => new V4i(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNY => new V4i(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNZ => new V4i(1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNNW => new V4i(1, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXO => new V4i(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXP => new V4i(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXN => new V4i(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXX => new V4i(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXY => new V4i(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXZ => new V4i(1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNXW => new V4i(1, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYO => new V4i(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYP => new V4i(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYN => new V4i(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYX => new V4i(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYY => new V4i(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYZ => new V4i(1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNYW => new V4i(1, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZO => new V4i(1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZP => new V4i(1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZN => new V4i(1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZX => new V4i(1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZY => new V4i(1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZZ => new V4i(1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNZW => new V4i(1, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNWO => new V4i(1, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNWP => new V4i(1, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNWN => new V4i(1, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNWX => new V4i(1, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNWY => new V4i(1, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNWZ => new V4i(1, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PNWW => new V4i(1, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOO => new V4i(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOI => new V4i(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXON => new V4i(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOX => new V4i(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOY => new V4i(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOZ => new V4i(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXOW => new V4i(1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIO => new V4i(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXII => new V4i(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXPN => new V4i(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIX => new V4i(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIY => new V4i(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIZ => new V4i(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXIW => new V4i(1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNO => new V4i(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNP => new V4i(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNN => new V4i(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNX => new V4i(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNY => new V4i(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNZ => new V4i(1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXNW => new V4i(1, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXO => new V4i(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXI => new V4i(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXXN => new V4i(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXX => new V4i(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXY => new V4i(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXZ => new V4i(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXXW => new V4i(1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYO => new V4i(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYI => new V4i(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXYN => new V4i(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYX => new V4i(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYY => new V4i(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYZ => new V4i(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXYW => new V4i(1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZO => new V4i(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZI => new V4i(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXZN => new V4i(1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZX => new V4i(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZY => new V4i(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZZ => new V4i(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXZW => new V4i(1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXWO => new V4i(1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXWI => new V4i(1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PXWN => new V4i(1, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXWX => new V4i(1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXWY => new V4i(1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXWZ => new V4i(1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IXWW => new V4i(1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOO => new V4i(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOI => new V4i(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYON => new V4i(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOX => new V4i(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOY => new V4i(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOZ => new V4i(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYOW => new V4i(1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIO => new V4i(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYII => new V4i(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYPN => new V4i(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIX => new V4i(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIY => new V4i(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIZ => new V4i(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYIW => new V4i(1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNO => new V4i(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNP => new V4i(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNN => new V4i(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNX => new V4i(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNY => new V4i(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNZ => new V4i(1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYNW => new V4i(1, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXO => new V4i(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXI => new V4i(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYXN => new V4i(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXX => new V4i(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXY => new V4i(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXZ => new V4i(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYXW => new V4i(1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYO => new V4i(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYI => new V4i(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYYN => new V4i(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYX => new V4i(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYY => new V4i(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYZ => new V4i(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYYW => new V4i(1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZO => new V4i(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZI => new V4i(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYZN => new V4i(1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZX => new V4i(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZY => new V4i(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZZ => new V4i(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYZW => new V4i(1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYWO => new V4i(1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYWI => new V4i(1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PYWN => new V4i(1, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYWX => new V4i(1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYWY => new V4i(1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYWZ => new V4i(1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IYWW => new V4i(1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOO => new V4i(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOI => new V4i(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZON => new V4i(1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOX => new V4i(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOY => new V4i(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOZ => new V4i(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZOW => new V4i(1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIO => new V4i(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZII => new V4i(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZPN => new V4i(1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIX => new V4i(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIY => new V4i(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIZ => new V4i(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZIW => new V4i(1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNO => new V4i(1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNP => new V4i(1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNN => new V4i(1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNX => new V4i(1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNY => new V4i(1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNZ => new V4i(1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZNW => new V4i(1, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXO => new V4i(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXI => new V4i(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZXN => new V4i(1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXX => new V4i(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXY => new V4i(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXZ => new V4i(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZXW => new V4i(1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYO => new V4i(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYI => new V4i(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZYN => new V4i(1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYX => new V4i(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYY => new V4i(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYZ => new V4i(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZYW => new V4i(1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZO => new V4i(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZI => new V4i(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZZN => new V4i(1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZX => new V4i(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZY => new V4i(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZZ => new V4i(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZZW => new V4i(1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZWO => new V4i(1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZWI => new V4i(1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PZWN => new V4i(1, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZWX => new V4i(1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZWY => new V4i(1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZWZ => new V4i(1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IZWW => new V4i(1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWOO => new V4i(1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWOI => new V4i(1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWON => new V4i(1, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWOX => new V4i(1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWOY => new V4i(1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWOZ => new V4i(1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWOW => new V4i(1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWIO => new V4i(1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWII => new V4i(1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWPN => new V4i(1, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWIX => new V4i(1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWIY => new V4i(1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWIZ => new V4i(1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWIW => new V4i(1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWNO => new V4i(1, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWNP => new V4i(1, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWNN => new V4i(1, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWNX => new V4i(1, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWNY => new V4i(1, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWNZ => new V4i(1, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWNW => new V4i(1, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWXO => new V4i(1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWXI => new V4i(1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWXN => new V4i(1, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWXX => new V4i(1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWXY => new V4i(1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWXZ => new V4i(1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWXW => new V4i(1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWYO => new V4i(1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWYI => new V4i(1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWYN => new V4i(1, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWYX => new V4i(1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWYY => new V4i(1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWYZ => new V4i(1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWYW => new V4i(1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWZO => new V4i(1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWZI => new V4i(1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWZN => new V4i(1, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWZX => new V4i(1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWZY => new V4i(1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWZZ => new V4i(1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWZW => new V4i(1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWWO => new V4i(1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWWI => new V4i(1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i PWWN => new V4i(1, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWWX => new V4i(1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWWY => new V4i(1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWWZ => new V4i(1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i IWWW => new V4i(1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NOOO => new V4i(-1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NOOP => new V4i(-1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NOON => new V4i(-1, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOX => new V4i(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOY => new V4i(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOZ => new V4i(-1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOOW => new V4i(-1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NOPO => new V4i(-1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NOPP => new V4i(-1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NOPN => new V4i(-1, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPX => new V4i(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPY => new V4i(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPZ => new V4i(-1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOPW => new V4i(-1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NONO => new V4i(-1, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NONP => new V4i(-1, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NONN => new V4i(-1, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONX => new V4i(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONY => new V4i(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONZ => new V4i(-1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NONW => new V4i(-1, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXO => new V4i(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXP => new V4i(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXN => new V4i(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXX => new V4i(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXY => new V4i(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXZ => new V4i(-1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOXW => new V4i(-1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYO => new V4i(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYP => new V4i(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYN => new V4i(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYX => new V4i(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYY => new V4i(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYZ => new V4i(-1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOYW => new V4i(-1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZO => new V4i(-1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZP => new V4i(-1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZN => new V4i(-1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZX => new V4i(-1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZY => new V4i(-1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZZ => new V4i(-1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOZW => new V4i(-1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOWO => new V4i(-1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOWP => new V4i(-1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOWN => new V4i(-1, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOWX => new V4i(-1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOWY => new V4i(-1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOWZ => new V4i(-1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NOWW => new V4i(-1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPOO => new V4i(-1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPOP => new V4i(-1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPON => new V4i(-1, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOX => new V4i(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOY => new V4i(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOZ => new V4i(-1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPOW => new V4i(-1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPPO => new V4i(-1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPPP => new V4i(-1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPPN => new V4i(-1, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPX => new V4i(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPY => new V4i(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPZ => new V4i(-1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPPW => new V4i(-1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPNO => new V4i(-1, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPNP => new V4i(-1, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NPNN => new V4i(-1, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNX => new V4i(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNY => new V4i(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNZ => new V4i(-1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPNW => new V4i(-1, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXO => new V4i(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXP => new V4i(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXN => new V4i(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXX => new V4i(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXY => new V4i(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXZ => new V4i(-1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPXW => new V4i(-1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYO => new V4i(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYP => new V4i(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYN => new V4i(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYX => new V4i(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYY => new V4i(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYZ => new V4i(-1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPYW => new V4i(-1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZO => new V4i(-1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZP => new V4i(-1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZN => new V4i(-1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZX => new V4i(-1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZY => new V4i(-1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZZ => new V4i(-1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPZW => new V4i(-1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPWO => new V4i(-1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPWP => new V4i(-1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPWN => new V4i(-1, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPWX => new V4i(-1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPWY => new V4i(-1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPWZ => new V4i(-1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NPWW => new V4i(-1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNOO => new V4i(-1, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNOP => new V4i(-1, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNON => new V4i(-1, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOX => new V4i(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOY => new V4i(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOZ => new V4i(-1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNOW => new V4i(-1, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNPO => new V4i(-1, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNPP => new V4i(-1, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNPN => new V4i(-1, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPX => new V4i(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPY => new V4i(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPZ => new V4i(-1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNPW => new V4i(-1, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNNO => new V4i(-1, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNNP => new V4i(-1, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4i NNNN => new V4i(-1, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNX => new V4i(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNY => new V4i(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNZ => new V4i(-1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNNW => new V4i(-1, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXO => new V4i(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXP => new V4i(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXN => new V4i(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXX => new V4i(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXY => new V4i(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXZ => new V4i(-1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNXW => new V4i(-1, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYO => new V4i(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYP => new V4i(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYN => new V4i(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYX => new V4i(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYY => new V4i(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYZ => new V4i(-1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNYW => new V4i(-1, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZO => new V4i(-1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZP => new V4i(-1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZN => new V4i(-1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZX => new V4i(-1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZY => new V4i(-1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZZ => new V4i(-1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNZW => new V4i(-1, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNWO => new V4i(-1, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNWP => new V4i(-1, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNWN => new V4i(-1, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNWX => new V4i(-1, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNWY => new V4i(-1, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNWZ => new V4i(-1, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NNWW => new V4i(-1, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOO => new V4i(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOP => new V4i(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXON => new V4i(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOX => new V4i(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOY => new V4i(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOZ => new V4i(-1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXOW => new V4i(-1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPO => new V4i(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPP => new V4i(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPN => new V4i(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPX => new V4i(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPY => new V4i(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPZ => new V4i(-1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXPW => new V4i(-1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNO => new V4i(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNP => new V4i(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNN => new V4i(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNX => new V4i(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNY => new V4i(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNZ => new V4i(-1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXNW => new V4i(-1, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXO => new V4i(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXP => new V4i(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXN => new V4i(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXX => new V4i(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXY => new V4i(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXZ => new V4i(-1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXXW => new V4i(-1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYO => new V4i(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYP => new V4i(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYN => new V4i(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYX => new V4i(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYY => new V4i(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYZ => new V4i(-1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXYW => new V4i(-1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZO => new V4i(-1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZP => new V4i(-1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZN => new V4i(-1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZX => new V4i(-1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZY => new V4i(-1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZZ => new V4i(-1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXZW => new V4i(-1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXWO => new V4i(-1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXWP => new V4i(-1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXWN => new V4i(-1, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXWX => new V4i(-1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXWY => new V4i(-1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXWZ => new V4i(-1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NXWW => new V4i(-1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOO => new V4i(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOP => new V4i(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYON => new V4i(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOX => new V4i(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOY => new V4i(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOZ => new V4i(-1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYOW => new V4i(-1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPO => new V4i(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPP => new V4i(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPN => new V4i(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPX => new V4i(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPY => new V4i(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPZ => new V4i(-1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYPW => new V4i(-1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNO => new V4i(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNP => new V4i(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNN => new V4i(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNX => new V4i(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNY => new V4i(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNZ => new V4i(-1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYNW => new V4i(-1, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXO => new V4i(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXP => new V4i(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXN => new V4i(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXX => new V4i(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXY => new V4i(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXZ => new V4i(-1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYXW => new V4i(-1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYO => new V4i(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYP => new V4i(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYN => new V4i(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYX => new V4i(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYY => new V4i(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYZ => new V4i(-1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYYW => new V4i(-1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZO => new V4i(-1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZP => new V4i(-1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZN => new V4i(-1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZX => new V4i(-1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZY => new V4i(-1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZZ => new V4i(-1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYZW => new V4i(-1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYWO => new V4i(-1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYWP => new V4i(-1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYWN => new V4i(-1, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYWX => new V4i(-1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYWY => new V4i(-1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYWZ => new V4i(-1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NYWW => new V4i(-1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOO => new V4i(-1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOP => new V4i(-1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZON => new V4i(-1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOX => new V4i(-1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOY => new V4i(-1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOZ => new V4i(-1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZOW => new V4i(-1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPO => new V4i(-1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPP => new V4i(-1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPN => new V4i(-1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPX => new V4i(-1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPY => new V4i(-1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPZ => new V4i(-1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZPW => new V4i(-1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNO => new V4i(-1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNP => new V4i(-1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNN => new V4i(-1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNX => new V4i(-1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNY => new V4i(-1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNZ => new V4i(-1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZNW => new V4i(-1, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXO => new V4i(-1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXP => new V4i(-1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXN => new V4i(-1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXX => new V4i(-1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXY => new V4i(-1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXZ => new V4i(-1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZXW => new V4i(-1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYO => new V4i(-1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYP => new V4i(-1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYN => new V4i(-1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYX => new V4i(-1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYY => new V4i(-1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYZ => new V4i(-1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZYW => new V4i(-1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZO => new V4i(-1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZP => new V4i(-1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZN => new V4i(-1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZX => new V4i(-1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZY => new V4i(-1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZZ => new V4i(-1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZZW => new V4i(-1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZWO => new V4i(-1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZWP => new V4i(-1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZWN => new V4i(-1, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZWX => new V4i(-1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZWY => new V4i(-1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZWZ => new V4i(-1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NZWW => new V4i(-1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWOO => new V4i(-1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWOP => new V4i(-1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWON => new V4i(-1, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWOX => new V4i(-1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWOY => new V4i(-1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWOZ => new V4i(-1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWOW => new V4i(-1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWPO => new V4i(-1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWPP => new V4i(-1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWPN => new V4i(-1, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWPX => new V4i(-1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWPY => new V4i(-1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWPZ => new V4i(-1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWPW => new V4i(-1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWNO => new V4i(-1, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWNP => new V4i(-1, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWNN => new V4i(-1, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWNX => new V4i(-1, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWNY => new V4i(-1, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWNZ => new V4i(-1, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWNW => new V4i(-1, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWXO => new V4i(-1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWXP => new V4i(-1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWXN => new V4i(-1, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWXX => new V4i(-1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWXY => new V4i(-1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWXZ => new V4i(-1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWXW => new V4i(-1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWYO => new V4i(-1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWYP => new V4i(-1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWYN => new V4i(-1, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWYX => new V4i(-1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWYY => new V4i(-1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWYZ => new V4i(-1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWYW => new V4i(-1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWZO => new V4i(-1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWZP => new V4i(-1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWZN => new V4i(-1, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWZX => new V4i(-1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWZY => new V4i(-1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWZZ => new V4i(-1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWZW => new V4i(-1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWWO => new V4i(-1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWWP => new V4i(-1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWWN => new V4i(-1, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWWX => new V4i(-1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWWY => new V4i(-1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWWZ => new V4i(-1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i NWWW => new V4i(-1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOO => new V4i(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOI => new V4i(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOON => new V4i(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOX => new V4i(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOY => new V4i(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOZ => new V4i(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOOW => new V4i(X, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIO => new V4i(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOII => new V4i(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOPN => new V4i(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIX => new V4i(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIY => new V4i(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIZ => new V4i(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOIW => new V4i(X, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONO => new V4i(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONP => new V4i(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONN => new V4i(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONX => new V4i(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONY => new V4i(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONZ => new V4i(X, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XONW => new V4i(X, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXO => new V4i(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXI => new V4i(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXN => new V4i(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXX => new V4i(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXY => new V4i(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXZ => new V4i(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOXW => new V4i(X, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYO => new V4i(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYI => new V4i(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYN => new V4i(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYX => new V4i(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYY => new V4i(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYZ => new V4i(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOYW => new V4i(X, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZO => new V4i(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZI => new V4i(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZN => new V4i(X, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZX => new V4i(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZY => new V4i(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZZ => new V4i(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOZW => new V4i(X, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOWO => new V4i(X, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOWI => new V4i(X, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOWN => new V4i(X, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOWX => new V4i(X, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOWY => new V4i(X, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOWZ => new V4i(X, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XOWW => new V4i(X, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOO => new V4i(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOI => new V4i(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPON => new V4i(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOX => new V4i(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOY => new V4i(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOZ => new V4i(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIOW => new V4i(X, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIO => new V4i(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIII => new V4i(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPPN => new V4i(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIX => new V4i(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIY => new V4i(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIZ => new V4i(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIIW => new V4i(X, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNO => new V4i(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNP => new V4i(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNN => new V4i(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNX => new V4i(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNY => new V4i(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNZ => new V4i(X, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPNW => new V4i(X, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXO => new V4i(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXI => new V4i(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPXN => new V4i(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXX => new V4i(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXY => new V4i(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXZ => new V4i(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIXW => new V4i(X, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYO => new V4i(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYI => new V4i(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPYN => new V4i(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYX => new V4i(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYY => new V4i(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYZ => new V4i(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIYW => new V4i(X, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZO => new V4i(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZI => new V4i(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPZN => new V4i(X, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZX => new V4i(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZY => new V4i(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZZ => new V4i(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIZW => new V4i(X, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIWO => new V4i(X, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIWI => new V4i(X, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XPWN => new V4i(X, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIWX => new V4i(X, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIWY => new V4i(X, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIWZ => new V4i(X, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XIWW => new V4i(X, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOO => new V4i(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOP => new V4i(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNON => new V4i(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOX => new V4i(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOY => new V4i(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOZ => new V4i(X, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNOW => new V4i(X, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPO => new V4i(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPP => new V4i(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPN => new V4i(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPX => new V4i(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPY => new V4i(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPZ => new V4i(X, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNPW => new V4i(X, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNO => new V4i(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNP => new V4i(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNN => new V4i(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNX => new V4i(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNY => new V4i(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNZ => new V4i(X, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNNW => new V4i(X, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXO => new V4i(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXP => new V4i(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXN => new V4i(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXX => new V4i(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXY => new V4i(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXZ => new V4i(X, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNXW => new V4i(X, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYO => new V4i(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYP => new V4i(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYN => new V4i(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYX => new V4i(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYY => new V4i(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYZ => new V4i(X, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNYW => new V4i(X, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZO => new V4i(X, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZP => new V4i(X, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZN => new V4i(X, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZX => new V4i(X, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZY => new V4i(X, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZZ => new V4i(X, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNZW => new V4i(X, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNWO => new V4i(X, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNWP => new V4i(X, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNWN => new V4i(X, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNWX => new V4i(X, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNWY => new V4i(X, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNWZ => new V4i(X, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XNWW => new V4i(X, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOO => new V4i(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOI => new V4i(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXON => new V4i(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOX => new V4i(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOY => new V4i(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOZ => new V4i(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXOW => new V4i(X, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIO => new V4i(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXII => new V4i(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXPN => new V4i(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIX => new V4i(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIY => new V4i(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIZ => new V4i(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXIW => new V4i(X, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNO => new V4i(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNP => new V4i(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNN => new V4i(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNX => new V4i(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNY => new V4i(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNZ => new V4i(X, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXNW => new V4i(X, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXO => new V4i(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXI => new V4i(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXN => new V4i(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXX => new V4i(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXY => new V4i(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXZ => new V4i(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXXW => new V4i(X, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYO => new V4i(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYI => new V4i(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYN => new V4i(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYX => new V4i(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYY => new V4i(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYZ => new V4i(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXYW => new V4i(X, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZO => new V4i(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZI => new V4i(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZN => new V4i(X, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZX => new V4i(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZY => new V4i(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZZ => new V4i(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXZW => new V4i(X, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXWO => new V4i(X, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXWI => new V4i(X, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXWN => new V4i(X, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXWX => new V4i(X, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXWY => new V4i(X, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXWZ => new V4i(X, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XXWW => new V4i(X, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOO => new V4i(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOI => new V4i(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYON => new V4i(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOX => new V4i(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOY => new V4i(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOZ => new V4i(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYOW => new V4i(X, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIO => new V4i(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYII => new V4i(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYPN => new V4i(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIX => new V4i(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIY => new V4i(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIZ => new V4i(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYIW => new V4i(X, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNO => new V4i(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNP => new V4i(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNN => new V4i(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNX => new V4i(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNY => new V4i(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNZ => new V4i(X, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYNW => new V4i(X, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXO => new V4i(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXI => new V4i(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXN => new V4i(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXX => new V4i(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXY => new V4i(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXZ => new V4i(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYXW => new V4i(X, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYO => new V4i(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYI => new V4i(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYN => new V4i(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYX => new V4i(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYY => new V4i(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYZ => new V4i(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYYW => new V4i(X, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZO => new V4i(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZI => new V4i(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZN => new V4i(X, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZX => new V4i(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZY => new V4i(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYZZ => new V4i(X, Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i XYZW\n        {\n            readonly get => new V4i(X, Y, Z, W);\n            set { X = value.X; Y = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYWO => new V4i(X, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYWI => new V4i(X, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYWN => new V4i(X, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYWX => new V4i(X, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYWY => new V4i(X, Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i XYWZ\n        {\n            readonly get => new V4i(X, Y, W, Z);\n            set { X = value.X; Y = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XYWW => new V4i(X, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOO => new V4i(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOI => new V4i(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZON => new V4i(X, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOX => new V4i(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOY => new V4i(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOZ => new V4i(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZOW => new V4i(X, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIO => new V4i(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZII => new V4i(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZPN => new V4i(X, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIX => new V4i(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIY => new V4i(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIZ => new V4i(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZIW => new V4i(X, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNO => new V4i(X, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNP => new V4i(X, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNN => new V4i(X, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNX => new V4i(X, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNY => new V4i(X, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNZ => new V4i(X, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZNW => new V4i(X, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXO => new V4i(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXI => new V4i(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXN => new V4i(X, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXX => new V4i(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXY => new V4i(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXZ => new V4i(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZXW => new V4i(X, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYO => new V4i(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYI => new V4i(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYN => new V4i(X, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYX => new V4i(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYY => new V4i(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZYZ => new V4i(X, Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i XZYW\n        {\n            readonly get => new V4i(X, Z, Y, W);\n            set { X = value.X; Z = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZO => new V4i(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZI => new V4i(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZN => new V4i(X, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZX => new V4i(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZY => new V4i(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZZ => new V4i(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZZW => new V4i(X, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZWO => new V4i(X, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZWI => new V4i(X, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZWN => new V4i(X, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZWX => new V4i(X, Z, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i XZWY\n        {\n            readonly get => new V4i(X, Z, W, Y);\n            set { X = value.X; Z = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZWZ => new V4i(X, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XZWW => new V4i(X, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWOO => new V4i(X, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWOI => new V4i(X, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWON => new V4i(X, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWOX => new V4i(X, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWOY => new V4i(X, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWOZ => new V4i(X, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWOW => new V4i(X, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWIO => new V4i(X, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWII => new V4i(X, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWPN => new V4i(X, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWIX => new V4i(X, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWIY => new V4i(X, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWIZ => new V4i(X, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWIW => new V4i(X, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWNO => new V4i(X, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWNP => new V4i(X, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWNN => new V4i(X, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWNX => new V4i(X, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWNY => new V4i(X, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWNZ => new V4i(X, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWNW => new V4i(X, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWXO => new V4i(X, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWXI => new V4i(X, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWXN => new V4i(X, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWXX => new V4i(X, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWXY => new V4i(X, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWXZ => new V4i(X, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWXW => new V4i(X, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWYO => new V4i(X, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWYI => new V4i(X, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWYN => new V4i(X, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWYX => new V4i(X, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWYY => new V4i(X, W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i XWYZ\n        {\n            readonly get => new V4i(X, W, Y, Z);\n            set { X = value.X; W = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWYW => new V4i(X, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWZO => new V4i(X, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWZI => new V4i(X, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWZN => new V4i(X, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWZX => new V4i(X, W, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i XWZY\n        {\n            readonly get => new V4i(X, W, Z, Y);\n            set { X = value.X; W = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWZZ => new V4i(X, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWZW => new V4i(X, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWWO => new V4i(X, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWWI => new V4i(X, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWWN => new V4i(X, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWWX => new V4i(X, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWWY => new V4i(X, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWWZ => new V4i(X, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i XWWW => new V4i(X, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOO => new V4i(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOI => new V4i(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOON => new V4i(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOX => new V4i(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOY => new V4i(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOZ => new V4i(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOOW => new V4i(Y, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIO => new V4i(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOII => new V4i(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOPN => new V4i(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIX => new V4i(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIY => new V4i(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIZ => new V4i(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOIW => new V4i(Y, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONO => new V4i(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONP => new V4i(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONN => new V4i(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONX => new V4i(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONY => new V4i(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONZ => new V4i(Y, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YONW => new V4i(Y, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXO => new V4i(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXI => new V4i(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXN => new V4i(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXX => new V4i(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXY => new V4i(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXZ => new V4i(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOXW => new V4i(Y, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYO => new V4i(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYI => new V4i(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYN => new V4i(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYX => new V4i(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYY => new V4i(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYZ => new V4i(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOYW => new V4i(Y, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZO => new V4i(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZI => new V4i(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZN => new V4i(Y, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZX => new V4i(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZY => new V4i(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZZ => new V4i(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOZW => new V4i(Y, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOWO => new V4i(Y, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOWI => new V4i(Y, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOWN => new V4i(Y, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOWX => new V4i(Y, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOWY => new V4i(Y, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOWZ => new V4i(Y, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YOWW => new V4i(Y, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOO => new V4i(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOI => new V4i(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPON => new V4i(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOX => new V4i(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOY => new V4i(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOZ => new V4i(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIOW => new V4i(Y, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIO => new V4i(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIII => new V4i(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPPN => new V4i(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIX => new V4i(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIY => new V4i(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIZ => new V4i(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIIW => new V4i(Y, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNO => new V4i(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNP => new V4i(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNN => new V4i(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNX => new V4i(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNY => new V4i(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNZ => new V4i(Y, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPNW => new V4i(Y, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXO => new V4i(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXI => new V4i(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPXN => new V4i(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXX => new V4i(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXY => new V4i(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXZ => new V4i(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIXW => new V4i(Y, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYO => new V4i(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYI => new V4i(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPYN => new V4i(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYX => new V4i(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYY => new V4i(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYZ => new V4i(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIYW => new V4i(Y, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZO => new V4i(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZI => new V4i(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPZN => new V4i(Y, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZX => new V4i(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZY => new V4i(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZZ => new V4i(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIZW => new V4i(Y, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIWO => new V4i(Y, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIWI => new V4i(Y, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YPWN => new V4i(Y, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIWX => new V4i(Y, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIWY => new V4i(Y, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIWZ => new V4i(Y, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YIWW => new V4i(Y, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOO => new V4i(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOP => new V4i(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNON => new V4i(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOX => new V4i(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOY => new V4i(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOZ => new V4i(Y, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNOW => new V4i(Y, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPO => new V4i(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPP => new V4i(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPN => new V4i(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPX => new V4i(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPY => new V4i(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPZ => new V4i(Y, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNPW => new V4i(Y, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNO => new V4i(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNP => new V4i(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNN => new V4i(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNX => new V4i(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNY => new V4i(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNZ => new V4i(Y, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNNW => new V4i(Y, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXO => new V4i(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXP => new V4i(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXN => new V4i(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXX => new V4i(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXY => new V4i(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXZ => new V4i(Y, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNXW => new V4i(Y, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYO => new V4i(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYP => new V4i(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYN => new V4i(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYX => new V4i(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYY => new V4i(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYZ => new V4i(Y, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNYW => new V4i(Y, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZO => new V4i(Y, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZP => new V4i(Y, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZN => new V4i(Y, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZX => new V4i(Y, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZY => new V4i(Y, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZZ => new V4i(Y, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNZW => new V4i(Y, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNWO => new V4i(Y, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNWP => new V4i(Y, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNWN => new V4i(Y, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNWX => new V4i(Y, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNWY => new V4i(Y, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNWZ => new V4i(Y, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YNWW => new V4i(Y, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOO => new V4i(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOI => new V4i(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXON => new V4i(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOX => new V4i(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOY => new V4i(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOZ => new V4i(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXOW => new V4i(Y, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIO => new V4i(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXII => new V4i(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXPN => new V4i(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIX => new V4i(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIY => new V4i(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIZ => new V4i(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXIW => new V4i(Y, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNO => new V4i(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNP => new V4i(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNN => new V4i(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNX => new V4i(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNY => new V4i(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNZ => new V4i(Y, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXNW => new V4i(Y, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXO => new V4i(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXI => new V4i(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXN => new V4i(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXX => new V4i(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXY => new V4i(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXZ => new V4i(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXXW => new V4i(Y, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYO => new V4i(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYI => new V4i(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYN => new V4i(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYX => new V4i(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYY => new V4i(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYZ => new V4i(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXYW => new V4i(Y, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZO => new V4i(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZI => new V4i(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZN => new V4i(Y, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZX => new V4i(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZY => new V4i(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXZZ => new V4i(Y, X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i YXZW\n        {\n            readonly get => new V4i(Y, X, Z, W);\n            set { Y = value.X; X = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXWO => new V4i(Y, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXWI => new V4i(Y, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXWN => new V4i(Y, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXWX => new V4i(Y, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXWY => new V4i(Y, X, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i YXWZ\n        {\n            readonly get => new V4i(Y, X, W, Z);\n            set { Y = value.X; X = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YXWW => new V4i(Y, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOO => new V4i(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOI => new V4i(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYON => new V4i(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOX => new V4i(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOY => new V4i(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOZ => new V4i(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYOW => new V4i(Y, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIO => new V4i(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYII => new V4i(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYPN => new V4i(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIX => new V4i(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIY => new V4i(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIZ => new V4i(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYIW => new V4i(Y, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNO => new V4i(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNP => new V4i(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNN => new V4i(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNX => new V4i(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNY => new V4i(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNZ => new V4i(Y, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYNW => new V4i(Y, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXO => new V4i(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXI => new V4i(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXN => new V4i(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXX => new V4i(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXY => new V4i(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXZ => new V4i(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYXW => new V4i(Y, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYO => new V4i(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYI => new V4i(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYN => new V4i(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYX => new V4i(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYY => new V4i(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYZ => new V4i(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYYW => new V4i(Y, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZO => new V4i(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZI => new V4i(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZN => new V4i(Y, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZX => new V4i(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZY => new V4i(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZZ => new V4i(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYZW => new V4i(Y, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYWO => new V4i(Y, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYWI => new V4i(Y, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYWN => new V4i(Y, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYWX => new V4i(Y, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYWY => new V4i(Y, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYWZ => new V4i(Y, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YYWW => new V4i(Y, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOO => new V4i(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOI => new V4i(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZON => new V4i(Y, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOX => new V4i(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOY => new V4i(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOZ => new V4i(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZOW => new V4i(Y, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIO => new V4i(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZII => new V4i(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZPN => new V4i(Y, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIX => new V4i(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIY => new V4i(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIZ => new V4i(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZIW => new V4i(Y, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNO => new V4i(Y, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNP => new V4i(Y, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNN => new V4i(Y, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNX => new V4i(Y, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNY => new V4i(Y, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNZ => new V4i(Y, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZNW => new V4i(Y, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXO => new V4i(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXI => new V4i(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXN => new V4i(Y, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXX => new V4i(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXY => new V4i(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZXZ => new V4i(Y, Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i YZXW\n        {\n            readonly get => new V4i(Y, Z, X, W);\n            set { Y = value.X; Z = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYO => new V4i(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYI => new V4i(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYN => new V4i(Y, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYX => new V4i(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYY => new V4i(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYZ => new V4i(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZYW => new V4i(Y, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZO => new V4i(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZI => new V4i(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZN => new V4i(Y, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZX => new V4i(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZY => new V4i(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZZ => new V4i(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZZW => new V4i(Y, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZWO => new V4i(Y, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZWI => new V4i(Y, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZWN => new V4i(Y, Z, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i YZWX\n        {\n            readonly get => new V4i(Y, Z, W, X);\n            set { Y = value.X; Z = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZWY => new V4i(Y, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZWZ => new V4i(Y, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YZWW => new V4i(Y, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWOO => new V4i(Y, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWOI => new V4i(Y, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWON => new V4i(Y, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWOX => new V4i(Y, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWOY => new V4i(Y, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWOZ => new V4i(Y, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWOW => new V4i(Y, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWIO => new V4i(Y, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWII => new V4i(Y, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWPN => new V4i(Y, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWIX => new V4i(Y, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWIY => new V4i(Y, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWIZ => new V4i(Y, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWIW => new V4i(Y, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWNO => new V4i(Y, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWNP => new V4i(Y, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWNN => new V4i(Y, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWNX => new V4i(Y, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWNY => new V4i(Y, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWNZ => new V4i(Y, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWNW => new V4i(Y, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWXO => new V4i(Y, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWXI => new V4i(Y, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWXN => new V4i(Y, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWXX => new V4i(Y, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWXY => new V4i(Y, W, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i YWXZ\n        {\n            readonly get => new V4i(Y, W, X, Z);\n            set { Y = value.X; W = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWXW => new V4i(Y, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWYO => new V4i(Y, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWYI => new V4i(Y, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWYN => new V4i(Y, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWYX => new V4i(Y, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWYY => new V4i(Y, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWYZ => new V4i(Y, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWYW => new V4i(Y, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWZO => new V4i(Y, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWZI => new V4i(Y, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWZN => new V4i(Y, W, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i YWZX\n        {\n            readonly get => new V4i(Y, W, Z, X);\n            set { Y = value.X; W = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWZY => new V4i(Y, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWZZ => new V4i(Y, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWZW => new V4i(Y, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWWO => new V4i(Y, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWWI => new V4i(Y, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWWN => new V4i(Y, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWWX => new V4i(Y, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWWY => new V4i(Y, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWWZ => new V4i(Y, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i YWWW => new V4i(Y, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOO => new V4i(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOI => new V4i(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOON => new V4i(Z, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOX => new V4i(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOY => new V4i(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOZ => new V4i(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOOW => new V4i(Z, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIO => new V4i(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOII => new V4i(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOPN => new V4i(Z, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIX => new V4i(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIY => new V4i(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIZ => new V4i(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOIW => new V4i(Z, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONO => new V4i(Z, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONP => new V4i(Z, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONN => new V4i(Z, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONX => new V4i(Z, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONY => new V4i(Z, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONZ => new V4i(Z, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZONW => new V4i(Z, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXO => new V4i(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXI => new V4i(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXN => new V4i(Z, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXX => new V4i(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXY => new V4i(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXZ => new V4i(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOXW => new V4i(Z, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYO => new V4i(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYI => new V4i(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYN => new V4i(Z, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYX => new V4i(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYY => new V4i(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYZ => new V4i(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOYW => new V4i(Z, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZO => new V4i(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZI => new V4i(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZN => new V4i(Z, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZX => new V4i(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZY => new V4i(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZZ => new V4i(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOZW => new V4i(Z, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOWO => new V4i(Z, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOWI => new V4i(Z, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOWN => new V4i(Z, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOWX => new V4i(Z, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOWY => new V4i(Z, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOWZ => new V4i(Z, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZOWW => new V4i(Z, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOO => new V4i(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOI => new V4i(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPON => new V4i(Z, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOX => new V4i(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOY => new V4i(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOZ => new V4i(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIOW => new V4i(Z, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIO => new V4i(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIII => new V4i(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPPN => new V4i(Z, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIX => new V4i(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIY => new V4i(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIZ => new V4i(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIIW => new V4i(Z, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNO => new V4i(Z, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNP => new V4i(Z, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNN => new V4i(Z, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNX => new V4i(Z, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNY => new V4i(Z, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNZ => new V4i(Z, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPNW => new V4i(Z, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXO => new V4i(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXI => new V4i(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPXN => new V4i(Z, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXX => new V4i(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXY => new V4i(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXZ => new V4i(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIXW => new V4i(Z, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYO => new V4i(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYI => new V4i(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPYN => new V4i(Z, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYX => new V4i(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYY => new V4i(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYZ => new V4i(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIYW => new V4i(Z, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZO => new V4i(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZI => new V4i(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPZN => new V4i(Z, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZX => new V4i(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZY => new V4i(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZZ => new V4i(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIZW => new V4i(Z, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIWO => new V4i(Z, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIWI => new V4i(Z, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZPWN => new V4i(Z, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIWX => new V4i(Z, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIWY => new V4i(Z, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIWZ => new V4i(Z, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZIWW => new V4i(Z, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOO => new V4i(Z, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOP => new V4i(Z, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNON => new V4i(Z, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOX => new V4i(Z, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOY => new V4i(Z, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOZ => new V4i(Z, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNOW => new V4i(Z, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPO => new V4i(Z, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPP => new V4i(Z, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPN => new V4i(Z, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPX => new V4i(Z, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPY => new V4i(Z, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPZ => new V4i(Z, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNPW => new V4i(Z, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNO => new V4i(Z, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNP => new V4i(Z, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNN => new V4i(Z, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNX => new V4i(Z, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNY => new V4i(Z, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNZ => new V4i(Z, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNNW => new V4i(Z, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXO => new V4i(Z, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXP => new V4i(Z, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXN => new V4i(Z, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXX => new V4i(Z, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXY => new V4i(Z, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXZ => new V4i(Z, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNXW => new V4i(Z, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYO => new V4i(Z, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYP => new V4i(Z, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYN => new V4i(Z, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYX => new V4i(Z, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYY => new V4i(Z, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYZ => new V4i(Z, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNYW => new V4i(Z, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZO => new V4i(Z, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZP => new V4i(Z, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZN => new V4i(Z, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZX => new V4i(Z, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZY => new V4i(Z, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZZ => new V4i(Z, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNZW => new V4i(Z, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNWO => new V4i(Z, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNWP => new V4i(Z, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNWN => new V4i(Z, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNWX => new V4i(Z, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNWY => new V4i(Z, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNWZ => new V4i(Z, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZNWW => new V4i(Z, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOO => new V4i(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOI => new V4i(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXON => new V4i(Z, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOX => new V4i(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOY => new V4i(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOZ => new V4i(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXOW => new V4i(Z, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIO => new V4i(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXII => new V4i(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXPN => new V4i(Z, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIX => new V4i(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIY => new V4i(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIZ => new V4i(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXIW => new V4i(Z, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNO => new V4i(Z, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNP => new V4i(Z, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNN => new V4i(Z, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNX => new V4i(Z, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNY => new V4i(Z, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNZ => new V4i(Z, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXNW => new V4i(Z, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXO => new V4i(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXI => new V4i(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXN => new V4i(Z, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXX => new V4i(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXY => new V4i(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXZ => new V4i(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXXW => new V4i(Z, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYO => new V4i(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYI => new V4i(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYN => new V4i(Z, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYX => new V4i(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYY => new V4i(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXYZ => new V4i(Z, X, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i ZXYW\n        {\n            readonly get => new V4i(Z, X, Y, W);\n            set { Z = value.X; X = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZO => new V4i(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZI => new V4i(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZN => new V4i(Z, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZX => new V4i(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZY => new V4i(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZZ => new V4i(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXZW => new V4i(Z, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXWO => new V4i(Z, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXWI => new V4i(Z, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXWN => new V4i(Z, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXWX => new V4i(Z, X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i ZXWY\n        {\n            readonly get => new V4i(Z, X, W, Y);\n            set { Z = value.X; X = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXWZ => new V4i(Z, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZXWW => new V4i(Z, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOO => new V4i(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOI => new V4i(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYON => new V4i(Z, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOX => new V4i(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOY => new V4i(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOZ => new V4i(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYOW => new V4i(Z, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIO => new V4i(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYII => new V4i(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYPN => new V4i(Z, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIX => new V4i(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIY => new V4i(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIZ => new V4i(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYIW => new V4i(Z, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNO => new V4i(Z, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNP => new V4i(Z, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNN => new V4i(Z, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNX => new V4i(Z, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNY => new V4i(Z, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNZ => new V4i(Z, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYNW => new V4i(Z, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXO => new V4i(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXI => new V4i(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXN => new V4i(Z, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXX => new V4i(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXY => new V4i(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYXZ => new V4i(Z, Y, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i ZYXW\n        {\n            readonly get => new V4i(Z, Y, X, W);\n            set { Z = value.X; Y = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYO => new V4i(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYI => new V4i(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYN => new V4i(Z, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYX => new V4i(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYY => new V4i(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYZ => new V4i(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYYW => new V4i(Z, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZO => new V4i(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZI => new V4i(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZN => new V4i(Z, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZX => new V4i(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZY => new V4i(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZZ => new V4i(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYZW => new V4i(Z, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYWO => new V4i(Z, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYWI => new V4i(Z, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYWN => new V4i(Z, Y, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i ZYWX\n        {\n            readonly get => new V4i(Z, Y, W, X);\n            set { Z = value.X; Y = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYWY => new V4i(Z, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYWZ => new V4i(Z, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZYWW => new V4i(Z, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOO => new V4i(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOI => new V4i(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZON => new V4i(Z, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOX => new V4i(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOY => new V4i(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOZ => new V4i(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZOW => new V4i(Z, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIO => new V4i(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZII => new V4i(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZPN => new V4i(Z, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIX => new V4i(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIY => new V4i(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIZ => new V4i(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZIW => new V4i(Z, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNO => new V4i(Z, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNP => new V4i(Z, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNN => new V4i(Z, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNX => new V4i(Z, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNY => new V4i(Z, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNZ => new V4i(Z, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZNW => new V4i(Z, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXO => new V4i(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXI => new V4i(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXN => new V4i(Z, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXX => new V4i(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXY => new V4i(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXZ => new V4i(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZXW => new V4i(Z, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYO => new V4i(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYI => new V4i(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYN => new V4i(Z, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYX => new V4i(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYY => new V4i(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYZ => new V4i(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZYW => new V4i(Z, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZO => new V4i(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZI => new V4i(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZN => new V4i(Z, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZX => new V4i(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZY => new V4i(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZZ => new V4i(Z, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZZW => new V4i(Z, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZWO => new V4i(Z, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZWI => new V4i(Z, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZWN => new V4i(Z, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZWX => new V4i(Z, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZWY => new V4i(Z, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZWZ => new V4i(Z, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZZWW => new V4i(Z, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWOO => new V4i(Z, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWOI => new V4i(Z, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWON => new V4i(Z, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWOX => new V4i(Z, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWOY => new V4i(Z, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWOZ => new V4i(Z, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWOW => new V4i(Z, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWIO => new V4i(Z, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWII => new V4i(Z, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWPN => new V4i(Z, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWIX => new V4i(Z, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWIY => new V4i(Z, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWIZ => new V4i(Z, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWIW => new V4i(Z, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWNO => new V4i(Z, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWNP => new V4i(Z, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWNN => new V4i(Z, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWNX => new V4i(Z, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWNY => new V4i(Z, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWNZ => new V4i(Z, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWNW => new V4i(Z, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWXO => new V4i(Z, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWXI => new V4i(Z, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWXN => new V4i(Z, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWXX => new V4i(Z, W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i ZWXY\n        {\n            readonly get => new V4i(Z, W, X, Y);\n            set { Z = value.X; W = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWXZ => new V4i(Z, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWXW => new V4i(Z, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWYO => new V4i(Z, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWYI => new V4i(Z, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWYN => new V4i(Z, W, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i ZWYX\n        {\n            readonly get => new V4i(Z, W, Y, X);\n            set { Z = value.X; W = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWYY => new V4i(Z, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWYZ => new V4i(Z, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWYW => new V4i(Z, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWZO => new V4i(Z, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWZI => new V4i(Z, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWZN => new V4i(Z, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWZX => new V4i(Z, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWZY => new V4i(Z, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWZZ => new V4i(Z, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWZW => new V4i(Z, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWWO => new V4i(Z, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWWI => new V4i(Z, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWWN => new V4i(Z, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWWX => new V4i(Z, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWWY => new V4i(Z, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWWZ => new V4i(Z, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i ZWWW => new V4i(Z, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOOO => new V4i(W, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOOI => new V4i(W, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOON => new V4i(W, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOOX => new V4i(W, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOOY => new V4i(W, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOOZ => new V4i(W, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOOW => new V4i(W, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOIO => new V4i(W, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOII => new V4i(W, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOPN => new V4i(W, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOIX => new V4i(W, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOIY => new V4i(W, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOIZ => new V4i(W, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOIW => new V4i(W, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WONO => new V4i(W, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WONP => new V4i(W, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WONN => new V4i(W, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WONX => new V4i(W, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WONY => new V4i(W, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WONZ => new V4i(W, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WONW => new V4i(W, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOXO => new V4i(W, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOXI => new V4i(W, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOXN => new V4i(W, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOXX => new V4i(W, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOXY => new V4i(W, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOXZ => new V4i(W, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOXW => new V4i(W, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOYO => new V4i(W, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOYI => new V4i(W, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOYN => new V4i(W, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOYX => new V4i(W, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOYY => new V4i(W, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOYZ => new V4i(W, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOYW => new V4i(W, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOZO => new V4i(W, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOZI => new V4i(W, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOZN => new V4i(W, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOZX => new V4i(W, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOZY => new V4i(W, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOZZ => new V4i(W, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOZW => new V4i(W, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOWO => new V4i(W, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOWI => new V4i(W, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOWN => new V4i(W, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOWX => new V4i(W, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOWY => new V4i(W, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOWZ => new V4i(W, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WOWW => new V4i(W, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIOO => new V4i(W, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIOI => new V4i(W, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPON => new V4i(W, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIOX => new V4i(W, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIOY => new V4i(W, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIOZ => new V4i(W, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIOW => new V4i(W, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIIO => new V4i(W, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIII => new V4i(W, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPPN => new V4i(W, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIIX => new V4i(W, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIIY => new V4i(W, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIIZ => new V4i(W, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIIW => new V4i(W, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPNO => new V4i(W, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPNP => new V4i(W, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPNN => new V4i(W, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPNX => new V4i(W, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPNY => new V4i(W, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPNZ => new V4i(W, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPNW => new V4i(W, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIXO => new V4i(W, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIXI => new V4i(W, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPXN => new V4i(W, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIXX => new V4i(W, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIXY => new V4i(W, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIXZ => new V4i(W, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIXW => new V4i(W, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIYO => new V4i(W, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIYI => new V4i(W, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPYN => new V4i(W, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIYX => new V4i(W, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIYY => new V4i(W, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIYZ => new V4i(W, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIYW => new V4i(W, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIZO => new V4i(W, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIZI => new V4i(W, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPZN => new V4i(W, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIZX => new V4i(W, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIZY => new V4i(W, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIZZ => new V4i(W, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIZW => new V4i(W, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIWO => new V4i(W, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIWI => new V4i(W, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WPWN => new V4i(W, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIWX => new V4i(W, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIWY => new V4i(W, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIWZ => new V4i(W, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WIWW => new V4i(W, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNOO => new V4i(W, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNOP => new V4i(W, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNON => new V4i(W, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNOX => new V4i(W, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNOY => new V4i(W, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNOZ => new V4i(W, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNOW => new V4i(W, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNPO => new V4i(W, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNPP => new V4i(W, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNPN => new V4i(W, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNPX => new V4i(W, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNPY => new V4i(W, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNPZ => new V4i(W, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNPW => new V4i(W, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNNO => new V4i(W, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNNP => new V4i(W, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNNN => new V4i(W, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNNX => new V4i(W, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNNY => new V4i(W, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNNZ => new V4i(W, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNNW => new V4i(W, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNXO => new V4i(W, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNXP => new V4i(W, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNXN => new V4i(W, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNXX => new V4i(W, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNXY => new V4i(W, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNXZ => new V4i(W, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNXW => new V4i(W, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNYO => new V4i(W, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNYP => new V4i(W, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNYN => new V4i(W, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNYX => new V4i(W, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNYY => new V4i(W, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNYZ => new V4i(W, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNYW => new V4i(W, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNZO => new V4i(W, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNZP => new V4i(W, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNZN => new V4i(W, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNZX => new V4i(W, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNZY => new V4i(W, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNZZ => new V4i(W, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNZW => new V4i(W, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNWO => new V4i(W, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNWP => new V4i(W, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNWN => new V4i(W, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNWX => new V4i(W, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNWY => new V4i(W, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNWZ => new V4i(W, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WNWW => new V4i(W, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXOO => new V4i(W, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXOI => new V4i(W, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXON => new V4i(W, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXOX => new V4i(W, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXOY => new V4i(W, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXOZ => new V4i(W, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXOW => new V4i(W, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXIO => new V4i(W, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXII => new V4i(W, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXPN => new V4i(W, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXIX => new V4i(W, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXIY => new V4i(W, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXIZ => new V4i(W, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXIW => new V4i(W, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXNO => new V4i(W, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXNP => new V4i(W, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXNN => new V4i(W, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXNX => new V4i(W, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXNY => new V4i(W, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXNZ => new V4i(W, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXNW => new V4i(W, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXXO => new V4i(W, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXXI => new V4i(W, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXXN => new V4i(W, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXXX => new V4i(W, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXXY => new V4i(W, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXXZ => new V4i(W, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXXW => new V4i(W, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXYO => new V4i(W, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXYI => new V4i(W, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXYN => new V4i(W, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXYX => new V4i(W, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXYY => new V4i(W, X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i WXYZ\n        {\n            readonly get => new V4i(W, X, Y, Z);\n            set { W = value.X; X = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXYW => new V4i(W, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXZO => new V4i(W, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXZI => new V4i(W, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXZN => new V4i(W, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXZX => new V4i(W, X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i WXZY\n        {\n            readonly get => new V4i(W, X, Z, Y);\n            set { W = value.X; X = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXZZ => new V4i(W, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXZW => new V4i(W, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXWO => new V4i(W, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXWI => new V4i(W, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXWN => new V4i(W, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXWX => new V4i(W, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXWY => new V4i(W, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXWZ => new V4i(W, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WXWW => new V4i(W, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYOO => new V4i(W, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYOI => new V4i(W, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYON => new V4i(W, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYOX => new V4i(W, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYOY => new V4i(W, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYOZ => new V4i(W, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYOW => new V4i(W, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYIO => new V4i(W, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYII => new V4i(W, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYPN => new V4i(W, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYIX => new V4i(W, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYIY => new V4i(W, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYIZ => new V4i(W, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYIW => new V4i(W, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYNO => new V4i(W, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYNP => new V4i(W, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYNN => new V4i(W, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYNX => new V4i(W, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYNY => new V4i(W, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYNZ => new V4i(W, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYNW => new V4i(W, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYXO => new V4i(W, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYXI => new V4i(W, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYXN => new V4i(W, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYXX => new V4i(W, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYXY => new V4i(W, Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i WYXZ\n        {\n            readonly get => new V4i(W, Y, X, Z);\n            set { W = value.X; Y = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYXW => new V4i(W, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYYO => new V4i(W, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYYI => new V4i(W, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYYN => new V4i(W, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYYX => new V4i(W, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYYY => new V4i(W, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYYZ => new V4i(W, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYYW => new V4i(W, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYZO => new V4i(W, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYZI => new V4i(W, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYZN => new V4i(W, Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i WYZX\n        {\n            readonly get => new V4i(W, Y, Z, X);\n            set { W = value.X; Y = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYZY => new V4i(W, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYZZ => new V4i(W, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYZW => new V4i(W, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYWO => new V4i(W, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYWI => new V4i(W, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYWN => new V4i(W, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYWX => new V4i(W, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYWY => new V4i(W, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYWZ => new V4i(W, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WYWW => new V4i(W, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZOO => new V4i(W, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZOI => new V4i(W, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZON => new V4i(W, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZOX => new V4i(W, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZOY => new V4i(W, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZOZ => new V4i(W, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZOW => new V4i(W, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZIO => new V4i(W, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZII => new V4i(W, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZPN => new V4i(W, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZIX => new V4i(W, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZIY => new V4i(W, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZIZ => new V4i(W, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZIW => new V4i(W, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZNO => new V4i(W, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZNP => new V4i(W, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZNN => new V4i(W, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZNX => new V4i(W, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZNY => new V4i(W, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZNZ => new V4i(W, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZNW => new V4i(W, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZXO => new V4i(W, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZXI => new V4i(W, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZXN => new V4i(W, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZXX => new V4i(W, Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i WZXY\n        {\n            readonly get => new V4i(W, Z, X, Y);\n            set { W = value.X; Z = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZXZ => new V4i(W, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZXW => new V4i(W, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZYO => new V4i(W, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZYI => new V4i(W, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZYN => new V4i(W, Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4i WZYX\n        {\n            readonly get => new V4i(W, Z, Y, X);\n            set { W = value.X; Z = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZYY => new V4i(W, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZYZ => new V4i(W, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZYW => new V4i(W, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZZO => new V4i(W, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZZI => new V4i(W, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZZN => new V4i(W, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZZX => new V4i(W, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZZY => new V4i(W, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZZZ => new V4i(W, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZZW => new V4i(W, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZWO => new V4i(W, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZWI => new V4i(W, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZWN => new V4i(W, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZWX => new V4i(W, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZWY => new V4i(W, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZWZ => new V4i(W, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WZWW => new V4i(W, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWOO => new V4i(W, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWOI => new V4i(W, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWON => new V4i(W, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWOX => new V4i(W, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWOY => new V4i(W, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWOZ => new V4i(W, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWOW => new V4i(W, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWIO => new V4i(W, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWII => new V4i(W, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWPN => new V4i(W, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWIX => new V4i(W, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWIY => new V4i(W, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWIZ => new V4i(W, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWIW => new V4i(W, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWNO => new V4i(W, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWNP => new V4i(W, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWNN => new V4i(W, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWNX => new V4i(W, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWNY => new V4i(W, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWNZ => new V4i(W, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWNW => new V4i(W, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWXO => new V4i(W, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWXI => new V4i(W, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWXN => new V4i(W, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWXX => new V4i(W, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWXY => new V4i(W, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWXZ => new V4i(W, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWXW => new V4i(W, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWYO => new V4i(W, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWYI => new V4i(W, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWYN => new V4i(W, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWYX => new V4i(W, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWYY => new V4i(W, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWYZ => new V4i(W, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWYW => new V4i(W, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWZO => new V4i(W, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWZI => new V4i(W, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWZN => new V4i(W, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWZX => new V4i(W, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWZY => new V4i(W, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWZZ => new V4i(W, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWZW => new V4i(W, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWWO => new V4i(W, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWWI => new V4i(W, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWWN => new V4i(W, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWWX => new V4i(W, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWWY => new V4i(W, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWWZ => new V4i(W, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4i WWWW => new V4i(W, W, W, W);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (int)value; }\n        }\n\n        #endregion\n\n        #region ISize4i Members\n\n        public readonly V4i Size4i { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 4; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (int)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V4iEqualityComparer : IEqualityComparer<V4i>\n    {\n        public static V4iEqualityComparer Default\n            => new V4iEqualityComparer();\n\n        #region IEqualityComparer<V4i> Members\n\n        public bool Equals(V4i v0, V4i v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V4i v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Min(this V4i a, V4i b)\n        {\n            return new V4i(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z), Min(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Min(this V4i a, int b)\n        {\n            return new V4i(Min(a.X, b), Min(a.Y, b), Min(a.Z, b), Min(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Min(this int a, V4i b)\n        {\n            return new V4i(Min(a, b.X), Min(a, b.Y), Min(a, b.Z), Min(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Max(this V4i a, V4i b)\n        {\n            return new V4i(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z), Max(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Max(this V4i a, int b)\n        {\n            return new V4i(Max(a.X, b), Max(a.Y, b), Max(a.Z, b), Max(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Max(this int a, V4i b)\n        {\n            return new V4i(Max(a, b.X), Max(a, b.Y), Max(a, b.Z), Max(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Min(this V4i a, V4i b, V4i c)\n        {\n            return new V4i(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z), Min(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Max(this V4i a, V4i b, V4i c)\n        {\n            return new V4i(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z), Max(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Min(this V4i a, V4i b, V4i c, V4i d)\n        {\n            return new V4i(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z), Min(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Max(this V4i a, V4i b, V4i c, V4i d)\n        {\n            return new V4i(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z), Max(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Min(this V4i x, params V4i[] values)\n        {\n            return new V4i(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)), Min(x.W, values.Map(a => a.W)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Max(this V4i x, params V4i[] values)\n        {\n            return new V4i(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)), Max(x.W, values.Map(a => a.W)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Abs(this V4i x)\n        {\n            return new V4i(Abs(x.X), Abs(x.Y), Abs(x.Z), Abs(x.W));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Clamp(this V4i x, V4i a, V4i b)\n        {\n            return new V4i(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z), Clamp(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Clamp(this V4i x, int a, int b)\n        {\n            return new V4i(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b), Clamp(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i ClampExcl(this V4i x, V4i a, V4i b)\n        {\n            return new V4i(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y), ClampExcl(x.Z, a.Z, b.Z), ClampExcl(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i ClampExcl(this V4i x, int a, int b)\n        {\n            return new V4i(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b), ClampExcl(x.Z, a, b), ClampExcl(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i ClampWrap(this V4i x, V4i a, V4i b)\n        {\n            return new V4i(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z), ClampWrap(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i ClampWrap(this V4i x, int a, int b)\n        {\n            return new V4i(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b), ClampWrap(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Saturate(this V4i x)\n        {\n            return new V4i(Saturate(x.X), Saturate(x.Y), Saturate(x.Z), Saturate(x.W));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Sign(this V4i x)\n        {\n            return new V4i(Sign(x.X), Sign(x.Y), Sign(x.Z), Sign(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Signumi(this V4i x)\n        {\n            return new V4i(Signumi(x.X), Signumi(x.Y), Signumi(x.Z), Signumi(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Signum(this V4i x)\n        {\n            return new V4i(Signum(x.X), Signum(x.Y), Signum(x.Z), Signum(x.W));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i MultiplyAdd(V4i x, V4i y, V4i z)\n        {\n            return new V4i(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z), MultiplyAdd(x.W, y.W, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i MultiplyAdd(V4i x, int y, V4i z)\n        {\n            return new V4i(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z), MultiplyAdd(x.W, y, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i MultiplyAdd(int x, V4i y, V4i z)\n        {\n            return new V4i(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z), MultiplyAdd(x, y.W, z.W));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sqrt(this V4i x)\n        {\n            return new V4d(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z), Sqrt(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Cbrt(this V4i x)\n        {\n            return new V4d(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z), Cbrt(x.W));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Square(this V4i x)\n        {\n            return new V4i(Square(x.X), Square(x.Y), Square(x.Z), Square(x.W));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Pown(this V4i x, V4i y)\n        {\n            return new V4i(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z), Pown(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Pown(this V4i x, int y)\n        {\n            return new V4i(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y), Pown(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Pown(this int x, V4i y)\n        {\n            return new V4i(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z), Pown(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this V4i x, V4f y)\n        {\n            return new V4f(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z), Pow(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this V4i x, float y)\n        {\n            return new V4f(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y), Pow(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this int x, V4f y)\n        {\n            return new V4f(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z), Pow(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this V4i x, V4d y)\n        {\n            return new V4d(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z), Pow(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this V4i x, double y)\n        {\n            return new V4d(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y), Pow(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this int x, V4d y)\n        {\n            return new V4d(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z), Pow(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this V4i x, V4f y)\n        {\n            return new V4f(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z), Power(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this V4i x, float y)\n        {\n            return new V4f(Power(x.X, y), Power(x.Y, y), Power(x.Z, y), Power(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this int x, V4f y)\n        {\n            return new V4f(Power(x, y.X), Power(x, y.Y), Power(x, y.Z), Power(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this V4i x, V4d y)\n        {\n            return new V4d(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z), Power(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this V4i x, double y)\n        {\n            return new V4d(Power(x.X, y), Power(x.Y, y), Power(x.Z, y), Power(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this int x, V4d y)\n        {\n            return new V4d(Power(x, y.X), Power(x, y.Y), Power(x, y.Z), Power(x, y.W));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Exp(this V4i x)\n        {\n            return new V4d(Exp(x.X), Exp(x.Y), Exp(x.Z), Exp(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(this V4i x)\n        {\n            return new V4d(Log(x.X), Log(x.Y), Log(x.Z), Log(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log2(this V4i x)\n        {\n            return new V4d(Log2(x.X), Log2(x.Y), Log2(x.Z), Log2(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Log2Int(this V4i x)\n        {\n            return new V4i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z), Log2Int(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log10(this V4i x)\n        {\n            return new V4d(Log10(x.X), Log10(x.Y), Log10(x.Z), Log10(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(this V4i x, double basis)\n        {\n            return new V4d(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis), Log(x.W, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i ModP(this V4i a, V4i b)\n        {\n            return new V4i(ModP(a.X, b.X), ModP(a.Y, b.Y), ModP(a.Z, b.Z), ModP(a.W, b.W));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l PowerOfTwo(this V4i x)\n        {\n            return new V4l(PowerOfTwo(x.X), PowerOfTwo(x.Y), PowerOfTwo(x.Z), PowerOfTwo(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.NextPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i NextPowerOfTwo(this V4i x)\n        {\n            return new V4i(NextPowerOfTwo(x.X), NextPowerOfTwo(x.Y), NextPowerOfTwo(x.Z), NextPowerOfTwo(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.PrevPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i PrevPowerOfTwo(this V4i x)\n        {\n            return new V4i(PrevPowerOfTwo(x.X), PrevPowerOfTwo(x.Y), PrevPowerOfTwo(x.Z), PrevPowerOfTwo(x.W));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Step(this V4i x, V4i edge)\n        {\n            return new V4i(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z), Step(x.W, edge.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Step(this V4i x, int edge)\n        {\n            return new V4i(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge), Step(x.W, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Lerp(this float t, V4i a, V4i b)\n        {\n            return new V4i(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z), Lerp(t, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Lerp(this V4f t, V4i a, V4i b)\n        {\n            return new V4i(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z), Lerp(t.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Lerp(this double t, V4i a, V4i b)\n        {\n            return new V4i(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z), Lerp(t, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Lerp(this V4d t, V4i a, V4i b)\n        {\n            return new V4i(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z), Lerp(t.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvLerp(this V4i y, V4i a, V4i b)\n        {\n            return new V4d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z), InvLerp(y.W, a.W, b.W));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i GreatestCommonDivisor(this V4i a, V4i b)\n        {\n            return new V4i(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y), GreatestCommonDivisor(a.Z, b.Z), GreatestCommonDivisor(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i LeastCommonMultiple(this V4i a, V4i b)\n        {\n            return new V4i(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y), LeastCommonMultiple(a.Z, b.Z), LeastCommonMultiple(a.W, b.W));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FloatFromBits(this V4i x)\n        {\n            return new V4f(FloatFromBits(x.X), FloatFromBits(x.Y), FloatFromBits(x.Z), FloatFromBits(x.W));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V4i a, V4i b, int tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance) && ApproximateEquals(a.W, b.W, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V4i v, int epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LengthSquared(V4i v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V4i v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Normalized(V4i v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Norm1(V4i v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V4i v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMax(V4i v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int NormMin(V4i v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V4i v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p) + \n                Fun.Abs(v.W).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceSquared(this V4i a, V4i b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y) + Fun.Square(b.Z - a.Z) + Fun.Square(b.W - a.W);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V4i a, V4i b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Distance1(this V4i a, V4i b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y) + Fun.Abs(b.Z - a.Z) + Fun.Abs(b.W - a.W);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V4i a, V4i b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p) + Fun.Abs(b.Z - a.Z).Pow(p) + Fun.Abs(b.W - a.W).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceMax(this V4i a, V4i b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z), Fun.Abs(b.W - a.W));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int DistanceMin(this V4i a, V4i b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z), Fun.Abs(b.W - a.W));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V4i query, V4i p0, V4i p1)\n        {\n            return DistanceToLine((V4d) query, (V4d) p0, (V4d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V4i query, V4i p0, V4i p1)\n        {\n            return DistanceToInfiniteLine((V4d) query, (V4d) p0, (V4d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V4i query, V4i p0, V4i p1, out double t)\n        {\n            return DistanceToLine((V4d) query, (V4d) p0, (V4d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V4i query, V4i p0, V4i p1, out double t)\n        {\n            return DistanceToInfiniteLine((V4d) query, (V4d) p0, (V4d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V4i v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n            v.Z = -v.Z;\n            v.W = -v.W;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 4x4 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44i Outer(this V4i a, V4i b)\n        {\n            return new M44i(\n                        a.X * b.X, a.X * b.Y, a.X * b.Z, a.X * b.W, \n                        a.Y * b.X, a.Y * b.Y, a.Y * b.Z, a.Y * b.W, \n                        a.Z * b.X, a.Z * b.Y, a.Z * b.Z, a.Z * b.W, \n                        a.W * b.X, a.W * b.Y, a.W * b.Z, a.W * b.W);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int Dot(this V4i a, V4i b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V4i v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > 0) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < 0) flags |= Aardbase.DirFlags.NegativeZ;\n            if (v.W > 0) flags |= Aardbase.DirFlags.PositiveW;\n            if (v.W < 0) flags |= Aardbase.DirFlags.NegativeW;\n            return flags;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4i a, V4i b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z && a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4i v, int s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s && v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(int s, V4i v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z && s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4i a, V4i b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z || a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4i v, int s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s || v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(int s, V4i v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z || s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4i a, V4i b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z && a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4i v, int s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s && v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(int s, V4i v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z && s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4i a, V4i b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z || a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4i v, int s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s || v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(int s, V4i v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z || s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4i a, V4i b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z && a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4i v, int s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s && v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(int s, V4i v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z && s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4i a, V4i b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z || a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4i v, int s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s || v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(int s, V4i v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z || s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4i a, V4i b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z && a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4i v, int s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s && v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(int s, V4i v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z && s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4i a, V4i b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z || a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4i v, int s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s || v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(int s, V4i v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z || s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4i a, V4i b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4i v, int s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s && v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(int s, V4i v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z && s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4i a, V4i b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z || a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4i v, int s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s || v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(int s, V4i v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z || s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4i a, V4i b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z && a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4i v, int s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s && v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(int s, V4i v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z && s != v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4i a, V4i b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4i v, int s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s || v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(int s, V4i v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z || s != v.W);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V4i v0, V4i v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            if (v0.W < v1.W) return -1;\n            if (v0.W > v1.W) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V4i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MinElement(V4i v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V4i\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int MaxElement(V4i v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V4i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V4i v, int epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon) || v.W.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4i\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V4i v, int epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon) && v.W.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V4i[] pointArray, V4i point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V4i[] array, int start, int count,\n                V4i point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V4i> pointSelector, V4i point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V4i[] pointArray, V4i point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V4i[] array, long start, long count,\n                V4i point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V4i> pointSelector, V4i point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V4i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V4i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V4i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V4i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V4i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V4i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V4i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V4i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V4i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V4i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V4i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V4i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinW(this V4i[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinW(this V4i[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxW(this V4i[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxW(this V4i[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V4i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V4i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V4i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V4i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V4i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V4i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinW(this IList<V4i> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxW(this IList<V4i> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static int[] CopyCoord(this V4i[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                case 3: return self.Map(v => v.W);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV4iExtensions\n    {\n        #region IRandomUniform extensions for V4i\n\n        /// <summary>\n        /// Uses UniformInt() to generate the elements of a V4i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i UniformV4i(this IRandomUniform rnd)\n        {\n            return new V4i(rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt());\n        }\n\n        /// <summary>\n        /// Uses UniformIntNonZero() to generate the elements of a V4i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i UniformV4iNonZero(this IRandomUniform rnd)\n        {\n            return new V4i(rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero(), rnd.UniformIntNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of a V4i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i UniformV4i(this IRandomUniform rnd, int size)\n        {\n            return new V4i(rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size), rnd.UniformInt(size));\n        }\n\n        /// <summary>\n        /// Uses UniformInt(int) to generate the elements of a V4i vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i UniformV4i(this IRandomUniform rnd, V4i size)\n        {\n            return new V4i(rnd.UniformInt(size.X), rnd.UniformInt(size.Y), rnd.UniformInt(size.Z), rnd.UniformInt(size.W));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V4ui\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V4ui : IVector<double>, ISize4ui, IFormattable, IEquatable<V4ui>\n    {\n        [DataMember]\n        public uint X;\n        [DataMember]\n        public uint Y;\n        [DataMember]\n        public uint Z;\n        [DataMember]\n        public uint W;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(int x, int y, int z, int w)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n            W = (uint)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(int v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n            Z = (uint)v;\n            W = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(int[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n            Z = (uint)a[2];\n            W = (uint)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(int[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n            Z = (uint)a[start + 2];\n            W = (uint)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(int a, V3i b)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n            W = (uint)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2i a, V2i b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b.X;\n            W = (uint)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3i a, int b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)a.Z;\n            W = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/>, <see cref=\"int\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2i a, int b, int c)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b;\n            W = (uint)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"V2i\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(int a, V2i b, int c)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n            W = (uint)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"int\"/>, and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(int a, int b, V2i c)\n        {\n            X = (uint)a;\n            Y = (uint)b;\n            Z = (uint)c.X;\n            W = (uint)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(uint x, uint y, uint z, uint w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(uint v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n            W = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(uint[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n            W = a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(uint[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n            W = a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(uint a, V3ui b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2ui a, V2ui b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b.X;\n            W = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3ui a, uint b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = a.Z;\n            W = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/>, <see cref=\"uint\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2ui a, uint b, uint c)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"V2ui\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(uint a, V2ui b, uint c)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"uint\"/>, and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(uint a, uint b, V2ui c)\n        {\n            X = a;\n            Y = b;\n            Z = c.X;\n            W = c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(long x, long y, long z, long w)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n            W = (uint)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(long v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n            Z = (uint)v;\n            W = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(long[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n            Z = (uint)a[2];\n            W = (uint)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(long[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n            Z = (uint)a[start + 2];\n            W = (uint)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(long a, V3l b)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n            W = (uint)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2l a, V2l b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b.X;\n            W = (uint)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3l a, long b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)a.Z;\n            W = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/>, <see cref=\"long\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2l a, long b, long c)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b;\n            W = (uint)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"V2l\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(long a, V2l b, long c)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n            W = (uint)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"long\"/>, and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(long a, long b, V2l c)\n        {\n            X = (uint)a;\n            Y = (uint)b;\n            Z = (uint)c.X;\n            W = (uint)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(float x, float y, float z, float w)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n            W = (uint)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(float v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n            Z = (uint)v;\n            W = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(float[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n            Z = (uint)a[2];\n            W = (uint)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(float[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n            Z = (uint)a[start + 2];\n            W = (uint)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(float a, V3f b)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n            W = (uint)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2f a, V2f b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b.X;\n            W = (uint)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3f a, float b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)a.Z;\n            W = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/>, <see cref=\"float\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2f a, float b, float c)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b;\n            W = (uint)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"V2f\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(float a, V2f b, float c)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n            W = (uint)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"float\"/>, and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(float a, float b, V2f c)\n        {\n            X = (uint)a;\n            Y = (uint)b;\n            Z = (uint)c.X;\n            W = (uint)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(double x, double y, double z, double w)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n            W = (uint)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(double v)\n        {\n            X = (uint)v;\n            Y = (uint)v;\n            Z = (uint)v;\n            W = (uint)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(double[] a)\n        {\n            X = (uint)a[0];\n            Y = (uint)a[1];\n            Z = (uint)a[2];\n            W = (uint)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(double[] a, int start)\n        {\n            X = (uint)a[start + 0];\n            Y = (uint)a[start + 1];\n            Z = (uint)a[start + 2];\n            W = (uint)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(double a, V3d b)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n            W = (uint)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2d a, V2d b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b.X;\n            W = (uint)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3d a, double b)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)a.Z;\n            W = (uint)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/>, <see cref=\"double\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2d a, double b, double c)\n        {\n            X = (uint)a.X;\n            Y = (uint)a.Y;\n            Z = (uint)b;\n            W = (uint)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"V2d\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(double a, V2d b, double c)\n        {\n            X = (uint)a;\n            Y = (uint)b.X;\n            Z = (uint)b.Y;\n            W = (uint)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"double\"/>, and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(double a, double b, V2d c)\n        {\n            X = (uint)a;\n            Y = (uint)b;\n            Z = (uint)c.X;\n            W = (uint)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(Func<int, uint> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n            W = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;uint&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 4.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(IVector<double> v)\n            : this(v[0], v[1], v[2], v[3])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V2d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V3d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V4i v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n            W = (uint)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V4ui v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V4l v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n            W = (uint)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V4f v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n            W = (uint)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(V4d v)\n        {\n            X = (uint)v.X;\n            Y = (uint)v.Y;\n            Z = (uint)v.Z;\n            W = (uint)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(C3b c)\n        {\n            X = (uint)(c.R);\n            Y = (uint)(c.G);\n            Z = (uint)(c.B);\n            W = (uint)255;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(C3us c)\n        {\n            X = (uint)(c.R);\n            Y = (uint)(c.G);\n            Z = (uint)(c.B);\n            W = (uint)65535;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3ui\"/> color.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(C3ui c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n            W = UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(C4b c)\n        {\n            X = (uint)(c.R);\n            Y = (uint)(c.G);\n            Z = (uint)(c.B);\n            W = (uint)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(C4us c)\n        {\n            X = (uint)(c.R);\n            Y = (uint)(c.G);\n            Z = (uint)(c.B);\n            W = (uint)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4ui(C4ui c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n            W = (c.A);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V2i v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V2ui v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V2l v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V2f v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V2d v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V3i v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V3ui v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V3l v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V3f v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V3d v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V4i v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V4l v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V4f v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(V4d v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V4ui v)\n            => new int[] { (int)v.X, (int)v.Y, (int)v.Z, (int)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(int[] v)\n            => new V4ui((uint)v[0], (uint)v[1], (uint)v[2], (uint)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V4ui v)\n            => new uint[] { v.X, v.Y, v.Z, v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(uint[] v)\n            => new V4ui(v[0], v[1], v[2], v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V4ui v)\n            => new long[] { (long)v.X, (long)v.Y, (long)v.Z, (long)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(long[] v)\n            => new V4ui((uint)v[0], (uint)v[1], (uint)v[2], (uint)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V4ui v)\n            => new float[] { (float)v.X, (float)v.Y, (float)v.Z, (float)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(float[] v)\n            => new V4ui((uint)v[0], (uint)v[1], (uint)v[2], (uint)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V4ui v)\n            => new double[] { (double)v.X, (double)v.Y, (double)v.Z, (double)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(double[] v)\n            => new V4ui((uint)v[0], (uint)v[1], (uint)v[2], (uint)v[3]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(C3b v)\n            => new V4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(C3us v)\n            => new V4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(C3ui v)\n            => new V4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(C4b v)\n            => new V4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(C4us v)\n            => new V4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V4ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4ui(C4ui v)\n            => new V4ui(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4ui\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<uint, int> element_fun)\n            => new V4i(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<uint, int, int> element_index_fun)\n            => new V4i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n            array[start + 2] = (int)Z;\n            array[start + 3] = (int)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<uint, uint> element_fun)\n            => new V4ui(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<uint, int, uint> element_index_fun)\n            => new V4ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n            array[start + 3] = W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<uint, long> element_fun)\n            => new V4l(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<uint, int, long> element_index_fun)\n            => new V4l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n            array[start + 2] = (long)Z;\n            array[start + 3] = (long)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<uint, float> element_fun)\n            => new V4f(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<uint, int, float> element_index_fun)\n            => new V4f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n            array[start + 2] = (float)Z;\n            array[start + 3] = (float)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<uint, double> element_fun)\n            => new V4d(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<uint, int, double> element_index_fun)\n            => new V4d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n            array[start + 2] = (double)Z;\n            array[start + 3] = (double)W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n            array[start + 3] = element_fun(W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<uint, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n            array[start + 3] = element_index_fun(W, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly uint[] ToArray()\n            => new uint[] { X, Y, Z, W };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field W.\n        /// Useful when properties are required, but the field W is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public uint P_W\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return W;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                W = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<uint> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n                yield return W;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe uint this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (uint* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (uint* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y\n                        ? (X >= Z ? (X >= W ? 0 : 3) : (Z >= W ? 2 : 3))\n                        : (Y >= Z ? (Y >= W ? 1 : 3) : (Z >= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y\n                        ? (X <= Z ? (X <= W ? 0 : 3) : (Z <= W ? 2 : 3))\n                        : (Y <= Z ? (Y <= W ? 1 : 3) : (Z <= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly uint MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z, W);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly uint MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z, W);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 4;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V4ui Zero\n        {\n            get { return new V4ui(0, 0, 0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V4ui One\n        {\n            get { return new V4ui(1, 1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V4ui MaxValue\n        {\n            get { return new V4ui(Constant<uint>.ParseableMaxValue, Constant<uint>.ParseableMaxValue, Constant<uint>.ParseableMaxValue, Constant<uint>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V4ui MinValue\n        {\n            get { return new V4ui(Constant<uint>.ParseableMinValue, Constant<uint>.ParseableMinValue, Constant<uint>.ParseableMinValue, Constant<uint>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V4ui XAxis\n        {\n            get { return new V4ui(1, 0, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V4ui YAxis\n        {\n            get { return new V4ui(0, 1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V4ui ZAxis\n        {\n            get { return new V4ui(0, 0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized W-axis.\n        /// </summary>\n        public static V4ui WAxis\n        {\n            get { return new V4ui(0, 0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V4ui, uint>[] SelectorArray =\n            new Func<V4ui, uint>[] { v => v.X, v => v.Y, v => v.Z, v => v.W };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V4ui, int, uint> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V4ui, int, uint> Setter =\n            (ref V4ui v, int i, uint s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V4ui, long, uint> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V4ui, long, uint> LongSetter =\n            (ref V4ui v, long i, uint s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromV4i(V4i v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromV4l(V4l v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromV4f(V4f v)\n            => new V4ui(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromV4d(V4d v)\n            => new V4ui(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromC3b(C3b c) => new V4ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromC3us(C3us c) => new V4ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3ui\"/> color.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromC3ui(C3ui c) => new V4ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromC4b(C4b c) => new V4ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromC4us(C4us c) => new V4ui(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4ui\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FromC4ui(C4ui c) => new V4ui(c);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly uint LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z  + W * W ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z  + W * W );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly uint Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X + Y + Z + W; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z + W * W); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly uint NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(X, Y, Z, W); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly uint NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(X, Y, Z, W); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V4d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V4d.Zero;\n                s = 1 / s;\n                return new V4d(X * s, Y * s, Z * s, W * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui LinearInterp(float t, V4ui a, V4ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui LinearInterp(V4f t, V4ui a, V4ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui LinearInterp(double t, V4ui a, V4ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui LinearInterp(V4d t, V4ui a, V4ui b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Min(V4ui v0, V4ui v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Min(V4ui v, uint x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Max(V4ui v0, V4ui v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Max(V4ui v, uint x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Saturate(V4ui v)\n            => Fun.Saturate(v);\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z, int w)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n            W = (uint)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z, uint w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z, long w)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n            W = (uint)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z, float w)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n            W = (uint)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z, double w)\n        {\n            X = (uint)x;\n            Y = (uint)y;\n            Z = (uint)z;\n            W = (uint)w;\n        }\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator ~(V4ui v)\n            => new V4ui(~v.X, ~v.Y, ~v.Z, ~v.W);\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator +(V4ui a, V4ui b)\n            => new V4ui(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator +(V4ui v, uint s)\n            => new V4ui(v.X + s, v.Y + s, v.Z + s, v.W + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator +(uint s, V4ui v)\n            => new V4ui(s + v.X, s + v.Y, s + v.Z, s + v.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator -(V4ui a, V4ui b)\n            => new V4ui(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator -(V4ui v, uint s)\n            => new V4ui(v.X - s, v.Y - s, v.Z - s, v.W - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator -(uint s, V4ui v)\n            => new V4ui(s - v.X, s - v.Y, s - v.Z, s - v.W);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator *(V4ui a, V4ui b)\n            => new V4ui(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator *(V4ui v, uint s)\n            => new V4ui(v.X * s, v.Y * s, v.Z * s, v.W * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator *(uint s, V4ui v)\n            => new V4ui(s * v.X, s * v.Y, s * v.Z, s * v.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator /(V4ui a, V4ui b)\n            => new V4ui(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator /(V4ui v, uint s)\n            => new V4ui(v.X / s, v.Y / s, v.Z / s, v.W / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator /(uint s, V4ui v)\n            => new V4ui(s / v.X, s / v.Y, s / v.Z, s / v.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator %(V4ui a, V4ui b)\n            => new V4ui(a.X % b.X, a.Y % b.Y, a.Z % b.Z, a.W % b.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator %(V4ui v, uint s)\n            => new V4ui(v.X % s, v.Y % s, v.Z % s, v.W % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator %(uint s, V4ui v)\n            => new V4ui(s % v.X, s % v.Y, s % v.Z, s % v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator &(V4ui a, V4ui b)\n            => new V4ui(a.X & b.X, a.Y & b.Y, a.Z & b.Z, a.W & b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator &(V4ui v, uint s)\n            => new V4ui(v.X & s, v.Y & s, v.Z & s, v.W & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator &(uint s, V4ui v)\n            => new V4ui(s & v.X, s & v.Y, s & v.Z, s & v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator |(V4ui a, V4ui b)\n            => new V4ui(a.X | b.X, a.Y | b.Y, a.Z | b.Z, a.W | b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator |(V4ui v, uint s)\n            => new V4ui(v.X | s, v.Y | s, v.Z | s, v.W | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator |(uint s, V4ui v)\n            => new V4ui(s | v.X, s | v.Y, s | v.Z, s | v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator ^(V4ui a, V4ui b)\n            => new V4ui(a.X ^ b.X, a.Y ^ b.Y, a.Z ^ b.Z, a.W ^ b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator ^(V4ui v, uint s)\n            => new V4ui(v.X ^ s, v.Y ^ s, v.Z ^ s, v.W ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator ^(uint s, V4ui v)\n            => new V4ui(s ^ v.X, s ^ v.Y, s ^ v.Z, s ^ v.W);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator <<(V4ui v, int s)\n            => new V4ui(v.X << s, v.Y << s, v.Z << s, v.W << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui operator >>(V4ui v, int s)\n            => new V4ui(v.X >> s, v.Y >> s, v.Z >> s, v.W >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4ui a, V4ui b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4ui v, uint s)\n        {\n            return v.X == s && v.Y == s && v.Z == s && v.W == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(uint s, V4ui v)\n        {\n            return s == v.X && s == v.Y && s == v.Z && s == v.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4ui a, V4ui b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4ui v, uint s)\n        {\n            return v.X != s || v.Y != s || v.Z != s || v.W != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(uint s, V4ui v)\n        {\n            return s != v.X || s != v.Y || s != v.Z || s != v.W;\n        }\n\n        #endregion\n\n        #region IEquatable<V4ui> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V4ui other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + between + W.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z, W);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V4ui o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + W.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V4ui Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V4ui(\n                uint.Parse(x[0], CultureInfo.InvariantCulture), \n                uint.Parse(x[1], CultureInfo.InvariantCulture), \n                uint.Parse(x[2], CultureInfo.InvariantCulture), \n                uint.Parse(x[3], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V4ui Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<uint>.Parse, V4ui.Setter);\n        }\n\n        public static V4ui Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<uint>.Parse, V4ui.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OX => new V2ui(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OY => new V2ui(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OZ => new V2ui(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui OW => new V2ui(0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IX => new V2ui(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IY => new V2ui(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IZ => new V2ui(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui IW => new V2ui(1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XO => new V2ui(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XI => new V2ui(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui XX => new V2ui(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui XY\n        {\n            readonly get => new V2ui(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui XZ\n        {\n            readonly get => new V2ui(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui XW\n        {\n            readonly get => new V2ui(X, W);\n            set { X = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YO => new V2ui(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YI => new V2ui(Y, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui YX\n        {\n            readonly get => new V2ui(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui YY => new V2ui(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui YZ\n        {\n            readonly get => new V2ui(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui YW\n        {\n            readonly get => new V2ui(Y, W);\n            set { Y = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui ZO => new V2ui(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui ZI => new V2ui(Z, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui ZX\n        {\n            readonly get => new V2ui(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui ZY\n        {\n            readonly get => new V2ui(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui ZZ => new V2ui(Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui ZW\n        {\n            readonly get => new V2ui(Z, W);\n            set { Z = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui WO => new V2ui(W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui WI => new V2ui(W, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui WX\n        {\n            readonly get => new V2ui(W, X);\n            set { W = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui WY\n        {\n            readonly get => new V2ui(W, Y);\n            set { W = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2ui WZ\n        {\n            readonly get => new V2ui(W, Z);\n            set { W = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2ui WW => new V2ui(W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOX => new V3ui(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOY => new V3ui(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOZ => new V3ui(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OOW => new V3ui(0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIX => new V3ui(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIY => new V3ui(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIZ => new V3ui(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OIW => new V3ui(0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXO => new V3ui(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXI => new V3ui(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXX => new V3ui(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXY => new V3ui(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXZ => new V3ui(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OXW => new V3ui(0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYO => new V3ui(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYI => new V3ui(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYX => new V3ui(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYY => new V3ui(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYZ => new V3ui(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OYW => new V3ui(0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZO => new V3ui(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZI => new V3ui(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZX => new V3ui(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZY => new V3ui(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZZ => new V3ui(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OZW => new V3ui(0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OWO => new V3ui(0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OWI => new V3ui(0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OWX => new V3ui(0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OWY => new V3ui(0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OWZ => new V3ui(0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui OWW => new V3ui(0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOX => new V3ui(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOY => new V3ui(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOZ => new V3ui(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IOW => new V3ui(1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIX => new V3ui(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIY => new V3ui(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIZ => new V3ui(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IIW => new V3ui(1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXO => new V3ui(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXI => new V3ui(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXX => new V3ui(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXY => new V3ui(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXZ => new V3ui(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IXW => new V3ui(1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYO => new V3ui(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYI => new V3ui(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYX => new V3ui(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYY => new V3ui(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYZ => new V3ui(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IYW => new V3ui(1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZO => new V3ui(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZI => new V3ui(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZX => new V3ui(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZY => new V3ui(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZZ => new V3ui(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IZW => new V3ui(1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IWO => new V3ui(1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IWI => new V3ui(1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IWX => new V3ui(1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IWY => new V3ui(1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IWZ => new V3ui(1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui IWW => new V3ui(1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOO => new V3ui(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOI => new V3ui(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOX => new V3ui(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOY => new V3ui(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOZ => new V3ui(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XOW => new V3ui(X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIO => new V3ui(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XII => new V3ui(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIX => new V3ui(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIY => new V3ui(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIZ => new V3ui(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XIW => new V3ui(X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXO => new V3ui(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXI => new V3ui(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXX => new V3ui(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXY => new V3ui(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXZ => new V3ui(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XXW => new V3ui(X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYO => new V3ui(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYI => new V3ui(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYX => new V3ui(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XYY => new V3ui(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui XYZ\n        {\n            readonly get => new V3ui(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui XYW\n        {\n            readonly get => new V3ui(X, Y, W);\n            set { X = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XZO => new V3ui(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XZI => new V3ui(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XZX => new V3ui(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui XZY\n        {\n            readonly get => new V3ui(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XZZ => new V3ui(X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui XZW\n        {\n            readonly get => new V3ui(X, Z, W);\n            set { X = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XWO => new V3ui(X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XWI => new V3ui(X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XWX => new V3ui(X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui XWY\n        {\n            readonly get => new V3ui(X, W, Y);\n            set { X = value.X; W = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui XWZ\n        {\n            readonly get => new V3ui(X, W, Z);\n            set { X = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui XWW => new V3ui(X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOO => new V3ui(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOI => new V3ui(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOX => new V3ui(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOY => new V3ui(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOZ => new V3ui(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YOW => new V3ui(Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIO => new V3ui(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YII => new V3ui(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIX => new V3ui(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIY => new V3ui(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIZ => new V3ui(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YIW => new V3ui(Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXO => new V3ui(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXI => new V3ui(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXX => new V3ui(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YXY => new V3ui(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui YXZ\n        {\n            readonly get => new V3ui(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui YXW\n        {\n            readonly get => new V3ui(Y, X, W);\n            set { Y = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYO => new V3ui(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYI => new V3ui(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYX => new V3ui(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYY => new V3ui(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYZ => new V3ui(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YYW => new V3ui(Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YZO => new V3ui(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YZI => new V3ui(Y, Z, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui YZX\n        {\n            readonly get => new V3ui(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YZY => new V3ui(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YZZ => new V3ui(Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui YZW\n        {\n            readonly get => new V3ui(Y, Z, W);\n            set { Y = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YWO => new V3ui(Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YWI => new V3ui(Y, W, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui YWX\n        {\n            readonly get => new V3ui(Y, W, X);\n            set { Y = value.X; W = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YWY => new V3ui(Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui YWZ\n        {\n            readonly get => new V3ui(Y, W, Z);\n            set { Y = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui YWW => new V3ui(Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOO => new V3ui(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOI => new V3ui(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOX => new V3ui(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOY => new V3ui(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOZ => new V3ui(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZOW => new V3ui(Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIO => new V3ui(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZII => new V3ui(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIX => new V3ui(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIY => new V3ui(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIZ => new V3ui(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZIW => new V3ui(Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZXO => new V3ui(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZXI => new V3ui(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZXX => new V3ui(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui ZXY\n        {\n            readonly get => new V3ui(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZXZ => new V3ui(Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui ZXW\n        {\n            readonly get => new V3ui(Z, X, W);\n            set { Z = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZYO => new V3ui(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZYI => new V3ui(Z, Y, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui ZYX\n        {\n            readonly get => new V3ui(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZYY => new V3ui(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZYZ => new V3ui(Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui ZYW\n        {\n            readonly get => new V3ui(Z, Y, W);\n            set { Z = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZO => new V3ui(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZI => new V3ui(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZX => new V3ui(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZY => new V3ui(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZZ => new V3ui(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZZW => new V3ui(Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZWO => new V3ui(Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZWI => new V3ui(Z, W, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui ZWX\n        {\n            readonly get => new V3ui(Z, W, X);\n            set { Z = value.X; W = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui ZWY\n        {\n            readonly get => new V3ui(Z, W, Y);\n            set { Z = value.X; W = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZWZ => new V3ui(Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui ZWW => new V3ui(Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WOO => new V3ui(W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WOI => new V3ui(W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WOX => new V3ui(W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WOY => new V3ui(W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WOZ => new V3ui(W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WOW => new V3ui(W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WIO => new V3ui(W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WII => new V3ui(W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WIX => new V3ui(W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WIY => new V3ui(W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WIZ => new V3ui(W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WIW => new V3ui(W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WXO => new V3ui(W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WXI => new V3ui(W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WXX => new V3ui(W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui WXY\n        {\n            readonly get => new V3ui(W, X, Y);\n            set { W = value.X; X = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui WXZ\n        {\n            readonly get => new V3ui(W, X, Z);\n            set { W = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WXW => new V3ui(W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WYO => new V3ui(W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WYI => new V3ui(W, Y, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui WYX\n        {\n            readonly get => new V3ui(W, Y, X);\n            set { W = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WYY => new V3ui(W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui WYZ\n        {\n            readonly get => new V3ui(W, Y, Z);\n            set { W = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WYW => new V3ui(W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WZO => new V3ui(W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WZI => new V3ui(W, Z, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui WZX\n        {\n            readonly get => new V3ui(W, Z, X);\n            set { W = value.X; Z = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3ui WZY\n        {\n            readonly get => new V3ui(W, Z, Y);\n            set { W = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WZZ => new V3ui(W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WZW => new V3ui(W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WWO => new V3ui(W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WWI => new V3ui(W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WWX => new V3ui(W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WWY => new V3ui(W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WWZ => new V3ui(W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3ui WWW => new V3ui(W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui OOOO => new V4ui(0, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui OOOI => new V4ui(0, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOX => new V4ui(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOY => new V4ui(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOZ => new V4ui(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOOW => new V4ui(0, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui OOIO => new V4ui(0, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui OOII => new V4ui(0, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIX => new V4ui(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIY => new V4ui(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIZ => new V4ui(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOIW => new V4ui(0, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXO => new V4ui(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXI => new V4ui(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXX => new V4ui(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXY => new V4ui(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXZ => new V4ui(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOXW => new V4ui(0, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYO => new V4ui(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYI => new V4ui(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYX => new V4ui(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYY => new V4ui(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYZ => new V4ui(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOYW => new V4ui(0, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZO => new V4ui(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZI => new V4ui(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZX => new V4ui(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZY => new V4ui(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZZ => new V4ui(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOZW => new V4ui(0, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOWO => new V4ui(0, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOWI => new V4ui(0, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOWX => new V4ui(0, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOWY => new V4ui(0, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOWZ => new V4ui(0, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OOWW => new V4ui(0, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui OIOO => new V4ui(0, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui OIOI => new V4ui(0, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOX => new V4ui(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOY => new V4ui(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOZ => new V4ui(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIOW => new V4ui(0, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui OIIO => new V4ui(0, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui OIII => new V4ui(0, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIX => new V4ui(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIY => new V4ui(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIZ => new V4ui(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIIW => new V4ui(0, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXO => new V4ui(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXI => new V4ui(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXX => new V4ui(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXY => new V4ui(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXZ => new V4ui(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIXW => new V4ui(0, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYO => new V4ui(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYI => new V4ui(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYX => new V4ui(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYY => new V4ui(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYZ => new V4ui(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIYW => new V4ui(0, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZO => new V4ui(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZI => new V4ui(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZX => new V4ui(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZY => new V4ui(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZZ => new V4ui(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIZW => new V4ui(0, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIWO => new V4ui(0, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIWI => new V4ui(0, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIWX => new V4ui(0, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIWY => new V4ui(0, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIWZ => new V4ui(0, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OIWW => new V4ui(0, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOO => new V4ui(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOI => new V4ui(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOX => new V4ui(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOY => new V4ui(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOZ => new V4ui(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXOW => new V4ui(0, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIO => new V4ui(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXII => new V4ui(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIX => new V4ui(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIY => new V4ui(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIZ => new V4ui(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXIW => new V4ui(0, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXO => new V4ui(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXI => new V4ui(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXX => new V4ui(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXY => new V4ui(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXZ => new V4ui(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXXW => new V4ui(0, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYO => new V4ui(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYI => new V4ui(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYX => new V4ui(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYY => new V4ui(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYZ => new V4ui(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXYW => new V4ui(0, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZO => new V4ui(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZI => new V4ui(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZX => new V4ui(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZY => new V4ui(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZZ => new V4ui(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXZW => new V4ui(0, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXWO => new V4ui(0, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXWI => new V4ui(0, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXWX => new V4ui(0, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXWY => new V4ui(0, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXWZ => new V4ui(0, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OXWW => new V4ui(0, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOO => new V4ui(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOI => new V4ui(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOX => new V4ui(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOY => new V4ui(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOZ => new V4ui(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYOW => new V4ui(0, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIO => new V4ui(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYII => new V4ui(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIX => new V4ui(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIY => new V4ui(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIZ => new V4ui(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYIW => new V4ui(0, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXO => new V4ui(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXI => new V4ui(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXX => new V4ui(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXY => new V4ui(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXZ => new V4ui(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYXW => new V4ui(0, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYO => new V4ui(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYI => new V4ui(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYX => new V4ui(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYY => new V4ui(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYZ => new V4ui(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYYW => new V4ui(0, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZO => new V4ui(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZI => new V4ui(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZX => new V4ui(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZY => new V4ui(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZZ => new V4ui(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYZW => new V4ui(0, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYWO => new V4ui(0, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYWI => new V4ui(0, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYWX => new V4ui(0, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYWY => new V4ui(0, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYWZ => new V4ui(0, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OYWW => new V4ui(0, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOO => new V4ui(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOI => new V4ui(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOX => new V4ui(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOY => new V4ui(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOZ => new V4ui(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZOW => new V4ui(0, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIO => new V4ui(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZII => new V4ui(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIX => new V4ui(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIY => new V4ui(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIZ => new V4ui(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZIW => new V4ui(0, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXO => new V4ui(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXI => new V4ui(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXX => new V4ui(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXY => new V4ui(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXZ => new V4ui(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZXW => new V4ui(0, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYO => new V4ui(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYI => new V4ui(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYX => new V4ui(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYY => new V4ui(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYZ => new V4ui(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZYW => new V4ui(0, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZO => new V4ui(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZI => new V4ui(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZX => new V4ui(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZY => new V4ui(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZZ => new V4ui(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZZW => new V4ui(0, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZWO => new V4ui(0, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZWI => new V4ui(0, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZWX => new V4ui(0, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZWY => new V4ui(0, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZWZ => new V4ui(0, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OZWW => new V4ui(0, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWOO => new V4ui(0, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWOI => new V4ui(0, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWOX => new V4ui(0, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWOY => new V4ui(0, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWOZ => new V4ui(0, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWOW => new V4ui(0, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWIO => new V4ui(0, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWII => new V4ui(0, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWIX => new V4ui(0, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWIY => new V4ui(0, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWIZ => new V4ui(0, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWIW => new V4ui(0, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWXO => new V4ui(0, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWXI => new V4ui(0, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWXX => new V4ui(0, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWXY => new V4ui(0, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWXZ => new V4ui(0, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWXW => new V4ui(0, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWYO => new V4ui(0, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWYI => new V4ui(0, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWYX => new V4ui(0, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWYY => new V4ui(0, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWYZ => new V4ui(0, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWYW => new V4ui(0, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWZO => new V4ui(0, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWZI => new V4ui(0, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWZX => new V4ui(0, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWZY => new V4ui(0, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWZZ => new V4ui(0, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWZW => new V4ui(0, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWWO => new V4ui(0, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWWI => new V4ui(0, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWWX => new V4ui(0, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWWY => new V4ui(0, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWWZ => new V4ui(0, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui OWWW => new V4ui(0, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui IOOO => new V4ui(1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui IOOI => new V4ui(1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOX => new V4ui(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOY => new V4ui(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOZ => new V4ui(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOOW => new V4ui(1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui IOIO => new V4ui(1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui IOII => new V4ui(1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIX => new V4ui(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIY => new V4ui(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIZ => new V4ui(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOIW => new V4ui(1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXO => new V4ui(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXI => new V4ui(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXX => new V4ui(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXY => new V4ui(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXZ => new V4ui(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOXW => new V4ui(1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYO => new V4ui(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYI => new V4ui(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYX => new V4ui(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYY => new V4ui(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYZ => new V4ui(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOYW => new V4ui(1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZO => new V4ui(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZI => new V4ui(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZX => new V4ui(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZY => new V4ui(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZZ => new V4ui(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOZW => new V4ui(1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOWO => new V4ui(1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOWI => new V4ui(1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOWX => new V4ui(1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOWY => new V4ui(1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOWZ => new V4ui(1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IOWW => new V4ui(1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui IIOO => new V4ui(1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui IIOI => new V4ui(1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOX => new V4ui(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOY => new V4ui(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOZ => new V4ui(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIOW => new V4ui(1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui IIIO => new V4ui(1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4ui IIII => new V4ui(1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIX => new V4ui(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIY => new V4ui(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIZ => new V4ui(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIIW => new V4ui(1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXO => new V4ui(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXI => new V4ui(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXX => new V4ui(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXY => new V4ui(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXZ => new V4ui(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIXW => new V4ui(1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYO => new V4ui(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYI => new V4ui(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYX => new V4ui(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYY => new V4ui(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYZ => new V4ui(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIYW => new V4ui(1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZO => new V4ui(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZI => new V4ui(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZX => new V4ui(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZY => new V4ui(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZZ => new V4ui(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIZW => new V4ui(1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIWO => new V4ui(1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIWI => new V4ui(1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIWX => new V4ui(1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIWY => new V4ui(1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIWZ => new V4ui(1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IIWW => new V4ui(1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOO => new V4ui(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOI => new V4ui(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOX => new V4ui(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOY => new V4ui(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOZ => new V4ui(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXOW => new V4ui(1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIO => new V4ui(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXII => new V4ui(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIX => new V4ui(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIY => new V4ui(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIZ => new V4ui(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXIW => new V4ui(1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXO => new V4ui(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXI => new V4ui(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXX => new V4ui(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXY => new V4ui(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXZ => new V4ui(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXXW => new V4ui(1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYO => new V4ui(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYI => new V4ui(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYX => new V4ui(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYY => new V4ui(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYZ => new V4ui(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXYW => new V4ui(1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZO => new V4ui(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZI => new V4ui(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZX => new V4ui(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZY => new V4ui(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZZ => new V4ui(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXZW => new V4ui(1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXWO => new V4ui(1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXWI => new V4ui(1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXWX => new V4ui(1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXWY => new V4ui(1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXWZ => new V4ui(1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IXWW => new V4ui(1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOO => new V4ui(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOI => new V4ui(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOX => new V4ui(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOY => new V4ui(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOZ => new V4ui(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYOW => new V4ui(1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIO => new V4ui(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYII => new V4ui(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIX => new V4ui(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIY => new V4ui(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIZ => new V4ui(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYIW => new V4ui(1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXO => new V4ui(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXI => new V4ui(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXX => new V4ui(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXY => new V4ui(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXZ => new V4ui(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYXW => new V4ui(1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYO => new V4ui(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYI => new V4ui(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYX => new V4ui(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYY => new V4ui(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYZ => new V4ui(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYYW => new V4ui(1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZO => new V4ui(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZI => new V4ui(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZX => new V4ui(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZY => new V4ui(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZZ => new V4ui(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYZW => new V4ui(1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYWO => new V4ui(1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYWI => new V4ui(1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYWX => new V4ui(1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYWY => new V4ui(1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYWZ => new V4ui(1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IYWW => new V4ui(1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOO => new V4ui(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOI => new V4ui(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOX => new V4ui(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOY => new V4ui(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOZ => new V4ui(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZOW => new V4ui(1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIO => new V4ui(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZII => new V4ui(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIX => new V4ui(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIY => new V4ui(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIZ => new V4ui(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZIW => new V4ui(1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXO => new V4ui(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXI => new V4ui(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXX => new V4ui(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXY => new V4ui(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXZ => new V4ui(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZXW => new V4ui(1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYO => new V4ui(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYI => new V4ui(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYX => new V4ui(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYY => new V4ui(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYZ => new V4ui(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZYW => new V4ui(1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZO => new V4ui(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZI => new V4ui(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZX => new V4ui(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZY => new V4ui(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZZ => new V4ui(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZZW => new V4ui(1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZWO => new V4ui(1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZWI => new V4ui(1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZWX => new V4ui(1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZWY => new V4ui(1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZWZ => new V4ui(1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IZWW => new V4ui(1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWOO => new V4ui(1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWOI => new V4ui(1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWOX => new V4ui(1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWOY => new V4ui(1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWOZ => new V4ui(1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWOW => new V4ui(1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWIO => new V4ui(1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWII => new V4ui(1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWIX => new V4ui(1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWIY => new V4ui(1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWIZ => new V4ui(1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWIW => new V4ui(1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWXO => new V4ui(1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWXI => new V4ui(1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWXX => new V4ui(1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWXY => new V4ui(1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWXZ => new V4ui(1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWXW => new V4ui(1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWYO => new V4ui(1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWYI => new V4ui(1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWYX => new V4ui(1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWYY => new V4ui(1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWYZ => new V4ui(1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWYW => new V4ui(1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWZO => new V4ui(1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWZI => new V4ui(1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWZX => new V4ui(1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWZY => new V4ui(1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWZZ => new V4ui(1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWZW => new V4ui(1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWWO => new V4ui(1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWWI => new V4ui(1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWWX => new V4ui(1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWWY => new V4ui(1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWWZ => new V4ui(1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui IWWW => new V4ui(1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOO => new V4ui(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOI => new V4ui(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOX => new V4ui(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOY => new V4ui(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOZ => new V4ui(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOOW => new V4ui(X, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIO => new V4ui(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOII => new V4ui(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIX => new V4ui(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIY => new V4ui(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIZ => new V4ui(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOIW => new V4ui(X, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXO => new V4ui(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXI => new V4ui(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXX => new V4ui(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXY => new V4ui(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXZ => new V4ui(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOXW => new V4ui(X, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYO => new V4ui(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYI => new V4ui(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYX => new V4ui(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYY => new V4ui(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYZ => new V4ui(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOYW => new V4ui(X, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZO => new V4ui(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZI => new V4ui(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZX => new V4ui(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZY => new V4ui(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZZ => new V4ui(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOZW => new V4ui(X, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOWO => new V4ui(X, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOWI => new V4ui(X, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOWX => new V4ui(X, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOWY => new V4ui(X, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOWZ => new V4ui(X, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XOWW => new V4ui(X, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOO => new V4ui(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOI => new V4ui(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOX => new V4ui(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOY => new V4ui(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOZ => new V4ui(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIOW => new V4ui(X, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIO => new V4ui(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIII => new V4ui(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIX => new V4ui(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIY => new V4ui(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIZ => new V4ui(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIIW => new V4ui(X, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXO => new V4ui(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXI => new V4ui(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXX => new V4ui(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXY => new V4ui(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXZ => new V4ui(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIXW => new V4ui(X, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYO => new V4ui(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYI => new V4ui(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYX => new V4ui(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYY => new V4ui(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYZ => new V4ui(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIYW => new V4ui(X, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZO => new V4ui(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZI => new V4ui(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZX => new V4ui(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZY => new V4ui(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZZ => new V4ui(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIZW => new V4ui(X, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIWO => new V4ui(X, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIWI => new V4ui(X, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIWX => new V4ui(X, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIWY => new V4ui(X, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIWZ => new V4ui(X, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XIWW => new V4ui(X, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOO => new V4ui(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOI => new V4ui(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOX => new V4ui(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOY => new V4ui(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOZ => new V4ui(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXOW => new V4ui(X, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIO => new V4ui(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXII => new V4ui(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIX => new V4ui(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIY => new V4ui(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIZ => new V4ui(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXIW => new V4ui(X, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXO => new V4ui(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXI => new V4ui(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXX => new V4ui(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXY => new V4ui(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXZ => new V4ui(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXXW => new V4ui(X, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYO => new V4ui(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYI => new V4ui(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYX => new V4ui(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYY => new V4ui(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYZ => new V4ui(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXYW => new V4ui(X, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZO => new V4ui(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZI => new V4ui(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZX => new V4ui(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZY => new V4ui(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZZ => new V4ui(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXZW => new V4ui(X, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXWO => new V4ui(X, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXWI => new V4ui(X, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXWX => new V4ui(X, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXWY => new V4ui(X, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXWZ => new V4ui(X, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XXWW => new V4ui(X, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOO => new V4ui(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOI => new V4ui(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOX => new V4ui(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOY => new V4ui(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOZ => new V4ui(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYOW => new V4ui(X, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIO => new V4ui(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYII => new V4ui(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIX => new V4ui(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIY => new V4ui(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIZ => new V4ui(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYIW => new V4ui(X, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXO => new V4ui(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXI => new V4ui(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXX => new V4ui(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXY => new V4ui(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXZ => new V4ui(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYXW => new V4ui(X, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYO => new V4ui(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYI => new V4ui(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYX => new V4ui(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYY => new V4ui(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYZ => new V4ui(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYYW => new V4ui(X, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZO => new V4ui(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZI => new V4ui(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZX => new V4ui(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZY => new V4ui(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYZZ => new V4ui(X, Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui XYZW\n        {\n            readonly get => new V4ui(X, Y, Z, W);\n            set { X = value.X; Y = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYWO => new V4ui(X, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYWI => new V4ui(X, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYWX => new V4ui(X, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYWY => new V4ui(X, Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui XYWZ\n        {\n            readonly get => new V4ui(X, Y, W, Z);\n            set { X = value.X; Y = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XYWW => new V4ui(X, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOO => new V4ui(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOI => new V4ui(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOX => new V4ui(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOY => new V4ui(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOZ => new V4ui(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZOW => new V4ui(X, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIO => new V4ui(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZII => new V4ui(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIX => new V4ui(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIY => new V4ui(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIZ => new V4ui(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZIW => new V4ui(X, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXO => new V4ui(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXI => new V4ui(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXX => new V4ui(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXY => new V4ui(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXZ => new V4ui(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZXW => new V4ui(X, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYO => new V4ui(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYI => new V4ui(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYX => new V4ui(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYY => new V4ui(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZYZ => new V4ui(X, Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui XZYW\n        {\n            readonly get => new V4ui(X, Z, Y, W);\n            set { X = value.X; Z = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZO => new V4ui(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZI => new V4ui(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZX => new V4ui(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZY => new V4ui(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZZ => new V4ui(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZZW => new V4ui(X, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZWO => new V4ui(X, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZWI => new V4ui(X, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZWX => new V4ui(X, Z, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui XZWY\n        {\n            readonly get => new V4ui(X, Z, W, Y);\n            set { X = value.X; Z = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZWZ => new V4ui(X, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XZWW => new V4ui(X, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWOO => new V4ui(X, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWOI => new V4ui(X, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWOX => new V4ui(X, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWOY => new V4ui(X, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWOZ => new V4ui(X, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWOW => new V4ui(X, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWIO => new V4ui(X, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWII => new V4ui(X, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWIX => new V4ui(X, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWIY => new V4ui(X, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWIZ => new V4ui(X, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWIW => new V4ui(X, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWXO => new V4ui(X, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWXI => new V4ui(X, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWXX => new V4ui(X, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWXY => new V4ui(X, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWXZ => new V4ui(X, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWXW => new V4ui(X, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWYO => new V4ui(X, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWYI => new V4ui(X, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWYX => new V4ui(X, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWYY => new V4ui(X, W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui XWYZ\n        {\n            readonly get => new V4ui(X, W, Y, Z);\n            set { X = value.X; W = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWYW => new V4ui(X, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWZO => new V4ui(X, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWZI => new V4ui(X, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWZX => new V4ui(X, W, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui XWZY\n        {\n            readonly get => new V4ui(X, W, Z, Y);\n            set { X = value.X; W = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWZZ => new V4ui(X, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWZW => new V4ui(X, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWWO => new V4ui(X, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWWI => new V4ui(X, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWWX => new V4ui(X, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWWY => new V4ui(X, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWWZ => new V4ui(X, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui XWWW => new V4ui(X, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOO => new V4ui(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOI => new V4ui(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOX => new V4ui(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOY => new V4ui(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOZ => new V4ui(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOOW => new V4ui(Y, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIO => new V4ui(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOII => new V4ui(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIX => new V4ui(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIY => new V4ui(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIZ => new V4ui(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOIW => new V4ui(Y, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXO => new V4ui(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXI => new V4ui(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXX => new V4ui(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXY => new V4ui(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXZ => new V4ui(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOXW => new V4ui(Y, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYO => new V4ui(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYI => new V4ui(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYX => new V4ui(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYY => new V4ui(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYZ => new V4ui(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOYW => new V4ui(Y, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZO => new V4ui(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZI => new V4ui(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZX => new V4ui(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZY => new V4ui(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZZ => new V4ui(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOZW => new V4ui(Y, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOWO => new V4ui(Y, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOWI => new V4ui(Y, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOWX => new V4ui(Y, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOWY => new V4ui(Y, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOWZ => new V4ui(Y, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YOWW => new V4ui(Y, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOO => new V4ui(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOI => new V4ui(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOX => new V4ui(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOY => new V4ui(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOZ => new V4ui(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIOW => new V4ui(Y, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIO => new V4ui(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIII => new V4ui(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIX => new V4ui(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIY => new V4ui(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIZ => new V4ui(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIIW => new V4ui(Y, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXO => new V4ui(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXI => new V4ui(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXX => new V4ui(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXY => new V4ui(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXZ => new V4ui(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIXW => new V4ui(Y, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYO => new V4ui(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYI => new V4ui(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYX => new V4ui(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYY => new V4ui(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYZ => new V4ui(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIYW => new V4ui(Y, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZO => new V4ui(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZI => new V4ui(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZX => new V4ui(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZY => new V4ui(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZZ => new V4ui(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIZW => new V4ui(Y, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIWO => new V4ui(Y, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIWI => new V4ui(Y, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIWX => new V4ui(Y, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIWY => new V4ui(Y, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIWZ => new V4ui(Y, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YIWW => new V4ui(Y, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOO => new V4ui(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOI => new V4ui(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOX => new V4ui(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOY => new V4ui(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOZ => new V4ui(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXOW => new V4ui(Y, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIO => new V4ui(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXII => new V4ui(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIX => new V4ui(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIY => new V4ui(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIZ => new V4ui(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXIW => new V4ui(Y, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXO => new V4ui(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXI => new V4ui(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXX => new V4ui(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXY => new V4ui(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXZ => new V4ui(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXXW => new V4ui(Y, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYO => new V4ui(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYI => new V4ui(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYX => new V4ui(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYY => new V4ui(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYZ => new V4ui(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXYW => new V4ui(Y, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZO => new V4ui(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZI => new V4ui(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZX => new V4ui(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZY => new V4ui(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXZZ => new V4ui(Y, X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui YXZW\n        {\n            readonly get => new V4ui(Y, X, Z, W);\n            set { Y = value.X; X = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXWO => new V4ui(Y, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXWI => new V4ui(Y, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXWX => new V4ui(Y, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXWY => new V4ui(Y, X, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui YXWZ\n        {\n            readonly get => new V4ui(Y, X, W, Z);\n            set { Y = value.X; X = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YXWW => new V4ui(Y, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOO => new V4ui(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOI => new V4ui(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOX => new V4ui(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOY => new V4ui(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOZ => new V4ui(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYOW => new V4ui(Y, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIO => new V4ui(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYII => new V4ui(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIX => new V4ui(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIY => new V4ui(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIZ => new V4ui(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYIW => new V4ui(Y, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXO => new V4ui(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXI => new V4ui(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXX => new V4ui(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXY => new V4ui(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXZ => new V4ui(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYXW => new V4ui(Y, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYO => new V4ui(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYI => new V4ui(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYX => new V4ui(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYY => new V4ui(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYZ => new V4ui(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYYW => new V4ui(Y, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZO => new V4ui(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZI => new V4ui(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZX => new V4ui(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZY => new V4ui(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZZ => new V4ui(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYZW => new V4ui(Y, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYWO => new V4ui(Y, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYWI => new V4ui(Y, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYWX => new V4ui(Y, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYWY => new V4ui(Y, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYWZ => new V4ui(Y, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YYWW => new V4ui(Y, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOO => new V4ui(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOI => new V4ui(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOX => new V4ui(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOY => new V4ui(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOZ => new V4ui(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZOW => new V4ui(Y, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIO => new V4ui(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZII => new V4ui(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIX => new V4ui(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIY => new V4ui(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIZ => new V4ui(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZIW => new V4ui(Y, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXO => new V4ui(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXI => new V4ui(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXX => new V4ui(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXY => new V4ui(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZXZ => new V4ui(Y, Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui YZXW\n        {\n            readonly get => new V4ui(Y, Z, X, W);\n            set { Y = value.X; Z = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYO => new V4ui(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYI => new V4ui(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYX => new V4ui(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYY => new V4ui(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYZ => new V4ui(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZYW => new V4ui(Y, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZO => new V4ui(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZI => new V4ui(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZX => new V4ui(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZY => new V4ui(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZZ => new V4ui(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZZW => new V4ui(Y, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZWO => new V4ui(Y, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZWI => new V4ui(Y, Z, W, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui YZWX\n        {\n            readonly get => new V4ui(Y, Z, W, X);\n            set { Y = value.X; Z = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZWY => new V4ui(Y, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZWZ => new V4ui(Y, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YZWW => new V4ui(Y, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWOO => new V4ui(Y, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWOI => new V4ui(Y, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWOX => new V4ui(Y, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWOY => new V4ui(Y, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWOZ => new V4ui(Y, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWOW => new V4ui(Y, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWIO => new V4ui(Y, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWII => new V4ui(Y, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWIX => new V4ui(Y, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWIY => new V4ui(Y, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWIZ => new V4ui(Y, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWIW => new V4ui(Y, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWXO => new V4ui(Y, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWXI => new V4ui(Y, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWXX => new V4ui(Y, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWXY => new V4ui(Y, W, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui YWXZ\n        {\n            readonly get => new V4ui(Y, W, X, Z);\n            set { Y = value.X; W = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWXW => new V4ui(Y, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWYO => new V4ui(Y, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWYI => new V4ui(Y, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWYX => new V4ui(Y, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWYY => new V4ui(Y, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWYZ => new V4ui(Y, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWYW => new V4ui(Y, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWZO => new V4ui(Y, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWZI => new V4ui(Y, W, Z, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui YWZX\n        {\n            readonly get => new V4ui(Y, W, Z, X);\n            set { Y = value.X; W = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWZY => new V4ui(Y, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWZZ => new V4ui(Y, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWZW => new V4ui(Y, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWWO => new V4ui(Y, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWWI => new V4ui(Y, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWWX => new V4ui(Y, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWWY => new V4ui(Y, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWWZ => new V4ui(Y, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui YWWW => new V4ui(Y, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOO => new V4ui(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOI => new V4ui(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOX => new V4ui(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOY => new V4ui(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOZ => new V4ui(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOOW => new V4ui(Z, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIO => new V4ui(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOII => new V4ui(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIX => new V4ui(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIY => new V4ui(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIZ => new V4ui(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOIW => new V4ui(Z, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXO => new V4ui(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXI => new V4ui(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXX => new V4ui(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXY => new V4ui(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXZ => new V4ui(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOXW => new V4ui(Z, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYO => new V4ui(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYI => new V4ui(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYX => new V4ui(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYY => new V4ui(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYZ => new V4ui(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOYW => new V4ui(Z, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZO => new V4ui(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZI => new V4ui(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZX => new V4ui(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZY => new V4ui(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZZ => new V4ui(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOZW => new V4ui(Z, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOWO => new V4ui(Z, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOWI => new V4ui(Z, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOWX => new V4ui(Z, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOWY => new V4ui(Z, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOWZ => new V4ui(Z, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZOWW => new V4ui(Z, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOO => new V4ui(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOI => new V4ui(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOX => new V4ui(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOY => new V4ui(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOZ => new V4ui(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIOW => new V4ui(Z, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIO => new V4ui(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIII => new V4ui(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIX => new V4ui(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIY => new V4ui(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIZ => new V4ui(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIIW => new V4ui(Z, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXO => new V4ui(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXI => new V4ui(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXX => new V4ui(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXY => new V4ui(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXZ => new V4ui(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIXW => new V4ui(Z, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYO => new V4ui(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYI => new V4ui(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYX => new V4ui(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYY => new V4ui(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYZ => new V4ui(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIYW => new V4ui(Z, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZO => new V4ui(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZI => new V4ui(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZX => new V4ui(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZY => new V4ui(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZZ => new V4ui(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIZW => new V4ui(Z, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIWO => new V4ui(Z, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIWI => new V4ui(Z, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIWX => new V4ui(Z, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIWY => new V4ui(Z, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIWZ => new V4ui(Z, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZIWW => new V4ui(Z, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOO => new V4ui(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOI => new V4ui(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOX => new V4ui(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOY => new V4ui(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOZ => new V4ui(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXOW => new V4ui(Z, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIO => new V4ui(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXII => new V4ui(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIX => new V4ui(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIY => new V4ui(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIZ => new V4ui(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXIW => new V4ui(Z, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXO => new V4ui(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXI => new V4ui(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXX => new V4ui(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXY => new V4ui(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXZ => new V4ui(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXXW => new V4ui(Z, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYO => new V4ui(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYI => new V4ui(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYX => new V4ui(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYY => new V4ui(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXYZ => new V4ui(Z, X, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui ZXYW\n        {\n            readonly get => new V4ui(Z, X, Y, W);\n            set { Z = value.X; X = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZO => new V4ui(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZI => new V4ui(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZX => new V4ui(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZY => new V4ui(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZZ => new V4ui(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXZW => new V4ui(Z, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXWO => new V4ui(Z, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXWI => new V4ui(Z, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXWX => new V4ui(Z, X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui ZXWY\n        {\n            readonly get => new V4ui(Z, X, W, Y);\n            set { Z = value.X; X = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXWZ => new V4ui(Z, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZXWW => new V4ui(Z, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOO => new V4ui(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOI => new V4ui(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOX => new V4ui(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOY => new V4ui(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOZ => new V4ui(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYOW => new V4ui(Z, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIO => new V4ui(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYII => new V4ui(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIX => new V4ui(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIY => new V4ui(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIZ => new V4ui(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYIW => new V4ui(Z, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXO => new V4ui(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXI => new V4ui(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXX => new V4ui(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXY => new V4ui(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYXZ => new V4ui(Z, Y, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui ZYXW\n        {\n            readonly get => new V4ui(Z, Y, X, W);\n            set { Z = value.X; Y = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYO => new V4ui(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYI => new V4ui(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYX => new V4ui(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYY => new V4ui(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYZ => new V4ui(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYYW => new V4ui(Z, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZO => new V4ui(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZI => new V4ui(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZX => new V4ui(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZY => new V4ui(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZZ => new V4ui(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYZW => new V4ui(Z, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYWO => new V4ui(Z, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYWI => new V4ui(Z, Y, W, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui ZYWX\n        {\n            readonly get => new V4ui(Z, Y, W, X);\n            set { Z = value.X; Y = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYWY => new V4ui(Z, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYWZ => new V4ui(Z, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZYWW => new V4ui(Z, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOO => new V4ui(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOI => new V4ui(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOX => new V4ui(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOY => new V4ui(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOZ => new V4ui(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZOW => new V4ui(Z, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIO => new V4ui(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZII => new V4ui(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIX => new V4ui(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIY => new V4ui(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIZ => new V4ui(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZIW => new V4ui(Z, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXO => new V4ui(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXI => new V4ui(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXX => new V4ui(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXY => new V4ui(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXZ => new V4ui(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZXW => new V4ui(Z, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYO => new V4ui(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYI => new V4ui(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYX => new V4ui(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYY => new V4ui(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYZ => new V4ui(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZYW => new V4ui(Z, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZO => new V4ui(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZI => new V4ui(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZX => new V4ui(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZY => new V4ui(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZZ => new V4ui(Z, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZZW => new V4ui(Z, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZWO => new V4ui(Z, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZWI => new V4ui(Z, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZWX => new V4ui(Z, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZWY => new V4ui(Z, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZWZ => new V4ui(Z, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZZWW => new V4ui(Z, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWOO => new V4ui(Z, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWOI => new V4ui(Z, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWOX => new V4ui(Z, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWOY => new V4ui(Z, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWOZ => new V4ui(Z, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWOW => new V4ui(Z, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWIO => new V4ui(Z, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWII => new V4ui(Z, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWIX => new V4ui(Z, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWIY => new V4ui(Z, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWIZ => new V4ui(Z, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWIW => new V4ui(Z, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWXO => new V4ui(Z, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWXI => new V4ui(Z, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWXX => new V4ui(Z, W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui ZWXY\n        {\n            readonly get => new V4ui(Z, W, X, Y);\n            set { Z = value.X; W = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWXZ => new V4ui(Z, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWXW => new V4ui(Z, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWYO => new V4ui(Z, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWYI => new V4ui(Z, W, Y, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui ZWYX\n        {\n            readonly get => new V4ui(Z, W, Y, X);\n            set { Z = value.X; W = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWYY => new V4ui(Z, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWYZ => new V4ui(Z, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWYW => new V4ui(Z, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWZO => new V4ui(Z, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWZI => new V4ui(Z, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWZX => new V4ui(Z, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWZY => new V4ui(Z, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWZZ => new V4ui(Z, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWZW => new V4ui(Z, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWWO => new V4ui(Z, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWWI => new V4ui(Z, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWWX => new V4ui(Z, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWWY => new V4ui(Z, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWWZ => new V4ui(Z, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui ZWWW => new V4ui(Z, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOOO => new V4ui(W, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOOI => new V4ui(W, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOOX => new V4ui(W, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOOY => new V4ui(W, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOOZ => new V4ui(W, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOOW => new V4ui(W, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOIO => new V4ui(W, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOII => new V4ui(W, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOIX => new V4ui(W, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOIY => new V4ui(W, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOIZ => new V4ui(W, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOIW => new V4ui(W, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOXO => new V4ui(W, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOXI => new V4ui(W, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOXX => new V4ui(W, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOXY => new V4ui(W, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOXZ => new V4ui(W, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOXW => new V4ui(W, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOYO => new V4ui(W, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOYI => new V4ui(W, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOYX => new V4ui(W, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOYY => new V4ui(W, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOYZ => new V4ui(W, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOYW => new V4ui(W, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOZO => new V4ui(W, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOZI => new V4ui(W, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOZX => new V4ui(W, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOZY => new V4ui(W, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOZZ => new V4ui(W, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOZW => new V4ui(W, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOWO => new V4ui(W, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOWI => new V4ui(W, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOWX => new V4ui(W, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOWY => new V4ui(W, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOWZ => new V4ui(W, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WOWW => new V4ui(W, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIOO => new V4ui(W, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIOI => new V4ui(W, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIOX => new V4ui(W, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIOY => new V4ui(W, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIOZ => new V4ui(W, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIOW => new V4ui(W, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIIO => new V4ui(W, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIII => new V4ui(W, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIIX => new V4ui(W, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIIY => new V4ui(W, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIIZ => new V4ui(W, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIIW => new V4ui(W, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIXO => new V4ui(W, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIXI => new V4ui(W, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIXX => new V4ui(W, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIXY => new V4ui(W, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIXZ => new V4ui(W, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIXW => new V4ui(W, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIYO => new V4ui(W, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIYI => new V4ui(W, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIYX => new V4ui(W, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIYY => new V4ui(W, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIYZ => new V4ui(W, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIYW => new V4ui(W, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIZO => new V4ui(W, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIZI => new V4ui(W, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIZX => new V4ui(W, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIZY => new V4ui(W, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIZZ => new V4ui(W, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIZW => new V4ui(W, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIWO => new V4ui(W, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIWI => new V4ui(W, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIWX => new V4ui(W, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIWY => new V4ui(W, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIWZ => new V4ui(W, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WIWW => new V4ui(W, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXOO => new V4ui(W, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXOI => new V4ui(W, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXOX => new V4ui(W, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXOY => new V4ui(W, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXOZ => new V4ui(W, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXOW => new V4ui(W, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXIO => new V4ui(W, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXII => new V4ui(W, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXIX => new V4ui(W, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXIY => new V4ui(W, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXIZ => new V4ui(W, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXIW => new V4ui(W, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXXO => new V4ui(W, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXXI => new V4ui(W, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXXX => new V4ui(W, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXXY => new V4ui(W, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXXZ => new V4ui(W, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXXW => new V4ui(W, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXYO => new V4ui(W, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXYI => new V4ui(W, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXYX => new V4ui(W, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXYY => new V4ui(W, X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui WXYZ\n        {\n            readonly get => new V4ui(W, X, Y, Z);\n            set { W = value.X; X = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXYW => new V4ui(W, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXZO => new V4ui(W, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXZI => new V4ui(W, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXZX => new V4ui(W, X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui WXZY\n        {\n            readonly get => new V4ui(W, X, Z, Y);\n            set { W = value.X; X = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXZZ => new V4ui(W, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXZW => new V4ui(W, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXWO => new V4ui(W, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXWI => new V4ui(W, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXWX => new V4ui(W, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXWY => new V4ui(W, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXWZ => new V4ui(W, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WXWW => new V4ui(W, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYOO => new V4ui(W, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYOI => new V4ui(W, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYOX => new V4ui(W, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYOY => new V4ui(W, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYOZ => new V4ui(W, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYOW => new V4ui(W, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYIO => new V4ui(W, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYII => new V4ui(W, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYIX => new V4ui(W, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYIY => new V4ui(W, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYIZ => new V4ui(W, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYIW => new V4ui(W, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYXO => new V4ui(W, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYXI => new V4ui(W, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYXX => new V4ui(W, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYXY => new V4ui(W, Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui WYXZ\n        {\n            readonly get => new V4ui(W, Y, X, Z);\n            set { W = value.X; Y = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYXW => new V4ui(W, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYYO => new V4ui(W, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYYI => new V4ui(W, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYYX => new V4ui(W, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYYY => new V4ui(W, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYYZ => new V4ui(W, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYYW => new V4ui(W, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYZO => new V4ui(W, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYZI => new V4ui(W, Y, Z, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui WYZX\n        {\n            readonly get => new V4ui(W, Y, Z, X);\n            set { W = value.X; Y = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYZY => new V4ui(W, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYZZ => new V4ui(W, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYZW => new V4ui(W, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYWO => new V4ui(W, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYWI => new V4ui(W, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYWX => new V4ui(W, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYWY => new V4ui(W, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYWZ => new V4ui(W, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WYWW => new V4ui(W, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZOO => new V4ui(W, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZOI => new V4ui(W, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZOX => new V4ui(W, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZOY => new V4ui(W, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZOZ => new V4ui(W, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZOW => new V4ui(W, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZIO => new V4ui(W, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZII => new V4ui(W, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZIX => new V4ui(W, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZIY => new V4ui(W, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZIZ => new V4ui(W, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZIW => new V4ui(W, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZXO => new V4ui(W, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZXI => new V4ui(W, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZXX => new V4ui(W, Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui WZXY\n        {\n            readonly get => new V4ui(W, Z, X, Y);\n            set { W = value.X; Z = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZXZ => new V4ui(W, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZXW => new V4ui(W, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZYO => new V4ui(W, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZYI => new V4ui(W, Z, Y, 1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4ui WZYX\n        {\n            readonly get => new V4ui(W, Z, Y, X);\n            set { W = value.X; Z = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZYY => new V4ui(W, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZYZ => new V4ui(W, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZYW => new V4ui(W, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZZO => new V4ui(W, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZZI => new V4ui(W, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZZX => new V4ui(W, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZZY => new V4ui(W, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZZZ => new V4ui(W, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZZW => new V4ui(W, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZWO => new V4ui(W, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZWI => new V4ui(W, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZWX => new V4ui(W, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZWY => new V4ui(W, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZWZ => new V4ui(W, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WZWW => new V4ui(W, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWOO => new V4ui(W, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWOI => new V4ui(W, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWOX => new V4ui(W, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWOY => new V4ui(W, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWOZ => new V4ui(W, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWOW => new V4ui(W, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWIO => new V4ui(W, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWII => new V4ui(W, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWIX => new V4ui(W, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWIY => new V4ui(W, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWIZ => new V4ui(W, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWIW => new V4ui(W, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWXO => new V4ui(W, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWXI => new V4ui(W, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWXX => new V4ui(W, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWXY => new V4ui(W, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWXZ => new V4ui(W, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWXW => new V4ui(W, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWYO => new V4ui(W, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWYI => new V4ui(W, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWYX => new V4ui(W, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWYY => new V4ui(W, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWYZ => new V4ui(W, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWYW => new V4ui(W, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWZO => new V4ui(W, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWZI => new V4ui(W, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWZX => new V4ui(W, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWZY => new V4ui(W, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWZZ => new V4ui(W, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWZW => new V4ui(W, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWWO => new V4ui(W, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWWI => new V4ui(W, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWWX => new V4ui(W, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWWY => new V4ui(W, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWWZ => new V4ui(W, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4ui WWWW => new V4ui(W, W, W, W);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (uint)value; }\n        }\n\n        #endregion\n\n        #region ISize4ui Members\n\n        public readonly V4ui Size4ui { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 4; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (uint)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V4uiEqualityComparer : IEqualityComparer<V4ui>\n    {\n        public static V4uiEqualityComparer Default\n            => new V4uiEqualityComparer();\n\n        #region IEqualityComparer<V4ui> Members\n\n        public bool Equals(V4ui v0, V4ui v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V4ui v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Min(this V4ui a, V4ui b)\n        {\n            return new V4ui(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z), Min(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Min(this V4ui a, uint b)\n        {\n            return new V4ui(Min(a.X, b), Min(a.Y, b), Min(a.Z, b), Min(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Min(this uint a, V4ui b)\n        {\n            return new V4ui(Min(a, b.X), Min(a, b.Y), Min(a, b.Z), Min(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Max(this V4ui a, V4ui b)\n        {\n            return new V4ui(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z), Max(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Max(this V4ui a, uint b)\n        {\n            return new V4ui(Max(a.X, b), Max(a.Y, b), Max(a.Z, b), Max(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Max(this uint a, V4ui b)\n        {\n            return new V4ui(Max(a, b.X), Max(a, b.Y), Max(a, b.Z), Max(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Min(this V4ui a, V4ui b, V4ui c)\n        {\n            return new V4ui(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z), Min(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Max(this V4ui a, V4ui b, V4ui c)\n        {\n            return new V4ui(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z), Max(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Min(this V4ui a, V4ui b, V4ui c, V4ui d)\n        {\n            return new V4ui(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z), Min(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Max(this V4ui a, V4ui b, V4ui c, V4ui d)\n        {\n            return new V4ui(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z), Max(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Min(this V4ui x, params V4ui[] values)\n        {\n            return new V4ui(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)), Min(x.W, values.Map(a => a.W)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Max(this V4ui x, params V4ui[] values)\n        {\n            return new V4ui(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)), Max(x.W, values.Map(a => a.W)));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Clamp(this V4ui x, V4ui a, V4ui b)\n        {\n            return new V4ui(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z), Clamp(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Clamp(this V4ui x, uint a, uint b)\n        {\n            return new V4ui(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b), Clamp(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui ClampExcl(this V4ui x, V4ui a, V4ui b)\n        {\n            return new V4ui(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y), ClampExcl(x.Z, a.Z, b.Z), ClampExcl(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui ClampExcl(this V4ui x, uint a, uint b)\n        {\n            return new V4ui(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b), ClampExcl(x.Z, a, b), ClampExcl(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui ClampWrap(this V4ui x, V4ui a, V4ui b)\n        {\n            return new V4ui(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z), ClampWrap(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui ClampWrap(this V4ui x, uint a, uint b)\n        {\n            return new V4ui(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b), ClampWrap(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Saturate(this V4ui x)\n        {\n            return new V4ui(Saturate(x.X), Saturate(x.Y), Saturate(x.Z), Saturate(x.W));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui MultiplyAdd(V4ui x, V4ui y, V4ui z)\n        {\n            return new V4ui(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z), MultiplyAdd(x.W, y.W, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui MultiplyAdd(V4ui x, uint y, V4ui z)\n        {\n            return new V4ui(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z), MultiplyAdd(x.W, y, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui MultiplyAdd(uint x, V4ui y, V4ui z)\n        {\n            return new V4ui(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z), MultiplyAdd(x, y.W, z.W));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sqrt(this V4ui x)\n        {\n            return new V4d(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z), Sqrt(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Cbrt(this V4ui x)\n        {\n            return new V4d(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z), Cbrt(x.W));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Square(this V4ui x)\n        {\n            return new V4ui(Square(x.X), Square(x.Y), Square(x.Z), Square(x.W));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Pown(this V4ui x, V4ui y)\n        {\n            return new V4ui(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z), Pown(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Pown(this V4ui x, uint y)\n        {\n            return new V4ui(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y), Pown(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Pown(this uint x, V4ui y)\n        {\n            return new V4ui(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z), Pown(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Pown(this V4ui x, V4i y)\n        {\n            return new V4ui(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z), Pown(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Pown(this V4ui x, int y)\n        {\n            return new V4ui(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y), Pown(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Pown(this uint x, V4i y)\n        {\n            return new V4ui(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z), Pown(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this V4ui x, V4f y)\n        {\n            return new V4f(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z), Pow(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this V4ui x, float y)\n        {\n            return new V4f(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y), Pow(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this uint x, V4f y)\n        {\n            return new V4f(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z), Pow(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this V4ui x, V4d y)\n        {\n            return new V4d(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z), Pow(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this V4ui x, double y)\n        {\n            return new V4d(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y), Pow(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this uint x, V4d y)\n        {\n            return new V4d(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z), Pow(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this V4ui x, V4f y)\n        {\n            return new V4f(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z), Power(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this V4ui x, float y)\n        {\n            return new V4f(Power(x.X, y), Power(x.Y, y), Power(x.Z, y), Power(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this uint x, V4f y)\n        {\n            return new V4f(Power(x, y.X), Power(x, y.Y), Power(x, y.Z), Power(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this V4ui x, V4d y)\n        {\n            return new V4d(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z), Power(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this V4ui x, double y)\n        {\n            return new V4d(Power(x.X, y), Power(x.Y, y), Power(x.Z, y), Power(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this uint x, V4d y)\n        {\n            return new V4d(Power(x, y.X), Power(x, y.Y), Power(x, y.Z), Power(x, y.W));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Exp(this V4ui x)\n        {\n            return new V4d(Exp(x.X), Exp(x.Y), Exp(x.Z), Exp(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(this V4ui x)\n        {\n            return new V4d(Log(x.X), Log(x.Y), Log(x.Z), Log(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log2(this V4ui x)\n        {\n            return new V4d(Log2(x.X), Log2(x.Y), Log2(x.Z), Log2(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Log2Int(this V4ui x)\n        {\n            return new V4i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z), Log2Int(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log10(this V4ui x)\n        {\n            return new V4d(Log10(x.X), Log10(x.Y), Log10(x.Z), Log10(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(this V4ui x, double basis)\n        {\n            return new V4d(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis), Log(x.W, basis));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Step(this V4ui x, V4ui edge)\n        {\n            return new V4ui(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z), Step(x.W, edge.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Step(this V4ui x, uint edge)\n        {\n            return new V4ui(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge), Step(x.W, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Lerp(this float t, V4ui a, V4ui b)\n        {\n            return new V4ui(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z), Lerp(t, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Lerp(this V4f t, V4ui a, V4ui b)\n        {\n            return new V4ui(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z), Lerp(t.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Lerp(this double t, V4ui a, V4ui b)\n        {\n            return new V4ui(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z), Lerp(t, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui Lerp(this V4d t, V4ui a, V4ui b)\n        {\n            return new V4ui(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z), Lerp(t.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvLerp(this V4ui y, V4ui a, V4ui b)\n        {\n            return new V4d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z), InvLerp(y.W, a.W, b.W));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui GreatestCommonDivisor(this V4ui a, V4ui b)\n        {\n            return new V4ui(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y), GreatestCommonDivisor(a.Z, b.Z), GreatestCommonDivisor(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui LeastCommonMultiple(this V4ui a, V4ui b)\n        {\n            return new V4ui(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y), LeastCommonMultiple(a.Z, b.Z), LeastCommonMultiple(a.W, b.W));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromUnsignedBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FloatFromUnsignedBits(this V4ui x)\n        {\n            return new V4f(FloatFromUnsignedBits(x.X), FloatFromUnsignedBits(x.Y), FloatFromUnsignedBits(x.Z), FloatFromUnsignedBits(x.W));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V4ui a, V4ui b, uint tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance) && ApproximateEquals(a.W, b.W, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V4ui v, uint epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint LengthSquared(V4ui v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V4ui v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Normalized(V4ui v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Norm1(V4ui v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V4ui v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint NormMax(V4ui v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint NormMin(V4ui v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V4ui v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p) + \n                Fun.Abs(v.W).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceSquared(this V4ui a, V4ui b)\n            => Fun.Square((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)) + Fun.Square((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)) + Fun.Square((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z)) + Fun.Square((a.W < b.W) ? (b.W - a.W) : (a.W - b.W));\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V4ui a, V4ui b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Distance1(this V4ui a, V4ui b)\n            => ((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)) + ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)) + ((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z)) + ((a.W < b.W) ? (b.W - a.W) : (a.W - b.W));\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V4ui a, V4ui b, double p)\n            => (((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)).Pow(p) + ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)).Pow(p) + ((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z)).Pow(p) + ((a.W < b.W) ? (b.W - a.W) : (a.W - b.W)).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceMax(this V4ui a, V4ui b)\n            => Fun.Max(((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)), ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)), ((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z)), ((a.W < b.W) ? (b.W - a.W) : (a.W - b.W)));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint DistanceMin(this V4ui a, V4ui b)\n            => Fun.Min(((a.X < b.X) ? (b.X - a.X) : (a.X - b.X)), ((a.Y < b.Y) ? (b.Y - a.Y) : (a.Y - b.Y)), ((a.Z < b.Z) ? (b.Z - a.Z) : (a.Z - b.Z)), ((a.W < b.W) ? (b.W - a.W) : (a.W - b.W)));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V4ui query, V4ui p0, V4ui p1)\n        {\n            return DistanceToLine((V4d) query, (V4d) p0, (V4d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V4ui query, V4ui p0, V4ui p1)\n        {\n            return DistanceToInfiniteLine((V4d) query, (V4d) p0, (V4d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V4ui query, V4ui p0, V4ui p1, out double t)\n        {\n            return DistanceToLine((V4d) query, (V4d) p0, (V4d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V4ui query, V4ui p0, V4ui p1, out double t)\n        {\n            return DistanceToInfiniteLine((V4d) query, (V4d) p0, (V4d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint Dot(this V4ui a, V4ui b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V4ui v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > 0) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < 0) flags |= Aardbase.DirFlags.NegativeZ;\n            if (v.W > 0) flags |= Aardbase.DirFlags.PositiveW;\n            if (v.W < 0) flags |= Aardbase.DirFlags.NegativeW;\n            return flags;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4ui a, V4ui b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z && a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4ui v, uint s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s && v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(uint s, V4ui v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z && s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4ui a, V4ui b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z || a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4ui v, uint s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s || v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(uint s, V4ui v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z || s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4ui a, V4ui b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z && a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4ui v, uint s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s && v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(uint s, V4ui v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z && s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4ui a, V4ui b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z || a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4ui v, uint s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s || v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(uint s, V4ui v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z || s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4ui a, V4ui b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z && a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4ui v, uint s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s && v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(uint s, V4ui v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z && s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4ui a, V4ui b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z || a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4ui v, uint s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s || v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(uint s, V4ui v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z || s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4ui a, V4ui b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z && a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4ui v, uint s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s && v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(uint s, V4ui v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z && s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4ui a, V4ui b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z || a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4ui v, uint s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s || v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(uint s, V4ui v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z || s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4ui a, V4ui b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4ui v, uint s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s && v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(uint s, V4ui v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z && s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4ui a, V4ui b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z || a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4ui v, uint s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s || v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(uint s, V4ui v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z || s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4ui a, V4ui b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z && a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4ui v, uint s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s && v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(uint s, V4ui v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z && s != v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4ui a, V4ui b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4ui v, uint s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s || v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(uint s, V4ui v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z || s != v.W);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V4ui v0, V4ui v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            if (v0.W < v1.W) return -1;\n            if (v0.W > v1.W) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V4ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint MinElement(V4ui v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V4ui\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static uint MaxElement(V4ui v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V4ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V4ui v, uint epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon) || v.W.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4ui\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V4ui v, uint epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon) && v.W.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V4ui[] pointArray, V4ui point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V4ui[] array, int start, int count,\n                V4ui point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V4ui> pointSelector, V4ui point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V4ui[] pointArray, V4ui point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V4ui[] array, long start, long count,\n                V4ui point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V4ui> pointSelector, V4ui point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V4ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V4ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V4ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V4ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V4ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V4ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V4ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V4ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V4ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V4ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V4ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V4ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinW(this V4ui[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinW(this V4ui[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxW(this V4ui[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxW(this V4ui[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V4ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V4ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V4ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V4ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V4ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V4ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinW(this IList<V4ui> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxW(this IList<V4ui> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static uint[] CopyCoord(this V4ui[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                case 3: return self.Map(v => v.W);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV4uiExtensions\n    {\n        #region IRandomUniform extensions for V4ui\n\n        /// <summary>\n        /// Uses UniformUInt() to generate the elements of a V4ui vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui UniformV4ui(this IRandomUniform rnd)\n        {\n            return new V4ui(rnd.UniformUInt(), rnd.UniformUInt(), rnd.UniformUInt(), rnd.UniformUInt());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V4l\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V4l : IVector<double>, ISize4l, IFormattable, IEquatable<V4l>\n    {\n        [DataMember]\n        public long X;\n        [DataMember]\n        public long Y;\n        [DataMember]\n        public long Z;\n        [DataMember]\n        public long W;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(int x, int y, int z, int w)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n            W = (long)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(int v)\n        {\n            X = (long)v;\n            Y = (long)v;\n            Z = (long)v;\n            W = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(int[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n            Z = (long)a[2];\n            W = (long)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(int[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n            Z = (long)a[start + 2];\n            W = (long)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(int a, V3i b)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n            W = (long)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2i a, V2i b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b.X;\n            W = (long)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3i a, int b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)a.Z;\n            W = (long)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/>, <see cref=\"int\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2i a, int b, int c)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b;\n            W = (long)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"V2i\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(int a, V2i b, int c)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n            W = (long)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"int\"/>, and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(int a, int b, V2i c)\n        {\n            X = (long)a;\n            Y = (long)b;\n            Z = (long)c.X;\n            W = (long)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(uint x, uint y, uint z, uint w)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n            W = (long)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(uint v)\n        {\n            X = (long)v;\n            Y = (long)v;\n            Z = (long)v;\n            W = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(uint[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n            Z = (long)a[2];\n            W = (long)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(uint[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n            Z = (long)a[start + 2];\n            W = (long)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(uint a, V3ui b)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n            W = (long)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2ui a, V2ui b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b.X;\n            W = (long)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3ui a, uint b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)a.Z;\n            W = (long)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/>, <see cref=\"uint\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2ui a, uint b, uint c)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b;\n            W = (long)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"V2ui\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(uint a, V2ui b, uint c)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n            W = (long)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"uint\"/>, and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(uint a, uint b, V2ui c)\n        {\n            X = (long)a;\n            Y = (long)b;\n            Z = (long)c.X;\n            W = (long)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(long x, long y, long z, long w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(long v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n            W = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(long[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n            W = a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(long[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n            W = a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(long a, V3l b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2l a, V2l b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b.X;\n            W = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3l a, long b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = a.Z;\n            W = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/>, <see cref=\"long\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2l a, long b, long c)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"V2l\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(long a, V2l b, long c)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"long\"/>, and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(long a, long b, V2l c)\n        {\n            X = a;\n            Y = b;\n            Z = c.X;\n            W = c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(float x, float y, float z, float w)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n            W = (long)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(float v)\n        {\n            X = (long)v;\n            Y = (long)v;\n            Z = (long)v;\n            W = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(float[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n            Z = (long)a[2];\n            W = (long)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(float[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n            Z = (long)a[start + 2];\n            W = (long)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(float a, V3f b)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n            W = (long)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2f a, V2f b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b.X;\n            W = (long)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3f a, float b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)a.Z;\n            W = (long)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/>, <see cref=\"float\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2f a, float b, float c)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b;\n            W = (long)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"V2f\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(float a, V2f b, float c)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n            W = (long)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"float\"/>, and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(float a, float b, V2f c)\n        {\n            X = (long)a;\n            Y = (long)b;\n            Z = (long)c.X;\n            W = (long)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(double x, double y, double z, double w)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n            W = (long)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(double v)\n        {\n            X = (long)v;\n            Y = (long)v;\n            Z = (long)v;\n            W = (long)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(double[] a)\n        {\n            X = (long)a[0];\n            Y = (long)a[1];\n            Z = (long)a[2];\n            W = (long)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(double[] a, int start)\n        {\n            X = (long)a[start + 0];\n            Y = (long)a[start + 1];\n            Z = (long)a[start + 2];\n            W = (long)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(double a, V3d b)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n            W = (long)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2d a, V2d b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b.X;\n            W = (long)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3d a, double b)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)a.Z;\n            W = (long)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/>, <see cref=\"double\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2d a, double b, double c)\n        {\n            X = (long)a.X;\n            Y = (long)a.Y;\n            Z = (long)b;\n            W = (long)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"V2d\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(double a, V2d b, double c)\n        {\n            X = (long)a;\n            Y = (long)b.X;\n            Z = (long)b.Y;\n            W = (long)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"double\"/>, and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(double a, double b, V2d c)\n        {\n            X = (long)a;\n            Y = (long)b;\n            Z = (long)c.X;\n            W = (long)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(Func<int, long> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n            W = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;long&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 4.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(IVector<double> v)\n            : this(v[0], v[1], v[2], v[3])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2l v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V2d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3l v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V3d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V4i v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n            W = (long)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V4ui v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n            W = (long)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V4l v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V4f v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n            W = (long)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(V4d v)\n        {\n            X = (long)v.X;\n            Y = (long)v.Y;\n            Z = (long)v.Z;\n            W = (long)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(C3b c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n            W = (long)255;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(C3us c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n            W = (long)65535;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(C3ui c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n            W = (long)UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(C4b c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n            W = (long)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(C4us c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n            W = (long)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4l(C4ui c)\n        {\n            X = (long)(c.R);\n            Y = (long)(c.G);\n            Z = (long)(c.B);\n            W = (long)(c.A);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V2i v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V2ui v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V2l v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V2f v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V2d v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V3i v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V3ui v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V3l v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V3f v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V3d v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V4i v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V4ui v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V4f v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(V4d v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V4l v)\n            => new int[] { (int)v.X, (int)v.Y, (int)v.Z, (int)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(int[] v)\n            => new V4l((long)v[0], (long)v[1], (long)v[2], (long)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V4l v)\n            => new uint[] { (uint)v.X, (uint)v.Y, (uint)v.Z, (uint)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(uint[] v)\n            => new V4l((long)v[0], (long)v[1], (long)v[2], (long)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V4l v)\n            => new long[] { v.X, v.Y, v.Z, v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(long[] v)\n            => new V4l(v[0], v[1], v[2], v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V4l v)\n            => new float[] { (float)v.X, (float)v.Y, (float)v.Z, (float)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(float[] v)\n            => new V4l((long)v[0], (long)v[1], (long)v[2], (long)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V4l v)\n            => new double[] { (double)v.X, (double)v.Y, (double)v.Z, (double)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(double[] v)\n            => new V4l((long)v[0], (long)v[1], (long)v[2], (long)v[3]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(C3b v)\n            => new V4l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(C3us v)\n            => new V4l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(C3ui v)\n            => new V4l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(C4b v)\n            => new V4l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(C4us v)\n            => new V4l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V4l\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4l(C4ui v)\n            => new V4l(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4l\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<long, int> element_fun)\n            => new V4i(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<long, int, int> element_index_fun)\n            => new V4i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n            array[start + 2] = (int)Z;\n            array[start + 3] = (int)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<long, uint> element_fun)\n            => new V4ui(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<long, int, uint> element_index_fun)\n            => new V4ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n            array[start + 2] = (uint)Z;\n            array[start + 3] = (uint)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<long, long> element_fun)\n            => new V4l(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<long, int, long> element_index_fun)\n            => new V4l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n            array[start + 3] = W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<long, float> element_fun)\n            => new V4f(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<long, int, float> element_index_fun)\n            => new V4f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n            array[start + 2] = (float)Z;\n            array[start + 3] = (float)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<long, double> element_fun)\n            => new V4d(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<long, int, double> element_index_fun)\n            => new V4d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n            array[start + 2] = (double)Z;\n            array[start + 3] = (double)W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<long, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n            array[start + 3] = element_fun(W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<long, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n            array[start + 3] = element_index_fun(W, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly long[] ToArray()\n            => new long[] { X, Y, Z, W };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field W.\n        /// Useful when properties are required, but the field W is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public long P_W\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return W;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                W = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<long> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n                yield return W;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe long this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (long* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (long* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y\n                        ? (X >= Z ? (X >= W ? 0 : 3) : (Z >= W ? 2 : 3))\n                        : (Y >= Z ? (Y >= W ? 1 : 3) : (Z >= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y\n                        ? (X <= Z ? (X <= W ? 0 : 3) : (Z <= W ? 2 : 3))\n                        : (Y <= Z ? (Y <= W ? 1 : 3) : (Z <= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly long MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z, W);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly long MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z, W);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 4;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V4l Zero\n        {\n            get { return new V4l(0, 0, 0, 0); }\n        }\n\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V4l One\n        {\n            get { return new V4l(1, 1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V4l MaxValue\n        {\n            get { return new V4l(Constant<long>.ParseableMaxValue, Constant<long>.ParseableMaxValue, Constant<long>.ParseableMaxValue, Constant<long>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V4l MinValue\n        {\n            get { return new V4l(Constant<long>.ParseableMinValue, Constant<long>.ParseableMinValue, Constant<long>.ParseableMinValue, Constant<long>.ParseableMinValue); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V4l XAxis\n        {\n            get { return new V4l(1, 0, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V4l YAxis\n        {\n            get { return new V4l(0, 1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V4l ZAxis\n        {\n            get { return new V4l(0, 0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized W-axis.\n        /// </summary>\n        public static V4l WAxis\n        {\n            get { return new V4l(0, 0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V4l, long>[] SelectorArray =\n            new Func<V4l, long>[] { v => v.X, v => v.Y, v => v.Z, v => v.W };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V4l, int, long> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V4l, int, long> Setter =\n            (ref V4l v, int i, long s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V4l, long, long> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V4l, long, long> LongSetter =\n            (ref V4l v, long i, long s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromV4i(V4i v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromV4ui(V4ui v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromV4f(V4f v)\n            => new V4l(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromV4d(V4d v)\n            => new V4l(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromC3b(C3b c) => new V4l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromC3us(C3us c) => new V4l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromC3ui(C3ui c) => new V4l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromC4b(C4b c) => new V4l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromC4us(C4us c) => new V4l(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FromC4ui(C4ui c) => new V4l(c);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly long LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z  + W * W ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z  + W * W );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly long Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y) + Fun.Abs(Z) + Fun.Abs(W); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z + W * W); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly long NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly long NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V4d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V4d.Zero;\n                s = 1 / s;\n                return new V4d(X * s, Y * s, Z * s, W * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Abs(V4l v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l LinearInterp(float t, V4l a, V4l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l LinearInterp(V4f t, V4l a, V4l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l LinearInterp(double t, V4l a, V4l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l LinearInterp(V4d t, V4l a, V4l b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Min(V4l v0, V4l v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Min(V4l v, long x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Max(V4l v0, V4l v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Max(V4l v, long x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Saturate(V4l v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l DivideByInt(V4l v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z, int w)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n            W = (long)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z, uint w)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n            W = (long)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z, long w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z, float w)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n            W = (long)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z, double w)\n        {\n            X = (long)x;\n            Y = (long)y;\n            Z = (long)z;\n            W = (long)w;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator -(V4l v)\n            => new V4l(-v.X, -v.Y, -v.Z, -v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator ~(V4l v)\n            => new V4l(~v.X, ~v.Y, ~v.Z, ~v.W);\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator +(V4l a, V4l b)\n            => new V4l(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator +(V4l v, long s)\n            => new V4l(v.X + s, v.Y + s, v.Z + s, v.W + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator +(long s, V4l v)\n            => new V4l(s + v.X, s + v.Y, s + v.Z, s + v.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator -(V4l a, V4l b)\n            => new V4l(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator -(V4l v, long s)\n            => new V4l(v.X - s, v.Y - s, v.Z - s, v.W - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator -(long s, V4l v)\n            => new V4l(s - v.X, s - v.Y, s - v.Z, s - v.W);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator *(V4l a, V4l b)\n            => new V4l(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator *(V4l v, long s)\n            => new V4l(v.X * s, v.Y * s, v.Z * s, v.W * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator *(long s, V4l v)\n            => new V4l(s * v.X, s * v.Y, s * v.Z, s * v.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator /(V4l a, V4l b)\n            => new V4l(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator /(V4l v, long s)\n            => new V4l(v.X / s, v.Y / s, v.Z / s, v.W / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator /(long s, V4l v)\n            => new V4l(s / v.X, s / v.Y, s / v.Z, s / v.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator %(V4l a, V4l b)\n            => new V4l(a.X % b.X, a.Y % b.Y, a.Z % b.Z, a.W % b.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator %(V4l v, long s)\n            => new V4l(v.X % s, v.Y % s, v.Z % s, v.W % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator %(long s, V4l v)\n            => new V4l(s % v.X, s % v.Y, s % v.Z, s % v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator &(V4l a, V4l b)\n            => new V4l(a.X & b.X, a.Y & b.Y, a.Z & b.Z, a.W & b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator &(V4l v, long s)\n            => new V4l(v.X & s, v.Y & s, v.Z & s, v.W & s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise and of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator &(long s, V4l v)\n            => new V4l(s & v.X, s & v.Y, s & v.Z, s & v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator |(V4l a, V4l b)\n            => new V4l(a.X | b.X, a.Y | b.Y, a.Z | b.Z, a.W | b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator |(V4l v, long s)\n            => new V4l(v.X | s, v.Y | s, v.Z | s, v.W | s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator |(long s, V4l v)\n            => new V4l(s | v.X, s | v.Y, s | v.Z, s | v.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator ^(V4l a, V4l b)\n            => new V4l(a.X ^ b.X, a.Y ^ b.Y, a.Z ^ b.Z, a.W ^ b.W);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator ^(V4l v, long s)\n            => new V4l(v.X ^ s, v.Y ^ s, v.Z ^ s, v.W ^ s);\n\n        /// <summary>\n        /// Returns the component-wise bitwise exclusive or of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator ^(long s, V4l v)\n            => new V4l(s ^ v.X, s ^ v.Y, s ^ v.Z, s ^ v.W);\n\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator <<(V4l v, int s)\n            => new V4l(v.X << s, v.Y << s, v.Z << s, v.W << s);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l operator >>(V4l v, int s)\n            => new V4l(v.X >> s, v.Y >> s, v.Z >> s, v.W >> s);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4l a, V4l b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4l v, long s)\n        {\n            return v.X == s && v.Y == s && v.Z == s && v.W == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(long s, V4l v)\n        {\n            return s == v.X && s == v.Y && s == v.Z && s == v.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4l a, V4l b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4l v, long s)\n        {\n            return v.X != s || v.Y != s || v.Z != s || v.W != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(long s, V4l v)\n        {\n            return s != v.X || s != v.Y || s != v.Z || s != v.W;\n        }\n\n        #endregion\n\n        #region IEquatable<V4l> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V4l other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + between + W.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z, W);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V4l o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + W.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V4l Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V4l(\n                long.Parse(x[0], CultureInfo.InvariantCulture), \n                long.Parse(x[1], CultureInfo.InvariantCulture), \n                long.Parse(x[2], CultureInfo.InvariantCulture), \n                long.Parse(x[3], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V4l Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<long>.Parse, V4l.Setter);\n        }\n\n        public static V4l Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<long>.Parse, V4l.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OX => new V2l(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OY => new V2l(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OZ => new V2l(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OW => new V2l(0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IX => new V2l(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IY => new V2l(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IZ => new V2l(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IW => new V2l(1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NX => new V2l(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NY => new V2l(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NZ => new V2l(-1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l NW => new V2l(-1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XO => new V2l(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XI => new V2l(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XN => new V2l(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l XX => new V2l(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l XY\n        {\n            readonly get => new V2l(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l XZ\n        {\n            readonly get => new V2l(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l XW\n        {\n            readonly get => new V2l(X, W);\n            set { X = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YO => new V2l(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YI => new V2l(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YN => new V2l(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l YX\n        {\n            readonly get => new V2l(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l YY => new V2l(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l YZ\n        {\n            readonly get => new V2l(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l YW\n        {\n            readonly get => new V2l(Y, W);\n            set { Y = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l ZO => new V2l(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l ZI => new V2l(Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l ZN => new V2l(Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l ZX\n        {\n            readonly get => new V2l(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l ZY\n        {\n            readonly get => new V2l(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l ZZ => new V2l(Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l ZW\n        {\n            readonly get => new V2l(Z, W);\n            set { Z = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l WO => new V2l(W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l WI => new V2l(W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l WN => new V2l(W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l WX\n        {\n            readonly get => new V2l(W, X);\n            set { W = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l WY\n        {\n            readonly get => new V2l(W, Y);\n            set { W = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l WZ\n        {\n            readonly get => new V2l(W, Z);\n            set { W = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l WW => new V2l(W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOX => new V3l(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOY => new V3l(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOZ => new V3l(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOW => new V3l(0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIX => new V3l(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIY => new V3l(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIZ => new V3l(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIW => new V3l(0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONX => new V3l(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONY => new V3l(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONZ => new V3l(0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ONW => new V3l(0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXO => new V3l(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXI => new V3l(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXN => new V3l(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXX => new V3l(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXY => new V3l(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXZ => new V3l(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OXW => new V3l(0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYO => new V3l(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYI => new V3l(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYN => new V3l(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYX => new V3l(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYY => new V3l(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYZ => new V3l(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OYW => new V3l(0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZO => new V3l(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZI => new V3l(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZN => new V3l(0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZX => new V3l(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZY => new V3l(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZZ => new V3l(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OZW => new V3l(0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OWO => new V3l(0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OWI => new V3l(0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OWN => new V3l(0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OWX => new V3l(0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OWY => new V3l(0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OWZ => new V3l(0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OWW => new V3l(0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOX => new V3l(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOY => new V3l(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOZ => new V3l(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOW => new V3l(1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIX => new V3l(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIY => new V3l(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIZ => new V3l(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIW => new V3l(1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNX => new V3l(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNY => new V3l(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNZ => new V3l(1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PNW => new V3l(1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXO => new V3l(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXI => new V3l(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PXN => new V3l(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXX => new V3l(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXY => new V3l(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXZ => new V3l(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IXW => new V3l(1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYO => new V3l(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYI => new V3l(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PYN => new V3l(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYX => new V3l(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYY => new V3l(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYZ => new V3l(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IYW => new V3l(1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZO => new V3l(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZI => new V3l(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PZN => new V3l(1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZX => new V3l(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZY => new V3l(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZZ => new V3l(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IZW => new V3l(1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IWO => new V3l(1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IWI => new V3l(1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l PWN => new V3l(1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IWX => new V3l(1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IWY => new V3l(1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IWZ => new V3l(1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IWW => new V3l(1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOX => new V3l(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOY => new V3l(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOZ => new V3l(-1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NOW => new V3l(-1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPX => new V3l(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPY => new V3l(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPZ => new V3l(-1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NPW => new V3l(-1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNX => new V3l(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNY => new V3l(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNZ => new V3l(-1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NNW => new V3l(-1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXO => new V3l(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXP => new V3l(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXN => new V3l(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXX => new V3l(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXY => new V3l(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXZ => new V3l(-1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NXW => new V3l(-1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYO => new V3l(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYP => new V3l(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYN => new V3l(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYX => new V3l(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYY => new V3l(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYZ => new V3l(-1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NYW => new V3l(-1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZO => new V3l(-1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZP => new V3l(-1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZN => new V3l(-1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZX => new V3l(-1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZY => new V3l(-1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZZ => new V3l(-1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NZW => new V3l(-1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NWO => new V3l(-1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NWP => new V3l(-1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NWN => new V3l(-1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NWX => new V3l(-1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NWY => new V3l(-1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NWZ => new V3l(-1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l NWW => new V3l(-1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOO => new V3l(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOI => new V3l(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XON => new V3l(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOX => new V3l(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOY => new V3l(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOZ => new V3l(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XOW => new V3l(X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIO => new V3l(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XII => new V3l(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XPN => new V3l(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIX => new V3l(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIY => new V3l(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIZ => new V3l(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XIW => new V3l(X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNO => new V3l(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNP => new V3l(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNN => new V3l(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNX => new V3l(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNY => new V3l(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNZ => new V3l(X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XNW => new V3l(X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXO => new V3l(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXI => new V3l(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXN => new V3l(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXX => new V3l(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXY => new V3l(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXZ => new V3l(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XXW => new V3l(X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYO => new V3l(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYI => new V3l(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYN => new V3l(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYX => new V3l(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XYY => new V3l(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l XYZ\n        {\n            readonly get => new V3l(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l XYW\n        {\n            readonly get => new V3l(X, Y, W);\n            set { X = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZO => new V3l(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZI => new V3l(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZN => new V3l(X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZX => new V3l(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l XZY\n        {\n            readonly get => new V3l(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XZZ => new V3l(X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l XZW\n        {\n            readonly get => new V3l(X, Z, W);\n            set { X = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XWO => new V3l(X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XWI => new V3l(X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XWN => new V3l(X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XWX => new V3l(X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l XWY\n        {\n            readonly get => new V3l(X, W, Y);\n            set { X = value.X; W = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l XWZ\n        {\n            readonly get => new V3l(X, W, Z);\n            set { X = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l XWW => new V3l(X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOO => new V3l(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOI => new V3l(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YON => new V3l(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOX => new V3l(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOY => new V3l(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOZ => new V3l(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YOW => new V3l(Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIO => new V3l(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YII => new V3l(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YPN => new V3l(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIX => new V3l(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIY => new V3l(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIZ => new V3l(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YIW => new V3l(Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNO => new V3l(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNP => new V3l(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNN => new V3l(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNX => new V3l(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNY => new V3l(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNZ => new V3l(Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YNW => new V3l(Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXO => new V3l(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXI => new V3l(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXN => new V3l(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXX => new V3l(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YXY => new V3l(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l YXZ\n        {\n            readonly get => new V3l(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l YXW\n        {\n            readonly get => new V3l(Y, X, W);\n            set { Y = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYO => new V3l(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYI => new V3l(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYN => new V3l(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYX => new V3l(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYY => new V3l(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYZ => new V3l(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YYW => new V3l(Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZO => new V3l(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZI => new V3l(Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZN => new V3l(Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l YZX\n        {\n            readonly get => new V3l(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZY => new V3l(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YZZ => new V3l(Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l YZW\n        {\n            readonly get => new V3l(Y, Z, W);\n            set { Y = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YWO => new V3l(Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YWI => new V3l(Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YWN => new V3l(Y, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l YWX\n        {\n            readonly get => new V3l(Y, W, X);\n            set { Y = value.X; W = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YWY => new V3l(Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l YWZ\n        {\n            readonly get => new V3l(Y, W, Z);\n            set { Y = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l YWW => new V3l(Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOO => new V3l(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOI => new V3l(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZON => new V3l(Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOX => new V3l(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOY => new V3l(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOZ => new V3l(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZOW => new V3l(Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIO => new V3l(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZII => new V3l(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZPN => new V3l(Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIX => new V3l(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIY => new V3l(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIZ => new V3l(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZIW => new V3l(Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNO => new V3l(Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNP => new V3l(Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNN => new V3l(Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNX => new V3l(Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNY => new V3l(Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNZ => new V3l(Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZNW => new V3l(Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXO => new V3l(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXI => new V3l(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXN => new V3l(Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXX => new V3l(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l ZXY\n        {\n            readonly get => new V3l(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZXZ => new V3l(Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l ZXW\n        {\n            readonly get => new V3l(Z, X, W);\n            set { Z = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYO => new V3l(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYI => new V3l(Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYN => new V3l(Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l ZYX\n        {\n            readonly get => new V3l(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYY => new V3l(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZYZ => new V3l(Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l ZYW\n        {\n            readonly get => new V3l(Z, Y, W);\n            set { Z = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZO => new V3l(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZI => new V3l(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZN => new V3l(Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZX => new V3l(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZY => new V3l(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZZ => new V3l(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZZW => new V3l(Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZWO => new V3l(Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZWI => new V3l(Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZWN => new V3l(Z, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l ZWX\n        {\n            readonly get => new V3l(Z, W, X);\n            set { Z = value.X; W = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l ZWY\n        {\n            readonly get => new V3l(Z, W, Y);\n            set { Z = value.X; W = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZWZ => new V3l(Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l ZWW => new V3l(Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WOO => new V3l(W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WOI => new V3l(W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WON => new V3l(W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WOX => new V3l(W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WOY => new V3l(W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WOZ => new V3l(W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WOW => new V3l(W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WIO => new V3l(W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WII => new V3l(W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WPN => new V3l(W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WIX => new V3l(W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WIY => new V3l(W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WIZ => new V3l(W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WIW => new V3l(W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WNO => new V3l(W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WNP => new V3l(W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WNN => new V3l(W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WNX => new V3l(W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WNY => new V3l(W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WNZ => new V3l(W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WNW => new V3l(W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WXO => new V3l(W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WXI => new V3l(W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WXN => new V3l(W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WXX => new V3l(W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l WXY\n        {\n            readonly get => new V3l(W, X, Y);\n            set { W = value.X; X = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l WXZ\n        {\n            readonly get => new V3l(W, X, Z);\n            set { W = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WXW => new V3l(W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WYO => new V3l(W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WYI => new V3l(W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WYN => new V3l(W, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l WYX\n        {\n            readonly get => new V3l(W, Y, X);\n            set { W = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WYY => new V3l(W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l WYZ\n        {\n            readonly get => new V3l(W, Y, Z);\n            set { W = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WYW => new V3l(W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WZO => new V3l(W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WZI => new V3l(W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WZN => new V3l(W, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l WZX\n        {\n            readonly get => new V3l(W, Z, X);\n            set { W = value.X; Z = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l WZY\n        {\n            readonly get => new V3l(W, Z, Y);\n            set { W = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WZZ => new V3l(W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WZW => new V3l(W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WWO => new V3l(W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WWI => new V3l(W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WWN => new V3l(W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WWX => new V3l(W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WWY => new V3l(W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WWZ => new V3l(W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l WWW => new V3l(W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OOOO => new V4l(0, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OOOI => new V4l(0, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OOON => new V4l(0, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOX => new V4l(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOY => new V4l(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOZ => new V4l(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOW => new V4l(0, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OOIO => new V4l(0, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OOII => new V4l(0, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OOPN => new V4l(0, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIX => new V4l(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIY => new V4l(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIZ => new V4l(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIW => new V4l(0, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OONO => new V4l(0, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OONP => new V4l(0, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OONN => new V4l(0, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONX => new V4l(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONY => new V4l(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONZ => new V4l(0, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OONW => new V4l(0, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXO => new V4l(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXI => new V4l(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXN => new V4l(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXX => new V4l(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXY => new V4l(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXZ => new V4l(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOXW => new V4l(0, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYO => new V4l(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYI => new V4l(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYN => new V4l(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYX => new V4l(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYY => new V4l(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYZ => new V4l(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOYW => new V4l(0, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZO => new V4l(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZI => new V4l(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZN => new V4l(0, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZX => new V4l(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZY => new V4l(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZZ => new V4l(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOZW => new V4l(0, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOWO => new V4l(0, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOWI => new V4l(0, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOWN => new V4l(0, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOWX => new V4l(0, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOWY => new V4l(0, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOWZ => new V4l(0, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOWW => new V4l(0, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OIOO => new V4l(0, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OIOI => new V4l(0, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OPON => new V4l(0, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOX => new V4l(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOY => new V4l(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOZ => new V4l(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOW => new V4l(0, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OIIO => new V4l(0, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OIII => new V4l(0, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OPPN => new V4l(0, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIX => new V4l(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIY => new V4l(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIZ => new V4l(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIW => new V4l(0, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OPNO => new V4l(0, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OPNP => new V4l(0, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l OPNN => new V4l(0, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNX => new V4l(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNY => new V4l(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNZ => new V4l(0, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPNW => new V4l(0, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXO => new V4l(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXI => new V4l(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPXN => new V4l(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXX => new V4l(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXY => new V4l(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXZ => new V4l(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIXW => new V4l(0, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYO => new V4l(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYI => new V4l(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPYN => new V4l(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYX => new V4l(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYY => new V4l(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYZ => new V4l(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIYW => new V4l(0, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZO => new V4l(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZI => new V4l(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPZN => new V4l(0, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZX => new V4l(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZY => new V4l(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZZ => new V4l(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIZW => new V4l(0, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIWO => new V4l(0, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIWI => new V4l(0, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OPWN => new V4l(0, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIWX => new V4l(0, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIWY => new V4l(0, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIWZ => new V4l(0, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIWW => new V4l(0, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONOO => new V4l(0, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONOP => new V4l(0, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONON => new V4l(0, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOX => new V4l(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOY => new V4l(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOZ => new V4l(0, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONOW => new V4l(0, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONPO => new V4l(0, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONPP => new V4l(0, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONPN => new V4l(0, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPX => new V4l(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPY => new V4l(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPZ => new V4l(0, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONPW => new V4l(0, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONNO => new V4l(0, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONNP => new V4l(0, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l ONNN => new V4l(0, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNX => new V4l(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNY => new V4l(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNZ => new V4l(0, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONNW => new V4l(0, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXO => new V4l(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXP => new V4l(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXN => new V4l(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXX => new V4l(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXY => new V4l(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXZ => new V4l(0, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONXW => new V4l(0, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYO => new V4l(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYP => new V4l(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYN => new V4l(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYX => new V4l(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYY => new V4l(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYZ => new V4l(0, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONYW => new V4l(0, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZO => new V4l(0, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZP => new V4l(0, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZN => new V4l(0, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZX => new V4l(0, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZY => new V4l(0, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZZ => new V4l(0, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONZW => new V4l(0, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONWO => new V4l(0, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONWP => new V4l(0, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONWN => new V4l(0, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONWX => new V4l(0, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONWY => new V4l(0, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONWZ => new V4l(0, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ONWW => new V4l(0, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOO => new V4l(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOI => new V4l(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXON => new V4l(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOX => new V4l(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOY => new V4l(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOZ => new V4l(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXOW => new V4l(0, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIO => new V4l(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXII => new V4l(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXPN => new V4l(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIX => new V4l(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIY => new V4l(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIZ => new V4l(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXIW => new V4l(0, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNO => new V4l(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNP => new V4l(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNN => new V4l(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNX => new V4l(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNY => new V4l(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNZ => new V4l(0, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXNW => new V4l(0, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXO => new V4l(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXI => new V4l(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXN => new V4l(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXX => new V4l(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXY => new V4l(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXZ => new V4l(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXXW => new V4l(0, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYO => new V4l(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYI => new V4l(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYN => new V4l(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYX => new V4l(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYY => new V4l(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYZ => new V4l(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXYW => new V4l(0, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZO => new V4l(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZI => new V4l(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZN => new V4l(0, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZX => new V4l(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZY => new V4l(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZZ => new V4l(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXZW => new V4l(0, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXWO => new V4l(0, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXWI => new V4l(0, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXWN => new V4l(0, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXWX => new V4l(0, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXWY => new V4l(0, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXWZ => new V4l(0, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OXWW => new V4l(0, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOO => new V4l(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOI => new V4l(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYON => new V4l(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOX => new V4l(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOY => new V4l(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOZ => new V4l(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYOW => new V4l(0, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIO => new V4l(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYII => new V4l(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYPN => new V4l(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIX => new V4l(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIY => new V4l(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIZ => new V4l(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYIW => new V4l(0, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNO => new V4l(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNP => new V4l(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNN => new V4l(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNX => new V4l(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNY => new V4l(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNZ => new V4l(0, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYNW => new V4l(0, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXO => new V4l(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXI => new V4l(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXN => new V4l(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXX => new V4l(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXY => new V4l(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXZ => new V4l(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYXW => new V4l(0, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYO => new V4l(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYI => new V4l(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYN => new V4l(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYX => new V4l(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYY => new V4l(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYZ => new V4l(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYYW => new V4l(0, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZO => new V4l(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZI => new V4l(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZN => new V4l(0, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZX => new V4l(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZY => new V4l(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZZ => new V4l(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYZW => new V4l(0, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYWO => new V4l(0, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYWI => new V4l(0, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYWN => new V4l(0, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYWX => new V4l(0, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYWY => new V4l(0, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYWZ => new V4l(0, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OYWW => new V4l(0, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOO => new V4l(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOI => new V4l(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZON => new V4l(0, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOX => new V4l(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOY => new V4l(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOZ => new V4l(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZOW => new V4l(0, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIO => new V4l(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZII => new V4l(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZPN => new V4l(0, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIX => new V4l(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIY => new V4l(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIZ => new V4l(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZIW => new V4l(0, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNO => new V4l(0, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNP => new V4l(0, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNN => new V4l(0, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNX => new V4l(0, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNY => new V4l(0, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNZ => new V4l(0, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZNW => new V4l(0, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXO => new V4l(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXI => new V4l(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXN => new V4l(0, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXX => new V4l(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXY => new V4l(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXZ => new V4l(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZXW => new V4l(0, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYO => new V4l(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYI => new V4l(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYN => new V4l(0, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYX => new V4l(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYY => new V4l(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYZ => new V4l(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZYW => new V4l(0, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZO => new V4l(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZI => new V4l(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZN => new V4l(0, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZX => new V4l(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZY => new V4l(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZZ => new V4l(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZZW => new V4l(0, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZWO => new V4l(0, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZWI => new V4l(0, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZWN => new V4l(0, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZWX => new V4l(0, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZWY => new V4l(0, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZWZ => new V4l(0, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OZWW => new V4l(0, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWOO => new V4l(0, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWOI => new V4l(0, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWON => new V4l(0, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWOX => new V4l(0, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWOY => new V4l(0, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWOZ => new V4l(0, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWOW => new V4l(0, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWIO => new V4l(0, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWII => new V4l(0, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWPN => new V4l(0, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWIX => new V4l(0, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWIY => new V4l(0, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWIZ => new V4l(0, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWIW => new V4l(0, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWNO => new V4l(0, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWNP => new V4l(0, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWNN => new V4l(0, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWNX => new V4l(0, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWNY => new V4l(0, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWNZ => new V4l(0, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWNW => new V4l(0, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWXO => new V4l(0, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWXI => new V4l(0, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWXN => new V4l(0, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWXX => new V4l(0, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWXY => new V4l(0, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWXZ => new V4l(0, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWXW => new V4l(0, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWYO => new V4l(0, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWYI => new V4l(0, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWYN => new V4l(0, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWYX => new V4l(0, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWYY => new V4l(0, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWYZ => new V4l(0, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWYW => new V4l(0, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWZO => new V4l(0, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWZI => new V4l(0, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWZN => new V4l(0, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWZX => new V4l(0, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWZY => new V4l(0, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWZZ => new V4l(0, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWZW => new V4l(0, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWWO => new V4l(0, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWWI => new V4l(0, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWWN => new V4l(0, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWWX => new V4l(0, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWWY => new V4l(0, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWWZ => new V4l(0, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OWWW => new V4l(0, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l IOOO => new V4l(1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l IOOI => new V4l(1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l POON => new V4l(1, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOX => new V4l(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOY => new V4l(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOZ => new V4l(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOW => new V4l(1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l IOIO => new V4l(1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l IOII => new V4l(1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l POPN => new V4l(1, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIX => new V4l(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIY => new V4l(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIZ => new V4l(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIW => new V4l(1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PONO => new V4l(1, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PONP => new V4l(1, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PONN => new V4l(1, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONX => new V4l(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONY => new V4l(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONZ => new V4l(1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PONW => new V4l(1, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXO => new V4l(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXI => new V4l(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POXN => new V4l(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXX => new V4l(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXY => new V4l(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXZ => new V4l(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOXW => new V4l(1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYO => new V4l(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYI => new V4l(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POYN => new V4l(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYX => new V4l(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYY => new V4l(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYZ => new V4l(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOYW => new V4l(1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZO => new V4l(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZI => new V4l(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POZN => new V4l(1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZX => new V4l(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZY => new V4l(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZZ => new V4l(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOZW => new V4l(1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOWO => new V4l(1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOWI => new V4l(1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l POWN => new V4l(1, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOWX => new V4l(1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOWY => new V4l(1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOWZ => new V4l(1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOWW => new V4l(1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l IIOO => new V4l(1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l IIOI => new V4l(1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PPON => new V4l(1, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOX => new V4l(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOY => new V4l(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOZ => new V4l(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOW => new V4l(1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l IIIO => new V4l(1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l IIII => new V4l(1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PPPN => new V4l(1, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIX => new V4l(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIY => new V4l(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIZ => new V4l(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIW => new V4l(1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PPNO => new V4l(1, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PPNP => new V4l(1, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PPNN => new V4l(1, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNX => new V4l(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNY => new V4l(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNZ => new V4l(1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPNW => new V4l(1, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXO => new V4l(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXI => new V4l(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPXN => new V4l(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXX => new V4l(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXY => new V4l(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXZ => new V4l(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIXW => new V4l(1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYO => new V4l(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYI => new V4l(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPYN => new V4l(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYX => new V4l(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYY => new V4l(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYZ => new V4l(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIYW => new V4l(1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZO => new V4l(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZI => new V4l(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPZN => new V4l(1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZX => new V4l(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZY => new V4l(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZZ => new V4l(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIZW => new V4l(1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIWO => new V4l(1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIWI => new V4l(1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PPWN => new V4l(1, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIWX => new V4l(1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIWY => new V4l(1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIWZ => new V4l(1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIWW => new V4l(1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNOO => new V4l(1, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNOP => new V4l(1, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNON => new V4l(1, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOX => new V4l(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOY => new V4l(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOZ => new V4l(1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNOW => new V4l(1, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNPO => new V4l(1, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNPP => new V4l(1, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNPN => new V4l(1, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPX => new V4l(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPY => new V4l(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPZ => new V4l(1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNPW => new V4l(1, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNNO => new V4l(1, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNNP => new V4l(1, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l PNNN => new V4l(1, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNX => new V4l(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNY => new V4l(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNZ => new V4l(1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNNW => new V4l(1, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXO => new V4l(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXP => new V4l(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXN => new V4l(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXX => new V4l(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXY => new V4l(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXZ => new V4l(1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNXW => new V4l(1, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYO => new V4l(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYP => new V4l(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYN => new V4l(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYX => new V4l(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYY => new V4l(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYZ => new V4l(1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNYW => new V4l(1, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZO => new V4l(1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZP => new V4l(1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZN => new V4l(1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZX => new V4l(1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZY => new V4l(1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZZ => new V4l(1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNZW => new V4l(1, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNWO => new V4l(1, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNWP => new V4l(1, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNWN => new V4l(1, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNWX => new V4l(1, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNWY => new V4l(1, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNWZ => new V4l(1, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PNWW => new V4l(1, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOO => new V4l(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOI => new V4l(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXON => new V4l(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOX => new V4l(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOY => new V4l(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOZ => new V4l(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXOW => new V4l(1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIO => new V4l(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXII => new V4l(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXPN => new V4l(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIX => new V4l(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIY => new V4l(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIZ => new V4l(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXIW => new V4l(1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNO => new V4l(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNP => new V4l(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNN => new V4l(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNX => new V4l(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNY => new V4l(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNZ => new V4l(1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXNW => new V4l(1, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXO => new V4l(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXI => new V4l(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXXN => new V4l(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXX => new V4l(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXY => new V4l(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXZ => new V4l(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXXW => new V4l(1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYO => new V4l(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYI => new V4l(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXYN => new V4l(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYX => new V4l(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYY => new V4l(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYZ => new V4l(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXYW => new V4l(1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZO => new V4l(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZI => new V4l(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXZN => new V4l(1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZX => new V4l(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZY => new V4l(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZZ => new V4l(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXZW => new V4l(1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXWO => new V4l(1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXWI => new V4l(1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PXWN => new V4l(1, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXWX => new V4l(1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXWY => new V4l(1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXWZ => new V4l(1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IXWW => new V4l(1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOO => new V4l(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOI => new V4l(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYON => new V4l(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOX => new V4l(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOY => new V4l(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOZ => new V4l(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYOW => new V4l(1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIO => new V4l(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYII => new V4l(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYPN => new V4l(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIX => new V4l(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIY => new V4l(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIZ => new V4l(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYIW => new V4l(1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNO => new V4l(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNP => new V4l(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNN => new V4l(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNX => new V4l(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNY => new V4l(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNZ => new V4l(1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYNW => new V4l(1, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXO => new V4l(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXI => new V4l(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYXN => new V4l(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXX => new V4l(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXY => new V4l(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXZ => new V4l(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYXW => new V4l(1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYO => new V4l(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYI => new V4l(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYYN => new V4l(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYX => new V4l(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYY => new V4l(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYZ => new V4l(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYYW => new V4l(1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZO => new V4l(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZI => new V4l(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYZN => new V4l(1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZX => new V4l(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZY => new V4l(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZZ => new V4l(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYZW => new V4l(1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYWO => new V4l(1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYWI => new V4l(1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PYWN => new V4l(1, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYWX => new V4l(1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYWY => new V4l(1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYWZ => new V4l(1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IYWW => new V4l(1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOO => new V4l(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOI => new V4l(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZON => new V4l(1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOX => new V4l(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOY => new V4l(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOZ => new V4l(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZOW => new V4l(1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIO => new V4l(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZII => new V4l(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZPN => new V4l(1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIX => new V4l(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIY => new V4l(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIZ => new V4l(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZIW => new V4l(1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNO => new V4l(1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNP => new V4l(1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNN => new V4l(1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNX => new V4l(1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNY => new V4l(1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNZ => new V4l(1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZNW => new V4l(1, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXO => new V4l(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXI => new V4l(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZXN => new V4l(1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXX => new V4l(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXY => new V4l(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXZ => new V4l(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZXW => new V4l(1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYO => new V4l(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYI => new V4l(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZYN => new V4l(1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYX => new V4l(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYY => new V4l(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYZ => new V4l(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZYW => new V4l(1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZO => new V4l(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZI => new V4l(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZZN => new V4l(1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZX => new V4l(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZY => new V4l(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZZ => new V4l(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZZW => new V4l(1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZWO => new V4l(1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZWI => new V4l(1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PZWN => new V4l(1, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZWX => new V4l(1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZWY => new V4l(1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZWZ => new V4l(1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IZWW => new V4l(1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWOO => new V4l(1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWOI => new V4l(1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWON => new V4l(1, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWOX => new V4l(1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWOY => new V4l(1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWOZ => new V4l(1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWOW => new V4l(1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWIO => new V4l(1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWII => new V4l(1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWPN => new V4l(1, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWIX => new V4l(1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWIY => new V4l(1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWIZ => new V4l(1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWIW => new V4l(1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWNO => new V4l(1, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWNP => new V4l(1, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWNN => new V4l(1, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWNX => new V4l(1, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWNY => new V4l(1, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWNZ => new V4l(1, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWNW => new V4l(1, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWXO => new V4l(1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWXI => new V4l(1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWXN => new V4l(1, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWXX => new V4l(1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWXY => new V4l(1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWXZ => new V4l(1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWXW => new V4l(1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWYO => new V4l(1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWYI => new V4l(1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWYN => new V4l(1, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWYX => new V4l(1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWYY => new V4l(1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWYZ => new V4l(1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWYW => new V4l(1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWZO => new V4l(1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWZI => new V4l(1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWZN => new V4l(1, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWZX => new V4l(1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWZY => new V4l(1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWZZ => new V4l(1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWZW => new V4l(1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWWO => new V4l(1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWWI => new V4l(1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l PWWN => new V4l(1, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWWX => new V4l(1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWWY => new V4l(1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWWZ => new V4l(1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IWWW => new V4l(1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NOOO => new V4l(-1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NOOP => new V4l(-1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NOON => new V4l(-1, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOX => new V4l(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOY => new V4l(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOZ => new V4l(-1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOOW => new V4l(-1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NOPO => new V4l(-1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NOPP => new V4l(-1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NOPN => new V4l(-1, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPX => new V4l(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPY => new V4l(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPZ => new V4l(-1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOPW => new V4l(-1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NONO => new V4l(-1, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NONP => new V4l(-1, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NONN => new V4l(-1, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONX => new V4l(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONY => new V4l(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONZ => new V4l(-1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NONW => new V4l(-1, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXO => new V4l(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXP => new V4l(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXN => new V4l(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXX => new V4l(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXY => new V4l(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXZ => new V4l(-1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOXW => new V4l(-1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYO => new V4l(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYP => new V4l(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYN => new V4l(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYX => new V4l(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYY => new V4l(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYZ => new V4l(-1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOYW => new V4l(-1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZO => new V4l(-1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZP => new V4l(-1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZN => new V4l(-1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZX => new V4l(-1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZY => new V4l(-1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZZ => new V4l(-1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOZW => new V4l(-1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOWO => new V4l(-1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOWP => new V4l(-1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOWN => new V4l(-1, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOWX => new V4l(-1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOWY => new V4l(-1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOWZ => new V4l(-1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NOWW => new V4l(-1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPOO => new V4l(-1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPOP => new V4l(-1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPON => new V4l(-1, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOX => new V4l(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOY => new V4l(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOZ => new V4l(-1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPOW => new V4l(-1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPPO => new V4l(-1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPPP => new V4l(-1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPPN => new V4l(-1, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPX => new V4l(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPY => new V4l(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPZ => new V4l(-1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPPW => new V4l(-1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPNO => new V4l(-1, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPNP => new V4l(-1, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NPNN => new V4l(-1, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNX => new V4l(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNY => new V4l(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNZ => new V4l(-1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPNW => new V4l(-1, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXO => new V4l(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXP => new V4l(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXN => new V4l(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXX => new V4l(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXY => new V4l(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXZ => new V4l(-1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPXW => new V4l(-1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYO => new V4l(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYP => new V4l(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYN => new V4l(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYX => new V4l(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYY => new V4l(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYZ => new V4l(-1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPYW => new V4l(-1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZO => new V4l(-1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZP => new V4l(-1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZN => new V4l(-1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZX => new V4l(-1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZY => new V4l(-1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZZ => new V4l(-1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPZW => new V4l(-1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPWO => new V4l(-1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPWP => new V4l(-1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPWN => new V4l(-1, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPWX => new V4l(-1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPWY => new V4l(-1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPWZ => new V4l(-1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NPWW => new V4l(-1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNOO => new V4l(-1, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNOP => new V4l(-1, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNON => new V4l(-1, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOX => new V4l(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOY => new V4l(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOZ => new V4l(-1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNOW => new V4l(-1, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNPO => new V4l(-1, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNPP => new V4l(-1, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNPN => new V4l(-1, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPX => new V4l(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPY => new V4l(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPZ => new V4l(-1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNPW => new V4l(-1, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNNO => new V4l(-1, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNNP => new V4l(-1, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4l NNNN => new V4l(-1, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNX => new V4l(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNY => new V4l(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNZ => new V4l(-1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNNW => new V4l(-1, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXO => new V4l(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXP => new V4l(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXN => new V4l(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXX => new V4l(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXY => new V4l(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXZ => new V4l(-1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNXW => new V4l(-1, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYO => new V4l(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYP => new V4l(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYN => new V4l(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYX => new V4l(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYY => new V4l(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYZ => new V4l(-1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNYW => new V4l(-1, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZO => new V4l(-1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZP => new V4l(-1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZN => new V4l(-1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZX => new V4l(-1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZY => new V4l(-1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZZ => new V4l(-1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNZW => new V4l(-1, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNWO => new V4l(-1, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNWP => new V4l(-1, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNWN => new V4l(-1, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNWX => new V4l(-1, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNWY => new V4l(-1, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNWZ => new V4l(-1, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NNWW => new V4l(-1, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOO => new V4l(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOP => new V4l(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXON => new V4l(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOX => new V4l(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOY => new V4l(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOZ => new V4l(-1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXOW => new V4l(-1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPO => new V4l(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPP => new V4l(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPN => new V4l(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPX => new V4l(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPY => new V4l(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPZ => new V4l(-1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXPW => new V4l(-1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNO => new V4l(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNP => new V4l(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNN => new V4l(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNX => new V4l(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNY => new V4l(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNZ => new V4l(-1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXNW => new V4l(-1, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXO => new V4l(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXP => new V4l(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXN => new V4l(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXX => new V4l(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXY => new V4l(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXZ => new V4l(-1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXXW => new V4l(-1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYO => new V4l(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYP => new V4l(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYN => new V4l(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYX => new V4l(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYY => new V4l(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYZ => new V4l(-1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXYW => new V4l(-1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZO => new V4l(-1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZP => new V4l(-1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZN => new V4l(-1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZX => new V4l(-1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZY => new V4l(-1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZZ => new V4l(-1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXZW => new V4l(-1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXWO => new V4l(-1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXWP => new V4l(-1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXWN => new V4l(-1, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXWX => new V4l(-1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXWY => new V4l(-1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXWZ => new V4l(-1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NXWW => new V4l(-1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOO => new V4l(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOP => new V4l(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYON => new V4l(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOX => new V4l(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOY => new V4l(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOZ => new V4l(-1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYOW => new V4l(-1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPO => new V4l(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPP => new V4l(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPN => new V4l(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPX => new V4l(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPY => new V4l(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPZ => new V4l(-1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYPW => new V4l(-1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNO => new V4l(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNP => new V4l(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNN => new V4l(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNX => new V4l(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNY => new V4l(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNZ => new V4l(-1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYNW => new V4l(-1, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXO => new V4l(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXP => new V4l(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXN => new V4l(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXX => new V4l(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXY => new V4l(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXZ => new V4l(-1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYXW => new V4l(-1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYO => new V4l(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYP => new V4l(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYN => new V4l(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYX => new V4l(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYY => new V4l(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYZ => new V4l(-1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYYW => new V4l(-1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZO => new V4l(-1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZP => new V4l(-1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZN => new V4l(-1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZX => new V4l(-1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZY => new V4l(-1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZZ => new V4l(-1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYZW => new V4l(-1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYWO => new V4l(-1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYWP => new V4l(-1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYWN => new V4l(-1, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYWX => new V4l(-1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYWY => new V4l(-1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYWZ => new V4l(-1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NYWW => new V4l(-1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOO => new V4l(-1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOP => new V4l(-1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZON => new V4l(-1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOX => new V4l(-1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOY => new V4l(-1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOZ => new V4l(-1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZOW => new V4l(-1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPO => new V4l(-1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPP => new V4l(-1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPN => new V4l(-1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPX => new V4l(-1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPY => new V4l(-1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPZ => new V4l(-1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZPW => new V4l(-1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNO => new V4l(-1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNP => new V4l(-1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNN => new V4l(-1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNX => new V4l(-1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNY => new V4l(-1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNZ => new V4l(-1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZNW => new V4l(-1, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXO => new V4l(-1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXP => new V4l(-1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXN => new V4l(-1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXX => new V4l(-1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXY => new V4l(-1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXZ => new V4l(-1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZXW => new V4l(-1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYO => new V4l(-1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYP => new V4l(-1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYN => new V4l(-1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYX => new V4l(-1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYY => new V4l(-1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYZ => new V4l(-1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZYW => new V4l(-1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZO => new V4l(-1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZP => new V4l(-1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZN => new V4l(-1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZX => new V4l(-1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZY => new V4l(-1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZZ => new V4l(-1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZZW => new V4l(-1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZWO => new V4l(-1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZWP => new V4l(-1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZWN => new V4l(-1, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZWX => new V4l(-1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZWY => new V4l(-1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZWZ => new V4l(-1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NZWW => new V4l(-1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWOO => new V4l(-1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWOP => new V4l(-1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWON => new V4l(-1, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWOX => new V4l(-1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWOY => new V4l(-1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWOZ => new V4l(-1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWOW => new V4l(-1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWPO => new V4l(-1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWPP => new V4l(-1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWPN => new V4l(-1, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWPX => new V4l(-1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWPY => new V4l(-1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWPZ => new V4l(-1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWPW => new V4l(-1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWNO => new V4l(-1, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWNP => new V4l(-1, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWNN => new V4l(-1, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWNX => new V4l(-1, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWNY => new V4l(-1, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWNZ => new V4l(-1, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWNW => new V4l(-1, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWXO => new V4l(-1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWXP => new V4l(-1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWXN => new V4l(-1, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWXX => new V4l(-1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWXY => new V4l(-1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWXZ => new V4l(-1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWXW => new V4l(-1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWYO => new V4l(-1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWYP => new V4l(-1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWYN => new V4l(-1, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWYX => new V4l(-1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWYY => new V4l(-1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWYZ => new V4l(-1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWYW => new V4l(-1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWZO => new V4l(-1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWZP => new V4l(-1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWZN => new V4l(-1, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWZX => new V4l(-1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWZY => new V4l(-1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWZZ => new V4l(-1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWZW => new V4l(-1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWWO => new V4l(-1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWWP => new V4l(-1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWWN => new V4l(-1, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWWX => new V4l(-1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWWY => new V4l(-1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWWZ => new V4l(-1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l NWWW => new V4l(-1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOO => new V4l(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOI => new V4l(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOON => new V4l(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOX => new V4l(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOY => new V4l(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOZ => new V4l(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOOW => new V4l(X, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIO => new V4l(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOII => new V4l(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOPN => new V4l(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIX => new V4l(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIY => new V4l(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIZ => new V4l(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOIW => new V4l(X, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONO => new V4l(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONP => new V4l(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONN => new V4l(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONX => new V4l(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONY => new V4l(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONZ => new V4l(X, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XONW => new V4l(X, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXO => new V4l(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXI => new V4l(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXN => new V4l(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXX => new V4l(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXY => new V4l(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXZ => new V4l(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOXW => new V4l(X, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYO => new V4l(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYI => new V4l(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYN => new V4l(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYX => new V4l(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYY => new V4l(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYZ => new V4l(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOYW => new V4l(X, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZO => new V4l(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZI => new V4l(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZN => new V4l(X, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZX => new V4l(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZY => new V4l(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZZ => new V4l(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOZW => new V4l(X, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOWO => new V4l(X, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOWI => new V4l(X, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOWN => new V4l(X, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOWX => new V4l(X, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOWY => new V4l(X, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOWZ => new V4l(X, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XOWW => new V4l(X, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOO => new V4l(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOI => new V4l(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPON => new V4l(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOX => new V4l(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOY => new V4l(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOZ => new V4l(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIOW => new V4l(X, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIO => new V4l(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIII => new V4l(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPPN => new V4l(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIX => new V4l(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIY => new V4l(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIZ => new V4l(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIIW => new V4l(X, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNO => new V4l(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNP => new V4l(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNN => new V4l(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNX => new V4l(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNY => new V4l(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNZ => new V4l(X, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPNW => new V4l(X, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXO => new V4l(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXI => new V4l(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPXN => new V4l(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXX => new V4l(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXY => new V4l(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXZ => new V4l(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIXW => new V4l(X, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYO => new V4l(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYI => new V4l(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPYN => new V4l(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYX => new V4l(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYY => new V4l(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYZ => new V4l(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIYW => new V4l(X, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZO => new V4l(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZI => new V4l(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPZN => new V4l(X, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZX => new V4l(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZY => new V4l(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZZ => new V4l(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIZW => new V4l(X, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIWO => new V4l(X, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIWI => new V4l(X, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XPWN => new V4l(X, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIWX => new V4l(X, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIWY => new V4l(X, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIWZ => new V4l(X, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XIWW => new V4l(X, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOO => new V4l(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOP => new V4l(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNON => new V4l(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOX => new V4l(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOY => new V4l(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOZ => new V4l(X, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNOW => new V4l(X, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPO => new V4l(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPP => new V4l(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPN => new V4l(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPX => new V4l(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPY => new V4l(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPZ => new V4l(X, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNPW => new V4l(X, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNO => new V4l(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNP => new V4l(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNN => new V4l(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNX => new V4l(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNY => new V4l(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNZ => new V4l(X, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNNW => new V4l(X, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXO => new V4l(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXP => new V4l(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXN => new V4l(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXX => new V4l(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXY => new V4l(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXZ => new V4l(X, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNXW => new V4l(X, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYO => new V4l(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYP => new V4l(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYN => new V4l(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYX => new V4l(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYY => new V4l(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYZ => new V4l(X, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNYW => new V4l(X, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZO => new V4l(X, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZP => new V4l(X, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZN => new V4l(X, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZX => new V4l(X, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZY => new V4l(X, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZZ => new V4l(X, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNZW => new V4l(X, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNWO => new V4l(X, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNWP => new V4l(X, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNWN => new V4l(X, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNWX => new V4l(X, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNWY => new V4l(X, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNWZ => new V4l(X, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XNWW => new V4l(X, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOO => new V4l(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOI => new V4l(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXON => new V4l(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOX => new V4l(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOY => new V4l(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOZ => new V4l(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXOW => new V4l(X, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIO => new V4l(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXII => new V4l(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXPN => new V4l(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIX => new V4l(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIY => new V4l(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIZ => new V4l(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXIW => new V4l(X, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNO => new V4l(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNP => new V4l(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNN => new V4l(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNX => new V4l(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNY => new V4l(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNZ => new V4l(X, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXNW => new V4l(X, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXO => new V4l(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXI => new V4l(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXN => new V4l(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXX => new V4l(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXY => new V4l(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXZ => new V4l(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXXW => new V4l(X, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYO => new V4l(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYI => new V4l(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYN => new V4l(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYX => new V4l(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYY => new V4l(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYZ => new V4l(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXYW => new V4l(X, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZO => new V4l(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZI => new V4l(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZN => new V4l(X, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZX => new V4l(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZY => new V4l(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZZ => new V4l(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXZW => new V4l(X, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXWO => new V4l(X, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXWI => new V4l(X, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXWN => new V4l(X, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXWX => new V4l(X, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXWY => new V4l(X, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXWZ => new V4l(X, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XXWW => new V4l(X, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOO => new V4l(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOI => new V4l(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYON => new V4l(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOX => new V4l(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOY => new V4l(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOZ => new V4l(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYOW => new V4l(X, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIO => new V4l(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYII => new V4l(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYPN => new V4l(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIX => new V4l(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIY => new V4l(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIZ => new V4l(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYIW => new V4l(X, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNO => new V4l(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNP => new V4l(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNN => new V4l(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNX => new V4l(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNY => new V4l(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNZ => new V4l(X, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYNW => new V4l(X, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXO => new V4l(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXI => new V4l(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXN => new V4l(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXX => new V4l(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXY => new V4l(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXZ => new V4l(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYXW => new V4l(X, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYO => new V4l(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYI => new V4l(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYN => new V4l(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYX => new V4l(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYY => new V4l(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYZ => new V4l(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYYW => new V4l(X, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZO => new V4l(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZI => new V4l(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZN => new V4l(X, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZX => new V4l(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZY => new V4l(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYZZ => new V4l(X, Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l XYZW\n        {\n            readonly get => new V4l(X, Y, Z, W);\n            set { X = value.X; Y = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYWO => new V4l(X, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYWI => new V4l(X, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYWN => new V4l(X, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYWX => new V4l(X, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYWY => new V4l(X, Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l XYWZ\n        {\n            readonly get => new V4l(X, Y, W, Z);\n            set { X = value.X; Y = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XYWW => new V4l(X, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOO => new V4l(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOI => new V4l(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZON => new V4l(X, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOX => new V4l(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOY => new V4l(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOZ => new V4l(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZOW => new V4l(X, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIO => new V4l(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZII => new V4l(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZPN => new V4l(X, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIX => new V4l(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIY => new V4l(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIZ => new V4l(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZIW => new V4l(X, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNO => new V4l(X, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNP => new V4l(X, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNN => new V4l(X, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNX => new V4l(X, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNY => new V4l(X, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNZ => new V4l(X, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZNW => new V4l(X, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXO => new V4l(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXI => new V4l(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXN => new V4l(X, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXX => new V4l(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXY => new V4l(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXZ => new V4l(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZXW => new V4l(X, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYO => new V4l(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYI => new V4l(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYN => new V4l(X, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYX => new V4l(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYY => new V4l(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZYZ => new V4l(X, Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l XZYW\n        {\n            readonly get => new V4l(X, Z, Y, W);\n            set { X = value.X; Z = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZO => new V4l(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZI => new V4l(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZN => new V4l(X, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZX => new V4l(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZY => new V4l(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZZ => new V4l(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZZW => new V4l(X, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZWO => new V4l(X, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZWI => new V4l(X, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZWN => new V4l(X, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZWX => new V4l(X, Z, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l XZWY\n        {\n            readonly get => new V4l(X, Z, W, Y);\n            set { X = value.X; Z = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZWZ => new V4l(X, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XZWW => new V4l(X, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWOO => new V4l(X, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWOI => new V4l(X, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWON => new V4l(X, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWOX => new V4l(X, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWOY => new V4l(X, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWOZ => new V4l(X, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWOW => new V4l(X, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWIO => new V4l(X, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWII => new V4l(X, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWPN => new V4l(X, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWIX => new V4l(X, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWIY => new V4l(X, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWIZ => new V4l(X, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWIW => new V4l(X, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWNO => new V4l(X, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWNP => new V4l(X, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWNN => new V4l(X, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWNX => new V4l(X, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWNY => new V4l(X, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWNZ => new V4l(X, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWNW => new V4l(X, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWXO => new V4l(X, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWXI => new V4l(X, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWXN => new V4l(X, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWXX => new V4l(X, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWXY => new V4l(X, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWXZ => new V4l(X, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWXW => new V4l(X, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWYO => new V4l(X, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWYI => new V4l(X, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWYN => new V4l(X, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWYX => new V4l(X, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWYY => new V4l(X, W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l XWYZ\n        {\n            readonly get => new V4l(X, W, Y, Z);\n            set { X = value.X; W = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWYW => new V4l(X, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWZO => new V4l(X, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWZI => new V4l(X, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWZN => new V4l(X, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWZX => new V4l(X, W, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l XWZY\n        {\n            readonly get => new V4l(X, W, Z, Y);\n            set { X = value.X; W = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWZZ => new V4l(X, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWZW => new V4l(X, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWWO => new V4l(X, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWWI => new V4l(X, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWWN => new V4l(X, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWWX => new V4l(X, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWWY => new V4l(X, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWWZ => new V4l(X, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l XWWW => new V4l(X, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOO => new V4l(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOI => new V4l(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOON => new V4l(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOX => new V4l(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOY => new V4l(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOZ => new V4l(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOOW => new V4l(Y, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIO => new V4l(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOII => new V4l(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOPN => new V4l(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIX => new V4l(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIY => new V4l(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIZ => new V4l(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOIW => new V4l(Y, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONO => new V4l(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONP => new V4l(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONN => new V4l(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONX => new V4l(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONY => new V4l(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONZ => new V4l(Y, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YONW => new V4l(Y, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXO => new V4l(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXI => new V4l(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXN => new V4l(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXX => new V4l(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXY => new V4l(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXZ => new V4l(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOXW => new V4l(Y, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYO => new V4l(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYI => new V4l(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYN => new V4l(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYX => new V4l(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYY => new V4l(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYZ => new V4l(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOYW => new V4l(Y, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZO => new V4l(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZI => new V4l(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZN => new V4l(Y, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZX => new V4l(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZY => new V4l(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZZ => new V4l(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOZW => new V4l(Y, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOWO => new V4l(Y, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOWI => new V4l(Y, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOWN => new V4l(Y, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOWX => new V4l(Y, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOWY => new V4l(Y, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOWZ => new V4l(Y, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YOWW => new V4l(Y, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOO => new V4l(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOI => new V4l(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPON => new V4l(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOX => new V4l(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOY => new V4l(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOZ => new V4l(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIOW => new V4l(Y, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIO => new V4l(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIII => new V4l(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPPN => new V4l(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIX => new V4l(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIY => new V4l(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIZ => new V4l(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIIW => new V4l(Y, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNO => new V4l(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNP => new V4l(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNN => new V4l(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNX => new V4l(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNY => new V4l(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNZ => new V4l(Y, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPNW => new V4l(Y, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXO => new V4l(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXI => new V4l(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPXN => new V4l(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXX => new V4l(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXY => new V4l(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXZ => new V4l(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIXW => new V4l(Y, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYO => new V4l(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYI => new V4l(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPYN => new V4l(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYX => new V4l(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYY => new V4l(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYZ => new V4l(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIYW => new V4l(Y, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZO => new V4l(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZI => new V4l(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPZN => new V4l(Y, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZX => new V4l(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZY => new V4l(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZZ => new V4l(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIZW => new V4l(Y, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIWO => new V4l(Y, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIWI => new V4l(Y, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YPWN => new V4l(Y, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIWX => new V4l(Y, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIWY => new V4l(Y, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIWZ => new V4l(Y, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YIWW => new V4l(Y, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOO => new V4l(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOP => new V4l(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNON => new V4l(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOX => new V4l(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOY => new V4l(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOZ => new V4l(Y, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNOW => new V4l(Y, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPO => new V4l(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPP => new V4l(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPN => new V4l(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPX => new V4l(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPY => new V4l(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPZ => new V4l(Y, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNPW => new V4l(Y, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNO => new V4l(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNP => new V4l(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNN => new V4l(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNX => new V4l(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNY => new V4l(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNZ => new V4l(Y, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNNW => new V4l(Y, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXO => new V4l(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXP => new V4l(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXN => new V4l(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXX => new V4l(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXY => new V4l(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXZ => new V4l(Y, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNXW => new V4l(Y, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYO => new V4l(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYP => new V4l(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYN => new V4l(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYX => new V4l(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYY => new V4l(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYZ => new V4l(Y, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNYW => new V4l(Y, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZO => new V4l(Y, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZP => new V4l(Y, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZN => new V4l(Y, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZX => new V4l(Y, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZY => new V4l(Y, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZZ => new V4l(Y, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNZW => new V4l(Y, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNWO => new V4l(Y, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNWP => new V4l(Y, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNWN => new V4l(Y, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNWX => new V4l(Y, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNWY => new V4l(Y, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNWZ => new V4l(Y, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YNWW => new V4l(Y, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOO => new V4l(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOI => new V4l(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXON => new V4l(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOX => new V4l(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOY => new V4l(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOZ => new V4l(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXOW => new V4l(Y, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIO => new V4l(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXII => new V4l(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXPN => new V4l(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIX => new V4l(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIY => new V4l(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIZ => new V4l(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXIW => new V4l(Y, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNO => new V4l(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNP => new V4l(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNN => new V4l(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNX => new V4l(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNY => new V4l(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNZ => new V4l(Y, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXNW => new V4l(Y, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXO => new V4l(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXI => new V4l(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXN => new V4l(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXX => new V4l(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXY => new V4l(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXZ => new V4l(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXXW => new V4l(Y, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYO => new V4l(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYI => new V4l(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYN => new V4l(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYX => new V4l(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYY => new V4l(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYZ => new V4l(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXYW => new V4l(Y, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZO => new V4l(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZI => new V4l(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZN => new V4l(Y, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZX => new V4l(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZY => new V4l(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXZZ => new V4l(Y, X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l YXZW\n        {\n            readonly get => new V4l(Y, X, Z, W);\n            set { Y = value.X; X = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXWO => new V4l(Y, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXWI => new V4l(Y, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXWN => new V4l(Y, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXWX => new V4l(Y, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXWY => new V4l(Y, X, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l YXWZ\n        {\n            readonly get => new V4l(Y, X, W, Z);\n            set { Y = value.X; X = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YXWW => new V4l(Y, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOO => new V4l(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOI => new V4l(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYON => new V4l(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOX => new V4l(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOY => new V4l(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOZ => new V4l(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYOW => new V4l(Y, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIO => new V4l(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYII => new V4l(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYPN => new V4l(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIX => new V4l(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIY => new V4l(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIZ => new V4l(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYIW => new V4l(Y, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNO => new V4l(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNP => new V4l(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNN => new V4l(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNX => new V4l(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNY => new V4l(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNZ => new V4l(Y, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYNW => new V4l(Y, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXO => new V4l(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXI => new V4l(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXN => new V4l(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXX => new V4l(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXY => new V4l(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXZ => new V4l(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYXW => new V4l(Y, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYO => new V4l(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYI => new V4l(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYN => new V4l(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYX => new V4l(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYY => new V4l(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYZ => new V4l(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYYW => new V4l(Y, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZO => new V4l(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZI => new V4l(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZN => new V4l(Y, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZX => new V4l(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZY => new V4l(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZZ => new V4l(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYZW => new V4l(Y, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYWO => new V4l(Y, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYWI => new V4l(Y, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYWN => new V4l(Y, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYWX => new V4l(Y, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYWY => new V4l(Y, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYWZ => new V4l(Y, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YYWW => new V4l(Y, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOO => new V4l(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOI => new V4l(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZON => new V4l(Y, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOX => new V4l(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOY => new V4l(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOZ => new V4l(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZOW => new V4l(Y, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIO => new V4l(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZII => new V4l(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZPN => new V4l(Y, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIX => new V4l(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIY => new V4l(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIZ => new V4l(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZIW => new V4l(Y, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNO => new V4l(Y, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNP => new V4l(Y, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNN => new V4l(Y, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNX => new V4l(Y, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNY => new V4l(Y, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNZ => new V4l(Y, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZNW => new V4l(Y, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXO => new V4l(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXI => new V4l(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXN => new V4l(Y, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXX => new V4l(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXY => new V4l(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZXZ => new V4l(Y, Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l YZXW\n        {\n            readonly get => new V4l(Y, Z, X, W);\n            set { Y = value.X; Z = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYO => new V4l(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYI => new V4l(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYN => new V4l(Y, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYX => new V4l(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYY => new V4l(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYZ => new V4l(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZYW => new V4l(Y, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZO => new V4l(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZI => new V4l(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZN => new V4l(Y, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZX => new V4l(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZY => new V4l(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZZ => new V4l(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZZW => new V4l(Y, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZWO => new V4l(Y, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZWI => new V4l(Y, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZWN => new V4l(Y, Z, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l YZWX\n        {\n            readonly get => new V4l(Y, Z, W, X);\n            set { Y = value.X; Z = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZWY => new V4l(Y, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZWZ => new V4l(Y, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YZWW => new V4l(Y, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWOO => new V4l(Y, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWOI => new V4l(Y, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWON => new V4l(Y, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWOX => new V4l(Y, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWOY => new V4l(Y, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWOZ => new V4l(Y, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWOW => new V4l(Y, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWIO => new V4l(Y, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWII => new V4l(Y, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWPN => new V4l(Y, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWIX => new V4l(Y, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWIY => new V4l(Y, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWIZ => new V4l(Y, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWIW => new V4l(Y, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWNO => new V4l(Y, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWNP => new V4l(Y, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWNN => new V4l(Y, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWNX => new V4l(Y, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWNY => new V4l(Y, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWNZ => new V4l(Y, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWNW => new V4l(Y, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWXO => new V4l(Y, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWXI => new V4l(Y, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWXN => new V4l(Y, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWXX => new V4l(Y, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWXY => new V4l(Y, W, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l YWXZ\n        {\n            readonly get => new V4l(Y, W, X, Z);\n            set { Y = value.X; W = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWXW => new V4l(Y, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWYO => new V4l(Y, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWYI => new V4l(Y, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWYN => new V4l(Y, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWYX => new V4l(Y, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWYY => new V4l(Y, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWYZ => new V4l(Y, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWYW => new V4l(Y, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWZO => new V4l(Y, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWZI => new V4l(Y, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWZN => new V4l(Y, W, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l YWZX\n        {\n            readonly get => new V4l(Y, W, Z, X);\n            set { Y = value.X; W = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWZY => new V4l(Y, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWZZ => new V4l(Y, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWZW => new V4l(Y, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWWO => new V4l(Y, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWWI => new V4l(Y, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWWN => new V4l(Y, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWWX => new V4l(Y, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWWY => new V4l(Y, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWWZ => new V4l(Y, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l YWWW => new V4l(Y, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOO => new V4l(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOI => new V4l(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOON => new V4l(Z, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOX => new V4l(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOY => new V4l(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOZ => new V4l(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOOW => new V4l(Z, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIO => new V4l(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOII => new V4l(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOPN => new V4l(Z, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIX => new V4l(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIY => new V4l(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIZ => new V4l(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOIW => new V4l(Z, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONO => new V4l(Z, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONP => new V4l(Z, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONN => new V4l(Z, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONX => new V4l(Z, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONY => new V4l(Z, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONZ => new V4l(Z, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZONW => new V4l(Z, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXO => new V4l(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXI => new V4l(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXN => new V4l(Z, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXX => new V4l(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXY => new V4l(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXZ => new V4l(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOXW => new V4l(Z, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYO => new V4l(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYI => new V4l(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYN => new V4l(Z, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYX => new V4l(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYY => new V4l(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYZ => new V4l(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOYW => new V4l(Z, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZO => new V4l(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZI => new V4l(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZN => new V4l(Z, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZX => new V4l(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZY => new V4l(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZZ => new V4l(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOZW => new V4l(Z, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOWO => new V4l(Z, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOWI => new V4l(Z, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOWN => new V4l(Z, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOWX => new V4l(Z, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOWY => new V4l(Z, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOWZ => new V4l(Z, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZOWW => new V4l(Z, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOO => new V4l(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOI => new V4l(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPON => new V4l(Z, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOX => new V4l(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOY => new V4l(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOZ => new V4l(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIOW => new V4l(Z, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIO => new V4l(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIII => new V4l(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPPN => new V4l(Z, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIX => new V4l(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIY => new V4l(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIZ => new V4l(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIIW => new V4l(Z, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNO => new V4l(Z, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNP => new V4l(Z, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNN => new V4l(Z, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNX => new V4l(Z, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNY => new V4l(Z, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNZ => new V4l(Z, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPNW => new V4l(Z, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXO => new V4l(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXI => new V4l(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPXN => new V4l(Z, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXX => new V4l(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXY => new V4l(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXZ => new V4l(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIXW => new V4l(Z, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYO => new V4l(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYI => new V4l(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPYN => new V4l(Z, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYX => new V4l(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYY => new V4l(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYZ => new V4l(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIYW => new V4l(Z, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZO => new V4l(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZI => new V4l(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPZN => new V4l(Z, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZX => new V4l(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZY => new V4l(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZZ => new V4l(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIZW => new V4l(Z, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIWO => new V4l(Z, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIWI => new V4l(Z, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZPWN => new V4l(Z, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIWX => new V4l(Z, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIWY => new V4l(Z, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIWZ => new V4l(Z, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZIWW => new V4l(Z, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOO => new V4l(Z, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOP => new V4l(Z, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNON => new V4l(Z, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOX => new V4l(Z, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOY => new V4l(Z, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOZ => new V4l(Z, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNOW => new V4l(Z, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPO => new V4l(Z, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPP => new V4l(Z, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPN => new V4l(Z, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPX => new V4l(Z, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPY => new V4l(Z, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPZ => new V4l(Z, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNPW => new V4l(Z, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNO => new V4l(Z, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNP => new V4l(Z, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNN => new V4l(Z, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNX => new V4l(Z, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNY => new V4l(Z, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNZ => new V4l(Z, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNNW => new V4l(Z, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXO => new V4l(Z, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXP => new V4l(Z, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXN => new V4l(Z, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXX => new V4l(Z, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXY => new V4l(Z, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXZ => new V4l(Z, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNXW => new V4l(Z, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYO => new V4l(Z, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYP => new V4l(Z, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYN => new V4l(Z, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYX => new V4l(Z, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYY => new V4l(Z, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYZ => new V4l(Z, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNYW => new V4l(Z, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZO => new V4l(Z, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZP => new V4l(Z, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZN => new V4l(Z, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZX => new V4l(Z, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZY => new V4l(Z, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZZ => new V4l(Z, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNZW => new V4l(Z, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNWO => new V4l(Z, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNWP => new V4l(Z, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNWN => new V4l(Z, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNWX => new V4l(Z, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNWY => new V4l(Z, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNWZ => new V4l(Z, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZNWW => new V4l(Z, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOO => new V4l(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOI => new V4l(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXON => new V4l(Z, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOX => new V4l(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOY => new V4l(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOZ => new V4l(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXOW => new V4l(Z, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIO => new V4l(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXII => new V4l(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXPN => new V4l(Z, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIX => new V4l(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIY => new V4l(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIZ => new V4l(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXIW => new V4l(Z, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNO => new V4l(Z, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNP => new V4l(Z, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNN => new V4l(Z, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNX => new V4l(Z, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNY => new V4l(Z, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNZ => new V4l(Z, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXNW => new V4l(Z, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXO => new V4l(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXI => new V4l(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXN => new V4l(Z, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXX => new V4l(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXY => new V4l(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXZ => new V4l(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXXW => new V4l(Z, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYO => new V4l(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYI => new V4l(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYN => new V4l(Z, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYX => new V4l(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYY => new V4l(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXYZ => new V4l(Z, X, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l ZXYW\n        {\n            readonly get => new V4l(Z, X, Y, W);\n            set { Z = value.X; X = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZO => new V4l(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZI => new V4l(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZN => new V4l(Z, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZX => new V4l(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZY => new V4l(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZZ => new V4l(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXZW => new V4l(Z, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXWO => new V4l(Z, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXWI => new V4l(Z, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXWN => new V4l(Z, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXWX => new V4l(Z, X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l ZXWY\n        {\n            readonly get => new V4l(Z, X, W, Y);\n            set { Z = value.X; X = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXWZ => new V4l(Z, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZXWW => new V4l(Z, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOO => new V4l(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOI => new V4l(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYON => new V4l(Z, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOX => new V4l(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOY => new V4l(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOZ => new V4l(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYOW => new V4l(Z, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIO => new V4l(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYII => new V4l(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYPN => new V4l(Z, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIX => new V4l(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIY => new V4l(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIZ => new V4l(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYIW => new V4l(Z, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNO => new V4l(Z, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNP => new V4l(Z, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNN => new V4l(Z, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNX => new V4l(Z, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNY => new V4l(Z, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNZ => new V4l(Z, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYNW => new V4l(Z, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXO => new V4l(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXI => new V4l(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXN => new V4l(Z, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXX => new V4l(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXY => new V4l(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYXZ => new V4l(Z, Y, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l ZYXW\n        {\n            readonly get => new V4l(Z, Y, X, W);\n            set { Z = value.X; Y = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYO => new V4l(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYI => new V4l(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYN => new V4l(Z, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYX => new V4l(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYY => new V4l(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYZ => new V4l(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYYW => new V4l(Z, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZO => new V4l(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZI => new V4l(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZN => new V4l(Z, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZX => new V4l(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZY => new V4l(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZZ => new V4l(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYZW => new V4l(Z, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYWO => new V4l(Z, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYWI => new V4l(Z, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYWN => new V4l(Z, Y, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l ZYWX\n        {\n            readonly get => new V4l(Z, Y, W, X);\n            set { Z = value.X; Y = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYWY => new V4l(Z, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYWZ => new V4l(Z, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZYWW => new V4l(Z, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOO => new V4l(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOI => new V4l(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZON => new V4l(Z, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOX => new V4l(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOY => new V4l(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOZ => new V4l(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZOW => new V4l(Z, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIO => new V4l(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZII => new V4l(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZPN => new V4l(Z, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIX => new V4l(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIY => new V4l(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIZ => new V4l(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZIW => new V4l(Z, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNO => new V4l(Z, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNP => new V4l(Z, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNN => new V4l(Z, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNX => new V4l(Z, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNY => new V4l(Z, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNZ => new V4l(Z, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZNW => new V4l(Z, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXO => new V4l(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXI => new V4l(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXN => new V4l(Z, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXX => new V4l(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXY => new V4l(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXZ => new V4l(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZXW => new V4l(Z, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYO => new V4l(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYI => new V4l(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYN => new V4l(Z, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYX => new V4l(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYY => new V4l(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYZ => new V4l(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZYW => new V4l(Z, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZO => new V4l(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZI => new V4l(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZN => new V4l(Z, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZX => new V4l(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZY => new V4l(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZZ => new V4l(Z, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZZW => new V4l(Z, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZWO => new V4l(Z, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZWI => new V4l(Z, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZWN => new V4l(Z, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZWX => new V4l(Z, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZWY => new V4l(Z, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZWZ => new V4l(Z, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZZWW => new V4l(Z, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWOO => new V4l(Z, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWOI => new V4l(Z, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWON => new V4l(Z, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWOX => new V4l(Z, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWOY => new V4l(Z, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWOZ => new V4l(Z, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWOW => new V4l(Z, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWIO => new V4l(Z, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWII => new V4l(Z, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWPN => new V4l(Z, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWIX => new V4l(Z, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWIY => new V4l(Z, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWIZ => new V4l(Z, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWIW => new V4l(Z, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWNO => new V4l(Z, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWNP => new V4l(Z, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWNN => new V4l(Z, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWNX => new V4l(Z, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWNY => new V4l(Z, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWNZ => new V4l(Z, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWNW => new V4l(Z, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWXO => new V4l(Z, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWXI => new V4l(Z, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWXN => new V4l(Z, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWXX => new V4l(Z, W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l ZWXY\n        {\n            readonly get => new V4l(Z, W, X, Y);\n            set { Z = value.X; W = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWXZ => new V4l(Z, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWXW => new V4l(Z, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWYO => new V4l(Z, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWYI => new V4l(Z, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWYN => new V4l(Z, W, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l ZWYX\n        {\n            readonly get => new V4l(Z, W, Y, X);\n            set { Z = value.X; W = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWYY => new V4l(Z, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWYZ => new V4l(Z, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWYW => new V4l(Z, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWZO => new V4l(Z, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWZI => new V4l(Z, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWZN => new V4l(Z, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWZX => new V4l(Z, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWZY => new V4l(Z, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWZZ => new V4l(Z, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWZW => new V4l(Z, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWWO => new V4l(Z, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWWI => new V4l(Z, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWWN => new V4l(Z, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWWX => new V4l(Z, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWWY => new V4l(Z, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWWZ => new V4l(Z, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l ZWWW => new V4l(Z, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOOO => new V4l(W, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOOI => new V4l(W, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOON => new V4l(W, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOOX => new V4l(W, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOOY => new V4l(W, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOOZ => new V4l(W, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOOW => new V4l(W, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOIO => new V4l(W, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOII => new V4l(W, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOPN => new V4l(W, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOIX => new V4l(W, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOIY => new V4l(W, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOIZ => new V4l(W, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOIW => new V4l(W, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WONO => new V4l(W, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WONP => new V4l(W, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WONN => new V4l(W, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WONX => new V4l(W, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WONY => new V4l(W, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WONZ => new V4l(W, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WONW => new V4l(W, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOXO => new V4l(W, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOXI => new V4l(W, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOXN => new V4l(W, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOXX => new V4l(W, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOXY => new V4l(W, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOXZ => new V4l(W, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOXW => new V4l(W, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOYO => new V4l(W, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOYI => new V4l(W, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOYN => new V4l(W, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOYX => new V4l(W, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOYY => new V4l(W, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOYZ => new V4l(W, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOYW => new V4l(W, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOZO => new V4l(W, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOZI => new V4l(W, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOZN => new V4l(W, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOZX => new V4l(W, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOZY => new V4l(W, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOZZ => new V4l(W, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOZW => new V4l(W, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOWO => new V4l(W, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOWI => new V4l(W, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOWN => new V4l(W, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOWX => new V4l(W, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOWY => new V4l(W, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOWZ => new V4l(W, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WOWW => new V4l(W, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIOO => new V4l(W, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIOI => new V4l(W, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPON => new V4l(W, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIOX => new V4l(W, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIOY => new V4l(W, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIOZ => new V4l(W, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIOW => new V4l(W, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIIO => new V4l(W, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIII => new V4l(W, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPPN => new V4l(W, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIIX => new V4l(W, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIIY => new V4l(W, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIIZ => new V4l(W, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIIW => new V4l(W, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPNO => new V4l(W, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPNP => new V4l(W, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPNN => new V4l(W, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPNX => new V4l(W, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPNY => new V4l(W, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPNZ => new V4l(W, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPNW => new V4l(W, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIXO => new V4l(W, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIXI => new V4l(W, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPXN => new V4l(W, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIXX => new V4l(W, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIXY => new V4l(W, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIXZ => new V4l(W, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIXW => new V4l(W, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIYO => new V4l(W, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIYI => new V4l(W, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPYN => new V4l(W, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIYX => new V4l(W, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIYY => new V4l(W, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIYZ => new V4l(W, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIYW => new V4l(W, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIZO => new V4l(W, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIZI => new V4l(W, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPZN => new V4l(W, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIZX => new V4l(W, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIZY => new V4l(W, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIZZ => new V4l(W, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIZW => new V4l(W, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIWO => new V4l(W, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIWI => new V4l(W, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WPWN => new V4l(W, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIWX => new V4l(W, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIWY => new V4l(W, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIWZ => new V4l(W, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WIWW => new V4l(W, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNOO => new V4l(W, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNOP => new V4l(W, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNON => new V4l(W, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNOX => new V4l(W, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNOY => new V4l(W, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNOZ => new V4l(W, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNOW => new V4l(W, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNPO => new V4l(W, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNPP => new V4l(W, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNPN => new V4l(W, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNPX => new V4l(W, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNPY => new V4l(W, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNPZ => new V4l(W, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNPW => new V4l(W, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNNO => new V4l(W, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNNP => new V4l(W, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNNN => new V4l(W, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNNX => new V4l(W, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNNY => new V4l(W, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNNZ => new V4l(W, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNNW => new V4l(W, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNXO => new V4l(W, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNXP => new V4l(W, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNXN => new V4l(W, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNXX => new V4l(W, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNXY => new V4l(W, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNXZ => new V4l(W, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNXW => new V4l(W, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNYO => new V4l(W, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNYP => new V4l(W, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNYN => new V4l(W, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNYX => new V4l(W, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNYY => new V4l(W, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNYZ => new V4l(W, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNYW => new V4l(W, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNZO => new V4l(W, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNZP => new V4l(W, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNZN => new V4l(W, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNZX => new V4l(W, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNZY => new V4l(W, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNZZ => new V4l(W, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNZW => new V4l(W, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNWO => new V4l(W, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNWP => new V4l(W, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNWN => new V4l(W, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNWX => new V4l(W, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNWY => new V4l(W, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNWZ => new V4l(W, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WNWW => new V4l(W, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXOO => new V4l(W, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXOI => new V4l(W, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXON => new V4l(W, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXOX => new V4l(W, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXOY => new V4l(W, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXOZ => new V4l(W, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXOW => new V4l(W, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXIO => new V4l(W, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXII => new V4l(W, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXPN => new V4l(W, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXIX => new V4l(W, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXIY => new V4l(W, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXIZ => new V4l(W, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXIW => new V4l(W, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXNO => new V4l(W, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXNP => new V4l(W, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXNN => new V4l(W, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXNX => new V4l(W, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXNY => new V4l(W, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXNZ => new V4l(W, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXNW => new V4l(W, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXXO => new V4l(W, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXXI => new V4l(W, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXXN => new V4l(W, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXXX => new V4l(W, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXXY => new V4l(W, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXXZ => new V4l(W, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXXW => new V4l(W, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXYO => new V4l(W, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXYI => new V4l(W, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXYN => new V4l(W, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXYX => new V4l(W, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXYY => new V4l(W, X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l WXYZ\n        {\n            readonly get => new V4l(W, X, Y, Z);\n            set { W = value.X; X = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXYW => new V4l(W, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXZO => new V4l(W, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXZI => new V4l(W, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXZN => new V4l(W, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXZX => new V4l(W, X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l WXZY\n        {\n            readonly get => new V4l(W, X, Z, Y);\n            set { W = value.X; X = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXZZ => new V4l(W, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXZW => new V4l(W, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXWO => new V4l(W, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXWI => new V4l(W, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXWN => new V4l(W, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXWX => new V4l(W, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXWY => new V4l(W, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXWZ => new V4l(W, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WXWW => new V4l(W, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYOO => new V4l(W, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYOI => new V4l(W, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYON => new V4l(W, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYOX => new V4l(W, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYOY => new V4l(W, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYOZ => new V4l(W, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYOW => new V4l(W, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYIO => new V4l(W, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYII => new V4l(W, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYPN => new V4l(W, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYIX => new V4l(W, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYIY => new V4l(W, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYIZ => new V4l(W, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYIW => new V4l(W, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYNO => new V4l(W, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYNP => new V4l(W, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYNN => new V4l(W, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYNX => new V4l(W, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYNY => new V4l(W, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYNZ => new V4l(W, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYNW => new V4l(W, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYXO => new V4l(W, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYXI => new V4l(W, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYXN => new V4l(W, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYXX => new V4l(W, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYXY => new V4l(W, Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l WYXZ\n        {\n            readonly get => new V4l(W, Y, X, Z);\n            set { W = value.X; Y = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYXW => new V4l(W, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYYO => new V4l(W, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYYI => new V4l(W, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYYN => new V4l(W, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYYX => new V4l(W, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYYY => new V4l(W, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYYZ => new V4l(W, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYYW => new V4l(W, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYZO => new V4l(W, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYZI => new V4l(W, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYZN => new V4l(W, Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l WYZX\n        {\n            readonly get => new V4l(W, Y, Z, X);\n            set { W = value.X; Y = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYZY => new V4l(W, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYZZ => new V4l(W, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYZW => new V4l(W, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYWO => new V4l(W, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYWI => new V4l(W, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYWN => new V4l(W, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYWX => new V4l(W, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYWY => new V4l(W, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYWZ => new V4l(W, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WYWW => new V4l(W, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZOO => new V4l(W, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZOI => new V4l(W, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZON => new V4l(W, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZOX => new V4l(W, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZOY => new V4l(W, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZOZ => new V4l(W, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZOW => new V4l(W, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZIO => new V4l(W, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZII => new V4l(W, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZPN => new V4l(W, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZIX => new V4l(W, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZIY => new V4l(W, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZIZ => new V4l(W, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZIW => new V4l(W, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZNO => new V4l(W, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZNP => new V4l(W, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZNN => new V4l(W, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZNX => new V4l(W, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZNY => new V4l(W, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZNZ => new V4l(W, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZNW => new V4l(W, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZXO => new V4l(W, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZXI => new V4l(W, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZXN => new V4l(W, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZXX => new V4l(W, Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l WZXY\n        {\n            readonly get => new V4l(W, Z, X, Y);\n            set { W = value.X; Z = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZXZ => new V4l(W, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZXW => new V4l(W, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZYO => new V4l(W, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZYI => new V4l(W, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZYN => new V4l(W, Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l WZYX\n        {\n            readonly get => new V4l(W, Z, Y, X);\n            set { W = value.X; Z = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZYY => new V4l(W, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZYZ => new V4l(W, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZYW => new V4l(W, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZZO => new V4l(W, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZZI => new V4l(W, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZZN => new V4l(W, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZZX => new V4l(W, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZZY => new V4l(W, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZZZ => new V4l(W, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZZW => new V4l(W, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZWO => new V4l(W, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZWI => new V4l(W, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZWN => new V4l(W, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZWX => new V4l(W, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZWY => new V4l(W, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZWZ => new V4l(W, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WZWW => new V4l(W, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWOO => new V4l(W, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWOI => new V4l(W, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWON => new V4l(W, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWOX => new V4l(W, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWOY => new V4l(W, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWOZ => new V4l(W, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWOW => new V4l(W, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWIO => new V4l(W, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWII => new V4l(W, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWPN => new V4l(W, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWIX => new V4l(W, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWIY => new V4l(W, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWIZ => new V4l(W, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWIW => new V4l(W, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWNO => new V4l(W, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWNP => new V4l(W, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWNN => new V4l(W, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWNX => new V4l(W, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWNY => new V4l(W, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWNZ => new V4l(W, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWNW => new V4l(W, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWXO => new V4l(W, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWXI => new V4l(W, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWXN => new V4l(W, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWXX => new V4l(W, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWXY => new V4l(W, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWXZ => new V4l(W, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWXW => new V4l(W, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWYO => new V4l(W, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWYI => new V4l(W, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWYN => new V4l(W, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWYX => new V4l(W, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWYY => new V4l(W, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWYZ => new V4l(W, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWYW => new V4l(W, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWZO => new V4l(W, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWZI => new V4l(W, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWZN => new V4l(W, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWZX => new V4l(W, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWZY => new V4l(W, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWZZ => new V4l(W, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWZW => new V4l(W, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWWO => new V4l(W, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWWI => new V4l(W, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWWN => new V4l(W, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWWX => new V4l(W, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWWY => new V4l(W, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWWZ => new V4l(W, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l WWWW => new V4l(W, W, W, W);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (long)value; }\n        }\n\n        #endregion\n\n        #region ISize4l Members\n\n        public readonly V4l Size4l { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 4; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (long)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V4lEqualityComparer : IEqualityComparer<V4l>\n    {\n        public static V4lEqualityComparer Default\n            => new V4lEqualityComparer();\n\n        #region IEqualityComparer<V4l> Members\n\n        public bool Equals(V4l v0, V4l v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V4l v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Min(this V4l a, V4l b)\n        {\n            return new V4l(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z), Min(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Min(this V4l a, long b)\n        {\n            return new V4l(Min(a.X, b), Min(a.Y, b), Min(a.Z, b), Min(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Min(this long a, V4l b)\n        {\n            return new V4l(Min(a, b.X), Min(a, b.Y), Min(a, b.Z), Min(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Max(this V4l a, V4l b)\n        {\n            return new V4l(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z), Max(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Max(this V4l a, long b)\n        {\n            return new V4l(Max(a.X, b), Max(a.Y, b), Max(a.Z, b), Max(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Max(this long a, V4l b)\n        {\n            return new V4l(Max(a, b.X), Max(a, b.Y), Max(a, b.Z), Max(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Min(this V4l a, V4l b, V4l c)\n        {\n            return new V4l(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z), Min(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Max(this V4l a, V4l b, V4l c)\n        {\n            return new V4l(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z), Max(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Min(this V4l a, V4l b, V4l c, V4l d)\n        {\n            return new V4l(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z), Min(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Max(this V4l a, V4l b, V4l c, V4l d)\n        {\n            return new V4l(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z), Max(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Min(this V4l x, params V4l[] values)\n        {\n            return new V4l(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)), Min(x.W, values.Map(a => a.W)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Max(this V4l x, params V4l[] values)\n        {\n            return new V4l(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)), Max(x.W, values.Map(a => a.W)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Abs(this V4l x)\n        {\n            return new V4l(Abs(x.X), Abs(x.Y), Abs(x.Z), Abs(x.W));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Clamp(this V4l x, V4l a, V4l b)\n        {\n            return new V4l(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z), Clamp(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Clamp(this V4l x, long a, long b)\n        {\n            return new V4l(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b), Clamp(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l ClampExcl(this V4l x, V4l a, V4l b)\n        {\n            return new V4l(ClampExcl(x.X, a.X, b.X), ClampExcl(x.Y, a.Y, b.Y), ClampExcl(x.Z, a.Z, b.Z), ClampExcl(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampExcl to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l ClampExcl(this V4l x, long a, long b)\n        {\n            return new V4l(ClampExcl(x.X, a, b), ClampExcl(x.Y, a, b), ClampExcl(x.Z, a, b), ClampExcl(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l ClampWrap(this V4l x, V4l a, V4l b)\n        {\n            return new V4l(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z), ClampWrap(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l ClampWrap(this V4l x, long a, long b)\n        {\n            return new V4l(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b), ClampWrap(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Saturate(this V4l x)\n        {\n            return new V4l(Saturate(x.X), Saturate(x.Y), Saturate(x.Z), Saturate(x.W));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Sign(this V4l x)\n        {\n            return new V4i(Sign(x.X), Sign(x.Y), Sign(x.Z), Sign(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Signumi(this V4l x)\n        {\n            return new V4i(Signumi(x.X), Signumi(x.Y), Signumi(x.Z), Signumi(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Signum(this V4l x)\n        {\n            return new V4l(Signum(x.X), Signum(x.Y), Signum(x.Z), Signum(x.W));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l MultiplyAdd(V4l x, V4l y, V4l z)\n        {\n            return new V4l(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z), MultiplyAdd(x.W, y.W, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l MultiplyAdd(V4l x, long y, V4l z)\n        {\n            return new V4l(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z), MultiplyAdd(x.W, y, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l MultiplyAdd(long x, V4l y, V4l z)\n        {\n            return new V4l(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z), MultiplyAdd(x, y.W, z.W));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sqrt(this V4l x)\n        {\n            return new V4d(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z), Sqrt(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Cbrt(this V4l x)\n        {\n            return new V4d(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z), Cbrt(x.W));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Square(this V4l x)\n        {\n            return new V4l(Square(x.X), Square(x.Y), Square(x.Z), Square(x.W));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Pown(this V4l x, V4l y)\n        {\n            return new V4l(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z), Pown(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Pown(this V4l x, long y)\n        {\n            return new V4l(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y), Pown(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Pown(this long x, V4l y)\n        {\n            return new V4l(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z), Pown(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Pown(this V4l x, V4i y)\n        {\n            return new V4l(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z), Pown(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Pown(this V4l x, int y)\n        {\n            return new V4l(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y), Pown(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Pown(this long x, V4i y)\n        {\n            return new V4l(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z), Pown(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this V4l x, V4f y)\n        {\n            return new V4f(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z), Pow(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this V4l x, float y)\n        {\n            return new V4f(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y), Pow(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this long x, V4f y)\n        {\n            return new V4f(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z), Pow(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this V4l x, V4d y)\n        {\n            return new V4d(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z), Pow(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this V4l x, double y)\n        {\n            return new V4d(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y), Pow(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this long x, V4d y)\n        {\n            return new V4d(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z), Pow(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this V4l x, V4f y)\n        {\n            return new V4f(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z), Power(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this V4l x, float y)\n        {\n            return new V4f(Power(x.X, y), Power(x.Y, y), Power(x.Z, y), Power(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this long x, V4f y)\n        {\n            return new V4f(Power(x, y.X), Power(x, y.Y), Power(x, y.Z), Power(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this V4l x, V4d y)\n        {\n            return new V4d(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z), Power(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this V4l x, double y)\n        {\n            return new V4d(Power(x.X, y), Power(x.Y, y), Power(x.Z, y), Power(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this long x, V4d y)\n        {\n            return new V4d(Power(x, y.X), Power(x, y.Y), Power(x, y.Z), Power(x, y.W));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Exp(this V4l x)\n        {\n            return new V4d(Exp(x.X), Exp(x.Y), Exp(x.Z), Exp(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(this V4l x)\n        {\n            return new V4d(Log(x.X), Log(x.Y), Log(x.Z), Log(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log2(this V4l x)\n        {\n            return new V4d(Log2(x.X), Log2(x.Y), Log2(x.Z), Log2(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Log2Int(this V4l x)\n        {\n            return new V4i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z), Log2Int(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log10(this V4l x)\n        {\n            return new V4d(Log10(x.X), Log10(x.Y), Log10(x.Z), Log10(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(this V4l x, double basis)\n        {\n            return new V4d(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis), Log(x.W, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l ModP(this V4l a, V4l b)\n        {\n            return new V4l(ModP(a.X, b.X), ModP(a.Y, b.Y), ModP(a.Z, b.Z), ModP(a.W, b.W));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l PowerOfTwo(this V4l x)\n        {\n            return new V4l(PowerOfTwo(x.X), PowerOfTwo(x.Y), PowerOfTwo(x.Z), PowerOfTwo(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.NextPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l NextPowerOfTwo(this V4l x)\n        {\n            return new V4l(NextPowerOfTwo(x.X), NextPowerOfTwo(x.Y), NextPowerOfTwo(x.Z), NextPowerOfTwo(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.PrevPowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l PrevPowerOfTwo(this V4l x)\n        {\n            return new V4l(PrevPowerOfTwo(x.X), PrevPowerOfTwo(x.Y), PrevPowerOfTwo(x.Z), PrevPowerOfTwo(x.W));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Step(this V4l x, V4l edge)\n        {\n            return new V4l(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z), Step(x.W, edge.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Step(this V4l x, long edge)\n        {\n            return new V4l(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge), Step(x.W, edge));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Lerp(this float t, V4l a, V4l b)\n        {\n            return new V4l(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z), Lerp(t, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Lerp(this V4f t, V4l a, V4l b)\n        {\n            return new V4l(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z), Lerp(t.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Lerp(this double t, V4l a, V4l b)\n        {\n            return new V4l(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z), Lerp(t, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l Lerp(this V4d t, V4l a, V4l b)\n        {\n            return new V4l(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z), Lerp(t.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvLerp(this V4l y, V4l a, V4l b)\n        {\n            return new V4d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z), InvLerp(y.W, a.W, b.W));\n        }\n\n        #endregion\n\n        #region Common Divisor and Multiple\n\n        /// <summary>\n        /// Applies Fun.GreatestCommonDivisor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l GreatestCommonDivisor(this V4l a, V4l b)\n        {\n            return new V4l(GreatestCommonDivisor(a.X, b.X), GreatestCommonDivisor(a.Y, b.Y), GreatestCommonDivisor(a.Z, b.Z), GreatestCommonDivisor(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.LeastCommonMultiple to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l LeastCommonMultiple(this V4l a, V4l b)\n        {\n            return new V4l(LeastCommonMultiple(a.X, b.X), LeastCommonMultiple(a.Y, b.Y), LeastCommonMultiple(a.Z, b.Z), LeastCommonMultiple(a.W, b.W));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatFromBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FloatFromBits(this V4l x)\n        {\n            return new V4d(FloatFromBits(x.X), FloatFromBits(x.Y), FloatFromBits(x.Z), FloatFromBits(x.W));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V4l a, V4l b, long tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance) && ApproximateEquals(a.W, b.W, tolerance);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V4l v, long epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long LengthSquared(V4l v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V4l v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Normalized(V4l v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Norm1(V4l v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V4l v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMax(V4l v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long NormMin(V4l v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V4l v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p) + \n                Fun.Abs(v.W).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceSquared(this V4l a, V4l b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y) + Fun.Square(b.Z - a.Z) + Fun.Square(b.W - a.W);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V4l a, V4l b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Distance1(this V4l a, V4l b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y) + Fun.Abs(b.Z - a.Z) + Fun.Abs(b.W - a.W);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V4l a, V4l b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p) + Fun.Abs(b.Z - a.Z).Pow(p) + Fun.Abs(b.W - a.W).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceMax(this V4l a, V4l b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z), Fun.Abs(b.W - a.W));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long DistanceMin(this V4l a, V4l b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z), Fun.Abs(b.W - a.W));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V4l query, V4l p0, V4l p1)\n        {\n            return DistanceToLine((V4d) query, (V4d) p0, (V4d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V4l query, V4l p0, V4l p1)\n        {\n            return DistanceToInfiniteLine((V4d) query, (V4d) p0, (V4d) p1);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V4l query, V4l p0, V4l p1, out double t)\n        {\n            return DistanceToLine((V4d) query, (V4d) p0, (V4d) p1, out t);\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V4l query, V4l p0, V4l p1, out double t)\n        {\n            return DistanceToInfiniteLine((V4d) query, (V4d) p0, (V4d) p1, out t);\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V4l v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n            v.Z = -v.Z;\n            v.W = -v.W;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 4x4 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44l Outer(this V4l a, V4l b)\n        {\n            return new M44l(\n                        a.X * b.X, a.X * b.Y, a.X * b.Z, a.X * b.W, \n                        a.Y * b.X, a.Y * b.Y, a.Y * b.Z, a.Y * b.W, \n                        a.Z * b.X, a.Z * b.Y, a.Z * b.Z, a.Z * b.W, \n                        a.W * b.X, a.W * b.Y, a.W * b.Z, a.W * b.W);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long Dot(this V4l a, V4l b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V4l v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > 0) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < 0) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > 0) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < 0) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > 0) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < 0) flags |= Aardbase.DirFlags.NegativeZ;\n            if (v.W > 0) flags |= Aardbase.DirFlags.PositiveW;\n            if (v.W < 0) flags |= Aardbase.DirFlags.NegativeW;\n            return flags;\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4l a, V4l b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z && a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4l v, long s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s && v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(long s, V4l v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z && s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4l a, V4l b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z || a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4l v, long s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s || v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(long s, V4l v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z || s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4l a, V4l b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z && a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4l v, long s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s && v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(long s, V4l v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z && s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4l a, V4l b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z || a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4l v, long s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s || v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(long s, V4l v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z || s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4l a, V4l b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z && a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4l v, long s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s && v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(long s, V4l v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z && s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4l a, V4l b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z || a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4l v, long s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s || v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(long s, V4l v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z || s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4l a, V4l b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z && a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4l v, long s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s && v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(long s, V4l v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z && s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4l a, V4l b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z || a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4l v, long s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s || v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(long s, V4l v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z || s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4l a, V4l b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4l v, long s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s && v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(long s, V4l v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z && s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4l a, V4l b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z || a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4l v, long s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s || v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(long s, V4l v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z || s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4l a, V4l b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z && a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4l v, long s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s && v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(long s, V4l v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z && s != v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4l a, V4l b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4l v, long s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s || v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(long s, V4l v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z || s != v.W);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V4l v0, V4l v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            if (v0.W < v1.W) return -1;\n            if (v0.W > v1.W) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V4l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MinElement(V4l v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V4l\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static long MaxElement(V4l v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V4l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V4l v, long epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon) || v.W.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4l\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V4l v, long epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon) && v.W.IsTiny(epsilon);\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V4l[] pointArray, V4l point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V4l[] array, int start, int count,\n                V4l point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V4l> pointSelector, V4l point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V4l[] pointArray, V4l point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V4l[] array, long start, long count,\n                V4l point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V4l> pointSelector, V4l point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V4l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V4l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V4l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V4l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V4l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V4l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V4l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V4l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V4l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V4l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V4l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V4l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinW(this V4l[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinW(this V4l[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxW(this V4l[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxW(this V4l[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V4l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V4l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V4l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V4l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V4l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V4l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinW(this IList<V4l> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxW(this IList<V4l> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static long[] CopyCoord(this V4l[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                case 3: return self.Map(v => v.W);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV4lExtensions\n    {\n        #region IRandomUniform extensions for V4l\n\n        /// <summary>\n        /// Uses UniformLong() to generate the elements of a V4l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l UniformV4l(this IRandomUniform rnd)\n        {\n            return new V4l(rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong(), rnd.UniformLong());\n        }\n\n        /// <summary>\n        /// Uses UniformLongNonZero() to generate the elements of a V4l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l UniformV4lNonZero(this IRandomUniform rnd)\n        {\n            return new V4l(rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero(), rnd.UniformLongNonZero());\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of a V4l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l UniformV4l(this IRandomUniform rnd, long size)\n        {\n            return new V4l(rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size), rnd.UniformLong(size));\n        }\n\n        /// <summary>\n        /// Uses UniformLong(long) to generate the elements of a V4l vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l UniformV4l(this IRandomUniform rnd, V4l size)\n        {\n            return new V4l(rnd.UniformLong(size.X), rnd.UniformLong(size.Y), rnd.UniformLong(size.Z), rnd.UniformLong(size.W));\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V4f\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V4f : IVector<double>, ISize4f, IFormattable, IEquatable<V4f>\n    {\n        [DataMember]\n        public float X;\n        [DataMember]\n        public float Y;\n        [DataMember]\n        public float Z;\n        [DataMember]\n        public float W;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(int x, int y, int z, int w)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n            W = (float)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(int v)\n        {\n            X = (float)v;\n            Y = (float)v;\n            Z = (float)v;\n            W = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(int[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n            Z = (float)a[2];\n            W = (float)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(int[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n            Z = (float)a[start + 2];\n            W = (float)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(int a, V3i b)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n            W = (float)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2i a, V2i b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b.X;\n            W = (float)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3i a, int b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)a.Z;\n            W = (float)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/>, <see cref=\"int\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2i a, int b, int c)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b;\n            W = (float)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"V2i\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(int a, V2i b, int c)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n            W = (float)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"int\"/>, and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(int a, int b, V2i c)\n        {\n            X = (float)a;\n            Y = (float)b;\n            Z = (float)c.X;\n            W = (float)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(uint x, uint y, uint z, uint w)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n            W = (float)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(uint v)\n        {\n            X = (float)v;\n            Y = (float)v;\n            Z = (float)v;\n            W = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(uint[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n            Z = (float)a[2];\n            W = (float)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(uint[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n            Z = (float)a[start + 2];\n            W = (float)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(uint a, V3ui b)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n            W = (float)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2ui a, V2ui b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b.X;\n            W = (float)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3ui a, uint b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)a.Z;\n            W = (float)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/>, <see cref=\"uint\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2ui a, uint b, uint c)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b;\n            W = (float)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"V2ui\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(uint a, V2ui b, uint c)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n            W = (float)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"uint\"/>, and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(uint a, uint b, V2ui c)\n        {\n            X = (float)a;\n            Y = (float)b;\n            Z = (float)c.X;\n            W = (float)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(long x, long y, long z, long w)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n            W = (float)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(long v)\n        {\n            X = (float)v;\n            Y = (float)v;\n            Z = (float)v;\n            W = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(long[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n            Z = (float)a[2];\n            W = (float)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(long[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n            Z = (float)a[start + 2];\n            W = (float)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(long a, V3l b)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n            W = (float)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2l a, V2l b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b.X;\n            W = (float)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3l a, long b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)a.Z;\n            W = (float)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/>, <see cref=\"long\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2l a, long b, long c)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b;\n            W = (float)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"V2l\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(long a, V2l b, long c)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n            W = (float)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"long\"/>, and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(long a, long b, V2l c)\n        {\n            X = (float)a;\n            Y = (float)b;\n            Z = (float)c.X;\n            W = (float)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(float x, float y, float z, float w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(float v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n            W = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(float[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n            W = a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(float[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n            W = a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(float a, V3f b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2f a, V2f b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b.X;\n            W = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3f a, float b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = a.Z;\n            W = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/>, <see cref=\"float\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2f a, float b, float c)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"V2f\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(float a, V2f b, float c)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"float\"/>, and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(float a, float b, V2f c)\n        {\n            X = a;\n            Y = b;\n            Z = c.X;\n            W = c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(double x, double y, double z, double w)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n            W = (float)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(double v)\n        {\n            X = (float)v;\n            Y = (float)v;\n            Z = (float)v;\n            W = (float)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(double[] a)\n        {\n            X = (float)a[0];\n            Y = (float)a[1];\n            Z = (float)a[2];\n            W = (float)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(double[] a, int start)\n        {\n            X = (float)a[start + 0];\n            Y = (float)a[start + 1];\n            Z = (float)a[start + 2];\n            W = (float)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(double a, V3d b)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n            W = (float)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2d a, V2d b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b.X;\n            W = (float)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3d a, double b)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)a.Z;\n            W = (float)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/>, <see cref=\"double\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2d a, double b, double c)\n        {\n            X = (float)a.X;\n            Y = (float)a.Y;\n            Z = (float)b;\n            W = (float)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"V2d\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(double a, V2d b, double c)\n        {\n            X = (float)a;\n            Y = (float)b.X;\n            Z = (float)b.Y;\n            W = (float)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"double\"/>, and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(double a, double b, V2d c)\n        {\n            X = (float)a;\n            Y = (float)b;\n            Z = (float)c.X;\n            W = (float)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(Func<int, float> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n            W = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;float&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 4.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(IVector<double> v)\n            : this(v[0], v[1], v[2], v[3])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2f v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V2d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3f v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V3d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V4i v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n            W = (float)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V4ui v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n            W = (float)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V4l v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n            W = (float)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V4f v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(V4d v)\n        {\n            X = (float)v.X;\n            Y = (float)v.Y;\n            Z = (float)v.Z;\n            W = (float)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C3b c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n            W = (float)255;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C3us c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n            W = (float)65535;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C3ui c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n            W = (float)UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3f\"/> color.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C3f c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n            W = 1.0f;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3d\"/> color.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C3d c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n            W = (float)1.0;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C4b c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n            W = (float)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C4us c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n            W = (float)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C4ui c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n            W = (float)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C4f c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n            W = (c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4f(C4d c)\n        {\n            X = (float)(c.R);\n            Y = (float)(c.G);\n            Z = (float)(c.B);\n            W = (float)(c.A);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V2i v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V2ui v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V2l v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V2f v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V2d v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V3i v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V3ui v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V3l v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V3f v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V3d v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V4i v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V4ui v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V4l v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(V4d v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2d ToV2d() => (V2d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3d() => (V3d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d ToV4d() => (V4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V4f v)\n            => new int[] { (int)v.X, (int)v.Y, (int)v.Z, (int)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(int[] v)\n            => new V4f((float)v[0], (float)v[1], (float)v[2], (float)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V4f v)\n            => new uint[] { (uint)v.X, (uint)v.Y, (uint)v.Z, (uint)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(uint[] v)\n            => new V4f((float)v[0], (float)v[1], (float)v[2], (float)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V4f v)\n            => new long[] { (long)v.X, (long)v.Y, (long)v.Z, (long)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(long[] v)\n            => new V4f((float)v[0], (float)v[1], (float)v[2], (float)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V4f v)\n            => new float[] { v.X, v.Y, v.Z, v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(float[] v)\n            => new V4f(v[0], v[1], v[2], v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V4f v)\n            => new double[] { (double)v.X, (double)v.Y, (double)v.Z, (double)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(double[] v)\n            => new V4f((float)v[0], (float)v[1], (float)v[2], (float)v[3]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C3b v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C3us v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C3ui v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"V4f\"/> vector.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C3f v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"V4f\"/> vector.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C3d v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C4b v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C4us v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V4f\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C4ui v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C4f v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4f(C4d v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4f\"/> vector to a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToFloorV4i()\n            => new V4i((int)Fun.Floor(X), (int)Fun.Floor(Y), (int)Fun.Floor(Z), (int)Fun.Floor(W));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToCeilingV4i()\n            => new V4i((int)Fun.Ceiling(X), (int)Fun.Ceiling(Y), (int)Fun.Ceiling(Z), (int)Fun.Ceiling(W));\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3iInhomo()\n        {\n            var div = 1 / W;\n            return new V3i(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3uiInhomo()\n        {\n            var div = 1 / W;\n            return new V3ui(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3lInhomo()\n        {\n            var div = 1 / W;\n            return new V3l(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3fInhomo()\n        {\n            var div = 1 / W;\n            return new V3f(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3dInhomo()\n        {\n            var div = 1 / W;\n            return new V3d(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<float, int> element_fun)\n            => new V4i(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<float, int, int> element_index_fun)\n            => new V4i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n            array[start + 2] = (int)Z;\n            array[start + 3] = (int)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<float, uint> element_fun)\n            => new V4ui(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<float, int, uint> element_index_fun)\n            => new V4ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n            array[start + 2] = (uint)Z;\n            array[start + 3] = (uint)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<float, long> element_fun)\n            => new V4l(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<float, int, long> element_index_fun)\n            => new V4l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n            array[start + 2] = (long)Z;\n            array[start + 3] = (long)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<float, float> element_fun)\n            => new V4f(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<float, int, float> element_index_fun)\n            => new V4f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n            array[start + 3] = W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<float, double> element_fun)\n            => new V4d(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<float, int, double> element_index_fun)\n            => new V4d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = (double)X;\n            array[start + 1] = (double)Y;\n            array[start + 2] = (double)Z;\n            array[start + 3] = (double)W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n            array[start + 3] = element_fun(W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<float, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n            array[start + 3] = element_index_fun(W, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly float[] ToArray()\n            => new float[] { X, Y, Z, W };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field W.\n        /// Useful when properties are required, but the field W is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public float P_W\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return W;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                W = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<float> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n                yield return W;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe float this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (float* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (float* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y\n                        ? (X >= Z ? (X >= W ? 0 : 3) : (Z >= W ? 2 : 3))\n                        : (Y >= Z ? (Y >= W ? 1 : 3) : (Z >= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y\n                        ? (X <= Z ? (X <= W ? 0 : 3) : (Z <= W ? 2 : 3))\n                        : (Y <= Z ? (Y <= W ? 1 : 3) : (Z <= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly float MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z, W);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly float MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z, W);\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) || Fun.IsFinite(Y) || Fun.IsFinite(Z) || Fun.IsFinite(W);\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) && Fun.IsFinite(Y) && Fun.IsFinite(Z) && Fun.IsFinite(W);\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(X) || float.IsNaN(Y) || float.IsNaN(Z) || float.IsNaN(W);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNaN(X) && float.IsNaN(Y) && float.IsNaN(Z) && float.IsNaN(W);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(X) || float.IsInfinity(Y) || float.IsInfinity(Z) || float.IsInfinity(W);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsInfinity(X) && float.IsInfinity(Y) && float.IsInfinity(Z) && float.IsInfinity(W);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(X) || float.IsPositiveInfinity(Y) || float.IsPositiveInfinity(Z) || float.IsPositiveInfinity(W);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsPositiveInfinity(X) && float.IsPositiveInfinity(Y) && float.IsPositiveInfinity(Z) && float.IsPositiveInfinity(W);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(X) || float.IsNegativeInfinity(Y) || float.IsNegativeInfinity(Z) || float.IsNegativeInfinity(W);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => float.IsNegativeInfinity(X) && float.IsNegativeInfinity(Y) && float.IsNegativeInfinity(Z) && float.IsNegativeInfinity(W);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) || Fun.IsTiny(Y) || Fun.IsTiny(Z) || Fun.IsTiny(W);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) && Fun.IsTiny(Y) && Fun.IsTiny(Z) && Fun.IsTiny(W);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the vector is smaller than Constant&lt;float&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the vector are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 4;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V4f Zero\n        {\n            get { return new V4f(0, 0, 0, 0); }\n        }\n\n        /// <summary>\n        /// All elements half.\n        /// </summary>\n        public static V4f Half\n        {\n            get { return new V4f(0.5, 0.5, 0.5, 0.5); }\n        }\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V4f One\n        {\n            get { return new V4f(1, 1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V4f MaxValue\n        {\n            get { return new V4f(Constant<float>.ParseableMaxValue, Constant<float>.ParseableMaxValue, Constant<float>.ParseableMaxValue, Constant<float>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V4f MinValue\n        {\n            get { return new V4f(Constant<float>.ParseableMinValue, Constant<float>.ParseableMinValue, Constant<float>.ParseableMinValue, Constant<float>.ParseableMinValue); }\n        }\n\n         /// <summary>\n        /// All elements set to negative infinity.\n        /// </summary>\n        public static V4f NegativeInfinity\n        {\n            get { return new V4f(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to positive infinity.\n        /// </summary>\n        public static V4f PositiveInfinity\n        {\n            get { return new V4f(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to NaN.\n        /// </summary>\n        public static V4f NaN\n        {\n            get { return new V4f(float.NaN, float.NaN, float.NaN, float.NaN); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V4f XAxis\n        {\n            get { return new V4f(1, 0, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V4f YAxis\n        {\n            get { return new V4f(0, 1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V4f ZAxis\n        {\n            get { return new V4f(0, 0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized W-axis.\n        /// </summary>\n        public static V4f WAxis\n        {\n            get { return new V4f(0, 0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V4f, float>[] SelectorArray =\n            new Func<V4f, float>[] { v => v.X, v => v.Y, v => v.Z, v => v.W };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V4f, int, float> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V4f, int, float> Setter =\n            (ref V4f v, int i, float s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V4f, long, float> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V4f, long, float> LongSetter =\n            (ref V4f v, long i, float s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromV4i(V4i v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromV4ui(V4ui v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromV4l(V4l v)\n            => new V4f(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromV4d(V4d v)\n            => new V4f(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC3b(C3b c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC3us(C3us c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC3ui(C3ui c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3f\"/> color.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC3f(C3f c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3d\"/> color.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC3d(C3d c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC4b(C4b c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC4us(C4us c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC4ui(C4ui c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC4f(C4f c) => new V4f(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FromC4d(C4d c) => new V4f(c);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly float LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z  + W * W ; }\n        }\n\n#if NETCOREAPP3_1_OR_GREATER\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        static float Length_Sse41(V4f vec)\n        {\n            unsafe\n            {\n                var x = (float*)&vec;\n                var vv = Sse.LoadVector128(x);\n                vv = Sse41.DotProduct(vv, vv, 0xF1);\n                var l2 = vv.GetElement(0);\n                return MathF.Sqrt(l2);\n            }\n        }\n#endif\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly float Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n#if NETCOREAPP3_1_OR_GREATER\n                if (Sse41.IsSupported)\n                    return Length_Sse41(this);\n#endif\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z  + W * W );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly float Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y) + Fun.Abs(Z) + Fun.Abs(W); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly float Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z + W * W); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly float NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly float NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V4f Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V4f.Zero;\n                s = 1 / s;\n                return new V4f(X * s, Y * s, Z * s, W * s);\n            }\n        }\n\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered cube with side length 2.\n        /// </summary>\n        public readonly V4f CubeMapped\n        {\n            get\n            {\n                var s = 1 / Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W));\n                return new V4f(X * s, Y * s, Z * s, W * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Abs(V4f v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Floor(V4f v)\n            => v.Floor();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Ceiling(V4f v)\n            => v.Ceiling();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Round(V4f v)\n            => v.Round();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Truncate(V4f v)\n            => v.Truncate();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Acos(V4f v)\n            => Fun.Acos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Acoshb(V4f v)\n            => Fun.Acosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Cos(V4f v)\n            => Fun.Cos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Cosh(V4f v)\n            => Fun.Cosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Asin(V4f v)\n            => Fun.Asin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Asinhb(V4f v)\n            => Fun.Asinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Sin(V4f v)\n            => Fun.Sin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Sinh(V4f v)\n            => Fun.Sinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Atan(V4f v)\n            => Fun.Atan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Atanhb(V4f v)\n            => Fun.Atanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Atan2(V4f a, V4f b)\n            => Fun.Atan2(a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Tan(V4f v)\n            => Fun.Tan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Tanh(V4f v)\n            => Fun.Tanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Sqrt(V4f v)\n            => Fun.Sqrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f CubeRoot(V4f v)\n            => Fun.Cbrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Exp(V4f v)\n            => Fun.Exp(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Log(V4f v)\n            => Fun.Log(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LogBinary(V4f v)\n            => Fun.Log2(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Log10(V4f v)\n            => Fun.Log10(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f CopySgn(V4f value, V4f sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f CopySgn(V4f value, float sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LinearInterp(float t, V4f a, V4f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LinearInterp(V4f t, V4f a, V4f b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Min(V4f v0, V4f v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Min(V4f v, float x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Max(V4f v0, V4f v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Max(V4f v, float x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Saturate(V4f v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f DivideByInt(V4f v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z, int w)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n            W = (float)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z, uint w)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n            W = (float)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z, long w)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n            W = (float)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z, float w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z, double w)\n        {\n            X = (float)x;\n            Y = (float)y;\n            Z = (float)z;\n            W = (float)w;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator -(V4f v)\n            => new V4f(-v.X, -v.Y, -v.Z, -v.W);\n\n        /// <summary>\n        /// Gets a copy of this vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        public readonly V4f Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V4f(1 / X, 1 / Y, 1 / Z, 1 / W); }\n        }\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator +(V4f a, V4f b)\n            => new V4f(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator +(V4f v, float s)\n            => new V4f(v.X + s, v.Y + s, v.Z + s, v.W + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator +(float s, V4f v)\n            => new V4f(s + v.X, s + v.Y, s + v.Z, s + v.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator -(V4f a, V4f b)\n            => new V4f(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator -(V4f v, float s)\n            => new V4f(v.X - s, v.Y - s, v.Z - s, v.W - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator -(float s, V4f v)\n            => new V4f(s - v.X, s - v.Y, s - v.Z, s - v.W);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(V4f a, V4f b)\n            => new V4f(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(V4f v, float s)\n            => new V4f(v.X * s, v.Y * s, v.Z * s, v.W * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator *(float s, V4f v)\n            => new V4f(s * v.X, s * v.Y, s * v.Z, s * v.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator /(V4f a, V4f b)\n            => new V4f(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator /(V4f v, float s)\n            => new V4f(v.X / s, v.Y / s, v.Z / s, v.W / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator /(float s, V4f v)\n            => new V4f(s / v.X, s / v.Y, s / v.Z, s / v.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator %(V4f a, V4f b)\n            => new V4f(a.X % b.X, a.Y % b.Y, a.Z % b.Z, a.W % b.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator %(V4f v, float s)\n            => new V4f(v.X % s, v.Y % s, v.Z % s, v.W % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f operator %(float s, V4f v)\n            => new V4f(s % v.X, s % v.Y, s % v.Z, s % v.W);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4f a, V4f b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4f v, float s)\n        {\n            return v.X == s && v.Y == s && v.Z == s && v.W == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(float s, V4f v)\n        {\n            return s == v.X && s == v.Y && s == v.Z && s == v.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4f a, V4f b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4f v, float s)\n        {\n            return v.X != s || v.Y != s || v.Z != s || v.W != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(float s, V4f v)\n        {\n            return s != v.X || s != v.Y || s != v.Z || s != v.W;\n        }\n\n        #endregion\n\n        #region IEquatable<V4f> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V4f other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + between + W.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z, W);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V4f o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + W.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V4f Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V4f(\n                float.Parse(x[0], CultureInfo.InvariantCulture), \n                float.Parse(x[1], CultureInfo.InvariantCulture), \n                float.Parse(x[2], CultureInfo.InvariantCulture), \n                float.Parse(x[3], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V4f Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<float>.Parse, V4f.Setter);\n        }\n\n        public static V4f Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<float>.Parse, V4f.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OX => new V2f(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OY => new V2f(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OZ => new V2f(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f OW => new V2f(0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IX => new V2f(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IY => new V2f(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IZ => new V2f(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f IW => new V2f(1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NX => new V2f(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NY => new V2f(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NZ => new V2f(-1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f NW => new V2f(-1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XO => new V2f(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XI => new V2f(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XN => new V2f(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f XX => new V2f(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f XY\n        {\n            readonly get => new V2f(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f XZ\n        {\n            readonly get => new V2f(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f XW\n        {\n            readonly get => new V2f(X, W);\n            set { X = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YO => new V2f(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YI => new V2f(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YN => new V2f(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f YX\n        {\n            readonly get => new V2f(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f YY => new V2f(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f YZ\n        {\n            readonly get => new V2f(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f YW\n        {\n            readonly get => new V2f(Y, W);\n            set { Y = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f ZO => new V2f(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f ZI => new V2f(Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f ZN => new V2f(Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f ZX\n        {\n            readonly get => new V2f(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f ZY\n        {\n            readonly get => new V2f(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f ZZ => new V2f(Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f ZW\n        {\n            readonly get => new V2f(Z, W);\n            set { Z = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f WO => new V2f(W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f WI => new V2f(W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f WN => new V2f(W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f WX\n        {\n            readonly get => new V2f(W, X);\n            set { W = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f WY\n        {\n            readonly get => new V2f(W, Y);\n            set { W = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2f WZ\n        {\n            readonly get => new V2f(W, Z);\n            set { W = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2f WW => new V2f(W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOX => new V3f(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOY => new V3f(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOZ => new V3f(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OOW => new V3f(0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIX => new V3f(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIY => new V3f(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIZ => new V3f(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OIW => new V3f(0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONX => new V3f(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONY => new V3f(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONZ => new V3f(0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ONW => new V3f(0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXO => new V3f(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXI => new V3f(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXN => new V3f(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXX => new V3f(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXY => new V3f(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXZ => new V3f(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OXW => new V3f(0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYO => new V3f(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYI => new V3f(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYN => new V3f(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYX => new V3f(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYY => new V3f(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYZ => new V3f(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OYW => new V3f(0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZO => new V3f(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZI => new V3f(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZN => new V3f(0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZX => new V3f(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZY => new V3f(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZZ => new V3f(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OZW => new V3f(0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OWO => new V3f(0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OWI => new V3f(0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OWN => new V3f(0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OWX => new V3f(0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OWY => new V3f(0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OWZ => new V3f(0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f OWW => new V3f(0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOX => new V3f(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOY => new V3f(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOZ => new V3f(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IOW => new V3f(1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIX => new V3f(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIY => new V3f(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIZ => new V3f(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IIW => new V3f(1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNX => new V3f(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNY => new V3f(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNZ => new V3f(1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PNW => new V3f(1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXO => new V3f(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXI => new V3f(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PXN => new V3f(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXX => new V3f(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXY => new V3f(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXZ => new V3f(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IXW => new V3f(1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYO => new V3f(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYI => new V3f(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PYN => new V3f(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYX => new V3f(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYY => new V3f(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYZ => new V3f(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IYW => new V3f(1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZO => new V3f(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZI => new V3f(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PZN => new V3f(1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZX => new V3f(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZY => new V3f(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZZ => new V3f(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IZW => new V3f(1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IWO => new V3f(1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IWI => new V3f(1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f PWN => new V3f(1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IWX => new V3f(1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IWY => new V3f(1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IWZ => new V3f(1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f IWW => new V3f(1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOX => new V3f(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOY => new V3f(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOZ => new V3f(-1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NOW => new V3f(-1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPX => new V3f(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPY => new V3f(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPZ => new V3f(-1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NPW => new V3f(-1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNX => new V3f(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNY => new V3f(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNZ => new V3f(-1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NNW => new V3f(-1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXO => new V3f(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXP => new V3f(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXN => new V3f(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXX => new V3f(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXY => new V3f(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXZ => new V3f(-1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NXW => new V3f(-1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYO => new V3f(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYP => new V3f(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYN => new V3f(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYX => new V3f(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYY => new V3f(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYZ => new V3f(-1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NYW => new V3f(-1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZO => new V3f(-1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZP => new V3f(-1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZN => new V3f(-1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZX => new V3f(-1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZY => new V3f(-1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZZ => new V3f(-1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NZW => new V3f(-1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NWO => new V3f(-1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NWP => new V3f(-1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NWN => new V3f(-1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NWX => new V3f(-1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NWY => new V3f(-1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NWZ => new V3f(-1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f NWW => new V3f(-1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOO => new V3f(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOI => new V3f(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XON => new V3f(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOX => new V3f(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOY => new V3f(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOZ => new V3f(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XOW => new V3f(X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIO => new V3f(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XII => new V3f(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XPN => new V3f(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIX => new V3f(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIY => new V3f(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIZ => new V3f(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XIW => new V3f(X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNO => new V3f(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNP => new V3f(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNN => new V3f(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNX => new V3f(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNY => new V3f(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNZ => new V3f(X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XNW => new V3f(X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXO => new V3f(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXI => new V3f(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXN => new V3f(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXX => new V3f(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXY => new V3f(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXZ => new V3f(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XXW => new V3f(X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYO => new V3f(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYI => new V3f(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYN => new V3f(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYX => new V3f(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XYY => new V3f(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f XYZ\n        {\n            readonly get => new V3f(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f XYW\n        {\n            readonly get => new V3f(X, Y, W);\n            set { X = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZO => new V3f(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZI => new V3f(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZN => new V3f(X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZX => new V3f(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f XZY\n        {\n            readonly get => new V3f(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XZZ => new V3f(X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f XZW\n        {\n            readonly get => new V3f(X, Z, W);\n            set { X = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XWO => new V3f(X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XWI => new V3f(X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XWN => new V3f(X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XWX => new V3f(X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f XWY\n        {\n            readonly get => new V3f(X, W, Y);\n            set { X = value.X; W = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f XWZ\n        {\n            readonly get => new V3f(X, W, Z);\n            set { X = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f XWW => new V3f(X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOO => new V3f(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOI => new V3f(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YON => new V3f(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOX => new V3f(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOY => new V3f(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOZ => new V3f(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YOW => new V3f(Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIO => new V3f(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YII => new V3f(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YPN => new V3f(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIX => new V3f(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIY => new V3f(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIZ => new V3f(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YIW => new V3f(Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNO => new V3f(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNP => new V3f(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNN => new V3f(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNX => new V3f(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNY => new V3f(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNZ => new V3f(Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YNW => new V3f(Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXO => new V3f(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXI => new V3f(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXN => new V3f(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXX => new V3f(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YXY => new V3f(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f YXZ\n        {\n            readonly get => new V3f(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f YXW\n        {\n            readonly get => new V3f(Y, X, W);\n            set { Y = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYO => new V3f(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYI => new V3f(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYN => new V3f(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYX => new V3f(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYY => new V3f(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYZ => new V3f(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YYW => new V3f(Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZO => new V3f(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZI => new V3f(Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZN => new V3f(Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f YZX\n        {\n            readonly get => new V3f(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZY => new V3f(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YZZ => new V3f(Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f YZW\n        {\n            readonly get => new V3f(Y, Z, W);\n            set { Y = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YWO => new V3f(Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YWI => new V3f(Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YWN => new V3f(Y, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f YWX\n        {\n            readonly get => new V3f(Y, W, X);\n            set { Y = value.X; W = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YWY => new V3f(Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f YWZ\n        {\n            readonly get => new V3f(Y, W, Z);\n            set { Y = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f YWW => new V3f(Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOO => new V3f(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOI => new V3f(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZON => new V3f(Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOX => new V3f(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOY => new V3f(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOZ => new V3f(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZOW => new V3f(Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIO => new V3f(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZII => new V3f(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZPN => new V3f(Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIX => new V3f(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIY => new V3f(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIZ => new V3f(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZIW => new V3f(Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNO => new V3f(Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNP => new V3f(Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNN => new V3f(Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNX => new V3f(Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNY => new V3f(Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNZ => new V3f(Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZNW => new V3f(Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXO => new V3f(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXI => new V3f(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXN => new V3f(Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXX => new V3f(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f ZXY\n        {\n            readonly get => new V3f(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZXZ => new V3f(Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f ZXW\n        {\n            readonly get => new V3f(Z, X, W);\n            set { Z = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYO => new V3f(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYI => new V3f(Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYN => new V3f(Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f ZYX\n        {\n            readonly get => new V3f(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYY => new V3f(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZYZ => new V3f(Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f ZYW\n        {\n            readonly get => new V3f(Z, Y, W);\n            set { Z = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZO => new V3f(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZI => new V3f(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZN => new V3f(Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZX => new V3f(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZY => new V3f(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZZ => new V3f(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZZW => new V3f(Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZWO => new V3f(Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZWI => new V3f(Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZWN => new V3f(Z, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f ZWX\n        {\n            readonly get => new V3f(Z, W, X);\n            set { Z = value.X; W = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f ZWY\n        {\n            readonly get => new V3f(Z, W, Y);\n            set { Z = value.X; W = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZWZ => new V3f(Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f ZWW => new V3f(Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WOO => new V3f(W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WOI => new V3f(W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WON => new V3f(W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WOX => new V3f(W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WOY => new V3f(W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WOZ => new V3f(W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WOW => new V3f(W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WIO => new V3f(W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WII => new V3f(W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WPN => new V3f(W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WIX => new V3f(W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WIY => new V3f(W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WIZ => new V3f(W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WIW => new V3f(W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WNO => new V3f(W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WNP => new V3f(W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WNN => new V3f(W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WNX => new V3f(W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WNY => new V3f(W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WNZ => new V3f(W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WNW => new V3f(W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WXO => new V3f(W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WXI => new V3f(W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WXN => new V3f(W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WXX => new V3f(W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f WXY\n        {\n            readonly get => new V3f(W, X, Y);\n            set { W = value.X; X = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f WXZ\n        {\n            readonly get => new V3f(W, X, Z);\n            set { W = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WXW => new V3f(W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WYO => new V3f(W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WYI => new V3f(W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WYN => new V3f(W, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f WYX\n        {\n            readonly get => new V3f(W, Y, X);\n            set { W = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WYY => new V3f(W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f WYZ\n        {\n            readonly get => new V3f(W, Y, Z);\n            set { W = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WYW => new V3f(W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WZO => new V3f(W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WZI => new V3f(W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WZN => new V3f(W, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f WZX\n        {\n            readonly get => new V3f(W, Z, X);\n            set { W = value.X; Z = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3f WZY\n        {\n            readonly get => new V3f(W, Z, Y);\n            set { W = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WZZ => new V3f(W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WZW => new V3f(W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WWO => new V3f(W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WWI => new V3f(W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WWN => new V3f(W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WWX => new V3f(W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WWY => new V3f(W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WWZ => new V3f(W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3f WWW => new V3f(W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OOOO => new V4f(0, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OOOI => new V4f(0, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OOON => new V4f(0, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOX => new V4f(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOY => new V4f(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOZ => new V4f(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOOW => new V4f(0, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OOIO => new V4f(0, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OOII => new V4f(0, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OOPN => new V4f(0, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIX => new V4f(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIY => new V4f(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIZ => new V4f(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOIW => new V4f(0, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OONO => new V4f(0, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OONP => new V4f(0, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OONN => new V4f(0, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONX => new V4f(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONY => new V4f(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONZ => new V4f(0, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OONW => new V4f(0, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXO => new V4f(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXI => new V4f(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXN => new V4f(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXX => new V4f(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXY => new V4f(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXZ => new V4f(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOXW => new V4f(0, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYO => new V4f(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYI => new V4f(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYN => new V4f(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYX => new V4f(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYY => new V4f(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYZ => new V4f(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOYW => new V4f(0, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZO => new V4f(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZI => new V4f(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZN => new V4f(0, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZX => new V4f(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZY => new V4f(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZZ => new V4f(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOZW => new V4f(0, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOWO => new V4f(0, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOWI => new V4f(0, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOWN => new V4f(0, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOWX => new V4f(0, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOWY => new V4f(0, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOWZ => new V4f(0, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OOWW => new V4f(0, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OIOO => new V4f(0, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OIOI => new V4f(0, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OPON => new V4f(0, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOX => new V4f(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOY => new V4f(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOZ => new V4f(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIOW => new V4f(0, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OIIO => new V4f(0, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OIII => new V4f(0, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OPPN => new V4f(0, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIX => new V4f(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIY => new V4f(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIZ => new V4f(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIIW => new V4f(0, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OPNO => new V4f(0, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OPNP => new V4f(0, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f OPNN => new V4f(0, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNX => new V4f(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNY => new V4f(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNZ => new V4f(0, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPNW => new V4f(0, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXO => new V4f(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXI => new V4f(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPXN => new V4f(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXX => new V4f(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXY => new V4f(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXZ => new V4f(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIXW => new V4f(0, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYO => new V4f(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYI => new V4f(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPYN => new V4f(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYX => new V4f(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYY => new V4f(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYZ => new V4f(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIYW => new V4f(0, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZO => new V4f(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZI => new V4f(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPZN => new V4f(0, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZX => new V4f(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZY => new V4f(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZZ => new V4f(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIZW => new V4f(0, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIWO => new V4f(0, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIWI => new V4f(0, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OPWN => new V4f(0, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIWX => new V4f(0, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIWY => new V4f(0, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIWZ => new V4f(0, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OIWW => new V4f(0, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONOO => new V4f(0, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONOP => new V4f(0, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONON => new V4f(0, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOX => new V4f(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOY => new V4f(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOZ => new V4f(0, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONOW => new V4f(0, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONPO => new V4f(0, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONPP => new V4f(0, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONPN => new V4f(0, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPX => new V4f(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPY => new V4f(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPZ => new V4f(0, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONPW => new V4f(0, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONNO => new V4f(0, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONNP => new V4f(0, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f ONNN => new V4f(0, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNX => new V4f(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNY => new V4f(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNZ => new V4f(0, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONNW => new V4f(0, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXO => new V4f(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXP => new V4f(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXN => new V4f(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXX => new V4f(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXY => new V4f(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXZ => new V4f(0, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONXW => new V4f(0, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYO => new V4f(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYP => new V4f(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYN => new V4f(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYX => new V4f(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYY => new V4f(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYZ => new V4f(0, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONYW => new V4f(0, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZO => new V4f(0, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZP => new V4f(0, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZN => new V4f(0, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZX => new V4f(0, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZY => new V4f(0, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZZ => new V4f(0, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONZW => new V4f(0, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONWO => new V4f(0, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONWP => new V4f(0, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONWN => new V4f(0, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONWX => new V4f(0, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONWY => new V4f(0, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONWZ => new V4f(0, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ONWW => new V4f(0, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOO => new V4f(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOI => new V4f(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXON => new V4f(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOX => new V4f(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOY => new V4f(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOZ => new V4f(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXOW => new V4f(0, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIO => new V4f(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXII => new V4f(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXPN => new V4f(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIX => new V4f(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIY => new V4f(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIZ => new V4f(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXIW => new V4f(0, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNO => new V4f(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNP => new V4f(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNN => new V4f(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNX => new V4f(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNY => new V4f(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNZ => new V4f(0, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXNW => new V4f(0, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXO => new V4f(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXI => new V4f(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXN => new V4f(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXX => new V4f(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXY => new V4f(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXZ => new V4f(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXXW => new V4f(0, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYO => new V4f(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYI => new V4f(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYN => new V4f(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYX => new V4f(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYY => new V4f(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYZ => new V4f(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXYW => new V4f(0, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZO => new V4f(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZI => new V4f(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZN => new V4f(0, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZX => new V4f(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZY => new V4f(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZZ => new V4f(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXZW => new V4f(0, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXWO => new V4f(0, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXWI => new V4f(0, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXWN => new V4f(0, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXWX => new V4f(0, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXWY => new V4f(0, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXWZ => new V4f(0, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OXWW => new V4f(0, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOO => new V4f(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOI => new V4f(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYON => new V4f(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOX => new V4f(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOY => new V4f(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOZ => new V4f(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYOW => new V4f(0, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIO => new V4f(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYII => new V4f(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYPN => new V4f(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIX => new V4f(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIY => new V4f(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIZ => new V4f(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYIW => new V4f(0, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNO => new V4f(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNP => new V4f(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNN => new V4f(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNX => new V4f(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNY => new V4f(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNZ => new V4f(0, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYNW => new V4f(0, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXO => new V4f(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXI => new V4f(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXN => new V4f(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXX => new V4f(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXY => new V4f(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXZ => new V4f(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYXW => new V4f(0, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYO => new V4f(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYI => new V4f(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYN => new V4f(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYX => new V4f(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYY => new V4f(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYZ => new V4f(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYYW => new V4f(0, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZO => new V4f(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZI => new V4f(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZN => new V4f(0, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZX => new V4f(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZY => new V4f(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZZ => new V4f(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYZW => new V4f(0, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYWO => new V4f(0, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYWI => new V4f(0, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYWN => new V4f(0, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYWX => new V4f(0, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYWY => new V4f(0, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYWZ => new V4f(0, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OYWW => new V4f(0, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOO => new V4f(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOI => new V4f(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZON => new V4f(0, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOX => new V4f(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOY => new V4f(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOZ => new V4f(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZOW => new V4f(0, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIO => new V4f(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZII => new V4f(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZPN => new V4f(0, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIX => new V4f(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIY => new V4f(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIZ => new V4f(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZIW => new V4f(0, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNO => new V4f(0, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNP => new V4f(0, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNN => new V4f(0, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNX => new V4f(0, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNY => new V4f(0, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNZ => new V4f(0, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZNW => new V4f(0, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXO => new V4f(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXI => new V4f(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXN => new V4f(0, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXX => new V4f(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXY => new V4f(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXZ => new V4f(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZXW => new V4f(0, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYO => new V4f(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYI => new V4f(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYN => new V4f(0, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYX => new V4f(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYY => new V4f(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYZ => new V4f(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZYW => new V4f(0, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZO => new V4f(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZI => new V4f(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZN => new V4f(0, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZX => new V4f(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZY => new V4f(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZZ => new V4f(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZZW => new V4f(0, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZWO => new V4f(0, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZWI => new V4f(0, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZWN => new V4f(0, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZWX => new V4f(0, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZWY => new V4f(0, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZWZ => new V4f(0, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OZWW => new V4f(0, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWOO => new V4f(0, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWOI => new V4f(0, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWON => new V4f(0, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWOX => new V4f(0, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWOY => new V4f(0, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWOZ => new V4f(0, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWOW => new V4f(0, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWIO => new V4f(0, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWII => new V4f(0, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWPN => new V4f(0, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWIX => new V4f(0, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWIY => new V4f(0, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWIZ => new V4f(0, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWIW => new V4f(0, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWNO => new V4f(0, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWNP => new V4f(0, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWNN => new V4f(0, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWNX => new V4f(0, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWNY => new V4f(0, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWNZ => new V4f(0, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWNW => new V4f(0, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWXO => new V4f(0, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWXI => new V4f(0, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWXN => new V4f(0, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWXX => new V4f(0, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWXY => new V4f(0, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWXZ => new V4f(0, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWXW => new V4f(0, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWYO => new V4f(0, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWYI => new V4f(0, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWYN => new V4f(0, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWYX => new V4f(0, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWYY => new V4f(0, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWYZ => new V4f(0, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWYW => new V4f(0, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWZO => new V4f(0, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWZI => new V4f(0, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWZN => new V4f(0, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWZX => new V4f(0, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWZY => new V4f(0, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWZZ => new V4f(0, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWZW => new V4f(0, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWWO => new V4f(0, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWWI => new V4f(0, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWWN => new V4f(0, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWWX => new V4f(0, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWWY => new V4f(0, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWWZ => new V4f(0, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f OWWW => new V4f(0, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f IOOO => new V4f(1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f IOOI => new V4f(1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f POON => new V4f(1, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOX => new V4f(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOY => new V4f(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOZ => new V4f(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOOW => new V4f(1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f IOIO => new V4f(1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f IOII => new V4f(1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f POPN => new V4f(1, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIX => new V4f(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIY => new V4f(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIZ => new V4f(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOIW => new V4f(1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PONO => new V4f(1, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PONP => new V4f(1, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PONN => new V4f(1, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONX => new V4f(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONY => new V4f(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONZ => new V4f(1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PONW => new V4f(1, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXO => new V4f(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXI => new V4f(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POXN => new V4f(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXX => new V4f(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXY => new V4f(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXZ => new V4f(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOXW => new V4f(1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYO => new V4f(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYI => new V4f(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POYN => new V4f(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYX => new V4f(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYY => new V4f(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYZ => new V4f(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOYW => new V4f(1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZO => new V4f(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZI => new V4f(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POZN => new V4f(1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZX => new V4f(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZY => new V4f(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZZ => new V4f(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOZW => new V4f(1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOWO => new V4f(1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOWI => new V4f(1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f POWN => new V4f(1, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOWX => new V4f(1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOWY => new V4f(1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOWZ => new V4f(1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IOWW => new V4f(1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f IIOO => new V4f(1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f IIOI => new V4f(1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PPON => new V4f(1, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOX => new V4f(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOY => new V4f(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOZ => new V4f(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIOW => new V4f(1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f IIIO => new V4f(1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f IIII => new V4f(1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PPPN => new V4f(1, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIX => new V4f(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIY => new V4f(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIZ => new V4f(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIIW => new V4f(1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PPNO => new V4f(1, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PPNP => new V4f(1, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PPNN => new V4f(1, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNX => new V4f(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNY => new V4f(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNZ => new V4f(1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPNW => new V4f(1, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXO => new V4f(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXI => new V4f(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPXN => new V4f(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXX => new V4f(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXY => new V4f(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXZ => new V4f(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIXW => new V4f(1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYO => new V4f(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYI => new V4f(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPYN => new V4f(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYX => new V4f(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYY => new V4f(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYZ => new V4f(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIYW => new V4f(1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZO => new V4f(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZI => new V4f(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPZN => new V4f(1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZX => new V4f(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZY => new V4f(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZZ => new V4f(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIZW => new V4f(1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIWO => new V4f(1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIWI => new V4f(1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PPWN => new V4f(1, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIWX => new V4f(1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIWY => new V4f(1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIWZ => new V4f(1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IIWW => new V4f(1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNOO => new V4f(1, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNOP => new V4f(1, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNON => new V4f(1, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOX => new V4f(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOY => new V4f(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOZ => new V4f(1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNOW => new V4f(1, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNPO => new V4f(1, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNPP => new V4f(1, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNPN => new V4f(1, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPX => new V4f(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPY => new V4f(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPZ => new V4f(1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNPW => new V4f(1, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNNO => new V4f(1, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNNP => new V4f(1, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f PNNN => new V4f(1, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNX => new V4f(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNY => new V4f(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNZ => new V4f(1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNNW => new V4f(1, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXO => new V4f(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXP => new V4f(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXN => new V4f(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXX => new V4f(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXY => new V4f(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXZ => new V4f(1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNXW => new V4f(1, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYO => new V4f(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYP => new V4f(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYN => new V4f(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYX => new V4f(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYY => new V4f(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYZ => new V4f(1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNYW => new V4f(1, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZO => new V4f(1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZP => new V4f(1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZN => new V4f(1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZX => new V4f(1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZY => new V4f(1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZZ => new V4f(1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNZW => new V4f(1, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNWO => new V4f(1, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNWP => new V4f(1, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNWN => new V4f(1, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNWX => new V4f(1, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNWY => new V4f(1, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNWZ => new V4f(1, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PNWW => new V4f(1, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOO => new V4f(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOI => new V4f(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXON => new V4f(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOX => new V4f(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOY => new V4f(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOZ => new V4f(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXOW => new V4f(1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIO => new V4f(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXII => new V4f(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXPN => new V4f(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIX => new V4f(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIY => new V4f(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIZ => new V4f(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXIW => new V4f(1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNO => new V4f(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNP => new V4f(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNN => new V4f(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNX => new V4f(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNY => new V4f(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNZ => new V4f(1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXNW => new V4f(1, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXO => new V4f(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXI => new V4f(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXXN => new V4f(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXX => new V4f(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXY => new V4f(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXZ => new V4f(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXXW => new V4f(1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYO => new V4f(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYI => new V4f(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXYN => new V4f(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYX => new V4f(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYY => new V4f(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYZ => new V4f(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXYW => new V4f(1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZO => new V4f(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZI => new V4f(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXZN => new V4f(1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZX => new V4f(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZY => new V4f(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZZ => new V4f(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXZW => new V4f(1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXWO => new V4f(1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXWI => new V4f(1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PXWN => new V4f(1, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXWX => new V4f(1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXWY => new V4f(1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXWZ => new V4f(1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IXWW => new V4f(1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOO => new V4f(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOI => new V4f(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYON => new V4f(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOX => new V4f(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOY => new V4f(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOZ => new V4f(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYOW => new V4f(1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIO => new V4f(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYII => new V4f(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYPN => new V4f(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIX => new V4f(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIY => new V4f(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIZ => new V4f(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYIW => new V4f(1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNO => new V4f(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNP => new V4f(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNN => new V4f(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNX => new V4f(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNY => new V4f(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNZ => new V4f(1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYNW => new V4f(1, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXO => new V4f(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXI => new V4f(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYXN => new V4f(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXX => new V4f(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXY => new V4f(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXZ => new V4f(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYXW => new V4f(1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYO => new V4f(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYI => new V4f(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYYN => new V4f(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYX => new V4f(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYY => new V4f(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYZ => new V4f(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYYW => new V4f(1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZO => new V4f(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZI => new V4f(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYZN => new V4f(1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZX => new V4f(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZY => new V4f(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZZ => new V4f(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYZW => new V4f(1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYWO => new V4f(1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYWI => new V4f(1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PYWN => new V4f(1, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYWX => new V4f(1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYWY => new V4f(1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYWZ => new V4f(1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IYWW => new V4f(1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOO => new V4f(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOI => new V4f(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZON => new V4f(1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOX => new V4f(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOY => new V4f(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOZ => new V4f(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZOW => new V4f(1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIO => new V4f(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZII => new V4f(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZPN => new V4f(1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIX => new V4f(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIY => new V4f(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIZ => new V4f(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZIW => new V4f(1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNO => new V4f(1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNP => new V4f(1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNN => new V4f(1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNX => new V4f(1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNY => new V4f(1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNZ => new V4f(1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZNW => new V4f(1, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXO => new V4f(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXI => new V4f(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZXN => new V4f(1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXX => new V4f(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXY => new V4f(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXZ => new V4f(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZXW => new V4f(1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYO => new V4f(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYI => new V4f(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZYN => new V4f(1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYX => new V4f(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYY => new V4f(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYZ => new V4f(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZYW => new V4f(1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZO => new V4f(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZI => new V4f(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZZN => new V4f(1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZX => new V4f(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZY => new V4f(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZZ => new V4f(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZZW => new V4f(1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZWO => new V4f(1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZWI => new V4f(1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PZWN => new V4f(1, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZWX => new V4f(1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZWY => new V4f(1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZWZ => new V4f(1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IZWW => new V4f(1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWOO => new V4f(1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWOI => new V4f(1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWON => new V4f(1, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWOX => new V4f(1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWOY => new V4f(1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWOZ => new V4f(1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWOW => new V4f(1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWIO => new V4f(1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWII => new V4f(1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWPN => new V4f(1, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWIX => new V4f(1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWIY => new V4f(1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWIZ => new V4f(1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWIW => new V4f(1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWNO => new V4f(1, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWNP => new V4f(1, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWNN => new V4f(1, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWNX => new V4f(1, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWNY => new V4f(1, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWNZ => new V4f(1, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWNW => new V4f(1, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWXO => new V4f(1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWXI => new V4f(1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWXN => new V4f(1, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWXX => new V4f(1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWXY => new V4f(1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWXZ => new V4f(1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWXW => new V4f(1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWYO => new V4f(1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWYI => new V4f(1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWYN => new V4f(1, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWYX => new V4f(1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWYY => new V4f(1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWYZ => new V4f(1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWYW => new V4f(1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWZO => new V4f(1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWZI => new V4f(1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWZN => new V4f(1, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWZX => new V4f(1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWZY => new V4f(1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWZZ => new V4f(1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWZW => new V4f(1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWWO => new V4f(1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWWI => new V4f(1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f PWWN => new V4f(1, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWWX => new V4f(1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWWY => new V4f(1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWWZ => new V4f(1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f IWWW => new V4f(1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NOOO => new V4f(-1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NOOP => new V4f(-1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NOON => new V4f(-1, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOX => new V4f(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOY => new V4f(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOZ => new V4f(-1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOOW => new V4f(-1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NOPO => new V4f(-1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NOPP => new V4f(-1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NOPN => new V4f(-1, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPX => new V4f(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPY => new V4f(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPZ => new V4f(-1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOPW => new V4f(-1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NONO => new V4f(-1, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NONP => new V4f(-1, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NONN => new V4f(-1, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONX => new V4f(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONY => new V4f(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONZ => new V4f(-1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NONW => new V4f(-1, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXO => new V4f(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXP => new V4f(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXN => new V4f(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXX => new V4f(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXY => new V4f(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXZ => new V4f(-1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOXW => new V4f(-1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYO => new V4f(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYP => new V4f(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYN => new V4f(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYX => new V4f(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYY => new V4f(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYZ => new V4f(-1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOYW => new V4f(-1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZO => new V4f(-1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZP => new V4f(-1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZN => new V4f(-1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZX => new V4f(-1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZY => new V4f(-1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZZ => new V4f(-1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOZW => new V4f(-1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOWO => new V4f(-1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOWP => new V4f(-1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOWN => new V4f(-1, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOWX => new V4f(-1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOWY => new V4f(-1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOWZ => new V4f(-1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NOWW => new V4f(-1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPOO => new V4f(-1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPOP => new V4f(-1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPON => new V4f(-1, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOX => new V4f(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOY => new V4f(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOZ => new V4f(-1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPOW => new V4f(-1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPPO => new V4f(-1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPPP => new V4f(-1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPPN => new V4f(-1, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPX => new V4f(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPY => new V4f(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPZ => new V4f(-1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPPW => new V4f(-1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPNO => new V4f(-1, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPNP => new V4f(-1, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NPNN => new V4f(-1, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNX => new V4f(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNY => new V4f(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNZ => new V4f(-1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPNW => new V4f(-1, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXO => new V4f(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXP => new V4f(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXN => new V4f(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXX => new V4f(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXY => new V4f(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXZ => new V4f(-1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPXW => new V4f(-1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYO => new V4f(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYP => new V4f(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYN => new V4f(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYX => new V4f(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYY => new V4f(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYZ => new V4f(-1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPYW => new V4f(-1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZO => new V4f(-1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZP => new V4f(-1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZN => new V4f(-1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZX => new V4f(-1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZY => new V4f(-1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZZ => new V4f(-1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPZW => new V4f(-1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPWO => new V4f(-1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPWP => new V4f(-1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPWN => new V4f(-1, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPWX => new V4f(-1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPWY => new V4f(-1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPWZ => new V4f(-1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NPWW => new V4f(-1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNOO => new V4f(-1, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNOP => new V4f(-1, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNON => new V4f(-1, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOX => new V4f(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOY => new V4f(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOZ => new V4f(-1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNOW => new V4f(-1, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNPO => new V4f(-1, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNPP => new V4f(-1, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNPN => new V4f(-1, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPX => new V4f(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPY => new V4f(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPZ => new V4f(-1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNPW => new V4f(-1, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNNO => new V4f(-1, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNNP => new V4f(-1, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4f NNNN => new V4f(-1, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNX => new V4f(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNY => new V4f(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNZ => new V4f(-1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNNW => new V4f(-1, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXO => new V4f(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXP => new V4f(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXN => new V4f(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXX => new V4f(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXY => new V4f(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXZ => new V4f(-1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNXW => new V4f(-1, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYO => new V4f(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYP => new V4f(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYN => new V4f(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYX => new V4f(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYY => new V4f(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYZ => new V4f(-1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNYW => new V4f(-1, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZO => new V4f(-1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZP => new V4f(-1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZN => new V4f(-1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZX => new V4f(-1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZY => new V4f(-1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZZ => new V4f(-1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNZW => new V4f(-1, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNWO => new V4f(-1, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNWP => new V4f(-1, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNWN => new V4f(-1, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNWX => new V4f(-1, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNWY => new V4f(-1, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNWZ => new V4f(-1, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NNWW => new V4f(-1, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOO => new V4f(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOP => new V4f(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXON => new V4f(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOX => new V4f(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOY => new V4f(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOZ => new V4f(-1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXOW => new V4f(-1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPO => new V4f(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPP => new V4f(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPN => new V4f(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPX => new V4f(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPY => new V4f(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPZ => new V4f(-1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXPW => new V4f(-1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNO => new V4f(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNP => new V4f(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNN => new V4f(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNX => new V4f(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNY => new V4f(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNZ => new V4f(-1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXNW => new V4f(-1, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXO => new V4f(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXP => new V4f(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXN => new V4f(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXX => new V4f(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXY => new V4f(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXZ => new V4f(-1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXXW => new V4f(-1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYO => new V4f(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYP => new V4f(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYN => new V4f(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYX => new V4f(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYY => new V4f(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYZ => new V4f(-1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXYW => new V4f(-1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZO => new V4f(-1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZP => new V4f(-1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZN => new V4f(-1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZX => new V4f(-1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZY => new V4f(-1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZZ => new V4f(-1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXZW => new V4f(-1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXWO => new V4f(-1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXWP => new V4f(-1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXWN => new V4f(-1, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXWX => new V4f(-1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXWY => new V4f(-1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXWZ => new V4f(-1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NXWW => new V4f(-1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOO => new V4f(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOP => new V4f(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYON => new V4f(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOX => new V4f(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOY => new V4f(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOZ => new V4f(-1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYOW => new V4f(-1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPO => new V4f(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPP => new V4f(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPN => new V4f(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPX => new V4f(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPY => new V4f(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPZ => new V4f(-1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYPW => new V4f(-1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNO => new V4f(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNP => new V4f(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNN => new V4f(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNX => new V4f(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNY => new V4f(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNZ => new V4f(-1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYNW => new V4f(-1, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXO => new V4f(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXP => new V4f(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXN => new V4f(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXX => new V4f(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXY => new V4f(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXZ => new V4f(-1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYXW => new V4f(-1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYO => new V4f(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYP => new V4f(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYN => new V4f(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYX => new V4f(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYY => new V4f(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYZ => new V4f(-1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYYW => new V4f(-1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZO => new V4f(-1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZP => new V4f(-1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZN => new V4f(-1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZX => new V4f(-1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZY => new V4f(-1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZZ => new V4f(-1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYZW => new V4f(-1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYWO => new V4f(-1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYWP => new V4f(-1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYWN => new V4f(-1, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYWX => new V4f(-1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYWY => new V4f(-1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYWZ => new V4f(-1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NYWW => new V4f(-1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOO => new V4f(-1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOP => new V4f(-1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZON => new V4f(-1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOX => new V4f(-1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOY => new V4f(-1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOZ => new V4f(-1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZOW => new V4f(-1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPO => new V4f(-1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPP => new V4f(-1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPN => new V4f(-1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPX => new V4f(-1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPY => new V4f(-1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPZ => new V4f(-1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZPW => new V4f(-1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNO => new V4f(-1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNP => new V4f(-1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNN => new V4f(-1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNX => new V4f(-1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNY => new V4f(-1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNZ => new V4f(-1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZNW => new V4f(-1, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXO => new V4f(-1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXP => new V4f(-1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXN => new V4f(-1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXX => new V4f(-1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXY => new V4f(-1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXZ => new V4f(-1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZXW => new V4f(-1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYO => new V4f(-1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYP => new V4f(-1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYN => new V4f(-1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYX => new V4f(-1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYY => new V4f(-1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYZ => new V4f(-1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZYW => new V4f(-1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZO => new V4f(-1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZP => new V4f(-1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZN => new V4f(-1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZX => new V4f(-1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZY => new V4f(-1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZZ => new V4f(-1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZZW => new V4f(-1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZWO => new V4f(-1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZWP => new V4f(-1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZWN => new V4f(-1, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZWX => new V4f(-1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZWY => new V4f(-1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZWZ => new V4f(-1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NZWW => new V4f(-1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWOO => new V4f(-1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWOP => new V4f(-1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWON => new V4f(-1, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWOX => new V4f(-1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWOY => new V4f(-1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWOZ => new V4f(-1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWOW => new V4f(-1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWPO => new V4f(-1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWPP => new V4f(-1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWPN => new V4f(-1, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWPX => new V4f(-1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWPY => new V4f(-1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWPZ => new V4f(-1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWPW => new V4f(-1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWNO => new V4f(-1, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWNP => new V4f(-1, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWNN => new V4f(-1, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWNX => new V4f(-1, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWNY => new V4f(-1, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWNZ => new V4f(-1, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWNW => new V4f(-1, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWXO => new V4f(-1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWXP => new V4f(-1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWXN => new V4f(-1, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWXX => new V4f(-1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWXY => new V4f(-1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWXZ => new V4f(-1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWXW => new V4f(-1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWYO => new V4f(-1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWYP => new V4f(-1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWYN => new V4f(-1, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWYX => new V4f(-1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWYY => new V4f(-1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWYZ => new V4f(-1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWYW => new V4f(-1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWZO => new V4f(-1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWZP => new V4f(-1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWZN => new V4f(-1, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWZX => new V4f(-1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWZY => new V4f(-1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWZZ => new V4f(-1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWZW => new V4f(-1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWWO => new V4f(-1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWWP => new V4f(-1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWWN => new V4f(-1, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWWX => new V4f(-1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWWY => new V4f(-1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWWZ => new V4f(-1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f NWWW => new V4f(-1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOO => new V4f(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOI => new V4f(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOON => new V4f(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOX => new V4f(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOY => new V4f(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOZ => new V4f(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOOW => new V4f(X, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIO => new V4f(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOII => new V4f(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOPN => new V4f(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIX => new V4f(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIY => new V4f(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIZ => new V4f(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOIW => new V4f(X, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONO => new V4f(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONP => new V4f(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONN => new V4f(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONX => new V4f(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONY => new V4f(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONZ => new V4f(X, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XONW => new V4f(X, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXO => new V4f(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXI => new V4f(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXN => new V4f(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXX => new V4f(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXY => new V4f(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXZ => new V4f(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOXW => new V4f(X, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYO => new V4f(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYI => new V4f(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYN => new V4f(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYX => new V4f(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYY => new V4f(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYZ => new V4f(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOYW => new V4f(X, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZO => new V4f(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZI => new V4f(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZN => new V4f(X, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZX => new V4f(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZY => new V4f(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZZ => new V4f(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOZW => new V4f(X, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOWO => new V4f(X, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOWI => new V4f(X, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOWN => new V4f(X, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOWX => new V4f(X, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOWY => new V4f(X, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOWZ => new V4f(X, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XOWW => new V4f(X, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOO => new V4f(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOI => new V4f(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPON => new V4f(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOX => new V4f(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOY => new V4f(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOZ => new V4f(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIOW => new V4f(X, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIO => new V4f(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIII => new V4f(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPPN => new V4f(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIX => new V4f(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIY => new V4f(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIZ => new V4f(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIIW => new V4f(X, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNO => new V4f(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNP => new V4f(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNN => new V4f(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNX => new V4f(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNY => new V4f(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNZ => new V4f(X, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPNW => new V4f(X, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXO => new V4f(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXI => new V4f(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPXN => new V4f(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXX => new V4f(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXY => new V4f(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXZ => new V4f(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIXW => new V4f(X, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYO => new V4f(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYI => new V4f(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPYN => new V4f(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYX => new V4f(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYY => new V4f(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYZ => new V4f(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIYW => new V4f(X, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZO => new V4f(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZI => new V4f(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPZN => new V4f(X, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZX => new V4f(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZY => new V4f(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZZ => new V4f(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIZW => new V4f(X, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIWO => new V4f(X, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIWI => new V4f(X, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XPWN => new V4f(X, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIWX => new V4f(X, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIWY => new V4f(X, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIWZ => new V4f(X, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XIWW => new V4f(X, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOO => new V4f(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOP => new V4f(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNON => new V4f(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOX => new V4f(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOY => new V4f(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOZ => new V4f(X, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNOW => new V4f(X, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPO => new V4f(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPP => new V4f(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPN => new V4f(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPX => new V4f(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPY => new V4f(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPZ => new V4f(X, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNPW => new V4f(X, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNO => new V4f(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNP => new V4f(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNN => new V4f(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNX => new V4f(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNY => new V4f(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNZ => new V4f(X, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNNW => new V4f(X, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXO => new V4f(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXP => new V4f(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXN => new V4f(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXX => new V4f(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXY => new V4f(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXZ => new V4f(X, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNXW => new V4f(X, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYO => new V4f(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYP => new V4f(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYN => new V4f(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYX => new V4f(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYY => new V4f(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYZ => new V4f(X, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNYW => new V4f(X, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZO => new V4f(X, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZP => new V4f(X, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZN => new V4f(X, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZX => new V4f(X, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZY => new V4f(X, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZZ => new V4f(X, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNZW => new V4f(X, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNWO => new V4f(X, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNWP => new V4f(X, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNWN => new V4f(X, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNWX => new V4f(X, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNWY => new V4f(X, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNWZ => new V4f(X, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XNWW => new V4f(X, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOO => new V4f(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOI => new V4f(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXON => new V4f(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOX => new V4f(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOY => new V4f(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOZ => new V4f(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXOW => new V4f(X, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIO => new V4f(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXII => new V4f(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXPN => new V4f(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIX => new V4f(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIY => new V4f(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIZ => new V4f(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXIW => new V4f(X, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNO => new V4f(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNP => new V4f(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNN => new V4f(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNX => new V4f(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNY => new V4f(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNZ => new V4f(X, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXNW => new V4f(X, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXO => new V4f(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXI => new V4f(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXN => new V4f(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXX => new V4f(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXY => new V4f(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXZ => new V4f(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXXW => new V4f(X, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYO => new V4f(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYI => new V4f(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYN => new V4f(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYX => new V4f(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYY => new V4f(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYZ => new V4f(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXYW => new V4f(X, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZO => new V4f(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZI => new V4f(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZN => new V4f(X, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZX => new V4f(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZY => new V4f(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZZ => new V4f(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXZW => new V4f(X, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXWO => new V4f(X, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXWI => new V4f(X, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXWN => new V4f(X, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXWX => new V4f(X, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXWY => new V4f(X, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXWZ => new V4f(X, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XXWW => new V4f(X, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOO => new V4f(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOI => new V4f(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYON => new V4f(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOX => new V4f(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOY => new V4f(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOZ => new V4f(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYOW => new V4f(X, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIO => new V4f(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYII => new V4f(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYPN => new V4f(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIX => new V4f(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIY => new V4f(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIZ => new V4f(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYIW => new V4f(X, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNO => new V4f(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNP => new V4f(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNN => new V4f(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNX => new V4f(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNY => new V4f(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNZ => new V4f(X, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYNW => new V4f(X, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXO => new V4f(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXI => new V4f(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXN => new V4f(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXX => new V4f(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXY => new V4f(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXZ => new V4f(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYXW => new V4f(X, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYO => new V4f(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYI => new V4f(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYN => new V4f(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYX => new V4f(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYY => new V4f(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYZ => new V4f(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYYW => new V4f(X, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZO => new V4f(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZI => new V4f(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZN => new V4f(X, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZX => new V4f(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZY => new V4f(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYZZ => new V4f(X, Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f XYZW\n        {\n            readonly get => new V4f(X, Y, Z, W);\n            set { X = value.X; Y = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYWO => new V4f(X, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYWI => new V4f(X, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYWN => new V4f(X, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYWX => new V4f(X, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYWY => new V4f(X, Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f XYWZ\n        {\n            readonly get => new V4f(X, Y, W, Z);\n            set { X = value.X; Y = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XYWW => new V4f(X, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOO => new V4f(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOI => new V4f(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZON => new V4f(X, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOX => new V4f(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOY => new V4f(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOZ => new V4f(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZOW => new V4f(X, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIO => new V4f(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZII => new V4f(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZPN => new V4f(X, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIX => new V4f(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIY => new V4f(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIZ => new V4f(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZIW => new V4f(X, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNO => new V4f(X, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNP => new V4f(X, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNN => new V4f(X, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNX => new V4f(X, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNY => new V4f(X, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNZ => new V4f(X, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZNW => new V4f(X, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXO => new V4f(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXI => new V4f(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXN => new V4f(X, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXX => new V4f(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXY => new V4f(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXZ => new V4f(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZXW => new V4f(X, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYO => new V4f(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYI => new V4f(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYN => new V4f(X, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYX => new V4f(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYY => new V4f(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZYZ => new V4f(X, Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f XZYW\n        {\n            readonly get => new V4f(X, Z, Y, W);\n            set { X = value.X; Z = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZO => new V4f(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZI => new V4f(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZN => new V4f(X, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZX => new V4f(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZY => new V4f(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZZ => new V4f(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZZW => new V4f(X, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZWO => new V4f(X, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZWI => new V4f(X, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZWN => new V4f(X, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZWX => new V4f(X, Z, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f XZWY\n        {\n            readonly get => new V4f(X, Z, W, Y);\n            set { X = value.X; Z = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZWZ => new V4f(X, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XZWW => new V4f(X, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWOO => new V4f(X, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWOI => new V4f(X, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWON => new V4f(X, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWOX => new V4f(X, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWOY => new V4f(X, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWOZ => new V4f(X, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWOW => new V4f(X, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWIO => new V4f(X, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWII => new V4f(X, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWPN => new V4f(X, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWIX => new V4f(X, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWIY => new V4f(X, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWIZ => new V4f(X, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWIW => new V4f(X, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWNO => new V4f(X, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWNP => new V4f(X, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWNN => new V4f(X, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWNX => new V4f(X, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWNY => new V4f(X, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWNZ => new V4f(X, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWNW => new V4f(X, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWXO => new V4f(X, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWXI => new V4f(X, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWXN => new V4f(X, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWXX => new V4f(X, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWXY => new V4f(X, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWXZ => new V4f(X, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWXW => new V4f(X, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWYO => new V4f(X, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWYI => new V4f(X, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWYN => new V4f(X, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWYX => new V4f(X, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWYY => new V4f(X, W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f XWYZ\n        {\n            readonly get => new V4f(X, W, Y, Z);\n            set { X = value.X; W = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWYW => new V4f(X, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWZO => new V4f(X, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWZI => new V4f(X, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWZN => new V4f(X, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWZX => new V4f(X, W, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f XWZY\n        {\n            readonly get => new V4f(X, W, Z, Y);\n            set { X = value.X; W = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWZZ => new V4f(X, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWZW => new V4f(X, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWWO => new V4f(X, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWWI => new V4f(X, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWWN => new V4f(X, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWWX => new V4f(X, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWWY => new V4f(X, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWWZ => new V4f(X, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f XWWW => new V4f(X, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOO => new V4f(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOI => new V4f(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOON => new V4f(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOX => new V4f(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOY => new V4f(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOZ => new V4f(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOOW => new V4f(Y, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIO => new V4f(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOII => new V4f(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOPN => new V4f(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIX => new V4f(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIY => new V4f(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIZ => new V4f(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOIW => new V4f(Y, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONO => new V4f(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONP => new V4f(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONN => new V4f(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONX => new V4f(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONY => new V4f(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONZ => new V4f(Y, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YONW => new V4f(Y, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXO => new V4f(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXI => new V4f(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXN => new V4f(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXX => new V4f(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXY => new V4f(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXZ => new V4f(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOXW => new V4f(Y, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYO => new V4f(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYI => new V4f(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYN => new V4f(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYX => new V4f(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYY => new V4f(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYZ => new V4f(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOYW => new V4f(Y, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZO => new V4f(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZI => new V4f(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZN => new V4f(Y, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZX => new V4f(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZY => new V4f(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZZ => new V4f(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOZW => new V4f(Y, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOWO => new V4f(Y, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOWI => new V4f(Y, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOWN => new V4f(Y, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOWX => new V4f(Y, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOWY => new V4f(Y, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOWZ => new V4f(Y, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YOWW => new V4f(Y, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOO => new V4f(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOI => new V4f(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPON => new V4f(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOX => new V4f(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOY => new V4f(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOZ => new V4f(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIOW => new V4f(Y, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIO => new V4f(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIII => new V4f(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPPN => new V4f(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIX => new V4f(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIY => new V4f(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIZ => new V4f(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIIW => new V4f(Y, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNO => new V4f(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNP => new V4f(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNN => new V4f(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNX => new V4f(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNY => new V4f(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNZ => new V4f(Y, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPNW => new V4f(Y, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXO => new V4f(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXI => new V4f(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPXN => new V4f(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXX => new V4f(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXY => new V4f(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXZ => new V4f(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIXW => new V4f(Y, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYO => new V4f(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYI => new V4f(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPYN => new V4f(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYX => new V4f(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYY => new V4f(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYZ => new V4f(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIYW => new V4f(Y, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZO => new V4f(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZI => new V4f(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPZN => new V4f(Y, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZX => new V4f(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZY => new V4f(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZZ => new V4f(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIZW => new V4f(Y, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIWO => new V4f(Y, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIWI => new V4f(Y, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YPWN => new V4f(Y, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIWX => new V4f(Y, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIWY => new V4f(Y, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIWZ => new V4f(Y, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YIWW => new V4f(Y, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOO => new V4f(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOP => new V4f(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNON => new V4f(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOX => new V4f(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOY => new V4f(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOZ => new V4f(Y, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNOW => new V4f(Y, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPO => new V4f(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPP => new V4f(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPN => new V4f(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPX => new V4f(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPY => new V4f(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPZ => new V4f(Y, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNPW => new V4f(Y, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNO => new V4f(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNP => new V4f(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNN => new V4f(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNX => new V4f(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNY => new V4f(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNZ => new V4f(Y, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNNW => new V4f(Y, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXO => new V4f(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXP => new V4f(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXN => new V4f(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXX => new V4f(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXY => new V4f(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXZ => new V4f(Y, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNXW => new V4f(Y, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYO => new V4f(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYP => new V4f(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYN => new V4f(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYX => new V4f(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYY => new V4f(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYZ => new V4f(Y, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNYW => new V4f(Y, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZO => new V4f(Y, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZP => new V4f(Y, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZN => new V4f(Y, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZX => new V4f(Y, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZY => new V4f(Y, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZZ => new V4f(Y, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNZW => new V4f(Y, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNWO => new V4f(Y, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNWP => new V4f(Y, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNWN => new V4f(Y, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNWX => new V4f(Y, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNWY => new V4f(Y, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNWZ => new V4f(Y, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YNWW => new V4f(Y, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOO => new V4f(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOI => new V4f(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXON => new V4f(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOX => new V4f(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOY => new V4f(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOZ => new V4f(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXOW => new V4f(Y, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIO => new V4f(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXII => new V4f(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXPN => new V4f(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIX => new V4f(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIY => new V4f(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIZ => new V4f(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXIW => new V4f(Y, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNO => new V4f(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNP => new V4f(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNN => new V4f(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNX => new V4f(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNY => new V4f(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNZ => new V4f(Y, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXNW => new V4f(Y, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXO => new V4f(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXI => new V4f(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXN => new V4f(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXX => new V4f(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXY => new V4f(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXZ => new V4f(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXXW => new V4f(Y, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYO => new V4f(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYI => new V4f(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYN => new V4f(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYX => new V4f(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYY => new V4f(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYZ => new V4f(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXYW => new V4f(Y, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZO => new V4f(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZI => new V4f(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZN => new V4f(Y, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZX => new V4f(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZY => new V4f(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXZZ => new V4f(Y, X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f YXZW\n        {\n            readonly get => new V4f(Y, X, Z, W);\n            set { Y = value.X; X = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXWO => new V4f(Y, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXWI => new V4f(Y, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXWN => new V4f(Y, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXWX => new V4f(Y, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXWY => new V4f(Y, X, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f YXWZ\n        {\n            readonly get => new V4f(Y, X, W, Z);\n            set { Y = value.X; X = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YXWW => new V4f(Y, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOO => new V4f(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOI => new V4f(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYON => new V4f(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOX => new V4f(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOY => new V4f(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOZ => new V4f(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYOW => new V4f(Y, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIO => new V4f(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYII => new V4f(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYPN => new V4f(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIX => new V4f(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIY => new V4f(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIZ => new V4f(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYIW => new V4f(Y, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNO => new V4f(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNP => new V4f(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNN => new V4f(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNX => new V4f(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNY => new V4f(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNZ => new V4f(Y, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYNW => new V4f(Y, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXO => new V4f(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXI => new V4f(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXN => new V4f(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXX => new V4f(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXY => new V4f(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXZ => new V4f(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYXW => new V4f(Y, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYO => new V4f(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYI => new V4f(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYN => new V4f(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYX => new V4f(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYY => new V4f(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYZ => new V4f(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYYW => new V4f(Y, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZO => new V4f(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZI => new V4f(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZN => new V4f(Y, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZX => new V4f(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZY => new V4f(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZZ => new V4f(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYZW => new V4f(Y, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYWO => new V4f(Y, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYWI => new V4f(Y, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYWN => new V4f(Y, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYWX => new V4f(Y, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYWY => new V4f(Y, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYWZ => new V4f(Y, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YYWW => new V4f(Y, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOO => new V4f(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOI => new V4f(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZON => new V4f(Y, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOX => new V4f(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOY => new V4f(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOZ => new V4f(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZOW => new V4f(Y, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIO => new V4f(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZII => new V4f(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZPN => new V4f(Y, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIX => new V4f(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIY => new V4f(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIZ => new V4f(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZIW => new V4f(Y, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNO => new V4f(Y, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNP => new V4f(Y, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNN => new V4f(Y, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNX => new V4f(Y, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNY => new V4f(Y, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNZ => new V4f(Y, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZNW => new V4f(Y, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXO => new V4f(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXI => new V4f(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXN => new V4f(Y, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXX => new V4f(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXY => new V4f(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZXZ => new V4f(Y, Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f YZXW\n        {\n            readonly get => new V4f(Y, Z, X, W);\n            set { Y = value.X; Z = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYO => new V4f(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYI => new V4f(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYN => new V4f(Y, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYX => new V4f(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYY => new V4f(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYZ => new V4f(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZYW => new V4f(Y, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZO => new V4f(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZI => new V4f(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZN => new V4f(Y, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZX => new V4f(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZY => new V4f(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZZ => new V4f(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZZW => new V4f(Y, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZWO => new V4f(Y, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZWI => new V4f(Y, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZWN => new V4f(Y, Z, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f YZWX\n        {\n            readonly get => new V4f(Y, Z, W, X);\n            set { Y = value.X; Z = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZWY => new V4f(Y, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZWZ => new V4f(Y, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YZWW => new V4f(Y, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWOO => new V4f(Y, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWOI => new V4f(Y, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWON => new V4f(Y, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWOX => new V4f(Y, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWOY => new V4f(Y, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWOZ => new V4f(Y, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWOW => new V4f(Y, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWIO => new V4f(Y, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWII => new V4f(Y, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWPN => new V4f(Y, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWIX => new V4f(Y, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWIY => new V4f(Y, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWIZ => new V4f(Y, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWIW => new V4f(Y, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWNO => new V4f(Y, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWNP => new V4f(Y, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWNN => new V4f(Y, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWNX => new V4f(Y, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWNY => new V4f(Y, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWNZ => new V4f(Y, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWNW => new V4f(Y, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWXO => new V4f(Y, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWXI => new V4f(Y, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWXN => new V4f(Y, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWXX => new V4f(Y, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWXY => new V4f(Y, W, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f YWXZ\n        {\n            readonly get => new V4f(Y, W, X, Z);\n            set { Y = value.X; W = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWXW => new V4f(Y, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWYO => new V4f(Y, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWYI => new V4f(Y, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWYN => new V4f(Y, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWYX => new V4f(Y, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWYY => new V4f(Y, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWYZ => new V4f(Y, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWYW => new V4f(Y, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWZO => new V4f(Y, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWZI => new V4f(Y, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWZN => new V4f(Y, W, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f YWZX\n        {\n            readonly get => new V4f(Y, W, Z, X);\n            set { Y = value.X; W = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWZY => new V4f(Y, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWZZ => new V4f(Y, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWZW => new V4f(Y, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWWO => new V4f(Y, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWWI => new V4f(Y, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWWN => new V4f(Y, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWWX => new V4f(Y, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWWY => new V4f(Y, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWWZ => new V4f(Y, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f YWWW => new V4f(Y, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOO => new V4f(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOI => new V4f(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOON => new V4f(Z, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOX => new V4f(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOY => new V4f(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOZ => new V4f(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOOW => new V4f(Z, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIO => new V4f(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOII => new V4f(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOPN => new V4f(Z, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIX => new V4f(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIY => new V4f(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIZ => new V4f(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOIW => new V4f(Z, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONO => new V4f(Z, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONP => new V4f(Z, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONN => new V4f(Z, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONX => new V4f(Z, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONY => new V4f(Z, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONZ => new V4f(Z, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZONW => new V4f(Z, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXO => new V4f(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXI => new V4f(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXN => new V4f(Z, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXX => new V4f(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXY => new V4f(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXZ => new V4f(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOXW => new V4f(Z, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYO => new V4f(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYI => new V4f(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYN => new V4f(Z, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYX => new V4f(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYY => new V4f(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYZ => new V4f(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOYW => new V4f(Z, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZO => new V4f(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZI => new V4f(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZN => new V4f(Z, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZX => new V4f(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZY => new V4f(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZZ => new V4f(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOZW => new V4f(Z, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOWO => new V4f(Z, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOWI => new V4f(Z, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOWN => new V4f(Z, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOWX => new V4f(Z, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOWY => new V4f(Z, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOWZ => new V4f(Z, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZOWW => new V4f(Z, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOO => new V4f(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOI => new V4f(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPON => new V4f(Z, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOX => new V4f(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOY => new V4f(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOZ => new V4f(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIOW => new V4f(Z, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIO => new V4f(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIII => new V4f(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPPN => new V4f(Z, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIX => new V4f(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIY => new V4f(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIZ => new V4f(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIIW => new V4f(Z, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNO => new V4f(Z, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNP => new V4f(Z, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNN => new V4f(Z, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNX => new V4f(Z, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNY => new V4f(Z, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNZ => new V4f(Z, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPNW => new V4f(Z, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXO => new V4f(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXI => new V4f(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPXN => new V4f(Z, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXX => new V4f(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXY => new V4f(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXZ => new V4f(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIXW => new V4f(Z, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYO => new V4f(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYI => new V4f(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPYN => new V4f(Z, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYX => new V4f(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYY => new V4f(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYZ => new V4f(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIYW => new V4f(Z, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZO => new V4f(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZI => new V4f(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPZN => new V4f(Z, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZX => new V4f(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZY => new V4f(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZZ => new V4f(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIZW => new V4f(Z, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIWO => new V4f(Z, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIWI => new V4f(Z, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZPWN => new V4f(Z, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIWX => new V4f(Z, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIWY => new V4f(Z, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIWZ => new V4f(Z, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZIWW => new V4f(Z, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOO => new V4f(Z, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOP => new V4f(Z, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNON => new V4f(Z, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOX => new V4f(Z, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOY => new V4f(Z, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOZ => new V4f(Z, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNOW => new V4f(Z, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPO => new V4f(Z, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPP => new V4f(Z, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPN => new V4f(Z, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPX => new V4f(Z, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPY => new V4f(Z, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPZ => new V4f(Z, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNPW => new V4f(Z, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNO => new V4f(Z, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNP => new V4f(Z, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNN => new V4f(Z, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNX => new V4f(Z, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNY => new V4f(Z, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNZ => new V4f(Z, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNNW => new V4f(Z, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXO => new V4f(Z, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXP => new V4f(Z, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXN => new V4f(Z, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXX => new V4f(Z, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXY => new V4f(Z, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXZ => new V4f(Z, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNXW => new V4f(Z, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYO => new V4f(Z, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYP => new V4f(Z, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYN => new V4f(Z, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYX => new V4f(Z, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYY => new V4f(Z, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYZ => new V4f(Z, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNYW => new V4f(Z, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZO => new V4f(Z, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZP => new V4f(Z, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZN => new V4f(Z, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZX => new V4f(Z, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZY => new V4f(Z, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZZ => new V4f(Z, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNZW => new V4f(Z, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNWO => new V4f(Z, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNWP => new V4f(Z, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNWN => new V4f(Z, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNWX => new V4f(Z, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNWY => new V4f(Z, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNWZ => new V4f(Z, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZNWW => new V4f(Z, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOO => new V4f(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOI => new V4f(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXON => new V4f(Z, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOX => new V4f(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOY => new V4f(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOZ => new V4f(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXOW => new V4f(Z, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIO => new V4f(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXII => new V4f(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXPN => new V4f(Z, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIX => new V4f(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIY => new V4f(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIZ => new V4f(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXIW => new V4f(Z, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNO => new V4f(Z, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNP => new V4f(Z, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNN => new V4f(Z, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNX => new V4f(Z, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNY => new V4f(Z, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNZ => new V4f(Z, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXNW => new V4f(Z, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXO => new V4f(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXI => new V4f(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXN => new V4f(Z, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXX => new V4f(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXY => new V4f(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXZ => new V4f(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXXW => new V4f(Z, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYO => new V4f(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYI => new V4f(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYN => new V4f(Z, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYX => new V4f(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYY => new V4f(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXYZ => new V4f(Z, X, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f ZXYW\n        {\n            readonly get => new V4f(Z, X, Y, W);\n            set { Z = value.X; X = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZO => new V4f(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZI => new V4f(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZN => new V4f(Z, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZX => new V4f(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZY => new V4f(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZZ => new V4f(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXZW => new V4f(Z, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXWO => new V4f(Z, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXWI => new V4f(Z, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXWN => new V4f(Z, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXWX => new V4f(Z, X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f ZXWY\n        {\n            readonly get => new V4f(Z, X, W, Y);\n            set { Z = value.X; X = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXWZ => new V4f(Z, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZXWW => new V4f(Z, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOO => new V4f(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOI => new V4f(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYON => new V4f(Z, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOX => new V4f(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOY => new V4f(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOZ => new V4f(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYOW => new V4f(Z, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIO => new V4f(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYII => new V4f(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYPN => new V4f(Z, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIX => new V4f(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIY => new V4f(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIZ => new V4f(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYIW => new V4f(Z, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNO => new V4f(Z, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNP => new V4f(Z, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNN => new V4f(Z, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNX => new V4f(Z, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNY => new V4f(Z, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNZ => new V4f(Z, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYNW => new V4f(Z, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXO => new V4f(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXI => new V4f(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXN => new V4f(Z, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXX => new V4f(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXY => new V4f(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYXZ => new V4f(Z, Y, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f ZYXW\n        {\n            readonly get => new V4f(Z, Y, X, W);\n            set { Z = value.X; Y = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYO => new V4f(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYI => new V4f(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYN => new V4f(Z, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYX => new V4f(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYY => new V4f(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYZ => new V4f(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYYW => new V4f(Z, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZO => new V4f(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZI => new V4f(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZN => new V4f(Z, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZX => new V4f(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZY => new V4f(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZZ => new V4f(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYZW => new V4f(Z, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYWO => new V4f(Z, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYWI => new V4f(Z, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYWN => new V4f(Z, Y, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f ZYWX\n        {\n            readonly get => new V4f(Z, Y, W, X);\n            set { Z = value.X; Y = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYWY => new V4f(Z, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYWZ => new V4f(Z, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZYWW => new V4f(Z, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOO => new V4f(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOI => new V4f(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZON => new V4f(Z, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOX => new V4f(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOY => new V4f(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOZ => new V4f(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZOW => new V4f(Z, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIO => new V4f(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZII => new V4f(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZPN => new V4f(Z, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIX => new V4f(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIY => new V4f(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIZ => new V4f(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZIW => new V4f(Z, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNO => new V4f(Z, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNP => new V4f(Z, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNN => new V4f(Z, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNX => new V4f(Z, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNY => new V4f(Z, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNZ => new V4f(Z, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZNW => new V4f(Z, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXO => new V4f(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXI => new V4f(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXN => new V4f(Z, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXX => new V4f(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXY => new V4f(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXZ => new V4f(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZXW => new V4f(Z, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYO => new V4f(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYI => new V4f(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYN => new V4f(Z, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYX => new V4f(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYY => new V4f(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYZ => new V4f(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZYW => new V4f(Z, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZO => new V4f(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZI => new V4f(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZN => new V4f(Z, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZX => new V4f(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZY => new V4f(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZZ => new V4f(Z, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZZW => new V4f(Z, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZWO => new V4f(Z, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZWI => new V4f(Z, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZWN => new V4f(Z, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZWX => new V4f(Z, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZWY => new V4f(Z, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZWZ => new V4f(Z, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZZWW => new V4f(Z, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWOO => new V4f(Z, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWOI => new V4f(Z, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWON => new V4f(Z, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWOX => new V4f(Z, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWOY => new V4f(Z, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWOZ => new V4f(Z, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWOW => new V4f(Z, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWIO => new V4f(Z, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWII => new V4f(Z, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWPN => new V4f(Z, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWIX => new V4f(Z, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWIY => new V4f(Z, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWIZ => new V4f(Z, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWIW => new V4f(Z, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWNO => new V4f(Z, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWNP => new V4f(Z, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWNN => new V4f(Z, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWNX => new V4f(Z, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWNY => new V4f(Z, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWNZ => new V4f(Z, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWNW => new V4f(Z, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWXO => new V4f(Z, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWXI => new V4f(Z, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWXN => new V4f(Z, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWXX => new V4f(Z, W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f ZWXY\n        {\n            readonly get => new V4f(Z, W, X, Y);\n            set { Z = value.X; W = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWXZ => new V4f(Z, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWXW => new V4f(Z, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWYO => new V4f(Z, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWYI => new V4f(Z, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWYN => new V4f(Z, W, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f ZWYX\n        {\n            readonly get => new V4f(Z, W, Y, X);\n            set { Z = value.X; W = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWYY => new V4f(Z, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWYZ => new V4f(Z, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWYW => new V4f(Z, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWZO => new V4f(Z, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWZI => new V4f(Z, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWZN => new V4f(Z, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWZX => new V4f(Z, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWZY => new V4f(Z, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWZZ => new V4f(Z, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWZW => new V4f(Z, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWWO => new V4f(Z, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWWI => new V4f(Z, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWWN => new V4f(Z, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWWX => new V4f(Z, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWWY => new V4f(Z, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWWZ => new V4f(Z, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f ZWWW => new V4f(Z, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOOO => new V4f(W, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOOI => new V4f(W, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOON => new V4f(W, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOOX => new V4f(W, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOOY => new V4f(W, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOOZ => new V4f(W, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOOW => new V4f(W, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOIO => new V4f(W, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOII => new V4f(W, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOPN => new V4f(W, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOIX => new V4f(W, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOIY => new V4f(W, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOIZ => new V4f(W, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOIW => new V4f(W, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WONO => new V4f(W, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WONP => new V4f(W, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WONN => new V4f(W, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WONX => new V4f(W, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WONY => new V4f(W, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WONZ => new V4f(W, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WONW => new V4f(W, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOXO => new V4f(W, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOXI => new V4f(W, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOXN => new V4f(W, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOXX => new V4f(W, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOXY => new V4f(W, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOXZ => new V4f(W, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOXW => new V4f(W, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOYO => new V4f(W, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOYI => new V4f(W, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOYN => new V4f(W, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOYX => new V4f(W, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOYY => new V4f(W, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOYZ => new V4f(W, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOYW => new V4f(W, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOZO => new V4f(W, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOZI => new V4f(W, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOZN => new V4f(W, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOZX => new V4f(W, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOZY => new V4f(W, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOZZ => new V4f(W, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOZW => new V4f(W, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOWO => new V4f(W, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOWI => new V4f(W, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOWN => new V4f(W, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOWX => new V4f(W, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOWY => new V4f(W, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOWZ => new V4f(W, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WOWW => new V4f(W, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIOO => new V4f(W, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIOI => new V4f(W, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPON => new V4f(W, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIOX => new V4f(W, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIOY => new V4f(W, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIOZ => new V4f(W, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIOW => new V4f(W, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIIO => new V4f(W, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIII => new V4f(W, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPPN => new V4f(W, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIIX => new V4f(W, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIIY => new V4f(W, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIIZ => new V4f(W, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIIW => new V4f(W, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPNO => new V4f(W, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPNP => new V4f(W, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPNN => new V4f(W, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPNX => new V4f(W, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPNY => new V4f(W, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPNZ => new V4f(W, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPNW => new V4f(W, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIXO => new V4f(W, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIXI => new V4f(W, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPXN => new V4f(W, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIXX => new V4f(W, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIXY => new V4f(W, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIXZ => new V4f(W, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIXW => new V4f(W, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIYO => new V4f(W, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIYI => new V4f(W, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPYN => new V4f(W, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIYX => new V4f(W, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIYY => new V4f(W, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIYZ => new V4f(W, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIYW => new V4f(W, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIZO => new V4f(W, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIZI => new V4f(W, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPZN => new V4f(W, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIZX => new V4f(W, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIZY => new V4f(W, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIZZ => new V4f(W, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIZW => new V4f(W, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIWO => new V4f(W, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIWI => new V4f(W, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WPWN => new V4f(W, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIWX => new V4f(W, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIWY => new V4f(W, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIWZ => new V4f(W, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WIWW => new V4f(W, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNOO => new V4f(W, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNOP => new V4f(W, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNON => new V4f(W, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNOX => new V4f(W, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNOY => new V4f(W, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNOZ => new V4f(W, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNOW => new V4f(W, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNPO => new V4f(W, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNPP => new V4f(W, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNPN => new V4f(W, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNPX => new V4f(W, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNPY => new V4f(W, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNPZ => new V4f(W, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNPW => new V4f(W, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNNO => new V4f(W, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNNP => new V4f(W, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNNN => new V4f(W, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNNX => new V4f(W, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNNY => new V4f(W, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNNZ => new V4f(W, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNNW => new V4f(W, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNXO => new V4f(W, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNXP => new V4f(W, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNXN => new V4f(W, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNXX => new V4f(W, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNXY => new V4f(W, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNXZ => new V4f(W, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNXW => new V4f(W, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNYO => new V4f(W, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNYP => new V4f(W, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNYN => new V4f(W, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNYX => new V4f(W, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNYY => new V4f(W, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNYZ => new V4f(W, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNYW => new V4f(W, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNZO => new V4f(W, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNZP => new V4f(W, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNZN => new V4f(W, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNZX => new V4f(W, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNZY => new V4f(W, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNZZ => new V4f(W, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNZW => new V4f(W, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNWO => new V4f(W, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNWP => new V4f(W, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNWN => new V4f(W, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNWX => new V4f(W, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNWY => new V4f(W, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNWZ => new V4f(W, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WNWW => new V4f(W, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXOO => new V4f(W, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXOI => new V4f(W, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXON => new V4f(W, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXOX => new V4f(W, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXOY => new V4f(W, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXOZ => new V4f(W, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXOW => new V4f(W, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXIO => new V4f(W, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXII => new V4f(W, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXPN => new V4f(W, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXIX => new V4f(W, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXIY => new V4f(W, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXIZ => new V4f(W, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXIW => new V4f(W, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXNO => new V4f(W, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXNP => new V4f(W, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXNN => new V4f(W, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXNX => new V4f(W, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXNY => new V4f(W, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXNZ => new V4f(W, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXNW => new V4f(W, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXXO => new V4f(W, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXXI => new V4f(W, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXXN => new V4f(W, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXXX => new V4f(W, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXXY => new V4f(W, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXXZ => new V4f(W, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXXW => new V4f(W, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXYO => new V4f(W, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXYI => new V4f(W, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXYN => new V4f(W, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXYX => new V4f(W, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXYY => new V4f(W, X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f WXYZ\n        {\n            readonly get => new V4f(W, X, Y, Z);\n            set { W = value.X; X = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXYW => new V4f(W, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXZO => new V4f(W, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXZI => new V4f(W, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXZN => new V4f(W, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXZX => new V4f(W, X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f WXZY\n        {\n            readonly get => new V4f(W, X, Z, Y);\n            set { W = value.X; X = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXZZ => new V4f(W, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXZW => new V4f(W, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXWO => new V4f(W, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXWI => new V4f(W, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXWN => new V4f(W, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXWX => new V4f(W, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXWY => new V4f(W, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXWZ => new V4f(W, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WXWW => new V4f(W, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYOO => new V4f(W, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYOI => new V4f(W, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYON => new V4f(W, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYOX => new V4f(W, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYOY => new V4f(W, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYOZ => new V4f(W, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYOW => new V4f(W, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYIO => new V4f(W, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYII => new V4f(W, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYPN => new V4f(W, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYIX => new V4f(W, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYIY => new V4f(W, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYIZ => new V4f(W, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYIW => new V4f(W, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYNO => new V4f(W, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYNP => new V4f(W, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYNN => new V4f(W, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYNX => new V4f(W, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYNY => new V4f(W, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYNZ => new V4f(W, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYNW => new V4f(W, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYXO => new V4f(W, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYXI => new V4f(W, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYXN => new V4f(W, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYXX => new V4f(W, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYXY => new V4f(W, Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f WYXZ\n        {\n            readonly get => new V4f(W, Y, X, Z);\n            set { W = value.X; Y = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYXW => new V4f(W, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYYO => new V4f(W, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYYI => new V4f(W, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYYN => new V4f(W, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYYX => new V4f(W, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYYY => new V4f(W, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYYZ => new V4f(W, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYYW => new V4f(W, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYZO => new V4f(W, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYZI => new V4f(W, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYZN => new V4f(W, Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f WYZX\n        {\n            readonly get => new V4f(W, Y, Z, X);\n            set { W = value.X; Y = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYZY => new V4f(W, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYZZ => new V4f(W, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYZW => new V4f(W, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYWO => new V4f(W, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYWI => new V4f(W, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYWN => new V4f(W, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYWX => new V4f(W, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYWY => new V4f(W, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYWZ => new V4f(W, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WYWW => new V4f(W, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZOO => new V4f(W, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZOI => new V4f(W, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZON => new V4f(W, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZOX => new V4f(W, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZOY => new V4f(W, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZOZ => new V4f(W, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZOW => new V4f(W, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZIO => new V4f(W, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZII => new V4f(W, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZPN => new V4f(W, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZIX => new V4f(W, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZIY => new V4f(W, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZIZ => new V4f(W, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZIW => new V4f(W, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZNO => new V4f(W, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZNP => new V4f(W, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZNN => new V4f(W, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZNX => new V4f(W, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZNY => new V4f(W, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZNZ => new V4f(W, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZNW => new V4f(W, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZXO => new V4f(W, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZXI => new V4f(W, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZXN => new V4f(W, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZXX => new V4f(W, Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f WZXY\n        {\n            readonly get => new V4f(W, Z, X, Y);\n            set { W = value.X; Z = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZXZ => new V4f(W, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZXW => new V4f(W, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZYO => new V4f(W, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZYI => new V4f(W, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZYN => new V4f(W, Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4f WZYX\n        {\n            readonly get => new V4f(W, Z, Y, X);\n            set { W = value.X; Z = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZYY => new V4f(W, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZYZ => new V4f(W, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZYW => new V4f(W, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZZO => new V4f(W, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZZI => new V4f(W, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZZN => new V4f(W, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZZX => new V4f(W, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZZY => new V4f(W, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZZZ => new V4f(W, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZZW => new V4f(W, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZWO => new V4f(W, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZWI => new V4f(W, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZWN => new V4f(W, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZWX => new V4f(W, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZWY => new V4f(W, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZWZ => new V4f(W, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WZWW => new V4f(W, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWOO => new V4f(W, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWOI => new V4f(W, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWON => new V4f(W, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWOX => new V4f(W, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWOY => new V4f(W, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWOZ => new V4f(W, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWOW => new V4f(W, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWIO => new V4f(W, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWII => new V4f(W, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWPN => new V4f(W, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWIX => new V4f(W, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWIY => new V4f(W, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWIZ => new V4f(W, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWIW => new V4f(W, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWNO => new V4f(W, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWNP => new V4f(W, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWNN => new V4f(W, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWNX => new V4f(W, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWNY => new V4f(W, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWNZ => new V4f(W, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWNW => new V4f(W, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWXO => new V4f(W, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWXI => new V4f(W, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWXN => new V4f(W, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWXX => new V4f(W, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWXY => new V4f(W, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWXZ => new V4f(W, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWXW => new V4f(W, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWYO => new V4f(W, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWYI => new V4f(W, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWYN => new V4f(W, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWYX => new V4f(W, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWYY => new V4f(W, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWYZ => new V4f(W, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWYW => new V4f(W, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWZO => new V4f(W, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWZI => new V4f(W, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWZN => new V4f(W, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWZX => new V4f(W, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWZY => new V4f(W, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWZZ => new V4f(W, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWZW => new V4f(W, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWWO => new V4f(W, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWWI => new V4f(W, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWWN => new V4f(W, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWWX => new V4f(W, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWWY => new V4f(W, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWWZ => new V4f(W, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4f WWWW => new V4f(W, W, W, W);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (float)value; }\n        }\n\n        #endregion\n\n        #region ISize4f Members\n\n        public readonly V4f Size4f { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 4; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (float)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V4fEqualityComparer : IEqualityComparer<V4f>\n    {\n        public static V4fEqualityComparer Default\n            => new V4fEqualityComparer();\n\n        #region IEqualityComparer<V4f> Members\n\n        public bool Equals(V4f v0, V4f v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V4f v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Min(this V4f a, V4f b)\n        {\n            return new V4f(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z), Min(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Min(this V4f a, float b)\n        {\n            return new V4f(Min(a.X, b), Min(a.Y, b), Min(a.Z, b), Min(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Min(this float a, V4f b)\n        {\n            return new V4f(Min(a, b.X), Min(a, b.Y), Min(a, b.Z), Min(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Max(this V4f a, V4f b)\n        {\n            return new V4f(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z), Max(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Max(this V4f a, float b)\n        {\n            return new V4f(Max(a.X, b), Max(a.Y, b), Max(a.Z, b), Max(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Max(this float a, V4f b)\n        {\n            return new V4f(Max(a, b.X), Max(a, b.Y), Max(a, b.Z), Max(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Min(this V4f a, V4f b, V4f c)\n        {\n            return new V4f(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z), Min(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Max(this V4f a, V4f b, V4f c)\n        {\n            return new V4f(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z), Max(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Min(this V4f a, V4f b, V4f c, V4f d)\n        {\n            return new V4f(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z), Min(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Max(this V4f a, V4f b, V4f c, V4f d)\n        {\n            return new V4f(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z), Max(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Min(this V4f x, params V4f[] values)\n        {\n            return new V4f(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)), Min(x.W, values.Map(a => a.W)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Max(this V4f x, params V4f[] values)\n        {\n            return new V4f(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)), Max(x.W, values.Map(a => a.W)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Abs(this V4f x)\n        {\n            return new V4f(Abs(x.X), Abs(x.Y), Abs(x.Z), Abs(x.W));\n        }\n\n        #endregion\n\n        #region Rounding\n\n        /// <summary>\n        /// Applies Fun.Floor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Floor(this V4f x)\n        {\n            return new V4f(Floor(x.X), Floor(x.Y), Floor(x.Z), Floor(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Ceiling to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Ceiling(this V4f x)\n        {\n            return new V4f(Ceiling(x.X), Ceiling(x.Y), Ceiling(x.Z), Ceiling(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Round(this V4f x)\n        {\n            return new V4f(Round(x.X), Round(x.Y), Round(x.Z), Round(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Round(this V4f x, MidpointRounding mode)\n        {\n            return new V4f(Round(x.X, mode), Round(x.Y, mode), Round(x.Z, mode), Round(x.W, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Round(this V4f x, int digits)\n        {\n            return new V4f(Round(x.X, digits), Round(x.Y, digits), Round(x.Z, digits), Round(x.W, digits));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Round(this V4f x, int digits, MidpointRounding mode)\n        {\n            return new V4f(Round(x.X, digits, mode), Round(x.Y, digits, mode), Round(x.Z, digits, mode), Round(x.W, digits, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Truncate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Truncate(this V4f x)\n        {\n            return new V4f(Truncate(x.X), Truncate(x.Y), Truncate(x.Z), Truncate(x.W));\n        }\n\n        #endregion\n\n        #region Frac\n\n        /// <summary>\n        /// Applies Fun.Frac to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Frac(this V4f x)\n        {\n            return new V4f(Frac(x.X), Frac(x.Y), Frac(x.Z), Frac(x.W));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Clamp(this V4f x, V4f a, V4f b)\n        {\n            return new V4f(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z), Clamp(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Clamp(this V4f x, float a, float b)\n        {\n            return new V4f(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b), Clamp(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f ClampWrap(this V4f x, V4f a, V4f b)\n        {\n            return new V4f(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z), ClampWrap(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f ClampWrap(this V4f x, float a, float b)\n        {\n            return new V4f(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b), ClampWrap(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Saturate(this V4f x)\n        {\n            return new V4f(Saturate(x.X), Saturate(x.Y), Saturate(x.Z), Saturate(x.W));\n        }\n\n        #endregion\n\n        #region MapToUnitInterval\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f MapToUnitInterval(this V4f t, V4f tMax, bool repeat, bool mirror)\n        {\n            return new V4f(MapToUnitInterval(t.X, tMax.X, repeat, mirror), MapToUnitInterval(t.Y, tMax.Y, repeat, mirror), MapToUnitInterval(t.Z, tMax.Z, repeat, mirror), MapToUnitInterval(t.W, tMax.W, repeat, mirror));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f MapToUnitInterval(this V4f t, V4f tMax, bool repeat)\n        {\n            return new V4f(MapToUnitInterval(t.X, tMax.X, repeat), MapToUnitInterval(t.Y, tMax.Y, repeat), MapToUnitInterval(t.Z, tMax.Z, repeat), MapToUnitInterval(t.W, tMax.W, repeat));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f MapToUnitInterval(this V4f t, V4f tMax)\n        {\n            return new V4f(MapToUnitInterval(t.X, tMax.X), MapToUnitInterval(t.Y, tMax.Y), MapToUnitInterval(t.Z, tMax.Z), MapToUnitInterval(t.W, tMax.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f MapToUnitInterval(this V4f t, V4f tMin, V4f tMax)\n        {\n            return new V4f(MapToUnitInterval(t.X, tMin.X, tMax.X), MapToUnitInterval(t.Y, tMin.Y, tMax.Y), MapToUnitInterval(t.Z, tMin.Z, tMax.Z), MapToUnitInterval(t.W, tMin.W, tMax.W));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Sign(this V4f x)\n        {\n            return new V4i(Sign(x.X), Sign(x.Y), Sign(x.Z), Sign(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Signumi(this V4f x)\n        {\n            return new V4i(Signumi(x.X), Signumi(x.Y), Signumi(x.Z), Signumi(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Signum(this V4f x)\n        {\n            return new V4f(Signum(x.X), Signum(x.Y), Signum(x.Z), Signum(x.W));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f MultiplyAdd(V4f x, V4f y, V4f z)\n        {\n            return new V4f(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z), MultiplyAdd(x.W, y.W, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f MultiplyAdd(V4f x, float y, V4f z)\n        {\n            return new V4f(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z), MultiplyAdd(x.W, y, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f MultiplyAdd(float x, V4f y, V4f z)\n        {\n            return new V4f(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z), MultiplyAdd(x, y.W, z.W));\n        }\n\n        #endregion\n\n        #region Copy sign\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f CopySign(V4f value, V4f sign)\n        {\n            return new V4f(CopySign(value.X, sign.X), CopySign(value.Y, sign.Y), CopySign(value.Z, sign.Z), CopySign(value.W, sign.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f CopySign(float value, V4f sign)\n        {\n            return new V4f(CopySign(value, sign.X), CopySign(value, sign.Y), CopySign(value, sign.Z), CopySign(value, sign.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f CopySign(V4f value, float sign)\n        {\n            return new V4f(CopySign(value.X, sign), CopySign(value.Y, sign), CopySign(value.Z, sign), CopySign(value.W, sign));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Sqrt(this V4f x)\n        {\n            return new V4f(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z), Sqrt(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Cbrt(this V4f x)\n        {\n            return new V4f(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z), Cbrt(x.W));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Square(this V4f x)\n        {\n            return new V4f(Square(x.X), Square(x.Y), Square(x.Z), Square(x.W));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pown(this V4f x, V4i y)\n        {\n            return new V4f(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z), Pown(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pown(this V4f x, int y)\n        {\n            return new V4f(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y), Pown(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pown(this float x, V4i y)\n        {\n            return new V4f(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z), Pown(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this V4f x, V4f y)\n        {\n            return new V4f(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z), Pow(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this V4f x, float y)\n        {\n            return new V4f(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y), Pow(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Pow(this float x, V4f y)\n        {\n            return new V4f(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z), Pow(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this V4f x, V4f y)\n        {\n            return new V4f(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z), Power(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this V4f x, float y)\n        {\n            return new V4f(Power(x.X, y), Power(x.Y, y), Power(x.Z, y), Power(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Power(this float x, V4f y)\n        {\n            return new V4f(Power(x, y.X), Power(x, y.Y), Power(x, y.Z), Power(x, y.W));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Exp(this V4f x)\n        {\n            return new V4f(Exp(x.X), Exp(x.Y), Exp(x.Z), Exp(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Log(this V4f x)\n        {\n            return new V4f(Log(x.X), Log(x.Y), Log(x.Z), Log(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Log2(this V4f x)\n        {\n            return new V4f(Log2(x.X), Log2(x.Y), Log2(x.Z), Log2(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Log2Int(this V4f x)\n        {\n            return new V4i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z), Log2Int(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Log10(this V4f x)\n        {\n            return new V4f(Log10(x.X), Log10(x.Y), Log10(x.Z), Log10(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Log(this V4f x, float basis)\n        {\n            return new V4f(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis), Log(x.W, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f ModP(this V4f a, V4f b)\n        {\n            return new V4f(ModP(a.X, b.X), ModP(a.Y, b.Y), ModP(a.Z, b.Z), ModP(a.W, b.W));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f PowerOfTwo(this V4f x)\n        {\n            return new V4f(PowerOfTwo(x.X), PowerOfTwo(x.Y), PowerOfTwo(x.Z), PowerOfTwo(x.W));\n        }\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Applies Fun.Sin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Sin(this V4f x)\n        {\n            return new V4f(Sin(x.X), Sin(x.Y), Sin(x.Z), Sin(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Cos(this V4f x)\n        {\n            return new V4f(Cos(x.X), Cos(x.Y), Cos(x.Z), Cos(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Tan(this V4f x)\n        {\n            return new V4f(Tan(x.X), Tan(x.Y), Tan(x.Z), Tan(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Asin(this V4f x)\n        {\n            return new V4f(Asin(x.X), Asin(x.Y), Asin(x.Z), Asin(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.AsinClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f AsinClamped(this V4f x)\n        {\n            return new V4f(AsinClamped(x.X), AsinClamped(x.Y), AsinClamped(x.Z), AsinClamped(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Acos(this V4f x)\n        {\n            return new V4f(Acos(x.X), Acos(x.Y), Acos(x.Z), Acos(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.AcosClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f AcosClamped(this V4f x)\n        {\n            return new V4f(AcosClamped(x.X), AcosClamped(x.Y), AcosClamped(x.Z), AcosClamped(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Atan(this V4f x)\n        {\n            return new V4f(Atan(x.X), Atan(x.Y), Atan(x.Z), Atan(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Atan2(V4f y, V4f x)\n        {\n            return new V4f(Atan2(y.X, x.X), Atan2(y.Y, x.Y), Atan2(y.Z, x.Z), Atan2(y.W, x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.FastAtan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f FastAtan2(V4f y, V4f x)\n        {\n            return new V4f(FastAtan2(y.X, x.X), FastAtan2(y.Y, x.Y), FastAtan2(y.Z, x.Z), FastAtan2(y.W, x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Sinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Sinh(this V4f x)\n        {\n            return new V4f(Sinh(x.X), Sinh(x.Y), Sinh(x.Z), Sinh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Cosh(this V4f x)\n        {\n            return new V4f(Cosh(x.X), Cosh(x.Y), Cosh(x.Z), Cosh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Tanh(this V4f x)\n        {\n            return new V4f(Tanh(x.X), Tanh(x.Y), Tanh(x.Z), Tanh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Asinh(this V4f x)\n        {\n            return new V4f(Asinh(x.X), Asinh(x.Y), Asinh(x.Z), Asinh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Acosh(this V4f x)\n        {\n            return new V4f(Acosh(x.X), Acosh(x.Y), Acosh(x.Z), Acosh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Atanh(this V4f x)\n        {\n            return new V4f(Atanh(x.X), Atanh(x.Y), Atanh(x.Z), Atanh(x.W));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Step(this V4f x, V4f edge)\n        {\n            return new V4f(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z), Step(x.W, edge.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Step(this V4f x, float edge)\n        {\n            return new V4f(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge), Step(x.W, edge));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Linearstep(this V4f x, V4f edge0, V4f edge1)\n        {\n            return new V4f(Linearstep(x.X, edge0.X, edge1.X), Linearstep(x.Y, edge0.Y, edge1.Y), Linearstep(x.Z, edge0.Z, edge1.Z), Linearstep(x.W, edge0.W, edge1.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Linearstep(this V4f x, float edge0, float edge1)\n        {\n            return new V4f(Linearstep(x.X, edge0, edge1), Linearstep(x.Y, edge0, edge1), Linearstep(x.Z, edge0, edge1), Linearstep(x.W, edge0, edge1));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Smoothstep(this V4f x, V4f edge0, V4f edge1)\n        {\n            return new V4f(Smoothstep(x.X, edge0.X, edge1.X), Smoothstep(x.Y, edge0.Y, edge1.Y), Smoothstep(x.Z, edge0.Z, edge1.Z), Smoothstep(x.W, edge0.W, edge1.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Smoothstep(this V4f x, float edge0, float edge1)\n        {\n            return new V4f(Smoothstep(x.X, edge0, edge1), Smoothstep(x.Y, edge0, edge1), Smoothstep(x.Z, edge0, edge1), Smoothstep(x.W, edge0, edge1));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Lerp(this float t, V4f a, V4f b)\n        {\n            return new V4f(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z), Lerp(t, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Lerp(this V4f t, V4f a, V4f b)\n        {\n            return new V4f(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z), Lerp(t.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f InvLerp(this V4f y, V4f a, V4f b)\n        {\n            return new V4f(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z), InvLerp(y.W, a.W, b.W));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatToBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i FloatToBits(this V4f x)\n        {\n            return new V4i(FloatToBits(x.X), FloatToBits(x.Y), FloatToBits(x.Z), FloatToBits(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.FloatToUnsignedBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4ui FloatToUnsignedBits(this V4f x)\n        {\n            return new V4ui(FloatToUnsignedBits(x.X), FloatToUnsignedBits(x.Y), FloatToUnsignedBits(x.Z), FloatToUnsignedBits(x.W));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V4f a, V4f b, float tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance) && ApproximateEquals(a.W, b.W, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within\n        /// Constant{float}.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V4f a, V4f b)\n        {\n            return ApproximateEquals(a, b, Constant<float>.PositiveTinyValue);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V4f v, float epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4f\"/> is smaller than Constant&lt;float&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(V4f v)\n            => v.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"V4f\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(V4f v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V4f\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(V4f v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V4f\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(V4f v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V4f\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(V4f v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"V4f\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(V4f v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts the angles given in degrees to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f RadiansFromDegrees(this V4f degrees)\n            => new V4f(\n                   RadiansFromDegrees(degrees.X), \n                   RadiansFromDegrees(degrees.Y), \n                   RadiansFromDegrees(degrees.Z), \n                   RadiansFromDegrees(degrees.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f RadiansFromGons(this V4f gons)\n            => new V4f(\n                   RadiansFromGons(gons.X), \n                   RadiansFromGons(gons.Y), \n                   RadiansFromGons(gons.Z), \n                   RadiansFromGons(gons.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f DegreesFromRadians(this V4f radians)\n            => new V4f(\n                   DegreesFromRadians(radians.X), \n                   DegreesFromRadians(radians.Y), \n                   DegreesFromRadians(radians.Z), \n                   DegreesFromRadians(radians.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f DegreesFromGons(this V4f gons)\n            => new V4f(\n                   DegreesFromGons(gons.X), \n                   DegreesFromGons(gons.Y), \n                   DegreesFromGons(gons.Z), \n                   DegreesFromGons(gons.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f GonsFromRadians(this V4f radians)\n            => new V4f(\n                   GonsFromRadians(radians.X), \n                   GonsFromRadians(radians.Y), \n                   GonsFromRadians(radians.Z), \n                   GonsFromRadians(radians.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in degrees to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f GonsFromDegrees(this V4f degrees)\n            => new V4f(\n                   GonsFromDegrees(degrees.X), \n                   GonsFromDegrees(degrees.Y), \n                   GonsFromDegrees(degrees.Z), \n                   GonsFromDegrees(degrees.W)\n               );\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float LengthSquared(V4f v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Length(V4f v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Normalizes the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref V4f v)\n        {\n            var s = v.Length; if (s == 0) return;\n            s = 1 / s;\n            v.X *= s;\n            v.Y *= s;\n            v.Z *= s;\n            v.W *= s;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Normalized(V4f v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm1(V4f v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm2(V4f v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMax(V4f v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float NormMin(V4f v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Norm(this V4f v, float p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p) + \n                Fun.Abs(v.W).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceSquared(this V4f a, V4f b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y) + Fun.Square(b.Z - a.Z) + Fun.Square(b.W - a.W);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(this V4f a, V4f b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance1(this V4f a, V4f b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y) + Fun.Abs(b.Z - a.Z) + Fun.Abs(b.W - a.W);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Distance(this V4f a, V4f b, float p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p) + Fun.Abs(b.Z - a.Z).Pow(p) + Fun.Abs(b.W - a.W).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceMax(this V4f a, V4f b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z), Fun.Abs(b.W - a.W));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceMin(this V4f a, V4f b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z), Fun.Abs(b.W - a.W));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToLine(\n                this V4f query, V4f p0, V4f p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            if (t <= 0) { return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToInfiniteLine(\n                this V4f query, V4f p0, V4f p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToLine(\n                this V4f query, V4f p0, V4f p1, out float t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            if (t <= 0) { t = 0; return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { t = 1; return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float DistanceToInfiniteLine(\n                this V4f query, V4f p0, V4f p1, out float t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Gets a copy of the given vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Reciprocal(V4f v)\n            => v.Reciprocal;\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V4f v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n            v.Z = -v.Z;\n            v.W = -v.W;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 4x4 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44f Outer(this V4f a, V4f b)\n        {\n            return new M44f(\n                        a.X * b.X, a.X * b.Y, a.X * b.Z, a.X * b.W, \n                        a.Y * b.X, a.Y * b.Y, a.Y * b.Z, a.Y * b.W, \n                        a.Z * b.X, a.Z * b.Y, a.Z * b.Z, a.Z * b.W, \n                        a.W * b.X, a.W * b.Y, a.W * b.Z, a.W * b.W);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float Dot(this V4f a, V4f b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V4f v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeZ;\n            if (v.W > Constant<float>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveW;\n            if (v.W < Constant<float>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeW;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the reflection direction of the given vector v (pointing to the surface) for the given normal (should be normalized).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Reflect(this V4f v, V4f normal)\n        {\n            return v - 2 * v.Dot(normal) * normal;\n        }\n\n        /// <summary>\n        /// Returns the refraction direction of the given vector v (pointing to the surface) for the given normal and ratio of refraction indices (n_out / n_in).\n        /// Both the input vectors should be normalized.\n        /// Returns a zero-vector in case of total internal reflection.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f Refract(this V4f v, V4f normal, float eta)\n        {\n            var t = v.Dot(normal);\n            var k = 1 - eta * eta * (1 - t * t);\n\n            if (k < 0)\n            {\n                return V4f.Zero;\n            }\n            else\n            {\n                return eta * v - (eta * t + Fun.Sqrt(k)) * normal;\n            }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4f a, V4f b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z && a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4f v, float s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s && v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(float s, V4f v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z && s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4f a, V4f b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z || a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4f v, float s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s || v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(float s, V4f v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z || s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4f a, V4f b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z && a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4f v, float s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s && v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(float s, V4f v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z && s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4f a, V4f b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z || a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4f v, float s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s || v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(float s, V4f v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z || s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4f a, V4f b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z && a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4f v, float s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s && v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(float s, V4f v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z && s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4f a, V4f b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z || a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4f v, float s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s || v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(float s, V4f v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z || s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4f a, V4f b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z && a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4f v, float s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s && v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(float s, V4f v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z && s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4f a, V4f b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z || a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4f v, float s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s || v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(float s, V4f v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z || s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4f a, V4f b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4f v, float s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s && v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(float s, V4f v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z && s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4f a, V4f b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z || a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4f v, float s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s || v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(float s, V4f v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z || s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4f a, V4f b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z && a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4f v, float s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s && v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(float s, V4f v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z && s != v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4f a, V4f b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4f v, float s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s || v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(float s, V4f v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z || s != v.W);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V4f v0, V4f v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            if (v0.W < v1.W) return -1;\n            if (v0.W > v1.W) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MinElement(V4f v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V4f\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float MaxElement(V4f v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region Angle between two vectors\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleBetweenFast(this V4f x, V4f y)\n        {\n            return Fun.AcosClamped(x.Dot(y));\n        }\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians using a numerically stable algorithm.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        // https://scicomp.stackexchange.com/a/27769\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float AngleBetween(this V4f x, V4f y)\n        {\n            var a = x + y;\n            var b = x - y;\n            return 2 * Fun.Atan2(b.Length, a.Length);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V4f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V4f v, float epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon) || v.W.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4f\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V4f v, float epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon) && v.W.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(V4f v)\n            => v.AnyFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(V4f v)\n            => v.AllFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(V4f v)\n            => v.AnyNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(V4f v)\n            => v.AllNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(V4f v)\n            => v.AnyInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(V4f v)\n            => v.AllInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(V4f v)\n            => v.AnyPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(V4f v)\n            => v.AllPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(V4f v)\n            => v.AnyNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(V4f v)\n            => v.AllNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(V4f v)\n            => v.AnyTiny;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(V4f v)\n            => v.AllTiny;\n\n        #endregion\n\n        #region Linear Combination\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LinCom(V4f p0, V4f p1, ref Tup2<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LinCom(V4f p0, V4f p1, V4f p2, ref Tup3<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LinCom(V4f p0, V4f p1, V4f p2, V4f p3, ref Tup4<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LinCom(V4f p0, V4f p1, V4f p2, V4f p3, V4f p4, ref Tup5<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LinCom(V4f p0, V4f p1, V4f p2, V4f p3, V4f p4, V4f p5, ref Tup6<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f LinCom(V4f p0, V4f p1, V4f p2, V4f p3, V4f p4, V4f p5, V4f p6, ref Tup7<float> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V4f[] pointArray, V4f point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V4f[] array, int start, int count,\n                V4f point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V4f> pointSelector, V4f point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V4f[] pointArray, V4f point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V4f[] array, long start, long count,\n                V4f point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V4f> pointSelector, V4f point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V4f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V4f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V4f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V4f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V4f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V4f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V4f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V4f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V4f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V4f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V4f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V4f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinW(this V4f[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinW(this V4f[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxW(this V4f[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxW(this V4f[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V4f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V4f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V4f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V4f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V4f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V4f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinW(this IList<V4f> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxW(this IList<V4f> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static float[] CopyCoord(this V4f[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                case 3: return self.Map(v => v.W);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        public static V4f WeightedSum(\n                this V4f[] vectorArray, float[] weightArray)\n        {\n            var r = V4f.Zero;\n            var count = vectorArray.LongLength;\n            for (long i = 0; i < count; i++) r += vectorArray[i] * weightArray[i];\n            return r;\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV4fExtensions\n    {\n        #region IRandomUniform extensions for V4f\n\n        /// <summary>\n        /// Uses UniformFloat() to generate the elements of a V4f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f UniformV4f(this IRandomUniform rnd)\n        {\n            return new V4f(rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat(), rnd.UniformFloat());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatClosed() to generate the elements of a V4f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f UniformV4fClosed(this IRandomUniform rnd)\n        {\n            return new V4f(rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed(), rnd.UniformFloatClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformFloatOpen() to generate the elements of a V4f vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4f UniformV4fOpen(this IRandomUniform rnd)\n        {\n            return new V4f(rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen(), rnd.UniformFloatOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region V4d\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct V4d : IVector<double>, ISize4d, IFormattable, IEquatable<V4d>\n    {\n        [DataMember]\n        public double X;\n        [DataMember]\n        public double Y;\n        [DataMember]\n        public double Z;\n        [DataMember]\n        public double W;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"int\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(int x, int y, int z, int w)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n            W = (double)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"int\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(int v)\n        {\n            X = (double)v;\n            Y = (double)v;\n            Z = (double)v;\n            W = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(int[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n            Z = (double)a[2];\n            W = (double)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(int[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n            Z = (double)a[start + 2];\n            W = (double)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/> and <see cref=\"V3i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(int a, V3i b)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n            W = (double)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/> and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2i a, V2i b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b.X;\n            W = (double)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3i\"/> and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3i a, int b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)a.Z;\n            W = (double)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2i\"/>, <see cref=\"int\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2i a, int b, int c)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b;\n            W = (double)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"V2i\"/>, and <see cref=\"int\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(int a, V2i b, int c)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n            W = (double)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"int\"/>, <see cref=\"int\"/>, and <see cref=\"V2i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(int a, int b, V2i c)\n        {\n            X = (double)a;\n            Y = (double)b;\n            Z = (double)c.X;\n            W = (double)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"uint\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(uint x, uint y, uint z, uint w)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n            W = (double)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"uint\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(uint v)\n        {\n            X = (double)v;\n            Y = (double)v;\n            Z = (double)v;\n            W = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(uint[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n            Z = (double)a[2];\n            W = (double)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(uint[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n            Z = (double)a[start + 2];\n            W = (double)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/> and <see cref=\"V3ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(uint a, V3ui b)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n            W = (double)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/> and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2ui a, V2ui b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b.X;\n            W = (double)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3ui\"/> and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3ui a, uint b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)a.Z;\n            W = (double)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2ui\"/>, <see cref=\"uint\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2ui a, uint b, uint c)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b;\n            W = (double)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"V2ui\"/>, and <see cref=\"uint\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(uint a, V2ui b, uint c)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n            W = (double)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"uint\"/>, <see cref=\"uint\"/>, and <see cref=\"V2ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(uint a, uint b, V2ui c)\n        {\n            X = (double)a;\n            Y = (double)b;\n            Z = (double)c.X;\n            W = (double)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"long\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(long x, long y, long z, long w)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n            W = (double)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"long\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(long v)\n        {\n            X = (double)v;\n            Y = (double)v;\n            Z = (double)v;\n            W = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(long[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n            Z = (double)a[2];\n            W = (double)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(long[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n            Z = (double)a[start + 2];\n            W = (double)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/> and <see cref=\"V3l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(long a, V3l b)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n            W = (double)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/> and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2l a, V2l b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b.X;\n            W = (double)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3l\"/> and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3l a, long b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)a.Z;\n            W = (double)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2l\"/>, <see cref=\"long\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2l a, long b, long c)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b;\n            W = (double)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"V2l\"/>, and <see cref=\"long\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(long a, V2l b, long c)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n            W = (double)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"long\"/>, <see cref=\"long\"/>, and <see cref=\"V2l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(long a, long b, V2l c)\n        {\n            X = (double)a;\n            Y = (double)b;\n            Z = (double)c.X;\n            W = (double)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"float\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(float x, float y, float z, float w)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n            W = (double)w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"float\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(float v)\n        {\n            X = (double)v;\n            Y = (double)v;\n            Z = (double)v;\n            W = (double)v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(float[] a)\n        {\n            X = (double)a[0];\n            Y = (double)a[1];\n            Z = (double)a[2];\n            W = (double)a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(float[] a, int start)\n        {\n            X = (double)a[start + 0];\n            Y = (double)a[start + 1];\n            Z = (double)a[start + 2];\n            W = (double)a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/> and <see cref=\"V3f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(float a, V3f b)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n            W = (double)b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/> and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2f a, V2f b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b.X;\n            W = (double)b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3f\"/> and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3f a, float b)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)a.Z;\n            W = (double)b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2f\"/>, <see cref=\"float\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2f a, float b, float c)\n        {\n            X = (double)a.X;\n            Y = (double)a.Y;\n            Z = (double)b;\n            W = (double)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"V2f\"/>, and <see cref=\"float\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(float a, V2f b, float c)\n        {\n            X = (double)a;\n            Y = (double)b.X;\n            Z = (double)b.Y;\n            W = (double)c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"float\"/>, <see cref=\"float\"/>, and <see cref=\"V2f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(float a, float b, V2f c)\n        {\n            X = (double)a;\n            Y = (double)b;\n            Z = (double)c.X;\n            W = (double)c.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"double\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(double x, double y, double z, double w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"double\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(double v)\n        {\n            X = v;\n            Y = v;\n            Z = v;\n            W = v;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(double[] a)\n        {\n            X = a[0];\n            Y = a[1];\n            Z = a[2];\n            W = a[3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(double[] a, int start)\n        {\n            X = a[start + 0];\n            Y = a[start + 1];\n            Z = a[start + 2];\n            W = a[start + 3];\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/> and <see cref=\"V3d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(double a, V3d b)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = b.Z;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/> and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2d a, V2d b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b.X;\n            W = b.Y;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V3d\"/> and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3d a, double b)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = a.Z;\n            W = b;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"V2d\"/>, <see cref=\"double\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2d a, double b, double c)\n        {\n            X = a.X;\n            Y = a.Y;\n            Z = b;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"V2d\"/>, and <see cref=\"double\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(double a, V2d b, double c)\n        {\n            X = a;\n            Y = b.X;\n            Z = b.Y;\n            W = c;\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"double\"/>, <see cref=\"double\"/>, and <see cref=\"V2d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(double a, double b, V2d c)\n        {\n            X = a;\n            Y = b;\n            Z = c.X;\n            W = c.Y;\n        }\n\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(Func<int, double> index_fun)\n        {\n            X = index_fun(0);\n            Y = index_fun(1);\n            Z = index_fun(2);\n            W = index_fun(3);\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;double&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least 4.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(IVector<double> v)\n            : this(v[0], v[1], v[2], v[3])\n        { }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2i\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2ui\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2l\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2f\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V2d\"/>.\n        /// Z, W are set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V2d v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = 0;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3i\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3ui\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3l\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3f\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V3d\"/>.\n        /// W is set to zero.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V3d v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = 0;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4i\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V4i v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n            W = (double)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4ui\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V4ui v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n            W = (double)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4l\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V4l v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n            W = (double)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4f\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V4f v)\n        {\n            X = (double)v.X;\n            Y = (double)v.Y;\n            Z = (double)v.Z;\n            W = (double)v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"V4d\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(V4d v)\n        {\n            X = v.X;\n            Y = v.Y;\n            Z = v.Z;\n            W = v.W;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C3b c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n            W = (double)255;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C3us c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n            W = (double)65535;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C3ui c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n            W = (double)UInt32.MaxValue;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3f\"/> color.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C3f c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n            W = (double)1.0f;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C3d\"/> color.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C3d c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n            W = 1.0;\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C4b c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n            W = (double)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C4us c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n            W = (double)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C4ui c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n            W = (double)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C4f c)\n        {\n            X = (double)(c.R);\n            Y = (double)(c.G);\n            Z = (double)(c.B);\n            W = (double)(c.A);\n        }\n\n        /// <summary>\n        /// Creates a vector from a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public V4d(C4d c)\n        {\n            X = (c.R);\n            Y = (c.G);\n            Z = (c.B);\n            W = (c.A);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V2i v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V2ui v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V2l v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V2f v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V2d v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V3i v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V3ui v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V3l v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V3f v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V3d v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V4i v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V4ui v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V4l v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(V4f v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2i ToV2i() => (V2i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2ui ToV2ui() => (V2ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2l ToV2l() => (V2l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V2f ToV2f() => (V2f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3i() => (V3i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3ui() => (V3ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3l() => (V3l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3f() => (V3f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i ToV4i() => (V4i)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui ToV4ui() => (V4ui)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToV4l() => (V4l)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f ToV4f() => (V4f)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator int[](V4d v)\n            => new int[] { (int)v.X, (int)v.Y, (int)v.Z, (int)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(int[] v)\n            => new V4d((double)v[0], (double)v[1], (double)v[2], (double)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator uint[](V4d v)\n            => new uint[] { (uint)v.X, (uint)v.Y, (uint)v.Z, (uint)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(uint[] v)\n            => new V4d((double)v[0], (double)v[1], (double)v[2], (double)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator long[](V4d v)\n            => new long[] { (long)v.X, (long)v.Y, (long)v.Z, (long)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(long[] v)\n            => new V4d((double)v[0], (double)v[1], (double)v[2], (double)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator float[](V4d v)\n            => new float[] { (float)v.X, (float)v.Y, (float)v.Z, (float)v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(float[] v)\n            => new V4d((double)v[0], (double)v[1], (double)v[2], (double)v[3]);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator double[](V4d v)\n            => new double[] { v.X, v.Y, v.Z, v.W };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(double[] v)\n            => new V4d(v[0], v[1], v[2], v[3]);\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3b\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C3b v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3b\"/> color.\n        /// The values are not mapped to the <see cref=\"C3b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3b ToC3b() => (C3b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3us\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C3us v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3us\"/> color.\n        /// The values are not mapped to the <see cref=\"C3us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3us ToC3us() => (C3us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3ui\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C3ui v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C3ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3ui ToC3ui() => (C3ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3f\"/> color to a <see cref=\"V4d\"/> vector.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C3f v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3f ToC3f() => (C3f)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C3d\"/> color to a <see cref=\"V4d\"/> vector.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C3d v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C3d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C3d ToC3d() => (C3d)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4b\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C4b v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4b\"/> color.\n        /// The values are not mapped to the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4b ToC4b() => (C4b)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4us\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C4us v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4us\"/> color.\n        /// The values are not mapped to the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4us ToC4us() => (C4us)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4ui\"/> color to a <see cref=\"V4d\"/> vector.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C4ui v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4ui\"/> color.\n        /// The values are not mapped to the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4ui ToC4ui() => (C4ui)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4f\"/> color to a <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C4f v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4f ToC4f() => (C4f)this;\n\n        /// <summary>\n        /// Converts the given <see cref=\"C4d\"/> color to a <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator V4d(C4d v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"V4d\"/> vector to a <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly C4d ToC4d() => (C4d)this;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToFloorV4l()\n            => new V4l((long)Fun.Floor(X), (long)Fun.Floor(Y), (long)Fun.Floor(Z), (long)Fun.Floor(W));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l ToCeilingV4l()\n            => new V4l((long)Fun.Ceiling(X), (long)Fun.Ceiling(Y), (long)Fun.Ceiling(Z), (long)Fun.Ceiling(W));\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3i ToV3iInhomo()\n        {\n            var div = 1 / W;\n            return new V3i(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3ui ToV3uiInhomo()\n        {\n            var div = 1 / W;\n            return new V3ui(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3l ToV3lInhomo()\n        {\n            var div = 1 / W;\n            return new V3l(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3f ToV3fInhomo()\n        {\n            var div = 1 / W;\n            return new V3f(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V3d ToV3dInhomo()\n        {\n            var div = 1 / W;\n            return new V3d(X * div, Y * div, Z * div);\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<double, int> element_fun)\n            => new V4i(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4i Copy(Func<double, int, int> element_index_fun)\n            => new V4i(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(int[] array, int start)\n        {\n            array[start + 0] = (int)X;\n            array[start + 1] = (int)Y;\n            array[start + 2] = (int)Z;\n            array[start + 3] = (int)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<double, uint> element_fun)\n            => new V4ui(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4ui Copy(Func<double, int, uint> element_index_fun)\n            => new V4ui(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(uint[] array, int start)\n        {\n            array[start + 0] = (uint)X;\n            array[start + 1] = (uint)Y;\n            array[start + 2] = (uint)Z;\n            array[start + 3] = (uint)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<double, long> element_fun)\n            => new V4l(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4l Copy(Func<double, int, long> element_index_fun)\n            => new V4l(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(long[] array, int start)\n        {\n            array[start + 0] = (long)X;\n            array[start + 1] = (long)Y;\n            array[start + 2] = (long)Z;\n            array[start + 3] = (long)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<double, float> element_fun)\n            => new V4f(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4f Copy(Func<double, int, float> element_index_fun)\n            => new V4f(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(float[] array, int start)\n        {\n            array[start + 0] = (float)X;\n            array[start + 1] = (float)Y;\n            array[start + 2] = (float)Z;\n            array[start + 3] = (float)W;\n        }\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<double, double> element_fun)\n            => new V4d(element_fun(X), element_fun(Y), element_fun(Z), element_fun(W));\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V4d Copy(Func<double, int, double> element_index_fun)\n            => new V4d(element_index_fun(X, 0), element_index_fun(Y, 1), element_index_fun(Z, 2), element_index_fun(W, 3));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(double[] array, int start)\n        {\n            array[start + 0] = X;\n            array[start + 1] = Y;\n            array[start + 2] = Z;\n            array[start + 3] = W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, T> element_fun)\n        {\n            array[start + 0] = element_fun(X);\n            array[start + 1] = element_fun(Y);\n            array[start + 2] = element_fun(Z);\n            array[start + 3] = element_fun(W);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<double, int, T> element_index_fun)\n        {\n            array[start + 0] = element_index_fun(X, 0);\n            array[start + 1] = element_index_fun(Y, 1);\n            array[start + 2] = element_index_fun(Z, 2);\n            array[start + 3] = element_index_fun(W, 3);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly double[] ToArray()\n            => new double[] { X, Y, Z, W };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        /// <summary>\n        /// Property for the field X.\n        /// Useful when properties are required, but the field X is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_X\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return X;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                X = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Y.\n        /// Useful when properties are required, but the field Y is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_Y\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Y;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Y = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field Z.\n        /// Useful when properties are required, but the field Z is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_Z\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return Z;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                Z = value;\n            }\n        }\n\n        /// <summary>\n        /// Property for the field W.\n        /// Useful when properties are required, but the field W is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public double P_W\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return W;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                W = value;\n            }\n        }\n\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<double> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                yield return X;\n                yield return Y;\n                yield return Z;\n                yield return W;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe double this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (double* ptr = &X) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (double* ptr = &X) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X >= Y\n                        ? (X >= Z ? (X >= W ? 0 : 3) : (Z >= W ? 2 : 3))\n                        : (Y >= Z ? (Y >= W ? 1 : 3) : (Z >= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return X <= Y\n                        ? (X <= Z ? (X <= W ? 0 : 3) : (Z <= W ? 2 : 3))\n                        : (Y <= Z ? (Y <= W ? 1 : 3) : (Z <= W ? 2 : 3));\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly double MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(X, Y, Z, W);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly double MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(X, Y, Z, W);\n        }\n\n        public readonly bool AnyFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) || Fun.IsFinite(Y) || Fun.IsFinite(Z) || Fun.IsFinite(W);\n        }\n\n        public readonly bool AllFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsFinite(X) && Fun.IsFinite(Y) && Fun.IsFinite(Z) && Fun.IsFinite(W);\n        }\n\n        public readonly bool AnyNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(X) || double.IsNaN(Y) || double.IsNaN(Z) || double.IsNaN(W);\n        }\n\n        public readonly bool AllNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNaN(X) && double.IsNaN(Y) && double.IsNaN(Z) && double.IsNaN(W);\n        }\n\n        public readonly bool AnyInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(X) || double.IsInfinity(Y) || double.IsInfinity(Z) || double.IsInfinity(W);\n        }\n\n        public readonly bool AllInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsInfinity(X) && double.IsInfinity(Y) && double.IsInfinity(Z) && double.IsInfinity(W);\n        }\n\n        public readonly bool AnyPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(X) || double.IsPositiveInfinity(Y) || double.IsPositiveInfinity(Z) || double.IsPositiveInfinity(W);\n        }\n\n        public readonly bool AllPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsPositiveInfinity(X) && double.IsPositiveInfinity(Y) && double.IsPositiveInfinity(Z) && double.IsPositiveInfinity(W);\n        }\n\n        public readonly bool AnyNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(X) || double.IsNegativeInfinity(Y) || double.IsNegativeInfinity(Z) || double.IsNegativeInfinity(W);\n        }\n\n        public readonly bool AllNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => double.IsNegativeInfinity(X) && double.IsNegativeInfinity(Y) && double.IsNegativeInfinity(Z) && double.IsNegativeInfinity(W);\n        }\n\n        public readonly bool AnyTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) || Fun.IsTiny(Y) || Fun.IsTiny(Z) || Fun.IsTiny(W);\n        }\n\n        public readonly bool AllTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.IsTiny(X) && Fun.IsTiny(Y) && Fun.IsTiny(Z) && Fun.IsTiny(W);\n        }\n\n        /// <summary>\n        /// Returns true if the absolute value of each component of the vector is smaller than Constant&lt;double&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the vector are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = 4;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static V4d Zero\n        {\n            get { return new V4d(0, 0, 0, 0); }\n        }\n\n        /// <summary>\n        /// All elements half.\n        /// </summary>\n        public static V4d Half\n        {\n            get { return new V4d(0.5, 0.5, 0.5, 0.5); }\n        }\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static V4d One\n        {\n            get { return new V4d(1, 1, 1, 1); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static V4d MaxValue\n        {\n            get { return new V4d(Constant<double>.ParseableMaxValue, Constant<double>.ParseableMaxValue, Constant<double>.ParseableMaxValue, Constant<double>.ParseableMaxValue); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static V4d MinValue\n        {\n            get { return new V4d(Constant<double>.ParseableMinValue, Constant<double>.ParseableMinValue, Constant<double>.ParseableMinValue, Constant<double>.ParseableMinValue); }\n        }\n\n         /// <summary>\n        /// All elements set to negative infinity.\n        /// </summary>\n        public static V4d NegativeInfinity\n        {\n            get { return new V4d(double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to positive infinity.\n        /// </summary>\n        public static V4d PositiveInfinity\n        {\n            get { return new V4d(double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity); }\n        }\n\n        /// <summary>\n        /// All elements set to NaN.\n        /// </summary>\n        public static V4d NaN\n        {\n            get { return new V4d(double.NaN, double.NaN, double.NaN, double.NaN); }\n        }\n\n        /// <summary>\n        /// Normalized X-axis.\n        /// </summary>\n        public static V4d XAxis\n        {\n            get { return new V4d(1, 0, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Y-axis.\n        /// </summary>\n        public static V4d YAxis\n        {\n            get { return new V4d(0, 1, 0, 0); }\n        }\n\n        /// <summary>\n        /// Normalized Z-axis.\n        /// </summary>\n        public static V4d ZAxis\n        {\n            get { return new V4d(0, 0, 1, 0); }\n        }\n\n        /// <summary>\n        /// Normalized W-axis.\n        /// </summary>\n        public static V4d WAxis\n        {\n            get { return new V4d(0, 0, 0, 1); }\n        }\n\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<V4d, double>[] SelectorArray =\n            new Func<V4d, double>[] { v => v.X, v => v.Y, v => v.Z, v => v.W };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<V4d, int, double> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<V4d, int, double> Setter =\n            (ref V4d v, int i, double s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<V4d, long, double> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    case 0: return v.X;\n                    case 1: return v.Y;\n                    case 2: return v.Z;\n                    case 3: return v.W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<V4d, long, double> LongSetter =\n            (ref V4d v, long i, double s) =>\n            {\n                switch (i)\n                {\n                    case 0: v.X = s; return;\n                    case 1: v.Y = s; return;\n                    case 2: v.Z = s; return;\n                    case 3: v.W = s; return;\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromV4i(V4i v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromV4ui(V4ui v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromV4l(V4l v)\n            => new V4d(v);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromV4f(V4f v)\n            => new V4d(v);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3b\"/> color.\n        /// The values are not mapped from the <see cref=\"C3b\"/> color range.\n        /// W is set to 255.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC3b(C3b c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3us\"/> color.\n        /// The values are not mapped from the <see cref=\"C3us\"/> color range.\n        /// W is set to 2^16 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC3us(C3us c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C3ui\"/> color range.\n        /// W is set to 2^32 - 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC3ui(C3ui c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3f\"/> color.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC3f(C3f c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C3d\"/> color.\n        /// W is set to 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC3d(C3d c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4b\"/> color.\n        /// The values are not mapped from the <see cref=\"C4b\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC4b(C4b c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4us\"/> color.\n        /// The values are not mapped from the <see cref=\"C4us\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC4us(C4us c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4ui\"/> color.\n        /// The values are not mapped from the <see cref=\"C4ui\"/> color range.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC4ui(C4ui c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4f\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC4f(C4f c) => new V4d(c);\n\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"C4d\"/> color.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FromC4d(C4d c) => new V4d(c);\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly double LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return X * X  + Y * Y  + Z * Z  + W * W ; }\n        }\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly double Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                return Fun.Sqrt(X * X  + Y * Y  + Z * Z  + W * W );\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly double Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Abs(X) + Fun.Abs(Y) + Fun.Abs(Z) + Fun.Abs(W); }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly double Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(X * X + Y * Y + Z * Z + W * W); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly double NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W)); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly double NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W)); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly V4d Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return V4d.Zero;\n                s = 1 / s;\n                return new V4d(X * s, Y * s, Z * s, W * s);\n            }\n        }\n\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered cube with side length 2.\n        /// </summary>\n        public readonly V4d CubeMapped\n        {\n            get\n            {\n                var s = 1 / Fun.Max(Fun.Abs(X), Fun.Abs(Y), Fun.Abs(Z), Fun.Abs(W));\n                return new V4d(X * s, Y * s, Z * s, W * s);\n            }\n        }\n\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Abs(V4d v)\n            => v.Abs();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Floor(V4d v)\n            => v.Floor();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Ceiling(V4d v)\n            => v.Ceiling();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Round(V4d v)\n            => v.Round();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Truncate(V4d v)\n            => v.Truncate();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Acos(V4d v)\n            => Fun.Acos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Acoshb(V4d v)\n            => Fun.Acosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Cos(V4d v)\n            => Fun.Cos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Cosh(V4d v)\n            => Fun.Cosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Asin(V4d v)\n            => Fun.Asin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Asinhb(V4d v)\n            => Fun.Asinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sin(V4d v)\n            => Fun.Sin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sinh(V4d v)\n            => Fun.Sinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Atan(V4d v)\n            => Fun.Atan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Atanhb(V4d v)\n            => Fun.Atanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Atan2(V4d a, V4d b)\n            => Fun.Atan2(a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Tan(V4d v)\n            => Fun.Tan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Tanh(V4d v)\n            => Fun.Tanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sqrt(V4d v)\n            => Fun.Sqrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d CubeRoot(V4d v)\n            => Fun.Cbrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Exp(V4d v)\n            => Fun.Exp(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(V4d v)\n            => Fun.Log(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LogBinary(V4d v)\n            => Fun.Log2(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log10(V4d v)\n            => Fun.Log10(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d CopySgn(V4d value, V4d sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d CopySgn(V4d value, double sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LinearInterp(double t, V4d a, V4d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LinearInterp(V4d t, V4d a, V4d b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Min(V4d v0, V4d v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Min(V4d v, double x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Max(V4d v0, V4d v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Max(V4d v, double x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Saturate(V4d v)\n            => Fun.Saturate(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d DivideByInt(V4d v, int x)\n            => v / x;\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Sets the elements of a vector to the given int elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(int x, int y, int z, int w)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n            W = (double)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given uint elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(uint x, uint y, uint z, uint w)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n            W = (double)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given long elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(long x, long y, long z, long w)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n            W = (double)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given float elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(float x, float y, float z, float w)\n        {\n            X = (double)x;\n            Y = (double)y;\n            Z = (double)z;\n            W = (double)w;\n        }\n\n        /// <summary>\n        /// Sets the elements of a vector to the given double elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(double x, double y, double z, double w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator -(V4d v)\n            => new V4d(-v.X, -v.Y, -v.Z, -v.W);\n\n        /// <summary>\n        /// Gets a copy of this vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        public readonly V4d Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new V4d(1 / X, 1 / Y, 1 / Z, 1 / W); }\n        }\n\n        /// <summary>\n        /// Returns the component-wise sum of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator +(V4d a, V4d b)\n            => new V4d(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);\n\n        /// <summary>\n        /// Returns the component-wise sum of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator +(V4d v, double s)\n            => new V4d(v.X + s, v.Y + s, v.Z + s, v.W + s);\n\n        /// <summary>\n        /// Returns the component-wise sum of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator +(double s, V4d v)\n            => new V4d(s + v.X, s + v.Y, s + v.Z, s + v.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator -(V4d a, V4d b)\n            => new V4d(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);\n\n        /// <summary>\n        /// Returns the component-wise difference of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator -(V4d v, double s)\n            => new V4d(v.X - s, v.Y - s, v.Z - s, v.W - s);\n\n        /// <summary>\n        /// Returns the component-wise difference of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator -(double s, V4d v)\n            => new V4d(s - v.X, s - v.Y, s - v.Z, s - v.W);\n\n        /// <summary>\n        /// Returns the component-wise product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(V4d a, V4d b)\n            => new V4d(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W);\n\n        /// <summary>\n        /// Returns the component-wise product of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(V4d v, double s)\n            => new V4d(v.X * s, v.Y * s, v.Z * s, v.W * s);\n\n        /// <summary>\n        /// Returns the component-wise product of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator *(double s, V4d v)\n            => new V4d(s * v.X, s * v.Y, s * v.Z, s * v.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator /(V4d a, V4d b)\n            => new V4d(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator /(V4d v, double s)\n            => new V4d(v.X / s, v.Y / s, v.Z / s, v.W / s);\n\n        /// <summary>\n        /// Returns the component-wise fraction of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator /(double s, V4d v)\n            => new V4d(s / v.X, s / v.Y, s / v.Z, s / v.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator %(V4d a, V4d b)\n            => new V4d(a.X % b.X, a.Y % b.Y, a.Z % b.Z, a.W % b.W);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator %(V4d v, double s)\n            => new V4d(v.X % s, v.Y % s, v.Z % s, v.W % s);\n\n        /// <summary>\n        /// Returns the component-wise remainder of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d operator %(double s, V4d v)\n            => new V4d(s % v.X, s % v.Y, s % v.Z, s % v.W);\n\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4d a, V4d b)\n        {\n            return a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(V4d v, double s)\n        {\n            return v.X == s && v.Y == s && v.Z == s && v.W == s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(double s, V4d v)\n        {\n            return s == v.X && s == v.Y && s == v.Z && s == v.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4d a, V4d b)\n        {\n            return a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(V4d v, double s)\n        {\n            return v.X != s || v.Y != s || v.Z != s || v.W != s;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(double s, V4d v)\n        {\n            return s != v.X || s != v.Y || s != v.Z || s != v.W;\n        }\n\n        #endregion\n\n        #region IEquatable<V4d> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(V4d other)\n        {\n            return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin + X.ToString(format, fp)  + between + Y.ToString(format, fp)  + between + Z.ToString(format, fp)  + between + W.ToString(format, fp)  + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(X, Y, Z, W);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is V4d o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")\n                + X.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Y.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + Z.ToString(null, CultureInfo.InvariantCulture)  + \", \" \n                + W.ToString(null, CultureInfo.InvariantCulture) \n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static V4d Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new V4d(\n                double.Parse(x[0], CultureInfo.InvariantCulture), \n                double.Parse(x[1], CultureInfo.InvariantCulture), \n                double.Parse(x[2], CultureInfo.InvariantCulture), \n                double.Parse(x[3], CultureInfo.InvariantCulture)\n            );\n        }\n\n        public static V4d Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<double>.Parse, V4d.Setter);\n        }\n\n        public static V4d Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<double>.Parse, V4d.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OX => new V2d(0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OY => new V2d(0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OZ => new V2d(0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d OW => new V2d(0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IX => new V2d(1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IY => new V2d(1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IZ => new V2d(1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d IW => new V2d(1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NX => new V2d(-1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NY => new V2d(-1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NZ => new V2d(-1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d NW => new V2d(-1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XO => new V2d(X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XI => new V2d(X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XN => new V2d(X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d XX => new V2d(X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d XY\n        {\n            readonly get => new V2d(X, Y);\n            set { X = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d XZ\n        {\n            readonly get => new V2d(X, Z);\n            set { X = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d XW\n        {\n            readonly get => new V2d(X, W);\n            set { X = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YO => new V2d(Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YI => new V2d(Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YN => new V2d(Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d YX\n        {\n            readonly get => new V2d(Y, X);\n            set { Y = value.X; X = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d YY => new V2d(Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d YZ\n        {\n            readonly get => new V2d(Y, Z);\n            set { Y = value.X; Z = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d YW\n        {\n            readonly get => new V2d(Y, W);\n            set { Y = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d ZO => new V2d(Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d ZI => new V2d(Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d ZN => new V2d(Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d ZX\n        {\n            readonly get => new V2d(Z, X);\n            set { Z = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d ZY\n        {\n            readonly get => new V2d(Z, Y);\n            set { Z = value.X; Y = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d ZZ => new V2d(Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d ZW\n        {\n            readonly get => new V2d(Z, W);\n            set { Z = value.X; W = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d WO => new V2d(W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d WI => new V2d(W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d WN => new V2d(W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d WX\n        {\n            readonly get => new V2d(W, X);\n            set { W = value.X; X = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d WY\n        {\n            readonly get => new V2d(W, Y);\n            set { W = value.X; Y = value.Y; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2d WZ\n        {\n            readonly get => new V2d(W, Z);\n            set { W = value.X; Z = value.Y; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2d WW => new V2d(W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOX => new V3d(0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOY => new V3d(0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOZ => new V3d(0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OOW => new V3d(0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIX => new V3d(0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIY => new V3d(0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIZ => new V3d(0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OIW => new V3d(0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONX => new V3d(0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONY => new V3d(0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONZ => new V3d(0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ONW => new V3d(0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXO => new V3d(0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXI => new V3d(0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXN => new V3d(0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXX => new V3d(0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXY => new V3d(0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXZ => new V3d(0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OXW => new V3d(0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYO => new V3d(0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYI => new V3d(0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYN => new V3d(0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYX => new V3d(0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYY => new V3d(0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYZ => new V3d(0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OYW => new V3d(0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZO => new V3d(0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZI => new V3d(0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZN => new V3d(0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZX => new V3d(0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZY => new V3d(0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZZ => new V3d(0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OZW => new V3d(0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OWO => new V3d(0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OWI => new V3d(0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OWN => new V3d(0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OWX => new V3d(0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OWY => new V3d(0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OWZ => new V3d(0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d OWW => new V3d(0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOX => new V3d(1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOY => new V3d(1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOZ => new V3d(1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IOW => new V3d(1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIX => new V3d(1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIY => new V3d(1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIZ => new V3d(1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IIW => new V3d(1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNX => new V3d(1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNY => new V3d(1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNZ => new V3d(1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PNW => new V3d(1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXO => new V3d(1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXI => new V3d(1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PXN => new V3d(1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXX => new V3d(1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXY => new V3d(1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXZ => new V3d(1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IXW => new V3d(1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYO => new V3d(1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYI => new V3d(1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PYN => new V3d(1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYX => new V3d(1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYY => new V3d(1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYZ => new V3d(1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IYW => new V3d(1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZO => new V3d(1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZI => new V3d(1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PZN => new V3d(1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZX => new V3d(1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZY => new V3d(1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZZ => new V3d(1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IZW => new V3d(1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IWO => new V3d(1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IWI => new V3d(1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d PWN => new V3d(1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IWX => new V3d(1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IWY => new V3d(1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IWZ => new V3d(1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d IWW => new V3d(1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOX => new V3d(-1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOY => new V3d(-1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOZ => new V3d(-1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NOW => new V3d(-1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPX => new V3d(-1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPY => new V3d(-1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPZ => new V3d(-1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NPW => new V3d(-1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNX => new V3d(-1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNY => new V3d(-1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNZ => new V3d(-1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NNW => new V3d(-1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXO => new V3d(-1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXP => new V3d(-1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXN => new V3d(-1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXX => new V3d(-1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXY => new V3d(-1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXZ => new V3d(-1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NXW => new V3d(-1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYO => new V3d(-1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYP => new V3d(-1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYN => new V3d(-1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYX => new V3d(-1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYY => new V3d(-1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYZ => new V3d(-1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NYW => new V3d(-1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZO => new V3d(-1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZP => new V3d(-1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZN => new V3d(-1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZX => new V3d(-1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZY => new V3d(-1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZZ => new V3d(-1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NZW => new V3d(-1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NWO => new V3d(-1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NWP => new V3d(-1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NWN => new V3d(-1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NWX => new V3d(-1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NWY => new V3d(-1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NWZ => new V3d(-1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d NWW => new V3d(-1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOO => new V3d(X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOI => new V3d(X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XON => new V3d(X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOX => new V3d(X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOY => new V3d(X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOZ => new V3d(X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XOW => new V3d(X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIO => new V3d(X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XII => new V3d(X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XPN => new V3d(X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIX => new V3d(X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIY => new V3d(X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIZ => new V3d(X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XIW => new V3d(X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNO => new V3d(X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNP => new V3d(X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNN => new V3d(X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNX => new V3d(X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNY => new V3d(X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNZ => new V3d(X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XNW => new V3d(X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXO => new V3d(X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXI => new V3d(X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXN => new V3d(X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXX => new V3d(X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXY => new V3d(X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXZ => new V3d(X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XXW => new V3d(X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYO => new V3d(X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYI => new V3d(X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYN => new V3d(X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYX => new V3d(X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XYY => new V3d(X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d XYZ\n        {\n            readonly get => new V3d(X, Y, Z);\n            set { X = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d XYW\n        {\n            readonly get => new V3d(X, Y, W);\n            set { X = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZO => new V3d(X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZI => new V3d(X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZN => new V3d(X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZX => new V3d(X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d XZY\n        {\n            readonly get => new V3d(X, Z, Y);\n            set { X = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XZZ => new V3d(X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d XZW\n        {\n            readonly get => new V3d(X, Z, W);\n            set { X = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XWO => new V3d(X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XWI => new V3d(X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XWN => new V3d(X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XWX => new V3d(X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d XWY\n        {\n            readonly get => new V3d(X, W, Y);\n            set { X = value.X; W = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d XWZ\n        {\n            readonly get => new V3d(X, W, Z);\n            set { X = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d XWW => new V3d(X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOO => new V3d(Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOI => new V3d(Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YON => new V3d(Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOX => new V3d(Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOY => new V3d(Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOZ => new V3d(Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YOW => new V3d(Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIO => new V3d(Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YII => new V3d(Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YPN => new V3d(Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIX => new V3d(Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIY => new V3d(Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIZ => new V3d(Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YIW => new V3d(Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNO => new V3d(Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNP => new V3d(Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNN => new V3d(Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNX => new V3d(Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNY => new V3d(Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNZ => new V3d(Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YNW => new V3d(Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXO => new V3d(Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXI => new V3d(Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXN => new V3d(Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXX => new V3d(Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YXY => new V3d(Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d YXZ\n        {\n            readonly get => new V3d(Y, X, Z);\n            set { Y = value.X; X = value.Y; Z = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d YXW\n        {\n            readonly get => new V3d(Y, X, W);\n            set { Y = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYO => new V3d(Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYI => new V3d(Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYN => new V3d(Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYX => new V3d(Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYY => new V3d(Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYZ => new V3d(Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YYW => new V3d(Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZO => new V3d(Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZI => new V3d(Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZN => new V3d(Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d YZX\n        {\n            readonly get => new V3d(Y, Z, X);\n            set { Y = value.X; Z = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZY => new V3d(Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YZZ => new V3d(Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d YZW\n        {\n            readonly get => new V3d(Y, Z, W);\n            set { Y = value.X; Z = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YWO => new V3d(Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YWI => new V3d(Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YWN => new V3d(Y, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d YWX\n        {\n            readonly get => new V3d(Y, W, X);\n            set { Y = value.X; W = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YWY => new V3d(Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d YWZ\n        {\n            readonly get => new V3d(Y, W, Z);\n            set { Y = value.X; W = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d YWW => new V3d(Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOO => new V3d(Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOI => new V3d(Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZON => new V3d(Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOX => new V3d(Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOY => new V3d(Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOZ => new V3d(Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZOW => new V3d(Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIO => new V3d(Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZII => new V3d(Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZPN => new V3d(Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIX => new V3d(Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIY => new V3d(Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIZ => new V3d(Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZIW => new V3d(Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNO => new V3d(Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNP => new V3d(Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNN => new V3d(Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNX => new V3d(Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNY => new V3d(Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNZ => new V3d(Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZNW => new V3d(Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXO => new V3d(Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXI => new V3d(Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXN => new V3d(Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXX => new V3d(Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d ZXY\n        {\n            readonly get => new V3d(Z, X, Y);\n            set { Z = value.X; X = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZXZ => new V3d(Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d ZXW\n        {\n            readonly get => new V3d(Z, X, W);\n            set { Z = value.X; X = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYO => new V3d(Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYI => new V3d(Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYN => new V3d(Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d ZYX\n        {\n            readonly get => new V3d(Z, Y, X);\n            set { Z = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYY => new V3d(Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZYZ => new V3d(Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d ZYW\n        {\n            readonly get => new V3d(Z, Y, W);\n            set { Z = value.X; Y = value.Y; W = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZO => new V3d(Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZI => new V3d(Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZN => new V3d(Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZX => new V3d(Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZY => new V3d(Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZZ => new V3d(Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZZW => new V3d(Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZWO => new V3d(Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZWI => new V3d(Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZWN => new V3d(Z, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d ZWX\n        {\n            readonly get => new V3d(Z, W, X);\n            set { Z = value.X; W = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d ZWY\n        {\n            readonly get => new V3d(Z, W, Y);\n            set { Z = value.X; W = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZWZ => new V3d(Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d ZWW => new V3d(Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WOO => new V3d(W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WOI => new V3d(W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WON => new V3d(W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WOX => new V3d(W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WOY => new V3d(W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WOZ => new V3d(W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WOW => new V3d(W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WIO => new V3d(W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WII => new V3d(W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WPN => new V3d(W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WIX => new V3d(W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WIY => new V3d(W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WIZ => new V3d(W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WIW => new V3d(W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WNO => new V3d(W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WNP => new V3d(W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WNN => new V3d(W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WNX => new V3d(W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WNY => new V3d(W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WNZ => new V3d(W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WNW => new V3d(W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WXO => new V3d(W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WXI => new V3d(W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WXN => new V3d(W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WXX => new V3d(W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d WXY\n        {\n            readonly get => new V3d(W, X, Y);\n            set { W = value.X; X = value.Y; Y = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d WXZ\n        {\n            readonly get => new V3d(W, X, Z);\n            set { W = value.X; X = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WXW => new V3d(W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WYO => new V3d(W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WYI => new V3d(W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WYN => new V3d(W, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d WYX\n        {\n            readonly get => new V3d(W, Y, X);\n            set { W = value.X; Y = value.Y; X = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WYY => new V3d(W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d WYZ\n        {\n            readonly get => new V3d(W, Y, Z);\n            set { W = value.X; Y = value.Y; Z = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WYW => new V3d(W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WZO => new V3d(W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WZI => new V3d(W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WZN => new V3d(W, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d WZX\n        {\n            readonly get => new V3d(W, Z, X);\n            set { W = value.X; Z = value.Y; X = value.Z; }\n        }\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3d WZY\n        {\n            readonly get => new V3d(W, Z, Y);\n            set { W = value.X; Z = value.Y; Y = value.Z; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WZZ => new V3d(W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WZW => new V3d(W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WWO => new V3d(W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WWI => new V3d(W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WWN => new V3d(W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WWX => new V3d(W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WWY => new V3d(W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WWZ => new V3d(W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3d WWW => new V3d(W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OOOO => new V4d(0, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OOOI => new V4d(0, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OOON => new V4d(0, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOX => new V4d(0, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOY => new V4d(0, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOZ => new V4d(0, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOOW => new V4d(0, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OOIO => new V4d(0, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OOII => new V4d(0, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OOPN => new V4d(0, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIX => new V4d(0, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIY => new V4d(0, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIZ => new V4d(0, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOIW => new V4d(0, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OONO => new V4d(0, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OONP => new V4d(0, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OONN => new V4d(0, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONX => new V4d(0, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONY => new V4d(0, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONZ => new V4d(0, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OONW => new V4d(0, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXO => new V4d(0, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXI => new V4d(0, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXN => new V4d(0, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXX => new V4d(0, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXY => new V4d(0, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXZ => new V4d(0, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOXW => new V4d(0, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYO => new V4d(0, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYI => new V4d(0, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYN => new V4d(0, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYX => new V4d(0, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYY => new V4d(0, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYZ => new V4d(0, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOYW => new V4d(0, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZO => new V4d(0, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZI => new V4d(0, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZN => new V4d(0, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZX => new V4d(0, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZY => new V4d(0, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZZ => new V4d(0, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOZW => new V4d(0, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOWO => new V4d(0, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOWI => new V4d(0, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOWN => new V4d(0, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOWX => new V4d(0, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOWY => new V4d(0, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOWZ => new V4d(0, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OOWW => new V4d(0, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OIOO => new V4d(0, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OIOI => new V4d(0, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OPON => new V4d(0, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOX => new V4d(0, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOY => new V4d(0, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOZ => new V4d(0, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIOW => new V4d(0, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OIIO => new V4d(0, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OIII => new V4d(0, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OPPN => new V4d(0, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIX => new V4d(0, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIY => new V4d(0, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIZ => new V4d(0, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIIW => new V4d(0, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OPNO => new V4d(0, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OPNP => new V4d(0, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d OPNN => new V4d(0, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNX => new V4d(0, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNY => new V4d(0, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNZ => new V4d(0, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPNW => new V4d(0, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXO => new V4d(0, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXI => new V4d(0, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPXN => new V4d(0, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXX => new V4d(0, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXY => new V4d(0, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXZ => new V4d(0, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIXW => new V4d(0, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYO => new V4d(0, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYI => new V4d(0, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPYN => new V4d(0, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYX => new V4d(0, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYY => new V4d(0, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYZ => new V4d(0, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIYW => new V4d(0, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZO => new V4d(0, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZI => new V4d(0, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPZN => new V4d(0, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZX => new V4d(0, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZY => new V4d(0, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZZ => new V4d(0, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIZW => new V4d(0, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIWO => new V4d(0, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIWI => new V4d(0, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OPWN => new V4d(0, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIWX => new V4d(0, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIWY => new V4d(0, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIWZ => new V4d(0, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OIWW => new V4d(0, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONOO => new V4d(0, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONOP => new V4d(0, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONON => new V4d(0, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOX => new V4d(0, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOY => new V4d(0, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOZ => new V4d(0, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONOW => new V4d(0, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONPO => new V4d(0, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONPP => new V4d(0, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONPN => new V4d(0, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPX => new V4d(0, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPY => new V4d(0, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPZ => new V4d(0, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONPW => new V4d(0, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONNO => new V4d(0, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONNP => new V4d(0, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d ONNN => new V4d(0, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNX => new V4d(0, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNY => new V4d(0, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNZ => new V4d(0, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONNW => new V4d(0, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXO => new V4d(0, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXP => new V4d(0, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXN => new V4d(0, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXX => new V4d(0, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXY => new V4d(0, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXZ => new V4d(0, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONXW => new V4d(0, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYO => new V4d(0, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYP => new V4d(0, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYN => new V4d(0, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYX => new V4d(0, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYY => new V4d(0, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYZ => new V4d(0, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONYW => new V4d(0, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZO => new V4d(0, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZP => new V4d(0, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZN => new V4d(0, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZX => new V4d(0, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZY => new V4d(0, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZZ => new V4d(0, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONZW => new V4d(0, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONWO => new V4d(0, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONWP => new V4d(0, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONWN => new V4d(0, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONWX => new V4d(0, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONWY => new V4d(0, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONWZ => new V4d(0, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ONWW => new V4d(0, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOO => new V4d(0, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOI => new V4d(0, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXON => new V4d(0, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOX => new V4d(0, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOY => new V4d(0, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOZ => new V4d(0, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXOW => new V4d(0, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIO => new V4d(0, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXII => new V4d(0, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXPN => new V4d(0, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIX => new V4d(0, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIY => new V4d(0, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIZ => new V4d(0, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXIW => new V4d(0, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNO => new V4d(0, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNP => new V4d(0, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNN => new V4d(0, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNX => new V4d(0, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNY => new V4d(0, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNZ => new V4d(0, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXNW => new V4d(0, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXO => new V4d(0, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXI => new V4d(0, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXN => new V4d(0, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXX => new V4d(0, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXY => new V4d(0, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXZ => new V4d(0, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXXW => new V4d(0, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYO => new V4d(0, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYI => new V4d(0, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYN => new V4d(0, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYX => new V4d(0, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYY => new V4d(0, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYZ => new V4d(0, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXYW => new V4d(0, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZO => new V4d(0, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZI => new V4d(0, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZN => new V4d(0, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZX => new V4d(0, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZY => new V4d(0, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZZ => new V4d(0, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXZW => new V4d(0, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXWO => new V4d(0, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXWI => new V4d(0, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXWN => new V4d(0, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXWX => new V4d(0, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXWY => new V4d(0, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXWZ => new V4d(0, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OXWW => new V4d(0, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOO => new V4d(0, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOI => new V4d(0, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYON => new V4d(0, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOX => new V4d(0, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOY => new V4d(0, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOZ => new V4d(0, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYOW => new V4d(0, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIO => new V4d(0, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYII => new V4d(0, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYPN => new V4d(0, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIX => new V4d(0, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIY => new V4d(0, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIZ => new V4d(0, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYIW => new V4d(0, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNO => new V4d(0, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNP => new V4d(0, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNN => new V4d(0, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNX => new V4d(0, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNY => new V4d(0, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNZ => new V4d(0, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYNW => new V4d(0, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXO => new V4d(0, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXI => new V4d(0, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXN => new V4d(0, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXX => new V4d(0, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXY => new V4d(0, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXZ => new V4d(0, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYXW => new V4d(0, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYO => new V4d(0, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYI => new V4d(0, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYN => new V4d(0, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYX => new V4d(0, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYY => new V4d(0, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYZ => new V4d(0, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYYW => new V4d(0, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZO => new V4d(0, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZI => new V4d(0, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZN => new V4d(0, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZX => new V4d(0, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZY => new V4d(0, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZZ => new V4d(0, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYZW => new V4d(0, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYWO => new V4d(0, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYWI => new V4d(0, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYWN => new V4d(0, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYWX => new V4d(0, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYWY => new V4d(0, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYWZ => new V4d(0, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OYWW => new V4d(0, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOO => new V4d(0, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOI => new V4d(0, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZON => new V4d(0, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOX => new V4d(0, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOY => new V4d(0, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOZ => new V4d(0, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZOW => new V4d(0, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIO => new V4d(0, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZII => new V4d(0, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZPN => new V4d(0, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIX => new V4d(0, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIY => new V4d(0, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIZ => new V4d(0, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZIW => new V4d(0, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNO => new V4d(0, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNP => new V4d(0, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNN => new V4d(0, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNX => new V4d(0, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNY => new V4d(0, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNZ => new V4d(0, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZNW => new V4d(0, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXO => new V4d(0, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXI => new V4d(0, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXN => new V4d(0, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXX => new V4d(0, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXY => new V4d(0, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXZ => new V4d(0, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZXW => new V4d(0, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYO => new V4d(0, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYI => new V4d(0, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYN => new V4d(0, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYX => new V4d(0, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYY => new V4d(0, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYZ => new V4d(0, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZYW => new V4d(0, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZO => new V4d(0, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZI => new V4d(0, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZN => new V4d(0, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZX => new V4d(0, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZY => new V4d(0, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZZ => new V4d(0, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZZW => new V4d(0, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZWO => new V4d(0, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZWI => new V4d(0, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZWN => new V4d(0, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZWX => new V4d(0, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZWY => new V4d(0, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZWZ => new V4d(0, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OZWW => new V4d(0, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWOO => new V4d(0, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWOI => new V4d(0, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWON => new V4d(0, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWOX => new V4d(0, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWOY => new V4d(0, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWOZ => new V4d(0, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWOW => new V4d(0, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWIO => new V4d(0, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWII => new V4d(0, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWPN => new V4d(0, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWIX => new V4d(0, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWIY => new V4d(0, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWIZ => new V4d(0, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWIW => new V4d(0, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWNO => new V4d(0, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWNP => new V4d(0, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWNN => new V4d(0, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWNX => new V4d(0, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWNY => new V4d(0, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWNZ => new V4d(0, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWNW => new V4d(0, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWXO => new V4d(0, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWXI => new V4d(0, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWXN => new V4d(0, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWXX => new V4d(0, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWXY => new V4d(0, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWXZ => new V4d(0, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWXW => new V4d(0, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWYO => new V4d(0, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWYI => new V4d(0, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWYN => new V4d(0, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWYX => new V4d(0, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWYY => new V4d(0, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWYZ => new V4d(0, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWYW => new V4d(0, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWZO => new V4d(0, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWZI => new V4d(0, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWZN => new V4d(0, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWZX => new V4d(0, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWZY => new V4d(0, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWZZ => new V4d(0, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWZW => new V4d(0, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWWO => new V4d(0, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWWI => new V4d(0, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWWN => new V4d(0, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWWX => new V4d(0, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWWY => new V4d(0, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWWZ => new V4d(0, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d OWWW => new V4d(0, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d IOOO => new V4d(1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d IOOI => new V4d(1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d POON => new V4d(1, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOX => new V4d(1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOY => new V4d(1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOZ => new V4d(1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOOW => new V4d(1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d IOIO => new V4d(1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d IOII => new V4d(1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d POPN => new V4d(1, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIX => new V4d(1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIY => new V4d(1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIZ => new V4d(1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOIW => new V4d(1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PONO => new V4d(1, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PONP => new V4d(1, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PONN => new V4d(1, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONX => new V4d(1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONY => new V4d(1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONZ => new V4d(1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PONW => new V4d(1, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXO => new V4d(1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXI => new V4d(1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POXN => new V4d(1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXX => new V4d(1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXY => new V4d(1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXZ => new V4d(1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOXW => new V4d(1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYO => new V4d(1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYI => new V4d(1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POYN => new V4d(1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYX => new V4d(1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYY => new V4d(1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYZ => new V4d(1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOYW => new V4d(1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZO => new V4d(1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZI => new V4d(1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POZN => new V4d(1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZX => new V4d(1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZY => new V4d(1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZZ => new V4d(1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOZW => new V4d(1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOWO => new V4d(1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOWI => new V4d(1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d POWN => new V4d(1, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOWX => new V4d(1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOWY => new V4d(1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOWZ => new V4d(1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IOWW => new V4d(1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d IIOO => new V4d(1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d IIOI => new V4d(1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PPON => new V4d(1, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOX => new V4d(1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOY => new V4d(1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOZ => new V4d(1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIOW => new V4d(1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d IIIO => new V4d(1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d IIII => new V4d(1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PPPN => new V4d(1, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIX => new V4d(1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIY => new V4d(1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIZ => new V4d(1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIIW => new V4d(1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PPNO => new V4d(1, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PPNP => new V4d(1, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PPNN => new V4d(1, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNX => new V4d(1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNY => new V4d(1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNZ => new V4d(1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPNW => new V4d(1, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXO => new V4d(1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXI => new V4d(1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPXN => new V4d(1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXX => new V4d(1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXY => new V4d(1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXZ => new V4d(1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIXW => new V4d(1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYO => new V4d(1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYI => new V4d(1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPYN => new V4d(1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYX => new V4d(1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYY => new V4d(1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYZ => new V4d(1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIYW => new V4d(1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZO => new V4d(1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZI => new V4d(1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPZN => new V4d(1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZX => new V4d(1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZY => new V4d(1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZZ => new V4d(1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIZW => new V4d(1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIWO => new V4d(1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIWI => new V4d(1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PPWN => new V4d(1, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIWX => new V4d(1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIWY => new V4d(1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIWZ => new V4d(1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IIWW => new V4d(1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNOO => new V4d(1, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNOP => new V4d(1, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNON => new V4d(1, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOX => new V4d(1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOY => new V4d(1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOZ => new V4d(1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNOW => new V4d(1, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNPO => new V4d(1, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNPP => new V4d(1, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNPN => new V4d(1, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPX => new V4d(1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPY => new V4d(1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPZ => new V4d(1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNPW => new V4d(1, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNNO => new V4d(1, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNNP => new V4d(1, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d PNNN => new V4d(1, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNX => new V4d(1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNY => new V4d(1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNZ => new V4d(1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNNW => new V4d(1, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXO => new V4d(1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXP => new V4d(1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXN => new V4d(1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXX => new V4d(1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXY => new V4d(1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXZ => new V4d(1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNXW => new V4d(1, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYO => new V4d(1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYP => new V4d(1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYN => new V4d(1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYX => new V4d(1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYY => new V4d(1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYZ => new V4d(1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNYW => new V4d(1, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZO => new V4d(1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZP => new V4d(1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZN => new V4d(1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZX => new V4d(1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZY => new V4d(1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZZ => new V4d(1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNZW => new V4d(1, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNWO => new V4d(1, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNWP => new V4d(1, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNWN => new V4d(1, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNWX => new V4d(1, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNWY => new V4d(1, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNWZ => new V4d(1, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PNWW => new V4d(1, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOO => new V4d(1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOI => new V4d(1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXON => new V4d(1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOX => new V4d(1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOY => new V4d(1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOZ => new V4d(1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXOW => new V4d(1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIO => new V4d(1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXII => new V4d(1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXPN => new V4d(1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIX => new V4d(1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIY => new V4d(1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIZ => new V4d(1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXIW => new V4d(1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNO => new V4d(1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNP => new V4d(1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNN => new V4d(1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNX => new V4d(1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNY => new V4d(1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNZ => new V4d(1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXNW => new V4d(1, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXO => new V4d(1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXI => new V4d(1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXXN => new V4d(1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXX => new V4d(1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXY => new V4d(1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXZ => new V4d(1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXXW => new V4d(1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYO => new V4d(1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYI => new V4d(1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXYN => new V4d(1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYX => new V4d(1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYY => new V4d(1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYZ => new V4d(1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXYW => new V4d(1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZO => new V4d(1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZI => new V4d(1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXZN => new V4d(1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZX => new V4d(1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZY => new V4d(1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZZ => new V4d(1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXZW => new V4d(1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXWO => new V4d(1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXWI => new V4d(1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PXWN => new V4d(1, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXWX => new V4d(1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXWY => new V4d(1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXWZ => new V4d(1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IXWW => new V4d(1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOO => new V4d(1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOI => new V4d(1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYON => new V4d(1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOX => new V4d(1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOY => new V4d(1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOZ => new V4d(1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYOW => new V4d(1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIO => new V4d(1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYII => new V4d(1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYPN => new V4d(1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIX => new V4d(1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIY => new V4d(1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIZ => new V4d(1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYIW => new V4d(1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNO => new V4d(1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNP => new V4d(1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNN => new V4d(1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNX => new V4d(1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNY => new V4d(1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNZ => new V4d(1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYNW => new V4d(1, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXO => new V4d(1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXI => new V4d(1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYXN => new V4d(1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXX => new V4d(1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXY => new V4d(1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXZ => new V4d(1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYXW => new V4d(1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYO => new V4d(1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYI => new V4d(1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYYN => new V4d(1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYX => new V4d(1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYY => new V4d(1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYZ => new V4d(1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYYW => new V4d(1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZO => new V4d(1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZI => new V4d(1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYZN => new V4d(1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZX => new V4d(1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZY => new V4d(1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZZ => new V4d(1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYZW => new V4d(1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYWO => new V4d(1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYWI => new V4d(1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PYWN => new V4d(1, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYWX => new V4d(1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYWY => new V4d(1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYWZ => new V4d(1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IYWW => new V4d(1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOO => new V4d(1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOI => new V4d(1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZON => new V4d(1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOX => new V4d(1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOY => new V4d(1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOZ => new V4d(1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZOW => new V4d(1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIO => new V4d(1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZII => new V4d(1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZPN => new V4d(1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIX => new V4d(1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIY => new V4d(1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIZ => new V4d(1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZIW => new V4d(1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNO => new V4d(1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNP => new V4d(1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNN => new V4d(1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNX => new V4d(1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNY => new V4d(1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNZ => new V4d(1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZNW => new V4d(1, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXO => new V4d(1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXI => new V4d(1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZXN => new V4d(1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXX => new V4d(1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXY => new V4d(1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXZ => new V4d(1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZXW => new V4d(1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYO => new V4d(1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYI => new V4d(1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZYN => new V4d(1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYX => new V4d(1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYY => new V4d(1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYZ => new V4d(1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZYW => new V4d(1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZO => new V4d(1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZI => new V4d(1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZZN => new V4d(1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZX => new V4d(1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZY => new V4d(1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZZ => new V4d(1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZZW => new V4d(1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZWO => new V4d(1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZWI => new V4d(1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PZWN => new V4d(1, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZWX => new V4d(1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZWY => new V4d(1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZWZ => new V4d(1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IZWW => new V4d(1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWOO => new V4d(1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWOI => new V4d(1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWON => new V4d(1, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWOX => new V4d(1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWOY => new V4d(1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWOZ => new V4d(1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWOW => new V4d(1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWIO => new V4d(1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWII => new V4d(1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWPN => new V4d(1, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWIX => new V4d(1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWIY => new V4d(1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWIZ => new V4d(1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWIW => new V4d(1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWNO => new V4d(1, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWNP => new V4d(1, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWNN => new V4d(1, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWNX => new V4d(1, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWNY => new V4d(1, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWNZ => new V4d(1, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWNW => new V4d(1, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWXO => new V4d(1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWXI => new V4d(1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWXN => new V4d(1, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWXX => new V4d(1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWXY => new V4d(1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWXZ => new V4d(1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWXW => new V4d(1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWYO => new V4d(1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWYI => new V4d(1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWYN => new V4d(1, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWYX => new V4d(1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWYY => new V4d(1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWYZ => new V4d(1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWYW => new V4d(1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWZO => new V4d(1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWZI => new V4d(1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWZN => new V4d(1, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWZX => new V4d(1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWZY => new V4d(1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWZZ => new V4d(1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWZW => new V4d(1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWWO => new V4d(1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWWI => new V4d(1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d PWWN => new V4d(1, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWWX => new V4d(1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWWY => new V4d(1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWWZ => new V4d(1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d IWWW => new V4d(1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NOOO => new V4d(-1, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NOOP => new V4d(-1, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NOON => new V4d(-1, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOX => new V4d(-1, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOY => new V4d(-1, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOZ => new V4d(-1, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOOW => new V4d(-1, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NOPO => new V4d(-1, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NOPP => new V4d(-1, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NOPN => new V4d(-1, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPX => new V4d(-1, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPY => new V4d(-1, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPZ => new V4d(-1, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOPW => new V4d(-1, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NONO => new V4d(-1, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NONP => new V4d(-1, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NONN => new V4d(-1, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONX => new V4d(-1, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONY => new V4d(-1, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONZ => new V4d(-1, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NONW => new V4d(-1, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXO => new V4d(-1, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXP => new V4d(-1, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXN => new V4d(-1, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXX => new V4d(-1, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXY => new V4d(-1, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXZ => new V4d(-1, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOXW => new V4d(-1, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYO => new V4d(-1, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYP => new V4d(-1, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYN => new V4d(-1, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYX => new V4d(-1, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYY => new V4d(-1, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYZ => new V4d(-1, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOYW => new V4d(-1, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZO => new V4d(-1, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZP => new V4d(-1, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZN => new V4d(-1, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZX => new V4d(-1, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZY => new V4d(-1, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZZ => new V4d(-1, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOZW => new V4d(-1, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOWO => new V4d(-1, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOWP => new V4d(-1, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOWN => new V4d(-1, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOWX => new V4d(-1, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOWY => new V4d(-1, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOWZ => new V4d(-1, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NOWW => new V4d(-1, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPOO => new V4d(-1, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPOP => new V4d(-1, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPON => new V4d(-1, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOX => new V4d(-1, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOY => new V4d(-1, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOZ => new V4d(-1, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPOW => new V4d(-1, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPPO => new V4d(-1, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPPP => new V4d(-1, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPPN => new V4d(-1, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPX => new V4d(-1, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPY => new V4d(-1, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPZ => new V4d(-1, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPPW => new V4d(-1, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPNO => new V4d(-1, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPNP => new V4d(-1, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NPNN => new V4d(-1, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNX => new V4d(-1, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNY => new V4d(-1, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNZ => new V4d(-1, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPNW => new V4d(-1, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXO => new V4d(-1, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXP => new V4d(-1, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXN => new V4d(-1, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXX => new V4d(-1, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXY => new V4d(-1, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXZ => new V4d(-1, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPXW => new V4d(-1, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYO => new V4d(-1, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYP => new V4d(-1, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYN => new V4d(-1, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYX => new V4d(-1, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYY => new V4d(-1, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYZ => new V4d(-1, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPYW => new V4d(-1, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZO => new V4d(-1, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZP => new V4d(-1, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZN => new V4d(-1, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZX => new V4d(-1, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZY => new V4d(-1, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZZ => new V4d(-1, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPZW => new V4d(-1, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPWO => new V4d(-1, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPWP => new V4d(-1, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPWN => new V4d(-1, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPWX => new V4d(-1, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPWY => new V4d(-1, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPWZ => new V4d(-1, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NPWW => new V4d(-1, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNOO => new V4d(-1, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNOP => new V4d(-1, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNON => new V4d(-1, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOX => new V4d(-1, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOY => new V4d(-1, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOZ => new V4d(-1, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNOW => new V4d(-1, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNPO => new V4d(-1, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNPP => new V4d(-1, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNPN => new V4d(-1, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPX => new V4d(-1, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPY => new V4d(-1, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPZ => new V4d(-1, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNPW => new V4d(-1, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNNO => new V4d(-1, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNNP => new V4d(-1, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static V4d NNNN => new V4d(-1, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNX => new V4d(-1, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNY => new V4d(-1, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNZ => new V4d(-1, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNNW => new V4d(-1, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXO => new V4d(-1, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXP => new V4d(-1, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXN => new V4d(-1, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXX => new V4d(-1, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXY => new V4d(-1, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXZ => new V4d(-1, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNXW => new V4d(-1, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYO => new V4d(-1, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYP => new V4d(-1, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYN => new V4d(-1, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYX => new V4d(-1, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYY => new V4d(-1, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYZ => new V4d(-1, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNYW => new V4d(-1, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZO => new V4d(-1, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZP => new V4d(-1, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZN => new V4d(-1, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZX => new V4d(-1, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZY => new V4d(-1, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZZ => new V4d(-1, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNZW => new V4d(-1, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNWO => new V4d(-1, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNWP => new V4d(-1, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNWN => new V4d(-1, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNWX => new V4d(-1, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNWY => new V4d(-1, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNWZ => new V4d(-1, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NNWW => new V4d(-1, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOO => new V4d(-1, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOP => new V4d(-1, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXON => new V4d(-1, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOX => new V4d(-1, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOY => new V4d(-1, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOZ => new V4d(-1, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXOW => new V4d(-1, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPO => new V4d(-1, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPP => new V4d(-1, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPN => new V4d(-1, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPX => new V4d(-1, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPY => new V4d(-1, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPZ => new V4d(-1, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXPW => new V4d(-1, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNO => new V4d(-1, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNP => new V4d(-1, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNN => new V4d(-1, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNX => new V4d(-1, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNY => new V4d(-1, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNZ => new V4d(-1, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXNW => new V4d(-1, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXO => new V4d(-1, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXP => new V4d(-1, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXN => new V4d(-1, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXX => new V4d(-1, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXY => new V4d(-1, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXZ => new V4d(-1, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXXW => new V4d(-1, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYO => new V4d(-1, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYP => new V4d(-1, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYN => new V4d(-1, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYX => new V4d(-1, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYY => new V4d(-1, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYZ => new V4d(-1, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXYW => new V4d(-1, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZO => new V4d(-1, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZP => new V4d(-1, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZN => new V4d(-1, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZX => new V4d(-1, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZY => new V4d(-1, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZZ => new V4d(-1, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXZW => new V4d(-1, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXWO => new V4d(-1, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXWP => new V4d(-1, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXWN => new V4d(-1, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXWX => new V4d(-1, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXWY => new V4d(-1, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXWZ => new V4d(-1, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NXWW => new V4d(-1, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOO => new V4d(-1, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOP => new V4d(-1, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYON => new V4d(-1, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOX => new V4d(-1, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOY => new V4d(-1, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOZ => new V4d(-1, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYOW => new V4d(-1, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPO => new V4d(-1, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPP => new V4d(-1, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPN => new V4d(-1, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPX => new V4d(-1, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPY => new V4d(-1, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPZ => new V4d(-1, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYPW => new V4d(-1, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNO => new V4d(-1, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNP => new V4d(-1, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNN => new V4d(-1, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNX => new V4d(-1, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNY => new V4d(-1, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNZ => new V4d(-1, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYNW => new V4d(-1, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXO => new V4d(-1, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXP => new V4d(-1, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXN => new V4d(-1, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXX => new V4d(-1, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXY => new V4d(-1, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXZ => new V4d(-1, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYXW => new V4d(-1, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYO => new V4d(-1, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYP => new V4d(-1, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYN => new V4d(-1, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYX => new V4d(-1, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYY => new V4d(-1, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYZ => new V4d(-1, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYYW => new V4d(-1, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZO => new V4d(-1, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZP => new V4d(-1, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZN => new V4d(-1, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZX => new V4d(-1, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZY => new V4d(-1, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZZ => new V4d(-1, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYZW => new V4d(-1, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYWO => new V4d(-1, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYWP => new V4d(-1, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYWN => new V4d(-1, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYWX => new V4d(-1, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYWY => new V4d(-1, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYWZ => new V4d(-1, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NYWW => new V4d(-1, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOO => new V4d(-1, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOP => new V4d(-1, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZON => new V4d(-1, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOX => new V4d(-1, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOY => new V4d(-1, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOZ => new V4d(-1, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZOW => new V4d(-1, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPO => new V4d(-1, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPP => new V4d(-1, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPN => new V4d(-1, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPX => new V4d(-1, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPY => new V4d(-1, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPZ => new V4d(-1, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZPW => new V4d(-1, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNO => new V4d(-1, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNP => new V4d(-1, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNN => new V4d(-1, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNX => new V4d(-1, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNY => new V4d(-1, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNZ => new V4d(-1, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZNW => new V4d(-1, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXO => new V4d(-1, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXP => new V4d(-1, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXN => new V4d(-1, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXX => new V4d(-1, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXY => new V4d(-1, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXZ => new V4d(-1, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZXW => new V4d(-1, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYO => new V4d(-1, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYP => new V4d(-1, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYN => new V4d(-1, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYX => new V4d(-1, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYY => new V4d(-1, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYZ => new V4d(-1, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZYW => new V4d(-1, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZO => new V4d(-1, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZP => new V4d(-1, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZN => new V4d(-1, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZX => new V4d(-1, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZY => new V4d(-1, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZZ => new V4d(-1, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZZW => new V4d(-1, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZWO => new V4d(-1, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZWP => new V4d(-1, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZWN => new V4d(-1, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZWX => new V4d(-1, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZWY => new V4d(-1, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZWZ => new V4d(-1, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NZWW => new V4d(-1, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWOO => new V4d(-1, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWOP => new V4d(-1, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWON => new V4d(-1, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWOX => new V4d(-1, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWOY => new V4d(-1, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWOZ => new V4d(-1, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWOW => new V4d(-1, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWPO => new V4d(-1, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWPP => new V4d(-1, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWPN => new V4d(-1, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWPX => new V4d(-1, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWPY => new V4d(-1, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWPZ => new V4d(-1, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWPW => new V4d(-1, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWNO => new V4d(-1, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWNP => new V4d(-1, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWNN => new V4d(-1, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWNX => new V4d(-1, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWNY => new V4d(-1, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWNZ => new V4d(-1, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWNW => new V4d(-1, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWXO => new V4d(-1, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWXP => new V4d(-1, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWXN => new V4d(-1, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWXX => new V4d(-1, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWXY => new V4d(-1, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWXZ => new V4d(-1, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWXW => new V4d(-1, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWYO => new V4d(-1, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWYP => new V4d(-1, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWYN => new V4d(-1, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWYX => new V4d(-1, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWYY => new V4d(-1, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWYZ => new V4d(-1, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWYW => new V4d(-1, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWZO => new V4d(-1, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWZP => new V4d(-1, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWZN => new V4d(-1, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWZX => new V4d(-1, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWZY => new V4d(-1, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWZZ => new V4d(-1, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWZW => new V4d(-1, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWWO => new V4d(-1, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWWP => new V4d(-1, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWWN => new V4d(-1, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWWX => new V4d(-1, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWWY => new V4d(-1, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWWZ => new V4d(-1, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d NWWW => new V4d(-1, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOO => new V4d(X, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOI => new V4d(X, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOON => new V4d(X, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOX => new V4d(X, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOY => new V4d(X, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOZ => new V4d(X, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOOW => new V4d(X, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIO => new V4d(X, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOII => new V4d(X, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOPN => new V4d(X, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIX => new V4d(X, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIY => new V4d(X, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIZ => new V4d(X, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOIW => new V4d(X, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONO => new V4d(X, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONP => new V4d(X, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONN => new V4d(X, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONX => new V4d(X, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONY => new V4d(X, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONZ => new V4d(X, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XONW => new V4d(X, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXO => new V4d(X, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXI => new V4d(X, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXN => new V4d(X, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXX => new V4d(X, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXY => new V4d(X, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXZ => new V4d(X, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOXW => new V4d(X, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYO => new V4d(X, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYI => new V4d(X, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYN => new V4d(X, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYX => new V4d(X, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYY => new V4d(X, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYZ => new V4d(X, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOYW => new V4d(X, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZO => new V4d(X, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZI => new V4d(X, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZN => new V4d(X, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZX => new V4d(X, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZY => new V4d(X, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZZ => new V4d(X, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOZW => new V4d(X, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOWO => new V4d(X, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOWI => new V4d(X, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOWN => new V4d(X, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOWX => new V4d(X, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOWY => new V4d(X, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOWZ => new V4d(X, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XOWW => new V4d(X, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOO => new V4d(X, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOI => new V4d(X, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPON => new V4d(X, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOX => new V4d(X, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOY => new V4d(X, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOZ => new V4d(X, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIOW => new V4d(X, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIO => new V4d(X, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIII => new V4d(X, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPPN => new V4d(X, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIX => new V4d(X, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIY => new V4d(X, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIZ => new V4d(X, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIIW => new V4d(X, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNO => new V4d(X, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNP => new V4d(X, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNN => new V4d(X, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNX => new V4d(X, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNY => new V4d(X, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNZ => new V4d(X, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPNW => new V4d(X, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXO => new V4d(X, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXI => new V4d(X, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPXN => new V4d(X, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXX => new V4d(X, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXY => new V4d(X, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXZ => new V4d(X, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIXW => new V4d(X, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYO => new V4d(X, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYI => new V4d(X, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPYN => new V4d(X, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYX => new V4d(X, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYY => new V4d(X, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYZ => new V4d(X, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIYW => new V4d(X, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZO => new V4d(X, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZI => new V4d(X, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPZN => new V4d(X, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZX => new V4d(X, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZY => new V4d(X, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZZ => new V4d(X, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIZW => new V4d(X, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIWO => new V4d(X, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIWI => new V4d(X, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XPWN => new V4d(X, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIWX => new V4d(X, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIWY => new V4d(X, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIWZ => new V4d(X, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XIWW => new V4d(X, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOO => new V4d(X, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOP => new V4d(X, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNON => new V4d(X, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOX => new V4d(X, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOY => new V4d(X, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOZ => new V4d(X, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNOW => new V4d(X, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPO => new V4d(X, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPP => new V4d(X, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPN => new V4d(X, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPX => new V4d(X, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPY => new V4d(X, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPZ => new V4d(X, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNPW => new V4d(X, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNO => new V4d(X, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNP => new V4d(X, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNN => new V4d(X, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNX => new V4d(X, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNY => new V4d(X, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNZ => new V4d(X, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNNW => new V4d(X, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXO => new V4d(X, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXP => new V4d(X, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXN => new V4d(X, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXX => new V4d(X, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXY => new V4d(X, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXZ => new V4d(X, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNXW => new V4d(X, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYO => new V4d(X, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYP => new V4d(X, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYN => new V4d(X, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYX => new V4d(X, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYY => new V4d(X, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYZ => new V4d(X, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNYW => new V4d(X, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZO => new V4d(X, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZP => new V4d(X, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZN => new V4d(X, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZX => new V4d(X, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZY => new V4d(X, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZZ => new V4d(X, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNZW => new V4d(X, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNWO => new V4d(X, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNWP => new V4d(X, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNWN => new V4d(X, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNWX => new V4d(X, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNWY => new V4d(X, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNWZ => new V4d(X, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XNWW => new V4d(X, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOO => new V4d(X, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOI => new V4d(X, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXON => new V4d(X, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOX => new V4d(X, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOY => new V4d(X, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOZ => new V4d(X, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXOW => new V4d(X, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIO => new V4d(X, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXII => new V4d(X, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXPN => new V4d(X, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIX => new V4d(X, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIY => new V4d(X, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIZ => new V4d(X, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXIW => new V4d(X, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNO => new V4d(X, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNP => new V4d(X, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNN => new V4d(X, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNX => new V4d(X, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNY => new V4d(X, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNZ => new V4d(X, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXNW => new V4d(X, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXO => new V4d(X, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXI => new V4d(X, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXN => new V4d(X, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXX => new V4d(X, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXY => new V4d(X, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXZ => new V4d(X, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXXW => new V4d(X, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYO => new V4d(X, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYI => new V4d(X, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYN => new V4d(X, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYX => new V4d(X, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYY => new V4d(X, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYZ => new V4d(X, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXYW => new V4d(X, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZO => new V4d(X, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZI => new V4d(X, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZN => new V4d(X, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZX => new V4d(X, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZY => new V4d(X, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZZ => new V4d(X, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXZW => new V4d(X, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXWO => new V4d(X, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXWI => new V4d(X, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXWN => new V4d(X, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXWX => new V4d(X, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXWY => new V4d(X, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXWZ => new V4d(X, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XXWW => new V4d(X, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOO => new V4d(X, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOI => new V4d(X, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYON => new V4d(X, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOX => new V4d(X, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOY => new V4d(X, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOZ => new V4d(X, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYOW => new V4d(X, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIO => new V4d(X, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYII => new V4d(X, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYPN => new V4d(X, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIX => new V4d(X, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIY => new V4d(X, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIZ => new V4d(X, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYIW => new V4d(X, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNO => new V4d(X, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNP => new V4d(X, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNN => new V4d(X, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNX => new V4d(X, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNY => new V4d(X, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNZ => new V4d(X, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYNW => new V4d(X, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXO => new V4d(X, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXI => new V4d(X, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXN => new V4d(X, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXX => new V4d(X, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXY => new V4d(X, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXZ => new V4d(X, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYXW => new V4d(X, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYO => new V4d(X, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYI => new V4d(X, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYN => new V4d(X, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYX => new V4d(X, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYY => new V4d(X, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYZ => new V4d(X, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYYW => new V4d(X, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZO => new V4d(X, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZI => new V4d(X, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZN => new V4d(X, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZX => new V4d(X, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZY => new V4d(X, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYZZ => new V4d(X, Y, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d XYZW\n        {\n            readonly get => new V4d(X, Y, Z, W);\n            set { X = value.X; Y = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYWO => new V4d(X, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYWI => new V4d(X, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYWN => new V4d(X, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYWX => new V4d(X, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYWY => new V4d(X, Y, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d XYWZ\n        {\n            readonly get => new V4d(X, Y, W, Z);\n            set { X = value.X; Y = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XYWW => new V4d(X, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOO => new V4d(X, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOI => new V4d(X, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZON => new V4d(X, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOX => new V4d(X, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOY => new V4d(X, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOZ => new V4d(X, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZOW => new V4d(X, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIO => new V4d(X, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZII => new V4d(X, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZPN => new V4d(X, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIX => new V4d(X, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIY => new V4d(X, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIZ => new V4d(X, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZIW => new V4d(X, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNO => new V4d(X, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNP => new V4d(X, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNN => new V4d(X, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNX => new V4d(X, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNY => new V4d(X, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNZ => new V4d(X, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZNW => new V4d(X, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXO => new V4d(X, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXI => new V4d(X, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXN => new V4d(X, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXX => new V4d(X, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXY => new V4d(X, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXZ => new V4d(X, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZXW => new V4d(X, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYO => new V4d(X, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYI => new V4d(X, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYN => new V4d(X, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYX => new V4d(X, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYY => new V4d(X, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZYZ => new V4d(X, Z, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d XZYW\n        {\n            readonly get => new V4d(X, Z, Y, W);\n            set { X = value.X; Z = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZO => new V4d(X, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZI => new V4d(X, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZN => new V4d(X, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZX => new V4d(X, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZY => new V4d(X, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZZ => new V4d(X, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZZW => new V4d(X, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZWO => new V4d(X, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZWI => new V4d(X, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZWN => new V4d(X, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZWX => new V4d(X, Z, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d XZWY\n        {\n            readonly get => new V4d(X, Z, W, Y);\n            set { X = value.X; Z = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZWZ => new V4d(X, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XZWW => new V4d(X, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWOO => new V4d(X, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWOI => new V4d(X, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWON => new V4d(X, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWOX => new V4d(X, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWOY => new V4d(X, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWOZ => new V4d(X, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWOW => new V4d(X, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWIO => new V4d(X, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWII => new V4d(X, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWPN => new V4d(X, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWIX => new V4d(X, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWIY => new V4d(X, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWIZ => new V4d(X, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWIW => new V4d(X, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWNO => new V4d(X, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWNP => new V4d(X, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWNN => new V4d(X, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWNX => new V4d(X, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWNY => new V4d(X, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWNZ => new V4d(X, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWNW => new V4d(X, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWXO => new V4d(X, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWXI => new V4d(X, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWXN => new V4d(X, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWXX => new V4d(X, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWXY => new V4d(X, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWXZ => new V4d(X, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWXW => new V4d(X, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWYO => new V4d(X, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWYI => new V4d(X, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWYN => new V4d(X, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWYX => new V4d(X, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWYY => new V4d(X, W, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d XWYZ\n        {\n            readonly get => new V4d(X, W, Y, Z);\n            set { X = value.X; W = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWYW => new V4d(X, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWZO => new V4d(X, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWZI => new V4d(X, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWZN => new V4d(X, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWZX => new V4d(X, W, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d XWZY\n        {\n            readonly get => new V4d(X, W, Z, Y);\n            set { X = value.X; W = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWZZ => new V4d(X, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWZW => new V4d(X, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWWO => new V4d(X, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWWI => new V4d(X, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWWN => new V4d(X, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWWX => new V4d(X, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWWY => new V4d(X, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWWZ => new V4d(X, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d XWWW => new V4d(X, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOO => new V4d(Y, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOI => new V4d(Y, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOON => new V4d(Y, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOX => new V4d(Y, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOY => new V4d(Y, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOZ => new V4d(Y, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOOW => new V4d(Y, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIO => new V4d(Y, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOII => new V4d(Y, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOPN => new V4d(Y, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIX => new V4d(Y, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIY => new V4d(Y, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIZ => new V4d(Y, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOIW => new V4d(Y, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONO => new V4d(Y, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONP => new V4d(Y, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONN => new V4d(Y, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONX => new V4d(Y, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONY => new V4d(Y, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONZ => new V4d(Y, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YONW => new V4d(Y, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXO => new V4d(Y, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXI => new V4d(Y, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXN => new V4d(Y, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXX => new V4d(Y, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXY => new V4d(Y, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXZ => new V4d(Y, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOXW => new V4d(Y, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYO => new V4d(Y, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYI => new V4d(Y, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYN => new V4d(Y, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYX => new V4d(Y, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYY => new V4d(Y, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYZ => new V4d(Y, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOYW => new V4d(Y, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZO => new V4d(Y, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZI => new V4d(Y, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZN => new V4d(Y, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZX => new V4d(Y, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZY => new V4d(Y, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZZ => new V4d(Y, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOZW => new V4d(Y, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOWO => new V4d(Y, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOWI => new V4d(Y, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOWN => new V4d(Y, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOWX => new V4d(Y, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOWY => new V4d(Y, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOWZ => new V4d(Y, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YOWW => new V4d(Y, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOO => new V4d(Y, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOI => new V4d(Y, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPON => new V4d(Y, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOX => new V4d(Y, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOY => new V4d(Y, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOZ => new V4d(Y, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIOW => new V4d(Y, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIO => new V4d(Y, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIII => new V4d(Y, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPPN => new V4d(Y, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIX => new V4d(Y, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIY => new V4d(Y, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIZ => new V4d(Y, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIIW => new V4d(Y, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNO => new V4d(Y, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNP => new V4d(Y, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNN => new V4d(Y, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNX => new V4d(Y, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNY => new V4d(Y, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNZ => new V4d(Y, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPNW => new V4d(Y, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXO => new V4d(Y, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXI => new V4d(Y, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPXN => new V4d(Y, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXX => new V4d(Y, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXY => new V4d(Y, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXZ => new V4d(Y, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIXW => new V4d(Y, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYO => new V4d(Y, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYI => new V4d(Y, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPYN => new V4d(Y, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYX => new V4d(Y, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYY => new V4d(Y, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYZ => new V4d(Y, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIYW => new V4d(Y, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZO => new V4d(Y, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZI => new V4d(Y, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPZN => new V4d(Y, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZX => new V4d(Y, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZY => new V4d(Y, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZZ => new V4d(Y, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIZW => new V4d(Y, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIWO => new V4d(Y, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIWI => new V4d(Y, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YPWN => new V4d(Y, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIWX => new V4d(Y, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIWY => new V4d(Y, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIWZ => new V4d(Y, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YIWW => new V4d(Y, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOO => new V4d(Y, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOP => new V4d(Y, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNON => new V4d(Y, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOX => new V4d(Y, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOY => new V4d(Y, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOZ => new V4d(Y, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNOW => new V4d(Y, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPO => new V4d(Y, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPP => new V4d(Y, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPN => new V4d(Y, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPX => new V4d(Y, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPY => new V4d(Y, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPZ => new V4d(Y, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNPW => new V4d(Y, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNO => new V4d(Y, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNP => new V4d(Y, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNN => new V4d(Y, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNX => new V4d(Y, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNY => new V4d(Y, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNZ => new V4d(Y, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNNW => new V4d(Y, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXO => new V4d(Y, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXP => new V4d(Y, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXN => new V4d(Y, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXX => new V4d(Y, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXY => new V4d(Y, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXZ => new V4d(Y, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNXW => new V4d(Y, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYO => new V4d(Y, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYP => new V4d(Y, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYN => new V4d(Y, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYX => new V4d(Y, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYY => new V4d(Y, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYZ => new V4d(Y, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNYW => new V4d(Y, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZO => new V4d(Y, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZP => new V4d(Y, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZN => new V4d(Y, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZX => new V4d(Y, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZY => new V4d(Y, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZZ => new V4d(Y, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNZW => new V4d(Y, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNWO => new V4d(Y, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNWP => new V4d(Y, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNWN => new V4d(Y, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNWX => new V4d(Y, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNWY => new V4d(Y, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNWZ => new V4d(Y, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YNWW => new V4d(Y, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOO => new V4d(Y, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOI => new V4d(Y, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXON => new V4d(Y, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOX => new V4d(Y, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOY => new V4d(Y, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOZ => new V4d(Y, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXOW => new V4d(Y, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIO => new V4d(Y, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXII => new V4d(Y, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXPN => new V4d(Y, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIX => new V4d(Y, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIY => new V4d(Y, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIZ => new V4d(Y, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXIW => new V4d(Y, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNO => new V4d(Y, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNP => new V4d(Y, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNN => new V4d(Y, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNX => new V4d(Y, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNY => new V4d(Y, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNZ => new V4d(Y, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXNW => new V4d(Y, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXO => new V4d(Y, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXI => new V4d(Y, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXN => new V4d(Y, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXX => new V4d(Y, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXY => new V4d(Y, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXZ => new V4d(Y, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXXW => new V4d(Y, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYO => new V4d(Y, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYI => new V4d(Y, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYN => new V4d(Y, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYX => new V4d(Y, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYY => new V4d(Y, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYZ => new V4d(Y, X, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXYW => new V4d(Y, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZO => new V4d(Y, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZI => new V4d(Y, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZN => new V4d(Y, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZX => new V4d(Y, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZY => new V4d(Y, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXZZ => new V4d(Y, X, Z, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d YXZW\n        {\n            readonly get => new V4d(Y, X, Z, W);\n            set { Y = value.X; X = value.Y; Z = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXWO => new V4d(Y, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXWI => new V4d(Y, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXWN => new V4d(Y, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXWX => new V4d(Y, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXWY => new V4d(Y, X, W, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d YXWZ\n        {\n            readonly get => new V4d(Y, X, W, Z);\n            set { Y = value.X; X = value.Y; W = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YXWW => new V4d(Y, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOO => new V4d(Y, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOI => new V4d(Y, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYON => new V4d(Y, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOX => new V4d(Y, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOY => new V4d(Y, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOZ => new V4d(Y, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYOW => new V4d(Y, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIO => new V4d(Y, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYII => new V4d(Y, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYPN => new V4d(Y, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIX => new V4d(Y, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIY => new V4d(Y, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIZ => new V4d(Y, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYIW => new V4d(Y, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNO => new V4d(Y, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNP => new V4d(Y, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNN => new V4d(Y, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNX => new V4d(Y, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNY => new V4d(Y, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNZ => new V4d(Y, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYNW => new V4d(Y, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXO => new V4d(Y, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXI => new V4d(Y, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXN => new V4d(Y, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXX => new V4d(Y, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXY => new V4d(Y, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXZ => new V4d(Y, Y, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYXW => new V4d(Y, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYO => new V4d(Y, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYI => new V4d(Y, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYN => new V4d(Y, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYX => new V4d(Y, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYY => new V4d(Y, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYZ => new V4d(Y, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYYW => new V4d(Y, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZO => new V4d(Y, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZI => new V4d(Y, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZN => new V4d(Y, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZX => new V4d(Y, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZY => new V4d(Y, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZZ => new V4d(Y, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYZW => new V4d(Y, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYWO => new V4d(Y, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYWI => new V4d(Y, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYWN => new V4d(Y, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYWX => new V4d(Y, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYWY => new V4d(Y, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYWZ => new V4d(Y, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YYWW => new V4d(Y, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOO => new V4d(Y, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOI => new V4d(Y, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZON => new V4d(Y, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOX => new V4d(Y, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOY => new V4d(Y, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOZ => new V4d(Y, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZOW => new V4d(Y, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIO => new V4d(Y, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZII => new V4d(Y, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZPN => new V4d(Y, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIX => new V4d(Y, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIY => new V4d(Y, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIZ => new V4d(Y, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZIW => new V4d(Y, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNO => new V4d(Y, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNP => new V4d(Y, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNN => new V4d(Y, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNX => new V4d(Y, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNY => new V4d(Y, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNZ => new V4d(Y, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZNW => new V4d(Y, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXO => new V4d(Y, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXI => new V4d(Y, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXN => new V4d(Y, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXX => new V4d(Y, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXY => new V4d(Y, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZXZ => new V4d(Y, Z, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d YZXW\n        {\n            readonly get => new V4d(Y, Z, X, W);\n            set { Y = value.X; Z = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYO => new V4d(Y, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYI => new V4d(Y, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYN => new V4d(Y, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYX => new V4d(Y, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYY => new V4d(Y, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYZ => new V4d(Y, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZYW => new V4d(Y, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZO => new V4d(Y, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZI => new V4d(Y, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZN => new V4d(Y, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZX => new V4d(Y, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZY => new V4d(Y, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZZ => new V4d(Y, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZZW => new V4d(Y, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZWO => new V4d(Y, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZWI => new V4d(Y, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZWN => new V4d(Y, Z, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d YZWX\n        {\n            readonly get => new V4d(Y, Z, W, X);\n            set { Y = value.X; Z = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZWY => new V4d(Y, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZWZ => new V4d(Y, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YZWW => new V4d(Y, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWOO => new V4d(Y, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWOI => new V4d(Y, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWON => new V4d(Y, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWOX => new V4d(Y, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWOY => new V4d(Y, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWOZ => new V4d(Y, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWOW => new V4d(Y, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWIO => new V4d(Y, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWII => new V4d(Y, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWPN => new V4d(Y, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWIX => new V4d(Y, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWIY => new V4d(Y, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWIZ => new V4d(Y, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWIW => new V4d(Y, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWNO => new V4d(Y, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWNP => new V4d(Y, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWNN => new V4d(Y, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWNX => new V4d(Y, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWNY => new V4d(Y, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWNZ => new V4d(Y, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWNW => new V4d(Y, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWXO => new V4d(Y, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWXI => new V4d(Y, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWXN => new V4d(Y, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWXX => new V4d(Y, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWXY => new V4d(Y, W, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d YWXZ\n        {\n            readonly get => new V4d(Y, W, X, Z);\n            set { Y = value.X; W = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWXW => new V4d(Y, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWYO => new V4d(Y, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWYI => new V4d(Y, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWYN => new V4d(Y, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWYX => new V4d(Y, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWYY => new V4d(Y, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWYZ => new V4d(Y, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWYW => new V4d(Y, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWZO => new V4d(Y, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWZI => new V4d(Y, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWZN => new V4d(Y, W, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d YWZX\n        {\n            readonly get => new V4d(Y, W, Z, X);\n            set { Y = value.X; W = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWZY => new V4d(Y, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWZZ => new V4d(Y, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWZW => new V4d(Y, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWWO => new V4d(Y, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWWI => new V4d(Y, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWWN => new V4d(Y, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWWX => new V4d(Y, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWWY => new V4d(Y, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWWZ => new V4d(Y, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d YWWW => new V4d(Y, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOO => new V4d(Z, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOI => new V4d(Z, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOON => new V4d(Z, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOX => new V4d(Z, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOY => new V4d(Z, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOZ => new V4d(Z, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOOW => new V4d(Z, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIO => new V4d(Z, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOII => new V4d(Z, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOPN => new V4d(Z, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIX => new V4d(Z, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIY => new V4d(Z, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIZ => new V4d(Z, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOIW => new V4d(Z, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONO => new V4d(Z, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONP => new V4d(Z, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONN => new V4d(Z, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONX => new V4d(Z, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONY => new V4d(Z, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONZ => new V4d(Z, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZONW => new V4d(Z, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXO => new V4d(Z, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXI => new V4d(Z, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXN => new V4d(Z, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXX => new V4d(Z, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXY => new V4d(Z, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXZ => new V4d(Z, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOXW => new V4d(Z, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYO => new V4d(Z, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYI => new V4d(Z, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYN => new V4d(Z, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYX => new V4d(Z, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYY => new V4d(Z, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYZ => new V4d(Z, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOYW => new V4d(Z, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZO => new V4d(Z, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZI => new V4d(Z, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZN => new V4d(Z, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZX => new V4d(Z, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZY => new V4d(Z, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZZ => new V4d(Z, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOZW => new V4d(Z, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOWO => new V4d(Z, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOWI => new V4d(Z, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOWN => new V4d(Z, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOWX => new V4d(Z, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOWY => new V4d(Z, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOWZ => new V4d(Z, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZOWW => new V4d(Z, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOO => new V4d(Z, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOI => new V4d(Z, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPON => new V4d(Z, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOX => new V4d(Z, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOY => new V4d(Z, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOZ => new V4d(Z, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIOW => new V4d(Z, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIO => new V4d(Z, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIII => new V4d(Z, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPPN => new V4d(Z, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIX => new V4d(Z, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIY => new V4d(Z, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIZ => new V4d(Z, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIIW => new V4d(Z, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNO => new V4d(Z, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNP => new V4d(Z, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNN => new V4d(Z, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNX => new V4d(Z, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNY => new V4d(Z, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNZ => new V4d(Z, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPNW => new V4d(Z, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXO => new V4d(Z, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXI => new V4d(Z, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPXN => new V4d(Z, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXX => new V4d(Z, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXY => new V4d(Z, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXZ => new V4d(Z, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIXW => new V4d(Z, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYO => new V4d(Z, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYI => new V4d(Z, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPYN => new V4d(Z, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYX => new V4d(Z, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYY => new V4d(Z, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYZ => new V4d(Z, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIYW => new V4d(Z, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZO => new V4d(Z, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZI => new V4d(Z, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPZN => new V4d(Z, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZX => new V4d(Z, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZY => new V4d(Z, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZZ => new V4d(Z, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIZW => new V4d(Z, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIWO => new V4d(Z, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIWI => new V4d(Z, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZPWN => new V4d(Z, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIWX => new V4d(Z, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIWY => new V4d(Z, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIWZ => new V4d(Z, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZIWW => new V4d(Z, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOO => new V4d(Z, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOP => new V4d(Z, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNON => new V4d(Z, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOX => new V4d(Z, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOY => new V4d(Z, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOZ => new V4d(Z, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNOW => new V4d(Z, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPO => new V4d(Z, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPP => new V4d(Z, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPN => new V4d(Z, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPX => new V4d(Z, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPY => new V4d(Z, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPZ => new V4d(Z, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNPW => new V4d(Z, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNO => new V4d(Z, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNP => new V4d(Z, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNN => new V4d(Z, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNX => new V4d(Z, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNY => new V4d(Z, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNZ => new V4d(Z, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNNW => new V4d(Z, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXO => new V4d(Z, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXP => new V4d(Z, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXN => new V4d(Z, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXX => new V4d(Z, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXY => new V4d(Z, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXZ => new V4d(Z, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNXW => new V4d(Z, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYO => new V4d(Z, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYP => new V4d(Z, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYN => new V4d(Z, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYX => new V4d(Z, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYY => new V4d(Z, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYZ => new V4d(Z, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNYW => new V4d(Z, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZO => new V4d(Z, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZP => new V4d(Z, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZN => new V4d(Z, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZX => new V4d(Z, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZY => new V4d(Z, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZZ => new V4d(Z, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNZW => new V4d(Z, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNWO => new V4d(Z, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNWP => new V4d(Z, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNWN => new V4d(Z, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNWX => new V4d(Z, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNWY => new V4d(Z, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNWZ => new V4d(Z, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZNWW => new V4d(Z, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOO => new V4d(Z, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOI => new V4d(Z, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXON => new V4d(Z, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOX => new V4d(Z, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOY => new V4d(Z, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOZ => new V4d(Z, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXOW => new V4d(Z, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIO => new V4d(Z, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXII => new V4d(Z, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXPN => new V4d(Z, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIX => new V4d(Z, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIY => new V4d(Z, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIZ => new V4d(Z, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXIW => new V4d(Z, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNO => new V4d(Z, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNP => new V4d(Z, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNN => new V4d(Z, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNX => new V4d(Z, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNY => new V4d(Z, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNZ => new V4d(Z, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXNW => new V4d(Z, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXO => new V4d(Z, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXI => new V4d(Z, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXN => new V4d(Z, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXX => new V4d(Z, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXY => new V4d(Z, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXZ => new V4d(Z, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXXW => new V4d(Z, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYO => new V4d(Z, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYI => new V4d(Z, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYN => new V4d(Z, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYX => new V4d(Z, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYY => new V4d(Z, X, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXYZ => new V4d(Z, X, Y, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d ZXYW\n        {\n            readonly get => new V4d(Z, X, Y, W);\n            set { Z = value.X; X = value.Y; Y = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZO => new V4d(Z, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZI => new V4d(Z, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZN => new V4d(Z, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZX => new V4d(Z, X, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZY => new V4d(Z, X, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZZ => new V4d(Z, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXZW => new V4d(Z, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXWO => new V4d(Z, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXWI => new V4d(Z, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXWN => new V4d(Z, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXWX => new V4d(Z, X, W, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d ZXWY\n        {\n            readonly get => new V4d(Z, X, W, Y);\n            set { Z = value.X; X = value.Y; W = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXWZ => new V4d(Z, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZXWW => new V4d(Z, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOO => new V4d(Z, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOI => new V4d(Z, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYON => new V4d(Z, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOX => new V4d(Z, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOY => new V4d(Z, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOZ => new V4d(Z, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYOW => new V4d(Z, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIO => new V4d(Z, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYII => new V4d(Z, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYPN => new V4d(Z, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIX => new V4d(Z, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIY => new V4d(Z, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIZ => new V4d(Z, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYIW => new V4d(Z, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNO => new V4d(Z, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNP => new V4d(Z, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNN => new V4d(Z, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNX => new V4d(Z, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNY => new V4d(Z, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNZ => new V4d(Z, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYNW => new V4d(Z, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXO => new V4d(Z, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXI => new V4d(Z, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXN => new V4d(Z, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXX => new V4d(Z, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXY => new V4d(Z, Y, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYXZ => new V4d(Z, Y, X, Z);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d ZYXW\n        {\n            readonly get => new V4d(Z, Y, X, W);\n            set { Z = value.X; Y = value.Y; X = value.Z; W = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYO => new V4d(Z, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYI => new V4d(Z, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYN => new V4d(Z, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYX => new V4d(Z, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYY => new V4d(Z, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYZ => new V4d(Z, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYYW => new V4d(Z, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZO => new V4d(Z, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZI => new V4d(Z, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZN => new V4d(Z, Y, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZX => new V4d(Z, Y, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZY => new V4d(Z, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZZ => new V4d(Z, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYZW => new V4d(Z, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYWO => new V4d(Z, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYWI => new V4d(Z, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYWN => new V4d(Z, Y, W, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d ZYWX\n        {\n            readonly get => new V4d(Z, Y, W, X);\n            set { Z = value.X; Y = value.Y; W = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYWY => new V4d(Z, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYWZ => new V4d(Z, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZYWW => new V4d(Z, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOO => new V4d(Z, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOI => new V4d(Z, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZON => new V4d(Z, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOX => new V4d(Z, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOY => new V4d(Z, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOZ => new V4d(Z, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZOW => new V4d(Z, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIO => new V4d(Z, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZII => new V4d(Z, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZPN => new V4d(Z, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIX => new V4d(Z, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIY => new V4d(Z, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIZ => new V4d(Z, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZIW => new V4d(Z, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNO => new V4d(Z, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNP => new V4d(Z, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNN => new V4d(Z, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNX => new V4d(Z, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNY => new V4d(Z, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNZ => new V4d(Z, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZNW => new V4d(Z, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXO => new V4d(Z, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXI => new V4d(Z, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXN => new V4d(Z, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXX => new V4d(Z, Z, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXY => new V4d(Z, Z, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXZ => new V4d(Z, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZXW => new V4d(Z, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYO => new V4d(Z, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYI => new V4d(Z, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYN => new V4d(Z, Z, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYX => new V4d(Z, Z, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYY => new V4d(Z, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYZ => new V4d(Z, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZYW => new V4d(Z, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZO => new V4d(Z, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZI => new V4d(Z, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZN => new V4d(Z, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZX => new V4d(Z, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZY => new V4d(Z, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZZ => new V4d(Z, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZZW => new V4d(Z, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZWO => new V4d(Z, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZWI => new V4d(Z, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZWN => new V4d(Z, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZWX => new V4d(Z, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZWY => new V4d(Z, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZWZ => new V4d(Z, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZZWW => new V4d(Z, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWOO => new V4d(Z, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWOI => new V4d(Z, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWON => new V4d(Z, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWOX => new V4d(Z, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWOY => new V4d(Z, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWOZ => new V4d(Z, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWOW => new V4d(Z, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWIO => new V4d(Z, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWII => new V4d(Z, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWPN => new V4d(Z, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWIX => new V4d(Z, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWIY => new V4d(Z, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWIZ => new V4d(Z, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWIW => new V4d(Z, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWNO => new V4d(Z, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWNP => new V4d(Z, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWNN => new V4d(Z, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWNX => new V4d(Z, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWNY => new V4d(Z, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWNZ => new V4d(Z, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWNW => new V4d(Z, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWXO => new V4d(Z, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWXI => new V4d(Z, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWXN => new V4d(Z, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWXX => new V4d(Z, W, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d ZWXY\n        {\n            readonly get => new V4d(Z, W, X, Y);\n            set { Z = value.X; W = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWXZ => new V4d(Z, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWXW => new V4d(Z, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWYO => new V4d(Z, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWYI => new V4d(Z, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWYN => new V4d(Z, W, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d ZWYX\n        {\n            readonly get => new V4d(Z, W, Y, X);\n            set { Z = value.X; W = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWYY => new V4d(Z, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWYZ => new V4d(Z, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWYW => new V4d(Z, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWZO => new V4d(Z, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWZI => new V4d(Z, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWZN => new V4d(Z, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWZX => new V4d(Z, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWZY => new V4d(Z, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWZZ => new V4d(Z, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWZW => new V4d(Z, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWWO => new V4d(Z, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWWI => new V4d(Z, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWWN => new V4d(Z, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWWX => new V4d(Z, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWWY => new V4d(Z, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWWZ => new V4d(Z, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d ZWWW => new V4d(Z, W, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOOO => new V4d(W, 0, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOOI => new V4d(W, 0, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOON => new V4d(W, 0, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOOX => new V4d(W, 0, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOOY => new V4d(W, 0, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOOZ => new V4d(W, 0, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOOW => new V4d(W, 0, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOIO => new V4d(W, 0, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOII => new V4d(W, 0, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOPN => new V4d(W, 0, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOIX => new V4d(W, 0, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOIY => new V4d(W, 0, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOIZ => new V4d(W, 0, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOIW => new V4d(W, 0, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WONO => new V4d(W, 0, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WONP => new V4d(W, 0, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WONN => new V4d(W, 0, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WONX => new V4d(W, 0, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WONY => new V4d(W, 0, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WONZ => new V4d(W, 0, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WONW => new V4d(W, 0, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOXO => new V4d(W, 0, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOXI => new V4d(W, 0, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOXN => new V4d(W, 0, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOXX => new V4d(W, 0, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOXY => new V4d(W, 0, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOXZ => new V4d(W, 0, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOXW => new V4d(W, 0, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOYO => new V4d(W, 0, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOYI => new V4d(W, 0, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOYN => new V4d(W, 0, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOYX => new V4d(W, 0, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOYY => new V4d(W, 0, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOYZ => new V4d(W, 0, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOYW => new V4d(W, 0, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOZO => new V4d(W, 0, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOZI => new V4d(W, 0, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOZN => new V4d(W, 0, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOZX => new V4d(W, 0, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOZY => new V4d(W, 0, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOZZ => new V4d(W, 0, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOZW => new V4d(W, 0, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOWO => new V4d(W, 0, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOWI => new V4d(W, 0, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOWN => new V4d(W, 0, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOWX => new V4d(W, 0, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOWY => new V4d(W, 0, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOWZ => new V4d(W, 0, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WOWW => new V4d(W, 0, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIOO => new V4d(W, 1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIOI => new V4d(W, 1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPON => new V4d(W, 1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIOX => new V4d(W, 1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIOY => new V4d(W, 1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIOZ => new V4d(W, 1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIOW => new V4d(W, 1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIIO => new V4d(W, 1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIII => new V4d(W, 1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPPN => new V4d(W, 1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIIX => new V4d(W, 1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIIY => new V4d(W, 1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIIZ => new V4d(W, 1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIIW => new V4d(W, 1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPNO => new V4d(W, 1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPNP => new V4d(W, 1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPNN => new V4d(W, 1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPNX => new V4d(W, 1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPNY => new V4d(W, 1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPNZ => new V4d(W, 1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPNW => new V4d(W, 1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIXO => new V4d(W, 1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIXI => new V4d(W, 1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPXN => new V4d(W, 1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIXX => new V4d(W, 1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIXY => new V4d(W, 1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIXZ => new V4d(W, 1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIXW => new V4d(W, 1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIYO => new V4d(W, 1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIYI => new V4d(W, 1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPYN => new V4d(W, 1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIYX => new V4d(W, 1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIYY => new V4d(W, 1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIYZ => new V4d(W, 1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIYW => new V4d(W, 1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIZO => new V4d(W, 1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIZI => new V4d(W, 1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPZN => new V4d(W, 1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIZX => new V4d(W, 1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIZY => new V4d(W, 1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIZZ => new V4d(W, 1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIZW => new V4d(W, 1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIWO => new V4d(W, 1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIWI => new V4d(W, 1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WPWN => new V4d(W, 1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIWX => new V4d(W, 1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIWY => new V4d(W, 1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIWZ => new V4d(W, 1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WIWW => new V4d(W, 1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNOO => new V4d(W, -1, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNOP => new V4d(W, -1, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNON => new V4d(W, -1, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNOX => new V4d(W, -1, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNOY => new V4d(W, -1, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNOZ => new V4d(W, -1, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNOW => new V4d(W, -1, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNPO => new V4d(W, -1, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNPP => new V4d(W, -1, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNPN => new V4d(W, -1, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNPX => new V4d(W, -1, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNPY => new V4d(W, -1, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNPZ => new V4d(W, -1, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNPW => new V4d(W, -1, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNNO => new V4d(W, -1, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNNP => new V4d(W, -1, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNNN => new V4d(W, -1, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNNX => new V4d(W, -1, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNNY => new V4d(W, -1, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNNZ => new V4d(W, -1, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNNW => new V4d(W, -1, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNXO => new V4d(W, -1, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNXP => new V4d(W, -1, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNXN => new V4d(W, -1, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNXX => new V4d(W, -1, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNXY => new V4d(W, -1, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNXZ => new V4d(W, -1, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNXW => new V4d(W, -1, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNYO => new V4d(W, -1, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNYP => new V4d(W, -1, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNYN => new V4d(W, -1, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNYX => new V4d(W, -1, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNYY => new V4d(W, -1, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNYZ => new V4d(W, -1, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNYW => new V4d(W, -1, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNZO => new V4d(W, -1, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNZP => new V4d(W, -1, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNZN => new V4d(W, -1, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNZX => new V4d(W, -1, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNZY => new V4d(W, -1, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNZZ => new V4d(W, -1, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNZW => new V4d(W, -1, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNWO => new V4d(W, -1, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNWP => new V4d(W, -1, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNWN => new V4d(W, -1, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNWX => new V4d(W, -1, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNWY => new V4d(W, -1, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNWZ => new V4d(W, -1, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WNWW => new V4d(W, -1, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXOO => new V4d(W, X, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXOI => new V4d(W, X, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXON => new V4d(W, X, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXOX => new V4d(W, X, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXOY => new V4d(W, X, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXOZ => new V4d(W, X, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXOW => new V4d(W, X, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXIO => new V4d(W, X, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXII => new V4d(W, X, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXPN => new V4d(W, X, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXIX => new V4d(W, X, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXIY => new V4d(W, X, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXIZ => new V4d(W, X, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXIW => new V4d(W, X, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXNO => new V4d(W, X, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXNP => new V4d(W, X, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXNN => new V4d(W, X, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXNX => new V4d(W, X, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXNY => new V4d(W, X, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXNZ => new V4d(W, X, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXNW => new V4d(W, X, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXXO => new V4d(W, X, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXXI => new V4d(W, X, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXXN => new V4d(W, X, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXXX => new V4d(W, X, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXXY => new V4d(W, X, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXXZ => new V4d(W, X, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXXW => new V4d(W, X, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXYO => new V4d(W, X, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXYI => new V4d(W, X, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXYN => new V4d(W, X, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXYX => new V4d(W, X, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXYY => new V4d(W, X, Y, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d WXYZ\n        {\n            readonly get => new V4d(W, X, Y, Z);\n            set { W = value.X; X = value.Y; Y = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXYW => new V4d(W, X, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXZO => new V4d(W, X, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXZI => new V4d(W, X, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXZN => new V4d(W, X, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXZX => new V4d(W, X, Z, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d WXZY\n        {\n            readonly get => new V4d(W, X, Z, Y);\n            set { W = value.X; X = value.Y; Z = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXZZ => new V4d(W, X, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXZW => new V4d(W, X, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXWO => new V4d(W, X, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXWI => new V4d(W, X, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXWN => new V4d(W, X, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXWX => new V4d(W, X, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXWY => new V4d(W, X, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXWZ => new V4d(W, X, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WXWW => new V4d(W, X, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYOO => new V4d(W, Y, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYOI => new V4d(W, Y, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYON => new V4d(W, Y, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYOX => new V4d(W, Y, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYOY => new V4d(W, Y, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYOZ => new V4d(W, Y, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYOW => new V4d(W, Y, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYIO => new V4d(W, Y, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYII => new V4d(W, Y, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYPN => new V4d(W, Y, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYIX => new V4d(W, Y, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYIY => new V4d(W, Y, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYIZ => new V4d(W, Y, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYIW => new V4d(W, Y, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYNO => new V4d(W, Y, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYNP => new V4d(W, Y, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYNN => new V4d(W, Y, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYNX => new V4d(W, Y, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYNY => new V4d(W, Y, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYNZ => new V4d(W, Y, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYNW => new V4d(W, Y, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYXO => new V4d(W, Y, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYXI => new V4d(W, Y, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYXN => new V4d(W, Y, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYXX => new V4d(W, Y, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYXY => new V4d(W, Y, X, Y);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d WYXZ\n        {\n            readonly get => new V4d(W, Y, X, Z);\n            set { W = value.X; Y = value.Y; X = value.Z; Z = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYXW => new V4d(W, Y, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYYO => new V4d(W, Y, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYYI => new V4d(W, Y, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYYN => new V4d(W, Y, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYYX => new V4d(W, Y, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYYY => new V4d(W, Y, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYYZ => new V4d(W, Y, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYYW => new V4d(W, Y, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYZO => new V4d(W, Y, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYZI => new V4d(W, Y, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYZN => new V4d(W, Y, Z, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d WYZX\n        {\n            readonly get => new V4d(W, Y, Z, X);\n            set { W = value.X; Y = value.Y; Z = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYZY => new V4d(W, Y, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYZZ => new V4d(W, Y, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYZW => new V4d(W, Y, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYWO => new V4d(W, Y, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYWI => new V4d(W, Y, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYWN => new V4d(W, Y, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYWX => new V4d(W, Y, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYWY => new V4d(W, Y, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYWZ => new V4d(W, Y, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WYWW => new V4d(W, Y, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZOO => new V4d(W, Z, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZOI => new V4d(W, Z, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZON => new V4d(W, Z, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZOX => new V4d(W, Z, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZOY => new V4d(W, Z, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZOZ => new V4d(W, Z, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZOW => new V4d(W, Z, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZIO => new V4d(W, Z, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZII => new V4d(W, Z, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZPN => new V4d(W, Z, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZIX => new V4d(W, Z, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZIY => new V4d(W, Z, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZIZ => new V4d(W, Z, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZIW => new V4d(W, Z, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZNO => new V4d(W, Z, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZNP => new V4d(W, Z, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZNN => new V4d(W, Z, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZNX => new V4d(W, Z, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZNY => new V4d(W, Z, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZNZ => new V4d(W, Z, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZNW => new V4d(W, Z, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZXO => new V4d(W, Z, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZXI => new V4d(W, Z, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZXN => new V4d(W, Z, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZXX => new V4d(W, Z, X, X);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d WZXY\n        {\n            readonly get => new V4d(W, Z, X, Y);\n            set { W = value.X; Z = value.Y; X = value.Z; Y = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZXZ => new V4d(W, Z, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZXW => new V4d(W, Z, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZYO => new V4d(W, Z, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZYI => new V4d(W, Z, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZYN => new V4d(W, Z, Y, -1);\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4d WZYX\n        {\n            readonly get => new V4d(W, Z, Y, X);\n            set { W = value.X; Z = value.Y; Y = value.Z; X = value.W; }\n        }\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZYY => new V4d(W, Z, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZYZ => new V4d(W, Z, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZYW => new V4d(W, Z, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZZO => new V4d(W, Z, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZZI => new V4d(W, Z, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZZN => new V4d(W, Z, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZZX => new V4d(W, Z, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZZY => new V4d(W, Z, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZZZ => new V4d(W, Z, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZZW => new V4d(W, Z, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZWO => new V4d(W, Z, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZWI => new V4d(W, Z, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZWN => new V4d(W, Z, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZWX => new V4d(W, Z, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZWY => new V4d(W, Z, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZWZ => new V4d(W, Z, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WZWW => new V4d(W, Z, W, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWOO => new V4d(W, W, 0, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWOI => new V4d(W, W, 0, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWON => new V4d(W, W, 0, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWOX => new V4d(W, W, 0, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWOY => new V4d(W, W, 0, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWOZ => new V4d(W, W, 0, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWOW => new V4d(W, W, 0, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWIO => new V4d(W, W, 1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWII => new V4d(W, W, 1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWPN => new V4d(W, W, 1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWIX => new V4d(W, W, 1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWIY => new V4d(W, W, 1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWIZ => new V4d(W, W, 1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWIW => new V4d(W, W, 1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWNO => new V4d(W, W, -1, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWNP => new V4d(W, W, -1, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWNN => new V4d(W, W, -1, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWNX => new V4d(W, W, -1, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWNY => new V4d(W, W, -1, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWNZ => new V4d(W, W, -1, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWNW => new V4d(W, W, -1, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWXO => new V4d(W, W, X, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWXI => new V4d(W, W, X, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWXN => new V4d(W, W, X, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWXX => new V4d(W, W, X, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWXY => new V4d(W, W, X, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWXZ => new V4d(W, W, X, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWXW => new V4d(W, W, X, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWYO => new V4d(W, W, Y, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWYI => new V4d(W, W, Y, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWYN => new V4d(W, W, Y, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWYX => new V4d(W, W, Y, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWYY => new V4d(W, W, Y, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWYZ => new V4d(W, W, Y, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWYW => new V4d(W, W, Y, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWZO => new V4d(W, W, Z, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWZI => new V4d(W, W, Z, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWZN => new V4d(W, W, Z, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWZX => new V4d(W, W, Z, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWZY => new V4d(W, W, Z, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWZZ => new V4d(W, W, Z, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWZW => new V4d(W, W, Z, W);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWWO => new V4d(W, W, W, 0);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWWI => new V4d(W, W, W, 1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWWN => new V4d(W, W, W, -1);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWWX => new V4d(W, W, W, X);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWWY => new V4d(W, W, W, Y);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWWZ => new V4d(W, W, W, Z);\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4d WWWW => new V4d(W, W, W, W);\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (double)value; }\n        }\n\n        #endregion\n\n        #region ISize4d Members\n\n        public readonly V4d Size4d { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return 4; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (double)value;\n        }\n\n        #endregion\n\n    }\n\n    public class V4dEqualityComparer : IEqualityComparer<V4d>\n    {\n        public static V4dEqualityComparer Default\n            => new V4dEqualityComparer();\n\n        #region IEqualityComparer<V4d> Members\n\n        public bool Equals(V4d v0, V4d v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(V4d v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        #region Min and Max\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Min(this V4d a, V4d b)\n        {\n            return new V4d(Min(a.X, b.X), Min(a.Y, b.Y), Min(a.Z, b.Z), Min(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Min(this V4d a, double b)\n        {\n            return new V4d(Min(a.X, b), Min(a.Y, b), Min(a.Z, b), Min(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Min(this double a, V4d b)\n        {\n            return new V4d(Min(a, b.X), Min(a, b.Y), Min(a, b.Z), Min(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Max(this V4d a, V4d b)\n        {\n            return new V4d(Max(a.X, b.X), Max(a.Y, b.Y), Max(a.Z, b.Z), Max(a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Max(this V4d a, double b)\n        {\n            return new V4d(Max(a.X, b), Max(a.Y, b), Max(a.Z, b), Max(a.W, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Max(this double a, V4d b)\n        {\n            return new V4d(Max(a, b.X), Max(a, b.Y), Max(a, b.Z), Max(a, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Min(this V4d a, V4d b, V4d c)\n        {\n            return new V4d(Min(a.X, b.X, c.X), Min(a.Y, b.Y, c.Y), Min(a.Z, b.Z, c.Z), Min(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Max(this V4d a, V4d b, V4d c)\n        {\n            return new V4d(Max(a.X, b.X, c.X), Max(a.Y, b.Y, c.Y), Max(a.Z, b.Z, c.Z), Max(a.W, b.W, c.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Min(this V4d a, V4d b, V4d c, V4d d)\n        {\n            return new V4d(Min(a.X, b.X, c.X, d.X), Min(a.Y, b.Y, c.Y, d.Y), Min(a.Z, b.Z, c.Z, d.Z), Min(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Max(this V4d a, V4d b, V4d c, V4d d)\n        {\n            return new V4d(Max(a.X, b.X, c.X, d.X), Max(a.Y, b.Y, c.Y, d.Y), Max(a.Z, b.Z, c.Z, d.Z), Max(a.W, b.W, c.W, d.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Min to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Min(this V4d x, params V4d[] values)\n        {\n            return new V4d(Min(x.X, values.Map(a => a.X)), Min(x.Y, values.Map(a => a.Y)), Min(x.Z, values.Map(a => a.Z)), Min(x.W, values.Map(a => a.W)));\n        }\n\n        /// <summary>\n        /// Applies Fun.Max to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Max(this V4d x, params V4d[] values)\n        {\n            return new V4d(Max(x.X, values.Map(a => a.X)), Max(x.Y, values.Map(a => a.Y)), Max(x.Z, values.Map(a => a.Z)), Max(x.W, values.Map(a => a.W)));\n        }\n\n        #endregion\n\n        #region Abs\n\n        /// <summary>\n        /// Applies Fun.Abs to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Abs(this V4d x)\n        {\n            return new V4d(Abs(x.X), Abs(x.Y), Abs(x.Z), Abs(x.W));\n        }\n\n        #endregion\n\n        #region Rounding\n\n        /// <summary>\n        /// Applies Fun.Floor to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Floor(this V4d x)\n        {\n            return new V4d(Floor(x.X), Floor(x.Y), Floor(x.Z), Floor(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Ceiling to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Ceiling(this V4d x)\n        {\n            return new V4d(Ceiling(x.X), Ceiling(x.Y), Ceiling(x.Z), Ceiling(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Round(this V4d x)\n        {\n            return new V4d(Round(x.X), Round(x.Y), Round(x.Z), Round(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Round(this V4d x, MidpointRounding mode)\n        {\n            return new V4d(Round(x.X, mode), Round(x.Y, mode), Round(x.Z, mode), Round(x.W, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Round(this V4d x, int digits)\n        {\n            return new V4d(Round(x.X, digits), Round(x.Y, digits), Round(x.Z, digits), Round(x.W, digits));\n        }\n\n        /// <summary>\n        /// Applies Fun.Round to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Round(this V4d x, int digits, MidpointRounding mode)\n        {\n            return new V4d(Round(x.X, digits, mode), Round(x.Y, digits, mode), Round(x.Z, digits, mode), Round(x.W, digits, mode));\n        }\n\n        /// <summary>\n        /// Applies Fun.Truncate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Truncate(this V4d x)\n        {\n            return new V4d(Truncate(x.X), Truncate(x.Y), Truncate(x.Z), Truncate(x.W));\n        }\n\n        #endregion\n\n        #region Frac\n\n        /// <summary>\n        /// Applies Fun.Frac to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Frac(this V4d x)\n        {\n            return new V4d(Frac(x.X), Frac(x.Y), Frac(x.Z), Frac(x.W));\n        }\n\n        #endregion\n\n        #region Clamping\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Clamp(this V4d x, V4d a, V4d b)\n        {\n            return new V4d(Clamp(x.X, a.X, b.X), Clamp(x.Y, a.Y, b.Y), Clamp(x.Z, a.Z, b.Z), Clamp(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Clamp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Clamp(this V4d x, double a, double b)\n        {\n            return new V4d(Clamp(x.X, a, b), Clamp(x.Y, a, b), Clamp(x.Z, a, b), Clamp(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d ClampWrap(this V4d x, V4d a, V4d b)\n        {\n            return new V4d(ClampWrap(x.X, a.X, b.X), ClampWrap(x.Y, a.Y, b.Y), ClampWrap(x.Z, a.Z, b.Z), ClampWrap(x.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.ClampWrap to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d ClampWrap(this V4d x, double a, double b)\n        {\n            return new V4d(ClampWrap(x.X, a, b), ClampWrap(x.Y, a, b), ClampWrap(x.Z, a, b), ClampWrap(x.W, a, b));\n        }\n\n        /// <summary>\n        /// Applies Fun.Saturate to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Saturate(this V4d x)\n        {\n            return new V4d(Saturate(x.X), Saturate(x.Y), Saturate(x.Z), Saturate(x.W));\n        }\n\n        #endregion\n\n        #region MapToUnitInterval\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d MapToUnitInterval(this V4d t, V4d tMax, bool repeat, bool mirror)\n        {\n            return new V4d(MapToUnitInterval(t.X, tMax.X, repeat, mirror), MapToUnitInterval(t.Y, tMax.Y, repeat, mirror), MapToUnitInterval(t.Z, tMax.Z, repeat, mirror), MapToUnitInterval(t.W, tMax.W, repeat, mirror));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d MapToUnitInterval(this V4d t, V4d tMax, bool repeat)\n        {\n            return new V4d(MapToUnitInterval(t.X, tMax.X, repeat), MapToUnitInterval(t.Y, tMax.Y, repeat), MapToUnitInterval(t.Z, tMax.Z, repeat), MapToUnitInterval(t.W, tMax.W, repeat));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d MapToUnitInterval(this V4d t, V4d tMax)\n        {\n            return new V4d(MapToUnitInterval(t.X, tMax.X), MapToUnitInterval(t.Y, tMax.Y), MapToUnitInterval(t.Z, tMax.Z), MapToUnitInterval(t.W, tMax.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MapToUnitInterval to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d MapToUnitInterval(this V4d t, V4d tMin, V4d tMax)\n        {\n            return new V4d(MapToUnitInterval(t.X, tMin.X, tMax.X), MapToUnitInterval(t.Y, tMin.Y, tMax.Y), MapToUnitInterval(t.Z, tMin.Z, tMax.Z), MapToUnitInterval(t.W, tMin.W, tMax.W));\n        }\n\n        #endregion\n\n        #region Sign\n\n        /// <summary>\n        /// Applies Fun.Sign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Sign(this V4d x)\n        {\n            return new V4i(Sign(x.X), Sign(x.Y), Sign(x.Z), Sign(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signumi to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Signumi(this V4d x)\n        {\n            return new V4i(Signumi(x.X), Signumi(x.Y), Signumi(x.Z), Signumi(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Signum to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Signum(this V4d x)\n        {\n            return new V4d(Signum(x.X), Signum(x.Y), Signum(x.Z), Signum(x.W));\n        }\n\n        #endregion\n\n        #region Multiply-Add\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d MultiplyAdd(V4d x, V4d y, V4d z)\n        {\n            return new V4d(MultiplyAdd(x.X, y.X, z.X), MultiplyAdd(x.Y, y.Y, z.Y), MultiplyAdd(x.Z, y.Z, z.Z), MultiplyAdd(x.W, y.W, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d MultiplyAdd(V4d x, double y, V4d z)\n        {\n            return new V4d(MultiplyAdd(x.X, y, z.X), MultiplyAdd(x.Y, y, z.Y), MultiplyAdd(x.Z, y, z.Z), MultiplyAdd(x.W, y, z.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.MultiplyAdd to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d MultiplyAdd(double x, V4d y, V4d z)\n        {\n            return new V4d(MultiplyAdd(x, y.X, z.X), MultiplyAdd(x, y.Y, z.Y), MultiplyAdd(x, y.Z, z.Z), MultiplyAdd(x, y.W, z.W));\n        }\n\n        #endregion\n\n        #region Copy sign\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d CopySign(V4d value, V4d sign)\n        {\n            return new V4d(CopySign(value.X, sign.X), CopySign(value.Y, sign.Y), CopySign(value.Z, sign.Z), CopySign(value.W, sign.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d CopySign(double value, V4d sign)\n        {\n            return new V4d(CopySign(value, sign.X), CopySign(value, sign.Y), CopySign(value, sign.Z), CopySign(value, sign.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.CopySign to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d CopySign(V4d value, double sign)\n        {\n            return new V4d(CopySign(value.X, sign), CopySign(value.Y, sign), CopySign(value.Z, sign), CopySign(value.W, sign));\n        }\n\n        #endregion\n\n        #region Roots\n\n        /// <summary>\n        /// Applies Fun.Sqrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sqrt(this V4d x)\n        {\n            return new V4d(Sqrt(x.X), Sqrt(x.Y), Sqrt(x.Z), Sqrt(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cbrt to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Cbrt(this V4d x)\n        {\n            return new V4d(Cbrt(x.X), Cbrt(x.Y), Cbrt(x.Z), Cbrt(x.W));\n        }\n\n        #endregion\n\n        #region Square\n\n        /// <summary>\n        /// Applies Fun.Square to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Square(this V4d x)\n        {\n            return new V4d(Square(x.X), Square(x.Y), Square(x.Z), Square(x.W));\n        }\n\n        #endregion\n\n        #region Power\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pown(this V4d x, V4i y)\n        {\n            return new V4d(Pown(x.X, y.X), Pown(x.Y, y.Y), Pown(x.Z, y.Z), Pown(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pown(this V4d x, int y)\n        {\n            return new V4d(Pown(x.X, y), Pown(x.Y, y), Pown(x.Z, y), Pown(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pown to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pown(this double x, V4i y)\n        {\n            return new V4d(Pown(x, y.X), Pown(x, y.Y), Pown(x, y.Z), Pown(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this V4d x, V4d y)\n        {\n            return new V4d(Pow(x.X, y.X), Pow(x.Y, y.Y), Pow(x.Z, y.Z), Pow(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this V4d x, double y)\n        {\n            return new V4d(Pow(x.X, y), Pow(x.Y, y), Pow(x.Z, y), Pow(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Pow to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Pow(this double x, V4d y)\n        {\n            return new V4d(Pow(x, y.X), Pow(x, y.Y), Pow(x, y.Z), Pow(x, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this V4d x, V4d y)\n        {\n            return new V4d(Power(x.X, y.X), Power(x.Y, y.Y), Power(x.Z, y.Z), Power(x.W, y.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this V4d x, double y)\n        {\n            return new V4d(Power(x.X, y), Power(x.Y, y), Power(x.Z, y), Power(x.W, y));\n        }\n\n        /// <summary>\n        /// Applies Fun.Power to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Power(this double x, V4d y)\n        {\n            return new V4d(Power(x, y.X), Power(x, y.Y), Power(x, y.Z), Power(x, y.W));\n        }\n\n        #endregion\n\n        #region Exp and Log\n\n        /// <summary>\n        /// Applies Fun.Exp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Exp(this V4d x)\n        {\n            return new V4d(Exp(x.X), Exp(x.Y), Exp(x.Z), Exp(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(this V4d x)\n        {\n            return new V4d(Log(x.X), Log(x.Y), Log(x.Z), Log(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log2(this V4d x)\n        {\n            return new V4d(Log2(x.X), Log2(x.Y), Log2(x.Z), Log2(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log2Int to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4i Log2Int(this V4d x)\n        {\n            return new V4i(Log2Int(x.X), Log2Int(x.Y), Log2Int(x.Z), Log2Int(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log10 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log10(this V4d x)\n        {\n            return new V4d(Log10(x.X), Log10(x.Y), Log10(x.Z), Log10(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Log to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Log(this V4d x, double basis)\n        {\n            return new V4d(Log(x.X, basis), Log(x.Y, basis), Log(x.Z, basis), Log(x.W, basis));\n        }\n\n        #endregion\n\n        #region ModP\n\n        /// <summary>\n        /// Applies Fun.ModP to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d ModP(this V4d a, V4d b)\n        {\n            return new V4d(ModP(a.X, b.X), ModP(a.Y, b.Y), ModP(a.Z, b.Z), ModP(a.W, b.W));\n        }\n\n        #endregion\n\n        #region Power of Two\n\n        /// <summary>\n        /// Applies Fun.PowerOfTwo to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d PowerOfTwo(this V4d x)\n        {\n            return new V4d(PowerOfTwo(x.X), PowerOfTwo(x.Y), PowerOfTwo(x.Z), PowerOfTwo(x.W));\n        }\n\n        #endregion\n\n        #region Trigonometry\n\n        /// <summary>\n        /// Applies Fun.Sin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sin(this V4d x)\n        {\n            return new V4d(Sin(x.X), Sin(x.Y), Sin(x.Z), Sin(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Cos(this V4d x)\n        {\n            return new V4d(Cos(x.X), Cos(x.Y), Cos(x.Z), Cos(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Tan(this V4d x)\n        {\n            return new V4d(Tan(x.X), Tan(x.Y), Tan(x.Z), Tan(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asin to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Asin(this V4d x)\n        {\n            return new V4d(Asin(x.X), Asin(x.Y), Asin(x.Z), Asin(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.AsinClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d AsinClamped(this V4d x)\n        {\n            return new V4d(AsinClamped(x.X), AsinClamped(x.Y), AsinClamped(x.Z), AsinClamped(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acos to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Acos(this V4d x)\n        {\n            return new V4d(Acos(x.X), Acos(x.Y), Acos(x.Z), Acos(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.AcosClamped to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d AcosClamped(this V4d x)\n        {\n            return new V4d(AcosClamped(x.X), AcosClamped(x.Y), AcosClamped(x.Z), AcosClamped(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Atan(this V4d x)\n        {\n            return new V4d(Atan(x.X), Atan(x.Y), Atan(x.Z), Atan(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Atan2(V4d y, V4d x)\n        {\n            return new V4d(Atan2(y.X, x.X), Atan2(y.Y, x.Y), Atan2(y.Z, x.Z), Atan2(y.W, x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.FastAtan2 to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d FastAtan2(V4d y, V4d x)\n        {\n            return new V4d(FastAtan2(y.X, x.X), FastAtan2(y.Y, x.Y), FastAtan2(y.Z, x.Z), FastAtan2(y.W, x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Sinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Sinh(this V4d x)\n        {\n            return new V4d(Sinh(x.X), Sinh(x.Y), Sinh(x.Z), Sinh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Cosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Cosh(this V4d x)\n        {\n            return new V4d(Cosh(x.X), Cosh(x.Y), Cosh(x.Z), Cosh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Tanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Tanh(this V4d x)\n        {\n            return new V4d(Tanh(x.X), Tanh(x.Y), Tanh(x.Z), Tanh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Asinh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Asinh(this V4d x)\n        {\n            return new V4d(Asinh(x.X), Asinh(x.Y), Asinh(x.Z), Asinh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Acosh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Acosh(this V4d x)\n        {\n            return new V4d(Acosh(x.X), Acosh(x.Y), Acosh(x.Z), Acosh(x.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Atanh to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Atanh(this V4d x)\n        {\n            return new V4d(Atanh(x.X), Atanh(x.Y), Atanh(x.Z), Atanh(x.W));\n        }\n\n        #endregion\n\n        #region Step functions\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Step(this V4d x, V4d edge)\n        {\n            return new V4d(Step(x.X, edge.X), Step(x.Y, edge.Y), Step(x.Z, edge.Z), Step(x.W, edge.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Step to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Step(this V4d x, double edge)\n        {\n            return new V4d(Step(x.X, edge), Step(x.Y, edge), Step(x.Z, edge), Step(x.W, edge));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Linearstep(this V4d x, V4d edge0, V4d edge1)\n        {\n            return new V4d(Linearstep(x.X, edge0.X, edge1.X), Linearstep(x.Y, edge0.Y, edge1.Y), Linearstep(x.Z, edge0.Z, edge1.Z), Linearstep(x.W, edge0.W, edge1.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Linearstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Linearstep(this V4d x, double edge0, double edge1)\n        {\n            return new V4d(Linearstep(x.X, edge0, edge1), Linearstep(x.Y, edge0, edge1), Linearstep(x.Z, edge0, edge1), Linearstep(x.W, edge0, edge1));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Smoothstep(this V4d x, V4d edge0, V4d edge1)\n        {\n            return new V4d(Smoothstep(x.X, edge0.X, edge1.X), Smoothstep(x.Y, edge0.Y, edge1.Y), Smoothstep(x.Z, edge0.Z, edge1.Z), Smoothstep(x.W, edge0.W, edge1.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Smoothstep to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Smoothstep(this V4d x, double edge0, double edge1)\n        {\n            return new V4d(Smoothstep(x.X, edge0, edge1), Smoothstep(x.Y, edge0, edge1), Smoothstep(x.Z, edge0, edge1), Smoothstep(x.W, edge0, edge1));\n        }\n\n        #endregion\n\n        #region Interpolation\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Lerp(this double t, V4d a, V4d b)\n        {\n            return new V4d(Lerp(t, a.X, b.X), Lerp(t, a.Y, b.Y), Lerp(t, a.Z, b.Z), Lerp(t, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.Lerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Lerp(this V4d t, V4d a, V4d b)\n        {\n            return new V4d(Lerp(t.X, a.X, b.X), Lerp(t.Y, a.Y, b.Y), Lerp(t.Z, a.Z, b.Z), Lerp(t.W, a.W, b.W));\n        }\n\n        /// <summary>\n        /// Applies Fun.InvLerp to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d InvLerp(this V4d y, V4d a, V4d b)\n        {\n            return new V4d(InvLerp(y.X, a.X, b.X), InvLerp(y.Y, a.Y, b.Y), InvLerp(y.Z, a.Z, b.Z), InvLerp(y.W, a.W, b.W));\n        }\n\n        #endregion\n\n        #region Floating point bits\n\n        /// <summary>\n        /// Applies Fun.FloatToBits to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4l FloatToBits(this V4d x)\n        {\n            return new V4l(FloatToBits(x.X), FloatToBits(x.Y), FloatToBits(x.Z), FloatToBits(x.W));\n        }\n\n        #endregion\n\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V4d a, V4d b, double tolerance)\n        {\n            return ApproximateEquals(a.X, b.X, tolerance) && ApproximateEquals(a.Y, b.Y, tolerance) && ApproximateEquals(a.Z, b.Z, tolerance) && ApproximateEquals(a.W, b.W, tolerance);\n        }\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within\n        /// Constant{double}.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this V4d a, V4d b)\n        {\n            return ApproximateEquals(a, b, Constant<double>.PositiveTinyValue);\n        }\n\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this V4d v, double epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4d\"/> is smaller than Constant&lt;double&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(V4d v)\n            => v.IsTiny;\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"V4d\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(V4d v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V4d\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(V4d v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V4d\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(V4d v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"V4d\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(V4d v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"V4d\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(V4d v)\n            => v.IsFinite;\n\n        #endregion\n    }\n\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        /// <summary>\n        /// Converts the angles given in degrees to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d RadiansFromDegrees(this V4d degrees)\n            => new V4d(\n                   RadiansFromDegrees(degrees.X), \n                   RadiansFromDegrees(degrees.Y), \n                   RadiansFromDegrees(degrees.Z), \n                   RadiansFromDegrees(degrees.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to radians.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d RadiansFromGons(this V4d gons)\n            => new V4d(\n                   RadiansFromGons(gons.X), \n                   RadiansFromGons(gons.Y), \n                   RadiansFromGons(gons.Z), \n                   RadiansFromGons(gons.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d DegreesFromRadians(this V4d radians)\n            => new V4d(\n                   DegreesFromRadians(radians.X), \n                   DegreesFromRadians(radians.Y), \n                   DegreesFromRadians(radians.Z), \n                   DegreesFromRadians(radians.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in gons to degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d DegreesFromGons(this V4d gons)\n            => new V4d(\n                   DegreesFromGons(gons.X), \n                   DegreesFromGons(gons.Y), \n                   DegreesFromGons(gons.Z), \n                   DegreesFromGons(gons.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in radians to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d GonsFromRadians(this V4d radians)\n            => new V4d(\n                   GonsFromRadians(radians.X), \n                   GonsFromRadians(radians.Y), \n                   GonsFromRadians(radians.Z), \n                   GonsFromRadians(radians.W)\n               );\n\n        /// <summary>\n        /// Converts the angles given in degrees to gons.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d GonsFromDegrees(this V4d degrees)\n            => new V4d(\n                   GonsFromDegrees(degrees.X), \n                   GonsFromDegrees(degrees.Y), \n                   GonsFromDegrees(degrees.Z), \n                   GonsFromDegrees(degrees.W)\n               );\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double LengthSquared(V4d v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Length(V4d v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        /// <summary>\n        /// Normalizes the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref V4d v)\n        {\n            var s = v.Length; if (s == 0) return;\n            s = 1 / s;\n            v.X *= s;\n            v.Y *= s;\n            v.Z *= s;\n            v.W *= s;\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Normalized(V4d v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm1(V4d v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm2(V4d v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMax(V4d v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double NormMin(V4d v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Norm(this V4d v, double p)\n        {\n            return (\n                Fun.Abs(v.X).Pow(p) + \n                Fun.Abs(v.Y).Pow(p) + \n                Fun.Abs(v.Z).Pow(p) + \n                Fun.Abs(v.W).Pow(p)).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceSquared(this V4d a, V4d b)\n            => Fun.Square(b.X - a.X) + Fun.Square(b.Y - a.Y) + Fun.Square(b.Z - a.Z) + Fun.Square(b.W - a.W);\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V4d a, V4d b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance1(this V4d a, V4d b)\n            => Fun.Abs(b.X - a.X) + Fun.Abs(b.Y - a.Y) + Fun.Abs(b.Z - a.Z) + Fun.Abs(b.W - a.W);\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Distance(this V4d a, V4d b, double p)\n            => (Fun.Abs(b.X - a.X).Pow(p) + Fun.Abs(b.Y - a.Y).Pow(p) + Fun.Abs(b.Z - a.Z).Pow(p) + Fun.Abs(b.W - a.W).Pow(p)).Pow(1 / p);\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceMax(this V4d a, V4d b)\n            => Fun.Max(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z), Fun.Abs(b.W - a.W));\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceMin(this V4d a, V4d b)\n            => Fun.Min(Fun.Abs(b.X - a.X), Fun.Abs(b.Y - a.Y), Fun.Abs(b.Z - a.Z), Fun.Abs(b.W - a.W));\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V4d query, V4d p0, V4d p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            if (t <= 0) { return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V4d query, V4d p0, V4d p1)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            var t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToLine(\n                this V4d query, V4d p0, V4d p1, out double t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            if (t <= 0) { t = 0; return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { t = 1; return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double DistanceToInfiniteLine(\n                this V4d query, V4d p0, V4d p1, out double t)\n        {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n        }\n\n        #endregion\n\n        #region Operations\n\n        /// <summary>\n        /// Gets a copy of the given vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Reciprocal(V4d v)\n            => v.Reciprocal;\n\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref V4d v)\n        {\n            v.X = -v.X;\n            v.Y = -v.Y;\n            v.Z = -v.Z;\n            v.W = -v.W;\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a 4x4 matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static M44d Outer(this V4d a, V4d b)\n        {\n            return new M44d(\n                        a.X * b.X, a.X * b.Y, a.X * b.Z, a.X * b.W, \n                        a.Y * b.X, a.Y * b.Y, a.Y * b.Z, a.Y * b.W, \n                        a.Z * b.X, a.Z * b.Y, a.Z * b.Z, a.Z * b.W, \n                        a.W * b.X, a.W * b.Y, a.W * b.Z, a.W * b.W);\n        }\n\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double Dot(this V4d a, V4d b)\n        {\n            return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this V4d v)\n        {\n            DirFlags flags = Aardbase.DirFlags.None;\n            if (v.X > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveX;\n            if (v.X < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeX;\n            if (v.Y > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveY;\n            if (v.Y < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeY;\n            if (v.Z > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveZ;\n            if (v.Z < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeZ;\n            if (v.W > Constant<double>.PositiveTinyValue) flags |= Aardbase.DirFlags.PositiveW;\n            if (v.W < Constant<double>.NegativeTinyValue) flags |= Aardbase.DirFlags.NegativeW;\n            return flags;\n        }\n\n        /// <summary>\n        /// Returns the reflection direction of the given vector v (pointing to the surface) for the given normal (should be normalized).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Reflect(this V4d v, V4d normal)\n        {\n            return v - 2 * v.Dot(normal) * normal;\n        }\n\n        /// <summary>\n        /// Returns the refraction direction of the given vector v (pointing to the surface) for the given normal and ratio of refraction indices (n_out / n_in).\n        /// Both the input vectors should be normalized.\n        /// Returns a zero-vector in case of total internal reflection.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d Refract(this V4d v, V4d normal, double eta)\n        {\n            var t = v.Dot(normal);\n            var k = 1 - eta * eta * (1 - t * t);\n\n            if (k < 0)\n            {\n                return V4d.Zero;\n            }\n            else\n            {\n                return eta * v - (eta * t + Fun.Sqrt(k)) * normal;\n            }\n        }\n\n        #endregion\n\n        #region Comparisons\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4d a, V4d b)\n        {\n            return (a.X < b.X && a.Y < b.Y && a.Z < b.Z && a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(this V4d v, double s)\n        {\n            return (v.X < s && v.Y < s && v.Z < s && v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmaller(double s, V4d v)\n        {\n            return (s < v.X && s < v.Y && s < v.Z && s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Smaller the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4d a, V4d b)\n        {\n            return (a.X < b.X || a.Y < b.Y || a.Z < b.Z || a.W < b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Smaller s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(this V4d v, double s)\n        {\n            return (v.X < s || v.Y < s || v.Z < s || v.W < s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Smaller AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmaller(double s, V4d v)\n        {\n            return (s < v.X || s < v.Y || s < v.Z || s < v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4d a, V4d b)\n        {\n            return (a.X > b.X && a.Y > b.Y && a.Z > b.Z && a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(this V4d v, double s)\n        {\n            return (v.X > s && v.Y > s && v.Z > s && v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreater(double s, V4d v)\n        {\n            return (s > v.X && s > v.Y && s > v.Z && s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Greater the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4d a, V4d b)\n        {\n            return (a.X > b.X || a.Y > b.Y || a.Z > b.Z || a.W > b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Greater s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(this V4d v, double s)\n        {\n            return (v.X > s || v.Y > s || v.Z > s || v.W > s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Greater AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreater(double s, V4d v)\n        {\n            return (s > v.X || s > v.Y || s > v.Z || s > v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4d a, V4d b)\n        {\n            return (a.X <= b.X && a.Y <= b.Y && a.Z <= b.Z && a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(this V4d v, double s)\n        {\n            return (v.X <= s && v.Y <= s && v.Z <= s && v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllSmallerOrEqual(double s, V4d v)\n        {\n            return (s <= v.X && s <= v.Y && s <= v.Z && s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is SmallerOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4d a, V4d b)\n        {\n            return (a.X <= b.X || a.Y <= b.Y || a.Z <= b.Z || a.W <= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is SmallerOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(this V4d v, double s)\n        {\n            return (v.X <= s || v.Y <= s || v.Z <= s || v.W <= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is SmallerOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnySmallerOrEqual(double s, V4d v)\n        {\n            return (s <= v.X || s <= v.Y || s <= v.Z || s <= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4d a, V4d b)\n        {\n            return (a.X >= b.X && a.Y >= b.Y && a.Z >= b.Z && a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(this V4d v, double s)\n        {\n            return (v.X >= s && v.Y >= s && v.Z >= s && v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllGreaterOrEqual(double s, V4d v)\n        {\n            return (s >= v.X && s >= v.Y && s >= v.Z && s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is GreaterOrEqual the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4d a, V4d b)\n        {\n            return (a.X >= b.X || a.Y >= b.Y || a.Z >= b.Z || a.W >= b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is GreaterOrEqual s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(this V4d v, double s)\n        {\n            return (v.X >= s || v.Y >= s || v.Z >= s || v.W >= s);\n        }\n\n        /// <summary>\n        /// Returns whether a is GreaterOrEqual AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyGreaterOrEqual(double s, V4d v)\n        {\n            return (s >= v.X || s >= v.Y || s >= v.Z || s >= v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4d a, V4d b)\n        {\n            return (a.X == b.X && a.Y == b.Y && a.Z == b.Z && a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(this V4d v, double s)\n        {\n            return (v.X == s && v.Y == s && v.Z == s && v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllEqual(double s, V4d v)\n        {\n            return (s == v.X && s == v.Y && s == v.Z && s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Equal the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4d a, V4d b)\n        {\n            return (a.X == b.X || a.Y == b.Y || a.Z == b.Z || a.W == b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Equal s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(this V4d v, double s)\n        {\n            return (v.X == s || v.Y == s || v.Z == s || v.W == s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Equal AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyEqual(double s, V4d v)\n        {\n            return (s == v.X || s == v.Y || s == v.Z || s == v.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of a are Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4d a, V4d b)\n        {\n            return (a.X != b.X && a.Y != b.Y && a.Z != b.Z && a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(this V4d v, double s)\n        {\n            return (v.X != s && v.Y != s && v.Z != s && v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different ALL elements of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllDifferent(double s, V4d v)\n        {\n            return (s != v.X && s != v.Y && s != v.Z && s != v.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is Different the corresponding element of b.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4d a, V4d b)\n        {\n            return (a.X != b.X || a.Y != b.Y || a.Z != b.Z || a.W != b.W);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is Different s.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(this V4d v, double s)\n        {\n            return (v.X != s || v.Y != s || v.Z != s || v.W != s);\n        }\n\n        /// <summary>\n        /// Returns whether a is Different AT LEAST ONE element of v.\n        /// ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyDifferent(double s, V4d v)\n        {\n            return (s != v.X || s != v.Y || s != v.Z || s != v.W);\n        }\n\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this V4d v0, V4d v1)\n        {\n            if (v0.X < v1.X) return -1;\n            if (v0.X > v1.X) return +1;\n            if (v0.Y < v1.Y) return -1;\n            if (v0.Y > v1.Y) return +1;\n            if (v0.Z < v1.Z) return -1;\n            if (v0.Z > v1.Z) return +1;\n            if (v0.W < v1.W) return -1;\n            if (v0.W > v1.W) return +1;\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MinElement(V4d v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"V4d\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double MaxElement(V4d v)\n            => v.MaxElement;\n\n        #endregion\n\n        #region Angle between two vectors\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleBetweenFast(this V4d x, V4d y)\n        {\n            return Fun.AcosClamped(x.Dot(y));\n        }\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians using a numerically stable algorithm.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        // https://scicomp.stackexchange.com/a/27769\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static double AngleBetween(this V4d x, V4d y)\n        {\n            var a = x + y;\n            var b = x - y;\n            return 2 * Fun.Atan2(b.Length, a.Length);\n        }\n\n        #endregion\n\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"V4d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this V4d v, double epsilon)\n            => v.X.IsTiny(epsilon) || v.Y.IsTiny(epsilon) || v.Z.IsTiny(epsilon) || v.W.IsTiny(epsilon);\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"V4d\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this V4d v, double epsilon)\n            => v.X.IsTiny(epsilon) && v.Y.IsTiny(epsilon) && v.Z.IsTiny(epsilon) && v.W.IsTiny(epsilon);\n\n        #endregion\n\n        #region Special Floating Point Value Checks\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyFinite(V4d v)\n            => v.AnyFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllFinite(V4d v)\n            => v.AllFinite;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNaN(V4d v)\n            => v.AnyNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNaN(V4d v)\n            => v.AllNaN;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyInfinity(V4d v)\n            => v.AnyInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllInfinity(V4d v)\n            => v.AllInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyPositiveInfinity(V4d v)\n            => v.AnyPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllPositiveInfinity(V4d v)\n            => v.AllPositiveInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyNegativeInfinity(V4d v)\n            => v.AnyNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllNegativeInfinity(V4d v)\n            => v.AllNegativeInfinity;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(V4d v)\n            => v.AnyTiny;\n\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(V4d v)\n            => v.AllTiny;\n\n        #endregion\n\n        #region Linear Combination\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LinCom(V4d p0, V4d p1, ref Tup2<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LinCom(V4d p0, V4d p1, V4d p2, ref Tup3<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LinCom(V4d p0, V4d p1, V4d p2, V4d p3, ref Tup4<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LinCom(V4d p0, V4d p1, V4d p2, V4d p3, V4d p4, ref Tup5<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LinCom(V4d p0, V4d p1, V4d p2, V4d p3, V4d p4, V4d p5, ref Tup6<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d LinCom(V4d p0, V4d p1, V4d p2, V4d p3, V4d p4, V4d p5, V4d p6, ref Tup7<double> w)\n        {\n            return p0 * w.E0 + p1 * w.E1 + p2 * w.E2 + p3 * w.E3 + p4 * w.E4 + p5 * w.E5 + p6 * w.E6;\n        }\n\n        #endregion\n\n        #region ArrayExtensions\n\n        public static int IndexOfClosestPoint(this V4d[] pointArray, V4d point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            int bestIndex = 0;\n            int count = pointArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint(\n                this V4d[] array, int start, int count,\n                V4d point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static int IndexOfClosestPoint<T>(\n                this T[] array, int start, int count,\n                Func<T, V4d> pointSelector, V4d point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            int bestIndex = 0;\n            for (int i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(this V4d[] pointArray, V4d point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            long bestIndex = 0;\n            long count = pointArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint(\n                this V4d[] array, long start, long count,\n                V4d point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static long LongIndexOfClosestPoint<T>(\n                this T[] array, long start, long count,\n                Func<T, V4d> pointSelector, V4d point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            long bestIndex = 0;\n            for (long i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinX(this V4d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinX(this V4d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxX(this V4d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxX(this V4d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinY(this V4d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinY(this V4d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxY(this V4d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxY(this V4d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinZ(this V4d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinZ(this V4d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxZ(this V4d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxZ(this V4d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMinW(this V4d[] vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMinW(this V4d[] vectorArray, long count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            long minIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static int IndexOfMaxW(this V4d[] vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Length;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the array.\n        /// </summary>\n        public static long LongIndexOfMaxW(this V4d[] vectorArray, long count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            long maxIndex = 0;\n            if (count == 0) count = vectorArray.LongLength;\n            for (long i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinX(this IList<V4d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].X;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal X coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxX(this IList<V4d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].X;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].X;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinY(this IList<V4d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Y;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Y coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxY(this IList<V4d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Y;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Y;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinZ(this IList<V4d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].Z;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal Z coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxZ(this IList<V4d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].Z;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].Z;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the minimal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMinW(this IList<V4d> vectorArray, int count = 0)\n        {\n            var minimum = vectorArray[0].W;\n            int minIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p < minimum) { minimum = p; minIndex = i; }\n            }\n            return minIndex;\n        }\n\n        /// <summary>\n        /// Returns the index of the element with the maximal W coordinate\n        /// within the list.\n        /// </summary>\n        public static int IndexOfMaxW(this IList<V4d> vectorArray, int count = 0)\n        {\n            var maximum = vectorArray[0].W;\n            int maxIndex = 0;\n            if (count == 0) count = vectorArray.Count;\n            for (int i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].W;\n                if (p > maximum) { maximum = p; maxIndex = i; }\n            }\n            return maxIndex;\n        }\n\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static double[] CopyCoord(this V4d[] self, int index)\n        {\n            switch (index)\n            {\n                case 0: return self.Map(v => v.X);\n                case 1: return self.Map(v => v.Y);\n                case 2: return self.Map(v => v.Z);\n                case 3: return self.Map(v => v.W);\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        public static V4d WeightedSum(\n                this V4d[] vectorArray, double[] weightArray)\n        {\n            var r = V4d.Zero;\n            var count = vectorArray.LongLength;\n            for (long i = 0; i < count; i++) r += vectorArray[i] * weightArray[i];\n            return r;\n        }\n\n        #endregion\n    }\n\n    public static class IRandomUniformV4dExtensions\n    {\n        #region IRandomUniform extensions for V4d\n\n        /// <summary>\n        /// Uses UniformDouble() to generate the elements of a V4d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d UniformV4d(this IRandomUniform rnd)\n        {\n            return new V4d(rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble(), rnd.UniformDouble());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleClosed() to generate the elements of a V4d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d UniformV4dClosed(this IRandomUniform rnd)\n        {\n            return new V4d(rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed(), rnd.UniformDoubleClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleOpen() to generate the elements of a V4d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d UniformV4dOpen(this IRandomUniform rnd)\n        {\n            return new V4d(rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen(), rnd.UniformDoubleOpen());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFull() to generate the elements of a V4d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d UniformV4dFull(this IRandomUniform rnd)\n        {\n            return new V4d(rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull(), rnd.UniformDoubleFull());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullClosed() to generate the elements of a V4d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d UniformV4dFullClosed(this IRandomUniform rnd)\n        {\n            return new V4d(rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed(), rnd.UniformDoubleFullClosed());\n        }\n\n        /// <summary>\n        /// Uses UniformDoubleFullOpen() to generate the elements of a V4d vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static V4d UniformV4dFullOpen(this IRandomUniform rnd)\n        {\n            return new V4d(rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen(), rnd.UniformDoubleFullOpen());\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base/Math/Vectors/Vector_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Diagnostics.Contracts;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Runtime.Serialization;\nusing System.Xml.Serialization;\n#if NETCOREAPP3_1_OR_GREATER\nusing System.Runtime.Intrinsics.X86;\nusing System.Runtime.Intrinsics;\n#endif\n\nusing Aardbase = Aardvark.Base;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    [Flags]\n    public enum DirFlags\n    {\n        None = 0x00,\n        NegativeX = 0x01,\n        PositiveX = 0x02,\n        NegativeY = 0x04,\n        PositiveY = 0x08,\n        NegativeZ = 0x10,\n        PositiveZ = 0x20,\n        NegativeW = 0x40,\n        PositiveW = 0x80,\n\n        X = NegativeX | PositiveX,\n        Y = NegativeY | PositiveY,\n        Z = NegativeZ | PositiveZ,\n    };\n    //# Action comma = () => Out(\", \");\n    //# Action add = () => Out(\" + \");\n    //# Action addqcommaspace = () => Out(\" + \\\", \\\" \");\n    //# Action addbetween = () => Out(\" + between \");\n    //# Action andand = () => Out(\" && \");\n    //# Action oror = () => Out(\" || \");\n    //# Action xor = () => Out(\" ^ \");\n    //# Action el = () => Out(\"else \");\n    //# string f0 = Meta.VecFields[0], f1 = Meta.VecFields[1];\n    //# string f2 = Meta.VecFields[2], f3 = Meta.VecFields[3];\n    //# var fdtypes = new[] { Meta.FloatType, Meta.DoubleType };\n    //# var allfields = Meta.VecFields;\n    //#\n    //# Func<Meta.SimpleType, Meta.SimpleType, bool> iscolormapped =\n    //#     (t1, t2) => (t1 != t2) && !(t1.IsReal && t2.IsReal);\n    //#\n    //# Func<Meta.SimpleType, Meta.SimpleType, bool> coltovecsupported =\n    //#     (cft, vft) => (!cft.IsReal || vft.IsReal) && (cft != Meta.UIntType || vft != Meta.IntType);\n    //#\n    //# var colmaxvalmap = new Dictionary<Meta.SimpleType, string>\n    //#     {\n    //#         { Meta.ByteType, \"255\" },\n    //#         { Meta.UShortType, \"2^16 - 1\" },\n    //#         { Meta.UIntType, \"2^32 - 1\" },\n    //#         { Meta.FloatType, \"1\" },\n    //#         { Meta.DoubleType, \"1\" },\n    //#     };\n\n    //# foreach (var vt in Meta.VecTypes) {\n    //#     int d = vt.Len;\n    //#     var ft = vt.FieldType;\n    //#     var unsigned = Meta.UnsignedTypes.Contains(ft);\n    //#     var ct = Meta.ComputationTypeOf(ft);\n    //#     var ht = Meta.HighPrecisionTypeOf(ft);\n    //#     var vct = Meta.VecTypeOf(d, ct);\n    //#     var vtype = vt.Name;\n    //#     var fcaps = ft.Caps;\n    //#     var ftype = ft.Name;\n    //#     var fchar = ft.Char;\n    //#     var ctype = ct.Name;\n    //#     var htype = ht.Name;\n    //#     var vctype = vct.Name;\n    //#     var vitype = Meta.VecTypeOf(d, Meta.IntType).Name;\n    //#     var v2type = Meta.VecTypeOf(2, ft).Name;\n    //#     var v3type = Meta.VecTypeOf(3, ft).Name;\n    //#     var v4type = Meta.VecTypeOf(4, ft).Name;\n    //#     var mtype = unsigned ? \"UnknownMatrixType\" : Meta.MatTypeOf(d, d, ft).Name;\n    //#     var fields = vt.Fields;\n    //#     var args = fields.ToLower();\n    //#     var getptr = \"&\" + fields[0];\n    #region __vtype__\n\n    [DataContract]\n    [Serializable]\n    [StructLayout(LayoutKind.Sequential)]\n    public partial struct __vtype__ : IVector<double>, ISize__d____fchar__, IFormattable, IEquatable<__vtype__>\n    {\n        //# fields.ForEach(f => {\n        [DataMember]\n        public __ftype__ __f__;\n        //# });\n\n        #region Constructors\n\n        //# foreach (var ft1 in Meta.VecFieldTypes) {\n        //#     var vt1 = Meta.VecTypeOf(d, ft1);\n        //#     var ftype1 = ft1.Name;\n        /// <summary>\n        /// Creates a new vector from given <see cref=\"__ftype1__\"/> elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(/*# args.ForEach(a => { */__ftype1__ __a__/*# }, comma); */)\n        {\n            //# fields.ForEach(args, (f, a) => {\n            __f__ = /*# if (ft != ft1) { */(__ftype__)/*# } */__a__;\n            //# });\n        }\n\n        /// <summary>\n        /// Creates a new vector by assigning the given <see cref=\"__ftype1__\"/> to all elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(__ftype1__ v)\n        {\n            //# fields.ForEach(args, (f, a) => {\n            __f__ = /*# if (ft != ft1) { */(__ftype__)/*# } */v;\n            //# });\n        }\n\n        /// <summary>\n        /// Creates a new vector from the given array.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(__ftype1__[] a)\n        {\n            //# fields.ForEach((f, i) => {\n            __f__ = /*# if (ft != ft1) { */(__ftype__)/*# } */a[__i__];\n            //# });\n        }\n\n        /// <summary>\n        /// Creates a new vector from given array, starting at specified index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(__ftype1__[] a, int start)\n        {\n            //# fields.ForEach((f, i) => {\n            __f__ = /*# if (ft != ft1) {*/(__ftype__)/*# } */a[start + __i__];\n            //# });\n        }\n\n        //# if (d > 2) { for (int i = 1; i < d; i++) { var j = d - i;\n        //# var fsttype = (i > 1) ? Meta.VecTypeOf(i, ft1) : ft1;\n        //# var sndtype = (j > 1) ? Meta.VecTypeOf(j, ft1) : ft1;\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"__fsttype.Name__\"/> and <see cref=\"__sndtype.Name__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(__fsttype.Name__ a, __sndtype.Name__ b)\n        {\n            //# if (i == 1) {\n            __f0__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/a;\n            //# } else { for (int k = 0; k < i; k++) { var fk = Meta.VecFields[k];\n            __fk__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/a.__fk__;\n            //# } }\n            //# if (j == 1) { var fj = Meta.VecFields[i];\n            __fj__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/b;\n            //# } else { for (int k = 0; k < j; k++) { var fj = Meta.VecFields[i + k]; var fk = Meta.VecFields[k];\n            __fj__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/b.__fk__;\n            //# } }\n        }\n\n        //# } }\n        //# if (d > 3) { for (int i = 0; i < 3; i++) {\n        //# var t0 = (i == 0) ? Meta.VecTypeOf(2, ft1).Name : ft1.Name;\n        //# var t1 = (i == 1) ? Meta.VecTypeOf(2, ft1).Name : ft1.Name;\n        //# var t2 = (i == 2) ? Meta.VecTypeOf(2, ft1).Name : ft1.Name;\n        /// <summary>\n        /// Creates a new vector from the given <see cref=\"__t0__\"/>, <see cref=\"__t1__\"/>, and <see cref=\"__t2__\"/>.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(__t0__ a, __t1__ b, __t2__ c)\n        {\n            //# if (i != 0) {\n            __f0__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/a;\n            //# } else { for (int k = 0; k < 2; k++) { var fk = Meta.VecFields[k];\n            __fk__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/a.__fk__;\n            //# } }\n            //# if (i != 1) { var fj = Meta.VecFields[(i < 1) ? 2 : 1];\n            __fj__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/b;\n            //# } else { for (int k = 0; k < 2; k++) { var fj = Meta.VecFields[((i < 1) ? 2 : 1) + k]; var fk = Meta.VecFields[k];\n            __fj__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/b.__fk__;\n            //# } }\n            //# if (i != 2) {\n            __f3__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/c;\n            //# } else { for (int k = 0; k < 2; k++) { var fj = Meta.VecFields[2 + k]; var fk = Meta.VecFields[k];\n            __fj__ = /*# if (ft != ft1) {*/(__ftype__)/*# }*/c.__fk__;\n            //# } }\n        }\n\n        //# } }\n        //# }\n        /// <summary>\n        /// Creates a vector from the results of the supplied function of the index.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(Func<int, __ftype__> index_fun)\n        {\n            //# fields.ForEach((f, fi) => {\n            __f__ = index_fun(__fi__);\n            //# });\n        }\n\n        /// <summary>\n        /// Creates a vector from a general vector implementing the IVector&lt;__ftype__&gt; interface.\n        /// The caller has to verify that the dimension of <paramref name=\"v\"/> is at least __d__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(IVector<double> v)\n            : this(/*# d.ForEach(i => {*/v[__i__]/*# }, comma); */)\n        { }\n\n        //# foreach (var vt1 in Meta.VecTypes) {\n        //# var vtype1 = vt1.Name;\n        //# var d1 = vt1.Len;\n        //# var ft1 = vt1.FieldType;\n        //# var cast = (ft != ft1) ? \"(\" + ftype + \")\" : \"\";\n        //# var missingfields = allfields.Skip(d1).Take(d - d1);\n        //# var mfcount = missingfields.Count();\n        //# var ignoredfields = allfields.Skip(d).Take(d1 - d);\n        //# var ifcount = ignoredfields.Count();\n        /// <summary>\n        /// Creates a vector from another vector of type <see cref=\"__vtype1__\"/>.\n        //# if (mfcount > 0) { var isare = (mfcount > 1) ? \"are\" : \"is\";\n        /// /*# missingfields.ForEach(f => {*/__f__/*# }, comma);*/ __isare__ set to zero.\n        //# }\n        //# if (ifcount > 0) { var isare = (ifcount > 1) ? \"are\" : \"is\";\n        /// /*# ignoredfields.ForEach(f => {*/v.__f__/*# }, comma);*/ __isare__ ignored.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(__vtype1__ v)\n        {\n            //# fields.ForEach((f, i) => {\n            //# if (i < d1) {\n            __f__ = __cast__v.__f__;\n            //# } else {\n            __f__ = 0;\n            //# }\n            //# });\n        }\n\n        //# }\n        //# if (d == 3 || d == 4) {\n        //#     foreach (var t1 in Meta.ColorTypes) { var ft1 = t1.FieldType;\n        //#         if (coltovecsupported(ft1, ft)) {\n        //#             var type1 = t1.Name;\n        //#             var ftype1 = ft1.Name;\n        //#             var convert = ft != ft1 ? \"(\"+ ftype +\")\" : \"\";\n        //#             var maxval = colmaxvalmap[ft1];\n        /// <summary>\n        /// Creates a vector from a <see cref=\"__type1__\"/> color.\n        //# if (iscolormapped(ft, ft1)) {\n        /// The values are not mapped from the <see cref=\"__type1__\"/> color range.\n        //# }\n        //# if (d == 4 && !t1.HasAlpha) {\n        /// W is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public __vtype__(__type1__ c)\n        {\n            //# t1.Channels.ForEach(fields, (c, f) => {\n            __f__ = __convert__(c.__c__);\n            //# });\n            //# if (d == 4) {\n            //#     if (t1.HasAlpha) {\n            W = __convert__(c.A);\n            //#     } else {\n            W = __convert____t1.MaxValue__;\n            //#     }\n            //# }\n        }\n\n        //#     } }\n        //# }\n        #endregion\n\n        #region Conversions\n\n        //# foreach (var vt1 in Meta.VecTypes) {\n        //#     var vtype1 = vt1.Name;\n        //#     if (vt != vt1) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __vtype__(__vtype1__ v)\n            => new __vtype__(v);\n\n        //# } }\n        //# foreach (var vt1 in Meta.VecTypes) {\n        //#     var ft1 = vt1.FieldType;\n        //#     var vtype1 = vt1.Name;\n        //#     var d1 = vt1.Len;\n        //#     if (vt != vt1 && (ft != ft1 || d < d1)) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vtype1__ To__vtype1__() => (__vtype1__)this;\n\n        //# } }\n        //# foreach (var ft1 in Meta.VecFieldTypes) {\n        //#     var ftype1 = ft1.Name;\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __ftype1__[](__vtype__ v)\n            => new __ftype1__[] { /*# fields.ForEach(f => {\n                if (ft != ft1) { */(__ftype1__)/*# } */v.__f__/*# }, comma); */ };\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __vtype__(__ftype1__[] v)\n            => new __vtype__(/*# d.ForEach(fi => {\n                if (ft != ft1) { */(__ftype__)/*# } */v[__fi__]/*# }, comma); */);\n\n        //# }\n        //# if (d == 3 || d == 4) {\n        //#     foreach (var t1 in Meta.ColorTypes) { var ft1 = t1.FieldType;\n        //#         if (coltovecsupported(ft1, ft)) {\n        //#             var type1 = t1.Name;\n        //#             var ftype1 = ft1.Name;\n        //#             var convert = ft != ft1 ? \"(\"+ ftype +\")\" : \"\";\n        //#             var maxval = colmaxvalmap[ft1];\n        /// <summary>\n        /// Converts the given <see cref=\"__type1__\"/> color to a <see cref=\"__vtype__\"/> vector.\n        //# if (iscolormapped(ft, ft1)) {\n        /// The values are not mapped from the <see cref=\"__type1__\"/> color range.\n        //# }\n        //# if (d == 4 && !t1.HasAlpha) {\n        /// W is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static explicit operator __vtype__(__type1__ v)\n            => new __vtype__(v);\n\n        /// <summary>\n        /// Converts the given <see cref=\"__vtype__\"/> vector to a <see cref=\"__type1__\"/> color.\n        //# if (iscolormapped(ft, ft1)) {\n        /// The values are not mapped to the <see cref=\"__type1__\"/> color range.\n        //# }\n        //# if (d == 3 && t1.HasAlpha) {\n        /// The alpha channel is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __type1__ To__type1__() => (__type1__)this;\n\n        //#     } }\n        //# }\n        //# if (ft.IsReal) {\n        //#     var ichar = ft == Meta.DoubleType ? \"l\" : \"i\";\n        //#     var icast = ft == Meta.DoubleType ? \"long\" : \"int\";\n        //#     foreach (var floor in new[] { \"Floor\", \"Ceiling\" }) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly V__d____ichar__ To__floor__V__d____ichar__()\n            => new V__d____ichar__(/*# vt.Fields.ForEach(f => { */(__icast__)Fun.__floor__(__f__)/*# }, comma); */);\n\n        //#   }\n        //# }\n        //# if (d >= 3 && ft.IsReal) {\n        //#     foreach (var ft1 in Meta.VecFieldTypes) {\n        //#         var vt1 = Meta.VecTypeOf(d-1, ft1);\n        //#         var vtype1 = vt1.Name;\n        //#         var ftype1 = ft1.Name;\n        //#         var lastF = fields.Last();\n        /// <summary>\n        /// Creates the inhomogenized Version by dividing the first elements by the last element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vtype1__ To__vtype1__Inhomo()\n        {\n            var div = 1 / __lastF__;\n            return new __vtype1__(/*# vt1.Fields.ForEach(f => { */__f__ * div/*# }, comma); */);\n        }\n\n        //#     }\n        //# }\n        //# if (d <= 3 && ft.IsReal) {\n        //#     foreach (var ft1 in Meta.VecFieldTypes) {\n        //#         var vt1 = Meta.VecTypeOf(d+1, ft1);\n        //#         var vtype1 = vt1.Name;\n        //#         var ftype1 = ft1.Name;\n        /// <summary>\n        /// Creates the homogenized Version by adding an additional element 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vtype1__ To__vtype1__Homo()\n            => new __vtype1__(/*# fields.ForEach(f => { */__f__/*# }, comma); */, 1);\n\n        //#     }\n        //# }\n        //# foreach (var ft1 in Meta.VecFieldTypes) {\n        //#     var vt1 = Meta.VecTypeOf(d, ft1);\n        //#     var vtype1 = vt1.Name;\n        //#     var ftype1 = ft1.Name;\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vtype1__ Copy(Func<__ftype__, __ftype1__> element_fun)\n            => new __vtype1__(/*# fields.ForEach(f => { */element_fun(__f__)/*# }, comma); */);\n\n        /// <summary>\n        /// Returns a copy with all elements transformed by the supplied function.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __vtype1__ Copy(Func<__ftype__, int, __ftype1__> element_index_fun)\n            => new __vtype1__(/*# fields.ForEach((f, i) => { */element_index_fun(__f__, __i__)/*# }, comma); */);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo(__ftype1__[] array, int start)\n        {\n            //# fields.ForEach((f, i) => {\n            array[start + __i__] = /*# if (ft != ft1) { */(__ftype1__)/*# } */__f__;\n            //# });\n        }\n\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<__ftype__, T> element_fun)\n        {\n            //# fields.ForEach((f, i) => {\n            array[start + __i__] = element_fun(__f__);\n            //# });\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly void CopyTo<T>(T[] array, int start, Func<__ftype__, int, T> element_index_fun)\n        {\n            //# fields.ForEach((f, i) => {\n            array[start + __i__] = element_index_fun(__f__, __i__);\n            //# });\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly __ftype__[] ToArray()\n            => new __ftype__[] { /*# fields.ForEach((f, i) => { */__f__/*# }, comma); */ };\n\n        #endregion\n\n        #region Properties and Indexers\n\n        //# fields.ForEach(f => {\n        //# var pf = \"P_\" + f;\n        /// <summary>\n        /// Property for the field __f__.\n        /// Useful when properties are required, but the field __f__ is recommended for general use.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        [XmlIgnore]\n        public __ftype__ __pf__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                return __f__;\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                __f__ = value;\n            }\n        }\n\n        //# });\n        /// <summary>\n        /// Enumerates all elements of this vector.\n        /// </summary>\n        public readonly IEnumerable<__ftype__> Elements\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                //# fields.ForEach(f => {\n                yield return __f__;\n                //# });\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets element with given index.\n        /// </summary>\n        public unsafe __ftype__ this[int index]\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            readonly get\n            {\n                fixed (__ftype__* ptr = __getptr__) { return ptr[index]; }\n            }\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            set\n            {\n                fixed (__ftype__* ptr = __getptr__) { ptr[index] = value; }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the largest dimension of the vector.\n        /// </summary>\n        public readonly int MajorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                //# if (d == 2) {\n                return X >= Y ? 0 : 1;\n                //# }\n                //# if (d == 3) {\n                return X >= Y ? (X >= Z ? 0 : 2) : (Y >= Z ? 1 : 2);\n                //# }\n                //# if (d == 4) {\n                return X >= Y\n                        ? (X >= Z ? (X >= W ? 0 : 3) : (Z >= W ? 2 : 3))\n                        : (Y >= Z ? (Y >= W ? 1 : 3) : (Z >= W ? 2 : 3));\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Returns the index of the smallest dimension of the vector.\n        /// </summary>\n        public readonly int MinorDim\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                //# if (d == 2) {\n                return X <= Y ? 0 : 1;\n                //# }\n                //# if (d == 3) {\n                return X <= Y ? (X <= Z ? 0 : 2) : (Y <= Z ? 1 : 2);\n                //# }\n                //# if (d == 4) {\n                return X <= Y\n                        ? (X <= Z ? (X <= W ? 0 : 3) : (Z <= W ? 2 : 3))\n                        : (Y <= Z ? (Y <= W ? 1 : 3) : (Z <= W ? 2 : 3));\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Returns the minimum element of the vector.\n        /// </summary>\n        public readonly __ftype__ MinElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Min(/*# fields.ForEach(f => { */__f__/*# }, comma); */);\n        }\n\n        /// <summary>\n        /// Returns the maximum element of the vector.\n        /// </summary>\n        public readonly __ftype__ MaxElement\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => Fun.Max(/*# fields.ForEach(f => { */__f__/*# }, comma); */);\n        }\n\n        //# if (ft.IsReal) {\n        //# var condArray = new[] { \"Finite\", \"NaN\", \"Infinity\", \"PositiveInfinity\", \"NegativeInfinity\", \"Tiny\" };\n        //# var scopeArray = new[] { \"Fun\", ftype, ftype, ftype, ftype, \"Fun\" };\n        //# var quantArray = new[] { \"Any\", \"All\" };\n        //# var actArray = new[] { oror, andand };\n        //# condArray.ForEach(scopeArray, (cond, scope) => {\n        //# quantArray.ForEach(actArray, (qant, act) => {\n        public readonly bool __qant____cond__\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => /*# fields.ForEach((f, i) => { */__scope__.Is__cond__(__f__)/*# }, act); */;\n        }\n\n        //# }); // quantArray\n        //# }); // condArray\n        /// <summary>\n        /// Returns true if the absolute value of each component of the vector is smaller than Constant&lt;__ftype__&gt;.PositiveTinyValue, false otherwise.\n        /// </summary>\n        public readonly bool IsTiny\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AllTiny;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is NaN, false otherwise.\n        /// </summary>\n        public readonly bool IsNaN\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNaN;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite (positive or negative), false otherwise.\n        /// </summary>\n        public readonly bool IsInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and positive, false otherwise.\n        /// </summary>\n        public readonly bool IsPositiveInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyPositiveInfinity;\n        }\n\n        /// <summary>\n        /// Returns true if any component of the vector is infinite and negative, false otherwise.\n        /// </summary>\n        public readonly bool IsNegativeInfinity\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => AnyNegativeInfinity;\n        }\n\n        /// <summary>\n        /// Returns whether all components of the vector are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        public readonly bool IsFinite\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get => !(IsInfinity || IsNaN);\n        }\n\n        //# } // ft.IsReal\n        #endregion\n\n        #region Constants\n\n        /// <summary>\n        /// Number of elements in this vector.\n        /// </summary>\n        public const int Dimension = __d__;\n\n        /// <summary>\n        /// All elements zero.\n        /// </summary>\n        public static __vtype__ Zero\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { */0/*# }, comma); */); }\n        }\n\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// All elements half.\n        /// </summary>\n        public static __vtype__ Half\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { */0.5/*# }, comma); */); }\n        }\n        //# } // ft.IsReal\n\n        /// <summary>\n        /// All elements one.\n        /// </summary>\n        public static __vtype__ One\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { */1/*# }, comma); */); }\n        }\n\n        /// <summary>\n        /// All elements set to maximum possible value.\n        /// </summary>\n        public static __vtype__ MaxValue\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { */Constant<__ftype__>.ParseableMaxValue/*# }, comma); */); }\n        }\n\n        /// <summary>\n        /// All elements set to minimum possible value.\n        /// </summary>\n        public static __vtype__ MinValue\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { */Constant<__ftype__>.ParseableMinValue/*# }, comma); */); }\n        }\n\n        //# if (ft.IsReal) {\n         /// <summary>\n        /// All elements set to negative infinity.\n        /// </summary>\n        public static __vtype__ NegativeInfinity\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { */__ftype__.NegativeInfinity/*# }, comma); */); }\n        }\n\n        /// <summary>\n        /// All elements set to positive infinity.\n        /// </summary>\n        public static __vtype__ PositiveInfinity\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { */__ftype__.PositiveInfinity/*# }, comma); */); }\n        }\n\n        /// <summary>\n        /// All elements set to NaN.\n        /// </summary>\n        public static __vtype__ NaN\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { */__ftype__.NaN/*# }, comma); */); }\n        }\n\n        //# }\n        //# fields.ForEach((f, j) => {\n        /// <summary>\n        /// Normalized __f__-axis.\n        /// </summary>\n        public static __vtype__ __f__Axis\n        {\n            get { return new __vtype__(/*# d.ForEach(i => { var v = i != j ? 0 : 1; */__v__/*# }, comma); */); }\n        }\n\n        //# });\n        /// <summary>\n        /// An array of accessor functions for the coordinates of the vector.\n        /// </summary>\n        public static readonly Func<__vtype__, __ftype__>[] SelectorArray =\n            new Func<__vtype__, __ftype__>[] { /*# fields.ForEach(f => { */v => v.__f__/*# }, comma); */ };\n\n        /// <summary>\n        /// Element getter function.\n        /// </summary>\n        public static readonly Func<__vtype__, int, __ftype__> Getter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    //# fields.ForEach((f, i) => {\n                    case __i__: return v.__f__;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action.\n        /// </summary>\n        public static readonly ActionRefValVal<__vtype__, int, __ftype__> Setter =\n            (ref __vtype__ v, int i, __ftype__ s) =>\n            {\n                switch (i)\n                {\n                    //# fields.ForEach((f, i) => {\n                    case __i__: v.__f__ = s; return;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element getter function with long index.\n        /// </summary>\n        public static readonly Func<__vtype__, long, __ftype__> LongGetter =\n            (v, i) =>\n            {\n                switch (i)\n                {\n                    //# fields.ForEach((f, i) => {\n                    case __i__: return v.__f__;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        /// <summary>\n        /// Element setter action with long index.\n        /// </summary>\n        public static readonly ActionRefValVal<__vtype__, long, __ftype__> LongSetter =\n            (ref __vtype__ v, long i, __ftype__ s) =>\n            {\n                switch (i)\n                {\n                    //# fields.ForEach((f, i) => {\n                    case __i__: v.__f__ = s; return;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            };\n\n        #endregion\n\n        #region Static factories\n\n        //# foreach (var ft1 in Meta.VecFieldTypes) {\n        //#     var vt1 = Meta.VecTypeOf(d, ft1);\n        //#     var vtype1 = vt1.Name;\n        //#     if (ft != ft1) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ From__vtype1__(__vtype1__ v)\n            => new __vtype__(v);\n\n        //#     }\n        //# }\n        //# if (d == 3 || d == 4) {\n        //#     foreach (var t1 in Meta.ColorTypes) { var ft1 = t1.FieldType;\n        //#         if (coltovecsupported(ft1, ft)) {\n        //#             var type1 = t1.Name;\n        //#             var ftype1 = ft1.Name;\n        //#             var convert = ft != ft1 ? \"(\"+ ftype +\")\" : \"\";\n        //#             var maxval = colmaxvalmap[ft1];\n        /// <summary>\n        /// Creates a vector from the given <see cref=\"__type1__\"/> color.\n        //# if (iscolormapped(ft, ft1)) {\n        /// The values are not mapped from the <see cref=\"__type1__\"/> color range.\n        //# }\n        //# if (d == 4 && !t1.HasAlpha) {\n        /// W is set to __maxval__.\n        //# }\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ From__type1__(__type1__ c) => new __vtype__(c);\n\n        //#     } }\n        //# }\n        //# if (ft.IsReal) {\n        //# if (d == 2) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ FromPolar(__ftype__ angleInRadians, __ftype__ radius)\n            => new __vtype__(Fun.Cos(angleInRadians) * radius, Fun.Sin(angleInRadians) * radius);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ FromPolar(__ftype__ angleInRadians)\n            => new __vtype__(Fun.Cos(angleInRadians), Fun.Sin(angleInRadians));\n\n        //# } else if (d == 3) {\n        private static readonly __vtype__[] s_fromCubeCode =\n            new __vtype__[] { -__vtype__.XAxis, -__vtype__.YAxis, -__vtype__.ZAxis,\n                        __vtype__.XAxis, __vtype__.YAxis, __vtype__.ZAxis };\n\n        /// <summary>\n        /// Return the vector for the supplied cube face code.\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ FromCubeFaceCode(int i) { return s_fromCubeCode[i]; }\n\n        //# } // d = 3\n        //# } // ft.IsReal\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        public readonly __ftype__ LengthSquared\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return /*# fields.ForEach(f => { */__f__ * __f__ /*# }, add); */; }\n        }\n\n        //# if (ft == Meta.FloatType && d == 4) {\n#if NETCOREAPP3_1_OR_GREATER\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        static __ctype__ Length_Sse41(__vtype__ vec)\n        {\n            unsafe\n            {\n                //# if (d == 2) {\n                var vv = Vector128.Create(vec.X, vec.Y, 0.0f, 0.0f);\n                vv = Sse41.DotProduct(vv, vv, 0x31);\n                //# } else if (d == 3) {\n                var vv = Vector128.Create(vec.X, vec.Y, vec.Z, 0.0f);\n                vv = Sse41.DotProduct(vv, vv, 0x71);\n                //# } else { // d == 4\n                var x = (float*)&vec;\n                var vv = Sse.LoadVector128(x);\n                vv = Sse41.DotProduct(vv, vv, 0xF1);\n                //# }\n                var l2 = vv.GetElement(0);\n                return MathF.Sqrt(l2);\n            }\n        }\n#endif\n\n        //# } // end ft == Meta.FloatType\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        public readonly __ctype__ Length\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                //# if (ft == Meta.FloatType && d == 4) {\n#if NETCOREAPP3_1_OR_GREATER\n                if (Sse41.IsSupported)\n                    return Length_Sse41(this);\n#endif\n                //# }\n                return Fun.Sqrt(/*# fields.ForEach(f => { */__f__ * __f__ /*# }, add); */);\n            }\n        }\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        public readonly __ftype__ Norm1\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return /*# fields.ForEach(f => { if (unsigned) {*/__f__/*# } else {*/Fun.Abs(__f__)/*# } }, add); */; }\n        }\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        public readonly __ctype__ Norm2\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Sqrt(/*# fields.ForEach(f => { */__f__ * __f__/*# }, add); */); }\n        }\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        public readonly __ftype__ NormMax\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Max(/*# fields.ForEach(f => { if (unsigned) {*/__f__/*# } else {*/Fun.Abs(__f__)/*# } }, comma); */); }\n        }\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        public readonly __ftype__ NormMin\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return Fun.Min(/*# fields.ForEach(f => { if (unsigned) {*/__f__/*# } else {*/Fun.Abs(__f__)/*# } }, comma); */); }\n        }\n\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        public readonly __vctype__ Normalized\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get\n            {\n                var s = Length; if (s == 0) return __vctype__.Zero;\n                s = 1 / s;\n                return new __vctype__(/*# fields.ForEach(f => { */__f__ * s/*# }, comma); */);\n            }\n        }\n\n        //# if (d == 2 && !unsigned) {\n        /// <summary>\n        /// Vector rotated 90° counter clockwise: (-Y, X)\n        /// </summary>\n        public readonly __vtype__ Rot90\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new __vtype__(-Y, X); }\n        }\n\n        /// <summary>\n        /// Vector rotated 180° counter clockwise: (-X, -Y)\n        /// </summary>\n        public readonly __vtype__ Rot180\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new __vtype__(-X, -Y); }\n        }\n\n        /// <summary>\n        /// Vector rotated 270° counter clockwise: (Y, -X)\n        /// </summary>\n        public readonly __vtype__ Rot270\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new __vtype__(Y, -X); }\n        }\n\n        //# } // d == 2\n        //# if (ft.IsReal) {\n        //# if (d == 2) {\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered square with side length 2.\n        /// </summary>\n        public readonly __vtype__ CubeMapped\n        {\n            get\n            {\n                __ftype__ x = Fun.Abs(X);\n                __ftype__ y = Fun.Abs(Y);\n                return x > y\n                        ? new __vtype__(Fun.Sign(X), Y / x)\n                        : new __vtype__(X / y, Fun.Sign(Y));\n            }\n        }\n\n        //# } // d == 2\n        //# else if (d == 3) {\n        //# foreach (var face in new bool[] { false, true }) {\n        //#     string facepar = face ? \"OnFace(out int face)\" : \"\";\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered cube with side length 2.\n        //# if (face) {\n        /// The out parameter face indicate which face the vector was mapped to:\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        //# }\n        /// </summary>\n        public readonly __vtype__ CubeMapped__facepar__\n        {\n            //# if (!face) {\n            get\n            {\n            //# }\n                __ftype__ x = Fun.Abs(X);\n                __ftype__ y = Fun.Abs(Y);\n                __ftype__ z = Fun.Abs(Z);\n                if (x > y)\n                {\n                    if (x > z)\n                    {\n                        double s = 1 / x;/*# if (face) { */ face = X < 0 ? 0 : 3;/*# } */\n                        return new __vtype__(Fun.Sign(X), Y * s, Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z;/*# if (face) { */ face = Z < 0 ? 2 : 5;/*# } */\n                        return new __vtype__(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n                else\n                {\n                    if (y > z)\n                    {\n                        double s = 1 / y;/*# if (face) { */ face = Y < 0 ? 1 : 4;/*# } */\n                        return new __vtype__(X * s, Fun.Sign(Y), Z * s);\n                    }\n                    else\n                    {\n                        double s = 1 / z;/*# if (face) { */ face = Z < 0 ? 2 : 5;/*# } */\n                        return new __vtype__(X * s, Y * s, Fun.Sign(Z));\n                    }\n                }\n            //# if (!face) {\n            }\n            //# }\n        }\n\n        //# } // face\n        /// <summary>\n        /// Return an index for the cube face onto which the vector points.\n        /// 0 ... -XAxis, 1 ... -YAxis, 2 ... -ZAsix, 3 ... XAxis, 4 ... YAxis, 5 ... ZAxis.\n        /// </summary>\n        public readonly int CubeFaceCode\n        {\n            get\n            {\n                double x = Fun.Abs(X);\n                double y = Fun.Abs(Y);\n                double z = Fun.Abs(Z);\n                int c;\n                double v;\n                if (x > y)\n                {\n                    if (x > z) { c = 0; v = X; } else { c = 2; v = Z; }\n                }\n                else\n                {\n                    if (y > z) { c = 1; v = Y; } else { c = 2; v = Z; }\n                }\n                return v < 0 ? c : c + 3;\n            }\n        }\n\n        //# } // d == 3\n        //# else {\n        /// <summary>\n        /// Returns a copy of the vector with the maximum component length of\n        /// exactly 1. This corresponds to mapping the vector onto an origin-\n        /// centered cube with side length 2.\n        /// </summary>\n        public readonly __vtype__ CubeMapped\n        {\n            get\n            {\n                var s = 1 / Fun.Max(/*# fields.ForEach(f => { */Fun.Abs(__f__)/*# }, comma); */);\n                return new __vtype__(/*# fields.ForEach(f => { */__f__ * s/*# }, comma); */);\n            }\n        }\n\n        //# } // d > 3\n        //# } // ft.IsReal\n        #endregion\n\n        #region Static methods for F# core and Aardvark library support\n\n        //# if (!unsigned) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Abs(__vtype__ v)\n            => v.Abs();\n\n        //# }\n        //# if (ft.IsReal) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Floor(__vtype__ v)\n            => v.Floor();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Ceiling(__vtype__ v)\n            => v.Ceiling();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Round(__vtype__ v)\n            => v.Round();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Truncate(__vtype__ v)\n            => v.Truncate();\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Acos(__vtype__ v)\n            => Fun.Acos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Acoshb(__vtype__ v)\n            => Fun.Acosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Cos(__vtype__ v)\n            => Fun.Cos(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Cosh(__vtype__ v)\n            => Fun.Cosh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Asin(__vtype__ v)\n            => Fun.Asin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Asinhb(__vtype__ v)\n            => Fun.Asinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Sin(__vtype__ v)\n            => Fun.Sin(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Sinh(__vtype__ v)\n            => Fun.Sinh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Atan(__vtype__ v)\n            => Fun.Atan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Atanhb(__vtype__ v)\n            => Fun.Atanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Atan2(__vtype__ a, __vtype__ b)\n            => Fun.Atan2(a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Tan(__vtype__ v)\n            => Fun.Tan(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Tanh(__vtype__ v)\n            => Fun.Tanh(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Sqrt(__vtype__ v)\n            => Fun.Sqrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ CubeRoot(__vtype__ v)\n            => Fun.Cbrt(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Exp(__vtype__ v)\n            => Fun.Exp(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Log(__vtype__ v)\n            => Fun.Log(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ LogBinary(__vtype__ v)\n            => Fun.Log2(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Log10(__vtype__ v)\n            => Fun.Log10(v);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ CopySgn(__vtype__ value, __vtype__ sign)\n            => Fun.CopySign(value, sign);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ CopySgn(__vtype__ value, __ftype__ sign)\n            => Fun.CopySign(value, sign);\n\n        //# } // ft.IsReal\n        //# foreach(var tt in fdtypes) {\n        //# var vtt = Meta.VecTypeOf(d, tt);\n        //# if (ft.IsReal && tt != ft) continue;\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ LinearInterp(__tt.Name__ t, __vtype__ a, __vtype__ b)\n            => Fun.Lerp(t, a, b);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ LinearInterp(__vtt.Name__ t, __vtype__ a, __vtype__ b)\n            => Fun.Lerp(t, a, b);\n\n        //#}\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Min(__vtype__ v0, __vtype__ v1)\n            => Fun.Min(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Min(__vtype__ v, __ftype__ x)\n            => Fun.Min(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Max(__vtype__ v0, __vtype__ v1)\n            => Fun.Max(v0, v1);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Max(__vtype__ v, __ftype__ x)\n            => Fun.Max(v, x);\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Saturate(__vtype__ v)\n            => Fun.Saturate(v);\n\n        //# if (!unsigned) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ DivideByInt(__vtype__ v, int x)\n            => v / x;\n\n        //# }\n        #endregion\n\n        #region Operations\n\n        //# foreach (var ft1 in Meta.VecFieldTypes) {\n        //#     var vt1 = Meta.VecTypeOf(d, ft1);\n        //#     var ftype1 = ft1.Name;\n        /// <summary>\n        /// Sets the elements of a vector to the given __ftype1__ elements.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void Set(/*# args.ForEach(a => { */__ftype1__ __a__/*# }, comma); */)\n        {\n            //# fields.ForEach(args, (f, a) => {\n            __f__ = /*# if (ft != ft1) { */(__ftype__)/*# } */__a__;\n            //# });\n        }\n\n        //# }\n        //# if (!unsigned) {\n        /// <summary>\n        /// Returns a negated copy of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ operator -(__vtype__ v)\n            => new __vtype__(/*# fields.ForEach(f => { */-v.__f__/*# }, comma); */);\n\n        //# }\n        //# if (!ft.IsReal) {\n        /// <summary>\n        /// Returns the component-wise bitwise complement of the specified vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ operator ~(__vtype__ v)\n            => new __vtype__(/*# fields.ForEach(f => { */~v.__f__/*# }, comma); */);\n\n        //# }\n        //# if (d == 2 && !unsigned) {\n        /// <summary>\n        /// Returns a vector that is orthogonal to this one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        public readonly __vtype__ Orthogonal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new __vtype__(-__f1__, __f0__); }\n        }\n\n        //# }\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Gets a copy of this vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        public readonly __vtype__ Reciprocal\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            get { return new __vtype__(/*# fields.ForEach(f => { */1 / __f__/*# }, comma); */); }\n        }\n\n        //# }\n        //# {\n        //# var ops = new[] {\" + \", \" - \", \" * \", \" / \", \" % \"};\n        //# var opactions = new[]  { \"operator +\", \"operator -\", \"operator *\", \"operator /\", \"operator %\"};\n        //# var opnames = new[] {\"sum\", \"difference\", \"product\", \"fraction\", \"remainder\"};\n        //# for (int o = 0; o < ops.Length; o++) {\n        //#     var op = ops[o];\n        //#     var opname = opnames[o];\n        //#     var opaction = opactions[o];\n        /// <summary>\n        /// Returns the component-wise __opname__ of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ __opaction__(__vtype__ a, __vtype__ b)\n            => new __vtype__(/*# fields.ForEach(f => { */a.__f____op__b.__f__/*# }, comma); */);\n\n        /// <summary>\n        /// Returns the component-wise __opname__ of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ __opaction__(__vtype__ v, __ftype__ s)\n            => new __vtype__(/*# fields.ForEach(f => { */v.__f____op__s/*#  }, comma); */);\n\n        /// <summary>\n        /// Returns the component-wise __opname__ of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ __opaction__(__ftype__ s, __vtype__ v)\n            => new __vtype__(/*# fields.ForEach(f => { */s__op__v.__f__/*# }, comma); */);\n\n        //# }\n        //# }\n        //# if (!ft.IsReal) {\n        //# var ops = new[] {\"&\", \"|\", \"^\"};\n        //# var opnames = new[] {\"bitwise and\", \"bitwise or\", \"bitwise exclusive or\" };\n        //# for (int o = 0; o < ops.Length; o++) {\n        //#     var op = ops[o];\n        //#     var opname = opnames[o];\n        /// <summary>\n        /// Returns the component-wise __opname__ of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ operator __op__(__vtype__ a, __vtype__ b)\n            => new __vtype__(/*# fields.ForEach(f => { */a.__f__ __op__ b.__f__/*# }, comma); */);\n\n        /// <summary>\n        /// Returns the component-wise __opname__ of a vector and a scalar.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ operator __op__(__vtype__ v, __ftype__ s)\n            => new __vtype__(/*# fields.ForEach(f => { */v.__f__ __op__ s/*#  }, comma); */);\n\n        /// <summary>\n        /// Returns the component-wise __opname__ of a scalar and a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ operator __op__(__ftype__ s, __vtype__ v)\n            => new __vtype__(/*# fields.ForEach(f => { */s __op__ v.__f__/*# }, comma); */);\n\n        //# }\n        /// <summary>\n        /// Returns the component-wise left bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ operator <<(__vtype__ v, int s)\n            => new __vtype__(/*# fields.ForEach(f => { */v.__f__ << s/*#  }, comma); */);\n\n        /// <summary>\n        /// Returns the component-wise right bitshift of a vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ operator >>(__vtype__ v, int s)\n            => new __vtype__(/*# fields.ForEach(f => { */v.__f__ >> s/*#  }, comma); */);\n\n        //# }\n        /// Attention: NEVER implement operators &lt;, &lt;=, &gt;=, &gt;,\n        /// since these are not defined in a Vector space.\n        /// Use AllSmaller() and similar comparators!\n        #endregion\n\n        #region Comparisons\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__vtype__ a, __vtype__ b)\n        {\n            return /*# fields.ForEach(f => { */a.__f__ == b.__f__/*# }, andand); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__vtype__ v, __ftype__ s)\n        {\n            return /*# fields.ForEach(f => { */v.__f__ == s/*# }, andand); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator ==(__ftype__ s, __vtype__ v)\n        {\n            return /*# fields.ForEach(f => { */s == v.__f__/*# }, andand); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__vtype__ a, __vtype__ b)\n        {\n            return /*# fields.ForEach(f => { */a.__f__ != b.__f__/*# }, oror); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__vtype__ v, __ftype__ s)\n        {\n            return /*# fields.ForEach(f => { */v.__f__ != s/*# }, oror); */;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool operator !=(__ftype__ s, __vtype__ v)\n        {\n            return /*# fields.ForEach(f => { */s != v.__f__/*# }, oror); */;\n        }\n\n        #endregion\n\n        #region IEquatable<__vtype__> Members\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public readonly bool Equals(__vtype__ other)\n        {\n            return /*# fields.ForEach(f => { */__f__.Equals(other.__f__)/*# }, andand); */;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString()\n        {\n            return ToString(null, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format)\n        {\n            return ToString(format, CultureInfo.InvariantCulture);\n        }\n\n        public readonly string ToString(string format, IFormatProvider fp)\n        {\n            return ToString(format, fp, \"[\", \", \", \"]\");\n        }\n\n        /// <summary>\n        /// Outputs e.g. a 3D-Vector in the form \"(begin)x(between)y(between)z(end)\".\n        /// </summary>\n        public readonly string ToString(string format, IFormatProvider fp, string begin, string between, string end)\n        {\n            if (fp == null) fp = CultureInfo.InvariantCulture;\n            return begin /*# fields.ForEach(f => {*/+ __f__.ToString(format, fp) /*# }, addbetween); */ + end;\n        }\n\n        public override readonly int GetHashCode()\n        {\n            return HashCode.GetCombined(/*# fields.ForEach(f => { */__f__/*# }, comma); */);\n        }\n\n        public override readonly bool Equals(object other)\n            => (other is __vtype__ o) ? Equals(o) : false;\n\n        public readonly Text ToText(int bracketLevel = 1)\n        {\n            return\n                ((bracketLevel == 1 ? \"[\" : \"\")/*# fields.ForEach(f => {*/\n                + __f__.ToString(null, CultureInfo.InvariantCulture) /*# }, addqcommaspace); */\n                + (bracketLevel == 1 ? \"]\" : \"\")).ToText();\n        }\n\n        #endregion\n\n        #region Parsing\n\n        public static __vtype__ Parse(string s)\n        {\n            var x = s.NestedBracketSplitLevelOne().ToArray();\n            return new __vtype__(/*# d.ForEach(p => { */\n                __ftype__.Parse(x[__p__], CultureInfo.InvariantCulture)/*# }, comma); */\n            );\n        }\n\n        public static __vtype__ Parse(Text t)\n        {\n            return t.NestedBracketSplit(1, Text<__ftype__>.Parse, __vtype__.Setter);\n        }\n\n        public static __vtype__ Parse(Text t, int bracketLevel)\n        {\n            return t.NestedBracketSplit(bracketLevel, Text<__ftype__>.Parse, __vtype__.Setter);\n        }\n\n        #endregion\n\n        #region Swizzle Methods\n\n        //# var snames  = unsigned ? new string[] { \"O\", \"I\", \"X\", \"Y\", \"Z\", \"W\" } : new string[] { \"O\", \"I\", \"N\", \"X\", \"Y\", \"Z\", \"W\" };\n        //# var svalues = unsigned ? new string[] { \"0\", \"1\", \"X\", \"Y\", \"Z\", \"W\" } : new string[] { \"0\", \"1\", \"-1\",\"X\", \"Y\", \"Z\", \"W\" };\n        //# var isConst = new Func<int, bool>(i => i < (unsigned ? 2 : 3));\n        //# var s = d + (unsigned ? 2 : 3);\n        //# var getName = new Func<bool, int, string>((anyN, i) => anyN && i == 1 ? \"P\" : snames[i]);\n        //# for (int xi = 0; xi < s; xi++) { var x = svalues[xi];\n        //#     for (int yi = 0; yi < s; yi++) { var y = svalues[yi];\n        //#         var anyN = !unsigned && (xi == 2 || yi == 2); // replace I by P if any N\n        //#         var name = getName(anyN, xi) + getName(anyN, yi);\n        //#         if (isConst(xi) && isConst(yi)) { // check for constant -> otherwise property\n        //#             if (d == 2) { // only constants of matching size\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static __v2type__ __name__ => new __v2type__(__x__, __y__);\n        //#             }\n        //#         }\n        //#         else {\n        //#             if (xi == yi || isConst(xi) || isConst(yi)) { // readonly if the same or constants\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly __v2type__ __name__ => new __v2type__(__x__, __y__);\n        //#             } else {\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __v2type__ __name__\n        {\n            readonly get => new __v2type__(__x__, __y__);\n            set { __x__ = value.X; __y__ = value.Y; }\n        }\n        //#             }\n        //#         }\n        //#     }\n        //# }\n        //# for (int xi = 0; xi < s; xi++) { var x = svalues[xi];\n        //#     for (int yi = 0; yi < s; yi++) { var y = svalues[yi];\n        //#         for (int zi = 0; zi < s; zi++) { var z = svalues[zi];\n        //#             var anyN = !unsigned && (xi == 2 || yi == 2 || zi == 2); // replace I by P if any N\n        //#             var name = getName(anyN, xi) + getName(anyN, yi) + getName(anyN, zi);\n        //#             if (isConst(xi) && isConst(yi) && isConst(zi)) { // check for constant -> otherwise property\n        //#                 if (d == 3) { // only constants of matching size\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static __v3type__ __name__ => new __v3type__(__x__, __y__, __z__);\n        //#                 }\n        //#             }\n        //#             else {\n        //#                 if (xi == yi || xi == zi || yi == zi || isConst(xi) || isConst(yi) || isConst(zi)) { // readonly if the same or constants\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly __v3type__ __name__ => new __v3type__(__x__, __y__, __z__);\n        //#                 } else {\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __v3type__ __name__\n        {\n            readonly get => new __v3type__(__x__, __y__, __z__);\n            set { __x__ = value.X; __y__ = value.Y; __z__ = value.Z; }\n        }\n        //#                 }\n        //#             }\n        //#         }\n        //#     }\n        //# }\n        //# // if (d != 4) { // lets try if it does not explode\n        //#     for (int xi = 0; xi < s; xi++) { var x = svalues[xi];\n        //#         for (int yi = 0; yi < s; yi++) { var y = svalues[yi];\n        //#             for (int zi = 0; zi < s; zi++) { var z = svalues[zi];\n        //#                 for (int wi = 0; wi < s; wi++) { var w = svalues[wi];\n        //#                     var anyN = !unsigned && (xi == 2 || yi == 2 || zi == 2 || wi == 2); // replace I by P if any N\n        //#                     var name = getName(anyN, xi) + getName(anyN, yi) + getName(anyN, zi) + getName(anyN, wi);\n        //#                     if (isConst(xi) && isConst(yi) && isConst(zi) && isConst(wi)) { // check for constant -> otherwise property\n        //#                         if (d == 4) { // only constants of matching size\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public static __v4type__ __name__ => new __v4type__(__x__, __y__, __z__, __w__);\n        //#                         }\n        //#                     }\n        //#                     else {\n        //#                         if (xi == yi || xi == zi || xi == wi ||\n        //#                             yi == zi || yi == wi || zi == wi ||\n        //#                             isConst(xi) || isConst(yi) || isConst(zi) || isConst(wi)) { // readonly if the same or constants\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly __v4type__ __name__ => new __v4type__(__x__, __y__, __z__, __w__);\n        //#                         } else {\n        [XmlIgnore]\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __v4type__ __name__\n        {\n            readonly get => new __v4type__(__x__, __y__, __z__, __w__);\n            set { __x__ = value.X; __y__ = value.Y; __z__ = value.Z; __w__ = value.W; }\n        }\n        //#                         }\n        //#                     }\n        //#                 }\n        //#             }\n        //#         }\n        //#     }\n        //# // }\n\n        #endregion\n\n        #region IVector<double> Members\n\n        /// <summary>\n        /// By using long indices, the IVector&lt;double&gt; interface is\n        /// accessed.\n        /// </summary>\n        public double this[long i]\n        {\n            readonly get { return (double)this[(int)i]; }\n            set { this[(int)i] = (__ftype__)value; }\n        }\n\n        #endregion\n\n        #region ISize__d____fchar__ Members\n\n        public readonly __vtype__ Size__d____fchar__ { get { return this; } }\n\n        #endregion\n\n        #region IVector\n\n        public readonly long Dim\n        {\n            get { return __d__; }\n        }\n\n        public readonly object GetValue(long index)\n        {\n            return (object)this[(int)index];\n        }\n\n        public void SetValue(object value, long index)\n        {\n            this[(int)index] = (__ftype__)value;\n        }\n\n        #endregion\n\n    }\n\n    public class __vtype__EqualityComparer : IEqualityComparer<__vtype__>\n    {\n        public static __vtype__EqualityComparer Default\n            => new __vtype__EqualityComparer();\n\n        #region IEqualityComparer<__vtype__> Members\n\n        public bool Equals(__vtype__ v0, __vtype__ v1)\n        {\n            return v0 == v1;\n        }\n\n        public int GetHashCode(__vtype__ v)\n        {\n            return v.GetHashCode();\n        }\n\n        #endregion\n    }\n\n    public static partial class Fun\n    {\n        //# Func<Meta.ElementwiseFun.Parameter, Meta.SimpleType> getParamType =\n        //#    (p) =>\n        //#    {\n        //#        var elemType = p.ElementType ?? ft;\n        //#        return (p.IsScalar()) ? elemType : Meta.VecTypeOf(d, elemType);\n        //#    };\n        //#\n        //# foreach (var group in Meta.ElementwiseFuns.Keys) {\n        //# var isEmpty = Meta.ElementwiseFuns[group].TrueForAll(f => !f.Domain.Contains(ft));\n        //# if (!isEmpty) {\n        #region __group__\n\n        //# foreach (var fun in Meta.ElementwiseFuns[group]) {\n        //# if (!fun.Domain.Contains(ft)) continue;\n        //# var retType = Meta.VecTypeOf(d, fun.ReturnType ?? ft).Name;\n        /// <summary>\n        /// Applies Fun.__fun.Name__ to each element of the given vector(s).\n        /// </summary>\n        [Pure]\n        //# if (fun.Obsolete) {\n        [Obsolete]\n        //# }\n        //# if (!fun.EditorBrowsable) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __retType__ __fun.Name__(/*# fun.Parameters.ForEach((p, i) => {\n        var name = p.Name;\n        var ptype = getParamType(p).Name;\n        var ext = fun.IsExtension && (i == 0);\n        var varg = fun.HasVarArgs && (i == fun.Parameters.Length - 1);\n        if (ext) { */this /*# } if (varg) { */params /*# } */__ptype__/*# if (varg) {*/[]/*# }*/ __name__/*#}, comma); */)\n        {\n            return new __retType__(/*# fields.ForEach(f => {*/__fun.Name__(/*# fun.Parameters.ForEach((p, i) => {\n            var vec = !p.IsScalar();\n            var varg = fun.HasVarArgs && (i == fun.Parameters.Length - 1);\n            */__p.Name__/*#if (vec) { if (varg) {*/.Map(a => a.__f__)/*# } else {*/.__f__/*#} } }, comma); */)/*#}, comma); */);\n        }\n\n        //# }\n        #endregion\n\n        //# } // isEmpty\n        //# }\n        #region ApproximateEquals\n\n        /// <summary>\n        /// Returns whether the given vectors are equal within the given tolerance.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __vtype__ a, __vtype__ b, __ftype__ tolerance)\n        {\n            return /*# fields.ForEach(f => { */ApproximateEquals(a.__f__, b.__f__, tolerance)/*# }, andand); */;\n        }\n\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Returns whether the given vectors are equal within\n        /// Constant{__ftype__}.PositiveTinyValue.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool ApproximateEquals(this __vtype__ a, __vtype__ b)\n        {\n            return ApproximateEquals(a, b, Constant<__ftype__>.PositiveTinyValue);\n        }\n\n        //# }\n\n        #endregion\n\n        #region IsTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"__vtype__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(this __vtype__ v, __ftype__ epsilon)\n            => Vec.AllTiny(v, epsilon);\n\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"__vtype__\"/> is smaller than Constant&lt;__ftype__&gt;.PositiveTinyValue.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsTiny(__vtype__ v)\n            => v.IsTiny;\n\n        //# }\n        #endregion\n        //# if (ft.IsReal) {\n\n        #region Special Floating Point Value Checks\n\n        /// <summary>\n        /// Returns whether any component of the given <see cref=\"__vtype__\"/> is NaN.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNaN(__vtype__ v)\n            => v.IsNaN;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"__vtype__\"/> is infinity (positive or negative).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsInfinity(__vtype__ v)\n            => v.IsInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"__vtype__\"/> is positive infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsPositiveInfinity(__vtype__ v)\n            => v.IsPositiveInfinity;\n\n        /// <summary>\n        /// Returns whether any component of the the given <see cref=\"__vtype__\"/> is negative infinity.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsNegativeInfinity(__vtype__ v)\n            => v.IsNegativeInfinity;\n\n        /// <summary>\n        /// Returns whether all components of the the given <see cref=\"__vtype__\"/> are finite (i.e. not NaN and not infinity).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool IsFinite(__vtype__ v)\n            => v.IsFinite;\n\n        #endregion\n        //# }\n    }\n\n    //# if (ft.IsReal) {\n    public static partial class Conversion\n    {\n        #region Angles (Radians, Degrees, Gons)\n\n        //# var units = new[] { \"Radians\", \"Degrees\", \"Gons\" };\n        //# units.ForEach(u1 => {\n        //# units.ForEach(u2 => { if (u1 == u2) return;\n        //# var n1 = u1.ToLower();\n        //# var n2 = u2.ToLower();\n        /// <summary>\n        /// Converts the angles given in __n2__ to __n1__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ __u1__From__u2__(this __vtype__ __n2__)\n            => new __vtype__(/*# fields.ForEach(f => {*/\n                   __u1__From__u2__(__n2__.__f__)/*# }, comma); */\n               );\n\n        //# }); });\n        #endregion\n    }\n\n    //# }\n    /// <summary>\n    /// Contains static methods\n    /// </summary>\n    public static partial class Vec\n    {\n        #region Length\n\n        /// <summary>\n        /// Returns the squared length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ LengthSquared(__vtype__ v)\n            => v.LengthSquared;\n\n        /// <summary>\n        /// Returns the length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ Length(__vtype__ v)\n            => v.Length;\n\n        #endregion\n\n        #region Normalize\n\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Normalizes the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Normalize(this ref __vtype__ v)\n        {\n            var s = v.Length; if (s == 0) return;\n            s = 1 / s;\n            //# fields.ForEach(f => {\n            v.__f__ *= s;\n            //# });\n        }\n\n        //# } // ft.IsReal\n        /// <summary>\n        /// Returns a normalized copy of this vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vctype__ Normalized(__vtype__ v)\n            => v.Normalized;\n\n        #endregion\n\n        #region Norms\n\n        /// <summary>\n        /// Returns the Manhattan (or 1-) norm of the vector. This is\n        /// calculated as |x| + |y| + ...\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Norm1(__vtype__ v)\n            => v.Norm1;\n\n        /// <summary>\n        /// Returns the Euclidean (or 2-) norm of the vector. This is the\n        /// length of the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ Norm2(__vtype__ v)\n            => v.Norm2;\n\n        /// <summary>\n        /// Returns the infinite (or maximum) norm of the vector. This is\n        /// calculated as max(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ NormMax(__vtype__ v)\n            => v.NormMax;\n\n        /// <summary>\n        /// Returns the minimum norm of the vector. This is calculated as\n        /// min(|x|, |y|, ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ NormMin(__vtype__ v)\n            => v.NormMin;\n\n        /// <summary>\n        /// Gets the p-norm. This is calculated as the p-th root of (|x|^n + |y|^n + ...).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ Norm(this __vtype__ v, __ctype__ p)\n        {\n            return (/*# fields.ForEach(f => { */\n                Fun.Abs(v.__f__).Pow(p)/*# }, add); */).Pow(1 / p);\n        }\n\n        #endregion\n\n        #region Distance functions\n\n        /// <summary>\n        /// Returns the squared distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ DistanceSquared(this __vtype__ a, __vtype__ b)\n            //# if (unsigned) {\n            => /*# fields.ForEach(f => { */Fun.Square((a.__f__ < b.__f__) ? (b.__f__ - a.__f__) : (a.__f__ - b.__f__))/*# }, add); */;\n            //# } else {\n            => /*# fields.ForEach(f => { */Fun.Square(b.__f__ - a.__f__)/*# }, add); */;\n            //# }\n\n        /// <summary>\n        /// Returns the distance between the given points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ Distance(this __vtype__ a, __vtype__ b)\n            => Fun.Sqrt(DistanceSquared(a, b));\n\n        /// <summary>\n        /// Returns the Manhatten (or 1-) distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Distance1(this __vtype__ a, __vtype__ b)\n            //# if (unsigned) {\n            => /*# fields.ForEach(f => { */((a.__f__ < b.__f__) ? (b.__f__ - a.__f__) : (a.__f__ - b.__f__))/*# }, add); */;\n            //# } else {\n            => /*# fields.ForEach(f => { */Fun.Abs(b.__f__ - a.__f__)/*# }, add); */;\n            //# }\n\n        /// <summary>\n        /// Returns the p-distance between two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ Distance(this __vtype__ a, __vtype__ b, __ctype__ p)\n            //# if (unsigned) {\n            => (/*# fields.ForEach(f => { */((a.__f__ < b.__f__) ? (b.__f__ - a.__f__) : (a.__f__ - b.__f__)).Pow(p)/*# }, add); */).Pow(1 / p);\n            //# } else {\n            => (/*# fields.ForEach(f => { */Fun.Abs(b.__f__ - a.__f__).Pow(p)/*# }, add); */).Pow(1 / p);\n            //# }\n\n        /// <summary>\n        /// Returns the maximal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ DistanceMax(this __vtype__ a, __vtype__ b)\n            //# if (unsigned) {\n            => Fun.Max(/*# fields.ForEach(f => { */((a.__f__ < b.__f__) ? (b.__f__ - a.__f__) : (a.__f__ - b.__f__))/*# }, comma); */);\n            //# } else {\n            => Fun.Max(/*# fields.ForEach(f => { */Fun.Abs(b.__f__ - a.__f__)/*# }, comma); */);\n            //# }\n\n        /// <summary>\n        /// Returns the minimal absolute distance between the components of\n        /// the two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ DistanceMin(this __vtype__ a, __vtype__ b)\n            //# if (unsigned) {\n            => Fun.Min(/*# fields.ForEach(f => { */((a.__f__ < b.__f__) ? (b.__f__ - a.__f__) : (a.__f__ - b.__f__))/*# }, comma); */);\n            //# } else {\n            => Fun.Min(/*# fields.ForEach(f => { */Fun.Abs(b.__f__ - a.__f__)/*# }, comma); */);\n            //# }\n\n        //# foreach (var hasT in new[] { false, true }) {\n        //# var cast = (ft != ct) ? \"(\" + vctype + \") \" : \"\";\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the line segment defined by the two supplied line end\n        /// points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ DistanceToLine(\n                this __vtype__ query, __vtype__ p0, __vtype__ p1/*# if (hasT) { */, out __ctype__ t/*# } */)\n        {\n            //# if (ft.IsReal) {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            /*# if (!hasT) {\n            */var /*# } */t = Dot(p0q, p0p1);\n            if (t <= 0) { /*# if (hasT) { */t = 0; /*# } */return p0q.Length; }\n            var denom = p0p1.LengthSquared;\n            if (t >= denom) { /*# if (hasT) { */t = 1; /*# } */return Distance(query, p1); }\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n            //# } else {\n            return DistanceToLine(__cast__query, __cast__p0, __cast__p1/*# if (hasT) { */, out t/*# } */);\n            //# }\n        }\n\n        /// <summary>\n        /// Returns the minimal euclidean distance between the supplied query\n        /// point and the infinite line defined by two points.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ DistanceToInfiniteLine(\n                this __vtype__ query, __vtype__ p0, __vtype__ p1/*# if (hasT) { */, out __ctype__ t/*# } */)\n        {\n            //# if (ft.IsReal) {\n            var p0p1 = p1 - p0;\n            var p0q = query - p0;\n            /*# if (!hasT) {\n            */var /*# } */t = Dot(p0q, p0p1);\n            var denom = p0p1.LengthSquared;\n            t /= denom;\n            return (p0q - t * p0p1).Length;\n            //# } else {\n            return DistanceToInfiniteLine(__cast__query, __cast__p0, __cast__p1/*# if (hasT) { */, out t/*# } */);\n            //# }\n        }\n\n        //# } // hasT\n        #endregion\n\n        #region Operations\n\n        //# if (d == 2 && !unsigned) {\n        /// <summary>\n        /// Returns a vector that is orthogonal to the given one (i.e. {x,y} -> {-y,x}).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Orthogonal(__vtype__ v)\n            => v.Orthogonal;\n\n        //# }\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Gets a copy of the given vector containing the reciprocal (1/x) of each element.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Reciprocal(__vtype__ v)\n            => v.Reciprocal;\n\n        //# }\n        //# if (!unsigned) {\n        /// <summary>\n        /// Negates the vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void Negate(this ref __vtype__ v)\n        {\n            //# fields.ForEach(f => {\n            v.__f__ = -v.__f__;\n            //# });\n        }\n\n        /// <summary>\n        /// Returns the outer product (tensor-product) of a * b^T as a __d__x__d__ matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __mtype__ Outer(this __vtype__ a, __vtype__ b)\n        {\n            return new __mtype__(/*# d.ForEach(i => { var fi = fields[i]; */\n                        /*# d.ForEach(j => { var fj = fields[j]; */a.__fi__ * b.__fj__/*# }, comma); }, comma); */);\n        }\n\n        //# }\n        /// <summary>\n        /// Returns the dot product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Dot(this __vtype__ a, __vtype__ b)\n        {\n            return /*# fields.ForEach(f => { */a.__f__ * b.__f__/*# }, add); */;\n        }\n\n        //# if (d == 3 && !unsigned) {\n        /// <summary>\n        /// Returns the skew-symmetric \"cross\" matrix (A^T = -A) of the vector v.\n        /// </summary>\n        public static __mtype__ CrossMatrix(this __vtype__ v)\n        {\n            return new __mtype__(0, -v.Z, +v.Y,\n                            +v.Z, 0, -v.X,\n                            -v.Y, +v.X, 0);\n        }\n\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static DirFlags DirFlags(this __vtype__ v)\n        {\n            //# var posTiny = ft.IsReal ? \"Constant<\" + ftype + \">.PositiveTinyValue\" : \"0\";\n            //# var negTiny = ft.IsReal ? \"Constant<\" + ftype + \">.NegativeTinyValue\" : \"0\";\n            DirFlags flags = Aardbase.DirFlags.None;\n            //# fields.ForEach(f => {\n            if (v.__f__ > __posTiny__) flags |= Aardbase.DirFlags.Positive__f__;\n            if (v.__f__ < __negTiny__) flags |= Aardbase.DirFlags.Negative__f__;\n            //# });\n            return flags;\n        }\n\n        //# if (ft.IsReal) {\n        /// <summary>\n        /// Returns the reflection direction of the given vector v (pointing to the surface) for the given normal (should be normalized).\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Reflect(this __vtype__ v, __vtype__ normal)\n        {\n            return v - 2 * v.Dot(normal) * normal;\n        }\n\n        /// <summary>\n        /// Returns the refraction direction of the given vector v (pointing to the surface) for the given normal and ratio of refraction indices (n_out / n_in).\n        /// Both the input vectors should be normalized.\n        /// Returns a zero-vector in case of total internal reflection.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Refract(this __vtype__ v, __vtype__ normal, __ftype__ eta)\n        {\n            var t = v.Dot(normal);\n            var k = 1 - eta * eta * (1 - t * t);\n\n            if (k < 0)\n            {\n                return __vtype__.Zero;\n            }\n            else\n            {\n                return eta * v - (eta * t + Fun.Sqrt(k)) * normal;\n            }\n        }\n\n        //# } // ft.IsReal\n        //# if (d == 3 && !unsigned) {\n        /// <summary>\n        /// Returns the cross product of two vectors.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Cross(this __vtype__ a, __vtype__ b)\n        {\n            return new __vtype__(\n            a.__f1__ * b.__f2__ - a.__f2__ * b.__f1__,\n            a.__f2__ * b.__f0__ - a.__f0__ * b.__f2__,\n            a.__f0__ * b.__f1__ - a.__f1__ * b.__f0__\n            );\n        }\n\n        //# }\n        //# if (d == 2 && !unsigned) {\n        /// <summary>\n        /// Returns the cross product of vector a.\n        /// In 2D the cross product is simply a vector that is normal\n        /// to the given vector (i.e. {x,y} -> {-y,x})\n        /// </summary>\n        public static __vtype__ Cross(this __vtype__ a)\n        {\n            return new __vtype__(-a.__f1__, a.__f0__);\n        }\n\n        //# }\n        #endregion\n\n        #region Comparisons\n\n        //# var bops = new[,] { { \"<\",  \"Smaller\"        }, { \">\" , \"Greater\"},\n        //#                     { \"<=\", \"SmallerOrEqual\" }, { \">=\", \"GreaterOrEqual\"},\n        //#                     { \"==\", \"Equal\" },          { \"!=\", \"Different\" } };\n        //# var attention = \"ATTENTION: For example (AllSmaller(a,b)) is not the same as !(AllGreaterOrEqual(a,b)) but !(AnyGreaterOrEqual(a,b)).\";\n        //# for(int o = 0; o < bops.GetLength(0); o++) {\n        //#     string bop = \" \" + bops[o,0] + \" \", opName = bops[o,1];\n        /// <summary>\n        /// Returns whether ALL elements of a are __opName__ the corresponding element of b.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(this __vtype__ a, __vtype__ b)\n        {\n            return (/*# fields.ForEach(f => { */a.__f____bop__b.__f__/*# }, andand); */);\n        }\n\n        /// <summary>\n        /// Returns whether ALL elements of v are __opName__ s.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(this __vtype__ v, __ftype__ s)\n        {\n            return (/*# fields.ForEach(f => { */v.__f____bop__s/*# }, andand); */);\n        }\n\n        /// <summary>\n        /// Returns whether a is __opName__ ALL elements of v.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool All__opName__(__ftype__ s, __vtype__ v)\n        {\n            return (/*# fields.ForEach(f => { */s__bop__v.__f__/*# }, andand); */);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of a is __opName__ the corresponding element of b.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(this __vtype__ a, __vtype__ b)\n        {\n            return (/*# fields.ForEach(f => { */a.__f____bop__b.__f__/*# }, oror); */);\n        }\n\n        /// <summary>\n        /// Returns whether AT LEAST ONE element of v is __opName__ s.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(this __vtype__ v, __ftype__ s)\n        {\n            return (/*# fields.ForEach(f => { */v.__f____bop__s/*# }, oror); */);\n        }\n\n        /// <summary>\n        /// Returns whether a is __opName__ AT LEAST ONE element of v.\n        /// __attention__\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool Any__opName__(__ftype__ s, __vtype__ v)\n        {\n            return (/*# fields.ForEach(f => { */s__bop__v.__f__/*# }, oror); */);\n        }\n\n        //# }\n\n        /// <summary>\n        /// Compare x-coordinate before y-coordinate, aso.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static int LexicalCompare(this __vtype__ v0, __vtype__ v1)\n        {\n            //# fields.ForEach(f => {\n            if (v0.__f__ < v1.__f__) return -1;\n            if (v0.__f__ > v1.__f__) return +1;\n            //# });\n            return 0;\n        }\n\n        #endregion\n\n        #region Min- / MaxElement\n\n        /// <summary>\n        /// Returns the minimum element of the given <see cref=\"__vtype__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ MinElement(__vtype__ v)\n            => v.MinElement;\n\n        /// <summary>\n        /// Returns the maximum element of the given <see cref=\"__vtype__\"/> vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ MaxElement(__vtype__ v)\n            => v.MaxElement;\n\n        #endregion\n\n        //# if (d == 3 && ft.IsReal) {\n        #region Axis aligned normal\n\n        /// <summary>\n        /// Returns an arbitrary normal vector, which\n        /// is also normal to either the x, y or z-axis.\n        /// </summary>\n        public static __vtype__ AxisAlignedNormal(this __vtype__ v)\n        {\n            __vtype__ vector;\n            __ftype__ x = v.X.Abs();\n            __ftype__ y = v.Y.Abs();\n            __ftype__ z = v.Z.Abs();\n\n            if (x < y)\n            {\n                if (x < z)\n                    vector = __vtype__.XAxis;\n                else\n                    vector = __vtype__.ZAxis;\n            }\n            else\n            {\n                if (y < z)\n                    vector = __vtype__.YAxis;\n                else\n                    vector = __vtype__.ZAxis;\n            }\n\n            return v.Cross(vector).Normalized;\n        }\n\n        #endregion\n\n        //# }\n        //# if (ft.IsReal) {\n        #region Angle between two vectors\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ AngleBetweenFast(this __vtype__ x, __vtype__ y)\n        {\n            return Fun.AcosClamped(x.Dot(y));\n        }\n\n        /// <summary>\n        /// Computes the angle between two given vectors in radians using a numerically stable algorithm.\n        /// The input vectors have to be normalized.\n        /// </summary>\n        // https://scicomp.stackexchange.com/a/27769\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ AngleBetween(this __vtype__ x, __vtype__ y)\n        {\n            var a = x + y;\n            var b = x - y;\n            return 2 * Fun.Atan2(b.Length, a.Length);\n        }\n\n        //# if (d == 2) {\n        /// <summary>\n        /// Computes the signed angle between two given vectors in radians. The input vectors have to be normalized.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ctype__ AngleBetweenSigned(this __vtype__ x, __vtype__ y)\n        {\n            var a = x.X * y.Y - x.Y * y.X;\n            var b = x.X * y.X + x.Y * y.Y;\n            return Fun.Atan2(a, b);\n        }\n\n        //# }\n        #endregion\n\n        //# }\n        #region AnyTiny, AllTiny\n\n        /// <summary>\n        /// Returns whether the absolute value of any component of the given <see cref=\"__vtype__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AnyTiny(this __vtype__ v, __ftype__ epsilon)\n            => /*# fields.ForEach(f => { */v.__f__.IsTiny(epsilon)/*# }, oror);*/;\n\n        /// <summary>\n        /// Returns whether the absolute value of each component of the given <see cref=\"__vtype__\"/> is smaller than <paramref name=\"epsilon\"/>.\n        /// </summary>\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool AllTiny(this __vtype__ v, __ftype__ epsilon)\n            => /*# fields.ForEach(f => { */v.__f__.IsTiny(epsilon)/*# }, andand);*/;\n\n        #endregion\n\n        //# if (ft.IsReal) {\n        #region Special Floating Point Value Checks\n\n        //# var condArray = new[] { \"Finite\", \"NaN\", \"Infinity\", \"PositiveInfinity\", \"NegativeInfinity\", \"Tiny\" };\n        //# var quantArray = new[] { \"Any\", \"All\" };\n        //# condArray.ForEach(cond => {\n        //# quantArray.ForEach(qant => {\n        [Pure]\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static bool __qant____cond__(__vtype__ v)\n            => v.__qant____cond__;\n\n        //# }); // quantArray\n        //# }); // condArray\n        #endregion\n\n        //# if (d == 2 && !unsigned) {\n        #region 2D Vector Arithmetics\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 90 degrees counterclockwise.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Dot90(this __vtype__ v, __vtype__ dir)\n        {\n            return v.Y * dir.X - v.X * dir.Y;\n        }\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 180 degrees.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Dot180(this __vtype__ v, __vtype__ dir)\n        {\n            return -(v.X * dir.X + v.Y * dir.Y);\n        }\n\n        /// <summary>\n        /// Dot product of vector with dir rotated by 270 degrees counterclockwise.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ Dot270(this __vtype__ v, __vtype__ dir)\n        {\n            return v.X * dir.Y - v.Y * dir.X;\n        }\n\n        /// <summary>\n        /// Returns the left value of the direction v with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ DirLeftOfLineValue(this __vtype__ v, __vtype__ p0, __vtype__ p1)\n        {\n            return v.X * (p0.Y - p1.Y) + v.Y * (p1.X - p0.X);\n        }\n\n        /// <summary>\n        /// Returns the right value of the direction v with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ DirRightOfLineValue(this __vtype__ v, __vtype__ p0, __vtype__ p1)\n        {\n            return v.X * (p1.Y - p0.Y) + v.Y * (p0.X - p1.X);\n        }\n\n        /// <summary>\n        /// Returns the left value of the point p with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ PosLeftOfLineValue(this __vtype__ p, __vtype__ p0, __vtype__ p1)\n        {\n            return (p.X - p0.X) * (p0.Y - p1.Y) + (p.Y - p0.Y) * (p1.X - p0.X);\n        }\n\n        /// <summary>\n        /// Returns the right value of the point p with respect to the\n        /// line from p0 to p1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __ftype__ PosRightOfLineValue(this __vtype__ p, __vtype__ p0, __vtype__ p1)\n        {\n            return (p.X - p0.X) * (p1.Y - p0.Y) + (p.Y - p0.Y) * (p0.X - p1.X);\n        }\n\n        #endregion\n\n        //# } // d == 2\n        #region Linear Combination\n\n        //# if (ft.IsReal) {\n        //# for (int tpc = 2; tpc < 8; tpc++ ) {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ LinCom(/*# tpc.ForEach(i => { */__vtype__ p__i__/*# }, comma); */, ref Tup__tpc__<__ftype__> w)\n        {\n            return /*# tpc.ForEach(i => { */p__i__ * w.E__i__/*# }, add); */;\n        }\n\n        //# } // tpc\n        //# } // isreal\n        #endregion\n\n        //# } // ft.IsReal\n        #region ArrayExtensions\n\n        //# foreach (var it in Meta.IndexTypes) { var itype = it.Name;\n        //#     var prefix = it == Meta.LongType ? \"Long\" : \"\";\n        public static __itype__ __prefix__IndexOfClosestPoint(this __vtype__[] pointArray, __vtype__ point)\n        {\n            var bestDist = DistanceSquared(point, pointArray[0]);\n            __itype__ bestIndex = 0;\n            __itype__ count = pointArray.__prefix__Length;\n            for (__itype__ i = 1; i < count; i++)\n            {\n                var dist = DistanceSquared(point, pointArray[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static __itype__ __prefix__IndexOfClosestPoint(\n                this __vtype__[] array, __itype__ start, __itype__ count,\n                __vtype__ point)\n        {\n            var bestDist = DistanceSquared(point, array[start]);\n            __itype__ bestIndex = 0;\n            for (__itype__ i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, array[i]);\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        public static __itype__ __prefix__IndexOfClosestPoint<T>(\n                this T[] array, __itype__ start, __itype__ count,\n                Func<T, __vtype__> pointSelector, __vtype__ point)\n        {\n            var bestDist = DistanceSquared(point, pointSelector(array[start]));\n            __itype__ bestIndex = 0;\n            for (__itype__ i = start + 1, e = start + count; i < e; i++)\n            {\n                var dist = DistanceSquared(point, pointSelector(array[i]));\n                if (dist < bestDist) { bestDist = dist; bestIndex = i; }\n            }\n            return bestIndex;\n        }\n\n        //# } // it\n        //# var opArray = new[] { \" < \", \" > \" };\n        //# var exArray = new[] { \"min\", \"max\" };\n        //# foreach (var isList in new[] { false, true }) {\n        //# fields.ForEach(f => {\n        //# for (int ei = 0; ei < 2; ei++) {\n        //#     var op = opArray[ei]; var ex = exArray[ei]; var fun = ex.Capitalized();\n        //# foreach (var it in Meta.IndexTypes) { var itype = it.Name;\n        //#     if (isList && it == Meta.LongType) continue;\n        //#     var prefix = it == Meta.LongType ? \"Long\" : \"\";\n        //#     var arrayLen = isList ? \"Count\" : prefix + \"Length\";\n        //#     var atype = isList ? \"IList<\" + vtype + \">\" : vtype + \"[]\";\n        //#     var listText = isList ? \"list\" : \"array\";\n        /// <summary>\n        /// Returns the index of the element with the __ex__imal __f__ coordinate\n        /// within the __listText__.\n        /// </summary>\n        public static __itype__ __prefix__IndexOf__fun____f__(this __atype__ vectorArray, __itype__ count = 0)\n        {\n            var __ex__imum = vectorArray[0].__f__;\n            __itype__ __ex__Index = 0;\n            if (count == 0) count = vectorArray.__arrayLen__;\n            for (__itype__ i = 1; i < count; i++)\n            {\n                var p = vectorArray[i].__f__;\n                if (p__op____ex__imum) { __ex__imum = p; __ex__Index = i; }\n            }\n            return __ex__Index;\n        }\n\n        //# } // it\n        //# } // fi\n        //# });\n        //# } // isList\n        /// <summary>\n        /// Returns the array of the index-th coordinate of each vector.\n        /// </summary>\n        public static __ftype__[] CopyCoord(this __vtype__[] self, int index)\n        {\n            switch (index)\n            {\n                //# fields.ForEach((f, i) => {\n                case __i__: return self.Map(v => v.__f__);\n                //# });\n                default: throw new IndexOutOfRangeException();\n            }\n        }\n\n        //# if (ft.IsReal) {\n        public static __vtype__ WeightedSum(\n                this __vtype__[] vectorArray, __ftype__[] weightArray)\n        {\n            var r = __vtype__.Zero;\n            var count = vectorArray.LongLength;\n            for (long i = 0; i < count; i++) r += vectorArray[i] * weightArray[i];\n            return r;\n        }\n\n        //# } // ft.IsReal\n        #endregion\n    }\n\n    public static class IRandomUniform__vtype__Extensions\n    {\n        #region IRandomUniform extensions for __vtype__\n\n        //# string[] variants;\n        //# if (ft == Meta.FloatType) {\n        //#     variants = new string[] { \"\", \"Closed\", \"Open\" };\n        //# } else if (ft == Meta.DoubleType) {\n        //#     variants = new string[] { \"\", \"Closed\", \"Open\", \"Full\", \"FullClosed\", \"FullOpen\" };\n        //# } else if (!unsigned) {\n        //#     variants = new string[] { \"\", \"NonZero\" };\n        //# } else {\n        //#     variants = new string[] { \"\" };\n        //# }\n        //# foreach (var v in variants) {\n        /// <summary>\n        /// Uses Uniform__fcaps____v__() to generate the elements of a __vtype__ vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Uniform__vtype____v__(this IRandomUniform rnd)\n        {\n            return new __vtype__(/*# fields.ForEach(f => { */rnd.Uniform__fcaps____v__()/*#  }, comma); */);\n        }\n\n        //# if (ft.IsReal && d < 4) {\n        /// <summary>\n        /// Uses Uniform__fcaps____v__() to generate the elements of a __vtype__\n        /// vector within the given Box__d____fchar__.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Uniform__vtype____v__(this IRandomUniform rnd, Box__d____fchar__ box)\n        {\n            return new __vtype__(/*# fields.ForEach(f => { */box.Min.__f__ + rnd.Uniform__fcaps____v__() * (box.Max.__f__ - box.Min.__f__)/*#  }, comma); */);\n        }\n\n        //# }\n        //# }\n        //# if (ft.IsReal) {\n        //# var constant = (ft != Meta.DoubleType) ? \"ConstantF\" : \"Constant\";\n        //# variants = (ft == Meta.FloatType) ? new string[] { \"\" } : new string[] { \"\", \"Full\" };\n        //# foreach (var v in variants) {\n        //# if (d == 2) {\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the unit circle). Uses Uniform__fcaps____v__() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Uniform__vtype____v__Direction(this IRandomUniform rnd)\n        {\n            __ftype__ phi = rnd.Uniform__fcaps____v__() * __constant__.PiTimesTwo;\n            return new __vtype__(Fun.Cos(phi), Fun.Sin(phi));\n        }\n\n        //# } else if (d == 3) {\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the surface of the unit sphere).\n        /// Note however, that the returned vector will never be equal to\n        /// [0, 0, -1]. Uses Uniform__fcaps____v__() internally.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Uniform__vtype____v__Direction(this IRandomUniform rnd)\n        {\n            __ftype__ phi = rnd.Uniform__fcaps____v__() * __constant__.PiTimesTwo;\n            __ftype__ z = 1 - rnd.Uniform__fcaps____v__() * 2;\n            __ftype__ s = Fun.Sqrt(1 - z * z);\n            return new __vtype__(Fun.Cos(phi) * s, Fun.Sin(phi) * s, z);\n        }\n\n        //# var sphereVariants = new string[] { \"Closed\", \"Open\" };\n        //# foreach (var sv in sphereVariants) {\n        //# if (sv == \"Closed\") {\n        /// <summary>\n        /// Uniform vector in the closed unit sphere (i.e vectors to\n        /// the surface of the sphere may be generated). Uses Uniform__vtype____sv__() internally.\n        /// </summary>\n        //# } else {\n        /// <summary>\n        /// Uniform vector inside the open unit sphere (i.e. no vector\n        /// ends on the surface of the sphere). Uses Uniform__vtype____sv__() internally.\n        /// </summary>\n        //# }\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Uniform__vtype____v____sv__Sphere(this IRandomUniform rnd)\n        {\n            __ftype__ r2;\n            __vtype__ p;\n            __vtype__ c_shift = -__vtype__.Half;\n            do\n            {\n                p = (rnd.Uniform__vtype____sv__() + c_shift) * 2;\n                r2 = p.LengthSquared;\n            }\n            while (r2 >= 1);\n            return p;\n        }\n\n        //# }\n        //# } //d\n        //# }\n        //# } else if (!unsigned) { //ft.Real\n        /// <summary>\n        /// Uses Uniform__fcaps__(__ftype__) to generate the elements of a __vtype__ vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Uniform__vtype__(this IRandomUniform rnd, __ftype__ size)\n        {\n            return new __vtype__(/*# fields.ForEach(f => { */rnd.Uniform__fcaps__(size)/*#  }, comma); */);\n        }\n\n        /// <summary>\n        /// Uses Uniform__fcaps__(__ftype__) to generate the elements of a __vtype__ vector.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static __vtype__ Uniform__vtype__(this IRandomUniform rnd, __vtype__ size)\n        {\n            return new __vtype__(/*# fields.ForEach(f => { */rnd.Uniform__fcaps__(size.__f__)/*#  }, comma); */);\n        }\n\n        //# }\n        #endregion\n    }\n\n    #endregion\n\n    //# } // vt\n}"
  },
  {
    "path": "src/Aardvark.Base/Random/ForcedRandomSeries.cs",
    "content": "﻿using System.IO;\nusing System.Runtime.InteropServices;\nusing System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Provides an IRandomSeries view of a pre-computed 2d random sequence.\n    /// </summary>\n    public class ForcedRandomSeries : IRandomSeries\n    {\n        V2i m_index = V2i.OO;\n        readonly V2i[] m_series;\n        readonly int m_matrixSize;\n        readonly double m_norm;\n        readonly IRandomUniform m_rnd;\n        V2i m_seed;\n        readonly bool m_jitter;\n\n        /// <summary>\n        /// Reads a file that contains a raw V2i binary array as V2i[].\n        /// The binary data is supposed to contain NxN points as (int, int) in random order.\n        /// </summary>\n        public static V2i[] ReadSeries(string frsSqFile)\n        {\n            var bytes = File.ReadAllBytes(frsSqFile);\n            var matrixSize = (int)(bytes.Length / 8).Sqrt();\n\n            // V2i[] encoded in byte array must be NxN and a multiple of 8.\n            if (matrixSize * matrixSize * 8 != bytes.Length)\n                throw new InvalidDataException(\"Forced Random series data has invalid length.\");\n\n            var dst = new V2i[bytes.Length / 8];\n            bytes.AsSpan().CopyTo(MemoryMarshal.AsBytes(dst.AsSpan()));\n            return dst;\n        }\n\n        /// <summary>\n        /// Create a ForcedRandomSeries with the given sample sequence and the seed as offset.\n        /// The sequence is supposed to contain NxN points in random order.\n        /// </summary>\n        public ForcedRandomSeries(V2i[] series, int matrixSize, IRandomUniform rnd, bool jitter = true)\n        {\n            m_series = series;\n            m_matrixSize = matrixSize;\n            m_norm = 1.0 / m_matrixSize; // [0, 1) \n            m_rnd = rnd;\n            m_jitter = jitter;\n            // random offset of sample pattern\n            m_seed = new V2i(rnd.UniformInt(m_matrixSize), rnd.UniformInt(m_matrixSize)); \n        }\n\n        /// <summary>\n        /// Create a ForcedRandomSeries with the given sample sequence and the seed as offset.\n        /// The sequence is supposed to contain NxN points in random order.\n        /// </summary>\n        public ForcedRandomSeries(V2i[] series, IRandomUniform rnd, bool jitter = true)\n            : this(series, (int)series.Length.Sqrt(), rnd, jitter)\n        {\n        }\n\n        /// <summary>\n        /// Create a ForcedRandomSeries from the given sequence data file\n        /// and a random generator that is used to generate a seed.\n        /// </summary>\n        public ForcedRandomSeries(string frsSqFile, IRandomUniform rndSeed, bool jitter = true)\n            : this(ReadSeries(frsSqFile), rndSeed, jitter)\n        {\n        }\n\n        public double UniformDouble(int seriesIndex)\n        {\n            var ind = m_index[seriesIndex]++;\n            var rnd = m_series[ind++ % m_series.Length][seriesIndex];\n            rnd += m_seed[seriesIndex]; // shift complete pattern by seed\n            return ((rnd + (m_jitter ? m_rnd.UniformDouble() : 0.0)) * m_norm).Frac(); // optionally add sub-pixel jittering\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/HaltonRandomSeries.cs",
    "content": "namespace Aardvark.Base\n{\n    /// <summary>\n    /// A halton series generator, that uses a normal random generator for\n    /// higher order series, in order to avoid the slow coverage of higher\n    /// order halton series.\n    /// </summary>\n    public class HaltonRandomSeries : IRandomSeries\n    {\n\t    public HaltonRandomSeries(\n\t            int haltonCount, IRandomUniform randomUniform)\n        {\n            m_haltonStateArray = new double[haltonCount].SetByIndex(\n                                        i => randomUniform.UniformDouble());\n            m_randomUniform = randomUniform;\n        }\n\n\t    public double UniformDouble(int seriesIndex)\n        {\n            if (seriesIndex < m_haltonStateArray.Length)\n\t        {\n                double value = Quasi.QuasiHaltonWithIndex(\n                                seriesIndex, m_haltonStateArray[seriesIndex]);\n\t            m_haltonStateArray[seriesIndex] = value;\n\t            return value;\n\t        }\n\t        else\n                return m_randomUniform.UniformDouble();\n        }\n\n\t    private readonly double [] m_haltonStateArray;\n        private readonly IRandomUniform m_randomUniform;\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/IRandomDistribution.cs",
    "content": "namespace Aardvark.Base\n{\n    public interface IRandomDistribution\n    {\n        /// <summary>\n        /// Returns a distributed double.\n        /// </summary>\n        double GetDouble();\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/IRandomSeries.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// Maintain multiple independent series of random or quasi-random\n    /// variables. For two-dimensional sampling the random variables of two\n    /// series need to be combined (e.g. a random variable of series k and\n    /// a random variable of series k+1). For quasi-random sampling, the\n    /// lower series are assumed to achieve a faster coverage of the domain,\n    /// and should therefore be used for the sampling dimensions with a \n    /// larger influence on the result.\n    /// </summary>\n    public interface IRandomSeries\n    {\n        double UniformDouble(int seriesIndex);\n    }\n\n    public static class RandomSeriesExtensions\n    {\n        /// <summary>\n        /// Returns a uniformly distributed vector (corresponds to a\n        /// uniformly distributed point on the unit sphere) by using\n        /// 2 random values from the series with the supplied indices.\n        /// Note, that the returned vector will never be equal to [0, 0, -1].\n        /// </summary>\n        public static V3d UniformV3dDirection(this IRandomSeries rnd, int si0, int si1)\n        {\n            double phi = rnd.UniformDouble(si0) * Constant.PiTimesTwo;\n            double z = 1.0 - rnd.UniformDouble(si1) * 2.0;\n            double s = System.Math.Sqrt(1.0 - z * z);\n            return new V3d(System.Math.Cos(phi) * s, System.Math.Sin(phi) * s, z);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/IRandomUniform.cs",
    "content": "using Aardvark.Base.Sorting;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// This interface enforces a common API for random number generators.\n    /// </summary>\n    public interface IRandomUniform\n    {\n        #region Info and Seeding\n\n        /// <summary>\n        /// Returns the number of random bits that the generator\n        /// delivers. This many bits are actually random in the \n        /// doubles returned by <see cref=\"UniformDouble()\"/>.\n        /// </summary>\n        int RandomBits { get; }\n\n        /// <summary>\n        /// Returns true if the doubles generated by this random\n        /// generator contain 52 random mantissa bits.\n        /// </summary>\n        bool GeneratesFullDoubles { get; }\n\n        /// <summary>\n        /// Reinitializes the random generator with the specified seed.\n        /// </summary>\n        void ReSeed(int seed);\n\n        #endregion\n\n        #region Random Integers\n\n        /// <summary>\n        /// Returns a uniformly distributed integer in the interval\n        /// [0, 2^31-1].\n        /// </summary>\n        int UniformInt();\n\n        /// <summary>\n        /// Returns a uniformly distributed integer in the interval\n        /// [0, 2^32-1].\n        /// </summary>\n        uint UniformUInt();\n\n        /// <summary>\n        /// Returns a uniformly distributed integer in the interval\n        /// [0, 2^63-1].\n        /// </summary>\n        long UniformLong();\n\n        /// <summary>\n        /// Returns a uniformly distributed integer in the interval\n        /// [0, 2^64-1].\n        /// </summary>\n        ulong UniformULong();\n\n        #endregion\n\n        #region Random Floating Point Values\n\n        /// <summary>\n        /// Returns a uniformly distributed float in the half-open interval\n        /// [0.0f, 1.0f).\n        /// </summary>\n        float UniformFloat();\n\n        /// <summary>\n        /// Returns a uniformly distributed float in the closed interval\n        /// [0.0f, 1.0f].\n        /// </summary>\n        float UniformFloatClosed();\n\n        /// <summary>\n        /// Returns a uniformly distributed float in the open interval\n        /// (0.0f, 1.0f).\n        /// </summary>\n        float UniformFloatOpen();\n\n        /// <summary>\n        /// Returns a uniformly distributed double in the half-open interval\n        /// [0.0, 1.0). Note, that only RandomBits bits are guaranteed to be\n        /// random.\n        /// </summary>\n        double UniformDouble();\n\n        /// <summary>\n        /// Returns a uniformly distributed double in the closed interval\n        /// [0.0, 1.0]. Note, that only RandomBits bits are guaranteed to be\n        /// random.\n        /// </summary>\n        double UniformDoubleClosed();\n\n        /// <summary>\n        /// Returns a uniformly distributed double in the open interval\n        /// (0.0, 1.0). Note, that only RandomBits bits are guaranteed to be\n        /// random.\n        /// </summary>\n        double UniformDoubleOpen();\n\n        #endregion\n    }\n\n    public static class IRandomUniformExtensions\n    {\n        #region Random Bits\n\n        /// <summary>\n        /// Supply random bits one at a time. The currently unused bits are\n        /// maintained in the supplied reference parameter. Before the first\n        /// call randomBits must be 0.\n        /// </summary>\n        public static bool RandomBit(\n               this IRandomUniform rnd, ref int randomBits)\n        {\n            if (randomBits <= 1)\n            {\n                randomBits = rnd.UniformInt();\n                bool bit = (randomBits & 1) != 0;\n                randomBits = 0x40000000 | (randomBits >> 1);\n                return bit;\n            }\n            else\n            {\n                bool bit = (randomBits & 1) != 0;\n                randomBits >>= 1;\n                return bit;\n            }\n        }\n\n        #endregion\n\n        #region Random Integers\n\n        /// <summary>\n        /// Returns a uniformly distributed int in the interval [0, count-1].\n        /// In order to avoid excessive aliasing, two random numbers are used\n        /// when count is greater or equal 2^24 and the random generator\n        /// delivers 32 random bits or less. The method thus works fairly\n        /// decently for all integers.\n        /// </summary>\n        public static int UniformInt(this IRandomUniform rnd, int size)\n        {\n            if (rnd.GeneratesFullDoubles || size < 16777216)\n                return (int)(rnd.UniformDouble() * size);\n            else\n                return (int)(rnd.UniformDoubleFull() * size);\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed long in the interval [0, size-1].\n        /// NOTE: If count has more than about 48 bits, aliasing leads to \n        /// noticeable (greater 5%) shifts in the probabilities (i.e. one\n        /// long has a probability of x and the other a probability of\n        /// x * (2^(52-b)-1)/(2^(52-b)), where b is log(size)/log(2)).\n        /// </summary>\n        public static long UniformLong(this IRandomUniform rnd, long size)\n        {\n            if (rnd.GeneratesFullDoubles || size < 16777216)\n                return (long)(rnd.UniformDouble() * size);\n            else\n                return (long)(rnd.UniformDoubleFull() * size);\n        }\n\n        /// <summary>\n        /// Returns a uniform int which is guaranteed not to be zero.\n        /// </summary>\n        public static int UniformIntNonZero(this IRandomUniform rnd)\n        {\n            int r;\n            do { r = rnd.UniformInt(); } while (r == 0);\n            return r;\n        }\n\n        /// <summary>\n        /// Returns a uniform long which is guaranteed not to be zero.\n        /// </summary>\n        public static long UniformLongNonZero(this IRandomUniform rnd)\n        {\n            long r;\n            do { r = rnd.UniformLong(); } while (r == 0);\n            return r;\n        }\n\n        #endregion\n\n        #region Random Floating Point Values\n\n        /// <summary>\n        /// Returns a uniformly distributed double in the half-open interval\n        /// [0.0, 1.0). Note, that two random values are used to make all 53\n        /// bits random. If you use this repeatedly, consider using a 64-bit\n        /// random generator, which can  provide such doubles directly using\n        /// UniformDouble().\n        /// </summary>\n        public static double UniformDoubleFull(this IRandomUniform rnd)\n        {\n            if (rnd.GeneratesFullDoubles) return rnd.UniformDouble();\n            long r = ((~0xfL & (long)rnd.UniformInt()) << 22)\n                      | ((long)rnd.UniformInt() >> 5);\n            return r * (1.0 / 9007199254740992.0);\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed double in the closed interval\n        /// [0.0, 1.0]. Note, that two random values are used to make all 53\n        /// bits random.\n        /// </summary>\n        public static double UniformDoubleFullClosed(this IRandomUniform rnd)\n        {\n            if (rnd.GeneratesFullDoubles) return rnd.UniformDoubleClosed();\n            long r = ((~0xfL & (long)rnd.UniformInt()) << 22)\n                      | ((long)rnd.UniformInt() >> 5);\n            return r * (1.0 / 9007199254740991.0);\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed double in the open interval\n        /// (0.0, 1.0). Note, that two random values are used to make all 53\n        /// bits random.\n        /// </summary>\n        public static double UniformDoubleFullOpen(this IRandomUniform rnd)\n        {\n            if (rnd.GeneratesFullDoubles) return rnd.UniformDoubleOpen();\n            long r;\n            do\n            {\n                r = ((~0xfL & (long)rnd.UniformInt()) << 22)\n                    | ((long)rnd.UniformInt() >> 5);\n            }\n            while (r == 0);\n            return r * (1.0 / 9007199254740992.0);\n        }\n\n        #endregion\n\n        #region Creating Randomly Filled Arrays\n\n        /// <summary>\n        /// Create a random array of ints in the interval\n        /// [0, 2^31-1] of the specified length.\n        /// </summary>\n        public static int[] CreateUniformIntArray(\n                this IRandomUniform rnd, long length)\n        {\n            var array = new int[length];\n            rnd.FillUniform(array);\n            return array;\n        }\n\n        /// <summary>\n        /// Create a random array of longs in the interval\n        /// [0, 2^63-1] of the specified length.\n        /// </summary>\n        public static long[] CreateUniformLongArray(\n                this IRandomUniform rnd, long length)\n        {\n            var array = new long[length];\n            rnd.FillUniform(array);\n            return array;\n        }\n\n        /// <summary>\n        /// Create a random array of floats in the half-open interval\n        /// [0.0, 1.0) of the specified length.\n        /// </summary>\n        public static float[] CreateUniformFloatArray(\n                this IRandomUniform rnd, long length)\n        {\n            var array = new float[length];\n            rnd.FillUniform(array);\n            return array;\n        }\n\n        /// <summary>\n        /// Create a random array of doubles in the half-open interval\n        /// [0.0, 1.0) of the specified length.\n        /// </summary>\n        public static double[] CreateUniformDoubleArray(\n                this IRandomUniform rnd, long length)\n        {\n            var array = new double[length];\n            rnd.FillUniform(array);\n            return array;\n        }\n\n        /// <summary>\n        /// Create a random array of full doubles in the half-open interval\n        /// [0.0, 1.0) of the specified length.\n        /// </summary>\n        public static double[] CreateUniformDoubleFullArray(\n            this IRandomUniform rnd, long length)\n        {\n            var array = new double[length];\n            rnd.FillUniformFull(array);\n            return array;\n        }\n\n        /// <summary>\n        /// Fills the specified array with random ints in the interval\n        /// [0, 2^31-1].\n        /// </summary>\n        public static void FillUniform(this IRandomUniform rnd, int[] array)\n        {\n            long count = array.LongLength;\n            for (long i = 0; i < count; i++)\n                array[i] = rnd.UniformInt();\n        }\n\n        /// <summary>\n        /// Fills the specified array with random longs in the interval\n        /// [0, 2^63-1].\n        /// </summary>\n        public static void FillUniform(this IRandomUniform rnd, long[] array)\n        {\n            long count = array.LongLength;\n            for (long i = 0; i < count; i++)\n                array[i] = rnd.UniformLong();\n        }\n\n        /// <summary>\n        /// Fills the specified array with random floats in the half-open\n        /// interval [0.0f, 1.0f).\n        /// </summary>\n        public static void FillUniform(this IRandomUniform rnd, float[] array)\n        {\n            long count = array.LongLength;\n            for (long i = 0; i < count; i++)\n                array[i] = rnd.UniformFloat();\n        }\n\n        /// <summary>\n        /// Fills the specified array with random doubles in the half-open\n        /// interval [0.0, 1.0).\n        /// </summary>\n        public static void FillUniform(\n                this IRandomUniform rnd, double[] array)\n        {\n            long count = array.LongLength;\n            for (long i = 0; i < count; i++)\n                array[i] = rnd.UniformDouble();\n        }\n\n        /// <summary>\n        /// Fills the specified array with fully random doubles (53 random\n        /// bits) in the half-open interval [0.0, 1.0).\n        /// </summary>\n        public static void FillUniformFull(\n                this IRandomUniform rnd, double[] array)\n        {\n            long count = array.LongLength;\n            if (rnd.GeneratesFullDoubles)\n            {\n                for (long i = 0; i < count; i++)\n                    array[i] = rnd.UniformDoubleFull();\n            }\n            else\n            {\n                for (long i = 0; i < count; i++)\n                    array[i] = rnd.UniformDouble();\n            }\n        }\n\n        /// <summary>\n        /// Creates an array that contains a random permutation of the\n        /// ints in the interval [0, count-1].\n        /// </summary>\n        public static int[] CreatePermutationArray(\n                this IRandomUniform rnd, int count)\n        {\n            var p = new int[count].SetByIndex(i => i);\n            rnd.Randomize(p);\n            return p;\n        }\n\n        /// <summary>\n        /// Creates an array that contains a random permutation of the\n        /// numbers in the interval [0, count-1].\n        /// </summary>\n        public static long[] CreatePermutationArrayLong(\n                this IRandomUniform rnd, long count)\n        {\n            var p = new long[count].SetByIndexLong(i => i);\n            rnd.Randomize(p);\n            return p;\n        }\n\n        #endregion\n\n        #region Creationg a Random Subset (while maintaing order)\n\n        /// <summary>\n        /// Returns a random subset of an array with a supplied number of\n        /// elements (subsetCount). The elements in the subset are in the\n        /// same order as in the original array. O(count).\n        /// NOTE: this method needs to generate one random number for each\n        /// element of the original array. If subsetCount is significantly\n        /// smaller than count, it is more efficient to use\n        /// <see cref=\"CreateSmallRandomSubsetIndexArray\"/> or\n        /// <see cref=\"CreateSmallRandomSubsetIndexArrayLong\"/> or\n        /// <see cref=\"CreateSmallRandomOrderedSubsetIndexArray\"/> or\n        /// <see cref=\"CreateSmallRandomOrderedSubsetIndexArrayLong\"/>.\n        /// </summary>\n        public static T[] CreateRandomSubsetOfSize<T>(\n                this T[] array, long subsetCount, IRandomUniform rnd = null)\n        {\n            if (rnd == null) rnd = new RandomSystem();\n            long count = array.LongLength;\n            if (!(subsetCount >= 0 && subsetCount <= count)) throw new ArgumentOutOfRangeException(nameof(subsetCount));\n            var subset = new T[subsetCount];\n            long si = 0;\n            for (int ai = 0; ai < count && si < subsetCount; ai++)\n            {\n                var p = (double)(subsetCount - si) / (double)(count - ai);\n                if (rnd.UniformDouble() <= p) subset[si++] = array[ai];\n            }\n            return subset;\n        }\n\n        /// <summary>\n        /// Returns a random subset of the enumeration with a supplied number of\n        /// elements (subsetCount). The elements in the subset are in the\n        /// same order as in the input. O(count).\n        /// NOTE: The number of elements of the Enumerable need to be calculated, in case of true enumerations\n        ///       the implementation of .Count() results in a second evaluation of the enumerable.\n        /// </summary>\n        public static T[] CreateRandomSubsetOfSize<T>(\n                this IEnumerable<T> input, long subsetCount, IRandomUniform rnd = null)\n        {\n            if (rnd == null) rnd = new RandomSystem();\n            long count = input.Count();\n            if (!(subsetCount >= 0 && subsetCount <= count)) throw new ArgumentOutOfRangeException(nameof(subsetCount));\n            var subset = new T[subsetCount];\n            long si = 0, ai = 0;\n            foreach (var a in input)\n            {\n                if (ai < count && si < subsetCount)\n                {\n                    var p = (double)(subsetCount - si) / (double)(count - ai++);\n                    if (rnd.UniformDouble() <= p) subset[si++] = a;\n                }\n                else\n                    break;\n            }\n            return subset;\n        }\n\n        /// <summary>\n        /// Creates an unordered array of subsetCount long indices that\n        /// constitute a subset of all longs in the range  [0, count-1].\n        /// O(subsetCount) for subsetCount &lt;&lt; count.\n        /// NOTE: It is assumed that subsetCount is significantly smaller\n        /// than count. If this is not the case, use\n        /// CreateRandomSubsetOfSize instead.\n        /// WARNING: As subsetCount approaches count execution time\n        /// increases significantly.\n        /// </summary>\n        public static long[] CreateSmallRandomSubsetIndexArrayLong(\n                this IRandomUniform rnd, long subsetCount, long count)\n        {\n            if (!(subsetCount >= 0 && subsetCount <= count)) throw new ArgumentOutOfRangeException(nameof(subsetCount));\n            var subsetIndices = new LongSet(subsetCount);\n            for (int i = 0; i < subsetCount; i++)\n            {\n                long index;\n                do { index = rnd.UniformLong(count); }\n                while (!subsetIndices.TryAdd(index));\n            }\n            return subsetIndices.ToArray();\n        }\n\n        /// <summary>\n        /// Creates an ordered array of subsetCount long indices that\n        /// constitute a subset of all longs in the range [0, count-1].\n        /// O(subsetCount * log(subsetCount)) for subsetCount &lt;&lt; count.\n        /// NOTE: It is assumed that subsetCount is significantly smaller\n        /// than count. If this is not the case, use\n        /// CreateRandomSubsetOfSize instead.\n        /// WARNING: As subsetCount approaches count execution time\n        /// increases significantly.\n        /// </summary>\n        public static long[] CreateSmallRandomOrderedSubsetIndexArrayLong(\n                this IRandomUniform rnd, long subsetCount, long count)\n        {\n            var subsetIndexArray = rnd.CreateSmallRandomSubsetIndexArrayLong(subsetCount, count);\n            subsetIndexArray.QuickSortAscending();\n            return subsetIndexArray;\n        }\n\n        /// <summary>\n        /// Creates an unordered array of subsetCount int indices that\n        /// constitute a subset of all ints in the range [0, count-1].\n        /// O(subsetCount) for subsetCount &lt;&lt; count.\n        /// NOTE: It is assumed that subsetCount is significantly smaller\n        /// than count. If this is not the case, use\n        /// CreateRandomSubsetOfSize instead.\n        /// WARNING: As subsetCount approaches count execution time\n        /// increases significantly.\n        /// </summary>\n        public static int[] CreateSmallRandomSubsetIndexArray(\n                this IRandomUniform rnd, int subsetCount, int count)\n        {\n            if (!(subsetCount >= 0 && subsetCount <= count)) throw new ArgumentOutOfRangeException(nameof(subsetCount));\n            var subsetIndices = new IntSet(subsetCount);\n            for (int i = 0; i < subsetCount; i++)\n            {\n                int index;\n                do { index = rnd.UniformInt(count); }\n                while (!subsetIndices.TryAdd(index));\n            }\n            return subsetIndices.ToArray();\n        }\n\n        /// <summary>\n        /// Creates an ordered array of subsetCount int indices that\n        /// constitute a subset of all ints in the range [0, count-1].\n        /// O(subsetCount * log(subsetCount)) for subsetCount &lt;&lt; count.\n        /// NOTE: It is assumed that subsetCount is significantly smaller\n        /// than count. If this is not the case, use\n        /// CreateRandomSubsetOfSize instead.\n        /// WARNING: As subsetCount approaches count execution time\n        /// increases significantly.\n        /// </summary>\n        public static int[] CreateSmallRandomOrderedSubsetIndexArray(\n                this IRandomUniform rnd, int subsetCount, int count)\n        {\n            var subsetIndexArray = rnd.CreateSmallRandomSubsetIndexArray(subsetCount, count);\n            subsetIndexArray.QuickSortAscending();\n            return subsetIndexArray;\n        }\n\n        #endregion\n\n        #region Randomizing Existing Arrays\n\n        /// <summary>\n        /// Randomly permute the first count elements of the\n        /// supplied array. This does work with counts of up\n        /// to about 2^50. \n        /// </summary>\n        public static void Randomize<T>(\n                this IRandomUniform rnd, T[] array, long count)\n        {\n            if (count <= (long)int.MaxValue)\n            {\n                int intCount = (int)count;\n                for (int i = 0; i < intCount; i++)\n                    array.Swap(i, rnd.UniformInt(intCount));\n            }\n            else\n            {\n                for (long i = 0; i < count; i++)\n                    array.Swap(i, rnd.UniformLong(count));\n            }\n        }\n\n        /// <summary>\n        /// Randomly permute the elements of the supplied array. This does\n        /// work with arrays up to a length of about 2^50. \n        /// </summary>\n        public static void Randomize<T>(\n            this IRandomUniform rnd, T[] array)\n        {\n            rnd.Randomize(array, array.LongLength);\n        }\n\n        /// <summary>\n        /// Randomly permute the elements of the supplied list.\n        /// </summary>\n        public static void Randomize<T>(\n            this IRandomUniform rnd, List<T> list)\n        {\n            int count = list.Count;\n            for (int i = 0; i < count; i++)\n                list.Swap(i, rnd.UniformInt(count));\n        }\n\n        /// <summary>\n        /// Randomly permute the specified number of elements in the supplied\n        /// array starting at the specified index.\n        /// </summary>\n        public static void Randomize<T>(\n            this IRandomUniform rnd, T[] array, int start, int count)\n        {\n            for (int i = start, e = start + count; i < e; i++)\n                array.Swap(i, start + rnd.UniformInt(count));\n        }\n\n        /// <summary>\n        /// Randomly permute the specified number of elements in the supplied\n        /// array starting at the specified index.\n        /// </summary>\n        public static void Randomize<T>(\n            this IRandomUniform rnd, T[] array, long start, long count)\n        {\n            for (long i = start, e = start + count; i < e; i++)\n                array.Swap(i, start + rnd.UniformLong(count));\n        }\n\n        /// <summary>\n        /// Randomly permute the specified number of elements in the supplied\n        /// list starting at the specified index.\n        /// </summary>\n        public static void Randomize<T>(\n            this IRandomUniform rnd, List<T> list, int start, int count)\n        {\n            for (int i = start; i < start + count; i++)\n                list.Swap(i, start + rnd.UniformInt(count));\n        }\n\n        #endregion\n\n        #region Random Distributions\n\n        /// <summary>\n        /// Generates normal distributed random variable with given mean and standard deviation.\n        /// Uses the Box-Muller Transformation to transform two uniform distributed random variables to one normal distributed value.\n        /// NOTE: If multiple normal distributed random values are required, consider using <see cref=\"RandomGaussian\"/>.\n        /// </summary>\n        public static double Gaussian(this IRandomUniform rnd, double mean = 0.0, double stdDev = 1.0)\n        {\n            // Box-Muller Transformation\n            var u1 = 1.0 - rnd.UniformDouble();   // uniform (0,1] -> log requires > 0\n            var u2 = rnd.UniformDouble();         // uniform [0,1)\n            var randStdNormal = Fun.Sqrt(-2.0 * Fun.Log(u1)) *\n                                Fun.Sin(Constant.PiTimesTwo * u2);\n            return mean + stdDev * randStdNormal;\n        }\n\n        #endregion\n    }\n\n    public static class IRandomEnumerableExtensions\n    {\n        #region Random Order\n\n        /// <summary>\n        /// Enumerates elements in random order.\n        /// </summary>\n        public static IEnumerable<T> RandomOrder<T>(this IEnumerable<T> self, IRandomUniform rnd = null)\n        {\n            var tmp = self.ToArray();\n            if (rnd == null) rnd = new RandomSystem();\n            var perm = rnd.CreatePermutationArray(tmp.Length);\n            return perm.Select(index => tmp[index]);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/PerlinNoise.cs",
    "content": "using System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Perlin noise generation class.\n    /// Contains functions for 1D, 2D and 3D perlin noise generation.\n    /// </summary>\n    public class PerlinNoise\n\t{\n\t\tprivate readonly int m_PrimeOne;\n\t\tprivate readonly int m_PrimeTwo;\n\t\tprivate readonly int m_PrimeThree;\n\t\tprivate int m_maxX;\n\t\tprivate int m_maxY;\n\t\t// private int m_maxZ;\n\t\tfloat[] m_lookup;\n\n\t\tprivate readonly Func<float,float,float,float> m_interpolate;\n\n\t\t#region Constructors\n\t\t/// <summary>\n\t\t/// InitialintegerZes a new instance of the <see cref=\"PerlinNoise\"/> class.\n\t\t/// </summary>\n\t\tpublic PerlinNoise()\n\t\t{\n\t\t\tm_PrimeOne   = 15731;\n\t\t\tm_PrimeTwo   = 789221;\n\t\t\tm_PrimeThree = 1376312589;\n\t\t\tm_lookup = null;\n\t\t\tm_maxX = 0;\n\t\t\tm_maxY = 0;\n\t\t\t// m_maxZ = 0;\n\n            m_interpolate = (a, b, x) =>\n            {\n                x = (1 - (x * ConstantF.Pi).Cos()) * 0.5f;\n                return a * (1 - x) + b * x;\n            };\n\t\t}\n\n\t\t#endregion\n\n\t\t/// <summary>\n\t\t/// Generates a pseudo-random number based upon one value(dimension).\n\t\t/// </summary>\n\t\t/// <param name=\"x\">An integer value.</param>\n\t\t/// <returns>A single-precision floating point value between -1 and 1.</returns>\n\t\tpublic float Noise(int x)\n\t\t{\n\t\t\tif (m_lookup != null)\n\t\t\t\treturn m_lookup[x];\n\n\t\t\tx  = (x << 13) ^ x;\n\t\t\tdouble d = (double)((x * (x*x*m_PrimeOne+m_PrimeTwo)+m_PrimeThree) & 0x7fffffff);\n\t\t\treturn ( 1.0f - (float)( d / 1073741824.0 ) );\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Generates a pseudo-random number based upon two value(dimensions).\n\t\t/// </summary>\n\t\t/// <param name=\"x\">An integer value.</param>\n\t\t/// <param name=\"y\">An integer value.</param>\n\t\t/// <returns>A single-precision floating point value between -1 and 1.</returns>\n\t\tpublic float Noise(int x, int y)\n\t\t{\n\t\t\tif (m_lookup != null)\n\t\t\t\treturn m_lookup[x+y*m_maxX];\n\n\t\t\tuint N = (uint)(x+y * 57);\n\t\t\tN = (N << 13) ^ N;\n\t\t\tdouble d = (double)((N * (N * N * m_PrimeOne+m_PrimeTwo )+m_PrimeThree) & 0x7fffffff);\n\t\t\treturn(1.0f - (float)(d / 1073741824.0));\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Generates a pseudo-random number based upon three value(dimensions).\n\t\t/// </summary>\n\t\t/// <param name=\"x\">An integer value.</param>\n\t\t/// <param name=\"y\">An integer value.</param>\n\t\t/// <param name=\"z\">An integer value.</param>\n\t\t/// <returns>A single-precision floating point value between -1 and 1.</returns>\n\t\tpublic float Noise(int x, int y, int z)\n\t\t{\n\t\t\tif (m_lookup != null)\n\t\t\t\treturn m_lookup[x+(z*m_maxY+y) * m_maxX];\n\n\t\t\tint L = (x+y * 57);\n\t\t\tint M = (y+z * 57);\n\t\t\tuint N = (uint)(L+M * 57);\n\t\t\tN = (N << 13) ^ N;\n\t\t\tdouble d = (double)((N * (N * N * m_PrimeOne+m_PrimeTwo )+m_PrimeThree ) & 0x7fffffff);\n\t\t\treturn(1.0f - (float)(d / 1073741824.0));\n\t\t}\n        \n\t\tpublic float SmoothNoise(int x)\n            => (Noise(x)/2.0f)+(Noise(x-1)/4.0f)+(Noise(x+1)/4.0f);\n\n\t\tpublic float SmoothNoise(int x, int y)\n\t\t{\n\t\t\tfloat corners = (Noise(x-1, y-1) + Noise(x+1, y-1) + Noise(x-1, y+1) + Noise(x+1, y+1)) / 16.0f;\n\t\t\tfloat sides   = (Noise(x-1, y  ) + Noise(x+1, y  ) + Noise(x  , y-1) + Noise(x  , y+1)) / 8.0f;\n\t\t\tfloat center  =  Noise(x, y)/4.0f;\n\t\t\treturn(corners+sides+center);\n\t\t}\n\n\t\tpublic float SmoothNoise(int x, int y, int z)\n\t\t{\n\t\t\tfloat corners, sides, center;\n\t\t\tfloat averageZM1, averageZ, averageZP1;\n\n\t\t\t// average of neighbours in z-1\n\t\t\tcorners = (Noise(x-1, y-1, z-1) + Noise(x+1, y-1, z-1) + Noise(x-1, y+1, z-1) + Noise(x+1, y+1, z-1)) / 16.0f;\n\t\t\tsides   = (Noise(x-1, y  , z-1) + Noise(x+1, y  , z-1) + Noise(x  , y-1, z-1) + Noise(x  , y+1, z-1)) / 8.0f;\n\t\t\tcenter  =  Noise(x  , y  , z-1) / 4.0f;\n\t\t\taverageZM1     = corners+sides+center;\n\n\t\t\t// average of neighbours in z\n\t\t\tcorners = (Noise(x-1, y-1, z) + Noise(x+1, y-1, z) + Noise(x-1, y+1, z) + Noise(x+1, y+1, z)) / 16.0f;\n\t\t\tsides   = (Noise(x-1, y  , z) + Noise(x+1, y  , z) + Noise(x  , y-1, z) + Noise(x  , y+1, z)) / 8.0f;\n\t\t\tcenter  =  Noise(x, y, z ) / 4.0f;\n\t\t\taverageZ       = corners+sides+center;\n\n\t\t\t// average of neighbours in z+1\n\t\t\tcorners = (Noise(x-1, y-1, z+1) + Noise(x+1, y-1, z+1) + Noise(x-1, y+1, z+1) + Noise(x+1, y+1, z+1)) / 16.0f;\n\t\t\tsides   = (Noise(x-1, y  , z+1) + Noise(x+1, y  , z+1) + Noise(x  , y-1, z+1) + Noise(x  , y+1, z+1)) / 8.0f;\n\t\t\tcenter  =  Noise(x  , y  , z+1) / 4.0f;\n\t\t\taverageZP1     = corners+sides+center;\n\n\t\t\treturn((averageZM1 / 4.0f)+(averageZ / 2.0f)+(averageZP1 / 4.0f));\n\t\t}\n        \n\t\tpublic float InterpolateNoise(float x)\n\t\t{\n\t\t\tint integerX = (int)x;\n\t\t\tfloat fracX  = x - (float)integerX;\n\n\t\t\tfloat v1 = SmoothNoise(integerX);\n\t\t\tfloat v2 = SmoothNoise(integerX + 1);\n\n\t\t\treturn m_interpolate(v1, v2, fracX);\n\t\t}\n\n\t\tpublic float InterpolateNoise(float x, float y)\n\t\t{\n\t\t\tint integerX = (int)x;\n\t\t\tfloat fracX  = x - (float)integerX;\n\n\t\t\tint integerY = (int)y;\n\t\t\tfloat fracY  = y - (float)integerY;\n\n\t\t\tfloat v1 = SmoothNoise(integerX   , integerY);\n\t\t\tfloat v2 = SmoothNoise(integerX+1 , integerY);\n\t\t\tfloat v3 = SmoothNoise(integerX   , integerY+1);\n\t\t\tfloat v4 = SmoothNoise(integerX+1 , integerY+1);\n\n\t\t\tfloat i1 = m_interpolate(v1, v2, fracX);\n\t\t\tfloat i2 = m_interpolate(v3, v4, fracX);\n\n\t\t\treturn m_interpolate(i1, i2, fracY);\n\n\t\t}\n\n\t\tpublic float InterpolateNoise(float x, float y, float z)\n\t\t{\n\t\t\tint integerX = (int)x;\n\t\t\tfloat fracX  = x - (float)integerX;\n\n\t\t\tint integerY = (int)y;\n\t\t\tfloat fracY  = y - (float)integerY;\n\t\t\t\n\t\t\tint integerZ = (int)z;\n\t\t\tfloat fracZ  = z - (float)integerZ;\t\n\n\t\t\tfloat v1 = SmoothNoise(integerX   , integerY   , integerZ);\n\t\t\tfloat v2 = SmoothNoise(integerX+1 , integerY   , integerZ);\n\t\t\tfloat v3 = SmoothNoise(integerX   , integerY+1 , integerZ);\n\t\t\tfloat v4 = SmoothNoise(integerX+1 , integerY+1 , integerZ);\n\t\t\tfloat v5 = SmoothNoise(integerX   , integerY   , integerZ+1);\n\t\t\tfloat v6 = SmoothNoise(integerX+1 , integerY   , integerZ+1);\n\t\t\tfloat v7 = SmoothNoise(integerX   , integerY+1 , integerZ+1);\n\t\t\tfloat v8 = SmoothNoise(integerX+1 , integerY+1 , integerZ+1);\n\n\t\t\tfloat i1 = m_interpolate(v1, v2, fracX);\n\t\t\tfloat i2 = m_interpolate(v3, v4, fracX);\n\t\t\tfloat i3 = m_interpolate(v5, v6, fracX);\n\t\t\tfloat i4 = m_interpolate(v7, v8, fracX);\n\n\t\t\tfloat i5 = m_interpolate(i1, i2, fracY);\n\t\t\tfloat i6 = m_interpolate(i3, i4, fracY);\n\n\t\t\treturn m_interpolate(i5, i6, fracZ);\n\t\t}\n        \n\t\tpublic float PerlinNoise1F(float x, float amplitude, float frequencyX)\n\t\t{\n\t\t\treturn InterpolateNoise(x*frequencyX) * amplitude;\n\t\t}\n\n\t\tpublic float PerlinNoise2F(float x, float y, float amplitude, float frequencyX, float frequencyY)\n\t\t{\n\t\t\treturn InterpolateNoise(x*frequencyX, y*frequencyY ) * amplitude;\n\t\t}\n\n\t\tpublic float PerlinNoise3F(float x, float y, float z, float amplitude, float frequencyX, float frequencyY, float frequencyZ)\n\t\t{\n\t\t\treturn InterpolateNoise(x*frequencyX, y*frequencyY, z*frequencyZ) * amplitude;\n        }\n        \n        /// <summary>\n        /// Generates the 1d noise and stores it in the lookup table(for faster processing).\n        /// </summary>\n        /// <param name=\"maxX\">max x value (generates noise from 0 to uiMaxX)</param>\n        void GenerateLookup(int maxX)\n\t\t{\n\t\t\tm_maxX = maxX;\n\t\t\tm_lookup = new float[maxX];\n\n\t\t\tfor (int x = 0; x < maxX; x++)\n\t\t\t\tm_lookup[x] = Noise(x);\n        }\n\t\n        /// <summary>\n        /// Generates the 2d noise and stores it in the lookup table (for faster processing).\n        /// </summary>\n        /// <param name=\"maxX\">max x value (generates noise from 0 to uiMaxX)</param>\n        /// <param name=\"maxY\">max y value (generates noise from 0 to uiMaxY)</param>\n        void GenerateLookup(int maxX, int maxY)\n\t\t{\n\t\t\tm_maxX = maxX;\n\t\t\tm_maxY = maxY;\n\t\t\tm_lookup = new float[maxX * maxY];\n\n\t\t\tint offsetY = 0;\n\n\t\t\tfor (int y = 0; y < maxY; y++)\n\t\t\t{\n\t\t\t\tfor (int x = 0; x < maxX; x++)\n\t\t\t\t\tm_lookup[x + offsetY] = Noise(x,y);\n\n\t\t\t\toffsetY += maxX;\n\t\t\t}\n\t\t}\n\n        /// <summary>\n        /// Generates the 3d noise and stores it in the lookup table (for faster processing).\n        /// </summary>\n        /// <param name=\"maxX\">max x value (generates noise from 0 to uiMaxX)</param>\n        /// <param name=\"maxY\">max y value (generates noise from 0 to uiMaxY)</param>\n        /// <param name=\"maxZ\">max z value (generates noise from 0 to uiMaxZ)</param>\n        void GenerateLookup(int maxX, int maxY, int maxZ)\n\t\t{\n\t\t\tm_maxX = maxX;\n\t\t\tm_maxY = maxY;\n\t\t\t// m_maxZ = maxZ;\n\t\t\tm_lookup = new float[maxX * maxY * maxZ];\n\n\t\t\tint offsetY = 0;\n\t\t\tint offsetZ = 0;\n\t\t\tint stepZ = maxX * maxY;\n\n\t\t\tfor (int z = 0; z < maxZ; z++)\n\t\t\t{\n\t\t\t\tfor (int y = 0; y < maxY; y++)\n\t\t\t\t{\n\t\t\t\t\tfor (int x = 0; x < maxX; x++)\n\t\t\t\t\t\tm_lookup[x + offsetY + offsetZ] = Noise(x,y,z);\n\n\t\t\t\t\toffsetY += maxX;\n\t\t\t\t}\n\n\t\t\t\toffsetY = 0;\n\t\t\t\toffsetZ += stepZ;\n\t\t\t}\n\t\t}\n\t}\n\n    public static class ImprovedNoise\n    {\n        public static double Noise(double x, double y, double z)\n        {\n            int xc = (int)Fun.Floor(x) & 0xff,          // Find unit cube that\n                yc = (int)Fun.Floor(y) & 0xff,          // contains point.\n                zc = (int)Fun.Floor(z) & 0xff;\n            x -= Fun.Floor(x);                          // Find relative x,y,z\n            y -= Fun.Floor(y);                          // of point in cube.\n            z -= Fun.Floor(z);\n            double u = Fade(x), v = Fade(y), w = Fade(z);\n                    \n            int a = p[xc  ]+yc, aa = p[a]+zc, ab = p[a+1]+zc, // hash of cube \n                b = p[xc+1]+yc, ba = p[b]+zc, bb = p[b+1]+zc; // corners\n\n            return Lerp(w, Lerp(v, Lerp(u, Grad(p[aa  ], x  , y  , z  ),\n                                           Grad(p[ba  ], x-1, y  , z  )),\n                                   Lerp(u, Grad(p[ab  ], x  , y-1, z  ),\n                                           Grad(p[bb  ], x-1, y-1, z  ))),\n                           Lerp(v, Lerp(u, Grad(p[aa+1], x  , y  , z-1),\n                                           Grad(p[ba+1], x-1, y  , z-1)),\n                                   Lerp(u, Grad(p[ab+1], x  , y-1, z-1),\n                                           Grad(p[bb+1], x-1, y-1, z-1))));\n        }\n\n        static double Fade(double t) => t * t * t * (t * (t * 6 - 15) + 10);\n\n        static double Lerp(double t, double a, double b) => a + t * (b - a);\n\n        static double Grad(int hash, double x, double y, double z)\n        {\n            int h = hash & 0xf;             // Convert lo 4 bits of hash code\n            double  u = h < 8 ? x : y,      // into 12 gradient directions.\n                    v = h < 4 ? y : h == 12 || h == 14 ? x : z;\n            return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);\n        }\n\n        static readonly int[] permutation = {\n            151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,\n            30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75, 0,26,197,\n            62,94,252,219,203,117,35, 11,32,57,177,33,88,237,149,56,87,174,20,\n            125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,\n            83,111,229,122,60,211,133,230,220,105,92, 41,55,46,245,40,244,102,\n            143,54,65,25,63,161, 1,216,80,73,209,76,132,187,208,89,18,169,200,\n            196,135,130,116,188,159, 86,164,100,109,198,173,186, 3,64, 52,217,\n            226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,\n            47, 16,58,17,182,189, 28,42,223,183,170,213,119,248,152, 2,44,154,\n            163,70,221,153,101,155,167,43,172, 9,129, 22,39,253,19,98,108,110,\n            79,113,224,232,178,185,112,104,218,246,97,228,251, 34,242,193,238,\n            210,144, 12,191,179,162,241,81,51,145,235,249, 14,239,107, 49,192,\n            214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,\n            138,236,205,93,222,114,67,29, 24,72,243,141,128,195,78, 66,215,61,\n            156,180\n        };\n\n        static readonly int[] p;\n\n        static ImprovedNoise()\n        {\n            p = new int[512];\n            for (int i = 0; i < 256 ; i++) p[256+i] = p[i] = permutation[i];\n        }\n    }\n}\n\n"
  },
  {
    "path": "src/Aardvark.Base/Random/Prime.cs",
    "content": "using System;\n\nnamespace Aardvark.Base\n{\n    public static class Prime\n    {\n        const int c_initialPrimeCount = 64;\n        const int c_maxPrimeCount = 1 << 24;\n\n        public static bool IsTrueFor(long value)\n        {\n            if (value < 0) return false;\n            if (value < isPrimeArray.Length) return isPrimeArray[value];\n\n            int root = (int)Fun.Sqrt(value);\n            int directMaxPrime = Fun.Min(primeArray[primeCount - 1], root);\n            int pi;\n            for (pi = 0; primeArray[pi] <= directMaxPrime; pi++)\n                if (value % primeArray[pi] == 0) return false;\n\n            if (directMaxPrime == root) return true;\n\n            while (true)\n            {\n                int p = Prime.WithIndex(pi);\n                if (p > root) break;\n                if (value % p == 0) return false;\n                pi++;\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Returns the prime number with the supplied index. Indices start at\n        /// zero and the first prime number is 2. Thus\n        /// 'Prime.WithIndex(0) == 2'.\n        /// </summary>\n        public static int WithIndex(int primeIndex)\n        {\n            if (primeIndex >= primeCount) CalculateUpToIndex(primeIndex);\n            return primeArray[primeIndex];\n        }\n\n        /// <summary>\n        /// Returns the inverse of the prime number with the supplied index.\n        /// Indices start at zero and the first prime number is 2. Thus\n        /// 'Prime.InverseWithIndex(0) == 0.5'.\n        /// </summary>\n        public static double InverseWithIndex(int primeIndex)\n        {\n            if (primeIndex >= primeCount) CalculateUpToIndex(primeIndex);\n            return primeInverseArray[primeIndex];\n        }\n\n        /// <summary>\n        /// The number of primes that have already been calculated.\n        /// </summary>\n        private static int primeCount;\n\n        private static int candidate = 5;\n        private static int root = 3;\n        private static int square = 9;\n        private static int step = 2;\n\n        private static int logIndexCount = 3;\n        private static int logIndexTrigger = 8;\n\n        private static void CalculateUpToIndex(int last)\n        {\n            if (last >= c_maxPrimeCount)\n                throw new ArgumentException(\"exceeded prime table size limit\");\n            if (last >= primeCapacity)\n            {\n                while (last >= primeCapacity) primeCapacity *= 2;\n                Array.Resize(ref primeArray, primeCapacity);\n                Array.Resize(ref primeInverseArray, primeCapacity);\n            }\n\n            while (primeCount <= last)\n            {\n                for (bool found = false; !found; )\n                {\n\t                candidate += step;\n\t                step = 6 - step;\n\t                if (candidate > square)\n\t                {\n\t\t                ++root;\n\t\t                square = root * root;\n\t                }\n            \t    \n\t                found = true;\n\t                for (int pi = 2; primeArray[pi] <= root; pi++)\n\t\t                if (candidate % primeArray[pi] == 0)\n\t\t                {\n\t\t                    found = false; break;\n\t\t                }\n\t            }\n                if (candidate > logIndexTrigger)\n                {\n                    primeLogIndexArray[logIndexCount++] = primeCount;\n                    logIndexTrigger *= 2;\n                }\n\t            primeArray[primeCount] = candidate;\n\t            primeInverseArray[primeCount] = 1.0/(double)candidate;\n\t            ++primeCount;\n            }\n        }\n\n        static Prime()\n        {\n            primeCapacity = c_initialPrimeCount;\n\n            primeArray[0] = 2;\n            primeArray[1] = 3;\n            primeArray[2] = 5;\n            primeInverseArray[0] = 1/2.0;\n            primeInverseArray[1] = 1/3.0;\n            primeInverseArray[2] = 1/5.0;\n\n            primeLogIndexArray[0] = -1;\n            primeLogIndexArray[1] = 0;\n            primeLogIndexArray[2] = 2;\n\n            primeCount = 3;\n\n            CalculateUpToIndex(c_initialPrimeCount - 1);\n\n            int isPrimeCount = primeArray[c_initialPrimeCount - 1] + 1;\n            isPrimeArray = new bool[isPrimeCount];\n            for (int pi = 0; pi < primeCount; pi++)\n                isPrimeArray[primeArray[pi]] = true;\n        }\n\n        private static int primeCapacity;\n        private static int[] primeArray = new int[c_initialPrimeCount];\n        private static double[] primeInverseArray = new double[c_initialPrimeCount];\n        private static readonly bool[] isPrimeArray;\n        private static readonly int[] primeLogIndexArray = new int[64];\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/PseudoRandomSeries.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Uses an IRandomUniform generator to create an IRandomSeries.\n    /// The series that are generated will not correlated.\n    /// </summary>\n    public class PseudoRandomSeries : IRandomSeries\n    {\n        readonly IRandomUniform m_rnd;\n\n        public PseudoRandomSeries(IRandomUniform rnd)\n        {\n            m_rnd = rnd;\n        }\n\n        public double UniformDouble(int seriesIndex)\n        {\n            return m_rnd.UniformDouble();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/Quasi.cs",
    "content": "namespace Aardvark.Base\n{\n    public static class Quasi\n    {\n        /// <summary>\n        /// Generates a new number in the halton sequence\n        /// with the given inverse base, and the previous\n        /// number in the sequence.\n        /// \n        /// This is the incremental version to generate\n        /// the halton squence of quasi-random numbers of\n        /// a given base.  It has been taken from:\n        ///\n        /// A. Keller: Instant Radiosity,\n        /// In Computer Graphics (SIGGRAPH 97 Conference Proceedings),\n        /// pp. 49--56, August 1997.\n        /// \n        /// As a small optimization, the inverse of the base is used.\n        /// </summary>\n        public static double QuasiHalton(\n                double inverse_base, double value)\n        {\n            double r = 1.0 - value - 1e-10;\n            if (inverse_base < r)\n            {\n                value += inverse_base;\n            }\n            else\n            {\n                double h = inverse_base * inverse_base;\n                double hh = inverse_base;\n                while (h >= r)\n                {\n                    hh = h;\n                    h *= inverse_base;\n                }\n                value += hh + h - 1.0;\n            }\n            return value;\n        }\n        \n        /// <summary>\n        /// Generates a new number in the halton sequence\n        /// with the 'index'th prime as base.\n        /// </summary>\n        public static double QuasiHaltonWithIndex(\n                int index, double value)\n        {\n            return QuasiHalton(Prime.InverseWithIndex(index), value);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/RandomDistributions.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Generator of normal distributed random values.\n    /// The generator uses the Box-Muller transformation to generate two samples at \n    /// once and thereby is superior to <see cref=\"IRandomUniformExtensions.Gaussian\" /> if multiple samples are required.\n    /// </summary>\n    public class RandomGaussian : IRandomDistribution\n    {\n        private readonly IRandomUniform m_rndUniform;\n        private double m_cachedValue;\n\n        public RandomGaussian(IRandomUniform rndUniform)\n        {\n            m_rndUniform = rndUniform;\n            m_cachedValue = Double.NaN;\n        }\n\n        #region IRandomDistribution Members\n\n        /// <summary>\n        /// Returns a Gaussian distributed double.\n        /// </summary>\n        public double GetDouble()\n        {\n            double value;\n\n            if (!Double.IsNaN(m_cachedValue))\n            {\n                value = m_cachedValue;\n                m_cachedValue = Double.NaN;\n            }\n            else\n            {\n                // using the polar form of the Box-Muller transformation to\n                // transform two random uniform values to two Gaussian\n                // distributed values\n                double x1, x2, w;\n                do\n                {\n                    x1 = 2.0 * m_rndUniform.UniformDouble() - 1.0;\n                    x2 = 2.0 * m_rndUniform.UniformDouble() - 1.0;\n                    w = x1 * x1 + x2 * x2;\n                } while (w >= 1.0);\n\n                w = Fun.Sqrt((-2.0 * Fun.Log(w)) / w);\n                value = x1 * w;\n                m_cachedValue = x2 * w;\n            }\n\n            return value;\n        }\n\n        #endregion\n\n        #region Other Methods\n\n        /// <summary>\n        /// Returns a Gaussian distributed double given a mean and standard deviation.\n        /// </summary>\n        public double GetDouble(double mean, double standardDeviation)\n            => GetDouble() * standardDeviation + mean;\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/RandomIEnumerableExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class RandomIEnumerableExtensions\n    {\n        /// <summary>\n        /// Yields each element with propability p.\n        /// </summary>\n        public static IEnumerable<T> TakeRandomly<T>(this IEnumerable<T> self, double p,\n                                                     IRandomUniform random = null)\n        {\n            if (self == null) throw new ArgumentNullException(nameof(self));\n            if (double.IsNaN(p) || p < 0 || p > 1) throw new ArgumentOutOfRangeException(nameof(p));\n\n            if (random == null) random = new RandomSystem();\n            foreach (var s in self) if (random.UniformDouble() <= p) yield return s;\n        }\n\n        /// <summary>\n        /// Yields each element with propability p.\n        /// </summary>\n        public static IEnumerable<R> TakeRandomly<T, R>(this IEnumerable<T> self, Func<T, R> selector, double p,\n                                                        IRandomUniform random = null)\n        {\n            if (self == null) throw new ArgumentNullException(nameof(self));\n            if (double.IsNaN(p) || p < 0 || p > 1) throw new ArgumentOutOfRangeException(nameof(p));\n\n            if (random == null) random = new RandomSystem();\n            foreach (var s in self) if (random.UniformDouble() <= p) yield return selector(s);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/RandomSample.cs",
    "content": "namespace Aardvark.Base\n{\n    public static class RandomSample\n    {\n        /// <summary>\n        /// Uses the 2 random series (seriesIndex, seriesIndex+1) to generate a random point on a sphere.\n        /// </summary>\n        public static V3d Spherical(IRandomSeries rnds, int seriesIndex)\n        {\n            return Spherical(rnds.UniformDouble(seriesIndex), rnds.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Uses the 2 random variables x1 and x2 to generate a random point on a sphere.\n        /// </summary>\n        public static V3d Spherical(double x1, double x2)\n        {\n            var phi = Constant.PiTimesTwo * x1;\n            var z = 1 - 2 * x2;\n            var r = Fun.Max(1 - z * z, 0).Sqrt();\n            return new V3d(r * phi.Cos(), r * phi.Sin(), z);\n        }\n\n        /// <summary>\n        /// Uses the 2 random variables x1 and x2 to generate a random point on a sphere.\n        /// </summary>\n        public static V3f Spherical(float x1, float x2)\n        {\n            var phi = ConstantF.PiTimesTwo * x1;\n            var z = 1 - 2 * x2;\n            var r = Fun.Max(1 - z * z, 0).Sqrt();\n            return new V3f(r * phi.Cos(), r * phi.Sin(), z);\n        }\n\n        /// <summary>\n        /// Generate a cosine weighted random sample oriented in the supplied normal direction \n        /// using two random series (seriesIndex, seriesIndex+1).\n        /// The normal is expected to be normalized.\n        /// </summary>\n        public static V3d Lambertian(V3d normal, IRandomSeries rnds, int seriesIndex)\n        {\n            return Lambertian(normal, \n                rnds.UniformDouble(seriesIndex),\n                rnds.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generate a cosine weighted random sample oriented in the supplied normal direction \n        /// using two random series (seriesIndex, seriesIndex+1).\n        /// The normal is expected to be normalized.\n        /// </summary>\n        public static V3f Lambertian(V3f normal, IRandomSeries rnds, int seriesIndex)\n        {\n            return Lambertian(normal,\n                (float)rnds.UniformDouble(seriesIndex),\n                (float)rnds.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generate a cosine weighted random sample oriented in the supplied normal direction \n        /// using the 2 random variables x1 and x2.\n        /// The normal is expected to be normalized.\n        /// </summary>\n        public static V3d Lambertian(V3d normal, double x1, double x2)\n        {\n            // random point on cylinder barrel\n            var phi = Constant.PiTimesTwo * x1;\n            var z = 1 - 2 * x2;\n            // project to sphere\n            var r = Fun.Max(1 - z * z, 0).Sqrt();\n            var vec = new V3d(r * phi.Cos(), r * phi.Sin(), z) + normal;\n            var squareLen = vec.LengthSquared;\n\n            // check if random sphere point was perfectly opposite of the normal direction (in case x2 ~= 1)\n            if (squareLen < 1e-9)\n                return normal;\n\n            var norm = 1 / squareLen.Sqrt();\n            return vec * norm;\n        }\n\n        /// <summary>\n        /// Generate a cosine weighted random sample oriented in the supplied normal direction \n        /// using the 2 random variables x1 and x2.\n        /// The normal is expected to be normalized.\n        /// </summary>\n        public static V3f Lambertian(V3f normal, float x1, float x2)\n        {\n            // random point on cylinder barrel\n            var phi = ConstantF.PiTimesTwo * x1;\n            var z = 1 - 2 * x2;\n            // project to sphere\n            var r = Fun.Max(1 - z * z, 0).Sqrt();\n            var vec = new V3f(r * phi.Cos(), r * phi.Sin(), z) + normal;\n            var squareLen = vec.LengthSquared;\n\n            // check if random sphere point was perfectly opposite of the normal direction (in case x2 ~= 1)\n            if (squareLen < 1e-9f)\n                return normal;\n\n            var norm = 1 / squareLen.Sqrt();\n            return vec * norm;\n        }\n\n        /// <summary>\n        /// Generates a cosine weighted random direction using the 2 random series (seriesIndex, seriesIndex+1).\n        /// See Global Illuminatin Compendium, Dutre 2003, (35)\n        /// PDF = cos(theta)/PI\n        /// </summary>\n        public static V3d Lambertian(IRandomSeries rnds, int seriesIndex)\n        {\n            return Lambertian(\n                rnds.UniformDouble(seriesIndex),\n                rnds.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a cosine weighted random direction using the 2 random varables x1 and x2.\n        /// See Global Illuminatin Compendium, Dutr 2003, (35)\n        /// PDF = cos(theta)/PI\n        /// </summary>\n        public static V3d Lambertian(double x1, double x2)\n        {\n            // random point on disk\n            var r = Fun.Sqrt(x1);\n            var phi = Constant.PiTimesTwo * x2;\n            var x = r * Fun.Cos(phi);\n            var y = r * Fun.Sin(phi);\n            // project to hemisphere\n            var z = Fun.Sqrt(1 - x1); // x1 = r^2\n            return new V3d(x, y, z);\n        }\n\n        /// <summary>\n        /// Generates a cosine weighted random direction using the 2 random varables x1 and x2.\n        /// See Global Illuminatin Compendium, Dutr 2003, (35)\n        /// PDF = cos(theta)/PI\n        /// </summary>\n        public static V3f Lambertian(float x1, float x2)\n        {\n            // random point on disk\n            var r = Fun.Sqrt(x1);\n            var phi = ConstantF.PiTimesTwo * x2;\n            var x = r * Fun.Cos(phi);\n            var y = r * Fun.Sin(phi);\n            // project to hemisphere\n            var z = Fun.Sqrt(1 - x1); // x1 = r^2\n            return new V3f(x, y, z);\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed 2d random sample on a disk with radius 1.\n        /// It uses two random series (seriesIndex, seriesIndex+1).\n        /// </summary>\n        public static V2d Disk(IRandomSeries rnd, int seriesIndex)\n        {\n            return Disk(rnd.UniformDouble(seriesIndex), rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed 2d random sample on a disk with radius 1 \n        /// using the 2 random variables x1 and x2.\n        /// </summary>\n        public static V2d Disk(double x1, double x2)\n        {\n            // random direction\n            var phi = x1 * Constant.PiTimesTwo;\n            // random radius transformed by sqrt to result in area equivalent samples distribution\n            var r = x2.Sqrt();\n            return new V2d(r * Fun.Cos(phi),\n                           r * Fun.Sin(phi));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed 2d random sample on a disk with radius 1 \n        /// using the 2 random variables x1 and x2.\n        /// </summary>\n        public static V2f Disk(float x1, float x2)\n        {\n            // random direction\n            var phi = x1 * ConstantF.PiTimesTwo;\n            // random radius transformed by sqrt to result in area equivalent samples distribution\n            var r = x2.Sqrt();\n            return new V2f(r * Fun.Cos(phi),\n                           r * Fun.Sin(phi));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random series (seriesIndex,  seriesIndex + 1).\n        /// </summary>\n        public static V2d Triangle(Triangle2d t, IRandomSeries rnd, int seriesIndex)\n        {\n            return Triangle(t.P0, t.P1, t.P2,\n                        rnd.UniformDouble(seriesIndex),\n                        rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random series (seriesIndex,  seriesIndex + 1).\n        /// </summary>\n        public static V2f Triangle(Triangle2f t, IRandomSeries rnd, int seriesIndex)\n        {\n            return Triangle(t.P0, t.P1, t.P2,\n                        (float)rnd.UniformDouble(seriesIndex),\n                        (float)rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random variables x1 and x2.\n        /// </summary>\n        public static V2d Triangle(Triangle2d t, double x1, double x2)\n        {\n            return Triangle(t.P0, t.P1, t.P2, x1, x2);\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random variables x1 and x2.\n        /// </summary>\n        public static V2f Triangle(Triangle2f t, float x1, float x2)\n        {\n            return Triangle(t.P0, t.P1, t.P2, x1, x2);\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random series (seriesIndex,  seriesIndex + 1).\n        /// </summary>\n        public static V2d Triangle(V2d p0, V2d p1, V2d p2, IRandomSeries rnd, int seriesIndex)\n        {\n            return Triangle(p0, p1, p2,\n                        rnd.UniformDouble(seriesIndex),\n                        rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random series (seriesIndex,  seriesIndex + 1).\n        /// </summary>\n        public static V2f Triangle(V2f p0, V2f p1, V2f p2, IRandomSeries rnd, int seriesIndex)\n        {\n            return Triangle(p0, p1, p2,\n                        (float)rnd.UniformDouble(seriesIndex),\n                        (float)rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random variables x1 and x2.\n        /// </summary>\n        public static V2d Triangle(V2d p0, V2d p1, V2d p2, double x1, double x2)\n        {\n            var x1sq = x1.Sqrt();\n            return (1 - x1sq) * p0 + (x1sq * (1 - x2)) * p1 + (x1sq * x2) * p2;\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random variables x1 and x2.\n        /// </summary>\n        public static V2f Triangle(V2f p0, V2f p1, V2f p2, float x1, float x2)\n        {\n            var x1sq = x1.Sqrt();\n            return (1 - x1sq) * p0 + (x1sq * (1 - x2)) * p1 + (x1sq * x2) * p2;\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random series (seriesIndex,  seriesIndex + 1).\n        /// </summary>\n        public static V3d Triangle(Triangle3d t, IRandomSeries rnd, int seriesIndex)\n        {\n            return Triangle(t.P0, t.P1, t.P2,\n                        rnd.UniformDouble(seriesIndex),\n                        rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random series (seriesIndex,  seriesIndex + 1).\n        /// </summary>\n        public static V3f Triangle(Triangle3f t, IRandomSeries rnd, int seriesIndex)\n        {\n            return Triangle(t.P0, t.P1, t.P2,\n                        (float)rnd.UniformDouble(seriesIndex),\n                        (float)rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random variables x1 and x2.\n        /// </summary>\n        public static V3d Triangle(Triangle3d t, double x1, double x2)\n        {\n            return Triangle(t.P0, t.P1, t.P2, x1, x2);\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random variables x1 and x2.\n        /// </summary>\n        public static V3f Triangle(Triangle3f t, float x1, float x2)\n        {\n            return Triangle(t.P0, t.P1, t.P2, x1, x2);\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random series (seriesIndex,  seriesIndex + 1).\n        /// </summary>\n        public static V3d Triangle(V3d p0, V3d p1, V3d p2, IRandomSeries rnd, int seriesIndex)\n        {\n            return Triangle(p0, p1, p2, \n                        rnd.UniformDouble(seriesIndex),\n                        rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random series (seriesIndex,  seriesIndex + 1).\n        /// </summary>\n        public static V3f Triangle(V3f p0, V3f p1, V3f p2, IRandomSeries rnd, int seriesIndex)\n        {\n            return Triangle(p0, p1, p2,\n                        (float)rnd.UniformDouble(seriesIndex),\n                        (float)rnd.UniformDouble(seriesIndex + 1));\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random variables x1 and x2.\n        /// </summary>\n        public static V3d Triangle(V3d p0, V3d p1, V3d p2, double x1, double x2)\n        {\n            var x1sq = x1.Sqrt();\n            return (1 - x1sq) * p0 + (x1sq * (1 - x2)) * p1 + (x1sq * x2) * p2;\n        }\n\n        /// <summary>\n        /// Generates a uniform distributed random sample on the given triangle using \n        /// two random variables x1 and x2.\n        /// </summary>\n        public static V3f Triangle(V3f p0, V3f p1, V3f p2, float x1, float x2)\n        {\n            var x1sq = x1.Sqrt();\n            return (1 - x1sq) * p0 + (x1sq * (1 - x2)) * p1 + (x1sq * x2) * p2;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Random/RandomSystem.cs",
    "content": "﻿using System;\nusing System.Threading;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// System Random Generator.\n    /// </summary>\n    public class RandomSystem : IRandomUniform\n    {\n        public Random Generator;\n\n        #region Constructors\n\n        /// <summary>\n        /// Initialize using the time of day in milliseconds as seed.\n        /// </summary>\n        public RandomSystem() => Generator = new Random();\n\n        /// <summary>\n        /// Initialize using custom seed.\n        /// </summary>\n        public RandomSystem(int seed) => Generator = new Random(seed);\n\n        #endregion\n\n        #region IRandomUniform Members\n\n        public int RandomBits => 31;\n\n        public bool GeneratesFullDoubles => false;\n\n        public void ReSeed(int seed) => Generator = new Random(seed);\n\n        private static readonly ThreadLocal<byte[]> s_buffer4 = new ThreadLocal<byte[]>(() => new byte[4]);\n        public int UniformInt()\n        {\n            var array = s_buffer4.Value;\n            Generator.NextBytes(array);\n            return (int)(BitConverter.ToUInt32(array, 0) & 0x7fffffffu);\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed uint in the interval [0, 2^63-1].\n        /// Constructed using 16 bits of each of two random integers.\n        /// </summary>\n        public uint UniformUInt()\n        {\n            var array = s_buffer4.Value;\n            Generator.NextBytes(array);\n            return BitConverter.ToUInt32(array, 0);\n        }\n\n        private static readonly ThreadLocal<byte[]> s_buffer8 = new ThreadLocal<byte[]>(() => new byte[8]);\n        /// <summary>\n        /// Returns a uniformly distributed long in the interval [0, 2^63-1].\n        /// </summary>\n        public long UniformLong()\n        {\n            var array = s_buffer8.Value;\n            Generator.NextBytes(array);\n            return (long)(BitConverter.ToUInt64(array, 0) & 0x7ffffffffffffffful);\n\n        }\n\n        /// <summary>\n        /// Returns a uniformly distributed long in the interval [0, 2^64-1].\n        /// </summary>\n        public ulong UniformULong()\n        {\n            var array = s_buffer8.Value;\n            Generator.NextBytes(array);\n            return BitConverter.ToUInt64(array, 0);\n        }\n\n        public float UniformFloat() => (UniformInt() >> 7) * (float)(1.0 / 16777216.0);\n\n        public float UniformFloatClosed() => (float)(UniformInt() / 2147483647.0);\n\n        public float UniformFloatOpen()\n        {\n            int r; do { r = UniformInt() >> 7; } while (r == 0);\n            return r * (float)(1.0 / 16777216.0);\n        }\n\n        public double UniformDouble() => Generator.NextDouble();\n\n        public double UniformDoubleClosed() => UniformInt() / 2147483647.0;\n\n        public double UniformDoubleOpen()\n        {\n            int r; do { r = UniformInt(); } while (r == 0);\n            return r * (1.0 / 2147483648.0);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/FilterLogTarget.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// A filtering log target that only records messages for which the\n    /// filter function supplied in the constructor returns true.\n    /// </summary>\n    public class FilterLogTarget : ILogTarget\n    {\n        private readonly ILogTarget m_target;\n        private readonly Func<LogMsg, bool> m_filterFun;\n\n        public FilterLogTarget(ILogTarget target, Func<LogMsg, bool> filterFun)\n        {\n            m_target = target;\n            m_filterFun = filterFun;\n        }\n\n        public void NewThreadIndex(int threadIndex)\n        {\n            m_target.NewThreadIndex(threadIndex);\n        }\n\n        public void Log(int threadIndex, LogMsg msg)\n        {\n            if (m_filterFun(msg))\n                m_target.Log(threadIndex, msg);\n        }\n\n        public void Dispose()\n        {\n            m_target.Dispose();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/IJobReporter.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    public interface IJobReporter\n    {\n        /// <summary>\n        /// The number of spaces of indent caused by Begin / Report.End.\n        /// This property should only be set BEFORE actual reporting.\n        /// </summary>\n        int Indent { get; set; }\n        void Line(LogType type, int level, ILogTarget target,\n                  string leftText, int rightPos = 0, string rightText = null);\n        // the following methods are regarded as LogType.Info\n        void Text(int level, ILogTarget target, string text);\n        void Wrap(int level, ILogTarget target, string text);\n        ReportJob Begin(ReportJob parentJob, int level, ILogTarget target, string text, bool timed, bool noLog = false);\n        double End(int level, ILogTarget target, string text, bool addTimeToParent);\n        void Tests(TestInfo testInfo);\n        void Progress(int level, ILogTarget target, double progress, bool relative = false);\n        void Values(int level, ILogTarget target, string name, string separator, object[] values);\n        // internal API for managing external reporters\n        void AddReporter(IReporter reporter);\n        void RemoveReporter(IReporter reporter);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/ILogTarget.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public interface ILogTarget : IDisposable\n    {\n        void NewThreadIndex(int threadIndex);\n        void Log(int threadIndex, LogMsg msg);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/IReportable.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public interface IReportable\n    {\n        void ReportValue(int verbosity, string name);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/IReporter.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// The IReporter interface can be implemented for objects to catch\n    /// reports on a level, where some info is passed with typed parameters\n    /// (e.g. timing seconds as doubles, values as objects).\n    /// As soon as a reporter object is added, all Report calls from the\n    /// same thread are also delivered to that reporter object. Reporting\n    /// on other threads, where the reporter object was not added, does not\n    /// appear. If the same reporter object is added multiple times from\n    /// different threads, all these methods need to do their own locking.\n    /// If only one reporter object is added from one thread, no locking is\n    /// necessary. The supplied threadIndex, is a running number for each\n    /// thread assigned based on their first sending of a Report message.\n    /// It can be directly used as a key in e.g. an IntDict.\n    /// </summary>\n    public interface IReporter\n    {\n        void Line(int threadIndex, LogType type, int level, ILogTarget target,\n                  string leftText, int rightPos = 0, string rightText = null);\n        // the following methods are regarded as LogType.Info\n        void Text(int threadIndex, int level, ILogTarget target, string text);\n        void Wrap(int threadIndex, int level, ILogTarget target, string text);\n        void Begin(int threadIndex, int level, ILogTarget target, string text, bool timed);\n        void End(int threadIndex, int level, ILogTarget target, string text, double seconds);\n        void Progress(int threadIndex, int level, ILogTarget target, string text, double progress, double seconds);\n        void Values(int threadIndex, int level, ILogTarget target, string name, string separator, object[] values);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/JobReporter.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\n\nnamespace Aardvark.Base\n{\n    public class JobReporter : IJobReporter\n    {\n        private readonly int m_ti;\n        public int m_indent;\n        private ReportJob m_job;\n        private readonly Stack<ReportJob> m_jobStack;\n        private volatile IReporter[] m_reporterArray;\n        private readonly object m_reporterArrayLock;\n\n        #region Constructor\n\n        public JobReporter(int threadIndex = 0)\n        {\n            m_ti = threadIndex; m_indent = 2;\n            m_job = new ReportJob(\"THREAD\", 0, true);\n            m_jobStack = new Stack<ReportJob>();\n            m_reporterArray = null;\n            m_reporterArrayLock = new object();\n        }\n\n        #endregion\n\n        #region Properties\n\n        public int Indent\n        {\n            get { return m_indent; }\n            set { m_indent = value; }\n        }\n\n        #endregion\n\n        #region IJobReporter\n\n        public void Line(LogType type, int level, ILogTarget target, string t0, int p1 = 0, string t1 = null)\n        {\n            target.Log(m_ti, new LogMsg(type, LogOpt.EndLine, level, m_job.HierarchyLevel * m_indent, t0, p1, t1));\n            var reporterArray = m_reporterArray;\n            if (reporterArray != null)\n                for (int i = 0; i < reporterArray.Length; i++)\n                    reporterArray[i].Line(m_ti, type, level, target, t0, p1, t1);\n        }\n\n        public void Wrap(int level, ILogTarget target, string text)\n        {\n            target.Log(m_ti, new LogMsg(LogType.Info, LogOpt.Join | LogOpt.Wrap, level,\n                                            m_job.HierarchyLevel * m_indent, text, -2));\n            var reporterArray = m_reporterArray;\n            if (reporterArray != null)\n                for (int i = 0; i < reporterArray.Length; i++)\n                    reporterArray[i].Wrap(m_ti, level, target, text);\n        }\n\n        public void Text(int level, ILogTarget target, string text)\n        {\n            string[] lines = text.Split('\\n');\n            var last = lines.Length - 1;\n            if (last == 0)\n            {\n                target.Log(m_ti, new LogMsg(LogType.Info, LogOpt.Join, level,\n                                             m_job.HierarchyLevel * m_indent, lines[0], -2));\n            }\n            else\n            {\n                for (int i = 0; i < last; i++)\n                    target.Log(m_ti, new LogMsg(LogType.Info, LogOpt.Join | LogOpt.EndLine, level,\n                                                 m_job.HierarchyLevel * m_indent, lines[i]));\n                if (lines[last].Length > 0)\n                    target.Log(m_ti, new LogMsg(LogType.Info, LogOpt.Join, level,\n                                                m_job.HierarchyLevel * m_indent, lines[last]));\n            }\n            var reporterArray = m_reporterArray;\n            if (reporterArray != null)\n                for (int i = 0; i < reporterArray.Length; i++)\n                    reporterArray[i].Text(m_ti, level, target, text);\n        }\n\n        public ReportJob Begin(ReportJob parentJob, int level, ILogTarget target, string text, bool timed, bool noLog = false)\n        {\n            if (parentJob == null) parentJob = m_job;\n            var reporterArray = m_reporterArray;\n            if (reporterArray != null)\n                for (int i = 0; i < reporterArray.Length; i++)\n                    reporterArray[i].Begin(m_ti, level, target, text, timed);\n            var opt = timed ? LogOpt.Timed : LogOpt.None;\n            if (!noLog)\n                target.Log(m_ti, new LogMsg(LogType.Begin, opt, level, parentJob.HierarchyLevel * m_indent, text, -2));\n            m_jobStack.Push(m_job);\n            m_job = new ReportJob(text, level, timed, parentJob);\n            return m_job;\n        }\n\n        public void Tests(TestInfo testInfo)\n        {\n            m_job.TestInfo += testInfo;\n            m_job.ReportTests = true;\n        }\n\n        public double End(int level, ILogTarget target, string text, bool addTimeToParent)\n        {\n            var parentJob = m_job.ParentJob;\n            if (m_jobStack.Count == 0)\n            {\n                Report.Warn(\"superfluous Report.End() encountered\");\n                if (text != null) // still report message if some\n                    target.Log(m_ti, new LogMsg(LogType.End, LogOpt.NewText, level, 0,\n                                                text, -2, null));\n                return 0.0;\n            }\n            double seconds; string time; LogOpt opt;\n            if (m_job.IsTimed)\n            {\n                seconds = m_job.ElapsedSeconds; opt = LogOpt.EndLine | LogOpt.Timed;\n                time = String.Format(CultureInfo.InvariantCulture, \"{0:F3} s\", seconds);\n            }\n            else\n            {\n                seconds = 0.0; time = null; opt = LogOpt.EndLine;\n            }\n            m_job.Disposed = true;\n            if (level != m_job.Level)\n            {\n                Report.Warn(\"Report.Begin({0}) level different from Report.End({1}),\"\n                            + \" using Report.End({0})\", m_job.Level, level);\n                level = m_job.Level;\n            }\n            var beginText = m_job.Message;\n            if (text == null) text = beginText;\n            else if (text != beginText) { text = beginText + text; opt |= LogOpt.NewText; }\n            if (m_job.ReportTests == true)\n            {\n                var testInfo = m_job.TestInfo;\n                m_job = m_jobStack.Pop(); m_job.TestInfo += testInfo;\n                var passed = String.Format(CultureInfo.InvariantCulture,\n                             \"[{0}/{1} OK]\", testInfo.PassedCount, testInfo.TestCount);\n                time = time != null ? passed + ' ' + time : passed;\n                target.Log(m_ti, new LogMsg(LogType.End, opt, level, parentJob.HierarchyLevel * m_indent,\n                                            text, -2, time));\n                if (testInfo.FailedCount > 0)\n                {\n                    var failed = String.Format(CultureInfo.InvariantCulture,\n                                               \" {0}/{1} FAILED\", testInfo.FailedCount, testInfo.TestCount);\n                    target.Log(m_ti, new LogMsg(LogType.Warn, opt, level, parentJob.HierarchyLevel * m_indent,\n                                                    \"WARNING: \" + text + failed));\n                }\n            }\n            else\n            {\n                var childrenTime = m_job.ChildrenTime;\n                if (seconds > 0.0 && childrenTime > 0.0)\n                    time = String.Format(CultureInfo.InvariantCulture, \"[{0:F2}x] \", childrenTime / seconds) + time;\n                if (addTimeToParent)\n                {\n                    lock (parentJob) parentJob.ChildrenTime += seconds;\n                }\n                m_job = m_jobStack.Pop();\n                target.Log(m_ti, new LogMsg(LogType.End, opt, level, parentJob.HierarchyLevel * m_indent,\n                                            text, -2, time));\n            }\n            var reporterArray = m_reporterArray;\n            if (reporterArray != null)\n                for (int i = 1; i < reporterArray.Length; i++)\n                    reporterArray[i].End(m_ti, level, target, text, seconds);\n            return seconds;\n        }\n\n        public void Progress(int level, ILogTarget target, double progress, bool relative = false)\n        {\n            if (relative) progress += m_job.Progress;\n            if (progress > 1.0) progress = 1.0;\n            m_job.Progress = progress;\n            double seconds; string text; LogOpt opt;\n            if (!m_job.IsTimed)\n            {\n                seconds = -1.0; opt = LogOpt.None;\n                text = String.Format(CultureInfo.InvariantCulture, \"{0,6:F2}%\", 100.0 * progress);\n            }\n            else\n            {\n                seconds = m_job.ElapsedSeconds; opt = LogOpt.Timed;\n                text = String.Format(CultureInfo.InvariantCulture, \"{0,6:F2}% {1,10:F3} s\", 100.0 * progress, seconds);\n            }\n            target.Log(m_ti, new LogMsg(LogType.Progress, opt, level,\n                                        (m_job.HierarchyLevel - 1) * m_indent, m_job.Message, -2, text));\n            var reporterArray = m_reporterArray;\n            if (reporterArray != null)\n                for (int i = 0; i < reporterArray.Length; i++)\n                    reporterArray[i].Progress(m_ti, level, target, m_job.Message, progress, seconds);\n        }\n\n        public void Values(int level, ILogTarget target, string name, string separator, object[] values)\n        {\n            var text = values.Length == 1 ? values[0].ToString() : values.Map(o => o.ToString()).Join(separator);\n            target.Log(m_ti, new LogMsg(LogType.Info, LogOpt.EndLine, level,\n                                        m_job.HierarchyLevel * m_indent, name, 40, text));\n            var reporterArray = m_reporterArray;\n            if (reporterArray != null)\n                for (int i = 0; i < reporterArray.Length; i++)\n                    reporterArray[i].Values(m_ti, level, target, name, separator, values);\n        }\n\n        #endregion\n\n        #region Adding and Removing IReporters\n\n        public void AddReporter(IReporter reporter)\n        {\n            lock (m_reporterArrayLock)\n            {\n                m_reporterArray = m_reporterArray.WithAppended(reporter);\n            }\n        }\n\n        public void RemoveReporter(IReporter reporter)\n        {\n            lock (m_reporterArrayLock)\n            {\n                m_reporterArray = m_reporterArray.WithRemoved(reporter);\n            }\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/LogMsg.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    [Flags]\n    public enum LogType\n    {\n        Unknown = 0,\n        Info = 1,\n        Begin = 2,\n        End = 3,\n        Progress = 4,\n        Warn = 5,\n        Trace = 6,\n        Debug = 7,\n        Error = 8,\n        Fatal = 9,\n    }\n\n    [Flags]\n    public enum LogOpt\n    {\n        None = 0x00,\n        EndLine = 0x01,\n        Timed = 0x02,\n        Join = 0x04,\n        Wrap = 0x08,\n        NewText = 0x10, // new text on Report.End\n    };\n\n    public struct LogMsg\n    {\n        public LogType Type;\n        public LogOpt Opt;\n        public int Level;\n        public int LeftPos; public string LeftText;\n        public int RightPos; public string RightText;\n\n        public LogMsg(LogType type, LogOpt opt, int level,\n                      int leftPos, string leftText, int rightPos = 0, string rightText = null)\n        {\n            Type = type; Opt = opt; Level = level;\n            LeftPos = leftPos; LeftText = leftText; RightPos = rightPos; RightText = rightText;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/MultiLogTarget.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    public class MultiLogTarget : ILogTarget\n    {\n        private volatile ILogTarget[] m_targetArray;\n        private readonly object m_targetArrayLock;\n\n        #region Constructor\n\n        public MultiLogTarget(params ILogTarget[] targetArray)\n        {\n            m_targetArray = targetArray;\n            m_targetArrayLock = new object();\n        }\n\n        #endregion\n\n        #region ILogTarget\n\n        public void NewThreadIndex(int threadIndex)\n        {\n            var targetArray = m_targetArray;\n            for (int i = 0; i < targetArray.Length; i++)\n                targetArray[i].NewThreadIndex(threadIndex);\n        }\n\n        public void Log(int threadIndex, LogMsg msg)\n        {\n            var targetArray = m_targetArray;\n            for (int i = 0; i < targetArray.Length; i++)\n                targetArray[i].Log(threadIndex, msg);\n        }\n\n        public void Dispose()\n        {\n            var targetArray = m_targetArray;\n            for (int i = 0; i < targetArray.Length; i++)\n                targetArray[i].Dispose();\n        }\n\n        #endregion\n\n        #region Adding and Removing Targets\n\n        public void Add(ILogTarget target)\n        {\n            lock (m_targetArrayLock)\n            {\n                m_targetArray = m_targetArray.WithAppended(target);\n            }\n        }\n\n        public void Remove(ILogTarget target)\n        {\n            lock (m_targetArrayLock)\n            {\n                m_targetArray = m_targetArray.WithRemoved(target);\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/NullReporter.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    public class NullReporter : IJobReporter\n    {\n        public int Indent\n        {\n            get { return 0; }\n            set { }\n        }\n\n        public void AddReporter(IReporter reporter)\n        {\n        }\n\n        public ReportJob Begin(ReportJob parentJob, int level, ILogTarget target, string text, bool timed, bool noLog = false)\n        {\n            return null;\n        }\n\n        public double End(int level, ILogTarget target, string text, bool addTimeToParent)\n        {\n            return 0.0;\n        }\n\n        public void Line(LogType type, int level, ILogTarget target, string leftText, int rightPos = 0, string rightText = null)\n        {\n        }\n\n        public void Progress(int level, ILogTarget target, double progress, bool relative = false)\n        {\n        }\n\n        public void RemoveReporter(IReporter reporter)\n        {\n        }\n\n        public void Tests(TestInfo testInfo)\n        {\n        }\n\n        public void Text(int level, ILogTarget target, string text)\n        {\n        }\n\n        public void Values(int level, ILogTarget target, string name, string separator, object[] values)\n        {\n        }\n\n        public void Wrap(int level, ILogTarget target, string text)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/PerThreadJobReporter.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Threading;\n\nnamespace Aardvark.Base\n{\n    public class PerThreadJobReporter : IJobReporter\n    {\n        private SpinLock m_lock;\n        private readonly Dictionary<int, IJobReporter> m_reporterMap;\n        private volatile int m_threadCount;\n        private int m_indent;\n\n        #region Constructor\n\n        public PerThreadJobReporter()\n        {\n            m_reporterMap = new Dictionary<int, IJobReporter>();\n            m_threadCount = 0; m_indent = 2;\n        }\n\n        #endregion\n\n        #region Thread Handling\n\n        private IJobReporter CurrentReporter(ILogTarget target = null)\n        {\n            IJobReporter reporter;\n            var threadId = Thread.CurrentThread.ManagedThreadId;\n            bool lockTaken = false;\n            try\n            {\n                m_lock.Enter(ref lockTaken);\n                if (!m_reporterMap.TryGetValue(threadId, out reporter))\n                {\n                    var threadIndex = m_threadCount++;\n                    reporter = new JobReporter(threadIndex) { Indent = m_indent };\n                    m_reporterMap[threadId] = reporter;\n                    if (target != null) target.NewThreadIndex(threadIndex);\n                }\n            }\n            finally\n            {\n                if (lockTaken) m_lock.Exit(true);\n            }\n            return reporter;\n        }\n\n        #endregion\n\n        #region IJobReporter\n\n        public int Indent\n        {\n            get { return m_indent; }\n            set { m_indent = value; }\n        }\n\n        public void Line(LogType type, int level, ILogTarget target, string text0, int pos1 = 0, string text1 = null)\n        {\n            CurrentReporter(target).Line(type, level, target, text0, pos1, text1);\n        }\n\n        public void Text(int level, ILogTarget target, string text)\n        {\n            CurrentReporter(target).Text(level, target, text);\n        }\n\n        public void Wrap(int level, ILogTarget target, string text)\n        {\n            CurrentReporter(target).Wrap(level, target, text);\n        }\n\n        public ReportJob Begin(ReportJob parentJob, int level, ILogTarget target, string text, bool timed, bool noLog = false)\n        {\n            return CurrentReporter(target).Begin(parentJob, level, target, text, timed, noLog);\n        }\n\n        public double End(int level, ILogTarget target, string text, bool addTimeToParent)\n        {\n            return CurrentReporter(target).End(level, target, text, addTimeToParent);\n        }\n\n        public void Tests(TestInfo testInfo)\n        {\n            CurrentReporter().Tests(testInfo);\n        }\n\n        public void Progress(int level, ILogTarget target, double progress, bool relative = false)\n        {\n            CurrentReporter(target).Progress(level, target, progress, relative);\n        }\n\n        public void Values(int level, ILogTarget target, string name, string separator, object[] values)\n        {\n            CurrentReporter(target).Values(level, target, name, separator, values);\n        }\n\n        public void AddReporter(IReporter reporter)\n        {\n            CurrentReporter().AddReporter(reporter);\n        }\n\n        public void RemoveReporter(IReporter reporter)\n        {\n            CurrentReporter().RemoveReporter(reporter);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/PerThreadLogTarget.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public class PerThreadLogTarget : ILogTarget\n    {\n        private volatile ILogTarget[] m_targetArray;\n        readonly Func<int, ILogTarget> m_targetCreator;\n\n        #region Constructor\n\n        public PerThreadLogTarget(Func<int, ILogTarget> targetCreator)\n        {\n            m_targetArray = null;\n            m_targetCreator = targetCreator;\n        }\n\n        #endregion\n\n        #region ILogTarget\n\n        public void NewThreadIndex(int threadIndex)\n        {\n            m_targetArray = m_targetArray.With(threadIndex, m_targetCreator(threadIndex));\n        }\n\n        public void Log(int threadIndex, LogMsg msg)\n        {\n            m_targetArray[threadIndex].Log(threadIndex, msg);\n        }\n\n        public void Dispose()\n        {\n            for (int i = 0; i < m_targetArray.Length; i++)\n                if (m_targetArray != null)\n                    m_targetArray[i].Dispose();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/Report.cs",
    "content": "﻿using System;\r\nusing System.ComponentModel;\r\nusing System.Globalization;\r\nusing System.IO;\r\n#if __ANDROID__\r\nusing Log = Android.Util.Log;\r\n#endif\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// This class makes it possible to report messages with different\r\n    /// verbosity levels to the console or a stream.\r\n    /// \r\n    /// In the simplest case, you can start by reporting single line messages\r\n    /// with a level Report.Line. The level gives an\r\n    /// indication of how important this message is: a value of 0 indicates\r\n    /// that this is a message of utmost importance that cannot be suppressed.\r\n    /// The higher the level, the lower the importance of the message. In the\r\n    /// default case only messages of level 0, 1 and 2 are actually reported.\r\n    ///\r\n    /// The following use of levels is suggested:\r\n    /// \r\n    ///     0 ... unsupressable message of utmost importance (e.g warning),\r\n    ///     1 ... very short output,\r\n    ///     2 ... short output (this is the default level),\r\n    ///     3 ... normal output,\r\n    ///     4 ... detailed output,\r\n    ///     5-9 ... debugging levels\r\n    /// \r\n    /// The static Report class wraps all methods to a concrete reporter that\r\n    /// performs the actual reporting. The default reporting setup consists\r\n    /// of a console reporter at verbosity level 2, and a file reporter at\r\n    /// reporting level 9 that writes it contents to the file\r\n    /// \"Aardvark.log\". Each thread gets its own reporters, which report to\r\n    /// the logs in a synchronized manner. In order to globally change the\r\n    /// console report level, you can just conveniently use the static\r\n    /// Verbosity property.\r\n    /// </summary>\r\n    public static class Report\r\n    {\r\n        #region\r\n        /// <summary>\r\n        /// Breaks and throws an exception on error if a debugger is attached.\r\n        /// </summary>\r\n        public static bool ThrowOnError = false;\r\n        #endregion\r\n\r\n        #region Telemetry\r\n        \r\n        public static Telemetry.Counter CountCallsToBeginTimed = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToBegin = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToEnd = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToLine = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToText = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToWarn = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToDebug = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToTrace = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToError = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToFatal = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToValues = new Telemetry.Counter();\r\n        public static Telemetry.Counter CountCallsToProgress = new Telemetry.Counter();\r\n\r\n        static Report()\r\n        {\r\n            Telemetry.Register(\"Report: BeginTimed\", CountCallsToBeginTimed);\r\n            Telemetry.Register(\"Report: BeginTimed/s\", CountCallsToBeginTimed.RatePerSecond());\r\n            Telemetry.Register(\"Report: Begin\", CountCallsToBegin);\r\n            Telemetry.Register(\"Report: Begin/s\", CountCallsToBegin.RatePerSecond());\r\n            Telemetry.Register(\"Report: End\", CountCallsToEnd);\r\n            Telemetry.Register(\"Report: End/s\", CountCallsToEnd.RatePerSecond());\r\n            Telemetry.Register(\"Report: Line\", CountCallsToLine);\r\n            Telemetry.Register(\"Report: Line/s\", CountCallsToLine.RatePerSecond());\r\n            Telemetry.Register(\"Report: Text\", CountCallsToText);\r\n            Telemetry.Register(\"Report: Text/s\", CountCallsToText.RatePerSecond());\r\n            Telemetry.Register(\"Report: Warn\", CountCallsToWarn);\r\n            Telemetry.Register(\"Report: Warn/s\", CountCallsToWarn.RatePerSecond());\r\n            Telemetry.Register(\"Report: Debug\", CountCallsToDebug);\r\n            Telemetry.Register(\"Report: Debug/s\", CountCallsToDebug.RatePerSecond());\r\n            Telemetry.Register(\"Report: Trace\", CountCallsToTrace);\r\n            Telemetry.Register(\"Report: Trace/s\", CountCallsToTrace.RatePerSecond());\r\n            Telemetry.Register(\"Report: Error\", CountCallsToError);\r\n            Telemetry.Register(\"Report: Error/s\", CountCallsToError.RatePerSecond());\r\n            Telemetry.Register(\"Report: Fatal\", CountCallsToFatal);\r\n            Telemetry.Register(\"Report: Fatal/s\", CountCallsToFatal.RatePerSecond());\r\n            Telemetry.Register(\"Report: Values\", CountCallsToValues);\r\n            Telemetry.Register(\"Report: Values/s\", CountCallsToValues.RatePerSecond());\r\n            Telemetry.Register(\"Report: Progress\", CountCallsToProgress);\r\n            Telemetry.Register(\"Report: Progress/s\", CountCallsToProgress.RatePerSecond());\r\n\r\n            try\r\n            {\r\n                s_defaultForeground = Console.ForegroundColor;\r\n                s_defaultBackground = Console.BackgroundColor;\r\n                s_coloredConsole = true;\r\n            }\r\n            catch\r\n            {\r\n                s_coloredConsole = false;\r\n                s_defaultForeground = ConsoleColor.White;\r\n                s_defaultBackground = ConsoleColor.Black;\r\n            }\r\n\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Static Report Targets\r\n\r\n        public static readonly PerThreadJobReporter ThreadedJobReporter = new PerThreadJobReporter { Indent = 2 };\r\n        public static readonly JobReporter JobReporter = new JobReporter { Indent = 2 };\r\n\r\n        /// <summary>\r\n        /// By assigning this property multi-threaded reporting can be turned on or off.\r\n        /// This is mainly a feature for cosmetic and performance reasons of single-\r\n        /// threaded applciations.\r\n        /// </summary>\r\n        public static bool MultiThreaded\r\n        {\r\n            get { return s_reporter is PerThreadJobReporter; }\r\n            set { s_reporter = value ? (IJobReporter)ThreadedJobReporter : (IJobReporter)JobReporter; }\r\n        }\r\n\r\n        private static IJobReporter s_reporter = ThreadedJobReporter;\r\n\r\n        public static void ConsoleWriteAct(int threadIndex, LogType type, int level, string message)\r\n        {\r\n            Console.Write(message); Console.Out.Flush();\r\n        }\r\n\r\n        private static readonly bool s_coloredConsole;\r\n        private static readonly ConsoleColor s_defaultForeground;\r\n        private static readonly ConsoleColor s_defaultBackground;\r\n\r\n\r\n#if !__ANDROID__\r\n\r\n        public static void ConsoleColoredWriteAct(int threadIndex, LogType type, int level, string message)\r\n        {\r\n            if(!s_coloredConsole)\r\n            {\r\n                ConsoleWriteAct(threadIndex, type, level, message);\r\n                return;\r\n            }\r\n\r\n            bool resetBackground = false;\r\n            switch (type)\r\n            {\r\n                case LogType.Fatal:\r\n                    {\r\n                        Console.ForegroundColor = ConsoleColor.Black;\r\n                        Console.BackgroundColor = ConsoleColor.Red;\r\n                        resetBackground = true;\r\n                        break;\r\n                    }\r\n                case LogType.Error: Console.ForegroundColor = ConsoleColor.Red; break;\r\n                case LogType.Warn: Console.ForegroundColor = ConsoleColor.Yellow; break;\r\n                case LogType.Info:\r\n                    switch (level)\r\n                    {\r\n                        case 0: Console.ForegroundColor = s_defaultForeground; break;\r\n                        case 1: Console.ForegroundColor = ConsoleColor.Gray; break;\r\n                        case 2: Console.ForegroundColor = ConsoleColor.DarkGray; break;\r\n                        default: Console.ForegroundColor = ConsoleColor.DarkGreen; break;\r\n                    }\r\n                    break;\r\n                default: Console.ForegroundColor = s_defaultForeground; break;\r\n            }\r\n            Console.Write(message);\r\n            Console.ForegroundColor = s_defaultForeground;\r\n            if (resetBackground) Console.BackgroundColor = s_defaultBackground;\r\n            Console.Out.Flush();\r\n        }\r\n\r\n        public static void ConsoleForegroundColoredWriteAct(\r\n                int threadIndex, LogType type, int level, string message)\r\n        {\r\n            if (!s_coloredConsole)\r\n            {\r\n                ConsoleWriteAct(threadIndex, type, level, message);\r\n                return;\r\n            }\r\n            switch (type)\r\n            {\r\n                case LogType.Fatal: Console.ForegroundColor = ConsoleColor.Red; break;\r\n                case LogType.Error: Console.ForegroundColor = ConsoleColor.Red; break;\r\n                case LogType.Warn: Console.ForegroundColor = ConsoleColor.Yellow; break;\r\n                case LogType.Info:\r\n                    switch (level)\r\n                    {\r\n                        case 0: Console.ForegroundColor = s_defaultForeground; break;\r\n                        case 1: Console.ForegroundColor = ConsoleColor.Gray; break;\r\n                        case 2: Console.ForegroundColor = ConsoleColor.DarkGray; break;\r\n                        default: Console.ForegroundColor = ConsoleColor.DarkGreen; break;\r\n                    }\r\n                    break;\r\n                default: Console.ForegroundColor = s_defaultForeground; break;\r\n            }\r\n            Console.Write(message);\r\n            Console.ForegroundColor = s_defaultForeground;\r\n            Console.Out.Flush();\r\n        }\r\n\r\n#else\r\n\r\n\t\tpublic static void ConsoleColoredWriteAct(int threadIndex, LogType type, int level, string message)\r\n\t\t{\r\n\t\t\tLog.Verbose (\"Aardvark\", \"{0}\", message);\r\n\t\t}\r\n\r\n\t\tpublic static void ConsoleForegroundColoredWriteAct(int threadIndex, LogType type, int level, string message)\r\n\t\t{\r\n\t\t\tLog.Verbose (\"Aardvark\", \"{0}\", message);\r\n\t\t}\r\n\r\n#endif\r\n\r\n        // Note that TextLogTarget needs to be created with a writer function that\r\n        // gets the (type, level, message) triple as parameter. The writer functions\r\n        // flush their output in order to provide output even if incomplete lines are\r\n        // sent.\r\n\r\n        public static readonly TextLogTarget ConsoleTarget =\r\n                new TextLogTarget(ConsoleColoredWriteAct)\r\n                { Width = 80, Verbosity = 2, AllowBackspace = true, };\r\n\r\n        public static readonly TextLogTarget TraceTarget =\r\n                new TextLogTarget((i, t, l, m) => {\r\n                    System.Diagnostics.Debug.Write(m);\r\n                    System.Diagnostics.Debug.Flush();\r\n                })\r\n                { Width = 100, Verbosity = 15, /* LogCompleteLinesOnly = true, */ };\r\n\r\n        /// <summary>\r\n        /// The LogFileName may be modified before the first log message is written.\r\n        /// </summary>\r\n        public static string LogFileName = @\"Aardvark.log\";\r\n\r\n        /// <summary>\r\n        /// Creates a stream writer writing to LogFileName but retries, if file is\r\n        /// already open by another instance.\r\n        /// </summary>\r\n        private static StreamWriter CreateLogFileWriter(string fileName, int cnt)\r\n        {\r\n            if (cnt > 5)\r\n                throw new Exception(\"Could not create writer (many instances running?)\");\r\n\r\n            try\r\n            {\r\n                var dir = Path.GetDirectoryName(fileName);\r\n\r\n                if (!dir.IsNullOrEmpty() && !Directory.Exists(dir))\r\n                {\r\n                    Directory.CreateDirectory(dir);\r\n                }\r\n\r\n                var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read);\r\n                return new StreamWriter(stream);\r\n            }\r\n\r\n            catch (IOException)\r\n            {\r\n                return CreateLogFileWriter(string.Format(\"{0}_{1}\", fileName, cnt), cnt + 1);\r\n            }\r\n            catch (UnauthorizedAccessException)\r\n            {\r\n                var dir = Path.Combine(Path.GetTempPath(), \"Aardvark\", \"logs\");\r\n                if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);\r\n\r\n                var now = DateTime.Now.ToString(\"yyyy-MM-dd-HH-mm-ss-fffffff\");\r\n                var name = Path.Combine(dir, now);\r\n                return CreateLogFileWriter(name, cnt + 1);\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// The LogTarget opens the log file on the first logging write, so that it can\r\n        /// be deactivated before first use by calling Report.Targets.Remove(Report.LogTarget)\r\n        /// without leaving an empty log file\r\n        /// </summary>\r\n        public readonly static TextLogTarget LogTarget\r\n                 = new TextLogTarget((firstThreadIndex, firstType, firstLevel, firstMessage) =>\r\n                 {\r\n                     StreamWriter writer = CreateLogFileWriter(LogFileName, 0);\r\n                     LogTarget.WriteAct = (i, t, l, m) =>\r\n                     {\r\n                         try\r\n                         {\r\n                             writer.Write(m); writer.Flush();\r\n                         }\r\n                         catch (ObjectDisposedException) // in finalization, finalizers which perform logging fail due to non deterministic finalization order\r\n                         { }\r\n                     };\r\n                     LogTarget.WriteAct(firstThreadIndex, firstType, firstLevel, firstMessage);\r\n                 })\r\n                 { Width = 100, Verbosity = 9 };\r\n\r\n        public static string PerThreadLogName = @\"Aardvark_{0}.log\";\r\n        public readonly static PerThreadLogTarget PerThreadLogTarget =\r\n            new PerThreadLogTarget(CreatePerThreadLogTarget);\r\n\r\n        private static TextLogTarget CreatePerThreadLogTarget(int index)\r\n        {\r\n            TextLogTarget logTarget =\r\n                new TextLogTarget(null, index) { Width = 100, Verbosity = 9, Synchronized = false };\r\n            logTarget.WriteAct = (firstThreadIndex, firstType, firstLevel, firstMessage) =>\r\n            {\r\n                var writer = new StreamWriter(\r\n                    new FileStream(String.Format(PerThreadLogName, firstThreadIndex),\r\n                                   FileMode.Create, FileAccess.Write, FileShare.Read));\r\n                logTarget.WriteAct = (i, t, l, m) => { writer.Write(m); writer.Flush(); };\r\n                logTarget.WriteAct(firstThreadIndex, firstType, firstLevel, firstMessage);\r\n            };\r\n            return logTarget;\r\n        }\r\n\r\n        /// <summary>\r\n        /// You can add and remove log targets by adding or removing them from Targets.\r\n        /// </summary>\r\n        public readonly static MultiLogTarget Targets = new MultiLogTarget(ConsoleTarget, LogTarget);\r\n\r\n        public static readonly ILogTarget NoTarget = new MultiLogTarget();\r\n\r\n        /// <summary>\r\n        /// If you only want a single log target, you can assign it to the RootTarget.\r\n        /// </summary>\r\n        public static ILogTarget RootTarget = Targets;\r\n\r\n#endregion\r\n\r\n        #region Static Reporting Methods\r\n\r\n        /// <summary>\r\n        /// A shortcut for the verbosity of the ConsoleTarget.\r\n        /// </summary>\r\n        public static int Verbosity\r\n        {\r\n            get { return ConsoleTarget.Verbosity; }\r\n            set { ConsoleTarget.Verbosity = value; }\r\n        }\r\n\r\n        private static string Format(string message, params object[] args)\r\n        {\r\n            if (args.Length == 0) return message;\r\n\r\n\r\n            try\r\n            {\r\n                return String.Format(CultureInfo.InvariantCulture, message, args);\r\n            }\r\n            catch (FormatException)\r\n            {\r\n                Report.Warn(\"Report FormatException in \\\"{0}\\\"\", message);\r\n                return message;\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message that will only be logged at the end of the job.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static ReportJob JobTimedNoBeginLog(ReportJob parentJob, int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            return s_reporter.Begin(parentJob, level, RootTarget, Format(message, args), true, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message that will only be logged at the end of the job.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static ReportJob JobTimedNoBeginLog(ReportJob parentJob, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            return s_reporter.Begin(parentJob, 0, RootTarget, Format(message, args), true, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static ReportJob JobTimed(ReportJob parentJob, int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            return s_reporter.Begin(parentJob, level, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static ReportJob JobTimed(ReportJob parentJob, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            return s_reporter.Begin(parentJob, 0, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static ReportJob Job(ReportJob parentJob, int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            return s_reporter.Begin(parentJob, level, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static ReportJob Job(ReportJob parentJob, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            return s_reporter.Begin(parentJob, 0, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message that will only be logged at the end of the job.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static ReportJob JobTimedNoBeginLog(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            return s_reporter.Begin(null, level, RootTarget, Format(message, args), true, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message that will only be logged at the end of the job.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static ReportJob JobTimedNoBeginLog([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            return s_reporter.Begin(null, 0, RootTarget, Format(message, args), true, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static ReportJob JobTimed(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            return s_reporter.Begin(null, level, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static ReportJob JobTimed([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            return s_reporter.Begin(null, 0, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static ReportJob Job(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            return s_reporter.Begin(null, level, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static ReportJob Job([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            return s_reporter.Begin(null, 0, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message that will only be logged at the end of the job.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static void BeginTimedNoLog(ReportJob parentJob, int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            s_reporter.Begin(parentJob, level, RootTarget, Format(message, args), true, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message that will only be logged at the end of the job.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static void BeginTimedNoLog(ReportJob parentJob, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            s_reporter.Begin(parentJob, 0, RootTarget, Format(message, args), true, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static void BeginTimed(ReportJob parentJob, int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            s_reporter.Begin(parentJob, level, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static void BeginTimed(ReportJob parentJob, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            s_reporter.Begin(parentJob, 0, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static void Begin(ReportJob parentJob, int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            s_reporter.Begin(parentJob, level, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static void Begin(ReportJob parentJob, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            s_reporter.Begin(parentJob, 0, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n\r\n        /// <summary>\r\n        /// Begin a block without an explicit message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static void Begin(ReportJob parentJob, int level)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            s_reporter.Begin(parentJob, level, RootTarget, \"\", false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block without an explicit message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static void Begin(ReportJob parentJob)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            s_reporter.Begin(parentJob, 0, RootTarget, \"\", false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message that will only be logged at the end of the job.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static void BeginTimedNoLog(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            s_reporter.Begin(null, level, RootTarget, Format(message, args), true, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message that will only be logged at the end of the job.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static void BeginTimedNoLog([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            s_reporter.Begin(null, 0, RootTarget, Format(message, args), true, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static void BeginTimed(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            s_reporter.Begin(null, level, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a timed block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// At the <see cref=\"End()\"/> of the block the run time is reported.\r\n        /// </summary>\r\n        public static void BeginTimed([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBeginTimed.Increment();\r\n            s_reporter.Begin(null, 0, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static void Begin(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            s_reporter.Begin(null, level, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block with a formatted message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static void Begin([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            s_reporter.Begin(null, 0, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n\r\n        /// <summary>\r\n        /// Begin a block without an explicit message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static void Begin(int level)\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            s_reporter.Begin(null, level, RootTarget, \"\", false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Begin a block without an explicit message.\r\n        /// All report calls till the call to the next\r\n        /// <see cref=\"End()\"/> are either indented (console/stream) or\r\n        /// hierarchical children of this block (treeview).\r\n        /// </summary>\r\n        public static void Begin()\r\n        {\r\n            CountCallsToBegin.Increment();\r\n            s_reporter.Begin(null, 0, RootTarget, \"\", false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Ends a block of messages. If the block was timed, its runtime is\r\n        /// reported. The End call MUST use the same level as the\r\n        /// corresponding Begin/BeginTimed. The runtime in seconds is also returned.\r\n        /// </summary>\r\n        public static double End(int level)\r\n        {\r\n            CountCallsToEnd.Increment();\r\n            return s_reporter.End(level, RootTarget, null, false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Ends a block of messages. If the block was timed, its runtime is\r\n        /// reported. The End call MUST use the same level as the\r\n        /// corresponding Begin/BeginTimed. The runtime in seconds is also returned.\r\n        /// </summary>\r\n        public static double End()\r\n        {\r\n            CountCallsToEnd.Increment();\r\n            return s_reporter.End(0, RootTarget, null, false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Ends a block of messages, and supply an end message. If the end\r\n        /// message is the very same as the begin message it is suppressed.\r\n        /// If the end message starts with a continuation character (a space,\r\n        /// a colon or a comma), it is viewed as a continuation message of\r\n        /// the begin message, and appended as appropriate. If it is not the\r\n        /// same and does not start with a continuation character, it is used\r\n        /// as a distinct end message.\r\n        /// </summary>\r\n        public static double End(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToEnd.Increment();\r\n            return s_reporter.End(level, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Ends a block of messages, and supply an end message. If the end\r\n        /// message is the very same as the begin message it is suppressed.\r\n        /// If the end message starts with a continuation character (a space,\r\n        /// a colon or a comma), it is viewed as a continuation message of\r\n        /// the begin message, and appended as appropriate. If it is not the\r\n        /// same and does not start with a continuation character, it is used\r\n        /// as a distinct end message.\r\n        /// </summary>\r\n        public static double End([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToEnd.Increment();\r\n            return s_reporter.End(0, RootTarget, Format(message, args), false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Ends a block of messages. If the block was timed, its runtime is\r\n        /// reported. The End call MUST use the same level as the\r\n        /// corresponding Begin/BeginTimed. The runtime in seconds is also returned.\r\n        /// </summary>\r\n        public static double EndTimed(int level)\r\n        {\r\n            CountCallsToEnd.Increment();\r\n            return s_reporter.End(level, RootTarget, null, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Ends a block of messages. If the block was timed, its runtime is\r\n        /// reported. The End call MUST use the same level as the\r\n        /// corresponding Begin/BeginTimed. The runtime in seconds is also returned.\r\n        /// </summary>\r\n        public static double EndTimed()\r\n        {\r\n            CountCallsToEnd.Increment();\r\n            return s_reporter.End(0, RootTarget, null, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Ends a block of messages, and supply an end message. If the end\r\n        /// message is the very same as the begin message it is suppressed.\r\n        /// If the end message starts with a continuation character (a space,\r\n        /// a colon or a comma), it is viewed as a continuation message of\r\n        /// the begin message, and appended as appropriate. If it is not the\r\n        /// same and does not start with a continuation character, it is used\r\n        /// as a distinct end message.\r\n        /// </summary>\r\n        public static double EndTimed(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToEnd.Increment();\r\n            return s_reporter.End(level, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Ends a block of messages, and supply an end message. If the end\r\n        /// message is the very same as the begin message it is suppressed.\r\n        /// If the end message starts with a continuation character (a space,\r\n        /// a colon or a comma), it is viewed as a continuation message of\r\n        /// the begin message, and appended as appropriate. If it is not the\r\n        /// same and does not start with a continuation character, it is used\r\n        /// as a distinct end message.\r\n        /// </summary>\r\n        public static double EndTimed([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToEnd.Increment();\r\n            return s_reporter.End(0, RootTarget, Format(message, args), true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a single message line with formatted parameters.\r\n        /// </summary>\r\n        public static void Line(int level, [Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToLine.Increment();\r\n            s_reporter.Line(LogType.Info, level, RootTarget, Format(line, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a single message line with formatted parameters.\r\n        /// </summary>\r\n        public static void Line([Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToLine.Increment();\r\n            s_reporter.Line(LogType.Info, 0, RootTarget, Format(line, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report an empty line or end the line after using Text.\r\n        /// </summary>\r\n        public static void Line(int level)\r\n        {\r\n            CountCallsToLine.Increment();\r\n            s_reporter.Line(LogType.Info, level, RootTarget, \"\");\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report an empty line or end the line after using Text.\r\n        /// </summary>\r\n        public static void Line()\r\n        {\r\n            CountCallsToLine.Increment();\r\n            s_reporter.Line(LogType.Info, 0, RootTarget, \"\");\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a (possibly multilined) message with formatted parameters.\r\n        /// </summary>\r\n        public static void Text(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToText.Increment();\r\n            s_reporter.Text(level, RootTarget, Format(message, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a (possibly multilined) message with formatted parameters.\r\n        /// </summary>\r\n        public static void Text([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToText.Increment();\r\n            s_reporter.Text(0, RootTarget, Format(message, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a message that will be written in the current line if it fits, or in\r\n        /// the next line (with correct indent) if it does not fit.\r\n        /// </summary>\r\n        public static void Wrap(int level, [Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToText.Increment();\r\n            s_reporter.Wrap(level, RootTarget, Format(message, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a message that will be written in the current line if it fits, or in\r\n        /// the next line (with correct indent) if it does not fit.\r\n        /// </summary>\r\n        public static void Wrap([Localizable(true)] string message, params object[] args)\r\n        {\r\n            CountCallsToText.Increment();\r\n            s_reporter.Wrap(0, RootTarget, Format(message, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Write a warning. Warnings are at level 0 and cannot be\r\n        /// suppressed.\r\n        /// </summary>\r\n        public static void Warn([Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToWarn.Increment();\r\n            s_reporter.Line(LogType.Warn, 0, RootTarget, \"WARNING:\", 0, Format(line, args));\r\n        }\r\n\r\n\r\n        /// <summary>\r\n        /// Write a warning. Warnings are at level 0 and cannot be\r\n        /// suppressed.\r\n        /// </summary>\r\n        public static void WarnNoPrefix([Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToWarn.Increment();\r\n            s_reporter.Line(LogType.Warn, 0, RootTarget, \"\", 0, Format(line, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Write a debug message.\r\n        /// </summary>\r\n        public static void Debug([Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToDebug.Increment();\r\n            s_reporter.Line(LogType.Debug, 0, RootTarget, \"Debug:\", 0, Format(line, args));\r\n        }\r\n        /// <summary>\r\n        /// Write a debug message.\r\n        /// </summary>\r\n        public static void DebugNoPrefix([Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToDebug.Increment();\r\n            s_reporter.Line(LogType.Debug, 0, RootTarget, \"\", 0, Format(line, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Write a debug message.\r\n        /// </summary>\r\n        public static void Debug(int level, [Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToDebug.Increment();\r\n            s_reporter.Line(LogType.Debug, level, RootTarget, \"Debug:\", 0, Format(line, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Write a debug message.\r\n        /// </summary>\r\n        public static void Trace([Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToTrace.Increment();\r\n            s_reporter.Line(LogType.Trace, 0, RootTarget, \"Trace:\", 0, Format(line, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Write a debug message.\r\n        /// </summary>\r\n        public static void Trace(int level, [Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToTrace.Increment();\r\n            s_reporter.Line(LogType.Trace, level, RootTarget, \"Trace:\", 0, Format(line, args));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Write an error. Errors are at level 0 and cannot be\r\n        /// suppressed. More serious than a Warning, the program commences.\r\n        /// </summary>\r\n        public static void Error([Localizable(true)] string line, params object[] args)\r\n        {\r\n            var output = Format(line, args);\r\n            CountCallsToError.Increment();\r\n            s_reporter.Line(LogType.Error, 0, RootTarget, \"ERROR:\", 0, output);\r\n            if (ThrowOnError)\r\n            {\r\n                System.Diagnostics.Debugger.Break();\r\n                if (System.Diagnostics.Debugger.IsAttached)\r\n                {\r\n                    throw new Exception(output);\r\n                }\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// Write an error. Errors are at level 0 and cannot be\r\n        /// suppressed. More serious than a Warning, the program commences.\r\n        /// </summary>\r\n        public static void ErrorNoPrefix([Localizable(true)] string line, params object[] args)\r\n        {\r\n            var output = Format(line, args);\r\n            CountCallsToError.Increment();\r\n            s_reporter.Line(LogType.Error, 0, RootTarget, \"\", 0, output);\r\n            if (ThrowOnError)\r\n            {\r\n                System.Diagnostics.Debugger.Break();\r\n                if (System.Diagnostics.Debugger.IsAttached)\r\n                {\r\n                    throw new Exception(output);\r\n                }\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a critical failure and break into the debugger, if\r\n        /// one is attached.\r\n        /// </summary>\r\n        public static void Fatal([Localizable(true)] string line, params object[] args)\r\n        {\r\n            CountCallsToFatal.Increment();\r\n\r\n            s_reporter.Line(LogType.Fatal, 0, RootTarget, \"CRITICAL ERROR:\", 0, Format(line, args));\r\n            /* System.Diagnostics.StackTrace trace = */\r\n            new System.Diagnostics.StackTrace(1);\r\n\r\n            if (System.Diagnostics.Debugger.IsAttached)\r\n                System.Diagnostics.Debugger.Break();\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public static void Progress(int level, double progress)\r\n        {\r\n            CountCallsToProgress.Increment();\r\n            s_reporter.Progress(level, RootTarget, progress, false);\r\n        }\r\n\r\n        public static void Progress(double progress)\r\n        {\r\n            CountCallsToProgress.Increment();\r\n            s_reporter.Progress(0, RootTarget, progress, false);\r\n        }\r\n\r\n        public static void ProgressDelta(int level, double progressDelta)\r\n        {\r\n            CountCallsToProgress.Increment();\r\n            s_reporter.Progress(level, RootTarget, progressDelta, true);\r\n        }\r\n\r\n        public static void ProgressDelta(double progressDelta)\r\n        {\r\n            CountCallsToProgress.Increment();\r\n            s_reporter.Progress(0, RootTarget, progressDelta, true);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a single, named, reportable value.\r\n        /// </summary>\r\n        public static void Value(int level, [Localizable(true)] string name, IReportable reportable)\r\n        {\r\n            CountCallsToValues.Increment();\r\n            reportable.ReportValue(level, name);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a single, named, reportable value.\r\n        /// </summary>\r\n        public static void Value([Localizable(true)] string name, IReportable reportable)\r\n        {\r\n            CountCallsToValues.Increment();\r\n            reportable.ReportValue(0, name);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a single, named, formattable value.\r\n        /// </summary>\r\n        public static void Value(int level, [Localizable(true)] string name, object value)\r\n        {\r\n            CountCallsToValues.Increment();\r\n            s_reporter.Values(level, RootTarget, name, null, value.IntoArray());\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a single, named, formattable value.\r\n        /// </summary>\r\n        public static void Value([Localizable(true)] string name, object value)\r\n        {\r\n            CountCallsToValues.Increment();\r\n            s_reporter.Values(0, RootTarget, name, null, value.IntoArray());\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a sequence of formattable values.\r\n        /// </summary>\r\n        public static void Values(int level, [Localizable(true)] string name, string separator, params object[] values)\r\n        {\r\n            CountCallsToValues.Increment();\r\n            s_reporter.Values(level, RootTarget, name, separator, values);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Report a sequence of formattable values.\r\n        /// </summary>\r\n        public static void Values([Localizable(true)] string name, string separator, params object[] values)\r\n        {\r\n            CountCallsToValues.Increment();\r\n            s_reporter.Values(0, RootTarget, name, separator, values);\r\n        }\r\n\r\n        public static void Tests(TestInfo testInfo)\r\n        {\r\n            s_reporter.Tests(testInfo);\r\n        }\r\n\r\n        public static void Tests()\r\n        {\r\n            s_reporter.Tests(TestInfo.Empty);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Adds the reporter to report for the current active thread.\r\n        /// </summary>\r\n        public static void AddReporter(IReporter reporter)\r\n        {\r\n            s_reporter.AddReporter(reporter);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Removes the reporter to report for the current active thread.\r\n        /// </summary>\r\n        public static void RemoveReporter(IReporter reporter)\r\n        {\r\n            s_reporter.RemoveReporter(reporter);\r\n        }\r\n\r\n#endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/ReportJob.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\n\nnamespace Aardvark.Base\n{\n    public class ReportJob : IDisposable\n    {\n        internal string Message;\n        public readonly int HierarchyLevel;\n        public readonly ReportJob ParentJob;\n        public double ChildrenTime;\n        internal int Level;\n        internal long StartTime = -1;\n        internal double Progress;\n        internal bool ReportTests;\n        internal TestInfo TestInfo;\n        internal bool Disposed;\n\n        internal bool IsTimed => StartTime >= 0;\n\n#if NET8_0_OR_GREATER\n        internal double ElapsedSeconds => Stopwatch.GetElapsedTime(StartTime).TotalSeconds;\n#else\n        internal double ElapsedSeconds => new TimeSpan((Stopwatch.GetTimestamp() - StartTime) * TimeSpan.TicksPerSecond / Stopwatch.Frequency).TotalSeconds;\n#endif\n\n        public ReportJob(string message, int level, bool timed, ReportJob parentJob = null)\n        {\n            Disposed = false;\n            Message = message;\n            ParentJob = parentJob;\n            ChildrenTime = 0.0;\n            HierarchyLevel = parentJob == null ? 0 : parentJob.HierarchyLevel + 1;\n            Level = level;\n            Progress = -1.0;\n            ReportTests = false;\n            TestInfo = default(TestInfo);\n                        \n            if (timed)\n                StartTime = Stopwatch.GetTimestamp();\n        }\n\n        public void Dispose() { if (!Disposed) Report.End(Level); }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/Skipper.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// This small struct helps to optimize the number of calls to Report.Progress.\n    /// If you initialize it with a value of N, each Nth call of <see cref=\"Skipper.Do\"/>\n    /// will return true.\n    /// </summary>\n    public struct Skipper\n    {\n        int m_count;\n        readonly int m_limit;\n\n        #region Constructor\n\n        /// <summary>\n        /// Initialize a skipper that results true every Nth call to Do.\n        /// </summary>\n        /// <param name=\"limit\">N</param>\n        public Skipper(int limit)\n        {\n            m_count = limit;\n            m_limit = limit;\n        }\n\n        #endregion\n\n        #region Do\n\n        public readonly bool HasDone\n        {\n            get { return m_count == m_limit; }\n        }\n\n        public bool Do\n        {\n            get\n            {\n                if (--m_count > 0) return false;\n                m_count = m_limit;\n                return true;\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/TestInfo.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// A container for passed and failed counts.\n    /// </summary>\n    public struct TestInfo\n    {\n        public long PassedCount;\n        public long FailedCount;\n\n        #region Constructor\n\n        public TestInfo(long passed, long failed)\n        {\n            PassedCount = passed; FailedCount = failed;\n        }\n\n        #endregion\n\n        #region Operations\n\n        public readonly long TestCount { get { return PassedCount + FailedCount; } }\n\n        public static TestInfo operator +(TestInfo a, TestInfo b)\n        {\n            return new TestInfo(a.PassedCount + b.PassedCount,\n                                a.FailedCount + b.FailedCount);\n        }\n\n        public static readonly TestInfo Empty = new TestInfo(0, 0);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Reporting/TextLogTarget.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing static System.Math;\n\nnamespace Aardvark.Base\n{\n    public class TextLogTarget : ILogTarget\n    {\n        private readonly object m_lock;\n        private ReportState m_state;\n        private readonly Dictionary<int, ReportState> m_stateTable;\n        public Action<int, LogType, int, string> WriteAct;\n        private int m_width = 80;\n        private int m_maxIndent = 40;\n\n        public int Verbosity = 0;\n        public bool LogCompleteLinesOnly = false;\n        public bool AllowBackspace = false;\n        public bool Synchronized = true;\n        public Func<int, string> m_prefixFun = threadIndex => String.Format(\"{0,2:x}: \", threadIndex);\n\n        #region Constructor\n\n        public TextLogTarget(Action<int, LogType, int, string> write, int threadIndex = 0)\n        {\n            m_lock = new object();\n            m_state = new ReportState(threadIndex, m_prefixFun(threadIndex));\n            m_stateTable = new Dictionary<int, ReportState>();\n            WriteAct = write;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public int Width\n        {\n            get { return m_width; }\n            set { m_width = value; m_maxIndent = value / 2; }\n        }\n\n        public Func<int, string> PrefixFun\n        {\n            set\n            {\n                m_prefixFun = value; m_state.Prefix = value(m_state.TIdx);\n                m_state.PrefixLength = m_state.Prefix.Length;\n            }\n        }\n\n        #endregion\n\n        #region Constants\n\n        const int c_maxWidth = 160;\n        const string c_spaces160 =\n            \"                                                                                \"\n            + \"                                                                                \";\n        const string c_dots160 =\n            \"................................................................................\"\n            + \"................................................................................\";\n        const string c_back160 =\n            \"\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\"\n            + \"\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\"\n            + \"\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\"\n            + \"\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\"\n            + \"\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\"\n            + \"\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\"\n            + \"\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\"\n            + \"\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08\";\n\n        #endregion\n\n        #region ILogTarget\n\n        public void NewThreadIndex(int threadIndex)\n        {\n        }\n\n        public void Log(int threadIndex, LogMsg msg)\n        {\n            if (msg.Level > Verbosity) return;\n            if (!Synchronized) { Log(msg); return; }\n            lock (m_lock)\n            {\n                if (threadIndex != m_state.TIdx)\n                {\n                    if (m_state.Level <= Verbosity && m_state.Buffer.Length > 0 && !LogCompleteLinesOnly)\n                    {\n                        WriteAct(m_state.TIdx, m_state.Type, m_state.Level, \"\\n\"); // crlf for clean start\n                        m_state.DoneCount = 0; // trigger the line to be printed again by the thread later\n                    }\n                    if (!m_stateTable.TryGetValue(threadIndex, out m_state))\n                        m_stateTable[threadIndex] = m_state = new ReportState(threadIndex,\n                                                                              m_prefixFun(threadIndex));\n                }\n                Log(msg);\n            }\n        }\n\n        public void Dispose()\n        {\n            lock (m_lock)\n            {\n                if (m_state.Level <= Verbosity && m_state.Buffer.Length > 0)\n                    WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear());\n            }\n        }\n\n        #endregion\n\n        #region ReportState\n\n        private class ReportState\n        {\n            public int TIdx;\n            public string Prefix;\n            public int PrefixLength;\n            public LogType Type;\n            public int Level = 0;\n            public StringBuilder Buffer;\n            public bool Timed;\n            public int LeftPos;\n            public int RightPos;\n            public int DoneCount;\n\n            public ReportState(int threadIndex, string prefix)\n            {\n                TIdx = threadIndex; Type = LogType.Unknown; Level = 0;\n                Prefix = prefix;\n                PrefixLength = Prefix.Length;\n                Buffer = new StringBuilder(80); DoneCount = 0;\n            }\n\n            public void AddSpaceText(int pos, string text)\n            {\n                int len = Buffer.Length - PrefixLength;\n                var fillCount = pos < len ? 0 : pos - len;\n                if (fillCount > 0) Buffer.Append(c_spaces160, 0, fillCount);\n                Buffer.Append(text);\n            }\n\n            public void AddDotsText(int pos, string text, int width)\n            {\n                int len = Buffer.Length;\n                if (pos < 0) pos = width + pos - text.Length;\n                if (len > PrefixLength && Buffer[len - 1] != ' ') { Buffer.Append(' '); len += 1; }\n                var empty = text == \"\";\n                var fillCount = pos < len ? -1 : pos - len - 1 + (empty ? 1 : 0);\n                if (fillCount > 0) Buffer.Append(c_dots160, 0, fillCount);\n                if (fillCount >= 0 && !empty) Buffer.Append(' ');\n                Buffer.Append(text);\n            }\n\n            public string Backspace(int count)\n            {\n                if (count > Buffer.Length) count = Buffer.Length;\n                if (count > DoneCount) count = DoneCount;\n                Buffer.Length -= count; DoneCount -= count; return c_back160.Substring(160 - count);\n            }\n\n            public string GetBufferLineAndClear()\n            {\n                int pos = DoneCount; DoneCount = 0; Buffer.Append(\"\\r\\n\");\n                var text = Buffer.ToString(pos, Buffer.Length - pos);\n                Buffer.Clear();\n                return text;\n            }\n        }\n\n        #endregion\n\n        #region Log Message\n\n        public void Log(LogMsg msg)\n        {\n            if (msg.Type == LogType.End)\n            {\n                if (m_state.Buffer.Length > 0 &&\n                    (m_state.Type == LogType.Info\n                     || (m_state.Type != LogType.Unknown && m_state.LeftPos != msg.LeftPos))) // different indent == other job\n                    WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear());\n                if ((msg.Opt & (LogOpt.Timed | LogOpt.NewText)) == 0) return;// if End is not timed, suppress repeated start message\n            }\n            if (msg.Type == LogType.Progress && !AllowBackspace) msg.Opt |= LogOpt.EndLine;\n            if (LogCompleteLinesOnly)\n            {\n                if (msg.Type == LogType.Begin)\n                {\n                    msg.Opt = msg.Opt | LogOpt.EndLine; if ((msg.Opt & LogOpt.Timed) != 0) msg.RightText = \"\";\n                }\n                else if (msg.Type == LogType.Progress)\n                {\n                    msg.Opt = msg.Opt | LogOpt.EndLine;\n                }\n            }\n            else if (m_state.Type == LogType.Begin)\n            {\n                if (msg.Type == LogType.End)\n                {\n                    var pos = m_state.LeftPos + m_state.PrefixLength; var len = m_state.Buffer.Length - pos;\n                    if (len > 0 // len < 0 if we are from a different indent == other job\n                        && msg.LeftText.StartsWith(m_state.Buffer.ToString(pos, len)))\n                    {\n                        msg.LeftText = msg.LeftText.Substring(len); msg.LeftPos = 0;\n                    }\n                }\n                else if (msg.Type == LogType.Progress)\n                {\n                    msg.LeftText = null;\n                }\n                else if ((msg.Opt & LogOpt.Wrap) == 0)\n                {\n                    if (m_state.Timed) m_state.AddDotsText(m_state.RightPos, \"\", m_width); // dots to line end\n                    WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear());\n                }\n            }\n            else if (m_state.Type == LogType.Progress)\n            {\n                if (msg.Type == LogType.Progress)\n                {\n                    if (AllowBackspace)\n                    {\n                        if (m_state.DoneCount > 0)\n                        {\n                            WriteAct(m_state.TIdx, msg.Type, msg.Level, m_state.Backspace(msg.RightText.Length));\n                            msg.LeftText = null;\n                        }\n                        else\n                            m_state.Buffer.Clear();\n                    }\n                }\n                else if (msg.Type == LogType.End)\n                {\n                    if (AllowBackspace)\n                    {\n                        if (m_state.DoneCount > 0)\n                        {\n                            var len = m_state.Buffer.Length - m_state.PrefixLength - m_state.LeftPos;\n                            WriteAct(m_state.TIdx, msg.Type, msg.Level, m_state.Backspace(len));\n                        }\n                        else\n                            m_state.Buffer.Clear();\n                    }\n                }\n                else\n                    WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear());\n            }\n            if ((msg.Opt & LogOpt.Wrap) != 0)\n            {\n                if (m_state.Buffer.Length + msg.LeftText.Length + 1 > Width + msg.RightPos)\n                    WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear());\n                else if (m_state.Buffer.Length > 0 && m_state.Buffer[m_state.Buffer.Length - 1] != ' ')\n                    m_state.Buffer.Append(' ');\n            }\n            if (m_state.Buffer.Length == 0) m_state.Buffer.Append(m_state.Prefix);\n            if (msg.LeftText != null) m_state.AddSpaceText(Min(msg.LeftPos, m_maxIndent), msg.LeftText);\n            if (msg.RightText != null) m_state.AddDotsText(Min(msg.RightPos, m_width), msg.RightText, m_width);\n            if ((msg.Opt & LogOpt.EndLine) != 0)\n            {\n                WriteAct(m_state.TIdx, msg.Type, msg.Level, m_state.GetBufferLineAndClear());\n                m_state.Type = LogType.Unknown;\n            }\n            else\n            {\n                if (!LogCompleteLinesOnly)\n                {\n                    int pos = m_state.DoneCount; int len = m_state.Buffer.Length - pos;\n                    WriteAct(m_state.TIdx, msg.Type, msg.Level, m_state.Buffer.ToString(pos, len));\n                    m_state.DoneCount = pos + len;\n                }\n                m_state.Type = msg.Type;\n                m_state.Timed = (msg.Opt & LogOpt.Timed) != 0;\n                m_state.LeftPos = msg.LeftPos;\n                m_state.RightPos = msg.RightPos; // remember EndPos of timed begins for dotting to lineEnd\n            }\n            m_state.Level = msg.Level;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Sorting/ArrayExtensions.cs",
    "content": "﻿using Aardvark.Base.Sorting;\nusing System;\n\nnamespace Aardvark.Base\n{\n    public static class ComparableArrayExtensions\n    {\n        #region Comparable Array\n        \n\t\tpublic static int IndexOfNSmallest<T>(this T[] a, int n)\n            where T : IComparable<T>\n        {\n            if (n == 0) return a.IndexOfMin();\n            var p = a.CreatePermutationQuickMedianAscending(n);\n            return p[n];\n        }\n\n        public static int IndexOfNLargest<T>(this T[] a, int n)\n            where T : IComparable<T>\n        {\n            if (n == 0) return a.IndexOfMax();\n            var p = a.CreatePermutationQuickMedianDescending(n);\n            return p[n];\n        }\n        \n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Sorting/IEnumerableExtensions.cs",
    "content": "﻿using Aardvark.Base.Sorting;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    public static class IEnumerableSortingExtensions\n    {\n        public static SymbolSet ToSymbolSet(this IEnumerable<Symbol> symbols) => new SymbolSet(symbols);\n\n        public static bool SetEquals<T>(this IEnumerable<T> self, IEnumerable<T> other)\n        {\n            if (self == null && other != null) return false;\n            if (self != null && other == null) return false;\n            if (self.Count() != other.Count()) return false;\n            if (self.Count() != self.Distinct().Count()) throw new Exception(\"not a proper set\");\n            if (other.Count() != other.Distinct().Count()) throw new Exception(\"not a proper set\");\n\n            var tmp = new Dictionary<T, T>();\n            tmp.AddRange(self.Select(x => new KeyValuePair<T, T>(x, x)));\n            foreach (var x in other) if (!tmp.ContainsKey(x)) return false;\n\n            return true;\n        }\n\n        #region Median\n\n        /// <summary>\n        /// Searches for the median-element in the Enumerable (according to cmp) and returns its value.\n        /// Runtime is in O(N) and Memory in O(N)\n        /// For partitioning use QuickMedian\n        /// </summary>\n        public static T Median<T>(this IEnumerable<T> self, Func<T, T, int> cmp)\n        {\n            var array = self.ToArray();\n            var med = array.Length / 2;\n\n            array.QuickMedian(cmp, med);\n\n            var result = array[med];\n            array = null;\n\n            return result;\n        }\n\n        /// <summary>\n        /// Searches for the median-element in the Enumerable and returns its value.\n        /// Runtime is in O(N) and Memory in O(N)\n        /// For partitioning use QuickMedian\n        /// </summary>\n        public static T Median<T>(this IEnumerable<T> self) where T : IComparable<T>\n            => Median(self, (a, b) => a.CompareTo(b));\n\n        /// <summary>\n        /// Searches for the median-element in the Array (according to cmp) and returns its value.\n        /// Does not change the given Array\n        /// Runtime is in O(N) and Memory in O(N)\n        /// For partitioning use QuickMedian\n        /// </summary>\n        public static T Median<T>(this T[] self, Func<T, T, int> cmp)\n        {\n            var med = self.Length / 2;\n            var indices = self.CreatePermutationQuickMedian(cmp, med);\n            var result = self[indices[med]];\n            indices = null;\n\n            return result;\n        }\n\n        /// <summary>\n        /// Searches for the median-element in the Array and returns its value.\n        /// Does not change the given Array\n        /// Runtime is in O(N) and Memory in O(N)\n        /// For partitioning use QuickMedian\n        /// </summary>\n        public static T Median<T>(this T[] self) where T : IComparable<T>\n            => Median(self, (a, b) => a.CompareTo(b));\n\n        /// <summary>\n        /// Searches for the median-element in the List (according to cmp) and returns its value.\n        /// Does not change the given List\n        /// Runtime is in O(N) and Memory in O(N)\n        /// For partitioning use QuickMedian\n        /// </summary>\n        public static T Median<T>(this List<T> self, Func<T, T, int> cmp)\n        {\n            var med = self.Count / 2;\n            var indices = self.CreatePermutationQuickMedian(cmp, med);\n            var result = self[indices[med]];\n            indices = null;\n\n            return result;\n        }\n\n        /// <summary>\n        /// Searches for the median-element in the List and returns its value.\n        /// Does not change the given List\n        /// Runtime is in O(N) and Memory in O(N)\n        /// For partitioning use QuickMedian\n        /// </summary>\n        public static T Median<T>(this List<T> self) where T : IComparable<T>\n            => Median(self, (a, b) => a.CompareTo(b));\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Sorting/ListExtensions.cs",
    "content": "﻿using Aardvark.Base.Sorting;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public static class ListOrderingExtensions\n    {\n        public static int NSmallestIndex<T>(this List<T> a, int n)\n            where T : IComparable<T>\n        {\n            if (n == 0) return a.SmallestIndex();\n            var p = a.CreatePermutationQuickMedianAscending(n);\n            return p[n];\n        }\n\n        public static int NLargestIndex<T>(this List<T> a, int n)\n            where T : IComparable<T>\n        {\n            if (n == 0) return a.LargestIndex();\n            var p = a.CreatePermutationQuickMedianDescending(n);\n            return p[n];\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Sorting/Sorting_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\n\nnamespace Aardvark.Base.Sorting\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    public static class SortingExtensions\n    {\n        #region Constants\n\n        /// Use insertion sort if count smaller than this (quicksort, quickmedian).\n        private const int c_insertionSortThreshold = 31;\n        private const int c_insertionMedianThreshold = 7;\n\n        private const int c_minMerge = 32;\n        private const int c_minGallop = 7;\n        private const int c_initialTmpStorageLength = 256;\n\n        #endregion\n        \n        #region Sort/Median for int[]\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this int[] a, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this int[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending(\n                this int[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this int[] a)\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this int[] a,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending(\n                this int[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this int[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element < a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin] < a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] < element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this int[] a)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element < a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1] < a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] < element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending(\n                this int[] a)\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending(\n                this int[] a,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange(\n                this int[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift(\n                this int[] a,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val >= a[lf] && val >= a[rt]) break;\n                if (a[lf] >= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle(\n                this int[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson <= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt] >= vstepson || a[lf] >= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this int[] a)\n        {\n            TimSortAscending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this int[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<int>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntLongAsc(ti);\n        }\n\n        private static void MergeCollapseIntLongAsc(this TimSortInfoLong<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntLongAsc(this TimSortInfoLong<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntLongAsc(this TimSortInfoLong<int> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntLongAsc(this TimSortInfoLong<int> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] < t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiIntLongAsc(this TimSortInfoLong<int> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] < a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending(\n                this int[] a,\n                int key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key > a[start + hint])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key > a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key <= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending(\n                this int[] a,\n                int key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key < a[start + hint])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key < a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key >= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending(\n                this int[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot < a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending(\n                this int[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] < a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] < a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] >= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this int[] a, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this int[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending(\n                this int[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this int[] a)\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this int[] a,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending(\n                this int[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this int[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element > a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin] > a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] > element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this int[] a)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element > a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1] > a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] > element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending(\n                this int[] a)\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending(\n                this int[] a,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange(\n                this int[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift(\n                this int[] a,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val <= a[lf] && val <= a[rt]) break;\n                if (a[lf] <= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle(\n                this int[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson >= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt] <= vstepson || a[lf] <= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this int[] a)\n        {\n            TimSortDescending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this int[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<int>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntLongDesc(ti);\n        }\n\n        private static void MergeCollapseIntLongDesc(this TimSortInfoLong<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntLongDesc(this TimSortInfoLong<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntLongDesc(this TimSortInfoLong<int> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntLongDesc(this TimSortInfoLong<int> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] > t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiIntLongDesc(this TimSortInfoLong<int> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] > a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending(\n                this int[] a,\n                int key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key < a[start + hint])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key < a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key >= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending(\n                this int[] a,\n                int key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key > a[start + hint])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key > a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key <= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending(\n                this int[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot > a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending(\n                this int[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] > a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] > a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] <= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for int[]\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending(\n                this int[] a, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, int[] a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this int[] p, int[] a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending(\n                this int[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, int[] a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this int[] p, int[] a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending(\n                this int[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, int[] a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, int[] a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending(\n                this int[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, int[] a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this int[] p, int[] a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this int[] p, int[] a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this int[] p, int[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending(\n                this int[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, int[] a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, int[] a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<int>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntPermAsc(ti);\n        }\n\n        private static void MergeCollapseIntPermAsc(this TimSortInfoPerm<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntPermAsc(this TimSortInfoPerm<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntPermAsc(this TimSortInfoPerm<int> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntPermAsc(this TimSortInfoPerm<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiIntPermAsc(this TimSortInfoPerm<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending(\n                this int[] p, int[] a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending(\n                this int[] p, int[] a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong(\n                this int[] a, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this long[] p, int[] a, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this long[] p, int[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong(\n                this int[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this long[] p, int[] a)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this long[] p, int[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong(\n                this int[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this long[] p, int[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this long[] p, int[] a)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong(\n                this int[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this long[] p, int[] a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this long[] p, int[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this long[] p, int[] a,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this long[] p, int[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong(\n                this int[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this long[] p, int[] a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this long[] p, int[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<int>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntPermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntPermLongAsc(ti);\n        }\n\n        private static void MergeCollapseIntPermLongAsc(this TimSortInfoPermLong<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntPermLongAsc(this TimSortInfoPermLong<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntPermLongAsc(this TimSortInfoPermLong<int> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntPermLongAsc(this TimSortInfoPermLong<int> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiIntPermLongAsc(this TimSortInfoPermLong<int> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending(\n                this long[] p, int[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending(\n                this long[] p, int[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending(\n                this int[] a, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, int[] a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this int[] p, int[] a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending(\n                this int[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, int[] a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this int[] p, int[] a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending(\n                this int[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, int[] a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, int[] a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending(\n                this int[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, int[] a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this int[] p, int[] a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this int[] p, int[] a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this int[] p, int[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending(\n                this int[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, int[] a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, int[] a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<int>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntPermDesc(ti);\n        }\n\n        private static void MergeCollapseIntPermDesc(this TimSortInfoPerm<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntPermDesc(this TimSortInfoPerm<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntPermDesc(this TimSortInfoPerm<int> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntPermDesc(this TimSortInfoPerm<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiIntPermDesc(this TimSortInfoPerm<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending(\n                this int[] p, int[] a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending(\n                this int[] p, int[] a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending(\n                this int[] p, int[] a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong(\n                this int[] a, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this long[] p, int[] a, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this long[] p, int[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong(\n                this int[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this long[] p, int[] a)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this long[] p, int[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong(\n                this int[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this long[] p, int[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this long[] p, int[] a)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong(\n                this int[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this long[] p, int[] a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this long[] p, int[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this long[] p, int[] a,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this long[] p, int[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong(\n                this int[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this long[] p, int[] a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this long[] p, int[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<int>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntPermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntPermLongDesc(ti);\n        }\n\n        private static void MergeCollapseIntPermLongDesc(this TimSortInfoPermLong<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntPermLongDesc(this TimSortInfoPermLong<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntPermLongDesc(this TimSortInfoPermLong<int> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntPermLongDesc(this TimSortInfoPermLong<int> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiIntPermLongDesc(this TimSortInfoPermLong<int> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending(\n                this long[] p, int[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending(\n                this long[] p, int[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending(\n                this long[] p, int[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for long[]\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this long[] a, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this long[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending(\n                this long[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this long[] a)\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this long[] a,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending(\n                this long[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this long[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element < a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin] < a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] < element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this long[] a)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element < a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1] < a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] < element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending(\n                this long[] a)\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending(\n                this long[] a,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange(\n                this long[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift(\n                this long[] a,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val >= a[lf] && val >= a[rt]) break;\n                if (a[lf] >= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle(\n                this long[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson <= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt] >= vstepson || a[lf] >= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this long[] a)\n        {\n            TimSortAscending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this long[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<long>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongLongAsc(this TimSortInfoLong<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongLongAsc(this TimSortInfoLong<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongLongAsc(this TimSortInfoLong<long> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongLongAsc(this TimSortInfoLong<long> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] < t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongLongAsc(this TimSortInfoLong<long> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] < a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending(\n                this long[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key > a[start + hint])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key > a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key <= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending(\n                this long[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key < a[start + hint])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key < a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key >= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending(\n                this long[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot < a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending(\n                this long[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] < a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] < a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] >= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this long[] a, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this long[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending(\n                this long[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this long[] a)\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this long[] a,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending(\n                this long[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this long[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element > a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin] > a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] > element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this long[] a)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element > a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1] > a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] > element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending(\n                this long[] a)\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending(\n                this long[] a,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange(\n                this long[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift(\n                this long[] a,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val <= a[lf] && val <= a[rt]) break;\n                if (a[lf] <= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle(\n                this long[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson >= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt] <= vstepson || a[lf] <= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this long[] a)\n        {\n            TimSortDescending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this long[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<long>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongLongDesc(this TimSortInfoLong<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongLongDesc(this TimSortInfoLong<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongLongDesc(this TimSortInfoLong<long> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongLongDesc(this TimSortInfoLong<long> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] > t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongLongDesc(this TimSortInfoLong<long> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] > a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending(\n                this long[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key < a[start + hint])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key < a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key >= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending(\n                this long[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key > a[start + hint])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key > a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key <= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending(\n                this long[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot > a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending(\n                this long[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] > a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] > a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] <= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for long[]\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending(\n                this long[] a, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, long[] a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this int[] p, long[] a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending(\n                this long[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, long[] a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this int[] p, long[] a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending(\n                this long[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, long[] a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, long[] a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending(\n                this long[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, long[] a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this int[] p, long[] a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this int[] p, long[] a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this int[] p, long[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending(\n                this long[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, long[] a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, long[] a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<long>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongPermAsc(ti);\n        }\n\n        private static void MergeCollapseLongPermAsc(this TimSortInfoPerm<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongPermAsc(this TimSortInfoPerm<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongPermAsc(this TimSortInfoPerm<long> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongPermAsc(this TimSortInfoPerm<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiLongPermAsc(this TimSortInfoPerm<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending(\n                this int[] p, long[] a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending(\n                this int[] p, long[] a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong(\n                this long[] a, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this long[] p, long[] a, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this long[] p, long[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong(\n                this long[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this long[] p, long[] a)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this long[] p, long[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong(\n                this long[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this long[] p, long[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this long[] p, long[] a)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong(\n                this long[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this long[] p, long[] a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this long[] p, long[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this long[] p, long[] a,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this long[] p, long[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong(\n                this long[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this long[] p, long[] a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this long[] p, long[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<long>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongPermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongPermLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongPermLongAsc(this TimSortInfoPermLong<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongPermLongAsc(this TimSortInfoPermLong<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongPermLongAsc(this TimSortInfoPermLong<long> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongPermLongAsc(this TimSortInfoPermLong<long> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiLongPermLongAsc(this TimSortInfoPermLong<long> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending(\n                this long[] p, long[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending(\n                this long[] p, long[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending(\n                this long[] a, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, long[] a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this int[] p, long[] a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending(\n                this long[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, long[] a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this int[] p, long[] a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending(\n                this long[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, long[] a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, long[] a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending(\n                this long[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, long[] a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this int[] p, long[] a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this int[] p, long[] a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this int[] p, long[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending(\n                this long[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, long[] a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, long[] a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<long>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongPermDesc(ti);\n        }\n\n        private static void MergeCollapseLongPermDesc(this TimSortInfoPerm<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongPermDesc(this TimSortInfoPerm<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongPermDesc(this TimSortInfoPerm<long> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongPermDesc(this TimSortInfoPerm<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiLongPermDesc(this TimSortInfoPerm<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending(\n                this int[] p, long[] a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending(\n                this int[] p, long[] a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending(\n                this int[] p, long[] a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong(\n                this long[] a, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this long[] p, long[] a, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this long[] p, long[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong(\n                this long[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this long[] p, long[] a)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this long[] p, long[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong(\n                this long[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this long[] p, long[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this long[] p, long[] a)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong(\n                this long[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this long[] p, long[] a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this long[] p, long[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this long[] p, long[] a,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this long[] p, long[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong(\n                this long[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this long[] p, long[] a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this long[] p, long[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<long>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongPermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongPermLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongPermLongDesc(this TimSortInfoPermLong<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongPermLongDesc(this TimSortInfoPermLong<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongPermLongDesc(this TimSortInfoPermLong<long> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongPermLongDesc(this TimSortInfoPermLong<long> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiLongPermLongDesc(this TimSortInfoPermLong<long> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending(\n                this long[] p, long[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending(\n                this long[] p, long[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending(\n                this long[] p, long[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for float[]\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this float[] a, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this float[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending(\n                this float[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this float[] a)\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this float[] a,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending(\n                this float[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this float[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element < a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin] < a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] < element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this float[] a)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element < a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1] < a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] < element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending(\n                this float[] a)\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending(\n                this float[] a,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange(\n                this float[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift(\n                this float[] a,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val >= a[lf] && val >= a[rt]) break;\n                if (a[lf] >= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle(\n                this float[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson <= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt] >= vstepson || a[lf] >= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this float[] a)\n        {\n            TimSortAscending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this float[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<float>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatLongAsc(ti);\n        }\n\n        private static void MergeCollapseFloatLongAsc(this TimSortInfoLong<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatLongAsc(this TimSortInfoLong<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatLongAsc(this TimSortInfoLong<float> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatLongAsc(this TimSortInfoLong<float> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] < t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiFloatLongAsc(this TimSortInfoLong<float> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] < a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending(\n                this float[] a,\n                float key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key > a[start + hint])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key > a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key <= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending(\n                this float[] a,\n                float key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key < a[start + hint])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key < a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key >= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending(\n                this float[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot < a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending(\n                this float[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] < a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] < a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] >= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this float[] a, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this float[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending(\n                this float[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this float[] a)\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this float[] a,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending(\n                this float[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this float[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element > a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin] > a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] > element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this float[] a)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element > a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1] > a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] > element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending(\n                this float[] a)\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending(\n                this float[] a,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange(\n                this float[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift(\n                this float[] a,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val <= a[lf] && val <= a[rt]) break;\n                if (a[lf] <= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle(\n                this float[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson >= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt] <= vstepson || a[lf] <= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this float[] a)\n        {\n            TimSortDescending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this float[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<float>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatLongDesc(ti);\n        }\n\n        private static void MergeCollapseFloatLongDesc(this TimSortInfoLong<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatLongDesc(this TimSortInfoLong<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatLongDesc(this TimSortInfoLong<float> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatLongDesc(this TimSortInfoLong<float> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] > t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiFloatLongDesc(this TimSortInfoLong<float> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] > a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending(\n                this float[] a,\n                float key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key < a[start + hint])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key < a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key >= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending(\n                this float[] a,\n                float key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key > a[start + hint])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key > a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key <= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending(\n                this float[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot > a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending(\n                this float[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] > a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] > a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] <= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for float[]\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending(\n                this float[] a, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, float[] a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this int[] p, float[] a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending(\n                this float[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, float[] a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this int[] p, float[] a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending(\n                this float[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, float[] a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, float[] a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending(\n                this float[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, float[] a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this int[] p, float[] a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this int[] p, float[] a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this int[] p, float[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending(\n                this float[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, float[] a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, float[] a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<float>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatPermAsc(ti);\n        }\n\n        private static void MergeCollapseFloatPermAsc(this TimSortInfoPerm<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatPermAsc(this TimSortInfoPerm<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatPermAsc(this TimSortInfoPerm<float> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatPermAsc(this TimSortInfoPerm<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiFloatPermAsc(this TimSortInfoPerm<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending(\n                this int[] p, float[] a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending(\n                this int[] p, float[] a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong(\n                this float[] a, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this long[] p, float[] a, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this long[] p, float[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong(\n                this float[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this long[] p, float[] a)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this long[] p, float[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong(\n                this float[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this long[] p, float[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this long[] p, float[] a)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong(\n                this float[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this long[] p, float[] a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this long[] p, float[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this long[] p, float[] a,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this long[] p, float[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong(\n                this float[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this long[] p, float[] a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this long[] p, float[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<float>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatPermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatPermLongAsc(ti);\n        }\n\n        private static void MergeCollapseFloatPermLongAsc(this TimSortInfoPermLong<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatPermLongAsc(this TimSortInfoPermLong<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatPermLongAsc(this TimSortInfoPermLong<float> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatPermLongAsc(this TimSortInfoPermLong<float> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiFloatPermLongAsc(this TimSortInfoPermLong<float> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending(\n                this long[] p, float[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending(\n                this long[] p, float[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending(\n                this float[] a, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, float[] a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this int[] p, float[] a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending(\n                this float[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, float[] a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this int[] p, float[] a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending(\n                this float[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, float[] a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, float[] a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending(\n                this float[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, float[] a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this int[] p, float[] a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this int[] p, float[] a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this int[] p, float[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending(\n                this float[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, float[] a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, float[] a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<float>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatPermDesc(ti);\n        }\n\n        private static void MergeCollapseFloatPermDesc(this TimSortInfoPerm<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatPermDesc(this TimSortInfoPerm<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatPermDesc(this TimSortInfoPerm<float> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatPermDesc(this TimSortInfoPerm<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiFloatPermDesc(this TimSortInfoPerm<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending(\n                this int[] p, float[] a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending(\n                this int[] p, float[] a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending(\n                this int[] p, float[] a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong(\n                this float[] a, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this long[] p, float[] a, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this long[] p, float[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong(\n                this float[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this long[] p, float[] a)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this long[] p, float[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong(\n                this float[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this long[] p, float[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this long[] p, float[] a)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong(\n                this float[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this long[] p, float[] a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this long[] p, float[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this long[] p, float[] a,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this long[] p, float[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong(\n                this float[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this long[] p, float[] a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this long[] p, float[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<float>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatPermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatPermLongDesc(ti);\n        }\n\n        private static void MergeCollapseFloatPermLongDesc(this TimSortInfoPermLong<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatPermLongDesc(this TimSortInfoPermLong<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatPermLongDesc(this TimSortInfoPermLong<float> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatPermLongDesc(this TimSortInfoPermLong<float> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiFloatPermLongDesc(this TimSortInfoPermLong<float> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending(\n                this long[] p, float[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending(\n                this long[] p, float[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending(\n                this long[] p, float[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for double[]\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this double[] a, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this double[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending(\n                this double[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this double[] a)\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this double[] a,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending(\n                this double[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this double[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element < a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin] < a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] < element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this double[] a)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element < a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1] < a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] < element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending(\n                this double[] a)\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending(\n                this double[] a,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange(\n                this double[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift(\n                this double[] a,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val >= a[lf] && val >= a[rt]) break;\n                if (a[lf] >= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle(\n                this double[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson <= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt] >= vstepson || a[lf] >= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this double[] a)\n        {\n            TimSortAscending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this double[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<double>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoubleLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoubleLongAsc(ti);\n        }\n\n        private static void MergeCollapseDoubleLongAsc(this TimSortInfoLong<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoubleLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoubleLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoubleLongAsc(this TimSortInfoLong<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoubleLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoubleLongAsc(this TimSortInfoLong<double> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoubleLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoubleLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoubleLongAsc(this TimSortInfoLong<double> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] < t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiDoubleLongAsc(this TimSortInfoLong<double> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] < a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending(\n                this double[] a,\n                double key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key > a[start + hint])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key > a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key <= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending(\n                this double[] a,\n                double key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key < a[start + hint])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key < a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key >= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending(\n                this double[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot < a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending(\n                this double[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] < a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] < a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] >= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this double[] a, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this double[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending(\n                this double[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this double[] a)\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this double[] a,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending(\n                this double[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this double[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element > a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin] > a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] > element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this double[] a)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element > a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1] > a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] > element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending(\n                this double[] a)\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending(\n                this double[] a,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange(\n                this double[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift(\n                this double[] a,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val <= a[lf] && val <= a[rt]) break;\n                if (a[lf] <= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle(\n                this double[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson >= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt] <= vstepson || a[lf] <= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this double[] a)\n        {\n            TimSortDescending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this double[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<double>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoubleLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoubleLongDesc(ti);\n        }\n\n        private static void MergeCollapseDoubleLongDesc(this TimSortInfoLong<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoubleLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoubleLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoubleLongDesc(this TimSortInfoLong<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoubleLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoubleLongDesc(this TimSortInfoLong<double> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoubleLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoubleLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoubleLongDesc(this TimSortInfoLong<double> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] > t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiDoubleLongDesc(this TimSortInfoLong<double> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] > a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending(\n                this double[] a,\n                double key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key < a[start + hint])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key < a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key >= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending(\n                this double[] a,\n                double key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key > a[start + hint])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key > a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key <= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending(\n                this double[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot > a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending(\n                this double[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] > a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] > a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] <= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for double[]\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending(\n                this double[] a, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, double[] a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this int[] p, double[] a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending(\n                this double[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, double[] a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this int[] p, double[] a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending(\n                this double[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, double[] a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, double[] a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending(\n                this double[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, double[] a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this int[] p, double[] a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this int[] p, double[] a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this int[] p, double[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending(\n                this double[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, double[] a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, double[] a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<double>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoublePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoublePermAsc(ti);\n        }\n\n        private static void MergeCollapseDoublePermAsc(this TimSortInfoPerm<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoublePermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoublePermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoublePermAsc(this TimSortInfoPerm<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoublePermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoublePermAsc(this TimSortInfoPerm<double> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoublePermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoublePermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoublePermAsc(this TimSortInfoPerm<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiDoublePermAsc(this TimSortInfoPerm<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending(\n                this int[] p, double[] a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending(\n                this int[] p, double[] a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong(\n                this double[] a, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this long[] p, double[] a, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this long[] p, double[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong(\n                this double[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this long[] p, double[] a)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this long[] p, double[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong(\n                this double[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this long[] p, double[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this long[] p, double[] a)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong(\n                this double[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this long[] p, double[] a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this long[] p, double[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this long[] p, double[] a,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this long[] p, double[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong(\n                this double[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this long[] p, double[] a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this long[] p, double[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<double>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoublePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoublePermLongAsc(ti);\n        }\n\n        private static void MergeCollapseDoublePermLongAsc(this TimSortInfoPermLong<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoublePermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoublePermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoublePermLongAsc(this TimSortInfoPermLong<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoublePermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoublePermLongAsc(this TimSortInfoPermLong<double> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoublePermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoublePermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoublePermLongAsc(this TimSortInfoPermLong<double> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiDoublePermLongAsc(this TimSortInfoPermLong<double> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending(\n                this long[] p, double[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending(\n                this long[] p, double[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending(\n                this double[] a, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, double[] a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this int[] p, double[] a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending(\n                this double[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, double[] a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this int[] p, double[] a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending(\n                this double[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, double[] a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, double[] a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending(\n                this double[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, double[] a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this int[] p, double[] a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this int[] p, double[] a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this int[] p, double[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending(\n                this double[] a)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, double[] a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, double[] a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<double>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoublePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoublePermDesc(ti);\n        }\n\n        private static void MergeCollapseDoublePermDesc(this TimSortInfoPerm<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoublePermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoublePermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoublePermDesc(this TimSortInfoPerm<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoublePermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoublePermDesc(this TimSortInfoPerm<double> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoublePermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoublePermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoublePermDesc(this TimSortInfoPerm<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiDoublePermDesc(this TimSortInfoPerm<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending(\n                this int[] p, double[] a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending(\n                this int[] p, double[] a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending(\n                this int[] p, double[] a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong(\n                this double[] a, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this long[] p, double[] a, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this long[] p, double[] a,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong(\n                this double[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this long[] p, double[] a)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this long[] p, double[] a,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong(\n                this double[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this long[] p, double[] a, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this long[] p, double[] a)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong(\n                this double[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this long[] p, double[] a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this long[] p, double[] a,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this long[] p, double[] a,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this long[] p, double[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong(\n                this double[] a)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this long[] p, double[] a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this long[] p, double[] a,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<double>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoublePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoublePermLongDesc(ti);\n        }\n\n        private static void MergeCollapseDoublePermLongDesc(this TimSortInfoPermLong<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoublePermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoublePermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoublePermLongDesc(this TimSortInfoPermLong<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoublePermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoublePermLongDesc(this TimSortInfoPermLong<double> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoublePermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoublePermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoublePermLongDesc(this TimSortInfoPermLong<double> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiDoublePermLongDesc(this TimSortInfoPermLong<double> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending(\n                this long[] p, double[] a,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending(\n                this long[] p, double[] a,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending(\n                this long[] p, double[] a,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for List<int>\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this List<int> a, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this List<int> a,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending(\n                this List<int> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this List<int> a)\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this List<int> a,\n                int beginIncl, int endExcl)\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending(\n                this List<int> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this List<int> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element < a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin] < a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] < element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this List<int> a)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element < a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1] < a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] < element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending(\n                this List<int> a)\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending(\n                this List<int> a,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange(\n                this List<int> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift(\n                this List<int> a,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val >= a[lf] && val >= a[rt]) break;\n                if (a[lf] >= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle(\n                this List<int> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson <= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt] >= vstepson || a[lf] >= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this List<int> a)\n        {\n            TimSortAscending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this List<int> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<int>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntListAsc(ti);\n        }\n\n        private static void MergeCollapseIntListAsc(this TimSortInfoList<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntListAsc(this TimSortInfoList<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntListAsc(this TimSortInfoList<int> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntListAsc(this TimSortInfoList<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] < t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiIntListAsc(this TimSortInfoList<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] < a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending(\n                this List<int> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key > a[start + hint])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key > a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key <= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending(\n                this List<int> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key < a[start + hint])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key < a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key >= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending(\n                this List<int> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot < a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending(\n                this List<int> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] < a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] < a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] >= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this List<int> a, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this List<int> a,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending(\n                this List<int> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this List<int> a)\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this List<int> a,\n                int beginIncl, int endExcl)\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending(\n                this List<int> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this List<int> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element > a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin] > a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] > element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this List<int> a)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element > a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1] > a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] > element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending(\n                this List<int> a)\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending(\n                this List<int> a,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange(\n                this List<int> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift(\n                this List<int> a,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val <= a[lf] && val <= a[rt]) break;\n                if (a[lf] <= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle(\n                this List<int> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson >= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt] <= vstepson || a[lf] <= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this List<int> a)\n        {\n            TimSortDescending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this List<int> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<int>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntListDesc(ti);\n        }\n\n        private static void MergeCollapseIntListDesc(this TimSortInfoList<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntListDesc(this TimSortInfoList<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntListDesc(this TimSortInfoList<int> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntListDesc(this TimSortInfoList<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] > t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiIntListDesc(this TimSortInfoList<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] > a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending(\n                this List<int> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key < a[start + hint])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key < a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key >= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending(\n                this List<int> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key > a[start + hint])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key > a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key <= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending(\n                this List<int> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot > a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending(\n                this List<int> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] > a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] > a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] <= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for List<int>\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending(\n                this List<int> a, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, List<int> a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this int[] p, List<int> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending(\n                this List<int> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, List<int> a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this int[] p, List<int> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending(\n                this List<int> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, List<int> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, List<int> a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending(\n                this List<int> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, List<int> a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this int[] p, List<int> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this int[] p, List<int> a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this int[] p, List<int> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending(\n                this List<int> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, List<int> a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, List<int> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<int>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntListPermAsc(ti);\n        }\n\n        private static void MergeCollapseIntListPermAsc(this TimSortInfoListPerm<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntListPermAsc(this TimSortInfoListPerm<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntListPermAsc(this TimSortInfoListPerm<int> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntListPermAsc(this TimSortInfoListPerm<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiIntListPermAsc(this TimSortInfoListPerm<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending(\n                this int[] p, List<int> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending(\n                this int[] p, List<int> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending(\n                this List<int> a, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, List<int> a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this int[] p, List<int> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending(\n                this List<int> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, List<int> a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this int[] p, List<int> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending(\n                this List<int> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, List<int> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, List<int> a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending(\n                this List<int> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, List<int> a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this int[] p, List<int> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this int[] p, List<int> a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this int[] p, List<int> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending(\n                this List<int> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, List<int> a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, List<int> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<int>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseIntListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseIntListPermDesc(ti);\n        }\n\n        private static void MergeCollapseIntListPermDesc(this TimSortInfoListPerm<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtIntListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtIntListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseIntListPermDesc(this TimSortInfoListPerm<int> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtIntListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtIntListPermDesc(this TimSortInfoListPerm<int> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoIntListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiIntListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoIntListPermDesc(this TimSortInfoListPerm<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiIntListPermDesc(this TimSortInfoListPerm<int> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending(\n                this int[] p, List<int> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending(\n                this int[] p, List<int> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending(\n                this int[] p, List<int> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for List<long>\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this List<long> a, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this List<long> a,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending(\n                this List<long> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this List<long> a)\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this List<long> a,\n                int beginIncl, int endExcl)\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending(\n                this List<long> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this List<long> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element < a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin] < a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] < element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this List<long> a)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element < a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1] < a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] < element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending(\n                this List<long> a)\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending(\n                this List<long> a,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange(\n                this List<long> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift(\n                this List<long> a,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val >= a[lf] && val >= a[rt]) break;\n                if (a[lf] >= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle(\n                this List<long> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson <= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt] >= vstepson || a[lf] >= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this List<long> a)\n        {\n            TimSortAscending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this List<long> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<long>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongListAsc(ti);\n        }\n\n        private static void MergeCollapseLongListAsc(this TimSortInfoList<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongListAsc(this TimSortInfoList<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongListAsc(this TimSortInfoList<long> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongListAsc(this TimSortInfoList<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] < t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongListAsc(this TimSortInfoList<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] < a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending(\n                this List<long> a,\n                long key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key > a[start + hint])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key > a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key <= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending(\n                this List<long> a,\n                long key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key < a[start + hint])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key < a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key >= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending(\n                this List<long> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot < a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending(\n                this List<long> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] < a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] < a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] >= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this List<long> a, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this List<long> a,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending(\n                this List<long> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this List<long> a)\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this List<long> a,\n                int beginIncl, int endExcl)\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending(\n                this List<long> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this List<long> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element > a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin] > a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] > element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this List<long> a)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element > a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1] > a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] > element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending(\n                this List<long> a)\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending(\n                this List<long> a,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange(\n                this List<long> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift(\n                this List<long> a,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val <= a[lf] && val <= a[rt]) break;\n                if (a[lf] <= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle(\n                this List<long> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson >= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt] <= vstepson || a[lf] <= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this List<long> a)\n        {\n            TimSortDescending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this List<long> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<long>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongListDesc(ti);\n        }\n\n        private static void MergeCollapseLongListDesc(this TimSortInfoList<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongListDesc(this TimSortInfoList<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongListDesc(this TimSortInfoList<long> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongListDesc(this TimSortInfoList<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] > t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongListDesc(this TimSortInfoList<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] > a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending(\n                this List<long> a,\n                long key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key < a[start + hint])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key < a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key >= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending(\n                this List<long> a,\n                long key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key > a[start + hint])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key > a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key <= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending(\n                this List<long> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot > a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending(\n                this List<long> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] > a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] > a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] <= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for List<long>\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending(\n                this List<long> a, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, List<long> a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this int[] p, List<long> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending(\n                this List<long> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, List<long> a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this int[] p, List<long> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending(\n                this List<long> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, List<long> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, List<long> a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending(\n                this List<long> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, List<long> a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this int[] p, List<long> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this int[] p, List<long> a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this int[] p, List<long> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending(\n                this List<long> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, List<long> a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, List<long> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<long>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongListPermAsc(ti);\n        }\n\n        private static void MergeCollapseLongListPermAsc(this TimSortInfoListPerm<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongListPermAsc(this TimSortInfoListPerm<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongListPermAsc(this TimSortInfoListPerm<long> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongListPermAsc(this TimSortInfoListPerm<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiLongListPermAsc(this TimSortInfoListPerm<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending(\n                this int[] p, List<long> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending(\n                this int[] p, List<long> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending(\n                this List<long> a, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, List<long> a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this int[] p, List<long> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending(\n                this List<long> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, List<long> a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this int[] p, List<long> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending(\n                this List<long> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, List<long> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, List<long> a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending(\n                this List<long> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, List<long> a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this int[] p, List<long> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this int[] p, List<long> a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this int[] p, List<long> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending(\n                this List<long> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, List<long> a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, List<long> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<long>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongListPermDesc(ti);\n        }\n\n        private static void MergeCollapseLongListPermDesc(this TimSortInfoListPerm<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongListPermDesc(this TimSortInfoListPerm<long> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongListPermDesc(this TimSortInfoListPerm<long> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongListPermDesc(this TimSortInfoListPerm<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiLongListPermDesc(this TimSortInfoListPerm<long> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending(\n                this int[] p, List<long> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending(\n                this int[] p, List<long> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending(\n                this int[] p, List<long> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for List<float>\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this List<float> a, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this List<float> a,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending(\n                this List<float> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this List<float> a)\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this List<float> a,\n                int beginIncl, int endExcl)\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending(\n                this List<float> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this List<float> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element < a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin] < a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] < element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this List<float> a)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element < a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1] < a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] < element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending(\n                this List<float> a)\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending(\n                this List<float> a,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange(\n                this List<float> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift(\n                this List<float> a,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val >= a[lf] && val >= a[rt]) break;\n                if (a[lf] >= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle(\n                this List<float> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson <= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt] >= vstepson || a[lf] >= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this List<float> a)\n        {\n            TimSortAscending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this List<float> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<float>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatListAsc(ti);\n        }\n\n        private static void MergeCollapseFloatListAsc(this TimSortInfoList<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatListAsc(this TimSortInfoList<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatListAsc(this TimSortInfoList<float> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatListAsc(this TimSortInfoList<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] < t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiFloatListAsc(this TimSortInfoList<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] < a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending(\n                this List<float> a,\n                float key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key > a[start + hint])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key > a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key <= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending(\n                this List<float> a,\n                float key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key < a[start + hint])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key < a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key >= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending(\n                this List<float> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot < a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending(\n                this List<float> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] < a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] < a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] >= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this List<float> a, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this List<float> a,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending(\n                this List<float> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this List<float> a)\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this List<float> a,\n                int beginIncl, int endExcl)\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending(\n                this List<float> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this List<float> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element > a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin] > a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] > element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this List<float> a)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element > a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1] > a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] > element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending(\n                this List<float> a)\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending(\n                this List<float> a,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange(\n                this List<float> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift(\n                this List<float> a,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val <= a[lf] && val <= a[rt]) break;\n                if (a[lf] <= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle(\n                this List<float> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson >= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt] <= vstepson || a[lf] <= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this List<float> a)\n        {\n            TimSortDescending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this List<float> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<float>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatListDesc(ti);\n        }\n\n        private static void MergeCollapseFloatListDesc(this TimSortInfoList<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatListDesc(this TimSortInfoList<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatListDesc(this TimSortInfoList<float> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatListDesc(this TimSortInfoList<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] > t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiFloatListDesc(this TimSortInfoList<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] > a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending(\n                this List<float> a,\n                float key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key < a[start + hint])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key < a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key >= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending(\n                this List<float> a,\n                float key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key > a[start + hint])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key > a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key <= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending(\n                this List<float> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot > a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending(\n                this List<float> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] > a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] > a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] <= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for List<float>\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending(\n                this List<float> a, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, List<float> a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this int[] p, List<float> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending(\n                this List<float> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, List<float> a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this int[] p, List<float> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending(\n                this List<float> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, List<float> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, List<float> a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending(\n                this List<float> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, List<float> a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this int[] p, List<float> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this int[] p, List<float> a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this int[] p, List<float> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending(\n                this List<float> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, List<float> a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, List<float> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<float>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatListPermAsc(ti);\n        }\n\n        private static void MergeCollapseFloatListPermAsc(this TimSortInfoListPerm<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatListPermAsc(this TimSortInfoListPerm<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatListPermAsc(this TimSortInfoListPerm<float> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatListPermAsc(this TimSortInfoListPerm<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiFloatListPermAsc(this TimSortInfoListPerm<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending(\n                this int[] p, List<float> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending(\n                this int[] p, List<float> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending(\n                this List<float> a, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, List<float> a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this int[] p, List<float> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending(\n                this List<float> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, List<float> a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this int[] p, List<float> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending(\n                this List<float> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, List<float> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, List<float> a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending(\n                this List<float> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, List<float> a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this int[] p, List<float> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this int[] p, List<float> a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this int[] p, List<float> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending(\n                this List<float> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, List<float> a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, List<float> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<float>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseFloatListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseFloatListPermDesc(ti);\n        }\n\n        private static void MergeCollapseFloatListPermDesc(this TimSortInfoListPerm<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtFloatListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtFloatListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseFloatListPermDesc(this TimSortInfoListPerm<float> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtFloatListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtFloatListPermDesc(this TimSortInfoListPerm<float> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoFloatListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiFloatListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoFloatListPermDesc(this TimSortInfoListPerm<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiFloatListPermDesc(this TimSortInfoListPerm<float> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending(\n                this int[] p, List<float> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending(\n                this int[] p, List<float> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending(\n                this int[] p, List<float> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for List<double>\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this List<double> a, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending(\n                this List<double> a,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending(\n                this List<double> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this List<double> a)\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending(\n                this List<double> a,\n                int beginIncl, int endExcl)\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending(\n                this List<double> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] > a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] > a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] > a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] > a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] > a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] > a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] > a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai > p2)\n                        {\n                            while (a[hi] > p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] > p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai < p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai < a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this List<double> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element < a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin] < a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] < element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending(\n                this List<double> a)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element < a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1] < a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] < element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending(\n                this List<double> a)\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending(\n                this List<double> a,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange(\n                this List<double> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift(\n                this List<double> a,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val >= a[lf] && val >= a[rt]) break;\n                if (a[lf] >= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle(\n                this List<double> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson <= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt] >= vstepson || a[lf] >= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this List<double> a)\n        {\n            TimSortAscending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending(\n                this List<double> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<double>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoubleListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoubleListAsc(ti);\n        }\n\n        private static void MergeCollapseDoubleListAsc(this TimSortInfoList<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoubleListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoubleListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoubleListAsc(this TimSortInfoList<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoubleListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoubleListAsc(this TimSortInfoList<double> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoubleListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoubleListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoubleListAsc(this TimSortInfoList<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] < t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiDoubleListAsc(this TimSortInfoList<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] < a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending(\n                this List<double> a,\n                double key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key > a[start + hint])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key > a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key <= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending(\n                this List<double> a,\n                double key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key < a[start + hint])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key < a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key >= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending(\n                this List<double> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot < a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending(\n                this List<double> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] < a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] < a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] >= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this List<double> a, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending(\n                this List<double> a,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending(\n                this List<double> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this List<double> a)\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending(\n                this List<double> a,\n                int beginIncl, int endExcl)\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending(\n                this List<double> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1] < a[e2]) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1] < a[e3]) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1] < a[e4]) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3] < a[e4]) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2] < a[e5]) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2] < a[e3]) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4] < a[e5]) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1 != p2;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai < p2)\n                        {\n                            while (a[hi] < p2 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai == p1) continue;\n                        if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi] < p1)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai > p1) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo] == p1)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i] == p1) { a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi] == p2)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i] == p2) { a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai > a[j]; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this List<double> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element > a[i2 + begin])\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin] > a[i2 + begin])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin] > element)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending(\n                this List<double> a)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element > a[i2])\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1] > a[i2])\n                                 ? i2 : i1; // smaller child\n                    if (a[ni] > element)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending(\n                this List<double> a)\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending(\n                this List<double> a,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange(\n                this List<double> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift(\n                this List<double> a,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val <= a[lf] && val <= a[rt]) break;\n                if (a[lf] <= a[rt])\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle(\n                this List<double> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson >= val) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt] <= vstepson || a[lf] <= vstepson)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this List<double> a)\n        {\n            TimSortDescending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending(\n                this List<double> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<double>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoubleListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoubleListDesc(ti);\n        }\n\n        private static void MergeCollapseDoubleListDesc(this TimSortInfoList<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoubleListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoubleListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoubleListDesc(this TimSortInfoList<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoubleListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoubleListDesc(this TimSortInfoList<double> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoubleListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoubleListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoubleListDesc(this TimSortInfoList<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2] > t[idx1])\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiDoubleListDesc(this TimSortInfoList<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2] > a[idx1])\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending(\n                this List<double> a,\n                double key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key < a[start + hint])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key < a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key >= a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key < a[start + m])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending(\n                this List<double> a,\n                double key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key > a[start + hint])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key > a[start + hint - ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key <= a[start + hint + ofs])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key > a[start + m])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending(\n                this List<double> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot > a[mid])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending(\n                this List<double> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++] > a[beginIncl])\n            {\n                while (runHi < endExcl && a[runHi] > a[runHi - 1])\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi] <= a[runHi - 1])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for List<double>\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending(\n                this List<double> a, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, List<double> a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending(\n                this int[] p, List<double> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending(\n                this List<double> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, List<double> a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending(\n                this int[] p, List<double> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] > a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] > a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] > a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] > a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] > a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] > a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] > a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] > a[p2])\n                        {\n                            while (a[p[hi]] > a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] > a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] < a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] < a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending(\n                this List<double> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, List<double> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] < a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] < a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending(\n                this int[] p, List<double> a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] < a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] < a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] < a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending(\n                this List<double> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, List<double> a)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange(\n                this int[] p, List<double> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift(\n                this int[] p, List<double> a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] >= a[p[lf]] && a[val] >= a[p[rt]]) break;\n                if (a[p[lf]] >= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle(\n                this int[] p, List<double> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] <= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] >= a[vstepson] || a[p[lf]] >= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending(\n                this List<double> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, List<double> a)\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending(\n                this int[] p, List<double> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<double>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoubleListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoubleListPermAsc(ti);\n        }\n\n        private static void MergeCollapseDoubleListPermAsc(this TimSortInfoListPerm<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoubleListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoubleListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoubleListPermAsc(this TimSortInfoListPerm<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoubleListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoubleListPermAsc(this TimSortInfoListPerm<double> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoubleListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoubleListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoubleListPermAsc(this TimSortInfoListPerm<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] < a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiDoubleListPermAsc(this TimSortInfoListPerm<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] < a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending(\n                this int[] p, List<double> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] > a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending(\n                this int[] p, List<double> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] < a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] < a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] < a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] < a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] >= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending(\n                this List<double> a, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, List<double> a, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending(\n                this int[] p, List<double> a,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending(\n                this List<double> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, List<double> a)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending(\n                this int[] p, List<double> a,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]] < a[p[e2]]) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]] < a[p[e3]]) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]] < a[p[e4]]) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]] < a[p[e4]]) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]] < a[p[e5]]) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]] < a[p[e3]]) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]] < a[p[e5]]) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1] != a[p2];\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai] < a[p2])\n                        {\n                            while (a[p[hi]] < a[p2] && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai] == a[p1]) continue;\n                        if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]] < a[p1])\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai] > a[p1]) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]] == a[p1])\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]] == a[p1]) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]] == a[p2])\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]] == a[p2]) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai] > a[p[j]]; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending(\n                this List<double> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, List<double> a, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2 + begin]])\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]] > a[p[i2 + begin]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]] > a[element])\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending(\n                this int[] p, List<double> a)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element] > a[p[i2]])\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]] > a[p[i2]])\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]] > a[element])\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending(\n                this List<double> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, List<double> a)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange(\n                this int[] p, List<double> a,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift(\n                this int[] p, List<double> a,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val] <= a[p[lf]] && a[val] <= a[p[rt]]) break;\n                if (a[p[lf]] <= a[p[rt]])\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle(\n                this int[] p, List<double> a,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson] >= a[val]) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]] <= a[vstepson] || a[p[lf]] <= a[vstepson])\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending(\n                this List<double> a)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, List<double> a)\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending(\n                this int[] p, List<double> a,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<double>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseDoubleListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseDoubleListPermDesc(ti);\n        }\n\n        private static void MergeCollapseDoubleListPermDesc(this TimSortInfoListPerm<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtDoubleListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtDoubleListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseDoubleListPermDesc(this TimSortInfoListPerm<double> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtDoubleListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtDoubleListPermDesc(this TimSortInfoListPerm<double> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoDoubleListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiDoubleListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoDoubleListPermDesc(this TimSortInfoListPerm<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]] > a[t[idx1]])\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiDoubleListPermDesc(this TimSortInfoListPerm<double> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]] > a[p[idx1]])\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending(\n                this int[] p, List<double> a,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key] < a[p[start + hint]])\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] < a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] >= a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] < a[p[start + m]])\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending(\n                this int[] p, List<double> a,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key] > a[p[start + hint]])\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key] > a[p[start + hint - ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key] <= a[p[start + hint + ofs]])\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key] > a[p[start + m]])\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot] > a[p[mid]])\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending(\n                this int[] p, List<double> a,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]] > a[p[beginIncl]])\n            {\n                while (runHi < endExcl && a[p[runHi]] > a[p[runHi - 1]])\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]] <= a[p[runHi - 1]])\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for T[]\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedian<T>(\n                this T[] a, Func<T, T, int> cmp, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedian(a, cmp, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedian<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedian(a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedian<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (cmp(a[e1], a[e2]) > 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (cmp(a[e4], a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (cmp(a[e1], a[e3]) > 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (cmp(a[e2], a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (cmp(a[e1], a[e4]) > 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (cmp(a[e3], a[e4]) > 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (cmp(a[e2], a[e5]) > 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (cmp(a[e2], a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (cmp(a[e4], a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = cmp(p1, p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (cmp(ai, p2) > 0)\n                        {\n                            while (cmp(a[hi], p2) > 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (cmp(ai, p1) == 0) continue;\n                        if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[hi], p1) > 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (cmp(a[lo], p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[i], p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[hi], p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[i], p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && cmp(ai, a[j]) < 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSort<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            long last = a.LongLength - 1;\n            QuickSort(a, cmp, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSort<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            QuickSort(a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSort<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (cmp(a[e1], a[e2]) > 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (cmp(a[e4], a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (cmp(a[e1], a[e3]) > 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (cmp(a[e2], a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (cmp(a[e1], a[e4]) > 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (cmp(a[e3], a[e4]) > 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (cmp(a[e2], a[e5]) > 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (cmp(a[e2], a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (cmp(a[e4], a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = cmp(p1, p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (cmp(ai, p2) > 0)\n                        {\n                            while (cmp(a[hi], p2) > 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (cmp(ai, p1) == 0) continue;\n                        if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[hi], p1) > 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSort(a, cmp, l, lo - 2, cl);\n                        QuickSort(a, cmp, hi + 2, r, cr);\n                        {\n                            while (cmp(a[lo], p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[i], p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[hi], p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[i], p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSort(a, cmp, lo, hi, cm);\n                                QuickSort(a, cmp, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSort(a, cmp, l, lo - 2, cl);\n                                QuickSort(a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSort(a, cmp, l, lo - 2, cl);\n                                QuickSort(a, cmp, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSort(a, cmp, l, lo - 2, cl);\n                                QuickSort(a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSort(a, cmp, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSort(a, cmp, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && cmp(ai, a[j]) < 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSort<T>(\n                this T[] a, Func<T, T, int> cmp, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (cmp(element, a[i2 + begin]) < 0)\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && cmp(a[i1 + begin], a[i2 + begin]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[ni + begin], element) < 0)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSort<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (cmp(element, a[i2]) < 0)\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && cmp(a[i1], a[i2]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[ni], element) < 0)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSort<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            SmoothSortInclusiveRange(a, cmp, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSort<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortInclusiveRange(a, cmp, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortInclusiveRange<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortSift(a, cmp, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortTrinkle(a, cmp, pbits, pshift, head, false);\n                    else\n                        SmoothSortSift(a, cmp, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortTrinkle(a, cmp, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortTrinkle(a, cmp, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortTrinkle(a, cmp, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortSift<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (cmp(val, a[lf]) >= 0 && cmp(val, a[rt]) >= 0) break;\n                if (cmp(a[lf], a[rt]) >= 0)\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortTrinkle<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (cmp(vstepson, val) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (cmp(a[rt], vstepson) >= 0 || cmp(a[lf], vstepson) >= 0)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortSift(a, cmp, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongCmp<T>\n        {\n            public T[] m_a;\n            public Func<T, T, int> m_cmp;\n            public long m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongCmp(T[] a, Func<T, T, int> cmp)\n            {\n                m_a = a;\n                m_cmp = cmp;\n                long count = a.LongLength;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSort<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            TimSort(a, cmp, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSort<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrder(a, cmp, lo, hi);\n                BinarySort(a, cmp, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongCmp<T>(a, cmp);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrder(a, cmp, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySort(a, cmp, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongCmp(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongCmp(ti);\n        }\n\n        private static void MergeCollapseLongCmp<T>(this TimSortInfoLongCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongCmp(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongCmp(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongCmp<T>(this TimSortInfoLongCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongCmp(ti, n);\n            }\n        }\n\n        private static void MergeAtLongCmp<T>(this TimSortInfoLongCmp<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRight(a, ti.m_cmp, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeft(a, ti.m_cmp, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongCmp(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongCmp(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongCmp<T>(this TimSortInfoLongCmp<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(a[idx2], t[idx1]) < 0)\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRight(t, cmp, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeft(a, cmp, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongCmp<T>(this TimSortInfoLongCmp<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(t[idx2], a[idx1]) < 0)\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRight(a, cmp, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeft(t, cmp, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeft<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (cmp(key, a[start + hint]) > 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(key, a[start + hint + ofs]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(key, a[start + hint - ofs]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(key, a[start + m]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRight<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (cmp(key, a[start + hint]) < 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(key, a[start + hint - ofs]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(key, a[start + hint + ofs]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(key, a[start + m]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySort<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (cmp(pivot, a[mid]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrder<T>(\n                this T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (cmp(a[runHi++], a[beginIncl]) < 0)\n            {\n                while (runHi < endExcl && cmp(a[runHi], a[runHi - 1]) < 0)\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && cmp(a[runHi], a[runHi - 1]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        public static void ReverseRange<T>(\n                T[] a,\n                long beginIncl, long endExcl)\n        {\n            endExcl--; // now incorrectly named\n            while (beginIncl < endExcl)\n            {\n                var t = a[beginIncl]; a[beginIncl] = a[endExcl]; a[endExcl] = t;\n                ++beginIncl; --endExcl;\n            }\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a, long med)\n            where T : IComparable<T>\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a,\n                long beginIncl, long endExcl, long med)\n            where T : IComparable<T>\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this T[] a,\n                long l, long r, long countSub1, long med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1].CompareTo(a[e2]) > 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4].CompareTo(a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1].CompareTo(a[e3]) > 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2].CompareTo(a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1].CompareTo(a[e4]) > 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3].CompareTo(a[e4]) > 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2].CompareTo(a[e5]) > 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2].CompareTo(a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4].CompareTo(a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai.CompareTo(p2) > 0)\n                        {\n                            while (a[hi].CompareTo(p2) > 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi].CompareTo(p1) > 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo].CompareTo(p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i].CompareTo(p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi].CompareTo(p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i].CompareTo(p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai.CompareTo(a[j]) < 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this T[] a,\n                long l, long r, long countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1].CompareTo(a[e2]) > 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4].CompareTo(a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1].CompareTo(a[e3]) > 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2].CompareTo(a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1].CompareTo(a[e4]) > 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3].CompareTo(a[e4]) > 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2].CompareTo(a[e5]) > 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2].CompareTo(a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4].CompareTo(a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai.CompareTo(p2) > 0)\n                        {\n                            while (a[hi].CompareTo(p2) > 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi].CompareTo(p1) > 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo].CompareTo(p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i].CompareTo(p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi].CompareTo(p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i].CompareTo(p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai.CompareTo(a[j]) < 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, long begin, long end)\n            where T : IComparable<T>\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element.CompareTo(a[i2 + begin]) < 0)\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin].CompareTo(a[i2 + begin]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin].CompareTo(element) < 0)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element.CompareTo(a[i2]) < 0)\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1].CompareTo(a[i2]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[ni].CompareTo(element) < 0)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this T[] a,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this T[] a,\n                int pshift, long head)\n            where T : IComparable<T>\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val.CompareTo(a[lf]) >= 0 && val.CompareTo(a[rt]) >= 0) break;\n                if (a[lf].CompareTo(a[rt]) >= 0)\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this T[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson.CompareTo(val) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt].CompareTo(vstepson) >= 0 || a[lf].CompareTo(vstepson) >= 0)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLong<T>\n            where T : IComparable<T>\n        {\n            public T[] m_a;\n            public long m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLong(T[] a)\n            {\n                m_a = a;\n                \n                long count = a.LongLength;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            TimSortAscending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<T>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<T>(this TimSortInfoLong<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<T>(this TimSortInfoLong<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<T>(this TimSortInfoLong<T> ti, int i)\n            where T : IComparable<T>\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<T>(this TimSortInfoLong<T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2].CompareTo(t[idx1]) < 0)\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<T>(this TimSortInfoLong<T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2].CompareTo(a[idx1]) < 0)\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<T>(\n                this T[] a,\n                T key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key.CompareTo(a[start + hint]) > 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint + ofs]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint - ofs]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(a[start + m]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<T>(\n                this T[] a,\n                T key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key.CompareTo(a[start + hint]) < 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint - ofs]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint + ofs]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(a[start + m]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this T[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot.CompareTo(a[mid]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending<T>(\n                this T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++].CompareTo(a[beginIncl]) < 0)\n            {\n                while (runHi < endExcl && a[runHi].CompareTo(a[runHi - 1]) < 0)\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi].CompareTo(a[runHi - 1]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a, long med)\n            where T : IComparable<T>\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a,\n                long beginIncl, long endExcl, long med)\n            where T : IComparable<T>\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this T[] a,\n                long l, long r, long countSub1, long med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1].CompareTo(a[e2]) < 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4].CompareTo(a[e5]) < 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1].CompareTo(a[e3]) < 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2].CompareTo(a[e3]) < 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1].CompareTo(a[e4]) < 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3].CompareTo(a[e4]) < 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2].CompareTo(a[e5]) < 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2].CompareTo(a[e3]) < 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4].CompareTo(a[e5]) < 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai.CompareTo(p2) < 0)\n                        {\n                            while (a[hi].CompareTo(p2) < 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi].CompareTo(p1) < 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo].CompareTo(p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i].CompareTo(p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi].CompareTo(p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i].CompareTo(p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai.CompareTo(a[j]) > 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this T[] a,\n                long l, long r, long countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[e1].CompareTo(a[e2]) < 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4].CompareTo(a[e5]) < 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1].CompareTo(a[e3]) < 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2].CompareTo(a[e3]) < 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1].CompareTo(a[e4]) < 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3].CompareTo(a[e4]) < 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2].CompareTo(a[e5]) < 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2].CompareTo(a[e3]) < 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4].CompareTo(a[e5]) < 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai.CompareTo(p2) < 0)\n                        {\n                            while (a[hi].CompareTo(p2) < 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi].CompareTo(p1) < 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo].CompareTo(p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i].CompareTo(p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi].CompareTo(p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i].CompareTo(p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && ai.CompareTo(a[j]) > 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, long begin, long end)\n            where T : IComparable<T>\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element.CompareTo(a[i2 + begin]) > 0)\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1 + begin].CompareTo(a[i2 + begin]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin].CompareTo(element) > 0)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element.CompareTo(a[i2]) > 0)\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[i1].CompareTo(a[i2]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[ni].CompareTo(element) > 0)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this T[] a,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this T[] a,\n                int pshift, long head)\n            where T : IComparable<T>\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val.CompareTo(a[lf]) <= 0 && val.CompareTo(a[rt]) <= 0) break;\n                if (a[lf].CompareTo(a[rt]) <= 0)\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this T[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (vstepson.CompareTo(val) >= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[rt].CompareTo(vstepson) <= 0 || a[lf].CompareTo(vstepson) <= 0)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            TimSortDescending(a, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLong<T>(a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<T>(this TimSortInfoLong<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<T>(this TimSortInfoLong<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<T>(this TimSortInfoLong<T> ti, int i)\n            where T : IComparable<T>\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<T>(this TimSortInfoLong<T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2].CompareTo(t[idx1]) > 0)\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<T>(this TimSortInfoLong<T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2].CompareTo(a[idx1]) > 0)\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<T>(\n                this T[] a,\n                T key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key.CompareTo(a[start + hint]) < 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint + ofs]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint - ofs]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(a[start + m]) < 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<T>(\n                this T[] a,\n                T key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key.CompareTo(a[start + hint]) > 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint - ofs]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint + ofs]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(a[start + m]) > 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this T[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot.CompareTo(a[mid]) > 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending<T>(\n                this T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++].CompareTo(a[beginIncl]) > 0)\n            {\n                while (runHi < endExcl && a[runHi].CompareTo(a[runHi - 1]) > 0)\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi].CompareTo(a[runHi - 1]) <= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a, Func<T, int> selector, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, Func<T, int> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) < selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) < selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1]) < selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) < selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this T[] a,\n                Func<T, int> selector,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) >= selector(a[lf]) && selector(val) >= selector(a[rt])) break;\n                if (selector(a[lf]) >= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[rt]) >= selector(vstepson) || selector(a[lf]) >= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongIntSel<T>\n        {\n            public T[] m_a;\n            public Func<T, int> m_sel;\n            public long m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongIntSel(T[] a, Func<T, int> selector)\n            {\n                m_a = a;\n                m_sel = selector;\n                long count = a.LongLength;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            TimSortAscending(a, selector, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                BinarySortAscending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongIntSel<T>(a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<T>(this TimSortInfoLongIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<T>(this TimSortInfoLongIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<T>(this TimSortInfoLongIntSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<T>(this TimSortInfoLongIntSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) < selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<T>(this TimSortInfoLongIntSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) < selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) < selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) < selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) >= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a, Func<T, int> selector, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, Func<T, int> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) > selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) > selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1]) > selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) > selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this T[] a,\n                Func<T, int> selector,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) <= selector(a[lf]) && selector(val) <= selector(a[rt])) break;\n                if (selector(a[lf]) <= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[rt]) <= selector(vstepson) || selector(a[lf]) <= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            TimSortDescending(a, selector, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                BinarySortDescending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongIntSel<T>(a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<T>(this TimSortInfoLongIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<T>(this TimSortInfoLongIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<T>(this TimSortInfoLongIntSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<T>(this TimSortInfoLongIntSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) > selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<T>(this TimSortInfoLongIntSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) > selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending<T>(\n                this T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) > selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) > selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) <= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a, Func<T, long> selector, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, Func<T, long> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) < selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) < selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1]) < selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) < selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this T[] a,\n                Func<T, long> selector,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) >= selector(a[lf]) && selector(val) >= selector(a[rt])) break;\n                if (selector(a[lf]) >= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[rt]) >= selector(vstepson) || selector(a[lf]) >= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongLongSel<T>\n        {\n            public T[] m_a;\n            public Func<T, long> m_sel;\n            public long m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongLongSel(T[] a, Func<T, long> selector)\n            {\n                m_a = a;\n                m_sel = selector;\n                long count = a.LongLength;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            TimSortAscending(a, selector, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                BinarySortAscending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongLongSel<T>(a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<T>(this TimSortInfoLongLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<T>(this TimSortInfoLongLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<T>(this TimSortInfoLongLongSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<T>(this TimSortInfoLongLongSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) < selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<T>(this TimSortInfoLongLongSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) < selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) < selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) < selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) >= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a, Func<T, long> selector, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, Func<T, long> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) > selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) > selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1]) > selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) > selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this T[] a,\n                Func<T, long> selector,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) <= selector(a[lf]) && selector(val) <= selector(a[rt])) break;\n                if (selector(a[lf]) <= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[rt]) <= selector(vstepson) || selector(a[lf]) <= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            TimSortDescending(a, selector, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                BinarySortDescending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongLongSel<T>(a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<T>(this TimSortInfoLongLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<T>(this TimSortInfoLongLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<T>(this TimSortInfoLongLongSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<T>(this TimSortInfoLongLongSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) > selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<T>(this TimSortInfoLongLongSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) > selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending<T>(\n                this T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) > selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) > selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) <= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a, Func<T, float> selector, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, Func<T, float> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) < selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) < selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1]) < selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) < selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this T[] a,\n                Func<T, float> selector,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) >= selector(a[lf]) && selector(val) >= selector(a[rt])) break;\n                if (selector(a[lf]) >= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[rt]) >= selector(vstepson) || selector(a[lf]) >= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongFloatSel<T>\n        {\n            public T[] m_a;\n            public Func<T, float> m_sel;\n            public long m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongFloatSel(T[] a, Func<T, float> selector)\n            {\n                m_a = a;\n                m_sel = selector;\n                long count = a.LongLength;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            TimSortAscending(a, selector, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                BinarySortAscending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongFloatSel<T>(a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<T>(this TimSortInfoLongFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<T>(this TimSortInfoLongFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<T>(this TimSortInfoLongFloatSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<T>(this TimSortInfoLongFloatSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) < selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<T>(this TimSortInfoLongFloatSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) < selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) < selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) < selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) >= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a, Func<T, float> selector, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, Func<T, float> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) > selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) > selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1]) > selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) > selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this T[] a,\n                Func<T, float> selector,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) <= selector(a[lf]) && selector(val) <= selector(a[rt])) break;\n                if (selector(a[lf]) <= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[rt]) <= selector(vstepson) || selector(a[lf]) <= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            TimSortDescending(a, selector, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                BinarySortDescending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongFloatSel<T>(a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<T>(this TimSortInfoLongFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<T>(this TimSortInfoLongFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<T>(this TimSortInfoLongFloatSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<T>(this TimSortInfoLongFloatSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) > selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<T>(this TimSortInfoLongFloatSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) > selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending<T>(\n                this T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) > selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) > selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) <= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a, Func<T, double> selector, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianAscending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long last = a.LongLength - 1;\n            QuickSortAscending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, Func<T, double> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) < selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) < selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1]) < selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) < selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this T[] a,\n                Func<T, double> selector,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) >= selector(a[lf]) && selector(val) >= selector(a[rt])) break;\n                if (selector(a[lf]) >= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[rt]) >= selector(vstepson) || selector(a[lf]) >= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongDoubleSel<T>\n        {\n            public T[] m_a;\n            public Func<T, double> m_sel;\n            public long m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongDoubleSel(T[] a, Func<T, double> selector)\n            {\n                m_a = a;\n                m_sel = selector;\n                long count = a.LongLength;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            TimSortAscending(a, selector, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                BinarySortAscending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongDoubleSel<T>(a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<T>(this TimSortInfoLongDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<T>(this TimSortInfoLongDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<T>(this TimSortInfoLongDoubleSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<T>(this TimSortInfoLongDoubleSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) < selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<T>(this TimSortInfoLongDoubleSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) < selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderAscending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) < selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) < selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) >= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a, Func<T, double> selector, long med)\n        {\n            long last = a.LongLength - 1;\n            QuickMedianDescending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long last = a.LongLength - 1;\n            QuickSortDescending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, Func<T, double> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) > selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) > selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long count = a.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = a[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[i1]) > selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) > selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, 0, a.LongLength - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this T[] a,\n                Func<T, double> selector,\n                int pshift, long head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) <= selector(a[lf]) && selector(val) <= selector(a[rt])) break;\n                if (selector(a[lf]) <= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[rt]) <= selector(vstepson) || selector(a[lf]) <= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            TimSortDescending(a, selector, 0, a.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                BinarySortDescending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongDoubleSel<T>(a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<T>(this TimSortInfoLongDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<T>(this TimSortInfoLongDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<T>(this TimSortInfoLongDoubleSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<T>(this TimSortInfoLongDoubleSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) > selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<T>(this TimSortInfoLongDoubleSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) > selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: Array.Copy(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static long CountRunAndOrderDescending<T>(\n                this T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) > selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) > selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) <= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for T[]\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedian<T>(\n                this T[] a, Func<T, T, int> cmp, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedian(p, a, cmp, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedian<T>(\n                this int[] p, T[] a, Func<T, T, int> cmp, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedian(p, a, cmp, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedian<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedian(p, a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedian<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (cmp(a[p[e1]], a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e1]], a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e1]], a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e3]], a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e2]], a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = cmp(a[p1], a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(a[ai], a[p2]) > 0)\n                        {\n                            while (cmp(a[p[hi]], a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) == 0) continue;\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[p[hi]], a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (cmp(a[p[lo]], a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[p[i]], a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[p[hi]], a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[p[i]], a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && cmp(a[ai], a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSort<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSort(p, a, cmp, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSort<T>(\n                this int[] p, T[] a, Func<T, T, int> cmp)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSort(p, a, cmp, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSort<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSort(p, a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSort<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (cmp(a[p[e1]], a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e1]], a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e1]], a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e3]], a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e2]], a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = cmp(a[p1], a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(a[ai], a[p2]) > 0)\n                        {\n                            while (cmp(a[p[hi]], a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) == 0) continue;\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[p[hi]], a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                        PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                        {\n                            while (cmp(a[p[lo]], a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[p[i]], a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[p[hi]], a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[p[i]], a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSort(p, a, cmp, lo, hi, cm);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && cmp(a[ai], a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSort<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSort(p, a, cmp);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSort<T>(\n                this int[] p, T[] a, Func<T, T, int> cmp, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (cmp(a[element], a[p[i2 + begin]]) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && cmp(a[p[i1 + begin]], a[p[i2 + begin]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[p[ni + begin]], a[element]) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSort<T>(\n                this int[] p, T[] a, Func<T, T, int> cmp)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (cmp(a[element], a[p[i2]]) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && cmp(a[p[i1]], a[p[i2]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[p[ni]], a[element]) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSort<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSort(p, a, cmp);\n            return p;\n        }\n\n        public static void PermutationSmoothSort<T>(\n                this int[] p, T[] a, Func<T, T, int> cmp)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, cmp, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSort<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, cmp, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortSift(p, a, cmp, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortSift(p, a, cmp, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortTrinkle(p, a, cmp, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortSift<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (cmp(a[val], a[p[lf]]) >= 0 && cmp(a[val], a[p[rt]]) >= 0) break;\n                if (cmp(a[p[lf]], a[p[rt]]) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (cmp(a[vstepson], a[val]) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (cmp(a[p[rt]], a[vstepson]) >= 0 || cmp(a[p[lf]], a[vstepson]) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortSift(p, a, cmp, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermCmp<T>\n        {\n            public int[] m_p;\n            public T[] m_a;\n            public Func<T, T, int> m_cmp;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermCmp(int[] p, T[] a, Func<T, T, int> cmp)\n            {\n                m_p = p; m_a = a;\n                m_cmp = cmp;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSort<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSort(p, a, cmp);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSort<T>(\n                this int[] p, T[] a, Func<T, T, int> cmp)\n        {\n            PermutationTimSort(p, a, cmp, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSort<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrder(p, a, cmp, lo, hi);\n                PermutationBinarySort(p, a, cmp, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermCmp<T>(p, a, cmp);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrder(p, a, cmp, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySort(p, a, cmp, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermCmp(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermCmp(ti);\n        }\n\n        private static void MergeCollapsePermCmp<T>(this TimSortInfoPermCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermCmp(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermCmp(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermCmp<T>(this TimSortInfoPermCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermCmp(ti, n);\n            }\n        }\n\n        private static void MergeAtPermCmp<T>(this TimSortInfoPermCmp<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRight(ti.m_p, a, ti.m_cmp, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeft(ti.m_p, a, ti.m_cmp, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermCmp(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermCmp(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermCmp<T>(this TimSortInfoPermCmp<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(a[p[idx2]], a[t[idx1]]) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRight(t, a, cmp, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeft(p, a, cmp, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermCmp<T>(this TimSortInfoPermCmp<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(a[t[idx2]], a[p[idx1]]) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRight(p, a, cmp, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeft(t, a, cmp, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeft<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (cmp(a[key], a[p[start + hint]]) > 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint + ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint - ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(a[key], a[p[start + m]]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRight<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (cmp(a[key], a[p[start + hint]]) < 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint - ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint + ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(a[key], a[p[start + m]]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySort<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (cmp(a[pivot], a[p[mid]]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrder<T>(\n                this int[] p, T[] a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (cmp(a[p[runHi++]], a[p[beginIncl]]) < 0)\n            {\n                while (runHi < endExcl && cmp(a[p[runHi]], a[p[runHi - 1]]) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && cmp(a[p[runHi]], a[p[runHi - 1]]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianLong<T>(\n                this T[] a, Func<T, T, int> cmp, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedian(p, a, cmp, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedian<T>(\n                this long[] p, T[] a, Func<T, T, int> cmp, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedian(p, a, cmp, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedian<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedian(p, a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedian<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (cmp(a[p[e1]], a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e1]], a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e1]], a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e3]], a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e2]], a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = cmp(a[p1], a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(a[ai], a[p2]) > 0)\n                        {\n                            while (cmp(a[p[hi]], a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) == 0) continue;\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[p[hi]], a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (cmp(a[p[lo]], a[p1]) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[p[i]], a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[p[hi]], a[p2]) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[p[i]], a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && cmp(a[ai], a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortLong<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSort(p, a, cmp, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSort<T>(\n                this long[] p, T[] a, Func<T, T, int> cmp)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSort(p, a, cmp, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSort<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSort(p, a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSort<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (cmp(a[p[e1]], a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e1]], a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e1]], a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e3]], a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e2]], a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = cmp(a[p1], a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(a[ai], a[p2]) > 0)\n                        {\n                            while (cmp(a[p[hi]], a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) == 0) continue;\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[p[hi]], a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                        PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                        {\n                            while (cmp(a[p[lo]], a[p1]) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[p[i]], a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[p[hi]], a[p2]) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[p[i]], a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSort(p, a, cmp, lo, hi, cm);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && cmp(a[ai], a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortLong<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSort(p, a, cmp);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSort<T>(\n                this long[] p, T[] a, Func<T, T, int> cmp, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (cmp(a[element], a[p[i2 + begin]]) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && cmp(a[p[i1 + begin]], a[p[i2 + begin]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[p[ni + begin]], a[element]) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSort<T>(\n                this long[] p, T[] a, Func<T, T, int> cmp)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (cmp(a[element], a[p[i2]]) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && cmp(a[p[i1]], a[p[i2]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[p[ni]], a[element]) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortLong<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSort(p, a, cmp);\n            return p;\n        }\n\n        public static void PermutationSmoothSort<T>(\n                this long[] p, T[] a, Func<T, T, int> cmp)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, cmp, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSort<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, cmp, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortSift(p, a, cmp, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortSift(p, a, cmp, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortTrinkle(p, a, cmp, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortSift<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (cmp(a[val], a[p[lf]]) >= 0 && cmp(a[val], a[p[rt]]) >= 0) break;\n                if (cmp(a[p[lf]], a[p[rt]]) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (cmp(a[vstepson], a[val]) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (cmp(a[p[rt]], a[vstepson]) >= 0 || cmp(a[p[lf]], a[vstepson]) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortSift(p, a, cmp, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongCmp<T>\n        {\n            public long[] m_p;\n            public T[] m_a;\n            public Func<T, T, int> m_cmp;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongCmp(long[] p, T[] a, Func<T, T, int> cmp)\n            {\n                m_p = p; m_a = a;\n                m_cmp = cmp;\n                long count = p.LongLength;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortLong<T>(\n                this T[] a, Func<T, T, int> cmp)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSort(p, a, cmp);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSort<T>(\n                this long[] p, T[] a, Func<T, T, int> cmp)\n        {\n            PermutationTimSort(p, a, cmp, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSort<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrder(p, a, cmp, lo, hi);\n                PermutationBinarySort(p, a, cmp, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongCmp<T>(p, a, cmp);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrder(p, a, cmp, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySort(p, a, cmp, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongCmp(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongCmp(ti);\n        }\n\n        private static void MergeCollapsePermLongCmp<T>(this TimSortInfoPermLongCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongCmp(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongCmp(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongCmp<T>(this TimSortInfoPermLongCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongCmp(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongCmp<T>(this TimSortInfoPermLongCmp<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRight(ti.m_p, a, ti.m_cmp, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeft(ti.m_p, a, ti.m_cmp, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongCmp(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongCmp(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongCmp<T>(this TimSortInfoPermLongCmp<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(a[p[idx2]], a[t[idx1]]) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRight(t, a, cmp, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeft(p, a, cmp, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongCmp<T>(this TimSortInfoPermLongCmp<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(a[t[idx2]], a[p[idx1]]) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRight(p, a, cmp, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeft(t, a, cmp, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeft<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (cmp(a[key], a[p[start + hint]]) > 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint + ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint - ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(a[key], a[p[start + m]]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRight<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (cmp(a[key], a[p[start + hint]]) < 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint - ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint + ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(a[key], a[p[start + m]]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySort<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (cmp(a[pivot], a[p[mid]]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrder<T>(\n                this long[] p, T[] a,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (cmp(a[p[runHi++]], a[p[beginIncl]]) < 0)\n            {\n                while (runHi < endExcl && cmp(a[p[runHi]], a[p[runHi - 1]]) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && cmp(a[p[runHi]], a[p[runHi - 1]]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this T[] a, int med)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a, int med)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl, int med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                int l, int r, int countSub1, int med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) > 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                int l, int r, int countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) > 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, int begin, int end)\n            where T : IComparable<T>\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2 + begin]]) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]].CompareTo(a[p[i2 + begin]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]].CompareTo(a[element]) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a)\n            where T : IComparable<T>\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2]]) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]].CompareTo(a[p[i2]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]].CompareTo(a[element]) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, T[] a,\n                int pshift, int head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val].CompareTo(a[p[lf]]) >= 0 && a[val].CompareTo(a[p[rt]]) >= 0) break;\n                if (a[p[lf]].CompareTo(a[p[rt]]) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, T[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson].CompareTo(a[val]) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]].CompareTo(a[vstepson]) >= 0 || a[p[lf]].CompareTo(a[vstepson]) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPerm<T>\n            where T : IComparable<T>\n        {\n            public int[] m_p;\n            public T[] m_a;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPerm(int[] p, T[] a)\n            {\n                m_p = p; m_a = a;\n                \n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a)\n            where T : IComparable<T>\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<T>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<T>(this TimSortInfoPerm<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<T>(this TimSortInfoPerm<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<T>(this TimSortInfoPerm<T> ti, int i)\n            where T : IComparable<T>\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<T>(this TimSortInfoPerm<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]].CompareTo(a[t[idx1]]) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<T>(this TimSortInfoPerm<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]].CompareTo(a[p[idx1]]) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, T[] a,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key].CompareTo(a[p[start + hint]]) > 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, T[] a,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key].CompareTo(a[p[start + hint]]) < 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot].CompareTo(a[p[mid]]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]].CompareTo(a[p[beginIncl]]) < 0)\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong<T>(\n                this T[] a, long med)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a, long med)\n            where T : IComparable<T>\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl, long med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                long l, long r, long countSub1, long med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) > 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a)\n            where T : IComparable<T>\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                long l, long r, long countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) > 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, long begin, long end)\n            where T : IComparable<T>\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2 + begin]]) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]].CompareTo(a[p[i2 + begin]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]].CompareTo(a[element]) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a)\n            where T : IComparable<T>\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2]]) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]].CompareTo(a[p[i2]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]].CompareTo(a[element]) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this long[] p, T[] a,\n                int pshift, long head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val].CompareTo(a[p[lf]]) >= 0 && a[val].CompareTo(a[p[rt]]) >= 0) break;\n                if (a[p[lf]].CompareTo(a[p[rt]]) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this long[] p, T[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson].CompareTo(a[val]) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]].CompareTo(a[vstepson]) >= 0 || a[p[lf]].CompareTo(a[vstepson]) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLong<T>\n            where T : IComparable<T>\n        {\n            public long[] m_p;\n            public T[] m_a;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLong(long[] p, T[] a)\n            {\n                m_p = p; m_a = a;\n                \n                long count = p.LongLength;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a)\n            where T : IComparable<T>\n        {\n            PermutationTimSortAscending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<T>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<T>(this TimSortInfoPermLong<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<T>(this TimSortInfoPermLong<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<T>(this TimSortInfoPermLong<T> ti, int i)\n            where T : IComparable<T>\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<T>(this TimSortInfoPermLong<T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]].CompareTo(a[t[idx1]]) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<T>(this TimSortInfoPermLong<T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]].CompareTo(a[p[idx1]]) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<T>(\n                this long[] p, T[] a,\n                long key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key].CompareTo(a[p[start + hint]]) > 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<T>(\n                this long[] p, T[] a,\n                long key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key].CompareTo(a[p[start + hint]]) < 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot].CompareTo(a[p[mid]]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]].CompareTo(a[p[beginIncl]]) < 0)\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this T[] a, int med)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a, int med)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl, int med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                int l, int r, int countSub1, int med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) < 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                int l, int r, int countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) < 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, int begin, int end)\n            where T : IComparable<T>\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2 + begin]]) > 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]].CompareTo(a[p[i2 + begin]]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]].CompareTo(a[element]) > 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a)\n            where T : IComparable<T>\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2]]) > 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]].CompareTo(a[p[i2]]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]].CompareTo(a[element]) > 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, T[] a,\n                int pshift, int head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val].CompareTo(a[p[lf]]) <= 0 && a[val].CompareTo(a[p[rt]]) <= 0) break;\n                if (a[p[lf]].CompareTo(a[p[rt]]) <= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, T[] a,\n                long pbits, int pshift, int head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson].CompareTo(a[val]) >= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]].CompareTo(a[vstepson]) <= 0 || a[p[lf]].CompareTo(a[vstepson]) <= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a)\n            where T : IComparable<T>\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPerm<T>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<T>(this TimSortInfoPerm<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<T>(this TimSortInfoPerm<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<T>(this TimSortInfoPerm<T> ti, int i)\n            where T : IComparable<T>\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<T>(this TimSortInfoPerm<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]].CompareTo(a[t[idx1]]) > 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<T>(this TimSortInfoPerm<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]].CompareTo(a[p[idx1]]) > 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, T[] a,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key].CompareTo(a[p[start + hint]]) < 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) < 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, T[] a,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key].CompareTo(a[p[start + hint]]) > 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) > 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl, int beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot].CompareTo(a[p[mid]]) > 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, T[] a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]].CompareTo(a[p[beginIncl]]) > 0)\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) > 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) <= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong<T>(\n                this T[] a, long med)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a, long med)\n            where T : IComparable<T>\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl, long med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                long l, long r, long countSub1, long med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) < 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a)\n            where T : IComparable<T>\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                long l, long r, long countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) < 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, long begin, long end)\n            where T : IComparable<T>\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2 + begin]]) > 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1 + begin]].CompareTo(a[p[i2 + begin]]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]].CompareTo(a[element]) > 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a)\n            where T : IComparable<T>\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2]]) > 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && a[p[i1]].CompareTo(a[p[i2]]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]].CompareTo(a[element]) > 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this long[] p, T[] a,\n                int pshift, long head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (a[val].CompareTo(a[p[lf]]) <= 0 && a[val].CompareTo(a[p[rt]]) <= 0) break;\n                if (a[p[lf]].CompareTo(a[p[rt]]) <= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this long[] p, T[] a,\n                long pbits, int pshift, long head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson].CompareTo(a[val]) >= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (a[p[rt]].CompareTo(a[vstepson]) <= 0 || a[p[lf]].CompareTo(a[vstepson]) <= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong<T>(\n                this T[] a)\n            where T : IComparable<T>\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a)\n            where T : IComparable<T>\n        {\n            PermutationTimSortDescending(p, a, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLong<T>(p, a);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<T>(this TimSortInfoPermLong<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<T>(this TimSortInfoPermLong<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<T>(this TimSortInfoPermLong<T> ti, int i)\n            where T : IComparable<T>\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<T>(this TimSortInfoPermLong<T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]].CompareTo(a[t[idx1]]) > 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<T>(this TimSortInfoPermLong<T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]].CompareTo(a[p[idx1]]) > 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<T>(\n                this long[] p, T[] a,\n                long key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long lastOfs = 0, ofs = 1;\n            if (a[key].CompareTo(a[p[start + hint]]) < 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) < 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<T>(\n                this long[] p, T[] a,\n                long key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long ofs = 1, lastOfs = 0;\n            if (a[key].CompareTo(a[p[start + hint]]) > 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) > 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl, long beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (a[pivot].CompareTo(a[p[mid]]) > 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<T>(\n                this long[] p, T[] a,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]].CompareTo(a[p[beginIncl]]) > 0)\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) > 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) <= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this T[] a, Func<T, int> selector, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a, Func<T, int> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a, Func<T, int> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, Func<T, int> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, Func<T, int> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a, Func<T, int> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermIntSel<T>\n        {\n            public int[] m_p;\n            public T[] m_a;\n            public Func<T, int> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermIntSel(int[] p, T[] a, Func<T, int> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a, Func<T, int> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermIntSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<T>(this TimSortInfoPermIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<T>(this TimSortInfoPermIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<T>(this TimSortInfoPermIntSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<T>(this TimSortInfoPermIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<T>(this TimSortInfoPermIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong<T>(\n                this T[] a, Func<T, int> selector, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a, Func<T, int> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a, Func<T, int> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, Func<T, int> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, Func<T, int> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a, Func<T, int> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongIntSel<T>\n        {\n            public long[] m_p;\n            public T[] m_a;\n            public Func<T, int> m_sel;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongIntSel(long[] p, T[] a, Func<T, int> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                long count = p.LongLength;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a, Func<T, int> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongIntSel<T>(p, a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<T>(this TimSortInfoPermLongIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<T>(this TimSortInfoPermLongIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<T>(this TimSortInfoPermLongIntSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<T>(this TimSortInfoPermLongIntSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<T>(this TimSortInfoPermLongIntSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this T[] a, Func<T, int> selector, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a, Func<T, int> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a, Func<T, int> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, Func<T, int> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, Func<T, int> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a, Func<T, int> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a, Func<T, int> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermIntSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<T>(this TimSortInfoPermIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<T>(this TimSortInfoPermIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<T>(this TimSortInfoPermIntSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<T>(this TimSortInfoPermIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<T>(this TimSortInfoPermIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, T[] a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong<T>(\n                this T[] a, Func<T, int> selector, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a, Func<T, int> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a, Func<T, int> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, Func<T, int> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, Func<T, int> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a, Func<T, int> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong<T>(\n                this T[] a, Func<T, int> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a, Func<T, int> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongIntSel<T>(p, a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<T>(this TimSortInfoPermLongIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<T>(this TimSortInfoPermLongIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<T>(this TimSortInfoPermLongIntSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<T>(this TimSortInfoPermLongIntSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<T>(this TimSortInfoPermLongIntSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<T>(\n                this long[] p, T[] a,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this T[] a, Func<T, long> selector, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a, Func<T, long> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a, Func<T, long> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, Func<T, long> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, Func<T, long> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a, Func<T, long> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongSel<T>\n        {\n            public int[] m_p;\n            public T[] m_a;\n            public Func<T, long> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermLongSel(int[] p, T[] a, Func<T, long> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a, Func<T, long> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<T>(this TimSortInfoPermLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<T>(this TimSortInfoPermLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<T>(this TimSortInfoPermLongSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<T>(this TimSortInfoPermLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<T>(this TimSortInfoPermLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong<T>(\n                this T[] a, Func<T, long> selector, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a, Func<T, long> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a, Func<T, long> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, Func<T, long> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, Func<T, long> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a, Func<T, long> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongLongSel<T>\n        {\n            public long[] m_p;\n            public T[] m_a;\n            public Func<T, long> m_sel;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongLongSel(long[] p, T[] a, Func<T, long> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                long count = p.LongLength;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a, Func<T, long> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongLongSel<T>(p, a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<T>(this TimSortInfoPermLongLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<T>(this TimSortInfoPermLongLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<T>(this TimSortInfoPermLongLongSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<T>(this TimSortInfoPermLongLongSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<T>(this TimSortInfoPermLongLongSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this T[] a, Func<T, long> selector, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a, Func<T, long> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a, Func<T, long> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, Func<T, long> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, Func<T, long> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a, Func<T, long> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a, Func<T, long> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<T>(this TimSortInfoPermLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<T>(this TimSortInfoPermLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<T>(this TimSortInfoPermLongSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<T>(this TimSortInfoPermLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<T>(this TimSortInfoPermLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, T[] a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong<T>(\n                this T[] a, Func<T, long> selector, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a, Func<T, long> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a, Func<T, long> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, Func<T, long> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, Func<T, long> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a, Func<T, long> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong<T>(\n                this T[] a, Func<T, long> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a, Func<T, long> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongLongSel<T>(p, a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<T>(this TimSortInfoPermLongLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<T>(this TimSortInfoPermLongLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<T>(this TimSortInfoPermLongLongSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<T>(this TimSortInfoPermLongLongSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<T>(this TimSortInfoPermLongLongSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<T>(\n                this long[] p, T[] a,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this T[] a, Func<T, float> selector, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a, Func<T, float> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a, Func<T, float> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, Func<T, float> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, Func<T, float> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a, Func<T, float> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermFloatSel<T>\n        {\n            public int[] m_p;\n            public T[] m_a;\n            public Func<T, float> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermFloatSel(int[] p, T[] a, Func<T, float> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a, Func<T, float> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermFloatSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<T>(this TimSortInfoPermFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<T>(this TimSortInfoPermFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<T>(this TimSortInfoPermFloatSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<T>(this TimSortInfoPermFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<T>(this TimSortInfoPermFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong<T>(\n                this T[] a, Func<T, float> selector, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a, Func<T, float> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a, Func<T, float> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, Func<T, float> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, Func<T, float> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a, Func<T, float> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongFloatSel<T>\n        {\n            public long[] m_p;\n            public T[] m_a;\n            public Func<T, float> m_sel;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongFloatSel(long[] p, T[] a, Func<T, float> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                long count = p.LongLength;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a, Func<T, float> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongFloatSel<T>(p, a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<T>(this TimSortInfoPermLongFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<T>(this TimSortInfoPermLongFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<T>(this TimSortInfoPermLongFloatSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<T>(this TimSortInfoPermLongFloatSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<T>(this TimSortInfoPermLongFloatSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this T[] a, Func<T, float> selector, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a, Func<T, float> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a, Func<T, float> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, Func<T, float> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, Func<T, float> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a, Func<T, float> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a, Func<T, float> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermFloatSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<T>(this TimSortInfoPermFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<T>(this TimSortInfoPermFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<T>(this TimSortInfoPermFloatSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<T>(this TimSortInfoPermFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<T>(this TimSortInfoPermFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, T[] a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong<T>(\n                this T[] a, Func<T, float> selector, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a, Func<T, float> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a, Func<T, float> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, Func<T, float> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, Func<T, float> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a, Func<T, float> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong<T>(\n                this T[] a, Func<T, float> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a, Func<T, float> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongFloatSel<T>(p, a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<T>(this TimSortInfoPermLongFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<T>(this TimSortInfoPermLongFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<T>(this TimSortInfoPermLongFloatSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<T>(this TimSortInfoPermLongFloatSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<T>(this TimSortInfoPermLongFloatSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<T>(\n                this long[] p, T[] a,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this T[] a, Func<T, double> selector, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a, Func<T, double> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a, Func<T, double> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, Func<T, double> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, T[] a, Func<T, double> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a, Func<T, double> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermDoubleSel<T>\n        {\n            public int[] m_p;\n            public T[] m_a;\n            public Func<T, double> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermDoubleSel(int[] p, T[] a, Func<T, double> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a, Func<T, double> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermDoubleSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<T>(this TimSortInfoPermDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<T>(this TimSortInfoPermDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<T>(this TimSortInfoPermDoubleSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<T>(this TimSortInfoPermDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<T>(this TimSortInfoPermDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianAscendingLong<T>(\n                this T[] a, Func<T, double> selector, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a, Func<T, double> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortAscendingLong<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a, Func<T, double> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortAscendingLong<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, Func<T, double> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this long[] p, T[] a, Func<T, double> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortAscendingLong<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a, Func<T, double> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongDoubleSel<T>\n        {\n            public long[] m_p;\n            public T[] m_a;\n            public Func<T, double> m_sel;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongDoubleSel(long[] p, T[] a, Func<T, double> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                long count = p.LongLength;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortAscendingLong<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a, Func<T, double> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongDoubleSel<T>(p, a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<T>(this TimSortInfoPermLongDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<T>(this TimSortInfoPermLongDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<T>(this TimSortInfoPermLongDoubleSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<T>(this TimSortInfoPermLongDoubleSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<T>(this TimSortInfoPermLongDoubleSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this T[] a, Func<T, double> selector, int med)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a, Func<T, double> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a, Func<T, double> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, Func<T, double> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, T[] a, Func<T, double> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a, Func<T, double> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            int len = a.Length;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a, Func<T, double> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermDoubleSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<T>(this TimSortInfoPermDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<T>(this TimSortInfoPermDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<T>(this TimSortInfoPermDoubleSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<T>(this TimSortInfoPermDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<T>(this TimSortInfoPermDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, T[] a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static long[] CreatePermutationQuickMedianDescendingLong<T>(\n                this T[] a, Func<T, double> selector, long med)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a, Func<T, double> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static long[] CreatePermutationQuickSortDescendingLong<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a, Func<T, double> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static long[] CreatePermutationHeapSortDescendingLong<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, Func<T, double> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this long[] p, T[] a, Func<T, double> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static long[] CreatePermutationSmoothSortDescendingLong<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a, Func<T, double> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.LongLength - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static long[] CreatePermutationTimSortDescendingLong<T>(\n                this T[] a, Func<T, double> selector)\n        {\n            long len = a.LongLength;\n            var p = new long[len].SetByIndexLong(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a, Func<T, double> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongDoubleSel<T>(p, a, selector);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<T>(this TimSortInfoPermLongDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<T>(this TimSortInfoPermLongDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<T>(this TimSortInfoPermLongDoubleSel<T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<T>(this TimSortInfoPermLongDoubleSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<T>(this TimSortInfoPermLongDoubleSel<T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<T>(\n                this long[] p, T[] a,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for List<T>\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedian<T>(\n                this List<T> a, Func<T, T, int> cmp, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedian(a, cmp, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedian<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedian(a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedian<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (cmp(a[e1], a[e2]) > 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (cmp(a[e4], a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (cmp(a[e1], a[e3]) > 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (cmp(a[e2], a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (cmp(a[e1], a[e4]) > 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (cmp(a[e3], a[e4]) > 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (cmp(a[e2], a[e5]) > 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (cmp(a[e2], a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (cmp(a[e4], a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = cmp(p1, p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (cmp(ai, p2) > 0)\n                        {\n                            while (cmp(a[hi], p2) > 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (cmp(ai, p1) == 0) continue;\n                        if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[hi], p1) > 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (cmp(a[lo], p1) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[i], p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[hi], p2) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[i], p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && cmp(ai, a[j]) < 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSort<T>(\n                this List<T> a, Func<T, T, int> cmp)\n        {\n            int last = a.Count - 1;\n            QuickSort(a, cmp, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSort<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            QuickSort(a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSort<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (cmp(a[e1], a[e2]) > 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (cmp(a[e4], a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (cmp(a[e1], a[e3]) > 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (cmp(a[e2], a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (cmp(a[e1], a[e4]) > 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (cmp(a[e3], a[e4]) > 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (cmp(a[e2], a[e5]) > 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (cmp(a[e2], a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (cmp(a[e4], a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = cmp(p1, p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (cmp(ai, p2) > 0)\n                        {\n                            while (cmp(a[hi], p2) > 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (cmp(ai, p1) == 0) continue;\n                        if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[hi], p1) > 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (cmp(ai, p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSort(a, cmp, l, lo - 2, cl);\n                        QuickSort(a, cmp, hi + 2, r, cr);\n                        {\n                            while (cmp(a[lo], p1) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[i], p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[hi], p2) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[i], p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSort(a, cmp, lo, hi, cm);\n                                QuickSort(a, cmp, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSort(a, cmp, l, lo - 2, cl);\n                                QuickSort(a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSort(a, cmp, l, lo - 2, cl);\n                                QuickSort(a, cmp, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSort(a, cmp, l, lo - 2, cl);\n                                QuickSort(a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSort(a, cmp, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSort(a, cmp, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && cmp(ai, a[j]) < 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSort<T>(\n                this List<T> a, Func<T, T, int> cmp, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (cmp(element, a[i2 + begin]) < 0)\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && cmp(a[i1 + begin], a[i2 + begin]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[ni + begin], element) < 0)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSort<T>(\n                this List<T> a, Func<T, T, int> cmp)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (cmp(element, a[i2]) < 0)\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && cmp(a[i1], a[i2]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[ni], element) < 0)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSort<T>(\n                this List<T> a, Func<T, T, int> cmp)\n        {\n            SmoothSortInclusiveRange(a, cmp, 0, a.Count - 1);\n        }\n\n        public static void SmoothSort<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortInclusiveRange(a, cmp, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortInclusiveRange<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortSift(a, cmp, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortTrinkle(a, cmp, pbits, pshift, head, false);\n                    else\n                        SmoothSortSift(a, cmp, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortTrinkle(a, cmp, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortTrinkle(a, cmp, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortTrinkle(a, cmp, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortSift<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (cmp(val, a[lf]) >= 0 && cmp(val, a[rt]) >= 0) break;\n                if (cmp(a[lf], a[rt]) >= 0)\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortTrinkle<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (cmp(vstepson, val) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (cmp(a[rt], vstepson) >= 0 || cmp(a[lf], vstepson) >= 0)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortSift(a, cmp, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListCmp<T>\n        {\n            public List<T> m_a;\n            public Func<T, T, int> m_cmp;\n            public int m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListCmp(List<T> a, Func<T, T, int> cmp)\n            {\n                m_a = a;\n                m_cmp = cmp;\n                int count = a.Count;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.Count >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSort<T>(\n                this List<T> a, Func<T, T, int> cmp)\n        {\n            TimSort(a, cmp, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSort<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrder(a, cmp, lo, hi);\n                BinarySort(a, cmp, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListCmp<T>(a, cmp);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrder(a, cmp, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySort(a, cmp, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListCmp(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListCmp(ti);\n        }\n\n        private static void MergeCollapseListCmp<T>(this TimSortInfoListCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListCmp(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListCmp(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListCmp<T>(this TimSortInfoListCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListCmp(ti, n);\n            }\n        }\n\n        private static void MergeAtListCmp<T>(this TimSortInfoListCmp<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRight(a, ti.m_cmp, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeft(a, ti.m_cmp, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListCmp(ti, start1, len1, start2, len2);\n            else\n                MergeHiListCmp(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListCmp<T>(this TimSortInfoListCmp<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(a[idx2], t[idx1]) < 0)\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRight(t, cmp, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeft(a, cmp, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListCmp<T>(this TimSortInfoListCmp<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(t[idx2], a[idx1]) < 0)\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRight(a, cmp, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeft(t, cmp, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeft<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (cmp(key, a[start + hint]) > 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(key, a[start + hint + ofs]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(key, a[start + hint - ofs]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(key, a[start + m]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRight<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (cmp(key, a[start + hint]) < 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(key, a[start + hint - ofs]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(key, a[start + hint + ofs]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(key, a[start + m]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySort<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (cmp(pivot, a[mid]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrder<T>(\n                this List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (cmp(a[runHi++], a[beginIncl]) < 0)\n            {\n                while (runHi < endExcl && cmp(a[runHi], a[runHi - 1]) < 0)\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && cmp(a[runHi], a[runHi - 1]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        public static void ReverseRange<T>(\n                List<T> a,\n                int beginIncl, int endExcl)\n        {\n            endExcl--; // now incorrectly named\n            while (beginIncl < endExcl)\n            {\n                var t = a[beginIncl]; a[beginIncl] = a[endExcl]; a[endExcl] = t;\n                ++beginIncl; --endExcl;\n            }\n        }\n\n        private static void CopyElements<T>(\n                List<T> src, int start, List<T> dst, int dstStart, int count)\n        {\n            for (var end = start + count; start < end; start++, dstStart++)\n                dst[dstStart] = src[start];\n        }\n\n        private static void CopyElements<T>(\n                List<T> src, int start, T[] dst, int dstStart, int count)\n        {\n            for (var end = start + count; start < end; start++, dstStart++)\n                dst[dstStart] = src[start];\n        }\n\n        private static void CopyElements<T>(\n                T[] src, int start, List<T> dst, int dstStart, int count)\n        {\n            for (var end = start + count; start < end; start++, dstStart++)\n                dst[dstStart] = src[start];\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a, int med)\n            where T : IComparable<T>\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl, int med)\n            where T : IComparable<T>\n        {\n            QuickMedianAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this List<T> a,\n                int l, int r, int countSub1, int med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1].CompareTo(a[e2]) > 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4].CompareTo(a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1].CompareTo(a[e3]) > 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2].CompareTo(a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1].CompareTo(a[e4]) > 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3].CompareTo(a[e4]) > 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2].CompareTo(a[e5]) > 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2].CompareTo(a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4].CompareTo(a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai.CompareTo(p2) > 0)\n                        {\n                            while (a[hi].CompareTo(p2) > 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi].CompareTo(p1) > 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo].CompareTo(p1) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i].CompareTo(p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi].CompareTo(p2) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i].CompareTo(p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai.CompareTo(a[j]) < 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            QuickSortAscending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this List<T> a,\n                int l, int r, int countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1].CompareTo(a[e2]) > 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4].CompareTo(a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1].CompareTo(a[e3]) > 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2].CompareTo(a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1].CompareTo(a[e4]) > 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3].CompareTo(a[e4]) > 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2].CompareTo(a[e5]) > 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2].CompareTo(a[e3]) > 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4].CompareTo(a[e5]) > 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai.CompareTo(p2) > 0)\n                        {\n                            while (a[hi].CompareTo(p2) > 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi].CompareTo(p1) > 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) < 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo].CompareTo(p1) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i].CompareTo(p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi].CompareTo(p2) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i].CompareTo(p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, lo, hi, cm);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, l, lo - 2, cl);\n                                QuickSortAscending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai.CompareTo(a[j]) < 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, int begin, int end)\n            where T : IComparable<T>\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element.CompareTo(a[i2 + begin]) < 0)\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin].CompareTo(a[i2 + begin]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin].CompareTo(element) < 0)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element.CompareTo(a[i2]) < 0)\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1].CompareTo(a[i2]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[ni].CompareTo(element) < 0)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            SmoothSortAscendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            SmoothSortAscendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this List<T> a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this List<T> a,\n                int pshift, int head)\n            where T : IComparable<T>\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val.CompareTo(a[lf]) >= 0 && val.CompareTo(a[rt]) >= 0) break;\n                if (a[lf].CompareTo(a[rt]) >= 0)\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this List<T> a,\n                long pbits, int pshift, int head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson.CompareTo(val) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt].CompareTo(vstepson) >= 0 || a[lf].CompareTo(vstepson) >= 0)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, pshift, head);\n            }\n        }\n\n        public class TimSortInfoList<T>\n            where T : IComparable<T>\n        {\n            public List<T> m_a;\n            public int m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoList(List<T> a)\n            {\n                m_a = a;\n                \n                int count = a.Count;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.Count >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            TimSortAscending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, lo, hi);\n                BinarySortAscending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<T>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListAsc(ti);\n        }\n\n        private static void MergeCollapseListAsc<T>(this TimSortInfoList<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListAsc<T>(this TimSortInfoList<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListAsc<T>(this TimSortInfoList<T> ti, int i)\n            where T : IComparable<T>\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListAsc<T>(this TimSortInfoList<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2].CompareTo(t[idx1]) < 0)\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListAsc<T>(this TimSortInfoList<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2].CompareTo(a[idx1]) < 0)\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending<T>(\n                this List<T> a,\n                T key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key.CompareTo(a[start + hint]) > 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint + ofs]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint - ofs]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(a[start + m]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending<T>(\n                this List<T> a,\n                T key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key.CompareTo(a[start + hint]) < 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint - ofs]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint + ofs]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(a[start + m]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot.CompareTo(a[mid]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++].CompareTo(a[beginIncl]) < 0)\n            {\n                while (runHi < endExcl && a[runHi].CompareTo(a[runHi - 1]) < 0)\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi].CompareTo(a[runHi - 1]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a, int med)\n            where T : IComparable<T>\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl, int med)\n            where T : IComparable<T>\n        {\n            QuickMedianDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this List<T> a,\n                int l, int r, int countSub1, int med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1].CompareTo(a[e2]) < 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4].CompareTo(a[e5]) < 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1].CompareTo(a[e3]) < 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2].CompareTo(a[e3]) < 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1].CompareTo(a[e4]) < 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3].CompareTo(a[e4]) < 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2].CompareTo(a[e5]) < 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2].CompareTo(a[e3]) < 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4].CompareTo(a[e5]) < 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai.CompareTo(p2) < 0)\n                        {\n                            while (a[hi].CompareTo(p2) < 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi].CompareTo(p1) < 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[lo].CompareTo(p1) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i].CompareTo(p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi].CompareTo(p2) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i].CompareTo(p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai.CompareTo(a[j]) > 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            QuickSortDescending(a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this List<T> a,\n                int l, int r, int countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[e1].CompareTo(a[e2]) < 0) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (a[e4].CompareTo(a[e5]) < 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (a[e1].CompareTo(a[e3]) < 0) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (a[e2].CompareTo(a[e3]) < 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e1].CompareTo(a[e4]) < 0) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (a[e3].CompareTo(a[e4]) < 0) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (a[e2].CompareTo(a[e5]) < 0) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (a[e2].CompareTo(a[e3]) < 0) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (a[e4].CompareTo(a[e5]) < 0) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (ai.CompareTo(p2) < 0)\n                        {\n                            while (a[hi].CompareTo(p2) < 0 && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[hi].CompareTo(p1) < 0)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (ai.CompareTo(p1) > 0) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        {\n                            while (a[lo].CompareTo(p1) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[i].CompareTo(p1) == 0) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (a[hi].CompareTo(p2) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[i].CompareTo(p2) == 0) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, lo, hi, cm);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, l, lo - 2, cl);\n                                QuickSortDescending(a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && ai.CompareTo(a[j]) > 0; j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, int begin, int end)\n            where T : IComparable<T>\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element.CompareTo(a[i2 + begin]) > 0)\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1 + begin].CompareTo(a[i2 + begin]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[ni + begin].CompareTo(element) > 0)\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (element.CompareTo(a[i2]) > 0)\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[i1].CompareTo(a[i2]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[ni].CompareTo(element) > 0)\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            SmoothSortDescendingInclusiveRange(a, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            SmoothSortDescendingInclusiveRange(a, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this List<T> a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this List<T> a,\n                int pshift, int head)\n            where T : IComparable<T>\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (val.CompareTo(a[lf]) <= 0 && val.CompareTo(a[rt]) <= 0) break;\n                if (a[lf].CompareTo(a[rt]) <= 0)\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this List<T> a,\n                long pbits, int pshift, int head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (vstepson.CompareTo(val) >= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[rt].CompareTo(vstepson) <= 0 || a[lf].CompareTo(vstepson) <= 0)\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            TimSortDescending(a, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, lo, hi);\n                BinarySortDescending(a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoList<T>(a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListDesc(ti);\n        }\n\n        private static void MergeCollapseListDesc<T>(this TimSortInfoList<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListDesc<T>(this TimSortInfoList<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListDesc<T>(this TimSortInfoList<T> ti, int i)\n            where T : IComparable<T>\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListDesc<T>(this TimSortInfoList<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[idx2].CompareTo(t[idx1]) > 0)\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListDesc<T>(this TimSortInfoList<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (t[idx2].CompareTo(a[idx1]) > 0)\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending<T>(\n                this List<T> a,\n                T key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int lastOfs = 0, ofs = 1;\n            if (key.CompareTo(a[start + hint]) < 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint + ofs]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint - ofs]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(a[start + m]) < 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending<T>(\n                this List<T> a,\n                T key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int ofs = 1, lastOfs = 0;\n            if (key.CompareTo(a[start + hint]) > 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint - ofs]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(a[start + hint + ofs]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(a[start + m]) > 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (pivot.CompareTo(a[mid]) > 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending<T>(\n                this List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[runHi++].CompareTo(a[beginIncl]) > 0)\n            {\n                while (runHi < endExcl && a[runHi].CompareTo(a[runHi - 1]) > 0)\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[runHi].CompareTo(a[runHi - 1]) <= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a, Func<T, int> selector, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            QuickSortAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, Func<T, int> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) < selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) < selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1]) < selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) < selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(val) >= selector(a[lf]) && selector(val) >= selector(a[rt])) break;\n                if (selector(a[lf]) >= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[rt]) >= selector(vstepson) || selector(a[lf]) >= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListIntSel<T>\n        {\n            public List<T> m_a;\n            public Func<T, int> m_sel;\n            public int m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListIntSel(List<T> a, Func<T, int> selector)\n            {\n                m_a = a;\n                m_sel = selector;\n                int count = a.Count;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.Count >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            TimSortAscending(a, selector, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                BinarySortAscending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListIntSel<T>(a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListAsc(ti);\n        }\n\n        private static void MergeCollapseListAsc<T>(this TimSortInfoListIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListAsc<T>(this TimSortInfoListIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListAsc<T>(this TimSortInfoListIntSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListAsc<T>(this TimSortInfoListIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) < selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListAsc<T>(this TimSortInfoListIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) < selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) < selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) < selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) >= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a, Func<T, int> selector, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            QuickSortDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, Func<T, int> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) > selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) > selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1]) > selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) > selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(val) <= selector(a[lf]) && selector(val) <= selector(a[rt])) break;\n                if (selector(a[lf]) <= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[rt]) <= selector(vstepson) || selector(a[lf]) <= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            TimSortDescending(a, selector, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                BinarySortDescending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListIntSel<T>(a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListDesc(ti);\n        }\n\n        private static void MergeCollapseListDesc<T>(this TimSortInfoListIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListDesc<T>(this TimSortInfoListIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListDesc<T>(this TimSortInfoListIntSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListDesc<T>(this TimSortInfoListIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) > selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListDesc<T>(this TimSortInfoListIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) > selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending<T>(\n                this List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) > selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) > selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) <= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a, Func<T, long> selector, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            QuickSortAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, Func<T, long> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) < selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) < selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1]) < selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) < selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(val) >= selector(a[lf]) && selector(val) >= selector(a[rt])) break;\n                if (selector(a[lf]) >= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[rt]) >= selector(vstepson) || selector(a[lf]) >= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListLongSel<T>\n        {\n            public List<T> m_a;\n            public Func<T, long> m_sel;\n            public int m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListLongSel(List<T> a, Func<T, long> selector)\n            {\n                m_a = a;\n                m_sel = selector;\n                int count = a.Count;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.Count >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            TimSortAscending(a, selector, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                BinarySortAscending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListLongSel<T>(a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListAsc(ti);\n        }\n\n        private static void MergeCollapseListAsc<T>(this TimSortInfoListLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListAsc<T>(this TimSortInfoListLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListAsc<T>(this TimSortInfoListLongSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListAsc<T>(this TimSortInfoListLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) < selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListAsc<T>(this TimSortInfoListLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) < selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) < selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) < selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) >= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a, Func<T, long> selector, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            QuickSortDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, Func<T, long> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) > selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) > selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1]) > selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) > selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(val) <= selector(a[lf]) && selector(val) <= selector(a[rt])) break;\n                if (selector(a[lf]) <= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[rt]) <= selector(vstepson) || selector(a[lf]) <= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            TimSortDescending(a, selector, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                BinarySortDescending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListLongSel<T>(a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListDesc(ti);\n        }\n\n        private static void MergeCollapseListDesc<T>(this TimSortInfoListLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListDesc<T>(this TimSortInfoListLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListDesc<T>(this TimSortInfoListLongSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListDesc<T>(this TimSortInfoListLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) > selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListDesc<T>(this TimSortInfoListLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) > selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending<T>(\n                this List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) > selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) > selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) <= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a, Func<T, float> selector, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            QuickSortAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, Func<T, float> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) < selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) < selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1]) < selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) < selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(val) >= selector(a[lf]) && selector(val) >= selector(a[rt])) break;\n                if (selector(a[lf]) >= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[rt]) >= selector(vstepson) || selector(a[lf]) >= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListFloatSel<T>\n        {\n            public List<T> m_a;\n            public Func<T, float> m_sel;\n            public int m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListFloatSel(List<T> a, Func<T, float> selector)\n            {\n                m_a = a;\n                m_sel = selector;\n                int count = a.Count;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.Count >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            TimSortAscending(a, selector, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                BinarySortAscending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListFloatSel<T>(a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListAsc(ti);\n        }\n\n        private static void MergeCollapseListAsc<T>(this TimSortInfoListFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListAsc<T>(this TimSortInfoListFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListAsc<T>(this TimSortInfoListFloatSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListAsc<T>(this TimSortInfoListFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) < selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListAsc<T>(this TimSortInfoListFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) < selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) < selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) < selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) >= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a, Func<T, float> selector, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            QuickSortDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, Func<T, float> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) > selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) > selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1]) > selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) > selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(val) <= selector(a[lf]) && selector(val) <= selector(a[rt])) break;\n                if (selector(a[lf]) <= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[rt]) <= selector(vstepson) || selector(a[lf]) <= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            TimSortDescending(a, selector, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                BinarySortDescending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListFloatSel<T>(a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListDesc(ti);\n        }\n\n        private static void MergeCollapseListDesc<T>(this TimSortInfoListFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListDesc<T>(this TimSortInfoListFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListDesc<T>(this TimSortInfoListFloatSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListDesc<T>(this TimSortInfoListFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) > selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListDesc<T>(this TimSortInfoListFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) > selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending<T>(\n                this List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) > selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) > selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) <= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a, Func<T, double> selector, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianAscending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int last = a.Count - 1;\n            QuickSortAscending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            QuickSortAscending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) > selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) > selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) > selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) > selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) > selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) > selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) > selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(a[hi]) > selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) > selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) < selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) < selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, Func<T, double> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) < selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) < selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortAscending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) < selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1]) < selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) < selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(val) >= selector(a[lf]) && selector(val) >= selector(a[rt])) break;\n                if (selector(a[lf]) >= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortAscendingTrinkle<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[rt]) >= selector(vstepson) || selector(a[lf]) >= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortAscendingSift(a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListDoubleSel<T>\n        {\n            public List<T> m_a;\n            public Func<T, double> m_sel;\n            public int m_minGallop = c_minGallop;\n            public T[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListDoubleSel(List<T> a, Func<T, double> selector)\n            {\n                m_a = a;\n                m_sel = selector;\n                int count = a.Count;\n                m_tmp = new T[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public T[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new T[c < 0 ? cap : Math.Min(c, m_a.Count >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            TimSortAscending(a, selector, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                BinarySortAscending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListDoubleSel<T>(a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderAscending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListAsc(ti);\n        }\n\n        private static void MergeCollapseListAsc<T>(this TimSortInfoListDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListAsc<T>(this TimSortInfoListDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListAsc<T>(this TimSortInfoListDoubleSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightAscending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListAsc<T>(this TimSortInfoListDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) < selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightAscending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListAsc<T>(this TimSortInfoListDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) < selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftAscending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderAscending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) < selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) < selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) >= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a, Func<T, double> selector, int med)\n        {\n            int last = a.Count - 1;\n            QuickMedianDescending(a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        public static void QuickMedianDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            QuickMedianDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int last = a.Count - 1;\n            QuickSortDescending(a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        public static void QuickSortDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            QuickSortDescending(a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[e1]) < selector(a[e2])) { var t = a[e1]; a[e1] = a[e2]; a[e2] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n                if (selector(a[e1]) < selector(a[e3])) { var t = a[e1]; a[e1] = a[e3]; a[e3] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e1]) < selector(a[e4])) { var t = a[e1]; a[e1] = a[e4]; a[e4] = t; }\n                if (selector(a[e3]) < selector(a[e4])) { var t = a[e3]; a[e3] = a[e4]; a[e4] = t; }\n                if (selector(a[e2]) < selector(a[e5])) { var t = a[e2]; a[e2] = a[e5]; a[e5] = t; }\n                if (selector(a[e2]) < selector(a[e3])) { var t = a[e2]; a[e2] = a[e3]; a[e3] = t; }\n                if (selector(a[e4]) < selector(a[e5])) { var t = a[e4]; a[e4] = a[e5]; a[e5] = t; }\n\n                var p1 = a[e2]; a[e2] = a[l];\n                var p2 = a[e4]; a[e4] = a[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(a[hi]) < selector(p2) && i < hi)\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = a[i];\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[hi]) < selector(p1))\n                                --hi;\n                            a[i] = a[hi]; a[hi] = ai; --hi; ai = a[i];\n                            if (selector(ai) > selector(p1)) { a[i] = a[lo]; a[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                a[l] = a[lo - 1]; a[lo - 1] = p1;\n                a[r] = a[hi + 1]; a[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[lo]) == selector(p1))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[i]) == selector(p1)) { p1 = a[i]; a[i] = a[lo]; a[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[hi]) == selector(p2))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[i]) == selector(p2)) { p2 = a[i]; a[i] = a[hi]; a[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = a[i]; int j;\n                for (j = i - 1; j >= l && selector(ai) > selector(a[j]); j--)\n                    a[j + 1] = a[j];\n                a[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, Func<T, double> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2 + begin]))\n                        break;\n                    a[i + begin] = a[i2 + begin];\n                    i = i2;\n                }\n                a[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count + begin];\n                a[count + begin] = a[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1 + begin]) > selector(a[i2 + begin]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni + begin]) > selector(element))\n                        break;\n                    a[i + begin] = a[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void HeapSortDescending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int count = a.Count;\n            for (int c = 1; c < count; c++)\n            {\n                var element = a[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(element) > selector(a[i2]))\n                        break;\n                    a[i] = a[i2];\n                    i = i2;\n                }\n                a[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = a[count];\n                a[count] = a[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[i1]) > selector(a[i2]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[ni]) > selector(element))\n                        break;\n                    a[i] = a[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                a[i] = element;\n            }\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, 0, a.Count - 1);\n        }\n\n        public static void SmoothSortDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int pshift, int head)\n        {\n            var val = a[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(val) <= selector(a[lf]) && selector(val) <= selector(a[rt])) break;\n                if (selector(a[lf]) <= selector(a[rt]))\n                {\n                    a[head] = a[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    a[head] = a[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            a[head] = val;\n        }\n\n        private static void SmoothSortDescendingTrinkle<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = a[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = a[stepson];\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[rt]) <= selector(vstepson) || selector(a[lf]) <= selector(vstepson))\n                        break;\n                }\n                a[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                a[head] = val;\n                SmoothSortDescendingSift(a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            TimSortDescending(a, selector, 0, a.Count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void TimSortDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                BinarySortDescending(a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListDoubleSel<T>(a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = CountRunAndOrderDescending(a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListDesc(ti);\n        }\n\n        private static void MergeCollapseListDesc<T>(this TimSortInfoListDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListDesc<T>(this TimSortInfoListDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListDesc<T>(this TimSortInfoListDoubleSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = GallopRightDescending(a, ti.m_sel, ti.m_a[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_sel, ti.m_a[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListDesc<T>(this TimSortInfoListDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(a, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            a[dest++] = a[idx2++];\n            if (--len2 == 0)\n            {\n                CopyElements(t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[idx2]) > selector(t[idx1]))\n                    {\n                        a[dest++] = a[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)GallopRightDescending(t, selector, a[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    a[dest++] = a[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    a[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(a, idx2, a, dest, len2);\n                a[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiListDesc<T>(this TimSortInfoListDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(a, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            a[dest--] = a[idx1--];\n            if (--len1 == 0)\n            {\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(t[idx2]) > selector(a[idx1]))\n                    {\n                        a[dest--] = a[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        a[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    a[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)GallopLeftDescending(t, selector, a[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    a[dest--] = a[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(a, idx1 + 1, a, dest + 1, len1);\n                a[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static int GallopLeftDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                T key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(a[start + hint]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(a[start + m]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int GallopRightDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                T key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(a[start + hint]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(a[start + hint - ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(a[start + hint + ofs]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(a[start + m]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = a[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(a[mid]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: a[l + 2] = a[l + 1]; a[l + 1] = a[l]; break;\n                    case 1: a[l + 1] = a[l]; break;\n                    default: CopyElements(a, l, a, l + 1, n); break;\n                }\n                a[l] = pivot;\n            }\n        }\n\n        private static int CountRunAndOrderDescending<T>(\n                this List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[runHi++]) > selector(a[beginIncl]))\n            {\n                while (runHi < endExcl && selector(a[runHi]) > selector(a[runHi - 1]))\n                    runHi++;\n                ReverseRange(a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[runHi]) <= selector(a[runHi - 1]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for List<T>\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedian<T>(\n                this List<T> a, Func<T, T, int> cmp, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedian(p, a, cmp, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedian<T>(\n                this int[] p, List<T> a, Func<T, T, int> cmp, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedian(p, a, cmp, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedian<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedian(p, a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedian<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (cmp(a[p[e1]], a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e1]], a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e1]], a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e3]], a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e2]], a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = cmp(a[p1], a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(a[ai], a[p2]) > 0)\n                        {\n                            while (cmp(a[p[hi]], a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) == 0) continue;\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[p[hi]], a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (cmp(a[p[lo]], a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[p[i]], a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[p[hi]], a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[p[i]], a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && cmp(a[ai], a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSort<T>(\n                this List<T> a, Func<T, T, int> cmp)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSort(p, a, cmp, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSort<T>(\n                this int[] p, List<T> a, Func<T, T, int> cmp)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSort(p, a, cmp, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSort<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSort(p, a, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSort<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (cmp(a[p[e1]], a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e1]], a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e1]], a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e3]], a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(a[p[e2]], a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(a[p[e2]], a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(a[p[e4]], a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = cmp(a[p1], a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(a[ai], a[p2]) > 0)\n                        {\n                            while (cmp(a[p[hi]], a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(a[ai], a[p1]) == 0) continue;\n                        if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(a[p[hi]], a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(a[ai], a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                        PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                        {\n                            while (cmp(a[p[lo]], a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(a[p[i]], a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(a[p[hi]], a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(a[p[i]], a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSort(p, a, cmp, lo, hi, cm);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSort(p, a, cmp, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSort(p, a, cmp, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && cmp(a[ai], a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSort<T>(\n                this List<T> a, Func<T, T, int> cmp)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSort(p, a, cmp);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSort<T>(\n                this int[] p, List<T> a, Func<T, T, int> cmp, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (cmp(a[element], a[p[i2 + begin]]) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && cmp(a[p[i1 + begin]], a[p[i2 + begin]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[p[ni + begin]], a[element]) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSort<T>(\n                this int[] p, List<T> a, Func<T, T, int> cmp)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (cmp(a[element], a[p[i2]]) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && cmp(a[p[i1]], a[p[i2]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(a[p[ni]], a[element]) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSort<T>(\n                this List<T> a, Func<T, T, int> cmp)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSort(p, a, cmp);\n            return p;\n        }\n\n        public static void PermutationSmoothSort<T>(\n                this int[] p, List<T> a, Func<T, T, int> cmp)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, cmp, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSort<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, cmp, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortSift(p, a, cmp, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortSift(p, a, cmp, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortTrinkle(p, a, cmp, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortTrinkle(p, a, cmp, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortSift<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (cmp(a[val], a[p[lf]]) >= 0 && cmp(a[val], a[p[rt]]) >= 0) break;\n                if (cmp(a[p[lf]], a[p[rt]]) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (cmp(a[vstepson], a[val]) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (cmp(a[p[rt]], a[vstepson]) >= 0 || cmp(a[p[lf]], a[vstepson]) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortSift(p, a, cmp, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListPermCmp<T>\n        {\n            public int[] m_p;\n            public List<T> m_a;\n            public Func<T, T, int> m_cmp;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListPermCmp(int[] p, List<T> a, Func<T, T, int> cmp)\n            {\n                m_p = p; m_a = a;\n                m_cmp = cmp;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSort<T>(\n                this List<T> a, Func<T, T, int> cmp)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSort(p, a, cmp);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSort<T>(\n                this int[] p, List<T> a, Func<T, T, int> cmp)\n        {\n            PermutationTimSort(p, a, cmp, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSort<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrder(p, a, cmp, lo, hi);\n                PermutationBinarySort(p, a, cmp, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermCmp<T>(p, a, cmp);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrder(p, a, cmp, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySort(p, a, cmp, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermCmp(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermCmp(ti);\n        }\n\n        private static void MergeCollapseListPermCmp<T>(this TimSortInfoListPermCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermCmp(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermCmp(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermCmp<T>(this TimSortInfoListPermCmp<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermCmp(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermCmp<T>(this TimSortInfoListPermCmp<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRight(ti.m_p, a, ti.m_cmp, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeft(ti.m_p, a, ti.m_cmp, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermCmp(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermCmp(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermCmp<T>(this TimSortInfoListPermCmp<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(a[p[idx2]], a[t[idx1]]) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRight(t, a, cmp, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeft(p, a, cmp, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermCmp<T>(this TimSortInfoListPermCmp<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(a[t[idx2]], a[p[idx1]]) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRight(p, a, cmp, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeft(t, a, cmp, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeft<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (cmp(a[key], a[p[start + hint]]) > 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint + ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint - ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(a[key], a[p[start + m]]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRight<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (cmp(a[key], a[p[start + hint]]) < 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint - ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(a[key], a[p[start + hint + ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(a[key], a[p[start + m]]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySort<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (cmp(a[pivot], a[p[mid]]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrder<T>(\n                this int[] p, List<T> a,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (cmp(a[p[runHi++]], a[p[beginIncl]]) < 0)\n            {\n                while (runHi < endExcl && cmp(a[p[runHi]], a[p[runHi - 1]]) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && cmp(a[p[runHi]], a[p[runHi - 1]]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this List<T> a, int med)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a, int med)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl, int med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                int l, int r, int countSub1, int med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) > 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortAscending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                int l, int r, int countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) > 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, int begin, int end)\n            where T : IComparable<T>\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2 + begin]]) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]].CompareTo(a[p[i2 + begin]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]].CompareTo(a[element]) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a)\n            where T : IComparable<T>\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2]]) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]].CompareTo(a[p[i2]]) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]].CompareTo(a[element]) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, List<T> a,\n                int pshift, int head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val].CompareTo(a[p[lf]]) >= 0 && a[val].CompareTo(a[p[rt]]) >= 0) break;\n                if (a[p[lf]].CompareTo(a[p[rt]]) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, List<T> a,\n                long pbits, int pshift, int head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson].CompareTo(a[val]) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]].CompareTo(a[vstepson]) >= 0 || a[p[lf]].CompareTo(a[vstepson]) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListPerm<T>\n            where T : IComparable<T>\n        {\n            public int[] m_p;\n            public List<T> m_a;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListPerm(int[] p, List<T> a)\n            {\n                m_p = p; m_a = a;\n                \n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a)\n            where T : IComparable<T>\n        {\n            PermutationTimSortAscending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                PermutationBinarySortAscending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<T>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermAsc(ti);\n        }\n\n        private static void MergeCollapseListPermAsc<T>(this TimSortInfoListPerm<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermAsc<T>(this TimSortInfoListPerm<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermAsc<T>(this TimSortInfoListPerm<T> ti, int i)\n            where T : IComparable<T>\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermAsc<T>(this TimSortInfoListPerm<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]].CompareTo(a[t[idx1]]) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermAsc<T>(this TimSortInfoListPerm<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]].CompareTo(a[p[idx1]]) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, List<T> a,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key].CompareTo(a[p[start + hint]]) > 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, List<T> a,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key].CompareTo(a[p[start + hint]]) < 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot].CompareTo(a[p[mid]]) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]].CompareTo(a[p[beginIncl]]) < 0)\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this List<T> a, int med)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a, int med)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl, int med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                int l, int r, int countSub1, int med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) < 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortDescending(p, a, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                int l, int r, int countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (a[p[e1]].CompareTo(a[p[e2]]) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (a[p[e1]].CompareTo(a[p[e3]]) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e1]].CompareTo(a[p[e4]]) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (a[p[e3]].CompareTo(a[p[e4]]) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (a[p[e2]].CompareTo(a[p[e5]]) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (a[p[e2]].CompareTo(a[p[e3]]) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (a[p[e4]].CompareTo(a[p[e5]]) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = a[p1].CompareTo(a[p2]) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (a[ai].CompareTo(a[p2]) < 0)\n                        {\n                            while (a[p[hi]].CompareTo(a[p2]) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (a[ai].CompareTo(a[p1]) == 0) continue;\n                        if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (a[p[hi]].CompareTo(a[p1]) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (a[ai].CompareTo(a[p1]) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        {\n                            while (a[p[lo]].CompareTo(a[p1]) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (a[p[i]].CompareTo(a[p1]) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (a[p[hi]].CompareTo(a[p2]) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (a[p[i]].CompareTo(a[p2]) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && a[ai].CompareTo(a[p[j]]) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, int begin, int end)\n            where T : IComparable<T>\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2 + begin]]) > 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1 + begin]].CompareTo(a[p[i2 + begin]]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni + begin]].CompareTo(a[element]) > 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a)\n            where T : IComparable<T>\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (a[element].CompareTo(a[p[i2]]) > 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && a[p[i1]].CompareTo(a[p[i2]]) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (a[p[ni]].CompareTo(a[element]) > 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, List<T> a,\n                int pshift, int head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (a[val].CompareTo(a[p[lf]]) <= 0 && a[val].CompareTo(a[p[rt]]) <= 0) break;\n                if (a[p[lf]].CompareTo(a[p[rt]]) <= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, List<T> a,\n                long pbits, int pshift, int head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (a[vstepson].CompareTo(a[val]) >= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (a[p[rt]].CompareTo(a[vstepson]) <= 0 || a[p[lf]].CompareTo(a[vstepson]) <= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this List<T> a)\n            where T : IComparable<T>\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a)\n            where T : IComparable<T>\n        {\n            PermutationTimSortDescending(p, a, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                PermutationBinarySortDescending(p, a, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPerm<T>(p, a);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermDesc(ti);\n        }\n\n        private static void MergeCollapseListPermDesc<T>(this TimSortInfoListPerm<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermDesc<T>(this TimSortInfoListPerm<T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermDesc<T>(this TimSortInfoListPerm<T> ti, int i)\n            where T : IComparable<T>\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermDesc<T>(this TimSortInfoListPerm<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[p[idx2]].CompareTo(a[t[idx1]]) > 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermDesc<T>(this TimSortInfoListPerm<T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (a[t[idx2]].CompareTo(a[p[idx1]]) > 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, List<T> a,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int lastOfs = 0, ofs = 1;\n            if (a[key].CompareTo(a[p[start + hint]]) < 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) < 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, List<T> a,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int ofs = 1, lastOfs = 0;\n            if (a[key].CompareTo(a[p[start + hint]]) > 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint - ofs]]) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && a[key].CompareTo(a[p[start + hint + ofs]]) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (a[key].CompareTo(a[p[start + m]]) > 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl, int beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (a[pivot].CompareTo(a[p[mid]]) > 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, List<T> a,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (a[p[runHi++]].CompareTo(a[p[beginIncl]]) > 0)\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) > 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && a[p[runHi]].CompareTo(a[p[runHi - 1]]) <= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this List<T> a, Func<T, int> selector, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a, Func<T, int> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a, Func<T, int> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, Func<T, int> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, Func<T, int> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a, Func<T, int> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListPermIntSel<T>\n        {\n            public int[] m_p;\n            public List<T> m_a;\n            public Func<T, int> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListPermIntSel(int[] p, List<T> a, Func<T, int> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a, Func<T, int> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermIntSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermAsc(ti);\n        }\n\n        private static void MergeCollapseListPermAsc<T>(this TimSortInfoListPermIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermAsc<T>(this TimSortInfoListPermIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermAsc<T>(this TimSortInfoListPermIntSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermAsc<T>(this TimSortInfoListPermIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermAsc<T>(this TimSortInfoListPermIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this List<T> a, Func<T, int> selector, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a, Func<T, int> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a, Func<T, int> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, Func<T, int> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, Func<T, int> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a, Func<T, int> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this List<T> a, Func<T, int> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a, Func<T, int> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermIntSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermDesc(ti);\n        }\n\n        private static void MergeCollapseListPermDesc<T>(this TimSortInfoListPermIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermDesc<T>(this TimSortInfoListPermIntSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermDesc<T>(this TimSortInfoListPermIntSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermDesc<T>(this TimSortInfoListPermIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermDesc<T>(this TimSortInfoListPermIntSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this List<T> a, Func<T, long> selector, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a, Func<T, long> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a, Func<T, long> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, Func<T, long> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, Func<T, long> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a, Func<T, long> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListPermLongSel<T>\n        {\n            public int[] m_p;\n            public List<T> m_a;\n            public Func<T, long> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListPermLongSel(int[] p, List<T> a, Func<T, long> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a, Func<T, long> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermLongSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermAsc(ti);\n        }\n\n        private static void MergeCollapseListPermAsc<T>(this TimSortInfoListPermLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermAsc<T>(this TimSortInfoListPermLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermAsc<T>(this TimSortInfoListPermLongSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermAsc<T>(this TimSortInfoListPermLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermAsc<T>(this TimSortInfoListPermLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this List<T> a, Func<T, long> selector, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a, Func<T, long> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a, Func<T, long> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, Func<T, long> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, Func<T, long> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a, Func<T, long> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this List<T> a, Func<T, long> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a, Func<T, long> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermLongSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermDesc(ti);\n        }\n\n        private static void MergeCollapseListPermDesc<T>(this TimSortInfoListPermLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermDesc<T>(this TimSortInfoListPermLongSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermDesc<T>(this TimSortInfoListPermLongSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermDesc<T>(this TimSortInfoListPermLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermDesc<T>(this TimSortInfoListPermLongSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this List<T> a, Func<T, float> selector, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a, Func<T, float> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a, Func<T, float> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, Func<T, float> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, Func<T, float> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a, Func<T, float> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListPermFloatSel<T>\n        {\n            public int[] m_p;\n            public List<T> m_a;\n            public Func<T, float> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListPermFloatSel(int[] p, List<T> a, Func<T, float> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a, Func<T, float> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermFloatSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermAsc(ti);\n        }\n\n        private static void MergeCollapseListPermAsc<T>(this TimSortInfoListPermFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermAsc<T>(this TimSortInfoListPermFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermAsc<T>(this TimSortInfoListPermFloatSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermAsc<T>(this TimSortInfoListPermFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermAsc<T>(this TimSortInfoListPermFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this List<T> a, Func<T, float> selector, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a, Func<T, float> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a, Func<T, float> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, Func<T, float> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, Func<T, float> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a, Func<T, float> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this List<T> a, Func<T, float> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a, Func<T, float> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermFloatSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermDesc(ti);\n        }\n\n        private static void MergeCollapseListPermDesc<T>(this TimSortInfoListPermFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermDesc<T>(this TimSortInfoListPermFloatSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermDesc<T>(this TimSortInfoListPermFloatSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermDesc<T>(this TimSortInfoListPermFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermDesc<T>(this TimSortInfoListPermFloatSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianAscending<T>(\n                this List<T> a, Func<T, double> selector, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianAscending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a, Func<T, double> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortAscending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortAscending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a, Func<T, double> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) > selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) > selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) > selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) > selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) > selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) > selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) > selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) < selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) < selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortAscending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, Func<T, double> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) < selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) < selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortAscending<T>(\n                this int[] p, List<T> a, Func<T, double> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) < selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) < selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) < selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortAscending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortAscending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a, Func<T, double> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) >= selector(a[p[lf]]) && selector(a[val]) >= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) >= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) <= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) >= selector(a[vstepson]) || selector(a[p[lf]]) >= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoListPermDoubleSel<T>\n        {\n            public int[] m_p;\n            public List<T> m_a;\n            public Func<T, double> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoListPermDoubleSel(int[] p, List<T> a, Func<T, double> selector)\n            {\n                m_p = p; m_a = a;\n                m_sel = selector;\n                int count = p.Length;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortAscending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortAscending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a, Func<T, double> selector)\n        {\n            PermutationTimSortAscending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermDoubleSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermAsc(ti);\n        }\n\n        private static void MergeCollapseListPermAsc<T>(this TimSortInfoListPermDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermAsc<T>(this TimSortInfoListPermDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermAsc<T>(this TimSortInfoListPermDoubleSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermAsc<T>(this TimSortInfoListPermDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) < selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightAscending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermAsc<T>(this TimSortInfoListPermDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) < selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftAscending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) < selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) < selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) < selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) >= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        /// </summary>\n        public static int[] CreatePermutationQuickMedianDescending<T>(\n                this List<T> a, Func<T, double> selector, int med)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickMedianDescending(p, a, selector, 0, len - 1, len - 1, med);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a, Func<T, double> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        public static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        /// </summary>\n        public static int[] CreatePermutationQuickSortDescending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationQuickSortDescending(p, a, selector, 0, len - 1, len - 1);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a, Func<T, double> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        public static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(a[p[e1]]) < selector(a[p[e2]])) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e3]])) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e1]]) < selector(a[p[e4]])) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e3]]) < selector(a[p[e4]])) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e5]])) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(a[p[e2]]) < selector(a[p[e3]])) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(a[p[e4]]) < selector(a[p[e5]])) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(a[p1]) != selector(a[p2]);\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(a[ai]) < selector(a[p2]))\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p2]) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(a[ai]) == selector(a[p1])) continue;\n                        if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(a[p[hi]]) < selector(a[p1]))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(a[ai]) > selector(a[p1])) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        {\n                            while (selector(a[p[lo]]) == selector(a[p1]))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p1])) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(a[p[hi]]) == selector(a[p2]))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(a[p[i]]) == selector(a[p2])) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(a[ai]) > selector(a[p[j]]); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        public static int[] CreatePermutationHeapSortDescending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationHeapSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, Func<T, double> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2 + begin]]))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1 + begin]]) > selector(a[p[i2 + begin]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni + begin]]) > selector(a[element]))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        public static void PermutationHeapSortDescending<T>(\n                this int[] p, List<T> a, Func<T, double> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(a[element]) > selector(a[p[i2]]))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(a[p[i1]]) > selector(a[p[i2]]))\n                                 ? i2 : i1; // smaller child\n                    if (selector(a[p[ni]]) > selector(a[element]))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        public static int[] CreatePermutationSmoothSortDescending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationSmoothSortDescending(p, a, selector);\n            return p;\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a, Func<T, double> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, 0, p.Length - 1);\n        }\n\n        public static void PermutationSmoothSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(a[val]) <= selector(a[p[lf]]) && selector(a[val]) <= selector(a[p[rt]])) break;\n                if (selector(a[p[lf]]) <= selector(a[p[rt]]))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(a[vstepson]) >= selector(a[val])) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(a[p[rt]]) <= selector(a[vstepson]) || selector(a[p[lf]]) <= selector(a[vstepson]))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static int[] CreatePermutationTimSortDescending<T>(\n                this List<T> a, Func<T, double> selector)\n        {\n            int len = a.Count;\n            var p = new int[len].SetByIndex(i => i);\n            PermutationTimSortDescending(p, a, selector);\n            return p;\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a, Func<T, double> selector)\n        {\n            PermutationTimSortDescending(p, a, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        public static void PermutationTimSortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoListPermDoubleSel<T>(p, a, selector);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseListPermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseListPermDesc(ti);\n        }\n\n        private static void MergeCollapseListPermDesc<T>(this TimSortInfoListPermDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtListPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtListPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseListPermDesc<T>(this TimSortInfoListPermDoubleSel<T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtListPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtListPermDesc<T>(this TimSortInfoListPermDoubleSel<T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoListPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiListPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoListPermDesc<T>(this TimSortInfoListPermDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[p[idx2]]) > selector(a[t[idx1]]))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = (int)PermutationGallopRightDescending(t, a, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiListPermDesc<T>(this TimSortInfoListPermDoubleSel<T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(a[t[idx2]]) > selector(a[p[idx1]]))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - (int)PermutationGallopLeftDescending(t, a, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(a[key]) < selector(a[p[start + hint]]))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) < selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) >= selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) < selector(a[p[start + m]]))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(a[key]) > selector(a[p[start + hint]]))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(a[key]) > selector(a[p[start + hint - ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(a[key]) <= selector(a[p[start + hint + ofs]]))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(a[key]) > selector(a[p[start + m]]))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(a[pivot]) > selector(a[p[mid]]))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<T>(\n                this int[] p, List<T> a,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(a[p[runHi++]]) > selector(a[p[beginIncl]]))\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) > selector(a[p[runHi - 1]]))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(a[p[runHi]]) <= selector(a[p[runHi - 1]]))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Sort/Median for TArray\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedian<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, T, int> cmp, long med)\n        {\n            long last = count - 1;\n            QuickMedian(a, aget, aset, cmp, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedian<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedian(a, aget, aset, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedian<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (cmp(aget(a, e1), aget(a, e2)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (cmp(aget(a, e4), aget(a, e5)) > 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (cmp(aget(a, e1), aget(a, e3)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (cmp(aget(a, e2), aget(a, e3)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (cmp(aget(a, e1), aget(a, e4)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (cmp(aget(a, e3), aget(a, e4)) > 0) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (cmp(aget(a, e2), aget(a, e5)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (cmp(aget(a, e2), aget(a, e3)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (cmp(aget(a, e4), aget(a, e5)) > 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = cmp(p1, p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (cmp(ai, p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (cmp(ai, p2) > 0)\n                        {\n                            while (cmp(aget(a, hi), p2) > 0 && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (cmp(ai, p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (cmp(ai, p1) == 0) continue;\n                        if (cmp(ai, p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (cmp(aget(a, hi), p1) > 0)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (cmp(ai, p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (cmp(aget(a, lo), p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(aget(a, i), p1) == 0) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (cmp(aget(a, hi), p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(aget(a, i), p2) == 0) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && cmp(ai, aget(a, j)) < 0; j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSort<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, T, int> cmp)\n        {\n            long last = count - 1;\n            QuickSort(a, aget, aset, cmp, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSort<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            QuickSort(a, aget, aset, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSort<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (cmp(aget(a, e1), aget(a, e2)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (cmp(aget(a, e4), aget(a, e5)) > 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (cmp(aget(a, e1), aget(a, e3)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (cmp(aget(a, e2), aget(a, e3)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (cmp(aget(a, e1), aget(a, e4)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (cmp(aget(a, e3), aget(a, e4)) > 0) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (cmp(aget(a, e2), aget(a, e5)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (cmp(aget(a, e2), aget(a, e3)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (cmp(aget(a, e4), aget(a, e5)) > 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = cmp(p1, p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (cmp(ai, p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (cmp(ai, p2) > 0)\n                        {\n                            while (cmp(aget(a, hi), p2) > 0 && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (cmp(ai, p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (cmp(ai, p1) == 0) continue;\n                        if (cmp(ai, p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (cmp(aget(a, hi), p1) > 0)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (cmp(ai, p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSort(a, aget, aset, cmp, l, lo - 2, cl);\n                        QuickSort(a, aget, aset, cmp, hi + 2, r, cr);\n                        {\n                            while (cmp(aget(a, lo), p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(aget(a, i), p1) == 0) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (cmp(aget(a, hi), p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(aget(a, i), p2) == 0) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSort(a, aget, aset, cmp, lo, hi, cm);\n                                QuickSort(a, aget, aset, cmp, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSort(a, aget, aset, cmp, l, lo - 2, cl);\n                                QuickSort(a, aget, aset, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSort(a, aget, aset, cmp, l, lo - 2, cl);\n                                QuickSort(a, aget, aset, cmp, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSort(a, aget, aset, cmp, l, lo - 2, cl);\n                                QuickSort(a, aget, aset, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSort(a, aget, aset, cmp, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSort(a, aget, aset, cmp, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && cmp(ai, aget(a, j)) < 0; j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSort<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, T, int> cmp, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (cmp(element, aget(a, i2 + begin)) < 0)\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && cmp(aget(a, i1 + begin), aget(a, i2 + begin)) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(aget(a, ni + begin), element) < 0)\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSort<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, T, int> cmp)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (cmp(element, aget(a, i2)) < 0)\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && cmp(aget(a, i1), aget(a, i2)) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(aget(a, ni), element) < 0)\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSort<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, T, int> cmp)\n        {\n            SmoothSortInclusiveRange(a, aget, aset, cmp, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSort<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortInclusiveRange(a, aget, aset, cmp, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortSift(a, aget, aset, cmp, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortTrinkle(a, aget, aset, cmp, pbits, pshift, head, false);\n                    else\n                        SmoothSortSift(a, aget, aset, cmp, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortTrinkle(a, aget, aset, cmp, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortTrinkle(a, aget, aset, cmp, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortTrinkle(a, aget, aset, cmp, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (cmp(val, aget(a, lf)) >= 0 && cmp(val, aget(a, rt)) >= 0) break;\n                if (cmp(aget(a, lf), aget(a, rt)) >= 0)\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (cmp(vstepson, val) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (cmp(aget(a, rt), vstepson) >= 0 || cmp(aget(a, lf), vstepson) >= 0)\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortSift(a, aget, aset, cmp, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongGetCmp<TArray, T>\n        {\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Action<TArray, long, T> m_aset;\n            public Func<long, TArray> m_amake;\n            public Func<T, T, int> m_cmp;\n            public long m_minGallop = c_minGallop;\n            public TArray m_tmp;\n            public long m_len;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongGetCmp(TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, T, int> cmp, long count)\n            {\n                m_a = a; m_count = count;\n                m_aget = aget; m_aset = aset; m_amake = amake; m_cmp = cmp;\n                m_len = count < 2 * c_initialTmpStorageLength\n                        ? count >> 1 : c_initialTmpStorageLength;\n                m_tmp = amake(m_len);\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public TArray EnsureCapacity(long cap)\n            {\n                if (m_len < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_len = c < 0 ? cap : Math.Min(c, m_count >> 1);\n                    m_tmp = m_amake(m_len);\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSort<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, T, int> cmp)\n        {\n            TimSort(a, aget, aset, amake, cmp, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSort<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, T, int> cmp,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrder(a, aget, aset, cmp, lo, hi);\n                BinarySort(a, aget, aset, cmp, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetCmp<TArray, T>(a, aget, aset, amake, cmp, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrder(a, aget, aset, cmp, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySort(a, aget, aset, cmp, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongCmp(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongCmp(ti);\n        }\n\n        private static void MergeCollapseLongCmp<TArray, T>(this TimSortInfoLongGetCmp<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongCmp(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongCmp(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongCmp<TArray, T>(this TimSortInfoLongGetCmp<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongCmp(ti, n);\n            }\n        }\n\n        private static void MergeAtLongCmp<TArray, T>(this TimSortInfoLongGetCmp<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRight(a, ti.m_aget, ti.m_cmp, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeft(a, ti.m_aget, ti.m_cmp, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongCmp(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongCmp(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongCmp<TArray, T>(this TimSortInfoLongGetCmp<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(aget(a, idx2), aget(t, idx1)) < 0)\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRight(t, aget, cmp, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeft(a, aget, cmp, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongCmp<TArray, T>(this TimSortInfoLongGetCmp<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(aget(t, idx2), aget(a, idx1)) < 0)\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRight(a, aget, cmp, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeft(t, aget, cmp, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeft<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (cmp(key, aget(a, start + hint)) > 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(key, aget(a, start + hint + ofs)) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(key, aget(a, start + hint - ofs)) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(key, aget(a, start + m)) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRight<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (cmp(key, aget(a, start + hint)) < 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(key, aget(a, start + hint - ofs)) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(key, aget(a, start + hint + ofs)) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(key, aget(a, start + m)) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySort<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (cmp(pivot, aget(a, mid)) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrder<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (cmp(aget(a, runHi++), aget(a, beginIncl)) < 0)\n            {\n                while (runHi < endExcl && cmp(aget(a, runHi), aget(a, runHi - 1)) < 0)\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && cmp(aget(a, runHi), aget(a, runHi - 1)) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void ReverseRange<TArray, T>(\n                 Func<TArray, long, T> aget, Action<TArray, long, T> aset,TArray a,\n                long beginIncl, long endExcl)\n        {\n            endExcl--; // now incorrectly named\n            while (beginIncl < endExcl)\n            {\n                var t = aget(a, beginIncl); aset(a, beginIncl, aget(a, endExcl)); aset(a, endExcl, t);\n                ++beginIncl; --endExcl;\n            }\n        }\n\n        private static void CopyElements<TArray, T>(\n                Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                TArray src, long start, TArray dst, long dstStart, long count)\n        {\n            for (var end = start + count; start < end; start++, dstStart++)\n                aset(dst, dstStart, aget(src, start));\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, long med)\n            where T : IComparable<T>\n        {\n            long last = count - 1;\n            QuickMedianAscending(a, aget, aset, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl, long med)\n            where T : IComparable<T>\n        {\n            QuickMedianAscending(a, aget, aset, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long l, long r, long countSub1, long med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (aget(a, e1).CompareTo(aget(a, e2)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (aget(a, e4).CompareTo(aget(a, e5)) > 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (aget(a, e1).CompareTo(aget(a, e3)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e2).CompareTo(aget(a, e3)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e1).CompareTo(aget(a, e4)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (aget(a, e3).CompareTo(aget(a, e4)) > 0) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (aget(a, e2).CompareTo(aget(a, e5)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (aget(a, e2).CompareTo(aget(a, e3)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e4).CompareTo(aget(a, e5)) > 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (ai.CompareTo(p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (ai.CompareTo(p2) > 0)\n                        {\n                            while (aget(a, hi).CompareTo(p2) > 0 && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (ai.CompareTo(p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (aget(a, hi).CompareTo(p1) > 0)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (ai.CompareTo(p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (aget(a, lo).CompareTo(p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a, i).CompareTo(p1) == 0) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (aget(a, hi).CompareTo(p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a, i).CompareTo(p2) == 0) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && ai.CompareTo(aget(a, j)) < 0; j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset)\n            where T : IComparable<T>\n        {\n            long last = count - 1;\n            QuickSortAscending(a, aget, aset, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            QuickSortAscending(a, aget, aset, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long l, long r, long countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (aget(a, e1).CompareTo(aget(a, e2)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (aget(a, e4).CompareTo(aget(a, e5)) > 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (aget(a, e1).CompareTo(aget(a, e3)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e2).CompareTo(aget(a, e3)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e1).CompareTo(aget(a, e4)) > 0) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (aget(a, e3).CompareTo(aget(a, e4)) > 0) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (aget(a, e2).CompareTo(aget(a, e5)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (aget(a, e2).CompareTo(aget(a, e3)) > 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e4).CompareTo(aget(a, e5)) > 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (ai.CompareTo(p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (ai.CompareTo(p2) > 0)\n                        {\n                            while (aget(a, hi).CompareTo(p2) > 0 && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (ai.CompareTo(p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (aget(a, hi).CompareTo(p1) > 0)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (ai.CompareTo(p1) < 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, aget, aset, l, lo - 2, cl);\n                        QuickSortAscending(a, aget, aset, hi + 2, r, cr);\n                        {\n                            while (aget(a, lo).CompareTo(p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a, i).CompareTo(p1) == 0) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (aget(a, hi).CompareTo(p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a, i).CompareTo(p2) == 0) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, lo, hi, cm);\n                                QuickSortAscending(a, aget, aset, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, aget, aset, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, aget, aset, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && ai.CompareTo(aget(a, j)) < 0; j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, long begin, long end)\n            where T : IComparable<T>\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element.CompareTo(aget(a, i2 + begin)) < 0)\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && aget(a, i1 + begin).CompareTo(aget(a, i2 + begin)) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a, ni + begin).CompareTo(element) < 0)\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset)\n            where T : IComparable<T>\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element.CompareTo(aget(a, i2)) < 0)\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && aget(a, i1).CompareTo(aget(a, i2)) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a, ni).CompareTo(element) < 0)\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset)\n            where T : IComparable<T>\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, aget, aset, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, aget, aset, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, aget, aset, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, aget, aset, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, aget, aset, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, aget, aset, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                int pshift, long head)\n            where T : IComparable<T>\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val.CompareTo(aget(a, lf)) >= 0 && val.CompareTo(aget(a, rt)) >= 0) break;\n                if (aget(a, lf).CompareTo(aget(a, rt)) >= 0)\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortAscendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long pbits, int pshift, long head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (vstepson.CompareTo(val) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (aget(a, rt).CompareTo(vstepson) >= 0 || aget(a, lf).CompareTo(vstepson) >= 0)\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortAscendingSift(a, aget, aset, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongGet<TArray, T>\n            where T : IComparable<T>\n        {\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Action<TArray, long, T> m_aset;\n            public Func<long, TArray> m_amake;\n            public long m_minGallop = c_minGallop;\n            public TArray m_tmp;\n            public long m_len;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongGet(TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, long count)\n            {\n                m_a = a; m_count = count;\n                m_aget = aget; m_aset = aset; m_amake = amake; \n                m_len = count < 2 * c_initialTmpStorageLength\n                        ? count >> 1 : c_initialTmpStorageLength;\n                m_tmp = amake(m_len);\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public TArray EnsureCapacity(long cap)\n            {\n                if (m_len < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_len = c < 0 ? cap : Math.Min(c, m_count >> 1);\n                    m_tmp = m_amake(m_len);\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake)\n            where T : IComparable<T>\n        {\n            TimSortAscending(a, aget, aset, amake, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, aget, aset, lo, hi);\n                BinarySortAscending(a, aget, aset, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGet<TArray, T>(a, aget, aset, amake, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, aget, aset, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, aget, aset, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti, int i)\n            where T : IComparable<T>\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_aget, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_aget, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a, idx2).CompareTo(aget(t, idx1)) < 0)\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, aget, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, aget, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(t, idx2).CompareTo(aget(a, idx1)) < 0)\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, aget, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, aget, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                T key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key.CompareTo(aget(a, start + hint)) > 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(aget(a, start + hint + ofs)) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(aget(a, start + hint - ofs)) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(aget(a, start + m)) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                T key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key.CompareTo(aget(a, start + hint)) < 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(aget(a, start + hint - ofs)) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(aget(a, start + hint + ofs)) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(aget(a, start + m)) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl, long beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot.CompareTo(aget(a, mid)) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (aget(a, runHi++).CompareTo(aget(a, beginIncl)) < 0)\n            {\n                while (runHi < endExcl && aget(a, runHi).CompareTo(aget(a, runHi - 1)) < 0)\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && aget(a, runHi).CompareTo(aget(a, runHi - 1)) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, long med)\n            where T : IComparable<T>\n        {\n            long last = count - 1;\n            QuickMedianDescending(a, aget, aset, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl, long med)\n            where T : IComparable<T>\n        {\n            QuickMedianDescending(a, aget, aset, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long l, long r, long countSub1, long med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (aget(a, e1).CompareTo(aget(a, e2)) < 0) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (aget(a, e4).CompareTo(aget(a, e5)) < 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (aget(a, e1).CompareTo(aget(a, e3)) < 0) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e2).CompareTo(aget(a, e3)) < 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e1).CompareTo(aget(a, e4)) < 0) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (aget(a, e3).CompareTo(aget(a, e4)) < 0) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (aget(a, e2).CompareTo(aget(a, e5)) < 0) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (aget(a, e2).CompareTo(aget(a, e3)) < 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e4).CompareTo(aget(a, e5)) < 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (ai.CompareTo(p1) > 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (ai.CompareTo(p2) < 0)\n                        {\n                            while (aget(a, hi).CompareTo(p2) < 0 && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (ai.CompareTo(p1) > 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) > 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (aget(a, hi).CompareTo(p1) < 0)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (ai.CompareTo(p1) > 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (aget(a, lo).CompareTo(p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a, i).CompareTo(p1) == 0) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (aget(a, hi).CompareTo(p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a, i).CompareTo(p2) == 0) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && ai.CompareTo(aget(a, j)) > 0; j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset)\n            where T : IComparable<T>\n        {\n            long last = count - 1;\n            QuickSortDescending(a, aget, aset, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            QuickSortDescending(a, aget, aset, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long l, long r, long countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (aget(a, e1).CompareTo(aget(a, e2)) < 0) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (aget(a, e4).CompareTo(aget(a, e5)) < 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (aget(a, e1).CompareTo(aget(a, e3)) < 0) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e2).CompareTo(aget(a, e3)) < 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e1).CompareTo(aget(a, e4)) < 0) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (aget(a, e3).CompareTo(aget(a, e4)) < 0) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (aget(a, e2).CompareTo(aget(a, e5)) < 0) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (aget(a, e2).CompareTo(aget(a, e3)) < 0) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (aget(a, e4).CompareTo(aget(a, e5)) < 0) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = p1.CompareTo(p2) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (ai.CompareTo(p1) > 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (ai.CompareTo(p2) < 0)\n                        {\n                            while (aget(a, hi).CompareTo(p2) < 0 && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (ai.CompareTo(p1) > 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (ai.CompareTo(p1) == 0) continue;\n                        if (ai.CompareTo(p1) > 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (aget(a, hi).CompareTo(p1) < 0)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (ai.CompareTo(p1) > 0) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, aget, aset, l, lo - 2, cl);\n                        QuickSortDescending(a, aget, aset, hi + 2, r, cr);\n                        {\n                            while (aget(a, lo).CompareTo(p1) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a, i).CompareTo(p1) == 0) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (aget(a, hi).CompareTo(p2) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a, i).CompareTo(p2) == 0) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, lo, hi, cm);\n                                QuickSortDescending(a, aget, aset, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, aget, aset, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, aget, aset, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && ai.CompareTo(aget(a, j)) > 0; j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, long begin, long end)\n            where T : IComparable<T>\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element.CompareTo(aget(a, i2 + begin)) > 0)\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && aget(a, i1 + begin).CompareTo(aget(a, i2 + begin)) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a, ni + begin).CompareTo(element) > 0)\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset)\n            where T : IComparable<T>\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (element.CompareTo(aget(a, i2)) > 0)\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && aget(a, i1).CompareTo(aget(a, i2)) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a, ni).CompareTo(element) > 0)\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset)\n            where T : IComparable<T>\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, aget, aset, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, aget, aset, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, aget, aset, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, aget, aset, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, aget, aset, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, aget, aset, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                int pshift, long head)\n            where T : IComparable<T>\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (val.CompareTo(aget(a, lf)) <= 0 && val.CompareTo(aget(a, rt)) <= 0) break;\n                if (aget(a, lf).CompareTo(aget(a, rt)) <= 0)\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortDescendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long pbits, int pshift, long head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (vstepson.CompareTo(val) >= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (aget(a, rt).CompareTo(vstepson) <= 0 || aget(a, lf).CompareTo(vstepson) <= 0)\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortDescendingSift(a, aget, aset, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake)\n            where T : IComparable<T>\n        {\n            TimSortDescending(a, aget, aset, amake, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, aget, aset, lo, hi);\n                BinarySortDescending(a, aget, aset, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGet<TArray, T>(a, aget, aset, amake, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, aget, aset, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, aget, aset, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti, int i)\n            where T : IComparable<T>\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_aget, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_aget, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a, idx2).CompareTo(aget(t, idx1)) > 0)\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, aget, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, aget, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<TArray, T>(this TimSortInfoLongGet<TArray, T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(t, idx2).CompareTo(aget(a, idx1)) > 0)\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, aget, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, aget, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                T key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long lastOfs = 0, ofs = 1;\n            if (key.CompareTo(aget(a, start + hint)) < 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(aget(a, start + hint + ofs)) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(aget(a, start + hint - ofs)) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(aget(a, start + m)) < 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                T key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long ofs = 1, lastOfs = 0;\n            if (key.CompareTo(aget(a, start + hint)) > 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && key.CompareTo(aget(a, start + hint - ofs)) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && key.CompareTo(aget(a, start + hint + ofs)) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (key.CompareTo(aget(a, start + m)) > 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl, long beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (pivot.CompareTo(aget(a, mid)) > 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (aget(a, runHi++).CompareTo(aget(a, beginIncl)) > 0)\n            {\n                while (runHi < endExcl && aget(a, runHi).CompareTo(aget(a, runHi - 1)) > 0)\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && aget(a, runHi).CompareTo(aget(a, runHi - 1)) <= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector, long med)\n        {\n            long last = count - 1;\n            QuickMedianAscending(a, aget, aset, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) > selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) > selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(aget(a, hi)) > selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) > selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector)\n        {\n            long last = count - 1;\n            QuickSortAscending(a, aget, aset, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) > selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) > selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(aget(a, hi)) > selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) > selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, selector, lo, hi, cm);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(aget(a, i2 + begin)))\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1 + begin)) < selector(aget(a, i2 + begin)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni + begin)) < selector(element))\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(aget(a, i2)))\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1)) < selector(aget(a, i2)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni)) < selector(element))\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, selector, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) >= selector(aget(a, lf)) && selector(val) >= selector(aget(a, rt))) break;\n                if (selector(aget(a, lf)) >= selector(aget(a, rt)))\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortAscendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a, rt)) >= selector(vstepson) || selector(aget(a, lf)) >= selector(vstepson))\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongGetIntSel<TArray, T>\n        {\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Action<TArray, long, T> m_aset;\n            public Func<long, TArray> m_amake;\n            public Func<T, int> m_sel;\n            public long m_minGallop = c_minGallop;\n            public TArray m_tmp;\n            public long m_len;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongGetIntSel(TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, int> selector, long count)\n            {\n                m_a = a; m_count = count;\n                m_aget = aget; m_aset = aset; m_amake = amake; m_sel = selector;\n                m_len = count < 2 * c_initialTmpStorageLength\n                        ? count >> 1 : c_initialTmpStorageLength;\n                m_tmp = amake(m_len);\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public TArray EnsureCapacity(long cap)\n            {\n                if (m_len < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_len = c < 0 ? cap : Math.Min(c, m_count >> 1);\n                    m_tmp = m_amake(m_len);\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, int> selector)\n        {\n            TimSortAscending(a, aget, aset, amake, selector, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, aget, aset, selector, lo, hi);\n                BinarySortAscending(a, aget, aset, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetIntSel<TArray, T>(a, aget, aset, amake, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, aget, aset, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, aget, aset, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a, idx2)) < selector(aget(t, idx1)))\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, aget, selector, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, aget, selector, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(t, idx2)) < selector(aget(a, idx1)))\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, aget, selector, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, aget, selector, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(aget(a, start + hint)))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(aget(a, start + m)))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(aget(a, start + hint)))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(aget(a, start + m)))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(aget(a, mid)))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a, runHi++)) < selector(aget(a, beginIncl)))\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) < selector(aget(a, runHi - 1)))\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) >= selector(aget(a, runHi - 1)))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector, long med)\n        {\n            long last = count - 1;\n            QuickMedianDescending(a, aget, aset, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) < selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) < selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(aget(a, hi)) < selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) < selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector)\n        {\n            long last = count - 1;\n            QuickSortDescending(a, aget, aset, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) < selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) < selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(aget(a, hi)) < selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) < selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, selector, lo, hi, cm);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(aget(a, i2 + begin)))\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1 + begin)) > selector(aget(a, i2 + begin)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni + begin)) > selector(element))\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(aget(a, i2)))\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1)) > selector(aget(a, i2)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni)) > selector(element))\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, int> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, selector, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) <= selector(aget(a, lf)) && selector(val) <= selector(aget(a, rt))) break;\n                if (selector(aget(a, lf)) <= selector(aget(a, rt)))\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortDescendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a, rt)) <= selector(vstepson) || selector(aget(a, lf)) <= selector(vstepson))\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, int> selector)\n        {\n            TimSortDescending(a, aget, aset, amake, selector, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, aget, aset, selector, lo, hi);\n                BinarySortDescending(a, aget, aset, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetIntSel<TArray, T>(a, aget, aset, amake, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, aget, aset, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, aget, aset, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a, idx2)) > selector(aget(t, idx1)))\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, aget, selector, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, aget, selector, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<TArray, T>(this TimSortInfoLongGetIntSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(t, idx2)) > selector(aget(a, idx1)))\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, aget, selector, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, aget, selector, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(aget(a, start + hint)))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(aget(a, start + m)))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(aget(a, start + hint)))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(aget(a, start + m)))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(aget(a, mid)))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a, runHi++)) > selector(aget(a, beginIncl)))\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) > selector(aget(a, runHi - 1)))\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) <= selector(aget(a, runHi - 1)))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector, long med)\n        {\n            long last = count - 1;\n            QuickMedianAscending(a, aget, aset, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) > selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) > selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(aget(a, hi)) > selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) > selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector)\n        {\n            long last = count - 1;\n            QuickSortAscending(a, aget, aset, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) > selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) > selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(aget(a, hi)) > selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) > selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, selector, lo, hi, cm);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(aget(a, i2 + begin)))\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1 + begin)) < selector(aget(a, i2 + begin)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni + begin)) < selector(element))\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(aget(a, i2)))\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1)) < selector(aget(a, i2)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni)) < selector(element))\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, selector, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) >= selector(aget(a, lf)) && selector(val) >= selector(aget(a, rt))) break;\n                if (selector(aget(a, lf)) >= selector(aget(a, rt)))\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortAscendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a, rt)) >= selector(vstepson) || selector(aget(a, lf)) >= selector(vstepson))\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongGetLongSel<TArray, T>\n        {\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Action<TArray, long, T> m_aset;\n            public Func<long, TArray> m_amake;\n            public Func<T, long> m_sel;\n            public long m_minGallop = c_minGallop;\n            public TArray m_tmp;\n            public long m_len;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongGetLongSel(TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, long> selector, long count)\n            {\n                m_a = a; m_count = count;\n                m_aget = aget; m_aset = aset; m_amake = amake; m_sel = selector;\n                m_len = count < 2 * c_initialTmpStorageLength\n                        ? count >> 1 : c_initialTmpStorageLength;\n                m_tmp = amake(m_len);\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public TArray EnsureCapacity(long cap)\n            {\n                if (m_len < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_len = c < 0 ? cap : Math.Min(c, m_count >> 1);\n                    m_tmp = m_amake(m_len);\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, long> selector)\n        {\n            TimSortAscending(a, aget, aset, amake, selector, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, aget, aset, selector, lo, hi);\n                BinarySortAscending(a, aget, aset, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetLongSel<TArray, T>(a, aget, aset, amake, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, aget, aset, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, aget, aset, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a, idx2)) < selector(aget(t, idx1)))\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, aget, selector, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, aget, selector, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(t, idx2)) < selector(aget(a, idx1)))\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, aget, selector, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, aget, selector, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(aget(a, start + hint)))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(aget(a, start + m)))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(aget(a, start + hint)))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(aget(a, start + m)))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(aget(a, mid)))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a, runHi++)) < selector(aget(a, beginIncl)))\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) < selector(aget(a, runHi - 1)))\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) >= selector(aget(a, runHi - 1)))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector, long med)\n        {\n            long last = count - 1;\n            QuickMedianDescending(a, aget, aset, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) < selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) < selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(aget(a, hi)) < selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) < selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector)\n        {\n            long last = count - 1;\n            QuickSortDescending(a, aget, aset, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) < selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) < selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(aget(a, hi)) < selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) < selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, selector, lo, hi, cm);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(aget(a, i2 + begin)))\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1 + begin)) > selector(aget(a, i2 + begin)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni + begin)) > selector(element))\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(aget(a, i2)))\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1)) > selector(aget(a, i2)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni)) > selector(element))\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, long> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, selector, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) <= selector(aget(a, lf)) && selector(val) <= selector(aget(a, rt))) break;\n                if (selector(aget(a, lf)) <= selector(aget(a, rt)))\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortDescendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a, rt)) <= selector(vstepson) || selector(aget(a, lf)) <= selector(vstepson))\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, long> selector)\n        {\n            TimSortDescending(a, aget, aset, amake, selector, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, aget, aset, selector, lo, hi);\n                BinarySortDescending(a, aget, aset, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetLongSel<TArray, T>(a, aget, aset, amake, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, aget, aset, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, aget, aset, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a, idx2)) > selector(aget(t, idx1)))\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, aget, selector, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, aget, selector, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<TArray, T>(this TimSortInfoLongGetLongSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(t, idx2)) > selector(aget(a, idx1)))\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, aget, selector, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, aget, selector, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(aget(a, start + hint)))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(aget(a, start + m)))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(aget(a, start + hint)))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(aget(a, start + m)))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(aget(a, mid)))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a, runHi++)) > selector(aget(a, beginIncl)))\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) > selector(aget(a, runHi - 1)))\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) <= selector(aget(a, runHi - 1)))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector, long med)\n        {\n            long last = count - 1;\n            QuickMedianAscending(a, aget, aset, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) > selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) > selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(aget(a, hi)) > selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) > selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector)\n        {\n            long last = count - 1;\n            QuickSortAscending(a, aget, aset, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) > selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) > selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(aget(a, hi)) > selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) > selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, selector, lo, hi, cm);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(aget(a, i2 + begin)))\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1 + begin)) < selector(aget(a, i2 + begin)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni + begin)) < selector(element))\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(aget(a, i2)))\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1)) < selector(aget(a, i2)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni)) < selector(element))\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, selector, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) >= selector(aget(a, lf)) && selector(val) >= selector(aget(a, rt))) break;\n                if (selector(aget(a, lf)) >= selector(aget(a, rt)))\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortAscendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a, rt)) >= selector(vstepson) || selector(aget(a, lf)) >= selector(vstepson))\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongGetFloatSel<TArray, T>\n        {\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Action<TArray, long, T> m_aset;\n            public Func<long, TArray> m_amake;\n            public Func<T, float> m_sel;\n            public long m_minGallop = c_minGallop;\n            public TArray m_tmp;\n            public long m_len;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongGetFloatSel(TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, float> selector, long count)\n            {\n                m_a = a; m_count = count;\n                m_aget = aget; m_aset = aset; m_amake = amake; m_sel = selector;\n                m_len = count < 2 * c_initialTmpStorageLength\n                        ? count >> 1 : c_initialTmpStorageLength;\n                m_tmp = amake(m_len);\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public TArray EnsureCapacity(long cap)\n            {\n                if (m_len < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_len = c < 0 ? cap : Math.Min(c, m_count >> 1);\n                    m_tmp = m_amake(m_len);\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, float> selector)\n        {\n            TimSortAscending(a, aget, aset, amake, selector, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, aget, aset, selector, lo, hi);\n                BinarySortAscending(a, aget, aset, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetFloatSel<TArray, T>(a, aget, aset, amake, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, aget, aset, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, aget, aset, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a, idx2)) < selector(aget(t, idx1)))\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, aget, selector, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, aget, selector, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(t, idx2)) < selector(aget(a, idx1)))\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, aget, selector, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, aget, selector, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(aget(a, start + hint)))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(aget(a, start + m)))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(aget(a, start + hint)))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(aget(a, start + m)))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(aget(a, mid)))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a, runHi++)) < selector(aget(a, beginIncl)))\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) < selector(aget(a, runHi - 1)))\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) >= selector(aget(a, runHi - 1)))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector, long med)\n        {\n            long last = count - 1;\n            QuickMedianDescending(a, aget, aset, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) < selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) < selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(aget(a, hi)) < selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) < selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector)\n        {\n            long last = count - 1;\n            QuickSortDescending(a, aget, aset, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) < selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) < selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(aget(a, hi)) < selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) < selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, selector, lo, hi, cm);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(aget(a, i2 + begin)))\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1 + begin)) > selector(aget(a, i2 + begin)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni + begin)) > selector(element))\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(aget(a, i2)))\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1)) > selector(aget(a, i2)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni)) > selector(element))\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, float> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, selector, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) <= selector(aget(a, lf)) && selector(val) <= selector(aget(a, rt))) break;\n                if (selector(aget(a, lf)) <= selector(aget(a, rt)))\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortDescendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a, rt)) <= selector(vstepson) || selector(aget(a, lf)) <= selector(vstepson))\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, float> selector)\n        {\n            TimSortDescending(a, aget, aset, amake, selector, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, aget, aset, selector, lo, hi);\n                BinarySortDescending(a, aget, aset, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetFloatSel<TArray, T>(a, aget, aset, amake, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, aget, aset, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, aget, aset, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a, idx2)) > selector(aget(t, idx1)))\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, aget, selector, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, aget, selector, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<TArray, T>(this TimSortInfoLongGetFloatSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(t, idx2)) > selector(aget(a, idx1)))\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, aget, selector, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, aget, selector, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(aget(a, start + hint)))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(aget(a, start + m)))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(aget(a, start + hint)))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(aget(a, start + m)))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(aget(a, mid)))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a, runHi++)) > selector(aget(a, beginIncl)))\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) > selector(aget(a, runHi - 1)))\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) <= selector(aget(a, runHi - 1)))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector, long med)\n        {\n            long last = count - 1;\n            QuickMedianAscending(a, aget, aset, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianAscending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) > selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) > selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(aget(a, hi)) > selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) > selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector)\n        {\n            long last = count - 1;\n            QuickSortAscending(a, aget, aset, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortAscending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) > selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) > selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) > selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) > selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) > selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) > selector(p2))\n                        {\n                            while (selector(aget(a, hi)) > selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) > selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) < selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                        QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, selector, lo, hi, cm);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortAscending(a, aget, aset, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortAscending(a, aget, aset, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) < selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(aget(a, i2 + begin)))\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1 + begin)) < selector(aget(a, i2 + begin)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni + begin)) < selector(element))\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) < selector(aget(a, i2)))\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1)) < selector(aget(a, i2)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni)) < selector(element))\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector)\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, selector, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortAscendingInclusiveRange(a, aget, aset, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortAscendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortAscendingTrinkle(a, aget, aset, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortAscendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) >= selector(aget(a, lf)) && selector(val) >= selector(aget(a, rt))) break;\n                if (selector(aget(a, lf)) >= selector(aget(a, rt)))\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortAscendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (selector(vstepson) <= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a, rt)) >= selector(vstepson) || selector(aget(a, lf)) >= selector(vstepson))\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortAscendingSift(a, aget, aset, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoLongGetDoubleSel<TArray, T>\n        {\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Action<TArray, long, T> m_aset;\n            public Func<long, TArray> m_amake;\n            public Func<T, double> m_sel;\n            public long m_minGallop = c_minGallop;\n            public TArray m_tmp;\n            public long m_len;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoLongGetDoubleSel(TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, double> selector, long count)\n            {\n                m_a = a; m_count = count;\n                m_aget = aget; m_aset = aset; m_amake = amake; m_sel = selector;\n                m_len = count < 2 * c_initialTmpStorageLength\n                        ? count >> 1 : c_initialTmpStorageLength;\n                m_tmp = amake(m_len);\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public TArray EnsureCapacity(long cap)\n            {\n                if (m_len < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_len = c < 0 ? cap : Math.Min(c, m_count >> 1);\n                    m_tmp = m_amake(m_len);\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, double> selector)\n        {\n            TimSortAscending(a, aget, aset, amake, selector, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderAscending(a, aget, aset, selector, lo, hi);\n                BinarySortAscending(a, aget, aset, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetDoubleSel<TArray, T>(a, aget, aset, amake, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderAscending(a, aget, aset, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortAscending(a, aget, aset, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongAsc(ti);\n        }\n\n        private static void MergeCollapseLongAsc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongAsc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongAsc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightAscending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftAscending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongAsc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a, idx2)) < selector(aget(t, idx1)))\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightAscending(t, aget, selector, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftAscending(a, aget, selector, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongAsc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(t, idx2)) < selector(aget(a, idx1)))\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightAscending(a, aget, selector, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftAscending(t, aget, selector, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) > selector(aget(a, start + hint)))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) > selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) <= selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(aget(a, start + m)))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) < selector(aget(a, start + hint)))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) < selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) >= selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(aget(a, start + m)))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) < selector(aget(a, mid)))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderAscending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a, runHi++)) < selector(aget(a, beginIncl)))\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) < selector(aget(a, runHi - 1)))\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) >= selector(aget(a, runHi - 1)))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector, long med)\n        {\n            long last = count - 1;\n            QuickMedianDescending(a, aget, aset, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            QuickMedianDescending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickMedianDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) < selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) < selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(aget(a, hi)) < selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) < selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector)\n        {\n            long last = count - 1;\n            QuickSortDescending(a, aget, aset, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            QuickSortDescending(a, aget, aset, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void QuickSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a, e1)) < selector(aget(a, e2))) { var t = aget(a, e1); aset(a, e1, aget(a, e2)); aset(a, e2, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e3))) { var t = aget(a, e1); aset(a, e1, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e1)) < selector(aget(a, e4))) { var t = aget(a, e1); aset(a, e1, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e3)) < selector(aget(a, e4))) { var t = aget(a, e3); aset(a, e3, aget(a, e4)); aset(a, e4, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e5))) { var t = aget(a, e2); aset(a, e2, aget(a, e5)); aset(a, e5, t); }\n                if (selector(aget(a, e2)) < selector(aget(a, e3))) { var t = aget(a, e2); aset(a, e2, aget(a, e3)); aset(a, e3, t); }\n                if (selector(aget(a, e4)) < selector(aget(a, e5))) { var t = aget(a, e4); aset(a, e4, aget(a, e5)); aset(a, e5, t); }\n\n                var p1 = aget(a, e2); aset(a, e2, aget(a, l));\n                var p2 = aget(a, e4); aset(a, e4, aget(a, r));\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(p1) != selector(p2);\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else if (selector(ai) < selector(p2))\n                        {\n                            while (selector(aget(a, hi)) < selector(p2) && i < hi)\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = aget(a, i);\n                        if (selector(ai) == selector(p1)) continue;\n                        if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        else\n                        {\n                            while (selector(aget(a, hi)) < selector(p1))\n                                --hi;\n                            aset(a, i, aget(a, hi)); aset(a, hi, ai); --hi; ai = aget(a, i);\n                            if (selector(ai) > selector(p1)) { aset(a, i, aget(a, lo)); aset(a, lo, ai); ++lo; }\n                        }\n                    }\n                }\n\n                aset(a, l, aget(a, lo - 1)); aset(a, lo - 1, p1);\n                aset(a, r, aget(a, hi + 1)); aset(a, hi + 1, p2);\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                        QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a, lo)) == selector(p1))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a, i)) == selector(p1)) { p1 = aget(a, i); aset(a, i, aget(a, lo)); aset(a, lo, p1); ++lo; }\n                            }\n                            while (selector(aget(a, hi)) == selector(p2))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a, i)) == selector(p2)) { p2 = aget(a, i); aset(a, i, aget(a, hi)); aset(a, hi, p2); --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, selector, lo, hi, cm);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                                QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        QuickSortDescending(a, aget, aset, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        QuickSortDescending(a, aget, aset, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = aget(a, i); long j;\n                for (j = i - 1; j >= l && selector(ai) > selector(aget(a, j)); j--)\n                    aset(a, j + 1, aget(a, j));\n                aset(a, j + 1, ai);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c + begin);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(aget(a, i2 + begin)))\n                        break;\n                    aset(a, i + begin, aget(a, i2 + begin));\n                    i = i2;\n                }\n                aset(a, i + begin, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count + begin);\n                aset(a, count + begin, aget(a, 0 + begin));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1 + begin)) > selector(aget(a, i2 + begin)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni + begin)) > selector(element))\n                        break;\n                    aset(a, i + begin, aget(a, ni + begin));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i + begin, element);\n            }\n        }\n\n        /// <summary>\n        /// The HeapSort algorithm sorts the data array.\n        /// It is slower than the QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void HeapSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector)\n        {\n            for (long c = 1; c < count; c++)\n            {\n                var element = aget(a, c);\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(element) > selector(aget(a, i2)))\n                        break;\n                    aset(a, i, aget(a, i2));\n                    i = i2;\n                }\n                aset(a, i, element);\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = aget(a, count);\n                aset(a, count, aget(a, 0));\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a, i1)) > selector(aget(a, i2)))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a, ni)) > selector(element))\n                        break;\n                    aset(a, i, aget(a, ni));\n                    i = ni; i1 = 2 * i + 1;\n                }\n                aset(a, i, element);\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<T, double> selector)\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, selector, 0, count - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void SmoothSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            SmoothSortDescendingInclusiveRange(a, aget, aset, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void SmoothSortDescendingInclusiveRange<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n                    else\n                        SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    SmoothSortDescendingTrinkle(a, aget, aset, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void SmoothSortDescendingSift<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                int pshift, long head)\n        {\n            var val = aget(a, head);\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(val) <= selector(aget(a, lf)) && selector(val) <= selector(aget(a, rt))) break;\n                if (selector(aget(a, lf)) <= selector(aget(a, rt)))\n                {\n                    aset(a, head, aget(a, lf));\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    aset(a, head, aget(a, rt));\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            aset(a, head, val);\n        }\n\n        private static void SmoothSortDescendingTrinkle<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = aget(a, head);\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = aget(a, stepson);\n                if (selector(vstepson) >= selector(val)) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a, rt)) <= selector(vstepson) || selector(aget(a, lf)) <= selector(vstepson))\n                        break;\n                }\n                aset(a, head, vstepson);\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                aset(a, head, val);\n                SmoothSortDescendingSift(a, aget, aset, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, long count, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake, Func<T, double> selector)\n        {\n            TimSortDescending(a, aget, aset, amake, selector, 0, count);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void TimSortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset, Func<long, TArray> amake,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = CountRunAndOrderDescending(a, aget, aset, selector, lo, hi);\n                BinarySortDescending(a, aget, aset, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoLongGetDoubleSel<TArray, T>(a, aget, aset, amake, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = CountRunAndOrderDescending(a, aget, aset, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    BinarySortDescending(a, aget, aset, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapseLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapseLongDesc(ti);\n        }\n\n        private static void MergeCollapseLongDesc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapseLongDesc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtLongDesc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = GallopRightDescending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start2), start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = GallopLeftDescending(a, ti.m_aget, ti.m_sel, ti.m_aget(a, start1 + len1 - 1), start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoLongDesc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len1);\n            CopyElements(aget, aset, a, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            aset(a, dest++, aget(a, idx2++));\n            if (--len2 == 0)\n            {\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a, idx2)) > selector(aget(t, idx1)))\n                    {\n                        aset(a, dest++, aget(a, idx2++));\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest++, aget(t, idx1++));\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = GallopRightDescending(t, aget, selector, aget(a, idx2), idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        CopyElements(aget, aset, t, idx1, a, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    aset(a, dest++, aget(a, idx2++));\n                    if (--len2 == 0) goto breakouter;\n                    count2 = GallopLeftDescending(a, aget, selector, aget(t, idx1), idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        CopyElements(aget, aset, a, idx2, a, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    aset(a, dest++, aget(t, idx1++));\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                CopyElements(aget, aset, a, idx2, a, dest, len2);\n                aset(a, dest + len2, aget(t, idx1));\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, idx1, a, dest, len1);\n        }\n\n        private static void MergeHiLongDesc<TArray, T>(this TimSortInfoLongGetDoubleSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var aset = ti.m_aset;\n            var t = ti.EnsureCapacity(len2);\n            CopyElements(aget, aset, a, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            aset(a, dest--, aget(a, idx1--));\n            if (--len1 == 0)\n            {\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(t, idx2)) > selector(aget(a, idx1)))\n                    {\n                        aset(a, dest--, aget(a, idx1--));\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        aset(a, dest--, aget(t, idx2--));\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - GallopRightDescending(a, aget, selector, aget(t, idx2), start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    aset(a, dest--, aget(t, idx2--));\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - GallopLeftDescending(t, aget, selector, aget(a, idx1), 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        CopyElements(aget, aset, t, idx2 + 1, a, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    aset(a, dest--, aget(a, idx1--));\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                CopyElements(aget, aset, a, idx1 + 1, a, dest + 1, len1);\n                aset(a, dest, aget(t, idx2));\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                CopyElements(aget, aset, t, 0, a, dest - (len2 - 1), len2);\n        }\n\n        private static long GallopLeftDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                T key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(key) < selector(aget(a, start + hint)))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) < selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) >= selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) < selector(aget(a, start + m)))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long GallopRightDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                T key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(key) > selector(aget(a, start + hint)))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(key) > selector(aget(a, start + hint - ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(key) <= selector(aget(a, start + hint + ofs)))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(key) > selector(aget(a, start + m)))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void BinarySortDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = aget(a, beginUnsorted);\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(pivot) > selector(aget(a, mid)))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: aset(a, l + 2, aget(a, l + 1)); aset(a, l + 1, aget(a, l)); break;\n                    case 1: aset(a, l + 1, aget(a, l)); break;\n                    default: CopyElements(aget, aset, a, l, a, l + 1, n); break;\n                }\n                aset(a, l, pivot);\n            }\n        }\n\n        private static long CountRunAndOrderDescending<TArray, T>(\n                this TArray a, Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a, runHi++)) > selector(aget(a, beginIncl)))\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) > selector(aget(a, runHi - 1)))\n                    runHi++;\n                ReverseRange(aget, aset, a, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a, runHi)) <= selector(aget(a, runHi - 1)))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Permutation Sort/Median for TArray\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedian<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedian(p, a, aget, cmp, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedian<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedian(p, a, aget, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedian<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (cmp(aget(a,p[e1]), aget(a,p[e2])) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(aget(a,p[e4]), aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(aget(a,p[e1]), aget(a,p[e3])) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e1]), aget(a,p[e4])) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(aget(a,p[e3]), aget(a,p[e4])) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e5])) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e4]), aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = cmp(aget(a,p1), aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(aget(a,ai), aget(a,p2)) > 0)\n                        {\n                            while (cmp(aget(a,p[hi]), aget(a,p2)) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(aget(a,ai), aget(a,p1)) == 0) continue;\n                        if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(aget(a,p[hi]), aget(a,p1)) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (cmp(aget(a,p[lo]), aget(a,p1)) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(aget(a,p[i]), aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(aget(a,p[hi]), aget(a,p2)) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(aget(a,p[i]), aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && cmp(aget(a,ai), aget(a,p[j])) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSort(p, a, aget, cmp, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSort(p, a, aget, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (cmp(aget(a,p[e1]), aget(a,p[e2])) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(aget(a,p[e4]), aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(aget(a,p[e1]), aget(a,p[e3])) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e1]), aget(a,p[e4])) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(aget(a,p[e3]), aget(a,p[e4])) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e5])) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e4]), aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = cmp(aget(a,p1), aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(aget(a,ai), aget(a,p2)) > 0)\n                        {\n                            while (cmp(aget(a,p[hi]), aget(a,p2)) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(aget(a,ai), aget(a,p1)) == 0) continue;\n                        if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(aget(a,p[hi]), aget(a,p1)) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                        PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                        {\n                            while (cmp(aget(a,p[lo]), aget(a,p1)) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(aget(a,p[i]), aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(aget(a,p[hi]), aget(a,p2)) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(aget(a,p[i]), aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSort(p, a, aget, cmp, lo, hi, cm);\n                                PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, aget, cmp, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && cmp(aget(a,ai), aget(a,p[j])) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (cmp(aget(a,element), aget(a,p[i2 + begin])) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && cmp(aget(a,p[i1 + begin]), aget(a,p[i2 + begin])) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(aget(a,p[ni + begin]), aget(a,element)) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (cmp(aget(a,element), aget(a,p[i2])) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && cmp(aget(a,p[i1]), aget(a,p[i2])) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(aget(a,p[ni]), aget(a,element)) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, aget, cmp, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, aget, cmp, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortSift(p, a, aget, cmp, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortTrinkle(p, a, aget, cmp, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortSift(p, a, aget, cmp, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortTrinkle(p, a, aget, cmp, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortTrinkle(p, a, aget, cmp, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortTrinkle(p, a, aget, cmp, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (cmp(aget(a,val), aget(a,p[lf])) >= 0 && cmp(aget(a,val), aget(a,p[rt])) >= 0) break;\n                if (cmp(aget(a,p[lf]), aget(a,p[rt])) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (cmp(aget(a,vstepson), aget(a,val)) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (cmp(aget(a,p[rt]), aget(a,vstepson)) >= 0 || cmp(aget(a,p[lf]), aget(a,vstepson)) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortSift(p, a, aget, cmp, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermGetCmp<TArray, T>\n        {\n            public int[] m_p;\n            public TArray m_a;\n            public int m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, T, int> m_cmp;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermGetCmp(int[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp, int count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_cmp = cmp;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp)\n        {\n            PermutationTimSort(p, a, aget, cmp, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrder(p, a, aget, cmp, lo, hi);\n                PermutationBinarySort(p, a, aget, cmp, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetCmp<TArray, T>(p, a, aget, cmp, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrder(p, a, aget, cmp, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySort(p, a, aget, cmp, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermCmp(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermCmp(ti);\n        }\n\n        private static void MergeCollapsePermCmp<TArray, T>(this TimSortInfoPermGetCmp<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermCmp(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermCmp(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermCmp<TArray, T>(this TimSortInfoPermGetCmp<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermCmp(ti, n);\n            }\n        }\n\n        private static void MergeAtPermCmp<TArray, T>(this TimSortInfoPermGetCmp<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRight(ti.m_p, a, ti.m_aget, ti.m_cmp, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeft(ti.m_p, a, ti.m_aget, ti.m_cmp, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermCmp(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermCmp(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermCmp<TArray, T>(this TimSortInfoPermGetCmp<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(aget(a,p[idx2]), aget(a,t[idx1])) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRight(t, a, aget, cmp, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeft(p, a, aget, cmp, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermCmp<TArray, T>(this TimSortInfoPermGetCmp<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(aget(a,t[idx2]), aget(a,p[idx1])) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRight(p, a, aget, cmp, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeft(t, a, aget, cmp, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeft<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (cmp(aget(a,key), aget(a,p[start + hint])) > 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(aget(a,key), aget(a,p[start + hint + ofs])) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(aget(a,key), aget(a,p[start + hint - ofs])) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(aget(a,key), aget(a,p[start + m])) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRight<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (cmp(aget(a,key), aget(a,p[start + hint])) < 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(aget(a,key), aget(a,p[start + hint - ofs])) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(aget(a,key), aget(a,p[start + hint + ofs])) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(aget(a,key), aget(a,p[start + m])) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySort<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (cmp(aget(a,pivot), aget(a,p[mid])) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrder<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (cmp(aget(a,p[runHi++]), aget(a,p[beginIncl])) < 0)\n            {\n                while (runHi < endExcl && cmp(aget(a,p[runHi]), aget(a,p[runHi - 1])) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && cmp(aget(a,p[runHi]), aget(a,p[runHi - 1])) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedian<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedian(p, a, aget, cmp, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedian<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedian(p, a, aget, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedian<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (cmp(aget(a,p[e1]), aget(a,p[e2])) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(aget(a,p[e4]), aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(aget(a,p[e1]), aget(a,p[e3])) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e1]), aget(a,p[e4])) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(aget(a,p[e3]), aget(a,p[e4])) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e5])) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e4]), aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = cmp(aget(a,p1), aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(aget(a,ai), aget(a,p2)) > 0)\n                        {\n                            while (cmp(aget(a,p[hi]), aget(a,p2)) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(aget(a,ai), aget(a,p1)) == 0) continue;\n                        if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(aget(a,p[hi]), aget(a,p1)) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (cmp(aget(a,p[lo]), aget(a,p1)) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(aget(a,p[i]), aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(aget(a,p[hi]), aget(a,p2)) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(aget(a,p[i]), aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && cmp(aget(a,ai), aget(a,p[j])) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSort(p, a, aget, cmp, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSort(p, a, aget, cmp, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (cmp(aget(a,p[e1]), aget(a,p[e2])) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (cmp(aget(a,p[e4]), aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (cmp(aget(a,p[e1]), aget(a,p[e3])) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e1]), aget(a,p[e4])) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (cmp(aget(a,p[e3]), aget(a,p[e4])) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e5])) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (cmp(aget(a,p[e2]), aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (cmp(aget(a,p[e4]), aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = cmp(aget(a,p1), aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (cmp(aget(a,ai), aget(a,p2)) > 0)\n                        {\n                            while (cmp(aget(a,p[hi]), aget(a,p2)) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (cmp(aget(a,ai), aget(a,p1)) == 0) continue;\n                        if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (cmp(aget(a,p[hi]), aget(a,p1)) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (cmp(aget(a,ai), aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                        PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                        {\n                            while (cmp(aget(a,p[lo]), aget(a,p1)) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (cmp(aget(a,p[i]), aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (cmp(aget(a,p[hi]), aget(a,p2)) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (cmp(aget(a,p[i]), aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSort(p, a, aget, cmp, lo, hi, cm);\n                                PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, aget, cmp, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                                PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSort(p, a, aget, cmp, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSort(p, a, aget, cmp, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && cmp(aget(a,ai), aget(a,p[j])) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (cmp(aget(a,element), aget(a,p[i2 + begin])) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && cmp(aget(a,p[i1 + begin]), aget(a,p[i2 + begin])) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(aget(a,p[ni + begin]), aget(a,element)) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (cmp(aget(a,element), aget(a,p[i2])) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && cmp(aget(a,p[i1]), aget(a,p[i2])) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (cmp(aget(a,p[ni]), aget(a,element)) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, aget, cmp, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortInclusiveRange(p, a, aget, cmp, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortSift(p, a, aget, cmp, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortTrinkle(p, a, aget, cmp, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortSift(p, a, aget, cmp, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortTrinkle(p, a, aget, cmp, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortTrinkle(p, a, aget, cmp, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortTrinkle(p, a, aget, cmp, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (cmp(aget(a,val), aget(a,p[lf])) >= 0 && cmp(aget(a,val), aget(a,p[rt])) >= 0) break;\n                if (cmp(aget(a,p[lf]), aget(a,p[rt])) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (cmp(aget(a,vstepson), aget(a,val)) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (cmp(aget(a,p[rt]), aget(a,vstepson)) >= 0 || cmp(aget(a,p[lf]), aget(a,vstepson)) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortSift(p, a, aget, cmp, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongGetCmp<TArray, T>\n        {\n            public long[] m_p;\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, T, int> m_cmp;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongGetCmp(long[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp, long count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_cmp = cmp;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, T, int> cmp)\n        {\n            PermutationTimSort(p, a, aget, cmp, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrder(p, a, aget, cmp, lo, hi);\n                PermutationBinarySort(p, a, aget, cmp, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetCmp<TArray, T>(p, a, aget, cmp, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrder(p, a, aget, cmp, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySort(p, a, aget, cmp, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongCmp(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongCmp(ti);\n        }\n\n        private static void MergeCollapsePermLongCmp<TArray, T>(this TimSortInfoPermLongGetCmp<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongCmp(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongCmp(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongCmp<TArray, T>(this TimSortInfoPermLongGetCmp<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongCmp(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongCmp<TArray, T>(this TimSortInfoPermLongGetCmp<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRight(ti.m_p, a, ti.m_aget, ti.m_cmp, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeft(ti.m_p, a, ti.m_aget, ti.m_cmp, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongCmp(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongCmp(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongCmp<TArray, T>(this TimSortInfoPermLongGetCmp<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(aget(a,p[idx2]), aget(a,t[idx1])) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRight(t, a, aget, cmp, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeft(p, a, aget, cmp, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongCmp<TArray, T>(this TimSortInfoPermLongGetCmp<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, T, int> cmp = ti.m_cmp;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (cmp(aget(a,t[idx2]), aget(a,p[idx1])) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRight(p, a, aget, cmp, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeft(t, a, aget, cmp, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeft<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (cmp(aget(a,key), aget(a,p[start + hint])) > 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(aget(a,key), aget(a,p[start + hint + ofs])) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(aget(a,key), aget(a,p[start + hint - ofs])) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(aget(a,key), aget(a,p[start + m])) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRight<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (cmp(aget(a,key), aget(a,p[start + hint])) < 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && cmp(aget(a,key), aget(a,p[start + hint - ofs])) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && cmp(aget(a,key), aget(a,p[start + hint + ofs])) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (cmp(aget(a,key), aget(a,p[start + m])) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySort<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (cmp(aget(a,pivot), aget(a,p[mid])) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrder<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, T, int> cmp,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (cmp(aget(a,p[runHi++]), aget(a,p[beginIncl])) < 0)\n            {\n                while (runHi < endExcl && cmp(aget(a,p[runHi]), aget(a,p[runHi - 1])) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && cmp(aget(a,p[runHi]), aget(a,p[runHi - 1])) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, int med)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, aget, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl, int med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianAscending(p, a, aget, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int l, int r, int countSub1, int med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e2])) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e4])) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e3]).CompareTo(aget(a,p[e4])) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = aget(a,p1).CompareTo(aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (aget(a,ai).CompareTo(aget(a,p2)) > 0)\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) == 0) continue;\n                        if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p1)) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (aget(a,p[lo]).CompareTo(aget(a,p1)) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && aget(a,ai).CompareTo(aget(a,p[j])) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, aget, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortAscending(p, a, aget, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int l, int r, int countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e2])) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e4])) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e3]).CompareTo(aget(a,p[e4])) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = aget(a,p1).CompareTo(aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (aget(a,ai).CompareTo(aget(a,p2)) > 0)\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) == 0) continue;\n                        if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p1)) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                        {\n                            while (aget(a,p[lo]).CompareTo(aget(a,p1)) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && aget(a,ai).CompareTo(aget(a,p[j])) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, int begin, int end)\n            where T : IComparable<T>\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (aget(a,element).CompareTo(aget(a,p[i2 + begin])) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && aget(a,p[i1 + begin]).CompareTo(aget(a,p[i2 + begin])) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a,p[ni + begin]).CompareTo(aget(a,element)) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (aget(a,element).CompareTo(aget(a,p[i2])) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && aget(a,p[i1]).CompareTo(aget(a,p[i2])) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a,p[ni]).CompareTo(aget(a,element)) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int pshift, int head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (aget(a,val).CompareTo(aget(a,p[lf])) >= 0 && aget(a,val).CompareTo(aget(a,p[rt])) >= 0) break;\n                if (aget(a,p[lf]).CompareTo(aget(a,p[rt])) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                long pbits, int pshift, int head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (aget(a,vstepson).CompareTo(aget(a,val)) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (aget(a,p[rt]).CompareTo(aget(a,vstepson)) >= 0 || aget(a,p[lf]).CompareTo(aget(a,vstepson)) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermGet<TArray, T>\n            where T : IComparable<T>\n        {\n            public int[] m_p;\n            public TArray m_a;\n            public int m_count;\n            public Func<TArray, long, T> m_aget;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermGet(int[] p, TArray a, Func<TArray, long, T> aget, int count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; \n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            PermutationTimSortAscending(p, a, aget, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGet<TArray, T>(p, a, aget, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, aget, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti, int i)\n            where T : IComparable<T>\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a,p[idx2]).CompareTo(aget(a,t[idx1])) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a,t[idx2]).CompareTo(aget(a,p[idx1])) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int lastOfs = 0, ofs = 1;\n            if (aget(a,key).CompareTo(aget(a,p[start + hint])) > 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint + ofs])) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint - ofs])) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (aget(a,key).CompareTo(aget(a,p[start + m])) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int ofs = 1, lastOfs = 0;\n            if (aget(a,key).CompareTo(aget(a,p[start + hint])) < 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint - ofs])) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint + ofs])) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (aget(a,key).CompareTo(aget(a,p[start + m])) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl, int beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (aget(a,pivot).CompareTo(aget(a,p[mid])) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (aget(a,p[runHi++]).CompareTo(aget(a,p[beginIncl])) < 0)\n            {\n                while (runHi < endExcl && aget(a,p[runHi]).CompareTo(aget(a,p[runHi - 1])) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && aget(a,p[runHi]).CompareTo(aget(a,p[runHi - 1])) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, long med)\n            where T : IComparable<T>\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, aget, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl, long med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianAscending(p, a, aget, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long l, long r, long countSub1, long med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e2])) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e4])) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e3]).CompareTo(aget(a,p[e4])) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = aget(a,p1).CompareTo(aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (aget(a,ai).CompareTo(aget(a,p2)) > 0)\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) == 0) continue;\n                        if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p1)) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (aget(a,p[lo]).CompareTo(aget(a,p1)) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && aget(a,ai).CompareTo(aget(a,p[j])) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, aget, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortAscending(p, a, aget, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long l, long r, long countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e2])) > 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e4])) > 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e3]).CompareTo(aget(a,p[e4])) > 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) > 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) > 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = aget(a,p1).CompareTo(aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (aget(a,ai).CompareTo(aget(a,p2)) > 0)\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) > 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) == 0) continue;\n                        if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p1)) > 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) < 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                        {\n                            while (aget(a,p[lo]).CompareTo(aget(a,p1)) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && aget(a,ai).CompareTo(aget(a,p[j])) < 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, long begin, long end)\n            where T : IComparable<T>\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (aget(a,element).CompareTo(aget(a,p[i2 + begin])) < 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && aget(a,p[i1 + begin]).CompareTo(aget(a,p[i2 + begin])) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a,p[ni + begin]).CompareTo(aget(a,element)) < 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (aget(a,element).CompareTo(aget(a,p[i2])) < 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && aget(a,p[i1]).CompareTo(aget(a,p[i2])) < 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a,p[ni]).CompareTo(aget(a,element)) < 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                int pshift, long head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (aget(a,val).CompareTo(aget(a,p[lf])) >= 0 && aget(a,val).CompareTo(aget(a,p[rt])) >= 0) break;\n                if (aget(a,p[lf]).CompareTo(aget(a,p[rt])) >= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long pbits, int pshift, long head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (aget(a,vstepson).CompareTo(aget(a,val)) <= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (aget(a,p[rt]).CompareTo(aget(a,vstepson)) >= 0 || aget(a,p[lf]).CompareTo(aget(a,vstepson)) >= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongGet<TArray, T>\n            where T : IComparable<T>\n        {\n            public long[] m_p;\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongGet(long[] p, TArray a, Func<TArray, long, T> aget, long count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; \n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            PermutationTimSortAscending(p, a, aget, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGet<TArray, T>(p, a, aget, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, aget, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti, int i)\n            where T : IComparable<T>\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a,p[idx2]).CompareTo(aget(a,t[idx1])) < 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a,t[idx2]).CompareTo(aget(a,p[idx1])) < 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long lastOfs = 0, ofs = 1;\n            if (aget(a,key).CompareTo(aget(a,p[start + hint])) > 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint + ofs])) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint - ofs])) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (aget(a,key).CompareTo(aget(a,p[start + m])) > 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long ofs = 1, lastOfs = 0;\n            if (aget(a,key).CompareTo(aget(a,p[start + hint])) < 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint - ofs])) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint + ofs])) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (aget(a,key).CompareTo(aget(a,p[start + m])) < 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl, long beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (aget(a,pivot).CompareTo(aget(a,p[mid])) < 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (aget(a,p[runHi++]).CompareTo(aget(a,p[beginIncl])) < 0)\n            {\n                while (runHi < endExcl && aget(a,p[runHi]).CompareTo(aget(a,p[runHi - 1])) < 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && aget(a,p[runHi]).CompareTo(aget(a,p[runHi - 1])) >= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, int med)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, aget, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl, int med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianDescending(p, a, aget, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int l, int r, int countSub1, int med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e2])) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e4])) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e3]).CompareTo(aget(a,p[e4])) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = aget(a,p1).CompareTo(aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (aget(a,ai).CompareTo(aget(a,p2)) < 0)\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) == 0) continue;\n                        if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p1)) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (aget(a,p[lo]).CompareTo(aget(a,p1)) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && aget(a,ai).CompareTo(aget(a,p[j])) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, aget, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortDescending(p, a, aget, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int l, int r, int countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e2])) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e4])) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e3]).CompareTo(aget(a,p[e4])) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = aget(a,p1).CompareTo(aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (aget(a,ai).CompareTo(aget(a,p2)) < 0)\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) == 0) continue;\n                        if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p1)) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                        {\n                            while (aget(a,p[lo]).CompareTo(aget(a,p1)) == 0)\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) == 0)\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && aget(a,ai).CompareTo(aget(a,p[j])) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, int begin, int end)\n            where T : IComparable<T>\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (aget(a,element).CompareTo(aget(a,p[i2 + begin])) > 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && aget(a,p[i1 + begin]).CompareTo(aget(a,p[i2 + begin])) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a,p[ni + begin]).CompareTo(aget(a,element)) > 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (aget(a,element).CompareTo(aget(a,p[i2])) > 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && aget(a,p[i1]).CompareTo(aget(a,p[i2])) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a,p[ni]).CompareTo(aget(a,element)) > 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int pshift, int head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (aget(a,val).CompareTo(aget(a,p[lf])) <= 0 && aget(a,val).CompareTo(aget(a,p[rt])) <= 0) break;\n                if (aget(a,p[lf]).CompareTo(aget(a,p[rt])) <= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                long pbits, int pshift, int head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (aget(a,vstepson).CompareTo(aget(a,val)) >= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (aget(a,p[rt]).CompareTo(aget(a,vstepson)) <= 0 || aget(a,p[lf]).CompareTo(aget(a,vstepson)) <= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            PermutationTimSortDescending(p, a, aget, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int lo, int hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGet<TArray, T>(p, a, aget, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, aget, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti, int i)\n            where T : IComparable<T>\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a,p[idx2]).CompareTo(aget(a,t[idx1])) > 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<TArray, T>(this TimSortInfoPermGet<TArray, T> ti, int start1, int len1, int start2, int len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a,t[idx2]).CompareTo(aget(a,p[idx1])) > 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int lastOfs = 0, ofs = 1;\n            if (aget(a,key).CompareTo(aget(a,p[start + hint])) < 0)\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint + ofs])) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint - ofs])) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (aget(a,key).CompareTo(aget(a,p[start + m])) < 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int key, int start, int len, int hint)\n            where T : IComparable<T>\n        {\n            int ofs = 1, lastOfs = 0;\n            if (aget(a,key).CompareTo(aget(a,p[start + hint])) > 0)\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint - ofs])) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint + ofs])) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (aget(a,key).CompareTo(aget(a,p[start + m])) > 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl, int beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (aget(a,pivot).CompareTo(aget(a,p[mid])) > 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                int beginIncl, int endExcl)\n            where T : IComparable<T>\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (aget(a,p[runHi++]).CompareTo(aget(a,p[beginIncl])) > 0)\n            {\n                while (runHi < endExcl && aget(a,p[runHi]).CompareTo(aget(a,p[runHi - 1])) > 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && aget(a,p[runHi]).CompareTo(aget(a,p[runHi - 1])) <= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, long med)\n            where T : IComparable<T>\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, aget, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl, long med)\n            where T : IComparable<T>\n        {\n            PermutationQuickMedianDescending(p, a, aget, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long l, long r, long countSub1, long med)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e2])) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e4])) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e3]).CompareTo(aget(a,p[e4])) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = aget(a,p1).CompareTo(aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (aget(a,ai).CompareTo(aget(a,p2)) < 0)\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) == 0) continue;\n                        if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p1)) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (aget(a,p[lo]).CompareTo(aget(a,p1)) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && aget(a,ai).CompareTo(aget(a,p[j])) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, aget, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            PermutationQuickSortDescending(p, a, aget, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long l, long r, long countSub1)\n            where T : IComparable<T>\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e2])) < 0) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e1]).CompareTo(aget(a,p[e4])) < 0) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e3]).CompareTo(aget(a,p[e4])) < 0) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (aget(a,p[e2]).CompareTo(aget(a,p[e3])) < 0) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (aget(a,p[e4]).CompareTo(aget(a,p[e5])) < 0) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = aget(a,p1).CompareTo(aget(a,p2)) != 0;\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (aget(a,ai).CompareTo(aget(a,p2)) < 0)\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) < 0 && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (aget(a,ai).CompareTo(aget(a,p1)) == 0) continue;\n                        if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (aget(a,p[hi]).CompareTo(aget(a,p1)) < 0)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (aget(a,ai).CompareTo(aget(a,p1)) > 0) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                        {\n                            while (aget(a,p[lo]).CompareTo(aget(a,p1)) == 0)\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p1)) == 0) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (aget(a,p[hi]).CompareTo(aget(a,p2)) == 0)\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (aget(a,p[i]).CompareTo(aget(a,p2)) == 0) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && aget(a,ai).CompareTo(aget(a,p[j])) > 0; j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, long begin, long end)\n            where T : IComparable<T>\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (aget(a,element).CompareTo(aget(a,p[i2 + begin])) > 0)\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && aget(a,p[i1 + begin]).CompareTo(aget(a,p[i2 + begin])) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a,p[ni + begin]).CompareTo(aget(a,element)) > 0)\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (aget(a,element).CompareTo(aget(a,p[i2])) > 0)\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && aget(a,p[i1]).CompareTo(aget(a,p[i2])) > 0)\n                                 ? i2 : i1; // smaller child\n                    if (aget(a,p[ni]).CompareTo(aget(a,element)) > 0)\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                int pshift, long head)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (aget(a,val).CompareTo(aget(a,p[lf])) <= 0 && aget(a,val).CompareTo(aget(a,p[rt])) <= 0) break;\n                if (aget(a,p[lf]).CompareTo(aget(a,p[rt])) <= 0)\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long pbits, int pshift, long head, bool isTrusty)\n            where T : IComparable<T>\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (aget(a,vstepson).CompareTo(aget(a,val)) >= 0) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (aget(a,p[rt]).CompareTo(aget(a,vstepson)) <= 0 || aget(a,p[lf]).CompareTo(aget(a,vstepson)) <= 0)\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget)\n            where T : IComparable<T>\n        {\n            PermutationTimSortDescending(p, a, aget, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long lo, long hi)\n            where T : IComparable<T>\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGet<TArray, T>(p, a, aget, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, aget, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti)\n            where T : IComparable<T>\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti, int i)\n            where T : IComparable<T>\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a,p[idx2]).CompareTo(aget(a,t[idx1])) > 0)\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<TArray, T>(this TimSortInfoPermLongGet<TArray, T> ti, long start1, long len1, long start2, long len2)\n            where T : IComparable<T>\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (aget(a,t[idx2]).CompareTo(aget(a,p[idx1])) > 0)\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long lastOfs = 0, ofs = 1;\n            if (aget(a,key).CompareTo(aget(a,p[start + hint])) < 0)\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint + ofs])) < 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint - ofs])) >= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (aget(a,key).CompareTo(aget(a,p[start + m])) < 0)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long key, long start, long len, long hint)\n            where T : IComparable<T>\n        {\n            long ofs = 1, lastOfs = 0;\n            if (aget(a,key).CompareTo(aget(a,p[start + hint])) > 0)\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint - ofs])) > 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && aget(a,key).CompareTo(aget(a,p[start + hint + ofs])) <= 0)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (aget(a,key).CompareTo(aget(a,p[start + m])) > 0)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl, long beginUnsorted)\n            where T : IComparable<T>\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (aget(a,pivot).CompareTo(aget(a,p[mid])) > 0)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                long beginIncl, long endExcl)\n            where T : IComparable<T>\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (aget(a,p[runHi++]).CompareTo(aget(a,p[beginIncl])) > 0)\n            {\n                while (runHi < endExcl && aget(a,p[runHi]).CompareTo(aget(a,p[runHi - 1])) > 0)\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && aget(a,p[runHi]).CompareTo(aget(a,p[runHi - 1])) <= 0)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) < selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) < selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) < selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) < selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(aget(a,val)) >= selector(aget(a,p[lf])) && selector(aget(a,val)) >= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) >= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) <= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(aget(a,p[rt])) >= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) >= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermGetIntSel<TArray, T>\n        {\n            public int[] m_p;\n            public TArray m_a;\n            public int m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, int> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermGetIntSel(int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, int count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_sel = selector;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            PermutationTimSortAscending(p, a, aget, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetIntSel<TArray, T>(p, a, aget, selector, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) < selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) < selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) < selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) < selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) < selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) >= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) < selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) < selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) < selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) < selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(aget(a,val)) >= selector(aget(a,p[lf])) && selector(aget(a,val)) >= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) >= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) <= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a,p[rt])) >= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) >= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongGetIntSel<TArray, T>\n        {\n            public long[] m_p;\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, int> m_sel;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongGetIntSel(long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, long count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_sel = selector;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            PermutationTimSortAscending(p, a, aget, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetIntSel<TArray, T>(p, a, aget, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) < selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) < selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) < selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) < selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) < selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) >= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) > selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) > selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) > selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) > selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(aget(a,val)) <= selector(aget(a,p[lf])) && selector(aget(a,val)) <= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) <= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) >= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(aget(a,p[rt])) <= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) <= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            PermutationTimSortDescending(p, a, aget, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetIntSel<TArray, T>(p, a, aget, selector, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) > selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<TArray, T>(this TimSortInfoPermGetIntSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) > selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) > selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) > selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) > selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) <= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) > selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) > selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) > selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) > selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(aget(a,val)) <= selector(aget(a,p[lf])) && selector(aget(a,val)) <= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) <= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) >= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a,p[rt])) <= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) <= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, int> selector)\n        {\n            PermutationTimSortDescending(p, a, aget, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetIntSel<TArray, T>(p, a, aget, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) > selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<TArray, T>(this TimSortInfoPermLongGetIntSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, int> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) > selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) > selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, int> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) > selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) > selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) <= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) < selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) < selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) < selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) < selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(aget(a,val)) >= selector(aget(a,p[lf])) && selector(aget(a,val)) >= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) >= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) <= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(aget(a,p[rt])) >= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) >= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermGetLongSel<TArray, T>\n        {\n            public int[] m_p;\n            public TArray m_a;\n            public int m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, long> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermGetLongSel(int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, int count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_sel = selector;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            PermutationTimSortAscending(p, a, aget, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetLongSel<TArray, T>(p, a, aget, selector, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) < selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) < selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) < selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) < selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) < selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) >= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) < selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) < selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) < selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) < selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(aget(a,val)) >= selector(aget(a,p[lf])) && selector(aget(a,val)) >= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) >= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) <= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a,p[rt])) >= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) >= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongGetLongSel<TArray, T>\n        {\n            public long[] m_p;\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, long> m_sel;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongGetLongSel(long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, long count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_sel = selector;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            PermutationTimSortAscending(p, a, aget, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetLongSel<TArray, T>(p, a, aget, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) < selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) < selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) < selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) < selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) < selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) >= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) > selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) > selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) > selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) > selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(aget(a,val)) <= selector(aget(a,p[lf])) && selector(aget(a,val)) <= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) <= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) >= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(aget(a,p[rt])) <= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) <= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            PermutationTimSortDescending(p, a, aget, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetLongSel<TArray, T>(p, a, aget, selector, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) > selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<TArray, T>(this TimSortInfoPermGetLongSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) > selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) > selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) > selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) > selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) <= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) > selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) > selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) > selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) > selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(aget(a,val)) <= selector(aget(a,p[lf])) && selector(aget(a,val)) <= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) <= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) >= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a,p[rt])) <= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) <= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, long> selector)\n        {\n            PermutationTimSortDescending(p, a, aget, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetLongSel<TArray, T>(p, a, aget, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) > selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<TArray, T>(this TimSortInfoPermLongGetLongSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, long> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) > selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) > selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, long> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) > selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) > selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) <= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) < selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) < selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) < selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) < selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(aget(a,val)) >= selector(aget(a,p[lf])) && selector(aget(a,val)) >= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) >= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) <= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(aget(a,p[rt])) >= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) >= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermGetFloatSel<TArray, T>\n        {\n            public int[] m_p;\n            public TArray m_a;\n            public int m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, float> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermGetFloatSel(int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, int count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_sel = selector;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            PermutationTimSortAscending(p, a, aget, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetFloatSel<TArray, T>(p, a, aget, selector, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) < selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) < selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) < selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) < selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) < selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) >= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) < selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) < selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) < selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) < selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(aget(a,val)) >= selector(aget(a,p[lf])) && selector(aget(a,val)) >= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) >= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) <= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a,p[rt])) >= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) >= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongGetFloatSel<TArray, T>\n        {\n            public long[] m_p;\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, float> m_sel;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongGetFloatSel(long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, long count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_sel = selector;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            PermutationTimSortAscending(p, a, aget, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetFloatSel<TArray, T>(p, a, aget, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) < selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) < selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) < selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) < selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) < selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) >= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) > selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) > selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) > selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) > selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(aget(a,val)) <= selector(aget(a,p[lf])) && selector(aget(a,val)) <= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) <= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) >= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(aget(a,p[rt])) <= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) <= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            PermutationTimSortDescending(p, a, aget, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetFloatSel<TArray, T>(p, a, aget, selector, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) > selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<TArray, T>(this TimSortInfoPermGetFloatSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) > selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) > selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) > selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) > selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) <= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) > selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) > selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) > selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) > selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(aget(a,val)) <= selector(aget(a,p[lf])) && selector(aget(a,val)) <= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) <= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) >= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a,p[rt])) <= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) <= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, float> selector)\n        {\n            PermutationTimSortDescending(p, a, aget, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetFloatSel<TArray, T>(p, a, aget, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) > selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<TArray, T>(this TimSortInfoPermLongGetFloatSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, float> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) > selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) > selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, float> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) > selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) > selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) <= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianAscending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortAscending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) < selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) < selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) < selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) < selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(aget(a,val)) >= selector(aget(a,p[lf])) && selector(aget(a,val)) >= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) >= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) <= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(aget(a,p[rt])) >= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) >= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermGetDoubleSel<TArray, T>\n        {\n            public int[] m_p;\n            public TArray m_a;\n            public int m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, double> m_sel;\n            public int m_minGallop = c_minGallop;\n            public int[] m_tmp;\n            public int m_stackSize = 0;\n            public int[] m_runStart;\n            public int[] m_runLen;\n\n            public TimSortInfoPermGetDoubleSel(int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, int count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_sel = selector;\n                m_tmp = new int[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new int[stackLen];\n                m_runLen = new int[stackLen];\n            }\n\n            public void PushRun(int runStart, int runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public int[] EnsureCapacity(int cap)\n            {\n                if (m_tmp.Length < cap)\n                {\n                    int c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c++;\n                    m_tmp = new int[c < 0 ? cap : Math.Min(c, m_p.Length >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            PermutationTimSortAscending(p, a, aget, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetDoubleSel<TArray, T>(p, a, aget, selector, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermAsc(ti);\n        }\n\n        private static void MergeCollapsePermAsc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermAsc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermAsc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermAsc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) < selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermAsc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) < selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) < selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderAscending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) < selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) < selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) >= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianAscending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortAscending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortAscending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) > selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) > selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) > selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) > selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) > selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) > selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) < selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortAscending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) < selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) < selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) < selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) < selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) < selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) < selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortAscendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortAscendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortAscendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortAscendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(aget(a,val)) >= selector(aget(a,p[lf])) && selector(aget(a,val)) >= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) >= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortAscendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) <= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a,p[rt])) >= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) >= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortAscendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        public class TimSortInfoPermLongGetDoubleSel<TArray, T>\n        {\n            public long[] m_p;\n            public TArray m_a;\n            public long m_count;\n            public Func<TArray, long, T> m_aget;\n            public Func<T, double> m_sel;\n            public long m_minGallop = c_minGallop;\n            public long[] m_tmp;\n            public int m_stackSize = 0;\n            public long[] m_runStart;\n            public long[] m_runLen;\n\n            public TimSortInfoPermLongGetDoubleSel(long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, long count)\n            {\n                m_p = p; m_a = a; m_count = count;\n                m_aget = aget; m_sel = selector;\n                m_tmp = new long[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new long[stackLen];\n                m_runLen = new long[stackLen];\n            }\n\n            public void PushRun(long runStart, long runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public long[] EnsureCapacity(long cap)\n            {\n                if (m_tmp.LongLength < cap)\n                {\n                    long c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16; c |= c >> 32; c++;\n                    m_tmp = new long[c < 0 ? cap : Math.Min(c, m_p.LongLength >> 1)];\n                }\n                return m_tmp;\n            }\n\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            PermutationTimSortAscending(p, a, aget, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortAscending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetDoubleSel<TArray, T>(p, a, aget, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderAscending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortAscending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongAsc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongAsc(ti);\n        }\n\n        private static void MergeCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongAsc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongAsc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongAsc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongAsc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongAsc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftAscending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongAsc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongAsc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongAsc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) < selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightAscending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftAscending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongAsc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) < selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightAscending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftAscending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) < selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderAscending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) < selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) < selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) >= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, int med)\n        {\n            int last = p.Length - 1;\n            PermutationQuickMedianDescending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int med)\n        {\n            PermutationQuickMedianDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int l, int r, int countSub1, int med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            int last = p.Length - 1;\n            PermutationQuickSortDescending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationQuickSortDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int l, int r, int countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                int sixth = (1 + countSub1) / 6;\n                int e1 = l + sixth;\n                int e5 = r - sixth;\n                int e3 = (l + r) >> 1;\n                int e4 = e3 + sixth;\n                int e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                int lo = l + 1;\n                int hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (int i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                int cl = lo - 2 - l;\n                int cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (int i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (int i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        int cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (int i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; int j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, int begin, int end)\n        {\n            int count = end - begin;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) > selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) > selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            int count = p.Length;\n            for (int c = 1; c < count; c++)\n            {\n                var element = p[c];\n                int i = c;\n                while (i > 0)\n                {\n                    int i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                int i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    int i2 = i1 + 1;\n                    int ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) > selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) > selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, 0, p.Length - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            int head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LP[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int pshift, int head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                int rt = head - 1;\n                int lf = head - 1 - LP[pshift - 2];\n                if (selector(aget(a,val)) <= selector(aget(a,p[lf])) && selector(aget(a,val)) <= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) <= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long pbits, int pshift, int head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                int stepson = head - LP[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) >= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    int rt = head - 1;\n                    int lf = head - 1 - LP[pshift - 2];\n                    if (selector(aget(a,p[rt])) <= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) <= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            PermutationTimSortDescending(p, a, aget, selector, 0, p.Length);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int lo, int hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            int count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermGetDoubleSel<TArray, T>(p, a, aget, selector, count);\n            int minRun = TimSortMinRunLength(count);\n            do\n            {\n                int runLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    int force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermDesc(ti);\n        }\n\n        private static void MergeCollapsePermDesc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermDesc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermDesc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti, int i)\n        {\n            int start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            int start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            int k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermDesc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            int idx1 = 0, idx2 = start2;\n            int dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) > selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermDesc<TArray, T>(this TimSortInfoPermGetDoubleSel<TArray, T> ti, int start1, int len1, int start2, int len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            int idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            int dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            int minGallop = ti.m_minGallop;\n            while (true)\n            {\n                int count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) > selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static int PermutationGallopLeftDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static int PermutationGallopRightDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int key, int start, int len, int hint)\n        {\n            int ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                int maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                int tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                int maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                int m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl, int beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                int l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    int mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) > selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                int n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static int PermutationCountRunAndOrderDescending<TArray, T>(\n                this int[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int beginIncl, int endExcl)\n        {\n            int runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) > selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) > selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) <= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, long med)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickMedianDescending(p, a, aget, selector, 0, last, last, med);\n        }\n\n        /// <summary>\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long med)\n        {\n            PermutationQuickMedianDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1, med);\n        }\n\n        /*\n            This implementation of QuickMedian is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickMedianDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long l, long r, long countSub1, long med)\n        {\n            while (countSub1 >= c_insertionMedianThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            if (med < lo || med > hi) return;\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                    }\n                }\n                else\n                {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            long last = p.LongLength - 1;\n            PermutationQuickSortDescending(p, a, aget, selector, 0, last, last);\n        }\n\n        /// <summary>\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationQuickSortDescending(p, a, aget, selector, beginIncl, endExcl - 1, endExcl - beginIncl - 1);\n        }\n\n        /*\n            This implementation of QuickSort is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void PermutationQuickSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long l, long r, long countSub1)\n        {\n            while (countSub1 >= c_insertionSortThreshold)\n            {\n                long sixth = (1 + countSub1) / 6;\n                long e1 = l + sixth;\n                long e5 = r - sixth;\n                long e3 = (l + r) >> 1;\n                long e4 = e3 + sixth;\n                long e2 = e3 - sixth;\n\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e2]))) { var t = p[e1]; p[e1] = p[e2]; p[e2] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e3]))) { var t = p[e1]; p[e1] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e1])) < selector(aget(a,p[e4]))) { var t = p[e1]; p[e1] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e3])) < selector(aget(a,p[e4]))) { var t = p[e3]; p[e3] = p[e4]; p[e4] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e5]))) { var t = p[e2]; p[e2] = p[e5]; p[e5] = t; }\n                if (selector(aget(a,p[e2])) < selector(aget(a,p[e3]))) { var t = p[e2]; p[e2] = p[e3]; p[e3] = t; }\n                if (selector(aget(a,p[e4])) < selector(aget(a,p[e5]))) { var t = p[e4]; p[e4] = p[e5]; p[e5] = t; }\n\n                var p1 = p[e2]; p[e2] = p[l];\n                var p2 = p[e4]; p[e4] = p[r];\n\n                long lo = l + 1;\n                long hi = r - 1;\n\n                bool pivotsDiffer = selector(aget(a,p1)) != selector(aget(a,p2));\n\n                if (pivotsDiffer)\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else if (selector(aget(a,ai)) < selector(aget(a,p2)))\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p2)) && i < hi)\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (long i = lo; i <= hi; i++)\n                    {\n                        var ai = p[i];\n                        if (selector(aget(a,ai)) == selector(aget(a,p1))) continue;\n                        if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        else\n                        {\n                            while (selector(aget(a,p[hi])) < selector(aget(a,p1)))\n                                --hi;\n                            p[i] = p[hi]; p[hi] = ai; --hi; ai = p[i];\n                            if (selector(aget(a,ai)) > selector(aget(a,p1))) { p[i] = p[lo]; p[lo] = ai; ++lo; }\n                        }\n                    }\n                }\n\n                p[l] = p[lo - 1]; p[lo - 1] = p1;\n                p[r] = p[hi + 1]; p[hi + 1] = p2;\n\n                long cl = lo - 2 - l;\n                long cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        {\n                            while (selector(aget(a,p[lo])) == selector(aget(a,p1)))\n                                ++lo;\n                            for (long i = lo + 1; i <= hi; i++)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p1))) { p1 = p[i]; p[i] = p[lo]; p[lo] = p1; ++lo; }\n                            }\n                            while (selector(aget(a,p[hi])) == selector(aget(a,p2)))\n                                --hi;\n                            for (long i = hi - 1; i >= lo; i--)\n                            {\n                                if (selector(aget(a,p[i])) == selector(aget(a,p2))) { p2 = p[i]; p[i] = p[hi]; p[hi] = p2; --hi; }\n                            }\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        long cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                                PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    if (cl > cr)\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        PermutationQuickSortDescending(p, a, aget, selector, l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                }\n            }\n\n            for (long i = l + 1; i <= r; i++)\n            {\n                var ai = p[i]; long j;\n                for (j = i - 1; j >= l && selector(aget(a,ai)) > selector(aget(a,p[j])); j--)\n                    p[j + 1] = p[j];\n                p[j + 1] = ai;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector, long begin, long end)\n        {\n            long count = end - begin;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c + begin];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2 + begin])))\n                        break;\n                    p[i + begin] = p[i2 + begin];\n                    i = i2;\n                }\n                p[i + begin] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count + begin];\n                p[count + begin] = p[0 + begin];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1 + begin])) > selector(aget(a,p[i2 + begin])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni + begin])) > selector(aget(a,element)))\n                        break;\n                    p[i + begin] = p[ni + begin];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i + begin] = element;\n            }\n        }\n\n        /// <summary>\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        /// It is slower than the PermutationQuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationHeapSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            long count = p.LongLength;\n            for (long c = 1; c < count; c++)\n            {\n                var element = p[c];\n                long i = c;\n                while (i > 0)\n                {\n                    long i2 = (i - 1) / 2;\n                    if (selector(aget(a,element)) > selector(aget(a,p[i2])))\n                        break;\n                    p[i] = p[i2];\n                    i = i2;\n                }\n                p[i] = element;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = p[count];\n                p[count] = p[0];\n                long i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    long i2 = i1 + 1;\n                    long ni = (i2 < count // two children?\n                              && selector(aget(a,p[i1])) > selector(aget(a,p[i2])))\n                                 ? i2 : i1; // smaller child\n                    if (selector(aget(a,p[ni])) > selector(aget(a,element)))\n                        break;\n                    p[i] = p[ni];\n                    i = ni; i1 = 2 * i + 1;\n                }\n                p[i] = element;\n            }\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, 0, p.LongLength - 1);\n        }\n\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationSmoothSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            PermutationSmoothSortDescendingInclusiveRange(p, a, aget, selector, beginIncl, endExcl - 1);\n        }\n\n        private static void PermutationSmoothSortDescendingInclusiveRange<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            long head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LPLong[pshift - 1] >= hi - head)\n                        PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n                    else\n                        PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits >> 1, pshift + 1, head - LPLong[pshift] - 1, true);\n                    PermutationSmoothSortDescendingTrinkle(p, a, aget, selector, pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void PermutationSmoothSortDescendingSift<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                int pshift, long head)\n        {\n            var val = p[head];\n            while (pshift > 1)\n            {\n                long rt = head - 1;\n                long lf = head - 1 - LPLong[pshift - 2];\n                if (selector(aget(a,val)) <= selector(aget(a,p[lf])) && selector(aget(a,val)) <= selector(aget(a,p[rt]))) break;\n                if (selector(aget(a,p[lf])) <= selector(aget(a,p[rt])))\n                {\n                    p[head] = p[lf];\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    p[head] = p[rt];\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            p[head] = val;\n        }\n\n        private static void PermutationSmoothSortDescendingTrinkle<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long pbits, int pshift, long head, bool isTrusty)\n        {\n            var val = p[head];\n\n            while (pbits != 1)\n            {\n                long stepson = head - LPLong[pshift];\n                var vstepson = p[stepson];\n                if (selector(aget(a,vstepson)) >= selector(aget(a,val))) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    long rt = head - 1;\n                    long lf = head - 1 - LPLong[pshift - 2];\n                    if (selector(aget(a,p[rt])) <= selector(aget(a,vstepson)) || selector(aget(a,p[lf])) <= selector(aget(a,vstepson)))\n                        break;\n                }\n                p[head] = vstepson;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                p[head] = val;\n                PermutationSmoothSortDescendingSift(p, a, aget, selector, pshift, head);\n            }\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget, Func<T, double> selector)\n        {\n            PermutationTimSortDescending(p, a, aget, selector, 0, p.LongLength);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        public static void PermutationTimSortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long lo, long hi)\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            long count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                PermutationBinarySortDescending(p, a, aget, selector, lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new TimSortInfoPermLongGetDoubleSel<TArray, T>(p, a, aget, selector, count);\n            long minRun = TimSortMinRunLength(count);\n            do\n            {\n                long runLen = PermutationCountRunAndOrderDescending(p, a, aget, selector, lo, hi);\n                if (runLen < minRun)\n                {\n                    long force = count <= minRun ? count : minRun;\n                    PermutationBinarySortDescending(p, a, aget, selector, lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapsePermLongDesc(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapsePermLongDesc(ti);\n        }\n\n        private static void MergeCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAtPermLongDesc(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAtPermLongDesc(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapsePermLongDesc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti)\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAtPermLongDesc(ti, n);\n            }\n        }\n\n        private static void MergeAtPermLongDesc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti, int i)\n        {\n            long start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            long start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            long k = PermutationGallopRightDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start2], start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = PermutationGallopLeftDescending(ti.m_p, a, ti.m_aget, ti.m_sel, ti.m_p[start1 + len1 - 1], start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLoPermLongDesc(ti, start1, len1, start2, len2);\n            else\n                MergeHiPermLongDesc(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLoPermLongDesc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len1);\n            Array.Copy(p, start1, t, 0, len1);\n            long idx1 = 0, idx2 = start2;\n            long dest = start1;\n            p[dest++] = p[idx2++];\n            if (--len2 == 0)\n            {\n                Array.Copy(t, idx1, p, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,p[idx2])) > selector(aget(a,t[idx1])))\n                    {\n                        p[dest++] = p[idx2++];\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest++] = t[idx1++];\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = PermutationGallopRightDescending(t, a, aget, selector, p[idx2], idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        Array.Copy(t, idx1, p, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    p[dest++] = p[idx2++];\n                    if (--len2 == 0) goto breakouter;\n                    count2 = PermutationGallopLeftDescending(p, a, aget, selector, t[idx1], idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        Array.Copy(p, idx2, p, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    p[dest++] = t[idx1++];\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                Array.Copy(p, idx2, p, dest, len2);\n                p[dest + len2] = t[idx1];\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, idx1, p, dest, len1);\n        }\n\n        private static void MergeHiPermLongDesc<TArray, T>(this TimSortInfoPermLongGetDoubleSel<TArray, T> ti, long start1, long len1, long start2, long len2)\n        {\n            var p = ti.m_p;\n            var a = ti.m_a;\n            var aget = ti.m_aget;\n            var t = ti.EnsureCapacity(len2);\n            Array.Copy(p, start2, t, 0, len2);\n            long idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            long dest = start2 + len2 - 1;\n            p[dest--] = p[idx1--];\n            if (--len1 == 0)\n            {\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n                return;\n            }\n            Func<T, double> selector = ti.m_sel;\n            long minGallop = ti.m_minGallop;\n            while (true)\n            {\n                long count1 = 0, count2 = 0;\n                do\n                {\n                    if (selector(aget(a,t[idx2])) > selector(aget(a,p[idx1])))\n                    {\n                        p[dest--] = p[idx1--];\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        p[dest--] = t[idx2--];\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - PermutationGallopRightDescending(p, a, aget, selector, t[idx2], start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        Array.Copy(p, idx1 + 1, p, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    p[dest--] = t[idx2--];\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - PermutationGallopLeftDescending(t, a, aget, selector, p[idx1], 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        Array.Copy(t, idx2 + 1, p, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    p[dest--] = p[idx1--];\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                Array.Copy(p, idx1 + 1, p, dest + 1, len1);\n                p[dest] = t[idx2];\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                Array.Copy(t, 0, p, dest - (len2 - 1), len2);\n        }\n\n        private static long PermutationGallopLeftDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long key, long start, long len, long hint)\n        {\n            long lastOfs = 0, ofs = 1;\n            if (selector(aget(a,key)) < selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) < selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) >= selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) < selector(aget(a,p[start + m])))\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static long PermutationGallopRightDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long key, long start, long len, long hint)\n        {\n            long ofs = 1, lastOfs = 0;\n            if (selector(aget(a,key)) > selector(aget(a,p[start + hint])))\n            {\n                long maxOfs = hint + 1;\n                while (ofs < maxOfs && selector(aget(a,key)) > selector(aget(a,p[start + hint - ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                long tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                long maxOfs = len - hint;\n                while (ofs < maxOfs && selector(aget(a,key)) <= selector(aget(a,p[start + hint + ofs])))\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                long m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (selector(aget(a,key)) > selector(aget(a,p[start + m])))\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void PermutationBinarySortDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl, long beginUnsorted)\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = p[beginUnsorted];\n                long l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    long mid = (l + r) >> 1;\n                    if (selector(aget(a,pivot)) > selector(aget(a,p[mid])))\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                long n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: p[l + 2] = p[l + 1]; p[l + 1] = p[l]; break;\n                    case 1: p[l + 1] = p[l]; break;\n                    default: Array.Copy(p, l, p, l + 1, n); break;\n                }\n                p[l] = pivot;\n            }\n        }\n\n        private static long PermutationCountRunAndOrderDescending<TArray, T>(\n                this long[] p, TArray a, Func<TArray, long, T> aget,\n                Func<T, double> selector,\n                long beginIncl, long endExcl)\n        {\n            long runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (selector(aget(a,p[runHi++])) > selector(aget(a,p[beginIncl])))\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) > selector(aget(a,p[runHi - 1])))\n                    runHi++;\n                ReverseRange(p, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && selector(aget(a,p[runHi])) <= selector(aget(a,p[runHi - 1])))\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        #endregion\n\n        #region Auxiliary Functions, Structures, and Data\n\n        /// <summary>\n        /// Necessary for bit-field representation of smooth sort\n        /// Leonardo heaps. \n        /// </summary>\n        private static int TrailingZeroBitCount(this long x)\n        {\n            x &= -x;\n            int c = (x == 0) ? 1 : 0;\n            if ((x & 0x00000000ffffffffL) == 0) c += 32;\n            if ((x & 0x0000ffff0000ffffL) == 0) c += 16;\n            if ((x & 0x00ff00ff00ff00ffL) == 0) c += 8;\n            if ((x & 0x0f0f0f0f0f0f0f0fL) == 0) c += 4;\n            if ((x & 0x3333333333333333L) == 0) c += 2;\n            if ((x & 0x5555555555555555L) == 0) c += 1;\n            return c;\n        }\n\n        /// <summary>\n        /// Int Leonardo numbers (smooth sort).\n        /// </summary>\n        private static readonly int[] LP =\n        {\n            1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219,\n            1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735,\n            150049, 242785, 392835, 635621, 1028457, 1664079, 2692537,\n            4356617, 7049155, 11405773, 18454929, 29860703, 48315633,\n            78176337, 126491971, 204668309, 331160281, 535828591, 866988873,\n            1402817465\n        };\n\n        /// <summary>\n        /// Long Leonardo numbers (smooth sort).\n        /// </summary>\n        private static readonly long[] LPLong =\n        {\n            1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219,\n            1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735,\n            150049, 242785, 392835, 635621, 1028457, 1664079, 2692537,\n            4356617, 7049155, 11405773, 18454929, 29860703, 48315633,\n            78176337, 126491971, 204668309, 331160281, 535828591, 866988873,\n            1402817465, 2269806339, 3672623805, 5942430145, 9615053951,\n            15557484097, 25172538049, 40730022147, 65902560197, 106632582345,\n            172535142543, 279167724889, 451702867433, 730870592323,\n            1182573459757, 1913444052081, 3096017511839, 5009461563921,\n            8105479075761, 13114940639683, 21220419715445, 34335360355129,\n            55555780070575, 89891140425705, 145446920496281, 235338060921987,\n            380784981418269, 616123042340257, 996908023758527,\n            1613031066098785, 2609939089857313, 4222970155956099,\n            6832909245813413, 11055879401769513, 17888788647582927,\n            28944668049352441, 46833456696935369, 75778124746287811,\n            122611581443223181, 198389706189510993, 321001287632734175,\n            519390993822245169, 840392281454979345, 1359783275277224515,\n            2200175556732203861, 3559958832009428377, 5760134388741632239\n        };\n\n        private static int TimSortMinRunLength(int n)\n        {\n            // assert n >= 0;\n            int r = 0;      // Becomes 1 if any 1 bits are shifted off\n            while (n >= c_minMerge)\n            {\n                r |= (n & 1);\n                n >>= 1;\n            }\n            return n + r;\n        }\n\n        private static long TimSortMinRunLength(long n)\n        {\n            // assert n >= 0;\n            long r = 0;      // Becomes 1 if any 1 bits are shifted off\n            while (n >= c_minMerge)\n            {\n                r |= (n & 1);\n                n >>= 1;\n            }\n            return n + r;\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Sorting/Sorting_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\n\nnamespace Aardvark.Base.Sorting\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    public static class SortingExtensions\n    {\n        #region Constants\n\n        /// Use insertion sort if count smaller than this (quicksort, quickmedian).\n        private const int c_insertionSortThreshold = 31;\n        private const int c_insertionMedianThreshold = 7;\n\n        private const int c_minMerge = 32;\n        private const int c_minGallop = 7;\n        private const int c_initialTmpStorageLength = 256;\n\n        #endregion\n        /*CLASS#\n\n        public struct Opt\n        {\n            public bool Generic;\n            public bool Get;\n            public bool Fun;\n            public bool Perm;\n            public bool Sel;\n        }\n\n        public static string OpFilter(string s)\n        {\n            if (s == \" < \") return \" > \";\n            if (s == \" > \") return \" < \";\n            if (s == \" <= \") return \" >= \";\n            if (s == \" >= \") return \" <= \";\n            return s;\n        }\n        \n        public static void Cmp(\n                Opt opt, Action<string> pr, bool asc,\n                string c, Action<int> a, Action<int> o, Action<int> b)\n        {\n            if (!asc) Filter = OpFilter;\n            if (opt.Generic && !opt.Sel) { if (opt.Fun) { pr(c); pr(\"(\"); } }\n            if (opt.Sel) pr(\"selector(\");\n            if (opt.Perm) {  if (opt.Get) pr(\"aget(a,\"); else pr(\"a[\"); }\n            a(0);\n            if (opt.Perm) { if (opt.Get) pr(\")\"); else  pr(\"]\"); }\n            if (opt.Sel) pr(\")\");\n            if (opt.Generic && !opt.Sel) { if (opt.Fun) pr(\", \"); else { pr(\".\"); pr(c); pr(\"(\"); } } else  o(0);          \n            if (opt.Sel) pr(\"selector(\");\n            if (opt.Perm) {  if (opt.Get) pr(\"aget(a,\"); else pr(\"a[\"); }\n            b(0);\n            if (opt.Perm) { if (opt.Get) pr(\")\"); else  pr(\"]\"); }\n            if (opt.Sel) pr(\")\");\n            if (opt.Generic && !opt.Sel) { pr(\")\"); o(0); pr(\"0\"); }\n            if (!asc) Filter = null;\n        }\n        */\n        //# string add = \" + \", sub = \" - \", inc = \"++\", dec = \"--\";\n        //# string add1 = \" + 1\", add2 = \" + 2\", sub1 = \" - 1\";\n        //# var mathtypes = Meta.SignedVecFieldTypes.Select(t => t.Name);\n        //# var generictypes = new [] { \"T[]\", \"List<T>\", \"TArray\" };\n        //# foreach (var isGeneric in new[] { false, true }) {\n        //#     var types = isGeneric ? generictypes : mathtypes;\n        //# foreach (var isNonGenericList in new[] { false, true }) { if (isGeneric && isNonGenericList) continue;\n        //# foreach (var type in types) {\n        //#     var etype = isGeneric ? \"T\" : type;\n        //#     var atype = isGeneric ? type : (isNonGenericList ? \"List<\" + type + \">\" : type + \"[]\");\n        //#     var hasGet = atype == \"TArray\";\n        //#     var isArray = atype.EndsWith(\"[]\");\n        //#     var isList = atype.EndsWith(\">\");\n        //# foreach (var isPerm in new[] { false, true }) {\n        //#     var permStr = isPerm ? \"Perm\" : \"\";\n        //#     var p = isPerm ? \"p[\" : (hasGet ? \"aget(a, \" : \"a[\");\n        //#     var pt = isPerm ? \"t[\" : (hasGet ? \"aget(t, \" : \"t[\");\n        //#     var q = isPerm ? \"]\" : (hasGet ? \")\" : \"]\");\n        //#     var P = isPerm ? \"p[\" : (hasGet ? \"aset(a, \" : \"a[\");\n        //#     var I = isPerm ? \"] = \" : (hasGet ? \", \" : \"] = \");\n        //#     var Q = isPerm ? \"\" : (hasGet ? \")\" : \"\");\n        //#     var pa = isPerm ? \"p\" : \"a\";\n        //#     var ta = isPerm ? \"a\" : \"t\";\n        //#     var hasSet = hasGet && !isPerm;\n        //#     var copy = (isList || hasGet) && !isPerm ? \"CopyElements\" : \"Array.Copy\";\n        //#     var agetset = hasSet ? \"aget, aset, \" : \"\";\n        //#     var permName = isPerm ? \"Permutation\" : \"\";\n        //#     var permNameSpace = isPerm ? \"Permutation \" : \"\";\n        #region __permNameSpace__Sort/Median for __atype__\n\n        //# foreach (var hasFun in new[] { true, false }) { if (hasFun && !isGeneric) continue;\n        //#     var isComparable = isGeneric && !hasFun;\n        //# foreach (var hasSel in new[] { false, true }) {\n        //#     if (hasSel && hasFun) continue;\n        //#     if (hasSel && !isGeneric) continue;\n        //#     if (hasSel) isComparable = false;\n        //# foreach (var ctype in mathtypes) { if (ctype != \"int\" && !hasSel) continue;\n        //#     var ctypecap = ctype.Capitalized();\n        //# foreach (var isAsc in new[] { true, false }) { if (hasFun && !isAsc) continue;\n        //# foreach (var itype in new[] { \"int\", \"long\" }) { if (isList && itype == \"long\") continue;\n        //#     if (!isList && !isPerm && itype == \"int\") continue;\n        //#     var itypecast = isList ? \"(\" + itype + \")\" : \"\";\n        //#     var stype = isPerm ? itype : etype; // sort type\n        //#     var tatype = hasSet ? \"TArray\" : stype + \"[]\"; // temp array type\n        //#     var pdef = isPerm ? \"-1\" : \"default(\"+stype+\")\";\n        //#     var isLong = itype == \"long\";\n        //#     var makeCreator = isPerm && (isArray || (isList && !isLong));\n        //#     var longStr = isLong ? \"Long\" : \"\";\n        //#     var agetcmp = (hasGet ? \"aget, \" : \"\") + (hasFun ? \"cmp, \" : \"\") + (hasSel ? \"selector, \" : \"\");\n        //#     var alen = isPerm ? \"p.\" + longStr + \"Length\" :\n        //#                 (hasGet ? \"count\" : (isList ? \"a.Count\" : \"a.\" + longStr + \"Length\"));\n        //#     var getLength = isArray ? longStr + \"Length\" : (isList ? \"Count\" : \"\");\n        //#     var opt = new Opt { Generic = isGeneric, Get = hasGet, Fun = hasFun, Perm = isPerm, Sel = hasSel };\n        //#     var ext = (isGeneric && hasFun) ? \"\" : (isAsc ? \"Ascending\" : \"Descending\");\n        //#     var rext = (isGeneric && hasFun) ? \"\" : (isAsc ? \"Descending\" : \"Ascending\");\n        //#     var uid = (isGeneric ? \"\" : type.Capitalized()) +  (isList ? \"List\" : \"\") + permStr + longStr\n        //#                 +  (hasFun ? \"Cmp\" : isAsc ? \"Asc\" : \"Desc\");\n        //#     var c = hasFun ? \"cmp\" : \"CompareTo\";\n        //#     Action<Action<int>,Action<int>,Action<int>> cmp = (a,o,b) => Cmp(opt, Out, isAsc, c, a, o, b);\n        //# foreach (var algo in new[] { \"Median\", \"Sort\" }) {\n        //#     var isSort = algo == \"Sort\"; var isMedian = algo == \"Median\";\n        //#     var qname = \"Quick\" + algo;\n        //#     var qcall = permName + qname + ext;\n        //# if (makeCreator) {\n        /// <summary>\n        //# if (isSort) {\n        /// The CreatePermutationQuickSort algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in sorted a manner.\n        //# } else {\n        /// The CreatePermutationQuickMedian algorithm returns an array of\n        /// element indices p that reference the elements in the data array\n        /// in a partially sorted manner, such that p[med] is placed at the\n        /// correct position, and correctly partitions the array into larger\n        /// and smaller elements.\n        //# }\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static __itype__[] Create__qcall____longStr__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this __atype__ a/*# if (hasGet) { */, Func<TArray, long, T> aget/*# }\n                if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } if (isMedian) { */, __itype__ med/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ len = a.__getLength__;\n            var p = new __itype__[len].SetByIndex__longStr__(i => i);\n            __qcall__(p, a, /*# if (hasGet) { */aget, /*# } if (hasFun) { */cmp, /*#\n                        } if (hasSel) { */selector, /*# } */0, len - 1, len - 1/*# if (isMedian) { */, med/*# } */);\n            return p;\n        }\n\n        //# }\n        /// <summary>\n        //# if (isSort) {\n        //# if (isPerm) {\n        /// The PermutationQuickSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        //# } else {\n        /// The QuickSort algorithm sorts the data array.\n        //# }\n        //# } else {\n        //# if (isPerm) {\n        /// The PermutationQuickMedian algorithm partially sorts the array of\n        /// element indices p that reference the elements in the data array\n        /// in such a way that p[med] is placed at the correct position.\n        //# } else {\n        /// The QuickMedian algorithm partially sorts the data array in such\n        /// a way that the element at position med is correctly placed, and\n        /// correctly partitions the array into larger and smaller elements.\n        //# }\n        //# }\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static void __qcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a/*# if (hasGet) { */, /*# if (!isPerm) { */__itype__ count, /*# } */Func<TArray, long, T> aget/*# if (!isPerm) { */, Action<TArray, long, T> aset/*# } }\n                if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } if (isMedian) { */, __itype__ med/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ last = __alen__ - 1;\n            __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*#\n                        } if (hasSel) { */selector, /*# } */0, last, last/*# if (isMedian) { */, med/*# } */);\n        }\n\n        /// <summary>\n        //# if (isSort) {\n        //# if (isPerm) {\n        /// The PermutationQuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of element indices p that reference the\n        /// elements in the data array.\n        //# } else {\n        /// The QuickSort algorithm sorts the range [beginIncl,\n        /// endExcl) of the array of elements in the data array.\n        //# }\n        //# } else {\n        //# if (isPerm) {\n        /// The PermutationQuickMedian algorithm partially sorts the range\n        /// [beginIncl, endExcl) of the array of element indices p\n        /// that reference the elements in the data array in such a way that\n        /// p[med] is placed at the correct position, and correctly partitions\n        /// this array range into larger and smaller elements.\n        //# } else {\n        /// The QuickMedian algorithm partially sorts the range [beginIncl,\n        /// endExcl) of the data array in such a way that the element at\n        /// position med is correctly placed, and correctly partitions this\n        /// array range into larger and smaller elements.\n        //# }\n        //# }\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static void __qcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __itype__ beginIncl, __itype__ endExcl/*# if (isMedian) { */, __itype__ med/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */beginIncl, endExcl - 1, endExcl - beginIncl - 1/*# if (isMedian) { */, med/*# } */);\n        }\n\n        /*\n            This implementation of __qname__ is based on the paper\n            \"Dual-Pivot Quicksort\" by Vladimir Yaroslavskiy <iaroslavski@mail.ru>.\n        */\n        private static void __qcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __itype__ l, __itype__ r, __itype__ countSub1/*# if (isMedian) { */, __itype__ med/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            while (countSub1 >= c_insertion__algo__Threshold)\n            {\n                __itype__ sixth = (1 + countSub1) / 6;\n                __itype__ e1 = l + sixth;\n                __itype__ e5 = r - sixth;\n                __itype__ e3 = (l + r) >> 1;\n                __itype__ e4 = e3 + sixth;\n                __itype__ e2 = e3 - sixth;\n\n                if (/*#cmp(a=>{*/__p__e1__q__/*#},o=>{*/ > /*#},b=>{*/__p__e2__q__/*#});*/) { var t = __p__e1__q__; __P__e1__I____p__e2__q____Q__; __P__e2__I__t__Q__; }\n                if (/*#cmp(a=>{*/__p__e4__q__/*#},o=>{*/ > /*#},b=>{*/__p__e5__q__/*#});*/) { var t = __p__e4__q__; __P__e4__I____p__e5__q____Q__; __P__e5__I__t__Q__; }\n                if (/*#cmp(a=>{*/__p__e1__q__/*#},o=>{*/ > /*#},b=>{*/__p__e3__q__/*#});*/) { var t = __p__e1__q__; __P__e1__I____p__e3__q____Q__; __P__e3__I__t__Q__; }\n                if (/*#cmp(a=>{*/__p__e2__q__/*#},o=>{*/ > /*#},b=>{*/__p__e3__q__/*#});*/) { var t = __p__e2__q__; __P__e2__I____p__e3__q____Q__; __P__e3__I__t__Q__; }\n                if (/*#cmp(a=>{*/__p__e1__q__/*#},o=>{*/ > /*#},b=>{*/__p__e4__q__/*#});*/) { var t = __p__e1__q__; __P__e1__I____p__e4__q____Q__; __P__e4__I__t__Q__; }\n                if (/*#cmp(a=>{*/__p__e3__q__/*#},o=>{*/ > /*#},b=>{*/__p__e4__q__/*#});*/) { var t = __p__e3__q__; __P__e3__I____p__e4__q____Q__; __P__e4__I__t__Q__; }\n                if (/*#cmp(a=>{*/__p__e2__q__/*#},o=>{*/ > /*#},b=>{*/__p__e5__q__/*#});*/) { var t = __p__e2__q__; __P__e2__I____p__e5__q____Q__; __P__e5__I__t__Q__; }\n                if (/*#cmp(a=>{*/__p__e2__q__/*#},o=>{*/ > /*#},b=>{*/__p__e3__q__/*#});*/) { var t = __p__e2__q__; __P__e2__I____p__e3__q____Q__; __P__e3__I__t__Q__; }\n                if (/*#cmp(a=>{*/__p__e4__q__/*#},o=>{*/ > /*#},b=>{*/__p__e5__q__/*#});*/) { var t = __p__e4__q__; __P__e4__I____p__e5__q____Q__; __P__e5__I__t__Q__; }\n\n                var p1 = __p__e2__q__; __P__e2__I____p__l__q____Q__;\n                var p2 = __p__e4__q__; __P__e4__I____p__r__q____Q__;\n\n                __itype__ lo = l + 1;\n                __itype__ hi = r - 1;\n\n                bool pivotsDiffer = /*#cmp(a=>{*/p1/*#},o=>{*/ != /*#},b=>{*/p2/*#});*/;\n\n                if (pivotsDiffer)\n                {\n                    for (__itype__ i = lo; i <= hi; i++)\n                    {\n                        var ai = __p__i__q__;\n                        if (/*#cmp(a=>{*/ai/*#},o=>{*/ < /*#},b=>{*/p1/*#});*/) { __P__i__I____p__lo__q____Q__; __P__lo__I__ai__Q__; ++lo; }\n                        else if (/*#cmp(a=>{*/ai/*#},o=>{*/ > /*#},b=>{*/p2/*#});*/)\n                        {\n                            while (/*#cmp(a=>{*/__p__hi__q__/*#},o=>{*/ > /*#},b=>{*/p2/*#});*/ && i < hi)\n                                --hi;\n                            __P__i__I____p__hi__q____Q__; __P__hi__I__ai__Q__; --hi; ai = __p__i__q__;\n                            if (/*#cmp(a=>{*/ai/*#},o=>{*/ < /*#},b=>{*/p1/*#});*/) { __P__i__I____p__lo__q____Q__; __P__lo__I__ai__Q__; ++lo; }\n                        }\n                    }\n                }\n                else\n                {\n                    for (__itype__ i = lo; i <= hi; i++)\n                    {\n                        var ai = __p__i__q__;\n                        if (/*#cmp(a=>{*/ai/*#},o=>{*/ == /*#},b=>{*/p1/*#});*/) continue;\n                        if (/*#cmp(a=>{*/ai/*#},o=>{*/ < /*#},b=>{*/p1/*#});*/) { __P__i__I____p__lo__q____Q__; __P__lo__I__ai__Q__; ++lo; }\n                        else\n                        {\n                            while (/*#cmp(a=>{*/__p__hi__q__/*#},o=>{*/ > /*#},b=>{*/p1/*#});*/)\n                                --hi;\n                            __P__i__I____p__hi__q____Q__; __P__hi__I__ai__Q__; --hi; ai = __p__i__q__;\n                            if (/*#cmp(a=>{*/ai/*#},o=>{*/ < /*#},b=>{*/p1/*#});*/) { __P__i__I____p__lo__q____Q__; __P__lo__I__ai__Q__; ++lo; }\n                        }\n                    }\n                }\n\n                __P__l__I____p__lo__sub__1__q____Q__; __P__lo__sub__1__I__p1__Q__;\n                __P__r__I____p__hi__add__1__q____Q__; __P__hi__add__1__I__p2__Q__;\n\n                __itype__ cl = lo - 2 - l;\n                __itype__ cr = r - hi - 2;\n\n                if (pivotsDiffer)\n                {\n                    if (lo < e1 && e5 < hi)\n                    {\n                        //# if (isSort) {\n                        __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */l, lo - 2, cl);\n                        __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */hi + 2, r, cr);\n                        //# } // isSort\n                        //# if (isMedian) {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else\n                        //# } // isMedian\n                        {\n                            while (/*#cmp(a=>{*/__p__lo__q__/*#},o=>{*/ == /*#},b=>{*/p1/*#});*/)\n                                ++lo;\n                            for (__itype__ i = lo + 1; i <= hi; i++)\n                            {\n                                if (/*#cmp(a=>{*/__p__i__q__/*#},o=>{*/ == /*#},b=>{*/p1/*#});*/) { /*# if (isGeneric || isPerm) { */p1 = __p__i__q__; /*# } */__P__i__I____p__lo__q____Q__; __P__lo__I__p1__Q__; ++lo; }\n                            }\n                            while (/*#cmp(a=>{*/__p__hi__q__/*#},o=>{*/ == /*#},b=>{*/p2/*#});*/)\n                                --hi;\n                            for (__itype__ i = hi - 1; i >= lo; i--)\n                            {\n                                if (/*#cmp(a=>{*/__p__i__q__/*#},o=>{*/ == /*#},b=>{*/p2/*#});*/) { /*# if (isGeneric || isPerm) { */p2 = __p__i__q__; /*# } */__P__i__I____p__hi__q____Q__; __P__hi__I__p2__Q__; --hi; }\n                            }\n                            //# if (isMedian) {\n                            if (med < lo || med > hi) return;\n                            //# } // isMedian\n                            l = lo; r = hi; countSub1 = hi - lo;\n                        }\n                    }\n                    else\n                    {\n                        //# if (isSort) {\n                        __itype__ cm = hi - lo;\n                        if (cl > cr)\n                        {\n                            if (cl > cm)\n                            {\n                                __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */lo, hi, cm);\n                                __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */hi + 2, r, cr);\n                                r = lo - 2; countSub1 = cl;\n                            }\n                            else\n                            {\n                                __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */l, lo - 2, cl);\n                                __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        else\n                        {\n                            if (cr > cm)\n                            {\n                                __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */l, lo - 2, cl);\n                                __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */lo, hi, cm);\n                                l = hi + 2; countSub1 = cr;\n                            }\n                            else\n                            {\n                                __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */l, lo - 2, cl);\n                                __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */hi + 2, r, cr);\n                                l = lo; r = hi; countSub1 = cm;\n                            }\n                        }\n                        //# } // isSort\n                        //# if (isMedian) {\n                        if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                        else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                        else if (med >= lo && med <= hi) { l = lo; r = hi; countSub1 = hi - lo; }\n                        else return;\n                        //# } // isMedian\n                    }\n                }\n                else\n                {\n                    //# if (isSort) {\n                    if (cl > cr)\n                    {\n                        __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */hi + 2, r, cr);\n                        r = lo - 2; countSub1 = cl;\n                    }\n                    else\n                    {\n                        __qcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */l, lo - 2, cl);\n                        l = hi + 2; countSub1 = cr;\n                    }\n                    //# } // isSort\n                    //# if (isMedian) {\n                    if (med <= lo - 2) { r = lo - 2; countSub1 = cl; }\n                    else if (med >= hi + 2) { l = hi + 2; countSub1 = cr; }\n                    else return;\n                    //# } // isMedian\n                }\n            }\n\n            for (__itype__ i = l + 1; i <= r; i++)\n            {\n                var ai = __p__i__q__; __itype__ j;\n                for (j = i - 1; j >= l && /*#cmp(a=>{*/ai/*#},o=>{*/ < /*#},b=>{*/__p__j__q__/*#});*/; j--)\n                    __P__j__add__1__I____p__j__q____Q__;\n                __P__j__add__1__I__ai__Q__;\n            }\n        }\n\n        //# } // algo\n        //# var hcall = permName + \"HeapSort\" + ext;\n        //# if (makeCreator) {\n        /// <summary>\n        /// The PermutationHeapSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// It is slower than the PermutationQuickSort algorithm, but\n        /// is not affected by the data distribution in any way, even if\n        /// there are a huge number of equal data elements.\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static __itype__[] Create__hcall____longStr__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this __atype__ a/*# if (hasGet) { */, Func<TArray, long, T> aget/*# }\n                if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ len = a.__getLength__;\n            var p = new __itype__[len].SetByIndex__longStr__(i => i);\n            __hcall__(p, a/*# if (hasGet) { */, aget/*# } if (hasFun) { */, cmp/*# } if (hasSel) { */, selector/*# } */);\n            return p;\n        }\n\n        //# }\n        //# foreach (var range in new[] { true, false }) { var r = range ? \" + begin\" : \"\";\n        /// <summary>\n        //# if (isPerm) {\n        /// The PermutationHeapSort algorithm sorts the array of element\n        /// indices p that reference the elements in the data array.\n        //# } else {\n        /// The HeapSort algorithm sorts the data array.\n        //# }\n        /// It is slower than the __permName__QuickSort algorithm,\n        /// but is not affected by the data distribution in any\n        /// way, even if there are a huge number of equal data elements.\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static void __hcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a/*# if (hasGet) { */, /*# if (!isPerm && !range) { */__itype__ count, /*# } */Func<TArray, long, T> aget/*# if (!isPerm) { */, Action<TArray, long, T> aset/*# } }\n                if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } if (range) { */, __itype__ begin, __itype__ end/*# }*/)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            //# if (alen != \"count\" && !range) {\n            __itype__ count = __alen__;\n            //# }\n            //# if (range) {\n            __itype__ count = end - begin;\n            //# }\n            for (__itype__ c = 1; c < count; c++)\n            {\n                var element = __p__c__r____q__;\n                __itype__ i = c;\n                while (i > 0)\n                {\n                    __itype__ i2 = (i - 1) / 2;\n                    if (/*#cmp(a=>{*/element/*#},o=>{*/ < /*#},b=>{*/__p__i2__r____q__/*#});*/)\n                        break;\n                    __P__i__r____I____p__i2__r____q____Q__;\n                    i = i2;\n                }\n                __P__i__r____I__element__Q__;\n            }\n            while (count > 1)\n            {\n                --count;\n                var element = __p__count__r____q__;\n                __P__count__r____I____p__0__r____q____Q__;\n                __itype__ i = 0, i1 = 1;\n                while (i1 < count) // at least one child\n                {\n                    __itype__ i2 = i1 + 1;\n                    __itype__ ni = (i2 < count // two children?\n                              && /*#cmp(a=>{*/__p__i1__r____q__/*#},o=>{*/ < /*#},b=>{*/__p__i2__r____q__/*#});*/)\n                                 ? i2 : i1; // smaller child\n                    if (/*#cmp(a=>{*/__p__ni__r____q__/*#},o=>{*/ < /*#},b=>{*/element/*#});*/)\n                        break;\n                    __P__i__r____I____p__ni__r____q____Q__;\n                    i = ni; i1 = 2 * i + 1;\n                }\n                __P__i__r____I__element__Q__;\n            }\n        }\n\n        //# } // range\n        //# var scall = permName + \"SmoothSort\" + ext;\n        //# if (makeCreator) {\n        /// <summary>\n        /// The PermutationSmoothSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static __itype__[] Create__scall____longStr__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this __atype__ a/*# if (hasGet) { */, Func<TArray, long, T> aget/*# }\n                if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n        //# }\n        {\n            __itype__ len = a.__getLength__;\n            var p = new __itype__[len].SetByIndex__longStr__(i => i);\n            __scall__(p, a/*# if (hasGet) { */, aget/*# } if (hasFun) { */, cmp/*# } if (hasSel) { */, selector/*# } */);\n            return p;\n        }\n\n        //# }\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static void __scall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a/*# if (hasGet) { */, /*# if (!isPerm) { */__itype__ count, /*# } */Func<TArray, long, T> aget/*# if (!isPerm) { */, Action<TArray, long, T> aset/*# } }\n                if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n        //# }\n        {\n            __scall__InclusiveRange(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */0, __alen__ - 1);\n        }\n\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static void __scall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __itype__ beginIncl, __itype__ endExcl)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __scall__InclusiveRange(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */beginIncl, endExcl - 1);\n        }\n\n        private static void __scall__InclusiveRange/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __itype__ lo, __itype__ hi)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ head = lo;\n            long pbits = 1;\n            int pshift = 1;\n            while (head < hi)\n            {\n                if ((pbits & 3) == 3)\n                {\n                    __scall__Sift(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */pshift, head);\n                    pbits >>= 2; pshift += 2;\n                }\n                else\n                {\n                    if (LP__longStr__[pshift - 1] >= hi - head)\n                        __scall__Trinkle(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */pbits, pshift, head, false);\n                    else\n                        __scall__Sift(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */pshift, head);\n                    if (pshift == 1)\n                    {\n                        pbits <<= 1; pshift--;\n                    }\n                    else\n                    {\n                        pbits <<= (pshift - 1); pshift = 1;\n                    }\n                }\n                pbits |= 1;\n                head++;\n            }\n\n            __scall__Trinkle(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */pbits, pshift, head, false);\n\n            while (pshift != 1 || pbits != 1)\n            {\n                if (pshift <= 1)\n                {\n                    int trail = TrailingZeroBitCount(pbits & ~1);\n                    pbits >>= trail; pshift += trail;\n                }\n                else\n                {\n                    pbits <<= 2; pbits ^= 7; pshift -= 2;\n                    __scall__Trinkle(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */pbits >> 1, pshift + 1, head - LP__longStr__[pshift] - 1, true);\n                    __scall__Trinkle(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */pbits, pshift, head - 1, true);\n                }\n                head--;\n            }\n        }\n\n        private static void __scall__Sift/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                int pshift, __itype__ head)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            var val = __p__head__q__;\n            while (pshift > 1)\n            {\n                __itype__ rt = head - 1;\n                __itype__ lf = head - 1 - LP__longStr__[pshift - 2];\n                if (/*#cmp(a=>{*/val/*#},o=>{*/ >= /*#},b=>{*/__p__lf__q__/*#});*/ && /*#cmp(a=>{*/val/*#},o=>{*/ >= /*#},b=>{*/__p__rt__q__/*#});*/) break;\n                if (/*#cmp(a=>{*/__p__lf__q__/*#},o=>{*/ >= /*#},b=>{*/__p__rt__q__/*#});*/)\n                {\n                    __P__head__I____p__lf__q____Q__;\n                    head = lf;\n                    pshift -= 1;\n                }\n                else\n                {\n                    __P__head__I____p__rt__q____Q__;\n                    head = rt;\n                    pshift -= 2;\n                }\n            }\n            __P__head__I__val__Q__;\n        }\n\n        private static void __scall__Trinkle/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                long pbits, int pshift, __itype__ head, bool isTrusty)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            var val = __p__head__q__;\n\n            while (pbits != 1)\n            {\n                __itype__ stepson = head - LP__longStr__[pshift];\n                var vstepson = __p__stepson__q__;\n                if (/*#cmp(a=>{*/vstepson/*#},o=>{*/ <= /*#},b=>{*/val/*#});*/) break;\n                if (!isTrusty && pshift > 1)\n                {\n                    __itype__ rt = head - 1;\n                    __itype__ lf = head - 1 - LP__longStr__[pshift - 2];\n                    if (/*#cmp(a=>{*/__p__rt__q__/*#},o=>{*/ >= /*#},b=>{*/vstepson/*#});*/ || /*#cmp(a=>{*/__p__lf__q__/*#},o=>{*/ >= /*#},b=>{*/vstepson/*#});*/)\n                        break;\n                }\n                __P__head__I__vstepson__Q__;\n                head = stepson;\n                int trail = TrailingZeroBitCount(pbits & ~1);\n                pbits >>= trail;\n                pshift += trail;\n                isTrusty = false;\n            }\n            if (!isTrusty)\n            {\n                __P__head__I__val__Q__;\n                __scall__Sift(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */pshift, head);\n            }\n        }\n\n        //# var tsi = \"TimSortInfo\" + (isList ? \"List\" : \"\") + permStr + longStr\n        //#            + (hasGet ? \"Get\" : \"\") + (hasFun ? \"Cmp\" : \"\") + (hasSel ? ctypecap + \"Sel\" : \"\");\n        //# var mb = \"m_\";\n        //# if (isGeneric && (hasFun || isAsc)) {\n        public class __tsi__</*# if (hasGet) { */TArray, /*# } */T>\n            //# if (!hasFun && !hasSel) {\n            where T : IComparable<T>\n            //# }\n        {\n            //# if (isPerm) {\n            public __itype__[] m_p;\n            //# }\n            public __atype__ m_a;\n            //# if (hasGet) {\n            public __itype__ m_count;\n            public Func<TArray, long, T> m_aget;\n            //# if (!isPerm) {\n            public Action<TArray, long, T> m_aset;\n            public Func<long, TArray> m_amake;\n            //# }\n            //# }\n            //# if (hasFun) {\n            public Func<T, T, int> m_cmp;\n            //# }\n            //# if (hasSel) {\n            public Func<T, __ctype__> m_sel;\n            //# }\n            public __itype__ m_minGallop = c_minGallop;\n            //# if (hasSet) {\n            public TArray m_tmp;\n            public long m_len;\n            //# } else {\n            public __stype__[] m_tmp;\n            //# }\n            public int m_stackSize = 0;\n            public __itype__[] m_runStart;\n            public __itype__[] m_runLen;\n\n            public __tsi__(/*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a/*# if (hasGet) { */, Func<TArray, long, T> aget/*# if (!isPerm) { */, Action<TArray, long, T> aset, Func<long, TArray> amake/*# } }\n                            if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } if (hasGet) { */, __itype__ count/*# } */)\n            {\n                /*# if (isPerm) { */m_p = p; /*# } */m_a = a;/*# if (hasGet) { */ m_count = count;/*# } */\n                /*# if (hasGet) { */m_aget = aget; /*# if (!isPerm) { */m_aset = aset; m_amake = amake; /*# } } if (hasFun) { */m_cmp = cmp;/*# } if (hasSel) { */m_sel = selector;/*# } */\n                //# if (!hasGet) {\n                __itype__ count = __alen__;\n                //# }\n                //# if (hasSet) {\n                m_len = count < 2 * c_initialTmpStorageLength\n                        ? count >> 1 : c_initialTmpStorageLength;\n                m_tmp = amake(m_len);\n                //# } else {\n                m_tmp = new __stype__[count < 2 * c_initialTmpStorageLength\n                                    ? count >> 1 : c_initialTmpStorageLength];\n                //# }\n                int stackLen = (count < 120 ? 5 :\n                                count < 1542 ? 10 :\n                                count < 119151 ? 19 : 40);\n                m_runStart = new __itype__[stackLen];\n                m_runLen = new __itype__[stackLen];\n            }\n\n            public void PushRun(__itype__ runStart, __itype__ runLen)\n            {\n                m_runStart[m_stackSize] = runStart;\n                m_runLen[m_stackSize] = runLen;\n                m_stackSize++;\n            }\n\n            public __tatype__ EnsureCapacity(__itype__ cap)\n            {\n                //# var tlen = hasSet ? \"m_len\" : \"m_tmp.\" + longStr + \"Length\";\n                if (__tlen__ < cap)\n                {\n                    __itype__ c = cap;\n                    c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8;\n                    c |= c >> 16;/*# if (isLong) { */ c |= c >> 32;/*# } */ c++;\n                    //# if (hasSet) {\n                    m_len = c < 0 ? cap : Math.Min(c, __mb____alen__ >> 1);\n                    m_tmp = m_amake(m_len);\n                    //# } else {\n                    m_tmp = new __stype__[c < 0 ? cap : Math.Min(c, __mb____alen__ >> 1)];\n                    //# }\n                }\n                return m_tmp;\n            }\n\n        }\n\n        //# } // isGeneric && (hasFun || isAsc)\n        //# var tcall = permName + \"TimSort\" + ext;\n        //# var glcall = permName + \"GallopLeft\" + ext;\n        //# var grcall = permName + \"GallopRight\" + ext;\n        //# var bcall = permName + \"BinarySort\" + ext;\n        //# var crcall = permName + \"CountRunAndOrder\" + ext;\n        //# if (makeCreator) {\n        /// <summary>\n        /// The PermutationTimSort algorithm returns an array of element\n        /// indices that enumerate the array elements in sorted fashion.\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static __itype__[] Create__tcall____longStr__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this __atype__ a/*# if (hasGet) { */, Func<TArray, long, T> aget/*# }\n                if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ len = a.__getLength__;\n            var p = new __itype__[len].SetByIndex__longStr__(i => i);\n            __tcall__(p, a/*# if (hasGet) { */, aget/*# } if (hasFun) { */, cmp/*# } if (hasSel) { */, selector/*# } */);\n            return p;\n        }\n\n        //# }\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static void __tcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a/*# if (hasGet) { */, /*# if (!isPerm) { */__itype__ count, /*# } */Func<TArray, long, T> aget/*# if (!isPerm) { */, Action<TArray, long, T> aset, Func<long, TArray> amake/*# } }\n                if (hasFun) { */, Func<T, T, int> cmp/*# } if (hasSel) { */, Func<T, __ctype__> selector/*# } */)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __tcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, amake, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */0, __alen__);\n        }\n\n        /// <summary>\n        /// The TimSort algorithm is not as fast as QuickSort for completely\n        /// randomized arrays, but is a bit faster for mostly sorted or\n        /// mostly reversed arrays. Additionally it is a stable algorithm.\n        /// </summary>\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static void __tcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset, Func<long, TArray> amake,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __itype__ lo, __itype__ hi)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            /*\n                An implementation of the TimSort Algorithm which was invented\n                by Tim Peters in 2002 for use in the Python programming language. \n            */\n            __itype__ count = hi - lo;\n            if (count < 2) return;\n            if (count < c_minMerge)\n            {\n                var initRunLen = __crcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */lo, hi);\n                __bcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */lo, hi, lo + initRunLen);\n                return;\n            }\n            var ti = new __tsi__</*# if (hasGet) { */TArray, /*# } */__etype__>(/*# if (isPerm) { */p, /*# } */a/*# if (hasGet) { */, aget/*# if (!isPerm) { */, aset, amake/*# } }\n                            if (hasFun) { */, cmp/*# } if (hasSel) { */, selector/*# } if (hasGet) { */, count/*# } */);\n            __itype__ minRun = TimSortMinRunLength(count);\n            do\n            {\n                __itype__ runLen = __crcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */lo, hi);\n                if (runLen < minRun)\n                {\n                    __itype__ force = count <= minRun ? count : minRun;\n                    __bcall__(/*# if (isPerm) { */p, /*# } */a, /*# if (hasGet) { */aget, /*# if (!isPerm) { */aset, /*# } } if (hasFun) { */cmp, /*# } if (hasSel) { */selector, /*# } */lo, lo + force, lo + runLen);\n                    runLen = force;\n                }\n                ti.PushRun(lo, runLen);\n                MergeCollapse__uid__(ti);\n                lo += runLen; count -= runLen;\n            }\n            while (count != 0);\n            MergeForceCollapse__uid__(ti);\n        }\n\n        private static void MergeCollapse__uid__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(this __tsi__</*# if (hasGet) { */TArray, /*# } */__etype__> ti)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] <= ti.m_runLen[n] + ti.m_runLen[n + 1])\n                {\n                    if (ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                        n--;\n                    MergeAt__uid__(ti, n);\n                }\n                else if (ti.m_runLen[n] <= ti.m_runLen[n + 1])\n                    MergeAt__uid__(ti, n);\n                else\n                    break;\n            }\n        }\n\n        private static void MergeForceCollapse__uid__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(this __tsi__</*# if (hasGet) { */TArray, /*# } */__etype__> ti)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            while (ti.m_stackSize > 1)\n            {\n                int n = ti.m_stackSize - 2;\n                if (n > 0 && ti.m_runLen[n - 1] < ti.m_runLen[n + 1])\n                    n--;\n                MergeAt__uid__(ti, n);\n            }\n        }\n\n        private static void MergeAt__uid__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(this __tsi__</*# if (hasGet) { */TArray, /*# } */__etype__> ti, int i)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ start1 = ti.m_runStart[i], len1 = ti.m_runLen[i];\n            __itype__ start2 = ti.m_runStart[i + 1], len2 = ti.m_runLen[i + 1];\n            ti.m_runLen[i] = len1 + len2;\n            if (i == ti.m_stackSize - 3)\n            {\n                ti.m_runStart[i + 1] = ti.m_runStart[i + 2];\n                ti.m_runLen[i + 1] = ti.m_runLen[i + 2];\n            }\n            ti.m_stackSize--;\n            var a = ti.m_a;\n            __itype__ k = __grcall__(/*# if (isPerm) { */ti.m_p, /*# } */a, /*# if (hasGet) { */ti.m_aget, /*# } if (hasFun) { */ti.m_cmp, /*# } if (hasSel) { */ti.m_sel, /*# } */ti.__mb____p__start2__q__, start1, len1, 0);\n            len1 -= k;\n            if (len1 == 0) return;\n            start1 += k;\n            len2 = __glcall__(/*# if (isPerm) { */ti.m_p, /*# } */a, /*# if (hasGet) { */ti.m_aget, /*# } if (hasFun) { */ti.m_cmp, /*# } if (hasSel) { */ti.m_sel, /*# } */ti.__mb____p__start1__add__len1__sub1____q__, start2, len2, len2 - 1);\n            if (len2 == 0) return;\n            if (len1 <= len2)\n                MergeLo__uid__(ti, start1, len1, start2, len2);\n            else\n                MergeHi__uid__(ti, start1, len1, start2, len2);\n        }\n\n        private static void MergeLo__uid__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(this __tsi__</*# if (hasGet) { */TArray, /*# } */__etype__> ti, __itype__ start1, __itype__ len1, __itype__ start2, __itype__ len2)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            //# if (isPerm) {\n            var p = ti.m_p;\n            //# }\n            var a = ti.m_a;\n            //# if (hasGet) {\n            var aget = ti.m_aget;\n            //# if (!isPerm) {\n            var aset = ti.m_aset;\n            //# } }\n            var t = ti.EnsureCapacity(len1);\n            __copy__(__agetset____pa__, start1, t, 0, len1);\n            __itype__ idx1 = 0, idx2 = start2;\n            __itype__ dest = start1;\n            __P__dest__inc____I____p__idx2__inc____q____Q__;\n            if (--len2 == 0)\n            {\n                __copy__(__agetset__t, idx1, __pa__, dest, len1);\n                return;\n            }\n            if (len1 == 1)\n            {\n                __copy__(__agetset____pa__, idx2, __pa__, dest, len2);\n                __P__dest__add__len2__I____pt__idx1__q____Q__;\n                return;\n            }\n            //# if (hasFun) {\n            Func<T, T, int> cmp = ti.m_cmp;\n            //# }\n            //# if (hasSel) {\n            Func<T, __ctype__> selector = ti.m_sel;\n            //# }\n            __itype__ minGallop = ti.m_minGallop;\n            while (true)\n            {\n                __itype__ count1 = 0, count2 = 0;\n                do\n                {\n                    if (/*#cmp(a=>{*/__p__idx2__q__/*#},o=>{*/ < /*#},b=>{*/__pt__idx1__q__/*#});*/)\n                    {\n                        __P__dest__inc____I____p__idx2__inc____q____Q__;\n                        count2++; count1 = 0;\n                        if (--len2 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        __P__dest__inc____I____pt__idx1__inc____q____Q__;\n                        count1++; count2 = 0;\n                        if (--len1 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = __itypecast____grcall__(/*# if (isPerm) { */t, /*# } */__ta__, __agetcmp____p__idx2__q__, idx1, len1, 0);\n                    if (count1 != 0)\n                    {\n                        __copy__(__agetset__t, idx1, __pa__, dest, count1);\n                        dest += count1; idx1 += count1; len1 -= count1;\n                        if (len1 <= 1) goto breakouter;\n                    }\n                    __P__dest__inc____I____p__idx2__inc____q____Q__;\n                    if (--len2 == 0) goto breakouter;\n                    count2 = __glcall__(/*# if (isPerm) { */p, /*# } */a, __agetcmp____pt__idx1__q__, idx2, len2, 0);\n                    if (count2 != 0)\n                    {\n                        __copy__(__agetset____pa__, idx2, __pa__, dest, count2);\n                        dest += count2; idx2 += count2; len2 -= count2;\n                        if (len2 == 0) goto breakouter;\n                    }\n                    __P__dest__inc____I____pt__idx1__inc____q____Q__;\n                    if (--len1 == 1) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;  // Penalize for leaving gallop mode\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len1 == 1)\n            {\n                __copy__(__agetset____pa__, idx2, __pa__, dest, len2);\n                __P__dest__add__len2__I____pt__idx1__q____Q__;\n            }\n            else if (len1 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                __copy__(__agetset__t, idx1, __pa__, dest, len1);\n        }\n\n        private static void MergeHi__uid__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(this __tsi__</*# if (hasGet) { */TArray, /*# } */__etype__> ti, __itype__ start1, __itype__ len1, __itype__ start2, __itype__ len2)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            //# if (isPerm) {\n            var p = ti.m_p;\n            //# }\n            var a = ti.m_a;\n            //# if (hasGet) {\n            var aget = ti.m_aget;\n            //# if (!isPerm) {\n            var aset = ti.m_aset;\n            //# } }\n            var t = ti.EnsureCapacity(len2);\n            __copy__(__agetset____pa__, start2, t, 0, len2);\n            __itype__ idx1 = start1 + len1 - 1, idx2 = len2 - 1;\n            __itype__ dest = start2 + len2 - 1;\n            __P__dest__dec____I____p__idx1__dec____q____Q__;\n            if (--len1 == 0)\n            {\n                __copy__(__agetset__t, 0, __pa__, dest - (len2 - 1), len2);\n                return;\n            }\n            if (len2 == 1)\n            {\n                idx1 -= len1; dest -= len1;\n                __copy__(__agetset____pa__, idx1 + 1, __pa__, dest + 1, len1);\n                __P__dest__I____pt__idx2__q____Q__;\n                return;\n            }\n            //# if (hasFun) {\n            Func<T, T, int> cmp = ti.m_cmp;\n            //# }\n            //# if (hasSel) {\n            Func<T, __ctype__> selector = ti.m_sel;\n            //# }\n            __itype__ minGallop = ti.m_minGallop;\n            while (true)\n            {\n                __itype__ count1 = 0, count2 = 0;\n                do\n                {\n                    if (/*#cmp(a=>{*/__pt__idx2__q__/*#},o=>{*/ < /*#},b=>{*/__p__idx1__q__/*#});*/)\n                    {\n                        __P__dest__dec____I____p__idx1__dec____q____Q__;\n                        count1++; count2 = 0;\n                        if (--len1 == 0) goto breakouter;\n                    }\n                    else\n                    {\n                        __P__dest__dec____I____pt__idx2__dec____q____Q__;\n                        count2++; count1 = 0;\n                        if (--len2 == 1) goto breakouter;\n                    }\n                }\n                while ((count1 | count2) < minGallop);\n                do\n                {\n                    count1 = len1 - __grcall__(/*# if (isPerm) { */p, /*# } */a, __agetcmp____pt__idx2__q__, start1, len1, len1 - 1);\n                    if (count1 != 0)\n                    {\n                        dest -= count1; idx1 -= count1; len1 -= count1;\n                        __copy__(__agetset____pa__, idx1 + 1, __pa__, dest + 1, count1);\n                        if (len1 == 0) goto breakouter;\n                    }\n                    __P__dest__dec____I____pt__idx2__dec____q____Q__;\n                    if (--len2 == 1) goto breakouter;\n                    count2 = len2 - __itypecast____glcall__(/*# if (isPerm) { */t, /*# } */__ta__, __agetcmp____p__idx1__q__, 0, len2, len2 - 1);\n                    if (count2 != 0)\n                    {\n                        dest -= count2; idx2 -= count2; len2 -= count2;\n                        __copy__(__agetset__t, idx2 + 1, __pa__, dest + 1, count2);\n                        if (len2 <= 1) goto breakouter;\n                    }\n                    __P__dest__dec____I____p__idx1__dec____q____Q__;\n                    if (--len1 == 0) goto breakouter;\n                    minGallop--;\n                }\n                while (count1 >= c_minGallop | count2 >= c_minGallop);\n                if (minGallop < 0) minGallop = 0;\n                minGallop += 2;\n            }\n            breakouter:\n            ti.m_minGallop = minGallop < 1 ? 1 : minGallop;\n            if (len2 == 1)\n            {\n                dest -= len1; idx1 -= len1;\n                __copy__(__agetset____pa__, idx1 + 1, __pa__, dest + 1, len1);\n                __P__dest__I____pt__idx2__q____Q__;\n            }\n            else if (len2 == 0)\n                throw new ArgumentException(\n                    \"Comparison method violates its general contract!\");\n            else\n                __copy__(__agetset__t, 0, __pa__, dest - (len2 - 1), len2);\n        }\n\n        private static __itype__ __glcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __stype__ key, __itype__ start, __itype__ len, __itype__ hint)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ lastOfs = 0, ofs = 1;\n            if (/*#cmp(a=>{*/key/*#},o=>{*/ > /*#},b=>{*/__p__start__add__hint__q__/*#});*/)\n            {\n                __itype__ maxOfs = len - hint;\n                while (ofs < maxOfs && /*#cmp(a=>{*/key/*#},o=>{*/ > /*#},b=>{*/__p__start__add__hint__add__ofs__q__/*#});*/)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            else\n            {\n                __itype__ maxOfs = hint + 1;\n                while (ofs < maxOfs && /*#cmp(a=>{*/key/*#},o=>{*/ <= /*#},b=>{*/__p__start__add__hint__sub__ofs__q__/*#});*/)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                __itype__ tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                __itype__ m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (/*#cmp(a=>{*/key/*#},o=>{*/ > /*#},b=>{*/__p__start__add__m__q__/*#});*/)\n                    lastOfs = m + 1;\n                else\n                    ofs = m;\n            }\n            return ofs;\n        }\n\n        private static __itype__ __grcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __stype__ key, __itype__ start, __itype__ len, __itype__ hint)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ ofs = 1, lastOfs = 0;\n            if (/*#cmp(a=>{*/key/*#},o=>{*/ < /*#},b=>{*/__p__start__add__hint__q__/*#});*/)\n            {\n                __itype__ maxOfs = hint + 1;\n                while (ofs < maxOfs && /*#cmp(a=>{*/key/*#},o=>{*/ < /*#},b=>{*/__p__start__add__hint__sub__ofs__q__/*#});*/)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                __itype__ tmp = lastOfs;\n                lastOfs = hint - ofs;\n                ofs = hint - tmp;\n            }\n            else\n            {\n                __itype__ maxOfs = len - hint;\n                while (ofs < maxOfs && /*#cmp(a=>{*/key/*#},o=>{*/ >= /*#},b=>{*/__p__start__add__hint__add__ofs__q__/*#});*/)\n                {\n                    lastOfs = ofs;\n                    ofs = (ofs << 1) + 1;\n                    if (ofs <= 0) ofs = maxOfs;\n                }\n                if (ofs > maxOfs) ofs = maxOfs;\n                lastOfs += hint;\n                ofs += hint;\n            }\n            lastOfs++;\n            while (lastOfs < ofs)\n            {\n                __itype__ m = lastOfs + ((ofs - lastOfs) >> 1);\n                if (/*#cmp(a=>{*/key/*#},o=>{*/ < /*#},b=>{*/__p__start__add__m__q__/*#});*/)\n                    ofs = m;\n                else\n                    lastOfs = m + 1;\n            }\n            return ofs;\n        }\n        \n        /// <summary>\n        /// Sorts the specified portion of the specified array using a binary\n        /// insertion sort. This is the best method for sorting small numbers\n        /// of elements.  It requires O(n log n) compares, but O(n^2) data\n        /// movements (worst case).\n        /// If the initial part of the specified range is already sorted,\n        /// this method can take advantage of it: the method assumes that the\n        /// elements in range [beginIncl, beginUnsorted) are already sorted.\n        /// </summary>\n        /// \n        private static void __bcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __itype__ beginIncl, __itype__ endExcl, __itype__ beginUnsorted)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            if (beginUnsorted == beginIncl)\n                beginUnsorted++;\n            for (; beginUnsorted < endExcl; beginUnsorted++)\n            {\n                var pivot = __p__beginUnsorted__q__;\n                __itype__ l = beginIncl, r = beginUnsorted;\n                while (l < r)\n                {\n                    __itype__ mid = (l + r) >> 1;\n                    if (/*#cmp(a=>{*/pivot/*#},o=>{*/ < /*#},b=>{*/__p__mid__q__/*#});*/)\n                        r = mid;\n                    else\n                        l = mid + 1;\n                }\n                __itype__ n = beginUnsorted - l;\n                switch (n)\n                {\n                    case 2: __P__l__add2____I____p__l__add1____q____Q__; __P__l__add1____I____p__l__q____Q__; break;\n                    case 1: __P__l__add1____I____p__l__q____Q__; break;\n                    default: __copy__(__agetset____pa__, l, __pa__, l + 1, n); break;\n                }\n                __P__l__I__pivot__Q__;\n            }\n        }\n\n        private static __itype__ __crcall__/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                this /*# if (isPerm) { */__itype__[] p, /*# } */__atype__ a,/*# if (hasGet) { */ Func<TArray, long, T> aget,/*# if (!isPerm) { */ Action<TArray, long, T> aset,/*# } } */\n                //# if (hasFun) {\n                Func<T, T, int> cmp,\n                //# }\n                //# if (hasSel) {\n                Func<T, __ctype__> selector,\n                //# }\n                __itype__ beginIncl, __itype__ endExcl)\n            //# if (isComparable) {\n            where T : IComparable<T>\n            //# }\n        {\n            __itype__ runHi = beginIncl + 1;\n            if (runHi == endExcl) return 1;\n            if (/*#cmp(a=>{*/__p__runHi__inc____q__/*#},o=>{*/ < /*#},b=>{*/__p__beginIncl__q__/*#});*/)\n            {\n                while (runHi < endExcl && /*#cmp(a=>{*/__p__runHi__q__/*#},o=>{*/ < /*#},b=>{*/__p__runHi__sub1____q__/*#});*/)\n                    runHi++;\n                ReverseRange(__agetset____pa__, beginIncl, runHi);\n            }\n            else\n            {\n                while (runHi < endExcl && /*#cmp(a=>{*/__p__runHi__q__/*#},o=>{*/ >= /*#},b=>{*/__p__runHi__sub1____q__/*#});*/)\n                    runHi++;\n            }\n            return runHi - beginIncl;\n        }\n\n        //# if (isGeneric && hasFun && !isPerm) {\n        //# if (hasGet) {\n        [EditorBrowsable(EditorBrowsableState.Never)]\n        //# }\n        public static void ReverseRange/*# if (isGeneric) { */</*# if (hasGet) { */TArray, /*# } */T>/*# } */(\n                /*# if (hasGet) { */ Func<TArray, long, T> aget, Action<TArray, long, T> aset,/*# } */__atype__ a,\n                __itype__ beginIncl, __itype__ endExcl)\n        {\n            endExcl--; // now incorrectly named\n            while (beginIncl < endExcl)\n            {\n                var t = __p__beginIncl__q__; __P__beginIncl__I____p__endExcl__q____Q__; __P__endExcl__I__t__Q__;\n                ++beginIncl; --endExcl;\n            }\n        }\n\n        //# } // isGeneric && hasFun && !isPerm\n        //# if (hasFun && isList && isGeneric && !isPerm) {\n        private static void CopyElements<T>(\n                List<T> src, int start, List<T> dst, int dstStart, int count)\n        {\n            for (var end = start + count; start < end; start++, dstStart++)\n                dst[dstStart] = src[start];\n        }\n\n        private static void CopyElements<T>(\n                List<T> src, int start, T[] dst, int dstStart, int count)\n        {\n            for (var end = start + count; start < end; start++, dstStart++)\n                dst[dstStart] = src[start];\n        }\n\n        private static void CopyElements<T>(\n                T[] src, int start, List<T> dst, int dstStart, int count)\n        {\n            for (var end = start + count; start < end; start++, dstStart++)\n                dst[dstStart] = src[start];\n        }\n\n        //# } // hasFun && isList && isGeneric && !isPerm\n        //# if (hasFun && hasGet && !isPerm) {\n        private static void CopyElements<TArray, T>(\n                Func<TArray, long, T> aget, Action<TArray, long, T> aset,\n                TArray src, long start, TArray dst, long dstStart, long count)\n        {\n            for (var end = start + count; start < end; start++, dstStart++)\n                aset(dst, dstStart, aget(src, start));\n        }\n\n        //# } // hasFun && hasGet && !isPerm\n        //# } // itype\n        //# } // isAsc\n        //# } // ctype\n        //# } // hasSel\n        //# } // hasFun\n        #endregion\n\n        //# } // isPerm\n        //# } // type\n        //# } // isNonGenericList\n        //# } // isGeneric\n        #region Auxiliary Functions, Structures, and Data\n\n        /// <summary>\n        /// Necessary for bit-field representation of smooth sort\n        /// Leonardo heaps. \n        /// </summary>\n        private static int TrailingZeroBitCount(this long x)\n        {\n            x &= -x;\n            int c = (x == 0) ? 1 : 0;\n            if ((x & 0x00000000ffffffffL) == 0) c += 32;\n            if ((x & 0x0000ffff0000ffffL) == 0) c += 16;\n            if ((x & 0x00ff00ff00ff00ffL) == 0) c += 8;\n            if ((x & 0x0f0f0f0f0f0f0f0fL) == 0) c += 4;\n            if ((x & 0x3333333333333333L) == 0) c += 2;\n            if ((x & 0x5555555555555555L) == 0) c += 1;\n            return c;\n        }\n\n        /// <summary>\n        /// Int Leonardo numbers (smooth sort).\n        /// </summary>\n        private static readonly int[] LP =\n        {\n            1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219,\n            1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735,\n            150049, 242785, 392835, 635621, 1028457, 1664079, 2692537,\n            4356617, 7049155, 11405773, 18454929, 29860703, 48315633,\n            78176337, 126491971, 204668309, 331160281, 535828591, 866988873,\n            1402817465\n        };\n\n        /// <summary>\n        /// Long Leonardo numbers (smooth sort).\n        /// </summary>\n        private static readonly long[] LPLong =\n        {\n            1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219,\n            1973, 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735,\n            150049, 242785, 392835, 635621, 1028457, 1664079, 2692537,\n            4356617, 7049155, 11405773, 18454929, 29860703, 48315633,\n            78176337, 126491971, 204668309, 331160281, 535828591, 866988873,\n            1402817465, 2269806339, 3672623805, 5942430145, 9615053951,\n            15557484097, 25172538049, 40730022147, 65902560197, 106632582345,\n            172535142543, 279167724889, 451702867433, 730870592323,\n            1182573459757, 1913444052081, 3096017511839, 5009461563921,\n            8105479075761, 13114940639683, 21220419715445, 34335360355129,\n            55555780070575, 89891140425705, 145446920496281, 235338060921987,\n            380784981418269, 616123042340257, 996908023758527,\n            1613031066098785, 2609939089857313, 4222970155956099,\n            6832909245813413, 11055879401769513, 17888788647582927,\n            28944668049352441, 46833456696935369, 75778124746287811,\n            122611581443223181, 198389706189510993, 321001287632734175,\n            519390993822245169, 840392281454979345, 1359783275277224515,\n            2200175556732203861, 3559958832009428377, 5760134388741632239\n        };\n\n        private static int TimSortMinRunLength(int n)\n        {\n            // assert n >= 0;\n            int r = 0;      // Becomes 1 if any 1 bits are shifted off\n            while (n >= c_minMerge)\n            {\n                r |= (n & 1);\n                n >>= 1;\n            }\n            return n + r;\n        }\n\n        private static long TimSortMinRunLength(long n)\n        {\n            // assert n >= 0;\n            long r = 0;      // Becomes 1 if any 1 bits are shifted off\n            while (n >= c_minMerge)\n            {\n                r |= (n & 1);\n                n >>= 1;\n            }\n            return n + r;\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Symbol/Dict_auto.cs",
    "content": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Text;\nusing System.Threading;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Dict<TKey, TValue>\n\n    /// <summary>\n    /// A Dict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class Dict<TKey, TValue>\n            : IIntCountable, ICountableDict, IDict<TKey, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>,\n              ICollection, ICollection<KeyValuePair<TKey, TValue>>,\n              IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>\n    {\n        private uint m_capacity;\n        private NextHashKeyValue<TKey, TValue>[] m_firstArray;\n        private HashKeyValueNext<TKey, TValue>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a Dict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// Dict acts as a stack for all items with the same key.\n        /// </summary>\n        public Dict(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a Dict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// Dict acts as a stack for all items with the same key.\n        /// </summary>\n        public Dict(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a Dict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// Dict acts as a stack for all items with the same key.\n        /// </summary>\n        public Dict(int initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a Dict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// Dict acts as a stack for all items with the same key.\n        /// </summary>\n        public Dict(IEnumerable<KeyValuePair<TKey, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private Dict(\n                uint firstCapacity, uint extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyValue<TKey, TValue>[m_capacity];\n            m_extraArray = new HashKeyValueNext<TKey, TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the Dict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the Dict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the Dict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the Dict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<KeyValuePair<TKey, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        /// <summary>\n        /// Returns all values in the Dict.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Value;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Value;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the Dict.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    while (ei > 0)\n                    {\n                        yield return new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the Dict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new Dict in the order they are returned.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                var stack = new Stack<int>();\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        yield return new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    }\n                    yield return new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the Dict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                var hash = key.GetHashCode();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key.GetHashCode();\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Hash == hash\n                        && key.Equals(m_firstArray[fi].Item.Key))\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Hash == hash\n                            && key.Equals(m_extraArray[ei].Item.Key))\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the Dict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the Dict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the Dict.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the Dict.\n        /// </summary>\n        public void Add(TKey key, int hash, TValue value)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the Dict.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the Dict.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash, TValue value)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the Dict.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the Dict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the Dict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Dict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Dict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Dict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Dict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Dict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, int hash, TValue value)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the Dict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the Dict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the Dict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        TValue AddCreated(TKey key, int hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the Dict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, int hash, Func<TKey, TValue> creator)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, int hash, TValue defaultValue)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, int hash, out TValue value)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                yield return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    yield return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values.\n        /// Should be preferred over Values enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValueEnumerator GetValuesEnumerator()\n        {\n            return new ValueEnumerator(this);\n        }\n\n        public struct ValueEnumerator : IEnumerator<TValue>\n        {\n            Dict<TKey, TValue>.Enumerator m_inner;\n\n            public ValueEnumerator(Dict<TKey, TValue> dict)\n            {\n                m_inner = dict.GetEnumerator();\n            }\n\n            public TValue Current => m_inner.Current.Value;\n\n            object IEnumerator.Current => Current;\n\n            public void Dispose() => m_inner.Dispose();\n\n            public bool MoveNext() => m_inner.MoveNext();\n\n            public void Reset() => m_inner.Reset();\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values with key. It is only useful\n        /// if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// Should be preferred over ValuesWithKey enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValuesWithKeyEnumerator GetValuesWithKeyEnumerator(TKey key)\n        {\n            return new ValuesWithKeyEnumerator(this, key);\n        }\n\n        public struct ValuesWithKeyEnumerator : IEnumerator<TValue>\n        {\n            readonly Dict<TKey, TValue> m_dict;\n            readonly TKey m_key;\n            readonly int m_hash;\n            int m_extraIndex;\n            TValue m_current;\n\n            public ValuesWithKeyEnumerator(Dict<TKey, TValue> dict, TKey key)\n            {\n                m_dict = dict;\n                m_key = key;\n                m_hash = key.GetHashCode();\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n\n            public readonly TValue Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex == int.MaxValue)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var fi = ((uint)m_hash) % m_dict.m_capacity;\n                    m_extraIndex = fa[fi].Next;\n                    if (m_extraIndex == 0) return false;\n                    if (fa[fi].Item.Hash == m_hash\n                        && m_key.Equals(fa[fi].Item.Key))\n                    {\n                        m_current = fa[fi].Item.Value;\n                        return true;\n                    }\n                }\n                if (m_extraIndex > 0)\n                {\n                    var ea = m_dict.m_extraArray;\n                    do\n                    {\n                        var valid = ea[m_extraIndex].Item.Hash == m_hash\n                                    && m_key.Equals(ea[m_extraIndex].Item.Key);\n                        if (valid) m_current = ea[m_extraIndex].Item.Value;\n                        m_extraIndex = ea[m_extraIndex].Next;\n                        if (valid) return true;\n                    } while (m_extraIndex > 0);\n                }\n\n                return false;\n            }\n\n            public void Reset()\n            {\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, int skip)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the Dict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the Dict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the Dict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            TValue value;\n            return TryRemove(key, hash, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the Dict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the Dict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash, TValue value)\n        {\n            return TryRemove(key, hash, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the Dict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, out TValue value)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, TValue value)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            var array = new TKey[m_count];\n            CopyKeysTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<TKey, TValue>[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextHashKeyValue<TKey, TValue>));\n            m_extraArray.Set(default(HashKeyValueNext<TKey, TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<TKey, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<TKey, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as KeyValuePair<TKey, TValue>[];\n            if (typedArray != null)\n                CopyTo(typedArray, index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the Dict to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentDict<TKey, TValue> AsConcurrent()\n        {\n            return new ConcurrentDict<TKey, TValue>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey, TValue>> Members\n\n        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n        \n        #region IDictionary<TKey, TValue> Members\n\n        ICollection<TKey> IDictionary<TKey, TValue>.Keys => new KeyCollection(this);\n\n        ICollection<TValue> IDictionary<TKey, TValue>.Values => new ValueCollection(this);\n\n        private sealed class KeyCollection(Dict<TKey, TValue> parent) : ICollection<TKey>, ICollection, IReadOnlyCollection<TKey>\n        {\n            public void CopyTo(TKey[] array, int index) => parent.CopyKeysTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<TKey>.IsReadOnly => true;\n\n            void ICollection<TKey>.Add(TKey item) => throw new NotSupportedException();\n\n            void ICollection<TKey>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(TKey item) => parent.ContainsKey(item);\n\n            bool ICollection<TKey>.Remove(TKey item) => throw new NotSupportedException();\n\n            IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<TKey>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is TKey[] keys) parent.CopyKeysTo(keys, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(Dict<TKey, TValue> dictionary) : IEnumerator<TKey>, IEnumerator\n            {\n                private Dict<TKey, TValue>.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public TKey Current => _inner.Current.Key;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        private sealed class ValueCollection(Dict<TKey, TValue> parent) : ICollection<TValue>, ICollection, IReadOnlyCollection<TValue>\n        {\n            public void CopyTo(TValue[] array, int index) => parent.CopyValuesTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<TValue>.IsReadOnly => true;\n\n            void ICollection<TValue>.Add(TValue item) => throw new NotSupportedException();\n\n            void ICollection<TValue>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(TValue item) => parent.ContainsValue(item);\n\n            bool ICollection<TValue>.Remove(TValue item) => throw new NotSupportedException();\n\n            IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<TValue>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is TValue[] values) parent.CopyValuesTo(values, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(Dict<TKey, TValue> dictionary) : IEnumerator<TValue>, IEnumerator\n            {\n                private Dict<TKey, TValue>.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public TValue Current => _inner.Current.Value;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        #endregion\n        \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>\n        {\n            readonly Dict<TKey, TValue> m_dict;\n            int m_index;\n            int m_extraIndex;\n            KeyValuePair<TKey, TValue> m_current;\n\n            public Enumerator(Dict<TKey, TValue> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(KeyValuePair<TKey, TValue>);\n            }\n\n            public readonly KeyValuePair<TKey, TValue> Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = new KeyValuePair<TKey, TValue>(fa[m_index].Item.Key, fa[m_index].Item.Value);\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = new KeyValuePair<TKey, TValue>(ea[m_extraIndex].Item.Key, ea[m_extraIndex].Item.Value);\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default( KeyValuePair<TKey, TValue>);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                HashKeyValueNext<TKey, TValue>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyValue<TKey, TValue> item,\n                NextHashKeyValue<TKey, TValue>[] firstArray,\n                uint capacity,\n                ref HashKeyValueNext<TKey, TValue>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyValue<TKey, TValue>[newCapacity];\n            var extraArray = new HashKeyValueNext<TKey, TValue>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region DictSet<TKey>\n\n    /// <summary>\n    /// A DictSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class DictSet<TKey>\n            : IIntCountable, ICountableDictSet, IDictSet<TKey>,\n              IEnumerable, IEnumerable<TKey>,\n              ICollection, ICollection<TKey>\n    {\n        private uint m_capacity;\n        private NextHashKey<TKey>[] m_firstArray;\n        private HashKeyNext<TKey>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a DictSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public DictSet()\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a DictSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public DictSet(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a DictSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public DictSet(IEnumerable<TKey> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private DictSet(\n                uint firstCapacity, uint extraCapacity)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKey<TKey>[m_capacity];\n            m_extraArray = new HashKeyNext<TKey>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the DictSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<TKey> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the DictSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the DictSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        void ICollection<TKey>.Add(TKey key)\n        {\n            Add(key);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the DictSet.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            var hash = key.GetHashCode();\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the DictSet.\n        /// </summary>\n        public bool Add(TKey key, int hash)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the DictSet.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            var hash = key.GetHashCode();\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the DictSet.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the DictSet.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the DictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the DictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the DictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the DictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            return TryRemove(key, hash);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKey<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKey<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKey<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKey<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            var array = new TKey[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextHashKey<TKey>));\n            m_extraArray.Set(default(HashKeyNext<TKey>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(TKey[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as TKey[];\n            if (typedArray != null)\n                CopyTo(typedArray, index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the DictSet to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentDictSet<TKey> AsConcurrent()\n        {\n            return new ConcurrentDictSet<TKey>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<TKey> Members\n\n        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<TKey>\n        {\n            readonly DictSet<TKey> m_dict;\n            int m_index;\n            int m_extraIndex;\n            TKey m_current;\n\n            public Enumerator(DictSet<TKey> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(TKey);\n            }\n\n            public readonly TKey Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = fa[m_index].Item.Key;\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = ea[m_extraIndex].Item.Key;\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(TKey);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                HashKeyNext<TKey>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKey<TKey> item,\n                NextHashKey<TKey>[] firstArray,\n                uint capacity,\n                ref HashKeyNext<TKey>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKey<TKey>[newCapacity];\n            var extraArray = new HashKeyNext<TKey>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IntDict<TValue>\n\n    /// <summary>\n    /// A IntDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class IntDict<TValue>\n            : IIntCountable, ICountableDict, IDict<int, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<int, TValue>>,\n              ICollection, ICollection<KeyValuePair<int, TValue>>,\n              IDictionary<int, TValue>, IReadOnlyDictionary<int, TValue>\n    {\n        private uint m_capacity;\n        private NextIntValue<TValue>[] m_firstArray;\n        private IntValueNext<TValue>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a IntDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// IntDict acts as a stack for all items with the same key.\n        /// </summary>\n        public IntDict(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a IntDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// IntDict acts as a stack for all items with the same key.\n        /// </summary>\n        public IntDict(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a IntDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// IntDict acts as a stack for all items with the same key.\n        /// </summary>\n        public IntDict(int initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a IntDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// IntDict acts as a stack for all items with the same key.\n        /// </summary>\n        public IntDict(IEnumerable<KeyValuePair<int, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private IntDict(\n                uint firstCapacity, uint extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextIntValue<TValue>[m_capacity];\n            m_extraArray = new IntValueNext<TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the IntDict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the IntDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the IntDict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the IntDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<KeyValuePair<int, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<int> Keys\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(int); } }\n\n        /// <summary>\n        /// Returns all values in the IntDict.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Value;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Value;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the IntDict.\n        /// </summary>\n        public IEnumerable<KeyValuePair<int, TValue>> KeyValuePairs\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return new KeyValuePair<int, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    while (ei > 0)\n                    {\n                        yield return new KeyValuePair<int, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the IntDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new IntDict in the order they are returned.\n        /// </summary>\n        public IEnumerable<KeyValuePair<int, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                var stack = new Stack<int>();\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        yield return new KeyValuePair<int, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    }\n                    yield return new KeyValuePair<int, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the IntDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[int key]\n        {\n            get\n            {\n                var hash = key;\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Key == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Key == hash)\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Key == hash)\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the IntDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the IntDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((int)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the IntDict.\n        /// </summary>\n        public void Add(int key, TValue value)\n        {\n            var hash = key;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key == hash)\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the IntDict.\n        /// </summary>\n        public bool TryAdd(int key, TValue value)\n        {\n            var hash = key;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the IntDict.\n        /// </summary>\n        public void Add(KeyValuePair<int, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the IntDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<int, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the IntDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(int key)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the IntDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(int key)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the IntDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(int key, TValue value)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the IntDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<int, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the IntDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(int key)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the IntDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(int key, Func<int, TValue> creator)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        TValue AddCreated(int key, int hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Key == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(int key, TValue defaultValue)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(int key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(int key, out TValue value)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(int key)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Key == hash)\n                yield return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    yield return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values.\n        /// Should be preferred over Values enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValueEnumerator GetValuesEnumerator()\n        {\n            return new ValueEnumerator(this);\n        }\n\n        public struct ValueEnumerator : IEnumerator<TValue>\n        {\n            IntDict<TValue>.Enumerator m_inner;\n\n            public ValueEnumerator(IntDict<TValue> dict)\n            {\n                m_inner = dict.GetEnumerator();\n            }\n\n            public TValue Current => m_inner.Current.Value;\n\n            object IEnumerator.Current => Current;\n\n            public void Dispose() => m_inner.Dispose();\n\n            public bool MoveNext() => m_inner.MoveNext();\n\n            public void Reset() => m_inner.Reset();\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values with key. It is only useful\n        /// if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// Should be preferred over ValuesWithKey enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValuesWithKeyEnumerator GetValuesWithKeyEnumerator(int key)\n        {\n            return new ValuesWithKeyEnumerator(this, key);\n        }\n\n        public struct ValuesWithKeyEnumerator : IEnumerator<TValue>\n        {\n            readonly IntDict<TValue> m_dict;\n            readonly int m_hash;\n            int m_extraIndex;\n            TValue m_current;\n\n            public ValuesWithKeyEnumerator(IntDict<TValue> dict, int key)\n            {\n                m_dict = dict;\n                m_hash = key;\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n\n            public readonly TValue Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex == int.MaxValue)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var fi = ((uint)m_hash) % m_dict.m_capacity;\n                    m_extraIndex = fa[fi].Next;\n                    if (m_extraIndex == 0) return false;\n                    if (fa[fi].Item.Key == m_hash)\n                    {\n                        m_current = fa[fi].Item.Value;\n                        return true;\n                    }\n                }\n                if (m_extraIndex > 0)\n                {\n                    var ea = m_dict.m_extraArray;\n                    do\n                    {\n                        var valid = ea[m_extraIndex].Item.Key == m_hash;\n                        if (valid) m_current = ea[m_extraIndex].Item.Value;\n                        m_extraIndex = ea[m_extraIndex].Next;\n                        if (valid) return true;\n                    } while (m_extraIndex > 0);\n                }\n\n                return false;\n            }\n\n            public void Reset()\n            {\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(int key, int skip)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the IntDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(int key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the IntDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(int key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the IntDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(int key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the IntDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<int, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(int key, out TValue value)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(IntValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(IntValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(IntValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key == hash)\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(IntValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(int key, TValue value)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(IntValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(IntValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(IntValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key == hash\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(IntValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public int[] KeysToArray()\n        {\n            var array = new int[m_count];\n            CopyKeysTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// </summary>\n        public KeyValuePair<int, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<int, TValue>[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextIntValue<TValue>));\n            m_extraArray.Set(default(IntValueNext<TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyKeysTo(int[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(KeyValuePair<int, TValue>[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<int, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<int, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as KeyValuePair<int, TValue>[];\n            if (typedArray != null)\n                CopyTo(typedArray, index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the IntDict to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentIntDict<TValue> AsConcurrent()\n        {\n            return new ConcurrentIntDict<TValue>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<int, TValue>> Members\n\n        IEnumerator<KeyValuePair<int, TValue>> IEnumerable<KeyValuePair<int, TValue>>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n        \n        #region IDictionary<int, TValue> Members\n\n        ICollection<int> IDictionary<int, TValue>.Keys => new KeyCollection(this);\n\n        ICollection<TValue> IDictionary<int, TValue>.Values => new ValueCollection(this);\n\n        private sealed class KeyCollection(IntDict<TValue> parent) : ICollection<int>, ICollection, IReadOnlyCollection<int>\n        {\n            public void CopyTo(int[] array, int index) => parent.CopyKeysTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<int>.IsReadOnly => true;\n\n            void ICollection<int>.Add(int item) => throw new NotSupportedException();\n\n            void ICollection<int>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(int item) => parent.ContainsKey(item);\n\n            bool ICollection<int>.Remove(int item) => throw new NotSupportedException();\n\n            IEnumerator<int> IEnumerable<int>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<int>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is int[] keys) parent.CopyKeysTo(keys, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(IntDict<TValue> dictionary) : IEnumerator<int>, IEnumerator\n            {\n                private IntDict<TValue>.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public int Current => _inner.Current.Key;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        private sealed class ValueCollection(IntDict<TValue> parent) : ICollection<TValue>, ICollection, IReadOnlyCollection<TValue>\n        {\n            public void CopyTo(TValue[] array, int index) => parent.CopyValuesTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<TValue>.IsReadOnly => true;\n\n            void ICollection<TValue>.Add(TValue item) => throw new NotSupportedException();\n\n            void ICollection<TValue>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(TValue item) => parent.ContainsValue(item);\n\n            bool ICollection<TValue>.Remove(TValue item) => throw new NotSupportedException();\n\n            IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<TValue>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is TValue[] values) parent.CopyValuesTo(values, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(IntDict<TValue> dictionary) : IEnumerator<TValue>, IEnumerator\n            {\n                private IntDict<TValue>.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public TValue Current => _inner.Current.Value;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        #endregion\n        \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<KeyValuePair<int, TValue>>\n        {\n            readonly IntDict<TValue> m_dict;\n            int m_index;\n            int m_extraIndex;\n            KeyValuePair<int, TValue> m_current;\n\n            public Enumerator(IntDict<TValue> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(KeyValuePair<int, TValue>);\n            }\n\n            public readonly KeyValuePair<int, TValue> Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = new KeyValuePair<int, TValue>(fa[m_index].Item.Key, fa[m_index].Item.Value);\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = new KeyValuePair<int, TValue>(ea[m_extraIndex].Item.Key, ea[m_extraIndex].Item.Value);\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default( KeyValuePair<int, TValue>);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                IntValueNext<TValue>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                IntValue<TValue> item,\n                NextIntValue<TValue>[] firstArray,\n                uint capacity,\n                ref IntValueNext<TValue>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Key) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextIntValue<TValue>[newCapacity];\n            var extraArray = new IntValueNext<TValue>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region IntSet\n\n    /// <summary>\n    /// A IntSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class IntSet\n            : IIntCountable, ICountableDictSet, IDictSet<int>,\n              IEnumerable, IEnumerable<int>,\n              ICollection, ICollection<int>\n    {\n        private uint m_capacity;\n        private NextInt[] m_firstArray;\n        private IntNext[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a IntSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public IntSet()\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a IntSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public IntSet(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a IntSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public IntSet(IEnumerable<int> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private IntSet(\n                uint firstCapacity, uint extraCapacity)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextInt[m_capacity];\n            m_extraArray = new IntNext[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the IntSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the IntSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the IntSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the IntSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<int> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<int> Keys\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(int); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the IntSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the IntSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((int)objkey);\n        }\n\n        void ICollection<int>.Add(int key)\n        {\n            Add(key);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the IntSet.\n        /// </summary>\n        public bool Add(int key)\n        {\n            var hash = key;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the IntSet.\n        /// </summary>\n        public bool TryAdd(int key)\n        {\n            var hash = key;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the IntSet.\n        /// </summary>\n        public void AddRange(IEnumerable<int> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the IntSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(int key)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the IntSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(int key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(int key)\n        {\n            var hash = key;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item == hash)\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(int);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(int);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item == hash)\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(int);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item == hash)\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(int);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public int[] ToArray()\n        {\n            var array = new int[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextInt));\n            m_extraArray.Set(default(IntNext));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(int[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as int[];\n            if (typedArray != null)\n                CopyTo(typedArray, index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the IntSet to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentIntSet AsConcurrent()\n        {\n            return new ConcurrentIntSet(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<int> Members\n\n        IEnumerator<int> IEnumerable<int>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<int>\n        {\n            readonly IntSet m_dict;\n            int m_index;\n            int m_extraIndex;\n            int m_current;\n\n            public Enumerator(IntSet dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(int);\n            }\n\n            public readonly int Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = fa[m_index].Item;\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = ea[m_extraIndex].Item;\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(int);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                IntNext[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                int item,\n                NextInt[] firstArray,\n                uint capacity,\n                ref IntNext[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextInt[newCapacity];\n            var extraArray = new IntNext[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region SymbolDict<TValue>\n\n    /// <summary>\n    /// A SymbolDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class SymbolDict<TValue>\n            : IIntCountable, ICountableDict, IDict<Symbol, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<Symbol, TValue>>,\n              ICollection, ICollection<KeyValuePair<Symbol, TValue>>,\n              IDictionary<Symbol, TValue>, IReadOnlyDictionary<Symbol, TValue>\n    {\n        private uint m_capacity;\n        private NextSymbolValue<TValue>[] m_firstArray;\n        private SymbolValueNext<TValue>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a SymbolDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// SymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public SymbolDict(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a SymbolDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// SymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public SymbolDict(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a SymbolDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// SymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public SymbolDict(int initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a SymbolDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// SymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public SymbolDict(IEnumerable<KeyValuePair<Symbol, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Create a SymbolDict and initialize to contain the supplied items.\n        /// Note hat this incurs the overhead of converting all string keys\n        /// to symbols.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// SymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public SymbolDict(IEnumerable<KeyValuePair<string, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private SymbolDict(\n                uint firstCapacity, uint extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextSymbolValue<TValue>[m_capacity];\n            m_extraArray = new SymbolValueNext<TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the SymbolDict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the SymbolDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the SymbolDict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the SymbolDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<KeyValuePair<Symbol, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<Symbol> Keys\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(Symbol); } }\n\n        /// <summary>\n        /// Returns all values in the SymbolDict.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Value;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Value;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the SymbolDict.\n        /// </summary>\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairs\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return new KeyValuePair<Symbol, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    while (ei > 0)\n                    {\n                        yield return new KeyValuePair<Symbol, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the SymbolDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new SymbolDict in the order they are returned.\n        /// </summary>\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                var stack = new Stack<int>();\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        yield return new KeyValuePair<Symbol, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    }\n                    yield return new KeyValuePair<Symbol, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the SymbolDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[Symbol key]\n        {\n            get\n            {\n                var hash = key.Id;\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Key.Id == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key.Id == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key.Id;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Key.Id == hash)\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Key.Id == hash)\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the SymbolDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the SymbolDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((Symbol)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the SymbolDict.\n        /// </summary>\n        public void Add(Symbol key, TValue value)\n        {\n            var hash = key.Id;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key.Id == hash)\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key.Id == hash)\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the SymbolDict.\n        /// </summary>\n        public bool TryAdd(Symbol key, TValue value)\n        {\n            var hash = key.Id;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key.Id == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key.Id == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Adds the supplied item to the SymbolDict. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(string key, TValue value)\n        {\n            Add(key.ToSymbol(), value);\n        }\n\n        /// <summary>\n        /// Add the supplied item to the SymbolDict. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(KeyValuePair<string, TValue> item)\n        {\n            Add(item.Key.ToSymbol(), item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied item to the SymbolDict.\n        /// </summary>\n        public void Add(KeyValuePair<Symbol, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the SymbolDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<Symbol, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the SymbolDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(Symbol key)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the SymbolDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(Symbol key)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the SymbolDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(Symbol key, TValue value)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key.Id == hash\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the SymbolDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<Symbol, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the SymbolDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(Symbol key)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the SymbolDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(Symbol key, Func<Symbol, TValue> creator)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        TValue AddCreated(Symbol key, int hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Key.Id == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key.Id == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(Symbol key, TValue defaultValue)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(Symbol key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(Symbol key, out TValue value)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Key.Id == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(Symbol key)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                yield return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    yield return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values.\n        /// Should be preferred over Values enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValueEnumerator GetValuesEnumerator()\n        {\n            return new ValueEnumerator(this);\n        }\n\n        public struct ValueEnumerator : IEnumerator<TValue>\n        {\n            SymbolDict<TValue>.Enumerator m_inner;\n\n            public ValueEnumerator(SymbolDict<TValue> dict)\n            {\n                m_inner = dict.GetEnumerator();\n            }\n\n            public TValue Current => m_inner.Current.Value;\n\n            object IEnumerator.Current => Current;\n\n            public void Dispose() => m_inner.Dispose();\n\n            public bool MoveNext() => m_inner.MoveNext();\n\n            public void Reset() => m_inner.Reset();\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values with key. It is only useful\n        /// if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// Should be preferred over ValuesWithKey enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValuesWithKeyEnumerator GetValuesWithKeyEnumerator(Symbol key)\n        {\n            return new ValuesWithKeyEnumerator(this, key);\n        }\n\n        public struct ValuesWithKeyEnumerator : IEnumerator<TValue>\n        {\n            readonly SymbolDict<TValue> m_dict;\n            readonly int m_hash;\n            int m_extraIndex;\n            TValue m_current;\n\n            public ValuesWithKeyEnumerator(SymbolDict<TValue> dict, Symbol key)\n            {\n                m_dict = dict;\n                m_hash = key.Id;\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n\n            public readonly TValue Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex == int.MaxValue)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var fi = ((uint)m_hash) % m_dict.m_capacity;\n                    m_extraIndex = fa[fi].Next;\n                    if (m_extraIndex == 0) return false;\n                    if (fa[fi].Item.Key.Id == m_hash)\n                    {\n                        m_current = fa[fi].Item.Value;\n                        return true;\n                    }\n                }\n                if (m_extraIndex > 0)\n                {\n                    var ea = m_dict.m_extraArray;\n                    do\n                    {\n                        var valid = ea[m_extraIndex].Item.Key.Id == m_hash;\n                        if (valid) m_current = ea[m_extraIndex].Item.Value;\n                        m_extraIndex = ea[m_extraIndex].Next;\n                        if (valid) return true;\n                    } while (m_extraIndex > 0);\n                }\n\n                return false;\n            }\n\n            public void Reset()\n            {\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(Symbol key, int skip)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key.Id == hash)\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the SymbolDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(Symbol key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the SymbolDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(Symbol key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the SymbolDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(Symbol key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the SymbolDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<Symbol, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(Symbol key, out TValue value)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Key.Id == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(SymbolValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(SymbolValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(SymbolValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key.Id == hash)\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(SymbolValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(Symbol key, TValue value)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key.Id == hash\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(SymbolValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(SymbolValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(SymbolValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key.Id == hash\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(SymbolValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public Symbol[] KeysToArray()\n        {\n            var array = new Symbol[m_count];\n            CopyKeysTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// </summary>\n        public KeyValuePair<Symbol, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<Symbol, TValue>[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextSymbolValue<TValue>));\n            m_extraArray.Set(default(SymbolValueNext<TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyKeysTo(Symbol[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(KeyValuePair<Symbol, TValue>[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<Symbol, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<Symbol, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as KeyValuePair<Symbol, TValue>[];\n            if (typedArray != null)\n                CopyTo(typedArray, index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the SymbolDict to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentSymbolDict<TValue> AsConcurrent()\n        {\n            return new ConcurrentSymbolDict<TValue>(this);\n        }\n\n        public void Add<TType>(TypedSymbol<TType> key, TType value)\n            where TType : TValue\n        {\n            this.Add(key.Symbol, value);\n        }\n\n        public bool Contains<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return Contains(key.Symbol);\n        }\n\n        public bool ContainsKey<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return ContainsKey(key.Symbol);\n        }\n\n        public TType Get<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return (TType)this[key.Symbol];\n        }\n\n        public TType Get<TType>(TypedSymbol<TType> key, TType defaultValue)\n            where TType : TValue\n        {\n            TType value;\n            if (TryGetValue(key, out value)) return value;\n            return defaultValue;\n        }\n\n        public TType GetOrDefault<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            TType value;\n            if (TryGetValue(key, out value)) return value;\n            return default(TType);\n        }\n\n        public bool Remove<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return Remove(key.Symbol);\n        }\n\n        public void Set<TType>(TypedSymbol<TType> key, TType value)\n            where TType : TValue\n        {\n            this[key.Symbol] = value;\n        }\n\n        public bool TryGetValue<TType>(TypedSymbol<TType> key, out TType value)\n            where TType : TValue\n        {\n            TValue val;\n            if (TryGetValue(key.Symbol, out val)) { value = (TType)val; return true; }\n            value = default(TType);\n            return false;\n        }\n\n        public TType GetAs<TType>(Symbol key)\n            where TType : TValue\n        {\n            return (TType)this[key];\n        }\n\n        public TType GetAs<TType>(Symbol key, TType defaultValue)\n            where TType : TValue\n        {\n            TValue value;\n            if (TryGetValue(key, out value)) return (TType)value;\n            return defaultValue;\n        }\n\n        public TType GetAsOrDefault<TType>(Symbol key)\n            where TType : TValue\n        {\n            TValue value;\n            if (TryGetValue(key, out value)) return (TType)value;\n            return default(TType);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<Symbol, TValue>> Members\n\n        IEnumerator<KeyValuePair<Symbol, TValue>> IEnumerable<KeyValuePair<Symbol, TValue>>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n        \n        #region IDictionary<Symbol, TValue> Members\n\n        ICollection<Symbol> IDictionary<Symbol, TValue>.Keys => new KeyCollection(this);\n\n        ICollection<TValue> IDictionary<Symbol, TValue>.Values => new ValueCollection(this);\n\n        private sealed class KeyCollection(SymbolDict<TValue> parent) : ICollection<Symbol>, ICollection, IReadOnlyCollection<Symbol>\n        {\n            public void CopyTo(Symbol[] array, int index) => parent.CopyKeysTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<Symbol>.IsReadOnly => true;\n\n            void ICollection<Symbol>.Add(Symbol item) => throw new NotSupportedException();\n\n            void ICollection<Symbol>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(Symbol item) => parent.ContainsKey(item);\n\n            bool ICollection<Symbol>.Remove(Symbol item) => throw new NotSupportedException();\n\n            IEnumerator<Symbol> IEnumerable<Symbol>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<Symbol>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is Symbol[] keys) parent.CopyKeysTo(keys, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(SymbolDict<TValue> dictionary) : IEnumerator<Symbol>, IEnumerator\n            {\n                private SymbolDict<TValue>.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public Symbol Current => _inner.Current.Key;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        private sealed class ValueCollection(SymbolDict<TValue> parent) : ICollection<TValue>, ICollection, IReadOnlyCollection<TValue>\n        {\n            public void CopyTo(TValue[] array, int index) => parent.CopyValuesTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<TValue>.IsReadOnly => true;\n\n            void ICollection<TValue>.Add(TValue item) => throw new NotSupportedException();\n\n            void ICollection<TValue>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(TValue item) => parent.ContainsValue(item);\n\n            bool ICollection<TValue>.Remove(TValue item) => throw new NotSupportedException();\n\n            IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<TValue>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is TValue[] values) parent.CopyValuesTo(values, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(SymbolDict<TValue> dictionary) : IEnumerator<TValue>, IEnumerator\n            {\n                private SymbolDict<TValue>.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public TValue Current => _inner.Current.Value;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        #endregion\n        \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<KeyValuePair<Symbol, TValue>>\n        {\n            readonly SymbolDict<TValue> m_dict;\n            int m_index;\n            int m_extraIndex;\n            KeyValuePair<Symbol, TValue> m_current;\n\n            public Enumerator(SymbolDict<TValue> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(KeyValuePair<Symbol, TValue>);\n            }\n\n            public readonly KeyValuePair<Symbol, TValue> Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = new KeyValuePair<Symbol, TValue>(fa[m_index].Item.Key, fa[m_index].Item.Value);\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = new KeyValuePair<Symbol, TValue>(ea[m_extraIndex].Item.Key, ea[m_extraIndex].Item.Value);\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default( KeyValuePair<Symbol, TValue>);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                SymbolValueNext<TValue>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                SymbolValue<TValue> item,\n                NextSymbolValue<TValue>[] firstArray,\n                uint capacity,\n                ref SymbolValueNext<TValue>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Key.Id) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextSymbolValue<TValue>[newCapacity];\n            var extraArray = new SymbolValueNext<TValue>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region SymbolSet\n\n    /// <summary>\n    /// A SymbolSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class SymbolSet\n            : IIntCountable, ICountableDictSet, IDictSet<Symbol>,\n              IEnumerable, IEnumerable<Symbol>,\n              ICollection, ICollection<Symbol>\n    {\n        private uint m_capacity;\n        private NextSymbol[] m_firstArray;\n        private SymbolNext[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a SymbolSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public SymbolSet()\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a SymbolSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public SymbolSet(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a SymbolSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public SymbolSet(IEnumerable<Symbol> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Create a SymbolSet and initialize to contain the supplied items.\n        /// Note hat this incurs the overhead of converting all string keys\n        /// to symbols.\n        /// </summary>\n        public SymbolSet(IEnumerable<string> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private SymbolSet(\n                uint firstCapacity, uint extraCapacity)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextSymbol[m_capacity];\n            m_extraArray = new SymbolNext[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the SymbolSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the SymbolSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the SymbolSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the SymbolSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<Symbol> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<Symbol> Keys\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(Symbol); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the SymbolSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the SymbolSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((Symbol)objkey);\n        }\n\n        void ICollection<Symbol>.Add(Symbol key)\n        {\n            Add(key);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the SymbolSet.\n        /// </summary>\n        public bool Add(Symbol key)\n        {\n            var hash = key.Id;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Id == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Id == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the SymbolSet.\n        /// </summary>\n        public bool TryAdd(Symbol key)\n        {\n            var hash = key.Id;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Id == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Id == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Adds the supplied item to the SymbolSet. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(string key)\n        {\n            Add(key.ToSymbol());\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the SymbolSet.\n        /// </summary>\n        public void AddRange(IEnumerable<Symbol> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the SymbolSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(Symbol key)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Id == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Id == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the SymbolSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(Symbol key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(Symbol key)\n        {\n            var hash = key.Id;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Id == hash)\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(Symbol);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(Symbol);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Id == hash)\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(Symbol);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Id == hash)\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(Symbol);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public Symbol[] ToArray()\n        {\n            var array = new Symbol[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextSymbol));\n            m_extraArray.Set(default(SymbolNext));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(Symbol[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as Symbol[];\n            if (typedArray != null)\n                CopyTo(typedArray, index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the SymbolSet to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentSymbolSet AsConcurrent()\n        {\n            return new ConcurrentSymbolSet(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<Symbol> Members\n\n        IEnumerator<Symbol> IEnumerable<Symbol>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<Symbol>\n        {\n            readonly SymbolSet m_dict;\n            int m_index;\n            int m_extraIndex;\n            Symbol m_current;\n\n            public Enumerator(SymbolSet dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(Symbol);\n            }\n\n            public readonly Symbol Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = fa[m_index].Item;\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = ea[m_extraIndex].Item;\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(Symbol);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                SymbolNext[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                Symbol item,\n                NextSymbol[] firstArray,\n                uint capacity,\n                ref SymbolNext[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Id) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextSymbol[newCapacity];\n            var extraArray = new SymbolNext[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region BigDict<TKey, TValue>\n\n    /// <summary>\n    /// A BigDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class BigDict<TKey, TValue>\n            : ICountableDict, IDict<TKey, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>\n    {\n        private readonly Func<TKey, long> m_hfun;\n        private ulong m_capacity;\n        private NextHashKeyValueLong<TKey, TValue>[] m_firstArray;\n        private HashKeyValueNextLong<TKey, TValue>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a BigDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// BigDict acts as a stack for all items with the same key.\n        /// </summary>\n        public BigDict(Func<TKey, long> hfun, bool stackDuplicateKeys = false)\n            : this(hfun, DictConstant.PrimeSizesLong[0], (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a BigDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// BigDict acts as a stack for all items with the same key.\n        /// </summary>\n        public BigDict(Func<TKey, long> hfun, long initialCapacity)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a BigDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// BigDict acts as a stack for all items with the same key.\n        /// </summary>\n        public BigDict(Func<TKey, long> hfun, long initialCapacity, bool stackDuplicateKeys)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a BigDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// BigDict acts as a stack for all items with the same key.\n        /// </summary>\n        public BigDict(Func<TKey, long> hfun, IEnumerable<KeyValuePair<TKey, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(hfun, Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizesLong[0]), (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private BigDict(\n                Func<TKey, long> hfun, ulong firstCapacity, ulong extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_hfun = hfun;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizesLong[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizesLong[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyValueLong<TKey, TValue>[m_capacity];\n            m_extraArray = new HashKeyValueNextLong<TKey, TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the BigDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the BigDict\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the BigDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<KeyValuePair<TKey, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        /// <summary>\n        /// Returns all values in the BigDict.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Value;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Value;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the BigDict.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    while (ei > 0)\n                    {\n                        yield return new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the BigDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new BigDict in the order they are returned.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                var stack = new Stack<long>();\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        yield return new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    }\n                    yield return new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the BigDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                var hash = m_hfun(key);\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = m_hfun(key);\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Hash == hash\n                        && key.Equals(m_firstArray[fi].Item.Key))\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Hash == hash\n                            && key.Equals(m_extraArray[ei].Item.Key))\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.LongLength;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the BigDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the BigDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the BigDict.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the BigDict.\n        /// </summary>\n        public void Add(TKey key, long hash, TValue value)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the BigDict.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the BigDict.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash, TValue value)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the BigDict.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the BigDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the BigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, long hash, TValue value)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the BigDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the BigDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        TValue AddCreated(TKey key, long hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the BigDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, long hash, Func<TKey, TValue> creator)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, long hash, TValue defaultValue)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, long hash, out TValue value)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                yield return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    yield return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values.\n        /// Should be preferred over Values enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValueEnumerator GetValuesEnumerator()\n        {\n            return new ValueEnumerator(this);\n        }\n\n        public struct ValueEnumerator : IEnumerator<TValue>\n        {\n            BigDict<TKey, TValue>.Enumerator m_inner;\n\n            public ValueEnumerator(BigDict<TKey, TValue> dict)\n            {\n                m_inner = dict.GetEnumerator();\n            }\n\n            public TValue Current => m_inner.Current.Value;\n\n            object IEnumerator.Current => Current;\n\n            public void Dispose() => m_inner.Dispose();\n\n            public bool MoveNext() => m_inner.MoveNext();\n\n            public void Reset() => m_inner.Reset();\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values with key. It is only useful\n        /// if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// Should be preferred over ValuesWithKey enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValuesWithKeyEnumerator GetValuesWithKeyEnumerator(TKey key)\n        {\n            return new ValuesWithKeyEnumerator(this, key);\n        }\n\n        public struct ValuesWithKeyEnumerator : IEnumerator<TValue>\n        {\n            readonly BigDict<TKey, TValue> m_dict;\n            readonly TKey m_key;\n            readonly long m_hash;\n            long m_extraIndex;\n            TValue m_current;\n\n            public ValuesWithKeyEnumerator(BigDict<TKey, TValue> dict, TKey key)\n            {\n                m_dict = dict;\n                m_key = key;\n                m_hash = dict.m_hfun(key);\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n\n            public readonly TValue Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex == int.MaxValue)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var fi = ((uint)m_hash) % m_dict.m_capacity;\n                    m_extraIndex = fa[fi].Next;\n                    if (m_extraIndex == 0) return false;\n                    if (fa[fi].Item.Hash == m_hash\n                        && m_key.Equals(fa[fi].Item.Key))\n                    {\n                        m_current = fa[fi].Item.Value;\n                        return true;\n                    }\n                }\n                if (m_extraIndex > 0)\n                {\n                    var ea = m_dict.m_extraArray;\n                    do\n                    {\n                        var valid = ea[m_extraIndex].Item.Hash == m_hash\n                                    && m_key.Equals(ea[m_extraIndex].Item.Key);\n                        if (valid) m_current = ea[m_extraIndex].Item.Value;\n                        m_extraIndex = ea[m_extraIndex].Next;\n                        if (valid) return true;\n                    } while (m_extraIndex > 0);\n                }\n\n                return false;\n            }\n\n            public void Reset()\n            {\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, long skip)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the BigDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the BigDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the BigDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            TValue value;\n            return TryRemove(key, hash, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the BigDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the BigDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash, TValue value)\n        {\n            return TryRemove(key, hash, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the BigDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, out TValue value)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, TValue value)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            var array = new TKey[m_count];\n            CopyKeysTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<TKey, TValue>[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextHashKeyValueLong<TKey, TValue>));\n            m_extraArray.Set(default(HashKeyValueNextLong<TKey, TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<TKey, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<TKey, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as KeyValuePair<TKey, TValue>[];\n            if (typedArray != null)\n                CopyTo(typedArray, (long)index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the BigDict to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentBigDict<TKey, TValue> AsConcurrent()\n        {\n            return new ConcurrentBigDict<TKey, TValue>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey, TValue>> Members\n\n        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>\n        {\n            readonly BigDict<TKey, TValue> m_dict;\n            long m_index;\n            long m_extraIndex;\n            KeyValuePair<TKey, TValue> m_current;\n\n            public Enumerator(BigDict<TKey, TValue> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(KeyValuePair<TKey, TValue>);\n            }\n\n            public readonly KeyValuePair<TKey, TValue> Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = new KeyValuePair<TKey, TValue>(fa[m_index].Item.Key, fa[m_index].Item.Value);\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = new KeyValuePair<TKey, TValue>(ea[m_extraIndex].Item.Key, ea[m_extraIndex].Item.Value);\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default( KeyValuePair<TKey, TValue>);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                HashKeyValueNextLong<TKey, TValue>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizesLong[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizesLong[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyValueLong<TKey, TValue> item,\n                NextHashKeyValueLong<TKey, TValue>[] firstArray,\n                ulong capacity,\n                ref HashKeyValueNextLong<TKey, TValue>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyValueLong<TKey, TValue>[newCapacity];\n            var extraArray = new HashKeyValueNextLong<TKey, TValue>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.LongLength / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region BigDictSet<TKey>\n\n    /// <summary>\n    /// A BigDictSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class BigDictSet<TKey>\n            : ICountableDictSet, IDictSet<TKey>,\n              IEnumerable, IEnumerable<TKey>\n    {\n        private readonly Func<TKey, long> m_hfun;\n        private ulong m_capacity;\n        private NextHashKeyLong<TKey>[] m_firstArray;\n        private HashKeyNextLong<TKey>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a BigDictSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public BigDictSet(Func<TKey, long> hfun)\n            : this(hfun, DictConstant.PrimeSizesLong[0], (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a BigDictSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public BigDictSet(Func<TKey, long> hfun, long initialCapacity)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a BigDictSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public BigDictSet(Func<TKey, long> hfun, IEnumerable<TKey> items)\n            : this(hfun, Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizesLong[0]), (ulong)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private BigDictSet(\n                Func<TKey, long> hfun, ulong firstCapacity, ulong extraCapacity)\n        {\n            m_hfun = hfun;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizesLong[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizesLong[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyLong<TKey>[m_capacity];\n            m_extraArray = new HashKeyNextLong<TKey>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the BigDictSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the BigDictSet\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the BigDictSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<TKey> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the BigDictSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the BigDictSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the BigDictSet.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            var hash = m_hfun(key);\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the BigDictSet.\n        /// </summary>\n        public bool Add(TKey key, long hash)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the BigDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            var hash = m_hfun(key);\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the BigDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the BigDictSet.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the BigDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the BigDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            return TryRemove(key, hash);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyLong<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyLong<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyLong<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyLong<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            var array = new TKey[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextHashKeyLong<TKey>));\n            m_extraArray.Set(default(HashKeyNextLong<TKey>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(TKey[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as TKey[];\n            if (typedArray != null)\n                CopyTo(typedArray, (long)index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the BigDictSet to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentBigDictSet<TKey> AsConcurrent()\n        {\n            return new ConcurrentBigDictSet<TKey>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<TKey> Members\n\n        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<TKey>\n        {\n            readonly BigDictSet<TKey> m_dict;\n            long m_index;\n            long m_extraIndex;\n            TKey m_current;\n\n            public Enumerator(BigDictSet<TKey> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(TKey);\n            }\n\n            public readonly TKey Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = fa[m_index].Item.Key;\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = ea[m_extraIndex].Item.Key;\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(TKey);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                HashKeyNextLong<TKey>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizesLong[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizesLong[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyLong<TKey> item,\n                NextHashKeyLong<TKey>[] firstArray,\n                ulong capacity,\n                ref HashKeyNextLong<TKey>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyLong<TKey>[newCapacity];\n            var extraArray = new HashKeyNextLong<TKey>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.LongLength / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region LongDict<TValue>\n\n    /// <summary>\n    /// A LongDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class LongDict<TValue>\n            : ICountableDict, IDict<long, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<long, TValue>>\n    {\n        private ulong m_capacity;\n        private NextLongValue<TValue>[] m_firstArray;\n        private LongValueNext<TValue>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a LongDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// LongDict acts as a stack for all items with the same key.\n        /// </summary>\n        public LongDict(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a LongDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// LongDict acts as a stack for all items with the same key.\n        /// </summary>\n        public LongDict(long initialCapacity)\n            : this(System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (ulong)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a LongDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// LongDict acts as a stack for all items with the same key.\n        /// </summary>\n        public LongDict(long initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (ulong)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a LongDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// LongDict acts as a stack for all items with the same key.\n        /// </summary>\n        public LongDict(IEnumerable<KeyValuePair<long, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private LongDict(\n                ulong firstCapacity, ulong extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextLongValue<TValue>[m_capacity];\n            m_extraArray = new LongValueNext<TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the LongDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the LongDict\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the LongDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<KeyValuePair<long, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<long> Keys\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(long); } }\n\n        /// <summary>\n        /// Returns all values in the LongDict.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Value;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Value;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the LongDict.\n        /// </summary>\n        public IEnumerable<KeyValuePair<long, TValue>> KeyValuePairs\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return new KeyValuePair<long, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    while (ei > 0)\n                    {\n                        yield return new KeyValuePair<long, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the LongDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new LongDict in the order they are returned.\n        /// </summary>\n        public IEnumerable<KeyValuePair<long, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                var stack = new Stack<long>();\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        yield return new KeyValuePair<long, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    }\n                    yield return new KeyValuePair<long, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the LongDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[long key]\n        {\n            get\n            {\n                var hash = key;\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Key == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Key == hash)\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Key == hash)\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the LongDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the LongDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((long)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the LongDict.\n        /// </summary>\n        public void Add(long key, TValue value)\n        {\n            var hash = key;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key == hash)\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the LongDict.\n        /// </summary>\n        public bool TryAdd(long key, TValue value)\n        {\n            var hash = key;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the LongDict.\n        /// </summary>\n        public void Add(KeyValuePair<long, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the LongDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<long, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the LongDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(long key)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the LongDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(long key)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the LongDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(long key, TValue value)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the LongDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<long, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the LongDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(long key)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the LongDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(long key, Func<long, TValue> creator)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        TValue AddCreated(long key, long hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Key == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(long key, TValue defaultValue)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(long key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(long key, out TValue value)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(long key)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Key == hash)\n                yield return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    yield return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values.\n        /// Should be preferred over Values enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValueEnumerator GetValuesEnumerator()\n        {\n            return new ValueEnumerator(this);\n        }\n\n        public struct ValueEnumerator : IEnumerator<TValue>\n        {\n            LongDict<TValue>.Enumerator m_inner;\n\n            public ValueEnumerator(LongDict<TValue> dict)\n            {\n                m_inner = dict.GetEnumerator();\n            }\n\n            public TValue Current => m_inner.Current.Value;\n\n            object IEnumerator.Current => Current;\n\n            public void Dispose() => m_inner.Dispose();\n\n            public bool MoveNext() => m_inner.MoveNext();\n\n            public void Reset() => m_inner.Reset();\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values with key. It is only useful\n        /// if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// Should be preferred over ValuesWithKey enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValuesWithKeyEnumerator GetValuesWithKeyEnumerator(long key)\n        {\n            return new ValuesWithKeyEnumerator(this, key);\n        }\n\n        public struct ValuesWithKeyEnumerator : IEnumerator<TValue>\n        {\n            readonly LongDict<TValue> m_dict;\n            readonly long m_hash;\n            long m_extraIndex;\n            TValue m_current;\n\n            public ValuesWithKeyEnumerator(LongDict<TValue> dict, long key)\n            {\n                m_dict = dict;\n                m_hash = key;\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n\n            public readonly TValue Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex == int.MaxValue)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var fi = ((uint)m_hash) % m_dict.m_capacity;\n                    m_extraIndex = fa[fi].Next;\n                    if (m_extraIndex == 0) return false;\n                    if (fa[fi].Item.Key == m_hash)\n                    {\n                        m_current = fa[fi].Item.Value;\n                        return true;\n                    }\n                }\n                if (m_extraIndex > 0)\n                {\n                    var ea = m_dict.m_extraArray;\n                    do\n                    {\n                        var valid = ea[m_extraIndex].Item.Key == m_hash;\n                        if (valid) m_current = ea[m_extraIndex].Item.Value;\n                        m_extraIndex = ea[m_extraIndex].Next;\n                        if (valid) return true;\n                    } while (m_extraIndex > 0);\n                }\n\n                return false;\n            }\n\n            public void Reset()\n            {\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(long key, long skip)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the LongDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(long key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the LongDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(long key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the LongDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(long key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the LongDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<long, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(long key, out TValue value)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(LongValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(LongValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(LongValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key == hash)\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(LongValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(long key, TValue value)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(LongValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(LongValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(LongValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key == hash\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(LongValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public long[] KeysToArray()\n        {\n            var array = new long[m_count];\n            CopyKeysTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// </summary>\n        public KeyValuePair<long, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<long, TValue>[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextLongValue<TValue>));\n            m_extraArray.Set(default(LongValueNext<TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyKeysTo(long[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(KeyValuePair<long, TValue>[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<long, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<long, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as KeyValuePair<long, TValue>[];\n            if (typedArray != null)\n                CopyTo(typedArray, (long)index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the LongDict to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentLongDict<TValue> AsConcurrent()\n        {\n            return new ConcurrentLongDict<TValue>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<long, TValue>> Members\n\n        IEnumerator<KeyValuePair<long, TValue>> IEnumerable<KeyValuePair<long, TValue>>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<KeyValuePair<long, TValue>>\n        {\n            readonly LongDict<TValue> m_dict;\n            long m_index;\n            long m_extraIndex;\n            KeyValuePair<long, TValue> m_current;\n\n            public Enumerator(LongDict<TValue> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(KeyValuePair<long, TValue>);\n            }\n\n            public readonly KeyValuePair<long, TValue> Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = new KeyValuePair<long, TValue>(fa[m_index].Item.Key, fa[m_index].Item.Value);\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = new KeyValuePair<long, TValue>(ea[m_extraIndex].Item.Key, ea[m_extraIndex].Item.Value);\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default( KeyValuePair<long, TValue>);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                LongValueNext<TValue>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                LongValue<TValue> item,\n                NextLongValue<TValue>[] firstArray,\n                ulong capacity,\n                ref LongValueNext<TValue>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Key) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextLongValue<TValue>[newCapacity];\n            var extraArray = new LongValueNext<TValue>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region LongSet\n\n    /// <summary>\n    /// A LongSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class LongSet\n            : ICountableDictSet, IDictSet<long>,\n              IEnumerable, IEnumerable<long>\n    {\n        private ulong m_capacity;\n        private NextLong[] m_firstArray;\n        private LongNext[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a LongSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public LongSet()\n            : this(DictConstant.PrimeSizes[0], (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a LongSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public LongSet(long initialCapacity)\n            : this(System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a LongSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public LongSet(IEnumerable<long> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (ulong)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private LongSet(\n                ulong firstCapacity, ulong extraCapacity)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextLong[m_capacity];\n            m_extraArray = new LongNext[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the LongSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the LongSet\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the LongSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<long> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<long> Keys\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(long); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the LongSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the LongSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((long)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the LongSet.\n        /// </summary>\n        public bool Add(long key)\n        {\n            var hash = key;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the LongSet.\n        /// </summary>\n        public bool TryAdd(long key)\n        {\n            var hash = key;\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the LongSet.\n        /// </summary>\n        public void AddRange(IEnumerable<long> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the LongSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(long key)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the LongSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(long key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(long key)\n        {\n            var hash = key;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item == hash)\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(long);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(long);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item == hash)\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(long);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item == hash)\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(long);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public long[] ToArray()\n        {\n            var array = new long[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextLong));\n            m_extraArray.Set(default(LongNext));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(long[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as long[];\n            if (typedArray != null)\n                CopyTo(typedArray, (long)index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the LongSet to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentLongSet AsConcurrent()\n        {\n            return new ConcurrentLongSet(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<long> Members\n\n        IEnumerator<long> IEnumerable<long>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<long>\n        {\n            readonly LongSet m_dict;\n            long m_index;\n            long m_extraIndex;\n            long m_current;\n\n            public Enumerator(LongSet dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(long);\n            }\n\n            public readonly long Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = fa[m_index].Item;\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = ea[m_extraIndex].Item;\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(long);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                LongNext[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                long item,\n                NextLong[] firstArray,\n                ulong capacity,\n                ref LongNext[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextLong[newCapacity];\n            var extraArray = new LongNext[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentDict<TKey, TValue>\n\n    /// <summary>\n    /// A ConcurrentDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentDict<TKey, TValue>\n    {\n        private readonly Dict<TKey, TValue> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentDict can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentDict(Dict<TKey, TValue> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return m_dict.Count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentDict.\n        /// </summary>\n        public Dict<TKey, TValue> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the ConcurrentDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                Monitor.Enter(this); try { return m_dict[key]; } finally { Monitor.Exit(this); }\n            }\n            set\n            {\n                Monitor.Enter(this); try { m_dict[key] = value; } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the ConcurrentDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentDict.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentDict.\n        /// </summary>\n        public void Add(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentDict.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentDict.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied item to the ConcurrentDict.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied items to the ConcurrentDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, int hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Contains(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            return m_dict.ContainsValue(value);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, int hash, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, hash, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, int hash, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, int hash, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, int skip)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.ValueWithKeySkip(key, skip);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the ConcurrentDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetAndRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the ConcurrentDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            return m_dict.KeysToArray();\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            return m_dict.ValuesToArray();\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyKeysTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyValuesTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)\n        {\n            Monitor.Enter(this); try { m_dict.CopyTo(array, index); } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentDictSet<TKey>\n\n    /// <summary>\n    /// A ConcurrentDictSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentDictSet<TKey>\n    {\n        private readonly DictSet<TKey> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentDictSet can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentDictSet(DictSet<TKey> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return m_dict.Count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentDictSet.\n        /// </summary>\n        public DictSet<TKey> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the ConcurrentDictSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentDictSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentDictSet.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentDictSet.\n        /// </summary>\n        public bool Add(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the ConcurrentDictSet.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(TKey[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentIntDict<TValue>\n\n    /// <summary>\n    /// A ConcurrentIntDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentIntDict<TValue>\n    {\n        private readonly IntDict<TValue> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentIntDict can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentIntDict(IntDict<TValue> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentIntDict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return m_dict.Count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentIntDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentIntDict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentIntDict.\n        /// </summary>\n        public IntDict<TValue> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the ConcurrentIntDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[int key]\n        {\n            get\n            {\n                Monitor.Enter(this); try { return m_dict[key]; } finally { Monitor.Exit(this); }\n            }\n            set\n            {\n                Monitor.Enter(this); try { m_dict[key] = value; } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the ConcurrentIntDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentIntDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((int)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentIntDict.\n        /// </summary>\n        public void Add(int key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentIntDict.\n        /// </summary>\n        public bool TryAdd(int key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied item to the ConcurrentIntDict.\n        /// </summary>\n        public void Add(KeyValuePair<int, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied items to the ConcurrentIntDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<int, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentIntDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(int key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentIntDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(int key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentIntDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(int key, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentIntDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<int, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Contains(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentIntDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            return m_dict.ContainsValue(value);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(int key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentIntDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(int key, Func<int, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(int key, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(int key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(int key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(int key, int skip)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.ValueWithKeySkip(key, skip);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the ConcurrentIntDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(int key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetAndRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentIntDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(int key)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentIntDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(int key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the ConcurrentIntDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<int, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(int key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(int key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public int[] KeysToArray()\n        {\n            return m_dict.KeysToArray();\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            return m_dict.ValuesToArray();\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<int, TValue>[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(int[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyKeysTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyValuesTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<int, TValue>[] array, int index)\n        {\n            Monitor.Enter(this); try { m_dict.CopyTo(array, index); } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentIntSet\n\n    /// <summary>\n    /// A ConcurrentIntSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentIntSet\n    {\n        private readonly IntSet m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentIntSet can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentIntSet(IntSet dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentIntSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return m_dict.Count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentIntSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentIntSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentIntSet.\n        /// </summary>\n        public IntSet NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the ConcurrentIntSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentIntSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((int)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentIntSet.\n        /// </summary>\n        public bool Add(int key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentIntSet.\n        /// </summary>\n        public bool TryAdd(int key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the ConcurrentIntSet.\n        /// </summary>\n        public void AddRange(IEnumerable<int> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentIntSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(int key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentIntSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(int key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(int key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public int[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(int[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentSymbolDict<TValue>\n\n    /// <summary>\n    /// A ConcurrentSymbolDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentSymbolDict<TValue>\n    {\n        private readonly SymbolDict<TValue> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentSymbolDict can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentSymbolDict(SymbolDict<TValue> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentSymbolDict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return m_dict.Count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentSymbolDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentSymbolDict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentSymbolDict.\n        /// </summary>\n        public SymbolDict<TValue> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the ConcurrentSymbolDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[Symbol key]\n        {\n            get\n            {\n                Monitor.Enter(this); try { return m_dict[key]; } finally { Monitor.Exit(this); }\n            }\n            set\n            {\n                Monitor.Enter(this); try { m_dict[key] = value; } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the ConcurrentSymbolDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentSymbolDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((Symbol)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentSymbolDict.\n        /// </summary>\n        public void Add(Symbol key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentSymbolDict.\n        /// </summary>\n        public bool TryAdd(Symbol key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Adds the supplied item to the ConcurrentSymbolDict. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(string key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key.ToSymbol(), value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied item to the ConcurrentSymbolDict. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(KeyValuePair<string, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key.ToSymbol(), item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied item to the ConcurrentSymbolDict.\n        /// </summary>\n        public void Add(KeyValuePair<Symbol, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied items to the ConcurrentSymbolDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<Symbol, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentSymbolDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(Symbol key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentSymbolDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(Symbol key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentSymbolDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(Symbol key, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentSymbolDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<Symbol, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Contains(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentSymbolDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            return m_dict.ContainsValue(value);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(Symbol key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentSymbolDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(Symbol key, Func<Symbol, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(Symbol key, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(Symbol key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(Symbol key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(Symbol key, int skip)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.ValueWithKeySkip(key, skip);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the ConcurrentSymbolDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(Symbol key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetAndRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentSymbolDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(Symbol key)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentSymbolDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(Symbol key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the ConcurrentSymbolDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<Symbol, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(Symbol key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(Symbol key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public Symbol[] KeysToArray()\n        {\n            return m_dict.KeysToArray();\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            return m_dict.ValuesToArray();\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<Symbol, TValue>[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(Symbol[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyKeysTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyValuesTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<Symbol, TValue>[] array, int index)\n        {\n            Monitor.Enter(this); try { m_dict.CopyTo(array, index); } finally { Monitor.Exit(this); }\n        }\n\n        public void Add<TType>(TypedSymbol<TType> key, TType value)\n            where TType : TValue\n        {\n            this.Add(key.Symbol, value);\n        }\n\n        public bool Contains<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return Contains(key.Symbol);\n        }\n\n        public bool ContainsKey<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return ContainsKey(key.Symbol);\n        }\n\n        public TType Get<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return (TType)this[key.Symbol];\n        }\n\n        public TType Get<TType>(TypedSymbol<TType> key, TType defaultValue)\n            where TType : TValue\n        {\n            TType value;\n            if (TryGetValue(key, out value)) return value;\n            return defaultValue;\n        }\n\n        public TType GetOrDefault<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            TType value;\n            if (TryGetValue(key, out value)) return value;\n            return default(TType);\n        }\n\n        public bool Remove<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return Remove(key.Symbol);\n        }\n\n        public void Set<TType>(TypedSymbol<TType> key, TType value)\n            where TType : TValue\n        {\n            this[key.Symbol] = value;\n        }\n\n        public bool TryGetValue<TType>(TypedSymbol<TType> key, out TType value)\n            where TType : TValue\n        {\n            TValue val;\n            if (TryGetValue(key.Symbol, out val)) { value = (TType)val; return true; }\n            value = default(TType);\n            return false;\n        }\n\n        public TType GetAs<TType>(Symbol key)\n            where TType : TValue\n        {\n            return (TType)this[key];\n        }\n\n        public TType GetAs<TType>(Symbol key, TType defaultValue)\n            where TType : TValue\n        {\n            TValue value;\n            if (TryGetValue(key, out value)) return (TType)value;\n            return defaultValue;\n        }\n\n        public TType GetAsOrDefault<TType>(Symbol key)\n            where TType : TValue\n        {\n            TValue value;\n            if (TryGetValue(key, out value)) return (TType)value;\n            return default(TType);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentSymbolSet\n\n    /// <summary>\n    /// A ConcurrentSymbolSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentSymbolSet\n    {\n        private readonly SymbolSet m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentSymbolSet can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentSymbolSet(SymbolSet dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentSymbolSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return m_dict.Count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentSymbolSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentSymbolSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentSymbolSet.\n        /// </summary>\n        public SymbolSet NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the ConcurrentSymbolSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentSymbolSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((Symbol)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentSymbolSet.\n        /// </summary>\n        public bool Add(Symbol key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentSymbolSet.\n        /// </summary>\n        public bool TryAdd(Symbol key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Adds the supplied item to the ConcurrentSymbolSet. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(string key)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key.ToSymbol());\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the ConcurrentSymbolSet.\n        /// </summary>\n        public void AddRange(IEnumerable<Symbol> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentSymbolSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(Symbol key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentSymbolSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(Symbol key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(Symbol key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public Symbol[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(Symbol[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentBigDict<TKey, TValue>\n\n    /// <summary>\n    /// A ConcurrentBigDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentBigDict<TKey, TValue>\n    {\n        private readonly BigDict<TKey, TValue> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentBigDict can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentBigDict(BigDict<TKey, TValue> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentBigDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentBigDict\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentBigDict.\n        /// </summary>\n        public BigDict<TKey, TValue> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the ConcurrentBigDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                Monitor.Enter(this); try { return m_dict[key]; } finally { Monitor.Exit(this); }\n            }\n            set\n            {\n                Monitor.Enter(this); try { m_dict[key] = value; } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the ConcurrentBigDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentBigDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentBigDict.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentBigDict.\n        /// </summary>\n        public void Add(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentBigDict.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentBigDict.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied item to the ConcurrentBigDict.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied items to the ConcurrentBigDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, long hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Contains(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            return m_dict.ContainsValue(value);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentBigDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentBigDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, long hash, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, hash, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, long hash, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, long hash, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, long skip)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.ValueWithKeySkip(key, skip);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the ConcurrentBigDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetAndRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentBigDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentBigDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentBigDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentBigDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the ConcurrentBigDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            return m_dict.KeysToArray();\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            return m_dict.ValuesToArray();\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyKeysTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyValuesTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, long index)\n        {\n            Monitor.Enter(this); try { m_dict.CopyTo(array, index); } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentBigDictSet<TKey>\n\n    /// <summary>\n    /// A ConcurrentBigDictSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentBigDictSet<TKey>\n    {\n        private readonly BigDictSet<TKey> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentBigDictSet can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentBigDictSet(BigDictSet<TKey> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentBigDictSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentBigDictSet\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentBigDictSet.\n        /// </summary>\n        public BigDictSet<TKey> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the ConcurrentBigDictSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentBigDictSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentBigDictSet.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentBigDictSet.\n        /// </summary>\n        public bool Add(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentBigDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentBigDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the ConcurrentBigDictSet.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentBigDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentBigDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(TKey[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentLongDict<TValue>\n\n    /// <summary>\n    /// A ConcurrentLongDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentLongDict<TValue>\n    {\n        private readonly LongDict<TValue> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentLongDict can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentLongDict(LongDict<TValue> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentLongDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentLongDict\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentLongDict.\n        /// </summary>\n        public LongDict<TValue> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the ConcurrentLongDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[long key]\n        {\n            get\n            {\n                Monitor.Enter(this); try { return m_dict[key]; } finally { Monitor.Exit(this); }\n            }\n            set\n            {\n                Monitor.Enter(this); try { m_dict[key] = value; } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the ConcurrentLongDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentLongDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((long)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentLongDict.\n        /// </summary>\n        public void Add(long key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentLongDict.\n        /// </summary>\n        public bool TryAdd(long key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied item to the ConcurrentLongDict.\n        /// </summary>\n        public void Add(KeyValuePair<long, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied items to the ConcurrentLongDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<long, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentLongDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(long key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentLongDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(long key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentLongDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(long key, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentLongDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<long, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Contains(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentLongDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            return m_dict.ContainsValue(value);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(long key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentLongDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(long key, Func<long, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(long key, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(long key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(long key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(long key, long skip)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.ValueWithKeySkip(key, skip);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the ConcurrentLongDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(long key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetAndRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentLongDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(long key)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentLongDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(long key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the ConcurrentLongDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<long, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(long key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(long key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public long[] KeysToArray()\n        {\n            return m_dict.KeysToArray();\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            return m_dict.ValuesToArray();\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<long, TValue>[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(long[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyKeysTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyValuesTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<long, TValue>[] array, long index)\n        {\n            Monitor.Enter(this); try { m_dict.CopyTo(array, index); } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentLongSet\n\n    /// <summary>\n    /// A ConcurrentLongSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentLongSet\n    {\n        private readonly LongSet m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentLongSet can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentLongSet(LongSet dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentLongSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentLongSet\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentLongSet.\n        /// </summary>\n        public LongSet NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the ConcurrentLongSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentLongSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((long)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentLongSet.\n        /// </summary>\n        public bool Add(long key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentLongSet.\n        /// </summary>\n        public bool TryAdd(long key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the ConcurrentLongSet.\n        /// </summary>\n        public void AddRange(IEnumerable<long> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentLongSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(long key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentLongSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(long key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(long key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public long[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(long[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentDict<TKey, TValue>\n\n    /// <summary>\n    /// A FastConcurrentDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentDict<TKey, TValue>\n            : IIntCountable, ICountableDict, IDict<TKey, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>\n    {\n        private long m_version;\n        private uint m_capacity;\n        private NextHashKeyValue<TKey, TValue>[] m_firstArray;\n        private HashKeyValueNext<TKey, TValue>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentDict(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentDict(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentDict(int initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentDict(IEnumerable<KeyValuePair<TKey, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentDict(\n                uint firstCapacity, uint extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyValue<TKey, TValue>[m_capacity];\n            m_extraArray = new HashKeyValueNext<TKey, TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        /// <summary>\n        /// Returns all values in the FastConcurrentDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var v = m_firstArray[fi].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        v = m_extraArray[ei].Item.Value;\n                        Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var kvp = new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        kvp = new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new FastConcurrentDict in the order they are returned.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                var stack = new Stack<int>();\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    var kvp = default(KeyValuePair<TKey, TValue>);\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        kvp = new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                    }\n                    kvp = new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the FastConcurrentDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                var hash = key.GetHashCode();\n                Monitor.Enter(this); try {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                } finally { Monitor.Exit(this); }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key.GetHashCode();\n                Monitor.Enter(this); try { ++m_version;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Hash == hash\n                        && key.Equals(m_firstArray[fi].Item.Key))\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Hash == hash\n                            && key.Equals(m_extraArray[ei].Item.Key))\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the FastConcurrentDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentDict.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentDict.\n        /// </summary>\n        public void Add(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentDict.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentDict.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the FastConcurrentDict.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the FastConcurrentDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        TValue AddCreated(TKey key, int hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    ++m_version;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_version;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, int hash, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, int hash, TValue defaultValue)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, int hash, out TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try { var version = m_version;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                var v = m_firstArray[fi].Item.Value;\n                Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                if (version != m_version)\n                    throw new ConcurrentDataModifiedException();\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    var v = m_extraArray[ei].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, int skip)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the FastConcurrentDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            TValue value;\n            return TryRemove(key, hash, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash, TValue value)\n        {\n            return TryRemove(key, hash, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the FastConcurrentDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, out TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            var array = new TKey[m_count];\n            CopyKeysTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<TKey, TValue>[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextHashKeyValue<TKey, TValue>));\n            m_extraArray.Set(default(HashKeyValueNext<TKey, TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<TKey, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<TKey, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey, TValue>> Members\n\n        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                HashKeyValueNext<TKey, TValue>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyValue<TKey, TValue> item,\n                NextHashKeyValue<TKey, TValue>[] firstArray,\n                uint capacity,\n                ref HashKeyValueNext<TKey, TValue>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyValue<TKey, TValue>[newCapacity];\n            var extraArray = new HashKeyValueNext<TKey, TValue>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentDictSet<TKey>\n\n    /// <summary>\n    /// A FastConcurrentDictSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentDictSet<TKey>\n            : IIntCountable, ICountableDictSet, IDictSet<TKey>,\n              IEnumerable, IEnumerable<TKey>\n    {\n        private long m_version;\n        private uint m_capacity;\n        private NextHashKey<TKey>[] m_firstArray;\n        private HashKeyNext<TKey>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentDictSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public FastConcurrentDictSet()\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDictSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public FastConcurrentDictSet(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDictSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public FastConcurrentDictSet(IEnumerable<TKey> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentDictSet(\n                uint firstCapacity, uint extraCapacity)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKey<TKey>[m_capacity];\n            m_extraArray = new HashKeyNext<TKey>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentDictSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<TKey> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the FastConcurrentDictSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentDictSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentDictSet.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentDictSet.\n        /// </summary>\n        public bool Add(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the FastConcurrentDictSet.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            return TryRemove(key, hash);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKey<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKey<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKey<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKey<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            var array = new TKey[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextHashKey<TKey>));\n            m_extraArray.Set(default(HashKeyNext<TKey>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(TKey[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<TKey> Members\n\n        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                HashKeyNext<TKey>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKey<TKey> item,\n                NextHashKey<TKey>[] firstArray,\n                uint capacity,\n                ref HashKeyNext<TKey>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKey<TKey>[newCapacity];\n            var extraArray = new HashKeyNext<TKey>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentIntDict<TValue>\n\n    /// <summary>\n    /// A FastConcurrentIntDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentIntDict<TValue>\n            : IIntCountable, ICountableDict, IDict<int, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<int, TValue>>\n    {\n        private long m_version;\n        private uint m_capacity;\n        private NextIntValue<TValue>[] m_firstArray;\n        private IntValueNext<TValue>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentIntDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentIntDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentIntDict(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentIntDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentIntDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentIntDict(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentIntDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentIntDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentIntDict(int initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentIntDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentIntDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentIntDict(IEnumerable<KeyValuePair<int, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentIntDict(\n                uint firstCapacity, uint extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextIntValue<TValue>[m_capacity];\n            m_extraArray = new IntValueNext<TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentIntDict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentIntDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentIntDict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentIntDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<KeyValuePair<int, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<int> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(int); } }\n\n        /// <summary>\n        /// Returns all values in the FastConcurrentIntDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var v = m_firstArray[fi].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        v = m_extraArray[ei].Item.Value;\n                        Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentIntDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<int, TValue>> KeyValuePairs\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var kvp = new KeyValuePair<int, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        kvp = new KeyValuePair<int, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentIntDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new FastConcurrentIntDict in the order they are returned.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<int, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                var stack = new Stack<int>();\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    var kvp = default(KeyValuePair<int, TValue>);\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        kvp = new KeyValuePair<int, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                    }\n                    kvp = new KeyValuePair<int, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the FastConcurrentIntDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[int key]\n        {\n            get\n            {\n                var hash = key;\n                Monitor.Enter(this); try {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Key == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                } finally { Monitor.Exit(this); }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key;\n                Monitor.Enter(this); try { ++m_version;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Key == hash)\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Key == hash)\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the FastConcurrentIntDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentIntDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((int)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentIntDict.\n        /// </summary>\n        public void Add(int key, TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key == hash)\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentIntDict.\n        /// </summary>\n        public bool TryAdd(int key, TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the FastConcurrentIntDict.\n        /// </summary>\n        public void Add(KeyValuePair<int, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the FastConcurrentIntDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<int, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentIntDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(int key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentIntDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(int key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentIntDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(int key, TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentIntDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<int, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentIntDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(int key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentIntDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(int key, Func<int, TValue> creator)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        TValue AddCreated(int key, int hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    ++m_version;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Key == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_version;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(int key, TValue defaultValue)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(int key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(int key, out TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(int key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try { var version = m_version;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                var v = m_firstArray[fi].Item.Value;\n                Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                if (version != m_version)\n                    throw new ConcurrentDataModifiedException();\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    var v = m_extraArray[ei].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(int key, int skip)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the FastConcurrentIntDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(int key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentIntDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(int key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentIntDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(int key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the FastConcurrentIntDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<int, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(int key, out TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(IntValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(IntValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(IntValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key == hash)\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(IntValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(int key, TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(IntValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(IntValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(IntValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key == hash\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(IntValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public int[] KeysToArray()\n        {\n            var array = new int[m_count];\n            CopyKeysTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<int, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<int, TValue>[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextIntValue<TValue>));\n            m_extraArray.Set(default(IntValueNext<TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(int[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<int, TValue>[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<int, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<int, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<int, TValue>> Members\n\n        IEnumerator<KeyValuePair<int, TValue>> IEnumerable<KeyValuePair<int, TValue>>.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                IntValueNext<TValue>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                IntValue<TValue> item,\n                NextIntValue<TValue>[] firstArray,\n                uint capacity,\n                ref IntValueNext<TValue>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Key) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextIntValue<TValue>[newCapacity];\n            var extraArray = new IntValueNext<TValue>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentIntSet\n\n    /// <summary>\n    /// A FastConcurrentIntSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentIntSet\n            : IIntCountable, ICountableDictSet, IDictSet<int>,\n              IEnumerable, IEnumerable<int>\n    {\n        private long m_version;\n        private uint m_capacity;\n        private NextInt[] m_firstArray;\n        private IntNext[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentIntSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public FastConcurrentIntSet()\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentIntSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public FastConcurrentIntSet(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentIntSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public FastConcurrentIntSet(IEnumerable<int> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentIntSet(\n                uint firstCapacity, uint extraCapacity)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextInt[m_capacity];\n            m_extraArray = new IntNext[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentIntSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentIntSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentIntSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentIntSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<int> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<int> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(int); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the FastConcurrentIntSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentIntSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((int)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentIntSet.\n        /// </summary>\n        public bool Add(int key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentIntSet.\n        /// </summary>\n        public bool TryAdd(int key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the FastConcurrentIntSet.\n        /// </summary>\n        public void AddRange(IEnumerable<int> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentIntSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(int key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentIntSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(int key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(int key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item == hash)\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(int);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(int);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item == hash)\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(int);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item == hash)\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(int);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public int[] ToArray()\n        {\n            var array = new int[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextInt));\n            m_extraArray.Set(default(IntNext));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(int[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<int> Members\n\n        IEnumerator<int> IEnumerable<int>.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                IntNext[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                int item,\n                NextInt[] firstArray,\n                uint capacity,\n                ref IntNext[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextInt[newCapacity];\n            var extraArray = new IntNext[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentSymbolDict<TValue>\n\n    /// <summary>\n    /// A FastConcurrentSymbolDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentSymbolDict<TValue>\n            : IIntCountable, ICountableDict, IDict<Symbol, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<Symbol, TValue>>\n    {\n        private long m_version;\n        private uint m_capacity;\n        private NextSymbolValue<TValue>[] m_firstArray;\n        private SymbolValueNext<TValue>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentSymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentSymbolDict(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentSymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentSymbolDict(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentSymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentSymbolDict(int initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentSymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentSymbolDict(IEnumerable<KeyValuePair<Symbol, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolDict and initialize to contain the supplied items.\n        /// Note hat this incurs the overhead of converting all string keys\n        /// to symbols.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentSymbolDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentSymbolDict(IEnumerable<KeyValuePair<string, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentSymbolDict(\n                uint firstCapacity, uint extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextSymbolValue<TValue>[m_capacity];\n            m_extraArray = new SymbolValueNext<TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentSymbolDict.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentSymbolDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentSymbolDict\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentSymbolDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<KeyValuePair<Symbol, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<Symbol> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(Symbol); } }\n\n        /// <summary>\n        /// Returns all values in the FastConcurrentSymbolDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var v = m_firstArray[fi].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        v = m_extraArray[ei].Item.Value;\n                        Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentSymbolDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairs\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var kvp = new KeyValuePair<Symbol, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        kvp = new KeyValuePair<Symbol, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentSymbolDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new FastConcurrentSymbolDict in the order they are returned.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                var stack = new Stack<int>();\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    var kvp = default(KeyValuePair<Symbol, TValue>);\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        kvp = new KeyValuePair<Symbol, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                    }\n                    kvp = new KeyValuePair<Symbol, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the FastConcurrentSymbolDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[Symbol key]\n        {\n            get\n            {\n                var hash = key.Id;\n                Monitor.Enter(this); try {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Key.Id == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key.Id == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                } finally { Monitor.Exit(this); }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key.Id;\n                Monitor.Enter(this); try { ++m_version;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Key.Id == hash)\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Key.Id == hash)\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the FastConcurrentSymbolDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentSymbolDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((Symbol)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentSymbolDict.\n        /// </summary>\n        public void Add(Symbol key, TValue value)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key.Id == hash)\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key.Id == hash)\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentSymbolDict.\n        /// </summary>\n        public bool TryAdd(Symbol key, TValue value)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key.Id == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key.Id == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Adds the supplied item to the FastConcurrentSymbolDict. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(string key, TValue value)\n        {\n            Add(key.ToSymbol(), value);\n        }\n\n        /// <summary>\n        /// Add the supplied item to the FastConcurrentSymbolDict. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(KeyValuePair<string, TValue> item)\n        {\n            Add(item.Key.ToSymbol(), item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied item to the FastConcurrentSymbolDict.\n        /// </summary>\n        public void Add(KeyValuePair<Symbol, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the FastConcurrentSymbolDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<Symbol, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentSymbolDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(Symbol key)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentSymbolDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(Symbol key)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentSymbolDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(Symbol key, TValue value)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key.Id == hash\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentSymbolDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<Symbol, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentSymbolDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(Symbol key)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentSymbolDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(Symbol key, Func<Symbol, TValue> creator)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        TValue AddCreated(Symbol key, int hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    ++m_version;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Key.Id == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key.Id == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_version;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(Symbol key, TValue defaultValue)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Key.Id == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(Symbol key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(Symbol key, out TValue value)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Key.Id == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(Symbol key)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try { var version = m_version;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Key.Id == hash)\n            {\n                var v = m_firstArray[fi].Item.Value;\n                Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                if (version != m_version)\n                    throw new ConcurrentDataModifiedException();\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                {\n                    var v = m_extraArray[ei].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(Symbol key, int skip)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key.Id == hash)\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the FastConcurrentSymbolDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(Symbol key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentSymbolDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(Symbol key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentSymbolDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(Symbol key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the FastConcurrentSymbolDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<Symbol, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(Symbol key, out TValue value)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Key.Id == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(SymbolValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(SymbolValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(SymbolValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key.Id == hash)\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(SymbolValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(Symbol key, TValue value)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key.Id == hash\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(SymbolValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(SymbolValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key.Id == hash\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(SymbolValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key.Id == hash\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(SymbolValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public Symbol[] KeysToArray()\n        {\n            var array = new Symbol[m_count];\n            CopyKeysTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<Symbol, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<Symbol, TValue>[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextSymbolValue<TValue>));\n            m_extraArray.Set(default(SymbolValueNext<TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(Symbol[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<Symbol, TValue>[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<Symbol, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<Symbol, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        public void Add<TType>(TypedSymbol<TType> key, TType value)\n            where TType : TValue\n        {\n            this.Add(key.Symbol, value);\n        }\n\n        public bool Contains<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return Contains(key.Symbol);\n        }\n\n        public bool ContainsKey<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return ContainsKey(key.Symbol);\n        }\n\n        public TType Get<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return (TType)this[key.Symbol];\n        }\n\n        public TType Get<TType>(TypedSymbol<TType> key, TType defaultValue)\n            where TType : TValue\n        {\n            TType value;\n            if (TryGetValue(key, out value)) return value;\n            return defaultValue;\n        }\n\n        public TType GetOrDefault<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            TType value;\n            if (TryGetValue(key, out value)) return value;\n            return default(TType);\n        }\n\n        public bool Remove<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return Remove(key.Symbol);\n        }\n\n        public void Set<TType>(TypedSymbol<TType> key, TType value)\n            where TType : TValue\n        {\n            this[key.Symbol] = value;\n        }\n\n        public bool TryGetValue<TType>(TypedSymbol<TType> key, out TType value)\n            where TType : TValue\n        {\n            TValue val;\n            if (TryGetValue(key.Symbol, out val)) { value = (TType)val; return true; }\n            value = default(TType);\n            return false;\n        }\n\n        public TType GetAs<TType>(Symbol key)\n            where TType : TValue\n        {\n            return (TType)this[key];\n        }\n\n        public TType GetAs<TType>(Symbol key, TType defaultValue)\n            where TType : TValue\n        {\n            TValue value;\n            if (TryGetValue(key, out value)) return (TType)value;\n            return defaultValue;\n        }\n\n        public TType GetAsOrDefault<TType>(Symbol key)\n            where TType : TValue\n        {\n            TValue value;\n            if (TryGetValue(key, out value)) return (TType)value;\n            return default(TType);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<Symbol, TValue>> Members\n\n        IEnumerator<KeyValuePair<Symbol, TValue>> IEnumerable<KeyValuePair<Symbol, TValue>>.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                SymbolValueNext<TValue>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                SymbolValue<TValue> item,\n                NextSymbolValue<TValue>[] firstArray,\n                uint capacity,\n                ref SymbolValueNext<TValue>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Key.Id) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextSymbolValue<TValue>[newCapacity];\n            var extraArray = new SymbolValueNext<TValue>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentSymbolSet\n\n    /// <summary>\n    /// A FastConcurrentSymbolSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentSymbolSet\n            : IIntCountable, ICountableDictSet, IDictSet<Symbol>,\n              IEnumerable, IEnumerable<Symbol>\n    {\n        private long m_version;\n        private uint m_capacity;\n        private NextSymbol[] m_firstArray;\n        private SymbolNext[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public FastConcurrentSymbolSet()\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public FastConcurrentSymbolSet(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public FastConcurrentSymbolSet(IEnumerable<Symbol> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Create a FastConcurrentSymbolSet and initialize to contain the supplied items.\n        /// Note hat this incurs the overhead of converting all string keys\n        /// to symbols.\n        /// </summary>\n        public FastConcurrentSymbolSet(IEnumerable<string> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentSymbolSet(\n                uint firstCapacity, uint extraCapacity)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextSymbol[m_capacity];\n            m_extraArray = new SymbolNext[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentSymbolSet.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentSymbolSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentSymbolSet\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentSymbolSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<Symbol> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<Symbol> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(Symbol); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the FastConcurrentSymbolSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentSymbolSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((Symbol)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentSymbolSet.\n        /// </summary>\n        public bool Add(Symbol key)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Id == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Id == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentSymbolSet.\n        /// </summary>\n        public bool TryAdd(Symbol key)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Id == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Id == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Adds the supplied item to the FastConcurrentSymbolSet. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(string key)\n        {\n            Add(key.ToSymbol());\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the FastConcurrentSymbolSet.\n        /// </summary>\n        public void AddRange(IEnumerable<Symbol> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentSymbolSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(Symbol key)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Id == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Id == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentSymbolSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(Symbol key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(Symbol key)\n        {\n            var hash = key.Id;\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Id == hash)\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(Symbol);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(Symbol);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Id == hash)\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(Symbol);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Id == hash)\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(Symbol);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public Symbol[] ToArray()\n        {\n            var array = new Symbol[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextSymbol));\n            m_extraArray.Set(default(SymbolNext));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(Symbol[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<Symbol> Members\n\n        IEnumerator<Symbol> IEnumerable<Symbol>.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                SymbolNext[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                Symbol item,\n                NextSymbol[] firstArray,\n                uint capacity,\n                ref SymbolNext[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Id) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextSymbol[newCapacity];\n            var extraArray = new SymbolNext[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentBigDict<TKey, TValue>\n\n    /// <summary>\n    /// A FastConcurrentBigDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentBigDict<TKey, TValue>\n            : ICountableDict, IDict<TKey, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>\n    {\n        private long m_version;\n        private readonly Func<TKey, long> m_hfun;\n        private ulong m_capacity;\n        private NextHashKeyValueLong<TKey, TValue>[] m_firstArray;\n        private HashKeyValueNextLong<TKey, TValue>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentBigDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentBigDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentBigDict(Func<TKey, long> hfun, bool stackDuplicateKeys = false)\n            : this(hfun, DictConstant.PrimeSizesLong[0], (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentBigDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentBigDict(Func<TKey, long> hfun, long initialCapacity)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentBigDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentBigDict(Func<TKey, long> hfun, long initialCapacity, bool stackDuplicateKeys)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentBigDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentBigDict(Func<TKey, long> hfun, IEnumerable<KeyValuePair<TKey, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(hfun, Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizesLong[0]), (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentBigDict(\n                Func<TKey, long> hfun, ulong firstCapacity, ulong extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_version = 0;\n            m_hfun = hfun;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizesLong[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizesLong[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyValueLong<TKey, TValue>[m_capacity];\n            m_extraArray = new HashKeyValueNextLong<TKey, TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentBigDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentBigDict\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentBigDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        /// <summary>\n        /// Returns all values in the FastConcurrentBigDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var v = m_firstArray[fi].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        v = m_extraArray[ei].Item.Value;\n                        Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentBigDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var kvp = new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        kvp = new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentBigDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new FastConcurrentBigDict in the order they are returned.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                var stack = new Stack<long>();\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    var kvp = default(KeyValuePair<TKey, TValue>);\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        kvp = new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                    }\n                    kvp = new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the FastConcurrentBigDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                var hash = m_hfun(key);\n                Monitor.Enter(this); try {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                } finally { Monitor.Exit(this); }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = m_hfun(key);\n                Monitor.Enter(this); try { ++m_version;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Hash == hash\n                        && key.Equals(m_firstArray[fi].Item.Key))\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Hash == hash\n                            && key.Equals(m_extraArray[ei].Item.Key))\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.LongLength;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the FastConcurrentBigDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentBigDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentBigDict.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentBigDict.\n        /// </summary>\n        public void Add(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentBigDict.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentBigDict.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the FastConcurrentBigDict.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the FastConcurrentBigDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentBigDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        TValue AddCreated(TKey key, long hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    ++m_version;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_version;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentBigDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, long hash, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, long hash, TValue defaultValue)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, long hash, out TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try { var version = m_version;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                var v = m_firstArray[fi].Item.Value;\n                Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                if (version != m_version)\n                    throw new ConcurrentDataModifiedException();\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    var v = m_extraArray[ei].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, long skip)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the FastConcurrentBigDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentBigDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentBigDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            TValue value;\n            return TryRemove(key, hash, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentBigDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentBigDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash, TValue value)\n        {\n            return TryRemove(key, hash, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the FastConcurrentBigDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, out TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            var array = new TKey[m_count];\n            CopyKeysTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<TKey, TValue>[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextHashKeyValueLong<TKey, TValue>));\n            m_extraArray.Set(default(HashKeyValueNextLong<TKey, TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<TKey, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<TKey, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey, TValue>> Members\n\n        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                HashKeyValueNextLong<TKey, TValue>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizesLong[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizesLong[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyValueLong<TKey, TValue> item,\n                NextHashKeyValueLong<TKey, TValue>[] firstArray,\n                ulong capacity,\n                ref HashKeyValueNextLong<TKey, TValue>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyValueLong<TKey, TValue>[newCapacity];\n            var extraArray = new HashKeyValueNextLong<TKey, TValue>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.LongLength / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentBigDictSet<TKey>\n\n    /// <summary>\n    /// A FastConcurrentBigDictSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentBigDictSet<TKey>\n            : ICountableDictSet, IDictSet<TKey>,\n              IEnumerable, IEnumerable<TKey>\n    {\n        private long m_version;\n        private readonly Func<TKey, long> m_hfun;\n        private ulong m_capacity;\n        private NextHashKeyLong<TKey>[] m_firstArray;\n        private HashKeyNextLong<TKey>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public FastConcurrentBigDictSet(Func<TKey, long> hfun)\n            : this(hfun, DictConstant.PrimeSizesLong[0], (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public FastConcurrentBigDictSet(Func<TKey, long> hfun, long initialCapacity)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public FastConcurrentBigDictSet(Func<TKey, long> hfun, IEnumerable<TKey> items)\n            : this(hfun, Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizesLong[0]), (ulong)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentBigDictSet(\n                Func<TKey, long> hfun, ulong firstCapacity, ulong extraCapacity)\n        {\n            m_version = 0;\n            m_hfun = hfun;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizesLong[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizesLong[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyLong<TKey>[m_capacity];\n            m_extraArray = new HashKeyNextLong<TKey>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentBigDictSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentBigDictSet\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentBigDictSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<TKey> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the FastConcurrentBigDictSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentBigDictSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentBigDictSet.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentBigDictSet.\n        /// </summary>\n        public bool Add(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentBigDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentBigDictSet.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the FastConcurrentBigDictSet.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentBigDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentBigDictSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            return TryRemove(key, hash);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyLong<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyLong<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyLong<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyLong<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            var array = new TKey[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextHashKeyLong<TKey>));\n            m_extraArray.Set(default(HashKeyNextLong<TKey>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(TKey[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<TKey> Members\n\n        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                HashKeyNextLong<TKey>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizesLong[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizesLong[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyLong<TKey> item,\n                NextHashKeyLong<TKey>[] firstArray,\n                ulong capacity,\n                ref HashKeyNextLong<TKey>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyLong<TKey>[newCapacity];\n            var extraArray = new HashKeyNextLong<TKey>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.LongLength / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentLongDict<TValue>\n\n    /// <summary>\n    /// A FastConcurrentLongDict is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentLongDict<TValue>\n            : ICountableDict, IDict<long, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<long, TValue>>\n    {\n        private long m_version;\n        private ulong m_capacity;\n        private NextLongValue<TValue>[] m_firstArray;\n        private LongValueNext<TValue>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentLongDict that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentLongDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentLongDict(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentLongDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentLongDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentLongDict(long initialCapacity)\n            : this(System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (ulong)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentLongDict that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentLongDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentLongDict(long initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (ulong)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentLongDict and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentLongDict acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentLongDict(IEnumerable<KeyValuePair<long, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentLongDict(\n                ulong firstCapacity, ulong extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextLongValue<TValue>[m_capacity];\n            m_extraArray = new LongValueNext<TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentLongDict\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentLongDict\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentLongDict. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<KeyValuePair<long, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<long> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(long); } }\n\n        /// <summary>\n        /// Returns all values in the FastConcurrentLongDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var v = m_firstArray[fi].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        v = m_extraArray[ei].Item.Value;\n                        Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentLongDict.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<long, TValue>> KeyValuePairs\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var kvp = new KeyValuePair<long, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        kvp = new KeyValuePair<long, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentLongDict, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new FastConcurrentLongDict in the order they are returned.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<long, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                var stack = new Stack<long>();\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    var kvp = default(KeyValuePair<long, TValue>);\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        kvp = new KeyValuePair<long, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                    }\n                    kvp = new KeyValuePair<long, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the FastConcurrentLongDict acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[long key]\n        {\n            get\n            {\n                var hash = key;\n                Monitor.Enter(this); try {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Key == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                } finally { Monitor.Exit(this); }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key;\n                Monitor.Enter(this); try { ++m_version;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Key == hash)\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Key == hash)\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the FastConcurrentLongDict. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentLongDict\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((long)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentLongDict.\n        /// </summary>\n        public void Add(long key, TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key == hash)\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentLongDict.\n        /// </summary>\n        public bool TryAdd(long key, TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Key == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the FastConcurrentLongDict.\n        /// </summary>\n        public void Add(KeyValuePair<long, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the FastConcurrentLongDict.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<long, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentLongDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(long key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentLongDict contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(long key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentLongDict contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(long key, TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentLongDict contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<long, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentLongDict contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(long key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentLongDict and returned.\n        /// </summary>\n        public TValue GetOrCreate(long key, Func<long, TValue> creator)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        TValue AddCreated(long key, long hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    ++m_version;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Key == hash)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Key == hash)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_version;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(long key, TValue defaultValue)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Key == hash)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(long key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(long key, out TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(long key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try { var version = m_version;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                var v = m_firstArray[fi].Item.Value;\n                Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                if (version != m_version)\n                    throw new ConcurrentDataModifiedException();\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    var v = m_extraArray[ei].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(long key, long skip)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the FastConcurrentLongDict and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(long key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentLongDict.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(long key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentLongDict. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(long key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the FastConcurrentLongDict.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<long, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(long key, out TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Key == hash)\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(LongValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(LongValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(LongValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key == hash)\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(LongValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(long key, TValue value)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Key == hash\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(LongValue<TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(LongValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Key == hash\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(LongValue<TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Key == hash\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(LongValue<TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public long[] KeysToArray()\n        {\n            var array = new long[m_count];\n            CopyKeysTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<long, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<long, TValue>[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextLongValue<TValue>));\n            m_extraArray.Set(default(LongValueNext<TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(long[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<long, TValue>[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<long, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<long, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<long, TValue>> Members\n\n        IEnumerator<KeyValuePair<long, TValue>> IEnumerable<KeyValuePair<long, TValue>>.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                LongValueNext<TValue>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                LongValue<TValue> item,\n                NextLongValue<TValue>[] firstArray,\n                ulong capacity,\n                ref LongValueNext<TValue>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Key) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextLongValue<TValue>[newCapacity];\n            var extraArray = new LongValueNext<TValue>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentLongSet\n\n    /// <summary>\n    /// A FastConcurrentLongSet is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentLongSet\n            : ICountableDictSet, IDictSet<long>,\n              IEnumerable, IEnumerable<long>\n    {\n        private long m_version;\n        private ulong m_capacity;\n        private NextLong[] m_firstArray;\n        private LongNext[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentLongSet that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public FastConcurrentLongSet()\n            : this(DictConstant.PrimeSizes[0], (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentLongSet that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public FastConcurrentLongSet(long initialCapacity)\n            : this(System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentLongSet and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public FastConcurrentLongSet(IEnumerable<long> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (ulong)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentLongSet(\n                ulong firstCapacity, ulong extraCapacity)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextLong[m_capacity];\n            m_extraArray = new LongNext[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentLongSet\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentLongSet\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentLongSet. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<long> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<long> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(long); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the FastConcurrentLongSet. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentLongSet\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((long)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentLongSet.\n        /// </summary>\n        public bool Add(long key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentLongSet.\n        /// </summary>\n        public bool TryAdd(long key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item == hash)\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item == hash)\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the FastConcurrentLongSet.\n        /// </summary>\n        public void AddRange(IEnumerable<long> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentLongSet contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(long key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item == hash)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item == hash)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentLongSet. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(long key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(long key)\n        {\n            var hash = key;\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item == hash)\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(long);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(long);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item == hash)\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(long);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item == hash)\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(long);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public long[] ToArray()\n        {\n            var array = new long[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextLong));\n            m_extraArray.Set(default(LongNext));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(long[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<long> Members\n\n        IEnumerator<long> IEnumerable<long>.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                LongNext[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                long item,\n                NextLong[] firstArray,\n                ulong capacity,\n                ref LongNext[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextLong[newCapacity];\n            var extraArray = new LongNext[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region DictIEq<TKey, TValue>\n\n    /// <summary>\n    /// A DictIEq is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class DictIEq<TKey, TValue>\n            : IIntCountable, ICountableDict, IDict<TKey, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>,\n              ICollection, ICollection<KeyValuePair<TKey, TValue>>,\n              IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>\n        where TKey : IEquatable<TKey>\n    {\n        private uint m_capacity;\n        private NextHashKeyValue<TKey, TValue>[] m_firstArray;\n        private HashKeyValueNext<TKey, TValue>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a DictIEq that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// DictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public DictIEq(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a DictIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// DictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public DictIEq(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a DictIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// DictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public DictIEq(int initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a DictIEq and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// DictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public DictIEq(IEnumerable<KeyValuePair<TKey, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private DictIEq(\n                uint firstCapacity, uint extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyValue<TKey, TValue>[m_capacity];\n            m_extraArray = new HashKeyValueNext<TKey, TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictIEq.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictIEq\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the DictIEq. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<KeyValuePair<TKey, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        /// <summary>\n        /// Returns all values in the DictIEq.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Value;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Value;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the DictIEq.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    while (ei > 0)\n                    {\n                        yield return new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the DictIEq, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new DictIEq in the order they are returned.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                var stack = new Stack<int>();\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        yield return new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    }\n                    yield return new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the DictIEq acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                var hash = key.GetHashCode();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key.GetHashCode();\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Hash == hash\n                        && key.Equals(m_firstArray[fi].Item.Key))\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Hash == hash\n                            && key.Equals(m_extraArray[ei].Item.Key))\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the DictIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the DictIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the DictIEq.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the DictIEq.\n        /// </summary>\n        public void Add(TKey key, int hash, TValue value)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the DictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the DictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash, TValue value)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the DictIEq.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the DictIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the DictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the DictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the DictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the DictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the DictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the DictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, int hash, TValue value)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the DictIEq contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the DictIEq contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the DictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        TValue AddCreated(TKey key, int hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the DictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, int hash, Func<TKey, TValue> creator)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, int hash, TValue defaultValue)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, int hash, out TValue value)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                yield return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    yield return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values.\n        /// Should be preferred over Values enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValueEnumerator GetValuesEnumerator()\n        {\n            return new ValueEnumerator(this);\n        }\n\n        public struct ValueEnumerator : IEnumerator<TValue>\n        {\n            DictIEq<TKey, TValue>.Enumerator m_inner;\n\n            public ValueEnumerator(DictIEq<TKey, TValue> dict)\n            {\n                m_inner = dict.GetEnumerator();\n            }\n\n            public TValue Current => m_inner.Current.Value;\n\n            object IEnumerator.Current => Current;\n\n            public void Dispose() => m_inner.Dispose();\n\n            public bool MoveNext() => m_inner.MoveNext();\n\n            public void Reset() => m_inner.Reset();\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values with key. It is only useful\n        /// if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// Should be preferred over ValuesWithKey enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValuesWithKeyEnumerator GetValuesWithKeyEnumerator(TKey key)\n        {\n            return new ValuesWithKeyEnumerator(this, key);\n        }\n\n        public struct ValuesWithKeyEnumerator : IEnumerator<TValue>\n        {\n            readonly DictIEq<TKey, TValue> m_dict;\n            readonly TKey m_key;\n            readonly int m_hash;\n            int m_extraIndex;\n            TValue m_current;\n\n            public ValuesWithKeyEnumerator(DictIEq<TKey, TValue> dict, TKey key)\n            {\n                m_dict = dict;\n                m_key = key;\n                m_hash = key.GetHashCode();\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n\n            public readonly TValue Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex == int.MaxValue)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var fi = ((uint)m_hash) % m_dict.m_capacity;\n                    m_extraIndex = fa[fi].Next;\n                    if (m_extraIndex == 0) return false;\n                    if (fa[fi].Item.Hash == m_hash\n                        && m_key.Equals(fa[fi].Item.Key))\n                    {\n                        m_current = fa[fi].Item.Value;\n                        return true;\n                    }\n                }\n                if (m_extraIndex > 0)\n                {\n                    var ea = m_dict.m_extraArray;\n                    do\n                    {\n                        var valid = ea[m_extraIndex].Item.Hash == m_hash\n                                    && m_key.Equals(ea[m_extraIndex].Item.Key);\n                        if (valid) m_current = ea[m_extraIndex].Item.Value;\n                        m_extraIndex = ea[m_extraIndex].Next;\n                        if (valid) return true;\n                    } while (m_extraIndex > 0);\n                }\n\n                return false;\n            }\n\n            public void Reset()\n            {\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, int skip)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the DictIEq and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the DictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the DictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            TValue value;\n            return TryRemove(key, hash, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the DictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the DictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash, TValue value)\n        {\n            return TryRemove(key, hash, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the DictIEq.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, out TValue value)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, TValue value)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            var array = new TKey[m_count];\n            CopyKeysTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<TKey, TValue>[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextHashKeyValue<TKey, TValue>));\n            m_extraArray.Set(default(HashKeyValueNext<TKey, TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<TKey, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<TKey, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as KeyValuePair<TKey, TValue>[];\n            if (typedArray != null)\n                CopyTo(typedArray, index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the DictIEq to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentDictIEq<TKey, TValue> AsConcurrent()\n        {\n            return new ConcurrentDictIEq<TKey, TValue>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey, TValue>> Members\n\n        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n        \n        #region IDictionary<TKey, TValue> Members\n\n        ICollection<TKey> IDictionary<TKey, TValue>.Keys => new KeyCollection(this);\n\n        ICollection<TValue> IDictionary<TKey, TValue>.Values => new ValueCollection(this);\n\n        private sealed class KeyCollection(DictIEq<TKey, TValue> parent) : ICollection<TKey>, ICollection, IReadOnlyCollection<TKey>\n        {\n            public void CopyTo(TKey[] array, int index) => parent.CopyKeysTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<TKey>.IsReadOnly => true;\n\n            void ICollection<TKey>.Add(TKey item) => throw new NotSupportedException();\n\n            void ICollection<TKey>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(TKey item) => parent.ContainsKey(item);\n\n            bool ICollection<TKey>.Remove(TKey item) => throw new NotSupportedException();\n\n            IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<TKey>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is TKey[] keys) parent.CopyKeysTo(keys, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(DictIEq<TKey, TValue> dictionary) : IEnumerator<TKey>, IEnumerator\n            {\n                private DictIEq<TKey, TValue>.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public TKey Current => _inner.Current.Key;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        private sealed class ValueCollection(DictIEq<TKey, TValue> parent) : ICollection<TValue>, ICollection, IReadOnlyCollection<TValue>\n        {\n            public void CopyTo(TValue[] array, int index) => parent.CopyValuesTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<TValue>.IsReadOnly => true;\n\n            void ICollection<TValue>.Add(TValue item) => throw new NotSupportedException();\n\n            void ICollection<TValue>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(TValue item) => parent.ContainsValue(item);\n\n            bool ICollection<TValue>.Remove(TValue item) => throw new NotSupportedException();\n\n            IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<TValue>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is TValue[] values) parent.CopyValuesTo(values, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(DictIEq<TKey, TValue> dictionary) : IEnumerator<TValue>, IEnumerator\n            {\n                private DictIEq<TKey, TValue>.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public TValue Current => _inner.Current.Value;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        #endregion\n        \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>\n        {\n            readonly DictIEq<TKey, TValue> m_dict;\n            int m_index;\n            int m_extraIndex;\n            KeyValuePair<TKey, TValue> m_current;\n\n            public Enumerator(DictIEq<TKey, TValue> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(KeyValuePair<TKey, TValue>);\n            }\n\n            public readonly KeyValuePair<TKey, TValue> Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = new KeyValuePair<TKey, TValue>(fa[m_index].Item.Key, fa[m_index].Item.Value);\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = new KeyValuePair<TKey, TValue>(ea[m_extraIndex].Item.Key, ea[m_extraIndex].Item.Value);\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default( KeyValuePair<TKey, TValue>);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                HashKeyValueNext<TKey, TValue>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyValue<TKey, TValue> item,\n                NextHashKeyValue<TKey, TValue>[] firstArray,\n                uint capacity,\n                ref HashKeyValueNext<TKey, TValue>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyValue<TKey, TValue>[newCapacity];\n            var extraArray = new HashKeyValueNext<TKey, TValue>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region DictSetIEq<TKey>\n\n    /// <summary>\n    /// A DictSetIEq is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class DictSetIEq<TKey>\n            : IIntCountable, ICountableDictSet, IDictSet<TKey>,\n              IEnumerable, IEnumerable<TKey>,\n              ICollection, ICollection<TKey>\n        where TKey : IEquatable<TKey>\n    {\n        private uint m_capacity;\n        private NextHashKey<TKey>[] m_firstArray;\n        private HashKeyNext<TKey>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a DictSetIEq that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public DictSetIEq()\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a DictSetIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public DictSetIEq(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a DictSetIEq and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public DictSetIEq(IEnumerable<TKey> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private DictSetIEq(\n                uint firstCapacity, uint extraCapacity)\n        {\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKey<TKey>[m_capacity];\n            m_extraArray = new HashKeyNext<TKey>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictSetIEq.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictSetIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the DictSetIEq\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the DictSetIEq. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<TKey> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the DictSetIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the DictSetIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        void ICollection<TKey>.Add(TKey key)\n        {\n            Add(key);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the DictSetIEq.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            var hash = key.GetHashCode();\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the DictSetIEq.\n        /// </summary>\n        public bool Add(TKey key, int hash)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the DictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            var hash = key.GetHashCode();\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the DictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the DictSetIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the DictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the DictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the DictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the DictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            return TryRemove(key, hash);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            var hash = key.GetHashCode();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKey<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKey<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash)\n        {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKey<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKey<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            var array = new TKey[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextHashKey<TKey>));\n            m_extraArray.Set(default(HashKeyNext<TKey>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(TKey[] array, int index)\n        {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as TKey[];\n            if (typedArray != null)\n                CopyTo(typedArray, index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the DictSetIEq to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentDictSetIEq<TKey> AsConcurrent()\n        {\n            return new ConcurrentDictSetIEq<TKey>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<TKey> Members\n\n        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<TKey>\n        {\n            readonly DictSetIEq<TKey> m_dict;\n            int m_index;\n            int m_extraIndex;\n            TKey m_current;\n\n            public Enumerator(DictSetIEq<TKey> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(TKey);\n            }\n\n            public readonly TKey Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = fa[m_index].Item.Key;\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = ea[m_extraIndex].Item.Key;\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(TKey);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                HashKeyNext<TKey>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKey<TKey> item,\n                NextHashKey<TKey>[] firstArray,\n                uint capacity,\n                ref HashKeyNext<TKey>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKey<TKey>[newCapacity];\n            var extraArray = new HashKeyNext<TKey>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region BigDictIEq<TKey, TValue>\n\n    /// <summary>\n    /// A BigDictIEq is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class BigDictIEq<TKey, TValue>\n            : ICountableDict, IDict<TKey, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>\n        where TKey : IEquatable<TKey>\n    {\n        private readonly Func<TKey, long> m_hfun;\n        private ulong m_capacity;\n        private NextHashKeyValueLong<TKey, TValue>[] m_firstArray;\n        private HashKeyValueNextLong<TKey, TValue>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a BigDictIEq that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// BigDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public BigDictIEq(Func<TKey, long> hfun, bool stackDuplicateKeys = false)\n            : this(hfun, DictConstant.PrimeSizesLong[0], (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a BigDictIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// BigDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public BigDictIEq(Func<TKey, long> hfun, long initialCapacity)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a BigDictIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// BigDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public BigDictIEq(Func<TKey, long> hfun, long initialCapacity, bool stackDuplicateKeys)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a BigDictIEq and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// BigDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public BigDictIEq(Func<TKey, long> hfun, IEnumerable<KeyValuePair<TKey, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(hfun, Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizesLong[0]), (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private BigDictIEq(\n                Func<TKey, long> hfun, ulong firstCapacity, ulong extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_hfun = hfun;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizesLong[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizesLong[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyValueLong<TKey, TValue>[m_capacity];\n            m_extraArray = new HashKeyValueNextLong<TKey, TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the BigDictIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the BigDictIEq\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the BigDictIEq. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<KeyValuePair<TKey, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        /// <summary>\n        /// Returns all values in the BigDictIEq.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Value;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Value;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the BigDictIEq.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    while (ei > 0)\n                    {\n                        yield return new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the BigDictIEq, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new BigDictIEq in the order they are returned.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                var stack = new Stack<long>();\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        yield return new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    }\n                    yield return new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the BigDictIEq acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                var hash = m_hfun(key);\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = m_hfun(key);\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Hash == hash\n                        && key.Equals(m_firstArray[fi].Item.Key))\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Hash == hash\n                            && key.Equals(m_extraArray[ei].Item.Key))\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.LongLength;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the BigDictIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the BigDictIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the BigDictIEq.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the BigDictIEq.\n        /// </summary>\n        public void Add(TKey key, long hash, TValue value)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the BigDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the BigDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash, TValue value)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the BigDictIEq.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the BigDictIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, long hash, TValue value)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictIEq contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictIEq contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the BigDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        TValue AddCreated(TKey key, long hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the BigDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, long hash, Func<TKey, TValue> creator)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, long hash, TValue defaultValue)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, long hash, out TValue value)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                yield return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    yield return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values.\n        /// Should be preferred over Values enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValueEnumerator GetValuesEnumerator()\n        {\n            return new ValueEnumerator(this);\n        }\n\n        public struct ValueEnumerator : IEnumerator<TValue>\n        {\n            BigDictIEq<TKey, TValue>.Enumerator m_inner;\n\n            public ValueEnumerator(BigDictIEq<TKey, TValue> dict)\n            {\n                m_inner = dict.GetEnumerator();\n            }\n\n            public TValue Current => m_inner.Current.Value;\n\n            object IEnumerator.Current => Current;\n\n            public void Dispose() => m_inner.Dispose();\n\n            public bool MoveNext() => m_inner.MoveNext();\n\n            public void Reset() => m_inner.Reset();\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values with key. It is only useful\n        /// if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// Should be preferred over ValuesWithKey enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValuesWithKeyEnumerator GetValuesWithKeyEnumerator(TKey key)\n        {\n            return new ValuesWithKeyEnumerator(this, key);\n        }\n\n        public struct ValuesWithKeyEnumerator : IEnumerator<TValue>\n        {\n            readonly BigDictIEq<TKey, TValue> m_dict;\n            readonly TKey m_key;\n            readonly long m_hash;\n            long m_extraIndex;\n            TValue m_current;\n\n            public ValuesWithKeyEnumerator(BigDictIEq<TKey, TValue> dict, TKey key)\n            {\n                m_dict = dict;\n                m_key = key;\n                m_hash = dict.m_hfun(key);\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n\n            public readonly TValue Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex == int.MaxValue)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var fi = ((uint)m_hash) % m_dict.m_capacity;\n                    m_extraIndex = fa[fi].Next;\n                    if (m_extraIndex == 0) return false;\n                    if (fa[fi].Item.Hash == m_hash\n                        && m_key.Equals(fa[fi].Item.Key))\n                    {\n                        m_current = fa[fi].Item.Value;\n                        return true;\n                    }\n                }\n                if (m_extraIndex > 0)\n                {\n                    var ea = m_dict.m_extraArray;\n                    do\n                    {\n                        var valid = ea[m_extraIndex].Item.Hash == m_hash\n                                    && m_key.Equals(ea[m_extraIndex].Item.Key);\n                        if (valid) m_current = ea[m_extraIndex].Item.Value;\n                        m_extraIndex = ea[m_extraIndex].Next;\n                        if (valid) return true;\n                    } while (m_extraIndex > 0);\n                }\n\n                return false;\n            }\n\n            public void Reset()\n            {\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, long skip)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the BigDictIEq and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the BigDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the BigDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            TValue value;\n            return TryRemove(key, hash, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the BigDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the BigDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash, TValue value)\n        {\n            return TryRemove(key, hash, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the BigDictIEq.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, out TValue value)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, TValue value)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            var array = new TKey[m_count];\n            CopyKeysTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<TKey, TValue>[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextHashKeyValueLong<TKey, TValue>));\n            m_extraArray.Set(default(HashKeyValueNextLong<TKey, TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<TKey, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<TKey, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as KeyValuePair<TKey, TValue>[];\n            if (typedArray != null)\n                CopyTo(typedArray, (long)index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the BigDictIEq to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentBigDictIEq<TKey, TValue> AsConcurrent()\n        {\n            return new ConcurrentBigDictIEq<TKey, TValue>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey, TValue>> Members\n\n        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>\n        {\n            readonly BigDictIEq<TKey, TValue> m_dict;\n            long m_index;\n            long m_extraIndex;\n            KeyValuePair<TKey, TValue> m_current;\n\n            public Enumerator(BigDictIEq<TKey, TValue> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(KeyValuePair<TKey, TValue>);\n            }\n\n            public readonly KeyValuePair<TKey, TValue> Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = new KeyValuePair<TKey, TValue>(fa[m_index].Item.Key, fa[m_index].Item.Value);\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = new KeyValuePair<TKey, TValue>(ea[m_extraIndex].Item.Key, ea[m_extraIndex].Item.Value);\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default( KeyValuePair<TKey, TValue>);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                HashKeyValueNextLong<TKey, TValue>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizesLong[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizesLong[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyValueLong<TKey, TValue> item,\n                NextHashKeyValueLong<TKey, TValue>[] firstArray,\n                ulong capacity,\n                ref HashKeyValueNextLong<TKey, TValue>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyValueLong<TKey, TValue>[newCapacity];\n            var extraArray = new HashKeyValueNextLong<TKey, TValue>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.LongLength / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region BigDictSetIEq<TKey>\n\n    /// <summary>\n    /// A BigDictSetIEq is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class BigDictSetIEq<TKey>\n            : ICountableDictSet, IDictSet<TKey>,\n              IEnumerable, IEnumerable<TKey>\n        where TKey : IEquatable<TKey>\n    {\n        private readonly Func<TKey, long> m_hfun;\n        private ulong m_capacity;\n        private NextHashKeyLong<TKey>[] m_firstArray;\n        private HashKeyNextLong<TKey>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a BigDictSetIEq that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public BigDictSetIEq(Func<TKey, long> hfun)\n            : this(hfun, DictConstant.PrimeSizesLong[0], (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a BigDictSetIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public BigDictSetIEq(Func<TKey, long> hfun, long initialCapacity)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a BigDictSetIEq and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public BigDictSetIEq(Func<TKey, long> hfun, IEnumerable<TKey> items)\n            : this(hfun, Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizesLong[0]), (ulong)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private BigDictSetIEq(\n                Func<TKey, long> hfun, ulong firstCapacity, ulong extraCapacity)\n        {\n            m_hfun = hfun;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizesLong[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizesLong[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyLong<TKey>[m_capacity];\n            m_extraArray = new HashKeyNextLong<TKey>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the BigDictSetIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the BigDictSetIEq\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the BigDictSetIEq. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        public IEnumerable<TKey> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    yield return m_firstArray[fi].Item.Key;\n                    while (ei > 0)\n                    {\n                        yield return m_extraArray[ei].Item.Key;\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the BigDictSetIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the BigDictSetIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the BigDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            var hash = m_hfun(key);\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the BigDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key, long hash)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the BigDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            var hash = m_hfun(key);\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the BigDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash)\n        {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the BigDictSetIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the BigDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the BigDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the BigDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            return TryRemove(key, hash);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            var hash = m_hfun(key);\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyLong<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyLong<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash)\n        {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyLong<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyLong<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            var array = new TKey[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            m_firstArray.Set(default(NextHashKeyLong<TKey>));\n            m_extraArray.Set(default(HashKeyNextLong<TKey>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// </summary>\n        public void CopyTo(TKey[] array, long index)\n        {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as TKey[];\n            if (typedArray != null)\n                CopyTo(typedArray, (long)index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the BigDictSetIEq to enable\n        /// concurrent modifications.\n        /// </summary>\n        public ConcurrentBigDictSetIEq<TKey> AsConcurrent()\n        {\n            return new ConcurrentBigDictSetIEq<TKey>(this);\n        }\n\n        #endregion\n\n        #region IEnumerable<TKey> Members\n\n        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return new Enumerator(this);\n            \n        }\n\n        #endregion\n                \n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator<TKey>\n        {\n            readonly BigDictSetIEq<TKey> m_dict;\n            long m_index;\n            long m_extraIndex;\n            TKey m_current;\n\n            public Enumerator(BigDictSetIEq<TKey> dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(TKey);\n            }\n\n            public readonly TKey Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = fa[m_index].Item.Key;\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = ea[m_extraIndex].Item.Key;\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(TKey);\n            }\n        }\n\n        #endregion\n        \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                HashKeyNextLong<TKey>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizesLong[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizesLong[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyLong<TKey> item,\n                NextHashKeyLong<TKey>[] firstArray,\n                ulong capacity,\n                ref HashKeyNextLong<TKey>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyLong<TKey>[newCapacity];\n            var extraArray = new HashKeyNextLong<TKey>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.LongLength / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentDictIEq<TKey, TValue>\n\n    /// <summary>\n    /// A ConcurrentDictIEq is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentDictIEq<TKey, TValue>\n        where TKey : IEquatable<TKey>\n    {\n        private readonly DictIEq<TKey, TValue> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentDictIEq can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentDictIEq(DictIEq<TKey, TValue> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictIEq.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return m_dict.Count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictIEq\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentDictIEq.\n        /// </summary>\n        public DictIEq<TKey, TValue> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the ConcurrentDictIEq acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                Monitor.Enter(this); try { return m_dict[key]; } finally { Monitor.Exit(this); }\n            }\n            set\n            {\n                Monitor.Enter(this); try { m_dict[key] = value; } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the ConcurrentDictIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentDictIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentDictIEq.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentDictIEq.\n        /// </summary>\n        public void Add(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied item to the ConcurrentDictIEq.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied items to the ConcurrentDictIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, int hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictIEq contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Contains(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictIEq contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            return m_dict.ContainsValue(value);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, int hash, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, hash, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, int hash, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, int hash, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, int skip)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.ValueWithKeySkip(key, skip);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the ConcurrentDictIEq and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetAndRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the ConcurrentDictIEq.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            return m_dict.KeysToArray();\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            return m_dict.ValuesToArray();\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyKeysTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyValuesTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)\n        {\n            Monitor.Enter(this); try { m_dict.CopyTo(array, index); } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentDictSetIEq<TKey>\n\n    /// <summary>\n    /// A ConcurrentDictSetIEq is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentDictSetIEq<TKey>\n        where TKey : IEquatable<TKey>\n    {\n        private readonly DictSetIEq<TKey> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentDictSetIEq can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentDictSetIEq(DictSetIEq<TKey> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictSetIEq.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return m_dict.Count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictSetIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentDictSetIEq\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentDictSetIEq.\n        /// </summary>\n        public DictSetIEq<TKey> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the ConcurrentDictSetIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentDictSetIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the ConcurrentDictSetIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(TKey[] array, int index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentBigDictIEq<TKey, TValue>\n\n    /// <summary>\n    /// A ConcurrentBigDictIEq is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentBigDictIEq<TKey, TValue>\n        where TKey : IEquatable<TKey>\n    {\n        private readonly BigDictIEq<TKey, TValue> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentBigDictIEq can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentBigDictIEq(BigDictIEq<TKey, TValue> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentBigDictIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentBigDictIEq\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentBigDictIEq.\n        /// </summary>\n        public BigDictIEq<TKey, TValue> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the ConcurrentBigDictIEq acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                Monitor.Enter(this); try { return m_dict[key]; } finally { Monitor.Exit(this); }\n            }\n            set\n            {\n                Monitor.Enter(this); try { m_dict[key] = value; } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the ConcurrentBigDictIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentBigDictIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentBigDictIEq.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentBigDictIEq.\n        /// </summary>\n        public void Add(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentBigDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the ConcurrentBigDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied item to the ConcurrentBigDictIEq.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied items to the ConcurrentBigDictIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, long hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictIEq contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Contains(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictIEq contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            return m_dict.ContainsValue(value);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentBigDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the ConcurrentBigDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, long hash, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetOrCreate(key, hash, creator);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, long hash, TValue defaultValue)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, long hash, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, long skip)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.ValueWithKeySkip(key, skip);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the ConcurrentBigDictIEq and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetAndRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentBigDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the ConcurrentBigDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            TValue value;\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentBigDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the ConcurrentBigDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the ConcurrentBigDictIEq.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, out TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, out value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash, value);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            return m_dict.KeysToArray();\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            return m_dict.ValuesToArray();\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyKeysTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyValuesTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, long index)\n        {\n            Monitor.Enter(this); try { m_dict.CopyTo(array, index); } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ConcurrentBigDictSetIEq<TKey>\n\n    /// <summary>\n    /// A ConcurrentBigDictSetIEq is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class ConcurrentBigDictSetIEq<TKey>\n        where TKey : IEquatable<TKey>\n    {\n        private readonly BigDictSetIEq<TKey> m_dict;\n\n        #region Constructors\n\n        /// <summary>\n        /// A ConcurrentBigDictSetIEq can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public ConcurrentBigDictSetIEq(BigDictSetIEq<TKey> dict)\n        {\n            m_dict = dict;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentBigDictSetIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return m_dict.LongCount;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the ConcurrentBigDictSetIEq\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_dict.Capacity;\n            }\n            set\n            {\n                m_dict.Capacity = value;\n            }\n        }\n\n        /// <summary>\n        /// Return the non-concurrent contained ConcurrentBigDictSetIEq.\n        /// </summary>\n        public BigDictSetIEq<TKey> NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the ConcurrentBigDictSetIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the ConcurrentBigDictSetIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentBigDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentBigDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Add(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentBigDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the ConcurrentBigDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryAdd(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the ConcurrentBigDictSetIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns true if the ConcurrentBigDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentBigDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the ConcurrentBigDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash)\n        {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key, hash);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            return m_dict.ToArray();\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(TKey[] array, long index)\n        {\n            Monitor.Enter(this); try\n            {\n                m_dict.CopyTo(array, index);\n            }\n            finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentDictIEq<TKey, TValue>\n\n    /// <summary>\n    /// A FastConcurrentDictIEq is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentDictIEq<TKey, TValue>\n            : IIntCountable, ICountableDict, IDict<TKey, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>\n        where TKey : IEquatable<TKey>\n    {\n        private long m_version;\n        private uint m_capacity;\n        private NextHashKeyValue<TKey, TValue>[] m_firstArray;\n        private HashKeyValueNext<TKey, TValue>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentDictIEq that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentDictIEq(bool stackDuplicateKeys = false)\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDictIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentDictIEq(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDictIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentDictIEq(int initialCapacity, bool stackDuplicateKeys)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDictIEq and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentDictIEq(IEnumerable<KeyValuePair<TKey, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentDictIEq(\n                uint firstCapacity, uint extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyValue<TKey, TValue>[m_capacity];\n            m_extraArray = new HashKeyValueNext<TKey, TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictIEq.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictIEq\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentDictIEq. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        /// <summary>\n        /// Returns all values in the FastConcurrentDictIEq.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var v = m_firstArray[fi].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        v = m_extraArray[ei].Item.Value;\n                        Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentDictIEq.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var kvp = new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        kvp = new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentDictIEq, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new FastConcurrentDictIEq in the order they are returned.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                var stack = new Stack<int>();\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    var kvp = default(KeyValuePair<TKey, TValue>);\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        kvp = new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                    }\n                    kvp = new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the FastConcurrentDictIEq acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                var hash = key.GetHashCode();\n                Monitor.Enter(this); try {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                } finally { Monitor.Exit(this); }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = key.GetHashCode();\n                Monitor.Enter(this); try { ++m_version;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Hash == hash\n                        && key.Equals(m_firstArray[fi].Item.Key))\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Hash == hash\n                            && key.Equals(m_extraArray[ei].Item.Key))\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the FastConcurrentDictIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentDictIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentDictIEq.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentDictIEq.\n        /// </summary>\n        public void Add(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the FastConcurrentDictIEq.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the FastConcurrentDictIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictIEq contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictIEq contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        TValue AddCreated(TKey key, int hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((uint)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    ++m_version;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_version;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, int hash, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, int hash, TValue defaultValue)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, int hash, out TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try { var version = m_version;\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                var v = m_firstArray[fi].Item.Value;\n                Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                if (version != m_version)\n                    throw new ConcurrentDataModifiedException();\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    var v = m_extraArray[ei].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, int skip)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the FastConcurrentDictIEq and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            TValue value;\n            return TryRemove(key, hash, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash, TValue value)\n        {\n            return TryRemove(key, hash, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the FastConcurrentDictIEq.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, out TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValue<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValue<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValue<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            var array = new TKey[m_count];\n            CopyKeysTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<TKey, TValue>[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextHashKeyValue<TKey, TValue>));\n            m_extraArray.Set(default(HashKeyValueNext<TKey, TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<TKey, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<TKey, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey, TValue>> Members\n\n        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                HashKeyValueNext<TKey, TValue>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyValue<TKey, TValue> item,\n                NextHashKeyValue<TKey, TValue>[] firstArray,\n                uint capacity,\n                ref HashKeyValueNext<TKey, TValue>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyValue<TKey, TValue>[newCapacity];\n            var extraArray = new HashKeyValueNext<TKey, TValue>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentDictSetIEq<TKey>\n\n    /// <summary>\n    /// A FastConcurrentDictSetIEq is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentDictSetIEq<TKey>\n            : IIntCountable, ICountableDictSet, IDictSet<TKey>,\n              IEnumerable, IEnumerable<TKey>\n        where TKey : IEquatable<TKey>\n    {\n        private long m_version;\n        private uint m_capacity;\n        private NextHashKey<TKey>[] m_firstArray;\n        private HashKeyNext<TKey>[] m_extraArray;\n        private uint m_count;\n        private uint m_increaseThreshold;\n        private uint m_decreaseThreshold;\n        private int m_freeIndex;\n        private int m_capacityIndex;\n        private uint m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentDictSetIEq that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public FastConcurrentDictSetIEq()\n            : this(DictConstant.PrimeSizes[0], (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDictSetIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public FastConcurrentDictSetIEq(int initialCapacity)\n            : this(System.Math.Max((uint)initialCapacity,\n                                         DictConstant.PrimeSizes[0]),\n                   (uint)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentDictSetIEq and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public FastConcurrentDictSetIEq(IEnumerable<TKey> items)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes[0]), (uint)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentDictSetIEq(\n                uint firstCapacity, uint extraCapacity)\n        {\n            m_version = 0;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKey<TKey>[m_capacity];\n            m_extraArray = new HashKeyNext<TKey>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictSetIEq.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                return (int)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictSetIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentDictSetIEq\n        /// as long.\n        /// </summary>\n        public uint Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentDictSetIEq. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<TKey> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the FastConcurrentDictSetIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentDictSetIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the FastConcurrentDictSetIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, int hash)\n        {\n            return TryRemove(key, hash);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            var hash = key.GetHashCode();\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKey<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKey<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, int hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((uint)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKey<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKey<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKey<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            var array = new TKey[m_count];\n            CopyTo(array, 0);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextHashKey<TKey>));\n            m_extraArray.Set(default(HashKeyNext<TKey>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(TKey[] array, int index)\n        {\n            Monitor.Enter(this); try {\n            for (uint fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<TKey> Members\n\n        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private uint ComputeIncreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_maxFillFactor);\n        }\n\n        private uint ComputeDecreaseThreshold(uint capacity)\n        {\n            return (uint)(capacity * (double)m_minFillFactor);\n        }\n\n        private static int AddSlotsToFreeList(\n                HashKeyNext<TKey>[] extraArray, int start)\n        {\n            var length = extraArray.Length - 1;\n            for (int i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKey<TKey> item,\n                NextHashKey<TKey>[] firstArray,\n                uint capacity,\n                ref HashKeyNext<TKey>[] extraArray,\n                ref int freeIndex,\n                ref uint extraCount)\n        {\n            var fi = ((uint)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(uint newCapacity, uint oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKey<TKey>[newCapacity];\n            var extraArray = new HashKeyNext<TKey>[\n                                    System.Math.Max((int)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            uint newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (uint fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                uint fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        int head = -1;\n                        do\n                        {\n                            int next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((uint)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (uint)m_extraArray.Length,\n                            (uint)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (uint)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    uint oldFirstCount, uint oldCapacity,\n                    uint oldExtraCount, uint oldExtraCapacity,\n                    uint newFirstCount, uint newCapacity,\n                    uint newExtraCount, uint newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentBigDictIEq<TKey, TValue>\n\n    /// <summary>\n    /// A FastConcurrentBigDictIEq is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentBigDictIEq<TKey, TValue>\n            : ICountableDict, IDict<TKey, TValue>,\n              IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>\n        where TKey : IEquatable<TKey>\n    {\n        private long m_version;\n        private readonly Func<TKey, long> m_hfun;\n        private ulong m_capacity;\n        private NextHashKeyValueLong<TKey, TValue>[] m_firstArray;\n        private HashKeyValueNextLong<TKey, TValue>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private readonly bool m_doNotStackDuplicateKeys;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictIEq that autmatically grows and shrinks as necessary.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentBigDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentBigDictIEq(Func<TKey, long> hfun, bool stackDuplicateKeys = false)\n            : this(hfun, DictConstant.PrimeSizesLong[0], (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentBigDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentBigDictIEq(Func<TKey, long> hfun, long initialCapacity)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity, false)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentBigDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentBigDictIEq(Func<TKey, long> hfun, long initialCapacity, bool stackDuplicateKeys)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictIEq and initialize it to contain the supplied\n        /// items.\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// FastConcurrentBigDictIEq acts as a stack for all items with the same key.\n        /// </summary>\n        public FastConcurrentBigDictIEq(Func<TKey, long> hfun, IEnumerable<KeyValuePair<TKey, TValue>> items,\n                bool stackDuplicateKeys = false)\n            : this(hfun, Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizesLong[0]), (ulong)DictConstant.MinExtraCapacity,\n                   stackDuplicateKeys)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentBigDictIEq(\n                Func<TKey, long> hfun, ulong firstCapacity, ulong extraCapacity,\n                bool stackDuplicateKeys = false)\n        {\n            m_version = 0;\n            m_hfun = hfun;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizesLong[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizesLong[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyValueLong<TKey, TValue>[m_capacity];\n            m_extraArray = new HashKeyValueNextLong<TKey, TValue>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentBigDictIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentBigDictIEq\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentBigDictIEq. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> Items { get { return KeyValuePairs; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        /// <summary>\n        /// Returns all values in the FastConcurrentBigDictIEq.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var v = m_firstArray[fi].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        v = m_extraArray[ei].Item.Value;\n                        Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentBigDictIEq.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var kvp = new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        kvp = new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the FastConcurrentBigDictIEq, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new FastConcurrentBigDictIEq in the order they are returned.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                var stack = new Stack<long>();\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    var kvp = default(KeyValuePair<TKey, TValue>);\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        kvp = new KeyValuePair<TKey, TValue>(\n                                m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                    }\n                    kvp = new KeyValuePair<TKey, TValue>(\n                            m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the FastConcurrentBigDictIEq acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[TKey key]\n        {\n            get\n            {\n                var hash = m_hfun(key);\n                Monitor.Enter(this); try {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                } finally { Monitor.Exit(this); }\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                var hash = m_hfun(key);\n                Monitor.Enter(this); try { ++m_version;\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item.Hash == hash\n                        && key.Equals(m_firstArray[fi].Item.Key))\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item.Hash == hash\n                            && key.Equals(m_extraArray[ei].Item.Key))\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.LongLength;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key and the supplied value\n        /// both supplied as generic objects, to the FastConcurrentBigDictIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentBigDictIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public void AddObject(object objkey, object objvalue)\n        {\n            Add((TKey)objkey, (TValue)objvalue);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentBigDictIEq.\n        /// </summary>\n        public void Add(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentBigDictIEq.\n        /// </summary>\n        public void Add(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    throw new ArgumentException(\"duplicate key\");\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        throw new ArgumentException(\"duplicate key\");\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentBigDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key and the supplied value\n        /// to the FastConcurrentBigDictIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return true;\n            }\n            if (m_doNotStackDuplicateKeys)\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            m_firstArray[fi].Item.Value = value;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied item to the FastConcurrentBigDictIEq.\n        /// </summary>\n        public void Add(KeyValuePair<TKey, TValue> item)\n        {\n            Add(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Add the supplied items to the FastConcurrentBigDictIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool ContainsKey(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictIEq contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictIEq contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<TKey, TValue> item)\n        {\n            return Contains(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictIEq contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentBigDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, Func<TKey, TValue> creator)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        TValue AddCreated(TKey key, long hash, TValue value)\n        {\n            while (true)\n            {\n                var fi = ((ulong)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    ++m_version;\n                    m_firstArray[fi].Next = -1;\n                    m_firstArray[fi].Item.Hash = hash;\n                    m_firstArray[fi].Item.Key = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                ++m_version;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, TValue defaultValue)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        /// </summary>\n        public TValue Get(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the FastConcurrentBigDictIEq and returned.\n        /// </summary>\n        public TValue GetOrCreate(TKey key, long hash, Func<TKey, TValue> creator)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key.\n        /// Returns the supplied default value if the element is not found.\n        /// </summary>\n        public TValue Get(TKey key, long hash, TValue defaultValue)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                return defaultValue;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            return defaultValue;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(TKey key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(TKey key, long hash, out TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try { var version = m_version;\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                var v = m_firstArray[fi].Item.Value;\n                Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                if (version != m_version)\n                    throw new ConcurrentDataModifiedException();\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    var v = m_extraArray[ei].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(TKey key, long skip)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            throw new KeyNotFoundException();\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the FastConcurrentBigDictIEq and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(TKey key)\n        {\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentBigDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            TValue value;\n            return TryRemove(key, out value);\n        }\n\n        /// <summary>\n        /// Try to remove the item with the supplied key from the FastConcurrentBigDictIEq.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            TValue value;\n            return TryRemove(key, hash, out value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentBigDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, TValue value)\n        {\n            return TryRemove(key, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key and the supplied value\n        /// from the FastConcurrentBigDictIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash, TValue value)\n        {\n            return TryRemove(key, hash, value);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the FastConcurrentBigDictIEq.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<TKey, TValue> item)\n        {\n            return TryRemove(item.Key, item.Value);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, out TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found, which is returned via the out\n        /// parameter.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, out TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                value = default(TValue); return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                value = m_firstArray[fi].Item.Value;\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        value = m_extraArray[ni].Item.Value;\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            value = default(TValue);\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, TValue value)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash, TValue value)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key)\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyValueLong<TKey, TValue>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key)\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyValueLong<TKey, TValue>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key)\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyValueLong<TKey, TValue>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] KeysToArray()\n        {\n            var array = new TKey[m_count];\n            CopyKeysTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all values in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TValue[] ValuesToArray()\n        {\n            var array = new TValue[m_count];\n            CopyValuesTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public KeyValuePair<TKey, TValue>[] ToArray()\n        {\n            var array = new KeyValuePair<TKey, TValue>[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextHashKeyValueLong<TKey, TValue>));\n            m_extraArray.Set(default(HashKeyValueNextLong<TKey, TValue>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyKeysTo(TKey[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all values in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyValuesTo(TValue[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(KeyValuePair<TKey, TValue>[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<TKey, TValue>(\n                                m_firstArray[fi].Item.Key, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<TKey, TValue>(\n                                    m_extraArray[ei].Item.Key, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey, TValue>> Members\n\n        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return KeyValuePairs.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                HashKeyValueNextLong<TKey, TValue>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizesLong[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizesLong[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyValueLong<TKey, TValue> item,\n                NextHashKeyValueLong<TKey, TValue>[] firstArray,\n                ulong capacity,\n                ref HashKeyValueNextLong<TKey, TValue>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyValueLong<TKey, TValue>[newCapacity];\n            var extraArray = new HashKeyValueNextLong<TKey, TValue>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.LongLength / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region FastConcurrentBigDictSetIEq<TKey>\n\n    /// <summary>\n    /// A FastConcurrentBigDictSetIEq is an alternate implementation of a HashSet.\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class FastConcurrentBigDictSetIEq<TKey>\n            : ICountableDictSet, IDictSet<TKey>,\n              IEnumerable, IEnumerable<TKey>\n        where TKey : IEquatable<TKey>\n    {\n        private long m_version;\n        private readonly Func<TKey, long> m_hfun;\n        private ulong m_capacity;\n        private NextHashKeyLong<TKey>[] m_firstArray;\n        private HashKeyNextLong<TKey>[] m_extraArray;\n        private ulong m_count;\n        private ulong m_increaseThreshold;\n        private ulong m_decreaseThreshold;\n        private long m_freeIndex;\n        private int m_capacityIndex;\n        private ulong m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n\n        #region Constructors\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictSetIEq that autmatically grows and shrinks as necessary.\n        /// </summary>\n        public FastConcurrentBigDictSetIEq(Func<TKey, long> hfun)\n            : this(hfun, DictConstant.PrimeSizesLong[0], (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictSetIEq that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        /// </summary>\n        public FastConcurrentBigDictSetIEq(Func<TKey, long> hfun, long initialCapacity)\n            : this(hfun, System.Math.Max((ulong)initialCapacity,\n                                         DictConstant.PrimeSizesLong[0]),\n                   (ulong)DictConstant.MinExtraCapacity)\n        { }\n\n        /// <summary>\n        /// Create a FastConcurrentBigDictSetIEq and initialize it to contain the supplied\n        /// items.\n        /// </summary>\n        public FastConcurrentBigDictSetIEq(Func<TKey, long> hfun, IEnumerable<TKey> items)\n            : this(hfun, Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizesLong[0]), (ulong)DictConstant.MinExtraCapacity)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        private FastConcurrentBigDictSetIEq(\n                Func<TKey, long> hfun, ulong firstCapacity, ulong extraCapacity)\n        {\n            m_version = 0;\n            m_hfun = hfun;\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizesLong[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizesLong[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new NextHashKeyLong<TKey>[m_capacity];\n            m_extraArray = new HashKeyNextLong<TKey>[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentBigDictSetIEq\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                return (long)m_count;\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the FastConcurrentBigDictSetIEq\n        /// as long.\n        /// </summary>\n        public ulong Capacity\n        {\n            get\n            {\n                return m_capacity;\n            }\n            set\n            {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n            }\n        }\n\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the FastConcurrentBigDictSetIEq. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                Monitor.Enter(this); try {\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public IEnumerable<TKey> Items { get { return Keys; } }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        /// </summary>\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                Monitor.Enter(this); try { var version = m_version;\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    var k = m_firstArray[fi].Item.Key;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    while (ei > 0)\n                    {\n                        k = m_extraArray[ei].Item.Key;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                } finally { Monitor.Exit(this); }\n            }\n        }\n\n        public Type KeyType { get { return typeof(TKey); } }\n\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        #endregion\n\n        #region Public Methods\n\n        /// <summary>\n        /// Add the item with supplied key\n        /// both supplied as generic objects, to the FastConcurrentBigDictSetIEq. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the FastConcurrentBigDictSetIEq\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public bool AddObject(object objkey)\n        {\n            return Add((TKey)objkey);\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentBigDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentBigDictSetIEq.\n        /// </summary>\n        public bool Add(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentBigDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the item with the supplied key\n        /// to the FastConcurrentBigDictSetIEq.\n        /// </summary>\n        public bool TryAdd(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                ++m_version;\n               m_firstArray[fi].Next = -1;\n                m_firstArray[fi].Item.Hash = hash;\n                m_firstArray[fi].Item.Key = key;\n                return true;\n            }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item.Hash == hash\n                    && key.Equals(m_firstArray[fi].Item.Key))\n                {\n                    return false;\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item.Hash == hash\n                        && key.Equals(m_extraArray[ei].Item.Key))\n                    {\n                        return false;\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            ++m_version;\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            m_firstArray[fi].Item.Hash = hash;\n            m_firstArray[fi].Item.Key = key;\n            } finally { Monitor.Exit(this); }\n            return true;\n        }\n\n        /// <summary>\n        /// Add the supplied keys to the FastConcurrentBigDictSetIEq.\n        /// </summary>\n        public void AddRange(IEnumerable<TKey> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns true if the FastConcurrentBigDictSetIEq contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentBigDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key)\n        {\n            return TryRemove(key);\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key\n        /// from the FastConcurrentBigDictSetIEq. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(TKey key, long hash)\n        {\n            return TryRemove(key, hash);\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key)\n        {\n            var hash = m_hfun(key);\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyLong<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyLong<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(TKey key, long hash)\n        {\n            Monitor.Enter(this); try {\n            var fi = ((ulong)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                return false;\n            }\n            if (m_firstArray[fi].Item.Hash == hash\n                && key.Equals(m_firstArray[fi].Item.Key))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(HashKeyLong<TKey>);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                ++m_version;\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item.Hash == hash\n                    && key.Equals(m_extraArray[ei].Item.Key))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(HashKeyLong<TKey>);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    ++m_version;\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item.Hash == hash\n                        && key.Equals(m_extraArray[ni].Item.Key))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(HashKeyLong<TKey>);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        ++m_version;\n                        return true;\n                    }\n                }\n            }\n            } finally { Monitor.Exit(this); }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns all keys in the dictionary as an array.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public TKey[] ToArray()\n        {\n            var array = new TKey[m_count];\n            CopyTo(array, 0L);\n            return array;\n        }\n\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            Monitor.Enter(this); try { ++m_version;\n            m_firstArray.Set(default(NextHashKeyLong<TKey>));\n            m_extraArray.Set(default(HashKeyNextLong<TKey>));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            } finally { Monitor.Exit(this); }\n        }\n\n        /// <summary>\n        /// Copies all keys in the dictionary to the supplied\n        /// array starting at the supplied index.\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        /// </summary>\n        public void CopyTo(TKey[] array, long index)\n        {\n            Monitor.Enter(this); try {\n            for (ulong fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item.Key;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item.Key;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            } finally { Monitor.Exit(this); }\n        }\n\n        #endregion\n\n        #region IEnumerable<TKey> Members\n\n        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            \n            return Keys.GetEnumerator();\n            \n        }\n\n        #endregion\n                \n        #region Private Helper Methods\n\n        private ulong ComputeIncreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_maxFillFactor);\n        }\n\n        private ulong ComputeDecreaseThreshold(ulong capacity)\n        {\n            return (ulong)(capacity * (double)m_minFillFactor);\n        }\n\n        private static long AddSlotsToFreeList(\n                HashKeyNextLong<TKey>[] extraArray, long start)\n        {\n            var length = extraArray.Length - 1;\n            for (long i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizesLong[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizesLong[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                HashKeyLong<TKey> item,\n                NextHashKeyLong<TKey>[] firstArray,\n                ulong capacity,\n                ref HashKeyNextLong<TKey>[] extraArray,\n                ref long freeIndex,\n                ref ulong extraCount)\n        {\n            var fi = ((ulong)item.Hash) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(ulong newCapacity, ulong oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new NextHashKeyLong<TKey>[newCapacity];\n            var extraArray = new HashKeyNextLong<TKey>[\n                                    System.Math.Max((long)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.LongLength / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            ulong newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (ulong fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                ulong fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        long head = -1;\n                        do\n                        {\n                            long next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((ulong)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (ulong)m_extraArray.Length,\n                            (ulong)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (ulong)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    ulong oldFirstCount, ulong oldCapacity,\n                    ulong oldExtraCount, ulong oldExtraCapacity,\n                    ulong newFirstCount, ulong newCapacity,\n                    ulong newExtraCount, ulong newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Support Data Structures\n\n    [Flags]\n    public enum DictReport\n    {\n        Resize = 0x0001,\n    }\n\n    public class ConcurrentDataModifiedException : Exception\n    {\n        public ConcurrentDataModifiedException()\n        { }\n    }\n\n    #endregion\n\n    #region Internal Helper Structures\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyValue<TKey, Tvalue>\n    {\n        public int Hash;\n        public TKey Key;\n        public Tvalue Value;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextHashKeyValue<TKey, Tvalue>\n    {\n        public int Next;\n        public HashKeyValue<TKey, Tvalue> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyValueNext<TKey, Tvalue>\n    {\n        public HashKeyValue<TKey, Tvalue> Item;\n        public int Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKey<TKey>\n    {\n        public int Hash;\n        public TKey Key;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextHashKey<TKey>\n    {\n        public int Next;\n        public HashKey<TKey> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyNext<TKey>\n    {\n        public HashKey<TKey> Item;\n        public int Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct IntValue<Tvalue>\n    {\n        public int Key;\n        public Tvalue Value;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextIntValue<Tvalue>\n    {\n        public int Next;\n        public IntValue<Tvalue> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct IntValueNext<Tvalue>\n    {\n        public IntValue<Tvalue> Item;\n        public int Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextInt\n    {\n        public int Next;\n        public int Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct IntNext\n    {\n        public int Item;\n        public int Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyValueLong<TKey, Tvalue>\n    {\n        public long Hash;\n        public TKey Key;\n        public Tvalue Value;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextHashKeyValueLong<TKey, Tvalue>\n    {\n        public long Next;\n        public HashKeyValueLong<TKey, Tvalue> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyValueNextLong<TKey, Tvalue>\n    {\n        public HashKeyValueLong<TKey, Tvalue> Item;\n        public long Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyLong<TKey>\n    {\n        public long Hash;\n        public TKey Key;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextHashKeyLong<TKey>\n    {\n        public long Next;\n        public HashKeyLong<TKey> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyNextLong<TKey>\n    {\n        public HashKeyLong<TKey> Item;\n        public long Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct LongValue<Tvalue>\n    {\n        public long Key;\n        public Tvalue Value;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextLongValue<Tvalue>\n    {\n        public long Next;\n        public LongValue<Tvalue> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct LongValueNext<Tvalue>\n    {\n        public LongValue<Tvalue> Item;\n        public long Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextLong\n    {\n        public long Next;\n        public long Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct LongNext\n    {\n        public long Item;\n        public long Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SymbolValue<Tvalue>\n    {\n        public Symbol Key;\n        public Tvalue Value;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextSymbolValue<Tvalue>\n    {\n        public int Next;\n        public SymbolValue<Tvalue> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SymbolValueNext<Tvalue>\n    {\n        public SymbolValue<Tvalue> Item;\n        public int Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextSymbol\n    {\n        public int Next;\n        public Symbol Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SymbolNext\n    {\n        public Symbol Item;\n        public int Next;\n    }\n\n    public static class DictConstant\n    {\n        #region Constants\n\n        public const float MaxFillFactorDefault = 0.8f; // growing avg: (0.8 + 0.4)/2 = 0.6\n        public const float MinFillFactorDefault = 0.2f; // shrinking avg: (0.4 + 0.2)/2 = 0.3\n        public const int MinExtraCapacity = 4;\n\n        public readonly static uint[] PrimeSizes =\n        {\n            /*    prime no.           prime */\n            /*           2                3,       +  1 = 2^2 */\n            /*           4 */             7,    // +  1 = 2^3, minimal size\n            /*           6 */            13,    // +  3 = 2^4\n            /*          11 */            31,    // +  1 = 2^5\n            /*          18 */            61,    // +  3 = 2^6\n            /*          31 */           127,    // +  1 = 2^7\n            /*          54 */           251,    // +  5 = 2^8\n            /*          97 */           509,    // +  3 = 2^9\n            /*         172 */          1021,    // +  3 = 2^10\n            /*         309 */          2039,    // +  9 = 2^11\n            /*         564 */          4093,    // +  3 = 2^12\n            /*        1028 */          8191,    // +  1 = 2^13\n            /*        1900 */         16381,    // +  3 = 2^14\n            /*        3512 */         32749,    // + 19 = 2^15\n            /*        6542 */         65521,    // + 15 = 2^16\n            /*       12251 */        131071,    // +  1 = 2^17\n            /*       23000 */        262139,    // +  5 = 2^18\n            /*       43390 */        524287,    // +  1 = 2^19\n            /*       82025 */       1048573,    // +  3 = 2^20\n            /*      155611 */       2097143,    // +  9 = 2^21\n            /*      295947 */       4194301,    // +  3 = 2^22\n            /*      564163 */       8388593,    // + 15 = 2^23\n            /*     1077871 */      16777213,    // +  3 = 2^24\n            /*     2063689 */      33554393,    // + 39 = 2^25\n            /*     3957809 */      67108859,    // +  5 = 2^26\n            /*     7603553 */     134217689,    // + 39 = 2^27\n            /*    14630843 */     268435399,    // + 57 = 2^28\n            /*    28192750 */     536870909,    // +  3 = 2^29\n            /*    54400028 */    1073741789,    // + 35 = 2^30\n            /*   105097565 */    2147483647,    // +  1 = 2^31\n            /*   203280221 */    4294967291,    // +  5 = 2^32\n        };\n\n        public readonly static ulong[] PrimeSizesLong =\n        {\n            /*        prime no.               prime */\n            /*               2                    3,       +  1 = 2^2 */\n            /*               4 */                 7,    // +  1 = 2^3, minimal size\n            /*               6 */                13,    // +  3 = 2^4\n            /*              11 */                31,    // +  1 = 2^5\n            /*              18 */                61,    // +  3 = 2^6\n            /*              31 */               127,    // +  1 = 2^7\n            /*              54 */               251,    // +  5 = 2^8\n            /*              97 */               509,    // +  3 = 2^9\n            /*             172 */              1021,    // +  3 = 2^10\n            /*             309 */              2039,    // +  9 = 2^11\n            /*             564 */              4093,    // +  3 = 2^12\n            /*            1028 */              8191,    // +  1 = 2^13\n            /*            1900 */             16381,    // +  3 = 2^14\n            /*            3512 */             32749,    // + 19 = 2^15\n            /*            6542 */             65521,    // + 15 = 2^16\n            /*           12251 */            131071,    // +  1 = 2^17\n            /*           23000 */            262139,    // +  5 = 2^18\n            /*           43390 */            524287,    // +  1 = 2^19\n            /*           82025 */           1048573,    // +  3 = 2^20\n            /*          155611 */           2097143,    // +  9 = 2^21\n            /*          295947 */           4194301,    // +  3 = 2^22\n            /*          564163 */           8388593,    // + 15 = 2^23\n            /*         1077871 */          16777213,    // +  3 = 2^24\n            /*         2063689 */          33554393,    // + 39 = 2^25\n            /*         3957809 */          67108859,    // +  5 = 2^26\n            /*         7603553 */         134217689,    // + 39 = 2^27\n            /*        14630843 */         268435399,    // + 57 = 2^28\n            /*        28192750 */         536870909,    // +  3 = 2^29\n            /*        54400028 */        1073741789,    // + 35 = 2^30\n            /*       105097565 */        2147483647,    // +  1 = 2^31\n            /*       203280221 */        4294967291,    // +  5 = 2^32\n            /*       393615806 */        8589934583,    // +  9 = 2^33\n            /*       762939111 */       17179869143,    // + 41 = 2^34\n            /*      1480206279 */       34359738337,    // + 31 = 2^35\n            /*      2874398515 */       68719476731,    // +  5 = 2^36\n            /*      5586502348 */      137438953447,    // + 25 = 2^37\n            /*     10866266172 */      274877906899,    // + 45 = 2^38\n            /*     21151907950 */      549755813881,    // +  7 = 2^39\n            /*     41203088796 */     1099511627689,    // + 87 = 2^40\n            /*     80316571436 */     2199023255531,    // + 21 = 2^41\n            /*    156661034233 */     4398046511093,    // + 11 = 2^42\n            /*    305761713237 */     8796093022151,    // + 57 = 2^43\n            /*    597116381732 */    17592186044399,    // + 17 = 2^44\n        };\n\n        #endregion\n\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Symbol/Dict_template.cs",
    "content": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Runtime.CompilerServices;\nusing System.Text;\nusing System.Threading;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var typea   = new[] { \"Dict\",   \"DictSet\", \"IntDict\", \"IntSet\", \"SymbolDict\", \"SymbolSet\",\n    //#                       \"BigDict\", \"BigDictSet\", \"LongDict\", \"LongSet\" };\n    //# var tka     = new[] { \"TKey\",   \"TKey\",    \"int\",     \"int\",    \"Symbol\",     \"Symbol\",\n    //#                       \"TKey\",   \"TKey\",    \"long\",    \"long\" };\n    //# var tva     = new[] { \"TValue\", \"\",        \"TValue\",  \"\",       \"TValue\",     \"\",\n    //#                       \"TValue\", \"\",        \"TValue\",  \"\" };\n    //# var kia     = new[] { 0, 0, 1, 1, 2, 2, 3, 3, 1, 1 };\n    //# var hfa     = new[] { \"\", \"\", \"\", \"m_hfun(\" };\n    //# var gha     = new[] { \".GetHashCode()\", \"\", \".Id\", \")\" };\n    //# var hia     = new[] { \"HashKeyValue\", \"HashKey\", \"IntValue\", \"int\", \"SymbolValue\", \"Symbol\",\n    //#                       \"HashKeyValue\", \"HashKey\", \"LongValue\", \"long\" };\n    //# var ha      = new[] { \".Hash\", \".Hash\", \".Key\", \"\", \".Key.Id\", \".Id\",\n    //#                       \".Hash\", \".Hash\", \".Key\", \"\" };\n    //# var ka      = new[] { \".Key\", \".Key\", \".Key\", \"\", \".Key\", \"\", \".Key\", \".Key\", \".Key\", \"\" };\n    //# foreach (var equatable in new bool[] { false, true }) { var eqString = (equatable ? \"IEq\" : \"\");\n    //# foreach (var fast in new bool[] { false, true }) {\n    //# foreach (var concurrent in new bool[] { false, true }) { if (fast && !concurrent) continue;\n    //# for (int ti = 0; ti < typea.Length; ti++) {\n    //#     var big = ti >= 6;\n    //#     var izero = big ? \"0L\" : \"0\";\n    //#     var wrapped = concurrent && !fast;\n    //#     var concurrentString = (fast ? \"Fast\" : \"\") + (concurrent ? \"Concurrent\" : \"\");\n    //#     var type = concurrentString + typea[ti] + eqString; var ki = kia[ti];\n    //#     var itype = big ? \"long\" : \"int\";\n    //#     var icast = big ? \"(long)\" : \"\";\n    //#     var uitype = big ? \"ulong\" : \"uint\";\n    //#     var nctype = typea[ti] + eqString;\n    //#     var ctype = \"Concurrent\" + nctype;\n    //#     var hasKey = tka[ti] == \"TKey\";\n    //#     if (equatable && !hasKey) continue;\n    //#     var hasValue = tva[ti] == \"TValue\";\n    //#     var isGeneric = hasKey || hasValue;\n    //#     var tpar = (isGeneric ? \"<\" : \"\")\n    //#                + (hasKey ? tka[ti] : \"\")\n    //#                + (hasKey && hasValue ? \", \" : \"\")\n    //#                + (hasValue ? tva[ti] : \"\")\n    //#                + (isGeneric ? \">\" : \"\");\n    //#     var isSym = tka[ti] == \"Symbol\";\n    //#     var hitem = hia[ti];\n    //#     var fun = big && hasKey;\n    //#     var ext = fun ? \"Long\" : \"\";\n    //#     var HashItem = hitem + ext + tpar;\n    //#     var NextHashItem = \"Next\" + hitem.Capitalized() + ext + tpar;\n    //#     var HashItemNext = hitem.Capitalized() + \"Next\" + ext + tpar;\n    //#     var HashFun = hfa[ki];\n    //#     var GetHash = gha[ki];\n    //#     var Hash = ha[ti];\n    //#     var Key = ka[ti];\n    //#     var tkey = tka[ti];\n    //#     var tvalue = tva[ti];\n    //#     var uintCast = hasKey ? \"\" : \"(uint)\";\n    //#     var ValuePair = hasValue ? \"ValuePair\" : \"\";\n    //#     var idict = \"ICountableDict\" + (hasValue ? \"\" : \"Set\");\n    #region __type____tpar__\n\n    /// <summary>\n    //# if (hasValue) {\n    /// A __type__ is an alternate implementation of a Dictionary that can\n    /// optionally act as a stack for all items with the same key.\n    //# } else {\n    /// A __type__ is an alternate implementation of a HashSet.\n    //# }\n    /// It is implemented as a hashtable with external linking, that uses\n    /// primes as the table size in order to reduce the danger of funneling.\n    /// </summary>\n    public class __type__/*# if (isGeneric) { */</*# if (hasKey) { */TKey/*# } if (hasValue) { if (hasKey) { */, /*# } */TValue/*# } */>/*# } */\n            //# if (!wrapped) {\n            : /*# if (!big) { */IIntCountable, /*# } */__idict__,/*# if (!hasValue) { */ IDictSet<__tkey__>,/*# } else { */ IDict<__tkey__, TValue>,/*# } */\n              IEnumerable, IEnumerable</*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */>/*# if (!big && !concurrent) { */,\n              ICollection, ICollection</*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */>/*# if (hasValue) { */,\n              IDictionary<__tkey__, TValue>, IReadOnlyDictionary<__tkey__, TValue>/*# } }*/\n        //# }\n        //# if (equatable) {\n        where TKey : IEquatable<TKey>\n        //# }\n    {\n        //# if (wrapped) {\n        private readonly __nctype____tpar__ m_dict;\n        //# } else { // !wrapped\n        //# if (concurrent) {\n        private long m_version;\n        //# }\n        //# if (fun) {\n        private readonly Func<__tkey__, __itype__> m_hfun;\n        //# }\n        private __uitype__ m_capacity;\n        private __NextHashItem__[] m_firstArray;\n        private __HashItemNext__[] m_extraArray;\n        private __uitype__ m_count;\n        private __uitype__ m_increaseThreshold;\n        private __uitype__ m_decreaseThreshold;\n        //# if (hasValue) {\n        private readonly bool m_doNotStackDuplicateKeys;\n        //# }\n        private __itype__ m_freeIndex;\n        private int m_capacityIndex;\n        private __uitype__ m_extraCount;\n        private float m_maxFillFactor;\n        private float m_minFillFactor;\n        public DictReport Report;\n        //# } // !wrapped\n\n        #region Constructors\n\n        //# if (wrapped) {\n        /// <summary>\n        /// A __ctype__ can only be concstructed by wrapping its non-concurrent\n        /// counterpart.\n        /// </summary>\n        public __type__(__nctype____tpar__ dict)\n        {\n            m_dict = dict;\n        }\n\n        //# } else { // !wrapped\n        /// <summary>\n        /// Create a __type__ that autmatically grows and shrinks as necessary.\n        //# if (hasValue) {\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// __type__ acts as a stack for all items with the same key.\n        //# }\n        /// </summary>\n        public __type__(/*# if (fun) { */Func<__tkey__, __itype__> hfun/*# } if (fun && hasValue) { */, /*# } if (hasValue) { */bool stackDuplicateKeys = false/*# } */)\n            : this(/*# if (fun) { */hfun, /*# } */DictConstant.PrimeSizes__ext__[0], (__uitype__)DictConstant.MinExtraCapacity/*# if (hasValue) { */,\n                   stackDuplicateKeys/*# } */)\n        { }\n\n        /// <summary>\n        /// Create a __type__ that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        //# if (hasValue) {\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// __type__ acts as a stack for all items with the same key.\n        //# }\n        /// </summary>\n        public __type__(/*# if (fun) { */Func<__tkey__, __itype__> hfun, /*# } */__itype__ initialCapacity)\n            : this(/*# if (fun) { */hfun, /*# } */System.Math.Max((__uitype__)initialCapacity,\n                                         DictConstant.PrimeSizes__ext__[0]),\n                   (__uitype__)DictConstant.MinExtraCapacity/*# if (hasValue) { */, false/*# } */)\n        { }\n\n        //# if (hasValue) {\n        /// <summary>\n        /// Create a __type__ that autmatically grows and shrinks as necessary,\n        /// but also specify an initial capacity.\n        //# if (hasValue) {\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// __type__ acts as a stack for all items with the same key.\n        //# }\n        /// </summary>\n        public __type__(/*# if (fun) { */Func<__tkey__, __itype__> hfun, /*# } */__itype__ initialCapacity, bool stackDuplicateKeys)\n            : this(/*# if (fun) { */hfun, /*# } */System.Math.Max((__uitype__)initialCapacity,\n                                         DictConstant.PrimeSizes__ext__[0]),\n                   (__uitype__)DictConstant.MinExtraCapacity, stackDuplicateKeys)\n        { }\n\n        //# }\n        /// <summary>\n        /// Create a __type__ and initialize it to contain the supplied\n        /// items.\n        //# if (hasValue) {\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// __type__ acts as a stack for all items with the same key.\n        //# }\n        /// </summary>\n        public __type__(/*# if (fun) { */Func<__tkey__, __itype__> hfun, /*# } */IEnumerable</*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */> items/*# if (hasValue) { */,\n                bool stackDuplicateKeys = false/*# } */)\n            : this(/*# if (fun) { */hfun, /*# } */Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes__ext__[0]), (__uitype__)DictConstant.MinExtraCapacity/*# if (hasValue) { */,\n                   stackDuplicateKeys/*# } */)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        //# if (isSym) {\n        /// <summary>\n        /// Create a __type__ and initialize to contain the supplied items.\n        /// Note hat this incurs the overhead of converting all string keys\n        /// to symbols.\n        //# if (hasValue) {\n        /// If the optional parameter stackDuplicateKeys is set to true, the\n        /// __type__ acts as a stack for all items with the same key.\n        //# }\n        /// </summary>\n        public __type__(IEnumerable</*# if (hasValue) { */KeyValuePair</*# } */string/*# if (hasValue) { */, TValue>/*# } */> items/*# if (hasValue) { */,\n                bool stackDuplicateKeys = false/*# } */)\n            : this(Math.Max(items is ICollection c ? (uint)c.Count : 0u, DictConstant.PrimeSizes__ext__[0]), DictConstant.MinExtraCapacity/*# if (hasValue) { */,\n                   stackDuplicateKeys/*# } */)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        //# } // isSym\n        private __type__(\n                /*# if (fun) { */Func<__tkey__, __itype__> hfun, /*# } */__uitype__ firstCapacity, __uitype__ extraCapacity/*# if (hasValue) { */,\n                bool stackDuplicateKeys = false/*# } */)\n        {\n            //# if (concurrent) {\n            m_version = 0;\n            //# }\n            //# if (fun) {\n            m_hfun = hfun;\n            //# }\n            m_maxFillFactor = DictConstant.MaxFillFactorDefault;\n            m_minFillFactor = DictConstant.MinFillFactorDefault;\n            //# if (hasValue) {\n            m_doNotStackDuplicateKeys = !stackDuplicateKeys;\n            //# }\n            m_capacityIndex = 0;\n            m_capacity = DictConstant.PrimeSizes__ext__[m_capacityIndex];\n            m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            while (firstCapacity >= m_increaseThreshold)\n            {\n                m_capacity = DictConstant.PrimeSizes__ext__[++m_capacityIndex];\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n            }\n            firstCapacity /= 4;\n            while (firstCapacity >= extraCapacity) extraCapacity *= 2;\n            m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n            m_firstArray = new __NextHashItem__[m_capacity];\n            m_extraArray = new __HashItemNext__[extraCapacity];\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            Report = 0;\n        }\n\n        //# } // !wrapped\n        #endregion\n\n        #region Properties\n\n        //# if (!big) {\n        /// <summary>\n        /// Returns the number of items currently contained in the __type__.\n        /// </summary>\n        public int Count\n        {\n            get\n            {\n                //# if (wrapped) {\n                return m_dict.Count;\n                //# } else {\n                return (int)m_count;\n                //# }\n            }\n        }\n\n        //# } // !big\n        /// <summary>\n        /// Returns the number of items currently contained in the __type__\n        /// as long.\n        /// </summary>\n        public long LongCount\n        {\n            get\n            {\n                //# if (wrapped) {\n                return m_dict.LongCount;\n                //# } else {\n                return (long)m_count;\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Returns the number of items currently contained in the __type__\n        /// as long.\n        /// </summary>\n        public __uitype__ Capacity\n        {\n            get\n            {\n                //# if (wrapped) {\n                return m_dict.Capacity;\n                //# } else {\n                return m_capacity;\n                //# }\n            }\n            set\n            {\n                //# if (wrapped) {\n                m_dict.Capacity = value;\n                //# } else {\n                if (value < m_count)\n                    throw new System.ArgumentOutOfRangeException(\"The new capacity is less than the current number of elements.\");\n                Resize(value, m_capacity);\n                //# }\n            }\n        }\n\n        //# if (!wrapped) {\n        /// <summary>\n        /// Setting the maximal fill factor makes it possible to fine-tune\n        /// the performance for certain applications. Normally this should\n        /// not be necessary.\n        /// </summary>\n        public float MaxFillFactor\n        {\n            get { return m_maxFillFactor; }\n            set\n            {\n                //# if (concurrent) {\n                Monitor.Enter(this); try {\n                //# }\n                m_maxFillFactor = value;\n                m_increaseThreshold = ComputeIncreaseThreshold(m_capacity);\n                //# if (concurrent) {\n                } finally { Monitor.Exit(this); }\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Setting the minimal fill factor makes it possible to influence\n        /// the shrinking behaviour of the __type__. Normally this should\n        /// be set to a quater of the maximal fill factor. In order to\n        /// completely prevent shrinking it can also be set to 0.0f.\n        /// </summary>\n        public float MinFillFactor\n        {\n            get { return m_minFillFactor; }\n            set\n            {\n                //# if (concurrent) {\n                Monitor.Enter(this); try {\n                //# }\n                m_minFillFactor = value;\n                m_decreaseThreshold = ComputeDecreaseThreshold(m_capacity);\n                //# if (concurrent) {\n                } finally { Monitor.Exit(this); }\n                //# }\n            }\n        }\n\n        //# if (!concurrent) {\n        /// <summary>\n        /// Always returns false. Part of the ICollection implementation.\n        /// </summary>\n        public bool IsReadOnly { get { return false; } }\n\n        public bool IsSynchronized { get { return false; } }\n\n        public object SyncRoot { get { return this; } }\n        //# }\n        //# if (!hasValue) {\n        public IEnumerable<__tkey__> Items { get { return Keys; } }\n        //# } else { // hasValue\n        public IEnumerable<KeyValuePair<__tkey__, TValue>> Items { get { return KeyValuePairs; } }\n        //# }\n        /// <summary>\n        /// Returns all keys in the dictionary.\n        //# if (concurrent) {\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        //# }\n        /// </summary>\n        public IEnumerable<__tkey__> Keys\n        {\n            get\n            {\n                //# if (concurrent) {\n                Monitor.Enter(this); try { var version = m_version;\n                //# }\n                for (__uitype__ fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    //# if (!concurrent) {\n                    yield return m_firstArray[fi].Item__Key__;\n                    //# } else {\n                    var k = m_firstArray[fi].Item__Key__;\n                    Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    //# }\n                    while (ei > 0)\n                    {\n                        //# if (!concurrent) {\n                        yield return m_extraArray[ei].Item__Key__;\n                        //# } else {\n                        k = m_extraArray[ei].Item__Key__;\n                        Monitor.Exit(this); yield return k; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        //# }\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                //# if (concurrent) {\n                } finally { Monitor.Exit(this); }\n                //# }\n            }\n        }\n\n        public Type KeyType { get { return typeof(__tkey__); } }\n\n        //# if (!hasValue) {\n        public IEnumerable<object> Objects\n        {\n            get\n            {\n                foreach (object obj in Keys)\n                    yield return obj;\n            }\n        }\n\n        //# }\n        //# if (hasValue) {\n        /// <summary>\n        /// Returns all values in the __type__.\n        //# if (concurrent) {\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        //# }\n        /// </summary>\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                //# if (concurrent) {\n                Monitor.Enter(this); try { var version = m_version;\n                //# }\n                for (__uitype__ fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    //# if (!concurrent) {\n                    yield return m_firstArray[fi].Item.Value;\n                    //# } else {\n                    var v = m_firstArray[fi].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    //# }\n                    while (ei > 0)\n                    {\n                        //# if (!concurrent) {\n                        yield return m_extraArray[ei].Item.Value;\n                        //# } else {\n                        v = m_extraArray[ei].Item.Value;\n                        Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        //# }\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                //# if (concurrent) {\n                } finally { Monitor.Exit(this); }\n                //# }\n            }\n        }\n\n        public Type ValueType { get { return typeof(TValue); } }\n\n        /// <summary>\n        /// Returns all key value pairs in the __type__.\n        //# if (concurrent) {\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        //# }\n        /// </summary>\n        public IEnumerable<KeyValuePair<__tkey__, TValue>> KeyValuePairs\n        {\n            get\n            {\n                //# if (concurrent) {\n                Monitor.Enter(this); try { var version = m_version;\n                //# }\n                for (__uitype__ fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    //# if (!concurrent) {\n                    yield return new KeyValuePair<__tkey__, TValue>(\n                            m_firstArray[fi].Item__Key__, m_firstArray[fi].Item.Value);\n                    //# } else {\n                    var kvp = new KeyValuePair<__tkey__, TValue>(\n                            m_firstArray[fi].Item__Key__, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    //# }\n                    while (ei > 0)\n                    {\n                        //# if (!concurrent) {\n                        yield return new KeyValuePair<__tkey__, TValue>(\n                                m_extraArray[ei].Item__Key__, m_extraArray[ei].Item.Value);\n                        //# } else {\n                        kvp = new KeyValuePair<__tkey__, TValue>(\n                                m_extraArray[ei].Item__Key__, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        //# }\n                        ei = m_extraArray[ei].Next;\n                    }\n                }\n                //# if (concurrent) {\n                } finally { Monitor.Exit(this); }\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Returns all key value pairs in the __type__, in such a way,\n        /// that the stack order is correct when the pairs are put into a\n        /// new __type__ in the order they are returned.\n        //# if (concurrent) {\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the enumeration.\n        //# }\n        /// </summary>\n        public IEnumerable<KeyValuePair<__tkey__, TValue>> KeyValuePairsForStorage\n        {\n            get\n            {\n                //# if (concurrent) {\n                Monitor.Enter(this); try { var version = m_version;\n                //# }\n                var stack = new Stack<__itype__>();\n                for (__uitype__ fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    while (ei > 0) { stack.Push(ei); ei = m_extraArray[ei].Next; }\n                    //# if (concurrent) {\n                    var kvp = default(KeyValuePair<__tkey__, TValue>);\n                    //# }\n                    while (stack.Count > 0)\n                    {\n                        ei = stack.Pop();\n                        //# if (!concurrent) {\n                        yield return new KeyValuePair<__tkey__, TValue>(\n                                m_extraArray[ei].Item__Key__, m_extraArray[ei].Item.Value);\n                        //# } else {\n                        kvp = new KeyValuePair<__tkey__, TValue>(\n                                m_extraArray[ei].Item__Key__, m_extraArray[ei].Item.Value);\n                        Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                        if (version != m_version)\n                            throw new ConcurrentDataModifiedException();\n                        //# }\n                    }\n                    //# if (!concurrent) {\n                    yield return new KeyValuePair<__tkey__, TValue>(\n                            m_firstArray[fi].Item__Key__, m_firstArray[fi].Item.Value);\n                    //# } else {\n                    kvp = new KeyValuePair<__tkey__, TValue>(\n                            m_firstArray[fi].Item__Key__, m_firstArray[fi].Item.Value);\n                    Monitor.Exit(this); yield return kvp; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                    //# }\n                }\n                //# if (concurrent) {\n                } finally { Monitor.Exit(this); }\n                //# }\n            }\n        }\n\n        public IEnumerable<(object, object)> ObjectPairs\n        {\n            get\n            {\n                foreach (var kvp in KeyValuePairsForStorage)\n                    yield return (kvp.Key, kvp.Value);\n            }\n        }\n\n        //# } // hasValue\n        //# } // !wrapped\n        //# if (wrapped) {\n        /// <summary>\n        /// Return the non-concurrent contained __type__.\n        /// </summary>\n        public __nctype____tpar__ NonConcurrent\n        {\n            get { return m_dict; }\n        }\n\n        //# }\n        #endregion\n\n        //# if (hasValue) {\n        #region Indexer\n\n        /// <summary>\n        /// Get or set the item with the supplied key. If multiple items with\n        /// the same key are allowed, the __type__ acts as a stack.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public TValue this[__tkey__ key]\n        {\n            get\n            {\n                //# if (wrapped) {\n                Monitor.Enter(this); try { return m_dict[key]; } finally { Monitor.Exit(this); }\n                //# } else { // !wrapped\n                var hash = __HashFun__key__GetHash__;\n                //# if (concurrent) {\n                Monitor.Enter(this); try {\n                //# }\n                var fi = ((__uitype__)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                    throw new KeyNotFoundException();\n                if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                        && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                //# if (concurrent) {\n                } finally { Monitor.Exit(this); }\n                //# }\n                throw new KeyNotFoundException();\n                //# } // !wrapped\n            }\n            set\n            {\n                //# if (wrapped) {\n                Monitor.Enter(this); try { m_dict[key] = value; } finally { Monitor.Exit(this); }\n                //# } else { // !wrapped\n                var hash = __HashFun__key__GetHash__;\n                //# if (concurrent) {\n                Monitor.Enter(this); try { ++m_version;\n                //# }\n                if (m_count >= m_increaseThreshold) IncreaseCapacity();\n                var fi = ((__uitype__)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    ++m_count;\n                    m_firstArray[fi].Next = -1;\n                    //# if (hasKey) {\n                    m_firstArray[fi].Item.Hash = hash;\n                    //# }\n                    m_firstArray[fi].Item__Key__ = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return;\n                }\n                if (m_doNotStackDuplicateKeys)\n                {\n                    if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                        && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n                    {\n                        m_firstArray[fi].Item.Value = value;\n                        return;\n                    }\n                    while (ei > 0)\n                    {\n                        if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                            && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                        {\n                            m_extraArray[ei].Item.Value = value;\n                            return;\n                        }\n                        ei = m_extraArray[ei].Next;\n                    }\n                    ei = m_firstArray[fi].Next;\n                }\n                ++m_count;\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.__ext__Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = ei;\n\n                m_firstArray[fi].Next = ni;\n                //# if (hasKey) {\n                m_firstArray[fi].Item.Hash = hash;\n                //# }\n                m_firstArray[fi].Item__Key__ = key;\n                m_firstArray[fi].Item.Value = value;\n                //# if (concurrent) {\n                } finally { Monitor.Exit(this); }\n                //# }\n                //# } // !wrapped\n            }\n        }\n\n        #endregion\n\n        //# } // hasValue\n        #region Public Methods\n\n        //# var aortype = hasValue ? \"void\" : \"bool\";\n        /// <summary>\n        /// Add the item with supplied key/*# if (hasValue) { */ and the supplied value/*# } */\n        /// both supplied as generic objects, to the __type__. Note that the supplied key\n        /// and value are cast to the concrete type of the keys and values used in the __type__\n        /// and this will fail if they are of different types.\n        /// </summary>\n        public __aortype__ AddObject(object objkey/*# if (hasValue) { */, object objvalue/*# } */)\n        {\n            /*# if (!hasValue) { */return /*# } */Add((__tkey__)objkey/*# if (hasValue) { */, (__tvalue__)objvalue/*# } */);\n        }\n\n        //# if (!hasValue && !big && !concurrent) {\n        void ICollection<__tkey__>.Add(__tkey__ key)\n        {\n            Add(key);\n        }\n\n        //# }\n        //# foreach (var isTry in new[] { false, true }) {\n        //# var rtype = (isTry || !hasValue) ? \"bool\" : \"void\";\n        //# var tryPrefix = isTry ? \"Try\" : \"\";\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        /// <summary>\n        /// Add the item with the supplied key/*# if (hasValue) { */ and the supplied value/*# } */\n        /// to the __type__.\n        /// </summary>\n        public __rtype__ __tryPrefix__Add(__tkey__ key/*#\n                if (hasHashPar) { */, __itype__ hash/*# }\n                if (hasValue) { */, __tvalue__ value/*# } */)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                /*# if (isTry || !hasValue) { */return /*# } */m_dict.__tryPrefix__Add(key/*#\n                        if (hasHashPar) { */, hash/*# } if (hasValue) { */, value/*# } */);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (!hasHashPar) {\n            var hash = __HashFun__key__GetHash__;\n            //# }\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            if (m_count >= m_increaseThreshold) IncreaseCapacity();\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                ++m_count;\n                //# if (concurrent) {\n                ++m_version;\n                //# }\n               m_firstArray[fi].Next = -1;\n                //# if (hasKey) {\n                m_firstArray[fi].Item.Hash = hash;\n                //# }\n                m_firstArray[fi].Item__Key__ = key;\n                //# if (hasValue) {\n                m_firstArray[fi].Item.Value = value;\n                //# }\n                return/*# if (isTry || !hasValue) { */ true/*# } */;\n            }\n            //# if (hasValue) {\n            if (m_doNotStackDuplicateKeys)\n            //# }\n            {\n                // no duplicate keys, check for existing entries\n                if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n                {\n                    //# if (hasValue && !isTry) {\n                    throw new ArgumentException(\"duplicate key\");\n                    //# } else {\n                    return/*# if (isTry || !hasValue) { */ false/*# } */;\n                    //# }\n                }\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                        && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                    {\n                        //# if (hasValue && !isTry) {\n                        throw new ArgumentException(\"duplicate key\");\n                        //# } else {\n                        return/*# if (isTry || !hasValue) { */ false/*# } */;\n                        //# }\n                    }\n                    ei = m_extraArray[ei].Next;\n                }\n                ei = m_firstArray[fi].Next;\n            }\n            ++m_count;\n            //# if (concurrent) {\n            ++m_version;\n            //# }\n            ++m_extraCount;\n            if (m_freeIndex < 0)\n            {\n                var length = m_extraArray.Length;\n                m_extraArray = m_extraArray.Resized(length * 2);\n                m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n            }\n            var ni = m_freeIndex;\n            m_freeIndex = m_extraArray[ni].Next;\n            m_extraArray[ni].Item = m_firstArray[fi].Item;\n            m_extraArray[ni].Next = ei;\n            m_firstArray[fi].Next = ni;\n            //# if (hasKey) {\n            m_firstArray[fi].Item.Hash = hash;\n            //# }\n            m_firstArray[fi].Item__Key__ = key;\n            //# if (hasValue) {\n            m_firstArray[fi].Item.Value = value;\n            //# }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            //# if (isTry || !hasValue) {\n            return true;\n            //# }\n            //# } // !wrapped\n        }\n\n        //# } // hasHashPar\n        //# } // isTry\n        //# if (isSym) {\n        /// <summary>\n        /// Adds the supplied item to the __type__. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(string key/*# if (hasValue) { */, __tvalue__ value/*# } */)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(key.ToSymbol()/*# if (hasValue) { */, value/*# } */);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            Add(key.ToSymbol()/*# if (hasValue) { */, value/*# } */);\n            //# } // !wrapped\n        }\n\n        //# if (hasValue) {\n        /// <summary>\n        /// Add the supplied item to the __type__. Note that this incurs the\n        /// overhead of converting the string key to a symbol.\n        /// </summary>\n        public void Add(KeyValuePair<string, TValue> item)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key.ToSymbol(), item.Value);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            Add(item.Key.ToSymbol(), item.Value);\n            //# } // !wrapped\n        }\n\n        //# } // hasValue\n        //# } // isSym\n        //# if (hasValue) {\n        /// <summary>\n        /// Add the supplied item to the __type__.\n        /// </summary>\n        public void Add(KeyValuePair<__tkey__, TValue> item)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                m_dict.Add(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            Add(item.Key, item.Value);\n            //# } // !wrapped\n        }\n\n        /// <summary>\n        /// Add the supplied items to the __type__.\n        /// </summary>\n        public void AddRange(IEnumerable<KeyValuePair<__tkey__, TValue>> items)\n        {\n            foreach (var item in items) Add(item);\n        }\n\n        //# } else { // !hasValue\n        /// <summary>\n        /// Add the supplied keys to the __type__.\n        /// </summary>\n        public void AddRange(IEnumerable<__tkey__> keys)\n        {\n            foreach (var key in keys) Add(key);\n        }\n\n        //# } // !hasValue\n        //# foreach (var keyStr in new string[] { \"\", \"Key\" }) { if (keyStr != \"\" && !hasValue) continue;\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        /// <summary>\n        /// Returns true if the __type__ contains the item with the supplied\n        /// key.\n        /// </summary>\n        public bool Contains__keyStr__(__tkey__ key/*# if (hasHashPar) { */, __itype__ hash/*# } */)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try { return m_dict.Contains(key); } finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (!hasHashPar) {\n            var hash = __HashFun__key__GetHash__;\n            //# }\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            return false;\n            //# } // !wrapped\n        }\n\n        //# } // hasHashPar\n        //# } // keyStr\n        //# if (hasValue) {\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        /// <summary>\n        /// Returns true if the __type__ contains the item with the supplied\n        /// key and the supplied value.\n        /// </summary>\n        public bool Contains(__tkey__ key/*# if (hasHashPar) { */, __itype__ hash/*# } */, TValue value)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try { return m_dict.Contains(key, value); } finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (!hasHashPar) {\n            var hash = __HashFun__key__GetHash__;\n            //# }\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                && key.Equals(m_firstArray[fi].Item__Key__)/*# } */\n                && EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value))\n                return true;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_extraArray[ei].Item__Key__)/*# } */\n                    && EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value))\n                    return true;\n                ei = m_extraArray[ei].Next;\n            }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            return false;\n            //# } // !wrapped\n        }\n\n        //# } // hasHashPar\n        /// <summary>\n        /// Returns true if the __type__ contains the item with the supplied\n        /// KeyValuePair.\n        /// </summary>\n        public bool Contains(KeyValuePair<__tkey__, TValue> item)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Contains(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            return Contains(item.Key, item.Value);\n            //# } // !wrapped\n        }\n\n        //# if (hasValue) {\n        /// <summary>\n        /// Returns true if the __type__ contains the given value.\n        /// </summary>\n        public bool ContainsValue(TValue value)\n        {\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            //# if (wrapped) {\n            return m_dict.ContainsValue(value);\n            //# } else { // wrapped\n            for (__uitype__ fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                if (EqualityComparer<TValue>.Default.Equals(value, m_firstArray[fi].Item.Value)) return true;\n                while (ei > 0)\n                {\n                    if (EqualityComparer<TValue>.Default.Equals(value, m_extraArray[ei].Item.Value)) return true;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            return false;\n            //# } // !wrapped \n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n        }\n\n        //# } // hasValue\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        //# foreach (var hasDefault in new[] { false, true }) {\n        //# foreach (var isCreate in new[] { false, true }) {\n        //# if (hasDefault && isCreate) continue;\n        //# var orCreate = isCreate ? \"OrCreate\" : \"\";\n        /// <summary>\n        /// Get the element with the supplied key.\n        //# if (isCreate) {\n        /// If the element is not found, the supplied creator is called to create\n        /// a new element that is added to the __type__ and returned.\n        //# } else if (hasDefault) {\n        /// Returns the supplied default value if the element is not found.\n        //# } else {\n        /// Throws an exception if the element is not found. This is an alias of the indexer.\n        //# }\n        /// </summary>\n        public TValue Get__orCreate__(__tkey__ key/*#\n                if (hasHashPar) { */, __itype__ hash/*# }\n                if (isCreate) { */, Func<__tkey__, TValue> creator/*# }\n                if (hasDefault) { */, TValue defaultValue/*# } */)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.Get__orCreate__(key/*#\n                            if (hasHashPar) { */, hash/*# } if (isCreate) { */, creator/*# } */);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (!hasHashPar) {\n            var hash = __HashFun__key__GetHash__;\n            //# }\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            //# if (isCreate) {\n            {\n                var value = creator(key);\n                return AddCreated(key, hash, value);\n            }\n            //# } else if (hasDefault) {\n                return defaultValue;\n            //# } else { // !isCreate && ! isDefault\n                throw new KeyNotFoundException();\n            //# }\n            if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n                return m_firstArray[fi].Item.Value;\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                    return m_extraArray[ei].Item.Value;\n                ei = m_extraArray[ei].Next;\n            }\n            //# if (isCreate) {\n            var val = creator(key);\n            return AddCreated(key, hash, val);\n            //# } else if (hasDefault) {\n            return defaultValue;\n            //# }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            //# if (!isCreate && !hasDefault) {\n            throw new KeyNotFoundException();\n            //# }\n            //# } // !wrapped\n        }\n\n        //# if (!wrapped && isCreate && !hasHashPar) {\n        __tvalue__ AddCreated(__tkey__ key, __itype__ hash, __tvalue__ value)\n        {\n            while (true)\n            {\n                var fi = ((__uitype__)hash) % m_capacity;\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0)\n                {\n                    if (m_count >= m_increaseThreshold)\n                    {\n                        IncreaseCapacity();\n                        continue;\n                    }\n                    ++m_count;\n                    //# if (concurrent) {\n                    ++m_version;\n                    //# }\n                    m_firstArray[fi].Next = -1;\n                    //# if (hasKey) {\n                    m_firstArray[fi].Item.Hash = hash;\n                    //# }\n                    m_firstArray[fi].Item__Key__ = key;\n                    m_firstArray[fi].Item.Value = value;\n                    return value;\n                }\n                if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n                    return m_firstArray[fi].Item.Value;\n                while (ei > 0)\n                {\n                    if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                        && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                        return m_extraArray[ei].Item.Value;\n                    ei = m_extraArray[ei].Next;\n                }\n                if (m_count >= m_increaseThreshold)\n                {\n                    IncreaseCapacity();\n                    continue;\n                }\n                ei = m_firstArray[fi].Next;\n                ++m_count;\n                //# if (concurrent) {\n                ++m_version;\n                //# }\n                ++m_extraCount;\n                if (m_freeIndex < 0)\n                {\n                    var length = m_extraArray.Length;\n                    m_extraArray = m_extraArray.Resized(length * 2);\n                    m_freeIndex = AddSlotsToFreeList(m_extraArray, length);\n                }\n                var ni = m_freeIndex;\n                m_freeIndex = m_extraArray[ni].Next;\n                m_extraArray[ni].Item = m_firstArray[fi].Item;\n                m_extraArray[ni].Next = m_firstArray[fi].Next;\n                m_firstArray[fi].Next = ni;\n                //# if (hasKey) {\n                m_firstArray[fi].Item.Hash = hash;\n                //# }\n                m_firstArray[fi].Item__Key__ = key;\n                m_firstArray[fi].Item.Value = value;\n                return value;\n            }\n        }\n\n        //# } // !wrapped && isCreate && hasHashPar\n        //# } // isCreate\n        //# } // hasDefault\n        //# } // hasHashPar\n        /// <summary>\n        /// Get the element with the supplied key. Returns the default\n        /// value of the value type if the element is not found.\n        /// </summary>\n        public TValue GetOrDefault(__tkey__ key)\n        {\n            return Get(key, default(TValue));\n        }\n\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        /// <summary>\n        /// Try to retrieve the value with the supplied key, return true if\n        /// successful and return the value via the out parameter.\n        /// </summary>\n        public bool TryGetValue(__tkey__ key, /*#\n                if (hasHashPar) { */__itype__ hash, /*# } */out TValue value)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryGetValue(key, /*#\n                        if (hasHashPar) { */hash, /*# } */out value);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (!hasHashPar) {\n            var hash = __HashFun__key__GetHash__;\n            //# }\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) { value = default(TValue); return false; }\n            if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n            {\n                value = m_firstArray[fi].Item.Value;\n                return true;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                {\n                    value = m_extraArray[ei].Item.Value;\n                    return true;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            value = default(TValue);\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            return false;\n            //# } // !wrapped\n        }\n\n        //# }\n        //# if (!wrapped) {\n        /// <summary>\n        /// Return all the value with the given key. This method is only\n        /// useful if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// </summary>\n        public IEnumerable<TValue> ValuesWithKey(__tkey__ key)\n        {\n            var hash = __HashFun__key__GetHash__;\n            //# if (concurrent) {\n            Monitor.Enter(this); try { var version = m_version;\n            //# }\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) yield break;\n            if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n                //# if (!concurrent) {\n                yield return m_firstArray[fi].Item.Value;\n            //# } else {\n            {\n                var v = m_firstArray[fi].Item.Value;\n                Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                if (version != m_version)\n                    throw new ConcurrentDataModifiedException();\n            }\n            //# }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                    //# if (!concurrent) {\n                    yield return m_extraArray[ei].Item.Value;\n                //# } else {\n                {\n                    var v = m_extraArray[ei].Item.Value;\n                    Monitor.Exit(this); yield return v; Monitor.Enter(this);\n                    if (version != m_version)\n                        throw new ConcurrentDataModifiedException();\n                }\n                //# }\n                ei = m_extraArray[ei].Next;\n            }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n        }\n\n        //# if (!concurrent) {\n        /// <summary>\n        /// Gets an enumerator for values.\n        /// Should be preferred over Values enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValueEnumerator GetValuesEnumerator()\n        {\n            return new ValueEnumerator(this);\n        }\n\n        public struct ValueEnumerator : IEnumerator<TValue>\n        {\n            __type__/*# if (isGeneric) { */</*# if (hasKey) { */TKey/*# } if (hasValue) { if (hasKey) { */, /*# } */TValue/*# } */>/*# } */.Enumerator m_inner;\n\n            public ValueEnumerator(__type__/*# if (isGeneric) { */</*# if (hasKey) { */TKey/*# } if (hasValue) { if (hasKey) { */, /*# } */TValue/*# } */>/*# } */ dict)\n            {\n                m_inner = dict.GetEnumerator();\n            }\n\n            public TValue Current => m_inner.Current.Value;\n\n            object IEnumerator.Current => Current;\n\n            public void Dispose() => m_inner.Dispose();\n\n            public bool MoveNext() => m_inner.MoveNext();\n\n            public void Reset() => m_inner.Reset();\n        }\n\n        /// <summary>\n        /// Gets an enumerator for values with key. It is only useful\n        /// if multiple item with the same key are allowed (stackDuplicateKeys=true).\n        /// The order of the values is reversed to their additions (like a stack).\n        /// Should be preferred over ValuesWithKey enumeration in\n        /// performance critical code.\n        /// </summary>\n        public ValuesWithKeyEnumerator GetValuesWithKeyEnumerator(__tkey__ key)\n        {\n            return new ValuesWithKeyEnumerator(this, key);\n        }\n\n        public struct ValuesWithKeyEnumerator : IEnumerator<TValue>\n        {\n            readonly __type__/*# if (isGeneric) { */</*# if (hasKey) { */TKey/*# } if (hasValue) { if (hasKey) { */, /*# } */TValue/*# } */>/*# } */ m_dict;/*# if (hasKey) { */\n            readonly TKey m_key;/*# } */\n            readonly __itype__ m_hash;\n            __itype__ m_extraIndex;\n            TValue m_current;\n\n            public ValuesWithKeyEnumerator(__type__/*# if (isGeneric) { */</*# if (hasKey) { */TKey/*# } if (hasValue) { if (hasKey) { */, /*# } */TValue/*# } */>/*# } */ dict, __tkey__ key)\n            {\n                m_dict = dict;/*# if (hasKey) { */\n                m_key = key;/*# } */\n                m_hash = /*# if (fun) {*/dict./*# } */__HashFun__key__GetHash__;\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n\n            public readonly TValue Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex == int.MaxValue)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var fi = ((uint)m_hash) % m_dict.m_capacity;\n                    m_extraIndex = fa[fi].Next;\n                    if (m_extraIndex == 0) return false;\n                    if (fa[fi].Item__Hash__ == m_hash/*# if (hasKey) { */\n                        && m_key.Equals(fa[fi].Item__Key__)/*# } */)\n                    {\n                        m_current = fa[fi].Item.Value;\n                        return true;\n                    }\n                }\n                if (m_extraIndex > 0)\n                {\n                    var ea = m_dict.m_extraArray;\n                    do\n                    {\n                        var valid = ea[m_extraIndex].Item__Hash__ == m_hash/*# if (hasKey) { */\n                                    && m_key.Equals(ea[m_extraIndex].Item__Key__)/*# } */;\n                        if (valid) m_current = ea[m_extraIndex].Item.Value;\n                        m_extraIndex = ea[m_extraIndex].Next;\n                        if (valid) return true;\n                    } while (m_extraIndex > 0);\n                }\n\n                return false;\n            }\n\n            public void Reset()\n            {\n                m_extraIndex = int.MaxValue;\n                m_current = default(TValue);\n            }\n        }\n        //# } // !concurrent\n\n        //# } // !wrapped\n        /// <summary>\n        /// Return the value with the given key, but skip a supplied number\n        /// of entries with this key. This method is only useful if multiple\n        /// item with the same key are allowed.\n        /// </summary>\n        public TValue ValueWithKeySkip(__tkey__ key, __itype__ skip)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.ValueWithKeySkip(key, skip);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            var hash = __HashFun__key__GetHash__;\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n                throw new KeyNotFoundException();\n            if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n            {\n                if (skip == 0) return m_firstArray[fi].Item.Value;\n                --skip;\n            }\n            while (ei > 0)\n            {\n                if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                {\n                    if (skip == 0) return m_extraArray[ei].Item.Value;\n                    --skip;\n                }\n                ei = m_extraArray[ei].Next;\n            }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            throw new KeyNotFoundException();\n            //# } // !wrapped\n        }\n\n        /// <summary>\n        /// Remove the item with the supplied key from the __type__ and\n        /// return it. If multipe entries have the same key, the one that\n        /// was inserted last is removed.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public TValue GetAndRemove(__tkey__ key)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.GetAndRemove(key);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            TValue value;\n            if (!TryRemove(key, out value))\n                throw new KeyNotFoundException();\n            return value;\n            //# } // !wrapped\n        }\n\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        /// <summary>\n        /// Try to remove the item with the supplied key from the __type__.\n        /// and return true if it was succesfully removed. If multipe\n        /// entries have the same key, the one that was inserted last is\n        /// removed. If the item is not found, false is returned.\n        /// </summary>\n        public bool Remove(__tkey__ key/*# if (hasHashPar) { */, __itype__ hash/*# } */)\n        {\n            TValue value;\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key/*# if (hasHashPar) { */, hash/*# } */, out value);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            return TryRemove(key/*# if (hasHashPar) { */, hash/*# } */, out value);\n            //# } // !wrapped\n        }\n\n        //# } // hasHashPar\n        //# }\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        /// <summary>\n        /// Remove the item with the supplied key/*# if (hasValue) { */ and the supplied value/*# } */\n        /// from the __type__. Returns true if the value was removed.\n        /// </summary>\n        public bool Remove(__tkey__ key/*# if (hasHashPar) { */, __itype__ hash/*# } if (hasValue) { */, TValue value/*# } */)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key/*# if (hasHashPar) { */, hash/*# } if (hasValue) { */, value/*# } */);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            return TryRemove(key/*# if (hasHashPar) { */, hash/*# } if (hasValue) { */, value/*# } */);\n            //# } // !wrapped\n        }\n\n        //# } // hasHashPar\n        //# if (hasValue) {\n        /// <summary>\n        /// Remove the item with the supplied KeyValuePair from the __type__.\n        /// If the item is not found, a KeyNotFoundException is thrown.\n        /// </summary>\n        public bool Remove(KeyValuePair<__tkey__, TValue> item)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(item.Key, item.Value);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            return TryRemove(item.Key, item.Value);\n            //# } // !wrapped\n        }\n\n        //# } // hasValue\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        /// <summary>\n        /// Try to reomve the item with the supplied key. If multipe entries\n        /// have the same key, the one that was inserted last is removed.\n        /// Returns true if the item was found/*# if (hasValue) { */, which is returned via the out\n        /// parameter/*# } */.\n        /// </summary>\n        public bool TryRemove(__tkey__ key/*# if (hasHashPar) { */, __itype__ hash/*# } if (hasValue) { */, out TValue value/*# } */)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key/*# if (hasHashPar) { */, hash/*# } if (hasValue) { */, out value/*# } */);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (!hasHashPar) {\n            var hash = __HashFun__key__GetHash__;\n            //# }\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0)\n            {\n                /*# if (hasValue) { */value = default(TValue); /*# } */return false;\n            }\n            if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                && key.Equals(m_firstArray[fi].Item__Key__)/*# } */)\n            {\n                //# if (hasValue) {\n                value = m_firstArray[fi].Item.Value;\n                //# }\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(__HashItem__);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(__HashItem__);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                //# if (concurrent) {\n                ++m_version;\n                //# }\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_extraArray[ei].Item__Key__)/*# } */)\n                {\n                    //# if (hasValue) {\n                    value = m_extraArray[ei].Item.Value;\n                    //# }\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(__HashItem__);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    //# if (concurrent) {\n                    ++m_version;\n                    //# }\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item__Hash__ == hash/*# if (hasKey) { */\n                        && key.Equals(m_extraArray[ni].Item__Key__)/*# } */)\n                    {\n                        //# if (hasValue) {\n                        value = m_extraArray[ni].Item.Value;\n                        //# }\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(__HashItem__);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        //# if (concurrent) {\n                        ++m_version;\n                        //# }\n                        return true;\n                    }\n                }\n            }\n            //# if (hasValue) {\n            value = default(TValue);\n            //# }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            return false;\n            //# } // !wrapped\n        }\n\n        //# } // hasHashPar\n        //# if (hasValue) {\n        //# foreach (var hasHashPar in new[] { false, true }) { if (hasHashPar && !hasKey) continue;\n        /// <summary>\n        /// Try to reomve the item with the supplied key and the supplied\n        /// value. If multipe entries match, the one that was inserted last\n        /// is removed. Returns true if the item was found.\n        /// </summary>\n        public bool TryRemove(__tkey__ key/*# if (hasHashPar) { */, __itype__ hash/*# } */, TValue value)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                return m_dict.TryRemove(key/*# if (hasHashPar) { */, hash/*# } */, value);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (!hasHashPar) {\n            var hash = __HashFun__key__GetHash__;\n            //# }\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            var fi = ((__uitype__)hash) % m_capacity;\n            var ei = m_firstArray[fi].Next;\n            if (ei == 0) return false;\n            if (m_firstArray[fi].Item__Hash__ == hash/*# if (hasKey) { */\n                && key.Equals(m_firstArray[fi].Item__Key__)/*# } */\n                && value.Equals(m_firstArray[fi].Item.Value))\n            {\n                if (ei < 0)\n                {\n                    m_firstArray[fi].Next = 0;\n                    m_firstArray[fi].Item = default(__HashItem__);\n                }\n                else\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_firstArray[fi].Item = m_extraArray[ei].Item;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(__HashItem__);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                }\n                if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                //# if (concurrent) {\n                ++m_version;\n                //# }\n                return true;\n            }\n            if (ei > 0)\n            {\n                if (m_extraArray[ei].Item__Hash__ == hash/*# if (hasKey) { */\n                    && key.Equals(m_extraArray[ei].Item__Key__)/*# } */\n                    && value.Equals(m_extraArray[ei].Item.Value))\n                {\n                    m_firstArray[fi].Next = m_extraArray[ei].Next;\n                    m_extraArray[ei].Next = m_freeIndex;\n                    m_extraArray[ei].Item = default(__HashItem__);\n                    m_freeIndex = ei;\n                    --m_extraCount;\n                    if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                    //# if (concurrent) {\n                    ++m_version;\n                    //# }\n                    return true;\n                }\n                for (var ni = m_extraArray[ei].Next; ni > 0;\n                     ei = ni, ni = m_extraArray[ei].Next)\n                {\n                    if (m_extraArray[ni].Item__Hash__ == hash/*# if (hasKey) { */\n                        && key.Equals(m_extraArray[ni].Item__Key__)/*# } */\n                        && value.Equals(m_extraArray[ni].Item.Value))\n                    {\n                        m_extraArray[ei].Next = m_extraArray[ni].Next;\n                        m_extraArray[ni].Next = m_freeIndex;\n                        m_extraArray[ni].Item = default(__HashItem__);\n                        m_freeIndex = ni;\n                        --m_extraCount;\n                        if (--m_count < m_decreaseThreshold) DecreaseCapacity();\n                        //# if (concurrent) {\n                        ++m_version;\n                        //# }\n                        return true;\n                    }\n                }\n            }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            return false;\n            //# } // !wrapped\n        }\n\n        //# } // hasHashPar\n        //# } // hasValue\n        //# foreach (var toaKeys in new[] { true, false }) {\n        //# if (!hasValue && !toaKeys) continue;\n        //# var KeysValues = hasValue ? (toaKeys ? \"Keys\" : \"Values\") : \"\";\n        //# var tkeyvalue = toaKeys ? tkey : \"TValue\";\n        //# var KeyValue = toaKeys ? Key : \".Value\";\n        //# var keysvalues = toaKeys ? \"keys\" : \"values\";\n        /// <summary>\n        /// Returns all __keysvalues__ in the dictionary as an array.\n        //# if (concurrent) {\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        //# }\n        /// </summary>\n        public __tkeyvalue__[] __KeysValues__ToArray()\n        {\n            //# if (wrapped) {\n            return m_dict.__KeysValues__ToArray();\n            //# } else {\n            var array = new __tkeyvalue__[m_count];\n            Copy__KeysValues__To(array, __izero__);\n            return array;\n            //# }\n        }\n\n        //# } // toaKeys\n        //# if (hasValue) {\n        /// <summary>\n        /// Returns all KeyValuePairs in the dictionary as an array.\n        //# if (concurrent) {\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        //# }\n        /// </summary>\n        public KeyValuePair<__tkey__, TValue>[] ToArray()\n        {\n            //# if (wrapped) {\n            return m_dict.ToArray();\n            //# } else {\n            var array = new KeyValuePair<__tkey__, TValue>[m_count];\n            CopyTo(array, __izero__);\n            return array;\n            //# }\n        }\n\n        //# } // hasValue\n        /// <summary>\n        /// Remove all items. Capacity remains unchanged.\n        /// </summary>\n        public void Clear()\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try { m_dict.Clear(); } finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (concurrent) {\n            Monitor.Enter(this); try { ++m_version;\n            //# }\n            m_firstArray.Set(default(__NextHashItem__));\n            m_extraArray.Set(default(__HashItemNext__));\n            m_freeIndex = AddSlotsToFreeList(m_extraArray, 1);\n            m_count = 0;\n            m_extraCount = 0;\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            //# } // !wrapped\n        }\n\n        //# foreach (var toaKeys in new[] { true, false }) {\n        //# if (!hasValue && !toaKeys) continue;\n        //# var KeysValues = hasValue ? (toaKeys ? \"Keys\" : \"Values\") : \"\";\n        //# var tkeyvalue = toaKeys ? tkey : \"TValue\";\n        //# var KeyValue = toaKeys ? Key : \".Value\";\n        //# var keysvalues = toaKeys ? \"keys\" : \"values\";\n        /// <summary>\n        /// Copies all __keysvalues__ in the dictionary to the supplied\n        /// array starting at the supplied index.\n        //# if (concurrent) {\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        //# }\n        /// </summary>\n        public void Copy__KeysValues__To(__tkeyvalue__[] array, __itype__ index)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try\n            {\n                m_dict.Copy__KeysValues__To(array, index);\n            }\n            finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            for (__uitype__ fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = m_firstArray[fi].Item__KeyValue__;\n                while (ei > 0)\n                {\n                    array[index++] = m_extraArray[ei].Item__KeyValue__;\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            //# } // !wrapped\n        }\n\n        //# } // toaKeys\n        //# if (hasValue) {\n        /// <summary>\n        /// Copies all KeyValuePairs in the dictionary into the supplied\n        /// array starting at the supplied index.\n        //# if (concurrent) {\n        /// This may throw a ConcurrentDataModifiedException if data is\n        /// modified by another task during the operation.\n        //# }\n        /// </summary>\n        public void CopyTo(KeyValuePair<__tkey__, TValue>[] array, __itype__ index)\n        {\n            //# if (wrapped) {\n            Monitor.Enter(this); try { m_dict.CopyTo(array, index); } finally { Monitor.Exit(this); }\n            //# } else { // !wrapped\n            //# if (concurrent) {\n            Monitor.Enter(this); try {\n            //# }\n            for (__uitype__ fi = 0; fi < m_capacity; fi++)\n            {\n                var ei = m_firstArray[fi].Next;\n                if (ei == 0) continue;\n                array[index++] = new KeyValuePair<__tkey__, TValue>(\n                                m_firstArray[fi].Item__Key__, m_firstArray[fi].Item.Value);\n                while (ei > 0)\n                {\n                    array[index++] = new KeyValuePair<__tkey__, TValue>(\n                                    m_extraArray[ei].Item__Key__, m_extraArray[ei].Item.Value);\n                    ei = m_extraArray[ei].Next;\n                }\n            }\n            //# if (concurrent) {\n            } finally { Monitor.Exit(this); }\n            //# }\n            //# } // !wrapped\n        }\n\n        //# } // hasValue\n        //# if (!concurrent) {\n        /// <summary>\n        /// Copy items into supplied array starting at supplied index.\n        /// </summary>\n        public void CopyTo(Array array, int index)\n        {\n            var typedArray = array as /*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */[];\n            if (typedArray != null)\n                CopyTo(typedArray, __icast__index);\n            else\n                throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Retuns a concurrent wrapper around the __type__ to enable\n        /// concurrent modifications.\n        /// </summary>\n        public __ctype____tpar__ AsConcurrent()\n        {\n            return new __ctype____tpar__(this);\n        }\n\n        //# }\n        //# if (isSym && hasValue) {\n        public void Add<TType>(TypedSymbol<TType> key, TType value)\n            where TType : TValue\n        {\n            this.Add(key.Symbol, value);\n        }\n\n        public bool Contains<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return Contains(key.Symbol);\n        }\n\n        public bool ContainsKey<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return ContainsKey(key.Symbol);\n        }\n\n        public TType Get<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return (TType)this[key.Symbol];\n        }\n\n        public TType Get<TType>(TypedSymbol<TType> key, TType defaultValue)\n            where TType : TValue\n        {\n            TType value;\n            if (TryGetValue(key, out value)) return value;\n            return defaultValue;\n        }\n\n        public TType GetOrDefault<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            TType value;\n            if (TryGetValue(key, out value)) return value;\n            return default(TType);\n        }\n\n        public bool Remove<TType>(TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return Remove(key.Symbol);\n        }\n\n        public void Set<TType>(TypedSymbol<TType> key, TType value)\n            where TType : TValue\n        {\n            this[key.Symbol] = value;\n        }\n\n        public bool TryGetValue<TType>(TypedSymbol<TType> key, out TType value)\n            where TType : TValue\n        {\n            TValue val;\n            if (TryGetValue(key.Symbol, out val)) { value = (TType)val; return true; }\n            value = default(TType);\n            return false;\n        }\n\n        public TType GetAs<TType>(__tkey__ key)\n            where TType : TValue\n        {\n            return (TType)this[key];\n        }\n\n        public TType GetAs<TType>(__tkey__ key, TType defaultValue)\n            where TType : TValue\n        {\n            TValue value;\n            if (TryGetValue(key, out value)) return (TType)value;\n            return defaultValue;\n        }\n\n        public TType GetAsOrDefault<TType>(__tkey__ key)\n            where TType : TValue\n        {\n            TValue value;\n            if (TryGetValue(key, out value)) return (TType)value;\n            return default(TType);\n        }\n\n        //# } // isSym\n        #endregion\n        //# if (!wrapped) {\n\n        #region IEnumerable</*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */> Members\n\n        IEnumerator</*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */> IEnumerable</*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */>.GetEnumerator()\n        {\n            /*# if (!concurrent) { */\n            return new Enumerator(this);\n            /*# } else { */\n            return Key__ValuePair__s.GetEnumerator();\n            /*# } */\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            /*# if (!concurrent) { */\n            return new Enumerator(this);\n            /*# } else { */\n            return Key__ValuePair__s.GetEnumerator();\n            /*# } */\n        }\n\n        #endregion\n        /*# if (hasValue && !big && !concurrent) { */\n        #region IDictionary<__tkey__, TValue> Members\n\n        ICollection<__tkey__> IDictionary<__tkey__, TValue>.Keys => new KeyCollection(this);\n\n        ICollection<TValue> IDictionary<__tkey__, TValue>.Values => new ValueCollection(this);\n\n        private sealed class KeyCollection(__type____tpar__ parent) : ICollection<__tkey__>, ICollection, IReadOnlyCollection<__tkey__>\n        {\n            public void CopyTo(__tkey__[] array, int index) => parent.CopyKeysTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<__tkey__>.IsReadOnly => true;\n\n            void ICollection<__tkey__>.Add(__tkey__ item) => throw new NotSupportedException();\n\n            void ICollection<__tkey__>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(__tkey__ item) => parent.ContainsKey(item);\n\n            bool ICollection<__tkey__>.Remove(__tkey__ item) => throw new NotSupportedException();\n\n            IEnumerator<__tkey__> IEnumerable<__tkey__>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<__tkey__>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is __tkey__[] keys) parent.CopyKeysTo(keys, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(__type____tpar__ dictionary) : IEnumerator<__tkey__>, IEnumerator\n            {\n                private __type____tpar__.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public __tkey__ Current => _inner.Current.Key;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        private sealed class ValueCollection(__type____tpar__ parent) : ICollection<TValue>, ICollection, IReadOnlyCollection<TValue>\n        {\n            public void CopyTo(TValue[] array, int index) => parent.CopyValuesTo(array, index);\n\n            public int Count => parent.Count;\n\n            bool ICollection<TValue>.IsReadOnly => true;\n\n            void ICollection<TValue>.Add(TValue item) => throw new NotSupportedException();\n\n            void ICollection<TValue>.Clear() => throw new NotSupportedException();\n\n            public bool Contains(TValue item) => parent.ContainsValue(item);\n\n            bool ICollection<TValue>.Remove(TValue item) => throw new NotSupportedException();\n\n            IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => new Enumerator(parent);\n\n            IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<TValue>)this).GetEnumerator();\n\n            void ICollection.CopyTo(Array array, int index)\n            {\n                if (array is TValue[] values) parent.CopyValuesTo(values, index);\n                throw new ArrayTypeMismatchException();\n            }\n\n            bool ICollection.IsSynchronized => false;\n\n            object ICollection.SyncRoot => ((ICollection)parent).SyncRoot;\n\n            private class Enumerator(__type____tpar__ dictionary) : IEnumerator<TValue>, IEnumerator\n            {\n                private __type____tpar__.Enumerator _inner = dictionary.GetEnumerator();\n\n                public void Dispose() => _inner.Dispose();\n                public bool MoveNext() => _inner.MoveNext();\n                public TValue Current => _inner.Current.Value;\n                object IEnumerator.Current => Current;\n                void IEnumerator.Reset() => _inner.Reset();\n            }\n        }\n\n        #endregion\n        //# } // hasValue && !big && !concurrent\n        /*# if (!concurrent) { */\n        #region Enumerator\n\n        public Enumerator GetEnumerator() { return new Enumerator(this); }\n\n        public struct Enumerator : IEnumerator</*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */>\n        {\n            readonly __type__/*# if (isGeneric) { */</*# if (hasKey) { */TKey/*# } if (hasValue) { if (hasKey) { */, /*# } */TValue/*# } */>/*# } */ m_dict;\n            __itype__ m_index;\n            __itype__ m_extraIndex;\n            /*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */ m_current;\n\n            public Enumerator(__type__/*# if (isGeneric) { */</*# if (hasKey) { */TKey/*# } if (hasValue) { if (hasKey) { */, /*# } */TValue/*# } */>/*# } */ dict)\n            {\n                m_dict = dict;\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(/*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */);\n            }\n\n            public readonly /*# if (hasValue) { */KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */ Current => m_current;\n\n            readonly object IEnumerator.Current => m_current;\n\n            public readonly void Dispose() { }\n\n            public bool MoveNext()\n            {\n                if (m_extraIndex < 0)\n                {\n                    var fa = m_dict.m_firstArray;\n                    var cap = fa.Length;\n                    while (m_index < cap)\n                    {\n                        var nxt = fa[m_index].Next;\n                        if (nxt != 0)\n                        {\n                            m_current = /*# if (hasValue) { */new KeyValuePair<__tkey__, TValue>(/*# } */fa[m_index].Item__Key__/*# if (hasValue) { */, fa[m_index].Item.Value)/*# } */;\n                            m_extraIndex = nxt;\n                            m_index++;\n                            return true;\n                        }\n                        m_index++;\n                    }\n                    return false;\n                }\n                else\n                {\n                    var ea = m_dict.m_extraArray;\n                    m_current = /*# if (hasValue) { */new KeyValuePair<__tkey__, TValue>(/*# } */ea[m_extraIndex].Item__Key__/*# if (hasValue) { */, ea[m_extraIndex].Item.Value)/*# } */;\n                    m_extraIndex = ea[m_extraIndex].Next;\n                    return true;\n                }\n            }\n\n            public void Reset()\n            {\n                m_index = 0;\n                m_extraIndex = -1;\n                m_current = default(/*# if (hasValue) { */ KeyValuePair</*# } */__tkey__/*# if (hasValue) { */, TValue>/*# } */);\n            }\n        }\n\n        #endregion\n        /*# } */\n        #region Private Helper Methods\n\n        private __uitype__ ComputeIncreaseThreshold(__uitype__ capacity)\n        {\n            return (__uitype__)(capacity * (double)m_maxFillFactor);\n        }\n\n        private __uitype__ ComputeDecreaseThreshold(__uitype__ capacity)\n        {\n            return (__uitype__)(capacity * (double)m_minFillFactor);\n        }\n\n        private static __itype__ AddSlotsToFreeList(\n                __HashItemNext__[] extraArray, __itype__ start)\n        {\n            var length = extraArray.Length - 1;\n            for (__itype__ i = start; i < length; i++)\n                extraArray[i].Next = i + 1;\n            extraArray[length].Next = -1;\n            return start;\n        }\n\n        private void IncreaseCapacity()\n        {\n            Resize(DictConstant.PrimeSizes__ext__[++m_capacityIndex], m_capacity);\n        }\n\n        private void DecreaseCapacity()\n        {\n            if (m_capacityIndex > 0)\n                Resize(DictConstant.PrimeSizes__ext__[--m_capacityIndex], m_capacity);\n        }\n\n        /// <summary>\n        /// Add item to the hashtable supplied in the parameters.\n        /// This is used in resizing, therefore no size check is done.\n        /// </summary>\n        private static void Add(\n                __HashItem__ item,\n                __NextHashItem__[] firstArray,\n                __uitype__ capacity,\n                ref __HashItemNext__[] extraArray,\n                ref __itype__ freeIndex,\n                ref __uitype__ extraCount)\n        {\n            var fi = ((__uitype__)item__Hash__) % capacity;\n            var ei = firstArray[fi].Next;\n            if (ei == 0)\n            {\n                firstArray[fi].Next = -1;\n                firstArray[fi].Item = item;\n                return;\n            }\n            if (freeIndex < 0)\n            {\n                var length = extraArray.Length;\n                extraArray = extraArray.Resized(length * 2);\n                freeIndex = AddSlotsToFreeList(extraArray, length);\n            }\n            var ni = freeIndex;\n            freeIndex = extraArray[ni].Next;\n\n            extraArray[ni].Item = firstArray[fi].Item;\n            extraArray[ni].Next = ei;\n\n            firstArray[fi].Next = ni;\n            firstArray[fi].Item = item;\n            ++extraCount;\n        }\n\n        /// <summary>\n        /// The resize method has to maintain the stack order of the lists in\n        /// the extra array. Therefore one list reversal is necessary.\n        /// </summary>\n        private void Resize(__uitype__ newCapacity, __uitype__ oldCapacity)\n        {\n            m_increaseThreshold = ComputeIncreaseThreshold(newCapacity);\n            m_decreaseThreshold = ComputeDecreaseThreshold(newCapacity);\n            var firstArray = new __NextHashItem__[newCapacity];\n            var extraArray = new __HashItemNext__[\n                                    System.Math.Max((__itype__)DictConstant.MinExtraCapacity,\n                                                    m_extraArray.__ext__Length / 2)];\n            var freeIndex = AddSlotsToFreeList(extraArray, 1);\n            __uitype__ newExtraCount = 0;\n            if ((m_capacityIndex & 1) != 0)\n            {\n                for (__uitype__ fi = 0; fi < m_capacity; fi++)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        __itype__ head = -1;\n                        do\n                        {\n                            __itype__ next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n            else\n            {\n                __uitype__ fi = m_capacity;\n                while (fi-- > 0)\n                {\n                    var ei = m_firstArray[fi].Next;\n                    if (ei == 0) continue;\n                    if (ei > 0)\n                    {\n                        // reverse the extra list\n                        __itype__ head = -1;\n                        do\n                        {\n                            __itype__ next = m_extraArray[ei].Next;\n                            m_extraArray[ei].Next = head;\n                            head = ei; ei = next;\n                        }\n                        while (ei > 0);\n\n                        // insert the extras into the new table\n                        do\n                        {\n                            Add(m_extraArray[head].Item, firstArray, newCapacity,\n                                ref extraArray, ref freeIndex, ref newExtraCount);\n                            head = m_extraArray[head].Next;\n                        }\n                        while (head > 0);\n                    }\n                    Add(m_firstArray[fi].Item, firstArray, newCapacity,\n                        ref extraArray, ref freeIndex, ref newExtraCount);\n                }\n            }\n\n            if ((Report & DictReport.Resize) != 0)\n                ReportStats((__uitype__)m_count - m_extraCount, oldCapacity,\n                            m_extraCount, (__uitype__)m_extraArray.Length,\n                            (__uitype__)m_count - newExtraCount, newCapacity,\n                            newExtraCount, (__uitype__)extraArray.Length);\n\n            m_firstArray = firstArray;\n            m_capacity = newCapacity;\n            m_extraArray = extraArray;\n            m_freeIndex = freeIndex;\n            m_extraCount = newExtraCount;\n        }\n\n        private void ReportStats(\n                    __uitype__ oldFirstCount, __uitype__ oldCapacity,\n                    __uitype__ oldExtraCount, __uitype__ oldExtraCapacity,\n                    __uitype__ newFirstCount, __uitype__ newCapacity,\n                    __uitype__ newExtraCount, __uitype__ newExtraCapacity)\n        {\n            Base.Report.Line(\"\\nresize at {0}:\", m_count);\n            Base.Report.Line(\"  old: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    oldFirstCount, oldCapacity, (100.0 * oldFirstCount) / (double)oldCapacity,\n                    oldExtraCount, oldExtraCapacity, (100.0 * oldExtraCount) / (double)oldExtraCapacity);\n            Base.Report.Line(\"  new: first {0,9}/{1,-9} [{2:00.0}%] - extra {3,9}/{4,-9} [{5:00.0}%]\",\n                    newFirstCount, newCapacity, (100.0 * oldFirstCount) / (double)newCapacity,\n                    newExtraCount, newExtraCapacity, (100.0 * newExtraCount) / (double)newExtraCapacity);\n        }\n\n        #endregion\n        //# } // !wrapped\n    }\n\n    #endregion\n\n    //# } // ti\n    //# } // concurrent\n    //# } // fast\n    //# } // equatable\n    #region Support Data Structures\n\n    [Flags]\n    public enum DictReport\n    {\n        Resize = 0x0001,\n    }\n\n    public class ConcurrentDataModifiedException : Exception\n    {\n        public ConcurrentDataModifiedException()\n        { }\n    }\n\n    #endregion\n\n    #region Internal Helper Structures\n\n    //# foreach (var itype in new[] { \"int\", \"long\" }) {\n    //#   var Long = itype == \"int\" ? \"\" : \"Long\";\n    //#   var Int = itype == \"int\" ? \"Int\" : \"Long\";\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyValue__Long__<TKey, Tvalue>\n    {\n        public __itype__ Hash;\n        public TKey Key;\n        public Tvalue Value;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextHashKeyValue__Long__<TKey, Tvalue>\n    {\n        public __itype__ Next;\n        public HashKeyValue__Long__<TKey, Tvalue> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyValueNext__Long__<TKey, Tvalue>\n    {\n        public HashKeyValue__Long__<TKey, Tvalue> Item;\n        public __itype__ Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKey__Long__<TKey>\n    {\n        public __itype__ Hash;\n        public TKey Key;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextHashKey__Long__<TKey>\n    {\n        public __itype__ Next;\n        public HashKey__Long__<TKey> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct HashKeyNext__Long__<TKey>\n    {\n        public HashKey__Long__<TKey> Item;\n        public __itype__ Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct __Int__Value<Tvalue>\n    {\n        public __itype__ Key;\n        public Tvalue Value;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct Next__Int__Value<Tvalue>\n    {\n        public __itype__ Next;\n        public __Int__Value<Tvalue> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct __Int__ValueNext<Tvalue>\n    {\n        public __Int__Value<Tvalue> Item;\n        public __itype__ Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct Next__Int__\n    {\n        public __itype__ Next;\n        public __itype__ Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct __Int__Next\n    {\n        public __itype__ Item;\n        public __itype__ Next;\n    }\n\n    //# } // itype\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SymbolValue<Tvalue>\n    {\n        public Symbol Key;\n        public Tvalue Value;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextSymbolValue<Tvalue>\n    {\n        public int Next;\n        public SymbolValue<Tvalue> Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SymbolValueNext<Tvalue>\n    {\n        public SymbolValue<Tvalue> Item;\n        public int Next;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct NextSymbol\n    {\n        public int Next;\n        public Symbol Item;\n    }\n\n    [StructLayout(LayoutKind.Sequential)]\n    internal struct SymbolNext\n    {\n        public Symbol Item;\n        public int Next;\n    }\n\n    public static class DictConstant\n    {\n        #region Constants\n\n        public const float MaxFillFactorDefault = 0.8f; // growing avg: (0.8 + 0.4)/2 = 0.6\n        public const float MinFillFactorDefault = 0.2f; // shrinking avg: (0.4 + 0.2)/2 = 0.3\n        public const int MinExtraCapacity = 4;\n\n        public readonly static uint[] PrimeSizes =\n        {\n            /*    prime no.           prime */\n            /*           2                3,       +  1 = 2^2 */\n            /*           4 */             7,    // +  1 = 2^3, minimal size\n            /*           6 */            13,    // +  3 = 2^4\n            /*          11 */            31,    // +  1 = 2^5\n            /*          18 */            61,    // +  3 = 2^6\n            /*          31 */           127,    // +  1 = 2^7\n            /*          54 */           251,    // +  5 = 2^8\n            /*          97 */           509,    // +  3 = 2^9\n            /*         172 */          1021,    // +  3 = 2^10\n            /*         309 */          2039,    // +  9 = 2^11\n            /*         564 */          4093,    // +  3 = 2^12\n            /*        1028 */          8191,    // +  1 = 2^13\n            /*        1900 */         16381,    // +  3 = 2^14\n            /*        3512 */         32749,    // + 19 = 2^15\n            /*        6542 */         65521,    // + 15 = 2^16\n            /*       12251 */        131071,    // +  1 = 2^17\n            /*       23000 */        262139,    // +  5 = 2^18\n            /*       43390 */        524287,    // +  1 = 2^19\n            /*       82025 */       1048573,    // +  3 = 2^20\n            /*      155611 */       2097143,    // +  9 = 2^21\n            /*      295947 */       4194301,    // +  3 = 2^22\n            /*      564163 */       8388593,    // + 15 = 2^23\n            /*     1077871 */      16777213,    // +  3 = 2^24\n            /*     2063689 */      33554393,    // + 39 = 2^25\n            /*     3957809 */      67108859,    // +  5 = 2^26\n            /*     7603553 */     134217689,    // + 39 = 2^27\n            /*    14630843 */     268435399,    // + 57 = 2^28\n            /*    28192750 */     536870909,    // +  3 = 2^29\n            /*    54400028 */    1073741789,    // + 35 = 2^30\n            /*   105097565 */    2147483647,    // +  1 = 2^31\n            /*   203280221 */    4294967291,    // +  5 = 2^32\n        };\n\n        public readonly static ulong[] PrimeSizesLong =\n        {\n            /*        prime no.               prime */\n            /*               2                    3,       +  1 = 2^2 */\n            /*               4 */                 7,    // +  1 = 2^3, minimal size\n            /*               6 */                13,    // +  3 = 2^4\n            /*              11 */                31,    // +  1 = 2^5\n            /*              18 */                61,    // +  3 = 2^6\n            /*              31 */               127,    // +  1 = 2^7\n            /*              54 */               251,    // +  5 = 2^8\n            /*              97 */               509,    // +  3 = 2^9\n            /*             172 */              1021,    // +  3 = 2^10\n            /*             309 */              2039,    // +  9 = 2^11\n            /*             564 */              4093,    // +  3 = 2^12\n            /*            1028 */              8191,    // +  1 = 2^13\n            /*            1900 */             16381,    // +  3 = 2^14\n            /*            3512 */             32749,    // + 19 = 2^15\n            /*            6542 */             65521,    // + 15 = 2^16\n            /*           12251 */            131071,    // +  1 = 2^17\n            /*           23000 */            262139,    // +  5 = 2^18\n            /*           43390 */            524287,    // +  1 = 2^19\n            /*           82025 */           1048573,    // +  3 = 2^20\n            /*          155611 */           2097143,    // +  9 = 2^21\n            /*          295947 */           4194301,    // +  3 = 2^22\n            /*          564163 */           8388593,    // + 15 = 2^23\n            /*         1077871 */          16777213,    // +  3 = 2^24\n            /*         2063689 */          33554393,    // + 39 = 2^25\n            /*         3957809 */          67108859,    // +  5 = 2^26\n            /*         7603553 */         134217689,    // + 39 = 2^27\n            /*        14630843 */         268435399,    // + 57 = 2^28\n            /*        28192750 */         536870909,    // +  3 = 2^29\n            /*        54400028 */        1073741789,    // + 35 = 2^30\n            /*       105097565 */        2147483647,    // +  1 = 2^31\n            /*       203280221 */        4294967291,    // +  5 = 2^32\n            /*       393615806 */        8589934583,    // +  9 = 2^33\n            /*       762939111 */       17179869143,    // + 41 = 2^34\n            /*      1480206279 */       34359738337,    // + 31 = 2^35\n            /*      2874398515 */       68719476731,    // +  5 = 2^36\n            /*      5586502348 */      137438953447,    // + 25 = 2^37\n            /*     10866266172 */      274877906899,    // + 45 = 2^38\n            /*     21151907950 */      549755813881,    // +  7 = 2^39\n            /*     41203088796 */     1099511627689,    // + 87 = 2^40\n            /*     80316571436 */     2199023255531,    // + 21 = 2^41\n            /*    156661034233 */     4398046511093,    // + 11 = 2^42\n            /*    305761713237 */     8796093022151,    // + 57 = 2^43\n            /*    597116381732 */    17592186044399,    // + 17 = 2^44\n        };\n\n        #endregion\n\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Symbol/Dicts.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    #region Special Dicts\n\n    public class SingleEntryDict<TKey, TValue> : IDict<TKey, TValue>\n    {\n        readonly TKey m_key;\n        TValue m_value;\n        bool m_hasEntry;\n\n        #region Constructors\n\n        public SingleEntryDict(TKey key, TValue value)\n        {\n            m_key = key;\n            m_value = value;\n            m_hasEntry = true;\n        }\n\n        #endregion\n\n        #region IDict<TKey, TValue>\n\n        public IEnumerable<TKey> Keys\n        {\n            get { if (m_hasEntry) yield return m_key; }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get { if (m_hasEntry) yield return m_value; }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get { if (m_hasEntry) yield return new KeyValuePair<TKey, TValue>(m_key, m_value); }\n        }\n\n        public TValue this[TKey key]\n        {\n            get\n            {\n                if (ContainsKey(key)) return m_value;\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                if (EqualityComparer<TKey>.Default.Equals(key, m_key))\n                {\n                    m_value = value;\n                    m_hasEntry = true;\n                    return;\n                }\n                throw new ArgumentException();\n            }\n        }\n\n        public void Add(TKey key, TValue value)\n        {\n            if (!EqualityComparer<TKey>.Default.Equals(key, m_key))\n                throw new ArgumentException();\n            if (m_hasEntry)\n                throw new ArgumentException();\n\n            m_value = value;\n            m_hasEntry = true;\n        }\n\n        public bool ContainsKey(TKey key)\n        {\n            return m_hasEntry && EqualityComparer<TKey>.Default.Equals(key, m_key);\n        }\n\n        public bool Remove(TKey key)\n        {\n            if (!ContainsKey(key)) return false;\n\n            m_hasEntry = false;\n            m_value = default(TValue);\n            return true;\n        }\n\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            if (ContainsKey(key))\n            {\n                value = m_value;\n                return true;\n            }\n\n            value = default(TValue);\n            return false;\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// An IDict where all contained keys return the same specified value.\n    /// </summary>\n    public class SingleValueDict<TKey, TValue> : IDict<TKey, TValue>, IEnumerable<KeyValuePair<TKey, TValue>>\n    {\n        private readonly IDictSet<TKey> m_keys;\n        private readonly TValue m_value;\n\n        #region Constructors\n\n        public SingleValueDict(TValue value)\n        {\n            m_keys = new DictSet<TKey>();\n            m_value = value;\n        }\n\n        public SingleValueDict(IDictSet<TKey> keySet, TValue value)\n        {\n            m_keys = keySet;\n            m_value = value;\n        }\n\n        #endregion\n\n        #region IDict<TKey,TValue> Members\n\n        public IEnumerable<TKey> Keys\n        {\n            get { return m_keys.Items; }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get { yield return m_value; }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get { return m_keys.Items.Select(k => new KeyValuePair<TKey, TValue>(k, m_value)); }\n        }\n\n        public TValue this[TKey key]\n        {\n            get\n            {\n                if (m_keys.Contains(key)) return m_value;\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                if (EqualityComparer<TValue>.Default.Equals(value, m_value))\n                {\n                    m_keys.Add(key);\n                    return;\n                }\n                throw new ArgumentException();\n            }\n        }\n\n        public void Add(TKey key, TValue value)\n        {\n            if (EqualityComparer<TValue>.Default.Equals(value, m_value))\n            {\n                m_keys.Add(key);\n                return;\n            }\n            throw new ArgumentException();\n        }\n\n        public bool ContainsKey(TKey key)\n        {\n            return m_keys.Contains(key);\n        }\n\n        public bool Remove(TKey key)\n        {\n            return m_keys.Remove(key);\n        }\n\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            if (m_keys.Contains(key))\n            {\n                value = m_value; return true;\n            }\n            else\n            {\n                value = default(TValue); return false;\n            }\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey,TValue>> Members\n\n        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// An IDict where all possible keys return the same specified value.\n    /// </summary>\n    public class UniversalDict<TKey, TValue> : IDict<TKey, TValue>\n    {\n        private readonly TValue m_value;\n\n        #region Constructor\n\n        public UniversalDict(TValue value)\n        {\n            m_value = value;\n        }\n\n        #endregion\n\n        #region IDict<TKey,TValue> Members\n\n        public IEnumerable<TKey> Keys\n        {\n            get { throw new NotImplementedException(); }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get { yield return m_value; }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get { throw new NotImplementedException(); }\n        }\n\n        public TValue this[TKey key]\n        {\n            get\n            {\n                return m_value;\n            }\n            set\n            {\n                if (!EqualityComparer<TValue>.Default.Equals(value, m_value))\n                    throw new ArgumentException();\n            }\n        }\n\n        public void Add(TKey key, TValue value)\n        {\n            if (!EqualityComparer<TValue>.Default.Equals(value, m_value))\n                throw new ArgumentException();\n        }\n\n        public bool ContainsKey(TKey key)\n        {\n            return true;\n        }\n\n        public bool Remove(TKey key)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            value = m_value;\n            return true;\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A union of IDicts with left priority.\n    /// </summary>\n    public class UnionDict<TKey, TValue> : IDict<TKey, TValue>, IEnumerable<KeyValuePair<TKey, TValue>>\n    {\n        readonly List<IDict<TKey, TValue>> m_dictList;\n\n        #region Constructors\n\n        public UnionDict()\n        {\n            m_dictList = new List<IDict<TKey, TValue>>();\n        }\n\n        public UnionDict(IEnumerable<IDict<TKey, TValue>> dicts)\n        {\n            m_dictList = dicts.ToList();\n        }\n\n        public UnionDict(params IDict<TKey, TValue>[] dictArray)\n            : this((IEnumerable<IDict<TKey, TValue>>)dictArray)\n        { }\n\n        #endregion\n\n        #region Properties\n\n        public IEnumerable<IDict<TKey, TValue>> Dicts { get { return m_dictList; } }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        public void Add(IDict<TKey, TValue> dict)\n        {\n            m_dictList.Add(dict);\n        }\n\n        #endregion\n\n        #region IDict<TKey,TValue> Members\n\n        public IEnumerable<TKey> Keys\n        {\n            get { return (from d in m_dictList from k in d.Keys select k)\n                            .GroupBy(k => k).Select(g => g.Key); }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get { return (from d in m_dictList from k in d.Keys select k)\n                            .GroupBy(k => k).Select(g => this[g.Key]); }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get { return (from d in m_dictList from k in d.Keys select k)\n                            .GroupBy(k => k).Select(g => new KeyValuePair<TKey, TValue>(g.Key, this[g.Key])); }\n        }\n\n        public TValue this[TKey key]\n        {\n            get\n            {\n                TValue value;\n                foreach (var d in m_dictList)\n                    if (d.TryGetValue(key, out value))\n                        return value;\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                throw new NotImplementedException();\n            }\n        }\n\n        public void Add(TKey key, TValue value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool ContainsKey(TKey key)\n        {\n            foreach (var d in m_dictList)\n                if (d.ContainsKey(key))\n                    return true;\n            return false;\n        }\n\n        public bool Remove(TKey key)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            foreach (var d in m_dictList)\n                if (d.TryGetValue(key, out value))\n                    return true;\n            value = default(TValue);\n            return false;\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey,TValue>> Members\n\n        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A Dict that overrides a single value of a supplied\n    /// base Dict.\n    /// </summary>\n    public class SingleDeltaDict<TKey, TValue> : IDict<TKey, TValue>, IDictDepth, IEnumerable<KeyValuePair<TKey, TValue>>\n    {\n        internal IDict<TKey, TValue> m_baseDict;\n        internal TKey m_key;\n        internal TValue m_value;\n        internal int m_depth;\n\n        #region Constructors\n\n        public SingleDeltaDict(IDict<TKey, TValue> baseDict, TKey key, TValue value)\n        {\n            m_baseDict = baseDict;\n            m_key = key;\n            m_value = value;\n            var dictDepth = baseDict as IDictDepth;\n            m_depth = dictDepth != null ? dictDepth.Depth + 1 : 1;\n        }\n\n        #endregion\n\n        #region IDict<TKey,TValue> Members\n\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                yield return m_key;\n                foreach (var k in m_baseDict.Keys)\n                    if (!k.Equals(m_key))\n                        yield return k;\n            }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                yield return m_value;\n                foreach (var kvp in m_baseDict.KeyValuePairs)\n                    if (!kvp.Key.Equals(m_key))\n                        yield return kvp.Value;\n            }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                yield return new KeyValuePair<TKey, TValue>(m_key, m_value);\n                foreach (var kvp in m_baseDict.KeyValuePairs)\n                    if (!kvp.Key.Equals(m_key))\n                        yield return kvp;\n            }\n        }\n\n        public TValue this[TKey key]\n        {\n            get\n            {\n                if (key.Equals(m_key)) return m_value;\n                return m_baseDict[key];\n            }\n            set\n            {\n                throw new NotImplementedException();\n            }\n        }\n\n        public void Add(TKey key, TValue value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool ContainsKey(TKey key)\n        {\n            if (key.Equals(m_key)) return true;\n            return m_baseDict.ContainsKey(key);\n        }\n\n        public bool Remove(TKey key)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            if (key.Equals(m_key))\n            {\n                value = m_value;\n                return true;\n            }\n            return m_baseDict.TryGetValue(key, out value);\n        }\n\n        #endregion\n\n        #region IDictDepth\n\n        public int Depth { get { return m_depth; } }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey,TValue>> Members\n\n        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n    }\n\n    /// <summary>\n    /// A Dict that overrides all values contained in a delta\n    /// Dict with respect to a supplied base Dict.\n    /// </summary>\n    public class DeltaDict<TKey, TValue> : IDict<TKey, TValue>, IDictDepth, IEnumerable<KeyValuePair<TKey, TValue>>\n    {\n        readonly IDict<TKey, TValue> m_baseDict;\n        readonly Dict<TKey, TValue> m_deltaDict;\n        readonly int m_depth;\n\n        #region Constructors\n\n        public DeltaDict(IDict<TKey, TValue> baseDict, Dict<TKey, TValue> deltaDict)\n        {\n            m_baseDict = baseDict;\n            m_deltaDict = deltaDict;\n            var dictDepth = baseDict as IDictDepth;\n            m_depth = dictDepth != null ? dictDepth.Depth + 1 : 1;\n        }\n\n        #endregion\n\n        #region IDict<TKey,TValue> Members\n\n        public IEnumerable<TKey> Keys\n        {\n            get\n            {\n                return m_deltaDict.Keys.Concat(m_baseDict.Keys.Where(k => !m_deltaDict.ContainsKey(k)));\n            }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                return m_deltaDict.Values.Concat(m_baseDict.KeyValuePairs.Where(kvp => !m_deltaDict.ContainsKey(kvp.Key))\n                                                                         .Select(kvp => kvp.Value));\n            }\n        }\n\n        public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs\n        {\n            get\n            {\n                return m_deltaDict.KeyValuePairs.Concat(m_baseDict.KeyValuePairs.Where(kvp => !m_deltaDict.ContainsKey(kvp.Key)));\n            }\n        }\n\n        public TValue this[TKey key]\n        {\n            get\n            {\n                TValue value;\n                if (m_deltaDict.TryGetValue(key, out value)) return value;\n                return m_baseDict[key];\n            }\n            set\n            {\n                throw new NotImplementedException();\n            }\n        }\n\n        public void Add(TKey key, TValue value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool ContainsKey(TKey key)\n        {\n            if (m_deltaDict.ContainsKey(key)) return true;\n            return m_baseDict.ContainsKey(key);\n        }\n\n        public bool Remove(TKey key)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool TryGetValue(TKey key, out TValue value)\n        {\n            if (m_deltaDict.TryGetValue(key, out value))\n                return true;\n            return m_baseDict.TryGetValue(key, out value);\n        }\n\n        #endregion\n\n        #region IDictDepth\n\n        public int Depth { get { return m_depth; } }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<TKey,TValue>> Members\n\n        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n    }\n\n    /// <summary>\n    /// An IDict with Symbol keys where all contained keys return the same\n    /// specified value.\n    /// </summary>\n    public class SingleValueSymbolDict<TValue> : IDict<Symbol, TValue>, IEnumerable<KeyValuePair<Symbol, TValue>>\n    {\n        private readonly IDictSet<Symbol> m_keys;\n        private readonly TValue m_value;\n\n        #region Constructors\n\n        public SingleValueSymbolDict(IDictSet<Symbol> keySet, TValue value)\n        {\n            m_keys = keySet;\n            m_value = value;\n        }\n\n        public SingleValueSymbolDict(TValue value)\n        {\n            m_keys = new SymbolSet();\n            m_value = value;\n        }\n\n        #endregion\n\n        #region IDict<Symbol,TValue> Members\n\n        public IEnumerable<Symbol> Keys\n        {\n            get { return m_keys.Items; }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get { yield return m_value; }\n        }\n\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairs\n        {\n            get { return m_keys.Items.Select(k => new KeyValuePair<Symbol, TValue>(k, m_value)); }\n        }\n\n        public TValue this[Symbol key]\n        {\n            get\n            {\n                if (m_keys.Contains(key)) return m_value;\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                if (EqualityComparer<TValue>.Default.Equals(value, m_value))\n                {\n                    m_keys.Add(key);\n                    return;\n                }\n                throw new ArgumentException();\n            }\n        }\n\n        public void Add(Symbol key, TValue value)\n        {\n            if (EqualityComparer<TValue>.Default.Equals(value, m_value))\n            {\n                m_keys.Add(key);\n                return;\n            }\n            throw new ArgumentException();\n        }\n\n        public bool ContainsKey(Symbol key)\n        {\n            return m_keys.Contains(key);\n        }\n\n        public bool Remove(Symbol key)\n        {\n            return m_keys.Remove(key);\n        }\n\n        public bool TryGetValue(Symbol key, out TValue value)\n        {\n            if (m_keys.Contains(key))\n            {\n                value = m_value; return true;\n            }\n            else\n            {\n                value = default(TValue); return false;\n            }\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<Symbol,TValue>> Members\n\n        public IEnumerator<KeyValuePair<Symbol, TValue>> GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// An IDict with Symbol keys where all possible keys return the same\n    /// specified value.\n    /// </summary>\n    public class UniversalSymbolDict<TValue> : IDict<Symbol, TValue>\n    {\n        private readonly TValue m_value;\n\n        #region Constructor\n\n        public UniversalSymbolDict(TValue value)\n        {\n            m_value = value;\n        }\n\n        #endregion\n\n        #region IDict<Symbol,TValue> Members\n\n        public IEnumerable<Symbol> Keys\n        {\n            get { throw new NotImplementedException(); }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get { yield return m_value; }\n        }\n\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairs\n        {\n            get { throw new NotImplementedException(); }\n        }\n\n        public TValue this[Symbol key]\n        {\n            get\n            {\n                return m_value;\n            }\n            set\n            {\n                if (!EqualityComparer<TValue>.Default.Equals(value, m_value))\n                    throw new ArgumentException();\n            }\n        }\n\n        public void Add(Symbol key, TValue value)\n        {\n            if (!EqualityComparer<TValue>.Default.Equals(value, m_value))\n                throw new ArgumentException();\n        }\n\n        public bool ContainsKey(Symbol key)\n        {\n            return true;\n        }\n\n        public bool Remove(Symbol key)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool TryGetValue(Symbol key, out TValue value)\n        {\n            value = m_value;\n            return true;\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A union of IDicts with Symbol keys with left priority.\n    /// </summary>\n    public class UnionSymbolDict<TValue> : IDict<Symbol, TValue>, IEnumerable<KeyValuePair<Symbol, TValue>>\n    {\n        readonly List<IDict<Symbol, TValue>> m_dictList;\n\n        #region Constructors\n\n        public UnionSymbolDict()\n        {\n            m_dictList = new List<IDict<Symbol, TValue>>();\n        }\n\n        public UnionSymbolDict(IEnumerable<IDict<Symbol, TValue>> dicts)\n        {\n            m_dictList = dicts.ToList();\n        }\n\n        public UnionSymbolDict(params IDict<Symbol, TValue>[] dictArray)\n            : this((IEnumerable<IDict<Symbol, TValue>>)dictArray)\n        { }\n\n        #endregion\n\n        #region Properties\n\n        public IEnumerable<IDict<Symbol, TValue>> Dicts { get { return m_dictList; } }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        public void Add(IDict<Symbol, TValue> dict)\n        {\n            m_dictList.Add(dict);\n        }\n\n        #endregion\n\n        #region IDict<Symbol,TValue> Members\n\n        public IEnumerable<Symbol> Keys\n        {\n            get\n            {\n                return (from d in m_dictList from k in d.Keys select k)\n                          .GroupBy(k => k).Select(g => g.Key);\n            }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                return (from d in m_dictList from k in d.Keys select k)\n                          .GroupBy(k => k).Select(g => this[g.Key]);\n            }\n        }\n\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairs\n        {\n            get\n            {\n                return (from d in m_dictList from k in d.Keys select k)\n                          .GroupBy(k => k).Select(g => new KeyValuePair<Symbol, TValue>(g.Key, this[g.Key]));\n            }\n        }\n        public TValue this[Symbol key]\n        {\n            get\n            {\n                TValue value;\n                foreach (var d in m_dictList)\n                    if (d.TryGetValue(key, out value))\n                        return value;\n                throw new KeyNotFoundException();\n            }\n            set\n            {\n                throw new NotImplementedException();\n            }\n        }\n\n        public void Add(Symbol key, TValue value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool ContainsKey(Symbol key)\n        {\n            foreach (var d in m_dictList)\n                if (d.ContainsKey(key))\n                    return true;\n            return false;\n        }\n\n        public bool Remove(Symbol key)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool TryGetValue(Symbol key, out TValue value)\n        {\n            foreach (var d in m_dictList)\n                if (d.TryGetValue(key, out value))\n                    return true;\n            value = default(TValue);\n            return false;\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<Symbol,TValue>> Members\n\n        public IEnumerator<KeyValuePair<Symbol, TValue>> GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A SymbolDict that overrides a single value of a supplied\n    /// base SymbolDict.\n    /// </summary>\n    public class SingleDeltaSymbolDict<TValue> : IDict<Symbol, TValue>, IEnumerable<KeyValuePair<Symbol, TValue>>\n    {\n        internal IDict<Symbol, TValue> m_baseDict;\n        internal Symbol m_key;\n        internal TValue m_value;\n\n        #region Constructors\n\n        public SingleDeltaSymbolDict(IDict<Symbol, TValue> baseDict, Symbol key, TValue value)\n        {\n            m_baseDict = baseDict;\n            m_key = key;\n            m_value = value;\n        }\n\n        #endregion\n\n        #region IDict<TKey,TValue> Members\n\n        public IEnumerable<Symbol> Keys\n        {\n            get\n            {\n                yield return m_key;\n                foreach (var k in m_baseDict.Keys)\n                    if (k != m_key)\n                        yield return k;\n            }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                yield return m_value;\n                foreach (var kvp in m_baseDict.KeyValuePairs)\n                    if (kvp.Key != m_key)\n                        yield return kvp.Value;\n            }\n        }\n\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairs\n        {\n            get\n            {\n                yield return new KeyValuePair<Symbol, TValue>(m_key, m_value);\n                foreach (var kvp in m_baseDict.KeyValuePairs)\n                    if (kvp.Key != m_key)\n                        yield return kvp;\n            }\n        }\n\n        public TValue this[Symbol key]\n        {\n            get\n            {\n                if (key == m_key) return m_value;\n                return m_baseDict[key];\n            }\n            set\n            {\n                throw new NotImplementedException();\n            }\n        }\n\n        public void Add(Symbol key, TValue value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool ContainsKey(Symbol key)\n        {\n            if (key == m_key) return true;\n            return m_baseDict.ContainsKey(key);\n        }\n\n        public bool Remove(Symbol key)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool TryGetValue(Symbol key, out TValue value)\n        {\n            if (key == m_key)\n            {\n                value = m_value;\n                return true;\n            }\n            return m_baseDict.TryGetValue(key, out value);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<Symbol,TValue>> Members\n\n        public IEnumerator<KeyValuePair<Symbol, TValue>> GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A SymbolDict that overrides all values contained in a delta\n    /// SymbolDict with respect to a supplied base SymbolDict.\n    /// </summary>\n    public class DeltaSymbolDict<TValue> : IDict<Symbol, TValue>, IEnumerable<KeyValuePair<Symbol, TValue>>\n    {\n        readonly IDict<Symbol, TValue> m_baseDict;\n        readonly IDict<Symbol, TValue> m_deltaDict;\n\n        #region Constructors\n\n        public DeltaSymbolDict(IDict<Symbol, TValue> baseDict, IDict<Symbol, TValue> deltaDict)\n        {\n            m_baseDict = baseDict;\n            m_deltaDict = deltaDict;\n        }\n\n        #endregion\n\n        #region IDict<Symbol,TValue> Members\n\n        public IEnumerable<Symbol> Keys\n        {\n            get\n            {\n                return m_deltaDict.Keys.Concat(m_baseDict.Keys.Where(k => !m_deltaDict.ContainsKey(k)));\n            }\n        }\n\n        public IEnumerable<TValue> Values\n        {\n            get\n            {\n                return m_deltaDict.Values.Concat(m_baseDict.KeyValuePairs.Where(kvp => !m_deltaDict.ContainsKey(kvp.Key))\n                                                                         .Select(kvp => kvp.Value));\n            }\n        }\n\n        public IEnumerable<KeyValuePair<Symbol, TValue>> KeyValuePairs\n        {\n            get\n            {\n                return m_deltaDict.KeyValuePairs.Concat(m_baseDict.KeyValuePairs.Where(kvp => !m_deltaDict.ContainsKey(kvp.Key)));\n            }\n        }\n\n        public TValue this[Symbol key]\n        {\n            get\n            {\n                TValue value;\n                if (m_deltaDict.TryGetValue(key, out value)) return value;\n                return m_baseDict[key];\n            }\n            set\n            {\n                throw new NotImplementedException();\n            }\n        }\n\n        public void Add(Symbol key, TValue value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool ContainsKey(Symbol key)\n        {\n            if (m_deltaDict.ContainsKey(key)) return true;\n            return m_baseDict.ContainsKey(key);\n        }\n\n        public bool Remove(Symbol key)\n        {\n            throw new NotImplementedException();\n        }\n\n        public bool TryGetValue(Symbol key, out TValue value)\n        {\n            if (m_deltaDict.TryGetValue(key, out value))\n                return true;\n            return m_baseDict.TryGetValue(key, out value);\n        }\n\n        #endregion\n\n        #region IEnumerable<KeyValuePair<Symbol,TValue>> Members\n\n        public IEnumerator<KeyValuePair<Symbol, TValue>> GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return KeyValuePairs.GetEnumerator();\n        }\n\n        #endregion\n    }\n\n    public static class IDictExtensions\n    {\n\n        /// <summary>\n        /// Returns an IDict with the supplied key/value pair added. Internally\n        /// the supplied dict is not modified, but referenced, and a suitable\n        /// DeltaDict is built that contains only the changes.\n        /// </summary>\n        public static IDict<TKey, TValue> WithAdded<TKey, TValue>(\n                this IDict<TKey, TValue> dict,\n                TKey key, TValue value)\n        {\n            var sd = dict as SingleDeltaDict<TKey, TValue>;\n            if (sd != null && key.Equals(sd.m_key))\n                return new SingleDeltaDict<TKey, TValue>(sd.m_baseDict, key, value);\n            return new SingleDeltaDict<TKey, TValue>(dict, key, value);\n        }\n\n        /// <summary>\n        /// Return an IDict with the supplied Dict added as deltas. Internally\n        /// the supplied dicts are not modified, but referenced, and a suitable\n        /// DeltaDict is built.\n        /// </summary>\n        public static IDict<TKey, TValue> WithAdded<TKey, TValue>(\n                this IDict<TKey, TValue> dict,\n                Dict<TKey, TValue> deltaDict)\n        {\n            return new DeltaDict<TKey, TValue>(dict, deltaDict);\n        }\n\n        /// <summary>\n        /// Returns an IDict with the supplied key/value pair added. Internally\n        /// the supplied dict is not modified, but referenced, and a suitable\n        /// DeltaDict is built that contains only the changes.\n        /// </summary>\n        public static IDict<Symbol, TValue> WithAdded<TValue>(\n                this IDict<Symbol, TValue> dict,\n                Symbol key, TValue value)\n        {\n            var sd = dict as SingleDeltaSymbolDict<TValue>;\n            if (sd != null && key == sd.m_key)\n                return new SingleDeltaSymbolDict<TValue>(sd.m_baseDict, key, value);\n            return new SingleDeltaSymbolDict<TValue>(dict, key, value);\n        }\n\n        /// <summary>\n        /// Return an IDict with the supplied Dict added as deltas. Internally\n        /// the supplied dicts are not modified, but referenced, and a suitable\n        /// DeltaDict is built.\n        /// </summary>\n        public static IDict<Symbol, TValue> WithAdded<TKey, TValue>(\n                this IDict<Symbol, TValue> dict,\n                SymbolDict<TValue> deltaDict)\n        {\n            return new DeltaSymbolDict<TValue>(dict, deltaDict);\n        }\n\n        public static bool ContainsKey<TType, TValue>(\n                this IDict<Symbol, TValue> dict, TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return dict.ContainsKey(key.Symbol);\n        }\n\n        public static TType Get<TType, TValue>(\n                this IDict<Symbol, TValue> dict, TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            return (TType)dict[key.Symbol];\n        }\n\n        public static TType Get<TType, TValue>(\n                this IDict<Symbol, TValue> dict, TypedSymbol<TType> key, TType defaultValue)\n            where TType : TValue\n        {\n            TValue value;\n            if (dict.TryGetValue(key.Symbol, out value)) return (TType)value;\n            return defaultValue;\n        }\n\n        public static TType GetOrDefault<TType, TValue>(\n                this IDict<Symbol, TValue> dict, TypedSymbol<TType> key)\n            where TType : TValue\n        {\n            TValue value;\n            if (dict.TryGetValue(key.Symbol, out value)) return (TType)value;\n            return default(TType);\n        }\n\n        public static bool TryGetValue<TType, TValue>(\n                this IDict<Symbol, TValue> dict, TypedSymbol<TType> key, out TType typedValue)\n            where TType : TValue\n        {\n            TValue value;\n            if (dict.TryGetValue(key.Symbol, out value))\n            {\n                typedValue = (TType)value;\n                return true;\n            }\n            typedValue = default(TType);\n            return false;\n        }\n    }\n\n    #endregion\n\n    #region Dict Extensions\n\n    public static class DictFun\n    {\n        public static T[] GetArray<T>(this SymbolDict<Array> dict, Symbol name)\n        {\n            Array array;\n            if (dict.TryGetValue(name, out array)) return (T[])array;\n            throw new ArgumentException(\n                    String.Format(\"symbol \\\"{0}\\\" not found in dictionary\", name));\n        }\n\n        public static T[] GetArray<T>(this SymbolDict<Array> dict, Symbol name, T[] defaultArray)\n        {\n            Array array;\n            if (dict.TryGetValue(name, out array)) return (T[])array;\n            return defaultArray;\n        }\n\n        public static SymbolDict<Tv> Copy<Tv>(\n            this SymbolDict<Tv> self)\n        {\n            var r = new SymbolDict<Tv>(self.Count);\n            foreach (var kvp in self)\n                r[kvp.Key] = kvp.Value;\n            return r;\n        }\n\n        public static SymbolDict<Tr> Copy<T, Tr>(\n            this SymbolDict<T> self,\n            Func<Symbol, T, Tr> fun)\n        {\n            var r = new SymbolDict<Tr>(self.Count);\n            foreach (var kvp in self)\n                r[kvp.Key] = fun(kvp.Key, kvp.Value);\n            return r;\n        }\n\n        public static SymbolDict<Tr> Copy<T, Tr>(\n            this SymbolDict<T> self,\n            Func<KeyValuePair<Symbol, T>, KeyValuePair<Symbol, Tr>> fun)\n        {\n            var r = new SymbolDict<Tr>(self.Count);\n            foreach (var kvp in self)\n            {\n                var nkvp = fun(kvp);\n                r[nkvp.Key] = nkvp.Value;\n            }\n            return r;\n        }\n\n        public static SymbolDict<T1v> Copy<Tv, T1v>(\n            this SymbolDict<Tv> self,\n            SymbolDict<Func<Tv, T1v>> funMap,\n            Func<Tv, T1v> defaultFun)\n        {\n            var r = new SymbolDict<T1v>(self.Count);\n            foreach (var kvp in self)\n            {\n                Func<Tv, T1v> fun;\n                if (funMap.TryGetValue(kvp.Key, out fun))\n                    r[kvp.Key] = fun(kvp.Value);\n                else if (defaultFun != null)\n                    r[kvp.Key] = defaultFun(kvp.Value);\n            }\n            return r;\n        }\n\n        public static IEnumerable<KeyValuePair<Tk, Tv>> KeyValueParisWith<Tk, Tv>(this Dict<Tk, Tv> dict, Tk key)\n            where Tk : IEquatable<Tk>\n        {\n            return dict.ValuesWithKey(key).Select(v => new KeyValuePair<Tk, Tv>(key, v));\n        }\n\n        public static void RemoveAll<Tk, Tv>(this Dict<Tk, Tv> dict, Tk key)\n        {\n            while (dict.Remove(key)) ;\n        }\n\n        public static void RemoveWithValue<Tk, Tv>(this Dict<Tk, Tv> dict, Tk key, Func<Tv, bool> remove)\n            where Tk : IEquatable<Tk>\n        {\n            var values = dict.ValuesWithKey(key).ToArray();\n            dict.RemoveAll(key);\n            dict.AddRange(values.Where(v => !remove(v)).Select(v => new KeyValuePair<Tk, Tv>(key, v)));\n        }\n\n        public static IEnumerable<Tv> PopWithValue<Tk, Tv>(this Dict<Tk, Tv> dict, Tk key, Func<Tv, bool> remove)\n            where Tk : IEquatable<Tk>\n        {\n            var values = dict.ValuesWithKey(key).ToArray();\n            dict.RemoveAll(key);\n            foreach (var v in values)\n            {\n                if (remove(v))\n                    yield return v;\n                else\n                    dict.Add(new KeyValuePair<Tk, Tv>(key, v));\n            }\n        }\n\n        public static IEnumerable<Tv> PopAll<Tk, Tv>(this Dict<Tk, Tv> dict, Tk key)\n            where Tk : IEquatable<Tk>\n        {\n            while (true)\n            {\n                Tv value;\n                if (dict.TryGetValue(key, out value))\n                    yield return value;\n                else\n                    yield break;\n                dict.Remove(key);\n            }\n        }\n\n        public static int Pop(this IntSet self)\n        {\n            if (self.Count == 0)\n                throw new InvalidOperationException();\n            int result = self.First();\n            self.Remove(result);\n            return result;\n        }\n\n        public static T TryPop<T>(this SymbolDict<T> self, Symbol key)\n        {\n            T value = default(T);\n            if (self.TryGetValue(key, out value))\n                self.Remove(key);\n            return value;\n        }\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Symbol/IDict.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public interface IIntCountable\n    {\n        int Count { get; }\n    }\n\n    public interface ICountable\n    {\n        long LongCount { get; }\n    }\n\n    public interface IDict\n    {\n        Type KeyType { get; }\n        Type ValueType { get; }\n\n        IEnumerable<(object, object)> ObjectPairs { get; }\n\n        void AddObject(object key, object value);\n        void Clear();\n    }\n\n    public interface ICountableDict : ICountable, IDict\n    {\n    }\n\n    public interface IDict<TKey, TValue>\n    {\n        IEnumerable<TKey> Keys { get; }\n        IEnumerable<TValue> Values { get; }\n        IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs { get; }\n        TValue this[TKey key] { get; set; }\n        void Add(TKey key, TValue value);\n        bool ContainsKey(TKey key);\n        bool Remove(TKey key);\n        bool TryGetValue(TKey key, out TValue value);\n    }\n\n    public interface IDictDepth\n    {\n        int Depth { get; }\n    }\n\n\n    public interface IDictSet\n    {\n        Type KeyType { get; }\n\n        IEnumerable<object> Objects { get; }\n\n        bool AddObject(object obj);\n        void Clear();\n    }\n\n    public interface ICountableDictSet : ICountable, IDictSet\n    {\n    }\n\n    public interface IDictSet<TKey>\n    {\n        IEnumerable<TKey> Items { get; }\n        bool Add(TKey item);\n        bool Contains(TKey item);\n        bool Remove(TKey item);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Symbol/SymMapBase.cs",
    "content": "using System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    public class SymMapBase\n    {\n        protected SymbolDict<object> m_ht;\n        protected Symbol m_typeName;\n\n        #region Constructors\n\n        public SymMapBase(Symbol typeName, SymbolDict<object> ht)\n        {\n            m_typeName = typeName;\n            m_ht = ht;\n        }\n\n        public SymMapBase()\n            : this(Symbol.Empty, new SymbolDict<object>())\n        { }\n\n        public SymMapBase(Symbol typeName)\n            : this(typeName, new SymbolDict<object>())\n        { }\n\n        public SymMapBase(SymMapBase map)\n            : this(map.m_typeName, map.m_ht.Copy())\n        { }\n\n        /// <summary>\n        /// Creates a shallow copy of the supplied map, but uses entries\n        /// in the supplied override dictionary instead of map entries\n        /// where they exist.\n        /// </summary>\n        public SymMapBase(SymMapBase map, SymbolDict<object> overrides)\n            : this(map.m_typeName,\n                   overrides != null ? overrides.Copy() : new SymbolDict<object>())\n        {\n            if (overrides != null)\n            {\n                foreach (var item in map.m_ht)\n                {\n                    if (overrides.Contains(item.Key)) continue;\n                    m_ht[item.Key] = item.Value;\n                }\n            }\n            else\n            {\n                foreach (var item in map.m_ht)\n                    m_ht[item.Key] = item.Value;\n            }\n        }\n\n        #endregion\n\n        #region Indexer\n\n        public object this[string key]\n        {\n            get\n            {\n                return m_ht[Symbol.Create(key)];\n            }\n            set\n            {\n                m_ht[Symbol.Create(key)] = value;\n            }\n        }\n\n        public object this[Symbol key]\n        {\n            get\n            {\n                return m_ht[key];\n            }\n            set\n            {\n                m_ht[key] = value;\n            }\n        }\n\n        #endregion\n\n        #region Properties\n\n        public Symbol TypeName\n        {\n            get { return m_typeName; }\n            set { m_typeName = value; }\n        }\n\n        public IEnumerable<KeyValuePair<Symbol, object>> MapItems\n        {\n            get { foreach (var kvp in m_ht) yield return kvp; }\n        }\n\n        #endregion\n\n        #region Typed Access\n\n        public T Get<T>(TypedSymbol<T> key) => m_ht.Get(key);\n\n        public T GetOrDefault<T>(TypedSymbol<T> key) => m_ht.GetOrDefault(key);\n\n        public T Get<T>(TypedSymbol<T> key, T defaultValue) => m_ht.Get(key, defaultValue);\n\n        public T Get<T>(Symbol key) => m_ht.TryGetValue(key, out object r) ? (T)r : default;\n\n        public T Get<T>(Symbol key, T defaultValue) => m_ht.TryGetValue(key, out object r) ? (T)r : defaultValue;\n\n        public void Set<T>(TypedSymbol<T> key, T value) => m_ht.Set(key, value);\n\n        #endregion\n\n        #region Queries\n\n        /// <summary>\n        /// Checks if key exists.\n        /// </summary>\n        public bool Contains(Symbol key) => m_ht.Contains(key);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Symbol/SymMapBaseTraversal.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace Aardvark.Base\n{\n    public delegate SymMapBase SymMapBaseVisitor(SymMapBase map, SymMapBaseTraversal.Visit visit);\n\n    public class SymMapBaseTraversal\n    {\n        public enum Mode\n        {\n            NonModifying = 0x0000,\n            Modifying = 0x0001,\n        }\n\n        [Flags]\n        public enum Visit\n        {\n            Pre = 0x0001,\n            Post = 0x0002,\n            PreAndPost = Pre | Post,\n        }\n\n        /// <summary>\n        /// This event fires once for each node, .\n        /// </summary>\n        public event SymMapBaseVisitor OnDefaultVisit;\n\n        #region Constructors\n\n        public SymMapBaseTraversal()\n        {\n            ModifyMode = Mode.Modifying;\n            VisitMode = Visit.Pre;\n        }\n\n        public SymMapBaseTraversal(Mode mode)\n        {\n            ModifyMode = mode;\n            VisitMode = Visit.Pre;\n        }\n\n        public SymMapBaseTraversal(Visit visit)\n        {\n            ModifyMode = Mode.NonModifying;\n            VisitMode = visit;\n        }\n\n        public SymMapBaseTraversal(Mode mode, Visit visit)\n        {\n            ModifyMode = mode;\n            VisitMode = visit;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public Mode ModifyMode { get; set; }\n\n        public Visit VisitMode { get; set; }\n\n        public SymbolDict<SymMapBaseVisitor> PerNameVisitors { get; } = new SymbolDict<SymMapBaseVisitor>();\n\n        #endregion\n\n        public SymMapBase Traverse(SymMapBase map)\n        {\n            // choose visitor\n            SymMapBaseVisitor visitor = OnDefaultVisit;\n            if (map.TypeName != null && PerNameVisitors.ContainsKey(map.TypeName))\n            {\n                visitor = PerNameVisitors[map.TypeName];\n            }\n\n            // pre visit\n            if ((VisitMode & Visit.Pre) != 0)\n            {\n                if (visitor != null)\n                {\n                    if (ModifyMode == Mode.Modifying)\n                    {\n                        map = visitor(map, Visit.Pre);\n                    }\n                    else\n                    {\n                        SymMapBase tmp = visitor(map, Visit.Pre);\n                        if (tmp != map)\n                        {\n                            throw new ArgumentException(\n                                \"The node returned by a non-modifying pre-visit is \" +\n                                \"different from the node that has been visited. \" +\n                                \"This makes no sense!\"\n                                );\n                        }\n                    }\n                }\n            }\n\n            // traverse children\n            if (ModifyMode == Mode.Modifying)\n            {\n                SymbolDict<object> tmp = new SymbolDict<object>();\n                foreach (var e in map.MapItems)\n                {\n                    tmp[e.Key] = e.Value;\n                }\n\n                foreach (var e in tmp)\n                {\n                    object o = e.Value;\n                    if (o is SymMapBase)\n                        map[e.Key] = Traverse((SymMapBase)o);\n                    else if (o is SymMapBase[] array)\n                    {\n                        for (int i = 0; i < array.Length; i++)\n                            array[i] = Traverse(array[i]);\n\n                    }\n                    else if (o is List<SymMapBase> list)\n                    {\n                        for (int i = 0; i < list.Count; i++)\n                            list[i] = Traverse(list[i]);\n                    }\n                    else if (o is Dict<string, SymMapBase>)\n                    {\n                        var dict = new Dict<string, SymMapBase>();\n                        foreach (var kvp in (Dict<string, SymMapBase>)o)\n                        {\n                            dict[kvp.Key] = Traverse(kvp.Value);\n                        }\n                        map[e.Key] = dict;\n                    }\n                    else if (o is SymbolDict<SymMapBase>)\n                    {\n                        var dict = new SymbolDict<SymMapBase>();\n                        foreach (var kvp in (SymbolDict<SymMapBase>)o)\n                        {\n                            dict[kvp.Key] = Traverse(kvp.Value);\n                        }\n                        map[e.Key] = dict;\n                    }\n                    else if (o is DictSet<SymMapBase>)\n                    {\n                        var set = new DictSet<SymMapBase>();\n                        foreach (var m in (DictSet<SymMapBase>)o)\n                            set.Add(Traverse(m));\n                        map[e.Key] = set;\n                    }\n                }\n            }\n            else\n            {\n                foreach (var e in map.MapItems)\n                {\n                    object o = e.Value;\n                    if (o is SymMapBase)\n                    {\n                        Traverse((SymMapBase)o);\n                    }\n                    else if (o is SymMapBase[])\n                    {\n                        foreach (var m in (SymMapBase[])o)\n                            Traverse(m);\n                    }\n                    else if (o is List<SymMapBase>)\n                    {\n                        foreach (var m in (List<SymMapBase>)o)\n                            Traverse(m);\n                    }\n                    else if (o is Dict<string, SymMapBase>)\n                    {\n                        foreach (var m in ((Dict<string, SymMapBase>)o).Values)\n                            Traverse(m);\n                    }\n                    else if (o is SymbolDict<SymMapBase>)\n                    {\n                        foreach (var m in ((SymbolDict<SymMapBase>)o).Values)\n                            Traverse(m);\n                    }\n                    else if (o is DictSet<SymMapBase>)\n                    {\n                        foreach (var m in (DictSet<SymMapBase>)o)\n                            Traverse(m);\n                    }\n                }\n            }\n\n            // post visit\n            if ((VisitMode & Visit.Post) != 0)\n            {\n                if (visitor != null)\n                {\n                    if (ModifyMode == Mode.Modifying)\n                    {\n                        map = visitor(map, Visit.Post);\n                    }\n                    else\n                    {\n                        var tmp = visitor(map, Visit.Post);\n                        if (tmp != map)\n                        {\n                            throw new ArgumentException(\n                                \"The node returned by a non-modifying post-visit is \" +\n                                \"different from the node that has been visited. \" +\n                                \"This makes no sense!\"\n                                );\n                        }\n                    }\n                }\n            }\n\n            return map;\n        }\n    }\n\n    public class SymMapBaseCollectionTraversal\n    {\n        [Obsolete(\"Use Symbol overload\")]\n        public static List<SymMapBase> Collect(SymMapBase root, string typenameToCollect)\n             => new SymMapBaseCollectionTraversal(root).Collect((Symbol)typenameToCollect);\n\n        public static List<SymMapBase> Collect(SymMapBase root, Symbol typenameToCollect)\n             => new SymMapBaseCollectionTraversal(root).Collect(typenameToCollect);\n\n        public SymMapBaseCollectionTraversal(SymMapBase root) => m_root = root;\n\n        public SymMapBaseCollectionTraversal(SymMapBase root, TextWriter debugOutput)\n        {\n            m_root = root;\n            m_out = debugOutput;\n        }\n\n        private readonly TextWriter m_out = null;\n\n        [Obsolete(\"Use Symbol overload\")]\n        public List<SymMapBase> Collect(string typenameToCollect)\n        {\n            return Collect((Symbol)typenameToCollect);\n        }\n\n        public List<SymMapBase> Collect(Symbol typenameToCollect)\n        {\n            if (m_out != null)\n            {\n                m_out.WriteLine(\"SymMapBaseCollectionTraversal START\");\n            }\n\n            m_visited = new Dictionary<SymMapBase, int>();\n            m_name = typenameToCollect;\n            m_result = new List<SymMapBase>();\n            SymMapBaseTraversal trav = new SymMapBaseTraversal(\n                SymMapBaseTraversal.Mode.NonModifying,\n                SymMapBaseTraversal.Visit.Pre\n                );\n            trav.OnDefaultVisit += new SymMapBaseVisitor(Visit);\n            trav.Traverse(m_root);\n\n            if (m_out != null)\n            {\n                m_out.WriteLine(\"SymMapBaseCollectionTraversal END\");\n            }\n\n            return m_result;\n        }\n\n        private SymMapBase Visit(SymMapBase m, SymMapBaseTraversal.Visit visit)\n        {\n            if (m_out != null)\n            {\n                m_out.WriteLine(\"visiting {0}\", m.TypeName);\n            }\n\n            if (m_visited.ContainsKey(m))\n            {\n                //throw new InvalidOperationException(m.TypeName);\n                m_visited[m] += 1;\n                //Console.WriteLine(\n                //    \"cycle detected: map {0}, {1} visits\", m.TypeName, m_visited[m]\n                //    );\n            }\n            else\n            {\n                m_visited[m] = 1;\n            }\n\n            if (m.TypeName == m_name)\n            {\n                m_result.Add(m);\n            }\n            return m;\n        }\n\n        private readonly SymMapBase m_root;\n        private Symbol m_name;\n        private List<SymMapBase> m_result;\n        private Dictionary<SymMapBase, int> m_visited;\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Symbol/Symbol.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Threading;\n\nnamespace Aardvark.Base\n{\n    public readonly struct Symbol : IEquatable<Symbol>, IComparable<Symbol>, IComparable\n    {\n        public readonly int Id;\n\n        #region Internal Constructor\n\n        /// <summary>\n        /// DO NOT USE THIS CONSTRUCTOR!\n        /// Use Create(...) instead.\n        /// </summary>\n        internal Symbol(int id) => Id = id;\n\n        #endregion\n\n        #region Static Creators\n\n        public static Symbol Create(string str) => SymbolManager.GetSymbol(str);\n\n        public static Symbol CreateNewGuid() => SymbolManager.GetSymbol(Guid.NewGuid());\n\n        public static Symbol Create(Guid guid) => SymbolManager.GetSymbol(guid);\n\n        public static readonly Symbol Empty = default;\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns true if the Symbol is negative.\n        /// For details on negative symbols see the\n        /// unary minus operator.\n        /// </summary>\n        public bool IsNegative => Id < 0;\n\n        /// <summary>\n        /// Returns true if the Symbol is not negative.\n        /// For details on negative symbols see the\n        /// unary minus operator.\n        /// </summary>\n        public bool IsPositive => Id > 0;\n\n        public bool IsNotEmpty => Id != 0;\n\n        public bool IsEmpty => Id == 0;\n\n        #endregion\n\n        #region Overrides\n\n        public override int GetHashCode() => Id;\n\n        public override bool Equals(object obj) => (obj is Symbol symbol) ? (Id == symbol.Id) : false;\n\n        public override string ToString() => SymbolManager.GetString(Id);\n\n        public Guid ToGuid() => SymbolManager.GetGuid(Id);\n\n        #endregion\n\n        #region IEquatable<Symbol> Members\n\n        public bool Equals(Symbol other) => Id == other.Id;\n\n        #endregion\n\n        #region IComparable Members\n\n        public int CompareTo(object obj)\n        {\n            if (obj is Symbol) return Id.CompareTo(((Symbol)obj).Id);\n            else throw new NotSupportedException(string.Format(\"Cannot compare symbol to {0}\", obj));\n        }\n\n        #endregion\n\n        #region IComparable<Symbol> Members\n\n        public int CompareTo(Symbol other) => Id.CompareTo(other.Id);\n\n        #endregion\n\n        #region Operators\n\n        public static bool operator ==(Symbol a, Symbol b) => a.Id == b.Id;\n\n        public static bool operator !=(Symbol a, Symbol b) => a.Id != b.Id;\n\n        /// <summary>\n        /// Creates a negative symbol from an ordinary symbol.\n        /// Negative symbols have no string representation, they\n        /// are however useful to store a second value in a\n        /// dictionary.\n        /// </summary>\n        public static Symbol operator -(Symbol symbol) => new Symbol(-symbol.Id);\n\n        #endregion\n\n        #region Conversion\n\n        public static implicit operator Symbol(string str) => Create(str);\n\n        #endregion\n    }\n\n    public interface ITypedSymbol\n    {\n        Symbol GetSymbol();\n        Type GetSymbolType();\n    }\n\n    /// <summary>\n    /// A typed symbol is a symbol that is associated with\n    /// a type at compile time. This can be used in Dicts\n    /// to associate each key with a value type.\n    /// </summary>\n    public readonly struct TypedSymbol<T> : ITypedSymbol\n    {\n        public readonly Symbol Symbol;\n\n        #region Constructor\n\n        public TypedSymbol(string str) => Symbol = str;\n\n        public TypedSymbol(Symbol symbol) => Symbol = symbol;\n\n        #endregion\n\n        #region ITypedSymbol Members\n\n        public Symbol GetSymbol() => Symbol;\n\n        public Type GetSymbolType() => typeof(T);\n\n        #endregion\n\n        #region Conversion\n\n        public static implicit operator TypedSymbol<T>(string str) => new TypedSymbol<T>(str);\n\n        #endregion\n    }\n\n    public static class SymbolExtensions\n    {\n        public static Symbol ToSymbol(this string str) => Symbol.Create(str);\n\n        public static TypedSymbol<T> WithType<T>(this Symbol symbol) => new TypedSymbol<T>(symbol);\n\n        /// <summary>\n        /// Returns the result of .ToString() of an objects as Symbol.\n        /// </summary>\n        public static Symbol ToSymbol(this object self) => Symbol.Create(self.ToString());\n    }\n    \n    internal static class SymbolManager\n    {\n        private static readonly Dict<string, int> s_stringDict = new Dict<string, int>(1024);\n        private static readonly Dict<Guid, int> s_guidDict = new Dict<Guid, int>(1024);\n        private static readonly List<string> s_allStrings = new List<string>(1024);\n        private static readonly List<Guid> s_allGuids = new List<Guid>(1024);\n        private static SpinLock s_lock = new SpinLock();\n        \n        static SymbolManager()\n        {\n            s_allStrings.Add(string.Empty);\n            s_allGuids.Add(Guid.Empty);\n        }\n\n        internal static Symbol GetSymbol(Guid guid)\n        {\n            int id;\n            var locked = false;\n            try\n            {\n                s_lock.Enter(ref locked);\n                if (!s_guidDict.TryGetValue(guid, out id))\n                {\n                    id = s_allStrings.Count;\n                    var str = guid.ToString();\n                    s_guidDict.Add(guid, id);\n                    s_stringDict.Add(str, id);\n                    s_allStrings.Add(str);\n                    s_allGuids.Add(guid);\n                }\n            }\n            finally { if (locked) s_lock.Exit(); }\n            return new Symbol(id);\n        }\n\n        internal static Symbol GetSymbol(string str)\n        {\n            if (string.IsNullOrEmpty(str))\n                return default;\n\n            int id;\n            int hash = str.GetHashCode(); // hashcode computation outside spinlock\n            var locked = false;\n            try\n            {\n                s_lock.Enter(ref locked);\n                if (!s_stringDict.TryGetValue(str, hash, out id))\n                {\n                    id = s_allStrings.Count;\n                    s_stringDict.Add(str, hash, id);\n                    s_allStrings.Add(str);\n                    s_allGuids.Add(Guid.Empty);\n                }\n            }\n            finally { if (locked) s_lock.Exit(); }\n            return new Symbol(id);\n        }\n\n        internal static Guid GetGuid(int id)\n        {\n            if (id > 0)\n            {\n                var locked = false;\n                try\n                {\n                    s_lock.Enter(ref locked);\n                    return s_allGuids[id];\n                }\n                finally { if (locked) s_lock.Exit(); }\n            }\n            return Guid.Empty;\n        }\n\n        internal static string GetString(int id)\n        {\n            var locked = false;\n            if (id > 0)\n            {\n                try\n                {\n                    s_lock.Enter(ref locked);\n                    return s_allStrings[id];\n                }\n                finally { if (locked) s_lock.Exit(); }\n            }\n            else if (id < 0)\n            {\n                string str;\n                try\n                {\n                    s_lock.Enter(ref locked);\n                    str = s_allStrings[-id];\n                }\n                finally { if (locked) s_lock.Exit(); }\n                return \"-\" + str;\n            }\n            return string.Empty;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Text/Text.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Text;\nusing System.Text.RegularExpressions;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// A facade structure that represents a part of a string.\n    /// This can be used to do string manipulations without copying\n    /// too many strings.\n    /// </summary>\n    public struct Text : IEquatable<Text>\n    {\n        public readonly int Start;\n        public readonly int End;\n        public readonly string String;\n\n        #region Constructors\n\n        public Text(string str)\n        {\n            Start = 0;\n            End = str.Length;\n            String = str;\n        }\n\n        public Text(string str, int start)\n        {\n            Start = start;\n            End = str.Length;\n            String = str;\n        }\n\n        public Text(string str, int start, int count)\n        {\n            Start = start;\n            End = start + count;\n            String = str;\n        }\n\n        public Text(int start, int end, string str)\n        {\n            Start = start;\n            End = end;\n            String = str;\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Text Empty = new Text(null, 0, 0);\n\n        #endregion\n\n        #region Properties\n\n        public readonly int Count => End - Start;\n\n        public readonly bool IsEmpty => Count <= 0;\n\n        public readonly bool IsWhiteSpace => IsOnly(CharFun.IsWhiteSpace);\n\n        public readonly Text WhiteSpaceAtStartTrimmed => TrimmedAtStart(CharFun.IsWhiteSpace);\n\n        public readonly Text WhiteSpaceAtEndTrimmed => TrimmedAtEnd(CharFun.IsWhiteSpace);\n\n        public readonly Text WhiteSpaceTrimmed => Trimmed(CharFun.IsWhiteSpace);\n\n        #endregion\n\n        #region Indexer\n\n        public readonly char this[int index] => String[Start + index];\n\n        #endregion\n\n        #region Processing Methods\n\n        public readonly int IndexOf(char ch)\n        {\n            var index = String.IndexOf(ch, Start, Count);\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int IndexOf(string str)\n        {\n            var index = String.IndexOf(str, Start, Count);\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int IndexOf(char ch, int start)\n        {\n            if (start >= 0) { start += Start; if (start >= End) return -1; }\n            else start = Math.Max(Start, start + End);\n            var index = String.IndexOf(ch, start, End - start);\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int IndexOf(string str, int start)\n        {\n            if (start >= 0) { start += Start; if (start >= End) return -1; }\n            else start = Math.Max(Start, start + End);\n            var index = String.IndexOf(str, start, End - start);\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int IndexOf(char ch, int start, int count)\n        {\n            if (start >= 0) { start += Start; if (start >= End) return -1; }\n            else start = Math.Max(Start, start + End);\n            var index = String.IndexOf(ch, start, Math.Min(count, End - start));\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int IndexOf(string str, int start, int count)\n        {\n            if (start >= 0) { start += Start; if (start >= End) return -1; }\n            else start = Math.Max(Start, start + End);\n            var index = String.IndexOf(str, start, Math.Min(count, End - start));\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int LastIndexOf(char ch)\n        {\n            var index = String.LastIndexOf(ch, Start, Count);\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int LastIndexOf(string str)\n        {\n            var index = String.LastIndexOf(str, Start, Count);\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int LastIndexOf(char ch, int start)\n        {\n            if (start >= 0) { start += Start; if (start >= End) return -1; }\n            else start = Math.Max(Start, start + End);\n            var index = String.LastIndexOf(ch, start, End - start);\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int LastIndexOf(string str, int start)\n        {\n            if (start >= 0) { start += Start; if (start >= End) return -1; }\n            else start = Math.Max(Start, start + End);\n            var index = String.LastIndexOf(str, start, End - start);\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int LastIndexOf(char ch, int start, int count)\n        {\n            if (start >= 0) { start += Start; if (start >= End) return -1; }\n            else start = Math.Max(Start, start + End);\n            var index = String.LastIndexOf(ch, start, Math.Min(count, End - start));\n            return index < 0 ? -1 : index - Start;\n        }\n\n        public readonly int LastIndexOf(string str, int start, int count)\n        {\n            if (start >= 0) { start += Start; if (start >= End) return -1; }\n            else start = Math.Max(Start, start + End);\n            var index = String.LastIndexOf(str, start, Math.Min(count, End - start));\n            return index < 0 ? -1 : index - Start;\n        }\n\n        /// <summary>\n        /// Return the subtext in the range [start, end). For the start\n        /// index, negative indices count from the end. For the end index,\n        /// negative indices and the index 0 count from the end. The ranges\n        /// are clamped to the input text so that no exceptions can occur.\n        /// If the the start and end index are crossed, the empty text is\n        /// returned. As an example the call t.Sub(-3, 0) returns a text\n        /// containing the last 3 characters t or the complete text t, if\n        /// its length is less than 3 characters.\n        /// </summary>\n        public readonly Text Sub(int start, int end)\n        {\n            start = start < 0   ? Math.Max(Start, End + start)\n                                : Math.Min(Start + start, End);\n            end = end <= 0      ? Math.Max(Start, End + end)\n                                : Math.Min(Start + end, End);\n            return start < end ? new Text(start, end, String) : Empty;\n        }\n\n        public readonly string SubString(int start, int count)\n        {\n            start += Start;\n            return start < End\n                    ? String.Substring(start, Math.Min(count, End - start))\n                    : \"\";\n        }\n\n        public readonly Text SubText(int start)\n        {\n            start += Start;\n            return start < End ? new Text(start, End, String) : Empty;\n        }\n\n        public readonly Text SubText(int start, int count)\n        {\n            start += Start;\n            return start < End\n                    ? new Text(start, Math.Min(start + count, End), String)\n                    : Empty;\n        }\n\n        public readonly bool StartsWith(string prefix)\n        {\n            int c = prefix.Length;\n            if (c > Count) return false;\n            for (int i = 0, p = Start; i < c; i++, p++)\n                if (prefix[i] != String[p]) return false;\n            return true;\n        }\n\n        public readonly bool EndsWith(string postfix)\n        {\n            int c = postfix.Length;\n            if (c > Count) return false;\n            for (int i = 0, p = End - c; i < c; i++, p++)\n                if (postfix[i] != String[p]) return false;\n            return true;\n        }\n\n        public readonly bool StartsWith(Text prefix)\n        {\n            int c = prefix.Count;\n            if (c > Count) return false;\n            for (int p = Start, e = Start + c, q = prefix.Start; p < e; p++, q++)\n                if (prefix.String[q] != String[p]) return false;\n            return true;\n        }\n\n        public readonly bool EndsWith(Text postfix)\n        {\n            int c = postfix.Count;\n            if (c > Count) return false;\n            for (int p = End - c, e = End, q = postfix.Start; p < e; p++, q++)\n                if (postfix.String[q] != String[p]) return false;\n            return true;\n        }\n\n        /// <summary>\n        /// Returns true if the supplied predicate is true for all characters\n        /// of the text.\n        /// </summary>\n        public readonly bool IsOnly(Func<char, bool> charPredicate)\n        {\n            for (int i = Start, e = End; i < e; i++)\n            {\n                if (charPredicate(String[i])) continue;\n                return false;\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Returns the text without the characters at the start, for which\n        /// the supplied predicate is true.\n        /// </summary>\n        public readonly Text TrimmedAtStart(Func<char, bool> trimIfTrue)\n        {\n            for (int s = Start, e = End; s < e; s++)\n            {\n                if (trimIfTrue(String[s])) continue;\n                return new Text(s, e, String);\n            }\n            return Empty;\n        }\n\n        /// <summary>\n        /// Returns the text without the characters at the end, for which\n        /// the supplied predicate is true.\n        /// </summary>\n        public readonly Text TrimmedAtEnd(Func<char, bool> trimIfTrue)\n        {\n            for (int s = Start, e = End - 1; s <= e; e--)\n            {\n                if (trimIfTrue(String[e])) continue;\n                return new Text(s, 1 + e, String);\n            }\n            return Empty;\n        }\n        \n        /// <summary>\n        /// Returns the text without the caracters at the start and at the\n        /// end, for which the supplied predicate is true.\n        /// </summary>\n        /// <param name=\"trimIfTrue\"></param>\n        public readonly Text Trimmed(Func<char, bool> trimIfTrue)\n        {\n            for (int s = Start, e = End; s < e; s++)\n            {\n                if (trimIfTrue(String[s])) continue;\n                for (--e; s < e; e--) // String[s] already tested\n                {\n                    if (trimIfTrue(String[e])) continue;\n                    return new Text(s, 1 + e, String);\n                }\n            }\n            return Empty;\n        }\n\n        #endregion\n\n        #region Overrides\n\n        public override readonly string ToString() => String.Substring(Start, Count);\n\n        public override readonly int GetHashCode()\n        {\n            int hc = Count;\n            for (int i = Start, e = End; i < e; i++)\n                hc = hc * 31 + String[i];\n            return hc;\n        }\n\n        public override readonly bool Equals(object obj) => obj is Text ? this == (Text)obj : false;\n\n        #endregion\n\n        #region Operators\n\n        public static bool operator ==(Text t, Text t1)\n        {\n            if (t.Count != t1.Count) return false;\n            string s = t.String, s1 = t1.String;\n            if (s == s1 && t.Start == t1.Start) return true;\n            for (int i = t.Start, e = t.End, i1 = t1.Start; i < e; i++, i1++)\n                if (s[i] != s1[i1]) return false;\n            return true;\n        }\n\n        public static bool operator !=(Text t, Text t1)\n        {\n            if (t.Count != t1.Count) return true;\n            string s = t.String, s1 = t1.String;\n            if (s == s1 && t.Start == t1.Start) return false;\n            for (int i = t.Start, e = t.End, i1 = t1.Start; i < e; i++, i1++)\n                if (s[i] != s1[i1]) return true;\n            return false;\n        }\n\n        public static bool operator ==(Text t, string s1)\n        {\n            if (t.Count != s1.Length) return false;\n            string s = t.String;\n            if (s == s1 && t.Start == 0) return true;\n            for (int i = t.Start, e = t.End, i1 = 0; i < e; i++, i1++)\n                if (s[i] != s1[i1]) return false;\n            return true;\n        }\n\n        public static bool operator !=(Text t, string s1)\n        {\n            if (t.Count != s1.Length) return true;\n            string s = t.String;\n            if (s == s1 && t.Start == 0) return false;\n            for (int i = t.Start, e = t.End, i1 = 0; i < e; i++, i1++)\n                if (s[i] != s1[i1]) return true;\n            return false;\n        }\n\n        #endregion\n\n        #region Various Operations\n\n        public static Regex IdentifierRegex = new Regex(@\"\\b[A-Za-z_][0-9A-Za-z_]*\\b\");\n\n        public readonly Text ReplaceIdentifiers(Dictionary<string, string> changeMap)\n             => ReplaceParts(IdentifierRegex, changeMap);\n\n        public readonly Text ReplaceParts(\n            Regex partRegex,\n            Dictionary<string, string> changeMap)\n        {\n            StringBuilder newText = new StringBuilder();\n            var str = String;\n            int pos = Start, end = End;\n            Match match = partRegex.Match(str, pos, end - pos);\n            while (match.Success)\n            {\n                Group group = match.Groups[1];\n                newText.Append(str, pos, match.Index - pos);\n                var unchanged = match.Value;\n                if (changeMap.TryGetValue(unchanged, out string changed))\n                    newText.Append(changed);\n                else\n                    newText.Append(unchanged);\n                pos = match.Index + match.Length;\n                if (pos >= end) break;\n                match = partRegex.Match(str, pos, end - pos);\n            }\n            if (pos > 0)\n            {\n                if (pos < end)\n                    newText.Append(str, pos, end - pos);\n                return new Text(newText.ToString());\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Splits a nested structure of comma-separated square bracked\n        /// delimited lists at a specified split level. Level 0 means that\n        /// the split is performed outside the outermost square brackets.\n        /// Level 1 means that the split is peformed inside the outermost\n        /// square brackets.\n        /// NOTE: The resulting parts are not trimmed. Use the Trim extension\n        /// to trim all resulting strings.\n        /// </summary>\n        public readonly IEnumerable<Text> NestedBracketSplit(int splitLevel)\n        {\n            int level = 0;\n            int begin = Start;\n            int end = End;\n            for (int pos = Start; pos < end; pos++)\n            {\n                switch (String[pos])\n                {\n                    case '[':\n                        ++level;\n                        if (level == splitLevel) begin = pos + 1;\n                        break;\n                    case ']':\n                        if (level == splitLevel)\n                            yield return new Text(begin, pos, String);\n                        --level;\n                        break;\n                    case ',':\n                        if (level == splitLevel)\n                        {\n                            yield return new Text(begin, pos, String);\n                            begin = pos + 1;\n                        }\n                        break;\n                }\n            }\n            if (level == splitLevel && begin < end)\n                yield return new Text(begin, end, String);\n        }\n\n        #endregion\n\n        #region Parsing\n\n        /// <summary>\n        /// This structure holds info about where the line with the number\n        /// (Index - 1) starts.\n        /// </summary>\n        public struct Line\n        {\n            public int Index;\n            public int Start;\n\n            public Line(int count, int start) { Index = count; Start = start; }\n        }\n\n        /// <summary>\n        /// Given a known previous line, get the line at the current position.\n        /// </summary>\n        public readonly Line GetLineOfPos(Line line, int pos)\n        {\n            int i = line.Start;\n            while (i < pos)\n            {\n                if (String[Start + i] == '\\n')\n                    { ++i; ++line.Index; line.Start = i; }\n                else\n                    ++i;\n            }\n            return line;\n        }\n\n        /// <summary>\n        /// Get the line of the current position without knowledge of any\n        /// pervious line.\n        /// </summary>\n        public readonly Line GetLineOfPos(int pos) => GetLineOfPos(new Line(0, 0), pos);\n\n        /// <summary>\n        /// Returns the first position after position start in the text, that\n        /// does not contain a whitespace character, or the length of the text\n        /// if it is all whitespace.\n        /// </summary>\n        public readonly int SkipWhiteSpace(int start = 0) => Skip(CharFun.IsWhiteSpace, start);\n\n        public readonly int Skip(Func<char, bool> skipFun, int start = 0)\n        {\n            for (int i = Start + start, e = End; i < e; i++)\n            {\n                if (skipFun(String[i])) continue;\n                return i - Start;\n            }\n            return End - Start;\n        }\n\n        public readonly bool ParseBool()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfBoolAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly byte ParseByte()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfByteAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly sbyte ParseSByte()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfSByteAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly short ParseShort()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfShortAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly ushort ParseUShort()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfUShortAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly int ParseInt()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfIntAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly uint ParseUInt()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfUIntAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly long ParseLong()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfLongAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly ulong ParseULong()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfULongAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly float ParseFloat()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfFloatAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly double ParseDouble()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfDoubleAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        public readonly decimal ParseDecimal()\n        {\n            int i = SkipWhiteSpace(), c = Count;\n            if (i == c) throw new ArgumentException();\n            var pv = ParsedValueOfDecimalAt(i);\n            if (pv.Error != ParseError.None) throw new ArgumentException();\n            i += pv.Length;\n            if (i < c && SkipWhiteSpace(i) < c) throw new ArgumentException();\n            return pv.Value;\n        }\n\n        private static readonly Regex s_boolRegex\n                = new Regex(@\"(?<1>false|f)|(?<2>true|t)|(?<3>.|\\r)\",\n                            RegexOptions.Singleline | RegexOptions.IgnoreCase\n                            | RegexOptions.ExplicitCapture | RegexOptions.Compiled);\n\n        public readonly ParsedValue<bool> ParsedValueOfBoolAt(int start)\n        {\n            start += Start;\n            if (start >= End) return new ParsedValue<bool>(ParseError.EndOfText, 0);\n            var match = s_boolRegex.Match(String, start, 5);\n            if (!match.Success) return new ParsedValue<bool>(ParseError.OutOfRange, 0);\n            if (match.Groups[1].Success) return new ParsedValue<bool>(false, match.Length);\n            if (match.Groups[2].Success) return new ParsedValue<bool>(true, match.Length);\n            return new ParsedValue<bool>(ParseError.OutOfRange, 0);\n        }\n\n        public readonly ParsedValue<byte> ParsedValueOfByteAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            int ch = 0;\n            if (pos >= end) return new ParsedValue<byte>(ParseError.EndOfText, 0);\n            if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n            {\n                ++pos;\n                byte v = (byte)ch; int c = 1;\n                while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    byte v1 = (byte)(v * 10 + ch);\n                    if (++c > 2 && v != v1 / 10)\n                        return new ParsedValue<byte>(ParseError.OutOfRange, pos - start);\n                    v = v1; ++pos;\n                }\n                return new ParsedValue<byte>(v, pos - start);\n            }\n            return new ParsedValue<byte>(ParseError.IllegalCharacter, pos - start);\n        }\n\n        public readonly ParsedValue<sbyte> ParsedValueOfSByteAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            int ch = 0;\n            if (pos >= end) return new ParsedValue<sbyte>(ParseError.EndOfText, 0);\n            if (String[pos] == '-')\n            {\n                if (++pos == end) return new ParsedValue<sbyte>(ParseError.EndOfText, 1);\n                if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ++pos;\n                    sbyte v = (sbyte)(-ch); int c = 1;\n                    while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                    {\n                        sbyte v1 = (sbyte)(v * 10 - ch);\n                        if (++c > 2 && v != v1 / 10L)\n                            return new ParsedValue<sbyte>(ParseError.OutOfRange, pos - start);\n                        v = v1; ++pos;\n                    }\n                    return new ParsedValue<sbyte>(v, pos - start);\n                }\n            }\n            else\n            {\n                if (String[pos] == '+')\n                {\n                    if (++pos == end) return new ParsedValue<sbyte>(ParseError.EndOfText, 1);\n                }\n                if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ++pos;\n                    sbyte v = (sbyte)ch; int c = 1;\n                    while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                    {\n                        sbyte v1 = (sbyte)(v * 10 + ch);\n                        if (++c > 2 && v != v1 / 10L)\n                            return new ParsedValue<sbyte>(ParseError.OutOfRange, pos - start);\n                        v = v1; ++pos;\n                    }\n                    return new ParsedValue<sbyte>(v, pos - start);\n                }\n            }\n            return new ParsedValue<sbyte>(ParseError.IllegalCharacter, pos - start);\n        }\n\n        public readonly ParsedValue<short> ParsedValueOfShortAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            int ch = 0;\n            if (pos >= end) return new ParsedValue<short>(ParseError.EndOfText, 0);\n            if (String[pos] == '-')\n            {\n                if (++pos == end) return new ParsedValue<short>(ParseError.EndOfText, 1);\n                if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ++pos;\n                    short v = (short)(-ch); int c = 1;\n                    while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                    {\n                        short v1 = (short)(v * 10 - ch);\n                        if (++c > 4 && v != v1 / 10L)\n                            return new ParsedValue<short>(ParseError.OutOfRange, pos - start);\n                        v = v1; ++pos;\n                    }\n                    return new ParsedValue<short>(v, pos - start);\n                }\n            }\n            else\n            {\n                if (String[pos] == '+')\n                {\n                    if (++pos == end) return new ParsedValue<short>(ParseError.EndOfText, 1);\n                }\n                if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ++pos;\n                    short v = (short)ch; int c = 1;\n                    while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                    {\n                        short v1 = (short)(v * 10 + ch);\n                        if (++c > 4 && v != v1 / 10L)\n                            return new ParsedValue<short>(ParseError.OutOfRange, pos - start);\n                        v = v1; ++pos;\n                    }\n                    return new ParsedValue<short>(v, pos - start);\n                }\n            }\n            return new ParsedValue<short>(ParseError.IllegalCharacter, pos - start);\n        }\n\n        public readonly ParsedValue<ushort> ParsedValueOfUShortAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            int ch = 0;\n            if (pos >= end) return new ParsedValue<ushort>(ParseError.EndOfText, 0);\n            if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n            {\n                ++pos;\n                ushort v = (ushort)ch; int c = 1;\n                while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ushort v1 = (ushort)(v * 10 + ch);\n                    if (++c > 4 && v != v1 / 10L)\n                        return new ParsedValue<ushort>(ParseError.OutOfRange, pos - start);\n                    v = v1; ++pos;\n                }\n                return new ParsedValue<ushort>(v, pos - start);\n            }\n            return new ParsedValue<ushort>(ParseError.IllegalCharacter, pos - start);\n        }\n\n        public readonly ParsedValue<int> ParsedValueOfIntAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            int ch = 0;\n            if (pos >= end) return new ParsedValue<int>(ParseError.EndOfText, 0);\n            if (String[pos] == '-')\n            {\n                if (++pos == end) return new ParsedValue<int>(ParseError.EndOfText, 1);\n                if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ++pos;\n                    int v = -ch; int c = 1;\n                    while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                    {\n                        int v1 = v * 10 - ch;\n                        if (++c > 9 && v != v1 / 10L)\n                            return new ParsedValue<int>(ParseError.OutOfRange, pos - start);\n                        v = v1;  ++pos;\n                    }\n                    return new ParsedValue<int>(v, pos - start);\n                }\n            }\n            else\n            {\n                if (String[pos] == '+')\n                {\n                    if (++pos == end) return new ParsedValue<int>(ParseError.EndOfText, 1);\n                }\n                if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ++pos;\n                    int v = ch; int c = 1;\n                    while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                    {\n                        int v1 = v * 10 + ch;\n                        if (++c > 9 && v != v1 / 10L)\n                            return new ParsedValue<int>(ParseError.OutOfRange, pos - start);\n                        v = v1;  ++pos;\n                    }\n                    return new ParsedValue<int>(v, pos - start);\n                }\n            }\n            return new ParsedValue<int>(ParseError.IllegalCharacter, pos - start);\n        }\n\n        public readonly ParsedValue<uint> ParsedValueOfUIntAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            int ch = 0;\n            if (pos >= end) return new ParsedValue<uint>(ParseError.EndOfText, 0);\n            if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n            {\n                ++pos;\n                uint v = (uint)ch; int c = 1;\n                while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    uint v1 = v * 10 + (uint)ch;\n                    if (++c > 9 && v != v1 / 10L)\n                        return new ParsedValue<uint>(ParseError.OutOfRange, pos - start);\n                    v = v1; ++pos;\n                }\n                return new ParsedValue<uint>(v, pos - start);\n            }\n            return new ParsedValue<uint>(ParseError.IllegalCharacter, pos - start);\n        }\n\n        public readonly ParsedValue<long> ParsedValueOfLongAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            int ch = 0;\n            if (pos >= end) return new ParsedValue<long>(ParseError.EndOfText, 0);\n            if (String[pos] == '-')\n            {\n                if (++pos == end) return new ParsedValue<long>(ParseError.EndOfText, 1);\n                if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ++pos;\n                    long v = -ch; int c = 1;\n                    while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                    {\n                        long v1 = v * 10 - ch;\n                        if (++c > 18 && v != v1 / 10L)\n                            return new ParsedValue<long>(ParseError.OutOfRange, pos - start);\n                        v = v1; ++pos;\n                    }\n                    return new ParsedValue<long>(v, pos - start);\n                }\n            }\n            else\n            {\n                if (String[pos] == '+')\n                {\n                    if (++pos == end) return new ParsedValue<long>(ParseError.EndOfText, 1);\n                }\n                if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ++pos;\n                    long v = ch; int c = 1;\n                    while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                    {\n                        long v1 = v * 10 + ch;\n                        if (++c > 18 && v != v1 / 10L)\n                            return new ParsedValue<long>(ParseError.OutOfRange, pos - start);\n                        v = v1; ++pos;\n                    }\n                    return new ParsedValue<long>(v, pos - start);\n                }\n            }\n            return new ParsedValue<long>(ParseError.IllegalCharacter, pos - start);\n        }\n\n        public readonly ParsedValue<ulong> ParsedValueOfULongAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            int ch = 0;\n            if (pos >= end) return new ParsedValue<ulong>(ParseError.EndOfText, 0);\n            if ((ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n            {\n                ++pos;\n                ulong v = (ulong)ch;\n                int c = 1;\n                while (pos < end && (ch = (int)(String[pos] - '0')) >= 0 && ch < 10)\n                {\n                    ulong v1 = v * 10 + (ulong)ch;\n                    if (++c > 18 && v != v1 / 10L)\n                        return new ParsedValue<ulong>(ParseError.OutOfRange, pos - start);\n                    v = v1; ++pos;\n                }\n                return new ParsedValue<ulong>(v, pos - start);\n            }\n            return new ParsedValue<ulong>(ParseError.IllegalCharacter, pos - start);\n        }\n\n        public readonly ParsedValue<float> ParsedValueOfFloatAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            if (pos >= end) return new ParsedValue<float>(ParseError.EndOfText, 0);\n            char ch;\n            if ((ch = String[pos]) == '-' || ch == '+')\n            {\n                pos++;\n                if (pos == end) return new ParsedValue<float>(ParseError.EndOfText, pos - start);\n            }\n            if ((ch = String[pos]) < '0' || ch > '9')\n                return new ParsedValue<float>(ParseError.IllegalCharacter, pos - start);\n            while (pos < end && (ch = String[pos]) >= '0' && ch <= '9') pos++;\n            if (pos < end && ch == '.')\n            {\n                ++pos;\n                while (pos < end && (ch = String[pos]) >= '0' && ch <= '9') pos++;\n            }\n            if (pos < end && (ch == 'e' || ch == 'E'))\n            {\n                ++pos;\n                if (pos == end) return new ParsedValue<float>(ParseError.EndOfText, pos - start);\n                if ((ch = String[pos]) == '-' || ch == '+')\n                {\n                    pos++;\n                    if (pos == end) return new ParsedValue<float>(ParseError.EndOfText, pos - start);\n                }\n                if ((ch = String[pos]) < '0' || ch > '9')\n                    return new ParsedValue<float>(ParseError.IllegalCharacter, pos - start);\n                ++pos;\n                while (pos < end && (ch = String[pos]) >= '0' && ch <= '9') pos++;\n            }\n            int len = pos - start;\n            try\n            {\n                return new ParsedValue<float>(float.Parse(String.Substring(start, len), CultureInfo.InvariantCulture), len);\n            }\n            catch\n            {\n                return new ParsedValue<float>(ParseError.OutOfRange, len);\n            }\n        }\n\n        public readonly ParsedValue<double> ParsedValueOfDoubleAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            if (pos >= end) return new ParsedValue<double>(ParseError.EndOfText, 0);\n            char ch;\n            if ((ch = String[pos]) == '-' || ch == '+')\n            {\n                pos++;\n                if (pos == end) return new ParsedValue<double>(ParseError.EndOfText, pos - start);\n            }\n            if ((ch = String[pos]) < '0' || ch > '9')\n                return new ParsedValue<double>(ParseError.IllegalCharacter, pos - start);\n            while (pos < end && (ch = String[pos]) >= '0' && ch <= '9') pos++;\n            if (pos < end && ch == '.')\n            {\n                ++pos;\n                while (pos < end && (ch = String[pos]) >= '0' && ch <= '9') pos++;\n            }\n            if (pos < end && (ch == 'e' || ch == 'E'))\n            {\n                ++pos;\n                if (pos == end) return new ParsedValue<double>(ParseError.EndOfText, pos - start);\n                if ((ch = String[pos]) == '-' || ch == '+')\n                {\n                    pos++;\n                    if (pos == end) return new ParsedValue<double>(ParseError.EndOfText, pos - start);\n                }\n                if ((ch = String[pos]) < '0' || ch > '9')\n                    return new ParsedValue<double>(ParseError.IllegalCharacter, pos - start);\n                ++pos;\n                while (pos < end && (ch = String[pos]) >= '0' && ch <= '9') pos++;\n            }\n            int len = pos - start;\n            try\n            {\n                return new ParsedValue<double>(double.Parse(String.Substring(start, len), CultureInfo.InvariantCulture), len);\n            }\n            catch\n            {\n                return new ParsedValue<double>(ParseError.OutOfRange, len);\n            }\n        }\n\n        public readonly ParsedValue<decimal> ParsedValueOfDecimalAt(int start)\n        {\n            start += Start;\n            int pos = start;\n            int end = End;\n            if (pos >= end) return new ParsedValue<decimal>(ParseError.EndOfText, 0);\n            char ch;\n            if ((ch = String[pos]) == '-' || ch == '+')\n            {\n                pos++;\n                if (pos == end) return new ParsedValue<decimal>(ParseError.EndOfText, pos - start);\n            }\n            if ((ch = String[pos]) < '0' || ch > '9')\n                return new ParsedValue<decimal>(ParseError.IllegalCharacter, pos - start);\n            while (pos < end && (ch = String[pos]) >= '0' && ch <= '9') pos++;\n            if (pos < end && ch == '.')\n            {\n                ++pos;\n                while (pos < end && (ch = String[pos]) >= '0' && ch <= '9') pos++;\n            }\n            int len = pos - start;\n            try\n            {\n                return new ParsedValue<decimal>(decimal.Parse(String.Substring(start, len), CultureInfo.InvariantCulture), len);\n            }\n            catch\n            {\n                return new ParsedValue<decimal>(ParseError.OutOfRange, len);\n            }\n        }\n\n        #endregion\n\n        #region IEquatable<Text> Members\n\n        public readonly bool Equals(Text other) => this == other;\n\n        #endregion\n    }\n\n    public readonly struct Rx\n    {\n        public readonly string Pattern;\n        public readonly Regex Regex;\n\n        /// <summary>\n        /// A second regex is built if the match has to be anchored at the\n        /// start of the search (sub-)string (the caret only works for non-\n        /// sub strings). This is done by adding an always matching second\n        /// group of one character. Thus if the second group succeeds, the\n        /// regex did not match anchored at the start of the search string.\n        /// </summary>\n        public readonly Regex AnchoredRegex;\n\n        #region Constructor\n\n        public Rx(string pattern)\n        {\n            Pattern = pattern;\n            Regex = new Regex(pattern, RegexOptions.Singleline\n                                       | RegexOptions.ExplicitCapture\n                                       | RegexOptions.Compiled);\n\n            AnchoredRegex = new Regex(\"(?<1>\" + pattern + \")|(?<2>.|\\r)\",\n                                      RegexOptions.Singleline\n                                      | RegexOptions.ExplicitCapture\n                                      | RegexOptions.Compiled);\n        }\n\n        public Rx(string pattern, RegexOptions options)\n        {\n            Pattern = pattern;\n            Regex = new Regex(pattern, options | RegexOptions.Singleline\n                                       | RegexOptions.ExplicitCapture\n                                       | RegexOptions.Compiled);\n\n            AnchoredRegex = new Regex(\"(?<1>\" + pattern + \")|(?<2>.|\\r)\",\n                                      options | RegexOptions.Singleline\n                                      | RegexOptions.ExplicitCapture\n                                      | RegexOptions.Compiled);\n        }\n\n        #endregion\n    }\n\n    public enum ParseError\n    {\n        None = 0,\n        EndOfText,\n        IllegalCharacter,\n        OutOfRange,\n    }\n\n    /// <summary>\n    /// A parsed value contains the actual value, the number of characters\n    /// that have been parsed in Length, and an error value of the parse\n    /// operation.\n    /// </summary>\n    public readonly struct ParsedValue<T>\n    {\n        public readonly ParseError Error;\n        public readonly T Value;\n        public readonly int Length;\n\n        #region Constructors\n\n        public ParsedValue(T value, int count)\n        {\n            Value = value; Error = ParseError.None; Length = count;\n        }\n\n        public ParsedValue(ParseError error, int count)\n        {\n            Value = default; Error = error; Length = count;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public bool IsValid => Error == ParseError.None;\n        public bool IsInValid => Error != ParseError.None;\n\n        #endregion\n    }\n\n    public static class Text<T>\n    {\n        public static readonly Func<Text, T> Parse;\n        public static readonly Func<Text, int, ParsedValue<T>> ParsedValueAt;\n\n        #region Constructor\n\n        static Text()\n        {\n            if (typeof(T) == typeof(byte))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, byte>)(t => t.ParseByte());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<byte>>)((t, i) => t.ParsedValueOfByteAt(i));\n            }\n            else if (typeof(T) == typeof(sbyte))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, sbyte>)(t => t.ParseSByte());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<sbyte>>)((t, i) => t.ParsedValueOfSByteAt(i));\n            }\n            else if (typeof(T) == typeof(short))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, short>)(t => t.ParseShort());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<short>>)((t, i) => t.ParsedValueOfShortAt(i));\n            }\n            else if (typeof(T) == typeof(ushort))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, ushort>)(t => t.ParseUShort());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<ushort>>)((t, i) => t.ParsedValueOfUShortAt(i));\n            }\n            else if (typeof(T) == typeof(int))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, int>)(t =>t.ParseInt());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<int>>)((t, i) => t.ParsedValueOfIntAt(i));\n            }\n            else if (typeof(T) == typeof(uint))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, uint>)(t => t.ParseUInt());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<uint>>)((t, i) => t.ParsedValueOfUIntAt(i));\n            }\n            else if (typeof(T) == typeof(long))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, long>)(t => t.ParseLong());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<long>>)((t, i) => t.ParsedValueOfLongAt(i));\n            }\n            else if (typeof(T) == typeof(ulong))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, ulong>)(t => t.ParseULong());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<ulong>>)((t, i) => t.ParsedValueOfULongAt(i));\n            }\n            else if (typeof(T) == typeof(float))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, float>)(t => t.ParseFloat());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<float>>)((t, i) => t.ParsedValueOfFloatAt(i));\n            }\n            else if (typeof(T) == typeof(double))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, double>)(t => t.ParseDouble());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<double>>)((t, i) => t.ParsedValueOfDoubleAt(i));\n            }\n            else if (typeof(T) == typeof(decimal))\n            {\n                Parse = (Func<Text, T>)(object)(Func<Text, decimal>)(t => t.ParseDecimal());\n                ParsedValueAt = (Func<Text, int, ParsedValue<T>>)(object)(Func<Text, int, ParsedValue<decimal>>)((t, i) => t.ParsedValueOfDecimalAt(i));\n            }\n        }\n\n        #endregion\n    }\n\n    public static class TextExtensions\n    {\n        #region String Extension\n\n        public static Text ToText(this String str) => new Text(str);\n\n        public static string ReplaceIdentifiers(this string str, Dictionary<string, string> changeMap)\n             => str.ToText().ReplaceIdentifiers(changeMap).ToString();\n\n        #endregion\n\n        #region StringBuilder Extension\n\n        public static StringBuilder Append(this StringBuilder builder, Text text)\n             => builder.Append(text.String, text.Start, text.Count);\n\n        public static Text ToText(this StringBuilder builder)\n             => new Text(builder.ToString());\n\n        #endregion\n\n        #region List<Text> Extensions\n\n        public static List<string> ToListOfString(this List<Text> textList)\n             => textList.Map(t => t.ToString());\n\n        public static string[] ToStringArray(this List<Text> textList)\n             => textList.MapToArray(t => t.ToString());\n\n        public static string JoinToString(this List<Text> textList, string delimiter)\n             => textList.Map(t => t.ToString()).Join(delimiter);\n\n        #endregion\n\n        #region TextArray Extensions\n\n        public static string[] ToStringArray(this Text[] textArray)\n             => textArray.Map(t => t.ToString());\n\n        public static List<string> ToListOfString(this Text[] textArray)\n            => textArray.MapToList(t => t.ToString());\n\n        [Obsolete(\"Does not always return the same count as NestedBracketSplit() result length. Use NestedBracketSplitCount2 instead.\")]\n        public static int NestedBracketSplitCount(this Text text, int splitLevel)\n        {\n            int count = 0;\n            int level = 0;\n            for (int i = text.Start, e = text.End; i < e; i++)\n            {\n                switch (text.String[i])\n                {\n                    case '[':  ++level; break;\n                    case ']': --level; break;\n                    case ',':\n                        if (level == splitLevel) ++count;\n                        break;\n                }\n            }\n            if (level == splitLevel) ++count;\n            return count;\n        }\n\n        public static int NestedBracketSplitCount2(this Text text, int splitLevel)\n        {\n            int count = 0;\n            int level = 0;\n            int begin = text.Start;\n            int end = text.End;\n            for (int pos = text.Start; pos < end; pos++)\n            {\n                switch (text.String[pos])\n                {\n                    case '[':\n                        ++level;\n                        if (level == splitLevel) begin = pos + 1;\n                        break;\n                    case ']':\n                        if (level == splitLevel) ++count;\n                        --level;\n                        break;\n                    case ',':\n                        if (level == splitLevel)\n                        {\n                            ++count;\n                            begin = pos + 1;\n                        }\n                        break;\n                }\n            }\n            if (level == splitLevel && begin < end)\n                ++count;\n            return count;\n        }\n\n        #endregion\n\n        #region Text Extensions\n\n        public static TArray NestedBracketSplit<T, TArray>(\n                this Text text, int splitLevel, Func<Text, T> parse,\n                Func<TArray> creator, Action<TArray, long, T> setter)\n        {\n            int level = 0;\n            int start = text.Start;\n            int end = text.End;\n            long ai = 0;\n            var array = creator();\n            for (int i = start; i < end; i++)\n            {\n                switch (text.String[i])\n                {\n                    case '[':\n                        ++level;\n                        if (level == splitLevel) start = i + 1;\n                        break;\n                    case ']':\n                        if (level == splitLevel)\n                            setter(array, ai++, parse(new Text(start, i, text.String)));\n                        --level;\n                        break;\n                    case ',':\n                        if (level == splitLevel)\n                        {\n                            setter(array, ai++, parse(new Text(start, i, text.String)));\n                            start = i + 1;\n                        }\n                        break;\n                }\n            }\n            if (level == splitLevel && start < end)\n                setter(array, ai, parse(new Text(start, end, text.String)));\n            return array;\n        }\n\n        public static TStruct NestedBracketSplit<T, TStruct>(\n                this Text text, int splitLevel, Func<Text, T> parse,\n                ActionRefValVal<TStruct, int, T> setter)\n        {\n            int level = 0;\n            int start = text.Start;\n            int end = text.End;\n            int ai = 0;\n            var str = default(TStruct);\n            for (int i = start; i < end; i++)\n            {\n                switch (text.String[i])\n                {\n                    case '[':\n                        ++level;\n                        if (level == splitLevel) start = i + 1;\n                        break;\n                    case ']':\n                        if (level == splitLevel)\n                            setter(ref str, ai++, parse(new Text(start, i, text.String)));\n                        --level;\n                        break;\n                    case ',':\n                        if (level == splitLevel)\n                        {\n                            setter(ref str, ai++, parse(new Text(start, i, text.String)));\n                            start = i + 1;\n                        }\n                        break;\n                }\n            }\n            if (level == splitLevel && start < end)\n                setter(ref str, ai, parse(new Text(start, end, text.String)));\n            return str;\n        }\n\n        public static T[] NestedBracketSplit<T>(\n                this Text text, int splitLevel, Func<Text, T> parse, Func<T[]> creator)\n        {\n            int level = 0;\n            int start = text.Start;\n            int end = text.End;\n            int ai = 0;\n            var array = creator();\n            for (int i = start; i < end; i++)\n            {\n                switch (text.String[i])\n                {\n                    case '[':\n                        ++level;\n                        if (level == splitLevel) start = i + 1;\n                        break;\n                    case ']':\n                        if (level == splitLevel)\n                            array[ai++] = parse(new Text(start, i, text.String));\n                        --level;\n                        break;\n                    case ',':\n                        if (level == splitLevel)\n                        {\n                            array[ai++] = parse(new Text(start, i, text.String));\n                            start = i + 1;\n                        }\n                        break;\n                }\n            }\n            if (level == splitLevel && start < end)\n                array[ai] = parse(new Text(start, end, text.String));\n            return array;\n        }\n\n        public static IEnumerable<Text> Split(this Text text, char c)\n        {\n            int start = text.Start;\n            int end = text.Start;\n\n            while (end < text.End)\n            {\n                if (text.String[end++] == c)\n                {\n                    yield return new Text(start, end - 1, text.String);\n                    start = end;\n                }\n            }\n\n            yield return new Text(start, end, text.String);\n        }\n   \n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Text/TextParser.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Text.RegularExpressions;\n\nnamespace Aardvark.Base\n{\n    #region State with Parser as Generic Parameter\n\n    /// <summary>\n    /// State of a generic recursive descent parser.\n    /// </summary>\n    /// <typeparam name=\"TPar\">Parser class containing static state variables.</typeparam>\n    /// <typeparam name=\"TNode\">Node class for building parse trees.</typeparam>\n    public class State<TPar, TNode> : IEnumerable<Case<TPar, TNode>>\n        where TPar : TextParser<TPar>\n    {\n        public readonly Action<TPar, TNode, Text> TextAct;\n        public readonly Case<TPar, TNode>[] Cases;\n        public readonly Func<TPar, State<TPar, TNode>, TNode, int> Match;\n\n        #region Constructors\n\n        public State(Cases<TPar, TNode> cases)\n            : this(cases.Array, null)\n        { }\n\n        public State(Case<TPar, TNode>[] cases)\n            : this(cases, null)\n        { }\n\n        public State(Cases<TPar, TNode> cases, Action<TPar, TNode, Text> textAct)\n            : this(cases.Array, textAct)\n        { }\n\n        public State(Case<TPar, TNode>[] cases, Action<TPar, TNode, Text> textAct)\n        {\n            Cases = cases;\n            TextAct = textAct;\n\n            var pattern = cases.Map(\n                (c, i) => c.Pattern != null\n                            ? \"(?<\" + (i + 1) + \">\" + c.Pattern + \")\"\n                            : \"(?<\" + (i + 1) + \">.|\\r)\"\n            ).Join(\"|\");\n\n            var regex = new Regex(pattern, RegexOptions.Singleline\n                                           | RegexOptions.ExplicitCapture\n                                           | RegexOptions.Compiled);\n            var caseCount = cases.Length;\n\n            if (textAct != null)\n            {\n                Match = (par, state, node) =>\n                {\n                    var m = regex.Match(par.Text.String, par.Pos, par.Text.End - par.Pos);\n                    if (m.Success)\n                        for (int i = 1; i <= caseCount; i++)\n                            if (m.Groups[i].Success)\n                            {\n                                var c = i - 1;\n                                var index = m.Groups[i].Index;\n                                if (par.Pos < index)\n                                {\n                                    var t = par.PeekToPos(index);\n                                    var adj = state.Cases[c].AdjustFun;\n                                    if (adj != null) t = adj(par, node, t);\n                                    state.TextAct(par, node, t);\n                                    par.SetPosAndCountLines(index);\n                                }\n                                par.LastEnd = index + m.Groups[i].Length;\n                                par.LastCase = c;\n                                return c;\n                            }\n                    if (par.Pos < par.Text.End)\n                    {\n                        state.TextAct(par, node, par.PeekToPos(par.Text.End));\n                        par.SetPosAndCountLines(par.Text.End);\n                    }\n                    return -1;\n                };\n            }\n            else\n            {\n                if (cases[caseCount - 1].Pattern != null)\n                    throw new ArgumentException(\n                        \"either a text action or a default case needs to be specified\");\n\n                Match = (par, state, node) =>\n                {\n                    var m = regex.Match(par.Text.String, par.Pos, par.Text.End - par.Pos);\n                    if (m.Success)\n                        for (int i = 1; i <= caseCount; i++)\n                            if (m.Groups[i].Success)\n                            {\n                                par.LastEnd = m.Groups[i].Index + m.Groups[i].Length;\n                                return par.LastCase = i - 1;\n                            }\n                    return -1;\n                };\n            }\n        }\n\n        #endregion\n\n        public IEnumerable<Case<TPar, TNode>> Items { get { foreach (var c in Cases) yield return c; } }\n\n        #region IEnumerable implementation\n\n        public IEnumerator<Case<TPar, TNode>> GetEnumerator() => Items.GetEnumerator();\n\n        #endregion\n\n        #region IEnumerable implementation\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => Items.GetEnumerator();\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Case with Parser as Generic Parameter\n\n    /// <summary>\n    /// Case represents a state transition of a generic recursive descent parser.\n    /// </summary>\n    /// <typeparam name=\"TPar\">Parser class containing static state variables.</typeparam>\n    /// <typeparam name=\"TNode\">Node class for building parse trees.</typeparam>\n    public readonly struct Case<TPar, TNode>\n        where TPar : TextParser<TPar>\n    {\n        public readonly Func<TPar, TNode, State<TPar, TNode>> MatchedFun;\n        public readonly Func<TPar, TNode, Text, Text> AdjustFun;\n        public readonly string Pattern;\n\n        #region Constructors\n\n        /// <summary>\n        /// A supplied adjustFun can modify the text preceeding the match \n        /// of the case in a searching state, before it is handed to the\n        /// TextAct of the state.\n        /// </summary>\n        public Case(string pattern, Func<TPar, TNode, State<TPar, TNode>> matchedFun,\n            Func<TPar, TNode, Text, Text> adjustFun = null)\n        {\n            MatchedFun = matchedFun;\n            AdjustFun = adjustFun;\n            Pattern = pattern;\n        }\n\n        public Case(Func<TPar, TNode, State<TPar, TNode>> matchedFun,\n            Func<TPar, TNode, Text, Text> adjustFun = null)\n            : this((string)null, matchedFun, adjustFun)\n        { }\n\n        public Case(Regex regex, Func<TPar, TNode, State<TPar, TNode>> matchedFun,\n                    Func<TPar, TNode, Text, Text> adjustFun = null)\n            : this(regex.ToString(), matchedFun, adjustFun)\n        { }\n\n        public Case(Rx rx, Func<TPar, TNode, State<TPar, TNode>> matchedFun,\n            Func<TPar, TNode, Text, Text> adjustFun = null)\n            : this(rx.Pattern, matchedFun, adjustFun)\n        { }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Cases with Parser as Generic Parameter\n\n    /// <summary>\n    /// The Cases class makes it possible to build a single state transition\n    /// table by combining already defined case arrays. This makes it possible\n    /// to avoid re-specifying cases that appear in multiple states.\n    /// </summary>\n    public class Cases<TPar, TNode> : IEnumerable<Case<TPar, TNode>>\n        where TPar : TextParser<TPar>\n    {\n        private readonly List<Case<TPar, TNode>> CaseList;\n\n        public Case<TPar, TNode>[] Array => CaseList.ToArray();\n\n        public Cases() => CaseList = new List<Case<TPar, TNode>>();\n\n        public Cases(Rx[] rxs, Func<TPar, TNode, State<TPar, TNode>> matchedFun)\n            : this()\n        {\n            foreach (var rx in rxs)\n                CaseList.Add(new Case<TPar, TNode>(rx, matchedFun));\n        }\n\n        public void Add(Case<TPar, TNode> singleCase) => CaseList.Add(singleCase);\n\n        public void Add(Case<TPar, TNode>[] caseArray)\n        {\n            foreach (var c in caseArray) CaseList.Add(c);\n        }\n\n        public void Add(Cases<TPar, TNode> cases)\n        {\n            foreach (var c in cases.Array) CaseList.Add(c);\n        }\n\n        public void Add(string pattern, Func<TPar, TNode, State<TPar, TNode>> matchedFun,\n            Func<TPar, TNode, Text, Text> adjustFun = null)\n        {\n            CaseList.Add(new Case<TPar, TNode>(pattern, matchedFun, adjustFun));\n        }\n\n        public void Add(Regex regex, Func<TPar, TNode, State<TPar, TNode>> matchedFun,\n            Func<TPar, TNode, Text, Text> adjustFun = null)\n        {\n            CaseList.Add(new Case<TPar, TNode>(regex.ToString(), matchedFun, adjustFun));\n        }\n\n        public void Add(Rx rx, Func<TPar, TNode, State<TPar, TNode>> matchedFun,\n            Func<TPar, TNode, Text, Text> adjustFun = null)\n        {\n            CaseList.Add(new Case<TPar, TNode>(rx.Pattern, matchedFun, adjustFun));\n        }\n\n        public void Add(Func<TPar, TNode, State<TPar, TNode>> matchedFun,\n            Func<TPar, TNode, Text, Text> adjustFun = null)\n        {\n            CaseList.Add(new Case<TPar, TNode>(matchedFun, adjustFun));\n        }\n\n        public State<TPar, TNode> ToState(Action<TPar, TNode, Text> textAct = null)\n             => new State<TPar, TNode>(this, textAct);\n    \n        #region IEnumerable<Case<TPar,TNode>> Members\n\n        public IEnumerator<Case<TPar, TNode>> GetEnumerator() => CaseList.GetEnumerator();\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => CaseList.GetEnumerator();\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ParserState\n\n    /// <summary>\n    /// State of a generic recursive descent parser.\n    /// </summary>\n    /// <typeparam name=\"TNode\">Node class for building parse trees.</typeparam>\n    public class ParserState<TNode> : IEnumerable<ParserCase<TNode>>\n    {\n        public readonly Action<TextParser, TNode, Text> TextAct;\n        public readonly ParserCase<TNode>[] Cases;\n        public readonly Func<TextParser, ParserState<TNode>, TNode, int> Match;\n\n        #region Constructors\n\n        public ParserState(ParserCases<TNode> cases)\n            : this(cases.Array, null)\n        { }\n\n        public ParserState(ParserCase<TNode>[] cases)\n            : this(cases, null)\n        { }\n\n        public ParserState(ParserCases<TNode> cases, Action<TextParser, TNode, Text> textAct)\n            : this(cases.Array, textAct)\n        { }\n\n        public ParserState(ParserCase<TNode>[] cases, Action<TextParser, TNode, Text> textAct)\n        {\n            Cases = cases;\n            TextAct = textAct;\n\n            var pattern = cases.Map(\n                (c, i) => c.Pattern != null\n                ? \"(?<\" + (i + 1) + \">\" + c.Pattern + \")\"\n                : \"(?<\" + (i + 1) + \">.|\\r)\"\n            ).Join(\"|\");\n\n            var regex = new Regex(pattern, RegexOptions.Singleline\n                | RegexOptions.ExplicitCapture\n                | RegexOptions.Compiled);\n            var caseCount = cases.Length;\n\n            if (textAct != null)\n            {\n                Match = (par, state, node) =>\n                {\n                    var m = regex.Match(par.Text.String, par.Pos, par.Text.End - par.Pos);\n                    if (m.Success)\n                        for (int i = 1; i <= caseCount; i++)\n                            if (m.Groups[i].Success)\n                            {\n                                var c = i - 1;\n                                var index = m.Groups[i].Index;\n                                if (par.Pos < index)\n                                {\n                                    var t = par.PeekToPos(index);\n                                    var adj = state.Cases[c].AdjustFun;\n                                    if (adj != null) t = adj(par, node, t);\n                                    state.TextAct(par, node, t);\n                                    par.SetPosAndCountLines(index);\n                                }\n                                par.LastEnd = index + m.Groups[i].Length;\n                                par.LastCase = c;\n                                return c;\n                            }\n                    if (par.Pos < par.Text.End)\n                    {\n                        state.TextAct(par, node, par.PeekToPos(par.Text.End));\n                        par.SetPosAndCountLines(par.Text.End);\n                    }\n                    return -1;\n                };\n            }\n            else\n            {\n                if (cases[caseCount - 1].Pattern != null)\n                    throw new ArgumentException(\n                        \"either a text action or a default case needs to be specified\");\n\n                Match = (par, state, node) =>\n                {\n                    var m = regex.Match(par.Text.String, par.Pos, par.Text.End - par.Pos);\n                    if (m.Success)\n                        for (int i = 1; i <= caseCount; i++)\n                            if (m.Groups[i].Success)\n                            {\n                                par.LastEnd = m.Groups[i].Index + m.Groups[i].Length;\n                                return par.LastCase = i - 1;\n                            }\n                    return -1;\n                };\n            }\n        }\n\n        #endregion\n\n        public IEnumerable<ParserCase<TNode>> Items { get { foreach (var c in Cases) yield return c; } }\n\n        #region IEnumerable implementation\n\n        public IEnumerator<ParserCase<TNode>> GetEnumerator() => Items.GetEnumerator();\n\n        #endregion\n\n        #region IEnumerable implementation\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => Items.GetEnumerator();\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ParserCase\n\n    /// <summary>\n    /// Case represents a state transition of a generic recursive descent parser.\n    /// </summary>\n    /// <typeparam name=\"TNode\">Node class for building parse trees.</typeparam>\n    public readonly struct ParserCase<TNode>\n    {\n        public readonly Func<TextParser, TNode, ParserState<TNode>> MatchedFun;\n        public readonly Func<TextParser, TNode, Text, Text> AdjustFun;\n        public readonly string Pattern;\n\n        #region Constructors\n\n        /// <summary>\n        /// A supplied adjustFun can modify the text preceeding the match \n        /// of the case in a searching state, before it is handed to the\n        /// TextAct of the state.\n        /// </summary>\n        public ParserCase(string pattern, Func<TextParser, TNode, ParserState<TNode>> matchedFun,\n            Func<TextParser, TNode, Text, Text> adjustFun = null)\n        {\n            MatchedFun = matchedFun;\n            AdjustFun = adjustFun;\n            Pattern = pattern;\n        }\n\n        public ParserCase(Func<TextParser, TNode, ParserState<TNode>> matchedFun,\n            Func<TextParser, TNode, Text, Text> adjustFun = null)\n            : this((string)null, matchedFun, adjustFun)\n        { }\n\n        public ParserCase(Regex regex, Func<TextParser, TNode, ParserState<TNode>> matchedFun,\n            Func<TextParser, TNode, Text, Text> adjustFun = null)\n            : this(regex.ToString(), matchedFun, adjustFun)\n        { }\n\n        public ParserCase(Rx rx, Func<TextParser, TNode, ParserState<TNode>> matchedFun,\n            Func<TextParser, TNode, Text, Text> adjustFun = null)\n            : this(rx.Pattern, matchedFun, adjustFun)\n        { }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region ParserCases\n\n    /// <summary>\n    /// The Cases class makes it possible to build a single state transition\n    /// table by combining already defined case arrays. This makes it possible\n    /// to avoid re-specifying cases that appear in multiple states.\n    /// </summary>\n    public class ParserCases<TNode> : IEnumerable<ParserCase<TNode>>\n    {\n        private readonly List<ParserCase<TNode>> CaseList;\n\n        public ParserCase<TNode>[] Array => CaseList.ToArray(); \n\n        public ParserCases() => CaseList = new List<ParserCase<TNode>>();\n\n        public ParserCases(Rx[] rxs, Func<TextParser, TNode, ParserState<TNode>> matchedFun)\n            : this()\n        {\n            foreach (var rx in rxs)\n                CaseList.Add(new ParserCase<TNode>(rx, matchedFun));\n        }\n\n        public void Add(ParserCase<TNode> singleCase) => CaseList.Add(singleCase);\n\n        public void Add(ParserCase<TNode>[] caseArray)\n        {\n            foreach (var c in caseArray) CaseList.Add(c);\n        }\n\n        public void Add(ParserCases<TNode> cases)\n        {\n            foreach (var c in cases.Array) CaseList.Add(c);\n        }\n\n        public void Add(string pattern, Func<TextParser, TNode, ParserState<TNode>> matchedFun,\n            Func<TextParser, TNode, Text, Text> adjustFun = null)\n        {\n            CaseList.Add(new ParserCase<TNode>(pattern, matchedFun, adjustFun));\n        }\n\n        public void Add(Regex regex, Func<TextParser, TNode, ParserState<TNode>> matchedFun,\n            Func<TextParser, TNode, Text, Text> adjustFun = null)\n        {\n            CaseList.Add(new ParserCase<TNode>(regex.ToString(), matchedFun, adjustFun));\n        }\n\n        public void Add(Rx rx, Func<TextParser, TNode, ParserState<TNode>> matchedFun,\n            Func<TextParser, TNode, Text, Text> adjustFun = null)\n        {\n            CaseList.Add(new ParserCase<TNode>(rx.Pattern, matchedFun, adjustFun));\n        }\n\n        public void Add(Func<TextParser, TNode, ParserState<TNode>> matchedFun,\n            Func<TextParser, TNode, Text, Text> adjustFun = null)\n        {\n            CaseList.Add(new ParserCase<TNode>(matchedFun, adjustFun));\n        }\n\n        public ParserState<TNode> ToState(Action<TextParser, TNode, Text> textAct = null)\n        {\n            return new ParserState<TNode>(this, textAct);\n        }\n        \n        #region IEnumerable<Case<TPar,TNode>> Members\n\n        public IEnumerator<ParserCase<TNode>> GetEnumerator() => CaseList.GetEnumerator();\n\n        #endregion\n\n        #region IEnumerable Members\n\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => CaseList.GetEnumerator();\n\n        #endregion\n    }\n\n    #endregion\n\n    #region TextParser\n\n    /// <summary>\n    /// The recursive descent parser class contains parsing state and serves\n    /// as a base class for specific parser implementations. The specific\n    /// derived parser class needs to be specified as type parameter. It\n    /// should also contain the state transition table as static member\n    /// variables.\n    /// </summary>\n    /// <typeparam name=\"TPar\">A concrete parser class derived from\n    /// this generic parser class.</typeparam>\n    public class TextParser<TPar>\n        where TPar : TextParser<TPar>\n    {\n        public Text Text;\n        public int Pos;\n        public int LastEnd;\n        public int LastCase;\n        public Text.Line Line;\n        public int LastWhiteSpace;\n        protected int m_currentCaseIndex;\n\n        #region Static Parsing Methods\n\n        /// <summary>\n        /// Parse the supplied text into the supplied node, starting the\n        /// parser in the supplied root state. This function is the entry\n        /// call to the parser, it returns when the text has been fully\n        /// parsed, or throws a ParserException.\n        /// </summary>\n        public static TPar Parse<TNode>(\n            Text text,\n            TPar parser, State<TPar, TNode> rootState, TNode rootNode)\n        {\n            parser.Text = text;\n            parser.Pos = text.Start;\n            parser.LastEnd = text.Start;\n            parser.Line = new Text.Line(0, text.Start);\n            parser.LastWhiteSpace = -1;\n            parser.LastCase = -1;\n            parser.m_currentCaseIndex = -1;\n\n            return Parse(parser, rootState, rootNode);\n        }\n\n        /// <summary>\n        /// Parse a part of the input into the supplied node.\n        /// This function can be called to implement recursive descent.\n        /// </summary>\n        public static TPar Parse<TNode>(\n            TPar parser, State<TPar, TNode> state, TNode node)\n        {\n            int end = parser.Text.End;\n            var match = state.Match(parser, state, node);\n            while (parser.Pos < end)\n            {\n                parser.m_currentCaseIndex = match;\n                state = state.Cases[match].MatchedFun(parser, node);\n                if (state == null) break;\n                match = state.Match(parser, state, node);\n            }\n            return parser;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// True if parsing has consumed all input.\n        /// </summary>\n        public bool EndOfText => Pos == Text.End;\n\n        /// <summary>\n        /// Users start counting at 1.\n        /// </summary>\n        public int UserLine => 1 + Line.Index;\n\n        /// <summary>\n        /// Users start counting at 1.\n        /// </summary>\n        public int UserColumn => Pos - Line.Start;\n\n        /// <summary>\n        /// The index of the current case within the state table.\n        /// This is only valid as long as no recursive parse function\n        /// has been called.\n        /// </summary>\n        public int CurrentCaseIndex => m_currentCaseIndex;\n\n        #endregion\n\n        #region Current State Query Methods\n\n        /// <summary>\n        /// The current case within the supplied state table.\n        /// This is only valid as long as no recursive parse function\n        /// has been called.\n        /// </summary>\n        public Case<TPar, TNode> CurrentCase<TNode>(State<TPar, TNode> state) => state.Cases[m_currentCaseIndex];\n\n        /// <summary>\n        /// The current pattern within the supplied state table.\n        /// This is only valid as long as no recursive parse function\n        /// has been called.\n        /// </summary>\n        public string CurrentPattern<TNode>(State<TPar, TNode> state) => state.Cases[m_currentCaseIndex].Pattern;\n\n        #endregion\n\n        #region Skipping Text\n\n        public void SkipToEnd() => Pos = Text.End;\n\n        /// <summary>\n        /// Skip the last pattern that was matched up to its start. This can\n        /// either be the pattern of the case, or the pattern that is left\n        /// by one of the GetToStartOf(...) methods.\n        /// </summary>\n        public void Skip() => Pos = LastEnd;\n\n        /// <summary>\n        /// Skip exactly count characters.\n        /// </summary>\n        public void Skip(int count) => Pos += count;\n\n        public void SkipAndCountLines() => SetPosAndCountLines(LastEnd);\n\n        public void SkipAndCountLines(int count) => SetPosAndCountLines(Pos + count);\n\n        public bool TrySkip(int count)\n        {\n            var pos = Pos + count;\n            if (pos > Text.End) return false;\n            SetPosAndCountLines(pos);\n            return true;\n        }\n\n        public void Skip(char skipCh)\n        {\n            if (!TrySkip(skipCh)) ThrowCouldNotSkip(\"'\" + skipCh + \"'\");\n        }\n\n        public void Skip(string skipStr)\n        {\n            if (!TrySkip(skipStr)) ThrowCouldNotSkip('\"' + skipStr + '\"');\n        }\n\n        public void Skip(Rx skipRx)\n        {\n            if (!TrySkip(skipRx))\n                ThrowCouldNotSkip(\"pattern \\\"\" + skipRx.Pattern + '\"');\n        }\n\n        public bool TrySkip(char skipCh)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            var end = index + 1;\n            if (end >= Text.End) return false;\n            if (Text[index] != skipCh) return false;\n            SetPosAndCountLines(end);\n            return true;\n        }\n\n        public bool TrySkip(string skipStr)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            var end = index + skipStr.Length;\n            if (end > Text.End) return false;\n            for (int i = 0; index < end; index++, i++)\n                if (Text[index] != skipStr[i]) return false;\n            SetPosAndCountLines(index);\n            return true;\n        }\n\n        public bool TrySkip(Rx skipRx)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            var m = skipRx.AnchoredRegex.Match(Text.String, index, Text.End - index);\n            if (!m.Success || m.Groups[2].Success) return false;\n            SetPosAndCountLines(index); LastEnd = index + m.Length;\n            return true;\n        }\n\n        /// <summary>\n        /// Skip as much white space characters as possible. Returns the\n        /// actual number skipped.\n        /// </summary>\n        public int SkipWhiteSpace()\n        {\n            var start = Pos;\n            while (Pos < Text.End)\n            {\n                var c = Text.String[Pos];\n                switch (c)\n                {\n                    case ' ':\n                    case '\\t':\n                    case '\\r': ++Pos; break;\n                    case '\\n':\n                        ++Pos; Line.Index++; Line.Start = Pos; break;\n                    default: return Pos - start;\n                }\n            }\n            return Pos - start;\n        }\n\n        /// <summary>\n        /// Skip at least minimalCount white space characters.\n        /// Throws a ParserException if less white space is available.\n        /// </summary>\n        public void SkipWhiteSpaceAtLeast(int minimalCount)\n        {\n            if (SkipWhiteSpace() < minimalCount)\n                throw new ParserException<TPar>((TPar)this,\n                    \"not enough white space\");\n        }\n\n        public void SkipWhiteSpaceAndCheckProgress()\n        {\n            if (Pos == LastWhiteSpace) // stall detected\n                throw new ParserException<TPar>((TPar)this, \"illegal character\");\n            SkipWhiteSpace(); LastWhiteSpace = Pos;\n        }\n\n        public void SkipToStartOf(char searchChar)\n        {\n            if (!TrySkipToStartOf(searchChar))\n                ThrowCouldNotFind(\"'\" + searchChar + \"'\");\n        }\n\n        public void SkipToStartOf(string searchString)\n        {\n            if (!TrySkipToStartOf(searchString))\n                ThrowCouldNotFind('\"' + searchString + '\"');\n        }\n\n        public void SkipToStartOf(Rx searchRx)\n        {\n            if (!TrySkipToStartOf(searchRx))\n                ThrowCouldNotFind(\"pattern \\\"\" + searchRx.Pattern + '\"');\n        }\n\n        public void SkipToEndOf(char searchChar)\n        {\n            if (!TrySkipToEndOf(searchChar))\n                ThrowCouldNotFind(\"'\" + searchChar + \"'\");\n        }\n\n        public void SkipToEndOf(string searchString)\n        {\n            if (!TrySkipToEndOf(searchString))\n                ThrowCouldNotFind('\"' + searchString + '\"');\n        }\n\n        public void SkipToEndOf(Rx searchRx)\n        {\n            if (!TrySkipToEndOf(searchRx))\n                ThrowCouldNotFind(\"pattern \\\"\" + searchRx.Pattern + '\"');\n        }\n\n        public void SkipToEndOfOrEnd(char searchChar)\n        {\n            if (!TrySkipToEndOf(searchChar)) SkipToEnd();\n        }\n\n        public void SkipToEndOfOrEnd(string searchString)\n        {\n            if (!TrySkipToEndOf(searchString)) SkipToEnd();\n        }\n\n        public void SkipToEndOfOrEnd(Rx searchRx)\n        {\n            if (!TrySkipToEndOf(searchRx)) SkipToEnd();\n        }\n\n        public bool TrySkipToStartOf(char searchChar)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            index = Text.String.IndexOf(searchChar, index, Text.End - index);\n            if (index < 0) return false;\n            SetPosAndCountLines(index); LastEnd = index + 1;\n            return true;\n        }\n\n        public bool TrySkipToStartOf(string searchString)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            index = Text.String.IndexOf(searchString, index, Text.End - index);\n            if (index < 0) return false;\n            SetPosAndCountLines(index); LastEnd = index + searchString.Length;\n            return true;\n        }\n\n        public bool TrySkipToStartOf(Rx searchRx)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            var m = searchRx.Regex.Match(Text.String, index, Text.End - index);\n            if (!m.Success) return false;\n            index = m.Index;\n            SetPosAndCountLines(index); LastEnd = index + m.Length;\n            return true;\n        }\n\n        public bool TrySkipToEndOf(char searchChar)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            index = Text.String.IndexOf(searchChar, index, Text.End - index);\n            if (index < 0) return false;\n            SetPosAndCountLines(++index);\n            return true;\n        }\n\n        public bool TrySkipToEndOf(string searchString)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            index = Text.String.IndexOf(searchString, index, Text.End - index);\n            if (index < 0) return false;\n            index += searchString.Length;\n            SetPosAndCountLines(index);\n            return true;\n        }\n\n        public bool TrySkipToEndOf(Rx searchRx)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            var m = searchRx.Regex.Match(Text.String, index, Text.End - index);\n            if (!m.Success) return false;\n            index = m.Index + m.Length;\n            SetPosAndCountLines(index);\n            return true;\n        }\n\n        #endregion\n\n        #region Getting Text\n\n        /// <summary>\n        /// Get one character of input.\n        /// </summary>\n        public char GetChar()\n        {\n            if (Pos >= Text.End)\n                throw new ParserException<TPar>((TPar)this, \"end of text\");\n            return Text.String[Pos++];\n        }\n\n        public bool TryGet(char ch)\n        {\n            if (Pos >= Text.End) return false;\n            if (Text.String[Pos] != ch) return false;\n            ++Pos;\n            return true;\n        }\n\n        public bool TryGet(string str)\n        {\n            var len = str.Length;\n            if (Pos + len > Text.End) return false;\n            for (int i = 0, p = Pos; i < len; i++, p++)\n                if (str[i] != Text.String[p]) return false;\n            Pos += len;\n            return true;\n        }\n\n        /// <summary>\n        /// Get the text up to the end of the last pattern that was matched\n        /// up to its start. This can either be the pattern of the case,\n        /// the pattern that is left by one of the GetToStartOf(...), or\n        /// the pattern that was left by one of the SkipToStartOf(...)\n        /// methods.\n        /// </summary>\n        public Text Get()\n        {\n            var text = new Text(Pos, LastEnd, Text.String);\n            Pos = LastEnd;\n            return text;\n        }\n\n        /// <summary>\n        /// Get the text from the supplied start up to the current parsing\n        /// position. This can be used, if a number of patterns have been\n        /// skipped before and need to be combined into a single text.\n        /// </summary>\n        public Text GetFrom(int start)\n        {\n            var text = new Text(start, Pos, Text.String);\n            return text;\n        }\n\n        /// <summary>\n        /// Get text that matches the supplied regular expression (it must\n        /// start at the current position). If the text does not match, an\n        /// exception is thrown.\n        /// </summary>\n        public Text Get(Rx rx)\n        {\n            return Get(rx, p => p.ThrowCouldNotFind(\n                                    \"pattern \\\"\" + rx.Pattern + '\"'));\n        }\n\n        /// <summary>\n        /// Get text that matches the supplied regular expression (it must\n        /// start at the current position). If the text does not match, the\n        /// supplied function is executed and its result is returned.\n        /// </summary>\n        public Text Get(Rx rx, Func<TPar, Text> notMatchedFun)\n        {\n            var m = rx.AnchoredRegex.Match(Text.String, Pos);\n            if (!m.Success || m.Groups[2].Success) return notMatchedFun((TPar)this);\n            Pos += m.Length;\n            return new Text(Text.String, m.Index, m.Length);\n        }\n\n        /// <summary>\n        /// Get text [pos, pos + offset) if offset is greater than 0, and\n        /// text [pos, end + offset) if offset is lower or equal to 0.\n        /// </summary>\n        public Text GetTo(int offset) => GetToPos(offset <= 0\n            ? Math.Max(Pos, Text.End + offset)\n            : Math.Min(Pos + offset, Text.End));\n\n        public Text GetToPos(int pos)\n        {\n            var text = new Text(Pos, pos, Text.String);\n            SetPosAndCountLines(pos);\n            return text;\n        }\n\n        public Text GetToEnd() => GetToPos(Text.End);\n\n        public List<Text> GetList(Rx item, Rx sep)\n        {\n            var idx = Math.Max(Pos, LastEnd);\n            var list = new List<Text>();\n            var m = item.AnchoredRegex.Match(Text.String, idx);\n            if (!m.Success || m.Groups[2].Success\n                || idx + m.Length > Text.End)\n                throw new ParserException<TPar>((TPar)this, idx,\n                    \"could not get list item with pattern \\\"\"\n                    + item.Pattern + '\"');\n            list.Add(new Text(Text.String, m.Index, m.Length));\n            idx += m.Length;\n            while ((m = sep.AnchoredRegex.Match(Text.String, idx)).Success\n                   && m.Groups[1].Success && idx + m.Length < Text.End)\n            {\n                idx += m.Length;\n                m = item.Regex.Match(Text.String, idx);\n                if (!m.Success || m.Groups[2].Success\n                    || idx + m.Length > Text.End)\n                    throw new ParserException<TPar>((TPar)this, idx,\n                        \"could not get list item with pattern \\\"\"\n                        + item.Pattern + '\"');\n                list.Add(new Text(Text.String, m.Index, m.Length));\n                idx = m.Index + m.Length;\n            }\n            SetPosAndCountLines(idx);\n            return list;\n        }\n\n        public Text GetToStartOf(char searchChar) => GetToStartOf(\n            searchChar, p => p.ThrowCouldNotFind(\"'\" + searchChar + \"'\")\n            );\n\n        public Text GetToStartOf(char searchChar, Func<TPar, Text> notFoundAction)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            index = Text.String.IndexOf(searchChar, index, Text.End - index);\n            if (index < 0) return notFoundAction((TPar)this);\n            var text = new Text(Pos, index, Text.String);\n            SetPosAndCountLines(index); LastEnd = index + 1;\n            return text;\n        }\n\n        public Text GetToStartOf(string searchString) => GetToStartOf(\n            searchString, p => p.ThrowCouldNotFind('\"' + searchString + '\"')\n            );\n\n        public Text GetToStartOf(string searchString, Func<TPar, Text> notFoundAction)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            index = Text.String.IndexOf(searchString, index, Text.End - index);\n            if (index < 0) return notFoundAction((TPar)this);\n            var text = new Text(Pos, index, Text.String);\n            SetPosAndCountLines(index); LastEnd = index + searchString.Length;\n            return text;\n        }\n\n        public Text GetToStartOf(Rx searchRx) => GetToStartOf(\n            searchRx, p => p.ThrowCouldNotFind(\"pattern \\\"\" + searchRx.Pattern + '\"')\n            );\n\n        public Text GetToStartOf(Rx searchRx, Func<TPar, Text> notFoundAction)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            var m = searchRx.Regex.Match(Text.String, index, Text.End - index);\n            if (!m.Success) return notFoundAction((TPar)this);\n            index = m.Index;\n            var text = new Text(Pos, index, Text.String);\n            SetPosAndCountLines(index); LastEnd = index + m.Length;\n            return text;\n        }\n\n        public Text GetToEndOf(char searchChar) => GetToEndOf(\n            searchChar, p => p.ThrowCouldNotFind(\"'\" + searchChar + \"'\")\n            );\n\n        public Text GetToEndOf(char searchChar, Func<TPar, Text> notFoundFun)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            index = Text.String.IndexOf(searchChar, index, Text.End - index);\n            if (index < 0) return notFoundFun((TPar)this);\n            index++;\n            var text = new Text(Pos, index, Text.String);\n            SetPosAndCountLines(index);\n            return text;\n        }\n\n        public Text GetToEndOf(string searchString) => GetToEndOf(\n            searchString, p => p.ThrowCouldNotFind('\"' + searchString + '\"')\n            );\n\n        public Text GetToEndOf(string searchString, Func<TPar, Text> notFoundFun)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            index = Text.String.IndexOf(searchString, index, Text.End - index);\n            if (index < 0) return notFoundFun((TPar)this);\n            index += searchString.Length;\n            var text = new Text(Pos, index, Text.String);\n            SetPosAndCountLines(index);\n            return text;\n        }\n\n        public Text GetToEndOf(Rx searchRx) => GetToEndOf(\n            searchRx, p => p.ThrowCouldNotFind(\"pattern \\\"\" + searchRx.Pattern + '\"')\n            );\n\n        public Text GetToEndOf(Rx searchRx, Func<TPar, Text> notFoundFun)\n        {\n            var index = Math.Max(Pos, LastEnd);\n            var m = searchRx.Regex.Match(Text.String, index, Text.End - index);\n            if (!m.Success) return notFoundFun((TPar)this);\n            index = m.Index + m.Length;\n            var text = new Text(Pos, index, Text.String);\n            SetPosAndCountLines(index);\n            return text;\n        }\n\n        public Text GetToStartOfOrEnd(char searchChar) => GetToStartOf(searchChar, p => p.GetToPos(Text.End));\n\n        public Text GetToStartOfOrEnd(string searchString) => GetToStartOf(searchString, p => p.GetToPos(Text.End));\n\n        public Text GetToStartOfOrEnd(Rx searchRx) => GetToStartOf(searchRx, p => p.GetToPos(Text.End));\n\n        public Text GetToEndOfOrEnd(char searchChar) => GetToEndOf(searchChar, p => p.GetToPos(Text.End));\n\n        public Text GetToEndOfOrEnd(string searchString) => GetToEndOf(searchString, p => p.GetToPos(Text.End));\n\n        public Text GetToEndOfOrEnd(Rx searchRx) => GetToEndOf(searchRx, p => p.GetToPos(Text.End));\n\n        public Text GetToWhiteSpace()\n        {\n            var start = Pos;\n            while (Pos < Text.End && !IsWhiteSpace(Text.String[Pos]))\n                Pos++;\n            return new Text(start, Pos, Text.String);\n\n            bool IsWhiteSpace(char ch) => ch == ' ' || ch == '\\t' || ch == '\\r' || ch == '\\n';\n        }\n\n        public bool TryGetByte(ref ParsedValue<byte> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfByteAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetSByte(ref ParsedValue<sbyte> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfSByteAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetShort(ref ParsedValue<short> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfShortAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetUShort(ref ParsedValue<ushort> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfUShortAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetInt(ref ParsedValue<int> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfIntAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetUInt(ref ParsedValue<uint> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfUIntAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetLong(ref ParsedValue<long> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfLongAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetULong(ref ParsedValue<ulong> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfULongAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetFloat(ref ParsedValue<float> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfFloatAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetDouble(ref ParsedValue<double> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfDoubleAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        public bool TryGetDecimal(ref ParsedValue<decimal> parsedValue)\n        {\n            parsedValue = Text.ParsedValueOfDecimalAt(Pos - Text.Start);\n            if (parsedValue.Error != ParseError.None) return false;\n            Pos += parsedValue.Length;\n            return true;\n        }\n\n        #endregion\n\n        #region Peeking\n\n        public char Peek => Text.String[Pos];\n\n        public Text PeekGet() => new Text(Pos, LastEnd, Text.String);\n\n        public Text PeekFromStart => PeekFromPos(Text.Start);\n\n        public Text PeekLastLine => PeekFromPos(Line.Start);\n\n        public Text PeekToEnd => PeekToPos(Text.End);\n\n        /// <summary>\n        /// Returns the text [pos + offset, pos) if offset is lower than 0,\n        /// and the text [start + offset, pos) if offset is greater or equal\n        /// to 0.\n        /// </summary>\n        public Text PeekFrom(int offset) => PeekFromPos(offset < 0\n                                ? Math.Max(Text.Start, Pos + offset)\n                                : Math.Min(Text.Start + offset, Pos));\n\n        /// <summary>\n        /// Returns the text [pos, pos + offset) if offset is greater than 0,\n        /// and the text [pos, end + offset) if offset is lower or equal to 0.\n        /// </summary>\n        public Text PeekTo(int offset) => PeekToPos(offset <= 0\n                                ? Math.Max(Pos, Text.End + offset)\n                                : Math.Min(Pos + offset, Text.End));\n\n        public Text PeekFromPos(int pos) => new Text(pos, Pos, Text.String);\n\n        public Text PeekToPos(int pos) => new Text(Pos, pos, Text.String);\n\n        #endregion\n\n        #region Mostly Internal Methods\n\n        public void SetPosAndCountLines(int pos)\n        {\n            int i = Pos;\n            while (i < pos)\n            {\n                if (Text.String[i] == '\\n')\n                { ++i; Line.Index++; Line.Start = i; }\n                else\n                    ++i;\n            }\n            Pos = pos;\n        }\n\n        #endregion\n\n        #region Throwing Exceptions\n\n        public void ThrowEndOfText()\n             => throw new ParserException<TPar>((TPar)this, \"end of text\");\n\n        public void ThrowOutOfRange(string typeName)\n             => throw new ParserException<TPar>((TPar)this, \"value out of \" + typeName + \" range\");\n\n        public Text ThrowCouldNotFind(string str)\n            => throw new ParserException<TPar>((TPar)this, \"could not find \" + str);\n\n        public Text ThrowCouldNotSkip(string str)\n             => throw new ParserException<TPar>((TPar)this, \"could not skip \" + str);\n\n        #endregion\n    }\n    \n    public class TextParser : TextParser<TextParser>\n    {\n\n        public void Parse<TNode>(Text text, ParserState<TNode> rootState, TNode rootNode)\n        {\n            Text = text;\n            Pos = text.Start;\n            LastEnd = text.Start;\n            Line = new Text.Line(0, text.Start);\n            LastWhiteSpace = -1;\n            LastCase = -1;\n            m_currentCaseIndex = -1;\n\n            Parse(rootState, rootNode);\n        }\n\n        /// <summary>\n        /// Parse a part of the input into the supplied node.\n        /// This function can be called to implement recursive descent.\n        /// </summary>\n        public void Parse<TNode>(ParserState<TNode> state, TNode node)\n        {\n            int end = Text.End;\n            var match = state.Match(this, state, node);\n            while (Pos < end)\n            {\n                m_currentCaseIndex = match;\n                state = state.Cases[match].MatchedFun(this, node);\n                if (state == null) break;\n                match = state.Match(this, state, node);\n            }\n        }\n\n    }\n\n    #endregion\n\n    #region ParserException\n\n    /// <summary>\n    /// The generic recursive descent parser throws this type of exception.\n    /// </summary>\n    public class ParserException<TPar> : ApplicationException\n        where TPar : TextParser<TPar>\n    {\n        public readonly TPar Parser;\n\n        #region Constructors\n\n        public ParserException(TPar parser, string message)\n            : base(message)\n        {\n            Parser = parser;\n        }\n\n        public ParserException(TPar parser, int pos, string message)\n            : base(message)\n        {\n            parser.SetPosAndCountLines(pos);\n            Parser = parser;\n        }\n\n        public ParserException(TPar parser, string message, Exception inner)\n            : base(message, inner)\n        {\n            Parser = parser;\n        }\n\n        #endregion\n    }\n\n    public class ParserException : ParserException<TextParser>\n    {\n        #region Constructors\n\n        public ParserException(TextParser parser, string message)\n            : base(parser, message)\n        { }\n\n        public ParserException(TextParser parser, int pos, string message)\n            : base(parser, pos, message)\n        { }\n\n        public ParserException(TextParser parser, string message, Exception inner)\n            : base(parser, message, inner)\n        { }\n\n        #endregion\n    }\n    \n    #endregion\n\n    #region VerbatimString TextParser Extension\n\n    public static class VerbatimStringTextParserExtension\n    {\n        public static string GetVerbatimString(this TextParser parser, bool alreadyInside = false)\n        {\n            var sb = new StringBuilder();\n            parser.Parse(alreadyInside ? s_stringState : s_quoteState, sb);\n            return sb.ToString();\n        }\n\n        private static readonly ParserState<StringBuilder> s_quoteState = new ParserCases<StringBuilder> {\n            { \"@\\\"\",    (p, b) => { p.Skip(); return s_stringState; } },\n            { /* def. */(p, b) => { throw new ParserException(p, \"no @\\\" at start of verbatim string\"); } }\n        }.ToState();\n\n        private static readonly ParserState<StringBuilder> s_stringState = new ParserCases<StringBuilder> {\n            { \"\\\"\\\"\",   (p, b) => { p.Skip(); b.Append('\"'); return s_stringState; } }, // escape\n            { \"\\\"\",     (p, b) => { p.Skip(); return null; } }, // string end\n        }.ToState((p, b, t) => { b.Append(t.String, t.Start, t.Count); }); // process\n\n    }\n\n    #endregion\n\n    #region CSharpString TextParser Extension\n\n    internal readonly struct Esc\n    {\n        public readonly string Pattern;\n        public readonly Func<string, char> EscFun;\n        public Esc(string pattern, Func<string, char> escFun) { Pattern = pattern; EscFun = escFun; }\n    }\n\n    internal static class EscDictExtension\n    {\n        public static void Add(this Dictionary<char, Esc> escMap, char escStart, string pattern, Func<string, char> escFun)\n        {\n            escMap.Add(escStart, new Esc(pattern, escFun));\n        }\n    }\n\n    public static class CSharpStringTextParserExtension\n    {\n        public static string GetCSharpString(this TextParser parser, bool alreadyInside = false)\n        {\n            var sb = new StringBuilder();\n            parser.Parse(alreadyInside ? s_strState : s_quoteState, sb);\n            return sb.ToString();\n        }\n\n        private static readonly ParserState<StringBuilder> s_quoteState = new ParserCases<StringBuilder> {\n            { \"\\\"\", (p, b) => { p.Skip(); return s_strState; } },\n            {       (p, b) => { throw new ParserException(p, \"no \\\" at start of string\"); } }\n        }.ToState();\n\n        private static readonly ParserState<StringBuilder> s_strState = new ParserCases<StringBuilder> {\n            { \"\\\"\",         (p, b) => { p.Skip(); return null; } }, // search string end\n            { @\"\\\\\",        (p, b) => { p.Skip(); return s_escState; } }, // search escape\n            { @\"\\n|\\r\",     (p, b) => { throw new ParserException(p, \"newline in string\"); } }\n        }.ToState((p, b, t) => { b.Append(t.String, t.Start, t.Count); }); // process text inbetween\n\n        private const int c_a = (int)'a', c_A = (int)'A', c_0 = (int)'0';\n        private static readonly Esc s_octalEsc = new Esc(\n            \"[0-3][0-7][0-7]\",\n            str => (char)(((((int)str[0]) - c_0) * 8 + (((int)str[1]) - c_0)) * 8 + (((int)str[2]) - c_0))\n        );\n        private static int HexOfOrd(int ord)\n                => ord >= c_a ? 10 + ord - c_a : ord >= c_A ? ord - c_A : ord - c_0;\n        private static char HexOfEscString(string str)\n                => (char)(HexOfOrd((int)str[1]) * 16 + HexOfOrd((int)str[2]));\n\n        // Decide what to do, based on the first character of the escape sequence.\n        private static readonly Dictionary<char, Esc> s_escMap = new Dictionary<char, Esc> {\n            { 'a', \"a\", str => '\\a' },  { 'b', \"b\", str => '\\b' },  { 'f', \"f\", str => '\\f' },\n            { 'n', \"n\", str => '\\n' },  { 'r', \"r\", str => '\\r' },  { 't', \"t\", str => '\\t' },\n            { 'v', \"v\", str => '\\v' },\n            { '\\'', \"\\'\", str => '\\'' }, { '\\\"', \"\\\"\", str => '\\\"' }, { '\\\\', @\"\\\\\", str => '\\\\' },\n            { '0', s_octalEsc }, { '1', s_octalEsc }, { '2', s_octalEsc }, { '3', s_octalEsc },\n            { 'x', \"x[0-9a-fA-F][0-9a-fA-F]\", HexOfEscString },\n        };\n\n        private static readonly string s_escapes\n                = String.Join(\"|\", s_escMap.Values.Select(e => e.Pattern).Distinct());\n\n        private static readonly ParserState<StringBuilder> s_escState = new ParserCases<StringBuilder> {\n            { s_escapes, (p, b) => { var esc = p.Get().ToString();\n                                     b.Append(s_escMap[esc[0]].EscFun(esc)); return s_strState; }},\n            { /* def. */ (p, b) => { throw new ParserException(p, \"invalid escape sequence in string\"); }}\n        }.ToState();\n\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Tup/Tuples_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Simple Tuples of uniform type\n\n    #region Tup2\n\n    public struct Tup2<T>\n    {\n        public T E0, E1;\n\n        #region Constructors\n\n        public Tup2(T e) { E0 = e; E1 = e; }\n        public Tup2(T e0, T e1) { E0 = e0; E1 = e1; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup3\n\n    public struct Tup3<T>\n    {\n        public T E0, E1, E2;\n\n        #region Constructors\n\n        public Tup3(T e) { E0 = e; E1 = e; E2 = e; }\n        public Tup3(T e0, T e1, T e2) { E0 = e0; E1 = e1; E2 = e2; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup4\n\n    public struct Tup4<T>\n    {\n        public T E0, E1, E2, E3;\n\n        #region Constructors\n\n        public Tup4(T e) { E0 = e; E1 = e; E2 = e; E3 = e; }\n        public Tup4(T e0, T e1, T e2, T e3) { E0 = e0; E1 = e1; E2 = e2; E3 = e3; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup5\n\n    public struct Tup5<T>\n    {\n        public T E0, E1, E2, E3, E4;\n\n        #region Constructors\n\n        public Tup5(T e) { E0 = e; E1 = e; E2 = e; E3 = e; E4 = e; }\n        public Tup5(T e0, T e1, T e2, T e3, T e4) { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup6\n\n    public struct Tup6<T>\n    {\n        public T E0, E1, E2, E3, E4, E5;\n\n        #region Constructors\n\n        public Tup6(T e) { E0 = e; E1 = e; E2 = e; E3 = e; E4 = e; E5 = e; }\n        public Tup6(T e0, T e1, T e2, T e3, T e4, T e5) { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup7\n\n    public struct Tup7<T>\n    {\n        public T E0, E1, E2, E3, E4, E5, E6;\n\n        #region Constructors\n\n        public Tup7(T e) { E0 = e; E1 = e; E2 = e; E3 = e; E4 = e; E5 = e; E6 = e; }\n        public Tup7(T e0, T e1, T e2, T e3, T e4, T e5, T e6) { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; E6 = e6; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup8\n\n    public struct Tup8<T>\n    {\n        public T E0, E1, E2, E3, E4, E5, E6, E7;\n\n        #region Constructors\n\n        public Tup8(T e) { E0 = e; E1 = e; E2 = e; E3 = e; E4 = e; E5 = e; E6 = e; E7 = e; }\n        public Tup8(T e0, T e1, T e2, T e3, T e4, T e5, T e6, T e7) { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; E6 = e6; E7 = e7; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup9\n\n    public struct Tup9<T>\n    {\n        public T E0, E1, E2, E3, E4, E5, E6, E7, E8;\n\n        #region Constructors\n\n        public Tup9(T e) { E0 = e; E1 = e; E2 = e; E3 = e; E4 = e; E5 = e; E6 = e; E7 = e; E8 = e; }\n        public Tup9(T e0, T e1, T e2, T e3, T e4, T e5, T e6, T e7, T e8) { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; E6 = e6; E7 = e7; E8 = e8; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup10\n\n    public struct Tup10<T>\n    {\n        public T E00, E01, E02, E03, E04, E05, E06, E07, E08, E09;\n\n        #region Constructors\n\n        public Tup10(T e) { E00 = e; E01 = e; E02 = e; E03 = e; E04 = e; E05 = e; E06 = e; E07 = e; E08 = e; E09 = e; }\n        public Tup10(T e00, T e01, T e02, T e03, T e04, T e05, T e06, T e07, T e08, T e09) { E00 = e00; E01 = e01; E02 = e02; E03 = e03; E04 = e04; E05 = e05; E06 = e06; E07 = e07; E08 = e08; E09 = e09; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup11\n\n    public struct Tup11<T>\n    {\n        public T E00, E01, E02, E03, E04, E05, E06, E07, E08, E09, E10;\n\n        #region Constructors\n\n        public Tup11(T e) { E00 = e; E01 = e; E02 = e; E03 = e; E04 = e; E05 = e; E06 = e; E07 = e; E08 = e; E09 = e; E10 = e; }\n        public Tup11(T e00, T e01, T e02, T e03, T e04, T e05, T e06, T e07, T e08, T e09, T e10) { E00 = e00; E01 = e01; E02 = e02; E03 = e03; E04 = e04; E05 = e05; E06 = e06; E07 = e07; E08 = e08; E09 = e09; E10 = e10; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup12\n\n    public struct Tup12<T>\n    {\n        public T E00, E01, E02, E03, E04, E05, E06, E07, E08, E09, E10, E11;\n\n        #region Constructors\n\n        public Tup12(T e) { E00 = e; E01 = e; E02 = e; E03 = e; E04 = e; E05 = e; E06 = e; E07 = e; E08 = e; E09 = e; E10 = e; E11 = e; }\n        public Tup12(T e00, T e01, T e02, T e03, T e04, T e05, T e06, T e07, T e08, T e09, T e10, T e11) { E00 = e00; E01 = e01; E02 = e02; E03 = e03; E04 = e04; E05 = e05; E06 = e06; E07 = e07; E08 = e08; E09 = e09; E10 = e10; E11 = e11; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup13\n\n    public struct Tup13<T>\n    {\n        public T E00, E01, E02, E03, E04, E05, E06, E07, E08, E09, E10, E11, E12;\n\n        #region Constructors\n\n        public Tup13(T e) { E00 = e; E01 = e; E02 = e; E03 = e; E04 = e; E05 = e; E06 = e; E07 = e; E08 = e; E09 = e; E10 = e; E11 = e; E12 = e; }\n        public Tup13(T e00, T e01, T e02, T e03, T e04, T e05, T e06, T e07, T e08, T e09, T e10, T e11, T e12) { E00 = e00; E01 = e01; E02 = e02; E03 = e03; E04 = e04; E05 = e05; E06 = e06; E07 = e07; E08 = e08; E09 = e09; E10 = e10; E11 = e11; E12 = e12; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup14\n\n    public struct Tup14<T>\n    {\n        public T E00, E01, E02, E03, E04, E05, E06, E07, E08, E09, E10, E11, E12, E13;\n\n        #region Constructors\n\n        public Tup14(T e) { E00 = e; E01 = e; E02 = e; E03 = e; E04 = e; E05 = e; E06 = e; E07 = e; E08 = e; E09 = e; E10 = e; E11 = e; E12 = e; E13 = e; }\n        public Tup14(T e00, T e01, T e02, T e03, T e04, T e05, T e06, T e07, T e08, T e09, T e10, T e11, T e12, T e13) { E00 = e00; E01 = e01; E02 = e02; E03 = e03; E04 = e04; E05 = e05; E06 = e06; E07 = e07; E08 = e08; E09 = e09; E10 = e10; E11 = e11; E12 = e12; E13 = e13; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup15\n\n    public struct Tup15<T>\n    {\n        public T E00, E01, E02, E03, E04, E05, E06, E07, E08, E09, E10, E11, E12, E13, E14;\n\n        #region Constructors\n\n        public Tup15(T e) { E00 = e; E01 = e; E02 = e; E03 = e; E04 = e; E05 = e; E06 = e; E07 = e; E08 = e; E09 = e; E10 = e; E11 = e; E12 = e; E13 = e; E14 = e; }\n        public Tup15(T e00, T e01, T e02, T e03, T e04, T e05, T e06, T e07, T e08, T e09, T e10, T e11, T e12, T e13, T e14) { E00 = e00; E01 = e01; E02 = e02; E03 = e03; E04 = e04; E05 = e05; E06 = e06; E07 = e07; E08 = e08; E09 = e09; E10 = e10; E11 = e11; E12 = e12; E13 = e13; E14 = e14; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tup16\n\n    public struct Tup16<T>\n    {\n        public T E00, E01, E02, E03, E04, E05, E06, E07, E08, E09, E10, E11, E12, E13, E14, E15;\n\n        #region Constructors\n\n        public Tup16(T e) { E00 = e; E01 = e; E02 = e; E03 = e; E04 = e; E05 = e; E06 = e; E07 = e; E08 = e; E09 = e; E10 = e; E11 = e; E12 = e; E13 = e; E14 = e; E15 = e; }\n        public Tup16(T e00, T e01, T e02, T e03, T e04, T e05, T e06, T e07, T e08, T e09, T e10, T e11, T e12, T e13, T e14, T e15) { E00 = e00; E01 = e01; E02 = e02; E03 = e03; E04 = e04; E05 = e05; E06 = e06; E07 = e07; E08 = e08; E09 = e09; E10 = e10; E11 = e11; E12 = e12; E13 = e13; E14 = e14; E15 = e15; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #endregion\n\n    #region Tuple of 2 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1.\n    /// </summary>\n    public struct Tup<T0, T1>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        public Tup(T0 e0, T1 e1)\n        { E0 = e0; E1 = e1; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1})\", E0, E1);\n        }\n    }\n\n    #endregion\n\n    #region Tuple of 3 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1, E2.\n    /// </summary>\n    public struct Tup<T0, T1, T2>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        /// <summary>\n        /// Element 2 of the tuple.\n        /// </summary>\n        public T2 E2;\n\n        public Tup(T0 e0, T1 e1, T2 e2)\n        { E0 = e0; E1 = e1; E2 = e2; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1}, {2})\", E0, E1, E2);\n        }\n    }\n\n    #endregion\n\n    #region Tuple of 4 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1, E2, E3.\n    /// </summary>\n    public struct Tup<T0, T1, T2, T3>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        /// <summary>\n        /// Element 2 of the tuple.\n        /// </summary>\n        public T2 E2;\n\n        /// <summary>\n        /// Element 3 of the tuple.\n        /// </summary>\n        public T3 E3;\n\n        public Tup(T0 e0, T1 e1, T2 e2, T3 e3)\n        { E0 = e0; E1 = e1; E2 = e2; E3 = e3; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1}, {2}, {3})\", E0, E1, E2, E3);\n        }\n    }\n\n    #endregion\n\n    #region Tuple of 5 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1, E2, E3, E4.\n    /// </summary>\n    public struct Tup<T0, T1, T2, T3, T4>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        /// <summary>\n        /// Element 2 of the tuple.\n        /// </summary>\n        public T2 E2;\n\n        /// <summary>\n        /// Element 3 of the tuple.\n        /// </summary>\n        public T3 E3;\n\n        /// <summary>\n        /// Element 4 of the tuple.\n        /// </summary>\n        public T4 E4;\n\n        public Tup(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n        { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1}, {2}, {3}, {4})\", E0, E1, E2, E3, E4);\n        }\n    }\n\n    #endregion\n\n    #region Tuple of 6 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1, E2, E3, E4, E5.\n    /// </summary>\n    public struct Tup<T0, T1, T2, T3, T4, T5>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        /// <summary>\n        /// Element 2 of the tuple.\n        /// </summary>\n        public T2 E2;\n\n        /// <summary>\n        /// Element 3 of the tuple.\n        /// </summary>\n        public T3 E3;\n\n        /// <summary>\n        /// Element 4 of the tuple.\n        /// </summary>\n        public T4 E4;\n\n        /// <summary>\n        /// Element 5 of the tuple.\n        /// </summary>\n        public T5 E5;\n\n        public Tup(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5)\n        { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1}, {2}, {3}, {4}, {5})\", E0, E1, E2, E3, E4, E5);\n        }\n    }\n\n    #endregion\n\n    #region Tuple of 7 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1, E2, E3, E4, E5, E6.\n    /// </summary>\n    public struct Tup<T0, T1, T2, T3, T4, T5, T6>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        /// <summary>\n        /// Element 2 of the tuple.\n        /// </summary>\n        public T2 E2;\n\n        /// <summary>\n        /// Element 3 of the tuple.\n        /// </summary>\n        public T3 E3;\n\n        /// <summary>\n        /// Element 4 of the tuple.\n        /// </summary>\n        public T4 E4;\n\n        /// <summary>\n        /// Element 5 of the tuple.\n        /// </summary>\n        public T5 E5;\n\n        /// <summary>\n        /// Element 6 of the tuple.\n        /// </summary>\n        public T6 E6;\n\n        public Tup(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6)\n        { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; E6 = e6; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1}, {2}, {3}, {4}, {5}, {6})\", E0, E1, E2, E3, E4, E5, E6);\n        }\n    }\n\n    #endregion\n\n    #region Tuple of 8 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1, E2, E3, E4, E5, E6, E7.\n    /// </summary>\n    public struct Tup<T0, T1, T2, T3, T4, T5, T6, T7>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        /// <summary>\n        /// Element 2 of the tuple.\n        /// </summary>\n        public T2 E2;\n\n        /// <summary>\n        /// Element 3 of the tuple.\n        /// </summary>\n        public T3 E3;\n\n        /// <summary>\n        /// Element 4 of the tuple.\n        /// </summary>\n        public T4 E4;\n\n        /// <summary>\n        /// Element 5 of the tuple.\n        /// </summary>\n        public T5 E5;\n\n        /// <summary>\n        /// Element 6 of the tuple.\n        /// </summary>\n        public T6 E6;\n\n        /// <summary>\n        /// Element 7 of the tuple.\n        /// </summary>\n        public T7 E7;\n\n        public Tup(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7)\n        { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; E6 = e6; E7 = e7; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7})\", E0, E1, E2, E3, E4, E5, E6, E7);\n        }\n    }\n\n    #endregion\n\n    #region Tuple of 9 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1, E2, E3, E4, E5, E6, E7, E8.\n    /// </summary>\n    public struct Tup<T0, T1, T2, T3, T4, T5, T6, T7, T8>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        /// <summary>\n        /// Element 2 of the tuple.\n        /// </summary>\n        public T2 E2;\n\n        /// <summary>\n        /// Element 3 of the tuple.\n        /// </summary>\n        public T3 E3;\n\n        /// <summary>\n        /// Element 4 of the tuple.\n        /// </summary>\n        public T4 E4;\n\n        /// <summary>\n        /// Element 5 of the tuple.\n        /// </summary>\n        public T5 E5;\n\n        /// <summary>\n        /// Element 6 of the tuple.\n        /// </summary>\n        public T6 E6;\n\n        /// <summary>\n        /// Element 7 of the tuple.\n        /// </summary>\n        public T7 E7;\n\n        /// <summary>\n        /// Element 8 of the tuple.\n        /// </summary>\n        public T8 E8;\n\n        public Tup(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8)\n        { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; E6 = e6; E7 = e7; E8 = e8; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8})\", E0, E1, E2, E3, E4, E5, E6, E7, E8);\n        }\n    }\n\n    #endregion\n\n    #region Tuple of 10 Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields E0, E1, E2, E3, E4, E5, E6, E7, E8, E9.\n    /// </summary>\n    public struct Tup<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>\n    {\n        /// <summary>\n        /// Element 0 of the tuple.\n        /// </summary>\n        public T0 E0;\n\n        /// <summary>\n        /// Element 1 of the tuple.\n        /// </summary>\n        public T1 E1;\n\n        /// <summary>\n        /// Element 2 of the tuple.\n        /// </summary>\n        public T2 E2;\n\n        /// <summary>\n        /// Element 3 of the tuple.\n        /// </summary>\n        public T3 E3;\n\n        /// <summary>\n        /// Element 4 of the tuple.\n        /// </summary>\n        public T4 E4;\n\n        /// <summary>\n        /// Element 5 of the tuple.\n        /// </summary>\n        public T5 E5;\n\n        /// <summary>\n        /// Element 6 of the tuple.\n        /// </summary>\n        public T6 E6;\n\n        /// <summary>\n        /// Element 7 of the tuple.\n        /// </summary>\n        public T7 E7;\n\n        /// <summary>\n        /// Element 8 of the tuple.\n        /// </summary>\n        public T8 E8;\n\n        /// <summary>\n        /// Element 9 of the tuple.\n        /// </summary>\n        public T9 E9;\n\n        public Tup(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9)\n        { E0 = e0; E1 = e1; E2 = e2; E3 = e3; E4 = e4; E5 = e5; E6 = e6; E7 = e7; E8 = e8; E9 = e9; }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9})\", E0, E1, E2, E3, E4, E5, E6, E7, E8, E9);\n        }\n    }\n\n    #endregion\n\n    #region Static Tuple Create Methods\n\n    /// <summary>\n    /// This static class allows the creation of tuples without specifying\n    /// the types in angle brackets.\n    /// </summary>\n    public static class Tup\n    {\n        public static Tup<T0, T1> Create<T0, T1>(T0 e0, T1 e1)\n        {\n            return new Tup<T0, T1>(e0, e1);\n        }\n\n        public static Tup<T0, T1, T2> Create<T0, T1, T2>(T0 e0, T1 e1, T2 e2)\n        {\n            return new Tup<T0, T1, T2>(e0, e1, e2);\n        }\n\n        public static Tup<T0, T1, T2, T3> Create<T0, T1, T2, T3>(T0 e0, T1 e1, T2 e2, T3 e3)\n        {\n            return new Tup<T0, T1, T2, T3>(e0, e1, e2, e3);\n        }\n\n        public static Tup<T0, T1, T2, T3, T4> Create<T0, T1, T2, T3, T4>(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4)\n        {\n            return new Tup<T0, T1, T2, T3, T4>(e0, e1, e2, e3, e4);\n        }\n\n        public static Tup<T0, T1, T2, T3, T4, T5> Create<T0, T1, T2, T3, T4, T5>(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5)\n        {\n            return new Tup<T0, T1, T2, T3, T4, T5>(e0, e1, e2, e3, e4, e5);\n        }\n\n        public static Tup<T0, T1, T2, T3, T4, T5, T6> Create<T0, T1, T2, T3, T4, T5, T6>(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6)\n        {\n            return new Tup<T0, T1, T2, T3, T4, T5, T6>(e0, e1, e2, e3, e4, e5, e6);\n        }\n\n        public static Tup<T0, T1, T2, T3, T4, T5, T6, T7> Create<T0, T1, T2, T3, T4, T5, T6, T7>(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7)\n        {\n            return new Tup<T0, T1, T2, T3, T4, T5, T6, T7>(e0, e1, e2, e3, e4, e5, e6, e7);\n        }\n\n        public static Tup<T0, T1, T2, T3, T4, T5, T6, T7, T8> Create<T0, T1, T2, T3, T4, T5, T6, T7, T8>(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8)\n        {\n            return new Tup<T0, T1, T2, T3, T4, T5, T6, T7, T8>(e0, e1, e2, e3, e4, e5, e6, e7, e8);\n        }\n\n        public static Tup<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> Create<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(T0 e0, T1 e1, T2 e2, T3 e3, T4 e4, T5 e5, T6 e6, T7 e7, T8 e8, T9 e9)\n        {\n            return new Tup<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9);\n        }\n\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/Tup/Tuples_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n    //# Action comma = () => Out(\", \");\n    //# Action space = () => Out(\" \");\n    //# int MaxTupleCount = 10;\n    //# int MaxSimpleTupleCount = 16;\n\n    #region Simple Tuples of uniform type\n\n    //# for (int tc = 2; tc <= MaxSimpleTupleCount; tc++) {\n    //# Func<int, string> ename = i => tc < 10 ? i.ToString() : i.ToString(\"00\");\n    #region Tup__tc__\n\n    public struct Tup__tc__<T>\n    {\n        public T /*# tc.ForEach(i => { var e = ename(i); */E__e__/*# }, comma); */;\n\n        #region Constructors\n\n        public Tup__tc__(T e) {/*# tc.ForEach(i => { var e = ename(i); */ E__e__ = e;/*# }); */ }\n        public Tup__tc__(/*# tc.ForEach(i => { var e = ename(i); */T e__e__/*# }, comma); */) {/*# tc.ForEach(i => { var e = ename(i); */ E__e__ = e__e__;/*# }); */ }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } // tc\n    #endregion\n\n    //# for (int tc = 2; tc <= MaxTupleCount; tc++) {\n    #region Tuple of __tc__ Elements\n\n    /// <summary>\n    /// A tuple is a structure containing three elements of different types,\n    /// that can be accessed using the fields /*# tc.ForEach(i => { */E__i__/*# }, comma); */.\n    /// </summary>\n    public struct Tup</*# tc.ForEach(i => { */T__i__/*# }, comma); */>\n    {\n        //# for (int i = 0; i < tc; i++) {\n        /// <summary>\n        /// Element __i__ of the tuple.\n        /// </summary>\n        public T__i__ E__i__;\n\n        //# } // i\n        public Tup(/*# tc.ForEach(i => { */T__i__ e__i__/*# }, comma); */)\n        {/*# tc.ForEach(i => { */ E__i__ = e__i__;/*# }); */ }\n\n        public override readonly string ToString()\n        {\n            return string.Format(\"(/*# tc.ForEach(i => { */{__i__}/*# }, comma); */)\", /*# tc.ForEach(i => { */E__i__/*# }, comma); */);\n        }\n    }\n\n    #endregion\n\n    //# } // tc\n    #region Static Tuple Create Methods\n\n    /// <summary>\n    /// This static class allows the creation of tuples without specifying\n    /// the types in angle brackets.\n    /// </summary>\n    public static class Tup\n    {\n        //# for (int tc = 2; tc <= MaxTupleCount; tc++) {\n        //# var tpar = tc.Range().Select(i => \"T\" + i).Join(\", \");\n        public static Tup<__tpar__> Create<__tpar__>(/*# tc.ForEach(i => { */T__i__ e__i__/*# }, comma); */)\n        {\n            return new Tup<__tpar__>(/*# tc.ForEach(i => { */e__i__/*# }, comma); */);\n        }\n\n        //# } // tc\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base/paket.references",
    "content": "Aardvark.Build\nSystem.Collections.Immutable\nSystem.Reflection.Metadata\nSystem.Text.Json\nSingleFileExtractor.Core"
  },
  {
    "path": "src/Aardvark.Base/paket.template",
    "content": "type project\nid Aardvark.Base\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Aardvark.Base.Essentials.csproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <TargetFramework>netstandard2.0</TargetFramework>\r\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n    <NoWarn>1701;1702;1705;1591</NoWarn>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\Aardvark.Base.Tensors.CSharp\\Aardvark.Base.Tensors.CSharp.csproj\" />\r\n    <ProjectReference Include=\"..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/CameraProjectionOrtho.cs",
    "content": "﻿\nusing System;\n\nnamespace Aardvark.Base\n{\n    public class CameraProjectionOrtho : ICameraProjection\n    {\n        private Trafo3d m_trafo;\n        private readonly EventSource<Trafo3d> m_trafoChanges = new EventSource<Trafo3d>();\n        private Box3d m_box;\n        \n        public CameraProjectionOrtho(double left, double right, double bottom, double top, double near, double far)\n        {\n            SetClippingParams(left, right, bottom, top, near, far);\n        }\n\n        public Trafo3d ProjectionTrafo => m_trafo;\n\n        public IEvent<Trafo3d> ProjectionTrafos => m_trafoChanges;\n\n        public Ray3d Unproject(V2d xyOnNearPlane)\n            => new Ray3d(new V3d(xyOnNearPlane, 0.0), new V3d(xyOnNearPlane, -m_box.Min.Z));\n\n        public void SetClippingParams(double left, double right, double bottom, double top, double near, double far)\n        {\n            m_box.Min.X = left;\n            m_box.Max.X = right;\n            m_box.Min.Y = bottom;\n            m_box.Max.Y = top;\n            m_box.Min.Z = near;\n            m_box.Max.Z = far;\n\n            UpdateProjectionTrafo();\n        }\n\n        public double Near\n        {\n            get { return m_box.Min.Z; }\n            set\n            {\n                if (!(value > 0.0 && value < Far)) throw new ArgumentOutOfRangeException();\n                m_box.Min.Z = value;\n                UpdateProjectionTrafo();\n            }\n        }\n\n        public double Far\n        {\n            get { return m_box.Max.Z; }\n            set\n            {\n                if (!(value > 0.0 && value > Near)) throw new ArgumentOutOfRangeException();\n                m_box.Max.Z = value;\n                UpdateProjectionTrafo();\n            }\n        }\n\n        public Box2d ClippingWindow\n        {\n            get { return m_box.XY; }\n            set\n            {\n                if (m_box.IsInvalid) throw new ArgumentOutOfRangeException();\n                m_box.Min.X = value.Min.X;\n                m_box.Min.Y = value.Min.Y;\n                m_box.Max.X = value.Max.X;\n                m_box.Max.Y = value.Max.Y;\n                UpdateProjectionTrafo();\n            }\n        }\n\n        public double AspectRatio\n        {\n            get\n            {\n                return (m_box.Max.X - m_box.Min.X) / (m_box.Max.Y - m_box.Min.Y);\n            }\n            set\n            {\n                if (value <= 0.0) throw new ArgumentOutOfRangeException();\n                var w = m_box.Max.X - m_box.Min.X;\n                var hOld = m_box.Max.Y - m_box.Min.Y;\n                var hNew = w / value;\n                var f = hNew / hOld;\n                var c = (m_box.Min.Y + m_box.Max.Y) * 0.5;\n                m_box.Min.Y = (m_box.Min.Y - c) * f + c;\n                m_box.Max.Y = (m_box.Max.Y - c) * f + c;\n                UpdateProjectionTrafo();\n            }\n        }\n\n        /// <summary>\n        /// Scales clipping window by given factor.\n        /// </summary>\n        public void Zoom(V2d center, double factor)\n        {\n            if (factor <= 0.0) throw new ArgumentException(\"Factor needs to be greater than 0.0, but is \" + factor + \".\", \"factor\");\n            m_box.Min.X = (m_box.Min.X - center.X) * factor + center.X;\n            m_box.Min.Y = (m_box.Min.Y - center.Y) * factor + center.Y;\n            m_box.Max.X = (m_box.Max.X - center.X) * factor + center.X;\n            m_box.Max.Y = (m_box.Max.Y - center.Y) * factor + center.Y;\n            UpdateProjectionTrafo();\n        }\n\n        private void UpdateProjectionTrafo()\n        {\n            var l = m_box.Min.X; var r = m_box.Max.X;\n            var b = m_box.Min.Y; var t = m_box.Max.Y;\n            var n = m_box.Min.Z; var f = m_box.Max.Z;\n\n            m_trafo = new Trafo3d(\n                new M44d(\n                    2 / (r - l),               0,               0,     (l + r) / (l - r),\n                              0,     2 / (t - b),               0,     (b + t) / (b - t),\n                              0,               0,     1 / (n - f),           n / (n - f),\n                              0,               0,               0,                     1\n                    ),\n\n                new M44d(\n                    (r - l) / 2,               0,               0,           (l + r) / 2,\n                              0,     (t - b) / 2,               0,           (b + t) / 2,\n                              0,               0,           n - f,                    -n,\n                              0,               0,               0,                     1\n                    )\n                );\n\n            m_trafoChanges.Emit(m_trafo);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/CameraProjectionPerspective.cs",
    "content": "﻿\n\nusing System;\n\nnamespace Aardvark.Base\n{\n    public class CameraProjectionPerspective : ICameraProjectionPerspective\n    {\n        private Trafo3d m_trafo;\n        private readonly EventSource<Trafo3d> m_trafoChanges = new EventSource<Trafo3d>();\n        private Box3d m_box;\n\n        public CameraProjectionPerspective(double horizontalFovInDegrees, double near, double far, double aspectRatio = 1.0)\n        {\n            SetClippingParams(horizontalFovInDegrees, near, far, aspectRatio);\n        }\n\n        public CameraProjectionPerspective(double left, double right, double bottom, double top, double near, double far)\n        {\n            SetClippingParams(left, right, bottom, top, near, far);\n        }\n\n        public Trafo3d ProjectionTrafo => m_trafo;\n\n        public IEvent<Trafo3d> ProjectionTrafos => m_trafoChanges;\n\n        public Ray3d Unproject(V2d xyOnNearPlane)\n            => new Ray3d(V3d.Zero, new V3d(xyOnNearPlane, -m_box.Min.Z));\n\n        public void SetClippingParams(double left, double right, double bottom, double top, double near, double far)\n        {\n            m_box.Min.X = left;\n            m_box.Max.X = right;\n            m_box.Min.Y = bottom;\n            m_box.Max.Y = top;\n            m_box.Min.Z = near;\n            m_box.Max.Z = far;\n\n            UpdateProjectionTrafo();\n        }\n\n        public void SetClippingParams(double horizontalFovInDegrees, double near, double far, double aspectRatio = 1.0)\n        {\n            var d = System.Math.Tan(Conversion.RadiansFromDegrees(horizontalFovInDegrees) * 0.5) * near;\n            m_box.Min.X = -d;\n            m_box.Max.X = +d;\n            m_box.Min.Y = -d / aspectRatio;\n            m_box.Max.Y = +d / aspectRatio;\n            m_box.Min.Z = near;\n            m_box.Max.Z = far;\n\n            UpdateProjectionTrafo();\n        }\n\n        public double Near\n        {\n            get { return m_box.Min.Z; }\n            set\n            {\n                if (!(value > 0.0 && value < Far)) throw new ArgumentOutOfRangeException();\n\n                var s = value / m_box.Min.Z;\n                m_box.Min.X *= s; m_box.Max.X *= s;\n                m_box.Min.Y *= s; m_box.Max.Y *= s;\n                m_box.Min.Z = value;\n                UpdateProjectionTrafo();\n            }\n        }\n\n        public double Far\n        {\n            get { return m_box.Max.Z; }\n            set\n            {\n                if (!(value > 0.0 && value > Near)) throw new ArgumentOutOfRangeException();\n                m_box.Max.Z = value;\n                UpdateProjectionTrafo();\n            }\n        }\n\n        public Box2d ClippingWindow\n        {\n            get { return m_box.XY; }\n            set\n            {\n                if (m_box.IsInvalid) throw new ArgumentException();\n                m_box.Min.X = value.Min.X;\n                m_box.Min.Y = value.Min.Y;\n                m_box.Max.X = value.Max.X;\n                m_box.Max.Y = value.Max.Y;\n                UpdateProjectionTrafo();\n            }\n        }\n\n        public double AspectRatio\n        {\n            get\n            {\n                return (m_box.Max.X - m_box.Min.X) / (m_box.Max.Y - m_box.Min.Y);\n            }\n            set\n            {\n                if (value <= 0.0) throw new ArgumentOutOfRangeException();\n                m_box.Min.Y = m_box.Min.X / value;\n                m_box.Max.Y = m_box.Max.X / value;\n                UpdateProjectionTrafo();\n            }\n        }\n\n        public double HorizontalFieldOfViewInDegrees\n        {\n            get\n            {\n                var l = System.Math.Atan2(m_box.Min.X, m_box.Min.Z);\n                var r = System.Math.Atan2(m_box.Max.X, m_box.Min.Z);\n                return Conversion.DegreesFromRadians(-l + r);\n            }\n        }\n\n        private void UpdateProjectionTrafo()\n        {\n            var l = m_box.Min.X; var r = m_box.Max.X;\n            var b = m_box.Min.Y; var t = m_box.Max.Y;\n            var n = m_box.Min.Z; var f = m_box.Max.Z;\n\n            m_trafo = Trafo3d.PerspectiveProjectionRH(l, r, b, t, n, f);\n\n            m_trafoChanges.Emit(m_trafo);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/CameraViewRaw.cs",
    "content": "﻿\n\nnamespace Aardvark.Base\n{\n    public class CameraViewRaw : ICameraView\n    {\n        private Trafo3d m_trafo = Trafo3d.ViewTrafo(V3d.Zero, V3d.XAxis, V3d.ZAxis, -V3d.YAxis);\n        private readonly EventSource<Trafo3d> m_trafoChanges;\n\n        public CameraViewRaw()\n        {\n            m_trafoChanges = EventSource.Create(m_trafo);\n        }\n\n        /// <summary>\n        /// Gets or sets view trafo, which transforms world space into camera space.\n        /// \n        /// In camera space the camera is placed at the origin looking\n        /// down the negative z-axis, with the y-axis pointing upwards\n        /// and the x-axis pointing to the right.\n        /// </summary>\n        public Trafo3d ViewTrafo\n        {\n            get { return m_trafo; }\n            set { m_trafo = value; m_trafoChanges.Emit(m_trafo); }\n        }\n\n        /// <summary>\n        /// Changes of ViewTrafo.\n        /// </summary>\n        public IEvent<Trafo3d> ViewTrafos => m_trafoChanges;\n\n        /// <summary>\n        /// Gets or sets camera location in world space (origin in camera space).\n        /// </summary>\n        public V3d Location\n        {\n            get { return m_trafo.Backward.C3.XYZ; }\n            set { m_trafo = Trafo3d.ViewTrafo(value, Right, Up, -Forward); m_trafoChanges.Emit(m_trafo); }\n        }\n\n        /// <summary>\n        /// Gets or sets camera right vector in world space (+x in camera space).\n        /// </summary>\n        public V3d Right\n        {\n            get { return m_trafo.Backward.C0.XYZ; }\n            set { m_trafo = Trafo3d.ViewTrafo(Location, value, Up, -Forward); m_trafoChanges.Emit(m_trafo); }\n        }\n\n        /// <summary>\n        /// Gets or sets camera up vector in world space (+y in camera space).\n        /// </summary>\n        public V3d Up\n        {\n            get { return m_trafo.Backward.C1.XYZ; }\n            set { m_trafo = Trafo3d.ViewTrafo(Location, Right, value, -Forward); m_trafoChanges.Emit(m_trafo); }\n        }\n\n        /// <summary>\n        /// Gets or sets camera forward direction in world space (-z in camera space).\n        /// </summary>\n        public V3d Forward\n        {\n            get { return -m_trafo.Backward.C2.XYZ; }\n            set { m_trafo = Trafo3d.ViewTrafo(Location, Right, Up, -value); m_trafoChanges.Emit(m_trafo); }\n        }\n        \n        /// <summary>\n        /// Sets location and axes in a single transaction.\n        /// </summary>\n        public void Set(V3d location, V3d right, V3d up, V3d forward)\n        {\n            m_trafo = Trafo3d.ViewTrafo(location, right, up, -forward);\n            m_trafoChanges.Emit(m_trafo);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/CameraViewWithSky.cs",
    "content": "﻿\nusing System;\n\nnamespace Aardvark.Base\n{\n    public class CameraViewWithSky : ICameraView\n    {\n        private V3d m_sky = V3d.OOI;\n        private Trafo3d m_trafo = Trafo3d.ViewTrafo(V3d.Zero, V3d.XAxis, V3d.ZAxis, -V3d.YAxis);\n        private readonly EventSource<Trafo3d> m_trafoChanges = new EventSource<Trafo3d>();\n\n        /// <summary>\n        /// Sky direction (normalized).\n        /// </summary>\n        public V3d Sky\n        {\n            get { return m_sky; }\n            set\n            {\n                m_sky = value.Normalized;\n                if (m_sky == V3d.Zero) throw new ArgumentException(\"Sky direction must not be V3d.Zero.\");\n\n                var r = Vec.Cross(Forward, m_sky).Normalized;\n                var u = Vec.Cross(r, Forward);\n\n                m_trafo = Trafo3d.ViewTrafo(Location, r, u, -Forward);\n                m_trafoChanges.Emit(m_trafo);\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets view trafo, which transforms world space into camera space.\n        /// \n        /// In camera space the camera is placed at the origin looking\n        /// down the negative z-axis, with the y-axis pointing upwards\n        /// and the x-axis pointing to the right.\n        /// </summary>\n        public Trafo3d ViewTrafo\n        {\n            get { return m_trafo; }\n            set { m_trafo = value; m_trafoChanges.Emit(m_trafo); }\n        }\n\n        /// <summary>\n        /// Changes of ViewTrafo.\n        /// </summary>\n        public IEvent<Trafo3d> ViewTrafos => m_trafoChanges;\n\n        /// <summary>\n        /// Gets or sets camera location in world space (origin in camera space).\n        /// </summary>\n        public V3d Location\n        {\n            get { return m_trafo.Backward.C3.XYZ; }\n            set\n            {\n                //Report.Line(\"{0:0.00}\", value);\n                m_trafo = Trafo3d.ViewTrafo(value, Right, Up, -Forward);\n                m_trafoChanges.Emit(m_trafo);\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets camera right vector in world space (+x in camera space).\n        /// </summary>\n        public V3d Right\n        {\n            get { return m_trafo.Backward.C0.XYZ; }\n            set\n            {\n                var r = value.Normalized;\n                var f = Vec.Cross(m_sky, r).Normalized;\n                var u = Vec.Cross(r, f);\n\n                m_trafo = Trafo3d.ViewTrafo(Location, r, u, -f);\n                m_trafoChanges.Emit(m_trafo);\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets camera up vector in world space (+y in camera space).\n        /// </summary>\n        public V3d Up\n        {\n            get { return m_trafo.Backward.C1.XYZ; }\n            set\n            {\n                var u = value.Normalized;\n                var r = Vec.Cross(u, m_sky).Normalized;\n                var f = Vec.Cross(u, r);\n\n                m_trafo = Trafo3d.ViewTrafo(Location, r, u, -f);\n                m_trafoChanges.Emit(m_trafo);\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets camera forward direction in world space (-z in camera space).\n        /// </summary>\n        public V3d Forward\n        {\n            get { return -m_trafo.Backward.C2.XYZ; }\n            set\n            {\n                var f = value.Normalized;\n                var r = Vec.Cross(f, m_sky).Normalized;\n                var u = Vec.Cross(r, f);\n\n                m_trafo = Trafo3d.ViewTrafo(Location, r, u, -f);\n                m_trafoChanges.Emit(m_trafo);\n            }\n        }\n\n        /// <summary>\n        /// Sets location and axes in a single transaction.\n        /// </summary>\n        public void Set(V3d location, V3d right, V3d up, V3d forward)\n        {\n            m_trafo = Trafo3d.ViewTrafo(location, right, up, -forward);\n            m_trafoChanges.Emit(m_trafo);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/ICameraProjection.cs",
    "content": "﻿using Aardvark.Base;\n\nnamespace Aardvark.Base\n{\n    public interface ICameraProjection\n    {\n        /// <summary>\n        /// Transforms the right-handed camera space (looking down the negative z-axis)\n        /// to left-handed normalized device coordinates of the canonical view volume\n        /// defined as [(-1, -1, 0), (+1, +1, +1)].\n        /// Here the x-axis goes to the right, the y-axis goes up, and the z-axis goes\n        /// into the viewport, with near plane mapped to z = 0 and far plane to z = 1.\n        /// </summary>\n        Trafo3d ProjectionTrafo { get; }\n\n        /// <summary>\n        /// Changes of ProjectionTrafo.\n        /// </summary>\n        IEvent<Trafo3d> ProjectionTrafos { get; }\n\n        /// <summary>\n        /// E.g. SetClippingParams(-1, +1, -0.75, +0.75, 1.0, 1000.0)\n        /// will create 90° horizontal field-of-view, with aspect ratio 4:3,\n        /// near distance at 1.0, and far distance at 1000.0.\n        /// </summary>\n        void SetClippingParams(double left, double right, double bottom, double top, double near, double far);\n\n        /// <summary>\n        /// Gets or sets distance of near clipping plane.\n        /// Same as 'near' argument in SetClippingParams.\n        /// </summary>\n        double Near { get; set; }\n\n        /// <summary>\n        /// Gets or sets distance of far clipping plane.\n        /// Same as 'far' argument in SetClippingParams.\n        /// </summary>\n        double Far { get; set; }\n\n        /// <summary>\n        /// Gets or sets clipping window on near plane [(left, bottom), (right, top)].\n        /// Same as 'left', 'right', 'bottom', 'top' arguments in SetClippingParams.\n        /// </summary>\n        Box2d ClippingWindow { get; set; }\n\n        /// <summary>\n        /// Width / Height.\n        /// </summary>\n        double AspectRatio { get; set; }\n    }\n\n    public interface ICameraProjectionPerspective : ICameraProjection\n    {\n        double HorizontalFieldOfViewInDegrees { get; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/ICameraProjectionExtensions.cs",
    "content": "﻿using Aardvark.Base;\r\nusing System;\n\nnamespace Aardvark.Base\n{\n    public static class ICameraProjectionExtensions\n    {\n        /// <summary>\n        /// Gets line (in camera space) from point on near plane to corresponding point on far plane.\n        /// </summary>\n        public static Line3d Unproject(this ICameraProjection self, Ndc2d p)\n            => new Line3d(\n                self.UnprojectPointOnNearPlane(p),\n                self.UnprojectPointOnFarPlane(p)\n                );\n\n        /// <summary>\n        /// Gets point (in camera space) from point in normalized device coordinates.\n        /// </summary>\n        public static V3d Unproject(this ICameraProjection self, Ndc3d p)\n            => self.ProjectionTrafo.Backward.TransformPosProj(p.Position);\r\n\r\n        /// <summary>\n        /// Gets point on near plane (in camera space) from point in normalized device coordinates.\n        /// </summary>\n        public static V3d UnprojectPointOnNearPlane(this ICameraProjection self, Ndc2d p)\n            => self.ProjectionTrafo.Backward.TransformPosProj(new V3d(p.Position, 0.0));\n\n        /// <summary>\n        /// Gets point on far plane (in camera space) from point in normalized device coordinates.\n        /// </summary>\n        public static V3d UnprojectPointOnFarPlane(this ICameraProjection self, Ndc2d p)\n            => self.ProjectionTrafo.Backward.TransformPosProj(new V3d(p.Position, 1.0));\n\n        /// <summary>\n        /// Gets normalized device coordinates from point in camera space.\n        /// </summary>\n        public static Ndc3d TransformPos(this ICameraProjection self, V3d posInCameraSpace)\n            => new Ndc3d(self.ProjectionTrafo.Forward.TransformPosProj(posInCameraSpace));\r\n\r\n        /// <summary>\r\n        /// Scales clipping window by given factor.\r\n        /// </summary>\r\n        public static void Zoom(this ICameraProjection self, V2d center, double factor)\r\n        {\r\n            if (factor <= 0.0) throw new ArgumentException(\"Factor needs to be greater than 0.0, but is \" + factor + \".\", \"factor\");\r\n            var box = self.ClippingWindow;\r\n            box.Min.X = (box.Min.X - center.X) * factor + center.X;\r\n            box.Min.Y = (box.Min.Y - center.Y) * factor + center.Y;\r\n            box.Max.X = (box.Max.X - center.X) * factor + center.X;\r\n            box.Max.Y = (box.Max.Y - center.Y) * factor + center.Y;\r\n            self.ClippingWindow = box;\r\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/ICameraView.cs",
    "content": "﻿using Aardvark.Base;\n\nnamespace Aardvark.Base\n{\n    public interface ICameraView\n    {\n        /// <summary>\n        /// Gets or sets view trafo, which transforms world space into camera space.\n        /// \n        /// In camera space the camera is placed at the origin looking\n        /// down the negative z-axis, with the y-axis pointing upwards\n        /// and the x-axis pointing to the right.\n        /// </summary>\n        Trafo3d ViewTrafo { get; set; }\n\n        /// <summary>\n        /// Changes of ViewTrafo.\n        /// </summary>\n        IEvent<Trafo3d> ViewTrafos { get; }\n\n        /// <summary>\n        /// Gets or sets camera location in world space (origin in camera space).\n        /// </summary>\n        V3d Location { get; set; }\n\n        /// <summary>\n        /// Gets or sets camera right vector in world space (+x in camera space).\n        /// </summary>\n        V3d Right { get; set; }\n\n        /// <summary>\n        /// Gets or sets camera up vector in world space (+y in camera space).\n        /// </summary>\n        V3d Up { get; set; }\n\n        /// <summary>\n        /// Gets or sets camera forward direction in world space (-z in camera space).\n        /// </summary>\n        V3d Forward { get; set; }\n\n        /// <summary>\n        /// Sets location and axes in a single transaction.\n        /// </summary>\n        void Set(V3d location, V3d right, V3d up, V3d forward);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/ICameraViewExtensions.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static class ICameraViewExtensions\n    {\n        /// <summary>\n        /// Turns camera to look at given point p.\n        /// </summary>\n        public static void LookAt(this ICameraView self, V3d p)\n            => self.Forward = (p - self.Location).Normalized;\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/IRenderView.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public interface IViewProjection\n    {\n        /// <summary>\n        /// The view transformation\n        /// </summary>\n        ICameraView View { get; }\n\n        /// <summary>\n        /// The projection transformation\n        /// </summary>\n        ICameraProjection Projection { get; }\n    }\n\n    public interface IRenderView: IViewProjection\n    {\n        /// <summary>\n        /// Region of the RenderBuffer or Control\n        /// </summary>\n        Box2i Region { get; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Camera/IRenderViewExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static class IRenderViewExtensions\n    {\n        /// <summary>\n        /// Projects a point from world-space to normalized device coordinates.\n        /// </summary>\n        public static Ndc3d Project(this IRenderView rv, V3d point)\n        {\n            var viewPoint = rv.View.ViewTrafo.Forward.TransformPos(point);\n            return rv.Projection.TransformPos(viewPoint);\n        }\n\n        /// <summary>\n        /// Project a point from world-space to a pixel position.\n        /// </summary>\n        public static PixelPosition ProjectPixel(this IRenderView rv, V3d point)\n        {\n            var ndcPoint = rv.Project(point);\n            return new PixelPosition(ndcPoint, rv.Region);\n        }\n\n        /// <summary>\n        /// Returns the number of pixels per unit on the near plane. \n        /// ISSUE: Does not consider ClippingWindow of projection\n        /// </summary>\n        public static V2d PixelsPerUnitOnNearPlane(this IRenderView rv)\n        {\n            if (rv.Projection is ICameraProjectionPerspective)\n            {\n                var unitsOnNearPlane = Fun.Tan(((ICameraProjectionPerspective)rv.Projection).HorizontalFieldOfViewInDegrees.RadiansFromDegrees() * 0.5) * 2 * rv.Projection.Near;\n                return (V2d)rv.Region.Size / new V2d(unitsOnNearPlane, unitsOnNearPlane / rv.Projection.AspectRatio);\n            }\n            else\n            {\n                return (V2d)rv.Region.Size / rv.Projection.ClippingWindow.Size; \n            }\n        }\n\n\n        /// <summary>\n        /// Returns the multiplied View-Projection transformation.\n        /// </summary>\n        public static Trafo3d ViewProjTrafo(this IViewProjection vp)\n            => vp.View.ViewTrafo * vp.Projection.ProjectionTrafo;\n\n        /// <summary>\n        /// Builds a hull from the given view-projection (left, right, top, bottom, near, far).\n        /// The normals of the hull planes point to the outside. \n        /// A point inside the visual hull will have positive height to all planes.\n        /// </summary>\n        public static Hull3d GetVisualHull(this IViewProjection vp)\n            => vp.ViewProjTrafo().GetVisualHull();\n\n        /// <summary>\n        /// Returns the ray-direction towards the center of the view.\n        /// </summary>\n        public static V3d CentralDirection(this IViewProjection vp)\n        {\n            var trafo = vp.View.ViewTrafo.Backward * vp.Projection.ProjectionTrafo.Backward;\n\n            var nearPoint = trafo.TransformPosProj(V3d.OOO);\n            var farPoint = trafo.TransformPosProj(V3d.OOI);\n\n            return (farPoint - nearPoint).Normalized;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/BehaviorDragAbsolute.cs",
    "content": "﻿using System;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Behavior extension DragAbsolute.\r\n    /// </summary>\r\n    public static class BehaviorDragAbsolute\r\n    {\r\n        /// <summary>\r\n        /// Updates position until stopDragging completes.\r\n        /// </summary>\r\n        public static async Task<IBehavior> DragAbsolute(this IBehavior self,\r\n            IEvent<V2d> positions, IAwaitable stopDragging, CancellationToken ct\r\n            )\r\n        {\r\n            var obj = self as IBehaviorPosition2d;\r\n            if (obj == null) throw new InvalidOperationException(\"DragAbsolute requires IBehaviorPosition2d.\");\r\n\r\n            await stopDragging.RepeatUntilCompleted(async delegate\r\n            {\r\n                var p = await positions.Next.WithCancellation(ct);\r\n                if (stopDragging.IsCompleted) return;\r\n                obj.Position = p;\r\n            });\r\n\r\n            return self;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/BehaviorDragRelative.cs",
    "content": "﻿using System;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Behavior extension DragRelative.\r\n    /// </summary>\r\n    public static class BehaviorDragRelative\r\n    {\r\n        /// <summary>\r\n        /// Updates position until stopDragging completes.\r\n        /// </summary>\r\n        public static async Task<IBehavior> DragRelative(this IBehavior self,\r\n            V2d initialPosition, IEvent<V2d> moves, IAwaitable stopDragging, CancellationToken ct\r\n            )\r\n        {\r\n            var obj = self as IBehaviorTransform2d;\r\n            if (obj == null) throw new InvalidOperationException(\"DragRelative requires IBehaviorTransform2d.\");\r\n\r\n            var lastPos = initialPosition;\r\n            await stopDragging.RepeatUntilCompleted(\r\n                async delegate\r\n                {\r\n                    var p = await moves.Next.WithCancellation(ct);\r\n                    obj.Transform(M33d.Translation(p - lastPos));\r\n                    lastPos = p;\r\n                });\r\n\r\n            return self;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IBehavior.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Marker interface fort all behaviors.\r\n    /// </summary>\r\n    public interface IBehavior\r\n    {\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IBehaviorDeletable.cs",
    "content": "﻿namespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Editable object can be deleted.\r\n    /// </summary>\r\n    public interface IBehaviorDeletable : IBehavior\r\n    {\r\n        /// <summary>\r\n        /// Deletes editable object.\r\n        /// </summary>\r\n        void Delete();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IBehaviorPosition2d.cs",
    "content": "﻿namespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Editable object has a position in 2d.\r\n    /// </summary>\r\n    public interface IBehaviorPosition2d : IBehavior\r\n    {\r\n        /// <summary>\r\n        /// Gets or sets 2d position.\r\n        /// </summary>\r\n        V2d Position { get; set; }\r\n    }\r\n}"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IBehaviorSplittableEdge2d.cs",
    "content": "﻿namespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Editable edge that can be splitted.\r\n    /// </summary>\r\n    public interface IBehaviorSplittableEdge2d : IBehavior\r\n    {\r\n        /// <summary>\r\n        /// Splits edge at position nearest to given split position.\r\n        /// </summary>\r\n        void Split(V2d splitPosition);\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IBehaviorTransform2d.cs",
    "content": "﻿namespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Editable object can be transformed in 2d.\r\n    /// </summary>\r\n    public interface IBehaviorTransform2d : IBehavior\r\n    {\r\n        /// <summary>\r\n        /// Transform in 2d.\r\n        /// </summary>\r\n        void Transform(M33d trafo);\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IEditableEdge2d.cs",
    "content": "﻿namespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// An editable edge.\r\n    /// </summary>\r\n    public interface IEditableEdge2d :\r\n        IBehaviorPosition2d,\r\n        IBehaviorTransform2d,\r\n        IBehaviorSplittableEdge2d,\r\n        IBehaviorDeletable,\r\n        IEditableSequence<Line2d>\r\n    {\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IEditableFace2d.cs",
    "content": "﻿namespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// An editable face.\r\n    /// </summary>\r\n    public interface IEditableFace2d :\r\n        IBehaviorPosition2d,\r\n        IBehaviorTransform2d,\r\n        IBehaviorDeletable\r\n    {\r\n        /// <summary>\r\n        /// Returns index-th vertex as editable vertex.\r\n        /// </summary>\r\n        IEditableVertex2d GetEditableVertex(int index);\r\n\r\n        /// <summary>\r\n        /// Returns index-th edge as editable edge.\r\n        /// </summary>\r\n        IEditableEdge2d GetEditableEdge(int index);\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IEditableSequence.cs",
    "content": "﻿namespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Exposes sequence of editing steps.\r\n    /// </summary>\r\n    public interface IEditableSequence<T>\r\n    {\r\n        /// <summary>\r\n        /// Sets or gets current version of editable object.\r\n        /// </summary>\r\n        T Current { get; set; }\r\n\r\n        /// <summary>\r\n        /// Sequence of editing steps. \r\n        /// </summary>\r\n        IEvent<T> EditingSteps { get; }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Editing/IEditableVertex2d.cs",
    "content": "﻿namespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// An editable vertex.\r\n    /// </summary>\r\n    public interface IEditableVertex2d :\r\n        IBehaviorPosition2d,\r\n        IBehaviorTransform2d,\r\n        IBehaviorDeletable,\r\n        IEditableSequence<V2d>\r\n    {\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/NormalizedDeviceCoordinates.cs",
    "content": "﻿using Aardvark.Base;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Position (x,y) in normalized device coordinates.\n    /// The canonical view volume is defined as [(-1, -1, 0), (+1, +1, 1)].\n    /// </summary>\n    public readonly struct Ndc2d\n    {\n        /// <summary>\n        /// Normalized device coordinates.\n        /// </summary>\n        public readonly V2d Position;\n\n        /// <summary>\n        /// Position (xy) in normalized device coordinates.\n        /// </summary>\n        public Ndc2d(V2d position)\n        {\n            Position = position;\n        }\n\n        /// <summary>\n        /// Position (xy) in normalized device coordinates.\n        /// </summary>\n        public Ndc2d(double x, double y)\n        {\n            Position = new V2d(x, y);\n        }\n\n        /// <summary>\n        /// Position (xy) in normalized device coordinates.\n        /// </summary>\n        public Ndc2d(PixelPosition p)\n        {\n            var np = p.NormalizedPosition;\n            Position = new V2d(\n                -1.0 + np.X * 2.0,\n                +1.0 - np.Y * 2.0\n                );\n        }\n\n        /// <summary>\n        /// Transform the normalized device coordinate to a [0, 1] texture coordinate (flipping Y).\n        /// </summary>\n        public V2d TextureCoordinate\n        {\n            get\n            {\n                return new V2d(Position.X * 0.5 + 0.5, -Position.Y * 0.5 + 0.5);\n            }\n        }\n    }\n\n    /// <summary>\n    /// Position (xyz) in normalized device coordinates.\n    /// The canonical view volume is defined as [(-1, -1, 0), (+1, +1, 1)].\n    /// </summary>\n    public readonly struct Ndc3d\n    {\n        /// <summary>\n        /// Normalized device coordinates.\n        /// </summary>\n        public readonly V3d Position;\n\n        /// <summary>\n        /// Position (xyz) in normalized device coordinates.\n        /// </summary>\n        public Ndc3d(V3d position)\n        {\n            Position = position;\n        }\n\n        /// <summary>\n        /// Position (xy) in normalized device coordinates.\n        /// </summary>\n        public Ndc3d(double x, double y, double z)\n        {\n            Position = new V3d(x, y, z);\n        }\n\n        /// <summary>\n        /// Transform the normalized device coordinate to a [0, 1] texture coordinate (flipping Y) with depth.\n        /// </summary>\n        public V3d TextureCoordinate\n        {\n            get\n            {\n                return new V3d(Position.X * 0.5 + 0.5, -Position.Y * 0.5 + 0.5, Position.Z);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/PixelPosition.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// An integral pixel position relative to specified bounds.\n    /// The x-axis goes from left to right and y-axis from top to bottom.\n    /// </summary>\n    public readonly struct PixelPosition\n    {\n        /// <summary>\n        /// X goes from left to right and y from top to bottom.\n        /// Integral pixel positions correspond to pixel centers.\n        /// </summary>\n        public readonly V2i Position;\n\n        /// <summary>\n        /// Minimum is top left pixel (inclusive) and maximum is bottom right pixel (exclusive).\n        /// E.g. with bounds [(0, 0), (800, 600)] the top left pixel is (0,0) and the bottom\n        /// right pixel is (799,599).\n        /// </summary>\n        public readonly Box2i Bounds;\n\n        /// <summary>\n        /// Pixel position relative to specified bounds.\n        /// For example, a typical render window has bounds [(0, 0), (width, height)].\n        /// </summary>\n        public PixelPosition(V2i position, Box2i bounds)\n        {\n            Position = position;\n            Bounds = bounds;\n        }\r\n\r\n        /// <summary>\r\n        /// Pixel position relative to specified bounds.\r\n        /// For example, a typical render window has bounds [(0, 0), (width, height)].\r\n        /// </summary>\r\n        public PixelPosition(V2i position, int width, int height)\r\n        {\r\n            Position = position;\r\n            Bounds = Box2i.FromSize(width, height);\r\n        }\n\n        /// <summary>\n        /// Pixel position relative to specified bounds.\n        /// For example, a typical render window has bounds [(0, 0), (width, height)].\n        /// </summary>\n        public PixelPosition(int x, int y, int width, int height)\n        {\n            Position = new V2i(x, y);\n            Bounds = Box2i.FromSize(width, height);\n        }\n        \n        /// <summary>\n        /// PixelPosition from normalized device coordinates.\n        /// </summary>\n        public PixelPosition(Ndc2d ndc, V2i renderTargetSize)\n            : this(ndc, Box2i.FromSize(renderTargetSize))\n        {\n        }\n\n        /// <summary>\n        /// PixelPosition from normalized device coordinates.\n        /// </summary>\n        public PixelPosition(Ndc2d ndc, Box2i renderTargetRegion)\n        {\n            Position = new V2i(ndc.TextureCoordinate * (V2d)renderTargetRegion.Size);\n            Bounds = renderTargetRegion;\n        }\n\n        /// <summary>\n        /// PixelPosition from normalized device coordinates.\n        /// </summary>\n        public PixelPosition(Ndc3d ndc, V2i renderTargetSize)\n            : this(ndc, Box2i.FromSize(renderTargetSize))\n        {\n        }\n\n        /// <summary>\n        /// PixelPosition from normalized device coordinates.\n        /// </summary>\n        public PixelPosition(Ndc3d ndc, Box2i renderTargetRegion)\n            : this(new Ndc2d(ndc.Position.XY), renderTargetRegion)\n        {\n        }\n        \n        /// <summary>\n        /// Maps integral pixel position to range ](0,0), (1,1)[,\n        /// where integral pixel positions correspond to pixel centers.\n        /// E.g. all pixel mappings for Bounds [(0,0), (3,2)] are as follows:\n        /// (0,0) -> (0.17, 0.25)\n        /// (1,0) -> (0.50, 0.25)\n        /// (2,0) -> (0.83, 0.25)\n        /// (0,1) -> (0.17, 0.75)\n        /// (0,2) -> (0.50, 0.75)\n        /// (0,3) -> (0.83, 0.75)\n        /// </summary>\n        public V2d NormalizedPosition => new V2d(\n            (Position.X - Bounds.Min.X + 0.5) / (Bounds.Max.X - Bounds.Min.X),\n            (Position.Y - Bounds.Min.Y + 0.5) / (Bounds.Max.Y - Bounds.Min.Y)\n            );\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/Screenshot.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Reflection;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Xml.Linq;\nusing Aardvark.Base;\nusing System.Net;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Net.Sockets;\n\nnamespace Aardvark.Rendering\n{\n\n    public class HttpServer2Route\n    {\n        private enum Mode\n        {\n            Literal,\n            Variable,\n            Mixed,\n        }\n        private readonly Http.Verb m_verb;\n        private readonly string m_route;\n        private readonly Action<HttpServerRequestInfo> m_handler;\n\n        private readonly string[] m_tokens;\n        private readonly Mode[] m_modes;\n\n        public Action<HttpServerRequestInfo> Handler { get { return m_handler; } }\n        public string Route { get { return m_route; } }\n        public Http.Verb Verb { get { return m_verb; } }\n        public bool Matches(string s, Dictionary<string, string> variables)\n        {\n            var matchedVariables = new List<(string, string)>();\n            var tokens = s.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);\n            if (tokens.Length != m_tokens.Length) return false;\n            for (int i = 0; i < tokens.Length; i++)\n            {\n                switch (m_modes[i])\n                {\n                    case Mode.Literal:\n                        if (!m_tokens[i].Equals(tokens[i])) return false;\n                        break;\n                    case Mode.Variable:\n                        matchedVariables.Add((m_tokens[i], tokens[i]));\n                        break;\n                    case Mode.Mixed:\n                        {\n                            int start = m_tokens[i].IndexOf('[');\n                            int end = m_tokens[i].IndexOf(']');\n                            if (end != m_tokens[i].Length - 1) return false;\n                            var pre = m_tokens[i].Left(start);\n                            if (!tokens[i].StartsWith(pre)) return false;\n                            matchedVariables.Add(\n                                (\n                                    m_tokens[i].Substring(start + 1, end - start - 1),\n                                    tokens[i].Substring(pre.Length)\n                                ));\n                        }\n                        break;\n                    default:\n                        throw new NotImplementedException();\n                }\n            }\n\n            foreach (var mv in matchedVariables) variables[mv.Item1] = mv.Item2;\n            return true;\n        }\n\n        public HttpServer2Route(string route, Http.Verb verb, Action<HttpServerRequestInfo> handler)\n        {\n            m_verb = verb;\n            m_route = route;\n            m_handler = handler;\n\n            m_tokens = route.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);\n            m_modes = new Mode[m_tokens.Length];\n            for (int i = 0; i < m_tokens.Length; i++)\n            {\n                var token = m_tokens[i];\n                var length = token.Length;\n                if (token.Contains(\"[\"))\n                {\n                    if (token[0] == '[' && token[length - 1] == ']')\n                    {\n                        m_modes[i] = Mode.Variable;\n                        m_tokens[i] = token.Substring(1, length - 2);\n                    }\n                    else\n                    {\n                        m_modes[i] = Mode.Mixed;\n                    }\n                }\n                else\n                {\n                    m_modes[i] = Mode.Literal;\n                }\n            }\n        }\n    }\n\n    public class HttpServer2Dispatcher\n    {\n        private readonly List<HttpServer2Route> m_routes = new List<HttpServer2Route>();\n\n        public void AddRoutes(params HttpServer2Route[] routes)\n        {\n            AddRoutes((IEnumerable<HttpServer2Route>)routes);\n        }\n        public void AddRoutes(IEnumerable<HttpServer2Route> routes)\n        {\n            m_routes.AddRange(routes);\n        }\n        public void AddRoute(HttpServer2Route route)\n        {\n            m_routes.Add(route);\n        }\n\n        public HttpServer2Dispatcher() { }\n        public HttpServer2Dispatcher(params HttpServer2Route[] routes)\n            : this((IEnumerable<HttpServer2Route>)routes)\n        {\n        }\n        public HttpServer2Dispatcher(IEnumerable<HttpServer2Route> routes)\n        {\n            m_routes.AddRange(routes);\n        }\n\n        public HttpServer2Route Dispatch(string uri, Http.Verb verb, Dictionary<string, string> variables)\n        {\n            return m_routes\n                .Where(r => r.Verb == verb)\n                .Where(r => r.Matches(uri, variables))\n                .FirstOrDefault();\n        }\n    }\n\n    public class HttpServerRequestInfo\n    {\n        private HttpListenerContext m_context;\n\n        private string m_head;\n        private string m_route;\n        private Http.Verb m_verb;\n        private readonly Dictionary<string, string> m_query = new Dictionary<string, string>();\n\n        public string Head\n        {\n            get { return m_head; }\n            internal set { m_head = value; }\n        }\n        public string Route\n        {\n            get { return m_route; }\n            internal set { m_route = value; }\n        }\n        public HttpListenerContext Context\n        {\n            get { return m_context; }\n            internal set { m_context = value; }\n        }\n        public Http.Verb Verb\n        {\n            get { return m_verb; }\n            internal set { m_verb = value; }\n        }\n        public Dictionary<string, string> Query\n        {\n            get { return m_query; }\n        }\n        public string Get(string paramName, string defaultValue)\n        {\n            return m_query.ContainsKey(paramName) ? m_query[paramName] : defaultValue;\n        }\n        public int Get(string paramName, int defaultValue)\n        {\n            try\n            {\n                return m_query.ContainsKey(paramName) ? m_query[paramName].ToInt() : defaultValue;\n            }\n            catch\n            {\n                return defaultValue;\n            }\n        }\n        public double Get(string paramName, double defaultValue)\n        {\n            try\n            {\n                return m_query.ContainsKey(paramName) ? m_query[paramName].ToDouble() : defaultValue;\n            }\n            catch\n            {\n                return defaultValue;\n            }\n        }\n    }\n\n    public class HttpServerDispatcher\n    {\n        private readonly Dictionary<string, List<Func<HttpServerRequestInfo, bool>>> m_handlers =\n            new Dictionary<string, List<Func<HttpServerRequestInfo, bool>>>();\n        private readonly Dictionary<string, List<HttpServerDispatcher>> m_dispatchers =\n            new Dictionary<string, List<HttpServerDispatcher>>();\n\n        public void Register(Func<HttpServerRequestInfo, bool> handler)\n        {\n            Register(\"\", handler);\n        }\n        public void Register(string prefix, Func<HttpServerRequestInfo, bool> handler)\n        {\n            prefix = prefix ?? \"\";\n            if (!m_handlers.ContainsKey(prefix))\n            {\n                m_handlers[prefix] = new List<Func<HttpServerRequestInfo, bool>>();\n            }\n            m_handlers[prefix].Add(handler);\n        }\n\n        public void Register(Http.Verb verb, Func<HttpServerRequestInfo, bool> handler)\n        {\n            Register(\"\", verb, handler);\n        }\n        public void Register(string prefix, Http.Verb verb, Func<HttpServerRequestInfo, bool> handler)\n        {\n            prefix = prefix ?? \"\";\n            prefix += \".\" + verb.ToString();\n            Register(prefix, handler);\n        }\n\n        public void Register(HttpServerDispatcher dispatcher)\n        {\n            Register(\"\", dispatcher);\n        }\n        public void Register(string prefix, HttpServerDispatcher dispatcher)\n        {\n            prefix = prefix ?? \"\";\n            if (!m_dispatchers.ContainsKey(prefix))\n            {\n                m_dispatchers[prefix] = new List<HttpServerDispatcher>();\n            }\n            m_dispatchers[prefix].Add(dispatcher);\n        }\n\n        public IEnumerable<string> Prefixes\n        {\n            get\n            {\n                return\n                    m_handlers.Keys.Select(x => x.ToString()).Concat(\n                    m_dispatchers.Keys.Select(x => x.ToString())\n                    );\n            }\n        }\n\n        /// <summary>\n        /// Returns true if route has been handled.\n        /// </summary>\n        internal bool Dispatch(HttpServerRequestInfo info)\n        {\n            string route = info.Route;\n            bool routeHasBeenHandled = false;\n\n            // 0. preconditions\n            // (e.g. \"/foo/bar/woohoo\" -> \"foo/bar/woohoo\")\n            if (route != null && route.Length > 0 && route[0] == '/') route = route.Substring(1);\n\n            // 1. split route into head and tail\n            string head, tail;\n            int separatorIndex = route.IndexOf('/');\n            if (separatorIndex < 0)\n            {\n                head = route;\n                tail = \"\";\n            }\n            else\n            {\n                head = route.Substring(0, separatorIndex);\n                tail = route.Substring(separatorIndex + 1);\n            }\n\n            // 2. call handlers & dispatchers\n            List<Func<HttpServerRequestInfo, bool>> handlers;\n            if (m_handlers.TryGetValue(\"\", out handlers))\n            {\n                foreach (var handler in handlers)\n                {\n                    routeHasBeenHandled |= handler(info);\n                }\n            }\n\n            var storeRoute = info.Route;\n            var storeHead = info.Head;\n            info.Route = tail;\n            info.Head = head;\n\n            if (m_handlers.TryGetValue(head, out handlers))\n            {\n                foreach (var handler in handlers)\n                {\n                    routeHasBeenHandled |= handler(info);\n                }\n            }\n            if (m_handlers.TryGetValue(head + \".\" + info.Verb.ToString(), out handlers))\n            {\n                foreach (var handler in handlers)\n                {\n                    routeHasBeenHandled |= handler(info);\n                }\n            }\n\n            List<HttpServerDispatcher> dispatchers;\n            if (m_dispatchers.TryGetValue(head, out dispatchers))\n            {\n                foreach (var dispatcher in dispatchers)\n                {\n                    routeHasBeenHandled |= dispatcher.Dispatch(info);\n                }\n            }\n\n            info.Head = storeHead;\n            info.Route = storeRoute;\n            return routeHasBeenHandled;\n        }\n\n        public HttpServerDispatcher()\n        {\n            Register(\"help\", DefaultHelpHandler);\n        }\n\n        private bool DefaultHelpHandler(HttpServerRequestInfo info)\n        {\n            var items = new List<string>();\n            foreach (var p in Prefixes)\n            {\n                if (p == null || p == \"\" || p == \"help\") continue;\n                if (p.EndsWith(\".GET\")) { items.Add(p.Sub(0, -4)); continue; }\n                if (p.EndsWith(\".POST\")) { items.Add(p.Sub(0, -5)); continue; }\n                if (p.EndsWith(\".PUT\")) { items.Add(p.Sub(0, -4)); continue; }\n                if (p.EndsWith(\".DELETE\")) { items.Add(p.Sub(0, -7)); continue; }\n                items.Add(p);\n            }\n            info.Context.SendReply(items.Distinct().Join(\", \"));\n            return true;\n        }\n\n    }\n\n    public static class Http\n    {\n        public enum Verb\n        {\n            GET,\n            POST,\n            PUT,\n            DELETE,\n        }\n\n        public static WebResponse Get(string uri, Dictionary<string, object> query)\n        {\n            return Send(\"GET\", uri, query, null, null);\n        }\n\n        public static WebResponse Get(string uri)\n        {\n            return Send(\"GET\", uri, null, null, null);\n        }\n\n        public static WebResponse Post(\n            string uri, Dictionary<string, object> query,\n            string contentType, byte[] data)\n        {\n            return Send(\"POST\", uri, query, data, contentType);\n        }\n\n        public static WebResponse Post(\n            string uri, Dictionary<string, object> query,\n            string contentType, string data)\n        {\n            return Send(\"POST\", uri, query, new UTF8Encoding().GetBytes(data), contentType);\n        }\n\n        public static WebResponse Post(\n            string uri, string contentType, byte[] data)\n        {\n            return Send(\"POST\", uri, null, data, contentType);\n        }\n\n        public static WebResponse Post(\n            string uri, string contentType, string data)\n        {\n            return Send(\"POST\", uri, null, new UTF8Encoding().GetBytes(data), contentType);\n        }\n\n        public static WebResponse Delete(string uri)\n        {\n            return Send(\"DELETE\", uri, null, null, null);\n        }\n\n        public static WebResponse Put(string uri)\n        {\n            return Send(\"PUT\", uri, null, null, null);\n        }\n\n        //public static WebResponse Put(\n        //    string uri, Dictionary<string, object> query,\n        //    string contentType, byte[] data)\n        //{\n        //    return Send(\"PUT\", uri, query, data, contentType);\n        //}\n\n        //public static WebResponse Delete(\n        //    string uri, Dictionary<string, object> query)\n        //{\n        //    return Send(\"DELETE\", uri, query, null, null);\n        //}\n\n        public static WebResponse Send(\n            string verb, string uri,\n            Dictionary<string, object> query,\n            byte[] postData,\n            string contentType)\n        {\n            if (uri.Right(1) == \"/\") uri = uri.Substring(0, uri.Length - 1);\n            if (query != null)\n            {\n                uri += \"?\" + query\n                    .Select(x => string.Format(\"{0}={1}\", x.Key, x.Value.ToString()))\n                    .Join(\"&\");\n            }\n            var finalUri = new Uri(uri);\n            var httpRequest = (HttpWebRequest)WebRequest.Create(finalUri);\n            httpRequest.Method = verb;\n            if (postData != null)\n            {\n                httpRequest.ContentType = contentType;\n                httpRequest.ContentLength = postData.Length;\n                using (var s = httpRequest.GetRequestStream())\n                {\n                    s.Write(postData, 0, postData.Length);\n                }\n            }\n            return httpRequest.GetResponse();\n        }\n    }\n\n    public class HttpServer\n    {\n        private static string s_defaultPrefix = null;\n        private readonly HttpListener m_listener = new HttpListener();\n        private readonly HttpServerDispatcher m_dispatcher = new HttpServerDispatcher();\n        private HttpServer2Dispatcher m_dispatcher2 = null;\n\n        private volatile bool m_isRunning = false;\n        private volatile bool m_stop = false;\n        private readonly object m_lock = new object();\n\n        public void SwitchToNewStyle()\n        {\n            m_dispatcher2 = new HttpServer2Dispatcher();\n        }\n\n        /// <summary>\n        /// Old-style dispatcher.\n        /// </summary>\n        public HttpServerDispatcher Dispatcher\n        {\n            get { return m_dispatcher; }\n        }\n        /// <summary>\n        /// New-style dispatcher.\n        /// </summary>\n        public HttpServer2Dispatcher Dispatcher2\n        {\n            get { return m_dispatcher2; }\n        }\n\n        public bool IsRunning\n        {\n            get { return m_isRunning; }\n        }\n\n        /// <summary>\n        /// Gets underlying HttpListener for fine-grained control.\n        /// </summary>\n        public HttpListener HttpListener\n        {\n            get { return m_listener; }\n        }\n\n        public void Stop()\n        {\n            if (!m_isRunning) return;\n            m_stop = true;\n            m_listener.Close();\n            while (m_isRunning) ;// Report.Warn(\"stopping\");\n        }\n\n        public void Start()\n        {\n            lock (m_lock)\n            {\n                if (m_isRunning)\n                {\n                    Report.Line(5, \"WARNING: HttpServer already running - doing nothing\");\n                    return;\n                }\n                m_isRunning = true;\n            }\n\n            // listen on default uri if no user-specified prefix is given\n            // default is: http:\\\\<first local ip address>:4242/\n            if (m_listener.Prefixes.Count == 0)\n            {\n                if (s_defaultPrefix == null)\n                {\n                    var localIP =\n                        Dns.GetHostAddresses(Dns.GetHostName())\n                        .Where(x => x.AddressFamily == AddressFamily.InterNetwork)\n                        .FirstOrDefault()\n                        ;\n                    if (localIP != null)\n                    {\n                        s_defaultPrefix = string.Format(\"http://{0}:4242/\", localIP.ToString());\n                    }\n                    else\n                    {\n                        s_defaultPrefix = \"http://localhost:4242/\";\n                    }\n                }\n\n                m_listener.Prefixes.Add(s_defaultPrefix);\n            }\n\n            try\n            {\n                Report.Line(4, \"[starting] kernel http server\");\n                m_listener.Start();\n                Report.Line(4, \"[started ] kernel http server\");\n                Report.Line(4, \"           listening on {0}\",\n                    m_listener.Prefixes.Select(x => x).Join(\", \")\n                    );\n            }\n            catch (Exception e)\n            {\n                // catch all - if listening fails for any reason\n                // then report exception and continue without kernel http server\n                Report.Line(\"[info] failed to listen on {0}\", s_defaultPrefix);\n                Report.Line(\"       {0}\", e.ToString());\n\n                lock (m_lock) m_isRunning = false;\n                return; // do not start server loop\n            }\n\n            // http server loop\n            Task.Factory.StartNew(delegate\n            {\n                while (!m_stop)\n                {\n                    try\n                    {\n                        var context = m_listener.GetContext();\n                        if (m_stop) break;\n\n                        #region Init HttpServerRequestInfo\n\n                        var info = new HttpServerRequestInfo() { Context = context };\n\n                        // init route\n                        var route = context.Request.RawUrl;\n                        var queryStartIndex = route.IndexOf('?');\n                        if (queryStartIndex >= 0)\n                        {  // cut off query part of uri\n                            route = route.Substring(0, queryStartIndex);\n                        }\n                        if (route.Length > 0 && route.Right(1) == \"/\")\n                        {   // cut off trailing '/'\n                            route = route.Substring(0, route.Length - 1);\n                        }\n                        info.Route = route;\n\n                        // init verb\n                        switch (context.Request.HttpMethod)\n                        {\n                            case \"GET\": info.Verb = Http.Verb.GET; break;\n                            case \"POST\": info.Verb = Http.Verb.POST; break;\n                            case \"PUT\": info.Verb = Http.Verb.PUT; break;\n                            case \"DELETE\": info.Verb = Http.Verb.DELETE; break;\n                        }\n\n                        // init query\n                        var query = context.Request.QueryString;\n                        for (int i = 0; i < query.Count; i++)\n                        {\n                            info.Query[query.GetKey(i)] = query.GetValues(i).Join(\";\");\n                        }\n\n                        #endregion\n\n                        if (m_dispatcher2 == null)\n                        {\n                            // dispatch (old-style)\n                            Task.Factory.StartNew(delegate\n                            {\n                                try\n                                {\n                                    bool handled = m_dispatcher.Dispatch(info);\n\n                                    // if no handler matches reply \"not found\"\n                                    if (!handled)\n                                    {\n                                        context.SendReply(s_notFoundReply, HttpStatusCode.NotFound);\n                                    }\n                                }\n                                catch (Exception e)\n                                {\n                                    Report.Warn(\"HttpServer: {0}\", e.ToString());\n                                }\n                            });\n                        }\n                        else\n                        {\n                            // dispatch new-style\n                            var match = m_dispatcher2.Dispatch(info.Route, info.Verb, info.Query);\n                            if (match == null)\n                            {\n                                Task.Factory.StartNew(delegate\n                                {\n                                    context.SendReply(s_notFoundReply, HttpStatusCode.NotFound);\n                                });\n                            }\n                            else\n                            {\n                                Task.Factory.StartNew(delegate\n                                {\n                                    match.Handler(info);\n                                });\n                            }\n                        }\n                    }\n                    catch (Exception e)\n                    {\n                        // catch all - the server loop must not end\n                        // [ISSUE 20080715 sm> handle case when the thread itself dies\n                        // -> has to be resurrected by the kernel\n                        Report.Line(4, \"HttpServer: {0}\", e.ToString());\n                        Thread.Sleep(100);\n                    }\n                }\n\n                m_stop = false;\n                lock (m_lock) m_isRunning = false;\n            });\n        }\n\n        private static readonly string s_notFoundReply =\n            new XElement(\"html\",\n                new XElement(\"body\",\n                    new XElement(\"div\", \"Not found!\"),\n                    new XElement(\"br\"),\n                    new XElement(\"div\", \"Copyright (c) 2008-2017. Aardvark Platform Team.\")\n                    )\n                )\n                .ToString();\n\n        private void ReportRequestProperties(HttpListenerRequest request)\n        {\n            Report.Begin(4, \"Request\");\n\n            // Display the MIME types that can be used in the response.\n            string[] types = request.AcceptTypes;\n            if (types != null)\n            {\n                Report.Begin(4, \"acceptable mime types\");\n                foreach (string s in types)\n                {\n                    Report.Line(4, \"{0}\", s);\n                }\n                Report.End();\n            }\n            // Display the language preferences for the response.\n            types = request.UserLanguages;\n            if (types != null)\n            {\n                Report.Begin(4, \"acceptable natural languages\");\n                foreach (string l in types)\n                {\n                    Report.Line(4, \"{0}\", l);\n                }\n                Report.End();\n            }\n\n            Report.Begin(4, \"query\");\n            foreach (var x in request.QueryString.AllKeys)\n            {\n                Report.Line(4, \"{0} = {1}\", x.ToString(), request.QueryString[x].ToString());\n            }\n            Report.End();\n\n            Report.Line(4, \"url         : {0}\", request.Url.OriginalString);\n            Report.Line(4, \"raw url     : {0}\", request.RawUrl);\n\n            Report.Line(4, \"referred by : {0}\", request.UrlReferrer);\n\n            Report.Line(4, \"http method : {0}\", request.HttpMethod);\n\n            Report.Line(4, \"host name   : {0}\", request.UserHostName);\n            Report.Line(4, \"host address: {0}\", request.UserHostAddress);\n            Report.Line(4, \"user agent  : {0}\", request.UserAgent);\n\n            Report.End();\n        }\n\n    }\n\n    public static class WebReponseExtensions\n    {\n        public static string GetResponseAsString(this WebResponse response)\n        {\n            return new StreamReader(response.GetResponseStream()).ReadToEnd();\n        }\n\n        public static byte[] GetResponseAsBytes(this WebResponse response)\n        {\n            return new BinaryReader(response.GetResponseStream()).ReadBytes(\n                (int)response.ContentLength\n                );\n        }\n    }\n\n    public static class HttpListenerContextExtensions\n    {\n        public static void SendReply(this HttpListenerContext context)\n        {\n            SendReply(context, \"\", HttpStatusCode.OK);\n        }\n\n        public static void SendReply(this HttpListenerContext context, string message)\n        {\n            SendReply(context, message, HttpStatusCode.OK);\n        }\n\n        public static void SendReply(this HttpListenerContext context,\n            string message, HttpStatusCode httpStatusCode)\n        {\n            context.Response.ContentLength64 = Encoding.UTF8.GetByteCount(message);\n            context.Response.StatusCode = (int)httpStatusCode;\n            using (var s = context.Response.OutputStream)\n            {\n                using (var writer = new StreamWriter(s))\n                {\n                    writer.Write(message);\n                }\n            }\n        }\n\n        public static void SendReply(this HttpListenerContext context, byte[] message)\n        {\n            SendReply(context, message, HttpStatusCode.OK);\n        }\n\n        public static void SendReply(this HttpListenerContext context,\n            byte[] message, HttpStatusCode httpStatusCode)\n        {\n            context.Response.ContentLength64 = message.Length;\n            context.Response.StatusCode = (int)httpStatusCode;\n            using (var s = context.Response.OutputStream)\n            {\n                s.Write(message, 0, message.Length);\n            }\n        }\n    }\n\n    public static class Screenshot\n    {\n        public static string CreateImageDesktopFilename()\n        {\n            var now = DateTime.Now;\n            return Path.Combine(\n                Environment.GetFolderPath(Environment.SpecialFolder.Desktop),\n                string.Format(\n                    \"screenshot_{0:0000}{1:00}{2:00}_{3:00}{4:00}{5:00}.png\",\n                    now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second\n                    )\n                );\n        }\n\n        public static string CreateScreenShotFilePath(string path)\n        {\n            var now = DateTime.Now;\n            return Path.Combine(\n                path,\n                string.Format(\n                    \"screenshot_{0:0000}{1:00}{2:00}_{3:00}{4:00}{5:00}.png\",\n                    now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second\n                    )\n                );\n        }\n\n        /// <summary>\n        /// Saves the image to a file on the desktop.\n        /// </summary>\n        public static void SaveToDesktop(PixImage image)\n        {\n            SaveToFile(image, CreateImageDesktopFilename());\n        }\n\n        public static void SaveToFileInPath(PixImage image, string path)\n        {\n            SaveToFile(image, CreateScreenShotFilePath(path));\n        }\n\n        /// <summary>\n        /// Saves the image to a given filename.\n        /// </summary>\n        public static void SaveToFile(PixImage image, string fileName)\n        {\n            image.Save(fileName, PixFileFormat.Png);\n            Report.Line(5, \"saved screenshot: {0}\", fileName);\n        }\n\n        public static string UploadImageDataToServer(MemoryStream stream, string tags)\n        {\n            try\n            {\n                var data = stream.ToArray();\n\n                var response = Http.Post(\n                    \"http://tracker.vrvis.lan:4242/Screenshots\", \"image/png\", data);\n                //\"http://localhost:4242/Screenshots\", \"image/png\", data);\n\n                var key = response.GetResponseAsString();\n\n                Report.Line(\"uploaded screenshot to server\");\n                Report.Line(\"tags: {0}\", tags);\n\n\n                Http.Post(String.Format(\n                    \"http://tracker.vrvis.lan:4242/ScreenshotTag?screenshotUri={0}\", Path.GetFileName(key)),\n                    //\"http://localhost:4242/ScreenshotTag?screenshotUri={0}\", Path.GetFileName(key)),\n                    \"text/xml\",\n                    tags);\n\n                return key;\n            }\n            catch (Exception e)\n            {\n                // fail (almost) silently if upload does not work\n                Report.Line(\"screenshot upload failed: {0}\", e.ToString());\n                return null;\n            }\n        }\n\n        /// <summary>\n        /// Starts the image upload and returns an image key which\n        /// is generated by the server to identify the image.\n        /// </summary>\n        public static string UploadImageToServer(PixImage image, string tags = null)\n        {\n            try\n            {\n                using (var stream = new MemoryStream())\n                {\n                    image.Save(stream, PixFileFormat.Png);\n\n                    tags = tags ?? Environment.UserName + \" \" + Assembly.GetEntryAssembly().GetName().Name;\n                    tags = \"aardvark.rendering \" + tags;\n\n                    return UploadImageDataToServer(stream, tags);\n                }\n            }\n            catch (Exception e)\n            {\n                // fail (almost) silently if upload does not work\n                Report.Line(\"screenshot upload failed: {0}\", e.ToString());\n                return null;\n            }\n        }\n\n        /// <summary>\n        /// Uploads the meta information, which is stored in an XElement hierarchy\n        /// to the server.\n        /// </summary>\n        public static void UploadMetaInfoToServer(XElement metaInfo)\n        {\n            try\n            {\n                byte[] data;\n                using (var stream = new MemoryStream())\n                {\n                    var streamWriter = new StreamWriter(stream);\n                    metaInfo.Save(streamWriter);\n                    data = stream.ToArray();\n                }\n\n                Http.Post(\"http://tracker.vrvis.lan:4242/ScreenshotInfo\", \"text/xml\", data);\n                Report.Line(\"uploaded meta info to server\");\n            }\n            catch (Exception e)\n            {\n                // fail (almost) silently if upload does not work\n                Report.Line(\"metainfo upload failed: {0}\", e.ToString());\n            }\n        }\n\n        private static XElement BuildCompleteMetaInfo(XElement metaDataFromForm, string imageKey, PixImage image)\n        {\n            string[] parts = imageKey.Split('\\\\');\n            string fileName = parts[3];\n\n            var created = DateTime.Now;\n            var thumbFileName = fileName + \".thumb.jpg\";\n            //var infoFileName = fileName + \".xml\";\n            var size = image.Size;\n\n            var metaInfo =\n                new XElement(\"ScreenshotInfo\",\n                    new XAttribute(\"Created\", created.ToString()),\n                    new XElement(\"FileName\", fileName),\n                    new XElement(\"ThumbFileName\", thumbFileName),\n                    new XElement(\"Size\", size.ToString()),\n                    new XElement(\"Tag\", \"\",\n                        new XAttribute(\"Created\", created.ToString())),\n                    new XElement(\"Tag\", metaDataFromForm.Element(\"Tag\").Value,\n                        new XAttribute(\"Created\", created.ToString())),\n                    new XElement(\"Kategorie\", \"\",\n                        new XAttribute(\"Created\", created.ToString())),\n                    new XElement(\"Kategorie\", metaDataFromForm.Element(\"Kategorie\").Value,\n                        new XAttribute(\"Created\", created.ToString())),\n                    new XElement(\"Comment\", \"Screenshot erstellt\",\n                        new XAttribute(\"Created\", created.ToString())),\n                    new XElement(\"Comment\", metaDataFromForm.Element(\"Comment\").Value,\n                    new XAttribute(\"Created\", created.ToString()))\n                );\n\n            return metaInfo;\n        }\n\n        public static void SaveAndUpload(PixImage image, bool uploadToServer, string tags = null)\n        {\n            // need to clone the image; original will be disposed afterwards\n            Task.Factory.StartNew(delegate\n            {\n                // 1. save file locally\n                SaveToDesktop(image);\n\n                // 2. upload\n                if (uploadToServer)\n                {\n                    UploadImageToServer(image, tags);\n                }\n            }\n            //, Kernel.TaskManager.CpuBoundLowPriority\n            );\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/Awaitable.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Represents an awaitable with clear-push semantics. \r\n    /// Since Task/TaskCompletionSource are likely to spawn new threads \r\n    /// and execute the respective continuations on haphazardous threads \r\n    /// we implemeted our own awaitable executing all continuations on \r\n    /// the thread which they were triggered on.\r\n    /// </summary>\r\n    public class Awaitable : IAwaitable, IEventEmitter<Unit>\r\n    {\r\n        private int m_isCompleted;\r\n        private List<Action> m_continuations;\r\n        private SpinLock m_continuationLock;\r\n\r\n        private CancellationToken? m_ct;\r\n        private CancellationTokenRegistration m_ctRegistration;\r\n\r\n        private readonly Awaiter m_awaiter;\r\n\r\n        #region Constructors\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public Awaitable(CancellationToken? ct = null)\r\n        {\r\n            m_isCompleted = 0;\r\n            m_continuations = new List<Action>();\r\n            m_continuationLock = new SpinLock();\r\n\r\n            m_ct = ct;\r\n            if (m_ct.HasValue)\r\n            {\r\n                if (m_ct.Value.CanBeCanceled)\r\n                {\r\n                    m_ctRegistration = m_ct.Value.Register(Emit);\r\n                }\r\n            }\r\n\r\n            m_awaiter = new Awaiter(this);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Properties\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public bool IsCompleted\r\n        {\r\n            get { return m_isCompleted == 1; }\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Methods\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void Emit()\r\n        {\r\n            var old = Interlocked.Exchange(ref m_isCompleted, 1);\r\n            if (old == 0)\r\n            {\r\n                //If the Awaitable has a CancellationToken release the registration\r\n                if (m_ct.HasValue) m_ctRegistration.Dispose();\r\n\r\n                List<Action> actions = null;\r\n                bool taken = false;\r\n                try\r\n                {\r\n                    m_continuationLock.Enter(ref taken);\r\n                    actions = m_continuations;\r\n                    m_continuations = null;\r\n                }\r\n                finally\r\n                {\r\n                    if (taken) m_continuationLock.Exit();\r\n                }\r\n\r\n                if (actions != null)\r\n                {\r\n                    var acts = Interlocked.Exchange(ref actions, new List<Action>());\r\n                    foreach (var c in acts)\r\n                    {\r\n                        try { c(); }\r\n                        catch { }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        \r\n        /// <summary>\r\n        /// </summary>\r\n        public void Emit(Unit value)\r\n        {\r\n            Emit();\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void Subscribe(Action continuation)\r\n        {\r\n            bool execute = false;\r\n            bool taken = false;\r\n            try\r\n            {\r\n                m_continuationLock.Enter(ref taken);\r\n\r\n                if (m_isCompleted == 1)\r\n                    execute = true;\r\n                else\r\n                    m_continuations.Add(continuation);\r\n            }\r\n            finally\r\n            {\r\n                if (taken) m_continuationLock.Exit();\r\n            }\r\n\r\n            if (execute)\r\n                continuation();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region IAwaitable Members\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public IAwaiter GetAwaiter()\r\n        {\r\n            return m_awaiter;\r\n        }\r\n\r\n        #endregion\r\n\r\n        private readonly struct Awaiter : IAwaiter\r\n        {\r\n            private readonly Awaitable m_source;\r\n\r\n            #region Constructors\r\n\r\n            public Awaiter(Awaitable source)\r\n            {\r\n                m_source = source;\r\n            }\r\n\r\n            #endregion\r\n\r\n            #region IAwaiter Members\r\n\r\n            public bool IsCompleted\r\n            {\r\n                get { return m_source.m_isCompleted == 1; }\r\n            }\r\n\r\n            public void GetResult()\r\n            {\r\n                //since we're here in the waiting code again the exception will occur where expected\r\n                if (m_source.m_ct.HasValue && m_source.m_ct.Value.IsCancellationRequested)\r\n                    throw new TaskCanceledException();\r\n            }\r\n\r\n            public void OnCompleted(Action continuation)\r\n            {\r\n                m_source.Subscribe(continuation);\r\n            }\r\n\r\n            #endregion\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// Represents an awaitable with clear-push semantics. \r\n    /// Since Task/TaskCompletionSource are likely to spawn new threads \r\n    /// and execute the respective continuations on haphazardous threads \r\n    /// we implemeted our own awaitable executing all continuations on \r\n    /// the thread which they were triggered on.\r\n    /// </summary>\r\n    public class Awaitable<T> : IAwaitable<T>, IEventEmitter<T>\r\n    {\r\n        private int m_isCompleted;\r\n        private T m_result;\r\n\r\n        private List<Action> m_continuations;\r\n        private SpinLock m_continuationLock;\r\n\r\n        private CancellationToken? m_ct;\r\n        private CancellationTokenRegistration m_ctRegistration;\r\n\r\n        private readonly Awaiter m_awaiter;\r\n        private ManualResetEventSlim m_onPush = null;\r\n\r\n        #region Constructors\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public Awaitable(CancellationToken? ct = null)\r\n        {\r\n            m_isCompleted = 0;\r\n            m_result = default(T);\r\n\r\n            m_continuations = new List<Action>();\r\n            m_continuationLock = new SpinLock();\r\n\r\n            m_ct = ct;\r\n            if (m_ct.HasValue)\r\n            {\r\n                if (m_ct.Value.CanBeCanceled)\r\n                {\r\n                    m_ctRegistration = m_ct.Value.Register(() => Emit(default(T)));\r\n                }\r\n            }\r\n\r\n            m_awaiter = new Awaiter(this);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Properties\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public bool IsCompleted\r\n        {\r\n            get { return m_isCompleted == 1; }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public T Result\r\n        {\r\n            get\r\n            {\r\n                if (m_isCompleted == 1) return m_result;\r\n                else\r\n                {\r\n                    if (m_onPush == null)\r\n                    {\r\n                        Interlocked.CompareExchange(ref m_onPush, new ManualResetEventSlim(), null);\r\n                    }\r\n\r\n                    m_onPush.Wait();\r\n\r\n                    return m_result;\r\n                }\r\n            }\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Methods\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void Emit(T value)\r\n        {\r\n            var old = Interlocked.Exchange(ref m_isCompleted, 1);\r\n            if (old == 0)\r\n            {\r\n                m_result = value;\r\n                //If the Awaitable has a CancellationToken release the registration\r\n                if (m_ct.HasValue) m_ctRegistration.Dispose();\r\n\r\n                List<Action> actions = null;\r\n                bool taken = false;\r\n                try\r\n                {\r\n                    m_continuationLock.Enter(ref taken);\r\n                    actions = m_continuations;\r\n                    m_continuations = null;\r\n                }\r\n                finally\r\n                {\r\n                    if (taken) m_continuationLock.Exit();\r\n                }\r\n\r\n                if (actions != null)\r\n                {\r\n                    //Run all registered Continuations\r\n                    var acts = Interlocked.Exchange(ref actions, new List<Action>());\r\n                    foreach (var c in acts)\r\n                    {\r\n                        try { c(); }\r\n                        catch { }\r\n                    }\r\n                }\r\n\r\n                if (m_onPush != null)\r\n                {\r\n                    m_onPush.Set();\r\n                    m_onPush = null;\r\n                }\r\n\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void Subscribe(Action continuation)\r\n        {\r\n            bool execute = false;\r\n            bool taken = false;\r\n            try\r\n            {\r\n                m_continuationLock.Enter(ref taken);\r\n\r\n                if (m_isCompleted == 1)\r\n                    execute = true;\r\n                else\r\n                    m_continuations.Add(continuation);\r\n            }\r\n            finally\r\n            {\r\n                if (taken) m_continuationLock.Exit();\r\n            }\r\n\r\n            if (execute)\r\n                continuation();\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void Subscribe(Action<T> continuation)\r\n        {\r\n            if (m_isCompleted == 1)\r\n            {\r\n                Report.Warn(\"awaiting already completed Awaitable\");\r\n                continuation(m_result);\r\n            }\r\n            else\r\n            {\r\n                bool taken = false;\r\n                try\r\n                {\r\n                    m_continuationLock.Enter(ref taken);\r\n                    m_continuations.Add(() => continuation(m_result));\r\n                }\r\n                finally\r\n                {\r\n                    if (taken) m_continuationLock.Exit();\r\n                }\r\n            }\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region IAwaitable Members\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public IAwaiter<T> GetAwaiter()\r\n        {\r\n            return m_awaiter;\r\n        }\r\n\r\n        IAwaiter IAwaitable.GetAwaiter()\r\n        {\r\n            return m_awaiter;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region IEventEmitter\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void Emit()\r\n        {\r\n            Emit(default(T));\r\n        }\r\n\r\n        #endregion\r\n\r\n        private readonly struct Awaiter : IAwaiter<T>\r\n        {\r\n            private readonly Awaitable<T> m_source;\r\n\r\n            #region Constructors\r\n\r\n            public Awaiter(Awaitable<T> source)\r\n            {\r\n                m_source = source;\r\n            }\r\n\r\n            #endregion\r\n\r\n            #region IAwaiter Members\r\n\r\n            public bool IsCompleted\r\n            {\r\n                get { return m_source.m_isCompleted == 1; }\r\n            }\r\n\r\n            public T GetResult()\r\n            {\r\n                //since we're here in the waiting code again the exception will occur where expected\r\n                if (m_source.m_ct.HasValue && m_source.m_ct.Value.IsCancellationRequested) \r\n                    throw new TaskCanceledException();\r\n\r\n                return m_source.m_result;\r\n            }\r\n\r\n            public void OnCompleted(Action continuation)\r\n            {\r\n                m_source.Subscribe(continuation);\r\n            }\r\n\r\n            void IAwaiter.GetResult()\r\n            {\r\n                //since we're here in the waiting code again the exception will occur where expected\r\n                if (m_source.m_ct.HasValue) m_source.m_ct.Value.ThrowIfCancellationRequested();\r\n            }\r\n\r\n            #endregion\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// Contains various combinators for Awaitables (e.g. WhenAny, WhenAll, WithCancellation) since the Task-combinators cannot be used for Awaitables.\r\n    /// </summary>\r\n    public static class Await\r\n    {\r\n        /// <summary>\r\n        /// </summary>\r\n        public static readonly Clock GlobalClock = new Clock(120);\r\n\r\n        #region WithCancellation\r\n\r\n        /// <summary>\r\n        /// Creates a task that completes (or cancels) when either the input task completes or the cancellation token is signalled.\r\n        /// On cancellation, the original task still runs to completion because there is no way to preemptively cancel it.\r\n        /// </summary>\r\n        public static IAwaitable<T> WithCancellation<T>(this IAwaitable<T> input, CancellationToken ct)\r\n        {\r\n            var result = new Awaitable<T>(ct);\r\n            input.Subscribe(v => result.Emit(v));\r\n            return result;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a task that completes (or cancels) when either the input task completes or the cancellation token is signalled.\r\n        /// On cancellation, the original task still runs to completion because there is no way to preemptively cancel it.\r\n        /// </summary>\r\n        public static IAwaitable WithCancellation(this IAwaitable input, CancellationToken ct)\r\n        {\r\n            var result = new Awaitable(ct);\r\n            input.Subscribe(() => result.Emit());\r\n            return result;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region WhenAny\r\n\r\n        /// <summary>\r\n        /// Creates a task that will complete when any of the supplied tasks have completed.\r\n        /// </summary>\r\n        public static IAwaitable<IAwaitable> WhenAny(params IAwaitable[] inputs)\r\n        {\r\n            var result = new Awaitable<IAwaitable>();\r\n\r\n            foreach (var i in inputs)\r\n            {\r\n                i.Subscribe(() =>\r\n                {\r\n                    if (!result.IsCompleted) result.Emit(i);\r\n                });\r\n            }\r\n\r\n            return result;\r\n        }\r\n        \r\n        /// <summary>\r\n        /// Creates a task that will complete when any of the supplied tasks have completed.\r\n        /// </summary>\r\n        public static IAwaitable<IAwaitable<T>> WhenAny<T>(params IAwaitable<T>[] inputs)\r\n        {\r\n            var result = new Awaitable<IAwaitable<T>>();\r\n\r\n            foreach (var i in inputs)\r\n            {\r\n                i.Subscribe(v =>\r\n                {\r\n                    if (!result.IsCompleted) result.Emit(i);\r\n                });\r\n            }\r\n\r\n            return result;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region WhenAll\r\n\r\n        /// <summary>\r\n        /// Creates a task that will complete when all of the supplied tasks have completed.\r\n        /// </summary>\r\n        public static IAwaitable<T[]> WhenAll<T>(params IAwaitable<T>[] inputs)\r\n        {\r\n            var result = new Awaitable<T[]>();\r\n\r\n            var set = new HashSet<IAwaitable<T>>(inputs);\r\n            var output = new T[inputs.Length];\r\n            var i = 0;\r\n            foreach (var input in set)\r\n            {\r\n                var index = i;\r\n                var ip = input;\r\n                ip.Subscribe(v =>\r\n                {\r\n                    output[index] = v;\r\n                    if (set.Remove(ip) && set.Count == 0)\r\n                    {\r\n                        if (!result.IsCompleted) result.Emit(output);\r\n                    }\r\n                });\r\n\r\n                i++;\r\n            }\r\n\r\n            return result;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a task that will complete when all of the supplied tasks have completed.\r\n        /// </summary>\r\n        public static IAwaitable WhenAll(params IAwaitable[] inputs)\r\n        {\r\n            var result = new Awaitable();\r\n\r\n            var set = new HashSet<IAwaitable>(inputs);\r\n            foreach (var input in set)\r\n            {\r\n                var ip = input;\r\n                ip.Subscribe(() =>\r\n                {\r\n                    if (set.Remove(ip) && set.Count == 0)\r\n                    {\r\n                        if (!result.IsCompleted) result.Emit();\r\n                    }\r\n                });\r\n            }\r\n\r\n            return result;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Select\r\n\r\n        /// <summary>\r\n        /// Projects the result of the task into a new form.\r\n        /// </summary>\r\n        public static IAwaitable<TResult> Select<TInput, TResult>(this IAwaitable<TInput> input, Func<TInput, TResult> f)\r\n        {\r\n            var result = new Awaitable<TResult>();\r\n            input.Subscribe(v => result.Emit(f(v)));\r\n            return result;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Projects the result of the task into a new form.\r\n        /// </summary>\r\n        public static IAwaitable<TResult> Select<TResult>(this IAwaitable input, Func<TResult> f)\r\n        {\r\n            var result = new Awaitable<TResult>();\r\n            input.Subscribe(() => result.Emit(f()));\r\n            return result;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region ContinueWith\r\n\r\n        /// <summary>\r\n        /// Creates a continuation that executes when the target task completes.\r\n        /// </summary>\r\n        public static IAwaitable<TResult> ContinueWith<T, TResult>(this IAwaitable<T> awaitable, Func<T, TResult> fun)\r\n        {\r\n            var result = new Awaitable<TResult>();\r\n\r\n            awaitable.Subscribe(v =>\r\n                {\r\n                    result.Emit(fun(v));\r\n                });\r\n\r\n            return result;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a continuation that executes when the target task completes.\r\n        /// </summary>\r\n        public static IAwaitable ContinueWith<T>(this IAwaitable<T> awaitable, Action<T> action)\r\n        {\r\n            var result = new Awaitable();\r\n\r\n            awaitable.Subscribe(v =>\r\n            {\r\n                action(v);\r\n                result.Emit();\r\n            });\r\n\r\n            return result;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a continuation that executes when the target task completes.\r\n        /// </summary>\r\n        public static IAwaitable<TResult> ContinueWith<TResult>(this IAwaitable awaitable, Func<TResult> fun)\r\n        {\r\n            var result = new Awaitable<TResult>();\r\n\r\n            awaitable.Subscribe(() =>\r\n            {\r\n                result.Emit(fun());\r\n            });\r\n\r\n            return result;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a continuation that executes when the target task completes.\r\n        /// </summary>\r\n        public static IAwaitable ContinueWith<TResult>(this IAwaitable awaitable, Action fun)\r\n        {\r\n            var result = new Awaitable();\r\n\r\n            awaitable.Subscribe(() =>\r\n            {\r\n                fun();\r\n                result.Emit();\r\n            });\r\n\r\n            return result;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Delay\r\n\r\n        /// <summary>\r\n        /// Creates a task that will complete after a time delay.\r\n        /// </summary>\r\n        public static IAwaitable<TimeValue> Delay(uint milliseconds, CancellationToken ct)\r\n        {\r\n            return GlobalClock.Future((int)milliseconds).WithCancellation(ct);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a task that will complete after a time delay.\r\n        /// </summary>\r\n        public static IAwaitable<TimeValue> Delay(uint milliseconds)\r\n        {\r\n            return GlobalClock.Future((int)milliseconds);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a task that will complete after a time delay.\r\n        /// </summary>\r\n        public static IAwaitable<TimeValue> Delay(TimeSpan delay, CancellationToken ct)\r\n        {\r\n            return Delay((uint)delay.TotalMilliseconds, ct);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a task that will complete after a time delay.\r\n        /// </summary>\r\n        public static IAwaitable<TimeValue> Delay(TimeSpan delay)\r\n        {\r\n            return Delay((uint)delay.TotalMilliseconds);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a task that will complete after the shortest possible time delay.\r\n        /// </summary>\r\n        public static IAwaitable<TimeValue> Tick\r\n        {\r\n            get { return GlobalClock.Tick(); }\r\n        }\r\n\r\n        #endregion\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public static class AwaitableTest\r\n    {\r\n        static async void Run(Awaitable<int> a, Awaitable<int> b, CancellationToken ct)\r\n        {\r\n            try\r\n            {\r\n                var i = await Await.WhenAny(a, b).WithCancellation(ct);\r\n                Console.WriteLine(\"got: {0}\", i);\r\n            }\r\n            catch (OperationCanceledException)\r\n            {\r\n                Report.Line(\"cancelled\");\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public static void Run()\r\n        {\r\n            var c = new CancellationTokenSource();\r\n            var ct = c.Token;\r\n\r\n            var a = new Awaitable<int>();\r\n            var b = new Awaitable<int>();\r\n            Run(a, b, ct);\r\n\r\n            //c.Cancel();\r\n            a.Emit(1);\r\n            b.Emit(2);\r\n\r\n            Console.ReadLine();\r\n\r\n\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public class TaskAwaiter<T> : IAwaiter<T>\r\n    {\r\n        private System.Runtime.CompilerServices.TaskAwaiter<T> m_awaiter;\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public TaskAwaiter(System.Runtime.CompilerServices.TaskAwaiter<T> awaiter)\r\n        {\r\n            m_awaiter = awaiter;\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void OnCompleted(Action continuation)\r\n        {\r\n            m_awaiter.OnCompleted(continuation);\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public bool IsCompleted\r\n        {\r\n            get { return m_awaiter.IsCompleted; }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public T GetResult()\r\n        {\r\n            return m_awaiter.GetResult();\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        void IAwaiter.GetResult()\r\n        {\r\n            m_awaiter.GetResult();\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public class TaskAwaiter : IAwaiter\r\n    {\r\n        private System.Runtime.CompilerServices.TaskAwaiter m_awaiter;\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public TaskAwaiter(System.Runtime.CompilerServices.TaskAwaiter awaiter)\r\n        {\r\n            m_awaiter = awaiter;\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void OnCompleted(Action continuation)\r\n        {\r\n            m_awaiter.OnCompleted(continuation);\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public bool IsCompleted\r\n        {\r\n            get { return m_awaiter.IsCompleted; }\r\n        }\r\n\r\n        void IAwaiter.GetResult()\r\n        {\r\n            m_awaiter.GetResult();\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public class TaskAwaitable<T> : IAwaitable<T>\r\n    {\r\n        private readonly Task<T> m_task;\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public TaskAwaitable(Task<T> task) { m_task = task; }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public IAwaiter<T> GetAwaiter()\r\n        {\r\n            return new TaskAwaiter<T>(m_task.GetAwaiter());\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public T Result\r\n        {\r\n            get { return m_task.Result; }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        IAwaiter IAwaitable.GetAwaiter()\r\n        {\r\n            return new TaskAwaiter<T>(m_task.GetAwaiter());\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public bool IsCompleted\r\n        {\r\n            get { return m_task.IsCompleted; }\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public class TaskAwaitable : IAwaitable\r\n    {\r\n        private readonly Task m_task;\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public TaskAwaitable(Task task) { m_task = task; }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public IAwaiter GetAwaiter()\r\n        {\r\n            return new TaskAwaiter(m_task.GetAwaiter());\r\n        }\r\n\r\n        bool IAwaitable.IsCompleted\r\n        {\r\n            get { return m_task.IsCompleted; }\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public static class TaskAwaitableExtensions\r\n    {\r\n        /// <summary>\r\n        /// </summary>\r\n        public static TaskAwaitable AsAwaitable(this Task task)\r\n        { \r\n            return new TaskAwaitable(task); \r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public static TaskAwaitable<T> AsAwaitable<T>(this Task<T> task)\r\n        {\r\n            return new TaskAwaitable<T>(task);\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/Clock.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Diagnostics;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// </summary>\r\n    public class Clock : IDisposable\r\n    {\r\n        private Task m_timeThread;\r\n        private List<Action> m_waiters;\r\n        private object m_queueLock;\r\n        private SemaphoreSlim m_waitersEnqueued;\r\n        private int m_frequency;\r\n        private int m_minimalUpdateTime;\r\n        private CancellationTokenSource m_source;\r\n        private readonly Dictionary<Action, DateTime> m_lastTime;\r\n\r\n        #region Constructors\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public Clock(int maxUpdateFrequency = 0)\r\n        {\r\n            m_waiters = new List<Action>();\r\n            m_queueLock = new object();\r\n            m_waitersEnqueued = new SemaphoreSlim(0);\r\n            m_frequency = maxUpdateFrequency;\r\n            m_minimalUpdateTime = m_frequency == 0 ? 0 : (int)(1000.0 / (double)m_frequency);\r\n            m_source = new CancellationTokenSource();\r\n\r\n            m_lastTime = new Dictionary<Action, DateTime>();\r\n\r\n            m_timeThread = new Task(Run, TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler);\r\n            //m_timeThread.Priority = ThreadPriority.Highest;\r\n            //m_timeThread.Name = \"ClockThread\";\r\n            //m_timeThread.IsBackground = true;\r\n\r\n            m_timeThread.Start();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Properties\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public int MaximalFrequency\r\n        {\r\n            get { return m_frequency; }\r\n            set\r\n            {\r\n                m_frequency = value;\r\n                m_minimalUpdateTime = m_frequency == 0 ? 0 : (int)(1000.0 / (double)m_frequency);\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public int MinimalUpdateTime\r\n        {\r\n            get { return m_minimalUpdateTime; }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public TimeSpan GetTimeSpanForContinuation(Action continuation, out DateTime now)\r\n        {\r\n            var current = DateTime.Now;\r\n\r\n            DateTime last;\r\n            if (!m_lastTime.TryGetValue(continuation, out last))\r\n            {\r\n                last = current;\r\n                m_lastTime[continuation] = last;\r\n            }\r\n            m_lastTime[continuation] = current;\r\n\r\n            now = current;\r\n            return current - last;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Methods\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void Enqueue(Action a)\r\n        {\r\n            lock (m_queueLock)\r\n            {\r\n                m_waiters.Add(a);\r\n                m_waitersEnqueued.Release();\r\n            }\r\n        }\r\n\r\n        private void Run()\r\n        {\r\n            var w = new Stopwatch();\r\n            var token = m_source.Token;\r\n\r\n            try\r\n            {\r\n                while (true)\r\n                {\r\n                    w.Stop();\r\n                    m_waitersEnqueued.Wait();\r\n                    token.ThrowIfCancellationRequested();\r\n\r\n                    var wait = System.Math.Max(0, m_minimalUpdateTime - (int)w.Elapsed.TotalMilliseconds);\r\n                    if (wait > 0) Thread.Sleep(wait);\r\n                    token.ThrowIfCancellationRequested();\r\n                    w.Restart();\r\n\r\n\r\n                    List<Action> current = null;\r\n                    lock (m_queueLock)\r\n                    {\r\n                        current = m_waiters;\r\n                        m_waiters = new List<Action>();\r\n                    }\r\n\r\n                    for (int i = 1; i < current.Count; i++) m_waitersEnqueued.Wait();\r\n\r\n                    foreach (var a in current)\r\n                    {\r\n                        a();\r\n                    }\r\n                    token.ThrowIfCancellationRequested();\r\n\r\n\r\n                }\r\n            }\r\n            catch (OperationCanceledException)\r\n            {\r\n                Report.Warn(\"clock cancelled\");\r\n            }\r\n            catch (Exception e)\r\n            {\r\n                Report.Warn(\"clock faulted: {0}\", e);\r\n            }\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region IDisposable Members\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public void Dispose()\r\n        {\r\n            if (m_timeThread != null)\r\n            {\r\n                m_source.Cancel();\r\n                m_waitersEnqueued.Release();\r\n                m_timeThread.Wait();\r\n\r\n                m_timeThread = null;\r\n                m_waiters = null;\r\n                m_queueLock = null;\r\n                m_waitersEnqueued = null;\r\n                m_frequency = 0;\r\n                m_minimalUpdateTime = 0;\r\n                m_source = null;\r\n            }\r\n        }\r\n\r\n        #endregion\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public static class ClockExtensions\r\n    {\r\n        /// <summary>\r\n        /// </summary>\r\n        public static double SanityThreshold = 10;\r\n\r\n        #region Awaitable\r\n\r\n        private struct FutureAwaiter : IAwaiter<TimeValue>\r\n        {\r\n            private readonly FutureAwaitable m_future;\r\n            private Action m_continuation;\r\n\r\n            public FutureAwaiter(FutureAwaitable f)\r\n            {\r\n                m_future = f;\r\n                m_continuation = null;\r\n            }\r\n\r\n            public bool IsCompleted\r\n            {\r\n                get { return false; }\r\n            }\r\n\r\n            private void MakeSane(ref TimeSpan span)\r\n            {\r\n                if (m_future.TimeOut > 0)\r\n                {\r\n                    var cap = SanityThreshold * m_future.TimeOut;\r\n                    if (span.TotalMilliseconds > cap) span = TimeSpan.FromMilliseconds(cap);\r\n                }\r\n                else if (m_future.Clock.MinimalUpdateTime != 0)\r\n                {\r\n                    var cap = SanityThreshold * m_future.Clock.MinimalUpdateTime;\r\n                    if (span.TotalMilliseconds > SanityThreshold * m_future.Clock.MinimalUpdateTime) span = TimeSpan.FromMilliseconds(cap);\r\n                }\r\n            }\r\n\r\n            public TimeValue GetResult()\r\n            {\r\n                DateTime current;\r\n                var span = m_future.Clock.GetTimeSpanForContinuation(m_continuation, out current);\r\n\r\n                MakeSane(ref span);\r\n\r\n\r\n                return new TimeValue(current, span.TotalSeconds);\r\n            }\r\n\r\n            public void OnCompleted(Action continuation)\r\n            {\r\n                m_continuation = continuation;\r\n                var timeOut = m_future.TimeOut;\r\n\r\n                if (timeOut == 0)\r\n                {\r\n                    m_future.Clock.Enqueue(continuation);\r\n                }\r\n                else\r\n                {\r\n                    var time = m_future.Clock;\r\n\r\n                    Task.Factory.StartNew(() =>\r\n                    {\r\n                        Thread.Sleep(timeOut);\r\n                        time.Enqueue(continuation);\r\n                    });\r\n                }\r\n            }\r\n\r\n            void IAwaiter.GetResult()\r\n            {\r\n                DateTime current;\r\n                m_future.Clock.GetTimeSpanForContinuation(m_continuation, out current);\r\n            }\r\n        }\r\n\r\n        private class FutureAwaitable : IAwaitable<TimeValue>\r\n        {\r\n            private readonly Clock m_time;\r\n            private readonly int m_timeOut;\r\n\r\n            public FutureAwaitable(Clock time, int timeout = 0)\r\n            {\r\n                m_time = time;\r\n                m_timeOut = timeout;\r\n            }\r\n\r\n            public int TimeOut\r\n            {\r\n                get { return m_timeOut; }\r\n            }\r\n\r\n            public Clock Clock\r\n            {\r\n                get { return m_time; }\r\n            }\r\n\r\n            public IAwaiter<TimeValue> GetAwaiter()\r\n            {\r\n                return new FutureAwaiter(this);\r\n            }\r\n\r\n            IAwaiter IAwaitable.GetAwaiter()\r\n            {\r\n                return new FutureAwaiter(this);\r\n            }\r\n\r\n            public TimeValue Result\r\n            {\r\n                get { throw new NotSupportedException(); }\r\n            }\r\n\r\n            public bool IsCompleted\r\n            {\r\n                get { return false; }\r\n            }\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Extensions\r\n\r\n        /// <summary>\r\n        /// Awaits a time being approximately \"timeout\" milliseconds in the future.\r\n        /// If timeout is zero the maximal clock frequency limits the execution.\r\n        /// </summary>\r\n        public static IAwaitable<TimeValue> Future(this Clock clock, int timeoutInMilliSeconds = 0)\r\n        {\r\n            return new FutureAwaitable(clock, timeoutInMilliSeconds);\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public static IAwaitable<TimeValue> Tick(this Clock clock)\r\n        {\r\n            return new FutureAwaitable(clock, 0);\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public static IEvent<double> TickEvent(this Clock clock)\r\n        {\r\n            var evt = new EventSource<double>(0.0);\r\n\r\n            var w = new Stopwatch();\r\n            w.Start();\r\n            Action a = null;\r\n            a = () =>\r\n            {\r\n                evt.Emit(w.Elapsed.TotalSeconds);\r\n                //w.Restart();\r\n                clock.Enqueue(a);\r\n            };\r\n\r\n            clock.Enqueue(a);\r\n\r\n            return evt;\r\n        }\r\n\r\n        #endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/Disposable.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// </summary>\r\n    public static class IDisposableExtensions\r\n    {\r\n        /// <summary>\r\n        /// Calls Dispose() and returns true if not null,\r\n        /// returns false otherwise.\r\n        /// </summary>\r\n        public static bool TryDispose(this IDisposable self)\r\n        {\r\n            if (self == null) return false;\r\n            self.Dispose();\r\n            return true;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Checks if the objects impelemtns the IDisposable interface,\r\n        /// performs Dispose() in case and returns true, otherwise false.\r\n        /// </summary>\r\n        public static bool TryDispose(this object obj)\r\n        {\r\n            var d = obj as IDisposable;\r\n            if (d == null) return false;\r\n            d.Dispose();\r\n            return true;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Disposes a sequence of IDisposables.\r\n        /// </summary>\r\n        public static void DisposeAll(this IEnumerable<IDisposable> disposables)\r\n        {\r\n            foreach (var d in disposables) d.Dispose();\r\n        }\r\n\r\n        /// <summary>\r\n        /// Disposes a list of IDisposables.\r\n        /// </summary>\r\n        public static void DisposeAll(this List<IDisposable> disposables)\r\n        {\r\n            foreach (var d in disposables) d.Dispose();\r\n        }\r\n\r\n        /// <summary>\r\n        /// Disposes an array of IDisposables.\r\n        /// </summary>\r\n        public static void DisposeAll(this IDisposable[] disposables)\r\n        {\r\n            foreach (var d in disposables) d.Dispose();\r\n        }\r\n\r\n        /// <summary>\r\n        /// Disposes all valid disposables of a sequence.\r\n        /// </summary>\r\n        public static void TryDisposeAll(this IEnumerable<IDisposable> disposables)\r\n        {\r\n            disposables.WhereNotNull().ForEach(x => x.Dispose());\r\n        }\r\n\r\n        /// <summary>\r\n        /// Disposes all disposables in a collections and clears the collection afterwards.\r\n        /// </summary>\r\n        public static void DisposeAllAndClear(this ICollection<IDisposable> disposables)\r\n        {\r\n            if (disposables.IsReadOnly) throw new Exception(\"The collection is read-only... it cannot be cleared.\");\r\n            foreach (var d in disposables) d.Dispose();\r\n            disposables.Clear();\r\n        }\r\n\r\n        /// <summary>\r\n        /// Disposes all disposables in the list and clears it afterwards.\r\n        /// </summary>\r\n        public static void DisposeAllAndClear(this List<IDisposable> disposables)\r\n        {\r\n            foreach (var d in disposables) d.Dispose();\r\n            disposables.Clear();\r\n        }\r\n\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public static class Try\r\n    {\r\n        /// <summary>\r\n        /// Disposes the Disposable if not null and sets its reference to null.\r\n        /// NOTE: needs to be generic since refs somehow do not work with interfaces.\r\n        /// </summary>\r\n        public static void Dispose<T>(ref T x) where T : IDisposable\r\n        {\r\n            if (x != null)\r\n            {\r\n                x.Dispose();\r\n                x = default(T);\r\n            }\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/EventSource.cs",
    "content": "﻿using System;\r\nusing System.Threading;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    public class EventSourceSlim<T> : IEvent<T>\n    {\n        private readonly Subject<T> m_subject;\n        private Awaitable<T> m_awaitable;\n        private T m_latest;\n\n        public EventSourceSlim(T defaultValue)\n        {\n            m_subject = new Subject<T>();\n            m_awaitable = new Awaitable<T>();\n            m_latest = defaultValue;\n        }\n\n        public void Emit(T v)\n        {\n            lock(this)\n            {\n                var currentAwaitable = m_awaitable;\n                m_awaitable = new Awaitable<T>();\n                m_latest = v;\n                currentAwaitable.Emit(v);\n                m_subject.OnNext(v);\n            }\n        }\n\r\n        public T Latest\r\n        {\r\n            get\r\n            {\r\n                lock(this)\r\n                {\r\n                    return m_latest;\r\n                }\r\n            }\r\n        }\r\n\r\n        public IAwaitable<T> Next\n        {\n            get\n            {\n                lock(this)\n                {\n                    return m_awaitable;\n                }\n            }\n        }\n\r\n        public IObservable<T> Values\r\n        {\r\n            get\r\n            {\r\n                return m_subject;\r\n            }\r\n        }\r\n\r\n        IAwaitable IEvent.Next\n        {\n            get\n            {\n                return Next;\n            }\n        }\n\n        IObservable<Unit> IEvent.Values\n        {\n            get\n            {\n                return new MapObservable<T, Unit>(Values, _ => Unit.Default);\n            }\n        }\n    }\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public static class EventSource\r\n    {\r\n        /// <summary>\r\n        /// The type used for the Values property in non-generic event sources.\r\n        /// </summary>\r\n        public static readonly Type UnitEventType = typeof(Unit);\r\n\r\n        /// <summary>\r\n        /// Creates new EventSource with given initial value.\r\n        /// </summary>\r\n        public static EventSource<T> Create<T>(T initialValue)\r\n        {\r\n            return new EventSource<T>(initialValue);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates new EventSource with tuple of given initial values.\r\n        /// </summary>\r\n        public static EventSource<Tuple<T0, T1>> Create<T0, T1>(T0 initialValue0, T1 initialValue1)\r\n        {\r\n            return new EventSource<Tuple<T0, T1>>(Tuple.Create(initialValue0, initialValue1));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates new EventSource with tuple of given initial values.\r\n        /// </summary>\r\n        public static EventSource<Tuple<T0, T1, T2>> Create<T0, T1, T2>(T0 initialValue0, T1 initialValue1, T2 initialValue2)\r\n        {\r\n            return new EventSource<Tuple<T0, T1, T2>>(Tuple.Create(initialValue0, initialValue1, initialValue2));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates new EventSource with tuple of given initial values.\r\n        /// </summary>\r\n        public static EventSource<Tuple<T0, T1, T2, T3>> Create<T0, T1, T2, T3>(T0 initialValue0, T1 initialValue1, T2 initialValue2, T3 initialValue3)\r\n        {\r\n            return new EventSource<Tuple<T0, T1, T2, T3>>(Tuple.Create(initialValue0, initialValue1, initialValue2, initialValue3));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates new EventSource with tuple of given initial values.\r\n        /// </summary>\r\n        public static EventSource<Tuple<T0, T1, T2, T3, T4>> Create<T0, T1, T2, T3, T4>(T0 initialValue0, T1 initialValue1, T2 initialValue2, T3 initialValue3, T4 initialValue4)\r\n        {\r\n            return new EventSource<Tuple<T0, T1, T2, T3, T4>>(Tuple.Create(initialValue0, initialValue1, initialValue2, initialValue3, initialValue4));\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public class EventSource<T> : IEvent<T>, IEventEmitter<T>\r\n    {\r\n        private readonly ThreadLocal<bool> m_currentThreadDoesNotOwnLock = new ThreadLocal<bool>(() => true);\r\n        private SpinLock m_lock = new SpinLock(true);\r\n        private T m_latest;\r\n        private Awaitable<T> m_awaitable = new Awaitable<T>();\r\n        private readonly Lazy<Subject<T>> m_eventStream = new Lazy<Subject<T>>();\r\n\r\n        /// <summary>\r\n        /// Creates an EventSource with default initial value.\r\n        /// </summary>\r\n        public EventSource()\r\n        {\r\n            EventSourceTelemetry.CountConstructorDefault.Increment();\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a new EventSource with specified initial value.\r\n        /// </summary>\r\n        public EventSource(T initialValue)\r\n        {\r\n            EventSourceTelemetry.CountConstructorInitialValue.Increment();\r\n            m_latest = initialValue;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Wraps an observable as an event source.\r\n        /// </summary>\r\n        public EventSource(IObservable<T> fromObservable)\r\n        {\r\n            EventSourceTelemetry.CountConstructorFromObservable.Increment();\r\n            fromObservable.Subscribe(new LambdaObserver<T>(x => Emit(x)));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Wraps an observable as an event source and sets its initial value.\r\n        /// </summary>\r\n        public EventSource(T initialValue, IObservable<T> fromObservable)\r\n        {\r\n            m_latest = initialValue;\r\n            EventSourceTelemetry.CountConstructorInitialValue.Increment();\r\n            EventSourceTelemetry.CountConstructorFromObservable.Increment();\r\n            fromObservable.Subscribe(new LambdaObserver<T>(x => Emit(x)));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Gets latest value emitted by this event source,\r\n        /// or default(T) if no value has been emitted so far.\r\n        /// Do not set this value! Unless you have multiple\r\n        /// related event sources you want to 'update'\r\n        /// simultanously. In this case first set Latest for\r\n        /// all related event sources to their respective new\r\n        /// value, and then Emit the same values. A subscriber\r\n        /// of such an event source which accesses the Latest\r\n        /// property of a related event source then sees the\r\n        /// correct value (independent of emit order).\r\n        /// </summary>\r\n        public T Latest\r\n        {\r\n            get\r\n            {\r\n                EventSourceTelemetry.CountLatestGet.Increment();\r\n                return m_latest;\r\n            }\r\n            set\r\n            {\r\n                m_latest = value;\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// Gets next value that will be emitted by this event source.\r\n        /// </summary>\r\n        public IAwaitable<T> Next\r\n        {\r\n            get\r\n            {\r\n                EventSourceTelemetry.CountNextGet.Increment();\r\n\r\n                bool lockTaken = false;\r\n                try\r\n                {\r\n                    if (m_currentThreadDoesNotOwnLock.Value)\r\n                    {\r\n                        m_lock.Enter(ref lockTaken);\r\n                        m_currentThreadDoesNotOwnLock.Value = false;\r\n                    }\r\n                    return m_awaitable;\r\n                }\r\n                finally\r\n                {\r\n                    if (lockTaken)\r\n                    {\r\n                        m_currentThreadDoesNotOwnLock.Value = true;\r\n                        m_lock.Exit(true);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// Gets observable stream of values emitted by this event source.\r\n        /// </summary>\r\n        public IObservable<T> Values\r\n        {\r\n            get\r\n            {\r\n                EventSourceTelemetry.CountValuesGet.Increment();\r\n                return m_eventStream.Value;\r\n            }\r\n        }\r\n\r\n        /// <summary>\r\n        /// Emits given value from this event source.\r\n        /// </summary>\r\n        public virtual void Emit(T value)\r\n        {\r\n            EventSourceTelemetry.CountEmit.Increment();\r\n\r\n            bool lockTaken = false;\r\n            try\r\n            {\r\n                if (m_currentThreadDoesNotOwnLock.Value)\r\n                {\r\n                    m_currentThreadDoesNotOwnLock.Value = false;\r\n                    m_lock.Enter(ref lockTaken);\r\n                }\r\n\r\n                var currentAwaitable = m_awaitable;\r\n\r\n                // update Latest and Next\r\n                // (before emitting, such that a listener immediately coming back to us already sees the updated state)\r\n                m_awaitable = new Awaitable<T>();\r\n                m_latest = value;\r\n\r\n                // emit value\r\n                currentAwaitable.Emit(value);\r\n                if (m_eventStream.IsValueCreated) m_eventStream.Value.OnNext(value);\r\n            }\r\n            finally\r\n            {\r\n                if (lockTaken)\r\n                {\r\n                    m_currentThreadDoesNotOwnLock.Value = true;\r\n                    m_lock.Exit(true);\r\n                }\r\n            }\r\n        }\r\n\r\n        #region IEvent\r\n\r\n        /// <summary>\r\n        /// Observable notifications for all values that are emitted.\r\n        /// </summary>\r\n        IObservable<Unit> IEvent.Values\r\n        {\r\n            get { return new MapObservable<T, Unit>(Values, _ => Unit.Default); }\r\n        }\r\n\r\n        IAwaitable IEvent.Next\r\n        {\r\n            get { return Next; }\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region IEventEmitter\r\n\r\n        /// <summary>\r\n        /// Emits default T.\r\n        /// </summary>\r\n        public void Emit()\r\n        {\r\n            Emit(default(T));\r\n        }\r\n\r\n        #endregion\r\n    }\r\n\r\n    internal static class EventSourceTelemetry\r\n    {\r\n        public static readonly Telemetry.Counter CountConstructorDefault = new Telemetry.Counter();\r\n        public static readonly Telemetry.Counter CountConstructorInitialValue = new Telemetry.Counter();\r\n        public static readonly Telemetry.Counter CountConstructorFromObservable = new Telemetry.Counter();\r\n        public static readonly Telemetry.Counter CountEmit = new Telemetry.Counter();\r\n        public static readonly Telemetry.Counter CountNextGet = new Telemetry.Counter();\r\n        public static readonly Telemetry.Counter CountLatestGet = new Telemetry.Counter();\r\n        public static readonly Telemetry.Counter CountValuesGet = new Telemetry.Counter();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/EventSourceExtensions.cs",
    "content": "﻿using System;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// </summary>\r\n    public static class EventSourceExtensions\r\n    {\r\n        /// <summary>\r\n        /// Wraps an observable as an event source.\r\n        /// </summary>\r\n        public static EventSource<T> ToEventSource<T>(this IObservable<T> self)\r\n        {\r\n            return new EventSource<T>(self);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Executes action when next value arrives.\r\n        /// </summary>\r\n        public static void ExecuteOnNextValue<T>(this IEvent<T> self, Action<T> action)\r\n        {\r\n            self.Next.ContinueWith(t => action(t));\r\n        }\r\n        \r\n        /// <summary>\r\n        /// Executes action when next value arrives.\r\n        /// </summary>\r\n        public static void ExecuteOnNextValue<T>(this IEvent<T> self, Action action)\r\n        {\r\n            self.Next.ContinueWith(t => action());\r\n        }\r\n        \r\n        /// <summary>\r\n        /// Repeats given action until the next value of this event source arrives.\r\n        /// The optional final action gets called with this newly arrived value. \r\n        /// </summary>\r\n        public static async Task RepeatUntilNext<T>(this IEvent<T> self, Func<Task> action, Func<T, Task> finallyAction = null)\r\n        {\r\n            var next = self.Next;\r\n            while (!next.IsCompleted)\r\n            {\r\n                await Await.WhenAny(action().AsAwaitable(), next);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                await finallyAction(next.Result);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the task completes.\r\n        /// The optional final action gets called with the task's result. \r\n        /// </summary>\r\n        public static async Task RepeatUntilNext<T>(this Task<T> self, Func<Task> action, Func<T, Task> finallyAction = null)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Task.WhenAny(action(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                await finallyAction(self.Result);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the next value of this event source arrives.\r\n        /// The optional final action gets called with this newly arrived value. \r\n        /// </summary>\r\n        public static async Task RepeatUntilNext<T>(this IEvent<T> self, Func<Task> action, Action<T> finallyAction)\r\n        {\r\n            var next = self.Next;\r\n            while (!next.IsCompleted)\r\n            {\r\n                await Await.WhenAny(action().AsAwaitable(), next);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                finallyAction(next.Result);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the task completes.\r\n        /// The optional final action gets called with the task's result. \r\n        /// </summary>\r\n        public static async Task RepeatUntilNext<T>(this Task<T> self, Func<Task> action, Action<T> finallyAction)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Task.WhenAny(action(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                finallyAction(self.Result);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the given task/awaitable completes.\r\n        /// The optional final action gets called with the task's result. \r\n        /// </summary>\r\n        public static async Task RepeatUntilCompleted<T>(this IAwaitable<T> self, Func<Task> action, Func<T, Task> finallyAction = null)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Await.WhenAny(action().AsAwaitable(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                await finallyAction(self.Result);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the given task completes.\r\n        /// The optional final action gets called with the task's result. \r\n        /// </summary>\r\n        public static async Task RepeatUntilCompleted<T>(this Task<T> self, Func<Task> action, Func<T, Task> finallyAction = null)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Task.WhenAny(action(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                await finallyAction(self.Result);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the given task/awaitable completes.\r\n        /// The optional final action gets called with the task's result. \r\n        /// </summary>\r\n        public static async Task RepeatUntilCompleted<T>(this IAwaitable<T> self, Func<Task> action, Action<T> finallyAction)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Await.WhenAny(action().AsAwaitable(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                finallyAction(self.Result);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the given task completes.\r\n        /// The optional final action gets called with the task's result. \r\n        /// </summary>\r\n        public static async Task RepeatUntilCompleted<T>(this Task<T> self, Func<Task> action, Action<T> finallyAction)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Task.WhenAny(action(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                finallyAction(self.Result);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the given task/awaitable completes.\r\n        /// </summary>\r\n        public static async Task RepeatUntilCompleted(this IAwaitable self, Func<Task> action, Func<Task> finallyAction = null)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Await.WhenAny(action().AsAwaitable(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                await finallyAction();\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the given task completes.\r\n        /// </summary>\r\n        public static async Task RepeatUntilCompleted(this Task self, Func<Task> action, Func<Task> finallyAction = null)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Task.WhenAny(action(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                await finallyAction();\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the given task/awaitable completes.\r\n        /// </summary>\r\n        public static async Task RepeatUntilCompleted(this IAwaitable self, Func<Task> action, Action finallyAction)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Await.WhenAny(action().AsAwaitable(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                finallyAction();\r\n        }\r\n\r\n        /// <summary>\r\n        /// Repeats given action until the given task completes.\r\n        /// </summary>\r\n        public static async Task RepeatUntilCompleted(this Task self, Func<Task> action, Action finallyAction)\r\n        {\r\n            while (!self.IsCompleted)\r\n            {\r\n                await Task.WhenAny(action(), self);\r\n            }\r\n\r\n            if (finallyAction != null)\r\n                finallyAction();\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/EventSourceInterfaces.cs",
    "content": "﻿using System;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// The receiving side of an event source.\r\n    /// </summary>\r\n    public interface IEvent<T> : IEvent\r\n    {\r\n        /// <summary>\r\n        /// The latest value that has been emitted.\r\n        /// This will return default(T) if no value has been emitted yet. \r\n        /// </summary>\r\n        T Latest { get; }\r\n\r\n        /// <summary>\r\n        /// The next value that will be emitted.\r\n        /// </summary>\r\n        new IAwaitable<T> Next { get; }\r\n\r\n        /// <summary>\r\n        /// Observable sequence of emitted values.\r\n        /// </summary>\r\n        new IObservable<T> Values { get; }\r\n    }\r\n\r\n    /// <summary>\r\n    /// The sending side of an event source.\r\n    /// </summary>\r\n    public interface IEventEmitter<T> : IEventEmitter\r\n    {\r\n        /// <summary>\r\n        /// Pushes next event value.\r\n        /// </summary>\r\n        void Emit(T value);\r\n    }\r\n\r\n    /// <summary>\r\n    /// The receiving side of an event source.\r\n    /// </summary>\r\n    public interface IEvent\r\n    {\r\n        /// <summary>\r\n        /// The next value that will be emitted.\r\n        /// </summary>\r\n        IAwaitable Next { get; }\r\n\r\n        /// <summary>\r\n        /// Observable notifications for all values that are emitted.\r\n        /// </summary>\r\n        IObservable<Unit> Values { get; }\r\n    }\r\n\r\n    /// <summary>\r\n    /// The sending side of an event source.\r\n    /// </summary>\r\n    public interface IEventEmitter\r\n    {\r\n        /// <summary>\r\n        /// Pushes next event.\r\n        /// </summary>\r\n        void Emit();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/EventSourceSpecials.cs",
    "content": "﻿using System;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// </summary>\r\n    public class ConstEventSource\r\n    {\r\n        /// <summary>\r\n        /// Creates new ConstEventSource with given value.\r\n        /// </summary>\r\n        public static ConstEventSource<T> Create<T>(T value)\r\n        {\r\n            return new ConstEventSource<T>(value);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates new ConstEventSource with tuple of given values.\r\n        /// </summary>\r\n        public static ConstEventSource<Tuple<T0, T1>> Create<T0, T1>(T0 initialValue0, T1 initialValue1)\r\n        {\r\n            return new ConstEventSource<Tuple<T0, T1>>(Tuple.Create(initialValue0, initialValue1));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates new ConstEventSource with tuple of given values.\r\n        /// </summary>\r\n        public static ConstEventSource<Tuple<T0, T1, T2>> Create<T0, T1, T2>(T0 initialValue0, T1 initialValue1, T2 initialValue2)\r\n        {\r\n            return new ConstEventSource<Tuple<T0, T1, T2>>(Tuple.Create(initialValue0, initialValue1, initialValue2));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates new ConstEventSource with tuple of given values.\r\n        /// </summary>\r\n        public static ConstEventSource<Tuple<T0, T1, T2, T3>> Create<T0, T1, T2, T3>(T0 initialValue0, T1 initialValue1, T2 initialValue2, T3 initialValue3)\r\n        {\r\n            return new ConstEventSource<Tuple<T0, T1, T2, T3>>(Tuple.Create(initialValue0, initialValue1, initialValue2, initialValue3));\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates new ConstEventSource with tuple of given values.\r\n        /// </summary>\r\n        public static ConstEventSource<Tuple<T0, T1, T2, T3, T4>> Create<T0, T1, T2, T3, T4>(T0 initialValue0, T1 initialValue1, T2 initialValue2, T3 initialValue3, T4 initialValue4)\r\n        {\r\n            return new ConstEventSource<Tuple<T0, T1, T2, T3, T4>>(Tuple.Create(initialValue0, initialValue1, initialValue2, initialValue3, initialValue4));\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// A ConstEventSource has its initial value and will never emit new values.\r\n    /// </summary>\r\n    public class ConstEventSource<T> : IEvent<T>\r\n    {\r\n        private static readonly Awaitable s_awaitableNonGeneric = new Awaitable();\r\n        private static readonly Awaitable<T> s_awaitable = new Awaitable<T>();\r\n        private readonly T m_value;\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public ConstEventSource(T constValue)\r\n        {\r\n            m_value = constValue;\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public T Latest\r\n        {\r\n            get { return m_value; }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public IAwaitable<T> Next\r\n        {\r\n            get { return s_awaitable; }\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public IObservable<T> Values\r\n        {\r\n            get { return new NeverObservable<T>(); }\r\n        }\r\n\r\n        IAwaitable IEvent.Next\r\n        {\r\n            get { return s_awaitableNonGeneric; }\r\n        }\r\n\r\n        IObservable<Unit> IEvent.Values\r\n        {\r\n            get { return new NeverObservable<Unit>(); }\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/FilteredEventSource.cs",
    "content": "﻿using System;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// </summary>\r\n    public class FilteredEventSource<T> : EventSource<T>\r\n    {\r\n        private readonly Func<T, bool> m_predicate;\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public FilteredEventSource(Func<T, bool> predicate)\r\n        {\r\n            if (predicate == null) throw new ArgumentNullException();\r\n            m_predicate = predicate;\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public override void Emit(T value)\r\n        {\r\n            if (m_predicate(value)) base.Emit(value);\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/IAwaitable.cs",
    "content": "﻿using System;\r\nusing System.Runtime.CompilerServices;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    //These are the interfaces needed to be awaitable (which are not exposed by the .NET)\r\n    //Here's a little example to make it easier to understand its behaviour.\r\n    //\r\n    //  Consider the follwing function:\r\n    //\r\n    //    async void Foo()\r\n    //    {\r\n    //        await x;\r\n    //        Bar();\r\n    //    }\r\n    //\r\n    //  Which will be translated to something like (it's actually more complicated but this will give you the basic idea)\r\n    //  Basically all the continuations call Foo itself and Foo contains something like a jump table (at least using the current .NET framework)\r\n    //\r\n    //    async void Foo()\r\n    //    {\r\n    //        var xAwaiter = x.GetAwaiter();\r\n    //        if(xAwaiter.IsCompleted) Bar();\r\n    //        else\r\n    //        {\r\n    //            xAwaiter.OnCompleted(() =>\r\n    //            {\r\n    //                xAwaiter.GetResult();\r\n    //                Bar();\r\n    //            }\r\n    //        }\r\n    //    }\r\n\r\n    /// <summary>\r\n    /// Represents the required interface for using the async/await syntax.\r\n    /// every class implementing IAwaitable can be 'awaited' like tasks\r\n    /// for an awaitable returning a value see IAwaitable[T].\r\n    /// </summary>\r\n    public interface IAwaitable\r\n    {\r\n        /// <summary>\r\n        /// </summary>\r\n        IAwaiter GetAwaiter();\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        bool IsCompleted { get; }\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public interface IAwaiter : INotifyCompletion\r\n    {\r\n        /// <summary>\r\n        /// When IsCompleted returns true the the awaiting code will simply keep running without subscribing itself\r\n        /// </summary>\r\n        bool IsCompleted { get; }\r\n\r\n        /// <summary>\r\n        /// GetResult is always the first function called in the continuation (even for void) \r\n        /// and is therefore the only point where one can throw exceptions which will occur in user-code\r\n        /// </summary>\r\n        void GetResult();\r\n    }\r\n\r\n    /// <summary>\r\n    /// represents the required interface for using the async/await syntax\r\n    /// every class implementing IAwaitable can be 'awaited' like tasks\r\n    /// for an awaitable returning no value see IAwaitable\r\n    /// </summary>\r\n    public interface IAwaitable<T> : IAwaitable\r\n    {\r\n        /// <summary>\r\n        /// </summary>\r\n        new IAwaiter<T> GetAwaiter();\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        T Result { get; }\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public interface IAwaiter<T> : INotifyCompletion, IAwaiter\r\n    {\r\n        /// <summary>\r\n        /// GetResult is always the first function called in the continuation (even for void) \r\n        /// and is therefore the only point where one can throw exceptions which will occur in user-code\r\n        /// </summary>\r\n        new T GetResult();\r\n    }\r\n\r\n    /// <summary>\r\n    /// </summary>\r\n    public static class IAwaitableExtensions\r\n    {\r\n        /// <summary>\r\n        /// </summary>\r\n        public static void Subscribe<T>(this IAwaitable<T> awaitable, Action<T> action)\r\n        {\r\n            var awaiter = awaitable.GetAwaiter();\r\n            awaiter.OnCompleted(() => { try { action(awaiter.GetResult()); } catch (OperationCanceledException) { } });\r\n        }\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public static void Subscribe(this IAwaitable awaitable, Action action)\r\n        {\r\n            var awaiter = awaitable.GetAwaiter();\r\n            awaiter.OnCompleted(() => { try { awaiter.GetResult(); action(); } catch (OperationCanceledException) { } });\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/Reactive.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public sealed class Unit\n    {\n        private Unit() { }\n\n        public static Unit Default { get { return null; } }\n    }\n\n    internal class SubjectDisposable<T> : IDisposable\n    {\n        private Dictionary<IObserver<T>, int> m_store;\n        private IObserver<T> m_self;\n\n        public SubjectDisposable(Dictionary<IObserver<T>, int> store, IObserver<T> self)\n        {\n            m_store = store;\n            m_self = self;\n        }\n\n        public void Dispose()\n        {\n            if (m_self == null) return;\n\n            lock(m_store)\n            {\n                if(m_store.TryGetValue(m_self, out var cnt))\n                {\n                    cnt--;\n                    if (cnt > 0) m_store[m_self] = cnt;\n                    else m_store.Remove(m_self);\n                }\n                m_store = null;\n                m_self = null;\n            }\n        }\n\n    }\n\n\n    internal class Subject<T> : IObservable<T>, IObserver<T>\n    {\n        private readonly Dictionary<IObserver<T>, int> m_observers;\n\n        public Subject()\n        {\n            m_observers = new Dictionary<IObserver<T>, int>();\n        }\n\n        public void OnCompleted()\n        {\n            IObserver<T>[] arr = null;\n            lock (m_observers)\n            {\n                arr = m_observers.Keys.ToArray(m_observers.Count);\n            }\n            foreach (var obs in arr)\n            {\n                obs.OnCompleted();\n            }\n        }\n\n        public void OnNext(T value)\n        {\n            IObserver<T>[] arr = null;\n            lock (m_observers)\n            {\n                arr = m_observers.Keys.ToArray(m_observers.Count);\n            }\n            foreach (var obs in arr)\n            {\n                obs.OnNext(value);\n            }\n        }\n\n        public void OnError(Exception e)\n        {\n            IObserver<T>[] arr = null;\n            lock (m_observers)\n            {\n                arr = m_observers.Keys.ToArray(m_observers.Count);\n            }\n            foreach (var obs in arr)\n            {\n                obs.OnError(e);\n            }\n        }\n\n        public IDisposable Subscribe(IObserver<T> obs)\n        {\n            lock (m_observers)\n            {\n                if(m_observers.TryGetValue(obs, out var cnt))\n                {\n                    m_observers[obs] = cnt + 1;\n                }\n                else\n                {\n                    m_observers[obs] = 1;\n                }\n\n                return new SubjectDisposable<T>(m_observers, obs);\n            }\n        }\n\n    }\n\n    internal class LambdaObserver<T> : IObserver<T>\n    {\n        private readonly Action<T> m_action;\n\n        public LambdaObserver(Action<T> action)\n        {\n            m_action = action;\n        }\n\n        public void OnNext(T value)\n        {\n            m_action(value);\n        }\n\n        public void OnCompleted()\n        { }\n\n        public void OnError(Exception e)\n        { }\n    }\n\n    internal class MapObserver<T1, T2> : IObserver<T1>\n    {\n        private readonly Func<T1, T2> m_mapping;\n        private readonly IObserver<T2> m_target;\n\n        public MapObserver(IObserver<T2> target, Func<T1, T2> mapping)\n        {\n            m_mapping = mapping;\n            m_target = target;\n        }\n\n        public void OnNext(T1 value)\n        {\n            m_target.OnNext(m_mapping(value));\n        }\n        public void OnCompleted()\n        {\n            m_target.OnCompleted();\n        }\n        public void OnError(Exception error)\n        {\n            m_target.OnError(error);\n        }\n    }\n\n    internal class MapObservable<T1, T2> : IObservable<T2>\n    {\n        private readonly IObservable<T1> m_input;\n        private readonly Func<T1, T2> m_mapping;\n\n        public MapObservable(IObservable<T1> input, Func<T1, T2> mapping)\n        {\n            m_input = input;\n            m_mapping = mapping;\n        }\n\n        public IDisposable Subscribe(IObserver<T2> obs)\n        {\n            return m_input.Subscribe(new MapObserver<T1, T2>(obs, m_mapping));\n        }\n\n    }\n\n    internal class NoDisposable : IDisposable\n    {\n        public NoDisposable() { }\n        public void Dispose()\n        {}\n    }\n    internal class NeverObservable<T> : IObservable<T>\n    {\n        public NeverObservable()\n        {\n\n        }\n        public IDisposable Subscribe(IObserver<T> observer)\n        {\n            return new NoDisposable();\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/Time.cs",
    "content": "﻿using System;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// </summary>\r\n    public readonly struct TimeValue\r\n    {\r\n        /// <summary>\r\n        /// </summary>\r\n        public readonly DateTime T;\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public readonly double Delta;\r\n\r\n        #region Constructors\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public TimeValue(DateTime t, double delta)\r\n        {\r\n            T = t;\r\n            Delta = delta;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Creators\r\n\r\n        /// <summary>\r\n        /// </summary>\r\n        public static TimeValue Now\r\n        {\r\n            get { return new TimeValue(DateTime.Now, 0.0); }\r\n        }\r\n\r\n        #endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/System/WithCancellationExtension.cs",
    "content": "﻿using System;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Aardvark.Base\r\n{\r\n    /// <summary>\r\n    /// Implementation based on\r\n    /// http://blogs.msdn.com/b/dotnet/archive/2013/04/04/net-memory-allocation-profiling-with-visual-studio-2012.aspx\r\n    /// http://blogs.msdn.com/b/pfxteam/archive/2012/10/05/how-do-i-cancel-non-cancelable-async-operations.aspx\r\n    /// </summary>\r\n    public static class TaskWithCancellationExtensions\r\n    {\r\n        /// <summary>\r\n        /// Creates a task that completes (or cancels) when either the input task completes or the cancellation token is signalled.\r\n        /// On cancellation, the original task still runs to completion because there is no way to preemptively cancel it.\r\n        /// </summary>\r\n        public static Task<T> WithCancellation<T>(this Task<T> task, CancellationToken ct)\r\n        {\r\n            if (task.IsCompleted || !ct.CanBeCanceled)\n                return task;\n            else if (ct.IsCancellationRequested)\n                return Task.FromCanceled<T>(ct);\n            else\r\n                return task.WithCancellationInternal(ct);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Creates a task that completes (or cancels) when either the input task completes or the cancellation token is signalled.\r\n        /// On cancellation, the original task still runs to completion because there is no way to preemptively cancel it.\r\n        /// </summary>\r\n        public static Task<T> WithCancellation<T>(this Task<T> task, CancellationToken? ct)\r\n        {\r\n            if (task.IsCompleted || !ct.HasValue || !ct.Value.CanBeCanceled)\n                return task;\n            else if (ct.Value.IsCancellationRequested)\n                return Task.FromCanceled<T>(ct.Value);\n            else\r\n                return task.WithCancellationInternal(ct.Value);\r\n        }\r\n\r\n\r\n        private static readonly Action<object> s_cancellationRegistration =\r\n            s => ((TaskCompletionSource<bool>)s).TrySetResult(true);\r\n\r\n        private static async Task<T> WithCancellationInternal<T>(this Task<T> task, CancellationToken ct)\r\n        {\r\n            var tcs = new TaskCompletionSource<bool>();\r\n            using (ct.Register(s_cancellationRegistration, tcs))\r\n            {\r\n                if (task != await Task.WhenAny(task, tcs.Task))\n                {\n                    throw new TaskCanceledException(task);\n                }\n            }\r\n            return await task;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.Essentials/paket.references",
    "content": "Aardvark.Build\nSystem.Collections.Immutable"
  },
  {
    "path": "src/Aardvark.Base.Essentials/paket.template",
    "content": "type project\nid Aardvark.Base.Essentials\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks>\r\n    <AssemblyName>Aardvark.Base.FSharp</AssemblyName>\r\n    <OutputType>Library</OutputType>\r\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\r\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n    <WarnOn>3389;3390;3395</WarnOn>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug\\</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"Utilities\\Logging.fs\" />\r\n    <Compile Include=\"Utilities\\Interop\\FSLibExtensions.fs\" />\r\n    <Compile Include=\"Utilities\\Interop\\Dictionary.fs\" />\r\n    <Compile Include=\"Utilities\\Interop\\Symbol.fs\" />\r\n    <Compile Include=\"Utilities\\Interop\\String.fs\" />\r\n    <Compile Include=\"Utilities\\Interop\\SortedSet.fs\" />\r\n    <Compile Include=\"Utilities\\Interop\\HashSet.fs\" />\r\n    <Compile Include=\"Utilities\\Interop\\CSharpList.fs\" />\r\n    <Compile Include=\"Utilities\\Interop\\ArraySegment.fs\" />\r\n    <Compile Include=\"Utilities\\Pickler\\FsPicklerExtensions.fs\" />\r\n    <Compile Include=\"Utilities\\Pickler\\AdaptivePicklers.fs\" />\r\n    <Compile Include=\"Utilities\\Threading.fs\" />\r\n    <Compile Include=\"Utilities\\IO.fs\" />\r\n    <Compile Include=\"Utilities\\Native.fs\" />\r\n    <Compile Include=\"Utilities\\Measures.fs\" />\r\n    <Compile Include=\"Utilities\\Lens.fs\" />\r\n    <Compile Include=\"Utilities\\Monoid.fs\" />\r\n    <Compile Include=\"Utilities\\Monads.fs\" />\r\n    <Compile Include=\"Utilities\\Weak.fs\" />\r\n    <Compile Include=\"Utilities\\PrimitiveValueConverter.fs\" />\r\n    <Compile Include=\"Math\\Math.fs\" />\r\n    <Compile Include=\"Math\\Vectors.fs\" />\r\n    <Compile Include=\"Math\\Matrix.fs\" />\r\n    <Compile Include=\"Math\\SVDM33f.fs\" />\r\n    <Compile Include=\"Math\\AverageWindow.fs\" />\r\n    <Compile Include=\"Math\\Converters.fs\" />\r\n    <Compile Include=\"Datastructures\\Mutable\\FixedSizeArray.fs\" />\r\n    <Compile Include=\"Datastructures\\Mutable\\OrderMaintenance.fs\" />\r\n    <Compile Include=\"Datastructures\\Mutable\\SkipList.fs\" />\r\n    <Compile Include=\"Datastructures\\Mutable\\AVL.fs\" />\r\n    <Compile Include=\"Datastructures\\Mutable\\StableSet.fs\" />\r\n    <Compile Include=\"Datastructures\\Mutable\\ConcurrentHashQueue.fs\" />\r\n    <Compile Include=\"Datastructures\\Mutable\\OrderMaintenanceTrie.fs\" />\r\n    <Compile Include=\"Datastructures\\Mutable\\ReferenceCountingSet.fs\" />\r\n    <Compile Include=\"Datastructures\\Immutable\\MapExt.fs\" />\r\n    <Compile Include=\"Datastructures\\Immutable\\FingerTree.fs\" />\r\n    <None Include=\"Datastructures\\Immutable\\RangeSet_template.fs\" />\r\n    <Compile Include=\"Datastructures\\Immutable\\RangeSet_auto.fs\" />\r\n    <Compile Include=\"Datastructures\\Immutable\\Graph.fs\" />\r\n    <Compile Include=\"Datastructures\\Geometry\\Boundable.fs\" />\r\n    <Compile Include=\"Datastructures\\Geometry\\KdTree.fs\" />\r\n    <Compile Include=\"Datastructures\\Geometry\\Bvh.fs\" />\r\n    <Compile Include=\"Algorithms\\PolygonSimplification.fs\" />\r\n    <Compile Include=\"Color\\ColorBrewer.fs\" />\r\n    <Compile Include=\"Color\\ColorBrewerSchemes.fs\" />\r\n    <None Include=\"color\\ColorBrewerSchemes.fsx\" />\r\n    <None Include=\"Reflection\\TypeMeta_template.fs\" />\r\n    <Compile Include=\"Reflection\\TypeMeta_auto.fs\" />\r\n    <Compile Include=\"Reflection\\TypeInfo.fs\" />\r\n    <Compile Include=\"Reflection\\FunctionReflection.fs\" />\r\n    <Compile Include=\"Reflection\\Formatf.fs\" />\r\n    <Compile Include=\"Reflection\\UnmanagedFunctions.fs\" />\r\n    <Compile Include=\"Reflection\\Multimethod.fs\" />\r\n    <Compile Include=\"Reflection\\IL.fs\" />\r\n    <Compile Include=\"Reflection\\Quotations.fs\" />\r\n    <Compile Include=\"Reflection\\TypeBuilder.fs\" />\r\n    <Compile Include=\"Reflection\\ReflectionExtensions.fs\" />\r\n    <Compile Include=\"Runtime\\DynamicLinker.fs\" />\r\n    <Compile Include=\"Runtime\\Assembler.fs\" />\r\n    <Compile Include=\"Runtime\\WeakTable.fs\" />\r\n    <Compile Include=\"Runtime\\NativeMemory.fs\" />\r\n    <Compile Include=\"Runtime\\Fragments.fs\" />\r\n    <Compile Include=\"Runtime\\CustomSchedulers.fs\" />\r\n    <Compile Include=\"Runtime\\Caches.fs\" />\r\n    <Compile Include=\"Native\\BlobStore.fs\" />\r\n    <Compile Include=\"Native\\Pointer.fs\" />\r\n    <Compile Include=\"Native\\Memory.fs\" />\r\n    <Compile Include=\"Native\\FileTable.fs\" />\r\n    <Compile Include=\"Native\\Manager.fs\" />\r\n    <Compile Include=\"Native\\Store.fs\" />\r\n    <Compile Include=\"Ag.fs\" />\r\n    <None Include=\"paket.references\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Ag.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Runtime.CompilerServices\nopen System.Collections.Generic\nopen Aardvark.Base\nopen System.Reflection\nopen System.Runtime.InteropServices\n\n#nowarn \"1337\"\n\n[<AttributeUsage(AttributeTargets.Struct ||| AttributeTargets.Class ||| AttributeTargets.Method)>]\ntype RuleAttribute() =\n    inherit Attribute()\n\n[<AttributeUsage(AttributeTargets.Method)>]\ntype CacheSynthesizedAttribute() =\n    inherit Attribute()\n\nmodule Ag =\n\n    let internal anyObj = obj()\n\n    let private globalValues = ConditionalWeakTable<obj, Dictionary<string, obj>>()\n\n    [<AutoOpen>]\n    module private TypeHelpers =\n        open Microsoft.FSharp.Reflection\n    \n        let private genRx = System.Text.RegularExpressions.Regex @\"^([^`]*)`[0-9]+$\"\n\n        let withBrackets (str : string) =\n            if str.Contains \" \" && not (str.StartsWith \"(\") then \"(\" + str + \")\"\n            else str\n\n        let rec prettyName (t : Type) : string =\n            if t.IsByRef then\n                let t = prettyName (t.GetElementType())\n                sprintf \"byref<%s>\" t\n\n            elif t.IsArray then\n                let d = t.GetArrayRank()\n                let t = prettyName (t.GetElementType())\n                if d = 1 then sprintf \"array<%s>\" t\n                else sprintf \"array%dd<%s>\" d t\n\n            elif FSharpType.IsTuple(t) then\n                let elems = FSharpType.GetTupleElements t |> Seq.map (prettyName >> withBrackets) |> String.concat \" * \"\n                if t.IsValueType then sprintf \"struct(%s)\" elems\n                else sprintf \"%s\" elems\n\n            elif FSharpType.IsFunction(t) then\n                let a, b = FSharpType.GetFunctionElements t\n                sprintf \"%s -> %s\" (prettyName a) (prettyName b)\n\n            elif t.IsGenericType then\n                let def = t.GetGenericTypeDefinition().Name\n                let m = genRx.Match def\n                let clean = \n                    if m.Success then m.Groups.[1].Value\n                    else def\n\n                sprintf \"%s<%s>\" clean (t.GetGenericArguments() |> Seq.map prettyName |> String.concat \", \")\n\n            else\n                t.Name     \n\n    type Scope private(parent : option<Scope>, node : obj, childScopes : ConditionalWeakTable<obj, Scope>) =  \n        let inherited = Dictionary<string, obj voption>()\n        let anyChild = Dictionary<string, obj voption>()\n\n        let name = \n            lazy (\n                match parent with\n                | None -> \"Root\"\n                | Some p ->\n                    let self = sprintf \"%s[H%X]\" (prettyName(node.GetType())) (node.GetHashCode())\n                    p.Name + \"/\" + self\n            )\n\n        [<ThreadStatic; DefaultValue>]\n        static val mutable private CurrentScope_ : option<Scope>\n\n        static let root =\n            Scope(None, null, ConditionalWeakTable<obj, Scope>())\n\n        static member internal CurrentScope\n            with get() = Scope.CurrentScope_\n            and set v = Scope.CurrentScope_ <- v\n\n        member x.Node = node\n        member x.Parent = parent\n\n        member private x.TryGetAnyChildValue(name : string) =\n            lock inherited (fun () ->\n                match anyChild.TryGetValue(name) with\n                | (true, v) -> ValueSome v\n                | _ -> ValueNone\n            )\n\n        static member internal Pseudo(node : obj, childScope : Scope) =\n            let cwt = ConditionalWeakTable<obj, Scope>()\n            cwt.Add(childScope.Node, childScope)\n            Scope(None, node, cwt)\n\n        member internal x.SetInherited(name : string, value : obj voption) =\n            lock inherited (fun () ->\n                inherited.[name] <- value\n            )\n\n        member internal x.SetInheritedForChild(child : obj, name : string, value : obj voption) =\n            lock inherited (fun () ->\n                if child = anyObj then\n                    anyChild.[name] <- value\n                else\n                    let c = x.GetChildScope(child)\n                    c.SetInherited(name, value)\n            )\n\n        member private x.TryGetGlobalValue(name : string) =\n            match lock globalValues (fun () -> globalValues.TryGetValue(node)) with\n            | (true, d) ->\n                match lock d (fun () -> d.TryGetValue(name)) with\n                | (true, v) -> \n                    ValueSome v\n                | _ -> \n                    ValueNone\n            | _ ->\n                ValueNone\n                \n\n        member internal x.Locked (action : unit -> 'T) =\n            lock inherited action\n            \n\n        member internal x.Enter () =\n            System.Threading.Monitor.Enter inherited\n\n            \n        member internal x.Exit () =\n            if System.Threading.Monitor.IsEntered inherited then\n                System.Threading.Monitor.Exit inherited\n\n\n        member internal x.TryGetCacheValue(name : string) =\n            lock inherited (fun () ->\n                match inherited.TryGetValue name with\n                | (true, v) -> ValueSome v\n                | _ -> ValueNone\n            )\n\n        member internal x.SetCacheValue(name : string, value : obj voption) =\n            lock inherited (fun () ->\n                inherited.[name] <- value\n            )\n\n        member internal x.GetOrCreateCache(name : string, create : string -> 'a voption) =\n            lock inherited (fun () ->\n                match inherited.TryGetValue name with\n                | (true, v) -> \n                    match v with\n                    | ValueSome (:? 'a as v) -> ValueSome v\n                    | _ -> ValueNone\n                | _ ->\n                    let res = create name\n                    match res with\n                    | ValueSome v -> inherited.[name] <- ValueSome (v :> obj)\n                    | ValueNone -> inherited.[name] <- ValueNone\n                    res\n            )\n\n        member internal x.TryGetInheritedCache(name : string) : obj voption voption =\n            lock inherited (fun () ->\n                match x.TryGetGlobalValue(name) with\n                | ValueSome v -> ValueSome (ValueSome v)\n                | ValueNone ->\n                    match inherited.TryGetValue name with\n                    | (true, v) -> ValueSome v\n                    | _ ->\n                        match parent with\n                        | Some p ->\n                            match p.TryGetAnyChildValue(name) with\n                            | ValueSome v ->\n                                inherited.[name] <- v\n                                ValueSome v\n                            | ValueNone ->\n                                ValueNone\n                        | None ->\n                            ValueNone\n            )\n\n\n        member x.Name : string =\n            name.Value\n\n        override x.ToString() =\n            name.Value\n\n        /// the root scope\n        static member Root = root\n\n        /// get a (possibly cached) child scope for the given node\n        member x.GetChildScope<'a when 'a : not struct>(node : 'a) : Scope =\n            lock childScopes (fun () ->\n                if typeof<'a>.IsValueType then\n                    Scope(Some x, node :> obj, ConditionalWeakTable<obj, Scope>())\n                else\n                    match childScopes.TryGetValue(node :> obj) with\n                    | (true, s) -> s\n                    | _ ->\n                        let s = Scope(Some x, node :> obj, ConditionalWeakTable<obj, Scope>())\n                        childScopes.Add(node :> obj, s)\n                        s\n            )\n            \n        /// attach a global inherited value to a node (overrides any other inheritance mechanisms).\n        static member SetGlobalValue<'a when 'a : not struct>(node : 'a, name : string, value : obj) : unit =\n            let dict =\n                lock globalValues (fun () ->\n                    match globalValues.TryGetValue node with\n                    | (true, d) -> d\n                    | _ -> \n                        let d = Dictionary()\n                        globalValues.Add(node, d)\n                        d\n                )\n            lock dict (fun () ->\n                dict.[name] <- value\n            )\n\n    type Root<'a>(child : 'a) =\n        member x.Child = child\n\n    [<AutoOpen>]\n    module private Helpers =\n        open System.Reflection.Emit\n\n        type NewRootDelegate = delegate of obj -> obj\n        type SynDelegateStatic = delegate of obj * Scope -> obj\n        type SynDelegateInstance = delegate of obj * obj * Scope -> obj\n        type InhDelegateStatic = delegate of obj * Scope -> unit\n        type InhDelegateInstance = delegate of obj * obj * Scope -> unit\n\n        \n        [<StructuredFormatDisplay(\"{AsString}\")>]\n        type InheritMethod(mi : MethodInfo, invoke : obj -> Scope -> unit) =\n            member x.MethodInfo = mi\n            member x.Invoke = invoke\n\n            member private x.AsString = x.ToString()\n            override x.ToString() =\n                let decl = prettyName mi.DeclaringType\n                let nodeType = prettyName (mi.GetParameters().[0].ParameterType)\n                sprintf \"%s.%s(node : %s, _)\" decl mi.Name nodeType\n                \n        [<StructuredFormatDisplay(\"{AsString}\")>]\n        type SynMethod(mi : MethodInfo, invoke : obj -> Scope -> obj) =\n            let cache = mi.GetCustomAttributes<CacheSynthesizedAttribute>() |> Seq.isEmpty |> not\n\n            member x.MethodInfo = mi\n            member x.Invoke = invoke\n            member x.Cache = cache\n\n            member private x.AsString = \n                x.ToString()\n\n            override x.ToString() =\n                let decl = prettyName mi.DeclaringType\n                let ret = prettyName mi.ReturnType\n                let nodeType = prettyName (mi.GetParameters().[0].ParameterType)\n                sprintf \"%s %s.%s(node : %s, _)\" ret decl mi.Name nodeType\n\n        let createSynMethod (self : obj) (mi : MethodInfo) (nodeType : Type) : SynMethod =\n            let name = sprintf \"Syn%s_%s\" mi.Name nodeType.Name\n            let dyn = \n                DynamicMethod(\n                    name,\n                    MethodAttributes.Public ||| MethodAttributes.Static,\n                    CallingConventions.Standard,\n                    typeof<obj>,\n                    [| \n                        if not mi.IsStatic then yield typeof<obj>\n                        yield typeof<obj>\n                        yield typeof<Scope>\n                    |],\n                    typeof<Scope>,\n                    true\n                )\n\n            let il = dyn.GetILGenerator()\n\n            if mi.IsStatic then\n                il.Emit(OpCodes.Ldarg, 0)\n                if nodeType.IsValueType then \n                    il.Emit(OpCodes.Unbox, nodeType)\n                    il.Emit(OpCodes.Ldind_Ref)\n\n                il.Emit(OpCodes.Ldarg, 1)\n                il.EmitCall(OpCodes.Call, mi, null)\n                if mi.ReturnType.IsValueType then il.Emit(OpCodes.Box, mi.ReturnType)\n                il.Emit(OpCodes.Ret)\n\n                let del = dyn.CreateDelegate(typeof<SynDelegateStatic>) |> unbox<SynDelegateStatic>\n                SynMethod(mi, fun (node : obj) (scope : Scope) -> del.Invoke(node, scope))\n            else\n                il.Emit(OpCodes.Ldarg, 0)\n                if mi.DeclaringType.IsValueType then \n                    il.Emit(OpCodes.Unbox, mi.DeclaringType)\n                    il.Emit(OpCodes.Ldind_Ref)\n\n                il.Emit(OpCodes.Ldarg, 1)\n                if nodeType.IsValueType then \n                    il.Emit(OpCodes.Unbox, nodeType)\n                    il.Emit(OpCodes.Ldind_Ref)\n\n                il.Emit(OpCodes.Ldarg, 2)\n\n                if mi.IsVirtual then il.EmitCall(OpCodes.Callvirt, mi, null)\n                else il.EmitCall(OpCodes.Call, mi, null)\n\n                if mi.ReturnType.IsValueType then il.Emit(OpCodes.Box, mi.ReturnType)\n                il.Emit(OpCodes.Ret)\n                \n                let del = dyn.CreateDelegate(typeof<SynDelegateInstance>) |> unbox<SynDelegateInstance>\n                SynMethod(mi, fun (node : obj) (scope : Scope) -> del.Invoke(self, node, scope))\n\n        let createInhMethod (self : obj) (mi : MethodInfo) (nodeType : Type) : InheritMethod =\n            let name = sprintf \"Inh%s_%s\" mi.Name nodeType.Name\n            let dyn = \n                DynamicMethod(\n                    name,\n                    MethodAttributes.Public ||| MethodAttributes.Static,\n                    CallingConventions.Standard,\n                    typeof<System.Void>,\n                    [| \n                        if not mi.IsStatic then yield typeof<obj>\n                        yield typeof<obj>\n                        yield typeof<Scope>\n                    |],\n                    typeof<Scope>,\n                    true\n                )\n\n            let il = dyn.GetILGenerator()\n\n            if mi.IsStatic then\n                il.Emit(OpCodes.Ldarg, 0)\n                if nodeType.IsValueType then \n                    il.Emit(OpCodes.Unbox, nodeType)\n                    il.Emit(OpCodes.Ldind_Ref)\n\n                il.Emit(OpCodes.Ldarg, 1)\n                il.EmitCall(OpCodes.Call, mi, null)\n                il.Emit(OpCodes.Ret)\n\n                let del = dyn.CreateDelegate(typeof<InhDelegateStatic>) |> unbox<InhDelegateStatic>\n                InheritMethod(mi, fun (node : obj) (scope : Scope) -> del.Invoke(node, scope))\n            else\n                il.Emit(OpCodes.Ldarg, 0)\n                if mi.DeclaringType.IsValueType then \n                    il.Emit(OpCodes.Unbox, mi.DeclaringType)\n                    il.Emit(OpCodes.Ldind_Ref)\n\n                il.Emit(OpCodes.Ldarg, 1)\n                if nodeType.IsValueType then \n                    il.Emit(OpCodes.Unbox, nodeType)\n                    il.Emit(OpCodes.Ldind_Ref)\n\n                il.Emit(OpCodes.Ldarg, 2)\n\n                if mi.IsVirtual then il.EmitCall(OpCodes.Callvirt, mi, null)\n                else il.EmitCall(OpCodes.Call, mi, null)\n\n                il.Emit(OpCodes.Ret)\n                \n                let del = dyn.CreateDelegate(typeof<InhDelegateInstance>) |> unbox<InhDelegateInstance>\n                InheritMethod(mi, fun (node : obj) (scope : Scope) -> del.Invoke(self, node, scope))\n\n        let private rootCreators = System.Collections.Concurrent.ConcurrentDictionary<Type, obj -> obj>()\n\n        let getRootCreator (t : Type) =\n            rootCreators.GetOrAdd(t, System.Func<Type,_>(fun nodeType ->\n                let name = sprintf \"NewRoot%s\" nodeType.Name\n\n                let res = typedefof<Root<_>>.MakeGenericType [| nodeType |]\n                let ctor = res.GetConstructor([| nodeType |])\n                let dyn = \n                    DynamicMethod(\n                        name,\n                        MethodAttributes.Public ||| MethodAttributes.Static,\n                        CallingConventions.Standard,\n                        typeof<obj>,\n                        [| \n                            typeof<obj>\n                        |],\n                        typeof<obj>,\n                        true\n                    )\n                let il = dyn.GetILGenerator()\n                il.Emit(OpCodes.Ldarg, 0)\n                il.Emit(OpCodes.Newobj, ctor)\n                il.Emit(OpCodes.Ret)\n\n                let del = dyn.CreateDelegate(typeof<NewRootDelegate>) |> unbox<NewRootDelegate>\n                del.Invoke\n            ))\n\n\n\n\n        let private instances = ConcurrentDict<Type, obj voption>(Dict())\n\n        let tryCreateInstance (t : Type) =\n            instances.GetOrCreate(t, fun t ->\n                let ctor = t.GetConstructor(BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Instance, Type.DefaultBinder, [||], null)\n                if isNull ctor then \n                    ValueNone\n                else \n                    let v = ctor.Invoke([||])\n                    ValueSome v\n            )\n\n        let isSynMethod (mi : MethodInfo) =\n            let pars = mi.GetParameters()\n            if pars.Length = 2 && mi.ReturnType <> typeof<System.Void> && mi.ReturnType <> typeof<unit> then\n                pars.[1].ParameterType.IsAssignableFrom typeof<Scope>\n            else\n                false\n\n        let isInhMethod (mi : MethodInfo) =\n            let pars = mi.GetParameters()\n            if pars.Length = 2 && (mi.ReturnType = typeof<System.Void> || mi.ReturnType = typeof<unit>) then\n                pars.[1].ParameterType.IsAssignableFrom typeof<Scope>\n            else\n                false\n\n        type RuleTable() = \n            let all =\n                let semTypes =\n                    Introspection.GetAllTypesWithAttribute<RuleAttribute>()\n                    |> Seq.collect (fun struct (t,_) -> t.GetMethods(BindingFlags.Static ||| BindingFlags.Instance ||| BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.DeclaredOnly))\n                let semMeths = \n                    Introspection.GetAllMethodsWithAttribute<RuleAttribute>()\n                    |> Seq.map (fun struct (m,_) -> m)\n\n                Seq.append semTypes semMeths \n                |> Seq.filter (fun m -> \n                    let decl = m.DeclaringType\n                    let ps = m.GetParameters()\n\n                    let generated = m.GetCustomAttribute<System.Runtime.CompilerServices.CompilerGeneratedAttribute>()\n\n                    if not (isNull generated) then\n                        false\n                    elif decl.ContainsGenericParameters then\n                        Log.warn \"unexpected generic rule-type: %A\" decl\n                        false\n                    elif ps.Length <> 2 || (ps.Length = 2 && ps.[1].ParameterType <> typeof<Scope>) then\n                        Log.warn \"unexpected rule: %A\" m\n                        false\n                    elif not m.IsStatic then\n                        let ctor = decl.GetConstructor(BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Instance, Type.DefaultBinder, [||], null)\n                        if isNull ctor then\n                            Log.warn \"cannot construct rule type: %A\" decl\n                            false\n                        else\n                            true\n                    else\n                        true\n                )\n                |> Seq.toArray\n\n            let synRules : Dictionary<string, MethodInfo[]> =\n                all\n                |> Seq.filter isSynMethod\n                |> Seq.groupBy _.Name\n                |> Seq.map (fun (g, meths) -> g, meths |> Seq.toArray)\n                |> Dictionary.ofSeq\n\n            let inhRules : Dictionary<string, MethodInfo[]> =\n                all\n                |> Seq.filter isInhMethod\n                |> Seq.groupBy _.Name\n                |> Seq.map (fun (g, meths) -> g, meths |> Seq.toArray)\n                |> Dictionary.ofSeq\n\n            let synCache = ConcurrentDict(Dict<string * Type * Type, SynMethod voption>())\n            let inhCache = ConcurrentDict(Dict<string * Type, InheritMethod voption>())\n\n            member x.TryGetSynRule(name : string, nodeType : Type, expectedType : Type) : SynMethod voption =\n                synCache.GetOrCreate((name, nodeType, expectedType), fun (name, nodeType, expectedType) ->\n                    match synRules.TryGetValue name with\n                    | (true, rules) ->\n                        let argTypes = [| nodeType; typeof<Scope> |]\n                        let applicable = rules |> Array.choose (fun m -> m.TrySpecialize(argTypes, expectedType))\n\n                        if applicable.Length = 0 then\n                            ValueNone\n                        elif applicable.Length = 1 then\n                            let m = applicable.[0]\n                        \n                            let instance =\n                                if m.IsStatic then ValueSome null\n                                else tryCreateInstance m.DeclaringType\n                            match instance with\n                            | ValueSome instance -> createSynMethod instance m nodeType |> ValueSome\n                            | ValueNone -> ValueNone\n                        else\n                            let mb = applicable |> Array.map (fun m -> m :> MethodBase)\n                            try\n                                let selected = \n                                    Type.DefaultBinder.SelectMethod(\n                                        BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Instance ||| BindingFlags.Static,\n                                        mb, argTypes, null\n                                    )\n                                match selected with\n                                | null -> ValueNone\n                                | :? MethodInfo as m ->\n                                    let instance =\n                                        if m.IsStatic then ValueSome null\n                                        else tryCreateInstance m.DeclaringType\n                                    match instance with\n                                    | ValueSome instance ->createSynMethod instance m nodeType |> ValueSome\n                                    | ValueNone -> ValueNone\n                                | _ -> \n                                    ValueNone\n                            with _ ->\n                                ValueNone\n                    | _ ->\n                        ValueNone\n                )\n         \n            member x.TryGetInhRule(name : string, nodeType : Type) : InheritMethod voption =\n                inhCache.GetOrCreate((name, nodeType), fun (name, nodeType) ->\n                    match inhRules.TryGetValue name with\n                    | (true, rules) ->\n                        let argTypes = [| nodeType; typeof<Scope> |]\n                        let applicable = rules |> Array.choose (fun m -> m.TrySpecialize(argTypes, typeof<System.Void>))\n\n                        if applicable.Length = 0 then\n                            ValueNone\n                        elif applicable.Length = 1 then\n                            let m = applicable.[0]\n                        \n                            let instance =\n                                if m.IsStatic then ValueSome null\n                                else tryCreateInstance m.DeclaringType\n                            match instance with\n                            | ValueSome instance -> createInhMethod instance m nodeType |> ValueSome\n                            | ValueNone -> ValueNone\n                        else\n                            let mb = applicable |> Array.map (fun m -> m :> MethodBase)\n                            try\n                                let selected = \n                                    Type.DefaultBinder.SelectMethod(\n                                        BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Instance ||| BindingFlags.Static,\n                                        mb, argTypes, null\n                                    )\n                                match selected with\n                                | null -> ValueNone\n                                | :? MethodInfo as m ->\n                                    let instance =\n                                        if m.IsStatic then ValueSome null\n                                        else tryCreateInstance m.DeclaringType\n                                    match instance with\n                                    | ValueSome instance -> createInhMethod instance m nodeType |> ValueSome\n                                    | ValueNone -> ValueNone\n                                | _ -> \n                                    ValueNone\n                            with _ ->\n                                ValueNone\n                    | _ ->\n                        ValueNone\n                )\n\n        let table = lazy (RuleTable())\n\n    let hasSynRule (nodeType : Type) (expected : Type) (name : string) =\n        match table.Value.TryGetSynRule(name, nodeType, expected) with\n        | ValueSome _ -> true\n        | ValueNone -> false\n\n    let rec internal runinh (scope : Scope) (name : string) =\n        match scope.TryGetInheritedCache(name) with\n        | ValueSome v ->\n            v\n        | ValueNone ->\n            match scope.Parent with\n            | Some p ->\n                if isNull p.Node then\n                    let self = scope.Node.GetType().GetBaseTypesAndSelf()\n\n                    let meth =\n                        self |> Array.tryPickV (fun t ->\n                            let pseudo = typedefof<Root<_>>.MakeGenericType [| t |]\n                            match table.Value.TryGetInhRule(name, pseudo) with\n                            | ValueSome m -> ValueSome (t, m)\n                            | ValueNone -> ValueNone\n                        )\n                            \n                    match meth with\n                    | ValueSome (t, inh) ->\n                        let root = getRootCreator t scope.Node\n                        let pseudo = Scope.Pseudo(root, scope)\n                        let o = Scope.CurrentScope\n                        Scope.CurrentScope <- Some pseudo\n                        inh.Invoke root pseudo\n                        Scope.CurrentScope <- o\n                        match scope.TryGetInheritedCache(name) with\n                        | ValueSome v ->\n                            v\n                        | ValueNone ->\n                            Log.warn \"[Ag] bad root inherit method: %A\" inh\n                            ValueNone\n                    | ValueNone ->\n                        // root\n                        ValueNone\n                else\n\n                    match table.Value.TryGetInhRule(name, p.Node.GetType()) with\n                    | ValueSome inh ->\n                        let o = Scope.CurrentScope\n                        Scope.CurrentScope <- Some p\n                        inh.Invoke p.Node p\n                        Scope.CurrentScope <- o\n                        match scope.TryGetInheritedCache(name) with\n                        | ValueSome v -> v\n                        | ValueNone ->\n                            Log.warn \"[Ag] bad inherit method: %A\" inh\n                            ValueNone\n                    | ValueNone ->\n                        let res = runinh p name\n                        scope.SetInherited(name, res)\n                        res\n            | None ->\n                ValueNone\n\n    let internal syn (node : 'a) (scope : Scope) (name : string) (expectedType : Type) =\n        if isNull (node :> obj) then \n            ValueNone\n        else\n            let cacheName = \"syn.\" + name\n            scope.Enter()\n            try\n                let t = node.GetType()\n                match table.Value.TryGetSynRule(name, t, expectedType)  with\n                | ValueSome syn ->\n                    let newScope = scope.GetChildScope(node)\n                    if syn.Cache then\n                        match newScope.TryGetCacheValue cacheName with\n                        | ValueSome v ->\n                            v\n                        | ValueNone ->\n                            let result = syn.Invoke (node :> obj) newScope |> ValueSome\n                            newScope.SetCacheValue(cacheName, result)\n                            result\n                    else\n                        scope.Exit()\n                        syn.Invoke (node :> obj) newScope |> ValueSome\n\n                | _ ->\n                    ValueNone\n                finally\n                    scope.Exit()\n\n   \n    \n    type System.Object with\n        member x.AllChildren = anyObj\n\n    let internal set<'a, 'b when 'a : not struct> (target : 'a) (name : string) (value : 'b) =\n        let node = \n            match target :> obj with\n            | :? FSharp.Data.Adaptive.IAdaptiveValue as v -> v.GetValueUntyped(FSharp.Data.Adaptive.AdaptiveToken.Top)\n            | n -> n\n        match Scope.CurrentScope with\n        | Some s -> \n            // classic aval unpacking here\n            s.SetInheritedForChild(node, name, ValueSome (value :> obj))\n        | None ->\n            Scope.SetGlobalValue(node, name, value :> obj)\n\n    let (?<-) (target : 'a) (name : string) (value : 'b) = set target name value\n\n    type Operators private() =\n        static member Get(scope : Scope, name : string) : 'a =\n            match runinh scope name with\n            | ValueSome (:? 'a as v) -> v\n            | _ -> failwithf \"[Ag] could not get inh attribute %s in scope %A\" name scope\n\n        static member Get(node : 'a, name : string) : Scope -> 'b =\n            fun s -> \n                match syn (node :> obj) s name typeof<'b> with\n                | ValueSome (:? 'b as v) ->\n                    v\n                | ValueSome v ->\n                    failwithf \"[Ag] invalid result for syn attribute %s on node %A: %A\" name node v\n                | ValueNone ->\n                    failwithf \"[Ag] could not get syn attribute %s on node %A\" name node\n\n    let inline private opAux (_d : 'd) (a : 'a) (b : 'b) : 'c =\n        ((^a or ^b or ^d) : (static member Get : ^a * ^b -> ^c) (a, b))\n\n    let inline (?) a b = opAux Unchecked.defaultof<Operators> a b\n\n\n[<AbstractClass; Sealed; Extension>]\ntype AgScopeExtensions private() =\n    [<Extension>]\n    static member TryGetInherited(this : Ag.Scope, name : string) =\n        Ag.runinh this name |> ValueOption.toOption\n\n    [<Extension>]\n    static member TryGetInheritedV(this : Ag.Scope, name : string) =\n        Ag.runinh this name\n        \n    [<Extension>]\n    static member TryGetInherited<'a>(this : Ag.Scope, name : string) =\n        match Ag.runinh this name with\n        | ValueSome (:? 'a as res) -> Some res\n        | _ -> None\n\n    [<Extension>]\n    static member TryGetInheritedV<'a>(this : Ag.Scope, name : string) =\n        match Ag.runinh this name with\n        | ValueSome (:? 'a as res) -> ValueSome res\n        | _ -> ValueNone\n        \n    [<Extension>]\n    static member GetInherted(this : Ag.Scope, name : string) =\n        match Ag.runinh this name with\n        | ValueSome v -> v\n        | ValueNone -> failwithf \"[Ag] could not get inh attribute %s in scope %A\" name this\n        \n    [<Extension>]\n    static member GetInherted<'a>(this : Ag.Scope, name : string) =\n        match Ag.runinh this name with\n        | ValueSome (:? 'a as res) -> res\n        | _ -> failwithf \"[Ag] could not get inh attribute %s in scope %A\" name this\n        \n    [<Extension>]\n    static member TryGetSynthesized<'a>(node : obj, name : string, scope : Ag.Scope) =\n        match Ag.syn node scope name typeof<'a> with\n        | ValueSome (:? 'a as res) -> Some res\n        | _ -> None\n\n    [<Extension>]\n    static member TryGetSynthesizedV<'a>(node : obj, name : string, scope : Ag.Scope) =\n        match Ag.syn node scope name typeof<'a> with\n        | ValueSome (:? 'a as res) -> ValueSome res\n        | _ -> ValueNone\n        \n    [<Extension>]\n    static member TryGetSynthesized<'a>(scope : Ag.Scope, name : string) =\n        if isNull scope.Node then failwithf \"[Ag] cannot get syn attribute for scope with no node: %A\" scope\n        match scope.Parent with\n        | Some p -> scope.Node.TryGetSynthesized<'a>(name, p)\n        | None -> scope.Node.TryGetSynthesized<'a>(name, Ag.Scope.Root)\n\n    [<Extension>]\n    static member TryGetSynthesizedV<'a>(scope : Ag.Scope, name : string) =\n        if isNull scope.Node then failwithf \"[Ag] cannot get syn attribute for scope with no node: %A\" scope\n        match scope.Parent with\n        | Some p -> scope.Node.TryGetSynthesizedV<'a>(name, p)\n        | None -> scope.Node.TryGetSynthesizedV<'a>(name, Ag.Scope.Root)\n\n    [<Extension>]\n    static member GetSynthesized<'a>(node : obj, name : string, scope : Ag.Scope) =\n        match Ag.syn node scope name typeof<'a> with\n        | ValueSome (:? 'a as res) -> res\n        | _ -> failwithf \"[Ag] could not get syn attribute %s on node %A\" name node\n        \n    [<Extension>]\n    static member TryGetAttributeValue(scope : Ag.Scope, name : string) =\n        match scope.TryGetSynthesized(name) with\n        | None -> scope.TryGetInherited(name)\n        | r -> r\n\n    [<Extension>]\n    static member TryGetAttributeValueV(scope : Ag.Scope, name : string) =\n        match scope.TryGetSynthesizedV(name) with\n        | ValueNone -> scope.TryGetInheritedV(name)\n        | r -> r\n\n    [<Extension>]\n    static member TryGetAttributeValue<'a>(scope : Ag.Scope, name : string) =\n        match scope.TryGetSynthesized<'a>(name) with\n        | None -> scope.TryGetInherited<'a>(name)\n        | r -> r\n\n    [<Extension>]\n    static member TryGetAttributeValueV<'a>(scope : Ag.Scope, name : string) =\n        match scope.TryGetSynthesizedV<'a>(name) with\n        | ValueNone -> scope.TryGetInheritedV<'a>(name)\n        | r -> r"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Algorithms/PolygonSimplification.fs",
    "content": "﻿namespace Aardvark.Base\n\n\nopen System.Runtime.CompilerServices\n\n[<AbstractClass; Sealed; Extension>]\ntype PolygonExtensions private() =\n    [<Extension>]\n    static member Simplify(x : Polygon2d, eps : float) =\n        if eps <= 0.0 || x.PointCount <= 3 then\n            x\n        else\n            // find two points with maximum curvature\n            let mutable angle0 = 0.0\n            let mutable angle1 = 0.0\n            let mutable id0 = -1\n            let mutable id1 = -1\n\n            let mutable i0 = x.PointCount - 2\n            let mutable i1 = x.PointCount - 1\n            let mutable d01 = Vec.normalize (x.[i1] - x.[i0])\n            for i2 in 0 .. x.PointCount - 1 do\n                let d12 = Vec.normalize (x.[i2] - x.[i1])\n                let angle = Vec.AngleBetween(d01, d12) |> abs\n\n                if angle > angle0 then\n                    angle1 <- angle0\n                    id1 <- id0\n                    angle0 <- angle\n                    id0 <- i1\n                elif angle > angle1 then\n                    angle1 <- angle\n                    id1 <- i1\n\n                i0 <- i1\n                i1 <- i2\n                d01 <- d12\n\n            // if there are at least two points with curvature > 0\n            if id0 >= 0 && id1 >= 0 then\n                let inline iter (s : int) (e : int) (action : int -> unit) =\n                    let mutable i = (s + x.PointCount) % x.PointCount\n                    let e = (e + 1) % x.PointCount\n                    while i <> e do\n                        action i\n                        i <- i + 1\n                        if i >= x.PointCount then i <- i - x.PointCount\n\n                let rec simplify (set : System.Collections.Generic.SortedSet<int>) (l : int) (r : int) =\n                    set.Add l |> ignore\n                    if l <> r then\n                        let p0 = x.[l]\n                        let p1 = x.[r]\n                        let d = Vec.normalize (p1 - p0)\n                        let n = V2d(-d.Y, d.X)\n\n                        // find the worst point (max height)\n                        let mutable hMax = 0.0\n                        let mutable max = -1\n                        iter (l+1) (r-1) (fun i ->\n                            let h = Vec.dot n (x.[i] - p0) |> abs\n                            if h > hMax then\n                                hMax <- h\n                                max <- i\n                        )\n\n                        // if not within tolerance continue recursively\n                        if hMax > eps then\n                            simplify set l max\n                            simplify set max r\n\n                let set = System.Collections.Generic.SortedSet()\n\n                // simplify both curves\n                simplify set id0 id1\n                simplify set id1 id0\n\n                let arr = Array.zeroCreate set.Count\n                let mutable i = 0\n                for i0 in set do \n                    arr.[i] <- x.[i0]\n                    i <- i + 1\n\n                Polygon2d arr\n            else\n                x\n                \n    [<Extension>]\n    static member Simplify(x : Polygon3d, eps : float) =\n        if eps <= 0.0 || x.PointCount <= 3 then\n            x\n        else\n            // find two points with maximum curvature\n            let mutable angle0 = 0.0\n            let mutable angle1 = 0.0\n            let mutable id0 = -1\n            let mutable id1 = -1\n\n            let mutable i0 = x.PointCount - 2\n            let mutable i1 = x.PointCount - 1\n            let mutable d01 = Vec.normalize (x.[i1] - x.[i0])\n            for i2 in 0 .. x.PointCount - 1 do\n                let d12 = Vec.normalize (x.[i2] - x.[i1])\n                let angle = Vec.AngleBetween(d01, d12) |> abs\n\n                if angle > angle0 then\n                    angle1 <- angle0\n                    id1 <- id0\n                    angle0 <- angle\n                    id0 <- i1\n                elif angle > angle1 then\n                    angle1 <- angle\n                    id1 <- i1\n\n                i0 <- i1\n                i1 <- i2\n                d01 <- d12\n\n            // if there are at least two points with curvature > 0\n            if id0 >= 0 && id1 >= 0 then\n                let inline iter (s : int) (e : int) (action : int -> unit) =\n                    let mutable i = (s + x.PointCount) % x.PointCount\n                    let e = (e + 1) % x.PointCount\n                    while i <> e do\n                        action i\n                        i <- i + 1\n                        if i >= x.PointCount then i <- i - x.PointCount\n\n                let rec simplify (set : System.Collections.Generic.SortedSet<int>) (l : int) (r : int) =\n                    set.Add l |> ignore\n                    if l <> r then\n                        let p0 = x.[l]\n                        let p1 = x.[r]\n                        let d = Vec.normalize (p1 - p0)\n                        let n = V2d(-d.Y, d.X)\n\n                        // find the worst point (max height)\n                        let mutable hMax = 0.0\n                        let mutable max = -1\n                        iter (l+1) (r-1) (fun i ->\n                            let h = x.[i].DistanceToInfiniteLine(p0, p1)\n                            if h > hMax then\n                                hMax <- h\n                                max <- i\n                        )\n\n                        // if not within tolerance continue recursively\n                        if hMax > eps then\n                            simplify set l max\n                            simplify set max r\n\n                let set = System.Collections.Generic.SortedSet()\n\n                // simplify both curves\n                simplify set id0 id1\n                simplify set id1 id0\n\n                let arr = Array.zeroCreate set.Count\n                let mutable i = 0\n                for i0 in set do \n                    arr.[i] <- x.[i0]\n                    i <- i + 1\n\n                Polygon3d arr\n            else\n                x\n\n        \n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Color/ColorBrewer.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\n\n/// Brewer color schemes designed for choropleth map visualizations.\nmodule ColorBrewer =\n\n    [<Flags>]\n    type PaletteUsage =\n        | None       = 0\n\n        /// Does not confuse people with red-green color blindness.\n        | ColorBlind = 1\n\n        /// Suitable for desktop color printing.\n        | Print      = 2\n\n        /// Suitable for viewing on a laptop LCD display.\n        /// Small, portable LCD monitors tend to wash-out colors which results in noticeable differences from computer-to-computer.\n        | LCD        = 4\n\n        /// Withstands black and white photocopying.\n        /// Diverging schemes can not be photocopied successfully.\n        /// Differences in lightness should be preserved with sequential schemes.\n        | PhotoCopy  = 8\n\n    [<Struct>]\n    type Palette =\n        {\n            /// The color values of the palette.\n            Colors : C3b[]\n\n            /// Usage properties of the palette.\n            Usage  : PaletteUsage\n        }\n\n        member inline x.Length =\n            x.Colors.Length\n\n        member inline x.Item (index : int) =\n            x.Colors.[index]\n\n        interface IEnumerable with\n            member x.GetEnumerator() = x.Colors.GetEnumerator()\n\n        interface IEnumerable<C3b> with\n            member x.GetEnumerator() = (x.Colors :> IEnumerable<C3b>).GetEnumerator()\n\n\n    type SchemeType =\n\n        /// Diverging schemes put equal emphasis on mid-range critical values and extremes at both ends of the data range.\n        /// The critical class or break in the middle of the legend is emphasized with light colors and low and high extremes are\n        /// emphasized with dark colors that have contrasting hues.\n        | Diverging   = 0\n\n        /// Qualitative schemes do not imply magnitude differences between legend classes, and hues are used to\n        /// create the primary visual differences between classes. Qualitative schemes are best suited to representing nominal or categorical data.\n        | Qualitative = 1\n\n        /// Sequential schemes are suited to ordered data that progress from low to high.\n        /// Lightness steps dominate the look of these schemes, with light colors for low data values to dark colors for high data values.\n        | Sequential  = 2\n\n    /// A color scheme containing palettes of various size.\n    [<Struct>]\n    type Scheme =\n        {\n            /// Name of the scheme.\n            Name     : Symbol\n\n            /// Type of the scheme.\n            Type     : SchemeType\n\n            /// The palettes of the scheme according to their size.\n            Palettes : MapExt<int, Palette>\n        }\n\n        /// Returns whether the scheme is empty (i.e. has no palettes).\n        member inline x.IsEmpty =\n            x.Palettes.IsEmpty\n\n        /// Size of the smallest palette.\n        member inline x.MinSize =\n            x.Palettes.TryMinKeyV |> ValueOption.defaultValue 0\n\n        /// Size of the largest palette.\n        member inline x.MaxSize =\n            x.Palettes.TryMaxKeyV |> ValueOption.defaultValue 0\n\n        /// Gets the palette with the given size.\n        /// If the scheme is not defined for the requested size, gets the next larger palette.\n        /// Throws an exception if the requested size is greater than the maximum size.\n        member inline x.Item (requestedSize : int) =\n            match x.Palettes |> MapExt.neighboursV requestedSize with\n            | struct (_, ValueSome (struct (_, palette)), _)\n            | struct (_, _, ValueSome (struct (_, palette))) ->\n                palette\n\n            | struct (ValueSome (struct (max, _)), _, _) ->\n                raise <| ArgumentOutOfRangeException(\"requestedSize\", $\"Scheme {x.Name} has a maximum palette size of {max} (requested {requestedSize}).\")\n\n            | struct (ValueNone, ValueNone, ValueNone) ->\n                raise <| ArgumentException($\"Scheme {x.Name} is empty.\")\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module Scheme =\n\n        /// Returns whether the scheme is empty (i.e. has no palettes).\n        let inline isEmpty (scheme : Scheme) =\n            scheme.IsEmpty\n\n        /// Return the size of the smallest palette for the given scheme.\n        let inline minSize (scheme : Scheme) =\n            scheme.MinSize\n\n        /// Return the size of the largest palette for the given scheme.\n        let inline maxSize (scheme : Scheme) =\n            scheme.MaxSize\n\n        /// Gets the palette with the given size.\n        /// If the scheme is not defined for the requested size, gets the next larger palette.\n        /// Throws an exception if the requested size is greater than the maximum size.\n        let inline getPalette (requestedSize : int) (scheme : Scheme) =\n            scheme.[requestedSize]\n\n        /// Returns a new scheme containing only the palettes for which the predicate returns true.\n        let inline filter (predicate : Palette -> bool) (scheme : Scheme) =\n            { scheme with Palettes = scheme.Palettes |> MapExt.filter (fun _ -> predicate) }\n\n        /// Returns a new scheme containing only the palettes with the given usage flags.\n        let inline filterUsage (usage : PaletteUsage) (scheme : Scheme) =\n            scheme |> filter (fun p -> p.Usage &&& usage = usage)"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Color/ColorBrewerSchemes.fs",
    "content": "namespace Aardvark.Base\n\n[<AutoOpen>]\nmodule ColorBrewerSchemes =\n    open ColorBrewer\n\n    /// Brewer color schemes designed for choropleth map visualizations.\n    module ColorBrewer =\n\n        module Scheme =\n\n            /// Diverging schemes put equal emphasis on mid-range critical values and extremes at both ends of the data range.\n            /// The critical class or break in the middle of the legend is emphasized with light colors and low and high extremes are\n            /// emphasized with dark colors that have contrasting hues.\n            module Diverging =\n\n                let Spectral =\n                    {\n                        Name = Sym.ofString \"Spectral\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(252uy,141uy,89uy); C3b(255uy,255uy,191uy); C3b(153uy,213uy,148uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(171uy,221uy,164uy); C3b(43uy,131uy,186uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(255uy,255uy,191uy); C3b(171uy,221uy,164uy)\n                                                C3b(43uy,131uy,186uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(213uy,62uy,79uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,139uy); C3b(230uy,245uy,152uy)\n                                                C3b(153uy,213uy,148uy); C3b(50uy,136uy,189uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(213uy,62uy,79uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,139uy); C3b(255uy,255uy,191uy)\n                                                C3b(230uy,245uy,152uy); C3b(153uy,213uy,148uy); C3b(50uy,136uy,189uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(213uy,62uy,79uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,139uy)\n                                                C3b(230uy,245uy,152uy); C3b(171uy,221uy,164uy); C3b(102uy,194uy,165uy); C3b(50uy,136uy,189uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(213uy,62uy,79uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,139uy)\n                                                C3b(255uy,255uy,191uy); C3b(230uy,245uy,152uy); C3b(171uy,221uy,164uy); C3b(102uy,194uy,165uy)\n                                                C3b(50uy,136uy,189uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(158uy,1uy,66uy); C3b(213uy,62uy,79uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)\n                                                C3b(254uy,224uy,139uy); C3b(230uy,245uy,152uy); C3b(171uy,221uy,164uy); C3b(102uy,194uy,165uy)\n                                                C3b(50uy,136uy,189uy); C3b(94uy,79uy,162uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(158uy,1uy,66uy); C3b(213uy,62uy,79uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)\n                                                C3b(254uy,224uy,139uy); C3b(255uy,255uy,191uy); C3b(230uy,245uy,152uy); C3b(171uy,221uy,164uy)\n                                                C3b(102uy,194uy,165uy); C3b(50uy,136uy,189uy); C3b(94uy,79uy,162uy) |]\n                                }\n\n                            ]\n                    }\n\n                let RdYlGn =\n                    {\n                        Name = Sym.ofString \"RdYlGn\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(252uy,141uy,89uy); C3b(255uy,255uy,191uy); C3b(145uy,207uy,96uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(166uy,217uy,106uy); C3b(26uy,150uy,65uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(255uy,255uy,191uy); C3b(166uy,217uy,106uy)\n                                                C3b(26uy,150uy,65uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(215uy,48uy,39uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,139uy); C3b(217uy,239uy,139uy)\n                                                C3b(145uy,207uy,96uy); C3b(26uy,152uy,80uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(215uy,48uy,39uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,139uy); C3b(255uy,255uy,191uy)\n                                                C3b(217uy,239uy,139uy); C3b(145uy,207uy,96uy); C3b(26uy,152uy,80uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,139uy)\n                                                C3b(217uy,239uy,139uy); C3b(166uy,217uy,106uy); C3b(102uy,189uy,99uy); C3b(26uy,152uy,80uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,139uy)\n                                                C3b(255uy,255uy,191uy); C3b(217uy,239uy,139uy); C3b(166uy,217uy,106uy); C3b(102uy,189uy,99uy)\n                                                C3b(26uy,152uy,80uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(165uy,0uy,38uy); C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)\n                                                C3b(254uy,224uy,139uy); C3b(217uy,239uy,139uy); C3b(166uy,217uy,106uy); C3b(102uy,189uy,99uy)\n                                                C3b(26uy,152uy,80uy); C3b(0uy,104uy,55uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(165uy,0uy,38uy); C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)\n                                                C3b(254uy,224uy,139uy); C3b(255uy,255uy,191uy); C3b(217uy,239uy,139uy); C3b(166uy,217uy,106uy)\n                                                C3b(102uy,189uy,99uy); C3b(26uy,152uy,80uy); C3b(0uy,104uy,55uy) |]\n                                }\n\n                            ]\n                    }\n\n                let RdBu =\n                    {\n                        Name = Sym.ofString \"RdBu\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(239uy,138uy,98uy); C3b(247uy,247uy,247uy); C3b(103uy,169uy,207uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(202uy,0uy,32uy); C3b(244uy,165uy,130uy); C3b(146uy,197uy,222uy); C3b(5uy,113uy,176uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(202uy,0uy,32uy); C3b(244uy,165uy,130uy); C3b(247uy,247uy,247uy); C3b(146uy,197uy,222uy)\n                                                C3b(5uy,113uy,176uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(178uy,24uy,43uy); C3b(239uy,138uy,98uy); C3b(253uy,219uy,199uy); C3b(209uy,229uy,240uy)\n                                                C3b(103uy,169uy,207uy); C3b(33uy,102uy,172uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(178uy,24uy,43uy); C3b(239uy,138uy,98uy); C3b(253uy,219uy,199uy); C3b(247uy,247uy,247uy)\n                                                C3b(209uy,229uy,240uy); C3b(103uy,169uy,207uy); C3b(33uy,102uy,172uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy); C3b(253uy,219uy,199uy)\n                                                C3b(209uy,229uy,240uy); C3b(146uy,197uy,222uy); C3b(67uy,147uy,195uy); C3b(33uy,102uy,172uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy); C3b(253uy,219uy,199uy)\n                                                C3b(247uy,247uy,247uy); C3b(209uy,229uy,240uy); C3b(146uy,197uy,222uy); C3b(67uy,147uy,195uy)\n                                                C3b(33uy,102uy,172uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(103uy,0uy,31uy); C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy)\n                                                C3b(253uy,219uy,199uy); C3b(209uy,229uy,240uy); C3b(146uy,197uy,222uy); C3b(67uy,147uy,195uy)\n                                                C3b(33uy,102uy,172uy); C3b(5uy,48uy,97uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(103uy,0uy,31uy); C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy)\n                                                C3b(253uy,219uy,199uy); C3b(247uy,247uy,247uy); C3b(209uy,229uy,240uy); C3b(146uy,197uy,222uy)\n                                                C3b(67uy,147uy,195uy); C3b(33uy,102uy,172uy); C3b(5uy,48uy,97uy) |]\n                                }\n\n                            ]\n                    }\n\n                let PiYG =\n                    {\n                        Name = Sym.ofString \"PiYG\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(233uy,163uy,201uy); C3b(247uy,247uy,247uy); C3b(161uy,215uy,106uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(208uy,28uy,139uy); C3b(241uy,182uy,218uy); C3b(184uy,225uy,134uy); C3b(77uy,172uy,38uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(208uy,28uy,139uy); C3b(241uy,182uy,218uy); C3b(247uy,247uy,247uy); C3b(184uy,225uy,134uy)\n                                                C3b(77uy,172uy,38uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(197uy,27uy,125uy); C3b(233uy,163uy,201uy); C3b(253uy,224uy,239uy); C3b(230uy,245uy,208uy)\n                                                C3b(161uy,215uy,106uy); C3b(77uy,146uy,33uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(197uy,27uy,125uy); C3b(233uy,163uy,201uy); C3b(253uy,224uy,239uy); C3b(247uy,247uy,247uy)\n                                                C3b(230uy,245uy,208uy); C3b(161uy,215uy,106uy); C3b(77uy,146uy,33uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(197uy,27uy,125uy); C3b(222uy,119uy,174uy); C3b(241uy,182uy,218uy); C3b(253uy,224uy,239uy)\n                                                C3b(230uy,245uy,208uy); C3b(184uy,225uy,134uy); C3b(127uy,188uy,65uy); C3b(77uy,146uy,33uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(197uy,27uy,125uy); C3b(222uy,119uy,174uy); C3b(241uy,182uy,218uy); C3b(253uy,224uy,239uy)\n                                                C3b(247uy,247uy,247uy); C3b(230uy,245uy,208uy); C3b(184uy,225uy,134uy); C3b(127uy,188uy,65uy)\n                                                C3b(77uy,146uy,33uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(142uy,1uy,82uy); C3b(197uy,27uy,125uy); C3b(222uy,119uy,174uy); C3b(241uy,182uy,218uy)\n                                                C3b(253uy,224uy,239uy); C3b(230uy,245uy,208uy); C3b(184uy,225uy,134uy); C3b(127uy,188uy,65uy)\n                                                C3b(77uy,146uy,33uy); C3b(39uy,100uy,25uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(142uy,1uy,82uy); C3b(197uy,27uy,125uy); C3b(222uy,119uy,174uy); C3b(241uy,182uy,218uy)\n                                                C3b(253uy,224uy,239uy); C3b(247uy,247uy,247uy); C3b(230uy,245uy,208uy); C3b(184uy,225uy,134uy)\n                                                C3b(127uy,188uy,65uy); C3b(77uy,146uy,33uy); C3b(39uy,100uy,25uy) |]\n                                }\n\n                            ]\n                    }\n\n                let PRGn =\n                    {\n                        Name = Sym.ofString \"PRGn\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(175uy,141uy,195uy); C3b(247uy,247uy,247uy); C3b(127uy,191uy,123uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(123uy,50uy,148uy); C3b(194uy,165uy,207uy); C3b(166uy,219uy,160uy); C3b(0uy,136uy,55uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(123uy,50uy,148uy); C3b(194uy,165uy,207uy); C3b(247uy,247uy,247uy); C3b(166uy,219uy,160uy)\n                                                C3b(0uy,136uy,55uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(118uy,42uy,131uy); C3b(175uy,141uy,195uy); C3b(231uy,212uy,232uy); C3b(217uy,240uy,211uy)\n                                                C3b(127uy,191uy,123uy); C3b(27uy,120uy,55uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(118uy,42uy,131uy); C3b(175uy,141uy,195uy); C3b(231uy,212uy,232uy); C3b(247uy,247uy,247uy)\n                                                C3b(217uy,240uy,211uy); C3b(127uy,191uy,123uy); C3b(27uy,120uy,55uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(118uy,42uy,131uy); C3b(153uy,112uy,171uy); C3b(194uy,165uy,207uy); C3b(231uy,212uy,232uy)\n                                                C3b(217uy,240uy,211uy); C3b(166uy,219uy,160uy); C3b(90uy,174uy,97uy); C3b(27uy,120uy,55uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(118uy,42uy,131uy); C3b(153uy,112uy,171uy); C3b(194uy,165uy,207uy); C3b(231uy,212uy,232uy)\n                                                C3b(247uy,247uy,247uy); C3b(217uy,240uy,211uy); C3b(166uy,219uy,160uy); C3b(90uy,174uy,97uy)\n                                                C3b(27uy,120uy,55uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(64uy,0uy,75uy); C3b(118uy,42uy,131uy); C3b(153uy,112uy,171uy); C3b(194uy,165uy,207uy)\n                                                C3b(231uy,212uy,232uy); C3b(217uy,240uy,211uy); C3b(166uy,219uy,160uy); C3b(90uy,174uy,97uy)\n                                                C3b(27uy,120uy,55uy); C3b(0uy,68uy,27uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(64uy,0uy,75uy); C3b(118uy,42uy,131uy); C3b(153uy,112uy,171uy); C3b(194uy,165uy,207uy)\n                                                C3b(231uy,212uy,232uy); C3b(247uy,247uy,247uy); C3b(217uy,240uy,211uy); C3b(166uy,219uy,160uy)\n                                                C3b(90uy,174uy,97uy); C3b(27uy,120uy,55uy); C3b(0uy,68uy,27uy) |]\n                                }\n\n                            ]\n                    }\n\n                let RdYlBu =\n                    {\n                        Name = Sym.ofString \"RdYlBu\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(252uy,141uy,89uy); C3b(255uy,255uy,191uy); C3b(145uy,191uy,219uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(171uy,217uy,233uy); C3b(44uy,123uy,182uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(215uy,25uy,28uy); C3b(253uy,174uy,97uy); C3b(255uy,255uy,191uy); C3b(171uy,217uy,233uy)\n                                                C3b(44uy,123uy,182uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(215uy,48uy,39uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,144uy); C3b(224uy,243uy,248uy)\n                                                C3b(145uy,191uy,219uy); C3b(69uy,117uy,180uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(215uy,48uy,39uy); C3b(252uy,141uy,89uy); C3b(254uy,224uy,144uy); C3b(255uy,255uy,191uy)\n                                                C3b(224uy,243uy,248uy); C3b(145uy,191uy,219uy); C3b(69uy,117uy,180uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,144uy)\n                                                C3b(224uy,243uy,248uy); C3b(171uy,217uy,233uy); C3b(116uy,173uy,209uy); C3b(69uy,117uy,180uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy); C3b(254uy,224uy,144uy)\n                                                C3b(255uy,255uy,191uy); C3b(224uy,243uy,248uy); C3b(171uy,217uy,233uy); C3b(116uy,173uy,209uy)\n                                                C3b(69uy,117uy,180uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(165uy,0uy,38uy); C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)\n                                                C3b(254uy,224uy,144uy); C3b(224uy,243uy,248uy); C3b(171uy,217uy,233uy); C3b(116uy,173uy,209uy)\n                                                C3b(69uy,117uy,180uy); C3b(49uy,54uy,149uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(165uy,0uy,38uy); C3b(215uy,48uy,39uy); C3b(244uy,109uy,67uy); C3b(253uy,174uy,97uy)\n                                                C3b(254uy,224uy,144uy); C3b(255uy,255uy,191uy); C3b(224uy,243uy,248uy); C3b(171uy,217uy,233uy)\n                                                C3b(116uy,173uy,209uy); C3b(69uy,117uy,180uy); C3b(49uy,54uy,149uy) |]\n                                }\n\n                            ]\n                    }\n\n                let BrBG =\n                    {\n                        Name = Sym.ofString \"BrBG\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(216uy,179uy,101uy); C3b(245uy,245uy,245uy); C3b(90uy,180uy,172uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,97uy,26uy); C3b(223uy,194uy,125uy); C3b(128uy,205uy,193uy); C3b(1uy,133uy,113uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,97uy,26uy); C3b(223uy,194uy,125uy); C3b(245uy,245uy,245uy); C3b(128uy,205uy,193uy)\n                                                C3b(1uy,133uy,113uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(140uy,81uy,10uy); C3b(216uy,179uy,101uy); C3b(246uy,232uy,195uy); C3b(199uy,234uy,229uy)\n                                                C3b(90uy,180uy,172uy); C3b(1uy,102uy,94uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(140uy,81uy,10uy); C3b(216uy,179uy,101uy); C3b(246uy,232uy,195uy); C3b(245uy,245uy,245uy)\n                                                C3b(199uy,234uy,229uy); C3b(90uy,180uy,172uy); C3b(1uy,102uy,94uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(140uy,81uy,10uy); C3b(191uy,129uy,45uy); C3b(223uy,194uy,125uy); C3b(246uy,232uy,195uy)\n                                                C3b(199uy,234uy,229uy); C3b(128uy,205uy,193uy); C3b(53uy,151uy,143uy); C3b(1uy,102uy,94uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(140uy,81uy,10uy); C3b(191uy,129uy,45uy); C3b(223uy,194uy,125uy); C3b(246uy,232uy,195uy)\n                                                C3b(245uy,245uy,245uy); C3b(199uy,234uy,229uy); C3b(128uy,205uy,193uy); C3b(53uy,151uy,143uy)\n                                                C3b(1uy,102uy,94uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(84uy,48uy,5uy); C3b(140uy,81uy,10uy); C3b(191uy,129uy,45uy); C3b(223uy,194uy,125uy)\n                                                C3b(246uy,232uy,195uy); C3b(199uy,234uy,229uy); C3b(128uy,205uy,193uy); C3b(53uy,151uy,143uy)\n                                                C3b(1uy,102uy,94uy); C3b(0uy,60uy,48uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(84uy,48uy,5uy); C3b(140uy,81uy,10uy); C3b(191uy,129uy,45uy); C3b(223uy,194uy,125uy)\n                                                C3b(246uy,232uy,195uy); C3b(245uy,245uy,245uy); C3b(199uy,234uy,229uy); C3b(128uy,205uy,193uy)\n                                                C3b(53uy,151uy,143uy); C3b(1uy,102uy,94uy); C3b(0uy,60uy,48uy) |]\n                                }\n\n                            ]\n                    }\n\n                let RdGy =\n                    {\n                        Name = Sym.ofString \"RdGy\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(239uy,138uy,98uy); C3b(255uy,255uy,255uy); C3b(153uy,153uy,153uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(202uy,0uy,32uy); C3b(244uy,165uy,130uy); C3b(186uy,186uy,186uy); C3b(64uy,64uy,64uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.Print\n                                    Colors = [| C3b(202uy,0uy,32uy); C3b(244uy,165uy,130uy); C3b(255uy,255uy,255uy); C3b(186uy,186uy,186uy)\n                                                C3b(64uy,64uy,64uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(178uy,24uy,43uy); C3b(239uy,138uy,98uy); C3b(253uy,219uy,199uy); C3b(224uy,224uy,224uy)\n                                                C3b(153uy,153uy,153uy); C3b(77uy,77uy,77uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(178uy,24uy,43uy); C3b(239uy,138uy,98uy); C3b(253uy,219uy,199uy); C3b(255uy,255uy,255uy)\n                                                C3b(224uy,224uy,224uy); C3b(153uy,153uy,153uy); C3b(77uy,77uy,77uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy); C3b(253uy,219uy,199uy)\n                                                C3b(224uy,224uy,224uy); C3b(186uy,186uy,186uy); C3b(135uy,135uy,135uy); C3b(77uy,77uy,77uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy); C3b(253uy,219uy,199uy)\n                                                C3b(255uy,255uy,255uy); C3b(224uy,224uy,224uy); C3b(186uy,186uy,186uy); C3b(135uy,135uy,135uy)\n                                                C3b(77uy,77uy,77uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(103uy,0uy,31uy); C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy)\n                                                C3b(253uy,219uy,199uy); C3b(224uy,224uy,224uy); C3b(186uy,186uy,186uy); C3b(135uy,135uy,135uy)\n                                                C3b(77uy,77uy,77uy); C3b(26uy,26uy,26uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(103uy,0uy,31uy); C3b(178uy,24uy,43uy); C3b(214uy,96uy,77uy); C3b(244uy,165uy,130uy)\n                                                C3b(253uy,219uy,199uy); C3b(255uy,255uy,255uy); C3b(224uy,224uy,224uy); C3b(186uy,186uy,186uy)\n                                                C3b(135uy,135uy,135uy); C3b(77uy,77uy,77uy); C3b(26uy,26uy,26uy) |]\n                                }\n\n                            ]\n                    }\n\n                let PuOr =\n                    {\n                        Name = Sym.ofString \"PuOr\"\n                        Type = SchemeType.Diverging\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(241uy,163uy,64uy); C3b(247uy,247uy,247uy); C3b(153uy,142uy,195uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(230uy,97uy,1uy); C3b(253uy,184uy,99uy); C3b(178uy,171uy,210uy); C3b(94uy,60uy,153uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD\n                                    Colors = [| C3b(230uy,97uy,1uy); C3b(253uy,184uy,99uy); C3b(247uy,247uy,247uy); C3b(178uy,171uy,210uy)\n                                                C3b(94uy,60uy,153uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD\n                                    Colors = [| C3b(179uy,88uy,6uy); C3b(241uy,163uy,64uy); C3b(254uy,224uy,182uy); C3b(216uy,218uy,235uy)\n                                                C3b(153uy,142uy,195uy); C3b(84uy,39uy,136uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(179uy,88uy,6uy); C3b(241uy,163uy,64uy); C3b(254uy,224uy,182uy); C3b(247uy,247uy,247uy)\n                                                C3b(216uy,218uy,235uy); C3b(153uy,142uy,195uy); C3b(84uy,39uy,136uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(179uy,88uy,6uy); C3b(224uy,130uy,20uy); C3b(253uy,184uy,99uy); C3b(254uy,224uy,182uy)\n                                                C3b(216uy,218uy,235uy); C3b(178uy,171uy,210uy); C3b(128uy,115uy,172uy); C3b(84uy,39uy,136uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(179uy,88uy,6uy); C3b(224uy,130uy,20uy); C3b(253uy,184uy,99uy); C3b(254uy,224uy,182uy)\n                                                C3b(247uy,247uy,247uy); C3b(216uy,218uy,235uy); C3b(178uy,171uy,210uy); C3b(128uy,115uy,172uy)\n                                                C3b(84uy,39uy,136uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(127uy,59uy,8uy); C3b(179uy,88uy,6uy); C3b(224uy,130uy,20uy); C3b(253uy,184uy,99uy)\n                                                C3b(254uy,224uy,182uy); C3b(216uy,218uy,235uy); C3b(178uy,171uy,210uy); C3b(128uy,115uy,172uy)\n                                                C3b(84uy,39uy,136uy); C3b(45uy,0uy,75uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(127uy,59uy,8uy); C3b(179uy,88uy,6uy); C3b(224uy,130uy,20uy); C3b(253uy,184uy,99uy)\n                                                C3b(254uy,224uy,182uy); C3b(247uy,247uy,247uy); C3b(216uy,218uy,235uy); C3b(178uy,171uy,210uy)\n                                                C3b(128uy,115uy,172uy); C3b(84uy,39uy,136uy); C3b(45uy,0uy,75uy) |]\n                                }\n\n                            ]\n                    }\n\n            /// Qualitative schemes do not imply magnitude differences between legend classes, and hues are used to\n            /// create the primary visual differences between classes. Qualitative schemes are best suited to representing nominal or categorical data.\n            module Qualitative =\n\n                let Set2 =\n                    {\n                        Name = Sym.ofString \"Set2\"\n                        Type = SchemeType.Qualitative\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.Print\n                                    Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy)\n                                                C3b(166uy,216uy,84uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy)\n                                                C3b(166uy,216uy,84uy); C3b(255uy,217uy,47uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy)\n                                                C3b(166uy,216uy,84uy); C3b(255uy,217uy,47uy); C3b(229uy,196uy,148uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(102uy,194uy,165uy); C3b(252uy,141uy,98uy); C3b(141uy,160uy,203uy); C3b(231uy,138uy,195uy)\n                                                C3b(166uy,216uy,84uy); C3b(255uy,217uy,47uy); C3b(229uy,196uy,148uy); C3b(179uy,179uy,179uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Accent =\n                    {\n                        Name = Sym.ofString \"Accent\"\n                        Type = SchemeType.Qualitative\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.LCD\n                                    Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy)\n                                                C3b(56uy,108uy,176uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy)\n                                                C3b(56uy,108uy,176uy); C3b(240uy,2uy,127uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy)\n                                                C3b(56uy,108uy,176uy); C3b(240uy,2uy,127uy); C3b(191uy,91uy,23uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(127uy,201uy,127uy); C3b(190uy,174uy,212uy); C3b(253uy,192uy,134uy); C3b(255uy,255uy,153uy)\n                                                C3b(56uy,108uy,176uy); C3b(240uy,2uy,127uy); C3b(191uy,91uy,23uy); C3b(102uy,102uy,102uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Set1 =\n                    {\n                        Name = Sym.ofString \"Set1\"\n                        Type = SchemeType.Qualitative\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)\n                                                C3b(255uy,127uy,0uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)\n                                                C3b(255uy,127uy,0uy); C3b(255uy,255uy,51uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)\n                                                C3b(255uy,127uy,0uy); C3b(255uy,255uy,51uy); C3b(166uy,86uy,40uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)\n                                                C3b(255uy,127uy,0uy); C3b(255uy,255uy,51uy); C3b(166uy,86uy,40uy); C3b(247uy,129uy,191uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(228uy,26uy,28uy); C3b(55uy,126uy,184uy); C3b(77uy,175uy,74uy); C3b(152uy,78uy,163uy)\n                                                C3b(255uy,127uy,0uy); C3b(255uy,255uy,51uy); C3b(166uy,86uy,40uy); C3b(247uy,129uy,191uy)\n                                                C3b(153uy,153uy,153uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Set3 =\n                    {\n                        Name = Sym.ofString \"Set3\"\n                        Type = SchemeType.Qualitative\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)\n                                                C3b(128uy,177uy,211uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.Print\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)\n                                                C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.Print\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)\n                                                C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.Print\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)\n                                                C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)\n                                                C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy)\n                                                C3b(217uy,217uy,217uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)\n                                                C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy)\n                                                C3b(217uy,217uy,217uy); C3b(188uy,128uy,189uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)\n                                                C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy)\n                                                C3b(217uy,217uy,217uy); C3b(188uy,128uy,189uy); C3b(204uy,235uy,197uy) |]\n                                }\n\n                                12, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(141uy,211uy,199uy); C3b(255uy,255uy,179uy); C3b(190uy,186uy,218uy); C3b(251uy,128uy,114uy)\n                                                C3b(128uy,177uy,211uy); C3b(253uy,180uy,98uy); C3b(179uy,222uy,105uy); C3b(252uy,205uy,229uy)\n                                                C3b(217uy,217uy,217uy); C3b(188uy,128uy,189uy); C3b(204uy,235uy,197uy); C3b(255uy,237uy,111uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Dark2 =\n                    {\n                        Name = Sym.ofString \"Dark2\"\n                        Type = SchemeType.Qualitative\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy)\n                                                C3b(102uy,166uy,30uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy)\n                                                C3b(102uy,166uy,30uy); C3b(230uy,171uy,2uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy)\n                                                C3b(102uy,166uy,30uy); C3b(230uy,171uy,2uy); C3b(166uy,118uy,29uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(27uy,158uy,119uy); C3b(217uy,95uy,2uy); C3b(117uy,112uy,179uy); C3b(231uy,41uy,138uy)\n                                                C3b(102uy,166uy,30uy); C3b(230uy,171uy,2uy); C3b(166uy,118uy,29uy); C3b(102uy,102uy,102uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Paired =\n                    {\n                        Name = Sym.ofString \"Paired\"\n                        Type = SchemeType.Qualitative\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)\n                                                C3b(251uy,154uy,153uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)\n                                                C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)\n                                                C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)\n                                                C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)\n                                                C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy)\n                                                C3b(202uy,178uy,214uy) |]\n                                }\n\n                                10, {\n                                    Usage = PaletteUsage.LCD\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)\n                                                C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy)\n                                                C3b(202uy,178uy,214uy); C3b(106uy,61uy,154uy) |]\n                                }\n\n                                11, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)\n                                                C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy)\n                                                C3b(202uy,178uy,214uy); C3b(106uy,61uy,154uy); C3b(255uy,255uy,153uy) |]\n                                }\n\n                                12, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(166uy,206uy,227uy); C3b(31uy,120uy,180uy); C3b(178uy,223uy,138uy); C3b(51uy,160uy,44uy)\n                                                C3b(251uy,154uy,153uy); C3b(227uy,26uy,28uy); C3b(253uy,191uy,111uy); C3b(255uy,127uy,0uy)\n                                                C3b(202uy,178uy,214uy); C3b(106uy,61uy,154uy); C3b(255uy,255uy,153uy); C3b(177uy,89uy,40uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Pastel2 =\n                    {\n                        Name = Sym.ofString \"Pastel2\"\n                        Type = SchemeType.Qualitative\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy)\n                                                C3b(230uy,245uy,201uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy)\n                                                C3b(230uy,245uy,201uy); C3b(255uy,242uy,174uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy)\n                                                C3b(230uy,245uy,201uy); C3b(255uy,242uy,174uy); C3b(241uy,226uy,204uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(179uy,226uy,205uy); C3b(253uy,205uy,172uy); C3b(203uy,213uy,232uy); C3b(244uy,202uy,228uy)\n                                                C3b(230uy,245uy,201uy); C3b(255uy,242uy,174uy); C3b(241uy,226uy,204uy); C3b(204uy,204uy,204uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Pastel1 =\n                    {\n                        Name = Sym.ofString \"Pastel1\"\n                        Type = SchemeType.Qualitative\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)\n                                                C3b(254uy,217uy,166uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)\n                                                C3b(254uy,217uy,166uy); C3b(255uy,255uy,204uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)\n                                                C3b(254uy,217uy,166uy); C3b(255uy,255uy,204uy); C3b(229uy,216uy,189uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)\n                                                C3b(254uy,217uy,166uy); C3b(255uy,255uy,204uy); C3b(229uy,216uy,189uy); C3b(253uy,218uy,236uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.None\n                                    Colors = [| C3b(251uy,180uy,174uy); C3b(179uy,205uy,227uy); C3b(204uy,235uy,197uy); C3b(222uy,203uy,228uy)\n                                                C3b(254uy,217uy,166uy); C3b(255uy,255uy,204uy); C3b(229uy,216uy,189uy); C3b(253uy,218uy,236uy)\n                                                C3b(242uy,242uy,242uy) |]\n                                }\n\n                            ]\n                    }\n\n            /// Sequential schemes are suited to ordered data that progress from low to high.\n            /// Lightness steps dominate the look of these schemes, with light colors for low data values to dark colors for high data values.\n            module Sequential =\n\n                let OrRd =\n                    {\n                        Name = Sym.ofString \"OrRd\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(254uy,232uy,200uy); C3b(253uy,187uy,132uy); C3b(227uy,74uy,51uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(254uy,240uy,217uy); C3b(253uy,204uy,138uy); C3b(252uy,141uy,89uy); C3b(215uy,48uy,31uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD\n                                    Colors = [| C3b(254uy,240uy,217uy); C3b(253uy,204uy,138uy); C3b(252uy,141uy,89uy); C3b(227uy,74uy,51uy)\n                                                C3b(179uy,0uy,0uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,240uy,217uy); C3b(253uy,212uy,158uy); C3b(253uy,187uy,132uy); C3b(252uy,141uy,89uy)\n                                                C3b(227uy,74uy,51uy); C3b(179uy,0uy,0uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,240uy,217uy); C3b(253uy,212uy,158uy); C3b(253uy,187uy,132uy); C3b(252uy,141uy,89uy)\n                                                C3b(239uy,101uy,72uy); C3b(215uy,48uy,31uy); C3b(153uy,0uy,0uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,247uy,236uy); C3b(254uy,232uy,200uy); C3b(253uy,212uy,158uy); C3b(253uy,187uy,132uy)\n                                                C3b(252uy,141uy,89uy); C3b(239uy,101uy,72uy); C3b(215uy,48uy,31uy); C3b(153uy,0uy,0uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,247uy,236uy); C3b(254uy,232uy,200uy); C3b(253uy,212uy,158uy); C3b(253uy,187uy,132uy)\n                                                C3b(252uy,141uy,89uy); C3b(239uy,101uy,72uy); C3b(215uy,48uy,31uy); C3b(179uy,0uy,0uy)\n                                                C3b(127uy,0uy,0uy) |]\n                                }\n\n                            ]\n                    }\n\n                let PuBu =\n                    {\n                        Name = Sym.ofString \"PuBu\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(236uy,231uy,242uy); C3b(166uy,189uy,219uy); C3b(43uy,140uy,190uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD\n                                    Colors = [| C3b(241uy,238uy,246uy); C3b(189uy,201uy,225uy); C3b(116uy,169uy,207uy); C3b(5uy,112uy,176uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(241uy,238uy,246uy); C3b(189uy,201uy,225uy); C3b(116uy,169uy,207uy); C3b(43uy,140uy,190uy)\n                                                C3b(4uy,90uy,141uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(241uy,238uy,246uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy); C3b(116uy,169uy,207uy)\n                                                C3b(43uy,140uy,190uy); C3b(4uy,90uy,141uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(241uy,238uy,246uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy); C3b(116uy,169uy,207uy)\n                                                C3b(54uy,144uy,192uy); C3b(5uy,112uy,176uy); C3b(3uy,78uy,123uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,247uy,251uy); C3b(236uy,231uy,242uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy)\n                                                C3b(116uy,169uy,207uy); C3b(54uy,144uy,192uy); C3b(5uy,112uy,176uy); C3b(3uy,78uy,123uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,247uy,251uy); C3b(236uy,231uy,242uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy)\n                                                C3b(116uy,169uy,207uy); C3b(54uy,144uy,192uy); C3b(5uy,112uy,176uy); C3b(4uy,90uy,141uy)\n                                                C3b(2uy,56uy,88uy) |]\n                                }\n\n                            ]\n                    }\n\n                let BuPu =\n                    {\n                        Name = Sym.ofString \"BuPu\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(224uy,236uy,244uy); C3b(158uy,188uy,218uy); C3b(136uy,86uy,167uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(237uy,248uy,251uy); C3b(179uy,205uy,227uy); C3b(140uy,150uy,198uy); C3b(136uy,65uy,157uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD\n                                    Colors = [| C3b(237uy,248uy,251uy); C3b(179uy,205uy,227uy); C3b(140uy,150uy,198uy); C3b(136uy,86uy,167uy)\n                                                C3b(129uy,15uy,124uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,251uy); C3b(191uy,211uy,230uy); C3b(158uy,188uy,218uy); C3b(140uy,150uy,198uy)\n                                                C3b(136uy,86uy,167uy); C3b(129uy,15uy,124uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,251uy); C3b(191uy,211uy,230uy); C3b(158uy,188uy,218uy); C3b(140uy,150uy,198uy)\n                                                C3b(140uy,107uy,177uy); C3b(136uy,65uy,157uy); C3b(110uy,1uy,107uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,252uy,253uy); C3b(224uy,236uy,244uy); C3b(191uy,211uy,230uy); C3b(158uy,188uy,218uy)\n                                                C3b(140uy,150uy,198uy); C3b(140uy,107uy,177uy); C3b(136uy,65uy,157uy); C3b(110uy,1uy,107uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,252uy,253uy); C3b(224uy,236uy,244uy); C3b(191uy,211uy,230uy); C3b(158uy,188uy,218uy)\n                                                C3b(140uy,150uy,198uy); C3b(140uy,107uy,177uy); C3b(136uy,65uy,157uy); C3b(129uy,15uy,124uy)\n                                                C3b(77uy,0uy,75uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Oranges =\n                    {\n                        Name = Sym.ofString \"Oranges\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(254uy,230uy,206uy); C3b(253uy,174uy,107uy); C3b(230uy,85uy,13uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD\n                                    Colors = [| C3b(254uy,237uy,222uy); C3b(253uy,190uy,133uy); C3b(253uy,141uy,60uy); C3b(217uy,71uy,1uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD\n                                    Colors = [| C3b(254uy,237uy,222uy); C3b(253uy,190uy,133uy); C3b(253uy,141uy,60uy); C3b(230uy,85uy,13uy)\n                                                C3b(166uy,54uy,3uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,237uy,222uy); C3b(253uy,208uy,162uy); C3b(253uy,174uy,107uy); C3b(253uy,141uy,60uy)\n                                                C3b(230uy,85uy,13uy); C3b(166uy,54uy,3uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,237uy,222uy); C3b(253uy,208uy,162uy); C3b(253uy,174uy,107uy); C3b(253uy,141uy,60uy)\n                                                C3b(241uy,105uy,19uy); C3b(217uy,72uy,1uy); C3b(140uy,45uy,4uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,245uy,235uy); C3b(254uy,230uy,206uy); C3b(253uy,208uy,162uy); C3b(253uy,174uy,107uy)\n                                                C3b(253uy,141uy,60uy); C3b(241uy,105uy,19uy); C3b(217uy,72uy,1uy); C3b(140uy,45uy,4uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,245uy,235uy); C3b(254uy,230uy,206uy); C3b(253uy,208uy,162uy); C3b(253uy,174uy,107uy)\n                                                C3b(253uy,141uy,60uy); C3b(241uy,105uy,19uy); C3b(217uy,72uy,1uy); C3b(166uy,54uy,3uy)\n                                                C3b(127uy,39uy,4uy) |]\n                                }\n\n                            ]\n                    }\n\n                let BuGn =\n                    {\n                        Name = Sym.ofString \"BuGn\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(229uy,245uy,249uy); C3b(153uy,216uy,201uy); C3b(44uy,162uy,95uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(237uy,248uy,251uy); C3b(178uy,226uy,226uy); C3b(102uy,194uy,164uy); C3b(35uy,139uy,69uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,251uy); C3b(178uy,226uy,226uy); C3b(102uy,194uy,164uy); C3b(44uy,162uy,95uy)\n                                                C3b(0uy,109uy,44uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,251uy); C3b(204uy,236uy,230uy); C3b(153uy,216uy,201uy); C3b(102uy,194uy,164uy)\n                                                C3b(44uy,162uy,95uy); C3b(0uy,109uy,44uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,251uy); C3b(204uy,236uy,230uy); C3b(153uy,216uy,201uy); C3b(102uy,194uy,164uy)\n                                                C3b(65uy,174uy,118uy); C3b(35uy,139uy,69uy); C3b(0uy,88uy,36uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,252uy,253uy); C3b(229uy,245uy,249uy); C3b(204uy,236uy,230uy); C3b(153uy,216uy,201uy)\n                                                C3b(102uy,194uy,164uy); C3b(65uy,174uy,118uy); C3b(35uy,139uy,69uy); C3b(0uy,88uy,36uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,252uy,253uy); C3b(229uy,245uy,249uy); C3b(204uy,236uy,230uy); C3b(153uy,216uy,201uy)\n                                                C3b(102uy,194uy,164uy); C3b(65uy,174uy,118uy); C3b(35uy,139uy,69uy); C3b(0uy,109uy,44uy)\n                                                C3b(0uy,68uy,27uy) |]\n                                }\n\n                            ]\n                    }\n\n                let YlOrBr =\n                    {\n                        Name = Sym.ofString \"YlOrBr\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(255uy,247uy,188uy); C3b(254uy,196uy,79uy); C3b(217uy,95uy,14uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(255uy,255uy,212uy); C3b(254uy,217uy,142uy); C3b(254uy,153uy,41uy); C3b(204uy,76uy,2uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,212uy); C3b(254uy,217uy,142uy); C3b(254uy,153uy,41uy); C3b(217uy,95uy,14uy)\n                                                C3b(153uy,52uy,4uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,212uy); C3b(254uy,227uy,145uy); C3b(254uy,196uy,79uy); C3b(254uy,153uy,41uy)\n                                                C3b(217uy,95uy,14uy); C3b(153uy,52uy,4uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,212uy); C3b(254uy,227uy,145uy); C3b(254uy,196uy,79uy); C3b(254uy,153uy,41uy)\n                                                C3b(236uy,112uy,20uy); C3b(204uy,76uy,2uy); C3b(140uy,45uy,4uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,229uy); C3b(255uy,247uy,188uy); C3b(254uy,227uy,145uy); C3b(254uy,196uy,79uy)\n                                                C3b(254uy,153uy,41uy); C3b(236uy,112uy,20uy); C3b(204uy,76uy,2uy); C3b(140uy,45uy,4uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,229uy); C3b(255uy,247uy,188uy); C3b(254uy,227uy,145uy); C3b(254uy,196uy,79uy)\n                                                C3b(254uy,153uy,41uy); C3b(236uy,112uy,20uy); C3b(204uy,76uy,2uy); C3b(153uy,52uy,4uy)\n                                                C3b(102uy,37uy,6uy) |]\n                                }\n\n                            ]\n                    }\n\n                let YlGn =\n                    {\n                        Name = Sym.ofString \"YlGn\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(247uy,252uy,185uy); C3b(173uy,221uy,142uy); C3b(49uy,163uy,84uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(194uy,230uy,153uy); C3b(120uy,198uy,121uy); C3b(35uy,132uy,67uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(194uy,230uy,153uy); C3b(120uy,198uy,121uy); C3b(49uy,163uy,84uy)\n                                                C3b(0uy,104uy,55uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(217uy,240uy,163uy); C3b(173uy,221uy,142uy); C3b(120uy,198uy,121uy)\n                                                C3b(49uy,163uy,84uy); C3b(0uy,104uy,55uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(217uy,240uy,163uy); C3b(173uy,221uy,142uy); C3b(120uy,198uy,121uy)\n                                                C3b(65uy,171uy,93uy); C3b(35uy,132uy,67uy); C3b(0uy,90uy,50uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,229uy); C3b(247uy,252uy,185uy); C3b(217uy,240uy,163uy); C3b(173uy,221uy,142uy)\n                                                C3b(120uy,198uy,121uy); C3b(65uy,171uy,93uy); C3b(35uy,132uy,67uy); C3b(0uy,90uy,50uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,229uy); C3b(247uy,252uy,185uy); C3b(217uy,240uy,163uy); C3b(173uy,221uy,142uy)\n                                                C3b(120uy,198uy,121uy); C3b(65uy,171uy,93uy); C3b(35uy,132uy,67uy); C3b(0uy,104uy,55uy)\n                                                C3b(0uy,69uy,41uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Reds =\n                    {\n                        Name = Sym.ofString \"Reds\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(254uy,224uy,210uy); C3b(252uy,146uy,114uy); C3b(222uy,45uy,38uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,229uy,217uy); C3b(252uy,174uy,145uy); C3b(251uy,106uy,74uy); C3b(203uy,24uy,29uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,229uy,217uy); C3b(252uy,174uy,145uy); C3b(251uy,106uy,74uy); C3b(222uy,45uy,38uy)\n                                                C3b(165uy,15uy,21uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,229uy,217uy); C3b(252uy,187uy,161uy); C3b(252uy,146uy,114uy); C3b(251uy,106uy,74uy)\n                                                C3b(222uy,45uy,38uy); C3b(165uy,15uy,21uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,229uy,217uy); C3b(252uy,187uy,161uy); C3b(252uy,146uy,114uy); C3b(251uy,106uy,74uy)\n                                                C3b(239uy,59uy,44uy); C3b(203uy,24uy,29uy); C3b(153uy,0uy,13uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,245uy,240uy); C3b(254uy,224uy,210uy); C3b(252uy,187uy,161uy); C3b(252uy,146uy,114uy)\n                                                C3b(251uy,106uy,74uy); C3b(239uy,59uy,44uy); C3b(203uy,24uy,29uy); C3b(153uy,0uy,13uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,245uy,240uy); C3b(254uy,224uy,210uy); C3b(252uy,187uy,161uy); C3b(252uy,146uy,114uy)\n                                                C3b(251uy,106uy,74uy); C3b(239uy,59uy,44uy); C3b(203uy,24uy,29uy); C3b(165uy,15uy,21uy)\n                                                C3b(103uy,0uy,13uy) |]\n                                }\n\n                            ]\n                    }\n\n                let RdPu =\n                    {\n                        Name = Sym.ofString \"RdPu\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(253uy,224uy,221uy); C3b(250uy,159uy,181uy); C3b(197uy,27uy,138uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(254uy,235uy,226uy); C3b(251uy,180uy,185uy); C3b(247uy,104uy,161uy); C3b(174uy,1uy,126uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(254uy,235uy,226uy); C3b(251uy,180uy,185uy); C3b(247uy,104uy,161uy); C3b(197uy,27uy,138uy)\n                                                C3b(122uy,1uy,119uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,235uy,226uy); C3b(252uy,197uy,192uy); C3b(250uy,159uy,181uy); C3b(247uy,104uy,161uy)\n                                                C3b(197uy,27uy,138uy); C3b(122uy,1uy,119uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(254uy,235uy,226uy); C3b(252uy,197uy,192uy); C3b(250uy,159uy,181uy); C3b(247uy,104uy,161uy)\n                                                C3b(221uy,52uy,151uy); C3b(174uy,1uy,126uy); C3b(122uy,1uy,119uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,247uy,243uy); C3b(253uy,224uy,221uy); C3b(252uy,197uy,192uy); C3b(250uy,159uy,181uy)\n                                                C3b(247uy,104uy,161uy); C3b(221uy,52uy,151uy); C3b(174uy,1uy,126uy); C3b(122uy,1uy,119uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,247uy,243uy); C3b(253uy,224uy,221uy); C3b(252uy,197uy,192uy); C3b(250uy,159uy,181uy)\n                                                C3b(247uy,104uy,161uy); C3b(221uy,52uy,151uy); C3b(174uy,1uy,126uy); C3b(122uy,1uy,119uy)\n                                                C3b(73uy,0uy,106uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Greens =\n                    {\n                        Name = Sym.ofString \"Greens\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(229uy,245uy,224uy); C3b(161uy,217uy,155uy); C3b(49uy,163uy,84uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,233uy); C3b(186uy,228uy,179uy); C3b(116uy,196uy,118uy); C3b(35uy,139uy,69uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,233uy); C3b(186uy,228uy,179uy); C3b(116uy,196uy,118uy); C3b(49uy,163uy,84uy)\n                                                C3b(0uy,109uy,44uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,233uy); C3b(199uy,233uy,192uy); C3b(161uy,217uy,155uy); C3b(116uy,196uy,118uy)\n                                                C3b(49uy,163uy,84uy); C3b(0uy,109uy,44uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(237uy,248uy,233uy); C3b(199uy,233uy,192uy); C3b(161uy,217uy,155uy); C3b(116uy,196uy,118uy)\n                                                C3b(65uy,171uy,93uy); C3b(35uy,139uy,69uy); C3b(0uy,90uy,50uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,252uy,245uy); C3b(229uy,245uy,224uy); C3b(199uy,233uy,192uy); C3b(161uy,217uy,155uy)\n                                                C3b(116uy,196uy,118uy); C3b(65uy,171uy,93uy); C3b(35uy,139uy,69uy); C3b(0uy,90uy,50uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,252uy,245uy); C3b(229uy,245uy,224uy); C3b(199uy,233uy,192uy); C3b(161uy,217uy,155uy)\n                                                C3b(116uy,196uy,118uy); C3b(65uy,171uy,93uy); C3b(35uy,139uy,69uy); C3b(0uy,109uy,44uy)\n                                                C3b(0uy,68uy,27uy) |]\n                                }\n\n                            ]\n                    }\n\n                let YlGnBu =\n                    {\n                        Name = Sym.ofString \"YlGnBu\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(237uy,248uy,177uy); C3b(127uy,205uy,187uy); C3b(44uy,127uy,184uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(161uy,218uy,180uy); C3b(65uy,182uy,196uy); C3b(34uy,94uy,168uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(161uy,218uy,180uy); C3b(65uy,182uy,196uy); C3b(44uy,127uy,184uy)\n                                                C3b(37uy,52uy,148uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(199uy,233uy,180uy); C3b(127uy,205uy,187uy); C3b(65uy,182uy,196uy)\n                                                C3b(44uy,127uy,184uy); C3b(37uy,52uy,148uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(199uy,233uy,180uy); C3b(127uy,205uy,187uy); C3b(65uy,182uy,196uy)\n                                                C3b(29uy,145uy,192uy); C3b(34uy,94uy,168uy); C3b(12uy,44uy,132uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,217uy); C3b(237uy,248uy,177uy); C3b(199uy,233uy,180uy); C3b(127uy,205uy,187uy)\n                                                C3b(65uy,182uy,196uy); C3b(29uy,145uy,192uy); C3b(34uy,94uy,168uy); C3b(12uy,44uy,132uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,217uy); C3b(237uy,248uy,177uy); C3b(199uy,233uy,180uy); C3b(127uy,205uy,187uy)\n                                                C3b(65uy,182uy,196uy); C3b(29uy,145uy,192uy); C3b(34uy,94uy,168uy); C3b(37uy,52uy,148uy)\n                                                C3b(8uy,29uy,88uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Purples =\n                    {\n                        Name = Sym.ofString \"Purples\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(239uy,237uy,245uy); C3b(188uy,189uy,220uy); C3b(117uy,107uy,177uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(242uy,240uy,247uy); C3b(203uy,201uy,226uy); C3b(158uy,154uy,200uy); C3b(106uy,81uy,163uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(242uy,240uy,247uy); C3b(203uy,201uy,226uy); C3b(158uy,154uy,200uy); C3b(117uy,107uy,177uy)\n                                                C3b(84uy,39uy,143uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(242uy,240uy,247uy); C3b(218uy,218uy,235uy); C3b(188uy,189uy,220uy); C3b(158uy,154uy,200uy)\n                                                C3b(117uy,107uy,177uy); C3b(84uy,39uy,143uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(242uy,240uy,247uy); C3b(218uy,218uy,235uy); C3b(188uy,189uy,220uy); C3b(158uy,154uy,200uy)\n                                                C3b(128uy,125uy,186uy); C3b(106uy,81uy,163uy); C3b(74uy,20uy,134uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(252uy,251uy,253uy); C3b(239uy,237uy,245uy); C3b(218uy,218uy,235uy); C3b(188uy,189uy,220uy)\n                                                C3b(158uy,154uy,200uy); C3b(128uy,125uy,186uy); C3b(106uy,81uy,163uy); C3b(74uy,20uy,134uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(252uy,251uy,253uy); C3b(239uy,237uy,245uy); C3b(218uy,218uy,235uy); C3b(188uy,189uy,220uy)\n                                                C3b(158uy,154uy,200uy); C3b(128uy,125uy,186uy); C3b(106uy,81uy,163uy); C3b(84uy,39uy,143uy)\n                                                C3b(63uy,0uy,125uy) |]\n                                }\n\n                            ]\n                    }\n\n                let GnBu =\n                    {\n                        Name = Sym.ofString \"GnBu\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(224uy,243uy,219uy); C3b(168uy,221uy,181uy); C3b(67uy,162uy,202uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(240uy,249uy,232uy); C3b(186uy,228uy,188uy); C3b(123uy,204uy,196uy); C3b(43uy,140uy,190uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(240uy,249uy,232uy); C3b(186uy,228uy,188uy); C3b(123uy,204uy,196uy); C3b(67uy,162uy,202uy)\n                                                C3b(8uy,104uy,172uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(240uy,249uy,232uy); C3b(204uy,235uy,197uy); C3b(168uy,221uy,181uy); C3b(123uy,204uy,196uy)\n                                                C3b(67uy,162uy,202uy); C3b(8uy,104uy,172uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(240uy,249uy,232uy); C3b(204uy,235uy,197uy); C3b(168uy,221uy,181uy); C3b(123uy,204uy,196uy)\n                                                C3b(78uy,179uy,211uy); C3b(43uy,140uy,190uy); C3b(8uy,88uy,158uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,252uy,240uy); C3b(224uy,243uy,219uy); C3b(204uy,235uy,197uy); C3b(168uy,221uy,181uy)\n                                                C3b(123uy,204uy,196uy); C3b(78uy,179uy,211uy); C3b(43uy,140uy,190uy); C3b(8uy,88uy,158uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,252uy,240uy); C3b(224uy,243uy,219uy); C3b(204uy,235uy,197uy); C3b(168uy,221uy,181uy)\n                                                C3b(123uy,204uy,196uy); C3b(78uy,179uy,211uy); C3b(43uy,140uy,190uy); C3b(8uy,104uy,172uy)\n                                                C3b(8uy,64uy,129uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Greys =\n                    {\n                        Name = Sym.ofString \"Greys\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(240uy,240uy,240uy); C3b(189uy,189uy,189uy); C3b(99uy,99uy,99uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(247uy,247uy,247uy); C3b(204uy,204uy,204uy); C3b(150uy,150uy,150uy); C3b(82uy,82uy,82uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,247uy,247uy); C3b(204uy,204uy,204uy); C3b(150uy,150uy,150uy); C3b(99uy,99uy,99uy)\n                                                C3b(37uy,37uy,37uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,247uy,247uy); C3b(217uy,217uy,217uy); C3b(189uy,189uy,189uy); C3b(150uy,150uy,150uy)\n                                                C3b(99uy,99uy,99uy); C3b(37uy,37uy,37uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,247uy,247uy); C3b(217uy,217uy,217uy); C3b(189uy,189uy,189uy); C3b(150uy,150uy,150uy)\n                                                C3b(115uy,115uy,115uy); C3b(82uy,82uy,82uy); C3b(37uy,37uy,37uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,255uy); C3b(240uy,240uy,240uy); C3b(217uy,217uy,217uy); C3b(189uy,189uy,189uy)\n                                                C3b(150uy,150uy,150uy); C3b(115uy,115uy,115uy); C3b(82uy,82uy,82uy); C3b(37uy,37uy,37uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,255uy); C3b(240uy,240uy,240uy); C3b(217uy,217uy,217uy); C3b(189uy,189uy,189uy)\n                                                C3b(150uy,150uy,150uy); C3b(115uy,115uy,115uy); C3b(82uy,82uy,82uy); C3b(37uy,37uy,37uy)\n                                                C3b(0uy,0uy,0uy) |]\n                                }\n\n                            ]\n                    }\n\n                let YlOrRd =\n                    {\n                        Name = Sym.ofString \"YlOrRd\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(255uy,237uy,160uy); C3b(254uy,178uy,76uy); C3b(240uy,59uy,32uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print\n                                    Colors = [| C3b(255uy,255uy,178uy); C3b(254uy,204uy,92uy); C3b(253uy,141uy,60uy); C3b(227uy,26uy,28uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,178uy); C3b(254uy,204uy,92uy); C3b(253uy,141uy,60uy); C3b(240uy,59uy,32uy)\n                                                C3b(189uy,0uy,38uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,178uy); C3b(254uy,217uy,118uy); C3b(254uy,178uy,76uy); C3b(253uy,141uy,60uy)\n                                                C3b(240uy,59uy,32uy); C3b(189uy,0uy,38uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,178uy); C3b(254uy,217uy,118uy); C3b(254uy,178uy,76uy); C3b(253uy,141uy,60uy)\n                                                C3b(252uy,78uy,42uy); C3b(227uy,26uy,28uy); C3b(177uy,0uy,38uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(255uy,237uy,160uy); C3b(254uy,217uy,118uy); C3b(254uy,178uy,76uy)\n                                                C3b(253uy,141uy,60uy); C3b(252uy,78uy,42uy); C3b(227uy,26uy,28uy); C3b(177uy,0uy,38uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,255uy,204uy); C3b(255uy,237uy,160uy); C3b(254uy,217uy,118uy); C3b(254uy,178uy,76uy)\n                                                C3b(253uy,141uy,60uy); C3b(252uy,78uy,42uy); C3b(227uy,26uy,28uy); C3b(189uy,0uy,38uy)\n                                                C3b(128uy,0uy,38uy) |]\n                                }\n\n                            ]\n                    }\n\n                let PuRd =\n                    {\n                        Name = Sym.ofString \"PuRd\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(231uy,225uy,239uy); C3b(201uy,148uy,199uy); C3b(221uy,28uy,119uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(241uy,238uy,246uy); C3b(215uy,181uy,216uy); C3b(223uy,101uy,176uy); C3b(206uy,18uy,86uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD\n                                    Colors = [| C3b(241uy,238uy,246uy); C3b(215uy,181uy,216uy); C3b(223uy,101uy,176uy); C3b(221uy,28uy,119uy)\n                                                C3b(152uy,0uy,67uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(241uy,238uy,246uy); C3b(212uy,185uy,218uy); C3b(201uy,148uy,199uy); C3b(223uy,101uy,176uy)\n                                                C3b(221uy,28uy,119uy); C3b(152uy,0uy,67uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(241uy,238uy,246uy); C3b(212uy,185uy,218uy); C3b(201uy,148uy,199uy); C3b(223uy,101uy,176uy)\n                                                C3b(231uy,41uy,138uy); C3b(206uy,18uy,86uy); C3b(145uy,0uy,63uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,244uy,249uy); C3b(231uy,225uy,239uy); C3b(212uy,185uy,218uy); C3b(201uy,148uy,199uy)\n                                                C3b(223uy,101uy,176uy); C3b(231uy,41uy,138uy); C3b(206uy,18uy,86uy); C3b(145uy,0uy,63uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,244uy,249uy); C3b(231uy,225uy,239uy); C3b(212uy,185uy,218uy); C3b(201uy,148uy,199uy)\n                                                C3b(223uy,101uy,176uy); C3b(231uy,41uy,138uy); C3b(206uy,18uy,86uy); C3b(152uy,0uy,67uy)\n                                                C3b(103uy,0uy,31uy) |]\n                                }\n\n                            ]\n                    }\n\n                let Blues =\n                    {\n                        Name = Sym.ofString \"Blues\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(222uy,235uy,247uy); C3b(158uy,202uy,225uy); C3b(49uy,130uy,189uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(239uy,243uy,255uy); C3b(189uy,215uy,231uy); C3b(107uy,174uy,214uy); C3b(33uy,113uy,181uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(239uy,243uy,255uy); C3b(189uy,215uy,231uy); C3b(107uy,174uy,214uy); C3b(49uy,130uy,189uy)\n                                                C3b(8uy,81uy,156uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(239uy,243uy,255uy); C3b(198uy,219uy,239uy); C3b(158uy,202uy,225uy); C3b(107uy,174uy,214uy)\n                                                C3b(49uy,130uy,189uy); C3b(8uy,81uy,156uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(239uy,243uy,255uy); C3b(198uy,219uy,239uy); C3b(158uy,202uy,225uy); C3b(107uy,174uy,214uy)\n                                                C3b(66uy,146uy,198uy); C3b(33uy,113uy,181uy); C3b(8uy,69uy,148uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,251uy,255uy); C3b(222uy,235uy,247uy); C3b(198uy,219uy,239uy); C3b(158uy,202uy,225uy)\n                                                C3b(107uy,174uy,214uy); C3b(66uy,146uy,198uy); C3b(33uy,113uy,181uy); C3b(8uy,69uy,148uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(247uy,251uy,255uy); C3b(222uy,235uy,247uy); C3b(198uy,219uy,239uy); C3b(158uy,202uy,225uy)\n                                                C3b(107uy,174uy,214uy); C3b(66uy,146uy,198uy); C3b(33uy,113uy,181uy); C3b(8uy,81uy,156uy)\n                                                C3b(8uy,48uy,107uy) |]\n                                }\n\n                            ]\n                    }\n\n                let PuBuGn =\n                    {\n                        Name = Sym.ofString \"PuBuGn\"\n                        Type = SchemeType.Sequential\n                        Palettes =\n                            MapExt.ofList [\n                                3, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.Print ||| PaletteUsage.LCD ||| PaletteUsage.PhotoCopy\n                                    Colors = [| C3b(236uy,226uy,240uy); C3b(166uy,189uy,219uy); C3b(28uy,144uy,153uy) |]\n                                }\n\n                                4, {\n                                    Usage = PaletteUsage.ColorBlind ||| PaletteUsage.LCD\n                                    Colors = [| C3b(246uy,239uy,247uy); C3b(189uy,201uy,225uy); C3b(103uy,169uy,207uy); C3b(2uy,129uy,138uy) |]\n                                }\n\n                                5, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(246uy,239uy,247uy); C3b(189uy,201uy,225uy); C3b(103uy,169uy,207uy); C3b(28uy,144uy,153uy)\n                                                C3b(1uy,108uy,89uy) |]\n                                }\n\n                                6, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(246uy,239uy,247uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy); C3b(103uy,169uy,207uy)\n                                                C3b(28uy,144uy,153uy); C3b(1uy,108uy,89uy) |]\n                                }\n\n                                7, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(246uy,239uy,247uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy); C3b(103uy,169uy,207uy)\n                                                C3b(54uy,144uy,192uy); C3b(2uy,129uy,138uy); C3b(1uy,100uy,80uy) |]\n                                }\n\n                                8, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,247uy,251uy); C3b(236uy,226uy,240uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy)\n                                                C3b(103uy,169uy,207uy); C3b(54uy,144uy,192uy); C3b(2uy,129uy,138uy); C3b(1uy,100uy,80uy) |]\n                                }\n\n                                9, {\n                                    Usage = PaletteUsage.ColorBlind\n                                    Colors = [| C3b(255uy,247uy,251uy); C3b(236uy,226uy,240uy); C3b(208uy,209uy,230uy); C3b(166uy,189uy,219uy)\n                                                C3b(103uy,169uy,207uy); C3b(54uy,144uy,192uy); C3b(2uy,129uy,138uy); C3b(1uy,108uy,89uy)\n                                                C3b(1uy,70uy,54uy) |]\n                                }\n\n                            ]\n                    }\n\n            /// Array of all available color schemes.\n            let All =\n                [|\n                    Diverging.Spectral; Diverging.RdYlGn; Diverging.RdBu; Diverging.PiYG; Diverging.PRGn; Diverging.RdYlBu\n                    Diverging.BrBG; Diverging.RdGy; Diverging.PuOr; Qualitative.Set2; Qualitative.Accent; Qualitative.Set1\n                    Qualitative.Set3; Qualitative.Dark2; Qualitative.Paired; Qualitative.Pastel2; Qualitative.Pastel1; Sequential.OrRd\n                    Sequential.PuBu; Sequential.BuPu; Sequential.Oranges; Sequential.BuGn; Sequential.YlOrBr; Sequential.YlGn\n                    Sequential.Reds; Sequential.RdPu; Sequential.Greens; Sequential.YlGnBu; Sequential.Purples; Sequential.GnBu\n                    Sequential.Greys; Sequential.YlOrRd; Sequential.PuRd; Sequential.Blues; Sequential.PuBuGn\n                |]\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Color/ColorBrewerSchemes.fsx",
    "content": "#r \"../../../bin/Debug/netstandard2.0/Aardvark.Base.dll\"\n#r \"../../../bin/Debug/netstandard2.0/Aardvark.Base.FSharp.dll\"\n#r \"../../../bin/Debug/net6.0/FSharp.Data.Adaptive.dll\"\n#r \"System.Net.Http.dll\"\n\nopen Aardvark.Base\nopen System\nopen System.IO\nopen System.Text\nopen System.Text.RegularExpressions\nopen System.Net.Http\n\nfsi.ShowDeclarationValues <- false\n\nlet source =\n    let ws = Regex(@\"\\s+\", RegexOptions.Compiled)\n\n    use client = new HttpClient()\n    use task = client.GetStringAsync \"https://raw.githubusercontent.com/axismaps/colorbrewer/master/colorbrewer_schemes.js\"\n    task.Wait()\n\n    task.Result\n    |> String.getLines\n    |> Array.map (fun str -> ws.Replace(str, \"\"))\n\nmodule Regex =\n\n    let Scheme =\n        Regex(\n            @\"^(?<Name>[A-Za-z0-9]+):\\{\" +\n            @\"(?<Palettes>(?:[0-9]:\\[.+?\\],?)+)\" +\n            @\"'properties':\\{(?<Properties>.+)\\}\\},?$\",\n            RegexOptions.Multiline\n        );\n\n    let Palette =\n        Regex(@\"(?<Size>[0-9]+):\\[(?<Colors>[0-9'rgb\\(\\),]+)\\]\", RegexOptions.Compiled);\n\n    let Color =\n        Regex(@\"'(?<Color>rgb\\([0-9]{1,3},[0-9]{1,3},[0-9]{1,3}\\))'\", RegexOptions.Compiled)\n\n    let RGB =\n        Regex(@\"^rgb\\((?<R>[0-9]{1,3}),(?<G>[0-9]{1,3}),(?<B>[0-9]{1,3})\\)$\", RegexOptions.Compiled)\n\n    let Property =\n        Regex(@\"'(?<Key>[a-zA-Z]+)':(?:'(?<Value>[a-zA-Z]+)'|\\[(?<PerPaletteValue>[0-9,]+)\\])\", RegexOptions.Compiled);\n\n\ntype Severity =\n    | Warning = 0\n    | Error = 1\n\nlet messages = ResizeArray<Severity * string>()\n\nlet log severity fmt =\n    Printf.kprintf (fun str -> messages.Add (severity, str)) fmt\n\nlet schemes =\n    source |> Array.choose (fun str ->\n        let m = Regex.Scheme.Match str\n\n        if m.Success then\n            let schemeName = m.Groups.[\"Name\"].Value\n\n            try\n                let properties =\n                    Regex.Property.Matches m.Groups.[\"Properties\"].Value\n                    |> Seq.map (fun p ->\n                        let value =\n                            if p.Groups.[\"Value\"].Success then p.Groups.[\"Value\"].Value\n                            else p.Groups.[\"PerPaletteValue\"].Value\n\n                        p.Groups.[\"Key\"].Value, value\n                    )\n                    |> Map.ofSeq\n\n                let typ =\n                    match properties.[\"type\"] with\n                    | \"div\"  -> ColorBrewer.SchemeType.Diverging\n                    | \"qual\" -> ColorBrewer.SchemeType.Qualitative\n                    | \"seq\"  -> ColorBrewer.SchemeType.Sequential\n                    | t -> failwithf \"Unknown scheme type '%s'\" t\n\n                let colors =\n                    Regex.Palette.Matches m.Groups.[\"Palettes\"].Value\n                    |> Seq.map (fun p ->\n                        let size = Int32.Parse p.Groups.[\"Size\"].Value\n\n                        let colors =\n                            Regex.Color.Matches p.Groups.[\"Colors\"].Value\n                            |> Seq.map (fun m ->\n                                let m = Regex.RGB.Match m.Groups.[\"Color\"].Value\n                                let r = m.Groups.[\"R\"].Value\n                                let g = m.Groups.[\"G\"].Value\n                                let b = m.Groups.[\"B\"].Value\n                                $\"C3b({r}uy,{g}uy,{b}uy)\"\n                            )\n                            |> Array.ofSeq\n\n                        if colors.Length <> size then\n                            failwithf \"Size mismatch (expected %d but got %d)\" size colors.Length\n\n                        colors\n                    )\n                    |> Array.ofSeq\n\n                let getFlags (propertyName : string) =\n                    let values =\n                        properties.[propertyName] |> String.split \",\" |> Array.map (fun str ->\n                            Int32.Parse str = 1\n                        )\n\n                    if values.Length >= colors.Length then values\n                    elif values.Length = 1 then Array.replicate colors.Length values.[0]\n                    else\n                        let missing = Array.replicate (colors.Length - values.Length) false\n                        log Severity.Warning \"Property '%s' in scheme '%s' has %d entries but expected %d.\" propertyName schemeName values.Length colors.Length\n                        Array.concat [values; missing]\n\n                let blind  = getFlags \"blind\"\n                let print  = getFlags \"print\"\n                let copy   = getFlags \"copy\"\n                let screen = getFlags \"screen\"\n\n                let palettes =\n                    colors |> Array.mapi (fun i c ->\n                        let mutable usage = Set.empty\n                        if blind.[i] then usage <- usage |> Set.add ColorBrewer.PaletteUsage.ColorBlind\n                        if print.[i] then usage <- usage |> Set.add ColorBrewer.PaletteUsage.Print\n                        if copy.[i] then usage <- usage |> Set.add ColorBrewer.PaletteUsage.PhotoCopy\n                        if screen.[i] then usage <- usage |> Set.add ColorBrewer.PaletteUsage.LCD\n\n                        c.Length, {| Colors = c; Usage = usage |}\n                    )\n                    |> Map.ofArray\n\n                Some {| Name = schemeName; Type = typ; Palettes = palettes |}\n\n            with e ->\n                log Severity.Error \"Failed to parse scheme %s: %s\" schemeName e.Message\n                None\n        else\n            None\n    )\n\nprintfn \"Found %d schemes\" schemes.Length\n\nlet writeToFile() =\n    let builder = StringBuilder()\n\n    let writeln indent fmt =\n        Printf.kprintf (fun str -> builder.AppendLine(str |> String.indent indent) |> ignore) fmt\n\n    let schemeTypeComments =\n        Map.ofList [\n            ColorBrewer.SchemeType.Diverging, \"/// Diverging schemes put equal emphasis on mid-range critical values and extremes at both ends of the data range.\\n/// The critical class or break in the middle of the legend is emphasized with light colors and low and high extremes are\\n/// emphasized with dark colors that have contrasting hues.\"\n\n            ColorBrewer.SchemeType.Qualitative, \"/// Qualitative schemes do not imply magnitude differences between legend classes, and hues are used to\\n/// create the primary visual differences between classes. Qualitative schemes are best suited to representing nominal or categorical data.\"\n\n            ColorBrewer.SchemeType.Sequential, \"/// Sequential schemes are suited to ordered data that progress from low to high.\\n/// Lightness steps dominate the look of these schemes, with light colors for low data values to dark colors for high data values.\"\n        ]\n\n    writeln 0 \"namespace Aardvark.Base\"\n    writeln 0 \"\"\n    writeln 0 \"[<AutoOpen>]\"\n    writeln 0 \"module ColorBrewerSchemes =\"\n    writeln 1 \"open ColorBrewer\"\n    writeln 0 \"\"\n    writeln 1 \"/// Brewer color schemes designed for choropleth map visualizations.\"\n    writeln 1 \"module ColorBrewer =\"\n    writeln 0 \"\"\n    writeln 2 \"module Scheme =\"\n    writeln 0 \"\"\n\n    let grouped =\n        schemes |> Array.groupBy (fun s -> s.Type)\n\n    for (typ, schemes) in grouped do\n\n        for c in schemeTypeComments.[typ] |> String.getLines do\n            writeln 3 \"%s\" c\n\n        writeln 3 \"module %A =\" typ\n        writeln 0 \"\"\n\n        for s in schemes do\n            writeln 4 \"let %s =\" s.Name\n            writeln 5 \"{\"\n            writeln 6 \"Name = Sym.ofString \\\"%s\\\"\" s.Name\n            writeln 6 \"Type = SchemeType.%A\" s.Type\n            writeln 6 \"Palettes =\"\n            writeln 7 \"MapExt.ofList [\"\n\n            for (KeyValue(n, p)) in s.Palettes do\n                let usage =\n                    if Set.isEmpty p.Usage then \"PaletteUsage.None\"\n                    else p.Usage |> Seq.map (fun u -> $\"PaletteUsage.{u}\") |> String.concat \" ||| \"\n\n                let colors =\n                    Array.chunkBySize 4 p.Colors\n                    |> Array.map (String.concat \"; \")\n\n                colors.[0] <- $\"Colors = [| {colors.[0]}\"\n                colors.[colors.Length - 1] <- $\"{colors.[colors.Length - 1]} |]\"\n\n                writeln 8 \"%d, {\" n\n                writeln 9 \"Usage = %s\" usage\n\n                writeln 9 \"%s\" colors.[0]\n                for i = 1 to colors.Length - 1 do\n                    writeln 12 \"%s\" colors.[i]\n\n                writeln 8 \"}\"\n                writeln 0 \"\"\n\n            writeln 7 \"]\"\n            writeln 5 \"}\"\n            writeln 0 \"\"\n\n    writeln 3 \"/// Array of all available color schemes.\"\n    writeln 3 \"let All =\"\n    writeln 4 \"[|\"\n\n    let all =\n        grouped |> Array.collect (fun (typ, schemes) ->\n            schemes |> Array.map (fun s -> $\"{typ}.{s.Name}\")\n        )\n        |> Array.chunkBySize 6\n        |> Array.map (String.concat \"; \")\n\n    for schemes in all do\n        writeln 5 \"%s\" schemes\n\n    writeln 4 \"|]\"\n\n\n    let file = Path.Combine(__SOURCE_DIRECTORY__, \"ColorBrewerSchemes.fs\")\n    File.writeAllText file (builder.ToString())\n\n    for s in schemes do\n        printfn \"%s\" s.Name\n        printfn \"%A\" s.Palettes\n\n    for (s, e) in messages do\n        printfn \"[%A] %s\" s e\n\nwriteToFile()"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Geometry/Boundable.fs",
    "content": "﻿namespace Aardvark.Base.Geometry\n\nopen System\nopen System.Runtime.CompilerServices\nopen Aardvark.Base\n\ntype RayHit<'r> =\n    struct\n        val mutable public T : float\n        val mutable public Value : 'r\n\n        new(t, value) = { T = t; Value = value }\n    end\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule RayHit =\n    let inline create (t : float) (value : 'r) = RayHit(t, value)\n    let inline t (hit : RayHit<'r>) = hit.T\n    let inline value (hit : RayHit<'r>) = hit.Value\n\n    let map (f : 'a -> 'b) (hit : RayHit<'a>) =\n        RayHit(hit.T, f hit.Value)\n\ntype RayPart =\n    struct\n        val mutable public Ray  : FastRay3d\n        val mutable public TMin : float\n        val mutable public TMax : float\n\n        [<Extension>]\n        static member Intersects(x : RayPart, tri : Triangle3d) =\n            let ray = x.Ray.Ray\n            let mutable t = 0.0\n            if tri.Intersects(ray, x.TMin, x.TMax, &t) then\n                Some t\n            else\n                None\n\n        [<Extension>]\n        static member IntersectsV(x : RayPart, tri : Triangle3d) =\n            let ray = x.Ray.Ray\n            let mutable t = 0.0\n            if tri.Intersects(ray, x.TMin, x.TMax, &t) then\n                ValueSome t\n            else\n                ValueNone\n\n        [<Extension>]\n        static member Intersects(x : RayPart, box : Box3d) =\n            let ray = x.Ray\n            let mutable tmin = x.TMin\n            let mutable tmax = x.TMax\n            if ray.Intersects(box, &tmin, &tmax) then\n                Some tmin\n            else\n                None\n\n        [<Extension>]\n        static member IntersectsV(x : RayPart, box : Box3d) =\n            let ray = x.Ray\n            let mutable tmin = x.TMin\n            let mutable tmax = x.TMax\n            if ray.Intersects(box, &tmin, &tmax) then\n                ValueSome tmin\n            else\n                ValueNone\n\n        [<Extension>]\n        static member Intersects(x : RayPart, sphere : Sphere3d) =\n            let ray = x.Ray.Ray\n            //  | (o + t * d - c) |^2 = r^2\n            // let x = o - c\n            //  | (x + t * d) |^2 = r^2\n            //  <x + t*d | x + t*d> = r^2\n            //  <x|x>  + <t*d|x> + <x|t*d> + <t*d|t*d> = r^2\n            //  t^2*(<d|d>) + t*(2*<d|x>) + (<x|x> - r^2) = 0\n\n            let dp = ray.Origin - sphere.Center\n            let d = ray.Direction\n            let a = d.LengthSquared\n            let b = 2.0 * Vec.dot d dp\n            let c = dp.LengthSquared - sphere.RadiusSquared\n\n            let s = b*b - 4.0*a*c\n            if s < 0.0 then\n                None\n            else\n                let s = sqrt s\n                let t1 = (-b + s) / (2.0 * a)\n                let t2 = (-b - s) / (2.0 * a)\n\n                let t1v = t1 >= x.TMin && t1 <= x.TMax\n                let t2v = t2 >= x.TMin && t2 <= x.TMax\n\n                if t1v && t2v then Some (min t1 t2)\n                elif t1v then Some t1\n                elif t2v then Some t2\n                else None\n\n        [<Extension>]\n        static member IntersectsV(x : RayPart, sphere : Sphere3d) =\n            let ray = x.Ray.Ray\n            //  | (o + t * d - c) |^2 = r^2\n            // let x = o - c\n            //  | (x + t * d) |^2 = r^2\n            //  <x + t*d | x + t*d> = r^2\n            //  <x|x>  + <t*d|x> + <x|t*d> + <t*d|t*d> = r^2\n            //  t^2*(<d|d>) + t*(2*<d|x>) + (<x|x> - r^2) = 0\n\n            let dp = ray.Origin - sphere.Center\n            let d = ray.Direction\n            let a = d.LengthSquared\n            let b = 2.0 * Vec.dot d dp\n            let c = dp.LengthSquared - sphere.RadiusSquared\n\n            let s = b*b - 4.0*a*c\n            if s < 0.0 then\n                ValueNone\n            else\n                let s = sqrt s\n                let t1 = (-b + s) / (2.0 * a)\n                let t2 = (-b - s) / (2.0 * a)\n\n                let t1v = t1 >= x.TMin && t1 <= x.TMax\n                let t2v = t2 >= x.TMin && t2 <= x.TMax\n\n                if t1v && t2v then ValueSome (min t1 t2)\n                elif t1v then ValueSome t1\n                elif t2v then ValueSome t2\n                else ValueNone\n\n        [<Extension>]\n        static member Intersects(x : RayPart, cylinder : Cylinder3d) =\n            let ray = x.Ray.Ray\n            let tmin = x.TMin\n            let tmax = x.TMax\n            // taken from http://mrl.nyu.edu/~dzorin/rend05/lecture2.pdf\n            let v = ray.Direction\n            let va = cylinder.P1 - cylinder.P0\n            let la = Vec.length va\n            let va = va / la\n            let dp = ray.Origin - cylinder.P0\n            let r2 = cylinder.Radius * cylinder.Radius\n\n            let v' = v - (Vec.dot v va * va)\n            let dp' = dp - (Vec.dot dp va) * va\n\n            let a = v' |> Vec.lengthSquared\n            let b = 2.0 * (Vec.dot v' dp')\n            let c = Vec.lengthSquared dp' - r2\n            let s = b*b - 4.0*a*c\n            if s < 0.0 then\n                None\n            else\n                let s = sqrt s\n                let t1 = (-b + s) / (2.0 * a)\n                let t2 = (-b - s) / (2.0 * a)\n\n                let p0 = Plane3d(va, cylinder.P0)\n                let p1 = Plane3d(va, cylinder.P1)\n\n                let inline isValid (t : float) =\n                    let pt = ray.GetPointOnRay t\n                    t >= tmin && t <= tmax && p0.Height pt >= 0.0 && p1.Height pt <= 0.0\n\n                let t1 = if isValid t1 then ValueSome t1 else ValueNone\n                let t2 = if isValid t2 then ValueSome t2 else ValueNone\n\n                let t3 = \n                    let mutable t = 0.0\n                    let mutable pt = V3d.Zero\n                    if ray.Intersects(p0, &t, &pt) then\n                        let d = Vec.lengthSquared (pt - cylinder.P0)\n                        if d <= r2 then ValueSome t\n                        else ValueNone\n                    else\n                        ValueNone\n\n                let t4 = \n                    let mutable t = 0.0\n                    let mutable pt = V3d.Zero\n                    if ray.Intersects(p1, &t, &pt) then\n                        let d = Vec.lengthSquared (pt - cylinder.P1)\n                        if d <= r2 then ValueSome t\n                        else ValueNone\n                    else\n                        ValueNone\n\n                let hits = Array.chooseV id [|t1;t2;t3;t4|]\n                if hits.Length > 0 then\n                    hits |> Array.min |> Some\n                else\n                    None\n\n        [<Extension>]\n        static member IntersectsV(x : RayPart, cylinder : Cylinder3d) =\n            let ray = x.Ray.Ray\n            let tmin = x.TMin\n            let tmax = x.TMax\n            // taken from http://mrl.nyu.edu/~dzorin/rend05/lecture2.pdf\n            let v = ray.Direction\n            let va = cylinder.P1 - cylinder.P0\n            let la = Vec.length va\n            let va = va / la\n            let dp = ray.Origin - cylinder.P0\n            let r2 = cylinder.Radius * cylinder.Radius\n\n            let v' = v - (Vec.dot v va * va)\n            let dp' = dp - (Vec.dot dp va) * va\n\n            let a = v' |> Vec.lengthSquared\n            let b = 2.0 * (Vec.dot v' dp')\n            let c = Vec.lengthSquared dp' - r2\n            let s = b*b - 4.0*a*c\n            if s < 0.0 then\n                ValueNone\n            else\n                let s = sqrt s\n                let t1 = (-b + s) / (2.0 * a)\n                let t2 = (-b - s) / (2.0 * a)\n\n                let p0 = Plane3d(va, cylinder.P0)\n                let p1 = Plane3d(va, cylinder.P1)\n\n                let inline isValid (t : float) =\n                    let pt = ray.GetPointOnRay t\n                    t >= tmin && t <= tmax && p0.Height pt >= 0.0 && p1.Height pt <= 0.0\n\n                let t1 = if isValid t1 then ValueSome t1 else ValueNone\n                let t2 = if isValid t2 then ValueSome t2 else ValueNone\n\n                let t3 =\n                    let mutable t = 0.0\n                    let mutable pt = V3d.Zero\n                    if ray.Intersects(p0, &t, &pt) then\n                        let d = Vec.lengthSquared (pt - cylinder.P0)\n                        if d <= r2 then ValueSome t\n                        else ValueNone\n                    else\n                        ValueNone\n\n                let t4 =\n                    let mutable t = 0.0\n                    let mutable pt = V3d.Zero\n                    if ray.Intersects(p1, &t, &pt) then\n                        let d = Vec.lengthSquared (pt - cylinder.P1)\n                        if d <= r2 then ValueSome t\n                        else ValueNone\n                    else\n                        ValueNone\n\n                let hits = Array.chooseV id [|t1;t2;t3;t4|]\n                if hits.Length > 0 then\n                    hits |> Array.min |> ValueSome\n                else\n                    ValueNone\n\n        new(ray, min, max) = { Ray = ray; TMin = min; TMax = max }\n        new(ray) = { Ray = ray; TMin = 0.0; TMax = Double.PositiveInfinity }\n    end\n    \n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule RayPart =\n    let inline ray (part : RayPart) = part.Ray\n    let inline tmin (part : RayPart) = part.TMin\n    let inline tmax (part : RayPart) = part.TMax\n    let inline ofRay (ray : FastRay3d) = RayPart(ray)\n    let inline create (ray : FastRay3d) (tmin : float) (tmax : float) = RayPart(ray, tmin, tmax)\n\n    let inline intersect (part : RayPart) a =\n        let inline call (d : ^d) (a : ^a) = ((^d or ^a) : (static member Intersects : ^d * ^a -> float option) (d, a))\n        call part a\n\n    let inline intersectV (part : RayPart) a =\n        let inline call (d : ^d) (a : ^a) = ((^d or ^a) : (static member IntersectsV : ^d * ^a -> float voption) (d, a))\n        call part a\n\n[<Flags>]\ntype PlaneSide =\n    | None = 0x0\n    | Above = 0x1\n    | Below = 0x2\n    | Both = 0x3\n\n[<AbstractClass>]\ntype Spatial<'a>() =\n    abstract member ComputeBounds : seq<'a> -> Box3d\n    abstract member PlaneSide : Plane3d * 'a -> PlaneSide\n\nmodule Spatial =\n    let private side (pt : V3d) (plane : Plane3d) =\n        let h = plane.Height pt\n        if h > 0.0 then PlaneSide.Above\n        elif h < 0.0 then PlaneSide.Below\n        else PlaneSide.Both\n\n    let triangle =\n        { new Spatial<Triangle3d>() with\n            member x.ComputeBounds tris =\n                tris |> Seq.collect (fun t -> [t.P0; t.P1; t.P2]) |> Box3d\n\n            member x.PlaneSide(plane, tri) =\n                side tri.P0 plane ||| side tri.P1 plane ||| side tri.P2 plane\n        }\n\n    let box =\n        { new Spatial<Box3d>() with\n            member x.ComputeBounds boxes =\n                Box3d boxes\n\n            member x.PlaneSide(plane, box) =\n                let hmin = plane.Height box.Min\n                let hmax = plane.Height box.Max\n                if hmin > 0.0 && hmax > 0.0 then\n                    PlaneSide.Above\n                elif hmin < 0.0 && hmax < 0.0 then\n                    PlaneSide.Below\n                else\n                    PlaneSide.Both\n        }\n\n    let point =\n        { new Spatial<V3d>() with\n            member x.ComputeBounds pts =\n                pts |> Box3d\n\n            member x.PlaneSide(plane, pt) =\n                side pt plane\n        }\n\ntype IRayIntersectable<'a> =\n    abstract member Intersect : tryIntersect : (RayPart -> 'a -> RayHit<'r> option) * part : RayPart -> RayHit<'r> option\n\ntype ICullable<'a> =\n    abstract member Cull : hull : FastHull3d -> list<'a>\n\n\n[<AbstractClass; Sealed; Extension>]\ntype GeometryExtensions private() =\n\n    static let toPlane (v : V4d) =\n        Plane3d(-v.XYZ, v.W)\n\n    static let toHull3d (viewProj : Trafo3d) =\n        let r0 = viewProj.Forward.R0\n        let r1 = viewProj.Forward.R1\n        let r2 = viewProj.Forward.R2\n        let r3 = viewProj.Forward.R3\n\n\n        Hull3d [|\n            r3 + r0 |> toPlane  // left\n            r3 - r0 |> toPlane  // right\n            r3 + r1 |> toPlane  // bottom\n            r3 - r1 |> toPlane  // top\n            r3 + r2 |> toPlane  // near\n            r3 - r2 |> toPlane  // far\n        |]\n\n    [<Extension>]\n    static member inline Intersect(this : IRayIntersectable<_>, part : RayPart) =\n        let intersect (part : RayPart) (value : 'a) = \n            match RayPart.intersect part value with\n                | Some t -> Some (RayHit(t, value))\n                | None -> None\n\n        this.Intersect(intersect, part)\n        \n    [<Extension>]\n    static member CullFrustum(this : ICullable<'a>, viewProj : Trafo3d) =\n        let hull = toHull3d viewProj\n        this.Cull(FastHull3d hull)"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Geometry/Bvh.fs",
    "content": "﻿namespace Aardvark.Base.Geometry\n\nopen Aardvark.Base\n\n[<RequireQualifiedAccess>]\ntype BvhNode =\n    | Leaf of id : int\n    | Node of lBox : Box3d * rBox : Box3d * left : BvhNode * right : BvhNode\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule BvhNode =\n    open Aardvark.Base.Sorting\n\n    [<Literal>]\n    let private splitPenalty = 1.0\n\n    type private BvhSplit =\n        {\n            leftCount : int\n            rightCount : int\n            sortedIndexArray : int[]\n            leftBox : Box3d\n            rightBox : Box3d\n        }\n\n    let private cost (lBox : Box3d) (rBox : Box3d) (lWeight : float) (rWeight : float) (invBoxArea : float) =\n        let cBox = Box.Intersection(lBox, rBox)\n        let cSize =\n            V3d(\n                (if cBox.Max.X > cBox.Min.X then cBox.Max.X - cBox.Min.X else 0.0),\n                (if cBox.Max.Y > cBox.Min.Y then cBox.Max.Y - cBox.Min.Y else 0.0),\n                (if cBox.Max.Z > cBox.Min.Z then cBox.Max.Z - cBox.Min.Z else 0.0)\n            )\n\n        let leftP = lBox.SurfaceArea * invBoxArea\n        let rightP = rBox.SurfaceArea * invBoxArea\n        let commonP = 2.0 * (cSize.X * cSize.Y + cSize.X * cSize.Z + cSize.Y * cSize.Z) * invBoxArea\n\n        (leftP + (commonP * splitPenalty)) * (1.0 + lWeight) +\n        (rightP + (commonP * splitPenalty)) * (1.0 + rWeight)\n\n    let private calculateSplit (indexArray : int[]) (start : int) (count : int) (box : Box3d) (boxes : Box3d[]) =\n        let mutable bestLeft = 0\n        let mutable bestCost = System.Double.PositiveInfinity\n        let mutable bestLeftBox = Box3d.Invalid\n        let mutable bestRightBox = Box3d.Invalid\n        let mutable bestDim = -1\n        let invBoxArea = 1.0 / box.SurfaceArea\n\n        let iaa = Array.init 3 (fun _ -> Array.sub indexArray start count)\n\n        for d in 0 .. 2 do\n            let ia = iaa.[d]\n            ia.PermutationQuickSortAscending(boxes, fun ba i -> ba.[int i].Center.[d])\n\n            let bbLeftArray = ia.ScanLeft(Box3d.Invalid, fun b i -> Box3d(b, boxes.[i]))\n            let bbRightArray = ia.ScanRight((fun i b -> Box3d(boxes.[i], b)), Box3d.Invalid)\n\n            for s in 1 .. count - 1 do\n                let lBox = bbLeftArray.[s-1]\n                let rBox = bbRightArray.[s]\n\n                let lWeight = float s\n                let rWeight = float (count - s)\n\n                let cost = cost lBox rBox lWeight rWeight invBoxArea\n                if cost < bestCost then\n                    bestCost <- cost\n                    bestDim <- d\n                    bestLeft <- s\n                    bestLeftBox <- lBox\n                    bestRightBox <- rBox\n\n        {\n            leftCount = bestLeft\n            rightCount = count - bestLeft\n            sortedIndexArray = iaa.[bestDim]\n            leftBox = bestLeftBox\n            rightBox = bestRightBox\n        }\n\n    let rec build (boxes : Box3d[]) (indices : int[]) (start : int) (count : int) (box : Box3d) =\n        if count = 1 then\n            BvhNode.Leaf(indices.[start])\n        else\n            let split = calculateSplit indices start count box boxes\n            let left = build boxes split.sortedIndexArray 0 split.leftCount split.leftBox\n            let right = build boxes split.sortedIndexArray split.leftCount split.rightCount split.rightBox\n            BvhNode.Node(split.leftBox, split.rightBox, left, right)\n\n    let rec intersect (tryIntersect : RayPart -> 'a -> RayHit<'r> option) (data : 'a[]) (part : RayPart) (node : BvhNode) =\n        match node with\n        | BvhNode.Leaf id ->\n            tryIntersect part data.[id]\n\n        | BvhNode.Node(lBox, rBox, left, right) ->\n            let inline intersect part node = intersect tryIntersect data part node\n\n            let mutable lpart = part\n            let mutable rpart = part\n\n            let il = lpart.Ray.Intersects(lBox, &lpart.TMin, &lpart.TMax)\n            let ir = lpart.Ray.Intersects(rBox, &rpart.TMin, &rpart.TMax)\n\n            match il, ir with\n            | false, false ->\n                None\n\n            | true, false ->\n                intersect lpart left\n\n            | false, true ->\n                intersect rpart right\n\n            | true, true ->\n                if lpart.TMin < rpart.TMin then\n                    match intersect lpart left with\n                    | Some hit ->\n                        if hit.T > rpart.TMin then\n                            rpart.TMax <- hit.T\n                            match intersect rpart right with\n                            | Some hit -> Some hit\n                            | None -> Some hit\n                        else\n                            Some hit\n                    | None ->\n                        intersect rpart right\n                else\n                    match intersect rpart right with\n                    | Some hit ->\n                        if hit.T > lpart.TMin then\n                            lpart.TMax <- hit.T\n                            match intersect lpart left with\n                            | Some hit -> Some hit\n                            | None -> Some hit\n                        else\n                            Some hit\n                    | None ->\n                        intersect lpart left\n\n    let rec intersectV (tryIntersect : RayPart -> 'a -> RayHit<'r> voption) (data : 'a[]) (part : RayPart) (node : BvhNode) =\n        match node with\n        | BvhNode.Leaf id ->\n            tryIntersect part data.[id]\n\n        | BvhNode.Node(lBox, rBox, left, right) ->\n            let inline intersect part node = intersectV tryIntersect data part node\n\n            let mutable lpart = part\n            let mutable rpart = part\n\n            let il = lpart.Ray.Intersects(lBox, &lpart.TMin, &lpart.TMax)\n            let ir = lpart.Ray.Intersects(rBox, &rpart.TMin, &rpart.TMax)\n\n            match il, ir with\n            | false, false ->\n                ValueNone\n\n            | true, false ->\n                intersect lpart left\n\n            | false, true ->\n                intersect rpart right\n\n            | true, true ->\n                if lpart.TMin < rpart.TMin then\n                    match intersect lpart left with\n                    | ValueSome hit ->\n                        if hit.T > rpart.TMin then\n                            rpart.TMax <- hit.T\n                            match intersect rpart right with\n                            | ValueSome hit -> ValueSome hit\n                            | ValueNone -> ValueSome hit\n                        else\n                            ValueSome hit\n                    | ValueNone ->\n                        intersect rpart right\n                else\n                    match intersect rpart right with\n                    | ValueSome hit ->\n                        if hit.T > lpart.TMin then\n                            lpart.TMax <- hit.T\n                            match intersect lpart left with\n                            | ValueSome hit -> ValueSome hit\n                            | ValueNone -> ValueSome hit\n                        else\n                            ValueSome hit\n                    | ValueNone ->\n                        intersect lpart left\n\n    module Seq = \n        open System.Collections.Generic\n\n        let rec private mergeSortedAux (cmp : 'a -> 'a -> int) (cl : 'a voption) (cr : 'a voption) (l : IEnumerator<'a>) (r : IEnumerator<'a>) =\n            seq {\n                let cl =\n                    match cl with\n                    | ValueSome c -> ValueSome c\n                    | ValueNone ->\n                        if l.MoveNext() then ValueSome l.Current\n                        else ValueNone\n\n                let cr = \n                    match cr with\n                    | ValueSome c -> ValueSome c\n                    | ValueNone ->\n                        if r.MoveNext() then ValueSome r.Current\n                        else ValueNone\n\n                match cl, cr with\n                | ValueNone, ValueNone ->\n                    ()\n                | ValueSome cl, ValueNone ->\n                    yield cl\n                    yield! mergeSortedAux cmp ValueNone ValueNone l r\n\n                | ValueNone, ValueSome cr ->\n                    yield cr\n                    yield! mergeSortedAux cmp ValueNone ValueNone l r\n\n                | ValueSome vl, ValueSome vr ->\n                    let c = cmp vl vr\n                    if c < 0 then\n                        yield vl\n                        yield! mergeSortedAux cmp ValueNone cr l r\n                    else\n                        yield vr\n                        yield! mergeSortedAux cmp cl ValueNone l r\n            }\n\n        let mergeSorted (cmp : 'a -> 'a -> int) (l : seq<'a>) (r : seq<'a>) =\n            seq {\n                use le = l.GetEnumerator()\n                use re = r.GetEnumerator()\n                yield! mergeSortedAux cmp ValueNone ValueNone le re\n            }\n\n    let rec intersections (tryIntersect : RayPart -> 'a -> RayHit<'r> option) (data : 'a[]) (part : RayPart) (node : BvhNode) =\n        match node with\n        | BvhNode.Leaf id ->\n            match tryIntersect part data.[id] with\n            | Some h -> Seq.singleton h\n            | None -> Seq.empty\n\n        | BvhNode.Node(lBox, rBox, left, right) ->\n            let mutable lpart = part\n            let mutable rpart = part\n\n            let il = lpart.Ray.Intersects(lBox, &lpart.TMin, &lpart.TMax)\n            let ir = lpart.Ray.Intersects(rBox, &rpart.TMin, &rpart.TMax)\n\n            match il, ir with\n            | false, false ->\n                Seq.empty\n\n            | true, false ->\n                intersections tryIntersect data lpart left\n\n            | false, true ->\n                intersections tryIntersect data rpart right\n\n            | true, true ->\n                seq {\n                    if lpart.TMax <= rpart.TMin then\n                        // l strictly before r\n                        yield! intersections tryIntersect data lpart left\n                        yield! intersections tryIntersect data rpart right\n\n                    elif rpart.TMax <= lpart.TMin then\n                        // r strictly before l then\n                        yield! intersections tryIntersect data rpart right\n                        yield! intersections tryIntersect data lpart left\n\n                    else\n                        let li = intersections tryIntersect data lpart left\n                        let ri = intersections tryIntersect data rpart right\n                        yield! Seq.mergeSorted (fun (lh : RayHit<_>) (rh : RayHit<_>) -> compare lh.T rh.T) li ri\n                }\n\n    let rec intersectionsV (tryIntersect : RayPart -> 'a -> RayHit<'r> voption) (data : 'a[]) (part : RayPart) (node : BvhNode) =\n        match node with\n        | BvhNode.Leaf id ->\n            match tryIntersect part data.[id] with\n            | ValueSome h -> Seq.singleton h\n            | ValueNone -> Seq.empty\n\n        | BvhNode.Node(lBox, rBox, left, right) ->\n            let mutable lpart = part\n            let mutable rpart = part\n\n            let il = lpart.Ray.Intersects(lBox, &lpart.TMin, &lpart.TMax)\n            let ir = lpart.Ray.Intersects(rBox, &rpart.TMin, &rpart.TMax)\n\n            match il, ir with\n            | false, false ->\n                Seq.empty\n\n            | true, false ->\n                intersectionsV tryIntersect data lpart left\n\n            | false, true ->\n                intersectionsV tryIntersect data rpart right\n\n            | true, true ->\n                seq {\n                    if lpart.TMax <= rpart.TMin then\n                        // l strictly before r\n                        yield! intersectionsV tryIntersect data lpart left\n                        yield! intersectionsV tryIntersect data rpart right\n\n                    elif rpart.TMax <= lpart.TMin then\n                        // r strictly before l then\n                        yield! intersectionsV tryIntersect data rpart right\n                        yield! intersectionsV tryIntersect data lpart left\n\n                    else\n                        let li = intersectionsV tryIntersect data lpart left\n                        let ri = intersectionsV tryIntersect data rpart right\n                        yield! Seq.mergeSorted (fun (lh : RayHit<_>) (rh : RayHit<_>) -> compare lh.T rh.T) li ri\n                }\n\n    let cull (hull : FastHull3d) (node : BvhNode) =\n        let rec cullAcc (hull : FastHull3d) (res : System.Collections.Generic.List<int>) (node : BvhNode) =\n            match node with\n            | BvhNode.Leaf id ->\n                res.Add id\n\n            | BvhNode.Node(lBox, rBox, left, right) ->\n                if hull.Intersects(lBox) then\n                    cullAcc hull res left\n\n                if hull.Intersects(rBox) then\n                    cullAcc hull res right\n        let res = System.Collections.Generic.List()\n        cullAcc hull res node\n        res |> CSharpList.toList\n\ntype BvhTree<'a>(data : 'a[], bounds : Box3d, root : BvhNode option) =\n    member x.Data = data\n    member x.Root = root\n    member x.Bounds = bounds\n\n    member x.Intersect (tryIntersect : RayPart -> 'a -> RayHit<'r> option, part : RayPart) =\n        match root with\n        | Some root ->\n            let mutable part = part\n            if part.Ray.Intersects(bounds, &part.TMin, &part.TMax) then\n                BvhNode.intersect tryIntersect data part root\n            else\n                None\n        | None ->\n            None\n\n    member x.IntersectV (tryIntersect : RayPart -> 'a -> RayHit<'r> voption, part : RayPart) =\n        match root with\n        | Some root ->\n            let mutable part = part\n            if part.Ray.Intersects(bounds, &part.TMin, &part.TMax) then\n                BvhNode.intersectV tryIntersect data part root\n            else\n                ValueNone\n        | None ->\n            ValueNone\n\n    member x.Intersections (tryIntersect : RayPart -> 'a -> RayHit<'r> option, part : RayPart) =\n        match root with\n        | Some root ->\n            let mutable part = part\n            if part.Ray.Intersects(bounds, &part.TMin, &part.TMax) then\n                BvhNode.intersections tryIntersect data part root\n            else\n                Seq.empty\n        | None ->\n            Seq.empty\n\n    member x.IntersectionsV (tryIntersect : RayPart -> 'a -> RayHit<'r> voption, part : RayPart) =\n        match root with\n        | Some root ->\n            let mutable part = part\n            if part.Ray.Intersects(bounds, &part.TMin, &part.TMax) then\n                BvhNode.intersectionsV tryIntersect data part root\n            else\n                Seq.empty\n        | None ->\n            Seq.empty\n\n    member x.Cull (hull : FastHull3d) =\n        match root with\n        | Some root ->\n            if hull.Intersects(bounds) then\n                BvhNode.cull hull root |> List.map (Array.get data)\n            else\n                []\n        | None ->\n            []\n\n    interface IRayIntersectable<'a> with\n        member x.Intersect(tryIntersect, ray) = x.Intersect(tryIntersect, ray)\n\n    interface ICullable<'a> with\n        member x.Cull hull = x.Cull hull\n\n    new(data : array<struct ('a * Box3d)>) =\n        let data =\n            data |> Array.chooseV (fun struct (k, b) ->\n                if b.IsValid then\n                    let nb = Box3d.FromCenterAndSize(b.Center, b.Size + V3d(1E-8, 1E-8, 1E-8))\n                    ValueSome <| struct (k, nb)\n                else\n                    ValueNone\n            )\n        if data.Length > 0 then\n            let struct (data, boxes) = data |> Array.unzipV\n            let bounds = Box3d(boxes)\n            let root = BvhNode.build boxes (Array.init boxes.Length id) 0 boxes.Length bounds\n            BvhTree<'a>(data, bounds, Some root)\n        else\n            BvhTree<'a>([||], Box3d.Invalid, None)\n\n    new(data : array<'a * Box3d>) =\n        let data = \n            data |> Array.chooseV (fun (k, b) ->\n                if b.IsValid then   \n                    let nb = Box3d.FromCenterAndSize(b.Center, b.Size + V3d(1E-8, 1E-8, 1E-8))\n                    ValueSome <| struct (k, nb)\n                else\n                    ValueNone\n            )\n        if data.Length > 0 then\n            let struct (data, boxes) = data |> Array.unzipV\n            let bounds = Box3d(boxes)\n            let root = BvhNode.build boxes (Array.init boxes.Length id) 0 boxes.Length bounds\n            BvhTree<'a>(data, bounds, Some root)\n        else\n            BvhTree<'a>([||], Box3d.Invalid, None)\n\n    new(getBounds : 'a -> Box3d, data : 'a[]) =\n        let boxes = data |> Array.map(fun d -> struct (d, getBounds d))\n        BvhTree<'a>(boxes)\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule BvhTree =\n\n    let inline ofArray (data : array<'a * Box3d>) = BvhTree(data)\n    let inline ofArrayV (data : array<struct ('a * Box3d)>) = BvhTree(data)\n    let inline create (bounds : 'a -> Box3d) (data : array<'a>) = BvhTree(bounds, data)\n\n    let inline data (tree : BvhTree<'a>) = tree.Data\n    let inline root (tree : BvhTree<'a>) = tree.Root\n    let inline bounds (tree : BvhTree<'a>) = tree.Bounds\n\n    let inline intersect (tryIntersect : RayPart -> 'a -> RayHit<'r> option) (part : RayPart) (tree : BvhTree<'a>) =\n        tree.Intersect(tryIntersect, part)\n\n    let inline intersectV (tryIntersect : RayPart -> 'a -> RayHit<'r> voption) (part : RayPart) (tree : BvhTree<'a>) =\n        tree.IntersectV(tryIntersect, part)\n\n    let inline cull (hull : FastHull3d) (tree : BvhTree<'a>) =\n        tree.Cull(hull)\n\n    let inline cullFrustum (viewProj : Trafo3d) (tree : BvhTree<'a>) =\n        tree.CullFrustum(viewProj)"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Geometry/KdTree.fs",
    "content": "﻿namespace Aardvark.Base.Geometry\n\nopen Aardvark.Base\n\ntype KdBuildInfo =\n    struct\n        val mutable public MaxCount : int\n        val mutable public Splits : int\n\n        static member Default = KdBuildInfo(50, 3)\n        static member High = KdBuildInfo(50, 5)\n\n        new(cnt, splits) = { MaxCount = cnt; Splits = splits }\n    end\n\n[<RequireQualifiedAccess>]\ntype KdNode =\n    | Empty\n    | Leaf of int[]\n    | Node of Plane3d * KdNode * KdNode\n \n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule KdNode = \n\n    type private Split =\n        struct\n            val mutable public LeftCount    : int\n            val mutable public RightCount   : int\n            val mutable public BothCount    : int\n            val mutable public Plane        : Plane3d\n            val mutable public Cost         : float\n        end\n\n    let private count (spatial : Spatial<'a>) (plane : Plane3d) (indices : int[]) (data : 'a[]) =\n        let mutable left = 0\n        let mutable right = 0\n        let mutable both = 0\n\n        for i in indices do\n            let side = spatial.PlaneSide(plane, data.[i])\n            if side &&& PlaneSide.Both = PlaneSide.Both then\n                inc &both\n\n            elif side &&& PlaneSide.Above = PlaneSide.Above then\n                inc &right\n\n            elif side &&& PlaneSide.Below = PlaneSide.Below then\n                inc &left\n\n        (left, both, right)\n\n    let private cost (parent : Box3d) (lBox : Box3d) (rBox : Box3d) (left : int) (both : int) (right : int) =\n        let sl = lBox.SurfaceArea\n        let sr = rBox.SurfaceArea\n        let sp = parent.SurfaceArea\n\n        sl * (float left + 2.0 * float both) +\n        sr * (float right + 2.0 * float both)\n\n    let rec build (spatial : Spatial<'a>) (info : KdBuildInfo) (data : 'a[]) (bounds : Box3d) (indices : int[]) =\n        if indices.Length = 0 then\n            KdNode.Empty\n        elif indices.Length < info.MaxCount then\n            KdNode.Leaf indices\n        else\n            let mutable best = Split(Cost = System.Double.PositiveInfinity)\n\n            let size = bounds.Size\n\n            for d in 0 .. 2 do\n                let mutable n = V3d.Zero\n                n.[d] <- 1.0\n\n                let s = size.[d] / float (info.Splits + 1)\n                let mutable o = bounds.Min.[d] + s\n                let mutable lBox = bounds\n                let mutable rBox = bounds\n\n                for _ in 1 .. info.Splits do\n                    let p = Plane3d(n, o)\n                    lBox.Max.[d] <- o\n                    rBox.Min.[d] <- o\n\n                    let l,b,r = count spatial p indices data\n\n                    let cost = cost bounds lBox rBox l b r\n\n                    if cost < best.Cost then\n                        best.LeftCount <- l\n                        best.BothCount <- b\n                        best.RightCount <- r\n                        best.Cost <- cost\n                        best.Plane <- p\n\n                    o <- o + s\n\n            if best.BothCount = indices.Length then\n                KdNode.Leaf indices\n            else\n                let mutable lBox = bounds\n                let mutable rBox = bounds\n                lBox.Max.[best.Plane.Normal.MajorDim] <- best.Plane.Distance\n                rBox.Min.[best.Plane.Normal.MajorDim] <- best.Plane.Distance\n\n                let l = Array.zeroCreate (best.LeftCount + best.BothCount)\n                let r = Array.zeroCreate (best.RightCount + best.BothCount)\n                let mutable li = 0\n                let mutable ri = 0\n\n                for i in indices do\n                    let side = spatial.PlaneSide(best.Plane, data.[i])\n\n                    if (side &&& PlaneSide.Below) <> PlaneSide.None then\n                        l.[li] <- i\n                        inc &li\n\n                    if (side &&& PlaneSide.Above) <> PlaneSide.None then\n                        r.[ri] <- i\n                        inc &ri\n\n                let left = build spatial info data lBox l\n                let right = build spatial info data rBox r\n\n                KdNode.Node(best.Plane, left, right)\n\n    let rec intersect (tryIntersect : RayPart -> 'a -> RayHit<'r> option) (data : 'a[]) (part : RayPart) (node : KdNode) =\n        if part.TMax < part.TMin then\n            None\n        else\n            match node with\n            | KdNode.Empty ->\n                None\n\n            | KdNode.Leaf indices ->\n                let hits = indices |> Array.choose (Array.get data >> tryIntersect part) |> Array.toList\n                match hits with\n                | [] -> None\n                | hits -> hits |> List.minBy _.T |> Some\n\n            | KdNode.Node(plane, l, r) ->\n                let inline intersect p n = intersect tryIntersect data p n\n                let mutable t = 0.0\n                let mutable p = V3d.Zero\n\n                let dir = Vec.dot part.Ray.Ray.Direction plane.Normal\n                part.Ray.Ray.Intersects(plane, &t, &p) |> ignore\n\n                if dir > 0.0 then\n                    if t >= part.TMin && t <= part.TMax then\n                        match intersect (RayPart(part.Ray, part.TMin, t)) l with\n                        | Some hit -> Some hit\n                        | None -> intersect (RayPart(part.Ray, t, part.TMax)) r\n\n                    elif t < part.TMin then\n                        intersect part r\n\n                    else (* t > part.TMax *)\n                        intersect part l\n\n                elif dir < 0.0 then\n                    if t >= part.TMin && t <= part.TMax then\n                        match intersect (RayPart(part.Ray, part.TMin, t)) r with\n                        | Some hit -> Some hit\n                        | None -> intersect (RayPart(part.Ray, t, part.TMax)) l\n\n                    elif t < part.TMin then\n                        intersect part l\n\n                    else (* t > part.TMax *)\n                        intersect part r\n\n                else\n                    let h = plane.Height part.Ray.Ray.Origin\n                    if h > 0.0 then intersect part r\n                    else intersect part l\n\n    let rec intersectV (tryIntersect : RayPart -> 'a -> RayHit<'r> voption) (data : 'a[]) (part : RayPart) (node : KdNode) =\n        if part.TMax < part.TMin then\n            ValueNone\n        else\n            match node with\n            | KdNode.Empty ->\n                ValueNone\n\n            | KdNode.Leaf indices ->\n                let hits = indices |> Array.chooseV (Array.get data >> tryIntersect part) |> Array.toList\n                match hits with\n                | [] -> ValueNone\n                | hits -> hits |> List.minBy _.T |> ValueSome\n\n            | KdNode.Node(plane, l, r) ->\n                let inline intersect p n = intersectV tryIntersect data p n\n                let mutable t = 0.0\n                let mutable p = V3d.Zero\n\n                let dir = Vec.dot part.Ray.Ray.Direction plane.Normal\n                part.Ray.Ray.Intersects(plane, &t, &p) |> ignore\n\n                if dir > 0.0 then\n                    if t >= part.TMin && t <= part.TMax then\n                        match intersect (RayPart(part.Ray, part.TMin, t)) l with\n                        | ValueSome hit -> ValueSome hit\n                        | _ -> intersect (RayPart(part.Ray, t, part.TMax)) r\n\n                    elif t < part.TMin then\n                        intersect part r\n\n                    else (* t > part.TMax *)\n                        intersect part l\n\n                elif dir < 0.0 then\n                    if t >= part.TMin && t <= part.TMax then\n                        match intersect (RayPart(part.Ray, part.TMin, t)) r with\n                        | ValueSome hit -> ValueSome hit\n                        | _ -> intersect (RayPart(part.Ray, t, part.TMax)) l\n\n                    elif t < part.TMin then\n                        intersect part l\n\n                    else (* t > part.TMax *)\n                        intersect part r\n\n                else\n                    let h = plane.Height part.Ray.Ray.Origin\n                    if h > 0.0 then intersect part r\n                    else intersect part l\n\ntype KdTree<'a>(data : 'a[], root : KdNode, bounds : Box3d) =\n    member x.Bounds = bounds\n    member x.Data = data\n    member x.Root = root\n\n    member x.Intersect(tryIntersect : RayPart -> 'a -> RayHit<'r> option, ray : RayPart) : RayHit<'r> option =\n        let mutable ray = ray\n        if ray.Ray.Intersects(bounds, &ray.TMin, &ray.TMax) then\n            KdNode.intersect tryIntersect data ray root\n        else\n            None\n\n    member x.IntersectV(tryIntersect : RayPart -> 'a -> RayHit<'r> voption, ray : RayPart) : RayHit<'r> voption =\n        let mutable ray = ray\n        if ray.Ray.Intersects(bounds, &ray.TMin, &ray.TMax) then\n            KdNode.intersectV tryIntersect data ray root\n        else\n            ValueNone\n\n    interface IRayIntersectable<'a> with\n        member x.Intersect(tryIntersect, ray) = x.Intersect(tryIntersect, ray)\n\n    new(spatial : Spatial<'a>, info : KdBuildInfo, data : 'a[]) =\n        let bounds = spatial.ComputeBounds (data :> seq<_>)\n        let root = KdNode.build spatial info data bounds (Array.init data.Length id)\n        KdTree(data, root, bounds)\n\n    new(spatial : Spatial<'a>, data : 'a[]) =\n        KdTree(spatial, KdBuildInfo.Default, data)\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule KdTree =\n\n    let inline bounds (tree : KdTree<'a>) =\n        tree.Bounds\n\n    let inline root (tree : KdTree<'a>) =\n        tree.Root\n\n    let inline data (tree : KdTree<'a>) =\n        tree.Data\n\n    let inline build (spatial : Spatial<'a>) (info : KdBuildInfo) (data : 'a[]) =\n        KdTree(spatial, info, data)\n\n    let inline intersect (tryIntersect : RayPart -> 'a -> RayHit<'r> option) (ray : RayPart) (tree : KdTree<'a>) =\n        tree.Intersect(tryIntersect, ray)\n\n    let inline intersectV (tryIntersect : RayPart -> 'a -> RayHit<'r> voption) (ray : RayPart) (tree : KdTree<'a>) =\n        tree.IntersectV(tryIntersect, ray)"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Immutable/FingerTree.fs",
    "content": "﻿#if COMPILED\nnamespace Aardvark.Base\n#else\n#I @\"..\\..\\bin\\Release\"\n#r \"Aardvark.Base.dll\"\nopen Aardvark.Base\n#endif\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\n\n\n/// Measure represents a monoidal measure for the given type 'a \n/// where 'm has to fulfill monoid laws:\n///     1) identity element:    a <*> mempty = mempty <*> a = a\n///     2) associativity:       (a <*> b) <> c = a <*> (b <*> c)\ntype Measure<'a, 'm> = \n    { \n        quantify : 'a -> 'm\n        mappend : 'm -> 'm -> 'm\n        mempty : 'm\n    }\n\n[<AutoOpen>]\nmodule private MeasureHelpers =\n    \n    let inline ( +. ) (a : Measure<'a, 'm> -> 'm) (b : Measure<'a, 'm> -> 'm) : Measure<'a, 'm> -> 'm =\n        fun m -> m.mappend (a m) (b m)\n\n    let inline q (a : 'a) =\n        fun (m : Measure<'a, 'm>) -> m.quantify a\n\n    let inline cq (m : 'm) =\n        fun (_ : Measure<'a, 'm>) -> m\n\nmodule FingerTreeImplementation =\n    \n    type Affix<'a> =\n        | One of 'a\n        | Two of 'a * 'a\n        | Three of 'a * 'a * 'a\n        | Four of 'a * 'a * 'a * 'a\n\n    type Node<'a, 'm> =\n        | Node2 of 'm * 'a * 'a\n        | Node3 of 'm * 'a * 'a * 'a with\n\n        member inline x.Measure =\n            match x with\n                | Node2(m,_,_) -> m\n                | Node3(m,_,_,_) -> m\n\n    type FingerTreeNode<'a, 'm> =\n        | Empty\n        | Single of 'a\n        | Deep of m : 'm * prefix : Affix<'a> * deeper : FingerTreeNode<Node<'a, 'm>, 'm> * suffix : Affix<'a>\n       \n    type FingerTreeView<'a, 'm> =\n        | Nil\n        | Cons of 'a * FingerTreeNode<'a, 'm>   \n    \n    type FingerTreeSplit<'a, 'm> = { left : FingerTreeNode<'a, 'm>; value : 'a; right : FingerTreeNode<'a, 'm> }\n\n    type OptionalFingerTreeSplit<'a, 'm> =\n        | Left\n        | Right\n        | Inside of FingerTreeSplit<'a, 'm>\n\n    module Affix =\n        let inline one a = One(a)\n        let inline two a b = Two(a,b)\n        let inline three a b c = Three(a,b,c)\n        let inline four a b c d = Four(a,b,c,d)\n\n        let quanitfy (m : Measure<'a, 'm>) (a : Affix<'a>) =\n            match a with\n                | One(a) -> m |> (q a)\n                | Two(a,b) -> m |> (q a) +. (q b)\n                | Three(a,b,c) -> m |> (q a) +. (q b) +. (q c)\n                | Four(a,b,c,d) -> m |> (q a) +. (q b) +. (q c) +. (q d)\n\n        let prepend (value : 'a) (a : Affix<'a>) =\n            match a with\n                | One(a) -> Two(value, a)\n                | Two(a,b) -> Three(value, a, b)\n                | Three(a,b,c) -> Four(value, a, b, c)\n                | _ -> failwith \"affix can only hold 1 to 4 elements\"\n\n        let append (value : 'a) (a : Affix<'a>) =\n            match a with\n                | One(a) -> Two(a, value)\n                | Two(a,b) -> Three(a,b,value)\n                | Three(a,b,c) -> Four(a,b,c,value)\n                | _ -> failwith \"affix can only hold 1 to 4 elements\"\n\n        let toNode (m : Measure<'a, 'm>) (a : Affix<'a>) =\n            match a with\n                | Two(a,b) -> Node2(m |> (q a) +. (q b), a, b)\n                | Three(a,b,c) -> Node3(m |> (q a) +. (q b) +. (q c), a, b, c)\n                | _ -> failwith \"node can only hold 2 or 3 elements\"\n\n        let ofNode (n : Node<'a, 'm>) =\n            match n with\n                | Node2(_,a,b) -> Two(a,b)\n                | Node3(_,a,b,c) -> Three(a,b,c)\n\n        let toListFw (a : Affix<'a>) =\n            match a with\n                | One(a) -> [a]\n                | Two(a,b) -> [a;b]\n                | Three(a,b,c) -> [a;b;c]\n                | Four(a,b,c,d) -> [a;b;c;d]\n\n        let toListBw (a : Affix<'a>) =\n            match a with\n                | One(a) -> [a]\n                | Two(a,b) -> [b;a]\n                | Three(a,b,c) -> [c;b;a]\n                | Four(a,b,c,d) -> [d;c;b;a]\n\n        let ofList (l : list<'a>) =\n            match l with\n                | [a] -> One(a)\n                | [a;b] -> Two(a,b)\n                | [a;b;c] -> Three(a,b,c)\n                | [a;b;c;d] -> Four(a,b,c,d)\n                | _ -> failwith \"affix can only hold 1 to 4 elements\"\n\n        let first (a : Affix<'a>) =\n            match a with\n                | One(a) -> a\n                | Two(a,_) -> a\n                | Three(a,_,_) -> a\n                | Four(a,_,_,_) -> a \n\n        let last (a : Affix<'a>) =\n            match a with\n                | One(a) -> a\n                | Two(_,a) -> a\n                | Three(_,_,a) -> a\n                | Four(_,_,_,a) -> a \n\n        let takeFirst (a : Affix<'a>) =\n            match a with\n                | Two(a,b) -> a, One(b)\n                | Three(a,b,c) -> a, Two(b,c)\n                | Four(a,b,c,d) -> a, Three(b,c,d)\n                | _ -> failwith \"affix can only hold 1 to 4 elements\"\n\n        let takeLast(a : Affix<'a>) =\n            match a with\n                | Two(a,b) -> b, One(a)\n                | Three(a,b,c) -> c, Two(a,b)\n                | Four(a,b,c,d) -> d, Three(a,b,c)\n                | _ -> failwith \"affix can only hold 1 to 4 elements\"\n\n        let split (m : Measure<'a, 'm>) (pred : 'm -> bool) (start : 'm) (affix : Affix<'a>) =\n            match affix with\n                | One(a) ->\n                    let s = m.mappend start (m.quantify a)\n                    if pred s then None, Some a, None\n                    else Some affix, None, None\n\n                | Two(a,b) ->\n                    let s = m.mappend start (m.quantify a)\n                    if pred s then None, Some a, Some (One b)\n                    else\n                        let s = m.mappend s (m.quantify b)\n                        if pred s then Some (One a), Some b, None\n                        else Some affix, None, None\n                \n                | Three(a,b,c) ->\n                    let s = m.mappend start (m.quantify a)\n                    if pred s then None, Some a, Some (Two(b,c))\n                    else\n                        let s = m.mappend s (m.quantify b)\n                        if pred s then Some (One a), Some b, Some (One c)\n                        else\n                            let s = m.mappend s (m.quantify c)\n                            if pred s then Some (Two(a,b)), Some c, None\n                            else Some affix, None, None\n                \n                | Four(a,b,c,d) ->\n                    let s = m.mappend start (m.quantify a)\n                    if pred s then None, Some a, Some (Three(b,c,d))\n                    else\n                        let s = m.mappend s (m.quantify b)\n                        if pred s then Some (One a), Some b, Some (Two(c,d))\n                        else\n                            let s = m.mappend s (m.quantify c)\n                            if pred s then Some (Two(a,b)), Some c, Some (One d)\n                            else\n                                let s = m.mappend s (m.quantify d)\n                                if pred s then Some (Three(a,b,c)), Some d, None\n                                else Some affix, None, None\n\n    module Node = \n        let inline two (m : Measure<'a, 'm>) (a : 'a) (b : 'a) =\n            Node2(m |> (q a) +. (q b), a, b)\n\n        let inline three (m : Measure<'a, 'm>) (a : 'a) (b : 'a) (c : 'a) =\n            Node3(m |> (q a) +. (q b) +. (q c), a, b, c)\n\n        let inline quantify (n : Node<'a, 'm>) =\n            match n with\n                | Node2(m,_,_) -> m\n                | Node3(m,_,_,_) -> m \n\n        let inline toAffix (n : Node<'a, 'm>) =\n            Affix.ofNode n\n\n        let inline ofAffix (m : Measure<'a, 'm>) (a : Affix<'a>) =\n            Affix.toNode m a\n\n        let toListFw (n : Node<'a, 'm>) =\n            match n with\n                | Node2(_,a,b) -> [a;b]\n                | Node3(_,a,b,c) -> [a;b;c]\n\n        let toListBw (n : Node<'a, 'm>) =\n            match n with\n                | Node2(_,a,b) -> [b;a]\n                | Node3(_,a,b,c) -> [c;b;a]\n\n        let ofList (m : Measure<'a, 'm>) (l : list<'a>) =\n            match l with\n                | [a;b] -> Node2(m |> (q a) +. (q b), a, b)\n                | [a;b;c] -> Node3(m |> (q a) +. (q b) +. (q c), a, b, c)\n                | _ -> failwith \"node can only hold 2 or 3 elements\"\n\n        let rec manyOfList (m : Measure<'a, 'm>) (l : list<'a>) =\n            match l with\n                | [] | [_] -> failwith \"node can only hold 2 or 3 elements\"\n                | [a;b] -> [two m a b]\n                | [a;b;c] -> [three m a b c]\n                | a::b::rest -> (two m a b) :: manyOfList m rest\n\n        let nodesOf (m : Measure<'a, 'm>) (l : Affix<'a>) (r : Affix<'a>) =\n            match l, r with\n                | One(a), One(b) -> \n                    [ two m a b ]\n\n                | Two(a,b), One(c) \n                | One(a), Two(b,c) -> \n                    [ three m a b c ]\n\n                | One(a), Three(b,c,d)\n                | Two(a,b), Two(c,d)\n                | Three(a,b,c), One(d) ->\n                    [ two m a b; two m c d ]\n\n                | One(a), Four(b,c,d,e) \n                | Two(a,b), Three(c,d,e)\n                | Three(a,b,c), Two(d,e)\n                | Four(a,b,c,d), One(e) ->\n                    [ two m a b; three m c d e ]\n\n                | Two(a,b), Four(c,d,e,f)\n                | Three(a,b,c), Three(d,e,f)\n                | Four(a,b,c,d), Two(e,f) ->\n                    [ three m a b c; three m d e f ]\n\n                | Three(a,b,c), Four(d,e,f,g)\n                | Four(a,b,c,d), Three(e,f,g) ->\n                    [ two m a b; three m c d e; two m f g ]\n\n                | Four(a,b,c,d), Four(e,f,g,h) ->\n                    [ two m a b; three m c d e; three m f g h ]\n\n    module Measure =\n        type private NodeMeasureFun<'a, 'm>() =\n            static let measureFun = fun (n : Node<'a, 'm>) -> n.Measure\n            static member MeasureFun = measureFun\n\n        let node (m : Measure<'a, 'm>) =\n            {\n                quantify = NodeMeasureFun<'a, 'm>.MeasureFun\n                mempty = m.mempty\n                mappend = m.mappend\n            }\n\n    module FingerTreeNode =\n        \n        [<AutoOpen>]\n        module private ListExtensions =\n            \n            let rec extractLast (l : list<'a>) =\n                match l with\n                    | [a] -> a, []\n                    | a::rest -> \n                        let (last, l) = extractLast rest\n                        last, a :: l\n                    | [] -> failwith \"empty list\"\n\n            let (|Snoc|) (l : list<'a>) =\n                Snoc(l |> extractLast)\n\n\n        let quanitfy (m : Measure<'a, 'm>) (node : FingerTreeNode<'a, 'm>) =\n            match node with\n                | Empty -> m.mempty\n                | Single v -> m.quantify v\n                | Deep(m,_,_,_) -> m\n\n        let rec prepend<'a, 'm> (m : Measure<'a, 'm>) (value : 'a) (node : FingerTreeNode<'a, 'm>) : FingerTreeNode<'a, 'm> =\n            match node with\n                | Empty -> \n                    Single value\n\n                | Single y ->\n                    Deep(\n                        m |> (q y) +. (q value),\n                        Affix.one value,\n                        Empty,\n                        Affix.one y\n                    )\n\n                | Deep(ann, Four(a,b,c,d), deeper, suffix) ->\n                    Deep(\n                        m |> (cq ann) +. (q value),\n                        Affix.two value a,\n                        prepend (Measure.node m) (Node.three m b c d) deeper,\n                        suffix\n                    )\n\n                | Deep(ann, prefix, deeper, suffix) ->\n                    Deep(\n                        m |> (cq ann) +. (q value),\n                        Affix.prepend value prefix,\n                        deeper,\n                        suffix    \n                    )\n                            \n        let rec append<'a, 'm> (m : Measure<'a, 'm>) (value : 'a) (node : FingerTreeNode<'a, 'm>) : FingerTreeNode<'a, 'm> =\n            match node with\n                | Empty -> \n                    Single value\n\n                | Single y ->\n                    Deep(\n                        m |> (q y) +. (q value),\n                        Affix.one y,\n                        Empty,\n                        Affix.one value\n                    )\n\n                | Deep(ann, prefix, deeper, Four(a,b,c,d)) ->\n                    Deep(\n                        m |> (cq ann) +. (q value),\n                        prefix,\n                        append (Measure.node m) (Node.three m a b c) deeper,\n                        Affix.two d value\n                    )\n\n                | Deep(ann, prefix, deeper, suffix) ->\n                    Deep(\n                        m |> (cq ann) +. (q value),\n                        prefix,\n                        deeper,\n                        Affix.append value suffix    \n                    )\n                            \n        let ofAffix (m : Measure<'a, 'm>) (a : Affix<'a>) =\n            match a with\n                | One(a) -> \n                    Single a\n\n                | Two(a,b) ->\n                    Deep(\n                        m |> (q a) +. (q b),\n                        Affix.one a,\n                        Empty,\n                        Affix.one b    \n                    )\n\n                | Three(a,b,c) ->\n                    Deep(\n                        m |> (q a) +. (q b) +. (q c),\n                        Affix.one a,\n                        Empty,\n                        Affix.two b c\n                    )\n\n                | Four(a,b,c,d) ->\n                    Deep(\n                        m |> (q a) +. (q b) +. (q c) +. (q d),\n                        Affix.two a b,\n                        Empty,\n                        Affix.two c d\n                    )\n\n        let inline ofOptAffix (m : Measure<'a, 'm>) (o : Option<Affix<'a>>) =\n            match o with\n                | None -> Empty\n                | Some a -> ofAffix m a\n\n        let rec viewl<'a, 'm> (m : Measure<'a, 'm>) (node : FingerTreeNode<'a, 'm>) : FingerTreeView<'a, 'm> =\n            match node with\n                | Empty ->\n                    Nil\n\n                | Single v ->\n                    Cons(v, Empty)\n\n                | Deep(_, One(a), deeper, suffix) ->\n                    match viewl (Measure.node m) deeper with\n                        | Nil ->\n                            Cons(a, ofAffix m suffix)\n\n                        | Cons(n, rest) ->\n                            \n                            let pref = Affix.ofNode n\n                            let mPref = Affix.quanitfy m pref\n                            let mSuff = Affix.quanitfy m suffix\n                            let mDeeper = quanitfy (Measure.node m) rest\n\n                            let tail =\n                                Deep(\n                                    m.mappend (m.mappend mPref mDeeper) mSuff,\n                                    pref, rest, suffix\n                                )\n                            Cons(a, tail)\n\n                | Deep(_,prefix, deeper, suffix) ->\n                    let (a, pref) = Affix.takeFirst prefix\n\n                    let mPref = Affix.quanitfy m pref\n                    let mSuff = Affix.quanitfy m suffix\n                    let mDeeper = quanitfy (Measure.node m) deeper\n\n                    let tail =\n                        Deep(\n                            m.mappend (m.mappend mPref mDeeper) mSuff,\n                            pref, deeper, suffix\n                        )\n\n                    Cons(a, tail)\n\n        let rec viewr<'a, 'm> (m : Measure<'a, 'm>) (node : FingerTreeNode<'a, 'm>) : FingerTreeView<'a, 'm> =\n            match node with\n                | Empty ->\n                    Nil\n\n                | Single v ->\n                    Cons(v, Empty)\n\n                | Deep(_, prefix, deeper, One(a)) ->\n                    match viewr (Measure.node m) deeper with\n                        | Nil ->\n                            Cons(a, ofAffix m prefix)\n\n                        | Cons(n, rest) ->\n                            \n                            let suff = Affix.ofNode n\n                            let mPref = Affix.quanitfy m prefix\n                            let mSuff = Affix.quanitfy m suff\n                            let mDeeper = quanitfy (Measure.node m) rest\n\n                            let tail =\n                                Deep(\n                                    m.mappend (m.mappend mPref mDeeper) mSuff,\n                                    prefix, rest, suff\n                                )\n                            Cons(a, tail)\n\n                | Deep(_,prefix, deeper, suffix) ->\n                    let (a, suff) = Affix.takeLast suffix\n\n                    let mPref = Affix.quanitfy m prefix\n                    let mSuff = Affix.quanitfy m suff\n                    let mDeeper = quanitfy (Measure.node m) deeper\n\n                    let tail =\n                        Deep(\n                            m.mappend (m.mappend mPref mDeeper) mSuff,\n                            prefix, deeper, suff\n                        )\n\n                    Cons(a, tail)\n\n\n        let tail (m : Measure<'a,'m>) (node : FingerTreeNode<'a, 'm>) =\n            match viewl m node with\n                | Cons(_,rest) -> rest\n                | _ -> failwith \"empty sequence\"\n\n        let init (m : Measure<'a,'m>) (node : FingerTreeNode<'a, 'm>) =\n            match viewr m node with\n                | Cons(_,rest) -> rest\n                | _ -> failwith \"empty sequence\"\n\n        let firstOpt (n : FingerTreeNode<'a, 'm>) =\n            match n with\n                | Empty -> None\n                | Single v -> Some v\n                | Deep(_,p,_,_) -> Affix.first p |> Some\n\n        let lastOpt (n : FingerTreeNode<'a, 'm>) =\n            match n with\n                | Empty -> None\n                | Single v -> Some v\n                | Deep(_,_,_,s) -> Affix.last s |> Some\n\n        let total (m : Measure<'a, 'm>) (n : FingerTreeNode<'a, 'm>) =\n            match n with\n                | Empty -> m.mempty\n                | Single v -> m.quantify v\n                | Deep(m,_,_,_) -> m\n\n        let rec deep<'a, 'm> (m : Measure<'a, 'm>) (prefix : Option<Affix<'a>>) (deeper : FingerTreeNode<Node<'a, 'm>, 'm>) (suffix : Option<Affix<'a>>) =\n            match prefix, suffix with\n                | None, None ->\n                    match viewl (Measure.node m) deeper with\n                        | Cons(n, rest) ->\n                            deep m (Some (Affix.ofNode n)) rest None\n                        | Nil ->\n                            Empty\n\n                | None, Some s ->\n                    match viewl (Measure.node m) deeper with\n                        | Cons(n, rest) ->\n                            deep m (Some (Affix.ofNode n)) rest suffix\n                        | Nil ->\n                            ofAffix m s\n\n                | Some p, None ->\n                    match viewr (Measure.node m) deeper with\n                        | Cons(n, rest) ->\n                            deep m prefix rest (Some (Affix.ofNode n))\n                        | Nil ->\n                            ofAffix m p\n\n                | Some p, Some s ->\n                    let mPref = Affix.quanitfy m p\n                    let mSuff = Affix.quanitfy m s\n                    let mDeeper = quanitfy (Measure.node m) deeper\n\n                    Deep(\n                        m.mappend (m.mappend mPref mDeeper) mSuff,\n                        p, deeper, s\n                    )\n\n        let rec split<'a, 'm> (m : Measure<'a, 'm>) (pred : 'm -> bool) (start : 'm) (node : FingerTreeNode<'a, 'm>) : FingerTreeSplit<'a, 'm> =\n            match node with\n                | Empty -> \n                    failwith \"inconsistent measures in FingerTree\"\n\n                | Single v ->\n                    let s = m.mappend start (m.quantify v)\n                    if pred s then { left = Empty; value = v; right = Empty}\n                    else failwith \"inconsistent measures in FingerTree\"\n\n                | Deep(total, prefix, deeper, suffix) ->\n                    let current = start\n                    let s = m.mappend current (Affix.quanitfy m prefix)\n                    if pred s then\n                        // inside prefix\n                        match Affix.split m pred current prefix with\n                            | l, Some s, r ->\n                                { left = ofOptAffix m l; value = s; right = deep m r deeper (Some suffix) }\n                            | _ ->\n                                failwith \"inconsistent measures in FingerTree\"\n\n                    else\n                        let current = s\n                        let s = m.mappend current (quanitfy (Measure.node m) deeper)\n\n                        if pred s then\n                            // inside deeper\n                            let inner = split (Measure.node m) pred current deeper\n                            let start = m.mappend current (quanitfy (Measure.node m) inner.left)\n\n                            match Affix.split m pred start (Affix.ofNode inner.value) with\n                                | ls, Some s, rp ->\n                                    {\n                                        left = deep m (Some prefix) inner.left ls\n                                        value = s\n                                        right = deep m rp inner.right (Some suffix)\n                                    }\n                                | _ ->\n                                    failwith \"inconsistent measures in FingerTree\"\n\n\n                        else\n                            let current = s\n                            let s = m.mappend current (Affix.quanitfy m suffix)\n                            if pred s then\n                                match Affix.split m pred current suffix with\n                                    | l, Some s, r ->\n                                        { left = deep m (Some prefix) deeper l; value = s; right = ofOptAffix m r }\n                                    | _ ->\n                                        failwith \"inconsistent measures in FingerTree\"\n                            else\n                                failwith \"inconsistent measures in FingerTree\"\n   \n        let splitFirstRight<'a, 'm> (m : Measure<'a, 'm>) (pred : 'm -> bool) (start : 'm) (node : FingerTreeNode<'a, 'm>) : FingerTreeNode<'a, 'm> * FingerTreeNode<'a, 'm> =\n            match node with\n                | Empty -> \n                    (Empty, Empty)\n                | Single v ->\n                    let s = m.mappend start (m.quantify v)\n                    if pred s then (Empty, Single v)\n                    else (Single v, Empty)\n\n                | Deep(_,prefix,deeper,suffix) ->\n                    let current = start\n                    let s = m.mappend current (Affix.quanitfy m prefix)\n                    if pred s then\n                        // inside prefix\n                        match Affix.split m pred current prefix with\n                            | l, Some s, r ->\n                                let r =\n                                    match r with\n                                        | Some r -> Affix.prepend s r\n                                        | None -> One(s)\n\n                                (ofOptAffix m l, deep m (Some r) deeper (Some suffix))\n                            | _ ->\n                                failwith \"inconsistent measures in FingerTree\"\n\n                    else\n                        let current = s\n                        let s = m.mappend current (quanitfy (Measure.node m) deeper)\n\n                        if pred s then\n                            // inside deeper\n                            let inner = split (Measure.node m) pred current deeper\n                            let start = m.mappend current (quanitfy (Measure.node m) inner.left)\n\n                            match Affix.split m pred start (Affix.ofNode inner.value) with\n                                | ls, Some s, rp ->\n                                    let rp =\n                                        match rp with\n                                            | Some r -> Affix.prepend s r\n                                            | None -> One(s)\n                         \n                                    (deep m (Some prefix) inner.left ls, deep m (Some rp) inner.right (Some suffix))\n                   \n                                | _ ->\n                                    failwith \"inconsistent measures in FingerTree\"\n\n\n                        else\n                            let current = s\n                            let s = m.mappend current (Affix.quanitfy m suffix)\n                            if pred s then\n                                match Affix.split m pred current suffix with\n                                    | l, Some s, r ->\n                                        let r =\n                                            match r with\n                                                | Some r -> Affix.prepend s r\n                                                | None -> One(s)\n                                        (deep m (Some prefix) deeper l, ofAffix m r)\n                                    | _ ->\n                                        failwith \"inconsistent measures in FingerTree\"\n                            else\n                                (node, Empty)\n   \n          \n        let trySplit<'a, 'm> (m : Measure<'a, 'm>) (pred : 'm -> bool) (node : FingerTreeNode<'a, 'm>) : OptionalFingerTreeSplit<'a, 'm> =\n            if pred m.mempty then Left\n            elif not (pred (quanitfy m node)) then Right\n            else split m pred m.mempty node |> Inside\n\n        let rec concatWithMiddle<'a, 'm> (m : Measure<'a, 'm>) (l : FingerTreeNode<'a, 'm>) (mid : list<'a>) (r : FingerTreeNode<'a, 'm>) : FingerTreeNode<'a, 'm> =\n            match l, mid, r with\n                | Empty, [], r -> r\n                | Empty, (x::xs), r -> prepend m x (concatWithMiddle m Empty xs r)\n                | Single y, xs, r -> prepend m y (concatWithMiddle m Empty xs r)\n\n                | l, [], Empty -> l\n                | l, Snoc(x,xs), Empty -> append m x (concatWithMiddle m l xs Empty)\n                | l, xs, Single y -> append m y (concatWithMiddle m l xs Empty)\n\n\n                | Deep(lm, lp, ld, ls), mid, Deep(rm,rp,rd,rs) ->\n                    \n                    let mid' = Node.manyOfList m (Affix.toListFw ls @ mid @ Affix.toListFw rp)\n                    let deeper' = concatWithMiddle (Measure.node m) ld mid' rd\n\n                    let mPref = Affix.quanitfy m lp\n                    let mSuff = Affix.quanitfy m rs\n                    let mDeeper = quanitfy (Measure.node m) deeper'\n\n                    Deep(\n                        m.mappend (m.mappend mPref mDeeper) mSuff,\n                        lp, deeper', rs\n                    )\n\n            \n        let rec toSeqFw<'a, 'm> (n : FingerTreeNode<'a, 'm>) : seq<'a> =\n            match n with\n                | Empty -> Seq.empty\n                | Single v -> Seq.singleton v\n                | Deep(_,prefix, deeper, suffix) ->\n                    seq {\n                        yield! Affix.toListFw prefix\n                        for n in toSeqFw deeper do\n                            yield! Node.toListFw n\n                        yield! Affix.toListFw suffix\n                    }\n\n        let rec toSeqBw<'a, 'm> (n : FingerTreeNode<'a, 'm>) : seq<'a> =\n            match n with\n                | Empty -> Seq.empty\n                | Single v -> Seq.singleton v\n                | Deep(_,prefix, deeper, suffix) ->\n                    seq {\n                        yield! Affix.toListBw suffix\n                        for n in toSeqBw deeper do\n                            yield! Node.toListBw n\n                        yield! Affix.toListBw suffix\n                    }\n\n        let getEnumeratorFw<'a, 'm> (n : FingerTreeNode<'a, 'm>) =\n            let s = toSeqFw n\n            s.GetEnumerator()\n\n        let getEnumeratorBw<'a, 'm> (n : FingerTreeNode<'a, 'm>) =\n            let s = toSeqBw n\n            s.GetEnumerator()\n\n\n\nopen FingerTreeImplementation\n\ntype private ArrMeasureImpl<'a>() =\n    static let instance =\n        {\n            quantify = fun (a : 'a) -> 1\n            mempty = 0\n            mappend = (+)\n        }\n    static member Instance = instance\n\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype arr<'a> = private { root : FingerTreeNode<'a, int> } with\n    \n    member private x.AsString =\n        if x.Length > 20 then\n            x.root \n                |> FingerTreeNode.toSeqFw \n                |> Seq.take 20\n                |> Seq.map (sprintf \"%A\")\n                |> String.concat \"; \"\n                |> sprintf \"arr [%s; ...]\"\n        else\n            x.root \n                |> FingerTreeNode.toSeqFw \n                |> Seq.map (sprintf \"%A\")\n                |> String.concat \"; \"\n                |> sprintf \"arr [%s]\"\n\n    member x.Length =\n        x.root |> FingerTreeNode.quanitfy ArrMeasureImpl<'a>.Instance\n\n    member x.Item\n        with get (i : int) =\n            if i < 0 || i >= x.Length then raise <| IndexOutOfRangeException()\n            let split = x.root |> FingerTreeNode.split ArrMeasureImpl<'a>.Instance (fun id -> id > i) 0 \n            split.value\n\n    interface IEnumerable with\n        member x.GetEnumerator() = FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root :> IEnumerator\n\n    interface IEnumerable<'a> with\n        member x.GetEnumerator() = FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Arr =\n\n    let private mm<'a> = ArrMeasureImpl<'a>.Instance\n\n    let private outOfRange() =\n        raise <| IndexOutOfRangeException()\n\n\n    let empty<'a> : arr<'a> =\n        { root = Empty }\n\n    let ofSeq (s : seq<'a>) =\n        let mutable res = Empty\n        for e in s do res <- FingerTreeNode.append mm e res\n        { root = res }\n\n    let inline ofList (l : list<'a>) = ofSeq l\n    let inline ofArray (l : 'a[]) = ofSeq l\n\n\n    let toSeq (a : arr<'a>) = a.root |> FingerTreeNode.toSeqFw\n    let inline toList (a : arr<'a>) = a |> toSeq |> Seq.toList\n    let inline toArray (a : arr<'a>) = a |> toSeq |> Seq.toArray\n\n\n    let length (a : arr<'a>) =\n        a.root |> FingerTreeNode.quanitfy mm\n\n    let get (i : int) (a : arr<'a>) =\n        match FingerTreeNode.trySplit mm (fun id -> id > i) a.root with\n            | Inside res -> res.value\n            | _ -> outOfRange()\n\n    let set (i : int) (value : 'a) (a : arr<'a>) =\n        match FingerTreeNode.trySplit mm (fun id -> id > i) a.root with\n            | Inside res ->\n                { root = FingerTreeNode.concatWithMiddle mm res.left [value] res.right }\n            | _ -> \n                outOfRange()\n\n\n    let splitAt (i : int) (a : arr<'a>) =\n        if i = 0 then \n            empty, a\n        else\n            match FingerTreeNode.trySplit mm (fun id -> id > i) a.root with\n                | Inside res ->\n                    { root = res.left }, { root = FingerTreeNode.prepend mm res.value res.right }\n                | _ -> \n                    outOfRange()\n\n    let concatWithMiddle (l : arr<'a>) (m : list<'a>) (r : arr<'a>) =\n        { root = FingerTreeNode.concatWithMiddle mm l.root m r.root }\n\n    let viewl (a : arr<'a>) =\n        match FingerTreeNode.viewl mm a.root with\n            | Cons(a, rest) ->\n                Some(a, { root = rest })\n            | Nil ->\n                None\n\n    let viewr (a : arr<'a>) =\n        match FingerTreeNode.viewr mm a.root with\n            | Cons(a, rest) ->\n                Some(a, { root = rest })\n            | Nil ->\n                None\n\n    let prepend (value : 'a) (a : arr<'a>) =\n        { root = FingerTreeNode.prepend mm value a.root }\n\n    let append (value : 'a) (a : arr<'a>) =\n        { root = FingerTreeNode.append mm value a.root }\n\n\n\n\n\ntype private SortedMeasureImpl<'a when 'a : comparison>() =\n\n    static let cmp = Comparer<Option<'a>>.Default\n    static let vcmp = Comparer<'a>.Default\n\n    static let instance =\n        {\n            quantify = Some\n            mempty = None\n            mappend = fun a b -> if cmp.Compare(a,b) > 0 then a else b\n        }\n\n    static member Instance = instance\n    static member ValueComparer = vcmp\n\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype SortedList<'a> = private { root : FingerTreeNode<'a, Option<'a>> } with\n    \n    member private x.AsString =\n        x.root \n            |> FingerTreeNode.toSeqFw \n            |> Seq.map (sprintf \"%A\")\n            |> String.concat \"; \"\n            |> sprintf \"sorted [%s]\"\n\n    interface IEnumerable with\n        member x.GetEnumerator() = FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root :> IEnumerator\n\n    interface IEnumerable<'a> with\n        member x.GetEnumerator() = FingerTreeImplementation.FingerTreeNode.getEnumeratorFw x.root\n\nmodule SortedList =\n    let private mm<'a when 'a : comparison> = SortedMeasureImpl<'a>.Instance\n    let private cmp<'a when 'a : comparison> = SortedMeasureImpl<'a>.ValueComparer\n\n    let empty<'a> : SortedList<'a> =\n        { root = Empty }\n\n    let add (v : 'a) (l : SortedList<'a>) =\n        let ov = Some v\n        match FingerTreeNode.trySplit mm (fun i -> i >= ov) l.root with\n            | Left -> { root = FingerTreeNode.prepend mm v l.root }\n            | Right -> { root = FingerTreeNode.append mm v l.root }\n            | Inside split ->\n                if cmp.Compare(v, split.value) = 0 then \n                    l\n                else\n                    { root = FingerTreeNode.concatWithMiddle mm split.left [v; split.value] split.right}\n                \n    let remove (v : 'a) (l : SortedList<'a>) =\n        let ov = Some v\n        match FingerTreeNode.trySplit mm (fun i -> i >= ov) l.root with\n            | Left -> { root = FingerTreeNode.prepend mm v l.root }\n            | Right -> { root = FingerTreeNode.append mm v l.root }\n            | Inside split ->\n                if cmp.Compare(v, split.value) = 0 then \n                    { root = FingerTreeNode.concatWithMiddle mm split.left [] split.right}\n                else\n                    l\n                \n    let ofSeq (s : seq<'a>) =\n        let mutable res = empty\n        for e in s do res <- add e res\n        res\n    let inline ofList (l : list<'a>) = ofSeq l\n    let inline ofArray (l : 'a[]) = ofSeq l\n\n    let toSeq (a : SortedList<'a>) = a.root |> FingerTreeNode.toSeqFw\n    let inline toList (a : SortedList<'a>) = a |> toSeq |> Seq.toList\n    let inline toArray (a : SortedList<'a>) = a |> toSeq |> Seq.toArray\n\n    let maxOpt (l : SortedList<'a>) =\n        l.root |> FingerTreeNode.lastOpt\n\n    let minOpt (l : SortedList<'a>) =\n        l.root |> FingerTreeNode.firstOpt\n\n    let inline max l = (maxOpt l).Value\n    let inline min l = (minOpt l).Value\n\n    let viewl (a : SortedList<'a>) =\n        match FingerTreeNode.viewl mm a.root with\n            | Cons(a, rest) ->\n                Some(a, { root = rest })\n            | Nil ->\n                None\n\n    let viewr (a : SortedList<'a>) =\n        match FingerTreeNode.viewr mm a.root with\n            | Cons(a, rest) ->\n                Some(a, { root = rest })\n            | Nil ->\n                None\n\n\nmodule FingerTreeBenchmarks =\n    open System.Diagnostics\n    open System.IO\n\n    let testPerf (f : unit -> 'a) =\n        let sw = Stopwatch()\n\n        // warmup\n        for i in 0..100 do f() |> ignore\n\n        // determine an appropriate iteration count\n        let mutable iterations = 0UL\n        let mutable results = List<'a>(2000)\n        sw.Restart()\n        while sw.Elapsed.TotalMilliseconds < 500.0 do\n            f() |> results.Add\n            iterations <- iterations + 1UL\n            if iterations % 1000UL = 0UL then\n                sw.Stop()\n                results <- List<'a>(2000)\n\n                System.GC.Collect(3)\n                System.GC.WaitForFullGCComplete() |> ignore\n                System.GC.Collect(3)\n                System.GC.WaitForFullGCApproach() |> ignore\n\n                sw.Start()\n\n        // may have produced lots of garbage\n        System.GC.Collect(3)\n        System.GC.WaitForFullGCComplete() |> ignore\n        System.GC.Collect(3)\n        System.GC.WaitForFullGCApproach() |> ignore\n\n\n        let sw = Stopwatch()\n\n\n        // measure real performance\n        let mutable results = List<'a>(2000)\n        sw.Start()\n        for i in 1UL..iterations do\n            let r = f()\n            results.Add r\n\n            if i % 1000UL = 0UL then\n                sw.Stop()\n                results <- List<'a>(2000)\n\n                System.GC.Collect(3)\n                System.GC.WaitForFullGCComplete() |> ignore\n                System.GC.Collect(3)\n                System.GC.WaitForFullGCApproach() |> ignore\n\n                sw.Start()\n        sw.Stop()\n\n        let timePerF = sw.Elapsed.TotalMilliseconds / float iterations\n        \n        1000.0 * timePerF\n\n    let runTest (filename : string) (create : int -> 'a) (op : int -> 'a -> 'b) (sizes : list<int>) =\n        File.WriteAllLines(filename, [\"size;time\"])\n        \n        printfn \"determinig nop-overhead\"\n        let nopInstance = create (List.head sizes)\n        testPerf(fun () -> nopInstance) |> ignore // warmup\n        let tNop = testPerf(fun () -> nopInstance)\n        printfn \"nop: %fµs\" tNop\n        \n        for size in sizes do\n            System.GC.Collect()\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n            let instance = create size\n            let t = testPerf(fun () -> op size instance)\n            let t = t - tNop\n\n            printfn \"%d: %fµs\" size t\n            File.AppendAllLines(filename, [sprintf \"%d;%f\" size t])\n\n    let run() =\n\n//        runTest @\"C:\\Users\\schorsch\\desktop\\SortedListAdd.csv\" \n//                (fun s -> SortedList.ofList ([1..s]) )\n//                (fun s a -> SortedList.add 1 a)\n//                [0..10..2000]\n\n        runTest @\"C:\\Users\\schorsch\\desktop\\SortedListBuild.csv\" \n                (fun s -> [1..s] )\n                (fun s a -> a |> List.fold (fun s a -> SortedList.add a s) SortedList.empty)\n                [0..10..2000]\n\n        runTest @\"C:\\Users\\schorsch\\desktop\\FSharpSetBuild.csv\" \n                (fun s -> [1..s] )\n                (fun s a -> a |> List.fold (fun s a -> Set.add a s) Set.empty)\n                [0..10..2000]"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Immutable/Graph.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<RequireQualifiedAccess>]\ntype Tree<'a> =\n    | Empty\n    | Node of int * list<'a * Tree<'a>>\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Tree =\n    \n    let isEmpty (t : Tree<'a>) =\n        match t with\n            | Tree.Empty -> true\n            | _ -> false\n\n    let rec map (mapping : 'a -> 'b) (t : Tree<'a>) =\n        match t with\n            | Tree.Empty -> Tree.Empty\n            | Tree.Node(ni, children) -> Tree.Node(ni, children |> List.map (fun (e,c) -> mapping e, map mapping c))\n\n    let rec filter (predicate : 'a -> bool) (t : Tree<'a>) =\n        match t with\n            | Tree.Empty -> Tree.Empty\n            | Tree.Node(ni, children) ->\n                let newChildren = \n                    children |> List.choose (fun (e,c) -> \n                        if predicate e then \n                            let c = filter predicate c\n                            Some (e,c)\n                        else\n                            None\n                    )\n                Tree.Node(ni, newChildren)\n\n    let rec foldEdges (folder : 's -> 'a -> 's) (seed : 's) (t : Tree<'a>) =\n        match t with\n            | Tree.Empty -> \n                seed\n\n            | Tree.Node(_, edges) ->\n                edges |> List.fold (fun s (e,c) -> c |> foldEdges folder (folder s e)) seed\n\n    let rec foldNodes (folder : 's -> int -> 's) (seed : 's) (t : Tree<'a>) =\n        match t with\n            | Tree.Empty -> \n                seed\n\n            | Tree.Node(id, edges) ->\n                match edges with\n                    | [] -> \n                        folder seed id\n                    | edges ->\n                        edges |> List.fold (fun s (e,c) -> c |> foldNodes folder s) (folder seed id)\n\n    let count (t : Tree<'a>) =\n        foldNodes (fun c _ -> c + 1) 0 t\n\n    let inline weight (t : Tree<'a>) =\n        foldEdges (+) LanguagePrimitives.GenericZero t\n\ntype UndirectedGraph<'e> =\n    {\n        nodes       : Set<int>\n        adjacency   : MapExt<int, MapExt<int, 'e>>\n    }\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule UndirectedGraph =\n    open Aardvark.Base.Sorting\n    open System.Collections.Generic\n\n    type private UnionNode(id : int) as this =\n        let mutable parent = this\n        let mutable rank = 1\n\n        member x.Parent\n            with get() = parent\n            and set p = parent <- p\n\n        member x.Rank\n            with get() = rank\n            and set r = rank <- r\n\n        member x.Id = id\n\n    type private UnionFind() =\n        let nodes = Dict()\n\n        let node (id : int) = nodes.GetOrCreate(id, fun id -> UnionNode(id))\n\n        let rec rep (n : UnionNode) =\n            if n.Parent = n then\n                n\n            else\n                let r = rep n.Parent\n                n.Parent <- r\n                r\n\n        member x.Add(li : int, ri : int) =\n            let ln = node li\n            let rn = node ri\n\n            let lr = rep ln\n            let rr = rep rn\n\n            if lr = rr then\n                false\n            else\n                if lr.Rank < rr.Rank then\n                    lr.Parent <- rr\n                    true\n                elif rr.Rank < lr.Rank then\n                    rr.Parent <- lr.Parent\n                    true\n                else\n                    rr.Parent <- lr.Parent\n                    lr.Rank <- lr.Rank + 1\n                    true\n\n\n    let ofNodes (nodes : Set<int>) (getEdge : int -> int -> Option<'e>) =\n        \n        let mutable adjacency = MapExt.empty\n\n        let add (li : int) (ri : int) (e : 'e) =\n            adjacency <- MapExt.alter li (function Some o -> MapExt.add ri e o |> Some | None -> MapExt.ofList [ri, e] |> Some ) adjacency\n            adjacency <- MapExt.alter ri (function Some o -> MapExt.add li e o |> Some | None -> MapExt.ofList [li, e] |> Some ) adjacency\n\n\n        let nodeArr = Set.toArray nodes\n        for i in 0 .. nodeArr.Length - 1 do\n            let li = nodeArr.[i]\n            for j in i + 1 .. nodeArr.Length - 1 do\n                let ri = nodeArr.[j]\n                match getEdge li ri with\n                    | Some e -> add li ri e\n                    | None -> ()\n\n        {\n            nodes = nodes\n            adjacency = adjacency\n        }\n\n    let ofEdges (edges : seq<int * int * 'e>) =\n        let mutable nodes = Set.empty\n        let mutable adjacency = MapExt.empty\n\n        let add (li : int) (ri : int) (e : 'e) =\n            adjacency <- MapExt.alter li (function Some o -> MapExt.add ri e o |> Some | None -> MapExt.ofList [ri, e] |> Some ) adjacency\n            adjacency <- MapExt.alter ri (function Some o -> MapExt.add li e o |> Some | None -> MapExt.ofList [li, e] |> Some ) adjacency\n\n\n        for (li, ri, e) in edges do\n            nodes <- Set.add li (Set.add ri nodes)\n            add li ri e\n\n        {\n            nodes = nodes\n            adjacency = adjacency\n        }\n\n    let inline toNodes (g : UndirectedGraph<'e>) =\n        g.nodes\n\n    let toEdges (g : UndirectedGraph<'e>) =\n        g.adjacency \n            |> MapExt.toSeq \n            |> Seq.collect (fun (li,a) ->\n                let _, _, r = a |> MapExt.split li\n                r |> MapExt.toSeq |> Seq.map (fun (ri, e) -> (li, ri, e))\n            )\n            |> Seq.toList\n\n    let spanningTree (g : UndirectedGraph<'e>) =\n        if Set.isEmpty g.nodes then\n            Tree.Empty\n        else\n            let root = Seq.head g.nodes\n\n            let rec traverse (edgeCount : ref<int>) (visited : HashSet<int>) (n : int) =\n                if visited.Add n then\n                    let neighbours = MapExt.tryFind n g.adjacency |> Option.defaultValue MapExt.empty \n\n                    let children = \n                        neighbours \n                            |> MapExt.toList \n                            |> List.choose (fun (ri, e) -> \n                                match traverse edgeCount visited ri with\n                                    | Some r -> \n                                        edgeCount := !edgeCount + 1\n                                        Some (e, r)\n                                    | None -> \n                                        None\n                            )\n\n                    Tree.Node(n, children) |> Some\n                else\n                    None\n                \n            let cnt = ref 0\n            match traverse cnt (HashSet()) root with\n                | Some t -> \n                    assert (!cnt = Set.count g.nodes - 1)\n                    t\n                | None -> \n                    Tree.Empty\n\n    let minimumSpanningTree (cmp : 'e -> 'e -> int) (g : UndirectedGraph<'e>) =\n        let edges = g |> toEdges |> List.toArray\n        edges.TimSort(fun (_,_,l) (_,_,r) -> cmp l r)\n\n        let uf = UnionFind()\n        let finalEdges = List<int * int * 'e>()\n\n        for (li, ri, e) in edges do\n            if uf.Add(li, ri) then\n                finalEdges.Add(li, ri, e)\n\n\n        finalEdges\n            |> ofEdges\n            |> spanningTree\n\n    let maximumSpanningTree (cmp : 'e -> 'e -> int) (g : UndirectedGraph<'e>) =\n        minimumSpanningTree (fun l r -> cmp r l) g\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Immutable/MapExt.fs",
    "content": "﻿// THIS IS A MODIFIED VERSION OF F#'s Map<'Key, 'Value> !!!!\n// THE ORIGINAL CAN BE FOUND AT https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/map.fs\n\n// Copyright (c) Microsoft Corporation.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\n// THIS IS A MODIFIED VERSION OF F#'s Map<'Key, 'Value> !!!!\n// THE ORIGINAL CAN BE FOUND AT https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/map.fs\n\n// Copyright (c) Microsoft Corporation.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\n\nnamespace Aardvark.Base\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\nopen System.Diagnostics\nopen Microsoft.FSharp.Core\nopen Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators\nopen FSharp.Data.Adaptive\nopen MBrace.FsPickler\nopen MBrace.FsPickler.Combinators\n\nmodule internal MapExtImplementation = \n    [<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>]\n    [<NoEquality; NoComparison>]\n    type MapTree<'Key,'Value> = \n        | MapEmpty \n        | MapOne of 'Key * 'Value\n        | MapNode of 'Key * 'Value * MapTree<'Key,'Value> *  MapTree<'Key,'Value> * int * int\n            // REVIEW: performance rumour has it that the data held in MapNode and MapOne should be\n            // exactly one cache line. It is currently ~7 and 4 words respectively. \n\n    type MapExtReference<'v> =\n        | NonExisting of index : int\n        | Existing of index : int * value : 'v\n\n\n    type internal EnumeratorEnumerable<'T>(get : unit -> IEnumerator<'T>) =\n        interface System.Collections.IEnumerable with\n            member x.GetEnumerator() = get() :> System.Collections.IEnumerator\n\n        interface IEnumerable<'T> with\n            member x.GetEnumerator() = get()\n\n    \n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module MapTree = \n\n        let empty = MapEmpty \n\n        let height = function\n            | MapEmpty -> 0\n            | MapOne _ -> 1\n            | MapNode(_,_,_,_,h,_) -> h\n\n        let size = function\n            | MapEmpty -> 0\n            | MapOne _ -> 1\n            | MapNode(_,_,_,_,_,s) -> s\n\n        let isEmpty m = \n            match m with \n            | MapEmpty -> true\n            | _ -> false\n\n        let mk l k v r = \n            match l,r with \n            | MapEmpty,MapEmpty -> MapOne(k,v)\n            | _ -> \n                let hl = height l \n                let hr = height r \n                let m = if hl < hr then hr else hl \n                let res = MapNode(k,v,l,r,m+1, 1 + size l + size r)\n                res\n\n        let rec rebalance t1 k v t2 =\n            let t1h = height t1 \n            let t2h = height t2 \n            if  t2h > t1h + 2 then (* right is heavier than left *)\n                match t2 with \n                | MapNode(t2k,t2v,t2l,t2r,_,_) -> \n                    (* one of the nodes must have height > height t1 + 1 *)\n                   if height t2l > t1h + 1 then  (* balance left: combination *)\n                       match t2l with \n                       | MapNode(t2lk,t2lv,t2ll,t2lr,_,_) ->\n                           mk (mk t1 k v t2ll) t2lk t2lv (rebalance t2lr t2k t2v t2r) \n                       | _ -> failwith \"rebalance\"\n                   else (* rotate left *)\n                       mk (mk t1 k v t2l) t2k t2v t2r\n                | _ -> failwith \"rebalance\"\n            else\n                if  t1h > t2h + 2 then (* left is heavier than right *)\n                    match t1 with \n                    | MapNode(t1k,t1v,t1l,t1r,_,_) -> \n                        (* one of the nodes must have height > height t2 + 1 *)\n                        if height t1r > t2h + 1 then \n                            (* balance right: combination *)\n                            match t1r with \n                            | MapNode(t1rk,t1rv,t1rl,t1rr,_,_) ->\n                                mk (rebalance t1l t1k t1v t1rl) t1rk t1rv (mk t1rr k v t2)\n                            | _ -> failwith \"rebalance\"\n                        else\n                            mk t1l t1k t1v (mk t1r k v t2)\n                    | _ -> failwith \"rebalance\"\n                else mk t1 k v t2\n\n        let rec add (comparer: IComparer<'Value>) k v m = \n            match m with \n            | MapEmpty -> MapOne(k,v)\n            | MapOne(k2,_) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0   then MapNode (k,v,MapEmpty,m,2, 2)\n                elif c = 0 then MapOne(k,v)\n                else            MapNode (k,v,m,MapEmpty,2, 2)\n            | MapNode(k2,v2,l,r,h,s) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0 then rebalance (add comparer k v l) k2 v2 r\n                elif c = 0 then MapNode(k,v,l,r,h,s)\n                else rebalance l k2 v2 (add comparer k v r) \n\n        let rec find (comparer: IComparer<'Value>) k m = \n            match m with \n            | MapEmpty -> raise (KeyNotFoundException())\n            | MapOne(k2,v2) -> \n                let c = comparer.Compare(k,k2) \n                if c = 0 then v2\n                else raise (KeyNotFoundException())\n            | MapNode(k2,v2,l,r,_,_) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0 then find comparer k l\n                elif c = 0 then v2\n                else find comparer k r\n\n        let rec tryFind (comparer: IComparer<'Value>) k m = \n            match m with \n            | MapEmpty -> None\n            | MapOne(k2,v2) -> \n                let c = comparer.Compare(k,k2) \n                if c = 0 then Some v2\n                else None\n            | MapNode(k2,v2,l,r,_,_) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0 then tryFind comparer k l\n                elif c = 0 then Some v2\n                else tryFind comparer k r\n                \n        let rec tryFindV (comparer: IComparer<'Value>) k m = \n            match m with \n            | MapEmpty -> ValueNone\n            | MapOne(k2,v2) -> \n                let c = comparer.Compare(k,k2) \n                if c = 0 then ValueSome v2\n                else ValueNone\n            | MapNode(k2,v2,l,r,_,_) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0 then tryFindV comparer k l\n                elif c = 0 then ValueSome v2\n                else tryFindV comparer k r\n\n        let partition1 (comparer: IComparer<'Value>) (f:OptimizedClosures.FSharpFunc<_,_,_>) k v (acc1,acc2) = \n            if f.Invoke(k, v) then (add comparer k v acc1,acc2) else (acc1,add comparer k v acc2) \n        \n        let rec partitionAux (comparer: IComparer<'Value>) (f:OptimizedClosures.FSharpFunc<_,_,_>) s acc = \n            match s with \n            | MapEmpty -> acc\n            | MapOne(k,v) -> partition1 comparer f k v acc\n            | MapNode(k,v,l,r,_,_) -> \n                let acc = partitionAux comparer f r acc \n                let acc = partition1 comparer f k v acc\n                partitionAux comparer f l acc\n\n        let partition (comparer: IComparer<'Value>) f s = partitionAux comparer (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) s (empty,empty)\n\n        let filter1 (comparer: IComparer<'Value>) (f:OptimizedClosures.FSharpFunc<_,_,_>) k v acc = if f.Invoke(k, v) then add comparer k v acc else acc \n\n        let rec filterAux (comparer: IComparer<'Value>) (f:OptimizedClosures.FSharpFunc<_,_,_>) s acc = \n            match s with \n            | MapEmpty -> acc\n            | MapOne(k,v) -> filter1 comparer f k v acc\n            | MapNode(k,v,l,r,_,_) ->\n                let acc = filterAux comparer f l acc\n                let acc = filter1 comparer f k v acc\n                filterAux comparer f r acc\n\n        let filter (comparer: IComparer<'Value>) f s = filterAux comparer (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) s empty\n\n        let rec spliceOutSuccessor m = \n            match m with \n            | MapEmpty -> failwith \"internal error: MapExt.spliceOutSuccessor\"\n            | MapOne(k2,v2) -> k2,v2,MapEmpty\n            | MapNode(k2,v2,l,r,_,_) ->\n                match l with \n                | MapEmpty -> k2,v2,r\n                | _ -> let k3,v3,l' = spliceOutSuccessor l in k3,v3,rebalance l' k2 v2 r\n\n        let rec remove (comparer: IComparer<'Value>) k m = \n            match m with \n            | MapEmpty -> empty\n            | MapOne(k2,_) -> \n                let c = comparer.Compare(k,k2) \n                if c = 0 then MapEmpty else m\n            | MapNode(k2,v2,l,r,_,_) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0 then rebalance (remove comparer k l) k2 v2 r\n                elif c = 0 then \n                    match l with\n                    | MapEmpty -> r\n                    | _ ->\n                        match r with\n                        | MapEmpty -> l\n                        | _ -> \n                        let sk,sv,r' = spliceOutSuccessor r \n                        rebalance l sk sv r'\n                else \n                    rebalance l k2 v2 (remove comparer k r) \n\n\n        let rec tryRemove (comparer: IComparer<'Value>) k m = \n            match m with \n            | MapEmpty -> None\n            | MapOne(k2,v) -> \n                let c = comparer.Compare(k,k2) \n                if c = 0 then Some (v, MapEmpty) else None\n            | MapNode(k2,v2,l,r,_,_) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0 then \n                    match tryRemove comparer k l with\n                    | Some (v,l) ->\n                        Some (v, rebalance l k2 v2 r)\n                    | None ->\n                        None\n                elif c = 0 then \n                    match l with\n                    | MapEmpty -> Some(v2, r)\n                    | _ ->\n                        match r with\n                        | MapEmpty -> Some(v2, l)\n                        | _ -> \n                            let sk,sv,r' = spliceOutSuccessor r \n                            Some(v2, rebalance l sk sv r')\n                else \n                    match tryRemove comparer k r with\n                    | Some (v,r) ->\n                        Some (v, rebalance l k2 v2 r)\n                    | None ->\n                        None\n\n        let rec tryRemoveV (comparer: IComparer<'Value>) k m = \n            match m with \n            | MapEmpty -> ValueNone\n            | MapOne(k2,v) -> \n                let c = comparer.Compare(k,k2) \n                if c = 0 then ValueSome (struct(v, MapEmpty)) else ValueNone\n            | MapNode(k2,v2,l,r,_,_) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0 then \n                    match tryRemoveV comparer k l with\n                    | ValueSome (v,l) ->\n                        ValueSome (struct (v, rebalance l k2 v2 r))\n                    | ValueNone ->\n                        ValueNone\n                elif c = 0 then \n                    match l with\n                    | MapEmpty -> ValueSome(struct(v2, r))\n                    | _ ->\n                        match r with\n                        | MapEmpty -> ValueSome(struct(v2, l))\n                        | _ -> \n                            let sk,sv,r' = spliceOutSuccessor r \n                            ValueSome(struct(v2, rebalance l sk sv r'))\n                else \n                    match tryRemoveV comparer k r with\n                    | ValueSome (v,r) ->\n                        ValueSome (struct(v, rebalance l k2 v2 r))\n                    | ValueNone ->\n                        ValueNone\n\n\n\n        let rec tryRemoveMin cmp m = \n            match m with \n            | MapEmpty -> \n                None\n\n            | MapOne(k2,v) ->\n                Some (k2, v, MapEmpty)\n\n            | MapNode(k2,v2,l,r,_,_) -> \n                match tryRemoveMin cmp l with\n                | Some (k,v,rest) ->\n                    match rest with\n                    | MapEmpty -> Some (k, v, add cmp k2 v2 r)\n                    | _ -> Some (k, v, rebalance rest k2 v2 r)\n                | None ->\n                    Some(k2, v2, r)\n\n        let rec tryRemoveMax cmp m = \n            match m with \n            | MapEmpty -> \n                None\n\n            | MapOne(k2,v) ->\n                Some (k2, v, MapEmpty)\n\n            | MapNode(k2,v2,l,r,_,_) -> \n                match tryRemoveMax cmp r with\n                | Some (k,v,rest) ->\n                    match rest with\n                    | MapEmpty -> Some (k, v, add cmp k2 v2 l)\n                    | _ -> Some (k, v, rebalance l k2 v2 rest)\n                | None ->\n                    Some(k2, v2, l)\n\n\n        \n        let rec tryMinKeyV n =\n            match n with\n            | MapEmpty ->\n                ValueNone\n            | MapOne(k,_) ->\n                ValueSome k\n            | MapNode(k, _, l, _, _, _) ->\n                match tryMinKeyV l with\n                | ValueSome m -> ValueSome m\n                | ValueNone -> ValueSome k\n                \n        let rec tryMaxKeyV n =\n            match n with\n            | MapEmpty ->\n                ValueNone\n            | MapOne(k,_) ->\n                ValueSome k\n            | MapNode(k, _, _, r, _, _) ->\n                match tryMaxKeyV r with\n                | ValueSome m -> ValueSome m\n                | ValueNone -> ValueSome k\n\n        let rec tryRemoveMinV cmp next m = \n            match m with \n            | MapEmpty -> \n                ValueNone\n\n            | MapOne(k2,v) ->\n                ValueSome (struct (k2, v, next, MapEmpty))\n\n            | MapNode(k2,v2,l,r,_,_) -> \n                match tryRemoveMinV cmp (ValueSome k2) l with\n                | ValueSome (k,v,next,rest) ->\n                    match rest with\n                    | MapEmpty -> ValueSome (struct(k, v, next, add cmp k2 v2 r))\n                    | _ -> ValueSome (struct(k, v, next, rebalance rest k2 v2 r))\n                | ValueNone ->\n                    let next = tryMinKeyV r\n                    ValueSome(struct(k2, v2, next, r))\n\n\n        let rec tryRemoveMaxV cmp prev m = \n            match m with \n            | MapEmpty -> \n                ValueNone\n\n            | MapOne(k2,v) ->\n                ValueSome (struct(k2, v, prev, MapEmpty))\n\n            | MapNode(k2,v2,l,r,_,_) -> \n                match tryRemoveMaxV cmp (ValueSome k2) r with\n                | ValueSome (struct(k, v, prev, rest)) ->\n                    match rest with\n                    | MapEmpty -> ValueSome (struct(k, v, prev, add cmp k2 v2 l))\n                    | _ -> ValueSome (struct(k, v, prev, rebalance l k2 v2 rest))\n                | ValueNone ->\n                    let prev = tryMaxKeyV l\n                    ValueSome(k2, v2, prev, l)\n\n\n        \n        let rec alter (comparer : IComparer<'Value>) k f m =\n            match m with   \n            | MapEmpty ->\n                match f None with\n                    | Some v -> MapOne(k,v)\n                    | None -> MapEmpty\n\n            | MapOne(k2, v2) ->\n                let c = comparer.Compare(k,k2) \n                if c = 0 then\n                    match f (Some v2) with\n                        | Some v3 -> MapOne(k2, v3)\n                        | None -> MapEmpty\n                else\n                    match f None with\n                        | None -> \n                            MapOne(k2, v2)\n\n                        | Some v3 -> \n                            if c > 0 then MapNode (k2,v2,MapEmpty,MapOne(k, v3),2, 2)\n                            else MapNode(k2, v2, MapOne(k, v3), MapEmpty, 2, 2)\n            | MapNode(k2, v2, l, r, h, cnt) ->\n            \n                let c = comparer.Compare(k, k2)\n\n                if c = 0 then\n                    match f (Some v2) with\n                        | Some v3 -> \n                            MapNode(k2, v3, l, r, h, cnt)\n\n                        | None ->\n                            match l with\n                            | MapEmpty -> r\n                            | _ ->\n                                match r with\n                                | MapEmpty -> l\n                                | _ -> \n                                    let sk,sv,r' = spliceOutSuccessor r \n                                    rebalance l sk sv r'\n                elif c > 0 then\n                    rebalance l k2 v2 (alter comparer k f r) \n                else\n                    rebalance (alter comparer k f l)  k2 v2 r\n               \n        let rec join left k v right =\n            let lh = height left\n            let rh = height right\n            if lh > rh + 2 then\n                match left with\n                    | MapNode(k2,v2,l,r,_,_) ->\n                        // the join-result can at most be one level higher than r\n                        // therefore rebalance is sufficient here\n                        rebalance l k2 v2 (join r k v right)\n                    | _ ->\n                        failwith \"join\"\n            elif rh > lh + 2 then\n                match right with\n                    | MapNode(k2,v2,l,r,_,_) ->\n                        // the join-result can at most be one level higher than l\n                        // therefore rebalance is sufficient here\n                        rebalance (join left k v l) k2 v2 r\n                    | _ ->\n                        failwith \"join\"\n            else\n                mk left k v right\n\n\n        let inline merge l r =\n            match r with\n            | MapEmpty -> l\n            | _ ->\n                match l with\n                | MapEmpty -> r\n                | _ ->\n                    let (k,v,r) = spliceOutSuccessor r\n                    join l k v r\n\n        let inline joinV left k v right =\n            match v with\n            | ValueSome v -> join left k v right\n            | ValueNone -> merge left right\n\n        let rec range (comparer : IComparer<'Value>) lk rk m =\n            match m with\n            | _ when comparer.Compare(lk, rk) > 0 ->\n                MapEmpty\n\n            | MapEmpty ->\n                MapEmpty\n\n            | MapOne(k, _) as n ->\n                if comparer.Compare(lk, k) <= 0 && comparer.Compare(k, rk) <= 0 then n\n                else MapEmpty\n\n            | MapNode(k, v, l, r, _, _) ->\n                let cl = comparer.Compare(lk, k)\n\n                if cl = 0 then\n                    if comparer.Compare(k, rk) = 0 then\n                        MapOne(k, v)\n                    else\n                        join MapEmpty k v (range comparer lk rk r)\n\n                elif cl < 0 then\n                    let cr = comparer.Compare(k, rk)\n\n                    if cr = 0 then\n                        join (range comparer lk rk l) k v MapEmpty\n                    elif cr < 0 then\n                        join (range comparer lk rk l) k v (range comparer lk rk r)\n                    else\n                        range comparer lk rk l\n\n                else\n                    range comparer lk rk r\n\n        let rec split (comparer: IComparer<'Value>) k m =\n            match m with\n            | MapEmpty -> \n                MapEmpty, None, MapEmpty\n\n            | MapOne(k2,v2) ->\n                let c = comparer.Compare(k, k2)\n                if c < 0 then MapEmpty, None, MapOne(k2,v2)\n                elif c = 0 then MapEmpty, Some(v2), MapEmpty\n                else MapOne(k2,v2), None, MapEmpty\n\n            | MapNode(k2,v2,l,r,_,_) ->\n                let c = comparer.Compare(k, k2)\n                if c > 0 then\n                    let rl, res, rr = split comparer k r\n                    join l k2 v2 rl, res, rr\n\n                elif c = 0 then \n                    l, Some(v2), r\n\n                else\n                    let ll, res, lr = split comparer k l\n                    ll, res, join lr k2 v2 r\n\n\n        let rec tryMinAux acc m =\n            match m with\n            | MapEmpty -> acc\n            | MapOne(k,v) -> Some (k,v)\n            | MapNode(k,v,l,_,_,_) -> tryMinAux (Some (k,v)) l\n\n        let rec tryMin m = tryMinAux None m\n    \n        let rec tryMinVAux acc m =\n            match m with\n            | MapEmpty -> acc\n            | MapOne(k,v) -> ValueSome (struct(k,v))\n            | MapNode(k,v,l,_,_,_) -> tryMinVAux (ValueSome (struct(k,v))) l\n\n        let rec tryMinV m = tryMinVAux ValueNone m\n    \n        let rec tryMaxAux acc m =\n            match m with\n            | MapEmpty -> acc\n            | MapOne(k,v) -> Some (k,v)\n            | MapNode(k,v,_,r,_,_) -> tryMaxAux (Some (k,v)) r\n\n        let rec tryMax m = tryMaxAux None m\n        \n        let rec tryMaxVAux acc m =\n            match m with\n            | MapEmpty -> acc\n            | MapOne(k,v) -> ValueSome (struct(k,v))\n            | MapNode(k,v,_,r,_,_) -> tryMaxVAux (ValueSome (struct(k,v))) r\n\n        let rec tryMaxV m = tryMaxVAux ValueNone m\n\n        let rec splitV (comparer: IComparer<'Value>) k m =\n            match m with\n            | MapEmpty -> \n                struct (MapEmpty, ValueNone, ValueNone, ValueNone, MapEmpty)\n\n            | MapOne(k2,v2) ->\n                let c = comparer.Compare(k, k2)\n                if c < 0 then struct (MapEmpty, ValueNone, ValueNone, ValueSome k2, MapOne(k2,v2))\n                elif c = 0 then struct (MapEmpty, ValueNone, ValueSome(v2), ValueNone, MapEmpty)\n                else struct (MapOne(k2,v2), ValueSome k2, ValueNone, ValueNone, MapEmpty)\n\n            | MapNode(k2,v2,l,r,_,_) ->\n                let c = comparer.Compare(k, k2)\n                if c > 0 then\n                    let struct (rl, lmax, res, rmin, rr) = splitV comparer k r\n                    struct (join l k2 v2 rl, lmax, res, rmin, rr)\n\n                elif c = 0 then \n                    let lmax = tryMaxV l |> ValueOption.map (fun struct(k,_) -> k)\n                    let rmin = tryMinV r |> ValueOption.map (fun struct(k,_) -> k)\n                    struct (l, lmax, ValueSome(v2), rmin, r)\n\n                else\n                    let struct (ll, lmax, res, rmin, lr) = splitV comparer k l\n                    struct (ll, lmax, res, rmin, join lr k2 v2 r)\n\n        let rec getReference (comparer: IComparer<'Value>) (current : int) k m =\n            match m with\n                | MapEmpty -> \n                    NonExisting current\n\n                | MapOne(key,v) ->\n                    let c = comparer.Compare(k, key)\n                    \n                    if c > 0 then NonExisting (current + 1)\n                    elif c < 0 then NonExisting current\n                    else Existing(current, v)\n\n                | MapNode(key,v,l,r,_,s) ->\n                    let c = comparer.Compare(k, key)\n                    if c > 0 then getReference comparer (current + size l + 1) k r\n                    elif c < 0 then getReference comparer current k l\n                    else Existing(current+size l, v)\n\n\n                    \n        let rec union (comparer: IComparer<'Key>) l r =\n            match struct (l, r) with\n            | struct (MapEmpty, r) -> r\n            | struct (l, MapEmpty) -> l\n            | struct (MapOne(lk, _lv), MapOne(rk, rv)) ->\n                if Object.ReferenceEquals(l, r) then \n                    r\n                else \n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then r\n                    elif c > 0 then mk MapEmpty rk rv l\n                    else mk l rk rv MapEmpty\n                    \n            | struct (MapOne(lk, _), MapNode(rk, rv, rl, rr, rh, rc)) ->\n                let c = comparer.Compare(lk, rk)\n                if c = 0 then r\n                elif c < 0 then join (union comparer l rl) rk rv rr\n                else join rl rk rv (union comparer l rr)\n\n            | struct (MapNode(lk, lv, ll, lr, lh, lc), MapOne(rk, rv)) ->\n                let c = comparer.Compare(lk, rk)\n                if c = 0 then MapNode(lk, rv, ll, lr, lh, lc)\n                elif c < 0 then join ll lk lv (union comparer lr r)\n                else join (union comparer ll r) lk lv lr\n\n            | struct (MapNode(lk, lv, ll, lr, lh, lc), MapNode(rk, rv, rl, rr, rh, rc)) ->\n                if Object.ReferenceEquals(l, r) then \n                    r\n                else\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then \n                        let l = union comparer ll rl\n                        let r = union comparer lr rr\n                        join l rk rv r\n                    elif lh > rh then\n                        let struct (rl, _lmax, rv, _rmin, rr) = splitV comparer lk r\n                        let key = lk\n                        let l = union comparer ll rl\n                        let r = union comparer lr rr\n\n                        match rv with\n                        | ValueSome rv -> join l key rv r\n                        | ValueNone -> join l key lv r\n                    else\n                        let struct (ll, _lmax, _, _rmin, lr) = splitV comparer rk l\n                        let key = rk\n                        let l = union comparer ll rl\n                        let r = union comparer lr rr\n                        join l key rv r\n\n        let rec unionWithOpt (comparer: IComparer<'Value>) (f : OptimizedClosures.FSharpFunc<_,_,_>) l r =\n            match struct (l, r) with\n            | struct (MapEmpty, r) -> r\n            | struct (l, MapEmpty) -> l\n            | struct (MapOne(lk, lv), MapOne(rk, rv)) ->\n                let c = comparer.Compare(lk, rk)\n                if c = 0 then MapOne(rk, f.Invoke(lv, rv))\n                elif c > 0 then mk MapEmpty rk rv l\n                else mk l rk rv MapEmpty\n                    \n            | struct (MapOne(lk, lv), MapNode(rk, rv, rl, rr, rh, rc)) ->\n                let c = comparer.Compare(lk, rk)\n                if c = 0 then MapNode(rk, f.Invoke(lv, rv), rl, rr, rh, rc)\n                elif c < 0 then join (unionWithOpt comparer f l rl) rk rv rr\n                else join rl rk rv (unionWithOpt comparer f l rr)\n\n            | struct (MapNode(lk, lv, ll, lr, lh, lc), MapOne(rk, rv)) ->\n                let c = comparer.Compare(lk, rk)\n                if c = 0 then MapNode(lk, f.Invoke(lv, rv), ll, lr, lh, lc)\n                elif c < 0 then join ll lk lv (unionWithOpt comparer f lr r)\n                else join (unionWithOpt comparer f ll r) lk lv lr\n\n            | struct (MapNode(lk, lv, ll, lr, lh, lc), MapNode(rk, rv, rl, rr, rh, rc)) ->\n                let c = comparer.Compare(lk, rk)\n                if c = 0 then \n                    let l = unionWithOpt comparer f ll rl\n                    let r = unionWithOpt comparer f lr rr\n                    join l rk (f.Invoke(lv, rv)) r\n                elif lh > rh then\n                    let struct (rl, _lmax, rv, _rmin, rr) = splitV comparer lk r\n                    let key = lk\n                    let l = unionWithOpt comparer f ll rl\n                    let r = unionWithOpt comparer f lr rr\n\n                    match rv with\n                    | ValueSome rv -> join l key (f.Invoke(lv, rv)) r\n                    | ValueNone -> join l key lv r\n                else\n                    let struct (ll, _lmax, lv, _rmin, lr) = splitV comparer rk l\n                    let key = rk\n                    let l = unionWithOpt comparer f ll rl\n                    let r = unionWithOpt comparer f lr rr\n                    match lv with\n                    | ValueSome lv -> join l key (f.Invoke(lv, rv)) r\n                    | ValueNone -> join l key rv r\n  \n        let unionWith(comparer: IComparer<'Value>) f l r =\n            unionWithOpt comparer (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) l r\n\n\n\n        let rec stupidHeight m =\n            match m with\n                | MapEmpty -> 0\n                | MapOne _ -> 1\n                | MapNode(_,_,l,r,_,_) -> max (stupidHeight l) (stupidHeight r) + 1\n\n        let rec stupidCount m =\n            match m with\n                | MapEmpty -> 0\n                | MapOne _ -> 1\n                | MapNode(_,_,l,r,_,_) ->\n                    1 + stupidCount l + stupidCount r\n\n        let rec validateAux (comparer: IComparer<'Value>) (min : option<_>) (max : option<_>) m =\n            match m with\n                | MapNode(k,v,l,r,h,c) ->\n                    let lh = height l\n                    let rh = height r\n\n                    if Option.isSome min && comparer.Compare(k, min.Value) <= 0 then failwith \"invalid order\"\n                    if Option.isSome max && comparer.Compare(k, max.Value) >= 0 then failwith \"invalid order\"\n                    if stupidCount m <> c then failwith \"invalid count\"\n                    if stupidHeight l <> lh then failwith \"invalid height\"\n                    if stupidHeight r <> rh then failwith \"invalid height\"\n                    if abs (lh - rh) > 2 then failwith \"imbalanced\"   \n                    \n                    validateAux comparer min (Some k) l\n                    validateAux comparer (Some k) max r\n\n                | MapOne(k,v) ->\n                    if Option.isSome min && comparer.Compare(k, min.Value) <= 0 then failwith \"invalid order\"\n                    if Option.isSome max && comparer.Compare(k, max.Value) >= 0 then failwith \"invalid order\"\n\n                | MapEmpty ->\n                    ()\n\n        let validate (comparer: IComparer<'Value>) m =\n            validateAux comparer None None m\n\n\n        let rec mem (comparer: IComparer<'Value>) k m = \n            match m with \n            | MapEmpty -> false\n            | MapOne(k2,_) -> (comparer.Compare(k,k2) = 0)\n            | MapNode(k2,_,l,r,_,_) -> \n                let c = comparer.Compare(k,k2) \n                if c < 0 then mem comparer k l\n                else (c = 0 || mem comparer k r)\n\n        let rec iterOpt (f:OptimizedClosures.FSharpFunc<_,_,_>) m =\n            match m with \n            | MapEmpty -> ()\n            | MapOne(k2,v2) -> f.Invoke(k2, v2)\n            | MapNode(k2,v2,l,r,_,_) -> iterOpt f l; f.Invoke(k2, v2); iterOpt f r\n\n        let iter f m = iterOpt (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n\n        let rec tryPickOpt (f:OptimizedClosures.FSharpFunc<_,_,_>) m =\n            match m with \n            | MapEmpty -> None\n            | MapOne(k2,v2) -> f.Invoke(k2, v2) \n            | MapNode(k2,v2,l,r,_,_) -> \n                match tryPickOpt f l with \n                | Some _ as res -> res \n                | None -> \n                match f.Invoke(k2, v2) with \n                | Some _ as res -> res \n                | None -> \n                tryPickOpt f r\n\n        let tryPick f m = tryPickOpt (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n\n        let rec tryPickOptBack (f:OptimizedClosures.FSharpFunc<_,_,_>) m =\n            match m with \n            | MapEmpty -> None\n            | MapOne(k2,v2) -> f.Invoke(k2, v2) \n            | MapNode(k2,v2,l,r,_,_) -> \n                match tryPickOptBack f r with \n                | Some _ as res -> res \n                | None -> \n                match f.Invoke(k2, v2) with \n                | Some _ as res -> res \n                | None -> \n                tryPickOptBack f l\n\n        let tryPickBack f m = tryPickOptBack (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n\n\n        let rec existsOpt (f:OptimizedClosures.FSharpFunc<_,_,_>) m = \n            match m with \n            | MapEmpty -> false\n            | MapOne(k2,v2) -> f.Invoke(k2, v2)\n            | MapNode(k2,v2,l,r,_,_) -> existsOpt f l || f.Invoke(k2, v2) || existsOpt f r\n\n        let exists f m = existsOpt (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n\n        let rec forallOpt (f:OptimizedClosures.FSharpFunc<_,_,_>) m = \n            match m with \n            | MapEmpty -> true\n            | MapOne(k2,v2) -> f.Invoke(k2, v2)\n            | MapNode(k2,v2,l,r,_,_) -> forallOpt f l && f.Invoke(k2, v2) && forallOpt f r\n\n        let forall f m = forallOpt (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n\n        let rec map f m = \n            match m with \n            | MapEmpty -> empty\n            | MapOne(k,v) -> MapOne(k,f v)\n            | MapNode(k,v,l,r,h,c) -> \n                let l2 = map f l \n                let v2 = f v \n                let r2 = map f r \n                MapNode(k,v2,l2, r2,h,c)\n\n        let rec mapiOpt (f:OptimizedClosures.FSharpFunc<_,_,_>) m = \n            match m with\n            | MapEmpty -> empty\n            | MapOne(k,v) -> MapOne(k, f.Invoke(k, v))\n            | MapNode(k,v,l,r,h,c) -> \n                let l2 = mapiOpt f l \n                let v2 = f.Invoke(k, v) \n                let r2 = mapiOpt f r \n                MapNode(k,v2, l2, r2,h,c)\n\n        let mapi f m = mapiOpt (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n\n        let rec mapiMonotonicAux (f:OptimizedClosures.FSharpFunc<_,_,_>) m =\n            match m with\n            | MapEmpty -> empty\n            | MapOne(k,v) -> \n                let (k2, v2) = f.Invoke(k, v)\n                MapOne(k2, v2)\n            | MapNode(k,v,l,r,h,c) -> \n                let l2 = mapiMonotonicAux f l \n                let k2, v2 = f.Invoke(k, v) \n                let r2 = mapiMonotonicAux f r \n                MapNode(k2,v2, l2, r2,h,c)\n\n        let mapiMonotonic f m = mapiMonotonicAux (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n    \n\n        let rec chooseiMonotonicAux (f:OptimizedClosures.FSharpFunc<_,_,_>) m =\n            match m with\n            | MapEmpty -> empty\n            | MapOne(k,v) -> \n                match f.Invoke(k, v) with\n                | Some (k2, v2) ->\n                    MapOne(k2, v2)\n                | None ->\n                    MapEmpty\n            | MapNode(k,v,l,r,h,c) -> \n                let l2 = chooseiMonotonicAux f l \n                let self = f.Invoke(k, v) \n                let r2 = chooseiMonotonicAux f r \n                match self with\n                | Some (k2, v2) ->\n                    join l2 k2 v2 r2\n                | None ->\n                    match l2 with\n                    | MapEmpty -> r2\n                    | _ ->\n                        match r2 with\n                        | MapEmpty -> l2\n                        | _ ->\n                            let k,v,r2 = spliceOutSuccessor r2\n                            join l2 k v r2\n\n        let chooseiMonotonic f m = chooseiMonotonicAux (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n    \n        let rec chooseiOpt (f:OptimizedClosures.FSharpFunc<'Key,'T1,option<'T2>>) m =\n            match m with\n            | MapEmpty -> empty\n            | MapOne(k,v) ->\n                match f.Invoke(k,v) with\n                | Some v -> MapOne(k,v)\n                | None -> MapEmpty\n\n            | MapNode(k,v,l,r,h,c) ->\n                let l' = chooseiOpt f l\n                let s' = f.Invoke(k,v)\n                let r' = chooseiOpt f r\n                match s' with\n                | None -> merge l' r'\n                | Some v -> join l' k v r'\n\n        let choosei f m = chooseiOpt (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)) m\n    \n        let rec chooseiOptV (f:OptimizedClosures.FSharpFunc<'Key,'T1,voption<'T2>>) m =\n            match m with\n            | MapEmpty -> empty\n            | MapOne(k,v) ->\n                match f.Invoke(k,v) with\n                | ValueSome v -> MapOne(k,v)\n                | ValueNone -> MapEmpty\n\n            | MapNode(k,v,l,r,h,c) ->\n                let l' = chooseiOptV f l\n                let s' = f.Invoke(k,v)\n                let r' = chooseiOptV f r\n                match s' with\n                | ValueNone -> merge l' r'\n                | ValueSome v -> join l' k v r'\n\n        let rec chooseiOptV2 (f:OptimizedClosures.FSharpFunc<'Key,'T1,struct (voption<'T2> * voption<'T3>)>) m =\n            match m with\n                | MapEmpty -> \n                    struct(MapEmpty, MapEmpty)\n\n                | MapOne(k,v) ->\n                    let struct (a, b) = f.Invoke(k,v)\n                    let a = match a with | ValueSome v -> MapOne(k,v) | ValueNone -> MapEmpty\n                    let b = match b with | ValueSome v -> MapOne(k,v) | ValueNone -> MapEmpty\n                    struct (a, b)\n\n                | MapNode(k,v,l,r,h,c) ->\n                    let struct(la', lb') = chooseiOptV2 f l\n                    let struct (sa', sb') = f.Invoke(k,v)\n                    let struct (ra', rb') = chooseiOptV2 f r\n\n                    let a = joinV la' k sa' ra'\n                    let b = joinV lb' k sb' rb'\n                    struct (a, b)\n\n\n        let rec neighboursAux (comparer: IComparer<'Value>) k l r m =\n            match m with\n                | MapEmpty -> l, None, r\n                | MapOne(k2,v2) -> \n                    let c = comparer.Compare(k, k2)\n                    if c > 0 then Some(k2,v2), None, r\n                    elif c = 0 then l, Some(k2,v2), r\n                    else l, None, Some(k2,v2)\n\n                | MapNode(k2,v2,l2,r2,_,_) ->\n                    let c = comparer.Compare(k, k2)\n                    if c > 0 then \n                        let l = Some(k2, v2)\n                        neighboursAux comparer k l r r2\n\n                    elif c = 0 then\n                        let l =\n                            match tryMax l2 with\n                                | None -> l\n                                | l -> l\n\n                        let r =\n                            match tryMin r2 with\n                                | None -> r\n                                | r -> r\n\n                        l,Some(k2, v2),r\n\n                    else\n                        let r = Some(k2, v2)\n                        neighboursAux comparer k l r l2\n\n        let neighbours (comparer: IComparer<'Value>) k m =\n            neighboursAux comparer k None None m\n    \n        let rec neighboursiAux idx l r m =\n            match m with\n                | MapEmpty -> \n                    l, None, r\n\n                | MapOne(k2,v2) -> \n                    if idx > 0 then Some(k2,v2), None, r\n                    elif idx = 0 then l, Some(k2,v2), r\n                    else l, None, Some(k2,v2)\n\n                | MapNode(k2,v2,l2,r2,_,cnt) ->\n                    if idx < 0 then\n                        None, None, tryMin m\n                    elif idx >= cnt then\n                        tryMax m, None, None\n                    else\n                        let lc = size l2\n                        if idx < lc then \n                            let r = Some(k2, v2)\n                            neighboursiAux idx l r l2\n\n                        elif idx = lc then\n                            let l =\n                                match tryMax l2 with\n                                    | None -> l\n                                    | l -> l\n\n                            let r =\n                                match tryMin r2 with\n                                    | None -> r\n                                    | r -> r\n\n                            l, Some(k2, v2), r\n                        else\n                            let l = Some(k2, v2)\n                            neighboursiAux (idx-lc-1) l r r2\n\n        let neighboursi idx m =\n            neighboursiAux idx None None m\n    \n\n    \n        let rec neighboursVAux (comparer: IComparer<'Value>) k l r m =\n            match m with\n                | MapEmpty -> struct(l, ValueNone, r)\n                | MapOne(k2,v2) -> \n                    let c = comparer.Compare(k, k2)\n                    if c > 0 then struct(ValueSome(struct(k2,v2)), ValueNone, r)\n                    elif c = 0 then struct(l, ValueSome(struct(k2,v2)), r)\n                    else struct(l, ValueNone, ValueSome(struct(k2,v2)))\n\n                | MapNode(k2,v2,l2,r2,_,_) ->\n                    let c = comparer.Compare(k, k2)\n                    if c > 0 then \n                        let l = ValueSome(struct(k2, v2))\n                        neighboursVAux comparer k l r r2\n\n                    elif c = 0 then\n                        let l =\n                            match tryMaxV l2 with\n                            | ValueNone -> l\n                            | l -> l\n\n                        let r =\n                            match tryMinV r2 with\n                            | ValueNone -> r\n                            | r -> r\n\n                        struct(l,ValueSome(struct(k2, v2)),r)\n\n                    else\n                        let r = ValueSome(struct(k2, v2))\n                        neighboursVAux comparer k l r l2\n\n        let neighboursV (comparer: IComparer<'Value>) k m =\n            neighboursVAux comparer k ValueNone ValueNone m\n    \n    \n        let rec neighboursViAux idx l r m =\n            match m with\n                | MapEmpty -> \n                    struct(l, ValueNone, r)\n\n                | MapOne(k2,v2) -> \n                    if idx > 0 then struct(ValueSome(struct(k2,v2)), ValueNone, r)\n                    elif idx = 0 then struct(l, ValueSome(struct(k2,v2)), r)\n                    else struct(l, ValueNone, ValueSome(struct(k2,v2)))\n\n                | MapNode(k2,v2,l2,r2,_,cnt) ->\n                    if idx < 0 then\n                        struct(ValueNone, ValueNone, tryMinV m)\n                    elif idx >= cnt then\n                        struct(tryMaxV m, ValueNone, ValueNone)\n                    else\n                        let lc = size l2\n                        if idx < lc then \n                            let r = ValueSome(struct(k2, v2))\n                            neighboursViAux idx l r l2\n\n                        elif idx = lc then\n                            let l =\n                                match tryMaxV l2 with\n                                | ValueNone -> l\n                                | l -> l\n\n                            let r =\n                                match tryMinV r2 with\n                                | ValueNone -> r\n                                | r -> r\n\n                            struct(l, ValueSome(struct(k2, v2)), r)\n                        else\n                            let l = ValueSome(struct(k2, v2))\n                            neighboursViAux (idx-lc-1) l r r2\n\n        let neighboursVi idx m =\n            neighboursViAux idx ValueNone ValueNone m\n    \n\n\n        let rec tryAt i m =\n            match m with\n            | MapEmpty -> \n                None\n\n            | MapOne(k,v) -> \n                if i = 0 then Some (k,v)\n                else None\n\n            | MapNode(k,v,l,r,_,c) ->\n                if i < 0 || i >= c then\n                    None\n                else\n                    let ls = size l\n                    if i = ls then\n                        Some (k,v)\n                    elif i < ls then\n                        tryAt i l\n                    else\n                        tryAt (i - ls - 1) r\n\n        let rec tryAtV i m =\n            match m with\n            | MapEmpty -> \n                ValueNone\n\n            | MapOne(k,v) -> \n                if i = 0 then ValueSome (struct(k,v))\n                else ValueNone\n\n            | MapNode(k,v,l,r,_,c) ->\n                if i < 0 || i >= c then\n                    ValueNone\n                else\n                    let ls = size l\n                    if i = ls then\n                        ValueSome (struct(k,v))\n                    elif i < ls then\n                        tryAtV i l\n                    else\n                        tryAtV (i - ls - 1) r\n\n        let rec private tryGetIndexAux (comparer: IComparer<'Key>) (i : int) (key : 'Key) (m : MapTree<'Key, 'Value>) =\n            match m with\n            | MapEmpty -> \n                None\n            | MapOne(k,_value) -> \n                if comparer.Compare(key, k) = 0 then Some i\n                else None\n            | MapNode(k,_value,left,right,_,_) ->\n                let cmp = comparer.Compare(key, k)\n                if cmp > 0 then\n                    tryGetIndexAux comparer (i + size left + 1) key right\n                elif cmp < 0 then\n                    tryGetIndexAux comparer i key left\n                else\n                    Some (i + size left)\n                \n        let tryGetIndex (comparer: IComparer<'Key>) (key : 'Key) (m : MapTree<'Key, 'Value>) =\n            tryGetIndexAux comparer 0 key m\n            \n        let rec private tryGetIndexVAux (comparer: IComparer<'Key>) (i : int) (key : 'Key) (m : MapTree<'Key, 'Value>) =\n            match m with\n            | MapEmpty -> \n                ValueNone\n            | MapOne(k,_value) -> \n                if comparer.Compare(key, k) = 0 then ValueSome i\n                else ValueNone\n            | MapNode(k,_value,left,right,_,_) ->\n                let cmp = comparer.Compare(key, k)\n                if cmp > 0 then\n                    tryGetIndexVAux comparer (i + size left + 1) key right\n                elif cmp < 0 then\n                    tryGetIndexVAux comparer i key left\n                else\n                    ValueSome (i + size left)\n                \n        let tryGetIndexV (comparer: IComparer<'Key>) (key : 'Key) (m : MapTree<'Key, 'Value>) =\n            tryGetIndexVAux comparer 0 key m\n\n        let rec map2 (comparer: IComparer<'Value>) f l r =\n            match l, r with\n                | MapEmpty, r -> mapi (fun i rv -> f i None (Some rv)) r\n                | l, MapEmpty -> mapi (fun i lv -> f i (Some lv) None) l\n                | MapOne(k,v), r ->\n                    let mutable found = false\n                    let res = \n                        r |> mapi (fun i rv -> \n                            if i = k then \n                                found <- true\n                                f i (Some v) (Some rv)\n                            else \n                                f i None (Some rv)\n                        )\n                    if found then res \n                    else res |> add comparer k (f k (Some v) None)\n\n                | l, MapOne(k,v) ->\n                    let mutable found = false\n                    let res = \n                        l |> mapi (fun i lv -> \n                            if i = k then \n                                found <- true\n                                f i (Some lv) (Some v)\n                            else \n                                f i None (Some v)\n                        )\n                    if found then res \n                    else res |> add comparer k (f k None (Some v))\n\n                | MapNode(k,v,ll,lr,_,_),r ->\n                    let rs, self, rg = split comparer k r\n                    \n                    let v = \n                        match self with\n                            | Some rv -> f k (Some v) (Some rv)\n                            | None -> f k (Some v) None\n                    join (map2 comparer f ll rs) k v (map2 comparer f lr rg)\n\n        let rec map2VOpt\n            (comparer: IComparer<'Key>)\n            (f : OptimizedClosures.FSharpFunc<'Key, voption<'T1>, voption<'T2>, 'T3>)\n            (lo : OptimizedClosures.FSharpFunc<'Key, 'T1, 'T3>)\n            (ro : OptimizedClosures.FSharpFunc<'Key, 'T2, 'T3>)\n            l r =\n            match l, r with\n                | MapEmpty, r -> mapiOpt ro r\n                | l, MapEmpty -> mapiOpt lo l\n                | MapOne(lk, lv), MapOne(rk, rv) ->\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then\n                        MapOne(lk, f.Invoke(lk, ValueSome lv, ValueSome rv))\n                    else\n                        let l = MapOne(lk, f.Invoke(lk, ValueSome lv, ValueNone))\n                        let r = MapOne(rk, f.Invoke(rk, ValueNone, ValueSome rv))\n                        if c < 0 then\n                            merge l r\n                        else\n                            merge r l\n\n                | MapNode(lk, lv, ll, lr, lh, lc), MapOne(rk, rv) ->\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then\n                        let ll = mapiOpt lo ll\n                        let lr = mapiOpt lo lr\n                        let v = f.Invoke(lk, ValueSome lv, ValueSome rv)\n                        join ll lk v lr\n                    elif c > 0 then\n                        join (map2VOpt comparer f lo ro ll r) lk (lo.Invoke(lk, lv)) (mapiOpt lo lr)\n                    else\n                        join (mapiOpt lo ll) lk (lo.Invoke(lk, lv)) (map2VOpt comparer f lo ro lr r)\n\n\n                | MapOne(lk, lv), MapNode(rk, rv, rl, rr, rh, rc) ->\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then\n                        let rl = mapiOpt ro rl\n                        let rr = mapiOpt ro rr\n                        let v = f.Invoke(rk, ValueSome lv, ValueSome rv)\n                        join rl rk v rr\n                    elif c > 0 then\n                        join (mapiOpt ro rl) rk (ro.Invoke(rk, rv)) (map2VOpt comparer f lo ro l rr)\n                    else\n                        join (map2VOpt comparer f lo ro l rl) rk (ro.Invoke(rk, rv)) (mapiOpt ro rr)\n\n                | MapNode(lk, lv, ll, lr, lh, lc), MapNode(rk, rv, rl, rr, rh, rc) ->\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then\n                        join (map2VOpt comparer f lo ro ll rl) lk (f.Invoke(lk, ValueSome lv, ValueSome rv)) (map2VOpt comparer f lo ro  lr rr)\n                    elif lh > rh then\n                        let struct (rl, _lmax, rv, _rmin, rr) = splitV comparer lk r\n                        join (map2VOpt comparer f lo ro ll rl) lk (f.Invoke(lk, ValueSome lv, rv)) (map2VOpt comparer f lo ro  lr rr)\n                    else\n                        let struct (ll, _lmax, lv, _rmin, lr) = splitV comparer rk l\n                        join (map2VOpt comparer f lo ro ll rl) rk (f.Invoke(rk, lv, ValueSome rv)) (map2VOpt comparer f lo ro  lr rr)\n\n        let map2V\n            (comparer: IComparer<'Key>)\n            (mapping : 'Key -> voption<'T1> -> voption<'T2> -> 'T3)\n            l r =\n\n            let mapping = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt mapping\n            let lo = OptimizedClosures.FSharpFunc<_,_,_>.Adapt (fun k l -> mapping.Invoke(k, ValueSome l, ValueNone))\n            let ro = OptimizedClosures.FSharpFunc<_,_,_>.Adapt (fun k r -> mapping.Invoke(k, ValueNone, ValueSome r))\n\n            map2VOpt comparer mapping lo ro l r\n\n        let rec choose2VOpt \n            (comparer: IComparer<'Key>) \n            (f : OptimizedClosures.FSharpFunc<'Key, voption<'T1>, voption<'T2>, voption<'T3>>) \n            (lo : OptimizedClosures.FSharpFunc<'Key, 'T1, voption<'T3>>) \n            (ro : OptimizedClosures.FSharpFunc<'Key, 'T2, voption<'T3>>)\n            l r =\n            match l, r with\n                | MapEmpty, r -> chooseiOptV ro r\n                | l, MapEmpty -> chooseiOptV lo l\n                | MapOne(lk, lv), MapOne(rk, rv) ->\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then\n                        match f.Invoke(lk, ValueSome lv, ValueSome rv) with\n                        | ValueSome r -> MapOne(lk, r)\n                        | ValueNone -> MapEmpty\n                    else\n                        let l = match f.Invoke(lk, ValueSome lv, ValueNone) with | ValueSome r -> MapOne(lk, r) | ValueNone -> MapEmpty\n                        let r = match f.Invoke(rk, ValueNone, ValueSome rv) with | ValueSome r -> MapOne(rk, r) | ValueNone -> MapEmpty\n                        if c < 0 then\n                            merge l r\n                        else\n                            merge r l\n\n                | MapNode(lk, lv, ll, lr, lh, lc), MapOne(rk, rv) ->\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then\n                        let ll = chooseiOptV lo ll\n                        let lr = chooseiOptV lo lr\n                        match f.Invoke(lk, ValueSome lv, ValueSome rv) with\n                        | ValueSome v -> join ll lk v lr\n                        | ValueNone -> merge ll lr\n                    elif c > 0 then\n                        joinV (choose2VOpt comparer f lo ro ll r) lk (lo.Invoke(lk, lv)) (chooseiOptV lo lr)\n                    else\n                        joinV (chooseiOptV lo ll) lk (lo.Invoke(lk, lv)) (choose2VOpt comparer f lo ro lr r)\n                        \n\n                | MapOne(lk, lv), MapNode(rk, rv, rl, rr, rh, rc) ->\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then\n                        let rl = chooseiOptV ro rl\n                        let rr = chooseiOptV ro rr\n                        match f.Invoke(rk, ValueSome lv, ValueSome rv) with\n                        | ValueSome v -> join rl rk v rr\n                        | ValueNone -> merge rl rr\n                    elif c > 0 then\n                        joinV (chooseiOptV ro rl) rk (ro.Invoke(rk, rv)) (choose2VOpt comparer f lo ro l rr)\n                    else\n                        joinV (choose2VOpt comparer f lo ro l rl) rk (ro.Invoke(rk, rv)) (chooseiOptV ro rr)\n                    \n                | MapNode(lk, lv, ll, lr, lh, lc), MapNode(rk, rv, rl, rr, rh, rc) ->\n                    let c = comparer.Compare(lk, rk)\n                    if c = 0 then\n                        joinV (choose2VOpt comparer f lo ro ll rl) lk (f.Invoke(lk, ValueSome lv, ValueSome rv)) (choose2VOpt comparer f lo ro  lr rr)\n                    elif lh > rh then\n                        let struct (rl, _lmax, rv, _rmin, rr) = splitV comparer lk r\n                        joinV (choose2VOpt comparer f lo ro ll rl) lk (f.Invoke(lk, ValueSome lv, rv)) (choose2VOpt comparer f lo ro  lr rr)\n                    else\n                        let struct (ll, _lmax, lv, _rmin, lr) = splitV comparer rk l\n                        joinV (choose2VOpt comparer f lo ro ll rl) rk (f.Invoke(rk, lv, ValueSome rv)) (choose2VOpt comparer f lo ro  lr rr)\n\n\n        let choose2V \n            (comparer: IComparer<'Key>) \n            (mapping : 'Key -> voption<'T1> -> voption<'T2> -> voption<'T3>) \n            l r =\n                \n            let mapping = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt mapping\n            let lo = OptimizedClosures.FSharpFunc<_,_,_>.Adapt (fun k l -> mapping.Invoke(k, ValueSome l, ValueNone))\n            let ro = OptimizedClosures.FSharpFunc<_,_,_>.Adapt (fun k r -> mapping.Invoke(k, ValueNone, ValueSome r))\n\n            choose2VOpt comparer mapping lo ro l r\n\n\n\n        let rec applyDelta\n            (comparer : IComparer<'Key>)\n            (apply : OptimizedClosures.FSharpFunc<'Key, voption<'Value>, 'Delta, struct (voption<'Value> * voption<'DeltaOut>)>) \n            (onlyDelta : OptimizedClosures.FSharpFunc<'Key, 'Delta, struct (voption<'Value> * voption<'DeltaOut>)>)\n            (l : MapTree<'Key, 'Value>) \n            (r : MapTree<'Key, 'Delta>) =\n                \n            match struct(l, r) with\n            | struct (value, MapEmpty) ->\n                struct (value, MapEmpty)\n\n            | struct (MapEmpty, r) -> \n                chooseiOptV2 onlyDelta r\n\n            | struct (MapOne(lk, lv), MapOne(rk, rv)) ->\n                let c = comparer.Compare(lk, rk)\n                if c = 0 then\n                    let struct (s, d) = apply.Invoke(lk, ValueSome lv, rv)\n                    let s = match s with | ValueSome v -> MapOne(lk, v) | ValueNone -> MapEmpty\n                    let d = match d with | ValueSome v -> MapOne(rk, v) | ValueNone -> MapEmpty\n                    struct(s, d)\n                else\n                    let struct (s, d) = onlyDelta.Invoke(rk, rv)\n                    let d = match d with | ValueSome v -> MapOne(rk, v) | ValueNone -> MapEmpty\n                    match s with\n                    | ValueSome s ->\n                        //let state = merge (MapOne(lk, lv)) (MapOne(rk, s))\n                        let state =\n                            if c > 0 then MapNode(rk, s, MapEmpty, MapOne(lk, lv), 2, 2)\n                            else MapNode(lk, lv, MapEmpty, MapOne(rk, s), 2, 2)\n                        struct(state, d)\n                    | ValueNone ->\n                        struct (l, d)\n\n            | struct (MapOne(lk, lv), MapNode(rk, rv, rl, rr, rh, rc)) ->\n                let c = comparer.Compare(lk, rk)\n                 \n                //match tryRemove comparer lk r with\n                //| Some (rv, r) ->\n                //    let struct (s, d) = chooseiOptV2 onlyDelta r\n                //    let struct (sv, dv) = apply.Invoke(lk, ValueSome lv, rv)\n                //    let s = match sv with | ValueNone -> s | ValueSome v -> add comparer lk v s\n                //    let d = match dv with | ValueNone -> d | ValueSome v -> add comparer lk v d\n                //    struct (s, d)\n                //| None ->\n                //    let struct (s, d) = chooseiOptV2 onlyDelta r\n                //    struct(add comparer lk lv s, d)\n\n                if c = 0 then\n                    let struct (s, d) = apply.Invoke(rk, ValueSome lv, rv)\n                    let struct (rls, rld) = chooseiOptV2 onlyDelta rl\n                    let struct (rrs, rrd) = chooseiOptV2 onlyDelta rr\n\n                    let s = joinV rls rk s rrs \n                    let d = joinV rld rk d rrd \n                    struct (s, d)\n\n                elif c < 0 then\n                    let struct (s, d) = onlyDelta.Invoke(rk, rv)\n                    let struct (rls, rld) = applyDelta comparer apply onlyDelta l rl\n                    let struct (rrs, rrd) = chooseiOptV2 onlyDelta rr\n                    \n                    let s = joinV rls rk s rrs \n                    let d = joinV rld rk d rrd\n                    struct (s, d)\n\n                else\n                    let struct (s, d) = onlyDelta.Invoke(rk, rv)\n                    let struct (rls, rld) = chooseiOptV2 onlyDelta rl\n                    let struct (rrs, rrd) = applyDelta comparer apply onlyDelta l rr\n                    \n                    let s = joinV rls rk s rrs \n                    let d = joinV rld rk d rrd\n                    struct (s, d)\n\n            | struct(MapNode(lk, lv, ll, lr, _, _), MapOne(rk, rv)) ->\n                //match tryRemove comparer rk l with\n                //| Some (lv, l) ->\n                //    let struct (s, d) = apply.Invoke(rk, ValueSome lv, rv)\n                //    let s = match s with | ValueSome s -> (add comparer rk s l) | ValueNone -> l\n                //    let d = match d with | ValueSome v -> MapOne(rk, v) | ValueNone -> MapEmpty\n                //    struct (s, d)\n                //| None ->\n                //    let struct (s, d) = apply.Invoke(rk, ValueNone, rv)\n                //    let s = match s with | ValueSome s -> (add comparer rk s l) | ValueNone -> l\n                //    let d = match d with | ValueSome v -> MapOne(rk, v) | ValueNone -> MapEmpty\n                //    struct (s, d)\n                    \n                let c = comparer.Compare(lk, rk)\n                \n                if c = 0 then\n                    let struct (s, d) = apply.Invoke(lk, ValueSome lv, rv)\n                    let s = joinV ll lk s lr\n                    let d = match d with | ValueSome v -> MapOne(lk, v) | ValueNone -> MapEmpty\n                    struct (s, d)\n                    \n                elif c < 0 then\n                    // delta in right\n                    let struct (lr, d) = applyDelta comparer apply onlyDelta lr r\n                    let s = join ll lk lv lr\n                    struct (s, d)\n                else\n                    // delta in left\n                    let struct (ll, d) = applyDelta comparer apply onlyDelta ll r\n                    let s = join ll lk lv lr\n                    struct (s, d)\n                    \n            | struct(MapNode(lk, lv, ll, lr, lh, _), MapNode(rk, rv, rl, rr, rh, _)) ->\n                let c = comparer.Compare(lk, rk)\n                if c = 0 then\n                    let struct (s, d) = apply.Invoke(lk, ValueSome lv, rv)\n                    let struct (ls, ld) = applyDelta comparer apply onlyDelta ll rl\n                    let struct (rs, rd) = applyDelta comparer apply onlyDelta lr rr\n                    let s = joinV ls lk s rs \n                    let d = joinV ld lk d rd \n                    struct (s, d)\n                elif lh > rh then\n                    let struct (rl, _lmax, rv, _rmin, rr) = splitV comparer lk r\n                    let key = lk\n                    let rk = ()\n                    let lk = ()\n                    match rv with\n                    | ValueSome rv ->\n                        let struct (s, d) = apply.Invoke(key, ValueSome lv, rv)\n                        let struct (ls, ld) = applyDelta comparer apply onlyDelta ll rl\n                        let struct (rs, rd) = applyDelta comparer apply onlyDelta lr rr\n                        let s = joinV ls key s rs \n                        let d = joinV ld key d rd \n                        struct (s, d)\n                    | ValueNone ->\n                        let struct (ls, ld) = applyDelta comparer apply onlyDelta ll rl\n                        let struct (rs, rd) = applyDelta comparer apply onlyDelta lr rr\n                        let s = join ls key lv rs \n                        let d = merge ld rd \n                        struct (s, d)\n                else\n                    let struct (ll, _lmax, lv, _rmin, lr) = splitV comparer rk l\n                    let key = rk\n                    let rk = ()\n                    let lk = ()\n                    match lv with\n                    | ValueSome lv ->\n                        let struct (s, d) = apply.Invoke(key, ValueSome lv, rv)\n                        let struct (ls, ld) = applyDelta comparer apply onlyDelta ll rl\n                        let struct (rs, rd) = applyDelta comparer apply onlyDelta lr rr\n                        let s = joinV ls key s rs \n                        let d = joinV ld key d rd \n                        struct (s, d)\n                    | ValueNone ->\n                        let struct (s, d) = onlyDelta.Invoke(key, rv)\n                        let struct (ls, ld) = applyDelta comparer apply onlyDelta ll rl\n                        let struct (rs, rd) = applyDelta comparer apply onlyDelta lr rr\n                        let s = joinV ls key s rs \n                        let d = joinV ld key d rd \n                        struct (s, d)\n            //| _ ->\n            //    let mutable state = l\n\n            //    let set = System.Collections.Generic.HashSet<_>()\n\n            //    let delta = \n            //        r |> choosei (fun i op ->\n            //            if not (set.Add i) then failwith \"superbad\"\n            //            let l = match tryFind comparer i l with | Some l -> ValueSome l | None -> ValueNone\n            //            let struct (s, d) = apply.Invoke(i, l, op)\n            //            match s with\n            //            | ValueSome s -> state <- add comparer i s state\n            //            | ValueNone -> state <- remove comparer i state\n            //            match d with\n            //            | ValueSome d -> Some d\n            //            | ValueNone -> None\n            //        )\n            //    struct(state, delta)\n\n\n        let rec computeDelta \n            (comparer: IComparer<'Key>) \n            (set : OptimizedClosures.FSharpFunc<'Key, 'Value, 'OP>) \n            (update : OptimizedClosures.FSharpFunc<'Key, 'Value, 'Value, voption<'OP>>) \n            (remove : OptimizedClosures.FSharpFunc<'Key, 'Value, 'OP>) \n            (l : MapTree<'Key, 'Value>) \n            (r : MapTree<'Key, 'Value>) =\n            match struct (l, r) with\n                | struct (MapEmpty, MapEmpty) -> MapEmpty\n                | struct (MapEmpty, r) -> mapiOpt set r\n                | struct (l, MapEmpty) -> mapiOpt remove l\n\n                | struct (MapOne(lk, lv), MapOne(rk, rv)) ->\n                    if Object.ReferenceEquals(l, r) then\n                        MapEmpty\n                    else\n                        let c = comparer.Compare(lk, rk)\n                        if c = 0 then\n                            match update.Invoke(lk, lv, rv) with\n                            | ValueSome r -> MapOne(lk, r)\n                            | ValueNone -> MapEmpty\n                        elif c < 0 then\n                            MapNode(lk, remove.Invoke(lk, lv), MapEmpty, MapOne(rk, set.Invoke(rk, rv)), 2, 2)\n                        else\n                            MapNode(lk, remove.Invoke(lk, lv), MapOne(rk, set.Invoke(rk, rv)), MapEmpty, 2, 2)\n                            \n                | struct (MapOne(lk, lv), MapNode(nk, nv, nl, nr, _, _)) ->\n                    let c = comparer.Compare(lk, nk)\n                    if c = 0 then\n                        let ll = mapiOpt set nl\n                        let rr = mapiOpt set nr\n                        match update.Invoke(lk, lv, nv) with\n                        | ValueSome op ->\n                            join ll lk op rr\n                        | ValueNone ->\n                            merge ll rr\n                    elif c > 0 then\n                        let rr = computeDelta comparer set update remove l nr\n                        join (mapiOpt set nl) nk (set.Invoke(nk, nv)) rr\n                    else\n                        let ll = computeDelta comparer set update remove l nl\n                        join ll nk (set.Invoke(nk, nv)) (mapiOpt set nr)\n\n                | struct(MapNode(nk, nv, nl, nr, _, _), MapOne(rk, rv)) ->\n                    let c = comparer.Compare(rk, nk)\n                    if c = 0 then\n                        let ll = mapiOpt remove nl\n                        let rr = mapiOpt remove nr\n                        match update.Invoke(rk, nv, rv) with\n                        | ValueSome op ->\n                            join ll nk op rr\n                        | ValueNone ->\n                            merge ll rr\n                    elif c > 0 then\n                        let rr = computeDelta comparer set update remove nr r\n                        join (mapiOpt remove nl) nk (remove.Invoke(nk, nv)) rr\n                    else\n                        let ll = computeDelta comparer set update remove nl r\n                        join ll nk (remove.Invoke(nk, nv)) (mapiOpt remove nr)\n\n                | struct(MapNode(lka, lva, lla, lra, lha, _), MapNode(rka, rva, rla, rra, rha, _rc)) ->\n                    if Object.ReferenceEquals(l, r) then\n                        MapEmpty\n                    else\n                        let c = comparer.Compare(lka, rka)\n                        if c = 0 then\n                            let l = computeDelta comparer set update remove lla rla\n                            let r = computeDelta comparer set update remove lra rra\n                            match update.Invoke(lka, lva, rva) with\n                            | ValueSome op ->\n                                join l lka op r\n                            | ValueNone ->\n                                merge l r\n\n                        elif rha < lha then\n                            let struct (rl, _lmax, rv, _rmin, rr) = splitV comparer lka r\n                            let l = computeDelta comparer set update remove lla rl\n                            let r = computeDelta comparer set update remove lra rr\n                            match rv with\n                            | ValueSome rv -> \n                                match update.Invoke(lka, lva, rv) with\n                                | ValueSome op ->\n                                    join l lka op r\n                                | ValueNone ->\n                                    merge l r\n                            | ValueNone ->\n                                let k = lka\n                                let v = remove.Invoke(lka, lva)\n                                join l k v r\n                        else\n                            let struct (ll, _lmax, lv, _rmin, lr) = splitV comparer rka l\n                            let l = computeDelta comparer set update remove ll rla\n                            let r = computeDelta comparer set update remove lr rra\n\n                            match lv with\n                            | ValueSome lv -> \n                                match update.Invoke(rka, lv, rva) with\n                                | ValueSome op ->\n                                    join l rka op r\n                                | ValueNone ->\n                                    merge l r\n                            | ValueNone ->\n                                let k = rka\n                                let v = set.Invoke(rka, rva)\n                                join l k v r\n                                \n\n        let rec intersectWithAux (f:OptimizedClosures.FSharpFunc<'Key,'T1,'T2>) (comparer: IComparer<'k>) (l : MapTree<'k, 'Key>) (r : MapTree<'k, 'T1>) : MapTree<'k, 'T2> =\n            match l with\n            | MapEmpty -> \n                MapEmpty\n\n            | MapOne(k,lv) ->\n                match tryFind comparer k r with\n                | Some rv -> MapOne(k, f.Invoke(lv, rv))\n                | None -> MapEmpty\n\n            | MapNode(k,v,l1,r1,_,_) ->\n                let a, s, b = split comparer k r\n                match s with\n                | Some s ->\n                    let v = f.Invoke(v,s)\n                    rebalance (intersectWithAux f comparer l1 a) k v (intersectWithAux f comparer r1 b)\n                | None ->\n                    let l = intersectWithAux f comparer l1 a\n                    let r = intersectWithAux f comparer r1 b\n                    match l with\n                    | MapEmpty -> r\n                    | _ ->\n                        match r with\n                        | MapEmpty -> l\n                        | _ ->\n                            let k,v,r' = spliceOutSuccessor r\n                            rebalance l k v r'\n\n        let intersectWith (f : 'Key -> 'T1 -> 'T2) (comparer : IComparer<'k>) (l : MapTree<'k, 'Key>) (r : MapTree<'k, 'T1>) =\n            let lc = size l\n            let rc = size r\n            if lc <= rc then\n                intersectWithAux (OptimizedClosures.FSharpFunc<_,_,_>.Adapt f) comparer l r\n            else\n                intersectWithAux (OptimizedClosures.FSharpFunc<_,_,_>.Adapt(fun a b -> f b a)) comparer r l\n\n\n                      \n        let rec foldBackOpt (f:OptimizedClosures.FSharpFunc<_,_,_,_>) m x = \n            match m with \n            | MapEmpty -> x\n            | MapOne(k,v) -> f.Invoke(k,v,x)\n            | MapNode(k,v,l,r,_,_) -> \n                let x = foldBackOpt f r x\n                let x = f.Invoke(k,v,x)\n                foldBackOpt f l x\n\n        let foldBack f m x = foldBackOpt (OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f)) m x\n\n        let rec foldOpt (f:OptimizedClosures.FSharpFunc<_,_,_,_>) x m  = \n            match m with \n            | MapEmpty -> x\n            | MapOne(k,v) -> f.Invoke(x,k,v)\n            | MapNode(k,v,l,r,_,_) -> \n                let x = foldOpt f x l\n                let x = f.Invoke(x,k,v)\n                foldOpt f x r\n\n        let fold f x m = foldOpt (OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f)) x m\n\n        let foldSectionOpt (comparer: IComparer<'Value>) lo hi (f:OptimizedClosures.FSharpFunc<_,_,_,_>) m x =\n            let rec foldFromTo (f:OptimizedClosures.FSharpFunc<_,_,_,_>) m x = \n                match m with \n                | MapEmpty -> x\n                | MapOne(k,v) ->\n                    let cLoKey = comparer.Compare(lo,k)\n                    let cKeyHi = comparer.Compare(k,hi)\n                    let x = if cLoKey <= 0 && cKeyHi <= 0 then f.Invoke(k, v, x) else x\n                    x\n                | MapNode(k,v,l,r,_,_) ->\n                    let cLoKey = comparer.Compare(lo,k)\n                    let cKeyHi = comparer.Compare(k,hi)\n                    let x = if cLoKey < 0                 then foldFromTo f l x else x\n                    let x = if cLoKey <= 0 && cKeyHi <= 0 then f.Invoke(k, v, x) else x\n                    let x = if cKeyHi < 0                 then foldFromTo f r x else x\n                    x\n           \n            if comparer.Compare(lo,hi) = 1 then x else foldFromTo f m x\n\n        let foldSection (comparer: IComparer<'Value>) lo hi f m x =\n            foldSectionOpt comparer lo hi (OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f)) m x\n\n        let toList m = \n            let rec loop m acc = \n                match m with \n                | MapEmpty -> acc\n                | MapOne(k,v) -> (k,v)::acc\n                | MapNode(k,v,l,r,_,_) -> loop l ((k,v)::loop r acc)\n            loop m []\n\n        let toListV m =\n            let rec loop m acc = \n                match m with \n                | MapEmpty -> acc\n                | MapOne(k,v) -> struct(k,v)::acc\n                | MapNode(k,v,l,r,_,_) -> loop l (struct(k,v)::loop r acc)\n            loop m []\n\n        let rec private copyTo (array : array<'k * 'v>) (index : ref<int>) m =\n            match m with\n            | MapEmpty -> \n                ()\n            | MapOne(k,v) -> \n                array.[!index] <- (k, v)\n                index := !index + 1\n            | MapNode(k, v, l, r, _, _) ->\n                copyTo array index l\n                array.[!index] <- (k, v)\n                index := !index + 1\n                copyTo array index r\n\n        let rec private copyToV (array : array<struct('k * 'v)>) (index : ref<int>) m =\n            match m with\n            | MapEmpty -> \n                ()\n            | MapOne(k,v) -> \n                array.[!index] <- struct(k, v)\n                index := !index + 1\n            | MapNode(k, v, l, r, _, _) ->\n                copyToV array index l\n                array.[!index] <- struct(k, v)\n                index := !index + 1\n                copyToV array index r\n\n        let rec private copyValuesTo (array : array<'v>) (index : ref<int>) m =\n            match m with\n            | MapEmpty -> \n                ()\n            | MapOne(k,v) -> \n                array.[!index] <- v\n                index := !index + 1\n            | MapNode(k, v, l, r, _, _) ->\n                copyValuesTo array index l\n                array.[!index] <- v\n                index := !index + 1\n                copyValuesTo array index r\n\n        let toArrayV m =\n            let cnt = size m\n            let arr = Array.zeroCreate cnt\n            let index = ref 0 \n            copyToV arr index m\n            arr\n\n        let toArray m =\n            let cnt = size m\n            let arr = Array.zeroCreate cnt\n            let index = ref 0 \n            copyTo arr index m\n            arr\n            \n\n        let valueList m =\n            let rec loop m acc = \n                match m with \n                | MapEmpty -> acc\n                | MapOne(k,v) -> v::acc\n                | MapNode(k,v,l,r,_,_) -> loop l (v::loop r acc)\n            loop m []\n            \n        let valueArray m =\n            let cnt = size m\n            let arr = Array.zeroCreate cnt\n            let index = ref 0 \n            copyValuesTo arr index m\n            arr\n            \n\n\n        let ofList comparer l = List.fold (fun acc (k,v) -> add comparer k v acc) empty l\n        let ofListV comparer l = List.fold (fun acc (struct (k,v)) -> add comparer k v acc) empty l\n\n        let rec mkFromEnumerator comparer acc (e : IEnumerator<_>) = \n            if e.MoveNext() then \n                let (x,y) = e.Current \n                mkFromEnumerator comparer (add comparer x y acc) e\n            else acc\n\n        let rec mkFromEnumeratorV comparer acc (e : IEnumerator<_>) = \n            if e.MoveNext() then \n                let struct (x,y) = e.Current \n                mkFromEnumeratorV comparer (add comparer x y acc) e\n            else acc\n          \n        let ofArray comparer (arr : array<_>) =\n            let mutable res = empty\n            for (x,y) in arr do\n                res <- add comparer x y res \n            res\n\n        let ofArrayV comparer (arr : array<_>) =\n            let mutable res = empty\n            for struct (x,y) in arr do\n                res <- add comparer x y res \n            res\n\n        let ofSeq comparer (c : seq<'Key * 'T>) =\n            match c with \n            | :? array<'Key * 'T> as xs -> ofArray comparer xs\n            | :? list<'Key * 'T> as xs -> ofList comparer xs\n            | _ -> \n                use ie = c.GetEnumerator()\n                mkFromEnumerator comparer empty ie\n\n        let ofSeqV comparer (c : seq<struct ('Key * 'T)>) =\n            match c with \n            | :? array<struct ('Key * 'T)> as xs -> ofArrayV comparer xs\n            | :? list<struct ('Key * 'T)> as xs -> ofListV comparer xs\n            | _ -> \n                use ie = c.GetEnumerator()\n                mkFromEnumeratorV comparer empty ie \n\n          \n        let copyToArray s (arr: _[]) i =\n            let j = ref i \n            s |> iter (fun x y -> arr.[!j] <- KeyValuePair(x,y); j := !j + 1)\n\n\n        /// Imperative left-to-right iterators.\n        [<NoEquality; NoComparison>]\n        type MapIterator<'Key,'Value when 'Key : comparison > = \n                { /// invariant: always collapseLHS result \n                mutable stack: MapTree<'Key,'Value> list;  \n                /// true when MoveNext has been called   \n                mutable started : bool }\n\n        // collapseLHS:\n        // a) Always returns either [] or a list starting with MapOne.\n        // b) The \"fringe\" of the set stack is unchanged. \n        let rec collapseLHS stack =\n            match stack with\n            | []                           -> []\n            | MapEmpty             :: rest -> collapseLHS rest\n            | MapOne _         :: _ -> stack\n            | (MapNode(k,v,l,r,_,_)) :: rest -> collapseLHS (l :: MapOne (k,v) :: r :: rest)\n          \n        let mkIterator s = { stack = collapseLHS [s]; started = false }\n\n        let notStarted() = raise (InvalidOperationException(\"enumeration not started\"))\n        let alreadyFinished() = raise (InvalidOperationException(\"enumeration finished\"))\n\n        let current i =\n            if i.started then\n                match i.stack with\n                    | MapOne (k,v) :: _ -> new KeyValuePair<_,_>(k,v)\n                    | []            -> alreadyFinished()\n                    | _             -> failwith \"Please report error: MapExt iterator, unexpected stack for current\"\n            else\n                notStarted()\n\n        let rec moveNext i =\n            if i.started then\n                match i.stack with\n                    | MapOne _ :: rest -> \n                        i.stack <- collapseLHS rest\n                        not i.stack.IsEmpty\n                    | [] -> false\n                    | _ -> failwith \"Please report error: MapExt iterator, unexpected stack for moveNext\"\n            else\n                i.started <- true  (* The first call to MoveNext \"starts\" the enumeration. *)\n                not i.stack.IsEmpty\n\n        let mkIEnumerator s = \n            let i = ref (mkIterator s) \n            { new IEnumerator<_> with \n                member __.Current = current !i\n            interface System.Collections.IEnumerator with\n                member __.Current = box (current !i)\n                member __.MoveNext() = moveNext !i\n                member __.Reset() = i :=  mkIterator s\n            interface System.IDisposable with \n                member __.Dispose() = ()}\n\n\n        type MapTreeEnumerator<'k, 'v when 'k : comparison>(m : MapTree<'k, 'v>) =\n            let mutable stack = [m]\n            let mutable current = Unchecked.defaultof<'k * 'v>\n            \n            let rec move () =\n                match stack with\n                    | [] ->\n                        false\n                    | MapEmpty :: rest ->\n                        stack <- rest\n                        move()\n\n                    | MapOne(key,value) :: rest ->\n                        stack <- rest\n                        current <- (key, value)\n                        true\n\n                    | MapNode(k,v,l,r,_,_) :: rest ->\n                        stack <- l :: (MapOne(k,v)) :: r :: rest\n                        move()\n                        \n            interface System.Collections.IEnumerator with\n                member x.MoveNext() = move()\n                member x.Reset() =\n                    stack <- [m]\n                    current <- Unchecked.defaultof<'k * 'v>\n\n                member x.Current = current :> obj\n                \n            interface IEnumerator<'k * 'v> with\n                member x.Dispose() =\n                    stack <- []\n                    current <- Unchecked.defaultof<'k * 'v>\n                member x.Current = current\n\n        type MapTreeBackwardEnumerator<'k, 'v when 'k : comparison>(m : MapTree<'k, 'v>) =\n            let mutable stack = [m]\n            let mutable current = Unchecked.defaultof<'k * 'v>\n            \n            let rec move () =\n                match stack with\n                    | [] ->\n                        false\n                    | MapEmpty :: rest ->\n                        stack <- rest\n                        move()\n\n                    | MapOne(key,value) :: rest ->\n                        stack <- rest\n                        current <- (key, value)\n                        true\n\n                    | MapNode(k,v,l,r,_,_) :: rest ->\n                        stack <- r :: (MapOne(k,v)) :: l :: rest\n                        move()\n                        \n            interface System.Collections.IEnumerator with\n                member x.MoveNext() = move()\n                member x.Reset() =\n                    stack <- [m]\n                    current <- Unchecked.defaultof<'k * 'v>\n\n                member x.Current = current :> obj\n                \n            interface IEnumerator<'k * 'v> with\n                member x.Dispose() =\n                    stack <- []\n                    current <- Unchecked.defaultof<'k * 'v>\n                member x.Current = current\n\n        type ValueMapTreeEnumerator<'k, 'v when 'k : comparison>(m : MapTree<'k, 'v>) =\n            let mutable stack = [m]\n            let mutable current = Unchecked.defaultof<struct('k * 'v)>\n            \n            let rec move () =\n                match stack with\n                    | [] ->\n                        false\n                    | MapEmpty :: rest ->\n                        stack <- rest\n                        move()\n\n                    | MapOne(key,value) :: rest ->\n                        stack <- rest\n                        current <- struct(key, value)\n                        true\n\n                    | MapNode(k,v,l,r,_,_) :: rest ->\n                        stack <- l :: (MapOne(k,v)) :: r :: rest\n                        move()\n                        \n            interface System.Collections.IEnumerator with\n                member x.MoveNext() = move()\n                member x.Reset() =\n                    stack <- [m]\n                    current <- Unchecked.defaultof<_>\n\n                member x.Current = current :> obj\n                \n            interface IEnumerator<struct('k * 'v)> with\n                member x.Dispose() =\n                    stack <- []\n                    current <- Unchecked.defaultof<_>\n                member x.Current = current\n\n        type ValueMapTreeBackwardEnumerator<'k, 'v when 'k : comparison>(m : MapTree<'k, 'v>) =\n            let mutable stack = [m]\n            let mutable current = Unchecked.defaultof<struct('k * 'v)>\n            \n            let rec move () =\n                match stack with\n                    | [] ->\n                        false\n                    | MapEmpty :: rest ->\n                        stack <- rest\n                        move()\n\n                    | MapOne(key,value) :: rest ->\n                        stack <- rest\n                        current <- struct(key, value)\n                        true\n\n                    | MapNode(k,v,l,r,_,_) :: rest ->\n                        stack <- r :: (MapOne(k,v)) :: l :: rest\n                        move()\n                        \n            interface System.Collections.IEnumerator with\n                member x.MoveNext() = move()\n                member x.Reset() =\n                    stack <- [m]\n                    current <- Unchecked.defaultof<_>\n\n                member x.Current = current :> obj\n                \n            interface IEnumerator<struct('k * 'v)> with\n                member x.Dispose() =\n                    stack <- []\n                    current <- Unchecked.defaultof<_>\n                member x.Current = current\n\n\nopen MapExtImplementation\n\n\n[<System.Diagnostics.DebuggerTypeProxy(typedefof<MapDebugView<_,_>>)>]\n[<System.Diagnostics.DebuggerDisplay(\"Count = {Count}\")>]\n[<Sealed;CustomPickler>]\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype MapExt<[<EqualityConditionalOn>]'Key,[<EqualityConditionalOn;ComparisonConditionalOn>]'Value when 'Key : comparison > internal(comparer: IComparer<'Key>, tree: MapTree<'Key,'Value>) =\n\n    static let defaultComparer = LanguagePrimitives.FastGenericComparer<'Key> \n    // We use .NET generics per-instantiation static fields to avoid allocating a new object for each empty\n    // set (it is just a lookup into a .NET table of type-instantiation-indexed static fields).\n    static let empty = new MapExt<'Key,'Value>(defaultComparer, MapTree<_,_>.MapEmpty)\n\n    static member private CreatePickler (r : IPicklerResolver) =\n        let pInt = r.Resolve<int>()\n        let pKey = r.Resolve<'Key>()\n        let pValue = r.Resolve<'Value>()\n        let pArray = Pickler.array (Pickler.pair pKey pValue)\n\n        let read (rs : ReadState) =\n            let _cnt = pInt.Read rs \"count\"\n            let arr = pArray.Read rs \"items\"\n            MapExt<'Key, 'Value>(defaultComparer, MapTree.ofArray defaultComparer arr)\n\n        let write (ws : WriteState) (m : MapExt<'Key, 'Value>) =\n            pInt.Write ws \"count\" m.Count\n            pArray.Write ws \"items\" (m.ToArray())\n\n        let clone (cs : CloneState) (m : MapExt<'Key, 'Value>) =\n            m.MapMonotonic (fun k v -> pKey.Clone cs k, pValue.Clone cs v)\n\n        let accept (vs : VisitState) (m : MapExt<'Key, 'Value>) =\n            for kv in m do pKey.Accept vs kv.Key; pValue.Accept vs kv.Value\n\n        Pickler.FromPrimitives(read, write, clone, accept)\n\n\n    static member Empty : MapExt<'Key,'Value> = empty\n\n    static member Create(ie : IEnumerable<_>) : MapExt<'Key,'Value> = \n        let comparer = LanguagePrimitives.FastGenericComparer<'Key> \n        new MapExt<_,_>(comparer,MapTree.ofSeq comparer ie)\n\n    static member CreateV(ie : IEnumerable<_>) : MapExt<'Key,'Value> = \n        let comparer = LanguagePrimitives.FastGenericComparer<'Key> \n        new MapExt<_,_>(comparer,MapTree.ofSeqV comparer ie)\n    \n    static member Create() : MapExt<'Key,'Value> = empty\n\n    new(ie : seq<_>) = \n        let comparer = LanguagePrimitives.FastGenericComparer<'Key> \n        new MapExt<_,_>(comparer,MapTree.ofSeq comparer ie)\n\n    [<DebuggerBrowsable(DebuggerBrowsableState.Never)>]\n    member internal m.Comparer = comparer\n    //[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]\n    member internal m.Tree = tree\n    member m.Add(k,v) : MapExt<'Key,'Value> = \n        new MapExt<'Key,'Value>(comparer,MapTree.add comparer k v tree)\n\n    [<DebuggerBrowsable(DebuggerBrowsableState.Never)>]\n    member m.IsEmpty = MapTree.isEmpty tree\n    member m.Item \n        with get(k : 'Key) = MapTree.find comparer k tree\n\n\n    member x.Keys = \n        let mutable s = Set.empty\n        for (KeyValue(k,_)) in x do s <- s.Add k\n        s\n\n    member x.Values =\n        x |> Seq.map (fun (KeyValue(_,v)) -> v)\n\n    member x.TryAt i = MapTree.tryAt i tree\n    member x.TryAtV i = MapTree.tryAtV i tree\n    member x.Neighbours k = MapTree.neighbours comparer k tree\n    member x.NeighboursAt i = MapTree.neighboursi i tree\n    member x.NeighboursV k = MapTree.neighboursV comparer k tree\n    member x.NeighboursAtV i = MapTree.neighboursVi i tree\n    member x.TryGetIndex k = MapTree.tryGetIndex comparer k tree\n    member x.TryGetIndexV k = MapTree.tryGetIndexV comparer k tree\n\n    member m.TryPick(f) = MapTree.tryPick f tree \n    member m.TryPickBack(f) = MapTree.tryPickBack f tree \n    member m.Exists(f) = MapTree.exists f tree \n    member m.Filter(f)  : MapExt<'Key,'Value> = new MapExt<'Key,'Value>(comparer ,MapTree.filter comparer f tree)\n    member m.ForAll(f) = MapTree.forall f tree \n    member m.Fold f acc = MapTree.foldBack f tree acc\n\n    member m.FoldSection (lo:'Key) (hi:'Key) f (acc:'z) = MapTree.foldSection comparer lo hi f tree acc \n\n    member m.Iterate f = MapTree.iter f tree\n\n    member m.MapRange f  = new MapExt<'Key,'T2>(comparer,MapTree.map f tree)\n\n    member m.Map f  = new MapExt<'Key,'T2>(comparer,MapTree.mapi f tree)\n    \n    member m.MapMonotonic<'Key2, 'Value2 when 'Key2 : comparison> (f : 'Key -> 'Value -> 'Key2 * 'Value2) : MapExt<'Key2,'Value2> = new MapExt<'Key2,'Value2>(LanguagePrimitives.FastGenericComparer<'Key2>, MapTree.mapiMonotonic f tree)\n   \n    member m.ChooseMonotonic<'Key2, 'Value2 when 'Key2 : comparison> (f : 'Key -> 'Value -> option<'Key2 * 'Value2>) : MapExt<'Key2,'Value2> = \n        new MapExt<'Key2,'Value2>(LanguagePrimitives.FastGenericComparer<'Key2>, MapTree.chooseiMonotonic f tree)\n    \n    member internal x.GetReference key =\n        MapTree.getReference comparer 0 key tree\n        \n    member x.TryIndexOf key =\n        match MapTree.getReference comparer 0 key tree with\n            | Existing(i,_) -> Some i\n            | _ -> None\n\n    member x.TryRemoveMin() = \n        match MapTree.tryRemoveMin comparer tree with\n        | Some (k,v,t) -> Some(k,v, MapExt(comparer, t))\n        | None -> None\n\n    member x.TryRemoveMax() = \n        match MapTree.tryRemoveMax comparer tree with\n        | Some (k,v,t) -> Some(k,v, MapExt(comparer, t))\n        | None -> None\n        \n    member x.TryRemoveMinV() = \n        match MapTree.tryRemoveMinV comparer ValueNone tree with\n        | ValueSome (struct(k,v,n,t)) -> ValueSome(struct(k, v, n, MapExt(comparer, t)))\n        | ValueNone -> ValueNone\n\n    member x.TryRemoveMaxV() = \n        match MapTree.tryRemoveMaxV comparer ValueNone tree with\n        | ValueSome (struct(k,v,p,t)) -> ValueSome(struct(k, v, p, MapExt(comparer, t)))\n        | ValueNone -> ValueNone\n\n    member m.Map2(other:MapExt<'Key,'Value2>, f)  =\n        let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt f\n        let mapping k l r = f.Invoke(k, ValueOption.toOption l, ValueOption.toOption r)\n        new MapExt<'Key,'Result>(comparer, MapTree.map2V comparer mapping tree other.Tree)\n\n    member m.Map2V(other:MapExt<'Key,'Value2>, f)  =\n        new MapExt<'Key,'Result>(comparer, MapTree.map2V comparer f tree other.Tree)\n        \n    member m.Choose2(other:MapExt<'Key,'Value2>, f)  = \n        let inline v o = match o with | Some v -> ValueSome v | None -> ValueNone\n        let inline o o = match o with | ValueSome v -> Some v | ValueNone -> None\n\n        let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt f\n        let mapping k l r = f.Invoke(k, o l, o r) |> v\n        new MapExt<'Key,'Result>(comparer, MapTree.choose2V comparer mapping tree other.Tree)\n        \n    member m.Choose2V(other:MapExt<'Key,'Value2>, f)  = \n        new MapExt<'Key,'Result>(comparer, MapTree.choose2V comparer f tree other.Tree)\n        \n    member m.ComputeDelta(other:MapExt<'Key,'Value>, add, update, remove)  = \n        let add = OptimizedClosures.FSharpFunc<_,_,_>.Adapt add\n        let update = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt update\n        let remove = OptimizedClosures.FSharpFunc<_,_,_>.Adapt remove\n        new MapExt<'Key,_>(comparer, MapTree.computeDelta comparer add update remove tree other.Tree)\n        \n    member m.ApplyDelta(other:MapExt<'Key,'Delta>, apply)  = \n        let apply = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt apply\n        let onlyDelta = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(fun k d -> apply.Invoke(k, ValueNone, d))\n        let struct (s, d) = MapTree.applyDelta comparer apply onlyDelta tree other.Tree\n        new MapExt<'Key,_>(comparer, s), new MapExt<'Key,_>(comparer, d)\n\n    member m.Choose(f) =\n        new MapExt<'Key, 'Value2>(comparer, MapTree.choosei f tree)\n\n    member m.Alter(k, f) = new MapExt<'Key, 'Value>(comparer, MapTree.alter comparer k f tree)\n\n    member m.Partition(f)  : MapExt<'Key,'Value> * MapExt<'Key,'Value> = \n        let r1,r2 = MapTree.partition comparer f tree  in \n        new MapExt<'Key,'Value>(comparer,r1), new MapExt<'Key,'Value>(comparer,r2)\n\n    member m.Count = MapTree.size tree\n    \n    member x.TryMin = MapTree.tryMin tree\n    member x.TryMax = MapTree.tryMax tree\n\n    member x.TryMinKey = MapTree.tryMin tree |> Option.map fst\n    member x.TryMaxKey = MapTree.tryMax tree |> Option.map fst\n    \n    member x.TryMinKeyV = MapTree.tryMinV tree |> ValueOption.map (fun struct(k,_) -> k)\n    member x.TryMaxKeyV = MapTree.tryMaxV tree |> ValueOption.map (fun struct(k,_) -> k)\n    \n    member x.TryMinValue = MapTree.tryMin tree |> Option.map snd\n    member x.TryMaxValue = MapTree.tryMax tree |> Option.map snd\n    \n    member x.TryMinValueV = MapTree.tryMinV tree |> ValueOption.map (fun struct(_,v) -> v)\n    member x.TryMaxValueV = MapTree.tryMaxV tree |> ValueOption.map (fun struct(_,v) -> v)\n\n    member x.Range(min, max) =\n        MapExt<'Key, 'Value>(comparer, MapTree.range comparer min max tree)\n\n    member x.Split (k) =\n        let l, self, r = MapTree.split comparer k tree\n        MapExt<'Key, 'Value>(comparer, l), self, MapExt<'Key, 'Value>(comparer, r)\n        \n    member x.SplitV (k) =\n        let struct(l, lmax, self, rmin, r) = MapTree.splitV comparer k tree\n        struct(MapExt<'Key, 'Value>(comparer, l), lmax, self, rmin, MapExt<'Key, 'Value>(comparer, r))\n        \n    member x.UnionWith (other : MapExt<_,_>, resolve) =\n        if x.IsEmpty then other\n        elif other.IsEmpty then x\n        else new MapExt<'Key, 'Value>(comparer, MapTree.unionWith comparer resolve tree other.Tree)\n        \n    member x.Union(other : MapExt<_,_>) =\n        new MapExt<'Key, 'Value>(comparer, MapTree.union comparer tree other.Tree)\n\n    member x.IntersectWith(other : MapExt<_,_>, resolve) =\n        if x.IsEmpty || other.IsEmpty then MapExt<_,_>.Empty\n        else new MapExt<'Key, _>(comparer, MapTree.intersectWith resolve comparer tree other.Tree)\n        \n    member x.Intersect(other : MapExt<_,_>) =\n        if x.IsEmpty || other.IsEmpty then MapExt<_,_>.Empty\n        else new MapExt<'Key, _>(comparer, MapTree.intersectWith (fun l r -> (l,r)) comparer tree other.Tree)\n\n    member x.Validate() =\n        MapTree.validate comparer tree\n\n\n    member m.ContainsKey(k) = \n        MapTree.mem comparer k tree\n\n\n    member m.Remove(k)  : MapExt<'Key,'Value> = \n        new MapExt<'Key,'Value>(comparer,MapTree.remove comparer k tree)\n        \n    member m.TryRemove(k) : option<'Value * MapExt<'Key,'Value>> = \n        match MapTree.tryRemove comparer k tree with\n        | Some (v, t) -> \n            Some(v, new MapExt<'Key,'Value>(comparer, t))\n        | None ->\n            None\n            \n    member m.TryRemoveV(k) : voption<struct('Value * MapExt<'Key,'Value>)> = \n        match MapTree.tryRemoveV comparer k tree with\n        | ValueSome struct (v, t) -> \n            ValueSome(struct(v, new MapExt<'Key,'Value>(comparer, t)))\n        | ValueNone ->\n            ValueNone\n\n    member m.TryFind(k) = \n        MapTree.tryFind comparer k tree\n        \n    member m.TryFindV(k) = \n        MapTree.tryFindV comparer k tree\n\n    member m.ToList() = MapTree.toList tree\n\n    member m.ToArray() = MapTree.toArray tree\n\n    member x.ToListV() = MapTree.toListV tree\n    member x.ToArrayV() = MapTree.toArrayV tree\n    \n    member x.ToValueList() = MapTree.valueList tree\n    member x.ToValueArray() = MapTree.valueArray tree\n\n    static member ofList(l) : MapExt<'Key,'Value> = \n        let comparer = LanguagePrimitives.FastGenericComparer<'Key> \n        new MapExt<_,_>(comparer,MapTree.ofList comparer l)\n\n    static member ofListV(l) : MapExt<'Key,'Value> = \n        let comparer = LanguagePrimitives.FastGenericComparer<'Key> \n        new MapExt<_,_>(comparer,MapTree.ofListV comparer l)\n           \n    member this.ComputeHashCode() = \n        let combineHash x y = (x <<< 1) + y + 631 \n        let mutable res = 0\n        for (KeyValue(x,y)) in this do\n            res <- combineHash res (hash x)\n            res <- combineHash res (Unchecked.hash y)\n        abs res\n\n    override this.Equals(that) = \n        if System.Object.ReferenceEquals(this, that) then\n            true\n        else\n            match that with \n            | :? MapExt<'Key,'Value> as that -> \n                use e1 = (this :> seq<_>).GetEnumerator() \n                use e2 = (that :> seq<_>).GetEnumerator() \n                let rec loop () = \n                    let m1 = e1.MoveNext() \n                    let m2 = e2.MoveNext()\n                    (m1 = m2) && (not m1 || let e1c, e2c = e1.Current, e2.Current in ((e1c.Key = e2c.Key) && (Unchecked.equals e1c.Value e2c.Value) && loop()))\n                loop()\n            | _ -> false\n\n    override this.GetHashCode() = this.ComputeHashCode()\n\n    member x.GetForwardEnumerator() = new MapTree.MapTreeEnumerator<'Key, 'Value>(tree) :> IEnumerator<_> \n    member x.GetBackwardEnumerator() = new MapTree.MapTreeBackwardEnumerator<'Key, 'Value>(tree) :> IEnumerator<_> \n    \n    member x.GetForwardEnumeratorV() = new MapTree.ValueMapTreeEnumerator<'Key, 'Value>(tree) :> IEnumerator<_> \n    member x.GetBackwardEnumeratorV() = new MapTree.ValueMapTreeBackwardEnumerator<'Key, 'Value>(tree) :> IEnumerator<_> \n\n    interface IEnumerable<KeyValuePair<'Key, 'Value>> with\n        member __.GetEnumerator() = MapTree.mkIEnumerator tree\n\n    interface System.Collections.IEnumerable with\n        member __.GetEnumerator() = (MapTree.mkIEnumerator tree :> System.Collections.IEnumerator)\n\n    interface IDictionary<'Key, 'Value> with\n        member m.Item\n            with get x = m.[x]\n            and set _ _ = raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n        member m.Keys = KeyCollection(m) :> ICollection<'Key>\n        member m.Values = ValueCollection(m) :> ICollection<'Value>\n        member m.Add(_, _) = raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n        member m.ContainsKey k = m.ContainsKey k\n        member m.TryGetValue(k, r) = match m.TryFindV(k) with ValueSome v -> r <- v; true | _ -> false\n        member m.Remove(_) = raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n\n    interface ICollection<KeyValuePair<'Key, 'Value>> with\n        member _.Add(_) = raise (NotSupportedException(\"MapExt cannot be mutated.\"));\n        member _.Clear() = raise (NotSupportedException(\"MapExt cannot be mutated.\"));\n        member _.Remove(_) = raise (NotSupportedException(\"MapExt cannot be mutated.\"));\n        member s.Contains(x) = s.ContainsKey(x.Key) && DefaultEquality.equals s.[x.Key] x.Value\n        member _.CopyTo(arr,i) = MapTree.copyToArray tree arr i\n        member s.IsReadOnly = true\n        member s.Count = s.Count\n\n    interface IReadOnlyCollection<KeyValuePair<'Key, 'Value>> with\n        member m.Count = m.Count\n\n    interface IReadOnlyDictionary<'Key, 'Value> with\n        member m.Item with get key = m.[key]\n        member m.Keys = KeyCollection(m) :> IEnumerable<'Key>\n        member m.TryGetValue(key, value: byref<'Value>) = match m.TryFindV(key) with ValueSome r -> value <- r; true | _ -> false\n        member m.Values = ValueCollection(m) :> IEnumerable<'Value>\n        member m.ContainsKey key = m.ContainsKey key\n\n    interface System.IComparable with \n        member m.CompareTo(obj: obj) = \n            match obj with \n            | :? MapExt<'Key,'Value>  as m2->\n                Seq.compareWith \n                    (fun (kvp1 : KeyValuePair<_,_>) (kvp2 : KeyValuePair<_,_>)-> \n                        let c = comparer.Compare(kvp1.Key,kvp2.Key) in \n                        if c <> 0 then c else Unchecked.compare kvp1.Value kvp2.Value)\n                    m m2 \n            | _ -> \n                invalidArg \"obj\" (\"SR.GetString(SR.notComparable)\")\n    override x.ToString() = \n        let suffix = if x.Count > 4 then \"; ...\" else \"\"\n        let content = Seq.truncate 4 x |> Seq.map (fun (KeyValue t) -> sprintf \"%A\" t) |> String.concat \"; \"\n        \"map [\" + content + suffix + \"]\"\n\n    member private x.AsString = x.ToString()\n\nand \n    [<Sealed>]\n    internal MapDebugView<'Key,'Value when 'Key : comparison>(v: MapExt<'Key,'Value>)  =  \n\n        [<DebuggerBrowsable(DebuggerBrowsableState.RootHidden)>]\n        member x.Items = v |> Seq.truncate 10000 |> Seq.toArray\n\nand\n    internal KeyCollection<'Key,'Value when 'Key : comparison>(parent: MapExt<'Key,'Value>) =\n        interface ICollection<'Key> with\n            member _.Add(_) =\n                raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n\n            member _.Clear() =\n                raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n\n            member _.Remove(_) =\n                raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n\n            member _.Contains x =\n                parent.ContainsKey x\n\n            member _.CopyTo(arr, index) =\n                if isNull arr then\n                    nullArg \"arr\"\n\n                if index < 0 then\n                    invalidArg \"index\" \"index must be positive\"\n\n                if index + parent.Count > arr.Length then\n                    invalidArg \"index\" \"array is smaller than index plus the number of items to copy\"\n\n                let mutable i = index\n\n                for item in parent do\n                    arr.[i] <- item.Key\n                    i <- i + 1\n\n            member _.IsReadOnly = true\n\n            member _.Count = parent.Count\n\n        interface IEnumerable<'Key> with\n            member _.GetEnumerator() =\n                (seq {\n                    for item in parent do\n                        item.Key\n                })\n                    .GetEnumerator()\n\n        interface IEnumerable with\n            member _.GetEnumerator() =\n                (seq {\n                    for item in parent do\n                        item.Key\n                })\n                    .GetEnumerator()\n                :> IEnumerator\n\nand\n    internal ValueCollection<'Key, 'Value when 'Key: comparison>(parent: MapExt<'Key, 'Value>) =\n        interface ICollection<'Value> with\n            member _.Add(_) =\n                raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n\n            member _.Clear() =\n                raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n\n            member _.Remove(_) =\n                raise (NotSupportedException(\"MapExt cannot be mutated.\"))\n\n            member _.Contains x =\n                parent.Exists(fun _ value -> Unchecked.equals value x)\n\n            member _.CopyTo(arr, index) =\n                if isNull arr then\n                    nullArg \"arr\"\n\n                if index < 0 then\n                    invalidArg \"index\" \"index must be positive\"\n\n                if index + parent.Count > arr.Length then\n                    invalidArg \"index\" \"array is smaller than index plus the number of items to copy\"\n\n                let mutable i = index\n\n                for item in parent do\n                    arr.[i] <- item.Value\n                    i <- i + 1\n\n            member _.IsReadOnly = true\n\n            member _.Count = parent.Count\n\n        interface IEnumerable<'Value> with\n            member _.GetEnumerator() =\n                (seq {\n                    for item in parent do\n                        item.Value\n                })\n                    .GetEnumerator()\n\n        interface IEnumerable with\n            member _.GetEnumerator() =\n                (seq {\n                    for item in parent do\n                        item.Value\n                })\n                    .GetEnumerator()\n                :> IEnumerator\n\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n[<RequireQualifiedAccess>]\nmodule MapExt = \n\n    [<CompiledName(\"IsEmpty\")>]\n    let isEmpty (m:MapExt<_,_>) = m.IsEmpty\n    \n    [<CompiledName(\"Keys\")>]\n    let keys (m:MapExt<_,_>) = m.Keys\n    \n    [<CompiledName(\"Values\")>]\n    let values (m:MapExt<_,_>) = m.Values\n\n    [<CompiledName(\"Add\")>]\n    let add k v (m:MapExt<_,_>) = m.Add(k,v)\n\n    [<CompiledName(\"Find\")>]\n    let find k (m:MapExt<_,_>) = m.[k]\n\n    [<CompiledName(\"TryFind\")>]\n    let tryFind k (m:MapExt<_,_>) = m.TryFind(k)\n    \n    [<CompiledName(\"TryFindV\")>]\n    let tryFindV k (m:MapExt<_,_>) = m.TryFindV(k)\n\n    [<CompiledName(\"Remove\")>]\n    let remove k (m:MapExt<_,_>) = m.Remove(k)\n    \n    [<CompiledName(\"TryRemove\")>]\n    let tryRemove k (m:MapExt<_,_>) = m.TryRemove(k)\n    \n    [<CompiledName(\"TryRemoveValue\")>]\n    let tryRemoveV k (m:MapExt<_,_>) = m.TryRemoveV(k)\n    \n    [<CompiledName(\"TryRemoveMin\")>]\n    let tryRemoveMin (m:MapExt<_,_>) = m.TryRemoveMin()\n\n    [<CompiledName(\"TryRemoveMax\")>]\n    let tryRemoveMax (m:MapExt<_,_>) = m.TryRemoveMax()\n    \n    [<CompiledName(\"TryRemoveMinValue\")>]\n    let tryRemoveMinV (m:MapExt<_,_>) = m.TryRemoveMinV()\n\n    [<CompiledName(\"TryRemoveMaxValue\")>]\n    let tryRemoveMaxV (m:MapExt<_,_>) = m.TryRemoveMaxV()\n\n    [<CompiledName(\"ContainsKey\")>]\n    let containsKey k (m:MapExt<_,_>) = m.ContainsKey(k)\n\n    [<CompiledName(\"Iterate\")>]\n    let iter f (m:MapExt<_,_>) = m.Iterate(f)\n\n    [<CompiledName(\"TryPick\")>]\n    let tryPick f (m:MapExt<_,_>) = m.TryPick(f)\n\n    [<CompiledName(\"TryPickBack\")>]\n    let tryPickBack f (m:MapExt<_,_>) = m.TryPickBack(f)\n\n    [<CompiledName(\"Pick\")>]\n    let pick f (m:MapExt<_,_>) = match tryPick f m with None -> raise (KeyNotFoundException()) | Some res -> res\n\n    [<CompiledName(\"Exists\")>]\n    let exists f (m:MapExt<_,_>) = m.Exists(f)\n\n    [<CompiledName(\"Filter\")>]\n    let filter f (m:MapExt<_,_>) = m.Filter(f)\n\n    [<CompiledName(\"Partition\")>]\n    let partition f (m:MapExt<_,_>) = m.Partition(f)\n\n    [<CompiledName(\"ForAll\")>]\n    let forall f (m:MapExt<_,_>) = m.ForAll(f)\n    \n    [<CompiledName(\"MapRange\")>]\n    let mapRange f (m:MapExt<_,_>) = m.MapRange(f)\n\n    [<CompiledName(\"Map\")>]\n    let map f (m:MapExt<_,_>) = m.Map(f)\n\n    [<CompiledName(\"Fold\")>]\n    let fold<'Key,'T,'State when 'Key : comparison> f (z:'State) (m:MapExt<'Key,'T>) = MapTree.fold f z m.Tree\n\n    [<CompiledName(\"FoldBack\")>]\n    let foldBack<'Key,'T,'State  when 'Key : comparison> f (m:MapExt<'Key,'T>) (z:'State) =  MapTree.foldBack  f m.Tree z\n        \n    [<CompiledName(\"ToSeq\")>]\n    let toSeq (m:MapExt<_,_>) = m |> Seq.map (fun kvp -> kvp.Key, kvp.Value)\n    \n    [<CompiledName(\"ToSeqV\")>]\n    let toSeqV (m:MapExt<_,_>) = m |> Seq.map (fun kvp -> struct(kvp.Key, kvp.Value))\n    \n    [<CompiledName(\"ToValueSeq\")>]\n    let toValueSeq (m:MapExt<_,_>) = m |> Seq.map (fun kvp -> kvp.Value)\n    \n    [<CompiledName(\"ToSeqBack\")>]\n    let toSeqBack (m : MapExt<_,_>) = new EnumeratorEnumerable<_>(m.GetBackwardEnumerator) :> seq<_> \n    \n    [<CompiledName(\"ToSeqBackV\")>]\n    let toSeqBackV (m : MapExt<_,_>) = new EnumeratorEnumerable<_>(m.GetBackwardEnumeratorV) :> seq<_> \n\n    [<CompiledName(\"FindKey\")>]\n    let findKey f (m : MapExt<_,_>) = m |> toSeq |> Seq.pick (fun (k,v) -> if f k v then Some(k) else None)\n\n    [<CompiledName(\"TryFindKey\")>]\n    let tryFindKey f (m : MapExt<_,_>) = m |> toSeq |> Seq.tryPick (fun (k,v) -> if f k v then Some(k) else None)\n\n    [<CompiledName(\"OfList\")>]\n    let ofList (l: ('Key * 'Value) list) = MapExt<_,_>.ofList(l)\n\n    [<CompiledName(\"OfListV\")>]\n    let ofListV (l: (struct ('Key * 'Value)) list) = MapExt<_,_>.ofListV(l)\n\n    [<CompiledName(\"OfSeq\")>]\n    let ofSeq l = MapExt<_,_>.Create(l)\n\n    [<CompiledName(\"OfSeqV\")>]\n    let ofSeqV l = MapExt<_,_>.CreateV(l)\n\n    [<CompiledName(\"Singleton\")>]\n    let singleton k v = MapExt<_,_>(LanguagePrimitives.FastGenericComparer<_>,MapOne(k,v))\n\n    [<CompiledName(\"OfArray\")>]\n    let ofArray (array: ('Key * 'Value) array) = \n        let comparer = LanguagePrimitives.FastGenericComparer<'Key> \n        new MapExt<_,_>(comparer,MapTree.ofArray comparer array)\n\n    [<CompiledName(\"OfArrayV\")>]\n    let ofArrayV (array: (struct ('Key * 'Value)) array) = \n        let comparer = LanguagePrimitives.FastGenericComparer<'Key> \n        new MapExt<_,_>(comparer,MapTree.ofArrayV comparer array)\n\n    [<CompiledName(\"ToList\")>]\n    let toList (m:MapExt<_,_>) = m.ToList()\n\n    [<CompiledName(\"ToArray\")>]\n    let toArray (m:MapExt<_,_>) = m.ToArray()\n    \n    [<CompiledName(\"ToListV\")>]\n    let toListV (m:MapExt<_,_>) = m.ToListV()\n\n    [<CompiledName(\"ToArrayV\")>]\n    let toArrayV (m:MapExt<_,_>) = m.ToArrayV()\n    \n    [<CompiledName(\"ToValueList\")>]\n    let toValueList (m:MapExt<_,_>) = m.ToValueList()\n\n    [<CompiledName(\"ToValueArray\")>]\n    let toValueArray (m:MapExt<_,_>) = m.ToValueArray()\n\n    [<CompiledName(\"Empty\")>]\n    let empty<'Key,'Value  when 'Key : comparison> = MapExt<'Key,'Value>.Empty\n\n    [<CompiledName(\"Count\")>]\n    let count (m:MapExt<_,_>) = m.Count\n    \n    [<CompiledName(\"TryMin\")>]\n    let tryMin (m:MapExt<_,_>) = m.TryMinKey\n\n    [<CompiledName(\"TryMinV\")>]\n    let tryMinV (m:MapExt<_,_>) = m.TryMinKeyV\n    \n    [<CompiledName(\"Min\")>]\n    let min (m:MapExt<_,_>) = \n        match m.TryMinKey with\n            | Some min -> min\n            | None -> raise <| ArgumentException(\"The input sequence was empty.\")\n\n    [<CompiledName(\"TryMax\")>]\n    let tryMax (m:MapExt<_,_>) = m.TryMaxKey\n\n    [<CompiledName(\"TryMaxV\")>]\n    let tryMaxV (m:MapExt<_,_>) = m.TryMaxKeyV\n\n    [<CompiledName(\"Max\")>]\n    let max (m:MapExt<_,_>) = \n        match m.TryMaxKey with\n        | Some min -> min\n        | None -> raise <| ArgumentException(\"The input sequence was empty.\")\n\n    \n    [<CompiledName(\"TryItem\")>]\n    let tryItem i (m:MapExt<_,_>) = m.TryAt i\n    \n    [<CompiledName(\"TryItemV\")>]\n    let tryItemV i (m:MapExt<_,_>) = m.TryAtV i\n\n    [<CompiledName(\"Item\")>]\n    let item i (m:MapExt<_,_>) = \n        match m.TryAt i with\n            | Some t -> t\n            | None -> raise <| IndexOutOfRangeException()\n\n    [<CompiledName(\"Alter\")>]\n    let alter k f (m:MapExt<_,_>) = m.Alter(k, f)\n    \n    [<CompiledName(\"MapMonotonic\")>]\n    let mapMonotonic f (m:MapExt<_,_>) = m.MapMonotonic(f)\n    \n    [<CompiledName(\"ChooseMonotonic\")>]\n    let chooseMonotonic f (m:MapExt<_,_>) = m.ChooseMonotonic(f)\n\n    [<CompiledName(\"Range\")>]\n    let range min max (m:MapExt<_,_>) = m.Range(min, max)\n\n    [<CompiledName(\"Split\")>]\n    let split k (m:MapExt<_,_>) = m.Split k\n\n    [<CompiledName(\"SplitV\")>]\n    let splitV k (m:MapExt<_,_>) = m.SplitV k\n\n    [<CompiledName(\"TryIndexOf\")>]\n    let tryIndexOf i (m:MapExt<_,_>) = m.TryIndexOf i\n\n    [<CompiledName(\"GetReference\")>]\n    let internal reference i (m:MapExt<_,_>) = m.GetReference i\n\n\n    [<CompiledName(\"Union\")>]\n    let union (l:MapExt<_,_>) r = l.Union r\n\n    [<CompiledName(\"UnionWith\")>]\n    let unionWith f (l:MapExt<_,_>) r = l.UnionWith (r, f)\n    \n    [<CompiledName(\"IntersectWith\")>]\n    let intersectWith f (l:MapExt<_,_>) r = l.IntersectWith (r, f)\n    \n    [<CompiledName(\"Intersect\")>]\n    let intersect (l:MapExt<_,_>) r = l.Intersect r\n\n    [<CompiledName(\"Map2\")>]\n    let map2 f (l:MapExt<_,_>) r = l.Map2 (r, f)\n\n    [<CompiledName(\"Map2Value\")>]\n    let map2V f (l:MapExt<_,_>) r = l.Map2V (r, f)\n\n    [<CompiledName(\"Choose\")>]\n    let choose f (l:MapExt<_,_>) = l.Choose (f)\n    \n    [<CompiledName(\"Choose2\")>]\n    let choose2 f (l:MapExt<_,_>) r = l.Choose2 (r, f)\n    \n    [<CompiledName(\"Choose2Value\")>]\n    let choose2V f (l:MapExt<_,_>) r = l.Choose2V (r, f)\n    \n    [<CompiledName(\"Neighbours\")>]\n    let neighbours k (m:MapExt<_,_>) = m.Neighbours k\n    \n    [<CompiledName(\"NeighboursAt\")>]\n    let neighboursAt i (m:MapExt<_,_>) = m.NeighboursAt i\n    \n    [<CompiledName(\"NeighboursV\")>]\n    let neighboursV k (m:MapExt<_,_>) = m.NeighboursV k\n    \n    [<CompiledName(\"NeighboursAtV\")>]\n    let neighboursAtV i (m:MapExt<_,_>) = m.NeighboursAtV i\n\n    [<CompiledName(\"TryGetIndex\")>]\n    let tryGetIndex k (m:MapExt<_,_>) = m.TryGetIndex k\n    \n    [<CompiledName(\"TryGetIndexV\")>]\n    let tryGetIndexV k (m:MapExt<_,_>) = m.TryGetIndexV k"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_auto.fs",
    "content": "namespace Aardvark.Base\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base\n\ntype internal HalfRangeKind =\n    | Left = 0\n    | Right = 1\n\nmodule private RangeSetUtils =\n\n    let inline inc (value : 'T) =\n        let res = value + LanguagePrimitives.GenericOne<'T>\n        if res = Constant<'T>.ParseableMinValue then struct (Constant<'T>.ParseableMaxValue, true)\n        else struct (res, false)\n\n    module MapExt =\n        let inline splitAt (key : 'K) (map : MapExt<'K, 'V>) =\n            let struct (l, _, _, _, r) = MapExt.splitV key map\n            struct (l, r)\n\n        let inline tryMinValue (map : MapExt<'K, 'V>) =\n            MapExt.tryMinV map |> ValueOption.map (fun mk -> map.[mk])\n\n        let inline tryMaxValue (map : MapExt<'K, 'V>) =\n            MapExt.tryMaxV map |> ValueOption.map (fun mk -> map.[mk])\n\n        let inline maxValue (map : MapExt<'K, 'V>) =\n            map.[MapExt.max map]\n\nopen RangeSetUtils\n\n/// Set of ranges where overlapping and neighboring ranges are coalesced.\n/// Note that ranges describe closed intervals.\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype RangeSet1i internal (store : MapExt<int32, HalfRangeKind>) =\n    static let empty = RangeSet1i(MapExt.empty)\n\n    /// Empty range set.\n    static member Empty = empty\n\n    member inline private x.Store = store\n\n    // We cannot directly describe a range that ends at Int32.MaxValue since the right half-range is inserted\n    // at max + 1. In that case the right-half range will be missing and the total count is odd.\n    member inline private x.HasMaxValue = store.Count % 2 = 1\n\n    /// Returns the minimum value in the range set or Int32.MaxValue if the range is empty.\n    member x.Min =\n        match store.TryMinKeyV with\n        | ValueSome min -> min\n        | _ -> Int32.MaxValue\n\n    /// Returns the maximum value in the range set or Int32.MinValue if the range is empty.\n    member x.Max =\n        if x.HasMaxValue then Int32.MaxValue\n        else\n            match store.TryMaxKeyV with\n            | ValueSome max -> max - 1\n            | _ -> Int32.MinValue\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    member inline x.Range =\n        Range1i(x.Min, x.Max)\n\n    /// Adds the given range to the set.\n    member x.Add(r : Range1i) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained Int32.MaxValue or we have overflown, we must not add an explicit right half-range.\n            // Int32.MaxValue is stored implicitly.\n            let fixRightBoundary =\n                if x.HasMaxValue || overflow then\n                    id\n                else\n                    MapExt.add max HalfRangeKind.Right\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.ofListV [\n                        struct (min, HalfRangeKind.Left)\n                    ]\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> MapExt.add max HalfRangeKind.Right\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    MapExt.union lm rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1i(newStore)\n\n    /// Removes the given range from the set.\n    member x.Remove(r : Range1i) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained Int32.MaxValue and we have not overflown, there is still a range [max, Int32.MaxValue]\n            let fixRightBoundary =\n                if x.HasMaxValue && not overflow then\n                    MapExt.add max HalfRangeKind.Left\n                else\n                    id\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.empty\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Right\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add max HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    MapExt.union lm rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1i(newStore)\n\n    /// Returns the union of the set with the given set.\n    member inline x.Union(other : RangeSet1i) =\n        let mutable res = x\n        for r in other do\n            res <- res.Add r\n        res\n\n    /// Returns the intersection of the set with the given range.\n    member x.Intersect(r : Range1i) =\n        if r.Max < r.Min then\n            empty\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let inner =\n                store\n                |> MapExt.splitAt min |> sndv\n                |> if not overflow then MapExt.splitAt max >> fstv else id\n\n            let newStore =\n                inner\n                |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id\n                |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1i(newStore)\n\n    member private x.TryFindLeftBoundary(v : int32) =\n        let struct (l, s, _) = MapExt.neighboursV v store\n        match s with\n        | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone\n        | _ ->\n            match l with\n            | ValueSome (i, HalfRangeKind.Left) -> ValueSome i\n            | _ -> ValueNone\n\n    /// Returns whether the given value is contained in the range set.\n    member x.Contains(v : int32) =\n        x.TryFindLeftBoundary v |> ValueOption.isSome\n\n    /// Returns whether the given range is contained in the set.\n    member x.Contains(r : Range1i) =\n        if r.Max < r.Min then false\n        elif r.Min = r.Max then x.Contains r.Min\n        else\n            match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with\n            | ValueSome l, ValueSome r -> l = r\n            | _ -> false\n\n    /// Returns the number of disjoint ranges in the set.\n    member x.Count =\n        (store.Count + 1) / 2\n\n    /// Returns whether the set is empty.\n    member inline x.IsEmpty =\n        x.Count = 0\n\n    /// Builds an array from the range set.\n    member x.ToArray() =\n        let arr = Array.zeroCreate x.Count\n\n        let rec write (i : int) (l : struct (int32 * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                arr.[i] <- Range1i(l, r - 1)\n                write (i + 1) rest\n\n            | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->\n                arr.[i] <- Range1i(l, Int32.MaxValue)\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> ()\n\n        store |> MapExt.toListV |> write 0\n        arr\n\n    /// Builds a list from the range set.\n    member x.ToList() =\n        let rec build (accum : Range1i list) (l : struct (int32 * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                build (Range1i(l, r - 1) :: accum) rest\n\n            | [struct (l, HalfRangeKind.Left)] ->\n                build (Range1i(l, Int32.MaxValue) :: accum) []\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> List.rev accum\n\n        store |> MapExt.toListV |> build []\n\n    /// Views the range set as a sequence.\n    member x.ToSeq() =\n        x :> seq<_>\n\n    member inline private x.Equals(other : RangeSet1i) =\n        store = other.Store\n\n    override x.Equals(other : obj) =\n        match other with\n        | :? RangeSet1i as o -> x.Equals o\n        | _ -> false\n\n    override x.GetHashCode() =\n        store.GetHashCode()\n\n    member private x.AsString = x.ToString()\n\n    override x.ToString() =\n        let content =\n            x |> Seq.map (fun r ->\n                $\"[{r.Min}, {r.Max}]\"\n            )\n            |> String.concat \"; \"\n\n        $\"ranges [{content}]\"\n\n    member x.GetEnumerator() =\n        new RangeSetEnumerator1i((store :> seq<_>).GetEnumerator())\n\n    interface IEquatable<RangeSet1i> with\n        member x.Equals(other) = x.Equals(other)\n\n    interface IEnumerable with\n        member x.GetEnumerator() = new RangeSetEnumerator1i((store :> seq<_>).GetEnumerator()) :> _\n\n    interface IEnumerable<Range1i> with\n        member x.GetEnumerator() = new RangeSetEnumerator1i((store :> seq<_>).GetEnumerator()) :> _\n\n// TODO: MapExt should use a struct enumerator and return it directly.\n// That way we could get rid of allocations.\nand RangeSetEnumerator1i =\n    struct\n        val private Inner : IEnumerator<KeyValuePair<int32, HalfRangeKind>>\n        val mutable private Left : KeyValuePair<int32, HalfRangeKind>\n        val mutable private Right : KeyValuePair<int32, HalfRangeKind>\n\n        internal new (inner : IEnumerator<KeyValuePair<int32, HalfRangeKind>>) =\n            { Inner = inner\n              Left = Unchecked.defaultof<_>\n              Right = Unchecked.defaultof<_> }\n\n        member x.MoveNext() =\n            if x.Inner.MoveNext() then\n                x.Left <- x.Inner.Current\n                if x.Inner.MoveNext() then\n                    x.Right <- x.Inner.Current\n                    true\n                else\n                    if x.Left.Value = HalfRangeKind.Left then\n                        x.Right <- KeyValuePair(Int32.MinValue, HalfRangeKind.Right) // MaxValue + 1\n                        true\n                    else\n                        failwithf \"bad RangeSet\"\n            else\n                false\n\n        member x.Reset() =\n            x.Inner.Reset()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        member x.Current =\n            assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)\n            Range1i(x.Left.Key, x.Right.Key - 1)\n\n        member x.Dispose() =\n            x.Inner.Dispose()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        interface IEnumerator with\n            member x.MoveNext() = x.MoveNext()\n            member x.Current = x.Current :> obj\n            member x.Reset() = x.Reset()\n\n        interface IEnumerator<Range1i> with\n            member x.Dispose() = x.Dispose()\n            member x.Current = x.Current\n    end\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule RangeSet1i =\n\n    /// Empty range set.\n    let empty = RangeSet1i.Empty\n\n    /// Returns the minimum value in the range set or Int32.MaxValue if the range is empty.\n    let inline min (set : RangeSet1i) = set.Min\n\n    /// Returns the maximum value in the range set or Int32.MinValue if the range is empty.\n    let inline max (set : RangeSet1i) = set.Max\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    let inline range (set : RangeSet1i) = set.Range\n\n    let inline private getHalfRanges (r : Range1i) =\n        [ struct (r.Min, HalfRangeKind.Left)\n          if r.Max < Int32.MaxValue then struct (r.Max + 1, HalfRangeKind.Right) ]\n\n    let inline private ofRange (r : Range1i) =\n        RangeSet1i(MapExt.ofListV <| getHalfRanges r)\n\n    let private ofRanges (ranges : seq<Range1i>) =\n        let halves =\n            ranges\n            |> Seq.toList\n            |> List.collect getHalfRanges\n            |> List.sortBy fstv\n\n        let mutable level = 0\n        let result = ResizeArray()\n\n        for (struct (i, k) as h) in halves do\n            if k = HalfRangeKind.Left then\n                if level = 0 then result.Add h\n                level <- level + 1\n            else\n                level <- level - 1\n                if level = 0 then result.Add h\n\n        RangeSet1i(MapExt.ofSeqV result)\n\n    /// Builds a range set of the given list of ranges.\n    let ofList (ranges : Range1i list) =\n        match ranges with\n        | [] -> empty\n        | [r] -> ofRange r\n        | _ -> ofRanges ranges\n\n    /// Builds a range set of the given array of ranges.\n    let ofArray (ranges : Range1i[]) =\n        if ranges.Length = 0 then empty\n        elif ranges.Length = 1 then ofRange ranges.[0]\n        else ofRanges ranges\n\n    /// Builds a range set of the given sequence of ranges.\n    let inline ofSeq (ranges : seq<Range1i>) =\n        ofList <| Seq.toList ranges\n\n    /// Adds the given range to the set.\n    let inline add (range : Range1i) (set : RangeSet1i) = set.Add range\n\n    /// Removes the given range from the set.\n    let inline remove (range : Range1i) (set : RangeSet1i) = set.Remove range\n\n    /// Returns the union of two sets.\n    let inline union (l : RangeSet1i) (r : RangeSet1i) = l.Union r\n\n    /// Returns the intersection of the set with the given range.\n    let inline intersect (range : Range1i) (set : RangeSet1i) = set.Intersect range\n\n    /// Returns whether the given value is contained in the range set.\n    let inline contains (value : int32) (set : RangeSet1i) = set.Contains value\n\n    /// Returns whether the given range is contained in the set.\n    let inline containsRange (range : Range1i) (set : RangeSet1i) = set.Contains range\n\n    /// Returns the number of disjoint ranges in the set.\n    let inline count (set : RangeSet1i) = set.Count\n\n    /// Returns whether the set is empty.\n    let inline isEmpty (set : RangeSet1i) = set.IsEmpty\n\n    /// Views the range set as a sequence.\n    let inline toSeq (set : RangeSet1i) = set :> seq<_>\n\n    /// Builds a list from the range set.\n    let inline toList (set : RangeSet1i) = set.ToList()\n\n    /// Builds an array from the range set.\n    let inline toArray (set : RangeSet1i) = set.ToArray()\n\n\n/// Set of ranges where overlapping and neighboring ranges are coalesced.\n/// Note that ranges describe closed intervals.\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype RangeSet1ui internal (store : MapExt<uint32, HalfRangeKind>) =\n    static let empty = RangeSet1ui(MapExt.empty)\n\n    /// Empty range set.\n    static member Empty = empty\n\n    member inline private x.Store = store\n\n    // We cannot directly describe a range that ends at UInt32.MaxValue since the right half-range is inserted\n    // at max + 1. In that case the right-half range will be missing and the total count is odd.\n    member inline private x.HasMaxValue = store.Count % 2 = 1\n\n    /// Returns the minimum value in the range set or UInt32.MaxValue if the range is empty.\n    member x.Min =\n        match store.TryMinKeyV with\n        | ValueSome min -> min\n        | _ -> UInt32.MaxValue\n\n    /// Returns the maximum value in the range set or UInt32.MinValue if the range is empty.\n    member x.Max =\n        if x.HasMaxValue then UInt32.MaxValue\n        else\n            match store.TryMaxKeyV with\n            | ValueSome max -> max - 1u\n            | _ -> UInt32.MinValue\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    member inline x.Range =\n        Range1ui(x.Min, x.Max)\n\n    /// Adds the given range to the set.\n    member x.Add(r : Range1ui) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained UInt32.MaxValue or we have overflown, we must not add an explicit right half-range.\n            // UInt32.MaxValue is stored implicitly.\n            let fixRightBoundary =\n                if x.HasMaxValue || overflow then\n                    id\n                else\n                    MapExt.add max HalfRangeKind.Right\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.ofListV [\n                        struct (min, HalfRangeKind.Left)\n                    ]\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> MapExt.add max HalfRangeKind.Right\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    MapExt.union lm rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1ui(newStore)\n\n    /// Removes the given range from the set.\n    member x.Remove(r : Range1ui) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained UInt32.MaxValue and we have not overflown, there is still a range [max, UInt32.MaxValue]\n            let fixRightBoundary =\n                if x.HasMaxValue && not overflow then\n                    MapExt.add max HalfRangeKind.Left\n                else\n                    id\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.empty\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Right\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add max HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    MapExt.union lm rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1ui(newStore)\n\n    /// Returns the union of the set with the given set.\n    member inline x.Union(other : RangeSet1ui) =\n        let mutable res = x\n        for r in other do\n            res <- res.Add r\n        res\n\n    /// Returns the intersection of the set with the given range.\n    member x.Intersect(r : Range1ui) =\n        if r.Max < r.Min then\n            empty\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let inner =\n                store\n                |> MapExt.splitAt min |> sndv\n                |> if not overflow then MapExt.splitAt max >> fstv else id\n\n            let newStore =\n                inner\n                |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id\n                |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1ui(newStore)\n\n    member private x.TryFindLeftBoundary(v : uint32) =\n        let struct (l, s, _) = MapExt.neighboursV v store\n        match s with\n        | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone\n        | _ ->\n            match l with\n            | ValueSome (i, HalfRangeKind.Left) -> ValueSome i\n            | _ -> ValueNone\n\n    /// Returns whether the given value is contained in the range set.\n    member x.Contains(v : uint32) =\n        x.TryFindLeftBoundary v |> ValueOption.isSome\n\n    /// Returns whether the given range is contained in the set.\n    member x.Contains(r : Range1ui) =\n        if r.Max < r.Min then false\n        elif r.Min = r.Max then x.Contains r.Min\n        else\n            match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with\n            | ValueSome l, ValueSome r -> l = r\n            | _ -> false\n\n    /// Returns the number of disjoint ranges in the set.\n    member x.Count =\n        (store.Count + 1) / 2\n\n    /// Returns whether the set is empty.\n    member inline x.IsEmpty =\n        x.Count = 0\n\n    /// Builds an array from the range set.\n    member x.ToArray() =\n        let arr = Array.zeroCreate x.Count\n\n        let rec write (i : int) (l : struct (uint32 * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                arr.[i] <- Range1ui(l, r - 1u)\n                write (i + 1) rest\n\n            | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->\n                arr.[i] <- Range1ui(l, UInt32.MaxValue)\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> ()\n\n        store |> MapExt.toListV |> write 0\n        arr\n\n    /// Builds a list from the range set.\n    member x.ToList() =\n        let rec build (accum : Range1ui list) (l : struct (uint32 * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                build (Range1ui(l, r - 1u) :: accum) rest\n\n            | [struct (l, HalfRangeKind.Left)] ->\n                build (Range1ui(l, UInt32.MaxValue) :: accum) []\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> List.rev accum\n\n        store |> MapExt.toListV |> build []\n\n    /// Views the range set as a sequence.\n    member x.ToSeq() =\n        x :> seq<_>\n\n    member inline private x.Equals(other : RangeSet1ui) =\n        store = other.Store\n\n    override x.Equals(other : obj) =\n        match other with\n        | :? RangeSet1ui as o -> x.Equals o\n        | _ -> false\n\n    override x.GetHashCode() =\n        store.GetHashCode()\n\n    member private x.AsString = x.ToString()\n\n    override x.ToString() =\n        let content =\n            x |> Seq.map (fun r ->\n                $\"[{r.Min}, {r.Max}]\"\n            )\n            |> String.concat \"; \"\n\n        $\"ranges [{content}]\"\n\n    member x.GetEnumerator() =\n        new RangeSetEnumerator1ui((store :> seq<_>).GetEnumerator())\n\n    interface IEquatable<RangeSet1ui> with\n        member x.Equals(other) = x.Equals(other)\n\n    interface IEnumerable with\n        member x.GetEnumerator() = new RangeSetEnumerator1ui((store :> seq<_>).GetEnumerator()) :> _\n\n    interface IEnumerable<Range1ui> with\n        member x.GetEnumerator() = new RangeSetEnumerator1ui((store :> seq<_>).GetEnumerator()) :> _\n\n// TODO: MapExt should use a struct enumerator and return it directly.\n// That way we could get rid of allocations.\nand RangeSetEnumerator1ui =\n    struct\n        val private Inner : IEnumerator<KeyValuePair<uint32, HalfRangeKind>>\n        val mutable private Left : KeyValuePair<uint32, HalfRangeKind>\n        val mutable private Right : KeyValuePair<uint32, HalfRangeKind>\n\n        internal new (inner : IEnumerator<KeyValuePair<uint32, HalfRangeKind>>) =\n            { Inner = inner\n              Left = Unchecked.defaultof<_>\n              Right = Unchecked.defaultof<_> }\n\n        member x.MoveNext() =\n            if x.Inner.MoveNext() then\n                x.Left <- x.Inner.Current\n                if x.Inner.MoveNext() then\n                    x.Right <- x.Inner.Current\n                    true\n                else\n                    if x.Left.Value = HalfRangeKind.Left then\n                        x.Right <- KeyValuePair(UInt32.MinValue, HalfRangeKind.Right) // MaxValue + 1\n                        true\n                    else\n                        failwithf \"bad RangeSet\"\n            else\n                false\n\n        member x.Reset() =\n            x.Inner.Reset()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        member x.Current =\n            assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)\n            Range1ui(x.Left.Key, x.Right.Key - 1u)\n\n        member x.Dispose() =\n            x.Inner.Dispose()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        interface IEnumerator with\n            member x.MoveNext() = x.MoveNext()\n            member x.Current = x.Current :> obj\n            member x.Reset() = x.Reset()\n\n        interface IEnumerator<Range1ui> with\n            member x.Dispose() = x.Dispose()\n            member x.Current = x.Current\n    end\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule RangeSet1ui =\n\n    /// Empty range set.\n    let empty = RangeSet1ui.Empty\n\n    /// Returns the minimum value in the range set or UInt32.MaxValue if the range is empty.\n    let inline min (set : RangeSet1ui) = set.Min\n\n    /// Returns the maximum value in the range set or UInt32.MinValue if the range is empty.\n    let inline max (set : RangeSet1ui) = set.Max\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    let inline range (set : RangeSet1ui) = set.Range\n\n    let inline private getHalfRanges (r : Range1ui) =\n        [ struct (r.Min, HalfRangeKind.Left)\n          if r.Max < UInt32.MaxValue then struct (r.Max + 1u, HalfRangeKind.Right) ]\n\n    let inline private ofRange (r : Range1ui) =\n        RangeSet1ui(MapExt.ofListV <| getHalfRanges r)\n\n    let private ofRanges (ranges : seq<Range1ui>) =\n        let halves =\n            ranges\n            |> Seq.toList\n            |> List.collect getHalfRanges\n            |> List.sortBy fstv\n\n        let mutable level = 0\n        let result = ResizeArray()\n\n        for (struct (i, k) as h) in halves do\n            if k = HalfRangeKind.Left then\n                if level = 0 then result.Add h\n                level <- level + 1\n            else\n                level <- level - 1\n                if level = 0 then result.Add h\n\n        RangeSet1ui(MapExt.ofSeqV result)\n\n    /// Builds a range set of the given list of ranges.\n    let ofList (ranges : Range1ui list) =\n        match ranges with\n        | [] -> empty\n        | [r] -> ofRange r\n        | _ -> ofRanges ranges\n\n    /// Builds a range set of the given array of ranges.\n    let ofArray (ranges : Range1ui[]) =\n        if ranges.Length = 0 then empty\n        elif ranges.Length = 1 then ofRange ranges.[0]\n        else ofRanges ranges\n\n    /// Builds a range set of the given sequence of ranges.\n    let inline ofSeq (ranges : seq<Range1ui>) =\n        ofList <| Seq.toList ranges\n\n    /// Adds the given range to the set.\n    let inline add (range : Range1ui) (set : RangeSet1ui) = set.Add range\n\n    /// Removes the given range from the set.\n    let inline remove (range : Range1ui) (set : RangeSet1ui) = set.Remove range\n\n    /// Returns the union of two sets.\n    let inline union (l : RangeSet1ui) (r : RangeSet1ui) = l.Union r\n\n    /// Returns the intersection of the set with the given range.\n    let inline intersect (range : Range1ui) (set : RangeSet1ui) = set.Intersect range\n\n    /// Returns whether the given value is contained in the range set.\n    let inline contains (value : uint32) (set : RangeSet1ui) = set.Contains value\n\n    /// Returns whether the given range is contained in the set.\n    let inline containsRange (range : Range1ui) (set : RangeSet1ui) = set.Contains range\n\n    /// Returns the number of disjoint ranges in the set.\n    let inline count (set : RangeSet1ui) = set.Count\n\n    /// Returns whether the set is empty.\n    let inline isEmpty (set : RangeSet1ui) = set.IsEmpty\n\n    /// Views the range set as a sequence.\n    let inline toSeq (set : RangeSet1ui) = set :> seq<_>\n\n    /// Builds a list from the range set.\n    let inline toList (set : RangeSet1ui) = set.ToList()\n\n    /// Builds an array from the range set.\n    let inline toArray (set : RangeSet1ui) = set.ToArray()\n\n\n/// Set of ranges where overlapping and neighboring ranges are coalesced.\n/// Note that ranges describe closed intervals.\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype RangeSet1l internal (store : MapExt<int64, HalfRangeKind>) =\n    static let empty = RangeSet1l(MapExt.empty)\n\n    /// Empty range set.\n    static member Empty = empty\n\n    member inline private x.Store = store\n\n    // We cannot directly describe a range that ends at Int64.MaxValue since the right half-range is inserted\n    // at max + 1. In that case the right-half range will be missing and the total count is odd.\n    member inline private x.HasMaxValue = store.Count % 2 = 1\n\n    /// Returns the minimum value in the range set or Int64.MaxValue if the range is empty.\n    member x.Min =\n        match store.TryMinKeyV with\n        | ValueSome min -> min\n        | _ -> Int64.MaxValue\n\n    /// Returns the maximum value in the range set or Int64.MinValue if the range is empty.\n    member x.Max =\n        if x.HasMaxValue then Int64.MaxValue\n        else\n            match store.TryMaxKeyV with\n            | ValueSome max -> max - 1L\n            | _ -> Int64.MinValue\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    member inline x.Range =\n        Range1l(x.Min, x.Max)\n\n    /// Adds the given range to the set.\n    member x.Add(r : Range1l) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained Int64.MaxValue or we have overflown, we must not add an explicit right half-range.\n            // Int64.MaxValue is stored implicitly.\n            let fixRightBoundary =\n                if x.HasMaxValue || overflow then\n                    id\n                else\n                    MapExt.add max HalfRangeKind.Right\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.ofListV [\n                        struct (min, HalfRangeKind.Left)\n                    ]\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> MapExt.add max HalfRangeKind.Right\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    MapExt.union lm rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1l(newStore)\n\n    /// Removes the given range from the set.\n    member x.Remove(r : Range1l) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained Int64.MaxValue and we have not overflown, there is still a range [max, Int64.MaxValue]\n            let fixRightBoundary =\n                if x.HasMaxValue && not overflow then\n                    MapExt.add max HalfRangeKind.Left\n                else\n                    id\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.empty\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Right\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add max HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    MapExt.union lm rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1l(newStore)\n\n    /// Returns the union of the set with the given set.\n    member inline x.Union(other : RangeSet1l) =\n        let mutable res = x\n        for r in other do\n            res <- res.Add r\n        res\n\n    /// Returns the intersection of the set with the given range.\n    member x.Intersect(r : Range1l) =\n        if r.Max < r.Min then\n            empty\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let inner =\n                store\n                |> MapExt.splitAt min |> sndv\n                |> if not overflow then MapExt.splitAt max >> fstv else id\n\n            let newStore =\n                inner\n                |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id\n                |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1l(newStore)\n\n    member private x.TryFindLeftBoundary(v : int64) =\n        let struct (l, s, _) = MapExt.neighboursV v store\n        match s with\n        | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone\n        | _ ->\n            match l with\n            | ValueSome (i, HalfRangeKind.Left) -> ValueSome i\n            | _ -> ValueNone\n\n    /// Returns whether the given value is contained in the range set.\n    member x.Contains(v : int64) =\n        x.TryFindLeftBoundary v |> ValueOption.isSome\n\n    /// Returns whether the given range is contained in the set.\n    member x.Contains(r : Range1l) =\n        if r.Max < r.Min then false\n        elif r.Min = r.Max then x.Contains r.Min\n        else\n            match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with\n            | ValueSome l, ValueSome r -> l = r\n            | _ -> false\n\n    /// Returns the number of disjoint ranges in the set.\n    member x.Count =\n        (store.Count + 1) / 2\n\n    /// Returns whether the set is empty.\n    member inline x.IsEmpty =\n        x.Count = 0\n\n    /// Builds an array from the range set.\n    member x.ToArray() =\n        let arr = Array.zeroCreate x.Count\n\n        let rec write (i : int) (l : struct (int64 * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                arr.[i] <- Range1l(l, r - 1L)\n                write (i + 1) rest\n\n            | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->\n                arr.[i] <- Range1l(l, Int64.MaxValue)\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> ()\n\n        store |> MapExt.toListV |> write 0\n        arr\n\n    /// Builds a list from the range set.\n    member x.ToList() =\n        let rec build (accum : Range1l list) (l : struct (int64 * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                build (Range1l(l, r - 1L) :: accum) rest\n\n            | [struct (l, HalfRangeKind.Left)] ->\n                build (Range1l(l, Int64.MaxValue) :: accum) []\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> List.rev accum\n\n        store |> MapExt.toListV |> build []\n\n    /// Views the range set as a sequence.\n    member x.ToSeq() =\n        x :> seq<_>\n\n    member inline private x.Equals(other : RangeSet1l) =\n        store = other.Store\n\n    override x.Equals(other : obj) =\n        match other with\n        | :? RangeSet1l as o -> x.Equals o\n        | _ -> false\n\n    override x.GetHashCode() =\n        store.GetHashCode()\n\n    member private x.AsString = x.ToString()\n\n    override x.ToString() =\n        let content =\n            x |> Seq.map (fun r ->\n                $\"[{r.Min}, {r.Max}]\"\n            )\n            |> String.concat \"; \"\n\n        $\"ranges [{content}]\"\n\n    member x.GetEnumerator() =\n        new RangeSetEnumerator1l((store :> seq<_>).GetEnumerator())\n\n    interface IEquatable<RangeSet1l> with\n        member x.Equals(other) = x.Equals(other)\n\n    interface IEnumerable with\n        member x.GetEnumerator() = new RangeSetEnumerator1l((store :> seq<_>).GetEnumerator()) :> _\n\n    interface IEnumerable<Range1l> with\n        member x.GetEnumerator() = new RangeSetEnumerator1l((store :> seq<_>).GetEnumerator()) :> _\n\n// TODO: MapExt should use a struct enumerator and return it directly.\n// That way we could get rid of allocations.\nand RangeSetEnumerator1l =\n    struct\n        val private Inner : IEnumerator<KeyValuePair<int64, HalfRangeKind>>\n        val mutable private Left : KeyValuePair<int64, HalfRangeKind>\n        val mutable private Right : KeyValuePair<int64, HalfRangeKind>\n\n        internal new (inner : IEnumerator<KeyValuePair<int64, HalfRangeKind>>) =\n            { Inner = inner\n              Left = Unchecked.defaultof<_>\n              Right = Unchecked.defaultof<_> }\n\n        member x.MoveNext() =\n            if x.Inner.MoveNext() then\n                x.Left <- x.Inner.Current\n                if x.Inner.MoveNext() then\n                    x.Right <- x.Inner.Current\n                    true\n                else\n                    if x.Left.Value = HalfRangeKind.Left then\n                        x.Right <- KeyValuePair(Int64.MinValue, HalfRangeKind.Right) // MaxValue + 1\n                        true\n                    else\n                        failwithf \"bad RangeSet\"\n            else\n                false\n\n        member x.Reset() =\n            x.Inner.Reset()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        member x.Current =\n            assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)\n            Range1l(x.Left.Key, x.Right.Key - 1L)\n\n        member x.Dispose() =\n            x.Inner.Dispose()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        interface IEnumerator with\n            member x.MoveNext() = x.MoveNext()\n            member x.Current = x.Current :> obj\n            member x.Reset() = x.Reset()\n\n        interface IEnumerator<Range1l> with\n            member x.Dispose() = x.Dispose()\n            member x.Current = x.Current\n    end\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule RangeSet1l =\n\n    /// Empty range set.\n    let empty = RangeSet1l.Empty\n\n    /// Returns the minimum value in the range set or Int64.MaxValue if the range is empty.\n    let inline min (set : RangeSet1l) = set.Min\n\n    /// Returns the maximum value in the range set or Int64.MinValue if the range is empty.\n    let inline max (set : RangeSet1l) = set.Max\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    let inline range (set : RangeSet1l) = set.Range\n\n    let inline private getHalfRanges (r : Range1l) =\n        [ struct (r.Min, HalfRangeKind.Left)\n          if r.Max < Int64.MaxValue then struct (r.Max + 1L, HalfRangeKind.Right) ]\n\n    let inline private ofRange (r : Range1l) =\n        RangeSet1l(MapExt.ofListV <| getHalfRanges r)\n\n    let private ofRanges (ranges : seq<Range1l>) =\n        let halves =\n            ranges\n            |> Seq.toList\n            |> List.collect getHalfRanges\n            |> List.sortBy fstv\n\n        let mutable level = 0\n        let result = ResizeArray()\n\n        for (struct (i, k) as h) in halves do\n            if k = HalfRangeKind.Left then\n                if level = 0 then result.Add h\n                level <- level + 1\n            else\n                level <- level - 1\n                if level = 0 then result.Add h\n\n        RangeSet1l(MapExt.ofSeqV result)\n\n    /// Builds a range set of the given list of ranges.\n    let ofList (ranges : Range1l list) =\n        match ranges with\n        | [] -> empty\n        | [r] -> ofRange r\n        | _ -> ofRanges ranges\n\n    /// Builds a range set of the given array of ranges.\n    let ofArray (ranges : Range1l[]) =\n        if ranges.Length = 0 then empty\n        elif ranges.Length = 1 then ofRange ranges.[0]\n        else ofRanges ranges\n\n    /// Builds a range set of the given sequence of ranges.\n    let inline ofSeq (ranges : seq<Range1l>) =\n        ofList <| Seq.toList ranges\n\n    /// Adds the given range to the set.\n    let inline add (range : Range1l) (set : RangeSet1l) = set.Add range\n\n    /// Removes the given range from the set.\n    let inline remove (range : Range1l) (set : RangeSet1l) = set.Remove range\n\n    /// Returns the union of two sets.\n    let inline union (l : RangeSet1l) (r : RangeSet1l) = l.Union r\n\n    /// Returns the intersection of the set with the given range.\n    let inline intersect (range : Range1l) (set : RangeSet1l) = set.Intersect range\n\n    /// Returns whether the given value is contained in the range set.\n    let inline contains (value : int64) (set : RangeSet1l) = set.Contains value\n\n    /// Returns whether the given range is contained in the set.\n    let inline containsRange (range : Range1l) (set : RangeSet1l) = set.Contains range\n\n    /// Returns the number of disjoint ranges in the set.\n    let inline count (set : RangeSet1l) = set.Count\n\n    /// Returns whether the set is empty.\n    let inline isEmpty (set : RangeSet1l) = set.IsEmpty\n\n    /// Views the range set as a sequence.\n    let inline toSeq (set : RangeSet1l) = set :> seq<_>\n\n    /// Builds a list from the range set.\n    let inline toList (set : RangeSet1l) = set.ToList()\n\n    /// Builds an array from the range set.\n    let inline toArray (set : RangeSet1l) = set.ToArray()\n\n\n/// Set of ranges where overlapping and neighboring ranges are coalesced.\n/// Note that ranges describe closed intervals.\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype RangeSet1ul internal (store : MapExt<uint64, HalfRangeKind>) =\n    static let empty = RangeSet1ul(MapExt.empty)\n\n    /// Empty range set.\n    static member Empty = empty\n\n    member inline private x.Store = store\n\n    // We cannot directly describe a range that ends at UInt64.MaxValue since the right half-range is inserted\n    // at max + 1. In that case the right-half range will be missing and the total count is odd.\n    member inline private x.HasMaxValue = store.Count % 2 = 1\n\n    /// Returns the minimum value in the range set or UInt64.MaxValue if the range is empty.\n    member x.Min =\n        match store.TryMinKeyV with\n        | ValueSome min -> min\n        | _ -> UInt64.MaxValue\n\n    /// Returns the maximum value in the range set or UInt64.MinValue if the range is empty.\n    member x.Max =\n        if x.HasMaxValue then UInt64.MaxValue\n        else\n            match store.TryMaxKeyV with\n            | ValueSome max -> max - 1UL\n            | _ -> UInt64.MinValue\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    member inline x.Range =\n        Range1ul(x.Min, x.Max)\n\n    /// Adds the given range to the set.\n    member x.Add(r : Range1ul) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained UInt64.MaxValue or we have overflown, we must not add an explicit right half-range.\n            // UInt64.MaxValue is stored implicitly.\n            let fixRightBoundary =\n                if x.HasMaxValue || overflow then\n                    id\n                else\n                    MapExt.add max HalfRangeKind.Right\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.ofListV [\n                        struct (min, HalfRangeKind.Left)\n                    ]\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> MapExt.add max HalfRangeKind.Right\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    MapExt.union lm rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1ul(newStore)\n\n    /// Removes the given range from the set.\n    member x.Remove(r : Range1ul) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained UInt64.MaxValue and we have not overflown, there is still a range [max, UInt64.MaxValue]\n            let fixRightBoundary =\n                if x.HasMaxValue && not overflow then\n                    MapExt.add max HalfRangeKind.Left\n                else\n                    id\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.empty\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Right\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add max HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    MapExt.union lm rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1ul(newStore)\n\n    /// Returns the union of the set with the given set.\n    member inline x.Union(other : RangeSet1ul) =\n        let mutable res = x\n        for r in other do\n            res <- res.Add r\n        res\n\n    /// Returns the intersection of the set with the given range.\n    member x.Intersect(r : Range1ul) =\n        if r.Max < r.Min then\n            empty\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let inner =\n                store\n                |> MapExt.splitAt min |> sndv\n                |> if not overflow then MapExt.splitAt max >> fstv else id\n\n            let newStore =\n                inner\n                |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id\n                |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            RangeSet1ul(newStore)\n\n    member private x.TryFindLeftBoundary(v : uint64) =\n        let struct (l, s, _) = MapExt.neighboursV v store\n        match s with\n        | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone\n        | _ ->\n            match l with\n            | ValueSome (i, HalfRangeKind.Left) -> ValueSome i\n            | _ -> ValueNone\n\n    /// Returns whether the given value is contained in the range set.\n    member x.Contains(v : uint64) =\n        x.TryFindLeftBoundary v |> ValueOption.isSome\n\n    /// Returns whether the given range is contained in the set.\n    member x.Contains(r : Range1ul) =\n        if r.Max < r.Min then false\n        elif r.Min = r.Max then x.Contains r.Min\n        else\n            match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with\n            | ValueSome l, ValueSome r -> l = r\n            | _ -> false\n\n    /// Returns the number of disjoint ranges in the set.\n    member x.Count =\n        (store.Count + 1) / 2\n\n    /// Returns whether the set is empty.\n    member inline x.IsEmpty =\n        x.Count = 0\n\n    /// Builds an array from the range set.\n    member x.ToArray() =\n        let arr = Array.zeroCreate x.Count\n\n        let rec write (i : int) (l : struct (uint64 * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                arr.[i] <- Range1ul(l, r - 1UL)\n                write (i + 1) rest\n\n            | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->\n                arr.[i] <- Range1ul(l, UInt64.MaxValue)\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> ()\n\n        store |> MapExt.toListV |> write 0\n        arr\n\n    /// Builds a list from the range set.\n    member x.ToList() =\n        let rec build (accum : Range1ul list) (l : struct (uint64 * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                build (Range1ul(l, r - 1UL) :: accum) rest\n\n            | [struct (l, HalfRangeKind.Left)] ->\n                build (Range1ul(l, UInt64.MaxValue) :: accum) []\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> List.rev accum\n\n        store |> MapExt.toListV |> build []\n\n    /// Views the range set as a sequence.\n    member x.ToSeq() =\n        x :> seq<_>\n\n    member inline private x.Equals(other : RangeSet1ul) =\n        store = other.Store\n\n    override x.Equals(other : obj) =\n        match other with\n        | :? RangeSet1ul as o -> x.Equals o\n        | _ -> false\n\n    override x.GetHashCode() =\n        store.GetHashCode()\n\n    member private x.AsString = x.ToString()\n\n    override x.ToString() =\n        let content =\n            x |> Seq.map (fun r ->\n                $\"[{r.Min}, {r.Max}]\"\n            )\n            |> String.concat \"; \"\n\n        $\"ranges [{content}]\"\n\n    member x.GetEnumerator() =\n        new RangeSetEnumerator1ul((store :> seq<_>).GetEnumerator())\n\n    interface IEquatable<RangeSet1ul> with\n        member x.Equals(other) = x.Equals(other)\n\n    interface IEnumerable with\n        member x.GetEnumerator() = new RangeSetEnumerator1ul((store :> seq<_>).GetEnumerator()) :> _\n\n    interface IEnumerable<Range1ul> with\n        member x.GetEnumerator() = new RangeSetEnumerator1ul((store :> seq<_>).GetEnumerator()) :> _\n\n// TODO: MapExt should use a struct enumerator and return it directly.\n// That way we could get rid of allocations.\nand RangeSetEnumerator1ul =\n    struct\n        val private Inner : IEnumerator<KeyValuePair<uint64, HalfRangeKind>>\n        val mutable private Left : KeyValuePair<uint64, HalfRangeKind>\n        val mutable private Right : KeyValuePair<uint64, HalfRangeKind>\n\n        internal new (inner : IEnumerator<KeyValuePair<uint64, HalfRangeKind>>) =\n            { Inner = inner\n              Left = Unchecked.defaultof<_>\n              Right = Unchecked.defaultof<_> }\n\n        member x.MoveNext() =\n            if x.Inner.MoveNext() then\n                x.Left <- x.Inner.Current\n                if x.Inner.MoveNext() then\n                    x.Right <- x.Inner.Current\n                    true\n                else\n                    if x.Left.Value = HalfRangeKind.Left then\n                        x.Right <- KeyValuePair(UInt64.MinValue, HalfRangeKind.Right) // MaxValue + 1\n                        true\n                    else\n                        failwithf \"bad RangeSet\"\n            else\n                false\n\n        member x.Reset() =\n            x.Inner.Reset()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        member x.Current =\n            assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)\n            Range1ul(x.Left.Key, x.Right.Key - 1UL)\n\n        member x.Dispose() =\n            x.Inner.Dispose()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        interface IEnumerator with\n            member x.MoveNext() = x.MoveNext()\n            member x.Current = x.Current :> obj\n            member x.Reset() = x.Reset()\n\n        interface IEnumerator<Range1ul> with\n            member x.Dispose() = x.Dispose()\n            member x.Current = x.Current\n    end\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule RangeSet1ul =\n\n    /// Empty range set.\n    let empty = RangeSet1ul.Empty\n\n    /// Returns the minimum value in the range set or UInt64.MaxValue if the range is empty.\n    let inline min (set : RangeSet1ul) = set.Min\n\n    /// Returns the maximum value in the range set or UInt64.MinValue if the range is empty.\n    let inline max (set : RangeSet1ul) = set.Max\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    let inline range (set : RangeSet1ul) = set.Range\n\n    let inline private getHalfRanges (r : Range1ul) =\n        [ struct (r.Min, HalfRangeKind.Left)\n          if r.Max < UInt64.MaxValue then struct (r.Max + 1UL, HalfRangeKind.Right) ]\n\n    let inline private ofRange (r : Range1ul) =\n        RangeSet1ul(MapExt.ofListV <| getHalfRanges r)\n\n    let private ofRanges (ranges : seq<Range1ul>) =\n        let halves =\n            ranges\n            |> Seq.toList\n            |> List.collect getHalfRanges\n            |> List.sortBy fstv\n\n        let mutable level = 0\n        let result = ResizeArray()\n\n        for (struct (i, k) as h) in halves do\n            if k = HalfRangeKind.Left then\n                if level = 0 then result.Add h\n                level <- level + 1\n            else\n                level <- level - 1\n                if level = 0 then result.Add h\n\n        RangeSet1ul(MapExt.ofSeqV result)\n\n    /// Builds a range set of the given list of ranges.\n    let ofList (ranges : Range1ul list) =\n        match ranges with\n        | [] -> empty\n        | [r] -> ofRange r\n        | _ -> ofRanges ranges\n\n    /// Builds a range set of the given array of ranges.\n    let ofArray (ranges : Range1ul[]) =\n        if ranges.Length = 0 then empty\n        elif ranges.Length = 1 then ofRange ranges.[0]\n        else ofRanges ranges\n\n    /// Builds a range set of the given sequence of ranges.\n    let inline ofSeq (ranges : seq<Range1ul>) =\n        ofList <| Seq.toList ranges\n\n    /// Adds the given range to the set.\n    let inline add (range : Range1ul) (set : RangeSet1ul) = set.Add range\n\n    /// Removes the given range from the set.\n    let inline remove (range : Range1ul) (set : RangeSet1ul) = set.Remove range\n\n    /// Returns the union of two sets.\n    let inline union (l : RangeSet1ul) (r : RangeSet1ul) = l.Union r\n\n    /// Returns the intersection of the set with the given range.\n    let inline intersect (range : Range1ul) (set : RangeSet1ul) = set.Intersect range\n\n    /// Returns whether the given value is contained in the range set.\n    let inline contains (value : uint64) (set : RangeSet1ul) = set.Contains value\n\n    /// Returns whether the given range is contained in the set.\n    let inline containsRange (range : Range1ul) (set : RangeSet1ul) = set.Contains range\n\n    /// Returns the number of disjoint ranges in the set.\n    let inline count (set : RangeSet1ul) = set.Count\n\n    /// Returns whether the set is empty.\n    let inline isEmpty (set : RangeSet1ul) = set.IsEmpty\n\n    /// Views the range set as a sequence.\n    let inline toSeq (set : RangeSet1ul) = set :> seq<_>\n\n    /// Builds a list from the range set.\n    let inline toList (set : RangeSet1ul) = set.ToList()\n\n    /// Builds an array from the range set.\n    let inline toArray (set : RangeSet1ul) = set.ToArray()\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Immutable/RangeSet_template.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base\n\ntype internal HalfRangeKind =\n    | Left = 0\n    | Right = 1\n\nmodule private RangeSetUtils =\n\n    let inline inc (value : 'T) =\n        let res = value + LanguagePrimitives.GenericOne<'T>\n        if res = Constant<'T>.ParseableMinValue then struct (Constant<'T>.ParseableMaxValue, true)\n        else struct (res, false)\n\n    module MapExt =\n        let inline splitAt (key : 'K) (map : MapExt<'K, 'V>) =\n            let struct (l, _, _, _, r) = MapExt.splitV key map\n            struct (l, r)\n\n        let inline tryMinValue (map : MapExt<'K, 'V>) =\n            MapExt.tryMinV map |> ValueOption.map (fun mk -> map.[mk])\n\n        let inline tryMaxValue (map : MapExt<'K, 'V>) =\n            MapExt.tryMaxV map |> ValueOption.map (fun mk -> map.[mk])\n\n        let inline maxValue (map : MapExt<'K, 'V>) =\n            map.[MapExt.max map]\n\nopen RangeSetUtils\n\n//# var ltypes          = new[] { \"int32\", \"uint32\", \"int64\", \"uint64\" };\n//# var sltypes         = new[] { \"Int32\", \"UInt32\", \"Int64\", \"UInt64\" };\n//# var suffixes        = new[] { \"i\", \"ui\", \"l\", \"ul\" };\n//# var literalSuffixes = new[] { \"\", \"u\", \"L\", \"UL\" };\n//#\n//# for (int i = 0; i < ltypes.Length; i++) {\n//#     var ltype = ltypes[i];\n//#     var suffix = suffixes[i];\n//#     var range = \"Range1\" + suffix;\n//#     var rangeset = \"RangeSet1\" + suffix;\n//#     var enumerator = \"RangeSetEnumerator1\" + suffix;\n//#     var one = \"1\" + literalSuffixes[i];\n//#     var minvalue = sltypes[i] + \".MinValue\";\n//#     var maxvalue = sltypes[i] + \".MaxValue\";\n/// Set of ranges where overlapping and neighboring ranges are coalesced.\n/// Note that ranges describe closed intervals.\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype __rangeset__ internal (store : MapExt<__ltype__, HalfRangeKind>) =\n    static let empty = __rangeset__(MapExt.empty)\n\n    /// Empty range set.\n    static member Empty = empty\n\n    member inline private x.Store = store\n\n    // We cannot directly describe a range that ends at __maxvalue__ since the right half-range is inserted\n    // at max + 1. In that case the right-half range will be missing and the total count is odd.\n    member inline private x.HasMaxValue = store.Count % 2 = 1\n\n    /// Returns the minimum value in the range set or __maxvalue__ if the range is empty.\n    member x.Min =\n        match store.TryMinKeyV with\n        | ValueSome min -> min\n        | _ -> __maxvalue__\n\n    /// Returns the maximum value in the range set or __minvalue__ if the range is empty.\n    member x.Max =\n        if x.HasMaxValue then __maxvalue__\n        else\n            match store.TryMaxKeyV with\n            | ValueSome max -> max - __one__\n            | _ -> __minvalue__\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    member inline x.Range =\n        __range__(x.Min, x.Max)\n\n    /// Adds the given range to the set.\n    member x.Add(r : __range__) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained __maxvalue__ or we have overflown, we must not add an explicit right half-range.\n            // __maxvalue__ is stored implicitly.\n            let fixRightBoundary =\n                if x.HasMaxValue || overflow then\n                    id\n                else\n                    MapExt.add max HalfRangeKind.Right\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.ofListV [\n                        struct (min, HalfRangeKind.Left)\n                    ]\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n                    |> MapExt.add max HalfRangeKind.Right\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add min HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left); struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    MapExt.union lm rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            __rangeset__(newStore)\n\n    /// Removes the given range from the set.\n    member x.Remove(r : __range__) =\n        if r.Max < r.Min then\n            x\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let struct (lm, inner) = MapExt.splitAt min store\n            let rm =\n                if overflow then MapExt.empty\n                else sndv <| MapExt.splitAt max inner\n\n            let before = MapExt.tryMaxValue lm\n            let after = MapExt.tryMinValue rm\n\n            // If the set contained __maxvalue__ and we have not overflown, there is still a range [max, __maxvalue__]\n            let fixRightBoundary =\n                if x.HasMaxValue && not overflow then\n                    MapExt.add max HalfRangeKind.Left\n                else\n                    id\n\n            let newStore =\n                match before, after with\n                | ValueNone, ValueNone ->\n                    MapExt.empty\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Right, ValueNone ->\n                    lm\n                    |> fixRightBoundary\n\n                | ValueSome HalfRangeKind.Left, ValueNone ->\n                    lm\n                    |> MapExt.add min HalfRangeKind.Right\n                    |> fixRightBoundary\n\n                | ValueNone, ValueSome HalfRangeKind.Left ->\n                    rm\n\n                | ValueNone, ValueSome HalfRangeKind.Right ->\n                    rm\n                    |> MapExt.add max HalfRangeKind.Left\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Left ->\n                    MapExt.union lm rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Left ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Right, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | ValueSome HalfRangeKind.Left, ValueSome HalfRangeKind.Right ->\n                    let self = MapExt.ofListV [ struct (min, HalfRangeKind.Right); struct (max, HalfRangeKind.Left) ]\n                    MapExt.union (MapExt.union lm self) rm\n\n                | _ ->\n                    failwithf \"impossible\"\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            __rangeset__(newStore)\n\n    /// Returns the union of the set with the given set.\n    member inline x.Union(other : __rangeset__) =\n        let mutable res = x\n        for r in other do\n            res <- res.Add r\n        res\n\n    /// Returns the intersection of the set with the given range.\n    member x.Intersect(r : __range__) =\n        if r.Max < r.Min then\n            empty\n        else\n            let min = r.Min\n            let struct (max, overflow) = inc r.Max\n\n            let inner =\n                store\n                |> MapExt.splitAt min |> sndv\n                |> if not overflow then MapExt.splitAt max >> fstv else id\n\n            let newStore =\n                inner\n                |> if x.Contains r.Min then MapExt.add min HalfRangeKind.Left else id\n                |> if x.Contains r.Max && not overflow then MapExt.add max HalfRangeKind.Right else id\n\n            assert (newStore.Count % 2 = 0 || MapExt.maxValue newStore = HalfRangeKind.Left)\n            __rangeset__(newStore)\n\n    member private x.TryFindLeftBoundary(v : __ltype__) =\n        let struct (l, s, _) = MapExt.neighboursV v store\n        match s with\n        | ValueSome (i, k) -> if k = HalfRangeKind.Left then ValueSome i else ValueNone\n        | _ ->\n            match l with\n            | ValueSome (i, HalfRangeKind.Left) -> ValueSome i\n            | _ -> ValueNone\n\n    /// Returns whether the given value is contained in the range set.\n    member x.Contains(v : __ltype__) =\n        x.TryFindLeftBoundary v |> ValueOption.isSome\n\n    /// Returns whether the given range is contained in the set.\n    member x.Contains(r : __range__) =\n        if r.Max < r.Min then false\n        elif r.Min = r.Max then x.Contains r.Min\n        else\n            match x.TryFindLeftBoundary r.Min, x.TryFindLeftBoundary r.Max with\n            | ValueSome l, ValueSome r -> l = r\n            | _ -> false\n\n    /// Returns the number of disjoint ranges in the set.\n    member x.Count =\n        (store.Count + 1) / 2\n\n    /// Returns whether the set is empty.\n    member inline x.IsEmpty =\n        x.Count = 0\n\n    /// Builds an array from the range set.\n    member x.ToArray() =\n        let arr = Array.zeroCreate x.Count\n\n        let rec write (i : int) (l : struct (__ltype__ * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                arr.[i] <- __range__(l, r - __one__)\n                write (i + 1) rest\n\n            | [struct (l, HalfRangeKind.Left)] when i = x.Count - 1 ->\n                arr.[i] <- __range__(l, __maxvalue__)\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> ()\n\n        store |> MapExt.toListV |> write 0\n        arr\n\n    /// Builds a list from the range set.\n    member x.ToList() =\n        let rec build (accum : __range__ list) (l : struct (__ltype__ * HalfRangeKind) list) =\n            match l with\n            | struct (l, _) :: struct (r, _) :: rest ->\n                build (__range__(l, r - __one__) :: accum) rest\n\n            | [struct (l, HalfRangeKind.Left)] ->\n                build (__range__(l, __maxvalue__) :: accum) []\n\n            | [_] -> failwith \"bad RangeSet\"\n\n            | [] -> List.rev accum\n\n        store |> MapExt.toListV |> build []\n\n    /// Views the range set as a sequence.\n    member x.ToSeq() =\n        x :> seq<_>\n\n    member inline private x.Equals(other : __rangeset__) =\n        store = other.Store\n\n    override x.Equals(other : obj) =\n        match other with\n        | :? __rangeset__ as o -> x.Equals o\n        | _ -> false\n\n    override x.GetHashCode() =\n        store.GetHashCode()\n\n    member private x.AsString = x.ToString()\n\n    override x.ToString() =\n        let content =\n            x |> Seq.map (fun r ->\n                $\"[{r.Min}, {r.Max}]\"\n            )\n            |> String.concat \"; \"\n\n        $\"ranges [{content}]\"\n\n    member x.GetEnumerator() =\n        new __enumerator__((store :> seq<_>).GetEnumerator())\n\n    interface IEquatable<__rangeset__> with\n        member x.Equals(other) = x.Equals(other)\n\n    interface IEnumerable with\n        member x.GetEnumerator() = new __enumerator__((store :> seq<_>).GetEnumerator()) :> _\n\n    interface IEnumerable<__range__> with\n        member x.GetEnumerator() = new __enumerator__((store :> seq<_>).GetEnumerator()) :> _\n\n// TODO: MapExt should use a struct enumerator and return it directly.\n// That way we could get rid of allocations.\nand __enumerator__ =\n    struct\n        val private Inner : IEnumerator<KeyValuePair<__ltype__, HalfRangeKind>>\n        val mutable private Left : KeyValuePair<__ltype__, HalfRangeKind>\n        val mutable private Right : KeyValuePair<__ltype__, HalfRangeKind>\n\n        internal new (inner : IEnumerator<KeyValuePair<__ltype__, HalfRangeKind>>) =\n            { Inner = inner\n              Left = Unchecked.defaultof<_>\n              Right = Unchecked.defaultof<_> }\n\n        member x.MoveNext() =\n            if x.Inner.MoveNext() then\n                x.Left <- x.Inner.Current\n                if x.Inner.MoveNext() then\n                    x.Right <- x.Inner.Current\n                    true\n                else\n                    if x.Left.Value = HalfRangeKind.Left then\n                        x.Right <- KeyValuePair(__minvalue__, HalfRangeKind.Right) // MaxValue + 1\n                        true\n                    else\n                        failwithf \"bad RangeSet\"\n            else\n                false\n\n        member x.Reset() =\n            x.Inner.Reset()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        member x.Current =\n            assert (x.Left.Value = HalfRangeKind.Left && x.Right.Value = HalfRangeKind.Right)\n            __range__(x.Left.Key, x.Right.Key - __one__)\n\n        member x.Dispose() =\n            x.Inner.Dispose()\n            x.Left <- Unchecked.defaultof<_>\n            x.Right <- Unchecked.defaultof<_>\n\n        interface IEnumerator with\n            member x.MoveNext() = x.MoveNext()\n            member x.Current = x.Current :> obj\n            member x.Reset() = x.Reset()\n\n        interface IEnumerator<__range__> with\n            member x.Dispose() = x.Dispose()\n            member x.Current = x.Current\n    end\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule __rangeset__ =\n\n    /// Empty range set.\n    let empty = __rangeset__.Empty\n\n    /// Returns the minimum value in the range set or __maxvalue__ if the range is empty.\n    let inline min (set : __rangeset__) = set.Min\n\n    /// Returns the maximum value in the range set or __minvalue__ if the range is empty.\n    let inline max (set : __rangeset__) = set.Max\n\n    /// Returns the total range spanned by the range set, i.e. [min, max].\n    let inline range (set : __rangeset__) = set.Range\n\n    let inline private getHalfRanges (r : __range__) =\n        [ struct (r.Min, HalfRangeKind.Left)\n          if r.Max < __maxvalue__ then struct (r.Max + __one__, HalfRangeKind.Right) ]\n\n    let inline private ofRange (r : __range__) =\n        __rangeset__(MapExt.ofListV <| getHalfRanges r)\n\n    let private ofRanges (ranges : seq<__range__>) =\n        let halves =\n            ranges\n            |> Seq.toList\n            |> List.collect getHalfRanges\n            |> List.sortBy fstv\n\n        let mutable level = 0\n        let result = ResizeArray()\n\n        for (struct (i, k) as h) in halves do\n            if k = HalfRangeKind.Left then\n                if level = 0 then result.Add h\n                level <- level + 1\n            else\n                level <- level - 1\n                if level = 0 then result.Add h\n\n        __rangeset__(MapExt.ofSeqV result)\n\n    /// Builds a range set of the given list of ranges.\n    let ofList (ranges : __range__ list) =\n        match ranges with\n        | [] -> empty\n        | [r] -> ofRange r\n        | _ -> ofRanges ranges\n\n    /// Builds a range set of the given array of ranges.\n    let ofArray (ranges : __range__[]) =\n        if ranges.Length = 0 then empty\n        elif ranges.Length = 1 then ofRange ranges.[0]\n        else ofRanges ranges\n\n    /// Builds a range set of the given sequence of ranges.\n    let inline ofSeq (ranges : seq<__range__>) =\n        ofList <| Seq.toList ranges\n\n    /// Adds the given range to the set.\n    let inline add (range : __range__) (set : __rangeset__) = set.Add range\n\n    /// Removes the given range from the set.\n    let inline remove (range : __range__) (set : __rangeset__) = set.Remove range\n\n    /// Returns the union of two sets.\n    let inline union (l : __rangeset__) (r : __rangeset__) = l.Union r\n\n    /// Returns the intersection of the set with the given range.\n    let inline intersect (range : __range__) (set : __rangeset__) = set.Intersect range\n\n    /// Returns whether the given value is contained in the range set.\n    let inline contains (value : __ltype__) (set : __rangeset__) = set.Contains value\n\n    /// Returns whether the given range is contained in the set.\n    let inline containsRange (range : __range__) (set : __rangeset__) = set.Contains range\n\n    /// Returns the number of disjoint ranges in the set.\n    let inline count (set : __rangeset__) = set.Count\n\n    /// Returns whether the set is empty.\n    let inline isEmpty (set : __rangeset__) = set.IsEmpty\n\n    /// Views the range set as a sequence.\n    let inline toSeq (set : __rangeset__) = set :> seq<_>\n\n    /// Builds a list from the range set.\n    let inline toList (set : __rangeset__) = set.ToList()\n\n    /// Builds an array from the range set.\n    let inline toArray (set : __rangeset__) = set.ToArray()\n\n\n//# }"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Immutable/SetDelta.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<Struct>]\ntype SetOperation<'a>(value : 'a, cnt : int) =\n    member x.Value = value\n    member x.Count = cnt\n    member x.Inverse = SetOperation(value, -cnt)\n\n    override x.ToString() =\n        if cnt = 1 then sprintf \"Add(%A)\" value\n        elif cnt = -1 then sprintf \"Rem(%A)\" value\n        elif cnt > 0 then sprintf \"Add%d(%A)\" cnt value\n        elif cnt < 0 then sprintf \"Rem%d(%A)\" -cnt value\n        else \"Nop\"\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule SetOperation =\n    let inline create (cnt : int) (v : 'a) = SetOperation(v, cnt)\n    let inline add (v : 'a) = SetOperation(v, 1)   \n    let inline rem (v : 'a) = SetOperation(v, -1)     \n    let inline inverse (d : SetOperation<'a>) = d.Inverse\n    let map (f : 'a -> 'b) (d : SetOperation<'a>) = SetOperation<'b>(f d.Value, d.Count)\n\n[<AutoOpen>]\nmodule SetDeltaExtensions =\n    let inline Add(v : 'a) = SetOperation(v, 1)\n    let inline Rem(v : 'a) = SetOperation(v, -1)\n\n    type SetOperation<'a> with\n        static member inline Add v = SetOperation(v, 1)\n        static member inline Rem v = SetOperation(v, -1)\n\n    let inline (|Add|Rem|) (d : SetOperation<'a>) =\n        if d.Count > 0 then Add(d.Count, d.Value)\n        else Rem(-d.Count, d.Value)\n "
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Mutable/AVL.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\..\\\\Bin\\\\Release\\\\Aardvark.Base.dll\"\n#r \"..\\\\..\\\\..\\\\Bin\\\\Release\\\\Aardvark.Base.FSharp.dll\"\n#else\nnamespace Aardvark.Base\n#endif\n\nopen Aardvark.Base\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule AVL =\n\n    [<AllowNullLiteral>]\n    [<StructuredFormatDisplay(\"AsString\")>]\n    type Node<'a> =\n        class\n        val mutable public Value : 'a\n        val mutable public Left : Node<'a>\n        val mutable public Right : Node<'a>\n        val mutable public height : int\n\n        new(value : 'a) = { Value = value;  Left = null; Right = null; height = -1 }\n        new(value : 'a, l : Node<'a>, r : Node<'a>) = { Value = value;  Left = l; Right = r; height = -1 }\n\n        member x.Height =\n            if x.height < 0 then\n                let l = if not (isNull x.Left) then x.Left.Height else 0\n                let r = if not (isNull x.Right) then x.Right.Height else 0 \n                x.height <- 1 + Fun.Max(l,r)\n            x.height\n\n        member x.Balance =\n            let l = if not (isNull x.Left) then x.Left.Height else 0\n            let r = if not (isNull x.Right) then x.Right.Height else 0 \n            l - r\n\n        member x.AsString =\n            if not (isNull x.Left) || not (isNull x.Right) then\n                let l = if not (isNull x.Left) then x.Left.AsString else \"Nil\"\n                let r = if not (isNull x.Right) then x.Right.AsString else \"Nil\"\n                sprintf \"Node(%A, %s, %s)\" x.Value l r\n            else\n                sprintf \"Leaf(%A)\" x.Value\n\n        end\n        \n    [<StructuredFormatDisplay(\"AsString\")>]\n    type Tree<'a> =\n        class\n            val mutable public Root : Node<'a>\n            val public cmp : 'a -> 'a -> int\n\n            new(cmp) = { cmp = cmp; Root = null }\n\n\n            member x.AsString = if not (isNull x.Root) then x.Root.AsString else \"Nil\"\n\n        end\n\n    let private (|Nil|Node|) (n : Node<'a>) =\n        if isNull n then Nil\n        else Node(n.Value)\n\n    let private rebalance (n : byref<Node<'a>>) =\n        let b = if not (isNull n) then n.Balance else 0\n        if b = 2 then\n            let l = n.Left\n            if l.Balance >= 0 then\n                //left-left\n                let ll = l.Left\n                n <- Node(l.Value, ll, Node(n.Value, l.Right, n.Right))\n            elif l.Balance = -1 then\n                //left-right\n                let lr = l.Right\n                n <- Node(lr.Value, Node(l.Value, l.Left, lr.Left), Node(n.Value, lr.Right, n.Right))\n\n        elif b = -2 then\n            let r = n.Right\n            if r.Balance <= 0 then\n                //right-right\n                let rr = r.Right\n                n <- Node(r.Value, Node(n.Value, n.Left, r.Left), rr)\n            elif r.Balance = 1 then\n                //right-left\n                let rl = r.Left\n                n <- Node(rl.Value, Node(n.Value, n.Left, rl.Left), Node(r.Value, rl.Right, r.Right))\n\n    let rec private ninsert' (cmp : 'a -> 'a -> int) (n : byref<Node<'a>>) (value : 'a) =\n        match n with\n            | Node(v) ->\n                let c = cmp v value\n                if c = 0 then false\n                elif c > 0 then \n                    if ninsert' cmp &n.Left value then\n                        n.height <- -1\n                        rebalance &n\n                        true\n                    else false\n                else \n                    if ninsert' cmp &n.Right value then\n                        n.height <- -1\n                        rebalance &n\n                        true\n                    else false\n            | Nil ->\n                n <- Node(value)\n                true\n\n    let rec private ninsertNeighbourhood' (prev : Option<'a>) (next : Option<'a>) (cmp : 'a -> 'a -> int) (n : byref<Node<'a>>) (value : 'a) (f : Option<'a> -> Option<'a> -> unit) =\n        match n with\n            | Node(v) ->\n                let c = cmp v value\n                if c = 0 then false\n                elif c > 0 then \n                    if ninsertNeighbourhood' prev (Some v) cmp &n.Left value f then\n                        n.height <- -1\n                        rebalance &n\n                        true\n                    else false\n                else \n                    if ninsertNeighbourhood' (Some v) next cmp &n.Right value f then\n                        n.height <- -1\n                        rebalance &n\n                        true\n                    else false\n            | Nil ->\n                n <- Node(value)\n                f prev next\n                true\n\n    let rec private ninsertOrUpdateNeighbourhood' (prev : Option<'a>) (next : Option<'a>) (cmp : 'a -> 'a -> int) (n : byref<Node<'a>>) (value : 'a) (f : Option<'a> -> Option<'a> -> Option<'a> -> unit) =\n        match n with\n            | Node(v) ->\n                let c = cmp v value\n                if c = 0 then \n                    f prev (Some v) next\n                    false\n                elif c > 0 then \n                    if ninsertOrUpdateNeighbourhood' prev (Some v) cmp &n.Left value f then\n                        n.height <- -1\n                        rebalance &n\n                        true\n                    else false\n                else\n                    if ninsertOrUpdateNeighbourhood' (Some v) next cmp &n.Right value f then\n                        n.height <- -1\n                        rebalance &n\n                        true\n                    else false\n\n            | Nil ->\n                f prev None next\n                n <- Node(value)\n                true\n\n\n    let rec private nextractLeftmost' (n : byref<Node<'a>>) =\n        match n with\n            | Nil -> None\n            | _ -> \n                if isNull n.Left then\n                    let v = n.Value\n                    n <- n.Right\n                    Some v\n                else\n                    let r = nextractLeftmost' &n.Left\n                    if r.IsSome then\n                        n.height <- -1\n                        rebalance &n\n                    r\n\n    let rec private nextractRightmost' (n : byref<Node<'a>>) =\n        match n with\n            | Nil -> None\n            | _ -> \n                if isNull n.Right then\n                    let v = n.Value\n                    n <- n.Left\n                    Some v\n                else\n                    let r = nextractRightmost' &n.Right\n                    if r.IsSome then\n                        n.height <- -1\n                        rebalance &n\n                    r\n\n\n    let rec private nremove' (n : byref<Node<'a>>) (valueCmp : 'a -> int) =\n        match n with\n            | Nil -> false\n            | Node(v) ->\n                let c = valueCmp v\n                if c = 0 then\n                    match n.Left, n.Right with\n                        | Nil,r -> \n                            n <- r\n                            true\n                        | l,Nil -> \n                            n <- l\n                            true\n                        | _ -> \n                            match nextractLeftmost' &n.Right with\n                            | Some v -> \n                                n <- Node(v, n.Left, n.Right)\n                                rebalance &n\n                                true\n                            | None ->\n                                match nextractRightmost' &n.Left with\n                                    | Some v -> \n                                        n <- Node(v, n.Left, n.Right)\n                                        rebalance &n\n                                        true\n                                    | None -> failwith \"not possible\"\n\n                elif c < 0 then\n                    if nremove' &n.Left valueCmp then\n                        n.height <- -1\n                        rebalance &n\n                        true\n                    else\n                        false\n                else\n                    if nremove' &n.Right valueCmp then\n                        n.height <- -1\n                        rebalance &n\n                        true\n                    else\n                        false\n\n    let rec private ntoSeq' (n : Node<'a>) : seq<'a> =\n        seq {\n            match n with\n                | Node(v) -> \n                    yield! n.Left |> ntoSeq'\n                    yield v\n                    yield! n.Right |> ntoSeq'\n                | _ -> ()\n        }\n\n    let rec private nextractMinimalWhere' (condition : 'a -> bool) (n : byref<Node<'a>>) =\n        match n with\n            | Nil -> None\n            | Node(v) ->\n                let c = condition v\n                if c then\n                    if isNull n.Left then \n                        let v = n.Value\n                        n <- n.Right\n                        Some v\n                    else\n                        let r = nextractMinimalWhere' condition &n.Left\n                        if r.IsSome then\n                            n.height <- -1\n                            rebalance &n\n                            r\n                        else\n                            let v = n.Value\n                                \n                            if isNull n.Right then\n                                n <- n.Left\n                            else\n                                match nextractLeftmost' &n.Right with\n                                | Some v -> \n                                    n <- Node(v, n.Left, n.Right)\n                                    rebalance &n\n                                | None ->\n                                    match nextractRightmost' &n.Left with\n                                        | Some v -> \n                                            n <- Node(v, n.Left, n.Right)\n                                            rebalance &n\n                                        | None -> failwith \"not possible\"\n\n                            Some v\n                else\n                    if isNull n.Right then \n                        None\n                    else\n                        let r = nextractMinimalWhere' condition &n.Right\n                        if r.IsSome then\n                            n.height <- -1\n                            rebalance &n\n                        r\n\n    let rec private nfindMinimalWhere' (condition : 'a -> bool) (n : Node<'a>) =\n        match n with\n            | Nil -> None\n            | Node(v) ->\n                let c = condition v\n                if c then\n                    if isNull n.Left then \n                        Some n.Value\n                    else\n                        let r = nfindMinimalWhere' condition n.Left\n                        if r.IsSome then\n                            r\n                        else\n                            Some n.Value\n                else\n                    if isNull n.Right then \n                        None\n                    else\n                        nfindMinimalWhere' condition n.Right\n\n    let rec private nfindMaximalWhere' (condition : 'a -> bool) (n : Node<'a>) =\n        match n with\n            | Nil -> None\n            | Node(v) ->\n                let c = condition v\n                if c then\n                    if isNull n.Right then \n                        Some n.Value\n                    else\n                        let r = nfindMaximalWhere' condition n.Right\n                        if r.IsSome then\n                            r\n                        else\n                            Some n.Value\n                else\n                    if isNull n.Left then \n                        None\n                    else\n                        nfindMaximalWhere' condition n.Left\n\n\n    let rec private nextractMaximalWhere' (condition : 'a -> bool) (n : byref<Node<'a>>) =\n        match n with\n            | Nil -> None\n            | Node(v) ->\n                let c = condition v\n                if c then\n                    if isNull n.Right then \n                        let v = n.Value\n                        n <- n.Left\n                        Some v\n                    else\n                        let r = nextractMaximalWhere' condition &n.Right\n                        if r.IsSome then\n                            n.height <- -1\n                            rebalance &n\n                            r\n                        else\n                            let v = n.Value\n                                \n                            if isNull n.Left then\n                                n <- n.Right\n                            else\n                                match nextractLeftmost' &n.Right with\n                                | Some v -> \n                                    n <- Node(v, n.Left, n.Right)\n                                    rebalance &n\n                                | None ->\n                                    match nextractRightmost' &n.Left with\n                                        | Some v -> \n                                            n <- Node(v, n.Left, n.Right)\n                                            rebalance &n\n                                        | None -> failwith \"not possible\"\n\n                            Some v\n                else\n                    if isNull n.Left then \n                        None\n                    else\n                        let r = nextractMaximalWhere' condition &n.Left\n                        if r.IsSome then\n                            n.height <- -1\n                            rebalance &n\n                        r\n\n    let rec private nfind' (cmp : 'a -> int) (n : Node<'a>) =\n        match n with\n            | Nil -> None\n            | Node(v) ->\n                let c = cmp v\n                if c = 0 then Some v\n                elif c < 0 then nfind' cmp n.Left\n                else nfind' cmp n.Right\n\n    let private nprint' (n : Node<'a>) =\n        if isNull n then printfn \"Nil\"\n        else\n            let h = n.Height + 1\n            let data = System.Collections.Generic.Dictionary<int, Option<'a>[]>()\n            let set (x : int) (y : int) (v : 'a) =\n                match data.TryGetValue x with\n                    | (true, arr) -> arr.[y] <- Some v\n                    | _ -> let arr = Array.create h None\n                           arr.[y] <- Some v\n                           data.[x] <- arr\n\n            let rec dump (l : int) (x : int) (n : Node<'a>) =\n                match n with\n                    | Node _ ->\n                        if not (isNull n.Left) || not (isNull n.Right) then\n                            set x l n.Value\n                            dump (l + 1) (x - (1 <<< (1 + h - l))) n.Left\n                            dump (l + 1) (x + (1 <<< (1 + h - l))) n.Right\n                        else \n                            set x l n.Value\n                    | Nil -> ()\n\n            dump 0 0 n\n\n            let nonEmpty = data |> Seq.sortBy (fun (KeyValue(k,v)) -> k) |> Seq.map (fun (KeyValue(_,v)) -> v) |> Seq.toArray\n\n            let maxLength = ref 0\n            let strings = nonEmpty |> Array.map (fun a -> a |> Array.map (fun o ->\n                            match o with\n                                | None -> None\n                                | Some v -> \n                                    let str = sprintf \" %A \" v\n                                    if str.Length > !maxLength then maxLength := str.Length\n                                    Some str\n                            ))\n\n            let padToLength (s : string) =\n                if s.Length < !maxLength then\n                    s + System.String(' ', !maxLength - s.Length)\n                else\n                    s\n\n            let strings = strings |> Array.map (fun a -> a |> Array.map (fun o ->\n                            match o with\n                                | Some s -> padToLength s\n                                | None -> System.String(' ', !maxLength)\n                            ))\n\n            for y in 0..h-1 do\n                for x in 0..strings.Length-1 do\n                    printf  \"%s\" strings.[x].[y]\n                printf \"\\r\\n\"\n\n\n    /// <summary>\n    /// creates a new empty AVL-Tree using the given comparison function\n    /// note that the given function must define a total order and may only \n    /// return {-1,0,1}. Futhermore cmp(a,b) = 0 must be equivalent to a = b.\n    /// </summary>\n    let custom cmp = Tree(cmp)\n\n    /// <summary>\n    /// creates a new empty AVL-Tree using the default comparison function\n    /// </summary>\n    let empty<'a when 'a : comparison> =\n        Tree(compare<'a>)\n\n    /// <summary>\n    /// inserts a new value into the tree and returns true if the value was\n    /// not already present in the tree. \n    /// Runtime: O(log(N))\n    /// </summary>\n    let insert (t : Tree<'a>) (value : 'a) =\n        ninsert' t.cmp &t.Root value\n\n    let insertNeighbourhood (t : Tree<'a>) (value : 'a) (f : Option<'a> -> Option<'a> -> unit) =\n        ninsertNeighbourhood' None None t.cmp &t.Root value f\n\n    let insertOrUpdateNeighbourhood (t : Tree<'a>) (value : 'a) (f : Option<'a> -> Option<'a> -> Option<'a> -> unit) =\n        ninsertOrUpdateNeighbourhood' None None t.cmp &t.Root value f\n\n\n    /// <summary>\n    /// inserts a new value into the tree if not already present.\n    /// Runtime: O(log(N))\n    /// </summary>\n    let insert' (t : Tree<'a>) (value : 'a) =\n        ninsert' t.cmp &t.Root value |> ignore\n\n    /// <summary>\n    /// removes a value from the tree and returns true if the value was found.\n    /// Runtime: O(log(N))\n    /// </summary>\n    let remove (t : Tree<'a>) (value : 'a) =\n        nremove' &t.Root (fun v -> t.cmp value v)\n\n    /// <summary>\n    /// removes a value from the tree if present.\n    /// Runtime: O(log(N))\n    /// </summary>\n    let remove' (t : Tree<'a>) (value : 'a) =\n        nremove' &t.Root (fun v -> t.cmp value v) |> ignore\n\n\n    /// <summary>\n    /// removes a value using a partially applied comparison function.\n    /// the given function must perform comparison like: compare(myValue, treeValue).\n    /// returns true if the element was found and false otherwise\n    /// Runtime: O(log(N))\n    /// </summary>\n    let removeCmp (t : Tree<'a>) (cmpValue : 'a -> int) =\n        nremove' &t.Root cmpValue\n\n    /// <summary>\n    /// creates a sequence containing all the elements in the tree.\n    /// the sequence is ascendingly sorted with respect to the given comparison function.\n    /// Runtime: O(1) [Note that traversing the entire sequence is of course in O(N)]\n    /// </summary>\n    let toSeq (t : Tree<'a>) =\n        ntoSeq' t.Root\n\n    /// <summary>\n    /// creates a list containing all the elements in the tree.\n    /// the list is ascendingly sorted with respect to the given comparison function.\n    /// Runtime: O(N)\n    /// </summary>\n    let toList (t : Tree<'a>) =\n        t.Root |> ntoSeq' |> Seq.toList\n\n    /// <summary>\n    /// finds and removes the minimal value from the tree for which the given condition holds. \n    /// it is assumed that this condition is transitive with respect to the given comparison function.\n    /// returns the (optional) value found in the tree.\n    /// Example: extractMinimalWhere (fun v -> v > 10) gives the minimal value in the tree being greater than 10.\n    /// Runtime: O(log(N))\n    ///</summary>\n    let extractMinimalWhere (condition : 'a -> bool) (t : Tree<'a>) =\n        nextractMinimalWhere' condition &t.Root\n\n    /// <summary>\n    /// finds and removes the maximum value from the tree for which the given condition holds. \n    /// it is assumed that this condition is transitive with respect to the given comparison function.\n    /// returns the (optional) value found in the tree.\n    /// Example: extractMaximalWhere (fun v -> v > 10) gives the maximal value in the tree being greater than 10.\n    /// Runtime: O(log(N))\n    ///</summary>\n    let extractMaximalWhere (condition : 'a -> bool) (t : Tree<'a>) =\n        nextractMaximalWhere' condition &t.Root\n\n\n    let findMinimalWhere (condition : 'a -> bool) (t : Tree<'a>) =\n        nfindMinimalWhere' condition t.Root\n\n    let findMaximalWhere (condition : 'a -> bool) (t : Tree<'a>) =\n        nfindMaximalWhere' condition t.Root\n\n\n\n    /// <summary>\n    /// finds a value using a partially applied comparison function.\n    /// the given function must perform comparison like: compare(myValue, treeValue).\n    /// returns the (optional) value found\n    /// Runtime: O(log(N))\n    /// </summary>\n    let find (cmp : 'a -> int) (t : Tree<'a>) =\n        nfind' cmp t.Root\n\n    let get (element : 'a) (tree : Tree<'a>) =\n        nfind' (fun e -> tree.cmp element e) tree.Root\n\n    /// <summary>\n    /// prints the tree to the console for debugging purposes.\n    /// </summary>\n    let print (t : Tree<'a>) =\n        if isNull t.Root then printfn \"Nil\"\n        else nprint' t.Root\n\n    /// <summary>\n    /// runs a randomized series of additions / removals on a tree and \n    /// validates its correctness, completeness, order and internal cache-values.\n    /// </summary>\n    let runTests() =\n        let elements = Array.init 10000 (fun i -> i)\n        let elements = System.Collections.Generic.List(elements)\n        let used = System.Collections.Generic.List<int>()\n        let tree = custom (fun (a : int) (b : int) -> a.CompareTo b)\n\n        let checkCorrectness() =\n            let l = toList tree\n            let correct = l |> Seq.fold (fun a b -> a && used.Contains b) true\n            if not correct then\n                printfn \"ERROR: removed elements are still in the tree\"\n\n        let checkCompleteness() =\n            let l = System.Collections.Generic.HashSet(tree |> toList)\n            let correct = used |> Seq.fold (fun a b -> a && l.Contains b) true\n            if not correct then\n                printfn \"ERROR: elements are missing in the tree\"\n\n        let checkSorting() =\n            let list = System.Collections.Generic.List(tree |> toList)\n                \n            let mutable error = false\n            for i in 1..list.Count-1 do\n                let l = list.[i-1]\n                let r = list.[i]\n                if l > r then\n                    error <- true\n\n                     \n            if error then\n                printfn \"ERROR: elements are not ascending\"\n\n        let checkBalanceAndHeightCaches() =\n            let rec h (n : Node<int>) =\n                match n with\n                    | Nil -> 0\n                    | Node _ ->\n                        let l = if not (isNull n.Left) then h n.Left else 0\n                        let r = if not (isNull n.Right) then h n.Right else 0\n                        1 + Fun.Max(l,r)\n\n            let rec balanceAndHeightValid(n : Node<int>) =\n                if not (isNull n) then\n                    let mine = h n\n                    let cache = n.Height\n                    if mine <> cache then false\n                    else\n                        let b = (h n.Left) - (h n.Right)\n                        let cache = n.Balance\n                        if b <> cache || b >= 2 then false\n                        else true\n                else\n                    true\n\n            if not <| balanceAndHeightValid tree.Root then\n                printfn \"ERROR: invalid balance or height cache\"\n\n        let checkFind() =\n            for u in used do\n                match tree |> find (fun b -> compare u b) with\n                    | Some v -> ()\n                    | None -> printfn \"ERROR: find could not find element: %d\" u\n\n            for e in elements do\n                match tree |> find (fun b -> compare e b) with\n                    | Some v -> printfn \"ERROR: found element not in tree: %d\" e\n                    | None -> ()\n \n\n        let mutable iter = 0\n        let mutable maxCount = 0\n        let r = System.Random()\n\n        let mutable removeCount = 0\n        let mutable extractMinimalWhereCount = 0\n        let mutable extractMaximalWhereCount = 0\n        let mutable insertCount = 0\n\n        for i in 0..10000 do\n            let u = r.NextDouble()\n\n            if u < 0.5 && used.Count > 0 && iter > 500 then\n                let id = r.Next(used.Count)\n                let element = used.[id]\n                used.RemoveAt id\n                elements.Add element\n\n                let r = r.NextDouble()\n                if r < 0.3333 then\n                    if (extractMinimalWhere (fun e -> e >= element) tree).IsNone then printfn \"ERROR: extractMinimalWhere returned false although the element was present\"\n                    extractMinimalWhereCount <- extractMinimalWhereCount + 1\n                elif r < 0.6666 then\n                    if (extractMaximalWhere (fun e -> e <= element) tree).IsNone then printfn \"ERROR: extractMaximalWhere returned false although the element was present\"\n                    extractMaximalWhereCount <- extractMaximalWhereCount + 1\n                else\n                    if not <| remove tree element then printfn \"ERROR: remove returned false although the element was present\"\n                    removeCount <- removeCount + 1\n            else\n                let id = r.Next(elements.Count)\n                let element = elements.[id]\n                elements.RemoveAt id\n                used.Add element\n                if not <| insert tree element then printfn \"ERROR: insert returned false although the element was not present\"\n                maxCount <- Fun.Max(maxCount, used.Count)\n                insertCount <- insertCount + 1\n\n            iter <- iter + 1\n            checkCorrectness()\n            checkCompleteness()\n            checkSorting()\n            checkBalanceAndHeightCaches()\n            checkFind()\n\n        \n        printfn \"tree contained up to %d elements\" maxCount\n        printfn \"    insert:              %d\" insertCount\n        printfn \"    remove:              %d\" removeCount\n        printfn \"    extractMinimalWhere: %d\" extractMinimalWhereCount \n        printfn \"    extractMaximalWhere: %d\" extractMaximalWhereCount \n        printfn \"    current-count: %d (expected %d)\" (tree |> toList).Length (insertCount - removeCount - extractMaximalWhereCount - extractMinimalWhereCount)\n        printfn \"test finished\"\n\n    let test() =\n        let t = empty\n            \n        insert t 5 |> ignore\n        insert t 6 |> ignore\n        insert t 7 |> ignore\n        insert t 8 |> ignore\n        insert t 9 |> ignore\n        insert t 10 |> ignore\n\n        printfn \"%s\" t.AsString\n        print t\n\n        let test = extractMinimalWhere (fun v -> v > 5) t\n        let test2 = extractMaximalWhere (fun v -> v < 10) t\n\n        printfn \"minimal > 5 = %A\" test\n        printfn \"maximal < 10 = %A\" test2\n\n        remove t 10 |> ignore\n\n        printfn \"%s\" t.Root.AsString\n\n\nmodule BucketAVL =\n    open System.Collections.Generic\n\n    [<AllowNullLiteral>]\n    type private LinkedListNode<'a> =\n        class\n            val mutable public Value : 'a\n            val mutable public Next : LinkedListNode<'a>\n            val mutable public Prev : LinkedListNode<'a>\n            \n            new(value : 'a) = { Value = value; Next = null; Prev = null }\n        end\n\n    type private Bucket<'a when 'a : equality>() =\n        let mutable representative : Option<'a> = None\n        let mutable root : Option<LinkedListNode<'a>> = None\n        let references = Dictionary<'a, LinkedListNode<'a>>()\n        let mutable next : Option<Bucket<'a>> = None\n        let mutable prev : Option<Bucket<'a>> = None\n\n        member x.AsSeq =\n            match root with\n                | Some r ->\n                    seq {\n                        yield r.Value\n                        let current = ref r.Next\n                            \n                        while !current <> r do\n                            yield current.Value.Value\n                            current := current.Value.Next\n                    }\n                | None ->\n                    Seq.empty\n\n        member x.Next \n            with get() = next\n            and set v = next <- v\n\n        member x.Prev \n            with get() = prev\n            and set v = prev <- v\n\n        member x.Value = representative.Value\n\n        member x.Add(value : 'a) =\n            if references.ContainsKey value then\n                false\n            else\n                representative <- Some value\n                let node = LinkedListNode(value)\n                references.Add(value, node)\n\n                match root with\n                    | Some r -> \n                        let last = r.Prev\n                        node.Prev <- last\n                        node.Next <- r\n                        last.Next <- node\n                        r.Prev <- node\n                    | None ->\n                        node.Prev <- node\n                        node.Next <- node\n                        root <- Some node\n                true\n\n        member x.Remove(value : 'a) =\n            match references.TryGetValue value with\n                | (true, r) ->\n                    if r = root.Value then\n                        if r.Next = r then\n                            root <- None\n                        else\n                            root <- Some r.Next\n\n                        \n\n                    r.Prev.Next <- r.Next\n                    r.Next.Prev <- r.Prev\n                    references.Remove value |> ignore\n\n                    //if the representative is removed change it to some other one\n                    //if the bucket gets empty maintain the representative since\n                    //it is needed for the tree-removal. (the bucket will be removed anyways)\n                    if value = representative.Value && references.Count > 0 then\n                        representative <- Some root.Value.Value\n                        \n                    true\n\n                | _ -> false\n\n        member x.FirstElement = root.Value.Value\n        member x.LastElement = \n            let last : LinkedListNode<'a> = root.Value.Prev\n            last.Value\n        member x.Count = references.Count\n\n    type BucketTree<'a when 'a : equality> = private { cmp : 'a -> 'a -> int; tree : AVL.Tree<Bucket<'a>> }\n\n    let custom cmp = { cmp = cmp; tree = AVL.custom (fun (l : Bucket<'a>) (r : Bucket<'a>) -> cmp l.Value r.Value) }\n                              \n    let insert (t : BucketTree<'a>) (value : 'a) =\n        match AVL.find (fun (o : Bucket<'a>) -> t.cmp value o.Value) t.tree with\n            | Some b -> b.Add value\n            | None ->\n                let b = Bucket<'a>()\n                b.Add value |> ignore\n                AVL.insertNeighbourhood t.tree b (fun prev next -> \n                    b.Prev <- prev\n                    b.Next <- next\n                    match next with Some n -> n.Prev <- Some b | _ -> ()\n                    match prev with Some p -> p.Next <- Some b | _ -> ()\n                )\n\n    let insertNeighbourhood (t : BucketTree<'a>) (value : 'a) (f : Option<'a> -> Option<'a> -> unit) =\n        match t.tree |> AVL.find (fun o -> t.cmp value o.Value) with\n            | Some b ->\n                let last = Some b.LastElement\n                let next = match b.Next with | Some b -> Some b.FirstElement | _ -> None\n                if b.Add value then\n                    f last next\n                    true\n                else\n                    false\n            | _ ->\n                let b = Bucket<'a>()\n                b.Add value |> ignore\n                AVL.insertNeighbourhood t.tree b (fun prev next ->\n                    b.Prev <- prev\n                    b.Next <- next\n                    match next with Some n -> n.Prev <- Some b | _ -> ()\n                    match prev with Some p -> p.Next <- Some b | _ -> ()\n                        \n                        \n                    let prev = match prev with | Some p -> Some p.LastElement | None -> None\n                    let next = match next with | Some n -> Some n.FirstElement | None -> None\n\n                        \n\n                    f prev next\n                )\n\n    let remove (t : BucketTree<'a>) (value : 'a) =\n        match AVL.find (fun (o : Bucket<'a>) -> t.cmp value o.Value) t.tree with\n            | Some b ->\n                if b.Remove value then\n                    if b.Count = 0 then\n                        if AVL.remove t.tree b then\n                            match b.Prev with\n                                | Some p -> p.Next <- b.Next\n                                | _ -> ()\n                            match b.Next with\n                                | Some n -> n.Prev <- b.Prev\n                                | _ -> ()\n                            true\n                        else\n                            false\n                    else\n                        true\n                else\n                    false\n            | None -> false\n//\n//        let extractMinimalWhere (condition : 'a -> bool) (t : BucketTree<'a>) =\n//            match t.tree |> AVL.findMinimalWhere (fun b -> condition b.Value)  with\n//                | Some b -> \n//                    let some = b.Value\n//                    b.Remove some |> ignore\n//                    if b.Count = 0 then\n//                        AVL.remove t.tree b |> ignore\n//                    Some some\n//                | None -> None\n//\n//        let extractMaximalWhere (condition : 'a -> bool) (t : BucketTree<'a>) =\n//            match t.tree |> AVL.findMaximalWhere (fun b -> condition b.Value)  with\n//                | Some b -> \n//                    let some = b.Value\n//                    b.Remove some |> ignore\n//                    if b.Count = 0 then\n//                        AVL.remove t.tree b |> ignore\n//                    Some some\n//                | None -> None\n\n    let toSeq (t : BucketTree<'a>) =\n        t.tree |> AVL.toSeq |> Seq.collect (fun b -> b.AsSeq)\n\n    let toList (t : BucketTree<'a>) =\n        t |> toSeq |> Seq.toList\n\n    let toArray (t : BucketTree<'a>) =\n        t |> toSeq |> Seq.toArray\n\n\n    let runTests() =\n        let t = custom (fun l r -> compare (l % 10) (r % 10))\n\n        let numbers = Array.init 1000 id\n            \n\n        for n in numbers do\n            if not <| insertNeighbourhood t n (fun l r -> ()) then\n                printfn \"ERROR: insert of %A failed\" n\n\n        let content = toArray t\n        if content.Length <> numbers.Length then\n            printfn \"elements missing\"\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Mutable/ConcurrentHashQueue.fs",
    "content": "﻿namespace Aardvark.Base\n\n\nopen System.Threading\nopen System.Runtime.InteropServices\n\n[<AllowNullLiteral>]\ntype private HashQueueNode<'a> =\n    class\n        val mutable public Value : 'a\n        val mutable public Next : HashQueueNode<'a>\n        val mutable public Prev : HashQueueNode<'a>\n\n        new(v,p,n) = { Value = v; Prev = p; Next = n }\n    end\n\ntype ConcurrentHashQueue<'a when 'a : equality>() =\n    let lockObj = obj()\n    let nodes = Dict<'a, HashQueueNode<'a>>()\n    let mutable first = null\n    let mutable last = null\n\n    let detach (node : HashQueueNode<'a>) =\n        if isNull node.Prev then first <- node.Next\n        else node.Prev.Next <- node.Next\n\n        if isNull node.Next then last <- node.Prev\n        else node.Next.Prev <- node.Prev\n                                 \n\n    member x.Count = lock lockObj (fun () -> nodes.Count)\n\n    member x.Enqueue(value : 'a) =\n        lock lockObj (fun () ->\n            let node,added = \n                match nodes.TryGetValue value with\n                    | (true, node) -> \n                        detach node\n                        node.Prev <- last\n                        node.Next <- null\n                        node, false   \n                    | _ ->\n                        let node = HashQueueNode(value, last, null)\n                        nodes.[value] <- node\n                        node, true\n\n            if isNull last then first <- node\n            else last.Next <- node\n            last <- node\n            added\n        )\n\n    member x.Dequeue() =\n        lock lockObj (fun () ->\n            if isNull first then \n                failwith \"HashQueue empty\"\n            else\n                let value = first.Value\n                first <- first.Next\n                first.Prev <- null\n                nodes.Remove value |> ignore\n                value\n        )\n\n    member x.TryDequeue([<Out>] result : byref<'a>) =\n        try\n            Monitor.Enter lockObj\n            if isNull first then \n                false\n            else\n                let value = first.Value\n                detach first\n                nodes.Remove value |> ignore\n                result <- value\n                true\n        finally\n            Monitor.Exit lockObj\n\n    member x.Remove(value : 'a) =\n        lock lockObj (fun () ->\n            match nodes.TryRemove value with\n                | (true, node) ->\n                    detach node\n                    node.Value <- Unchecked.defaultof<_>\n                    node.Prev <- null\n                    node.Next <- null\n                    true\n                | _ ->\n                    false\n        )\n\n    member x.Clear() =\n        lock lockObj (fun () ->\n            nodes.Clear()\n            first <- null\n            last <- null\n        )\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule ConcurrentHashQueue =\n    \n    let inline empty<'a when 'a : equality> = ConcurrentHashQueue<'a>()\n\n    let inline enqueue (v : 'a) (q : ConcurrentHashQueue<'a>) =\n        q.Enqueue v\n\n    let inline tryDequeue (q : ConcurrentHashQueue<'a>) =\n        match q.TryDequeue() with\n            | (true, v) -> Some v\n            | _ -> None\n\n    let inline dequeue (q : ConcurrentHashQueue<'a>) =\n        q.Dequeue()\n\n    let inline count (q : ConcurrentHashQueue<'a>) =\n        q.Count\n\n    let inline clear (q : ConcurrentHashQueue<'a>) =\n        q.Clear()"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Mutable/FixedSizeArray.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<AutoOpen>]\nmodule Arrays =\n\n    open System\n    open System.Collections.Generic\n\n    [<StructuredFormatDisplay(\"{AsString}\")>]\n    type Arr<'d, 'a when 'd :> INatural>(elements : seq<'a>) =\n        static let size = typeSize<'d>\n        let data = Array.zeroCreate size\n        do let elements = elements |> Seq.toArray\n           let l = min elements.Length size\n           for i in 0..l-1 do\n           data.[i] <- elements.[i]\n\n        member x.Data = data\n\n        member x.Item\n            with get i = data.[i]\n            and set i v = data.[i] <- v\n\n        member x.Length = size\n\n        member x.AsString =\n            sprintf \"%A\" data\n\n        new() = Arr []\n\n        interface IEnumerable<'a> with\n            member x.GetEnumerator() : System.Collections.Generic.IEnumerator<'a> = (data |> Array.toSeq).GetEnumerator()\n            member x.GetEnumerator() : System.Collections.IEnumerator = data.GetEnumerator()\n\n    [<ReflectedDefinition>]\n    type FixedList<'d, 'a when 'd :> INatural> = { storage : Arr<'d, 'a>; mutable Count : int } with\n        member x.Item\n            with get i = x.storage.[i]\n            and set i v = x.storage.[i] <- v\n\n        member x.Add(value : 'a) =\n            x.storage.[x.Count] <- value\n            x.Count <- x.Count + 1\n\n        member x.RemoveAt(index : int) =\n            for i in index+1..x.Count-1 do\n                x.storage.[i-1] <- x.storage.[i]\n            x.Count <- x.Count - 1\n//\n//    let z<'a> = Arr<Z, 'a>([||])\n//\n//    let (|&) (a : Arr<'d, 'a>) (v : 'a) : Arr<S<'d>, 'a> =\n//        let data = a.Data\n//        let inner = Array.concat [data; [|v|]]\n//        Arr<S<'d>, 'a>(inner)\n//\n//    let (~~) (v : 'a) : Arr<S<Z>, 'a> =\n//        Arr [v]\n\n    [<ReflectedDefinition>]\n    module Arr =\n        let inline map ([<InlineIfLambda>] f : 'a -> 'b) (a : Arr<'d, 'a>) : Arr<'d, 'b> =\n            let result = Array.zeroCreate a.Length\n            for i in 0..a.Length-1 do\n                result.[i] <- f a.[i]\n            Arr<'d,'b>(result)\n\n        let inline fold (f : 's -> 'a -> 's) (seed : 's) (a : Arr<'d, 'a>) : 's =\n            let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n            let mutable result = seed\n            for i in 0..a.Length-1 do\n                result <- f.Invoke(result, a.[i])\n            result\n\n        let inline foldBack (f : 'a -> 's -> 's) (seed : 's) (a : Arr<'d, 'a>) : 's =\n            let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n            let mutable result = seed\n            for i in 1..a.Length do\n                let i = a.Length-i\n                result <- f.Invoke(a.[i], result)\n            result\n\n        let inline sumBy ([<InlineIfLambda>] f : 'a -> 'b) (arr : Arr<'d, 'a>)=\n            fold (fun s v -> s + (f v)) LanguagePrimitives.GenericZero arr\n\n        let inline sum (arr : Arr<'d, 'a>)=\n            fold (+) LanguagePrimitives.GenericZero arr\n\n        let ofList (l : list<'a>) : Arr<'d, 'a> =\n            Arr(l)\n\n        let ofSeq (l : seq<'a>) : Arr<'d, 'a> =\n            Arr(l)\n\n    [<ReflectedDefinition>]\n    module ArrList =\n\n\n        let empty<'d, 'a when 'd :> INatural> : FixedList<'d, 'a> = { storage = Arr<'d, 'a>(); Count = 0 }\n\n        let inline map ([<InlineIfLambda>] f : 'a -> 'b) (l : FixedList<'d, 'a>) : FixedList<'d, 'b> =\n            let result = Arr<'d, 'b>()\n            for i in 0..l.Count-1 do\n                result.[i] <- f l.storage.[i]\n            { storage =result; Count = l.Count }\n\n        let inline choose ([<InlineIfLambda>] f : 'a -> Option<'b>) (l : FixedList<'d, 'a>) : FixedList<'d, 'b> =\n            let result = Arr<'d, 'b>()\n            let mutable count = 0\n\n            for i in 0..l.Count-1 do\n                match f l.[i] with\n                    | Some v ->\n                        result.[count] <- v\n                        count <- count + 1\n                    | None -> ()\n\n            { storage = result; Count = count }\n\n        let inline fold (acc : 'a -> 'b -> 'a) (seed : 'a) (l : FixedList<'d, 'b>) : 'a =\n            let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt acc\n            let mutable result = seed\n            for i in 0..l.Count-1 do\n                result <- f.Invoke(result, l.storage.[i])\n            result\n\n        let inline foldBack (acc : 'b -> 'a -> 'a) (seed : 'a) (l : FixedList<'d, 'b>) : 'a =\n            let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt acc\n            let mutable result = seed\n            for i in 1..l.Count do\n                result <- f.Invoke(l.storage.[i - l.Count], result)\n            result\n\n        let inline sumBy ([<InlineIfLambda>] f : 'a -> 'b) (l : FixedList<'d, 'a>) : 'b =\n            let mutable result = LanguagePrimitives.GenericZero\n            for i in 0..l.Count-1 do\n                result <- result + f l.storage.[i]\n            result\n\n        let inline sum (l : FixedList<'d, 'a>) : 'a =\n            let mutable result = LanguagePrimitives.GenericZero\n            for i in 0..l.Count-1 do\n                result <- result + l.storage.[i]\n            result\n\n        let inline filter ([<InlineIfLambda>] condition : 'a -> bool) (l : FixedList<'d, 'a>) : FixedList<'d, 'a> =\n            let result = Arr<'d, 'a>()\n            let mutable count = 0\n\n            for i in 0..l.Count-1 do\n                if condition l.[i] then\n                    result.[count] <- l.storage.[i]\n                    count <- count + 1\n\n            { storage = result; Count = count }\n\n        let ofArr (a : Arr<'d, 'a>) =\n            { storage = a; Count = a.Length }\n\n    module List =\n        let toFixed<'d, 'a when 'd :> INatural> (l : list<'a>) =\n            Arr<'d, 'a>(l)\n\n    module Seq =\n        let toFixed<'d, 'a when 'd :> INatural> (l : seq<'a>) =\n            Arr<'d, 'a>(l)\n\n    module Array =\n        let toFixed<'d, 'a when 'd :> INatural> (l : seq<'a>) =\n            Arr<'d, 'a>(l)\n\n    [<return: Struct>]\n    let (|FixedArrayType|_|) (t : Type) =\n        if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<Arr<Z, int>> then\n            let targs = t.GetGenericArguments()\n            ValueSome (getSize targs.[0], targs.[1])\n        else\n            ValueNone\n\n    [<return: Struct>]\n    let (|FixedArray|_|) (o : obj) =\n        let t = o.GetType()\n        match t with\n        | FixedArrayType(_,content) ->\n            let store = t.GetProperty(\"Data\").GetValue(o) |> unbox<Array>\n            let result = Array.create store.Length null\n            for i in 0..store.Length-1 do\n                result.[i] <- store.GetValue(i)\n\n            ValueSome (content, result)\n\n        | _ -> ValueNone\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Mutable/OrderMaintenance.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections.Generic\n\n[<AllowNullLiteral>] \ntype IDeletableComparable =\n    inherit IComparable\n    abstract member IsDeleted : bool\n\n[<AllowNullLiteral>] \ntype ISortKey =\n    inherit IDeletableComparable\n    abstract member Clock : IOrder\n\nand IOrder =\n    abstract member Count : int\n    abstract member Root : ISortKey\n\nmodule Order =\n//    let toSeq (c : IOrder) =\n//        let rec toSeq (t : ISortKey) =\n//            seq {\n//                yield t\n//                if t.Next <> c.Root then\n//                    yield! toSeq t\n//            }\n//\n//        toSeq c.Root.Next\n//        \n//    let toArray (c : IOrder) =\n//        let mutable current = c.Root.Next\n//        let arr = Array.zeroCreate (c.Count-1)\n//        for i in 0..c.Count-2 do\n//            arr.[i] <- current\n//            current <- current.Next\n//        arr\n\n//    let toList (c : IOrder) =\n//        c |> toArray |> Array.toList\n\n    let inline count (c : IOrder) =\n        c.Count\n\n    let inline root (c : IOrder) =\n        c.Root\n\n\nmodule SimpleOrder =\n    \n    [<AllowNullLiteral>]\n    type SortKey =\n        class\n            val mutable public Clock : Order\n            val mutable public Tag : uint64\n            val mutable public Next : SortKey\n            val mutable public Prev : SortKey\n\n            member x.Time =\n                x.Tag - x.Clock.Root.Tag\n\n            member x.CompareTo (o : SortKey) =\n                if isNull o.Next || isNull x.Next then\n                    failwith \"cannot compare deleted times\"\n\n                if o.Clock <> x.Clock then\n                    failwith \"cannot compare times from different clocks\"\n\n                compare x.Time o.Time\n\n            interface IComparable with\n                member x.CompareTo o =\n                    match o with\n                        | :? SortKey as o -> x.CompareTo(o)\n                        | _ -> failwithf \"cannot compare time with %A\" o\n\n            interface IComparable<ISortKey> with\n                member x.CompareTo o =\n                    match o with\n                        | :? SortKey as o -> x.CompareTo o\n                        | _ -> failwithf \"cannot compare time with %A\" o\n\n            override x.GetHashCode() = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(x)\n            override x.Equals o = System.Object.ReferenceEquals(x,o)\n\n            interface ISortKey with\n                member x.Clock = x.Clock :> IOrder\n                member x.IsDeleted = isNull x.Next\n                //member x.Next = x.Next :> ISortKey\n\n            new(c) = { Clock = c; Tag = 0UL; Next = null; Prev = null }\n        end\n\n    and Order =\n        class\n            val mutable public Root : SortKey\n            val mutable public Count : int\n\n            member x.After (t : SortKey) =\n                if t.Clock <> x then\n                    failwith \"cannot insert after a different clock's time\"\n\n                let distance (a : SortKey) (b : SortKey) =\n                    if a = b then System.UInt64.MaxValue\n                    else b.Tag - a.Tag\n\n                let mutable dn = distance t t.Next\n\n                // if the distance to the next time is 1 (no room)\n                // relabel all times s.t. the new one can be inserted\n                if dn = 1UL then\n                    // find a range s.t. distance(range) >= 1 + |range|^2 \n                    let mutable current = t.Next\n                    let mutable j = 1UL\n                    while distance t current < 1UL + j * j do\n                        current <- current.Next\n                        j <- j + 1UL\n\n                    // distribute all times in the range equally spaced\n                    let step = (distance t current) / j\n                    current <- t.Next\n                    let mutable currentTime = t.Tag + step\n                    for k in 1UL..(j-1UL) do\n                        current.Tag <- currentTime\n                        current <- current.Next\n                        currentTime <- currentTime + step\n\n                    // store the distance to the next time\n                    dn <- step\n\n                // insert the new time with distance (dn / 2) after\n                // the given one (there has to be enough room now)\n                let res = SortKey(x)\n                res.Tag <- t.Tag + dn / 2UL\n\n                res.Next <- t.Next\n                res.Prev <- t\n                t.Next.Prev <- res\n                t.Next <- res\n\n                res\n\n            member x.Before (t : SortKey) =\n                if t = x.Root then\n                    failwith \"cannot insert before root-time\"\n                x.After t.Prev\n\n            member x.Delete (t : SortKey) =\n                if not (isNull t.Next) then\n                    if t.Clock <> x then\n                        failwith \"cannot delete time from different clock\"\n\n                    t.Prev.Next <- t.Next\n                    t.Next.Prev <- t.Prev\n                    t.Next <- null\n                    t.Prev <- null\n                    t.Tag <- 0UL\n                    t.Clock <- Unchecked.defaultof<_>      \n\n            member x.Clear() =\n                let r = SortKey(x)\n                x.Root <- r\n                r.Next <- r\n                r.Prev <- r\n                x.Count <- 1\n\n            interface IOrder with\n                member x.Root = x.Root :> ISortKey\n                member x.Count = x.Count\n\n            static member New() =\n                let c = Order()\n                let r = SortKey(c)\n                c.Root <- r\n                r.Next <- r\n                r.Prev <- r\n                c\n\n            private new() = { Root = null; Count = 1 }\n        end\n\n    let create() =\n        Order.New()\n\nmodule SkipOrder =\n    let private random = Random()\n    let randomHeight() =\n        1 - random.NextDouble().Log2Int()\n\n    [<AllowNullLiteral>]\n    type SortKey =\n        class\n            val mutable public Clock : Order\n            val mutable public Tag : uint64\n            val mutable public NextArray : SortKeyLink[]\n            val mutable public PrevArray : SortKeyLink[]\n            val mutable public IsDeleted : bool\n\n            member x.Time =\n                x.Tag - x.Clock.Root.Tag\n\n            member x.Height =\n                x.NextArray.Length\n\n            member x.Next = \n                if not (isNull x.NextArray) then x.NextArray.[0].Target\n                else null\n\n            member x.Prev =\n                if not (isNull x.PrevArray) then x.PrevArray.[0].Target\n                else null\n\n            member x.CompareTo (o : SortKey) =\n                if o.IsDeleted || x.IsDeleted then\n                    failwith \"cannot compare deleted times\"\n\n                if o.Clock <> x.Clock then\n                    failwith \"cannot compare times from different clocks\"\n\n                compare x.Time o.Time\n\n            interface IComparable with\n                member x.CompareTo o =\n                    match o with\n                        | :? SortKey as o -> x.CompareTo(o)\n                        | _ -> failwithf \"cannot compare time with %A\" o\n\n            interface IComparable<ISortKey> with\n                member x.CompareTo o =\n                    match o with\n                        | :? SortKey as o -> x.CompareTo o\n                        | _ -> failwithf \"cannot compare time with %A\" o\n\n            override x.GetHashCode() = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(x)\n            override x.Equals o = System.Object.ReferenceEquals(x,o)\n\n            interface ISortKey with\n                member x.Clock = x.Clock :> IOrder\n                member x.IsDeleted = x.IsDeleted\n                //member x.Next = x.Next :> ISortKey\n\n            new(c, h) = { Clock = c; Tag = 0UL; NextArray = Array.zeroCreate h; PrevArray = Array.zeroCreate h; IsDeleted = false }\n        end\n\n    and SortKeyLink =\n        struct\n            val mutable public Width : int\n            val mutable public Target : SortKey\n\n            new(w,t) = { Width = w; Target = t }\n        end\n\n    and Order =\n        class\n            val mutable public Root : SortKey\n            val mutable public Count : int\n\n            member x.After (t : SortKey) =\n                if t.Clock <> x then\n                    failwith \"cannot insert after a different clock's time\"\n\n                let distance (a : SortKey) (b : SortKey) =\n                    if a = b then System.UInt64.MaxValue\n                    else b.Tag - a.Tag\n\n                let mutable dn = distance t t.Next\n\n                // if the distance to the next time is 1 (no room)\n                // relabel all times s.t. the new one can be inserted\n                if dn = 1UL then\n                    // find a range s.t. distance(range) >= 1 + |range|^2 \n                    let mutable current = t.NextArray.[0].Target\n                    let mutable j = 1UL\n                    while distance t current < 1UL + j * j do\n                        current <- current.Next\n                        j <- j + 1UL\n\n                    // distribute all times in the range equally spaced\n                    let step = (distance t current) / j\n                    current <- t.NextArray.[0].Target\n                    let mutable currentTime = t.Tag + step\n                    for k in 1UL..(j-1UL) do\n                        current.Tag <- currentTime\n                        current <- current.NextArray.[0].Target\n                        currentTime <- currentTime + step\n\n                    // store the distance to the next time\n                    dn <- step\n\n                // insert the new time with distance (dn / 2) after\n                // the given one (there has to be enough room now)\n                let h = randomHeight()\n                let res = SortKey(x, h)\n                res.Tag <- t.Tag + dn / 2UL\n\n\n                // since the predecessor might be \"smaller\" than \n                // the new node we need to search the remaining links\n                // by going backward in the list\n                let mutable current = t\n                let mutable distance = 1\n\n                let resize (h : int) =\n                    let n = x.Root\n                    if h > n.Height then\n                        let additional = Array.create (h - n.Height) (SortKeyLink(x.Count,n))\n                        n.NextArray <- Array.append n.NextArray additional\n                        n.PrevArray <- Array.append n.PrevArray additional\n\n                let back (n : SortKey) =\n                    let link = n.PrevArray.[n.PrevArray.Length - 1]\n                    (link.Width, link.Target)\n\n                let tup (l : SortKeyLink) =\n                    (l.Width, l.Target)\n\n                for i in 0..h-1 do\n\n                    // go backwards until a node with sufficient height is found\n                    // or until we've reached the representant\n                    while i >= current.Height && current <> x.Root do\n                        let (d,l) = back current\n\n                        current <- l\n                        distance <- distance + d\n\n                    // if the found node is not sufficiently high it must\n                    // be the representant and therefore it has to be resized\n                    if i >= current.Height then\n                        resize h\n\n                    // current must now be sufficiently high  \n                    let (d,n) = tup current.NextArray.[i]\n\n                    current.NextArray.[i] <- SortKeyLink(distance, res)\n                    res.PrevArray.[i] <- SortKeyLink(distance, current)\n                    res.NextArray.[i] <- SortKeyLink(1 + d - distance, n)\n                    n.PrevArray.[i] <- SortKeyLink(1 + d - distance, res)\n\n                // since the predecessor and the new node might be\n                // smaller than the total height we need to increment\n                // the width of all pointers \"passing\" the new node (above)\n                let mutable current = t\n                for i in h..x.Root.Height-1 do\n                    while i >= current.Height && current <> x.Root do\n                        let (d,l) = back current\n                        current <- l\n\n                    let (d,n) = tup current.NextArray.[i]\n                    current.NextArray.[i] <- SortKeyLink(d + 1, n)\n                    n.PrevArray.[i] <- SortKeyLink(d + 1, current)\n\n                // finally increment the count and return the node\n                x.Count <- x.Count + 1\n                res\n\n            member x.Before (t : SortKey) =\n                if t = x.Root then\n                    failwith \"cannot insert before root-time\"\n                x.After t.Prev\n              \n            member x.Delete (t : SortKey) = \n                if not (isNull t.NextArray) then \n                    if t.Clock <> x then\n                        failwith \"cannot delete time from different clock\"\n\n                    let tup (l : SortKeyLink) = (l.Width, l.Target)\n                    for l in 0..t.Height-1 do\n                        let (dp, p) = tup t.PrevArray.[l]\n                        let (dn, n) = tup t.NextArray.[l]\n\n                        n.PrevArray.[l] <- SortKeyLink(dp + dn - 1, p)\n                        p.NextArray.[l] <- SortKeyLink(dp + dn - 1, n)\n\n                    let mutable current = t\n                    let mutable distance = 1\n                    for i in t.Height..x.Root.Height-1 do\n                        let back (n : SortKey) =\n                            let l = n.PrevArray.[n.PrevArray.Length - 1]\n                            (l.Width, l.Target)\n                        // go backwards until a node with sufficient height is found\n                        // or until we've reached the representant\n                        while i >= current.Height && current <> x.Root do\n                            let (d,l) = back current\n                            current <- l\n                            distance <- distance + d\n\n                        let (dn, n) = tup current.NextArray.[i]\n\n                        current.NextArray.[i] <- SortKeyLink(dn - 1, n)\n                        n.PrevArray.[i] <- SortKeyLink(dn - 1, current)\n\n                    // every level (except for 0) on which rep.NextArray.[level] = rep \n                    // is useless and is therefore removed\n                    let rep = x.Root\n                    let mutable repHeight = rep.Height\n                    while repHeight > 1 && rep.NextArray.[repHeight - 1].Target = rep do\n                        repHeight <- repHeight - 1\n\n                    if repHeight < rep.Height then\n                        rep.NextArray <- Array.sub rep.NextArray 0 repHeight\n                        rep.PrevArray <- Array.sub rep.PrevArray 0 repHeight\n        \n                    x.Count <- x.Count - 1\n                    t.IsDeleted <- true\n//                    t.NextArray <- null\n//                    t.PrevArray <- null\n//                    t.Tag <- 0UL\n//                    t.Clock <- Unchecked.defaultof<_>      \n\n            member x.Clear() =\n                let r = SortKey(x, 1)\n                x.Root <- r\n                r.NextArray.[0] <- SortKeyLink(1,r)\n                r.PrevArray.[0] <- SortKeyLink(1,r)\n                x.Count <- 1\n\n            /// gets the n-th time after this one\n            /// NOTE that this only works on representant-nodes\n            member x.TryAt (index : int) =\n\n                let rec search (index : int) (level : int) (t : SortKey) : Option<SortKey> =\n                    if level < 0 then\n                        if index = 0 then Some t\n                        else None\n                    else\n                        let link = t.NextArray.[level]\n                        if index < link.Width then\n                            search index (level - 1) t\n                        else\n                            search (index - link.Width) level link.Target\n\n                if index >= 0 && index < x.Count then\n                    search index (x.Root.Height - 1) x.Root\n                else\n                    None\n\n            member x.TryGetIndex (t : SortKey) =\n                if t.Clock <> x || t.IsDeleted then\n                    -1\n                else\n                    let mutable index = 0\n                    let mutable current = t\n                    while current <> x.Root do\n                        let link = t.PrevArray.[t.PrevArray.Length - 1]\n\n                        index <- index + link.Width\n                        current <- link.Target\n                    index\n\n            member x.Item\n                with get (index : int) =\n                    match x.TryAt index with\n                        | Some t -> t \n                        | None -> raise <| IndexOutOfRangeException()\n\n            interface IOrder with\n                member x.Root = x.Root :> ISortKey\n                member x.Count = x.Count\n\n            static member New() =\n                let c = Order()\n                let r = SortKey(c, 1)\n                c.Root <- r\n                r.NextArray.[0] <- SortKeyLink(1,r)\n                r.PrevArray.[0] <- SortKeyLink(1,r)\n                c\n\n            private new() = { Root = null; Count = 1 }\n        end\n\n    let create() =\n        Order.New()\n\nmodule DerivedOrder =\n    let private random = Random()\n    let randomHeight() =\n        1 - random.NextDouble().Log2Int()\n\n\n    type private DeletedImpl<'a>() =\n        static let isDeleted =\n            if typeof<IDeletableComparable>.IsAssignableFrom(typeof<'a>) then\n                fun (a : 'a) -> \n                    let t = unbox<IDeletableComparable> a\n                    if not (isNull t) then t.IsDeleted\n                    else false\n            else\n                fun (a : 'a) -> false\n\n        static member IsDeleted = isDeleted\n\n    [<AllowNullLiteral>]\n    type SortKey<'a> =\n        class\n            val mutable public Clock : Order<'a>\n            val mutable public Tag : uint64\n            val mutable public Item : 'a\n            val mutable public NextArray : SortKeyLink<'a>[]\n            val mutable public PrevArray : SortKeyLink<'a>[]\n            val mutable public IsDeleted : bool\n\n            member x.Time =\n                x.Tag - x.Clock.Root.Tag\n\n            member x.Height =\n                x.NextArray.Length\n\n            member x.Next = \n                if not (isNull x.NextArray) then x.NextArray.[0].Target\n                else null\n\n            member x.Prev =\n                if not (isNull x.PrevArray) then x.PrevArray.[0].Target\n                else null\n\n            member x.CompareTo (o : SortKey<'a>) =\n                if o.IsDeleted || x.IsDeleted then\n                    failwith \"cannot compare deleted times\"\n\n                if o.Clock <> x.Clock then\n                    failwith \"cannot compare times from different clocks\"\n\n                compare x.Time o.Time\n\n            interface IComparable with\n                member x.CompareTo o =\n                    match o with\n                        | :? SortKey<'a> as o -> x.CompareTo(o)\n                        | _ -> failwithf \"cannot compare time with %A\" o\n\n            interface IComparable<ISortKey> with\n                member x.CompareTo o =\n                    match o with\n                        | :? SortKey<'a> as o -> x.CompareTo o\n                        | _ -> failwithf \"cannot compare time with %A\" o\n\n            override x.GetHashCode() = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(x)\n            override x.Equals o = System.Object.ReferenceEquals(x,o)\n\n            interface ISortKey with\n                member x.Clock = x.Clock :> IOrder\n                member x.IsDeleted = x.IsDeleted\n                //member x.Next = x.Next :> ISortKey\n\n            new(c, h) = { Clock = c; Tag = 0UL; NextArray = Array.zeroCreate h; PrevArray = Array.zeroCreate h; Item = Unchecked.defaultof<_>; IsDeleted = false }\n        end\n\n    and SortKeyLink<'a> =\n        struct\n            val mutable public Width : int\n            val mutable public Target : SortKey<'a>\n\n            new(w,t) = { Width = w; Target = t }\n        end\n\n    and Order<'a> =\n        class\n            val mutable public Root : SortKey<'a>\n            val mutable public Count : int\n            val mutable public Comparer : IComparer<'a>\n\n            member x.IsDeleted (item : 'a) =\n                DeletedImpl<'a>.IsDeleted item\n\n            member private x.After (t : SortKey<'a>) =\n                if t.Clock <> x then\n                    failwith \"cannot insert after a different clock's time\"\n\n                let distance (a : SortKey<'a>) (b : SortKey<'a>) =\n                    if a = b then System.UInt64.MaxValue\n                    else b.Tag - a.Tag\n\n                let mutable dn = distance t t.Next\n\n                // if the distance to the next time is 1 (no room)\n                // relabel all times s.t. the new one can be inserted\n                if dn = 1UL then\n                    // find a range s.t. distance(range) >= 1 + |range|^2 \n                    let mutable current = t.NextArray.[0].Target\n                    let mutable j = 1UL\n                    while distance t current < 1UL + j * j do\n                        current <- current.Next\n                        j <- j + 1UL\n\n                    // distribute all times in the range equally spaced\n                    let step = (distance t current) / j\n                    current <- t.NextArray.[0].Target\n                    let mutable currentTime = t.Tag + step\n                    for k in 1UL..(j-1UL) do\n                        current.Tag <- currentTime\n                        current <- current.NextArray.[0].Target\n                        currentTime <- currentTime + step\n\n                    // store the distance to the next time\n                    dn <- step\n\n                // insert the new time with distance (dn / 2) after\n                // the given one (there has to be enough room now)\n                let h = randomHeight()\n                let res = SortKey(x, h)\n                res.Tag <- t.Tag + dn / 2UL\n\n\n                // since the predecessor might be \"smaller\" than \n                // the new node we need to search the remaining links\n                // by going backward in the list\n                let mutable current = t\n                let mutable distance = 1\n\n                let resize (h : int) =\n                    let n = x.Root\n                    if h > n.Height then\n                        let additional = Array.create (h - n.Height) (SortKeyLink(x.Count,n))\n                        n.NextArray <- Array.append n.NextArray additional\n                        n.PrevArray <- Array.append n.PrevArray additional\n\n                let back (n : SortKey<'a>) =\n                    let link = n.PrevArray.[n.PrevArray.Length - 1]\n                    (link.Width, link.Target)\n\n                let tup (l : SortKeyLink<'a>) =\n                    (l.Width, l.Target)\n\n                for i in 0..h-1 do\n\n                    // go backwards until a node with sufficient height is found\n                    // or until we've reached the representant\n                    while i >= current.Height && current <> x.Root do\n                        let (d,l) = back current\n\n                        current <- l\n                        distance <- distance + d\n\n                    // if the found node is not sufficiently high it must\n                    // be the representant and therefore it has to be resized\n                    if i >= current.Height then\n                        resize h\n\n                    // current must now be sufficiently high  \n                    let (d,n) = tup current.NextArray.[i]\n\n                    current.NextArray.[i] <- SortKeyLink(distance, res)\n                    res.PrevArray.[i] <- SortKeyLink(distance, current)\n                    res.NextArray.[i] <- SortKeyLink(1 + d - distance, n)\n                    n.PrevArray.[i] <- SortKeyLink(1 + d - distance, res)\n\n                // since the predecessor and the new node might be\n                // smaller than the total height we need to increment\n                // the width of all pointers \"passing\" the new node (above)\n                let mutable current = t\n                for i in h..x.Root.Height-1 do\n                    while i >= current.Height && current <> x.Root do\n                        let (d,l) = back current\n                        current <- l\n\n                    let (d,n) = tup current.NextArray.[i]\n                    current.NextArray.[i] <- SortKeyLink(d + 1, n)\n                    n.PrevArray.[i] <- SortKeyLink(d + 1, current)\n\n                // finally increment the count and return the node\n                x.Count <- x.Count + 1\n                res\n\n            member x.Get(value : 'a) : SortKey<'a> =\n                if x.IsDeleted value then\n                    failwith \"cannot get time for deleted input-value\"\n\n                let rec findPrevAcc (acc : array<_>) (index : int) (level : int) (v : 'a) (n : SortKey<'a>) =\n                    if level < 0 then \n                        (index, acc)\n                    else\n                        let link = n.NextArray.[level]\n                        if link.Target = x.Root then\n                            acc.[level] <- SortKeyLink(index, n)\n                            findPrevAcc acc index (level - 1) v n \n                        else\n                            if x.IsDeleted link.Target.Item then\n                                x.Delete link.Target\n                                findPrevAcc acc index (min (x.Root.Height-1) level) v n\n                            else\n                                if link.Target <> x.Root && x.Comparer.Compare(v, link.Target.Item) > 0 then\n                                    let t = n.NextArray.[level].Target\n\n                                    let level = min level (t.NextArray.Length-1)\n                                    findPrevAcc acc (index + link.Width) level v t \n                                else\n                                    acc.[level] <- SortKeyLink(index, n)\n                                    findPrevAcc acc index (level - 1) v n \n\n                let ptr = Array.zeroCreate x.Root.Height\n                let (index, prev) = findPrevAcc ptr 0 (x.Root.Height-1) value x.Root\n\n                let next = prev.[0].Target\n                if next <> x.Root && x.Comparer.Compare(next.Item, value) = 0 then\n                    prev.[0].Target\n                else\n                    let tn = x.After prev.[0].Target\n                    tn.Item <- value\n                    tn\n            \n            member x.Delete (t : SortKey<'a>) = \n                if t = x.Root then failwith \"tried to delete root\"\n                if t.IsDeleted |> not then \n                    if t.Clock <> x then\n                        failwith \"cannot delete time from different clock\"\n\n                    let tup (l : SortKeyLink<'a>) = (l.Width, l.Target)\n                    for l in 0..t.Height-1 do\n                        let (dp, p) = tup t.PrevArray.[l]\n                        let (dn, n) = tup t.NextArray.[l]\n\n                        n.PrevArray.[l] <- SortKeyLink(dp + dn - 1, p)\n                        p.NextArray.[l] <- SortKeyLink(dp + dn - 1, n)\n\n                    let mutable current = t\n                    let mutable distance = 1\n                    for i in t.Height..x.Root.Height-1 do\n                        let back (n : SortKey<'a>) =\n                            let l = n.PrevArray.[n.PrevArray.Length - 1]\n                            (l.Width, l.Target)\n                        // go backwards until a node with sufficient height is found\n                        // or until we've reached the representant\n                        while current.Height <= i && current <> x.Root do\n                            let (d,l) = back current\n                            current <- l\n                            distance <- distance + d\n\n                        let (dn, n) = tup current.NextArray.[i]\n\n                        current.NextArray.[i] <- SortKeyLink(dn - 1, n)\n                        n.PrevArray.[i] <- SortKeyLink(dn - 1, current)\n\n                    // every level (except for 0) on which rep.NextArray.[level] = rep \n                    // is useless and is therefore removed\n                    let rep = x.Root\n                    let mutable repHeight = rep.Height\n                    while repHeight > 1 && rep.NextArray.[repHeight - 1].Target = rep do\n                        repHeight <- repHeight - 1\n\n                    if repHeight < rep.Height then\n                        rep.NextArray <- Array.sub rep.NextArray 0 repHeight\n                        rep.PrevArray <- Array.sub rep.PrevArray 0 repHeight\n        \n                    x.Count <- x.Count - 1\n                    t.IsDeleted <- true\n//                    t.NextArray <- null\n//                    t.PrevArray <- null\n//                    t.Tag <- 0UL\n//                    t.Clock <- Unchecked.defaultof<_>      \n\n            member x.Clear() =\n                let r = SortKey(x, 1)\n                x.Root <- r\n                r.NextArray.[0] <- SortKeyLink(1,r)\n                r.PrevArray.[0] <- SortKeyLink(1,r)\n                x.Count <- 1\n\n            /// gets the n-th time after this one\n            /// NOTE that this only works on representant-nodes\n            member x.TryAt (index : int) =\n\n                let rec search (index : int) (level : int) (t : SortKey<'a>) : Option<SortKey<'a>> =\n                    if level < 0 then\n                        if index = 0 then Some t\n                        else None\n                    else\n                        let link = t.NextArray.[level]\n                        if index < link.Width then\n                            search index (level - 1) t\n                        else\n                            search (index - link.Width) level link.Target\n\n                if index >= 0 && index < x.Count then\n                    search index (x.Root.Height - 1) x.Root\n                else\n                    None\n\n            member x.Item\n                with get (index : int) =\n                    match x.TryAt index with\n                        | Some t -> t \n                        | None -> raise <| IndexOutOfRangeException()\n\n            interface IOrder with\n                member x.Root = x.Root :> ISortKey\n                member x.Count = x.Count\n\n            static member New(cmp) =\n                let c = Order<'a>(cmp)\n                let r = SortKey(c, 1)\n                c.Root <- r\n                r.NextArray.[0] <- SortKeyLink(1,r)\n                r.PrevArray.[0] <- SortKeyLink(1,r)\n                c\n\n            private new(cmp) = { Root = null; Count = 1; Comparer = cmp }\n        end\n\n    let create(cmp) =\n        Order.New(cmp)\n\ntype IReal =\n    inherit IComparable\n    abstract member InsertAfter : unit -> IReal\n\nmodule RealNumber =\n    open System.Threading\n\n    [<AutoOpen>]\n    module private Implementation = \n        type MonitorList() =\n            let acquired = HashSet<obj>()\n\n            member x.Add(o : obj) =\n                if acquired.Add o then\n                    Monitor.Enter o\n\n            member x.Dispose() =\n                for a in acquired do Monitor.Exit a\n\n            interface IDisposable with\n                member x.Dispose() = x.Dispose()\n\n        [<AllowNullLiteral>]\n        type SortKey =\n            class\n                val mutable public RefCount : int\n                val mutable public Root : SortKey\n                val mutable public Tag : uint64\n                val mutable public Next : SortKey\n                val mutable public Prev : SortKey\n\n                member x.Time =\n                    x.Tag - x.Root.Tag\n\n                static member private CompareInternal(l : SortKey, r : SortKey) =\n                    match Monitor.TryEnter(l), Monitor.TryEnter(r) with\n                        | true, true -> \n                            let res = compare l.Time r.Time\n                            Monitor.Exit l\n                            Monitor.Exit r\n                            res\n\n                        | false, true -> \n                            Monitor.Exit r\n                            SortKey.CompareInternal(l, r)\n\n                        | true, false -> \n                            Monitor.Exit l\n                            SortKey.CompareInternal(l, r)\n\n                        | false, false -> \n                            SortKey.CompareInternal(l, r)\n\n                member x.CompareTo (o : SortKey) =\n                    if isNull o.Root || isNull x.Root then\n                        failwith \"cannot compare deleted times\"\n\n                    if o.Root != x.Root then\n                        failwith \"cannot compare times from different clocks\"\n\n                    SortKey.CompareInternal(x, o)\n\n                member t.InsertAfter() =\n                    use l = new MonitorList()\n                    l.Add t\n                    l.Add t.Next\n\n                    let distance (a : SortKey) (b : SortKey) =\n                        if a = b then System.UInt64.MaxValue\n                        else b.Tag - a.Tag\n\n                    let mutable dn = distance t t.Next\n\n                    // if the distance to the next time is 1 (no room)\n                    // relabel all times s.t. the new one can be inserted\n                    if dn = 1UL then\n                        // find a range s.t. distance(range) >= 1 + |range|^2 \n                        let mutable current = t.Next\n                        let mutable j = 1UL\n                        while distance t current < 1UL + j * j do\n                            l.Add current.Next\n                            current <- current.Next\n                            j <- j + 1UL\n\n                        // distribute all times in the range equally spaced\n                        let step = (distance t current) / j\n                        current <- t.Next\n                        let mutable currentTime = t.Tag + step\n                        for k in 1UL..(j-1UL) do\n                            current.Tag <- currentTime\n                            current <- current.Next\n                            currentTime <- currentTime + step\n\n                        // store the distance to the next time\n                        dn <- step\n\n                    // insert the new time with distance (dn / 2) after\n                    // the given one (there has to be enough room now)\n                    let res = SortKey(t.Root, Prev = t, Next = t.Next, Tag = t.Tag + dn / 2UL)\n                    t.Next.Prev <- res\n                    t.Next <- res\n\n                    res\n\n                member x.AddRef() =\n                    Interlocked.Increment(&x.RefCount) |> ignore\n\n                member x.Delete() =\n                    if Interlocked.Decrement(&x.RefCount) = 0 then\n                        lock x (fun () ->\n                            x.Prev.Next <- x.Next\n                            x.Next.Prev <- x.Prev\n                            // x.Next <- null\n                            // x.Prev <- null\n                            x.Root <- null\n                        )\n\n                interface IComparable<ISortKey> with\n                    member x.CompareTo o =\n                        match o with\n                            | :? SortKey as o -> x.CompareTo o\n                            | _ -> failwithf \"cannot compare time with %A\" o\n                            \n\n                interface IComparable with\n                    member x.CompareTo o =\n                        match o with\n                            | :? SortKey as o -> x.CompareTo o\n                            | _ -> failwithf \"cannot compare time with %A\" o\n\n                override x.GetHashCode() = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(x)\n                override x.Equals o = System.Object.ReferenceEquals(x,o)\n\n\n                new(c) = { RefCount = 0; Root = c; Tag = 0UL; Next = null; Prev = null }\n            end\n\n        type GCKey(k : SortKey) =\n            do k.AddRef()\n\n            override x.Finalize() =\n                k.Delete()\n\n            member x.Key = k\n        \n            member x.InsertAfter() = GCKey(k.InsertAfter()) :> IReal\n\n            interface IReal with\n                member x.InsertAfter() = GCKey(k.InsertAfter()) :> IReal\n                member x.CompareTo o =\n                    match o with\n                        | :? GCKey as o -> compare k o.Key\n                        | :? SortKey as o -> compare k o\n                        | _ -> failwith \"cannot compare\"\n\n            override x.ToString() =\n               let value = float k.Time / float UInt64.MaxValue\n               value.ToString(System.Globalization.CultureInfo.InvariantCulture) + \"r\"\n\n            override x.GetHashCode() =\n                k.GetHashCode()\n\n            override x.Equals o =\n                match o with\n                    | :? GCKey as o -> k = o.Key\n                    | _ -> false\n\n    let zero = \n        let root = SortKey(null)\n        root.Root <- root\n        root.Next <- root\n        root.Prev <- root\n\n        GCKey(root) :> IReal\n\n    let after (k : IReal) =\n        k.InsertAfter()\n\n    let between (l : IReal) (r : IReal) =\n        let l = unbox<GCKey> l\n        let r = unbox<GCKey> r\n\n        if l >= r then\n            failwith \"[GCKey] negative range given\"\n\n        use locks = new MonitorList()\n        locks.Add l\n        locks.Add r\n\n        if l.Key.Next == r.Key then\n            l.InsertAfter()\n\n        elif l.Key.Next < r.Key then\n            GCKey(l.Key.Next) :> IReal\n\n        else\n            failwith \"[GCKey] illformed range given\"\n\n[<CustomEquality; CustomComparison>]\ntype private SortKeyTuple =\n    struct\n        val mutable public K0 : ISortKey\n        val mutable public K1 : ISortKey\n\n        interface IComparable with\n            member x.CompareTo o =\n                match o with\n                    | :? SortKeyTuple as o ->\n                        let c = compare x.K0 o.K0\n                        if c <> 0 then c\n                        else compare x.K1 o.K1\n                    | _ ->\n                        failwith \"uncomparable\"\n\n        override x.GetHashCode() =\n            HashCode.Combine(x.K0.GetHashCode(), x.K1.GetHashCode())\n\n        override x.Equals o =\n            match o with\n                | :? SortKeyTuple as o -> x.K0 = o.K0 && x.K1 = o.K1\n                | _ -> false\n\n        interface IDeletableComparable with\n            member x.IsDeleted = \n                (not (isNull x.K0) && x.K0.IsDeleted) || (not (isNull x.K1) && x.K1.IsDeleted)\n\n        new(k0, k1) = { K0 = k0; K1 = k1 }\n\n    end\n\ntype OrderMaintenance<'a when 'a : equality>(comparer : IComparer<'a>) =\n    let derived = DerivedOrder.create(comparer)\n    let nodes = Dictionary<'a, DerivedOrder.SortKey<'a>>()\n\n    member x.Count = derived.Count\n\n    member x.Order = derived :> IOrder\n\n    member x.Root = derived.Root :> ISortKey\n\n    member x.Clear() =\n        derived.Clear()\n        nodes.Clear()\n\n    member x.Invoke(t : 'a) =\n        let res = derived.Get t\n        nodes.[t] <- res\n        res :> ISortKey\n\n    member x.TryGet(t : 'a) =\n        match nodes.TryGetValue t with\n            | (true,v) -> Some (v :> ISortKey)\n            | _ -> None\n\n    member x.Revoke(t : 'a) =\n        match nodes.TryGetValue t with\n            | (true, d) ->\n                derived.Delete d\n                d :> ISortKey\n            | _ ->\n                failwith \"cannot delete unknown time\"\n\n    new() = OrderMaintenance(Comparer<'a>.Default)\n    new(cmp : 'a -> 'a -> int) = OrderMaintenance { new IComparer<'a> with member x.Compare(l,r) = cmp l r }\n\ntype OrderMapping() =\n    inherit OrderMaintenance<ISortKey>()\n\ntype NestedOrderMapping() =\n    let derived = DerivedOrder.create(Comparer<SortKeyTuple>.Default)\n    let nodes = Dictionary<SortKeyTuple, DerivedOrder.SortKey<SortKeyTuple>>()\n\n    member x.Order = derived :> IOrder\n\n    member x.Count = derived.Count\n\n    member x.Root = derived.Root :> ISortKey\n\n    member x.Clear() =\n        derived.Clear()\n        nodes.Clear()\n\n    member x.Invoke(outer : ISortKey, inner : ISortKey) =\n        let tup = SortKeyTuple(outer,inner)\n        let res = derived.Get tup\n        nodes.[tup] <- res\n        res :> ISortKey\n\n    member inline private x.Revoke(tup : SortKeyTuple) =\n        match nodes.TryGetValue tup with\n            | (true, d) ->\n                derived.Delete d\n                d :> ISortKey\n            | _ ->\n                failwith \"cannot delete unknown time\"\n\n    member x.Revoke(outer : ISortKey, inner : ISortKey) =\n        let tup = SortKeyTuple(outer,inner)\n        x.Revoke(tup)\n\n    member x.RevokeAll(outer : ISortKey) =\n        let all = nodes.Keys |> Seq.filter (fun tup -> tup.K0 = outer) |> Seq.toList\n        all |> List.map x.Revoke\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Mutable/OrderMaintenanceTrie.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen Aardvark.Base\nopen System.Collections.Generic\nopen FSharp.Data.Adaptive\n\n#nowarn \"1336\"\n\n[<AllowNullLiteral>]\ntype TrieReference<'k, 'a> =\n    abstract member Key : list<'k>\n    abstract member Prev : voption<TrieReference<'k, 'a>>\n    abstract member Next : voption<TrieReference<'k, 'a>>\n    abstract member Value : 'a with get, set\n\n[<CompilerMessage(\"for internal use only\", 1336, IsHidden = true)>]\nmodule OrderMaintenanceTrieImplementation = \n    [<AllowNullLiteral>]\n    type Linked<'s when 's :> Linked<'s> and 's : null> =\n        abstract member Prev : 's with get, set\n        abstract member Next : 's with get, set\n\n        \n    [<AllowNullLiteral>]\n    type IOrderedDict<'k, 'v when 'v :> Linked<'v> and 'v : null> =\n        abstract member Keys : seq<'k>\n        abstract member TryRemove : key : 'k -> voption<'v>\n        abstract member TryGet : key : 'k -> voption<'v>\n        abstract member GetOrCreate : key : 'k * create : ('k -> 'v -> 'v -> 'v) -> 'v\n        abstract member First : 'v\n        abstract member Last : 'v\n        \n    [<AllowNullLiteral>]\n    type UnorderedDict<'k, 'v when 'v :> Linked<'v> and 'v : null>() =\n        let mutable first : 'v = null\n        let mutable last : 'v = null\n        let store = Dict<'k, 'v>()\n\n        member x.GetOrCreate(key : 'k, create : 'k -> 'v -> 'v -> 'v) =\n            store.GetOrCreate(key, fun k ->\n                let n = create k last null\n                if isNull last then first <- n\n                else last.Next <- n\n                last <- n\n                n\n            )\n\n        member x.TryRemove(key : 'k) =\n            match store.TryRemove key with\n            | (true, node) ->\n                if isNull node.Prev then first <- node.Next\n                else node.Prev.Next <- node.Next\n\n                if isNull node.Next then last <- node.Prev\n                else node.Next.Prev <- node.Prev\n\n                node.Prev <- null\n                node.Next <- null\n\n                ValueSome node\n            | _ ->\n                ValueNone\n        \n        member x.TryGet(key : 'k) =\n            match store.TryGetValue key with\n            | (true, node) -> ValueSome node\n            | _ -> ValueNone\n\n        interface IOrderedDict<'k, 'v> with\n            member x.Keys = store.Keys\n            member x.First = first\n            member x.Last = last\n            member x.GetOrCreate(key, create) = x.GetOrCreate(key, create)\n            member x.TryRemove(key) = x.TryRemove(key)\n            member x.TryGet(key) = x.TryGet(key)\n        \n    [<AllowNullLiteral>]\n    type OrderedDict<'k, 'v when 'v :> Linked<'v> and 'v : null>(cmp : IComparer<'k>) =\n        let mutable first : 'v = null\n        let mutable last : 'v = null\n\n        static let vo (o : Optional<struct('k * 'v)>) =\n            if o.HasValue then\n                let struct(_, v) = o.Value\n                v\n            else\n                null\n\n\n        let store = \n            SortedSetExt<struct ('k * 'v)> { \n                new IComparer<struct ('k * 'v)> with\n                    member x.Compare((struct(lk,_)), (struct(rk, _))) = cmp.Compare(lk, rk)\n            }\n\n        member x.GetOrCreate(key : 'k, create : 'k -> 'v -> 'v -> 'v) =\n            let l, s, r = store.FindNeighbours(struct (key, null))\n\n            if s.HasValue then\n                let struct(_,v) = s.Value\n                v\n            else\n                let l = vo l\n                let r = vo r\n                let node = create key l r\n                store.Add(struct(key, node)) |> ignore\n\n                if isNull l then first <- node\n                else l.Next <- node\n\n                if isNull r then last <- node\n                else r.Prev <- node\n\n                node\n\n        member x.TryRemove(key : 'k) =\n            let _, s, _ = store.FindNeighbours(struct (key, null))\n\n            if s.HasValue then\n                let struct (_, node) = s.Value\n                store.Remove(struct (key, node)) |> ignore\n                let l = node.Prev\n                let r = node.Next\n\n                if isNull l then first <- r\n                else l.Next <- r\n\n                if isNull r then last <- l\n                else r.Prev <- l\n\n                node.Prev <- null\n                node.Next <- null\n\n                ValueSome node\n            else\n                ValueNone\n        \n        member x.TryGet(key : 'k) =\n            let _, s, _ = store.FindNeighbours(struct (key, null))\n            if s.HasValue then\n                let struct (_, node) = s.Value\n                ValueSome node\n            else\n                ValueNone\n\n        interface IOrderedDict<'k, 'v> with\n            member x.Keys = store |> Seq.map (fun struct (k,_) -> k)\n            member x.First = first\n            member x.Last = last\n            member x.GetOrCreate(key, create) = x.GetOrCreate(key, create)\n            member x.TryRemove(key) = x.TryRemove(key)\n            member x.TryGet(key) = x.TryGet(key)\n\n    module OrderedDict =\n        let ofComparer (cmp : option<System.Collections.Generic.IComparer<'k>>) =\n            match cmp with\n            | None ->\n                UnorderedDict<'k, 'v>() :> IOrderedDict<_,_>\n            | Some cmp ->\n                OrderedDict<'k, 'v>(cmp) :> IOrderedDict<_,_>\n \n    [<AllowNullLiteral>]\n    type OrderMaintenanceTrieNode<'k, 'a> =\n        val mutable public GetComparer : int -> option<IComparer<'k>>\n        val mutable public Level : int\n        val mutable public Path : list<'k>\n        val mutable public ChildrenDict : IOrderedDict<'k, OrderMaintenanceTrieNode<'k, 'a>>\n        val mutable public Value : ValueOption<'a>\n    \n        val mutable public Parent : OrderMaintenanceTrieNode<'k, 'a>\n        val mutable public Prev : OrderMaintenanceTrieNode<'k, 'a>\n        val mutable public Next : OrderMaintenanceTrieNode<'k, 'a>\n\n        member private x.AfterLast() =\n            if isNull x.Next then \n                if isNull x.Parent then ValueNone\n                else x.Parent.AfterLast()\n            else\n                x.Next.First\n\n        interface Linked<OrderMaintenanceTrieNode<'k, 'a>> with\n            member x.Prev\n                with get() = x.Prev\n                and set p = x.Prev <- p\n            member x.Next\n                with get() = x.Next\n                and set p = x.Next <- p\n\n        interface TrieReference<'k, 'a> with\n            member x.Key = List.rev x.Path\n            member x.Prev =\n                if isNull x.Prev then\n                    if isNull x.Parent then\n                        ValueNone\n                    elif ValueOption.isSome x.Parent.Value then\n                        ValueSome (x.Parent :> TrieReference<_,_>)\n                    else\n                        (x.Parent :> TrieReference<_,_>).Prev\n                else\n                    x.Prev.Last\n            member x.Next =\n                if isNull x.ChildrenDict || isNull x.ChildrenDict.First then\n                    if isNull x.Next then \n                        if isNull x.Parent then ValueNone\n                        else x.Parent.AfterLast()\n                    else \n                        x.Next.First\n                else\n                    x.ChildrenDict.First.First\n\n            member x.Value\n                with get() = match x.Value with | ValueSome v -> v | _ -> failwith \"bad\"\n                and set v = x.Value <- ValueSome v\n\n        member x.Last : voption<TrieReference<'k, 'a>> =\n            if isNull x.ChildrenDict || isNull x.ChildrenDict.Last then\n                match x.Value with\n                | ValueSome _ -> ValueSome (x :> TrieReference<_,_>)\n                | ValueNone -> \n                    if isNull x.Prev then ValueNone\n                    else x.Prev.Last\n            else\n                x.ChildrenDict.Last.Last\n\n        member x.First : voption<TrieReference<'k, 'a>> = \n            match x.Value with\n            | ValueSome _ ->\n                ValueSome (x :> TrieReference<_,_>)\n            | ValueNone ->\n                if isNull x.ChildrenDict || isNull x.ChildrenDict.First then\n                    if isNull x.Next then ValueNone\n                    else x.Next.First\n                else\n                    x.ChildrenDict.First.First\n\n        member x.IsEmpty =\n            ValueOption.isNone x.Value && (isNull x.ChildrenDict || isNull x.ChildrenDict.First)\n\n        member x.TryRemove(k : list<'k>) =\n            match k with\n            | [] ->\n                match x.Value with\n                | ValueSome _ -> \n                    let r = x :> TrieReference<_,_>\n                    let p = r.Prev\n                    let n = r.Next\n                    x.Value <- ValueNone\n                    ValueSome (p, n)\n                | ValueNone ->\n                    ValueNone\n            | h :: t ->\n                if isNull x.ChildrenDict then\n                    ValueNone\n                else\n                    match x.ChildrenDict.TryGet h with\n                    | ValueSome c ->\n                        match c.TryRemove t with\n                        | ValueSome (prev,next) ->\n                            if c.IsEmpty then\n                                x.ChildrenDict.TryRemove h |> ignore\n                    \n                            ValueSome(prev,next)\n                        | _ ->\n                            ValueNone\n                    | _ ->\n                        ValueNone\n\n        member x.Add(k : list<'k>, value : 'a) =\n            match k with\n            | [] ->\n                x.Value <- ValueSome value\n                x :> TrieReference<_,_>\n            | h :: t ->\n                let children = \n                    if isNull x.ChildrenDict then \n                        let d = OrderedDict.ofComparer (x.GetComparer (x.Level + 1))\n                        x.ChildrenDict <- d\n                        d\n                    else \n                        x.ChildrenDict\n                    \n                let node = \n                    children.GetOrCreate(h, fun k l r ->\n                        let n = OrderMaintenanceTrieNode<'k, 'a>(x.GetComparer, x.Level + 1, k :: x.Path)\n                        n.Prev <- l\n                        n.Next <- r\n                        n.Parent <- x\n                        n\n                    )\n                node.Add(t, value)\n            \n        member x.AddOrUpdate(k : list<'k>, create : voption<'a> -> 'a) =\n            match k with\n            | [] ->\n                x.Value <- ValueSome (create x.Value)\n                x :> TrieReference<_,_>\n            | h :: t ->\n                let children = \n                    if isNull x.ChildrenDict then \n                        let d = OrderedDict.ofComparer (x.GetComparer (x.Level + 1))\n                        x.ChildrenDict <- d\n                        d\n                    else \n                        x.ChildrenDict\n                let node = \n                    children.GetOrCreate(h, fun k l r ->\n                        let n = OrderMaintenanceTrieNode<'k, 'a>(x.GetComparer, x.Level + 1, k :: x.Path)\n                        n.Prev <- l\n                        n.Next <- r\n                        n.Parent <- x\n                        n\n                    )\n                node.AddOrUpdate(t, create)\n\n        member x.Alter(k : list<'k>, update : voption<'a> -> voption<'a>) =\n            match k with\n            | [] ->\n                x.Value <- update x.Value\n                match x.Value with\n                | ValueSome _ ->\n                    ValueSome (x :> TrieReference<_,_>)\n                | _ ->\n                    ValueNone\n            | h :: t ->\n                if isNull x.ChildrenDict then\n                    match update ValueNone with\n                    | ValueNone ->\n                        ValueNone\n                    | ValueSome v ->\n                        x.Add(h :: t, v) |> ValueSome\n                else\n                    match x.ChildrenDict.TryGet h with\n                    | ValueSome c ->\n                        let res = c.Alter(t, update)\n                        match res with\n                        | ValueNone ->  \n                            if c.IsEmpty then\n                                x.ChildrenDict.TryRemove h |> ignore\n                        | _ ->\n                            ()\n                        res\n                    | ValueNone ->\n                        match update ValueNone with\n                        | ValueNone ->\n                            ValueNone\n                        | ValueSome v ->\n                            x.Add(h :: t, v) |> ValueSome\n           \n\n        member x.Iter (action : list<'k> -> 'a -> unit) =\n            match x.Value with\n            | ValueSome v -> action (List.rev x.Path) v\n            | ValueNone -> ()\n\n            if not (isNull x.ChildrenDict) then\n            \n                let mutable c = x.ChildrenDict.First\n                while not (isNull c) do\n                    c.Iter action\n                    c <- c.Next\n\n        member x.TryGetValue (key : list<'k>) =\n            match key with\n            | [] ->\n                x.Value\n            | h :: t ->\n                if isNull x.ChildrenDict then\n                    ValueNone\n                else\n                    match x.ChildrenDict.TryGet(h) with\n                    | ValueSome c -> c.TryGetValue t\n                    | ValueNone -> ValueNone\n                    \n        member x.TryGetReference(key : list<'k>) =\n            match key with\n            | [] ->\n                match x.Value with\n                | ValueSome _ -> ValueSome (x :> TrieReference<_,_>)\n                | ValueNone -> ValueNone\n            | h :: t ->\n                if isNull x.ChildrenDict then\n                    ValueNone\n                else\n                    match x.ChildrenDict.TryGet(h) with\n                    | ValueSome c -> c.TryGetReference t\n                    | ValueNone -> ValueNone\n\n        member x.ContainsKey (key : list<'k>) =\n            match key with\n            | [] ->\n                ValueOption.isSome x.Value\n            | h :: t ->\n                if isNull x.ChildrenDict then\n                    false\n                else\n                    match x.ChildrenDict.TryGet(h) with\n                    | ValueSome c -> c.ContainsKey t\n                    | ValueNone -> false\n            \n\n        new(getComparer : int -> option<IComparer<'k>>, l : int, ks : list<'k>) = \n            { \n                GetComparer = getComparer; Level = l\n                Path = ks\n                ChildrenDict = null //OrderedDict.ofComparer (getComparer (l + 1))\n                Value = ValueNone\n                Parent = null\n                Prev = null; Next = null\n            }\n\n    type TrieReferenceForwardEnumerator<'k, 'v>(initial : unit -> voption<TrieReference<'k, 'v>>) =\n        let mutable initial = initial\n        let mutable started = false\n        let mutable current : TrieReference<'k, 'v> = null\n\n        member x.MoveNext() =\n            if not started then\n                started <- true\n                match initial() with\n                | ValueSome initial ->\n                    current <- initial\n                    true\n                | ValueNone ->\n                    false\n            elif not (isNull current) then\n                match current.Next with\n                | ValueSome n ->\n                    current <- n\n                    true\n                | ValueNone ->\n                    current <- null\n                    false\n            else\n                false\n               \n        member x.Reset() =\n            started <- false\n            current <- null\n\n        member x.Dispose() =\n            started <- false \n            current <- null\n            initial <- fun _ -> ValueNone\n\n        member x.Current =\n            current.Key, current.Value\n            \n        interface System.Collections.IEnumerator with\n            member x.MoveNext() = x.MoveNext()\n            member x.Reset() = x.Reset()\n            member x.Current = x.Current :> obj\n\n        interface IEnumerator<list<'k> * 'v> with\n            member x.Dispose() = x.Dispose()\n            member x.Current = x.Current\n \nopen OrderMaintenanceTrieImplementation\n\ntype OrderMaintenanceTrie<'k, 'a>(getComparer : int -> option<IComparer<'k>>) =\n    let comparerCache = IntDict<option<IComparer<'k>>>()\n    let getCachedComparer level = comparerCache.GetOrCreate(level, System.Func<_,_>(getComparer))\n    let mutable root = OrderMaintenanceTrieNode<'k, 'a>(getCachedComparer, -1, [])\n\n    member x.IsEmpty = \n        root.IsEmpty\n\n    member x.Set (key : list<'k>, value : 'a) =\n        root.Add(key, value)\n\n    member x.Iter (action : list<'k> -> 'a -> unit) =\n        root.Iter(action)\n\n    member x.TryRemove(key : list<'k>) =\n        root.TryRemove key\n\n    member x.AddOrUpdate(key : list<'k>, create : voption<'a> -> 'a) =\n        root.AddOrUpdate(key, create)\n        \n    member x.Alter(key : list<'k>, update : voption<'a> -> voption<'a>) =\n        root.Alter(key, update)\n\n    member x.TryGetValue (key : list<'k>) =\n        root.TryGetValue key\n                    \n    member x.TryGetReference(key : list<'k>) =\n        root.TryGetReference key\n\n    member x.ContainsKey (key : list<'k>) =\n        root.ContainsKey key\n\n    member x.Clear() =\n        root <- OrderMaintenanceTrieNode<'k, 'a>(getCachedComparer, 0, [])\n\n    member x.Root = root\n    member x.First = root.First\n    member x.Last = root.Last\n\n    interface System.Collections.IEnumerable with\n        member x.GetEnumerator() = new TrieReferenceForwardEnumerator<_,_>(fun () -> x.First) :> _\n        \n    interface IEnumerable<list<'k> * 'a> with\n        member x.GetEnumerator() = new TrieReferenceForwardEnumerator<_,_>(fun () -> x.First) :> _\n\n    new() = \n        OrderMaintenanceTrie(fun _ -> None)\n\n    new(cmp : IComparer<'k>) = \n        let res = Some cmp\n        OrderMaintenanceTrie(fun _ -> res)\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Mutable/ReferenceCountingSet.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System.Collections\nopen System.Collections.Generic\nopen System.Threading\nopen FSharp.Data.Adaptive\n\n/// <summary>\n/// represents a set of elements having a reference count.\n/// this means that an element is contained when it has been\n/// added at least once more than removed.\n/// </summary>\ntype ReferenceCountingSet<'a>(initial : seq<'a>) =\n    let mutable nullCount = 0\n    let mutable version = 0\n    let mutable store = Dictionary<obj, struct('a * ref<int>)>(1)\n\n    let hasChanged() =\n        Interlocked.Increment &version |> ignore\n\n    let toCollection (s : seq<'a>) =\n        match s with\n            | :? ICollection<'a> as s -> s\n            | _ -> System.Collections.Generic.HashSet s :> ICollection<_>\n\n    let compareSeq (other : seq<'a>) =\n        let distinctOther = toCollection other\n\n        let mutable both = 0\n        let mutable onlyMe = 0\n\n        for (o,_) in store.Values do\n            if distinctOther.Contains o then\n                both <- both + 1\n            else\n                onlyMe <- onlyMe + 1\n\n        let onlyOther = distinctOther.Count - both\n\n        (both, onlyMe, onlyOther)\n\n\n    let add (v : 'a) =\n        if isNull (v :> obj) then\n            nullCount <- nullCount + 1\n            nullCount = 1\n        else\n            match store.TryGetValue v with\n            | (true, (_,r)) ->\n                r := !r + 1\n                false\n            | _ ->\n                let r = struct(v, ref 1)\n                store.[v] <- r\n                hasChanged()\n                true\n\n    let remove (v : 'a) =\n        if isNull (v :> obj) then\n            nullCount <- nullCount - 1\n            nullCount = 0\n        else\n            match store.TryGetValue v with\n            | (true, (_,r)) ->\n                r := !r - 1\n                if !r = 0 then\n                    hasChanged()\n                    store.Remove v\n                else\n                    false\n            | _ ->\n                false\n\n    do for e in initial do\n        add e |> ignore\n\n    member private x.Version = version\n    member private x.Store = store\n    member private x.NullCount = nullCount\n\n\n    member internal x.SetTo(other : ReferenceCountingSet<'a>) =\n        nullCount <- other.NullCount\n        version <- other.Version\n\n        store <- Dictionary(other.Store.Count)\n        for (KeyValue(k,(v,r))) in other.Store do\n            store.[k] <- (v, ref !r)\n\n    member internal x.Apply(deltas : list<SetOperation<'a>>) =\n        match deltas with\n        | [] -> []\n        | [v] ->\n            match v with\n                | Add(_,v) ->\n                    if x.Add v then [Add v]\n                    else []\n                | Rem(_,v) ->\n                    if x.Remove v then [Rem v]\n                    else []\n\n        | _ ->\n            let mutable originalNullRefs = nullCount\n            let touched = Dictionary<obj, 'a * bool * ref<int>>()\n            for d in deltas do\n                match d with\n                | Add(_,v) ->\n                    let o = v :> obj\n                    if isNull o then\n                        nullCount <- nullCount + 1\n                    else\n                        match store.TryGetValue o with\n                        | (true, (_,r)) ->\n                            r := !r + 1\n                        | _ ->\n                            let r = ref 1\n                            touched.[o] <- (v, false, r)\n                            store.[o] <- (v, r)\n                | Rem(_, v) ->\n                    let o = v :> obj\n                    if isNull o then\n                        nullCount <- nullCount - 1\n                    else\n                        match store.TryGetValue o with\n                        | (true, (_,r)) ->\n                            r := !r - 1\n                            if !r = 0 && not (touched.ContainsKey o) then\n                                touched.[o] <- (v, true, r)\n                        | _ ->\n                            let r = ref -1\n                            touched.[o] <- (v, false, r)\n                            store.[o] <- (v, r)\n\n                    ()\n\n            let valueDeltas =\n                touched.Values\n                    |> Seq.choose (fun (value, wasContained, refCount) ->\n                        let r = !refCount\n                        if r > 0 then\n                            if wasContained then None\n                            else Some (Add value)\n                        else\n                            store.Remove value |> ignore\n                            if wasContained then Some (Rem value)\n                            else None\n                        )\n                    |> Seq.toList\n\n            let result =\n                if nullCount = 0 && originalNullRefs > 0 then\n                    (Rem Unchecked.defaultof<_>)::valueDeltas\n                elif nullCount > 0 && originalNullRefs = 0 then\n                    (Add Unchecked.defaultof<_>)::valueDeltas\n                else\n                    valueDeltas\n\n            if not (List.isEmpty result) then\n                hasChanged()\n\n            result\n\n    /// <summary>\n    /// adds an element to the ReferenceCountingSet and returns\n    /// true if the element was not contained in the set before\n    /// this operation.\n    /// </summary>\n    member x.Add (v : 'a) = add v\n\n    /// <summary>\n    /// removes an element from the ReferenceCountingSet and returns\n    /// true if the element is no longer contained after the operation.\n    /// </summary>\n    member x.Remove(v : 'a) = remove v\n\n    /// <summary>\n    /// checks if the set contains a specific element\n    /// </summary>\n    member x.Contains (v : 'a) =\n        if isNull (v :> obj) then\n            nullCount > 0\n        else\n            store.ContainsKey v\n\n    /// <summary>\n    /// clears the entire set\n    /// </summary>\n    member x.Clear() =\n        if x.Count <> 0 then\n            nullCount <- 0\n            store.Clear()\n            hasChanged()\n\n    /// <summary>\n    /// returns the number of (distinct) elements contained in\n    /// the set.\n    /// </summary>\n    member x.Count =\n        (if nullCount > 0 then 1 else 0) + store.Count\n\n    /// <summary>\n    /// gets the current reference count for the given element\n    /// </summary>\n    member x.GetReferenceCount(v) =\n        if isNull (v :> obj) then nullCount\n        else\n            match store.TryGetValue (v :> obj) with\n                | (true, (_,c)) -> !c\n                | _ -> 0\n\n    /// <summary>\n    /// Remove items in other from this set. Modifies this set.\n    /// </summary>\n    member x.ExceptWith (items : seq<'a>) =\n        for o in items do\n            x.Remove o |> ignore\n\n    /// <summary>\n    /// Take the union of this set with other. Modifies this set.\n    /// </summary>\n    member x.UnionWith (other : seq<'a>) =\n        for o in other do\n            x.Add o |> ignore\n\n    /// <summary>\n    /// Takes the intersection of this set with other. Modifies this set.\n    /// </summary>\n    member x.IntersectWith (other : seq<'a>) =\n        let other = toCollection other\n        for (v,_) in store.Values do\n            if not <| other.Contains v then\n                x.Remove v |> ignore\n\n    /// <summary>\n    /// Takes symmetric difference (XOR) with other and this set. Modifies this set.\n    /// </summary>\n    member x.SymmetricExceptWith (other : seq<'a>) =\n        for o in other do\n            if not <| x.Remove o then\n                x.Add o |> ignore\n\n    /// <summary>\n    /// determines if the set is a subset of the given sequence\n    /// </summary>\n    member x.IsSubsetOf (other : seq<'a>) =\n        match compareSeq other with\n            | (_, 0, _) -> true\n            | _ -> false\n\n    /// <summary>\n    /// determines if the set is a superset of the given sequence\n    /// </summary>\n    member x.IsSupersetOf (other : seq<'a>) =\n        match compareSeq other with\n            | (_, _, 0) -> true\n            | _ -> false\n\n    /// <summary>\n    /// determines if the set is a proper subset of the given sequence\n    /// </summary>\n    member x.IsProperSubsetOf (other : seq<'a>) =\n        match compareSeq other with\n            | (_, 0, o) -> o > 0\n            | _ -> false\n\n    /// <summary>\n    /// determines if the set is a proper superset of the given sequence\n    /// </summary>\n    member x.IsProperSupersetOf (other : seq<'a>) =\n        match compareSeq other with\n            | (_, m, 0) -> m > 0\n            | _ -> false\n\n    /// <summary>\n    /// determines if the set and the given sequence overlap\n    /// </summary>\n    member x.Overlaps (other : seq<'a>) =\n        let (b,_,_) = compareSeq other\n        b > 0\n\n    /// <summary>\n    /// determines if the set is equal (set) to the given sequence\n    /// </summary>\n    member x.SetEquals (other : seq<'a>) =\n        match compareSeq other with\n            | (_,0,0) -> true\n            | _ -> false\n\n\n    new() = ReferenceCountingSet Seq.empty\n\n    interface ICollection<'a> with\n        member x.Add v = x.Add v |> ignore\n        member x.Remove v = x.Remove v\n        member x.Clear() = x.Clear()\n        member x.Count = x.Count\n        member x.CopyTo(arr, index) =\n            let mutable i = index\n\n            if nullCount > 0 then\n                arr.[i] <- Unchecked.defaultof<_>\n                i <- i + 1\n\n            for e in x do\n                arr.[i] <- e\n                i <- i + 1\n\n        member x.IsReadOnly = false\n        member x.Contains v = store.ContainsKey v\n\n    interface ISet<'a> with\n        member x.Add item = x.Add item\n        member x.ExceptWith other = x.ExceptWith other\n        member x.IntersectWith other = x.IntersectWith other\n        member x.UnionWith other = x.UnionWith other\n        member x.SymmetricExceptWith other = x.SymmetricExceptWith other\n\n        member x.IsProperSubsetOf other = x.IsProperSubsetOf other\n        member x.IsProperSupersetOf other = x.IsProperSupersetOf other\n        member x.IsSubsetOf other = x.IsSubsetOf other\n        member x.IsSupersetOf other = x.IsSupersetOf other\n        member x.Overlaps other = x.Overlaps other\n        member x.SetEquals other = x.SetEquals other\n\n    member x.GetEnumerator() = new ReferenceCountingSetEnumerator<'a>(nullCount > 0, store)\n\n    interface IEnumerable with\n        member x.GetEnumerator() =\n            new ReferenceCountingSetEnumerator<'a>(nullCount > 0, store) :> IEnumerator\n\n    interface IEnumerable<'a> with\n        member x.GetEnumerator() =\n            new ReferenceCountingSetEnumerator<'a>(nullCount > 0, store) :> IEnumerator<'a>\n\n// define an Enumerator enumerating all (distinct) elements in the set\nand ReferenceCountingSetEnumerator<'a> =\n    struct \n        val mutable private containsNull : bool\n        val mutable private emitNull : bool\n        val mutable private currentIsNull : bool\n        val mutable private e : Dictionary<obj, struct('a * ref<int>)>.Enumerator\n\n        member x.Current =\n            if x.currentIsNull then\n                Unchecked.defaultof<_>\n            else\n                x.e.Current.Value |> fstv\n\n        member x.MoveNext() =\n            if x.emitNull then\n                x.emitNull <- false\n                x.currentIsNull <- true\n                true\n            else\n                x.currentIsNull <- false\n                x.e.MoveNext()\n\n        interface IEnumerator with\n            member x.MoveNext() = \n                x.MoveNext()\n\n            member x.Reset() =\n                x.emitNull <- x.containsNull\n                (x.e :> IEnumerator).Reset()\n\n            member x.Current = x.Current :> obj\n\n        interface IEnumerator<'a> with\n            member x.Current = x.Current\n            member x.Dispose() = x.e.Dispose()\n\n        internal new(containsNull : bool, store : Dictionary<obj, struct('a * ref<int>)>) =\n            {\n                containsNull = containsNull\n                emitNull = containsNull\n                currentIsNull = false\n                e = store.GetEnumerator()\n            }\n\n    end\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Mutable/SkipList.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\n\n[<AllowNullLiteral>]\ntype private Node<'a>(value : 'a, height : int) =\n    let mutable height = height\n    let mutable next : Link<'a>[] = Array.zeroCreate height\n\n    member x.Height = height\n    member x.Next = next\n    member x.Value = value\n\n    member x.Resize(h : int) =\n        if h < height then\n            failwith \"cannot shrink node\"\n        else\n            let newNext = Array.zeroCreate h\n            for i in 0..height-1 do\n                newNext.[i] <- next.[i]\n            next <- newNext\n\nand private Link<'a> =\n    struct \n        val mutable public Target : Node<'a>\n        val mutable public Width : int\n\n        new(target, w) = { Target = target; Width = w }\n    end\n\ntype SkipList<'a>(cmp : 'a -> 'a -> int) =\n    let mutable root : Link<'a>[] = Array.zeroCreate 0\n    let mutable count = 0\n    static let random = Random()\n\n    static let resize (height : int) (root : byref<Link<'a>[]>) =\n        if height > root.Length then\n            let newRoot = Array.zeroCreate height\n            for i in 0..root.Length-1 do\n                newRoot.[i] <- root.[i]\n            root <- newRoot\n\n    static let randomHeight() =\n        let mutable height = 1\n        while random.NextDouble() < 0.5 do\n            height <- height + 1\n        height\n\n    static let newNode (v : 'a) =\n        Node(v, randomHeight())\n\n    static let rec findPrev (acc : list<_>) (cmp : 'a -> 'a -> int) (index : int) (level : int) (v : 'a) (n : Node<'a>) (links : Link<'a>[]) =\n        if level < 0 then \n            (index, acc)\n        else\n            let link = links.[level]\n\n            let vCmp = \n                if isNull link.Target then -1\n                else cmp v link.Target.Value\n\n            if vCmp <= 0 then\n                findPrev ((index, n)::acc) cmp index (level - 1) v n links\n            else\n                let t = links.[level].Target\n\n                findPrev acc cmp (index + link.Width) level v t t.Next\n\n    static let rec findPrevIndex (acc : list<_>) (currentIndex : int) (level : int) (id : int) (n : Node<'a>) (links : Link<'a>[]) =\n        if level < 0 then \n            (currentIndex, acc)\n        else\n            let link = links.[level]\n\n            let vCmp = \n                if isNull link.Target then -1\n                else compare id (currentIndex + link.Width)//link.Target.Value\n\n            if vCmp <= 0 then\n                findPrevIndex ((currentIndex, n)::acc) currentIndex (level - 1) id n links\n            else\n                let t = links.[level].Target\n                findPrevIndex acc (currentIndex + link.Width) level id t t.Next\n\n    let print (l : SkipList<'a>) =\n        let rec cnt (n : Node<'a>) =\n            if isNull n then 1\n            else 1 + cnt n.Next.[0].Target\n\n        let rec dist (l : Node<'a>) (r : Node<'a>) =\n            if l = r then 0\n            else 1 + dist (l.Next.[0].Target) r\n\n        let h = root.Length\n        let w = cnt root.[0].Target\n        let arr = Array2D.create (w + 2) (h + 2) \" \"\n\n        for y in 0..h-1 do\n            let mutable current = root.[y].Target\n            let mutable x = root.[y].Width\n            while not (isNull current) do\n\n                arr.[x,y] <- sprintf \"%A\" current.Value\n\n                let next = current.Next.[y].Target\n                x <- x + dist current next\n                current <- next\n\n        for y in 1..h do\n            for x in 0..w-1 do\n                printf \"%s \" arr.[x,h - y]\n            printfn \"\"\n\n    let removePtr (prev : list<int * Node<'a>>) (n : Node<'a>)  =\n        let mutable level = 0\n        for (id,p) in prev do\n            let prevNext = if not (isNull p) then p.Next else root\n            let leftLink = prevNext.[level]\n            if level < n.Height then\n                let rightLink = n.Next.[level]\n                prevNext.[level] <- Link(rightLink.Target, leftLink.Width + rightLink.Width - 1)\n            else\n                prevNext.[level] <- Link(leftLink.Target, leftLink.Width - 1)\n\n            level <- level + 1\n\n        count <- count - 1\n\n    let toSeq() =\n        let rec toSeq (n : Node<'a>) =\n            if isNull n then \n                Seq.empty\n            else\n                seq {\n                    yield n.Value\n                    yield! toSeq n.Next.[0].Target\n                }\n        if root.Length > 0 then\n            toSeq root.[0].Target\n        else\n            Seq.empty\n\n\n    member x.Add (v : 'a) =\n        if root.Length <> 0 then\n            // create a new node with random height\n            let n = newNode v\n\n            // resize the root if necessary\n            resize n.Height &root\n\n            let height = root.Length\n            let (index, prev) = findPrev [] cmp 0 (height - 1) v null root\n\n            let (_,p) = prev |> List.head\n            let on = \n                if isNull p then root.[0].Target \n                else p.Next.[0].Target\n\n            if not (isNull on) && cmp on.Value v = 0 then\n                false\n            else\n                let fi = index + 1\n\n                let mutable level = 0\n                for (id,p) in prev do\n                    let prevNext = if not (isNull p) then p.Next else root\n                    let l = prevNext.[level]\n\n                    if level < n.Height then\n                        let ti = id + l.Width\n                        let si = id\n                        //ti - si\n                        prevNext.[level] <- Link(n, fi - si)\n                        n.Next.[level] <- Link(l.Target, 1 + ti - fi)\n                    else\n                        prevNext.[level] <- Link(l.Target, l.Width + 1)\n\n                    level <- level + 1\n\n                count <- count + 1\n                true\n        else\n            // create a new node with random height\n            let n = newNode v\n\n            // resize the root if necessary\n            resize n.Height &root\n\n            for i in 0..n.Height-1 do\n                root.[i] <- Link(n, 1)\n\n            count <- count + 1\n            true\n\n    member x.Remove (v : 'a) =\n        if root.Length <> 0 then\n            let height = root.Length\n            let (index, prev) = findPrev [] cmp 0 (height - 1) v null root\n\n            let (_,p) = prev |> List.head\n            let n = if isNull p then root.[0].Target else p.Next.[0].Target\n\n            if not (isNull n) && cmp n.Value v = 0 then\n                removePtr prev n\n                true\n            else\n                false\n        else\n            false\n\n    member x.Clear() =\n        count <- 0\n        root <- Array.zeroCreate 0\n\n    member x.RemoveAt (index : int) =\n        if root.Length <> 0 then\n            let height = root.Length\n            let (_, prev) = findPrevIndex [] 0 (height - 1) (index + 1) null root\n\n            let (_,p) = prev |> List.head\n            let n = if isNull p then root.[0].Target else p.Next.[0].Target\n\n            if not (isNull n) then\n                removePtr prev n\n                true\n            else\n                false\n        else\n            false\n\n    member x.TryAt(index : int) =\n        if root.Length = 0 then\n            None\n        else\n            let height = root.Length\n            let (_,ptr) = findPrevIndex [] 0 (height - 1) (index + 1) null root\n            let (id,n) = ptr |> List.head\n\n            let link = \n                if isNull n then root.[0] \n                else n.Next.[0]\n\n            if not (isNull link.Target) && link.Width + id = index + 1 then\n                Some link.Target.Value\n            else\n                None\n\n    member x.Contains (v : 'a) (l : SkipList<'a>) =\n        if root.Length <> 0 then\n            let height = root.Length\n            let (index, prev) = findPrev [] cmp 0 (height - 1) v null root\n\n            let (_,p) = prev |> List.head\n            let n = if isNull p then root.[0].Target else p.Next.[0].Target\n\n            if not (isNull n) && cmp n.Value v = 0 then\n                true\n            else\n                false\n        else\n            false\n\n    member x.Item\n        with get (index : int) = \n            match x.TryAt index with\n                | Some v -> v\n                | None -> raise <| IndexOutOfRangeException()\n\n    member x.Count = count\n\n    interface IEnumerable with\n        member x.GetEnumerator() = toSeq().GetEnumerator() :> IEnumerator\n\n    interface IEnumerable<'a> with\n        member x.GetEnumerator() = toSeq().GetEnumerator()\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule SkipList =\n\n    let empty<'a when 'a : comparison> : SkipList<'a> = SkipList<'a>(compare)\n\n    let custom (cmp : 'a -> 'a -> int) = SkipList<'a>(cmp)\n\n    let count (s : SkipList<'a>) = s.Count\n\n    let add (v : 'a) (l : SkipList<'a>) = l.Add v\n\n    let remove (v : 'a) (l : SkipList<'a>) = l.Remove v\n\n    let removeAt (index : int) (l : SkipList<'a>) = l.RemoveAt index\n\n    let clear (l : SkipList<'a>) =\n        l.Clear()\n\n    let at (index : int) (l : SkipList<'a>) = l.TryAt index\n\n    let contains (v : 'a) (l : SkipList<'a>) = l.Contains v\n\n    let ofSeq (s : seq<'a>) =\n        let l = empty\n        for e in s do\n            add e l |> ignore\n        l\n\n    let ofList (l : list<'a>) =\n        ofSeq l\n\n    let ofArray (a : 'a[]) =\n        ofSeq a\n\n    let toSeq (s : SkipList<'a>) =\n        s :> seq<_>\n\n    let toList (s : SkipList<'a>) =\n        s |> Seq.toList\n\n    let toArray (s : SkipList<'a>) =\n        s |> Seq.toArray"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Datastructures/Mutable/StableSet.fs",
    "content": "﻿namespace Aardvark.Base\n\n\nopen System.Collections\nopen System.Collections.Generic\nopen System.Runtime.InteropServices\nopen System.Runtime.CompilerServices\n\n[<AllowNullLiteral>]\ntype private Linked<'a> =\n    class\n        val mutable public Value : 'a\n        val mutable public Prev : Linked<'a>\n        val mutable public Next : Linked<'a>\n\n        new (v, p, n) = { Value = v; Prev = p; Next = n }\n        new (v) = { Value = v; Prev = null; Next = null }\n    end\n\n\ntype private LinkedEnumerator<'a>(l : Linked<'a>) =\n    let mutable current = null\n    interface IEnumerator with\n        member x.MoveNext() =\n            if isNull current then\n                current <- l\n            else\n                current <- current.Next\n            not (isNull current)\n\n        member x.Current =\n            current.Value :> obj\n\n        member x.Reset() =\n            current <- null\n\n    interface IEnumerator<'a> with\n        member x.Current = current.Value\n        member x.Dispose() = current <- null\n  \n[<AllowNullLiteral>]              \ntype StableSet<'a>() =\n    let content = Dict.empty<'a, Linked<'a>>\n    let mutable first : Linked<'a> = null\n    let mutable last : Linked<'a> = null\n\n    member x.Count = content.Count\n\n    member x.First = \n        if isNull first then None\n        else Some first.Value\n\n    member x.Last = \n        if isNull last then None\n        else Some last.Value\n\n    member x.Contains(v : 'a) =\n        content.ContainsKey v\n\n    member x.Clear() =\n        content.Clear()\n        first <- null\n        last <- null\n\n    member x.Add(v : 'a) =\n        let n = Linked(v, last, null)\n        if not (content.ContainsKey v) then\n            content.[v] <- n\n\n            if isNull last then first <- n\n            else last.Next <- n\n\n            last <- n\n            true\n        else\n            false\n\n    member x.Remove(v : 'a) =\n        match content.TryRemove v with\n            | (true, n) ->\n                \n                if isNull n.Prev then first <- n.Next\n                else n.Prev.Next <- n.Next\n\n                if isNull n.Next then last <- n.Prev\n                else n.Next.Prev <- n.Prev\n\n                n.Prev <- null\n                n.Next <- null\n\n                true\n            | _ ->\n                false\n\n    member x.UnionWith (s : seq<'a>) =\n        s |> Seq.iter (x.Add >> ignore)\n\n    member x.ExeptWith (s : seq<'a>) =\n        s |> Seq.iter (x.Remove >> ignore)\n\n    member x.TryGetPrev(v : 'a) =\n        match content.TryGetValue v with\n            | (true, n) ->\n                if isNull n.Prev then None\n                else Some n.Prev.Value\n            | _ ->\n                None\n\n    member x.TryGetNext(v : 'a) =\n        match content.TryGetValue v with\n            | (true, n) ->\n                if isNull n.Next then None\n                else Some n.Next.Value\n            | _ ->\n                None\n\n    member x.AddWithPrev (f : Option<'a> -> 'a) =\n        let left =\n            if isNull last then None\n            else Some last.Value\n\n        let v = f left\n        if x.Add v then\n            Some v\n        else\n            None\n\n    interface IEnumerable with\n        member x.GetEnumerator() = \n            new LinkedEnumerator<'a>(first) :> IEnumerator\n\n    interface IEnumerable<'a> with\n        member x.GetEnumerator() = \n            new LinkedEnumerator<'a>(first) :> IEnumerator<'a>\n\n[<AllowNullLiteral>]\ntype StableDict<'k, 'v>() =\n    let content = Dict.empty<'k, Linked<'k * 'v>>\n    let mutable first : Linked<'k * 'v> = null\n    let mutable last : Linked<'k * 'v> = null\n\n    member x.Count = content.Count\n\n    member x.First = \n        if isNull first then None\n        else Some first.Value\n\n    member x.Last = \n        if isNull last then None\n        else Some last.Value\n\n    member x.ContainsKey(v : 'k) =\n        content.ContainsKey v\n\n    member x.TryGetValue(k : 'k, [<Out>] value : byref<'v>) =\n        match content.TryGetValue k with\n            | (true, l) ->\n                value <- snd l.Value\n                true\n            | _ ->\n                false\n\n    member x.TryAdd(k : 'k, value : 'v) =\n        let n = Linked((k,value), last, null)\n        if content.TryAdd(k, n) then\n            if isNull last then first <- n\n            else last.Next <- n\n            last <- n\n            true\n        else\n            false\n\n    member x.TryRemove(k : 'k, [<Out>] value : byref<'v>) =\n        match content.TryRemove k with\n            | (true, n) ->\n                if isNull n.Prev then first <- n.Next\n                else n.Prev.Next <- n.Next\n\n                if isNull n.Next then last <- n.Prev\n                else n.Next.Prev <- n.Prev\n\n                value <- snd n.Value\n                true\n            | _ ->\n                false\n\n    member x.GetOrAdd(k : 'k, f : 'k -> 'v) =\n        let isNew = ref false\n        let node = \n            content.GetOrCreate(k, fun k ->\n                isNew := true\n                Linked((k, f k), last, null)\n            )\n        \n        if !isNew then\n            if isNull last then first <- node\n            else last.Next <- node\n\n            last <- node\n\n        node.Value |> snd\n        \n    member x.Remove(k : 'k) =\n        match content.TryRemove k with\n            | (true, n) ->\n                \n                if isNull n.Prev then first <- n.Next\n                else n.Prev.Next <- n.Next\n\n                if isNull n.Next then last <- n.Prev\n                else n.Next.Prev <- n.Prev\n\n\n                true\n            | _ ->\n                false\n    \n    member x.TryGetPrev(v : 'k) =\n        match content.TryGetValue v with\n            | (true, n) ->\n                if isNull n.Prev then None\n                else Some n.Prev.Value\n            | _ ->\n                None\n\n    member x.TryGetNext(v : 'k) =\n        match content.TryGetValue v with\n            | (true, n) ->\n                if isNull n.Next then None\n                else Some n.Next.Value\n            | _ ->\n                None \n\n    interface IEnumerable with\n        member x.GetEnumerator() = \n            new LinkedEnumerator<'k * 'v>(first) :> IEnumerator\n\n    interface IEnumerable<'k * 'v> with\n        member x.GetEnumerator() = \n            new LinkedEnumerator<'k * 'v>(first) :> IEnumerator<'k * 'v>\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Math/AverageWindow.fs",
    "content": "﻿namespace Aardvark.Base\n\n/// Represents a moving average window of a sequence.\n/// It builds the average of the last N inserted values.\ntype AverageWindow(maxCount : int) =\n    let values = Array.zeroCreate maxCount\n    let mutable index = 0\n    let mutable count = 0\n    let mutable sum = 0.0\n\n    /// Insert a new value to the sequence and returns the average of the last N values.\n    member x.Insert(v : float) =\n        let newSum =\n            if count < maxCount then\n                count <- count + 1\n                sum + v\n            else\n                sum + v - values.[index]\n\n        sum <- newSum\n        values.[index] <- v\n        index <- (index + 1) % maxCount\n\n        x.Value\n\n    /// The number of currently inserted values.\n    member x.Count = count\n\n    /// Returns the average of the last N inserted values.\n    member x.Value =\n        if count = 0 then 0.0\n        else sum / float count\n\n    /// Resets the average window.\n    member x.Reset() =\n        index <- 0\n        count <- 0\n        sum <- 0.0\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Math/Converters.fs",
    "content": "﻿namespace Aardvark.Base\n\n#nowarn \"77\"\n\n// Statically resolved, generic converters\n[<AutoOpen>]\nmodule Converters =\n\n    module Identity =\n        type Converter() =\n            static member inline op_Explicit (x : ^a) : ^a = x\n\n    let inline private conv< ^z, ^a, ^b when (^z or ^a or ^b) : (static member op_Explicit : ^a -> ^b) > (a : ^a) : ^b =\n        ((^z or ^a or ^b) : (static member op_Explicit : ^a -> ^b) (a))\n\n    [<AutoOpen>]\n    module Vector =\n        let inline v2d (v : ^a) = conv< Identity.Converter, ^a, V2d > v\n        let inline v2f (v : ^a) = conv< Identity.Converter, ^a, V2f > v\n        let inline v2i (v : ^a) = conv< Identity.Converter, ^a, V2i > v\n        let inline v2ui (v : ^a) = conv< Identity.Converter, ^a, V2ui > v\n        let inline v2l (v : ^a) = conv< Identity.Converter, ^a, V2l > v\n\n        let inline v3d (v : ^a) = conv< Identity.Converter, ^a, V3d > v\n        let inline v3f (v : ^a) = conv< Identity.Converter, ^a, V3f > v\n        let inline v3i (v : ^a) = conv< Identity.Converter, ^a, V3i > v\n        let inline v3ui (v : ^a) = conv< Identity.Converter, ^a, V3ui > v\n        let inline v3l (v : ^a) = conv< Identity.Converter, ^a, V3l > v\n\n        let inline v4d (v : ^a) = conv< Identity.Converter, ^a, V4d > v\n        let inline v4f (v : ^a) = conv< Identity.Converter, ^a, V4f > v\n        let inline v4i (v : ^a) = conv< Identity.Converter, ^a, V4i > v\n        let inline v4ui (v : ^a) = conv< Identity.Converter, ^a, V4ui > v\n        let inline v4l (v : ^a) = conv< Identity.Converter, ^a, V4l > v\n\n        module private CompilerTests =\n\n            let working() =\n                let a : V3d = v3d V2i.IO\n                let a : V3d = v3d V3f.IOI\n                let a : V3d = v3d V3d.IOI\n                let a : V3d = v3d V4l.IOII\n                let a : V3d = v3d [| 0l; 1l; 2l |]\n                let a : V3d = v3d C3ui.BlueViolet\n                let a : V4d = v4d C3ui.BlueViolet\n                let a : V3d = v3d C4f.BlueViolet\n                let a : V3ui = v3ui C4b.White\n                ()\n\n    [<AutoOpen>]\n    module Color =\n        let inline c3b  (v : ^a) = conv< Identity.Converter, ^a, C3b  > v\n        let inline c3us (v : ^a) = conv< Identity.Converter, ^a, C3us > v\n        let inline c3ui (v : ^a) = conv< Identity.Converter, ^a, C3ui > v\n        let inline c3f  (v : ^a) = conv< Identity.Converter, ^a, C3f  > v\n        let inline c3d  (v : ^a) = conv< Identity.Converter, ^a, C3d  > v\n\n        let inline c4b  (v : ^a) = conv< Identity.Converter, ^a, C4b  > v\n        let inline c4us (v : ^a) = conv< Identity.Converter, ^a, C4us > v\n        let inline c4ui (v : ^a) = conv< Identity.Converter, ^a, C4ui > v\n        let inline c4f  (v : ^a) = conv< Identity.Converter, ^a, C4f  > v\n        let inline c4d  (v : ^a) = conv< Identity.Converter, ^a, C4d  > v\n\n        let working() =\n            let a : C3d = c3d V3f.IOI\n            let a : C3d = c3d V4d.IOII\n            let a : C3ui = c3ui [| 0us; 1us; 2us |]\n            let a : C3d = c3d C3ui.BlueViolet\n            let a : C4d = c4d C3ui.BlueViolet\n            ()\n\n    [<AutoOpen>]\n    module Matrix =\n\n        let inline m22d (v : ^a) = conv< Identity.Converter, ^a, M22d > v\n        let inline m23d (v : ^a) = conv< Identity.Converter, ^a, M23d > v\n        let inline m33d (v : ^a) = conv< Identity.Converter, ^a, M33d > v\n        let inline m34d (v : ^a) = conv< Identity.Converter, ^a, M34d > v\n        let inline m44d (v : ^a) = conv< Identity.Converter, ^a, M44d > v\n\n        let inline m22f (v : ^a) = conv< Identity.Converter, ^a, M22f > v\n        let inline m23f (v : ^a) = conv< Identity.Converter, ^a, M23f > v\n        let inline m33f (v : ^a) = conv< Identity.Converter, ^a, M33f > v\n        let inline m34f (v : ^a) = conv< Identity.Converter, ^a, M34f > v\n        let inline m44f (v : ^a) = conv< Identity.Converter, ^a, M44f > v\n\n        let inline m22i (v : ^a) = conv< Identity.Converter, ^a, M22i > v\n        let inline m23i (v : ^a) = conv< Identity.Converter, ^a, M23i > v\n        let inline m33i (v : ^a) = conv< Identity.Converter, ^a, M33i > v\n        let inline m34i (v : ^a) = conv< Identity.Converter, ^a, M34i > v\n        let inline m44i (v : ^a) = conv< Identity.Converter, ^a, M44i > v\n\n        let inline m22l (v : ^a) = conv< Identity.Converter, ^a, M22l > v\n        let inline m23l (v : ^a) = conv< Identity.Converter, ^a, M23l > v\n        let inline m33l (v : ^a) = conv< Identity.Converter, ^a, M33l > v\n        let inline m34l (v : ^a) = conv< Identity.Converter, ^a, M34l > v\n        let inline m44l (v : ^a) = conv< Identity.Converter, ^a, M44l > v\n\n        module private CompilerTests =\n\n            let working() =\n                let a : M33d = m33d M23i.Zero\n                let a : M33d = m33d M33f.Zero\n                let a : M33d = m33d M33d.Zero\n                let a : M33d = m33d M34l.Zero\n                let a : M22d = m22d [| 0l; 1l; 2l; 3l |]\n                let a : M22d = m22d <| Array2D.create 2 2 2.0f\n                ()"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Math/Math.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\n\n/// Provides generic math functions that work for both scalars and vectors (element-wise).\n/// Functions already provided by the F# core library are only redefined if necessary\n/// (e.g. different signature)\n[<AutoOpen>]\nmodule FSharpMath =\n\n    module Helpers =\n\n        // Some of these SRTP member methods have odd names to avoid clashes with\n        // methods added in .NET 7 (e.g. Double.Log2). If we use those standard names in our helper types we\n        // get build errors due to ambiguities when targeting .NET 7+.\n        [<Sealed; AbstractClass>]\n        type Log2() =\n            static member inline LogBinary(x: int8)    : float   = Fun.Log2 x\n            static member inline LogBinary(x: int16)   : float   = Fun.Log2 x\n            static member inline LogBinary(x: int32)   : float   = Fun.Log2 x\n            static member inline LogBinary(x: int64)   : float   = Fun.Log2 x\n            static member inline LogBinary(x: uint8)   : float   = Fun.Log2 x\n            static member inline LogBinary(x: uint16)  : float   = Fun.Log2 x\n            static member inline LogBinary(x: uint32)  : float   = Fun.Log2 x\n            static member inline LogBinary(x: uint64)  : float   = Fun.Log2 x\n            static member inline LogBinary(x: float)   : float   = Fun.Log2 x\n            static member inline LogBinary(x: float32) : float32 = Fun.Log2 x\n\n        [<Sealed; AbstractClass>]\n        type Acosh() =\n            static member inline Acoshb(x: float)   : float   = Fun.Acosh x\n            static member inline Acoshb(x: float32) : float32 = Fun.Acosh x\n\n        [<Sealed; AbstractClass>]\n        type Asinh() =\n            static member inline Asinhb(x: float)   : float   = Fun.Asinh x\n            static member inline Asinhb(x: float32) : float32 = Fun.Asinh x\n\n        [<Sealed; AbstractClass>]\n        type Atanh() =\n            static member inline Atanhb(x: float)   : float   = Fun.Atanh x\n            static member inline Atanhb(x: float32) : float32 = Fun.Atanh x\n\n        [<Sealed; AbstractClass>]\n        type Cbrt() =\n            static member inline CubeRoot(x: int8)    : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: int16)   : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: int32)   : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: int64)   : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: uint8)   : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: uint16)  : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: uint32)  : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: uint64)  : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: float)   : float   = Fun.Cbrt x\n            static member inline CubeRoot(x: float32) : float32 = Fun.Cbrt x\n\n        [<Sealed; AbstractClass>]\n        type Lerp() =\n            static member inline LinearInterp(t: float, a: int8, b: int8)         : int8    = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: int8, b: int8)       : int8    = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float, a: uint8, b: uint8)       : uint8   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: uint8, b: uint8)     : uint8   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float, a: int16, b: int16)       : int16   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: int16, b: int16)     : int16   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float, a: uint16, b: uint16)     : uint16  = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: uint16, b: uint16)   : uint16  = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float, a: int32, b: int32)       : int32   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: int32, b: int32)     : int32   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float, a: uint32, b: uint32)     : uint32  = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: uint32, b: uint32)   : uint32  = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float, a: int64, b: int64)       : int64   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: int64, b: int64)     : int64   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float, a: uint64, b: uint64)     : uint64  = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: uint64, b: uint64)   : uint64  = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: decimal, a: decimal, b: decimal) : decimal = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float, a: float, b: float)       : float   = Fun.Lerp(t, a, b)\n            static member inline LinearInterp(t: float32, a: float32, b: float32) : float32 = Fun.Lerp(t, a, b)\n\n        [<Sealed; AbstractClass>]\n        type CopySign() =\n            static member inline CopySgn(value: float, sign: float)     : float   = Fun.CopySign(value, sign)\n            static member inline CopySgn(value: float32, sign: float32) : float32 = Fun.CopySign(value, sign)\n\n        [<Sealed; AbstractClass>]\n        type Comparison() =\n            static member inline Min< ^T when ^T : comparison>(a : ^T, b : ^T) = Operators.min a b\n\n            static member inline Min(a : float, b : V2d) = V2d.Min(b, a)\n            static member inline Min(a : float, b : V3d) = V3d.Min(b, a)\n            static member inline Min(a : float, b : V4d) = V4d.Min(b, a)\n            static member inline Min(a : float32, b : V2f) = V2f.Min(b, a)\n            static member inline Min(a : float32, b : V3f) = V3f.Min(b, a)\n            static member inline Min(a : float32, b : V4f) = V4f.Min(b, a)\n            static member inline Min(a : int, b : V2i) = V2i.Min(b, a)\n            static member inline Min(a : int, b : V3i) = V3i.Min(b, a)\n            static member inline Min(a : int, b : V4i) = V4i.Min(b, a)\n            static member inline Min(a : uint, b : V2ui) = V2ui.Min(b, a)\n            static member inline Min(a : uint, b : V3ui) = V3ui.Min(b, a)\n            static member inline Min(a : uint, b : V4ui) = V4ui.Min(b, a)\n            static member inline Min(a : int64, b : V2l) = V2l.Min(b, a)\n            static member inline Min(a : int64, b : V3l) = V3l.Min(b, a)\n            static member inline Min(a : int64, b : V4l) = V4l.Min(b, a)\n\n            static member inline Max< ^T when ^T : comparison>(a : ^T, b : ^T) = Operators.max a b\n\n            static member inline Max(a : float, b : V2d) = V2d.Max(b, a)\n            static member inline Max(a : float, b : V3d) = V3d.Max(b, a)\n            static member inline Max(a : float, b : V4d) = V4d.Max(b, a)\n            static member inline Max(a : float32, b : V2f) = V2f.Max(b, a)\n            static member inline Max(a : float32, b : V3f) = V3f.Max(b, a)\n            static member inline Max(a : float32, b : V4f) = V4f.Max(b, a)\n            static member inline Max(a : int, b : V2i) = V2i.Max(b, a)\n            static member inline Max(a : int, b : V3i) = V3i.Max(b, a)\n            static member inline Max(a : int, b : V4i) = V4i.Max(b, a)\n            static member inline Max(a : uint, b : V2ui) = V2ui.Max(b, a)\n            static member inline Max(a : uint, b : V3ui) = V3ui.Max(b, a)\n            static member inline Max(a : uint, b : V4ui) = V4ui.Max(b, a)\n            static member inline Max(a : int64, b : V2l) = V2l.Max(b, a)\n            static member inline Max(a : int64, b : V3l) = V3l.Max(b, a)\n            static member inline Max(a : int64, b : V4l) = V4l.Max(b, a)\n\n        [<Sealed; AbstractClass>]\n        type Saturate() =\n            static member inline Saturate(x : sbyte) = x |> max 0y |> min 1y\n            static member inline Saturate(x : int16) = x |> max 0s |> min 1s\n            static member inline Saturate(x : int32) = x |> max 0 |> min 1\n            static member inline Saturate(x : int64) = x |> max 0L |> min 1L\n\n            static member inline Saturate(x : byte) = x |> max 0uy |> min 1uy\n            static member inline Saturate(x : uint16) = x |> max 0us |> min 1us\n            static member inline Saturate(x : uint32) = x |> max 0u |> min 1u\n            static member inline Saturate(x : uint64) = x |> max 0UL |> min 1UL\n\n            static member inline Saturate(x : nativeint) = x |> max 0n |> min 1n\n            static member inline Saturate(x : float) = x |> max 0.0 |> min 1.0\n            static member inline Saturate(x : float16) = x |> max float16.Zero |> min float16.One\n            static member inline Saturate(x : float32) = x |> max 0.0f |> min 1.0f\n            static member inline Saturate(x : decimal) = x |> max 0m |> min 1m\n\n        [<Sealed; AbstractClass>]\n        type Infinity() =\n            static member inline IsNaN< ^T when ^T : (member IsNaN : bool)> (x : ^T) : bool =\n                (^T : (member IsNaN : bool) x)\n\n            static member inline IsInfinity< ^T when ^T : (member IsInfinity : bool)> (x : ^T) : bool =\n                (^T : (member IsInfinity : bool) x)\n\n            static member inline IsPositiveInfinity< ^T when ^T : (member IsPositiveInfinity : bool)> (x : ^T) : bool =\n                (^T : (member IsPositiveInfinity : bool) x)\n\n            static member inline IsNegativeInfinity< ^T when ^T : (member IsNegativeInfinity : bool)> (x : ^T) : bool =\n                (^T : (member IsNegativeInfinity : bool) x)\n\n        [<Sealed; AbstractClass>]\n        type InfinityS() =\n            static member inline IsNaN< ^T when ^T : (static member IsNaN : ^T -> bool)> (x : ^T) : bool =\n                (^T : (static member IsNaN : ^T -> bool) x)\n\n            static member inline IsInfinity< ^T when ^T : (static member IsInfinity : ^T -> bool)> (x : ^T) : bool =\n                (^T : (static member IsInfinity : ^T -> bool) x)\n\n            static member inline IsPositiveInfinity< ^T when ^T : (static member IsPositiveInfinity : ^T -> bool)> (x : ^T) : bool =\n                (^T : (static member IsPositiveInfinity : ^T -> bool) x)\n\n            static member inline IsNegativeInfinity< ^T when ^T : (static member IsNegativeInfinity : ^T -> bool)> (x : ^T) : bool =\n                (^T : (static member IsNegativeInfinity : ^T -> bool) x)\n\n    [<AutoOpen>]\n    module private Aux =\n        let inline signumAux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member Signum : ^T -> ^T) x)\n\n        let inline signumiAux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member Signumi : ^T -> ^U) x)\n\n        // Making the power functions more general with ^T -> ^U -> ^V\n        // generally works but requires manual type annotations in some cases\n        // It's not worth the hassle so we restrict them to ^T -> ^U -> ^T\n        // Also using the default pow / Pow() doesn't work with code quotations\n        // for some reason.\n        let inline powAux (_ : ^Z) (x : ^T) (y : ^U) =\n            ((^Z or ^T or ^U) : (static member Power : ^T * ^U -> ^T) (x, y))\n\n        let inline pownAux (_ : ^Z) (x : ^T) (y : ^U) =\n            ((^Z or ^T or ^U) : (static member Pown : ^T * ^U -> ^T) (x, y))\n\n        let inline exp2Aux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member PowerOfTwo : ^T -> ^T) (x))\n\n        let inline log2Aux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member LogBinary : ^T -> ^T) x)\n\n        let inline log2intAux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member Log2Int : ^T -> ^U) x)\n\n        let inline asinhAux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member Asinhb : ^T -> ^T) x)\n\n        let inline acoshAux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member Acoshb : ^T -> ^T) x)\n\n        let inline atanhAux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member Atanhb : ^T -> ^T) x)\n\n        let inline cbrtAux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member CubeRoot : ^T -> ^T) x)\n\n        // See comment for powAux\n        let inline minAux (_ : ^Z) (x : ^T) (y : ^U) =\n            ((^Z or ^T or ^U) : (static member Min : ^T * ^U -> ^U) (x, y))\n\n        let inline maxAux (_ : ^Z) (x : ^T) (y : ^U) =\n            ((^Z or ^T or ^U) : (static member Max : ^T * ^U -> ^U) (x, y))\n\n        // Simply using min and max directly will resolve to the comparison overload for some reason.\n        // Therefore we need to do it the dumb (incomplete) way. E.g. won't work for Version.\n        let inline saturateAux (_ : ^Z) (x : ^T) =\n            ((^Z or ^T) : (static member Saturate : ^T -> ^T) (x))\n\n        let inline lerpAux (_ : ^Z) (x : ^T) (y : ^T) (t : ^U) =\n            ((^Z or ^T or ^U) : (static member LinearInterp : ^U * ^T * ^T -> ^T) (t, x, y))\n\n        let inline invLerpAux (_ : ^Z) (a : ^T) (b : ^T) (y : ^T) =\n            ((^Z or ^T or ^U) : (static member InvLerp : ^T * ^T * ^T -> ^U) (y, a, b))\n\n        let inline stepAux (_ : ^Z) (edge : ^T) (x : ^U) =\n            ((^Z or ^T or ^U) : (static member Step : ^U * ^T -> ^U) (x, edge))\n\n        let inline linearstepAux (_ : ^Z) (edge0 : ^T) (edge1 : ^T) (x : ^U) =\n            ((^Z or ^T or ^U) : (static member Linearstep : ^U * ^T * ^T -> ^U) (x, edge0, edge1))\n\n        let inline smoothstepAux (_ : ^Z) (edge0 : ^T) (edge1 : ^T) (x : ^U) =\n            ((^Z or ^T or ^U) : (static member Smoothstep : ^U * ^T * ^T -> ^U) (x, edge0, edge1))\n\n        // See comment for powAux\n        let inline copysignAux (_ : ^Z) (value : ^T) (sign : ^U) =\n            ((^Z or ^T or ^U) : (static member CopySgn : ^T * ^U -> ^T) (value, sign))\n\n        let inline degreesAux (_ : ^Z) (radians : ^T) =\n            ((^Z or ^T) : (static member DegreesFromRadians : ^T -> ^T) radians)\n\n        let inline radiansAux (_ : ^Z) (degrees : ^T) =\n            ((^Z or ^T) : (static member RadiansFromDegrees : ^T -> ^T) degrees)\n\n        let inline maddAux (_ : ^Z) (x : ^T) (y : ^U) (z : ^T) =\n            ((^Z or ^T or ^U) : (static member MultiplyAdd : ^T * ^U * ^T -> ^T) (x, y, z))\n\n        let inline isNanAux (_ : ^Z) (_ : ^Y) (x : ^T) =\n            ((^Z or ^Y or ^T) : (static member IsNaN : ^T -> bool) x)\n\n        let inline isInfAux (_ : ^Z) (_ : ^Y) (x : ^T) =\n            ((^Z or ^Y or ^T) : (static member IsInfinity : ^T -> bool) x)\n\n        let inline isPosInfAux (_ : ^Z) (_ : ^Y) (x : ^T) =\n            ((^Z or ^Y or ^T) : (static member IsPositiveInfinity : ^T -> bool) x)\n\n        let inline isNegInfAux (_ : ^Z) (_ : ^Y) (x : ^T) =\n            ((^Z or ^Y or ^T) : (static member IsNegativeInfinity : ^T -> bool) x)\n\n        let inline approximateEqualsAux (_: ^Z) (epsilon: ^U) (x: ^T) (y: ^T) =\n            ((^Z or ^T) : (static member ApproximateEquals : ^T * ^T * ^U -> bool) (x, y, epsilon))\n\n    /// Resolves to the zero value for any scalar or vector type.\n    [<GeneralizableValue>]\n    let inline zero< ^T when ^T : (static member Zero : ^T) > : ^T =\n        LanguagePrimitives.GenericZero\n\n    /// Resolves to the one value for any scalar or vector type.\n    [<GeneralizableValue>]\n    let inline one< ^T when ^T : (static member One : ^T) > : ^T =\n        LanguagePrimitives.GenericOne\n\n    /// Returns -1 if x is less than zero, 0 if x is equal to zero, and 1 if\n    /// x is greater than zero. The result has the same type as the input.\n    let inline signum x =\n        signumAux Unchecked.defaultof<Fun> x\n\n    /// Returns -1 if x is less than zero, 0 if x is equal to zero, and 1 if\n    /// x is greater than zero.\n    let inline signumi x =\n        signumiAux Unchecked.defaultof<Fun> x\n\n    /// Returns x raised to the power of y (must be float or double).\n    // F# variant does not support integers!\n    let inline pow x y =\n        powAux Unchecked.defaultof<Fun> x y\n\n    /// Returns x raised to the power of y.\n    // F# variant does not support integers!\n    let inline ( ** ) x y =\n        pow x y\n\n    /// Returns x raised to the integer power of y (must not be negative).\n    // F# variant has signature a' -> int -> 'a, which does not permit for example V2f -> V2i -> V2f\n    let inline pown x y =\n        pownAux Unchecked.defaultof<Fun> x y\n\n    /// Returns 2 raised to the power of x (must be float, double, or uint64).\n    let inline exp2 x =\n        exp2Aux Unchecked.defaultof<Fun> x\n\n    /// Returns the base 2 logarithm of x.\n    let inline log2 x =\n        log2Aux Unchecked.defaultof<Helpers.Log2> x\n\n    /// Returns the base 2 logarithm of x rounded to the next integer towards negative infinity.\n    let inline log2int x =\n        log2intAux Unchecked.defaultof<Fun> x\n\n    /// Returns the inverse hyperbolic sine of x.\n    let inline asinh x =\n        asinhAux Unchecked.defaultof<Helpers.Asinh> x\n\n    /// Returns the inverse hyperbolic cosine of x.\n    let inline acosh x =\n        acoshAux Unchecked.defaultof<Helpers.Acosh> x\n\n    /// Returns the inverse hyperbolic tangent of x.\n    let inline atanh x =\n        atanhAux Unchecked.defaultof<Helpers.Atanh> x\n\n    /// Returns x^2\n    let inline sqr x = x * x\n\n    /// Returns the cubic root of x.\n    let inline cbrt x =\n        cbrtAux Unchecked.defaultof<Helpers.Cbrt> x\n\n    /// Returns the smaller of x and y.\n    let inline min x y = minAux Unchecked.defaultof<Helpers.Comparison> x y\n\n    /// Returns the larger of x and y.\n    let inline max x y = maxAux Unchecked.defaultof<Helpers.Comparison> x y\n\n    /// Clamps x to the interval [a, b].\n    let inline clamp a b x =\n        x |> max a |> min b\n\n    /// Clamps x to the interval [0, 1].\n    let inline saturate (x : ^T) =\n        saturateAux Unchecked.defaultof<Helpers.Saturate> x\n\n    /// Linearly interpolates between x and y.\n    let inline lerp x y t =\n        lerpAux Unchecked.defaultof<Helpers.Lerp> x y t\n\n    /// Inverse linear interpolation. Computes t of y = a * (1 - t) + b * t.\n    let inline invLerp a b y =\n        invLerpAux Unchecked.defaultof<Fun> a b y\n\n    /// Returns 0 if x < edge, and 1 otherwise.\n    let inline step (edge : ^T) (x : ^U) =\n        stepAux Unchecked.defaultof<Fun> edge x\n\n    /// Inverse linear interpolation. Clamped to [0, 1].\n    let inline linearstep (edge0 : ^T) (edge1 : ^T) (x : ^U) : ^U =\n        linearstepAux Unchecked.defaultof<Fun> edge0 edge1 x\n\n    /// Performs smooth Hermite interpolation between 0 and 1 when edge0 < x < edge1.\n    let inline smoothstep (edge0 : ^T) (edge1 : ^T) (x : ^U) =\n        smoothstepAux Unchecked.defaultof<Fun> edge0 edge1 x\n\n    /// Returns a value with the magnitude of the first argument and the sign of the second argument.\n    let inline copysign (value : ^T) (sign : ^U) =\n        copysignAux Unchecked.defaultof<Helpers.CopySign> value sign\n\n    /// Converts an angle given in radians to degrees.\n    let inline degrees (radians : ^T) =\n        degreesAux Unchecked.defaultof<Conversion> radians\n\n    /// Converts an angle given in degrees to radians.\n    let inline radians (degrees : ^T) =\n        radiansAux Unchecked.defaultof<Conversion> degrees\n\n    /// Returns (x * y) + z\n    let inline madd (x : ^T) (y : ^U) (z : ^T) =\n        maddAux Unchecked.defaultof<Fun> x y z\n\n    /// Returns whether x is NaN.\n    let inline isNaN (x : ^T) =\n        isNanAux Unchecked.defaultof<Helpers.Infinity> Unchecked.defaultof<Helpers.InfinityS> x\n\n    /// Returns whether x is infinity (positive or negative).\n    let inline isInfinity (x : ^T) =\n        isInfAux Unchecked.defaultof<Helpers.Infinity> Unchecked.defaultof<Helpers.InfinityS> x\n\n    /// Returns whether x is positive infinity.\n    let inline isPositiveInfinity (x : ^T) =\n        isPosInfAux Unchecked.defaultof<Helpers.Infinity> Unchecked.defaultof<Helpers.InfinityS> x\n\n    /// Returns whether x is negative infinity.\n    let inline isNegativeInfinity (x : ^T) =\n        isNegInfAux Unchecked.defaultof<Helpers.Infinity> Unchecked.defaultof<Helpers.InfinityS> x\n\n    /// Returns whether x is finite (i.e. not NaN and not infinity).\n    let inline isFinite (x : ^T) =\n        (x |> isInfinity |> not) && (x |> isNaN |> not)\n\n    /// Returns whether the distance between x and y is not more than epsilon.\n    let inline approximateEquals epsilon x y =\n        approximateEqualsAux Unchecked.defaultof<Fun> epsilon x y\n\n    [<CompilerMessage(\"testing purposes\", 1337, IsHidden = true)>]\n    module ``Math compiler tests 😀😁`` =\n        type MyCustomNumericTypeExtensionTestTypeForInternalTesting() =\n            static member IsNaN(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = false\n            static member Power(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting, e : float) = h\n            static member Pown(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting, e : int) = h\n            static member (*)(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting, e : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member (*)(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting, e : int) = h\n            static member (+)(h : int, e : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = e\n            static member (+)(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting, e : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member (-)(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting, e : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member (/)(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting, e : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n\n            static member Signum(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member Signumi(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = 0\n            static member CubeRoot(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n\n            static member Log(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member LogBinary(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member Log2Int(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = 0\n\n            static member Acoshb(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member Asinhb(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member Atanhb(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n\n            static member Sqrt(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n\n            static member inline MultiplyAdd(a : MyCustomNumericTypeExtensionTestTypeForInternalTesting, b : int, c : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = a\n\n            static member DegreesFromRadians(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n            static member RadiansFromDegrees(h : MyCustomNumericTypeExtensionTestTypeForInternalTesting) = h\n\n        let fsharpCoreWorking() =\n\n            let absWorking() =\n                let a : V2i = abs V2i.One\n                let a : V3f = abs V3f.One\n                ()\n\n            let acosWorking() =\n                let a : V2f = acos V2f.One\n                let a : V3d = acos V3d.One\n                let a : ComplexD = acos ComplexD.One\n                ()\n\n            let asinWorking() =\n                let a : V2f = asin V2f.One\n                let a : V3d = asin V3d.One\n                let a : ComplexD = asin ComplexD.One\n                ()\n\n            let atanWorking() =\n                let a : V2f = atan V2f.One\n                let a : V3d = atan V3d.One\n                let a : ComplexD = atan ComplexD.One\n                ()\n\n            let atan2Working() =\n                let a : V2f = atan2 V2f.One V2f.Zero\n                let a : V3d = atan2 V3d.One V3d.Zero\n                ()\n\n            let ceilWorking() =\n                let a : V2f = ceil V2f.One\n                let a : V3d = ceil V3d.One\n                ()\n\n            let expWorking() =\n                let a : V2f = exp V2f.One\n                let a : V3d = exp V3d.One\n                let a : ComplexD = exp ComplexD.One\n                ()\n\n            let floorWorking() =\n                let a : V2f = floor V2f.One\n                let a : V3d = floor V3d.One\n                ()\n\n            let truncateWorking() =\n                let a : V2f = truncate V2f.One\n                let a : V3d = truncate V3d.One\n                ()\n\n            let roundWorking() =\n                let a : V2f = round V2f.One\n                let a : V3d = round V3d.One\n                ()\n\n            let logWorking() =\n                let a : V2f = log V2f.One\n                let a : V3d = log V3d.One\n                let a : ComplexD = log ComplexD.One\n                ()\n\n            let log10Working() =\n                let a : V2f = log10 V2f.One\n                let a : V3d = log10 V3d.One\n                let a : ComplexD = log10 ComplexD.One\n                ()\n\n            let sqrtWorking() =\n                let a : V2f = sqrt V2f.One\n                let a : V3d = sqrt V3d.One\n                let a : ComplexD = sqrt ComplexD.One\n                ()\n\n            let cosWorking() =\n                let a : V2f = cos V2f.One\n                let a : V3d = cos V3d.One\n                let a : ComplexD = cos ComplexD.One\n                ()\n\n            let coshWorking() =\n                let a : V2f = cosh V2f.One\n                let a : V3d = cosh V3d.One\n                let a : ComplexD = cosh ComplexD.One\n                ()\n\n            let sinWorking() =\n                let a : V2f = sin V2f.One\n                let a : V3d = sin V3d.One\n                let a : ComplexD = sin ComplexD.One\n                ()\n\n            let sinhWorking() =\n                let a : V2f = sinh V2f.One\n                let a : V3d = sinh V3d.One\n                let a : ComplexD = sinh ComplexD.One\n                ()\n\n            let tanWorking() =\n                let a : V2f = tan V2f.One\n                let a : V3d = tan V3d.One\n                let a : ComplexD = tan ComplexD.One\n                ()\n\n            let tanhWorking() =\n                let a : V2f = tanh V2f.One\n                let a : V3d = tanh V3d.One\n                let a : ComplexD = tanh ComplexD.One\n                ()\n\n            let listAverageWorking() =\n                let a : V2f = List.average [V2f.One; V2f.Zero]\n                let a : C4us = List.average [C4us.Black; C4us.White]\n                let a : M34d = List.average [M34d.Zero; M34d.Zero]\n                let a : ComplexD = List.average [ComplexD.One; ComplexD.Zero]\n                ()\n\n            ()\n\n        let zeroWorking() =\n            let a : int = zero\n            let a : float = zero\n            let a : float16 = zero\n            let a : V2d = zero\n            let a : ComplexD = zero\n            ()\n\n        let oneWorking() =\n            let a : int = one\n            let a : float = one\n            let a : float16 = one\n            let a : V2d = one\n            let a : ComplexD = one\n            ()\n\n        let inline indirectSignum (x : ^T) =\n            signum x\n\n        let signumWorking() =\n            let a : float = signum 1.0\n            let b : int = signum 1\n            let s : V2d = signum V2d.II\n            let a : decimal = signum 1.0m\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = signum (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = indirectSignum (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let signumIntWorking() =\n            let a : int = signumi 1.0\n            let b : int = signumi 1\n            let s : V2i = signumi V2d.II\n            let a : int = signumi (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let inline indirectPown (x : ^T) (y : int) =\n            pown x y\n\n        let pownWorking() =\n            let a = pown (MyCustomNumericTypeExtensionTestTypeForInternalTesting()) 6\n            let a = indirectPown (MyCustomNumericTypeExtensionTestTypeForInternalTesting()) 6\n            let a : float = pown 1.0 2\n            let a : int = pown 1 2\n            let a : uint16 = pown 1us 2\n            let a : uint16 = pown 1us 2us\n            let a : int64 = pown 1L 2\n            let a : int64 = pown 1L 2L\n\n            let a = 2.0 * (pown V3d.III V3i.III)\n            let a = 2.0 * (indirectPown V3d.III 6)\n\n            let a : V2f = pown V2f.One 1\n            let a : V2f = pown V2f.One V2i.One\n\n            let a : V2i = pown V2i.One 1\n            let a : V2i = pown V2i.One V2i.One\n\n            let a : V2l = pown V2l.One 1\n            let a : V2l = pown V2l.One 1L\n            let a : V2l = pown V2l.One V2i.One\n            let a : V2l = pown V2l.One V2l.One\n\n            ()\n\n        let inline indirectExp2 (x : ^T) =\n            exp2 x\n\n        let exp2Working() =\n            let a : float = exp2 1.0\n            let a : float32 = exp2 1.0f\n            let a : uint64 = exp2 1UL\n\n            let a = 2.0 * (exp2 V3d.III)\n            let a = 2.0 * (indirectExp2 V3d.III)\n\n            let a : V2f = exp2 V2f.One\n            let a : V2d = exp2 V2d.One\n\n            ()\n\n        let inline indirectPow (x : ^T) (y : ^U) =\n            pow x y\n\n        let powWorking() =\n            let a : float = pow 1.0 2.0\n            let a : float = indirectPow 1.0 2.0\n            let a : float32 = pow 1.0f 2.0f\n            let a : float32 = indirectPow 1.0f 2.0f\n            let a = log (2.0 + 8.0 * (pow V3d.III V3d.III))\n            let a = log (2.0 + 8.0 * (indirectPow V3d.III V3d.III))\n\n            let a = pow (MyCustomNumericTypeExtensionTestTypeForInternalTesting()) 12.\n\n            // This doesn't work if we just extend the built-in pow function\n            // by adding Pow() members to the vector types...\n            let a : V2d -> float -> V2d = pow\n            let a : V2d -> float -> V2d = indirectPow\n            let a : V2d -> float -> V2d = ( ** )\n\n            let a : V2d = pow V2d.II V2d.II\n            let a : V2d = pow V2d.II 1.0\n\n            let a : ComplexD = pow ComplexD.One ComplexD.One\n            let a : ComplexD = pow ComplexD.One 1.0\n            ()\n\n        let powOpWorking() =\n            let a : float = 1.0 ** 2.0\n            let a : float32 = 1.0f ** 2.0f\n\n            let a = MyCustomNumericTypeExtensionTestTypeForInternalTesting() ** 12.0\n\n            let a : V2d = V2d.II ** V2d.II\n            let a : V2d = V2d.II ** 1.0\n\n            let a : ComplexD = ComplexD.One ** ComplexD.One\n            let a : ComplexD = ComplexD.One ** 1.0\n            ()\n\n        let inline indirectLog2 (x : ^T) : ^T =\n            log2 x\n\n        let log2Working() =\n            let a : float = log2 10.0\n            let a : V2d =  log2 V2d.II\n            let a : ComplexD = log2 ComplexD.One\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = log2 (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = indirectLog2 (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let inline indirectLog2int (x : ^T) =\n            log2int x\n\n        let log2intWorking() =\n            let a : int = log2int 10.0\n            let a : V2i = log2int V2d.II\n            let a : int = log2int (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            let a : int = indirectLog2int (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let acoshWorking() =\n            let a : float = acosh 1.0\n            let a : float32 = acosh 1.0f\n            let a : V2f = acosh V2f.One\n            let a : V3d = acosh V3d.One\n            let a : ComplexD = acosh ComplexD.One\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = acosh (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let asinhWorking() =\n            let a : float = asinh 1.0\n            let a : float32 = asinh 1.0f\n            let a : V2f = asinh V2f.One\n            let a : V3d = asinh V3d.One\n            let a : ComplexD = asinh ComplexD.One\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = asinh (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let atanhWorking() =\n            let a : float = atanh 1.0\n            let a : float32 = atanh 1.0f\n            let a : V2f = atanh V2f.One\n            let a : V3d = atanh V3d.One\n            let a : ComplexD = atanh ComplexD.One\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = atanh (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let cbrtWorking() =\n            let a : float = cbrt 10.0\n            let a : V2d =  cbrt V2d.II\n            let a : ComplexD = cbrt ComplexD.One\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = cbrt (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let sqrWorking() =\n            let a : byte = sqr 4uy\n            let a : float = sqr 10.0\n            let a : V2d = sqr V2d.II\n            let a : V2i = sqr V2i.II\n            let a : ComplexD = sqr ComplexD.One\n            ()\n\n        let clampWorking() =\n            let a : int = clamp 1 2 3\n            let a : float16 = clamp (float16 1) (float16 2) (float16 3)\n            let a : Version = clamp (Version(1,2,3)) (Version(3,2,3)) (Version(4,5,6))\n            let a : V2d = clamp V2d.Zero V2d.One V2d.Half\n            let a : V3f = clamp 0.5f 1.5f V3f.Zero\n            let a = exp ((V3f.Zero |> clamp 0.5f V3f.One) * 0.5f)\n            ()\n\n        let inline indirectMin x y =\n            min x y\n\n        let minWorking() =\n            let a : V2d = min V2d.II V2d.OO\n            let a : V2d = min 0.0 V2d.II\n            let a : V2ui = min 0u V2ui.II\n            let a = (V2d.II |> min 1.0) * 2.0 - 0.5\n            let a = (V2d.II |> indirectMin 1.0) * 2.0 - 0.5\n            let a : float = min 1.0 2.0\n            let a : float16 = min (float16 1.0) (float16 2.0)\n            let a : uint32 = min 1u 2u\n            let a : nativeint = min 1n 2n\n            let a : Version = min (Version(1,2,3)) (Version(3,2,3))\n            ()\n\n        let maxWorking() =\n            let a : V2d = max V2d.II V2d.OO\n            let a : V2d = max 0.0 V2d.II\n            let a : V2ui = max 0u V2ui.II\n            let a : float = max 1.0 2.0\n            let a : float16 = max (float16 1.0) (float16 2.0)\n            let a : uint32 = max 1u 2u\n            let a : nativeint = max 1n 2n\n            let a : Version = max (Version(1,2,3)) (Version(3,2,3))\n            ()\n\n        let inline indirectSaturate (x : ^T) =\n            saturate x\n\n        let saturateWorking() =\n            let a : int = saturate 3\n            let a : int = indirectSaturate 3\n            let a : float = saturate 3.0\n            let a : float16 = saturate (float16 3.0)\n            let a : uint32 = saturate 3u\n            let a : nativeint = saturate 3n\n            let a : V2d = saturate V2d.One\n            let a : V2d = indirectSaturate V2d.One\n            let a : V4i = saturate V4i.One\n            ()\n\n        let lerpWorking() =\n            let a : int = lerp 1 10 0.5\n            let a : int = lerp 1 10 0.5f\n            let a : float = lerp 1.0 10.0 0.5\n            let a : float32 = lerp 1.0f 10.0f 0.5f\n            let a : V2i = lerp V2i.Zero V2i.One 0.5\n            let a : V4i = lerp V4i.Zero V4i.One V4d.Half\n            let a : V2i = lerp V2i.Zero V2i.One 0.5f\n            let a : V4i = lerp V4i.Zero V4i.One V4f.Half\n            let a : C4b = lerp C4b.Black C4b.Black 0.5f\n            let a : C4b = lerp C4b.Black C4b.Black V4f.Half\n            let a : C4b = lerp C4b.Black C4b.Black V4d.Half\n            ()\n\n        let invLerpWorking() =\n            let a : float = 1 |> invLerp 1 10\n            let a : float = 1.0 |> invLerp 1.0 10.0\n            let a : float32 = 1.0f |> invLerp 1.0f 10.0f\n            let a : V2d = V2i.Zero |> invLerp V2i.Zero V2i.One\n            let a : V4d = V4i.Zero |> invLerp V4i.Zero V4i.One\n            let a : V2f = V2f.Zero |> invLerp V2f.Zero V2f.One\n            let a : V4f = V4f.Zero |> invLerp V4f.Zero V4f.One\n            let a : V2d = V2d.Zero |> invLerp V2d.Zero V2d.One\n            let a : V4d = V4d.Zero |> invLerp V4d.Zero V4d.One\n            ()\n\n        let stepWorking() =\n            let a : float = step 0.0 1.0\n            let a : float32 = step 0.0f 0.5f\n            let a : uint8 = step 32uy 64uy\n            let a : int8 = step 32y 64y\n            let a : int16 = step 32s 64s\n            let a : uint16 = step 32us 64us\n            let a : int32 = step 32 64\n            let a : int64 = step 32L 64L\n            let a : decimal = step 32m 64m\n            let a : V2i = step 0 V2i.One\n            let a : V2l = step 0L V2l.One\n            let a : V2f = step 0.0f V2f.Half\n            let a : V4d = step V4d.Zero V4d.Half\n            ()\n\n        let linearstepWorking() =\n            let a : float = linearstep 0.0 1.0 0.5\n            let a : float32 = linearstep 0.0f 1.0f 0.5f\n            let a : V2f = linearstep 0.0f 1.0f V2f.Half\n            let a : V4d = linearstep V4d.Zero V4d.One V4d.Half\n            ()\n\n        let smoothstepWorking() =\n            let a : float = smoothstep 0.0 1.0 0.5\n            let a : float32 = smoothstep 0.0f 1.0f 0.5f\n            let a : V2f = smoothstep 0.0f 1.0f V2f.Half\n            let a : V4d = smoothstep V4d.Zero V4d.One V4d.Half\n            ()\n\n        let copysignWorking() =\n            let a : float = copysign 0.0 1.0\n            let a : float32 = copysign 0.0f 10.0f\n            let a : V3d = copysign V3d.Zero V3d.One\n            let a : V3d = copysign V3d.Zero -1.0\n            let a = exp (2.0 * (copysign V3d.Zero -1.0))\n            ()\n\n        let conversionWorking() =\n            let a : float = degrees 0.0\n            let a : float32 = radians 0.0f\n            let a : V3d = degrees V3d.Zero\n            let a : V4f = radians V4f.Zero\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = radians (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = degrees (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let inline indirectMultiplyAdd (x : ^T) (y : ^U) (z : ^T) =\n            madd x y z\n\n        let multiplyAddWorking() =\n            let a : float = madd 0.0 1.0 2.0\n            let a : float32 = madd 0.0f 1.0f 2.0f\n            let a : V3d = madd V3d.Zero 1.0 V3d.Zero\n            let a : V3d = indirectMultiplyAdd V3d.Zero 1.0 V3d.Zero\n            let a : V3d = madd V3d.Zero V3d.Zero V3d.Zero\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = madd (MyCustomNumericTypeExtensionTestTypeForInternalTesting()) 1 (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            let a : MyCustomNumericTypeExtensionTestTypeForInternalTesting = indirectMultiplyAdd (MyCustomNumericTypeExtensionTestTypeForInternalTesting()) 1 (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            ()\n\n        let inline indirectIsNaN (x : ^T) =\n            isNaN x\n\n        let specialFloatingPointValuesWorking() =\n            let a : bool = isNaN 0.0\n            let a : bool = isNaN (float16 0.0)\n            let a : bool = indirectIsNaN 0.0\n            let a : bool = indirectIsNaN (float16 0.0)\n            let a : bool = isNaN 0.0f\n            let a : bool = isNaN ComplexD.Zero\n            let a : bool = isNaN V3d.Zero\n            let a : bool = isNaN C3d.Black\n            let a : bool = isNaN M44d.Identity\n            let a : bool = isNaN (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            let a : bool = indirectIsNaN (MyCustomNumericTypeExtensionTestTypeForInternalTesting())\n            let a : bool = isFinite 0.0\n            let a : bool = isFinite 0.0f\n            let a : bool = isFinite (float16 0.0f)\n            let a : bool = isFinite ComplexD.Zero\n            let a : bool = isFinite V3d.Zero\n            let a : bool = isFinite C3d.Black\n            let a : bool = isFinite M44d.Identity\n            let a : bool = isInfinity 0.0\n            let a : bool = isInfinity 0.0f\n            let a : bool = isInfinity (float16 0.0f)\n            let a : bool = isInfinity ComplexD.Zero\n            let a : bool = isInfinity V3d.Zero\n            let a : bool = isInfinity C3d.Black\n            let a : bool = isInfinity M44d.Identity\n            let a : bool = isPositiveInfinity 0.0\n            let a : bool = isPositiveInfinity 0.0f\n            let a : bool = isPositiveInfinity (float16 0.0f)\n            let a : bool = isPositiveInfinity ComplexD.Zero\n            let a : bool = isPositiveInfinity C3d.Black\n            let a : bool = isPositiveInfinity V3d.Zero\n            let a : bool = isPositiveInfinity M33d.Zero\n            let a : bool = isNegativeInfinity 0.0\n            let a : bool = isNegativeInfinity 0.0f\n            let a : bool = isNegativeInfinity (float16 0.0f)\n            let a : bool = isNegativeInfinity ComplexD.Zero\n            let a : bool = isNegativeInfinity C3d.Black\n            let a : bool = isNegativeInfinity V3d.Zero\n            let a : bool = isNegativeInfinity M33d.Zero\n            ()\n\n        let approximateEqualsWorking() =\n            let a : bool = approximateEquals 2 42 43\n            let a : bool = approximateEquals 1.0 42.0 43.0\n            let a : bool = approximateEquals 1 V2i.Zero V2i.One\n            let a : bool = approximateEquals 1 M44i.Zero M44i.Identity\n            let a : bool = approximateEquals 1.0 ComplexD.Zero ComplexD.One\n            ()\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Math/Matrix.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Mat =\n\n    [<AutoOpen>]\n    module private Aux =\n        let inline transposeAux (_ : ^z) (m : ^Matrix)  =\n            ((^z or ^Matrix) : (static member Transposed : ^Matrix -> ^Matrix') m)\n\n        let inline determinantAux (_ : ^z) (m : ^Matrix)  =\n            ((^z or ^Matrix) : (static member Determinant : ^Matrix -> ^Scalar) m)\n\n        let inline inverseAux (_ : ^z) (m : ^Matrix)  =\n            ((^z or ^Matrix) : (static member Inverse : ^Matrix -> ^Matrix) m)\n\n        let inline transformAux (_ : ^z) (m : ^Matrix) (v : ^Vector) =\n            ((^z or ^Matrix or ^Vector) : (static member Transform : ^Matrix * ^Vector -> ^Vector') (m, v))\n\n        let inline transformDirAux (_ : ^z) (m : ^Matrix) (v : ^Vector) =\n            ((^z or ^Matrix or ^Vector) : (static member TransformDir : ^Matrix * ^Vector -> ^Vector) (m, v))\n\n        let inline transformPosAux (_ : ^z) (m : ^Matrix) (v : ^Vector) =\n            ((^z or ^Matrix or ^Vector) : (static member TransformPos : ^Matrix * ^Vector -> ^Vector) (m, v))\n\n        let inline transformPosProjAux (_ : ^z) (m : ^Matrix) (v : ^Vector) =\n            ((^z or ^Matrix or ^Vector) : (static member TransformPosProj : ^Matrix * ^Vector -> ^Vector) (m, v))\n\n        let inline anyEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnyEqual : ^a * ^b -> bool) (a, b))\n\n        let inline anyDifferentAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnyDifferent : ^a * ^b -> bool) (a, b))\n\n        let inline anySmallerAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnySmaller : ^a * ^b -> bool) (a, b))\n\n        let inline anyGreaterAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnyGreater : ^a * ^b -> bool) (a, b))\n\n        let inline anySmallerOrEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnySmallerOrEqual : ^a * ^b -> bool) (a, b))\n\n        let inline anyGreaterOrEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnyGreaterOrEqual : ^a * ^b -> bool) (a, b))\n\n        let inline allEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllEqual : ^a * ^b -> bool) (a, b))\n\n        let inline allDifferentAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllDifferent : ^a * ^b -> bool) (a, b))\n\n        let inline allSmallerAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllSmaller : ^a * ^b -> bool) (a, b))\n\n        let inline allGreaterAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllGreater : ^a * ^b -> bool) (a, b))\n\n        let inline allSmallerOrEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllSmallerOrEqual : ^a * ^b -> bool) (a, b))\n\n        let inline allGreaterOrEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllGreaterOrEqual : ^a * ^b -> bool) (a, b))\n\n    /// Returns the transpose of a matrix.\n    let inline transpose (m : ^Matrix) : ^Matrix' =\n        transposeAux Unchecked.defaultof<Mat> m\n\n    /// Returns the determinant of a matrix.\n    let inline det (m : ^Matrix) : ^Scalar =\n        determinantAux Unchecked.defaultof<Mat> m\n\n    /// Returns the inverse of a matrix.\n    let inline inverse (m : ^Matrix) : ^Matrix =\n        inverseAux Unchecked.defaultof<Mat> m\n\n    /// Transforms a vector by a matrix.\n    let inline transform (m : ^Matrix) (v : ^Vector) : ^Vector' =\n        transformAux Unchecked.defaultof<Mat> m v\n\n    /// Transforms a point vector by a matrix (the last element of the vector is presumed 1)\n    let inline transformPos (m : ^Matrix) (v : ^Vector) : ^Vector =\n        transformPosAux Unchecked.defaultof<Mat> m v\n\n    /// Transforms a direction vector by a matrix (the last element of the vector is presumed 0)\n    let inline transformDir (m : ^Matrix) (v : ^Vector) : ^Vector =\n        transformDirAux Unchecked.defaultof<Mat> m v\n\n    /// Transforms a point vector by a matrix (the last element of the vector is presumed 1).\n    /// Projective transform is performed. Perspective Division is performed.\n    let inline transformPosProj (m : ^Matrix) (v : ^Vector) : ^Vector =\n        transformPosProjAux Unchecked.defaultof<Mat> m v\n\n    /// Returns if a = b for any component. One or both of a and b have to be a matrix.\n    let inline anyEqual a b =\n        anyEqualAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a <> b for any component. One or both of a and b have to be a matrix.\n    let inline anyDifferent a b =\n        anyDifferentAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a = b for all components. One or both of a and b have to be a matrix.\n    let inline allEqual a b =\n        allEqualAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a <> b for all components. One or both of a and b have to be a matrix.\n    let inline allDifferent a b =\n        allDifferentAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a < b for any component. One or both of a and b have to be a matrix.\n    let inline anySmaller a b =\n        anySmallerAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a > b for any component. One or both of a and b have to be a matrix.\n    let inline anyGreater a b =\n        anyGreaterAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a < b for all components. One or both of a and b have to be a matrix.\n    let inline allSmaller a b =\n        allSmallerAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a > b for all components. One or both of a and b have to be a matrix.\n    let inline allGreater a b =\n        allGreaterAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a <= b for any component. One or both of a and b have to be a matrix.\n    let inline anySmallerOrEqual a b =\n        anySmallerOrEqualAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a >= b for any component. One or both of a and b have to be a matrix.\n    let inline anyGreaterOrEqual a b =\n        anyGreaterOrEqualAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a <= b for all components. One or both of a and b have to be a matrix.\n    let inline allSmallerOrEqual a b =\n        allSmallerOrEqualAux Unchecked.defaultof<Mat> a b\n\n    /// Returns if a >= b for all components. One or both of a and b have to be a matrix.\n    let inline allGreaterOrEqual a b =\n        allGreaterOrEqualAux Unchecked.defaultof<Mat> a b\n\n    module private CompilerTests =\n\n        let working () =\n            let a = (transpose M33d.Identity) * 0.5\n            let a = (det M22l.Identity) * 5L\n            let a = inverse M22f.Identity\n\n            let a : V4d = transform M44d.Identity V4d.Zero\n            let a : V3d = transform M34d.Zero V4d.Zero\n            let a = (transform M34d.Zero V4d.Zero) * 0.5\n            let a = log (0.5 * (transform M22d.Identity V2d.Zero))\n\n            let a : V3d = transformPos M44d.Identity V3d.Zero\n            let a : V3d = transformPos M34d.Zero V3d.Zero\n            let a = (transformPos M34d.Zero V3d.Zero) * 0.5\n            let a = log (0.5 * (transformPos M33d.Identity V2d.Zero))\n\n            let a : V3d = transformDir M44d.Identity V3d.Zero\n            let a : V3d = transformDir M34d.Zero V3d.Zero\n            let a = (transformDir M34d.Zero V3d.Zero) * 0.5\n            let a = log (0.5 * (transformDir M33d.Identity V2d.Zero))\n\n            let a : V3d = transformPosProj M44d.Identity V3d.Zero\n            let a = log (0.5 * (transformPosProj M33d.Identity V2d.Zero))\n\n            ()\n\n        let comparisonsWorking () =\n            let a : bool = anyEqual M34i.Zero M34i.Zero\n            let a : bool = anyEqual M34i.Zero 0\n            let a : bool = anyEqual 1 M34i.Zero\n            let a : bool = anyDifferent M34i.Zero M34i.Zero\n            let a : bool = anyDifferent M34i.Zero 0\n            let a : bool = anyDifferent 1 M34i.Zero\n            let a : bool = anySmaller M34i.Zero M34i.Zero\n            let a : bool = anySmaller M34i.Zero 0\n            let a : bool = anySmaller 1 M34i.Zero\n            let a : bool = anyGreater M34i.Zero M34i.Zero\n            let a : bool = anyGreater M34i.Zero 0\n            let a : bool = anyGreater 1 M34i.Zero\n            let a : bool = anySmallerOrEqual M34i.Zero M34i.Zero\n            let a : bool = anySmallerOrEqual M34i.Zero 0\n            let a : bool = anySmallerOrEqual 1 M34i.Zero\n            let a : bool = anyGreaterOrEqual M34i.Zero M34i.Zero\n            let a : bool = anyGreaterOrEqual M34i.Zero 0\n            let a : bool = anyGreaterOrEqual 1 M34i.Zero\n            let a : bool = allEqual M34i.Zero M34i.Zero\n            let a : bool = allEqual M34i.Zero 0\n            let a : bool = allEqual 1 M34i.Zero\n            let a : bool = allDifferent M34i.Zero M34i.Zero\n            let a : bool = allDifferent M34i.Zero 0\n            let a : bool = allDifferent 1 M34i.Zero\n            let a : bool = allSmaller M34i.Zero M34i.Zero\n            let a : bool = allSmaller M34i.Zero 0\n            let a : bool = allSmaller 1 M34i.Zero\n            let a : bool = allGreater M34i.Zero M34i.Zero\n            let a : bool = allGreater M34i.Zero 0\n            let a : bool = allGreater 1 M34i.Zero\n            let a : bool = allSmallerOrEqual M34i.Zero M34i.Zero\n            let a : bool = allSmallerOrEqual M34i.Zero 0\n            let a : bool = allSmallerOrEqual 1 M34i.Zero\n            let a : bool = allGreaterOrEqual M34i.Zero M34i.Zero\n            let a : bool = allGreaterOrEqual M34i.Zero 0\n            let a : bool = allGreaterOrEqual 1 M34i.Zero\n            ()\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Trafo =\n\n    let inline private inverseAux (_ : ^z) (t : ^Trafo) =\n        ((^z or ^Trafo) : (static member Inverse : ^Trafo -> ^Trafo) t)\n\n    let inline private forwardAux (_ : ^z) (t : ^Trafo) =\n        ((^z or ^Trafo) : (static member Forward : ^Trafo -> ^Matrix) t)\n\n    let inline private backwardAux (_ : ^z) (t : ^Trafo) =\n        ((^z or ^Trafo) : (static member Backward : ^Trafo -> ^Matrix) t)\n\n    /// Returns the inverse of a transformation.\n    let inline inverse (t : ^Trafo) : ^Trafo =\n        t |> inverseAux Unchecked.defaultof<Trafo>\n\n    /// Returns the forward matrix of a transformation.\n    let inline forward (t : ^Trafo) : ^Matrix =\n        t |> forwardAux Unchecked.defaultof<Trafo>\n\n    /// Returns the backward matrix of a transformation.\n    let inline backward (t : ^Trafo) : ^Matrix =\n        t |> backwardAux Unchecked.defaultof<Trafo>\n\n    module private CompilerTests =\n\n        let working () =\n            let a : Trafo3d = inverse Trafo3d.Identity\n            let a = V3d.Zero |> Mat.transformPos (Trafo3d.Identity |> inverse |> forward)\n\n            let a : M44d = forward Trafo3d.Identity\n            let a : M33f = forward Trafo2f.Identity\n            let a = (forward Trafo3d.Identity) * 5.0\n            let a = V3d.Zero |> Mat.transformPos (Trafo3d.Identity |> forward)\n\n            let a : M44d = backward Trafo3d.Identity\n            let a : M33f = backward Trafo2f.Identity\n            let a = (backward Trafo3d.Identity) * 5.0\n            let a = V3d.Zero |> Mat.transformPos (Trafo3d.Identity |> backward)\n\n            ()"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Math/SVDM33f.fs",
    "content": "﻿namespace Aardvark.Base\r\n\n// Fast 3x3 float matrix SVD\n// Source: McAdams, Aleka, et al. \"Computing the singular value decomposition of 3× 3 matrices with minimal branching and elementary floating point operations.\" University of Wisconsin Madison (2011).\n// Implementation on: \n// https://github.com/ericjang/svd3/blob/master/svd3.h \n// by https://github.com/ericjang\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule M33f =\n\n    let gamma = 5.828427124f\n    let cstar = 0.923879532f\n    let sstar = 0.3826834323f\n    let epsilon = float32 1E-6\n\n    let inline invSqrt x = \n        1.0f / (sqrt x)\n\n    let inline quatToM33 (qV : V4f) =\n        let w = qV.W\n        let x = qV.X\n        let y = qV.Y\n        let z = qV.Z\n\n        let qxx = x*x\n        let qyy = y*y\n        let qzz = z*z\n        let qxz = x*z\n        let qxy = x*y\n        let qyz = y*z\n        let qwx = w*x\n        let qwy = w*y\n        let qwz = w*z\n\n        M33f(\n            1.0f - 2.0f * (qyy + qzz),      2.0f * (qxy - qwz),             2.0f * (qxz + qwy),\n            2.0f * (qxy + qwz),             1.0f - 2.0f * (qxx + qzz),      2.0f * (qyz - qwx),\n            2.0f * (qxz - qwy),             2.0f * (qyz + qwx),             1.0f - 2.0f * (qxx + qyy)\n        )\n\n    let inline givens m11 m12 m22 =\n        let ch = 2.0f * (m11 - m22)\n        let sh = m12\n        let b = gamma*sh*sh < ch*ch\n        let w = invSqrt(ch*ch + sh*sh)\n        let och = if b then w*ch else cstar\n        let osh = if b then w*sh else sstar\n        och, osh\n\n    let inline diagonal m11 m21 m22 m31 m32 m33 =\n        M33f(m11, m21, m31, m21, m22, m32, m31, m32, m33)\n\n    let inline conjugate (x : int) (y : int) (z : int) (m : M33f) (qV : V4f) =\n        let (ch,sh) = givens m.M00 m.M10 m.M11\n\n        let scale = ch*ch + sh*sh\n        let a = (ch*ch-sh*sh)/scale\n        let b = (2.0f*sh*ch)/scale\n\n        let m11 =  a*(a*m.M00+b*m.M10)  + b*(a*m.M10 + b*m.M11)\n        let m21 =  a*(-b*m.M00+a*m.M10) + b*(-b*m.M10 + a*m.M11)\n        let m22 = -b*(-b*m.M00+a*m.M10) + a*(-b*m.M10 + a*m.M11)\n        let m31 = a*m.M20 + b*m.M21\n        let m32 = -b*m.M20 + a*m.M21\n        let m33 = m.M22\n        \n        let tmp = V3f(qV.X*sh, qV.Y*sh, qV.Z*sh)\n        let shScaled = qV.W * sh\n\n        let q1 = qV.X * ch\n        let q2 = qV.Y * ch\n        let q3 = qV.Z * ch\n        let q4 = qV.W * ch\n\n        let q = [|q1; q2; q3; q4|]\n\n        q.[z] <- q.[z] + shScaled\n        q.[3] <- q.[3] - tmp.[z]\n        q.[x] <- q.[x] + tmp.[y]\n        q.[y] <- q.[y] - tmp.[x]\n\n        let ma = diagonal m22 m32 m33 m21 m31 m11\n        let va = V4f(q.[0], q.[1], q.[2], q.[3])\n        \n        ma,va\n\n\n    let inline diagonalizeSymmetric (m : M33f) =\n        \n        let mutable m = m\n        let mutable qV = V4f(0, 0, 0, 1)\n\n        let doIt (mm,mqV) =\n            m <- mm\n            qV <- mqV\n            \n        for _ in 0..4 do\n            doIt (conjugate 0 1 2 m qV)\n            doIt (conjugate 1 2 0 m qV)\n            doIt (conjugate 2 0 1 m qV)\n        m,qV\n\n    let inline swap c x y =\n        if c then \n            (y,-x)\n        else\n            (x,y)\n\n    let inline fswap c x y =\n        if c then\n            (y,x)\n        else\n            (x,y)\n\n    let inline decomposeAndSort (m : M33f) (q : M33f) =\n        let rho1 = m.C0.LengthSquared\n        let rho2 = m.C1.LengthSquared\n        let rho3 = m.C2.LengthSquared\n\n        let c = rho1 < rho2\n        let (m11,m12) = swap c m.M00 m.M01\n        let (m21,m22) = swap c m.M10 m.M11\n        let (m31,m32) = swap c m.M20 m.M21\n        \n        let (q11,q12) = swap c q.M00 q.M01\n        let (q21,q22) = swap c q.M10 q.M11\n        let (q31,q32) = swap c q.M20 q.M21\n        \n        let (rho1,rho2) = fswap c rho1 rho2\n\n        let c = rho1 < rho3\n        let (m11,m13) = swap c m11 m.M02\n        let (m21,m23) = swap c m21 m.M12\n        let (m31,m33) = swap c m31 m.M22\n        \n        let (q11,q13) = swap c q11 q.M02\n        let (q21,q23) = swap c q21 q.M12\n        let (q31,q33) = swap c q31 q.M22\n\n        let (rho1,rho3) = fswap c rho1 rho3\n\n        let c = rho2 < rho3\n        let (m12,m13) = swap c m12 m13\n        let (m22,m23) = swap c m22 m23\n        let (m32,m33) = swap c m32 m33\n        \n        let (q12,q13) = swap c q12 q13\n        let (q22,q23) = swap c q22 q23\n        let (q32,q33) = swap c q32 q33\n        \n        let M = M33f(m11,m12,m13,m21,m22,m23,m31,m32,m33)\n        let V = M33f(q11,q12,q13,q21,q22,q23,q31,q32,q33)\n\n        M,V\n\n    let inline QRgivens p a =\n        let rho = sqrt(p*p + a*a)\n        \n        let ch = (abs p) + max rho epsilon\n        let sh = if rho > epsilon then a else 0.0f\n        let (sh,ch) = fswap (p<0.0f) sh ch\n        let w = invSqrt(ch*ch + sh*sh)\n        let ch = w * ch\n        let sh = w * sh\n        ch,sh\n\n    let inline QRdecompose (m : M33f) =\n        let (ch1,sh1) = QRgivens m.M00 m.M10\n        let a = 1.0f - 2.0f * sh1 * sh1\n        let b = 2.0f * ch1 * sh1\n\n        let r11 = a * m.M00 + b * m.M10\n        let r12 = a * m.M01 + b * m.M11\n        let r13 = a * m.M02 + b * m.M12 \n        let r21 = -b* m.M00 + a * m.M10\n        let r22 = -b* m.M01 + a * m.M11\n        let r23 = -b* m.M02 + a * m.M12\n        let r31 = m.M20\n        let r32 = m.M21\n        let r33 = m.M22\n\n        let (ch2,sh2) = QRgivens r11 r31\n        let a = 1.0f - 2.0f * sh2 * sh2\n        let b = 2.0f * ch2 * sh2\n\n        let b11 = a * r11 + b * r31\n        let b12 = a * r12 + b * r32\n        let b13 = a * r13 + b * r33\n        let b21 = r21\n        let b22 = r22\n        let b23 = r23\n        let b31 = -b* r11 + a * r31\n        let b32 = -b* r12 + a * r32\n        let b33 = -b* r13 + a * r33\n\n        let (ch3,sh3) = QRgivens b22 b32\n        let a = 1.0f - 2.0f * sh3 * sh3\n        let b = 2.0f * ch3 * sh3\n\n        let r11 = b11\n        let r12 = b12\n        let r13 = b13\n        let r21 = a * b21 + b * b31\n        let r22 = a * b22 + b * b32\n        let r23 = a * b23 + b * b33\n        let r31 = -b* b21 + a * b31\n        let r32 = -b* b22 + a * b32\n        let r33 = -b* b23 + a * b33\n        \n        let sh1s = sh1*sh1\n        let sh2s = sh2*sh2\n        let sh3s = sh3*sh3\n\n        let q11 = (-1.0f + 2.0f * sh1s) * (-1.0f + 2.0f * sh2s)\n        let q12 = 4.0f * ch2 * ch3 * (-1.0f + 2.0f * sh1s) * sh2 * sh3 + 2.0f * ch1 * sh1 * (-1.0f + 2.0f * sh3s)\n        let q13 = 4.0f * ch1 * ch3 * sh1 * sh3 - 2.0f * ch2 * (-1.0f + 2.0f * sh1s) * sh2 * (-1.0f + 2.0f * sh3s)\n        \n        let q21 = 2.0f * ch1 * sh1 * (1.0f - 2.0f * sh2s)\n        let q22 = -8.0f * ch1 * ch2 * ch3 * sh1 * sh2 * sh3 + (-1.0f + 2.0f * sh1s) * (-1.0f + 2.0f * sh3s)\n        let q23 = -2.0f * ch3 * sh3 + 4.0f * sh1 * (ch3 * sh1 * sh3 + ch1 * ch2 * sh2 * (-1.0f + 2.0f * sh3s))\n\n        let q31 = 2.0f * ch2 * sh2\n        let q32 = 2.0f * ch3 * (1.0f - 2.0f * sh2s) * sh3\n        let q33 = (-1.0f + 2.0f * sh2s) * (-1.0f + 2.0f * sh3s)\n\n        let Q = M33f(q11,q12,q13,q21,q22,q23,q31,q32,q33)\n        let R = M33f(r11,r12,r13,r21,r22,r23,r31,r32,r33)\n\n        (Q,R)\n\n    let inline svd (m : M33f) =\n        \n        let norm = m.Transposed * m\n\n        let (_, qV) = diagonalizeSymmetric norm\n\n        let quat = quatToM33 qV\n\n        let B = m * quat\n\n        let (M,V) = decomposeAndSort B quat\n\n        let (U,S) = QRdecompose M\n\n        (U,S,V)\n\r\n\r\n\r\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Math/Vectors.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Vec =\n\n    [<AutoOpen>]\n    module private Aux =\n        let inline dotAux (_ : ^z) (a : ^a) (b : ^a) =\n            ((^z or ^a) : (static member Dot : ^a * ^a -> ^b) (a, b))\n\n        let inline crossAux (_ : ^z) (a : ^a) (b : ^a) =\n            ((^z or ^a) : (static member Cross : ^a * ^a -> ^a) (a, b))\n\n        let inline distanceAux (_ : ^z) (a : ^a) (b : ^a) =\n            ((^z or ^a) : (static member Distance : ^a * ^a -> ^b) (a, b))\n\n        let inline distanceSquaredAux (_ : ^z) (a : ^a) (b : ^a) =\n            ((^z or ^a) : (static member DistanceSquared : ^a * ^a -> ^b) (a, b))\n\n        let inline reflectAux (_ : ^z) (n : ^a) (v : ^a) =\n            ((^z or ^a) : (static member Reflect : ^a * ^a -> ^a) (v, n))\n\n        let inline refractAux (_ : ^z) (eta : ^b) (n : ^a) (v : ^a) =\n            ((^z or ^a) : (static member Refract : ^a * ^a * ^b -> ^a) (v, n, eta))\n\n        let inline anyEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnyEqual : ^a * ^b -> bool) (a, b))\n\n        let inline anyDifferentAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnyDifferent : ^a * ^b -> bool) (a, b))\n\n        let inline anySmallerAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnySmaller : ^a * ^b -> bool) (a, b))\n\n        let inline anyGreaterAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnyGreater : ^a * ^b -> bool) (a, b))\n\n        let inline anySmallerOrEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnySmallerOrEqual : ^a * ^b -> bool) (a, b))\n\n        let inline anyGreaterOrEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AnyGreaterOrEqual : ^a * ^b -> bool) (a, b))\n\n        let inline allEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllEqual : ^a * ^b -> bool) (a, b))\n\n        let inline allDifferentAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllDifferent : ^a * ^b -> bool) (a, b))\n\n        let inline allSmallerAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllSmaller : ^a * ^b -> bool) (a, b))\n\n        let inline allGreaterAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllGreater : ^a * ^b -> bool) (a, b))\n\n        let inline allSmallerOrEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllSmallerOrEqual : ^a * ^b -> bool) (a, b))\n\n        let inline allGreaterOrEqualAux (_ : ^z) (a : ^a) (b : ^b) =\n            ((^z or ^a or ^b) : (static member AllGreaterOrEqual : ^a * ^b -> bool) (a, b))\n\n    /// Computes the dot product of two vectors a and b.\n    let inline dot a b =\n        dotAux Unchecked.defaultof<Vec> a b\n\n    /// Computes the cross product of two 3D vectors a and b.\n    let inline cross a b =\n        crossAux Unchecked.defaultof<Vec> a b\n\n    /// Computes the distance between a and b\n    let inline distance a b =\n        distanceAux Unchecked.defaultof<Vec> a b\n\n    /// Computes the squared distance between a and b\n    let inline distanceSquared a b =\n        distanceSquaredAux Unchecked.defaultof<Vec> a b\n\n    /// Computes the length of the vector v.\n    let inline length< ^a, ^b when ^a : (member Length : ^b )> (v : ^a) =\n        (^a : (member Length : ^b ) (v))\n\n    /// Computes the squared length of the vector v.\n    let inline lengthSquared< ^a, ^b when ^a : (member LengthSquared : ^b )> (v : ^a) =\n        (^a : (member LengthSquared : ^b ) (v))\n\n    /// Returns the vector v with unit length.\n    let inline normalize< ^a, ^b when ^a : (member Normalized : ^b )> (v : ^a) =\n        (^a : (member Normalized : ^b ) v)\n\n    /// Returns the reflection direction of v for the normal n (should be normalized).\n    let inline reflect n v =\n        reflectAux Unchecked.defaultof<Vec> n v\n\n    /// Returns the refraction direction of v for the normal n and ratio of refraction indices eta.\n    /// v and n should be normalized.\n    let inline refract eta n v =\n        refractAux Unchecked.defaultof<Vec> eta n v\n\n    /// Returns the x-component of the vector v.\n    let inline x< ^a, ^b when ^a : (member P_X : ^b)> (v : ^a) =\n        (^a : (member P_X : ^b) v)\n\n    /// Returns the y-component of the vector v.\n    let inline y< ^a, ^b when ^a : (member P_Y : ^b)> (v : ^a) =\n        (^a : (member P_Y : ^b) v)\n\n    /// Returns the z-component of the vector v.\n    let inline z< ^a, ^b when ^a : (member P_Z : ^b)> (v : ^a) =\n        (^a : (member P_Z : ^b) v)\n\n    /// Returns the w-component of the vector v.\n    let inline w< ^a, ^b when ^a : (member P_W : ^b)> (v : ^a) =\n        (^a : (member P_W : ^b) v)\n\n    /// Returns the xy-components of the vector v.\n    let inline xy< ^a, ^b when ^a : (member XY : ^b)> (v : ^a) =\n        (^a : (member XY : ^b) v)\n\n    /// Returns the yz-components of the vector v.\n    let inline yz< ^a, ^b when ^a : (member YZ : ^b)> (v : ^a) =\n        (^a : (member YZ : ^b) v)\n\n    /// Returns the zw-components of the vector v.\n    let inline zw< ^a, ^b when ^a : (member ZW : ^b)> (v : ^a) =\n        (^a : (member ZW : ^b) v)\n\n    /// Returns the xyz-components of the vector v.\n    let inline xyz< ^a, ^b when ^a : (member XYZ : ^b)> (v : ^a) =\n        (^a : (member XYZ : ^b) v)\n\n    /// Returns the yzw-components of the vector v.\n    let inline yzw< ^a, ^b when ^a : (member YZW : ^b)> (v : ^a) =\n        (^a : (member YZW : ^b) v)\n\n    /// Returns if a = b for any component. One or both of a and b have to be a vector.\n    let inline anyEqual a b =\n        anyEqualAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a <> b for any component. One or both of a and b have to be a vector.\n    let inline anyDifferent a b =\n        anyDifferentAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a = b for all components. One or both of a and b have to be a vector.\n    let inline allEqual a b =\n        allEqualAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a <> b for all components. One or both of a and b have to be a vector.\n    let inline allDifferent a b =\n        allDifferentAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a < b for any component. One or both of a and b have to be a vector.\n    let inline anySmaller a b =\n        anySmallerAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a > b for any component. One or both of a and b have to be a vector.\n    let inline anyGreater a b =\n        anyGreaterAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a < b for all components. One or both of a and b have to be a vector.\n    let inline allSmaller a b =\n        allSmallerAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a > b for all components. One or both of a and b have to be a vector.\n    let inline allGreater a b =\n        allGreaterAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a <= b for any component. One or both of a and b have to be a vector.\n    let inline anySmallerOrEqual a b =\n        anySmallerOrEqualAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a >= b for any component. One or both of a and b have to be a vector.\n    let inline anyGreaterOrEqual a b =\n        anyGreaterOrEqualAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a <= b for all components. One or both of a and b have to be a vector.\n    let inline allSmallerOrEqual a b =\n        allSmallerOrEqualAux Unchecked.defaultof<Vec> a b\n\n    /// Returns if a >= b for all components. One or both of a and b have to be a vector.\n    let inline allGreaterOrEqual a b =\n        allGreaterOrEqualAux Unchecked.defaultof<Vec> a b\n\n    module private CompilerTests =\n\n        let dotWorking () =\n            let a : float = dot V3d.One V3d.Zero\n            let a : int = dot V3i.One V3i.Zero\n            ()\n\n        let crossWorking () =\n            let a : V3d = cross V3d.One V3d.Zero\n            let a : V3i = cross V3i.One V3i.Zero\n            ()\n\n        let distanceWorking () =\n            let a : float = distance V3d.One V3d.Zero\n            let a : float32 = distance V3f.One V3f.Zero\n            let a : float = distance V3i.One V3i.Zero\n            ()\n\n        let distanceSquaredWorking () =\n            let a : float = distanceSquared V3d.One V3d.Zero\n            let a : float32 = distanceSquared V3f.One V3f.Zero\n            let a : int = distanceSquared V3i.One V3i.Zero\n            ()\n\n        let lengthWorking () =\n            let a : float32 = length V3f.One\n            let a : float = length V3d.One\n            let a : float = length V3i.One\n            ()\n\n        let lengthSquaredWorking () =\n            let a : float32 = lengthSquared V3f.One\n            let a : float = lengthSquared V3d.One\n            let a : int = lengthSquared V3i.One\n            ()\n\n        let normalizeWorking () =\n            let a : V3f = normalize V3f.One\n            let a : V3d = normalize V3d.One\n            let a : V3d = normalize V3i.One\n            ()\n\n        let reflectWorking () =\n            let a : V3f = reflect V3f.One V3f.Zero\n            let a : V3d = reflect V3d.One V3d.Zero\n            ()\n\n        let refractWorking () =\n            let a : V3f = refract 0.0f V3f.One V3f.Zero\n            let a : V3d = refract 0.0 V3d.One V3d.Zero\n            ()\n\n        let swizzlesWorking () =\n            let a : float = x V3d.One\n            let a : float = y V3d.One\n            let a : float = z V3d.One\n            let a : float = w V4d.One\n            let a : V2d = xy V3d.One\n            let a : V2d = yz V3d.One\n            let a : V2d = zw V4d.One\n            let a : V3d = xyz V4d.One\n            let a : V3d = yzw V4d.One\n            ()\n\n        let comparisonsWorking () =\n            let a : bool = anyEqual V3i.One V3i.Zero\n            let a : bool = anyEqual V3i.One 0\n            let a : bool = anyEqual 1 V3i.Zero\n            let a : bool = anyDifferent V3i.One V3i.Zero\n            let a : bool = anyDifferent V3i.One 0\n            let a : bool = anyDifferent 1 V3i.Zero\n            let a : bool = anySmaller V3i.One V3i.Zero\n            let a : bool = anySmaller V3i.One 0\n            let a : bool = anySmaller 1 V3i.Zero\n            let a : bool = anyGreater V3i.One V3i.Zero\n            let a : bool = anyGreater V3i.One 0\n            let a : bool = anyGreater 1 V3i.Zero\n            let a : bool = anySmallerOrEqual V3i.One V3i.Zero\n            let a : bool = anySmallerOrEqual V3i.One 0\n            let a : bool = anySmallerOrEqual 1 V3i.Zero\n            let a : bool = anyGreaterOrEqual V3i.One V3i.Zero\n            let a : bool = anyGreaterOrEqual V3i.One 0\n            let a : bool = anyGreaterOrEqual 1 V3i.Zero\n            let a : bool = allEqual V3i.One V3i.Zero\n            let a : bool = allEqual V3i.One 0\n            let a : bool = allEqual 1 V3i.Zero\n            let a : bool = allDifferent V3i.One V3i.Zero\n            let a : bool = allDifferent V3i.One 0\n            let a : bool = allDifferent 1 V3i.Zero\n            let a : bool = allSmaller V3i.One V3i.Zero\n            let a : bool = allSmaller V3i.One 0\n            let a : bool = allSmaller 1 V3i.Zero\n            let a : bool = allGreater V3i.One V3i.Zero\n            let a : bool = allGreater V3i.One 0\n            let a : bool = allGreater 1 V3i.Zero\n            let a : bool = allSmallerOrEqual V3i.One V3i.Zero\n            let a : bool = allSmallerOrEqual V3i.One 0\n            let a : bool = allSmallerOrEqual 1 V3i.Zero\n            let a : bool = allGreaterOrEqual V3i.One V3i.Zero\n            let a : bool = allGreaterOrEqual V3i.One 0\n            let a : bool = allGreaterOrEqual 1 V3i.Zero\n            ()"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Native/BlobStore.fs",
    "content": "﻿namespace Aardvark.Base.Native\n\nopen Aardvark.Base\nopen System\n\ntype IBlobFile =\n    abstract member Name        : Guid\n    abstract member Exists      : bool\n    abstract member Size        : int64\n    abstract member Read        : unit -> byte[]\n    abstract member Write       : byte[] -> unit\n    abstract member Delete      : unit -> unit\n    abstract member CopyTo      : IBlobFile -> unit\n\ntype IBlobStore =\n    inherit IDisposable\n    abstract member Memory      : Mem\n    abstract member Create      : unit -> IBlobFile\n    abstract member Get         : Guid -> IBlobFile"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Native/FileTable.fs",
    "content": "﻿namespace Aardvark.Base.Native\n\n#nowarn \"9\"\n\nopen System\nopen System.Runtime.InteropServices\nopen System.Collections.Generic\nopen Aardvark.Base\n\n[<StructLayout(LayoutKind.Sequential)>]\ntype Entry =\n    struct\n        val mutable public Key      : Guid\n        val mutable public Offset   : int64\n        val mutable public Size     : int64\n        val mutable public HashCode : int\n        val mutable public Next     : int\n\n        override x.ToString() =\n            sprintf \"{ Key = %A; Offset = %d; Size = %d }\" x.Key x.Offset x.Size\n\n        new(k : Guid, o : int64, s : int64, h : int, n : int) = { Key = k; Offset = o; Size = s; HashCode = h; Next = n }\n    end\n\n\n[<StructLayout(LayoutKind.Explicit, Size = 40)>]\ntype private DictHeader =\n    struct\n        [<FieldOffset(0)>]\n        val mutable public Magic            : int64\n\n        [<FieldOffset(8)>]\n        val mutable public CapacityIndex    : int\n\n        [<FieldOffset(12)>]\n        val mutable public Capacity         : int\n\n        [<FieldOffset(16)>]\n        val mutable public FreeList         : int\n\n        [<FieldOffset(24)>]\n        val mutable public Count            : int\n\n        [<FieldOffset(28)>]\n        val mutable public FreeCount        : int\n    end \n\n[<AutoOpen>]\nmodule private ``DictHeader Extensions`` =\n    \n    let inline (==) (a : Guid) (b : Guid) =\n        a.Equals(b)\n    \n    let inline private read<'a when 'a : unmanaged> (ptr : ptr) : 'a =\n        ptr.Read<'a>()\n\n    let inline private write<'a when 'a : unmanaged> (v : 'a) (ptr : ptr) : unit =\n        ptr.Write<'a>(v)\n\n\n\n    let inline (!!) (ptr : ptr<'a>) = ptr.Value\n    let inline (!=) (ptr : ptr<'a>) (v : 'a) = ptr.Value <- v\n\n\n\n    type ptr with\n        member x.Magic\n            with inline get() = x |> read<int64>\n            and inline set m  = x |> write<int64> m\n\n        member x.CapacityIndex\n            with inline get() = (8n + x) |> read<int>\n            and inline set m  = (8n + x) |> write<int> m\n\n        member x.Capacity\n            with inline get() = (12n + x) |> read<int>\n            and inline set m  = (12n + x) |> write<int> m\n\n\n        member x.FreeList\n            with inline get() = (16n + x) |> read<int>\n            and inline set m  = (16n + x) |> write<int> m\n\n        member x.Count\n            with inline get() = (24n + x) |> read<int>\n            and inline set m  = (24n + x) |> write<int> m\n\n        member x.FreeCount\n            with inline get() = (28n + x) |> read<int>\n            and inline set m  = (28n + x) |> write<int> m\n\n\n        member x.Key\n            with inline get() = x |> read<Guid>\n            and inline set m  = x |> write<Guid> m\n\n        member x.Offset\n            with inline get() = (16n + x) |> read<int64>\n            and inline set m  = (16n + x) |> write<int64> m\n\n        member x.Size\n            with inline get() = (24n + x) |> read<int64>\n            and inline set m  = (24n + x) |> write<int64> m\n\n        member x.HashCode\n            with inline get() = (32n + x) |> read<int>\n            and inline set m  = (32n + x) |> write<int> m\n\n        member x.Next\n            with inline get() = (36n + x) |> read<int>\n            and inline set m  = (36n + x) |> write<int> m\n\n    let inline (.+) (ptr : ptr<'a>) (i : int) : ptr<'a> =\n        ptr + i\n\n\ntype private DictStore =\n    {\n        size        : int64\n        pointer     : Memory\n        header      : ptr<DictHeader>\n        entries     : ptr<Entry>\n        buckets     : ptr<int>\n    }\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule private DictStore =\n    let private magic = 0x4a3214b10905af7aL\n    let private se = sizeof<Entry> |> int64\n    let private si = sizeof<int> |> int64\n    let private sh = sizeof<DictHeader> |> int64\n\n\n    let primeSizes =\n        [|\n            (*    prime no.           prime *)\n            (*           2                3       +  1 = 2^2 *)\n            (*           4 *) 7                // +  1 = 2^3, minimal size\n            (*           6 *) 13               // +  3 = 2^4\n            (*          11 *) 31               // +  1 = 2^5\n            (*          18 *) 61               // +  3 = 2^6\n            (*          31 *) 127              // +  1 = 2^7\n            (*          54 *) 251              // +  5 = 2^8\n            (*          97 *) 509              // +  3 = 2^9\n            (*         172 *) 1021             // +  3 = 2^10\n            (*         309 *) 2039             // +  9 = 2^11\n            (*         564 *) 4093             // +  3 = 2^12\n            (*        1028 *) 8191             // +  1 = 2^13\n            (*        1900 *) 16381            // +  3 = 2^14\n            (*        3512 *) 32749            // + 19 = 2^15\n            (*        6542 *) 65521            // + 15 = 2^16\n            (*       12251 *) 131071           // +  1 = 2^17\n            (*       23000 *) 262139           // +  5 = 2^18\n            (*       43390 *) 524287           // +  1 = 2^19\n            (*       82025 *) 1048573          // +  3 = 2^20\n            (*      155611 *) 2097143          // +  9 = 2^21\n            (*      295947 *) 4194301          // +  3 = 2^22\n            (*      564163 *) 8388593          // + 15 = 2^23\n            (*     1077871 *) 16777213         // +  3 = 2^24\n            (*     2063689 *) 33554393         // + 39 = 2^25\n            (*     3957809 *) 67108859         // +  5 = 2^26\n            (*     7603553 *) 134217689        // + 39 = 2^27\n            (*    14630843 *) 268435399        // + 57 = 2^28\n            (*    28192750 *) 536870909        // +  3 = 2^29\n            (*    54400028 *) 1073741789       // + 35 = 2^30\n            (*   105097565 *) 2147483647       // +  1 = 2^31\n        |]\n\n\n    let empty =\n        {\n            size = 0L\n            pointer = Unchecked.defaultof<_>\n            header = ptr<_>.Null\n            entries = ptr<_>.Null\n            buckets = ptr<_>.Null\n        }\n        \n    let private isDict (ptr : ptr) =\n        ptr.Read<int64>() = magic\n\n    let create (mem : Memory) (capacityIndex : int) =      \n        let capacity = primeSizes.[capacityIndex]\n        // create a new dictionary\n        let size = sh + int64 capacity * (se + si)\n        mem.Clear size\n\n        let pHeader = Ptr.cast mem\n        let pEntries = Ptr.cast (mem + sh)\n        let pBuckets = Ptr.cast (mem + sh + (int64 capacity * se))\n\n        pHeader != \n            DictHeader(\n                Magic = magic,\n                CapacityIndex = capacityIndex,\n                Capacity = capacity,\n                FreeList = -1,\n                Count = 0,\n                FreeCount = 0\n            )\n\n\n        {\n            size = size\n            pointer = mem\n            header = pHeader\n            entries = pEntries\n            buckets = pBuckets\n        }\n\n    let getOrCreate (mem : Memory) (capacityIndex : int) =      \n        if mem.Size >= 8L && isDict mem then\n            // read the dictionary\n            let size = mem.Size\n            let mapName = Guid.NewGuid() |> string\n\n            let pHeader = Ptr.cast mem\n            let header : DictHeader = !!pHeader\n            let pEntries = Ptr.cast (mem + nativeint sh)\n            let pBuckets = Ptr.cast (mem + nativeint sh + nativeint (int64 header.Capacity * se))\n\n            {\n                size = size\n                pointer = mem\n                header = pHeader\n                entries = pEntries\n                buckets = pBuckets\n            }\n\n        else\n            create mem capacityIndex\n\n    let realloc (store : DictStore) (capacityIndex : int) =\n        let capacity = primeSizes.[capacityIndex]\n        let size = sh + int64 capacity * (se + si)\n\n        store.pointer.Realloc(size)\n\n        let pHeader = Ptr.cast store.pointer\n        let pEntries = Ptr.cast (store.pointer + sh)\n        let pBuckets = Ptr.cast (store.pointer + sh + (int64 capacity * se))\n\n        Marshal.Set(pBuckets.Pointer, 0, unativeint (sizeof<int> * capacity))\n\n        pHeader.CapacityIndex <- capacityIndex\n        pHeader.Capacity <- capacity\n\n        {\n            size = size\n            pointer = store.pointer\n            header = pHeader\n            entries = pEntries\n            buckets = pBuckets\n        }\n\n\n    let release (s : DictStore) =\n        s.pointer.Dispose()\n\n\ntype FileTable(mem : Memory) =\n\n    static let initialExp = 10\n    let mutable store = DictStore.getOrCreate mem (initialExp - 3)\n    let mutable header = store.header\n\n    member private x.Grow () : unit =\n        // TODO: backup!!!!\n\n        let oldHeader = !!header\n        let newCapacityIndex = 1 + oldHeader.CapacityIndex\n        let count = oldHeader.Count        \n        store <- DictStore.realloc store newCapacityIndex\n        header <- store.header\n\n\n        let cap = header.Capacity\n        let mutable pEntry = store.entries\n        for i in 0 .. count-1 do\n            if not (pEntry.Key == Guid.Empty) then\n                let bucket = pEntry.HashCode % cap\n                pEntry.Next <- store.buckets.[bucket] - 1\n                store.buckets.[bucket] <- i + 1\n\n            pEntry <- pEntry .+ 1\n\n\n        // TODO: remove backup\n        ()\n\n\n    member private x.FindEntry(key : Guid, hashCode : int) =\n        let index = hashCode % header.Capacity\n        let id = store.buckets.[index] - 1\n        if id < 0 then \n            -1\n        else\n            let mutable pEntry = store.entries .+ id\n            if pEntry.HashCode = hashCode && pEntry.Key == key then\n                id\n            else\n                let next = pEntry.Next\n                if next >= 0 then\n                    let rec search (id : int) (pEntry : ptr<Entry>) =\n                        if pEntry.HashCode = hashCode && pEntry.Key == key then \n                            id\n                        else\n                            let next = pEntry.Next\n                            if next >= 0 then\n                                search next (store.entries .+ pEntry.Next)\n                            else\n                                -1\n\n                    search next (store.entries .+ next)\n                else\n                    -1     \n\n    member private x.FindEntry(key : Guid) =\n        let hashCode = key.GetHashCode() &&& 0x7FFFFFFF\n        x.FindEntry(key, hashCode)\n\n    member private x.Set(key : Guid, offset : int64, size : int64) =\n        let hashCode = key.GetHashCode() &&& 0x7FFFFFFF\n        let mutable index = hashCode % header.Capacity\n        let id = x.FindEntry(key, hashCode)\n\n        if id >= 0 then\n            let p = store.entries .+ id\n            p.Offset <- offset\n            p.Size <- size\n        else\n            let freeCount = header.FreeCount\n            let entryId = \n                if freeCount > 0 then\n                    let newBucket = header.FreeList\n                    header.FreeList <- (store.entries .+ newBucket).Next\n                    header.FreeCount <- freeCount - 1\n                    newBucket\n                else\n                    let count = header.Count\n                    if count = header.Capacity then\n                        x.Grow()\n                        index <- hashCode % header.Capacity\n\n                    header.Count <- count + 1\n                    count\n\n            let pEntry = store.entries .+ entryId\n            let pBucket = store.buckets .+ index\n            pEntry.Key <- key\n            pEntry.Offset <- offset\n            pEntry.Size <- size\n            pEntry.HashCode <- hashCode\n            pEntry.Next <- !!pBucket - 1\n            pBucket != 1 + entryId\n\n        \n    member private x.Get(key : Guid) =\n        let id = x.FindEntry(key)\n        if id < 0 then\n            failwithf \"key not found: %A\" key\n        else\n            let p = store.entries .+ id\n            (p.Offset, p.Size)\n\n\n    member x.Remove(key : Guid) =\n        let hashCode = key.GetHashCode() &&& 0x7FFFFFFF\n        let index = hashCode % header.Capacity\n        let id = store.buckets.[index] - 1\n        if id < 0 then \n            false\n        else\n            let pEntry = store.entries .+ id\n            let mutable entryId = -1\n             \n            if pEntry.HashCode = hashCode && pEntry.Key == key then\n                store.buckets.[index] <- pEntry.Next + 1\n                entryId <- id\n            else\n                let next = pEntry.Next\n                if next >= 0 then\n                    let rec search (pLast : ptr<Entry>) (id : int) (pEntry : ptr<Entry>) =\n                        if pEntry.HashCode = hashCode && pEntry.Key == key then \n                            pLast.Next <- pEntry.Next\n                            entryId <- id\n                        else\n                            let next = pEntry.Next\n                            if next >= 0 then\n                                search pEntry next (store.entries .+ pEntry.Next)\n\n                    search pEntry next (store.entries .+ next)\n\n\n\n            if entryId >= 0 then\n    \n                let pEntry = store.entries .+ entryId\n                let nextFree =\n                    if header.FreeCount > 0 then header.FreeList\n                    else -1\n                pEntry != Entry(Guid.Empty, 0L, 0L, -1, nextFree)\n                header.FreeList <- entryId\n                header.FreeCount <- header.FreeCount + 1\n\n                true\n            else\n                false\n\n    member x.TryGetValue(key : Guid, [<Out>] value : byref<int64 * int64>) =\n        let id = x.FindEntry(key)\n        if id < 0 then\n            false\n        else\n            let p = store.entries .+ id\n            value <- (p.Offset, p.Size)\n            true\n\n    member x.Count =\n        header.Count - header.FreeCount\n\n    member x.Item\n        with get (key : Guid) = x.Get key\n        and set (key : Guid) (offset : int64, size : int64) = x.Set(key, offset, size)\n\n    member x.GetOrAdd(key : Guid, f : Guid -> int64 * int64) =\n        let hashCode = key.GetHashCode() &&& 0x7FFFFFFF\n        let mutable index = hashCode % header.Capacity\n        let id = x.FindEntry(key, hashCode)\n\n        if id >= 0 then\n            let p = store.entries .+ id\n            (p.Offset, p.Size)\n        else\n            let offset, size = f key\n            let freeCount = header.FreeCount\n            let entryId = \n                if freeCount > 0 then\n                    let newBucket = header.FreeList\n                    header.FreeList <- (store.entries .+ newBucket).Next\n                    header.FreeCount <- freeCount - 1\n                    newBucket\n                else\n                    let count = header.Count\n                    if count = header.Capacity then\n                        x.Grow()\n                        index <- hashCode % header.Capacity\n\n                    header.Count <- count + 1\n                    count\n\n            let pEntry = store.entries .+ entryId\n            let pBucket = store.buckets .+ index\n            pEntry.Key <- key\n            pEntry.Offset <- offset\n            pEntry.Size <- size\n            pEntry.HashCode <- hashCode\n            pEntry.Next <- !!pBucket - 1\n            pBucket != 1 + entryId\n            (offset, size)\n\n    member x.ContainsKey (key : Guid) =\n        let id = x.FindEntry(key)\n        id >= 0\n\n\n    member x.Dispose() =\n        DictStore.release store\n        store <- DictStore.empty\n\n    interface IDisposable with\n        member x.Dispose() = x.Dispose()\n\n    interface System.Collections.IEnumerable with\n        member x.GetEnumerator() = new FileDictEnumerator(store) :> _\n\n    interface System.Collections.Generic.IEnumerable<Entry> with\n        member x.GetEnumerator() = new FileDictEnumerator(store) :> _\n\nand private FileDictEnumerator(store : DictStore) =\n    static let nullPtr : ptr<Entry> = ptr<_>.Null\n\n    let cnt = store.header.Count\n    let mutable i = -1\n    let mutable ptr = store.entries .+ -1\n\n    member x.MoveNext() =\n        i <- i + 1\n        ptr <- ptr .+ 1\n        while i < cnt && (store.entries .+ i).HashCode < 0 do\n            i <- i + 1\n            ptr <- ptr .+ 1\n\n        i < cnt\n\n    member x.Current : Entry =\n        !!ptr\n\n    member x.Reset() =\n        i <- -1\n        ptr <- store.entries .+ -1\n\n    interface System.Collections.IEnumerator with\n        member x.Current = x.Current :> obj\n        member x.MoveNext() = x.MoveNext()\n        member x.Reset() = x.Reset()\n\n    interface IEnumerator<Entry> with\n        member x.Current = x.Current\n        member x.Dispose() = ()\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Native/Manager.fs",
    "content": "﻿namespace Aardvark.Base.Native\n\nopen System\nopen System.Threading\nopen System.Runtime.CompilerServices\nopen Aardvark.Base\n\n\ntype MemoryManager(store : Memory) as this =\n    let mutable capacity = store.Size\n    let mutable allocated = 0L\n    let free = FreeList<int64, Block>()\n\n    let mutable first : Block = null\n    let mutable last : Block = null\n\n    do\n        if store.Size <> 0L then\n            let b = Block(this, 0L, store.Size)\n            free.Insert(b.Size, b)\n            first <- b\n            last <- b\n\n    let mutable pointer = new ReaderWriterLockSlim()\n\n    member x.ReadEntries(entries : array<'a * int64 * int64>, newBlock : 'a -> Block -> unit) =\n        lock x (fun () ->\n            if entries.Length > 0 then\n                let (_,lo,ls) = entries.[entries.Length-1]\n                let maxUsed = lo + ls\n                x.Resize(false, maxUsed + 1L)\n                free.Clear()\n\n                let mutable current = first\n                let mutable offset = first.Size\n                for (name, off, size) in entries do\n                    if off <> offset then\n                        let between = Block(x, offset, off - offset, Prev = current, Next = null, IsFree = true)\n                        free.Insert(between.Size, between)\n                        offset <- off\n                        current <- between\n\n                    let b = Block(x, off, size, Prev = current, Next = null, IsFree = false)\n                    current.Next <- b\n                    offset <- offset + size\n                    allocated <- allocated + size\n\n                    newBlock name b\n\n                    current <- b\n\n                let off = current.Offset + current.Size\n                if off < capacity then\n                    let between = Block(x, off, capacity - off, Prev = current, Next = null, IsFree = true)\n                    free.Insert(between.Size, between)\n                    last <- between\n                else\n                    last <- current\n\n\n        )\n\n    member x.FillRate = float allocated / float capacity\n\n    member x.Allocated = allocated\n    member x.Capacity = capacity\n\n\n    member x.Compact() =\n        lock x (fun () ->\n            let mutable offset = 0L\n            let mutable prev = null\n            let mutable current = first\n            free.Clear()\n\n            while not (isNull current) do\n                if not current.IsFree then\n                    let pSource = store + current.Offset\n                    let pTarget = store + offset\n\n                    let temp = Array.zeroCreate (int current.Size)\n                    pSource.Read(temp, 0L, temp.LongLength)\n                    //mem.Read(store.Value, current.Offset, temp, 0L, temp.LongLength)\n\n                    current.Offset <- offset\n                    current.Prev <- prev\n                    if isNull prev then first <- current\n                    else prev.Next <- current\n\n                    pTarget.Write(temp, 0L, temp.LongLength)\n                    offset <- offset + current.Size\n\n\n                prev <- current\n                current <- current.Next\n\n            let off = current.Offset + current.Size\n            if off < capacity then\n                let between = Block(x, off, capacity - off, Prev = current, Next = null, IsFree = true)\n                free.Insert(between.Size, between)\n                last <- between\n            else\n                last <- current\n\n            x.Resize(true, off)\n                \n\n        )\n\n    member private x.Swap(l : Block, r : Block) =\n        let l,r =\n            if l.Offset < r.Offset then l,r\n            else r,l\n\n        Fun.Swap(&l.Offset, &r.Offset)\n        Fun.Swap(&l.Size, &r.Size)\n\n        if l.IsFree || r.IsFree then\n            failwith \"[MemoryManager] cannot swap free blocks\"\n\n        if l.Next = r then\n            if isNull l.Prev then \n                first <- r\n                r.Prev <- null\n            else \n                r.Prev <- l.Prev\n\n            if isNull r.Next then \n                last <- l\n                l.Next <- null\n            else \n                l.Next <- r.Next\n\n            r.Next <- l\n            l.Prev <- r\n        else\n            Fun.Swap(&l.Next, &r.Next)\n            Fun.Swap(&l.Prev, &r.Prev)\n\n            if isNull l.Next then last <- l\n            else l.Next.Prev <- l\n            if isNull l.Prev then first <- l\n            else l.Prev.Next <- l\n\n\n            if isNull r.Next then last <- r\n            else r.Next.Prev <- r\n            if isNull r.Prev then first <- r\n            else r.Prev.Next <- r\n\n    member private x.Resize (hard : bool, minCapacity : int64) =\n        lock x (fun () ->\n            let c = \n                if hard then minCapacity\n                else Fun.NextPowerOfTwo (max 1024L minCapacity)\n\n            if c <> capacity then\n                ReaderWriterLock.write pointer (fun () ->\n                    store.Realloc(c)\n\n                    if c > capacity then\n                        let newBlock = Block(x, capacity, c - capacity, Prev = last, Next = null, IsFree = false)\n                        if not (isNull last) then last.Next <- newBlock\n                        allocated <- allocated + newBlock.Size\n                        x.Free newBlock\n                    else\n                        if last.IsFree && last.Offset <= c then\n                            free.Remove(last.Size, last) |> ignore\n                            last.Size <- c - last.Offset\n                            free.Insert(last.Size, last)\n                        else\n                            Log.warn \"cannot shrink\"\n                    capacity <- c\n                )\n        )\n\n    member x.Free (b : Block) =\n        lock b (fun () ->\n            if not b.IsFree then\n                lock x (fun () ->\n                    let prev = b.Prev\n                    let next = b.Next\n\n                    if isNull prev then\n                        first <- b\n\n                    elif prev.IsFree then\n                        free.Remove(prev.Size, prev) |> ignore\n                        b.Offset <- prev.Offset\n                        b.Size <- b.Size + prev.Size\n\n                        b.Prev <- prev.Prev\n                        if isNull b.Prev then first <- b\n                        else b.Prev.Next <- b\n\n\n                    if isNull next then\n                        last <- b\n\n                    elif next.IsFree then\n                        free.Remove(next.Size, next) |> ignore\n                        b.Size <- b.Size + next.Size\n\n                        b.Next <- next.Next\n                        if isNull b.Next then last <- b\n                        else b.Next.Prev <- b\n\n\n                    allocated <- allocated - b.Size\n                    free.Insert(b.Size, b)\n                    b.IsFree <- true\n                )\n        )\n\n    member x.Alloc (size : int64) =\n        lock x (fun () ->\n            match free.TryGetGreaterOrEqualV(size) with\n                | ValueSome b ->\n                    b.IsFree <- false\n\n                    if b.Size > size then\n                        let n = Block(x, b.Offset + size, b.Size - size, Prev = b, Next = b.Next, IsFree = false)\n\n                        if isNull n.Next then last <- n\n                        else n.Next.Prev <- n\n                            \n                        b.Next <- n\n\n                        b.Size <- size\n                        x.Free n\n\n                    allocated <- allocated + size\n                    b\n\n                | ValueNone ->\n                    x.Resize(false, capacity + size)\n                    x.Alloc(size)\n        )\n\n    member x.Realloc (b : Block, newSize : int64) =\n        lock b (fun () ->\n            lock x (fun () ->\n                if b.Size <> newSize then\n                    let n = x.Alloc(newSize)\n                    x.Swap(b, n)\n                    x.Free(n)\n\n\n//                    let mutable missing = newSize - b.Size\n//                    if missing > 0L then\n//                        let next = b.Next\n//                        if not (isNull next) && next.IsFree && next.Size >= missing then\n//                            free.Remove(next.Size, next) |> ignore\n//                            next.Offset <- next.Offset + missing\n//                            next.Size <- next.Size - missing\n//                            free.Insert(next.Size, next)\n//                            allocated <- allocated + missing\n//\n//                            b.Size <- newSize\n//                        else\n//                            let n = x.Alloc(newSize)\n//                            x.Swap(b, n)\n//                            x.Free(n)\n//\n//\n//                    elif missing < 0L then\n//                        let rest = Block(x, b.Offset + newSize, b.Size + missing, Prev = b, Next = b.Next, IsFree = false)\n//                    \n//                        if isNull rest.Next then last <- rest\n//                        else rest.Next.Prev <- rest\n//                        b.Next <- rest\n//\n//                        b.Size <- newSize\n//\n//                    else\n//                        ()\n            )\n        )\n\n    member x.Write (b : Block, data : byte[]) =\n        lock b (fun () ->\n            if b.IsFree then failwith \"out of range\"\n            let ptr = store + b.Offset\n            ReaderWriterLock.read pointer (fun () ->\n                ptr.Write(data, 0L, data.LongLength)\n            )\n        )\n\n    member x.Read (b : Block, data : byte[]) =\n        lock b (fun () ->\n            if b.IsFree then failwith \"out of range\"\n            let ptr = store + b.Offset\n            ReaderWriterLock.read pointer (fun () ->\n                ptr.Read(data, 0L, data.LongLength)\n            )\n        )\n\n    member x.Dispose() =\n        lock x (fun () ->\n            store.Free()\n            capacity <- 0L\n            free.Clear()\n            first <- null\n            last <- null\n            pointer.Dispose()\n        )\n\n    interface IDisposable with\n        member x.Dispose() = x.Dispose()\n\nand [<AllowNullLiteral>]\n    Block =\n        class\n            val mutable public Memory   : MemoryManager\n            val mutable public Offset   : int64\n            val mutable public Size     : int64\n            val mutable public Next     : Block\n            val mutable public Prev     : Block\n            val mutable public IsFree   : bool\n\n            //member x.Write(source : nativeint, size : int64) = x.Memory.Write(x, source, size)\n\n            new(mem, off, size) = { Memory = mem; Offset = off; Size = size; Prev = null; Next = null; IsFree = true }\n        end\n\n[<AbstractClass; Sealed; Extension>]\ntype BlockExtensions private() =\n    [<Extension>]\n    static member Realloc(this : Block, size : int64) = \n        this.Memory.Realloc(this, size)\n\n    [<Extension>]\n    static member Read(this : Block, target : byte[]) = \n        this.Memory.Read(this, target)\n\n    [<Extension>]\n    static member Write(this : Block, source : byte[]) = \n        this.Memory.Write(this, source)\n\n    [<Extension>]\n    static member Read(this : Block) =\n        let target : byte[] = Array.zeroCreate (int this.Size)\n        this.Memory.Read(this, target)\n        target\n\n\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Native/Memory.fs",
    "content": "﻿namespace Aardvark.Base.Native\n\nopen System\nopen System.Threading\nopen System.IO\nopen System.IO.MemoryMappedFiles\nopen System.Runtime.InteropServices\nopen Aardvark.Base\n\nmodule OldImpl = \n    [<AbstractClass>]\n    type Memory() =\n        abstract member Alloc   : int64 -> sizedptr\n        abstract member Free    : sizedptr -> unit\n        abstract member Realloc : sizedptr * int64 -> unit\n\n\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module Memory =\n        type private Ptr =\n            class\n                inherit sizedptr\n                val mutable public Value : nativeint\n                val mutable public PointerSize : int64\n\n                override x.Pointer = x.Value\n                override x.IsValid = x.Value <> 0n\n                override x.Size = x.PointerSize\n\n                new(v, s) = { Value = v; PointerSize = s}\n            end\n\n        type private FilePtr =\n            class\n                inherit sizedptr\n\n                val mutable public FileSize     : int64\n                val mutable public Path         : Option<string>\n                val mutable public MapName      : string\n                val mutable public File         : MemoryMappedFile\n                val mutable public Accessor     : MemoryMappedViewAccessor\n                val mutable public Value        : nativeint\n\n                override x.Pointer = x.Value\n                override x.IsValid = x.Value <> 0n\n                override x.Size = x.FileSize\n\n                new(size, path, name, file, acc, value) = { FileSize = size; Path = path; MapName = name; File = file; Accessor = acc; Value = value }\n\n            end\n\n        type private ManagedPtr =\n            class\n                inherit sizedptr\n\n                val mutable public Array : byte[]\n                val mutable public Handle : GCHandle\n                val mutable public Value : nativeint\n\n                override x.Pointer = x.Value\n                override x.IsValid = x.Value <> 0n\n                override x.Size = \n                    if isNull x.Array then 0L\n                    else x.Array.LongLength\n\n                new(arr, handle, value) = { Array = arr; Handle = handle; Value = value }\n            end\n\n        type private ViewPointer =\n            class\n                inherit sizedptr\n\n                val mutable public Base : ptr\n                val mutable public Offset : nativeint\n                val mutable public PointerSize : int64\n\n       \n                override x.IsValid = x.Base.IsValid\n                override x.Pointer = x.Base.Pointer + x.Offset\n                override x.Size = x.PointerSize\n\n                new(ptr, o, s) = { Base = ptr; Offset = o; PointerSize = s }\n            end\n\n\n        let managed =\n            { new Memory() with\n                member x.Alloc(size) = \n                    let arr = Array.zeroCreate (int size)\n                    let gc = GCHandle.Alloc(arr, GCHandleType.Pinned)\n                    let v = gc.AddrOfPinnedObject()\n                    ManagedPtr(arr, gc, v) :> _\n\n                member x.Free(ptr) = \n                    let ptr = unbox<ManagedPtr> ptr\n                    ptr.Handle.Free()\n                    ptr.Array <- null\n                    ptr.Handle <- Unchecked.defaultof<_>\n                    ptr.Value <- 0n\n\n                member x.Realloc(ptr, size) =\n                    let ptr = unbox<ManagedPtr> ptr\n                    ptr.Handle.Free()\n                    Array.Resize(&ptr.Array, int size)\n                    let gc = GCHandle.Alloc(ptr.Array, GCHandleType.Pinned)\n                    let v = gc.AddrOfPinnedObject()\n                    ptr.Handle <- gc\n                    ptr.Value <- v\n                \n            }\n\n        let hglobal =\n            { new Memory() with\n                member x.Alloc(size) = \n                    Ptr(Marshal.AllocHGlobal(nativeint size), size) :> _\n\n                member x.Free(ptr) = \n                    let ptr = unbox<Ptr> ptr\n                    Marshal.FreeHGlobal ptr.Value\n                    ptr.Value <- 0n\n\n                member x.Realloc(ptr, size) =\n                    let ptr = unbox<Ptr> ptr\n                    ptr.Value <- Marshal.ReAllocHGlobal(ptr.Value, nativeint size)\n                \n            }\n\n        let cotask =\n            { new Memory() with\n                member x.Alloc(size) = \n                    Ptr(Marshal.AllocCoTaskMem(int size), size) :> _\n\n                member x.Free(ptr) = \n                    let ptr = unbox<Ptr> ptr\n                    Marshal.FreeCoTaskMem ptr.Value\n                    ptr.Value <- 0n\n\n                member x.Realloc(ptr, size) =\n                    let ptr = unbox<Ptr> ptr\n                    ptr.Value <- Marshal.ReAllocCoTaskMem(ptr.Value, int size)\n                \n            }\n\n        let newFile (path : string) =\n            { new Memory() with\n                member x.Alloc(size) = \n                    let mapName = Guid.NewGuid() |> string\n                    let file = MemoryMappedFile.CreateFromFile(path, FileMode.Create, mapName, size, MemoryMappedFileAccess.ReadWrite)\n                    let acc = file.CreateViewAccessor()\n                    let ptr = acc.SafeMemoryMappedViewHandle.DangerousGetHandle()\n\n                    FilePtr(size, Some path, mapName, file, acc, ptr) :> _\n\n                member x.Free(ptr) = \n                    let ptr = unbox<FilePtr> ptr\n                    ptr.Accessor.Dispose()\n                    ptr.File.Dispose()\n\n                    ptr.FileSize <- 0L\n                    ptr.Path <- None\n                    ptr.MapName <- null\n                    ptr.File <- null\n                    ptr.Accessor <- null\n                    ptr.Value <- 0n\n\n                member x.Realloc(ptr, size) =\n                    let ptr = unbox<FilePtr> ptr\n                \n                    ptr.Accessor.Dispose()\n                    ptr.File.Dispose()\n\n                    let file = MemoryMappedFile.CreateFromFile(ptr.Path.Value, FileMode.Open, ptr.MapName, size, MemoryMappedFileAccess.ReadWrite)\n                    let acc = file.CreateViewAccessor()\n                    let value = acc.SafeMemoryMappedViewHandle.DangerousGetHandle()\n                \n                    ptr.FileSize <- size\n                    ptr.File <- file\n                    ptr.Accessor <- acc\n                    ptr.Value <- value\n\n            }\n     \n        let ofFile (path : string) =\n            let ptr = \n                if File.Exists path then\n                    let size = FileInfo(path).Length\n                    let mapName = Guid.NewGuid() |> string\n                    let file = MemoryMappedFile.CreateFromFile(path, FileMode.Open, mapName, size, MemoryMappedFileAccess.ReadWrite)\n                    let acc = file.CreateViewAccessor()\n                    let value = acc.SafeMemoryMappedViewHandle.DangerousGetHandle()\n\n                    FilePtr(size, Some path, mapName, file, acc, value) :> sizedptr\n                else\n                    sizedptr.Null\n\n            let heap = newFile path\n\n            ptr, heap\n\n\n        let split (mem : Memory) =\n        \n            let real = mem.Alloc(8L)\n            let leftSizePtr = Ptr.cast<int64> real\n            let leftSize = leftSizePtr.Value\n\n            let mutable total = 0L\n            let leftPtr = ViewPointer(real, 8n, leftSize)\n            let rightPtr = ViewPointer(real, 8n + nativeint leftSize, real.Size - leftSize)\n\n            let mutable live = 0\n\n            let left =\n                { new Memory() with\n                    member x.Realloc(old : sizedptr, size : int64) =\n                        if size <> leftPtr.PointerSize then\n                            let rightShift = size - leftPtr.PointerSize\n                            leftPtr.PointerSize <- size\n                            leftSizePtr.Value <- size\n\n                            // if the overall size changed realloc the underlying store\n                            let newTotal = size + rightPtr.PointerSize\n                            if total <> newTotal then\n                                mem.Realloc(real, 8L + newTotal)\n                                total <- newTotal\n\n\n                            // move the right-block \n                            if rightPtr.PointerSize > 0L then\n                                let newRight = rightPtr + rightShift\n                                Marshal.Move(rightPtr.Pointer, newRight.Pointer, rightPtr.PointerSize)\n                                rightPtr.Offset <- nativeint leftPtr.PointerSize\n                \n                    member x.Alloc s =\n                        Interlocked.Increment(&live) |> ignore\n                        x.Realloc(sizedptr.Null, s)\n                        leftPtr :> sizedptr\n\n                    member x.Free(ptr) =\n                        if Interlocked.Decrement(&live) = 0 then\n                            mem.Free(real)\n                }\n\n            let right =\n                { new Memory() with\n                    member x.Realloc(old : sizedptr, size : int64) =\n                        if size <> rightPtr.PointerSize then\n                            rightPtr.PointerSize <- size\n\n                            // if the overall size changed realloc the underlying store\n                            let newTotal = leftPtr.PointerSize + size\n                            if total <> newTotal then\n                                mem.Realloc(real, 8L + newTotal)\n                                total <- newTotal\n\n\n                    member x.Alloc s =\n                        Interlocked.Increment(&live) |> ignore\n                        x.Realloc(sizedptr.Null, s)\n                        rightPtr :> _\n\n                    member x.Free(ptr) =\n                        if Interlocked.Decrement(&live) = 0 then\n                            mem.Free(real)\n                }\n\n            left, right\n\n\n\n[<AutoOpen>]\nmodule NewImpl =\n    \n    [<AbstractClass>]\n    type Memory() =\n        inherit sizedptr()\n\n\n        abstract member Clear : int64 -> unit\n        abstract member Realloc : int64 -> unit\n        abstract member Free : unit -> unit\n\n        member private x.Dispose(disposing : bool) =\n            if x.IsValid then\n                if disposing then GC.SuppressFinalize x\n                x.Free()\n\n        member x.Dispose() = x.Dispose(true)\n        override x.Finalize() = x.Dispose(false)\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose(true)\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module Memory =\n        \n        type HGlobalMemory(size : int64) =\n            inherit Memory()\n\n            let mutable size = size\n            let mutable ptr = Marshal.AllocHGlobal (nativeint size)\n\n            override x.IsValid = ptr <> 0n\n            override x.Pointer = ptr\n            override x.Size = size\n            override x.Realloc (newSize : int64) =\n                if newSize <> size then\n                    ptr <- Marshal.ReAllocHGlobal(ptr, nativeint newSize)\n                    size <- newSize\n\n            override x.Clear(newSize : int64) =\n                Marshal.FreeHGlobal(ptr)\n                ptr <- Marshal.AllocHGlobal (nativeint newSize)\n                Marshal.Set(ptr, 0, newSize)\n                size <- newSize\n\n            override x.Free() =\n                let p = Interlocked.Exchange(&ptr, 0n)\n                if p <> 0n then\n                    size <- 0L\n                    Marshal.FreeHGlobal p\n\n        type CoTaskMemory(size : int64) =\n            inherit Memory()\n\n            let mutable size = size\n            let mutable ptr = Marshal.AllocCoTaskMem (int size)\n\n            override x.IsValid = ptr <> 0n\n            override x.Pointer = ptr\n            override x.Size = size\n            override x.Realloc (newSize : int64) =\n                if newSize <> size then\n                    ptr <- Marshal.ReAllocCoTaskMem(ptr, int newSize)\n                    size <- newSize\n\n            override x.Clear(newSize : int64) =\n                Marshal.FreeCoTaskMem(ptr)\n                ptr <- Marshal.AllocCoTaskMem (int newSize)\n                size <- newSize\n\n            override x.Free() =\n                let p = Interlocked.Exchange(&ptr, 0n)\n                if p <> 0n then\n                    size <- 0L\n                    Marshal.FreeCoTaskMem p\n\n        type FileOperation =\n            | Open of string\n            | Create of string * int64\n\n        type MappedFileMemory(file : FileOperation) =\n            inherit Memory()\n\n            let mapName = Guid.NewGuid() |> string\n\n            let mutable fileName, file, size = \n                match file with\n                    | Open(fileName) ->\n                        if File.Exists fileName then\n                            let info = FileInfo(fileName)\n                            let file = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, mapName, info.Length, MemoryMappedFileAccess.ReadWrite)\n                            fileName, file, info.Length\n                        else\n                            let file = MemoryMappedFile.CreateFromFile(fileName, FileMode.Create, mapName, 4096L, MemoryMappedFileAccess.ReadWrite)\n                            fileName, file, 4096L\n\n                    | Create(fileName, capacity) ->\n                        let file = MemoryMappedFile.CreateFromFile(fileName, FileMode.Create, mapName, capacity, MemoryMappedFileAccess.ReadWrite)\n                        fileName, file, capacity\n            \n            let mutable accessor = file.CreateViewAccessor()\n            let mutable ptr = accessor.SafeMemoryMappedViewHandle.DangerousGetHandle()\n\n            override x.IsValid = not (isNull file)\n            override x.Pointer = ptr\n            override x.Size = size\n            override x.Realloc (newSize : int64) =\n                if newSize <> size then\n                    accessor.Dispose()\n                    file.Dispose()\n                    file <- MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, mapName, newSize, MemoryMappedFileAccess.ReadWrite)\n                    accessor <- file.CreateViewAccessor()\n                    ptr <- accessor.SafeMemoryMappedViewHandle.DangerousGetHandle()\n                    size <- newSize\n\n            override x.Clear (newSize : int64) =\n                accessor.Dispose()\n                file.Dispose()\n                file <- MemoryMappedFile.CreateFromFile(fileName, FileMode.Create, mapName, newSize, MemoryMappedFileAccess.ReadWrite)\n                accessor <- file.CreateViewAccessor()\n                ptr <- accessor.SafeMemoryMappedViewHandle.DangerousGetHandle()\n                size <- newSize\n\n            override x.Free() =\n                let f = Interlocked.Exchange(&file, null)\n                if not (isNull f) then\n                    accessor.Dispose()\n                    f.Dispose()\n                    fileName <- null\n                    file <- null\n                    size <- 0L\n                    accessor <- null\n                    ptr <- 0n\n\n\n        let hglobal (size : int64) =\n            new HGlobalMemory(size) :> Memory\n\n        let cotask (size : int64) =\n            new CoTaskMemory(size) :> Memory\n\n        let mapped (file : string) =\n            new MappedFileMemory(Open file) :> Memory\n\n\n\n\n        type private ViewPointer =\n            class\n                inherit sizedptr\n\n                val mutable public Base : ptr\n                val mutable public Offset : nativeint\n                val mutable public PointerSize : int64\n\n       \n                override x.IsValid = x.Base.IsValid\n                override x.Pointer = x.Base.Pointer + x.Offset\n                override x.Size = x.PointerSize\n\n                new(ptr, o, s) = { Base = ptr; Offset = o; PointerSize = s }\n            end\n\n        let split (mem : Memory) =\n            let leftSizePtr = Ptr.cast<int64> mem\n            \n            let mutable leftSize =\n                if mem.Size < 8L then \n                    mem.Clear 8L\n                    0L\n                else \n                    leftSizePtr.Value\n            \n            let mutable rightSize =\n                mem.Size - leftSize - 8L    \n\n            let mutable live = 2\n\n            let left =\n                { new Memory() with\n                    override x.IsValid = \n                        mem.IsValid\n\n                    override x.Pointer = \n                        mem.Pointer + 8n\n\n                    override x.Size =\n                        leftSize\n\n                    override x.Realloc (newSize : int64) =\n                        if newSize > leftSize then\n                            // realloc the underlying memory\n                            mem.Realloc (8L + newSize + rightSize)\n\n                            // move the right memory \n                            let rightShift = newSize - leftSize\n                            let rightStart = mem.Pointer + 8n + nativeint leftSize\n                            Marshal.Move(rightStart, rightStart + nativeint rightShift, rightSize)\n\n                            // set the new left-memory to 0\n                            Marshal.Set(rightStart, 0, rightShift)\n\n                            // store the new leftSize\n                            leftSizePtr.Value <- newSize\n                            leftSize <- newSize\n\n                        elif newSize < leftSize then\n                            \n                            // move the right memory\n                            let rightShift = newSize - leftSize\n                            let rightStart = mem.Pointer + 8n + nativeint leftSize\n                            Marshal.Move(rightStart, rightStart + nativeint rightShift, rightSize)\n\n\n                            // realloc the underlying memory\n                            mem.Realloc (8L + newSize + rightSize)\n                            \n                            // store the new leftSize\n                            leftSizePtr.Value <- newSize\n                            leftSize <- newSize\n\n\n                    override x.Clear (newSize : int64) =\n                        if newSize > leftSize then\n                            // realloc the underlying memory\n                            mem.Realloc (8L + newSize + rightSize)\n\n                            // move the right memory \n                            let rightShift = newSize - leftSize\n                            let rightStart = mem.Pointer + 8n + nativeint leftSize\n                            Marshal.Move(rightStart, rightStart + nativeint rightShift, rightSize)\n\n                            // set the left-memory to 0\n                            Marshal.Set(mem.Pointer + 8n, 0, newSize)\n\n                            // store the new leftSize\n                            leftSizePtr.Value <- newSize\n                            leftSize <- newSize\n\n                        elif newSize < leftSize then\n                            \n                            // move the right memory\n                            let rightShift = newSize - leftSize\n                            let rightStart = mem.Pointer + 8n + nativeint leftSize\n                            Marshal.Move(rightStart, rightStart + nativeint rightShift, rightSize)\n\n\n                            // realloc the underlying memory\n                            mem.Realloc (8L + newSize + rightSize)\n                            \n                            // set the left-memory to 0\n                            Marshal.Set(mem.Pointer + 8n, 0, newSize)\n\n                            // store the new leftSize\n                            leftSizePtr.Value <- newSize\n                            leftSize <- newSize\n\n                        else\n                            Marshal.Set(mem.Pointer + 8n, 0, leftSize)\n\n                    override x.Free() =\n                        if Interlocked.Decrement(&live) = 0 then\n                            mem.Free()\n                }\n\n            let right =\n                { new Memory() with\n                    override x.IsValid = \n                        mem.IsValid\n\n                    override x.Pointer = \n                        mem.Pointer + 8n + nativeint leftSize\n\n                    override x.Size =\n                        rightSize\n\n                    override x.Realloc (newSize : int64) =\n                        if newSize > rightSize then\n                            // realloc the underlying memory\n                            mem.Realloc (8L + leftSize + newSize)\n\n                            // store the new leftSize\n                            rightSize <- newSize\n\n                        elif newSize < leftSize then\n                            \n                            // realloc the leftSize memory\n                            mem.Realloc (8L + leftSize + newSize)\n                            \n                            // store the new leftSize\n                            rightSize <- newSize\n\n\n                    override x.Clear (newSize : int64) =\n                        x.Realloc(newSize)\n                        Marshal.Set(mem.Pointer + 8n + nativeint leftSize, 0, newSize)\n\n                    override x.Free() =\n                        if Interlocked.Decrement(&live) = 0 then\n                            mem.Free()\n                }\n\n\n\n            left, right\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Native/Pointer.fs",
    "content": "﻿namespace Aardvark.Base.Native\n\n#nowarn \"9\"\n\n\nopen System.Runtime.InteropServices\nopen Microsoft.FSharp.NativeInterop\nopen Aardvark.Base\n\n[<AbstractClass>]\ntype ptr() =\n    static let nullptr = \n        { new ptr() with \n            member x.Pointer = 0n\n            member x.IsValid = false\n        }\n\n    abstract member Pointer : nativeint\n    abstract member IsValid : bool\n    abstract member RealPointer : ptr\n    default x.RealPointer = x\n\n\n    member inline x.Read<'a when 'a : unmanaged>() = NativePtr.read (NativePtr.ofNativeInt<'a> x.Pointer)\n    member inline x.Write<'a when 'a : unmanaged>(value : 'a) = NativePtr.write (NativePtr.ofNativeInt<'a> x.Pointer) value\n    member inline x.Get<'a when 'a : unmanaged>(index : int) = NativePtr.get (NativePtr.ofNativeInt<'a> x.Pointer) index\n    member inline x.Set<'a when 'a : unmanaged>(index : int, value : 'a) = NativePtr.set (NativePtr.ofNativeInt<'a> x.Pointer) index value\n\n    member x.Write(source : byte[], offset : int64, length : int64) =\n        let gc = GCHandle.Alloc(source, GCHandleType.Pinned)\n        try\n            let src = gc.AddrOfPinnedObject()\n            Marshal.Copy(src + nativeint offset, x.Pointer, length)\n        finally\n            gc.Free()\n\n    member x.Read(target : byte[], offset : int64, length : int64) =\n        let gc = GCHandle.Alloc(target, GCHandleType.Pinned)\n        try\n            let src = gc.AddrOfPinnedObject()\n            Marshal.Copy(x.Pointer, src + nativeint offset, length)\n        finally\n            gc.Free()\n\n    member inline x.CopyTo(target : nativeint, length : int64) =\n        Marshal.Copy(x.Pointer, target, length)\n\n    member inline x.CopyTo(target : ptr, length : int64) =\n        Marshal.Copy(x.Pointer, target.Pointer, length)\n\n    member x.CopyTo(target : byte[], offset : int64, length : int64) =\n        let gc = GCHandle.Alloc(target, GCHandleType.Pinned)\n        try\n            let src = gc.AddrOfPinnedObject()\n            Marshal.Copy(x.Pointer, src + nativeint offset, length)\n        finally\n            gc.Free()\n\n    member inline x.CopyFrom(source : nativeint, length : int64) =\n        Marshal.Copy(source, x.Pointer, length)\n\n    member inline x.CopyFrom(source : ptr, length : int64) =\n        Marshal.Copy(source.Pointer, x.Pointer, length)\n\n    member x.CopyFrom(source : byte[], offset : int64, length : int64) =\n        let gc = GCHandle.Alloc(source, GCHandleType.Pinned)\n        try\n            let src = gc.AddrOfPinnedObject()\n            Marshal.Copy(src + nativeint offset, x.Pointer, length)\n        finally\n            gc.Free()\n\n\n    member x.ToByteArray (length : int64) =\n        let arr : byte[] = Array.zeroCreate (int length)\n        x.CopyTo(arr, 0L, length)\n        arr\n\n\n    override x.ToString() =\n        sprintf \"ptr 0x%X\" x.Pointer\n\n    override x.GetHashCode() =\n        if x.IsValid then \n            x.Pointer.GetHashCode()\n        else\n            0\n\n    override x.Equals o =\n        match o with\n            | :? ptr as o -> \n                match x.IsValid, o.IsValid with\n                    | true, true -> x.Pointer = o.Pointer\n                    | false, false -> true\n                    | _ -> false\n            | _ ->\n                false\n\n    static member Zero = nullptr\n    static member Null = nullptr\n\n    static member (+) (p : ptr, offset : nativeint) = \n        match p with\n            | :? ViewPointer as vp -> \n                let o = vp.Offset + offset\n                if o = 0n then vp.Source\n                else ViewPointer(vp.Source, o) :> ptr\n            | _ ->\n                ViewPointer(p, offset) :> ptr\n\n    static member inline (-) (p : ptr, offset : nativeint) = p + (-offset)\n    static member inline (+) (p : ptr, offset : 'a) = p + nativeint offset\n    static member inline (-) (p : ptr, offset : 'a) = p + nativeint -offset\n\n    static member inline (+) (offset : nativeint, p : ptr) = p + offset\n    static member inline (+) (offset : 'a, p : ptr) = p + nativeint offset\n\n    static member inline op_Equality (ptr : ptr, v : nativeint) = ptr.Pointer = v\n\nand private ViewPointer(p : ptr, offset : nativeint) =\n    inherit ptr()\n\n    member x.Source = p\n    member x.Offset = offset\n\n    override x.IsValid = p.IsValid\n    override x.Pointer = p.Pointer + offset\n\ntype ptr<'a when 'a : unmanaged>(p : ptr) =\n    inherit ptr()\n    static let nullptr = ptr<'a>(ptr.Null)\n\n    static let sa = sizeof<'a>\n    static let sa64 = int64 sa\n\n    override x.Pointer = p.Pointer\n    override x.RealPointer = p\n    override x.IsValid = p.IsValid\n\n    static member Zero = nullptr\n    static member  Null = nullptr\n\n    member x.Item\n        with get (i : int) : 'a = NativePtr.get (NativePtr.ofNativeInt p.Pointer) i\n        and set (i : int) (value : 'a) = NativePtr.set (NativePtr.ofNativeInt p.Pointer) i value\n\n    member x.Value \n        with get() : 'a = NativePtr.read (NativePtr.ofNativeInt p.Pointer)\n        and set (v : 'a) = NativePtr.write (NativePtr.ofNativeInt p.Pointer) v\n\n\n    member x.CopyTo(target : nativeint, count : int64) =\n        Marshal.Copy(x.Pointer, target, sa64 * count)\n\n    member x.CopyTo(target : ptr, count : int64) =\n        Marshal.Copy(x.Pointer, target.Pointer, sa64 * count)\n\n    member x.CopyTo(target : ptr<'a>, count : int64) =\n        Marshal.Copy(x.Pointer, target.Pointer, sa64 * count)\n\n    member x.CopyTo(target : 'a[], offset : int64, count : int64) =\n        let gc = GCHandle.Alloc(target, GCHandleType.Pinned)\n        try\n            let src = gc.AddrOfPinnedObject()\n            Marshal.Copy(x.Pointer, src + nativeint offset * nativeint sa, count * sa64)\n        finally\n            gc.Free()\n\n\n\n    member x.CopyFrom(source : nativeint, count : int64) =\n        Marshal.Copy(source, x.Pointer, sa64 * count)\n\n    member x.CopyFrom(source : ptr, count : int64) =\n        Marshal.Copy(source.Pointer, x.Pointer, sa64 * count)\n\n    member x.CopyFrom(source : ptr<'a>, count : int64) =\n        Marshal.Copy(source.Pointer, x.Pointer, sa64 * count)\n\n    member x.CopyFrom(source : 'a[], offset : int64, count : int64) =\n        let gc = GCHandle.Alloc(source, GCHandleType.Pinned)\n        try\n            let src = gc.AddrOfPinnedObject()\n            Marshal.Copy(src + nativeint offset * nativeint sa, x.Pointer, count * sa64)\n        finally\n            gc.Free()\n\n\n    member x.ToArray(count : int) =\n        let target : 'a[] = Array.zeroCreate count\n        x.CopyTo(target, 0L, int64 count)\n        target\n\n\n    static member (+) (l : ptr<'a>, index : int) = ptr<'a>(l.RealPointer + sa * index)\n    static member (-) (l : ptr<'a>, index : int) = ptr<'a>(l.RealPointer - sa * index)\n    static member (+) (l : ptr<'a>, index : int64) = ptr<'a>(l.RealPointer + sa64 * index)\n    static member (-) (l : ptr<'a>, index : int64) = ptr<'a>(l.RealPointer - sa64 * index)\n\n[<AbstractClass>]\ntype sizedptr() =\n    inherit ptr()\n\n    static let nullptr = \n        { new sizedptr() with \n            member x.Pointer = 0n\n            member x.IsValid = false\n            member x.Size = 0L\n        }\n\n    static member Null = nullptr\n    static member Zero = nullptr\n\n    abstract member Size : int64\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Ptr =\n    let zero = ptr.Zero\n\n    let inline isValid (p : ptr) = p.IsValid\n    let inline isNull (p : ptr) = not p.IsValid\n\n    let inline cast<'a when 'a : unmanaged> (p : ptr) : ptr<'a> =\n        ptr<'a>(p.RealPointer)\n    \n    let inline get (i : int) (p : ptr<'a>) = p.[i]\n    let inline set (i : int) (value : 'a) (p : ptr<'a>) = p.[i] <- value\n\n    let inline read (p : ptr<'a>) = p.Value\n    let inline write (value : 'a) (p : ptr<'a>) = p.Value <- value\n\n\n    let inline toByteArray (length : int64) (ptr : ptr) = ptr.ToByteArray(length)\n    let inline toArray (length : int) (ptr : ptr<'a>) = ptr.ToArray(length)\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Native/Store.fs",
    "content": "﻿namespace Aardvark.Base.Native\n\n#nowarn \"9\"\n\nopen System\nopen System.Diagnostics\nopen System.Runtime.InteropServices\nopen Aardvark.Base\nopen Microsoft.FSharp.NativeInterop\nopen System.Threading\nopen System.IO\n\nmodule FileManagerTypes =\n    let inline (++) (ptr : nativeptr<'a>) (v : 'a) = NativePtr.add ptr (int v)\n    let inline (!!) (ptr : nativeptr<'a>) = NativePtr.read ptr\n    let inline (<--) (ptr : nativeptr<'a>) c = NativePtr.write ptr c\n\n\n    let magic = Guid(\"CFD123CA-17BC-437A-9EFC-6EECE27188FF\")\n\n    [<Literal>]\n    let Red = 0\n\n    [<Literal>]\n    let Black = 1\n\n    [<StructLayout(LayoutKind.Explicit, Size = 32)>]\n    type Block =\n        struct\n            [<FieldOffset(0)>]\n            val mutable public Offset   : int64\n            [<FieldOffset(8)>]\n            val mutable public Size     : int64\n            [<FieldOffset(16)>]\n            val mutable public IsFree   : int\n            [<FieldOffset(20)>]\n            val mutable public Prev     : int\n            [<FieldOffset(24)>]\n            val mutable public Next     : int\n            [<FieldOffset(28)>]\n            val mutable public Chunk    : int\n\n            static member Invalid = Block(Offset = -1L, Size = -1L, IsFree = -1, Prev = -1, Next = -1, Chunk = -1)\n\n\n            override x.ToString() =\n                sprintf \"{ Offset = %d; Size = %d; IsFree = %A; Prev = %d; Next = %d; Chunk = %d }\" x.Offset x.Size (x.IsFree <> 0) x.Prev x.Next x.Chunk\n\n        end\n\n    [<StructLayout(LayoutKind.Explicit, Size = 32)>]\n    type DictEntry =\n        struct\n            [<FieldOffset(0)>]\n            val mutable public Key : Guid       // 16\n            [<FieldOffset(16)>]\n            val mutable public HashCode : int   // 20\n            [<FieldOffset(20)>]\n            val mutable public Next : int       // 24\n            [<FieldOffset(24)>]\n            val mutable public Block : int      // 28\n\n\n            static member Invalid = DictEntry(Key = Guid.Empty, HashCode = -1, Next = -1, Block = -1)\n\n\n\n        end\n        \n    [<StructLayout(LayoutKind.Explicit, Size = 32)>]\n    type Node =\n        struct  \n            [<FieldOffset(0)>]\n            val mutable public Offset : int64\n            [<FieldOffset(8)>]\n            val mutable public Size : int64\n            [<FieldOffset(16)>]\n            val mutable public Entry : int\n            [<FieldOffset(20)>]\n            val mutable public Left : int\n            [<FieldOffset(24)>]\n            val mutable public Right : int\n            [<FieldOffset(28)>]\n            val mutable public Color : int\n\n\n            static member Invalid = Node(Offset = -1L, Size = -1L, Entry = -1, Left = -1, Right = -1, Color = -1)\n\n\n        end\n\n\n    [<StructLayout(LayoutKind.Sequential, Size = 128)>]\n    type Header =\n        struct\n            val mutable public Magic        : Guid      // 16\n            val mutable public MFirst       : int       // 20\n            val mutable public MLast        : int       // 24\n            val mutable public MBlubb       : int64     // 32\n            val mutable public NRoot        : int       // 36\n            val mutable public NCount       : int       // 40\n            val mutable public NFreeList    : int       // 44\n            val mutable public NFreeCount   : int       // 48\n            val mutable public ECount       : int       // 52\n            val mutable public EFreeList    : int       // 56\n            val mutable public EFreeCount   : int       // 60\n            val mutable public DCapacity    : int       // 64\n            val mutable public DCapacityId  : int       // 68\n\n            val mutable public BCount       : int       // 72\n            val mutable public BFreeList    : int       // 76\n            val mutable public BFreeCount   : int       // 80\n            val mutable public BCapacity    : int       // 84\n            val mutable public Chunks       : int       // 88\n\n        end\n\n    type blockptr =\n        struct\n            val mutable public ptr : nativeint\n\n            member inline x.Offset      = NativePtr.ofNativeInt<int64>  x.ptr\n            member inline x.Size        = NativePtr.ofNativeInt<int64>  (8n + x.ptr)\n            member inline x.IsFree      = NativePtr.ofNativeInt<int>    (16n + x.ptr)\n            member inline x.Prev        = NativePtr.ofNativeInt<int>    (20n + x.ptr)\n            member inline x.Next        = NativePtr.ofNativeInt<int>    (24n + x.ptr)\n            member inline x.Chunk       = NativePtr.ofNativeInt<int>    (28n + x.ptr)\n \n \n            member x.Value  \n                with inline get() = NativePtr.read (NativePtr.ofNativeInt<Block> x.ptr)\n                and inline set v = NativePtr.write (NativePtr.ofNativeInt x.ptr) v\n\n            static member inline (+) (ptr : blockptr, index : int) = blockptr(ptr.ptr + nativeint (sizeof<Block> * index))\n            static member Null = blockptr(0n)\n\n            new(p) = { ptr = p }\n\n        end\n\n    type dentryptr =\n        struct\n            val mutable public ptr : nativeint\n            member inline x.Key         = (x.ptr) |> NativePtr.ofNativeInt<Guid>\n            member inline x.HashCode    = (x.ptr + 16n) |> NativePtr.ofNativeInt<int>\n            member inline x.Next        = (x.ptr + 20n) |> NativePtr.ofNativeInt<int>\n            member inline x.Block       = (x.ptr + 24n) |> NativePtr.ofNativeInt<int>\n\n\n            member x.Value  \n                with inline get() = NativePtr.read (NativePtr.ofNativeInt<DictEntry> x.ptr)\n                and inline set v = NativePtr.write (NativePtr.ofNativeInt x.ptr) v\n\n\n            static member inline (+) (ptr : dentryptr, index : int) = dentryptr(ptr.ptr + nativeint (sizeof<DictEntry> * index))\n            static member Null = dentryptr(0n)\n\n            new(p) = { ptr = p }\n        end\n\n    type nodeptr =\n        struct\n            val mutable public ptr : nativeint\n\n            member inline x.Offset      = NativePtr.ofNativeInt<int64> (x.ptr)\n            member inline x.Size        = NativePtr.ofNativeInt<int64> (8n + x.ptr)\n            member inline x.Entry       = NativePtr.ofNativeInt<int> (16n + x.ptr)\n            member inline x.Left        = NativePtr.ofNativeInt<int> (20n + x.ptr)\n            member inline x.Right       = NativePtr.ofNativeInt<int> (24n + x.ptr)\n            member inline x.Color       = NativePtr.ofNativeInt<int> (28n + x.ptr)\n\n            \n            member x.Value\n                with inline get() = NativePtr.read (NativePtr.ofNativeInt<Node> x.ptr)\n                and inline set n = NativePtr.write (NativePtr.ofNativeInt x.ptr) n\n\n            static member inline (+) (ptr : nodeptr, index : int) = nodeptr(ptr.ptr + nativeint (sizeof<Node> * index))\n            static member Null = nodeptr(0n)\n\n            new(p) = { ptr = p }\n        end\n\n    type headerptr =\n        struct\n            val mutable public ptr : nativeint\n            \n            member inline x.Magic           = NativePtr.ofNativeInt<Guid>   (0n + x.ptr)\n\n            member inline x.MFirst          = NativePtr.ofNativeInt<int>    (16n + x.ptr)\n            member inline x.MLast           = NativePtr.ofNativeInt<int>    (20n + x.ptr)\n\n            member inline x.NRoot           = NativePtr.ofNativeInt<int>    (32n + x.ptr)\n            member inline x.NCount          = NativePtr.ofNativeInt<int>    (36n + x.ptr)\n            member inline x.NFreeList       = NativePtr.ofNativeInt<int>    (40n + x.ptr)\n            member inline x.NFreeCount      = NativePtr.ofNativeInt<int>    (44n + x.ptr)\n\n            member inline x.ECount          = NativePtr.ofNativeInt<int>    (48n + x.ptr)\n            member inline x.EFreeList       = NativePtr.ofNativeInt<int>    (52n + x.ptr)\n            member inline x.EFreeCount      = NativePtr.ofNativeInt<int>    (56n + x.ptr)\n            member inline x.DCapacity       = NativePtr.ofNativeInt<int>    (60n + x.ptr)\n            member inline x.DCapacityId     = NativePtr.ofNativeInt<int>    (64n + x.ptr)\n\n            member inline x.BCount          = NativePtr.ofNativeInt<int>    (68n + x.ptr)\n            member inline x.BFreeList       = NativePtr.ofNativeInt<int>    (72n + x.ptr)\n            member inline x.BFreeCount      = NativePtr.ofNativeInt<int>    (76n + x.ptr)\n            member inline x.BCapacity       = NativePtr.ofNativeInt<int>    (80n + x.ptr)\n            member inline x.Chunks          = NativePtr.ofNativeInt<int>    (84n + x.ptr)\n \n\n            member inline x.Value = NativePtr.read (NativePtr.ofNativeInt<Header> x.ptr)\n\n            static member inline (+) (ptr : headerptr, index : int) = nodeptr(ptr.ptr + nativeint (sizeof<Header> * index))\n            static member Null = headerptr(0n)\n\n            new(p) = { ptr = p }\n        end\n\n    [<AllowNullLiteral>]\n    type VirtualNode(ptr : nodeptr, index : int) =\n\n        member x.Index = index\n            \n        override x.GetHashCode() =\n            index\n\n        override x.Equals o =\n            match o with\n                | :? VirtualNode as o -> index = o.Index\n                | _ -> false\n\n        interface IComparable with\n            member x.CompareTo o =\n                match o with\n                    | :? VirtualNode as o ->\n                        let c = compare x.Size o.Size\n                        if c = 0 then \n                            let c = compare x.Offset o.Offset\n                            if c = 0 then compare x.Entry o.Entry\n                            else c\n                        else c\n                    | _ ->\n                        failwith \"uncomparable\"\n\n        member x.Equals (o : VirtualNode) =\n            if isNull o then false\n            else index = o.Index\n\n        member x.Color\n            with get() = !!ptr.Color\n            and set v = ptr.Color <-- v\n\n        member x.Offset\n            with get() = !!ptr.Offset\n            and set v = ptr.Offset <-- v\n\n        member x.Size\n            with get() = !!ptr.Size\n            and set v = ptr.Size <-- v\n\n        member x.Entry\n            with get() = !!ptr.Entry\n            and set v = ptr.Entry <-- v\n\n        member x.Left\n            with get() = \n                let id = !!ptr.Left\n                if id < 0 then null\n                else VirtualNode(ptr + (id - x.Index), id)\n\n            and set (l : VirtualNode) =\n                if isNull l then ptr.Left <-- -1\n                else ptr.Left <-- l.Index\n\n        member x.Right\n            with get() = \n                let id = !!ptr.Right\n                if id < 0 then null\n                else VirtualNode(ptr + (id - x.Index), id)\n\n            and set (l : VirtualNode) =\n                if isNull l then ptr.Right <-- -1\n                else ptr.Right <-- l.Index\n\n    module Tree =\n\n        [<AutoOpen>]\n        module private Tools = \n        \n            type TreeRotation =\n                | Left\n                | Right\n                | RightLeft\n                | LeftRight\n\n            let inline isRed (n : VirtualNode) =\n                not (isNull n) && n.Color = Red\n\n            let inline isBlack (n : VirtualNode) =\n                not (isNull n) && n.Color = Black\n   \n            let inline isNullOrBlack (n : VirtualNode) =\n                isNull n || n.Color = Black\n            \n            let inline is4Node (n : VirtualNode) =\n                isRed n.Left && isRed n.Right\n\n            let inline is2Node (n : VirtualNode) =\n                assert (not (isNull n))\n                isBlack n && isNullOrBlack n.Left && isNullOrBlack n.Right\n\n            let split4Node (n : VirtualNode) =\n                n.Color <- Red\n                n.Left.Color <- Black\n                n.Right.Color <- Black\n\n            let merge2Nodes (parent : VirtualNode) (child1 : VirtualNode) (child2 : VirtualNode) =\n                assert (isRed parent)\n                parent.Color <- Black\n                child1.Color <- Red\n                child2.Color <- Red\n\n            let rotateLeft (n : VirtualNode) =\n                let x = n.Right\n                n.Right <- x.Left\n                x.Left <- n\n                x\n\n            let rotateRight (n : VirtualNode) : VirtualNode =\n                let x = n.Left\n                n.Left <- x.Right\n                x.Right <- n\n                x\n\n            let rotateLeftRight (n : VirtualNode) =\n                let child = n.Left\n                let grandChild = child.Right\n\n                n.Left <- grandChild.Right\n                grandChild.Right <- n\n                child.Right <- grandChild.Left\n                grandChild.Left <- child\n                grandChild\n\n            let rotateRightLeft (n : VirtualNode) =\n                let child = n.Right\n                let grandChild = child.Left\n\n                n.Right <- grandChild.Left\n                grandChild.Left <- n\n                child.Left <- grandChild.Right\n                grandChild.Right <- child\n                grandChild\n\n            let replaceChildOfNodeOrRoot(root : byref<VirtualNode>, parent : VirtualNode, child : VirtualNode, newChild : VirtualNode) =\n                if isNull parent then\n                    root <- newChild\n            \n                else\n                    if parent.Left = child then parent.Left <- newChild\n                    else parent.Right <- newChild\n\n            let replaceNode(root : byref<VirtualNode>, match_ : VirtualNode, parentOfMatch : VirtualNode, successor : VirtualNode, parentOfSuccessor : VirtualNode) =\n                let mutable successor = successor\n                if successor = match_ then\n                    assert (isNull match_.Right)\n                    successor <- match_.Left\n                else\n                    assert ( not (isNull parentOfSuccessor) && isNull successor.Left)\n                    assert ((isNull successor.Right && successor.Color = Red) || (successor.Right.Color = Red && successor.Color = Black))\n\n                    if not (isNull successor.Right) then\n                        successor.Right.Color <- Black\n\n                    if parentOfSuccessor <> match_ then\n                        parentOfSuccessor.Left <- successor.Right\n                        successor.Right <- match_.Right\n\n                    successor.Left <- match_.Left\n\n                if not (isNull successor) then\n                    successor.Color <- match_.Color\n\n                replaceChildOfNodeOrRoot(&root, parentOfMatch, match_, successor)\n\n            let sibling (n : VirtualNode) (p : VirtualNode) =\n                if n = p.Left then p.Right\n                else p.Left\n\n            let insertionBalance(root : byref<VirtualNode>, current : VirtualNode, parent : byref<VirtualNode>, grandParent : VirtualNode, greatGrandParent : VirtualNode) =\n                assert (not (isNull grandParent))\n\n                let parentIsOnRight = grandParent.Right = parent\n                let currentIsOnRight = parent.Right = current\n\n                let mutable newChildOfGreatGrandParent = null\n                if parentIsOnRight = currentIsOnRight then\n                    newChildOfGreatGrandParent <- if currentIsOnRight then rotateLeft grandParent else rotateRight grandParent\n                else\n                    newChildOfGreatGrandParent <- if currentIsOnRight then rotateLeftRight grandParent else rotateRightLeft grandParent\n                    parent <- greatGrandParent\n\n                grandParent.Color <- Red\n                newChildOfGreatGrandParent.Color <- Black\n\n                replaceChildOfNodeOrRoot(&root, greatGrandParent, grandParent, newChildOfGreatGrandParent)\n\n            let rotationNeeded (parent : VirtualNode) (current : VirtualNode) (sibling : VirtualNode) =\n                assert (isRed sibling.Left || isRed sibling.Right)\n\n                if isRed sibling.Left then\n                    if parent.Left = current then\n                        TreeRotation.RightLeft\n                    else\n                        TreeRotation.Right\n                else\n                    if parent.Left = current then\n                        TreeRotation.Left\n                    else\n                        TreeRotation.LeftRight\n\n        let insert (node : VirtualNode) (root : byref<VirtualNode>) =\n            node.Color <- Red\n\n            if isNull root then\n                node.Color <- Black\n                root <- node\n                true\n            else\n                let mutable current : VirtualNode           = root\n                let mutable parent : VirtualNode            = null\n                let mutable grandParent : VirtualNode       = null\n                let mutable greatGrandParent : VirtualNode  = null\n                let mutable order = 0\n                let mutable found = false\n\n                while not (found || isNull current) do\n                    order <- compare node current\n                    if order = 0 then\n                        root.Color <- Black\n                        found <- true\n\n                    else\n                        if is4Node current then\n                            split4Node current\n\n                            if isRed parent then\n                                insertionBalance(&root, current, &parent, grandParent, greatGrandParent)\n\n                        greatGrandParent <- grandParent\n                        grandParent <- parent\n                        parent <- current\n                        current <- if order < 0 then current.Left else current.Right\n                        ()\n\n                if found then \n                    false\n\n                else \n                    assert (not (isNull parent))\n\n                    if order > 0 then parent.Right <- node\n                    else parent.Left <- node\n\n                    if isRed parent then\n                        insertionBalance(&root, node, &parent, grandParent, greatGrandParent)\n\n                    root.Color <- Black\n                    true\n\n        let remove (node : VirtualNode) (root : byref<VirtualNode>) =\n            if isNull root then\n                false\n            else\n                let mutable current : VirtualNode           = root\n                let mutable parent : VirtualNode            = null\n                let mutable grandParent : VirtualNode       = null\n                let mutable match_ : VirtualNode            = null\n                let mutable parentOfMatch : VirtualNode     = null\n                let mutable foundMatch = false\n\n                while not (isNull current) do\n                    if is2Node current then\n                        if isNull parent then\n                            current.Color <- Red\n                        else\n                            let mutable sibling = sibling current parent\n                            if isRed sibling then\n\n                                assert(parent.Color <> Red)\n\n                                if parent.Right = sibling then rotateLeft parent |> ignore\n                                else rotateRight parent |> ignore\n\n                                parent.Color <- Red\n                                sibling.Color <- Black\n\n                                replaceChildOfNodeOrRoot(&root, grandParent, parent, sibling)\n\n                                grandParent <- sibling\n                                if parent = match_ then\n                                    parentOfMatch <- sibling\n\n                                sibling <- if parent.Left = current then parent.Right else parent.Left\n\n                            assert (not (isNull sibling) || sibling.Color <> Red)\n\n                            if is2Node sibling then\n                                merge2Nodes parent current sibling\n                            else\n                                let rotation = rotationNeeded parent current sibling\n                                let mutable newGrandParent = null\n\n                                match rotation with\n                                    | TreeRotation.Right ->\n                                        assert (parent.Left = sibling && sibling.Left.Color = Red)\n                                        sibling.Left.Color <- Black\n                                        newGrandParent <- rotateRight parent\n\n                                    | TreeRotation.Left ->\n                                        assert (parent.Right = sibling && sibling.Right.Color = Red)\n                                        sibling.Right.Color <- Black\n                                        newGrandParent <- rotateLeft parent\n\n                                    | TreeRotation.RightLeft ->\n                                        assert (parent.Right = sibling && sibling.Left.Color = Red)\n                                        newGrandParent <- rotateRightLeft parent\n\n                                    | TreeRotation.LeftRight ->\n                                        assert (parent.Left = sibling && sibling.Right.Color = Red)\n                                        newGrandParent <- rotateLeftRight parent\n\n                                newGrandParent.Color <- parent.Color\n                                parent.Color <- Black\n                                current.Color <- Red\n                                replaceChildOfNodeOrRoot(&root, grandParent, parent, newGrandParent)\n                                if parent = match_ then\n                                    parentOfMatch <- newGrandParent\n\n                                grandParent <- newGrandParent\n\n                    let order = if foundMatch then -1 else compare node current\n                    if order = 0 then\n                        foundMatch <- true\n                        match_ <- current\n                        parentOfMatch <- parent\n\n                    grandParent <- parent\n                    parent <- current\n\n                    current <- if order < 0 then current.Left else current.Right\n                \n                if not (isNull match_) then\n                    replaceNode(&root, match_, parentOfMatch, parent, grandParent)\n\n                if not (isNull root) then\n                    root.Color <- Black\n\n                foundMatch\n\n        let removeKey (offset : int64) (size : int64) (root : byref<VirtualNode>) =\n            if isNull root then\n                null\n            else\n                let mutable current : VirtualNode           = root\n                let mutable parent : VirtualNode            = null\n                let mutable grandParent : VirtualNode       = null\n                let mutable match_ : VirtualNode            = null\n                let mutable parentOfMatch : VirtualNode     = null\n                let mutable foundMatch = false\n\n                while not (isNull current) do\n                    if is2Node current then\n                        if isNull parent then\n                            current.Color <- Red\n                        else\n                            let mutable sibling = sibling current parent\n                            if isRed sibling then\n\n                                assert(parent.Color <> Red)\n\n                                if parent.Right = sibling then rotateLeft parent |> ignore\n                                else rotateRight parent |> ignore\n\n                                parent.Color <- Red\n                                sibling.Color <- Black\n\n                                replaceChildOfNodeOrRoot(&root, grandParent, parent, sibling)\n\n                                grandParent <- sibling\n                                if parent = match_ then\n                                    parentOfMatch <- sibling\n\n                                sibling <- if parent.Left = current then parent.Right else parent.Left\n\n                            assert (not (isNull sibling) || sibling.Color <> Red)\n\n                            if is2Node sibling then\n                                merge2Nodes parent current sibling\n                            else\n                                let rotation = rotationNeeded parent current sibling\n                                let mutable newGrandParent = null\n\n                                match rotation with\n                                    | TreeRotation.Right ->\n                                        assert (parent.Left = sibling && sibling.Left.Color = Red)\n                                        sibling.Left.Color <- Black\n                                        newGrandParent <- rotateRight parent\n\n                                    | TreeRotation.Left ->\n                                        assert (parent.Right = sibling && sibling.Right.Color = Red)\n                                        sibling.Right.Color <- Black\n                                        newGrandParent <- rotateLeft parent\n\n                                    | TreeRotation.RightLeft ->\n                                        assert (parent.Right = sibling && sibling.Left.Color = Red)\n                                        newGrandParent <- rotateRightLeft parent\n\n                                    | TreeRotation.LeftRight ->\n                                        assert (parent.Left = sibling && sibling.Right.Color = Red)\n                                        newGrandParent <- rotateLeftRight parent\n\n                                newGrandParent.Color <- parent.Color\n                                parent.Color <- Black\n                                current.Color <- Red\n                                replaceChildOfNodeOrRoot(&root, grandParent, parent, newGrandParent)\n                                if parent = match_ then\n                                    parentOfMatch <- newGrandParent\n\n                                grandParent <- newGrandParent\n\n                    let order = \n                        if foundMatch then \n                            -1 \n                        else \n                            let c = compare size current.Size\n                            if c = 0 then compare offset current.Offset\n                            else c\n\n                    if order = 0 then\n                        foundMatch <- true\n                        match_ <- current\n                        parentOfMatch <- parent\n\n                    grandParent <- parent\n                    parent <- current\n\n                    current <- if order < 0 then current.Left else current.Right\n                \n                if not (isNull match_) then\n                    replaceNode(&root, match_, parentOfMatch, parent, grandParent)\n\n                if not (isNull root) then\n                    root.Color <- Black\n\n                if not foundMatch then null\n                else match_\n\n        let findSmallestGreater (size : int64) (root : VirtualNode) =\n            if isNull root then\n                null\n            else\n                let mutable best = null\n                let mutable current = root\n                while not (isNull current) do\n                    let cmp = compare size current.Size\n\n\n                    if cmp = 0 then \n                        best <- current\n                        current <- null\n\n                    elif cmp > 0 then\n                        current <- current.Right\n\n                    else\n                        best <- current\n                        current <- current.Left\n\n                best\n\n        let removeSmallestGreater (size : int64) (root : byref<VirtualNode>) =\n            let n = findSmallestGreater size root\n\n            if isNull n then\n                null\n            else\n                let res = remove n &root\n                assert res\n                n\n        \n    let primeSizes =\n        [|\n            (*    prime no.           prime *)\n            (*           2                3       +  1 = 2^2 *)\n            (*           4 *) 7                // +  1 = 2^3, minimal size\n            (*           6 *) 13               // +  3 = 2^4\n            (*          11 *) 31               // +  1 = 2^5\n            (*          18 *) 61               // +  3 = 2^6\n            (*          31 *) 127              // +  1 = 2^7\n            (*          54 *) 251              // +  5 = 2^8\n            (*          97 *) 509              // +  3 = 2^9\n            (*         172 *) 1021             // +  3 = 2^10\n            (*         309 *) 2039             // +  9 = 2^11\n            (*         564 *) 4093             // +  3 = 2^12\n            (*        1028 *) 8191             // +  1 = 2^13\n            (*        1900 *) 16381            // +  3 = 2^14\n            (*        3512 *) 32749            // + 19 = 2^15\n            (*        6542 *) 65521            // + 15 = 2^16\n            (*       12251 *) 131071           // +  1 = 2^17\n            (*       23000 *) 262139           // +  5 = 2^18\n            (*       43390 *) 524287           // +  1 = 2^19\n            (*       82025 *) 1048573          // +  3 = 2^20\n            (*      155611 *) 2097143          // +  9 = 2^21\n            (*      295947 *) 4194301          // +  3 = 2^22\n            (*      564163 *) 8388593          // + 15 = 2^23\n            (*     1077871 *) 16777213         // +  3 = 2^24\n            (*     2063689 *) 33554393         // + 39 = 2^25\n            (*     3957809 *) 67108859         // +  5 = 2^26\n            (*     7603553 *) 134217689        // + 39 = 2^27\n            (*    14630843 *) 268435399        // + 57 = 2^28\n            (*    28192750 *) 536870909        // +  3 = 2^29\n            (*    54400028 *) 1073741789       // + 35 = 2^30\n            (*   105097565 *) 2147483647       // +  1 = 2^31\n        |]\n\n\n    [<AllowNullLiteral>]\n    type FileHandle =\n        class\n            val mutable internal EntryId : int\n            val mutable internal Length : int64\n            val public Id : Guid\n\n            member x.Size = x.Length\n            member x.Exists = x.EntryId >= 0\n\n            internal new(id : Guid, eid : int, length : int64) = { Id = id; EntryId = eid; Length = length }\n        end\n\n    type BlockHandle =\n        struct\n            val mutable internal BlockId : int\n            internal new(bid : int) = { BlockId = bid }\n        end\n\n    type FileManagerStatistics =\n        {\n            growManagerTime     : MicroTime\n            growDictTime        : MicroTime\n            growDataTime        : MicroTime\n            rehashTime          : MicroTime\n            reallocTime         : MicroTime\n            allocCount          : int64\n            freeCount           : int64\n            fileCount           : int\n            blockCount          : int\n        }\n\nopen FileManagerTypes\n\ntype FileManager(mem : Memory, getChunk : int -> Memory) =\n    static let initialCapacityId = 7\n    static let initialMemoryCapacity = 1L <<< 20\n    static let chunkSize = 2L <<< 30\n    static let isStore (m : Memory) =\n        if m.Size >= int64 sizeof<Header> then\n            let ptr = m.Pointer |> headerptr\n            magic.Equals !!ptr.Magic\n        else\n            false\n\n    static let headerSize = int64 sizeof<Header>\n\n    static let managerSize (bCapacity : int) =\n        let nCapacity = if bCapacity > 0 then bCapacity + 1 else 0\n\n        int64 sizeof<Node> * int64 nCapacity +\n        int64 sizeof<Block> * int64 bCapacity\n\n    static let dictSize (dCapacity : int) =\n        int64 (sizeof<int> + sizeof<DictEntry>) * int64 dCapacity\n\n\n    let mutable mem = mem\n\n    let chunks = System.Collections.Generic.List<Memory>()\n\n    let mutable header = headerptr.Null\n    let mutable nodes = nodeptr.Null\n    let mutable blocks = blockptr.Null\n    let mutable entries = dentryptr.Null\n    let mutable buckets = NativePtr.zero<int>\n\n    let growManagerTime = Stopwatch()\n    let growDictTime = Stopwatch()\n    let growDataTime = Stopwatch()\n    let rehashTime = Stopwatch()\n    let reallocTime = Stopwatch()\n    let mutable allocCount = 0L\n    let mutable freeCount = 0L\n        \n\n    let handleCache = Dict<Guid, FileHandle>()\n\n    let nCapacity() =\n        let cap = !!header.BCapacity\n        if cap > 0 then cap + 1 else 0\n\n    let bCapacity() = !!header.BCapacity\n    let dCapacity() = !!header.DCapacity\n\n    let setPointers() =\n        let ptr = mem.Pointer\n\n        header <- ptr |> headerptr\n        let ptr = ptr + nativeint headerSize\n\n        let nCapacity = nCapacity()\n        let bCapacity = bCapacity()\n        let dCapacity = dCapacity()\n\n        nodes <- ptr |> nodeptr\n        let ptr = ptr + (nativeint sizeof<Node> * nativeint nCapacity)\n\n        blocks <- ptr |> blockptr\n        let ptr = ptr + (nativeint sizeof<Block> * nativeint bCapacity)\n\n        entries <- ptr |> dentryptr\n        let ptr = ptr + (nativeint sizeof<DictEntry> * nativeint dCapacity)\n\n        buckets <- NativePtr.ofNativeInt ptr\n        let ptr = ptr + (nativeint sizeof<int> * nativeint dCapacity)\n\n        ()\n\n\n    let rec growManager() =\n        growManagerTime.Start()\n\n        let oldBCapacity = !!header.BCapacity\n        let newBCapacity = 2 * oldBCapacity\n        let oldNCapacity = if oldBCapacity = 0 then 0 else oldBCapacity + 1\n        let newNCapacity = if newBCapacity = 0 then 0 else newBCapacity + 1\n\n        let dictSize = dictSize !!header.DCapacity\n\n        let newTotalSize =\n            headerSize +\n            managerSize newBCapacity +\n            dictSize\n\n        let oldTotalSize =\n            headerSize +\n            managerSize oldBCapacity +\n            dictSize\n\n        header.BCapacity <-- newBCapacity\n        mem.Realloc(newTotalSize)\n            \n        let newPtr = mem.Pointer + nativeint newTotalSize\n        let oldPtr = mem.Pointer + nativeint oldTotalSize\n\n        // move the dict\n        let newPtr = newPtr - nativeint dictSize\n        let oldPtr = oldPtr - nativeint dictSize\n        Marshal.Move(oldPtr, newPtr, dictSize)\n\n        // move the Blocks\n        let oldSize = int64 sizeof<Block> * int64 oldBCapacity\n        let newSize = int64 sizeof<Block> * int64 newBCapacity\n        let newPtr = newPtr - nativeint newSize\n        let oldPtr = oldPtr - nativeint oldSize\n        Marshal.Move(oldPtr, newPtr, oldSize)\n        Marshal.Set(newPtr + nativeint oldSize, -1, newSize - oldSize)\n\n        // move the Nodes\n        let oldSize = int64 sizeof<Node> * int64 oldNCapacity\n        let newSize = int64 sizeof<Node> * int64 newNCapacity\n        let newPtr = newPtr - nativeint newSize\n        let oldPtr = oldPtr - nativeint oldSize\n        Marshal.Move(oldPtr, newPtr, oldSize)\n        Marshal.Set(newPtr + nativeint oldSize, -1, newSize - oldSize)\n\n            \n        setPointers()\n        growManagerTime.Stop()\n\n    and growDict() =\n        growDictTime.Start()\n        let oldDCapacityId = !!header.DCapacityId\n        let oldDCapacity = !!header.DCapacity\n        let newDCapacityId = 1 + oldDCapacityId\n        let newDCapacity = primeSizes.[newDCapacityId]\n\n        let oldDictSize = dictSize oldDCapacity\n        let newDictSize = dictSize newDCapacity\n\n        let managerSize = managerSize !!header.BCapacity\n\n        let newTotalSize =\n            headerSize +\n            managerSize +\n            newDictSize\n\n        let oldTotalSize =\n            headerSize +\n            managerSize +\n            oldDictSize\n                \n        header.DCapacityId <-- newDCapacityId\n        header.DCapacity <-- newDCapacity\n        reallocTime.Start()\n        mem.Realloc(newTotalSize)\n        reallocTime.Stop()\n\n        // move the dict\n        let newPtr = mem.Pointer + nativeint newTotalSize\n        let oldPtr = mem.Pointer + nativeint oldTotalSize\n\n\n        // set the buckets to 0\n        let newSize = int64 sizeof<int> * int64 newDCapacity\n        let oldSize = int64 sizeof<int> * int64 oldDCapacity\n        let newPtr = newPtr - nativeint newSize\n        let oldPtr = oldPtr - nativeint oldSize\n        Marshal.Set(newPtr, 0, newSize)\n\n        // move the DictEntries\n        let newSize = int64 sizeof<DictEntry> * int64 newDCapacity\n        let oldSize = int64 sizeof<DictEntry> * int64 oldDCapacity\n        let newPtr = newPtr - nativeint newSize\n        let oldPtr = oldPtr - nativeint oldSize\n        Marshal.Move(oldPtr, newPtr, oldSize)\n\n        setPointers()\n\n        rehashTime.Start()\n        rehash()\n        rehashTime.Stop()\n\n        growDictTime.Stop()\n\n    and growData(needed : int64) =\n        growDataTime.Start()\n\n        let chunkIndex = chunks.Count - 1\n\n        let oldLastId = !!header.MLast\n        let _, freeBlockId = newBlock()\n        let pFreeBlock = blocks + freeBlockId\n        pFreeBlock.Prev <-- oldLastId\n        pFreeBlock.Next <-- -1\n        pFreeBlock.IsFree <-- 0\n\n        if chunkIndex >= 0 && chunks.[chunkIndex].Size < chunkSize then\n            let lastChunk = chunks.[chunkIndex]\n            let oldChunkCapacity = lastChunk.Size\n            let newChunkCapacity = 2L * oldChunkCapacity\n            lastChunk.Realloc newChunkCapacity\n\n            let offset = chunkSize * int64 chunkIndex + oldChunkCapacity\n\n            // free the new block\n            pFreeBlock.Offset <-- offset\n            pFreeBlock.Size <-- newChunkCapacity - oldChunkCapacity\n            pFreeBlock.Chunk <-- chunkIndex\n\n        else\n            let chunkIndex = 1 + chunkIndex\n            let newChunk = getChunk chunkIndex\n            let newChunkCapacity = max (1L <<< 20) (Fun.NextPowerOfTwo needed)\n            newChunk.Clear newChunkCapacity\n            chunks.Add newChunk\n\n            let offset = chunkSize * int64 chunkIndex\n            pFreeBlock.Offset <-- offset\n            pFreeBlock.Size <-- newChunkCapacity\n            pFreeBlock.Chunk <-- chunkIndex\n\n            header.Chunks <-- !!header.Chunks + 1\n\n        if oldLastId < 0 then header.MFirst <-- freeBlockId\n        else (blocks + oldLastId).Next <-- freeBlockId\n\n        free freeBlockId\n        growDataTime.Stop()\n\n\n    and newBlock() : bool * int =\n        if !!header.BFreeCount > 0 then\n            let id = !!header.BFreeList\n            assert (id >= 0)\n\n            let b = blocks + id\n            header.BFreeList <-- !!b.Next\n            header.BFreeCount <-- !!header.BFreeCount - 1\n            b.Next <-- -1\n\n\n            false, id\n        else\n            let mutable resized = false\n            let cnt = !!header.BCount\n            if cnt >= bCapacity() then\n                resized <- true\n                growManager()\n\n            let id = cnt\n            header.BCount <-- cnt + 1\n            resized, id\n\n    and deleteBlock(bid : int) =\n        assert (bid >= 0)\n        let n = !!header.BFreeList\n        let mutable b = blocks + bid\n        b.Value <- Block.Invalid\n        b.Next <-- n\n        header.BFreeList <-- bid\n        header.BFreeCount <-- !!header.BFreeCount + 1\n\n    and newNode() : bool * int =\n        if !!header.NFreeCount > 0 then\n            let id = !!header.NFreeList\n            assert (id >= 0)\n\n            let n = nodes + id\n            header.NFreeList <-- !!n.Left\n            header.NFreeCount <-- !!header.NFreeCount - 1\n            n.Left <-- -1\n\n\n            false, id\n        else\n            let mutable resized = false\n            let cnt = !!header.NCount\n            if cnt >= nCapacity() then\n                resized <- true\n                growManager()\n\n            let id = cnt\n            header.NCount <-- cnt + 1\n            resized, id\n            \n    and deleteNode(nid : int) =\n        assert (nid >= 0)\n        let next = !!header.NFreeList\n        let mutable n = nodes + nid\n        n.Value <- Node.Invalid\n        n.Left <-- next\n        header.NFreeList <-- nid\n        header.NFreeCount <-- !!header.NFreeCount + 1   \n\n    and newEntry() : bool * int =\n        if !!header.EFreeCount > 0 then\n            let id = !!header.EFreeList\n            assert (id >= 0)\n\n            let e = entries + id\n            header.EFreeList <-- !!e.Next\n            header.EFreeCount <-- !!header.EFreeCount - 1\n            e.Next <-- -1\n\n            false, id\n        else\n            let mutable resized = false\n            let cnt = !!header.ECount\n            if cnt >= dCapacity() then\n                resized <- true\n                growDict()\n\n            let id = cnt\n            header.ECount <-- cnt + 1\n            resized, id\n\n    and deleteEntry(eid : int) =\n        assert (eid >= 0)\n\n        let next = !!header.EFreeList\n        let mutable e = entries + eid\n        e.Value <- DictEntry.Invalid\n        e.Next <-- next\n        header.EFreeList <-- eid\n        header.EFreeCount <-- !!header.EFreeCount + 1   \n\n\n\n    and withTree (f : ref<VirtualNode> -> 'a) =\n        let root = \n            let rid = !!header.NRoot\n            if rid < 0 then null\n            else VirtualNode(nodes + rid, rid)\n\n        let r = ref root\n        let res = f r\n        let root = !r\n\n        if isNull root then header.NRoot <-- -1\n        else header.NRoot <-- root.Index\n\n        res\n\n    and insertFreeBlock (bid : int) =\n        assert (bid >= 0)\n\n        let pBlock = blocks + bid\n        let size = !!pBlock.Size\n        let offset = !!pBlock.Offset\n        let _, nid = newNode()\n        let pEntry = ()\n\n        let pNode = nodes + nid\n        pNode.Offset <-- offset\n        pNode.Size <-- size\n        pNode.Left <-- -1\n        pNode.Right <-- -1\n        pNode.Entry <-- bid\n        pNode.Color <-- Red\n\n        withTree (fun root ->\n            let nn = VirtualNode(pNode, nid)\n            let worked = Tree.insert nn &root.contents\n            if not worked then\n                Log.warn \"could not add to freelist: %A\" (offset, size)\n                deleteNode nid\n                    \n        )\n\n    and removeFreeBlock (bid : int) =\n        assert (bid >= 0)\n\n        let pBlock = blocks + bid\n        let offset = !!pBlock.Offset\n        let size = !!pBlock.Size\n\n        let toKill =\n            withTree(fun root ->\n                Tree.removeKey offset size &root.contents\n            )\n\n        if not (isNull toKill) then\n            deleteNode toKill.Index\n            true\n        else\n            Log.warn \"could not remove from freelist: %A\" (offset, size)\n            false\n\n    and getFreeBlock (size : int64) : bool * int =\n        let node =\n            withTree (fun tree ->\n                Tree.removeSmallestGreater size &tree.contents\n            )\n\n        if isNull node then \n            growData size\n            let _, bid = getFreeBlock size\n            true, bid\n        else\n            let bid = node.Entry\n            assert (bid >= 0)\n            assert (!!(blocks + bid).Size >= size)\n            deleteNode node.Index\n            false, bid\n\n    and alloc (size : int64) =\n        if size <= 0L then\n            false, -1\n        else\n            allocCount <- allocCount + 1L\n            let mutable resized, bid = getFreeBlock size\n            let mutable pBlock = blocks + bid\n            let blockSize = !!pBlock.Size\n\n            if blockSize > size then\n                let r, rid = newBlock()\n                if r then\n                    pBlock <- blocks + bid\n                    resized <- true\n\n\n                let restNext = !!pBlock.Next\n\n                let mutable pRestBlock = blocks + rid\n                pRestBlock.Offset <-- !!pBlock.Offset + size\n                pRestBlock.Size <-- blockSize - size\n                pRestBlock.IsFree <-- 1\n                pRestBlock.Prev <-- bid\n                pRestBlock.Next <-- restNext\n                pRestBlock.Chunk <-- !!pBlock.Chunk\n\n                if restNext < 0 then header.MLast <-- rid\n                else (blocks + restNext).Prev <-- rid\n\n                pBlock.Size <-- size\n                pBlock.Next <-- rid \n                insertFreeBlock rid\n\n\n            pBlock.IsFree <-- 0\n            assert (!!pBlock.Size = size)\n            resized, bid\n\n    and free (bid : int) =\n        if bid >= 0 then\n            freeCount <- freeCount + 1L\n            let pBlock = blocks + bid\n            if !!pBlock.IsFree = 0 then\n                let chunk = !!pBlock.Chunk\n                let prev = !!pBlock.Prev\n                let next = !!pBlock.Next\n                let pPrevBlock = blocks + prev\n                let pNextBlock = blocks + next\n\n                if prev < 0 then\n                    header.MFirst <-- bid\n\n                elif !!pPrevBlock.IsFree <> 0 && !!pPrevBlock.Chunk = chunk then\n                    // merge with prev\n                    removeFreeBlock prev |> ignore\n\n                    pBlock.Offset <-- !!pPrevBlock.Offset\n                    pBlock.Size <-- !!pPrevBlock.Size + !!pBlock.Size\n\n\n                    let pp = !!pPrevBlock.Prev\n                    pBlock.Prev <-- pp\n                    if pp < 0 then header.MFirst <-- bid\n                    else (blocks + pp).Next <-- bid\n\n                    deleteBlock prev\n\n\n                if next < 0 then\n                    header.MLast <-- bid\n\n                elif !!pNextBlock.IsFree <> 0 && !!pNextBlock.Chunk = chunk then\n                    // merge with next\n                    removeFreeBlock next |> ignore\n\n                    pBlock.Size <-- !!pBlock.Size + !!pNextBlock.Size\n\n                    let nn = !!pNextBlock.Next\n                    pBlock.Next <-- nn\n                    if nn < 0 then header.MLast <-- bid\n                    else (blocks + nn).Prev <-- bid\n                    \n                    deleteBlock next\n\n                pBlock.IsFree <-- 1\n                insertFreeBlock bid\n\n        \n\n    and findEntry (key : Guid) (hashCode : int) =\n        let bid = hashCode % !!header.DCapacity\n        let pBucket = NativePtr.add buckets bid\n\n        let b = !!pBucket - 1\n        if b < 0 then\n            -1\n        else\n            let pEntry = entries + b\n            if !!pEntry.HashCode = hashCode && key.Equals !!pEntry.Key then\n                b\n            else\n                let rec search (id : int) (pEntry : dentryptr) = \n                    if id < 0 then\n                        -1\n                    elif !!pEntry.HashCode = hashCode && key.Equals !!pEntry.Key then\n                        id\n                    else\n                        let next = !!pEntry.Next\n                        search next (entries + next)\n\n                let next = !!pEntry.Next\n                search next (entries + next)\n\n//        and removeEntry (key : Guid) (hashCode : int) =\n//            let bid = hashCode % !!header.DCapacity\n//            let pBucket = NativePtr.add buckets bid\n//\n//            let b = !!pBucket - 1\n//            if b < 0 then\n//                -1\n//            else\n//                let pEntry = entries + b\n//                if !!pEntry.HashCode = hashCode && key.Equals !!pEntry.Key then\n//                    let block = !!pEntry.Block\n//                    deleteEntry b\n//                    pBucket <-- 0\n//                    block\n//                else\n//                    let rec search (last : dentryptr) (id : int) (pEntry : dentryptr) = \n//                        if id < 0 then\n//                            -1\n//                        elif !!pEntry.HashCode = hashCode && key.Equals !!pEntry.Key then\n//                            let next = !!pEntry.Next\n//                            last.Next <-- next\n//                            \n//                            let block = !!pEntry.Block\n//                            deleteEntry id\n//                            block\n//                        else\n//                            let next = !!pEntry.Next\n//                            search pEntry next (entries + next)\n//\n//                    let next = !!pEntry.Next\n//                    search pEntry next (entries + next) \n\n    and removeEntryPtr (eid : int) =\n        if eid >= 0 then\n            let pRemEntry = entries + eid\n            let hashCode = !!pRemEntry.HashCode\n            let bid = hashCode % !!header.DCapacity\n            let pBucket = NativePtr.add buckets bid\n\n            let b = !!pBucket - 1\n            if b < 0 then\n                false\n            else\n                let pEntry = entries + b\n                if b = eid then\n                    let next = !!pEntry.Next\n                    deleteEntry b\n                    pBucket <-- 1 + next\n                    true\n                else\n                    let rec search (last : dentryptr) (id : int) (pEntry : dentryptr) = \n                        if id < 0 then\n                            false\n                        elif id = eid then\n                            let next = !!pEntry.Next\n                            last.Next <-- next\n                            \n                            let block = !!pEntry.Block\n                            deleteEntry id\n                            true\n                        else\n                            let next = !!pEntry.Next\n                            search pEntry next (entries + next)\n\n                    let next = !!pEntry.Next\n                    search pEntry next (entries + next) \n        else\n            true\n\n    and setEntry (key : Guid) (hashCode : int) (value : int) =\n        let eid = findEntry key hashCode\n        if eid >= 0 then\n            let pEntry = entries + eid\n            pEntry.Block <-- value\n            eid\n        else\n            let _, eid = newEntry()\n               \n            let pEntry = entries + eid\n            pEntry.Key <-- key\n            pEntry.HashCode <-- hashCode\n            pEntry.Block <-- value\n            pEntry.Next <-- -1\n\n            let bid = hashCode % !!header.DCapacity\n            let pBucket = NativePtr.add buckets bid\n\n            let b = !!pBucket - 1\n            pEntry.Next <-- b\n            pBucket <-- eid + 1\n            eid\n\n    and rehash() =\n        let mutable pEntry = entries\n        let eCount = !!header.ECount\n        let dCapacity = !!header.DCapacity\n        for i in 0..eCount-1 do\n            let hash = !!pEntry.HashCode\n            if hash >= 0 then\n                let bid = hash % dCapacity\n                let pBucket = NativePtr.add buckets bid\n                let b = !!pBucket - 1\n                pEntry.Next <-- b\n                pBucket <-- i + 1\n\n            pEntry <- pEntry + 1\n\n\n\n    do  if isStore mem then\n            setPointers()\n\n            let numChunks = !!header.Chunks\n            for i in 0..numChunks-1 do\n                chunks.Add(getChunk i)\n\n        else\n            let dCapacityId = initialCapacityId\n            let dCapacity = primeSizes.[dCapacityId]\n            let bCapacity = Fun.NextPowerOfTwo dCapacity\n\n            let total =\n                headerSize +\n                managerSize bCapacity +\n                dictSize dCapacity\n\n            mem.Clear(total)\n\n            let c0 = getChunk 0\n            chunks.Add c0\n            c0.Clear(initialMemoryCapacity)\n\n            let initialHeader =\n                Header(\n                    Magic        = magic,\n                    MFirst       = -1,\n                    MLast        = -1,\n                    NRoot        = -1,\n                    NCount       = 0,\n                    NFreeList    = -1,\n                    NFreeCount   = 0,\n                    ECount       = 0,\n                    EFreeList    = -1,\n                    EFreeCount   = 0,\n                    DCapacity    = dCapacity,\n                    DCapacityId  = dCapacityId,\n                        \n                    BCount       = 0,\n                    BFreeList    = -1,\n                    BFreeCount   = 0,\n                    BCapacity    = bCapacity,\n                    Chunks       = 1  \n                )     \n                    \n            NativePtr.write (NativePtr.ofNativeInt mem.Pointer) initialHeader      \n            setPointers()\n\n            // create the new free-block\n            let _,bid = newBlock()\n            let pBlock = blocks + bid\n            pBlock.Offset <-- 0L\n            pBlock.Size <-- initialMemoryCapacity\n            pBlock.IsFree <-- 0\n            pBlock.Prev <-- -1\n            pBlock.Next <-- -1\n            pBlock.Chunk <-- 0\n\n            // store the free-block in a new entry\n            // and ensure its correct linkage\n            header.MFirst <-- bid\n            header.MLast <-- bid\n\n            // free the new block\n            free bid\n            \n    // ===================================================================================================\n    // Block API\n    // ===================================================================================================\n    member x.Alloc (size : int64) =\n        let _,bid = alloc size\n        BlockHandle bid\n\n    member x.Free (block : BlockHandle) =\n        free block.BlockId\n\n    member x.SizeOf(block : BlockHandle) =\n        let bid = block.BlockId\n        if bid < 0 then 0L\n        else\n            let pBlock = blocks + bid\n            !!pBlock.Size\n\n    member x.Copy(src : byte[], srcOffset : int64, dst : BlockHandle, dstOffset : int64, length : int64) =\n        if length <= 0L then\n            ()\n        else\n            let bid = dst.BlockId\n            if bid < 0 then failwithf \"[FileManager] cannot write %d bytes to block of size 0\" length\n            if isNull src then failwith \"[FileManager] cannot read from null array\"\n\n            let pBlock = blocks + bid\n            assert (!!pBlock.IsFree <> 1)\n\n            let blockSize = !!pBlock.Size\n            if length > blockSize then failwithf \"[FileManager] cannot write %d bytes to block of size %d\" length blockSize\n\n            let chunk = !!pBlock.Chunk\n            let memory = chunks.[chunk].Pointer - nativeint chunkSize * nativeint chunk\n\n            let gc = GCHandle.Alloc(src, GCHandleType.Pinned)\n            try\n                let dst = memory + nativeint !!pBlock.Offset + nativeint dstOffset\n                let src = gc.AddrOfPinnedObject() + nativeint srcOffset\n                Marshal.Copy(src, dst, length)\n            finally\n                gc.Free()\n\n    member x.Copy(src : BlockHandle, srcOffset : int64, dst : byte[], dstOffset : int64, length : int64) =\n        if length <= 0L then\n            ()\n        else\n            let bid = src.BlockId\n            if bid < 0 then failwithf \"[FileManager] cannot read %d bytes from block of size 0\" length\n            if isNull dst then failwith \"[FileManager] cannot write to null array\"\n\n            let pBlock = blocks + bid\n            assert (!!pBlock.IsFree <> 1)\n            let blockSize = !!pBlock.Size\n            if length > blockSize then failwithf \"[FileManager] cannot read %d bytes from block of size %d\" length blockSize\n                \n            let chunk = !!pBlock.Chunk\n            let memory = chunks.[chunk].Pointer - nativeint chunkSize * nativeint chunk\n\n\n            let gc = GCHandle.Alloc(dst, GCHandleType.Pinned)\n            try\n                let dst = gc.AddrOfPinnedObject() + nativeint dstOffset\n                let src = memory + nativeint !!pBlock.Offset + nativeint srcOffset\n                Marshal.Copy(src, dst, length)\n            finally\n                gc.Free()\n\n    member x.Copy(src : BlockHandle, srcOffset : int64, dst : BlockHandle, dstOffset : int64, length : int64) =\n        if length <= 0L then\n            ()\n        else\n            let sid = src.BlockId\n            let did = src.BlockId\n\n            if sid < 0 then failwithf \"[FileManager] cannot copy %d bytes from block of size 0\" length\n            if did < 0 then failwithf \"[FileManager] cannot copy %d bytes to block of size 0\" length\n\n            let pSrc = blocks + sid\n            let pDst = blocks + did\n\n            assert (!!pSrc.IsFree <> 1)\n            assert (!!pDst.IsFree <> 1)\n\n            let srcSize = !!pSrc.Size\n            let dstSize = !!pDst.Size\n\n\n\n            if length > srcSize then failwithf \"[FileManager] cannot copy %d bytes from block of size %d\" length srcSize\n            if length > dstSize then failwithf \"[FileManager] cannot copy %d bytes to block of size %d\" length dstSize\n\n            let dstChunk = !!pDst.Chunk\n            let dstMemory = chunks.[dstChunk].Pointer - nativeint chunkSize * nativeint dstChunk\n\n            let srcChunk = !!pSrc.Chunk\n            let srcMemory = chunks.[srcChunk].Pointer - nativeint chunkSize * nativeint srcChunk\n\n\n            Marshal.Copy(srcMemory + nativeint !!pSrc.Offset + nativeint srcOffset, dstMemory + nativeint !!pDst.Offset + nativeint dstOffset, length)\n\n    member x.Copy(src : BlockHandle, dst : byte[], dstOffset : int64, length : int64) = x.Copy(src, 0L, dst, dstOffset, length)\n    member x.Copy(src : BlockHandle, srcOffset : int64, dst : byte[], length : int64) = x.Copy(src, srcOffset, dst, 0L, length)\n    member x.Copy(src : BlockHandle, dst : byte[], length : int64) = x.Copy(src, 0L, dst, 0L, length)\n    member x.Copy(src : BlockHandle, dst : byte[]) = x.Copy(src, 0L, dst, 0L, dst.LongLength)\n    member x.Copy(src : byte[], dst : BlockHandle, dstOffset : int64, length : int64) = x.Copy(src, 0L, dst, dstOffset, length)\n    member x.Copy(src : byte[], srcOffset : int64, dst : BlockHandle, length : int64) = x.Copy(src, srcOffset, dst, 0L, length)\n    member x.Copy(src : byte[], dst : BlockHandle, length : int64) = x.Copy(src, 0L, dst, 0L, length)\n    member x.Copy(src : byte[], dst : BlockHandle) = x.Copy(src, 0L, dst, 0L, src.LongLength)\n    member x.Copy(src : BlockHandle, dst : BlockHandle, dstOffset : int64, length : int64) = x.Copy(src, 0L, dst, dstOffset, length)\n    member x.Copy(src : BlockHandle, srcOffset : int64, dst : BlockHandle, length : int64) = x.Copy(src, srcOffset, dst, 0L, length)\n    member x.Copy(src : BlockHandle, dst : BlockHandle, length : int64) = x.Copy(src, 0L, dst, 0L, length)\n    member x.Copy(src : BlockHandle, dst : BlockHandle) = x.Copy(src, 0L, dst, 0L, x.SizeOf src)\n\n    member x.Read(src : BlockHandle) =\n        if src.BlockId >= 0 then\n            let size = x.SizeOf src\n            let arr = Array.zeroCreate (int size)\n            x.Copy(src, 0L, arr, 0L, arr.LongLength)\n            arr\n        else\n            [||]\n\n\n    // ===================================================================================================\n    // File API\n    // ===================================================================================================\n\n    member x.Exists(file : FileHandle) =\n        file.EntryId >= 0\n\n    member x.GetCurrentBlock(file : FileHandle) =\n        if file.EntryId < 0 then\n            BlockHandle(-1)\n        else\n            let pEntry = entries + file.EntryId\n            BlockHandle(!!pEntry.Block)\n\n\n    member x.GetFile (key : Guid) =\n        handleCache.GetOrCreate(key, fun key ->\n            let hashCode = key.GetHashCode() &&& 0x7FFFFFFF\n            let eid = findEntry key hashCode\n            if eid < 0 then\n                FileHandle(key, -1, 0L)\n            else\n                let bid = !!(entries + eid).Block |> BlockHandle\n                let size = x.SizeOf bid\n                FileHandle(key, eid, size)\n        )\n\n    member x.TryGetFile (key : Guid, [<Out>] file : byref<FileHandle>) =\n        if handleCache.TryGetValue(key, &file) then\n            true\n        else\n            let hashCode = key.GetHashCode() &&& 0x7FFFFFFF\n            let eid = findEntry key hashCode\n            if eid < 0 then\n                false\n            else\n                let bid = !!(entries + eid).Block |> BlockHandle\n                let size = x.SizeOf bid\n                let res = FileHandle(key, eid, size)\n                handleCache.[key] <- res\n                file <- res\n                true\n\n    member x.Resize (file : FileHandle, newSize : int64) =\n        let eid = file.EntryId\n        if eid < 0 then\n            if newSize > 0L then\n                let _, bid = alloc newSize\n                let hashCode = file.Id.GetHashCode() &&& 0x7FFFFFFF\n                let eid = setEntry file.Id hashCode bid\n                file.EntryId <- eid\n                file.Length <- newSize\n\n            else\n                file.Length <- 0L\n\n        else\n\n            if newSize > 0L then\n                let mutable pEntry = entries + eid\n                let oldBlockId = !!pEntry.Block\n\n                if oldBlockId >= 0 then\n                    let pBlock = blocks + oldBlockId\n                    let oldSize = !!pBlock.Size\n\n                    if oldSize <> newSize then\n                        free oldBlockId\n                        let resized, newBlockId = alloc newSize\n                        if resized then \n                            pEntry <- entries + eid\n\n                        pEntry.Block <-- newBlockId\n\n                else\n                    let resized, bid = alloc newSize\n                    if resized then\n                        pEntry <- entries + eid\n\n                    pEntry.Block <-- bid\n\n                file.Length <- newSize\n\n            else\n                let pEntry = entries + eid\n                let bid = !!pEntry.Block\n                if bid >= 0 then\n                    pEntry.Block <-- -1\n                    free bid\n\n                file.Length <- 0L\n\n    member x.Delete(file : FileHandle) =\n        let eid = file.EntryId\n        if eid >= 0 then\n            file.EntryId <- -1\n\n            handleCache.Remove file.Id |> ignore\n                \n            let bid = !!(entries + eid).Block\n            let removed = removeEntryPtr eid\n            assert removed\n\n\n            if bid >= 0 then free bid\n         \n\n    member x.Copy(src : byte[], srcOffset : int64, dst : FileHandle, dstOffset : int64, length : int64) = x.Copy(src, srcOffset, x.GetCurrentBlock dst, dstOffset, length)\n    member x.Copy(src : byte[], dst : FileHandle, dstOffset : int64, length : int64) = x.Copy(src, 0L, x.GetCurrentBlock dst, dstOffset, length)\n    member x.Copy(src : byte[], srcOffset : int64, dst : FileHandle, length : int64) = x.Copy(src, srcOffset, x.GetCurrentBlock dst, 0L, length)\n    member x.Copy(src : byte[], dst : FileHandle, length : int64) = x.Copy(src, 0L, x.GetCurrentBlock dst, 0L, length)\n    member x.Copy(src : byte[], dst : FileHandle) = x.Copy(src, 0L, x.GetCurrentBlock dst, 0L, src.LongLength)\n\n    member x.Copy(src : FileHandle, srcOffset : int64, dst : byte[], dstOffset : int64, length : int64) = x.Copy(x.GetCurrentBlock src, srcOffset, dst, dstOffset, length) \n    member x.Copy(src : FileHandle, dst : byte[], dstOffset : int64, length : int64) = x.Copy(x.GetCurrentBlock src, 0L, dst, dstOffset, length)\n    member x.Copy(src : FileHandle, srcOffset : int64, dst : byte[], length : int64) = x.Copy(x.GetCurrentBlock src, srcOffset, dst, 0L, length)\n    member x.Copy(src : FileHandle, dst : byte[], length : int64) = x.Copy(x.GetCurrentBlock src, 0L, dst, 0L, length)\n    member x.Copy(src : FileHandle, dst : byte[]) = x.Copy(x.GetCurrentBlock src, 0L, dst, 0L, dst.LongLength)\n\n    member x.Read(src : FileHandle) =\n        if src.EntryId >= 0 then\n            let arr = Array.zeroCreate (int src.Length)\n            x.Copy(x.GetCurrentBlock src, 0L, arr, 0L, arr.LongLength)\n            arr\n        else\n            [||]\n\n\n\n    member x.TotalMemory = Mem mem.Size + Mem (chunks |> Seq.sumBy (fun m -> m.Size))\n    member x.Entries = !!header.BCount - !!header.BFreeCount\n    member x.Files = !!header.ECount - !!header.EFreeCount\n\n    member x.Statistics =\n        {\n            growManagerTime     = growManagerTime.MicroTime\n            growDictTime        = growDictTime.MicroTime\n            growDataTime        = growDataTime.MicroTime\n            rehashTime          = rehashTime.MicroTime\n            reallocTime         = reallocTime.MicroTime\n            allocCount          = allocCount\n            freeCount           = freeCount\n            fileCount           = !!header.ECount - !!header.EFreeCount\n            blockCount          = !!header.BCount - !!header.BFreeCount\n        }\n\n\n    member private x.Dispose(disposing : bool) =\n        if header.ptr <> 0n then\n            if disposing then GC.SuppressFinalize x\n            mem.Dispose()\n            chunks |> Seq.iter (fun c -> c.Dispose())\n            chunks.Clear()\n            header <- headerptr.Null\n            nodes <- nodeptr.Null\n            blocks <- blockptr.Null\n            entries <- dentryptr.Null\n            buckets <- NativePtr.zero<int>\n\n    member x.Dispose() = x.Dispose(true)\n    override x.Finalize() = x.Dispose(false)\n\n    interface IDisposable with\n        member x.Dispose() = x.Dispose(true)\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule FileManager =\n\n    let directory (dir : string) =\n        let exists = Directory.Exists dir\n        if not exists then Directory.CreateDirectory dir |> ignore\n\n        let main = Path.Combine(dir, \"index.bin\") |> Memory.mapped\n        let get (i : int) =\n            Path.Combine(dir, sprintf \"store%d.bin\" i) |> Memory.mapped\n\n        new FileManager(main, get)\n    \n    let hglobal () =\n        let main = Memory.hglobal 0L\n        let get (i : int) =\n            Memory.hglobal 0L\n\n        new FileManager(main, get)\n            \n\n\n\ntype BlobStore(m : Memory, getChunk : int -> Memory) =\n    let store = new FileManager(m, getChunk)\n    let cache = System.Collections.Concurrent.ConcurrentDictionary<Guid, BlobFile>()\n\n    let rw = new ReaderWriterLockSlim()\n\n    member x.Memory = \n        ReaderWriterLock.read rw (fun () -> store.TotalMemory)\n\n    member x.Get (id : Guid) =\n        cache.GetOrAdd(id, fun id ->\n            ReaderWriterLock.write rw (fun () -> \n                BlobFile(rw, store, id, store.GetFile id)\n            )\n        )\n\n    member x.Create() =\n        let id = Guid.NewGuid()\n        ReaderWriterLock.write rw (fun () -> \n            let res = BlobFile(rw, store, id, store.GetFile id)\n            cache.[id] <- res\n            res\n        )\n\n    member x.Dispose() = \n        ReaderWriterLock.write rw (fun () -> \n            store.Dispose()\n        )\n        \n\n    interface IBlobStore with\n        member x.Memory = x.Memory\n        member x.Get id = x.Get(id) :> IBlobFile\n        member x.Create() = x.Create() :> IBlobFile\n        member x.Dispose() = x.Dispose()\n\nand BlobFile(rw : ReaderWriterLockSlim, store : FileManager, id : Guid, eid : FileHandle) =\n    let mutable eid = eid\n    let mutable bid = store.GetCurrentBlock eid\n\n    member x.Name = id\n\n    member x.Exists =\n        lock x (fun () -> eid.Exists)\n\n    member x.Size =\n        lock x (fun () -> eid.Size)\n\n    member x.Read() =\n        lock x (fun () ->\n            ReaderWriterLock.read rw (fun () ->\n                store.Read bid\n            )\n        )\n\n    member x.Write(data : byte[]) =\n        lock x (fun () ->\n            if eid.Size <> data.LongLength then\n                ReaderWriterLock.write rw (fun () ->\n                    if not eid.Exists then\n                        eid <- store.GetFile(id)\n\n                    store.Resize(eid, data.LongLength)\n                    bid <- store.GetCurrentBlock eid\n                )\n\n            ReaderWriterLock.read rw (fun () ->\n                store.Copy(data, 0L, bid, 0L, data.LongLength)\n            )\n        )\n\n    member x.Delete() =\n        lock x (fun () ->\n            if eid.Exists then\n                ReaderWriterLock.write rw (fun () ->\n                    store.Delete(eid)\n                    \n                )\n        )\n\n    interface IBlobFile with\n        member x.Name = x.Name\n        member x.Exists = x.Exists\n        member x.Size = x.Size\n        member x.Read() = x.Read()\n        member x.Write arr = x.Write arr\n        member x.Delete() = x.Delete()\n        member x.CopyTo o = o.Write (x.Read())\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule BlobStore =\n    let directory (dir : string) =\n        let exists = Directory.Exists dir\n        if not exists then Directory.CreateDirectory dir |> ignore\n\n        let main = Path.Combine(dir, \"index.bin\") |> Memory.mapped\n        let get (i : int) =\n            Path.Combine(dir, sprintf \"store%d.bin\" i) |> Memory.mapped\n\n        new BlobStore(main, get)\n\n    let hglobal () =\n        let main = Memory.hglobal 0L\n        let get (i : int) =\n            Memory.hglobal 0L\n\n        new BlobStore(main, get)\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/Formatf.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Text\nopen System.Text.RegularExpressions\nopen System.Collections.Concurrent\nopen Aardvark.Base\nopen Microsoft.FSharp.Reflection\n\ntype StringFormat = \n    struct\n        val mutable public Format : string\n        val mutable public Args : obj[]\n\n        override x.ToString() = String.Format(x.Format, x.Args)\n\n        new(f,a) = { Format = f; Args = a }\n\n    end\n        \ntype StringFormat<'a, 'r> = Format<'a, unit, StringFormat, 'r>\n\n[<AutoOpen>]\nmodule Printf =\n    module private FormatString =\n\n        /// Used for width and precision to denote that user has specified '*' flag\n        [<Literal>]\n        let StarValue = -1\n        /// Used for width and precision to denote that corresponding value was omitted in format string\n        [<Literal>]\n        let NotSpecifiedValue = -2\n\n        type FormatFlags = \n            | None = 0\n            | LeftJustify = 1\n            | PadWithZeros = 2\n            | PlusForPositives = 4\n            | SpaceForPositives = 8\n\n        let inline isDigit c = c >= '0' && c <= '9'\n        let intFromString (s : string) pos = \n            let rec go acc i =\n                if isDigit s.[i] then \n                    let n = int s.[i] - int '0'\n                    go (acc * 10 + n) (i + 1)\n                else acc, i\n            go 0 pos\n\n        let parseFlags (s : string) i : FormatFlags * int = \n            let rec go flags i = \n                match s.[i] with\n                | '0' -> go (flags ||| FormatFlags.PadWithZeros) (i + 1)\n                | '+' -> go (flags ||| FormatFlags.PlusForPositives) (i + 1)\n                | ' ' -> go (flags ||| FormatFlags.SpaceForPositives) (i + 1)\n                | '-' -> go (flags ||| FormatFlags.LeftJustify) (i + 1)\n                | _ -> flags, i\n            go FormatFlags.None i\n\n        let parseWidth (s : string) i : int * int = \n            if s.[i] = '*' then StarValue, (i + 1)\n            elif isDigit (s.[i]) then intFromString s i\n            else NotSpecifiedValue, i\n\n        let parsePrecision (s : string) i : int * int = \n            if s.[i] = '.' then\n                if s.[i + 1] = '*' then StarValue, i + 2\n                elif isDigit (s.[i + 1]) then intFromString s (i + 1)\n                else raise (ArgumentException(\"invalid precision value\"))\n            else NotSpecifiedValue, i\n        \n        let parseTypeChar (s : string) i : char * int = \n            s.[i], (i + 1)\n\n        let findNextFormatSpecifier (s : string) i = \n            let rec go i (buf : Text.StringBuilder) =\n                if i >= s.Length then \n                    s.Length, s.Length, buf.ToString()\n                else\n                    let c = s.[i]\n                    if c = '%' then\n                        if i + 1 < s.Length then\n                            let _, i1 = parseFlags s (i + 1)\n                            let w, i2 = parseWidth s i1\n                            let p, i3 = parsePrecision s i2\n                            let typeChar, i4 = parseTypeChar s i3\n                            // shortcut for the simpliest case\n                            // if typeChar is not % or it has star as width\\precision - resort to long path\n                            if typeChar = '%' && not (w = StarValue || p = StarValue) then \n                                buf.Append('%') |> ignore\n                                go i4 buf\n                            else \n                                i, i4, buf.ToString()\n                        else\n                            raise (ArgumentException(\"Missing format specifier\"))\n                    else \n                        buf.Append(c) |> ignore\n                        go (i + 1) buf\n            go i (Text.StringBuilder())\n\n    open System.Reflection\n    open System.Reflection.Emit\n\n    type private StringFormatCache<'a, 'res> private() =\n        static let contType = typeof<StringFormat -> 'res>\n\n        static let rec getFunctionSignature (t : Type) =\n            if t = typeof<'res> then [], t\n            elif FSharpType.IsFunction t then\n                let (d,i) = FSharpType.GetFunctionElements t\n                let args, ret = getFunctionSignature i\n                d::args, ret\n            else\n                [], t\n\n        static let args, _ = getFunctionSignature typeof<'a>\n        static let args : Type[] = List.toArray (contType::args)\n\n        static let invokeCont = contType.GetMethod(\"Invoke\", BindingFlags.Instance ||| BindingFlags.Public, Type.DefaultBinder, [| typeof<StringFormat> |], null)\n        static let formatCtor = typeof<StringFormat>.GetConstructor [| typeof<string>; typeof<obj[]> |]\n\n        static let createFunction (fmt : string) : (StringFormat -> 'res) -> 'a =\n            let meth =\n                DynamicMethod(\n                    \"StringFormat_\" + fmt,\n                    typeof<'res>, args,\n                    true\n                )\n\n            let il = meth.GetILGenerator()\n\n            let arr = il.DeclareLocal(typeof<obj[]>)\n            il.Emit(OpCodes.Ldc_I4, args.Length - 1)\n            il.Emit(OpCodes.Newarr, typeof<obj>)\n            il.Emit(OpCodes.Stloc, arr)\n\n            for i in 1..args.Length-1 do\n                let t = args.[i] \n                il.Emit(OpCodes.Ldloc, arr)\n                il.Emit(OpCodes.Ldc_I4, i - 1)\n\n                il.Emit(OpCodes.Ldarg, i)\n                if t.IsValueType then\n                    il.Emit(OpCodes.Box, t)\n\n                il.Emit(OpCodes.Stelem_Ref)\n\n            il.Emit(OpCodes.Ldarg_0)\n\n            il.Emit(OpCodes.Ldstr, fmt)\n            il.Emit(OpCodes.Ldloc, arr)\n            il.Emit(OpCodes.Newobj, formatCtor)\n\n            il.EmitCall(OpCodes.Callvirt, invokeCont, null)\n            il.Emit(OpCodes.Ret)\n\n            let del = \n                if typeof<'res> = typeof<System.Void> then\n                    let funcType = typedefof<Action<_>>.FullName.Replace(\"1\", string (args.Length)) |> Type.GetType\n                    let funcType = funcType.MakeGenericType args\n\n                    meth.CreateDelegate(funcType)\n                else\n                    let funcType = typedefof<Func<_>>.FullName.Replace(\"1\", string (args.Length + 1)) |> Type.GetType\n                    let funcType = funcType.MakeGenericType (Array.append args [|typeof<'res>|])\n\n                    meth.CreateDelegate(funcType)\n\n            DelegateAdapters.wrap del\n\n        static let create(value : string) : (StringFormat -> 'res) -> 'a =\n            \n            let mutable args = []\n            let mutable ret = typeof<'a>\n\n            let formatBuilder = StringBuilder()\n            let mutable i = 0\n            let mutable c = 0\n            while c < value.Length do\n                let (s,e,str) = FormatString.findNextFormatSpecifier value c\n                formatBuilder.Append(str.Replace(\"{\", \"{{\").Replace(\"}\", \"}}\")) |> ignore\n                c <- e\n\n                if s < value.Length then\n                    formatBuilder.Append(\"{\" + string i + \"}\") |> ignore\n                    i <- i + 1\n                    let (d,i) = FSharpType.GetFunctionElements ret\n                    args <- d::args\n                    ret <- i\n\n            let formatString = formatBuilder.ToString()\n            createFunction formatString\n\n        static let cache = ConcurrentDictionary<string, (StringFormat -> 'res) -> 'a>()\n\n        static member get (fmt : StringFormat<'a, 'res>) =\n            cache.GetOrAdd(fmt.Value, Func<string, _>(fun value -> create value))\n\n\n    let formatf (fmt : StringFormat<'a, StringFormat>) : 'a =\n        StringFormatCache<'a, StringFormat>.get fmt id\n\n    let kformatf (f : StringFormat -> 'res) (fmt : StringFormat<'a, 'res>) : 'a =\n        StringFormatCache<'a, 'res>.get fmt f\n\n    "
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/FunctionReflection.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\Bin\\\\Debug\\\\Aardvark.Base.dll\"\nopen Aardvark.Base\n#else\nnamespace Aardvark.Base\n#endif\n\nopen System.Linq.Expressions\nopen System.Runtime.InteropServices\nopen Microsoft.FSharp.Reflection\nopen System.Reflection\nopen System.Reflection.Emit\nopen System\n\n/// <summary>\n/// FunctionReflection provides functions wrapping MethodInfos as F# functions efficiently.\n/// It also allows to create n-ary functions using an untyped implementation.\n/// </summary>\nmodule FunctionReflection =\n\n    let rec private sequentializeTupleType (t : Type) =\n        if FSharpType.IsTuple t then\n            t |> FSharpType.GetTupleElements |> Seq.collect sequentializeTupleType\n        else\n            seq { yield t }\n\n    let private tupleGet (p : ParameterExpression) (i : int) =\n        if FSharpType.IsTuple p.Type then\n            let name = sprintf \"Item%d\" (i+1)\n            let pi = p.Type.GetProperty(name)\n            if not (isNull pi) then\n                Expression.Property(p, pi.GetMethod) :> Expression\n            else\n                failwithf \"property %A was not fount for type %A\" name p.Type\n        else\n            if i = 0 then p :> Expression\n            else failwithf \"cannot access tuple elements of type %A\" p.Type\n\n    let rec private getMethodSignatureInternal (t : Type) =\n        if FSharpType.IsFunction t then\n            let a, ret = FSharpType.GetFunctionElements t\n            let args, ret = getMethodSignatureInternal ret\n\n            if a = typeof<unit> then\n                (args, ret)\n            else\n                (a::args, ret)\n\n        else\n            if t = typeof<unit> then ([],typeof<System.Void>)\n            else ([],t)\n\n    let rec getMethodSignature (t : Type) =\n        if FSharpType.IsFunction t then\n            let a, ret = FSharpType.GetFunctionElements t\n            let args, ret = getMethodSignature ret\n\n            //Here be dragons\n            if a = typeof<unit> then\n                (args, ret)\n            else\n                let a = a |> sequentializeTupleType |> Seq.toList\n                (List.concat [a; args], ret)\n\n        else\n            if t = typeof<unit> then ([],typeof<System.Void>)\n            else ([],t)\n\n    \n\n    let rec private buildLambda (args : list<ParameterExpression>) (callArgs : list<Expression>) (target : obj) (argTypes : list<Type>) (mi : MethodInfo) =\n        match argTypes with\n            | x::xs -> let v = Expression.Variable(x)\n                       let x = x |> sequentializeTupleType |> Seq.toList\n                       let tupleArgs = x |> List.mapi (fun i xi -> tupleGet v i)\n                       buildLambda (v::args) (List.concat [callArgs; tupleArgs]) target xs mi\n            | [] -> let args = List.rev args\n                    let call = if isNull target then Expression.Call(mi, callArgs)\n                               else Expression.Call(Expression.Constant(target), mi, callArgs)\n\n                    Expression.Lambda(\n                        call,\n                        args)\n          \n    let private buildLambdaExpression (target : obj) (mi : MethodInfo) (funType : Type) : 'a =\n        let (args,ret) = getMethodSignatureInternal funType //mi.GetParameters() |> Seq.map (fun p -> p.ParameterType) |> Seq.toList\n        let lambda = buildLambda [] [] target args mi |> unbox<Expression<'a>>\n\n        lambda.Compile()\n          \n    type FunctionBuilder =\n\n        static member BuildFunction (target : obj,mi : MethodInfo) : 'a -> 'r =\n            if typeof<'a> = typeof<unit> then\n                if typeof<'r> = typeof<unit> then\n                    let a : Action = buildLambdaExpression target mi typeof<'a -> 'r>\n                    fun _ -> a.Invoke() |> unbox<'r>\n                else\n                    let f : Func<'r> = buildLambdaExpression target mi typeof<'a -> 'r>\n                    fun _ -> f.Invoke()\n            else\n                if typeof<'r> = typeof<unit> then\n                    let a : Action<'a> = buildLambdaExpression target mi typeof<'a -> 'r>\n                    fun a0 -> a.Invoke(a0) |> unbox<'r>\n                else\n                    let f : Func<'a, 'r> = buildLambdaExpression target mi typeof<'a -> 'r>\n                    f.Invoke\n\n        static member BuildFunction (target : obj,mi : MethodInfo) : 'a -> 'b -> 'r =\n            if typeof<'r> = typeof<unit> then\n                let a : Action<'a, 'b> = buildLambdaExpression target mi typeof<'a -> 'b -> 'r>\n                fun a0 a1 -> a.Invoke(a0,a1) |> unbox<'r>\n            else\n                let f : Func<'a, 'b, 'r> = buildLambdaExpression target mi typeof<'a -> 'b -> 'r>\n                fun a0 a1 -> f.Invoke(a0,a1)\n\n        static member BuildFunction (target : obj,mi : MethodInfo) : 'a -> 'b -> 'c -> 'r =\n            if typeof<'r> = typeof<unit> then\n                let a : Action<'a, 'b, 'c> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'r>\n                fun a0 a1 a2 -> a.Invoke(a0,a1,a2) |> unbox<'r>\n            else\n                let f : Func<'a, 'b, 'c, 'r> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'r>\n                fun a0 a1 a2 -> f.Invoke(a0,a1,a2)\n\n        static member BuildFunction (target : obj,mi : MethodInfo) : 'a -> 'b -> 'c -> 'd -> 'r =\n            if typeof<'r> = typeof<unit> then\n                let a : Action<'a, 'b, 'c, 'd> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'r>\n                fun a0 a1 a2 a3 -> a.Invoke(a0,a1,a2,a3) |> unbox<'r>\n            else\n                let f : Func<'a, 'b, 'c, 'd, 'r> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'r>\n                fun a0 a1 a2 a3 -> f.Invoke(a0,a1,a2,a3)\n\n        static member BuildFunction (target : obj,mi : MethodInfo) : 'a -> 'b -> 'c -> 'd -> 'e -> 'r =\n            if typeof<'r> = typeof<unit> then\n                let a : Action<'a, 'b, 'c, 'd, 'e> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'e -> 'r>\n                fun a0 a1 a2 a3 a4 -> a.Invoke(a0,a1,a2,a3,a4) |> unbox<'r>\n            else\n                let f : Func<'a, 'b, 'c, 'd, 'e, 'r> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'e -> 'r>\n                fun a0 a1 a2 a3 a4 -> f.Invoke(a0,a1,a2,a3,a4)\n\n        static member BuildFunction (target : obj,mi : MethodInfo) : 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'r =\n            if typeof<'r> = typeof<unit> then\n                let a : Action<'a, 'b, 'c, 'd, 'e, 'f> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'r>\n                fun a0 a1 a2 a3 a4 a5 -> a.Invoke(a0,a1,a2,a3,a4,a5) |> unbox<'r>\n            else\n                let f : Func<'a, 'b, 'c, 'd, 'e, 'f, 'r> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'r>\n                fun a0 a1 a2 a3 a4 a5 -> f.Invoke(a0,a1,a2,a3,a4,a5)\n\n        static member BuildFunction (target : obj,mi : MethodInfo) : 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'r =\n            if typeof<'r> = typeof<unit> then\n                let a : Action<'a, 'b, 'c, 'd, 'e, 'f, 'g> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'r>\n                fun a0 a1 a2 a3 a4 a5 a6 -> a.Invoke(a0,a1,a2,a3,a4,a5,a6) |> unbox<'r>\n            else\n                let f : Func<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'r> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'r>\n                fun a0 a1 a2 a3 a4 a5 a6 -> f.Invoke(a0,a1,a2,a3,a4,a5,a6)\n\n        static member BuildFunction (target : obj,mi : MethodInfo) : 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'h -> 'r=\n            if typeof<'r> = typeof<unit> then\n                let a : Action<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'h -> 'r>\n                fun a0 a1 a2 a3 a4 a5 a6 a7 -> a.Invoke(a0,a1,a2,a3,a4,a5,a6,a7) |> unbox<'r>\n            else\n                let f : Func<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'r> = buildLambdaExpression target mi typeof<'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'h -> 'r>\n                fun a0 a1 a2 a3 a4 a5 a6 a7 -> f.Invoke(a0,a1,a2,a3,a4,a5,a6,a7)\n\n    let private buildFunctionInternal (target : obj) (argTypes : list<Type>) (mi : MethodInfo) : 'a =\n        let t = typeof<'a>\n        let mutable ret = t\n        let args = System.Collections.Generic.List()\n        while FSharpType.IsFunction ret do\n            let a,r = FSharpType.GetFunctionElements ret\n            args.Add a\n            ret <- r\n\n        let ret = ret\n        let genArgs = seq { yield! args; yield ret } |> Seq.toArray\n\n        let m = typeof<FunctionBuilder>.GetMethods(BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Static) \n             |> Seq.filter (fun mi -> mi.Name = \"BuildFunction\")\n             |> Seq.filter (fun mi -> mi.IsGenericMethodDefinition && mi.GetGenericArguments().Length = genArgs.Length)\n             |> Seq.tryPick(fun mi -> mi.MakeGenericMethod genArgs |> Some)\n\n        match m with\n            | Some m -> m.Invoke(null, [|target; mi :> obj|]) |> unbox<'a>\n            | None -> failwithf \"could not wrap function of with generic args: %A\" genArgs \n\n    let buildFunction (target : obj) (mi : MethodInfo) = \n        buildFunctionInternal target [] mi\n\n        \n\n    [<System.Diagnostics.DebuggerStepThroughAttribute>]\n    let rec private makeNAryFunctionInternal (t : Type) (count : int) (f : obj[] -> obj) : int * (obj[] -> obj) =\n        if FSharpType.IsFunction t then\n            let index = count\n            let (_,ret) = FSharpType.GetFunctionElements t\n            let count,c = makeNAryFunctionInternal ret (count + 1) f\n\n            (count, fun args ->\n                        FSharpValue.MakeFunction(t, fun o ->\n                            args.[index] <- o\n                            c(args))\n            )\n\n        else\n            (count, fun args -> f args)\n\n    [<System.Diagnostics.DebuggerStepThroughAttribute>]\n    let makeNAryFunction (f : obj[] -> obj) : 'x =\n        let t = typeof<'x>\n\n        let (count, c) = makeNAryFunctionInternal t 0 f\n        let args = Array.create count null\n        c args |> unbox\n\n    let makeFormatFunction (f : string -> obj[] -> obj) (fmt : Printf.BuilderFormat<'r, obj>) : 'r =\n        makeNAryFunction (fun args ->\n            (f fmt.Value args)\n        )\n\nmodule QuotationReflectionHelpers =\n    open Microsoft.FSharp.Quotations\n\n    //extracts the (optional) top-most method call from an expression\n    let rec tryGetMethodInfo (e : Expr) =\n        match e with\n            | Patterns.Call(_,mi,_) -> \n                if mi.IsGenericMethod then mi.GetGenericMethodDefinition() |> Some\n                else mi |> Some\n            | ExprShape.ShapeCombination(_, args) -> \n                args |> List.tryPick tryGetMethodInfo\n            | ExprShape.ShapeLambda(_,b) ->\n                tryGetMethodInfo b\n            | _ -> None\n\n\n    /// <summary>\n    /// extracts the top-most method-call from an expression.\n    /// When no method-call is found the method will raise an exception\n    /// </summary>\n    /// <param name=\"e\"></param>\n    let getMethodInfo (e : Expr) =\n        match tryGetMethodInfo e with\n            | Some mi -> mi\n            | None -> failwith \"could not find a method-call in expression\"\n\nmodule DelegateAdapters =\n\n    type AdapterFunc =\n        static member Convert0 (f : Func<'a>) = f.Invoke\n        static member Convert1 (f : Func<'a, 'b>) = f.Invoke\n        static member Convert2 (f : Func<'a, 'b, 'c>) = fun a b -> f.Invoke(a,b)\n        static member Convert3 (f : Func<'a, 'b, 'c, 'd>) = fun a b c -> f.Invoke(a,b,c)\n        static member Convert4 (f : Func<'a, 'b, 'c, 'd, 'e>) = fun a b c d -> f.Invoke(a,b,c,d)\n        static member Convert5 (f : Func<'a, 'b, 'c, 'd, 'e, 'f>) = fun a b c d e -> f.Invoke(a,b,c,d,e)\n        \n    type AdapterAction =\n        static member Convert0 (f : Action) = f.Invoke\n        static member Convert1 (f : Action<'a>) = f.Invoke\n        static member Convert2 (f : Action<'a, 'b>) = fun a b -> f.Invoke(a,b)\n        static member Convert3 (f : Action<'a, 'b, 'c>) = fun a b c -> f.Invoke(a,b,c)\n        static member Convert4 (f : Action<'a, 'b, 'c, 'd>) = fun a b c d -> f.Invoke(a,b,c,d)\n        static member Convert5 (f : Action<'a, 'b, 'c, 'd, 'e>) = fun a b c d e -> f.Invoke(a,b,c,d,e)\n     \n    let rec getFunctionSignature (t : Type) =\n        if FSharpType.IsFunction t then\n            let (d,i) = FSharpType.GetFunctionElements t\n            let args, ret = getFunctionSignature i\n            d::args, ret\n        else\n            [], t\n\n    let wrapUntyped (d : Delegate) : obj =\n        let mi = d.GetMethodInfo()\n        let args = mi.GetParameters() |> Array.map (fun p -> p.ParameterType)\n        \n        let ret = \n            if mi.ReturnType = typeof<System.Void> then typeof<unit>\n            else mi.ReturnType\n\n        let generic, args = \n            if mi.ReturnType = typeof<System.Void> then\n                typeof<AdapterAction>.GetMethod(\"Convert\" + string args.Length), args\n                //Type.GetType(typedefof<AdapterAction<_>>.FullName.Replace(\"1\", string args.Length))\n            else\n                typeof<AdapterFunc>.GetMethod(\"Convert\" + string args.Length), Array.append args [|ret|]\n                //Type.GetType(typedefof<AdapterFunc<_>>.FullName.Replace(\"1\", string args.Length))\n\n        if isNull generic then\n            let code = args |> Seq.map (fun t -> t.Name) |> String.concat \" -> \"\n            failwithf \"could not get delegate adapter: %s\" code\n\n        let t = generic.MakeGenericMethod args\n        t.Invoke(null, [|d|])\n        //Activator.CreateInstance(t, d)\n\n    let wrap (d : Delegate) : 'a =\n        match wrapUntyped d with\n            | :? 'a as res -> res\n            | _ ->\n                failwithf \"[DelegateAdapter] cannot convert from delegate %A to %A\" (d.GetType()) typeof<'a>\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/IL.fs",
    "content": "﻿namespace Aardvark.Base.IL\n\nopen System\nopen System.IO\nopen System.Threading\nopen System.Reflection\nopen System.Reflection.Emit\nopen Microsoft.FSharp.Quotations\nopen Microsoft.FSharp.Quotations.Patterns\nopen Aardvark.Base\nopen Aardvark.Base.FunctionReflection\n\ntype JumpCondition =\n    | Less \n    | LessOrEqual\n    | Greater\n    | GreaterOrEqual\n    | Equal\n    | NotEqual\n    | False\n    | True\n\ntype Constant =\n    | Int8 of int8\n    | UInt8 of uint8\n    | Int16 of int16\n    | UInt16 of uint16\n    | Int32 of int32\n    | UInt32 of uint32\n    | Int64 of int64\n    | UInt64 of uint64\n    | Float64 of float\n    | Float32 of float32\n    | NativeInt of nativeint\n    | UNativeInt of unativeint\n    | String of string\n\ntype ValueType =\n    | Int8              = 0\n    | UInt8             = 1\n    | Int16             = 2\n    | UInt16            = 3\n    | Int32             = 4\n    | UInt32            = 5            \n    | Int64             = 6\n    | UInt64            = 7\n    | Float64           = 8\n    | Float32           = 9\n    | NativeInt         = 10\n    | UNativeInt        = 11\n    | Object            = 12\n\ntype Label private(id : int) =\n    static let mutable currentId = 0\n    \n    member x.Id = id\n\n    override x.ToString() =\n        sprintf \"Label(%d)\" id\n\n    override x.GetHashCode() = id.GetHashCode()\n    override x.Equals o =\n        match o with\n            | :? Label as o -> id = o.Id\n            | _ -> false\n\n    interface IComparable with\n        member x.CompareTo o =\n            match o with\n                | :? Label as o -> compare id o.Id\n                | _ -> failwithf \"cannot compare Label with %A\" o\n\n\n    new() = Label(Interlocked.Increment(&currentId))\n\ntype Local private(id : int, name : string, t : Type) =\n    \n    static let mutable currentId = 0\n\n    member x.Id = id\n    member x.Name = name\n    member x.Type = t\n\n    override x.ToString() =\n        if String.IsNullOrWhiteSpace name then sprintf \"local%d(%A)\" id t\n        else sprintf \"%s(%A)\" name t\n\n    override x.GetHashCode() = id.GetHashCode()\n    override x.Equals o =\n        match o with\n            | :? Local as o -> id = o.Id\n            | _ -> false\n\n    interface IComparable with\n        member x.CompareTo o =\n            match o with\n                | :? Local as o -> compare id o.Id\n                | _ -> failwithf \"cannot compare Local with %A\" o\n\n\n    new(name, t) = Local(Interlocked.Increment(&currentId), name, t)\n    new(t) = Local(Interlocked.Increment(&currentId), \"\", t)\n\ntype Instruction =\n    | Start\n    | Nop\n    | Break\n        \n    | Dup\n    | Pop\n\n    | Ldarg of int\n    | LdargA of int\n    | Starg of int\n        \n    | Ldloc of Local\n    | LdlocA of Local\n    | Stloc of Local\n\n    | Ldfld of FieldInfo\n    | LdfldA of FieldInfo\n    | Stfld of FieldInfo\n\n\n    | LdIndirect of ValueType\n    | StIndirect of ValueType\n    | CpObj of Type\n    | LdObj of Type\n    | StObj of Type\n    | NewObj of ConstructorInfo\n    | InitObj of Type\n    | CastClass of Type\n    | IsInstance of Type\n\n    | Unbox of Type\n    | UnboxAny of Type\n    | Box of Type\n\n    | NewArr of Type\n    | Ldlen\n    | Ldelem of Type\n    | LdelemA of Type\n    | Stelem of Type\n\n\n    | Add | Sub | Mul | Div | Rem | And | Or | Xor | Shl | Shr \n    | Neg | Not\n\n    | Conv of ValueType\n    | ConvChecked of ValueType\n\n    | RefAnyVal of Type\n    | CkFinite\n    | MkRefAny of Type\n\n    | LdNull\n    | LdConst of Constant\n    | LdToken of obj\n    \n    | WriteLine of string\n        \n    | ReadOnly\n    | Tail\n    | Mark of Label\n    | ConditionalJump of JumpCondition * Label\n    | Jump of Label\n    | Call of MethodBase\n    | CallIndirect\n    | Ret\n    | Switch of Label[]\n    | Throw\n    | EndFinally\n    | Leave of Label\n\ntype MethodDefinition =\n    {\n        ArgumentTypes : Type[]\n        ReturnType : Type\n        Body : list<Instruction>\n    }\n\nmodule StateMonad =\n    type State<'s, 'a> = 's -> 's * 'a\n\n    module State =\n        let bind (f : 'a -> State<'s, 'b>) (m : State<'s, 'a>) : State<'s, 'b> =\n            fun s ->\n                let (s,v) = m s\n                f v s\n\n        let combine (l : State<'s, unit>) (r : State<'s, 'a>) : State<'s, 'a> =\n            fun s ->\n                let (s,()) = l s\n                r s\n\n        let map (f : 'a -> 'b) (m : State<'s, 'a>) : State<'s, 'b> =\n            fun s ->\n                let (s,v) = m s\n                s, f v\n\n        let create (v : 'a) : State<'s, 'a> = \n            fun s -> s,v\n\n        let delay (f : unit -> State<'s, 'a>) : State<'s, 'a> =\n            fun s ->\n                f () s\n\n        let get<'s> : State<'s, 's> = \n            fun s -> s,s\n\n        let put (s : 's) : State<'s, unit> = \n            fun _ -> s, ()\n\n        let modify (f : 's -> 's) : State<'s, unit> =\n            fun s -> (f s), ()\n\n\n    type StateBuilder() =\n        member x.Bind(m : State<'s, 'a>, f : 'a -> State<'s, 'b>) =\n            State.bind f m\n\n        member x.Return (v : 'a) : State<'s, 'a> =\n            State.create v\n\n        member x.ReturnFrom (m : State<'s, 'a>) : State<'s, 'a> =\n            m\n\n        member x.Delay (f : unit -> State<'s, 'a>) : State<'s, 'a> =\n            State.delay f\n                \n        member x.Zero() : State<'s, unit> =\n            State.create ()\n\n        member x.Combine(l : State<'s, unit>, r : State<'s, 'a>) =\n            State.combine l r\n\n        member x.For(elements : seq<'a>, f : 'a -> State<'s, unit>) : State<'s, unit> =\n            fun s ->\n                let mutable c = s\n                for e in elements do\n                    let (s,()) = f e c\n                    c <- s\n                c, ()\n\n        member x.While(guard : unit -> bool, body : State<'s, unit>) : State<'s, unit> =\n            fun s ->\n                let mutable c = s\n                while guard() do\n                    let (s,()) = body c\n                    c <- s\n                c, ()\n\n    let state = StateBuilder()\n\n\n[<AutoOpen>]\nmodule ReflectionExtensions = \n    type BindingFlags with\n        static member All = BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Instance\n\nmodule Disassembler = \n\n    type Parameter =\n        | This of Type\n        | Parameter of string * Type\n\n    type RawInstruction =\n        class\n            val mutable public Code : OpCode\n            val mutable public Operand : obj\n        \n\n            override x.ToString() =\n                if isNull x.Operand then sprintf \"%A\" x.Code\n                else sprintf \"%A(%A)\" x.Code x.Operand\n\n            new(c) = { Code = c; Operand = null }\n            new(c, o) = { Code = c; Operand = o }\n\n        end\n\n    [<AutoOpen>]\n    module private Helpers = \n        module OpCodes =\n            let table =\n                typeof<OpCodes>.GetFields() \n                    |> Array.toList \n                    |> List.map (fun f -> f.GetValue(null) |> unbox<OpCode>)\n                    |> List.map (fun c -> c.Value, c)\n                    |> Map.ofList\n\n            let get (value : int16) =\n                table.[value]\n\n        type ILContext =\n            {\n                TypeArgs : Type[]\n                MethodArgs : Type[]\n                Module : Module\n            }\n\n        type BinaryReader with\n\n            member x.ReadOpCode() =\n                let b0 = x.ReadByte()\n\n                if b0 = 0xFEuy then\n                    let b1 = x.ReadByte()\n                    let v = ((int16 b0) <<< 8) ||| (int16 b1)\n                    OpCodes.get v\n                else\n                    let v = int16 b0\n                    OpCodes.get v\n\n            member x.ReadOperand(ctx : ILContext, o : OperandType) =\n                match o with\n                    | OperandType.InlineNone ->\n                        null\n\n                    | OperandType.InlineBrTarget -> \n                        let off = x.ReadInt32()\n                        int x.BaseStream.Position + off :> obj\n\n\n                    | OperandType.InlineField ->\n                        let token = x.ReadInt32()\n                        let field = ctx.Module.ResolveField(token, ctx.TypeArgs, ctx.MethodArgs)\n                        field :> obj\n\n                    | OperandType.InlineI ->\n                        x.ReadInt32() :> obj\n\n                    | OperandType.InlineI8 ->\n                        x.ReadInt64() :> obj\n\n                    | OperandType.InlineMethod -> \n                        let token = x.ReadInt32()\n                        let meth = ctx.Module.ResolveMethod(token, ctx.TypeArgs, ctx.MethodArgs)\n                        meth :> obj\n\n                    | OperandType.InlineR ->\n                        x.ReadDouble() :> obj\n\n                    | OperandType.InlineSig ->\n                        let token = x.ReadInt32()\n                        let signature = ctx.Module.ResolveSignature(token)\n                        signature :> obj\n\n                    | OperandType.InlineString ->\n                        let token = x.ReadInt32()\n                        let string = ctx.Module.ResolveString(token)\n                        string :> obj\n\n                    | OperandType.InlineTok ->\n                        let token = x.ReadInt32()\n                        let v = ctx.Module.ResolveMember(token, ctx.TypeArgs, ctx.MethodArgs)\n                        v :> obj\n\n                    | OperandType.InlineType ->\n                        let token = x.ReadInt32()\n                        let v = ctx.Module.ResolveType(token, ctx.TypeArgs, ctx.MethodArgs)\n                        v :> obj\n\n                    | OperandType.InlineVar ->\n                        let id = x.ReadInt16()\n                        int id :> obj\n                \n                    | OperandType.ShortInlineBrTarget ->\n                        let off = x.ReadSByte() |> int\n                        int x.BaseStream.Position + off :> obj\n                \n\n                    | OperandType.ShortInlineI ->\n                        x.ReadSByte() :> obj\n\n                    | OperandType.ShortInlineR ->\n                        x.ReadSingle() :> obj\n\n                    | OperandType.ShortInlineVar ->\n                        let id = x.ReadByte() |> int\n                        id |> int :> obj\n\n\n                    | OperandType.InlineSwitch ->\n                        let length = x.ReadInt32()\n                        let baseOff = int x.BaseStream.Position\n                        Array.init length (fun _ -> baseOff + x.ReadInt32()) :> obj\n\n                    | _ -> failwithf \"[IL] unsupported operand-type: %A\" o\n\n            member x.ReadRawInstruction(ctx : ILContext) =\n                let code = x.ReadOpCode()\n                let op = x.ReadOperand(ctx, code.OperandType)\n                RawInstruction(code, op)\n\n\n    module Patterns =\n\n        [<return: Struct>]\n        let inline (|Nop|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Nop then ValueSome()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Break|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Break then ValueSome()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Dup|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Dup then ValueSome()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Pop|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Pop then ValueSome()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Ldarg|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldarg then ValueSome(unbox<int> i.Operand)\n            elif i.Code = OpCodes.Ldarg_0 then ValueSome 0\n            elif i.Code = OpCodes.Ldarg_1 then ValueSome 1\n            elif i.Code = OpCodes.Ldarg_2 then ValueSome 2\n            elif i.Code = OpCodes.Ldarg_3 then ValueSome 3\n            elif i.Code = OpCodes.Ldarg_S then ValueSome(unbox<int> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Starg|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Starg_S then ValueSome(unbox<int> i.Operand)\n            elif i.Code = OpCodes.Starg then ValueSome(unbox<int> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Ldarga|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldarga then ValueSome(unbox<int> i.Operand)\n            elif i.Code = OpCodes.Ldarga_S then ValueSome(unbox<int> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Ldloc|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldloc then ValueSome (unbox<int> i.Operand)\n            elif i.Code = OpCodes.Ldloc_S then ValueSome (unbox<int> i.Operand)\n            elif i.Code = OpCodes.Ldloc_0 then ValueSome 0\n            elif i.Code = OpCodes.Ldloc_1 then ValueSome 1\n            elif i.Code = OpCodes.Ldloc_2 then ValueSome 2\n            elif i.Code = OpCodes.Ldloc_3 then ValueSome 3\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|LdlocA|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldloca then ValueSome (unbox<int> i.Operand)\n            elif i.Code = OpCodes.Ldloca_S then ValueSome (unbox<int> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Stloc|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Stloc then ValueSome (unbox<int> i.Operand)\n            elif i.Code = OpCodes.Stloc_S then ValueSome (unbox<int> i.Operand)\n            elif i.Code = OpCodes.Stloc_0 then ValueSome 0\n            elif i.Code = OpCodes.Stloc_1 then ValueSome 1\n            elif i.Code = OpCodes.Stloc_2 then ValueSome 2\n            elif i.Code = OpCodes.Stloc_3 then ValueSome 3\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Ldfld|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldfld then ValueSome (unbox<FieldInfo> i.Operand)\n            elif i.Code = OpCodes.Ldsfld then ValueSome (unbox<FieldInfo> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|LdfldA|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldflda then ValueSome (unbox<FieldInfo> i.Operand)\n            elif i.Code = OpCodes.Ldsflda then ValueSome (unbox<FieldInfo> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Stfld|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Stfld then ValueSome (unbox<FieldInfo> i.Operand)\n            elif i.Code = OpCodes.Stsfld then ValueSome (unbox<FieldInfo> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|LdIndirect|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldind_I then ValueSome(ValueType.NativeInt)\n            elif i.Code = OpCodes.Ldind_I1 then ValueSome(ValueType.Int8)\n            elif i.Code = OpCodes.Ldind_U1 then ValueSome(ValueType.UInt8)\n            elif i.Code = OpCodes.Ldind_I2 then ValueSome(ValueType.Int16)\n            elif i.Code = OpCodes.Ldind_U2 then ValueSome(ValueType.UInt16)\n            elif i.Code = OpCodes.Ldind_I4 then ValueSome(ValueType.Int32)\n            elif i.Code = OpCodes.Ldind_U4 then ValueSome(ValueType.UInt32)\n            elif i.Code = OpCodes.Ldind_I8 then ValueSome(ValueType.Int64)\n\n            elif i.Code = OpCodes.Ldind_R4 then ValueSome(ValueType.Float32)\n            elif i.Code = OpCodes.Ldind_R8 then ValueSome(ValueType.Float64)\n            elif i.Code = OpCodes.Ldind_Ref then ValueSome(ValueType.Object)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|StIndirect|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Stind_I then ValueSome(ValueType.NativeInt)\n            elif i.Code = OpCodes.Stind_I1 then ValueSome(ValueType.Int8)\n            elif i.Code = OpCodes.Stind_I2 then ValueSome(ValueType.Int16)\n            elif i.Code = OpCodes.Stind_I4 then ValueSome(ValueType.Int32)\n            elif i.Code = OpCodes.Stind_I8 then ValueSome(ValueType.Int64)\n            elif i.Code = OpCodes.Stind_R4 then ValueSome(ValueType.Float32)\n            elif i.Code = OpCodes.Stind_R8 then ValueSome(ValueType.Float64)\n            elif i.Code = OpCodes.Stind_Ref then ValueSome(ValueType.Object)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|CpObj|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Cpobj then ValueSome(unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|LdObj|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldobj then ValueSome(unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|StObj|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Stobj then ValueSome(unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|NewObj|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Newobj then ValueSome (unbox<ConstructorInfo> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|InitObj|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Initobj then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|CastClass|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Castclass then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|IsInstance|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Isinst then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Unbox|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Unbox then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|UnboxAny|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Unbox_Any then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Box|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Box then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|NewArr|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Newarr then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Ldlen|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldlen then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Ldelem|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldelem then ValueSome(unbox<Type> i.Operand)\n            elif i.Code = OpCodes.Ldelem_I1 then ValueSome typeof<int8>\n            elif i.Code = OpCodes.Ldelem_U1 then ValueSome typeof<uint8>\n            elif i.Code = OpCodes.Ldelem_I2 then ValueSome typeof<int16>\n            elif i.Code = OpCodes.Ldelem_U2 then ValueSome typeof<uint16>\n            elif i.Code = OpCodes.Ldelem_I4 then ValueSome typeof<int32>\n            elif i.Code = OpCodes.Ldelem_U4 then ValueSome typeof<uint32>\n            elif i.Code = OpCodes.Ldelem_I8 then ValueSome typeof<int64>\n            elif i.Code = OpCodes.Ldelem_R4 then ValueSome typeof<float32>\n            elif i.Code = OpCodes.Ldelem_R8 then ValueSome typeof<float>\n            elif i.Code = OpCodes.Ldelem_I then ValueSome typeof<nativeint>\n            elif i.Code = OpCodes.Ldelem_Ref then ValueSome typeof<obj>\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|LdelemA|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldelema then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Stelem|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Stelem then ValueSome(unbox<Type> i.Operand)\n            elif i.Code = OpCodes.Stelem_I1 then ValueSome typeof<int8>\n            elif i.Code = OpCodes.Stelem_I2 then ValueSome typeof<int16>\n            elif i.Code = OpCodes.Stelem_I4 then ValueSome typeof<int32>\n            elif i.Code = OpCodes.Stelem_I8 then ValueSome typeof<int64>\n            elif i.Code = OpCodes.Stelem_R4 then ValueSome typeof<float32>\n            elif i.Code = OpCodes.Stelem_R8 then ValueSome typeof<float>\n            elif i.Code = OpCodes.Stelem_I then ValueSome typeof<nativeint>\n            elif i.Code = OpCodes.Stelem_Ref then ValueSome typeof<obj>\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Add|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Add then ValueSome ()\n            elif i.Code = OpCodes.Add_Ovf then ValueSome ()\n            elif i.Code = OpCodes.Add_Ovf_Un then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Sub|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Sub then ValueSome ()\n            elif i.Code = OpCodes.Sub_Ovf then ValueSome ()\n            elif i.Code = OpCodes.Sub_Ovf_Un then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Mul|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Mul then ValueSome ()\n            elif i.Code = OpCodes.Mul_Ovf then ValueSome ()\n            elif i.Code = OpCodes.Mul_Ovf_Un then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Div|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Div then ValueSome ()\n            elif i.Code = OpCodes.Div_Un then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Rem|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Rem then ValueSome ()\n            elif i.Code = OpCodes.Rem_Un then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|And|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.And then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Or|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Or then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Xor|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Xor then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Shl|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Shl then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Shr|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Shr then ValueSome ()\n            elif i.Code = OpCodes.Shr_Un then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Neg|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Neg then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Not|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Not then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Conv|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Conv_I1 then ValueSome ValueType.Int8\n            elif i.Code = OpCodes.Conv_U1 then ValueSome ValueType.UInt8\n            elif i.Code = OpCodes.Conv_I2 then ValueSome ValueType.Int16\n            elif i.Code = OpCodes.Conv_U2 then ValueSome ValueType.UInt16\n            elif i.Code = OpCodes.Conv_I4 then ValueSome ValueType.Int32\n            elif i.Code = OpCodes.Conv_U4 then ValueSome ValueType.UInt32\n            elif i.Code = OpCodes.Conv_I8 then ValueSome ValueType.Int64\n            elif i.Code = OpCodes.Conv_U8 then ValueSome ValueType.UInt64\n            elif i.Code = OpCodes.Conv_R4 then ValueSome ValueType.Float32\n            elif i.Code = OpCodes.Conv_R8 then ValueSome ValueType.Float64\n            elif i.Code = OpCodes.Conv_I then ValueSome ValueType.NativeInt\n            elif i.Code = OpCodes.Conv_U then ValueSome ValueType.UNativeInt\n            elif i.Code = OpCodes.Conv_R_Un then ValueSome ValueType.Float32\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|ConvChecked|_|) (i : RawInstruction) =\n            if i.Code =   OpCodes.Conv_Ovf_I1 then ValueSome ValueType.Int8\n            elif i.Code = OpCodes.Conv_Ovf_U1 then ValueSome ValueType.UInt8\n            elif i.Code = OpCodes.Conv_Ovf_I2 then ValueSome ValueType.Int16\n            elif i.Code = OpCodes.Conv_Ovf_U2 then ValueSome ValueType.UInt16\n            elif i.Code = OpCodes.Conv_Ovf_I4 then ValueSome ValueType.Int32\n            elif i.Code = OpCodes.Conv_Ovf_U4 then ValueSome ValueType.UInt32\n            elif i.Code = OpCodes.Conv_Ovf_I8 then ValueSome ValueType.Int64\n            elif i.Code = OpCodes.Conv_Ovf_U8 then ValueSome ValueType.UInt64\n            elif i.Code = OpCodes.Conv_Ovf_I then ValueSome ValueType.NativeInt\n            elif i.Code = OpCodes.Conv_Ovf_U then ValueSome ValueType.UNativeInt\n\n            \n            elif i.Code = OpCodes.Conv_Ovf_I1_Un then ValueSome ValueType.Int8\n            elif i.Code = OpCodes.Conv_Ovf_U1_Un then ValueSome ValueType.UInt8\n            elif i.Code = OpCodes.Conv_Ovf_I2_Un then ValueSome ValueType.Int16\n            elif i.Code = OpCodes.Conv_Ovf_U2_Un then ValueSome ValueType.UInt16\n            elif i.Code = OpCodes.Conv_Ovf_I4_Un then ValueSome ValueType.Int32\n            elif i.Code = OpCodes.Conv_Ovf_U4_Un then ValueSome ValueType.UInt32\n            elif i.Code = OpCodes.Conv_Ovf_I8_Un then ValueSome ValueType.Int64\n            elif i.Code = OpCodes.Conv_Ovf_U8_Un then ValueSome ValueType.UInt64\n            elif i.Code = OpCodes.Conv_Ovf_I_Un then ValueSome ValueType.NativeInt\n            elif i.Code = OpCodes.Conv_Ovf_U_Un then ValueSome ValueType.UNativeInt\n\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|RefAnyVal|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Refanyval then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|CkFinite|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ckfinite then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|MkRefAny|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Mkrefany then ValueSome (unbox<Type> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|LdNull|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldnull then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|LdConst|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldc_I4 then i.Operand |> unbox |> Int32 |> ValueSome\n            elif i.Code = OpCodes.Ldc_I4_S then i.Operand |> unbox<int8> |> int |> Int32 |> ValueSome\n            elif i.Code = OpCodes.Ldc_I8 then i.Operand |> unbox |> Int64 |> ValueSome\n            elif i.Code = OpCodes.Ldc_R4 then i.Operand |> unbox |> Float32 |> ValueSome\n            elif i.Code = OpCodes.Ldc_R8 then i.Operand |> unbox |> Float64 |> ValueSome\n\n            elif i.Code = OpCodes.Ldc_I4_0 then ValueSome (Int32 0)\n            elif i.Code = OpCodes.Ldc_I4_1 then ValueSome (Int32 1)\n            elif i.Code = OpCodes.Ldc_I4_2 then ValueSome (Int32 2)\n            elif i.Code = OpCodes.Ldc_I4_3 then ValueSome (Int32 3)\n            elif i.Code = OpCodes.Ldc_I4_4 then ValueSome (Int32 4)\n            elif i.Code = OpCodes.Ldc_I4_5 then ValueSome (Int32 5)\n            elif i.Code = OpCodes.Ldc_I4_6 then ValueSome (Int32 6)\n            elif i.Code = OpCodes.Ldc_I4_7 then ValueSome (Int32 7)\n            elif i.Code = OpCodes.Ldc_I4_8 then ValueSome (Int32 8)\n            elif i.Code = OpCodes.Ldc_I4_M1 then ValueSome (Int32 -1)\n\n            elif i.Code = OpCodes.Ldstr then i.Operand |> unbox<string> |> String |> ValueSome\n\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|LdToken|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ldtoken then ValueSome (i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|ReadOnly|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Readonly then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Tail|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Tailcall then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|ConditionalJump|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Blt || i.Code = OpCodes.Blt_S || i.Code = OpCodes.Blt_Un || i.Code = OpCodes.Blt_Un_S then\n                ValueSome (Less, unbox<int> i.Operand)\n\n            elif i.Code = OpCodes.Ble || i.Code = OpCodes.Ble_S || i.Code = OpCodes.Ble_Un || i.Code = OpCodes.Ble_Un_S then\n                ValueSome (LessOrEqual, unbox<int> i.Operand)\n\n            elif i.Code = OpCodes.Bgt || i.Code = OpCodes.Bgt_S || i.Code = OpCodes.Bgt_Un || i.Code = OpCodes.Bgt_Un_S then\n                ValueSome (Greater, unbox<int> i.Operand)\n\n            elif i.Code = OpCodes.Bge || i.Code = OpCodes.Bge_S || i.Code = OpCodes.Bge_Un || i.Code = OpCodes.Bge_Un_S then\n                ValueSome (GreaterOrEqual, unbox<int> i.Operand)\n\n            elif i.Code = OpCodes.Beq || i.Code = OpCodes.Beq_S then\n                ValueSome (Equal, unbox<int> i.Operand)\n\n            elif i.Code = OpCodes.Bne_Un || i.Code = OpCodes.Bne_Un_S then\n                ValueSome (NotEqual, unbox<int> i.Operand)\n\n            elif i.Code = OpCodes.Brfalse || i.Code = OpCodes.Brfalse_S then\n                ValueSome (False, unbox<int> i.Operand)\n\n            elif i.Code = OpCodes.Brtrue || i.Code = OpCodes.Brtrue_S then\n                ValueSome (True, unbox<int> i.Operand)\n            else\n                ValueNone\n\n        [<return: Struct>]\n        let inline (|Jump|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Br || i.Code = OpCodes.Br_S then\n                ValueSome (unbox<int> i.Operand)\n            else\n                ValueNone\n\n        [<return: Struct>]\n        let inline (|Call|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Call || i.Code = OpCodes.Callvirt then\n                ValueSome (unbox<MethodBase> i.Operand)\n            else\n                ValueNone\n\n        [<return: Struct>]\n        let inline (|CallIndirect|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Calli then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Ret|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Ret then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Switch|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Switch then\n                ValueSome (unbox<int[]> i.Operand)\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Throw|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Throw then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|EndFinally|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Endfinally then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Leave|_|) (i : RawInstruction) =\n            if i.Code = OpCodes.Leave then ValueSome (unbox<int> i.Operand)\n            else ValueNone\n\n\n    let read (m : MethodBase) =\n        let body = m.GetMethodBody()\n\n        if body = null then failwith \"could not get method body\"\n\n        let locals =\n            body.LocalVariables \n                |> Seq.map (fun l -> l.LocalIndex, Local(l.LocalType))\n                |> Map.ofSeq\n\n        let isInstance = not m.IsStatic\n\n        let parameters =\n            let off = if isInstance then 1 else 0\n            m.GetParameters()\n                |> Seq.map (fun p -> off + p.Position, Parameter(p.Name, p.ParameterType))\n                |> Map.ofSeq\n\n        let parameters =\n            if isInstance then Map.add 0 (This m.DeclaringType) parameters\n            else parameters\n\n        let ctx =\n            {\n                TypeArgs = if m.DeclaringType.IsGenericType then m.DeclaringType.GetGenericArguments() else [||]\n                MethodArgs = if m.IsGenericMethod then m.GetGenericArguments() else [||]\n                Module = m.Module\n            }\n\n        use binary = new BinaryReader(new MemoryStream(body.GetILAsByteArray()))\n\n        let all = System.Collections.Generic.List<int * RawInstruction>()\n        while binary.BaseStream.Position < binary.BaseStream.Length do\n            let offset = binary.BaseStream.Position |> int\n            let i = binary.ReadRawInstruction(ctx)\n            all.Add (offset, i)\n\n\n        parameters, locals, all.ToArray()\n\n    let disassemble (m : MethodBase) =\n        let parameter, locals, instructions = read m\n\n        let currentId = ref 0\n\n        let branchTargetIds =\n            instructions \n                |> Seq.collect (fun (_,i) ->\n                    if i.Code.OperandType = OperandType.InlineBrTarget || i.Code.OperandType = OperandType.ShortInlineBrTarget then \n                        [unbox<int> i.Operand] :> seq<_>\n                    elif i.Code.OperandType = OperandType.InlineSwitch then\n                        unbox<int[]> i.Operand :> seq<_>\n                    else \n                        Seq.empty\n                   )\n                |> Set.ofSeq\n                |> Seq.map (fun i -> i, Label())\n                |> Map.ofSeq\n\n        let body =\n            seq {\n                for (off, i) in instructions do\n                    match Map.tryFind off branchTargetIds with\n                        | Some l ->\n                            yield Mark l\n                        | _ ->\n                            ()\n\n                    match i with\n                        | Patterns.Nop              -> yield Nop\n                        | Patterns.Break            -> yield Break\n                        | Patterns.Dup              -> yield Dup\n                        | Patterns.Pop              -> yield Pop\n\n                        | Patterns.Ldarg index      -> yield Ldarg index\n                        | Patterns.Ldarga index     -> yield LdargA index\n                        | Patterns.Starg index      -> yield Starg index\n\n                        | Patterns.Ldloc index      -> yield Ldloc locals.[index]\n                        | Patterns.LdlocA index     -> yield LdlocA locals.[index]\n                        | Patterns.Stloc index      -> yield Stloc locals.[index]\n\n                        | Patterns.Ldfld f          -> yield Ldfld f\n                        | Patterns.LdfldA f         -> yield LdfldA f\n                        | Patterns.Stfld f          -> yield Stfld f\n\n                        | Patterns.LdIndirect t     -> yield LdIndirect t\n                        | Patterns.StIndirect t     -> yield StIndirect t\n\n                        | Patterns.CpObj t          -> yield CpObj t\n                        | Patterns.LdObj t          -> yield LdObj t\n                        | Patterns.StObj t          -> yield StObj t\n\n                        | Patterns.NewObj c         -> yield NewObj c\n                        | Patterns.InitObj t        -> yield InitObj t\n                        | Patterns.CastClass t      -> yield CastClass t\n                        | Patterns.IsInstance t     -> yield IsInstance t\n                        \n                        | Patterns.Unbox t          -> yield Unbox t\n                        | Patterns.UnboxAny t       -> yield UnboxAny t\n                        | Patterns.Box t            -> yield Box t\n\n                        | Patterns.NewArr t         -> yield NewArr t\n                        | Patterns.Ldlen            -> yield Ldlen\n                        | Patterns.Ldelem t         -> yield Ldelem t\n                        | Patterns.LdelemA t        -> yield LdelemA t\n                        | Patterns.Stelem t         -> yield Stelem t\n\n                        | Patterns.Add              -> yield Add\n                        | Patterns.Sub              -> yield Sub\n                        | Patterns.Mul              -> yield Mul\n                        | Patterns.Div              -> yield Div\n                        | Patterns.Rem              -> yield Rem\n                        | Patterns.And              -> yield And\n                        | Patterns.Or               -> yield Or\n                        | Patterns.Xor              -> yield Xor\n                        | Patterns.Shl              -> yield Shl\n                        | Patterns.Shr              -> yield Shr\n\n                        | Patterns.Neg              -> yield Neg\n                        | Patterns.Not              -> yield Not\n\n                        | Patterns.Conv t           -> yield Conv t\n                        | Patterns.ConvChecked t    -> yield ConvChecked t\n\n                        | Patterns.RefAnyVal t      -> yield RefAnyVal t\n                        | Patterns.CkFinite         -> yield CkFinite\n                        | Patterns.MkRefAny t       -> yield MkRefAny t\n                        | Patterns.LdNull           -> yield LdNull\n\n                        | Patterns.LdConst c        -> yield LdConst c\n                        | Patterns.LdToken t        -> yield LdToken t\n\n                        | Patterns.ReadOnly         -> yield ReadOnly\n                        | Patterns.Tail             -> yield Tail\n\n                        | Patterns.Jump target      -> yield Jump(branchTargetIds.[target])\n            \n                        | Patterns.Call mi          -> yield Call mi\n                        | Patterns.CallIndirect     -> yield CallIndirect\n                        | Patterns.Ret              -> yield Ret\n\n                        | Patterns.Throw            -> yield Throw\n                        | Patterns.EndFinally       -> yield EndFinally\n                        | Patterns.Leave t          -> yield Leave(branchTargetIds.[t])\n\n                        | Patterns.Switch targets ->\n                            yield Switch(targets |> Array.map (fun t -> branchTargetIds.[t]))\n\n                        | Patterns.ConditionalJump(condition, target) ->\n                            yield ConditionalJump(condition, branchTargetIds.[target])\n\n                        | _ ->\n                            failwithf \"unknown instruction: %A\" i\n            }\n            \n        let body = Start :: (Seq.toList body)\n\n        let returnType =\n            match m with\n                | :? MethodInfo as mi -> mi.ReturnType\n                | :? ConstructorInfo -> typeof<System.Void>\n                | _ -> failwithf \"unknown method type: %A\" m\n\n\n        let arguments = m.GetParameters() |> Array.map (fun p -> p.ParameterType)\n            \n        let arguments = \n            if m.IsStatic then arguments\n            else Array.append [|m.DeclaringType|] arguments\n\n        {\n            ArgumentTypes = arguments\n            ReturnType = returnType\n            Body = body\n        }\n\nmodule Assembler =\n    open StateMonad\n\n    type State =\n        {\n            generator   : ILGenerator\n            labels      : Map<Label, System.Reflection.Emit.Label>\n            locals      : Map<Local, LocalBuilder>\n            stack       : list<Type>\n        }\n\n    [<AutoOpen>]\n    module private Helpers =\n        open Microsoft.FSharp.Reflection\n        open StateMonad\n\n\n        let (|ValueType|_|) (t : Type) =\n            if t = typeof<obj> then Some ValueType.Object\n            elif t = typeof<int8> then Some ValueType.Int8\n            elif t = typeof<uint8> then Some ValueType.UInt8\n            elif t = typeof<int16> then Some ValueType.Int16\n            elif t = typeof<uint16> then Some ValueType.UInt16\n            elif t = typeof<int32> then Some ValueType.Int32\n            elif t = typeof<uint32> then Some ValueType.UInt32\n            elif t = typeof<int64> then Some ValueType.Int64\n            elif t = typeof<uint64> then Some ValueType.UInt64\n            elif t = typeof<nativeint> then Some ValueType.NativeInt\n            elif t = typeof<unativeint> then Some ValueType.UNativeInt\n            elif t = typeof<float32> then Some ValueType.Float64\n            elif t = typeof<float> then Some ValueType.Float64\n            else None\n\n        let (|Type|) (t : ValueType) =\n            match t with\n                | ValueType.Int8 -> typeof<int8>\n                | ValueType.UInt8 -> typeof<uint8>\n                | ValueType.Int16 -> typeof<int16>\n                | ValueType.UInt16 -> typeof<uint16>\n                | ValueType.Int32 -> typeof<int32>\n                | ValueType.UInt32 -> typeof<uint32>\n                | ValueType.Int64 -> typeof<int64>\n                | ValueType.UInt64 -> typeof<uint64>\n                | ValueType.NativeInt -> typeof<nativeint>\n                | ValueType.UNativeInt -> typeof<unativeint>\n                | ValueType.Float32 -> typeof<float32>\n                | ValueType.Float64 -> typeof<float>\n                | _ -> typeof<obj>\n\n        type Asm<'a> = State<State, 'a>\n\n        type Asm() =\n\n            static member Push (t : Type) : Asm<unit> =\n                fun s -> { s with stack = t::s.stack }, ()\n\n            static member Push (Type t) : Asm<unit> =\n                fun s ->  { s with stack = t::s.stack }, ()\n\n\n            static member Pop : Asm<Type> =\n                fun s -> \n                    match s.stack with\n                        | t::stack -> { s with stack = stack }, t\n                        | _ -> s, typeof<obj>\n\n            static member Peek : Asm<Type> =\n                fun s -> \n                    match s.stack with\n                        | t::_ -> s, t\n                        | _ -> s, typeof<obj>\n\n\n            static member PopN (n : int) : Asm<list<Type>> =\n                fun s -> \n                    let rec pop (n : int) (s : list<Type>) =\n                        if n <= 0 then [], s\n                        else\n                            match s with\n                                | h::t ->\n                                    let args, rest = pop (n - 1) t\n                                    (h::args), rest\n                                | _ ->  \n                                    let args = List.init n (fun _ -> typeof<obj>)\n                                    args, []\n                \n                    let res, stack = pop n s.stack\n                    { s with stack = stack }, res\n\n            static member fail fmt =\n                failwithf fmt\n\n            static member GetLocal (l : Local) : Asm<LocalBuilder> =\n                fun s ->\n                    match Map.tryFind l s.locals with\n                        | Some l -> s,l\n                        | None ->\n                            let res = s.generator.DeclareLocal(l.Type)\n                            let s = { s with locals = Map.add l res s.locals }\n                            s, res\n\n            static member GetLabel (l : Label) : Asm<System.Reflection.Emit.Label> =\n                fun s ->\n                    match Map.tryFind l s.labels with\n                        | Some l -> s,l\n                        | None ->\n                            let res = s.generator.DefineLabel()\n                            let s = { s with labels = Map.add l res s.labels }\n                            s, res\n\n            static member Mark(l : Label) =\n                state {\n                    let! l = Asm.GetLabel l\n                    do! (fun s -> s, s.generator.MarkLabel(l))\n                }\n            static member Emit(c : OpCode) : Asm<unit> =\n                fun s -> s, s.generator.Emit(c)\n\n            static member WriteLine (str : string) : Asm<unit> =\n                fun s -> s, s.generator.EmitWriteLine str\n\n            static member Emit(c : OpCode, arg : obj) : Asm<unit> =\n                fun s -> \n                    match arg with\n                        | null                      -> s.generator.Emit(c)\n                        | :? uint8 as o             -> s.generator.Emit(c, o)\n                        | :? float as o             -> s.generator.Emit(c, o)\n                        | :? int16 as o             -> s.generator.Emit(c, o)\n                        | :? int as o               -> s.generator.Emit(c, o)\n                        | :? int64 as o             -> s.generator.Emit(c, o)\n                        | :? ConstructorInfo as o   -> s.generator.Emit(c, o)\n                        | :? FieldInfo as o         -> s.generator.Emit(c, o)\n                        | :? MethodInfo as o        -> s.generator.Emit(c, o)\n                        | :? int8 as o              -> s.generator.Emit(c, o)\n                        | :? float32 as o           -> s.generator.Emit(c, o)\n                        | :? string as o            -> s.generator.Emit(c, o)\n                        | :? Type as o              -> s.generator.Emit(c, o)\n                        | :? SignatureHelper as o   -> s.generator.Emit(c, o)\n                        | :? Emit.Label as o        -> s.generator.Emit(c, o)\n                        | :? array<Emit.Label> as o -> s.generator.Emit(c, o)\n                        | :? LocalBuilder as o      -> s.generator.Emit(c, o)\n                        | operand ->\n                            failwithf \"[IL] unsupported operand: %A\" operand\n            \n                    s, ()\n\n    let private assembleInstruction (i : Instruction) =\n        state {\n            match i with\n                | Start -> ()\n                | Nop -> do! Asm.Emit(OpCodes.Nop)\n                | Break -> do! Asm.Emit(OpCodes.Break)\n                | Dup   -> \n                    let! t = Asm.Peek\n                    do! Asm.Push t\n                    do! Asm.Emit(OpCodes.Dup)\n                | Pop   -> \n                    let! _ = Asm.Pop\n                    do! Asm.Emit(OpCodes.Pop)\n\n                | WriteLine str ->\n                    do! Asm.WriteLine str\n\n                | Ldarg a ->\n                    match a with\n                        | 0 -> do! Asm.Emit(OpCodes.Ldarg_0)\n                        | 1 -> do! Asm.Emit(OpCodes.Ldarg_1)\n                        | 2 -> do! Asm.Emit(OpCodes.Ldarg_2)\n                        | 3 -> do! Asm.Emit(OpCodes.Ldarg_3)\n                        | p when p < 256 -> do! Asm.Emit(OpCodes.Ldarg_S, uint8 p :> obj)\n                        | p -> do! Asm.Emit(OpCodes.Ldarg, p :> obj)\n\n                    //do! Asm.Push a.ArgumentType\n\n                | LdargA a ->\n                    if a > 255 then do! Asm.Emit(OpCodes.Ldarga, a :> obj)\n                    else do! Asm.Emit(OpCodes.Ldarga_S, uint8 a)\n\n                    //do! Asm.Push (a.ArgumentType.MakeByRefType())\n\n                | Starg a ->\n                    let! t = Asm.Pop\n\n                    if a > 255 then do! Asm.Emit(OpCodes.Starg, a :> obj)\n                    else do! Asm.Emit(OpCodes.Starg_S, uint8 a)\n\n\n                | Ldloc l ->\n                    let! l = Asm.GetLocal l\n                    do! Asm.Emit(OpCodes.Ldloc, l)\n                    do! Asm.Push l.LocalType\n\n                | LdlocA l ->\n                    let! l = Asm.GetLocal l\n                    do! Asm.Emit(OpCodes.Ldloca, l)\n                    do! Asm.Push (l.LocalType.MakeByRefType())\n\n                | Stloc l ->\n                    let! l = Asm.GetLocal l\n                    let! t = Asm.Pop\n                    do! Asm.Emit(OpCodes.Stloc, l)\n\n                | Ldfld f -> \n                    if f.IsStatic then do! Asm.Emit(OpCodes.Ldsfld, f)\n                    else do! Asm.Emit(OpCodes.Ldfld, f)\n                    do! Asm.Push f.FieldType\n\n                | LdfldA f ->\n                    if f.IsStatic then do! Asm.Emit(OpCodes.Ldsflda, f)\n                    else do! Asm.Emit(OpCodes.Ldflda, f)\n                    do! Asm.Push (f.FieldType.MakeByRefType())\n\n                | Stfld f ->\n                    let! t = Asm.Pop\n                    if f.IsStatic then do! Asm.Emit(OpCodes.Stsfld, f)\n                    else do! Asm.Emit(OpCodes.Stfld, f)\n\n                | LdIndirect t ->\n                    match t with\n                        | ValueType.Int8 -> do! Asm.Emit(OpCodes.Ldind_I1)\n                        | ValueType.UInt8 -> do! Asm.Emit(OpCodes.Ldind_U1)\n                        | ValueType.Int16 -> do! Asm.Emit(OpCodes.Ldind_I2)\n                        | ValueType.UInt16 -> do! Asm.Emit(OpCodes.Ldind_U2)\n                        | ValueType.Int32 -> do! Asm.Emit(OpCodes.Ldind_I4)\n                        | ValueType.UInt32 -> do! Asm.Emit(OpCodes.Ldind_U4)\n                        | ValueType.Int64 -> do! Asm.Emit(OpCodes.Ldind_I8)\n                        | ValueType.UInt64 -> do! Asm.fail \"cannot LdIndirect uint64\"\n                        | ValueType.NativeInt -> do! Asm.Emit(OpCodes.Ldind_I)\n                        | ValueType.UNativeInt -> do! Asm.fail \"cannot LdIndirect unativeint\"\n                        | ValueType.Float32 -> do! Asm.Emit(OpCodes.Ldind_R4)\n                        | ValueType.Float64 -> do! Asm.Emit(OpCodes.Ldind_R8)\n                        | _ -> do! Asm.Emit(OpCodes.Ldind_Ref)\n\n                    do! Asm.Push t\n\n                | StIndirect t ->\n                    let! vt = Asm.Pop\n\n                    match t with\n                        | ValueType.Int8 -> do! Asm.Emit(OpCodes.Stind_I1)\n                        | ValueType.UInt8 -> do! Asm.Emit(OpCodes.Stind_I1)\n                        | ValueType.Int16 -> do! Asm.Emit(OpCodes.Stind_I2)\n                        | ValueType.UInt16 -> do! Asm.Emit(OpCodes.Stind_I2)\n                        | ValueType.Int32 -> do! Asm.Emit(OpCodes.Stind_I4)\n                        | ValueType.UInt32 -> do! Asm.Emit(OpCodes.Stind_I4)\n                        | ValueType.Int64 -> do! Asm.Emit(OpCodes.Stind_I8)\n                        | ValueType.UInt64 -> do! Asm.Emit(OpCodes.Stind_I8)\n                        | ValueType.NativeInt -> do! Asm.Emit(OpCodes.Stind_I)\n                        | ValueType.UNativeInt -> do! Asm.Emit(OpCodes.Stind_I)\n                        | ValueType.Float32 -> do! Asm.Emit(OpCodes.Stind_R4)\n                        | ValueType.Float64 -> do! Asm.Emit(OpCodes.Stind_R8)\n                        | _ -> do! Asm.Emit(OpCodes.Stind_Ref)\n\n                | CpObj t ->        \n                    do! Asm.Emit(OpCodes.Cpobj, t) \n                    do! Asm.Push t\n                | LdObj t ->        \n                    do! Asm.Emit(OpCodes.Ldobj, t)\n                    do! Asm.Push t\n                | StObj t ->        \n                    let! rt = Asm.Pop\n                    do! Asm.Emit(OpCodes.Stobj, t)\n\n                | NewObj c ->       \n                    let! args = Asm.PopN (c.GetParameters().Length)\n                    do! Asm.Emit(OpCodes.Newobj, c)\n                    do! Asm.Push c.DeclaringType\n\n                | InitObj t ->\n                    do! Asm.Emit(OpCodes.Initobj, t)\n\n                | CastClass t ->    \n                    let! tr = Asm.Pop\n                    do! Asm.Emit(OpCodes.Castclass, t)\n                    do! Asm.Push t\n\n                | IsInstance t ->   \n                    let! tr = Asm.Pop\n                    do! Asm.Emit(OpCodes.Isinst, t)\n                    do! Asm.Push t\n\n                | Unbox t ->        \n                    let! ot = Asm.Pop\n                    do! Asm.Emit(OpCodes.Unbox, t)\n                    do! Asm.Push t\n\n                | UnboxAny t ->     \n                    let! _ = Asm.Pop\n                    do! Asm.Emit(OpCodes.Unbox_Any, t)\n                    do! Asm.Push t\n\n                | Box t ->          \n                    let! tr = Asm.Pop\n                    do! Asm.Emit(OpCodes.Box, t)\n                    do! Asm.Push typeof<obj>\n\n                | NewArr t ->       \n                    let! tl = Asm.Pop\n                    do! Asm.Emit(OpCodes.Newarr, t)\n                    do! Asm.Push (t.MakeArrayType())\n\n                | Ldlen ->          \n                    let! tarr = Asm.Pop\n                    do! Asm.Emit(OpCodes.Ldlen)\n                    do! Asm.Push typeof<int>\n\n                // Stack maintained up to this point\n\n\n                | Ldelem t ->\n                    match t with\n                        | ValueType vt ->\n                            match vt with\n                                | ValueType.Int8 -> do! Asm.Emit(OpCodes.Ldelem_I1)\n                                | ValueType.UInt8 -> do! Asm.Emit(OpCodes.Ldelem_U1)\n                                | ValueType.Int16 -> do! Asm.Emit(OpCodes.Ldelem_I2)\n                                | ValueType.UInt16 -> do! Asm.Emit(OpCodes.Ldelem_U2)\n                                | ValueType.Int32 -> do! Asm.Emit(OpCodes.Ldelem_I4)\n                                | ValueType.UInt32 -> do! Asm.Emit(OpCodes.Ldelem_U4)\n                                | ValueType.Int64 -> do! Asm.Emit(OpCodes.Ldelem_I8)\n                                | ValueType.UInt64 -> do! Asm.fail \"cannot load uint64 array element\"\n                                | ValueType.NativeInt -> do! Asm.Emit(OpCodes.Ldelem_I)\n                                | ValueType.UNativeInt -> do! Asm.fail \"cannot load unativeint array element\"\n                                | ValueType.Float32 -> do! Asm.Emit(OpCodes.Ldelem_R4)\n                                | ValueType.Float64 -> do! Asm.Emit(OpCodes.Ldelem_R8)\n                                | _ -> do! Asm.Emit(OpCodes.Ldelem_Ref)\n\n                        | t -> \n                            do! Asm.Emit(OpCodes.Ldelem, t)\n\n                | LdelemA t ->\n                    do! Asm.Emit(OpCodes.Ldelema, t)\n\n                | Stelem t ->\n                    match t with\n                        | ValueType vt ->\n                            match vt with\n                                | ValueType.Int8 -> do! Asm.Emit(OpCodes.Stelem_I1)\n                                | ValueType.UInt8 -> do! Asm.Emit(OpCodes.Stelem_I1)\n                                | ValueType.Int16 -> do! Asm.Emit(OpCodes.Stelem_I2)\n                                | ValueType.UInt16 -> do! Asm.Emit(OpCodes.Stelem_I2)\n                                | ValueType.Int32 -> do! Asm.Emit(OpCodes.Stelem_I4)\n                                | ValueType.UInt32 -> do! Asm.Emit(OpCodes.Stelem_I4)\n                                | ValueType.Int64 -> do! Asm.Emit(OpCodes.Stelem_I8)\n                                | ValueType.UInt64 -> do! Asm.Emit(OpCodes.Stelem_I8)\n                                | ValueType.NativeInt -> do! Asm.Emit(OpCodes.Stelem_I)\n                                | ValueType.UNativeInt -> do! Asm.Emit(OpCodes.Stelem_I)\n                                | ValueType.Float32 -> do! Asm.Emit(OpCodes.Stelem_R4)\n                                | ValueType.Float64 -> do! Asm.Emit(OpCodes.Stelem_R8)\n                                | _ -> do! Asm.Emit(OpCodes.Stelem_Ref)\n\n                        | t -> \n                            do! Asm.Emit(OpCodes.Stelem, t)\n\n\n                | Add -> do! Asm.Emit(OpCodes.Add)\n                | Sub -> do! Asm.Emit(OpCodes.Sub)\n                | Mul -> do! Asm.Emit(OpCodes.Mul)\n                | Div -> do! Asm.Emit(OpCodes.Div)\n                | Rem -> do! Asm.Emit(OpCodes.Rem)\n                | And -> do! Asm.Emit(OpCodes.And)\n                | Or ->  do! Asm.Emit(OpCodes.Or)\n                | Xor -> do! Asm.Emit(OpCodes.Xor)\n                | Shl -> do! Asm.Emit(OpCodes.Shl)\n                | Shr -> do! Asm.Emit(OpCodes.Shr)\n                | Neg -> do! Asm.Emit(OpCodes.Neg)\n                | Not -> do! Asm.Emit(OpCodes.Not)\n\n\n                | Conv t ->\n                    match t with\n                        | ValueType.Int8 -> do! Asm.Emit(OpCodes.Conv_Ovf_I1)\n                        | ValueType.UInt8 -> do! Asm.Emit(OpCodes.Conv_Ovf_U1)\n                        | ValueType.Int16 -> do! Asm.Emit(OpCodes.Conv_Ovf_I2)\n                        | ValueType.UInt16 -> do! Asm.Emit(OpCodes.Conv_Ovf_U2)\n                        | ValueType.Int32 -> do! Asm.Emit(OpCodes.Conv_Ovf_I4)\n                        | ValueType.UInt32 -> do! Asm.Emit(OpCodes.Conv_Ovf_U4)\n                        | ValueType.Int64 -> do! Asm.Emit(OpCodes.Conv_Ovf_I8)\n                        | ValueType.UInt64 -> do! Asm.Emit(OpCodes.Conv_Ovf_U8)\n                        | ValueType.NativeInt -> do! Asm.Emit(OpCodes.Conv_Ovf_I)\n                        | ValueType.UNativeInt -> do! Asm.Emit(OpCodes.Conv_Ovf_U)\n                        | ValueType.Float32 -> do! Asm.Emit(OpCodes.Conv_R4)\n                        | ValueType.Float64 -> do! Asm.Emit(OpCodes.Conv_R8)\n                        | _ -> do! Asm.fail \"cannot convert to obj\"\n\n                | ConvChecked t ->\n                    match t with\n                        | ValueType.Int8 -> do! Asm.Emit(OpCodes.Conv_Ovf_I1)\n                        | ValueType.UInt8 -> do! Asm.Emit(OpCodes.Conv_Ovf_U1)\n                        | ValueType.Int16 -> do! Asm.Emit(OpCodes.Conv_Ovf_I2)\n                        | ValueType.UInt16 -> do! Asm.Emit(OpCodes.Conv_Ovf_U2)\n                        | ValueType.Int32 -> do! Asm.Emit(OpCodes.Conv_Ovf_I4)\n                        | ValueType.UInt32 -> do! Asm.Emit(OpCodes.Conv_Ovf_U4)\n                        | ValueType.Int64 -> do! Asm.Emit(OpCodes.Conv_Ovf_I8)\n                        | ValueType.UInt64 -> do! Asm.Emit(OpCodes.Conv_Ovf_U8)\n                        | ValueType.NativeInt -> do! Asm.Emit(OpCodes.Conv_Ovf_I)\n                        | ValueType.UNativeInt -> do! Asm.Emit(OpCodes.Conv_Ovf_U)\n                        | ValueType.Float32 -> do! Asm.Emit(OpCodes.Conv_R4)\n                        | ValueType.Float64 -> do! Asm.Emit(OpCodes.Conv_R8)\n                        | _ -> do! Asm.fail \"cannot convert to obj\"\n\n                | LdNull -> do! Asm.Emit(OpCodes.Ldnull)\n\n                | LdConst c ->\n                    match c with\n                        | Int8 i -> \n                            do! Asm.Emit(OpCodes.Ldc_I4, int i)\n                            do! Asm.Emit(OpCodes.Conv_I1)\n\n                        | UInt8 i ->\n                            do! Asm.Emit(OpCodes.Ldc_I4, int i)\n                            do! Asm.Emit(OpCodes.Conv_U1)\n\n                        \n                        | Int16 i -> \n                            do! Asm.Emit(OpCodes.Ldc_I4, int i)\n                            do! Asm.Emit(OpCodes.Conv_I2)\n\n                        | UInt16 i ->\n                            do! Asm.Emit(OpCodes.Ldc_I4, int i)\n                            do! Asm.Emit(OpCodes.Conv_U2)\n                        \n                        | Int32 i -> do! Asm.Emit(OpCodes.Ldc_I4, int i)\n                        | UInt32 i -> do! Asm.Emit(OpCodes.Ldc_I4, int i)\n                        | Int64 i -> do! Asm.Emit(OpCodes.Ldc_I8, i)\n                        | UInt64 i -> do! Asm.Emit(OpCodes.Ldc_I8, i)\n                        | Float32 f -> do! Asm.Emit(OpCodes.Ldc_R4, f)\n                        | Float64 f -> do! Asm.Emit(OpCodes.Ldc_R8, f)\n\n                        | NativeInt i -> \n                            do! Asm.Emit(OpCodes.Ldc_I8, int64 i)\n                            do! Asm.Emit(OpCodes.Conv_I)\n                        | UNativeInt i -> \n                            do! Asm.Emit(OpCodes.Ldc_I8, int64 i)\n                            do! Asm.Emit(OpCodes.Conv_I)\n\n                        | String str ->\n                            do! Asm.Emit(OpCodes.Ldstr, str)\n\n                | LdToken t ->\n                    do! Asm.Emit(OpCodes.Ldtoken, t)\n\n                | ReadOnly -> do! Asm.Emit(OpCodes.Readonly)\n                | Tail -> do! Asm.Emit(OpCodes.Tailcall)\n\n                | Mark l -> do! Asm.Mark l\n                | ConditionalJump(c, l) ->\n                    let! l = Asm.GetLabel l\n\n                    match c with\n                        | Less -> do! Asm.Emit(OpCodes.Blt, l)\n                        | LessOrEqual -> do! Asm.Emit(OpCodes.Ble, l)\n                        | Greater -> do! Asm.Emit(OpCodes.Bgt, l)\n                        | GreaterOrEqual -> do! Asm.Emit(OpCodes.Bge, l)\n                        | Equal -> do! Asm.Emit(OpCodes.Beq, l)\n                        | NotEqual -> do! Asm.Emit(OpCodes.Bne_Un, l)\n                        | True -> do! Asm.Emit(OpCodes.Brtrue, l)\n                        | False -> do! Asm.Emit(OpCodes.Brfalse, l)\n\n                | Jump l ->\n                    let! l = Asm.GetLabel l\n                    do! Asm.Emit(OpCodes.Br, l)\n\n                | Call mi ->\n                    if mi.IsVirtual then do! Asm.Emit(OpCodes.Callvirt, mi)\n                    else do! Asm.Emit(OpCodes.Call, mi)\n\n                | CallIndirect ->\n                    do! Asm.Emit(OpCodes.Calli)\n\n                | Ret ->\n                    do! Asm.Emit(OpCodes.Ret)\n\n                | Switch labels ->\n                    let arr = Array.zeroCreate labels.Length\n                    for i in 0..labels.Length-1 do\n                        let! l = Asm.GetLabel(labels.[i])\n                        arr.[i] <- l\n\n                    do! Asm.Emit(OpCodes.Switch, arr)\n\n                | Throw -> do! Asm.Emit(OpCodes.Throw)\n                | EndFinally -> do! Asm.Emit(OpCodes.Endfinally)\n                | Leave l -> \n                    let! l = Asm.GetLabel l\n                    do! Asm.Emit(OpCodes.Leave, l)\n                | CkFinite -> do! Asm.Emit(OpCodes.Ckfinite)\n                | MkRefAny t -> do! Asm.Emit(OpCodes.Mkrefany, t)\n                | RefAnyVal t -> do! Asm.Emit(OpCodes.Refanyval, t)\n\n     \n        }\n\n    let private assembleBody (m : seq<Instruction>) =\n        state {\n            for i in m do \n                do! assembleInstruction i\n        }\n\n    let assembleTo (il : ILGenerator) (m : seq<Instruction>) =\n        assembleBody m {\n            generator   = il\n            labels      = Map.empty\n            locals      = Map.empty\n            stack       = []\n        } |> ignore\n\n    let assembleTo' (state : State) (m : seq<Instruction>) =\n        assembleBody m state |> ignore\n\n    let assembleDelegateInternal (tdel : Type) (m : list<Instruction>) : Delegate =\n        let invoke = tdel.GetMethod(\"Invoke\")\n        let args = invoke.GetParameters() |> Array.map (fun p -> p.ParameterType)\n\n        let owner =\n            if args.Length > 0 then \n                let a0 = args.[0] \n                if a0.IsInterface then typeof<obj>\n                else a0\n            else \n                typeof<obj>\n\n        let meth = \n            DynamicMethod(\n                Guid.NewGuid() |> string,\n                invoke.ReturnType, args,\n                owner,\n                true\n            )\n\n        let state =\n            {\n                generator   = meth.GetILGenerator()\n                labels      = Map.empty\n                locals      = Map.empty\n                stack       = []\n            }\n\n        let endState,_ = assembleBody m state\n        meth.CreateDelegate(tdel)\n\n    let assembleDelegate  (m : MethodDefinition) : Delegate =\n        let delegateType = \n            if m.ReturnType = typeof<System.Void> then\n                if m.ArgumentTypes.Length = 0 then\n                    typeof<Action>\n                else\n                    let funcType = typedefof<Action<_>>.FullName.Replace(\"1\", string (m.ArgumentTypes.Length)) |> Type.GetType\n                    let funcType = funcType.MakeGenericType m.ArgumentTypes\n\n                    funcType\n            else\n                let funcType = typedefof<Func<_>>.FullName.Replace(\"1\", string (m.ArgumentTypes.Length + 1)) |> Type.GetType\n                let funcType = funcType.MakeGenericType (Array.append m.ArgumentTypes [|m.ReturnType|])\n\n                funcType\n\n        assembleDelegateInternal delegateType m.Body\n   \n    let assembleDefinition (m : MethodDefinition) : 'a =\n        let d = assembleDelegate m\n        DelegateAdapters.wrap d\n\n    let assemble (body : seq<Instruction>) : 'a =\n        let args, ret = DelegateAdapters.getFunctionSignature typeof<'a>\n\n        assembleDefinition {\n            ArgumentTypes = List.toArray args\n            ReturnType = if ret = typeof<unit> then typeof<System.Void> else ret\n            Body = Seq.toList body\n        }\n\n[<AutoOpen>]\nmodule Frontend =\n    open StateMonad\n\n    type ConcList<'a> =\n        private\n        | Empty\n        | List of list<'a>\n        | Single of 'a\n        | Concat of list<ConcList<'a>>\n\n    module ConcList =\n        let empty = Empty\n        let single v = Single v\n        \n        let ofList l = \n            match l with\n                | [] -> Empty\n                | l -> List l\n\n        let ofSeq (s : #seq<'a>) : ConcList<'a> = \n            match s :> seq<'a> with\n                | :? list<'a> as l -> List l\n                | _ -> s |> Seq.toList |> List\n\n        let ofArray a = a |> Array.toList |> List\n\n        let rec toSeq (c : ConcList<'a>) =\n            let res = System.Collections.Generic.List<'a>()\n\n            let rec recurse (c : ConcList<'a>) =\n                match c with\n                    | Empty -> ()\n                    | Single v -> res.Add v\n                    | List l -> res.AddRange l\n                    | Concat ls ->\n                        for l in ls do recurse l\n\n            recurse c\n            res :> seq<_>\n\n        let rec toList (c : ConcList<'a>) =\n            let l = toSeq c |> unbox<System.Collections.Generic.List<'a>>\n            l |> CSharpList.toList\n\n        let rec toArray (c : ConcList<'a>) =\n            let l = toSeq c |> unbox<System.Collections.Generic.List<'a>>\n            l.ToArray()\n\n        let append (l : ConcList<'a>) (r : ConcList<'a>) =\n            match l, r with\n                | Empty, r -> r\n                | l, Empty -> l\n                | l, r -> Concat [l;r]\n\n        let concat (l : #seq<ConcList<'a>>) =\n            let l = l |> Seq.toList\n            Concat l\n\n        let cons (a : 'a) (l : ConcList<'a>) =\n            Concat [Single a; l]\n\n        let snoc (l : ConcList<'a>) (a : 'a) =\n            Concat [l; Single a]\n\n    type CodeGenState = \n        {\n            instructions : ConcList<Instruction>\n        }\n\n    type CodeGen<'a> = State<CodeGenState, 'a>\n\n\n    type CodeGen =\n        static member concat (l : list<CodeGen<unit>>) =\n            fun s -> \n                let mutable c = s\n                for e in l do \n                    let (s,()) = e c\n                    c <- s\n                c, ()\n\n        static member run(c : CodeGen<unit>) =\n            let (s,()) = c { instructions = ConcList.empty }\n            s.instructions |> ConcList.toList\n\n        static member emit (i : ConcList<Instruction>) : CodeGen<unit> =\n            fun s -> { s with instructions = ConcList.append s.instructions i }, ()\n\n        static member emit (i : Instruction) : CodeGen<unit> =\n            fun s -> { s with instructions = ConcList.snoc s.instructions i }, ()\n\n        static member emit (i : #seq<Instruction>) : CodeGen<unit> =\n            fun s -> { s with instructions = ConcList.append s.instructions (ConcList.ofSeq i) }, ()\n           \n    type CodeGenBuilder() =\n        \n        member x.Bind(i : Instruction, f : unit -> CodeGen<'b>) = \n            state.Bind(CodeGen.emit (ConcList.single i), f)\n\n        member x.Bind(i : #seq<Instruction>, f : unit -> CodeGen<'b>) = \n            state.Bind(CodeGen.emit (ConcList.ofSeq i), f)\n\n\n        member x.Bind(m : CodeGen<'a>, f : 'a -> CodeGen<'b>) = state.Bind(m,f)\n        member x.Return (v : 'a) : CodeGen<'a> = state.Return v\n        member x.ReturnFrom (c : CodeGen<'a>) = state.ReturnFrom c\n        member x.Zero() : CodeGen<unit> = state.Zero()\n        member x.Delay(f : unit -> CodeGen<'a>) = state.Delay f\n        member x.Combine(l : CodeGen<unit>, r : CodeGen<'a>) = state.Combine(l,r)\n        member x.For(elements : seq<'a>, f : 'a -> CodeGen<unit>) = state.For(elements, f)\n        member x.While(guard, body : CodeGen<unit>) = state.While(guard, body)\n\n    type ExecutableBuilder() =\n        inherit CodeGenBuilder()\n\n        member x.Run(c : CodeGen<unit>) =\n            let code = c |> CodeGen.run\n            Assembler.assemble code\n\n    let codegen = CodeGenBuilder()\n\n    let cil = ExecutableBuilder()\n\n    [<AutoOpen>]\n    module private Helpers =\n\n        let rec tryGetMethodInfo (e : Expr) =\n            match e with\n                | Patterns.Call(_,mi,_) -> Some mi\n                | ExprShape.ShapeCombination(_, args) -> \n                    args |> List.tryPick tryGetMethodInfo\n                | ExprShape.ShapeLambda(_,b) ->\n                    tryGetMethodInfo b\n                | _ -> None\n\n        let getMethodInfo (e : Expr) =\n            match tryGetMethodInfo e with\n                | Some mi -> mi\n                | None -> failwithf \"[IL] could not get MethodInfo from: %A\" e\n   \n   \n        let rec tryGetFieldInfo (e : Expr) =\n            match e with\n                | FieldGet(_,fi) -> Some fi\n                | ExprShape.ShapeCombination(_, args) -> \n                    args |> List.tryPick tryGetFieldInfo\n                | ExprShape.ShapeLambda(_,b) ->\n                    tryGetFieldInfo b\n                | _ -> None\n\n        let getFieldInfo (e : Expr) =\n            match tryGetFieldInfo e with\n                | Some fi -> fi\n                | None -> failwithf \"[IL] could not get FieldInfo from: %A\" e\n  \n   \n        let rec tryGetConstructorInfo (e : Expr) =\n            match e with    \n                | NewObject(ctor,_) -> Some ctor\n                | ExprShape.ShapeCombination(_, args) -> \n                    args |> List.tryPick tryGetConstructorInfo\n                | ExprShape.ShapeLambda(_,b) ->\n                    tryGetConstructorInfo b\n                | _ -> None\n\n        let getConstructorInfo (e : Expr) =\n            match tryGetConstructorInfo e with\n                | Some fi -> fi\n                | None -> failwithf \"[IL] could not get ConstructorInfo from: %A\" e\n  \n   \n    type IL private() =\n        static let stringFormat = typeof<String>.GetMethod(\"Format\", [| typeof<string>; typeof<obj[]> |])\n        static let printString = typeof<Console>.GetMethod(\"WriteLine\", [| typeof<string>; typeof<obj[]> |])\n\n        /// nop\n        static member nop = Nop |> CodeGen.emit\n\n        // break\n        static member break_ = Break |> CodeGen.emit\n\n        /// duplicates the top-most value on the stack\n        static member dup = Dup |> CodeGen.emit\n\n        /// pops the top-most value from the stack\n        static member pop = Pop |> CodeGen.emit\n\n\n        /// loads the argument with the given index onto the stack\n        static member ldarg (i : int) = i |> Ldarg |> CodeGen.emit\n\n        /// loads the address of the argument with the given index onto the stack\n        static member ldarga (i : int) = i |> LdargA |> CodeGen.emit\n\n        /// stores the top-most value in the argument with the given index\n        static member starg (i : int) = i |> Starg |> CodeGen.emit\n\n\n        /// loads the local variable onto the stack\n        static member ldloc (l : Local) = l |> Ldloc |> CodeGen.emit\n\n        /// load the address of the local variable onto the stack\n        static member ldloca (l : Local) = l |> LdlocA |> CodeGen.emit\n\n        /// stores the top-most value in the local variable\n        static member stloc (l : Local) = l |> Stloc |> CodeGen.emit\n\n\n        /// loads the value of the field onto the stack\n        static member ldfld (f : FieldInfo) = \n            if isNull f then failwith \"[IL] cannot load null field\"\n            f |> Ldfld |> CodeGen.emit\n\n        /// loads the address of the field onto the stack\n        static member ldflda (f : FieldInfo) = \n            if isNull f then failwith \"[IL] cannot load null field\"\n            f |> LdfldA |> CodeGen.emit\n\n        /// stores the top-most value in the field\n        static member stfld (f : FieldInfo) = \n            if isNull f then failwith \"[IL] cannot store null field\"\n            f |> Stfld |> CodeGen.emit\n\n        /// loads the value of the field onto the stack\n        static member ldfld (e : Expr) = e |> getFieldInfo |> IL.ldfld\n\n        /// loads the address of the field onto the stack\n        static member ldflda (e : Expr) = e |> getFieldInfo |> IL.ldflda\n\n        /// stores the top-most value in the field\n        static member stfld (e : Expr) = e |> getFieldInfo |> IL.stfld\n\n        /// stores the top-most value in a ref on the stack\n        static member stind (t : ValueType) = t |> StIndirect |> CodeGen.emit\n\n        /// loads the value from a ref on the stack\n        static member ldind (t : ValueType) = t |> LdIndirect |> CodeGen.emit\n\n        /// TODO\n        static member cpobj (t : Type) = t |> CpObj |> CodeGen.emit\n\n        /// loads the object (with the given type) from the pointer currently on the stack\n        static member ldobj (t : Type) = t |> LdObj |> CodeGen.emit\n\n        /// stores the top-most value (with the given type) in a ptr on the stack\n        static member stobj (t : Type) = t |> LdObj |> CodeGen.emit\n\n        /// creates a new object by calling the given Constructor\n        static member newobj (ctor : ConstructorInfo) = ctor |> NewObj |> CodeGen.emit\n\n        /// creates a new uninitialized object\n        static member initobj (t : Type) = t |> InitObj |> CodeGen.emit\n\n        /// creates a new object by calling the given Constructor\n        static member newobj (e : Expr) = e |> getConstructorInfo |> IL.newobj\n\n        /// casts the top-most value to the given class\n        static member castclass (t : Type) = t |> CastClass |> CodeGen.emit\n\n        /// checks if the top-most value is an instance of the given type\n        static member isinst (t : Type) = t |> IsInstance |> CodeGen.emit\n\n\n        /// unboxes the top-most value (with the given type) to its unboxed representation\n        static member unbox (t : Type) = t |> Unbox |> CodeGen.emit\n\n        /// unboxes the top-most value to the given type\n        static member unboxAny (t : Type) = t |> UnboxAny |> CodeGen.emit\n\n        /// boxes the top-most value (with the given type) to an object\n        static member box (t : Type) = t |> Box |> CodeGen.emit\n\n\n        /// creates a new array using the given element-type and the length on the stack\n        static member newarr (t : Type) = t |> NewArr |> CodeGen.emit\n\n        /// loads the length of the array currently on the stack\n        static member ldlen = Ldlen |> CodeGen.emit\n\n        /// loads an element (with the given type) from the array on the stack\n        static member ldelem (t : Type) = t |> Ldelem |> CodeGen.emit\n\n        /// stores the element (with the given type) to the array on the stack\n        static member stelem (t : Type) = t |> Ldelem |> CodeGen.emit\n\n\n        static member add = Add |> CodeGen.emit\n        static member sub = Sub |> CodeGen.emit\n        static member mul = Mul |> CodeGen.emit\n        static member div = Div |> CodeGen.emit\n        static member rem = Rem |> CodeGen.emit\n        static member bitand = And |> CodeGen.emit\n        static member bitor = Or |> CodeGen.emit\n        static member bifxor = Xor |> CodeGen.emit\n        static member neg = Neg |> CodeGen.emit\n        static member not = Not |> CodeGen.emit\n\n\n        /// converts the top-most value to the given type\n        static member conv (t : ValueType) = t |> Conv |> CodeGen.emit\n\n        /// converts the top-most value to the given type (checked)\n        static member convChecked (t : ValueType) = t |> ConvChecked |> CodeGen.emit\n\n        /// loads null onto the stack\n        static member ldnull = LdNull |> CodeGen.emit\n\n        /// loads the given Constant onto the stack\n        static member ldconst(c : Constant) = LdConst c |> CodeGen.emit\n\n        /// loads the given int8 constant onto the stack\n        static member ldconst(i : int8) = LdConst(Int8 i) |> CodeGen.emit\n\n        /// loads the given uint8 constant onto the stack\n        static member ldconst(i : uint8) = LdConst(UInt8 i) |> CodeGen.emit\n\n        /// loads the given int16 constant onto the stack\n        static member ldconst(i : int16) = LdConst(Int16 i) |> CodeGen.emit\n\n        /// loads the given uint16 constant onto the stack\n        static member ldconst(i : uint16) = LdConst(UInt16 i) |> CodeGen.emit\n\n        /// loads the given int constant onto the stack\n        static member ldconst(i : int32) = LdConst(Int32 i) |> CodeGen.emit\n\n        /// loads the given uint32 constant onto the stack\n        static member ldconst(i : uint32) = LdConst(UInt32 i) |> CodeGen.emit\n\n        /// loads the given int64 constant onto the stack\n        static member ldconst(i : int64) = LdConst(Int64 i) |> CodeGen.emit\n\n        /// loads the given uint64 constant onto the stack\n        static member ldconst(i : uint64) = LdConst(UInt64 i) |> CodeGen.emit\n\n        /// loads the given nativeint constant onto the stack\n        static member ldconst(i : nativeint) = LdConst(NativeInt i) |> CodeGen.emit\n\n        /// loads the given unativeint constant onto the stack\n        static member ldconst(i : unativeint) = LdConst(UNativeInt i) |> CodeGen.emit\n\n        /// loads the given float constant onto the stack\n        static member ldconst(i : float32) = LdConst(Float32 i) |> CodeGen.emit\n\n        /// loads the given double constant onto the stack\n        static member ldconst(i : float) = LdConst(Float64 i) |> CodeGen.emit\n\n        /// loads the given string constant onto the stack\n        static member ldconst(i : string) = LdConst(String i) |> CodeGen.emit\n\n\n        /// load the given object as token onto the stack\n        static member ldtoken (t : obj) = LdToken(t) |> CodeGen.emit\n\n        /// load the given type-token onto the stack\n        static member ldtoken (t : Type) = LdToken(t) |> CodeGen.emit\n\n        /// tells the JITer that the following call is a tail-call\n        static member tail = Tail |> CodeGen.emit\n\n        /// marks the current location using the given label\n        static member mark l = l |> Mark |> CodeGen.emit\n\n        /// conditionally jumps to a label\n        static member jmp (c : JumpCondition) = \n            fun l -> ConditionalJump(c, l) |> CodeGen.emit\n\n        /// jumps to a label\n        static member jmp (l : Label) = Jump(l) |> CodeGen.emit\n\n        /// calls the given MethodInfo\n        static member call (e : Expr) = \n            e |> getMethodInfo :> MethodBase |> Call |> CodeGen.emit\n\n        /// calls the given MethodInfo\n        static member call (mi : MethodBase) =\n            mi |> Call |> CodeGen.emit\n            \n        /// returns from the current function\n        static member ret = Ret |> CodeGen.emit\n\n        /// prints a log-line using the given local values\n        static member println (format : string, [<ParamArray>] args : obj[]) =\n            let v = Local(typeof<string>)\n            let arr = Local(typeof<obj[]>)\n            codegen {\n                do! LdConst (Int32 args.Length)\n                do! NewArr typeof<obj>\n                do! Stloc arr\n\n                for i in 0..args.Length-1 do\n                    do! Ldloc arr\n                    do! LdConst (Int32 i)\n                    \n                    match args.[i] with\n                        | :? Local as a ->\n    \n                            do! Ldloc a\n                            if a.Type.IsValueType then \n                                do! Box a.Type\n                            else\n                                do! UnboxAny typeof<obj>\n                        | a ->\n                            do! LdConst (String (sprintf \"%A\" a))\n                            do! UnboxAny typeof<obj>\n\n                \n                    do! Stelem typeof<obj>\n\n                do! LdConst (String format)\n                do! Ldloc arr\n                do! Call printString\n            }\n\n        /// prints a log-line using the given local values\n        static member printfn (fmt : StringFormat<'a, CodeGen<unit>>) : 'a =\n            kformatf (fun fmt -> IL.println(fmt.Format, fmt.Args)) fmt\n\n        static member newlabel : CodeGen<Label> = fun s -> s, Label()\n        static member newlocal (t : Type) : CodeGen<Local> = fun s -> s, Local(t)\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module ILLog =\n\n        let private lineM = typeof<Report>.GetMethod(\"Line\", [| typeof<string>; typeof<obj[]> |])\n        let private startM = typeof<Report>.GetMethod(\"Begin\", [| typeof<string>; typeof<obj[]> |])\n        let private startTimedM = typeof<Report>.GetMethod(\"BeginTimed\", [| typeof<string>; typeof<obj[]> |])\n        let private stopM = typeof<Report>.GetMethod(\"End\", [| |])\n\n        /// prints a log-line using the given local values\n        let private print (meth : MethodInfo, format : string, [<ParamArray>] args : obj[]) =\n            let v = Local(typeof<string>)\n            let arr = Local(typeof<obj[]>)\n            codegen {\n                do! LdConst (Int32 args.Length)\n                do! NewArr typeof<obj>\n                do! Stloc arr\n\n                for i in 0..args.Length-1 do\n                    do! Ldloc arr\n                    do! LdConst (Int32 i)\n                    \n                    match args.[i] with\n                        | :? Local as a ->\n    \n                            do! Ldloc a\n                            if a.Type.IsValueType then \n                                do! Box a.Type\n                            else\n                                do! UnboxAny typeof<obj>\n                        | a ->\n                            do! LdConst (String (string a))\n\n                \n                    do! Stelem typeof<obj>\n\n                do! LdConst (String format)\n                do! Ldloc arr\n                do! Call meth\n\n                if meth.ReturnType <> typeof<System.Void> then\n                    do! IL.pop\n\n            }\n\n\n        /// prints a log-line using the given local values\n        let line (fmt : StringFormat<'a, CodeGen<unit>>) : 'a =\n            kformatf (fun fmt -> print(lineM, fmt.Format, fmt.Args)) fmt\n\n        /// prints a log-line using the given local values\n        let start (fmt : StringFormat<'a, CodeGen<unit>>) : 'a =\n            kformatf (fun fmt -> print(startM, fmt.Format, fmt.Args)) fmt\n\n        /// prints a log-line using the given local values\n        let startTimed (fmt : StringFormat<'a, CodeGen<unit>>) : 'a =\n            kformatf (fun fmt -> print(startTimedM, fmt.Format, fmt.Args)) fmt\n\n\n        /// prints a log-line using the given local values\n        let stop () : CodeGen<unit> =\n            codegen {\n                do! IL.call stopM\n                do! IL.pop\n            }\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module IL =\n        let substitute (f : Instruction -> CodeGen<unit>) (body : #seq<Instruction>) =\n            let body = Seq.toList body\n\n            let body = \n                match body with\n                    | Start::_ -> body\n                    | _ -> Start::body\n            \n            let code = codegen { for i in body do do! f i } |> CodeGen.run\n\n            match code with\n                | Start::_ -> code\n                | code -> Start::code\n\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module MethodDefinition =\n        let substitute (f : Instruction -> CodeGen<unit>) (d : MethodDefinition) =\n            { d with Body = IL.substitute f d.Body }\n        \n    \n\nmodule AssemblerTest =  \n    open System.Collections.Generic\n    type Type with\n        member x.GetInvokeMethod() =\n            x.GetMethods()\n                |> Array.filter (fun mi -> mi.Name = \"Invoke\")\n                |> Array.maxBy (fun mi -> mi.GetParameters().Length)\n\n    type TestMethods() =\n        static member Add(a : int, b : int) =\n            if a < 0 then b\n            else a + b\n\n    let listAdd() =\n        let l = System.Collections.Generic.List<int>()\n        let dis = Disassembler.disassemble (typeof<System.Collections.Generic.List<int>>.GetMethod(\"Add\", [| typeof<int> |]))\n        \n        let mutable i = 0\n        for instruction in dis.Body do\n            printfn \"%d: %A\" i instruction\n            i <- i + 1\n\n        let ass : System.Collections.Generic.List<int> -> int -> unit = \n            Assembler.assemble dis.Body\n\n        \n        ass l 2\n        ass l 3\n        printfn \"%A\" (Seq.toList l)\n\n    let testCustom() =\n        let custom : int -> int -> int =\n            cil {\n                let! bad = IL.newlabel\n                let! a0 = IL.newlocal typeof<int>\n                let! a1 = IL.newlocal typeof<int>\n\n                do! IL.ldarg 0\n                do! IL.stloc a0\n                do! IL.ldarg 1\n                do! IL.stloc a1\n\n                do! IL.ldloc a0\n                do! IL.ldloc a1\n                do! IL.jmp LessOrEqual bad\n       \n                do! IL.ldloc a0\n                do! IL.ldloc a1\n                do! IL.add\n                do! IL.call <@ Fun.NextPowerOfTwo : int -> int @>\n                do! IL.ret\n        \n                do! IL.mark bad\n                do! IL.printfn \"{ a = %A; b = %A }\" a0 a1\n                do! IL.ldconst 0\n                do! IL.ret\n            }\n\n\n        Log.line \"custom 1 2 = %A\" (custom 1 2)\n        Log.line \"custom 2 1 = %A\" (custom 2 1)\n\n    let testLambda() =\n        \n        let f = fun (a : WeakReference<obj>) -> isNull a\n\n        let invoke = f.GetType().GetInvokeMethod()\n        let def = Disassembler.disassemble invoke\n\n        for i in def.Body do\n            Log.line \"%A\" i\n\n        ()\n\n\n    let testInject() =\n        let l = List<int>()\n        let dis = Disassembler.disassemble (typeof<List<int>>.GetMethod(\"Add\", [| typeof<int> |]))\n\n        let ass : List<int> -> int -> unit =\n            cil {\n                for i in dis.Body do\n                    match i with\n                        | Start ->\n                            let! l = IL.newlocal typeof<int>\n                            do! IL.ldarg 1\n                            do! IL.stloc l\n                            do! ILLog.start \"add %A\" l\n\n                        | Ret -> \n                            do! ILLog.stop()\n                            do! IL.ret\n\n                        | Stfld f ->\n                            let! l = IL.newlocal f.FieldType\n                            do! IL.stloc l\n                            do! IL.ldloc l\n                            do! IL.stfld f\n                            do! ILLog.line \"%s <- %A\" f.Name l\n\n                        | Ldlen ->\n                            let! l = IL.newlocal typeof<int>\n                            do! IL.ldlen\n                            do! IL.stloc l\n                            do! ILLog.line \"length = %A\" l\n                            do! IL.ldloc l\n                        \n//                        | Ldfld f ->\n//                            let! l = IL.newlocal f.FieldType\n//                            do! IL.ldfld f\n//                            do! IL.stloc l\n//                            do! ILLog.line \"%s = %A\" f.Name l\n//                            do! IL.ldloc l\n\n\n                        | Call mi ->\n\n                            do! ILLog.start \"call %A\" mi.Name\n                            let parameters = mi.GetParameters()\n                            let locals = Array.zeroCreate parameters.Length\n                            let index = ref (parameters.Length - 1)\n                            for _ in 0..parameters.Length-1 do\n                                let p = parameters.[!index]\n                                let! l = IL.newlocal p.ParameterType\n                                do! IL.stloc l\n\n                                do! ILLog.line \"%s: %A\" p.Name l\n\n                                locals.[!index] <- l\n                                index := !index - 1 \n\n                            for l in locals do\n                                do! IL.ldloc l\n\n\n                            do! IL.call mi\n                            do! ILLog.stop()\n\n                        | i -> do! i\n            }\n\n\n        \n        ass l 2\n        ass l 3\n        ass l 4\n        ass l 5\n        ass l 6\n        ass l 7\n        Log.line \"%A\" (Seq.toList l)\n\n    let run() =\n        testInject()\n        //testLambda()\n        // let a : StringFormat = formatf \"sepp: %A hugo: %f\" 1 1.0\n        // a.Format = \"sepp: {0} hugo: {1}\"\n        // a.Args = [| 1 :> obj; 1.0 :> obj |]\n\n\n        //testCustom()\n        //listAdd()\n        //testInject()\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/Multimethod.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Reflection\nopen System.Collections.Generic\nopen System.Runtime.InteropServices\nopen System.Threading\nopen Microsoft.FSharp.Reflection\nopen FSharp.Data.Adaptive\n\nmodule private Helpers =\n    \n    type State = { assignment : HashMap<Type, Type> }\n    type Result<'a> = { run : State -> Option<State * 'a> }\n\n    type ResultBuilder() =\n        member x.Bind(r : Result<'a>, f : 'a -> Result<'b>) =\n            { run = fun s ->\n                match r.run s with\n                    | Some (s, v) ->\n                        (f v).run s\n                    | None ->\n                        None\n            }\n\n        member x.Return(v : 'a) =\n            { run = fun s -> Some(s,v) }\n\n        member x.Zero() =\n            { run = fun s -> Some(s, ()) }\n\n        member x.Delay(f : unit -> Result<'a>) =\n            { run = fun s -> f().run s }\n\n        member x.Combine(l : Result<unit>, r : Result<'a>) =\n            { run = fun s ->\n                match l.run s with\n                    | Some(s,()) -> r.run s\n                    | None -> None\n            }\n\n        member x.For(seq : seq<'a>, f : 'a -> Result<unit>) =\n            { run = fun s -> \n                let e = seq.GetEnumerator()\n\n                let rec run(s) =\n                    if e.MoveNext() then\n                        match (f e.Current).run s with\n                            | Some(s,()) ->\n                                run s\n                            | None ->\n                                None\n                    else\n                        Some(s,())\n\n                let res = run s\n                e.Dispose()\n                res\n            }\n\n        member x.While(guard : unit -> bool, body : Result<unit>) =\n            { run = fun s ->\n                if guard() then\n                    match body.run s with\n                        | Some (s,()) -> x.While(guard, body).run s\n                        | None -> None\n                else\n                    Some(s,())\n            }\n\n    let result = ResultBuilder()\n\n    let assign (t : Type) (o : Type) =\n        { run = fun s ->\n            match HashMap.tryFind t s.assignment with\n                | Some(old) when old <> o ->\n                    None\n                | _ ->\n                    Some({ s with assignment = HashMap.add t o s.assignment }, ())\n        }\n\n    let fail<'a> : Result<'a> = { run = fun s -> None }\n\n    let success = { run = fun s -> Some(s, ()) }\n\n    let rec tryInstantiateType (argType : Type) (realType : Type) =\n        result {\n            let genArg = if argType.IsGenericType then argType.GetGenericTypeDefinition() else argType\n\n            if argType = realType then\n                do! success\n            elif argType.IsAssignableFrom realType then\n                do! success\n\n            elif argType.IsGenericParameter then\n                do! assign argType realType\n\n            elif argType.ContainsGenericParameters && realType.IsGenericType && realType.GetGenericTypeDefinition() = genArg then\n                let argArgs = argType.GetGenericArguments()\n                let realGen = realType.GetGenericTypeDefinition()\n                let realArgs = realType.GetGenericArguments()\n\n                for i in 0..realArgs.Length-1 do\n                    let r = realArgs.[i]\n                    let a = argArgs.[i]\n                    do! tryInstantiateType a r\n\n            elif argType.IsInterface then\n                let iface = \n                    realType.GetInterfaces()\n                        |> Array.tryFind (fun iface -> \n                            let gen = if iface.IsGenericType then iface.GetGenericTypeDefinition() else iface\n                            gen = genArg\n                        )\n\n                match iface with\n                    | Some iface ->\n                        if iface.IsGenericType then\n                            let ifaceArgs = iface.GetGenericArguments()\n                            let argArgs = argType.GetGenericArguments()\n                            for i in 0..ifaceArgs.Length - 1 do\n                                do! tryInstantiateType argArgs.[i] ifaceArgs.[i]\n                        else\n                            ()\n                    | None ->\n                        do! fail\n\n            else\n                let baseType = realType.BaseType\n                if isNull baseType then do! fail\n                else do! tryInstantiateType argType baseType\n        }\n\n    let tryInstantiateMethodInfo (mi : MethodInfo) (real : Type[]) =\n        result {\n            let p = mi.GetParameters()\n            if p.Length = real.Length then\n                for i in 0..p.Length-1 do\n                    do! tryInstantiateType (p.[i].ParameterType) real.[i]\n            else\n                do! fail\n        }\n            \n\n    let tryInstantiate (mi : MethodInfo) (args : Type[]) =\n        let parameters = mi.GetParameters()\n        if parameters.Length = args.Length then\n            if mi.IsGenericMethod then\n                let mi = mi.GetGenericMethodDefinition()\n                let m = tryInstantiateMethodInfo mi args\n                match m.run { assignment = HashMap.empty } with\n                    | Some (s,()) ->\n                        let args = mi.GetGenericArguments() |> Array.map (fun a -> HashMap.find a s.assignment)\n                        mi.MakeGenericMethod(args) |> Some\n\n                    | None -> \n                        None\n            else\n                let works = Array.forall2 (fun (p : ParameterInfo) a -> p.ParameterType.IsAssignableFrom a) parameters args\n                if works then Some mi\n                else None\n        else\n            None\n\ntype IRuntimeMethod =\n    abstract member Invoke : obj[] -> obj\n\n\n\nmodule RuntimeMethodBuilder =\n    open System.Reflection.Emit\n    \n    \n    let internal bAss = AssemblyBuilder.DefineDynamicAssembly(AssemblyName(\"IRuntimeMethods\"), AssemblyBuilderAccess.Run)\n    let internal bMod = bAss.DefineDynamicModule(\"MainModule\")\n\n    exception UnknownException of Type[]\n    exception UnsupportedTypesException of Type[]\n\n    \n    type MultimethodImpl(argCount : int, f : Type[] -> Option<obj * MethodInfo>) =\n        let all = List<Type[] * obj * MethodInfo>()\n        let current = ref unbox\n        let mutable callCount = 0\n        let mutable init = true\n\n        let buildMatch(x : MultimethodImpl) =\n            let funType = typeof<FSharpFunc<obj[], obj>>\n            let bType = bMod.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class ||| TypeAttributes.Public, funType)\n            let bMeth = bType.DefineMethod(\"Invoke\", MethodAttributes.Public ||| MethodAttributes.Virtual, typeof<obj>, [|typeof<obj[]>|])\n            let il = bMeth.GetILGenerator()\n\n            let bTargets = bType.DefineField(\"targets\", typeof<obj[]>, FieldAttributes.Private)\n            let bSelf = bType.DefineField(\"parent\", typeof<MultimethodImpl>, FieldAttributes.Private)\n\n            let args = Array.init argCount (fun _ -> il.DeclareLocal(typeof<obj>))\n            let typeVars = Array.init argCount (fun i -> if sizeof<nativeint> = 8 then il.DeclareLocal(typeof<int64>) else il.DeclareLocal(typeof<int>))\n            let arr = il.DeclareLocal(typeof<Type[]>)\n\n            for i in 0..argCount-1 do\n                // load the args into args.[i]\n                il.Emit(OpCodes.Ldarg_1)\n                il.Emit(OpCodes.Ldc_I4, i)\n                il.Emit(OpCodes.Ldelem, typeof<obj>)\n                il.Emit(OpCodes.Stloc, args.[i])\n\n                // read the object's type-pointer\n                il.Emit(OpCodes.Ldloc, args.[i])\n                if sizeof<nativeint> = 8 then il.Emit(OpCodes.Ldobj, typeof<int64>)\n                else il.Emit(OpCodes.Ldobj, typeof<int>)\n                il.Emit(OpCodes.Stloc, typeVars.[i])\n\n            for ai in 0..all.Count-1 do\n                let (t, target, meth) = all.[ai]\n                let paramters = meth.GetParameters()\n\n                let fLabel = il.DefineLabel()\n\n                // check all type-ids\n                for i in 0..argCount-1 do\n                    let ti = t.[i]\n                    il.Emit(OpCodes.Ldloc, typeVars.[i])\n                    if sizeof<nativeint> = 8 then il.Emit(OpCodes.Ldc_I8, int64 ti.TypeHandle.Value)\n                    else il.Emit(OpCodes.Ldc_I4, int ti.TypeHandle.Value)\n                    il.Emit(OpCodes.Bne_Un_S, fLabel)\n\n                // load the target (if any)\n                if not meth.IsStatic then\n                    il.Emit(OpCodes.Ldarg_0)\n                    il.Emit(OpCodes.Ldfld, bTargets)\n                    il.Emit(OpCodes.Ldc_I4, ai)\n                    il.Emit(OpCodes.Ldelem_Ref)\n\n                        \n                // load and unbox the arguments\n                for i in 0..argCount-1 do\n                    let at = paramters.[i].ParameterType\n                    il.Emit(OpCodes.Ldloc, args.[i])\n\n                    // strange version of a cast\n                    let tmp = il.DeclareLocal(at)\n                    il.Emit(OpCodes.Stloc, tmp)\n                    il.Emit(OpCodes.Ldloc, tmp)\n\n\n                // finally call the method\n                if meth.ReturnType = typeof<obj> then\n                    il.Emit(OpCodes.Tailcall)\n                    il.EmitCall(OpCodes.Call, meth, null)\n                    il.Emit(OpCodes.Ret)\n                else\n                    il.EmitCall(OpCodes.Call, meth, null)\n                    if meth.ReturnType = typeof<System.Void> then\n                        il.Emit(OpCodes.Ldnull)\n                    elif meth.ReturnType.IsValueType then\n                        il.Emit(OpCodes.Box, meth.ReturnType)\n                    else\n                        let tmp = il.DeclareLocal(typeof<obj>)\n                        il.Emit(OpCodes.Stloc, tmp)\n                        il.Emit(OpCodes.Ldloc, tmp)\n\n                    il.Emit(OpCodes.Ret)\n\n                il.MarkLabel(fLabel)\n\n\n            il.Emit(OpCodes.Ldc_I4, argCount)\n            il.Emit(OpCodes.Newarr, typeof<Type>)\n            il.Emit(OpCodes.Stloc, arr)\n\n            for i in 0..argCount-1 do\n                il.Emit(OpCodes.Ldloc, arr)\n                il.Emit(OpCodes.Ldc_I4, i)\n\n                il.Emit(OpCodes.Ldloc, args.[i])\n                il.EmitCall(OpCodes.Callvirt, typeof<obj>.GetMethod \"GetType\", null)\n\n                il.Emit(OpCodes.Stelem_Ref)\n\n            \n            let rebuild = typeof<MultimethodImpl>.GetMethod(\"Rebuild\", BindingFlags.NonPublic ||| BindingFlags.Instance ||| BindingFlags.Public)\n            let invoke = typeof<MultimethodImpl>.GetMethod(\"Invoke\")\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldfld, bSelf)\n            il.Emit(OpCodes.Dup)\n            il.Emit(OpCodes.Ldloc, arr)\n            \n            il.EmitCall(OpCodes.Call, rebuild, null)\n           \n            il.Emit(OpCodes.Ldarg_1)\n            il.Emit(OpCodes.Tailcall)\n            il.EmitCall(OpCodes.Call, invoke, null)\n            il.Emit(OpCodes.Ret)\n                \n\n\n            let bCtor = bType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, [|typeof<obj[]>; typeof<MultimethodImpl>|])\n            let il = bCtor.GetILGenerator()\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Call, typeof<obj>.GetConstructor [||])\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldarg_1)\n            il.Emit(OpCodes.Stfld, bTargets)\n\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldarg_2)\n            il.Emit(OpCodes.Stfld, bSelf)\n\n            il.Emit(OpCodes.Ret)\n\n            bType.AddInterfaceImplementation(typeof<IRuntimeMethod>)\n            bType.DefineMethodOverride(bMeth, typeof<IRuntimeMethod>.GetMethod \"Invoke\")\n            bType.DefineMethodOverride(bMeth, funType.GetMethod \"Invoke\")\n\n            let t = bType.CreateTypeInfo()\n\n            let ctor = t.GetConstructor [|typeof<obj[]>; typeof<MultimethodImpl>|]\n            let targets = all |> Seq.map (fun (_,t,_) -> t) |> Seq.toArray\n            ctor.Invoke([|targets :> obj; x :> obj|]) |> unbox<obj[] -> obj>\n\n        let buildTable(x : MultimethodImpl) =\n            if argCount <> 1 then\n                failwith \"jump table only works with one argument atm.\"\n\n            let funType = typeof<FSharpFunc<obj[], obj>>\n            let bType = bMod.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class ||| TypeAttributes.Public, funType)\n            let bMeth = bType.DefineMethod(\"Invoke\", MethodAttributes.Public ||| MethodAttributes.Virtual, typeof<obj>, [|typeof<obj[]>|])\n            let il = bMeth.GetILGenerator()\n\n            let bTargets = bType.DefineField(\"targets\", typeof<obj[]>, FieldAttributes.Private)\n            let bSelf = bType.DefineField(\"parent\", typeof<MultimethodImpl>, FieldAttributes.Private)\n\n            let args = Array.init argCount (fun _ -> il.DeclareLocal(typeof<obj>))\n            let typeVars = Array.init argCount (fun i -> if sizeof<nativeint> = 8 then il.DeclareLocal(typeof<int64>) else il.DeclareLocal(typeof<int>))\n            let arr = il.DeclareLocal(typeof<Type[]>)\n\n            for i in 0..argCount-1 do\n                // load the args into args.[i]\n                il.Emit(OpCodes.Ldarg_1)\n                il.Emit(OpCodes.Ldc_I4, i)\n                il.Emit(OpCodes.Ldelem, typeof<obj>)\n                il.Emit(OpCodes.Stloc, args.[i])\n\n                // read the object's type-pointer\n                il.Emit(OpCodes.Ldloc, args.[i])\n                if sizeof<nativeint> = 8 then il.Emit(OpCodes.Ldobj, typeof<int64>)\n                else il.Emit(OpCodes.Ldobj, typeof<int>)\n                il.Emit(OpCodes.Stloc, typeVars.[i])\n\n            \n            let minId = all |> Seq.map (fun (t,_,_) -> t.[0].TypeHandle.Value) |> Seq.min\n\n            let rec createTable (size : int) =\n                let table = Array.zeroCreate size\n                let mutable success = true\n                \n                for (t,tar,meth) in all do\n                    let e = int (t.[0].TypeHandle.Value - minId) % table.Length\n                    match table.[e] with\n                        | None -> \n                            table.[e] <- Some (t, tar, meth)\n                        | _ ->\n                            success <- false\n\n                if success then\n                    table\n                else\n                    createTable (size + 1)\n\n            let table = createTable all.Count\n\n            let notFound = il.DefineLabel()\n            let labels = \n                table |> Array.map (fun f ->\n                    il.DefineLabel()\n                )\n\n            il.Emit(OpCodes.Ldloc, typeVars.[0])\n            if sizeof<nativeint> = 8 then il.Emit(OpCodes.Ldc_I8, int64 minId)\n            else il.Emit(OpCodes.Ldc_I4, int minId)\n            il.Emit(OpCodes.Sub)\n\n            if sizeof<nativeint> = 8 then il.Emit(OpCodes.Ldc_I8, int64 labels.Length)\n            else il.Emit(OpCodes.Ldc_I4, int64 labels.Length)\n            il.Emit(OpCodes.Rem)\n            il.Emit(OpCodes.Conv_I4)\n\n            il.Emit(OpCodes.Switch, labels)\n            il.Emit(OpCodes.Br, notFound)\n\n            for ai in 0..table.Length-1 do\n                match table.[ai] with\n                    | Some (t, target, meth) -> \n                        let paramters = meth.GetParameters()\n\n                        il.MarkLabel(labels.[ai])\n\n                        // check all type-ids\n                        for i in 0..argCount-1 do\n                            let ti = t.[i]\n                            il.Emit(OpCodes.Ldloc, typeVars.[i])\n                            if sizeof<nativeint> = 8 then il.Emit(OpCodes.Ldc_I8, int64 ti.TypeHandle.Value)\n                            else il.Emit(OpCodes.Ldc_I4, int ti.TypeHandle.Value)\n                            il.Emit(OpCodes.Bne_Un, notFound)\n\n                        // load the target (if any)\n                        if not meth.IsStatic then\n                            il.Emit(OpCodes.Ldarg_0)\n                            il.Emit(OpCodes.Ldfld, bTargets)\n                            il.Emit(OpCodes.Ldc_I4, ai)\n                            il.Emit(OpCodes.Ldelem_Ref)\n\n                        \n                        // load and unbox the arguments\n                        for i in 0..argCount-1 do\n                            let at = paramters.[i].ParameterType\n                            il.Emit(OpCodes.Ldloc, args.[i])\n\n                            // strange version of a cast\n                            let tmp = il.DeclareLocal(at)\n                            il.Emit(OpCodes.Stloc, tmp)\n                            il.Emit(OpCodes.Ldloc, tmp)\n\n\n                        // finally call the method\n                        if meth.ReturnType = typeof<obj> then\n                            il.Emit(OpCodes.Tailcall)\n                            il.EmitCall(OpCodes.Call, meth, null)\n                            il.Emit(OpCodes.Ret)\n                        else\n                            il.EmitCall(OpCodes.Call, meth, null)\n                            if meth.ReturnType = typeof<System.Void> then\n                                il.Emit(OpCodes.Ldnull)\n                            elif meth.ReturnType.IsValueType then\n                                il.Emit(OpCodes.Box, meth.ReturnType)\n                            else\n                                let tmp = il.DeclareLocal(typeof<obj>)\n                                il.Emit(OpCodes.Stloc, tmp)\n                                il.Emit(OpCodes.Ldloc, tmp)\n\n                            il.Emit(OpCodes.Ret)\n                    | None ->\n                        il.MarkLabel(labels.[ai])\n                        il.Emit(OpCodes.Br, notFound)\n\n            il.MarkLabel(notFound)\n            il.Emit(OpCodes.Ldc_I4, argCount)\n            il.Emit(OpCodes.Newarr, typeof<Type>)\n            il.Emit(OpCodes.Stloc, arr)\n\n            for i in 0..argCount-1 do\n                il.Emit(OpCodes.Ldloc, arr)\n                il.Emit(OpCodes.Ldc_I4, i)\n\n                il.Emit(OpCodes.Ldloc, args.[i])\n                il.EmitCall(OpCodes.Callvirt, typeof<obj>.GetMethod \"GetType\", null)\n\n                il.Emit(OpCodes.Stelem_Ref)\n\n            \n            let rebuild = typeof<MultimethodImpl>.GetMethod(\"Rebuild\", BindingFlags.NonPublic ||| BindingFlags.Instance ||| BindingFlags.Public)\n            let invoke = typeof<MultimethodImpl>.GetMethod(\"Invoke\")\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldfld, bSelf)\n            il.Emit(OpCodes.Dup)\n            il.Emit(OpCodes.Ldloc, arr)\n            \n            il.EmitCall(OpCodes.Call, rebuild, null)\n           \n            il.Emit(OpCodes.Ldarg_1)\n            il.Emit(OpCodes.Tailcall)\n            il.EmitCall(OpCodes.Call, invoke, null)\n            il.Emit(OpCodes.Ret)\n                \n\n\n            let bCtor = bType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, [|typeof<obj[]>; typeof<MultimethodImpl>|])\n            let il = bCtor.GetILGenerator()\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Call, typeof<obj>.GetConstructor [||])\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldarg_1)\n            il.Emit(OpCodes.Stfld, bTargets)\n\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldarg_2)\n            il.Emit(OpCodes.Stfld, bSelf)\n\n            il.Emit(OpCodes.Ret)\n\n            bType.AddInterfaceImplementation(typeof<IRuntimeMethod>)\n            bType.DefineMethodOverride(bMeth, typeof<IRuntimeMethod>.GetMethod \"Invoke\")\n            bType.DefineMethodOverride(bMeth, funType.GetMethod \"Invoke\")\n\n            let t = bType.CreateTypeInfo()\n\n            let ctor = t.GetConstructor [|typeof<obj[]>; typeof<MultimethodImpl>|]\n            let targets = all |> Seq.map (fun (_,t,_) -> t) |> Seq.toArray\n            ctor.Invoke([|targets :> obj; x :> obj|]) |> unbox<obj[] -> obj>\n\n\n        let rebuild (self : MultimethodImpl) (newArgTypes : Type[]) =\n            let meth = f newArgTypes\n            match meth with\n                | Some (target, meth) ->\n                    all.Add(newArgTypes, target, meth)\n                    if argCount < 0 then\n                        current := buildTable(self)\n                    else\n                        current := buildMatch(self)\n                | _ ->\n                    raise <| UnsupportedTypesException(newArgTypes)\n\n        member x.Init() =\n            current :=\n                fun args ->\n                    rebuild x (args |> Array.map (fun a -> a.GetType()))\n                    current.Value(args)\n\n        \n        member x.Rebuild(newArgTypes : Type[]) =\n            rebuild x newArgTypes\n\n        member x.Invoke(args : obj[]) =\n            current.Value args\n\n    let inlineCache (argCount : int) (f : Type[] -> Option<obj * MethodInfo>) =\n        let f = MultimethodImpl(argCount, f)\n        f.Init()\n        f\n\nexception MultimethodException              \ntype Multimethod(parameterCount : int, initial : seq<MethodInfo * obj>)  =\n    let implementations = Dictionary.ofSeq (initial)\n    let mutable initialized = false\n\n    static let instances = Dictionary<Type, obj>()\n\n    static let createInstance (t : Type) =\n        lock instances (fun () ->\n            match instances.TryGetValue t with\n                | (true, i) -> i\n                | _ ->\n                    let i = Activator.CreateInstance t\n                    instances.[t] <- i\n                    i\n        )\n\n    static let createTarget (mi : MethodInfo) =\n        if mi.IsStatic then null\n        else createInstance mi.DeclaringType\n\n    let tryGetMethodInfo(retType : Type) (types : Type[])=\n        let goodOnes = \n            implementations.Keys\n                |> Seq.choose (fun mi -> Helpers.tryInstantiate mi types)\n                |> Seq.filter (fun mi -> retType.IsAssignableFrom mi.ReturnType)\n                |> Seq.cast\n                |> Seq.toArray\n\n        if goodOnes.Length > 0 then\n            let selected =\n                if goodOnes.Length = 1 then goodOnes.[0] |> unbox<MethodInfo>\n                else \n                    Type.DefaultBinder.SelectMethod(\n                        BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.InvokeMethod,\n                        goodOnes,\n                        types,\n                        types |> Array.map (fun _ -> ParameterModifier())\n                    ) |> unbox<MethodInfo>\n                \n            if selected.IsGenericMethod then\n                Some (selected, implementations.[selected.GetGenericMethodDefinition()])\n            else\n                Some (selected, implementations.[selected])\n        else\n            None\n\n    let methodCache = \n        RuntimeMethodBuilder.inlineCache parameterCount (fun types -> \n            initialized <- true\n            match tryGetMethodInfo typeof<obj> types with\n                | Some(mi,target) -> Some(target, mi)\n                | _ -> None\n        )\n\n\n    static member GetTarget (mi : MethodInfo) = createTarget mi \n\n    member x.Add(mi : MethodInfo) =\n        if initialized then\n            failwith \"cannot modify Multimethod after first call\"\n\n        if mi.GetParameters().Length <> parameterCount then\n            failwithf \"cannot add %A to Multimethod due to parameter-count mismatch\" mi\n\n        if mi.IsGenericMethod then\n            let mi = mi.GetGenericMethodDefinition()\n            implementations.Add(mi, createTarget mi) |> ignore\n        else\n            implementations.Add(mi, createTarget mi) |> ignore\n\n    member x.Add(target : obj, mi : MethodInfo) =\n        if initialized then\n            failwith \"cannot modify Multimethod after first call\"\n\n        if mi.GetParameters().Length <> parameterCount then\n            failwithf \"cannot add %A to Multimethod due to parameter-count mismatch\" mi\n\n        if mi.IsGenericMethod then\n            let mi = mi.GetGenericMethodDefinition()\n            implementations.Add(mi, target) |> ignore\n        else\n            implementations.Add(mi, target) |> ignore\n\n\n    member x.TryInvoke(args : obj[], [<Out>] result : byref<obj>) : bool =\n        if args.Length <> parameterCount then\n            false\n        else\n            try\n                let res = methodCache.Invoke args\n                result <- res\n                true\n\n            with :? RuntimeMethodBuilder.UnsupportedTypesException ->\n                false\n\n    member x.InvokeUnsafe(args : obj[]) : obj =\n        methodCache.Invoke args\n\n\n    member x.Invoke(args : obj[]) =\n        if args.Length <> parameterCount then\n            raise <| MultimethodException\n        else\n            try\n                methodCache.Invoke args\n            with :? RuntimeMethodBuilder.UnsupportedTypesException ->\n                raise <| MultimethodException\n\n    new(parameterCount : int) = \n        Multimethod(parameterCount, Seq.empty)\n\n    new(methods : seq<MethodInfo>) = \n        let count = (methods |> Seq.head).GetParameters().Length\n        Multimethod(count, methods |> Seq.map (fun mi -> mi, createTarget mi))\n\nmodule MultimethodTest =\n\n\n    type IA<'a> =\n        abstract member V : obj\n        abstract member Sepp : unit -> obj\n\n    type A = \n        class\n            val mutable public V : obj\n\n            abstract member Sepp : unit -> obj\n            default x.Sepp() = x.V\n\n            interface IA<float32> with\n                member x.V = x.V\n                member x.Sepp() = x.Sepp()\n\n            new(v) = { V = v }\n        end\n\n    type B(a : obj) =\n        inherit A(a)\n\n        override x.Sepp() = x.V\n\n        member x.A = a\n\n    type C(v : obj) =\n        interface IA<obj> with\n            member x.V = v\n            member x.Sepp() = v\n\n    type D(v : obj) = inherit B(v)\n    type E(v : obj) = inherit B(v)\n    type F(v : obj) = inherit B(v)\n    type G(v : obj) = inherit B(v)\n    type H(v : obj) = inherit B(v)\n    type I(v : obj) = inherit B(v)\n    type J(v : obj) = inherit B(v)\n    type K(v : obj) = inherit B(v)\n    type L(v : obj) = inherit B(v)\n    type M(v : obj) = inherit B(v)\n    type N(v : obj) = inherit B(v)\n\n    open System.Runtime.CompilerServices\n\n    type Sepp() =\n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Value(ia : IA<'a>) =\n            ia.V\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Value(a : A) =\n            a.V\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Value(b : B) =\n            b.V\n\n    open System.Diagnostics\n    open System.IO\n    let inline (==) (a : 'a) (b : 'a) =\n        System.Object.ReferenceEquals(a, b)\n\n    let inline (!=) (a : 'a) (b : 'a) =\n        not (System.Object.ReferenceEquals(a, b))\n\n\n    let dt = typeof<D>\n    let dispatcher (o : obj[]) =\n        let a = o.[0]\n        match a with\n            | :? D as d -> Sepp.Value(d)\n            | _ -> \n                let t = a.GetType()\n                raise <| RuntimeMethodBuilder.UnsupportedTypesException [|t|]\n\n\n    let run() =\n        let m = Multimethod(typeof<Sepp>.GetMethods() |> Seq.filter (fun mi -> mi.Name = \"Value\"))\n\n        let iterations = 1 <<< 26\n\n        let nop() =\n            let args = [|D 10 :> obj|]\n            let sw = Stopwatch()\n            let mutable iter = 0\n\n            System.GC.Collect()\n            System.GC.WaitForFullGCComplete() |> ignore\n\n            sw.Start()\n            for i in 1..iterations do\n                iter <- iter + 1\n            sw.Stop()\n            let t = (1000000.0 * sw.Elapsed.TotalMilliseconds / float iter)\n            printfn \"nop:  %.3fns\" t\n            t\n\n\n        let ours() =\n            let args = [|D 10 :> obj|]\n            let sw = Stopwatch()\n            let mutable iter = 0\n            let mutable res = Unchecked.defaultof<obj>\n\n            let badInit() =\n                let mutable res = Unchecked.defaultof<obj>\n                m.TryInvoke([|A 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|B 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|C 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|E 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|F 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|G 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|H 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|I 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|J 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|K 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|L 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|M 10 :> obj|], &res) |> ignore\n                m.TryInvoke([|N 10 :> obj|], &res) |> ignore\n\n\n            \n            //badInit()\n            m.TryInvoke(args, &res) |> ignore\n\n            for i in 0..1000 do\n                m.InvokeUnsafe(args) |> ignore\n\n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n            sw.Start()\n            for i in 1..iterations do\n                m.InvokeUnsafe(args) |> ignore\n                iter <- iter + 1\n            sw.Stop()\n            let t = (1000000.0 * sw.Elapsed.TotalMilliseconds / float iter)\n            printfn \"ours: %.3fns\" t\n            t\n\n        let dispatcher() =\n            let args = [|D 10 :> obj|]\n            let sw = Stopwatch()\n            let mutable iter = 0\n            let mutable res = Unchecked.defaultof<obj>\n\n            for i in 0..1000 do\n                dispatcher(args) |> ignore\n\n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n            sw.Start()\n            for i in 1..iterations do\n                dispatcher(args) |> ignore\n                iter <- iter + 1\n            sw.Stop()\n            let t = (1000000.0 * sw.Elapsed.TotalMilliseconds / float iter)\n            printfn \"disp: %.3fns\" t\n            t\n\n        let virtualCall() =\n            let s = Sepp()\n            let args = D 10 :> IA<float32>\n            let sw = Stopwatch()\n            let mutable iter = 0\n            let mutable res = Unchecked.defaultof<obj>\n\n            for i in 0..1000 do\n                args.Sepp() |> ignore\n\n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n            sw.Start()\n            for i in 1..iterations do\n                args.Sepp() |> ignore\n                iter <- iter + 1\n            sw.Stop()\n            let t = (1000000.0 * sw.Elapsed.TotalMilliseconds / float iter)\n            printfn \"virt: %.3fns\" t\n            t\n\n        let staticCall() =\n            let s = Sepp()\n            let args = D 10\n            let sw = Stopwatch()\n            let mutable iter = 0\n            let mutable res = Unchecked.defaultof<obj>\n\n            for i in 0..1000 do\n                Sepp.Value(args) |> ignore\n\n\n            System.GC.Collect()\n            System.GC.WaitForFullGCComplete() |> ignore\n\n            sw.Start()\n            for i in 1..iterations do\n                Sepp.Value(args) |> ignore\n                iter <- iter + 1\n            sw.Stop()\n            let t = (1000000.0 * sw.Elapsed.TotalMilliseconds / float iter)\n            printfn \"stat: %.3fns\" t\n            t\n\n\n        let log = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), \"callPerf.csv\")\n        File.WriteAllText(log, \"nop;virtual;dispatcher;multimethods;static\\r\\n\")\n        for i in 1..50 do\n            let tNop = nop()\n            let tOurs = ours()\n            let tVirt = virtualCall()\n            let tStat = staticCall()\n            let tDisp = dispatcher()\n            let line = sprintf \"%.3f;%.3f;%.3f;%.3f;%.3f\" tNop tVirt tDisp tOurs tStat\n            File.AppendAllLines(log, [line])\n            System.GC.Collect()\n            System.GC.WaitForFullGCComplete() |> ignore\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/Quotations.fs",
    "content": "﻿namespace Aardvark.Base.Quotations\n\n\nopen System\nopen System.Reflection\nopen Aardvark.Base\nopen Aardvark.Base.IL\nopen Microsoft.FSharp.Quotations\nopen Microsoft.FSharp.Quotations.Patterns\n\nmodule QuotationDisassembler =\n    open Aardvark.Base.IL.StateMonad\n\n    type DisassemblerState =\n        {\n            labels      : list<Label>\n            entries     : Map<Label, list<Instruction>>\n            stack       : list<Expr>\n            locals      : Map<Local, Var>\n            args        : Var[]\n            ret         : Type\n        }\n\n    type Disasm<'a> = State<DisassemblerState, 'a>\n\n    module Disasm =\n        let pop : Disasm<Expr> =\n            fun s ->\n                match s.stack with\n                    | h::stack ->\n                        let s = { s with stack = stack }\n                        s, h\n                    | _ ->\n                        failwithf \"[Disasm] cannot pop from empty stack\"\n\n        let push (e : Expr) : Disasm<unit> =\n            fun s -> { s with stack = e::s.stack }, ()\n\n        let getArg (i : int) : Disasm<Var> =\n            fun s -> s, s.args.[i]\n\n        let getLocal (l : Local) : Disasm<bool * Var> =\n            fun s ->\n                match Map.tryFind l s.locals with\n                    | Some v -> s,(false, v)\n                    | None ->\n                        let v = Var(\"var\" + string l.Id, l.Type, true)\n                        let s = { s with locals = Map.add l v s.locals }\n                        s,(true, v)\n\n        let getCode (l : Label) : Disasm<list<Instruction>> =\n            fun s ->\n                match Map.tryFind l s.entries with\n                    | Some e -> s,e\n                    | None -> failwithf \"invalid label: %A\" l\n\n        let pushLabel (l : Label) : Disasm<unit> =\n            fun s -> { s with labels = l::s.labels }, ()\n\n        let peekLabel : Disasm<Option<Label>> =\n            fun s -> \n                match s.labels with\n                    | [] -> s, None\n                    | l::_ -> s, Some l\n\n        let popLabel : Disasm<unit> =\n            fun s -> \n                match s.labels with\n                    | [] -> s, ()\n                    | _::rest -> { s with labels = rest }, ()\n\n\n    let private add = QuotationReflectionHelpers.getMethodInfo <@ (+) @>\n    let private sub = QuotationReflectionHelpers.getMethodInfo <@ (-) @>\n\n    let private less = QuotationReflectionHelpers.getMethodInfo <@ (<) @>\n    let private lessEqual = QuotationReflectionHelpers.getMethodInfo <@ (<=) @>\n    let private greater = QuotationReflectionHelpers.getMethodInfo <@ (>) @>\n    let private greaterEqual = QuotationReflectionHelpers.getMethodInfo <@ (>=) @>\n    let private equal = QuotationReflectionHelpers.getMethodInfo <@ (=) @>\n    let private notEqual = QuotationReflectionHelpers.getMethodInfo <@ (<>) @>\n\n\n    type Expr with\n        static member Add (l : Expr, r : Expr) =\n            let m = add.MakeGenericMethod [|l.Type; r.Type; r.Type|]\n            Expr.Call(m, [l;r])\n\n        static member Sub (l : Expr, r : Expr) =\n            let m = sub.MakeGenericMethod [|l.Type; r.Type; r.Type|]\n            Expr.Call(m, [l;r])\n\n        static member Compare(op : JumpCondition, l : Expr, r : Expr) =\n            let meth = \n                match op with\n                    | Less              -> less.MakeGenericMethod [|l.Type|]\n                    | LessOrEqual       -> lessEqual.MakeGenericMethod [|l.Type|]\n                    | Greater           -> greater.MakeGenericMethod [|l.Type|]\n                    | GreaterOrEqual    -> greaterEqual.MakeGenericMethod [|l.Type|]\n                    | Equal             -> equal.MakeGenericMethod [|l.Type|]\n                    | NotEqual          -> notEqual.MakeGenericMethod [|l.Type|]\n                    | _                 -> failwithf \"%A is not a binary comparison\" op\n\n            Expr.Call(meth, [l;r])\n\n        static member NegatedCompare(op : JumpCondition, l : Expr, r : Expr) =\n            let meth = \n                match op with\n                    | Less              -> greaterEqual.MakeGenericMethod [|l.Type|]\n                    | LessOrEqual       -> greater.MakeGenericMethod [|l.Type|]\n                    | Greater           -> lessEqual.MakeGenericMethod [|l.Type|]\n                    | GreaterOrEqual    -> less.MakeGenericMethod [|l.Type|]\n                    | Equal             -> notEqual.MakeGenericMethod [|l.Type|]\n                    | NotEqual          -> equal.MakeGenericMethod [|l.Type|]\n                    | _                 -> failwithf \"%A is not a binary comparison\" op\n\n            Expr.Call(meth, [l;r])\n\n        static member Constant(c : Constant) =\n            match c with\n                | Int8 v -> Expr.Value(v)\n                | UInt8 v -> Expr.Value(v)\n                | Int16 v -> Expr.Value(v)\n                | UInt16 v -> Expr.Value(v)\n                | Int32 v -> Expr.Value(v)\n                | UInt32 v -> Expr.Value(v)\n                | Int64 v -> Expr.Value(v)\n                | UInt64 v -> Expr.Value(v)\n                | NativeInt v -> Expr.Value(v)\n                | UNativeInt v -> Expr.Value(v)\n                | Float32 v -> Expr.Value(v)\n                | Float64 v -> Expr.Value(v)\n                | String str -> Expr.Value(str)\n\n    let rec private simulate (code : list<Instruction>) =\n        state {\n            match code with\n                | [] -> \n                    return failwithf \"code ends without ret\"\n                | Nop :: rest -> \n                    return! simulate rest\n\n                | Ldarg i :: rest ->\n                    let! arg = Disasm.getArg i \n                    do! Disasm.push (Expr.Var arg)\n                    return! simulate rest\n\n                | Ldloc l :: rest ->\n                    let! (_,l) = Disasm.getLocal l\n                    do! Disasm.push (Expr.Var l)\n                    return! simulate rest\n\n                | Stloc l :: rest ->\n                    let! (isNew, l) = Disasm.getLocal l\n                    let! v = Disasm.pop\n                    let! rest = simulate rest\n                    if isNew then\n                        return Expr.Let(l, v, rest)\n                    else\n                        return Expr.Sequential(Expr.VarSet(l, v), rest)\n\n                | LdlocA l :: rest ->   \n                    let! (_,l) = Disasm.getLocal l\n                    do! Disasm.push (Expr.AddressOf (Expr.Var l))\n                    return! simulate rest\n\n                | Add :: rest ->\n                    let! r = Disasm.pop\n                    let! l = Disasm.pop\n                    do! Disasm.push (Expr.Add(l,r))\n                    return! simulate rest\n\n                | Sub :: rest ->\n                    let! r = Disasm.pop\n                    let! l = Disasm.pop\n                    do! Disasm.push (Expr.Sub(l,r))\n                    return! simulate rest\n\n\n                | Ret :: _ ->\n                    return! Disasm.pop\n\n                | Mark l :: rest ->\n                    do! Disasm.pushLabel l\n                    return! simulate rest\n\n                | LdConst c :: rest ->\n                    do! Disasm.push (Expr.Constant c)\n                    return! simulate rest\n\n                | ConditionalJump(c, label) :: rest ->\n                    let! r = Disasm.pop\n                    let! l = Disasm.pop\n\n                    let! trueCode = Disasm.getCode label\n\n                    let! ifFalse = simulate rest\n                    let! ifTrue = simulate trueCode\n\n                    let cmp = Expr.NegatedCompare(c, l, r)\n                    if ifFalse.Type <> ifTrue.Type then\n                        return Expr.Sequential(Expr.WhileLoop(cmp, ifFalse), ifTrue)\n                    else\n                        return Expr.IfThenElse(cmp, ifFalse, ifTrue)\n\n                | Jump label :: _ ->\n                    let! l = Disasm.peekLabel\n                    match l with\n                        | Some l when l = label ->\n                            do! Disasm.popLabel\n                            return Expr.Value(())\n                        | _ -> \n                            let! cont = Disasm.getCode label\n                            return! simulate cont\n\n                | _ ->\n                    return failwithf \"unsupported instruction: %A\" code\n        }\n\n    let disassemble (m : MethodDefinition) =\n\n        let rec buildEntries (current : Map<Label, list<Instruction>>) (code : list<Instruction>) =\n            match code with\n                | Mark l :: rest ->\n                    match Map.tryFind l current with\n                        | Some _ -> current\n                        | _ ->\n                            let current = Map.add l rest current\n                            buildEntries current rest\n                | a::rest ->\n                    \n                    buildEntries current rest\n\n\n                | [] ->\n                    current\n\n        let entries = buildEntries Map.empty m.Body\n\n        let (state,res) =\n            simulate m.Body {\n                labels = []\n                entries = entries\n                stack = []\n                locals = Map.empty\n                args = m.ArgumentTypes |> Array.mapi (fun i a -> Var(sprintf \"arg%d\" i, a, true))\n                ret = m.ReturnType\n            }\n\n        res\n            \n\nmodule QuotationDisassemblerTest =\n    \n\n    type Dummy =\n        static member Method (a : int, b : int) =\n            let mutable c = a\n            for i in 0..a do\n                c <- c - b\n            c\n\n    let run() =\n        let def = Disassembler.disassemble (typeof<Dummy>.GetMethod \"Method\")\n\n        Log.start \"Method\"\n\n        for i in def.Body do\n            Log.line \"%A\" i\n\n        Log.stop()\n\n        let e = QuotationDisassembler.disassemble def\n\n        printfn \"%A\" e\n\n\n\n\n\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/ReflectionExtensions.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Reflection\nopen System.Runtime.CompilerServices\nopen FSharp.Data.Adaptive\n\n\n[<AbstractClass; Sealed; Extension>]\ntype InheritanceTypeExtensions private() = \n\n\n    static let topoSort (types : Type[]) =\n        let rec cmp (a : Type) (b : Type) =\n            if a = b then 0\n\n            elif a.IsGenericParameter && b.IsGenericParameter then compare a.Name b.Name\n            elif a.IsGenericParameter then 1\n            elif b.IsGenericParameter then -1\n\n            elif a.IsAssignableFrom b then 1\n            elif b.IsAssignableFrom a then -1\n\n\n            elif a.IsInterface && b.IsInterface then compare a.FullName b.FullName\n            elif a.IsInterface then 1\n            elif b.IsInterface then -1\n\n            elif a.IsGenericType && b.IsGenericType then compare a.FullName b.FullName\n            elif a.IsGenericType then -1\n            elif b.IsGenericType then 1\n            else compare a.FullName b.FullName\n        Array.sortWith cmp types\n        \n    static let rec baseTypes (t : Type) =\n        if isNull t.BaseType || t.BaseType = t then \n            []\n        else \n            let b = t.BaseType\n            if b = typeof<System.ValueType> then [ typeof<obj> ]\n            else b :: baseTypes b\n\n    /// Gets the type's base-types (including interfaces) in topological order (from most specific to obj)\n    [<Extension>]\n    static member GetBaseTypes(this : Type) =\n        if this.IsByRef then\n            [||]\n        elif this.IsInterface then\n            this.GetInterfaces() |> topoSort\n        else\n            let ifaces = this.GetInterfaces()\n            let types = baseTypes this |> List.toArray\n            Array.append ifaces types |> topoSort\n               \n    /// Gets the type's base-types (including interfaces) in topological order (from most specific to obj)\n    [<Extension>]\n    static member GetBaseTypesAndSelf(this : Type) =\n        if this.IsByRef then\n            [| this |]\n        elif this.IsInterface then\n            Array.append [|this|] (this.GetInterfaces()) |> topoSort\n        else\n            let ifaces = this.GetInterfaces()\n            let types = this :: baseTypes this |> List.toArray\n            Array.append ifaces types |> topoSort\n               \n    /// Replaces all occurences of p in x with v\n    [<Extension>]\n    static member Substitute(x : Type, p : Type, v : Type) =\n        if x = p then\n            v\n        elif x.IsGenericParameter then\n            x\n\n        elif x.IsByRef then\n            let e = x.GetElementType().Substitute(p, v)\n            e.MakeByRefType()\n\n        elif x.IsArray then\n            let r = x.GetArrayRank()\n            let e = x.GetElementType().Substitute(p, v)\n            e.MakeArrayType(r)\n\n        elif x.IsGenericType then\n            let tdef = x.GetGenericTypeDefinition()\n            let targs = x.GetGenericArguments() |> Array.map (fun a -> a.Substitute(p, v))\n            tdef.MakeGenericType targs\n\n        else\n            x\n         \n    /// Replaces all generic parameters using the given mapping.\n    [<Extension>]\n    static member SubstituteParameters(x : Type, mapping : Type -> Type) =\n        if x.ContainsGenericParameters then\n            if x.IsGenericParameter then\n                mapping x\n\n            elif x.IsByRef then\n                let e = x.GetElementType().SubstituteParameters mapping\n                e.MakeByRefType()\n\n            elif x.IsArray then\n                let r = x.GetArrayRank()\n                let e = x.GetElementType().SubstituteParameters mapping\n                e.MakeArrayType(r)\n\n            elif x.IsGenericType then\n                let tdef = x.GetGenericTypeDefinition()\n                let targs = x.GetGenericArguments() |> Array.map (fun a -> a.SubstituteParameters mapping)\n                tdef.MakeGenericType targs\n\n            else\n                x\n        else\n            x\n       \n    [<Extension>]\n    static member FreeVariables(x : Type) =\n        if x.ContainsGenericParameters then\n            if x.IsGenericParameter then\n                HashSet.single x\n\n            elif x.IsArray || x.IsByRef then\n                x.GetElementType().FreeVariables()\n\n            elif x.IsGenericType then\n                (HashSet.empty, x.GetGenericArguments()) ||> Array.fold (fun s t ->\n                    HashSet.union s (t.FreeVariables())\n                ) \n            else\n                failwith \"bad\"\n        else\n            HashSet.empty\n            \n    /// topologically sorts the given types (from most specific to obj)\n    [<Extension>]\n    static member TopologicalSort(this : seq<Type>) =\n        match this with\n        | :? array<Type> as this -> topoSort this\n        | _ -> topoSort (Seq.toArray this)\n\n\nmodule private MethodResolver =\n\n    type TypeDef =\n        | Generic of Type * Type[]\n        | Array of dim : int * Type\n        | ByRef of Type\n\n        static member GetDefinition(x : Type) =\n            if x.IsArray then Array (x.GetArrayRank(), x.GetElementType())\n            elif x.IsByRef then ByRef (x.GetElementType())\n            elif x.IsGenericType then Generic (x.GetGenericTypeDefinition(), x.GetGenericArguments())\n            else Generic(x, [||])\n\n        member x.EqualDefinition(other : TypeDef) =\n            match x, other with\n            | Generic(a,_), Generic(b,_) -> a = b\n            | Array(a,_), Array(b,_) -> a = b\n            | ByRef _, ByRef _ -> true\n            | _ -> false\n\n        member x.IsInterface =\n            match x with\n            | Generic (t, _) -> t.IsInterface\n            | _ -> false\n\n        member x.IsSealed =\n            match x with\n            | Generic (t, _) -> t.IsSealed\n            | _ -> true\n\n        member x.IsValueType =\n            match x with\n            | Generic (t, _) -> t.IsValueType\n            | Array _ -> false\n            | _ -> true\n                \n        member x.FullName =\n            match x with\n            | Generic (t, _) -> t.FullName\n            | _ -> \"\"\n\n        member x.GenericArguments =\n            match x with\n            | Generic(_, args) -> args\n            | Array(dim, t) -> [| t |]\n            | ByRef t -> [| t |]\n\n        member x.Make(args : Type[]) =\n            match x with\n            | Generic(t, _) -> t.MakeGenericType args\n            | Array(dim,_) -> args.[0].MakeArrayType(dim)\n            | ByRef _ -> args.[0].MakeByRefType()\n\n        member x.BaseType =\n            match x with\n            | Generic(t, targs) ->\n                let self = if targs.Length > 0 then t.MakeGenericType(targs) else t\n                if not (isNull self.BaseType) && self.BaseType <> self then\n                    let baseDef = self.BaseType |> TypeDef.GetDefinition\n                    Some baseDef\n                else\n                    None\n            | Array(1, t) ->\n                Generic(typeof<System.Array>, [||]) |> Some\n            | _ ->\n                None\n                \n        member x.TryGetBaseType(t : TypeDef) =\n            if x.EqualDefinition t then Some x\n            elif t.IsSealed || t.IsValueType then None\n            else\n                match x.BaseType with\n                | Some b -> b.TryGetBaseType t\n                | None -> None\n\n\n    type System.Type with\n        member x.GetDefinition() =\n            if x.IsArray then Array (x.GetArrayRank(), x.GetElementType())\n            elif x.IsByRef then ByRef (x.GetElementType())\n            elif x.IsGenericType then Generic (x.GetGenericTypeDefinition(), x.GetGenericArguments())\n            else Generic(x, [||])\n\n    module SolverNoVariance =\n        let rec tryUnify (mapping : HashMap<Type, Type>) (p : Type) (a : Type) =\n            let pd = p.GetDefinition()\n            let ad = a.GetDefinition()\n\n            if p = a then \n                Some mapping\n            elif p.IsGenericParameter then\n                match HashMap.tryFind p mapping with\n                | Some old ->\n                    if a.ContainsGenericParameters then\n                        let m = HashMap.remove p mapping\n                        tryUnify m old a\n                    else\n                        if old <> a then None\n                        else Some mapping\n                | None ->\n                    Some (HashMap.add p a mapping)\n            elif a.IsGenericParameter then\n                match HashMap.tryFind a mapping with\n                | Some old ->\n                    if p.ContainsGenericParameters then\n                        let m = HashMap.remove a mapping\n                        tryUnify m old p\n                    else\n                        if old <> p then None\n                        else Some mapping\n                | None ->\n                    Some (HashMap.add a p mapping)\n            elif pd.EqualDefinition ad then\n                (Some mapping, pd.GenericArguments, ad.GenericArguments) |||> Array.fold2 (fun s pi ai ->\n                    match s with\n                    | Some s -> tryUnify s pi ai\n                    | None -> None\n                )\n            elif p.IsInterface then\n                let ri = a.GetInterface(pd.FullName)\n                if isNull ri then \n                    None\n                else\n                    tryUnify mapping p ri\n            else\n                a.GetBaseTypes() |> Array.tryPick (tryUnify mapping p)\n\n    let tryMakeApplicable (args : Type[]) (ret : Type) (meth : MethodInfo) : option<MethodInfo> =\n        let pars = meth.GetParameters()\n        if pars.Length = args.Length then\n            if meth.ContainsGenericParameters then\n                let def = meth.GetGenericMethodDefinition()\n                let tpars = def.GetGenericArguments()\n\n                let argumentConstraints = \n                    (Some HashMap.empty, pars, args) |||> Array.fold2 (fun ass p a -> \n                        match ass with\n                        | Some ass -> \n                            SolverNoVariance.tryUnify ass p.ParameterType a\n                            //Solver.tryUnify ass p.ParameterType a ConstraintKind.SuperType\n                        | None ->\n                            None\n                    )\n\n                let finalConstraints =\n                    match argumentConstraints with\n                    | Some a -> \n                        SolverNoVariance.tryUnify a ret meth.ReturnType\n                        //Solver.tryUnify a meth.ReturnType ret ConstraintKind.SubType\n                    | None -> None\n\n\n                match finalConstraints with\n                | Some solution ->\n                    let instantiation = tpars |> Array.map (fun p -> match HashMap.tryFind p solution with | Some t -> t | None -> typeof<obj>)\n                    if instantiation.Length = tpars.Length then\n                        let final = def.MakeGenericMethod instantiation\n                        if ret.IsAssignableFrom final.ReturnType then\n                            Some final\n                        else\n                            // bad return type\n                            None\n                    else    \n                        // internal error: assignment not complete\n                        None\n                | None ->\n                    // could not unify\n                    None\n            else\n                if ret.IsAssignableFrom meth.ReturnType then\n                    let argsMatch = (pars, args) ||> Array.forall2 (fun p a -> p.ParameterType.IsAssignableFrom a)\n                    if argsMatch then\n                        Some meth\n                    else\n                        // bad parameter types\n                        None\n                else\n                    // bad return type\n                    None\n        else\n            // bad parameter count\n            None\n\n\n[<AbstractClass; Sealed; Extension>]\ntype MethodInfoGenericExtensions private() =    \n    [<Extension>]\n    static member TrySpecialize(this : MethodInfo, args : Type[], ret : Type) =\n        MethodResolver.tryMakeApplicable args ret this\n\n    [<Extension>]\n    static member Specialize(this : MethodInfo, args : Type[], ret : Type) =\n        match MethodResolver.tryMakeApplicable args ret this with\n        | Some m -> m\n        | None -> null\n\n\n[<System.Runtime.CompilerServices.Extension>]\nmodule ReflectionHelpers =\n    open Microsoft.FSharp.Reflection\n\n    let private lockObj = obj()\n\n    let private prettyNames =\n        Dict.ofList [\n            typeof<sbyte>, \"sbyte\"\n            typeof<byte>, \"byte\"\n            typeof<int16>, \"int16\"\n            typeof<uint16>, \"uint16\"\n            typeof<int>, \"int\"\n            typeof<uint32>, \"uint32\"\n            typeof<int64>, \"int64\"\n            typeof<uint64>, \"uint64\"\n            typeof<nativeint>, \"nativeint\"\n            typeof<unativeint>, \"unativeint\"\n\n            typeof<char>, \"char\"\n            typeof<string>, \"string\"\n\n\n            typeof<float32>, \"float32\"\n            typeof<float>, \"float\"\n            typeof<decimal>, \"decimal\"\n\n            typeof<obj>, \"obj\"\n            typeof<unit>, \"unit\"\n            typeof<System.Void>, \"void\"\n\n        ]\n\n    let private genericPrettyNames =\n        Dict.ofList [\n            typedefof<list<_>>, \"list\"\n            typedefof<Option<_>>, \"Option\"\n            typedefof<Set<_>>, \"Set\"\n            typedefof<Map<_,_>>, \"Map\"\n            typedefof<seq<_>>, \"seq\"\n\n        ]\n\n    let private idRx = System.Text.RegularExpressions.Regex @\"[a-zA-Z_][a-zA-Z_0-9]*\"\n\n    let rec private getPrettyNameInternal (t : Type) =\n        let res = \n            match prettyNames.TryGetValue t with\n                | (true, n) -> n\n                | _ ->\n                    if t.IsArray then\n                        t.GetElementType() |> getPrettyNameInternal |> sprintf \"%s[]\"\n\n                    elif FSharpType.IsTuple t then\n                        FSharpType.GetTupleElements t |> Seq.map getPrettyNameInternal |> String.concat \" * \"\n\n                    elif FSharpType.IsFunction t then\n                        let (arg, res) = FSharpType.GetFunctionElements t\n\n                        sprintf \"%s -> %s\" (getPrettyNameInternal arg) (getPrettyNameInternal res)\n\n                    elif typeof<Aardvark.Base.INatural>.IsAssignableFrom t then\n                        let s = Aardvark.Base.Peano.getSize t\n                        sprintf \"N%d\" s\n\n                    elif t.IsGenericType then\n                        let args = t.GetGenericArguments() |> Seq.map getPrettyNameInternal |> String.concat \", \"\n                        let bt = t.GetGenericTypeDefinition()\n                        match genericPrettyNames.TryGetValue bt with\n                            | (true, gen) ->\n                                sprintf \"%s<%s>\" gen args\n                            | _ ->\n                                let gen = idRx.Match bt.Name\n                                sprintf \"%s<%s>\" gen.Value args\n\n\n                    else\n                        t.Name\n\n        prettyNames.[t] <- res\n        res\n\n    [<System.Runtime.CompilerServices.Extension; CompiledName(\"GetPrettyName\")>]\n    let getPrettyName(t : Type) =\n        lock lockObj (fun () ->\n            getPrettyNameInternal t\n        )\n\n    type Type with\n        member x.PrettyName =\n            lock lockObj (fun () ->\n                getPrettyNameInternal x\n            )\n\n\n/// <summary>\n/// Defines a number of active patterns for matching expressions. Includes some\n/// functionality missing in F#.\n/// </summary>\n[<AutoOpen>]\nmodule ReflectionPatterns =\n    open Microsoft.FSharp.Quotations\n    open QuotationReflectionHelpers\n    open System.Text.RegularExpressions\n\n    let private typePrefixPattern = Regex(@\"^.*\\.(?<methodName>.*)$\", RegexOptions.Compiled)\n\n    let (|Method|) (mi : MethodInfo) =\n        let parameters =\n            let p = mi.GetParameters() |> Array.toList |> List.map _.ParameterType\n            if mi.IsStatic then p else mi.DeclaringType :: p\n\n        let name =\n            let m = typePrefixPattern.Match mi.Name\n            if m.Success then m.Groups.[\"methodName\"].Value\n            else mi.Name\n\n        (name, parameters)\n\n    let private compareMethods (template : MethodInfo) (m : MethodInfo) =\n        if template.IsGenericMethod && m.IsGenericMethod then\n            if template.GetGenericMethodDefinition() = m.GetGenericMethodDefinition() then\n                let targs = template.GetGenericArguments() |> Array.toList\n                let margs = m.GetGenericArguments() |> Array.toList\n\n                let args =\n                    List.zip targs margs\n                    |> List.filter (fst >> _.IsGenericParameter)\n                    |> List.map snd\n\n                ValueSome args\n            else\n                ValueNone\n\n        elif template = m then\n            ValueSome []\n        else\n            ValueNone\n\n    [<return: Struct>]\n    let (|MethodQuote|_|) (e : Expr) (mi : MethodInfo) =\n        match tryGetMethodInfo e with\n        | Some m -> compareMethods m mi\n        | _ -> ValueNone\n\n    let (|Create|) (c : ConstructorInfo) =\n        (c.DeclaringType, c.GetParameters() |> Seq.toList)"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/TypeBuilder.fs",
    "content": "﻿namespace Aardvark.Base.IL\n\nopen System\nopen System.Reflection\nopen System.Reflection.Emit\nopen Aardvark.Base\nopen FSharp.Data.Adaptive\n\nmodule TypeBuilderOld =\n    \n    let private bAss = \n        AssemblyBuilder.DefineDynamicAssembly(\n            AssemblyName \"TypeBuilder\", \n            AssemblyBuilderAccess.Run\n        )\n\n    let private bMod =\n        bAss.DefineDynamicModule(\"MainModule\")\n\n\n    let implementInterface (iface : Type) (methods : list<Type * string * list<Type> * CodeGen<unit>>) =\n\n        let bType = \n            bMod.DefineType(\n                Guid.NewGuid() |> string,\n                TypeAttributes.Class,\n                typeof<obj>,\n                [|iface|]\n            )\n\n        let rec tryFindMethod (name : string) (args : Type[]) (ret : Type) (t : Type)=\n            let m = t.GetMethod(name, BindingFlags.Instance ||| BindingFlags.NonPublic ||| BindingFlags.Public, Type.DefaultBinder, args, null)\n            if isNull m || m.ReturnType <> ret then\n                let ifaces = t.GetInterfaces()\n                ifaces |> Array.tryPick (tryFindMethod name args ret)\n            else\n                Some m\n\n        let fields = \n            methods |> List.map (fun (ret, name, args, code) ->\n                \n                let prototype = \n                    match tryFindMethod name (List.toArray args) ret iface with\n                        | Some meth -> meth\n                        | _ -> null\n\n\n\n                let fieldType = \n                    let args = iface::args |> List.toArray\n                    if ret = typeof<System.Void> then\n                        let actionType = Type.GetType(typedefof<Action<_>>.FullName.Replace(\"1\", string args.Length))\n                        actionType.MakeGenericType args\n                    else\n                        let funcType = Type.GetType(typedefof<Func<_>>.FullName.Replace(\"1\", string (1 + args.Length)))\n                        funcType.MakeGenericType (Array.append args [|ret|])\n\n                let field = bType.DefineField(\"m_\" + name, fieldType, FieldAttributes.Private)\n\n                prototype, field, ret, List.toArray args, code\n            )\n\n        for (prototype, field, ret, args,_) in fields do\n            let meth = \n                bType.DefineMethod(\n                    field.Name.Substring 2, \n                    MethodAttributes.Virtual ||| MethodAttributes.Public,\n                    ret,\n                    args\n                )\n\n            let il = meth.GetILGenerator()\n\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldfld, field)\n\n\n            il.Emit(OpCodes.Ldarg_0)\n            for i in 1..args.Length do\n                il.Emit(OpCodes.Ldarg, i)\n\n            let invoke = field.FieldType.GetMethod(\"Invoke\")\n\n            //il.Emit(OpCodes.Tailcall)\n            il.EmitCall(OpCodes.Callvirt, invoke, null)\n            il.Emit(OpCodes.Ret)\n\n            if not (isNull prototype) then\n                bType.DefineMethodOverride(meth, prototype)\n\n        let fieldTypes = fields |> List.map (fun (_,f,_,_,_) -> f.FieldType) |> List.toArray\n\n        let ctor = \n            bType.DefineConstructor(\n                MethodAttributes.Public,\n                CallingConventions.Standard,\n                fieldTypes\n            )\n\n        let il = ctor.GetILGenerator()\n\n        il.Emit(OpCodes.Ldarg_0)\n        il.Emit(OpCodes.Call, typeof<obj>.GetConstructor [||])     \n\n\n        let mutable index = 1\n        for (_, field, _, _, _) in fields do\n\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldarg, index)\n            il.Emit(OpCodes.Stfld, field)\n            \n\n            index <- index + 1\n\n        il.Emit(OpCodes.Ret)\n\n        let t = bType.CreateTypeInfo()\n\n        let delegates =\n            fields |> List.map (fun (_, f, _,_,code) ->\n                Assembler.assembleDelegateInternal f.FieldType (CodeGen.run code) :> obj\n            )\n\n        let ctorArgs = fields |> List.map (fun (_,f,_,_,_) -> f.FieldType) |> List.toArray\n        let ctor = t.GetConstructor ctorArgs\n        ctor.Invoke(List.toArray delegates)\n\n    let implementSubType (baseType : Type) (methods : list<Type * string * list<Type> * CodeGen<unit>>) =\n\n        let bType = \n            bMod.DefineType(\n                Guid.NewGuid() |> string,\n                TypeAttributes.Class,\n                baseType,\n                [||]\n            )\n\n        let rec tryFindMethod (name : string) (args : Type[]) (ret : Type) (t : Type)=\n            let m = t.GetMethod(name, BindingFlags.Instance ||| BindingFlags.NonPublic ||| BindingFlags.Public, Type.DefaultBinder, args, null)\n            if isNull m || m.ReturnType <> ret then\n                let baseType = t.BaseType\n                if isNull baseType then None\n                else tryFindMethod name args ret baseType\n            else\n                Some m\n\n\n        let fields = \n            methods |> List.map (fun (ret, name, args, code) ->\n                \n                let prototype = \n                    match tryFindMethod name (List.toArray args) ret baseType with\n                        | Some meth -> meth\n                        | _ -> null\n\n\n                let fieldType = \n                    let args = baseType::args |> List.toArray\n                    if ret = typeof<System.Void> then\n                        let actionType = Type.GetType(typedefof<Action<_>>.FullName.Replace(\"1\", string args.Length))\n                        actionType.MakeGenericType args\n                    else\n                        let funcType = Type.GetType(typedefof<Func<_>>.FullName.Replace(\"1\", string (1 + args.Length)))\n                        funcType.MakeGenericType (Array.append args [|ret|])\n\n                let field = bType.DefineField(\"m_\" + name, fieldType, FieldAttributes.Private)\n\n                prototype, field, ret, List.toArray args, code\n            )\n\n        for (prototype, field, ret, args, _) in fields do\n\n            let meth = \n                bType.DefineMethod(\n                    field.Name.Substring 2, \n                    MethodAttributes.Virtual ||| MethodAttributes.Public,\n                    ret,\n                    args\n                )\n\n            let il = meth.GetILGenerator()\n\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldfld, field)\n\n            il.Emit(OpCodes.Ldarg_0)\n            for i in 1..args.Length do\n                il.Emit(OpCodes.Ldarg, i)\n\n            let invoke = field.FieldType.GetMethod(\"Invoke\")\n\n            il.Emit(OpCodes.Tailcall)\n            il.EmitCall(OpCodes.Callvirt, invoke, null)\n            il.Emit(OpCodes.Ret)\n\n            if not (isNull prototype) then\n                bType.DefineMethodOverride(meth, prototype)\n\n        let fieldTypes = fields |> List.map (fun (_,f,_,_,_) -> f.FieldType) |> List.toArray\n\n        let ctor = \n            bType.DefineConstructor(\n                MethodAttributes.Public,\n                CallingConventions.Standard,\n                fieldTypes\n            )\n\n        let il = ctor.GetILGenerator()\n\n        let baseCtor = baseType.GetConstructor(BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Instance, Type.DefaultBinder, [||], null)\n        il.Emit(OpCodes.Ldarg_0)\n        il.Emit(OpCodes.Call, baseCtor)     \n\n\n        let mutable index = 1\n        for (name, field,_,_, _) in fields do\n\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Ldarg, index)\n            il.Emit(OpCodes.Stfld, field)\n            \n\n            index <- index + 1\n\n        il.Emit(OpCodes.Ret)\n\n        let t = bType.CreateTypeInfo()\n\n        let delegates =\n            fields |> List.map (fun (name, f,_,_, code) ->\n                Assembler.assembleDelegateInternal f.FieldType (CodeGen.run code) :> obj\n            )\n\n        let ctorArgs = fields |> List.map (fun (_,f,_,_,_) -> f.FieldType) |> List.toArray\n        let ctor = t.GetConstructor ctorArgs\n        ctor.Invoke(List.toArray delegates)\n\n    let implement<'a> (methods : list<Type * string * list<Type> * CodeGen<unit>>) : 'a =\n        let t = typeof<'a>\n        if t.IsInterface then implementInterface t methods |> unbox<'a>\n        else implementSubType t methods |> unbox<'a>\n\n\n    let private funcType (args : list<Type>) (ret : Type) = \n        match args with\n            | [] -> failwithf \"[TypeBuilder] not a function-type: %A\" ret\n            | [x] -> typedefof<FSharpFunc<_,_>>.MakeGenericType [|x; ret|]\n            | args ->\n                let args = List.append args [ret] |> List.toArray\n                let name = typedefof<Microsoft.FSharp.Core.OptimizedClosures.FSharpFunc<_,_,_>>.AssemblyQualifiedName.Replace(\"`3\", \"`\" + string args.Length)\n                let tgen = Type.GetType(name)\n                tgen.MakeGenericType args\n\n    open Microsoft.FSharp.Core.OptimizedClosures\n    type private Pap =\n        static member Pap(f : FSharpFunc<'a, 'b, 'c>, a : 'a) = fun b -> f.Invoke(a, b)\n        static member Pap(f : FSharpFunc<'a, 'b, 'c, 'd>, a : 'a) = fun b c -> f.Invoke(a, b, c)\n        static member Pap(f : FSharpFunc<'a, 'b, 'c, 'd, 'e>, a : 'a) = fun b c d -> f.Invoke(a, b, c, d)\n        static member Pap(f : FSharpFunc<'a, 'b, 'c, 'd, 'e, 'f>, a : 'a) = fun b c d e -> f.Invoke(a, b, c, d, e)\n\n\n    let func<'a> (code : CodeGen<unit>) : 'a =\n        let args, ret = DelegateAdapters.getFunctionSignature typeof<'a>\n        let fType = funcType args ret\n\n        implementSubType fType [\n            yield ret, \"Invoke\", args, code\n\n            match args with\n                | a::_::_ ->\n                    let targs = List.toArray (List.append args [ret])\n                    let paps = typeof<Pap>.GetMethods(BindingFlags.NonPublic ||| BindingFlags.Static)\n                    let pap =\n                        paps |> Array.find(fun m ->\n                            m.Name = \"Pap\" && m.GetGenericArguments().Length = targs.Length\n                        )\n\n                    yield \n                        pap.ReturnType, \"Invoke\", [a],\n                        codegen {\n                            \n                            do! IL.ldarg 0\n                            do! IL.ldarg 1\n\n                            let paps = typeof<Pap>.GetMethods(BindingFlags.NonPublic ||| BindingFlags.Static)\n                            let pap =\n                                paps |> Array.find(fun m ->\n                                    m.Name = \"Pap\" && m.GetGenericArguments().Length = targs.Length\n                                )\n\n                            let pap = pap.MakeGenericMethod targs\n                            do! IL.call pap\n                            do! IL.ret\n                        }\n                | _ -> ()\n\n        ] |> unbox<'a>\n\nmodule TypeBuilder =\n    open System.Collections\n    open System.Collections.Generic\n\n    type TypeBuilderState =\n        {\n            builder : TypeBuilder\n            baseType : Type\n            delegates : HashMap<FieldBuilder, Type -> Delegate>\n        }\n\n    type TypeBuilder<'a> = TypeBuilderState -> TypeBuilderState * 'a\n\n    [<AutoOpen>]\n    module NewType =\n\n        module DelegateTypes =\n            type FuncVal<'a> = delegate of unit -> 'a\n            type FuncVal<'a, 'b> = delegate of 'a -> 'b\n            type FuncRef<'a, 'b> = delegate of byref<'a> -> 'b\n\n\n        let private getDelegateType (args : list<Type>) (ret : Type) =\n            let arr = System.Collections.Generic.List()\n            arr.AddRange args\n            arr.Add ret\n            System.Linq.Expressions.Expression.GetDelegateType(arr.ToArray())\n\n\n\n        type Type with\n            member x.GetMethod(name : string, args : Type[], ret : Type) =\n                let mi = x.GetMethod(name, BindingFlags.All, Type.DefaultBinder, args, null)\n                if isNull mi || mi.ReturnType <> ret then\n                    let baseMeth =\n                        if isNull x.BaseType then null\n                        else x.BaseType.GetMethod(name, args, ret)\n\n                    if isNull baseMeth then\n                        let iface = x.GetInterfaces()\n                        let inner = \n                            iface |> Seq.tryPick (fun i ->\n                                let m = i.GetMethod(name, args, ret)\n                                if isNull m then None\n                                else Some m\n                            )\n                        match inner with\n                            | Some m -> m\n                            | None -> null\n                    else\n                        baseMeth\n                else\n                    mi\n\n            member x.GetMethod(mb : MethodBuilder) =\n                let ret = mb.ReturnType\n                let args = mb.GetParameters() |> Array.map (fun p -> p.ParameterType)\n                x.GetMethod(mb.Name, args, ret)\n\n\n        let inh (t : Type) =\n            fun s ->\n                s.builder.SetParent t\n                s, ()\n\n        let fld (name : string) (t : Type) =\n            fun (b : TypeBuilderState) ->\n                let fld = b.builder.DefineField(name, t, FieldAttributes.Public)\n                b, fld\n\n        let sfld (name : string) (t : Type) =\n            fun (b : TypeBuilderState) ->\n                let fld = b.builder.DefineField(name, t, FieldAttributes.Public ||| FieldAttributes.Static)\n                b, fld\n\n        let private recmemint (r : Type) (n : string) (a : list<Type>) (body : MethodInfo -> CodeGen<unit>) : TypeBuilder<MethodBuilder> =\n            fun (b : TypeBuilderState) ->\n                let mutable b = b\n                let args = b.baseType::a\n                let fieldType = \n                    getDelegateType args r\n//                    if r = typeof<System.Void> then\n//                        let actionType = Type.GetType(typedefof<Action<_>>.FullName.Replace(\"1\", string args.Length))\n//                        actionType.MakeGenericType args\n//                    else\n//                        let funcType = Type.GetType(typedefof<Func<_>>.FullName.Replace(\"1\", string (1 + args.Length)))\n//                        funcType.MakeGenericType (Array.append args [|r|])\n\n\n\n                let fieldName = \"s_\" + n\n\n                let field = \n                    b.builder.DefineField(\n                        fieldName, fieldType, \n                        FieldAttributes.Static ||| FieldAttributes.Private ||| FieldAttributes.InitOnly\n                    )\n\n\n                let args = List.toArray a\n                let meth = \n                    b.builder.DefineMethod(\n                        n, MethodAttributes.Public ||| MethodAttributes.Virtual,\n                        CallingConventions.Standard,\n                        r,\n                        args\n                    )\n\n                let il = meth.GetILGenerator()\n\n                il.Emit(OpCodes.Ldsfld, field)\n                il.Emit(OpCodes.Ldarg_0)\n                for i in 0..args.Length-1 do\n                    il.Emit(OpCodes.Ldarg, i + 1)\n                il.EmitCall(OpCodes.Callvirt, fieldType.GetMethod \"Invoke\", null)\n                il.Emit(OpCodes.Ret)\n\n                let baseMeth = b.builder.BaseType.GetMethod(n, args, r)\n\n                if not (isNull baseMeth) then\n                    b.builder.DefineMethodOverride(meth, baseMeth)\n\n                let code (t : Type) = \n                    let mi = t.GetMethod(meth)\n                    let code =\n                        body mi\n                            |> CodeGen.run\n                            |> List.map (fun i ->\n                                match i with\n                                    | Call mi ->\n                                        match mi with\n                                            | :? MethodBuilder as mb ->\n                                                let mi = t.GetMethod(mb)\n                                                Call mi\n                                            | _ -> i\n\n                                    | Ldfld fb ->\n                                        match fb with\n                                            | :? FieldBuilder as fb ->\n                                                let f = t.GetField(fb.Name, BindingFlags.All ||| BindingFlags.Static)\n                                                Ldfld f\n                                            | _ -> i\n                                    | i -> i\n                            )\n\n                    code |> Assembler.assembleDelegateInternal fieldType\n\n                { b with delegates = HashMap.add field code b.delegates }, meth\n\n        let recmem (r : Type) (n : string) (a : list<Type>) (body : MethodInfo -> CodeGen<unit>) =\n            fun s -> \n                let (s,_) = recmemint r n a body s\n                s, ()\n        \n        let mem (r : Type) (n : string) (a : list<Type>) (body : CodeGen<unit>) =\n            fun s -> \n                let (s,_) = recmemint r n a (fun _ -> body) s\n                s, ()\n\n        let iface (iface : Type) (impl : list<Type * string * list<Type> * CodeGen<unit>>) : TypeBuilder<unit> =\n            fun (b : TypeBuilderState) ->\n                let mutable b = b\n                b.builder.AddInterfaceImplementation(iface)\n\n                for r,n,a,body in impl do\n                    \n                    let s,meth = recmemint r n a (fun _ -> body) b\n\n                    let prototype = iface.GetMethod(n,List.toArray a,r)\n                    if not (isNull prototype) then\n                        b.builder.DefineMethodOverride(meth, prototype)\n                    \n                    b <- s\n\n                b, ()\n\n\n        let ctor (args : list<Type>) (body : CodeGen<unit>) : TypeBuilder<unit> =\n            fun (b : TypeBuilderState) ->\n                \n                let ctor = \n                    b.builder.DefineConstructor(\n                        MethodAttributes.Public,\n                        CallingConventions.Standard,\n                        List.toArray args\n                    )\n\n                let il = ctor.GetILGenerator()\n\n                body \n                    |> CodeGen.run \n                    |> Assembler.assembleTo il\n\n\n                b,()\n\n\n        type NewTypeBuilder() =\n            let bAss =\n                AssemblyBuilder.DefineDynamicAssembly(\n                    AssemblyName \"asdsads\",\n                    AssemblyBuilderAccess.Run\n                )\n\n            let bMod = bAss.DefineDynamicModule(\"MainModule\")\n\n            member x.Zero() : TypeBuilder<unit> = fun s -> s,()\n\n            member x.Yield(u : unit) = x.Zero()\n\n            member x.For(m : seq<'a>, f : 'a -> TypeBuilder<unit>) : TypeBuilder<unit> =\n                fun (b : TypeBuilderState) ->\n                    let mutable c = b\n                    for e in m do\n                        let (s,()) = f e c\n                        c <- s\n                    c, ()\n\n            member x.Combine(l : TypeBuilder<unit>, r : TypeBuilder<'a>) =\n                fun b ->\n                    let (b,()) = l b\n                    r b\n\n            member x.Delay(f : unit -> TypeBuilder<'a>) =\n                fun b -> f () b\n\n\n            member x.Bind (m : TypeBuilder<'a>, f : 'a -> TypeBuilder<'b>) : TypeBuilder<'b> =\n                fun (b : TypeBuilderState) ->\n                    let (b, v) = m b\n                    (f v) b\n\n            member x.Return v =\n                fun (b : TypeBuilderState) -> b,v\n\n            member x.Run(b : TypeBuilderState -> TypeBuilderState * unit) =\n                let bType = bMod.DefineType(Guid.NewGuid() |> string)\n                let (s, ()) = b { baseType = typeof<obj>; builder = bType; delegates = HashMap.empty }\n\n                let t = s.builder.CreateTypeInfo()\n\n                for (v,k) in HashMap.toSeq s.delegates do\n                    let f = t.GetField(v.Name, BindingFlags.Static ||| BindingFlags.NonPublic)\n                    f.SetValue(null, k t)\n\n                t :> Type\n\n        let newtype = NewTypeBuilder()\n\n#nowarn \"9\"\n#nowarn \"51\"\n\nmodule Serializer =\n    \n    [<CustomEquality; NoComparison>]\n    type R<'a when 'a : not struct> =\n        struct\n            val mutable public Value : 'a\n\n            override x.GetHashCode() = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(x.Value)\n            override x.Equals o =\n                match o with\n                    | :? R<'a> as o -> Object.ReferenceEquals(x.Value, o.Value)\n                    | _ -> false\n\n            new(v) = { Value = v }\n        end\n\n    type RefMap<'a, 'b when 'a : not struct> = private { store : HashMap<R<'a>, 'b> }\n\n    module RefMap =\n        type private EmptyImpl<'a, 'b when 'a : not struct>() =\n            static let instance = { store = HashMap.empty<R<'a>, 'b> }\n            static member Instance = instance\n\n        let empty<'a, 'b when 'a : not struct> = EmptyImpl<'a, 'b>.Instance\n\n        let add (key : 'a) (value : 'b) (m : RefMap<'a, 'b>) =\n            { store = HashMap.add (R key) value m.store }\n\n        let remove (key : 'a) (m : RefMap<'a, 'b>) =\n            { store = HashMap.remove (R key) m.store }\n\n        let containsKey (key : 'a) (m : RefMap<'a, 'b>) =\n            HashMap.containsKey (R key) m.store\n\n        let update (key : 'a) (f : Option<'b> -> 'b) (m : RefMap<'a, 'b>) =\n            let key = R key\n            { store = HashMap.update key f m.store }\n\n        let tryFind (key : 'a) (m : RefMap<'a, 'b>) =\n            HashMap.tryFind (R key) m.store\n\n    type IStore =\n        abstract member TryLoad     : Guid * byref<'a> -> bool\n        abstract member TryStore    : 'a * byref<Guid> -> bool\n\n    type NopStore private () =\n        static let instance = NopStore() :> IStore\n        static member Instance = instance\n        interface IStore with\n            member x.TryLoad(_,_) = false\n            member x.TryStore(_,_) = false\n\n\n    type CoderState =\n        {\n            debug           : bool\n            isReading       : bool\n            externalStore   : IStore\n            references      : RefMap<obj, Guid>\n            values          : Map<Guid, obj>\n            namestack       : list<string>\n        }\n\n    type Coder<'a> = { code : CoderState -> CoderState * 'a }\n\n\n    type CoderBuilder() =\n        member x.Bind(m : Coder<'a>, f : 'a -> Coder<'b>) =\n            { code = fun s ->\n                let (s,v) = m.code s\n                (f v).code s\n            }\n        \n        member x.Return(v : 'a) =\n            { code = fun s -> s, v }\n\n        member x.ReturnFrom(c : Coder<'a>) =\n            c\n\n        member x.Zero() =\n            { code = fun s -> s, () }\n\n        member x.Delay(f : unit -> Coder<'a>) =\n            { code = fun s -> f().code s }\n\n        member x.Combine (l : Coder<unit>, r : Coder<'a>) =\n            { code = fun s ->\n                let (s,()) = l.code s\n                r.code s\n            }\n\n        member x.For(elements : seq<'a>, f : 'a -> Coder<unit>) =\n            { code = fun s ->\n                let mutable c = s\n                for e in elements do\n                    let (s, ()) = (f e).code c\n                    c <- s\n                c, ()\n            }\n\n        member x.While(guard : unit -> bool, body : Coder<unit>) =\n            { code = fun s ->\n                let mutable c = s\n                \n                while guard() do\n                    let (s,()) = body.code c\n                    c <- s\n                    \n                c, ()    \n                \n            }\n\n    let code = CoderBuilder()\n\n\n\n    type IReader =\n        abstract member ReadPrimitive<'a when 'a : unmanaged> : unit -> 'a\n        abstract member ReadBool : unit -> bool\n        abstract member ReadString : unit -> string\n\n    type IWriter =\n        abstract member WritePrimitive<'a when 'a : unmanaged> : 'a -> unit\n        abstract member WriteBool : bool -> unit\n        abstract member WriteString : string -> unit\n\n    type IValueCoder =\n        abstract member WriteAny : IWriter * 'b -> Coder<unit>\n        abstract member ReadAny : IReader -> Coder<'b>\n\n    type IValueCoder<'a> =\n        abstract member Write : IWriter * 'a -> Coder<unit>\n        abstract member Read : IReader -> Coder<'a>\n\n    module Coder =\n        let map (f : 'a -> 'b) (m : Coder<'a>) = \n            { code = fun s ->\n                let (s,v) = m.code s\n                s, f v\n            }\n\n        let state = { code = fun s -> s,s }\n        let put (s : CoderState) = { code = fun _ -> s,() }\n        let modify (f : CoderState -> CoderState) = { code = fun s -> f s,() }\n        let custom (f : CoderState -> CoderState * 'a) = { code = f }\n\n        let tryStore (value : 'a) =\n            { code = fun s ->\n                if isNull (value :> obj) then\n                    s, (false, Guid.Empty)\n                else\n                    let mutable id = Guid.Empty\n                    if s.externalStore.TryStore(value, &id) then\n                        s, (false, id)\n                    else\n                        let v = value :> obj\n                        match RefMap.tryFind v s.references with\n                            | Some r -> \n                                s, (false, r)\n                            | None ->\n                                let id = Guid.NewGuid()\n                                let s = { s with references = RefMap.add v id s.references }\n                                s, (true, id)\n            }\n\n\n        let tryLoad (id : Guid) : Coder<Option<'a>> =\n            { code = fun s ->\n                if id = Guid.Empty then\n                    s, Some (Unchecked.defaultof<'a>)\n                else\n                    let mutable value = Unchecked.defaultof<'a>\n                    if s.externalStore.TryLoad(id, &value) then\n                        s, Some value\n                    else\n                        match Map.tryFind id s.values with\n                            | Some (:? 'a as v) -> \n                                s, Some v\n                            | _ ->\n                                s, None\n            } \n\n        let tryStoreLocal (value : 'a) =\n            { code = fun s ->\n                if isNull (value :> obj) then\n                    s, (false, Guid.Empty)\n                else\n                    let v = value :> obj\n                    match RefMap.tryFind v s.references with\n                        | Some r -> \n                            s, (false, r)\n                        | None ->\n                            let id = Guid.NewGuid()\n                            let s = { s with references = RefMap.add v id s.references }\n                            s, (true, id)\n            }\n\n        let tryLoadLocal (id : Guid) : Coder<Option<'a>> =\n            { code = fun s ->\n                if id = Guid.Empty then\n                    s, Some (Unchecked.defaultof<'a>)\n                else\n                    match Map.tryFind id s.values with\n                        | Some (:? 'a as v) -> \n                            s, Some v\n                        | _ ->\n                            s, None\n            } \n\n\n        let storeValue (id : Guid) (v : 'a) =\n            { code = fun s ->\n                if id = Guid.Empty then s, ()\n                else { s with values = Map.add id (v :> obj) s.values }, ()\n            }\n\n\n        let pushName n = \n            { code = fun s -> \n                if s.debug then Log.start \"%s\" n\n                { s with namestack = n::s.namestack }, () \n            }\n\n        let popName = \n            { code = fun s -> \n                if s.debug then Log.stop()\n                { s with namestack = List.tail s.namestack }, () \n            }\n\n\n\n    \n\n\n\n    [<AttributeUsage(AttributeTargets.Field ||| AttributeTargets.Property)>]\n    type StoreExternAttribute() = inherit Attribute()\n\n    [<AutoOpen>]\n    module TypePropertyExtensions =\n        open System.Runtime.InteropServices\n        open System.Collections.Concurrent\n\n        type private TypePropertyImpl<'a> private() =\n            static let isBlittable =\n                if typeof<'a>.IsValueType then\n                    try\n                        let gc = GCHandle.Alloc(Unchecked.defaultof<'a>, GCHandleType.Pinned)\n                        gc.Free()\n                        true\n                    with _ ->\n                        false\n                else\n                    false\n\n            static member IsBlittable = isBlittable\n\n        let blittable<'a> = TypePropertyImpl<'a>.IsBlittable\n\n        let private blittableCache = ConcurrentDictionary<Type, bool>()\n\n        type Type with\n            member x.IsBlittable =\n                blittableCache.GetOrAdd(x, fun x ->\n                    let tb = typedefof<TypePropertyImpl<_>>.MakeGenericType [|x|]\n                    let prop = tb.GetProperty(\"IsBlittable\", BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic)\n                    prop.GetValue(null) |> unbox<bool>\n                )\n\n\n    module ValueCoders = \n        open TypeBuilder\n        open Microsoft.FSharp.Reflection\n\n        [<AbstractClass>]\n        type AbstractValueCoder<'a>() =\n            abstract member Read : IReader -> Coder<'a>\n            abstract member Write : IWriter * 'a -> Coder<unit>\n\n\n            interface IValueCoder with\n                member x.ReadAny r = \n                    x.Read r |> Coder.map unbox\n\n                member x.WriteAny(w,v) = \n                    x.Write(w,unbox v)\n\n            interface IValueCoder<'a> with\n                member x.Read r = x.Read r\n                member x.Write(w,v) = x.Write(w,v)\n\n        type BoolCoder() =\n            inherit AbstractValueCoder<bool>()\n            override x.Read (r : IReader) = code { return r.ReadBool() }\n            override x.Write(w,v) = code { w.WriteBool(v) }\n\n        type StringCoder() =\n            inherit AbstractValueCoder<string>()\n            override x.Read (r : IReader) = code { return r.ReadString() }\n            override x.Write(w,v) = code { w.WriteString(v) }\n\n        type PrimitiveValueCoder<'a when 'a : unmanaged>() =\n            inherit AbstractValueCoder<'a>()\n\n            override x.Read (r : IReader) = code { return r.ReadPrimitive() }\n            override x.Write(w,v) = code { w.WritePrimitive(v) }\n\n\n        [<AbstractClass>]\n        type ReferenceCoder<'a>() =\n            inherit AbstractValueCoder<'a>()\n\n            abstract member CreateEmptyInstance : unit -> 'a\n            abstract member ReadRef : IReader * 'a -> Coder<unit>\n            abstract member WriteRef : IWriter * 'a -> Coder<unit>\n\n            default x.CreateEmptyInstance() =\n#if NET8_0_OR_GREATER\n                System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof<'a>) |> unbox<'a>\n#else\n                System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(typeof<'a>) |> unbox<'a>\n#endif\n\n            override x.Read(r : IReader) =\n                code {\n                    let id = r.ReadPrimitive()\n                    let! res = Coder.tryLoad id \n                    match res with\n                        | Some v -> return v\n                        | None ->\n                            let i = x.CreateEmptyInstance()\n                            do! Coder.storeValue id i\n                            do! x.ReadRef(r, i)\n                            return i\n                }\n\n            override x.Write(w : IWriter, value : 'a) =\n                code {\n                    let! (isNew, id) = Coder.tryStore value\n                    w.WritePrimitive id\n\n                    if isNew then\n                        do! x.WriteRef(w, value)\n\n                }\n\n\n        type TypeCoder() =\n            inherit AbstractValueCoder<Type>()\n            override x.Read (r : IReader) = \n                code { \n                    let name = r.ReadString() \n                    return Type.GetType name\n                }\n\n            override x.Write(w,v) = \n                code { \n                    w.WriteString(v.AssemblyQualifiedName)\n                }\n\n        type PrimitiveArrayCoder<'a when 'a : unmanaged>() =\n            inherit AbstractValueCoder<'a[]>()\n\n            override x.Read (r : IReader) =\n                let read () =\n                    let cnt = r.ReadPrimitive()\n                    let arr = Array.zeroCreate cnt\n                    for i in 0..arr.Length-1 do\n                        arr.[i] <- r.ReadPrimitive()\n                    arr\n                code { return read() }\n\n            override x.Write(w,v) =\n                let write() =\n                    w.WritePrimitive v.Length\n                    for e in v do w.WritePrimitive e\n\n                code { write() }\n\n        type ExternArrayCoder<'a>(resolve : Type * FieldInfo -> IValueCoder) =\n            inherit AbstractValueCoder<'a[]>()\n\n            let valueCoder = resolve (typeof<'a>, null) |> unbox<IValueCoder<'a>>\n\n            override x.Read (r : IReader) = \n                code {\n                    \n                    let id = r.ReadPrimitive()\n                    let! v = Coder.tryLoad id\n\n                    match v with\n                        | Some v -> return v\n                        | _ ->\n                            do! Coder.pushName \"Length\"\n                            let cnt = r.ReadPrimitive()\n                            do! Coder.popName\n\n                            let arr = Array.zeroCreate cnt\n                            do! Coder.storeValue id arr\n                            do! Coder.pushName \"Data\"\n                            for i in 0..arr.Length - 1 do\n                                let! v = valueCoder.Read(r)\n                                arr.[i] <- v\n                            do! Coder.popName\n\n                            return arr\n                }\n\n            override x.Write(w,v) =\n                code {\n                    let! (isNew, id) = Coder.tryStore v\n                    w.WritePrimitive id\n\n                    if isNew then\n                        do! Coder.pushName \"Length\"\n                        w.WritePrimitive v.Length\n                        do! Coder.popName\n                        \n                        do! Coder.pushName \"Data\"\n                        for e in v do\n                            do! valueCoder.Write(w, e)\n                        do! Coder.popName\n\n                }\n\n        type InlineArrayCoder<'a>(resolve : Type * FieldInfo -> IValueCoder) =\n            inherit AbstractValueCoder<'a[]>()\n\n            let valueCoder = resolve (typeof<'a>, null) |> unbox<IValueCoder<'a>>\n\n            override x.Read (r : IReader) = \n                code {\n                    do! Coder.pushName \"Length\"\n                    let cnt = r.ReadPrimitive()\n                    let arr = Array.zeroCreate cnt\n                    do! Coder.popName\n\n                    \n                    do! Coder.pushName \"Data\"\n                    for i in 0..arr.Length - 1 do\n                        let! v = valueCoder.Read(r)\n                        arr.[i] <- v\n                    do! Coder.popName\n\n                    return arr\n                }\n\n            override x.Write(w,v) =\n                code {\n                    \n                    do! Coder.pushName \"Length\"\n                    w.WritePrimitive v.Length\n                    do! Coder.popName\n                    \n                    do! Coder.pushName \"Data\"\n                    for e in v do\n                        do! valueCoder.Write(w, e)\n                    do! Coder.popName\n\n                }\n\n        type private Marker =\n            class\n                val mutable public DynamicValue : obj\n            end\n\n        let dynValue = typeof<Marker>.GetField(\"DynamicValue\", BindingFlags.All)\n\n        type DynamicCoder<'a>(resolve : Type * FieldInfo -> IValueCoder) =\n            inherit AbstractValueCoder<'a>()\n\n            let typeCoder = resolve (typeof<Type>, null) |> unbox<IValueCoder<Type>>\n            \n\n            override x.Read(r) =\n                code {\n                    do! Coder.pushName \"Type\"\n                    let! t = typeCoder.Read r\n                    do! Coder.popName \n                    if isNull t then\n                        return Unchecked.defaultof<'a>\n                    else\n                        do! Coder.pushName \"Value\"\n                        let coder = resolve(t.MakeByRefType(), null)\n                        let! res = coder.ReadAny(r)\n                        do! Coder.popName\n                        return res\n                }\n\n            override x.Write(w,v) =\n                code {\n                    do! Coder.pushName \"Type\"\n                    if isNull (v :> obj) then\n                        do! typeCoder.Write(w, null)\n                        do! Coder.popName \n                    else\n                        let t = v.GetType()\n                        do! typeCoder.Write(w, t)\n                        do! Coder.popName \n\n                        do! Coder.pushName \"Value\"\n                        let coder = resolve(t.MakeByRefType(), null)\n                        do! coder.WriteAny(w,v)\n                        do! Coder.popName\n                }\n            \n\n\n        module AutoCoder = \n            type Helpers() =\n                static member NewObj() : 'a =\n#if NET8_0_OR_GREATER\n                    System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof<'a>) |> unbox<'a>\n#else\n                    System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(typeof<'a>) |> unbox<'a>\n#endif\n\n            [<AbstractClass>]\n            type AbstractStateCoder<'a>() =\n                inherit AbstractValueCoder<'a>()\n\n                override x.Read r =\n                    { code = fun s ->\n                        let s = ref s\n                        let v = x.ReadState(r, s)\n                        !s, v\n                    }\n\n                override x.Write(w,v) =\n                    { code = fun s ->\n                        let s = ref s\n                        x.WriteState(w, v, s)\n                        !s, ()\n                    }\n\n                abstract member ReadState : IReader * byref<CoderState> -> 'a\n                abstract member WriteState : IWriter * 'a * byref<CoderState> -> unit\n\n            [<AbstractClass>]\n            type AbstractStateReferenceCoder<'a when 'a : not struct>() =\n                inherit ReferenceCoder<'a>()\n\n                override x.ReadRef(r,v) =\n                    { code = fun s ->\n                        let s = ref s\n                        let v = x.ReadState(r, v, s)\n                        !s, ()\n                    }\n\n                override x.WriteRef(w,v) =\n                    { code = fun s ->\n                        let s = ref s\n                        x.WriteState(w, v, s)\n                        !s, ()\n                    }\n\n                abstract member ReadState : IReader * 'a * byref<CoderState> -> unit\n                abstract member WriteState : IWriter * 'a * byref<CoderState> -> unit\n\n\n            let private invoke = typeof<Type * FieldInfo -> IValueCoder>.GetMethod(\"Invoke\", [| typeof<Type * FieldInfo> |])\n\n\n            let createFieldCoder (t : Type) =\n                let fields = t.GetFields(BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Instance)\n\n                let baseType = typedefof<AbstractStateCoder<_>>.MakeGenericType [|t|]\n                let resType = typedefof<Coder<_>>.MakeGenericType [|t|]\n                let baseCtor = baseType.GetConstructor [||]\n            \n                let unitCoderType = typeof<Coder<unit>>\n\n                let types = fields |> Array.map (fun f -> f)\n\n                let newInstance = typeof<Helpers>.GetMethod(\"NewObj\").MakeGenericMethod [|t|]\n\n                let coderFields =\n                    fields |> Array.map (fun fi ->\n                        let fieldType = typedefof<IValueCoder<_>>.MakeGenericType [|fi.FieldType|]\n\n                        fieldType, fi.Name, fi\n                    )\n\n                let stateType = typeof<CoderState>.MakeByRefType()\n                //let refContents = typeof<ref<SerializerState>>.GetField(\"contents@\")\n\n                newtype {\n                    do! inh baseType\n\n                    let cf = Array.zeroCreate coderFields.Length\n                    for i in 0..coderFields.Length-1 do\n                        let (t,n,f) = coderFields.[i]\n                        let! h = fld n t\n                        cf.[i] <- (h :> FieldInfo, f)\n                        ()\n\n                    do! mem typeof<System.Void> \"WriteState\" [typeof<IWriter>; t; stateType] (\n                            codegen {\n                                for (coderField, field) in cf do\n                                    let tupType = typeof<CoderState *unit>\n                                    let codeType = typeof<CoderState -> CoderState *unit>\n\n                                    do! IL.ldarg 0\n                                    do! IL.ldfld coderField\n\n                                    do! IL.ldarg 1\n\n                                    do! IL.ldarg 2\n                                    do! IL.ldfld field\n\n                                    do! IL.call (coderField.FieldType.GetMethod \"Write\")\n                                    do! IL.call (unitCoderType.GetProperty(\"code\").GetMethod)\n\n\n                                    let! tup = IL.newlocal tupType\n                                    do! IL.ldarg 3\n                                    do! IL.ldind ValueType.Object\n                                    do! IL.call (codeType.GetMethod \"Invoke\")\n                                    do! IL.stloc tup\n\n                                    do! IL.ldarg 3\n                                    do! IL.ldloc tup\n                                    do! IL.call (tupType.GetProperty(\"Item1\").GetMethod)\n                                    do! IL.stind ValueType.Object\n\n\n                                do! IL.ret\n                            }\n                        )\n\n                    do! mem t \"ReadState\" [typeof<IReader>; stateType] (\n                            codegen {\n                                let! res = IL.newlocal t\n                                do! IL.call newInstance\n                                do! IL.stloc res\n\n\n                                for (coderField, field) in cf do\n                                    let resType = typedefof<Coder<_>>.MakeGenericType [|field.FieldType|]\n                                    let tupType = FSharpType.MakeTupleType [|typeof<CoderState>; field.FieldType|]\n                                    let codeType = FSharpType.MakeFunctionType(typeof<CoderState>, tupType)\n\n                                    do! IL.ldarg 0\n                                    do! IL.ldfld coderField\n\n                                    do! IL.ldarg 1\n                                    do! IL.call (coderField.FieldType.GetMethod \"Read\")\n                                    do! IL.call (resType.GetProperty(\"code\").GetMethod)\n\n\n                                    let! tup = IL.newlocal tupType\n                                    do! IL.ldarg 2\n                                    do! IL.ldind ValueType.Object\n                                    do! IL.call (codeType.GetMethod \"Invoke\")\n                                    do! IL.stloc tup\n\n                                    do! IL.ldarg 2\n                                    do! IL.ldloc tup\n                                    do! IL.call (tupType.GetProperty(\"Item1\").GetMethod)\n                                    do! IL.stind ValueType.Object\n\n\n                                    do! IL.ldloc res\n                                    do! IL.ldloc tup\n                                    do! IL.call (tupType.GetProperty(\"Item2\").GetMethod)\n                                    do! IL.stfld field\n\n\n                                do! IL.ldloc res\n                                do! IL.ret\n                            }\n                        )\n\n                    do! ctor [typeof<Type * FieldInfo -> IValueCoder> ] (\n                            codegen {\n                                do! IL.ldarg 0\n                                do! IL.call baseCtor\n\n                                for (coder, f) in cf do\n                                    do! IL.ldarg 0\n                                \n                                    do! IL.ldarg 1\n                                    do! IL.ldtoken f.FieldType\n                                    do! IL.call <@ Type.GetTypeFromHandle @>\n\n                                    do! IL.ldtoken f\n                                    do! IL.ldtoken f.DeclaringType\n                                    do! IL.call <@ FieldInfo.GetFieldFromHandle : _ * _ -> _ @>\n\n                                    do! IL.newobj (typeof<Type * FieldInfo>.GetConstructor [|typeof<Type>; typeof<FieldInfo>|])\n                                    do! IL.call invoke\n\n                                    do! IL.stfld coder\n\n\n                                do! IL.ret\n                            }\n                        )\n\n                }\n\n            let createUnionCoder (t : Type) =\n                let baseType = typedefof<AbstractStateCoder<_>>.MakeGenericType [|t|]\n\n                let cases = FSharpType.GetUnionCases (t, true) |> Array.sortBy (fun c -> c.Tag)\n                let stateType = typeof<CoderState>.MakeByRefType()\n                let tag = \n                    let prop = t.GetProperty(\"Tag\", BindingFlags.All)\n                    if isNull prop then null\n                    else prop.GetMethod\n\n                let resType = typedefof<Coder<_>>.MakeGenericType [|t|]\n                let baseCtor = baseType.GetConstructor [||]\n            \n                let unitCoderType = typeof<Coder<unit>>\n\n                let caseTypes = \n                    cases |> Array.map (fun ci ->\n                        let caseType = t.GetNestedType(ci.Name,BindingFlags.NonPublic ||| BindingFlags.Public)\n                        ci.Tag, ci\n                    )\n\n                let innerCoders =\n                    caseTypes \n                        |> Seq.collect (fun (_,ci) -> ci.GetFields() )\n                        |> Seq.map (fun fi -> fi.PropertyType)\n                        |> HashSet.ofSeq\n                        |> Seq.toArray\n\n                let coderFields =\n                    innerCoders\n                        |> Array.mapi (fun i ft ->\n                            let name = sprintf \"m_coder%d\" i\n                            let t = typedefof<IValueCoder<_>>.MakeGenericType [|ft|]\n                            name, t, ft\n                        )\n\n                let coderFieldIndex =\n                    innerCoders \n                        |> Array.mapi (fun i t -> t,i)\n                        |> Dictionary.ofArray\n\n                newtype {\n                    do! inh baseType\n                    \n                    let cf = Array.zeroCreate coderFields.Length\n                    for i in 0..coderFields.Length-1 do\n                        let (n,t,valueType) = coderFields.[i]\n                        let! h = fld n t\n                        cf.[i] <- valueType, h :> FieldInfo\n                        ()\n\n                    let getCf (t : Type) =\n                        cf.[coderFieldIndex.[t]] |> snd\n\n\n                    do! mem typeof<System.Void> \"WriteState\" [typeof<IWriter>; t; stateType] (\n                            codegen {\n                                do! IL.ldarg 2\n                                do! IL.call tag\n\n                                let labels = Array.zeroCreate cases.Length\n                                for i in 0..cases.Length-1 do\n                                    let! li = IL.newlabel \n                                    labels.[i] <- li\n\n\n\n                                do! IL.Switch labels\n                                do! IL.ret\n\n                                for c in cases do\n                                    do! IL.mark labels.[c.Tag]\n\n                                    do! IL.ldarg 1\n                                    do! IL.ldconst c.Tag\n                                    do! IL.call <@ fun (w : IWriter) -> w.WritePrimitive(0) @>\n\n                                    let fields = c.GetFields()\n\n                                    for f in fields do\n                                        let tupType = typeof<CoderState * unit>\n                                        let codeType = typeof<CoderState -> CoderState * unit>\n\n                                        let cf = getCf f.PropertyType\n                                        do! IL.ldarg 0\n                                        do! IL.ldfld cf\n\n                                        do! IL.ldarg 1\n\n                                        do! IL.ldarg 2\n                                        do! IL.call f.GetMethod\n\n                                        do! IL.call (cf.FieldType.GetMethod \"Write\")\n                                        do! IL.call (unitCoderType.GetProperty(\"code\").GetMethod)\n\n\n                                        let! tup = IL.newlocal tupType\n                                        do! IL.ldarg 3\n                                        do! IL.ldind ValueType.Object\n                                        do! IL.call (codeType.GetMethod \"Invoke\")\n                                        do! IL.stloc tup\n\n                                        do! IL.ldarg 3\n                                        do! IL.ldloc tup\n                                        do! IL.call (tupType.GetProperty(\"Item1\").GetMethod)\n                                        do! IL.stind ValueType.Object\n\n                                    do! IL.ret\n\n\n                                ()\n                            }\n                        )\n\n                    do! mem t \"ReadState\" [typeof<IReader>; stateType] (\n                            codegen {\n                                do! IL.ldarg 1\n                                do! IL.call <@ fun (r : IReader) -> r.ReadPrimitive() : int @>\n\n                                let labels = Array.zeroCreate cases.Length\n                                for i in 0..cases.Length-1 do\n                                    let! li = IL.newlabel \n                                    labels.[i] <- li\n\n\n\n                                do! IL.Switch labels\n                                do! IL.ldnull\n                                do! IL.ret\n\n                                for c in cases do\n                                    do! IL.mark labels.[c.Tag]\n                                    // let caseType = t.GetNestedType(c.Name,BindingFlags.NonPublic ||| BindingFlags.Public)\n                                    let ctor = \n                                        let m = c.DeclaringType.GetMethod(c.Name, BindingFlags.Static ||| BindingFlags.Public)\n                                        if isNull m then\n                                            let m = c.DeclaringType.GetMethod(\"New\" + c.Name, BindingFlags.Static ||| BindingFlags.Public)\n                                            if isNull m then\n                                                let prop = c.DeclaringType.GetProperty(c.Name, BindingFlags.Static ||| BindingFlags.Public)\n                                                if isNull prop then null\n                                                else prop.GetMethod\n                                            else\n                                                m\n                                        else\n                                            m\n                                            \n                                    let fields = c.GetFields()\n\n                                    let locals = Array.zeroCreate fields.Length\n\n                                    for fi in 0..fields.Length-1 do\n                                        let f = fields.[fi]\n                                        let! loc = IL.newlocal f.PropertyType\n                                        locals.[fi] <- loc\n\n                                        let resType = typedefof<Coder<_>>.MakeGenericType [|f.PropertyType|]\n                                        let tupType = FSharpType.MakeTupleType [|typeof<CoderState>; f.PropertyType|]\n                                        let codeType = FSharpType.MakeFunctionType(typeof<CoderState>, tupType)\n                                        \n                                        let cf = getCf f.PropertyType\n\n                                        do! IL.ldarg 0\n                                        do! IL.ldfld cf\n\n                                        do! IL.ldarg 1\n\n                                        do! IL.call (cf.FieldType.GetMethod \"Read\")\n                                        do! IL.call (resType.GetProperty(\"code\").GetMethod)\n\n\n                                        let! tup = IL.newlocal tupType\n                                        do! IL.ldarg 2\n                                        do! IL.ldind ValueType.Object\n                                        do! IL.call (codeType.GetMethod \"Invoke\")\n                                        do! IL.stloc tup\n\n                                        do! IL.ldarg 2\n                                        do! IL.ldloc tup\n                                        do! IL.call (tupType.GetProperty(\"Item1\").GetMethod)\n                                        do! IL.stind ValueType.Object\n\n                                        do! IL.ldloc tup\n                                        do! IL.call (tupType.GetProperty(\"Item2\").GetMethod)\n                                        do! IL.stloc locals.[fi]\n\n\n                                    if isNull ctor then \n                                        do! IL.ldnull\n                                    else \n                                        for l in locals do\n                                            do! IL.ldloc l\n                                        \n                                        do! IL.call ctor\n\n                                    do! IL.ret\n\n\n                            }\n                        )\n\n\n                    do! ctor [typeof<Type * FieldInfo -> IValueCoder> ] (\n                            codegen {\n                                do! IL.ldarg 0\n                                do! IL.call baseCtor\n\n                                for (t,cf) in cf do\n                                    do! IL.ldarg 0\n                                \n                                    do! IL.ldarg 1\n                                    do! IL.ldtoken t\n                                    do! IL.call <@ Type.GetTypeFromHandle @>\n\n                                    do! IL.ldnull\n\n                                    do! IL.newobj (typeof<Type * FieldInfo>.GetConstructor [|typeof<Type>; typeof<FieldInfo>|])\n                                    do! IL.call invoke\n\n                                    do! IL.stfld cf\n\n\n                                do! IL.ret\n                            }\n                        )\n                }\n\n            type OptionCoder<'a>(resolve : Type * FieldInfo -> IValueCoder) =\n                inherit AbstractValueCoder<Option<'a>>()\n\n                let valueCoder = resolve(typeof<'a>, null) |> unbox<IValueCoder<'a>>\n\n                override x.Write(w,v) =\n                    code {\n                        match v with\n                            | Some v -> do! valueCoder.Write(w,v)\n                            | _ -> ()\n                    }\n\n                override x.Read(r) =\n                    code {\n                        let! v = valueCoder.Read(r)\n                        return Some v\n                    }\n\n            let private unionCoderCache = System.Collections.Concurrent.ConcurrentDictionary<Type, Type>()\n\n            let create (t : Type) =\n                \n                if FSharpType.IsUnion t then\n                    if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<Option<_>> then\n                        typedefof<OptionCoder<_>>.MakeGenericType (t.GetGenericArguments())\n                    else\n                        let tparent = \n                            if t.IsNested then t.DeclaringType\n                            else t\n\n                        let tparent = \n                            if tparent.IsGenericTypeDefinition then tparent.MakeGenericType (t.GetGenericArguments())\n                            else tparent\n\n                        unionCoderCache.GetOrAdd(tparent, createUnionCoder)\n                else\n                    createFieldCoder t\n\n    module Coders =\n        open ValueCoders\n        open System.Collections.Concurrent\n\n        let private cache = ConcurrentDictionary<Type * bool, IValueCoder>()\n        let private fieldCache = ConcurrentDictionary<Type * FieldInfo, IValueCoder>()\n\n        type private Resolver = Type * FieldInfo -> IValueCoder\n        type private Creator<'a>() =\n            static let create =\n                let coderType = typeof<'a>\n                let resolveCtor = coderType.GetConstructor [| typeof<Resolver> |]\n                let emptyCtor = coderType.GetConstructor [||]\n\n                if isNull resolveCtor then\n                    if isNull emptyCtor then failwithf \"[Resolve] cannot create coder of type %A\" coderType\n                    else \n                        let value = emptyCtor.Invoke [||] |> unbox<IValueCoder>\n                        fun (r : Resolver) -> value\n                else\n                    let d = DynamicMethod(sprintf \"Create%A\" coderType, typeof<IValueCoder>, [| typeof<Resolver> |], true)\n                    let il = d.GetILGenerator()\n\n                    il.Emit(OpCodes.Ldarg_0)\n                    il.Emit(OpCodes.Newobj, resolveCtor)\n                    il.Emit(OpCodes.Castclass, typeof<IValueCoder>)\n                    il.Emit(OpCodes.Ret)\n\n                    let creator = \n                        d.CreateDelegate(typeof<Func<Resolver, IValueCoder>>)\n                            |> unbox<Func<Resolver, IValueCoder>>\n\n\n                    fun (r : Resolver) -> creator.Invoke(r)\n\n            static member Create = create\n\n        let private creatorCache = ConcurrentDictionary<Type, Resolver -> IValueCoder>()\n\n        type FieldCoder<'a>(field : FieldInfo, inner : IValueCoder<'a>) =\n            inherit AbstractValueCoder<'a>()\n\n            override x.Write(w, v) =\n                code {\n                    do! Coder.pushName field.Name\n                    let! res = inner.Write(w,v)\n                    do! Coder.popName\n                    return res\n                }\n\n             override x.Read(r) =\n                code {\n                    do! Coder.pushName field.Name\n                    let! res = inner.Read(r)\n                    do! Coder.popName\n                    return res\n                }               \n\n        type LocalNonRecusiveRefCoder<'a>(inner : IValueCoder<'a>) =\n            inherit AbstractValueCoder<'a>()\n\n            override x.Write(w,v) =\n                code {\n                    let! (isNew,id) = Coder.tryStoreLocal v\n\n                    do! Coder.pushName \"ReferenceId\"\n                    w.WritePrimitive id\n                    do! Coder.popName\n                    \n                    \n                    if isNew then\n                        do! Coder.pushName \"ReferenceValue\"\n                        do! inner.Write(w,v)\n                        do! Coder.popName\n\n                }\n\n            override x.Read(r) =\n                code {\n                    do! Coder.pushName \"ReferenceId\"\n                    let id = r.ReadPrimitive()\n                    do! Coder.popName\n\n                    let! res = Coder.tryLoadLocal id \n                    match res with\n                        | Some v -> return v\n                        | None ->\n                            do! Coder.pushName \"ReferenceValue\"\n                            let! result = inner.Read(r)\n                            do! Coder.storeValue id result\n                            do! Coder.popName\n                            return result\n                }\n\n\n        type Copy<'a> private() =\n            static let copy =\n                let fields = typeof<'a>.GetFields(BindingFlags.All)\n\n                let copyAll =\n                    DynamicMethod(\n                        \"CopyAll\" + typeof<'a>.Name,\n                        typeof<System.Void>,\n                        [|typeof<'a>; typeof<'a>|],\n                        typeof<'a>,\n                        true\n                    )\n\n                let il = copyAll.GetILGenerator()\n\n                for f in fields do\n                    il.Emit(OpCodes.Ldarg_0)\n                    il.Emit(OpCodes.Ldarg_1)\n                    il.Emit(OpCodes.Ldfld, f)\n                    il.Emit(OpCodes.Stfld, f)\n\n\n                il.Emit(OpCodes.Ret)\n\n                copyAll.CreateDelegate(typeof<Action<'a, 'a>>)\n                    |> unbox<Action<'a, 'a>>\n\n            static member Copy(target : 'a, source : 'a) =\n                copy.Invoke(target, source)\n\n        type LocalRefCoder<'a>(inner : IValueCoder<'a>) =\n            inherit AbstractValueCoder<'a>()\n\n\n            override x.Write(w,v) =\n                code {\n                    let! (isNew,id) = Coder.tryStoreLocal v\n\n                    do! Coder.pushName \"ReferenceId\"\n                    w.WritePrimitive id\n                    do! Coder.popName\n                    \n                    \n                    if isNew then\n                        do! Coder.pushName \"ReferenceValue\"\n                        do! inner.Write(w,v)\n                        do! Coder.popName\n\n                }\n\n            override x.Read(r) =\n                code {\n                    do! Coder.pushName \"ReferenceId\"\n                    let id = r.ReadPrimitive()\n                    do! Coder.popName\n\n                    let! res = Coder.tryLoadLocal id \n                    match res with\n                        | Some v -> return v\n                        | None ->\n                            do! Coder.pushName \"ReferenceValue\"\n#if NET8_0_OR_GREATER\n                            let res = System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof<'a>) |> unbox<'a>\n#else\n                            let res = System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject typeof<'a> |> unbox<'a>\n#endif\n                            do! Coder.storeValue id res\n\n                            let! result = inner.Read(r)\n                            Copy<'a>.Copy(res, result)\n                            \n\n                            do! Coder.popName\n                            return res\n                }\n\n        type ExternRefCoder<'a>(inner : IValueCoder<'a>) =\n            inherit AbstractValueCoder<'a>()\n\n            override x.Write(w,v) =\n                code {\n                    let! (isNew,id) = Coder.tryStore v\n\n                    do! Coder.pushName \"ReferenceId\"\n                    w.WritePrimitive id\n                    do! Coder.popName\n                    \n                    \n                    if isNew then\n                        do! Coder.pushName \"ReferenceValue\"\n                        do! inner.Write(w,v)\n                        do! Coder.popName\n\n                }\n\n            override x.Read(r) =\n                code {\n                    do! Coder.pushName \"ReferenceId\"\n                    let id = r.ReadPrimitive()\n                    do! Coder.popName\n\n                    let! res = Coder.tryLoad id \n                    match res with\n                        | Some v -> return v\n                        | None ->\n                            do! Coder.pushName \"ReferenceValue\"\n#if NET8_0_OR_GREATER\n                            let res = System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof<'a>) |> unbox<'a>\n#else\n                            let res = System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject typeof<'a> |> unbox<'a>\n#endif\n                            do! Coder.storeValue id res\n\n                            let! result = inner.Read(r)\n                            Copy<'a>.Copy(res, result)\n                            \n\n                            do! Coder.popName\n                            return res\n                }\n\n\n        let rec resolve (t : Type) (inlineStore : bool) : IValueCoder =\n            let createCoder (coderType : Type) =\n                let creator = \n                    creatorCache.GetOrAdd(coderType, Func<_,_>(fun t ->\n                        let tc = typedefof<Creator<_>>.MakeGenericType [|t|]\n                        tc.GetProperty(\"Create\", BindingFlags.Static ||| BindingFlags.All).GetValue(null) |> unbox<Resolver -> IValueCoder>\n                    ))\n                creator (uncurry getField)\n\n\n            let isGround, t = \n                if t.IsValueType then true, t\n                elif t.IsByRef then true, t.GetElementType()\n                elif Microsoft.FSharp.Reflection.FSharpType.IsUnion t then true, t\n                else false, t\n\n            let wrapRef (c : IValueCoder) =\n                if t.IsValueType then \n                    c\n\n                elif typeof<Type>.IsAssignableFrom t || t.IsArray  then\n                    let decorator = typedefof<LocalNonRecusiveRefCoder<_>>.MakeGenericType [|t|]\n                    Activator.CreateInstance(decorator, [|c :> obj|]) |> unbox<IValueCoder>\n                    \n                elif Microsoft.FSharp.Reflection.FSharpType.IsUnion t then\n                    c\n\n                else\n                    if inlineStore then\n                        let decorator = typedefof<LocalRefCoder<_>>.MakeGenericType [|t|]\n                        Activator.CreateInstance(decorator, [|c :> obj|]) |> unbox<IValueCoder>\n                    else\n                        let decorator = typedefof<ExternRefCoder<_>>.MakeGenericType [|t|]\n                        Activator.CreateInstance(decorator, [|c :> obj|]) |> unbox<IValueCoder>\n                        \n            let typeCoder =\n                if t = typeof<bool> then\n                    BoolCoder() :> IValueCoder\n\n                elif t = typeof<string> then\n                    StringCoder() :> IValueCoder\n\n                elif typeof<Type>.IsAssignableFrom t then\n                    TypeCoder() \n                        |> wrapRef\n\n                elif t.IsBlittable then\n                    typedefof<PrimitiveValueCoder<int>>.MakeGenericType [|t|]\n                        |> createCoder\n\n                elif t.IsArray then\n                    let et = t.GetElementType()\n\n                    if et.IsBlittable then \n                        typedefof<PrimitiveArrayCoder<int>>.MakeGenericType [|et|]\n                            |> createCoder\n                            |> wrapRef\n                    else \n                        if inlineStore then \n                            typedefof<InlineArrayCoder<_>>.MakeGenericType [|et|]\n                                |> createCoder\n                                |> wrapRef\n                        else \n                            typedefof<ExternArrayCoder<_>>.MakeGenericType [|et|]\n                                |> createCoder\n\n                else\n                    if isGround then\n                        AutoCoder.create t\n                            |> createCoder\n                            |> wrapRef\n                    else\n                        typedefof<DynamicCoder<_>>.MakeGenericType [|t|]\n                            |> createCoder\n\n            typeCoder\n\n        and get (t : Type) (inlineStore : bool) : IValueCoder = \n            let isNew = ref false\n            let res =\n                cache.GetOrAdd((t, inlineStore), Func<_,_>(fun (a,b) ->\n                    isNew := true\n                    resolve a b\n                ))\n\n            res\n\n\n        and getField (t : Type) (f : FieldInfo) : IValueCoder =\n            let wrapField (c : IValueCoder) =\n                if isNull f then \n                    c\n                else\n                    let decorator = typedefof<FieldCoder<_>>.MakeGenericType [|t|]\n                    Activator.CreateInstance(decorator, [|f :> obj; c :> obj|]) |> unbox<IValueCoder>\n            \n\n            fieldCache.GetOrAdd((t, f), Func<_,_>(fun (t : Type ,f : FieldInfo) ->\n                let inlineStore = isNull f || f.GetCustomAttributes<StoreExternAttribute>() |> Seq.isEmpty\n                let inner = get t inlineStore\n                wrapField inner\n            ))\n\n\n\n        type private Coder<'a> private() =\n            static let res = lazy ( get typeof<'a> true |> unbox<IValueCoder<'a>> )\n            static let ext = lazy ( get typeof<'a> false |> unbox<IValueCoder<'a>> )\n            static member Intern = res.Value\n            static member Extern = ext.Value\n\n        let coder<'a> = Coder<'a>.Intern\n        let externCoder<'a> = Coder<'a>.Extern\n        \n    \n    [<AutoOpen>]\n    module ReaderWriterExtensions =\n        type IReader with\n            member x.Read() : Coder<'a> =\n                let c = Coders.coder<'a>\n                c.Read(x)\n\n            member x.ReadExtern() : Coder<'a> =\n                let c = Coders.externCoder<'a>\n                c.Read(x)\n\n        type IWriter with\n            member x.Write(v : 'a) : Coder<unit> =\n                let c = Coders.coder<'a>\n                c.Write(x, v)\n                \n            member x.WriteExtern(v : 'a) : Coder<unit> =\n                let c = Coders.externCoder<'a>\n                c.Write(x, v)\n\n    open System.Runtime.CompilerServices\n    [<AbstractClass; Sealed; Extension>]\n    type IReaderWriterExtensions private()  =\n\n        [<Extension>]\n        static member ReadValue(this : IReader, store : IStore) : 'a =\n            let (_,value) =\n                this.Read().code {\n                    debug = false\n                    isReading = true \n                    externalStore = store\n                    references = RefMap.empty\n                    values = Map.empty\n                    namestack = []\n                }\n            value\n        \n        [<Extension>]\n        static member WriteValue(this : IWriter, store : IStore, value : 'a) : unit =\n            this.Write(value).code {\n                debug = false\n                isReading = false \n                externalStore = store\n                references = RefMap.empty\n                values = Map.empty\n                namestack = []\n            } |> ignore\n\n\n        [<Extension>]\n        static member ReadValue(this : IReader) : 'a =\n            let (_,value) =\n                this.Read().code {\n                    debug = false\n                    isReading = true \n                    externalStore = NopStore.Instance\n                    references = RefMap.empty\n                    values = Map.empty\n                    namestack = []\n                }\n            value\n        \n        [<Extension>]\n        static member WriteValue(this : IWriter, value : 'a) : unit =\n            this.Write(value).code {\n                debug = false\n                isReading = false \n                externalStore = NopStore.Instance\n                references = RefMap.empty\n                values = Map.empty\n                namestack = []\n            } |> ignore\n           \n        [<Extension>]\n        static member ReadValueDebug(this : IReader) : 'a =\n            let (_,value) =\n                this.Read().code {\n                    debug = true\n                    isReading = true \n                    externalStore = NopStore.Instance\n                    references = RefMap.empty\n                    values = Map.empty\n                    namestack = []\n                }\n            value\n        \n        [<Extension>]\n        static member WriteValueDebug(this : IWriter, value : 'a) : unit =\n            this.Write(value).code {\n                debug = true\n                isReading = false \n                externalStore = NopStore.Instance\n                references = RefMap.empty\n                values = Map.empty\n                namestack = []\n            } |> ignore\n           \n\n\n\n\n    type DummDb() =\n        interface IStore with\n            member x.TryStore(value : 'a, id : byref<Guid>) =\n                Log.line \"tryStore %A\" value\n                false\n\n            member x.TryLoad(id : Guid, value : byref<'a>) =\n                Log.line \"tryLoad %A\" value\n                false\n\n    type DummyWriter() =\n        interface IWriter with\n            member x.WritePrimitive(a) = Log.line \"prim %A\" a\n            member x.WriteBool(a) = Log.line \"bool %A\" a\n            member x.WriteString(a) = Log.line \"str %A\" a\n\n    open System.IO\n    open Microsoft.FSharp.NativeInterop\n    open System.Runtime.InteropServices\n\n    type BinaryWritingCoder(stream : Stream) =\n        let w = new BinaryWriter(stream)\n\n        interface IWriter with\n            member x.WritePrimitive(a : 'a) =\n                let mutable a = a\n                let ptr : nativeptr<byte> = &&a |> NativePtr.cast\n                let bytes = ptr |> NativePtr.toArray sizeof<'a>\n                w.Write(bytes)\n\n            member x.WriteBool(v : bool) =\n                if v then w.Write(1uy)\n                else w.Write(0uy)\n\n            member x.WriteString(str : string) =\n                w.Write(str.Length)\n                let bytes = Text.Encoding.Unicode.GetBytes(str)\n                w.Write(bytes)\n\n    type BinaryReadingCoder(stream : Stream) =\n        let r = new BinaryReader(stream)\n\n        interface IReader with\n            member x.ReadPrimitive() : 'a =\n                let bytes = r.ReadBytes sizeof<'a>\n                let gc = GCHandle.Alloc(bytes, GCHandleType.Pinned)\n                try\n                    NativePtr.read (NativePtr.ofNativeInt<'a> (gc.AddrOfPinnedObject()))\n                finally\n                    gc.Free()\n\n            member x.ReadBool() =\n                r.ReadByte() = 1uy\n\n            member x.ReadString() =\n                let length = r.ReadInt32()\n                let bytes = r.ReadBytes (2 * length)\n                Text.Encoding.Unicode.GetString(bytes)\n\n\n    let toArray<'a> (data : 'a) =\n        use ms = new MemoryStream()\n        let w = BinaryWritingCoder(ms)\n        w.WriteValue data\n        ms.ToArray()\n\n    let ofArray<'a> (bytes : byte[]) : 'a =\n        use ms = new MemoryStream(bytes)\n        let r = BinaryReadingCoder(ms)\n        r.ReadValue()\n\n    type Rec = { a : int; b : obj }\n\n    type Something =\n        class\n            val mutable public A : obj\n            val mutable public B : V3d\n            val mutable public C : string[]\n            val mutable public D : obj[]\n\n            new(a,b) = { A = a; B = b; C = [| \"A\"; \"B\" |]; D = null }\n        end\n\n\n    let test() =\n        let w = DummyWriter()\n        let db = DummDb()\n\n        let value = Something(1,V3d.III)\n        value.A <- value\n        let n : Option<int> = None\n\n        let values = [|Choice1Of2 1; Choice2Of2 \"bla\"|]\n\n        value.D <- [|Left 1 :> obj; Some 2 :> obj; n; {a = 1; b = null }; (1,2); values|]\n        w.WriteValueDebug(value)\n\n\n        let data = toArray value\n        let test = data |> ofArray<Something>\n        printfn \"size = %A\" data.Length\n        printfn \"%A\" test.D\n\n        printfn \"%A\" (test :> obj == test.A)\n\n        \n\n\nmodule TypeBuilderTest =\n    open TypeBuilder\n\n    let buildTest() =\n        newtype { \n            do! inh typeof<obj>\n\n            let! m_fld = NewType.fld \"m_fld\" typeof<int>\n\n            do! iface typeof<IComparable> [\n                    typeof<int>, \"CompareTo\", [typeof<obj>], (\n                        codegen {\n                            do! IL.ldconst 0\n                            do! IL.ret\n                        }\n                    )\n                ]\n\n            do! recmem typeof<int> \"Bla\" [typeof<int>; typeof<int>] (fun self -> \n                codegen {\n                    let! l = IL.newlabel\n                        \n                    do! IL.ldarg 1\n                    do! IL.ldconst 1\n                    do! IL.jmp LessOrEqual l\n\n                    do! IL.ldarg 0\n                    do! IL.ldfld m_fld\n                    do! IL.ldarg 1\n                    do! IL.ldarg 2\n                    do! IL.add\n                    do! IL.mul\n                    do! IL.ret\n\n\n                    do! IL.mark l\n                    do! IL.ldarg 0\n\n                    do! IL.ldarg 1\n                    do! IL.ldconst 1\n                    do! IL.add\n\n                    do! IL.ldarg 2\n                    do! IL.call self\n                    do! IL.ret\n                })\n\n            do! mem typeof<int> \"Blub\" [] (\n                    codegen {\n                        do! IL.ldconst 1\n                        do! IL.ret\n                    }\n                )\n\n            do! mem typeof<int> \"GetHashCode\" [] (\n                    codegen {\n                        do! IL.printfn \"hashcode\"\n                        do! IL.ldconst 27\n                        do! IL.ret\n                    }\n                )\n\n            do! ctor [typeof<int>] (\n                    codegen {\n                        do! IL.ldarg 0\n                        do! IL.ldarg 1\n                        do! IL.stfld m_fld\n                        do! IL.ret\n                    }\n                )\n\n        }\n\n    let buildFunc() =\n        newtype {\n            let! off = fld \"off\" typeof<int>\n\n            do! inh typeof<FSharpFunc<int, int>>\n\n            do! mem typeof<int> \"Invoke\" [typeof<int>] (\n                    codegen {\n                        do! IL.ldarg 0\n                        do! IL.ldfld off\n\n\n                        do! IL.ldarg 1\n                        do! IL.add\n                        do! IL.ret\n                    }\n                )\n\n            do! ctor [typeof<int>] (\n                    codegen {\n                        do! IL.ldarg 0\n                        do! IL.ldarg 1\n                        do! IL.stfld off\n                        do! IL.ret\n                    }\n                )\n\n        }\n\n    let run() =\n        Serializer.test()\n//\n//        let test = buildFunc()\n//        let ctor = test.GetConstructor [|typeof<int>|]\n//        let v = ctor.Invoke [|10|] |> unbox<int -> int>\n//        let w = ctor.Invoke [|6|] |> unbox<int -> int>\n//\n//        printfn \"v 10 = %A\" (v 10)\n//        printfn \"w 10 = %A\" (w 10)\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/TypeInfo.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\Bin\\\\Debug\\\\Aardvark.Base.dll\"\nopen Aardvark.Base\n#else\nnamespace Aardvark.Base\n#endif\n\n/// <summary>\n/// TypeInfo contains metadata associated with types and provides active patterns\n/// deconstructing vector/matrix types etc.\n/// </summary>\n[<System.Obsolete(\"Use TypeMeta module instead.\")>]\nmodule TypeInfo =\n    open System\n    open System.Collections.Generic\n\n    type ITypeInfo =\n        inherit IComparable\n        abstract member Type : Type\n\n    [<CustomEquality>]\n    [<CustomComparison>]\n    type SimpleType = { simpleType : Type } with\n        interface ITypeInfo with\n            member x.Type = x.simpleType\n        interface IComparable with\n            member x.CompareTo o =\n                match o with\n                    | :? ITypeInfo as o -> x.simpleType.Name.CompareTo o.Type.Name\n                    | _ -> failwith \"\"\n        override x.Equals o =\n            match o with\n                | :? ITypeInfo as o -> x.simpleType.Name = o.Type.Name\n                | _ -> false\n        override x.GetHashCode() =\n            x.simpleType.Name.GetHashCode()\n\n    [<CustomEquality>]\n    [<CustomComparison>]\n    type VectorType = { vectorType : Type; baseType : ITypeInfo; dimension : int } with\n        interface ITypeInfo with\n            member x.Type = x.vectorType\n        interface IComparable with\n            member x.CompareTo o =\n                match o with\n                    | :? ITypeInfo as o -> x.vectorType.Name.CompareTo o.Type.Name\n                    | _ -> failwith \"\"\n        override x.Equals o =\n            match o with\n                | :? ITypeInfo as o -> x.vectorType.Name = o.Type.Name\n                | _ -> false\n        override x.GetHashCode() =\n            x.vectorType.Name.GetHashCode()\n\n    [<CustomEquality>]\n    [<CustomComparison>]\n    type MatrixType = { matrixType : Type; baseType : ITypeInfo; dimension : V2i } with \n        interface ITypeInfo with\n            member x.Type = x.matrixType\n        interface IComparable with\n            member x.CompareTo o =\n                match o with\n                    | :? ITypeInfo as o -> x.matrixType.Name.CompareTo o.Type.Name\n                    | _ -> failwith \"\"\n        override x.Equals o =\n            match o with\n                | :? ITypeInfo as o -> x.matrixType.Name = o.Type.Name\n                | _ -> false\n        override x.GetHashCode() =\n            x.matrixType.Name.GetHashCode()\n\n\n    let TByte = { simpleType = typeof<byte> }\n    let TSByte = { simpleType = typeof<sbyte> }\n    let TInt16= { simpleType = typeof<int16> }\n    let TUInt16 = { simpleType = typeof<uint16> }\n    let TInt32 = { simpleType = typeof<int> }\n    let TUInt32 = { simpleType = typeof<uint32> }\n    let TInt64 = { simpleType = typeof<int64> }\n    let TUInt64 = { simpleType = typeof<uint64> }\n    let TFloat32 = { simpleType = typeof<float32> }\n    let TFloat64 = { simpleType = typeof<float> }\n    let TDecimal = { simpleType = typeof<decimal> }\n\n    let TUnit = { simpleType = typeof<unit> }\n    let TChar = { simpleType = typeof<char> }\n    let TString = { simpleType = typeof<string> }\n\n    let TV2i = { vectorType = typeof<V2i>; baseType = TInt32; dimension = 2 }\n    let TV3i = { vectorType = typeof<V3i>; baseType = TInt32; dimension = 3 }\n    let TV4i = { vectorType = typeof<V4i>; baseType = TInt32; dimension = 4 }\n\n    let TV2ui = { vectorType = typeof<V2ui>; baseType = TUInt32; dimension = 2 }\n    let TV3ui = { vectorType = typeof<V3ui>; baseType = TUInt32; dimension = 3 }\n    let TV4ui = { vectorType = typeof<V4ui>; baseType = TUInt32; dimension = 4 }\n\n    let TV2l = { vectorType = typeof<V2l>; baseType = TInt64; dimension = 2 }\n    let TV3l = { vectorType = typeof<V3l>; baseType = TInt64; dimension = 3 }\n    let TV4l = { vectorType = typeof<V4l>; baseType = TInt64; dimension = 4 }\n\n    let TV2f = { vectorType = typeof<V2f>; baseType = TFloat32; dimension = 2 }\n    let TV3f = { vectorType = typeof<V3f>; baseType = TFloat32; dimension = 3 }\n    let TV4f = { vectorType = typeof<V4f>; baseType = TFloat32; dimension = 4 }\n\n    let TV2d = { vectorType = typeof<V2d>; baseType = TFloat64; dimension = 2 }\n    let TV3d = { vectorType = typeof<V3d>; baseType = TFloat64; dimension = 3 }\n    let TV4d = { vectorType = typeof<V4d>; baseType = TFloat64; dimension = 4 }\n\n    let TC3b  = { vectorType = typeof<C3b>;  baseType = TByte;    dimension = 3 }\n    let TC3us = { vectorType = typeof<C3us>; baseType = TUInt16;  dimension = 3 }\n    let TC3ui = { vectorType = typeof<C3ui>; baseType = TUInt32;  dimension = 3 }\n    let TC3f  = { vectorType = typeof<C3f>;  baseType = TFloat32; dimension = 3 }\n    let TC3d  = { vectorType = typeof<C3d>;  baseType = TFloat64; dimension = 3 }\n\n    let TC4b  = { vectorType = typeof<C4b>;  baseType = TByte;    dimension = 4 }\n    let TC4us = { vectorType = typeof<C4us>; baseType = TUInt16;  dimension = 4 }\n    let TC4ui = { vectorType = typeof<C4ui>; baseType = TUInt32;  dimension = 4 }\n    let TC4f  = { vectorType = typeof<C4f>;  baseType = TFloat32; dimension = 4 }\n    let TC4d  = { vectorType = typeof<C4d>;  baseType = TFloat64; dimension = 4 }\n\n    let TM22i = { matrixType = typeof<M22i>; baseType = TInt32; dimension = V2i(2,2) }\n    let TM23i = { matrixType = typeof<M23i>; baseType = TInt32; dimension = V2i(3,2) }\n    let TM33i = { matrixType = typeof<M33i>; baseType = TInt32; dimension = V2i(3,3) }\n    let TM34i = { matrixType = typeof<M34i>; baseType = TInt32; dimension = V2i(4,3) }\n    let TM44i = { matrixType = typeof<M44i>; baseType = TInt32; dimension = V2i(4,4) }\n\n    let TM22l = { matrixType = typeof<M22l>; baseType = TInt64; dimension = V2i(2,2) }\n    let TM23l = { matrixType = typeof<M23l>; baseType = TInt64; dimension = V2i(3,2) }\n    let TM33l = { matrixType = typeof<M33l>; baseType = TInt64; dimension = V2i(3,3) }\n    let TM34l = { matrixType = typeof<M34l>; baseType = TInt64; dimension = V2i(4,3) }\n    let TM44l = { matrixType = typeof<M44l>; baseType = TInt64; dimension = V2i(4,4) }\n\n    let TM22f = { matrixType = typeof<M22f>; baseType = TFloat32; dimension = V2i(2,2) }\n    let TM23f = { matrixType = typeof<M23f>; baseType = TFloat32; dimension = V2i(3,2) }\n    let TM33f = { matrixType = typeof<M33f>; baseType = TFloat32; dimension = V2i(3,3) }\n    let TM34f = { matrixType = typeof<M34f>; baseType = TFloat32; dimension = V2i(4,3) }\n    let TM44f = { matrixType = typeof<M44f>; baseType = TFloat32; dimension = V2i(4,4) }\n\n    let TM22d = { matrixType = typeof<M22d>; baseType = TFloat64; dimension = V2i(2,2) }\n    let TM23d = { matrixType = typeof<M23d>; baseType = TFloat64; dimension = V2i(3,2) }\n    let TM33d = { matrixType = typeof<M33d>; baseType = TFloat64; dimension = V2i(3,3) }\n    let TM34d = { matrixType = typeof<M34d>; baseType = TFloat64; dimension = V2i(4,3) }\n    let TM44d = { matrixType = typeof<M44d>; baseType = TFloat64; dimension = V2i(4,4) }\n\n    let IntegralTypes : Set<ITypeInfo>  = Set.ofList [TByte; TSByte; TInt16; TUInt16; TInt32; TUInt32; TInt64; TUInt64]\n    let FractionalTypes : Set<ITypeInfo>  = Set.ofList [TFloat32; TFloat64; TDecimal]\n    let NumTypes : Set<ITypeInfo>  = Set.union IntegralTypes FractionalTypes\n\n    let VectorTypes  : Set<ITypeInfo> =\n        Set.ofList [\n            TV2i; TV3i; TV4i\n            TV2ui; TV3ui; TV4ui\n            TV2l; TV3l; TV4l\n            TV2f; TV3f; TV4f\n            TV2d; TV3d; TV4d\n        ]\n\n    let ColorTypes : Set<ITypeInfo> =\n        Set.ofList [\n            TC3b; TC3us; TC3ui; TC3f; TC3d\n            TC4b; TC4us; TC4ui; TC4f; TC4d\n        ]\n\n    let MatrixTypes : Set<ITypeInfo> =\n        Set.ofList [\n            TM22i; TM23i; TM33i; TM34i; TM44i\n            TM22l; TM23l; TM33l; TM34l; TM44l\n            TM22f; TM23f; TM33f; TM34f; TM44f\n            TM22d; TM23d; TM33d; TM34d; TM44d\n        ]\n\n    let TRef = { simpleType = typeof<ref<int>>.GetGenericTypeDefinition() }\n    let TList = { simpleType = typeof<list<int>>.GetGenericTypeDefinition() }\n    let TSeq = { simpleType = typeof<seq<int>>.GetGenericTypeDefinition() }\n\n    let inline private typeInfo t = { simpleType = t } :> ITypeInfo\n\n    let VectorFields = Set.ofList ['X'; 'Y'; 'Z'; 'W']\n\n    [<AutoOpen>]\n    [<System.Obsolete(\"Use TypeMeta.Patterns module instead.\")>]\n    module Patterns =\n\n        [<return: Struct>]\n        let inline (|Bool|_|) (t : Type) =\n            if t = typeof<bool> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Byte|_|) (t : Type) =\n            if t = typeof<byte> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|SByte|_|) (t : Type) =\n            if t = typeof<sbyte> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Int16|_|) (t : Type) =\n            if t = typeof<int16> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|UInt16|_|) (t : Type) =\n            if t = typeof<uint16> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Int32|_|) (t : Type) =\n            if t = typeof<int32> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|UInt32|_|) (t : Type) =\n            if t = typeof<uint32> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|UInt64|_|) (t : Type) =\n            if t = typeof<uint64> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Int64|_|) (t : Type) =\n            if t = typeof<int64> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|IntPtr|_|) (t : Type) =\n            if t = typeof<IntPtr> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Float32|_|) (t : Type) =\n            if t = typeof<float32> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Float64|_|) (t : Type) =\n            if t = typeof<float> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Decimal|_|) (t : Type) =\n            if t = typeof<decimal> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Char|_|) (t : Type) =\n            if t = typeof<char> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Unit|_|) (t : Type) =\n            if t = typeof<unit> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|String|_|) (t : Type) =\n            if t = typeof<string> then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Enum|_|) (t : Type) =\n            if t.IsEnum then ValueSome ()\n            else ValueNone\n\n        [<return: Struct>]\n        let inline (|Integral|_|) (t : Type) =\n            TypeMeta.Patterns.(|Integral|_|) t\n\n        [<return: Struct>]\n        let inline (|Fractional|_|) (t : Type) =\n            TypeMeta.Patterns.(|Fractional|_|) t\n\n        [<return: Struct>]\n        let inline (|Num|_|) (t : Type) =\n            TypeMeta.Patterns.(|Numeric|_|) t\n\n        [<return: Struct>]\n        let inline (|Vector|_|) (t : Type) =\n            TypeMeta.Patterns.(|Vector|_|) t\n\n        [<return: Struct>]\n        let inline (|Color|_|) (t : Type) =\n            TypeMeta.Patterns.(|Color|_|) t\n\n        [<return: Struct>]\n        let inline (|Matrix|_|) (t : Type) =\n            TypeMeta.Patterns.(|Matrix|_|) t\n\n        [<return: Struct>]\n        let inline (|VectorOf|_|) (t : Type) =\n            TypeMeta.Patterns.(|VectorOf|_|) t |> ValueOption.map (fun struct (d, t) -> d, t)\n\n        [<return: Struct>]\n        let inline (|ColorOf|_|) (t : Type) =\n            TypeMeta.Patterns.(|ColorOf|_|) t |> ValueOption.map (fun struct (d, t) -> d, t)\n\n        [<return: Struct>]\n        let inline (|MatrixOf|_|) (t : Type) =\n            TypeMeta.Patterns.(|MatrixOf|_|) t |> ValueOption.map (fun struct (d, t) -> d, t)\n\n        [<return: Struct>]\n        let inline (|Ref|_|) (t : Type) =\n            TypeMeta.Patterns.(|RefOf|_|) t\n\n        [<return: Struct>]\n        let inline (|List|_|) (t : Type) =\n            TypeMeta.Patterns.(|ListOf|_|) t\n\n        [<return: Struct>]\n        let inline (|Seq|_|) (t : Type) =\n            TypeMeta.Patterns.(|SeqOf|_|) t\n\n        [<Obsolete(\"Use Seq instead.\")>]\n        [<return: Struct>]\n        let (|SeqOf|_|) = (|Seq|_|)\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/TypeMeta_auto.fs",
    "content": "namespace Aardvark.Base\n\nopen System\n\n/// Contains metadata associated with types and provides active patterns for deconstructing types.\nmodule TypeMeta =\n\n    [<Struct>]\n    type VectorType =\n        {\n            Type      : Type\n            FieldType : Type\n            Dimension : int\n        }\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module VectorType =\n\n        /// List of all supported vector types.\n        let all : VectorType list =\n            [\n                { Type = typeof<V2i>; FieldType = typeof<int32>; Dimension = 2 }\n                { Type = typeof<V2ui>; FieldType = typeof<uint32>; Dimension = 2 }\n                { Type = typeof<V2l>; FieldType = typeof<int64>; Dimension = 2 }\n                { Type = typeof<V2f>; FieldType = typeof<float32>; Dimension = 2 }\n                { Type = typeof<V2d>; FieldType = typeof<float>; Dimension = 2 }\n                { Type = typeof<V3i>; FieldType = typeof<int32>; Dimension = 3 }\n                { Type = typeof<V3ui>; FieldType = typeof<uint32>; Dimension = 3 }\n                { Type = typeof<V3l>; FieldType = typeof<int64>; Dimension = 3 }\n                { Type = typeof<V3f>; FieldType = typeof<float32>; Dimension = 3 }\n                { Type = typeof<V3d>; FieldType = typeof<float>; Dimension = 3 }\n                { Type = typeof<V4i>; FieldType = typeof<int32>; Dimension = 4 }\n                { Type = typeof<V4ui>; FieldType = typeof<uint32>; Dimension = 4 }\n                { Type = typeof<V4l>; FieldType = typeof<int64>; Dimension = 4 }\n                { Type = typeof<V4f>; FieldType = typeof<float32>; Dimension = 4 }\n                { Type = typeof<V4d>; FieldType = typeof<float>; Dimension = 4 }\n            ]\n\n        let private lookupTable =\n            all\n            |> List.map (fun t -> struct (struct (t.Dimension, t.FieldType), t.Type))\n            |> Dictionary.ofListV\n\n        /// Tries to get the vector type of the given field type and dimension.\n        let tryGetV (fieldType: Type) (dimension: int) =\n            lookupTable.TryFindV(struct (dimension, fieldType))\n\n        /// Tries to get the vector type of the given field type and dimension.\n        let tryGet (fieldType: Type) (dimension: int) =\n            lookupTable.TryFind(struct (dimension, fieldType))\n\n        /// Gets the vector type of the given field type and dimension.\n        let inline get (fieldType: Type) (dimension: int) =\n            match tryGetV fieldType dimension with\n            | ValueSome t -> t\n            | _ -> raise <| ArgumentException($\"Vector type with field type {fieldType} and dimension {dimension} does not exist.\")\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module ColorType =\n\n        /// List of all supported color types.\n        let all : VectorType list =\n            [\n                { Type = typeof<C3b>; FieldType = typeof<uint8>; Dimension = 3 }\n                { Type = typeof<C3us>; FieldType = typeof<uint16>; Dimension = 3 }\n                { Type = typeof<C3ui>; FieldType = typeof<uint32>; Dimension = 3 }\n                { Type = typeof<C3f>; FieldType = typeof<float32>; Dimension = 3 }\n                { Type = typeof<C3d>; FieldType = typeof<float>; Dimension = 3 }\n                { Type = typeof<C4b>; FieldType = typeof<uint8>; Dimension = 4 }\n                { Type = typeof<C4us>; FieldType = typeof<uint16>; Dimension = 4 }\n                { Type = typeof<C4ui>; FieldType = typeof<uint32>; Dimension = 4 }\n                { Type = typeof<C4f>; FieldType = typeof<float32>; Dimension = 4 }\n                { Type = typeof<C4d>; FieldType = typeof<float>; Dimension = 4 }\n            ]\n\n        let private lookupTable =\n            all\n            |> List.map (fun t -> struct (struct (t.Dimension, t.FieldType), t.Type))\n            |> Dictionary.ofListV\n\n        /// Tries to get the color type of the given field type and dimension.\n        let tryGetV (fieldType: Type) (dimension: int) =\n            lookupTable.TryFindV(struct (dimension, fieldType))\n\n        /// Tries to get the color type of the given field type and dimension.\n        let tryGet (fieldType: Type) (dimension: int) =\n            lookupTable.TryFind(struct (dimension, fieldType))\n\n        /// Gets the color type of the given field type and dimension.\n        let inline get (fieldType: Type) (dimension: int) =\n            match tryGetV fieldType dimension with\n            | ValueSome t -> t\n            | _ -> raise <| ArgumentException($\"Color type with field type {fieldType} and dimension {dimension} does not exist.\")\n\n    [<Struct>]\n    type MatrixType =\n        {\n            Type      : Type\n            FieldType : Type\n            Dimension : V2i\n        }\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module MatrixType =\n\n        /// List of all supported matrix types.\n        let all : MatrixType list =\n            [\n                { Type = typeof<M22i>; FieldType = typeof<int32>; Dimension = V2i(2, 2) }\n                { Type = typeof<M22l>; FieldType = typeof<int64>; Dimension = V2i(2, 2) }\n                { Type = typeof<M22f>; FieldType = typeof<float32>; Dimension = V2i(2, 2) }\n                { Type = typeof<M22d>; FieldType = typeof<float>; Dimension = V2i(2, 2) }\n                { Type = typeof<M23i>; FieldType = typeof<int32>; Dimension = V2i(3, 2) }\n                { Type = typeof<M23l>; FieldType = typeof<int64>; Dimension = V2i(3, 2) }\n                { Type = typeof<M23f>; FieldType = typeof<float32>; Dimension = V2i(3, 2) }\n                { Type = typeof<M23d>; FieldType = typeof<float>; Dimension = V2i(3, 2) }\n                { Type = typeof<M33i>; FieldType = typeof<int32>; Dimension = V2i(3, 3) }\n                { Type = typeof<M33l>; FieldType = typeof<int64>; Dimension = V2i(3, 3) }\n                { Type = typeof<M33f>; FieldType = typeof<float32>; Dimension = V2i(3, 3) }\n                { Type = typeof<M33d>; FieldType = typeof<float>; Dimension = V2i(3, 3) }\n                { Type = typeof<M34i>; FieldType = typeof<int32>; Dimension = V2i(4, 3) }\n                { Type = typeof<M34l>; FieldType = typeof<int64>; Dimension = V2i(4, 3) }\n                { Type = typeof<M34f>; FieldType = typeof<float32>; Dimension = V2i(4, 3) }\n                { Type = typeof<M34d>; FieldType = typeof<float>; Dimension = V2i(4, 3) }\n                { Type = typeof<M44i>; FieldType = typeof<int32>; Dimension = V2i(4, 4) }\n                { Type = typeof<M44l>; FieldType = typeof<int64>; Dimension = V2i(4, 4) }\n                { Type = typeof<M44f>; FieldType = typeof<float32>; Dimension = V2i(4, 4) }\n                { Type = typeof<M44d>; FieldType = typeof<float>; Dimension = V2i(4, 4) }\n            ]\n\n        let private lookupTable =\n            all\n            |> List.map (fun t -> struct (struct (t.Dimension, t.FieldType), t.Type))\n            |> Dictionary.ofListV\n\n        /// Tries to get the matrix type of the given field type and dimension.\n        let tryGetV (fieldType: Type) (dimension: V2i) =\n            lookupTable.TryFindV(struct (dimension, fieldType))\n\n        /// Tries to get the matrix type of the given field type and dimension.\n        let tryGet (fieldType: Type) (dimension: V2i) =\n            lookupTable.TryFind(struct (dimension, fieldType))\n\n        /// Gets the matrix type of the given field type and dimension.\n        let inline get (fieldType: Type) (dimension: V2i) =\n            match tryGetV fieldType dimension with\n            | ValueSome t -> t\n            | _ -> raise <| ArgumentException($\"Matrix type with field type {fieldType} and dimension {dimension} does not exist.\")\n\n    [<AutoOpen>]\n    module Patterns =\n\n        [<AutoOpen>]\n        module private Lookup =\n\n            let vectorTypes =\n                VectorType.all\n                |> List.map (fun vt -> struct (vt.Type, struct (vt.Dimension, vt.FieldType)))\n                |> Dictionary.ofListV\n\n            let colorTypes =\n                ColorType.all\n                |> List.map (fun ct -> struct (ct.Type, struct (ct.Dimension, ct.FieldType)))\n                |> Dictionary.ofListV\n\n            let matrixTypes =\n                MatrixType.all\n                |> List.map (fun mt -> struct (mt.Type, struct (mt.Dimension, mt.FieldType)))\n                |> Dictionary.ofListV\n\n            let integralTypes =\n                [\n                    typeof<uint8>\n                    typeof<int8>\n                    typeof<int16>\n                    typeof<uint16>\n                    typeof<int32>\n                    typeof<uint32>\n                    typeof<int64>\n                    typeof<uint64>\n                ]\n                |> HashSet.ofList\n\n            let fractionalTypes =\n                [ typeof<float16>; typeof<float32>; typeof<float>; typeof<decimal> ]\n                |> HashSet.ofList\n\n            let numericTypes =\n                HashSet.union [ integralTypes; fractionalTypes ]\n\n        /// Determines if the given type is a bool.\n        [<return: Struct>]\n        let inline (|Bool|_|) (t: Type) =\n            if t = typeof<bool> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a uint8.\n        [<return: Struct>]\n        let inline (|UInt8|_|) (t: Type) =\n            if t = typeof<uint8> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a int8.\n        [<return: Struct>]\n        let inline (|Int8|_|) (t: Type) =\n            if t = typeof<int8> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a int16.\n        [<return: Struct>]\n        let inline (|Int16|_|) (t: Type) =\n            if t = typeof<int16> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a uint16.\n        [<return: Struct>]\n        let inline (|UInt16|_|) (t: Type) =\n            if t = typeof<uint16> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a int32.\n        [<return: Struct>]\n        let inline (|Int32|_|) (t: Type) =\n            if t = typeof<int32> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a uint32.\n        [<return: Struct>]\n        let inline (|UInt32|_|) (t: Type) =\n            if t = typeof<uint32> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a int64.\n        [<return: Struct>]\n        let inline (|Int64|_|) (t: Type) =\n            if t = typeof<int64> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a uint64.\n        [<return: Struct>]\n        let inline (|UInt64|_|) (t: Type) =\n            if t = typeof<uint64> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a float32.\n        [<return: Struct>]\n        let inline (|Float32|_|) (t: Type) =\n            if t = typeof<float32> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a float.\n        [<return: Struct>]\n        let inline (|Float64|_|) (t: Type) =\n            if t = typeof<float> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a float16.\n        [<return: Struct>]\n        let inline (|Float16|_|) (t: Type) =\n            if t = typeof<float16> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a decimal.\n        [<return: Struct>]\n        let inline (|Decimal|_|) (t: Type) =\n            if t = typeof<decimal> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a char.\n        [<return: Struct>]\n        let inline (|Char|_|) (t: Type) =\n            if t = typeof<char> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a string.\n        [<return: Struct>]\n        let inline (|String|_|) (t: Type) =\n            if t = typeof<string> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a IntPtr.\n        [<return: Struct>]\n        let inline (|IntPtr|_|) (t : Type) =\n            if t = typeof<IntPtr> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is unit.\n        [<return: Struct>]\n        let inline (|Unit|_|) (t : Type) =\n            if t = typeof<unit> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is an enumeration.\n        [<return: Struct>]\n        let inline (|Enum|_|) (t : Type) =\n            if t.IsEnum then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is an integral type.\n        [<return: Struct>]\n        let (|Integral|_|) (t : Type) =\n            if integralTypes.Contains t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is half, float, double, or decimal.\n        [<return: Struct>]\n        let (|Fractional|_|) (t : Type) =\n            if fractionalTypes.Contains t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a numeric type (i.e. half, float, double, decimal, or an integral type).\n        [<return: Struct>]\n        let (|Numeric|_|) (t : Type) =\n            if numericTypes.Contains t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a vector type.\n        [<return: Struct>]\n        let (|Vector|_|) (t: Type) =\n            if vectorTypes.ContainsKey t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a color type.\n        [<return: Struct>]\n        let (|Color|_|) (t: Type) =\n            if colorTypes.ContainsKey t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a matrix type.\n        [<return: Struct>]\n        let (|Matrix|_|) (t: Type) =\n            if matrixTypes.ContainsKey t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a vector type.\n        /// Returns the dimension and the underlying type.\n        [<return: Struct>]\n        let (|VectorOf|_|) (t: Type) =\n            vectorTypes.TryFindV t\n\n        /// Determines if the given type is a color type.\n        /// Returns the dimension and the underlying type.\n        [<return: Struct>]\n        let (|ColorOf|_|) (t: Type) =\n            colorTypes.TryFindV t\n\n        /// Determines if the given type is a matrix type.\n        /// Returns the dimension (columns, rows) and the underlying type.\n        [<return: Struct>]\n        let (|MatrixOf|_|) (t: Type) =\n            matrixTypes.TryFindV t\n\n        /// Determines if the given type is a reference type.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|RefOf|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<ref<_>> then ValueSome <| t.GetGenericArguments().[0]\n            else ValueNone\n\n        /// Determines if the given type is a list type.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|ListOf|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<list<_>> then ValueSome <| t.GetGenericArguments().[0]\n            else ValueNone\n\n        /// Determines if the given type is an array type.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|ArrayOf|_|) (t : Type) =\n            if t.IsArray then ValueSome(t.GetElementType())\n            else ValueNone\n\n        /// Determines if the given type is an Arr type.\n        /// Returns the dimension and the underlying type.\n        [<return: Struct>]\n        let inline (|ArrOf|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<Arr<_,_>> then\n                let targs = t.GetGenericArguments()\n                let len = targs.[0] |> Peano.getSize\n                let content = targs.[1]\n                ValueSome struct (len, content)\n            else\n                ValueNone\n\n        /// Determines if the given type is a sequence type.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|SeqOf|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<seq<_>> then ValueSome <| t.GetGenericArguments().[0]\n            else ValueNone\n\n        /// Determines if the given type supports the IEnumerable<'T> interface.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|EnumerableOf|_|) (t : Type) =\n            if t.IsArray then\n                ValueSome (t.GetElementType())\n\n            elif t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<seq<_>> then\n                ValueSome (t.GetGenericArguments().[0])\n\n            else\n                let iface = t.GetInterface(typedefof<seq<_>>.Name)\n                if isNull iface then\n                    ValueNone\n                else\n                    ValueSome (iface.GetGenericArguments().[0])"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/TypeMeta_template.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\n\n/// Contains metadata associated with types and provides active patterns for deconstructing types.\nmodule TypeMeta =\n\n    [<Struct>]\n    type VectorType =\n        {\n            Type      : Type\n            FieldType : Type\n            Dimension : int\n        }\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module VectorType =\n\n        /// List of all supported vector types.\n        let all : VectorType list =\n            [\n                //# foreach (var vt in Meta.VecTypes) {\n                { Type = typeof<__vt.Name__>; FieldType = typeof<__vt.FieldType.FSharpName__>; Dimension = __vt.Len__ }\n                //# }\n            ]\n\n        let private lookupTable =\n            all\n            |> List.map (fun t -> struct (struct (t.Dimension, t.FieldType), t.Type))\n            |> Dictionary.ofListV\n\n        /// Tries to get the vector type of the given field type and dimension.\n        let tryGetV (fieldType: Type) (dimension: int) =\n            lookupTable.TryFindV(struct (dimension, fieldType))\n\n        /// Tries to get the vector type of the given field type and dimension.\n        let tryGet (fieldType: Type) (dimension: int) =\n            lookupTable.TryFind(struct (dimension, fieldType))\n\n        /// Gets the vector type of the given field type and dimension.\n        let inline get (fieldType: Type) (dimension: int) =\n            match tryGetV fieldType dimension with\n            | ValueSome t -> t\n            | _ -> raise <| ArgumentException($\"Vector type with field type {fieldType} and dimension {dimension} does not exist.\")\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module ColorType =\n\n        /// List of all supported color types.\n        let all : VectorType list =\n            [\n                //# foreach (var ct in Meta.ColorTypes) {\n                { Type = typeof<__ct.Name__>; FieldType = typeof<__ct.FieldType.FSharpName__>; Dimension = __ct.Len__ }\n                //# }\n            ]\n\n        let private lookupTable =\n            all\n            |> List.map (fun t -> struct (struct (t.Dimension, t.FieldType), t.Type))\n            |> Dictionary.ofListV\n\n        /// Tries to get the color type of the given field type and dimension.\n        let tryGetV (fieldType: Type) (dimension: int) =\n            lookupTable.TryFindV(struct (dimension, fieldType))\n\n        /// Tries to get the color type of the given field type and dimension.\n        let tryGet (fieldType: Type) (dimension: int) =\n            lookupTable.TryFind(struct (dimension, fieldType))\n\n        /// Gets the color type of the given field type and dimension.\n        let inline get (fieldType: Type) (dimension: int) =\n            match tryGetV fieldType dimension with\n            | ValueSome t -> t\n            | _ -> raise <| ArgumentException($\"Color type with field type {fieldType} and dimension {dimension} does not exist.\")\n\n    [<Struct>]\n    type MatrixType =\n        {\n            Type      : Type\n            FieldType : Type\n            Dimension : V2i\n        }\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module MatrixType =\n\n        /// List of all supported matrix types.\n        let all : MatrixType list =\n            [\n                //# foreach (var mt in Meta.MatTypes) {\n                { Type = typeof<__mt.Name__>; FieldType = typeof<__mt.FieldType.FSharpName__>; Dimension = V2i(__mt.Cols__, __mt.Rows__) }\n                //# }\n            ]\n\n        let private lookupTable =\n            all\n            |> List.map (fun t -> struct (struct (t.Dimension, t.FieldType), t.Type))\n            |> Dictionary.ofListV\n\n        /// Tries to get the matrix type of the given field type and dimension.\n        let tryGetV (fieldType: Type) (dimension: V2i) =\n            lookupTable.TryFindV(struct (dimension, fieldType))\n\n        /// Tries to get the matrix type of the given field type and dimension.\n        let tryGet (fieldType: Type) (dimension: V2i) =\n            lookupTable.TryFind(struct (dimension, fieldType))\n\n        /// Gets the matrix type of the given field type and dimension.\n        let inline get (fieldType: Type) (dimension: V2i) =\n            match tryGetV fieldType dimension with\n            | ValueSome t -> t\n            | _ -> raise <| ArgumentException($\"Matrix type with field type {fieldType} and dimension {dimension} does not exist.\")\n\n    [<AutoOpen>]\n    module Patterns =\n\n        [<AutoOpen>]\n        module private Lookup =\n\n            let vectorTypes =\n                VectorType.all\n                |> List.map (fun vt -> struct (vt.Type, struct (vt.Dimension, vt.FieldType)))\n                |> Dictionary.ofListV\n\n            let colorTypes =\n                ColorType.all\n                |> List.map (fun ct -> struct (ct.Type, struct (ct.Dimension, ct.FieldType)))\n                |> Dictionary.ofListV\n\n            let matrixTypes =\n                MatrixType.all\n                |> List.map (fun mt -> struct (mt.Type, struct (mt.Dimension, mt.FieldType)))\n                |> Dictionary.ofListV\n\n            let integralTypes =\n                [\n                    //# foreach(var t in Meta.IntegerTypes) {\n                    typeof<__t.FSharpName__>\n                    //# }\n                ]\n                |> HashSet.ofList\n\n            let fractionalTypes =\n                [ typeof<float16>; typeof<float32>; typeof<float>; typeof<decimal> ]\n                |> HashSet.ofList\n\n            let numericTypes =\n                HashSet.union [ integralTypes; fractionalTypes ]\n\n        //# var patternTypes =\n        //#    Meta.BuiltInTypes\n        //#    .Concat(Meta.HalfType.IntoArray())\n        //#    .Concat(Meta.DecimalType.IntoArray())\n        //#    .Concat(Meta.CharType.IntoArray())\n        //#    .Concat(Meta.StringType.IntoArray());\n        //# foreach (var t in patternTypes) {\n        //# var name = t.FSharpName;\n        //# var caps = name.StartsWith(\"uint\") ? 2 : 1;\n        //# var patternName = name.Substring(0, caps).ToUpperInvariant() + name.Substring(caps);\n        //# if (patternName == \"Float\") patternName = \"Float64\";\n        //# var pattern = $\"(|{patternName}|_|)\";\n        /// Determines if the given type is a __name__.\n        [<return: Struct>]\n        let inline __pattern__ (t: Type) =\n            if t = typeof<__name__> then ValueSome ()\n            else ValueNone\n\n        //# }\n        /// Determines if the given type is a IntPtr.\n        [<return: Struct>]\n        let inline (|IntPtr|_|) (t : Type) =\n            if t = typeof<IntPtr> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is unit.\n        [<return: Struct>]\n        let inline (|Unit|_|) (t : Type) =\n            if t = typeof<unit> then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is an enumeration.\n        [<return: Struct>]\n        let inline (|Enum|_|) (t : Type) =\n            if t.IsEnum then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is an integral type.\n        [<return: Struct>]\n        let (|Integral|_|) (t : Type) =\n            if integralTypes.Contains t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is half, float, double, or decimal.\n        [<return: Struct>]\n        let (|Fractional|_|) (t : Type) =\n            if fractionalTypes.Contains t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a numeric type (i.e. half, float, double, decimal, or an integral type).\n        [<return: Struct>]\n        let (|Numeric|_|) (t : Type) =\n            if numericTypes.Contains t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a vector type.\n        [<return: Struct>]\n        let (|Vector|_|) (t: Type) =\n            if vectorTypes.ContainsKey t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a color type.\n        [<return: Struct>]\n        let (|Color|_|) (t: Type) =\n            if colorTypes.ContainsKey t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a matrix type.\n        [<return: Struct>]\n        let (|Matrix|_|) (t: Type) =\n            if matrixTypes.ContainsKey t then ValueSome ()\n            else ValueNone\n\n        /// Determines if the given type is a vector type.\n        /// Returns the dimension and the underlying type.\n        [<return: Struct>]\n        let (|VectorOf|_|) (t: Type) =\n            vectorTypes.TryFindV t\n\n        /// Determines if the given type is a color type.\n        /// Returns the dimension and the underlying type.\n        [<return: Struct>]\n        let (|ColorOf|_|) (t: Type) =\n            colorTypes.TryFindV t\n\n        /// Determines if the given type is a matrix type.\n        /// Returns the dimension (columns, rows) and the underlying type.\n        [<return: Struct>]\n        let (|MatrixOf|_|) (t: Type) =\n            matrixTypes.TryFindV t\n\n        /// Determines if the given type is a reference type.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|RefOf|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<ref<_>> then ValueSome <| t.GetGenericArguments().[0]\n            else ValueNone\n\n        /// Determines if the given type is a list type.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|ListOf|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<list<_>> then ValueSome <| t.GetGenericArguments().[0]\n            else ValueNone\n\n        /// Determines if the given type is an array type.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|ArrayOf|_|) (t : Type) =\n            if t.IsArray then ValueSome(t.GetElementType())\n            else ValueNone\n\n        /// Determines if the given type is an Arr type.\n        /// Returns the dimension and the underlying type.\n        [<return: Struct>]\n        let inline (|ArrOf|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<Arr<_,_>> then\n                let targs = t.GetGenericArguments()\n                let len = targs.[0] |> Peano.getSize\n                let content = targs.[1]\n                ValueSome struct (len, content)\n            else\n                ValueNone\n\n        /// Determines if the given type is a sequence type.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|SeqOf|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<seq<_>> then ValueSome <| t.GetGenericArguments().[0]\n            else ValueNone\n\n        /// Determines if the given type supports the IEnumerable<'T> interface.\n        /// Returns the underlying type.\n        [<return: Struct>]\n        let inline (|EnumerableOf|_|) (t : Type) =\n            if t.IsArray then\n                ValueSome (t.GetElementType())\n\n            elif t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<seq<_>> then\n                ValueSome (t.GetGenericArguments().[0])\n\n            else\n                let iface = t.GetInterface(typedefof<seq<_>>.Name)\n                if isNull iface then\n                    ValueNone\n                else\n                    ValueSome (iface.GetGenericArguments().[0])"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Reflection/UnmanagedFunctions.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\Bin\\\\Debug\\\\Aardvark.Base.dll\"\nopen Aardvark.Base\n#else\nnamespace Aardvark.Base\n#endif\n\nopen System.Linq.Expressions\nopen System.Runtime.InteropServices\nopen Microsoft.FSharp.Reflection\nopen System.Reflection\nopen System.Reflection.Emit\nopen System\n\n/// <summary>\n/// UnmanagedFunctions allows to wrap function pointers as F# functions efficiently.\n/// Since MethodInfo.Invoke is extremely slow it uses compiled Linq-Expressions here.\n/// </summary>\nmodule UnmanagedFunctions =\n    open System.Collections.Generic\n    open System.Collections.Concurrent\n    //open DynamicLinker\n\n//    let private functions = ConcurrentDictionary()\n    let private pointers = ConcurrentDictionary()\n\n    module private DelegateBuilder = \n        let assembly = new AssemblyName();\n        assembly.Version <- new Version(1, 0, 0, 0);\n        assembly.Name <- \"ReflectionEmitDelegateTest\";\n        let assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run)\n        let modbuilder = assemblyBuilder.DefineDynamicModule(\"MyModule\")\n\n        let mutable delegateIndex = 0\n        let buildDelegate (argTypes : Type[]) (ret : Type) =\n            let delegateIndex = System.Threading.Interlocked.Increment(&delegateIndex)\n            let name = sprintf \"DelegateType%d\" delegateIndex\n\n            let typeBuilder = modbuilder.DefineType(\n                                name, \n                                TypeAttributes.Class ||| TypeAttributes.Public ||| TypeAttributes.Sealed ||| TypeAttributes.AnsiClass ||| TypeAttributes.AutoClass, \n                                typeof<System.MulticastDelegate>)\n\n        \n            let unmanagedAtt = typeof<UnmanagedFunctionPointerAttribute>.GetConstructor([|typeof<CallingConvention>|])\n            let attBuilder = CustomAttributeBuilder(unmanagedAtt, [| CallingConvention.Cdecl :> obj |])\n            typeBuilder.SetCustomAttribute(attBuilder)\n\n            let constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.RTSpecialName ||| MethodAttributes.HideBySig ||| MethodAttributes.Public, CallingConventions.Standard, [| typeof<obj>; typeof<System.IntPtr> |])\n            constructorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime ||| MethodImplAttributes.Managed);\n\n            let methodBuilder = typeBuilder.DefineMethod(\"Invoke\", MethodAttributes.Public ||| MethodAttributes.HideBySig, ret, argTypes);\n            methodBuilder.SetImplementationFlags(MethodImplAttributes.Runtime ||| MethodImplAttributes.Managed ||| MethodImplAttributes.Native);\n\n            let supress = typeof<System.Security.SuppressUnmanagedCodeSecurityAttribute>.GetConstructor([||])\n            let supressSecAtt = CustomAttributeBuilder(supress, [||])\n            typeBuilder.SetCustomAttribute(supressSecAtt)\n            methodBuilder.SetCustomAttribute(supressSecAtt)\n\n            typeBuilder.CreateTypeInfo()\n\n    let private methodCache = System.Collections.Concurrent.ConcurrentDictionary<nativeint, Delegate>()\n\n    [<System.Security.SuppressUnmanagedCodeSecurity>]\n    let wrap (executableMemory : IntPtr) : 'a =\n        if executableMemory <> 0n then\n            let args, ret = FunctionReflection.getMethodSignature typeof<'a>\n\n            let delegateType = DelegateBuilder.buildDelegate (args |> List.toArray) ret\n            let d = Marshal.GetDelegateForFunctionPointer(executableMemory, delegateType)\n\n            let invoke = delegateType.GetMethod(\"Invoke\")\n            let f = FunctionReflection.buildFunction d invoke\n\n            pointers.TryAdd(f :> obj, executableMemory) |> ignore\n            f\n        else\n            FunctionReflection.makeNAryFunction (fun _ -> failwith \"could not get native function (maybe some opengl-driver problem?)\")\n\n    let private convert (o : obj) (t : Type) =\n        match o with\n            | :? int as o ->\n                if t = typeof<int64> then o |> int64 :> obj\n                elif t = typeof<nativeint> then o |> nativeint :> obj\n                elif t = typeof<int> then o :> obj\n                else failwith \"not implemented\"\n            | :? int64 as o ->\n                if t = typeof<int64> then o :> obj\n                elif t = typeof<nativeint> then o |> nativeint :> obj\n                elif t = typeof<int> then o |> int :> obj\n                else failwith \"not implemented\"\n            | :? nativeint as o ->\n                if t = typeof<int64> then o |> int64 :> obj\n                elif t = typeof<nativeint> then o :> obj\n                elif t = typeof<int> then o |> int :> obj\n                else failwith \"not implemented\"\n            | _ -> o\n\n    let private invokeDelegate (d : Delegate) (args : obj[]) =\n        let dArgs = d.Method.GetParameters()\n        let newArgs = Array.zeroCreate dArgs.Length\n        for i in 0..dArgs.Length-1 do\n            let a = args.[i]\n            let wanted = dArgs.[i]\n            let real = a.GetType()\n\n            if wanted.ParameterType <> real then\n                newArgs.[i] <- convert a wanted.ParameterType\n            else \n                newArgs.[i] <- a\n\n        d.GetMethodInfo().Invoke(d, newArgs)\n\n\n\n    [<System.Security.SuppressUnmanagedCodeSecurity>]\n    let callFunctionPointer (executableMemory : IntPtr) (arguments : obj[]) : 'a =\n        let d = methodCache.GetOrAdd(executableMemory, fun _ ->\n            let ret = typeof<'a>\n            let args = arguments |> Array.map (fun a -> a.GetType())\n\n            let delegateType = DelegateBuilder.buildDelegate (args) ret\n            let del = Marshal.GetDelegateForFunctionPointer(executableMemory, delegateType)\n            \n            del\n        )\n\n        invokeDelegate d arguments |> unbox\n\n    let tryFindFunctionPointer (f : 'a) =\n        match pointers.TryGetValue (f :> obj) with\n            | (true,f) -> Some f\n            | _ -> None\n    \n    let registerPointer (f : 'a) (ptr : nativeint) =\n        pointers.TryAdd(f :> obj, ptr) |> ignore\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Runtime/Assembler.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\..\\\\Bin\\\\Debug\\\\Aardvark.Base.dll\"\n#else\nnamespace Aardvark.Base\n#endif\n\nopen System.Linq.Expressions\nopen System.Runtime.InteropServices\nopen Microsoft.FSharp.Reflection\nopen System.Reflection\nopen System\n\n// ==============================================================================================\n// The native code-generation must be implemented for every\n// architecture/platform combination independently due to\n// different calling conventions. \n//\n// Configurations:\n//\n// +----------------+----------------+----------+\n// |  Architecture  |    Platform    |  State   |\n// +----------------+----------------+----------+\n// |      x64       |     Windows    |  test    |\n// |      x64       |      Linux     |  test    |\n// |      x64       |       Mac      |  TODO    |\n// |      arm       |      Linux     |  TODO    |\n// +----------------+----------------+----------+\n//\n// ==============================================================================================\n\nmodule Amd64Base =\n    type ArrayWriter = { size : int; build : int -> byte[] -> unit } with\n        static member Empty = { size = 0; build = fun _ _ -> () }\n\n    let write (index : int) (ptr : byte[]) (data : byte[]) =\n        data.CopyTo(ptr, index)\n\n    let toArray (p : ArrayWriter) =\n        let arr = Array.zeroCreate p.size\n        p.build 0 arr\n        arr\n\n    let jump  (offset : byte) =\n        { size = 2\n          build = fun i arr ->\n            //jmp +offset\n            write i arr [|0xEBuy; offset - 2uy|]\n        }\n\n    let jumpInt (offset : int) =\n        { size = 5\n          build = fun i arr ->\n            //jmp +offset\n            let bytes = BitConverter.GetBytes(offset - 5)\n            write i arr ([[|0xE9uy|]; bytes] |> Array.concat)\n        }\n\n    let nops (count : int) =\n        { size = count \n          build = fun i arr ->\n            if count > 2 then\n                write i arr (Array.concat [[|0xEBuy; byte count - 2uy|]; (Array.create (count-2) 0x90uy)])\n            elif count > 0 then\n                write i arr (Array.create count 0x90uy)\n        }\n\n\n    let call (ptr : nativeint) =\n        { size = 12\n          build = fun i arr ->\n            let ptr = BitConverter.GetBytes(int64 ptr)\n\n            //mov rax, <ptr>\n            write i arr (Array.concat [[|0x48uy; 0xB8uy;|]; ptr; [|0xFFuy; 0xD0uy|]])\n        }\n\n    let jmp (ptr : nativeint) =\n        { size = 12\n          build = fun i arr ->\n            let ptr = BitConverter.GetBytes(int64 ptr)\n\n            //mov rax, <ptr>\n            write i arr (Array.concat [[|0x48uy; 0xB8uy;|]; ptr; [|0xFFuy; 0xE0uy|]])\n        }\n\n    let pushret (skip : int) =\n        { size = 8\n          build = fun i arr ->\n            let data = Array.concat [[|0x48uy; 0x8Duy; 0x5uy|]; BitConverter.GetBytes(skip + 13); [|0x50uy|]]\n            //lea rax, [13+skip+rip]\n            //push rax\n            write i arr data\n        }\n\n    let concat (values : #seq<ArrayWriter>) =\n        let mutable result = ArrayWriter.Empty\n        let mutable index = 0\n        for w in values do\n            let p = result\n            result <- { size = result.size + w.size; build = fun i arr -> p.build i arr; w.build (i + p.size) arr }\n            index <- index + 1\n\n        result\n  \nmodule Amd64Linux =\n    open Amd64Base\n\n    let private argMovs64 = [| [| 0x48uy; 0xBFuy |]     //mov %rdi\n                               [| 0x48uy; 0xBEuy |]     //mov %rsi\n                               [| 0x48uy; 0xBAuy |]     //mov %rdx\n                               [| 0x48uy; 0xB9uy |]     //mov %rcx\n                               [| 0x49uy; 0xB8uy |]     //mov %r8\n                               [| 0x49uy; 0xB9uy |]     //mov %r9\n                            |]\n\n    let private argMovs32 = [| [| 0xBFuy |]             //mov %edi\n                               [| 0xBEuy |]             //mov %esi\n                               [| 0xBAuy |]             //mov %edx\n                               [| 0xB9uy |]             //mov %ecx\n                               [| 0x41uy; 0xB8uy |]     //mov %r8d\n                               [| 0x41uy; 0xB9uy |]     //mov %r9d\n                            |]\n\n    let private setArg64Internal (index : int) (value : int64) =\n        if index < argMovs64.Length then\n            let data = [argMovs64.[index]; BitConverter.GetBytes(value)] |> Array.concat\n            { size = data.Length; build = fun i a -> write i a data }\n        else\n            //movq value, 8*index(%rsp) doesn't work for some reason\n            //gcc splits the mov into two 32bit movs:\n            //c7 44 24 0c 80 00 00 00 = movl   $0x80,0xc(%rsp)\n            //c7 04 24 00 00 00 00    = movl   $0x0,(%rsp)\n            //c7 44 24 04 70 00 00 00 = movl   $0x70,0x4(%rsp)\n            failwith \"linux amd64 assembler currently only supports 6 arguments\"\n\n    let private setArg32Internal (index : int) (value : int) =\n        if index < argMovs32.Length then\n            let data = [argMovs32.[index]; BitConverter.GetBytes(value)] |> Array.concat\n            { size = data.Length; build = fun i a -> write i a data }\n        else\n            failwith \"linux amd64 assembler currently only supports 6 arguments\"\n\n\n    let setArg32 (index : int) (arg : int32) =\n        { size = if index < 4 then 5 else 6\n          build = fun i arr ->\n            let bytes = BitConverter.GetBytes arg\n\n            if index >= 6 then \n                failwith \"not spported in AMD64 linux assembler ATM\"\n            else\n                let mov = argMovs32.[index]\n                write i arr (Array.concat [mov; bytes])\n        }\n\n    let setArg64 (index : int) (arg : int64) =\n        { size = 10\n          build = fun i arr ->\n            let bytes = BitConverter.GetBytes arg\n\n            if index >= 6 then \n                failwith \"not spported in AMD64 linux assembler ATM\"\n            else\n                let mov = argMovs64.[index]\n                write i arr (Array.concat [mov; bytes])\n        }\n\n    let private compileCallInternal (f : nativeint) (args : obj[]) =\n        let argSetters =\n            args |> Array.mapi(fun i a ->\n                match a with    \n                    | :? int as a -> setArg32Internal i a // todo replace by non internal version\n                    | :? int64 as a -> setArg64Internal i a\n                    | :? nativeint as a -> setArg64Internal i (int64 a)\n                    | _ -> failwithf \"unsupported argument: %A\" a\n            )\n\n        let call = call f\n        [argSetters; [|call|]] |> Array.concat |> concat\n\n\n    let functionProlog argCount = [||]\n\n    let functionEpilog argCount = [|0xC3uy|]\n\n\n    let compileCall (f : nativeint) (args : obj[]) =\n        let writer = compileCallInternal f args\n        let arr = Array.zeroCreate writer.size\n        writer.build 0 arr\n        arr\n\n    let compileCalls (calls : seq<nativeint * obj[]>) =\n        let writer = calls |> Seq.map (fun (f,a) -> compileCallInternal f a) |> concat\n        let arr = Array.zeroCreate writer.size\n        writer.build 0 arr\n        arr\n\nmodule Amd64Windows =\n    open Amd64Base\n\n    let private prolog (additionalSpace : byte) =\n        { size = 4; build = fun i arr -> write i arr [| 0x48uy; 0x83uy; 0xECuy; 0x20uy + additionalSpace |] }\n\n    let private epilog (additionalSpace : byte) =\n        { size = 5; build = fun i arr -> write i arr [| 0x48uy; 0x83uy; 0xC4uy; 0x20uy + additionalSpace; 0xC3uy|] }\n\n    let private argumentMove64 = [| [| 0x48uy; 0xB9uy |]    //movq rcx, ...\n                                    [| 0x48uy; 0xBAuy |]    //movq rdx, ...\n                                    [| 0x49uy; 0xB8uy |]    //movq r8, ...\n                                    [| 0x49uy; 0xB9uy |]    //movq r9, ...\n                                 |]\n\n    let private argumentMove32 = [| [| 0xB9uy |]            //movd rcx, ...\n                                    [| 0xBAuy |]            //movd rdx, ...\n                                    [| 0x41uy; 0xB8uy  |]   //movd r8, ...\n                                    [| 0x41uy; 0xB9uy  |]   //movd r9, ...\n                                 |]\n\n    let private floatMoves32 =\n        [| [|0x66uy; 0x0Fuy; 0x6Euy; 0xC1uy |]          //movd xmm0, ecx\n           [|0x66uy; 0x0Fuy; 0x6Euy; 0xCAuy |]          //movd xmm1, edx\n           [|0x66uy; 0x41uy; 0x0Fuy; 0x6Euy; 0xD0uy |]  //movd xmm2, r8d\n           [|0x66uy; 0x41uy; 0x0Fuy; 0x6Euy; 0xD9uy |]  //movd xmm3, r9d\n           \n        |]\n\n    let setArg64 (index : int) (arg : int64) =\n        { size = if index < 4 then 10 else 15\n          build = fun i arr ->\n            let bytes = BitConverter.GetBytes arg\n\n            if index >= 4 then \n                //push the argument on the stack\n\n                //mov rax, <arg>\n                //mov [rsp+32 + <index>*8], rax\n                let offset = (byte index) * 8uy;\n                write i arr (Array.concat [ [| 0x48uy; 0xB8uy; |]; bytes; [| 0x48uy; 0x89uy; 0x44uy; 0x24uy; offset |] ])\n            else\n                let mov = argumentMove64.[index]\n                write i arr (Array.concat [mov; bytes])\n        }\n\n    let setArg32 (index : int) (arg : int) =\n        { size = if index < 2 then 5 elif index < 4 then 6 else 8\n          build = fun i arr -> \n            let bytes = BitConverter.GetBytes arg\n\n            if index >= 4 then\n                //mov [rsp+32 + <index>*8], DWORD <arg>\n                let offset = (byte index) * 8uy;\n                write i arr (Array.concat [ [| 0xC7uy; 0x44uy; 0x24uy; offset |]; bytes])\n            else\n                let mov = argumentMove32.[index]\n                write i arr  (Array.concat [ mov; bytes])\n        }\n\n    let setArg32f (index : int) (arg : float32) =\n        { size = if index < 2 then 9 elif index < 4 then 11 else 8\n          build = fun i arr -> \n            let bytes = BitConverter.GetBytes arg\n\n            if index >= 4 then\n                //mov [rsp+32 + <index>*8], DWORD <arg>\n                let offset = (byte index) * 8uy;\n                write i arr (Array.concat [ [| 0xC7uy; 0x44uy; 0x24uy; offset |]; bytes])\n            else\n                let mov = argumentMove32.[index]\n                let toXMM = floatMoves32.[index]\n                write i arr  (Array.concat [ mov; bytes; toXMM])\n        }\n\n\n    let private compileCallInternal (f : nativeint) (args : obj[]) =\n        let argSetters =\n            args |> Array.mapi(fun i a ->\n                match a with    \n                    | :? int as a -> setArg32 i a\n                    | :? int64 as a -> setArg64 i a\n                    | :? nativeint as a -> setArg64 i (int64 a)\n                    | :? float32 as a -> setArg32f i a\n                    | _ -> failwithf \"unsupported argument: %A\" a\n            )\n\n        let call = call f\n        [argSetters; [|call|]] |> Array.concat |> concat\n\n    let private getAdditionalSize (argCount : int) =\n        if argCount < 5 then 8uy\n        else \n            let size = argCount * 8 - 24\n            size |> byte\n\n    let functionProlog argCount = prolog (getAdditionalSize argCount) |> toArray\n\n    let functionEpilog argCount = epilog (getAdditionalSize argCount) |> toArray\n\n\n    let compileCall (f : nativeint) (args : obj[]) =\n        let writer = compileCallInternal f args\n        let arr = Array.zeroCreate writer.size\n        writer.build 0 arr\n        arr\n\n    let compileCalls (calls : seq<nativeint * obj[]>) =\n        let writer = calls |> Seq.map (fun (f,a) -> compileCallInternal f a) |> concat\n        let arr = Array.zeroCreate writer.size\n        writer.build 0 arr\n        arr\n\n\nmodule ArmLinux =\n    open Aardvark.Base\n\n    //c => 8\n    //a => 12\n    //8 => 16\n    //6 => 20\n    //4 => 24\n\n\n    let readArmImmediate (high : byte) (low : byte) =\n        let high = 2 * int high\n        let low = uint32 low\n        (low >>> high) ||| (low <<< (32 - high))\n\n    let private lookup =\n        [| 32; 0; 1; 26; 2; 23; 27; 0; 3; 16; 24; 30; 28; 11; 0; 13; 4; 7; 17;\n           0; 25; 22; 31; 15; 29; 10; 12; 6; 0; 21; 14; 9; 5; 20; 8; 19; 18 |]\n\n    let printBits (value : int) =\n        let mutable str = \"\"\n        let mutable started = false\n        for i in 0..31 do\n            let shift = 31 - i\n\n            let b = (value &&& (1 <<< shift)) >>> shift\n            if b <> 0 || started then\n                started <- true\n                str <- str + sprintf \"%d\" b\n        str\n\n    let countTrailingZeros (value : uint32) =\n        let value = int value\n        lookup.[(value &&& -value) % 37] |> uint32\n\n    let highestBit (value : uint32) =\n        (Fun.Log2(value) |> Fun.Ceiling |> int  |> uint32)\n\n    let toValueAndRotation (value : uint32) =\n        let trailing = countTrailingZeros value\n        let bits = 1u + highestBit value - countTrailingZeros value\n\n        let ror = 2 * (int trailing / 2)\n        (value >>> ror, 32 - ror)\n        \n    let toArmImmediate (value : uint32) =\n        let h,ror = toValueAndRotation value\n        if ror >= 0 && ror <= 32 && ror % 2 = 0 && h < 256u then\n            if ror = 32 then Some (byte h, 0uy)\n            else Some (byte h, byte (ror / 2))\n        else\n            None\n\n\n\n    let ldr (register : int) (offset : uint16) =\n        // ldr instruction-layout:\n        // 0xE5uy; 0x9Fuy | register (4 bit) | operand (12 bit)\n        if register > 15 then \n            failwith \"arm has only 16 registers\"\n        if offset > 4095us then\n            failwith \"offset must be less than 2^12\"\n\n        let registerAndOffset = BitConverter.GetBytes offset\n\n        let register = byte register\n        registerAndOffset.[0] <- (register <<< 4) ||| (registerAndOffset.[0] &&& 0xFuy)\n\n        [[| 0xE5uy; 0x9Fuy |]; registerAndOffset] |> Array.concat\n\n    let str (register : int) (stackoffset : uint16) =\n        // str instruction-layout:\n        // 0xE5uy; 0x8Duy | register (4 bit) | operand (12 bit)\n        if register > 15 then \n            failwith \"arm has only 16 registers\"\n        if stackoffset > 4095us then\n            failwith \"stackoffset must be less than 2^12\"\n\n        let registerAndOffset = BitConverter.GetBytes stackoffset\n\n        let register = byte register\n        registerAndOffset.[0] <- (register <<< 4) ||| (registerAndOffset.[0] &&& 0xFuy)\n\n        [[| 0xE5uy; 0x8Duy |]; registerAndOffset] |> Array.concat\n\n    type BuilderState = Map<int, int>\n    type Builder = { size : int; dataValues : Set<int>; write : BuilderState -> byte[] -> int -> unit }\n\n    let value (data : byte[]) =\n        { size = data.Length; dataValues = Set.empty; write = fun _ arr i -> data.CopyTo(arr, i) }\n\n    let runBuilder (b : Builder) =\n        let constantSize = b.dataValues.Count * 4\n        let constantLocations = \n            b.dataValues |> Seq.mapi (fun i v ->\n                let offset = b.size + i * 4\n                (v,offset)\n            ) |> Map.ofSeq\n\n        let size = constantSize + b.size\n        let arr = Array.zeroCreate size\n        b.write constantLocations arr 0\n\n        constantLocations |> Map.iter(fun v o ->\n            let data = BitConverter.GetBytes v\n            data.CopyTo(arr, o)\n        )\n\n        arr\n\n\n    let concatBinary (l : Builder) (r : Builder) =\n        { size = l.size + r.size\n          dataValues = Set.union l.dataValues r.dataValues\n          write = fun s arr i ->\n            l.write s arr i\n            r.write s arr (i + l.size)\n        }\n\n    let concat (builders : seq<Builder>) =\n        builders |> Seq.fold (fun s b -> concatBinary s b) { size = 0; dataValues = Set.empty; write = fun _ _ _ -> () }\n\n    let mov (register : int) (value : int) =\n        match toArmImmediate (uint32 value) with\n            | Some(h,l) ->\n                let h = byte (register <<< 4) ||| (h &&& 0xFuy)\n                let data = [|0xe3uy; 0xa0uy; h; l|]\n                { size = 4; dataValues = Set.empty; write = fun _ arr i -> data.CopyTo(arr, i) }\n            | None ->\n                { size = 4; dataValues = Set.singleton value; write = fun s arr i -> \n                    let offset = 8 + s.[value] - i // TODO: no idea why we need +8 here\n                    let data = ldr register (uint16 offset)\n                    data.CopyTo(arr, i)\n                }\n\n    let immediateMov (register : int) (value : int) =\n        match toArmImmediate (uint32 value) with\n            | Some(h,l) ->\n                let h = byte (register <<< 4) ||| (h &&& 0xFuy)\n                [|0xe3uy; 0xa0uy; h; l|]\n            | None -> failwith \"unsuppored immediate value\"\n\n    let changeReturnAddress (value : int) =\n        match toArmImmediate (uint32 value) with\n            | Some(h,l) ->\n                let h = byte (14 <<< 4) ||| (h &&& 0xFuy)\n                [|0xe2uy; 0x8fuy; h; l|]\n            | None -> failwith \"unsuppored immediate value\"\n\n    let setArg (index : int) (value : int) =\n        if index < 4 then\n            mov index value\n        else\n            failwith \"\"\n                \n    let call (ptr : nativeint) =\n        [ mov 4 (int ptr) \n          { size = 8; dataValues = Set.empty; write = fun s arr i ->\n                let constantSize = 4 + s.Count * 4\n                let writeRet = changeReturnAddress constantSize\n                [|0xEAuy; 0xFFuy; 0xFFuy; 0xFEuy|].CopyTo(arr, i)\n                writeRet.CopyTo(arr, i + 4) }              // bl r4\n        ] |> concat\n\n    let jmp (offset : int) =\n        let offset = BitConverter.GetBytes(offset).[0..2]\n\n        [[|0xEAuy|]; offset] |> Array.concat |> value  \n\n\n    let printInstructions (data : byte[]) =\n        for i in 0..4..data.Length-1 do\n            let str = data.[i..i+3] |> Array.map (sprintf \"%02X\") |> String.concat \"\"\n            printfn \"%s\" str\n\n\n    let compileCallInternal (f : nativeint) (args : obj[]) =\n        let argSetters =\n            args |> Array.mapi(fun i a ->\n                match a with    \n                    | :? int as a -> setArg i a\n                    | :? nativeint as a -> setArg i (int a)\n                    | _ -> failwithf \"unsupported argument: %A\" a\n            )\n\n        let call = call f\n        [argSetters; [|call|]] |> Array.concat |> concat\n\n    let functionProlog = [|0xe9uy; 0x2duy; 0x48uy; 0x00uy|]\n    let functionEpilog = [|0xe8uy; 0xbduy; 0x88uy; 0x00uy|]\n\n\n    let compileCall (f : nativeint) (args : obj[]) =\n        let writer = compileCallInternal f args\n        runBuilder writer\n\n    let compileCalls (calls : seq<nativeint * obj[]>) =\n        let writer = calls |> Seq.map (fun (f,a) -> compileCallInternal f a) |> concat\n        runBuilder writer\n\n\nmodule Assembler =\n    let os = System.Environment.OSVersion\n    type Architecture = AMD64 | X86 | ARM\n\n    let (|Windows|Linux|Mac|) (p : System.OperatingSystem) =\n        match p.Platform with\n            | System.PlatformID.Unix -> Linux\n            | System.PlatformID.MacOSX -> Mac\n            | _ -> Windows\n\n    let private getLinuxCpuArchitecture() =\n        \n        let ps = System.Diagnostics.ProcessStartInfo(\"lscpu\", \"\")\n        ps.UseShellExecute <- false\n        ps.RedirectStandardOutput <- true\n        let proc = System.Diagnostics.Process.Start(ps)\n        proc.WaitForExit()\n        let cpu = proc.StandardOutput.ReadToEnd()\n        let rx = System.Text.RegularExpressions.Regex @\"Architecture[ \\t]*:[ \\t]*(?<arch>.*)\"\n        let m = rx.Match cpu\n\n        if m.Success then\n            let arch = m.Groups.[\"arch\"].Value\n            match arch with\n                | \"x86_64\" -> AMD64\n                | \"x86\" -> AMD64\n                | _ -> \n                    if arch.Contains \"arm\" then ARM\n                    else failwithf \"unknown architecture: %A\" arch\n        else\n            failwith \"could not determine cpu info\"\n    \n    let cpu = \n        match os with\n            | Windows -> \n                match System.Environment.GetEnvironmentVariable(\"PROCESSOR_ARCHITECTURE\") with\n                    | \"AMD64\" -> AMD64\n                    | _ -> X86\n            | Linux ->\n                getLinuxCpuArchitecture()\n            | Mac ->\n                failwith \"mac currently not supported\"\n\n    module Disasm =\n        let decompile (data : byte[]) : seq<'a> =\n            Seq.empty\n\n    let functionProlog =\n        match os, cpu with\n            | Windows, AMD64 -> Amd64Windows.functionProlog\n            | Linux, AMD64 -> Amd64Linux.functionProlog\n            | Mac, AMD64 -> Amd64Linux.functionProlog\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu    \n                \n    let functionEpilog =\n        match os, cpu with\n            | Windows, AMD64 -> Amd64Windows.functionEpilog\n            | Linux, AMD64 -> Amd64Linux.functionEpilog\n            | Mac, AMD64 -> Amd64Linux.functionEpilog\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu        \n\n    let setArg64 =\n        match os, cpu with\n            | Windows, AMD64 -> Amd64Windows.setArg64\n            | Linux, AMD64 -> Amd64Linux.setArg64\n            | Mac, AMD64 -> Amd64Linux.setArg64\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu   \n\n    let setArg32 =\n        match os, cpu with\n            | Windows, AMD64 -> Amd64Windows.setArg32\n            | Linux, AMD64 -> Amd64Linux.setArg32\n            | Mac, AMD64 -> Amd64Linux.setArg32\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu      \n\n    let setArg32f =\n        match os, cpu with\n            | Windows, AMD64 -> Amd64Windows.setArg32f\n            | _ -> failwithf \"float arguments not implemented for: %A / %A\" os.Platform cpu  \n\n\n    let compileCall =\n        match os, cpu with\n            | Windows, AMD64 -> fun (padding : int) (a,b) -> Amd64Windows.compileCall a b\n            | Linux, AMD64 -> fun (padding : int) (a,b) -> Amd64Linux.compileCall a b\n            | Mac, AMD64 -> fun (padding : int) (a,b) -> Amd64Linux.compileCall a b\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu\n\n    let private compileCallsInternal : seq<nativeint * obj[]> -> byte[] =\n        match os, cpu with\n            | Windows, AMD64 -> Amd64Windows.compileCalls\n            | Linux, AMD64 -> Amd64Linux.compileCalls\n            | Mac, AMD64 -> Amd64Linux.compileCalls\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu\n\n    let compileCalls (padding : int) (calls : #seq<nativeint * obj[]>) = compileCallsInternal calls"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Runtime/Caches.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections.Generic\nopen System.Runtime.CompilerServices\n\n[<AutoOpen>]\nmodule Caches =\n\n    type UnaryCache<'a, 'b when 'a : not struct and 'b : not struct> private(store : Option<ConditionalWeakTable<'a, WeakReference<'b>>>, f : 'a -> 'b) =\n        let store = \n            match store with\n                | Some s -> s\n                | None -> ConditionalWeakTable<'a, WeakReference<'b>>()\n\n        member x.Store = store\n\n        member x.Invoke (a : 'a) =\n            lock store (fun () ->\n                match store.TryGetValue(a) with\n                    | (true, b) -> \n                        match b.TryGetTarget() with\n                        | (true, b) -> b\n                        | _ -> \n                            store.Remove a |> ignore\n                            let b = f a\n                            store.Add(a, WeakReference<'b>(b))\n                            b\n                    | _ ->\n                        let b = f a\n                        store.Add(a, WeakReference<'b>(b))\n                        b\n            )\n\n        new(f : 'a -> 'b) = UnaryCache<'a, 'b>(None, f)\n        new(store : ConditionalWeakTable<'a, WeakReference<'b>>, f : 'a -> 'b) = UnaryCache<'a, 'b>(Some store, f)\n\n    type BinaryCache<'a, 'b, 'c when 'a : not struct and 'b : not struct and 'c : not struct>(f : 'a -> 'b -> 'c) =\n        inherit OptimizedClosures.FSharpFunc<'a, 'b, 'c>()\n\n        // ISSUE: if the computation/cache value holds references to their inputs 'a' and 'b'\n        //        and 'a' is no longer held by the application \n        //         -> 'a' and the computation will not be collected !!\n        //        if 'b' runs out of scope -> 'b' and the computation is collected\n\n        let store = ConditionalWeakTable<'a, ConditionalWeakTable<'b, WeakReference<'c>>>()\n\n        override x.Invoke(a : 'a) =\n            lock store (fun () ->\n                match store.TryGetValue(a) with\n                | (true, inner) ->\n                    UnaryCache<'b, 'c>(inner, f a).Invoke\n                | _ ->\n                    let inner = ConditionalWeakTable()\n                    store.Add(a, inner)\n                    UnaryCache<'b, 'c>(inner, f a).Invoke\n            )\n\n        override x.Invoke(a : 'a, b : 'b) =\n            lock store (fun () ->\n                match store.TryGetValue(a) with\n                | (true, inner) ->\n                    match inner.TryGetValue(b) with\n                    | (true, v) -> \n                        match v.TryGetTarget() with\n                        | (true, v) -> v\n                        | _ ->  \n                            inner.Remove b |> ignore\n                            let v = f a b\n                            inner.Add(b, WeakReference<'c>(v))\n                            v\n\n                    | _ ->\n                        let v = f a b\n                        inner.Add(b, WeakReference<'c>(v))\n                        v\n                | _ ->\n                    let v = f a b\n                    let inner = ConditionalWeakTable<'b, WeakReference<'c>>()\n                    inner.Add(b, WeakReference<'c>(v))\n                    store.Add(a, inner)\n                    v\n            )\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Runtime/CustomSchedulers.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System;\nopen System.Collections\nopen System.Collections.Generic\nopen System.Collections.Concurrent\nopen System.Linq\nopen System.Threading\nopen System.Threading.Tasks\n\ntype CustomTaskScheduler(threadCount : int, priority : ThreadPriority) as this =\n    inherit TaskScheduler()\n\n    let workItems = new BlockingCollection<Task>()\n\n    let threads = \n        [| for i in 0 .. threadCount - 1 do\n            let t = System.Threading.Thread(ThreadStart(fun () ->\n                while true do \n                    let t = workItems.Take()\n                    this.TryExecuteTask t |> ignore\n            ))\n            t.Priority <- ThreadPriority.Lowest\n            t.IsBackground <- true\n            t.Start()\n            yield t\n        |]\n\n    let mutable isDisposed = false\n\n    member x.TryExecuteTask t = base.TryExecuteTask t \n    override x.QueueTask t = workItems.Add t\n    override x.TryExecuteTaskInline (t,p) = x.TryExecuteTask t\n\n    override x.MaximumConcurrencyLevel = threadCount\n    override x.GetScheduledTasks() = workItems.ToArray() :> _\n\n    interface IDisposable with\n        member x.Dispose() =\n            if not isDisposed then\n                isDisposed <- true\n                workItems.CompleteAdding()\n                for t in threads do t.Join()\n                workItems.Dispose()\n\n    new(threadCount) = new CustomTaskScheduler(threadCount,ThreadPriority.Normal)\n    new() = new CustomTaskScheduler(System.Environment.ProcessorCount,ThreadPriority.Normal)"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Runtime/DynamicLinker.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\Bin\\\\Debug\\\\Aardvark.Base.dll\"\nopen Aardvark.Base\n#else\nnamespace Aardvark.Base\n#endif\n\nopen System\nopen System.Reflection\nopen System.Runtime.CompilerServices\n\n/// <summary>\n/// Declares the basic interface for a dynamic linker provided by the OS.\n/// </summary>\nmodule DynamicLinkerTypes =\n    type IDynamicLinker =\n        abstract member LoadLibrary : string -> nativeint\n        abstract member FreeLibrary : nativeint -> unit\n        abstract member GetProcAddress : nativeint -> string -> nativeint\n\n    type Function internal(ptr : nativeint) =\n        member x.Handle = ptr\n\n    type Library internal(ptr : nativeint, linker : IDynamicLinker) =\n        let mutable ptr = ptr\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n\n        member x.Dispose() =\n            if ptr <> 0n then\n                linker.FreeLibrary ptr |> ignore\n                ptr <- 0n\n\n        member x.Handle = ptr\n\n        member x.TryFindFunction (name : string) =\n            if ptr = 0n then\n                None\n            else\n                let ptr = linker.GetProcAddress ptr name\n                if ptr <> 0n then\n                    Function(ptr) |> Some\n                else\n                    None\n\n        member x.GetFunction (name : string) =\n            if ptr <> 0n then\n                Function (linker.GetProcAddress ptr name)\n            else\n                raise <| ObjectDisposedException(\"Library\")\n\n/// <summary>\n/// DynamicLinker provides platform independent functions for loading libraries and\n/// resolving function-pointers within those libraries.\n/// Note that MacOSX is currently not supported\n/// </summary>\nmodule DynamicLinker =\n    open DynamicLinkerTypes\n\n    let private os = System.Environment.OSVersion\n\n    let notimp() = raise <| NotImplementedException()\n\n    \n    let private linker =\n        { new IDynamicLinker with\n            [<MethodImpl(MethodImplOptions.NoInlining)>]\n            member x.LoadLibrary(name : string) = Aardvark.LoadLibrary(name, Assembly.GetCallingAssembly())\n            member x.FreeLibrary(address : nativeint) = ()\n            member x.GetProcAddress (handle : nativeint) (name : string) = Aardvark.GetProcAddress(handle, name)\n        }\n\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    let tryLoadLibrary (name : string) =\n        let ptr = Aardvark.LoadLibrary(name, Assembly.GetCallingAssembly())\n        if ptr <> 0n then new Library(ptr, linker) |> Some\n        else None\n\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    let loadLibrary (name : string) =\n        let ptr = Aardvark.LoadLibrary(name, Assembly.GetCallingAssembly())\n        new Library(ptr, linker)\n\n    let tryLoadFunction (name : string) (lib : Library) =\n        lib.TryFindFunction name\n\n    let tryUnpackNativeLibrary (name : string) =\n        let resname = name + \".zip\"\n        let resourceInfo =\n            Introspection.AllAssemblies |> Seq.tryPick (fun a ->\n                let r = a.GetManifestResourceInfo(resname)\n                if not (isNull r) then Some (a,r)\n                else None\n            )\n\n        match resourceInfo with\n            | Some (ass,res) ->\n                use stream = ass.GetManifestResourceStream(resname)\n                use archive = new System.IO.Compression.ZipArchive(stream)\n\n                let osName =\n                    match os with\n                        | Windows -> \"Windows\"\n                        | Linux -> \"Linux\"\n                        | Mac -> \"Mac\"\n\n                let archName =\n                    if System.IntPtr.Size = 8 then \"AMD64\"\n                    else \"x86\"\n\n                let resName = osName + \"_\" + archName + \"/\"\n\n                let entries = archive.Entries |> Seq.filter (fun e -> e.FullName.StartsWith resName) |> Seq.toList\n\n                match entries with\n                    | [] -> false\n                    | entries ->\n                        for entry in entries do\n                            use stream = entry.Open()\n                            let data = Array.zeroCreate (int entry.Length)\n                            let mutable read = 0\n                            while read < data.Length do\n                                let r = stream.Read(data, read, data.Length - read)\n                                read <- read + r\n\n                            let name = entry.Name\n                            try\n                                System.IO.File.WriteAllBytes(name, data)\n                            with | :? System.IO.IOException as e -> \n                                Log.line \"could not unpack native dependency %s because: %s\" name e.Message\n                        true\n\n\n            | None ->\n                false"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Runtime/Fragments.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections.Generic\nopen System.Threading\nopen System.Runtime.InteropServices\nopen Microsoft.FSharp.NativeInterop\n\n#nowarn \"9\"\n#nowarn \"51\"\n\ntype NativeCall = nativeint * obj[]\n\ntype PtrArgument =\n    | Ptr64 of nativeint\n    | Ptr32 of nativeint\n\nmodule AMD64 =\n    open System.IO\n\n    type Register =\n        | Rax = 0\n        | Rcx = 1\n        | Rdx = 2\n        | Rbx = 3\n        | Rsp = 4\n        | Rbp = 5\n        | Rsi = 6\n        | Rdi = 7\n\n        | R8  = 8\n        | R9  = 9\n        | R10 = 10\n        | R11 = 11\n        | R12 = 12\n        | R13 = 13\n        | R14 = 14\n        | R15 = 15\n\n        | XMM0 = 16\n        | XMM1 = 17\n        | XMM2 = 18\n        | XMM3 = 19\n        | XMM4 = 20\n        | XMM5 = 21\n        | XMM6 = 22\n        | XMM7 = 23\n        | XMM8 = 24\n        | XMM9 = 25\n        | XMM10 = 26\n        | XMM11 = 27\n        | XMM12 = 28\n        | XMM13 = 29\n        | XMM14 = 30\n        | XMM15 = 31\n\n\n    type Value =\n        | Dword of uint32\n        | Qword of uint64\n        | Register of Register\n        | Memory of bool * nativeint\n\n    type Instruction =\n        | Mov of Register * Value\n        | CallRax\n        | Push of offset : int * Value\n        | PushReg of Register\n        | PopReg of Register\n        | Jmp of offset : int\n        | Nop of width : int\n        | Ret\n\n    type ArgumentLocation =\n        | RegisterArgument of Register\n        | StackArgument\n\n    type CallingConvention = { registers : Register[]; floatRegisters : Register[]; calleeSaved : Register[] }\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module CallingConvention =\n        \n        let getArgumentLocation (arg : int) (argType : Type) (cc : CallingConvention) =\n            match argType with\n                | TypeMeta.Patterns.Fractional ->\n                    if arg < cc.floatRegisters.Length then RegisterArgument cc.floatRegisters.[arg]\n                    else StackArgument\n                | _ -> \n                    if arg < cc.registers.Length then RegisterArgument cc.registers.[arg]\n                    else StackArgument\n\n        let tryFindRegister (arg : int) (cc : CallingConvention) =\n            if arg < cc.registers.Length then Some cc.registers.[arg]\n            else None\n\n        let tryFindStackIndex (arg : int) (cc : CallingConvention) =\n            if arg >= cc.registers.Length then Some (arg - cc.registers.Length)\n            else None\n\n    let windows = \n        { \n            registers = [| Register.Rcx; Register.Rdx; Register.R8; Register.R9 |] \n            floatRegisters = [| Register.XMM0; Register.XMM1; Register.XMM2; Register.XMM3 |]\n            calleeSaved = [|Register.R12; Register.R13; Register.R14; Register.R15 |]\n        }\n\n    let linux = \n        { \n            registers = [| Register.Rdi; Register.Rsi; Register.Rdx; Register.Rcx; Register.R8; Register.R9 |] \n            floatRegisters = [||]\n            calleeSaved = [|Register.R12; Register.R13; Register.R14; Register.R15 |]\n        }\n\n    module Compiler =\n        let private cast (v : 'a) : 'b =\n            let mutable v = v\n            &&v |> NativePtr.cast |> NativePtr.read\n             \n        let value (o : obj) =\n            match o with\n                | null -> Qword(0UL)\n                | :? nativeint as o -> Qword(uint64 o)\n                | :? int64 as o -> Qword(uint64 o)\n                | :? int as o -> Dword(uint32 o)\n                | :? unativeint as o -> Qword(uint64 o)\n                | :? uint64 as o -> Qword(o)\n                | :? uint32 as o -> Dword(o)\n                | :? float32 as o -> Dword(cast o)\n                | :? float as o -> Qword(cast o)\n                | :? Register as o -> Register(o)\n                | :? PtrArgument as o ->\n                    match o with\n                        | Ptr32 p -> Memory(false, p)\n                        | Ptr64 p -> Memory(true, p)\n                | _ ->\n                    let t = o.GetType()\n                    if t.IsValueType && Marshal.SizeOf t <= 8 then\n                        let ptr = NativePtr.stackalloc 1\n                        Marshal.StructureToPtr(o, NativePtr.toNativeInt ptr, false)\n                        ptr |> NativePtr.read |> Qword\n                    else\n                        failwithf \"unsupported argument-type: %A\" (o.GetType())\n\n        let stackSize(v : Value) =\n            match v with\n                | Qword _ -> 8\n                | Dword _ -> 8\n                | Register _ -> 8\n                | Memory _ -> 8\n\n        let setArg (cc : CallingConvention) (index : int) (stackOffset : int) (arg : obj) =\n            match cc |> CallingConvention.getArgumentLocation index (arg.GetType()) with\n                | RegisterArgument reg -> \n                    stackOffset, [ Mov(reg, value arg) ]\n                | StackArgument -> \n                    let v = value arg\n                    let s = stackSize v\n                    stackOffset + s, [ Push(stackOffset, value arg) ]\n\n        let call (ptr : nativeint) =\n            [ \n                Mov(Register.Rax, Qword(uint64 ptr))\n                CallRax\n            ]\n\n        let compileCalls (cc : CallingConvention) (dynamicArguments : int) (calls : seq<nativeint * obj[]>) =\n            let res = List<Instruction>()\n\n            for f,args in calls do\n                let mutable stackOffset = 32\n\n                for i in 0..dynamicArguments-1 do\n                    let source = cc.calleeSaved.[i]\n                    let target = cc.registers.[i]\n                    res.Add(Mov(target, Register source))\n\n                for i in 0..args.Length-1 do\n                    let (newOffset,code) = setArg cc (dynamicArguments + i) stackOffset args.[i]\n                    stackOffset <- newOffset\n                    res.AddRange(code)\n\n                res.AddRange(call f)\n\n            res.ToArray()\n\n        let compileCall (cc : CallingConvention) (dynamicArguments : int) (f : nativeint) (args : array<obj>) =\n            compileCalls cc dynamicArguments [f,args]\n\n        let functionProlog (cc : CallingConvention) (dynamicArguments : int) =\n            if dynamicArguments > 0 then\n                let pushTempArgs = \n                    List.init dynamicArguments (fun i -> [PushReg(cc.calleeSaved.[i]); Mov(cc.calleeSaved.[i], Register cc.registers.[i])])\n                        |> List.concat\n                    \n                let pushRsp = PushReg(Register.Rsp)\n\n                pushRsp :: pushTempArgs |> List.toArray\n            else\n                [||]\n\n        let functionEpilog (cc : CallingConvention) (dynamicArguments : int) =\n            if dynamicArguments > 0 then\n                let popTempArgs = \n                    List.init dynamicArguments (fun i -> PopReg(cc.calleeSaved.[i]))\n                    \n                let popRsp = PopReg(Register.Rsp)\n\n                popTempArgs @ [popRsp] |> List.toArray\n            else\n                [||]\n\n    module Decompiler =\n        let rec private decompileAcc (cc : CallingConvention) (rax : Option<Value>) (args : Map<int, Value>) (calls : list<NativeCall>) (l : list<Instruction>) =\n            \n            match l with\n                | PushReg _:: rest ->\n                    decompileAcc cc rax args calls rest\n\n                | PopReg _:: rest ->\n                    decompileAcc cc rax args calls rest\n\n                | CallRax::rest ->\n                    let ptr = \n                        match rax with\n                            | Some (Qword q) -> nativeint q\n                            |_ -> failwith \"[Decompiler] function pointer must be a QWORD\"\n\n                    let args =\n                        args |> Map.toList \n                             |> List.map (fun (_,a) ->\n                                match a with\n                                    | Qword q -> q :> obj\n                                    | Dword d -> d :> obj\n                                    | Register r -> r :> obj\n                                    | Memory(w,ptr) -> \n                                        if w then Ptr64 ptr :> obj\n                                        else Ptr32 ptr :> obj\n                                )\n                             |> List.toArray\n\n                    decompileAcc cc None Map.empty ((ptr, args)::calls) rest\n\n                | Mov(Register.Rax, value)::rest ->\n                    decompileAcc cc (Some value) args calls rest\n\n                | Mov(reg, value)::rest ->\n                    let argIndex = cc.registers |> Array.findIndex (fun r -> r = reg)\n                    if argIndex >= 0 then\n                        decompileAcc cc rax (Map.add argIndex value args) calls rest\n                    else\n                        decompileAcc cc rax args calls rest\n\n                | Push(offset, value)::rest ->\n                    let index = cc.registers.Length + offset / 8\n                    decompileAcc cc rax (Map.add index value args) calls rest\n\n                | Nop(_)::rest ->\n                    decompileAcc cc rax args calls rest\n\n                | [] | (Jmp(_) | Ret)::_ ->\n                    calls\n\n        let decompile (cc : CallingConvention) (instructions : Instruction[]) =\n            let res = decompileAcc cc None Map.empty [] (Array.toList instructions) |> List.toArray\n            Array.Reverse res\n            res\n\n    module Assembler =\n\n        let private oneByteNop       = [|0x90uy|]\n        let private twoByteNop       = [|0x66uy; 0x90uy|]\n        let private threeByteNop     = [|0x0Fuy; 0x1Fuy; 0x00uy|]\n        let private fourByteNop      = [|0x0Fuy; 0x1Fuy; 0x40uy; 0x00uy|]\n        let private fiveByteNop      = [|0x0Fuy; 0x1Fuy; 0x44uy; 0x00uy; 0x00uy|]\n        let private eightByteNop     = [|0x0Fuy; 0x1Fuy; 0x84uy; 0x00uy; 0x00uy; 0x00uy; 0x00uy; 0x00uy|]\n\n        let private printBits (arr : byte[]) =\n            let printSingleBits (b : byte) =\n                for i in 0..7 do\n                    printf \"%d\" ((b >>> (7 - i)) &&& 1uy)\n\n            arr |> Seq.iter printSingleBits\n            printfn \"\"\n\n        let private rexPrefix (wide : bool) (r : byte) (b : byte) =\n            assert(r < 2uy)\n            assert(b < 2uy)\n\n            let w = if wide then 1uy else 0uy\n            0x40uy ||| (w <<< 3) ||| (r <<< 2) ||| b\n\n        let private modRM (l : byte) (r : byte) =\n            assert (l < 8uy)\n            assert (r < 8uy)\n            0xC0uy ||| (l <<< 3) ||| r\n\n        let private rexAndModRM (wide : bool) (left : Register) (right : Register) =\n            let left = int left % 16 |> byte\n            let right = int right % 16 |> byte\n\n            let r, left = if left >= 8uy then 1uy,left-8uy else 0uy,left\n            let b, right = if right >= 8uy then 1uy,right-8uy else 0uy,right\n\n            // AMD Manual Volume 3 Page 21\n            // ModRM layout:\n            // mod |  left   | right\n            // 7 6    5 4 3    2 1 0\n\n            // REX prefix:\n            // [- 4 -] w r x b | [- 0xB8 + id -]\n            // 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0\n            // 0x4\n            rexPrefix wide r b, modRM left right\n\n        let private assembleImmediateMov (wide : bool) (target : Register) (stream : BinaryWriter) =\n            assert (target < Register.XMM0)\n\n            let tb = target |> int |> byte\n\n            let b, tb = if tb >= 8uy then 1uy,tb-8uy else 0uy,tb\n            let rex = rexPrefix wide 0uy b\n            if rex = 0x40uy then stream.Write (0xB8uy + tb)\n            else stream.Write [|rex; 0xB8uy + tb|]\n\n\n        let private assembleRegisterMov (wide : bool) (target : Register) (source : Register) (stream : BinaryWriter) =\n            \n            let rex, modRM = rexAndModRM wide target source\n            let targetMedia = target >= Register.XMM0\n            let sourceMedia = source >= Register.XMM0\n\n            if targetMedia && sourceMedia then\n                failwith \"movd xmm, xmm  not implemented\"\n\n            elif sourceMedia then\n                // MOVD  reg/mem32, xmm         66 0F 7E /r\n                // MOVD  reg/mem64, xmm         66 0F 7E /r\n                stream.Write [|0x66uy; rex; 0x0Fuy; 0x7Euy; modRM|] \n\n            elif targetMedia then\n                // MOVD  xmm, reg/mem32         66 0F 6E /r\n                // MOVD  xmm, reg/mem64         66 0F 6E /r\n                stream.Write [|0x66uy; rex; 0x0Fuy; 0x6Euy; modRM|]   \n\n            else\n                // MOV   reg/mem64, reg64       89/r\n                // MOV   reg64, reg/mem64       8B/r\n                stream.Write [|rex; 0x8Buy; modRM|]\n\n        let private assembleMemoryMov (wide : bool) (target : Register) (source : nativeint) (stream : BinaryWriter) =\n            stream |> assembleImmediateMov true Register.Rax \n            stream.Write(int64 source)\n            if wide then stream.Write 0x48uy\n            stream.Write [|0x8Buy; 0x00uy|]\n            if target <> Register.Rax then\n                stream |> assembleRegisterMov wide target Register.Rax\n            ()\n\n        let private asssemblePushReg (wide : bool) (reg : Register) (stream : BinaryWriter) =\n            let reg = reg |> int |> byte\n            let w = if wide then 1uy else 0uy\n            let b, reg = if reg >= 8uy then 1uy,reg-8uy else 0uy,reg\n\n            let code = 0x50uy + reg\n            let rex = rexPrefix wide 0uy b\n\n            stream.Write [|rex; code|]\n\n        let private asssemblePopReg (wide : bool) (reg : Register) (stream : BinaryWriter) =\n            let reg = reg |> int |> byte\n            let w = if wide then 1uy else 0uy\n            let b, reg = if reg >= 8uy then 1uy,reg-8uy else 0uy,reg\n\n            let code = 0x58uy + reg\n            let rex = rexPrefix wide 0uy b\n\n            stream.Write [|rex; code|]\n\n\n\n        let assembleMov (target : Register) (value : Value) (stream : BinaryWriter) =\n            if target < Register.XMM0 then\n                // general purpose registers\n                match value with\n                    | Qword q -> \n                        stream |> assembleImmediateMov true target\n                        stream.Write q \n                    | Dword d ->\n                        stream |> assembleImmediateMov false target\n                        stream.Write d\n                    | Register r ->\n                        stream |> assembleRegisterMov true target r\n                    | Memory(wide, ptr) ->\n                        \n                        stream |> assembleMemoryMov wide target ptr\n            else\n                // media registers\n                match value with\n                    | Qword q -> \n                        // mov rax, <value>\n                        // mov xmm, rax\n                        stream |> assembleImmediateMov true Register.Rax\n                        stream.Write q \n                        stream |> assembleRegisterMov true target Register.Rax\n                    | Dword d ->\n                        // mov eax, <value>\n                        // mov xmm, eax\n                        stream |> assembleImmediateMov false Register.Rax\n                        stream.Write d\n                        stream |> assembleRegisterMov false target Register.Rax\n                    | Register r ->\n                        // mov xmm, reg\n                        stream |> assembleRegisterMov true target r\n                    | Memory(wide, ptr) ->\n                        stream |> assembleMemoryMov wide target ptr\n\n                \n                ()\n\n\n        let assemblePush (stackOffset : int) (value : Value) (stream : BinaryWriter) =\n            stream |> assembleMov Register.Rax value\n            //asssemblePushReg true Register.Rax stream\n            stream.Write([| 0x48uy; 0x89uy; 0x44uy; 0x24uy; byte stackOffset |])\n\n        let assembleCallRax (stream : BinaryWriter) =\n            stream.Write [|0xFFuy; 0xD0uy|]\n\n        let assembleJmp (offset : int) (stream : BinaryWriter) =\n            stream.Write 0xE9uy\n            stream.Write offset\n\n        let rec assembleNop (width : int) (stream : BinaryWriter) =\n            if width > 0 then\n                match width with\n                    | 1 -> stream.Write oneByteNop\n                    | 2 -> stream.Write twoByteNop\n                    | 3 -> stream.Write threeByteNop\n                    | 4 -> stream.Write fourByteNop\n                    | 5 -> stream.Write fiveByteNop\n                    | 6 -> stream.Write fiveByteNop; assembleNop (width - 5) stream // TODO: find good 6 byte nop sequence\n                    | 7 -> stream.Write fiveByteNop; assembleNop (width - 5) stream // TODO: find good 7 byte nop sequence\n                    | _ -> stream.Write eightByteNop; assembleNop (width - 8) stream\n\n        let assembleRet (stream : BinaryWriter) =\n            stream.Write 0xC3uy\n\n        let assembleInstruction (i : Instruction) (stream : BinaryWriter) =\n            match i with\n                | Mov(r, value)       -> stream |> assembleMov r value\n                | Push(offset, value) -> stream |> assemblePush offset value\n                | CallRax             -> stream |> assembleCallRax\n                | Ret                 -> stream |> assembleRet\n                | Jmp o               -> stream |> assembleJmp o\n                | Nop w               -> stream |> assembleNop w\n                | PushReg r           -> stream |> asssemblePushReg true r\n                | PopReg r            -> stream |> asssemblePopReg true r\n\n        let assembleTo (stream : Stream) (instructions : Instruction[]) =\n            let writer = new BinaryWriter(stream, Text.ASCIIEncoding.ASCII, true)\n            for i in instructions do\n                writer |> assembleInstruction i\n\n        let assemble (instructions : Instruction[]) =\n            use s = new MemoryStream()\n            instructions |> assembleTo s\n            s.Flush()\n            s.ToArray()\n\n    module Disassembler =\n        \n        let fail (current : list<Instruction>) = current\n\n        let rec private disassembleAcc (current : list<Instruction>) (r : BinaryReader) =\n            if r.BaseStream.Position = r.BaseStream.Length then\n                current\n            else\n                let b0 = r.ReadByte()\n\n                match b0 with\n                    // NOP 1\n                    | 0x90uy -> \n                        disassembleAcc ((Nop 1)::current) r\n\n                    | 0x66uy ->\n                        if r.ReadByte() = 0x90uy then disassembleAcc ((Nop 2)::current) r\n                        else fail current\n\n                    | 0x0Fuy ->\n                        let b = r.ReadBytes(2)\n                        match b with\n                            | [| 0x1Fuy; 0x00uy |] -> \n                                disassembleAcc ((Nop 3)::current) r\n\n                            | [| 0x1Fuy; 0x40uy |] -> \n                                r.ReadByte() |> ignore\n                                disassembleAcc ((Nop 4)::current) r\n\n                            | [| 0x1Fuy; 0x44uy |] -> \n                                r.ReadBytes(2) |> ignore\n                                disassembleAcc ((Nop 5)::current) r\n\n                            | [| 0x1Fuy; 0x84uy |] -> \n                                r.ReadBytes(5) |> ignore\n                                disassembleAcc ((Nop 8)::current) r\n\n                            | _ ->\n                                fail current\n\n                    // MOVQ lo registers\n                    | 0x48uy -> \n                        let b1 = r.ReadByte()\n                        match b1 with\n                            | 0x89uy ->\n                                if r.ReadBytes(2) = [|0x44uy; 0x24uy|] then\n                                    let stackOffset = r.ReadByte() |> int\n                                    match current with\n                                        | Mov(Register.Rax, v)::rest ->\n                                            disassembleAcc (Push(stackOffset, v)::rest) r\n                                        | _ ->\n                                            fail current\n\n                                else\n                                    fail current\n                            | _ ->\n                                let reg = b1 - 0xB8uy |> int |> unbox<Register>\n                                let arg = r.ReadUInt64() |> Qword\n                                disassembleAcc (Mov(reg, arg)::current) r\n\n                    // MOVQ hi registers\n                    | 0x49uy -> \n                        let reg = r.ReadByte() - 0xB8uy + 8uy |> int |> unbox<Register>\n                        let arg = r.ReadUInt64() |> Qword\n                        disassembleAcc (Mov(reg, arg)::current) r\n\n                    // MOVD lo registers\n                    | reg when reg >= 0xB8uy && reg <= 0xBFuy ->\n                        let reg = reg - 0xB8uy |> int |> unbox<Register>\n                        let arg = r.ReadUInt32() |> Dword\n                        disassembleAcc (Mov(reg, arg)::current) r\n\n                    // MOVD hi registers\n                    | 0x41uy ->\n                        let reg = r.ReadByte() - 0xB8uy + 8uy |> int |> unbox<Register>\n                        let arg = r.ReadUInt32() |> Dword\n                        disassembleAcc (Mov(reg, arg)::current) r\n\n                    // CALL\n                    | 0xFFuy ->\n                        if r.ReadByte() = 0xD0uy then disassembleAcc (CallRax::current) r\n                        else fail current\n\n                    | 0xE9uy ->\n                        let dist = r.ReadInt32()\n                        (Jmp(dist)::current)\n\n                    | _ ->\n                        fail current\n\n\n        let disassembleFrom (r : BinaryReader) =\n            let res = disassembleAcc [] r\n\n            let rec flattenNops (l : list<Instruction>) =\n                match l with\n                    | (Nop l)::(Nop r)::rest -> flattenNops <| (Nop (l+r))::rest\n                    | i::rest -> i::flattenNops rest\n                    | [] -> []\n\n            res |> List.rev |> flattenNops |> List.toArray\n\n\n        let disassemble (arr : byte[]) =\n            use ms = new MemoryStream(arr)\n            let reader = new BinaryReader(ms)\n            disassembleFrom reader\n\n\nmodule ASM =\n    let os = System.Environment.OSVersion\n    type Architecture = AMD64 | X86 | ARM\n\n    let (|Windows|Linux|Mac|) (p : System.OperatingSystem) =\n        match p.Platform with\n            | System.PlatformID.Unix -> Linux\n            | System.PlatformID.MacOSX -> Mac\n            | _ -> Windows\n\n    let private getLinuxCpuArchitecture() =\n        \n        let ps = System.Diagnostics.ProcessStartInfo(\"uname\", \"-m\")\n        ps.UseShellExecute <- false\n        ps.RedirectStandardOutput <- true\n        let proc = System.Diagnostics.Process.Start(ps)\n        proc.WaitForExit()\n        let cpu = proc.StandardOutput.ReadToEnd().ToLower()\n        if cpu.Contains \"arm\" then ARM\n        else AMD64\n\n    let cpu = \n        match os with\n            | Windows -> \n                match System.Environment.GetEnvironmentVariable(\"PROCESSOR_ARCHITECTURE\") with\n                    | \"AMD64\" -> AMD64\n                    | _ -> X86\n            | _ ->\n                getLinuxCpuArchitecture()\n\n    let functionProlog =\n        let specific =\n            match os, cpu with\n                | Windows, AMD64 -> \n                    fun  (maxArgs : int) ->\n                        let additionalSize =\n                            if maxArgs < 5 then 8uy\n                            else 8 * maxArgs - 24 |> byte\n                        [| 0x48uy; 0x83uy; 0xECuy; 0x20uy + additionalSize |]\n\n                | Linux, AMD64 -> fun (maxArgs : int) -> [||]\n                | Mac, AMD64 -> fun (maxArgs : int) -> [||]\n                | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu    \n              \n        match cpu with  \n            | AMD64 ->\n                let cc = match os with | Windows -> AMD64.windows | _ -> AMD64.linux\n\n                fun (dynamicArgs : int) (maxArgs : int) ->\n                    let real = specific maxArgs\n                    let suffix = AMD64.Compiler.functionProlog cc dynamicArgs |> AMD64.Assembler.assemble\n                    Array.append suffix real\n\n            | _ ->\n                failwithf \"no assembler for: %A / %A\" os.Platform cpu    \n                \n    let functionEpilog =\n        let specific =\n            match os, cpu with\n                | Windows, AMD64 ->\n                    fun (maxArgs : int) ->\n                        let additionalSize =\n                            if maxArgs < 5 then 8uy\n                            else 8 * maxArgs - 24 |> byte\n                        [| 0x48uy; 0x83uy; 0xC4uy; 0x20uy + additionalSize|]\n                | Linux, AMD64 -> fun (maxArgs : int) -> [||]\n                | Mac, AMD64 -> fun (maxArgs : int) -> [||]\n                | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu     \n                 \n        match cpu with  \n            | AMD64 ->\n                let cc = match os with | Windows -> AMD64.windows | _ -> AMD64.linux\n\n                fun (dynamicArgs : int) (maxArgs : int) ->\n                    let real = specific maxArgs\n                    let prefix = AMD64.Compiler.functionEpilog cc dynamicArgs |> AMD64.Assembler.assemble\n                    Array.concat [real; prefix; [|0xC3uy|]]\n\n            | _ ->\n                failwithf \"no assembler for: %A / %A\" os.Platform cpu    \n\n    let private compileCallsNative : int -> seq<NativeCall> -> byte[] =\n         match os, cpu with\n            | Windows, AMD64 -> \n                fun dyn calls -> \n                    AMD64.Compiler.compileCalls AMD64.windows dyn calls |> AMD64.Assembler.assemble\n            | (Linux | Mac), AMD64 -> \n                fun dyn calls -> \n                    AMD64.Compiler.compileCalls AMD64.linux dyn calls |> AMD64.Assembler.assemble\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu      \n\n    let jumpSize =\n        match cpu with\n            | AMD64 -> 5\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu      \n\n    let jumpArgumentOffset =\n        match cpu with\n            | AMD64 -> 1\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu      \n\n    let jumpArgumentAlign =\n        match cpu with\n            | AMD64 -> 4\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu      \n\n    let assembleJump (nopBytes : int) (offset : int) =\n         match cpu with\n            | AMD64 -> AMD64.Assembler.assemble [|AMD64.Nop nopBytes; AMD64.Jmp offset|]\n            | _ -> failwithf \"no assembler for: %A / %A\" os.Platform cpu      \n\n    let assembleCalls (dynamicArguments : int) (calls : #seq<NativeCall>) =\n        calls |> compileCallsNative dynamicArguments\n\n    let disassemble : byte[] -> NativeCall[] =\n        match cpu with\n            | AMD64 -> \n                let cc =\n                    match os with\n                        | Windows -> AMD64.windows\n                        | Linux -> AMD64.linux\n                        | Mac -> AMD64.linux\n\n                fun (data : byte[]) ->\n                    data |> AMD64.Disassembler.disassemble |> AMD64.Decompiler.decompile cc\n\n\n            | _ -> failwithf \"no disassembler for: %A / %A\" os.Platform cpu      \n\n    let encodedJumpSize = jumpSize + (jumpArgumentAlign - 1)\n \n\n[<AllowNullLiteral>]\ntype CodeFragment(memory : managedptr, containsJmp : bool) = \n    let mutable memory = memory\n    let mutable containsJmp = containsJmp\n\n    let startOffsets = List<int>()\n\n    let resetStartOffsets() =\n        startOffsets.[0] <- 0\n        if startOffsets.Count > 1 then\n            startOffsets.RemoveRange(1, startOffsets.Count - 1)\n\n    do startOffsets.Add(0)\n\n    let nonAlignedJumpOffset() =\n        int memory.Size - ASM.encodedJumpSize\n        \n    let alignedJumpArgumentOffset() =\n        let jmpStart = ASM.jumpArgumentOffset + nonAlignedJumpOffset()\n        let a = ASM.jumpArgumentAlign - 1\n        (jmpStart + a) &&& ~~~a\n\n    member x.Calls =\n        memory \n            |> ManagedPtr.readArray 0\n            |> ASM.disassemble\n\n    member x.Offset =\n        memory.Offset\n\n    member x.Memory\n        with get() = memory\n        and set m = memory <- m\n\n    member x.ContainsJmp = containsJmp\n\n\n    member x.WriteNextPointer(target : nativeint) =\n        let jmpArgOffset = alignedJumpArgumentOffset()\n\n        let jmpEndLocation = memory.Offset + nativeint (jmpArgOffset + 4)\n        let jmpArg = int (target - jmpEndLocation)\n\n        if containsJmp then\n            // atomic write here since the offset is 4-byte aligned\n            memory |> ManagedPtr.write jmpArgOffset jmpArg\n        else\n            // if (for some reason) the fragment does currently not end\n            // with a jmp instruction we need to re-create it\n            let jmpStart = nonAlignedJumpOffset()\n            let nopSize = (jmpArgOffset - 1) - jmpStart\n\n            let jmp = ASM.assembleJump nopSize jmpArg\n            memory |> ManagedPtr.writeArray jmpStart jmp\n            containsJmp <- true\n\n        let distance = target - (memory.Offset + nativeint memory.Size) |> int\n        abs distance\n\n    member x.ReadNextPointer() =\n        if containsJmp then\n            let jmpArgOffset = alignedJumpArgumentOffset()\n            let jmpArg : int = memory |> ManagedPtr.read jmpArgOffset\n                \n            let nextPtr = \n                memory.Offset +                             // where am i located\n                nativeint (jmpArgOffset + sizeof<int>) +    // where is the jmp instruction\n                nativeint jmpArg                            // what's the argument of the jmp instruction\n\n            nextPtr\n        else\n            -1n\n\n    member x.Write (calls : NativeCall[]) =\n        resetStartOffsets()\n        calls |> ASM.assembleCalls 0 |> x.Write\n\n    member x.Write (binary : byte[]) =\n        resetStartOffsets()\n        let size = binary.Length + ASM.encodedJumpSize\n\n        if size <> int memory.Size then\n            let n = x.ReadNextPointer()\n            let moved = memory |> ManagedPtr.realloc (nativeint size)\n\n            // patch our own next-pointer since its location was changed\n            containsJmp <- false\n            if n <> -1n then\n                x.WriteNextPointer(n) |> ignore\n            //x.FixJumps moved\n\n            memory |> ManagedPtr.writeArray 0 binary\n        else\n            memory |> ManagedPtr.writeArray 0 binary\n\n\n    member x.Append (data : byte[]) =\n        let id = startOffsets.Count - 1\n        let oldSize = int memory.Size\n        let newSize = oldSize + data.Length\n\n        // realloc the memory\n        let moved = memory |> ManagedPtr.realloc (nativeint newSize)\n        containsJmp <- false\n\n        // write the data to the new region\n        memory |> ManagedPtr.writeArray (oldSize - ASM.encodedJumpSize) data\n\n        // if the block moved update the jump\n        //x.FixJumps moved\n\n        startOffsets.Add (newSize - ASM.encodedJumpSize)\n        id\n\n    member x.Update(id : int, data : byte[]) =\n        let startOffset = startOffsets.[id]\n        let endOffset = startOffsets.[id + 1]\n        let length = endOffset - startOffset\n\n        if length = data.Length then\n            // if the length did not change simply write the new data\n            memory |> ManagedPtr.writeArray startOffset data\n        else\n            let restSize = int memory.Size - endOffset\n            let delta = length - data.Length\n\n\n            let moved = \n                if delta > 0 then\n                    let moved = memory |> ManagedPtr.realloc (memory.Size + nativeint delta)\n                    // move all subsequent sub-blocks to the right (making space for data)\n                    memory |> ManagedPtr.move endOffset (endOffset + delta) restSize\n                    moved\n                else\n                    // move all subsequent sub-blocks to the left\n                    memory |> ManagedPtr.move endOffset (endOffset + delta) restSize\n                    memory |> ManagedPtr.realloc (memory.Size + nativeint delta)\n            containsJmp <- false\n\n            // write the data\n            memory |> ManagedPtr.writeArray startOffset data\n\n            // adjust all subsequent offsets\n            for i in id+1..startOffsets.Count-1 do\n                startOffsets.[i] <- startOffsets.[i] + delta\n\n\n    member x.Remove(id : int) =\n        x.Update(id, [||])\n\n    member x.Clear() =\n        resetStartOffsets()\n        let moved = memory |> ManagedPtr.realloc (nativeint ASM.encodedJumpSize)\n        containsJmp <- false\n\n    member x.Dispose() =\n        if not (isNull memory) then\n            ManagedPtr.free memory\n            memory <- null\n            containsJmp <- false\n\n\n\n    new(manager : MemoryManager, content : byte[]) =\n        let ptr = manager.Alloc(nativeint (content.Length + ASM.encodedJumpSize))\n        ptr |> ManagedPtr.writeArray 0 content\n        CodeFragment(ptr, false)\n\n    new(manager : MemoryManager, calls : NativeCall[]) = new CodeFragment(manager, calls |> ASM.assembleCalls 0)\n    new(manager : MemoryManager) = new CodeFragment(manager, ([||] : byte[]))\n\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule CodeFragment =\n\n    let inline prolog (maxArgs : int) (m : MemoryManager) =\n        new CodeFragment(m, ASM.functionProlog 0 maxArgs)\n\n    let inline epilog (maxArgs : int) (m : MemoryManager) =\n        new CodeFragment(m, ASM.functionEpilog 0 maxArgs)\n\n    let inline ofCalls (calls : seq<NativeCall>) (m : MemoryManager) =\n        new CodeFragment(m, Seq.toArray calls)\n\n    let inline update (calls : seq<NativeCall>) (f : CodeFragment) =\n        f.Write (Seq.toArray calls)\n\n    let inline destroy (f : CodeFragment) =\n        f.Dispose()\n\n    let inline offset (f : CodeFragment) =\n        f.Offset\n\n    let usePointer (f : CodeFragment) (func : nativeint -> 'a) =\n        let manager = f.Memory.Parent\n        ReaderWriterLock.read manager.PointerLock (fun () ->\n            let ptr = manager.Pointer + f.Offset\n            func ptr\n        )\n\n    let wrap (f : CodeFragment) : unit -> unit =\n        let current = ref 0n\n        let run = ref id\n\n        fun () ->\n            usePointer f (fun p ->\n                if p <> !current then\n                    current := p\n                    run := UnmanagedFunctions.wrap p\n\n                (!run)()\n            )\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Runtime/NativeMemory.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections.Generic\nopen System.Threading\nopen System.Runtime.InteropServices\nopen Aardvark.Base\nopen Microsoft.FSharp.NativeInterop\n\n#nowarn \"9\"\n#nowarn \"44\"\n\ntype FreeList<'k, 'v when 'k : comparison>() =\n    static let comparer = { new IComparer<struct('k * HashSet<'v>)> with member x.Compare((l,_), (r,_)) = compare l r }\n    let sortedSet = SortedSetExt comparer\n    let sets = Dictionary<'k, HashSet<'v>>()\n\n    let tryGet (minimal : 'k) =\n        let (struct(_, hasSelf, hasRight), _, self, right) = sortedSet.FindNeighboursV((minimal, Unchecked.defaultof<_>))\n    \n        let fitting =\n            if hasSelf then ValueSome self\n            elif hasRight then ValueSome right\n            else ValueNone\n        \n        match fitting with\n            | ValueSome (k, container) -> \n\n                if container.Count <= 0 then\n                    raise <| ArgumentException \"invalid memory manager state\"\n\n                let any = container |> Seq.head\n                container.Remove any |> ignore\n\n                // if the container just got empty we remove it from the\n                // sorted set and the cache-dictionary\n                if container.Count = 0 then\n                   sortedSet.Remove(k, container) |> ignore\n                   sets.Remove(k) |> ignore\n\n                Some any\n\n            | ValueNone -> None\n\n    let tryGetV (minimal : 'k) =\n        let (struct(_, hasSelf, hasRight), _, self, right) = sortedSet.FindNeighboursV((minimal, Unchecked.defaultof<_>))\n    \n        let fitting =\n            if hasSelf then ValueSome self\n            elif hasRight then ValueSome right\n            else ValueNone\n        \n        match fitting with\n            | ValueSome (k, container) -> \n\n                if container.Count <= 0 then\n                    raise <| ArgumentException \"invalid memory manager state\"\n\n                let any = container |> Seq.head\n                container.Remove any |> ignore\n\n                // if the container just got empty we remove it from the\n                // sorted set and the cache-dictionary\n                if container.Count = 0 then\n                   sortedSet.Remove(k, container) |> ignore\n                   sets.Remove(k) |> ignore\n\n                ValueSome any\n\n            | ValueNone -> ValueNone\n\n    let insert (k : 'k) (v : 'v) =\n        match sets.TryGetValue k with\n            | (true, container) ->\n                container.Add(v) |> ignore\n            | _ ->\n                let container = HashSet [v]\n                sortedSet.Add(k, container) |> ignore\n                sets.[k] <- container\n\n    let remove (k : 'k) (v : 'v) =\n        let (hasValue, value) = sortedSet.FindValue((k, Unchecked.defaultof<_>))\n   \n        if hasValue then\n            let struct(_,container) = value\n\n            if container.Count <= 0 then\n                raise <| ArgumentException \"invalid memory manager state\"\n\n            let res = container.Remove v\n\n            // if the container just got empty we remove it from the\n            // sorted set and the cache-dictionary\n            if container.Count = 0 then\n                sortedSet.Remove(k, container) |> ignore\n                sets.Remove(k) |> ignore\n\n            res\n        else \n            false\n\n    let contains (k : 'k) (v : 'v) =\n        let (hasValue, value) = sortedSet.FindValue((k, Unchecked.defaultof<_>))\n   \n        if hasValue then\n            let struct(_,container) = value\n            container.Contains v\n        else \n            false\n\n\n    member x.Values =\n        seq {\n            for _,s in sortedSet do\n                yield! s\n        }\n\n\n    member x.TryGetGreaterOrEqual (minimal : 'k) = tryGet minimal\n    member x.TryGetGreaterOrEqualV (minimal : 'k) = tryGetV minimal\n    member x.Insert (key : 'k, value : 'v) = insert key value\n    member x.Remove (key : 'k, value : 'v) = remove key value\n    member x.Contains (key : 'k, value : 'v) = contains key value\n    member x.Clear() =\n        sortedSet.Clear()\n        sets.Clear()\n\nmodule ReaderWriterLock =\n    let read (l : ReaderWriterLockSlim) (f : unit -> 'a) =\n        if l.IsReadLockHeld || l.IsWriteLockHeld then\n            f()\n        else\n            try\n                l.EnterReadLock()\n                f()\n            finally\n                if l.IsReadLockHeld then\n                    l.ExitReadLock()\n\n    let write (l : ReaderWriterLockSlim) (f : unit -> 'a) =\n        if l.IsWriteLockHeld then\n            f()\n        else\n            try\n                l.EnterWriteLock()\n                f()\n            finally\n                if l.IsWriteLockHeld then\n                    l.ExitWriteLock()\n\n\ntype MemoryManagerConfig =\n    {\n        malloc : nativeint -> nativeint\n        mfree : nativeint -> nativeint -> unit\n        mcopy : nativeint -> nativeint -> nativeint -> unit\n\n    }\n\n\n[<AllowNullLiteral>]\ntype internal Block =\n    class\n        val mutable public Parent : MemoryManager\n        val mutable public Offset : nativeint\n        val mutable public Size : nativeint\n        val mutable public Prev : Block\n        val mutable public Next : Block\n        val mutable public Free : bool\n\n        override x.ToString() =\n            if x.Size < 0n then \"invalid\"\n            else sprintf \"[%d:%d]\" x.Offset (x.Offset + x.Size)\n\n\n        static member Invalid = Block(Unchecked.defaultof<_>, 0n, 0n, null, null, true)\n\n        new(parent, o,s,p,n,f) = { Parent = parent; Offset = o; Size = s; Prev = p; Next = n; Free = f }\n    end\n\nand [<AllowNullLiteral>] managedptr internal(block : Block) =\n    let mutable block = block\n\n    #if DEBUG\n    let check() =\n        if isNull block then raise <| ObjectDisposedException(\"MemoryBlock\")\n    #else\n    let check() = ()\n    #endif\n\n\n    member x.Parent = check(); block.Parent\n    member x.Size = if isNull block then 0n else block.Size\n    member x.Offset = if isNull block then 0n else block.Offset\n    member x.Free = if isNull block then true else block.Free\n\n    override x.ToString() = \n        if isNull block then \"(null)\"\n        else string block\n\n    member internal x.Block\n        with get() = block\n        and set b = block <- b\n\n    member x.Use(action : nativeint -> 'r) =\n        ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n            action (block.Parent.Pointer + block.Offset)\n        )\n\n    member x.Write(offset : int, source : nativeint, size : int) =\n        check()\n        if nativeint (offset + size) > block.Size then failwith \"[Memory] write exceeding size\"\n\n        ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n            let target = block.Parent.Pointer + block.Offset + nativeint offset\n            Marshal.Copy(source, target, size)\n        )\n\n    member x.Read(offset : int, target : nativeint, size : int) =\n        check()\n        if nativeint (offset + size) > block.Size then failwith \"[Memory] read exceeding size\"\n\n        ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n            let source = block.Parent.Pointer + block.Offset + nativeint offset\n            Marshal.Copy(source, target, size)\n        )\n\n    member x.Write(offset : int, data : 'a) =\n        check()\n        if nativeint (offset + sizeof<'a>) > block.Size then failwith \"[Memory] write exceeding size\"\n\n        ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n            let ptr = block.Parent.Pointer + block.Offset + nativeint offset |> NativePtr.ofNativeInt\n            NativePtr.write ptr data\n        )\n\n    member x.Read(offset : int) : 'a =\n        check()\n        if nativeint (offset + sizeof<'a>) > block.Size then failwith \"[Memory] read exceeding size\"\n\n        ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n            let ptr = block.Parent.Pointer + block.Offset + nativeint offset |> NativePtr.ofNativeInt\n            NativePtr.read ptr\n        )\n\n    member x.Write(offset : int, data : 'a[]) =\n        check()\n        if nativeint (offset + sizeof<'a> * data.Length) > block.Size then failwith \"[Memory] write exceeding size\"\n\n        ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n            let mutable ptr = block.Parent.Pointer + block.Offset + nativeint offset |> NativePtr.ofNativeInt\n            for i in 0..data.Length-1 do\n                NativePtr.set ptr i data.[i]\n        )\n\n\n    member x.Read(offset : int, data : 'a[]) =\n        check()\n        if nativeint (offset + sizeof<'a> * data.Length) > block.Size then failwith \"[Memory] read exceeding size\"\n\n        ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n            let mutable ptr = block.Parent.Pointer + block.Offset + nativeint offset |> NativePtr.ofNativeInt\n            for i in 0..data.Length-1 do\n                data.[i] <- NativePtr.get ptr i\n        )\n\n    member x.Read(offset : int, count : int) : 'a[] =\n        check()\n        if offset + sizeof<'a> * count > int block.Size then failwith \"[Memory] read exceeding size\"\n\n        let arr = Array.zeroCreate count\n        x.Read(offset, arr)\n        arr\n\n    member x.Move(sourceOffset : int, targetOffset : int, length : int) =\n        check()\n        ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n            Marshal.Move(\n                x.Parent.Pointer + x.Offset + nativeint sourceOffset,\n                x.Parent.Pointer + x.Offset + nativeint targetOffset,\n                length\n            )\n        )\n\n    member x.CopyTo(target : managedptr) =\n        check()\n        ReaderWriterLock.read target.Parent.PointerLock (fun () ->\n            ReaderWriterLock.read block.Parent.PointerLock (fun () ->\n                Marshal.Move(\n                    block.Parent.Pointer + block.Offset,\n                    target.Parent.Pointer + target.Offset,\n                    min block.Size target.Size\n                )\n            )\n        )\n\n    member x.Int8Array      : int8[]    = x.Read(0, int block.Size)\n    member x.Int16Array     : int16[]   = x.Read(0, int block.Size / 2)\n    member x.Int32Array     : int[]     = x.Read(0, int block.Size / 4)\n    member x.Int64Array     : int64[]   = x.Read(0, int block.Size / 8)\n\n    member x.UInt8Array     : uint8[]   = x.Read(0, int block.Size)\n    member x.UInt16Array    : uint16[]  = x.Read(0, int block.Size / 2)\n    member x.UInt32Array    : uint32[]  = x.Read(0, int block.Size / 4)\n    member x.UInt64Array    : uint64[]  = x.Read(0, int block.Size / 8)\n\nand MemoryManager(capacity : nativeint, config : MemoryManagerConfig) as this =\n    let mutable capacity = capacity\n    let mutable allocated = 0n\n\n    let mutable ptr = config.malloc capacity\n    let freeList = FreeList<nativeint, Block>()\n    let l = obj()\n    let pointerLock = new ReaderWriterLockSlim()\n   \n    \n    let mutable firstBlock = Block(this, 0n, capacity, null, null, true)\n    let mutable lastBlock = firstBlock\n    do freeList.Insert(firstBlock.Size, firstBlock)\n\n    let readPointer (f : unit -> 'a) = ReaderWriterLock.read pointerLock f\n    let writePointer (f : unit -> 'a) = ReaderWriterLock.write pointerLock f\n\n    let validation () =\n        let mutable last = null\n        let mutable current = firstBlock\n        while not (isNull current) do\n            assert (current.Prev = last)\n\n            assert(current.Size > 0n)\n            assert(current.Offset >= 0n)\n\n            if not (isNull last) then\n                assert(last.Offset + nativeint last.Size = current.Offset)\n\n                if last.Free then\n                    assert(last.Free <> current.Free)\n                    assert(freeList.Contains(last.Size, last))\n                else\n                    assert(not <| freeList.Contains(last.Size, last))\n            last <- current\n            current <- current.Next\n\n    let free (b : Block) : unit =\n        assert (not (isNull b))\n\n        if not b.Free && b.Size > 0n then\n            allocated <- allocated - b.Size\n            // merge b with its prev (if it's free)\n            let prev = b.Prev\n            if not (isNull prev) && prev.Free then \n                assert(prev.Next = b)\n                assert(prev.Offset + nativeint prev.Size = b.Offset)\n\n                if freeList.Remove(prev.Size, prev) then\n                    // b now occupies the memory of both blocks\n                    b.Offset <- prev.Offset\n                    b.Size <- prev.Size + b.Size\n\n                    // all links to prev now link to b\n                    if isNull prev.Prev then firstBlock <- b\n                    else prev.Prev.Next <- b\n\n                    // b's prev now links wherever prev's prev linked to\n                    b.Prev <- prev.Prev\n\n                    assert(isNull firstBlock.Prev)\n\n                else\n                    failwithf \"[Memory] could not remove %A from freeList\" prev\n\n            // merge b with its next (if it's free)\n            let next = b.Next\n            if not (isNull next) && next.Free then \n                assert(next.Prev = b)\n                assert(next.Offset = b.Offset + nativeint b.Size)\n\n                if freeList.Remove(next.Size, next) then\n\n                    // b now occupies the memory of both blocks\n                    b.Size <- next.Size + b.Size\n\n                    // all links to next now link to b\n                    if isNull next.Next then lastBlock <- b\n                    else next.Next.Prev <- b\n\n                    // b's prev now links wherever prev's prev linked to\n                    b.Next <- next.Next\n\n                    assert(isNull lastBlock.Next)\n\n                else\n                    failwithf \"[Memory] could not remove %A from freeList\" prev\n\n            // tell b that it's free and add it to the freeList\n            b.Free <- true\n            freeList.Insert(b.Size, b)\n\n    let resize (additional : nativeint) =\n        assert (additional > 0n)\n\n        let oldCapacity = capacity\n        let newCapacity = Fun.NextPowerOfTwo(int64 (capacity + additional)) |> nativeint\n        writePointer (fun () ->\n            let n = config.malloc newCapacity\n            config.mcopy ptr n oldCapacity\n\n            config.mfree ptr capacity\n            ptr <- n\n            capacity <- newCapacity\n        )\n\n        let newMemory = Block(this, nativeint oldCapacity, newCapacity - oldCapacity, lastBlock, null, false)\n        lastBlock.Next <- newMemory\n        lastBlock <- newMemory\n        allocated <- allocated + newMemory.Size\n\n        free newMemory\n\n\n    let rec alloc (size : nativeint) : Block =\n        if size <= 0n then\n            null\n        else\n            match freeList.TryGetGreaterOrEqualV(size) with\n                | ValueSome block ->\n                    block.Free <- false\n                    allocated <- allocated + block.Size\n\n                    if block.Size > size then\n                        let rest = Block(this, block.Offset + size, block.Size - size, block, block.Next, false)\n\n                        if isNull block.Next then lastBlock <- rest\n                        else block.Next.Prev <- rest\n\n                        assert(isNull lastBlock.Next)\n\n                        block.Next <- rest\n                        block.Size <- size\n\n                        free rest\n\n                    block\n                | ValueNone ->\n                    // if there was no block of sufficient size resize the entire\n                    // memory and retry\n                    resize size\n                    alloc size\n        \n    let rec realloc (b : Block) (size : nativeint) : bool * Block =\n\n        if b.Size = size then\n            false, b\n\n        elif b.Free then\n            failwithf \"[Memory] cannot realloc free block: %A\" b\n\n        elif size > b.Size then\n            if not (isNull b.Next) && b.Next.Free && isNull b.Next.Next && b.Next.Size + b.Size < size then\n                \n                resize (size - b.Next.Size - b.Size)\n                realloc b size\n\n            elif isNull b.Next || not b.Next.Free || b.Next.Size + b.Size < size then\n                // alloc a completely new block and copy the contents there\n                let n = alloc size\n                readPointer (fun () -> config.mcopy (ptr + b.Offset) (ptr + n.Offset) b.Size)\n\n                free b\n\n                true, n\n\n            else\n                let next = b.Next\n                assert(next.Offset = b.Offset + b.Size)\n\n                if freeList.Remove(next.Size, next) then\n                    allocated <- allocated + next.Size\n                    next.Free <- false\n\n                    let additionalSize = size - b.Size\n                    b.Size <- size\n\n\n                    if next.Size > additionalSize then\n                        // if next is larger than needed we free the rest\n                        next.Offset <- b.Offset + nativeint size\n                        next.Size <- next.Size - additionalSize\n\n                        assert(next.Offset = b.Offset + b.Size)\n\n                        free next\n                    else\n                        // if next fits our requirements exactly it is deleted from the\n                        // linked list and finally destroyed\n                        b.Next <- next.Next\n                        if isNull next.Next then lastBlock <- b\n                        else next.Next.Prev <- b\n\n                        assert(isNull lastBlock.Next)\n                        //destroy next\n\n\n                    false, b\n                else \n                    failwith \"[Memory] could not remove free block from freeList\"\n\n        else (* if size < b.Size then *)\n            // if the block \"shrinked\" we can simply create and free the\n            // leftover memory\n            let rest = Block(this, b.Offset + size, b.Size - size, b, b.Next, false)\n            b.Size <- size\n\n            if isNull b.Next then lastBlock <- rest\n            else b.Next.Prev <- rest\n            b.Next <- rest\n\n            assert(isNull lastBlock.Next)\n            assert(b.Offset + b.Size = rest.Offset)\n\n            free rest\n\n            false, b\n\n    let allocAligned (align : nativeint) (size : nativeint) : Block =\n        let maxSize = size + align - 1n\n        let block = alloc maxSize\n        \n        let prev = block.Prev\n        let next = block.Next\n\n\n        let r = block.Offset % align\n        let alignedOffset = \n            if r = 0n then block.Offset\n            else align + block.Offset - r\n\n        let leftOffset = block.Offset\n        let leftSize =\n            if r = 0n then 0n\n            else align - r\n\n        let rightOffset = alignedOffset + size\n        let rightSize = maxSize - size - leftSize\n        \n\n        assert (leftSize + size + rightSize = maxSize)\n        assert (leftOffset + leftSize = alignedOffset)\n\n        if leftSize <> 0n then\n            let l = Block(this, leftOffset, leftSize, prev, block, false)\n\n            if isNull prev then firstBlock <- l\n            else prev.Next <- l\n            block.Prev <- l\n\n            block.Offset <- alignedOffset\n            block.Size <- block.Size - leftSize\n            free l\n\n        if rightSize <> 0n then\n            let r = Block(this, rightOffset, rightSize, block, next, false)\n\n            if isNull next then lastBlock <- r\n            else next.Prev <- r\n            block.Next <- r\n\n            block.Size <- block.Size - rightSize\n            free r\n\n        assert (block.Size = size)\n        assert (block.Offset % align = 0n)\n        block\n\n\n\n\n\n    let clone (b : Block) : Block =\n        if b.Free then failwithf \"[Memory] cannot spill free block: %A\" b\n\n        let n = alloc b.Size\n        readPointer (fun () -> Marshal.Copy(ptr + b.Offset, ptr + n.Offset, b.Size))\n        n\n\n    member x.Pointer : nativeint = ptr\n    member x.PointerLock : ReaderWriterLockSlim = pointerLock\n\n    member x.Capacity = capacity\n    member x.AllocatedBytes = allocated\n    member x.FreeBytes = capacity - allocated\n\n    member x.FreeList =\n        freeList.Values |> Seq.map (fun b -> managedptr(b))\n\n    member x.FirstUsedByte = \n        if firstBlock.Free then firstBlock.Offset + nativeint firstBlock.Size\n        else firstBlock.Offset\n\n    member x.LastUsedByte =\n        if lastBlock.Free then lastBlock.Offset - 1n\n        else lastBlock.Offset + nativeint lastBlock.Size - 1n\n\n    member x.Dispose() =\n        if ptr <> 0n then\n            config.mfree ptr capacity\n            ptr <- 0n\n            capacity <- 0n\n            allocated <- 0n\n            freeList.Clear()\n            pointerLock.Dispose()\n            firstBlock <- null\n            lastBlock <- null\n\n    member x.Alloc (size : nativeint) = \n        lock l (fun () ->\n            let block = alloc size\n            managedptr block\n        )\n\n    member x.AllocAligned (align : nativeint, size : nativeint) = \n        lock l (fun () ->\n            let block = allocAligned align size\n            managedptr block\n        )\n\n    member x.Free (ptr : managedptr) = \n        lock l (fun () -> \n            if not (isNull ptr.Block) then\n                ptr.Block |> free\n                ptr.Block <- null\n        )\n\n    member x.Realloc (ptr : managedptr, size : nativeint) = \n        lock l (fun () -> \n            if not (isNull ptr.Block) then\n                if size <= 0n then\n                    free ptr.Block\n                    ptr.Block <- null\n                    false\n                else\n                    let (moved, newBlock) = realloc ptr.Block size\n                    ptr.Block <- newBlock\n                    moved\n            else\n                if size <= 0n then false\n                else failwith \"[Memory] cannot realloc free managedptr\"\n        )\n\n    member x.Spill (ptr : managedptr) = \n        lock l (fun () -> \n            if not (isNull ptr.Block) then\n                let block = ptr.Block\n                let cloned = clone block\n                ptr.Block <- cloned\n                managedptr(block)\n            else\n                failwith \"[Memory] cannot spill free managedptr\"\n        )\n\n    member x.Validate() =\n        lock l (fun () ->\n            validation()\n        )\n\n    member x.Lock = l\n\n    new(cap,malloc,mfree) = new MemoryManager(cap, { malloc = malloc; mfree = mfree; mcopy = fun a b s -> Marshal.Copy(a, b, s)})\n\n    interface IDisposable with\n        member x.Dispose() = x.Dispose()\n\n\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule MemoryManager =\n    let createHGlobal() = new MemoryManager(16n, Marshal.AllocHGlobal, fun ptr _ -> Marshal.FreeHGlobal ptr)\n\n    let private nopConfig = { malloc = (fun _ -> 0n); mfree = (fun _ _ -> ()); mcopy = (fun _ _ _ -> ()) }\n    let createNop() = new MemoryManager(16n, nopConfig)\n\n    let inline alloc (size : nativeint) (m : MemoryManager) =\n        m.Alloc size\n\n    let inline free (b : managedptr) (m : MemoryManager) =\n        m.Free b\n\n    let inline realloc (b : managedptr) (size : nativeint) (m : MemoryManager) =\n        m.Realloc(b, size)\n\n    let inline spill (b : managedptr) (m : MemoryManager) =\n        m.Spill b\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule ManagedPtr =\n    let inline parent (b : managedptr) = b.Parent\n    let inline size (b : managedptr) = b.Size\n    let inline offset (b : managedptr) = b.Offset\n    let inline isFree (b : managedptr) = b.Free\n\n    let inline realloc (size : nativeint) (b : managedptr) =\n        if b.Free then\n            if size <> 0n then failwith \"[Memory] cannot realloc free managedptr\"\n            false\n        else\n            b.Parent.Realloc(b, size)\n\n    let inline free (b : managedptr) =\n        if not b.Free then\n            b.Parent.Free(b)\n\n    let inline spill (b : managedptr) =\n        if b.Free then\n            failwith \"[Memory] cannot spill free managedptr\"\n        else\n            b.Parent.Spill(b)\n\n    let inline write (offset : int) (value : 'a) (b : managedptr) =\n        b.Write(offset, value)\n\n    let inline writeArray (offset : int) (value : 'a[]) (b : managedptr) =\n        b.Write(offset, value)\n\n    let inline read (offset : int) (b : managedptr) =\n        b.Read(offset)\n\n    let inline readArray (offset : int) (b : managedptr) : 'a[] =\n        b.Read(offset, int (b.Size / nativeint sizeof<'a>))\n\n    let inline move (sourceOffset : int) (targetOffset : int) (length : int) (b : managedptr) =\n        b.Move(sourceOffset, targetOffset, length)\n\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Runtime/WeakTable.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\..\\\\Bin\\\\Debug\\\\Aardvark.Base.dll\"\n#else\nnamespace Aardvark.Base\n#endif\nopen System\nopen System.Reflection\nopen System.Linq.Expressions\nopen System.Threading\nopen System.Runtime.InteropServices\nopen System.Collections.Generic\n\nmodule DependentHandle =\n    module Api = \n        let flags = BindingFlags.NonPublic ||| BindingFlags.Static\n        let depType = Type.GetType(\"System.Runtime.CompilerServices.DependentHandle\") \n\n        //nInitialize\n        let nInitializeMeth = depType.GetMethod(\"nInitialize\", flags)\n        type NInitDel = delegate of obj * obj * byref<nativeint> -> unit\n        let nInitializeDel =\n            let p = Expression.Parameter(typeof<obj>, \"primary\")\n            let s = Expression.Parameter(typeof<obj>, \"secondary\")\n            let h = Expression.Parameter(typeof<nativeint>.MakeByRefType(), \"handle\")\n \n            let ex = Expression.Lambda<NInitDel>(Expression.Call(nInitializeMeth, p, s, h), [p;s;h])\n            ex.Compile()\n\n        let nInitialize (primary : obj, secondary : obj, handle : byref<nativeint>) =\n            nInitializeDel.Invoke(primary, secondary, &handle)\n\n        //nFree\n        let nFreeMeth = depType.GetMethod(\"nFree\", flags)\n        type NFreeDel = delegate of nativeint -> unit\n        let nFreeDel =\n            let h = Expression.Parameter(typeof<nativeint>)\n\n            let ex = Expression.Lambda<NFreeDel>(Expression.Call(nFreeMeth, h), [h])\n            ex.Compile()\n\n        let nFree (handle : nativeint) =\n            nFreeDel.Invoke(handle)\n\n\n        //nGetPrimary\n        let nGetPrimaryMeth = depType.GetMethod(\"nGetPrimary\", flags)\n        type NGetPrimaryDel = delegate of nativeint * byref<obj> -> unit\n        let nGetPrimaryDel =\n            let h = Expression.Parameter(typeof<nativeint>)\n            let p = Expression.Parameter(typeof<obj>.MakeByRefType())\n            let ex = Expression.Lambda<NGetPrimaryDel>(Expression.Call(nGetPrimaryMeth, h, p), [h;p])\n            ex.Compile()\n\n        let nGetPrimary (handle : nativeint, primary : byref<obj>) =\n            nGetPrimaryDel.Invoke(handle, &primary)\n\n        //nGetPrimaryAndSecondary\n        let nGetPrimaryAndSecondaryMeth = depType.GetMethod(\"nGetPrimaryAndSecondary\", flags)\n        type NGetPrimaryAndSecondaryDel = delegate of nativeint * byref<obj> * byref<obj> -> unit\n        let nGetPrimaryAndSecondaryDel =\n            let h = Expression.Parameter(typeof<nativeint>)\n            let p = Expression.Parameter(typeof<obj>.MakeByRefType())\n            let s = Expression.Parameter(typeof<obj>.MakeByRefType())\n            let ex = Expression.Lambda<NGetPrimaryAndSecondaryDel>(Expression.Call(nGetPrimaryAndSecondaryMeth, h, p, s), [h;p;s])\n            ex.Compile()\n\n        let nGetPrimaryAndSecondary (handle : nativeint, primary : byref<obj>, secondary : byref<obj>) =\n            nGetPrimaryAndSecondaryDel.Invoke(handle, &primary, &secondary)\n\n    type DependentHandle<'k, 'v when 'k : not struct and 'v : not struct>(primary : 'k, secondary : 'v) =\n        let mutable handle = 0n\n        do Api.nInitialize(primary :> obj, secondary :> obj, &handle)\n\n        member x.IsAllocated =\n            handle <> 0n\n\n        member x.Primary =\n            if handle <> 0n then\n                let mutable prim = null\n                Api.nGetPrimary(handle, &prim)\n                if isNull prim then \n                    None\n                else\n                    Some (prim |> unbox<'k>)\n            else\n                None\n\n        member x.PrimaryAndSecondary =\n            if handle <> 0n then\n                let mutable prim = null\n                let mutable sec = null\n                Api.nGetPrimaryAndSecondary(handle, &prim, &sec)\n\n                if not (isNull prim) && not (isNull sec) then\n                    Some (prim |> unbox<'k>, sec |> unbox<'v>)\n                else\n                    None\n\n            else\n                None\n\n        member x.Secondary =\n            match x.PrimaryAndSecondary with\n                | Some (_,s) -> Some s\n                | None -> None\n\n        member x.Dispose() =\n            let old = Interlocked.Exchange(&handle, 0n)\n            if old <> 0n then\n                Api.nFree(old)\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n\n    let makeDependent (a : 'a) (b : 'b) =\n        new DependentHandle<'a, 'b>(a, b)\n\n\n    let test() =\n        let mutable a = obj()\n        let h = makeDependent a \"some other string\"\n\n        printfn \"%A\" h.PrimaryAndSecondary\n        a <- null\n        System.GC.Collect()\n\n        printfn \"%A\" h.PrimaryAndSecondary\n\n        h.Dispose()\n\nmodule WeakTable =\n    open DependentHandle\n\n    type private Weak<'a when 'a : not struct>(value : 'a) =\n        do if isNull (value :> obj) then failwith \"created null weak\"\n        let wr = System.WeakReference<'a>(value)\n        let hash = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(value)\n\n        member x.IsLife =\n            match wr.TryGetTarget() with\n                | (true, o) when not (isNull (o :> obj)) -> true\n                | _ -> false\n\n        member x.TargetOption =\n            match wr.TryGetTarget() with\n                | (true, t) -> Some t\n                | _ -> None\n\n        override x.GetHashCode() =\n            hash\n\n        override x.Equals o =\n            match o with\n                | :? Weak<'a> as o -> \n                    match x.TargetOption, o.TargetOption with\n                        | Some l, Some r -> System.Object.ReferenceEquals(l,r)\n                        | None, None -> true\n                        | _ -> false\n                | _ -> false\n\n//    [<StructuredFormatDisplay(\"{AsString}\")>]\n//    type WeakTable<'k, 'v when 'k : not struct and 'v : not struct>() =\n//        let store = Dictionary<Weak<'k>, DependentHandle<'k, 'v>>()\n//        let l = obj()\n//\n//        let prune() =\n//            printfn \"prune: %d\" store.Count\n//            lock l (fun () ->\n//                let dead = store.Keys |> Seq.filter (fun w -> not w.IsLife) |> Seq.toArray\n//                for d in dead do\n//                    let dep = store.[d]\n//                    dep.Dispose()\n//                    store.Remove d |> ignore\n//            )\n//\n//        let mutable lastPrune = 0\n//\n//        let pruneIfLeakLarge() =\n//            let lowerPowerOfTwo = Fun.NextPowerOfTwo(store.Count) / 2\n//            if lowerPowerOfTwo > lastPrune then\n//                prune()\n//                lastPrune <- lowerPowerOfTwo\n//\n//        member x.TryGetValue(key : 'k, [<Out>] result : byref<'v>) =\n//            let r =\n//                lock l (fun () ->\n//                    let key = Weak key\n//                    match store.TryGetValue key with\n//                        | (true, dep) -> \n//                            match dep.Secondary with\n//                                | Some v ->\n//                                    Some v\n//                                | None ->\n//                                    dep.Dispose()\n//                                    store.Remove key |> ignore\n//                                    None\n//                        | _ -> None\n//                )\n//            match r with\n//                | Some r -> \n//                    result <- r\n//                    true\n//                | None ->\n//                    false\n//\n//        member x.Item \n//            with get key = match x.TryGetValue(key) with | (true,v) -> v | _ -> failwith \"sdsadsa\"\n//\n//        member x.Add(key : 'k, value : 'v) =\n//            lock l (fun () ->\n//                let dep = makeDependent key value\n//                store.Add(Weak key, dep)\n//                pruneIfLeakLarge()\n//            )\n//            \n//\n//        member x.Remove(key : 'k) =\n//            lock l (fun () ->\n//                let key = Weak key\n//                match store.TryGetValue key with\n//                    | (true, dep) -> \n//                        dep.Dispose()\n//                        store.Remove(key) |> ignore\n//                        true\n//                    | _ ->  \n//                        false\n//            )     \n//\n//        member x.Clear() =\n//            lock l (fun () ->\n//                store.Values |> Seq.iter(fun d -> d.Dispose())\n//                store.Clear()\n//                lastPrune <- 0\n//            )\n//\n//        member x.AsString =\n//            store.Values |> Seq.choose (fun v -> v.PrimaryAndSecondary) |> Seq.toList |> sprintf \"WeakTable %A\"\n//\n//    let empty<'k, 'v when 'k : not struct and 'v : not struct> = WeakTable<'k, 'v>()\n//\n//    let add (key : 'k) (value : 'v) (table : WeakTable<'k, 'v>) =\n//        table.Add(key, value)\n//\n//    let remove (key : 'k) (table : WeakTable<'k, 'v>) =\n//        table.Remove(key)\n//\n//    let clear (table : WeakTable<'k, 'v>) =\n//        table.Clear()\n//\n//    let find (key : 'k) (t : WeakTable<'k, 'v>) =\n//        t.[key]\n//\n//    let tryFind (key : 'k) (t : WeakTable<'k, 'v>) =\n//        match t.TryGetValue key with\n//            | (true, v) -> Some v\n//            | _ -> None\n//\n//    let test() =\n//        let table = WeakTable<obj, string>()\n//\n//        let mutable a = obj()\n//        let mutable b = obj()\n//\n//        table.Add(a, \"a\")\n//        table.Add(b, \"b\")\n//\n//        printfn \"%A\" table\n//\n//        a <- null\n//        System.GC.Collect()\n//        printfn \"%A\" table\n//\n//        b <- if not (isNull a) then b else null\n//        System.GC.Collect()\n//        printfn \"%A\" table\n//\n//        let str = sprintf \"%A %A\" a b\n//        ()\n//\n//    let testPruning() =\n//        let t = empty\n//\n//        for i in 0..1000 do\n//            add (obj()) (sprintf \"%d\" i) t\n//\n//        printfn \"%A\" t\n//\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/IO.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System.IO\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule IO =\n    let alterFileName (str: string) (f: string -> string) = Path.Combine (Path.GetDirectoryName str, f (Path.GetFileName str))\n\n    let createFileStream path =\n        if File.Exists path\n        then File.Delete path\n        new FileStream(path, FileMode.CreateNew)\n\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Path =\n\n    /// Combines a sequence of strings into a path.\n    let combine (paths: seq<string>) =\n        Path.Combine(paths |> Seq.toArray)\n\n    /// Combines two strings into a path.\n    let andPath (first: string) (second: string) =\n        Path.Combine(first, second)\n\n    /// Normalizes the directory separators of the given path, i.e. replaces\n    /// the alternative separator with the default separator.\n    let normalizeDirectorySeparators (path: string) =\n        path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar)\n\n    /// Adds a trailing slash unless the path already has one.\n    let withTrailingSlash (path: string) =\n#if NET6_0_OR_GREATER\n        if path.EndsWith Path.DirectorySeparatorChar || path.EndsWith Path.AltDirectorySeparatorChar then\n#else\n        if path.EndsWith(string Path.DirectorySeparatorChar) || path.EndsWith(string Path.AltDirectorySeparatorChar) then\n#endif\n            path\n        else\n            path + string Path.DirectorySeparatorChar\n\n    /// Removes the trailing slash from the given path if it has one.\n    let withoutTrailingSlash (path: string) =\n#if NET6_0_OR_GREATER\n        if path.EndsWith Path.DirectorySeparatorChar || path.EndsWith Path.AltDirectorySeparatorChar then\n#else\n        if path.EndsWith(string Path.DirectorySeparatorChar) || path.EndsWith(string Path.AltDirectorySeparatorChar)  then\n#endif\n            path.Substring(0, path.Length - 1)\n        else\n            path\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Stream =\n\n    /// <summary>\n    /// Copies a stream.\n    /// </summary>\n    /// <param name=\"stream\">Stream to copy.</param>\n    /// <returns>A new stream with the content of the input stream.</returns>\n    let copy (stream: Stream) : Stream =\n        let result =\n            if stream.CanSeek then\n                new MemoryStream(int stream.Length)\n            else\n                new MemoryStream()\n\n        stream.CopyTo result\n        result.Position <- 0L\n        result\n\n    /// <summary>\n    /// Reads the content of a stream into a byte array.\n    /// </summary>\n    /// <param name=\"stream\">Stream to read.</param>\n    /// <returns>A byte array containing the content of the input stream.</returns>\n    let readAllBytes (stream: Stream) =\n        if stream.CanSeek then\n            let buffer = Array.zeroCreate<byte> <| int stream.Length\n            use ms = new MemoryStream(buffer)\n            stream.CopyTo ms\n            buffer\n        else\n            use ms = new MemoryStream()\n            stream.CopyTo ms\n            ms.ToArray()\n\n    /// <summary>\n    /// Copies the content of a non-seekable stream to a seekable stream. The original stream is disposed, unless <paramref name=\"leaveOpen\"/> is <c>true</c>.\n    /// If the input stream is already seekable, it is returned as is.\n    /// </summary>\n    /// <param name=\"leaveOpen\">If <c>false</c> the input stream is disposed after copying, otherwise it remains open.</param>\n    /// <param name=\"stream\">Stream to copy.</param>\n    /// <returns>A seekable stream with the content of the input stream.</returns>\n    let toSeekable (leaveOpen: bool) (stream: Stream) : Stream =\n        if stream.CanSeek then stream\n        else\n            try\n                copy stream\n            finally\n                if not leaveOpen then stream.Dispose()\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule File =\n\n    /// <summary>\n    /// Creates the parent directory of the given file path, if it does not exist.\n    /// </summary>\n    /// <param name=\"path\">The path of the file, whose parent directory is to be created.</param>\n    let createParentDirectory (path : string) =\n        let info = FileInfo(path)\n        if not info.Directory.Exists then\n            info.Directory.Create()\n\n    /// <summary>\n    /// Creates a new file, writes the specified string array to the file, and then closes the file.\n    /// </summary>\n    /// <param name=\"path\">The file to write to.</param>\n    /// <param name=\"lines\">The lines to write to the file.</param>\n    let writeAllLines (path : string) (lines : string[]) =\n        File.WriteAllLines(path, lines)\n\n    /// <summary>\n    /// Creates a new file, writes the specified string array to the file, and then closes the file.\n    /// If the parent directory does not exist, it is created first.\n    /// </summary>\n    /// <param name=\"path\">The file to write to.</param>\n    /// <param name=\"lines\">The lines to write to the file.</param>\n    let writeAllLinesSafe (path : string) (lines : string[]) =\n        createParentDirectory path\n        File.WriteAllLines(path, lines)\n\n    /// <summary>\n    /// Creates a new file, writes the specified string to the file, and then closes the file.\n    /// </summary>\n    /// <param name=\"path\">The file to write to.</param>\n    /// <param name=\"text\">The string to write to the file.</param>\n    let writeAllText (path : string) (text : string) =\n        File.WriteAllText(path, text)\n\n    /// <summary>\n    /// Creates a new file, writes the specified string to the file, and then closes the file.\n    /// If the parent directory does not exist, it is created first.\n    /// </summary>\n    /// <param name=\"path\">The file to write to.</param>\n    /// <param name=\"text\">The string to write to the file.</param>\n    let writeAllTextSafe (path : string) (text : string) =\n        createParentDirectory path\n        File.WriteAllText(path, text)\n\n    /// <summary>\n    /// Creates a new file, writes the specified byte array to the file, and then closes the file.\n    /// </summary>\n    /// <param name=\"path\">The file to write to.</param>\n    /// <param name=\"bytes\">The bytes to write to the file.</param>\n    let writeAllBytes (path : string) (bytes : uint8[]) =\n        File.WriteAllBytes(path, bytes)\n\n    /// <summary>\n    /// Creates a new file, writes the specified byte array to the file, and then closes the file.\n    /// If the parent directory does not exist, it is created first.\n    /// </summary>\n    /// <param name=\"path\">The file to write to.</param>\n    /// <param name=\"bytes\">The bytes to write to the file.</param>\n    let writeAllBytesSafe (path : string) (bytes : uint8[]) =\n        createParentDirectory path\n        File.WriteAllBytes(path, bytes)\n\n    /// <summary>\n    /// Opens a text file, reads all lines of the file into a string array, and then closes the file.\n    /// </summary>\n    /// <param name=\"path\">The file to open for reading.</param>\n    /// <returns>A string array containing all lines of the file.</returns>\n    let readAllLines (path : string) =\n        File.ReadAllLines path\n\n    /// <summary>\n    /// Opens a text file, reads all the text in the file into a string, and then closes the file.\n    /// </summary>\n    /// <param name=\"path\">The file to open for reading.</param>\n    /// <returns>A string containing all the text in the file.</returns>\n    let readAllText (path : string) =\n        File.ReadAllText path\n\n    /// <summary>\n    /// Opens a binary file, reads the contents of the file into a byte array, and then closes the file.\n    /// </summary>\n    /// <param name=\"path\">The file to open for reading.</param>\n    /// <returns>A byte array containing the contents of the file.</returns>\n    let readAllBytes (path : string) =\n        File.ReadAllBytes path"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Interop/ArraySegment.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule ArraySegment =\n\n    #if !NETSTANDARD2_1_OR_GREATER\n    [<AutoOpen>]\n    module private Extensions =\n        type ArraySegment<'T> with\n            member inline x.Item(index : int) = x.Array.[x.Offset + index]\n    #endif\n\n    let inline tryHeadV (segment : ArraySegment<'T>) =\n        if segment.Count > 0 then ValueSome segment.[0]\n        else ValueNone\n\n    let inline copyArray (segment : ArraySegment<'T>) =\n        let arr = Array.zeroCreate<'T> segment.Count\n        Array.Copy(segment.Array, segment.Offset, arr, 0, arr.Length)\n        arr\n\n    let inline copy (segment : ArraySegment<'T1>) =\n        ArraySegment (copyArray segment)\n\n    let inline mapArray (mapping : 'T1 -> 'T2) (segment : ArraySegment<'T1>) =\n        Array.init segment.Count (fun i -> mapping segment.[i])\n\n    let inline map (mapping : 'T1 -> 'T2) (segment : ArraySegment<'T1>) =\n        ArraySegment (segment |> mapArray mapping)\n\n    /// Tests if the array segment contains the specified element.\n    let inline contains (value : 'T) (segment : ArraySegment<'T>) =\n        let mutable state = false\n        let mutable i = 0\n\n        while not state && i < segment.Count do\n            state <- value = segment.[i]\n            i <- i + 1\n\n        state\n\n    let inline reduce (reduction : 'T -> 'T -> 'T) (segment : ArraySegment<'T>) =\n        if segment.Count = 0 then\n            invalidArg \"segment\" \"Cannot reduce an empty ArraySegment.\"\n        else\n            let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt (reduction)\n            let mutable res = segment.[0]\n\n            for i = 1 to segment.Count - 1 do\n                res <- f.Invoke(res, segment.[i])\n\n            res\n\n    /// Forms a slice of the specified length out of the array segment starting at the specified index.\n    let inline slice (start : int) (count : int) (segment : ArraySegment<'T>) =\n        #if NETSTANDARD2_1_OR_GREATER\n        segment.Slice(start, count)\n        #else\n        ArraySegment<'T>(segment.Array, segment.Offset + start, count)\n        #endif\n\n    /// Forms a slice out of the array segment starting at the specified index.\n    let inline sliceFrom (start : int) (segment : ArraySegment<'T>) =\n        #if NETSTANDARD2_1_OR_GREATER\n        segment.Slice(start)\n        #else\n        ArraySegment<'T>(segment.Array, segment.Offset + start, segment.Count - start)\n        #endif"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Interop/CSharpList.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System.Collections.Generic\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule CSharpList =\n\n\n    let inline add (v : 'a) (l : List<'a>) = l.Add v\n    let inline addRange (elements : seq<'a>) (l : List<'a>) = l.AddRange elements\n    let inline removeAt (index : int) (l : List<'a>) = l.RemoveAt index\n    let inline clear (l : List<'a>) = l.Clear()\n    let inline insert (index : int) (value : 'a) (l : List<'a>) = l.Insert(index, value)\n\n    let inline map (f : 'a -> 'b) (l : List<'a>) = l.Map f\n\n    let inline collect ([<InlineIfLambda>] f : 'a -> seq<'b>) (l : List<'a>) =\n        let res = List()\n        for e in l do\n            res.AddRange (f e)\n        res\n\n    let inline choose ([<InlineIfLambda>] f : 'a -> Option<'b>) (l : List<'a>) =\n        let res = List()\n        for e in l do\n            match f e with\n                | Some v -> res.Add v\n                | None -> ()\n\n        res\n\n    let inline filter ([<InlineIfLambda>] f : 'a -> bool) (l : List<'a>) =\n        let res = List()\n        for e in l do\n            if f e then res.Add e\n\n        res\n\n    let append (l : List<'a>) (r : List<'a>) =\n        let res = List(l)\n        res.AddRange r\n        res\n        \n    let concat (l : seq<List<'a>>) =\n        let res = List()\n        for e in l do\n            res.AddRange e\n        res\n\n\n    let inline count (l : List<'a>) = l.Count\n\n    let inline iter ([<InlineIfLambda>] f : 'a -> unit) (l : List<'a>) =\n        for i in 0..l.Count-1 do\n            f l.[i]\n\n    let inline iteri (f : int -> 'a -> unit) (l : List<'a>) =\n        let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n        for i in 0..l.Count-1 do\n            f.Invoke(i, l.[i])\n\n\n    let empty<'a> : List<'a> = List()\n\n    let ofSeq (elements : seq<'a>) : List<'a> =\n        List elements\n\n    let ofList (elements : list<'a>) : List<'a> =\n        List elements\n\n    let ofArray (elements : 'a[]) : List<'a> =\n        List elements\n\n    let toList (l : List<'a>) : list<'a> =\n        let mutable res = []\n        for i in 1..l.Count do\n            let i = l.Count - i\n            res <- l.[i]::res\n        res\n\n    let toArray (l : List<'a>) : 'a[] =\n        l.ToArray()\n\n    let toSeq (l : List<'a>) : seq<'a> =\n        l :> _\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Interop/Dictionary.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Dictionary =\n    open System.Collections.Generic\n\n    let empty<'k, 'v when 'k : equality> = Dictionary<'k, 'v>()\n    let emptyNoEquality<'k,'v> =\n        Dictionary<'k,'v>(\n            { new IEqualityComparer<'k> with\n                    member x.Equals(a,b)    = Unchecked.equals a b\n                    member x.GetHashCode(t) = Unchecked.hash t\n            })\n\n    let inline add (key : 'k) (value : 'v) (d : Dictionary<'k, 'v>) =\n        d.Add(key,value)\n\n    let inline set (key : 'k) (value : 'v) (d : Dictionary<'k, 'v>) =\n        d.[key] <- value\n\n    let inline remove (key : 'k) (d : Dictionary<'k, 'v>) =\n        d.Remove key\n\n    let inline clear (d : Dictionary<'k, 'v>) =\n        d.Clear()\n\n    let inline map (f : 'k -> 'a -> 'b) (d : Dictionary<'k, 'a>) =\n        let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n        let result = Dictionary(capacity = d.Count)\n        for (KeyValue(k,v)) in d do\n            result.[k] <- f.Invoke(k, v)\n        result\n\n    let inline mapKeys (f : 'k -> 'a -> 'b) (d : Dictionary<'k, 'a>) =\n        let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n        let result = Dictionary(capacity = d.Count)\n        for (KeyValue(k,v)) in d do\n            result.[f.Invoke(k, v)] <- v\n        result\n\n    let inline union (dicts : #seq<Dictionary<'k, 'v>>) =\n        let result = Dictionary()\n        for d in dicts do\n            for v in d do\n                result.[v.Key] <- v.Value\n        result\n\n    let inline contains (key : 'k) (d : Dictionary<'k, 'v>) =\n        d.ContainsKey key\n\n    let inline tryFind (key : 'k) (d : Dictionary<'k, 'v>) =\n        match d.TryGetValue key with\n        | (true, v) -> Some v\n        | _ -> None\n\n    let inline tryFindV (key : 'k) (d : Dictionary<'k, 'v>) =\n        let mutable value = Unchecked.defaultof<_>\n        if d.TryGetValue(key, &value) then ValueSome value\n        else ValueNone\n\n    let inline ofSeq (elements : seq<'k * 'v>) =\n        let result = Dictionary()\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofSeqV (elements : seq<struct('k * 'v)>) =\n        let result = Dictionary()\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofList (elements : list<'k * 'v>) =\n        ofSeq elements\n\n    let inline ofListV (elements : list<struct('k * 'v)>) =\n        ofSeqV elements\n\n    let inline ofArray (elements : ('k * 'v)[]) =\n        let result = Dictionary(capacity = elements.Length)\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofArrayV (elements : (struct('k * 'v))[]) =\n        let result = Dictionary(capacity = elements.Length)\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofMap (elements : Map<'k, 'v>) =\n        elements |> Map.toSeq |> ofSeq\n\n    let inline toSeq (d : Dictionary<'k, 'v>) =\n        d |> Seq.map (fun (KeyValue(k,v)) -> k,v)\n\n    let inline toSeqV (d : Dictionary<'k, 'v>) =\n        d |> Seq.map (fun (KeyValue(k,v)) -> struct(k,v))\n\n    let inline toList (d : Dictionary<'k, 'v>) =\n        d |> toSeq |> Seq.toList\n\n    let inline toListV (d : Dictionary<'k, 'v>) =\n        d |> toSeqV |> Seq.toList\n\n    let inline toArray (d : Dictionary<'k, 'v>) =\n        d |> toSeq |> Seq.toArray\n\n    let inline toArrayV (d : Dictionary<'k, 'v>) =\n        d |> toSeqV |> Seq.toArray\n\n    let inline toMap (d : Dictionary<'k, 'v>) =\n        d |> toSeq |> Map.ofSeq\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Dict =\n\n    #if __SLIM__\n    let empty<'k, 'v> = Dictionary.emptyNoEquality<'k,'v>\n    #else\n    let empty<'k, 'v> = Dict<'k,'v>()\n    #endif\n\n    let inline add (key : 'k) (value : 'v) (d : Dict<'k, 'v>) =\n        d.Add(key,value)\n\n    let inline set (key : 'k) (value : 'v) (d : Dict<'k, 'v>) =\n        d.[key] <- value\n\n    let inline remove (key : 'k) (d : Dict<'k, 'v>) =\n        d.Remove key\n\n    let inline clear (d : Dict<'k, 'v>) =\n        d.Clear()\n\n    let inline keys (k : Dict<'k,'v>) =\n        #if __SLIM__\n        k.Keys |> Seq.map id\n        #else\n        k.Keys\n        #endif\n    let inline values (k : Dict<'k,'v>) =\n        #if __SLIM__\n        k.Values |> Seq.map id\n        #else\n        k.Values\n        #endif\n    let inline keyValues (k : Dict<'k,'v>) =\n        #if __SLIM__\n        k |> Seq.map id\n        #else\n        k.KeyValuePairs\n        #endif\n\n    let inline map (f : 'k -> 'a -> 'b) (d : Dict<'k, 'a>) =\n        let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n        let result = Dict(initialCapacity = d.Count)\n        for (KeyValue(k,v)) in d do\n            result.[k] <- f.Invoke(k, v)\n        result\n\n    let inline mapKeys (f : 'k -> 'a -> 'b) (d : Dict<'k, 'a>) =\n        let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n        let result = Dict(initialCapacity = d.Count)\n        for (KeyValue(k,v)) in d do\n            result.[f.Invoke(k, v)] <- v\n        result\n\n    let inline union (dicts : #seq<Dict<'k, 'v>>) =\n        let result = Dict()\n        for d in dicts do\n            for (KeyValue(k,v)) in d do\n                result.[k] <- v\n        result\n\n    let inline contains (key : 'k) (d : Dict<'k, 'v>) =\n        d.ContainsKey key\n\n    let inline tryFind (key : 'k) (d : Dict<'k, 'v>) =\n        match d.TryGetValue key with\n        | (true, v) -> Some v\n        | _ -> None\n\n    let inline tryFindV (key : 'k) (d : Dict<'k, 'v>) =\n        let mutable value = Unchecked.defaultof<_>\n        if d.TryGetValue(key, &value) then ValueSome value\n        else ValueNone\n\n    let inline ofSeq (elements : seq<'k * 'v>) =\n        let result = Dict()\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofSeqV (elements : seq<struct('k * 'v)>) =\n        let result = Dict()\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofList (elements : list<'k * 'v>) =\n        ofSeq elements\n\n    let inline ofListV (elements : list<struct('k * 'v)>) =\n        ofSeqV elements\n\n    let inline ofArray (elements : ('k * 'v)[]) =\n        let result = Dict(initialCapacity = elements.Length)\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofArrayV (elements : struct('k * 'v)[]) =\n        let result = Dict(initialCapacity = elements.Length)\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofMap (elements : Map<'k, 'v>) =\n        elements |> Map.toSeq |> ofSeq\n\n    let inline toSeq (d : Dict<'k, 'v>) =\n        d |> Seq.map (fun (KeyValue(k,v)) -> k,v)\n\n    let inline toSeqV (d : Dict<'k, 'v>) =\n        d |> Seq.map (fun (KeyValue(k,v)) -> struct(k,v))\n\n    let inline toList (d : Dict<'k, 'v>) =\n        d |> toSeq |> Seq.toList\n\n    let inline toListV (d : Dict<'k, 'v>) =\n        d |> toSeqV |> Seq.toList\n\n    let inline toArray (d : Dict<'k, 'v>) =\n        d |> toSeq |> Seq.toArray\n\n    let inline toArrayV (d : Dict<'k, 'v>) =\n        d |> toSeqV |> Seq.toArray\n\n    let inline toMap (d : Dict<'k, 'v>) =\n        d |> toSeq |> Map.ofSeq\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule SymDict =\n\n    let empty<'v> = SymbolDict<'v>()\n\n    let inline add (key : Symbol) (value : 'v) (d : SymbolDict<'v>) =\n        d.Add(key,value)\n\n    let inline set (key : Symbol) (value : 'v) (d : SymbolDict<'v>) =\n        d.[key] <- value\n\n    let inline remove (key : Symbol) (d : SymbolDict<'v>) =\n        d.Remove key\n\n    let inline clear (d : SymbolDict<'v>) =\n        d.Clear()\n\n    let inline map (f : Symbol -> 'a -> 'b) (d : SymbolDict<'a>) =\n        let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n        let result = SymbolDict(initialCapacity = d.Count)\n        for (KeyValue(k,v)) in d do\n            result.[k] <-  f.Invoke(k, v)\n        result\n\n    let inline mapKeys (f : Symbol -> 'a -> Symbol) (d : SymbolDict<'a>) =\n        let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f\n        let result = SymbolDict(initialCapacity = d.Count)\n        for (KeyValue(k,v)) in d do\n            result.[f.Invoke(k, v)] <- v\n        result\n\n    let inline union (dicts : #seq<SymbolDict<'v>>) =\n        let result = SymbolDict()\n        for d in dicts do\n            for v in d do\n                result.[v.Key] <- v.Value\n        result\n\n    let inline contains (key : Symbol) (d : SymbolDict<'v>) =\n        d.ContainsKey key\n\n    let inline tryFind (key : Symbol) (d : SymbolDict<'v>) =\n        match d.TryGetValue key with\n        | (true, v) -> Some v\n        | _ -> None\n\n    let inline tryFindV (key : Symbol) (d : SymbolDict<'v>) =\n        let mutable value = Unchecked.defaultof<_>\n        if d.TryGetValue(key, &value) then ValueSome value\n        else ValueNone\n\n    let inline ofSeq (elements : seq<Symbol * 'v>) =\n        let result = SymbolDict()\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofSeqV (elements : seq<struct(Symbol * 'v)>) =\n        let result = SymbolDict()\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofList (elements : list<Symbol * 'v>) =\n        ofSeq elements\n\n    let inline ofListV (elements : list<struct(Symbol * 'v)>) =\n        ofSeqV elements\n\n    let inline ofArray (elements : (Symbol * 'v)[]) =\n        let result = SymbolDict(initialCapacity = elements.Length)\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofArrayV (elements : (struct(Symbol * 'v))[]) =\n        let result = SymbolDict(initialCapacity = elements.Length)\n        for (k,v) in elements do\n            result.[k] <- v\n        result\n\n    let inline ofMap (elements : Map<Symbol, 'v>) =\n        elements |> Map.toSeq |> ofSeq\n\n    let inline toSeq (d : SymbolDict<'v>) =\n        d |> Seq.map (fun (KeyValue(k,v)) -> k,v)\n\n    let inline toSeqV (d : SymbolDict<'v>) =\n        d |> Seq.map (fun (KeyValue(k,v)) -> struct (k,v))\n\n    let inline toList (d : SymbolDict<'v>) =\n        d |> toSeq |> Seq.toList\n\n    let inline toListV (d : SymbolDict<'v>) =\n        d |> toSeqV |> Seq.toList\n\n    let inline toArray (d : SymbolDict<'v>) =\n        d |> toSeq |> Seq.toArray\n\n    let inline toArrayV (d : SymbolDict<'v>) =\n        d |> toSeqV |> Seq.toArray\n\n    let inline toMap (elements : SymbolDict<'v>) =\n        elements |> toSeq |> Map.ofSeq\n\n\n[<AutoOpen>]\nmodule CSharpCollectionExtensions =\n    open System.Collections.Generic\n\n    type Dictionary<'Key, 'Value> with\n        member inline x.TryFind(key : 'Key) : 'Value option = Dictionary.tryFind key x\n        member inline x.TryFindV(key : 'Key) : 'Value voption = Dictionary.tryFindV key x\n\n    type Dict<'Key, 'Value> with\n        member inline x.TryFind(key : 'Key) : 'Value option = Dict.tryFind key x\n        member inline x.TryFindV(key : 'Key) : 'Value voption = Dict.tryFindV key x\n\n    type SymbolDict<'Value> with\n        member inline x.TryFind(key : Symbol) : 'Value option = SymDict.tryFind key x\n        member inline x.TryFindV(key : Symbol) : 'Value voption = SymDict.tryFindV key x"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Interop/FSLibExtensions.fs",
    "content": "﻿namespace Aardvark.Base\n\n#nowarn \"9\"\n\nopen System\nopen FSharp.NativeInterop\n\n[<AutoOpen>]\nmodule Prelude =\n\n    type Type with\n        /// The managed size of the type.\n        member inline this.CLRSize = this.GetCLRSize()\n\n    [<AutoOpen>]\n    module ``Assignment Operators`` =\n\n        // Arithmetic\n        let inline ( += ) (x: byref<'T1>) (y: 'T2) = x <- x + y\n        let inline ( -= ) (x: byref<'T1>) (y: 'T2) = x <- x - y\n        let inline ( *= ) (x: byref<'T1>) (y: 'T2) = x <- x * y\n        let inline ( /= ) (x: byref<'T1>) (y: 'T2) = x <- x / y\n        let inline ( %= ) (x: byref<'T1>) (y: 'T2) = x <- x % y\n\n        // Boolean\n        let inline ( ||= ) (x: byref<bool>) (y: bool) = x <- x || y\n        let inline ( &&= ) (x: byref<bool>) (y: bool) = x <- x && y\n\n        // Bitwise\n        let inline ( |||= ) (x: byref<'T>) (y: 'T) = x <- x ||| y\n        let inline ( &&&= ) (x: byref<'T>) (y: 'T) = x <- x &&& y\n        let inline ( ^^^= ) (x: byref<'T>) (y: 'T) = x <- x ^^^ y\n        let inline ( <<<= ) (value: byref<'T>) (shift: int) = value <- value <<< shift\n        let inline ( >>>= ) (value: byref<'T>) (shift: int) = value <- value >>> shift\n\n    [<Obsolete>]\n    let inc (a:byref<int>) = a <- a + 1\n\n    [<Obsolete>]\n    let dec (a:byref<int>) = a <- a - 1\n\n    [<AutoOpen>]\n    module ``Generic Increments`` =\n\n        /// Increments the given value by one.\n        let inline inc (value: byref<'T>) = value <- value + LanguagePrimitives.GenericOne<'T>\n\n        /// Decrements the given value by one.\n        let inline dec (value: byref<'T>) = value <- value - LanguagePrimitives.GenericOne<'T>\n\n    module ``Null Coalescing Helpers`` =\n\n        [<AbstractClass; Sealed>]\n        type Coalescing() =\n            static member inline Coalesce(x: 'T option, y: 'T)         = match x with Some x -> x | _ -> y\n            static member inline Coalesce(x: 'T option, y: unit -> 'T) = match x with Some x -> x | _ -> y()\n            static member inline Coalesce(x: 'T option, y: Lazy<'T>)   = match x with Some x -> x | _ -> y.Value\n\n            static member inline Coalesce(x: 'T voption, y: 'T)         = match x with ValueSome x -> x | _ -> y\n            static member inline Coalesce(x: 'T voption, y: unit -> 'T) = match x with ValueSome x -> x | _ -> y()\n            static member inline Coalesce(x: 'T voption, y: Lazy<'T>)   = match x with ValueSome x -> x | _ -> y.Value\n\n            static member inline Coalesce(x: Nullable<'T>, y: 'T)           = if x.HasValue then x.Value else y\n            static member inline Coalesce(x: Nullable<'T>, y: unit -> 'T)   = if x.HasValue then x.Value else y()\n            static member inline Coalesce(x: Nullable<'T>, y: Lazy<'T>)     = if x.HasValue then x.Value else y.Value\n\n            static member inline Coalesce<'T when 'T : null>(x: 'T, y: 'T)         = match x with null -> y | _ -> x\n            static member inline Coalesce<'T when 'T : null>(x: 'T, y: unit -> 'T) = match x with null -> y() | _ -> x\n            static member inline Coalesce<'T when 'T : null>(x: 'T, y: Lazy<'T>)   = match x with null -> y.Value | _ -> x\n\n    let inline private nullCoalesceAux (_ : ^Z) (x : ^T1) (y: ^T2) : 'T3 =\n        ((^Z or ^T1) : (static member Coalesce : ^T1 * ^T2 -> ^T3) (x, y))\n\n    /// <summary>\n    /// Null-coalescing operator. Returns <paramref name=\"x\"/> if it has a value, <paramref name=\"y\"/> otherwise.\n    /// <paramref name=\"x\"/> may be an Option, ValueOption, Nullable or an object of a type that supports null.\n    /// <paramref name=\"y\"/> may be a (lazy) value or a parameterless function returning a value.\n    /// </summary>\n    /// <param name=\"x\">The value to check for null, None, or ValueNone.</param>\n    /// <param name=\"y\">The fallback value. May be a (lazy) value or a parameterless function returning a value.</param>\n    let inline (||?) x y =\n        nullCoalesceAux Unchecked.defaultof<``Null Coalescing Helpers``.Coalescing> x y\n\n    [<Obsolete(\"Use NullCheck.isNull instead.\")>]\n    let inline isNull (a : 'a) =\n        match a with\n        | null -> true\n        | _ -> false\n\n    [<AutoOpen>]\n    module NullCheck =\n\n        /// Returns whether the given object is null.\n        let inline isNull (obj: obj) =\n            Object.ReferenceEquals(obj, null)\n\n        /// Returns whether the given object is not null.\n        let inline notNull (obj: obj) =\n            not <| isNull obj\n\n    module Map =\n        let union (l : Map<'k, 'v>) (r : Map<'k, 'v>) =\n            let mutable result = l\n            for KeyValue(k,v) in r do\n                result <- Map.add k v result\n            result\n\n        let unionMany (input : seq<Map<'k, 'v>>) =\n            (Map.empty, input) ||> Seq.fold union\n\n        let inline tryFindV (key: 'Key) (map: Map<'Key, 'Value>) =\n            match map.TryGetValue key with\n            | true, value -> ValueSome value\n            | _ -> ValueNone\n\n        let ofSeqWithDuplicates (input: seq<'Key * 'Value>) =\n            let mutable result = Map.empty\n\n            for key, value in input do\n                let set =\n                    match result.TryGetValue key with\n                    | true, set -> set |> Set.add value\n                    | _ -> Set.singleton value\n\n                result <- result |> Map.add key set\n\n            result\n\n    module List =\n\n        //Experimental Results show that this implementation is faster than all other ones maintaining the list's order\n        let rec private partitionAcc (f : 'a -> bool) (source : list<'a>) (l : System.Collections.Generic.List<'a>) (r : System.Collections.Generic.List<'a>) =\n             match source with\n                | [] ->\n                    let mutable ll = []\n                    let mutable rr = []\n\n                    for i in 1..l.Count do\n                        let i = l.Count - i\n                        ll <- l.[i]::ll\n\n                    for i in 1..r.Count do\n                        let i = r.Count - i\n                        rr <- r.[i]::rr\n\n                    (ll,rr)\n\n                | x::xs ->\n                    if f x then\n                        l.Add(x)\n                        partitionAcc f xs l r\n                    else\n                        r.Add(x)\n                        partitionAcc f xs l r\n\n        let partition (f : 'a -> bool) (source : list<'a>) =\n            partitionAcc f source (System.Collections.Generic.List()) (System.Collections.Generic.List())\n\n        let inline choosei ([<InlineIfLambda>] chooser: int -> 'T -> 'U option) (list: 'T list) =\n            let mutable i = -1\n\n            let chooser value =\n                i <- i + 1\n                chooser i value\n\n            List.choose chooser list\n\n        let inline collecti ([<InlineIfLambda>] mapping: int -> 'T -> 'U list) (list: 'T list) =\n            let mutable i = -1\n\n            let mapping value =\n                i <- i + 1\n                mapping i value\n\n            List.collect mapping list\n\n        let inline foldi (folder : int -> 'State -> 'T -> 'State) (state : 'State) (list : 'T list) =\n            match list with\n            | [] -> state\n            | _ ->\n                let f = OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt(folder)\n                let mutable acc = state\n                let mutable i = 0\n\n                for x in list do\n                    acc <- f.Invoke(i, acc, x)\n                    i <- i + 1\n\n                acc\n\n        let rec tryPickV chooser list =\n            match list with\n            | [] -> ValueNone\n            | h :: t ->\n                match chooser h with\n                | ValueNone -> tryPickV chooser t\n                | r -> r\n\n        let rec pickV chooser list =\n            match list with\n            | [] -> raise <| System.Collections.Generic.KeyNotFoundException()\n            | h :: t ->\n                match chooser h with\n                | ValueNone -> pickV chooser t\n                | ValueSome r -> r\n\n        let rec tryFindV predicate list =\n            match list with\n            | [] -> ValueNone\n            | h :: t ->\n                if predicate h then\n                    ValueSome h\n                else\n                    tryFindV predicate t\n\n        let inline tryHeadV list =\n            match list with\n            | x :: _ -> ValueSome x\n            | [] -> ValueNone\n\n        let rec tryLastV (list: 'T list) =\n            match list with\n            | [] -> ValueNone\n            | [x] -> ValueSome x\n            | _ :: tail -> tryLastV tail\n\n        /// Inserts a separator in between the elements of the given list.\n        let inline intersperse (separator: 'T) (list: 'T list) =\n            (list, []) ||> List.foldBack (fun x -> function\n                | [] -> [x]\n                | xs -> x::separator::xs\n            )\n\n        /// Computes the sum of the given list using the Kahan summation algorithm.\n        let inline stableSumBy (projection: 'T -> float) (list: 'T list) =\n            let mutable sum = KahanSum.Zero\n            for x in list do sum <- sum + projection x\n            sum.Value\n\n        /// Computes the sum of the given list using the Kahan summation algorithm.\n        let inline stableSum (list: float list) =\n            stableSumBy id list\n\n    module Seq =\n\n        /// Returns the given sequence as an array.\n        /// If the input is already an array it is returned without creating a copy, otherwise a new array is allocated.\n        let inline asArray (seq: 'T seq) : 'T[] =\n            match seq with\n            | :? ('T[]) as arr -> arr\n            | _ -> Seq.toArray seq\n\n        let inline iter' ([<InlineIfLambda>] f : 'a -> 'b) (s : seq<'a>) =\n            for i in s do\n                f i |> ignore\n\n        let inline repeat (n : int) ([<InlineIfLambda>] f : unit -> unit) =\n            for i in 1..n do\n                f()\n\n        let inline repeat' (n : int) ([<InlineIfLambda>] f : unit -> 'a) =\n            for i in 1..n do\n                f() |> ignore\n\n        let inline partition ([<InlineIfLambda>] f : 'a -> bool) (xs : seq<'a>) =\n            let xs = xs |> Seq.map (fun a -> f a, a) |> Seq.cache\n            (xs |> Seq.filter (fun (r,v) -> not r) |> Seq.map snd, xs |> Seq.filter fst |> Seq.map snd)\n\n        [<Obsolete(\"Is anybody actually using this?\")>]\n        let inline chooseOption ([<InlineIfLambda>] f : 'a -> Option<'b>) (xs : seq<Option<'a>>) : seq<Option<'b>> =\n            seq {\n                for x in xs do\n                    match x with\n                     | None -> ()\n                     | Some x -> yield f x\n            }\n\n        let inline choosei ([<InlineIfLambda>] chooser: int -> 'T -> 'U option) (source: 'T seq) : 'U seq =\n            if isNull (box source) then nullArg \"source\"\n            let mutable i = 0\n            let result = ResizeArray<'U>()\n\n            use e = source.GetEnumerator()\n            while e.MoveNext() do\n                match chooser i e.Current with\n                | Some v -> result.Add v\n                | _ -> ()\n\n                i <- i + 1\n\n            result :> 'U seq\n\n        let inline collecti ([<InlineIfLambda>] mapping: int -> 'T -> 'U seq) (source: 'T seq) : 'U seq =\n            if isNull (box source) then nullArg \"source\"\n            let mutable i = 0\n            let result = ResizeArray<'U>()\n\n            use e = source.GetEnumerator()\n            while e.MoveNext() do\n                result.AddRange(mapping i e.Current)\n                i <- i + 1\n\n            result :> 'U seq\n\n        let inline foldi (folder : int -> 'State -> 'T -> 'State) (state : 'State) (source : 'T seq) =\n            if isNull (box source) then nullArg \"source\"\n            use e = source.GetEnumerator()\n            let f = OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt folder\n            let mutable state = state\n            let mutable i = 0\n\n            while e.MoveNext() do\n                state <- f.Invoke(i, state, e.Current)\n                i <- i + 1\n\n            state\n\n        let inline tryPickV ([<InlineIfLambda>] chooser) (source : seq<'T>) =\n            if isNull (box source) then nullArg \"source\"\n            use e = source.GetEnumerator()\n            let mutable res = ValueNone\n\n            while (ValueOption.isNone res && e.MoveNext()) do\n                res <- chooser e.Current\n\n            res\n\n        let inline pickV ([<InlineIfLambda>] chooser) (source : seq<'T>) =\n            match tryPickV chooser source with\n            | ValueNone -> raise <| System.Collections.Generic.KeyNotFoundException()\n            | ValueSome x -> x\n\n        let inline tryFindV ([<InlineIfLambda>] predicate) (source: seq<'T>) =\n            if isNull (box source) then nullArg \"source\"\n            use e = source.GetEnumerator()\n            let mutable res = ValueNone\n\n            while (ValueOption.isNone res && e.MoveNext()) do\n                let c = e.Current\n\n                if predicate c then\n                    res <- ValueSome c\n\n            res\n\n        let inline tryHeadV (source: seq<_>) =\n            if isNull (box source) then nullArg \"source\"\n            use e = source.GetEnumerator()\n\n            if (e.MoveNext()) then\n                ValueSome e.Current\n            else\n                ValueNone\n\n        let tryLastV (source: seq<_>) =\n            if isNull (box source) then nullArg \"source\"\n            match source with\n            | :? ('T[]) as a ->\n                if a.Length = 0 then ValueNone\n                else ValueSome(a.[a.Length - 1])\n\n            | :? ('T System.Collections.Generic.IList) as a -> //ResizeArray and other collections\n                if a.Count = 0 then ValueNone\n                else ValueSome(a.[a.Count - 1])\n\n            | :? ('T list) as a -> List.tryLastV a\n\n            | _ ->\n                use e = source.GetEnumerator()\n                if e.MoveNext() then\n                    let mutable res = e.Current\n                    while (e.MoveNext()) do res <- e.Current\n                    ValueSome(res)\n                else\n                    ValueNone\n\n        /// Computes the sum of the given sequence using the Kahan summation algorithm.\n        let inline stableSumBy (projection: 'T -> float) (source: 'T seq) =\n            let mutable sum = KahanSum.Zero\n            for x in source do sum <- sum + projection x\n            sum.Value\n\n        /// Computes the sum of the given sequence using the Kahan summation algorithm.\n        let inline stableSum (source: float seq) =\n            stableSumBy id source\n\n        open System.Collections\n        open System.Collections.Generic\n\n        let atMost (n : int) (s : seq<'a>) : seq<'a> =\n            let newEnumerator() =\n                let input = s.GetEnumerator()\n                let mutable remaining = n\n                { new IEnumerator<'a> with\n                    member x.MoveNext() =\n                        remaining <- remaining - 1\n                        remaining >= 0 && input.MoveNext()\n                    member x.Current : obj = input.Current :> obj\n                    member x.Dispose() = input.Dispose()\n                    member x.Reset() = input.Reset(); remaining <- n\n                    member x.Current : 'a = input.Current\n                }\n\n            { new IEnumerable<'a> with\n                member x.GetEnumerator() : IEnumerator = newEnumerator() :> IEnumerator\n                member x.GetEnumerator() : IEnumerator<'a> = newEnumerator()\n            }\n\n    module Array =\n\n        let inline choosei ([<InlineIfLambda>] chooser: int -> 'T -> 'U option) (array: 'T[]) =\n            let mutable i = -1\n\n            let chooser value =\n                i <- i + 1\n                chooser i value\n\n            Array.choose chooser array\n\n        let inline chooseV ([<InlineIfLambda>] chooser: 'T -> 'U voption) (array: 'T array) =\n            if isNull array then\n                nullArg \"array\"\n\n            let mutable i = 0\n            let mutable first = Unchecked.defaultof<'U>\n            let mutable found = false\n\n            while i < array.Length && not found do\n                let element = array.[i]\n\n                match chooser element with\n                | ValueNone -> i <- i + 1\n                | ValueSome b ->\n                    first <- b\n                    found <- true\n\n            if i <> array.Length then\n\n                let chunk1: 'U array =\n                    Array.zeroCreate ((array.Length >>> 2) + 1)\n\n                chunk1.[0] <- first\n                let mutable count = 1\n                i <- i + 1\n\n                while count < chunk1.Length && i < array.Length do\n                    let element = array.[i]\n\n                    match chooser element with\n                    | ValueNone -> ()\n                    | ValueSome b ->\n                        chunk1.[count] <- b\n                        count <- count + 1\n\n                    i <- i + 1\n\n                if i < array.Length then\n                    let chunk2: 'U array =\n                        Array.zeroCreate (array.Length - i)\n\n                    count <- 0\n\n                    while i < array.Length do\n                        let element = array.[i]\n\n                        match chooser element with\n                        | ValueNone -> ()\n                        | ValueSome b ->\n                            chunk2.[count] <- b\n                            count <- count + 1\n\n                        i <- i + 1\n\n                    let res: 'U array =\n                        Array.zeroCreate (chunk1.Length + count)\n\n                    Array.Copy(chunk1, res, chunk1.Length)\n                    Array.Copy(chunk2, 0, res, chunk1.Length, count)\n                    res\n                else\n                    Array.sub chunk1 0 count\n            else\n                Array.empty\n\n        let inline chooseiV ([<InlineIfLambda>] chooser: int -> 'T -> 'U voption) (array: 'T[]) =\n            let mutable i = -1\n\n            let chooser value =\n                i <- i + 1\n                chooser i value\n\n            chooseV chooser array\n\n        let inline collecti ([<InlineIfLambda>] mapping: int -> 'T -> 'U[]) (array: 'T[]) =\n            let mutable i = -1\n\n            let mapping value =\n                i <- i + 1\n                mapping i value\n\n            Array.collect mapping array\n\n        let inline foldi (folder : int -> 'State -> 'T -> 'State) (state : 'State) (array : 'T[]) =\n            if isNull array then\n                nullArg \"array\"\n\n            let f = OptimizedClosures.FSharpFunc<_, _, _, _>.Adapt(folder)\n            let mutable state = state\n\n            for i = 0 to array.Length - 1 do\n                state <- f.Invoke(i, state, array.[i])\n\n            state\n\n        let inline binarySearch ([<InlineIfLambda>] compare : 'T -> int) (array : 'T[]) =\n            let rec search (a : int) (b : int) =\n                if a <= b then\n                    let i = (a + b) / 2\n                    let cmp = compare array.[i]\n\n                    if cmp = 0 then ValueSome i\n                    elif cmp < 0 then search a (i - 1)\n                    else search (i + 1) b\n                else\n                    ValueNone\n\n            search 0 (array.Length - 1)\n\n        let inline tryPickV ([<InlineIfLambda>] chooser) (array : _[]) =\n            if isNull array then\n                nullArg \"array\"\n\n            let rec loop i =\n                if i >= array.Length then\n                    ValueNone\n                else\n                    match chooser array.[i] with\n                    | ValueNone -> loop (i + 1)\n                    | res -> res\n\n            loop 0\n\n        let inline pickV ([<InlineIfLambda>] chooser) (array : _[]) =\n            if isNull array then\n                nullArg \"array\"\n\n            let rec loop i =\n                if i >= array.Length then\n                    raise <| System.Collections.Generic.KeyNotFoundException()\n                else\n                    match chooser array.[i] with\n                    | ValueNone -> loop (i + 1)\n                    | ValueSome res -> res\n\n            loop 0\n\n        let inline tryFindV ([<InlineIfLambda>] predicate) (array: _ array) =\n            if isNull array then\n                nullArg \"array\"\n\n            let rec loop i =\n                if i >= array.Length then\n                    ValueNone\n                else if predicate array.[i] then\n                    ValueSome array.[i]\n                else\n                    loop (i + 1)\n\n            loop 0\n\n        let inline tryHeadV (array: 'T array) =\n            if isNull array then\n                nullArg \"array\"\n\n            if array.Length = 0 then ValueNone\n            else ValueSome array.[0]\n\n        let inline tryLastV (array: 'T array) =\n            if isNull array then\n                nullArg \"array\"\n\n            if array.Length = 0 then ValueNone\n            else ValueSome array.[array.Length - 1]\n\n        let unzipV (array: _ array) =\n            if isNull array then\n                nullArg \"array\"\n\n            let len = array.Length\n            let res1 = Array.zeroCreate len\n            let res2 = Array.zeroCreate len\n\n            for i = 0 to array.Length - 1 do\n                let struct (x, y) = array.[i]\n                res1.[i] <- x\n                res2.[i] <- y\n\n            struct (res1, res2)\n\n        let zipV (array1: _ array) (array2: _ array) =\n            if isNull array1 then\n                nullArg \"array1\"\n\n            if isNull array2 then\n                nullArg \"array2\"\n\n            let len1 = array1.Length\n\n            if len1 <> array2.Length then\n                raise <| ArgumentException($\"Arrays have different lengths (array1.Length = {array1.Length}, array2.Length = {array2.Length}).\")\n\n            let res = Array.zeroCreate len1\n\n            for i = 0 to res.Length - 1 do\n                res.[i] <- struct (array1.[i], array2.[i])\n\n            res\n\n        /// Computes the sum of the given array using the Kahan summation algorithm.\n        let inline stableSumBy (projection: 'T -> float) (array: 'T[]) =\n            let mutable sum = KahanSum.Zero\n            for x in array do sum <- sum + projection x\n            sum.Value\n\n        /// Computes the sum of the given array using the Kahan summation algorithm.\n        let inline stableSum (array: float[]) =\n            stableSumBy id array\n\n    module Disposable =\n\n        let empty = { new IDisposable with member x.Dispose() = () }\n\n        let inline dispose v = (^a : (member Dispose : unit -> unit) v)\n\n    module Option =\n        let inline toValueOption (value : 'T option) =\n            match value with Some x -> ValueSome x | _ -> ValueNone\n\n    module ValueOption =\n        let inline toOption (value : 'T voption) =\n            match value with ValueSome x -> Some x | _ -> None\n\n    [<AutoOpen>]\n    module ValueOptionOperators =\n        let inline fstv (struct (x, _)) = x\n        let inline sndv (struct (_, y)) = y\n\n    type nativeptr<'T when 'T : unmanaged> with\n        member inline ptr.Address = NativePtr.toNativeInt ptr\n\n        member ptr.Value\n            with inline get () = NativePtr.read ptr\n            and  inline set (value : 'T) = NativePtr.write ptr value\n\n        member ptr.Item\n            with inline get (index : int) = NativePtr.get ptr index\n            and  inline set (index : int) (value : 'T) = NativePtr.set ptr index value\n\n    module NativePtr =\n        open System.Runtime.InteropServices\n        open System.IO\n\n        [<GeneralizableValue>]\n        let inline zero<'a when 'a : unmanaged> : nativeptr<'a> = NativePtr.ofNativeInt 0n\n\n        let inline cast<'a, 'b when 'a : unmanaged and 'b : unmanaged> (ptr : nativeptr<'a>) : nativeptr<'b> =\n            ptr |> NativePtr.toNativeInt |> NativePtr.ofNativeInt\n\n        let inline step<'a when 'a : unmanaged> (count : int) (ptr : nativeptr<'a>) =\n            NativePtr.add ptr count\n\n        let inline toArray<'a when 'a : unmanaged> (cnt : int) (ptr : nativeptr<'a>) =\n            Array.init cnt (NativePtr.get ptr)\n\n        let inline toSeq<'a when 'a : unmanaged> (cnt : int) (ptr : nativeptr<'a>) =\n            Seq.init cnt (NativePtr.get ptr)\n\n        let inline toList<'a when 'a : unmanaged> (cnt : int) (ptr : nativeptr<'a>) =\n            List.init cnt (NativePtr.get ptr)\n\n        let inline isNull<'a when 'a : unmanaged> (ptr : nativeptr<'a>) =\n            ptr |> NativePtr.toNativeInt = 0n\n\n        let alloc<'a when 'a: unmanaged> (size : int) =\n            size * sizeof<'a> |> Marshal.AllocHGlobal |> NativePtr.ofNativeInt<'a>\n\n        let free<'a when 'a : unmanaged> (ptr : nativeptr<'a>) =\n            ptr |> NativePtr.toNativeInt |> Marshal.FreeHGlobal\n\n        let inline stackUse<'a when 'a : unmanaged> (elements : seq<'a>) =\n            let arr = elements |> Seq.toArray\n            let ptr = NativePtr.stackalloc arr.Length\n            for i in 0..arr.Length-1 do\n                NativePtr.set ptr i arr.[i]\n            ptr\n\n        /// Allocates and initializes native memory on the stack from the given array and mapping function.\n        let inline stackUseArr<'T, 'U when 'U : unmanaged> ([<InlineIfLambda>] mapping: 'T -> 'U) (data: 'T[]) =\n            let ptr = NativePtr.stackalloc<'U> data.Length\n            for i = 0 to data.Length - 1 do ptr.[i] <- mapping data.[i]\n            ptr\n\n        let toStream<'a when 'a : unmanaged> (count : int) (ptr : nativeptr<'a>) : Stream =\n            let l = int64 <| sizeof<'a> * count\n            new System.IO.UnmanagedMemoryStream(cast ptr, l,l, FileAccess.ReadWrite) :> _\n\n        /// Pins the given value and invokes the action with the native pointer.\n        /// Note: Use a fixed expression with a byref if writing to the original location is required.\n        let inline pin<'T, 'U when 'T : unmanaged> ([<InlineIfLambda>] action: nativeptr<'T> -> 'U) (value: 'T) =\n            // See: https://github.com/dotnet/fsharp/issues/18689\n            use ptr = fixed &value\n            try action ptr\n            with _ -> reraise()\n\n        /// Pins the given array and invokes the action with the native pointer.\n        let inline pinArr<'T, 'U when 'T : unmanaged> ([<InlineIfLambda>] action: nativeptr<'T> -> 'U) (array: 'T[]) =\n            // See: https://github.com/dotnet/fsharp/issues/18689\n            use ptr = fixed array\n            try action ptr\n            with _ -> reraise()\n\n        /// Pins the given array at the given index and invokes the action with the native pointer.\n        let inline pinArri<'T, 'U when 'T : unmanaged> ([<InlineIfLambda>] action: nativeptr<'T> -> 'U) (index: int) (array: 'T[]) =\n            // See: https://github.com/dotnet/fsharp/issues/18689\n            use ptr = fixed &array.[index]\n            try action ptr\n            with _ -> reraise()\n\n        /// Allocates a temporary native pointer and invokes the action.\n        let inline temp<'T, 'U when 'T : unmanaged> ([<InlineIfLambda>] action: nativeptr<'T> -> 'U) =\n            pin action Unchecked.defaultof<'T>\n\n        module Operators =\n\n            let ( &+ ) (ptr : nativeptr<'a>) (count : int) =\n                ptr |> step count\n\n            let ( &- ) (ptr : nativeptr<'a>) (count : int) =\n                ptr |> step (-count)\n\n            let ( !* ) (ptr : nativeptr<'a>) =\n                NativePtr.read ptr\n\n    type Buffer with\n\n        static member inline MemoryCopy(source : nativeint, destination : nativeint, destinationSizeInBytes : uint64, sourceBytesToCopy : uint64) =\n            Buffer.MemoryCopy(source.ToPointer(), destination.ToPointer(), destinationSizeInBytes, sourceBytesToCopy)\n\n        static member inline MemoryCopy(source : nativeint, destination : nativeint, destinationSizeInBytes : int64, sourceBytesToCopy : int64) =\n            Buffer.MemoryCopy(source.ToPointer(), destination.ToPointer(), destinationSizeInBytes, sourceBytesToCopy)\n\n\n    (* Error datastructure *)\n    [<Struct>]\n    type Error<'T> =\n        | Success of value: 'T\n        | Error of error: string\n\n    (* Either left or right *)\n    [<Struct>]\n    type Either<'L, 'R> =\n        | Left of left: 'L\n        | Right of right: 'R\n\n    let toFunc (f : 'a -> 'b) : Func<'a, 'b> =\n        Func<'a, 'b>(f)\n\n    let fromFunc (f : Func<'a, 'b>) : 'a -> 'b =\n        fun x -> f.Invoke(x)\n\n    let dowhile (f : unit -> bool) =\n        while f() do ()\n\n    //VERY IMPORTANT CODE\n    let uncurry (f : 'a -> 'b -> 'c) = fun (a,b) -> f a b\n    let curry (f : 'a * 'b -> 'c) = fun a b -> f (a,b)\n\n    [<AutoOpen>]\n    module ReferenceEquality =\n        let inline private refequals<'a when 'a : not struct> (a : 'a) (b : 'a) = Object.ReferenceEquals(a,b)\n\n        /// Reference equality\n        let inline (==) (a : 'a) (b : 'a) = refequals a b\n\n        /// Reference inequality\n        let inline (!=) (a : 'a) (b : 'a) = refequals a b |> not\n\n    let inline flip f a b = f b a\n\n    let inline constF v = fun _ -> v\n\n[<AutoOpen>]\nmodule CSharpInterop =\n\n    open System.Runtime.CompilerServices\n\n    type public FSharpFuncUtil =\n\n        [<Extension>]\n        static member ToFSharpFunc<'a,'b> (func:System.Converter<'a,'b>) = fun x -> func.Invoke(x)\n\n        [<Extension>]\n        static member ToFSharpFunc<'a,'b> (func:System.Func<'a,'b>) = fun x -> func.Invoke(x)\n\n        [<Extension>]\n        static member ToFSharpFunc<'a,'b,'c> (func:System.Func<'a,'b,'c>) = fun x y -> func.Invoke(x,y)\n\n        [<Extension>]\n        static member ToFSharpFunc<'a,'b,'c,'d> (func:System.Func<'a,'b,'c,'d>) = fun x y z -> func.Invoke(x,y,z)\n\n        static member Create<'a,'b> (func:System.Func<'a,'b>) = FSharpFuncUtil.ToFSharpFunc func\n\n        static member Create<'a,'b,'c> (func:System.Func<'a,'b,'c>) = FSharpFuncUtil.ToFSharpFunc func\n\n        static member Create<'a,'b,'c,'d> (func:System.Func<'a,'b,'c,'d>) = FSharpFuncUtil.ToFSharpFunc func\n\nmodule GenericValues =\n    open System.Reflection\n\n    [<Obsolete(\"Use LanguagePrimitives.GenericZero instead.\")>]\n    let inline zero< ^a when ^a : (static member (-) : ^a -> ^a -> ^a)> : ^a =\n        let t = typeof< ^a>\n        let pi = t.GetProperty(\"Zero\", BindingFlags.Static ||| BindingFlags.Public)\n        let fi = t.GetField(\"Zero\", BindingFlags.Static ||| BindingFlags.Public)\n\n        if not (isNull pi) then pi.GetValue(null) |> unbox\n        elif not (isNull fi) then fi.GetValue(null) |> unbox\n        else Unchecked.defaultof< ^a>\n\n[<AutoOpen>]\nmodule NiceUtilities =\n\n    module LookupTable =\n        open System.Collections.Generic\n\n        let private build (entries: list<'Key * 'Value>) =\n            let d = Dictionary()\n\n            for k, v in entries do\n                match d.TryGetValue k with\n                | (true, vo) -> raise <| ArgumentException($\"Duplicate lookup table entry {k}: {v} and {vo}.\")\n                | _ -> ()\n\n                d.[k] <- v\n\n            d\n\n        /// Builds a lookup table from the given entries and returns a function that retrieves the value associated with a key.\n        /// Fails if a key occurs more than once in the input collection.\n        let lookup (entries: list<'Key * 'Value>) =\n            let d = build entries\n\n            fun (key : 'Key) ->\n                match d.TryGetValue key with\n                | (true, v) -> v\n                | _ -> raise <| KeyNotFoundException($\"Key {key} of type {typeof<'Key>} not found in lookup table.\")\n\n        /// Builds a lookup table from the given entries and returns a function that retrieves the value associated with a key if it exists.\n        /// Fails if a key occurs more than once in the input collection.\n        let tryLookup (entries: list<'Key * 'Value>) =\n            let d = build entries\n\n            fun (key : 'Key) ->\n                match d.TryGetValue key with\n                | (true, v) -> Some v\n                | _ -> None\n\n        /// Builds a lookup table from the given entries and returns a function that retrieves the value associated with a key if it exists.\n        /// Fails if a key occurs more than once in the input collection.\n        let tryLookupV (entries: list<'Key * 'Value>) =\n            let d = build entries\n\n            fun (key : 'Key) ->\n                match d.TryGetValue key with\n                | (true, v) -> ValueSome v\n                | _ -> ValueNone\n\n        [<Obsolete(\"Use LookupTable.lookup instead.\")>]\n        let lookupTable (l : list<'a * 'b>) =\n            lookup l\n\n        [<Obsolete(\"Use LookupTable.tryLookup instead.\")>]\n        let lookupTable' (l : list<'a * 'b>) =\n            tryLookup l\n\n[<AutoOpen>]\nmodule EnumExtensions =\n\n    module Enum =\n\n        /// Converts the given value to an enumeration type.\n        /// The input value must be an enumeration type or convertible to the underlying target enumeration type.\n        /// If the value is not defined for the target enumeration, an InvalidCastException is thrown.\n        let inline convert< ^Value, ^Enum when ^Enum :> Enum\n                                           and ^Enum : struct\n                                           and ^Enum : (new : unit -> ^Enum)> (value: ^Value) : ^Enum =\n            let tSrc = typeof< ^Value>\n            let tDst = typeof< ^Enum>\n            let tDstBase = Enum.GetUnderlyingType tDst\n\n            let cast: ^Enum =\n                if tSrc = tDst || tSrc = tDstBase || (tSrc.IsEnum && Enum.GetUnderlyingType tSrc = tDstBase) then\n                    unbox< ^Enum> value\n                else\n                    if tDstBase = typeof<int8> then unbox< ^Enum> <| Convert.ToSByte value\n                    elif tDstBase = typeof<uint8> then unbox< ^Enum> <| Convert.ToByte value\n                    elif tDstBase = typeof<int16> then unbox< ^Enum> <| Convert.ToInt16 value\n                    elif tDstBase = typeof<uint16> then unbox< ^Enum> <| Convert.ToUInt16 value\n                    elif tDstBase = typeof<int32> then unbox< ^Enum> <| Convert.ToInt32 value\n                    elif tDstBase = typeof<uint32> then unbox< ^Enum> <| Convert.ToUInt32 value\n                    elif tDstBase = typeof<int64> then unbox< ^Enum> <| Convert.ToInt64 value\n                    elif tDstBase = typeof<uint64> then unbox< ^Enum> <| Convert.ToUInt64 value\n                    else\n                        failwithf \"Unknown underlying type %A for enumeration\" tDstBase\n\n#if NET6_0_OR_GREATER\n            if not <| Enum.IsDefined cast then\n#else\n            if not <| Enum.IsDefined(typeof< ^Enum>, cast) then\n#endif\n                raise <| InvalidCastException($\"Value {value} is invalid for enumeration type {typeof< ^Enum>}.\")\n\n            cast\n\nmodule ConversionHelpers =\n\n    [<Obsolete(\"Use Enum.convert instead.\")>]\n    let inline convertEnum< ^a, ^b when ^a : (static member op_Explicit : ^a -> int)> (fmt : ^a) : ^b =\n        let v = int fmt\n        if Enum.IsDefined(typeof< ^b >, v) then\n            unbox< ^b > v\n        else\n            failwithf \"cannot convert %s %A to %s\" typeof< ^a >.Name fmt typeof< ^b >.Name\n\ntype float16 = Aardvark.Base.Half\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Interop/HashSet.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule HashSet =\n    open System.Collections.Generic\n    open System.Linq\n\n    let empty<'k> = HashSet<'k>()\n\n    let inline add (k : 'a) (h : HashSet<_>) =\n        h.Add k\n        \n    let inline remove a (h : HashSet<_>) =\n        h.Remove a\n\n    let inline clear (h : HashSet<_>) =\n        h.Clear()\n\n    let inline map ([<InlineIfLambda>] f) (h : HashSet<_>) =\n        let r = HashSet()\n        for v in h do r.Add (f v) |> ignore\n        r\n\n    let inline union (dicts : #seq<HashSet<'a>>) =\n        let result = HashSet()\n        for d in dicts do\n            result.UnionWith d\n        result\n\n    let inline unionWith (xs : seq<'a>) (s : HashSet<'a>) =\n        s.UnionWith xs\n\n    let inline exceptWith (xs : seq<'a>) (s : HashSet<'a>) =\n        s.ExceptWith xs\n\n    let inline intersectWith (xs : seq<'a>) (s : HashSet<'a>) =\n        s.IntersectWith xs\n\n    let inline contains v (h : HashSet<_>) =\n        h.Contains v\n\n    let inline ofSeq (elements : seq<'a>) =\n        let result = HashSet()\n        for v in elements do\n            result.Add v |> ignore\n        result\n\n    let inline ofList (elements : list<'a>) =\n        ofSeq elements\n\n    let inline ofArray (elements : ('a)[]) =\n        ofSeq elements\n\n    let inline toSeq (d : HashSet<'a>) =\n        d :> seq<_>\n\n    let inline toList (d : HashSet<'a>) =\n        let mutable l = []\n        for x in d do\n            l <- x :: l\n        l\n\n    let inline toArray (d : HashSet<'a>) =\n       d.ToArray()\n\n    let inline toSet (d : HashSet<'a>) =\n        Set.ofSeq d"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Interop/SortedSet.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\nopen System.Runtime.InteropServices\nopen System.Linq\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule SortedSet =\n    \n    let inline private optionalToOpt (o : Optional<'a>) =\n        if o.HasValue then Some o.Value\n        else None\n\n\n    let empty<'a> = SortedSetExt<'a>()\n\n    let cusom (cmp : 'a -> 'a -> int) =\n        SortedSetExt<'a>({ new IComparer<'a> with member x.Compare(l,r) = cmp l r })\n\n    let inline count (s : SortedSetExt<'a>) =\n        s.Count\n\n    let inline add (value : 'a) (s : SortedSetExt<'a>) =\n        s.Add(value)\n\n    let inline remove (value : 'a) (s : SortedSetExt<'a>) =\n        s.Remove(value)\n\n    let clear (s : SortedSetExt<'a>) =\n        s.Clear()\n\n    let inline contains (value : 'a) (s : SortedSetExt<'a>) =\n        s.Contains(value)\n\n    let inline unionWith (values : seq<'a>) (s : SortedSetExt<'a>) =\n        s.UnionWith values\n\n    let inline exceptWith (values : seq<'a>) (s : SortedSetExt<'a>) =\n        s.ExceptWith values\n\n    let inline intersectWith (values : seq<'a>) (s : SortedSetExt<'a>) =\n        s.IntersectWith values\n\n    let inline symmetricExceptWith (values : seq<'a>) (s : SortedSetExt<'a>) =\n        s.SymmetricExceptWith values\n\n    let neighbourhood (value : 'a) (s : SortedSetExt<'a>) =\n        let mutable lower = Optional<'a>.None\n        let mutable upper = Optional<'a>.None\n        let mutable self = Optional<'a>.None\n        s.FindNeighbours(value, &lower, &self, &upper)\n\n        (optionalToOpt lower, optionalToOpt self, optionalToOpt upper)\n\n    let addWithNeighbours (value : 'a) (f : Option<'a> -> Option<'a> -> 'a) (s : SortedSetExt<'a>) =\n        let (p,self,n) = neighbourhood value s\n        match self with\n            | Some v -> s.Remove(v) |> ignore\n            | None -> ()\n\n        let res = f p n\n        s.Add res |> ignore\n\ntype SortedDictionaryExt<'k, 'v> private (comparer : IComparer<'k * ref<'v>>) =\n    let set = SortedSetExt<'k * ref<'v>> comparer\n\n    new(cmp : 'k -> 'k -> int) =\n        SortedDictionaryExt<'k, 'v>({ new IComparer<'k * ref<'v>> with member x.Compare((l,_),(r,_)) = cmp l r })\n\n    new(comparer : IComparer<'k>) =\n        SortedDictionaryExt<'k, 'v>({ new IComparer<'k * ref<'v>> with member x.Compare((l,_),(r,_)) = comparer.Compare(l, r) })\n\n    member internal x.Set = set\n\n    member x.TryGetValue (key : 'k, [<Out>] result : byref<'v>) =\n        match set |> SortedSet.neighbourhood (key, Unchecked.defaultof<_>) with\n            | _,Some (_,v),_ -> \n                result <- !v\n                true\n            | _ ->\n                false\n\n    member x.Count = set.Count\n\n    member x.Add (key : 'k, value : 'v) =\n        if not (set |> SortedSet.add (key, ref value)) then\n            raise <| ArgumentException(\"An item with the same key has already been added.\")\n\n    member x.Remove (key : 'k) =\n        set.Remove (key, Unchecked.defaultof<_>)\n\n    member x.Clear() =\n        set.Clear()\n\n    member x.ContainsKey (key : 'k) =\n        set.Contains ((key, Unchecked.defaultof<_>))\n\n    member x.Item\n        with get (key : 'k) =\n             match set |> SortedSet.neighbourhood (key, Unchecked.defaultof<_>) with\n                | _,Some (_,v),_ -> !v\n                | _ -> raise <| KeyNotFoundException()\n\n        and set (key : 'k) (value : 'v) =\n            match set |> SortedSet.neighbourhood (key, Unchecked.defaultof<_>) with\n                | _,Some (_,v),_ ->\n                    v := value\n                | _ ->\n                    set |> SortedSet.add (key, ref value) |> ignore\n\n    interface IEnumerable with\n        member x.GetEnumerator() = (set |> Seq.map (fun (k,v) -> KeyValuePair(k,!v))).GetEnumerator() :> IEnumerator\n\n    interface IEnumerable<KeyValuePair<'k, 'v>> with\n        member x.GetEnumerator() = (set |> Seq.map (fun (k,v) -> KeyValuePair(k,!v))).GetEnumerator() :> IEnumerator<_>\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule SortedDictionary =\n  \n    let inline private optionalToOpt (o : Optional<'k * ref<'v>>) =\n        if o.HasValue then\n            let (k,v) = o.Value\n            Some(k, v)\n        else \n            None\n\n    let inline private optionalToOptValue (o : Optional<'k * ref<'v>>) =\n        if o.HasValue then\n            let (k,v) = o.Value\n            Some(k, !v)\n        else \n            None\n\n    let inline private neighbourhoodInt (key : 'k) (s : SortedDictionaryExt<'k, 'v>) =\n        let mutable lower = Optional<'k * ref<'v>>.None\n        let mutable upper = Optional<'k * ref<'v>>.None\n        let mutable self = Optional<'k * ref<'v>>.None\n        s.Set.FindNeighbours((key, Unchecked.defaultof<_>), &lower, &self, &upper)\n\n        (optionalToOptValue lower, optionalToOpt self |> Option.map snd, optionalToOptValue upper)\n\n\n    let empty<'k, 'v when 'k : comparison> = SortedDictionaryExt<'k, 'v>(compare)\n\n    let custom (cmp : 'k -> 'k -> int) = SortedDictionaryExt<'k, 'v>(cmp)\n\n    let inline count (s : SortedDictionaryExt<'k, 'v>) =\n        s.Count\n\n    let inline add (key : 'k) (value : 'v) (s : SortedDictionaryExt<'k, 'v>) =\n        s.Add(key, value)\n\n    let inline remove (key : 'k) (s : SortedDictionaryExt<'k, 'v>) =\n        s.Remove(key)\n\n    let inline tryFind (key : 'k) (s : SortedDictionaryExt<'k, 'v>) =\n        match s.TryGetValue(key) with\n            | (true, v) -> Some v\n            | _ -> None\n\n    let clear (s : SortedDictionaryExt<'k, 'v>) =\n        s.Clear()\n\n    let neighbourhood (key : 'k) (s : SortedDictionaryExt<'k, 'v>) =\n        let (p,s,n) = neighbourhoodInt key s\n\n        match s with\n            | Some s -> (p,Some !s, n)\n            | None -> (p,None,n)\n\n    let setWithNeighbours (key : 'k) (f : Option<'k * 'v> -> Option<'v> -> Option<'k * 'v> -> 'v) (s : SortedDictionaryExt<'k, 'v>) =\n        let (p,self,n) = neighbourhoodInt key s\n        match self with\n            | Some s -> \n                let res = f p (Some !s) n\n                s := res\n                res\n            | None -> \n                let res = f p None n\n                s.Add(key, res)\n                res\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Interop/String.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\Bin\\\\Debug\\\\Aardvark.Base.dll\"\nopen Aardvark.Base\n#else\nnamespace Aardvark.Base\n#endif\n\nopen System\nopen System.Text.RegularExpressions\nopen System.Runtime.CompilerServices\n\n[<Sealed; Extension>]\ntype StringExtensions private() =\n\n    /// Replaces all newline sequences in the current string with replacementText.\n    [<Extension>]\n    static member inline NormalizeLineEndings(str : string, replacementText : string) =\n        #if NET6_0_OR_GREATER\n        str.ReplaceLineEndings(replacementText)\n        #else\n        Regex.Replace(str, @\"\\r\\n?|\\n\", replacementText)\n        #endif\n\n    /// Replaces all newline sequences in the current string with Environment.NewLine.\n    [<Extension>]\n    static member inline NormalizeLineEndings(str : string) =\n        #if NET6_0_OR_GREATER\n        str.ReplaceLineEndings()\n        #else\n        str.NormalizeLineEndings(Environment.NewLine)\n        #endif\n\n[<AutoOpen>]\nmodule ``String Extensions`` =\n    module String =\n\n        /// Splits the string into individual lines, recognizing various line ending sequences.\n        let inline getLines (str : string) =\n            str.NormalizeLineEndings().Split([| Environment.NewLine |], StringSplitOptions.None)\n\n        /// Replaces all newline sequences in the given string with Environment.NewLine.\n        let inline normalizeLineEndings (str : string) =\n            str.NormalizeLineEndings()\n\n        /// Adds line number prefixes to the given string.\n        /// Line endings are normalized.\n        let withLineNumbers (str : string) =\n            let lines = getLines str\n            let lineColumns = 1 + int (Fun.Log10 lines.Length)\n\n            lines |> Array.mapi (fun i str ->\n                let n = (string (i + 1)).PadLeft lineColumns\n                $\"{n}: {str}\"\n            )\n            |> String.concat Environment.NewLine\n\n        /// Indents each line of string by step * 4 spaces.\n        /// Line endings are normalized.\n        let indent (step : int) (s : string) =\n            let lines = getLines s\n            let indent = System.String(' ', step * 4)\n\n            lines\n            |> Array.map (fun l -> indent + l)\n            |> String.concat Environment.NewLine\n\n        /// Gets the number of lines in the given string, recognizing various line ending sequences.\n        let lineCount (s : string) =\n            let lines = getLines s\n            lines.Length\n\n        /// Returns whether the string contains the given pattern.\n        let inline contains (pattern : string) (str : string) =\n            str.Contains pattern\n\n        /// Returns a copy of the string converted to lowercase.\n        let inline toLower (str : string) =\n            str.ToLower()\n\n        /// Returns a copy of the string converted to uppercase.\n        let inline toUpper (str : string) =\n            str.ToUpper()\n\n        /// Splits the string into substring based on the separator.\n        let inline split (separator : string) (str : string) =\n            str.Split([| separator |], StringSplitOptions.None)\n\n        /// Returns whether the string starts with the given pattern.\n        let inline startsWith (pattern : string) (str : string) =\n            str.StartsWith pattern\n\n        /// Returns whether the string ends with the given pattern.\n        let inline endsWith (pattern : string) (str : string) =\n            str.EndsWith pattern\n\n        /// Removes all leading and trailing white-space characters from the string.\n        let inline trim (str : string) =\n            str.Trim()\n\n        /// Replaces all occurrences of the pattern with the replacement string.\n        let inline replace (pattern : string) (replacement : string) (str : string) =\n            str.Replace(pattern, replacement)"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Interop/Symbol.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Sym =\n\n    let empty = Symbol.Empty\n\n    let newGuid() = Symbol.CreateNewGuid()\n\n    let ofString (str : string) = Symbol.Create str\n\n    let toString (sym : Symbol) = sym.ToString()\n\n    let toGuid (sym : Symbol) = sym.ToGuid()\n\n    let id (sym : Symbol) = sym.Id\n\n    let isEmpty (sym : Symbol) = sym.IsEmpty\n\n    let isNotEmpty (sym : Symbol) = sym.IsNotEmpty\n\n    let isPositive (sym : Symbol) = sym.IsPositive\n\n    let isNegative (sym : Symbol) = sym.IsNegative"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Lens.fs",
    "content": "﻿#if COMPILED\nnamespace Aardvark.Base\n#endif\n\ntype Lens<'s, 'a>() =\n    abstract member Get : 's -> 'a\n    abstract member Set : 's * 'a -> 's \n    abstract member Update : 's * ('a -> 'a) -> 's\n\n    default x.Get s =\n        let mutable res = Unchecked.defaultof<'a>\n        x.Update(s, fun v -> res <- v; v) |> ignore\n        res\n\n    default x.Set(s,v) =\n        x.Update(s, fun _ -> v)\n\n    default x.Update(s, f) =\n        x.Set(s, x.Get(s) |> f)\n\n    static member Compose(l : Lens<'s, 'a>, r : Lens<'a, 'b>) =\n        { new Lens<'s, 'b>() with\n            member x.Get s = l.Get s |> r.Get\n            member x.Set(s,v) = l.Update(s, fun s -> r.Set(s, v))\n            member x.Update(s,f) = l.Update(s, fun s -> r.Update(s,f))\n        }\n\n[<AutoOpen>]\nmodule ``Lens Operators`` =\n\n    let inline (|.) (l : ^a) (r : ^b) : ^c =\n        ( (^a or ^b) : (static member Compose : ^a * ^b -> ^c) (l, r))\n\n    let inline (|?) (l : Lens<'s, Option<'a>>) (r : 'a) : Lens<'s, 'a> =\n        let def (o : Option<'a>) =\n            match o with\n                | Some o -> o\n                | _ -> r\n        { new Lens<'s, 'a>() with\n            member x.Get s = l.Get s |> def\n            member x.Set(s,v) = l.Set(s, Some v)\n            member x.Update(s,f) = l.Update(s, def >> f >> Some)\n        }\n\n    let inline (|??) (l : Lens<'s, Option<'a>>) (empty : 'a, isEmpty : 'a -> bool) : Lens<'s, 'a> =\n        let def (o : Option<'a>) =\n            match o with\n                | Some o -> o\n                | _ -> empty\n\n        { new Lens<'s, 'a>() with\n            member x.Get s = l.Get s |> def\n            member x.Set(s,v) = \n                if isEmpty v then l.Set(s, None)\n                else l.Set(s, Some v)\n        }\n\n[<AutoOpen>]\nmodule ``Predefined Lenses`` =\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module Set = \n        module Lens =\n            let contains (v : 'a) : Lens<Set<'a>, bool> =\n                { new Lens<_, _>() with\n                    member x.Get s = Set.contains v s\n                    member x.Set(s,r) =\n                        if r then Set.add v s\n                        else Set.remove v s\n                }  \n    \n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]        \n    module Map =\n        module Lens =\n            let item (key : 'k) : Lens<Map<'k, 'v>, Option<'v>> =\n                { new Lens<_, _>() with\n                    member x.Get s = \n                        Map.tryFind key s\n\n                    member x.Set(s,r) =\n                        match r with\n                            | Some r -> Map.add key r s\n                            | None -> Map.remove key s\n                }  \n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module List =\n        module Lens =\n            let item (i : int) =\n                { new Lens<list<'a>, Option<'a>>() with\n                    member x.Get l = \n                        List.tryItem i l\n\n                    member x.Set(l,v) = \n                        match v with\n                            | Some v -> \n                                let mutable found = false\n                                let mutable cnt = 0\n                                let res = l |> List.mapi (fun ii o -> cnt <- cnt + 1; if ii = i then found <- true; v else o)\n                            \n                                if found then\n                                    res\n                                elif i = cnt - 1 then\n                                    res @ [v]\n                                else\n                                    raise <| System.IndexOutOfRangeException()\n                            | None ->\n                                let mutable found = false\n                                let mutable cnt = 0\n                                let res = l |> List.mapi (fun ii o -> cnt <- cnt + 1; if ii = i then found <- true; None else Some o) |> List.choose id                          \n                                res\n                }\n\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Logging.fs",
    "content": "﻿namespace Aardvark.Base\n\n#nowarn \"1337\"\n\n\n[<AbstractClass; Sealed>]\ntype Log private() =\n    static let lineBreakRx = System.Text.RegularExpressions.Regex @\"\\r?\\n\"\n\n    static let printLines (print : string -> unit) (str : string) =\n        if str.IndexOf '\\n' >= 0 then\n            let lines = lineBreakRx.Split(str)\n            for l in lines do print l\n        else\n            print str\n        \n\n    static let writeLine =\n        () \n        fun (str : string) ->\n            if str.IndexOf '\\n' >= 0 then\n                let lines = lineBreakRx.Split(str)\n                for l in lines do Report.Line(\"{0}\", l)\n            else\n                Report.Line(\"{0}\", str)\n                \n        \n\n    static let writeDebug =\n        () \n        fun (str : string) ->\n            if str.IndexOf '\\n' >= 0 then\n                let lines = lineBreakRx.Split(str)\n                for l in lines do Report.DebugNoPrefix(\"{0}\", l)\n            else\n                Report.DebugNoPrefix(\"{0}\", str)\n\n    static let writeWarn =\n        () \n        fun (str : string) ->\n            if str.IndexOf '\\n' >= 0 then\n                let lines = lineBreakRx.Split(str)\n                Report.WarnNoPrefix(\"WARNING\")\n                for l in lines do Report.WarnNoPrefix(\"  {0}\", l)\n            else\n                Report.Warn(\"{0}\", str)\n        \n    static let writeError =\n        () \n        fun (str : string) ->\n            if str.IndexOf '\\n' >= 0 then\n                let lines = lineBreakRx.Split(str)\n                Report.ErrorNoPrefix(\"ERROR\")\n                for l in lines do Report.ErrorNoPrefix(\"  {0}\", l)\n            else\n                Report.Error(\"{0}\", str)\n        \n    [<CompilerMessage(\"internal\", 1337, IsHidden = true)>]\n    static member WriteDebug = writeDebug\n\n    [<CompilerMessage(\"internal\", 1337, IsHidden = true)>]\n    static member WriteLine = writeLine\n\n    [<CompilerMessage(\"internal\", 1337, IsHidden = true)>]\n    static member WriteWarn = writeWarn\n    \n    [<CompilerMessage(\"internal\", 1337, IsHidden = true)>]\n    static member WriteError = writeError\n    \n    static member inline debug fmt = Printf.kprintf Log.WriteDebug fmt\n    static member inline line fmt = Printf.kprintf Log.WriteLine fmt\n    static member inline warn fmt = Printf.kprintf Log.WriteWarn fmt\n    static member inline error fmt = Printf.kprintf Log.WriteError fmt\n\n    static member inline startTimed fmt = Printf.kprintf (fun str -> Report.BeginTimed(\"{0}\", str)) fmt\n    static member inline start fmt = Printf.kprintf (fun str -> Report.Begin(\"{0}\", str)) fmt\n    static member inline stop() = Report.End() |> ignore\n    static member inline stop fmt = Printf.kprintf (fun str -> Report.End(\"{0}\", str) |> ignore) fmt\n\n    static member inline section fmt = Printf.kprintf (fun str -> fun c -> Report.Begin(\"{0}\", str); c(); Report.End() |> ignore) fmt\n\n    static member check c fmt = Printf.kprintf (fun str -> if not c then printLines (fun str -> Report.Warn(\"{0}\", str)) str) fmt\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Measures.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Diagnostics\n\n\n\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype MicroTime =\n    struct\n        val mutable public TotalNanoseconds : int64\n\n        member x.TotalMinutes = float x.TotalNanoseconds / 60000000000.0\n        member x.TotalSeconds = float x.TotalNanoseconds / 1000000000.0\n        member x.TotalMilliseconds = float x.TotalNanoseconds / 1000000.0\n        member x.TotalMicroseconds = float x.TotalNanoseconds / 1000.0\n        \n        member x.IsZero = x.TotalNanoseconds = 0L\n\n        member x.IsPositiveInfinity =\n            x.TotalNanoseconds = Int64.MaxValue\n\n        member x.IsNegativeInfinity =\n            x.TotalNanoseconds = Int64.MinValue\n\n        member x.IsInfinite =\n            x.TotalNanoseconds = Int64.MaxValue ||\n            x.TotalNanoseconds = Int64.MinValue\n\n        member x.IsFinite =\n            x.TotalNanoseconds <> Int64.MaxValue &&\n            x.TotalNanoseconds <> Int64.MinValue\n\n        member private x.AsString =\n            x.ToString()\n\n        override x.ToString() =\n            if x.IsPositiveInfinity then \"inf\"\n            elif x.IsNegativeInfinity then \"-inf\"\n            else\n                let ns = abs x.TotalNanoseconds\n                if ns = 0L then \"0\"\n                elif ns >= 60000000000L then \n                    let m = x.TotalMinutes\n                    let sec = abs (60.0 * (m % 1.0))\n                    if sec = 0.0 then sprintf \"%.0fm\" m\n                    else sprintf \"%.0fm%.0fs\" m sec\n                elif ns >= 1000000000L then \n                    sprintf \"%.3fs\" x.TotalSeconds\n                elif ns >= 1000000L then \n                    sprintf \"%.2fms\" x.TotalMilliseconds\n                elif ns >= 1000L then \n                    sprintf \"%.1fµs\" x.TotalMicroseconds\n                else \n                    sprintf \"%dns\" x.TotalNanoseconds\n\n\n        static member (+) (l : MicroTime, r : MicroTime) = \n            if l.IsPositiveInfinity then MicroTime.PositiveInfinity\n            elif l.IsNegativeInfinity then MicroTime.NegativeInfinity\n            elif r.IsPositiveInfinity then MicroTime.PositiveInfinity\n            elif r.IsNegativeInfinity then MicroTime.NegativeInfinity\n            else MicroTime(l.TotalNanoseconds + r.TotalNanoseconds)\n\n        static member (-) (l : MicroTime, r : MicroTime) = \n            if l.IsPositiveInfinity then MicroTime.PositiveInfinity\n            elif l.IsNegativeInfinity then MicroTime.NegativeInfinity\n            elif r.IsPositiveInfinity then MicroTime.NegativeInfinity\n            elif r.IsNegativeInfinity then MicroTime.PositiveInfinity\n            else MicroTime(l.TotalNanoseconds - r.TotalNanoseconds)\n\n        static member (~-) (l : MicroTime) = \n            if l.IsPositiveInfinity then MicroTime.NegativeInfinity\n            elif l.IsNegativeInfinity then MicroTime.PositiveInfinity\n            else MicroTime(-l.TotalNanoseconds)\n\n        static member (*) (l : MicroTime, r : float) = \n            MicroTime(MicroTime.ToFloat l * r)\n\n        static member (*) (l : float, r : MicroTime) = \n            MicroTime(l * MicroTime.ToFloat r)\n\n        static member (*) (l : MicroTime, r : int) =\n            if l.IsInfinite then\n                if r = 0 then MicroTime.NegativeInfinity\n                else if r > 0 then l else -l\n            else\n                MicroTime(l.TotalNanoseconds * int64 r)\n\n        static member (*) (l : int, r : MicroTime) =\n            if r.IsInfinite then\n                if l = 0 then MicroTime.NegativeInfinity\n                else if l > 0 then r else -r\n            else\n                MicroTime(int64 l * r.TotalNanoseconds)\n\n        static member (/) (l : MicroTime, r : int) =\n            if l.IsInfinite then\n                if r = 0 then MicroTime.NegativeInfinity\n                else if r > 0 then l else -l\n            else\n                MicroTime(l.TotalNanoseconds / int64 r)\n\n        static member (/) (l : MicroTime, r : float) = \n            MicroTime(MicroTime.ToFloat l / r)\n\n        static member private ToFloat (t : MicroTime) : float =\n            if t.IsPositiveInfinity then Double.PositiveInfinity\n            elif t.IsNegativeInfinity then Double.NegativeInfinity\n            else float t.TotalNanoseconds\n\n        static member DivideByInt(l : MicroTime, r : int) = l / r\n\n        static member (/) (l : MicroTime, r : MicroTime) = \n            MicroTime.ToFloat l / MicroTime.ToFloat r\n\n        static member PositiveInfinity = MicroTime(Int64.MaxValue)\n        static member NegativeInfinity = MicroTime(Int64.MinValue)\n        static member Zero = MicroTime(0L)\n\n        static member FromNanoseconds(ns : int64) = MicroTime(ns)\n        static member FromMicroseconds(us : float) = MicroTime(us * 1000.0)\n        static member FromMilliseconds(ms : float) = MicroTime(ms * 1000000.0)\n        static member FromSeconds(s : float) = MicroTime(s * 1000000000.0)\n        static member FromMinutes(m : float) = MicroTime(m * 60000000000.0)\n        static member FromTicks (t : int64) = MicroTime.FromMicroseconds(float t * float TimeSpan.TicksPerSecond / 1000000.0)\n\n        static member Nanosecond = MicroTime(1L)\n        static member Microsecond = MicroTime(1000L)\n        static member Millisecond = MicroTime(1000000L)\n        static member Second = MicroTime(1000000000L)\n        static member Minute = MicroTime(60000000000L)\n\n        new (ns : int64) = { TotalNanoseconds = ns }\n        new (ts : TimeSpan) = { TotalNanoseconds = ts.Ticks * (1000000000L / TimeSpan.TicksPerSecond) }\n        new (ns : float) =\n            { TotalNanoseconds =\n                if Fun.IsFinite ns then int64 ns\n                elif Fun.IsPositiveInfinity ns then Int64.MaxValue\n                else Int64.MinValue\n            }\n\n    end\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule MicroTime =\n    \n    let zero = MicroTime.Zero\n\n    let ns = MicroTime.Nanosecond\n    let us = MicroTime.Microsecond\n    let ms = MicroTime.Millisecond\n    let s = MicroTime.Second\n    let m = MicroTime.Minute\n    \n    let inline ofNanoseconds (ns : ^a) = MicroTime(int64 ns)\n    let inline ofMicroseconds (us : ^a) = MicroTime.FromMicroseconds(float us)\n    let inline ofMilliseconds (us : ^a) = MicroTime.FromMilliseconds(float us)\n    let inline ofSeconds (us : ^a) = MicroTime.FromSeconds(float us)\n    let inline ofMinutes (us : ^a) = MicroTime.FromMinutes(float us)\n\n    let inline nanoseconds (t : MicroTime) = t.TotalNanoseconds\n    let inline microseconds (t : MicroTime) = t.TotalMicroseconds\n    let inline milliseconds (t : MicroTime) = t.TotalMilliseconds\n    let inline seconds (t : MicroTime) = t.TotalSeconds\n    let inline minutes (t : MicroTime) = t.TotalMinutes\n    \n    let inline isZero (t : MicroTime) = t.IsZero\n    let inline isFinite (t : MicroTime) = t.IsFinite\n    let inline isPositiveInfinity (t : MicroTime) = t.IsPositiveInfinity\n    let inline isNegativeInfinity (t : MicroTime) = t.IsNegativeInfinity\n\n\n\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype Mem =\n    struct\n        val mutable public Bytes : int64\n\n        member x.IsZero = x.Bytes = 0L\n\n        member x.Kibibytes = float x.Bytes / 1024.0\n        member x.Mebibytes = float x.Bytes / 1048576.0\n        member x.Gibibytes = float x.Bytes / 1073741824.0\n        member x.Tebibytes = float x.Bytes / 1099511627776.0\n        member x.Pebibytes = float x.Bytes / 1125899906842624.0\n        member x.Exbibytes = float x.Bytes / 1152921504606846976.0\n        member x.Kilobytes = float x.Bytes / 1000.0\n        member x.Megabytes = float x.Bytes / 1000000.0\n        member x.Gigabytes = float x.Bytes / 1000000000.0\n        member x.Terabytes = float x.Bytes / 1000000000000.0\n        member x.Petabytes = float x.Bytes / 1000000000000000.0\n        member x.Exabytes  = float x.Bytes / 1000000000000000000.0\n        \n        static member Byte      = Mem(1L)\n        static member Kibibyte  = Mem(1024L)\n        static member Mebibyte  = Mem(1048576L)\n        static member Gibibyte  = Mem(1073741824L)\n        static member Tebibyte  = Mem(1099511627776L)\n        static member Pebibyte  = Mem(1125899906842624L)\n        static member Exbibyte  = Mem(1152921504606846976L)\n        static member Kilobyte  = Mem(1000L)\n        static member Megabyte  = Mem(1000000L)\n        static member Gigabyte  = Mem(1000000000L)\n        static member Terabyte  = Mem(1000000000000L)\n        static member Petabyte  = Mem(1000000000000000L)\n        static member Exabyte   = Mem(1000000000000000000L)\n\n        member private x.AsString = x.ToString()\n        \n        member x.ToStringDecimal() =\n            let b = abs x.Bytes\n            if b = 0L then \"0\"\n            elif b >= 1000000000000000000L then sprintf \"%.3fEB\" x.Exabytes\n            elif b >= 1000000000000000L then sprintf \"%.3fPB\" x.Petabytes\n            elif b >= 1000000000000L then sprintf \"%.3fTB\" x.Terabytes\n            elif b >= 1000000000L then sprintf \"%.3fGB\" x.Gigabytes\n            elif b >= 1000000L then sprintf \"%.2fMB\" x.Megabytes\n            elif b >= 1000L then sprintf \"%.1fKiB\" x.Kilobytes\n            else sprintf \"%dB\" x.Bytes\n\n        member x.ToStringBinary() =\n            let b = abs x.Bytes\n            if b = 0L then \"0\"\n            elif b >= 1152921504606846976L then sprintf \"%.3fEiB\" x.Exbibytes\n            elif b >= 1125899906842624L then sprintf \"%.3fPiB\" x.Pebibytes\n            elif b >= 1099511627776L then sprintf \"%.3fTiB\" x.Tebibytes\n            elif b >= 1073741824L then sprintf \"%.3fGiB\" x.Gibibytes\n            elif b >= 1048576L then sprintf \"%.2fMiB\" x.Mebibytes\n            elif b >= 1024L then sprintf \"%.1fKiB\" x.Kibibytes\n            else sprintf \"%dB\" x.Bytes\n\n        member x.ToString(decimal : bool) =\n            if decimal then x.ToStringDecimal()\n            else x.ToStringBinary()\n\n        override x.ToString() = x.ToStringBinary()\n\n        static member Zero = Mem(0L)\n\n        static member (+) (l : Mem, r : Mem) = Mem(l.Bytes + r.Bytes)\n        static member (-) (l : Mem, r : Mem) = Mem(l.Bytes - r.Bytes)\n        static member (~-) (l : Mem) = Mem(-l.Bytes)\n\n        static member (*) (l : Mem, r : int) = Mem(l.Bytes * int64 r)\n        static member (*) (l : Mem, r : float) = Mem(float l.Bytes * r |> int64)\n        static member (*) (l : int, r : Mem) = Mem(int64 l * r.Bytes)\n        static member (*) (l : float, r : Mem) = Mem(l * float r.Bytes |> int64)\n        static member (/) (l : Mem, r : int) = Mem(l.Bytes / int64 r)\n        static member (/) (l : Mem, r : float) = Mem(float l.Bytes / r |> int64)\n        static member (/) (l : Mem, r : Mem) = float l.Bytes / float r.Bytes\n\n\n        static member FromKibibytes(kib : float) = Mem(int64 (1024.0 * kib))\n        static member FromMebibytes(mib : float) = Mem(int64 (1048576.0 * mib))\n        static member FromGibibytes(gib : float) = Mem(int64 (1073741824.0 * gib))\n        static member FromTebibytes(tib : float) = Mem(int64 (1099511627776.0 * tib))\n        static member FromPebibytes(pib : float) = Mem(int64 (1125899906842624.0 * pib))\n        static member FromExbibytes(eib : float) = Mem(int64 (1152921504606846976.0 * eib))\n        \n        static member FromKilobytes(kb : float) = Mem(int64 (1000.0 * kb))\n        static member FromMegabytes(mb : float) = Mem(int64 (1000000.0 * mb))\n        static member FromGigabytes(gm : float) = Mem(int64 (1000000000.0 * gm))\n        static member FromTerabytes(tb : float) = Mem(int64 (1000000000000.0 * tb))\n        static member FromPetabytes(pb : float) = Mem(int64 (1000000000000000.0 * pb))\n        static member FromExabytes(eb : float)  = Mem(int64 (1000000000000000000.0 * eb))\n\n        new(bytes : int64) = { Bytes = bytes }\n        new(bytes : int) = { Bytes = int64 bytes }\n        new(bytes : uint64) = { Bytes = int64 bytes }\n        new(bytes : uint32) = { Bytes = int64 bytes }\n        new(bytes : nativeint) = { Bytes = int64 bytes }\n        new(bytes : unativeint) = { Bytes = int64 bytes }\n    end\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Mem =\n    let zero = Mem.Zero\n    \n    let B = Mem.Byte\n    let kB = Mem.Kilobyte\n    let MB = Mem.Megabyte\n    let GB = Mem.Gigabyte\n    let TB = Mem.Terabyte\n    let PB = Mem.Petabyte\n    let EB = Mem.Exabyte\n\n    let kiB = Mem.Kibibyte\n    let MiB = Mem.Mebibyte\n    let GiB = Mem.Gibibyte\n    let TiB = Mem.Tebibyte\n    let PiB = Mem.Pebibyte\n    let EiB = Mem.Exbibyte\n\n    \n    let inline ofBytes (b : ^a) = Mem(int64 b)\n\n    let inline ofKibibytes (kib : ^a) = Mem.FromKibibytes(float kib)\n    let inline ofMebibytes (mib : ^a) = Mem.FromMebibytes(float mib)\n    let inline ofGibibytes (gib : ^a) = Mem.FromGibibytes(float gib)\n    let inline ofTebibytes (tib : ^a) = Mem.FromTebibytes(float tib)\n    let inline ofPebibytes (pib : ^a) = Mem.FromPebibytes(float pib)\n    let inline ofExbibytes (eib : ^a) = Mem.FromExbibytes(float eib)\n    \n    let inline ofKilobytes (kb : ^a) = Mem.FromKilobytes(float kb)\n    let inline ofMegabytes (mb : ^a) = Mem.FromMegabytes(float mb)\n    let inline ofGigabytes (gb : ^a) = Mem.FromGigabytes(float gb)\n    let inline ofTerabytes (tb : ^a) = Mem.FromTerabytes(float tb)\n    let inline ofPetabytes (pb : ^a) = Mem.FromPetabytes(float pb)\n    let inline ofExabytes  (eb : ^a) = Mem.FromExabytes(float eb)\n\n\n[<AutoOpen>]\nmodule ``Stopwatch Extensions`` =\n\n    type TimeSpan with\n        member x.MicroTime = MicroTime x\n\n    type Stopwatch with\n        member x.MicroTime = MicroTime x.Elapsed"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Monads.fs",
    "content": "﻿namespace Aardvark.Base\n\n\nmodule Monads =\n\n    module Cont =\n        type Cont<'r, 'a> = { runCont : ('a -> 'r) -> 'r }\n    \n        type ContBuilder() =\n            member x.Bind(m : Cont<'r, 'a>, f : 'a -> Cont<'r, 'b>) : Cont<'r, 'b> =\n                { runCont = fun c -> m.runCont (fun v -> (f v).runCont c) }\n\n            member x.Return(v : 'a) : Cont<'r, 'a> =\n                { runCont = fun c -> c v }\n\n            member x.ReturnFrom(c : Cont<'r, 'a>) =\n                c\n\n            member x.Delay(f : unit -> Cont<'r, 'a>) : Cont<'r, 'a> =\n                { runCont = fun c -> f().runCont c }\n\n            member x.Combine(l : Cont<'r, unit>, r : Cont<'r, 'a>) : Cont<'r, 'a> =\n                { runCont = fun c -> l.runCont (fun () -> r.runCont c) }\n\n            member x.Zero() : Cont<'r, unit> =\n                { runCont = fun c -> c () }\n                  \n            member x.For(elements : seq<'a>, f : 'a -> Cont<'r, unit>) : Cont<'r, unit> =\n                { runCont = fun c ->\n\n                    let mutable run = fun () -> c()\n                    for e in elements do\n                        let inner = run\n                        run <- fun c -> (f e).runCont inner\n\n                    run()\n                }\n                 \n            member x.While(condition : unit -> bool, b : Cont<'r, unit>) : Cont<'r, unit> =\n                { runCont = fun c ->\n                    if condition() then\n                        b.runCont (fun () -> x.While(condition, b).runCont c)\n                    else\n                        c ()\n                }     \n\n        let cont = ContBuilder()\n\n        let test() =\n            let a = cont { return 1 }\n            let b = cont { return 2 }\n            let c = cont {\n                        let! a = a\n                        let! b = b\n                        return a + b \n                    }\n\n            c.runCont (printfn \"%d\")\n\n    module StateOld =\n        type State<'s, 'a> = { runState : 's -> 'a * 's } \n\n\n\n        type StateBuilder() =\n            member x.Bind(m : State<'s, 'a>, f : 'a -> State<'s, 'b>) : State<'s, 'b> =\n                { runState = fun s -> let(v, s') = m.runState s in (f v).runState s' } \n\n            member x.Return(v : 'a) : State<'s, 'a> =\n                { runState = fun s -> (v,s) }\n\n            member x.ReturnFrom(s : State<'s, 'a>) =\n                s\n\n            member x.Delay(f : unit -> State<'s, 'a>) =\n                { runState = fun s -> f().runState s }\n\n            member x.Combine(l : State<'s, unit>, r : State<'s, 'a>) : State<'s, 'a> =\n                x.Bind(l, fun () -> r)\n\n            member x.Zero() : State<'s, unit> =\n                { runState = fun s -> ((), s) }\n\n            member x.For(elements : seq<'a>, f : 'a -> State<'s, unit>) : State<'s, unit> =\n                { runState = fun s ->\n                    let mutable current = s\n                    for e in elements do\n                        let ((), s') = (f e).runState current\n                        current <- s'\n                    ((), current)\n                }\n\n            member x.While(condition : unit -> bool, m : State<'s, unit>) : State<'s, unit> =\n                { runState = fun s ->\n                    let mutable current = s\n                    while condition() do\n                        let ((), s') = m.runState current\n                        current <- s'\n                    ((), current)\n                }\n\n\n        let state = StateBuilder()\n\n        let putState s = { runState = fun _ -> ((), s) }\n        let getState = { runState = fun s -> (s,s) }\n        let modifyState f = { runState = fun s -> ((), f s) }\n\n\n        let test() =\n            let a = state { return 1 }\n            let c = state {\n                        let! s = getState\n                        let! a = a\n                        do! putState 10\n                        return s + a\n                    }\n\n            let r = c.runState 2\n            printfn \"%A\" r\n\n    module State =\n\n        [<AbstractClass>]\n        type State<'s, 'a>() =\n            abstract member Run : byref<'s> -> 'a\n            abstract member RunUnit : byref<'s> -> unit\n\n            default x.Run(s) = x.RunUnit(&s); Unchecked.defaultof<'a>\n            default x.RunUnit(s) = x.Run(&s) |> ignore\n\n        module State =\n            \n            let ignore (s : State<'s, 'a>) =\n                { new State<'s, unit>() with\n                    member x.RunUnit state =\n                        s.RunUnit(&state)\n                }\n\n            let map (f : 'a -> 'b) (s : State<'s, 'a>) =\n                { new State<'s, 'b>() with\n                    member x.Run state =\n                        let a = s.Run(&state)\n                        f a\n                }\n\n            let bind (f : 'a -> State<'s, 'b>) (s : State<'s, 'a>) =\n                { new State<'s, 'b>() with\n                    member x.Run state =\n                        let a = s.Run(&state) |> f\n                        a.Run(&state)\n                }\n\n            let value (v : 'a) =\n                { new State<'s, 'a>() with\n                    member x.Run _ = v\n                }\n\n            let get<'s> =\n                { new State<'s, 's>() with\n                    member x.Run state = state\n                }\n\n            let put (s : 's) =\n                { new State<'s, unit>() with\n                    member x.RunUnit state = state <- s\n                }\n\n            let modify (f : 's -> 's) =\n                { new State<'s, unit>() with\n                    member x.RunUnit state = state <- f state\n                }\n\n            let custom (f : 's -> 's * 'a) =\n                { new State<'s, 'a>() with\n                    member x.Run state = \n                        let (s,r) = f state\n                        state <- s\n                        r\n                }\n\n            let run (state : 's) (m : State<'s, 'a>) =\n                let mutable res = state\n                let v = m.Run(&res)\n                res, v\n\n            let evaluate (state : 's) (m : State<'s, 'a>) =\n                let mutable res = state\n                let v = m.Run(&res)\n                v\n\n        module Seq =\n            let mapS (f : 'a -> State<'s, 'b>) (input : seq<'a>) =\n                { new State<'s, seq<'b>>() with\n                    member x.Run state =\n                        let result = System.Collections.Generic.List<'b>()\n                        for e in input do\n                            result.Add (f(e).Run(&state))\n                        result :> seq<_>    \n                }\n\n            let collectS (f : 'a -> State<'s, seq<'b>>) (input : seq<'a>) =\n                { new State<'s, seq<'b>>() with\n                    member x.Run state =\n                        let result = System.Collections.Generic.List<'b>()\n                        for e in input do\n                            result.AddRange (f(e).Run(&state))\n                        result :> seq<_>    \n                }\n\n            let chooseS (f : 'a -> State<'s, Option<'b>>) (input : seq<'a>) =\n                { new State<'s, seq<'b>>() with\n                    member x.Run state =\n                        let result = System.Collections.Generic.List<'b>()\n                        for e in input do\n                            match f(e).Run(&state) with\n                                | Some res -> result.Add res\n                                | _ -> ()\n                        result :> seq<_>    \n                }\n\n        module List =\n            let mapS (f : 'a -> State<'s, 'b>) (input : list<'a>) =\n                { new State<'s, list<'b>>() with\n                    member x.Run state =\n                        let result = System.Collections.Generic.List<'b>()\n                        for e in input do\n                            result.Add (f(e).Run(&state))\n                        result |> CSharpList.toList\n                }\n\n            let collectS (f : 'a -> State<'s, seq<'b>>) (input : list<'a>) =\n                { new State<'s, list<'b>>() with\n                    member x.Run state =\n                        let result = System.Collections.Generic.List<'b>()\n                        for e in input do\n                            result.AddRange (f(e).Run(&state))\n                        result |> CSharpList.toList\n                }\n\n            let chooseS (f : 'a -> State<'s, Option<'b>>) (input : list<'a>) =\n                { new State<'s, list<'b>>() with\n                    member x.Run state =\n                        let result = System.Collections.Generic.List<'b>()\n                        for e in input do\n                            match f(e).Run(&state) with\n                                | Some res -> result.Add res\n                                | _ -> ()\n                        result |> CSharpList.toList\n                }\n\n\n        type StateBuilder() =\n            member x.Bind(m : State<'s, 'a>, f : 'a -> State<'s, 'b>) =\n                State.bind f m\n\n            member x.Return(v : 'a) = \n                State.value v\n\n            member x.ReturnFrom(m : State<'s, 'a>) =\n                m\n\n            member x.Delay(f : unit -> State<'s, 'a>) =\n                { new State<'s, 'a>() with\n                    member x.Run(state) =\n                        f().Run(&state)\n                }\n\n            member x.Combine(l : State<'s, unit>, r : State<'s, 'a>) =\n                { new State<'s, 'a>() with\n                    member x.Run(state) =\n                        l.Run(&state)\n                        r.Run(&state)\n                }\n\n            member x.Zero() : State<'s, unit> =\n                { new State<'s, unit>() with\n                    member x.RunUnit(state) =\n                        ()\n                }\n\n            member x.For(input : seq<'a>, f : 'a -> State<'s, unit>) =\n                { new State<'s, unit>() with\n                    member x.RunUnit(state) =\n                        for e in input do\n                            f(e).Run(&state)\n                }\n\n            member x.While(guard : unit -> bool, body : State<'s, unit>) =\n                { new State<'s, unit>() with\n                    member x.RunUnit(state) =\n                        while guard() do\n                            body.Run(&state)\n                }\n\n            member x.TryFinally(m : State<'s, 'a>, fin : unit -> unit) =\n                { new State<'s, 'a>() with\n                    member x.Run(state) =\n                        try m.Run(&state)\n                        finally fin()\n                }\n\n            member x.TryWith(m : State<'s, 'a>, handler : exn -> State<'s, 'a>) =\n                { new State<'s, 'a>() with\n                    member x.Run(state) =\n                        let mutable local = state\n                        try \n                            let res = m.Run(&local)\n                            state <- local\n                            res\n                        with e ->  \n                            handler(e).Run(&state)\n                }\n\n            member x.Using(v : 'a, f : 'a -> State<'s, 'b>) =\n                { new State<'s, 'b>() with\n                    member x.Run(state) = \n                        use v = v\n                        let res = f(v).Run(&state)\n                        res\n                }\n\n            member x.TryFinally(m : State<'s, 'a>, fin : unit -> State<'s, unit>) =\n                { new State<'s, 'a>() with\n                    member x.Run(state) =\n                        try m.Run(&state)\n                        finally fin().Run(&state)\n                }\n\n            member x.TryFinally(m : State<'s, 'a>, fin : unit -> 's -> 's) =\n                { new State<'s, 'a>() with\n                    member x.Run(state) =\n                        try m.Run(&state)\n                        finally state <- fin () state\n                }\n\n        let state = StateBuilder()\n\n\n    module StateOpt =\n\n        type State<'s, 'a> = { runState : 's -> Option<'a * 's> } \n\n        type StateBuilder() =\n            member x.Bind(m : State<'s, 'a>, f : 'a -> State<'s, 'b>) : State<'s, 'b> =\n                { runState = fun s -> match m.runState s with\n                                       | Some (v, s') -> (f v).runState s'\n                                       | None -> None } \n\n            member x.Return(v : 'a) : State<'s, 'a> =\n                { runState = fun s -> Some (v,s) }\n\n            member x.ReturnFrom(s : State<'s, 'a>) =\n                s\n\n            member x.Delay(f : unit -> State<'s, 'a>) =\n                { runState = fun s -> f().runState s }\n\n            member x.Combine(l : State<'s, unit>, r : State<'s, 'a>) : State<'s, 'a> =\n                x.Bind(l, fun () -> r)\n\n            member x.Zero() : State<'s, unit> =\n                { runState = fun s -> Some ((), s) }\n\n            member x.For(elements : seq<'a>, f : 'a -> State<'s, unit>) : State<'s, unit> =\n                { runState = fun s ->\n                    if Seq.isEmpty elements then Some ((), s)\n                    else \n                        match (f <| Seq.head elements).runState s with\n                         | None -> None\n                         | Some ((),s') -> x.For(Seq.skip 1 elements, f).runState s' \n                }\n\n\n        let state = StateBuilder()\n\n        let putState s = { runState = fun _ -> Some ((), s) }\n        let getState = { runState = fun s -> Some (s,s) }\n        let modifyState f = { runState = fun s -> Some ((), f s) }\n        let evalState (m : State<'s,'a>) (state : 's) = m.runState state \n\n        let fail = { runState = fun s -> None }\n\n        let rec map2M (f : 'a -> 'b -> State<'s,'c>) (l0 : list<'a>) (l1 : list<'b>) : State<'s,list<'c>> =\n            state {\n                match l0,l1 with\n                 | x::xs, y::ys -> let! c = f x y\n                                   let! rest = map2M f xs ys\n                                   return c :: rest\n                 | [],[] -> return []\n                 | _ -> return failwith \"map2M list counts differ.\"\n            }\n\n    module StateCont =\n        type StateCont<'s, 'r, 'a> = { runStateCont : 's -> ('a * 's -> 'r) -> 'r }\n\n        type StateContBuilder() =\n            member x.Bind(m : StateCont<'s, 'r, 'a>, f : 'a -> StateCont<'s, 'r, 'b>) : StateCont<'s, 'r, 'b> =\n                { runStateCont = fun s c -> m.runStateCont s (fun (v,s') -> (f v).runStateCont s' c) }\n            \n            member x.Return(v : 'a) : StateCont<'s, 'r, 'a> =\n                { runStateCont = fun s c -> c(v, s) }\n\n            member x.ReturnFrom(m : StateCont<'s, 'r, 'a>) =\n                m\n\n            member x.Delay(f : unit -> StateCont<'s, 'r, 'a>) : StateCont<'s, 'r, 'a> =\n                { runStateCont = fun s c -> f().runStateCont s c }\n\n            member x.Combine(l : StateCont<'s, 'r, unit>, r : StateCont<'s, 'r, 'a>) : StateCont<'s, 'r, 'a> =\n                x.Bind(l, fun () -> r)\n\n            member x.Zero() : StateCont<'s, 'r, unit> =\n                { runStateCont = fun s c -> c((),s) }\n\n            member x.For(elements : seq<'a>, f : 'a -> StateCont<'s, 'r, unit>) : StateCont<'s, 'r, unit> =\n                { runStateCont = fun s c ->\n\n                    let mutable run = fun s -> c((), s)\n                    for e in elements do\n                        let inner = run\n                        run <- fun s -> (f e).runStateCont s (fun ((), s') -> inner s')\n\n                    run s\n                }\n                 \n            member x.While(condition : unit -> bool, b : StateCont<'s, 'r, unit>) : StateCont<'s, 'r, unit> =\n                { runStateCont = fun s c ->\n                    if condition() then\n                        b.runStateCont s (fun ((),s') -> x.While(condition, b).runStateCont s' c)\n                    else\n                        c ((),s)\n                }     \n\n\n        let scont = StateContBuilder()\n\n        let putState s = { runStateCont = fun _ c -> c((), s) }\n        let getState = { runStateCont = fun s c -> c(s,s) }\n        let modifyState f = { runStateCont = fun s c -> c((), f s) }\n\n        let test() =\n            let a = scont { return 1 }\n            let c = scont {\n                        let! s = getState\n                        let! a = a\n                        for i in 1..10 do\n                            do! modifyState ((+)1)\n\n                        let! s' = getState\n                        return s' - s + a\n                    }\n\n            c.runStateCont 0 (printfn \"%A\")\n\n    module StateSeq =\n        type StateSeq<'s, 'a> = { runStateSeq : 's -> 's * Option<'a * StateSeq<'s, 'a>> }\n        \n        let empty<'s, 'a> : StateSeq<'s, 'a> =  { runStateSeq = fun s -> s,None }\n\n        type StateSeqBuilder() =\n            member x.Yield(v : 'a) =\n                { runStateSeq = fun s -> s, Some(v, empty) }\n\n            member x.Bind(m : StateSeq<'s, 'a>, f : 'a -> StateSeq<'s, 'b>) : StateSeq<'s, 'b> =\n                { runStateSeq = fun s -> \n                    let s, o = m.runStateSeq s\n                    match o with\n                        | Some(v,_) -> (f v).runStateSeq s\n                        | None -> failwith \"empty sequence\" }\n\n            member x.Return( v : 'a ) = { runStateSeq = fun s -> s, Some(v, empty) }\n\n            member x.Zero() = empty\n\n            member x.Combine(l : StateSeq<'s, 'a>, r : StateSeq<'s, 'a>) =\n                { runStateSeq = fun s ->\n                    let s, o = l.runStateSeq s\n                    match o with\n                        | None -> r.runStateSeq s\n                        | Some(v,c) -> s,Some(v, x.Combine(c,r))\n                }\n\n            member x.For(self : StateSeq<'s, 'a>, f : 'a -> StateSeq<'s, 'b>) : StateSeq<'s, 'b> =\n                { runStateSeq = fun s ->\n                    let s, o = self.runStateSeq s\n                    match o with\n                        | None -> s,None\n                        | Some(h,cSelf) ->\n                            let s,o = (f h).runStateSeq s\n                            match o with\n                                | Some(v,cResult) -> x.Combine(x.Return(v), x.Combine(cResult, x.For(cSelf, f))).runStateSeq s\n                                | None -> x.For(cSelf, f).runStateSeq s\n\n                }\n\n            member x.Delay(f : unit -> StateSeq<'s, 'a>) =\n                { runStateSeq = fun s -> (f ()).runStateSeq s }\n\n            member x.For(self : seq<'a>, f : 'a -> StateSeq<'s, 'b>) : StateSeq<'s, 'b> =\n                if Seq.isEmpty self then\n                    empty\n                else\n                    let h = Seq.head self\n                    x.Combine(f h, x.For(Seq.skip 1 self, f))\n\n        let putState s = { runStateSeq = fun _ -> s,Some((), empty) }\n        let getState = { runStateSeq = fun s -> s,Some (s,empty) }\n        let rec toSeq (state : 's) (m : StateSeq<'s, 'a>) : seq<'s * 'a> =\n            seq {\n                let s,o = m.runStateSeq state\n                match o with\n                    | Some(v,c) ->\n                        yield (s,v)\n                        yield! toSeq s c\n                    | None -> ()\n            }\n\n        let sseq = StateSeqBuilder()\n\n\n        let a() =\n            sseq {\n                do! putState -12\n                printfn \"yield 1\"\n                yield 1\n                \n                do! putState 123\n                printfn \"yield 2\"\n                yield 2\n            }\n        let b() = \n            sseq {\n                for a in a() do\n                    printfn \"loop for %d\" a\n                    yield 11 * a\n            }\n\n        let test() =\n            b() |> toSeq 5 |> printfn \"%A\"\n\n    module Option = \n        open System.Collections.Generic\n\n        type OptionBuilder() =\n            member x.Bind(m : Option<'a>, f : 'a -> Option<'b>) : Option<'b> =\n                match m with\n                    | Some v -> f v\n                    | None -> None\n\n            member x.Return(v : 'a) =\n                Some v\n\n            member x.ReturnFrom(m : Option<'a>) =\n                m\n\n            member x.Zero() : Option<unit> =\n                Some ()\n\n            member x.Combine(l : Option<unit>, r : unit -> Option<'a>) : Option<'a> =\n                match l with\n                    | Some () -> r ()\n                    | None -> None\n\n            member x.For(elements : seq<'a>, f : 'a -> Option<unit>) : Option<unit> =\n                use enumerator = elements.GetEnumerator()\n                let rec fold (e : IEnumerator<_>) =\n                    if e.MoveNext() then\n                        match f e.Current with\n                         | Some v -> fold e\n                         | None -> None\n                    else Some ()\n                fold enumerator\n\n            member x.Delay(f : unit -> Option<'a>) =\n                f\n\n            member x.Run(f : unit -> Option<'a>) = f ()\n\n            member x.While(g : unit -> bool, b : unit -> Option<unit>) =\n                let rec run () =\n                    if g () then\n                        match b () with\n                         | Some v -> run ()\n                         | None -> None\n                    else Some ()\n                run ()\n\n            member x.TryFinally(m : unit -> Option<'a>, fin : unit -> unit) =\n                try m()\n                finally fin()\n\n            member x.TryWith(m : unit -> Option<'a>, handler : exn -> Option<'a>) =\n                try m()\n                with e -> handler e\n\n        let option = OptionBuilder()\n\n   \n    module Optics =\n        open Microsoft.FSharp.Quotations \n        open State\n\n        type [<AbstractClass>] Lens<'a, 'b>() =\n            abstract member Get : 'a -> 'b\n            abstract member Set : 'a * 'b -> 'a\n\n            static member Compose(l : Lens<'a, 'b>, r : Lens<'b, 'c>) =\n                { new Lens<'a, 'c>() with\n                    member x.Get a = a |> l.Get |> r.Get\n                    member x.Set(a,c) = l.Set(a, r.Set(l.Get a, c))\n                }\n\n            static member Compose(l : Lens<'a, 'b>, r : Prism<'b, 'c>) =\n                { new Prism<'a, 'c>() with\n                    member x.Get a = a |> l.Get |> r.Get\n                    member x.Set(a,c) = l.Set(a, r.Set(l.Get a, c))\n                }\n\n        and [<AbstractClass>] Prism<'a, 'b>() =\n            abstract member Get : 'a -> Option<'b>\n            abstract member Set : 'a * 'b -> 'a\n\n            static member Compose(l : Prism<'a, 'b>, r : Lens<'b, 'c>) =\n                { new Prism<'a, 'c>() with\n                    member x.Get a = \n                        match a |> l.Get with\n                            | Some v -> r.Get v |> Some\n                            | None -> None\n\n                    member x.Set(a,c) = \n                        match l.Get a with\n                            | Some v -> l.Set(a, r.Set(v, c))\n                            | None -> a\n                }\n\n            static member Compose(l : Prism<'a, 'b>, r : Prism<'b, 'c>) =\n                { new Prism<'a, 'c>() with\n                    member x.Get a = a |> l.Get |> (Option.bind r.Get)\n                    member x.Set(a,c) = \n                        match l.Get a with\n                            | Some v -> l.Set(a, r.Set(v, c))\n                            | None -> a\n                }\n\n\n        module Lens =\n        \n            let inline compose (l : ^a) (r : ^b) =\n                ((^a or ^b) : (static member Compose : ^a * ^b -> ^c) (l, r)) \n\n            let create (get : 'a -> 'b) (set : 'a -> 'b -> 'a) =\n                { new Lens<'a, 'b>() with\n                    member x.Get a = get a\n                    member x.Set(a,b) = set a b\n                }\n\n        module Prism =\n            let create (get : 'a -> Option<'b>) (set : 'a -> 'b -> 'a) =\n                { new Prism<'a, 'b>() with\n                    member x.Get a = get a\n                    member x.Set(a,b) = set a b\n                }\n    \n        module List =\n            let head_<'a> =\n                { new Prism<list<'a>, 'a>() with\n                    member x.Get(l) =\n                        match l with\n                            | h :: _ -> Some h\n                            | _ -> None\n\n                    member x.Set(l, h) =\n                        match l with\n                            | [] -> [h]\n                            | _ :: rest -> h :: rest\n                }\n\n        module Set =\n            let IsContained (v : 'a) =\n                { new Lens<Set<'a>, bool>() with\n                    member x.Get(set) = Set.contains v set\n                    member x.Set(set, contains) =\n                        if contains then Set.add v set\n                        else Set.remove v set\n                }\n\n        module State =\n            let lift (l : Lens<'a, 'b>) (m : State<'b, 'r>) =\n                { new State<'a, 'r>() with\n                    member x.Run a =\n                        let mutable b = l.Get a\n                        let res = m.Run(&b)\n                        a <- l.Set(a, b)\n                        res\n                }\n\n        type Inner = { x : int } with\n            static member X = Lens.create (fun a -> a.x) (fun a x -> { a with x = x })\n\n        let inline (<==) (m : ^l) (v : ^b) =\n            { new State.State< ^a, unit >() with\n                member x.RunUnit(state) =\n                    state <- (^l : (member Set : ^a * ^b -> ^a) (m, state, v))        \n            }\n\n        let inline (.*) (l : ^l) (r : ^r) =\n            Lens.compose l r\n\n        \n\n        type Test = { a : Inner; b : Set<float> } with\n            static member A = Lens.create (fun v -> v.a) (fun v a -> { v with a = a })\n            static member B = Lens.create (fun v -> v.b) (fun v b -> { v with b = b })\n\n        \n        let test() =\n            let perform =\n                state {\n                    do! Test.B .* Set.IsContained 10.0 <== true\n                    do! Test.A .* Inner.X <== 1\n                }\n\n            let (v, ()) = perform |> State.run { a = { x = 10 }; b = Set.empty }\n\n            printfn \"%A\" v\n            \n            ()\n\n\n    module StringBuilder =\n        open System.Text\n\n        type BuilderType = StringBuilder -> StringBuilder\n\n        type StringBuilderType() =\n\n            member x.Yield(v : string) : BuilderType =\n                fun b -> b.Append v\n\n            member x.YieldFrom(v : seq<string>) : BuilderType =\n                fun b -> v |> Seq.iter (ignore << b.Append); b\n\n            member x.For(s : #seq<'a>, f : 'a -> BuilderType) : BuilderType =\n                fun b ->\n                    let mutable r = b\n                    for e in s do\n                        r <- f e r\n                    r\n\n            member x.Delay(f : unit -> BuilderType) : BuilderType = \n                fun b -> f () b\n\n            member x.Zero() : BuilderType = \n                fun b -> b\n\n            member x.Run(b : BuilderType) =\n                let input = StringBuilder()\n                let output = b input\n                output.ToString()\n\n        let string = StringBuilderType()\n        \n\n    let cont = Cont.cont\n    let state = State.state\n    let scont = StateCont.scont\n    let option = Option.option\n    let sopt = StateOpt.state\n    let sseq = StateSeq.sseq\n    \n\n    \n\n\nmodule Cancellable =\n\n    type CancelState = { comp : list<unit->unit> ; ct : System.Threading.CancellationToken }\n    type Cancellable<'a> = { runState : CancelState -> 'a * CancelState } \n\n    let throwAndRollback (s : CancelState) =\n        if s.ct.IsCancellationRequested then \n            for c in s.comp do c ()\n            s.ct.ThrowIfCancellationRequested()\n        else ()\n\n    module Cancellable =\n        \n        let onCancel (f : unit -> unit) : Cancellable<unit> =\n            { runState = fun s -> (), { s with comp = f::s.comp } }\n\n        let run (ct : System.Threading.CancellationToken) (m : Cancellable<'a>) =\n            try\n                let (v,s') = m.runState { comp = []; ct = ct }\n                ct.Register(new System.Action(fun () -> for c in s'.comp do c())) |> ignore\n                Some v\n            with | :? System.OperationCanceledException as o -> \n                None\n\n        let start (m : Cancellable<unit>) (ct : System.Threading.CancellationToken) =\n            Async.Start (async { return run ct m |> ignore } )\n\n        let ignore (m : Cancellable<'a>) : Cancellable<unit> =\n            { runState = \n                fun s ->\n                    let (_,s') = m.runState s \n                    (), s' \n            }\n\n        let withCompensation (f : 'a -> unit) (m : Cancellable<'a>) =\n           { runState = \n                fun s ->\n                    let (r,s') = m.runState s \n                    let comp () = f r\n                    r, { s' with comp = comp :: s'.comp }\n            }\n\n        let tryFinallyAndUndo (f : unit -> (unit * ('a -> unit))) (m : Cancellable<'a>) =\n           { runState = \n                fun s ->\n                    let (r,s') = m.runState s \n                    throwAndRollback s'\n                    let (), undo = f ()\n                    r, { s' with comp = (fun () -> undo r) :: s'.comp }\n            }\n\n        let tryFinally (f : unit -> unit) (m : Cancellable<'a>) =\n           { runState = \n                fun s ->\n                    let (r,s') = m.runState s \n                    throwAndRollback s'\n                    f ()\n                    r, s'\n            }\n\n        let cancellationToken () =  \n            { runState =\n                fun s -> s.ct, s \n            }\n\n    \n    type CancelBuilder() =\n\n        member x.Bind(m : Cancellable<'a>, f : 'a -> Cancellable<'b>) : Cancellable<'b> =\n            { runState = \n                fun s -> \n                    throwAndRollback s\n                    let (v, s') = m.runState s \n                    throwAndRollback s'\n                    (f v).runState s' } \n\n        member x.Return(v : 'a) : Cancellable<'a> =\n            { runState = \n                fun s -> \n                    throwAndRollback s\n                    (v,s) }\n\n        member x.ReturnFrom(s : Cancellable<'a>) =\n            s\n\n        member x.TryFinally(m : Cancellable<'a>, f : unit -> (unit * ('a -> unit))) =\n            Cancellable.tryFinallyAndUndo f m\n\n        member x.TryFinally(m : Cancellable<'a>, f : unit -> unit) =\n            Cancellable.tryFinally f m\n\n        member x.Delay(f : unit -> Cancellable<'a>) =\n            { runState = fun s -> throwAndRollback s; f().runState s }\n\n        member x.Combine(l : Cancellable<unit>, r : Cancellable<'a>) : Cancellable<'a> =\n            x.Bind(l, fun () -> r)\n\n        member x.Zero() : Cancellable<unit> =\n            { runState = fun s -> ((), s) }\n\n    let cancel = CancelBuilder()\n\n    module Test =\n        open System.Threading\n\n        let test () =\n            let a = \n                cancel {\n                    Thread.Sleep 100\n                    do! Cancellable.onCancel (fun () -> printfn \"undo a\")\n                    return 1\n                }\n            let b = \n                cancel {\n                    Thread.Sleep 100\n                    do! Cancellable.onCancel (fun () -> printfn \"undo b\")\n                    return 2\n                }\n            let c = \n                cancel {\n                    Thread.Sleep 100\n                    do! Cancellable.onCancel (fun () -> printfn \"undo c\")\n                    return 3\n                }\n            let d = \n                cancel {\n                    let! a = a\n                    printfn \"a: %A\" a\n                    let! b = b\n                    printfn \"b: %A\" b\n                    let! c = c\n                    printfn \"c: %A\" c\n                    let r = a + b + c\n                    printfn \"r: %A\" r\n                    return r\n                }\n            use cts = new System.Threading.CancellationTokenSource()\n            Cancellable.start (Cancellable.ignore d) cts.Token\n            Thread.Sleep 300\n            cts.Cancel()\n            printfn \"done\"\n\n\n    module StatefulStepVar =    \n        open System\n        open System.Threading\n\n        type Step<'a,'b> = { run : 'a -> Cancellable<'b>; }\n\n        let ofPrimitive (m : 'a -> Cancellable<'ba>) =\n            { run = m }\n\n        let compose (f : Step<'a,'b>) (g : Step<'b,'c>) (fuse : 'b -> 'c -> 'd) : Step<'a,'d> =\n            { run = fun a -> \n                cancel {\n                    let! a = f.run a\n                    let! b = g.run a\n                    return fuse a b\n                }\n            }\n\n        module Step =\n            let ofFun (f : 'a -> Cancellable<'b>) = { run = fun a -> f a }\n            \n            let run (f : Step<unit,'a>) (ct : System.Threading.CancellationToken) =\n                let result = System.Threading.Tasks.TaskCompletionSource<_>()\n                try\n                    let r = f.run ()\n                    result.SetResult r\n                with | :? System.OperationCanceledException as o -> result.SetCanceled()\n                     | e -> result.SetException e   \n                result\n\n            let runRef (f : Step<unit,'a>) (ct : System.Threading.CancellationToken) =\n                let result = ref None\n                try\n                    let r = f.run () |> Cancellable.run ct\n                    result := r\n                with | e -> result := None\n                result\n\n        let (<*>) f g = compose f (Step.ofFun g) (fun a b -> a,b)\n        let ( **>) f g = compose (Step.ofFun (fun () -> f)) (Step.ofFun g) (fun a b -> a,b)\n        let ( *>) f g = compose f g (fun a b -> b)\n\n        module Test =\n            let test () =\n                let multiState =\n                    cancel { \n                            try \n                                Thread.Sleep 100; \n                                return 1 \n                            finally \n                                printfn \"do operation\", fun i -> printfn \"undo operation: %d\" i\n                        } \n                    **> (fun i  -> cancel { Thread.Sleep 100; return 1.0   } |> Cancellable.withCompensation (printfn \"undid: %f\")  ) \n                    <*> (fun d  -> cancel { Thread.Sleep 100; return \"abc\" } |> Cancellable.withCompensation (printfn \"undid: %s\")  )\n                \n                let cts = new System.Threading.CancellationTokenSource()\n                cts.CancelAfter(200)\n                let r = Step.runRef multiState cts.Token\n                Console.ReadLine() |> ignore\n                printfn \"%A\" r"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Monoid.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\n\ntype Monoid<'a> =\n    {\n        /// determines whether the given value is empty\n        misEmpty : 'a -> bool\n\n        /// the empty element\n        mempty : 'a\n\n        /// appends to values\n        mappend : 'a -> 'a -> 'a\n    }\n\ntype Traceable<'s, 'ops> =\n    {\n        /// the monoid instance for 'ops\n        tops : Monoid<'ops>\n\n        /// the empty state\n        tempty : 's\n\n        /// applies the given operations to the state and \n        /// returns the new state accompanied by (possibly) reduced ops (removing useless ops)\n        tapply : 's -> 'ops -> 's * 'ops\n\n        /// differentiates two states and returns the needed ops\n        tcompute : 's -> 's -> 'ops\n\n        /// determines whether or not a history should be pruned although it is still referntiable.\n        /// the first argument is the base-state for that history and the second argument is the number\n        /// of ops that would need to be applied.\n        /// when returning true the history implementation will discard the history and reproduce it on demand using\n        /// the above compute function.\n        tcollapse    : 's -> 'ops -> bool\n    }\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Native.fs",
    "content": "﻿namespace Aardvark.Base\n\n#nowarn \"9\"\n\nopen System\nopen System.Runtime.InteropServices\nopen FSharp.NativeInterop\n\n[<AutoOpen>]\nmodule NativeUtilities =\n\n    let private os = System.Environment.OSVersion\n\n    /// <summary>\n    /// MSVCRT wraps memory-functions provided by msvcrt.dll on windows systems.\n    /// </summary>\n    module internal MSVCRT =\n\n        [<DllImport(\"msvcrt.dll\", EntryPoint = \"memcpy\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern nativeint private memcpy_internal(nativeint dest, nativeint src, UIntPtr size);\n\n        [<DllImport(\"msvcrt.dll\", EntryPoint = \"memcmp\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern int private memcmp_internal(nativeint ptr1, nativeint ptr2, UIntPtr size);\n\n        [<DllImport(\"msvcrt.dll\", EntryPoint = \"memset\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern nativeint private memset_internal(nativeint ptr, int value, UIntPtr size);\n\n        [<DllImport(\"msvcrt.dll\", EntryPoint = \"memmove\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern nativeint private memmove_internal(nativeint dest, nativeint src, UIntPtr size);\n\n        let memcpy(target : nativeint, source : nativeint, size : unativeint) =\n            memcpy_internal(target, source, size) |> ignore\n\n        let memcmp(ptr1 : nativeint, ptr2 : nativeint, size : unativeint) =\n            memcmp_internal(ptr1, ptr2, size)\n\n        let memset(ptr : nativeint, value : int, size : unativeint) =\n            memset_internal(ptr, value, size) |> ignore\n\n        let memmove(target : nativeint, source : nativeint, size : unativeint) =\n            memmove_internal(target, source, size) |> ignore\n\n    /// <summary>\n    /// LibC wraps memory-functions provided by libc on linux systems.\n    /// </summary>\n    module internal LibC =\n\n        [<DllImport(\"libc\", EntryPoint = \"memcpy\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern nativeint private memcpy_internal(nativeint dest, nativeint src, UIntPtr size);\n\n        [<DllImport(\"libc\", EntryPoint = \"memcmp\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern int private memcmp_internal(nativeint ptr1, nativeint ptr2, UIntPtr size);\n\n        [<DllImport(\"libc\", EntryPoint = \"memset\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern nativeint private memset_internal(nativeint ptr, int value, UIntPtr size);\n\n        [<DllImport(\"libc\", EntryPoint = \"memmove\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern nativeint private memmove_internal(nativeint dest, nativeint src, UIntPtr size);\n\n        [<DllImport(\"libc\", EntryPoint = \"uname\", CallingConvention = CallingConvention.Cdecl, SetLastError = false)>]\n        extern int private uname_intern(nativeint buf);\n\n        let mutable osname = null\n        let uname() =\n            if isNull osname then\n                let ptr : nativeptr<byte> = NativePtr.stackalloc 8192\n                if uname_intern(NativePtr.toNativeInt ptr) = 0 then\n                    osname <- Marshal.PtrToStringAnsi(NativePtr.toNativeInt ptr)\n                else\n                    failwith \"could not get os-name\"\n            osname\n\n        let memcpy(target : nativeint, source : nativeint, size : unativeint) =\n            memcpy_internal(target, source, size) |> ignore\n\n        let memcmp(ptr1 : nativeint, ptr2 : nativeint, size : unativeint) =\n            memcmp_internal(ptr1, ptr2, size)\n\n        let memset(ptr : nativeint, value : int, size : unativeint) =\n            memset_internal(ptr, value, size) |> ignore\n\n        let memmove(target : nativeint, source : nativeint, size : unativeint) =\n            memmove_internal(target, source, size) |> ignore\n\n    [<AutoOpen>]\n    module PlatformStuff =\n\n        let (|Windows|Linux|Mac|) (p : System.OperatingSystem) =\n            match p.Platform with\n                | System.PlatformID.Unix ->\n                    if LibC.uname() = \"Darwin\" then Mac\n                    else Linux\n                | System.PlatformID.MacOSX -> Mac\n                | _ -> Windows\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module NativeInt =\n        let memcpy (src : nativeint) (dst : nativeint) (size : int) =\n            match os with\n                | Windows -> MSVCRT.memcpy(dst, src, unativeint size)\n                | _ -> LibC.memcpy(dst, src, unativeint size)\n\n        let memmove (src : nativeint) (dst : nativeint) (size : int) =\n            match os with\n                | Windows -> MSVCRT.memmove(dst, src, unativeint size)\n                | _ -> LibC.memmove(dst, src, unativeint size)\n\n        let memset (dst : nativeint) (value : int) (size : int) =\n            match os with\n                | Windows -> MSVCRT.memset(dst, value, unativeint size)\n                | _ -> LibC.memset(dst, value, unativeint size)\n\n        let memcmp (src : nativeint) (dst : nativeint) (size : int) =\n            match os with\n                | Windows -> MSVCRT.memcmp(dst, src, unativeint size)\n                | _ -> LibC.memcmp(dst, src, unativeint size)\n\n        let inline read<'a when 'a : unmanaged> (ptr : nativeint) =\n            NativePtr.read (NativePtr.ofNativeInt<'a> ptr)\n\n        let inline write<'a when 'a : unmanaged> (ptr : nativeint) (value : 'a) =\n            NativePtr.write (NativePtr.ofNativeInt<'a> ptr)  value\n\n        let inline get<'a when 'a : unmanaged> (ptr : nativeint) (index : int) =\n            NativePtr.get (NativePtr.ofNativeInt<'a> ptr) index\n\n        let inline set<'a when 'a : unmanaged> (ptr : nativeint) (index : int) (value : 'a)=\n            NativePtr.set (NativePtr.ofNativeInt<'a> ptr) index value\n\n        /// Pins the given object and invokes the action with its address.\n        let inline pin ([<InlineIfLambda>] action: nativeint -> 'T) (value: obj) =\n            let gc = GCHandle.Alloc(value, GCHandleType.Pinned)\n            try action <| gc.AddrOfPinnedObject()\n            finally gc.Free()\n\n    type Marshal with\n        static member Copy(source : nativeint, destination : nativeint, length : unativeint) =\n            match os with\n                | Windows -> MSVCRT.memcpy(destination, source, length)\n                | _ -> LibC.memcpy(destination, source, length)\n\n        static member Move(source : nativeint, destination : nativeint, length : unativeint) =\n            match os with\n                | Windows -> MSVCRT.memmove(destination, source, length)\n                | _ -> LibC.memmove(destination, source, length)\n\n        static member Set(memory : nativeint, value : int, length : unativeint) =\n            match os with\n                | Windows -> MSVCRT.memset(memory, value, length)\n                | _ -> LibC.memset(memory, value, length)\n\n        static member Compare(source : nativeint, destination : nativeint, length : unativeint) =\n            match os with\n                | Windows -> MSVCRT.memcmp(destination, source, length)\n                | _ -> LibC.memcmp(destination, source, length)\n\n\n        static member Copy(source : nativeint, destination : nativeint, length : int) =\n            Marshal.Copy(source, destination, unativeint length)\n\n        static member Move(source : nativeint, destination : nativeint, length : int) =\n            Marshal.Move(source, destination, unativeint length)\n\n        static member Set(memory : nativeint, value : int, length : int) =\n            Marshal.Set(memory, value, unativeint length)\n\n        static member Compare(source : nativeint, destination : nativeint, length : int) =\n            Marshal.Compare(source, destination, unativeint length)\n\n\n        static member inline Copy(source : nativeint, destination : nativeint, length : 'a) =\n            Marshal.Copy(source, destination, unativeint length)\n\n        static member inline Move(source : nativeint, destination : nativeint, length : 'a) =\n            Marshal.Move(source, destination, unativeint length)\n\n        static member inline Set(memory : nativeint, value : int, length : 'a) =\n            Marshal.Set(memory, value, unativeint length)\n\n        static member inline Compare(source : nativeint, destination : nativeint, length : 'a) =\n            Marshal.Compare(source, destination, unativeint length)\n\n    [<Obsolete(\"Use NativeInt.pin instead.\")>]\n    let pinned (a : obj) f =\n        NativeInt.pin f a\n\n    [<Obsolete(\"Use NativePtr.pin instead.\")>]\n    let inline pin ([<InlineIfLambda>] f: nativeptr<'T> -> 'U) (value: 'T) =\n        NativePtr.pin f value\n\n    [<Obsolete(\"Use NativePtr.pinArr instead.\")>]\n    let inline pinArr ([<InlineIfLambda>] f: nativeptr<'T> -> 'U) (array: 'T[])  =\n        NativePtr.pinArr f array\n\n    /// Utility to pin values with IDisposable semantics.\n    type PinnedValue private (value: obj, length: int) =\n        let gc = GCHandle.Alloc(value, GCHandleType.Pinned)\n        let address = gc.AddrOfPinnedObject()\n\n        new (value: obj) =\n            let length = match value with | :? Array as array -> array.Length | _ -> 1\n            new PinnedValue(value, length)\n\n        new (array: Array) =\n            new PinnedValue(array, array.Length)\n\n        /// The address of the pinned value.\n        member _.Address = address\n\n        /// The number of elements if the pinned value is an array, 1 otherwise.\n        member _.Length = length\n\n        member _.Dispose() = gc.Free()\n\n        interface IDisposable with\n            member this.Dispose() = this.Dispose()\n\n    /// Utility to pin values with IDisposable semantics.\n    type PinnedValue<'T when 'T : unmanaged> =\n        inherit PinnedValue\n        new (value: 'T) = { inherit PinnedValue(value :> obj) }\n        new (array: 'T[]) = { inherit PinnedValue(array :> Array) }\n\n        /// The pointer of the pinned value.\n        member inline this.Pointer : nativeptr<'T> = NativePtr.ofNativeInt this.Address\n\n[<AutoOpen>]\nmodule MarshalDelegateExtensions =\n    open System.Collections.Concurrent\n\n    let private pinnedDelegates = ConcurrentDictionary<Delegate, nativeint>()\n    type PinnedDelegate internal(d : Delegate, ptr : nativeint) =\n        member x.Pointer = ptr\n        member x.Dispose() = pinnedDelegates.TryRemove d |> ignore\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n    type Marshal with\n        static member PinDelegate(d : Delegate) =\n            let ptr = pinnedDelegates.GetOrAdd(d, fun _ -> Marshal.GetFunctionPointerForDelegate d)\n            new PinnedDelegate(d, ptr)\n\n        static member PinFunction(f : 'a -> 'b) =\n            Marshal.PinDelegate(Func<'a, 'b>(f))\n\n        static member PinFunction(f : 'a -> 'b -> 'c) =\n            Marshal.PinDelegate(Func<'a, 'b, 'c>(f))\n\n        static member PinFunction(f : 'a -> 'b -> 'c -> 'd) =\n            Marshal.PinDelegate(Func<'a, 'b, 'c, 'd>(f))"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Pickler/AdaptivePicklers.fs",
    "content": "﻿namespace Aardvark.Base.Picklers\n\nopen Aardvark.Base\nopen MBrace.FsPickler\nopen MBrace.FsPickler.Combinators\nopen FSharp.Data.Traceable\nopen FSharp.Data.Adaptive\n\n\n[<CustomPicklerProvider>]\ntype AdaptivePicklers() =\n    static member HashSet (r : IPicklerResolver) : Pickler<HashSet<'a>> =\n        let pInt = r.Resolve<int>()\n        let pValue = r.Resolve<'a>()\n        let pArray = Pickler.array pValue\n        let read (rs : ReadState) =\n            let _cnt = pInt.Read rs \"count\"\n            let elements = pArray.Read rs \"elements\"\n            HashSet<'a>.OfArray elements\n\n        let write (ws : WriteState) (s : HashSet<'a>) =\n            pInt.Write ws \"count\" s.Count\n            pArray.Write ws \"elements\" (s.ToArray())\n\n        let clone (cs : CloneState) (m : HashSet<'a>) =\n            m |> HashSet.map (pValue.Clone cs)\n\n        let accept (vs : VisitState) (m : HashSet<'a>) =\n            for v in m do pValue.Accept vs v\n            \n        Pickler.FromPrimitives(read, write, clone, accept)\n\n    static member CountingHashSet (r : IPicklerResolver) : Pickler<CountingHashSet<'a>> =\n        let pInt = r.Resolve<int>()\n        let pValue = r.Resolve<'a>()\n        let pArray = Pickler.array (Pickler.pair pValue pInt)\n\n        let read (rs : ReadState) =\n            let _cnt = pInt.Read rs \"count\"\n            let elements = pArray.Read rs \"elements\"\n            HashMap.ofArray elements \n            |> CountingHashSet.ofHashMap\n\n        let write (ws : WriteState) (s : CountingHashSet<'a>) =\n            pInt.Write ws \"count\" s.Count\n            let elements = s |> CountingHashSet.toHashMap |> HashMap.toArray\n            pArray.Write ws \"elements\" elements\n\n        let clone (cs : CloneState) (m : CountingHashSet<'a>) =\n            m |> CountingHashSet.map (pValue.Clone cs)\n\n        let accept (vs : VisitState) (m : CountingHashSet<'a>) =\n            for v in m do pValue.Accept vs v\n            \n        Pickler.FromPrimitives(read, write, clone, accept)\n\n    static member HashSetDelta (r : IPicklerResolver) : Pickler<HashSetDelta<'a>> =\n        let pInt = r.Resolve<int>()\n        let pValue = r.Resolve<'a>()\n        let pArray = Pickler.array (Pickler.pair pValue pInt)\n\n        let read (rs : ReadState) =\n            let _cnt = pInt.Read rs \"count\"\n            let elements = pArray.Read rs \"elements\"\n            HashMap.ofArray elements \n            |> HashSetDelta.ofHashMap\n\n        let write (ws : WriteState) (s : HashSetDelta<'a>) =\n            pInt.Write ws \"count\" s.Count\n            let elements = s |> HashSetDelta.toHashMap |> HashMap.toArray\n            pArray.Write ws \"elements\" elements\n\n        let clone (cs : CloneState) (m : HashSetDelta<'a>) =\n            m |> HashSetDelta.map (SetOperation.map (pValue.Clone cs))\n\n        let accept (vs : VisitState) (m : HashSetDelta<'a>) =\n            for v in m do \n                pValue.Accept vs v.Value\n            \n        Pickler.FromPrimitives(read, write, clone, accept)\n\n    static member IndexList (r : IPicklerResolver) : Pickler<IndexList<'a>> =\n        let pInt = r.Resolve<int>()\n        let pValue = r.Resolve<'a>()\n        let pArray = Pickler.array pValue\n\n        let read (rs : ReadState) =\n            let _cnt = pInt.Read rs \"count\"\n            let elements = pArray.Read rs \"elements\"\n            IndexList.ofArray elements\n\n        let write (ws : WriteState) (s : IndexList<'a>) =\n            pInt.Write ws \"count\" s.Count\n            pArray.Write ws \"elements\" (IndexList.toArray s)\n\n        let clone (cs : CloneState) (s : IndexList<'a>) =\n            s.Map(fun _ v -> pValue.Clone cs v)\n\n        let accept (vs : VisitState) (s : IndexList<'a>) =\n            s |> Seq.iter (pValue.Accept vs)\n\n        Pickler.FromPrimitives(read, write, clone, accept)\n\n    static member IndexListDelta (r : IPicklerResolver) : Pickler<IndexListDelta<'a>> =\n        failwith \"cannot pickle IndexListDelta\"\n\n    static member HashMap (r : IPicklerResolver) : Pickler<HashMap<'k, 'v>> =\n        let pInt = r.Resolve<int>()\n        let pKey = r.Resolve<'k>()\n        let pValue = r.Resolve<'v>()\n        let pArray = Pickler.array (Pickler.pair pKey pValue)\n\n        let read (rs : ReadState) =\n            let _cnt = pInt.Read rs \"count\"\n            let arr = pArray.Read rs \"items\"\n            HashMap<'k, 'v>.OfArray arr\n\n        let write (ws : WriteState) (m : HashMap<'k, 'v>) =\n            pInt.Write ws \"count\" m.Count\n            pArray.Write ws \"items\" (m.ToArray())\n\n        let clone (cs : CloneState) (m : HashMap<'k, 'v>) =\n            m.ToSeqV()\n            |> Seq.map (fun struct(k,v) -> struct(pKey.Clone cs k, pValue.Clone cs v))\n            |> HashMap.ofSeqV\n\n        let accept (vs : VisitState) (m : HashMap<'k, 'v>) =\n            for (k,v) in m do pKey.Accept vs k; pValue.Accept vs v\n\n        Pickler.FromPrimitives(read, write, clone, accept)\n\n    static member HashMapDelta (r : IPicklerResolver) : Pickler<HashMapDelta<'k, 'v>> =\n        let pInt = r.Resolve<int>()\n        let pKey = r.Resolve<'k>()\n        let pValue = r.Resolve<ElementOperation<'v>>()\n        let pArray = Pickler.array (Pickler.pair pKey pValue)\n\n        let read (rs : ReadState) =\n            let _cnt = pInt.Read rs \"count\"\n            let arr = pArray.Read rs \"items\"\n            HashMapDelta.ofArray arr\n\n        let write (ws : WriteState) (m : HashMapDelta<'k, 'v>) =\n            pInt.Write ws \"count\" m.Count\n            pArray.Write ws \"items\" (HashMapDelta.toArray m)\n\n        let clone (cs : CloneState) (m : HashMapDelta<'k, 'v>) =\n            (HashMapDelta.toHashMap m).ToSeqV()\n            |> Seq.map (fun struct(k,v) -> struct(pKey.Clone cs k, pValue.Clone cs v))\n            |> HashMap.ofSeqV\n            |> HashMapDelta.ofHashMap\n\n        let accept (vs : VisitState) (m : HashMapDelta<'k, 'v>) =\n            for (k,v) in m do pKey.Accept vs k; pValue.Accept vs v\n\n        Pickler.FromPrimitives(read, write, clone, accept)\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Pickler/FsPicklerExtensions.fs",
    "content": "﻿namespace MBrace.FsPickler\n\nopen System\nopen Aardvark.Base\n\nopen FSharp.Data.Adaptive\nopen FSharp.Data.Traceable\n\ntype CustomPicklerProviderAttribute() =\n    inherit Attribute()\n\n[<AutoOpen>]\nmodule PicklerExtensions =\n    open System.Reflection\n    open System.Reflection.Emit\n    open MBrace.FsPickler\n\n\n    let private tryUnifyTypes (decl : Type) (real : Type) =\n        let assignment = System.Collections.Generic.Dictionary<Type, Type>()\n\n        let rec recurse (decl : Type) (real : Type) =\n            if decl = real then\n                true\n\n            elif decl.IsGenericParameter then\n                match assignment.TryGetValue decl with\n                    | (true, old) ->\n                        if old.IsAssignableFrom real then \n                            true\n\n                        elif real.IsAssignableFrom old then\n                            assignment.[decl] <- real\n                            true\n\n                        else \n                            false\n                    | _ ->\n                        assignment.[decl] <- real\n                        true\n            \n            elif decl.IsArray then\n                if real.IsArray then\n                    let de = decl.GetElementType()\n                    let re = real.GetElementType()\n                    recurse de re\n                else\n                    false\n\n            elif decl.ContainsGenericParameters then\n                let dgen = decl.GetGenericTypeDefinition()\n                let rgen = \n                    if real.IsGenericType then real.GetGenericTypeDefinition()\n                    else real\n\n                if dgen = rgen then\n                    let dargs = decl.GetGenericArguments()\n                    let rargs = real.GetGenericArguments()\n                    Array.forall2 recurse dargs rargs\n\n                elif dgen.IsInterface then\n                    let rface = real.GetInterface(dgen.FullName)\n                    if isNull rface then\n                        false\n                    else\n                        recurse decl rface\n\n                elif not (isNull real.BaseType) then\n                    recurse decl real.BaseType\n\n                else\n                    false\n\n            elif decl.IsAssignableFrom real then\n                true\n\n            else\n                false\n\n\n        if recurse decl real then\n            Some (assignment |> Dictionary.toSeq |> HashMap.ofSeq)\n        else\n            None\n\n    type private PicklerRegistry(types : list<Type>, fallback : ICustomPicklerRegistry) =\n\n        let picklerGen = typedefof<Pickler<_>>\n        let allMeths = types |> List.collect (fun t -> t.GetMethods(BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic) |> Array.toList)\n\n        let upcastToPicker (mi : MethodInfo) =\n            let meth = \n                DynamicMethod(\n                    sprintf \"upcasted.%s\" mi.Name,\n                    MethodAttributes.Public ||| MethodAttributes.Static,\n                    CallingConventions.Standard,\n                    typeof<Pickler>,\n                    [| typeof<IPicklerResolver> |],\n                    typeof<obj>,\n                    true\n                )\n            let il = meth.GetILGenerator()\n\n            il.Emit(OpCodes.Ldarg_0)\n            il.Emit(OpCodes.Tailcall)\n            il.EmitCall(OpCodes.Call, mi, null)\n            il.Emit(OpCodes.Ret)\n            let func = \n                meth.CreateDelegate(typeof<Func<IPicklerResolver, Pickler>>) \n                    |> unbox<Func<IPicklerResolver, Pickler>>        \n            fun (r : IPicklerResolver) -> func.Invoke(r)\n\n        let genericThings = \n            allMeths\n            |> List.filter (fun mi -> mi.GetGenericArguments().Length > 0)\n            |> List.choose (fun mi ->\n                let ret = mi.ReturnType\n                if ret.IsGenericType && ret.GetGenericTypeDefinition() = picklerGen && mi.GetParameters().Length = 1 then\n                    let pickledType = ret.GetGenericArguments().[0]\n\n                    let tryInstantiate (t : Type) =\n                        match tryUnifyTypes pickledType t with\n                            | Some ass ->\n                                let targs = mi.GetGenericArguments() |> Array.map (fun a -> ass.[a])\n                                let mi = mi.MakeGenericMethod targs\n                                Some (upcastToPicker mi)\n                                            \n                            | None ->\n                                None\n                                        \n\n                    Some tryInstantiate\n                else\n                    None\n            )\n\n        let nonGenericThings = \n            allMeths\n            |> List.filter (fun mi -> mi.GetGenericArguments().Length = 0)\n            |> List.choose (fun mi ->\n                let ret = mi.ReturnType\n                if ret.IsGenericType && ret.GetGenericTypeDefinition() = picklerGen && mi.GetParameters().Length = 1 then\n                    let pickledType = ret.GetGenericArguments().[0]\n\n                    let create = upcastToPicker mi\n                    Some (pickledType, create)\n\n                else\n                    None\n            )\n            |> Dictionary.ofList\n   \n        member x.GetRegistration(t : Type) : CustomPicklerRegistration =\n            if t.IsGenericType then\n                match genericThings |> List.tryPick (fun a -> a t) with\n                | Some r -> \n                    CustomPicklerRegistration.CustomPickler r\n                | None ->\n                    match nonGenericThings.TryGetValue t with   \n                    | (true, r) -> CustomPicklerRegistration.CustomPickler r\n                    | _ -> fallback.GetRegistration t\n            else\n                match nonGenericThings.TryGetValue t with   \n                | (true, r) -> CustomPicklerRegistration.CustomPickler r\n                | _ -> fallback.GetRegistration t\n\n        interface ICustomPicklerRegistry with\n            member x.GetRegistration(t : Type) = x.GetRegistration t\n\n    let private installCustomPicklers(types : list<Type>) =\n        let instance = MBrace.FsPickler.PicklerCache.Instance\n        lock instance (fun () ->\n            let t = instance.GetType()\n\n            let registryField =\n                t.GetFields(BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Instance)\n                |> Array.tryFind (fun f -> f.FieldType = typeof<ICustomPicklerRegistry>)\n\n            match registryField with\n            | Some field ->\n                let old = \n                    match field.GetValue(instance) with\n                    | null -> EmptyPicklerRegistry() :> ICustomPicklerRegistry\n                    | :? ICustomPicklerRegistry as o -> o\n                    | _ -> EmptyPicklerRegistry() :> ICustomPicklerRegistry\n                let reg = PicklerRegistry(types, old) :> ICustomPicklerRegistry\n                field.SetValue(instance, reg)\n            | None ->\n                Log.warn \"cannot register custom picklers\"\n        )\n\n    type FsPickler with\n        static member AddCustomPicklers (types : list<Type>) =\n            installCustomPicklers types\n\nmodule CustomPicklerProvider =\n    open MBrace.FsPickler\n\n    let mutable private initialized = false\n\n    [<OnAardvarkInit>]\n    let init() =\n        if not initialized then\n            initialized <- true\n            let custom = \n                Introspection.GetAllTypesWithAttribute<CustomPicklerProviderAttribute>()\n                |> Seq.map (fun struct (t,_) -> t)\n                |> Seq.filter (not << isNull)\n                |> Seq.toList\n                \n            match custom with\n            | [] -> \n                Report.Line(4, \"no custom picklers found\")\n            | _ -> \n                for c in custom do\n                    Report.Line(4, \"installing pickler: {0}\", c)\n                FsPickler.AddCustomPicklers custom\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/PrimitiveValueConverter.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.Collections.Generic\nopen System.Collections.Concurrent\nopen Aardvark.Base\nopen System.Reflection\nopen System.Runtime.InteropServices\nopen Microsoft.FSharp.Reflection\n\nmodule PrimitiveValueConverter =\n\n    /// Exception thrown when an invalid conversion is requested.\n    type InvalidConversionException =\n        class\n            inherit Exception\n\n            /// The source type of the requested conversion.\n            val public Source : Type\n\n            /// The target type of the requested conversion.\n            val public Target : Type\n\n            new() = { inherit Exception(); Source = null; Target = null }\n            new(message : string) = { inherit Exception(message); Source = null; Target = null }\n            new(message : string, inner : Exception) = { inherit Exception(message, inner); Source = null; Target = null}\n\n            new(message : string, source : Type, target : Type) = { inherit Exception(message); Source = source; Target = target }\n            new(message : string, source : Type, target : Type, inner : Exception) = { inherit Exception(message, inner); Source = source; Target = target}\n        end\n\n    let private integralConversions =\n        [\n            // int8 -> other scalars\n            ( fun (i : int8)        -> int8 i ) :> obj\n            ( fun (i : int8)        -> int16 i ) :> obj\n            ( fun (i : int8)        -> int32 i ) :> obj\n            ( fun (i : int8)        -> int64 i ) :> obj\n            ( fun (i : int8)        -> uint8 i ) :> obj\n            ( fun (i : int8)        -> uint16 i ) :> obj\n            ( fun (i : int8)        -> uint32 i ) :> obj\n            ( fun (i : int8)        -> uint64 i ) :> obj\n            ( fun (i : int8)        -> float32 i ) :> obj\n            ( fun (i : int8)        -> float i ) :> obj\n\n            // int16 -> other scalars\n            ( fun (i : int16)       -> int8 i ) :> obj\n            ( fun (i : int16)       -> int16 i ) :> obj\n            ( fun (i : int16)       -> int32 i ) :> obj\n            ( fun (i : int16)       -> int64 i ) :> obj\n            ( fun (i : int16)       -> uint8 i ) :> obj\n            ( fun (i : int16)       -> uint16 i ) :> obj\n            ( fun (i : int16)       -> uint32 i ) :> obj\n            ( fun (i : int16)       -> uint64 i ) :> obj\n            ( fun (i : int16)       -> float32 i ) :> obj\n            ( fun (i : int16)       -> float i ) :> obj\n\n            // int32 -> other scalars\n            ( fun (i : int32)       -> int8 i ) :> obj\n            ( fun (i : int32)       -> int16 i ) :> obj\n            ( fun (i : int32)       -> int32 i ) :> obj\n            ( fun (i : int32)       -> int64 i ) :> obj\n            ( fun (i : int32)       -> uint8 i ) :> obj\n            ( fun (i : int32)       -> uint16 i ) :> obj\n            ( fun (i : int32)       -> uint32 i ) :> obj\n            ( fun (i : int32)       -> uint64 i ) :> obj\n            ( fun (i : int32)       -> float32 i ) :> obj\n            ( fun (i : int32)       -> float i ) :> obj\n\n            // int64 -> other scalars\n            ( fun (i : int64)       -> int8 i ) :> obj\n            ( fun (i : int64)       -> int16 i ) :> obj\n            ( fun (i : int64)       -> int32 i ) :> obj\n            ( fun (i : int64)       -> int64 i ) :> obj\n            ( fun (i : int64)       -> uint8 i ) :> obj\n            ( fun (i : int64)       -> uint16 i ) :> obj\n            ( fun (i : int64)       -> uint32 i ) :> obj\n            ( fun (i : int64)       -> uint64 i ) :> obj\n            ( fun (i : int64)       -> float32 i ) :> obj\n            ( fun (i : int64)       -> float i ) :> obj\n\n            // uint8 -> other scalars\n            ( fun (i : uint8)       -> int8 i ) :> obj\n            ( fun (i : uint8)       -> int16 i ) :> obj\n            ( fun (i : uint8)       -> int32 i ) :> obj\n            ( fun (i : uint8)       -> int64 i ) :> obj\n            ( fun (i : uint8)       -> uint8 i ) :> obj\n            ( fun (i : uint8)       -> uint16 i ) :> obj\n            ( fun (i : uint8)       -> uint32 i ) :> obj\n            ( fun (i : uint8)       -> uint64 i ) :> obj\n            ( fun (i : uint8)       -> float32 i ) :> obj\n            ( fun (i : uint8)       -> float i ) :> obj\n\n            // uint16 -> other scalars\n            ( fun (i : uint16)      -> int8 i ) :> obj\n            ( fun (i : uint16)      -> int16 i ) :> obj\n            ( fun (i : uint16)      -> int32 i ) :> obj\n            ( fun (i : uint16)      -> int64 i ) :> obj\n            ( fun (i : uint16)      -> uint8 i ) :> obj\n            ( fun (i : uint16)      -> uint16 i ) :> obj\n            ( fun (i : uint16)      -> uint32 i ) :> obj\n            ( fun (i : uint16)      -> uint64 i ) :> obj\n            ( fun (i : uint16)      -> float32 i ) :> obj\n            ( fun (i : uint16)      -> float i ) :> obj\n\n\n            // uint32 -> other scalars\n            ( fun (i : uint32)      -> int8 i ) :> obj\n            ( fun (i : uint32)      -> int16 i ) :> obj\n            ( fun (i : uint32)      -> int32 i ) :> obj\n            ( fun (i : uint32)      -> int64 i ) :> obj\n            ( fun (i : uint32)      -> uint8 i ) :> obj\n            ( fun (i : uint32)      -> uint16 i ) :> obj\n            ( fun (i : uint32)      -> uint32 i ) :> obj\n            ( fun (i : uint32)      -> uint64 i ) :> obj\n            ( fun (i : uint32)      -> float32 i ) :> obj\n            ( fun (i : uint32)      -> float i ) :> obj\n\n            // uint64 -> other scalars\n            ( fun (i : uint64)      -> int8 i ) :> obj\n            ( fun (i : uint64)      -> int16 i ) :> obj\n            ( fun (i : uint64)      -> int32 i ) :> obj\n            ( fun (i : uint64)      -> int64 i ) :> obj\n            ( fun (i : uint64)      -> uint8 i ) :> obj\n            ( fun (i : uint64)      -> uint16 i ) :> obj\n            ( fun (i : uint64)      -> uint32 i ) :> obj\n            ( fun (i : uint64)      -> uint64 i ) :> obj\n            ( fun (i : uint64)      -> float32 i ) :> obj\n            ( fun (i : uint64)      -> float i ) :> obj\n\n\n            // nativeint -> other scalars\n            ( fun (i : nativeint)   -> int8 i ) :> obj\n            ( fun (i : nativeint)   -> int16 i ) :> obj\n            ( fun (i : nativeint)   -> int32 i ) :> obj\n            ( fun (i : nativeint)   -> int64 i ) :> obj\n            ( fun (i : nativeint)   -> uint8 i ) :> obj\n            ( fun (i : nativeint)   -> uint16 i ) :> obj\n            ( fun (i : nativeint)   -> uint32 i ) :> obj\n            ( fun (i : nativeint)   -> uint64 i ) :> obj\n            ( fun (i : nativeint)   -> float32 i ) :> obj\n            ( fun (i : nativeint)   -> float i ) :> obj\n\n            // unativeint -> other scalars\n            ( fun (i : unativeint)  -> int8 i ) :> obj\n            ( fun (i : unativeint)  -> int16 i ) :> obj\n            ( fun (i : unativeint)  -> int32 i ) :> obj\n            ( fun (i : unativeint)  -> int64 i ) :> obj\n            ( fun (i : unativeint)  -> uint8 i ) :> obj\n            ( fun (i : unativeint)  -> uint16 i ) :> obj\n            ( fun (i : unativeint)  -> uint32 i ) :> obj\n            ( fun (i : unativeint)  -> uint64 i ) :> obj\n            ( fun (i : unativeint)  -> float32 i ) :> obj\n            ( fun (i : unativeint)  -> float i ) :> obj\n        ]\n\n    let private fractionalConversions =\n        [\n            ( fun (b : float32)        -> float32 b ) :> obj\n            ( fun (b : float32)        -> float b ) :> obj\n\n            ( fun (b : float)          -> float32 b ) :> obj\n            ( fun (b : float)          -> float b ) :> obj\n\n            ( fun (b : decimal)        -> float32 b ) :> obj\n            ( fun (b : decimal)        -> float b ) :> obj\n        ]\n\n    let private booleanConversions =\n        [\n            ( fun (b : bool)        -> if b then 1uy else 0uy ) :> obj\n            ( fun (b : bool)        -> if b then 1y else 0y ) :> obj\n            ( fun (b : bool)        -> if b then 1us else 0us ) :> obj\n            ( fun (b : bool)        -> if b then 1s else 0s ) :> obj\n            ( fun (b : bool)        -> if b then 1u else 0u ) :> obj\n            ( fun (b : bool)        -> if b then 1 else 0 ) :> obj\n            ( fun (b : bool)        -> if b then 1UL else 0UL ) :> obj\n            ( fun (b : bool)        -> if b then 1L else 0L ) :> obj\n\n            ( fun (b : bool)        -> if b then 1.0f else 0.0f ) :> obj\n            ( fun (b : bool)        -> if b then 1.0  else 0.0 ) :> obj\n        ]\n\n\n    let private vector2Conversions =\n        [\n            // V2i -> other vectors\n            ( fun (b : V2i)        -> b ) :> obj\n            ( fun (b : V2i)        -> V2ui b ) :> obj\n            ( fun (b : V2i)        -> V2l b ) :> obj\n            ( fun (b : V2i)        -> V2f b ) :> obj\n            ( fun (b : V2i)        -> V2d b ) :> obj\n            ( fun (b : V2i)        -> V3i(b.X, b.Y, 0) ) :> obj\n            ( fun (b : V2i)        -> V3ui(uint b.X, uint b.Y, 0u) ) :> obj\n            ( fun (b : V2i)        -> V3l(int64 b.X, int64 b.Y,0L) ) :> obj\n            ( fun (b : V2i)        -> V3f(float32 b.X, float32 b.Y, 0.0f) ) :> obj\n            ( fun (b : V2i)        -> V3d(float b.X, float b.Y,0.0) ) :> obj\n            ( fun (b : V2i)        -> V4i(b.X, b.Y, 0, 0) ) :> obj\n            ( fun (b : V2i)        -> V4ui(uint b.X, uint b.Y, 0u, 0u) ) :> obj\n            ( fun (b : V2i)        -> V4l(int64 b.X, int64 b.Y, 0L, 0L) ) :> obj\n            ( fun (b : V2i)        -> V4f(float32 b.X, float32 b.Y, 0.0f, 0.0f) ) :> obj\n            ( fun (b : V2i)        -> V4d(float b.X, float b.Y, 0.0, 0.0) ) :> obj\n\n            // V2ui -> other vectors\n            ( fun (b : V2ui)        -> V2i b ) :> obj\n            ( fun (b : V2ui)        -> b ) :> obj\n            ( fun (b : V2ui)        -> V2l b ) :> obj\n            ( fun (b : V2ui)        -> V2f b ) :> obj\n            ( fun (b : V2ui)        -> V2d b ) :> obj\n            ( fun (b : V2ui)        -> V3i(int b.X, int b.Y, 0) ) :> obj\n            ( fun (b : V2ui)        -> V3ui(b.X, b.Y, 0u) ) :> obj\n            ( fun (b : V2ui)        -> V3l(int64 b.X, int64 b.Y,0L) ) :> obj\n            ( fun (b : V2ui)        -> V3f(float32 b.X, float32 b.Y, 0.0f) ) :> obj\n            ( fun (b : V2ui)        -> V3d(float b.X, float b.Y,0.0) ) :> obj\n            ( fun (b : V2ui)        -> V4i(int b.X, int b.Y, 0, 0) ) :> obj\n            ( fun (b : V2ui)        -> V4ui(b.X, b.Y, 0u, 0u) ) :> obj\n            ( fun (b : V2ui)        -> V4l(int64 b.X, int64 b.Y, 0L, 0L) ) :> obj\n            ( fun (b : V2ui)        -> V4f(float32 b.X, float32 b.Y, 0.0f, 0.0f) ) :> obj\n            ( fun (b : V2ui)        -> V4d(float b.X, float b.Y, 0.0, 0.0) ) :> obj\n\n            // V2l -> other vectors\n            ( fun (b : V2l)        -> V2i b ) :> obj\n            ( fun (b : V2l)        -> V2ui b ) :> obj\n            ( fun (b : V2l)        -> b ) :> obj\n            ( fun (b : V2l)        -> V2f b ) :> obj\n            ( fun (b : V2l)        -> V2d b ) :> obj\n            ( fun (b : V2l)        -> V3i(int b.X, int b.Y, 0) ) :> obj\n            ( fun (b : V2l)        -> V3ui(uint b.X, uint b.Y, 0u) ) :> obj\n            ( fun (b : V2l)        -> V3l(b.X, b.Y,0L) ) :> obj\n            ( fun (b : V2l)        -> V3f(float32 b.X, float32 b.Y, 0.0f) ) :> obj\n            ( fun (b : V2l)        -> V3d(float b.X, float b.Y,0.0) ) :> obj\n            ( fun (b : V2l)        -> V4i(int b.X, int b.Y, 0, 0) ) :> obj\n            ( fun (b : V2l)        -> V4ui(uint b.X, uint b.Y, 0u, 0u) ) :> obj\n            ( fun (b : V2l)        -> V4l(b.X, b.Y, 0L, 0L) ) :> obj\n            ( fun (b : V2l)        -> V4f(float32 b.X, float32 b.Y, 0.0f, 0.0f) ) :> obj\n            ( fun (b : V2l)        -> V4d(float b.X, float b.Y, 0.0, 0.0) ) :> obj\n\n            // V2f -> other vectors\n            ( fun (b : V2f)        -> V2i b ) :> obj\n            ( fun (b : V2f)        -> V2ui b ) :> obj\n            ( fun (b : V2f)        -> V2l b ) :> obj\n            ( fun (b : V2f)        -> b ) :> obj\n            ( fun (b : V2f)        -> V2d b ) :> obj\n            ( fun (b : V2f)        -> V3i(int b.X, int b.Y, 0) ) :> obj\n            ( fun (b : V2f)        -> V3ui(uint b.X, uint b.Y, 0u) ) :> obj\n            ( fun (b : V2f)        -> V3l(int64 b.X, int64 b.Y,0L) ) :> obj\n            ( fun (b : V2f)        -> V3f(b.X, b.Y, 0.0f) ) :> obj\n            ( fun (b : V2f)        -> V3d(float b.X, float b.Y, 0.0) ) :> obj\n            ( fun (b : V2f)        -> V4i(int b.X, int b.Y, 0, 0) ) :> obj\n            ( fun (b : V2f)        -> V4ui(uint b.X, uint b.Y, 0u, 0u) ) :> obj\n            ( fun (b : V2f)        -> V4l(int64 b.X, int64 b.Y, 0L, 0L) ) :> obj\n            ( fun (b : V2f)        -> V4f(b.X, b.Y, 0.0f, 1.0f) ) :> obj\n            ( fun (b : V2f)        -> V4d(float b.X, float b.Y, 0.0, 1.0) ) :> obj\n\n            // V2d -> other vectors\n            ( fun (b : V2d)        -> V2i b ) :> obj\n            ( fun (b : V2d)        -> V2ui b ) :> obj\n            ( fun (b : V2d)        -> V2l b ) :> obj\n            ( fun (b : V2d)        -> V2f b ) :> obj\n            ( fun (b : V2d)        -> b ) :> obj\n            ( fun (b : V2d)        -> V3i(int b.X, int b.Y, 0) ) :> obj\n            ( fun (b : V2d)        -> V3ui(uint b.X, uint b.Y, 0u) ) :> obj\n            ( fun (b : V2d)        -> V3l(int64 b.X, int64 b.Y,0L) ) :> obj\n            ( fun (b : V2d)        -> V3f(float32 b.X, float32 b.Y, 0.0f) ) :> obj\n            ( fun (b : V2d)        -> V3d(b.X, b.Y, 0.0) ) :> obj\n            ( fun (b : V2d)        -> V4i(int b.X, int b.Y, 0, 0) ) :> obj\n            ( fun (b : V2d)        -> V4ui(uint b.X, uint b.Y, 0u, 0u) ) :> obj\n            ( fun (b : V2d)        -> V4l(int64 b.X, int64 b.Y, 0L, 0L) ) :> obj\n            ( fun (b : V2d)        -> V4f(float32 b.X, float32 b.Y, 0.0f, 1.0f) ) :> obj\n            ( fun (b : V2d)        -> V4d(b.X, b.Y, 0.0, 1.0) ) :> obj\n\n        ]\n\n    let private vector3Conversions =\n        [\n            // V3i -> other vectors\n            ( fun (b : V3i)        -> b) :> obj\n            ( fun (b : V3i)        -> V3ui b) :> obj\n            ( fun (b : V3i)        -> V3l b) :> obj\n            ( fun (b : V3i)        -> V3f b) :> obj\n            ( fun (b : V3i)        -> V3d b) :> obj\n            ( fun (b : V3i)        -> V4i(b.X, b.Y, b.Z, 0)) :> obj\n            ( fun (b : V3i)        -> V4ui(uint b.X, uint b.Y, uint b.Z, 0u)) :> obj\n            ( fun (b : V3i)        -> V4l(int64 b.X, int64 b.Y, int64 b.Z, 0L)) :> obj\n            ( fun (b : V3i)        -> V4f(float32 b.X, float32 b.Y, float32 b.Z, 0.0f)) :> obj\n            ( fun (b : V3i)        -> V4d(float b.X, float b.Y, float b.Z, 0.0)) :> obj\n\n            // V3ui -> other vectors\n            ( fun (b : V3ui)        -> V3i b) :> obj\n            ( fun (b : V3ui)        -> b) :> obj\n            ( fun (b : V3ui)        -> V3l b) :> obj\n            ( fun (b : V3ui)        -> V3f b) :> obj\n            ( fun (b : V3ui)        -> V3d b) :> obj\n            ( fun (b : V3ui)        -> V4i(int b.X, int b.Y, int b.Z, 0)) :> obj\n            ( fun (b : V3ui)        -> V4ui(b.X, b.Y, b.Z, 0u)) :> obj\n            ( fun (b : V3ui)        -> V4l(int64 b.X, int64 b.Y, int64 b.Z, 0L)) :> obj\n            ( fun (b : V3ui)        -> V4f(float32 b.X, float32 b.Y, float32 b.Z, 0.0f)) :> obj\n            ( fun (b : V3ui)        -> V4d(float b.X, float b.Y, float b.Z, 0.0)) :> obj\n\n            // V3l -> other vectors\n            ( fun (b : V3l)        -> V3i b) :> obj\n            ( fun (b : V3l)        -> V3ui b) :> obj\n            ( fun (b : V3l)        -> b) :> obj\n            ( fun (b : V3l)        -> V3f b) :> obj\n            ( fun (b : V3l)        -> V3d b) :> obj\n            ( fun (b : V3l)        -> V4i(int b.X, int b.Y, int b.Z, 0)) :> obj\n            ( fun (b : V3l)        -> V4ui(uint b.X, uint b.Y, uint b.Z, 0u)) :> obj\n            ( fun (b : V3l)        -> V4l(b.X, b.Y, b.Z, 0L)) :> obj\n            ( fun (b : V3l)        -> V4f(float32 b.X, float32 b.Y, float32 b.Z, 0.0f)) :> obj\n            ( fun (b : V3l)        -> V4d(float b.X, float b.Y, float b.Z, 0.0)) :> obj\n\n            // V3f -> other vectors\n            ( fun (b : V3f)        -> V3i b) :> obj\n            ( fun (b : V3f)        -> V3ui b) :> obj\n            ( fun (b : V3f)        -> V3l b) :> obj\n            ( fun (b : V3f)        -> b) :> obj\n            ( fun (b : V3f)        -> V3d b) :> obj\n            ( fun (b : V3f)        -> V4i(int b.X, int b.Y, int b.Z, 0)) :> obj\n            ( fun (b : V3f)        -> V4ui(uint b.X, uint b.Y, uint b.Z, 0u)) :> obj\n            ( fun (b : V3f)        -> V4l(int64 b.X, int64 b.Y, int64 b.Z, 0L)) :> obj\n            ( fun (b : V3f)        -> V4f(b.X, b.Y, b.Z, 1.0f)) :> obj\n            ( fun (b : V3f)        -> V4d(float b.X, float b.Y, float b.Z, 1.0)) :> obj\n\n            // V3d -> other vectors\n            ( fun (b : V3d)        -> V3i b) :> obj\n            ( fun (b : V3d)        -> V3ui b) :> obj\n            ( fun (b : V3d)        -> V3l b) :> obj\n            ( fun (b : V3d)        -> V3f b) :> obj\n            ( fun (b : V3d)        -> b) :> obj\n            ( fun (b : V3d)        -> V4i(int b.X, int b.Y, int b.Z, 0)) :> obj\n            ( fun (b : V3d)        -> V4ui(uint b.X, uint b.Y, uint b.Z, 0u)) :> obj\n            ( fun (b : V3d)        -> V4l(int64 b.X, int64 b.Y, int64 b.Z, 0L)) :> obj\n            ( fun (b : V3d)        -> V4f(float32 b.X, float32 b.Y, float32 b.Z, 1.0f)) :> obj\n            ( fun (b : V3d)        -> V4d(b.X, b.Y, b.Z, 1.0)) :> obj\n\n        ]\n\n    let private vector4Conversions =\n        [\n            // V4i -> other vectors\n            ( fun (b : V4i)        -> b) :> obj\n            ( fun (b : V4i)        -> V4ui b) :> obj\n            ( fun (b : V4i)        -> V4l b) :> obj\n            ( fun (b : V4i)        -> V4f b) :> obj\n            ( fun (b : V4i)        -> V4d b) :> obj\n\n            // V4ui -> other vectors\n            ( fun (b : V4ui)        -> V4i b) :> obj\n            ( fun (b : V4ui)        -> b) :> obj\n            ( fun (b : V4ui)        -> V4l b) :> obj\n            ( fun (b : V4ui)        -> V4f b) :> obj\n            ( fun (b : V4ui)        -> V4d b) :> obj\n\n            // V4l -> other vectors\n            ( fun (b : V4l)        -> V4i b) :> obj\n            ( fun (b : V4l)        -> V4ui b) :> obj\n            ( fun (b : V4l)        -> b) :> obj\n            ( fun (b : V4l)        -> V4f b) :> obj\n            ( fun (b : V4l)        -> V4d b) :> obj\n\n            // V4f -> other vectors\n            ( fun (b : V4f)        -> V4i b) :> obj\n            ( fun (b : V4f)        -> V4ui b) :> obj\n            ( fun (b : V4f)        -> V4l b) :> obj\n            ( fun (b : V4f)        -> b) :> obj\n            ( fun (b : V4f)        -> V4d b) :> obj\n\n            // V4d -> other vectors\n            ( fun (b : V4d)        -> V4i b) :> obj\n            ( fun (b : V4d)        -> V4ui b) :> obj\n            ( fun (b : V4d)        -> V4l b) :> obj\n            ( fun (b : V4d)        -> V4f b) :> obj\n            ( fun (b : V4d)        -> b) :> obj\n        ]\n\n\n    let private matrix22Conversions =\n        [\n\n            // M22i -> other matrices\n            ( fun (v : M22i)        -> v ) :> obj\n            ( fun (v : M22i)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M22i)        -> M44d.op_Explicit v ) :> obj\n\n\n            // M22l -> other matrices\n            ( fun (v : M22l)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> v ) :> obj\n            ( fun (v : M22l)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M22l)        -> M44d.op_Explicit v ) :> obj\n\n            // M22f -> other matrices\n            ( fun (v : M22f)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> v ) :> obj\n            ( fun (v : M22f)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M22f)        -> M44d.op_Explicit v ) :> obj\n\n            // M22d -> other matrices\n            ( fun (v : M22d)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> v ) :> obj\n            ( fun (v : M22d)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M22d)        -> M44d.op_Explicit v ) :> obj\n        ]\n\n    let private matrix23Conversions =\n        [\n\n            // M23i -> other matrices\n            ( fun (v : M23i)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> v ) :> obj\n            ( fun (v : M23i)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M23i)        -> M44d.op_Explicit v ) :> obj\n\n\n            // M23l -> other matrices\n            ( fun (v : M23l)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> v ) :> obj\n            ( fun (v : M23l)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M23l)        -> M44d.op_Explicit v ) :> obj\n\n            // M23f -> other matrices\n            ( fun (v : M23f)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> v ) :> obj\n            ( fun (v : M23f)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M23f)        -> M44d.op_Explicit v ) :> obj\n\n            // M23d -> other matrices\n            ( fun (v : M23d)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> v ) :> obj\n            ( fun (v : M23d)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M23d)        -> M44d.op_Explicit v ) :> obj\n        ]\n\n    let private matrix33Conversions =\n        [\n\n            // M33i -> other matrices\n            ( fun (v : M33i)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> v ) :> obj\n            ( fun (v : M33i)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M33i)        -> M44d.op_Explicit v ) :> obj\n\n\n            // M33l -> other matrices\n            ( fun (v : M33l)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> v ) :> obj\n            ( fun (v : M33l)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M33l)        -> M44d.op_Explicit v ) :> obj\n\n            // M33f -> other matrices\n            ( fun (v : M33f)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> v ) :> obj\n            ( fun (v : M33f)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M33f)        -> M44d.op_Explicit v ) :> obj\n\n            // M33d -> other matrices\n            ( fun (v : M33d)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> v ) :> obj\n            ( fun (v : M33d)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M33d)        -> M44d.op_Explicit v ) :> obj\n        ]\n\n    let private matrix34Conversions =\n        [\n\n            // M34i -> other matrices\n            ( fun (v : M34i)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> v ) :> obj\n            ( fun (v : M34i)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M34i)        -> M44d.op_Explicit v ) :> obj\n\n\n            // M34l -> other matrices\n            ( fun (v : M34l)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> v ) :> obj\n            ( fun (v : M34l)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M34l)        -> M44d.op_Explicit v ) :> obj\n\n            // M34f -> other matrices\n            ( fun (v : M34f)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> v ) :> obj\n            ( fun (v : M34f)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M34f)        -> M44d.op_Explicit v ) :> obj\n\n            // M34d -> other matrices\n            ( fun (v : M34d)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> v ) :> obj\n            ( fun (v : M34d)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M34d)        -> M44d.op_Explicit v ) :> obj\n        ]\n\n    let private matrix44Conversions =\n        [\n\n            // M44i -> other matrices\n            ( fun (v : M44i)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> v ) :> obj\n            ( fun (v : M44i)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M44i)        -> M44d.op_Explicit v ) :> obj\n\n\n            // M44l -> other matrices\n            ( fun (v : M44l)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> v ) :> obj\n            ( fun (v : M44l)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M44l)        -> M44d.op_Explicit v ) :> obj\n\n            // M44f -> other matrices\n            ( fun (v : M44f)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M44f)        -> v ) :> obj\n            ( fun (v : M44f)        -> M44d.op_Explicit v ) :> obj\n\n            // M44d -> other matrices\n            ( fun (v : M44d)        -> M22i.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M22l.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M22f.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M22d.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M23i.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M23l.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M23f.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M23d.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M33i.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M33l.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M33f.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M33d.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M34i.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M34l.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M34f.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M34d.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M44i.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M44l.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> M44f.op_Explicit v ) :> obj\n            ( fun (v : M44d)        -> v ) :> obj\n        ]\n\n\n    let private colorConversions =\n        [\n            // C3b -> other colors\n            ( fun (v : C3b)        -> C3b(v) ) :> obj\n            ( fun (v : C3b)        -> C4b(v) ) :> obj\n            ( fun (v : C3b)        -> C3us(v) ) :> obj\n            ( fun (v : C3b)        -> C4us(v) ) :> obj\n            ( fun (v : C3b)        -> C3ui(v) ) :> obj\n            ( fun (v : C3b)        -> C4ui(v) ) :> obj\n            ( fun (v : C3b)        -> C3f(v) ) :> obj\n            ( fun (v : C3b)        -> C4f(v) ) :> obj\n            ( fun (v : C3b)        -> C3d(v) ) :> obj\n            ( fun (v : C3b)        -> C4d(v) ) :> obj\n\n            // C3b -> vectors\n            ( fun (v : C3b)        -> v.ToV3i() ) :> obj\n            ( fun (v : C3b)        -> v.ToV4i() ) :> obj\n            ( fun (v : C3b)        -> v.ToV3ui() ) :> obj\n            ( fun (v : C3b)        -> v.ToV4ui() ) :> obj\n            ( fun (v : C3b)        -> v.ToV3l() ) :> obj\n            ( fun (v : C3b)        -> v.ToV4l() ) :> obj\n            ( fun (v : C3b)        -> C3f(v).ToV3f() ) :> obj\n            ( fun (v : C3b)        -> C4f(v).ToV4f() ) :> obj\n            ( fun (v : C3b)        -> C3d(v).ToV3d() ) :> obj\n            ( fun (v : C3b)        -> C4d(v).ToV4d() ) :> obj\n\n            // C4b -> other colors\n            ( fun (v : C4b)        -> C3b(v) ) :> obj\n            ( fun (v : C4b)        -> C4b(v) ) :> obj\n            ( fun (v : C4b)        -> C3us(v) ) :> obj\n            ( fun (v : C4b)        -> C4us(v) ) :> obj\n            ( fun (v : C4b)        -> C3ui(v) ) :> obj\n            ( fun (v : C4b)        -> C4ui(v) ) :> obj\n            ( fun (v : C4b)        -> C3f(v) ) :> obj\n            ( fun (v : C4b)        -> C4f(v) ) :> obj\n            ( fun (v : C4b)        -> C3d(v) ) :> obj\n            ( fun (v : C4b)        -> C4d(v) ) :> obj\n\n            // C4b -> vectors\n            ( fun (v : C4b)        -> v.ToV3i() ) :> obj\n            ( fun (v : C4b)        -> v.ToV4i() ) :> obj\n            ( fun (v : C4b)        -> v.ToV3ui() ) :> obj\n            ( fun (v : C4b)        -> v.ToV4ui() ) :> obj\n            ( fun (v : C4b)        -> v.ToV3l() ) :> obj\n            ( fun (v : C4b)        -> v.ToV4l() ) :> obj\n            ( fun (v : C4b)        -> C3f(v).ToV3f() ) :> obj\n            ( fun (v : C4b)        -> C4f(v).ToV4f() ) :> obj\n            ( fun (v : C4b)        -> C3d(v).ToV3d() ) :> obj\n            ( fun (v : C4b)        -> C4d(v).ToV4d() ) :> obj\n\n\n            // C3us -> other colors\n            ( fun (v : C3us)       -> C3b(v) ) :> obj\n            ( fun (v : C3us)       -> C4b(v) ) :> obj\n            ( fun (v : C3us)       -> C3us(v) ) :> obj\n            ( fun (v : C3us)       -> C4us(v) ) :> obj\n            ( fun (v : C3us)       -> C3ui(v) ) :> obj\n            ( fun (v : C3us)       -> C4ui(v) ) :> obj\n            ( fun (v : C3us)       -> C3f(v) ) :> obj\n            ( fun (v : C3us)       -> C4f(v) ) :> obj\n            ( fun (v : C3us)       -> C3d(v) ) :> obj\n            ( fun (v : C3us)       -> C4d(v) ) :> obj\n\n            // C3us -> vectors\n            ( fun (v : C3us)       -> v.ToV3i() ) :> obj\n            ( fun (v : C3us)       -> v.ToV4i() ) :> obj\n            ( fun (v : C3us)       -> v.ToV3ui() ) :> obj\n            ( fun (v : C3us)       -> v.ToV4ui() ) :> obj\n            ( fun (v : C3us)       -> v.ToV3l() ) :> obj\n            ( fun (v : C3us)       -> v.ToV4l() ) :> obj\n            ( fun (v : C3us)       -> C3f(v).ToV3f() ) :> obj\n            ( fun (v : C3us)       -> C4f(v).ToV4f() ) :> obj\n            ( fun (v : C3us)       -> C3d(v).ToV3d() ) :> obj\n            ( fun (v : C3us)       -> C4d(v).ToV4d() ) :> obj\n\n            // C4us -> other colors\n            ( fun (v : C4us)       -> C3b(v) ) :> obj\n            ( fun (v : C4us)       -> C4b(v) ) :> obj\n            ( fun (v : C4us)       -> C3us(v) ) :> obj\n            ( fun (v : C4us)       -> C4us(v) ) :> obj\n            ( fun (v : C4us)       -> C3ui(v) ) :> obj\n            ( fun (v : C4us)       -> C4ui(v) ) :> obj\n            ( fun (v : C4us)       -> C3f(v) ) :> obj\n            ( fun (v : C4us)       -> C4f(v) ) :> obj\n            ( fun (v : C4us)       -> C3d(v) ) :> obj\n            ( fun (v : C4us)       -> C4d(v) ) :> obj\n\n            // C4us -> vectors\n            ( fun (v : C4us)       -> v.ToV3i() ) :> obj\n            ( fun (v : C4us)       -> v.ToV4i() ) :> obj\n            ( fun (v : C4us)       -> v.ToV3ui() ) :> obj\n            ( fun (v : C4us)       -> v.ToV4ui() ) :> obj\n            ( fun (v : C4us)       -> v.ToV3l() ) :> obj\n            ( fun (v : C4us)       -> v.ToV4l() ) :> obj\n            ( fun (v : C4us)       -> C3f(v).ToV3f() ) :> obj\n            ( fun (v : C4us)       -> C4f(v).ToV4f() ) :> obj\n            ( fun (v : C4us)       -> C3d(v).ToV3d() ) :> obj\n            ( fun (v : C4us)       -> C4d(v).ToV4d() ) :> obj\n\n\n            // C3ui-> other colors\n            ( fun (v : C3ui)       -> C3b(v) ) :> obj\n            ( fun (v : C3ui)       -> C4b(v) ) :> obj\n            ( fun (v : C3ui)       -> C3us(v) ) :> obj\n            ( fun (v : C3ui)       -> C4us(v) ) :> obj\n            ( fun (v : C3ui)       -> C3ui(v) ) :> obj\n            ( fun (v : C3ui)       -> C4ui(v) ) :> obj\n            ( fun (v : C3ui)       -> C3f(v) ) :> obj\n            ( fun (v : C3ui)       -> C4f(v) ) :> obj\n            ( fun (v : C3ui)       -> C3d(v) ) :> obj\n            ( fun (v : C3ui)       -> C4d(v) ) :> obj\n\n            // C3ui -> vectors\n            ( fun (v : C3ui)       -> v.ToV3ui() ) :> obj\n            ( fun (v : C3ui)       -> v.ToV4ui() ) :> obj\n            ( fun (v : C3ui)       -> v.ToV3l() ) :> obj\n            ( fun (v : C3ui)       -> v.ToV4l() ) :> obj\n            ( fun (v : C3ui)       -> C3f(v).ToV3f() ) :> obj\n            ( fun (v : C3ui)       -> C4f(v).ToV4f() ) :> obj\n            ( fun (v : C3ui)       -> C3d(v).ToV3d() ) :> obj\n            ( fun (v : C3ui)       -> C4d(v).ToV4d() ) :> obj\n\n            // C4ui -> other colors\n            ( fun (v : C4ui)       -> C3b(v) ) :> obj\n            ( fun (v : C4ui)       -> C4b(v) ) :> obj\n            ( fun (v : C4ui)       -> C3us(v) ) :> obj\n            ( fun (v : C4ui)       -> C4us(v) ) :> obj\n            ( fun (v : C4ui)       -> C3ui(v) ) :> obj\n            ( fun (v : C4ui)       -> C4ui(v) ) :> obj\n            ( fun (v : C4ui)       -> C3f(v) ) :> obj\n            ( fun (v : C4ui)       -> C4f(v) ) :> obj\n            ( fun (v : C4ui)       -> C3d(v) ) :> obj\n            ( fun (v : C4ui)       -> C4d(v) ) :> obj\n\n            // C4ui -> vectors\n            ( fun (v : C4ui)       -> v.ToV3ui() ) :> obj\n            ( fun (v : C4ui)       -> v.ToV4ui() ) :> obj\n            ( fun (v : C4ui)       -> v.ToV3l() ) :> obj\n            ( fun (v : C4ui)       -> v.ToV4l() ) :> obj\n            ( fun (v : C4ui)       -> C3f(v).ToV3f() ) :> obj\n            ( fun (v : C4ui)       -> C4f(v).ToV4f() ) :> obj\n            ( fun (v : C4ui)       -> C3d(v).ToV3d() ) :> obj\n            ( fun (v : C4ui)       -> C4d(v).ToV4d() ) :> obj\n\n\n            // C3f -> other colors\n            ( fun (v : C3f)        -> C3b(v) ) :> obj\n            ( fun (v : C3f)        -> C4b(v) ) :> obj\n            ( fun (v : C3f)        -> C3us(v) ) :> obj\n            ( fun (v : C3f)        -> C4us(v) ) :> obj\n            ( fun (v : C3f)        -> C3ui(v) ) :> obj\n            ( fun (v : C3f)        -> C4ui(v) ) :> obj\n            ( fun (v : C3f)        -> C3f(v) ) :> obj\n            ( fun (v : C3f)        -> C4f(v) ) :> obj\n            ( fun (v : C3f)        -> C3d(v) ) :> obj\n            ( fun (v : C3f)        -> C4d(v) ) :> obj\n\n            // C3f -> vectors\n            ( fun (v : C3f)        -> v.ToV3f() ) :> obj\n            ( fun (v : C3f)        -> v.ToV4f() ) :> obj\n            ( fun (v : C3f)        -> v.ToV3d() ) :> obj\n            ( fun (v : C3f)        -> v.ToV4d() ) :> obj\n\n            // C4f -> other colors\n            ( fun (v : C4f)        -> C3b(v) ) :> obj\n            ( fun (v : C4f)        -> C4b(v) ) :> obj\n            ( fun (v : C4f)        -> C3us(v) ) :> obj\n            ( fun (v : C4f)        -> C4us(v) ) :> obj\n            ( fun (v : C4f)        -> C3ui(v) ) :> obj\n            ( fun (v : C4f)        -> C4ui(v) ) :> obj\n            ( fun (v : C4f)        -> C3f(v) ) :> obj\n            ( fun (v : C4f)        -> C4f(v) ) :> obj\n            ( fun (v : C4f)        -> C3d(v) ) :> obj\n            ( fun (v : C4f)        -> C4d(v) ) :> obj\n\n            // C4f -> vectors\n            ( fun (v : C4f)        -> v.ToV3f() ) :> obj\n            ( fun (v : C4f)        -> v.ToV4f() ) :> obj\n            ( fun (v : C4f)        -> v.ToV3d() ) :> obj\n            ( fun (v : C4f)        -> v.ToV4d() ) :> obj\n\n\n            // C3d -> other colors\n            ( fun (v : C3d)        -> C3b(v) ) :> obj\n            ( fun (v : C3d)        -> C4b(v) ) :> obj\n            ( fun (v : C3d)        -> C3us(v) ) :> obj\n            ( fun (v : C3d)        -> C4us(v) ) :> obj\n            ( fun (v : C3d)        -> C3ui(v) ) :> obj\n            ( fun (v : C3d)        -> C4ui(v) ) :> obj\n            ( fun (v : C3d)        -> C3f(v) ) :> obj\n            ( fun (v : C3d)        -> C4f(v) ) :> obj\n            ( fun (v : C3d)        -> C3d(v) ) :> obj\n            ( fun (v : C3d)        -> C4d(v) ) :> obj\n\n            // C3d -> vectors\n            ( fun (v : C3d)        -> v.ToV3f() ) :> obj\n            ( fun (v : C3d)        -> v.ToV4f() ) :> obj\n            ( fun (v : C3d)        -> v.ToV3d() ) :> obj\n            ( fun (v : C3d)        -> v.ToV4d() ) :> obj\n\n            // C4d -> other colors\n            ( fun (v : C4d)        -> C3b(v) ) :> obj\n            ( fun (v : C4d)        -> C4b(v) ) :> obj\n            ( fun (v : C4d)        -> C3us(v) ) :> obj\n            ( fun (v : C4d)        -> C4us(v) ) :> obj\n            ( fun (v : C4d)        -> C3ui(v) ) :> obj\n            ( fun (v : C4d)        -> C4ui(v) ) :> obj\n            ( fun (v : C4d)        -> C3f(v) ) :> obj\n            ( fun (v : C4d)        -> C4f(v) ) :> obj\n            ( fun (v : C4d)        -> C3d(v) ) :> obj\n            ( fun (v : C4d)        -> C4d(v) ) :> obj\n\n            // C4d -> vectors\n            ( fun (v : C4d)        -> v.ToV3f() ) :> obj\n            ( fun (v : C4d)        -> v.ToV4f() ) :> obj\n            ( fun (v : C4d)        -> v.ToV3d() ) :> obj\n            ( fun (v : C4d)        -> v.ToV4d() ) :> obj\n\n\n            // V3i -> colors\n            ( fun (v : V3i)        -> C3b(v) ) :> obj\n            ( fun (v : V3i)        -> C4b(v) ) :> obj\n            ( fun (v : V3i)        -> C3us(v) ) :> obj\n            ( fun (v : V3i)        -> C4us(v) ) :> obj\n\n            // V4i -> colors\n            ( fun (v : V4i)        -> C3b(v) ) :> obj\n            ( fun (v : V4i)        -> C4b(v) ) :> obj\n            ( fun (v : V4i)        -> C3us(v) ) :> obj\n            ( fun (v : V4i)        -> C4us(v) ) :> obj\n\n\n            // V3ui -> colors\n            ( fun (v : V3ui)       -> C3b(v) ) :> obj\n            ( fun (v : V3ui)       -> C4b(v) ) :> obj\n            ( fun (v : V3ui)       -> C3us(v) ) :> obj\n            ( fun (v : V3ui)       -> C4us(v) ) :> obj\n            ( fun (v : V3ui)       -> C3ui(v) ) :> obj\n            ( fun (v : V3ui)       -> C4ui(v) ) :> obj\n\n            // V4ui -> colors\n            ( fun (v : V4ui)       -> C3b(v) ) :> obj\n            ( fun (v : V4ui)       -> C4b(v) ) :> obj\n            ( fun (v : V4ui)       -> C3us(v) ) :> obj\n            ( fun (v : V4ui)       -> C4us(v) ) :> obj\n            ( fun (v : V4ui)       -> C3ui(v) ) :> obj\n            ( fun (v : V4ui)       -> C4ui(v) ) :> obj\n\n\n            // V3l -> colors\n            ( fun (v : V3l)        -> C3b(v) ) :> obj\n            ( fun (v : V3l)        -> C4b(v) ) :> obj\n            ( fun (v : V3l)        -> C3us(v) ) :> obj\n            ( fun (v : V3l)        -> C4us(v) ) :> obj\n            ( fun (v : V3l)        -> C3ui(v) ) :> obj\n            ( fun (v : V3l)        -> C4ui(v) ) :> obj\n\n            // V4l -> colors\n            ( fun (v : V4l)        -> C3b(v) ) :> obj\n            ( fun (v : V4l)        -> C4b(v) ) :> obj\n            ( fun (v : V4l)        -> C3us(v) ) :> obj\n            ( fun (v : V4l)        -> C4us(v) ) :> obj\n            ( fun (v : V4l)        -> C3ui(v) ) :> obj\n            ( fun (v : V4l)        -> C4ui(v) ) :> obj\n\n\n            // V3f -> colors\n            ( fun (v : V3f)        -> C3f(v) ) :> obj\n            ( fun (v : V3f)        -> C4f(v) ) :> obj\n            ( fun (v : V3f)        -> C3d(v) ) :> obj\n            ( fun (v : V3f)        -> C4d(v) ) :> obj\n\n            // V4f -> colors\n            ( fun (v : V4f)        -> C3f(v) ) :> obj\n            ( fun (v : V4f)        -> C4f(v) ) :> obj\n            ( fun (v : V4f)        -> C3d(v) ) :> obj\n            ( fun (v : V4f)        -> C4d(v) ) :> obj\n\n\n            // V3d -> colors\n            ( fun (v : V3d)        -> C3f(v) ) :> obj\n            ( fun (v : V3d)        -> C4f(v) ) :> obj\n            ( fun (v : V3d)        -> C3d(v) ) :> obj\n            ( fun (v : V3d)        -> C4d(v) ) :> obj\n\n            // V4d -> colors\n            ( fun (v : V4d)        -> C3f(v) ) :> obj\n            ( fun (v : V4d)        -> C4f(v) ) :> obj\n            ( fun (v : V4d)        -> C3d(v) ) :> obj\n            ( fun (v : V4d)        -> C4d(v) ) :> obj\n        ]\n\n\n    let private specialConversions =\n        [\n            ( fun (t : Trafo3d)     -> M44f.op_Explicit (t.Forward) ) :> obj\n        ]\n\n    let private allConversions =\n        List.concat [\n            integralConversions\n            booleanConversions\n            fractionalConversions\n\n            vector2Conversions\n            vector3Conversions\n            vector4Conversions\n\n            matrix22Conversions\n            matrix23Conversions\n            matrix33Conversions\n            matrix34Conversions\n            matrix44Conversions\n\n            colorConversions\n            specialConversions\n        ]\n\n\n    let private transposeFunctions =\n        [\n            ( fun (m : M22d) -> m.Transposed ) :> obj\n            ( fun (m : M22f) -> m.Transposed ) :> obj\n            ( fun (m : M22i) -> m.Transposed ) :> obj\n            ( fun (m : M22l) -> m.Transposed ) :> obj\n\n            ( fun (m : M33d) -> m.Transposed ) :> obj\n            ( fun (m : M33f) -> m.Transposed ) :> obj\n            ( fun (m : M33i) -> m.Transposed ) :> obj\n            ( fun (m : M33l) -> m.Transposed ) :> obj\n\n            ( fun (m : M23d) -> M23d(m.M00, m.M10, m.M02, m.M01, m.M11, m.M12 ) ) :> obj\n            ( fun (m : M23f) -> M23f(m.M00, m.M10, m.M02, m.M01, m.M11, m.M12 ) ) :> obj\n            ( fun (m : M23i) -> M23i(m.M00, m.M10, m.M02, m.M01, m.M11, m.M12 ) ) :> obj\n            ( fun (m : M23l) -> M23l(m.M00, m.M10, m.M02, m.M01, m.M11, m.M12 ) ) :> obj\n\n\n            ( fun (m : M44d) -> m.Transposed ) :> obj\n            ( fun (m : M44f) -> m.Transposed ) :> obj\n            ( fun (m : M44i) -> m.Transposed ) :> obj\n            ( fun (m : M44l) -> m.Transposed ) :> obj\n\n            ( fun (m : M34d) -> M34d(m.M00, m.M10, m.M20, m.M03, m.M01, m.M11, m.M21, m.M13, m.M02, m.M12, m.M22, m.M23) ) :> obj\n            ( fun (m : M34f) -> M34f(m.M00, m.M10, m.M20, m.M03, m.M01, m.M11, m.M21, m.M13, m.M02, m.M12, m.M22, m.M23) ) :> obj\n            ( fun (m : M34i) -> M34i(m.M00, m.M10, m.M20, m.M03, m.M01, m.M11, m.M21, m.M13, m.M02, m.M12, m.M22, m.M23) ) :> obj\n            ( fun (m : M34l) -> M34l(m.M00, m.M10, m.M20, m.M03, m.M01, m.M11, m.M21, m.M13, m.M02, m.M12, m.M22, m.M23) ) :> obj\n        ]\n\n\n    type private ConversionMapping<'a>() =\n        let store = Dictionary<Type, Dictionary<Type, 'a>>()\n\n        member x.Add(input : Type, output : Type, conversion : 'a) =\n            let map = store.GetCreate(input, fun _ -> Dictionary())\n\n            if map.ContainsKey output then\n                Log.warn \"[PrimitiveValueConverter] Conflicting conversions for: %s -> %s\" input.Name output.Name\n\n            map.[output] <- conversion\n\n        member x.TryGet(input : Type, output : Type, [<Out>] conversion : byref<'a>) =\n            match store.TryGetValue input with\n            | (true, m) ->\n                m.TryGetValue(output, &conversion)\n            | _ ->\n                false\n\n\n    let private createCompiledMap (conversions : list<obj>) =\n        let result = ConversionMapping()\n\n        for c in conversions do\n            let (i, o) = FSharpType.GetFunctionElements (c.GetType())\n            result.Add(i, o, c)\n\n        result\n\n    let private mapping = createCompiledMap allConversions\n\n    let private transposeMapping =\n        let dict = ConcurrentDictionary<Type, obj>()\n        for f in transposeFunctions do\n            let t = f.GetType()\n            let (arg, ret) = FSharpType.GetFunctionElements t\n            dict.[arg] <- f\n        dict\n\n\n    [<AutoOpen>]\n    module private Lambdas =\n        type UnboxLambda<'a> private() =\n            static let instance = fun (v : obj) -> unbox<'a> v\n            static member Instance = instance\n\n        type IdLambda<'a> private() =\n            static let instance = fun (v : 'a) -> v\n            static member Instance = instance\n\n        type ComposedLambda<'a, 'b, 'c> private() =\n            static member Create(f : 'a -> 'b, g : 'b -> 'c) =\n                f >> g\n\n        type UntypedArrayMapLambda<'a, 'b> private() =\n            static member Create(converter : 'a -> 'b) =\n                fun (arr : Array) -> arr |> unbox |> Array.map converter :> Array\n\n        type ArrayMapLambda<'a, 'b> private() =\n            static member Create(converter : 'a -> 'b) =\n                fun (arr : Array) -> arr |> unbox |> Array.map converter\n\n        type UnboxTyped<'e, 'b>() =\n            static let conv = fun (e : 'e) -> e |> unbox<'b>\n            static member Instance = conv\n\n\n        let compose (f : obj) (g : obj) =\n            let ft = f.GetType()\n            let gt = g.GetType()\n            let (a,b) = FSharpType.GetFunctionElements ft\n            let (b',c) = FSharpType.GetFunctionElements gt\n            if b <> b' then failwith \"[PrimitiveValueConverter] cannot compose functions\"\n            let t = typedefof<ComposedLambda<_,_,_>>.MakeGenericType [| a; b; c |]\n            let mi =\n                t.GetMethod(\n                    \"Create\",\n                    BindingFlags.NonPublic ||| BindingFlags.Static ||| BindingFlags.Public,\n                    Type.DefaultBinder,\n                    [| ft; gt|],\n                    null\n                )\n\n            mi.Invoke(null, [| f; g |])\n\n        let withTranspose (f : obj) =\n            let ft = f.GetType()\n            let (_,r) = FSharpType.GetFunctionElements ft\n            match transposeMapping.TryGetValue r with\n            | (true, transpose) -> compose f transpose\n            | _ -> f\n\n        let idFunction (t : Type) =\n            let t = typedefof<IdLambda<_>>.MakeGenericType [| t |]\n            t.GetProperty(\"Instance\").GetValue(null)\n\n        let unboxFunction (t : Type) =\n            let t = typedefof<UnboxLambda<_>>.MakeGenericType [| t |]\n            t.GetProperty(\"Instance\").GetValue(null)\n\n    let rec tryGetConverterV (inType : Type) (outType : Type) =\n        lock mapping (fun () ->\n            match mapping.TryGet(inType, outType) with\n            | (true, conv) ->\n                ValueSome conv\n\n            | _ ->\n                if outType.IsArray && inType.IsArray then\n                    let inType' = inType.GetElementType()\n                    let outType' = outType.GetElementType()\n\n                    match tryGetConverterV inType' outType' with\n                    | ValueSome innerConv ->\n                        let tconv = typedefof<ArrayMapLambda<_,_>>.MakeGenericType [| inType'; outType' |]\n\n                        let mi =\n                            tconv.GetMethod(\n                                \"Create\",\n                                BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Static,\n                                Type.DefaultBinder,\n                                [| innerConv.GetType() |],\n                                null\n                            )\n\n                        let conv = mi.Invoke(null, [|innerConv|])\n                        mapping.Add(inType, outType, conv)\n                        ValueSome conv\n\n                    | ValueNone ->\n                        ValueNone\n\n                elif inType.IsEnum then\n                    let valueType = Enum.GetUnderlyingType(inType)\n\n                    let toValue =\n                        let value = typedefof<UnboxTyped<_,_>>.MakeGenericType [| inType; valueType |]\n                        let prop = value.GetProperty(\"Instance\", BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Static)\n                        prop.GetValue(null)\n\n                    match tryGetConverterV valueType outType with\n                    | ValueSome inner ->\n                        let conv = compose toValue inner\n                        mapping.Add(inType, outType, conv)\n                        ValueSome conv\n\n                    | ValueNone ->\n                        ValueNone\n\n                else\n                    ValueNone\n            )\n\n    let tryGetConverter (inType : Type) (outType : Type) =\n        tryGetConverterV inType outType |> ValueOption.toOption\n\n    let getConverter (inType : Type) (outType : Type) =\n        match tryGetConverterV inType outType with\n        | ValueSome c -> c\n        | ValueNone -> raise <| InvalidConversionException($\"Unknown conversion from {inType} to {outType}\", inType, outType)\n\n    let addConverters (converters: #seq<obj>) =\n        lock mapping (fun _ ->\n            for c in converters do\n                let (i, o) = FSharpType.GetFunctionElements (c.GetType())\n                mapping.Add(i, o, c)\n        )\n\n    //open Aardvark.Base.IL\n    type private Invoker private() =\n        static let cache = System.Collections.Concurrent.ConcurrentDictionary<struct (Type * Type), obj -> obj -> obj>()\n\n        static let get (inType : Type) (outType : Type) =\n            cache.GetOrAdd(struct (inType, outType), Func<_,_>(fun struct (inType, outType) ->\n                let tfun = FSharpType.MakeFunctionType(inType, outType)\n                let invoke = tfun.GetMethod(\"Invoke\")\n\n                fun (f : obj) (arg : obj) ->\n                    invoke.Invoke(f, [| arg |])\n\n                //cil {\n                //    do! IL.ldarg 0\n                //    do! IL.ldarg 1\n                //    if inType.IsValueType then\n                //        do! IL.unbox inType\n                //    do! IL.call invoke\n                //    if outType.IsValueType then\n                //        do! IL.box outType\n                //    do! IL.ret\n                //}\n            ))\n\n        static member Invoke(inType : Type, outType : Type, f : obj, value : obj) =\n            let invoke = get inType outType\n            invoke f value\n\n\n    let convert (outType : Type) (value : obj) =\n        if isNull value then\n            if outType.IsValueType then raise <| InvalidConversionException($\"Cannot convert null to value type {outType}.\", null, outType)\n            null\n        else\n            let inType = value.GetType()\n            let conv = getConverter inType outType\n            Invoker.Invoke(inType, outType, conv, value)\n\n\n    type private ArrayConverterCache<'a>() =\n        static let conv = Dictionary<Type, Array -> 'a[]>()\n        static let t = typedefof<ArrayMapLambda<_,_>>\n\n        static member Get (inputType : Type) =\n            lock conv (fun () ->\n                conv.GetCreate(inputType, Func<Type, Array -> 'a[]>(fun inputType ->\n                    if inputType = typeof<'a> then\n                        unbox\n                    else\n                        let t = t.MakeGenericType [| inputType; typeof<'a> |]\n                        let mi = t.GetMethod(\"Create\", BindingFlags.NonPublic ||| BindingFlags.Static ||| BindingFlags.Public, Type.DefaultBinder, [| FSharpType.MakeFunctionType(inputType, typeof<'a>) |], null)\n                        let conv = getConverter inputType typeof<'a>\n                        mi.Invoke(null, [|conv|]) |> unbox<Array -> 'a[]>\n                ) )\n            )\n\n    type private ArrayConverterCache() =\n        static let conv = Dictionary<struct (Type * Type), Array -> Array>()\n        static let t = typedefof<UntypedArrayMapLambda<_,_>>\n\n        static member Get (inputType : Type, outputType : Type) =\n            lock conv (fun () ->\n                let key = struct (inputType, outputType)\n                conv.GetCreate(key, Func<struct (Type * Type), Array -> Array>(fun struct (inputType, outputType) ->\n                    if inputType = outputType then\n                        id\n                    else\n                        let t = t.MakeGenericType [| inputType; outputType |]\n                        let mi = t.GetMethod(\"Create\", BindingFlags.NonPublic ||| BindingFlags.Static ||| BindingFlags.Public, Type.DefaultBinder, [| FSharpType.MakeFunctionType(inputType, outputType) |], null)\n                        let conv = getConverter inputType outputType\n                        mi.Invoke(null, [|conv|]) |> unbox<Array -> Array>\n                ) )\n            )\n\n    let getArrayConverter (inputType : Type) (outputType : Type) : Array -> Array =\n        ArrayConverterCache.Get(inputType, outputType)\n\n    let private uniformCache = Dictionary<struct (bool * Type * Type), obj>()\n    let getUniformConverter (transpose : bool) (inType : Type) (outType : Type) =\n        let key = struct (transpose, inType, outType)\n        lock uniformCache (fun () ->\n            uniformCache.GetCreate(key, fun struct (transpose, inType, outType) ->\n                if transpose then getConverter inType outType |> withTranspose\n                else getConverter inType outType\n            )\n        )\n\n    let private idFunctions = Dictionary<Type, obj>()\n    let getIdentityConverter (t : Type) =\n        lock idFunctions (fun () ->\n            idFunctions.GetCreate(t, fun t -> idFunction t)\n        )\n\n    let getTransposeConverter (t : Type) =\n        match transposeMapping.TryGetValue t with\n        | (true, v) -> v\n        | _ -> getIdentityConverter t\n\n    let isTransposable (t : Type) =\n        transposeMapping.ContainsKey t\n\n\n\n    let converter<'a, 'b> : 'a -> 'b =\n        if typeof<'a> = typeof<'b> then\n            let f = id : 'a -> 'a\n            f |> unbox\n        else\n            getConverter typeof<'a> typeof<'b> |> unbox\n\n    let arrayConverter<'a> (inputType : Type) : Array -> 'a[] =\n        if inputType = typeof<'a> then unbox\n        else ArrayConverterCache<'a>.Get(inputType)\n\n    let uniformConverter<'a, 'b> (transpose : bool) : 'a -> 'b =\n        if not transpose && typeof<'a> = typeof<'b> then\n            let f = id : 'a -> 'a\n            f |> unbox\n        else\n            getUniformConverter transpose typeof<'a> typeof<'b> |> unbox\n\n    let transpose<'a> : 'a -> 'a =\n        getTransposeConverter typeof<'a> |> unbox\n\n    let transposable<'a> = isTransposable typeof<'a>"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Threading.fs",
    "content": "﻿namespace Aardvark.Base\n\n#nowarn \"44\"\n\nopen System\n\n[<AutoOpen>]\nmodule Threading =\n    open System.Threading\n\n    /// Please note that Aardvark.Base.FSharp's MVar implementation is different from Haskell's MVar introduced in\n    ///  \"Concurrent Haskell\" by Simon Peyton Jones, Andrew Gordon and Sigbjorn Finne.\n    /// see also: http://hackage.haskell.org/package/base-4.11.1.0/docs/Control-Concurrent-MVar.html\n    /// In our 'wrong' implementation put does not block but overrides the old value.\n    /// We use it typically for synchronized sampling use cases.\n    type MVar<'a>() =\n        let l = obj()\n\n        let mutable hasValue = false\n        let mutable content = Unchecked.defaultof<'a>\n\n        member x.Put v =\n            lock l (fun () ->\n                content <- v\n                if not hasValue then\n                    hasValue <- true\n                    Monitor.PulseAll l\n            )\n\n        member x.Take () =\n            lock l (fun () ->\n                while not hasValue do\n                    Monitor.Wait l |> ignore\n                let v = content\n                content <- Unchecked.defaultof<_>\n                hasValue <- false\n                v\n            )\n\n        [<Obsolete>]\n        member x.TakeAsync () =\n            async {\n                let! ct = Async.CancellationToken\n                do! Async.SwitchToThreadPool()\n                return x.Take()\n            }\n\n\n    let startThread (f : unit -> unit) =\n        let t = new Thread(ThreadStart f)\n        t.IsBackground <- true\n        t.Start()\n        t\n\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module MVar =\n        let empty () = MVar<'a>()\n        let create a =\n            let v = empty()\n            v.Put a\n            v\n        let put (m : MVar<'a>) v = m.Put v\n        let take (m : MVar<'a>) = m.Take()\n        [<Obsolete>]\n        let takeAsync (m : MVar<'a>) = m.TakeAsync ()\n\n    type Interlocked with\n        static member Change(location : byref<'a>, f : 'a -> 'a) =\n            let mutable initial = location\n            let mutable computed = f initial\n\n            while Interlocked.CompareExchange(&location, computed, initial) != initial do\n                initial <- location\n                computed <- f initial\n\n            computed\n\n        static member Change(location : byref<'a>, f : 'a -> 'a * 'b) =\n            let mutable initial = location\n            let (n,r) = f initial\n            let mutable computed = n\n            let mutable result = r\n\n            while Interlocked.CompareExchange(&location, computed, initial) != initial do\n                initial <- location\n                let (n,r) = f initial\n                computed <- n\n                result <- r\n\n            result\n\n\n        static member Change(location : byref<int>, f : int -> int) =\n            let mutable initial = location\n            let mutable computed = f initial\n\n            while Interlocked.CompareExchange(&location, computed, initial) <> initial do\n                initial <- location\n                computed <- f initial\n\n            computed\n\n        static member Change(location : byref<int>, f : int -> int * 'b) =\n            let mutable initial = location\n            let (n,r) = f initial\n            let mutable computed = n\n            let mutable result = r\n\n            while Interlocked.CompareExchange(&location, computed, initial) <> initial do\n                initial <- location\n                let (n,r) = f initial\n                computed <- n\n                result <- r\n\n            result\n\n        static member Change(location : byref<int64>, f : int64 -> int64) =\n            let mutable initial = location\n            let mutable computed = f initial\n\n            while Interlocked.CompareExchange(&location, computed, initial) <> initial do\n                initial <- location\n                computed <- f initial\n\n            computed\n\n        static member Change(location : byref<int64>, f : int64 -> int64 * 'b) =\n            let mutable initial = location\n            let (n,r) = f initial\n            let mutable computed = n\n            let mutable result = r\n\n            while Interlocked.CompareExchange(&location, computed, initial) <> initial do\n                initial <- location\n                let (n,r) = f initial\n                computed <- n\n                result <- r\n\n            result"
  },
  {
    "path": "src/Aardvark.Base.FSharp/Utilities/Weak.fs",
    "content": "﻿#if INTERACTIVE\n#r \"..\\\\..\\\\Bin\\\\Debug\\\\Aardvark.Base.dll\"\nopen Aardvark.Base\n#else\nnamespace Aardvark.Base\n#endif\n\n\nopen System\nopen System.Threading\n\n[<AutoOpen>]\nmodule Weak =\n    open System\n    open System.Collections.Generic\n    open System.Linq\n    open Aardvark.Base\n    open System.Threading\n    open System.Runtime.CompilerServices\n\n    (*============================ Statistics =================================*)\n    let private lastValues = Dictionary<obj, int>() \n    let mutable private lastNone = 0\n\n    let private statistics = Dictionary<obj, int>() \n    let mutable private statisticsNone = 0\n\n    let convertArray (f : ('a -> 'b)) (arr : Array) =\n        if isNull arr || arr.GetType().GetElementType() = typeof<'b> then\n            arr\n        else\n            let result = Array.CreateInstance(typeof<'b>, arr.Length)\n            for i in 0..(arr.Length-1) do\n                result.SetValue(f(arr.GetValue(i) |> unbox<'a>), i)\n            result\n\n    let private registerInStatistics(data : Option<obj>) =\n        match data with\n            | Some(key) -> if not (isNull key) then\n                                 Monitor.Enter(statistics)\n                                 match statistics.TryGetValue(key) with\n                                     | (true,v) -> statistics.[key] <- v + 1\n                                     | _ -> statistics.Add(key, 1)\n                                 Monitor.Exit(statistics)\n                            else\n                                 Report.Warn(\"Some(null)\")\n            | _ -> statisticsNone <- statisticsNone + 1\n\n    let printStatistics() =\n        let mem = System.GC.GetTotalMemory(true)\n        System.GC.WaitForPendingFinalizers()\n\n        Monitor.Enter(statistics)\n        Log.line \"============================= Finalizer Statistics ==========================\"\n        Log.line \"    Total:\"\n        for kvp in statistics do\n            Log.line \"        %A: %A\" kvp.Key kvp.Value\n        Log.line \"        \\\"NONE\\\": %A\" statisticsNone\n\n\n        Log.line \"    Relative:\"\n        for kvp in statistics do\n            let old = match lastValues.TryGetValue(kvp.Key) with\n                        | (true,v) -> v\n                        | _ -> 0\n            Log.line \"        %A: +%A\" kvp.Key (kvp.Value - old)\n        Log.line \"        \\\"NONE\\\": +%A\" (statisticsNone - lastNone)\n\n        Log.line \"    Total used Memory: %dMB\" (mem >>> 20)\n\n        Log.line \"=============================================================================\"\n\n        statistics |> Seq.iter (fun kvp -> lastValues.[kvp.Key] <- kvp.Value)\n        lastNone <- statisticsNone\n\n        Monitor.Exit(statistics)\n\n\n\n    (*============================ Registrations ==============================*)\n\n    type private Finalizable() =\n        let mutable finalizers = List<(obj -> unit) * Option<obj>>()\n\n        let finalizableFinalize(f,d) =\n            registerInStatistics(d)\n            match d with\n                | None -> f(null)\n                | Some(v) -> f(v)\n\n        member x.Add(f : obj -> unit, data : Option<obj>) =\n            finalizers.Add((f,data))\n\n        override x.Finalize() =\n            try\n                finalizers |> Seq.iter finalizableFinalize\n                finalizers.Clear()\n                finalizers <- null\n            with e -> Log.warn \"Finalizable threw an exception: %A\" e\n\n    let private registrations = ConditionalWeakTable<obj, Finalizable>()\n\n    let registerFinalizer<'a> (obj : 'a, finalizer : obj -> unit, data : Option<obj>) =\n        match registrations.TryGetValue(obj) with\n            | (true, v) -> v.Add(finalizer, data)\n            | _ -> let v = Finalizable()\n                   registrations.Add(obj,v)\n                   v.Add(finalizer, data)\n\n\n    (*============================ Weak Types =================================*)\n    [<AllowNullLiteral>]\n    type Weak<'a when 'a : not struct>(obj : 'a) =\n        do if isNull (obj :> obj) then failwith \"created null weak\"\n        let m_weak = System.WeakReference<'a>(obj)\n        let m_hashCode = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj)\n\n        member private x.WeakReference = m_weak\n\n        member x.IsLife = match m_weak.TryGetTarget() with\n                            | (true,o) when not (isNull (o :> obj)) -> true\n                            | _ -> false\n\n        member x.Target = match m_weak.TryGetTarget() with\n                            | (true,v) when not (isNull (v :> obj)) -> v\n                            | _ -> failwith \"Weak is no longer accessible\"\n\n        member x.TryGetTarget([<System.Runtime.InteropServices.OutAttribute>] a : byref<'a>) = \n            m_weak.TryGetTarget(&a) && not (isNull (a :> obj))\n\n        member x.TargetOption = \n            match m_weak.TryGetTarget() with\n                | (true, v) -> Some v\n                | _ -> None\n\n\n        member x.RegisterFinalizer(f : obj -> unit, ?data) =\n            match m_weak.TryGetTarget() with\n                | (true, v) -> registerFinalizer(v, f, data)\n                | _ -> f()\n\n        member x.RegisterFinalizer(f : unit -> unit) =\n            match m_weak.TryGetTarget() with\n                | (true, v) -> registerFinalizer(v, (fun _ -> f()), None)\n                | _ -> f()\n\n\n        override x.GetHashCode() = m_hashCode\n        override x.Equals(o : obj) =\n            if System.Object.ReferenceEquals(o, x) then\n                true\n            else\n                match o with\n                    | :? Weak<'a> as other -> match (m_weak.TryGetTarget(), other.WeakReference.TryGetTarget()) with\n                                                | ((true, l), (true, r)) -> System.Object.ReferenceEquals(l, r)\n                                                | ((false,_), (false,_)) -> true\n                                                | _ -> false \n                    | _ -> false\n \n    [<return: Struct>]\n    let inline (|Strong|_|) (weak : Weak<'a>) = \n        match weak.TryGetTarget() with\n        | (true, v) -> ValueSome v\n        | _ -> ValueNone\n        \n\n    \n    let registerWeakFinalizer (w : Weak<obj>, finalizer : obj -> unit, data : Option<obj>) =\n        match w with\n            | Strong(v) -> registerFinalizer(v, finalizer, data)\n            | _ -> match data with\n                    | Some(d) -> finalizer(d)\n                    | _ -> finalizer(null)\n\n\n    type System.Object with\n        member x.RegisterFinalizer(f : obj -> unit, ?data) =\n            registerFinalizer(x, f, data)\n\n        member x.RegisterFinalizer(f : unit -> unit) =\n            registerFinalizer(x, (fun _ -> f()), None)\n\n    type System.Collections.Generic.IEnumerable<'a> with\n        member x.RegisterAnyFinalizer(f : obj -> unit, ?data) =\n            let fRef = ref <| Some(f)\n            let finalize(_) =\n                match !fRef with\n                    | Some(f) -> match data with\n                                    | Some(v) -> f(v)\n                                    | _ -> f(null)\n\n                                 registerInStatistics(data)\n                                 fRef := None\n                    | None -> ()\n\n            x |> Seq.iter (fun o -> registerFinalizer(o, finalize, None))\n\n        member x.RegisterAllFinalizer(f : obj -> unit, ?data) =\n            let countRef = ref (x.Count())\n            let finalize(_) =\n                if !countRef = 1 then\n                    match data with\n                        | Some(v) -> f(v)\n                        | _ -> f(null)\n                    registerInStatistics(data)\n                else \n                    countRef := !countRef - 1\n\n            x |> Seq.iter (fun o -> registerFinalizer(o, finalize, None))\n\n        member x.RegisterAnyFinalizer(f : unit -> unit) =\n            x.RegisterAnyFinalizer(fun (o:obj) -> f())\n\n        member x.RegisterAllFinalizer(f : unit -> unit, ?data) =\n            x.RegisterAllFinalizer(fun (o:obj) -> f())\n\n\n    type WeakList<'a when 'a : not struct and 'a : equality>(l : list<Weak<'a>>) =\n        let m_elements = l\n        let m_isLife = ref true\n        let m_hashcode = l |> List.fold (fun c e -> c ^^^ e.GetHashCode()) 0\n\n\n        new(l : list<'a>) = WeakList<'a>(l |> List.map (fun e -> Weak(e)))\n\n        member private x.Target = m_elements\n        \n        member x.IsLife = m_elements |> List.fold (fun l e -> l && e.IsLife) true\n\n        member x.Elements = m_elements |> List.map (fun w -> w.Target)\n        \n\n        member x.RegisterAnyFinalizer(f : obj -> unit, ?data) =\n            let fRef = ref (Some(f))\n            let finalizer(_) =\n                match !fRef with\n                    | Some(f) -> match data with\n                                    | Some(v) -> f(v)\n                                    | _ -> f(null)\n\n                                 registerInStatistics(data)\n                                 fRef := None\n                    | _ -> ()\n\n            m_elements |> List.iter (fun e -> match e.TryGetTarget() with\n                                                    | (true,v) -> if (!fRef).IsSome then \n                                                                    registerFinalizer(v, finalizer, None)            \n                                                    | _ -> finalizer())\n\n        member x.RegisterAllFinalizer(f : obj -> unit, ?data) =\n            let countRef = ref (m_elements.Length)\n            let finalizer(_) =\n                if !countRef = 1 then\n                    registerInStatistics(data)\n                    match data with\n                        | Some(v) -> f(v)\n                        | _ -> f(null)\n                else\n                    countRef := !countRef - 1\n\n            m_elements |> List.iter (fun e -> match e.TryGetTarget() with\n                                                    | (true,v) -> registerFinalizer(v, finalizer, None)\n                                                    | _ -> finalizer())\n\n        member x.RegisterAnyFinalizer(f : unit -> unit) =\n            x.RegisterAnyFinalizer(fun (o:obj) -> f())\n\n        member x.RegisterAllFinalizer(f : unit -> unit) =\n            x.RegisterAllFinalizer(fun (o:obj) -> f())\n\n\n\n\n        override x.GetHashCode() = m_hashcode\n        override x.Equals(o) =\n            if System.Object.ReferenceEquals(x,o) then\n                true\n            else\n                match o with\n                    | :? WeakList<'a> as other -> if other.Target.Length <> m_elements.Length then\n                                                        false\n                                                   else\n                                                        List.fold2 (fun b l r -> b && (l.Equals(r))) true m_elements other.Target\n                    | _ -> false "
  },
  {
    "path": "src/Aardvark.Base.FSharp/__project.fsx",
    "content": "#r \"System\"\r\n#r \"System.Core\"\r\n#r \"System.Drawing\"\r\n#r \"System.Numerics\"\r\n#r @\".\\..\\..\\BinPrebuilt\\Release\\Aardvark.Base.TypeProviders.dll\"\r\n#r @\".\\..\\..\\Bin\\Debug\\Aardvark.Base.dll\"\r\n#r @\".\\..\\..\\Packages\\FSharp.Compiler.Service.0.0.58\\lib\\net40\\FSharp.Compiler.Service.dll\"\r\n#r @\".\\..\\..\\Packages\\NUnit.2.6.3\\lib\\nunit.framework.dll\"\r\n#r @\".\\..\\..\\Packages\\RegexProvider.0.0.2\\lib\\net40\\RegexProvider.dll\"\r\n"
  },
  {
    "path": "src/Aardvark.Base.FSharp/paket.references",
    "content": "FSharp.Core\nAardvark.Build\nSystem.Dynamic.Runtime\nFsPickler\nAardvark.Base.TypeProviders\nFSharp.Data.Adaptive"
  },
  {
    "path": "src/Aardvark.Base.FSharp/paket.template",
    "content": "type project\nid Aardvark.Base.FSharp\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.Base.Fonts/Aardvark.Base.Fonts.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <AssemblyName>Aardvark.Base.Fonts</AssemblyName>\n    <OutputType>Library</OutputType>\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <WarnOn>3389;3390;3395</WarnOn>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\bin\\Debug\\</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\n  </PropertyGroup>\n  <ItemGroup>\n    <EmbeddedResource Include=\"fonts\\Symbola.zip\" />\n    <Compile Include=\"BvhInternal.fs\" />\n    <Compile Include=\"PathSegment.fs\" />\n    <Compile Include=\"PathTessellator.fs\" />\n    <Compile Include=\"Path.fs\" />\n    <Compile Include=\"FontResolver.fs\" />\n    <Compile Include=\"Font.fs\" />\n    <None Include=\"paket.references\" />\n    <None Include=\"paket.template\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.Fonts/BvhInternal.fs",
    "content": "﻿module internal Aardvark.Base.Fonts.BvhImpl\n\nopen Aardvark.Base\nopen Aardvark.Base.Sorting\nopen FSharp.Data.Adaptive\n\ntype internal BvhNode3d<'K, 'V> =\n    | Leaf of overflowCount : int * bounds : Box3d * values : HashMap<'K, struct(Box3d * 'V)>\n    | Node of bestCost : float * count : int * bounds : Box3d * left : BvhNode3d<'K, 'V> * right : BvhNode3d<'K, 'V>\n\nmodule internal BvhNode3d =\n\n    module HashMap =\n        let partition (predicate : 'K -> 'V -> bool) (map : HashMap<'K, 'V>) =\n            HashMap.ApplyDelta(map, map, fun k _ v ->\n                if predicate k v then struct(ValueSome v, ValueNone)\n                else struct(ValueNone, ValueSome v)\n            )\n\n    [<GeneralizableValue>]\n    let empty<'K, 'V> : option<BvhNode3d<'K, 'V>> = None\n\n    let inline getBounds (n : BvhNode3d<'K, 'V>) =\n        match n with\n        | Leaf(_,b,_)\n        | Node(_,_,b,_,_) -> b\n\n    let inline count (n : BvhNode3d<'K, 'V>) =\n        match n with\n        | Leaf(_,_,v) -> v.Count\n        | Node(_,c,_,_,_) -> c\n\n    let cost (invVolume : float) (lBox : Box3d) (lCnt : int) (rBox : Box3d) (rCnt : int) =\n        let i = Box.Intersection(lBox, rBox)\n        let iVol = if i.IsValid then i.Volume * invVolume else 0.0\n        let lVol = lBox.Volume * invVolume\n        let rVol = rBox.Volume * invVolume\n        let cnt = lCnt + rCnt\n        let l = float lCnt / float cnt\n        let r = float rCnt / float cnt\n        (1.0 / float cnt + (l * lVol) + (r * rVol) + iVol) / 2.0\n\n    let split (invVolume : float) (elements : HashMap<'K, struct(Box3d * 'V)>) =\n        if elements.Count <= 1 then\n            None\n        else\n            let arr = elements.ToArrayV()\n            let bounds = arr |> Array.map (fun struct(k, struct(b,v)) -> b)\n\n            let mutable bestCost = System.Double.PositiveInfinity\n            let mutable bestPerm = null\n            let mutable bestSplit = -1\n            let mutable bestlBox = Unchecked.defaultof<Box3d>\n            let mutable bestrBox = Unchecked.defaultof<Box3d>\n\n\n            for dim in 0 .. 2 do\n                let getter =\n                    match dim with\n                    | 0 -> fun (v : V3d) -> v.X\n                    | 1 -> fun (v : V3d) -> v.Y\n                    | _ -> fun (v : V3d) -> v.Z\n                let mutable lBoxes = Array.zeroCreate elements.Count\n                let mutable rBoxes = Array.zeroCreate elements.Count\n\n                let perm = bounds.CreatePermutationQuickSortAscending(fun (b : Box3d) -> getter b.Center)\n\n                let mutable last = bounds.[perm.[0]]\n                lBoxes.[0] <- last\n                for i in 1 .. perm.Length - 1 do\n                    let b = bounds.[perm.[i]].Union(last)\n                    lBoxes.[i] <- b //Box3d.Union(last, b)\n                    last <- b\n\n                let mutable i = perm.Length-1\n                let mutable last = Box3d.Invalid\n                while i >= 0 do\n                    let b = bounds.[perm.[i]].Union(last)\n                    rBoxes.[i] <- b\n                    last <- b\n                    i <- i - 1\n\n\n                for lCnt in 1 .. perm.Length - 1 do\n                    let rCnt = perm.Length - lCnt\n                    let lBox = lBoxes.[lCnt-1]\n                    let rBox = rBoxes.[lCnt]\n\n                    let c = cost invVolume lBox lCnt rBox rCnt\n                    if c < bestCost then\n                        bestCost <- c\n                        bestPerm <- perm\n                        bestSplit <- lCnt\n                        bestlBox <- lBox\n                        bestrBox <- rBox\n\n            if bestCost < 1.0 then\n                let lCnt = bestSplit\n                let rCnt = arr.Length - lCnt\n\n                let left = Array.zeroCreate lCnt\n                let right = Array.zeroCreate rCnt\n\n                let mutable i = 0\n                for li in 0 .. lCnt - 1 do\n                    left.[li] <- arr.[bestPerm.[i]]\n                    i <- i + 1\n\n                for ri in 0 .. rCnt - 1 do\n                    right.[ri] <- arr.[bestPerm.[i]]\n                    i <- i + 1\n\n                Some (bestCost, bestlBox, HashMap.ofArrayV left, bestrBox, HashMap.ofArrayV right)\n            else\n                None\n\n    let rec build (limit : int) (bounds : Box3d) (elements : HashMap<'K, struct(Box3d * 'V)>) =\n        if elements.Count <= 0 then\n            failwith \"empty\"\n\n        elif elements.Count <= limit then\n            Leaf(0, bounds, elements)\n\n        else\n            let bv = 1.0 / bounds.Volume\n            match split bv elements with\n            | Some (cost, lBox, lElements, rBox, rElements) ->\n                let l = build limit lBox lElements\n                let r = build limit rBox rElements\n                Node(cost, elements.Count, bounds, l, r)\n            | None ->\n                //Log.warn \"bad split %d\" elements.Count\n                Leaf(elements.Count, bounds, elements)\n\n    let rec getIntersecting (query : Box3d) (node : BvhNode3d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            if bounds.Intersects query then\n                values |> HashMap.filter (fun _ struct(b,_) -> b.Intersects query)\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            if bounds.Intersects query then\n                let l = getIntersecting query l\n                let r = getIntersecting query r\n                HashMap.union l r\n            else\n                HashMap.empty\n\n    let rec getIntersectingFilter (query : Box3d) (filter : OptimizedClosures.FSharpFunc<'K, Box3d, 'V, bool>) (node : BvhNode3d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            if bounds.Intersects query then\n                values |> HashMap.filter (fun k struct(b,v) -> b.Intersects query && filter.Invoke(k, b, v))\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            if bounds.Intersects query then\n                let l = getIntersectingFilter query filter l\n                let r = getIntersectingFilter query filter r\n                HashMap.union l r\n            else\n                HashMap.empty\n\n    let rec toSeq (n : BvhNode3d<'K, 'V>) =\n        match n with\n        | Leaf(_,_,vs) -> vs.ToSeqV()\n        | Node(_,_,_,l,r) -> Seq.append (toSeq l) (toSeq r)\n\n    let rec add (limit : int) (key : 'K) (bounds : Box3d) (value : 'V) (node : BvhNode3d<'K, 'V>) =\n        match node with\n        | Leaf(overflowCount, b, values) ->\n            match HashMap.tryFindV key values with\n            | ValueSome (struct(ob, _ov)) ->\n                // replace\n                if bounds.Contains ob then\n                    Leaf(overflowCount, b, HashMap.add key (struct(bounds, value)) values)\n                else\n                    let mutable bb = bounds\n                    for struct(_,struct(b,_)) in values.ToSeqV() do\n                        bb.ExtendBy b\n                    Leaf(overflowCount, bb, HashMap.add key (struct(bounds, value)) values)\n            | _ ->\n                // add\n                let b = b.ExtendedBy bounds\n                let vs = HashMap.add key (struct(bounds, value)) values\n\n                if vs.Count >= 2 * overflowCount && vs.Count > limit then\n                    build limit b vs\n                else\n                    Leaf(overflowCount, b, vs)\n\n        | Node(bestCost, _, b, l, r) ->\n            let nb = Box.Union(b, bounds)\n\n            let lb = getBounds l\n            let rb = getBounds r\n            let lc = count l\n            let rc = count r\n            let invVol = 1.0 / nb.Volume\n            let lCost = cost invVol (Box.Union(lb, bounds)) (1 + lc) rb rc\n            let rCost = cost invVol lb lc (Box.Union(rb, bounds)) (1 + rc)\n\n            if lCost < rCost then\n                // add left\n                if lCost > 2.0 * bestCost then\n                    toSeq node\n                    |> HashMap.ofSeqV\n                    |> HashMap.add key (struct(bounds, value))\n                    |> build limit nb\n                else\n                    let l = add limit key bounds value l\n                    let lb = getBounds l\n                    let lc = count l\n                    let cc = cost invVol lb lc rb rc\n                    let nb = Box.Union(lb, rb)\n                    Node(min bestCost cc, lc + rc, nb, l, r)\n            else\n                if rCost > 2.0 * bestCost then\n                    toSeq node\n                    |> HashMap.ofSeqV\n                    |> HashMap.add key (struct(bounds, value))\n                    |> build limit nb\n                else\n                    let r = add limit key bounds value r\n                    let rb = getBounds r\n                    let rc = count r\n                    let cc = cost invVol lb lc rb rc\n                    let nb = Box.Union(lb, rb)\n                    Node(min bestCost cc, lc + rc, nb, l, r)\n\n    let rec tryRemove (limit : int) (key : 'K) (bounds : Box3d) (node : BvhNode3d<'K, 'V>) =\n        match node with\n        | Leaf(overflowCount, b, values) ->\n            if b.Intersects bounds then\n                match HashMap.tryRemove key values with\n                | Some (struct(_,v), n) ->\n                    if n.Count > 0 then\n                        let mutable bb = Box3d.Invalid\n                        for struct(_,struct(b,_)) in n.ToSeqV() do\n                            bb.ExtendBy b\n                        Some(v, Some (Leaf(max 0 (overflowCount - 1), bb, n)))\n                    else\n                        Some (v, None)\n                | None ->\n                    None\n            else\n                None\n\n        | Node(bestCost, _, b, l, r) ->\n            if b.Intersects bounds then\n                match tryRemove limit key bounds l with\n                | Some (v, l) ->\n                    match l with\n                    | Some l ->\n                        let lc = count l\n                        let rc = count r\n                        let lb = getBounds l\n                        let rb = getBounds r\n                        let o = Box.Union(lb, rb)\n                        let cnt = lc + rc\n                        if cnt <= limit then\n                            let values = Seq.append (toSeq l) (toSeq r) |> HashMap.ofSeqV\n                            Some (v, Some (Leaf(0, o, values)))\n                        else\n                            let cost = cost (1.0 / o.Volume) lb lc rb rc\n                            Some (v, Some (Node(min cost bestCost, cnt, o, l, r)))\n                    | None ->\n                        Some (v, Some r)\n                | None ->\n                    match tryRemove limit key bounds r with\n                    | Some(v,r) ->\n                        match r with\n                        | Some r ->\n                            let lc = count l\n                            let rc = count r\n                            let lb = getBounds l\n                            let rb = getBounds r\n                            let o = Box.Union(lb, rb)\n                            let cnt = lc + rc\n                            if cnt <= limit then\n                                let values = Seq.append (toSeq l) (toSeq r) |> HashMap.ofSeqV\n                                Some (v, Some (Leaf(0, o, values)))\n                            else\n                                let cost = cost (1.0 / o.Volume) lb lc rb rc\n                                Some (v, Some (Node(min cost bestCost, cnt, o, l, r)))\n                        | None ->\n                            Some (v, Some l)\n                    | None ->\n                        None\n            else\n                None\n\n    let remove (limit : int) (key : 'K) (bounds : Box3d) (node : BvhNode3d<'K, 'V>) =\n        match tryRemove limit key bounds node with\n        | Some (_, rest) -> rest\n        | None -> Some node\n\ntype BvhTree3d<'K, 'V> private(limit : int, root : option<BvhNode3d<'K, 'V>>, keyBounds : HashMap<'K, Box3d>) =\n    member internal x.Root = root\n\n    member x.Count =\n        match root with\n        | Some r -> BvhNode3d.count r\n        | None -> 0\n\n    member x.Add(key : 'K, bounds : Box3d, value : 'V) =\n        if bounds.IsValid then\n            let keyBounds = HashMap.add key bounds keyBounds\n            let newRoot =\n                match root with\n                | Some r -> BvhNode3d.add limit key bounds value r\n                | None -> BvhNode3d.Leaf(0, bounds, HashMap.single key (struct(bounds, value)))\n            BvhTree3d(limit, Some newRoot, keyBounds)\n        else\n            x\n\n    member x.Remove(key : 'K) =\n        match HashMap.tryRemove key keyBounds with\n        | Some (bounds, keyBounds) ->\n            let newRoot =\n                match root with\n                | Some r -> BvhNode3d.remove limit key bounds r\n                | None -> None\n            BvhTree3d(limit, newRoot, keyBounds)\n        | None ->\n            x\n\n    member x.TryRemove(key : 'K) =\n        match HashMap.tryRemove key keyBounds with\n        | Some (bounds, keyBounds) ->\n            let newRoot =\n                match root with\n                | Some r -> BvhNode3d.tryRemove limit key bounds r\n                | None -> None\n            match newRoot with\n            | Some (v, newRoot) ->\n                Some (v, BvhTree3d(limit, newRoot, keyBounds))\n            | None ->\n                None\n        | None ->\n            None\n\n    member x.GetIntersecting(query : Box3d) =\n        match root with\n        | Some r ->\n            BvhNode3d.getIntersecting query r\n        | None ->\n            HashMap.empty\n\n    member x.GetIntersecting(query : Box3d, filter : 'K -> Box3d -> 'V -> bool) =\n        match root with\n        | Some r ->\n            let opt = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt filter\n            BvhNode3d.getIntersectingFilter query opt r\n        | None ->\n            HashMap.empty\n\n    member x.ToSeq() =\n        match root with\n        | Some root -> BvhNode3d.toSeq root |> Seq.map (fun struct(k,struct(b,v)) -> k,b,v)\n        | None -> Seq.empty\n\n    member x.ToList() =\n        x.ToSeq() |> Seq.toList\n\n    member x.ToArray() =\n        match root with\n        | Some root ->\n            let arr = Array.zeroCreate x.Count\n            let mutable i = 0\n            for struct(k,struct(b,v)) in BvhNode3d.toSeq root do\n                arr.[i] <- (k,b,v)\n            arr\n        | None ->\n            [||]\n\n    static member Build(limit : int, elements : seq<'K * Box3d * 'V>) =\n        let mutable bb = Box3d.Invalid\n        let mutable all = HashMap.empty\n        let mutable keyBounds = HashMap.empty\n        for (k, b, v) in elements do\n            bb.ExtendBy b\n            all <- HashMap.add k (struct(b, v)) all\n            keyBounds <- HashMap.add k b keyBounds\n\n        if all.Count > 0 then\n            let root = BvhNode3d.build limit bb all\n            BvhTree3d(limit, Some root, keyBounds)\n        else\n            BvhTree3d(limit, None, HashMap.empty)\n\n    static member Empty(limit : int) = BvhTree3d<'K, 'V>(limit, None, HashMap.empty)\n\nmodule BvhTree3d =\n\n    let splitLimit = 24\n\n    [<GeneralizableValue>]\n    let empty<'K, 'V> : BvhTree3d<'K, 'V> = BvhTree3d.Empty(splitLimit)\n\n    let inline add (key : 'K) (bounds : Box3d) (value : 'V) (t : BvhTree3d<'K, 'V>) = t.Add(key, bounds, value)\n    let inline remove (key : 'K) (t : BvhTree3d<'K, 'V>) = t.Remove(key)\n    let inline tryRemove (key : 'K) (t : BvhTree3d<'K, 'V>) = t.TryRemove(key)\n\n    let inline getIntersecting (query : Box3d) (tree : BvhTree3d<'K, 'V>) = tree.GetIntersecting query\n\n    let inline ofSeq (elements : seq<'K * Box3d * 'V>)= BvhTree3d.Build(splitLimit, elements)\n    let inline ofList (elements : list<'K * Box3d * 'V>)= BvhTree3d.Build(splitLimit, elements)\n    let inline ofArray (elements : array<'K * Box3d * 'V>)= BvhTree3d.Build(splitLimit, elements)\n\n    let inline toSeq (tree : BvhTree3d<'K, 'V>)= tree.ToSeq()\n    let inline toList (tree : BvhTree3d<'K, 'V>)= tree.ToList()\n    let inline toArray (tree : BvhTree3d<'K, 'V>)= tree.ToArray()\n\n    let union (l : BvhTree3d<'K, 'V>) (r : BvhTree3d<'K, 'V>) =\n        let mutable l = l\n        for (k,b,v) in toSeq r do\n            l <- l.Add(k,b,v)\n        l\n\n\ntype internal BvhNode2d<'K, 'V> =\n    | Leaf of overflowCount : int * bounds : Box2d * values : HashMap<'K, struct(Box2d * 'V)>\n    | Node of bestCost : float * count : int * bounds : Box2d * left : BvhNode2d<'K, 'V> * right : BvhNode2d<'K, 'V>\n\nmodule internal BvhNode2d =\n\n    module HashMap =\n        let partition (predicate : 'K -> 'V -> bool) (map : HashMap<'K, 'V>) =\n            HashMap.ApplyDelta(map, map, fun k _ v ->\n                if predicate k v then struct(ValueSome v, ValueNone)\n                else struct(ValueNone, ValueSome v)\n            )\n\n    [<GeneralizableValue>]\n    let empty<'K, 'V> : option<BvhNode2d<'K, 'V>> = None\n\n    let inline getBounds (n : BvhNode2d<'K, 'V>) =\n        match n with\n        | Leaf(_,b,_)\n        | Node(_,_,b,_,_) -> b\n\n    let inline count (n : BvhNode2d<'K, 'V>) =\n        match n with\n        | Leaf(_,_,v) -> v.Count\n        | Node(_,c,_,_,_) -> c\n\n    let cost (invArea : float) (lBox : Box2d) (lCnt : int) (rBox : Box2d) (rCnt : int) =\n        let i = Box.Intersection(lBox, rBox)\n        let iVol = if i.IsValid then i.Area * invArea else 0.0\n        let lVol = lBox.Area * invArea\n        let rVol = rBox.Area * invArea\n        let cnt = lCnt + rCnt\n        let l = float lCnt / float cnt\n        let r = float rCnt / float cnt\n        (1.0 / float cnt + (l * lVol) + (r * rVol) + iVol) / 2.0\n\n    let split (invArea : float) (elements : HashMap<'K, struct(Box2d * 'V)>) =\n        if elements.Count <= 1 then\n            None\n        else\n            let arr = elements.ToArrayV()\n            let bounds = arr |> Array.map (fun struct(k, struct(b,v)) -> b)\n\n            let mutable bestCost = System.Double.PositiveInfinity\n            let mutable bestPerm = null\n            let mutable bestSplit = -1\n            let mutable bestlBox = Unchecked.defaultof<Box2d>\n            let mutable bestrBox = Unchecked.defaultof<Box2d>\n\n\n            for dim in 0 .. 1 do\n                let getter =\n                    match dim with\n                    | 0 -> fun (v : V2d) -> v.X\n                    | _ -> fun (v : V2d) -> v.Y\n                let mutable lBoxes = Array.zeroCreate elements.Count\n                let mutable rBoxes = Array.zeroCreate elements.Count\n\n                let perm = bounds.CreatePermutationQuickSortAscending(fun (b : Box2d) -> getter b.Center)\n\n                let mutable last = bounds.[perm.[0]]\n                lBoxes.[0] <- last\n                for i in 1 .. perm.Length - 1 do\n                    let b = bounds.[perm.[i]].Union(last)\n                    lBoxes.[i] <- b //Box3d.Union(last, b)\n                    last <- b\n\n                let mutable i = perm.Length-1\n                let mutable last = Box2d.Invalid\n                while i >= 0 do\n                    let b = bounds.[perm.[i]].Union(last)\n                    rBoxes.[i] <- b\n                    last <- b\n                    i <- i - 1\n\n\n                for lCnt in 1 .. perm.Length - 1 do\n                    let rCnt = perm.Length - lCnt\n                    let lBox = lBoxes.[lCnt-1]\n                    let rBox = rBoxes.[lCnt]\n\n                    let c = cost invArea lBox lCnt rBox rCnt\n                    if c < bestCost then\n                        bestCost <- c\n                        bestPerm <- perm\n                        bestSplit <- lCnt\n                        bestlBox <- lBox\n                        bestrBox <- rBox\n\n            if bestCost < 1.0 then\n                let lCnt = bestSplit\n                let rCnt = arr.Length - lCnt\n\n                let left = Array.zeroCreate lCnt\n                let right = Array.zeroCreate rCnt\n\n                let mutable i = 0\n                for li in 0 .. lCnt - 1 do\n                    left.[li] <- arr.[bestPerm.[i]]\n                    i <- i + 1\n\n                for ri in 0 .. rCnt - 1 do\n                    right.[ri] <- arr.[bestPerm.[i]]\n                    i <- i + 1\n\n                Some (bestCost, bestlBox, HashMap.ofArrayV left, bestrBox, HashMap.ofArrayV right)\n            else\n                None\n\n    let rec build (limit : int) (bounds : Box2d) (elements : HashMap<'K, struct(Box2d * 'V)>) =\n        if elements.Count <= 0 then\n            failwith \"empty\"\n\n        elif elements.Count <= limit then\n            Leaf(0, bounds, elements)\n\n        else\n            let bv = 1.0 / bounds.Area\n            match split bv elements with\n            | Some (cost, lBox, lElements, rBox, rElements) ->\n                let l = build limit lBox lElements\n                let r = build limit rBox rElements\n                Node(cost, elements.Count, bounds, l, r)\n            | None ->\n                //Log.warn \"bad split %d\" elements.Count\n                Leaf(elements.Count, bounds, elements)\n\n    let rec getIntersecting (tests : ref<int>) (query : Box2d) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            tests := !tests + 1\n            if bounds.Intersects(query, 1E-20) then\n                tests := !tests + values.Count\n                values |> HashMap.filter (fun _ struct(b,_) -> b.Intersects query)\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            tests := !tests + 1\n            if bounds.Intersects(query, 1E-20) then\n                let l = getIntersecting tests query l\n                let r = getIntersecting tests query r\n                HashMap.union l r\n            else\n                HashMap.empty\n\n    let rec getIntersectingFilter (query : Box2d) (filter : OptimizedClosures.FSharpFunc<'K, Box2d, 'V, option<'T>>) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            if bounds.Intersects(query, 1E-20) then\n                values |> HashMap.choose (fun k struct(b,v) -> if b.Intersects query then filter.Invoke(k, b, v) else None)\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            if bounds.Intersects(query, 1E-20) then\n                let l = getIntersectingFilter query filter l\n                let r = getIntersectingFilter query filter r\n                HashMap.union l r\n            else\n                HashMap.empty\n\n    let rec toSeq (n : BvhNode2d<'K, 'V>) =\n        match n with\n        | Leaf(_,_,vs) -> vs.ToSeqV()\n        | Node(_,_,_,l,r) -> Seq.append (toSeq l) (toSeq r)\n\n    let rec add (limit : int) (key : 'K) (bounds : Box2d) (value : 'V) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(overflowCount, b, values) ->\n            match HashMap.tryFindV key values with\n            | ValueSome (struct(ob, _ov)) ->\n                // replace\n                if bounds.Contains ob then\n                    Leaf(overflowCount, b, HashMap.add key (struct(bounds, value)) values)\n                else\n                    let mutable bb = bounds\n                    for struct(_,struct(b,_)) in values.ToSeqV() do\n                        bb.ExtendBy b\n                    Leaf(overflowCount, bb, HashMap.add key (struct(bounds, value)) values)\n            | _ ->\n                // add\n                let b = b.ExtendedBy bounds\n                let vs = HashMap.add key (struct(bounds, value)) values\n\n                if vs.Count >= 2 * overflowCount && vs.Count > limit then\n                    build limit b vs\n                else\n                    Leaf(overflowCount, b, vs)\n\n        | Node(bestCost, _, b, l, r) ->\n            let nb = Box.Union(b, bounds)\n\n            let lb = getBounds l\n            let rb = getBounds r\n            let lc = count l\n            let rc = count r\n            let invVol = 1.0 / nb.Area\n            let lCost = cost invVol (Box.Union(lb, bounds)) (1 + lc) rb rc\n            let rCost = cost invVol lb lc (Box.Union(rb, bounds)) (1 + rc)\n\n            if lCost < rCost then\n                // add left\n                if lCost > 2.0 * bestCost then\n                    toSeq node\n                    |> HashMap.ofSeqV\n                    |> HashMap.add key (struct(bounds, value))\n                    |> build limit nb\n                else\n                    let l = add limit key bounds value l\n                    let lb = getBounds l\n                    let lc = count l\n                    let cc = cost invVol lb lc rb rc\n                    let nb = Box.Union(lb, rb)\n                    Node(min bestCost cc, lc + rc, nb, l, r)\n            else\n                if rCost > 2.0 * bestCost then\n                    toSeq node\n                    |> HashMap.ofSeqV\n                    |> HashMap.add key (struct(bounds, value))\n                    |> build limit nb\n                else\n                    let r = add limit key bounds value r\n                    let rb = getBounds r\n                    let rc = count r\n                    let cc = cost invVol lb lc rb rc\n                    let nb = Box.Union(lb, rb)\n                    Node(min bestCost cc, lc + rc, nb, l, r)\n\n    let rec tryRemove (limit : int) (key : 'K) (bounds : Box2d) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(overflowCount, b, values) ->\n            if b.Intersects bounds then\n                match HashMap.tryRemove key values with\n                | Some (struct(_,v), n) ->\n                    if n.Count > 0 then\n                        let mutable bb = Box2d.Invalid\n                        for struct(_,struct(b,_)) in n.ToSeqV() do\n                            bb.ExtendBy b\n                        Some(v, Some (Leaf(max 0 (overflowCount - 1), bb, n)))\n                    else\n                        Some (v, None)\n                | None ->\n                    None\n            else\n                None\n\n        | Node(bestCost, _, b, l, r) ->\n            if b.Intersects bounds then\n                match tryRemove limit key bounds l with\n                | Some (v, l) ->\n                    match l with\n                    | Some l ->\n                        let lc = count l\n                        let rc = count r\n                        let lb = getBounds l\n                        let rb = getBounds r\n                        let o = Box.Union(lb, rb)\n                        let cnt = lc + rc\n                        if cnt <= limit then\n                            let values = Seq.append (toSeq l) (toSeq r) |> HashMap.ofSeqV\n                            Some (v, Some (Leaf(0, o, values)))\n                        else\n                            let cost = cost (1.0 / o.Area) lb lc rb rc\n                            Some (v, Some (Node(min cost bestCost, cnt, o, l, r)))\n                    | None ->\n                        Some (v, Some r)\n                | None ->\n                    match tryRemove limit key bounds r with\n                    | Some(v,r) ->\n                        match r with\n                        | Some r ->\n                            let lc = count l\n                            let rc = count r\n                            let lb = getBounds l\n                            let rb = getBounds r\n                            let o = Box.Union(lb, rb)\n                            let cnt = lc + rc\n                            if cnt <= limit then\n                                let values = Seq.append (toSeq l) (toSeq r) |> HashMap.ofSeqV\n                                Some (v, Some (Leaf(0, o, values)))\n                            else\n                                let cost = cost (1.0 / o.Area) lb lc rb rc\n                                Some (v, Some (Node(min cost bestCost, cnt, o, l, r)))\n                        | None ->\n                            Some (v, Some l)\n                    | None ->\n                        None\n            else\n                None\n\n    let remove (limit : int) (key : 'K) (bounds : Box2d) (node : BvhNode2d<'K, 'V>) =\n        match tryRemove limit key bounds node with\n        | Some (_, rest) -> rest\n        | None -> Some node\n\ntype BvhTree2d<'K, 'V> private(limit : int, root : option<BvhNode2d<'K, 'V>>, keyBounds : HashMap<'K, Box2d>) =\n    member internal x.Root = root\n\n    member x.Count =\n        match root with\n        | Some r -> BvhNode2d.count r\n        | None -> 0\n\n    member x.Add(key : 'K, bounds : Box2d, value : 'V) =\n        if bounds.IsValid then\n            let keyBounds = HashMap.add key bounds keyBounds\n            let newRoot =\n                match root with\n                | Some r -> BvhNode2d.add limit key bounds value r\n                | None -> BvhNode2d.Leaf(0, bounds, HashMap.single key (struct(bounds, value)))\n            BvhTree2d(limit, Some newRoot, keyBounds)\n        else\n            x\n\n    member x.Remove(key : 'K) =\n        match HashMap.tryRemove key keyBounds with\n        | Some (bounds, keyBounds) ->\n            let newRoot =\n                match root with\n                | Some r -> BvhNode2d.remove limit key bounds r\n                | None -> None\n            BvhTree2d(limit, newRoot, keyBounds)\n        | None ->\n            x\n\n    member x.TryRemove(key : 'K) =\n        match HashMap.tryRemove key keyBounds with\n        | Some (bounds, keyBounds) ->\n            let newRoot =\n                match root with\n                | Some r -> BvhNode2d.tryRemove limit key bounds r\n                | None -> None\n            match newRoot with\n            | Some (v, newRoot) ->\n                Some (v, BvhTree2d(limit, newRoot, keyBounds))\n            | None ->\n                None\n        | None ->\n            None\n\n    member x.GetIntersecting(query : Box2d) =\n        match root with\n        | Some r ->\n            BvhNode2d.getIntersecting (ref 0) query r\n        | None ->\n            HashMap.empty\n\n    member x.GetIntersecting(query : Box2d, filter : 'K -> Box2d -> 'V -> option<'T>) =\n        match root with\n        | Some r ->\n            let opt = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt filter\n            BvhNode2d.getIntersectingFilter query opt r\n        | None ->\n            HashMap.empty\n\n    member x.ToSeq() =\n        match root with\n        | Some root -> BvhNode2d.toSeq root |> Seq.map (fun struct(k,struct(b,v)) -> k,b,v)\n        | None -> Seq.empty\n\n    member x.ToList() =\n        x.ToSeq() |> Seq.toList\n\n    member x.ToArray() =\n        match root with\n        | Some root ->\n            let arr = Array.zeroCreate x.Count\n            let mutable i = 0\n            for struct(k,struct(b,v)) in BvhNode2d.toSeq root do\n                arr.[i] <- (k,b,v)\n            arr\n        | None ->\n            [||]\n\n    static member Build(limit : int, elements : seq<'K * Box2d * 'V>) =\n        let mutable bb = Box2d.Invalid\n        let mutable all = HashMap.empty\n        let mutable keyBounds = HashMap.empty\n        for (k, b, v) in elements do\n            bb.ExtendBy b\n            all <- HashMap.add k (struct(b, v)) all\n            keyBounds <- HashMap.add k b keyBounds\n\n        if all.Count > 0 then\n            let root = BvhNode2d.build limit bb all\n            BvhTree2d(limit, Some root, keyBounds)\n        else\n            BvhTree2d(limit, None, HashMap.empty)\n\n    static member Empty(limit : int) = BvhTree2d<'K, 'V>(limit, None, HashMap.empty)\n\n\n\nmodule BvhTree2d =\n\n    let splitLimit = 24\n\n    [<GeneralizableValue>]\n    let empty<'K, 'V> : BvhTree2d<'K, 'V> = BvhTree2d.Empty(splitLimit)\n\n    let inline add (key : 'K) (bounds : Box2d) (value : 'V) (t : BvhTree2d<'K, 'V>) = t.Add(key, bounds, value)\n    let inline remove (key : 'K) (t : BvhTree2d<'K, 'V>) = t.Remove(key)\n    let inline tryRemove (key : 'K) (t : BvhTree2d<'K, 'V>) = t.TryRemove(key)\n\n    let inline getIntersecting (query : Box2d) (tree : BvhTree2d<'K, 'V>) = tree.GetIntersecting query\n\n    let inline ofSeq (elements : seq<'K * Box2d * 'V>)= BvhTree2d.Build(splitLimit, elements)\n    let inline ofList (elements : list<'K * Box2d * 'V>)= BvhTree2d.Build(splitLimit, elements)\n    let inline ofArray (elements : array<'K * Box2d * 'V>)= BvhTree2d.Build(splitLimit, elements)\n\n    let inline toSeq (tree : BvhTree2d<'K, 'V>)= tree.ToSeq()\n    let inline toList (tree : BvhTree2d<'K, 'V>)= tree.ToList()\n    let inline toArray (tree : BvhTree2d<'K, 'V>)= tree.ToArray()\n\n    let union (l : BvhTree2d<'K, 'V>) (r : BvhTree2d<'K, 'V>) =\n        let mutable l = l\n        for (k,b,v) in toSeq r do\n            l <- l.Add(k,b,v)\n        l\n\n\nmodule BvhTest =\n\n    let ofSeq (limit : int) (bounds : seq<Box2d>) =\n        BvhTree2d.Build(limit, bounds |> Seq.mapi (fun i b -> i,b,b))\n\n    let ofSeqStupid (limit : int) (bounds : seq<Box2d>) =\n        let mutable t = BvhTree2d.Empty limit\n        for (i, b) in Seq.indexed bounds do\n            t <- t.Add(i, b, b)\n        t\n\n    let run() =\n        let randBounds = Box2d(-V2d.II, V2d.II)\n        let size = 0.02\n        let rand = RandomSystem()\n\n        let randomBox() =\n            Box2d.FromCenterAndSize(\n                rand.UniformV2d(randBounds),\n                V2d.II * rand.UniformDouble() * size\n            )\n\n        let limit = 24\n        for cnt in [1024; 65536] do\n            Log.start \"%d boxes\" cnt\n            let boxes =\n                Array.init cnt (fun _ -> randomBox())\n\n            let bruteForce (q : Box2d) =\n                let mutable res = HashSet.empty\n                for i in 0 .. boxes.Length - 1 do\n                    let b = boxes.[i]\n                    if b.Intersects q then\n                        res <- HashSet.add i res\n                res\n\n            let sw = System.Diagnostics.Stopwatch.StartNew()\n            let bvh = ofSeq limit boxes\n            sw.Stop()\n            Log.line \"build took: %A\" sw.MicroTime\n\n            sw.Restart()\n            let bvhs = ofSeqStupid limit boxes\n            sw.Stop()\n            Log.line \"incr took:  %A\" sw.MicroTime\n\n            sw.Restart()\n            let mutable r = bvhs\n            for i in 0 .. bvhs.Count - 1 do\n                r <- r.Remove i\n            sw.Stop()\n            Log.line \"clear took:  %A\" sw.MicroTime\n\n            let swb = System.Diagnostics.Stopwatch()\n            let swi = System.Diagnostics.Stopwatch()\n            let swf = System.Diagnostics.Stopwatch()\n\n            let iter = 100000\n            for i in 1 .. iter do\n                let q = randomBox()\n\n                swf.Start()\n                let reference = bruteForce q\n                swf.Stop()\n\n\n                swb.Start()\n                let build = bvh.GetIntersecting q\n                swb.Stop()\n\n                swi.Start()\n                let incr = bvhs.GetIntersecting q\n                swi.Stop()\n                let build = HashMap.keys build\n                let incr = HashMap.keys incr\n\n                let delta = HashSet.computeDelta build reference\n                if not (HashSetDelta.isEmpty delta) then\n                    Log.start \"build error\"\n                    Log.line \"result: [%s]\" (build |> Seq.sort |> Seq.map string |> String.concat \"; \")\n                    Log.line \"ref:    [%s]\" (reference |> Seq.sort |> Seq.map string |> String.concat \"; \")\n                    for op in delta do\n                        match op with\n                        | Add(_,i) -> Report.WarnNoPrefix(\"missing {0}\", i)\n                        | Rem(_,i) -> Report.WarnNoPrefix(\"wrong {0}\", i)\n                    Log.stop()\n\n                let delta = HashSet.computeDelta incr reference\n                if not (HashSetDelta.isEmpty delta) then\n                    Log.start \"incr error\"\n                    Log.line \"result: [%s]\" (build |> Seq.sort |> Seq.map string |> String.concat \"; \")\n                    Log.line \"ref:    [%s]\" (reference |> Seq.sort |> Seq.map string |> String.concat \"; \")\n                    for op in delta do\n                        match op with\n                        | Add(_,i) -> Report.WarnNoPrefix(\"missing {0}\", i)\n                        | Rem(_,i) -> Report.WarnNoPrefix(\"wrong {0}\", i)\n                    Log.stop()\n\n            Log.line \"force: %A\" (swf.MicroTime / iter)\n            Log.line \"build: %A\" (swb.MicroTime / iter)\n            Log.line \"incr:  %A\" (swi.MicroTime / iter)\n\n            Log.stop()\n\n\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.Fonts/Font.fs",
    "content": "﻿namespace Aardvark.Base.Fonts\n\nopen System\nopen System.IO.Compression\nopen System.Runtime.CompilerServices\nopen System.Runtime.InteropServices\nopen Aardvark.Base\n\n[<Flags>]\ntype FontStyle =\n    | Regular = 0\n    | Bold = 1\n    | Italic = 2\n    | BoldItalic = 3\n\nmodule internal FontStyle =\n\n    let toWeightAndItalic (style: FontStyle) =\n        let weight =\n            match style with\n            | FontStyle.Bold | FontStyle.BoldItalic -> 700\n            | _ -> 400\n\n        let italic =\n            match style with\n            | FontStyle.Italic | FontStyle.BoldItalic -> true\n            | _ -> false\n\n        struct (weight, italic)\n\ntype Shape(path : Path, windingRule : WindingRule) =\n\n    static let quad =\n        Shape(\n            Path.ofList [\n                PathSegment.line V2d.OO V2d.OI\n                PathSegment.line V2d.OI V2d.II\n                PathSegment.line V2d.II V2d.IO\n                PathSegment.line V2d.IO V2d.OO\n            ],\n            WindingRule.NonZero\n        )\n\n    let mutable geometry = ValueNone\n\n    static member Quad = quad\n\n    member x.Path = path\n\n    member x.Geometry =\n        match geometry with\n        | ValueSome g -> g\n        | ValueNone ->\n            let g = Path.toGeometry windingRule path\n            geometry <- ValueSome g\n            g\n\n    new(path : Path) = Shape(path, WindingRule.NonZero)\n\nopen Typography.OpenFont\n\n[<AutoOpen>]\nmodule private Typography =\n\n    module GlyphPoint =\n        let toV2d (scale : float) (p : GlyphPointF) = scale * V2d(p.X, p.Y)\n\n    module Bounds =\n        let toBox2d (scale : float) (b : Bounds) =\n            Box2d(scale * float b.XMin, scale * float b.YMin, scale * float b.XMax, scale * float b.YMax)\n\n    module Path =\n        type PathTranslator(scale : float) =\n            let mutable start : Option<V2d> = None\n            let mutable pos : Option<V2d> = None\n            let mutable bb = Box2d.Invalid\n            let list = System.Collections.Generic.List<PathSegment>()\n\n            member x.ToArray() = list.ToArray()\n\n            member x.Bounds = (Box2d.Invalid, list) ||> Seq.fold (fun b s -> Box.Union(b, PathSegment.bounds s))\n\n            interface IGlyphTranslator with\n                member x.BeginRead(_) = ()\n                member x.EndRead() = ()\n\n                member x.CloseContour() =\n                    match start, pos with\n                        | Some s, Some p ->\n                            if not (Fun.ApproximateEquals(p, s, bb.Size.NormMax * 1E-8)) then\n                                match PathSegment.tryLine p s with\n                                | Some l -> list.Add l\n                                | None -> ()\n                        | _ ->\n                            ()\n                    start <- None\n                    pos <- None\n                    ()\n\n                member x.MoveTo(xa,ya) =\n                    let pa = V2d(xa, ya) * scale\n                    bb.ExtendBy pa\n                    pos <- Some pa\n                    match start with\n                        | None -> start <- Some pa\n                        | _ -> ()\n\n                member x.LineTo(xa, ya) =\n                    match pos with\n                        | Some p0 ->\n                            let pa = V2d(xa, ya) * scale\n                            bb.ExtendBy pa\n                            match PathSegment.tryLine p0 pa with\n                            | Some l -> list.Add(l)\n                            | None -> ()\n                            pos <- Some pa\n                        | None ->\n                            failwith \"asdasd\"\n                    ()\n                member x.Curve3(xa, ya, xb, yb) =\n                    match pos with\n                        | Some p0 ->\n                            let pa = V2d(xa, ya) * scale\n                            let pb = V2d(xb, yb) * scale\n                            bb.ExtendBy pa\n                            bb.ExtendBy pb\n                            match PathSegment.tryBezier2 p0 pa pb with\n                            | Some b -> list.Add b\n                            | None -> ()\n                            pos <- Some pb\n                        | None ->\n                            ()\n                            //failwith \"asdasd\"\n\n                member x.Curve4(xa, ya, xb, yb, xc, yc) =\n                    match pos with\n                        | Some p0 ->\n                            let pa = V2d(xa, ya) * scale\n                            let pb = V2d(xb, yb) * scale\n                            let pc = V2d(xc, yc) * scale\n                            bb.ExtendBy pa\n                            bb.ExtendBy pb\n                            bb.ExtendBy pc\n\n                            match PathSegment.tryBezier3 p0 pa pb pc with\n                            | Some b -> list.Add b\n                            | None -> ()\n                            pos <- Some pc\n                        | None ->\n                            failwith \"asdasd\"\n\n        let ofGlyph (scale : float) (g : Glyph) =\n            if g.HasGlyphInstructions then\n                let tx = PathTranslator(scale)\n                tx.Read(g.GlyphPoints, g.EndPoints)\n                let segments = tx.ToArray()\n                { bounds = tx.Bounds; outline = segments }\n            elif g.IsCffGlyph then\n                let data = g.GetCff1GlyphData()\n                let tx = PathTranslator(scale / 1000.0)\n                let e : Typography.OpenFont.CFF.CffEvaluationEngine = Typography.OpenFont.CFF.CffEvaluationEngine()\n                e.Run(tx, g.GetOwnerCff(), data, 1000.0f)\n                let segments = tx.ToArray()\n                { bounds = tx.Bounds; outline = segments }\n            else\n                { bounds = Bounds.toBox2d scale g.Bounds; outline = [||] }\n                //[|\n                //    let mutable i = 0\n                //    while i < g.GlyphPoints.Length do\n                //        let mutable o = i + 1\n                //        while o < g.GlyphPoints.Length && not g.GlyphPoints.[o].OnCurve do\n                //            o <- o + 1\n\n                //        if o < g.GlyphPoints.Length then\n                //            let len = 1 + o - i\n                //            match len with\n                //                | 2 ->\n                //                    let p0  = g.GlyphPoints.[i] |> GlyphPoint.toV2d scale\n                //                    let p1  = g.GlyphPoints.[o] |> GlyphPoint.toV2d scale\n                //                    yield PathSegment.line p0 p1\n                //                | 3 ->\n                //                    let p0  = g.GlyphPoints.[i] |> GlyphPoint.toV2d scale\n                //                    let a   = g.GlyphPoints.[i+1] |> GlyphPoint.toV2d scale\n                //                    let p1  = g.GlyphPoints.[o] |> GlyphPoint.toV2d scale\n                //                    yield PathSegment.bezier2 p0 a p1\n                //                | 4 ->\n                //                    let p0  = g.GlyphPoints.[i] |> GlyphPoint.toV2d scale\n                //                    let a   = g.GlyphPoints.[i+1] |> GlyphPoint.toV2d scale\n                //                    let b   = g.GlyphPoints.[i+2] |> GlyphPoint.toV2d scale\n                //                    let p1  = g.GlyphPoints.[o] |> GlyphPoint.toV2d scale\n                //                    yield PathSegment.bezier3 p0 a b p1\n\n                //                | _ ->\n                //                    failwithf \"invalid path segment: %A\" len\n\n                //        i <- o\n                //|]\n\n\n\n\n\n[<Struct; StructuredFormatDisplay(\"{AsString}\")>]\ntype CodePoint(value : int) =\n    member x.Value = value\n\n    static member Invalid = CodePoint(-1)\n\n    member private x.AsString = x.ToString()\n\n    override x.ToString() =\n        if value < 0 then \"invalid\"\n        else sprintf \"U+%X\" value\n\n    member x.String =\n        if value &&& 0x10000 = 0 then\n            System.String(char value, 1)\n        else\n            let value = value - 65536\n            let c0 = char (0xD800 ||| ((value >>> 10)))\n            let c1 = char (0xDC00 ||| (value &&& 0x3FF))\n            System.String [| c0; c1 |]\n\n    new (c : char) =\n        if (uint16 c &&& 0xF800us) = 0xD800us then CodePoint(-1)\n        else CodePoint(int c)\n\n[<AbstractClass; Sealed; Extension>]\ntype CodePointStringExtensions private() =\n\n    [<Extension>]\n    static member ToCodePointArray(str : string) =\n        if str.Length > 0 then\n            let mutable arr : CodePoint[] = Array.zeroCreate str.Length\n            let mutable oi = 0\n            let mutable c0 = str.[0] |> uint16\n            let mutable lastSurrogate = (c0 &&& 0xF800us) = 0xD800us\n            if lastSurrogate then\n                c0 <- c0 &&& 0x27FFus\n            else\n                arr.[oi] <- CodePoint(int c0)\n                oi <- oi + 1\n\n            for ii in 1 .. str.Length - 1 do\n                let c1 = str.[ii] |> uint16\n                if lastSurrogate then\n                    let v1 = c1 &&& 0x23FFus\n                    let code = 0x10000 ||| (int c0 <<< 10) ||| int v1\n                    arr.[oi] <- CodePoint(code)\n                    oi <- oi + 1\n                    lastSurrogate <- false\n                elif (c1 &&& 0xF800us) = 0xD800us then\n                    c0 <- c1 &&& 0x27FFus\n                    lastSurrogate <- true\n                else\n                    arr.[oi] <- CodePoint(int c1)\n                    oi <- oi + 1\n\n            if arr.Length > oi then System.Array.Resize(&arr, oi)\n            arr\n        else\n            [||]\n\n    [<Extension>]\n    static member GetString(codepoints : CodePoint[]) =\n        let sb = System.Text.StringBuilder()\n\n        for c in codepoints do\n            let value = c.Value\n            if value &&& 0x10000 = 0 then\n                sb.Append(char value) |> ignore\n            else\n                let value = value - 65536\n                let c0 = char (0xD800 ||| ((value >>> 10)))\n                let c1 = char (0xDC00 ||| (value &&& 0x3FF))\n                sb.Append c0 |> ignore\n                sb.Append c1 |> ignore\n\n        sb.ToString()\n\ntype Glyph internal(g : Typography.OpenFont.Glyph, isValid : bool, scale : float, advance : float, bearing : float, c : CodePoint) =\n    inherit Shape(Path.ofGlyph scale g, WindingRule.NonZero)\n\n    let widths =\n        let width = float (g.MaxX - g.MinX) * scale\n        V3d(bearing, width, advance - width - bearing)\n\n    member x.CodePoint = c\n    member x.IsValid = isValid\n    member x.Bounds = base.Path.bounds\n\n    member x.Path = base.Path\n    member x.Advance =\n        let sizes = widths\n        sizes.X + sizes.Y + sizes.Z\n\n    member x.Before = -0.1666\n\n\n\ntype private FontImpl internal(f : Typeface, familyName : string, weight : int, italic : bool) =\n    let scale = f.CalculateScaleToPixel 1.0f |> float\n\n    let glyphCache = Dict<CodePoint, Glyph>()\n\n    let lineHeight = float (f.Ascender - f.Descender + f.LineGap) * scale\n\n    let spacing =\n        let idx = f.GetGlyphIndex(int ' ') |> int\n\n        if idx >= 0 && idx < f.Glyphs.Length then\n            let g = f.Glyphs.[idx]\n            if g.HasOriginalAdvancedWidth then\n                float g.OriginalAdvanceWidth  * scale\n            else\n                let a = f.GetHAdvanceWidthFromGlyphIndex(uint16 idx)\n                float a * scale\n        else\n            float (f.GetAdvanceWidth(idx)) * scale\n\n    // https://docs.microsoft.com/en-us/windows/desktop/gdi/string-widths-and-heights\n    let ascent = float f.Ascender * scale\n    let descent = float -f.Descender * scale\n    let lineGap = float f.LineGap * scale\n    let internalLeading = float ((f.Bounds.YMax - f.Bounds.YMin) - (f.Ascender - f.Descender) - f.LineGap) * scale\n    let externalLeading = lineGap - internalLeading\n\n    static let symbola =\n        lazy (\n            let assembly = typeof<FontImpl>.Assembly\n            FontImpl(assembly, \"Symbola.zip\", \"Symbola.ttf\", 400, false)\n        )\n\n    let get (c : CodePoint) (self : FontImpl) =\n        lock glyphCache (fun () ->\n            glyphCache.GetOrCreate(c, fun c ->\n                let idx = f.GetGlyphIndex(c.Value)\n                if idx = 0us && c.Value > 65535 && symbola.Value <> self then\n                    symbola.Value.GetGlyph c\n                else\n                    let glyph = f.Glyphs.[int idx]\n\n                    let advance =\n                        if glyph.HasOriginalAdvancedWidth then\n                            float glyph.OriginalAdvanceWidth  * scale\n                        else\n                            let a = f.GetHAdvanceWidthFromGlyphIndex(idx)\n                            float a * scale\n\n                    let bearing =\n                        let a = f.GetHFrontSideBearingFromGlyphIndex(idx)\n                        float a * scale\n                    Glyph(glyph, idx > 0us, scale, advance, bearing, c)\n            )\n        )\n\n    static member Symbola = symbola.Value\n\n    member x.Family = familyName\n    member x.LineHeight = lineHeight\n    member x.Descent = descent\n    member x.Ascent = ascent\n    member x.LineGap = lineGap\n    member x.InternalLeading = internalLeading\n    member x.ExternalLeading = externalLeading\n    member x.Weight = weight\n    member x.Italic = italic\n\n    member x.Style =\n        if weight >= 700 then\n            if italic then FontStyle.BoldItalic\n            else FontStyle.Bold\n        else\n            if italic then FontStyle.Italic\n            else FontStyle.Regular\n\n    member x.Spacing = spacing\n\n    member x.GetGlyph(c : CodePoint) =\n        get c x\n\n    member x.GetKerning(l : CodePoint, r : CodePoint) =\n        let l = f.GetGlyphIndex (l.Value)\n        let r = f.GetGlyphIndex (r.Value)\n        let d = f.GetKernDistance(l, r)\n        float d * scale\n\n    new (file : string, weight : int, italic : bool) =\n        let data = File.readAllBytes file\n        let family = try System.IO.Path.GetFileNameWithoutExtension file with _ -> null\n        FontImpl(data, family, weight, italic)\n\n    new (data : uint8[], family : string, weight : int, italic : bool) =\n        let openStream() =\n            new System.IO.MemoryStream(data) :> System.IO.Stream\n\n        let entry =\n            FontResolver.FontTableEntries.ofStream () openStream\n            |> FontResolver.FontTableEntries.chooseBestEntry weight italic\n\n        let family =\n            if String.IsNullOrEmpty entry.FamilyName then family\n            else entry.FamilyName\n\n        let face = entry |> FontResolver.FontTableEntries.read openStream\n        FontImpl(face, family, entry.Weight, entry.Italic)\n\n    new (assembly : System.Reflection.Assembly, file : string, entryName : string, weight : int, italic : bool) =\n        if isNull assembly then raise <| ArgumentNullException(nameof assembly)\n        let names = assembly.GetManifestResourceNames()\n\n        let resourceName =\n            names\n            |> Array.tryFindV (fun n -> n.EndsWith file)\n            |> ValueOption.defaultWith (fun _ ->\n                raise <| IO.FileNotFoundException($\"Could not find embedded resource with name '{file}' in assembly '{assembly}'.\", file)\n            )\n\n        let fontData =\n            if String.IsNullOrEmpty entryName then\n                use data = assembly.GetManifestResourceStream resourceName\n                Stream.readAllBytes data\n            else\n                use zip =\n                    let s = assembly.GetManifestResourceStream resourceName\n                    new ZipArchive(s, ZipArchiveMode.Read)\n\n                let entry = zip.GetEntry entryName\n                if isNull entry then\n                    raise <| IO.FileNotFoundException($\"Could not find entry with name '{entryName}' in ZIP archive '{file}' in assembly '{assembly}'.\", entryName)\n\n                use data = entry.Open()\n                Stream.readAllBytes data\n\n        let family =\n            let path = if String.IsNullOrEmpty entryName then file else entryName\n            try System.IO.Path.GetFileNameWithoutExtension path with _ -> null\n\n        FontImpl(fontData, family, weight, italic)\n\n\ntype Font private(impl : FontImpl) =\n\n    static let symbola =\n        lazy (\n            let impl = FontImpl.Symbola\n            Font impl\n        )\n\n    static let systemTable = System.Collections.Concurrent.ConcurrentDictionary<string * int * bool, FontImpl>()\n    static let fileTable = System.Collections.Concurrent.ConcurrentDictionary<string, FontImpl>()\n\n    static member Symbola = symbola.Value\n\n    member x.Family = impl.Family\n    member x.LineHeight = impl.LineHeight\n    member x.Descent = impl.Descent\n    member x.Ascent = impl.Ascent\n    member x.LineGap = impl.LineGap\n    member x.InternalLeading = impl.InternalLeading\n    member x.ExternalLeading = impl.ExternalLeading\n    member x.Style = impl.Style\n    member x.Weight = impl.Weight\n    member x.Italic = impl.Italic\n    member x.Spacing = impl.Spacing\n    member x.GetGlyph(c : CodePoint) = impl.GetGlyph(c)\n    member x.GetKerning(l : CodePoint, r : CodePoint) = impl.GetKerning(l,r)\n\n    static member Load(file : string, weight : int, italic : bool) =\n        let impl =\n            fileTable.GetOrAdd(file, fun file ->\n                let impl = FontImpl(file, weight, italic)\n                impl\n            )\n        Font(impl)\n\n    static member Load(file : string) =\n        Font.Load(file, 400, false)\n\n    static member Load(file : string, style : FontStyle) =\n        let struct (weight, italic) = FontStyle.toWeightAndItalic style\n        Font.Load(file, weight, italic)\n\n    /// <summary>\n    /// Loads a font embedded in an assembly as a ZIP archive.\n    /// The name of the ZIP archive does not have to be exact; the first embedded resource that ends with the given name is used.\n    /// </summary>\n    /// <param name=\"assembly\">Assembly to load the embedded font from.</param>\n    /// <param name=\"zipArchive\">Name of the embedded ZIP archive.</param>\n    /// <param name=\"entryName\">Name of the ZIP entry containing the font file.</param>\n    /// <param name=\"weight\">Weight of the font to load.</param>\n    /// <param name=\"italic\">Indicates whether italic variant is desired.</param>\n    static member LoadFromAssembly(assembly: System.Reflection.Assembly, zipArchive: string, entryName: string,\n                                   [<Optional; DefaultParameterValue(400)>] weight: int,\n                                   [<Optional; DefaultParameterValue(false)>] italic: bool) =\n        let impl = FontImpl(assembly, zipArchive, entryName, weight, italic)\n        Font(impl)\n\n    /// <summary>\n    /// Loads a font embedded in the calling assembly as a ZIP archive.\n    /// The name of the ZIP archive does not have to be exact; the first embedded resource that ends with the given name is used.\n    /// </summary>\n    /// <param name=\"zipArchive\">Name of the embedded ZIP archive.</param>\n    /// <param name=\"entryName\">Name of the ZIP entry containing the font file.</param>\n    /// <param name=\"weight\">Weight of the font to load.</param>\n    /// <param name=\"italic\">Indicates whether italic variant is desired.</param>\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member LoadFromAssembly(zipArchive: string, entryName: string,\n                                   [<Optional; DefaultParameterValue(400)>] weight: int,\n                                   [<Optional; DefaultParameterValue(false)>] italic: bool) =\n        let assembly = System.Reflection.Assembly.GetCallingAssembly()\n        Font.LoadFromAssembly(assembly, zipArchive, entryName, weight, italic)\n\n    /// <summary>\n    /// Loads a font embedded in an assembly.\n    /// The name of the font file does not have to be exact; the first embedded resource that ends with the given name is used.\n    /// </summary>\n    /// <param name=\"assembly\">Assembly to load the embedded font from.</param>\n    /// <param name=\"file\">Name of the embedded font file.</param>\n    /// <param name=\"weight\">Weight of the font to load.</param>\n    /// <param name=\"italic\">Indicates whether italic variant is desired.</param>\n    static member LoadFromAssembly(assembly: System.Reflection.Assembly, file: string,\n                                   [<Optional; DefaultParameterValue(400)>] weight: int,\n                                   [<Optional; DefaultParameterValue(false)>] italic: bool) =\n        Font.LoadFromAssembly(assembly, file, null, weight, italic)\n\n    /// <summary>\n    /// Loads a font embedded in the calling assembly.\n    /// The name of the font file does not have to be exact; the first embedded resource that ends with the given name is used.\n    /// </summary>\n    /// <param name=\"file\">Name of the embedded font file.</param>\n    /// <param name=\"weight\">Weight of the font to load.</param>\n    /// <param name=\"italic\">Indicates whether italic variant is desired.</param>\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member LoadFromAssembly(file: string,\n                                   [<Optional; DefaultParameterValue(400)>] weight: int,\n                                   [<Optional; DefaultParameterValue(false)>] italic: bool) =\n        let assembly = System.Reflection.Assembly.GetCallingAssembly()\n        Font.LoadFromAssembly(assembly, file, null, weight, italic)\n\n    /// <summary>\n    /// Loads a font embedded in an assembly as a ZIP archive.\n    /// The name of the ZIP archive does not have to be exact; the first embedded resource that ends with the given name is used.\n    /// </summary>\n    /// <param name=\"assembly\">Assembly to load the embedded font from.</param>\n    /// <param name=\"zipArchive\">Name of the embedded ZIP archive.</param>\n    /// <param name=\"entryName\">Name of the ZIP entry containing the font file.</param>\n    /// <param name=\"style\">Variant of the font to load.</param>\n    static member LoadFromAssembly(assembly: System.Reflection.Assembly, zipArchive: string, entryName: string, style: FontStyle) =\n        let struct (weight, italic) = FontStyle.toWeightAndItalic style\n        Font.LoadFromAssembly(assembly, zipArchive, entryName, weight, italic)\n\n    /// <summary>\n    /// Loads a font embedded in the calling assembly as a ZIP archive.\n    /// The name of the ZIP archive does not have to be exact; the first embedded resource that ends with the given name is used.\n    /// </summary>\n    /// <param name=\"zipArchive\">Name of the embedded ZIP archive.</param>\n    /// <param name=\"entryName\">Name of the ZIP entry containing the font file.</param>\n    /// <param name=\"style\">Variant of the font to load.</param>\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member LoadFromAssembly(zipArchive: string, entryName: string, style: FontStyle) =\n        let assembly = System.Reflection.Assembly.GetCallingAssembly()\n        Font.LoadFromAssembly(assembly, zipArchive, entryName, style)\n\n    /// <summary>\n    /// Loads a font embedded in an assembly.\n    /// The name of the font file does not have to be exact; the first embedded resource that ends with the given name is used.\n    /// </summary>\n    /// <param name=\"assembly\">Assembly to load the embedded font from.</param>\n    /// <param name=\"file\">Name of the embedded font file.</param>\n    /// <param name=\"style\">Variant of the font to load.</param>\n    static member LoadFromAssembly(assembly: System.Reflection.Assembly, file: string, style: FontStyle) =\n        Font.LoadFromAssembly(assembly, file, null, style)\n\n    /// <summary>\n    /// Loads a font embedded in the calling assembly.\n    /// The name of the font file does not have to be exact; the first embedded resource that ends with the given name is used.\n    /// </summary>\n    /// <param name=\"file\">Name of the embedded font file.</param>\n    /// <param name=\"style\">Variant of the font to load.</param>\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member LoadFromAssembly(file: string, style: FontStyle) =\n        let assembly = System.Reflection.Assembly.GetCallingAssembly()\n        Font.LoadFromAssembly(assembly, file, null, style)\n\n    new(stream : System.IO.Stream, weight : int, italic : bool) =\n        let data = Stream.readAllBytes stream\n        let impl = FontImpl(data, null, weight, italic)\n        Font(impl)\n\n    new(stream : System.IO.Stream, style : FontStyle) =\n        let struct (weight, italic) = FontStyle.toWeightAndItalic style\n        Font(stream, weight, italic)\n\n    new(stream : System.IO.Stream) =\n        Font(stream, 400, false)\n\n    new(family : string, weight : int, italic : bool) =\n        let impl =\n            systemTable.GetOrAdd((family, weight, italic), fun (family, weight, italic) ->\n                let (face, familyName, weight, italic) = FontResolver.loadTypeface family weight italic\n                let impl = FontImpl(face, familyName, weight, italic)\n                impl\n            )\n        Font(impl)\n\n    new(family : string, style : FontStyle) =\n        let struct (weight, italic) = FontStyle.toWeightAndItalic style\n        Font(family, weight, italic)\n\n    new(family : string) = Font(family, 400, false)\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Font =\n    let inline family (f : Font) = f.Family\n    let inline style (f : Font) = f.Style\n    let inline spacing (f : Font) = f.Spacing\n    let inline lineHeight (f : Font) = f.LineHeight\n\n    let inline glyph (c : CodePoint) (f : Font) = f.GetGlyph c\n    let inline kerning (l : CodePoint) (r : CodePoint) (f : Font) = f.GetKerning(l,r)\n\n    let inline create (family : string) (style : FontStyle) = Font(family, style)\n\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Glyph =\n    let inline advance (g : Glyph) = g.Advance\n    let inline path (g : Glyph) = g.Path\n    let inline geometry (g : Glyph) = g.Geometry\n    let inline codePoint (g : Glyph) = g.CodePoint\n    let inline string (g : Glyph) = g.CodePoint.String"
  },
  {
    "path": "src/Aardvark.Base.Fonts/FontResolver.fs",
    "content": "namespace Aardvark.Base.Fonts\n\nopen Aardvark.Base\nopen System\nopen System.IO\nopen System.Runtime.InteropServices\nopen Typography.OpenFont\n\n#nowarn \"9\"\n\nmodule internal FontResolver =\n\n    type FontTableEntry<'a> =\n        {\n            Tag             : 'a\n            FamilyName      : string\n            Offset          : int\n            Weight          : int\n            Italic          : bool\n            SubFamilyName   : string\n        }\n\n    module FontTableEntries =\n        // resolve according to: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight\n        let chooseBestEntry (weight : int) (italic : bool) (available : list<FontTableEntry<'a>>) =\n\n            let members =\n                if italic then\n                    let italics = available |> List.filter (fun m -> m.Italic)\n                    match italics with\n                    | [] -> available\n                    | _ -> italics\n                else\n                    let nonitalic = available |> List.filter (fun m -> not m.Italic)\n                    match nonitalic with\n                    | [] -> available\n                    | _ -> nonitalic\n\n            let bestEntry =\n                let map = members |> List.map (fun m -> m.Weight, m) |> MapExt.ofList\n                let (l, s, r) = MapExt.neighbours weight map\n\n                match s with\n                | Some (_, m) -> m\n                | None ->\n                    // If the target weight given is between 400 and 500 inclusive:\n                    if weight >= 400 && weight <= 500 then\n                        // Look for available weights between the target and 500, in ascending order.\n                        match r with\n                        | Some (rw, rm) when rw <= 500 ->\n                            rm\n                        | _ ->\n                            // If no match is found, look for available weights less than the target, in descending order.\n                            match l with\n                            | Some (lw, lm) ->\n                                lm\n                            | None ->\n                                // If no match is found, look for available weights greater than 500, in ascending order.\n                                Option.get r |> snd\n\n                    elif weight < 400 then\n                        // If a weight less than 400 is given, look for available weights less than the target, in descending order.\n                        // If no match is found, look for available weights greater than the target, in ascending order.\n                        match l with\n                        | Some (_, lm) -> lm\n                        | None -> Option.get r |> snd\n\n                    else\n                        // If a weight greater than 500 is given, look for available weights greater than the target, in ascending order.\n                        // If no match is found, look for available weights less than the target, in descending order.\n                        match r with\n                        | Some (_, rm) -> rm\n                        | None -> Option.get l |> snd\n\n            bestEntry\n\n        let ofStream (tag : 'a) (openStream : unit -> #Stream) =\n            let ofInfo (info : PreviewFontInfo) =\n                {\n                    Tag = tag\n                    FamilyName = info.TypographicFamilyName\n                    Offset = info.ActualStreamOffset\n                    Weight = int info.Weight\n                    Italic = info.OS2TranslatedStyle.HasFlag Extensions.TranslatedOS2FontStyle.ITALIC || info.OS2TranslatedStyle.HasFlag Extensions.TranslatedOS2FontStyle.OBLIQUE\n                    SubFamilyName = info.SubFamilyName\n                }\n\n            let r = OpenFontReader()\n\n            let info =\n                use s = openStream() |> Stream.toSeekable false\n                r.ReadPreview s\n\n            if info.IsFontCollection then\n                List.init info.MemberCount (info.GetMember >> ofInfo)\n            else\n                [ofInfo info]\n\n        let ofFile (file : string) =\n            ofStream file (fun () -> File.OpenRead file)\n\n        let private extensions = Set.ofList [\".ttf\"; \".otf\"; \".ttc\"; \".otc\"; \".woff\"; \".woff2\" ]\n\n        let ofFileSafe (file: string) =\n            try\n                if File.Exists file && extensions |> Set.contains (Path.GetExtension file) then\n                    ofFile file\n                else\n                    []\n            with _ ->\n                []\n\n        let read (openStream : 'a -> #Stream) (entry : FontTableEntry<'a>) =\n            let reader = OpenFontReader()\n            use s = openStream entry.Tag :> Stream\n            reader.Read(s, entry.Offset, ReadFlags.Full)\n\n\n    type FontTable<'a> (entries : seq<FontTableEntry<'a>>) =\n\n        static let normalizeFamilyName (name : string) =\n            name.ToLowerInvariant().Trim()\n\n\n\n        let table =\n            let dict = System.Collections.Generic.Dictionary<string, list<_>>()\n\n            for e in entries do\n                if not (isNull e.FamilyName) then\n                    let key = normalizeFamilyName e.FamilyName\n\n                    match dict.TryGetValue key with\n                    | (true,  s) ->\n                        dict.[key] <-  e :: s\n                    | _ ->\n                        dict.[key] <- [e]\n\n            dict\n\n        let keys =\n            table\n            |> Seq.collect (fun (KeyValue(key, e)) -> e |> Seq.map (fun e -> e.FamilyName, key))\n            |> Seq.toArray\n\n        let names =\n            keys |> Array.map fst\n\n\n        member x.Find(family : string, weight : int, italic : bool) =\n            let res = FuzzySharp.Process.ExtractOne(family, names)\n            let (_, key) = keys.[res.Index]\n            let entries = table.[key]\n            FontTableEntries.chooseBestEntry weight italic entries\n\n    module private Win32 =\n        open System.Runtime.InteropServices\n\n        type HKey =\n            | HKEY_CLASSES_ROOT = 0x80000000\n            | HKEY_CURRENT_USER = 0x80000001\n            | HKEY_LOCAL_MACHINE = 0x80000002\n            | HKEY_USERS = 0x80000003\n            | HKEY_PERFORMANCE_DATA = 0x80000004\n            | HKEY_CURRENT_CONFIG = 0x80000005\n            | HKEY_DYN_DATA = 0x80000006\n\n        type Flags =\n            | RRF_RT_ANY = 0x0000ffff\n            | RRF_RT_DWORD = 0x00000018\n            | RRF_RT_QWORD = 0x00000048\n            | RRF_RT_REG_BINARY = 0x00000008\n            | RRF_RT_REG_DWORD = 0x00000010\n            | RRF_RT_REG_EXPAND_SZ = 0x00000004\n            | RRF_RT_REG_MULTI_SZ = 0x00000020\n            | RRF_RT_REG_NONE = 0x00000001\n            | RRF_RT_REG_QWORD = 0x00000040\n            | RRF_RT_REG_SZ = 0x00000002\n\n        [<DllImport(\"kernel32.dll\")>]\n        extern int RegGetValue(HKey hkey, string lpSubKey, string lpValue, Flags dwFlags, uint32& pdwType, nativeint pvData, uint32& pcbData)\n\n\n        [<DllImport(\"kernel32.dll\")>]\n        extern int RegEnumValue(HKey hKey, int index, byte* lpValueName, int& lpcchValueName, void* lpReserved, void* lpType, byte* lpData, int& lpcbData)\n\n        [<DllImport(\"kernel32.dll\")>]\n        extern int RegOpenKeyExA(HKey hHey, string lpSubKey, int ulOptions, int samDesired, HKey& res)\n\n        let table =\n            lazy (\n\n                let mutable key = Unchecked.defaultof<HKey>\n                let ret = RegOpenKeyExA(HKey.HKEY_LOCAL_MACHINE, \"software\\\\microsoft\\\\windows nt\\\\currentversion\\\\Fonts\", 0, 0x20019, &key)\n\n\n                let mutable index = 0\n\n                let mutable run = true\n\n                let nameRx = System.Text.RegularExpressions.Regex(@\"^(.*?)[ \\t]*(Bold Italic|Light Italic|Thin Italic|Bold|Semibold|Thin|Italic|Light)?[ \\t]*\\([ \\t]*(TrueType|OpenType)[ \\t]*\\)[ \\t]*$\", System.Text.RegularExpressions.RegexOptions.IgnoreCase)\n\n                let result = System.Collections.Generic.List<_>()\n                let fonts = Environment.GetFolderPath Environment.SpecialFolder.Fonts\n                while run do\n\n                    let valueBuffer = Array.zeroCreate<byte> 8192\n                    let mutable valueLen = valueBuffer.Length\n\n                    let nameBuffer = Array.zeroCreate<byte> 8192\n                    let mutable nameLen = nameBuffer.Length\n\n                    use pValue = fixed valueBuffer\n                    use pName = fixed nameBuffer\n\n\n\n                    let ret = RegEnumValue(key, index, pName, &nameLen, 0n, 0n, pValue, &valueLen)\n                    if ret = 0 then\n                        let name = System.Text.Encoding.ASCII.GetString(nameBuffer, 0, nameLen).Trim(' ', char 0)\n                        let file = System.Text.Encoding.ASCII.GetString(valueBuffer, 0, valueLen).Trim(' ', char 0)\n\n                        let familyName =\n                            let m = nameRx.Match name\n                            if m.Success then\n                                let value = m.Groups.[1].Value\n                                if value.Contains \";\" then None\n                                else Some value\n                            else\n                                None\n\n                        let path = Path.Combine(fonts, file)\n                        if File.Exists path then\n                            let entries = FontTableEntries.ofFileSafe path\n                            match familyName with\n                            | Some f when not (isNull f) ->\n                                for r in entries do result.Add { r with FamilyName = f }\n                            | _ ->\n                                result.AddRange entries\n\n\n                        index <- index + 1\n                    else\n                        run <- false\n\n                FontTable result\n            )\n\n    module private MacOs =\n        open System.Runtime.InteropServices\n        open System.IO\n        open System.Linq\n        open Typography\n        open Typography.OpenFont\n        open Aardvark.Base\n\n        type CFArrayCallbackDelegate = delegate of nativeint * nativeint -> unit\n\n        module CFText =\n            [<Literal>]\n            let private CoreFoundation = \"/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation\"\n\n            [<Literal>]\n            let private CoreGraphics = \"/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics\"\n\n            [<Literal>]\n            let private CoreText = \"/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText\"\n\n\n            [<Struct; StructLayout(LayoutKind.Sequential)>]\n            type CFRange = { Start : nativeint; Length : nativeint }\n\n            [<DllImport(CoreFoundation)>]\n            extern void* CFDictionaryCreateMutable (void* a, int cap, void* b, void* c)\n\n            [<DllImport(CoreText)>]\n            extern void* CTFontCollectionCreateFromAvailableFonts (void* dict)\n\n            [<DllImport(CoreText)>]\n            extern void* CTFontCollectionCreateMatchingFontDescriptors(void* coll)\n\n            [<DllImport(CoreFoundation)>]\n            extern int CFArrayGetCount(void* arr)\n\n            [<DllImport(CoreFoundation)>]\n            extern void CFArrayApplyFunction(void* arr, CFRange range, CFArrayCallbackDelegate func, void* ctx)\n\n            [<DllImport(CoreText)>]\n            extern void* CTFontDescriptorCopyAttribute(void* desc, void* key)\n\n\n            [<DllImport(CoreFoundation)>]\n            extern void* CFStringCreateWithCString(void* a, string b, void* c)\n\n            [<DllImport(CoreFoundation)>]\n            extern void CFStringGetCString(void* str, byte* buffer, int len, void* encoding)\n\n            [<DllImport(CoreFoundation)>]\n            extern void* CFURLCopyFileSystemPath(void* url, int pathStyle)\n\n\n            let table =\n                lazy (\n\n                    //let NSFontNameAttribute = CFStringCreateWithCString(0n, \"NSFontNameAttribute\", 0n)\n                    let NSFontFamilyAttribute = CFStringCreateWithCString(0n, \"NSFontFamilyAttribute\", 0n)\n                    let NSFontFaceAttribute = CFStringCreateWithCString(0n, \"NSFontFaceAttribute\", 0n)\n                    let NSCTFontFileURLAttribute = CFStringCreateWithCString(0n, \"NSCTFontFileURLAttribute\", 0n)\n\n\n\n                    let ptr = CFDictionaryCreateMutable (0n, 100000, 0n, 0n)\n\n\n                    let coll = CTFontCollectionCreateFromAvailableFonts ptr\n                    let arr = CTFontCollectionCreateMatchingFontDescriptors coll\n                    let cnt = CFArrayGetCount arr\n\n                    let mutable range = { Start = 0n; Length = nativeint cnt }\n\n                    let getString (font : nativeint) (att : nativeint) =\n                        let test = CTFontDescriptorCopyAttribute(font, att)\n                        let buffer = Array.zeroCreate<byte> 8192\n                        use ptr = fixed buffer\n                        CFStringGetCString(test, ptr, 8192, 0n)\n\n\n                        let mutable l = 0\n                        while l < buffer.Length && buffer.[l] <> 0uy do l <- l + 1\n\n\n\n                        System.Text.Encoding.UTF8.GetString(buffer,0, l)\n\n                    let getPath (font : nativeint) (att : nativeint) =\n                        let test = CTFontDescriptorCopyAttribute(font, att)\n                        let path = CFURLCopyFileSystemPath(test, 0)\n\n                        let buffer = Array.zeroCreate<byte> 8192\n                        use ptr = fixed buffer\n                        CFStringGetCString(path, ptr, 8192, 0n)\n\n                        let mutable l = 0\n                        while l < buffer.Length && buffer.[l] <> 0uy do l <- l + 1\n\n\n                        System.Text.Encoding.UTF8.GetString(buffer, 0, l)\n\n                    let files = System.Collections.Generic.Dictionary<string, System.Collections.Generic.HashSet<string>>()\n                    let func =\n                        CFArrayCallbackDelegate(fun ptr _ ->\n                            let face = getString ptr NSFontFaceAttribute\n                            let family = getString ptr NSFontFamilyAttribute\n                            let path = getPath ptr NSCTFontFileURLAttribute\n\n                            match files.TryGetValue family with\n                            | (true, set) -> set.Add path |> ignore\n                            | _ ->\n                                let set = System.Collections.Generic.HashSet<string>()\n                                set.Add path |> ignore\n                                files.[family] <- set\n\n\n                        )\n                    CFArrayApplyFunction(arr, range, func, 0n)\n\n\n\n                    let allEntries = System.Collections.Generic.List()\n                    for KeyValue(family, files) in files do\n                        for f in files do\n                            let entries =\n                                FontTableEntries.ofFileSafe f\n                                |> List.map (fun i -> { i with FamilyName = family })\n                            allEntries.AddRange entries\n\n\n                    FontTable allEntries\n                )\n\n    module private Linux =\n        open System.Diagnostics\n\n        let private getFontFiles() =\n            let format = @\"%{family[0]};%{file}\\n\"\n\n            try\n                use p = new Process()\n                p.StartInfo.FileName <- \"fc-list\"\n                p.StartInfo.Arguments <- $\"-f \\\"{format}\\\"\"\n                p.StartInfo.RedirectStandardOutput <- true\n                p.StartInfo.RedirectStandardError <- true\n                p.StartInfo.UseShellExecute <- false\n                p.StartInfo.CreateNoWindow <- true\n\n                let result = System.Collections.Generic.Dictionary<string, string>()\n\n                p.OutputDataReceived.Add (fun args ->\n                    if not <| String.IsNullOrWhiteSpace args.Data then\n                        lock result (fun _ ->\n                            let tokens = args.Data |> String.split \";\"\n                            if tokens.Length = 2 then\n                                let family = tokens.[0]\n                                let path = tokens.[1]\n                                result.[path] <- family\n                        )\n                )\n                p.ErrorDataReceived.Add ignore\n\n                p.Start() |> ignore\n                p.BeginOutputReadLine()\n                p.BeginErrorReadLine()\n                p.WaitForExit()\n\n                if p.ExitCode = 0 then\n                    result\n                else\n                    Log.warn $\"Failed to invoke fc-list to build font table (exit code: {p.ExitCode})\"\n                    Dictionary.empty\n            with exn ->\n                Log.warn $\"Failed to invoke fc-list to build font table: {exn.Message}\"\n                Dictionary.empty\n\n        let table =\n            lazy (\n                let allEntries = ResizeArray()\n\n                for KeyValue(path, family) in getFontFiles() do\n                    let entries =\n                        FontTableEntries.ofFileSafe path\n                        |> List.map (fun e -> { e with FamilyName = family })\n\n                    allEntries.AddRange entries\n\n                FontTable allEntries\n            )\n\n    let tryLoadTypeFace (family : string) (weight : int) (italic : bool) : Error<Typeface * string * int * bool> =\n        try\n            let entry =\n                match Environment.OSVersion with\n                | Windows ->\n                    Win32.table.Value.Find(family, weight, italic) |> Success\n                | Mac ->\n                    MacOs.CFText.table.Value.Find(family, weight, italic) |> Success\n                | Linux ->\n                    Linux.table.Value.Find(family, weight, italic) |> Success\n\n            match entry with\n            | Success entry ->\n                let face = entry |> FontTableEntries.read File.OpenRead\n                Success (face, entry.FamilyName, entry.Weight, entry.Italic)\n            | Error error ->\n                Error error\n        with e ->\n            Error e.Message\n\n    let loadTypeface (family : string) (weight : int) (italic : bool) =\n        match tryLoadTypeFace family weight italic with\n        | Success file -> file\n        | Error error ->\n            failwithf $\"Could not resolve font '{family}' (weight = {weight}, italic = {italic}): {error}\""
  },
  {
    "path": "src/Aardvark.Base.Fonts/Path.fs",
    "content": "﻿namespace Aardvark.Base.Fonts\n\nopen Aardvark.Base\n\n[<Struct; RequireQualifiedAccess>]\ntype WindingRule =\n    | NonZero\n    | Positive\n    | Negative\n    | EvenOdd\n    | AbsGreaterEqualTwo\n\ntype Path =\n    private { bounds : Box2d; outline : PathSegment[] }\n    member x.Bounds = x.bounds\n    member x.Outline = x.outline\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Path =\n\n    let empty =\n        { bounds = Box2d.Invalid; outline = [||] }\n\n    /// create a path using a single segment\n    let single (seg : PathSegment) =\n        { bounds = PathSegment.bounds seg; outline = [| seg |] }\n\n    /// creates a path using the given segments\n    let ofSeq (segments : seq<PathSegment>) =\n        let arr = Seq.toArray segments\n        let bounds = arr |> Array.fold (fun l r -> Box.Union(l,PathSegment.bounds r)) Box2d.Invalid\n        { bounds = bounds; outline = arr }\n\n    /// creates a path using the given segments\n    let ofList (segments : list<PathSegment>) =\n        let arr = List.toArray segments\n        let bounds = arr |> Array.fold (fun l r -> Box.Union(l,PathSegment.bounds r)) Box2d.Invalid\n        { bounds = bounds; outline = arr }\n\n    /// creates a path using the given segments\n    let ofArray (segments : PathSegment[]) =\n        let bounds = segments |> Array.fold (fun l r -> Box.Union(l,PathSegment.bounds r)) Box2d.Invalid\n        { bounds = bounds; outline = segments }\n\n    /// returns all path segments\n    let toSeq (p : Path) =\n        p.outline :> seq<_>\n\n    /// returns all path segments\n    let toList (p : Path) =\n        p.outline |> Array.toList\n\n    /// returns all path segments\n    let toArray (p : Path) =\n        p.outline |> Array.copy\n\n    /// concatenates two paths\n    let append (l : Path) (r : Path) =\n        { bounds = Box.Union(l.bounds, r.bounds); outline = Array.append l.outline r.outline }\n\n    /// concatenates a sequence paths\n    let concat (l : seq<Path>) =\n        let bounds = l |> Seq.fold (fun l r -> Box.Union(l, r.bounds)) Box2d.Invalid\n        let arr = l |> Seq.collect toArray |> Seq.toArray\n        { bounds = bounds; outline = arr }\n\n    /// reverses the entrie path\n    let reverse (p : Path) =\n        { bounds = p.bounds; outline = p.outline |> Array.map PathSegment.reverse |> Array.rev }\n\n    /// gets an axis-aligned bounding box for the path\n    let bounds (p : Path) =\n        p.outline |> Seq.map PathSegment.bounds |> Box2d\n\n    /// gets the segment count for the path\n    let count (p : Path) =\n        p.outline.Length\n\n    /// gets the i-th segment from the path\n    let item (i : int) (p : Path) =\n        p.outline.[i]\n\n    /// applies the given transformation to all points used by the path\n    let transform (f : V2d -> V2d) (p : Path) =\n        p.outline |> Array.map (PathSegment.transform f) |> ofArray\n\n    type PathBuilderState =\n        {\n            currentStart : Option<V2d>\n            current : Option<V2d>\n            segments : list<PathSegment>\n        }\n\n    type PathBuilder() =\n        member x.Yield(()) =\n            {\n                currentStart = None\n                current = None\n                segments = []\n            }\n\n        [<CustomOperation(\"start\")>]\n        member x.Start(s : PathBuilderState, pt : V2d) =\n            { s with current = Some pt; currentStart = Some pt }\n\n        [<CustomOperation(\"lineTo\")>]\n        member x.LineTo(s : PathBuilderState, p1 : V2d) =\n            match s.current with\n                | Some p0 ->\n                    match PathSegment.tryLine p0 p1 with\n                        | Some seg ->\n                            { s with current = Some p1; segments = seg :: s.segments }\n                        | None ->\n                            s\n                | None ->\n                    failwith \"cannot use lineTo without starting the path\"\n\n        [<CustomOperation(\"bezierTo\")>]\n        member x.BezierTo(s : PathBuilderState, pc : V2d, p1 : V2d) =\n            match s.current with\n                | Some p0 ->\n                    match PathSegment.tryBezier2 p0 pc p1 with\n                        | Some seg ->\n                            { s with current = Some p1; segments = seg :: s.segments }\n                        | None ->\n                            s\n                | None ->\n                    failwith \"cannot use lineTo without starting the path\"\n\n        [<CustomOperation(\"arc\")>]\n        member x.Arc(s : PathBuilderState, p1 : V2d, p2 : V2d) =\n            match s.current with\n                | Some p0 ->\n                    match PathSegment.tryArcSegment p0 p1 p2 with\n                        | Some seg ->\n                            { s with current = Some p2; segments = seg :: s.segments }\n                        | None ->\n                            s\n                | None ->\n                    failwith \"cannot use lineTo without starting the path\"\n\n        [<CustomOperation(\"bezierTo3\")>]\n        member x.BezierTo3(s : PathBuilderState, pc0 : V2d, pc1 : V2d, p1 : V2d) =\n            match s.current with\n                | Some p0 ->\n                    match PathSegment.tryBezier3 p0 pc0 pc1 p1 with\n                        | Some seg ->\n                            { s with current = Some p1; segments = seg :: s.segments }\n                        | None ->\n                            s\n                | None ->\n                    failwith \"cannot use lineTo without starting the path\"\n\n        [<CustomOperation(\"stop\")>]\n        member x.Stop(s : PathBuilderState) =\n            { s with current = None; currentStart = None }\n\n        [<CustomOperation(\"close\")>]\n        member x.CloseLine(s : PathBuilderState) =\n            match s.current, s.currentStart with\n                | Some current, Some start ->\n                    let s = { s with current = None; currentStart = None }\n\n                    match PathSegment.tryLine current start with\n                        | Some seg -> { s with segments = seg :: s.segments }\n                        | None -> s\n                | _ ->\n                    failwith \"cannot close without starting the path\"\n\n        member x.Run(s : PathBuilderState) =\n            ofList (List.rev s.segments)\n\n    let build = PathBuilder()\n\n    /// creates a geometry using the !!closed!! path which contains the left-hand-side of\n    /// the outline.\n    /// The returned geometry contains Positions and a 4-dimensional vector (KLMKind) describing the\n    /// (k,l,m) coordinates for boundary triangles in its xyz components and\n    /// the kind of the triangle (inner = 0, boundary = 1) in its w component\n    let toGeometry (rule : WindingRule) (p : Path) =\n        let rule =\n            match rule with\n            | WindingRule.Positive -> LibTessDotNet.Double.WindingRule.Positive\n            | WindingRule.Negative -> LibTessDotNet.Double.WindingRule.Negative\n            | WindingRule.NonZero -> LibTessDotNet.Double.WindingRule.NonZero\n            | WindingRule.EvenOdd -> LibTessDotNet.Double.WindingRule.EvenOdd\n            | WindingRule.AbsGreaterEqualTwo -> LibTessDotNet.Double.WindingRule.AbsGeqTwo\n\n        Tessellator.toGeometry rule p.bounds p.outline"
  },
  {
    "path": "src/Aardvark.Base.Fonts/PathSegment.fs",
    "content": "﻿namespace Aardvark.Base.Fonts\n\nopen Aardvark.Base\n\n[<AutoOpen>]\nmodule Helpers =\n\n    [<Literal>]\n    let internal epsilon = 1E-9\n\n    let internal arcCoords (p0 : V2d) (p1 : V2d) (p2 : V2d) =\n        let p01 = Plane2d(Vec.normalize (p1 - p0), p0)\n        let p12 = Plane2d(Vec.normalize (p2 - p1), p2)\n        let mutable centerInWorld = V2d.Zero\n        p01.Intersects(p12, &centerInWorld) |> ignore\n\n        let u = p0 - p1\n        let v = p2 - p1\n        let uv2World = M33d.FromCols(V3d(u, 0.0), V3d(v, 0.0), V3d(p1, 1.0))\n        let world2UV = uv2World.Inverse\n\n        let cuv = world2UV.TransformPos centerInWorld\n        let ruv = Vec.length (V2d.IO - cuv)\n\n        let r0 = Plane2d(Vec.normalize (V2d.IO - cuv), V2d.IO)\n        let r2 = Plane2d(Vec.normalize (V2d.OI - cuv), V2d.OI)\n        let mutable uv1 = V2d.Zero\n        r0.Intersects(r2, &uv1) |> ignore\n\n        (V2d.IO - cuv) / ruv, (uv1 - cuv) / ruv, (V2d.OI - cuv) / ruv\n\n    let flip (a,b) = b,a\n\n    let findBezierT (epsilon : float) (pt : V2d) (p0 : V2d) (p1 : V2d) (p2 : V2d) : option<float> =\n        let a = p0 - 2.0*p1 + p2\n        let b = 2.0*p1 - 2.0*p0\n        let c = p0 - pt\n\n        let struct(t0, t1) = Polynomial.RealRootsOf(a.X, b.X, c.X)\n        let struct(t2, t3) = Polynomial.RealRootsOf(a.Y, b.Y, c.Y)\n\n        let inline check t = if t >= -epsilon && t <= 1.0 + epsilon then Some t else None\n\n        if Fun.ApproximateEquals(t0, t2, epsilon) then check ((t0 + t2) / 2.0)\n        elif Fun.ApproximateEquals(t0, t3, epsilon) then check ((t0 + t3) / 2.0)\n        elif Fun.ApproximateEquals(t1, t2, epsilon) then check ((t1 + t2) / 2.0)\n        elif Fun.ApproximateEquals(t1, t3, epsilon) then check ((t1 + t3) / 2.0)\n        else None\n\n    // TODO: check against real implementations\n    let inline arcT (a0 : float) (da : float) (v : float) =\n        let mutable a0 = a0\n        let mutable v = v\n\n        while a0 < 0.0 do a0 <- a0 + Constant.PiTimesTwo\n        while v < 0.0 do v <- v + Constant.PiTimesTwo\n\n        if da < 0.0 then\n            if v > a0 + 1E-8 then v <- v - Constant.PiTimesTwo\n            (v - a0) / da\n        else\n            if v < a0 - 1E-8  then v <- v + Constant.PiTimesTwo\n            (v - a0) / da\n\n    type Ellipse2d with\n\n        member x.IsCcw =\n            let n = V2d(-x.Axis0.Y, x.Axis0.X)\n            Vec.dot n x.Axis1 > 0.0\n\n        member x.TryGetAlpha(pt : V2d, eps : float) =\n            let a0 = x.Axis0\n            let a1 = x.Axis1\n            assert (Fun.IsTiny(Vec.dot a0 a1, 1E-6))\n\n            let c =\n                V2d(\n                    Vec.dot a0 (pt - x.Center) / a0.LengthSquared,\n                    Vec.dot a1 (pt - x.Center) / a1.LengthSquared\n                )\n\n            let c0 = Vec.normalize c\n            let pp = x.Center + x.Axis0 * c0.X + x.Axis1 * c0.Y\n            if Fun.ApproximateEquals(pp, pt, eps) then\n                Some (atan2 c0.Y c0.X)\n            else\n                None\n\n        member x.GetAlpha(pt : V2d) =\n            let l0 = x.Axis0.Length\n            let l1 = x.Axis1.Length\n            let a0 = x.Axis0 / l0\n            let a1 = x.Axis1 / l1\n\n            if Fun.IsTiny(Vec.dot a0 a1, epsilon) then\n                let d = pt - x.Center\n                let u = a0.Dot d / l0\n                let v = a1.Dot d / l1\n                atan2 v u\n            else\n                failwith \"cannot get alpha for bad ellipse\"\n\n        member internal x.GetControlPoint(alpha0 : float, alpha1 : float) =\n            let p0 = x.GetPoint alpha0\n            let p1 = x.GetPoint alpha1\n            let t0 = cos alpha0 * x.Axis1 - sin alpha0 * x.Axis0 |> Vec.normalize\n            let t1 = cos alpha1 * x.Axis1 - sin alpha1 * x.Axis0 |> Vec.normalize\n            let n0 = Ray2d(p0, t0)\n            let n1 = Ray2d(p1, t1)\n            let pc = n0.Intersect(n1)\n            pc\n\n\n\ntype PathSegment =\n    private\n    | LineSeg of p0 : V2d * p1 : V2d\n    | Bezier2Seg of p0 : V2d * p1 : V2d * p2 : V2d\n    | Bezier3Seg of p0 : V2d * p1 : V2d * p2 : V2d * p3 : V2d\n    | ArcSeg of p0 : V2d * p1 : V2d * alpha0 : float * dAlpha : float * e : Ellipse2d\n\n\nmodule internal PathSegmentIntersections =\n\n    let maxArcAngle = 95.0 * Constant.RadiansPerDegree\n\n    /// gets an axis aligned bounding box for the given segment\n    let bounds (seg : PathSegment) =\n        match seg with\n        | LineSeg(p0, p1) ->\n            let mutable b = Box2d(p0, p0)\n            b.ExtendBy p1\n            b\n        | Bezier2Seg(p0, p1, p2) ->\n            let mutable b = Box2d(p0, p0)\n            b.ExtendBy p1\n            b.ExtendBy p2\n            b\n        | Bezier3Seg(p0, p1, p2, p3) ->\n            let mutable b = Box2d(p0, p0)\n            b.ExtendBy p1\n            b.ExtendBy p2\n            b.ExtendBy p3\n            b\n        | ArcSeg(p0, p1, a0, da, ellipse) ->\n            let mutable bb = Box2d(p0, p0)\n            bb.ExtendBy p1\n\n            let steps = abs da / maxArcAngle |> ceil |> int\n            if steps = 1 then\n                let a1 = a0 + da\n                let d0 = cos a0 * ellipse.Axis1 - sin a0 * ellipse.Axis0 |> Vec.normalize\n                let d1 = cos a1 * ellipse.Axis1 - sin a1 * ellipse.Axis0 |> Vec.normalize\n                let n0 = Ray2d(p0, d0)\n                let n1 = Ray2d(p1, d1)\n                let pc = n0.Intersect(n1)\n                bb.ExtendBy pc\n            elif steps > 0 then\n                let step = da / float steps\n                let mutable t0 = a0\n                let mutable q0 = p0\n                let mutable d0 = cos a0 * ellipse.Axis1 - sin a0 * ellipse.Axis0 |> Vec.normalize\n                for s in 1 .. steps do\n                    let t1 = t0 + step\n\n                    let c1 = cos t1\n                    let s1 = sin t1\n\n                    let q1 = ellipse.Center + c1 * ellipse.Axis0 + s1 * ellipse.Axis1\n                    let d1 = c1 * ellipse.Axis1 - s1 * ellipse.Axis0 |> Vec.normalize\n                    let n0 = Ray2d(q0, d0)\n                    let n1 = Ray2d(q1, d1)\n                    let pc = n0.Intersect(n1)\n\n                    bb.ExtendBy q1\n                    bb.ExtendBy pc\n\n                    t0 <- t1\n                    q0 <- q1\n                    d0 <- d1\n\n            bb\n\n    /// returns the start-point of the segment (t=0)\n    let inline startPoint (seg : PathSegment) =\n        match seg with\n        | LineSeg(p0,_) -> p0\n        | Bezier2Seg(p0,_,_) -> p0\n        | Bezier3Seg(p0,_,_,_) -> p0\n        | ArcSeg(p0,_,_,_,_) -> p0\n\n    /// returns the end-point of the segment (t=1)\n    let inline endPoint (seg : PathSegment) =\n        match seg with\n        | LineSeg(_,p1) -> p1\n        | Bezier2Seg(_,_,p1) -> p1\n        | Bezier3Seg(_,_,_,p1) -> p1\n        | ArcSeg(_,p1,_,_,_) -> p1\n\n    /// evaluates the curve-position for the given parameter (t <- [0;1])\n    let point (t : float) (seg : PathSegment) =\n        if t <= 0.0 then startPoint seg\n        elif t >= 1.0 then endPoint seg\n        else\n            match seg with\n            | LineSeg(p0, p1) ->\n                lerp p0 p1 t\n\n            | Bezier2Seg(p0, p1, p2) ->\n                let u = 1.0 - t\n                (u * u) * p0 + (2.0 * t * u) * p1 + (t * t) * p2\n\n            | Bezier3Seg(p0, p1, p2, p3) ->\n                let u = 1.0 - t\n                let u2 = u * u\n                let t2 = t * t\n                (u * u2) * p0 + (3.0 * u2 * t) * p1 + (3.0 * u * t2) * p2 + (t * t2) * p3\n\n            | ArcSeg(p0, p1, a0, da, ellipse) ->\n                if t <= 0.0 then p0\n                elif t >= 1.0 then p1\n                else ellipse.GetPoint(a0 + t * da)\n\n    /// evaluates the curve-derivative for the given parameter (t <- [0;1])\n    let derivative (t : float) (seg : PathSegment) =\n        let t = clamp 0.0 1.0 t\n        match seg with\n        | LineSeg(p1, p0) ->\n            p1 - p0\n\n        | ArcSeg(p0, p1, a0, da, e) ->\n            let alpha = a0 + t * da\n            (cos alpha * e.Axis1 - sin alpha * e.Axis0) * da\n\n        | Bezier2Seg(p0, p1, p2) ->\n            let u = 1.0 - t\n            2.0 * (u*(p1 - p0) + t*(p2 - p1))\n\n        | Bezier3Seg(p0, p1, p2, p3) ->\n            let s = 1.0 - t\n            let u = p1 - p0\n            let v = p2 - p1\n            let w = p3 - p2\n            3.0 * (s*s*u + 2.0*t*s*v + t*t*w)\n\n\n    [<AutoOpen>]\n    module private Implementations =\n\n        let private teps = 1E-6\n\n        let lines (epsilon : float) (a0 : V2d) (a1 : V2d) (b0 : V2d) (b1 : V2d) =\n            if Fun.ApproximateEquals(a0, b0, epsilon) then [0.0, 0.0]\n            elif Fun.ApproximateEquals(a0, b1, epsilon) then [0.0, 1.0]\n            elif Fun.ApproximateEquals(a1, b0, epsilon) then [1.0, 0.0]\n            elif Fun.ApproximateEquals(a1, b1, epsilon) then [1.0, 1.0]\n            else\n                let ra = Ray2d(a0, a1 - a0)\n                let rb = Ray2d(b0, b1 - b0)\n                let mutable ta = 0.0\n                let mutable tb = 0.0\n                if ra.Intersects(rb, &ta) && rb.Intersects(ra, &tb) && ta <= 1.0 + teps && ta >= -teps && tb <= 1.0 + teps && tb >= -teps then\n                    let ta = clamp 0.0 1.0 ta\n                    let tb = clamp 0.0 1.0 tb\n                    if Fun.ApproximateEquals(ra.GetPointOnRay ta, rb.GetPointOnRay tb, epsilon) then\n                        [ta, tb]\n                    else\n                        []\n                else\n                    []\n\n        let arcLine (epsilon : float) (c0 : V2d) (c1 : V2d) (alpha0: float) (dAlpha : float) (e : Ellipse2d) (b0 : V2d) (b1 : V2d) =\n            // transform the ellipse to a unit-circle and solve the system in that space.\n            let toGlobal = M33d.FromCols(V3d(e.Axis0, 0.0), V3d(e.Axis1, 0.0), V3d(e.Center, 1.0))\n            let toLocal = toGlobal.Inverse\n\n            let r = Ray2d(b0, b1 - b0)\n\n            let p0 = toLocal.TransformPos b0\n            let p1 = toLocal.TransformPos b1\n            let o = p0\n            let d = p1 - p0\n\n\n            // | o + t*d | = 1\n            // <o+t*d|o+t*d> = 1\n            // <o|o+t*d> + t*<d|o+t*d> = 1\n            // <o|o> + 2t*<o|d> + t^2*<d|d> = 1\n            // t^2*(<d|d>) + t*(2*<o|d>) + (o^2 - 1) = 0\n            let a = Vec.lengthSquared d\n            let b = 2.0 * Vec.dot o d\n            let c = Vec.lengthSquared o - 1.0\n\n\n            let q2 = b*b - 4.0*a*c\n\n            let inline test (t : float) =\n                if t >= -teps && t <= 1.0 + teps then\n                    let t = clamp 0.0 1.0 t\n                    let pt = r.GetPointOnRay t\n                    match e.TryGetAlpha(pt, epsilon) with\n                    | Some a ->\n                        let ta = arcT alpha0 dAlpha a\n                        if ta >= -teps && ta <= 1.0 + teps then\n                            let ta = clamp 0.0 1.0 ta\n                            if Fun.ApproximateEquals(pt, e.GetPoint (alpha0 + ta*dAlpha), epsilon) then\n                                Some (ta, t)\n                            else\n                                None\n                        else\n                            None\n                    | None ->\n                        None\n                else\n                    None\n\n            if Fun.IsTiny(q2, epsilon) then\n                match test (-b / (2.0 * a)) with\n                | Some t -> [t]\n                | None -> []\n\n            elif q2 < 0.0 then\n                []\n\n            else\n                let q = sqrt q2\n                let t1 = (-b + q) / (2.0 * a)\n                let t2 = (-b - q) / (2.0 * a)\n\n                match test t1 with\n                | Some (t0a, t0b) ->\n                    match test t2 with\n                    | Some (t1a, t1b) ->\n                        if Fun.ApproximateEquals(t0a, t1a, epsilon) then [t0a, t0b]\n                        else [(t0a, t0b); (t1a, t1b)]\n                    | None ->\n                        [t0a, t0b]\n                | None ->\n                    match test t2 with\n                    | Some (t1a, t1b) -> [t1a, t1b]\n                    | None -> []\n\n        let bezier2Line (epsilon : float) (p0 : V2d) (p1 : V2d) (p2 : V2d) (q0 : V2d) (q1 : V2d) =\n            // o+t*d = a*t^2 + b*t + c\n\n            // o.X+s*d.X = a.X*t^2 + b.X*t + c.X\n            // o.Y+s*d.Y = a.Y*t^2 + b.Y*t + c.Y\n\n            let d = q1 - q0\n            let a = p0 - 2.0*p1 + p2\n            let b = 2.0*p1 - 2.0*p0\n\n            //  o.X*d.Y + s*d.X*d.Y =  a.X*d.Y*t^2 + b.X*d.Y*t + c.X*d.Y\n            // -o.Y*d.X - s*d.X*d.Y = -d.X*a.Y*t^2 - d.X*b.Y*t - d.X*c.Y\n            // 0 = t^2*(a.X*d.Y - d.X*a.Y)  + t*(b.X*d.Y - d.X*b.Y) + (c.X*d.Y - d.X*c.Y + o.Y*d.X - o.X*d.Y)\n\n            let f2 = a.X*d.Y - d.X*a.Y\n            let f1 = b.X*d.Y - d.X*b.Y\n            let f0 = (p0.X - q0.X)*d.Y - (p0.Y - q0.Y)*d.X\n            let struct (t0, t1) = Polynomial.RealRootsOf(f2, f1, f0)\n\n            let d2 = d.LengthSquared\n\n            let inline getS (t : float) =\n                let t2 = sqr t\n                let pt = a*(t2) + b*t + p0\n                Vec.dot (pt - q0) d / d2\n\n            let mutable i0 = V2d.NaN\n            let mutable result = []\n            if t0 >= -teps && t0 <= 1.0 + teps then\n                let s0 = getS t0\n                if s0 >= -teps && s0 <= 1.0 + teps then\n                    let t0 = clamp 0.0 1.0 t0\n                    let s0 = clamp 0.0 1.0 s0\n\n                    let pl = q0 + s0*d\n                    let ps = p0 + t0*b + (t0*t0)*a\n                    if Fun.ApproximateEquals(pl, ps, epsilon) then\n                        i0 <- pl\n                        result <- (t0, s0) :: result\n\n            if t1 >= -teps && t1 <= 1.0 + teps && not (Fun.ApproximateEquals(t0, t1)) then\n                let s1 = getS t1\n                if s1 >= -teps && s1 <= 1.0 + teps then\n                    let t1 = clamp 0.0 1.0 t1\n                    let s1 = clamp 0.0 1.0 s1\n\n                    let pl = q0 + s1*d\n                    let ps = p0 + t1*b + (t1*t1)*a\n                    if Fun.ApproximateEquals(pl, ps, epsilon) && not (Fun.ApproximateEquals(pl, i0)) then\n                        result <- (t1, s1) :: result\n\n            result\n\n        let bezier2 (epsilon : float) (p0 : V2d) (p1 : V2d) (p2 : V2d) (q0 : V2d) (q1 : V2d) (q2 : V2d) =\n            let f0 =\n               -4.0*q0.Y*q1.X*q1.Y*q2.X + 4.0*q0.X*sqr(q1.Y)*q2.X + sqr(q0.Y)*sqr(q2.X) + sqr(p0.Y)*sqr(q0.X - 2.0*q1.X + q2.X) + 4.0*q0.Y*sqr(q1.X)*q2.Y - 4.0*q0.X*q1.X*q1.Y*q2.Y - 2.0*q0.X*q0.Y*q2.X*q2.Y + sqr(q0.X)*sqr(q2.Y) + sqr(p0.X)*sqr(q0.Y - 2.0*q1.Y + q2.Y) -\n                2.0*p0.Y*(-2.0*q0.X*q1.X*q1.Y + 4.0*q0.X*q1.Y*q2.X - 2.0*q1.X*q1.Y*q2.X + q0.Y*(2.0*sqr(q1.X) - q0.X*q2.X - 2.0*q1.X*q2.X + sqr(q2.X)) + sqr(q0.X)*q2.Y - 2.0*q0.X*q1.X*q2.Y + 2.0*sqr(q1.X)*q2.Y - q0.X*q2.X*q2.Y + p0.X*(q0.X - 2.0*q1.X + q2.X)*(q0.Y - 2.0*q1.Y + q2.Y)) +\n                2.0*p0.X*(-(sqr(q0.Y)*q2.X) + 2.0*q1.Y*(-(q1.Y*q2.X) + q1.X*q2.Y) + q0.Y*(2.0*q1.Y*q2.X + 2.0*q1.X*(q1.Y - 2.0*q2.Y) + (q0.X + q2.X)*q2.Y) - q0.X*(2.0*sqr(q1.Y) - 2.0*q1.Y*q2.Y + sqr(q2.Y)))\n\n            let f1 =\n                -4.0*(2.0*p1.Y*q0.Y*sqr(q1.X) - 2.0*p1.Y*q0.X*q1.X*q1.Y - 2.0*p1.X*q0.Y*q1.X*q1.Y + 2.0*p1.X*q0.X*sqr(q1.Y) - p1.Y*q0.X*q0.Y*q2.X + p1.X*sqr(q0.Y)*q2.X - 2.0*p1.Y*q0.Y*q1.X*q2.X + 4.0*p1.Y*q0.X*q1.Y*q2.X - 2.0*p1.X*q0.Y*q1.Y*q2.X - 2.0*p1.Y*q1.X*q1.Y*q2.X + 2.0*p1.X*sqr(q1.Y)*q2.X +\n                     p1.Y*q0.Y*sqr(q2.X) + sqr(p0.Y)*sqr(q0.X - 2.0*q1.X + q2.X) + p1.Y*sqr(q0.X)*q2.Y - p1.X*q0.X*q0.Y*q2.Y - 2.0*p1.Y*q0.X*q1.X*q2.Y + 4.0*p1.X*q0.Y*q1.X*q2.Y + 2.0*p1.Y*sqr(q1.X)*q2.Y - 2.0*p1.X*q0.X*q1.Y*q2.Y - 2.0*p1.X*q1.X*q1.Y*q2.Y - p1.Y*q0.X*q2.X*q2.Y - p1.X*q0.Y*q2.X*q2.Y +\n                     p1.X*q0.X*sqr(q2.Y) + sqr(p0.X)*sqr(q0.Y - 2.0*q1.Y + q2.Y) + p0.Y*(p1.X*q0.X*q0.Y - 2.0*p1.X*q0.Y*q1.X - 2.0*q0.Y*sqr(q1.X) - 2.0*p1.X*q0.X*q1.Y + 4.0*p1.X*q1.X*q1.Y + 2.0*q0.X*q1.X*q1.Y + p1.X*q0.Y*q2.X + q0.X*q0.Y*q2.X + 2.0*q0.Y*q1.X*q2.X - 2.0*p1.X*q1.Y*q2.X - 4.0*q0.X*q1.Y*q2.X +\n                        2.0*q1.X*q1.Y*q2.X - q0.Y*sqr(q2.X) - p1.Y*sqr(q0.X - 2.0*q1.X + q2.X) + p1.X*q0.X*q2.Y - sqr(q0.X)*q2.Y - 2.0*p1.X*q1.X*q2.Y + 2.0*q0.X*q1.X*q2.Y - 2.0*sqr(q1.X)*q2.Y + p1.X*q2.X*q2.Y + q0.X*q2.X*q2.Y - 2.0*p0.X*(q0.X - 2.0*q1.X + q2.X)*(q0.Y - 2.0*q1.Y + q2.Y)) +\n                     p0.X*(2.0*q0.Y*q1.X*q1.Y - 2.0*q0.X*sqr(q1.Y) - sqr(q0.Y)*q2.X + 2.0*q0.Y*q1.Y*q2.X - 2.0*sqr(q1.Y)*q2.X + q0.X*q0.Y*q2.Y - 4.0*q0.Y*q1.X*q2.Y + 2.0*q0.X*q1.Y*q2.Y + 2.0*q1.X*q1.Y*q2.Y + q0.Y*q2.X*q2.Y - q0.X*sqr(q2.Y) + p1.Y*(q0.X - 2.0*q1.X + q2.X)*(q0.Y - 2.0*q1.Y + q2.Y) -\n                        p1.X*sqr(q0.Y - 2.0*q1.Y + q2.Y)))\n\n            let f2 =\n              2.0*(-(p0.X*p2.Y*q0.X*q0.Y) + 3.0*sqr(p0.X)*sqr(q0.Y) - 6.0*p0.X*p1.X*sqr(q0.Y) + 2.0*sqr(p1.X)*sqr(q0.Y) + p0.X*p2.X*sqr(q0.Y) + 2.0*p0.X*p2.Y*q0.Y*q1.X - 2.0*p2.Y*q0.Y*sqr(q1.X) + 2.0*p0.X*p2.Y*q0.X*q1.Y - 12.0*sqr(p0.X)*q0.Y*q1.Y + 24.0*p0.X*p1.X*q0.Y*q1.Y -\n                 8.0*sqr(p1.X)*q0.Y*q1.Y - 4.0*p0.X*p2.X*q0.Y*q1.Y - 4.0*p0.X*p2.Y*q1.X*q1.Y + 2.0*p2.Y*q0.X*q1.X*q1.Y + 2.0*p0.X*q0.Y*q1.X*q1.Y - 4.0*p1.X*q0.Y*q1.X*q1.Y + 2.0*p2.X*q0.Y*q1.X*q1.Y + 12.0*sqr(p0.X)*sqr(q1.Y) - 24.0*p0.X*p1.X*sqr(q1.Y) + 8.0*sqr(p1.X)*sqr(q1.Y) +\n                 4.0*p0.X*p2.X*sqr(q1.Y) - 2.0*p0.X*q0.X*sqr(q1.Y) + 4.0*p1.X*q0.X*sqr(q1.Y) - 2.0*p2.X*q0.X*sqr(q1.Y) - p0.X*p2.Y*q0.Y*q2.X + p2.Y*q0.X*q0.Y*q2.X - p0.X*sqr(q0.Y)*q2.X + 2.0*p1.X*sqr(q0.Y)*q2.X - p2.X*sqr(q0.Y)*q2.X + 2.0*p2.Y*q0.Y*q1.X*q2.X + 2.0*p0.X*p2.Y*q1.Y*q2.X -\n                 4.0*p2.Y*q0.X*q1.Y*q2.X + 2.0*p0.X*q0.Y*q1.Y*q2.X - 4.0*p1.X*q0.Y*q1.Y*q2.X + 2.0*p2.X*q0.Y*q1.Y*q2.X + 2.0*p2.Y*q1.X*q1.Y*q2.X - 2.0*p0.X*sqr(q1.Y)*q2.X + 4.0*p1.X*sqr(q1.Y)*q2.X - 2.0*p2.X*sqr(q1.Y)*q2.X - p2.Y*q0.Y*sqr(q2.X) + 3.0*sqr(p0.Y)*sqr(q0.X - 2.0*q1.X + q2.X) +\n                 2.0*sqr(p1.Y)*sqr(q0.X - 2.0*q1.X + q2.X) - p0.X*p2.Y*q0.X*q2.Y - p2.Y*sqr(q0.X)*q2.Y + 6.0*sqr(p0.X)*q0.Y*q2.Y - 12.0*p0.X*p1.X*q0.Y*q2.Y + 4.0*sqr(p1.X)*q0.Y*q2.Y + 2.0*p0.X*p2.X*q0.Y*q2.Y + p0.X*q0.X*q0.Y*q2.Y - 2.0*p1.X*q0.X*q0.Y*q2.Y + p2.X*q0.X*q0.Y*q2.Y +\n                 2.0*p0.X*p2.Y*q1.X*q2.Y + 2.0*p2.Y*q0.X*q1.X*q2.Y - 4.0*p0.X*q0.Y*q1.X*q2.Y + 8.0*p1.X*q0.Y*q1.X*q2.Y - 4.0*p2.X*q0.Y*q1.X*q2.Y - 2.0*p2.Y*sqr(q1.X)*q2.Y - 12.0*sqr(p0.X)*q1.Y*q2.Y + 24.0*p0.X*p1.X*q1.Y*q2.Y - 8.0*sqr(p1.X)*q1.Y*q2.Y - 4.0*p0.X*p2.X*q1.Y*q2.Y + 2.0*p0.X*q0.X*q1.Y*q2.Y -\n                 4.0*p1.X*q0.X*q1.Y*q2.Y + 2.0*p2.X*q0.X*q1.Y*q2.Y + 2.0*p0.X*q1.X*q1.Y*q2.Y - 4.0*p1.X*q1.X*q1.Y*q2.Y + 2.0*p2.X*q1.X*q1.Y*q2.Y - p0.X*p2.Y*q2.X*q2.Y + p2.Y*q0.X*q2.X*q2.Y + p0.X*q0.Y*q2.X*q2.Y - 2.0*p1.X*q0.Y*q2.X*q2.Y + p2.X*q0.Y*q2.X*q2.Y + 3.0*sqr(p0.X)*sqr(q2.Y) - 6.0*p0.X*p1.X*sqr(q2.Y) +\n                 2.0*sqr(p1.X)*sqr(q2.Y) + p0.X*p2.X*sqr(q2.Y) - p0.X*q0.X*sqr(q2.Y) + 2.0*p1.X*q0.X*sqr(q2.Y) - p2.X*q0.X*sqr(q2.Y) -\n                 p0.Y*(6.0*p0.X*q0.X*q0.Y - 6.0*p1.X*q0.X*q0.Y + p2.X*q0.X*q0.Y - 12.0*p0.X*q0.Y*q1.X + 12.0*p1.X*q0.Y*q1.X - 2.0*p2.X*q0.Y*q1.X + 2.0*q0.Y*sqr(q1.X) - 12.0*p0.X*q0.X*q1.Y + 12.0*p1.X*q0.X*q1.Y - 2.0*p2.X*q0.X*q1.Y + 24.0*p0.X*q1.X*q1.Y - 24.0*p1.X*q1.X*q1.Y + 4.0*p2.X*q1.X*q1.Y - 2.0*q0.X*q1.X*q1.Y +\n                    6.0*p0.X*q0.Y*q2.X - 6.0*p1.X*q0.Y*q2.X + p2.X*q0.Y*q2.X - q0.X*q0.Y*q2.X - 2.0*q0.Y*q1.X*q2.X - 12.0*p0.X*q1.Y*q2.X + 12.0*p1.X*q1.Y*q2.X - 2.0*p2.X*q1.Y*q2.X + 4.0*q0.X*q1.Y*q2.X - 2.0*q1.X*q1.Y*q2.X + q0.Y*sqr(q2.X) + 6.0*p1.Y*sqr(q0.X - 2.0*q1.X + q2.X) - p2.Y*sqr(q0.X - 2.0*q1.X + q2.X) +\n                    6.0*p0.X*q0.X*q2.Y - 6.0*p1.X*q0.X*q2.Y + p2.X*q0.X*q2.Y + sqr(q0.X)*q2.Y - 12.0*p0.X*q1.X*q2.Y + 12.0*p1.X*q1.X*q2.Y - 2.0*p2.X*q1.X*q2.Y - 2.0*q0.X*q1.X*q2.Y + 2.0*sqr(q1.X)*q2.Y + 6.0*p0.X*q2.X*q2.Y - 6.0*p1.X*q2.X*q2.Y + p2.X*q2.X*q2.Y - q0.X*q2.X*q2.Y) +\n                 2.0*p1.Y*(2.0*q0.Y*sqr(q1.X) - 2.0*q0.X*q1.X*q1.Y - q0.X*q0.Y*q2.X - 2.0*q0.Y*q1.X*q2.X + 4.0*q0.X*q1.Y*q2.X - 2.0*q1.X*q1.Y*q2.X + q0.Y*sqr(q2.X) + sqr(q0.X)*q2.Y - 2.0*q0.X*q1.X*q2.Y + 2.0*sqr(q1.X)*q2.Y - q0.X*q2.X*q2.Y + 3.0*p0.X*(q0.X - 2.0*q1.X + q2.X)*(q0.Y - 2.0*q1.Y + q2.Y) -\n                    2.0*p1.X*(q0.X - 2.0*q1.X + q2.X)*(q0.Y - 2.0*q1.Y + q2.Y)))\n\n            let f3 =\n                -4.0*(p2.Y*q0.X - p0.X*q0.Y + 2.0*p1.X*q0.Y - p2.X*q0.Y - 2.0*p2.Y*q1.X + 2.0*p0.X*q1.Y - 4.0*p1.X*q1.Y + 2.0*p2.X*q1.Y + p2.Y*q2.X + p0.Y*(q0.X - 2.0*q1.X + q2.X) - 2.0*p1.Y*(q0.X - 2.0*q1.X + q2.X) - p0.X*q2.Y + 2.0*p1.X*q2.Y - p2.X*q2.Y)*\n                    (p0.Y*(q0.X - 2.0*q1.X + q2.X) - p1.Y*(q0.X - 2.0*q1.X + q2.X) - (p0.X - p1.X)*(q0.Y - 2.0*q1.Y + q2.Y))\n\n            let f4 =\n                sqr(-(p2.Y*q0.X) + p0.X*q0.Y - 2.0*p1.X*q0.Y + p2.X*q0.Y + 2.0*p2.Y*q1.X - 2.0*p0.X*q1.Y + 4.0*p1.X*q1.Y - 2.0*p2.X*q1.Y - p2.Y*q2.X - p0.Y*(q0.X - 2.0*q1.X + q2.X) + 2.0*p1.Y*(q0.X - 2.0*q1.X + q2.X) + p0.X*q2.Y - 2.0*p1.X*q2.Y + p2.X*q2.Y)\n\n            let struct (t0, t1, t2, t3) = Polynomial.RealRootsOf(f4, f3, f2, f1, f0)\n\n            let inline evalP (t : float) =\n                if t >= -teps && t <= 1.0 + teps then\n                    let t = clamp 0.0 1.0 t\n                    let s = 1.0 - t\n                    Some (t, p0*s*s + 2.0*p1*s*t + p2*t*t)\n                else\n                    None\n\n            let inline evalQ (t : float) =\n                if t >= -teps && t <= 1.0 + teps then\n                    let t = clamp 0.0 1.0 t\n                    let s = 1.0 - t\n                    Some (t, q0*s*s + 2.0*q1*s*t + q2*t*t)\n                else\n                    None\n\n            let test (tp : float) =\n                match evalP tp with\n                | Some(tp, pp) ->\n                    match findBezierT teps pp q0 q1 q2 with\n                    | Some tq ->\n                        match evalQ tq with\n                        | Some (tq, pq) ->\n                            if Fun.ApproximateEquals(pq, pp, epsilon) then [tp, tq]\n                            else []\n                        | None ->\n                            []\n                    | None ->\n                        []\n                | None ->\n                    []\n\n            test t0 @ test t1 @ test t2 @ test t3\n\n        let ellipses (eps : float) (e0 : Ellipse2d) (e1 : Ellipse2d) =\n            let m = M33d.FromCols(V3d(e0.Axis0, 0.0), V3d(e0.Axis1, 0.0), V3d(e0.Center, 1.0))\n            let mi = m.Inverse\n\n            let c = mi.TransformPos e1.Center\n            let a = mi.TransformDir e1.Axis0\n            let b = mi.TransformDir e1.Axis1\n\n            // |c + cos t * a + sin t * b| = 1\n            // |c + cos t * a + sin t * b|^2 = 1\n            // <c + cos(t)*a + sin(t)*b | c + cos(t)*a + sin(t)*b> = 1\n\n            // <c|c> + cos(t)*<a|c> + sin(t)*<b|c> +\n            // cos(t)*<a|c> + cos(t)^2*<a|a> + sin(t)*cos(t)*<a|b> +\n            // sin(t)*<b|c> + sin(t)*cos(t)*<a|b> + sin(t)^2*<b|b> - 1 = 0\n\n            // (cos(t)^2*<a|a> + sin(t)^2*<b|b>) + 2*(sin(t)*cos(t)*<a|b> + cos(t)*<a|c> + sin(t)*<b|c>) + <c|c> - 1 = 0\n\n            let aa = a.LengthSquared\n            let bb = b.LengthSquared\n            let cc = c.LengthSquared\n            let ab = Vec.dot a b\n            let ac = Vec.dot a c\n            let bc = Vec.dot b c\n\n\n            // (c^2*<a|a> + s^2*<b|b>) + 2*(s*c*<a|b> + c*<a|c> + s*<b|c>) + <c|c> - 1 = 0\n            // c^2*aa + s^2*bb + 2*(s*c*ab + c*ac + s*bc) + cc - 1 = 0\n\n            // Mathematica:\n            // s0 := Eliminate [c^2*aa + s^2*bb + 2*(s*c*ab + c*ac + s*bc) + cc - 1 == 0 && c^2 + s^2 == 1, s]\n            // s1 := SubtractSides[s0][[1]]\n            // FullSimplify[Coefficient[s1, c, 0]]\n            let f0 = (-1.0 + bb - 2.0*bc + cc)*(-1.0 + bb + 2.0*bc + cc)\n            let f1 = -8.0*ab*bc + 4.0*ac*(-1.0 + bb + cc)\n            let f2 = 2.0*(-2.0*sqr(ab) + 2.0*sqr(ac) + bb + 2.0*sqr(bc) + aa*(-1.0 + bb + cc) - bb*(bb + cc))\n            let f3 = 4.0*aa*ac - 4.0*ac*bb + 8.0*ab*bc\n            let f4 = 4.0*sqr(ab) + sqr(aa - bb)\n            let struct(c0, c1, c2, c3) = Polynomial.RealRootsOf(f4, f3, f2, f1, f0)\n\n            let g0 = (-1.0 + aa - 2.0*ac + cc)*(-1.0 + aa + 2.0*ac + cc)\n            let g1 = -8.0*ab*ac + 4.0*bc*(-1.0 + aa + cc)\n            let g2 = -2.0*(sqr(aa) + 2.0*sqr(ab) - 2.0*sqr(ac) + bb - 2.0*sqr(bc) - bb*cc + aa*(-1.0 - bb + cc))\n            let g3 = 8.0*ab*ac + 4.0*(-aa + bb)*bc\n            let g4 = 4.0*sqr(ab) + sqr(aa - bb)\n            let struct(s0, s1, s2, s3) = Polynomial.RealRootsOf(g4, g3, g2, g1, g0)\n\n\n            let add (v0 : float, v1 : float) (l : list<float * float>) =\n                let exists = l |> List.exists (fun (va, vb) -> Fun.ApproximateEquals(v0, va, 1E-8) && Fun.ApproximateEquals(v1, vb, 1E-8))\n                if exists then l\n                else (v0, v1) :: l\n\n            let sols =\n                let mutable sols = []\n                for c in [c0;c1;c2;c3] do\n                    if c >= -1.0 && c <= 1.0 then\n                        let s = sqrt(1.0 - sqr c)\n                        sols <- sols |> add (c, s) |> add (c, -s)\n\n                for s in [s0;s1;s2;s3] do\n                    if s >= -1.0 && s <= 1.0 then\n                        let c = sqrt(1.0 - sqr s)\n                        sols <- sols |> add (c, s) |> add (-c, s)\n\n                sols\n\n            let rec getSolutions (acc : list<float * float>) (l : list<float * float>) =\n                match l with\n                | [] -> acc\n                | (cos, sin) :: t ->\n                    let p = c + cos*a + sin*b\n                    let a0 = atan2 p.Y p.X\n                    let a1 = atan2 sin cos\n\n                    let p0 = e0.GetPoint a0\n                    let p1 = e1.GetPoint a1\n                    if Fun.ApproximateEquals(p0, p1, eps) then\n                        getSolutions ((a0, a1) :: acc) t\n                    else\n                        getSolutions acc t\n\n\n\n\n\n            let solutions = getSolutions [] sols |> List.sort\n\n\n            solutions\n\n        let arcs (epsilon : float) (a0 : float) (da : float) (a : Ellipse2d) (b0 : float) (db : float) (b : Ellipse2d) =\n            ellipses epsilon a b |> List.choose (fun (aa, ba) ->\n                let ta = arcT a0 da aa\n                let tb = arcT b0 db ba\n                if ta >= -teps && ta <= 1.0 + teps && tb >= -teps && tb <= 1.0 + teps then\n                    let ta = clamp 0.0 1.0 ta\n                    let tb = clamp 0.0 1.0 tb\n                    let pa = a.GetPoint(a0 + da*ta)\n                    let pb = b.GetPoint(b0 + db*tb)\n                    if Fun.ApproximateEquals(pa, pb, epsilon) then\n                        Some (ta, tb)\n                    else\n                        None\n                else\n                    None\n            )\n\n        let private bezier2Ellipse (p0 : V2d) (p1 : V2d) (p2 : V2d) (e : Ellipse2d) =\n            let m = M33d.FromCols(V3d(e.Axis0, 0.0), V3d(e.Axis1, 0.0), V3d(e.Center, 1.0))\n            let mi = m.Inverse\n\n            let q0 = mi.TransformPos p0\n            let q1 = mi.TransformPos p1\n            let q2 = mi.TransformPos p2\n\n            let a = q0 - 2.0*q1 + q2\n            let b = 2.0*q1 - 2.0*q0\n            let c = q0\n\n            // |a*t^2 + b*t + c| = 1\n            // <a*t^2 + b*t + c | a*t^2 + b*t + c > = 1\n\n            // t^4*<a|a> + t^3*<a|b> + t^2*<a|c> +\n            // t^3*<a|b> + t^2*<b|b> + t*<b|c> +\n            // t^2*<a|c> + t*<b|c> + <c|c> - 1 = 0\n\n            // t^4*(<a|a>) + t^3*(2*<a|b>) + t^2*(2*<a|c> + <b|b>) + t*(2*<b|c>) + (<c|c> - 1) = 0\n\n            let f0 = c.LengthSquared - 1.0\n            let f1 = 2.0 * Vec.dot b c\n            let f2 = 2.0 * Vec.dot a c + b.LengthSquared\n            let f3 = 2.0 * Vec.dot a b\n            let f4 = a.LengthSquared\n\n            let struct (t0, t1, t2, t3) = Polynomial.RealRootsOf(f4, f3, f2, f1, f0)\n\n            [t0; t1; t2; t3] |> List.choose (fun t ->\n                if t >= -teps && t <= 1.0 + teps then\n                    let t = clamp 0.0 1.0 t\n                    let p = a*sqr t + b*t + c\n                    let alpha = atan2 p.Y p.X\n                    Some (t, alpha)\n                else\n                    None\n            )\n\n        let bezier2Arc (epsilon : float) (p0 : V2d) (p1 : V2d) (p2 : V2d) (alpha0 : float) (dAlpha : float) (e : Ellipse2d) =\n            bezier2Ellipse p0 p1 p2 e |> List.choose (fun (t, a) ->\n                let te = arcT alpha0 dAlpha a\n                if te >= -teps && te <= 1.0 + teps then\n                    let t = clamp 0.0 1.0 t\n                    let te = clamp 0.0 1.0 te\n\n                    let s = 1.0 - t\n                    let pb = p0*(s*s) + 2.0*p1*(s*t) + p2*(t*t)\n                    let pe = e.GetPoint(alpha0 + dAlpha*te)\n                    if Fun.ApproximateEquals(pb, pe, epsilon) then\n                        Some (t, te)\n                    else\n                        None\n                else\n                    None\n            )\n\n        let bezier3Line (epsilon : float) (p0 : V2d) (p1 : V2d) (p2 : V2d) (p3 : V2d) (q0 : V2d) (q1 : V2d) =\n\n            let a = -p0 + 3.0*p1 - 3.0*p2 + p3\n            let b = 3.0*p0 - 6.0*p1 + 3.0*p2\n            let c = 3.0*p1 - 3.0*p0\n            let d = p0\n\n            let o = q0\n            let v = q1 - q0\n\n            // v*t + o = a*s^3 + b*s^2 + c*s + d\n\n            // v.X*t + o.X = a.X*s^3 + b.X*s^2 + c.X*s + d.X\n            // v.Y*t + o.Y = a.Y*s^3 + b.Y*s^2 + c.Y*s + d.Y\n\n\n            // v.Y*v.X*t + v.Y*o.X = v.Y*a.X*s^3 + v.Y*b.X*s^2 + v.Y*c.X*s + v.Y*d.X\n            // -v.X*v.Y*t - v.X*o.Y = -v.X*a.Y*s^3 - v.X*b.Y*s^2 - v.X*c.Y*s - v.X*d.Y\n\n            // 0 = s^3*(v.Y*a.X - v.X*a.Y) + s^2*(v.Y*b.X - v.X*b.Y) + s*(v.Y*c.X - v.X*c.Y) + (v.Y*d.X - v.X*d.Y - v.Y*o.X + v.X*o.Y)\n\n            let f3 = v.Y*a.X - v.X*a.Y\n            let f2 = v.Y*b.X - v.X*b.Y\n            let f1 = v.Y*c.X - v.X*c.Y\n            let f0 = v.Y*d.X - v.X*d.Y - v.Y*o.X + v.X*o.Y\n            let struct (s0, s1, s2) = Polynomial.RealRootsOf(f3, f2, f1, f0)\n\n            [s0;s1;s2] |> List.choose (fun ts ->\n                if ts >= -teps && ts <= 1.0 + teps then\n                    let ts = clamp 0.0 1.0 ts\n                    let ts2 = sqr ts\n                    let pt = a*ts*ts2 + b*ts2 + c*ts + d\n                    let tl = Vec.dot v (pt - o) / v.LengthSquared\n                    if tl >= -teps && tl <= 1.0 + teps then\n                        let tl = clamp 0.0 1.0 tl\n                        let pl = o + v*tl\n                        if Fun.ApproximateEquals(pt, pl, epsilon) then\n                            Some (ts, tl)\n                        else\n                            None\n                    else\n                        None\n                else\n                    None\n            )\n\n        let private halves (s : PathSegment) =\n            match s with\n            | LineSeg(p0, p1) ->\n                let m = (p0+p1)/2.0\n                LineSeg(p0, m), LineSeg(m, p1)\n\n            | ArcSeg(p0, p1, a0, da, e) ->\n                let dh = da / 2.0\n                let pm = e.GetPoint(a0 + dh)\n                ArcSeg(p0, pm, a0, dh, e), ArcSeg(pm, p1, a0+dh, dh, e)\n\n\n            | Bezier2Seg(p0, p1, p2) ->\n                let q0 = (p0+p1) / 2.0\n                let q1 = (p1+p2) / 2.0\n                let c = (q0+q1)/2.0\n                Bezier2Seg(p0, q0, c), Bezier2Seg(c, q1, p2)\n\n            | Bezier3Seg(p0, p1, p2, p3) ->\n                let q0 = (p0+p1) / 2.0\n                let q1 = (p1+p2) / 2.0\n                let q2 = (p2+p3) / 2.0\n                let m0 = (q0+q1) / 2.0\n                let m1 = (q1+q2) / 2.0\n                let c = (m0+m1) / 2.0\n                Bezier3Seg(p0, q0, m0, c), Bezier3Seg(c, m1, q2, p3)\n\n        let numeric (epsilon : float) (l : PathSegment) (r : PathSegment) =\n\n            let stack = System.Collections.Generic.Stack<struct(PathSegment * PathSegment * V4d)>(64)\n\n            let mutable result = []\n            let mutable points = []\n            let mutable cnt = 0\n\n            let newtonStep (t : V2d) =\n                let vl = point t.X l\n                let vr = point t.Y r\n                let dl = derivative t.X l\n                let dr = derivative t.Y r\n\n\n                // v(x0, x1) = l(x0) - r(x1)\n                // dv/dx0 = l'(x0)\n                // dv/dx1 = -r'(x1)\n\n                let jacobian =\n                    M22d(\n                        dl.X, -dr.X,\n                        dl.Y, -dr.Y\n                    )\n\n                let inv = jacobian.Inverse\n                let delta = inv * (vl - vr)\n                -delta\n\n\n\n            let add (atl : float) (atr : float) =\n\n                let mutable t = V2d(atl, atr)\n                let mutable lastStep = 1E10\n                let mutable iter = 0\n                while iter < 30 && lastStep > 1E-15 do\n                    let dt = newtonStep t\n                    t <- t + dt\n                    lastStep <- dt.NormMax\n                    iter <- iter + 1\n\n\n\n                let tl = clamp 0.0 1.0 t.X\n                let tr = clamp 0.0 1.0 t.Y\n                let pl = point tl l\n                let pr = point tr r\n                let largeEps = 100.0 * epsilon\n\n\n                if Fun.ApproximateEquals(pl, pr, largeEps) then\n                    let pt = (pl + pr) / 2.0\n                    let contained = points |> List.exists (fun p -> Fun.ApproximateEquals(p, pt, largeEps))\n                    if not contained then\n                        result <- (tl, tr) :: result\n                        points <- pt :: points\n                        cnt <- cnt + 1\n\n            stack.Push(struct(l, r, V4d(0.0,1.0,0.0,1.0)))\n            let mutable maxLength = 0\n\n            while stack.Count > 0 && cnt < 9 do\n                maxLength <- max maxLength stack.Count\n                let struct(l, r, ranges) = stack.Pop()\n                let lo = ranges.X\n                let ls = ranges.Y\n                let ro = ranges.Z\n                let rs = ranges.W\n\n                let lb = bounds l\n                let rb = bounds r\n                if lb.Intersects rb then\n                    if lb.Size.NormMax <= 1E-6 || rb.Size.NormMax <= 1E-6 then\n                        add (lo + ls/2.0) (ro + rs/2.0)\n                    else\n                        let l0, l1 = halves l\n                        let r0, r1 = halves r\n\n                        let lsh = ls / 2.0\n                        let rsh = rs / 2.0\n\n                        let l0o = lo\n                        let l1o = lo + lsh\n                        let r0o = ro\n                        let r1o = ro + rsh\n                        stack.Push(struct(l0, r0, V4d(l0o, lsh, r0o, rsh)))\n                        stack.Push(struct(l0, r1, V4d(l0o, lsh, r1o, rsh)))\n                        stack.Push(struct(l1, r0, V4d(l1o, lsh, r0o, rsh)))\n                        stack.Push(struct(l1, r1, V4d(l1o, lsh, r1o, rsh)))\n\n                ()\n\n            if cnt > 9 then []\n            else result\n\n    let intersections (eps : float) (a : PathSegment) (b : PathSegment) : list<float * float> =\n        match a, b with\n        | LineSeg(a0, a1), LineSeg(b0, b1) ->\n            lines eps a0 a1 b0 b1\n\n        | LineSeg(a0, a1), Bezier2Seg(b0, b1, b2) ->\n            bezier2Line eps b0 b1 b2 a0 a1\n            |> List.map flip\n            |> List.sortBy fst\n\n        | LineSeg(a0, a1), ArcSeg(c0, c1, b0, db, b) ->\n            arcLine eps c0 c1 b0 db b a0 a1\n            |> List.map flip\n            |> List.sortBy fst\n\n        | LineSeg(a0, a1), Bezier3Seg(b0, b1, b2, b3) ->\n            bezier3Line eps b0 b1 b2 b3 a0 a1\n            |> List.map flip\n            |> List.sortBy fst\n\n        | Bezier2Seg(a0, a1, a2), LineSeg(b0, b1) ->\n            bezier2Line eps a0 a1 a2 b0 b1\n            |> List.sortBy fst\n\n        | Bezier2Seg(a0, a1, a2), Bezier2Seg(b0, b1, b2) ->\n            bezier2 eps a0 a1 a2 b0 b1 b2\n            |> List.sortBy fst\n\n        | Bezier2Seg(a0, a1, a2), ArcSeg(_, _, b0, db, b) ->\n            bezier2Arc eps a0 a1 a2 b0 db b\n            |> List.sortBy fst\n\n        | Bezier2Seg _, Bezier3Seg _ ->\n            numeric eps a b\n            |> List.sortBy fst\n\n        | ArcSeg(c0, c1, a0, da, a), LineSeg(b0, b1) ->\n            arcLine eps c0 c1 a0 da a b0 b1\n            |> List.sortBy fst\n\n        | ArcSeg(_, _, a0, da, a), Bezier2Seg(b0, b1, b2) ->\n            bezier2Arc eps b0 b1 b2 a0 da a\n            |> List.map flip\n            |> List.sortBy fst\n\n        | ArcSeg(ap0, ap1, a0, da, a), ArcSeg(bp0, bp1, b0, db, b) ->\n            if Fun.ApproximateEquals(ap0, bp0, eps) then [0.0, 0.0]\n            elif Fun.ApproximateEquals(ap0, bp1, eps) then [0.0, 1.0]\n            elif Fun.ApproximateEquals(ap1, bp0, eps) then [1.0, 0.0]\n            elif Fun.ApproximateEquals(ap1, bp1, eps) then [1.0, 1.0]\n            else\n                arcs eps a0 da a b0 db b\n                |> List.sortBy fst\n\n        | ArcSeg _, Bezier3Seg _ ->\n            numeric eps a b\n            |> List.sortBy fst\n\n        | Bezier3Seg(a0, a1, a2, a3), LineSeg(b0, b1) ->\n            bezier3Line eps a0 a1 a2 a3 b0 b1\n            |> List.sortBy fst\n\n        | Bezier3Seg _, Bezier2Seg _ ->\n            numeric eps a b\n            |> List.sortBy fst\n\n        | Bezier3Seg _, ArcSeg _ ->\n            numeric eps a b\n            |> List.sortBy fst\n\n        | Bezier3Seg _, Bezier3Seg _ ->\n            numeric eps a b\n            |> List.sortBy fst\n\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule PathSegment =\n\n\n    let inline private cc (a : V2d) (b : V2d) =\n        a.X*b.Y - a.Y*b.X\n\n    /// creates a clean (non-conjugate, non-clockwise) ellipse from two possilby conjugate diameters\n    let private createEllipse (center : V2d) (a0 : V2d) (a1 : V2d) =\n        let mutable a0 = a0\n        let mutable a1 = a1\n        if not (Fun.IsTiny(Vec.dot a0 a1, epsilon)) then\n            let e = Ellipse2d.FromConjugateDiameters(center, a0, a1)\n            a0 <- e.Axis0\n            a1 <- e.Axis1\n\n        // make the one with larger |X| Axis0\n        if abs a1.X > abs a0.X then Fun.Swap(&a0, &a1)\n        // flip the axis0 to positive x\n        if a0.X < 0.0 then a0 <- -a0\n        // ensure that Axis1 is left of Axis0\n        if cc a0 a1 < 0.0 then a1 <- -a1\n\n        Ellipse2d(center, a0, a1)\n\n    /// unsafely replaces the start point of a path segment\n    let withP0 (pt : V2d) (s : PathSegment) =\n        match s with\n        | LineSeg(_, p1) -> PathSegment.LineSeg(pt, p1)\n        | Bezier2Seg(_, p1, p2) -> PathSegment.Bezier2Seg(pt, p1, p2)\n        | Bezier3Seg(_, p1, p2, p3) -> PathSegment.Bezier3Seg(pt, p1, p2, p3)\n        | ArcSeg(_, p1, a, da, e) -> PathSegment.ArcSeg(pt, p1, a, da, e)\n\n    /// unsafely replaces the end point of a path segment\n    let withP1 (pt : V2d) (s : PathSegment) =\n        match s with\n        | LineSeg(p0, _) -> PathSegment.LineSeg(p0, pt)\n        | Bezier2Seg(p0, p1, p2) -> PathSegment.Bezier2Seg(p0, p1, pt)\n        | Bezier3Seg(p0, p1, p2, p3) -> PathSegment.Bezier3Seg(p0, p1, p2, pt)\n        | ArcSeg(p0, p1, a, da, e) -> PathSegment.ArcSeg(p0, pt, a, da, e)\n\n\n    /// creates a line segment\n    let line (p0 : V2d) (p1 : V2d) =\n        if Fun.ApproximateEquals(p0, p1, epsilon) then\n            failwithf \"[PathSegment] degenerate line at: %A\" p0\n\n        LineSeg(p0, p1)\n\n    /// creates a quadratic bezier segment\n    let bezier2 (p0 : V2d) (p1 : V2d) (p2 : V2d) =\n        // check if the spline is actually a line\n        let d = p2 - p0 |> Vec.normalize\n        let n = V2d(-d.Y, d.X)\n\n\n        if Fun.IsTiny(Vec.dot (p1 - p0) n, epsilon) then\n            line p0 p2\n        else\n            Bezier2Seg(p0, p1, p2)\n\n    /// creates a cubic bezier segment\n    let bezier3 (p0 : V2d) (p1 : V2d) (p2 : V2d) (p3 : V2d) =\n        if Fun.ApproximateEquals(p0, p1, epsilon) && Fun.ApproximateEquals(p1, p2, epsilon) && Fun.ApproximateEquals(p2, p3, epsilon) then\n            failwithf \"[PathSegment] degenerate line at: %A\" p0\n        else\n            let dd = (p3 - p0)\n            let len = Vec.length dd\n            let d03 = dd / len\n\n            let n = V2d(-d03.Y, d03.X)\n            let h1 = Vec.dot (p1 - p0) n\n            let h2 = Vec.dot (p2 - p0) n\n\n            if Fun.IsTiny(h1, epsilon) && Fun.IsTiny(h2, epsilon) then\n                line p0 p3\n            else\n                let f3 = -p0 + 3.0*p1 - 3.0*p2 + p3\n                if Fun.IsTiny(f3, epsilon) then\n                    let ctrl = -p0 + 3.0*p1 - 1.5*p2 + 0.5*p3\n                    bezier2 p0 ctrl p3\n                else\n                    Bezier3Seg(p0, p1, p2, p3)\n\n\n\n    /// creates a line segment (if not degenerate)\n    let tryLine (p0 : V2d) (p1 : V2d) =\n        if Fun.ApproximateEquals(p0, p1, epsilon) then None\n        else Some (LineSeg(p0, p1))\n\n    /// creates a qudratic bezier segment (if not degenerate)\n    let tryBezier2 (p0 : V2d) (p1 : V2d) (p2 : V2d) =\n        // check if the spline is actually a line\n        let d = p2 - p0 |> Vec.normalize\n        let n = V2d(-d.Y, d.X)\n\n\n        if Fun.IsTiny(Vec.dot (p1 - p0) n, epsilon) then\n            tryLine p0 p2\n        else\n            Bezier2Seg(p0, p1, p2) |> Some\n\n    /// creates a cubic bezier segment (if not degenerate)\n    let tryBezier3 (p0 : V2d) (p1 : V2d) (p2 : V2d) (p3 : V2d) =\n        if Fun.ApproximateEquals(p0, p1, epsilon) && Fun.ApproximateEquals(p1, p2, epsilon) && Fun.ApproximateEquals(p2, p3, epsilon) then\n            None\n        else\n            let dd = (p3 - p0)\n            let len = Vec.length dd\n            let d03 = dd / len\n\n            let n = V2d(-d03.Y, d03.X)\n            let h1 = Vec.dot (p1 - p0) n\n            let h2 = Vec.dot (p2 - p0) n\n\n            if Fun.IsTiny(h1, epsilon) && Fun.IsTiny(h2, epsilon) then\n                tryLine p0 p3\n            else\n                // let f3 = -p0 + 3.0*p1 - 3.0*p2 + p3\n                // let f2 = 3.0*p0 - 6.0*p1 + 3.0*p2\n                // let f1 = 3.0*p1 - 3.0*p0\n                // let f0 = p0\n\n\n                // let g2 = q2 + q0 - 2.0*q1\n                // let g1 = 2.0*(q1 - q0)\n                // let g0 = q0\n\n\n                // f3 = 0\n                // =>\n                // q2 + q0 - 2.0*q1 = 3.0*p0 - 6.0*p1 + 3.0*p2\n                // 3.0*p1 - 3.0*p0 = 2.0*q1 - 2.0*q0\n                // p0 = q0\n\n                // semantically: q2 = p3\n\n                // q1 = -p0 + 3*p1 - 1.5*p2 + 0.5*p3\n                let f3 = -p0 + 3.0*p1 - 3.0*p2 + p3\n                if Fun.IsTiny(f3, epsilon) then\n                    let ctrl = -p0 + 3.0*p1 - 1.5*p2 + 0.5*p3\n                    tryBezier2 p0 ctrl p3\n                else\n                    Bezier3Seg(p0, p1, p2, p3) |> Some\n\n    let private createArc (force : bool) (p0 : V2d) (p1 : V2d) (alpha0 : float) (dAlpha : float) (ellipse : Ellipse2d) =\n        let newEllipse = createEllipse ellipse.Center ellipse.Axis0 ellipse.Axis1\n        let a0 = newEllipse.GetAlpha p0\n        let da =\n            if not ellipse.IsCcw then -dAlpha\n            else dAlpha\n\n        let pm = newEllipse.GetPoint(a0 + da / 2.0)\n        if not force && not (Fun.ApproximateEquals(p0, p1, epsilon)) && Fun.IsTiny(pm.PosLeftOfLineValue(p0, p1), epsilon) then\n            tryLine p0 p1\n        else\n            ArcSeg(p0, p1, a0, da, newEllipse) |> Some\n\n\n    /// creates an arc using the an angle alpha0 and a (signed) dAlpha.\n    /// in order to avoid precision issues p0,p1 users may redundantly supply p0 and p1.\n    /// the implementation validates that p0~ellipse.GetPoint(alpha0) and p1~ellipse.GetPoint(alpha0+dAlpha) respectively.\n    let tryArcWithPoints (p0 : V2d) (p1 : V2d) (alpha0 : float) (dAlpha : float) (ellipse : Ellipse2d) =\n        if Fun.ApproximateEquals(p0, p1, epsilon) then\n            None\n        elif Fun.ApproximateEquals(p0, ellipse.GetPoint alpha0, epsilon) && Fun.ApproximateEquals(p1, ellipse.GetPoint (alpha0 + dAlpha), epsilon) then\n            createArc false p0 p1 alpha0 dAlpha ellipse\n        else\n            None\n\n    /// creates an arc using the an angle alpha0 and a (signed) dAlpha.\n    /// in order to avoid precision issues p0,p1 users may redundantly supply p0 and p1.\n    /// the implementation validates that p0~ellipse.GetPoint(alpha0) and p1~ellipse.GetPoint(alpha0+dAlpha) respectively.\n    let arcWithPoints (p0 : V2d) (p1 : V2d) (alpha0 : float) (dAlpha : float) (ellipse : Ellipse2d) =\n        if Fun.ApproximateEquals(p0, ellipse.GetPoint alpha0, epsilon) && Fun.ApproximateEquals(p1, ellipse.GetPoint (alpha0 + dAlpha), epsilon) then\n            createArc true p0 p1 alpha0 dAlpha ellipse |> Option.get\n        else\n            failwith \"bad points for arc\"\n\n    /// creates an arc using the an angle alpha0 and a (signed) dAlpha\n    let tryArc (alpha0 : float) (dAlpha : float) (ellipse : Ellipse2d) =\n        if Fun.IsTiny(dAlpha, epsilon) then\n            None\n        else\n            let p0 = ellipse.GetPoint alpha0\n            let p1 = ellipse.GetPoint (alpha0 + dAlpha)\n            createArc false p0 p1 alpha0 dAlpha ellipse\n\n    /// creates an arc using the an angle alpha0 and a (signed) dAlpha\n    let arc (alpha0 : float) (dAlpha : float) (ellipse : Ellipse2d) =\n        tryArc alpha0 dAlpha ellipse |> Option.get\n\n    /// creates an arc-segment passing through p0 and p2.\n    /// the tangents are made parallel to (p1-p0) and (p2-p1) respectively.\n    /// since this configuration is ambigous the ellipse with minimal eccentricity is chosen.\n    let tryArcSegment (p0 : V2d) (p1 : V2d) (p2 : V2d) =\n        // check if the arc is actually a line\n        let d = p2 - p0 |> Vec.normalize\n        let n = V2d(-d.Y, d.X)\n\n        if Fun.IsTiny(Vec.dot (p1 - p0) n, epsilon) then\n            tryLine p0 p2\n        else\n            // see: https://math.stackexchange.com/questions/2204258/roundest-ellipse-with-specified-tangents\n            let m = 0.5 * (p0 + p2)\n            let am = m - p0\n            let vm = m - p1\n            let va = p1 - p0\n\n            let lam = Vec.length am\n            let lvm = Vec.length vm\n            let lva = Vec.length va\n\n            let lam2 = lam * lam\n            let lmd = (lam2 + lam*sqrt (lam2 + lvm*lvm)) / lvm\n            let d = m + vm * (lmd / lvm)\n\n            let inline ln (v : V2d) = V2d(-v.Y, v.X)\n\n            let pd = Plane2d(ln (am / lam), d)\n            let pv = Plane2d(ln (va / lva), p0)\n            let mutable e = V2d.Zero\n            if pd.Intersects(pv, &e) then\n                let f = 0.5 * (d + p0)\n                let ef = f - e\n                let lef = Vec.length ef\n                let pef = Plane2d(ln (ef / lef), e)\n                let pvm = Plane2d(ln (vm / lvm), d)\n\n                let mutable c = V2d.Zero\n                if pef.Intersects(pvm, &c) then\n                    let lcd = Vec.length (d - c)\n                    let g = c - am * (lcd/lam)\n\n                    let ellipse = createEllipse c (d - c) (g - c)\n                    let a0 = ellipse.GetAlpha p0\n                    let a1 = ellipse.GetAlpha p2\n                    let da = a1 - a0\n                    let da1 = if da > Constant.Pi then da - Constant.PiTimesTwo elif da < -Constant.Pi then Constant.PiTimesTwo + da else da\n\n                    ArcSeg(p0, p2, a0, da1, ellipse) |> Some\n\n                else\n                    tryLine p0 p2\n\n            else\n                tryLine p0 p2\n\n    /// creates an arc-segment passing through p0 and p2.\n    /// the tangents are made parallel to (p1-p0) and (p2-p1) respectively.\n    /// since this configuration is ambigous the ellipse with minimal eccentricity is chosen.\n    let arcSegment (p0 : V2d) (p1 : V2d) (p2 : V2d) =\n        tryArcSegment p0 p1 p2 |> Option.get\n\n\n    /// returns the start-point of the segment (t=0)\n    let startPoint (seg : PathSegment) =\n        match seg with\n        | LineSeg(p0,_) -> p0\n        | Bezier2Seg(p0,_,_) -> p0\n        | Bezier3Seg(p0,_,_,_) -> p0\n        | ArcSeg(p0,_,_,_,_) -> p0\n\n    /// returns the end-point of the segment (t=1)\n    let endPoint (seg : PathSegment) =\n        match seg with\n        | LineSeg(_,p1) -> p1\n        | Bezier2Seg(_,_,p1) -> p1\n        | Bezier3Seg(_,_,_,p1) -> p1\n        | ArcSeg(_,p1,_,_,_) -> p1\n\n    /// evaluates the curve-position for the given parameter (t <- [0;1])\n    let point (t : float) (seg : PathSegment) =\n        if t <= 0.0 then startPoint seg\n        elif t >= 1.0 then endPoint seg\n        else\n            match seg with\n            | LineSeg(p0, p1) ->\n                lerp p0 p1 t\n\n            | Bezier2Seg(p0, p1, p2) ->\n                let u = 1.0 - t\n                (u * u) * p0 + (2.0 * t * u) * p1 + (t * t) * p2\n\n            | Bezier3Seg(p0, p1, p2, p3) ->\n                let u = 1.0 - t\n                let u2 = u * u\n                let t2 = t * t\n                (u * u2) * p0 + (3.0 * u2 * t) * p1 + (3.0 * u * t2) * p2 + (t * t2) * p3\n\n            | ArcSeg(p0, p1, a0, da, ellipse) ->\n                if t <= 0.0 then p0\n                elif t >= 1.0 then p1\n                else ellipse.GetPoint(a0 + t * da)\n\n    /// evaluates the curve-derivative for the given parameter (t <- [0;1])\n    let derivative (t : float) (seg : PathSegment) =\n        let t = clamp 0.0 1.0 t\n        match seg with\n        | LineSeg(p0, p1) ->\n            p1 - p0\n\n        | ArcSeg(_p0, _p1, a0, da, e) ->\n            let alpha = a0 + t * da\n            (cos alpha * e.Axis1 - sin alpha * e.Axis0) * da\n\n        | Bezier2Seg(p0, p1, p2) ->\n            let u = 1.0 - t\n            2.0 * (u*(p1 - p0) + t*(p2 - p1))\n\n        | Bezier3Seg(p0, p1, p2, p3) ->\n            let s = 1.0 - t\n            let u = p1 - p0\n            let v = p2 - p1\n            let w = p3 - p2\n            3.0 * (s*s*u + 2.0*t*s*v + t*t*w)\n\n    /// evaluates the second curve-derivative for the given parameter (t <- [0;1])\n    let secondDerivative (t : float) (seg : PathSegment) =\n        let t = clamp 0.0 1.0 t\n        match seg with\n        | LineSeg _ ->\n            V2d.Zero\n\n        | ArcSeg(p0, p1, a0, da, e) ->\n            let alpha = a0 + t * da\n            -sqr da * (cos alpha * e.Axis0 + sin alpha * e.Axis1)\n\n        | Bezier2Seg(p0, p1, p2) ->\n            2.0 * (p0 - 2.0*p1 + p2)\n\n        | Bezier3Seg(p0, p1, p2, p3) ->\n            let u = p1 - p0\n            let v = p2 - p1\n            let w = p3 - p2\n            6.0 * ((1.0-t)*(v-u) + t*(w-v))\n\n    /// evaluates the third curve-derivative for the given parameter (t <- [0;1])\n    let thirdDerivative (t : float) (seg : PathSegment) =\n        let t = clamp 0.0 1.0 t\n        match seg with\n        | LineSeg _ ->\n            V2d.Zero\n\n        | ArcSeg(p0, p1, a0, da, e) ->\n            let alpha = a0 + t * da\n            da*da*da * (sin alpha * e.Axis0 - cos alpha * e.Axis1)\n\n        | Bezier2Seg(p0, p1, p2) ->\n            V2d.Zero\n\n        | Bezier3Seg(p0, p1, p2, p3) ->\n            let u = p1 - p0\n            let v = p2 - p1\n            let w = p3 - p2\n            6.0 * (u+w - 2.0*v)\n\n    /// evaluates the curvature for the given parameter (t <- [0;1]).\n    /// the curvature is defined as: c(t) := (x'(t)*y''(t) - y'(t)*x''(t)) / (x'(t)^2 + y'(t)^2)^(3/2).\n    /// see https://en.wikipedia.org/wiki/Curvature#In_terms_of_a_general_parametrization\n    let curvature (t : float) (seg : PathSegment) =\n        match seg with\n        | LineSeg _ ->\n            0.0\n\n        | _ ->\n\n\n            //(df.X*ddf.Y - df.Y*ddf.X) / (df.LengthSquared ** 1.5)\n\n\n            // f = t^2 * (p0 - 2*p1 + p2) + t*2*(p1 - p0) + p0\n\n\n            // df = 2.0 * ((1-t)*(p1 - p0) + t*(p2 - p1))\n            // ddf = 2.0 * (p0 - 2.0*p1 + p2)\n\n\n            // df/2 =(p1 - p0)- t*(p1 - p0) + t*(p2 - p1)\n\n\n            // df/2 = (p1 - p0) - t*(p1 - p0) + t*(p2 - p1)\n            // df = t * 2*(p2 - 2*p1 + p0) + 2*(p1 - p0)\n            // ddf = 2*(p2 - 2*p1 + p0)\n\n\n            // c = (df.X*ddf.Y - df.Y*ddf.X) / (df.LengthSquared ** 1.5)\n            // c^2 = max\n\n            // c^2 = (df.X*ddf.Y - df.Y*ddf.X)^2 / (df.LengthSquared ** 3)\n\n            // a := 2*(p2 - 2*p1 + p0)\n            // b := 2*(p1 - p0)\n\n\n            // df = t*a + b\n            // ddf = a\n\n            // ((t*a.X + b.X)*a.Y - (t*a.Y + b.Y)*a.X)^2 / ((t*a + b)^2)^3\n\n            // (t*a.X*a.Y + b.X*a.Y - t*a.Y*a.X - b.Y*a.X)^2 / ((t*a + b)^2)^3\n            // c^2 = (b.X*a.Y - b.Y*a.X)^2 * ((t*a + b)^2)^-3\n\n            // dc^2 / dt = -3 * (b.X*a.Y - b.Y*a.X)^2 * ((t*a + b)^2)^-4 * 2*(t*a + b) * a\n\n\n            // (t*a + b) * a  = 0\n            // t = -<b|a> / <a|a>\n\n\n\n            // d := t0\n            // a := 2.0*(p0 - 2*p1 + p2)\n\n            // df = a*t + d\n            // ddf = a\n\n            // c^2 = [(a.X*t+d.X)*a.Y - (a.Y*t+d.Y)*a.X]^2 * [(a*t+d)^2]^-3\n            // c^2 = [t*(a.X*a.Y - a.Y*a.X) + (d.X*a.Y - d.Y*a.X)]^2 * [(a*t+d)^2]^-3\n\n            // f := a.X*a.Y - a.Y*a.X\n            // g := d.X*a.Y - d.Y*a.X\n\n            // f = 0\n\n            // c^2 = [t*f + g]^2 * [(a*t+d)^2]^-3\n\n\n            // c^2 = g^2 * [(a*t+d)^2]^-3\n\n            // dc^2 / dt = -3*g^2 * [(a*t+d)^2]^-4\n\n\n            // dc^2 / dt = 2*[t*f + g]*f * [(a*t+d)^2]^-3 - 6*[t*f + g]^2 * (a*t+d) * [(a*t+d)^2]^-4\n\n            // [t*f + g]*f * [(a*t+d)^2]^-3 - 3*[t*f + g]^2 * (a*t+d) * [(a*t+d)^2]^-4 = 0 /// * [(a*t+d)^2]^4\n\n            // [t*f + g]*f * [(a*t+d)^2] - 3*[t*f + g]^2 * (a*t+d) = 0\n\n\n\n\n\n\n\n            let df = derivative t seg\n            let ddf = secondDerivative t seg\n            (df.X*ddf.Y - df.Y*ddf.X) / (df.LengthSquared ** 1.5)\n\n    /// evaluates the curvature-derivative for the given parameter (t <- [0;1]).\n    let curvatureDerivative (t : float) (seg : PathSegment) =\n        match seg with\n        | LineSeg _ ->\n            0.0\n\n        | _ ->\n\n            // F = df/dt(t)\n            // G = d2f/dt^2(t)\n\n            // (F.X*G.Y - F.Y*G.X) * (F.X*G.X + F.Y*G.Y)\n\n            // sqr F.X*G.X*G.Y - sqr F.Y*G.X*G.Y - F.X*F.Y*sqr G.X + F.X*F.Y*sqr G.Y\n\n            // G.X*G.Y*(sqr F.X - sqr F.Y) + F.X*F.Y*(sqr G.Y - sqr G.X)\n\n            // (Fx*Gy - Fy*Gx) * (Fx^2 + Fy^2)^(2/3)\n\n            // (Gx*Gy + Fx*Hy - Gy*Gx - Fy*Hx) * (Fx^2 + Fy^2)^(2/3) +\n            // (Fx*Gy - Fy*Gx) * (4/3) * (Fx^2 + Fy^2)^(-1/3) * (Fx*Gx + Fy*Gy)\n\n\n            // (Fx*Hy - Fy*Hx) * (Fx^2 + Fy^2)^(2/3) +\n            // (4/3) * (Fx*Gy - Fy*Gx) * (Fx*Gx + Fy*Gy) * (Fx^2 + Fy^2)^(-1/3)\n\n\n            // (Fx*Hy - Fy*Hx) * (Fx^2 + Fy^2)^(2/3) + (Fx*Gy - Fy*Gx) * (2/3) * (Fx^2 + Fy^2)^(-1/3) * 2*(Fx*Gx + Fy*Gy)\n\n            // A := lim dp->0 [(c(p + dp) - c(p)) / |dp|]\n\n            // p(t) = f(t)\n            // dp(t) = f'(t) * dt\n\n            // dc/sqrt(dpx^2 + dpy^2)\n\n\n            // A^2 = dc^2/(dpx^2 + dpy^2)\n\n\n            // A^2 = dc^2/(f'x(t)^2*dt^2 + f'y(t)^2*dt^2)\n            // A^2 = (1 / (f'x(t)^2 + f'y(t)^2)) * (dc^/dt)^2\n            // A = (1 / |f'|) * (dc/dt)\n\n\n\n            // (c(f(t) + f'(t) * dt) - c(f(t))) / |f'(t) * dt|\n            // (1 / |f'(t)|) * lim dt->0 [(C(t + dt) - C(t)) / dt]\n\n            // (1 / |f'(t)|) * dC/dt\n\n\n            // (1 / |f'(t)|) * (c(t + dt) - c(t)) / dt\n\n\n            // c = (F.X*G.Y - F.Y*G.X) * (F.X^2 + F.Y^2)^(-3/2)\n\n            // dc / dt = (G.X*G.Y + F.X*H.Y - G.Y*G.X - F.Y*H.X) * (F.X^2 + F.Y^2)^(-3/2) -\n            // 3 * (F.X*G.Y - F.Y*G.X) * (F.X^2 + F.Y^2)^(-5/2) * (F.X*G.X + F.Y*G.Y)\n\n\n            // dc / dt = (F.X*H.Y - F.Y*H.X) * (F.X^2 + F.Y^2)^(-3/2) -\n            // 3 * (F.X*G.Y - F.Y*G.X) * (F.X^2 + F.Y^2)^(-5/2) * (F.X*G.X + F.Y*G.Y)\n\n\n            // dc / dt = (F.X^2 + F.Y^2)^(-3/2) * [(F.X*H.Y - F.Y*H.X) -\n            // 3 * (F.X*G.Y - F.Y*G.X) * (F.X*G.X + F.Y*G.Y) * (F.X^2 + F.Y^2)^-1]\n\n\n\n            let F = derivative t seg\n            let G = secondDerivative t seg\n            let H = thirdDerivative t seg\n\n            let lfSq = F.LengthSquared\n\n            let diff = lfSq**(-1.5) * ((F.X*H.Y - F.Y*H.X) - 3.0 * (F.X*G.Y - F.Y*G.X) * (F.X*G.X + F.Y*G.Y) / lfSq)\n            //\n            //\n            // let diff =\n            //     (F.X*H.Y - F.Y*H.X) * sqr lfSqCbrt +\n            //     (4.0/3.0) * (F.X*G.Y - F.Y*G.X) * (F.X*G.X + F.Y*G.Y) / lfSqCbrt\n\n            diff / F.Length\n\n\n    /// finds all parameters t <- [0;1] where the curvature changes its sign.\n    /// note that only Bezier3 segments may have inflection points.\n    let inflectionParameters (seg : PathSegment) =\n        // {t | t >= 0 && t <= 1 && f'(t).X*f''(t).Y - f'(t).Y*f''(t).X == 0 }\n        match seg with\n        | LineSeg _\n        | ArcSeg _\n        | Bezier2Seg _ ->\n            []\n\n        | Bezier3Seg(p0, p1, p2, p3) ->\n            let u = p1 - p0\n            let v = p2 - p1\n            let w = p3 - p2\n\n            let f0 = -18.0*u.Y*v.X + 18.0*u.X*v.Y\n            let f1 =  36.0*u.Y*v.X - 36.0*u.X*v.Y - 18.0*u.Y*w.X + 18.0*u.X*w.Y\n            let f2 = -18.0*u.Y*v.X + 18.0*u.X*v.Y + 18.0*u.Y*w.X - 18.0*v.Y*w.X - 18.0*u.X*w.Y + 18.0*v.X*w.Y\n\n            let struct(t0, t1) = Polynomial.RealRootsOf(f2, f1, f0)\n\n            let v0 = t0 >= 0.0 && t0 <= 1.0\n            let v1 = t1 >= 0.0 && t1 <= 1.0\n\n            if v0 then\n                if v1 then\n                    if Fun.ApproximateEquals(t0, t1, epsilon) then [t0]\n                    elif t1 > t0 then [t0; t1]\n                    else [t1; t0]\n                else\n                    [t0]\n            elif v1 then [t1]\n            else []\n\n    /// gets a normalized tangent at the given parameter (t <- [0;1])\n    let tangent (t : float) (seg : PathSegment) =\n        match seg with\n        | LineSeg(p0, p1) ->\n            p1 - p0 |> Vec.normalize\n\n        | ArcSeg(p0, p1, a0, da, e) ->\n            let t = clamp 0.0 1.0 t\n            let alpha = a0 + t * da\n            let n = (cos alpha * e.Axis1 - sin alpha * e.Axis0) |> Vec.normalize\n            if da > 0.0 then n else -n\n\n        | Bezier2Seg(p0, p1, p2) ->\n            if t <= 0.0 then\n                Vec.normalize (p1 - p0)\n            elif t >= 1.0 then\n                Vec.normalize (p2 - p1)\n            else\n                let u = 1.0 - t\n                Vec.normalize (u*(p1 - p0) + t*(p2 - p1))\n\n        | Bezier3Seg(p0, p1, p2, p3) ->\n            if t <= 0.0 then\n                if Fun.ApproximateEquals(p0, p1, 1E-9) then Vec.normalize (p2 - p0)\n                else Vec.normalize (p1 - p0)\n            elif t >= 1.0 then\n                if Fun.ApproximateEquals(p2, p3, 1E-9) then Vec.normalize (p3 - p1)\n                else Vec.normalize (p3 - p2)\n            else\n                let s = 1.0 - t\n                let u = p1 - p0\n                let v = p2 - p1\n                let w = p3 - p2\n                Vec.normalize (s*s*u + 2.0*t*s*v + t*t*w)\n\n    /// gets a normalized (left) normal at the given parameter (t <- [0;1])\n    let normal (t : float) (seg : PathSegment) =\n        let t = tangent t seg\n        V2d(-t.Y, t.X)\n\n    /// gets an axis aligned bounding box for the given segment\n    let bounds (seg : PathSegment) =\n        PathSegmentIntersections.bounds seg\n\n    /// reverses the given segment s.t. reversed(t) = original(1-t)\n    let reverse (seg : PathSegment) =\n        match seg with\n        | LineSeg(p0, p1) -> LineSeg(p1, p0)\n        | Bezier2Seg(p0, p1, p2) -> Bezier2Seg(p2, p1, p0)\n        | Bezier3Seg(p0, p1, p2, p3) -> Bezier3Seg(p3, p2, p1, p0)\n        | ArcSeg(p0, p1, a0, da, ellipse) -> ArcSeg(p1, p0, a0 + da, -da, ellipse)\n\n    /// applies a transformation to all the points in the segment\n    let transform (f : V2d -> V2d) (seg : PathSegment) =\n        match seg with\n        | LineSeg(p0, p1) -> line (f p0) (f p1)\n        | Bezier2Seg(p0, p1, p2) -> bezier2 (f p0) (f p1) (f p2)\n        | Bezier3Seg(p0, p1, p2, p3) -> bezier3 (f p0) (f p1) (f p2) (f p3)\n        | ArcSeg(p0, p1, a0, da, ellipse) ->\n            let c = f ellipse.Center\n            let ax0 = f (ellipse.Center + ellipse.Axis0) - c\n            let ax1 = f (ellipse.Center + ellipse.Axis1) - c\n            let e = Ellipse2d.FromConjugateDiameters(c, ax0, ax1)\n            let q0 = f p0\n            let q1 = f p1\n            let da =\n                if not e.IsCcw then -da\n                else da\n            let a0 = e.GetAlpha q0\n            arcWithPoints q0 q1 a0 da e\n\n    /// tries to create a sub-segment from range [0;t1] and returns None whenever the result would be degenerate.\n    let withT1 (t1 : float) (s : PathSegment) =\n        if t1 <= 0.0 then\n            None\n        elif t1 >= 1.0 then\n            Some s\n        else\n            match s with\n            | LineSeg(p0,_) ->\n                tryLine p0 (point t1 s)\n\n            | ArcSeg(p0, _, a0, da, e) ->\n                let d = t1*da\n                let p = e.GetPoint (a0 + d)\n                ArcSeg(p0, p, a0, d, e) |> Some\n\n            | Bezier2Seg(p0, p1, p2) ->\n                let q0 = lerp p0 p1 t1\n                let q1 = lerp p1 p2 t1\n                let m = lerp q0 q1 t1\n                tryBezier2 p0 q0 m\n\n            | Bezier3Seg(p0, p1, p2, p3) ->\n                let q0 = lerp p0 p1 t1\n                let q1 = lerp p1 p2 t1\n                let q2 = lerp p2 p3 t1\n                let m0 = lerp q0 q1 t1\n                let m1 = lerp q1 q2 t1\n                let m = lerp m0 m1 t1\n                tryBezier3 p0 q0 m0 m\n\n    /// tries to create a sub-segment from range [t0;1] and returns None whenever the result would be degenerate.\n    let withT0 (t0 : float) (s : PathSegment) =\n        if t0 >= 1.0 then\n            None\n        elif t0 <= 0.0 then\n            Some s\n        else\n            match s with\n            | LineSeg(_,p1) ->\n                tryLine (point t0 s) p1\n\n            | ArcSeg(p0, p1, a0, da, e) ->\n                let d = t0 * da\n                let p = e.GetPoint (a0 + d)\n                ArcSeg(p, p1, a0 + d, da - d, e) |> Some\n\n            | Bezier2Seg(p0, p1, p2) ->\n                let q0 = lerp p0 p1 t0\n                let q1 = lerp p1 p2 t0\n                let m = lerp q0 q1 t0\n                tryBezier2 m q1 p2\n\n            | Bezier3Seg(p0, p1, p2, p3) ->\n                let q0 = lerp p0 p1 t0\n                let q1 = lerp p1 p2 t0\n                let q2 = lerp p2 p3 t0\n                let m0 = lerp q0 q1 t0\n                let m1 = lerp q1 q2 t0\n                let m = lerp m0 m1 t0\n                tryBezier3 m m1 q2 p3\n\n    /// tries to create a sub-segment from range [t0;t1] and returns None whenever the result would be degenerate.\n    let withRange (t0 : float) (t1 : float) (s : PathSegment) =\n        if t0 <= 0.0 && t1 >= 1.0 then\n            Some s\n        elif t0 <= 0.0 then\n            withT1 t1 s\n        elif t1 >= 1.0 then\n            withT0 t0 s\n        elif t0 < t1 then\n            match s with\n            | LineSeg(_,_) ->\n                let p0 = point t0 s\n                let p1 = point t1 s\n                tryLine p0 p1\n\n            | ArcSeg(p0, p1, a0, da, e) ->\n                let p0 = a0 + t0 * da\n                let p1 = a0 + t1 * da\n                let d = p1 - p0\n                tryArc p0 d e\n\n            | Bezier2Seg _ ->\n                let p0 = point t0 s\n                let p1 = point t1 s\n                let d0 = tangent t0 s\n                let d1 = tangent t1 s\n\n                let r0 = Ray2d(p0, d0)\n                let r1 = Ray2d(p1, -d1)\n\n                let mutable t = 0.0\n                if r0.Intersects(r1, &t) then\n                    let c = r0.GetPointOnRay t\n                    tryBezier2 p0 c p1\n                else\n                    tryLine p0 p1\n\n            | Bezier3Seg _ ->\n\n                match withT0 t0 s with\n                | Some r ->\n                    withT1 ((t1 - t0) / (1.0 - t0)) r\n                | None ->\n                    None\n        else\n            None\n\n\n    /// tries to split the segment into two new segments having ranges [0;t] and [t;1] respectively.\n    let splitWithCenterPoint (t : float) (pt : V2d) (s : PathSegment) =\n        if t <= 0.0 then (None, Some s)\n        elif t >= 1.0 then (Some s, None)\n        else\n            match s with\n            | LineSeg(p0, p1) ->\n                tryLine p0 pt, tryLine pt p1\n\n            | ArcSeg(p0, p1, a0, da, e) ->\n\n                let l0 = a0\n                let ld = da * t\n\n                let r0 = a0 + ld\n                let rd = da - ld\n\n                let l = ArcSeg(p0, pt, l0, ld, e)\n                let r = ArcSeg(pt, p1, r0, rd, e)\n\n                Some l, Some r\n\n            | Bezier2Seg(p0, p1, p2) ->\n                let q0 = lerp p0 p1 t\n                let q1 = lerp p1 p2 t\n                tryBezier2 p0 q0 pt, tryBezier2 pt q1 p2\n\n            | Bezier3Seg(p0, p1, p2, p3) ->\n                let q0 = lerp p0 p1 t\n                let q1 = lerp p1 p2 t\n                let q2 = lerp p2 p3 t\n                let m0 = lerp q0 q1 t\n                let m1 = lerp q1 q2 t\n                tryBezier3 p0 q0 m0 pt, tryBezier3 pt m1 q2 p3\n\n    /// tries to split the segment into two new segments having ranges [0;t] and [t;1] respectively.\n    let split (t : float) (s : PathSegment) =\n        let pt = point t s\n        splitWithCenterPoint t pt s\n\n    /// tries to get the t-parameter for a point very near the segment (within eps)\n    let tryGetT (eps : float) (pt : V2d) (segment : PathSegment) =\n\n        let newtonImprove (iter : int) (t : float) =\n            let mutable t = t\n            let mutable dt = 1000.0\n            let mutable iter = iter\n            while iter > 0 && not (Fun.IsTiny (dt, 1E-15)) do\n                // err^2 = min\n                // 2*err * err' = 0\n\n                // f = 2*err * err'\n                // f' = 2*(err'^2 + err*err'')\n\n                let err = point t segment - pt\n                let d = derivative t segment\n                let dd = secondDerivative t segment\n\n                //let v = Vec.lengthSquared err\n                let dv = 2.0 * Vec.dot err d\n                let ddv = 2.0 * (Vec.dot d d + Vec.dot err dd)\n\n\n                dt <- -0.8 * dv / ddv\n                //printfn \"%d: %A %A -> %A\" iter t dv dt\n                t <- t + dt\n                iter <- iter - 1\n\n            let t = clamp 0.0 1.0 t\n            let err = point t segment - pt\n            if Fun.IsTiny(err, eps) then Some t\n            else None\n\n        match segment with\n        | LineSeg(p0, p1) ->\n            if Fun.ApproximateEquals(p0, pt, eps) then Some 0.0\n            elif Fun.ApproximateEquals(p1, pt, eps) then Some 1.0\n            else\n                let u = p1 - p0\n                let len = Vec.length u\n                let n = V2d(-u.Y, u.X) / len\n                let d = Vec.dot (pt - p0) n\n                if abs d < eps then\n                    let t = Vec.dot (pt - p0) u / sqr len\n                    if t >= 0.0 && t <= 1.0 then Some t\n                    else None\n                else\n                    None\n        | Bezier2Seg(p0, p1, p2) ->\n            if Fun.ApproximateEquals(p0, pt, eps) then Some 0.0\n            elif Fun.ApproximateEquals(p2, pt, eps) then Some 1.0\n            else\n                let box = Box2d([p0; p1; p2]).EnlargedBy eps\n\n                if box.Contains pt then\n                    let a = p2 + p0 - 2.0*p1\n                    let b = 2.0*(p1 - p0)\n                    let c = p0 - pt\n\n                    let struct(t0, t1) =\n                        if box.Size.MajorDim = 0 then Polynomial.RealRootsOf(a.X, b.X, c.X)\n                        else Polynomial.RealRootsOf(a.Y, b.Y, c.Y)\n\n                    let d0 = if t0 >= 0.0 && t0 <= 1.0 then Vec.length (a * sqr t0 + b * t0 + c) else System.Double.PositiveInfinity\n                    let d1 = if t1 >= 0.0 && t1 <= 1.0 then Vec.length (a * sqr t1 + b * t1 + c) else System.Double.PositiveInfinity\n\n                    if d0 < d1 then\n                        newtonImprove 20 t0\n                    else\n                        if not (System.Double.IsPositiveInfinity d1) then newtonImprove 20 t1\n                        else None\n                else\n                    None\n\n            //t^2 * (p2 + p0 - 2*p1) + t * 2*(p1 - p0) + p0\n\n        | Bezier3Seg(p0, p1, p2, p3) ->\n            if Fun.ApproximateEquals(p0, pt, eps) then Some 0.0\n            elif Fun.ApproximateEquals(p3, pt, eps) then Some 1.0\n            else\n                let box = Box2d([p0; p1; p2; p3]).EnlargedBy eps\n\n                if box.Contains pt then\n                    let a = -p0 + 3.0*p1 - 3.0*p2 + p3\n                    let b = 3.0*p0 - 6.0*p1 + 3.0*p2\n                    let c = 3.0*p1 - 3.0*p0\n                    let d = p0 - pt\n\n                    let struct(t0, t1, t2) =\n                        if box.Size.MajorDim = 0 then Polynomial.RealRootsOf(a.X, b.X, c.X, d.X)\n                        else Polynomial.RealRootsOf(a.Y, b.Y, c.Y, d.Y)\n\n\n                    let t0 = if t0 >= -eps && t0 <= 1.0 + eps then newtonImprove 10 t0 else None\n                    let t1 = if t1 >= -eps && t1 <= 1.0 + eps then newtonImprove 10 t1 else None\n                    let t2 = if t2 >= -eps && t2 <= 1.0 + eps then newtonImprove 10 t2 else None\n\n                    let d0 = match t0 with | Some t0 -> Vec.length (a * sqr t0 + b * t0 + c) | _ -> System.Double.PositiveInfinity\n                    let d1 = match t1 with | Some t1 -> Vec.length (a * sqr t1 + b * t1 + c) | _ -> System.Double.PositiveInfinity\n                    let d2 = match t2 with | Some t2 -> Vec.length (a * sqr t2 + b * t2 + c) | _ -> System.Double.PositiveInfinity\n\n\n                    let result =\n                        if d0 < d1 then\n                            if d0 < d2 then t0\n                            else t2\n                        else\n                            if d1 < d2 then t1\n                            else t2\n\n                    result |> Option.bind (newtonImprove 30)\n\n                else\n                    None\n        | ArcSeg(p0, p1, a, da, e) ->\n            if Fun.ApproximateEquals(p0, pt, eps) then Some 0.0\n            elif Fun.ApproximateEquals(p1, pt, eps) then Some 1.0\n            else\n                let m = M33d.FromCols(V3d(e.Axis0, 0.0), V3d(e.Axis1, 0.0), V3d(e.Center, 1.0))\n\n                let c = m.Inverse.TransformPos(pt) |> Vec.normalize\n                let angle = atan2 c.Y c.X\n\n                let t = arcT a da angle\n\n                if Fun.ApproximateEquals(m.TransformPos c, pt, eps) then\n                    newtonImprove 30 t\n                else\n                    None\n\n    /// tries to merge two segments together resulting in an optional new segment (or None if the segments cannot be merged)\n    let tryMerge (eps : float) (a : PathSegment) (b : PathSegment) =\n        match a with\n        | LineSeg(a0, a1) ->\n            match b with\n            | LineSeg(b0, b1) when Fun.ApproximateEquals(a1, b0, eps) ->\n                if Fun.ApproximateEquals(a0, b1) then\n                    Some None\n                else\n                    let u = Vec.normalize (b1 - a0)\n                    let n = V2d(-u.Y, u.X)\n                    if Fun.IsTiny (Vec.dot n (b0 - a0), eps) then\n                        Some (tryLine a0 b1)\n                    else\n                        None\n            | _ ->\n                None\n        | Bezier2Seg(a0, a1, a2) ->\n            match b with\n            | Bezier2Seg(b0, b1, b2) when Fun.ApproximateEquals(a2, b0, eps) ->\n                if Fun.ApproximateEquals(a0, b2, eps) then\n                    if Fun.ApproximateEquals(a1, b1, eps) then Some None\n                    else None\n                else\n                    let ta1 = a2 - a1 |> Vec.normalize\n                    let tb0 = b1 - b0 |> Vec.normalize\n\n                    if Fun.ApproximateEquals(ta1, tb0, 1E-9) then\n                        let ra = Ray2d(a0, a1 - a0)\n                        let rb = Ray2d(b2, b2 - b1)\n                        let mutable t = 0.0\n                        if ra.Intersects(rb, &t) then\n                            let c = ra.GetPointOnRay t\n                            match tryBezier2 a0 c b2 with\n                            | Some res ->\n                                match tryGetT eps a2 res with\n                                | Some _ -> Some (Some res)\n                                | None -> None\n                            | None ->\n                                None\n                        else\n                            None\n                    elif Fun.ApproximateEquals(ta1, -tb0, 1E-9) then\n                        match tryGetT eps b2 a with\n                        | Some _ ->\n                            let ra = Ray2d(a0, a1 - a0)\n                            let rb = Ray2d(b2, b2 - b1)\n                            let mutable t = 0.0\n                            if ra.Intersects(rb, &t) then\n                                let c = ra.GetPointOnRay t\n                                match tryBezier2 a0 c b2 with\n                                | Some res ->\n                                    Some (Some res)\n                                | None ->\n                                    None\n                            else\n                                None\n                        | None ->\n                            None\n                    else\n                        None\n            | _ ->\n                None\n        | _ ->\n            // TODO: proper merge for Arc/Bezier3\n            None\n\n\n    let private overlapTs = [| 0.25; 0.5; 0.75; 0.333 |]\n\n    /// tries to find the overlapping t-ranges for two segments. The first range will be sorted whereas the second one may not be.\n    let overlap (eps : float) (a : PathSegment) (b : PathSegment) =\n\n        let isOnLine (p0 : V2d) (p1 : V2d) (p : V2d) =\n            let u = p1 - p0\n            let len = Vec.length u\n            let n = V2d(-u.Y, u.X) / len\n            let d = Vec.dot (p - p0) n\n            if abs d < eps then\n                let t = Vec.dot (p - p0) u / sqr len\n                if t >= 0.0 && t <= 1.0 then\n                    let test = lerp p0 p1 t\n                    if not (Fun.ApproximateEquals(test, p, eps)) then printfn \"asdsadsad\"\n                    Some t\n                else\n                    None\n            else\n                None\n\n\n        let inline checkRange ((aRange : Range1d, bRange : V2d) as tup) =\n            let isOverlapping =\n                overlapTs |> Array.forall (fun t ->\n                    let ta = lerp aRange.Min aRange.Max t\n                    let tb = lerp bRange.X bRange.Y t\n                    Fun.ApproximateEquals(point ta a, point tb b)\n                )\n            if isOverlapping then\n                Some tup\n            else\n                None\n\n\n        let a0 = startPoint a\n        let a1 = endPoint a\n\n        let b0 = startPoint b\n        let b1 = endPoint b\n\n        match tryGetT eps b0 a with\n        | Some tab0 ->\n            match tryGetT eps b1 a with\n            | Some tab1 ->\n                // b is entirely on a\n                if tab0 < tab1 then\n                    checkRange (Range1d(tab0, tab1), V2d(0.0, 1.0))\n                else\n                    checkRange (Range1d(tab1, tab0), V2d(1.0, 0.0))\n            | None ->\n                match tryGetT eps a0 b with\n                | Some tba0 ->\n                    checkRange (Range1d(0.0, tab0), V2d(tba0, 0.0))\n                | None ->\n                    match tryGetT eps a1 b with\n                    | Some tba1 ->\n                        checkRange (Range1d(tab0, 1.0), V2d(0.0, tba1))\n                    | None ->\n                        None\n        | None ->\n            match tryGetT eps b1 a with\n            | Some tab1 ->\n                match tryGetT eps a0 b with\n                | Some tba0 ->\n                    checkRange (Range1d(0.0, tab1), V2d(tba0, 1.0))\n                | None ->\n                    match tryGetT eps a1 b with\n                    | Some tba1 ->\n                        checkRange (Range1d(tab1, 1.0), V2d(1.0, tba1))\n                    | None ->\n                        None\n            | None ->\n                match tryGetT eps a0 b with\n                | Some tba0 ->\n                    match tryGetT eps a1 b with\n                    | Some tba1 ->\n                        checkRange (Range1d(0.0, 1.0), V2d(tba0, tba1))\n                    | None ->\n                        None\n                | None ->\n                    None\n\n    /// splits a PathSegment given two ordered ts into possibly three parts (the range must not be empty or invalid)\n    let splitRange (r : Range1d) (seg : PathSegment) : option<PathSegment> * PathSegment * option<PathSegment> =\n        let l, rest = split r.Min seg\n        let m, r = split ((r.Max - r.Min) / (1.0 - r.Min)) (Option.get rest)\n        l, Option.get m, r\n\n\n    /// splits the segment at the given parameter values and returns the list of resulting segments.\n    let splitMany (ts : list<float>) (s : PathSegment) =\n        match ts with\n        | [] -> [s]\n        | _ ->\n            let rec run (ts : list<float>) (s : PathSegment) =\n                match ts with\n                | [] -> [s]\n                | t0 :: ts ->\n                    if t0 <= 0.0 then run ts s\n                    elif t0 >= 1.0 then [s]\n                    else\n                        let ts = ts |> List.map (fun t -> (t-t0)/(1.0-t0))\n                        let l, r = split t0 s\n                        let r =\n                            match r with\n                            | Some r -> run ts r\n                            | None -> []\n                        match l with\n                        | Some l -> l :: r\n                        | None -> r\n            let res = run (List.sort ts) s\n            res\n\n    /// gets all intersection parameter pairs for the two given segments sorted by the first parameter.\n    let intersections (eps : float) (l : PathSegment) (r : PathSegment) =\n        PathSegmentIntersections.intersections eps l r\n\n\n\n[<AutoOpen>]\nmodule ``PathSegment Public API`` =\n\n    type PathSegment with\n        member x.GetSlice(t0 : option<float>, t1 : option<float>) =\n            match t0 with\n            | Some t0 ->\n                match t1 with\n                | Some t1 -> PathSegment.withRange t0 t1 x\n                | None -> PathSegment.withT0 t0 x\n            | None ->\n                match t1 with\n                | Some t1 -> PathSegment.withT1 t1 x\n                | None -> Some x\n\n        member x.Item\n            with inline get(t : float) = PathSegment.point t x\n\n\n\n\n    let (|Line|Bezier2|Bezier3|Arc|) (s : PathSegment) =\n        match s with\n        | LineSeg(p0, p1) -> Line(p0, p1)\n        | Bezier2Seg(p0, p1, p2) -> Bezier2(p0, p1, p2)\n        | Bezier3Seg(p0, p1, p2, p3) -> Bezier3(p0, p1, p2, p3)\n        | ArcSeg(alpha0, alpha1, a0, da, ellipse) -> Arc(alpha0, alpha1, a0, da, ellipse)\n\n    type PathSegment with\n        static member inline Line(p0, p1) = PathSegment.line p0 p1\n        static member inline Bezier2(p0, p1, p2) = PathSegment.bezier2 p0 p1 p2\n        static member inline Bezier3(p0, p1, p2, p3) = PathSegment.bezier3 p0 p1 p2 p3\n        static member inline Arc(a0, da, p3) = PathSegment.arc a0 da p3\n\n        static member ForceLine(p0, p1) = LineSeg(p0, p1)\n        static member ForceBezier2(p0, p1, p2) = Bezier2Seg(p0, p1, p2)\n        static member ForceBezier3(p0, p1, p2, p3) = Bezier3Seg(p0, p1, p2, p3)\n        static member ForceArc(p0, p1, a0, da, e) = ArcSeg(p0, p1, a0, da, e)\n\n\n    module PathSegment =\n        let (|Line|Bezier2|Bezier3|Arc|) (s : PathSegment) =\n            match s with\n            | LineSeg(p0, p1) -> Line(p0, p1)\n            | Bezier2Seg(p0, p1, p2) -> Bezier2(p0, p1, p2)\n            | Bezier3Seg(p0, p1, p2, p3) -> Bezier3(p0, p1, p2, p3)\n            | ArcSeg(alpha0, alpha1, a0, da, ellipse) -> Arc(alpha0, alpha1, a0, da, ellipse)\n\n\n    let inline Line(p0, p1) = PathSegment.line p0 p1\n    let inline Bezier2(p0, p1, p2) = PathSegment.bezier2 p0 p1 p2\n    let inline Bezier3(p0, p1, p2, p3) = PathSegment.bezier3 p0 p1 p2 p3\n    let inline Arc(a0, da, p3) = PathSegment.arc a0 da p3\n\n"
  },
  {
    "path": "src/Aardvark.Base.Fonts/PathTessellator.fs",
    "content": "﻿namespace Aardvark.Base.Fonts\n\nopen FSharp.Data.Adaptive\nopen Aardvark.Base\nopen BvhImpl\n\n[<Struct>]\ntype ShapeGeometry(positions: V3f[], coordinates: V4f[]) =\n    member _.Positions = positions\n    member _.Coordinates = coordinates\n\nmodule internal Tessellator =\n    open LibTessDotNet.Double\n\n    [<AutoOpen>]\n    module private Helpers =\n\n        type Ellipse2d with\n            member internal x.GetControlPoint(alpha0 : float, alpha1 : float) =\n                let p0 = x.GetPoint alpha0\n                let p1 = x.GetPoint alpha1\n                let t0 = cos alpha0 * x.Axis1 - sin alpha0 * x.Axis0 |> Vec.normalize\n                let t1 = cos alpha1 * x.Axis1 - sin alpha1 * x.Axis0 |> Vec.normalize\n                let n0 = Ray2d(p0, t0)\n                let n1 = Ray2d(p1, t1)\n                let pc = n0.Intersect(n1)\n                pc\n\n        type Part =\n            | PolygonalPart of PathSegment * Polygon2d\n            | LinePart of Line2d\n\n        module Part =\n\n            let intersectsConvex (eps : float) (l : Polygon2d) (r : Polygon2d) =\n                let tess = Tess()\n\n                let c0 = System.Collections.Generic.List<ContourVertex>()\n                for p in l.Points do c0.Add(ContourVertex(Vec3(X = p.X, Y = p.Y)))\n                c0.Add(c0.[0])\n\n                let c1 = System.Collections.Generic.List<ContourVertex>()\n                for p in r.Points do c1.Add(ContourVertex(Vec3(X = p.X, Y = p.Y)))\n                c1.Add(c1.[0])\n                tess.AddContour(c0, ContourOrientation.CounterClockwise)\n                tess.AddContour(c1, ContourOrientation.CounterClockwise)\n                tess.Tessellate(WindingRule.AbsGeqTwo, ElementType.BoundaryContours, normal = Vec3(0.0, 0.0, 1.0))\n\n                let mutable empty = true\n                let mutable ei = 0\n                for _ in 0 .. tess.ElementCount - 1 do\n                    let o = tess.Elements.[ei]\n                    let c = tess.Elements.[ei+1]\n\n                    let mutable box = Box2d.Invalid\n                    let mutable vi = o\n                    for i in 0 .. c - 1 do\n                        let v = tess.Vertices.[vi]\n                        let p = V2d(v.Position.X, v.Position.Y)\n                        box.ExtendBy p\n                        vi <- vi + 1\n\n                    if box.Size.NormMax > eps then empty <- false\n\n                    ei <- ei + 2\n\n\n                not empty\n\n\n\n            let private linesIntersect (eps : float) (l : Line2d) (r : Line2d) =\n                let lr = l.Ray2d\n                let rr = r.Ray2d\n                let mutable t = 0.0\n                if lr.Intersects(rr, &t) && t >= 1E-8 && t <= 1.0 - 1E-8 then\n                    true\n                else\n                    false\n\n            let inline private sgn (eps : float) (v : float) =\n                if v < -eps then -1\n                elif v > eps then 1\n                else 0\n\n            let private polyAndLineIntersect (eps : float) (l : Polygon2d) (r : Line2d) =\n                use e = l.EdgeLines.GetEnumerator()\n\n                let mutable side0 = 0\n                let mutable side1 = 0\n\n                let mutable intersects = false\n                while not intersects && e.MoveNext() do\n                    let ll = e.Current\n\n                    let v0 = r.P0.PosLeftOfLineValue(ll.P0, ll.P1) |> sgn eps\n                    let v1 = r.P1.PosLeftOfLineValue(ll.P0, ll.P1) |> sgn eps\n\n                    if side0 = 0 then side0 <- v0\n                    elif side0 <> v0 then side0 <- 10\n\n                    if side1 = 0 then side1 <- v1\n                    elif side1 <> v1 then side1 <- 10\n\n                    if linesIntersect 1E-7 ll r then\n                        intersects <- true\n\n                intersects || (side0 = 1 || side0 = -1) || (side1 = 1 || side1 = -1)\n\n\n\n            let overlaps (l : Part) (r : Part) =\n                match l, r with\n                | LinePart l, LinePart r -> false //linesIntersect 1E-7 l r\n                | PolygonalPart(_,l), LinePart r -> polyAndLineIntersect 1E-7 l r\n                | LinePart l, PolygonalPart(_,r) -> polyAndLineIntersect 1E-7 r l\n                | PolygonalPart(_,l), PolygonalPart(_,r) ->\n                    intersectsConvex 1E-6 l r\n\n            let ofPathSegment (s : PathSegment) =\n                match s with\n                | Line(p0, p1) ->\n                    LinePart(Line2d(p0, p1))\n                | Bezier2(p0, p1, p2) ->\n                    PolygonalPart(s, Polygon2d [| p0; p1; p2 |])\n                | Bezier3(p0, p1, p2, p3) ->\n                    PolygonalPart(s, Polygon2d [| p0; p1; p2; p3 |])\n                | Arc(p0, p2, alpha0, dAlpha, ellipse) ->\n                    let p1 = ellipse.GetControlPoint(alpha0, alpha0 + dAlpha)\n                    PolygonalPart(s, Polygon2d [| p0; p1; p2 |])\n\n            let bounds (p : Part) =\n                match p with\n                | LinePart l -> l.BoundingBox2d\n                | PolygonalPart(_,p) -> p.BoundingBox2d\n\n            let toPathSegment (s : Part) =\n                match s with\n                | LinePart l -> PathSegment.line l.P0 l.P1\n                | PolygonalPart(s,_) -> s\n\n            let toLineArray (p : Part) =\n                match p with\n                | LinePart(l) ->\n                    [| l.P0; l.P1 |]\n                | PolygonalPart(_,p) ->\n                    let arr = Array.zeroCreate (2 * p.PointCount)\n                    let mutable oi = 0\n                    let mutable last = p.[p.PointCount - 1]\n                    for i in 0 .. p.PointCount - 1 do\n                        let p = p.[i]\n                        arr.[oi] <- last\n                        arr.[oi+1] <- p\n                        last <- p\n                        oi <- oi + 2\n                    arr\n\n            let startPoint (p : Part) =\n                match p with\n                | PolygonalPart(s,_) ->\n                    match s with\n                    | Line(p0, p1) -> p0\n                    | Bezier2(p0, p1, _) -> p0\n                    | Bezier3(p0, p1, _, _) -> p0\n                    | Arc(p0, _, _, _, _) -> p0\n                | LinePart l ->\n                    l.P0\n\n            let endPoint (p : Part) =\n                match p with\n                | PolygonalPart(s,_) ->\n                    match s with\n                    | Line(_, p1) -> p1\n                    | Bezier2(_, _, p2) -> p2\n                    | Bezier3(_, _, _, p3) -> p3\n                    | Arc(_, p1, _, _, _) -> p1\n                | LinePart l ->\n                    l.P1\n\n            let startTangent (p : Part) =\n                match p with\n                | PolygonalPart(s,_) ->\n                    PathSegment.tangent 0.0 s\n\n                | LinePart l ->\n                    Vec.normalize (l.P1 - l.P0)\n\n            let endTangent (p : Part) =\n                match p with\n                | PolygonalPart(s,_) ->\n                    PathSegment.tangent 1.0 s\n                | LinePart l ->\n                    Vec.normalize (l.P1 - l.P0)\n\n        let toBvh (positions : V2d[], triangleIndex : int[]) =\n            let mutable bvh = BvhTree2d.empty\n\n            let mutable bi = 0\n            let maxe = triangleIndex.Length - 2\n            let mutable ti = 0\n            while bi < maxe do\n                let i0 = triangleIndex.[bi]\n                let i1 = triangleIndex.[bi+1]\n                let i2 = triangleIndex.[bi+2]\n                let tri = Triangle2d(positions.[i0], positions.[i1], positions.[i2])\n\n                bvh <- bvh.Add(ti, tri.BoundingBox2d, tri)\n\n                bi <- bi + 3\n                ti <- ti + 1\n            bvh\n\n        let toBvhLine (polys : V2d[][]) =\n            let mutable bvh = BvhTree2d.empty\n\n            for poly in polys do\n                if poly.Length > 1 then\n                    let mutable p0 = poly.[poly.Length - 1]\n                    for i in 0 .. poly.Length - 1 do\n                        let p1 = poly.[i]\n                        let line = Line2d(p0, p1)\n                        let bb = line.BoundingBox2d.EnlargedBy(1E-8)\n                        bvh <- BvhTree2d.add line bb line bvh\n                        p0 <- p1\n\n            bvh\n\n        let containsPoint (bvh : BvhTree2d<int, Triangle2d>) (pt : V2d) =\n            let b = Box2d.FromCenterAndSize(pt, V2d.II * 1E-5)\n\n            let contains (t : Triangle2d) (pt : V2d) =\n                let eps = 1E-9\n\n                let a = pt.PosLeftOfLineValue(t.P0, t.P1)\n                let b = pt.PosLeftOfLineValue(t.P1, t.P2)\n                let c = pt.PosLeftOfLineValue(t.P2, t.P0)\n\n                if a >= -eps && b >= -eps && c >= -eps then Some t\n                elif a <= eps && b <= eps && c <= eps then Some t\n                else None\n\n\n                //let u = t.P1 - t.P0\n                //let v = t.P2 - t.P1\n                //let w = t.P0 - t.P2\n\n\n                //let ccw = u.X*v.Y - u.Y*v.X > 0.0\n                //let intersects =\n                //    if ccw then t.Contains pt\n                //    else Triangle2d(t.P0, t.P2, t.P1).Contains pt\n\n                //if intersects then Some t\n                //else None\n                //let m = M33d.FromCols(V3d(u, 0.0), V3d(v, 0.0), V3d(t.P0, 1.0))\n                //let mi = m.Inverse\n                //let uv = mi.TransformPos pt\n\n                //if uv.X >= -1E-9 && uv.Y >= -1E-9 && uv.X + uv.Y <= 1.0 + 1E-9 then\n                //    if not (t.Contains pt) then Log.warn \"asdsadlnmaskmdkasmdkl\"\n                //    Some t\n                //else\n                //    None\n\n\n\n\n            bvh.GetIntersecting(b, fun _ _ t -> contains t pt)\n            |> HashMap.isEmpty\n            |> not\n\n        let hasPoint (bvh : BvhTree2d<int, Triangle2d>) (pt : V2d) =\n            let b = Box2d.FromCenterAndSize(pt, V2d.II * 1E-3)\n            bvh.GetIntersecting(b, fun _ _ t -> if Fun.ApproximateEquals(t.P0, pt, 1E-9) || Fun.ApproximateEquals(t.P1, pt, 1E-9) || Fun.ApproximateEquals(t.P2, pt, 1E-9) then Some t else None)\n            |> HashMap.isEmpty\n            |> not\n\n        let containsPointLine (bvh : BvhTree2d<Line2d, Line2d>) (pt : V2d) =\n            let b = Box2d.FromCenterAndSize(pt, V2d.II * 1E-5)\n            bvh.GetIntersecting(b, fun _ _ t ->\n                let r = pt.GetClosestPointOn t\n                if Fun.ApproximateEquals(r, pt, 1E-9) then Some t\n                else None\n            )\n            |> HashMap.isEmpty\n            |> not\n\n        let hasEdge (bvh : BvhTree2d<Line2d, Line2d>) (p0 : V2d) (p1 : V2d) =\n            let edge = Line2d(p0, p1)\n            let b = edge.BoundingBox2d.EnlargedBy(1E-6)\n\n            if Fun.ApproximateEquals(p0, p1, 1E-9) then\n                // has point\n                bvh.GetIntersecting(b, fun _ _ t ->\n                    if (Fun.ApproximateEquals(t.P0, edge.P0, 1E-9) || Fun.ApproximateEquals(t.P1, edge.P1, 1E-9)) then\n                        Some t\n                    else\n                        None\n                )\n                |> HashMap.isEmpty\n                |> not\n            else\n                bvh.GetIntersecting(b, fun _ _ t ->\n                    if (Fun.ApproximateEquals(t.P0, edge.P0, 1E-9) && Fun.ApproximateEquals(t.P1, edge.P1, 1E-9)) ||\n                       (Fun.ApproximateEquals(t.P1, edge.P0, 1E-9) && Fun.ApproximateEquals(t.P0, edge.P1, 1E-9)) then\n                        Some t\n                    else\n                        None\n                )\n                |> HashMap.isEmpty\n                |> not\n\n        let private turningAngle (t0 : V2d) (t1 : V2d) =\n            let a = t0.X * t1.Y - t0.Y * t1.X\n            let b = t0.X * t1.X + t0.Y * t1.Y\n            atan2 a b\n\n        let boundary (rule : WindingRule) (parts : seq<#seq<V2d>>) =\n            let tess = Tess()\n            let emptys = System.Collections.Generic.List<V2d[]>()\n            for path in parts do\n                let vertices = System.Collections.Generic.List<ContourVertex>()\n\n                for pt in path do\n                    ContourVertex(Vec3(X = pt.X, Y = pt.Y)) |> vertices.Add\n\n                if vertices.Count > 2 then\n                    vertices.Add(vertices.[0])\n                    tess.AddContour(vertices, ContourOrientation.Original)\n                else\n                    let arr = Seq.toArray path\n                    if arr.Length > 1 then\n                        emptys.Add arr\n\n            tess.Tessellate(rule, ElementType.BoundaryContours, normal = Vec3(0.0, 0.0, 1.0))\n\n            let mutable i = 0\n            let res = Array.zeroCreate (emptys.Count + tess.ElementCount)\n            let mutable pi = 0\n\n            for e in emptys do\n                res.[pi] <- e\n                pi <- pi + 1\n\n            for _ in 0 .. tess.ElementCount - 1 do\n                let i0 = tess.Elements.[i]\n                let cnt = tess.Elements.[i+1]\n                if cnt > 2 then\n                    let arr = Array.zeroCreate cnt\n\n                    let mutable oi = 0\n                    for vi in i0 .. i0 + cnt - 1 do\n                        let v = tess.Vertices.[vi]\n                        let p = V2d(v.Position.X, v.Position.Y)\n                        arr.[oi] <- p\n                        oi <- oi + 1\n\n                    res.[pi] <- arr\n                else\n                    res.[pi] <- [||]\n                pi <- pi + 1\n                i <- i + 2\n            res\n\n        let triangulate (rule : WindingRule) (parts : seq<#seq<V2d>>) =\n            let tess = Tess()\n            for path in parts do\n                let vertices = System.Collections.Generic.List<ContourVertex>()\n\n                for pt in path do\n                    ContourVertex(Vec3(X = pt.X, Y = pt.Y)) |> vertices.Add\n\n                vertices.Add vertices.[0]\n                tess.AddContour(vertices, ContourOrientation.Original)\n\n            tess.Tessellate(rule, ElementType.Polygons, 3, normal = Vec3(0.0, 0.0, 1.0))\n            if tess.ElementCount > 0 then\n                let positions = tess.Vertices |> Array.map (fun v -> V2d(v.Position.X, v.Position.Y))\n                let index = tess.Elements\n                positions, index\n            else\n                [||], [||]\n\n\n    module private Coords =\n        let bezier3 (q0 : V2d) (q1 : V2d) (q2 : V2d) (q3 : V2d) =\n            let m3 =\n                M44d(\n                    +1.0,  0.0,  0.0,  0.0,\n                    -3.0,  3.0,  0.0,  0.0,\n                    +3.0, -6.0,  3.0,  0.0,\n                    -1.0,  3.0, -3.0,  1.0\n                )\n\n            let m3i =\n                M44d(\n                    1.0,  0.0,      0.0,     0.0,\n                    1.0,  1.0/3.0,  0.0,     0.0,\n                    1.0,  2.0/3.0,  1.0/3.0, 0.0,\n                    1.0,  1.0,      1.0,     1.0\n                )\n\n            let b =\n                M44d.FromRows(\n                    V4d(q0.X, q0.Y, 0.0, 1.0),\n                    V4d(q1.X, q1.Y, 0.0, 1.0),\n                    V4d(q2.X, q2.Y, 0.0, 1.0),\n                    V4d(q3.X, q3.Y, 0.0, 1.0)\n                )\n\n            let bla = m3 * b\n            let p0 = bla.R0.XYW\n            let p1 = bla.R1.XYW\n            let p2 = bla.R2.XYW\n            let p3 = bla.R3.XYW\n\n            let d0 =  M33d.FromRows(p3, p2, p1).Determinant\n            let d1 = -M33d.FromRows(p3, p2, p0).Determinant\n            let d2 =  M33d.FromRows(p3, p1, p0).Determinant\n            let d3 = -M33d.FromRows(p2, p1, p0).Determinant\n\n            let delta1 = d0*d2 - d1*d1\n            let delta2 = d1*d2 - d0*d3\n            let delta3 = d1*d3 - d2*d2\n            let discr = 4.0*delta1*delta3 - delta2*delta2\n\n            let inline flip (v : V3d) = V3d(-v.X, -v.Y, v.Z)\n\n            let qs2 = 3.0*d2*d2 - 4.0*d1*d3\n\n            if qs2 >= 0.0 && not (Fun.IsTiny(d1, 1E-8)) then\n                // serpentine / Cusp with inflection at infinity\n                let qs = sqrt(qs2 / 3.0)\n                let l = V2d(d2 + qs, 2.0*d1).Normalized\n                let m = V2d(d2 - qs, 2.0*d1).Normalized\n\n                let tl = l.X\n                let sl = l.Y\n                let tm = m.X\n                let sm = m.Y\n\n                let F =\n                    M44d(\n                        tl*tm,          tl*tl*tl,                   tm*tm*tm,                   1.0,\n                        -sm*tl-sl*tm,   -3.0*sl*tl*tl,              -3.0*sm*tm*tm,              0.0,\n                        sl*sm,          3.0*sl*sl*tl,               3.0*sm*sm*tm,               0.0,\n                        0.0,            -sl*sl*sl,                  -sm*sm*sm,                  0.0\n                    )\n\n                let shouldFlip = d1 > 0.0 // TODO\n                let w = m3i * F\n                if shouldFlip then Choice1Of2(7, flip w.R0.XYZ, flip w.R1.XYZ, flip w.R2.XYZ, flip w.R3.XYZ)\n                else Choice1Of2(7, w.R0.XYZ, w.R1.XYZ, w.R2.XYZ, w.R3.XYZ)\n\n            elif qs2 < 0.0 && not (Fun.IsTiny(d1, 1E-8)) then\n                // loop\n                let ql = sqrt(-qs2)\n                let d = V2d(d2 + ql, 2.0*d1).Normalized\n                let e = V2d(d2 - ql, 2.0*d1).Normalized\n\n                let td = d.X\n                let sd = d.Y\n                let te = e.X\n                let se = e.Y\n\n                let a = td / sd\n                let b = te / se\n\n                let va = a >= 1E-3 && a <= 1.0 - 1E-3\n                let vb = b >= 1E-3 && b <= 1.0 - 1E-3\n\n                if va then\n                    Choice2Of2(PathSegment.splitMany [a] (PathSegment.bezier3 q0 q1 q2 q3))\n                elif vb then\n                    Choice2Of2(PathSegment.splitMany [b] (PathSegment.bezier3 q0 q1 q2 q3))\n                else\n                    let F =\n                        M44d(\n                            td*te,          td*td*te,                   td*te*te,                   1.0,\n                            -se*td-sd*te,   -se*td*td-2.0*sd*te*td,     -sd*te*te-2.0*se*td*te,     0.0,\n                            sd*se,          te*sd*sd+2.0*se*td*sd,      td*se*se+2.0*sd*te*se,      0.0,\n                            0.0,            -sd*sd*se,                  -sd*se*se,                  0.0\n                        )\n\n                    let w = m3i * F\n\n                    let shouldNotFlip = (d1 > 0.0 && w.M10 < 0.0) || (d1 < 0.0 && w.M10 > 0.0)\n\n                    if not shouldNotFlip then Choice1Of2(8, flip w.R0.XYZ, flip w.R1.XYZ, flip w.R2.XYZ, flip w.R3.XYZ)\n                    else Choice1Of2(8, w.R0.XYZ, w.R1.XYZ, w.R2.XYZ, w.R3.XYZ)\n\n            elif Fun.IsTiny(d1, 1E-8) && not (Fun.IsTiny(d1, 1E-8)) then\n                // Cusp with cusp at infinity\n\n\n                let l = V2d(d3, 3.0*d2).Normalized\n                let tl = l.X\n                let sl = l.Y\n\n                let F =\n                    M44d(\n                        tl,         tl*tl*tl,       1.0, 1.0,\n                        -sl,        -3.0*sl*tl*tl,  0.0, 0.0,\n                        0.0,        3.0*sl*sl*tl,   0.0, 0.0,\n                        0.0,        -sl*sl*sl,      0.0, 0.0\n                    )\n\n                let w = m3i * F\n                Choice1Of2(6, w.R0.XYZ, w.R1.XYZ, w.R2.XYZ, w.R3.XYZ)\n\n            elif Fun.IsTiny(d1, 1E-8) && Fun.IsTiny(d2, 1E-8) && not (Fun.IsTiny(d3, 1E-8)) then\n                let qc = 1.5*q2 - 0.5*q3 //(3.0*(q1 + q2) - q0 - q3)/4.0\n                match PathSegment.tryBezier2 q0 qc q3 with\n                | Some l -> Choice2Of2 [l]\n                | None -> Choice2Of2 []\n\n            else\n                match PathSegment.tryLine q0 q3 with\n                | Some l -> Choice2Of2 [l]\n                | None -> Choice2Of2 []\n\n    /// tries to split the segment into two new segments having ranges [0;t] and [t;1] respectively.\n    let split (t : float) (pt : V2d) (s : PathSegment) =\n        if t <= 0.0 then (None, Some s)\n        elif t >= 1.0 then (Some s, None)\n        else\n            match s with\n            | Line(p0, p1) ->\n                PathSegment.tryLine p0 pt, PathSegment.tryLine pt p1\n\n            | Arc(p0, p1, a0, da, e) ->\n\n                let l0 = a0\n                let ld = da * t\n\n                let r0 = a0 + ld\n                let rd = da - ld\n\n                let l = PathSegment.ForceArc(p0, pt, l0, ld, e)\n                let r = PathSegment.ForceArc(pt, p1, r0, rd, e)\n\n                Some l, Some r\n                //let left =\n                //    match tryArc l0 ld e with\n                //    | Some(ArcSeg(_,_,a0,da,e)) -> Some (ArcSeg(p0, pm, a0, da, e))\n                //    | Some(LineSeg _) -> Some (LineSeg(p0, pm))\n                //    | o -> o\n\n                //let right =\n                //    match tryArc r0 rd  e with\n                //    | Some(ArcSeg(_,_,a0,da,e)) -> Some (ArcSeg(pm, p1, a0, da, e))\n                //    | Some(LineSeg _) -> Some (LineSeg(pm, p1))\n                //    | o -> o\n\n                //left, right\n\n\n            | Bezier2(p0, p1, p2) ->\n                let q0 = lerp p0 p1 t\n                let q1 = lerp p1 p2 t\n                PathSegment.tryBezier2 p0 q0 pt, PathSegment.tryBezier2 pt q1 p2\n\n            | Bezier3(p0, p1, p2, p3) ->\n                let q0 = lerp p0 p1 t\n                let q1 = lerp p1 p2 t\n                let q2 = lerp p2 p3 t\n                let m0 = lerp q0 q1 t\n                let m1 = lerp q1 q2 t\n                PathSegment.tryBezier3 p0 q0 m0 pt, PathSegment.tryBezier3 pt m1 q2 p3\n\n\n    /// splits the segment at the given parameter values and returns the list of resulting segments.\n    let splitMany (ts : list<float * V2d>) (s : PathSegment) =\n        match ts with\n        | [] -> [s]\n        | _ ->\n            let rec run (ts : list<float * V2d>) (s : PathSegment) =\n                match ts with\n                | [] -> [s]\n                | (t0, p0) :: ts ->\n                    if t0 <= 0.0 then run ts s\n                    elif t0 >= 1.0 then [s]\n                    else\n                        let ts = ts |> List.map (fun (t,p) -> (t-t0)/(1.0-t0), p)\n                        let l, r = split t0 p0 s\n\n                        let r =\n                            match r with\n                            | Some r -> run ts r\n                            | None -> []\n                        match l with\n                        | Some l -> l :: r\n                        | None -> r\n            run ts s\n\n    let splitManyMany (l : PathSegment) (intersections : seq<'a * PathSegment * list<float*float>>) : list<PathSegment> * HashMap<'a, list<PathSegment>> =\n        let intersections = Seq.toList intersections\n\n        let all =\n            intersections\n            |> List.collect (fun (id, r, ts) -> ts |> List.map (fun (tl, tr) -> tl, (id, r, tr)))\n            |> List.sortBy fst\n\n        let rec run (splits : HashMap<'a, PathSegment * Map<float, V2d>>) (interactions : list<float * ('a * PathSegment * float)>) (l : PathSegment) =\n            match interactions with\n            | [] ->\n                [l], splits\n            | (tl, (ri, r, tr)) :: rest ->\n                let l0, l1 = PathSegment.split tl l\n\n                match l1 with\n                | Some l1 ->\n\n                    let pt = PathSegment.startPoint l1\n                    let inline update (old : option<PathSegment * Map<float, V2d>>) =\n                        match old with\n                        | Some (s, m) ->\n                            Some (s, Map.add tr pt m)\n                        | None ->\n                            Some(r, Map.ofList [tr, pt])\n\n                    let splits = HashMap.alter ri update splits\n                    let rest = rest |> List.map (fun (ti, r) -> (ti - tl) / (1.0 - tl), r)\n\n                    let result, splits = run splits rest l1\n                    match l0 with\n                    | Some l0 -> l0 :: result, splits\n                    | None -> result, splits\n                | None ->\n                    match l0 with\n                    | Some l0 -> [l0], splits\n                    | None -> [], splits\n\n        let self, result = run HashMap.empty all l\n\n        let others =\n            result |> HashMap.map (fun _ (s, m) ->\n                splitMany (Map.toList m) s\n            )\n\n        self, others\n\n\n    let toGeometry (rule : WindingRule) (bounds : Box2d) (inputPath : seq<PathSegment>) : ShapeGeometry =\n        let trafo =\n            let size = bounds.Size.Length\n            let scale =\n                if Fun.IsTiny size then 1.0\n                else 1.0 / size\n            Trafo2d.Translation(-bounds.Center) *\n            Trafo2d.Scale scale\n\n        let path =\n            let trafo (pt : V2d) = trafo.Forward.TransformPos pt\n            inputPath |> Seq.map (PathSegment.transform trafo) |> Seq.toList\n\n        let split (part : Part) =\n            match part with\n            | PolygonalPart(s, _) ->\n                let (l,r) = PathSegment.split 0.5 s\n                match l, r with\n                | Some l, Some r ->\n                    [l;r]\n                | Some v, None\n                | None, Some v ->\n                    [v]\n                | None, None ->\n                    []\n            | LinePart l ->\n                [PathSegment.line l.P0 l.P1]\n\n        let turningAngle (t0 : V2d) (t1 : V2d) =\n            let a = t0.X * t1.Y - t0.Y * t1.X\n            let b = t0.X * t1.X + t0.Y * t1.Y\n            atan2 a b\n\n        let neededSplits (s : PathSegment) =\n            match s with\n            | Bezier3(p0, p1, p2, p3) ->\n                match Coords.bezier3 p0 p1 p2 p3 with\n                | Choice2Of2 replacement ->\n                    Some replacement\n                | _ ->\n                    None\n            | Arc(p0, p1, alpha0, dAlpha, ellipse) ->\n\n                let t0 = ellipse.GetPoint(alpha0)\n                let t1 = ellipse.GetPoint(alpha0 + dAlpha)\n\n                let steps = dAlpha / Constant.PiQuarter |> abs |> round |> int |> max 1\n                if steps > 1 then\n                    let mutable a0 = alpha0\n                    let mutable p0 = p0\n                    let step = dAlpha / float steps\n                    let res =\n                        List.init steps (fun i ->\n                            let a1 = a0 + step\n                            let p1 = if i = steps - 1 then p1 else ellipse.GetPoint a1\n                            let seg = PathSegment.arcWithPoints p0 p1 a0 step ellipse\n\n                            a0 <- a1\n                            p0 <- p1\n                            seg\n                        )\n                    Some res\n                else\n                    None\n            | _ ->\n                None\n\n        // get rid of intersections\n        let rec nonIntersecting (result : IndexList<PathSegment>) (bvh : BvhTree2d<Index, PathSegment>) (stack : list<PathSegment>) =\n\n            let replace (i : Index) (repl : seq<PathSegment>) (l : IndexList<PathSegment>) (bvh : BvhTree2d<Index, PathSegment>) =\n                use e = repl.GetEnumerator()\n                if e.MoveNext() then\n                    let _,_,r = IndexList.neighbours i l\n                    let indexAfter =\n                        match r with\n                        | Some(ri,_) -> fun i -> Index.between i ri\n                        | None -> Index.after\n\n                    let mutable b = BvhTree2d.remove i bvh\n                    let mutable i = i\n                    let mutable l = l |> IndexList.set i e.Current\n                    b <- BvhTree2d.add i (PathSegment.bounds e.Current) e.Current b\n                    while e.MoveNext() do\n                        i <- indexAfter i\n                        l <- IndexList.set i e.Current l\n                        b <- BvhTree2d.add i (PathSegment.bounds e.Current) e.Current b\n\n                    l, b\n                else\n                    let l1 = IndexList.remove i l\n                    let b1 = BvhTree2d.remove i bvh\n                    l1, b1\n\n            match stack with\n            | s :: stack ->\n                let b = PathSegment.bounds s\n\n                let intersecting =\n                    let teps = 1E-7\n                    bvh.GetIntersecting(b, fun _ _ other ->\n                        let all = PathSegment.intersections 1E-9 s other\n                        let parameters =\n                            all\n                            |> List.filter (fun (ta, tb) -> (ta >= teps && ta <= 1.0-teps) || (tb >= teps && tb <= 1.0-teps))\n\n                        match parameters with\n                        | [] -> None\n                        | ts -> Some (other, ts)\n                    )\n\n                if HashMap.isEmpty intersecting then\n                    let idx = Index.after result.MaxIndex\n                    let result1 = IndexList.set idx s result\n                    let bvh1 = bvh.Add(idx, b, s)\n                    nonIntersecting result1 bvh1 stack\n                else\n\n                    let self, others = splitManyMany s (HashMap.toSeq intersecting |> Seq.map (fun (a,(b,c)) -> a,b,c))\n\n                    //let mine =\n                    //    intersecting\n                    //    |> HashMap.toList\n                    //    |> List.collect (fun (o, (_, ts)) -> ts |> List.map fst)\n                    //    |> List.sort\n\n                    //let self = s |> PathSegment.splitMany mine\n\n                    let mutable r = result\n                    let mutable b = bvh\n                    for (oi, res) in others do\n                        let (r1, b1) = replace oi res r b\n                        r <- r1\n                        b <- b1\n\n\n                    //let mutable r = result\n                    //let mutable b = bvh\n                    //for (oi, (o, ts)) in intersecting do\n                    //    let ts = ts |> List.map snd\n                    //    let res = PathSegment.splitMany ts o\n                    //    let (r1, b1) = replace oi res r b\n                    //    r <- r1\n                    //    b <- b1\n\n\n                    nonIntersecting r b (self @ stack)\n\n            | [] ->\n                result, bvh\n\n        let path1,_ = nonIntersecting IndexList.empty BvhTree2d.empty path\n\n        // get rid of overlapping triangulations\n        let rec nonOverlapping (result : IndexList<Part>) (bvh : BvhTree2d<Index, Part>) (stack : list<PathSegment>) =\n            match stack with\n            | s :: stack ->\n                let replacements = neededSplits s\n\n                match replacements with\n                | Some repl ->\n                    nonOverlapping result bvh (repl @ stack)\n                | None ->\n                    let part = Part.ofPathSegment s\n                    let b = Part.bounds part\n\n                    let intersecting =\n                        bvh.GetIntersecting(b, fun _ _ other ->\n                            if Part.overlaps part other then Some other\n                            else None\n                        )\n\n                    if HashMap.isEmpty intersecting then\n                        let idx = Index.after result.MaxIndex\n                        let result1 = IndexList.set idx part result\n                        let bvh1 = bvh.Add(idx, b, part)\n                        nonOverlapping result1 bvh1 stack\n                    else\n                        let (bvh, result) =\n                            intersecting\n                            |> HashMap.choose (fun _ o -> match o with | PolygonalPart _ -> Some o | _ -> None)\n                            |> HashMap.fold (fun (obvh : BvhTree2d<Index, Part>, result : IndexList<Part>) idx part ->\n                                let bvh = BvhTree2d.remove idx obvh\n                                match split part with\n                                | [] ->\n                                    (bvh, IndexList.remove idx result)\n                                | [n] ->\n                                    let np = Part.ofPathSegment n\n                                    (BvhTree2d.add idx (Part.bounds np) np bvh, IndexList.set idx np result)\n                                | n :: many ->\n                                    let np = Part.ofPathSegment n\n                                    let mutable bvh = BvhTree2d.add idx (Part.bounds np) np bvh\n                                    let mutable result = IndexList.set idx np result\n                                    let mutable idx = idx\n                                    for m in many do\n                                        let i =\n                                            let (_,_,r) = IndexList.neighbours idx result\n                                            match r with\n                                            | Some(ri, _) -> Index.between idx ri\n                                            | None -> Index.after idx\n\n                                        let mp = Part.ofPathSegment m\n                                        result <- IndexList.set i mp result\n                                        bvh <- BvhTree2d.add i (Part.bounds mp) mp bvh\n                                        idx <- i\n\n                                    (bvh, result)\n                            ) (bvh, result)\n\n                        let self = split part\n                        nonOverlapping result bvh (self @ stack)\n            | _ ->\n                result |> IndexList.toList\n\n        let cleaned = nonOverlapping IndexList.empty BvhTree2d.empty (Seq.toList path1)\n\n        // find closed sub-paths\n        let rec findClosed (exteriorAngle : float) (last : V2d) (current : IndexList<Part>) (stack : list<Part>) =\n            match stack with\n            | part :: stack ->\n                let p0 = Part.startPoint part\n                let p1 = Part.endPoint part\n\n                if Fun.ApproximateEquals(last, p0) || last.IsNaN then\n                    let t0 = Part.startTangent part\n                    let t1 = Part.endTangent part\n                    let selfAngle = turningAngle t0 t1\n                    let cornerAngle =\n                        match IndexList.tryLast current with\n                        | Some last ->\n                            let tl = Part.endTangent last\n                            turningAngle tl t0\n                        | _ ->\n                            0.0\n                    let idx = Index.after current.MaxIndex\n                    let result1 = IndexList.set idx part current\n                    let exteriorAngle1 = exteriorAngle + selfAngle + cornerAngle\n\n                    match Seq.tryHead result1 with\n                    | Some start when Fun.ApproximateEquals(Part.startPoint start, p1, 1E-8) ->\n                        let cornerAngle = turningAngle (Part.endTangent part) (Part.startTangent start)\n                        let exteriorAngle2 = exteriorAngle1 + cornerAngle\n\n                        let rest = findClosed 0.0 V2d.NaN IndexList.empty stack\n\n                        (exteriorAngle2, result1) :: rest\n                    | _ ->\n                        findClosed exteriorAngle1 p1 result1 stack\n                else\n                    match Seq.tryHead current with\n                    | Some start ->\n                        findClosed exteriorAngle last current (LinePart(Line2d(last, Part.startPoint start)) :: part :: stack)\n                    | _ ->\n                        findClosed 0.0 V2d.NaN IndexList.empty stack\n            | [] ->\n                match Seq.tryHead current with\n                | Some start ->\n                    findClosed exteriorAngle last current [LinePart(Line2d(last, Part.startPoint start))]\n                | _ ->\n                    []\n\n        let parts = findClosed 0.0 V2d.NaN IndexList.empty cleaned |> IndexList.ofList\n\n        // triangulate the non-curved boundary\n        let nonCurvedBoundary =\n            parts |> Seq.choose (fun (_angle,path) ->\n                if path.Count > 0 then\n                    path |> IndexList.toSeqIndexed |> Seq.map (fun (i,s) ->\n                        Part.startPoint s\n                    ) |> Some\n                else\n                    None\n            )\n            |> boundary rule\n\n        let pos, idx =\n            nonCurvedBoundary\n            |> triangulate WindingRule.Positive\n\n        let nonCurved = toBvh (pos, idx)\n\n        // find the final solid boundary and triangulate it\n        let boundary =\n            let tess = Tess()\n            let emptys = System.Collections.Generic.List<V2d[]>()\n            for (_exterior, path) in parts do\n                if not (IndexList.isEmpty path) then\n                    let contour = System.Collections.Generic.List<ContourVertex>()\n\n                    let inline add (v : V2d) =\n                        contour.Add(ContourVertex(Vec3(X = v.X, Y = v.Y)))\n\n                    for part in path do\n                        match part with\n                        | LinePart l ->\n                            add l.P0\n                        | PolygonalPart(s, p) ->\n                            match s with\n                            | Line(p0, p1) ->\n                                add p0\n                            | Bezier2(p0, p1, p2) ->\n                                add p0\n                                if containsPoint nonCurved p1 then add p1\n                            | Bezier3(p0, p1, p2, p3) ->\n\n\n                                let points = [|p0;p1;p2;p3|]\n                                let hull = Polygon2d(points).ComputeConvexHullIndexPolygon().Indices |> Seq.toArray\n\n\n                                add p0\n                                if Array.contains 1 hull && containsPoint nonCurved p1 then add p1\n                                if Array.contains 2 hull && containsPoint nonCurved p2 then add p2\n\n                            | Arc(p0, p2, alpha0, dAlpha, ellipse) ->\n                                let p1 = ellipse.GetControlPoint(alpha0, alpha0 + dAlpha)\n                                add p0\n                                if containsPoint nonCurved p1 then add p1\n\n                    if contour.Count > 2 then\n                        contour.Add(contour.[0])\n\n                        if contour.Count > 0 then\n                            tess.AddContour(contour)\n                    elif contour.Count > 1 then\n                        emptys.Add(contour.MapToArray(fun v -> V2d(v.Position.X, v.Position.Y)))\n\n            tess.Tessellate(rule, ElementType.BoundaryContours, normal = Vec3(0.0, 0.0, 1.0))\n\n            let res = Array.zeroCreate (emptys.Count + tess.ElementCount)\n            let mutable ei = 0\n            let mutable i = 0\n\n            for e in emptys do\n                res.[i] <- e\n                i <- i + 1\n\n            for _ in 0 .. tess.ElementCount - 1 do\n                let o = tess.Elements.[ei]\n                let c = tess.Elements.[ei+1]\n                let arr = Array.zeroCreate c\n\n                let mutable vi = o\n                for j in 0 .. c - 1 do\n                    let v = tess.Vertices.[vi]\n                    arr.[j] <- V2d(v.Position.X, v.Position.Y)\n                    vi <- vi + 1\n\n                res.[i] <- arr\n                ei <- ei + 2\n                i <- i + 1\n            res\n\n        let pos, idx =\n            boundary\n            |> triangulate WindingRule.Positive\n\n\n        let toGlobal = trafo.Backward\n\n        let mutable cnt = 0\n        let mutable positions : V3f[]   = Array.zeroCreate (if idx.Length > 1024 then Fun.NextPowerOfTwo idx.Length else 1024)\n        let mutable coords    : V4f[]   = Array.zeroCreate positions.Length\n\n        for i = 0 to (idx.Length / 3) - 1 do\n            let p0 = pos.[idx.[i * 3]]\n            let p1 = pos.[idx.[i * 3 + 1]]\n            let p2 = pos.[idx.[i * 3 + 2]]\n\n            if abs <| Triangle.WindingOrder(p0, p1, p2) > 1E-16 then\n                positions.[cnt] <- V2f(toGlobal.TransformPos p0).XYO\n                positions.[cnt + 1] <- V2f(toGlobal.TransformPos p1).XYO\n                positions.[cnt + 2] <- V2f(toGlobal.TransformPos p2).XYO\n                cnt <- cnt + 3\n\n        let inline add (p0 : V2d) (p1 : V2d) (p2 : V2d) (c0 : V4f) (c1 : V4f) (c2 : V4f) =\n            let flip = Triangle.WindingOrder(p0, p1, p2) < 0.0\n            let p0, p2, c0, c2 = if flip then p2, p0, c2, c0 else p0, p2, c0, c2\n\n            let newCnt = cnt + 3\n            if newCnt > positions.Length then\n                System.Array.Resize(&positions, Fun.NextPowerOfTwo newCnt)\n                System.Array.Resize(&coords, positions.Length)\n\n            positions.[cnt] <- V2f(toGlobal.TransformPos p0).XYO\n            positions.[cnt + 1] <- V2f(toGlobal.TransformPos p1).XYO\n            positions.[cnt + 2] <- V2f(toGlobal.TransformPos p2).XYO\n\n            coords.[cnt] <- c0\n            coords.[cnt + 1] <- c1\n            coords.[cnt + 2] <- c2\n\n            cnt <- cnt + 3\n\n        let edges = toBvhLine boundary\n        // all polygonal parts not fully contained in the solid part need to be rendered.\n        // since all polygonal parts are non-overlapping, convex and are connected to at least two boundary points\n        // it should be sufficient to test whether or not their \"center\" point is covered by the solid part.\n        let solid = toBvh (pos, idx)\n        for (extAngle,path) in parts do\n            for s in path do\n                match s with\n                | PolygonalPart(s, _) ->\n                    let c = PathSegment.point 0.5 s\n                    let inside = containsPoint solid c\n                    if not inside then\n                        match s with\n                        | Line _ ->\n                            ()\n\n                        | Bezier2(p0, p1, p2) ->\n                            if hasEdge edges p0 p2 || (hasEdge edges p0 p1 && hasEdge edges p1 p2) then\n                                if containsPoint nonCurved p1 then\n                                    add p0 p1 p2\n                                        (V4f(0,0,-1,2)) (V4f(-0.5, 0.0,-1.0, 2.0)) (V4f(-1,1,-1,2))\n                                else\n                                    add p0 p1 p2\n                                        (V4f(0,0,1,3)) (V4f(0.5, 0.0, 1.0,3.0)) (V4f(1,1,1,3))\n\n                        | Arc(p0, p2, alpha0, dAlpha, ellipse) ->\n                            let uv2World = M33d.FromCols(V3d(ellipse.Axis0, 0.0), V3d(ellipse.Axis1, 0.0), V3d(ellipse.Center, 1.0))\n                            let world2UV = uv2World.Inverse\n                            let p1 = ellipse.GetControlPoint(alpha0, alpha0 + dAlpha)\n\n                            if hasEdge edges p0 p2 || (hasEdge edges p0 p1 && hasEdge edges p1 p2) then\n                                let c0 = world2UV.TransformPos p0\n                                let c1 = world2UV.TransformPos p1\n                                let c2 = world2UV.TransformPos p2\n\n                                if containsPoint nonCurved p1 then\n                                    add p0 p1 p2\n                                        (V4f(c0.X, c0.Y,-1.0, 4.0)) (V4f(c1.X, c1.Y,-1.0, 4.0)) (V4f(c2.X, c2.Y,-1.0,4.0))\n                                else\n                                    add p0 p1 p2\n                                        (V4f(c0.X, c0.Y,1.0, 5.0)) (V4f(c1.X, c1.Y,1.0, 5.0)) (V4f(c2.X, c2.Y,1.0,5.0))\n\n\n                        | Bezier3(p0, p1, p2, p3) ->\n                            match Coords.bezier3 p0 p1 p2 p3 with\n                            | Choice1Of2(k, c0, c1, c2, c3) ->\n\n                                let touching =\n                                    hasEdge edges p0 p3 || (\n                                        let e01 = hasEdge edges p0 p1\n                                        let e12 = hasEdge edges p1 p2\n                                        let e23 = hasEdge edges p2 p3\n                                        (e01 && e12 && e23) ||\n                                        (e01 && hasEdge edges p1 p3) ||\n                                        (e23 && hasEdge edges p0 p2)\n                                    )\n\n                                if touching then\n\n                                    let points  = [|p0;p1;p2;p3|]\n                                    let weights = [|c0;c1;c2;c3|]\n                                    let hull = Polygon2d(points).ComputeConvexHullIndexPolygon().Indices |> Seq.toArray\n\n                                    let ws = hull |> Array.map (fun i -> weights.[i])\n                                    let ps = hull |> Array.map (fun i -> points.[i])\n\n                                    //let pc, cc =\n                                    //    if Fun.ApproximateEquals(p0, p1, 1E-9) then p2, c2\n                                    //    else p1, c2\n\n                                    //let ccInside = cc.X*cc.X*cc.X - cc.Y*cc.Z < 0.0\n                                    //let pcInside = containsPoint nonCurved pc\n\n                                    let inline flip (v : V3d) = V3d(-v.XY, v.Z)\n                                    let ws = if extAngle > 0.0 then Array.map flip ws else ws\n\n                                    if hull.Length = 3 then\n                                        add ps.[0] ps.[1] ps.[2]\n                                            (V4f(ws.[0], float k)) (V4f(ws.[1], float k)) (V4f(ws.[2],float k))\n                                    else\n                                        add ps.[0] ps.[1] ps.[3]\n                                            (V4f(ws.[0], float k)) (V4f(ws.[1], float k)) (V4f(ws.[3],float k))\n                                        add ps.[3] ps.[1] ps.[2]\n                                            (V4f(ws.[3], float k)) (V4f(ws.[1], float k)) (V4f(ws.[2],float k))\n\n\n                            | _ ->\n                                failwith \"should have been subdivided\"\n\n\n                | _ ->\n                    ()\n\n        if cnt < positions.Length then\n            System.Array.Resize(&positions, cnt)\n            System.Array.Resize(&coords, cnt)\n\n        ShapeGeometry(positions, coords)"
  },
  {
    "path": "src/Aardvark.Base.Fonts/paket.references",
    "content": "FSharp.Core\nAardvark.Build\nUnofficial.LibTessDotNet\nUnofficial.Typography\nFuzzySharp"
  },
  {
    "path": "src/Aardvark.Base.Fonts/paket.template",
    "content": "type project\nid Aardvark.Base.Fonts\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.Base.IO/Aardvark.Base.IO.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks>\r\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n    <NoWarn>612;1591</NoWarn>\r\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r\n    <LangVersion>10.0</LangVersion>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n\t<Compile Remove=\"**\\*_template.cs\" />\r\n\t<Compile Remove=\"**\\*_generator.cs\" />\r\n\t<Compile Remove=\"Properties\\**\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n\t<None Include=\"**\\*_template.cs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <EmbeddedResource Remove=\"Properties\\**\" />\r\n    <None Remove=\"Properties\\**\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\Aardvark.Base.Tensors.CSharp\\Aardvark.Base.Tensors.CSharp.csproj\" />\r\n    <ProjectReference Include=\"..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\r\n    <ProjectReference Include=\"..\\Aardvark.Base\\Aardvark.Base.csproj\">\r\n      <Project>{c90c041e-e076-4bbc-bbcd-b29367f649a2}</Project>\r\n      <Name>Aardvark.Base</Name>\r\n    </ProjectReference>\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.IO/Annotations.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base.Coder\n{\n    internal static class AnnotatedExtensions\n    {\n        public static Annotated<T> Annotate<T>(this T self)\n        {\n            return new Annotated<T>(self);\n        }\n        public static Annotated<T> Annotate<T>(this T self, string key, object value)\n        {\n            return new Annotated<T>(self, key, value);\n        }\n        public static Annotated<T> Annotate<T>(this T self, IEnumerable<Annotation> tags)\n        {\n            return new Annotated<T>(self, tags);\n        }\n        public static Annotated<T> Annotate<T>(this Annotated<T> self, string key, object value)\n        {\n            return new Annotated<T>(self, key, value);\n        }\n        public static Annotated<T> Annotate<T>(this Annotated<T> self, IEnumerable<Annotation> tags)\n        {\n            return new Annotated<T>(self, tags);\n        }\n    }\n\n    internal struct Annotation\n    {\n        public string Key { get; private set; }\n        public object Value { get; private set; }\n        public override readonly string ToString() { return string.Format(\"{0} -> {1}\", Key, Value); }\n\n        public Annotation(string key, object value)\n            : this()\n        {\n            Key = key;\n            Value = value;\n        }\n    }\n\n    internal readonly struct Annotated<T>\n    {\n        private readonly T m_value;\n        private readonly IEnumerable<Annotation> m_tags;\n        private static readonly IEnumerable<Annotation> s_empty = System.Array.Empty<Annotation>();\n\n        public Annotated(T value)\n        {\n            m_value = value;\n            m_tags = s_empty;\n        }\n        public Annotated(T value, string tagKey, object tagValue)\n        {\n            m_value = value;\n            m_tags = new[] { new Annotation(tagKey, tagValue) };\n        }\n        public Annotated(T value, IEnumerable<Annotation> tags)\n        {\n            m_value = value;\n            m_tags = tags.ToArray();\n        }\n        public Annotated(Annotated<T> a)\n        {\n            m_value = a.Value;\n            m_tags = a.Tags.ToArray();\n        }\n        public Annotated(Annotated<T> a, string tagKey, object tagValue)\n        {\n            m_value = a.Value;\n            m_tags = a.Tags.Concat(new[] { new Annotation(tagKey, tagValue) });\n        }\n        public Annotated(Annotated<T> a, IEnumerable<Annotation> tags)\n        {\n            m_value = a.Value;\n            m_tags = a.Tags.Concat(tags.ToArray());\n        }\n\n        public T Value { get { return m_value; } }\n        public IEnumerable<Annotation> Tags { get { return m_tags ?? s_empty; } }\n\n        private string _debugView { get { return m_value.ToString(); } }\n        private Annotation[] _tagsDebugView { get { return Tags.ToArray(); } }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/BaseCoder.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base.Coder\n{\n    [Flags]\n    public enum CoderDebugMode\n    {\n        None = 0x0000,\n        ReportObjects = 0x0001,\n        ReportFields = 0x0002,\n        ReportReferences = 0x0004,\n        ReportQualifiedNames = 0x008,\n        ReportAll = 0xffff,\n    }\n\n    /// <summary>\n    /// Root class for all coders, currently handles only debug mode.\n    /// </summary>\n    public class BaseCoder\n    {\n        protected bool m_doRefs;\n        protected CoderDebugMode m_debugMode;\n        protected Stack<TypeInfo> m_typeInfoStack;\n        protected Stack<int> m_versionStack;\n        protected int m_version;\n        internal const int c_coderVersion = 4;\n                                // 3: KdTreeSet, SphereSet, TriangleSet are still Maps (later SymMaps)\n                                // 2: old SymMap coding\n                                // 1: wrong coding of SceneGraph Attribute<T>\n                                // 0: wrong coding of null strings\n\n        #region Contructor\n\n        public BaseCoder()\n        {\n            if (!s_initTypeInfosCalled) InitTypeInfos();\n            TypeCoder.Default.Init();\n            m_doRefs = true;\n            m_debugMode = CoderDebugMode.None;\n            m_typeInfoStack = new Stack<TypeInfo>();\n            m_versionStack = new Stack<int>();\n            m_version = 0;\n        }\n\n        private static bool s_initTypeInfosCalled = false;\n        private static readonly object s_initTypeInfosLock = new Object();\n\n        private static void InitTypeInfos()\n        {\n            lock (s_initTypeInfosLock)\n            {\n                if (!s_initTypeInfosCalled)\n                {\n                    s_initTypeInfosCalled = true;\n                    foreach (var assembly in Introspection.AllAssemblies)\n                    {\n                        var typeInfos = Introspection.GetAllTypesWithAttribute<RegisterTypeInfoAttribute>(assembly).ToArray();\n                        foreach (var x in typeInfos)\n                        {\n                            Report.Line(4, \"[RegisterTypeInfo] {0}\", x.Item1.FullName);\n                            try\n                            {\n                                foreach (var a in x.Item2)\n                                    TypeInfo.Add(x.Item1, a.Version);\n                            }\n                            catch (Exception e)\n                            {\n                                Report.Warn(\"Error registering TypeInfo:\\n{0}\", e.ToString());\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        #endregion\n\n        #region Properties\n\n        public CoderDebugMode DebugMode\n        {\n            get { return m_debugMode; }\n            set { m_debugMode = value; }\n        }\n\n        public TypeInfo TypeInfo\n        {\n            get { return m_typeInfoStack.Peek(); }\n        }\n\n        #endregion\n\n        #region Constants\n\n        internal static readonly Symbol AardvarkSymbol = Symbol.Create(\"Aardvark\");\n        internal static readonly Symbol VersionSymbol = Symbol.Create(\"version\");\n        internal static readonly Symbol NumSymbol = Symbol.Create(\"num\");\n        internal static readonly Symbol CountSymbol = Symbol.Create(\"count\");\n        internal static readonly Symbol TypeSymbol = Symbol.Create(\"type\");\n        internal static readonly Symbol NullSymbol = Symbol.Create(\"null\");\n        internal static readonly Symbol RefSymbol = Symbol.Create(\"ref\");\n\n        #endregion\n    }\n\n    /// <summary>\n    /// This class handles type information for reading coders.\n    /// </summary>\n    public class BaseReadingCoder : BaseCoder\n    {\n        protected Dictionary<string, TypeInfo> m_typeInfoOfName;\n        private readonly Stack<List<TypeInfo>> m_typeInfoArrayStack;\n        protected List<object> m_refs;\n\n        #region Constructor\n\n        public BaseReadingCoder() : base()\n        {\n            m_typeInfoOfName = new Dictionary<string, TypeInfo>();\n            m_typeInfoArrayStack = new Stack<List<TypeInfo>>();\n            m_refs = new List<object>();\n        }\n\n        #endregion\n\n        #region Properties\n\n        public bool IsReading { get { return true; } }\n        public bool IsWriting { get { return false; } }\n        public List<object> Refs { get { return m_refs; } set { m_refs = value; } }\n\n        #endregion\n\n        #region TypeInfo Management\n\n        public void Add(TypeInfo[] tia)\n        {\n            var oldTypeInfoList = new List<TypeInfo>();\n            foreach (var ti in tia)\n            {\n                TypeInfo old;\n                if (m_typeInfoOfName.TryGetValue(ti.Name, out old))\n                    oldTypeInfoList.Add(old);\n                m_typeInfoOfName.Add(ti.Name, ti);\n                if (ti.Type == typeof(TypeCoder.Reference)\n                    && ((ti.Options & TypeInfo.Option.Active) == 0))\n                    m_doRefs = false;\n            }\n            m_typeInfoArrayStack.Push(oldTypeInfoList);\n        }\n\n        public void Del(TypeInfo[] tia)\n        {\n            foreach (var ti in tia)\n            {\n                m_typeInfoOfName.Remove(ti.Name);\n                if (ti.Type == typeof(TypeCoder.Reference)) m_doRefs = true;\n            }\n            var oldTypeInfoList = m_typeInfoArrayStack.Pop();\n            foreach (var ti in oldTypeInfoList)\n            {\n                m_typeInfoOfName.Add(ti.Name, ti);\n                if (ti.Type == typeof(TypeCoder.Reference)\n                    && ((ti.Options & TypeInfo.Option.Active) == 0))\n                    m_doRefs = false;\n            }\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// This class handles type information for writing coders.\n    /// </summary>\n    public class BaseWritingCoder : BaseCoder\n    {\n        protected Dictionary<Type, TypeInfo> m_typeInfoOfType;\n        private readonly Stack<List<TypeInfo>> m_typeInfoArrayStack;\n        protected Dictionary<object, int> m_refs;\n\n        #region Constructor\n\n        public BaseWritingCoder() : base()\n        {\n            m_typeInfoOfType = new Dictionary<Type, TypeInfo>();\n            m_typeInfoArrayStack = new Stack<List<TypeInfo>>();\n            m_refs = new Dictionary<object, int>();\n        }\n\n        #endregion\n\n        #region Properties\n\n        public bool IsReading { get { return false; } }\n        public bool IsWriting { get { return true; } }\n        public Dictionary<object, int> Refs { get { return m_refs; } set { m_refs = value; } }\n\n        #endregion\n\n        #region TypeInfo Management\n\n        internal bool TryGetTypeInfo(Type type, out TypeInfo ti)\n        {\n            if (m_typeInfoOfType.TryGetValue(type, out ti)) return true;\n            return TypeInfo.OfType.TryGetValue(type, out ti);\n        }\n\n        public void Add(TypeInfo[] tia)\n        {\n            var oldTypeInfoList = new List<TypeInfo>();\n            foreach (var ti in tia)\n            {\n                TypeInfo old;\n                if (m_typeInfoOfType.TryGetValue(ti.Type, out old))\n                    oldTypeInfoList.Add(old);\n                m_typeInfoOfType.Add(ti.Type, ti);\n                if (ti.Type == typeof(TypeCoder.Reference)\n                    && ((ti.Options & TypeInfo.Option.Active) == 0))\n                    m_doRefs = false;\n            }\n            m_typeInfoArrayStack.Push(oldTypeInfoList);\n        }\n\n        public void Del(TypeInfo[] tia)\n        {\n            foreach (var ti in tia)\n            {\n                m_typeInfoOfType.Remove(ti.Type);\n                if (ti.Type == typeof(TypeCoder.Reference)) m_doRefs = true;\n            }\n            var oldTypeInfoList = m_typeInfoArrayStack.Pop();\n            foreach (var ti in oldTypeInfoList)\n            {\n                m_typeInfoOfType.Add(ti.Type, ti);\n                if (ti.Type == typeof(TypeCoder.Reference)\n                    && ((ti.Options & TypeInfo.Option.Active) == 0))\n                    m_doRefs = false;\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/BinaryReadingCoder.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// A class for reading binary files in an Aardvark specific format.\n    /// </summary>\n    public partial class BinaryReadingCoder\n        : BaseReadingCoder, ICoder, IDisposable, IReadingCoder\n    {\n        private readonly StreamCodeReader m_reader;\n        private string m_fileName;\n        private readonly int m_coderVersion;\n        private readonly bool m_disposeStream;\n\n        #region Constructors\n\n        public BinaryReadingCoder(Stream stream) : base()\n        {\n            m_reader = new StreamCodeReader(stream, Encoding.UTF8);\n            m_fileName = null;\n            var identifier = m_reader.ReadString();\n            if (identifier != \"Aardvark\")\n                throw new InvalidOperationException(\n                        \"attempted read on a file of a format unknown to \"\n                        + \"Aardvark\");\n            m_coderVersion = m_reader.ReadInt32();\n            if (m_coderVersion < 0\n                || m_coderVersion > c_coderVersion)\n                throw new InvalidOperationException(\n                        \"attempted read on an Aardvark file with an \"\n                        + \"unsupported coder version\");\n            /* var size = */m_reader.ReadInt64();\n            m_disposeStream = false;\n        }\n\n        public BinaryReadingCoder(string fileName)\n            : this(File.OpenRead(fileName))\n        {\n            m_fileName = fileName;\n            m_disposeStream = true;\n        }\n\n        #endregion\n\n        #region Static Convenience Functions\n\n        public static object ReadFirstObject(string fileName)\n        {\n            object first = null;\n            using (var coder = new BinaryReadingCoder(fileName))\n                coder.Code(ref first);\n            return first;\n        }\n\n        public static object ReadFirstObject(Stream stream)\n        {\n            object first = null;\n            using (var coder = new BinaryReadingCoder(stream))\n                coder.Code(ref first);\n            return first;\n        }\n\n        public static T ReadFirst<T>(string fileName)\n        {\n            T first = default(T);\n            using (var coder = new BinaryReadingCoder(fileName))\n                coder.CodeT(ref first);\n            return first;\n        }\n\n        public static T ReadFirst<T>(Stream stream)\n        {\n            T first = default(T);\n            using (var coder = new BinaryReadingCoder(stream))\n                coder.CodeT(ref first);\n            return first;\n        }\n\n        #endregion\n\n        #region ICoder Members\n\n        public string FileName\n        {\n            get { return m_fileName; }\n            set { m_fileName = value; }\n        }\n\n        public int CoderVersion { get { return m_coderVersion; } }\n\n        public int StreamVersion { get { return m_version; } }\n\n        public int MemoryVersion { get { return m_typeInfoStack.Peek().Version; } }\n\n        internal bool TryGetTypeInfo(string name, out TypeInfo ti)\n        {\n            if (m_typeInfoOfName.TryGetValue(name, out ti)) return true;\n            if (TypeInfo.OfName.TryGetValue(name, out ti)) return true;\n            return TypeInfo.TryGetOfFullName(name, out ti);\n        }\n\n        private int AddRef(object obj)\n        {\n            int count = m_refs.Count;\n            m_refs.Add(obj);\n            if ((m_debugMode & CoderDebugMode.ReportReferences) != 0)\n            {\n                Report.Line(\"{0,32}   0x{1:x}\", count, obj.GetHashCode());\n            }\n            return count;\n        }\n\n        private object UseRef(int refNum)\n        {\n            object obj = m_refs[refNum];\n            if ((m_debugMode & CoderDebugMode.ReportReferences) != 0)\n            {\n                Report.Line(\"{0,32} * 0x{1:x}\", refNum, obj.GetHashCode());\n            }\n            return obj;\n        }\n\n        private object UseRef(Guid guid)\n        {\n            // TODO\n\n            return null;\n        }\n\n\n        public void Code(ref object obj)\n        {\n            var typeName = m_reader.ReadString();\n            TypeInfo newTypeInfo = null;\n            TypeInfo typeInfo;\n            int objRef = -1;\n\n            if (TryGetTypeInfo(typeName, out typeInfo))\n            {\n                if (typeInfo.Type == typeof(TypeCoder.Null))\n                {\n                    if ((typeInfo.Options & TypeInfo.Option.Active) != 0)\n                    {\n                        obj = null;\n                        return;\n                    }\n                    else\n                        throw new Exception(\"cannot decode null object \"\n                            + \"- change by configuring coder with \"\n                            + \"\\\"coder.Add(TypeCoder.Default.Null);\\\"\");\n                }\n                if (typeInfo.Type == typeof(TypeCoder.Reference))\n                {\n                    if ((typeInfo.Options & TypeInfo.Option.Active) != 0)\n                    {\n                        if (CoderVersion < 5)\n                            obj = UseRef(m_reader.ReadInt32());\n                        else\n                        {\n                            obj = UseRef(m_reader.ReadGuid());\n                        }\n                        return;\n                    }\n                    else\n                        throw new Exception(\n                            \"cannot decode multiply referenced object \"\n                            + \"- change by configuring coder with \"\n                            + \"\\\"coder.Add(TypeCoder.Default.Reference);\\\"\");\n                }\n            }\n            else\n            {\n                typeInfo = new TypeInfo(typeName, Type.GetType(typeName),\n                            TypeInfo.Option.Size | TypeInfo.Option.Version);\n                if ((m_debugMode & CoderDebugMode.ReportQualifiedNames) != 0)\n                    Report.Line(\"qualified name \\\"{0}\\\"\", typeName);\n            }\n\n            if ((typeInfo.Options & TypeInfo.Option.Version) != 0)\n            {\n                m_versionStack.Push(m_version);\n                m_version = m_reader.ReadInt32();\n                if (m_version < typeInfo.Version)\n                {\n                    TypeInfo oldTypeInfo;\n                    if (typeInfo.VersionMap.TryGetValue(m_version, out oldTypeInfo))\n                    {\n                        newTypeInfo = typeInfo; typeInfo = oldTypeInfo;\n                    }\n                }\n            }\n\n            long end = 0;\n            if ((typeInfo.Options & TypeInfo.Option.Size) != 0)\n                end = m_reader.ReadInt64() + m_reader.BaseStream.Position;\n\n            if (typeInfo.Type != null)\n            {\n                if (! TypeCoder.ReadPrimitive(this, typeInfo.Type, ref obj))\n                {\n                    if ((typeInfo.Options & TypeInfo.Option.Ignore) != 0)\n                    {\n                        m_reader.BaseStream.Position = end;\n                        obj = null;\n                    }\n                    else\n                    {\n                        var codedVersion = m_version;\n\n                        m_typeInfoStack.Push(typeInfo);\n\n                        if (typeInfo.Creator != null)\n                            obj = typeInfo.Creator();\n                        else\n                            obj = FastObjectFactory.ObjectFactory(typeInfo.Type)();\n\n                        if ((m_debugMode & CoderDebugMode.ReportObjects) != 0)\n                        {\n                            Report.Line(\"{0,-34} 0x{1:x}\", typeName, obj.GetHashCode());\n                        }\n\n                        if (m_doRefs) objRef = AddRef(obj);\n\n                        #region code fields based on supported interface\n\n                        var fcobj = obj as IFieldCodeable;\n                        if (fcobj != null)\n                        {\n                            CodeFields(typeInfo.Type, codedVersion, fcobj);\n                            if (typeInfo.ProxyType != null)\n                            {\n                                obj = typeInfo.Proxy2ObjectFun(fcobj);\n                                if (m_doRefs) m_refs[objRef] = obj; // fix reference after proxy conversion -> Issue when sub-object (in CodeFields) codes this object! (see #77)\n                            }\n                            else\n                            {\n                                var tmobj = obj as ITypedMap;\n                                if (tmobj != null) CodeFields(typeInfo.Type, tmobj);\n                            }\n                            if ((typeInfo.Options & TypeInfo.Option.Size) != 0)\n                            {\n                                if (m_reader.BaseStream.Position != end)\n                                {\n                                    Report.Warn(\"invalid stream position after reading type \\\"{0}\\\" (potentially skipping referenced objects)\", typeName);\n                                    m_reader.BaseStream.Position = end;\n                                }\n                            }\n                        }\n                        else\n                        {\n                            if ((typeInfo.Options & TypeInfo.Option.Size) != 0)\n                            {\n                                m_reader.BaseStream.Position = end;\n                                Report.Warn(\n                                    \"skipping object of uncodeable type \\\"{0}\\\" (potentially skipping referenced objects)\",\n                                    typeName);\n                                obj = null;\n                            }\n                            else\n                                throw new Exception(\n                                        \"cannot skip uncodeable object of type \\\"\"\n                                        + typeName + '\"');\n                        }\n\n                        var aobj = obj as IAwakeable;\n                        if (aobj != null) aobj.Awake(codedVersion); // codedVersion\n                        #endregion\n\n                        m_typeInfoStack.Pop();\n                    }\n                }\n            }\n            else\n            {\n                if ((typeInfo.Options & TypeInfo.Option.Size) != 0)\n                {\n                    m_reader.BaseStream.Position = end;\n                    Report.Warn(\"skipping object of unknown type \" + typeName);\n                    obj = null;\n                }\n                else\n                    throw new Exception(\n                            \"cannot skip object of unknown type \\\"\"\n                            + typeName + '\"');\n            }\n\n            if ((typeInfo.Options & TypeInfo.Option.Version) != 0)\n            {\n                m_version = m_versionStack.Pop();\n                if (obj != null && newTypeInfo != null)\n                {\n                    var source = new Convertible(typeInfo.Name, obj);\n                    var target = new Convertible(newTypeInfo.Name, null);\n                    source.ConvertInto(target);\n                    obj = target.Data;\n                    if (m_doRefs) m_refs[objRef] = obj; // fix reference after conversion -> Issue when sub-object (in CodeFields) codes this object! (see #77)\n                }\n            }\n        }\n\n        public void CodeFields(Type type, int version, IFieldCodeable obj)\n        {\n            FieldCoder[] fca = FieldCoderArray.Get(m_coderVersion, type, version, obj);\n\n            if ((m_debugMode & CoderDebugMode.ReportFields) == 0)\n            {\n                foreach (var fc in fca)\n                    fc.Code(this, obj);\n            }\n            else\n            {\n                foreach (var fc in fca)\n                {\n                    Report.Line(\"  {0}\", fc.Name);\n                    fc.Code(this, obj);\n                }\n            }\n        }\n\n        public void CodeFields(Type type, ITypedMap obj)\n        {\n            TypeOfString fieldTypeMap = FieldTypeMap.Get(type, obj);\n\n            int fieldCount = m_reader.ReadInt32();\n\n            while (fieldCount-- > 0)\n            {\n                string fieldName = m_reader.ReadString();\n                if ((m_debugMode & CoderDebugMode.ReportFields) != 0)\n                    Report.Line(\"  {0}\", fieldName);\n                object value = null;\n                bool directlyCodeable = m_reader.ReadBoolean();\n                if (directlyCodeable)\n                {\n                    Type fieldType;\n                    if (!fieldTypeMap.TryGetValue(fieldName, out fieldType))\n                        throw new InvalidOperationException(String.Format(\"Could not get type of field \\\"{0}\\\"\", fieldName));\n                        // this can happen if a SymMap is used and a field has been removed\n                    TypeCoder.Read(this, fieldType, ref value);\n                }\n                else\n                    Code(ref value);\n                obj[fieldName] = value;\n            }\n        }\n\n        public void CodeT<T>(ref T obj)\n        {\n            object o = default(T);\n            var type = typeof(T);\n            if (type == typeof(Array))\n                Code(ref o);\n            else\n                TypeCoder.Read(this, type, ref o);\n            obj = (T)o;\n        }\n\n        public object ReferenceObject(int refNum)\n        {\n            return null;\n        }\n\n        private bool CodeNull<T>(ref T value) where T: class\n        {\n            bool isNonNull = m_reader.ReadBoolean();\n            if (isNonNull) return false;\n            value = null;\n            return true;\n        }\n\n        public int CodeCount<T>(ref T value, Func<int, T> creator) where T : class\n        {\n            int count = m_reader.ReadInt32();\n            if (count < 0)\n            {\n                switch (count)\n                {\n                    case -1:\n                        value = null; return -1;\n                    case -2:\n                        int refNum = m_reader.ReadInt32();\n                        if (refNum >= m_refs.Count)\n                        {\n                            Report.Warn(\"skipping invalid reference to \" + refNum);\n                            value = null; return -1;\n                        }\n                        value = (T)UseRef(refNum);\n                        return -2;\n                    default:\n                        Report.Warn(\"encountered invalid count of \" + count);\n                        value = null; return -1;\n                }\n            }\n            value = creator(count);\n            if (m_doRefs) AddRef(value); \n            return count;\n        }\n\n        private long CodeLong(long intValue)\n        {\n            return ((intValue & (long)int.MaxValue) << 32) + (long)m_reader.ReadUInt32();\n        }\n\n        /// <summary>\n        /// Backward compatible extension for coding collections with 64-bit lengths.\n        /// </summary>\n        public long CodeCountLong<T>(ref T value, Func<long, T> creator) where T : class\n        {\n            long count = m_reader.ReadInt32();\n            if (count < 0)\n            {\n                switch (count)\n                {\n                    case -1:\n                        value = null; return -1L;\n                    case -2:\n                        int refNum = m_reader.ReadInt32();\n                        if (refNum >= m_refs.Count)\n                        {\n                            Report.Warn(\"skipping invalid reference to \" + refNum);\n                            value = null;\n                        }\n                        else\n                            value = (T)UseRef(refNum);\n                        return -2L;\n                    default:\n                        count = CodeLong(count);\n                        break;\n                }\n            }\n            value = creator(count);\n            if (m_doRefs) AddRef(value);\n            return count;\n        }\n\n        /// <summary>\n        /// Backward compatible extension for coding collections with 64-bit lengths.\n        /// </summary>\n        public long[] CodeCountArray<T>(ref T value, Func<long[], T> creator) where T : class\n        {\n            long intCount = m_reader.ReadInt32();\n            long[] countArray = null;\n            if (intCount >= 0)\n                countArray = intCount.IntoArray();\n            if (intCount < 0)\n            {\n                switch (intCount)\n                {\n                    case -1:\n                        value = null; return (-1L).IntoArray();\n                    case -2:\n                        int refNum = m_reader.ReadInt32();\n                        if (refNum >= m_refs.Count)\n                        {\n                            Report.Warn(\"skipping invalid reference to \" + refNum);\n                            value = null;\n                        }\n                        else\n                            value = (T)UseRef(refNum);\n                        return (-2L).IntoArray();\n                    case -3:\n                    case -4:\n                        var dim = -intCount - 1;\n                        countArray = new long[dim];\n                        for (int d = 0; d < dim; d++)\n                        {\n                            long ci = m_reader.ReadInt32();\n                            countArray[d] = ci >= 0 ? ci : CodeLong(ci);\n                        }\n                        break;\n                    default:\n                        countArray = CodeLong(intCount).IntoArray();\n                        break;\n                }\n            }\n            value = creator(countArray);\n            if (m_doRefs) AddRef(value);\n            return countArray;\n        }\n\n        private long CodeCountLong<T>(ref T[] array)\n        {\n            return CodeCountLong(ref array, n => new T[n]);\n        }\n\n        private long[] CodeCountLong<T>(ref T[,] array)\n        {\n            return CodeCountArray(ref array, ca => new T[ca[0], ca[1]]);\n        }\n\n        private long[] CodeCountLong<T>(ref T[,,] array)\n        {\n            return CodeCountArray(ref array, ca => new T[ca[0], ca[1], ca[2]]);\n        }\n\n        private long CodeCountLong<T>(ref T[][] array)\n        {\n            return CodeCountLong(ref array, c => new T[c][]);\n        }\n\n        private long CodeCountLong<T>(ref T[][][] array)\n        {\n            return CodeCountLong(ref array, c => new T[c][][]);\n        }\n\n        private int CodeCount<T>(ref List<T> list)\n        {\n            return CodeCount(ref list, n => new List<T>(n));\n        }\n\n        public void CodeTArray<T>(ref T[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) CodeT(ref value[i]);\n        }\n\n        public void CodeList_of_T_<T>(ref List<T> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            while (count-- > 0)\n            {\n                object o = default(T); Code(ref o); value.Add((T)o);\n            }\n        }\n\n        public void CodeHashSet_of_T_<T>(ref HashSet<T> value)\n        {\n            int count = CodeCount(ref value, c => new HashSet<T>());\n            if (count < 1) return;\n            while (count-- > 0)\n            {\n                object o = default(T); Code(ref o); value.Add((T)o);\n            }\n        }\n\n        public void Code(Type t, ref object o)\n        {\n            TypeCoder.Read(this, t, ref o);\n        }\n\n        private static Array CreateArray(Type t, long[] countArray)\n        {\n            t = t.GetElementType();\n            switch (countArray.Length)\n            {\n                case 1: return Array.CreateInstance(t, countArray[0]);\n                case 2: return Array.CreateInstance(t, countArray[0], countArray[1]);\n                case 3: return Array.CreateInstance(t, countArray[0], countArray[1], countArray[2]);\n            }\n            throw new ArgumentException(\"cannot decode array with more than 3 dimensions\");\n        }\n\n        public void Code(Type t, ref Array array)\n        {\n            long[] countArray = CodeCountArray(ref array, ca => CreateArray(t, ca));\n            long c0 = countArray[0];  if (c0 < 1) return;\n            if (countArray.Length == 1)\n            {\n                for (int i = 0; i < c0; i++)\n                {\n                    object o = null; Code(ref o); array.SetValue(o, i);\n                }\n                return;\n            }\n            var c1 = countArray[1]; if (c1 < 1) return;\n            if (countArray.Length == 2)\n            {\n                for (long i = 0; i < c0; i++)\n                for (long j = 0; j < c1; j++)\n                {\n                    object o = null; Code(ref o); array.SetValue(o, i, j);\n                }\n                return;\n            }\n            var c2 = countArray[3]; if (c2 < 1) return;\n            if (countArray.Length == 3)\n            {\n                for (long i = 0; i < c0; i++)\n                for (long j = 0; j < c1; j++)\n                for (long k = 0; k < c2; k++)\n                {\n                    object o = null; Code(ref o); array.SetValue(o, i, j, k);\n                }\n                return;\n            }\n            throw new ArgumentException(\"cannot decode array with more than 3 dimensions\");\n        }\n\n        public void CodeOld(Type t, ref Array array)\n        {\n            int count = CodeCount(ref array,\n                                  n => (Array)Activator.CreateInstance(t, n));\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                object o = null;\n                Code(ref o);\n                array.SetValue(o, i);\n            }\n        }\n\n        public void Code(Type t, ref IList list)\n        {\n            int count = CodeCount(ref list,\n                                  n => (IList)Activator.CreateInstance(t, n));\n            if (count < 1) return;\n            while (count-- > 0)\n            {\n                object o = null;\n                Code(ref o);\n                list.Add(o);\n            }\n        }\n\n        public void Code(Type t, ref IDictionary dict)\n        {\n            int count = CodeCount(ref dict,\n                                  n => (IDictionary)Activator.CreateInstance(t, n));\n            if (count < 1) return;\n\n            Type[] subTypeArray = t.GetGenericArguments();\n\n            while (count-- > 0)\n            {\n                object key = null;\n                TypeCoder.Read(this, subTypeArray[0], ref key);\n                object val = null;\n                TypeCoder.Read(this, subTypeArray[1], ref val);\n                dict[key] = val;\n            }\n        }\n\n        public void Code(Type t, ref ICountableDict dict)\n        {\n            int count = CodeCount(ref dict,\n                                  n => (ICountableDict)Activator.CreateInstance(t, n));\n            if (count < 1) return;\n\n            var keyType = dict.KeyType;\n            var valueType = dict.ValueType;\n\n            while (count-- > 0)\n            {\n                object key = null;\n                TypeCoder.Read(this, keyType, ref key);\n                object val = null;\n                TypeCoder.Read(this, valueType, ref val);\n                dict.AddObject(key, val);\n            }\n        }\n\n        public void Code(Type t, ref ICountableDictSet dictSet)\n        {\n            int count = CodeCount(ref dictSet,\n                                  n => (ICountableDictSet)Activator.CreateInstance(t, n));\n            if (count < 1) return;\n\n            var keyType = dictSet.KeyType;\n\n            while (count-- > 0)\n            {\n                object key = null;\n                TypeCoder.Read(this, keyType, ref key);\n                dictSet.AddObject(key);\n            }\n        }\n\n        public void Code(Type t, ref IArrayVector value)\n        {\n            value = (IArrayVector)FastObjectFactory.ObjectFactory(t)();\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n            long length = 0L; CodeLong(ref length); value.Size = length;\n            long delta = 0L; CodeLong(ref delta); value.Delta = delta;\n        }\n\n        public void Code(Type t, ref IArrayMatrix value)\n        {\n            value = (IArrayMatrix)FastObjectFactory.ObjectFactory(t)();\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n            V2l length = default(V2l); CodeV2l(ref length); value.Size = length;\n            V2l delta = default(V2l); CodeV2l(ref delta); value.Delta = delta;\n        }\n\n        public void Code(Type t, ref IArrayVolume value)\n        {\n            value = (IArrayVolume)FastObjectFactory.ObjectFactory(t)();\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n            V3l length = default(V3l); CodeV3l(ref length); value.Size = length;\n            V3l delta = default(V3l); CodeV3l(ref delta); value.Delta = delta;\n        }\n\n        public void Code(Type t, ref IArrayTensor4 value)\n        {\n            value = (IArrayTensor4)FastObjectFactory.ObjectFactory(t)();\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n            V4l length = default(V4l); CodeV4l(ref length); value.Size = length;\n            V4l delta = default(V4l); CodeV4l(ref delta); value.Delta = delta;\n        }\n\n        public void Code(Type t, ref IArrayTensorN value)\n        {\n            value = (IArrayTensorN)FastObjectFactory.ObjectFactory(t)();\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n            long[] length = null; CodeLongArray(ref length); value.Size = length;\n            long[] delta = null; CodeLongArray(ref delta); value.Delta = delta;\n        }\n\n        public void CodeHashSet(Type t, ref object obj)\n        {\n            throw new NotImplementedException(\"only possible whith a non-generic ISet interface)\");\n        }\n\n        public void CodeEnum(Type type, ref object value)\n        {\n            Type systemType = Enum.GetUnderlyingType(type);\n            var reader = TypeCoder.TypeReaderMap[systemType];\n            object obj = reader(this);\n            value = Enum.ToObject(type, obj);\n        }\n\n        #endregion\n\n        #region Code Primitives\n\n        public void CodeBool(ref bool value)\n        {\n            value = m_reader.ReadBoolean();\n        }\n\n        public void CodeByte(ref byte value)\n        {\n            value = m_reader.ReadByte();\n        }\n\n        public void CodeSByte(ref sbyte value)\n        {\n            value = m_reader.ReadSByte();\n        }\n\n        public void CodeShort(ref short value)\n        {\n            value = m_reader.ReadInt16();\n        }\n\n        public void CodeUShort(ref ushort value)\n        {\n            value = m_reader.ReadUInt16();\n        }\n\n        public void CodeInt(ref int value)\n        {\n            value = m_reader.ReadInt32();\n        }\n\n        public void CodeUInt(ref uint value)\n        {\n            value = m_reader.ReadUInt32();\n        }\n\n        public void CodeLong(ref long value)\n        {\n            value = m_reader.ReadInt64();\n        }\n\n        public void CodeULong(ref ulong value)\n        {\n            value = m_reader.ReadUInt64();\n        }\n\n        public void CodeFloat(ref float value)\n        {\n            value = m_reader.ReadSingle();\n        }\n\n        public void CodeDouble(ref double value)\n        {\n            value = m_reader.ReadDouble();\n        }\n\n        public void CodeChar(ref char value)\n        {\n            value = m_reader.ReadChar();\n        }\n\n        public void CodeString(ref string value)\n        {\n            if (m_coderVersion == 0)\n                value = m_reader.ReadString();\n            else\n            {\n                if (CodeNull(ref value)) return;\n                value = m_reader.ReadString();\n            }\n        }\n\n        public void CodeType(ref Type value)\n        {\n            var typeName = m_reader.ReadString();\n            TypeInfo ti;\n\n            if (TryGetTypeInfo(typeName, out ti))\n                value = ti.Type;\n            else\n                value = Type.GetType(typeName);\n        }\n\n        public void CodeGuid(ref Guid value) { value = m_reader.ReadGuid(); }\n\n        public void CodeSymbol(ref Symbol value) { value = m_reader.ReadSymbol(); }\n\n        public void CodeGuidSymbol(ref Symbol value) { value = m_reader.ReadGuidSymbol(); }\n\n        public void CodePositiveSymbol(ref Symbol value) { value = m_reader.ReadPositiveSymbol(); }\n\n        public void CodeIntSet(ref IntSet set)\n        {\n            int count = CodeCount(ref set, n => new IntSet(n));\n            if (count < 1) return;\n            while (count-- > 0) set.Add(m_reader.ReadInt32());\n        }\n\n        public void CodeSymbolSet(ref SymbolSet set)\n        {\n            int count = CodeCount(ref set, n => new SymbolSet(n));\n            if (count < 1) return;\n            while (count-- > 0) set.Add(m_reader.ReadSymbol());\n        }\n\n        public void CodeFraction(ref Fraction value)\n        {\n            long numerator = m_reader.ReadInt64();\n            long denominator = m_reader.ReadInt64();\n            value = new Fraction(numerator, denominator);\n        }\n\n        #endregion\n\n        #region Code Arrays\n\n        public void CodeStructArray<T>(ref T[] value)\n            where T : struct\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeBoolArray(ref bool[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) value[i] = m_reader.ReadBoolean();\n        }\n\n        public void CodeByteArray(ref byte[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeSByteArray(ref sbyte[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeShortArray(ref short[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeUShortArray(ref ushort[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeIntArray(ref int[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeUIntArray(ref uint[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeLongArray(ref long[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeULongArray(ref ulong[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeFloatArray(ref float[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeDoubleArray(ref double[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        public void CodeCharArray(ref char[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) value[i] = m_reader.ReadChar();\n        }\n\n        public void CodeStringArray(ref string[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) value[i] = m_reader.ReadString();\n        }\n\n        public void CodeTypeArray(ref Type[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n\n            for (long i = 0; i < count; i++)\n            {\n                var typeName = m_reader.ReadString();\n                TypeInfo ti;\n\n                if (TryGetTypeInfo(typeName, out ti))\n                    value[i] = ti.Type;\n                else\n                    value[i] = Type.GetType(typeName);\n            }\n        }\n\n        public void CodeGuidArray(ref Guid[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) CodeGuid(ref value[i]);\n        }\n\n        public void CodeSymbolArray(ref Symbol[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) CodeSymbol(ref value[i]);\n        }\n\n        public void CodeFractionArray(ref Fraction[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        #endregion\n\n        #region Code Lists\n\n        public void CodeStructList<T>(ref List<T> value)\n            where T : struct\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_Bool_(ref List<bool> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            while (count-- > 0) value.Add(m_reader.ReadBoolean());\n        }\n\n        public void CodeList_of_Byte_(ref List<byte> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            while (count-- > 0) value.Add(m_reader.ReadByte());\n        }\n\n        public void CodeList_of_SByte_(ref List<sbyte> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_Short_(ref List<short> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_UShort_(ref List<ushort> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_Int_(ref List<int> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_UInt_(ref List<uint> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_Long_(ref List<long> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_ULong_(ref List<ulong> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_Float_(ref List<float> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_Double_(ref List<double> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        public void CodeList_of_Char_(ref List<char> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            while (count-- > 0) value.Add(m_reader.ReadChar());\n        }\n\n        public void CodeList_of_String_(ref List<string> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            while (count-- > 0) value.Add(m_reader.ReadString());\n            //for (int i = 0; i < count; i++) value[i] = m_reader.ReadString();\n        }\n\n        public void CodeList_of_Type_(ref List<Type> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n\n            for (int i = 0; i < count; i++)\n            {\n                var typeName = m_reader.ReadString();\n                TypeInfo ti;\n\n                if (TryGetTypeInfo(typeName, out ti))\n                    value.Add(ti.Type);\n                else\n                    value.Add(Type.GetType(typeName));\n            }\n        }\n\n        public void CodeList_of_Guid_(ref List<Guid> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            //while (count-- > 0) value.Add(new Guid(m_reader.ReadString()));\n            for (int i = 0; i < count; i++)\n            {\n                var m = new Guid();\n                CodeGuid(ref m);\n                value.Add(m);\n                //value[i] = new Guid(m_reader.ReadString());\n            }\n        }\n\n        public void CodeList_of_Symbol_(ref List<Symbol> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                var m = default(Symbol);\n                CodeSymbol(ref m);\n                value.Add(m);\n            }\n        }\n\n        public void CodeList_of_Fraction_(ref List<Fraction> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        #endregion\n\n        #region IDisposable Members\n\n        public void Dispose()\n        {\n            // dispose reader\n            if (m_disposeStream)\n                m_reader.BaseStream.Dispose();\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/BinaryReadingCoder_auto.cs",
    "content": "using Aardvark.Base;\r\nusing System;\r\nusing System.Collections.Generic;\r\n\r\nnamespace Aardvark.Base.Coder\r\n{\r\n    // AUTO GENERATED CODE - DO NOT CHANGE!\r\n\r\n    public partial class BinaryReadingCoder\r\n    {\r\n        #region Vectors\r\n\r\n        public void CodeV2i(ref V2i value) \r\n        {\r\n            value.X = m_reader.ReadInt32();\r\n            value.Y = m_reader.ReadInt32();\r\n        }\r\n\r\n        public void CodeV2ui(ref V2ui value) \r\n        {\r\n            value.X = m_reader.ReadUInt32();\r\n            value.Y = m_reader.ReadUInt32();\r\n        }\r\n\r\n        public void CodeV2l(ref V2l value) \r\n        {\r\n            value.X = m_reader.ReadInt64();\r\n            value.Y = m_reader.ReadInt64();\r\n        }\r\n\r\n        public void CodeV2f(ref V2f value) \r\n        {\r\n            value.X = m_reader.ReadSingle();\r\n            value.Y = m_reader.ReadSingle();\r\n        }\r\n\r\n        public void CodeV2d(ref V2d value) \r\n        {\r\n            value.X = m_reader.ReadDouble();\r\n            value.Y = m_reader.ReadDouble();\r\n        }\r\n\r\n        public void CodeV3i(ref V3i value) \r\n        {\r\n            value.X = m_reader.ReadInt32();\r\n            value.Y = m_reader.ReadInt32();\r\n            value.Z = m_reader.ReadInt32();\r\n        }\r\n\r\n        public void CodeV3ui(ref V3ui value) \r\n        {\r\n            value.X = m_reader.ReadUInt32();\r\n            value.Y = m_reader.ReadUInt32();\r\n            value.Z = m_reader.ReadUInt32();\r\n        }\r\n\r\n        public void CodeV3l(ref V3l value) \r\n        {\r\n            value.X = m_reader.ReadInt64();\r\n            value.Y = m_reader.ReadInt64();\r\n            value.Z = m_reader.ReadInt64();\r\n        }\r\n\r\n        public void CodeV3f(ref V3f value) \r\n        {\r\n            value.X = m_reader.ReadSingle();\r\n            value.Y = m_reader.ReadSingle();\r\n            value.Z = m_reader.ReadSingle();\r\n        }\r\n\r\n        public void CodeV3d(ref V3d value) \r\n        {\r\n            value.X = m_reader.ReadDouble();\r\n            value.Y = m_reader.ReadDouble();\r\n            value.Z = m_reader.ReadDouble();\r\n        }\r\n\r\n        public void CodeV4i(ref V4i value) \r\n        {\r\n            value.X = m_reader.ReadInt32();\r\n            value.Y = m_reader.ReadInt32();\r\n            value.Z = m_reader.ReadInt32();\r\n            value.W = m_reader.ReadInt32();\r\n        }\r\n\r\n        public void CodeV4ui(ref V4ui value) \r\n        {\r\n            value.X = m_reader.ReadUInt32();\r\n            value.Y = m_reader.ReadUInt32();\r\n            value.Z = m_reader.ReadUInt32();\r\n            value.W = m_reader.ReadUInt32();\r\n        }\r\n\r\n        public void CodeV4l(ref V4l value) \r\n        {\r\n            value.X = m_reader.ReadInt64();\r\n            value.Y = m_reader.ReadInt64();\r\n            value.Z = m_reader.ReadInt64();\r\n            value.W = m_reader.ReadInt64();\r\n        }\r\n\r\n        public void CodeV4f(ref V4f value) \r\n        {\r\n            value.X = m_reader.ReadSingle();\r\n            value.Y = m_reader.ReadSingle();\r\n            value.Z = m_reader.ReadSingle();\r\n            value.W = m_reader.ReadSingle();\r\n        }\r\n\r\n        public void CodeV4d(ref V4d value) \r\n        {\r\n            value.X = m_reader.ReadDouble();\r\n            value.Y = m_reader.ReadDouble();\r\n            value.Z = m_reader.ReadDouble();\r\n            value.W = m_reader.ReadDouble();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Matrices\r\n\r\n        public void CodeM22i(ref M22i value) { value = m_reader.ReadM22i(); }\r\n        public void CodeM22l(ref M22l value) { value = m_reader.ReadM22l(); }\r\n        public void CodeM22f(ref M22f value) { value = m_reader.ReadM22f(); }\r\n        public void CodeM22d(ref M22d value) { value = m_reader.ReadM22d(); }\r\n        public void CodeM23i(ref M23i value) { value = m_reader.ReadM23i(); }\r\n        public void CodeM23l(ref M23l value) { value = m_reader.ReadM23l(); }\r\n        public void CodeM23f(ref M23f value) { value = m_reader.ReadM23f(); }\r\n        public void CodeM23d(ref M23d value) { value = m_reader.ReadM23d(); }\r\n        public void CodeM33i(ref M33i value) { value = m_reader.ReadM33i(); }\r\n        public void CodeM33l(ref M33l value) { value = m_reader.ReadM33l(); }\r\n        public void CodeM33f(ref M33f value) { value = m_reader.ReadM33f(); }\r\n        public void CodeM33d(ref M33d value) { value = m_reader.ReadM33d(); }\r\n        public void CodeM34i(ref M34i value) { value = m_reader.ReadM34i(); }\r\n        public void CodeM34l(ref M34l value) { value = m_reader.ReadM34l(); }\r\n        public void CodeM34f(ref M34f value) { value = m_reader.ReadM34f(); }\r\n        public void CodeM34d(ref M34d value) { value = m_reader.ReadM34d(); }\r\n        public void CodeM44i(ref M44i value) { value = m_reader.ReadM44i(); }\r\n        public void CodeM44l(ref M44l value) { value = m_reader.ReadM44l(); }\r\n        public void CodeM44f(ref M44f value) { value = m_reader.ReadM44f(); }\r\n        public void CodeM44d(ref M44d value) { value = m_reader.ReadM44d(); }\r\n\r\n        #endregion\r\n\r\n        #region Ranges and Boxes\r\n\r\n        public void CodeRange1b(ref Range1b value)\r\n        {\r\n            value.Min = m_reader.ReadByte();\r\n            value.Max = m_reader.ReadByte();\r\n        }\r\n\r\n        public void CodeRange1sb(ref Range1sb value)\r\n        {\r\n            value.Min = m_reader.ReadSByte();\r\n            value.Max = m_reader.ReadSByte();\r\n        }\r\n\r\n        public void CodeRange1s(ref Range1s value)\r\n        {\r\n            value.Min = m_reader.ReadInt16();\r\n            value.Max = m_reader.ReadInt16();\r\n        }\r\n\r\n        public void CodeRange1us(ref Range1us value)\r\n        {\r\n            value.Min = m_reader.ReadUInt16();\r\n            value.Max = m_reader.ReadUInt16();\r\n        }\r\n\r\n        public void CodeRange1i(ref Range1i value)\r\n        {\r\n            value.Min = m_reader.ReadInt32();\r\n            value.Max = m_reader.ReadInt32();\r\n        }\r\n\r\n        public void CodeRange1ui(ref Range1ui value)\r\n        {\r\n            value.Min = m_reader.ReadUInt32();\r\n            value.Max = m_reader.ReadUInt32();\r\n        }\r\n\r\n        public void CodeRange1l(ref Range1l value)\r\n        {\r\n            value.Min = m_reader.ReadInt64();\r\n            value.Max = m_reader.ReadInt64();\r\n        }\r\n\r\n        public void CodeRange1ul(ref Range1ul value)\r\n        {\r\n            value.Min = m_reader.ReadUInt64();\r\n            value.Max = m_reader.ReadUInt64();\r\n        }\r\n\r\n        public void CodeRange1f(ref Range1f value)\r\n        {\r\n            value.Min = m_reader.ReadSingle();\r\n            value.Max = m_reader.ReadSingle();\r\n        }\r\n\r\n        public void CodeRange1d(ref Range1d value)\r\n        {\r\n            value.Min = m_reader.ReadDouble();\r\n            value.Max = m_reader.ReadDouble();\r\n        }\r\n\r\n        public void CodeBox2i(ref Box2i value)\r\n        {\r\n            value.Min = m_reader.ReadV2i();\r\n            value.Max = m_reader.ReadV2i();\r\n        }\r\n\r\n        public void CodeBox2l(ref Box2l value)\r\n        {\r\n            value.Min = m_reader.ReadV2l();\r\n            value.Max = m_reader.ReadV2l();\r\n        }\r\n\r\n        public void CodeBox2f(ref Box2f value)\r\n        {\r\n            value.Min = m_reader.ReadV2f();\r\n            value.Max = m_reader.ReadV2f();\r\n        }\r\n\r\n        public void CodeBox2d(ref Box2d value)\r\n        {\r\n            value.Min = m_reader.ReadV2d();\r\n            value.Max = m_reader.ReadV2d();\r\n        }\r\n\r\n        public void CodeBox3i(ref Box3i value)\r\n        {\r\n            value.Min = m_reader.ReadV3i();\r\n            value.Max = m_reader.ReadV3i();\r\n        }\r\n\r\n        public void CodeBox3l(ref Box3l value)\r\n        {\r\n            value.Min = m_reader.ReadV3l();\r\n            value.Max = m_reader.ReadV3l();\r\n        }\r\n\r\n        public void CodeBox3f(ref Box3f value)\r\n        {\r\n            value.Min = m_reader.ReadV3f();\r\n            value.Max = m_reader.ReadV3f();\r\n        }\r\n\r\n        public void CodeBox3d(ref Box3d value)\r\n        {\r\n            value.Min = m_reader.ReadV3d();\r\n            value.Max = m_reader.ReadV3d();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Geometry Types\r\n\r\n        public void CodeCircle2f(ref Circle2f v)\r\n        {\r\n            CodeV2f(ref v.Center); CodeFloat(ref v.Radius);\r\n        }\r\n\r\n        public void CodeLine2f(ref Line2f v)\r\n        {\r\n            CodeV2f(ref v.P0); CodeV2f(ref v.P1);\r\n        }\r\n\r\n        public void CodeLine3f(ref Line3f v)\r\n        {\r\n            CodeV3f(ref v.P0); CodeV3f(ref v.P1);\r\n        }\r\n\r\n        public void CodePlane2f(ref Plane2f v)\r\n        {\r\n            CodeV2f(ref v.Normal); CodeFloat(ref v.Distance);\r\n        }\r\n\r\n        public void CodePlane3f(ref Plane3f v)\r\n        {\r\n            CodeV3f(ref v.Normal); CodeFloat(ref v.Distance);\r\n        }\r\n\r\n        public void CodePlaneWithPoint3f(ref PlaneWithPoint3f v)\r\n        {\r\n            CodeV3f(ref v.Normal); CodeV3f(ref v.Point);\r\n        }\r\n\r\n        public void CodeQuad2f(ref Quad2f v)\r\n        {\r\n            CodeV2f(ref v.P0); CodeV2f(ref v.P1); CodeV2f(ref v.P2); CodeV2f(ref v.P3);\r\n        }\r\n\r\n        public void CodeQuad3f(ref Quad3f v)\r\n        {\r\n            CodeV3f(ref v.P0); CodeV3f(ref v.P1); CodeV3f(ref v.P2); CodeV3f(ref v.P3);\r\n        }\r\n\r\n        public void CodeRay2f(ref Ray2f v)\r\n        {\r\n            CodeV2f(ref v.Origin); CodeV2f(ref v.Direction);\r\n        }\r\n\r\n        public void CodeRay3f(ref Ray3f v)\r\n        {\r\n            CodeV3f(ref v.Origin); CodeV3f(ref v.Direction);\r\n        }\r\n\r\n        public void CodeSphere3f(ref Sphere3f v)\r\n        {\r\n            CodeV3f(ref v.Center); CodeFloat(ref v.Radius);\r\n        }\r\n\r\n        public void CodeTriangle2f(ref Triangle2f v)\r\n        {\r\n            CodeV2f(ref v.P0); CodeV2f(ref v.P1); CodeV2f(ref v.P2);\r\n        }\r\n\r\n        public void CodeTriangle3f(ref Triangle3f v)\r\n        {\r\n            CodeV3f(ref v.P0); CodeV3f(ref v.P1); CodeV3f(ref v.P2);\r\n        }\r\n\r\n        public void CodeCircle2d(ref Circle2d v)\r\n        {\r\n            CodeV2d(ref v.Center); CodeDouble(ref v.Radius);\r\n        }\r\n\r\n        public void CodeLine2d(ref Line2d v)\r\n        {\r\n            CodeV2d(ref v.P0); CodeV2d(ref v.P1);\r\n        }\r\n\r\n        public void CodeLine3d(ref Line3d v)\r\n        {\r\n            CodeV3d(ref v.P0); CodeV3d(ref v.P1);\r\n        }\r\n\r\n        public void CodePlane2d(ref Plane2d v)\r\n        {\r\n            CodeV2d(ref v.Normal); CodeDouble(ref v.Distance);\r\n        }\r\n\r\n        public void CodePlane3d(ref Plane3d v)\r\n        {\r\n            CodeV3d(ref v.Normal); CodeDouble(ref v.Distance);\r\n        }\r\n\r\n        public void CodePlaneWithPoint3d(ref PlaneWithPoint3d v)\r\n        {\r\n            CodeV3d(ref v.Normal); CodeV3d(ref v.Point);\r\n        }\r\n\r\n        public void CodeQuad2d(ref Quad2d v)\r\n        {\r\n            CodeV2d(ref v.P0); CodeV2d(ref v.P1); CodeV2d(ref v.P2); CodeV2d(ref v.P3);\r\n        }\r\n\r\n        public void CodeQuad3d(ref Quad3d v)\r\n        {\r\n            CodeV3d(ref v.P0); CodeV3d(ref v.P1); CodeV3d(ref v.P2); CodeV3d(ref v.P3);\r\n        }\r\n\r\n        public void CodeRay2d(ref Ray2d v)\r\n        {\r\n            CodeV2d(ref v.Origin); CodeV2d(ref v.Direction);\r\n        }\r\n\r\n        public void CodeRay3d(ref Ray3d v)\r\n        {\r\n            CodeV3d(ref v.Origin); CodeV3d(ref v.Direction);\r\n        }\r\n\r\n        public void CodeSphere3d(ref Sphere3d v)\r\n        {\r\n            CodeV3d(ref v.Center); CodeDouble(ref v.Radius);\r\n        }\r\n\r\n        public void CodeTriangle2d(ref Triangle2d v)\r\n        {\r\n            CodeV2d(ref v.P0); CodeV2d(ref v.P1); CodeV2d(ref v.P2);\r\n        }\r\n\r\n        public void CodeTriangle3d(ref Triangle3d v)\r\n        {\r\n            CodeV3d(ref v.P0); CodeV3d(ref v.P1); CodeV3d(ref v.P2);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Colors\r\n\r\n        public void CodeC3b(ref C3b value)\r\n        {\r\n            value.R = m_reader.ReadByte();\r\n            value.G = m_reader.ReadByte();\r\n            value.B = m_reader.ReadByte();\r\n        }\r\n\r\n        public void CodeC3us(ref C3us value)\r\n        {\r\n            value.R = m_reader.ReadUInt16();\r\n            value.G = m_reader.ReadUInt16();\r\n            value.B = m_reader.ReadUInt16();\r\n        }\r\n\r\n        public void CodeC3ui(ref C3ui value)\r\n        {\r\n            value.R = m_reader.ReadUInt32();\r\n            value.G = m_reader.ReadUInt32();\r\n            value.B = m_reader.ReadUInt32();\r\n        }\r\n\r\n        public void CodeC3f(ref C3f value)\r\n        {\r\n            value.R = m_reader.ReadSingle();\r\n            value.G = m_reader.ReadSingle();\r\n            value.B = m_reader.ReadSingle();\r\n        }\r\n\r\n        public void CodeC3d(ref C3d value)\r\n        {\r\n            value.R = m_reader.ReadDouble();\r\n            value.G = m_reader.ReadDouble();\r\n            value.B = m_reader.ReadDouble();\r\n        }\r\n\r\n        public void CodeC4b(ref C4b value)\r\n        {\r\n            value.R = m_reader.ReadByte();\r\n            value.G = m_reader.ReadByte();\r\n            value.B = m_reader.ReadByte();\r\n            value.A = m_reader.ReadByte();\r\n        }\r\n\r\n        public void CodeC4us(ref C4us value)\r\n        {\r\n            value.R = m_reader.ReadUInt16();\r\n            value.G = m_reader.ReadUInt16();\r\n            value.B = m_reader.ReadUInt16();\r\n            value.A = m_reader.ReadUInt16();\r\n        }\r\n\r\n        public void CodeC4ui(ref C4ui value)\r\n        {\r\n            value.R = m_reader.ReadUInt32();\r\n            value.G = m_reader.ReadUInt32();\r\n            value.B = m_reader.ReadUInt32();\r\n            value.A = m_reader.ReadUInt32();\r\n        }\r\n\r\n        public void CodeC4f(ref C4f value)\r\n        {\r\n            value.R = m_reader.ReadSingle();\r\n            value.G = m_reader.ReadSingle();\r\n            value.B = m_reader.ReadSingle();\r\n            value.A = m_reader.ReadSingle();\r\n        }\r\n\r\n        public void CodeC4d(ref C4d value)\r\n        {\r\n            value.R = m_reader.ReadDouble();\r\n            value.G = m_reader.ReadDouble();\r\n            value.B = m_reader.ReadDouble();\r\n            value.A = m_reader.ReadDouble();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Trafos\r\n\r\n        public void CodeEuclidean3f(ref Euclidean3f value) { value = m_reader.ReadEuclidean3f(); }\r\n        public void CodeEuclidean3d(ref Euclidean3d value) { value = m_reader.ReadEuclidean3d(); }\r\n        public void CodeRot2f(ref Rot2f value) { value = m_reader.ReadRot2f(); }\r\n        public void CodeRot2d(ref Rot2d value) { value = m_reader.ReadRot2d(); }\r\n        public void CodeRot3f(ref Rot3f value) { value = m_reader.ReadRot3f(); }\r\n        public void CodeRot3d(ref Rot3d value) { value = m_reader.ReadRot3d(); }\r\n        public void CodeScale3f(ref Scale3f value) { value = m_reader.ReadScale3f(); }\r\n        public void CodeScale3d(ref Scale3d value) { value = m_reader.ReadScale3d(); }\r\n        public void CodeShift3f(ref Shift3f value) { value = m_reader.ReadShift3f(); }\r\n        public void CodeShift3d(ref Shift3d value) { value = m_reader.ReadShift3d(); }\r\n        public void CodeTrafo2f(ref Trafo2f value) { value = m_reader.ReadTrafo2f(); }\r\n        public void CodeTrafo2d(ref Trafo2d value) { value = m_reader.ReadTrafo2d(); }\r\n        public void CodeTrafo3f(ref Trafo3f value) { value = m_reader.ReadTrafo3f(); }\r\n        public void CodeTrafo3d(ref Trafo3d value) { value = m_reader.ReadTrafo3d(); }\r\n\r\n        #endregion\r\n\r\n        #region Tensors\r\n\r\n        public void CodeVector_of_Byte_(ref Vector<byte> value)\r\n        {\r\n            byte[] data = null; CodeByteArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<byte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_SByte_(ref Vector<sbyte> value)\r\n        {\r\n            sbyte[] data = null; CodeSByteArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<sbyte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Short_(ref Vector<short> value)\r\n        {\r\n            short[] data = null; CodeShortArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<short>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_UShort_(ref Vector<ushort> value)\r\n        {\r\n            ushort[] data = null; CodeUShortArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<ushort>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Int_(ref Vector<int> value)\r\n        {\r\n            int[] data = null; CodeIntArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<int>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_UInt_(ref Vector<uint> value)\r\n        {\r\n            uint[] data = null; CodeUIntArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<uint>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Long_(ref Vector<long> value)\r\n        {\r\n            long[] data = null; CodeLongArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<long>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_ULong_(ref Vector<ulong> value)\r\n        {\r\n            ulong[] data = null; CodeULongArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<ulong>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Float_(ref Vector<float> value)\r\n        {\r\n            float[] data = null; CodeFloatArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<float>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Double_(ref Vector<double> value)\r\n        {\r\n            double[] data = null; CodeDoubleArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<double>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_(ref Vector<Fraction> value)\r\n        {\r\n            Fraction[] data = null; CodeFractionArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Fraction>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2i_(ref Vector<V2i> value)\r\n        {\r\n            V2i[] data = null; CodeV2iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2l_(ref Vector<V2l> value)\r\n        {\r\n            V2l[] data = null; CodeV2lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2f_(ref Vector<V2f> value)\r\n        {\r\n            V2f[] data = null; CodeV2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2d_(ref Vector<V2d> value)\r\n        {\r\n            V2d[] data = null; CodeV2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3i_(ref Vector<V3i> value)\r\n        {\r\n            V3i[] data = null; CodeV3iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3l_(ref Vector<V3l> value)\r\n        {\r\n            V3l[] data = null; CodeV3lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3f_(ref Vector<V3f> value)\r\n        {\r\n            V3f[] data = null; CodeV3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3d_(ref Vector<V3d> value)\r\n        {\r\n            V3d[] data = null; CodeV3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4i_(ref Vector<V4i> value)\r\n        {\r\n            V4i[] data = null; CodeV4iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V4i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4l_(ref Vector<V4l> value)\r\n        {\r\n            V4l[] data = null; CodeV4lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V4l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4f_(ref Vector<V4f> value)\r\n        {\r\n            V4f[] data = null; CodeV4fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4d_(ref Vector<V4d> value)\r\n        {\r\n            V4d[] data = null; CodeV4dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<V4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22i_(ref Vector<M22i> value)\r\n        {\r\n            M22i[] data = null; CodeM22iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M22i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22l_(ref Vector<M22l> value)\r\n        {\r\n            M22l[] data = null; CodeM22lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M22l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22f_(ref Vector<M22f> value)\r\n        {\r\n            M22f[] data = null; CodeM22fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M22f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22d_(ref Vector<M22d> value)\r\n        {\r\n            M22d[] data = null; CodeM22dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M22d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23i_(ref Vector<M23i> value)\r\n        {\r\n            M23i[] data = null; CodeM23iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M23i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23l_(ref Vector<M23l> value)\r\n        {\r\n            M23l[] data = null; CodeM23lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M23l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23f_(ref Vector<M23f> value)\r\n        {\r\n            M23f[] data = null; CodeM23fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M23f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23d_(ref Vector<M23d> value)\r\n        {\r\n            M23d[] data = null; CodeM23dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M23d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33i_(ref Vector<M33i> value)\r\n        {\r\n            M33i[] data = null; CodeM33iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M33i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33l_(ref Vector<M33l> value)\r\n        {\r\n            M33l[] data = null; CodeM33lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M33l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33f_(ref Vector<M33f> value)\r\n        {\r\n            M33f[] data = null; CodeM33fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M33f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33d_(ref Vector<M33d> value)\r\n        {\r\n            M33d[] data = null; CodeM33dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M33d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34i_(ref Vector<M34i> value)\r\n        {\r\n            M34i[] data = null; CodeM34iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M34i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34l_(ref Vector<M34l> value)\r\n        {\r\n            M34l[] data = null; CodeM34lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M34l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34f_(ref Vector<M34f> value)\r\n        {\r\n            M34f[] data = null; CodeM34fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M34f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34d_(ref Vector<M34d> value)\r\n        {\r\n            M34d[] data = null; CodeM34dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M34d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44i_(ref Vector<M44i> value)\r\n        {\r\n            M44i[] data = null; CodeM44iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M44i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44l_(ref Vector<M44l> value)\r\n        {\r\n            M44l[] data = null; CodeM44lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M44l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44f_(ref Vector<M44f> value)\r\n        {\r\n            M44f[] data = null; CodeM44fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M44f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44d_(ref Vector<M44d> value)\r\n        {\r\n            M44d[] data = null; CodeM44dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<M44d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3b_(ref Vector<C3b> value)\r\n        {\r\n            C3b[] data = null; CodeC3bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C3b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3us_(ref Vector<C3us> value)\r\n        {\r\n            C3us[] data = null; CodeC3usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C3us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_(ref Vector<C3ui> value)\r\n        {\r\n            C3ui[] data = null; CodeC3uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C3ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3f_(ref Vector<C3f> value)\r\n        {\r\n            C3f[] data = null; CodeC3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3d_(ref Vector<C3d> value)\r\n        {\r\n            C3d[] data = null; CodeC3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4b_(ref Vector<C4b> value)\r\n        {\r\n            C4b[] data = null; CodeC4bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C4b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4us_(ref Vector<C4us> value)\r\n        {\r\n            C4us[] data = null; CodeC4usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C4us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_(ref Vector<C4ui> value)\r\n        {\r\n            C4ui[] data = null; CodeC4uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C4ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4f_(ref Vector<C4f> value)\r\n        {\r\n            C4f[] data = null; CodeC4fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4d_(ref Vector<C4d> value)\r\n        {\r\n            C4d[] data = null; CodeC4dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<C4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_(ref Vector<Range1b> value)\r\n        {\r\n            Range1b[] data = null; CodeRange1bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_(ref Vector<Range1sb> value)\r\n        {\r\n            Range1sb[] data = null; CodeRange1sbArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1sb>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_(ref Vector<Range1s> value)\r\n        {\r\n            Range1s[] data = null; CodeRange1sArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1s>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_(ref Vector<Range1us> value)\r\n        {\r\n            Range1us[] data = null; CodeRange1usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_(ref Vector<Range1i> value)\r\n        {\r\n            Range1i[] data = null; CodeRange1iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_(ref Vector<Range1ui> value)\r\n        {\r\n            Range1ui[] data = null; CodeRange1uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_(ref Vector<Range1l> value)\r\n        {\r\n            Range1l[] data = null; CodeRange1lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_(ref Vector<Range1ul> value)\r\n        {\r\n            Range1ul[] data = null; CodeRange1ulArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1ul>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_(ref Vector<Range1f> value)\r\n        {\r\n            Range1f[] data = null; CodeRange1fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_(ref Vector<Range1d> value)\r\n        {\r\n            Range1d[] data = null; CodeRange1dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Range1d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_(ref Vector<Box2i> value)\r\n        {\r\n            Box2i[] data = null; CodeBox2iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Box2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_(ref Vector<Box2l> value)\r\n        {\r\n            Box2l[] data = null; CodeBox2lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Box2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_(ref Vector<Box2f> value)\r\n        {\r\n            Box2f[] data = null; CodeBox2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Box2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_(ref Vector<Box2d> value)\r\n        {\r\n            Box2d[] data = null; CodeBox2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Box2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_(ref Vector<Box3i> value)\r\n        {\r\n            Box3i[] data = null; CodeBox3iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Box3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_(ref Vector<Box3l> value)\r\n        {\r\n            Box3l[] data = null; CodeBox3lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Box3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_(ref Vector<Box3f> value)\r\n        {\r\n            Box3f[] data = null; CodeBox3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Box3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_(ref Vector<Box3d> value)\r\n        {\r\n            Box3d[] data = null; CodeBox3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Box3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_(ref Vector<Euclidean3f> value)\r\n        {\r\n            Euclidean3f[] data = null; CodeEuclidean3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Euclidean3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_(ref Vector<Euclidean3d> value)\r\n        {\r\n            Euclidean3d[] data = null; CodeEuclidean3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Euclidean3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_(ref Vector<Rot2f> value)\r\n        {\r\n            Rot2f[] data = null; CodeRot2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Rot2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_(ref Vector<Rot2d> value)\r\n        {\r\n            Rot2d[] data = null; CodeRot2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Rot2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_(ref Vector<Rot3f> value)\r\n        {\r\n            Rot3f[] data = null; CodeRot3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Rot3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_(ref Vector<Rot3d> value)\r\n        {\r\n            Rot3d[] data = null; CodeRot3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Rot3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_(ref Vector<Scale3f> value)\r\n        {\r\n            Scale3f[] data = null; CodeScale3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Scale3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_(ref Vector<Scale3d> value)\r\n        {\r\n            Scale3d[] data = null; CodeScale3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Scale3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_(ref Vector<Shift3f> value)\r\n        {\r\n            Shift3f[] data = null; CodeShift3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Shift3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_(ref Vector<Shift3d> value)\r\n        {\r\n            Shift3d[] data = null; CodeShift3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Shift3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_(ref Vector<Trafo2f> value)\r\n        {\r\n            Trafo2f[] data = null; CodeTrafo2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Trafo2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_(ref Vector<Trafo2d> value)\r\n        {\r\n            Trafo2d[] data = null; CodeTrafo2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Trafo2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_(ref Vector<Trafo3f> value)\r\n        {\r\n            Trafo3f[] data = null; CodeTrafo3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Trafo3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_(ref Vector<Trafo3d> value)\r\n        {\r\n            Trafo3d[] data = null; CodeTrafo3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Trafo3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Bool_(ref Vector<bool> value)\r\n        {\r\n            bool[] data = null; CodeBoolArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<bool>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Char_(ref Vector<char> value)\r\n        {\r\n            char[] data = null; CodeCharArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<char>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_String_(ref Vector<string> value)\r\n        {\r\n            string[] data = null; CodeStringArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<string>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Type_(ref Vector<Type> value)\r\n        {\r\n            Type[] data = null; CodeTypeArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Type>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Guid_(ref Vector<Guid> value)\r\n        {\r\n            Guid[] data = null; CodeGuidArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Guid>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_(ref Vector<Symbol> value)\r\n        {\r\n            Symbol[] data = null; CodeSymbolArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Symbol>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_(ref Vector<Circle2d> value)\r\n        {\r\n            Circle2d[] data = null; CodeCircle2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Circle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_(ref Vector<Line2d> value)\r\n        {\r\n            Line2d[] data = null; CodeLine2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Line2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_(ref Vector<Line3d> value)\r\n        {\r\n            Line3d[] data = null; CodeLine3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Line3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_(ref Vector<Plane2d> value)\r\n        {\r\n            Plane2d[] data = null; CodePlane2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Plane2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_(ref Vector<Plane3d> value)\r\n        {\r\n            Plane3d[] data = null; CodePlane3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Plane3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_(ref Vector<PlaneWithPoint3d> value)\r\n        {\r\n            PlaneWithPoint3d[] data = null; CodePlaneWithPoint3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<PlaneWithPoint3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_(ref Vector<Quad2d> value)\r\n        {\r\n            Quad2d[] data = null; CodeQuad2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Quad2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_(ref Vector<Quad3d> value)\r\n        {\r\n            Quad3d[] data = null; CodeQuad3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Quad3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_(ref Vector<Ray2d> value)\r\n        {\r\n            Ray2d[] data = null; CodeRay2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Ray2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_(ref Vector<Ray3d> value)\r\n        {\r\n            Ray3d[] data = null; CodeRay3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Ray3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_(ref Vector<Sphere3d> value)\r\n        {\r\n            Sphere3d[] data = null; CodeSphere3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Sphere3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_(ref Vector<Triangle2d> value)\r\n        {\r\n            Triangle2d[] data = null; CodeTriangle2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Triangle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_(ref Vector<Triangle3d> value)\r\n        {\r\n            Triangle3d[] data = null; CodeTriangle3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Triangle3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_(ref Vector<Circle2f> value)\r\n        {\r\n            Circle2f[] data = null; CodeCircle2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Circle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_(ref Vector<Line2f> value)\r\n        {\r\n            Line2f[] data = null; CodeLine2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Line2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_(ref Vector<Line3f> value)\r\n        {\r\n            Line3f[] data = null; CodeLine3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Line3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_(ref Vector<Plane2f> value)\r\n        {\r\n            Plane2f[] data = null; CodePlane2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Plane2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_(ref Vector<Plane3f> value)\r\n        {\r\n            Plane3f[] data = null; CodePlane3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Plane3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_(ref Vector<PlaneWithPoint3f> value)\r\n        {\r\n            PlaneWithPoint3f[] data = null; CodePlaneWithPoint3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<PlaneWithPoint3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_(ref Vector<Quad2f> value)\r\n        {\r\n            Quad2f[] data = null; CodeQuad2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Quad2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_(ref Vector<Quad3f> value)\r\n        {\r\n            Quad3f[] data = null; CodeQuad3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Quad3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_(ref Vector<Ray2f> value)\r\n        {\r\n            Ray2f[] data = null; CodeRay2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Ray2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_(ref Vector<Ray3f> value)\r\n        {\r\n            Ray3f[] data = null; CodeRay3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Ray3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_(ref Vector<Sphere3f> value)\r\n        {\r\n            Sphere3f[] data = null; CodeSphere3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Sphere3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_(ref Vector<Triangle2f> value)\r\n        {\r\n            Triangle2f[] data = null; CodeTriangle2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Triangle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_(ref Vector<Triangle3f> value)\r\n        {\r\n            Triangle3f[] data = null; CodeTriangle3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long size = default(long); CodeLong(ref size);\r\n            long delta = default(long); CodeLong(ref delta);\r\n            value = new Vector<Triangle3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_(ref Matrix<byte> value)\r\n        {\r\n            byte[] data = null; CodeByteArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<byte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_(ref Matrix<sbyte> value)\r\n        {\r\n            sbyte[] data = null; CodeSByteArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<sbyte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_(ref Matrix<short> value)\r\n        {\r\n            short[] data = null; CodeShortArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<short>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_(ref Matrix<ushort> value)\r\n        {\r\n            ushort[] data = null; CodeUShortArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<ushort>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_(ref Matrix<int> value)\r\n        {\r\n            int[] data = null; CodeIntArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<int>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_(ref Matrix<uint> value)\r\n        {\r\n            uint[] data = null; CodeUIntArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<uint>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_(ref Matrix<long> value)\r\n        {\r\n            long[] data = null; CodeLongArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<long>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_(ref Matrix<ulong> value)\r\n        {\r\n            ulong[] data = null; CodeULongArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<ulong>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_(ref Matrix<float> value)\r\n        {\r\n            float[] data = null; CodeFloatArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<float>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_(ref Matrix<double> value)\r\n        {\r\n            double[] data = null; CodeDoubleArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<double>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_(ref Matrix<Fraction> value)\r\n        {\r\n            Fraction[] data = null; CodeFractionArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Fraction>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_(ref Matrix<V2i> value)\r\n        {\r\n            V2i[] data = null; CodeV2iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_(ref Matrix<V2l> value)\r\n        {\r\n            V2l[] data = null; CodeV2lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_(ref Matrix<V2f> value)\r\n        {\r\n            V2f[] data = null; CodeV2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_(ref Matrix<V2d> value)\r\n        {\r\n            V2d[] data = null; CodeV2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_(ref Matrix<V3i> value)\r\n        {\r\n            V3i[] data = null; CodeV3iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_(ref Matrix<V3l> value)\r\n        {\r\n            V3l[] data = null; CodeV3lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_(ref Matrix<V3f> value)\r\n        {\r\n            V3f[] data = null; CodeV3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_(ref Matrix<V3d> value)\r\n        {\r\n            V3d[] data = null; CodeV3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_(ref Matrix<V4i> value)\r\n        {\r\n            V4i[] data = null; CodeV4iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V4i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_(ref Matrix<V4l> value)\r\n        {\r\n            V4l[] data = null; CodeV4lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V4l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_(ref Matrix<V4f> value)\r\n        {\r\n            V4f[] data = null; CodeV4fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_(ref Matrix<V4d> value)\r\n        {\r\n            V4d[] data = null; CodeV4dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<V4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_(ref Matrix<M22i> value)\r\n        {\r\n            M22i[] data = null; CodeM22iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M22i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_(ref Matrix<M22l> value)\r\n        {\r\n            M22l[] data = null; CodeM22lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M22l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_(ref Matrix<M22f> value)\r\n        {\r\n            M22f[] data = null; CodeM22fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M22f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_(ref Matrix<M22d> value)\r\n        {\r\n            M22d[] data = null; CodeM22dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M22d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_(ref Matrix<M23i> value)\r\n        {\r\n            M23i[] data = null; CodeM23iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M23i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_(ref Matrix<M23l> value)\r\n        {\r\n            M23l[] data = null; CodeM23lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M23l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_(ref Matrix<M23f> value)\r\n        {\r\n            M23f[] data = null; CodeM23fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M23f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_(ref Matrix<M23d> value)\r\n        {\r\n            M23d[] data = null; CodeM23dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M23d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_(ref Matrix<M33i> value)\r\n        {\r\n            M33i[] data = null; CodeM33iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M33i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_(ref Matrix<M33l> value)\r\n        {\r\n            M33l[] data = null; CodeM33lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M33l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_(ref Matrix<M33f> value)\r\n        {\r\n            M33f[] data = null; CodeM33fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M33f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_(ref Matrix<M33d> value)\r\n        {\r\n            M33d[] data = null; CodeM33dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M33d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_(ref Matrix<M34i> value)\r\n        {\r\n            M34i[] data = null; CodeM34iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M34i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_(ref Matrix<M34l> value)\r\n        {\r\n            M34l[] data = null; CodeM34lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M34l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_(ref Matrix<M34f> value)\r\n        {\r\n            M34f[] data = null; CodeM34fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M34f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_(ref Matrix<M34d> value)\r\n        {\r\n            M34d[] data = null; CodeM34dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M34d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_(ref Matrix<M44i> value)\r\n        {\r\n            M44i[] data = null; CodeM44iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M44i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_(ref Matrix<M44l> value)\r\n        {\r\n            M44l[] data = null; CodeM44lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M44l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_(ref Matrix<M44f> value)\r\n        {\r\n            M44f[] data = null; CodeM44fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M44f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_(ref Matrix<M44d> value)\r\n        {\r\n            M44d[] data = null; CodeM44dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<M44d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_(ref Matrix<C3b> value)\r\n        {\r\n            C3b[] data = null; CodeC3bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C3b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_(ref Matrix<C3us> value)\r\n        {\r\n            C3us[] data = null; CodeC3usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C3us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_(ref Matrix<C3ui> value)\r\n        {\r\n            C3ui[] data = null; CodeC3uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C3ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_(ref Matrix<C3f> value)\r\n        {\r\n            C3f[] data = null; CodeC3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_(ref Matrix<C3d> value)\r\n        {\r\n            C3d[] data = null; CodeC3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_(ref Matrix<C4b> value)\r\n        {\r\n            C4b[] data = null; CodeC4bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C4b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_(ref Matrix<C4us> value)\r\n        {\r\n            C4us[] data = null; CodeC4usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C4us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_(ref Matrix<C4ui> value)\r\n        {\r\n            C4ui[] data = null; CodeC4uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C4ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_(ref Matrix<C4f> value)\r\n        {\r\n            C4f[] data = null; CodeC4fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_(ref Matrix<C4d> value)\r\n        {\r\n            C4d[] data = null; CodeC4dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<C4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_(ref Matrix<Range1b> value)\r\n        {\r\n            Range1b[] data = null; CodeRange1bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_(ref Matrix<Range1sb> value)\r\n        {\r\n            Range1sb[] data = null; CodeRange1sbArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1sb>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_(ref Matrix<Range1s> value)\r\n        {\r\n            Range1s[] data = null; CodeRange1sArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1s>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_(ref Matrix<Range1us> value)\r\n        {\r\n            Range1us[] data = null; CodeRange1usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_(ref Matrix<Range1i> value)\r\n        {\r\n            Range1i[] data = null; CodeRange1iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_(ref Matrix<Range1ui> value)\r\n        {\r\n            Range1ui[] data = null; CodeRange1uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_(ref Matrix<Range1l> value)\r\n        {\r\n            Range1l[] data = null; CodeRange1lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_(ref Matrix<Range1ul> value)\r\n        {\r\n            Range1ul[] data = null; CodeRange1ulArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1ul>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_(ref Matrix<Range1f> value)\r\n        {\r\n            Range1f[] data = null; CodeRange1fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_(ref Matrix<Range1d> value)\r\n        {\r\n            Range1d[] data = null; CodeRange1dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Range1d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_(ref Matrix<Box2i> value)\r\n        {\r\n            Box2i[] data = null; CodeBox2iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Box2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_(ref Matrix<Box2l> value)\r\n        {\r\n            Box2l[] data = null; CodeBox2lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Box2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_(ref Matrix<Box2f> value)\r\n        {\r\n            Box2f[] data = null; CodeBox2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Box2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_(ref Matrix<Box2d> value)\r\n        {\r\n            Box2d[] data = null; CodeBox2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Box2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_(ref Matrix<Box3i> value)\r\n        {\r\n            Box3i[] data = null; CodeBox3iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Box3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_(ref Matrix<Box3l> value)\r\n        {\r\n            Box3l[] data = null; CodeBox3lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Box3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_(ref Matrix<Box3f> value)\r\n        {\r\n            Box3f[] data = null; CodeBox3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Box3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_(ref Matrix<Box3d> value)\r\n        {\r\n            Box3d[] data = null; CodeBox3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Box3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_(ref Matrix<Euclidean3f> value)\r\n        {\r\n            Euclidean3f[] data = null; CodeEuclidean3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Euclidean3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_(ref Matrix<Euclidean3d> value)\r\n        {\r\n            Euclidean3d[] data = null; CodeEuclidean3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Euclidean3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_(ref Matrix<Rot2f> value)\r\n        {\r\n            Rot2f[] data = null; CodeRot2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Rot2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_(ref Matrix<Rot2d> value)\r\n        {\r\n            Rot2d[] data = null; CodeRot2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Rot2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_(ref Matrix<Rot3f> value)\r\n        {\r\n            Rot3f[] data = null; CodeRot3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Rot3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_(ref Matrix<Rot3d> value)\r\n        {\r\n            Rot3d[] data = null; CodeRot3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Rot3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_(ref Matrix<Scale3f> value)\r\n        {\r\n            Scale3f[] data = null; CodeScale3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Scale3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_(ref Matrix<Scale3d> value)\r\n        {\r\n            Scale3d[] data = null; CodeScale3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Scale3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_(ref Matrix<Shift3f> value)\r\n        {\r\n            Shift3f[] data = null; CodeShift3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Shift3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_(ref Matrix<Shift3d> value)\r\n        {\r\n            Shift3d[] data = null; CodeShift3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Shift3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_(ref Matrix<Trafo2f> value)\r\n        {\r\n            Trafo2f[] data = null; CodeTrafo2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Trafo2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_(ref Matrix<Trafo2d> value)\r\n        {\r\n            Trafo2d[] data = null; CodeTrafo2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Trafo2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_(ref Matrix<Trafo3f> value)\r\n        {\r\n            Trafo3f[] data = null; CodeTrafo3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Trafo3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_(ref Matrix<Trafo3d> value)\r\n        {\r\n            Trafo3d[] data = null; CodeTrafo3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Trafo3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_(ref Matrix<bool> value)\r\n        {\r\n            bool[] data = null; CodeBoolArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<bool>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_(ref Matrix<char> value)\r\n        {\r\n            char[] data = null; CodeCharArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<char>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_String_(ref Matrix<string> value)\r\n        {\r\n            string[] data = null; CodeStringArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<string>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_(ref Matrix<Type> value)\r\n        {\r\n            Type[] data = null; CodeTypeArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Type>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_(ref Matrix<Guid> value)\r\n        {\r\n            Guid[] data = null; CodeGuidArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Guid>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_(ref Matrix<Symbol> value)\r\n        {\r\n            Symbol[] data = null; CodeSymbolArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Symbol>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_(ref Matrix<Circle2d> value)\r\n        {\r\n            Circle2d[] data = null; CodeCircle2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Circle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_(ref Matrix<Line2d> value)\r\n        {\r\n            Line2d[] data = null; CodeLine2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Line2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_(ref Matrix<Line3d> value)\r\n        {\r\n            Line3d[] data = null; CodeLine3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Line3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_(ref Matrix<Plane2d> value)\r\n        {\r\n            Plane2d[] data = null; CodePlane2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Plane2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_(ref Matrix<Plane3d> value)\r\n        {\r\n            Plane3d[] data = null; CodePlane3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Plane3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_(ref Matrix<PlaneWithPoint3d> value)\r\n        {\r\n            PlaneWithPoint3d[] data = null; CodePlaneWithPoint3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<PlaneWithPoint3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_(ref Matrix<Quad2d> value)\r\n        {\r\n            Quad2d[] data = null; CodeQuad2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Quad2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_(ref Matrix<Quad3d> value)\r\n        {\r\n            Quad3d[] data = null; CodeQuad3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Quad3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_(ref Matrix<Ray2d> value)\r\n        {\r\n            Ray2d[] data = null; CodeRay2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Ray2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_(ref Matrix<Ray3d> value)\r\n        {\r\n            Ray3d[] data = null; CodeRay3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Ray3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_(ref Matrix<Sphere3d> value)\r\n        {\r\n            Sphere3d[] data = null; CodeSphere3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Sphere3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_(ref Matrix<Triangle2d> value)\r\n        {\r\n            Triangle2d[] data = null; CodeTriangle2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Triangle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_(ref Matrix<Triangle3d> value)\r\n        {\r\n            Triangle3d[] data = null; CodeTriangle3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Triangle3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_(ref Matrix<Circle2f> value)\r\n        {\r\n            Circle2f[] data = null; CodeCircle2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Circle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_(ref Matrix<Line2f> value)\r\n        {\r\n            Line2f[] data = null; CodeLine2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Line2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_(ref Matrix<Line3f> value)\r\n        {\r\n            Line3f[] data = null; CodeLine3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Line3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_(ref Matrix<Plane2f> value)\r\n        {\r\n            Plane2f[] data = null; CodePlane2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Plane2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_(ref Matrix<Plane3f> value)\r\n        {\r\n            Plane3f[] data = null; CodePlane3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Plane3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_(ref Matrix<PlaneWithPoint3f> value)\r\n        {\r\n            PlaneWithPoint3f[] data = null; CodePlaneWithPoint3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<PlaneWithPoint3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_(ref Matrix<Quad2f> value)\r\n        {\r\n            Quad2f[] data = null; CodeQuad2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Quad2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_(ref Matrix<Quad3f> value)\r\n        {\r\n            Quad3f[] data = null; CodeQuad3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Quad3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_(ref Matrix<Ray2f> value)\r\n        {\r\n            Ray2f[] data = null; CodeRay2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Ray2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_(ref Matrix<Ray3f> value)\r\n        {\r\n            Ray3f[] data = null; CodeRay3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Ray3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_(ref Matrix<Sphere3f> value)\r\n        {\r\n            Sphere3f[] data = null; CodeSphere3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Sphere3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_(ref Matrix<Triangle2f> value)\r\n        {\r\n            Triangle2f[] data = null; CodeTriangle2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Triangle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_(ref Matrix<Triangle3f> value)\r\n        {\r\n            Triangle3f[] data = null; CodeTriangle3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n            value = new Matrix<Triangle3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_(ref Volume<byte> value)\r\n        {\r\n            byte[] data = null; CodeByteArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<byte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_(ref Volume<sbyte> value)\r\n        {\r\n            sbyte[] data = null; CodeSByteArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<sbyte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Short_(ref Volume<short> value)\r\n        {\r\n            short[] data = null; CodeShortArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<short>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_(ref Volume<ushort> value)\r\n        {\r\n            ushort[] data = null; CodeUShortArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<ushort>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Int_(ref Volume<int> value)\r\n        {\r\n            int[] data = null; CodeIntArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<int>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_(ref Volume<uint> value)\r\n        {\r\n            uint[] data = null; CodeUIntArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<uint>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Long_(ref Volume<long> value)\r\n        {\r\n            long[] data = null; CodeLongArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<long>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_(ref Volume<ulong> value)\r\n        {\r\n            ulong[] data = null; CodeULongArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<ulong>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Float_(ref Volume<float> value)\r\n        {\r\n            float[] data = null; CodeFloatArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<float>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Double_(ref Volume<double> value)\r\n        {\r\n            double[] data = null; CodeDoubleArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<double>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_(ref Volume<Fraction> value)\r\n        {\r\n            Fraction[] data = null; CodeFractionArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Fraction>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_(ref Volume<V2i> value)\r\n        {\r\n            V2i[] data = null; CodeV2iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_(ref Volume<V2l> value)\r\n        {\r\n            V2l[] data = null; CodeV2lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_(ref Volume<V2f> value)\r\n        {\r\n            V2f[] data = null; CodeV2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_(ref Volume<V2d> value)\r\n        {\r\n            V2d[] data = null; CodeV2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_(ref Volume<V3i> value)\r\n        {\r\n            V3i[] data = null; CodeV3iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_(ref Volume<V3l> value)\r\n        {\r\n            V3l[] data = null; CodeV3lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_(ref Volume<V3f> value)\r\n        {\r\n            V3f[] data = null; CodeV3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_(ref Volume<V3d> value)\r\n        {\r\n            V3d[] data = null; CodeV3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_(ref Volume<V4i> value)\r\n        {\r\n            V4i[] data = null; CodeV4iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V4i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_(ref Volume<V4l> value)\r\n        {\r\n            V4l[] data = null; CodeV4lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V4l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_(ref Volume<V4f> value)\r\n        {\r\n            V4f[] data = null; CodeV4fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_(ref Volume<V4d> value)\r\n        {\r\n            V4d[] data = null; CodeV4dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<V4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_(ref Volume<M22i> value)\r\n        {\r\n            M22i[] data = null; CodeM22iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M22i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_(ref Volume<M22l> value)\r\n        {\r\n            M22l[] data = null; CodeM22lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M22l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_(ref Volume<M22f> value)\r\n        {\r\n            M22f[] data = null; CodeM22fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M22f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_(ref Volume<M22d> value)\r\n        {\r\n            M22d[] data = null; CodeM22dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M22d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_(ref Volume<M23i> value)\r\n        {\r\n            M23i[] data = null; CodeM23iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M23i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_(ref Volume<M23l> value)\r\n        {\r\n            M23l[] data = null; CodeM23lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M23l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_(ref Volume<M23f> value)\r\n        {\r\n            M23f[] data = null; CodeM23fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M23f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_(ref Volume<M23d> value)\r\n        {\r\n            M23d[] data = null; CodeM23dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M23d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_(ref Volume<M33i> value)\r\n        {\r\n            M33i[] data = null; CodeM33iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M33i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_(ref Volume<M33l> value)\r\n        {\r\n            M33l[] data = null; CodeM33lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M33l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_(ref Volume<M33f> value)\r\n        {\r\n            M33f[] data = null; CodeM33fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M33f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_(ref Volume<M33d> value)\r\n        {\r\n            M33d[] data = null; CodeM33dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M33d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_(ref Volume<M34i> value)\r\n        {\r\n            M34i[] data = null; CodeM34iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M34i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_(ref Volume<M34l> value)\r\n        {\r\n            M34l[] data = null; CodeM34lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M34l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_(ref Volume<M34f> value)\r\n        {\r\n            M34f[] data = null; CodeM34fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M34f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_(ref Volume<M34d> value)\r\n        {\r\n            M34d[] data = null; CodeM34dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M34d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_(ref Volume<M44i> value)\r\n        {\r\n            M44i[] data = null; CodeM44iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M44i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_(ref Volume<M44l> value)\r\n        {\r\n            M44l[] data = null; CodeM44lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M44l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_(ref Volume<M44f> value)\r\n        {\r\n            M44f[] data = null; CodeM44fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M44f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_(ref Volume<M44d> value)\r\n        {\r\n            M44d[] data = null; CodeM44dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<M44d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_(ref Volume<C3b> value)\r\n        {\r\n            C3b[] data = null; CodeC3bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C3b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_(ref Volume<C3us> value)\r\n        {\r\n            C3us[] data = null; CodeC3usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C3us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_(ref Volume<C3ui> value)\r\n        {\r\n            C3ui[] data = null; CodeC3uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C3ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_(ref Volume<C3f> value)\r\n        {\r\n            C3f[] data = null; CodeC3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_(ref Volume<C3d> value)\r\n        {\r\n            C3d[] data = null; CodeC3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_(ref Volume<C4b> value)\r\n        {\r\n            C4b[] data = null; CodeC4bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C4b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_(ref Volume<C4us> value)\r\n        {\r\n            C4us[] data = null; CodeC4usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C4us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_(ref Volume<C4ui> value)\r\n        {\r\n            C4ui[] data = null; CodeC4uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C4ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_(ref Volume<C4f> value)\r\n        {\r\n            C4f[] data = null; CodeC4fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_(ref Volume<C4d> value)\r\n        {\r\n            C4d[] data = null; CodeC4dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<C4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_(ref Volume<Range1b> value)\r\n        {\r\n            Range1b[] data = null; CodeRange1bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_(ref Volume<Range1sb> value)\r\n        {\r\n            Range1sb[] data = null; CodeRange1sbArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1sb>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_(ref Volume<Range1s> value)\r\n        {\r\n            Range1s[] data = null; CodeRange1sArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1s>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_(ref Volume<Range1us> value)\r\n        {\r\n            Range1us[] data = null; CodeRange1usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_(ref Volume<Range1i> value)\r\n        {\r\n            Range1i[] data = null; CodeRange1iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_(ref Volume<Range1ui> value)\r\n        {\r\n            Range1ui[] data = null; CodeRange1uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_(ref Volume<Range1l> value)\r\n        {\r\n            Range1l[] data = null; CodeRange1lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_(ref Volume<Range1ul> value)\r\n        {\r\n            Range1ul[] data = null; CodeRange1ulArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1ul>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_(ref Volume<Range1f> value)\r\n        {\r\n            Range1f[] data = null; CodeRange1fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_(ref Volume<Range1d> value)\r\n        {\r\n            Range1d[] data = null; CodeRange1dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Range1d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_(ref Volume<Box2i> value)\r\n        {\r\n            Box2i[] data = null; CodeBox2iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Box2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_(ref Volume<Box2l> value)\r\n        {\r\n            Box2l[] data = null; CodeBox2lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Box2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_(ref Volume<Box2f> value)\r\n        {\r\n            Box2f[] data = null; CodeBox2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Box2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_(ref Volume<Box2d> value)\r\n        {\r\n            Box2d[] data = null; CodeBox2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Box2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_(ref Volume<Box3i> value)\r\n        {\r\n            Box3i[] data = null; CodeBox3iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Box3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_(ref Volume<Box3l> value)\r\n        {\r\n            Box3l[] data = null; CodeBox3lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Box3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_(ref Volume<Box3f> value)\r\n        {\r\n            Box3f[] data = null; CodeBox3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Box3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_(ref Volume<Box3d> value)\r\n        {\r\n            Box3d[] data = null; CodeBox3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Box3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_(ref Volume<Euclidean3f> value)\r\n        {\r\n            Euclidean3f[] data = null; CodeEuclidean3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Euclidean3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_(ref Volume<Euclidean3d> value)\r\n        {\r\n            Euclidean3d[] data = null; CodeEuclidean3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Euclidean3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_(ref Volume<Rot2f> value)\r\n        {\r\n            Rot2f[] data = null; CodeRot2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Rot2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_(ref Volume<Rot2d> value)\r\n        {\r\n            Rot2d[] data = null; CodeRot2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Rot2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_(ref Volume<Rot3f> value)\r\n        {\r\n            Rot3f[] data = null; CodeRot3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Rot3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_(ref Volume<Rot3d> value)\r\n        {\r\n            Rot3d[] data = null; CodeRot3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Rot3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_(ref Volume<Scale3f> value)\r\n        {\r\n            Scale3f[] data = null; CodeScale3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Scale3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_(ref Volume<Scale3d> value)\r\n        {\r\n            Scale3d[] data = null; CodeScale3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Scale3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_(ref Volume<Shift3f> value)\r\n        {\r\n            Shift3f[] data = null; CodeShift3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Shift3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_(ref Volume<Shift3d> value)\r\n        {\r\n            Shift3d[] data = null; CodeShift3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Shift3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_(ref Volume<Trafo2f> value)\r\n        {\r\n            Trafo2f[] data = null; CodeTrafo2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Trafo2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_(ref Volume<Trafo2d> value)\r\n        {\r\n            Trafo2d[] data = null; CodeTrafo2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Trafo2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_(ref Volume<Trafo3f> value)\r\n        {\r\n            Trafo3f[] data = null; CodeTrafo3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Trafo3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_(ref Volume<Trafo3d> value)\r\n        {\r\n            Trafo3d[] data = null; CodeTrafo3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Trafo3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_(ref Volume<bool> value)\r\n        {\r\n            bool[] data = null; CodeBoolArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<bool>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Char_(ref Volume<char> value)\r\n        {\r\n            char[] data = null; CodeCharArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<char>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_String_(ref Volume<string> value)\r\n        {\r\n            string[] data = null; CodeStringArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<string>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Type_(ref Volume<Type> value)\r\n        {\r\n            Type[] data = null; CodeTypeArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Type>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_(ref Volume<Guid> value)\r\n        {\r\n            Guid[] data = null; CodeGuidArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Guid>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_(ref Volume<Symbol> value)\r\n        {\r\n            Symbol[] data = null; CodeSymbolArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Symbol>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_(ref Volume<Circle2d> value)\r\n        {\r\n            Circle2d[] data = null; CodeCircle2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Circle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_(ref Volume<Line2d> value)\r\n        {\r\n            Line2d[] data = null; CodeLine2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Line2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_(ref Volume<Line3d> value)\r\n        {\r\n            Line3d[] data = null; CodeLine3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Line3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_(ref Volume<Plane2d> value)\r\n        {\r\n            Plane2d[] data = null; CodePlane2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Plane2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_(ref Volume<Plane3d> value)\r\n        {\r\n            Plane3d[] data = null; CodePlane3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Plane3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_(ref Volume<PlaneWithPoint3d> value)\r\n        {\r\n            PlaneWithPoint3d[] data = null; CodePlaneWithPoint3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<PlaneWithPoint3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_(ref Volume<Quad2d> value)\r\n        {\r\n            Quad2d[] data = null; CodeQuad2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Quad2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_(ref Volume<Quad3d> value)\r\n        {\r\n            Quad3d[] data = null; CodeQuad3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Quad3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_(ref Volume<Ray2d> value)\r\n        {\r\n            Ray2d[] data = null; CodeRay2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Ray2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_(ref Volume<Ray3d> value)\r\n        {\r\n            Ray3d[] data = null; CodeRay3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Ray3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_(ref Volume<Sphere3d> value)\r\n        {\r\n            Sphere3d[] data = null; CodeSphere3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Sphere3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_(ref Volume<Triangle2d> value)\r\n        {\r\n            Triangle2d[] data = null; CodeTriangle2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Triangle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_(ref Volume<Triangle3d> value)\r\n        {\r\n            Triangle3d[] data = null; CodeTriangle3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Triangle3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_(ref Volume<Circle2f> value)\r\n        {\r\n            Circle2f[] data = null; CodeCircle2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Circle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_(ref Volume<Line2f> value)\r\n        {\r\n            Line2f[] data = null; CodeLine2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Line2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_(ref Volume<Line3f> value)\r\n        {\r\n            Line3f[] data = null; CodeLine3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Line3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_(ref Volume<Plane2f> value)\r\n        {\r\n            Plane2f[] data = null; CodePlane2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Plane2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_(ref Volume<Plane3f> value)\r\n        {\r\n            Plane3f[] data = null; CodePlane3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Plane3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_(ref Volume<PlaneWithPoint3f> value)\r\n        {\r\n            PlaneWithPoint3f[] data = null; CodePlaneWithPoint3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<PlaneWithPoint3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_(ref Volume<Quad2f> value)\r\n        {\r\n            Quad2f[] data = null; CodeQuad2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Quad2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_(ref Volume<Quad3f> value)\r\n        {\r\n            Quad3f[] data = null; CodeQuad3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Quad3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_(ref Volume<Ray2f> value)\r\n        {\r\n            Ray2f[] data = null; CodeRay2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Ray2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_(ref Volume<Ray3f> value)\r\n        {\r\n            Ray3f[] data = null; CodeRay3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Ray3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_(ref Volume<Sphere3f> value)\r\n        {\r\n            Sphere3f[] data = null; CodeSphere3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Sphere3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_(ref Volume<Triangle2f> value)\r\n        {\r\n            Triangle2f[] data = null; CodeTriangle2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Triangle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_(ref Volume<Triangle3f> value)\r\n        {\r\n            Triangle3f[] data = null; CodeTriangle3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n            value = new Volume<Triangle3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_(ref Tensor<byte> value)\r\n        {\r\n            byte[] data = null; CodeByteArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<byte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_(ref Tensor<sbyte> value)\r\n        {\r\n            sbyte[] data = null; CodeSByteArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<sbyte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Short_(ref Tensor<short> value)\r\n        {\r\n            short[] data = null; CodeShortArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<short>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_(ref Tensor<ushort> value)\r\n        {\r\n            ushort[] data = null; CodeUShortArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<ushort>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Int_(ref Tensor<int> value)\r\n        {\r\n            int[] data = null; CodeIntArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<int>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_(ref Tensor<uint> value)\r\n        {\r\n            uint[] data = null; CodeUIntArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<uint>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Long_(ref Tensor<long> value)\r\n        {\r\n            long[] data = null; CodeLongArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<long>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_(ref Tensor<ulong> value)\r\n        {\r\n            ulong[] data = null; CodeULongArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<ulong>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Float_(ref Tensor<float> value)\r\n        {\r\n            float[] data = null; CodeFloatArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<float>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Double_(ref Tensor<double> value)\r\n        {\r\n            double[] data = null; CodeDoubleArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<double>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_(ref Tensor<Fraction> value)\r\n        {\r\n            Fraction[] data = null; CodeFractionArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Fraction>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_(ref Tensor<V2i> value)\r\n        {\r\n            V2i[] data = null; CodeV2iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_(ref Tensor<V2l> value)\r\n        {\r\n            V2l[] data = null; CodeV2lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_(ref Tensor<V2f> value)\r\n        {\r\n            V2f[] data = null; CodeV2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_(ref Tensor<V2d> value)\r\n        {\r\n            V2d[] data = null; CodeV2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_(ref Tensor<V3i> value)\r\n        {\r\n            V3i[] data = null; CodeV3iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_(ref Tensor<V3l> value)\r\n        {\r\n            V3l[] data = null; CodeV3lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_(ref Tensor<V3f> value)\r\n        {\r\n            V3f[] data = null; CodeV3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_(ref Tensor<V3d> value)\r\n        {\r\n            V3d[] data = null; CodeV3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_(ref Tensor<V4i> value)\r\n        {\r\n            V4i[] data = null; CodeV4iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V4i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_(ref Tensor<V4l> value)\r\n        {\r\n            V4l[] data = null; CodeV4lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V4l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_(ref Tensor<V4f> value)\r\n        {\r\n            V4f[] data = null; CodeV4fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_(ref Tensor<V4d> value)\r\n        {\r\n            V4d[] data = null; CodeV4dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<V4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_(ref Tensor<M22i> value)\r\n        {\r\n            M22i[] data = null; CodeM22iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M22i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_(ref Tensor<M22l> value)\r\n        {\r\n            M22l[] data = null; CodeM22lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M22l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_(ref Tensor<M22f> value)\r\n        {\r\n            M22f[] data = null; CodeM22fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M22f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_(ref Tensor<M22d> value)\r\n        {\r\n            M22d[] data = null; CodeM22dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M22d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_(ref Tensor<M23i> value)\r\n        {\r\n            M23i[] data = null; CodeM23iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M23i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_(ref Tensor<M23l> value)\r\n        {\r\n            M23l[] data = null; CodeM23lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M23l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_(ref Tensor<M23f> value)\r\n        {\r\n            M23f[] data = null; CodeM23fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M23f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_(ref Tensor<M23d> value)\r\n        {\r\n            M23d[] data = null; CodeM23dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M23d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_(ref Tensor<M33i> value)\r\n        {\r\n            M33i[] data = null; CodeM33iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M33i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_(ref Tensor<M33l> value)\r\n        {\r\n            M33l[] data = null; CodeM33lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M33l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_(ref Tensor<M33f> value)\r\n        {\r\n            M33f[] data = null; CodeM33fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M33f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_(ref Tensor<M33d> value)\r\n        {\r\n            M33d[] data = null; CodeM33dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M33d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_(ref Tensor<M34i> value)\r\n        {\r\n            M34i[] data = null; CodeM34iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M34i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_(ref Tensor<M34l> value)\r\n        {\r\n            M34l[] data = null; CodeM34lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M34l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_(ref Tensor<M34f> value)\r\n        {\r\n            M34f[] data = null; CodeM34fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M34f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_(ref Tensor<M34d> value)\r\n        {\r\n            M34d[] data = null; CodeM34dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M34d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_(ref Tensor<M44i> value)\r\n        {\r\n            M44i[] data = null; CodeM44iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M44i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_(ref Tensor<M44l> value)\r\n        {\r\n            M44l[] data = null; CodeM44lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M44l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_(ref Tensor<M44f> value)\r\n        {\r\n            M44f[] data = null; CodeM44fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M44f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_(ref Tensor<M44d> value)\r\n        {\r\n            M44d[] data = null; CodeM44dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<M44d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_(ref Tensor<C3b> value)\r\n        {\r\n            C3b[] data = null; CodeC3bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C3b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_(ref Tensor<C3us> value)\r\n        {\r\n            C3us[] data = null; CodeC3usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C3us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_(ref Tensor<C3ui> value)\r\n        {\r\n            C3ui[] data = null; CodeC3uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C3ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_(ref Tensor<C3f> value)\r\n        {\r\n            C3f[] data = null; CodeC3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_(ref Tensor<C3d> value)\r\n        {\r\n            C3d[] data = null; CodeC3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_(ref Tensor<C4b> value)\r\n        {\r\n            C4b[] data = null; CodeC4bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C4b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_(ref Tensor<C4us> value)\r\n        {\r\n            C4us[] data = null; CodeC4usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C4us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_(ref Tensor<C4ui> value)\r\n        {\r\n            C4ui[] data = null; CodeC4uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C4ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_(ref Tensor<C4f> value)\r\n        {\r\n            C4f[] data = null; CodeC4fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_(ref Tensor<C4d> value)\r\n        {\r\n            C4d[] data = null; CodeC4dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<C4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_(ref Tensor<Range1b> value)\r\n        {\r\n            Range1b[] data = null; CodeRange1bArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_(ref Tensor<Range1sb> value)\r\n        {\r\n            Range1sb[] data = null; CodeRange1sbArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1sb>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_(ref Tensor<Range1s> value)\r\n        {\r\n            Range1s[] data = null; CodeRange1sArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1s>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_(ref Tensor<Range1us> value)\r\n        {\r\n            Range1us[] data = null; CodeRange1usArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_(ref Tensor<Range1i> value)\r\n        {\r\n            Range1i[] data = null; CodeRange1iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_(ref Tensor<Range1ui> value)\r\n        {\r\n            Range1ui[] data = null; CodeRange1uiArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_(ref Tensor<Range1l> value)\r\n        {\r\n            Range1l[] data = null; CodeRange1lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_(ref Tensor<Range1ul> value)\r\n        {\r\n            Range1ul[] data = null; CodeRange1ulArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1ul>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_(ref Tensor<Range1f> value)\r\n        {\r\n            Range1f[] data = null; CodeRange1fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_(ref Tensor<Range1d> value)\r\n        {\r\n            Range1d[] data = null; CodeRange1dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Range1d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_(ref Tensor<Box2i> value)\r\n        {\r\n            Box2i[] data = null; CodeBox2iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Box2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_(ref Tensor<Box2l> value)\r\n        {\r\n            Box2l[] data = null; CodeBox2lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Box2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_(ref Tensor<Box2f> value)\r\n        {\r\n            Box2f[] data = null; CodeBox2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Box2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_(ref Tensor<Box2d> value)\r\n        {\r\n            Box2d[] data = null; CodeBox2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Box2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_(ref Tensor<Box3i> value)\r\n        {\r\n            Box3i[] data = null; CodeBox3iArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Box3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_(ref Tensor<Box3l> value)\r\n        {\r\n            Box3l[] data = null; CodeBox3lArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Box3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_(ref Tensor<Box3f> value)\r\n        {\r\n            Box3f[] data = null; CodeBox3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Box3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_(ref Tensor<Box3d> value)\r\n        {\r\n            Box3d[] data = null; CodeBox3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Box3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_(ref Tensor<Euclidean3f> value)\r\n        {\r\n            Euclidean3f[] data = null; CodeEuclidean3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Euclidean3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_(ref Tensor<Euclidean3d> value)\r\n        {\r\n            Euclidean3d[] data = null; CodeEuclidean3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Euclidean3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_(ref Tensor<Rot2f> value)\r\n        {\r\n            Rot2f[] data = null; CodeRot2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Rot2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_(ref Tensor<Rot2d> value)\r\n        {\r\n            Rot2d[] data = null; CodeRot2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Rot2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_(ref Tensor<Rot3f> value)\r\n        {\r\n            Rot3f[] data = null; CodeRot3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Rot3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_(ref Tensor<Rot3d> value)\r\n        {\r\n            Rot3d[] data = null; CodeRot3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Rot3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_(ref Tensor<Scale3f> value)\r\n        {\r\n            Scale3f[] data = null; CodeScale3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Scale3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_(ref Tensor<Scale3d> value)\r\n        {\r\n            Scale3d[] data = null; CodeScale3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Scale3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_(ref Tensor<Shift3f> value)\r\n        {\r\n            Shift3f[] data = null; CodeShift3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Shift3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_(ref Tensor<Shift3d> value)\r\n        {\r\n            Shift3d[] data = null; CodeShift3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Shift3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_(ref Tensor<Trafo2f> value)\r\n        {\r\n            Trafo2f[] data = null; CodeTrafo2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Trafo2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_(ref Tensor<Trafo2d> value)\r\n        {\r\n            Trafo2d[] data = null; CodeTrafo2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Trafo2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_(ref Tensor<Trafo3f> value)\r\n        {\r\n            Trafo3f[] data = null; CodeTrafo3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Trafo3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_(ref Tensor<Trafo3d> value)\r\n        {\r\n            Trafo3d[] data = null; CodeTrafo3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Trafo3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_(ref Tensor<bool> value)\r\n        {\r\n            bool[] data = null; CodeBoolArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<bool>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Char_(ref Tensor<char> value)\r\n        {\r\n            char[] data = null; CodeCharArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<char>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_String_(ref Tensor<string> value)\r\n        {\r\n            string[] data = null; CodeStringArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<string>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Type_(ref Tensor<Type> value)\r\n        {\r\n            Type[] data = null; CodeTypeArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Type>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_(ref Tensor<Guid> value)\r\n        {\r\n            Guid[] data = null; CodeGuidArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Guid>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_(ref Tensor<Symbol> value)\r\n        {\r\n            Symbol[] data = null; CodeSymbolArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Symbol>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_(ref Tensor<Circle2d> value)\r\n        {\r\n            Circle2d[] data = null; CodeCircle2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Circle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_(ref Tensor<Line2d> value)\r\n        {\r\n            Line2d[] data = null; CodeLine2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Line2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_(ref Tensor<Line3d> value)\r\n        {\r\n            Line3d[] data = null; CodeLine3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Line3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_(ref Tensor<Plane2d> value)\r\n        {\r\n            Plane2d[] data = null; CodePlane2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Plane2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_(ref Tensor<Plane3d> value)\r\n        {\r\n            Plane3d[] data = null; CodePlane3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Plane3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_(ref Tensor<PlaneWithPoint3d> value)\r\n        {\r\n            PlaneWithPoint3d[] data = null; CodePlaneWithPoint3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<PlaneWithPoint3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_(ref Tensor<Quad2d> value)\r\n        {\r\n            Quad2d[] data = null; CodeQuad2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Quad2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_(ref Tensor<Quad3d> value)\r\n        {\r\n            Quad3d[] data = null; CodeQuad3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Quad3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_(ref Tensor<Ray2d> value)\r\n        {\r\n            Ray2d[] data = null; CodeRay2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Ray2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_(ref Tensor<Ray3d> value)\r\n        {\r\n            Ray3d[] data = null; CodeRay3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Ray3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_(ref Tensor<Sphere3d> value)\r\n        {\r\n            Sphere3d[] data = null; CodeSphere3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Sphere3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_(ref Tensor<Triangle2d> value)\r\n        {\r\n            Triangle2d[] data = null; CodeTriangle2dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Triangle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_(ref Tensor<Triangle3d> value)\r\n        {\r\n            Triangle3d[] data = null; CodeTriangle3dArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Triangle3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_(ref Tensor<Circle2f> value)\r\n        {\r\n            Circle2f[] data = null; CodeCircle2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Circle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_(ref Tensor<Line2f> value)\r\n        {\r\n            Line2f[] data = null; CodeLine2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Line2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_(ref Tensor<Line3f> value)\r\n        {\r\n            Line3f[] data = null; CodeLine3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Line3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_(ref Tensor<Plane2f> value)\r\n        {\r\n            Plane2f[] data = null; CodePlane2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Plane2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_(ref Tensor<Plane3f> value)\r\n        {\r\n            Plane3f[] data = null; CodePlane3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Plane3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_(ref Tensor<PlaneWithPoint3f> value)\r\n        {\r\n            PlaneWithPoint3f[] data = null; CodePlaneWithPoint3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<PlaneWithPoint3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_(ref Tensor<Quad2f> value)\r\n        {\r\n            Quad2f[] data = null; CodeQuad2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Quad2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_(ref Tensor<Quad3f> value)\r\n        {\r\n            Quad3f[] data = null; CodeQuad3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Quad3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_(ref Tensor<Ray2f> value)\r\n        {\r\n            Ray2f[] data = null; CodeRay2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Ray2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_(ref Tensor<Ray3f> value)\r\n        {\r\n            Ray3f[] data = null; CodeRay3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Ray3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_(ref Tensor<Sphere3f> value)\r\n        {\r\n            Sphere3f[] data = null; CodeSphere3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Sphere3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_(ref Tensor<Triangle2f> value)\r\n        {\r\n            Triangle2f[] data = null; CodeTriangle2fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Triangle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_(ref Tensor<Triangle3f> value)\r\n        {\r\n            Triangle3f[] data = null; CodeTriangle3fArray(ref data);\r\n            long origin = 0L; CodeLong(ref origin);\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n            value = new Tensor<Triangle3f>(data, origin, size, delta);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Arrays\r\n\r\n        public void CodeV2iArray(ref V2i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV2uiArray(ref V2ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV2lArray(ref V2l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV2fArray(ref V2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV2dArray(ref V2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3iArray(ref V3i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3uiArray(ref V3ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3lArray(ref V3l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3fArray(ref V3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3dArray(ref V3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4iArray(ref V4i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4uiArray(ref V4ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4lArray(ref V4l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4fArray(ref V4f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4dArray(ref V4d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM22iArray(ref M22i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM22lArray(ref M22l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM22fArray(ref M22f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM22dArray(ref M22d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM23iArray(ref M23i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM23lArray(ref M23l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM23fArray(ref M23f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM23dArray(ref M23d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM33iArray(ref M33i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM33lArray(ref M33l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM33fArray(ref M33f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM33dArray(ref M33d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM34iArray(ref M34i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM34lArray(ref M34l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM34fArray(ref M34f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM34dArray(ref M34d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM44iArray(ref M44i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM44lArray(ref M44l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM44fArray(ref M44f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM44dArray(ref M44d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1bArray(ref Range1b[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1sbArray(ref Range1sb[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1sArray(ref Range1s[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1usArray(ref Range1us[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1iArray(ref Range1i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1uiArray(ref Range1ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1lArray(ref Range1l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1ulArray(ref Range1ul[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1fArray(ref Range1f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1dArray(ref Range1d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox2iArray(ref Box2i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox2lArray(ref Box2l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox2fArray(ref Box2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox2dArray(ref Box2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox3iArray(ref Box3i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox3lArray(ref Box3l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox3fArray(ref Box3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox3dArray(ref Box3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3bArray(ref C3b[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3usArray(ref C3us[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3uiArray(ref C3ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3fArray(ref C3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3dArray(ref C3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4bArray(ref C4b[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4usArray(ref C4us[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4uiArray(ref C4ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4fArray(ref C4f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4dArray(ref C4d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeEuclidean3fArray(ref Euclidean3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3dArray(ref Euclidean3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2fArray(ref Rot2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2dArray(ref Rot2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3fArray(ref Rot3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3dArray(ref Rot3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3fArray(ref Scale3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3dArray(ref Scale3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3fArray(ref Shift3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3dArray(ref Shift3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2fArray(ref Trafo2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2dArray(ref Trafo2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3fArray(ref Trafo3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3dArray(ref Trafo3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeCircle2dArray(ref Circle2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeCircle2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeLine2dArray(ref Line2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLine2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeLine3dArray(ref Line3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLine3d(ref value[i]);\r\n        }\r\n\r\n        public void CodePlane2dArray(ref Plane2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlane2d(ref value[i]);\r\n        }\r\n\r\n        public void CodePlane3dArray(ref Plane3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlane3d(ref value[i]);\r\n        }\r\n\r\n        public void CodePlaneWithPoint3dArray(ref PlaneWithPoint3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlaneWithPoint3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeQuad2dArray(ref Quad2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeQuad2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeQuad3dArray(ref Quad3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeQuad3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeRay2dArray(ref Ray2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRay2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeRay3dArray(ref Ray3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRay3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeSphere3dArray(ref Sphere3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSphere3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeTriangle2dArray(ref Triangle2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTriangle2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeTriangle3dArray(ref Triangle3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTriangle3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeCircle2fArray(ref Circle2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeCircle2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeLine2fArray(ref Line2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLine2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeLine3fArray(ref Line3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLine3f(ref value[i]);\r\n        }\r\n\r\n        public void CodePlane2fArray(ref Plane2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlane2f(ref value[i]);\r\n        }\r\n\r\n        public void CodePlane3fArray(ref Plane3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlane3f(ref value[i]);\r\n        }\r\n\r\n        public void CodePlaneWithPoint3fArray(ref PlaneWithPoint3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlaneWithPoint3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeQuad2fArray(ref Quad2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeQuad2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeQuad3fArray(ref Quad3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeQuad3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeRay2fArray(ref Ray2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRay2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeRay3fArray(ref Ray3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRay3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeSphere3fArray(ref Sphere3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSphere3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeTriangle2fArray(ref Triangle2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTriangle2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeTriangle3fArray(ref Triangle3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTriangle3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Byte_Array(ref Vector<byte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Byte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_SByte_Array(ref Vector<sbyte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_SByte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Short_Array(ref Vector<short>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Short_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_UShort_Array(ref Vector<ushort>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_UShort_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Int_Array(ref Vector<int>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Int_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_UInt_Array(ref Vector<uint>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_UInt_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Long_Array(ref Vector<long>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Long_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_ULong_Array(ref Vector<ulong>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_ULong_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Float_Array(ref Vector<float>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Float_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Double_Array(ref Vector<double>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Double_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_Array(ref Vector<Fraction>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Fraction_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V2i_Array(ref Vector<V2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V2l_Array(ref Vector<V2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V2f_Array(ref Vector<V2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V2d_Array(ref Vector<V2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V3i_Array(ref Vector<V3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V3l_Array(ref Vector<V3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V3f_Array(ref Vector<V3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V3d_Array(ref Vector<V3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V4i_Array(ref Vector<V4i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V4i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V4l_Array(ref Vector<V4l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V4l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V4f_Array(ref Vector<V4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V4d_Array(ref Vector<V4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M22i_Array(ref Vector<M22i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M22i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M22l_Array(ref Vector<M22l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M22l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M22f_Array(ref Vector<M22f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M22f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M22d_Array(ref Vector<M22d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M22d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M23i_Array(ref Vector<M23i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M23i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M23l_Array(ref Vector<M23l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M23l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M23f_Array(ref Vector<M23f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M23f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M23d_Array(ref Vector<M23d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M23d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M33i_Array(ref Vector<M33i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M33i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M33l_Array(ref Vector<M33l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M33l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M33f_Array(ref Vector<M33f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M33f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M33d_Array(ref Vector<M33d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M33d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M34i_Array(ref Vector<M34i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M34i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M34l_Array(ref Vector<M34l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M34l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M34f_Array(ref Vector<M34f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M34f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M34d_Array(ref Vector<M34d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M34d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M44i_Array(ref Vector<M44i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M44i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M44l_Array(ref Vector<M44l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M44l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M44f_Array(ref Vector<M44f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M44f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M44d_Array(ref Vector<M44d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M44d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3b_Array(ref Vector<C3b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3us_Array(ref Vector<C3us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_Array(ref Vector<C3ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3f_Array(ref Vector<C3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3d_Array(ref Vector<C3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4b_Array(ref Vector<C4b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4us_Array(ref Vector<C4us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_Array(ref Vector<C4ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4f_Array(ref Vector<C4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4d_Array(ref Vector<C4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_Array(ref Vector<Range1b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_Array(ref Vector<Range1sb>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1sb_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_Array(ref Vector<Range1s>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1s_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_Array(ref Vector<Range1us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_Array(ref Vector<Range1i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_Array(ref Vector<Range1ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_Array(ref Vector<Range1l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_Array(ref Vector<Range1ul>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1ul_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_Array(ref Vector<Range1f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_Array(ref Vector<Range1d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_Array(ref Vector<Box2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_Array(ref Vector<Box2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_Array(ref Vector<Box2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_Array(ref Vector<Box2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_Array(ref Vector<Box3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_Array(ref Vector<Box3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_Array(ref Vector<Box3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_Array(ref Vector<Box3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_Array(ref Vector<Euclidean3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Euclidean3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_Array(ref Vector<Euclidean3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Euclidean3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_Array(ref Vector<Rot2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Rot2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_Array(ref Vector<Rot2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Rot2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_Array(ref Vector<Rot3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Rot3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_Array(ref Vector<Rot3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Rot3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_Array(ref Vector<Scale3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Scale3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_Array(ref Vector<Scale3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Scale3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_Array(ref Vector<Shift3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Shift3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_Array(ref Vector<Shift3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Shift3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_Array(ref Vector<Trafo2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Trafo2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_Array(ref Vector<Trafo2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Trafo2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_Array(ref Vector<Trafo3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Trafo3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_Array(ref Vector<Trafo3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Trafo3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Bool_Array(ref Vector<bool>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Bool_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Char_Array(ref Vector<char>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Char_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_String_Array(ref Vector<string>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_String_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Type_Array(ref Vector<Type>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Type_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Guid_Array(ref Vector<Guid>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Guid_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_Array(ref Vector<Symbol>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Symbol_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_Array(ref Vector<Circle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Circle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_Array(ref Vector<Line2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Line2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_Array(ref Vector<Line3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Line3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_Array(ref Vector<Plane2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Plane2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_Array(ref Vector<Plane3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Plane3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_Array(ref Vector<PlaneWithPoint3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_PlaneWithPoint3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_Array(ref Vector<Quad2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Quad2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_Array(ref Vector<Quad3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Quad3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_Array(ref Vector<Ray2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Ray2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_Array(ref Vector<Ray3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Ray3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_Array(ref Vector<Sphere3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Sphere3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_Array(ref Vector<Triangle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Triangle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_Array(ref Vector<Triangle3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Triangle3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_Array(ref Vector<Circle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Circle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_Array(ref Vector<Line2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Line2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_Array(ref Vector<Line3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Line3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_Array(ref Vector<Plane2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Plane2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_Array(ref Vector<Plane3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Plane3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_Array(ref Vector<PlaneWithPoint3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_PlaneWithPoint3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_Array(ref Vector<Quad2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Quad2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_Array(ref Vector<Quad3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Quad3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_Array(ref Vector<Ray2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Ray2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_Array(ref Vector<Ray3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Ray3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_Array(ref Vector<Sphere3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Sphere3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_Array(ref Vector<Triangle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Triangle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_Array(ref Vector<Triangle3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Triangle3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_Array(ref Matrix<byte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Byte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_Array(ref Matrix<sbyte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_SByte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_Array(ref Matrix<short>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Short_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_Array(ref Matrix<ushort>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_UShort_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_Array(ref Matrix<int>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Int_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_Array(ref Matrix<uint>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_UInt_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_Array(ref Matrix<long>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Long_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_Array(ref Matrix<ulong>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_ULong_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_Array(ref Matrix<float>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Float_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_Array(ref Matrix<double>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Double_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_Array(ref Matrix<Fraction>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Fraction_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_Array(ref Matrix<V2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_Array(ref Matrix<V2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_Array(ref Matrix<V2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_Array(ref Matrix<V2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_Array(ref Matrix<V3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_Array(ref Matrix<V3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_Array(ref Matrix<V3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_Array(ref Matrix<V3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_Array(ref Matrix<V4i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V4i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_Array(ref Matrix<V4l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V4l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_Array(ref Matrix<V4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_Array(ref Matrix<V4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_Array(ref Matrix<M22i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M22i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_Array(ref Matrix<M22l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M22l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_Array(ref Matrix<M22f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M22f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_Array(ref Matrix<M22d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M22d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_Array(ref Matrix<M23i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M23i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_Array(ref Matrix<M23l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M23l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_Array(ref Matrix<M23f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M23f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_Array(ref Matrix<M23d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M23d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_Array(ref Matrix<M33i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M33i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_Array(ref Matrix<M33l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M33l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_Array(ref Matrix<M33f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M33f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_Array(ref Matrix<M33d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M33d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_Array(ref Matrix<M34i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M34i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_Array(ref Matrix<M34l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M34l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_Array(ref Matrix<M34f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M34f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_Array(ref Matrix<M34d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M34d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_Array(ref Matrix<M44i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M44i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_Array(ref Matrix<M44l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M44l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_Array(ref Matrix<M44f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M44f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_Array(ref Matrix<M44d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M44d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_Array(ref Matrix<C3b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_Array(ref Matrix<C3us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_Array(ref Matrix<C3ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_Array(ref Matrix<C3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_Array(ref Matrix<C3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_Array(ref Matrix<C4b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_Array(ref Matrix<C4us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_Array(ref Matrix<C4ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_Array(ref Matrix<C4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_Array(ref Matrix<C4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_Array(ref Matrix<Range1b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_Array(ref Matrix<Range1sb>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1sb_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_Array(ref Matrix<Range1s>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1s_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_Array(ref Matrix<Range1us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_Array(ref Matrix<Range1i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_Array(ref Matrix<Range1ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_Array(ref Matrix<Range1l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_Array(ref Matrix<Range1ul>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1ul_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_Array(ref Matrix<Range1f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_Array(ref Matrix<Range1d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_Array(ref Matrix<Box2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_Array(ref Matrix<Box2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_Array(ref Matrix<Box2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_Array(ref Matrix<Box2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_Array(ref Matrix<Box3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_Array(ref Matrix<Box3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_Array(ref Matrix<Box3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_Array(ref Matrix<Box3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_Array(ref Matrix<Euclidean3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Euclidean3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_Array(ref Matrix<Euclidean3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Euclidean3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_Array(ref Matrix<Rot2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Rot2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_Array(ref Matrix<Rot2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Rot2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_Array(ref Matrix<Rot3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Rot3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_Array(ref Matrix<Rot3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Rot3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_Array(ref Matrix<Scale3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Scale3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_Array(ref Matrix<Scale3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Scale3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_Array(ref Matrix<Shift3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Shift3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_Array(ref Matrix<Shift3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Shift3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_Array(ref Matrix<Trafo2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Trafo2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_Array(ref Matrix<Trafo2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Trafo2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_Array(ref Matrix<Trafo3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Trafo3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_Array(ref Matrix<Trafo3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Trafo3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_Array(ref Matrix<bool>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Bool_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_Array(ref Matrix<char>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Char_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_String_Array(ref Matrix<string>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_String_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_Array(ref Matrix<Type>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Type_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_Array(ref Matrix<Guid>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Guid_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_Array(ref Matrix<Symbol>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Symbol_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_Array(ref Matrix<Circle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Circle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_Array(ref Matrix<Line2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Line2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_Array(ref Matrix<Line3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Line3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_Array(ref Matrix<Plane2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Plane2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_Array(ref Matrix<Plane3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Plane3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_Array(ref Matrix<PlaneWithPoint3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_PlaneWithPoint3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_Array(ref Matrix<Quad2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Quad2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_Array(ref Matrix<Quad3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Quad3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_Array(ref Matrix<Ray2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Ray2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_Array(ref Matrix<Ray3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Ray3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_Array(ref Matrix<Sphere3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Sphere3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_Array(ref Matrix<Triangle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Triangle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_Array(ref Matrix<Triangle3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Triangle3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_Array(ref Matrix<Circle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Circle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_Array(ref Matrix<Line2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Line2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_Array(ref Matrix<Line3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Line3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_Array(ref Matrix<Plane2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Plane2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_Array(ref Matrix<Plane3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Plane3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_Array(ref Matrix<PlaneWithPoint3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_PlaneWithPoint3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_Array(ref Matrix<Quad2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Quad2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_Array(ref Matrix<Quad3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Quad3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_Array(ref Matrix<Ray2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Ray2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_Array(ref Matrix<Ray3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Ray3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_Array(ref Matrix<Sphere3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Sphere3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_Array(ref Matrix<Triangle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Triangle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_Array(ref Matrix<Triangle3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Triangle3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_Array(ref Volume<byte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Byte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_Array(ref Volume<sbyte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_SByte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Short_Array(ref Volume<short>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Short_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_Array(ref Volume<ushort>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_UShort_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Int_Array(ref Volume<int>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Int_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_Array(ref Volume<uint>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_UInt_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Long_Array(ref Volume<long>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Long_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_Array(ref Volume<ulong>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_ULong_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Float_Array(ref Volume<float>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Float_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Double_Array(ref Volume<double>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Double_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_Array(ref Volume<Fraction>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Fraction_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_Array(ref Volume<V2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_Array(ref Volume<V2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_Array(ref Volume<V2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_Array(ref Volume<V2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_Array(ref Volume<V3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_Array(ref Volume<V3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_Array(ref Volume<V3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_Array(ref Volume<V3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_Array(ref Volume<V4i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V4i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_Array(ref Volume<V4l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V4l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_Array(ref Volume<V4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_Array(ref Volume<V4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_Array(ref Volume<M22i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M22i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_Array(ref Volume<M22l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M22l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_Array(ref Volume<M22f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M22f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_Array(ref Volume<M22d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M22d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_Array(ref Volume<M23i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M23i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_Array(ref Volume<M23l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M23l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_Array(ref Volume<M23f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M23f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_Array(ref Volume<M23d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M23d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_Array(ref Volume<M33i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M33i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_Array(ref Volume<M33l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M33l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_Array(ref Volume<M33f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M33f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_Array(ref Volume<M33d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M33d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_Array(ref Volume<M34i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M34i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_Array(ref Volume<M34l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M34l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_Array(ref Volume<M34f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M34f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_Array(ref Volume<M34d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M34d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_Array(ref Volume<M44i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M44i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_Array(ref Volume<M44l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M44l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_Array(ref Volume<M44f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M44f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_Array(ref Volume<M44d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M44d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_Array(ref Volume<C3b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_Array(ref Volume<C3us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_Array(ref Volume<C3ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_Array(ref Volume<C3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_Array(ref Volume<C3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_Array(ref Volume<C4b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_Array(ref Volume<C4us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_Array(ref Volume<C4ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_Array(ref Volume<C4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_Array(ref Volume<C4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_Array(ref Volume<Range1b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_Array(ref Volume<Range1sb>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1sb_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_Array(ref Volume<Range1s>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1s_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_Array(ref Volume<Range1us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_Array(ref Volume<Range1i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_Array(ref Volume<Range1ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_Array(ref Volume<Range1l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_Array(ref Volume<Range1ul>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1ul_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_Array(ref Volume<Range1f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_Array(ref Volume<Range1d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_Array(ref Volume<Box2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_Array(ref Volume<Box2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_Array(ref Volume<Box2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_Array(ref Volume<Box2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_Array(ref Volume<Box3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_Array(ref Volume<Box3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_Array(ref Volume<Box3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_Array(ref Volume<Box3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_Array(ref Volume<Euclidean3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Euclidean3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_Array(ref Volume<Euclidean3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Euclidean3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_Array(ref Volume<Rot2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Rot2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_Array(ref Volume<Rot2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Rot2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_Array(ref Volume<Rot3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Rot3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_Array(ref Volume<Rot3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Rot3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_Array(ref Volume<Scale3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Scale3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_Array(ref Volume<Scale3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Scale3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_Array(ref Volume<Shift3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Shift3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_Array(ref Volume<Shift3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Shift3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_Array(ref Volume<Trafo2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Trafo2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_Array(ref Volume<Trafo2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Trafo2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_Array(ref Volume<Trafo3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Trafo3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_Array(ref Volume<Trafo3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Trafo3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_Array(ref Volume<bool>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Bool_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Char_Array(ref Volume<char>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Char_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_String_Array(ref Volume<string>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_String_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Type_Array(ref Volume<Type>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Type_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_Array(ref Volume<Guid>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Guid_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_Array(ref Volume<Symbol>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Symbol_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_Array(ref Volume<Circle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Circle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_Array(ref Volume<Line2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Line2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_Array(ref Volume<Line3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Line3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_Array(ref Volume<Plane2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Plane2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_Array(ref Volume<Plane3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Plane3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_Array(ref Volume<PlaneWithPoint3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_PlaneWithPoint3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_Array(ref Volume<Quad2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Quad2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_Array(ref Volume<Quad3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Quad3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_Array(ref Volume<Ray2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Ray2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_Array(ref Volume<Ray3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Ray3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_Array(ref Volume<Sphere3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Sphere3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_Array(ref Volume<Triangle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Triangle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_Array(ref Volume<Triangle3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Triangle3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_Array(ref Volume<Circle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Circle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_Array(ref Volume<Line2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Line2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_Array(ref Volume<Line3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Line3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_Array(ref Volume<Plane2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Plane2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_Array(ref Volume<Plane3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Plane3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_Array(ref Volume<PlaneWithPoint3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_PlaneWithPoint3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_Array(ref Volume<Quad2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Quad2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_Array(ref Volume<Quad3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Quad3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_Array(ref Volume<Ray2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Ray2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_Array(ref Volume<Ray3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Ray3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_Array(ref Volume<Sphere3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Sphere3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_Array(ref Volume<Triangle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Triangle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_Array(ref Volume<Triangle3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Triangle3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_Array(ref Tensor<byte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Byte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_Array(ref Tensor<sbyte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_SByte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Short_Array(ref Tensor<short>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Short_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_Array(ref Tensor<ushort>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_UShort_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Int_Array(ref Tensor<int>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Int_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_Array(ref Tensor<uint>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_UInt_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Long_Array(ref Tensor<long>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Long_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_Array(ref Tensor<ulong>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_ULong_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Float_Array(ref Tensor<float>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Float_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Double_Array(ref Tensor<double>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Double_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_Array(ref Tensor<Fraction>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Fraction_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_Array(ref Tensor<V2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_Array(ref Tensor<V2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_Array(ref Tensor<V2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_Array(ref Tensor<V2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_Array(ref Tensor<V3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_Array(ref Tensor<V3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_Array(ref Tensor<V3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_Array(ref Tensor<V3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_Array(ref Tensor<V4i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V4i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_Array(ref Tensor<V4l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V4l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_Array(ref Tensor<V4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_Array(ref Tensor<V4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_Array(ref Tensor<M22i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M22i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_Array(ref Tensor<M22l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M22l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_Array(ref Tensor<M22f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M22f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_Array(ref Tensor<M22d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M22d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_Array(ref Tensor<M23i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M23i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_Array(ref Tensor<M23l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M23l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_Array(ref Tensor<M23f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M23f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_Array(ref Tensor<M23d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M23d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_Array(ref Tensor<M33i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M33i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_Array(ref Tensor<M33l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M33l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_Array(ref Tensor<M33f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M33f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_Array(ref Tensor<M33d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M33d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_Array(ref Tensor<M34i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M34i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_Array(ref Tensor<M34l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M34l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_Array(ref Tensor<M34f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M34f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_Array(ref Tensor<M34d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M34d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_Array(ref Tensor<M44i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M44i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_Array(ref Tensor<M44l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M44l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_Array(ref Tensor<M44f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M44f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_Array(ref Tensor<M44d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M44d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_Array(ref Tensor<C3b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_Array(ref Tensor<C3us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_Array(ref Tensor<C3ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_Array(ref Tensor<C3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_Array(ref Tensor<C3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_Array(ref Tensor<C4b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_Array(ref Tensor<C4us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_Array(ref Tensor<C4ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_Array(ref Tensor<C4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_Array(ref Tensor<C4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_Array(ref Tensor<Range1b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_Array(ref Tensor<Range1sb>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1sb_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_Array(ref Tensor<Range1s>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1s_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_Array(ref Tensor<Range1us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_Array(ref Tensor<Range1i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_Array(ref Tensor<Range1ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_Array(ref Tensor<Range1l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_Array(ref Tensor<Range1ul>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1ul_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_Array(ref Tensor<Range1f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_Array(ref Tensor<Range1d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_Array(ref Tensor<Box2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_Array(ref Tensor<Box2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_Array(ref Tensor<Box2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_Array(ref Tensor<Box2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_Array(ref Tensor<Box3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_Array(ref Tensor<Box3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_Array(ref Tensor<Box3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_Array(ref Tensor<Box3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_Array(ref Tensor<Euclidean3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Euclidean3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_Array(ref Tensor<Euclidean3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Euclidean3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_Array(ref Tensor<Rot2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Rot2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_Array(ref Tensor<Rot2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Rot2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_Array(ref Tensor<Rot3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Rot3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_Array(ref Tensor<Rot3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Rot3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_Array(ref Tensor<Scale3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Scale3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_Array(ref Tensor<Scale3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Scale3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_Array(ref Tensor<Shift3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Shift3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_Array(ref Tensor<Shift3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Shift3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_Array(ref Tensor<Trafo2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Trafo2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_Array(ref Tensor<Trafo2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Trafo2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_Array(ref Tensor<Trafo3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Trafo3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_Array(ref Tensor<Trafo3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Trafo3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_Array(ref Tensor<bool>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Bool_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Char_Array(ref Tensor<char>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Char_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_String_Array(ref Tensor<string>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_String_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Type_Array(ref Tensor<Type>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Type_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_Array(ref Tensor<Guid>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Guid_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_Array(ref Tensor<Symbol>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Symbol_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_Array(ref Tensor<Circle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Circle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_Array(ref Tensor<Line2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Line2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_Array(ref Tensor<Line3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Line3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_Array(ref Tensor<Plane2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Plane2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_Array(ref Tensor<Plane3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Plane3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_Array(ref Tensor<PlaneWithPoint3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_PlaneWithPoint3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_Array(ref Tensor<Quad2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Quad2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_Array(ref Tensor<Quad3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Quad3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_Array(ref Tensor<Ray2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Ray2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_Array(ref Tensor<Ray3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Ray3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_Array(ref Tensor<Sphere3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Sphere3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_Array(ref Tensor<Triangle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Triangle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_Array(ref Tensor<Triangle3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Triangle3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_Array(ref Tensor<Circle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Circle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_Array(ref Tensor<Line2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Line2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_Array(ref Tensor<Line3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Line3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_Array(ref Tensor<Plane2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Plane2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_Array(ref Tensor<Plane3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Plane3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_Array(ref Tensor<PlaneWithPoint3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_PlaneWithPoint3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_Array(ref Tensor<Quad2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Quad2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_Array(ref Tensor<Quad3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Quad3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_Array(ref Tensor<Ray2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Ray2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_Array(ref Tensor<Ray3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Ray3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_Array(ref Tensor<Sphere3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Sphere3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_Array(ref Tensor<Triangle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Triangle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_Array(ref Tensor<Triangle3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Triangle3f_(ref value[i]);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArray2d(ref byte[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeByteArray3d(ref byte[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeSByteArray2d(ref sbyte[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeSByteArray3d(ref sbyte[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeShortArray2d(ref short[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeShortArray3d(ref short[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeUShortArray2d(ref ushort[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeUShortArray3d(ref ushort[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeIntArray2d(ref int[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeIntArray3d(ref int[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeUIntArray2d(ref uint[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeUIntArray3d(ref uint[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeLongArray2d(ref long[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeLongArray3d(ref long[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeULongArray2d(ref ulong[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeULongArray3d(ref ulong[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeFloatArray2d(ref float[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeFloatArray3d(ref float[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeDoubleArray2d(ref double[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeDoubleArray3d(ref double[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeFractionArray2d(ref Fraction[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeFractionArray3d(ref Fraction[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV2iArray2d(ref V2i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV2iArray3d(ref V2i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV2lArray2d(ref V2l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV2lArray3d(ref V2l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV2fArray2d(ref V2f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV2fArray3d(ref V2f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV2dArray2d(ref V2d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV2dArray3d(ref V2d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV3iArray2d(ref V3i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV3iArray3d(ref V3i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV3lArray2d(ref V3l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV3lArray3d(ref V3l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV3fArray2d(ref V3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV3fArray3d(ref V3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV3dArray2d(ref V3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV3dArray3d(ref V3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV4iArray2d(ref V4i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV4iArray3d(ref V4i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV4lArray2d(ref V4l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV4lArray3d(ref V4l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV4fArray2d(ref V4f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV4fArray3d(ref V4f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV4dArray2d(ref V4d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV4dArray3d(ref V4d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM22iArray2d(ref M22i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM22iArray3d(ref M22i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM22lArray2d(ref M22l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM22lArray3d(ref M22l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM22fArray2d(ref M22f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM22fArray3d(ref M22f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM22dArray2d(ref M22d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM22dArray3d(ref M22d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM23iArray2d(ref M23i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM23iArray3d(ref M23i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM23lArray2d(ref M23l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM23lArray3d(ref M23l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM23fArray2d(ref M23f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM23fArray3d(ref M23f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM23dArray2d(ref M23d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM23dArray3d(ref M23d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM33iArray2d(ref M33i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM33iArray3d(ref M33i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM33lArray2d(ref M33l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM33lArray3d(ref M33l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM33fArray2d(ref M33f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM33fArray3d(ref M33f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM33dArray2d(ref M33d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM33dArray3d(ref M33d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM34iArray2d(ref M34i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM34iArray3d(ref M34i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM34lArray2d(ref M34l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM34lArray3d(ref M34l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM34fArray2d(ref M34f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM34fArray3d(ref M34f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM34dArray2d(ref M34d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM34dArray3d(ref M34d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM44iArray2d(ref M44i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM44iArray3d(ref M44i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM44lArray2d(ref M44l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM44lArray3d(ref M44l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM44fArray2d(ref M44f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM44fArray3d(ref M44f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM44dArray2d(ref M44d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM44dArray3d(ref M44d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3bArray2d(ref C3b[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3bArray3d(ref C3b[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3usArray2d(ref C3us[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3usArray3d(ref C3us[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3uiArray2d(ref C3ui[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3uiArray3d(ref C3ui[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3fArray2d(ref C3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3fArray3d(ref C3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3dArray2d(ref C3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3dArray3d(ref C3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4bArray2d(ref C4b[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4bArray3d(ref C4b[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4usArray2d(ref C4us[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4usArray3d(ref C4us[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4uiArray2d(ref C4ui[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4uiArray3d(ref C4ui[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4fArray2d(ref C4f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4fArray3d(ref C4f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4dArray2d(ref C4d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4dArray3d(ref C4d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1bArray2d(ref Range1b[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1bArray3d(ref Range1b[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1sbArray2d(ref Range1sb[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1sbArray3d(ref Range1sb[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1sArray2d(ref Range1s[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1sArray3d(ref Range1s[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1usArray2d(ref Range1us[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1usArray3d(ref Range1us[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1iArray2d(ref Range1i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1iArray3d(ref Range1i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1uiArray2d(ref Range1ui[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1uiArray3d(ref Range1ui[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1lArray2d(ref Range1l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1lArray3d(ref Range1l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1ulArray2d(ref Range1ul[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1ulArray3d(ref Range1ul[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1fArray2d(ref Range1f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1fArray3d(ref Range1f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1dArray2d(ref Range1d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1dArray3d(ref Range1d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox2iArray2d(ref Box2i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox2iArray3d(ref Box2i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox2lArray2d(ref Box2l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox2lArray3d(ref Box2l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox2fArray2d(ref Box2f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox2fArray3d(ref Box2f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox2dArray2d(ref Box2d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox2dArray3d(ref Box2d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox3iArray2d(ref Box3i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox3iArray3d(ref Box3i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox3lArray2d(ref Box3l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox3lArray3d(ref Box3l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox3fArray2d(ref Box3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox3fArray3d(ref Box3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox3dArray2d(ref Box3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox3dArray3d(ref Box3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeEuclidean3fArray2d(ref Euclidean3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeEuclidean3fArray3d(ref Euclidean3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeEuclidean3dArray2d(ref Euclidean3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeEuclidean3dArray3d(ref Euclidean3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRot2fArray2d(ref Rot2f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRot2fArray3d(ref Rot2f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRot2dArray2d(ref Rot2d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRot2dArray3d(ref Rot2d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRot3fArray2d(ref Rot3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRot3fArray3d(ref Rot3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRot3dArray2d(ref Rot3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRot3dArray3d(ref Rot3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeScale3fArray2d(ref Scale3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeScale3fArray3d(ref Scale3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeScale3dArray2d(ref Scale3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeScale3dArray3d(ref Scale3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeShift3fArray2d(ref Shift3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeShift3fArray3d(ref Shift3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeShift3dArray2d(ref Shift3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeShift3dArray3d(ref Shift3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeTrafo2fArray2d(ref Trafo2f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeTrafo2fArray3d(ref Trafo2f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeTrafo2dArray2d(ref Trafo2d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeTrafo2dArray3d(ref Trafo2d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeTrafo3fArray2d(ref Trafo3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeTrafo3fArray3d(ref Trafo3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeTrafo3dArray2d(ref Trafo3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeTrafo3dArray3d(ref Trafo3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_reader.ReadArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Jagged Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArrayArray(ref byte[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeByteArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeByteArrayArrayArray(ref byte[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeByteArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeSByteArrayArray(ref sbyte[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSByteArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeSByteArrayArrayArray(ref sbyte[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSByteArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShortArrayArray(ref short[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShortArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShortArrayArrayArray(ref short[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShortArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeUShortArrayArray(ref ushort[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeUShortArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeUShortArrayArrayArray(ref ushort[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeUShortArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeIntArrayArray(ref int[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeIntArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeIntArrayArrayArray(ref int[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeIntArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeUIntArrayArray(ref uint[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeUIntArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeUIntArrayArrayArray(ref uint[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeUIntArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeLongArrayArray(ref long[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLongArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeLongArrayArrayArray(ref long[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLongArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeULongArrayArray(ref ulong[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeULongArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeULongArrayArrayArray(ref ulong[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeULongArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeFloatArrayArray(ref float[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeFloatArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeFloatArrayArrayArray(ref float[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeFloatArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeDoubleArrayArray(ref double[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeDoubleArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeDoubleArrayArrayArray(ref double[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeDoubleArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeFractionArrayArray(ref Fraction[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeFractionArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeFractionArrayArrayArray(ref Fraction[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeFractionArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2iArrayArray(ref V2i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2iArrayArrayArray(ref V2i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2lArrayArray(ref V2l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2lArrayArrayArray(ref V2l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2fArrayArray(ref V2f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2fArrayArrayArray(ref V2f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2dArrayArray(ref V2d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2dArrayArrayArray(ref V2d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3iArrayArray(ref V3i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3iArrayArrayArray(ref V3i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3lArrayArray(ref V3l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3lArrayArrayArray(ref V3l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3fArrayArray(ref V3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3fArrayArrayArray(ref V3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3dArrayArray(ref V3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3dArrayArrayArray(ref V3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4iArrayArray(ref V4i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4iArrayArrayArray(ref V4i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4lArrayArray(ref V4l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4lArrayArrayArray(ref V4l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4fArrayArray(ref V4f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4fArrayArrayArray(ref V4f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4dArrayArray(ref V4d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4dArrayArrayArray(ref V4d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22iArrayArray(ref M22i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22iArrayArrayArray(ref M22i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22lArrayArray(ref M22l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22lArrayArrayArray(ref M22l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22fArrayArray(ref M22f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22fArrayArrayArray(ref M22f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22dArrayArray(ref M22d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22dArrayArrayArray(ref M22d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23iArrayArray(ref M23i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23iArrayArrayArray(ref M23i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23lArrayArray(ref M23l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23lArrayArrayArray(ref M23l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23fArrayArray(ref M23f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23fArrayArrayArray(ref M23f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23dArrayArray(ref M23d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23dArrayArrayArray(ref M23d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33iArrayArray(ref M33i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33iArrayArrayArray(ref M33i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33lArrayArray(ref M33l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33lArrayArrayArray(ref M33l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33fArrayArray(ref M33f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33fArrayArrayArray(ref M33f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33dArrayArray(ref M33d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33dArrayArrayArray(ref M33d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34iArrayArray(ref M34i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34iArrayArrayArray(ref M34i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34lArrayArray(ref M34l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34lArrayArrayArray(ref M34l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34fArrayArray(ref M34f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34fArrayArrayArray(ref M34f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34dArrayArray(ref M34d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34dArrayArrayArray(ref M34d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44iArrayArray(ref M44i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44iArrayArrayArray(ref M44i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44lArrayArray(ref M44l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44lArrayArrayArray(ref M44l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44fArrayArray(ref M44f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44fArrayArrayArray(ref M44f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44dArrayArray(ref M44d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44dArrayArrayArray(ref M44d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3bArrayArray(ref C3b[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3bArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3bArrayArrayArray(ref C3b[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3bArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3usArrayArray(ref C3us[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3usArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3usArrayArrayArray(ref C3us[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3usArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3uiArrayArray(ref C3ui[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3uiArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3uiArrayArrayArray(ref C3ui[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3uiArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3fArrayArray(ref C3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3fArrayArrayArray(ref C3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3dArrayArray(ref C3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3dArrayArrayArray(ref C3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4bArrayArray(ref C4b[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4bArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4bArrayArrayArray(ref C4b[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4bArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4usArrayArray(ref C4us[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4usArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4usArrayArrayArray(ref C4us[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4usArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4uiArrayArray(ref C4ui[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4uiArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4uiArrayArrayArray(ref C4ui[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4uiArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4fArrayArray(ref C4f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4fArrayArrayArray(ref C4f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4dArrayArray(ref C4d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4dArrayArrayArray(ref C4d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1bArrayArray(ref Range1b[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1bArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1bArrayArrayArray(ref Range1b[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1bArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1sbArrayArray(ref Range1sb[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1sbArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1sbArrayArrayArray(ref Range1sb[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1sbArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1sArrayArray(ref Range1s[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1sArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1sArrayArrayArray(ref Range1s[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1sArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1usArrayArray(ref Range1us[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1usArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1usArrayArrayArray(ref Range1us[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1usArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1iArrayArray(ref Range1i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1iArrayArrayArray(ref Range1i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1uiArrayArray(ref Range1ui[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1uiArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1uiArrayArrayArray(ref Range1ui[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1uiArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1lArrayArray(ref Range1l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1lArrayArrayArray(ref Range1l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1ulArrayArray(ref Range1ul[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1ulArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1ulArrayArrayArray(ref Range1ul[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1ulArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1fArrayArray(ref Range1f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1fArrayArrayArray(ref Range1f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1dArrayArray(ref Range1d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1dArrayArrayArray(ref Range1d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2iArrayArray(ref Box2i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2iArrayArrayArray(ref Box2i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2lArrayArray(ref Box2l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2lArrayArrayArray(ref Box2l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2fArrayArray(ref Box2f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2fArrayArrayArray(ref Box2f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2dArrayArray(ref Box2d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2dArrayArrayArray(ref Box2d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3iArrayArray(ref Box3i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3iArrayArrayArray(ref Box3i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3lArrayArray(ref Box3l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3lArrayArrayArray(ref Box3l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3fArrayArray(ref Box3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3fArrayArrayArray(ref Box3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3dArrayArray(ref Box3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3dArrayArrayArray(ref Box3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3fArrayArray(ref Euclidean3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3fArrayArrayArray(ref Euclidean3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3dArrayArray(ref Euclidean3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3dArrayArrayArray(ref Euclidean3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2fArrayArray(ref Rot2f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2fArrayArrayArray(ref Rot2f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2dArrayArray(ref Rot2d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2dArrayArrayArray(ref Rot2d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3fArrayArray(ref Rot3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3fArrayArrayArray(ref Rot3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3dArrayArray(ref Rot3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3dArrayArrayArray(ref Rot3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3fArrayArray(ref Scale3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3fArrayArrayArray(ref Scale3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3dArrayArray(ref Scale3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3dArrayArrayArray(ref Scale3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3fArrayArray(ref Shift3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3fArrayArrayArray(ref Shift3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3dArrayArray(ref Shift3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3dArrayArrayArray(ref Shift3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2fArrayArray(ref Trafo2f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2fArrayArrayArray(ref Trafo2f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2dArrayArray(ref Trafo2d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2dArrayArrayArray(ref Trafo2d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3fArrayArray(ref Trafo3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3fArrayArrayArray(ref Trafo3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3dArrayArray(ref Trafo3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3dArrayArrayArray(ref Trafo3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Lists\r\n\r\n        public void CodeList_of_V2i_(ref List<V2i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V2ui_(ref List<V2ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V2l_(ref List<V2l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V2f_(ref List<V2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V2d_(ref List<V2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3i_(ref List<V3i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3ui_(ref List<V3ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3l_(ref List<V3l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3f_(ref List<V3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3d_(ref List<V3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4i_(ref List<V4i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4ui_(ref List<V4ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4l_(ref List<V4l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4f_(ref List<V4f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4d_(ref List<V4d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M22i_(ref List<M22i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M22l_(ref List<M22l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M22f_(ref List<M22f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M22d_(ref List<M22d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M23i_(ref List<M23i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M23l_(ref List<M23l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M23f_(ref List<M23f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M23d_(ref List<M23d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M33i_(ref List<M33i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M33l_(ref List<M33l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M33f_(ref List<M33f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M33d_(ref List<M33d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M34i_(ref List<M34i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M34l_(ref List<M34l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M34f_(ref List<M34f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M34d_(ref List<M34d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M44i_(ref List<M44i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M44l_(ref List<M44l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M44f_(ref List<M44f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M44d_(ref List<M44d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1b_(ref List<Range1b> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1sb_(ref List<Range1sb> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1s_(ref List<Range1s> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1us_(ref List<Range1us> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1i_(ref List<Range1i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1ui_(ref List<Range1ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1l_(ref List<Range1l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1ul_(ref List<Range1ul> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1f_(ref List<Range1f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1d_(ref List<Range1d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box2i_(ref List<Box2i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box2l_(ref List<Box2l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box2f_(ref List<Box2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box2d_(ref List<Box2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box3i_(ref List<Box3i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box3l_(ref List<Box3l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box3f_(ref List<Box3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box3d_(ref List<Box3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3b_(ref List<C3b> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3us_(ref List<C3us> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3ui_(ref List<C3ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3f_(ref List<C3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3d_(ref List<C3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4b_(ref List<C4b> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4us_(ref List<C4us> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4ui_(ref List<C4ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4f_(ref List<C4f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4d_(ref List<C4d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_reader.ReadList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Euclidean3f_(ref List<Euclidean3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Euclidean3f); CodeEuclidean3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Euclidean3d_(ref List<Euclidean3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Euclidean3d); CodeEuclidean3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Rot2f_(ref List<Rot2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Rot2f); CodeRot2f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Rot2d_(ref List<Rot2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Rot2d); CodeRot2d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Rot3f_(ref List<Rot3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Rot3f); CodeRot3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Rot3d_(ref List<Rot3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Rot3d); CodeRot3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Scale3f_(ref List<Scale3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Scale3f); CodeScale3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Scale3d_(ref List<Scale3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Scale3d); CodeScale3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Shift3f_(ref List<Shift3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Shift3f); CodeShift3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Shift3d_(ref List<Shift3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Shift3d); CodeShift3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Trafo2f_(ref List<Trafo2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Trafo2f); CodeTrafo2f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Trafo2d_(ref List<Trafo2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Trafo2d); CodeTrafo2d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Trafo3f_(ref List<Trafo3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Trafo3f); CodeTrafo3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Trafo3d_(ref List<Trafo3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Trafo3d); CodeTrafo3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Circle2d_(ref List<Circle2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Circle2d); CodeCircle2d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Line2d_(ref List<Line2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Line2d); CodeLine2d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Line3d_(ref List<Line3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Line3d); CodeLine3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Plane2d_(ref List<Plane2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Plane2d); CodePlane2d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Plane3d_(ref List<Plane3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Plane3d); CodePlane3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_PlaneWithPoint3d_(ref List<PlaneWithPoint3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(PlaneWithPoint3d); CodePlaneWithPoint3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Quad2d_(ref List<Quad2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Quad2d); CodeQuad2d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Quad3d_(ref List<Quad3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Quad3d); CodeQuad3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Ray2d_(ref List<Ray2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Ray2d); CodeRay2d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Ray3d_(ref List<Ray3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Ray3d); CodeRay3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Sphere3d_(ref List<Sphere3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Sphere3d); CodeSphere3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Triangle2d_(ref List<Triangle2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Triangle2d); CodeTriangle2d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Triangle3d_(ref List<Triangle3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Triangle3d); CodeTriangle3d(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Circle2f_(ref List<Circle2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Circle2f); CodeCircle2f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Line2f_(ref List<Line2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Line2f); CodeLine2f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Line3f_(ref List<Line3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Line3f); CodeLine3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Plane2f_(ref List<Plane2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Plane2f); CodePlane2f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Plane3f_(ref List<Plane3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Plane3f); CodePlane3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_PlaneWithPoint3f_(ref List<PlaneWithPoint3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(PlaneWithPoint3f); CodePlaneWithPoint3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Quad2f_(ref List<Quad2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Quad2f); CodeQuad2f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Quad3f_(ref List<Quad3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Quad3f); CodeQuad3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Ray2f_(ref List<Ray2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Ray2f); CodeRay2f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Ray3f_(ref List<Ray3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Ray3f); CodeRay3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Sphere3f_(ref List<Sphere3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Sphere3f); CodeSphere3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Triangle2f_(ref List<Triangle2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Triangle2f); CodeTriangle2f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Triangle3f_(ref List<Triangle3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Triangle3f); CodeTriangle3f(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Byte__(ref List<Vector<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<byte>); CodeVector_of_Byte_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_SByte__(ref List<Vector<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<sbyte>); CodeVector_of_SByte_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Short__(ref List<Vector<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<short>); CodeVector_of_Short_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_UShort__(ref List<Vector<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<ushort>); CodeVector_of_UShort_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Int__(ref List<Vector<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<int>); CodeVector_of_Int_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_UInt__(ref List<Vector<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<uint>); CodeVector_of_UInt_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Long__(ref List<Vector<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<long>); CodeVector_of_Long_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_ULong__(ref List<Vector<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<ulong>); CodeVector_of_ULong_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Float__(ref List<Vector<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<float>); CodeVector_of_Float_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Double__(ref List<Vector<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<double>); CodeVector_of_Double_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Fraction__(ref List<Vector<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Fraction>); CodeVector_of_Fraction_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2i__(ref List<Vector<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V2i>); CodeVector_of_V2i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2l__(ref List<Vector<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V2l>); CodeVector_of_V2l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2f__(ref List<Vector<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V2f>); CodeVector_of_V2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2d__(ref List<Vector<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V2d>); CodeVector_of_V2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3i__(ref List<Vector<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V3i>); CodeVector_of_V3i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3l__(ref List<Vector<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V3l>); CodeVector_of_V3l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3f__(ref List<Vector<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V3f>); CodeVector_of_V3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3d__(ref List<Vector<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V3d>); CodeVector_of_V3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4i__(ref List<Vector<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V4i>); CodeVector_of_V4i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4l__(ref List<Vector<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V4l>); CodeVector_of_V4l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4f__(ref List<Vector<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V4f>); CodeVector_of_V4f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4d__(ref List<Vector<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<V4d>); CodeVector_of_V4d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22i__(ref List<Vector<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M22i>); CodeVector_of_M22i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22l__(ref List<Vector<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M22l>); CodeVector_of_M22l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22f__(ref List<Vector<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M22f>); CodeVector_of_M22f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22d__(ref List<Vector<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M22d>); CodeVector_of_M22d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23i__(ref List<Vector<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M23i>); CodeVector_of_M23i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23l__(ref List<Vector<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M23l>); CodeVector_of_M23l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23f__(ref List<Vector<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M23f>); CodeVector_of_M23f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23d__(ref List<Vector<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M23d>); CodeVector_of_M23d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33i__(ref List<Vector<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M33i>); CodeVector_of_M33i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33l__(ref List<Vector<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M33l>); CodeVector_of_M33l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33f__(ref List<Vector<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M33f>); CodeVector_of_M33f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33d__(ref List<Vector<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M33d>); CodeVector_of_M33d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34i__(ref List<Vector<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M34i>); CodeVector_of_M34i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34l__(ref List<Vector<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M34l>); CodeVector_of_M34l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34f__(ref List<Vector<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M34f>); CodeVector_of_M34f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34d__(ref List<Vector<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M34d>); CodeVector_of_M34d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44i__(ref List<Vector<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M44i>); CodeVector_of_M44i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44l__(ref List<Vector<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M44l>); CodeVector_of_M44l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44f__(ref List<Vector<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M44f>); CodeVector_of_M44f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44d__(ref List<Vector<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<M44d>); CodeVector_of_M44d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3b__(ref List<Vector<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C3b>); CodeVector_of_C3b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3us__(ref List<Vector<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C3us>); CodeVector_of_C3us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3ui__(ref List<Vector<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C3ui>); CodeVector_of_C3ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3f__(ref List<Vector<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C3f>); CodeVector_of_C3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3d__(ref List<Vector<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C3d>); CodeVector_of_C3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4b__(ref List<Vector<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C4b>); CodeVector_of_C4b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4us__(ref List<Vector<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C4us>); CodeVector_of_C4us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4ui__(ref List<Vector<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C4ui>); CodeVector_of_C4ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4f__(ref List<Vector<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C4f>); CodeVector_of_C4f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4d__(ref List<Vector<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<C4d>); CodeVector_of_C4d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1b__(ref List<Vector<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1b>); CodeVector_of_Range1b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1sb__(ref List<Vector<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1sb>); CodeVector_of_Range1sb_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1s__(ref List<Vector<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1s>); CodeVector_of_Range1s_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1us__(ref List<Vector<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1us>); CodeVector_of_Range1us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1i__(ref List<Vector<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1i>); CodeVector_of_Range1i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1ui__(ref List<Vector<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1ui>); CodeVector_of_Range1ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1l__(ref List<Vector<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1l>); CodeVector_of_Range1l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1ul__(ref List<Vector<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1ul>); CodeVector_of_Range1ul_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1f__(ref List<Vector<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1f>); CodeVector_of_Range1f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1d__(ref List<Vector<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Range1d>); CodeVector_of_Range1d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2i__(ref List<Vector<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Box2i>); CodeVector_of_Box2i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2l__(ref List<Vector<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Box2l>); CodeVector_of_Box2l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2f__(ref List<Vector<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Box2f>); CodeVector_of_Box2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2d__(ref List<Vector<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Box2d>); CodeVector_of_Box2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3i__(ref List<Vector<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Box3i>); CodeVector_of_Box3i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3l__(ref List<Vector<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Box3l>); CodeVector_of_Box3l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3f__(ref List<Vector<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Box3f>); CodeVector_of_Box3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3d__(ref List<Vector<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Box3d>); CodeVector_of_Box3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Euclidean3f__(ref List<Vector<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Euclidean3f>); CodeVector_of_Euclidean3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Euclidean3d__(ref List<Vector<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Euclidean3d>); CodeVector_of_Euclidean3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot2f__(ref List<Vector<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Rot2f>); CodeVector_of_Rot2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot2d__(ref List<Vector<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Rot2d>); CodeVector_of_Rot2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot3f__(ref List<Vector<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Rot3f>); CodeVector_of_Rot3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot3d__(ref List<Vector<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Rot3d>); CodeVector_of_Rot3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Scale3f__(ref List<Vector<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Scale3f>); CodeVector_of_Scale3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Scale3d__(ref List<Vector<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Scale3d>); CodeVector_of_Scale3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Shift3f__(ref List<Vector<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Shift3f>); CodeVector_of_Shift3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Shift3d__(ref List<Vector<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Shift3d>); CodeVector_of_Shift3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo2f__(ref List<Vector<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Trafo2f>); CodeVector_of_Trafo2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo2d__(ref List<Vector<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Trafo2d>); CodeVector_of_Trafo2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo3f__(ref List<Vector<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Trafo3f>); CodeVector_of_Trafo3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo3d__(ref List<Vector<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Trafo3d>); CodeVector_of_Trafo3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Bool__(ref List<Vector<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<bool>); CodeVector_of_Bool_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Char__(ref List<Vector<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<char>); CodeVector_of_Char_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_String__(ref List<Vector<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<string>); CodeVector_of_String_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Type__(ref List<Vector<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Type>); CodeVector_of_Type_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Guid__(ref List<Vector<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Guid>); CodeVector_of_Guid_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Symbol__(ref List<Vector<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Symbol>); CodeVector_of_Symbol_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Circle2d__(ref List<Vector<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Circle2d>); CodeVector_of_Circle2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line2d__(ref List<Vector<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Line2d>); CodeVector_of_Line2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line3d__(ref List<Vector<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Line3d>); CodeVector_of_Line3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane2d__(ref List<Vector<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Plane2d>); CodeVector_of_Plane2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane3d__(ref List<Vector<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Plane3d>); CodeVector_of_Plane3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3d__(ref List<Vector<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<PlaneWithPoint3d>); CodeVector_of_PlaneWithPoint3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad2d__(ref List<Vector<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Quad2d>); CodeVector_of_Quad2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad3d__(ref List<Vector<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Quad3d>); CodeVector_of_Quad3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray2d__(ref List<Vector<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Ray2d>); CodeVector_of_Ray2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray3d__(ref List<Vector<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Ray3d>); CodeVector_of_Ray3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Sphere3d__(ref List<Vector<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Sphere3d>); CodeVector_of_Sphere3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle2d__(ref List<Vector<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Triangle2d>); CodeVector_of_Triangle2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle3d__(ref List<Vector<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Triangle3d>); CodeVector_of_Triangle3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Circle2f__(ref List<Vector<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Circle2f>); CodeVector_of_Circle2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line2f__(ref List<Vector<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Line2f>); CodeVector_of_Line2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line3f__(ref List<Vector<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Line3f>); CodeVector_of_Line3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane2f__(ref List<Vector<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Plane2f>); CodeVector_of_Plane2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane3f__(ref List<Vector<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Plane3f>); CodeVector_of_Plane3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3f__(ref List<Vector<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<PlaneWithPoint3f>); CodeVector_of_PlaneWithPoint3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad2f__(ref List<Vector<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Quad2f>); CodeVector_of_Quad2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad3f__(ref List<Vector<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Quad3f>); CodeVector_of_Quad3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray2f__(ref List<Vector<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Ray2f>); CodeVector_of_Ray2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray3f__(ref List<Vector<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Ray3f>); CodeVector_of_Ray3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Sphere3f__(ref List<Vector<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Sphere3f>); CodeVector_of_Sphere3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle2f__(ref List<Vector<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Triangle2f>); CodeVector_of_Triangle2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle3f__(ref List<Vector<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Vector<Triangle3f>); CodeVector_of_Triangle3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Byte__(ref List<Matrix<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<byte>); CodeMatrix_of_Byte_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_SByte__(ref List<Matrix<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<sbyte>); CodeMatrix_of_SByte_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Short__(ref List<Matrix<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<short>); CodeMatrix_of_Short_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_UShort__(ref List<Matrix<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<ushort>); CodeMatrix_of_UShort_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Int__(ref List<Matrix<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<int>); CodeMatrix_of_Int_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_UInt__(ref List<Matrix<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<uint>); CodeMatrix_of_UInt_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Long__(ref List<Matrix<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<long>); CodeMatrix_of_Long_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_ULong__(ref List<Matrix<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<ulong>); CodeMatrix_of_ULong_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Float__(ref List<Matrix<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<float>); CodeMatrix_of_Float_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Double__(ref List<Matrix<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<double>); CodeMatrix_of_Double_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Fraction__(ref List<Matrix<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Fraction>); CodeMatrix_of_Fraction_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2i__(ref List<Matrix<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V2i>); CodeMatrix_of_V2i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2l__(ref List<Matrix<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V2l>); CodeMatrix_of_V2l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2f__(ref List<Matrix<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V2f>); CodeMatrix_of_V2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2d__(ref List<Matrix<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V2d>); CodeMatrix_of_V2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3i__(ref List<Matrix<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V3i>); CodeMatrix_of_V3i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3l__(ref List<Matrix<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V3l>); CodeMatrix_of_V3l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3f__(ref List<Matrix<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V3f>); CodeMatrix_of_V3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3d__(ref List<Matrix<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V3d>); CodeMatrix_of_V3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4i__(ref List<Matrix<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V4i>); CodeMatrix_of_V4i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4l__(ref List<Matrix<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V4l>); CodeMatrix_of_V4l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4f__(ref List<Matrix<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V4f>); CodeMatrix_of_V4f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4d__(ref List<Matrix<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<V4d>); CodeMatrix_of_V4d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22i__(ref List<Matrix<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M22i>); CodeMatrix_of_M22i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22l__(ref List<Matrix<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M22l>); CodeMatrix_of_M22l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22f__(ref List<Matrix<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M22f>); CodeMatrix_of_M22f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22d__(ref List<Matrix<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M22d>); CodeMatrix_of_M22d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23i__(ref List<Matrix<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M23i>); CodeMatrix_of_M23i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23l__(ref List<Matrix<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M23l>); CodeMatrix_of_M23l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23f__(ref List<Matrix<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M23f>); CodeMatrix_of_M23f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23d__(ref List<Matrix<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M23d>); CodeMatrix_of_M23d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33i__(ref List<Matrix<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M33i>); CodeMatrix_of_M33i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33l__(ref List<Matrix<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M33l>); CodeMatrix_of_M33l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33f__(ref List<Matrix<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M33f>); CodeMatrix_of_M33f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33d__(ref List<Matrix<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M33d>); CodeMatrix_of_M33d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34i__(ref List<Matrix<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M34i>); CodeMatrix_of_M34i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34l__(ref List<Matrix<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M34l>); CodeMatrix_of_M34l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34f__(ref List<Matrix<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M34f>); CodeMatrix_of_M34f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34d__(ref List<Matrix<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M34d>); CodeMatrix_of_M34d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44i__(ref List<Matrix<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M44i>); CodeMatrix_of_M44i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44l__(ref List<Matrix<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M44l>); CodeMatrix_of_M44l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44f__(ref List<Matrix<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M44f>); CodeMatrix_of_M44f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44d__(ref List<Matrix<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<M44d>); CodeMatrix_of_M44d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3b__(ref List<Matrix<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C3b>); CodeMatrix_of_C3b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3us__(ref List<Matrix<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C3us>); CodeMatrix_of_C3us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3ui__(ref List<Matrix<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C3ui>); CodeMatrix_of_C3ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3f__(ref List<Matrix<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C3f>); CodeMatrix_of_C3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3d__(ref List<Matrix<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C3d>); CodeMatrix_of_C3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4b__(ref List<Matrix<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C4b>); CodeMatrix_of_C4b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4us__(ref List<Matrix<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C4us>); CodeMatrix_of_C4us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4ui__(ref List<Matrix<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C4ui>); CodeMatrix_of_C4ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4f__(ref List<Matrix<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C4f>); CodeMatrix_of_C4f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4d__(ref List<Matrix<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<C4d>); CodeMatrix_of_C4d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1b__(ref List<Matrix<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1b>); CodeMatrix_of_Range1b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1sb__(ref List<Matrix<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1sb>); CodeMatrix_of_Range1sb_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1s__(ref List<Matrix<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1s>); CodeMatrix_of_Range1s_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1us__(ref List<Matrix<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1us>); CodeMatrix_of_Range1us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1i__(ref List<Matrix<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1i>); CodeMatrix_of_Range1i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1ui__(ref List<Matrix<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1ui>); CodeMatrix_of_Range1ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1l__(ref List<Matrix<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1l>); CodeMatrix_of_Range1l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1ul__(ref List<Matrix<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1ul>); CodeMatrix_of_Range1ul_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1f__(ref List<Matrix<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1f>); CodeMatrix_of_Range1f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1d__(ref List<Matrix<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Range1d>); CodeMatrix_of_Range1d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2i__(ref List<Matrix<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Box2i>); CodeMatrix_of_Box2i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2l__(ref List<Matrix<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Box2l>); CodeMatrix_of_Box2l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2f__(ref List<Matrix<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Box2f>); CodeMatrix_of_Box2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2d__(ref List<Matrix<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Box2d>); CodeMatrix_of_Box2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3i__(ref List<Matrix<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Box3i>); CodeMatrix_of_Box3i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3l__(ref List<Matrix<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Box3l>); CodeMatrix_of_Box3l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3f__(ref List<Matrix<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Box3f>); CodeMatrix_of_Box3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3d__(ref List<Matrix<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Box3d>); CodeMatrix_of_Box3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Euclidean3f__(ref List<Matrix<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Euclidean3f>); CodeMatrix_of_Euclidean3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Euclidean3d__(ref List<Matrix<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Euclidean3d>); CodeMatrix_of_Euclidean3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot2f__(ref List<Matrix<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Rot2f>); CodeMatrix_of_Rot2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot2d__(ref List<Matrix<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Rot2d>); CodeMatrix_of_Rot2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot3f__(ref List<Matrix<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Rot3f>); CodeMatrix_of_Rot3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot3d__(ref List<Matrix<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Rot3d>); CodeMatrix_of_Rot3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Scale3f__(ref List<Matrix<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Scale3f>); CodeMatrix_of_Scale3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Scale3d__(ref List<Matrix<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Scale3d>); CodeMatrix_of_Scale3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Shift3f__(ref List<Matrix<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Shift3f>); CodeMatrix_of_Shift3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Shift3d__(ref List<Matrix<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Shift3d>); CodeMatrix_of_Shift3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo2f__(ref List<Matrix<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Trafo2f>); CodeMatrix_of_Trafo2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo2d__(ref List<Matrix<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Trafo2d>); CodeMatrix_of_Trafo2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo3f__(ref List<Matrix<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Trafo3f>); CodeMatrix_of_Trafo3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo3d__(ref List<Matrix<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Trafo3d>); CodeMatrix_of_Trafo3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Bool__(ref List<Matrix<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<bool>); CodeMatrix_of_Bool_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Char__(ref List<Matrix<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<char>); CodeMatrix_of_Char_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_String__(ref List<Matrix<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<string>); CodeMatrix_of_String_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Type__(ref List<Matrix<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Type>); CodeMatrix_of_Type_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Guid__(ref List<Matrix<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Guid>); CodeMatrix_of_Guid_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Symbol__(ref List<Matrix<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Symbol>); CodeMatrix_of_Symbol_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Circle2d__(ref List<Matrix<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Circle2d>); CodeMatrix_of_Circle2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line2d__(ref List<Matrix<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Line2d>); CodeMatrix_of_Line2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line3d__(ref List<Matrix<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Line3d>); CodeMatrix_of_Line3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane2d__(ref List<Matrix<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Plane2d>); CodeMatrix_of_Plane2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane3d__(ref List<Matrix<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Plane3d>); CodeMatrix_of_Plane3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3d__(ref List<Matrix<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<PlaneWithPoint3d>); CodeMatrix_of_PlaneWithPoint3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad2d__(ref List<Matrix<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Quad2d>); CodeMatrix_of_Quad2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad3d__(ref List<Matrix<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Quad3d>); CodeMatrix_of_Quad3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray2d__(ref List<Matrix<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Ray2d>); CodeMatrix_of_Ray2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray3d__(ref List<Matrix<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Ray3d>); CodeMatrix_of_Ray3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Sphere3d__(ref List<Matrix<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Sphere3d>); CodeMatrix_of_Sphere3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle2d__(ref List<Matrix<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Triangle2d>); CodeMatrix_of_Triangle2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle3d__(ref List<Matrix<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Triangle3d>); CodeMatrix_of_Triangle3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Circle2f__(ref List<Matrix<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Circle2f>); CodeMatrix_of_Circle2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line2f__(ref List<Matrix<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Line2f>); CodeMatrix_of_Line2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line3f__(ref List<Matrix<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Line3f>); CodeMatrix_of_Line3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane2f__(ref List<Matrix<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Plane2f>); CodeMatrix_of_Plane2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane3f__(ref List<Matrix<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Plane3f>); CodeMatrix_of_Plane3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3f__(ref List<Matrix<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<PlaneWithPoint3f>); CodeMatrix_of_PlaneWithPoint3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad2f__(ref List<Matrix<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Quad2f>); CodeMatrix_of_Quad2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad3f__(ref List<Matrix<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Quad3f>); CodeMatrix_of_Quad3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray2f__(ref List<Matrix<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Ray2f>); CodeMatrix_of_Ray2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray3f__(ref List<Matrix<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Ray3f>); CodeMatrix_of_Ray3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Sphere3f__(ref List<Matrix<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Sphere3f>); CodeMatrix_of_Sphere3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle2f__(ref List<Matrix<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Triangle2f>); CodeMatrix_of_Triangle2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle3f__(ref List<Matrix<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Matrix<Triangle3f>); CodeMatrix_of_Triangle3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Byte__(ref List<Volume<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<byte>); CodeVolume_of_Byte_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_SByte__(ref List<Volume<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<sbyte>); CodeVolume_of_SByte_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Short__(ref List<Volume<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<short>); CodeVolume_of_Short_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_UShort__(ref List<Volume<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<ushort>); CodeVolume_of_UShort_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Int__(ref List<Volume<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<int>); CodeVolume_of_Int_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_UInt__(ref List<Volume<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<uint>); CodeVolume_of_UInt_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Long__(ref List<Volume<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<long>); CodeVolume_of_Long_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_ULong__(ref List<Volume<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<ulong>); CodeVolume_of_ULong_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Float__(ref List<Volume<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<float>); CodeVolume_of_Float_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Double__(ref List<Volume<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<double>); CodeVolume_of_Double_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Fraction__(ref List<Volume<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Fraction>); CodeVolume_of_Fraction_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2i__(ref List<Volume<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V2i>); CodeVolume_of_V2i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2l__(ref List<Volume<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V2l>); CodeVolume_of_V2l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2f__(ref List<Volume<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V2f>); CodeVolume_of_V2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2d__(ref List<Volume<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V2d>); CodeVolume_of_V2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3i__(ref List<Volume<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V3i>); CodeVolume_of_V3i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3l__(ref List<Volume<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V3l>); CodeVolume_of_V3l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3f__(ref List<Volume<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V3f>); CodeVolume_of_V3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3d__(ref List<Volume<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V3d>); CodeVolume_of_V3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4i__(ref List<Volume<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V4i>); CodeVolume_of_V4i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4l__(ref List<Volume<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V4l>); CodeVolume_of_V4l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4f__(ref List<Volume<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V4f>); CodeVolume_of_V4f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4d__(ref List<Volume<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<V4d>); CodeVolume_of_V4d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22i__(ref List<Volume<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M22i>); CodeVolume_of_M22i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22l__(ref List<Volume<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M22l>); CodeVolume_of_M22l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22f__(ref List<Volume<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M22f>); CodeVolume_of_M22f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22d__(ref List<Volume<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M22d>); CodeVolume_of_M22d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23i__(ref List<Volume<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M23i>); CodeVolume_of_M23i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23l__(ref List<Volume<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M23l>); CodeVolume_of_M23l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23f__(ref List<Volume<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M23f>); CodeVolume_of_M23f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23d__(ref List<Volume<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M23d>); CodeVolume_of_M23d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33i__(ref List<Volume<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M33i>); CodeVolume_of_M33i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33l__(ref List<Volume<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M33l>); CodeVolume_of_M33l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33f__(ref List<Volume<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M33f>); CodeVolume_of_M33f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33d__(ref List<Volume<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M33d>); CodeVolume_of_M33d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34i__(ref List<Volume<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M34i>); CodeVolume_of_M34i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34l__(ref List<Volume<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M34l>); CodeVolume_of_M34l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34f__(ref List<Volume<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M34f>); CodeVolume_of_M34f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34d__(ref List<Volume<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M34d>); CodeVolume_of_M34d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44i__(ref List<Volume<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M44i>); CodeVolume_of_M44i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44l__(ref List<Volume<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M44l>); CodeVolume_of_M44l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44f__(ref List<Volume<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M44f>); CodeVolume_of_M44f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44d__(ref List<Volume<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<M44d>); CodeVolume_of_M44d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3b__(ref List<Volume<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C3b>); CodeVolume_of_C3b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3us__(ref List<Volume<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C3us>); CodeVolume_of_C3us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3ui__(ref List<Volume<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C3ui>); CodeVolume_of_C3ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3f__(ref List<Volume<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C3f>); CodeVolume_of_C3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3d__(ref List<Volume<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C3d>); CodeVolume_of_C3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4b__(ref List<Volume<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C4b>); CodeVolume_of_C4b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4us__(ref List<Volume<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C4us>); CodeVolume_of_C4us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4ui__(ref List<Volume<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C4ui>); CodeVolume_of_C4ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4f__(ref List<Volume<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C4f>); CodeVolume_of_C4f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4d__(ref List<Volume<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<C4d>); CodeVolume_of_C4d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1b__(ref List<Volume<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1b>); CodeVolume_of_Range1b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1sb__(ref List<Volume<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1sb>); CodeVolume_of_Range1sb_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1s__(ref List<Volume<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1s>); CodeVolume_of_Range1s_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1us__(ref List<Volume<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1us>); CodeVolume_of_Range1us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1i__(ref List<Volume<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1i>); CodeVolume_of_Range1i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1ui__(ref List<Volume<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1ui>); CodeVolume_of_Range1ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1l__(ref List<Volume<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1l>); CodeVolume_of_Range1l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1ul__(ref List<Volume<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1ul>); CodeVolume_of_Range1ul_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1f__(ref List<Volume<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1f>); CodeVolume_of_Range1f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1d__(ref List<Volume<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Range1d>); CodeVolume_of_Range1d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2i__(ref List<Volume<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Box2i>); CodeVolume_of_Box2i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2l__(ref List<Volume<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Box2l>); CodeVolume_of_Box2l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2f__(ref List<Volume<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Box2f>); CodeVolume_of_Box2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2d__(ref List<Volume<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Box2d>); CodeVolume_of_Box2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3i__(ref List<Volume<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Box3i>); CodeVolume_of_Box3i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3l__(ref List<Volume<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Box3l>); CodeVolume_of_Box3l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3f__(ref List<Volume<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Box3f>); CodeVolume_of_Box3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3d__(ref List<Volume<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Box3d>); CodeVolume_of_Box3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Euclidean3f__(ref List<Volume<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Euclidean3f>); CodeVolume_of_Euclidean3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Euclidean3d__(ref List<Volume<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Euclidean3d>); CodeVolume_of_Euclidean3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot2f__(ref List<Volume<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Rot2f>); CodeVolume_of_Rot2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot2d__(ref List<Volume<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Rot2d>); CodeVolume_of_Rot2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot3f__(ref List<Volume<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Rot3f>); CodeVolume_of_Rot3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot3d__(ref List<Volume<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Rot3d>); CodeVolume_of_Rot3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Scale3f__(ref List<Volume<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Scale3f>); CodeVolume_of_Scale3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Scale3d__(ref List<Volume<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Scale3d>); CodeVolume_of_Scale3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Shift3f__(ref List<Volume<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Shift3f>); CodeVolume_of_Shift3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Shift3d__(ref List<Volume<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Shift3d>); CodeVolume_of_Shift3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo2f__(ref List<Volume<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Trafo2f>); CodeVolume_of_Trafo2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo2d__(ref List<Volume<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Trafo2d>); CodeVolume_of_Trafo2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo3f__(ref List<Volume<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Trafo3f>); CodeVolume_of_Trafo3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo3d__(ref List<Volume<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Trafo3d>); CodeVolume_of_Trafo3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Bool__(ref List<Volume<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<bool>); CodeVolume_of_Bool_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Char__(ref List<Volume<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<char>); CodeVolume_of_Char_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_String__(ref List<Volume<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<string>); CodeVolume_of_String_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Type__(ref List<Volume<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Type>); CodeVolume_of_Type_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Guid__(ref List<Volume<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Guid>); CodeVolume_of_Guid_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Symbol__(ref List<Volume<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Symbol>); CodeVolume_of_Symbol_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Circle2d__(ref List<Volume<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Circle2d>); CodeVolume_of_Circle2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line2d__(ref List<Volume<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Line2d>); CodeVolume_of_Line2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line3d__(ref List<Volume<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Line3d>); CodeVolume_of_Line3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane2d__(ref List<Volume<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Plane2d>); CodeVolume_of_Plane2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane3d__(ref List<Volume<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Plane3d>); CodeVolume_of_Plane3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3d__(ref List<Volume<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<PlaneWithPoint3d>); CodeVolume_of_PlaneWithPoint3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad2d__(ref List<Volume<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Quad2d>); CodeVolume_of_Quad2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad3d__(ref List<Volume<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Quad3d>); CodeVolume_of_Quad3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray2d__(ref List<Volume<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Ray2d>); CodeVolume_of_Ray2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray3d__(ref List<Volume<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Ray3d>); CodeVolume_of_Ray3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Sphere3d__(ref List<Volume<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Sphere3d>); CodeVolume_of_Sphere3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle2d__(ref List<Volume<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Triangle2d>); CodeVolume_of_Triangle2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle3d__(ref List<Volume<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Triangle3d>); CodeVolume_of_Triangle3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Circle2f__(ref List<Volume<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Circle2f>); CodeVolume_of_Circle2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line2f__(ref List<Volume<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Line2f>); CodeVolume_of_Line2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line3f__(ref List<Volume<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Line3f>); CodeVolume_of_Line3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane2f__(ref List<Volume<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Plane2f>); CodeVolume_of_Plane2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane3f__(ref List<Volume<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Plane3f>); CodeVolume_of_Plane3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3f__(ref List<Volume<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<PlaneWithPoint3f>); CodeVolume_of_PlaneWithPoint3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad2f__(ref List<Volume<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Quad2f>); CodeVolume_of_Quad2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad3f__(ref List<Volume<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Quad3f>); CodeVolume_of_Quad3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray2f__(ref List<Volume<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Ray2f>); CodeVolume_of_Ray2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray3f__(ref List<Volume<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Ray3f>); CodeVolume_of_Ray3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Sphere3f__(ref List<Volume<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Sphere3f>); CodeVolume_of_Sphere3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle2f__(ref List<Volume<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Triangle2f>); CodeVolume_of_Triangle2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle3f__(ref List<Volume<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Volume<Triangle3f>); CodeVolume_of_Triangle3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Byte__(ref List<Tensor<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<byte>); CodeTensor_of_Byte_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_SByte__(ref List<Tensor<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<sbyte>); CodeTensor_of_SByte_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Short__(ref List<Tensor<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<short>); CodeTensor_of_Short_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_UShort__(ref List<Tensor<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<ushort>); CodeTensor_of_UShort_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Int__(ref List<Tensor<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<int>); CodeTensor_of_Int_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_UInt__(ref List<Tensor<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<uint>); CodeTensor_of_UInt_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Long__(ref List<Tensor<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<long>); CodeTensor_of_Long_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_ULong__(ref List<Tensor<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<ulong>); CodeTensor_of_ULong_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Float__(ref List<Tensor<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<float>); CodeTensor_of_Float_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Double__(ref List<Tensor<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<double>); CodeTensor_of_Double_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Fraction__(ref List<Tensor<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Fraction>); CodeTensor_of_Fraction_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2i__(ref List<Tensor<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V2i>); CodeTensor_of_V2i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2l__(ref List<Tensor<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V2l>); CodeTensor_of_V2l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2f__(ref List<Tensor<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V2f>); CodeTensor_of_V2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2d__(ref List<Tensor<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V2d>); CodeTensor_of_V2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3i__(ref List<Tensor<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V3i>); CodeTensor_of_V3i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3l__(ref List<Tensor<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V3l>); CodeTensor_of_V3l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3f__(ref List<Tensor<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V3f>); CodeTensor_of_V3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3d__(ref List<Tensor<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V3d>); CodeTensor_of_V3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4i__(ref List<Tensor<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V4i>); CodeTensor_of_V4i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4l__(ref List<Tensor<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V4l>); CodeTensor_of_V4l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4f__(ref List<Tensor<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V4f>); CodeTensor_of_V4f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4d__(ref List<Tensor<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<V4d>); CodeTensor_of_V4d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22i__(ref List<Tensor<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M22i>); CodeTensor_of_M22i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22l__(ref List<Tensor<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M22l>); CodeTensor_of_M22l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22f__(ref List<Tensor<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M22f>); CodeTensor_of_M22f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22d__(ref List<Tensor<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M22d>); CodeTensor_of_M22d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23i__(ref List<Tensor<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M23i>); CodeTensor_of_M23i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23l__(ref List<Tensor<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M23l>); CodeTensor_of_M23l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23f__(ref List<Tensor<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M23f>); CodeTensor_of_M23f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23d__(ref List<Tensor<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M23d>); CodeTensor_of_M23d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33i__(ref List<Tensor<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M33i>); CodeTensor_of_M33i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33l__(ref List<Tensor<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M33l>); CodeTensor_of_M33l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33f__(ref List<Tensor<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M33f>); CodeTensor_of_M33f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33d__(ref List<Tensor<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M33d>); CodeTensor_of_M33d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34i__(ref List<Tensor<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M34i>); CodeTensor_of_M34i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34l__(ref List<Tensor<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M34l>); CodeTensor_of_M34l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34f__(ref List<Tensor<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M34f>); CodeTensor_of_M34f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34d__(ref List<Tensor<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M34d>); CodeTensor_of_M34d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44i__(ref List<Tensor<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M44i>); CodeTensor_of_M44i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44l__(ref List<Tensor<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M44l>); CodeTensor_of_M44l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44f__(ref List<Tensor<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M44f>); CodeTensor_of_M44f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44d__(ref List<Tensor<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<M44d>); CodeTensor_of_M44d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3b__(ref List<Tensor<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C3b>); CodeTensor_of_C3b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3us__(ref List<Tensor<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C3us>); CodeTensor_of_C3us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3ui__(ref List<Tensor<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C3ui>); CodeTensor_of_C3ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3f__(ref List<Tensor<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C3f>); CodeTensor_of_C3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3d__(ref List<Tensor<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C3d>); CodeTensor_of_C3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4b__(ref List<Tensor<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C4b>); CodeTensor_of_C4b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4us__(ref List<Tensor<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C4us>); CodeTensor_of_C4us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4ui__(ref List<Tensor<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C4ui>); CodeTensor_of_C4ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4f__(ref List<Tensor<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C4f>); CodeTensor_of_C4f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4d__(ref List<Tensor<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<C4d>); CodeTensor_of_C4d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1b__(ref List<Tensor<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1b>); CodeTensor_of_Range1b_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1sb__(ref List<Tensor<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1sb>); CodeTensor_of_Range1sb_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1s__(ref List<Tensor<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1s>); CodeTensor_of_Range1s_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1us__(ref List<Tensor<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1us>); CodeTensor_of_Range1us_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1i__(ref List<Tensor<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1i>); CodeTensor_of_Range1i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1ui__(ref List<Tensor<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1ui>); CodeTensor_of_Range1ui_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1l__(ref List<Tensor<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1l>); CodeTensor_of_Range1l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1ul__(ref List<Tensor<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1ul>); CodeTensor_of_Range1ul_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1f__(ref List<Tensor<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1f>); CodeTensor_of_Range1f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1d__(ref List<Tensor<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Range1d>); CodeTensor_of_Range1d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2i__(ref List<Tensor<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Box2i>); CodeTensor_of_Box2i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2l__(ref List<Tensor<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Box2l>); CodeTensor_of_Box2l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2f__(ref List<Tensor<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Box2f>); CodeTensor_of_Box2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2d__(ref List<Tensor<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Box2d>); CodeTensor_of_Box2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3i__(ref List<Tensor<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Box3i>); CodeTensor_of_Box3i_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3l__(ref List<Tensor<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Box3l>); CodeTensor_of_Box3l_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3f__(ref List<Tensor<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Box3f>); CodeTensor_of_Box3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3d__(ref List<Tensor<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Box3d>); CodeTensor_of_Box3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Euclidean3f__(ref List<Tensor<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Euclidean3f>); CodeTensor_of_Euclidean3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Euclidean3d__(ref List<Tensor<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Euclidean3d>); CodeTensor_of_Euclidean3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot2f__(ref List<Tensor<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Rot2f>); CodeTensor_of_Rot2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot2d__(ref List<Tensor<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Rot2d>); CodeTensor_of_Rot2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot3f__(ref List<Tensor<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Rot3f>); CodeTensor_of_Rot3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot3d__(ref List<Tensor<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Rot3d>); CodeTensor_of_Rot3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Scale3f__(ref List<Tensor<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Scale3f>); CodeTensor_of_Scale3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Scale3d__(ref List<Tensor<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Scale3d>); CodeTensor_of_Scale3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Shift3f__(ref List<Tensor<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Shift3f>); CodeTensor_of_Shift3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Shift3d__(ref List<Tensor<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Shift3d>); CodeTensor_of_Shift3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo2f__(ref List<Tensor<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Trafo2f>); CodeTensor_of_Trafo2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo2d__(ref List<Tensor<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Trafo2d>); CodeTensor_of_Trafo2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo3f__(ref List<Tensor<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Trafo3f>); CodeTensor_of_Trafo3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo3d__(ref List<Tensor<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Trafo3d>); CodeTensor_of_Trafo3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Bool__(ref List<Tensor<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<bool>); CodeTensor_of_Bool_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Char__(ref List<Tensor<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<char>); CodeTensor_of_Char_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_String__(ref List<Tensor<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<string>); CodeTensor_of_String_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Type__(ref List<Tensor<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Type>); CodeTensor_of_Type_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Guid__(ref List<Tensor<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Guid>); CodeTensor_of_Guid_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Symbol__(ref List<Tensor<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Symbol>); CodeTensor_of_Symbol_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Circle2d__(ref List<Tensor<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Circle2d>); CodeTensor_of_Circle2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line2d__(ref List<Tensor<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Line2d>); CodeTensor_of_Line2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line3d__(ref List<Tensor<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Line3d>); CodeTensor_of_Line3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane2d__(ref List<Tensor<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Plane2d>); CodeTensor_of_Plane2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane3d__(ref List<Tensor<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Plane3d>); CodeTensor_of_Plane3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3d__(ref List<Tensor<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<PlaneWithPoint3d>); CodeTensor_of_PlaneWithPoint3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad2d__(ref List<Tensor<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Quad2d>); CodeTensor_of_Quad2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad3d__(ref List<Tensor<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Quad3d>); CodeTensor_of_Quad3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray2d__(ref List<Tensor<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Ray2d>); CodeTensor_of_Ray2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray3d__(ref List<Tensor<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Ray3d>); CodeTensor_of_Ray3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Sphere3d__(ref List<Tensor<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Sphere3d>); CodeTensor_of_Sphere3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle2d__(ref List<Tensor<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Triangle2d>); CodeTensor_of_Triangle2d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle3d__(ref List<Tensor<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Triangle3d>); CodeTensor_of_Triangle3d_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Circle2f__(ref List<Tensor<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Circle2f>); CodeTensor_of_Circle2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line2f__(ref List<Tensor<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Line2f>); CodeTensor_of_Line2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line3f__(ref List<Tensor<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Line3f>); CodeTensor_of_Line3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane2f__(ref List<Tensor<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Plane2f>); CodeTensor_of_Plane2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane3f__(ref List<Tensor<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Plane3f>); CodeTensor_of_Plane3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3f__(ref List<Tensor<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<PlaneWithPoint3f>); CodeTensor_of_PlaneWithPoint3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad2f__(ref List<Tensor<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Quad2f>); CodeTensor_of_Quad2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad3f__(ref List<Tensor<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Quad3f>); CodeTensor_of_Quad3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray2f__(ref List<Tensor<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Ray2f>); CodeTensor_of_Ray2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray3f__(ref List<Tensor<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Ray3f>); CodeTensor_of_Ray3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Sphere3f__(ref List<Tensor<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Sphere3f>); CodeTensor_of_Sphere3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle2f__(ref List<Tensor<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Triangle2f>); CodeTensor_of_Triangle2f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle3f__(ref List<Tensor<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                var m = default(Tensor<Triangle3f>); CodeTensor_of_Triangle3f_(ref m); value.Add(m);\r\n            }\r\n        }\r\n\r\n        #endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/BinaryReadingCoder_template.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Coder\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var directlyCodeableTypes = Meta.DirectlyCodeableTypes.Map(t =>t.Name);\n    //# var geometryTypes = Meta.GeometryTypes.Map(t => t.Name);\n    //# var specialSimpleTypes = new[] { \"bool\", \"char\", \"string\", \"Type\", \"Guid\", \"Symbol\" };\n    //# var structTypes = new List<string>();\n    //# var fastStructTypes = new List<string>();\n    public partial class BinaryReadingCoder\n    {\n        #region Vectors\n\n        //# foreach (var t in Meta.VecTypes) { fastStructTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value) \n        {\n            //# t.Fields.ForEach(f => {\n            value.__f__ = m_reader.__t.FieldType.Read__();\n            //# });\n        }\n\n        //# }\n        #endregion\n\n        #region Matrices\n\n        //# foreach (var t in Meta.MatTypes) { fastStructTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value) { value = m_reader.__t.Read__(); }\n        //# }\n\n        #endregion\n\n        #region Ranges and Boxes\n\n        //# foreach (var t in Meta.RangeAndBoxTypes) { fastStructTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value)\n        {\n            value.Min = m_reader.__t.LimitType.Read__();\n            value.Max = m_reader.__t.LimitType.Read__();\n        }\n\n        //# }\n        #endregion\n\n        #region Geometry Types\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"Double\" : \"Float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        public void CodeCircle2__tc__(ref Circle2__tc__ v)\n        {\n            CodeV2__tc__(ref v.Center); Code__ftype__(ref v.Radius);\n        }\n\n        public void CodeLine2__tc__(ref Line2__tc__ v)\n        {\n            CodeV2__tc__(ref v.P0); CodeV2__tc__(ref v.P1);\n        }\n\n        public void CodeLine3__tc__(ref Line3__tc__ v)\n        {\n            CodeV3__tc__(ref v.P0); CodeV3__tc__(ref v.P1);\n        }\n\n        public void CodePlane2__tc__(ref Plane2__tc__ v)\n        {\n            CodeV2__tc__(ref v.Normal); Code__ftype__(ref v.Distance);\n        }\n\n        public void CodePlane3__tc__(ref Plane3__tc__ v)\n        {\n            CodeV3__tc__(ref v.Normal); Code__ftype__(ref v.Distance);\n        }\n\n        public void CodePlaneWithPoint3__tc__(ref PlaneWithPoint3__tc__ v)\n        {\n            CodeV3__tc__(ref v.Normal); CodeV3__tc__(ref v.Point);\n        }\n\n        public void CodeQuad2__tc__(ref Quad2__tc__ v)\n        {\n            CodeV2__tc__(ref v.P0); CodeV2__tc__(ref v.P1); CodeV2__tc__(ref v.P2); CodeV2__tc__(ref v.P3);\n        }\n\n        public void CodeQuad3__tc__(ref Quad3__tc__ v)\n        {\n            CodeV3__tc__(ref v.P0); CodeV3__tc__(ref v.P1); CodeV3__tc__(ref v.P2); CodeV3__tc__(ref v.P3);\n        }\n\n        public void CodeRay2__tc__(ref Ray2__tc__ v)\n        {\n            CodeV2__tc__(ref v.Origin); CodeV2__tc__(ref v.Direction);\n        }\n\n        public void CodeRay3__tc__(ref Ray3__tc__ v)\n        {\n            CodeV3__tc__(ref v.Origin); CodeV3__tc__(ref v.Direction);\n        }\n\n        public void CodeSphere3__tc__(ref Sphere3__tc__ v)\n        {\n            CodeV3__tc__(ref v.Center); Code__ftype__(ref v.Radius);\n        }\n\n        public void CodeTriangle2__tc__(ref Triangle2__tc__ v)\n        {\n            CodeV2__tc__(ref v.P0); CodeV2__tc__(ref v.P1); CodeV2__tc__(ref v.P2);\n        }\n\n        public void CodeTriangle3__tc__(ref Triangle3__tc__ v)\n        {\n            CodeV3__tc__(ref v.P0); CodeV3__tc__(ref v.P1); CodeV3__tc__(ref v.P2);\n        }\n\n        //# }\n        #endregion\n\n        #region Colors\n\n        //# foreach (var t in Meta.ColorTypes) { fastStructTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value)\n        {\n            //# t.Fields.ForEach(f => {\n            value.__f__ = m_reader.__t.FieldType.Read__();\n            //# });\n        }\n\n        //# }\n        #endregion\n\n        #region Trafos\n\n        //# foreach (var t in Meta.TrafoTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value) { value = m_reader.__t.Read__(); }\n        //# }\n\n        #endregion\n\n        #region Tensors\n\n        //# foreach (var t in geometryTypes) structTypes.Add(t);\n        //# var simpleTypes = directlyCodeableTypes.Concat(specialSimpleTypes).Concat(geometryTypes);\n        //# var genericTensorTypes = new[] { \"Vector\", \"Matrix\", \"Volume\", \"Tensor\" };\n        //# var genericTensorSizes = new[] { \"long\", \"V2l\", \"V3l\", \"long[]\" };\n        //# genericTensorTypes.ForEach((tt, ti) => {\n        //#     var ts = genericTensorSizes[ti]; var tsn = Meta.GetXmlTypeName(ts);\n        //#     simpleTypes.ForEach((t, i) => {\n        //#         var type = tt + \"<\" + t + \">\";\n        //#         structTypes.Add(type);\n        //# var dname = Meta.GetXmlTypeName(t + \"[]\");\n        //# var name = Meta.GetXmlTypeName(type);\n        public void Code__name__(ref __type__ value)\n        {\n            __t__[] data = null; Code__dname__(ref data);\n            long origin = 0L; CodeLong(ref origin);\n            __ts__ size = default(__ts__); Code__tsn__(ref size);\n            __ts__ delta = default(__ts__); Code__tsn__(ref delta);\n            value = new __type__(data, origin, size, delta);\n        }\n\n        //#     });\n        //# });\n        #endregion\n\n        #region Arrays\n\n        //# fastStructTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_reader.ReadArray(value, 0, count);\n        }\n\n        //# });\n        //# structTypes.ForEach(t => {\n        //# var ename = Meta.GetXmlTypeName(t);\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) Code__ename__(ref value[i]);\n        }\n\n        //# });\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[,]\");\n        public void Code__name2d__(ref __t__[,] value)\n        {\n            long[] countArray = CodeCountLong(ref value);\n            long c0 = countArray[0]; if (c0 < 1) return;\n            long c1 = countArray[1]; if (c1 < 1) return;\n            m_reader.ReadArray(value, c0 * c1);\n        }\n\n        //# var name3d = Meta.GetXmlTypeName(t + \"[,,]\");\n        public void Code__name3d__(ref __t__[, ,] value)\n        {\n            long[] countArray = CodeCountLong(ref value);\n            long c0 = countArray[0]; if (c0 < 1) return;\n            long c1 = countArray[1]; if (c1 < 1) return;\n            long c2 = countArray[2]; if (c2 < 1) return;\n            m_reader.ReadArray(value, c0 * c1 * c2);\n        }\n\n        //# });\n        #endregion\n\n        #region Jagged Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var ename2d = Meta.GetXmlTypeName(t + \"[]\");\n        //# var name2d = Meta.GetXmlTypeName(t + \"[][]\");\n        public void Code__name2d__(ref __t__[][] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) Code__ename2d__(ref value[i]);\n        }\n\n        //# var ename3d = Meta.GetXmlTypeName(t + \"[][]\");\n        //# var name3d = Meta.GetXmlTypeName(t + \"[][][]\");\n        public void Code__name3d__(ref __t__[][][] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) Code__ename3d__(ref value[i]);\n        }\n\n        //# });\n        #endregion\n\n        #region Lists\n\n        //# fastStructTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_reader.ReadList(value, 0, count);\n        }\n\n        //# });\n        //# structTypes.ForEach(t => {\n        //# var ename = Meta.GetXmlTypeName(t);\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                var m = default(__t__); Code__ename__(ref m); value.Add(m);\n            }\n        }\n\n        //# });\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/BinaryWritingCoder.cs",
    "content": "using Aardvark.Base;\r\nusing System;\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing System.IO;\r\nusing System.Text;\r\n\r\nnamespace Aardvark.Base.Coder\r\n{\r\n    /// <summary>\r\n    /// A class for writing binary files in an Aardvark specific format.\r\n    /// </summary>\r\n    public partial class BinaryWritingCoder\r\n        : BaseWritingCoder, IWritingCoder, IDisposable\r\n    {\r\n        private readonly StreamCodeWriter m_writer;\r\n        private string m_fileName;\r\n        private long m_size = 0;\r\n        private readonly long m_sizePosition = 0;\r\n        private readonly long m_startPosition = 0;\r\n        private readonly bool m_disposeStream;\r\n\r\n        #region Constructors\r\n\r\n        public BinaryWritingCoder(Stream stream) : base()\r\n        {\r\n            m_writer = new StreamCodeWriter(stream, Encoding.UTF8);\r\n            m_fileName = null;\r\n            m_writer.Write(\"Aardvark\");\r\n            m_writer.Write(c_coderVersion);\r\n            m_sizePosition = m_writer.BaseStream.Position;\r\n            m_writer.Write(m_size);\r\n            m_startPosition = m_writer.BaseStream.Position;\r\n            m_disposeStream = false;\r\n        }\r\n\r\n        public BinaryWritingCoder(string fileName)\r\n            : this(File.Open(fileName, FileMode.Create))\r\n        {\r\n            m_fileName = fileName;\r\n            m_disposeStream = true;\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Static Convenience Methods\r\n\r\n        public static void WriteObject(string fileName, object obj)\r\n        {\r\n            using (var coder = new BinaryWritingCoder(fileName))\r\n                coder.Code(ref obj);\r\n        }\r\n\r\n        public static void WriteObject(Stream stream, object obj)\r\n        {\r\n            using (var coder = new BinaryWritingCoder(stream))\r\n                coder.Code(ref obj);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region ICoder Members\r\n\r\n        public string FileName\r\n        {\r\n            get { return m_fileName; }\r\n            set { m_fileName = value; }\r\n        }\r\n\r\n        public int CoderVersion { get { return c_coderVersion; } }\r\n\r\n        public int StreamVersion { get { return m_version; } }\r\n\r\n        public int MemoryVersion { get { return m_version; } }\r\n\r\n        private void AddRef(object obj)\r\n        {\r\n            int count = m_refs.Count;\r\n            m_refs[obj] = count;\r\n            if ((m_debugMode & CoderDebugMode.ReportReferences) != 0)\r\n            {\r\n                Report.Line(\"{0,32}   0x{1:x}\", count, obj.GetHashCode());\r\n            }\r\n        }\r\n\r\n        private bool HandleRef(ref object obj)\r\n        {\r\n            if (m_doRefs)\r\n            {\r\n                if (c_coderVersion < 5)\r\n                {\r\n                    int index;\r\n                    if (m_refs.TryGetValue(obj, out index))\r\n                    {\r\n                        TypeInfo typeInfo;\r\n                        if (TryGetTypeInfo(typeof(TypeCoder.Reference), out typeInfo))\r\n                        {\r\n                            m_writer.Write(typeInfo.Name);\r\n                            m_writer.Write(index);\r\n                            if ((m_debugMode & CoderDebugMode.ReportReferences) != 0)\r\n                            {\r\n                                Report.Line(\"{0,32} * 0x{1:x}\", index, obj.GetHashCode());\r\n                            }\r\n                            return true;\r\n                        }\r\n                        else\r\n                            throw new Exception(\r\n                                    \"cannot encode multiply referenced object \"\r\n                                    + \"- change by configuring coder with \"\r\n                                    + \"\\\"coder.Add(TypeCoder.Default.Reference);\\\"\");\r\n                    }\r\n                    AddRef(obj);\r\n                }\r\n                else\r\n                {\r\n                    // TODO\r\n                }\r\n            }\r\n            return false;\r\n        }\r\n\r\n        public void Code(ref object obj)\r\n        {\r\n            TypeInfo typeInfo;\r\n\r\n            #region handle null objects\r\n\r\n            if (obj == null)\r\n            {\r\n                if (TryGetTypeInfo(typeof(TypeCoder.Null), out typeInfo)\r\n                    && ((typeInfo.Options & TypeInfo.Option.Active) != 0))\r\n                {\r\n                    m_writer.Write(typeInfo.Name);\r\n                    return;\r\n                }\r\n                else\r\n                    throw new Exception(\"cannot encode null object \"\r\n                            + \"- change by configuring coder with \"\r\n                            + \"\\\"coder.Add(TypeCoder.Default.Null);\\\"\");\r\n            }\r\n\r\n            #endregion\r\n\r\n            Type type = obj.GetType();\r\n            string typeName;\r\n            TypeInfo.Option typeOptions = TypeInfo.Option.Size\r\n                                            | TypeInfo.Option.Version;\r\n\r\n            if (!TypeCoder.IsDirectlyCodeable(type))\r\n                if (HandleRef(ref obj)) return;\r\n\r\n            #region handle modified type names\r\n\r\n            if (TryGetTypeInfo(type, out typeInfo))\r\n            {\r\n                typeName = typeInfo.Name;\r\n                typeOptions = typeInfo.Options;\r\n            }\r\n            else\r\n            {\r\n                typeName = type.AssemblyQualifiedName;\r\n                if ((m_debugMode & CoderDebugMode.ReportQualifiedNames) != 0)\r\n                    Report.Line(\"qualified name \\\"{0}\\\"\", typeName); \r\n            }\r\n\r\n            #endregion\r\n\r\n            m_writer.Write(typeName);\r\n\r\n            #region code version placeholder\r\n\r\n            if ((typeOptions & TypeInfo.Option.Version) != 0)\r\n            {\r\n                m_versionStack.Push(m_version);\r\n                m_version = typeInfo != null ? typeInfo.Version : 0;\r\n                m_writer.Write(m_version);\r\n            }\r\n\r\n            #endregion\r\n\r\n            #region code size placeholder\r\n\r\n            long size = 0;\r\n            long sizePosition = 0;\r\n            long startPosition = 0;\r\n            if ((typeOptions & TypeInfo.Option.Size) != 0)\r\n            {\r\n                sizePosition = m_writer.BaseStream.Position;\r\n                m_writer.Write(size);\r\n                startPosition = m_writer.BaseStream.Position;\r\n            }\r\n\r\n            #endregion\r\n\r\n            #region code fields based on supported interface\r\n\r\n            if (!TypeCoder.WritePrimitive(this, type, ref obj))\r\n            {\r\n                m_typeInfoStack.Push(typeInfo);\r\n\r\n                if ((m_debugMode & CoderDebugMode.ReportObjects) != 0)\r\n                {\r\n                    Report.Line(\"{0,-34} 0x{1:x}\", typeName, obj.GetHashCode());\r\n                }\r\n\r\n                var fcobj = obj as IFieldCodeable;\r\n                if (fcobj != null)\r\n                {\r\n                    CodeFields(type, m_version, fcobj);\r\n                    var tmobj = obj as ITypedMap;\r\n                    if (tmobj != null) CodeFields(type, tmobj);\r\n                }\r\n                else if (typeInfo.ProxyType != null)\r\n                {\r\n                    CodeFields(type, m_version, typeInfo.Object2ProxyFun(obj));\r\n                }\r\n                else\r\n                {\r\n                    throw new Exception(\"uncodeable object of type \\\"\"\r\n                                        + typeName + '\\\"');\r\n                }\r\n\r\n                m_typeInfoStack.Pop();\r\n            }\r\n\r\n            #endregion\r\n\r\n            #region backpatch size into stream\r\n\r\n            if ((typeOptions & TypeInfo.Option.Size) != 0)\r\n            {\r\n                var position = m_writer.BaseStream.Position;\r\n\r\n                size = position - startPosition;\r\n                m_writer.BaseStream.Position = sizePosition;\r\n                m_writer.Write(size);\r\n                m_writer.BaseStream.Position = position;\r\n            }\r\n            #endregion\r\n\r\n            #region pop version stack\r\n\r\n            if ((typeOptions & TypeInfo.Option.Version) != 0)\r\n                m_version = m_versionStack.Pop();\r\n\r\n            #endregion\r\n        }\r\n\r\n        public void CodeFields(Type type, int version, IFieldCodeable obj)\r\n        {\r\n            FieldCoder[] fca = FieldCoderArray.Get(c_coderVersion, type, version, obj);\r\n            if ((m_debugMode & CoderDebugMode.ReportFields) == 0)\r\n            {\r\n                foreach (var fc in fca) fc.Code(this, obj);\r\n            }\r\n            else\r\n            {\r\n                foreach (var fc in fca)\r\n                {\r\n                    Report.Line(\"  {0}\", fc.Name);\r\n                    fc.Code(this, obj);\r\n                }\r\n            }\r\n        }\r\n\r\n        public void CodeFields(Type type, ITypedMap obj)\r\n        {\r\n            TypeOfString fieldTypeMap = FieldTypeMap.Get(type, obj);\r\n\r\n            m_writer.Write(obj.FieldCount);\r\n\r\n            foreach (string fieldName in obj.FieldNames)\r\n            {\r\n                m_writer.Write(fieldName);\r\n                object value = obj[fieldName];\r\n                bool directlyCodeable = true;\r\n                Type fieldType = null;\r\n\r\n                if ((m_debugMode & CoderDebugMode.ReportFields) != 0)\r\n                    Report.Line(\"  {0}\", fieldName);\r\n\r\n                // A field is directly codeable, if its type information can\r\n                // be computed by the writer and the reader without\r\n                // inspecting the actual field value.\r\n\r\n                if (!fieldTypeMap.TryGetValue(fieldName, out fieldType)\r\n                    || (value != null && fieldType != value.GetType())\r\n                    || !TypeCoder.IsDirectlyCodeable(fieldType))\r\n                    directlyCodeable = false;\r\n\r\n                // We store the directly codeable flag, so that a stored file\r\n                // can be read, even if the class has been modified, and the\r\n                // value of directly codeable has been changed.\r\n\r\n                m_writer.Write(directlyCodeable);\r\n                if (directlyCodeable)\r\n                    TypeCoder.Write(this, fieldType, ref value);\r\n                else\r\n                    Code(ref value);\r\n            }\r\n        }\r\n\r\n        public void CodeT<T>(ref T obj)\r\n        {\r\n            object o = obj;\r\n            if (typeof(T) == typeof(Array) || obj == null)\r\n                Code(ref o);\r\n            else\r\n                TypeCoder.Write(this, obj.GetType(), ref o);\r\n        }\r\n\r\n        public void Code(Type t, ref object o)\r\n        {\r\n            TypeCoder.Write(this, t, ref o);\r\n        }\r\n\r\n        public bool CodeNull<T>(ref T value) where T : class\r\n        {\r\n            bool isNonNull = value != null;\r\n            m_writer.Write(isNonNull);\r\n            return !isNonNull;\r\n        }\r\n\r\n        public int CodeCount<T>(ref T value, Func<T, int> counter) where T : class\r\n        {\r\n            if (value == null) { m_writer.Write(-1); return -1; }\r\n            int refNum;\r\n            if (m_refs.TryGetValue(value, out refNum))\r\n            {\r\n                m_writer.Write(-2); m_writer.Write(refNum);\r\n                if ((m_debugMode & CoderDebugMode.ReportReferences) != 0)\r\n                {\r\n                    Report.Line(\"{0,32} * 0x{1:x}\", refNum, value.GetHashCode());\r\n                }\r\n                return -2;\r\n            }\r\n            int count = counter(value);\r\n            m_writer.Write(count);\r\n            if (m_doRefs) AddRef(value);\r\n            return count;\r\n        }\r\n\r\n        private void CodeLong(long value)\r\n        {\r\n            if (value > (long)int.MaxValue)\r\n            {\r\n                m_writer.Write(int.MinValue | (int)(value >> 32));\r\n                m_writer.Write((uint)value);\r\n            }\r\n            else\r\n                m_writer.Write((uint)value);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Backward compatible extension for coding collections with 64-bit lengths.\r\n        /// </summary>\r\n        public long CodeCountLong<T>(ref T value, Func<T, long> counter) where T : class\r\n        {\r\n            if (value == null) { m_writer.Write(-1); return -1L; }\r\n            int refNum;\r\n            if (m_refs.TryGetValue(value, out refNum))\r\n            {\r\n                m_writer.Write(-2); m_writer.Write(refNum);\r\n                if ((m_debugMode & CoderDebugMode.ReportReferences) != 0)\r\n                {\r\n                    Report.Line(\"{0,32} * 0x{1:x}\", refNum, value.GetHashCode());\r\n                }\r\n                return -2L;\r\n            }\r\n            long count = counter(value);\r\n            CodeLong(count);\r\n            if (m_doRefs) AddRef(value);\r\n            return count;\r\n        }\r\n\r\n        /// <summary>\r\n        /// Backward compatible extension for coding collections with 64-bit lengths.\r\n        /// </summary>\r\n        public long[] CodeCountArray<T>(ref T value, Func<T, long[]> counter) where T : class\r\n        {\r\n            if (value == null) { m_writer.Write(-1); return (-1L).IntoArray(); }\r\n            int refNum;\r\n            if (m_refs.TryGetValue(value, out refNum))\r\n            {\r\n                m_writer.Write(-2); m_writer.Write(refNum);\r\n                if ((m_debugMode & CoderDebugMode.ReportReferences) != 0)\r\n                {\r\n                    Report.Line(\"{0,32} * 0x{1:x}\", refNum, value.GetHashCode());\r\n                }\r\n                return (-2L).IntoArray();\r\n            }\r\n            long[] countArray = counter(value);\r\n            if (countArray.Length == 1)\r\n            {\r\n                long count = countArray[0];\r\n                CodeLong(count);\r\n                if (m_doRefs) AddRef(value);\r\n                return count.IntoArray();\r\n            }\r\n            if (countArray.Length < 4)\r\n            {\r\n                m_writer.Write(-1 - countArray.Length);\r\n                foreach (long ci in countArray) CodeLong(ci);\r\n                if (m_doRefs) AddRef(value);\r\n                return countArray;\r\n            }\r\n            throw new ArgumentException(\"cannot encode array with more than 3 dimensions\");\r\n        }\r\n\r\n        private long CodeCountLong<T>(ref T[] array)\r\n        {\r\n            return CodeCountLong(ref array, v => v.LongLength);\r\n        }\r\n\r\n        private long[] CodeCountLong<T>(ref T[,] array)\r\n        {\r\n            return CodeCountArray(ref array, v => new[] {\r\n                                  v.GetLongLength(0), v.GetLongLength(1) });\r\n        }\r\n\r\n        private long[] CodeCountLong<T>(ref T[,,] array)\r\n        {\r\n            return CodeCountArray(ref array, v => new[] {\r\n                                  v.GetLongLength(0), v.GetLongLength(1), v.GetLongLength(2) });\r\n        }\r\n\r\n        private long CodeCountLong<T>(ref T[][] array)\r\n        {\r\n            return CodeCountLong(ref array, v => v.GetLongLength(0) );\r\n        }\r\n\r\n        private long CodeCountLong<T>(ref T[][][] array)\r\n        {\r\n            return CodeCountLong(ref array, v => v.GetLongLength(0) );\r\n        }\r\n\r\n        private int CodeCount<T>(ref List<T> list)\r\n        {\r\n            return CodeCount(ref list, v => v.Count);\r\n        }\r\n\r\n        public void CodeTArray<T>(ref T[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeT(ref value[i]);\r\n        }\r\n\r\n        public void CodeList_of_T_<T>(ref List<T> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                object o = value[i];\r\n                Code(ref o);\r\n            }\r\n        }\r\n\r\n        public void CodeHashSet_of_T_<T>(ref HashSet<T> value)\r\n        {\r\n            int count = CodeCount(ref value, v => v.Count);\r\n            if (count < 1) return;\r\n            foreach (var e in value)\r\n            {\r\n                object o = e;\r\n                Code(ref o);\r\n            }\r\n        }\r\n\r\n        private static long[] LengthArray(Array array)\r\n        {\r\n            switch (array.Rank)\r\n            {\r\n                case 1: return array.LongLength.IntoArray();\r\n                case 2: return new[] { array.GetLongLength(0), array.GetLongLength(1) };\r\n                case 3: return new[] { array.GetLongLength(0), array.GetLongLength(1), array.GetLongLength(2) };\r\n            }\r\n            throw new ArgumentException(\"cannot code arrays with more than 3 dimensions\");\r\n        }\r\n\r\n\r\n        public void Code(Type t, ref Array value)\r\n        {\r\n            long[] countArray = CodeCountArray(ref value, v => LengthArray(v));\r\n            var c0 = countArray[0]; if (c0 < 1) return;\r\n            if (countArray.Length == 1)\r\n            {\r\n                for (long i = 0; i < c0; i++)\r\n                {\r\n                    object o = value.GetValue(i); Code(ref o);\r\n                }\r\n                return;\r\n            }\r\n            var c1 = countArray[1]; if (c1 < 1) return;\r\n            if (countArray.Length == 2)\r\n            {\r\n                for (long i = 0; i < c0; i++)\r\n                for (long j = 0; j < c1; j++)\r\n                {\r\n                    object o = value.GetValue(i, j); Code(ref o);\r\n                }\r\n                return;\r\n            }\r\n            var c2 = countArray[3]; if (c2 < 1) return;\r\n            if (countArray.Length == 3)\r\n            {\r\n                for (long i = 0; i < c0; i++)\r\n                for (long j = 0; j < c1; j++)\r\n                for (long k = 0; k < c2; k++)\r\n                {\r\n                    object o = value.GetValue(i, j, k); Code(ref o);\r\n                }\r\n                return;\r\n            }\r\n            throw new ArgumentException(\"cannot code arrays with more than 3 dimensions\");\r\n        }\r\n\r\n        public void CodeOld(Type t, ref Array value)\r\n        {\r\n            int count = CodeCount(ref value, v => v.Length);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                object o = value.GetValue(i);\r\n                Code(ref o);\r\n            }\r\n        }\r\n\r\n        public void Code(Type t, ref IList list)\r\n        {\r\n            int count = CodeCount(ref list, v => v.Count);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                object o = list[i];\r\n                Code(ref o);\r\n            }\r\n        }\r\n\r\n        public void Code(Type t, ref IDictionary dict)\r\n        {\r\n            int count = CodeCount(ref dict, v => v.Count);\r\n            if (count < 1) return;\r\n            Type[] subTypeArray = t.GetGenericArguments();\r\n            foreach (object k in dict.Keys)\r\n            {\r\n                var key = k;\r\n                TypeCoder.Write(this, subTypeArray[0], ref key);\r\n                var val = dict[key];\r\n                TypeCoder.Write(this, subTypeArray[1], ref val);\r\n            }\r\n        }\r\n\r\n        public void Code(Type t, ref ICountableDict dict)\r\n        {\r\n            long count = CodeCountLong(ref dict, v => v.LongCount);\r\n            if (count < 1L) return;\r\n            var keyType = dict.KeyType;\r\n            var valueType = dict.ValueType;\r\n            foreach (var pair in dict.ObjectPairs)\r\n            {\r\n                var key = pair.Item1;\r\n                TypeCoder.Write(this, keyType, ref key);\r\n                var val = pair.Item2;\r\n                TypeCoder.Write(this, valueType, ref val);\r\n            }\r\n        }\r\n\r\n        public void Code(Type t, ref ICountableDictSet dictSet)\r\n        {\r\n            long count = CodeCountLong(ref dictSet, v => v.LongCount);\r\n            if (count < 1L) return;\r\n            var keyType = dictSet.KeyType;\r\n            foreach (var obj in dictSet.Objects)\r\n            {\r\n                var key = obj;\r\n                TypeCoder.Write(this, keyType, ref key);\r\n            }\r\n        }\r\n\r\n        public void Code(Type t, ref IArrayVector value)\r\n        {\r\n            var array = value.Array; Code(value.ArrayType, ref array);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var length = value.Size; CodeLong(ref length);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void Code(Type t, ref IArrayMatrix value)\r\n        {\r\n            var array = value.Array; Code(value.ArrayType, ref array);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var length = value.Size; CodeV2l(ref length);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void Code(Type t, ref IArrayVolume value)\r\n        {\r\n            var array = value.Array; Code(value.ArrayType, ref array);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var length = value.Size; CodeV3l(ref length);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void Code(Type t, ref IArrayTensor4 value)\r\n        {\r\n            var array = value.Array; Code(value.ArrayType, ref array);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var length = value.Size; CodeV4l(ref length);\r\n            var delta = value.Delta; CodeV4l(ref delta);\r\n        }\r\n\r\n        public void Code(Type t, ref IArrayTensorN value)\r\n        {\r\n            var array = value.Array; Code(value.ArrayType, ref array);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var length = value.Size; CodeLongArray(ref length);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeHashSet(Type t, ref object obj)\r\n        {\r\n            throw new NotImplementedException(\"only possible whith a non-generic ISet interface)\");\r\n        }\r\n\r\n        public void CodeEnum(Type type, ref object value)\r\n        {\r\n            Type systemType = Enum.GetUnderlyingType(type);\r\n            var writer = TypeCoder.TypeWriterMap[systemType];\r\n            writer(this, value);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Code Primitives\r\n\r\n        public void CodeBool(ref bool value) { m_writer.Write(value); }\r\n        public void CodeByte(ref byte value) { m_writer.Write(value); }\r\n        public void CodeSByte(ref sbyte value) { m_writer.Write(value); }\r\n        public void CodeShort(ref short value) { m_writer.Write(value); }\r\n        public void CodeUShort(ref ushort value) { m_writer.Write(value); }\r\n        public void CodeInt(ref int value) { m_writer.Write(value); }\r\n        public void CodeUInt(ref uint value) { m_writer.Write(value); }\r\n        public void CodeLong(ref long value) { m_writer.Write(value); }\r\n        public void CodeULong(ref ulong value)  { m_writer.Write(value); }\r\n        public void CodeFloat(ref float value) { m_writer.Write(value); }\r\n        public void CodeDouble(ref double value) { m_writer.Write(value); }\r\n        public void CodeChar(ref char value) { m_writer.Write(value); }\r\n\r\n        public void CodeString(ref string value)\r\n        {\r\n            if (CodeNull(ref value)) return;\r\n            m_writer.Write(value);\r\n        }\r\n\r\n        public void CodeType(ref Type value)\r\n        {\r\n            string typeName;\r\n            TypeInfo ti;\r\n\r\n            if (TryGetTypeInfo(value, out ti))\r\n                typeName = ti.Name;\r\n            else\r\n                typeName = value.AssemblyQualifiedName;\r\n\r\n            m_writer.Write(typeName);\r\n        }\r\n\r\n        public void CodeGuid(ref Guid value) { m_writer.Write(value); }\r\n\r\n        public void CodeSymbol(ref Symbol value) { m_writer.Write(value); }\r\n\r\n        public void CodeGuidSymbol(ref Symbol value) { m_writer.WriteGuidSymbol(value); }\r\n\r\n        public void CodePositiveSymbol(ref Symbol value) { m_writer.WritePositiveSymbol(value); }\r\n\r\n        public void CodeIntSet(ref IntSet set)\r\n        {\r\n            int count = CodeCount(ref set, v => v.Count);\r\n            if (count < 1) return;\r\n            foreach (var item in set.Keys) m_writer.Write(item);\r\n        }\r\n\r\n        public void CodeSymbolSet(ref SymbolSet set)\r\n        {\r\n            int count = CodeCount(ref set, v => v.Count);\r\n            if (count < 1) return;\r\n            foreach (var item in set.Keys) m_writer.Write(item);\r\n        }\r\n\r\n        public void CodeFraction(ref Fraction value)\r\n        {\r\n            m_writer.Write(value.Numerator);\r\n            m_writer.Write(value.Denominator);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Code Arrays\r\n\r\n        public void CodeStructArray<T>(ref T[] value)\r\n            where T: struct\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBoolArray(ref bool[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) m_writer.Write(value[i]);\r\n        }\r\n\r\n        public void CodeByteArray(ref byte[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeSByteArray(ref sbyte[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeShortArray(ref short[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeUShortArray(ref ushort[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeIntArray(ref int[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeUIntArray(ref uint[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeLongArray(ref long[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeULongArray(ref ulong[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeFloatArray(ref float[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeDoubleArray(ref double[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeCharArray(ref char[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) m_writer.Write(value[i]);\r\n        }\r\n\r\n        public void CodeStringArray(ref string[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) m_writer.Write(value[i]);\r\n        }\r\n\r\n        public void CodeTypeArray(ref Type[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n\r\n            for (long i = 0; i < count; i++)\r\n            {\r\n                string typeName;\r\n                TypeInfo ti;\r\n\r\n                if (TryGetTypeInfo(value[i], out ti))\r\n                    typeName = ti.Name;\r\n                else\r\n                    typeName = value[i].AssemblyQualifiedName;\r\n\r\n                m_writer.Write(typeName);\r\n            }\r\n        }\r\n\r\n        public void CodeGuidArray(ref Guid[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeGuid(ref value[i]);\r\n        }\r\n\r\n        public void CodeSymbolArray(ref Symbol[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSymbol(ref value[i]);\r\n        }\r\n\r\n        public void CodeFractionArray(ref Fraction[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Code Lists\r\n\r\n        public void CodeStructList<T>(ref List<T> value)\r\n            where T : struct\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Bool_(ref List<bool> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) m_writer.Write(value[i]);\r\n        }\r\n\r\n        public void CodeList_of_Byte_(ref List<byte> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) m_writer.Write(value[i]);\r\n        }\r\n\r\n        public void CodeList_of_SByte_(ref List<sbyte> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Short_(ref List<short> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_UShort_(ref List<ushort> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Int_(ref List<int> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_UInt_(ref List<uint> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Long_(ref List<long> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_ULong_(ref List<ulong> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Float_(ref List<float> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Double_(ref List<double> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Char_(ref List<char> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) m_writer.Write(value[i]);\r\n        }\r\n\r\n        public void CodeList_of_String_(ref List<string> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) m_writer.Write(value[i]);\r\n        }\r\n\r\n        public void CodeList_of_Type_(ref List<Type> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                string typeName;\r\n                TypeInfo ti;\r\n\r\n                if (TryGetTypeInfo(value[i], out ti))\r\n                    typeName = ti.Name;\r\n                else\r\n                    typeName = value[i].AssemblyQualifiedName;\r\n\r\n                m_writer.Write(typeName);\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Guid_(ref List<Guid> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeGuid(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Symbol_(ref List<Symbol> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeSymbol(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Fraction_(ref List<Fraction> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region IDisposable Members\r\n\r\n        public void Dispose()\r\n        {\r\n            var position = m_writer.BaseStream.Position;\r\n\r\n            m_size = position - m_startPosition;\r\n            m_writer.BaseStream.Position = m_sizePosition;\r\n            m_writer.Write(m_size);\r\n            m_writer.BaseStream.Position = position;\r\n\r\n            if (m_disposeStream)\r\n                m_writer.BaseStream.Dispose();\r\n            else\r\n                m_writer.BaseStream.Flush();\r\n        }\r\n\r\n        #endregion    \r\n\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/BinaryWritingCoder_auto.cs",
    "content": "using Aardvark.Base;\r\nusing System;\r\nusing System.Collections.Generic;\r\n\r\nnamespace Aardvark.Base.Coder\r\n{\r\n    // AUTO GENERATED CODE - DO NOT CHANGE!\r\n\r\n    public partial class BinaryWritingCoder\r\n    {\r\n        #region Vectors\r\n\r\n        public void CodeV2i(ref V2i value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n        }\r\n\r\n        public void CodeV2ui(ref V2ui value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n        }\r\n\r\n        public void CodeV2l(ref V2l value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n        }\r\n\r\n        public void CodeV2f(ref V2f value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n        }\r\n\r\n        public void CodeV2d(ref V2d value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n        }\r\n\r\n        public void CodeV3i(ref V3i value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n        }\r\n\r\n        public void CodeV3ui(ref V3ui value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n        }\r\n\r\n        public void CodeV3l(ref V3l value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n        }\r\n\r\n        public void CodeV3f(ref V3f value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n        }\r\n\r\n        public void CodeV3d(ref V3d value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n        }\r\n\r\n        public void CodeV4i(ref V4i value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n            m_writer.Write(value.W);\r\n        }\r\n\r\n        public void CodeV4ui(ref V4ui value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n            m_writer.Write(value.W);\r\n        }\r\n\r\n        public void CodeV4l(ref V4l value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n            m_writer.Write(value.W);\r\n        }\r\n\r\n        public void CodeV4f(ref V4f value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n            m_writer.Write(value.W);\r\n        }\r\n\r\n        public void CodeV4d(ref V4d value)\r\n        {\r\n            m_writer.Write(value.X);\r\n            m_writer.Write(value.Y);\r\n            m_writer.Write(value.Z);\r\n            m_writer.Write(value.W);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Matrices\r\n\r\n        public void CodeM22i(ref M22i value) { m_writer.Write(value); }\r\n        public void CodeM22l(ref M22l value) { m_writer.Write(value); }\r\n        public void CodeM22f(ref M22f value) { m_writer.Write(value); }\r\n        public void CodeM22d(ref M22d value) { m_writer.Write(value); }\r\n        public void CodeM23i(ref M23i value) { m_writer.Write(value); }\r\n        public void CodeM23l(ref M23l value) { m_writer.Write(value); }\r\n        public void CodeM23f(ref M23f value) { m_writer.Write(value); }\r\n        public void CodeM23d(ref M23d value) { m_writer.Write(value); }\r\n        public void CodeM33i(ref M33i value) { m_writer.Write(value); }\r\n        public void CodeM33l(ref M33l value) { m_writer.Write(value); }\r\n        public void CodeM33f(ref M33f value) { m_writer.Write(value); }\r\n        public void CodeM33d(ref M33d value) { m_writer.Write(value); }\r\n        public void CodeM34i(ref M34i value) { m_writer.Write(value); }\r\n        public void CodeM34l(ref M34l value) { m_writer.Write(value); }\r\n        public void CodeM34f(ref M34f value) { m_writer.Write(value); }\r\n        public void CodeM34d(ref M34d value) { m_writer.Write(value); }\r\n        public void CodeM44i(ref M44i value) { m_writer.Write(value); }\r\n        public void CodeM44l(ref M44l value) { m_writer.Write(value); }\r\n        public void CodeM44f(ref M44f value) { m_writer.Write(value); }\r\n        public void CodeM44d(ref M44d value) { m_writer.Write(value); }\r\n\r\n        #endregion\r\n\r\n        #region Ranges and Boxes\r\n\r\n        public void CodeRange1b(ref Range1b value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1sb(ref Range1sb value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1s(ref Range1s value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1us(ref Range1us value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1i(ref Range1i value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1ui(ref Range1ui value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1l(ref Range1l value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1ul(ref Range1ul value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1f(ref Range1f value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeRange1d(ref Range1d value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeBox2i(ref Box2i value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeBox2l(ref Box2l value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeBox2f(ref Box2f value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeBox2d(ref Box2d value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeBox3i(ref Box3i value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeBox3l(ref Box3l value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeBox3f(ref Box3f value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        public void CodeBox3d(ref Box3d value)\r\n        {\r\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Geometry types\r\n\r\n        public void CodeCircle2f(ref Circle2f v)\r\n        {\r\n            CodeV2f(ref v.Center); CodeFloat(ref v.Radius);\r\n        }\r\n\r\n        public void CodeLine2f(ref Line2f v)\r\n        {\r\n            CodeV2f(ref v.P0); CodeV2f(ref v.P1);\r\n        }\r\n\r\n        public void CodeLine3f(ref Line3f v)\r\n        {\r\n            CodeV3f(ref v.P0); CodeV3f(ref v.P1);\r\n        }\r\n\r\n        public void CodePlane2f(ref Plane2f v)\r\n        {\r\n            CodeV2f(ref v.Normal); CodeFloat(ref v.Distance);\r\n        }\r\n\r\n        public void CodePlane3f(ref Plane3f v)\r\n        {\r\n            CodeV3f(ref v.Normal); CodeFloat(ref v.Distance);\r\n        }\r\n\r\n        public void CodePlaneWithPoint3f(ref PlaneWithPoint3f v)\r\n        {\r\n            CodeV3f(ref v.Normal); CodeV3f(ref v.Point);\r\n        }\r\n\r\n        public void CodeQuad2f(ref Quad2f v)\r\n        {\r\n            CodeV2f(ref v.P0); CodeV2f(ref v.P1); CodeV2f(ref v.P2); CodeV2f(ref v.P3);\r\n        }\r\n\r\n        public void CodeQuad3f(ref Quad3f v)\r\n        {\r\n            CodeV3f(ref v.P0); CodeV3f(ref v.P1); CodeV3f(ref v.P2); CodeV3f(ref v.P3);\r\n        }\r\n\r\n        public void CodeRay2f(ref Ray2f v)\r\n        {\r\n            CodeV2f(ref v.Origin); CodeV2f(ref v.Direction);\r\n        }\r\n\r\n        public void CodeRay3f(ref Ray3f v)\r\n        {\r\n            CodeV3f(ref v.Origin); CodeV3f(ref v.Direction);\r\n        }\r\n\r\n        public void CodeSphere3f(ref Sphere3f v)\r\n        {\r\n            CodeV3f(ref v.Center); CodeFloat(ref v.Radius);\r\n        }\r\n\r\n        public void CodeTriangle2f(ref Triangle2f v)\r\n        {\r\n            CodeV2f(ref v.P0); CodeV2f(ref v.P1); CodeV2f(ref v.P2);\r\n        }\r\n\r\n        public void CodeTriangle3f(ref Triangle3f v)\r\n        {\r\n            CodeV3f(ref v.P0); CodeV3f(ref v.P1); CodeV3f(ref v.P2);\r\n        }\r\n\r\n        public void CodeCircle2d(ref Circle2d v)\r\n        {\r\n            CodeV2d(ref v.Center); CodeDouble(ref v.Radius);\r\n        }\r\n\r\n        public void CodeLine2d(ref Line2d v)\r\n        {\r\n            CodeV2d(ref v.P0); CodeV2d(ref v.P1);\r\n        }\r\n\r\n        public void CodeLine3d(ref Line3d v)\r\n        {\r\n            CodeV3d(ref v.P0); CodeV3d(ref v.P1);\r\n        }\r\n\r\n        public void CodePlane2d(ref Plane2d v)\r\n        {\r\n            CodeV2d(ref v.Normal); CodeDouble(ref v.Distance);\r\n        }\r\n\r\n        public void CodePlane3d(ref Plane3d v)\r\n        {\r\n            CodeV3d(ref v.Normal); CodeDouble(ref v.Distance);\r\n        }\r\n\r\n        public void CodePlaneWithPoint3d(ref PlaneWithPoint3d v)\r\n        {\r\n            CodeV3d(ref v.Normal); CodeV3d(ref v.Point);\r\n        }\r\n\r\n        public void CodeQuad2d(ref Quad2d v)\r\n        {\r\n            CodeV2d(ref v.P0); CodeV2d(ref v.P1); CodeV2d(ref v.P2); CodeV2d(ref v.P3);\r\n        }\r\n\r\n        public void CodeQuad3d(ref Quad3d v)\r\n        {\r\n            CodeV3d(ref v.P0); CodeV3d(ref v.P1); CodeV3d(ref v.P2); CodeV3d(ref v.P3);\r\n        }\r\n\r\n        public void CodeRay2d(ref Ray2d v)\r\n        {\r\n            CodeV2d(ref v.Origin); CodeV2d(ref v.Direction);\r\n        }\r\n\r\n        public void CodeRay3d(ref Ray3d v)\r\n        {\r\n            CodeV3d(ref v.Origin); CodeV3d(ref v.Direction);\r\n        }\r\n\r\n        public void CodeSphere3d(ref Sphere3d v)\r\n        {\r\n            CodeV3d(ref v.Center); CodeDouble(ref v.Radius);\r\n        }\r\n\r\n        public void CodeTriangle2d(ref Triangle2d v)\r\n        {\r\n            CodeV2d(ref v.P0); CodeV2d(ref v.P1); CodeV2d(ref v.P2);\r\n        }\r\n\r\n        public void CodeTriangle3d(ref Triangle3d v)\r\n        {\r\n            CodeV3d(ref v.P0); CodeV3d(ref v.P1); CodeV3d(ref v.P2);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Colors\r\n\r\n        public void CodeC3b(ref C3b value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n        }\r\n\r\n        public void CodeC3us(ref C3us value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n        }\r\n\r\n        public void CodeC3ui(ref C3ui value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n        }\r\n\r\n        public void CodeC3f(ref C3f value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n        }\r\n\r\n        public void CodeC3d(ref C3d value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n        }\r\n\r\n        public void CodeC4b(ref C4b value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n            m_writer.Write(value.A);\r\n        }\r\n\r\n        public void CodeC4us(ref C4us value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n            m_writer.Write(value.A);\r\n        }\r\n\r\n        public void CodeC4ui(ref C4ui value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n            m_writer.Write(value.A);\r\n        }\r\n\r\n        public void CodeC4f(ref C4f value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n            m_writer.Write(value.A);\r\n        }\r\n\r\n        public void CodeC4d(ref C4d value)\r\n        {\r\n            m_writer.Write(value.R);\r\n            m_writer.Write(value.G);\r\n            m_writer.Write(value.B);\r\n            m_writer.Write(value.A);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Trafos\r\n\r\n        public void CodeEuclidean3f(ref Euclidean3f value) { m_writer.Write(value); }\r\n        public void CodeEuclidean3d(ref Euclidean3d value) { m_writer.Write(value); }\r\n        public void CodeRot2f(ref Rot2f value) { m_writer.Write(value); }\r\n        public void CodeRot2d(ref Rot2d value) { m_writer.Write(value); }\r\n        public void CodeRot3f(ref Rot3f value) { m_writer.Write(value); }\r\n        public void CodeRot3d(ref Rot3d value) { m_writer.Write(value); }\r\n        public void CodeScale3f(ref Scale3f value) { m_writer.Write(value); }\r\n        public void CodeScale3d(ref Scale3d value) { m_writer.Write(value); }\r\n        public void CodeShift3f(ref Shift3f value) { m_writer.Write(value); }\r\n        public void CodeShift3d(ref Shift3d value) { m_writer.Write(value); }\r\n        public void CodeTrafo2f(ref Trafo2f value) { m_writer.Write(value); }\r\n        public void CodeTrafo2d(ref Trafo2d value) { m_writer.Write(value); }\r\n        public void CodeTrafo3f(ref Trafo3f value) { m_writer.Write(value); }\r\n        public void CodeTrafo3d(ref Trafo3d value) { m_writer.Write(value); }\r\n\r\n        #endregion\r\n\r\n        #region Tensors\r\n\r\n        public void CodeVector_of_Byte_(ref Vector<byte> value)\r\n        {\r\n            var data = value.Data; CodeByteArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_SByte_(ref Vector<sbyte> value)\r\n        {\r\n            var data = value.Data; CodeSByteArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Short_(ref Vector<short> value)\r\n        {\r\n            var data = value.Data; CodeShortArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_UShort_(ref Vector<ushort> value)\r\n        {\r\n            var data = value.Data; CodeUShortArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Int_(ref Vector<int> value)\r\n        {\r\n            var data = value.Data; CodeIntArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_UInt_(ref Vector<uint> value)\r\n        {\r\n            var data = value.Data; CodeUIntArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Long_(ref Vector<long> value)\r\n        {\r\n            var data = value.Data; CodeLongArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_ULong_(ref Vector<ulong> value)\r\n        {\r\n            var data = value.Data; CodeULongArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Float_(ref Vector<float> value)\r\n        {\r\n            var data = value.Data; CodeFloatArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Double_(ref Vector<double> value)\r\n        {\r\n            var data = value.Data; CodeDoubleArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_(ref Vector<Fraction> value)\r\n        {\r\n            var data = value.Data; CodeFractionArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2i_(ref Vector<V2i> value)\r\n        {\r\n            var data = value.Data; CodeV2iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2l_(ref Vector<V2l> value)\r\n        {\r\n            var data = value.Data; CodeV2lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2f_(ref Vector<V2f> value)\r\n        {\r\n            var data = value.Data; CodeV2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2d_(ref Vector<V2d> value)\r\n        {\r\n            var data = value.Data; CodeV2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3i_(ref Vector<V3i> value)\r\n        {\r\n            var data = value.Data; CodeV3iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3l_(ref Vector<V3l> value)\r\n        {\r\n            var data = value.Data; CodeV3lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3f_(ref Vector<V3f> value)\r\n        {\r\n            var data = value.Data; CodeV3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3d_(ref Vector<V3d> value)\r\n        {\r\n            var data = value.Data; CodeV3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4i_(ref Vector<V4i> value)\r\n        {\r\n            var data = value.Data; CodeV4iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4l_(ref Vector<V4l> value)\r\n        {\r\n            var data = value.Data; CodeV4lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4f_(ref Vector<V4f> value)\r\n        {\r\n            var data = value.Data; CodeV4fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4d_(ref Vector<V4d> value)\r\n        {\r\n            var data = value.Data; CodeV4dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22i_(ref Vector<M22i> value)\r\n        {\r\n            var data = value.Data; CodeM22iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22l_(ref Vector<M22l> value)\r\n        {\r\n            var data = value.Data; CodeM22lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22f_(ref Vector<M22f> value)\r\n        {\r\n            var data = value.Data; CodeM22fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22d_(ref Vector<M22d> value)\r\n        {\r\n            var data = value.Data; CodeM22dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23i_(ref Vector<M23i> value)\r\n        {\r\n            var data = value.Data; CodeM23iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23l_(ref Vector<M23l> value)\r\n        {\r\n            var data = value.Data; CodeM23lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23f_(ref Vector<M23f> value)\r\n        {\r\n            var data = value.Data; CodeM23fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23d_(ref Vector<M23d> value)\r\n        {\r\n            var data = value.Data; CodeM23dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33i_(ref Vector<M33i> value)\r\n        {\r\n            var data = value.Data; CodeM33iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33l_(ref Vector<M33l> value)\r\n        {\r\n            var data = value.Data; CodeM33lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33f_(ref Vector<M33f> value)\r\n        {\r\n            var data = value.Data; CodeM33fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33d_(ref Vector<M33d> value)\r\n        {\r\n            var data = value.Data; CodeM33dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34i_(ref Vector<M34i> value)\r\n        {\r\n            var data = value.Data; CodeM34iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34l_(ref Vector<M34l> value)\r\n        {\r\n            var data = value.Data; CodeM34lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34f_(ref Vector<M34f> value)\r\n        {\r\n            var data = value.Data; CodeM34fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34d_(ref Vector<M34d> value)\r\n        {\r\n            var data = value.Data; CodeM34dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44i_(ref Vector<M44i> value)\r\n        {\r\n            var data = value.Data; CodeM44iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44l_(ref Vector<M44l> value)\r\n        {\r\n            var data = value.Data; CodeM44lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44f_(ref Vector<M44f> value)\r\n        {\r\n            var data = value.Data; CodeM44fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44d_(ref Vector<M44d> value)\r\n        {\r\n            var data = value.Data; CodeM44dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3b_(ref Vector<C3b> value)\r\n        {\r\n            var data = value.Data; CodeC3bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3us_(ref Vector<C3us> value)\r\n        {\r\n            var data = value.Data; CodeC3usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_(ref Vector<C3ui> value)\r\n        {\r\n            var data = value.Data; CodeC3uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3f_(ref Vector<C3f> value)\r\n        {\r\n            var data = value.Data; CodeC3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3d_(ref Vector<C3d> value)\r\n        {\r\n            var data = value.Data; CodeC3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4b_(ref Vector<C4b> value)\r\n        {\r\n            var data = value.Data; CodeC4bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4us_(ref Vector<C4us> value)\r\n        {\r\n            var data = value.Data; CodeC4usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_(ref Vector<C4ui> value)\r\n        {\r\n            var data = value.Data; CodeC4uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4f_(ref Vector<C4f> value)\r\n        {\r\n            var data = value.Data; CodeC4fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4d_(ref Vector<C4d> value)\r\n        {\r\n            var data = value.Data; CodeC4dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_(ref Vector<Range1b> value)\r\n        {\r\n            var data = value.Data; CodeRange1bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_(ref Vector<Range1sb> value)\r\n        {\r\n            var data = value.Data; CodeRange1sbArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_(ref Vector<Range1s> value)\r\n        {\r\n            var data = value.Data; CodeRange1sArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_(ref Vector<Range1us> value)\r\n        {\r\n            var data = value.Data; CodeRange1usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_(ref Vector<Range1i> value)\r\n        {\r\n            var data = value.Data; CodeRange1iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_(ref Vector<Range1ui> value)\r\n        {\r\n            var data = value.Data; CodeRange1uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_(ref Vector<Range1l> value)\r\n        {\r\n            var data = value.Data; CodeRange1lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_(ref Vector<Range1ul> value)\r\n        {\r\n            var data = value.Data; CodeRange1ulArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_(ref Vector<Range1f> value)\r\n        {\r\n            var data = value.Data; CodeRange1fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_(ref Vector<Range1d> value)\r\n        {\r\n            var data = value.Data; CodeRange1dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_(ref Vector<Box2i> value)\r\n        {\r\n            var data = value.Data; CodeBox2iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_(ref Vector<Box2l> value)\r\n        {\r\n            var data = value.Data; CodeBox2lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_(ref Vector<Box2f> value)\r\n        {\r\n            var data = value.Data; CodeBox2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_(ref Vector<Box2d> value)\r\n        {\r\n            var data = value.Data; CodeBox2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_(ref Vector<Box3i> value)\r\n        {\r\n            var data = value.Data; CodeBox3iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_(ref Vector<Box3l> value)\r\n        {\r\n            var data = value.Data; CodeBox3lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_(ref Vector<Box3f> value)\r\n        {\r\n            var data = value.Data; CodeBox3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_(ref Vector<Box3d> value)\r\n        {\r\n            var data = value.Data; CodeBox3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_(ref Vector<Euclidean3f> value)\r\n        {\r\n            var data = value.Data; CodeEuclidean3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_(ref Vector<Euclidean3d> value)\r\n        {\r\n            var data = value.Data; CodeEuclidean3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_(ref Vector<Rot2f> value)\r\n        {\r\n            var data = value.Data; CodeRot2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_(ref Vector<Rot2d> value)\r\n        {\r\n            var data = value.Data; CodeRot2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_(ref Vector<Rot3f> value)\r\n        {\r\n            var data = value.Data; CodeRot3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_(ref Vector<Rot3d> value)\r\n        {\r\n            var data = value.Data; CodeRot3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_(ref Vector<Scale3f> value)\r\n        {\r\n            var data = value.Data; CodeScale3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_(ref Vector<Scale3d> value)\r\n        {\r\n            var data = value.Data; CodeScale3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_(ref Vector<Shift3f> value)\r\n        {\r\n            var data = value.Data; CodeShift3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_(ref Vector<Shift3d> value)\r\n        {\r\n            var data = value.Data; CodeShift3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_(ref Vector<Trafo2f> value)\r\n        {\r\n            var data = value.Data; CodeTrafo2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_(ref Vector<Trafo2d> value)\r\n        {\r\n            var data = value.Data; CodeTrafo2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_(ref Vector<Trafo3f> value)\r\n        {\r\n            var data = value.Data; CodeTrafo3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_(ref Vector<Trafo3d> value)\r\n        {\r\n            var data = value.Data; CodeTrafo3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Bool_(ref Vector<bool> value)\r\n        {\r\n            var data = value.Data; CodeBoolArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Char_(ref Vector<char> value)\r\n        {\r\n            var data = value.Data; CodeCharArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_String_(ref Vector<string> value)\r\n        {\r\n            var data = value.Data; CodeStringArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Type_(ref Vector<Type> value)\r\n        {\r\n            var data = value.Data; CodeTypeArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Guid_(ref Vector<Guid> value)\r\n        {\r\n            var data = value.Data; CodeGuidArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_(ref Vector<Symbol> value)\r\n        {\r\n            var data = value.Data; CodeSymbolArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_(ref Vector<Circle2d> value)\r\n        {\r\n            var data = value.Data; CodeCircle2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_(ref Vector<Line2d> value)\r\n        {\r\n            var data = value.Data; CodeLine2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_(ref Vector<Line3d> value)\r\n        {\r\n            var data = value.Data; CodeLine3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_(ref Vector<Plane2d> value)\r\n        {\r\n            var data = value.Data; CodePlane2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_(ref Vector<Plane3d> value)\r\n        {\r\n            var data = value.Data; CodePlane3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_(ref Vector<PlaneWithPoint3d> value)\r\n        {\r\n            var data = value.Data; CodePlaneWithPoint3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_(ref Vector<Quad2d> value)\r\n        {\r\n            var data = value.Data; CodeQuad2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_(ref Vector<Quad3d> value)\r\n        {\r\n            var data = value.Data; CodeQuad3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_(ref Vector<Ray2d> value)\r\n        {\r\n            var data = value.Data; CodeRay2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_(ref Vector<Ray3d> value)\r\n        {\r\n            var data = value.Data; CodeRay3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_(ref Vector<Sphere3d> value)\r\n        {\r\n            var data = value.Data; CodeSphere3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_(ref Vector<Triangle2d> value)\r\n        {\r\n            var data = value.Data; CodeTriangle2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_(ref Vector<Triangle3d> value)\r\n        {\r\n            var data = value.Data; CodeTriangle3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_(ref Vector<Circle2f> value)\r\n        {\r\n            var data = value.Data; CodeCircle2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_(ref Vector<Line2f> value)\r\n        {\r\n            var data = value.Data; CodeLine2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_(ref Vector<Line3f> value)\r\n        {\r\n            var data = value.Data; CodeLine3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_(ref Vector<Plane2f> value)\r\n        {\r\n            var data = value.Data; CodePlane2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_(ref Vector<Plane3f> value)\r\n        {\r\n            var data = value.Data; CodePlane3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_(ref Vector<PlaneWithPoint3f> value)\r\n        {\r\n            var data = value.Data; CodePlaneWithPoint3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_(ref Vector<Quad2f> value)\r\n        {\r\n            var data = value.Data; CodeQuad2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_(ref Vector<Quad3f> value)\r\n        {\r\n            var data = value.Data; CodeQuad3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_(ref Vector<Ray2f> value)\r\n        {\r\n            var data = value.Data; CodeRay2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_(ref Vector<Ray3f> value)\r\n        {\r\n            var data = value.Data; CodeRay3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_(ref Vector<Sphere3f> value)\r\n        {\r\n            var data = value.Data; CodeSphere3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_(ref Vector<Triangle2f> value)\r\n        {\r\n            var data = value.Data; CodeTriangle2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_(ref Vector<Triangle3f> value)\r\n        {\r\n            var data = value.Data; CodeTriangle3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLong(ref size);\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_(ref Matrix<byte> value)\r\n        {\r\n            var data = value.Data; CodeByteArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_(ref Matrix<sbyte> value)\r\n        {\r\n            var data = value.Data; CodeSByteArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_(ref Matrix<short> value)\r\n        {\r\n            var data = value.Data; CodeShortArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_(ref Matrix<ushort> value)\r\n        {\r\n            var data = value.Data; CodeUShortArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_(ref Matrix<int> value)\r\n        {\r\n            var data = value.Data; CodeIntArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_(ref Matrix<uint> value)\r\n        {\r\n            var data = value.Data; CodeUIntArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_(ref Matrix<long> value)\r\n        {\r\n            var data = value.Data; CodeLongArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_(ref Matrix<ulong> value)\r\n        {\r\n            var data = value.Data; CodeULongArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_(ref Matrix<float> value)\r\n        {\r\n            var data = value.Data; CodeFloatArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_(ref Matrix<double> value)\r\n        {\r\n            var data = value.Data; CodeDoubleArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_(ref Matrix<Fraction> value)\r\n        {\r\n            var data = value.Data; CodeFractionArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_(ref Matrix<V2i> value)\r\n        {\r\n            var data = value.Data; CodeV2iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_(ref Matrix<V2l> value)\r\n        {\r\n            var data = value.Data; CodeV2lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_(ref Matrix<V2f> value)\r\n        {\r\n            var data = value.Data; CodeV2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_(ref Matrix<V2d> value)\r\n        {\r\n            var data = value.Data; CodeV2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_(ref Matrix<V3i> value)\r\n        {\r\n            var data = value.Data; CodeV3iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_(ref Matrix<V3l> value)\r\n        {\r\n            var data = value.Data; CodeV3lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_(ref Matrix<V3f> value)\r\n        {\r\n            var data = value.Data; CodeV3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_(ref Matrix<V3d> value)\r\n        {\r\n            var data = value.Data; CodeV3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_(ref Matrix<V4i> value)\r\n        {\r\n            var data = value.Data; CodeV4iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_(ref Matrix<V4l> value)\r\n        {\r\n            var data = value.Data; CodeV4lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_(ref Matrix<V4f> value)\r\n        {\r\n            var data = value.Data; CodeV4fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_(ref Matrix<V4d> value)\r\n        {\r\n            var data = value.Data; CodeV4dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_(ref Matrix<M22i> value)\r\n        {\r\n            var data = value.Data; CodeM22iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_(ref Matrix<M22l> value)\r\n        {\r\n            var data = value.Data; CodeM22lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_(ref Matrix<M22f> value)\r\n        {\r\n            var data = value.Data; CodeM22fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_(ref Matrix<M22d> value)\r\n        {\r\n            var data = value.Data; CodeM22dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_(ref Matrix<M23i> value)\r\n        {\r\n            var data = value.Data; CodeM23iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_(ref Matrix<M23l> value)\r\n        {\r\n            var data = value.Data; CodeM23lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_(ref Matrix<M23f> value)\r\n        {\r\n            var data = value.Data; CodeM23fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_(ref Matrix<M23d> value)\r\n        {\r\n            var data = value.Data; CodeM23dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_(ref Matrix<M33i> value)\r\n        {\r\n            var data = value.Data; CodeM33iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_(ref Matrix<M33l> value)\r\n        {\r\n            var data = value.Data; CodeM33lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_(ref Matrix<M33f> value)\r\n        {\r\n            var data = value.Data; CodeM33fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_(ref Matrix<M33d> value)\r\n        {\r\n            var data = value.Data; CodeM33dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_(ref Matrix<M34i> value)\r\n        {\r\n            var data = value.Data; CodeM34iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_(ref Matrix<M34l> value)\r\n        {\r\n            var data = value.Data; CodeM34lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_(ref Matrix<M34f> value)\r\n        {\r\n            var data = value.Data; CodeM34fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_(ref Matrix<M34d> value)\r\n        {\r\n            var data = value.Data; CodeM34dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_(ref Matrix<M44i> value)\r\n        {\r\n            var data = value.Data; CodeM44iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_(ref Matrix<M44l> value)\r\n        {\r\n            var data = value.Data; CodeM44lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_(ref Matrix<M44f> value)\r\n        {\r\n            var data = value.Data; CodeM44fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_(ref Matrix<M44d> value)\r\n        {\r\n            var data = value.Data; CodeM44dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_(ref Matrix<C3b> value)\r\n        {\r\n            var data = value.Data; CodeC3bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_(ref Matrix<C3us> value)\r\n        {\r\n            var data = value.Data; CodeC3usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_(ref Matrix<C3ui> value)\r\n        {\r\n            var data = value.Data; CodeC3uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_(ref Matrix<C3f> value)\r\n        {\r\n            var data = value.Data; CodeC3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_(ref Matrix<C3d> value)\r\n        {\r\n            var data = value.Data; CodeC3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_(ref Matrix<C4b> value)\r\n        {\r\n            var data = value.Data; CodeC4bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_(ref Matrix<C4us> value)\r\n        {\r\n            var data = value.Data; CodeC4usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_(ref Matrix<C4ui> value)\r\n        {\r\n            var data = value.Data; CodeC4uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_(ref Matrix<C4f> value)\r\n        {\r\n            var data = value.Data; CodeC4fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_(ref Matrix<C4d> value)\r\n        {\r\n            var data = value.Data; CodeC4dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_(ref Matrix<Range1b> value)\r\n        {\r\n            var data = value.Data; CodeRange1bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_(ref Matrix<Range1sb> value)\r\n        {\r\n            var data = value.Data; CodeRange1sbArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_(ref Matrix<Range1s> value)\r\n        {\r\n            var data = value.Data; CodeRange1sArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_(ref Matrix<Range1us> value)\r\n        {\r\n            var data = value.Data; CodeRange1usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_(ref Matrix<Range1i> value)\r\n        {\r\n            var data = value.Data; CodeRange1iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_(ref Matrix<Range1ui> value)\r\n        {\r\n            var data = value.Data; CodeRange1uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_(ref Matrix<Range1l> value)\r\n        {\r\n            var data = value.Data; CodeRange1lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_(ref Matrix<Range1ul> value)\r\n        {\r\n            var data = value.Data; CodeRange1ulArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_(ref Matrix<Range1f> value)\r\n        {\r\n            var data = value.Data; CodeRange1fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_(ref Matrix<Range1d> value)\r\n        {\r\n            var data = value.Data; CodeRange1dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_(ref Matrix<Box2i> value)\r\n        {\r\n            var data = value.Data; CodeBox2iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_(ref Matrix<Box2l> value)\r\n        {\r\n            var data = value.Data; CodeBox2lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_(ref Matrix<Box2f> value)\r\n        {\r\n            var data = value.Data; CodeBox2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_(ref Matrix<Box2d> value)\r\n        {\r\n            var data = value.Data; CodeBox2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_(ref Matrix<Box3i> value)\r\n        {\r\n            var data = value.Data; CodeBox3iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_(ref Matrix<Box3l> value)\r\n        {\r\n            var data = value.Data; CodeBox3lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_(ref Matrix<Box3f> value)\r\n        {\r\n            var data = value.Data; CodeBox3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_(ref Matrix<Box3d> value)\r\n        {\r\n            var data = value.Data; CodeBox3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_(ref Matrix<Euclidean3f> value)\r\n        {\r\n            var data = value.Data; CodeEuclidean3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_(ref Matrix<Euclidean3d> value)\r\n        {\r\n            var data = value.Data; CodeEuclidean3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_(ref Matrix<Rot2f> value)\r\n        {\r\n            var data = value.Data; CodeRot2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_(ref Matrix<Rot2d> value)\r\n        {\r\n            var data = value.Data; CodeRot2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_(ref Matrix<Rot3f> value)\r\n        {\r\n            var data = value.Data; CodeRot3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_(ref Matrix<Rot3d> value)\r\n        {\r\n            var data = value.Data; CodeRot3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_(ref Matrix<Scale3f> value)\r\n        {\r\n            var data = value.Data; CodeScale3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_(ref Matrix<Scale3d> value)\r\n        {\r\n            var data = value.Data; CodeScale3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_(ref Matrix<Shift3f> value)\r\n        {\r\n            var data = value.Data; CodeShift3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_(ref Matrix<Shift3d> value)\r\n        {\r\n            var data = value.Data; CodeShift3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_(ref Matrix<Trafo2f> value)\r\n        {\r\n            var data = value.Data; CodeTrafo2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_(ref Matrix<Trafo2d> value)\r\n        {\r\n            var data = value.Data; CodeTrafo2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_(ref Matrix<Trafo3f> value)\r\n        {\r\n            var data = value.Data; CodeTrafo3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_(ref Matrix<Trafo3d> value)\r\n        {\r\n            var data = value.Data; CodeTrafo3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_(ref Matrix<bool> value)\r\n        {\r\n            var data = value.Data; CodeBoolArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_(ref Matrix<char> value)\r\n        {\r\n            var data = value.Data; CodeCharArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_String_(ref Matrix<string> value)\r\n        {\r\n            var data = value.Data; CodeStringArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_(ref Matrix<Type> value)\r\n        {\r\n            var data = value.Data; CodeTypeArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_(ref Matrix<Guid> value)\r\n        {\r\n            var data = value.Data; CodeGuidArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_(ref Matrix<Symbol> value)\r\n        {\r\n            var data = value.Data; CodeSymbolArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_(ref Matrix<Circle2d> value)\r\n        {\r\n            var data = value.Data; CodeCircle2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_(ref Matrix<Line2d> value)\r\n        {\r\n            var data = value.Data; CodeLine2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_(ref Matrix<Line3d> value)\r\n        {\r\n            var data = value.Data; CodeLine3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_(ref Matrix<Plane2d> value)\r\n        {\r\n            var data = value.Data; CodePlane2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_(ref Matrix<Plane3d> value)\r\n        {\r\n            var data = value.Data; CodePlane3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_(ref Matrix<PlaneWithPoint3d> value)\r\n        {\r\n            var data = value.Data; CodePlaneWithPoint3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_(ref Matrix<Quad2d> value)\r\n        {\r\n            var data = value.Data; CodeQuad2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_(ref Matrix<Quad3d> value)\r\n        {\r\n            var data = value.Data; CodeQuad3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_(ref Matrix<Ray2d> value)\r\n        {\r\n            var data = value.Data; CodeRay2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_(ref Matrix<Ray3d> value)\r\n        {\r\n            var data = value.Data; CodeRay3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_(ref Matrix<Sphere3d> value)\r\n        {\r\n            var data = value.Data; CodeSphere3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_(ref Matrix<Triangle2d> value)\r\n        {\r\n            var data = value.Data; CodeTriangle2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_(ref Matrix<Triangle3d> value)\r\n        {\r\n            var data = value.Data; CodeTriangle3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_(ref Matrix<Circle2f> value)\r\n        {\r\n            var data = value.Data; CodeCircle2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_(ref Matrix<Line2f> value)\r\n        {\r\n            var data = value.Data; CodeLine2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_(ref Matrix<Line3f> value)\r\n        {\r\n            var data = value.Data; CodeLine3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_(ref Matrix<Plane2f> value)\r\n        {\r\n            var data = value.Data; CodePlane2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_(ref Matrix<Plane3f> value)\r\n        {\r\n            var data = value.Data; CodePlane3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_(ref Matrix<PlaneWithPoint3f> value)\r\n        {\r\n            var data = value.Data; CodePlaneWithPoint3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_(ref Matrix<Quad2f> value)\r\n        {\r\n            var data = value.Data; CodeQuad2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_(ref Matrix<Quad3f> value)\r\n        {\r\n            var data = value.Data; CodeQuad3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_(ref Matrix<Ray2f> value)\r\n        {\r\n            var data = value.Data; CodeRay2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_(ref Matrix<Ray3f> value)\r\n        {\r\n            var data = value.Data; CodeRay3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_(ref Matrix<Sphere3f> value)\r\n        {\r\n            var data = value.Data; CodeSphere3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_(ref Matrix<Triangle2f> value)\r\n        {\r\n            var data = value.Data; CodeTriangle2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_(ref Matrix<Triangle3f> value)\r\n        {\r\n            var data = value.Data; CodeTriangle3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV2l(ref size);\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_(ref Volume<byte> value)\r\n        {\r\n            var data = value.Data; CodeByteArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_(ref Volume<sbyte> value)\r\n        {\r\n            var data = value.Data; CodeSByteArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Short_(ref Volume<short> value)\r\n        {\r\n            var data = value.Data; CodeShortArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_(ref Volume<ushort> value)\r\n        {\r\n            var data = value.Data; CodeUShortArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Int_(ref Volume<int> value)\r\n        {\r\n            var data = value.Data; CodeIntArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_(ref Volume<uint> value)\r\n        {\r\n            var data = value.Data; CodeUIntArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Long_(ref Volume<long> value)\r\n        {\r\n            var data = value.Data; CodeLongArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_(ref Volume<ulong> value)\r\n        {\r\n            var data = value.Data; CodeULongArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Float_(ref Volume<float> value)\r\n        {\r\n            var data = value.Data; CodeFloatArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Double_(ref Volume<double> value)\r\n        {\r\n            var data = value.Data; CodeDoubleArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_(ref Volume<Fraction> value)\r\n        {\r\n            var data = value.Data; CodeFractionArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_(ref Volume<V2i> value)\r\n        {\r\n            var data = value.Data; CodeV2iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_(ref Volume<V2l> value)\r\n        {\r\n            var data = value.Data; CodeV2lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_(ref Volume<V2f> value)\r\n        {\r\n            var data = value.Data; CodeV2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_(ref Volume<V2d> value)\r\n        {\r\n            var data = value.Data; CodeV2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_(ref Volume<V3i> value)\r\n        {\r\n            var data = value.Data; CodeV3iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_(ref Volume<V3l> value)\r\n        {\r\n            var data = value.Data; CodeV3lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_(ref Volume<V3f> value)\r\n        {\r\n            var data = value.Data; CodeV3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_(ref Volume<V3d> value)\r\n        {\r\n            var data = value.Data; CodeV3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_(ref Volume<V4i> value)\r\n        {\r\n            var data = value.Data; CodeV4iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_(ref Volume<V4l> value)\r\n        {\r\n            var data = value.Data; CodeV4lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_(ref Volume<V4f> value)\r\n        {\r\n            var data = value.Data; CodeV4fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_(ref Volume<V4d> value)\r\n        {\r\n            var data = value.Data; CodeV4dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_(ref Volume<M22i> value)\r\n        {\r\n            var data = value.Data; CodeM22iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_(ref Volume<M22l> value)\r\n        {\r\n            var data = value.Data; CodeM22lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_(ref Volume<M22f> value)\r\n        {\r\n            var data = value.Data; CodeM22fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_(ref Volume<M22d> value)\r\n        {\r\n            var data = value.Data; CodeM22dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_(ref Volume<M23i> value)\r\n        {\r\n            var data = value.Data; CodeM23iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_(ref Volume<M23l> value)\r\n        {\r\n            var data = value.Data; CodeM23lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_(ref Volume<M23f> value)\r\n        {\r\n            var data = value.Data; CodeM23fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_(ref Volume<M23d> value)\r\n        {\r\n            var data = value.Data; CodeM23dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_(ref Volume<M33i> value)\r\n        {\r\n            var data = value.Data; CodeM33iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_(ref Volume<M33l> value)\r\n        {\r\n            var data = value.Data; CodeM33lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_(ref Volume<M33f> value)\r\n        {\r\n            var data = value.Data; CodeM33fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_(ref Volume<M33d> value)\r\n        {\r\n            var data = value.Data; CodeM33dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_(ref Volume<M34i> value)\r\n        {\r\n            var data = value.Data; CodeM34iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_(ref Volume<M34l> value)\r\n        {\r\n            var data = value.Data; CodeM34lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_(ref Volume<M34f> value)\r\n        {\r\n            var data = value.Data; CodeM34fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_(ref Volume<M34d> value)\r\n        {\r\n            var data = value.Data; CodeM34dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_(ref Volume<M44i> value)\r\n        {\r\n            var data = value.Data; CodeM44iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_(ref Volume<M44l> value)\r\n        {\r\n            var data = value.Data; CodeM44lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_(ref Volume<M44f> value)\r\n        {\r\n            var data = value.Data; CodeM44fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_(ref Volume<M44d> value)\r\n        {\r\n            var data = value.Data; CodeM44dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_(ref Volume<C3b> value)\r\n        {\r\n            var data = value.Data; CodeC3bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_(ref Volume<C3us> value)\r\n        {\r\n            var data = value.Data; CodeC3usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_(ref Volume<C3ui> value)\r\n        {\r\n            var data = value.Data; CodeC3uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_(ref Volume<C3f> value)\r\n        {\r\n            var data = value.Data; CodeC3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_(ref Volume<C3d> value)\r\n        {\r\n            var data = value.Data; CodeC3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_(ref Volume<C4b> value)\r\n        {\r\n            var data = value.Data; CodeC4bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_(ref Volume<C4us> value)\r\n        {\r\n            var data = value.Data; CodeC4usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_(ref Volume<C4ui> value)\r\n        {\r\n            var data = value.Data; CodeC4uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_(ref Volume<C4f> value)\r\n        {\r\n            var data = value.Data; CodeC4fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_(ref Volume<C4d> value)\r\n        {\r\n            var data = value.Data; CodeC4dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_(ref Volume<Range1b> value)\r\n        {\r\n            var data = value.Data; CodeRange1bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_(ref Volume<Range1sb> value)\r\n        {\r\n            var data = value.Data; CodeRange1sbArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_(ref Volume<Range1s> value)\r\n        {\r\n            var data = value.Data; CodeRange1sArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_(ref Volume<Range1us> value)\r\n        {\r\n            var data = value.Data; CodeRange1usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_(ref Volume<Range1i> value)\r\n        {\r\n            var data = value.Data; CodeRange1iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_(ref Volume<Range1ui> value)\r\n        {\r\n            var data = value.Data; CodeRange1uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_(ref Volume<Range1l> value)\r\n        {\r\n            var data = value.Data; CodeRange1lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_(ref Volume<Range1ul> value)\r\n        {\r\n            var data = value.Data; CodeRange1ulArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_(ref Volume<Range1f> value)\r\n        {\r\n            var data = value.Data; CodeRange1fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_(ref Volume<Range1d> value)\r\n        {\r\n            var data = value.Data; CodeRange1dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_(ref Volume<Box2i> value)\r\n        {\r\n            var data = value.Data; CodeBox2iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_(ref Volume<Box2l> value)\r\n        {\r\n            var data = value.Data; CodeBox2lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_(ref Volume<Box2f> value)\r\n        {\r\n            var data = value.Data; CodeBox2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_(ref Volume<Box2d> value)\r\n        {\r\n            var data = value.Data; CodeBox2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_(ref Volume<Box3i> value)\r\n        {\r\n            var data = value.Data; CodeBox3iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_(ref Volume<Box3l> value)\r\n        {\r\n            var data = value.Data; CodeBox3lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_(ref Volume<Box3f> value)\r\n        {\r\n            var data = value.Data; CodeBox3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_(ref Volume<Box3d> value)\r\n        {\r\n            var data = value.Data; CodeBox3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_(ref Volume<Euclidean3f> value)\r\n        {\r\n            var data = value.Data; CodeEuclidean3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_(ref Volume<Euclidean3d> value)\r\n        {\r\n            var data = value.Data; CodeEuclidean3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_(ref Volume<Rot2f> value)\r\n        {\r\n            var data = value.Data; CodeRot2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_(ref Volume<Rot2d> value)\r\n        {\r\n            var data = value.Data; CodeRot2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_(ref Volume<Rot3f> value)\r\n        {\r\n            var data = value.Data; CodeRot3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_(ref Volume<Rot3d> value)\r\n        {\r\n            var data = value.Data; CodeRot3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_(ref Volume<Scale3f> value)\r\n        {\r\n            var data = value.Data; CodeScale3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_(ref Volume<Scale3d> value)\r\n        {\r\n            var data = value.Data; CodeScale3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_(ref Volume<Shift3f> value)\r\n        {\r\n            var data = value.Data; CodeShift3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_(ref Volume<Shift3d> value)\r\n        {\r\n            var data = value.Data; CodeShift3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_(ref Volume<Trafo2f> value)\r\n        {\r\n            var data = value.Data; CodeTrafo2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_(ref Volume<Trafo2d> value)\r\n        {\r\n            var data = value.Data; CodeTrafo2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_(ref Volume<Trafo3f> value)\r\n        {\r\n            var data = value.Data; CodeTrafo3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_(ref Volume<Trafo3d> value)\r\n        {\r\n            var data = value.Data; CodeTrafo3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_(ref Volume<bool> value)\r\n        {\r\n            var data = value.Data; CodeBoolArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Char_(ref Volume<char> value)\r\n        {\r\n            var data = value.Data; CodeCharArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_String_(ref Volume<string> value)\r\n        {\r\n            var data = value.Data; CodeStringArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Type_(ref Volume<Type> value)\r\n        {\r\n            var data = value.Data; CodeTypeArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_(ref Volume<Guid> value)\r\n        {\r\n            var data = value.Data; CodeGuidArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_(ref Volume<Symbol> value)\r\n        {\r\n            var data = value.Data; CodeSymbolArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_(ref Volume<Circle2d> value)\r\n        {\r\n            var data = value.Data; CodeCircle2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_(ref Volume<Line2d> value)\r\n        {\r\n            var data = value.Data; CodeLine2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_(ref Volume<Line3d> value)\r\n        {\r\n            var data = value.Data; CodeLine3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_(ref Volume<Plane2d> value)\r\n        {\r\n            var data = value.Data; CodePlane2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_(ref Volume<Plane3d> value)\r\n        {\r\n            var data = value.Data; CodePlane3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_(ref Volume<PlaneWithPoint3d> value)\r\n        {\r\n            var data = value.Data; CodePlaneWithPoint3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_(ref Volume<Quad2d> value)\r\n        {\r\n            var data = value.Data; CodeQuad2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_(ref Volume<Quad3d> value)\r\n        {\r\n            var data = value.Data; CodeQuad3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_(ref Volume<Ray2d> value)\r\n        {\r\n            var data = value.Data; CodeRay2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_(ref Volume<Ray3d> value)\r\n        {\r\n            var data = value.Data; CodeRay3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_(ref Volume<Sphere3d> value)\r\n        {\r\n            var data = value.Data; CodeSphere3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_(ref Volume<Triangle2d> value)\r\n        {\r\n            var data = value.Data; CodeTriangle2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_(ref Volume<Triangle3d> value)\r\n        {\r\n            var data = value.Data; CodeTriangle3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_(ref Volume<Circle2f> value)\r\n        {\r\n            var data = value.Data; CodeCircle2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_(ref Volume<Line2f> value)\r\n        {\r\n            var data = value.Data; CodeLine2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_(ref Volume<Line3f> value)\r\n        {\r\n            var data = value.Data; CodeLine3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_(ref Volume<Plane2f> value)\r\n        {\r\n            var data = value.Data; CodePlane2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_(ref Volume<Plane3f> value)\r\n        {\r\n            var data = value.Data; CodePlane3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_(ref Volume<PlaneWithPoint3f> value)\r\n        {\r\n            var data = value.Data; CodePlaneWithPoint3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_(ref Volume<Quad2f> value)\r\n        {\r\n            var data = value.Data; CodeQuad2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_(ref Volume<Quad3f> value)\r\n        {\r\n            var data = value.Data; CodeQuad3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_(ref Volume<Ray2f> value)\r\n        {\r\n            var data = value.Data; CodeRay2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_(ref Volume<Ray3f> value)\r\n        {\r\n            var data = value.Data; CodeRay3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_(ref Volume<Sphere3f> value)\r\n        {\r\n            var data = value.Data; CodeSphere3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_(ref Volume<Triangle2f> value)\r\n        {\r\n            var data = value.Data; CodeTriangle2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_(ref Volume<Triangle3f> value)\r\n        {\r\n            var data = value.Data; CodeTriangle3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeV3l(ref size);\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_(ref Tensor<byte> value)\r\n        {\r\n            var data = value.Data; CodeByteArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_(ref Tensor<sbyte> value)\r\n        {\r\n            var data = value.Data; CodeSByteArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Short_(ref Tensor<short> value)\r\n        {\r\n            var data = value.Data; CodeShortArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_(ref Tensor<ushort> value)\r\n        {\r\n            var data = value.Data; CodeUShortArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Int_(ref Tensor<int> value)\r\n        {\r\n            var data = value.Data; CodeIntArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_(ref Tensor<uint> value)\r\n        {\r\n            var data = value.Data; CodeUIntArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Long_(ref Tensor<long> value)\r\n        {\r\n            var data = value.Data; CodeLongArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_(ref Tensor<ulong> value)\r\n        {\r\n            var data = value.Data; CodeULongArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Float_(ref Tensor<float> value)\r\n        {\r\n            var data = value.Data; CodeFloatArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Double_(ref Tensor<double> value)\r\n        {\r\n            var data = value.Data; CodeDoubleArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_(ref Tensor<Fraction> value)\r\n        {\r\n            var data = value.Data; CodeFractionArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_(ref Tensor<V2i> value)\r\n        {\r\n            var data = value.Data; CodeV2iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_(ref Tensor<V2l> value)\r\n        {\r\n            var data = value.Data; CodeV2lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_(ref Tensor<V2f> value)\r\n        {\r\n            var data = value.Data; CodeV2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_(ref Tensor<V2d> value)\r\n        {\r\n            var data = value.Data; CodeV2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_(ref Tensor<V3i> value)\r\n        {\r\n            var data = value.Data; CodeV3iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_(ref Tensor<V3l> value)\r\n        {\r\n            var data = value.Data; CodeV3lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_(ref Tensor<V3f> value)\r\n        {\r\n            var data = value.Data; CodeV3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_(ref Tensor<V3d> value)\r\n        {\r\n            var data = value.Data; CodeV3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_(ref Tensor<V4i> value)\r\n        {\r\n            var data = value.Data; CodeV4iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_(ref Tensor<V4l> value)\r\n        {\r\n            var data = value.Data; CodeV4lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_(ref Tensor<V4f> value)\r\n        {\r\n            var data = value.Data; CodeV4fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_(ref Tensor<V4d> value)\r\n        {\r\n            var data = value.Data; CodeV4dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_(ref Tensor<M22i> value)\r\n        {\r\n            var data = value.Data; CodeM22iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_(ref Tensor<M22l> value)\r\n        {\r\n            var data = value.Data; CodeM22lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_(ref Tensor<M22f> value)\r\n        {\r\n            var data = value.Data; CodeM22fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_(ref Tensor<M22d> value)\r\n        {\r\n            var data = value.Data; CodeM22dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_(ref Tensor<M23i> value)\r\n        {\r\n            var data = value.Data; CodeM23iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_(ref Tensor<M23l> value)\r\n        {\r\n            var data = value.Data; CodeM23lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_(ref Tensor<M23f> value)\r\n        {\r\n            var data = value.Data; CodeM23fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_(ref Tensor<M23d> value)\r\n        {\r\n            var data = value.Data; CodeM23dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_(ref Tensor<M33i> value)\r\n        {\r\n            var data = value.Data; CodeM33iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_(ref Tensor<M33l> value)\r\n        {\r\n            var data = value.Data; CodeM33lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_(ref Tensor<M33f> value)\r\n        {\r\n            var data = value.Data; CodeM33fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_(ref Tensor<M33d> value)\r\n        {\r\n            var data = value.Data; CodeM33dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_(ref Tensor<M34i> value)\r\n        {\r\n            var data = value.Data; CodeM34iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_(ref Tensor<M34l> value)\r\n        {\r\n            var data = value.Data; CodeM34lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_(ref Tensor<M34f> value)\r\n        {\r\n            var data = value.Data; CodeM34fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_(ref Tensor<M34d> value)\r\n        {\r\n            var data = value.Data; CodeM34dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_(ref Tensor<M44i> value)\r\n        {\r\n            var data = value.Data; CodeM44iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_(ref Tensor<M44l> value)\r\n        {\r\n            var data = value.Data; CodeM44lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_(ref Tensor<M44f> value)\r\n        {\r\n            var data = value.Data; CodeM44fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_(ref Tensor<M44d> value)\r\n        {\r\n            var data = value.Data; CodeM44dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_(ref Tensor<C3b> value)\r\n        {\r\n            var data = value.Data; CodeC3bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_(ref Tensor<C3us> value)\r\n        {\r\n            var data = value.Data; CodeC3usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_(ref Tensor<C3ui> value)\r\n        {\r\n            var data = value.Data; CodeC3uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_(ref Tensor<C3f> value)\r\n        {\r\n            var data = value.Data; CodeC3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_(ref Tensor<C3d> value)\r\n        {\r\n            var data = value.Data; CodeC3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_(ref Tensor<C4b> value)\r\n        {\r\n            var data = value.Data; CodeC4bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_(ref Tensor<C4us> value)\r\n        {\r\n            var data = value.Data; CodeC4usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_(ref Tensor<C4ui> value)\r\n        {\r\n            var data = value.Data; CodeC4uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_(ref Tensor<C4f> value)\r\n        {\r\n            var data = value.Data; CodeC4fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_(ref Tensor<C4d> value)\r\n        {\r\n            var data = value.Data; CodeC4dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_(ref Tensor<Range1b> value)\r\n        {\r\n            var data = value.Data; CodeRange1bArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_(ref Tensor<Range1sb> value)\r\n        {\r\n            var data = value.Data; CodeRange1sbArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_(ref Tensor<Range1s> value)\r\n        {\r\n            var data = value.Data; CodeRange1sArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_(ref Tensor<Range1us> value)\r\n        {\r\n            var data = value.Data; CodeRange1usArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_(ref Tensor<Range1i> value)\r\n        {\r\n            var data = value.Data; CodeRange1iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_(ref Tensor<Range1ui> value)\r\n        {\r\n            var data = value.Data; CodeRange1uiArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_(ref Tensor<Range1l> value)\r\n        {\r\n            var data = value.Data; CodeRange1lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_(ref Tensor<Range1ul> value)\r\n        {\r\n            var data = value.Data; CodeRange1ulArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_(ref Tensor<Range1f> value)\r\n        {\r\n            var data = value.Data; CodeRange1fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_(ref Tensor<Range1d> value)\r\n        {\r\n            var data = value.Data; CodeRange1dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_(ref Tensor<Box2i> value)\r\n        {\r\n            var data = value.Data; CodeBox2iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_(ref Tensor<Box2l> value)\r\n        {\r\n            var data = value.Data; CodeBox2lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_(ref Tensor<Box2f> value)\r\n        {\r\n            var data = value.Data; CodeBox2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_(ref Tensor<Box2d> value)\r\n        {\r\n            var data = value.Data; CodeBox2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_(ref Tensor<Box3i> value)\r\n        {\r\n            var data = value.Data; CodeBox3iArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_(ref Tensor<Box3l> value)\r\n        {\r\n            var data = value.Data; CodeBox3lArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_(ref Tensor<Box3f> value)\r\n        {\r\n            var data = value.Data; CodeBox3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_(ref Tensor<Box3d> value)\r\n        {\r\n            var data = value.Data; CodeBox3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_(ref Tensor<Euclidean3f> value)\r\n        {\r\n            var data = value.Data; CodeEuclidean3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_(ref Tensor<Euclidean3d> value)\r\n        {\r\n            var data = value.Data; CodeEuclidean3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_(ref Tensor<Rot2f> value)\r\n        {\r\n            var data = value.Data; CodeRot2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_(ref Tensor<Rot2d> value)\r\n        {\r\n            var data = value.Data; CodeRot2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_(ref Tensor<Rot3f> value)\r\n        {\r\n            var data = value.Data; CodeRot3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_(ref Tensor<Rot3d> value)\r\n        {\r\n            var data = value.Data; CodeRot3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_(ref Tensor<Scale3f> value)\r\n        {\r\n            var data = value.Data; CodeScale3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_(ref Tensor<Scale3d> value)\r\n        {\r\n            var data = value.Data; CodeScale3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_(ref Tensor<Shift3f> value)\r\n        {\r\n            var data = value.Data; CodeShift3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_(ref Tensor<Shift3d> value)\r\n        {\r\n            var data = value.Data; CodeShift3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_(ref Tensor<Trafo2f> value)\r\n        {\r\n            var data = value.Data; CodeTrafo2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_(ref Tensor<Trafo2d> value)\r\n        {\r\n            var data = value.Data; CodeTrafo2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_(ref Tensor<Trafo3f> value)\r\n        {\r\n            var data = value.Data; CodeTrafo3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_(ref Tensor<Trafo3d> value)\r\n        {\r\n            var data = value.Data; CodeTrafo3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_(ref Tensor<bool> value)\r\n        {\r\n            var data = value.Data; CodeBoolArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Char_(ref Tensor<char> value)\r\n        {\r\n            var data = value.Data; CodeCharArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_String_(ref Tensor<string> value)\r\n        {\r\n            var data = value.Data; CodeStringArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Type_(ref Tensor<Type> value)\r\n        {\r\n            var data = value.Data; CodeTypeArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_(ref Tensor<Guid> value)\r\n        {\r\n            var data = value.Data; CodeGuidArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_(ref Tensor<Symbol> value)\r\n        {\r\n            var data = value.Data; CodeSymbolArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_(ref Tensor<Circle2d> value)\r\n        {\r\n            var data = value.Data; CodeCircle2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_(ref Tensor<Line2d> value)\r\n        {\r\n            var data = value.Data; CodeLine2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_(ref Tensor<Line3d> value)\r\n        {\r\n            var data = value.Data; CodeLine3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_(ref Tensor<Plane2d> value)\r\n        {\r\n            var data = value.Data; CodePlane2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_(ref Tensor<Plane3d> value)\r\n        {\r\n            var data = value.Data; CodePlane3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_(ref Tensor<PlaneWithPoint3d> value)\r\n        {\r\n            var data = value.Data; CodePlaneWithPoint3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_(ref Tensor<Quad2d> value)\r\n        {\r\n            var data = value.Data; CodeQuad2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_(ref Tensor<Quad3d> value)\r\n        {\r\n            var data = value.Data; CodeQuad3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_(ref Tensor<Ray2d> value)\r\n        {\r\n            var data = value.Data; CodeRay2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_(ref Tensor<Ray3d> value)\r\n        {\r\n            var data = value.Data; CodeRay3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_(ref Tensor<Sphere3d> value)\r\n        {\r\n            var data = value.Data; CodeSphere3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_(ref Tensor<Triangle2d> value)\r\n        {\r\n            var data = value.Data; CodeTriangle2dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_(ref Tensor<Triangle3d> value)\r\n        {\r\n            var data = value.Data; CodeTriangle3dArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_(ref Tensor<Circle2f> value)\r\n        {\r\n            var data = value.Data; CodeCircle2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_(ref Tensor<Line2f> value)\r\n        {\r\n            var data = value.Data; CodeLine2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_(ref Tensor<Line3f> value)\r\n        {\r\n            var data = value.Data; CodeLine3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_(ref Tensor<Plane2f> value)\r\n        {\r\n            var data = value.Data; CodePlane2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_(ref Tensor<Plane3f> value)\r\n        {\r\n            var data = value.Data; CodePlane3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_(ref Tensor<PlaneWithPoint3f> value)\r\n        {\r\n            var data = value.Data; CodePlaneWithPoint3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_(ref Tensor<Quad2f> value)\r\n        {\r\n            var data = value.Data; CodeQuad2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_(ref Tensor<Quad3f> value)\r\n        {\r\n            var data = value.Data; CodeQuad3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_(ref Tensor<Ray2f> value)\r\n        {\r\n            var data = value.Data; CodeRay2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_(ref Tensor<Ray3f> value)\r\n        {\r\n            var data = value.Data; CodeRay3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_(ref Tensor<Sphere3f> value)\r\n        {\r\n            var data = value.Data; CodeSphere3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_(ref Tensor<Triangle2f> value)\r\n        {\r\n            var data = value.Data; CodeTriangle2fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_(ref Tensor<Triangle3f> value)\r\n        {\r\n            var data = value.Data; CodeTriangle3fArray(ref data);\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n            var size = value.Size; CodeLongArray(ref size);\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Arrays\r\n\r\n        public void CodeV2iArray(ref V2i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV2uiArray(ref V2ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV2lArray(ref V2l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV2fArray(ref V2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV2dArray(ref V2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3iArray(ref V3i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3uiArray(ref V3ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3lArray(ref V3l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3fArray(ref V3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV3dArray(ref V3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4iArray(ref V4i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4uiArray(ref V4ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4lArray(ref V4l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4fArray(ref V4f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeV4dArray(ref V4d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM22iArray(ref M22i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM22lArray(ref M22l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM22fArray(ref M22f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM22dArray(ref M22d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM23iArray(ref M23i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM23lArray(ref M23l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM23fArray(ref M23f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM23dArray(ref M23d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM33iArray(ref M33i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM33lArray(ref M33l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM33fArray(ref M33f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM33dArray(ref M33d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM34iArray(ref M34i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM34lArray(ref M34l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM34fArray(ref M34f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM34dArray(ref M34d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM44iArray(ref M44i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM44lArray(ref M44l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM44fArray(ref M44f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeM44dArray(ref M44d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1bArray(ref Range1b[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1sbArray(ref Range1sb[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1sArray(ref Range1s[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1usArray(ref Range1us[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1iArray(ref Range1i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1uiArray(ref Range1ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1lArray(ref Range1l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1ulArray(ref Range1ul[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1fArray(ref Range1f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeRange1dArray(ref Range1d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox2iArray(ref Box2i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox2lArray(ref Box2l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox2fArray(ref Box2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox2dArray(ref Box2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox3iArray(ref Box3i[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox3lArray(ref Box3l[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox3fArray(ref Box3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeBox3dArray(ref Box3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3bArray(ref C3b[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3usArray(ref C3us[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3uiArray(ref C3ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3fArray(ref C3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC3dArray(ref C3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4bArray(ref C4b[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4usArray(ref C4us[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4uiArray(ref C4ui[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4fArray(ref C4f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeC4dArray(ref C4d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteArray(value, 0, count);\r\n        }\r\n\r\n        public void CodeEuclidean3fArray(ref Euclidean3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3dArray(ref Euclidean3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2fArray(ref Rot2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2dArray(ref Rot2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3fArray(ref Rot3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3dArray(ref Rot3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3fArray(ref Scale3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3dArray(ref Scale3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3fArray(ref Shift3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3dArray(ref Shift3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2fArray(ref Trafo2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2dArray(ref Trafo2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3fArray(ref Trafo3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3dArray(ref Trafo3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeCircle2dArray(ref Circle2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeCircle2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeLine2dArray(ref Line2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLine2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeLine3dArray(ref Line3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLine3d(ref value[i]);\r\n        }\r\n\r\n        public void CodePlane2dArray(ref Plane2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlane2d(ref value[i]);\r\n        }\r\n\r\n        public void CodePlane3dArray(ref Plane3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlane3d(ref value[i]);\r\n        }\r\n\r\n        public void CodePlaneWithPoint3dArray(ref PlaneWithPoint3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlaneWithPoint3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeQuad2dArray(ref Quad2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeQuad2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeQuad3dArray(ref Quad3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeQuad3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeRay2dArray(ref Ray2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRay2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeRay3dArray(ref Ray3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRay3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeSphere3dArray(ref Sphere3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSphere3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeTriangle2dArray(ref Triangle2d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTriangle2d(ref value[i]);\r\n        }\r\n\r\n        public void CodeTriangle3dArray(ref Triangle3d[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTriangle3d(ref value[i]);\r\n        }\r\n\r\n        public void CodeCircle2fArray(ref Circle2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeCircle2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeLine2fArray(ref Line2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLine2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeLine3fArray(ref Line3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLine3f(ref value[i]);\r\n        }\r\n\r\n        public void CodePlane2fArray(ref Plane2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlane2f(ref value[i]);\r\n        }\r\n\r\n        public void CodePlane3fArray(ref Plane3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlane3f(ref value[i]);\r\n        }\r\n\r\n        public void CodePlaneWithPoint3fArray(ref PlaneWithPoint3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodePlaneWithPoint3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeQuad2fArray(ref Quad2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeQuad2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeQuad3fArray(ref Quad3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeQuad3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeRay2fArray(ref Ray2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRay2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeRay3fArray(ref Ray3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRay3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeSphere3fArray(ref Sphere3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSphere3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeTriangle2fArray(ref Triangle2f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTriangle2f(ref value[i]);\r\n        }\r\n\r\n        public void CodeTriangle3fArray(ref Triangle3f[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTriangle3f(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Byte_Array(ref Vector<byte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Byte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_SByte_Array(ref Vector<sbyte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_SByte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Short_Array(ref Vector<short>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Short_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_UShort_Array(ref Vector<ushort>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_UShort_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Int_Array(ref Vector<int>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Int_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_UInt_Array(ref Vector<uint>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_UInt_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Long_Array(ref Vector<long>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Long_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_ULong_Array(ref Vector<ulong>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_ULong_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Float_Array(ref Vector<float>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Float_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Double_Array(ref Vector<double>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Double_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_Array(ref Vector<Fraction>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Fraction_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V2i_Array(ref Vector<V2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V2l_Array(ref Vector<V2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V2f_Array(ref Vector<V2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V2d_Array(ref Vector<V2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V3i_Array(ref Vector<V3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V3l_Array(ref Vector<V3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V3f_Array(ref Vector<V3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V3d_Array(ref Vector<V3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V4i_Array(ref Vector<V4i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V4i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V4l_Array(ref Vector<V4l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V4l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V4f_Array(ref Vector<V4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_V4d_Array(ref Vector<V4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_V4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M22i_Array(ref Vector<M22i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M22i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M22l_Array(ref Vector<M22l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M22l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M22f_Array(ref Vector<M22f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M22f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M22d_Array(ref Vector<M22d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M22d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M23i_Array(ref Vector<M23i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M23i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M23l_Array(ref Vector<M23l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M23l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M23f_Array(ref Vector<M23f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M23f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M23d_Array(ref Vector<M23d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M23d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M33i_Array(ref Vector<M33i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M33i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M33l_Array(ref Vector<M33l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M33l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M33f_Array(ref Vector<M33f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M33f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M33d_Array(ref Vector<M33d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M33d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M34i_Array(ref Vector<M34i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M34i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M34l_Array(ref Vector<M34l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M34l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M34f_Array(ref Vector<M34f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M34f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M34d_Array(ref Vector<M34d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M34d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M44i_Array(ref Vector<M44i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M44i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M44l_Array(ref Vector<M44l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M44l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M44f_Array(ref Vector<M44f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M44f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_M44d_Array(ref Vector<M44d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_M44d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3b_Array(ref Vector<C3b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3us_Array(ref Vector<C3us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_Array(ref Vector<C3ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3f_Array(ref Vector<C3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C3d_Array(ref Vector<C3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4b_Array(ref Vector<C4b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4us_Array(ref Vector<C4us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_Array(ref Vector<C4ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4f_Array(ref Vector<C4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_C4d_Array(ref Vector<C4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_C4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_Array(ref Vector<Range1b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_Array(ref Vector<Range1sb>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1sb_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_Array(ref Vector<Range1s>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1s_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_Array(ref Vector<Range1us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_Array(ref Vector<Range1i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_Array(ref Vector<Range1ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_Array(ref Vector<Range1l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_Array(ref Vector<Range1ul>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1ul_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_Array(ref Vector<Range1f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_Array(ref Vector<Range1d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Range1d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_Array(ref Vector<Box2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_Array(ref Vector<Box2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_Array(ref Vector<Box2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_Array(ref Vector<Box2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_Array(ref Vector<Box3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_Array(ref Vector<Box3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_Array(ref Vector<Box3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_Array(ref Vector<Box3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Box3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_Array(ref Vector<Euclidean3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Euclidean3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_Array(ref Vector<Euclidean3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Euclidean3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_Array(ref Vector<Rot2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Rot2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_Array(ref Vector<Rot2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Rot2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_Array(ref Vector<Rot3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Rot3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_Array(ref Vector<Rot3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Rot3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_Array(ref Vector<Scale3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Scale3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_Array(ref Vector<Scale3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Scale3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_Array(ref Vector<Shift3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Shift3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_Array(ref Vector<Shift3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Shift3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_Array(ref Vector<Trafo2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Trafo2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_Array(ref Vector<Trafo2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Trafo2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_Array(ref Vector<Trafo3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Trafo3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_Array(ref Vector<Trafo3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Trafo3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Bool_Array(ref Vector<bool>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Bool_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Char_Array(ref Vector<char>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Char_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_String_Array(ref Vector<string>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_String_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Type_Array(ref Vector<Type>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Type_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Guid_Array(ref Vector<Guid>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Guid_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_Array(ref Vector<Symbol>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Symbol_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_Array(ref Vector<Circle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Circle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_Array(ref Vector<Line2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Line2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_Array(ref Vector<Line3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Line3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_Array(ref Vector<Plane2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Plane2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_Array(ref Vector<Plane3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Plane3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_Array(ref Vector<PlaneWithPoint3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_PlaneWithPoint3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_Array(ref Vector<Quad2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Quad2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_Array(ref Vector<Quad3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Quad3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_Array(ref Vector<Ray2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Ray2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_Array(ref Vector<Ray3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Ray3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_Array(ref Vector<Sphere3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Sphere3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_Array(ref Vector<Triangle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Triangle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_Array(ref Vector<Triangle3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Triangle3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_Array(ref Vector<Circle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Circle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_Array(ref Vector<Line2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Line2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_Array(ref Vector<Line3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Line3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_Array(ref Vector<Plane2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Plane2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_Array(ref Vector<Plane3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Plane3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_Array(ref Vector<PlaneWithPoint3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_PlaneWithPoint3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_Array(ref Vector<Quad2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Quad2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_Array(ref Vector<Quad3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Quad3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_Array(ref Vector<Ray2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Ray2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_Array(ref Vector<Ray3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Ray3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_Array(ref Vector<Sphere3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Sphere3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_Array(ref Vector<Triangle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Triangle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_Array(ref Vector<Triangle3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVector_of_Triangle3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_Array(ref Matrix<byte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Byte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_Array(ref Matrix<sbyte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_SByte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_Array(ref Matrix<short>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Short_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_Array(ref Matrix<ushort>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_UShort_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_Array(ref Matrix<int>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Int_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_Array(ref Matrix<uint>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_UInt_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_Array(ref Matrix<long>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Long_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_Array(ref Matrix<ulong>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_ULong_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_Array(ref Matrix<float>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Float_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_Array(ref Matrix<double>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Double_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_Array(ref Matrix<Fraction>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Fraction_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_Array(ref Matrix<V2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_Array(ref Matrix<V2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_Array(ref Matrix<V2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_Array(ref Matrix<V2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_Array(ref Matrix<V3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_Array(ref Matrix<V3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_Array(ref Matrix<V3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_Array(ref Matrix<V3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_Array(ref Matrix<V4i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V4i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_Array(ref Matrix<V4l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V4l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_Array(ref Matrix<V4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_Array(ref Matrix<V4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_V4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_Array(ref Matrix<M22i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M22i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_Array(ref Matrix<M22l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M22l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_Array(ref Matrix<M22f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M22f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_Array(ref Matrix<M22d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M22d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_Array(ref Matrix<M23i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M23i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_Array(ref Matrix<M23l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M23l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_Array(ref Matrix<M23f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M23f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_Array(ref Matrix<M23d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M23d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_Array(ref Matrix<M33i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M33i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_Array(ref Matrix<M33l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M33l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_Array(ref Matrix<M33f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M33f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_Array(ref Matrix<M33d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M33d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_Array(ref Matrix<M34i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M34i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_Array(ref Matrix<M34l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M34l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_Array(ref Matrix<M34f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M34f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_Array(ref Matrix<M34d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M34d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_Array(ref Matrix<M44i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M44i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_Array(ref Matrix<M44l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M44l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_Array(ref Matrix<M44f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M44f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_Array(ref Matrix<M44d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_M44d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_Array(ref Matrix<C3b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_Array(ref Matrix<C3us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_Array(ref Matrix<C3ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_Array(ref Matrix<C3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_Array(ref Matrix<C3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_Array(ref Matrix<C4b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_Array(ref Matrix<C4us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_Array(ref Matrix<C4ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_Array(ref Matrix<C4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_Array(ref Matrix<C4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_C4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_Array(ref Matrix<Range1b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_Array(ref Matrix<Range1sb>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1sb_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_Array(ref Matrix<Range1s>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1s_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_Array(ref Matrix<Range1us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_Array(ref Matrix<Range1i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_Array(ref Matrix<Range1ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_Array(ref Matrix<Range1l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_Array(ref Matrix<Range1ul>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1ul_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_Array(ref Matrix<Range1f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_Array(ref Matrix<Range1d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Range1d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_Array(ref Matrix<Box2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_Array(ref Matrix<Box2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_Array(ref Matrix<Box2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_Array(ref Matrix<Box2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_Array(ref Matrix<Box3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_Array(ref Matrix<Box3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_Array(ref Matrix<Box3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_Array(ref Matrix<Box3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Box3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_Array(ref Matrix<Euclidean3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Euclidean3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_Array(ref Matrix<Euclidean3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Euclidean3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_Array(ref Matrix<Rot2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Rot2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_Array(ref Matrix<Rot2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Rot2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_Array(ref Matrix<Rot3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Rot3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_Array(ref Matrix<Rot3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Rot3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_Array(ref Matrix<Scale3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Scale3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_Array(ref Matrix<Scale3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Scale3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_Array(ref Matrix<Shift3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Shift3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_Array(ref Matrix<Shift3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Shift3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_Array(ref Matrix<Trafo2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Trafo2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_Array(ref Matrix<Trafo2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Trafo2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_Array(ref Matrix<Trafo3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Trafo3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_Array(ref Matrix<Trafo3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Trafo3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_Array(ref Matrix<bool>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Bool_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_Array(ref Matrix<char>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Char_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_String_Array(ref Matrix<string>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_String_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_Array(ref Matrix<Type>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Type_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_Array(ref Matrix<Guid>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Guid_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_Array(ref Matrix<Symbol>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Symbol_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_Array(ref Matrix<Circle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Circle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_Array(ref Matrix<Line2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Line2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_Array(ref Matrix<Line3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Line3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_Array(ref Matrix<Plane2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Plane2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_Array(ref Matrix<Plane3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Plane3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_Array(ref Matrix<PlaneWithPoint3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_PlaneWithPoint3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_Array(ref Matrix<Quad2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Quad2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_Array(ref Matrix<Quad3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Quad3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_Array(ref Matrix<Ray2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Ray2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_Array(ref Matrix<Ray3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Ray3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_Array(ref Matrix<Sphere3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Sphere3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_Array(ref Matrix<Triangle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Triangle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_Array(ref Matrix<Triangle3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Triangle3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_Array(ref Matrix<Circle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Circle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_Array(ref Matrix<Line2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Line2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_Array(ref Matrix<Line3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Line3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_Array(ref Matrix<Plane2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Plane2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_Array(ref Matrix<Plane3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Plane3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_Array(ref Matrix<PlaneWithPoint3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_PlaneWithPoint3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_Array(ref Matrix<Quad2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Quad2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_Array(ref Matrix<Quad3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Quad3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_Array(ref Matrix<Ray2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Ray2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_Array(ref Matrix<Ray3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Ray3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_Array(ref Matrix<Sphere3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Sphere3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_Array(ref Matrix<Triangle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Triangle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_Array(ref Matrix<Triangle3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeMatrix_of_Triangle3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_Array(ref Volume<byte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Byte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_Array(ref Volume<sbyte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_SByte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Short_Array(ref Volume<short>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Short_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_Array(ref Volume<ushort>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_UShort_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Int_Array(ref Volume<int>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Int_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_Array(ref Volume<uint>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_UInt_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Long_Array(ref Volume<long>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Long_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_Array(ref Volume<ulong>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_ULong_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Float_Array(ref Volume<float>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Float_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Double_Array(ref Volume<double>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Double_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_Array(ref Volume<Fraction>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Fraction_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_Array(ref Volume<V2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_Array(ref Volume<V2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_Array(ref Volume<V2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_Array(ref Volume<V2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_Array(ref Volume<V3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_Array(ref Volume<V3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_Array(ref Volume<V3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_Array(ref Volume<V3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_Array(ref Volume<V4i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V4i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_Array(ref Volume<V4l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V4l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_Array(ref Volume<V4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_Array(ref Volume<V4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_V4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_Array(ref Volume<M22i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M22i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_Array(ref Volume<M22l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M22l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_Array(ref Volume<M22f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M22f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_Array(ref Volume<M22d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M22d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_Array(ref Volume<M23i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M23i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_Array(ref Volume<M23l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M23l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_Array(ref Volume<M23f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M23f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_Array(ref Volume<M23d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M23d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_Array(ref Volume<M33i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M33i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_Array(ref Volume<M33l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M33l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_Array(ref Volume<M33f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M33f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_Array(ref Volume<M33d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M33d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_Array(ref Volume<M34i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M34i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_Array(ref Volume<M34l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M34l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_Array(ref Volume<M34f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M34f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_Array(ref Volume<M34d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M34d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_Array(ref Volume<M44i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M44i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_Array(ref Volume<M44l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M44l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_Array(ref Volume<M44f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M44f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_Array(ref Volume<M44d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_M44d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_Array(ref Volume<C3b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_Array(ref Volume<C3us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_Array(ref Volume<C3ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_Array(ref Volume<C3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_Array(ref Volume<C3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_Array(ref Volume<C4b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_Array(ref Volume<C4us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_Array(ref Volume<C4ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_Array(ref Volume<C4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_Array(ref Volume<C4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_C4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_Array(ref Volume<Range1b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_Array(ref Volume<Range1sb>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1sb_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_Array(ref Volume<Range1s>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1s_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_Array(ref Volume<Range1us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_Array(ref Volume<Range1i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_Array(ref Volume<Range1ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_Array(ref Volume<Range1l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_Array(ref Volume<Range1ul>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1ul_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_Array(ref Volume<Range1f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_Array(ref Volume<Range1d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Range1d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_Array(ref Volume<Box2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_Array(ref Volume<Box2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_Array(ref Volume<Box2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_Array(ref Volume<Box2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_Array(ref Volume<Box3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_Array(ref Volume<Box3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_Array(ref Volume<Box3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_Array(ref Volume<Box3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Box3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_Array(ref Volume<Euclidean3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Euclidean3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_Array(ref Volume<Euclidean3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Euclidean3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_Array(ref Volume<Rot2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Rot2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_Array(ref Volume<Rot2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Rot2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_Array(ref Volume<Rot3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Rot3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_Array(ref Volume<Rot3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Rot3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_Array(ref Volume<Scale3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Scale3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_Array(ref Volume<Scale3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Scale3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_Array(ref Volume<Shift3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Shift3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_Array(ref Volume<Shift3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Shift3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_Array(ref Volume<Trafo2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Trafo2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_Array(ref Volume<Trafo2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Trafo2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_Array(ref Volume<Trafo3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Trafo3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_Array(ref Volume<Trafo3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Trafo3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_Array(ref Volume<bool>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Bool_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Char_Array(ref Volume<char>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Char_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_String_Array(ref Volume<string>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_String_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Type_Array(ref Volume<Type>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Type_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_Array(ref Volume<Guid>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Guid_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_Array(ref Volume<Symbol>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Symbol_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_Array(ref Volume<Circle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Circle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_Array(ref Volume<Line2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Line2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_Array(ref Volume<Line3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Line3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_Array(ref Volume<Plane2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Plane2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_Array(ref Volume<Plane3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Plane3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_Array(ref Volume<PlaneWithPoint3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_PlaneWithPoint3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_Array(ref Volume<Quad2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Quad2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_Array(ref Volume<Quad3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Quad3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_Array(ref Volume<Ray2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Ray2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_Array(ref Volume<Ray3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Ray3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_Array(ref Volume<Sphere3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Sphere3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_Array(ref Volume<Triangle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Triangle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_Array(ref Volume<Triangle3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Triangle3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_Array(ref Volume<Circle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Circle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_Array(ref Volume<Line2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Line2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_Array(ref Volume<Line3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Line3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_Array(ref Volume<Plane2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Plane2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_Array(ref Volume<Plane3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Plane3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_Array(ref Volume<PlaneWithPoint3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_PlaneWithPoint3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_Array(ref Volume<Quad2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Quad2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_Array(ref Volume<Quad3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Quad3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_Array(ref Volume<Ray2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Ray2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_Array(ref Volume<Ray3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Ray3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_Array(ref Volume<Sphere3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Sphere3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_Array(ref Volume<Triangle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Triangle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_Array(ref Volume<Triangle3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeVolume_of_Triangle3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_Array(ref Tensor<byte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Byte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_Array(ref Tensor<sbyte>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_SByte_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Short_Array(ref Tensor<short>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Short_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_Array(ref Tensor<ushort>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_UShort_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Int_Array(ref Tensor<int>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Int_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_Array(ref Tensor<uint>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_UInt_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Long_Array(ref Tensor<long>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Long_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_Array(ref Tensor<ulong>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_ULong_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Float_Array(ref Tensor<float>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Float_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Double_Array(ref Tensor<double>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Double_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_Array(ref Tensor<Fraction>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Fraction_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_Array(ref Tensor<V2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_Array(ref Tensor<V2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_Array(ref Tensor<V2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_Array(ref Tensor<V2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_Array(ref Tensor<V3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_Array(ref Tensor<V3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_Array(ref Tensor<V3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_Array(ref Tensor<V3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_Array(ref Tensor<V4i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V4i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_Array(ref Tensor<V4l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V4l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_Array(ref Tensor<V4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_Array(ref Tensor<V4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_V4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_Array(ref Tensor<M22i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M22i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_Array(ref Tensor<M22l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M22l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_Array(ref Tensor<M22f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M22f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_Array(ref Tensor<M22d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M22d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_Array(ref Tensor<M23i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M23i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_Array(ref Tensor<M23l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M23l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_Array(ref Tensor<M23f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M23f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_Array(ref Tensor<M23d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M23d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_Array(ref Tensor<M33i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M33i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_Array(ref Tensor<M33l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M33l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_Array(ref Tensor<M33f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M33f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_Array(ref Tensor<M33d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M33d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_Array(ref Tensor<M34i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M34i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_Array(ref Tensor<M34l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M34l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_Array(ref Tensor<M34f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M34f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_Array(ref Tensor<M34d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M34d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_Array(ref Tensor<M44i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M44i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_Array(ref Tensor<M44l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M44l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_Array(ref Tensor<M44f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M44f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_Array(ref Tensor<M44d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_M44d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_Array(ref Tensor<C3b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_Array(ref Tensor<C3us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_Array(ref Tensor<C3ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_Array(ref Tensor<C3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_Array(ref Tensor<C3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_Array(ref Tensor<C4b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_Array(ref Tensor<C4us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_Array(ref Tensor<C4ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_Array(ref Tensor<C4f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_Array(ref Tensor<C4d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_C4d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_Array(ref Tensor<Range1b>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1b_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_Array(ref Tensor<Range1sb>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1sb_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_Array(ref Tensor<Range1s>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1s_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_Array(ref Tensor<Range1us>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1us_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_Array(ref Tensor<Range1i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_Array(ref Tensor<Range1ui>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1ui_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_Array(ref Tensor<Range1l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_Array(ref Tensor<Range1ul>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1ul_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_Array(ref Tensor<Range1f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_Array(ref Tensor<Range1d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Range1d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_Array(ref Tensor<Box2i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box2i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_Array(ref Tensor<Box2l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box2l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_Array(ref Tensor<Box2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_Array(ref Tensor<Box2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_Array(ref Tensor<Box3i>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box3i_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_Array(ref Tensor<Box3l>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box3l_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_Array(ref Tensor<Box3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_Array(ref Tensor<Box3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Box3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_Array(ref Tensor<Euclidean3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Euclidean3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_Array(ref Tensor<Euclidean3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Euclidean3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_Array(ref Tensor<Rot2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Rot2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_Array(ref Tensor<Rot2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Rot2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_Array(ref Tensor<Rot3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Rot3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_Array(ref Tensor<Rot3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Rot3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_Array(ref Tensor<Scale3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Scale3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_Array(ref Tensor<Scale3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Scale3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_Array(ref Tensor<Shift3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Shift3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_Array(ref Tensor<Shift3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Shift3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_Array(ref Tensor<Trafo2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Trafo2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_Array(ref Tensor<Trafo2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Trafo2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_Array(ref Tensor<Trafo3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Trafo3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_Array(ref Tensor<Trafo3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Trafo3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_Array(ref Tensor<bool>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Bool_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Char_Array(ref Tensor<char>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Char_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_String_Array(ref Tensor<string>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_String_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Type_Array(ref Tensor<Type>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Type_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_Array(ref Tensor<Guid>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Guid_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_Array(ref Tensor<Symbol>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Symbol_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_Array(ref Tensor<Circle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Circle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_Array(ref Tensor<Line2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Line2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_Array(ref Tensor<Line3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Line3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_Array(ref Tensor<Plane2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Plane2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_Array(ref Tensor<Plane3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Plane3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_Array(ref Tensor<PlaneWithPoint3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_PlaneWithPoint3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_Array(ref Tensor<Quad2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Quad2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_Array(ref Tensor<Quad3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Quad3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_Array(ref Tensor<Ray2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Ray2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_Array(ref Tensor<Ray3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Ray3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_Array(ref Tensor<Sphere3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Sphere3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_Array(ref Tensor<Triangle2d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Triangle2d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_Array(ref Tensor<Triangle3d>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Triangle3d_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_Array(ref Tensor<Circle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Circle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_Array(ref Tensor<Line2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Line2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_Array(ref Tensor<Line3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Line3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_Array(ref Tensor<Plane2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Plane2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_Array(ref Tensor<Plane3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Plane3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_Array(ref Tensor<PlaneWithPoint3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_PlaneWithPoint3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_Array(ref Tensor<Quad2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Quad2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_Array(ref Tensor<Quad3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Quad3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_Array(ref Tensor<Ray2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Ray2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_Array(ref Tensor<Ray3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Ray3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_Array(ref Tensor<Sphere3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Sphere3f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_Array(ref Tensor<Triangle2f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Triangle2f_(ref value[i]);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_Array(ref Tensor<Triangle3f>[] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTensor_of_Triangle3f_(ref value[i]);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArray2d(ref byte[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeByteArray3d(ref byte[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeSByteArray2d(ref sbyte[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeSByteArray3d(ref sbyte[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeShortArray2d(ref short[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeShortArray3d(ref short[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeUShortArray2d(ref ushort[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeUShortArray3d(ref ushort[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeIntArray2d(ref int[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeIntArray3d(ref int[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeUIntArray2d(ref uint[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeUIntArray3d(ref uint[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeLongArray2d(ref long[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeLongArray3d(ref long[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeULongArray2d(ref ulong[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeULongArray3d(ref ulong[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeFloatArray2d(ref float[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeFloatArray3d(ref float[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeDoubleArray2d(ref double[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeDoubleArray3d(ref double[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeFractionArray2d(ref Fraction[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeFractionArray3d(ref Fraction[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV2iArray2d(ref V2i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV2iArray3d(ref V2i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV2lArray2d(ref V2l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV2lArray3d(ref V2l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV2fArray2d(ref V2f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV2fArray3d(ref V2f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV2dArray2d(ref V2d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV2dArray3d(ref V2d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV3iArray2d(ref V3i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV3iArray3d(ref V3i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV3lArray2d(ref V3l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV3lArray3d(ref V3l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV3fArray2d(ref V3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV3fArray3d(ref V3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV3dArray2d(ref V3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV3dArray3d(ref V3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV4iArray2d(ref V4i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV4iArray3d(ref V4i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV4lArray2d(ref V4l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV4lArray3d(ref V4l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV4fArray2d(ref V4f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV4fArray3d(ref V4f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeV4dArray2d(ref V4d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeV4dArray3d(ref V4d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM22iArray2d(ref M22i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM22iArray3d(ref M22i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM22lArray2d(ref M22l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM22lArray3d(ref M22l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM22fArray2d(ref M22f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM22fArray3d(ref M22f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM22dArray2d(ref M22d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM22dArray3d(ref M22d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM23iArray2d(ref M23i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM23iArray3d(ref M23i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM23lArray2d(ref M23l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM23lArray3d(ref M23l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM23fArray2d(ref M23f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM23fArray3d(ref M23f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM23dArray2d(ref M23d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM23dArray3d(ref M23d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM33iArray2d(ref M33i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM33iArray3d(ref M33i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM33lArray2d(ref M33l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM33lArray3d(ref M33l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM33fArray2d(ref M33f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM33fArray3d(ref M33f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM33dArray2d(ref M33d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM33dArray3d(ref M33d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM34iArray2d(ref M34i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM34iArray3d(ref M34i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM34lArray2d(ref M34l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM34lArray3d(ref M34l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM34fArray2d(ref M34f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM34fArray3d(ref M34f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM34dArray2d(ref M34d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM34dArray3d(ref M34d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM44iArray2d(ref M44i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM44iArray3d(ref M44i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM44lArray2d(ref M44l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM44lArray3d(ref M44l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM44fArray2d(ref M44f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM44fArray3d(ref M44f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeM44dArray2d(ref M44d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeM44dArray3d(ref M44d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3bArray2d(ref C3b[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3bArray3d(ref C3b[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3usArray2d(ref C3us[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3usArray3d(ref C3us[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3uiArray2d(ref C3ui[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3uiArray3d(ref C3ui[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3fArray2d(ref C3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3fArray3d(ref C3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC3dArray2d(ref C3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC3dArray3d(ref C3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4bArray2d(ref C4b[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4bArray3d(ref C4b[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4usArray2d(ref C4us[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4usArray3d(ref C4us[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4uiArray2d(ref C4ui[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4uiArray3d(ref C4ui[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4fArray2d(ref C4f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4fArray3d(ref C4f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeC4dArray2d(ref C4d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeC4dArray3d(ref C4d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1bArray2d(ref Range1b[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1bArray3d(ref Range1b[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1sbArray2d(ref Range1sb[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1sbArray3d(ref Range1sb[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1sArray2d(ref Range1s[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1sArray3d(ref Range1s[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1usArray2d(ref Range1us[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1usArray3d(ref Range1us[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1iArray2d(ref Range1i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1iArray3d(ref Range1i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1uiArray2d(ref Range1ui[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1uiArray3d(ref Range1ui[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1lArray2d(ref Range1l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1lArray3d(ref Range1l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1ulArray2d(ref Range1ul[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1ulArray3d(ref Range1ul[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1fArray2d(ref Range1f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1fArray3d(ref Range1f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRange1dArray2d(ref Range1d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRange1dArray3d(ref Range1d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox2iArray2d(ref Box2i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox2iArray3d(ref Box2i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox2lArray2d(ref Box2l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox2lArray3d(ref Box2l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox2fArray2d(ref Box2f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox2fArray3d(ref Box2f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox2dArray2d(ref Box2d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox2dArray3d(ref Box2d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox3iArray2d(ref Box3i[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox3iArray3d(ref Box3i[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox3lArray2d(ref Box3l[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox3lArray3d(ref Box3l[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox3fArray2d(ref Box3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox3fArray3d(ref Box3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeBox3dArray2d(ref Box3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeBox3dArray3d(ref Box3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeEuclidean3fArray2d(ref Euclidean3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeEuclidean3fArray3d(ref Euclidean3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeEuclidean3dArray2d(ref Euclidean3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeEuclidean3dArray3d(ref Euclidean3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRot2fArray2d(ref Rot2f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRot2fArray3d(ref Rot2f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRot2dArray2d(ref Rot2d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRot2dArray3d(ref Rot2d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRot3fArray2d(ref Rot3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRot3fArray3d(ref Rot3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeRot3dArray2d(ref Rot3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeRot3dArray3d(ref Rot3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeScale3fArray2d(ref Scale3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeScale3fArray3d(ref Scale3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeScale3dArray2d(ref Scale3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeScale3dArray3d(ref Scale3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeShift3fArray2d(ref Shift3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeShift3fArray3d(ref Shift3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeShift3dArray2d(ref Shift3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeShift3dArray3d(ref Shift3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeTrafo2fArray2d(ref Trafo2f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeTrafo2fArray3d(ref Trafo2f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeTrafo2dArray2d(ref Trafo2d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeTrafo2dArray3d(ref Trafo2d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeTrafo3fArray2d(ref Trafo3f[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeTrafo3fArray3d(ref Trafo3f[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        public void CodeTrafo3dArray2d(ref Trafo3d[,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1);\r\n        }\r\n\r\n        public void CodeTrafo3dArray3d(ref Trafo3d[, ,] value)\r\n        {\r\n            long[] countArray = CodeCountLong(ref value);\r\n            long c0 = countArray[0]; if (c0 < 1) return;\r\n            long c1 = countArray[1]; if (c1 < 1) return;\r\n            long c2 = countArray[2]; if (c2 < 1) return;\r\n            m_writer.WriteArray(value, c0 * c1 * c2);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Jagged Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArrayArray(ref byte[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeByteArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeByteArrayArrayArray(ref byte[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeByteArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeSByteArrayArray(ref sbyte[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSByteArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeSByteArrayArrayArray(ref sbyte[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeSByteArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShortArrayArray(ref short[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShortArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShortArrayArrayArray(ref short[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShortArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeUShortArrayArray(ref ushort[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeUShortArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeUShortArrayArrayArray(ref ushort[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeUShortArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeIntArrayArray(ref int[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeIntArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeIntArrayArrayArray(ref int[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeIntArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeUIntArrayArray(ref uint[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeUIntArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeUIntArrayArrayArray(ref uint[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeUIntArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeLongArrayArray(ref long[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLongArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeLongArrayArrayArray(ref long[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeLongArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeULongArrayArray(ref ulong[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeULongArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeULongArrayArrayArray(ref ulong[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeULongArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeFloatArrayArray(ref float[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeFloatArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeFloatArrayArrayArray(ref float[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeFloatArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeDoubleArrayArray(ref double[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeDoubleArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeDoubleArrayArrayArray(ref double[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeDoubleArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeFractionArrayArray(ref Fraction[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeFractionArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeFractionArrayArrayArray(ref Fraction[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeFractionArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2iArrayArray(ref V2i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2iArrayArrayArray(ref V2i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2lArrayArray(ref V2l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2lArrayArrayArray(ref V2l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2fArrayArray(ref V2f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2fArrayArrayArray(ref V2f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2dArrayArray(ref V2d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV2dArrayArrayArray(ref V2d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV2dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3iArrayArray(ref V3i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3iArrayArrayArray(ref V3i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3lArrayArray(ref V3l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3lArrayArrayArray(ref V3l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3fArrayArray(ref V3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3fArrayArrayArray(ref V3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3dArrayArray(ref V3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV3dArrayArrayArray(ref V3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4iArrayArray(ref V4i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4iArrayArrayArray(ref V4i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4lArrayArray(ref V4l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4lArrayArrayArray(ref V4l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4fArrayArray(ref V4f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4fArrayArrayArray(ref V4f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4dArrayArray(ref V4d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeV4dArrayArrayArray(ref V4d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeV4dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22iArrayArray(ref M22i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22iArrayArrayArray(ref M22i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22lArrayArray(ref M22l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22lArrayArrayArray(ref M22l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22fArrayArray(ref M22f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22fArrayArrayArray(ref M22f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22dArrayArray(ref M22d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM22dArrayArrayArray(ref M22d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM22dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23iArrayArray(ref M23i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23iArrayArrayArray(ref M23i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23lArrayArray(ref M23l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23lArrayArrayArray(ref M23l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23fArrayArray(ref M23f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23fArrayArrayArray(ref M23f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23dArrayArray(ref M23d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM23dArrayArrayArray(ref M23d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM23dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33iArrayArray(ref M33i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33iArrayArrayArray(ref M33i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33lArrayArray(ref M33l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33lArrayArrayArray(ref M33l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33fArrayArray(ref M33f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33fArrayArrayArray(ref M33f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33dArrayArray(ref M33d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM33dArrayArrayArray(ref M33d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM33dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34iArrayArray(ref M34i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34iArrayArrayArray(ref M34i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34lArrayArray(ref M34l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34lArrayArrayArray(ref M34l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34fArrayArray(ref M34f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34fArrayArrayArray(ref M34f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34dArrayArray(ref M34d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM34dArrayArrayArray(ref M34d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM34dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44iArrayArray(ref M44i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44iArrayArrayArray(ref M44i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44lArrayArray(ref M44l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44lArrayArrayArray(ref M44l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44fArrayArray(ref M44f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44fArrayArrayArray(ref M44f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44dArrayArray(ref M44d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeM44dArrayArrayArray(ref M44d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeM44dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3bArrayArray(ref C3b[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3bArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3bArrayArrayArray(ref C3b[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3bArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3usArrayArray(ref C3us[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3usArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3usArrayArrayArray(ref C3us[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3usArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3uiArrayArray(ref C3ui[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3uiArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3uiArrayArrayArray(ref C3ui[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3uiArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3fArrayArray(ref C3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3fArrayArrayArray(ref C3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3dArrayArray(ref C3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC3dArrayArrayArray(ref C3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4bArrayArray(ref C4b[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4bArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4bArrayArrayArray(ref C4b[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4bArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4usArrayArray(ref C4us[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4usArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4usArrayArrayArray(ref C4us[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4usArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4uiArrayArray(ref C4ui[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4uiArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4uiArrayArrayArray(ref C4ui[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4uiArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4fArrayArray(ref C4f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4fArrayArrayArray(ref C4f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4dArrayArray(ref C4d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeC4dArrayArrayArray(ref C4d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeC4dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1bArrayArray(ref Range1b[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1bArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1bArrayArrayArray(ref Range1b[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1bArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1sbArrayArray(ref Range1sb[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1sbArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1sbArrayArrayArray(ref Range1sb[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1sbArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1sArrayArray(ref Range1s[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1sArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1sArrayArrayArray(ref Range1s[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1sArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1usArrayArray(ref Range1us[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1usArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1usArrayArrayArray(ref Range1us[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1usArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1iArrayArray(ref Range1i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1iArrayArrayArray(ref Range1i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1uiArrayArray(ref Range1ui[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1uiArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1uiArrayArrayArray(ref Range1ui[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1uiArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1lArrayArray(ref Range1l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1lArrayArrayArray(ref Range1l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1ulArrayArray(ref Range1ul[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1ulArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1ulArrayArrayArray(ref Range1ul[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1ulArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1fArrayArray(ref Range1f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1fArrayArrayArray(ref Range1f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1dArrayArray(ref Range1d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRange1dArrayArrayArray(ref Range1d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRange1dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2iArrayArray(ref Box2i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2iArrayArrayArray(ref Box2i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2lArrayArray(ref Box2l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2lArrayArrayArray(ref Box2l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2fArrayArray(ref Box2f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2fArrayArrayArray(ref Box2f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2dArrayArray(ref Box2d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox2dArrayArrayArray(ref Box2d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox2dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3iArrayArray(ref Box3i[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3iArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3iArrayArrayArray(ref Box3i[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3iArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3lArrayArray(ref Box3l[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3lArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3lArrayArrayArray(ref Box3l[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3lArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3fArrayArray(ref Box3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3fArrayArrayArray(ref Box3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3dArrayArray(ref Box3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeBox3dArrayArrayArray(ref Box3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeBox3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3fArrayArray(ref Euclidean3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3fArrayArrayArray(ref Euclidean3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3dArrayArray(ref Euclidean3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeEuclidean3dArrayArrayArray(ref Euclidean3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeEuclidean3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2fArrayArray(ref Rot2f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2fArrayArrayArray(ref Rot2f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2dArrayArray(ref Rot2d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot2dArrayArrayArray(ref Rot2d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot2dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3fArrayArray(ref Rot3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3fArrayArrayArray(ref Rot3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3dArrayArray(ref Rot3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeRot3dArrayArrayArray(ref Rot3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeRot3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3fArrayArray(ref Scale3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3fArrayArrayArray(ref Scale3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3dArrayArray(ref Scale3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeScale3dArrayArrayArray(ref Scale3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeScale3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3fArrayArray(ref Shift3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3fArrayArrayArray(ref Shift3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3dArrayArray(ref Shift3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeShift3dArrayArrayArray(ref Shift3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeShift3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2fArrayArray(ref Trafo2f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2fArrayArrayArray(ref Trafo2f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2dArrayArray(ref Trafo2d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo2dArrayArrayArray(ref Trafo2d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo2dArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3fArrayArray(ref Trafo3f[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3fArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3fArrayArrayArray(ref Trafo3f[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3fArrayArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3dArrayArray(ref Trafo3d[][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3dArray(ref value[i]);\r\n        }\r\n\r\n        public void CodeTrafo3dArrayArrayArray(ref Trafo3d[][][] value)\r\n        {\r\n            long count = CodeCountLong(ref value);\r\n            if (count < 1) return;\r\n            for (long i = 0; i < count; i++) CodeTrafo3dArrayArray(ref value[i]);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Lists\r\n\r\n        public void CodeList_of_V2i_(ref List<V2i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V2ui_(ref List<V2ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V2l_(ref List<V2l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V2f_(ref List<V2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V2d_(ref List<V2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3i_(ref List<V3i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3ui_(ref List<V3ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3l_(ref List<V3l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3f_(ref List<V3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V3d_(ref List<V3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4i_(ref List<V4i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4ui_(ref List<V4ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4l_(ref List<V4l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4f_(ref List<V4f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_V4d_(ref List<V4d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M22i_(ref List<M22i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M22l_(ref List<M22l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M22f_(ref List<M22f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M22d_(ref List<M22d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M23i_(ref List<M23i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M23l_(ref List<M23l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M23f_(ref List<M23f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M23d_(ref List<M23d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M33i_(ref List<M33i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M33l_(ref List<M33l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M33f_(ref List<M33f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M33d_(ref List<M33d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M34i_(ref List<M34i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M34l_(ref List<M34l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M34f_(ref List<M34f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M34d_(ref List<M34d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M44i_(ref List<M44i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M44l_(ref List<M44l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M44f_(ref List<M44f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_M44d_(ref List<M44d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1b_(ref List<Range1b> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1sb_(ref List<Range1sb> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1s_(ref List<Range1s> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1us_(ref List<Range1us> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1i_(ref List<Range1i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1ui_(ref List<Range1ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1l_(ref List<Range1l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1ul_(ref List<Range1ul> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1f_(ref List<Range1f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Range1d_(ref List<Range1d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box2i_(ref List<Box2i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box2l_(ref List<Box2l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box2f_(ref List<Box2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box2d_(ref List<Box2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box3i_(ref List<Box3i> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box3l_(ref List<Box3l> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box3f_(ref List<Box3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Box3d_(ref List<Box3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3b_(ref List<C3b> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3us_(ref List<C3us> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3ui_(ref List<C3ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3f_(ref List<C3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C3d_(ref List<C3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4b_(ref List<C4b> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4us_(ref List<C4us> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4ui_(ref List<C4ui> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4f_(ref List<C4f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_C4d_(ref List<C4d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            m_writer.WriteList(value, 0, count);\r\n        }\r\n\r\n        public void CodeList_of_Euclidean3f_(ref List<Euclidean3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeEuclidean3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Euclidean3d_(ref List<Euclidean3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeEuclidean3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Rot2f_(ref List<Rot2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeRot2f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Rot2d_(ref List<Rot2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeRot2d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Rot3f_(ref List<Rot3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeRot3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Rot3d_(ref List<Rot3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeRot3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Scale3f_(ref List<Scale3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeScale3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Scale3d_(ref List<Scale3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeScale3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Shift3f_(ref List<Shift3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeShift3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Shift3d_(ref List<Shift3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeShift3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Trafo2f_(ref List<Trafo2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTrafo2f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Trafo2d_(ref List<Trafo2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTrafo2d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Trafo3f_(ref List<Trafo3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTrafo3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Trafo3d_(ref List<Trafo3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTrafo3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Circle2d_(ref List<Circle2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeCircle2d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Line2d_(ref List<Line2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeLine2d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Line3d_(ref List<Line3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeLine3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Plane2d_(ref List<Plane2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodePlane2d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Plane3d_(ref List<Plane3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodePlane3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_PlaneWithPoint3d_(ref List<PlaneWithPoint3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodePlaneWithPoint3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Quad2d_(ref List<Quad2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeQuad2d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Quad3d_(ref List<Quad3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeQuad3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Ray2d_(ref List<Ray2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeRay2d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Ray3d_(ref List<Ray3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeRay3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Sphere3d_(ref List<Sphere3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeSphere3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Triangle2d_(ref List<Triangle2d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTriangle2d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Triangle3d_(ref List<Triangle3d> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTriangle3d(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Circle2f_(ref List<Circle2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeCircle2f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Line2f_(ref List<Line2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeLine2f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Line3f_(ref List<Line3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeLine3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Plane2f_(ref List<Plane2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodePlane2f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Plane3f_(ref List<Plane3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodePlane3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_PlaneWithPoint3f_(ref List<PlaneWithPoint3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodePlaneWithPoint3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Quad2f_(ref List<Quad2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeQuad2f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Quad3f_(ref List<Quad3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeQuad3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Ray2f_(ref List<Ray2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeRay2f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Ray3f_(ref List<Ray3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeRay3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Sphere3f_(ref List<Sphere3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeSphere3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Triangle2f_(ref List<Triangle2f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTriangle2f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Triangle3f_(ref List<Triangle3f> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTriangle3f(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Byte__(ref List<Vector<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Byte_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_SByte__(ref List<Vector<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_SByte_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Short__(ref List<Vector<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Short_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_UShort__(ref List<Vector<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_UShort_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Int__(ref List<Vector<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Int_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_UInt__(ref List<Vector<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_UInt_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Long__(ref List<Vector<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Long_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_ULong__(ref List<Vector<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_ULong_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Float__(ref List<Vector<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Float_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Double__(ref List<Vector<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Double_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Fraction__(ref List<Vector<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Fraction_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2i__(ref List<Vector<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V2i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2l__(ref List<Vector<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V2l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2f__(ref List<Vector<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2d__(ref List<Vector<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3i__(ref List<Vector<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V3i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3l__(ref List<Vector<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V3l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3f__(ref List<Vector<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3d__(ref List<Vector<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4i__(ref List<Vector<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V4i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4l__(ref List<Vector<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V4l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4f__(ref List<Vector<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V4f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4d__(ref List<Vector<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_V4d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22i__(ref List<Vector<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M22i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22l__(ref List<Vector<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M22l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22f__(ref List<Vector<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M22f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22d__(ref List<Vector<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M22d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23i__(ref List<Vector<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M23i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23l__(ref List<Vector<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M23l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23f__(ref List<Vector<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M23f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23d__(ref List<Vector<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M23d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33i__(ref List<Vector<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M33i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33l__(ref List<Vector<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M33l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33f__(ref List<Vector<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M33f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33d__(ref List<Vector<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M33d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34i__(ref List<Vector<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M34i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34l__(ref List<Vector<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M34l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34f__(ref List<Vector<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M34f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34d__(ref List<Vector<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M34d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44i__(ref List<Vector<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M44i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44l__(ref List<Vector<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M44l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44f__(ref List<Vector<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M44f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44d__(ref List<Vector<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_M44d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3b__(ref List<Vector<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C3b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3us__(ref List<Vector<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C3us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3ui__(ref List<Vector<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C3ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3f__(ref List<Vector<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3d__(ref List<Vector<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4b__(ref List<Vector<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C4b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4us__(ref List<Vector<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C4us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4ui__(ref List<Vector<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C4ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4f__(ref List<Vector<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C4f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4d__(ref List<Vector<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_C4d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1b__(ref List<Vector<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1sb__(ref List<Vector<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1sb_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1s__(ref List<Vector<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1s_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1us__(ref List<Vector<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1i__(ref List<Vector<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1ui__(ref List<Vector<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1l__(ref List<Vector<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1ul__(ref List<Vector<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1ul_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1f__(ref List<Vector<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1d__(ref List<Vector<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Range1d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2i__(ref List<Vector<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Box2i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2l__(ref List<Vector<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Box2l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2f__(ref List<Vector<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Box2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2d__(ref List<Vector<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Box2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3i__(ref List<Vector<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Box3i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3l__(ref List<Vector<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Box3l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3f__(ref List<Vector<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Box3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3d__(ref List<Vector<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Box3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Euclidean3f__(ref List<Vector<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Euclidean3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Euclidean3d__(ref List<Vector<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Euclidean3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot2f__(ref List<Vector<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Rot2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot2d__(ref List<Vector<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Rot2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot3f__(ref List<Vector<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Rot3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot3d__(ref List<Vector<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Rot3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Scale3f__(ref List<Vector<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Scale3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Scale3d__(ref List<Vector<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Scale3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Shift3f__(ref List<Vector<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Shift3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Shift3d__(ref List<Vector<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Shift3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo2f__(ref List<Vector<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Trafo2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo2d__(ref List<Vector<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Trafo2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo3f__(ref List<Vector<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Trafo3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo3d__(ref List<Vector<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Trafo3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Bool__(ref List<Vector<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Bool_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Char__(ref List<Vector<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Char_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_String__(ref List<Vector<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_String_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Type__(ref List<Vector<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Type_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Guid__(ref List<Vector<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Guid_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Symbol__(ref List<Vector<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Symbol_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Circle2d__(ref List<Vector<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Circle2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line2d__(ref List<Vector<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Line2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line3d__(ref List<Vector<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Line3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane2d__(ref List<Vector<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Plane2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane3d__(ref List<Vector<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Plane3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3d__(ref List<Vector<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_PlaneWithPoint3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad2d__(ref List<Vector<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Quad2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad3d__(ref List<Vector<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Quad3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray2d__(ref List<Vector<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Ray2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray3d__(ref List<Vector<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Ray3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Sphere3d__(ref List<Vector<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Sphere3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle2d__(ref List<Vector<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Triangle2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle3d__(ref List<Vector<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Triangle3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Circle2f__(ref List<Vector<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Circle2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line2f__(ref List<Vector<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Line2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line3f__(ref List<Vector<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Line3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane2f__(ref List<Vector<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Plane2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane3f__(ref List<Vector<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Plane3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3f__(ref List<Vector<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_PlaneWithPoint3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad2f__(ref List<Vector<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Quad2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad3f__(ref List<Vector<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Quad3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray2f__(ref List<Vector<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Ray2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray3f__(ref List<Vector<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Ray3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Sphere3f__(ref List<Vector<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Sphere3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle2f__(ref List<Vector<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Triangle2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle3f__(ref List<Vector<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVector_of_Triangle3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Byte__(ref List<Matrix<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Byte_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_SByte__(ref List<Matrix<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_SByte_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Short__(ref List<Matrix<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Short_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_UShort__(ref List<Matrix<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_UShort_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Int__(ref List<Matrix<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Int_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_UInt__(ref List<Matrix<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_UInt_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Long__(ref List<Matrix<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Long_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_ULong__(ref List<Matrix<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_ULong_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Float__(ref List<Matrix<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Float_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Double__(ref List<Matrix<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Double_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Fraction__(ref List<Matrix<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Fraction_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2i__(ref List<Matrix<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V2i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2l__(ref List<Matrix<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V2l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2f__(ref List<Matrix<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2d__(ref List<Matrix<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3i__(ref List<Matrix<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V3i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3l__(ref List<Matrix<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V3l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3f__(ref List<Matrix<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3d__(ref List<Matrix<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4i__(ref List<Matrix<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V4i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4l__(ref List<Matrix<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V4l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4f__(ref List<Matrix<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V4f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4d__(ref List<Matrix<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_V4d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22i__(ref List<Matrix<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M22i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22l__(ref List<Matrix<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M22l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22f__(ref List<Matrix<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M22f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22d__(ref List<Matrix<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M22d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23i__(ref List<Matrix<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M23i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23l__(ref List<Matrix<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M23l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23f__(ref List<Matrix<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M23f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23d__(ref List<Matrix<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M23d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33i__(ref List<Matrix<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M33i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33l__(ref List<Matrix<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M33l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33f__(ref List<Matrix<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M33f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33d__(ref List<Matrix<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M33d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34i__(ref List<Matrix<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M34i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34l__(ref List<Matrix<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M34l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34f__(ref List<Matrix<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M34f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34d__(ref List<Matrix<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M34d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44i__(ref List<Matrix<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M44i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44l__(ref List<Matrix<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M44l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44f__(ref List<Matrix<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M44f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44d__(ref List<Matrix<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_M44d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3b__(ref List<Matrix<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C3b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3us__(ref List<Matrix<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C3us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3ui__(ref List<Matrix<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C3ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3f__(ref List<Matrix<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3d__(ref List<Matrix<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4b__(ref List<Matrix<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C4b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4us__(ref List<Matrix<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C4us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4ui__(ref List<Matrix<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C4ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4f__(ref List<Matrix<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C4f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4d__(ref List<Matrix<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_C4d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1b__(ref List<Matrix<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1sb__(ref List<Matrix<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1sb_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1s__(ref List<Matrix<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1s_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1us__(ref List<Matrix<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1i__(ref List<Matrix<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1ui__(ref List<Matrix<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1l__(ref List<Matrix<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1ul__(ref List<Matrix<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1ul_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1f__(ref List<Matrix<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1d__(ref List<Matrix<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Range1d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2i__(ref List<Matrix<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Box2i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2l__(ref List<Matrix<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Box2l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2f__(ref List<Matrix<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Box2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2d__(ref List<Matrix<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Box2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3i__(ref List<Matrix<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Box3i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3l__(ref List<Matrix<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Box3l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3f__(ref List<Matrix<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Box3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3d__(ref List<Matrix<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Box3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Euclidean3f__(ref List<Matrix<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Euclidean3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Euclidean3d__(ref List<Matrix<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Euclidean3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot2f__(ref List<Matrix<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Rot2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot2d__(ref List<Matrix<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Rot2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot3f__(ref List<Matrix<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Rot3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot3d__(ref List<Matrix<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Rot3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Scale3f__(ref List<Matrix<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Scale3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Scale3d__(ref List<Matrix<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Scale3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Shift3f__(ref List<Matrix<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Shift3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Shift3d__(ref List<Matrix<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Shift3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo2f__(ref List<Matrix<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Trafo2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo2d__(ref List<Matrix<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Trafo2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo3f__(ref List<Matrix<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Trafo3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo3d__(ref List<Matrix<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Trafo3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Bool__(ref List<Matrix<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Bool_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Char__(ref List<Matrix<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Char_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_String__(ref List<Matrix<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_String_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Type__(ref List<Matrix<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Type_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Guid__(ref List<Matrix<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Guid_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Symbol__(ref List<Matrix<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Symbol_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Circle2d__(ref List<Matrix<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Circle2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line2d__(ref List<Matrix<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Line2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line3d__(ref List<Matrix<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Line3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane2d__(ref List<Matrix<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Plane2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane3d__(ref List<Matrix<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Plane3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3d__(ref List<Matrix<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_PlaneWithPoint3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad2d__(ref List<Matrix<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Quad2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad3d__(ref List<Matrix<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Quad3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray2d__(ref List<Matrix<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Ray2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray3d__(ref List<Matrix<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Ray3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Sphere3d__(ref List<Matrix<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Sphere3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle2d__(ref List<Matrix<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Triangle2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle3d__(ref List<Matrix<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Triangle3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Circle2f__(ref List<Matrix<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Circle2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line2f__(ref List<Matrix<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Line2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line3f__(ref List<Matrix<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Line3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane2f__(ref List<Matrix<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Plane2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane3f__(ref List<Matrix<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Plane3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3f__(ref List<Matrix<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_PlaneWithPoint3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad2f__(ref List<Matrix<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Quad2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad3f__(ref List<Matrix<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Quad3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray2f__(ref List<Matrix<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Ray2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray3f__(ref List<Matrix<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Ray3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Sphere3f__(ref List<Matrix<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Sphere3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle2f__(ref List<Matrix<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Triangle2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle3f__(ref List<Matrix<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeMatrix_of_Triangle3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Byte__(ref List<Volume<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Byte_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_SByte__(ref List<Volume<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_SByte_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Short__(ref List<Volume<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Short_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_UShort__(ref List<Volume<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_UShort_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Int__(ref List<Volume<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Int_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_UInt__(ref List<Volume<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_UInt_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Long__(ref List<Volume<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Long_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_ULong__(ref List<Volume<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_ULong_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Float__(ref List<Volume<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Float_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Double__(ref List<Volume<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Double_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Fraction__(ref List<Volume<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Fraction_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2i__(ref List<Volume<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V2i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2l__(ref List<Volume<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V2l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2f__(ref List<Volume<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2d__(ref List<Volume<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3i__(ref List<Volume<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V3i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3l__(ref List<Volume<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V3l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3f__(ref List<Volume<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3d__(ref List<Volume<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4i__(ref List<Volume<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V4i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4l__(ref List<Volume<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V4l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4f__(ref List<Volume<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V4f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4d__(ref List<Volume<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_V4d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22i__(ref List<Volume<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M22i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22l__(ref List<Volume<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M22l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22f__(ref List<Volume<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M22f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22d__(ref List<Volume<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M22d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23i__(ref List<Volume<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M23i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23l__(ref List<Volume<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M23l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23f__(ref List<Volume<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M23f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23d__(ref List<Volume<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M23d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33i__(ref List<Volume<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M33i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33l__(ref List<Volume<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M33l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33f__(ref List<Volume<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M33f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33d__(ref List<Volume<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M33d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34i__(ref List<Volume<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M34i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34l__(ref List<Volume<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M34l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34f__(ref List<Volume<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M34f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34d__(ref List<Volume<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M34d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44i__(ref List<Volume<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M44i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44l__(ref List<Volume<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M44l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44f__(ref List<Volume<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M44f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44d__(ref List<Volume<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_M44d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3b__(ref List<Volume<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C3b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3us__(ref List<Volume<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C3us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3ui__(ref List<Volume<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C3ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3f__(ref List<Volume<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3d__(ref List<Volume<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4b__(ref List<Volume<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C4b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4us__(ref List<Volume<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C4us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4ui__(ref List<Volume<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C4ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4f__(ref List<Volume<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C4f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4d__(ref List<Volume<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_C4d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1b__(ref List<Volume<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1sb__(ref List<Volume<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1sb_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1s__(ref List<Volume<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1s_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1us__(ref List<Volume<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1i__(ref List<Volume<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1ui__(ref List<Volume<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1l__(ref List<Volume<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1ul__(ref List<Volume<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1ul_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1f__(ref List<Volume<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1d__(ref List<Volume<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Range1d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2i__(ref List<Volume<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Box2i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2l__(ref List<Volume<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Box2l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2f__(ref List<Volume<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Box2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2d__(ref List<Volume<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Box2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3i__(ref List<Volume<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Box3i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3l__(ref List<Volume<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Box3l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3f__(ref List<Volume<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Box3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3d__(ref List<Volume<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Box3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Euclidean3f__(ref List<Volume<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Euclidean3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Euclidean3d__(ref List<Volume<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Euclidean3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot2f__(ref List<Volume<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Rot2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot2d__(ref List<Volume<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Rot2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot3f__(ref List<Volume<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Rot3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot3d__(ref List<Volume<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Rot3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Scale3f__(ref List<Volume<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Scale3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Scale3d__(ref List<Volume<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Scale3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Shift3f__(ref List<Volume<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Shift3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Shift3d__(ref List<Volume<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Shift3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo2f__(ref List<Volume<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Trafo2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo2d__(ref List<Volume<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Trafo2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo3f__(ref List<Volume<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Trafo3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo3d__(ref List<Volume<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Trafo3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Bool__(ref List<Volume<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Bool_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Char__(ref List<Volume<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Char_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_String__(ref List<Volume<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_String_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Type__(ref List<Volume<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Type_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Guid__(ref List<Volume<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Guid_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Symbol__(ref List<Volume<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Symbol_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Circle2d__(ref List<Volume<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Circle2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line2d__(ref List<Volume<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Line2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line3d__(ref List<Volume<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Line3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane2d__(ref List<Volume<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Plane2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane3d__(ref List<Volume<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Plane3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3d__(ref List<Volume<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_PlaneWithPoint3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad2d__(ref List<Volume<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Quad2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad3d__(ref List<Volume<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Quad3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray2d__(ref List<Volume<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Ray2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray3d__(ref List<Volume<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Ray3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Sphere3d__(ref List<Volume<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Sphere3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle2d__(ref List<Volume<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Triangle2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle3d__(ref List<Volume<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Triangle3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Circle2f__(ref List<Volume<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Circle2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line2f__(ref List<Volume<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Line2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line3f__(ref List<Volume<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Line3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane2f__(ref List<Volume<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Plane2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane3f__(ref List<Volume<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Plane3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3f__(ref List<Volume<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_PlaneWithPoint3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad2f__(ref List<Volume<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Quad2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad3f__(ref List<Volume<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Quad3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray2f__(ref List<Volume<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Ray2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray3f__(ref List<Volume<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Ray3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Sphere3f__(ref List<Volume<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Sphere3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle2f__(ref List<Volume<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Triangle2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle3f__(ref List<Volume<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeVolume_of_Triangle3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Byte__(ref List<Tensor<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Byte_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_SByte__(ref List<Tensor<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_SByte_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Short__(ref List<Tensor<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Short_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_UShort__(ref List<Tensor<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_UShort_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Int__(ref List<Tensor<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Int_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_UInt__(ref List<Tensor<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_UInt_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Long__(ref List<Tensor<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Long_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_ULong__(ref List<Tensor<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_ULong_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Float__(ref List<Tensor<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Float_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Double__(ref List<Tensor<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Double_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Fraction__(ref List<Tensor<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Fraction_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2i__(ref List<Tensor<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V2i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2l__(ref List<Tensor<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V2l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2f__(ref List<Tensor<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2d__(ref List<Tensor<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3i__(ref List<Tensor<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V3i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3l__(ref List<Tensor<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V3l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3f__(ref List<Tensor<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3d__(ref List<Tensor<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4i__(ref List<Tensor<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V4i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4l__(ref List<Tensor<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V4l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4f__(ref List<Tensor<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V4f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4d__(ref List<Tensor<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_V4d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22i__(ref List<Tensor<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M22i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22l__(ref List<Tensor<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M22l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22f__(ref List<Tensor<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M22f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22d__(ref List<Tensor<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M22d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23i__(ref List<Tensor<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M23i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23l__(ref List<Tensor<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M23l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23f__(ref List<Tensor<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M23f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23d__(ref List<Tensor<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M23d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33i__(ref List<Tensor<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M33i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33l__(ref List<Tensor<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M33l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33f__(ref List<Tensor<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M33f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33d__(ref List<Tensor<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M33d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34i__(ref List<Tensor<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M34i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34l__(ref List<Tensor<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M34l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34f__(ref List<Tensor<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M34f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34d__(ref List<Tensor<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M34d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44i__(ref List<Tensor<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M44i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44l__(ref List<Tensor<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M44l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44f__(ref List<Tensor<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M44f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44d__(ref List<Tensor<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_M44d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3b__(ref List<Tensor<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C3b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3us__(ref List<Tensor<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C3us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3ui__(ref List<Tensor<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C3ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3f__(ref List<Tensor<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3d__(ref List<Tensor<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4b__(ref List<Tensor<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C4b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4us__(ref List<Tensor<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C4us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4ui__(ref List<Tensor<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C4ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4f__(ref List<Tensor<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C4f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4d__(ref List<Tensor<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_C4d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1b__(ref List<Tensor<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1b_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1sb__(ref List<Tensor<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1sb_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1s__(ref List<Tensor<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1s_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1us__(ref List<Tensor<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1us_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1i__(ref List<Tensor<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1ui__(ref List<Tensor<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1ui_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1l__(ref List<Tensor<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1ul__(ref List<Tensor<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1ul_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1f__(ref List<Tensor<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1d__(ref List<Tensor<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Range1d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2i__(ref List<Tensor<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Box2i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2l__(ref List<Tensor<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Box2l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2f__(ref List<Tensor<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Box2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2d__(ref List<Tensor<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Box2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3i__(ref List<Tensor<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Box3i_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3l__(ref List<Tensor<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Box3l_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3f__(ref List<Tensor<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Box3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3d__(ref List<Tensor<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Box3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Euclidean3f__(ref List<Tensor<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Euclidean3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Euclidean3d__(ref List<Tensor<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Euclidean3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot2f__(ref List<Tensor<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Rot2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot2d__(ref List<Tensor<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Rot2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot3f__(ref List<Tensor<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Rot3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot3d__(ref List<Tensor<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Rot3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Scale3f__(ref List<Tensor<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Scale3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Scale3d__(ref List<Tensor<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Scale3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Shift3f__(ref List<Tensor<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Shift3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Shift3d__(ref List<Tensor<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Shift3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo2f__(ref List<Tensor<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Trafo2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo2d__(ref List<Tensor<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Trafo2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo3f__(ref List<Tensor<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Trafo3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo3d__(ref List<Tensor<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Trafo3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Bool__(ref List<Tensor<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Bool_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Char__(ref List<Tensor<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Char_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_String__(ref List<Tensor<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_String_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Type__(ref List<Tensor<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Type_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Guid__(ref List<Tensor<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Guid_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Symbol__(ref List<Tensor<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Symbol_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Circle2d__(ref List<Tensor<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Circle2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line2d__(ref List<Tensor<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Line2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line3d__(ref List<Tensor<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Line3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane2d__(ref List<Tensor<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Plane2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane3d__(ref List<Tensor<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Plane3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3d__(ref List<Tensor<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_PlaneWithPoint3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad2d__(ref List<Tensor<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Quad2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad3d__(ref List<Tensor<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Quad3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray2d__(ref List<Tensor<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Ray2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray3d__(ref List<Tensor<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Ray3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Sphere3d__(ref List<Tensor<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Sphere3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle2d__(ref List<Tensor<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Triangle2d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle3d__(ref List<Tensor<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Triangle3d_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Circle2f__(ref List<Tensor<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Circle2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line2f__(ref List<Tensor<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Line2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line3f__(ref List<Tensor<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Line3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane2f__(ref List<Tensor<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Plane2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane3f__(ref List<Tensor<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Plane3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3f__(ref List<Tensor<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_PlaneWithPoint3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad2f__(ref List<Tensor<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Quad2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad3f__(ref List<Tensor<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Quad3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray2f__(ref List<Tensor<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Ray2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray3f__(ref List<Tensor<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Ray3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Sphere3f__(ref List<Tensor<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Sphere3f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle2f__(ref List<Tensor<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Triangle2f_(ref x); }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle3f__(ref List<Tensor<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++) { var x = value[i]; CodeTensor_of_Triangle3f_(ref x); }\r\n        }\r\n\r\n        #endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/BinaryWritingCoder_template.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Coder\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var directlyCodeableTypes = Meta.DirectlyCodeableTypes.Map(t =>t.Name);\n    //# var geometryTypes = Meta.GeometryTypes.Map(t => t.Name);\n    //# var specialSimpleTypes = new[] { \"bool\", \"char\", \"string\", \"Type\", \"Guid\", \"Symbol\" };\n    //# var structTypes = new List<string>();\n    //# var fastStructTypes = new List<string>();\n    public partial class BinaryWritingCoder\n    {\n        #region Vectors\n\n        //# foreach (var t in Meta.VecTypes) { fastStructTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value)\n        {\n            //# t.Fields.ForEach(f => {\n            m_writer.Write(value.__f__);\n            //# });\n        }\n\n        //# }\n        #endregion\n\n        #region Matrices\n\n        //# foreach (var t in Meta.MatTypes) { fastStructTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value) { m_writer.Write(value); }\n        //# }\n\n        #endregion\n\n        #region Ranges and Boxes\n\n        //# foreach (var t in Meta.RangeAndBoxTypes) { fastStructTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value)\n        {\n            m_writer.Write(value.Min); m_writer.Write(value.Max);\n        }\n\n        //# }\n        #endregion\n\n        #region Geometry types\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"Double\" : \"Float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        public void CodeCircle2__tc__(ref Circle2__tc__ v)\n        {\n            CodeV2__tc__(ref v.Center); Code__ftype__(ref v.Radius);\n        }\n\n        public void CodeLine2__tc__(ref Line2__tc__ v)\n        {\n            CodeV2__tc__(ref v.P0); CodeV2__tc__(ref v.P1);\n        }\n\n        public void CodeLine3__tc__(ref Line3__tc__ v)\n        {\n            CodeV3__tc__(ref v.P0); CodeV3__tc__(ref v.P1);\n        }\n\n        public void CodePlane2__tc__(ref Plane2__tc__ v)\n        {\n            CodeV2__tc__(ref v.Normal); Code__ftype__(ref v.Distance);\n        }\n\n        public void CodePlane3__tc__(ref Plane3__tc__ v)\n        {\n            CodeV3__tc__(ref v.Normal); Code__ftype__(ref v.Distance);\n        }\n\n        public void CodePlaneWithPoint3__tc__(ref PlaneWithPoint3__tc__ v)\n        {\n            CodeV3__tc__(ref v.Normal); CodeV3__tc__(ref v.Point);\n        }\n\n        public void CodeQuad2__tc__(ref Quad2__tc__ v)\n        {\n            CodeV2__tc__(ref v.P0); CodeV2__tc__(ref v.P1); CodeV2__tc__(ref v.P2); CodeV2__tc__(ref v.P3);\n        }\n\n        public void CodeQuad3__tc__(ref Quad3__tc__ v)\n        {\n            CodeV3__tc__(ref v.P0); CodeV3__tc__(ref v.P1); CodeV3__tc__(ref v.P2); CodeV3__tc__(ref v.P3);\n        }\n\n        public void CodeRay2__tc__(ref Ray2__tc__ v)\n        {\n            CodeV2__tc__(ref v.Origin); CodeV2__tc__(ref v.Direction);\n        }\n\n        public void CodeRay3__tc__(ref Ray3__tc__ v)\n        {\n            CodeV3__tc__(ref v.Origin); CodeV3__tc__(ref v.Direction);\n        }\n\n        public void CodeSphere3__tc__(ref Sphere3__tc__ v)\n        {\n            CodeV3__tc__(ref v.Center); Code__ftype__(ref v.Radius);\n        }\n\n        public void CodeTriangle2__tc__(ref Triangle2__tc__ v)\n        {\n            CodeV2__tc__(ref v.P0); CodeV2__tc__(ref v.P1); CodeV2__tc__(ref v.P2);\n        }\n\n        public void CodeTriangle3__tc__(ref Triangle3__tc__ v)\n        {\n            CodeV3__tc__(ref v.P0); CodeV3__tc__(ref v.P1); CodeV3__tc__(ref v.P2);\n        }\n\n        //# }\n        #endregion\n\n        #region Colors\n\n        //# foreach (var t in Meta.ColorTypes) { fastStructTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value)\n        {\n            //# t.Fields.ForEach(f => {\n            m_writer.Write(value.__f__);\n            //# });\n        }\n\n        //# }\n        #endregion\n\n        #region Trafos\n\n        //# foreach (var t in Meta.TrafoTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ value) { m_writer.Write(value); }\n        //# }\n\n        #endregion\n\n        #region Tensors\n\n        //# foreach (var t in geometryTypes) structTypes.Add(t);\n        //# var simpleTypes = directlyCodeableTypes.Concat(specialSimpleTypes).Concat(geometryTypes);\n        //# var genericTensorTypes = new[] { \"Vector\", \"Matrix\", \"Volume\", \"Tensor\" };\n        //# var genericTensorSizes = new[] { \"long\", \"V2l\", \"V3l\", \"long[]\" };\n        //# genericTensorTypes.ForEach((tt, ti) => {\n        //#     var ts = genericTensorSizes[ti]; var tsn = Meta.GetXmlTypeName(ts);\n        //#     simpleTypes.ForEach(t => {\n        //#         var type = tt + \"<\" + t + \">\";\n        //#         structTypes.Add(type);\n        //# var dname = Meta.GetXmlTypeName(t + \"[]\");\n        //# var name = Meta.GetXmlTypeName(type);\n        public void Code__name__(ref __type__ value)\n        {\n            var data = value.Data; Code__dname__(ref data);\n            var origin = value.Origin; CodeLong(ref origin);\n            var size = value.Size; Code__tsn__(ref size);\n            var delta = value.Delta; Code__tsn__(ref delta);\n        }\n\n        //#     });\n        //# });\n        #endregion\n\n        #region Arrays\n\n        //# fastStructTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            m_writer.WriteArray(value, 0, count);\n        }\n\n        //# });\n        //# structTypes.ForEach(t => {\n        //# var ename = Meta.GetXmlTypeName(t);\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) Code__ename__(ref value[i]);\n        }\n\n        //# });\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[,]\");\n        public void Code__name2d__(ref __t__[,] value)\n        {\n            long[] countArray = CodeCountLong(ref value);\n            long c0 = countArray[0]; if (c0 < 1) return;\n            long c1 = countArray[1]; if (c1 < 1) return;\n            m_writer.WriteArray(value, c0 * c1);\n        }\n\n        //# var name3d = Meta.GetXmlTypeName(t + \"[,,]\");\n        public void Code__name3d__(ref __t__[, ,] value)\n        {\n            long[] countArray = CodeCountLong(ref value);\n            long c0 = countArray[0]; if (c0 < 1) return;\n            long c1 = countArray[1]; if (c1 < 1) return;\n            long c2 = countArray[2]; if (c2 < 1) return;\n            m_writer.WriteArray(value, c0 * c1 * c2);\n        }\n\n        //# });\n        #endregion\n\n        #region Jagged Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var ename2d = Meta.GetXmlTypeName(t + \"[]\");\n        //# var name2d = Meta.GetXmlTypeName(t + \"[][]\");\n        public void Code__name2d__(ref __t__[][] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) Code__ename2d__(ref value[i]);\n        }\n\n        //# var ename3d = Meta.GetXmlTypeName(t + \"[][]\");\n        //# var name3d = Meta.GetXmlTypeName(t + \"[][][]\");\n        public void Code__name3d__(ref __t__[][][] value)\n        {\n            long count = CodeCountLong(ref value);\n            if (count < 1) return;\n            for (long i = 0; i < count; i++) Code__ename3d__(ref value[i]);\n        }\n\n        //# });\n        #endregion\n\n        #region Lists\n\n        //# fastStructTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            m_writer.WriteList(value, 0, count);\n        }\n\n        //# });\n        //# structTypes.ForEach(t => {\n        //# var ename = Meta.GetXmlTypeName(t);\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++) { var x = value[i]; Code__ename__(ref x); }\n        }\n\n        //# });\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/ChunkedMemoryStream.cs",
    "content": "﻿using Aardvark.Base;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace Aardvark.Base.Coder\n{\n    public class ChunkedMemoryStream : Stream\n    {\n        private readonly long m_chunkSize;\n        readonly List<byte[]> m_chunkList;\n\n        private long m_position;\n        private int m_posChunk;\n        private long m_posOffset;\n        private long m_length;\n\n        #region Constructor\n\n        public ChunkedMemoryStream(long chunkSize)\n        {\n            m_chunkSize = chunkSize;\n            m_chunkList = new List<byte[]>();\n            m_chunkList.Add(new byte[m_chunkSize]);\n            m_position = 0L;\n            m_posChunk = 0;\n            m_posOffset = 0L;\n\n            m_length = 0L;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public override bool CanRead\n        {\n            get { return true; }\n        }\n\n        public override bool CanSeek\n        {\n            get { return true; }\n        }\n\n        public override bool CanWrite\n        {\n            get { return true; }\n        }\n\n        public override long Length\n        {\n            get { return m_length; }\n        }\n\n        public override long Position\n        {\n            get\n            {\n                return m_position;\n            }\n            set\n            {\n                m_position = value;\n                m_posChunk = (int)(value / m_chunkSize);\n                m_posOffset = m_position % m_chunkSize;\n            }\n        }\n\n        public List<byte[]> ChunkList\n        {\n            get { return m_chunkList; }\n        }\n\n        #endregion\n\n        public override void Flush()\n        {\n        }\n\n        public override int ReadByte()\n        {\n            if (m_position < m_length)\n            {\n                int value = m_chunkList[m_posChunk][m_posOffset++];\n                m_position++;\n                if (m_posOffset >= m_chunkSize) { m_posChunk++; m_posOffset = 0L; }\n                return value;\n            }\n            else\n                return -1;\n        }\n\n        public override int Read(byte[] buffer, int offset, int count)\n        {\n            count = Fun.Min(count, (int)(m_length - m_position));\n            int done = 0;\n            while (done < count)\n            {\n                var block = (int)Fun.Min((long)(count - done), m_chunkSize - m_posOffset);\n\n                var chunk = m_chunkList[m_posChunk];\n                for (int end = offset + block; offset < end; offset++)\n                    buffer[offset] = chunk[m_posOffset++];\n\n                if (m_posOffset >= m_chunkSize) { ++m_posChunk; m_posOffset = 0L; }\n\n                done += block;\n            }\n            m_position += done;\n            return done;\n        }\n\n        public override long Seek(long offset, SeekOrigin origin)\n        {\n            switch (origin)\n            {\n                case SeekOrigin.Begin: m_position = offset; break;\n                case SeekOrigin.Current: m_position += offset; break;\n                case SeekOrigin.End: m_position = m_length + offset; break;\n            }\n            m_posChunk = (int)(m_position / m_chunkSize);\n            m_posOffset = m_position % m_chunkSize;\n            return m_position;\n        }\n\n        public override void SetLength(long value)\n        {\n            var newChunk = (int)(value / m_chunkSize);\n            var oldChunk = (int)(m_length / m_chunkSize);\n\n            if (oldChunk > newChunk)\n            {\n                m_chunkList.RemoveRange(newChunk + 1, oldChunk - newChunk);\n            }\n            else if (oldChunk < newChunk)\n            {\n                while (oldChunk < newChunk)\n                {\n                    m_chunkList.Add(new byte[m_chunkSize]);\n                    oldChunk++;\n                }\n            }\n            m_length = value;\n        }\n\n        public override void WriteByte(byte value)\n        {\n            m_chunkList[m_posChunk][m_posOffset++] = value;\n            if (m_posOffset >= m_chunkSize)\n            {\n                ++m_posChunk; m_posOffset = 0;\n                if (m_posChunk >= m_chunkList.Count)\n                    m_chunkList.Add(new byte[m_chunkSize]);\n            }\n            ++m_position; if (m_position > m_length) m_length = m_position;\n        }\n\n        public override void Write(byte[] buffer, int offset, int count)\n        {\n            int done = 0;\n            while (done < count)\n            {\n                var block = (int)Fun.Min((long)(count - done), m_chunkSize - m_posOffset);\n\n                var chunk = m_chunkList[m_posChunk];\n                for (int end = offset + block; offset < end; offset++)\n                    chunk[m_posOffset++] = buffer[offset];\n\n                if (m_posOffset >= m_chunkSize)\n                {\n                    ++m_posChunk; m_posOffset = 0L;\n                    if (m_posChunk >= m_chunkList.Count)\n                        m_chunkList.Add(new byte[m_chunkSize]);\n                }\n\n                done += block;\n            }\n            m_position += done; if (m_position > m_length) m_length = m_position;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/CodingExtensions.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.IO;\n\nnamespace Aardvark.Base.Coder\n{\n    public static class CodingExtensions\n    {\n        public static byte[] Encode<T>(this T self)\n        {\n            using (var stream = new MemoryStream())\n            {\n                using (var coder = new BinaryWritingCoder(stream))\n                {\n                    coder.CodeT(ref self);\n                }\n                return stream.ToArray();\n            }\n        }\n\n        public static T Decode<T>(this byte[] self)\n        {\n            using (var stream = new MemoryStream(self))\n            {\n                T result = default(T);\n                using (var coder = new BinaryReadingCoder(stream)) coder.CodeT(ref result);\n                return result;\n            }\n        }\n\n        public static void CodeColFormat(this ICoder coder, ref Col.Format colFormat)\n        {\n            var reading = coder.IsReading;\n            string formatName = reading ? null : colFormat.GetName().ToString();\n            coder.CodeString(ref formatName);\n            if (reading) colFormat = Col.FormatOfName(formatName);\n        }\n\n        public static void CodePixFormat(this ICoder coder, ref PixFormat pixFormat)\n        {\n            var reading = coder.IsReading;\n            Type type = reading ? null : pixFormat.Type;\n            string formatName = reading ? null : pixFormat.Format.GetName().ToString();\n            coder.CodeType(ref type);\n            coder.CodeString(ref formatName);\n            if (reading) pixFormat = new PixFormat(type, Col.FormatOfName(formatName));\n        }\n\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/Converter.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\n\nnamespace Aardvark.Base.Coder\n{\n    [RegisterTypeInfo]\n    public class Convertible : IFieldCodeable, IEquatable<Convertible>\n    {\n        public class IllegalSizeException : Exception\n        {\n            public IllegalSizeException(string message)\n                : base(message)\n            { }\n        };\n\n        private string m_descriptor;\n        private object m_data;\n\n        #region Constructors\n\n        public Convertible() { }\n\n        public Convertible(string descriptor)\n            : this(descriptor, null)\n        { }\n\n        public Convertible(string descriptor, object data)\n        {\n            m_descriptor = descriptor;\n            m_data = data;\n        }\n\n        // This resolves a resources leak when loading Bitmaps, but apparently breaks SlimDX10 rendering.\n        //~Convertible()\n        //{\n        //    if (m_data is IDisposable)\n        //    {\n        //        var d = m_data as IDisposable;\n        //        d.Dispose();\n        //    }\n        //}\n\n        #endregion\n\n        #region Properties\n\n        public string Descriptor { get { return m_descriptor; } }\n\n        public object Data\n        {\n            get { return m_data; }\n            set { m_data = value; }\n        }\n        #endregion\n\n        #region Static Creator Functions\n\n        /// <summary>\n        /// Creates a convertible given its description (a matching creator must be registered).\n        /// </summary>\n        public static Convertible FromDescriptor(string descriptor)\n        {\n            return Converter.Global.FromDescriptor(descriptor);\n        }\n\n        /// <summary>\n        /// Creates a file convertible given a file name (a matching creator must be registered).\n        /// </summary>\n        public static Convertible FromFile(string fileName)\n        {\n            return Converter.Global.FindConvertibleByFileName(fileName);\n        }\n\n        /// <summary>\n        /// Creates a file convertible given a file name and a preferrable target used to\n        /// determine the shortest possible path (a matching creator must be registered).\n        /// </summary>\n        public static Convertible FromFile(string fileName, Convertible preferrableTarget)\n        {\n            return Converter.Global.FindConvertibleByFileName(fileName, preferrableTarget);\n        }\n\n        /// <summary>\n        /// Creates a file convertible given a file name and a preferrable target used to the\n        /// determine the shortest possible path (a matching creator must be registered).\n        /// </summary>\n        public static Convertible FromFile(string fileName, string preferrableTargetDescriptor)\n        {\n            return Converter.Global.FindConvertibleByFileName(fileName, preferrableTargetDescriptor);\n        }\n\n        /// <summary>\n        /// Creates a matching raw convertible from a given convertible (a matching raw convertible\n        /// creator must be registered).\n        /// </summary>\n        public static Convertible FindMatchingRaw(Convertible c)\n        {\n            return Converter.Global.FindMatchingRaw(c);\n        }\n\n        /// <summary>\n        /// Creates a matching raw convertible from a given convertible and a preferrable target\n        /// used to the determine the shortest possible path (a matching raw convertible creator\n        /// must be registered).\n        /// </summary>\n        public static Convertible FindMatchingRaw(Convertible c, Convertible preferrableTarget)\n        {\n            return Converter.Global.FindMatchingRaw(c, preferrableTarget);\n        }\n\n        /// <summary>\n        /// Creates a matching raw convertible from a given convertible and a preferrable target\n        /// used to the determine the shortest possible path (a matching raw convertible creator\n        /// must be registered).\n        /// </summary>\n        public static Convertible FindMatchingRaw(Convertible c, string preferrableTargetDescriptor)\n        {\n            return Converter.Global.FindMatchingRaw(c, preferrableTargetDescriptor);\n        }\n\n        #endregion\n\n        #region Conversion Methods\n\n        /// <summary>\n        /// Sets (i.e., replaces) the convertible.\n        /// </summary>\n        public void SetTo(Convertible convertible)\n        {\n            m_descriptor = convertible.m_descriptor;\n            m_data = convertible.m_data;\n        }\n\n        /// <summary>\n        /// Transmogrifies the convertible into the target convertible without\n        /// changing the target. Returns this.\n        /// </summary>\n        public Convertible ChangeInto(Convertible target)\n        {\n            var newConv = new Convertible(target.Descriptor, target.Data);\n            ConvertInto(newConv);\n            SetTo(newConv);\n            return this;\n        }\n\n        /// <summary>\n        /// Converts the convertible into the target, that is modified.\n        /// </summary>\n        public void ConvertInto(Convertible target)\n        {\n            Converter.Global.Convert(this, target);\n        }\n\n        /// <summary>\n        /// Returns the convertible converted to the target convertible without\n        /// changing the target.\n        /// </summary>\n        public Convertible ConvertedTo(Convertible target)\n        {\n            var newConv = new Convertible(target.Descriptor, target.Data);\n            ConvertInto(newConv);\n            return newConv;\n        }\n\n        #endregion\n\n        #region Query Methods\n\n        /// <summary>\n        /// Returns whether a convertible is directly convertible into the target.\n        /// </summary>\n        public bool IsDirectConvertibleTo(Convertible target)\n        {\n            return Converter.Global.IsDirectConversionPossible(this, target);\n        }\n\n        /// <summary>\n        /// Returns whether a convertible is convertible into the target.\n        /// </summary>\n        public bool IsConvertibleTo(Convertible target)\n        {\n            return Converter.Global.IsConversionPossible(this, target);\n        }\n\n        /// <summary>\n        /// Returns whether a convertible has data assigned.\n        /// </summary>\n        public bool HasData\n        {\n            get { return (m_data != null); }\n        }\n\n        #endregion\n\n        #region IFieldCodeable Members\n\n        public IEnumerable<FieldCoder> GetFieldCoders(int coderVersion)\n        {\n            yield return new FieldCoder(0, \"Descriptor\", (c, o) => c.CodeString(ref ((Convertible)o).m_descriptor));\n            yield return new FieldCoder(1, \"Data\", (c, o) => c.CodeT(ref ((Convertible)o).m_data));\n        }\n\n        #endregion\n\n        #region IEquatable<Convertible> Members\n\n        public bool Equals(Convertible other)\n        {\n            if (!m_descriptor.Equals(other.m_descriptor)) return false;\n            if (!m_data.Equals(other.m_data)) return false;\n            return true;\n        }\n\n        #endregion\n\n        #region HashCode and Equals\n\n        public override int GetHashCode()\n        {\n            return HashCode.GetCombinedWithDefaultZero(m_descriptor, m_data);\n        }\n\n        public override bool Equals(object other)\n        {\n            var otherConvertible = other as Convertible;\n            if (otherConvertible == null) return false;\n            return Equals(otherConvertible);\n        }\n\n        public static bool operator ==(Convertible a, Convertible b)\n        {\n            if (object.ReferenceEquals(a, b)) return true;\n            if (object.ReferenceEquals(a, null)) return false;\n            if (object.ReferenceEquals(b, null)) return false;\n\n            return a.Equals(b);\n        }\n\n        public static bool operator !=(Convertible a, Convertible b)\n        {\n            if (object.ReferenceEquals(a, b)) return false;\n            if (object.ReferenceEquals(a, null)) return true;\n            if (object.ReferenceEquals(b, null)) return true;\n\n            return !a.Equals(b);\n        }\n\n        #endregion\n    }\n\n    internal class Converter\n    {\n        #region Statics and Consts\n\n        /// <summary>\n        /// The one global converter.\n        /// </summary>\n        public static readonly Converter Global = new Converter();\n\n        private const int c_distanceUnreachable = 200;\n        private const int c_distanceComplex = 100;\n\n        #endregion\n\n        #region Members\n\n        private struct RoutingEntry\n        {\n            public string Next;\n            public int Distance;\n        }\n\n        private bool m_initialized = false;\n        private SpinLock m_spinLock = new SpinLock();\n\n        private readonly Dictionary<(string, string), Action<Convertible, Convertible>>\n            m_actionMap = new Dictionary<(string, string), Action<Convertible, Convertible>>();\n\n        private readonly Dictionary<(string, string), Annotation[]>\n            m_annotationsMap = new Dictionary<(string, string), Annotation[]>();\n\n        private readonly Dictionary<string, Dictionary<string, RoutingEntry>>\n            m_routingMap = new Dictionary<string, Dictionary<string, RoutingEntry>>();\n\n        private readonly Dictionary<(string, string), int>\n            m_weightMap = new Dictionary<(string, string), int>();\n\n        private readonly Dictionary<string, List<Func<string, Convertible>>>\n            m_fileExtensionsMap = new Dictionary<string, List<Func<string, Convertible>>>();\n\n        private readonly Dictionary<string, List<Func<Convertible>>>\n            m_rawConvertiblesMap = new Dictionary<string, List<Func<Convertible>>>();\n\n        private readonly Dictionary<string, List<Func<Convertible>>>\n            m_creatorsMap = new Dictionary<string, List<Func<Convertible>>>();\n\n        private readonly Dictionary<string, List<string>>\n            m_resourcesMap = new Dictionary<string, List<string>>();\n\n        private readonly List<string> m_availableResources = new List<string>();\n\n        #endregion\n\n        #region Constructor, Kernel startup\n\n        static Converter()\n        {\n            Init();\n        }\n\n        /// <summary>\n        /// Builds the initial routing table.\n        /// </summary>\n        public static void Init()\n        {\n            Global.BuildRoutingTables();\n        }\n\n        /// <summary>\n        /// Creates a new converter with an empty routing table and no registered conversions.\n        /// </summary>\n        public Converter()\n        {\n        }\n\n        /// <summary>\n        /// Creates a new converter by copying an existing one.\n        /// </summary>\n        public Converter(Converter converter)\n        {\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                this.m_initialized = converter.m_initialized;\n                this.m_availableResources = new List<string>(converter.m_availableResources);\n                this.m_actionMap = converter.m_actionMap.Copy();\n                this.m_annotationsMap = converter.m_annotationsMap.Copy();\n                this.m_weightMap = converter.m_weightMap.Copy();\n                this.m_fileExtensionsMap = Clone(converter.m_fileExtensionsMap);\n                this.m_rawConvertiblesMap = Clone(converter.m_rawConvertiblesMap);\n                this.m_creatorsMap = Clone(converter.m_creatorsMap);\n                this.m_resourcesMap = Clone(converter.m_resourcesMap);\n                this.m_routingMap = converter.CloneRoutingTable();\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Clones this converter and returns the new one.\n        /// </summary>\n        private Converter Clone()\n        {\n            return new Converter(this);\n        }\n\n        /// <summary>\n        /// Internal method for cloning a dictionary which contains a list.\n        /// </summary>\n        private Dictionary<string, List<T>> Clone<T>(Dictionary<string, List<T>> dictionary)\n        {\n            var clonedDictionary = new Dictionary<string, List<T>>(dictionary.Count);\n            foreach (var kvp in dictionary)\n                clonedDictionary[kvp.Key] = new List<T>(kvp.Value);\n            return clonedDictionary;\n        }\n\n        #endregion\n\n        #region Conversion\n\n        /// <summary>\n        /// Converts the source convertible into the target convertible.\n        /// There are 3 possibilities here:\n        ///     1) There is a direct conversion possible, this works no matter if the conversion requires user-set parameters.\n        ///     2) No direct conversion available. The conversion can be done indirectly in two cases:\n        ///             - there is no conversion with user parameters needed.\n        ///             - the only conversion with user parameters is the last one.\n        ///             ... in all other cases the conversion is not possible.\n        ///     3) The conversion would need more than two conversion with user parameters, which can not be done.\n        /// </summary>\n        /// <param name=\"source\">The source convertible</param>\n        /// <param name=\"target\">The target convertible (result will be stored in target.Data)</param>\n        public void Convert(Convertible source, Convertible target)\n        {\n            Convert(source, target, CloneRoutingTable(), new List<Convertible>());\n        }\n\n        /// <summary>\n        /// Private helper for public Convert method above.\n        /// </summary>\n        private void Convert(\n            Convertible source, Convertible target,\n            Dictionary<string, Dictionary<string, RoutingEntry>> routingMap,\n            List<Convertible> tempConvertibles)\n        {\n            var sourceDescr = source.Descriptor;\n            var targetDescr = target.Descriptor;\n\n            if (sourceDescr == targetDescr)\n            {\n                DirectConvert(source, target);\n                return;\n            }\n\n            try\n            {\n                int distance = routingMap[sourceDescr][targetDescr].Distance;\n\n                if (distance == 1 || distance == c_distanceComplex)\n                {\n                    DirectConvert(source, target);\n\n                    if (tempConvertibles != null)\n                    {\n                        // dispose any temporary convertibles\n                        foreach (var temp in tempConvertibles)\n                        {\n                            if (!temp.Data.Equals(target.Data))\n                            {\n                                var tempDisposable = temp.Data as IDisposable;\n                                if (tempDisposable != null)\n                                    tempDisposable.Dispose();\n                            }\n                        }\n\n                        tempConvertibles.Clear();\n                    }\n                }\n                else if (distance < c_distanceUnreachable)\n                {\n                    int lastDistance = FindLastDistance(sourceDescr, targetDescr);\n\n                    if ((distance < c_distanceComplex) || (lastDistance == c_distanceComplex))\n                    {\n                        Convertible tmp = new Convertible(routingMap[sourceDescr][targetDescr].Next, null);\n\n                        DirectConvert(source, tmp);\n\n                        if (tempConvertibles == null)\n                            tempConvertibles = new List<Convertible>();\n                        tempConvertibles.Add(tmp);\n\n                        Convert(tmp, target, routingMap, tempConvertibles);\n                    }\n                    else\n                    {\n                        throw new ConversionNotPossibleException(sourceDescr, targetDescr, \"not reachable 1\");\n                    }\n                }\n                else\n                {\n                    throw new ConversionNotPossibleException(sourceDescr, targetDescr, \"not reachable 2\");\n                }\n            }\n            catch (KeyNotFoundException)\n            {\n                throw new ConversionNotPossibleException(sourceDescr, targetDescr, \"key not found\");\n            }\n        }\n\n        /// <summary>\n        /// Direct conversion between two convertibles.\n        /// </summary>\n        private void DirectConvert(Convertible source, Convertible target)\n        {\n            if (source.Data == null) throw new ArgumentNullException();\n\n            var conversion = (source.Descriptor, target.Descriptor);\n\n            Action<Convertible, Convertible> procedure;\n            if (m_actionMap.TryGetValue(conversion, out procedure))\n                procedure(source, target);\n            else if (source.Descriptor == target.Descriptor)\n            {\n                target.Data = source.Data;\n            }\n            else\n                throw new ConversionNotPossibleException(source.Descriptor, target.Descriptor, \"convert failed\");\n        }\n\n        /// <summary>\n        /// Returns whether a direct conversion between two convertibles is possible.\n        /// </summary>\n        public bool IsDirectConversionPossible(Convertible source, Convertible target)\n        {\n            return IsDirectConversionPossible(source.Descriptor, target.Descriptor);\n        }\n\n        /// <summary>\n        /// Returns whether a direct conversion between two convertibles is possible.\n        /// </summary>\n        public bool IsDirectConversionPossible(string source, string target)\n        {\n            if (source == target) return true;\n            int distance = m_routingMap[source][target].Distance;\n            return distance == 1 || distance == c_distanceComplex;\n        }\n\n        /// <summary>\n        /// Returns whether a conversion will work or not.\n        /// </summary>\n        public bool IsConversionPossible(Convertible source, Convertible target)\n        {\n            return IsConversionPossible(source.Descriptor, target.Descriptor);\n        }\n\n        /// <summary>\n        /// Returns whether a conversion will work or not.\n        /// </summary>\n        public bool IsConversionPossible(string source, string target)\n        {\n            if (source == target) return true;\n\n            try\n            {\n                int distance = m_routingMap[source][target].Distance;\n\n                // direct conversion without params || direct conversion with params\n                if (distance == 1 || distance == c_distanceComplex)\n                {\n                    return true;\n                }\n                // conversion chain with at most one step requiring params\n                else if (distance < c_distanceUnreachable)\n                {\n                    // get weight of last step in chain\n                    int lastDistance = FindLastDistance(source, target);\n\n                    // if all steps of chain are steps without params || only last step requires params\n                    if ((distance < c_distanceComplex) || (lastDistance == c_distanceComplex))\n                        return true;\n                    else\n                        return false;\n                }\n                else\n                    return false;\n            }\n            catch (KeyNotFoundException)\n            {\n                return false;\n            }\n        }\n\n        #endregion\n\n        #region Registration\n\n        /// <summary>\n        /// Registers a parameterless conversion from a\n        /// source convertible to a target convertible.\n        /// </summary>\n        public void Register(\n            string sourceDescriptor, string targetDescriptor,\n            Action<Convertible, Convertible> procedure)\n        {\n            if (string.IsNullOrEmpty(sourceDescriptor) ||\n                string.IsNullOrEmpty(targetDescriptor) ||\n                procedure == null) throw new ArgumentNullException();\n            Register(sourceDescriptor, targetDescriptor, procedure, false);\n        }\n\n        /// <summary>\n        /// Registers a parameterless conversion from a\n        /// source convertible to a target convertible,\n        /// and a list of annotations for this action.\n        /// </summary>\n        public void Register(\n            string sourceDescriptor, string targetDescriptor,\n            Action<Convertible, Convertible> procedure,\n            IEnumerable<Annotation> annotations)\n        {\n            if (string.IsNullOrEmpty(sourceDescriptor) ||\n                string.IsNullOrEmpty(targetDescriptor) ||\n                procedure == null) throw new ArgumentNullException();\n            Register(sourceDescriptor, targetDescriptor, procedure, false);\n            Register(sourceDescriptor, targetDescriptor, annotations);\n        }\n\n        /// <summary>\n        /// This registers a conversion from a source convertible described\n        /// by a descriptor to a target convertible.\n        /// </summary>\n        /// <param name=\"sourceDescriptor\">The source descriptor</param>\n        /// <param name=\"targetDescriptor\">The target descriptor</param>\n        /// <param name=\"procedure\">The conversion method converting source to target (result is stored in target.Data)</param>\n        /// <param name=\"parameterRequired\">\n        /// Whether a user-set parameter is required for the conversion. This is important for conversion chaining. If no direct\n        /// conversion is possible, the chaining of conversion only works if there is no parameter required or the only conversion\n        /// with a parameter is the last one in the chain.\n        /// </param>\n        public void Register(\n            string sourceDescriptor, string targetDescriptor,\n            Action<Convertible, Convertible> procedure,\n            bool parameterRequired)\n        {\n            if (string.IsNullOrEmpty(sourceDescriptor) ||\n                string.IsNullOrEmpty(targetDescriptor) ||\n                procedure == null) throw new ArgumentNullException();\n\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                var conversion = (sourceDescriptor, targetDescriptor);\n                if (!m_actionMap.ContainsKey(conversion))\n                {\n                    m_actionMap[conversion] = procedure;\n\n                    if (parameterRequired)\n                        m_weightMap[conversion] = c_distanceComplex;\n                    else\n                        m_weightMap[conversion] = 1;\n                }\n                else\n                    throw new ArgumentException(\n                        String.Format(\n                            \"conversion from \\\"{0}\\\" to \\\"{1}\\\" \"\n                            + \"already registered\",\n                            sourceDescriptor, targetDescriptor));\n\n                if (!m_routingMap.ContainsKey(sourceDescriptor))\n                    AddNewRoutingObject(sourceDescriptor);\n\n                if (!m_routingMap.ContainsKey(targetDescriptor))\n                    AddNewRoutingObject(targetDescriptor);\n\n                if (m_initialized)\n                {\n                    AddDirectRoute(conversion);\n                    UpdateRoutingTable(conversion);\n                }\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Register a creator function for a given convertible, which allows convertibles\n        /// to be created using only their descriptor.\n        /// </summary>\n        public void RegisterCreator(string descriptor, Func<Convertible> creator)\n        {\n            if (string.IsNullOrEmpty(descriptor) || creator == null)\n                throw new ArgumentNullException();\n\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                if (!m_creatorsMap.ContainsKey(descriptor))\n                    m_creatorsMap[descriptor] = new List<Func<Convertible>>();\n\n                m_creatorsMap[descriptor].Add(creator);\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Registers a raw convertible for a given convertible descriptor.\n        /// </summary>\n        public void RegisterRaw(string descriptor, Func<Convertible> creator)\n        {\n            if (string.IsNullOrEmpty(descriptor) || creator == null)\n                throw new ArgumentNullException();\n\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                if (!m_rawConvertiblesMap.ContainsKey(descriptor))\n                    m_rawConvertiblesMap[descriptor] = new List<Func<Convertible>>();\n\n                m_rawConvertiblesMap[descriptor].Add(creator);\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Registers a file convertible for a given file extension.\n        /// </summary>\n        public void RegisterExtension(string fileExtension, Func<string, Convertible> creator)\n        {\n            if (string.IsNullOrEmpty(fileExtension) || creator == null)\n                throw new ArgumentNullException();\n\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                fileExtension = fileExtension.ToLower();\n\n                if (!m_fileExtensionsMap.ContainsKey(fileExtension))\n                    m_fileExtensionsMap[fileExtension] = new List<Func<string, Convertible>>();\n\n                m_fileExtensionsMap[fileExtension].Add(creator);\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Registers a resource for a descriptor.\n        /// </summary>\n        public void RegisterResource(string resource, string descriptor)\n        {\n            if (string.IsNullOrEmpty(resource) || string.IsNullOrEmpty(descriptor))\n                throw new ArgumentNullException();\n\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                if (!m_resourcesMap.ContainsKey(resource))\n                    m_resourcesMap[resource] = new List<string>();\n\n                m_resourcesMap[resource].Add(descriptor);\n\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Registers a resource for a list of descriptors.\n        /// </summary>\n        public void RegisterResource(string resource, List<string> descriptors)\n        {\n            if (string.IsNullOrEmpty(resource) || descriptors == null)\n                throw new ArgumentNullException();\n\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                if (!m_resourcesMap.ContainsKey(resource))\n                    m_resourcesMap[resource] = descriptors;\n                else\n                    m_resourcesMap[resource].AddRange(descriptors);\n\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Registers annotations for the conversion from given source to target.\n        /// Throws NullArgumentException if source- or target-descriptor is null.\n        /// Does nothing if annotations is null.\n        /// </summary>\n        public void Register(string sourceDescriptor, string targetDescriptor,\n            IEnumerable<Annotation> annotations)\n        {\n            if (string.IsNullOrEmpty(sourceDescriptor) || string.IsNullOrEmpty(targetDescriptor))\n                throw new ArgumentNullException();\n            if (annotations == null) return;\n            m_annotationsMap[(sourceDescriptor, targetDescriptor)] = annotations.ToArray();\n        }\n\n        #endregion\n\n        #region Routing table creation\n\n        private void AddNewRoutingObject(String descriptor)\n        {\n            // add new routing table\n            Dictionary<string, RoutingEntry> newRoutingTable = new Dictionary<string, RoutingEntry>();\n\n            // add existing targets to this one\n            foreach (string key in m_routingMap.Keys)\n                newRoutingTable[key] = new RoutingEntry() { Distance = 99999999 };\n\n            // add this new target to the existing routing tables\n            foreach (Dictionary<string, RoutingEntry> table in m_routingMap.Values)\n                table[descriptor] = new RoutingEntry() { Distance = 99999999 };\n\n            m_routingMap[descriptor] = newRoutingTable;\n        }\n\n        private void AddDirectRoute((string, string) conversion)\n        {\n            m_routingMap[conversion.Item1][conversion.Item2] =\n                    new RoutingEntry() { Distance = m_weightMap[conversion], Next = conversion.Item2 };\n        }\n\n        /// <summary>\n        /// Builds the static routing table and stores the shortest distances.\n        /// </summary>\n        public void BuildRoutingTables()\n        {\n            var keys = m_routingMap.Keys.ToList();\n\n            // clear all entries\n            foreach (var key1 in keys)\n                foreach (var key2 in keys)\n                    m_routingMap[key1][key2] = new RoutingEntry() { Distance = 99999999 };\n\n            var validConversions = (from conversion in m_actionMap.Keys\n                                    where AreAllResourcesAvailable(conversion.Item1) &&\n                                          AreAllResourcesAvailable(conversion.Item2)\n                                    select conversion).ToList();\n\n            // first add all direct routes\n            foreach (var conversion in validConversions)\n                AddDirectRoute(conversion);\n\n            // now go and find the indirect routes\n            foreach (var conversion in validConversions)\n                UpdateRoutingTable(conversion);\n\n            if (!m_initialized)\n                m_initialized = true;\n        }\n\n        /// <summary>\n        /// Clones the current routing table. This is usually done before a conversion is started\n        /// because the routing may be altered by a different thread (e.g. by setting invalid\n        /// convertibles).\n        /// </summary>\n        private Dictionary<string, Dictionary<string, RoutingEntry>> CloneRoutingTable()\n        {\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                var clonedTable = new Dictionary<string, Dictionary<string, RoutingEntry>>();\n                foreach (var kvp in m_routingMap)\n                    clonedTable[kvp.Key] = m_routingMap[kvp.Key].Copy();\n\n                return clonedTable;\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Updates the routing table with a conversion. If the conversion results\n        /// into a shorter path, the updates are propagated.\n        /// </summary>\n        private void UpdateRoutingTable((string, string) conversion)\n        {\n            Dictionary<string, RoutingEntry> tableToUpdate = m_routingMap[conversion.Item1];\n            Dictionary<string, RoutingEntry> tableWithNewInfo = m_routingMap[conversion.Item2];\n\n            bool updated = false;\n\n            var targetsToOptimize = (\n                from target in tableToUpdate.Keys\n                where target != conversion.Item2\n                select target\n            ).ToArray();\n\n            foreach (var target in targetsToOptimize)\n            {\n                int alternativeDistance = tableWithNewInfo[target].Distance + tableToUpdate[conversion.Item2].Distance;\n\n                // found a better way to the target\n                if (alternativeDistance < tableToUpdate[target].Distance)\n                {\n                    tableToUpdate[target] = new RoutingEntry()\n                    {\n                        Distance = alternativeDistance,\n                        Next = tableToUpdate[conversion.Item2].Next\n                    };\n                    updated = true;\n                }\n            }\n\n            if (updated)\n            {\n                foreach (var conv in m_actionMap.Keys)\n                {\n                    if (conv.Item2 == conversion.Item1)\n                        UpdateRoutingTable(conv);\n                }\n            }\n        }\n\n        #endregion\n\n        #region FindXYZ, FromXYZ, ...\n\n        /// <summary>\n        /// Creates a convertible from a descriptor. Only works if a creator function was\n        /// registered (see RegisterCreator).\n        /// </summary>\n        public Convertible FromDescriptor(string descriptor)\n        {\n            List<Func<Convertible>> creators;\n            if (!m_creatorsMap.TryGetValue(descriptor, out creators))\n                 return null;\n\n            var func = creators.First();\n            Convertible conv = func();\n\n            return conv;\n        }\n\n        /// <summary>\n        /// Returns a matching raw convertible for a convertible. Only works if a raw convertible\n        /// was registered (see RegisterRaw).\n        /// </summary>\n        public Convertible FindMatchingRaw(Convertible c)\n        {\n            var desc = c.Descriptor;\n\n            List<Func<Convertible>> creators;\n            if (!m_rawConvertiblesMap.TryGetValue(desc, out creators))\n                return null;\n\n            var func = creators.First();\n            Convertible conv = func();\n\n            return conv;\n        }\n\n        /// <summary>\n        /// Returns a matching raw convertible by also taking a preferred target into account.\n        /// Only works if a raw convertible was registered (see RegisterRaw).\n        /// </summary>\n        public Convertible FindMatchingRaw(Convertible conv, Convertible preferrableTarget)\n        {\n            return FindMatchingRaw(conv, preferrableTarget.Descriptor);\n        }\n\n        /// <summary>\n        /// Returns a matching raw convertible by also taking a preferred target into account.\n        /// Only works if a raw convertible was registered (see RegisterRaw).\n        /// </summary>\n        public Convertible FindMatchingRaw(Convertible conv, string preferrableTargetDescriptor)\n        {\n            List<Func<Convertible>> creators;\n            if (!m_rawConvertiblesMap.TryGetValue(conv.Descriptor, out creators))\n                return null;\n\n            var c = (from func in creators\n                     let source = func()\n                     let distance = m_routingMap[source.Descriptor][preferrableTargetDescriptor].Distance\n                     orderby distance ascending\n                     select source).First();\n            return c;\n        }\n\n        /// <summary>\n        /// Returns a matching file convertible given a file name.\n        /// Only works if a convertible was registered for the file extension (see RegisterExtension).\n        /// </summary>\n        public Convertible FindConvertibleByFileName(string fileName)\n        {\n            var fileExt = Path.GetExtension(fileName).ToLower();\n\n            List<Func<string, Convertible>> creators;\n            if (!m_fileExtensionsMap.TryGetValue(fileExt, out creators))\n                throw new ArgumentException(\"no convertible available for this file extension\", fileExt);\n\n            foreach (var func in creators)\n            {\n                Convertible conv = func(fileName);\n                if (AreAllResourcesAvailable(conv.Descriptor))\n                    return conv;\n            }\n\n            throw new ArgumentException(\"could not find a creator for this file extension\", fileExt);\n        }\n\n        /// <summary>\n        /// Returns a matching file convertible given a file name, taking a preferred target into account.\n        /// Only works if a convertible was registered for the file extension (see RegisterExtension).\n        /// </summary>\n        public Convertible FindConvertibleByFileName(string fileName, Convertible preferrableTarget)\n        {\n            return FindConvertibleByFileName(fileName, preferrableTarget.Descriptor);\n        }\n\n        /// <summary>\n        /// Returns a matching file convertible given a file name, taking a preferred target into account.\n        /// Only works if a convertible was registered for the file extension (see RegisterExtension).\n        /// </summary>\n        public Convertible FindConvertibleByFileName(string fileName, string preferrableTargetDescriptor)\n        {\n            var fileExt = Path.GetExtension(fileName).ToLower();\n\n            List<Func<string, Convertible>> creators;\n            if (!m_fileExtensionsMap.TryGetValue(fileExt, out creators))\n                return null;\n\n            var c = (from func in creators\n                     let source = func(fileName)\n                     let distance = m_routingMap[source.Descriptor][preferrableTargetDescriptor].Distance\n                     orderby distance ascending\n                     select source).First();\n            return c;\n        }\n\n        #endregion\n\n        #region Resources\n\n        /// <summary>\n        /// Sets whether a resource is available or not. By default, resources are\n        /// not available. If this is done after the routing table has been\n        /// initialized once, the routing table will be rebuilt (therefore, use\n        /// SetResourceAvailability(List{string} resources, bool available) if you need\n        /// to set the availability of multiple resources).\n        /// </summary>\n        public void SetResourceAvailability(string resource, bool available)\n        {\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                InternalSetAvailability(resource, available);\n\n                if (m_initialized)\n                    BuildRoutingTables();\n\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Sets whether resources are available or not. By default, resources are\n        /// not available. If this is done after the routing table has been\n        /// initialized once, the routing table will be rebuilt.\n        /// </summary>\n        public void SetResourceAvailability(List<string> resources, bool available)\n        {\n            bool lockTaken = false;\n            try\n            {\n                m_spinLock.Enter(ref lockTaken);\n\n                foreach (var resource in resources)\n                    InternalSetAvailability(resource, available);\n\n                if (m_initialized)\n                    BuildRoutingTables();\n            }\n            finally\n            {\n                if (lockTaken) m_spinLock.Exit();\n            }\n        }\n\n        /// <summary>\n        /// Sets the availability of a resource.\n        /// </summary>\n        private void InternalSetAvailability(string resource, bool available)\n        {\n            bool contained = m_availableResources.Contains(resource);\n\n            if (available && !contained)\n                m_availableResources.Add(resource);\n            else if (!available && contained)\n                m_availableResources.Remove(resource);\n        }\n\n        /// <summary>\n        /// Returns the required resources or null if none required.\n        /// </summary>\n        private List<string> RequiredResources(string descriptor)\n        {\n            var resources = new List<string>();\n\n            foreach (var kvp in m_resourcesMap)\n            {\n                if (kvp.Value.Contains(descriptor))\n                    resources.Add(kvp.Key);\n            }\n\n            return resources.Count > 0 ? resources : null;\n        }\n\n        /// <summary>\n        /// Returns whether a convertible can be used (i.e., all needed resources\n        /// are available).\n        /// </summary>\n        private bool AreAllResourcesAvailable(string descriptor)\n        {\n            var reqResources = RequiredResources(descriptor);\n\n            if (reqResources == null)\n                return true;\n\n            foreach (var res in reqResources)\n            {\n                if (!m_availableResources.Contains(res))\n                    return false;\n            }\n\n            return true;\n        }\n\n        #endregion\n\n        #region Queries\n\n        public struct Entry\n        {\n            public string SourceDescriptor;\n            public string TargetDescriptor;\n            public Action<Convertible, Convertible> Action;\n            public IEnumerable<Annotation> Annotations;\n        }\n\n        /// <summary>\n        /// Enumerates all conversions.\n        /// </summary>\n        public IEnumerable<Entry> Conversions\n        {\n            get\n            {\n                foreach (var kv in m_actionMap)\n                    yield return GetConversion(kv.Key.Item1, kv.Key.Item2);\n            }\n        }\n\n        /// <summary>\n        /// Gets conversion for given source- and target description.\n        /// </summary>\n        public Entry GetConversion(string sourceDescription, string targetDescription)\n        {\n            var key = (sourceDescription, targetDescription);\n            if (m_annotationsMap.ContainsKey(key))\n            {\n                return new Entry\n                {\n                    SourceDescriptor = sourceDescription,\n                    TargetDescriptor = targetDescription,\n                    Action = m_actionMap[key],\n                    Annotations = GetAnnotations(sourceDescription, targetDescription)\n                };\n            }\n            throw new ArgumentException();\n        }\n\n        /// <summary>\n        /// Enumerates all conversions in the specified conversion chain,\n        /// or returns null if no conversion exists.\n        /// </summary>\n        public IEnumerable<Entry> GetConversionChain(\n            string sourceDescription, string targetDescription)\n        {\n            if (string.IsNullOrEmpty(sourceDescription)) throw new ArgumentNullException();\n            if (string.IsNullOrEmpty(targetDescription)) throw new ArgumentNullException();\n            if (!m_routingMap.ContainsKey(sourceDescription)) throw new ArgumentException(\"unknow convertible\");\n            var tmp = m_routingMap[sourceDescription];\n            if (!tmp.ContainsKey(targetDescription)) return null; // no conversion exists\n\n            return EnumerateChain(sourceDescription, targetDescription);\n        }\n\n        /// <summary>\n        /// Enumerates annotations for given conversion.\n        /// </summary>\n        public IEnumerable<Annotation> GetAnnotations(string source, string target)\n        {\n            var key = (source, target);\n            if (m_annotationsMap.ContainsKey(key)) return m_annotationsMap[key];\n            return Array.Empty<Annotation>();\n        }\n\n        /// <summary>\n        /// Helper method for GetChain.\n        /// Requires that the conversion chain exists.\n        /// </summary>\n        private IEnumerable<Entry> EnumerateChain(string source, string target)\n        {\n            var next = m_routingMap[source][target].Next;\n            var proc = new[] { GetConversion(source, next) };\n\n            if (next == target) return proc;\n            return proc.Concat(EnumerateChain(next, target));\n        }\n\n        /// <summary>\n        /// Returns the \"last\" distance of a conversion chain.\n        /// Requires that the conversion chain exists.\n        /// </summary>\n        private int FindLastDistance(string source, string target)\n        {\n            if (m_routingMap[source][target].Next == target)\n                return m_routingMap[source][target].Distance;\n            else\n                return FindLastDistance(m_routingMap[source][target].Next, target);\n        }\n\n        #endregion\n    }\n\n    internal class ConversionNotPossibleException : Exception\n    {\n        public ConversionNotPossibleException(\n            string source, string target, string text)\n            : base(String.Format(\"unable to convert from \\\"{0}\\\" to \\\"{1}\\\": {2}\",\n                                 source, target, text))\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/FastObjectFactory.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.Reflection;\nusing System.Reflection.Emit;\n\nnamespace Aardvark.Base.Coder\n{\n    public static class FastObjectFactory\n    {\n        private static readonly FastConcurrentDict<Type, Func<object>> s_creatorCache =\n            new FastConcurrentDict<Type, Func<object>>();\n\n        /// <summary>\n        /// Returns an object factory that can be used to create instances\n        /// of the specified type T.\n        /// </summary>\n        public static Func<object> ObjectFactory(Type type)\n        {\n            var creator = s_creatorCache.Get(type, null);   // Some (non-exhaustive) tests\n            if (creator != null)                            // suggest this is faster than\n                return creator;                             // just using the call in the\n            else                                            // else branch.\n                return s_creatorCache.GetOrCreate(type, s_createObjectFun);\n        }\n\n        private static readonly Func<Type, Func<object>> s_createObjectFun = (Type t) =>\n        {\n            // get the parameterless constructor (including non-public) of the type t\n            var constructor = t.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);\n            if (constructor == null)\n                throw new InvalidOperationException(\n                    String.Format(\"cannot create object of type \\\"{0}\\\" - type does not have parameterless constructor\",\n                                  t.Name));\n            var dynMethod = new DynamicMethod(\"DM$OBJ_FACTORY_\" + t.Name, typeof(Func<object>), null, t);\n            ILGenerator ilGen = dynMethod.GetILGenerator();\n            ilGen.Emit(OpCodes.Newobj, constructor);\n            ilGen.Emit(OpCodes.Ret);\n            return (Func<object>)dynMethod.CreateDelegate(typeof(Func<object>));\n        };\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/FieldCoderExtensions.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Reflection.Emit;\n\nnamespace Aardvark.Base.Coder\n{\n    public static class FieldCoderExtensions\n    {\n        public static IEnumerable<FieldCoder> CreateFieldCoders(this IFieldCodeable self, params string[] members)\n        {\n            return CreateFieldCoders(self.GetType(), members);\n        }\n\n        public static IEnumerable<FieldCoder> CreateFieldCoders(this Type type, IEnumerable<string> members)\n        {\n            return CreateFieldCoders(type, members.ToArray());\n        }\n\n        public static IEnumerable<FieldCoder> CreateFieldCoders(this Type type, params string[] members)\n        {\n            foreach (var member in members)\n            {\n                var tokens = member.Split(new[] { '|' });\n                if (tokens.Length == 1) yield return CreateFieldCoder(type, member, member);\n                else if (tokens.Length == 2) yield return CreateFieldCoder(type, tokens[0], tokens[1]);\n                else throw new ArgumentException();\n            }\n        }\n\n        public static FieldCoder CreateFieldCoder(this IFieldCodeable self, string member)\n        {\n            return CreateFieldCoder(self, member, member);\n        }\n\n        public static FieldCoder CreateFieldCoder(this IFieldCodeable self, string name, string memberName)\n        {\n            return CreateFieldCoder(self.GetType(), name, memberName);\n        }\n\n        public static FieldCoder CreateFieldCoder(this Type type, string name, string memberName)\n        {\n            var field = type.GetField(memberName);\n            if (field != null)\n            {\n                // template:\n                // (c, o) => c.Code(ref ((Foo)o).m_myField)\n\n                var argumentTypes = new[] { typeof(ICoder), typeof(object) };\n\n                // create debug method\n                var debugGen = EmitDebug.CreateDebugMethod(\n                    string.Format(\"Field_{0}_{1}_{2}\", s_fieldId++, type.Name, memberName), typeof(void), argumentTypes);\n                EmitFieldCoder(debugGen, type, field);\n\n                // create result lambda function\n                var m = new DynamicMethod(\"lambda\", typeof(void), argumentTypes);\n                EmitFieldCoder(m.GetILGenerator(), type, field);\n                var code = (Action<ICoder, object>)m.CreateDelegate(typeof(Action<ICoder, object>));\n                return new FieldCoder(0, name, code);\n            }\n\n            var prop = type.GetProperty(memberName);\n            if (prop != null)\n            {\n                // template:\n                // (c, o) =>\n                // {\n                //     if (c.IsWriting) { var v = ((Foo)o).MyProperty; c.Code(ref v); }\n                //     else { var v = 0; c.Code(ref v); ((Foo)o).MyProperty = v; }\n                // }\n\n                var argumentTypes = new[] { typeof(ICoder), typeof(object) };\n\n                // create debug method\n                var debugGen = EmitDebug.CreateDebugMethod(\n                    string.Format(\"Property_{0}_{1}_{2}\", s_propId++, type.Name, memberName), typeof(void), argumentTypes);\n                EmitPropertyCoder(debugGen, type, prop);\n\n                // create result lambda function\n                var m = new DynamicMethod(\"lambda\", typeof(void), argumentTypes);\n                EmitPropertyCoder(m.GetILGenerator(), type, prop);\n                var code = (Action<ICoder, object>)m.CreateDelegate(typeof(Action<ICoder, object>));\n                return new FieldCoder(0, name, code);\n            }\n\n            throw new NotImplementedException();\n        }\n\n        private static void EmitFieldCoder(ILGenerator gen, Type type, FieldInfo field)\n        {\n            var method_Code = GetCodeMethodOverloadFor(field.FieldType);\n\n            gen.Emit(OpCodes.Ldarg_0);\n            gen.Emit(OpCodes.Ldarg_1);\n            gen.Emit(OpCodes.Castclass, type);\n            gen.Emit(OpCodes.Ldflda, field);\n            gen.Emit(OpCodes.Callvirt, method_Code);\n            gen.Emit(OpCodes.Ret);\n        }\n\n        private static void EmitPropertyCoder(ILGenerator gen, Type type, PropertyInfo prop)\n        {\n            var method_IsWriting = typeof(ICoder).GetMethod(\n                \"get_IsWriting\",\n                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,\n                null, Array.Empty<Type>(), null\n                );\n\n            var method_Code = GetCodeMethodOverloadFor(prop.PropertyType);\n            var typeOfCodeMethodArg = method_Code.GetParameters()[0].ParameterType;\n\n            //var c = m.DefineParameter(1, ParameterAttributes.None, \"c\");\n            //var o = m.DefineParameter(2, ParameterAttributes.None, \"o\");\n\n            /* var v = */ gen.DeclareLocal(prop.PropertyType);\n            var typeOfCodeMethodArdWithoutRef =\n                Type.GetType(typeOfCodeMethodArg.FullName.Substring(0, typeOfCodeMethodArg.FullName.Length - 1));\n            /* var v1 = */ gen.DeclareLocal(typeOfCodeMethodArdWithoutRef);\n\n            var label_isReading = gen.DefineLabel();\n\n            // if (c.IsWriting)\n            gen.Emit(OpCodes.Ldarg_0);\n            gen.Emit(OpCodes.Callvirt, method_IsWriting);\n            gen.Emit(OpCodes.Brfalse_S, label_isReading);\n            // then writing ...\n            gen.Emit(OpCodes.Ldarg_1);                      // var v = ((T)o).MyProperty; c.Code(ref v);\n            gen.Emit(OpCodes.Castclass, type);\n            gen.Emit(OpCodes.Callvirt, prop.GetGetMethod());\n            gen.Emit(OpCodes.Stloc_1);\n            gen.Emit(OpCodes.Ldarg_0);\n            gen.Emit(OpCodes.Ldloca_S, 1);\n            gen.Emit(OpCodes.Callvirt, method_Code);\n            gen.Emit(OpCodes.Ret);\n            // else reading ...\n            gen.MarkLabel(label_isReading);\n\n            // var v = default(T);\n            gen.Emit(OpCodes.Ldloca, 0);                        // load address of local variable v\n            gen.Emit(OpCodes.Initobj, prop.PropertyType);       // initialize v to default value\n\n            // c.Code(ref v);\n            gen.Emit(OpCodes.Ldarg_0);                          // c, used as this for following call\n            gen.Emit(OpCodes.Ldloca, 0);                        // ref v\n            gen.Emit(OpCodes.Callvirt, method_Code);            // call ... c.code(ref v)\n\n            // ((T)o).MyProperty = v;\n            gen.Emit(OpCodes.Ldarg_1);                          // o\n            gen.Emit(OpCodes.Castclass, type);                  // cast to T\n            gen.Emit(OpCodes.Ldloc_0);                          // v\n            //gen.Emit(OpCodes.Castclass, prop.PropertyType);\n            gen.Emit(OpCodes.Callvirt, prop.GetSetMethod());    // call setter\n            gen.Emit(OpCodes.Ret);\n        }\n\n        private static int s_fieldId = 0;\n        private static int s_propId = 0;\n\n        private static MethodInfo GetCodeMethodOverloadFor(Type t)\n        {\n            // try non-generic Code overloads first\n            var mi = typeof(ICoder).GetMethod(\n                \"Code\", BindingFlags.Instance | BindingFlags.Public, null,\n                new Type[] { t.MakeByRefType() }, null\n                );\n\n            // if match exists and it is not Code(ref object obj) then we're done\n            if (mi != null && mi.GetParameters()[0].ParameterType != typeof(object).MakeByRefType())\n            {\n                return mi;\n            }\n\n            // try Code<T>(ref T[] obj) overload\n            if (t.IsArray)\n            {\n                var s = t.FullName.Substring(0, t.FullName.Length - 2);\n                var arrayOfWhat = Type.GetType(s);\n                return s_methodCodeArrayOfT.MakeGenericMethod(arrayOfWhat);\n            }\n\n            if (t.FullName.StartsWith(\"System.Collections.Generic.List\"))\n            {\n                var i = t.FullName.IndexOf('[');\n                var s = t.FullName.Substring(i + 2, t.FullName.Length - i - 3);\n                var listOfWhat = Type.GetType(s);\n                return s_methodCodeListOfT.MakeGenericMethod(listOfWhat);\n            }\n\n            // finally use Code<T>(ref T obj) overload\n            return s_methodCodeT.MakeGenericMethod(t);\n        }\n\n        private static readonly MethodInfo s_methodCodeT;\n        private static readonly MethodInfo s_methodCodeArrayOfT;\n        private static readonly MethodInfo s_methodCodeListOfT;\n\n        static FieldCoderExtensions()\n        {\n            var genericCodeMethods = (\n               from m in typeof(ICoder).GetMethods(\n                   BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public)\n               where m.IsGenericMethod\n               where m.Name.StartsWith(\"Code\")\n               select new\n               {\n                   Method = m,\n                   ParameterType = m.GetParameters()[0].ParameterType\n               }\n               ).ToArray();\n\n            foreach (var m in genericCodeMethods)\n            {\n                switch (m.ParameterType.Name)\n                {\n                    case \"T&\": s_methodCodeT = m.Method; break;\n                    case \"T[]&\": s_methodCodeArrayOfT = m.Method; break;\n                    case \"List`1&\": s_methodCodeListOfT = m.Method; break;\n                    default: throw new NotImplementedException();\n                }\n            }\n        }\n\n    }\n\n    public static class EmitDebug\n    {\n\n        private static void BeginDebug(string debugAssemblyName)\n        {\n            var domain = AppDomain.CurrentDomain;\n            var aname = new AssemblyName(debugAssemblyName);\n            aname.Version = new Version(0, 0, 1);\n            s_assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(aname, AssemblyBuilderAccess.Run);\n\n            s_modBuilder = s_assemblyBuilder.DefineDynamicModule(\"MainModule\");\n\n            s_typeBuilder = s_modBuilder.DefineType(\"Debug\", TypeAttributes.Public);\n        }\n\n        public static ILGenerator CreateDebugMethod(string name, Type returnType, Type[] parameterTypes)\n        {\n            if (s_assemblyBuilder == null) BeginDebug(\"ReflectEmitDebug\");\n\n            var mb = s_typeBuilder.DefineMethod(\n                name, MethodAttributes.Static | MethodAttributes.Public,\n                returnType, parameterTypes);\n            return mb.GetILGenerator();\n        }\n\n        private static AssemblyBuilder s_assemblyBuilder;\n        private static ModuleBuilder s_modBuilder;\n        private static TypeBuilder s_typeBuilder;\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/GzipUtils.cs",
    "content": "using Aardvark.Base;\nusing System.IO;\nusing System.IO.Compression;\n\nnamespace Aardvark.Base.Coder\n{\n    public static class GzipUtils\n    {\n        public static void GzipFile(string fileName)\n        {\n            Report.BeginTimed(\"compressing {0}\", Path.GetFileName(fileName));\n            using (var ofs = new FileStream(\n                fileName + \".gz\", FileMode.OpenOrCreate, FileAccess.Write\n                ))\n            {\n                using (var ifs = new FileStream(fileName, FileMode.Open, FileAccess.Read))\n                {\n                    using (var gzs = new GZipStream(ofs, CompressionMode.Compress))\n                    {\n                        var buf = new byte[65536];\n                        int count;\n                        while ((count = ifs.Read(buf, 0, 65536)) > 0)\n                        {\n                            gzs.Write(buf, 0, count);\n                        }\n                    }\n                }\n            }\n            Report.End();\n        }\n\n        /// <summary>\n        /// Uncompress gzipped file.\n        /// </summary>\n        /// <param name=\"fileName\">Path without .gz at end of file name.</param>\n        public static void UnGzipFile(string fileName)\n        {\n            using (var ofs = new FileStream(\n                fileName, FileMode.OpenOrCreate, FileAccess.Write\n                ))\n            {\n                var srcFileName = fileName + \".gz\";\n                Report.BeginTimed(\"decompressing {0}\", Path.GetFileName(srcFileName));\n                using (var ifs = new FileStream(\n                    srcFileName, FileMode.Open, FileAccess.Read\n                    ))\n                {\n                    using (var gzs = new GZipStream(ifs, CompressionMode.Decompress))\n                    {\n                        var buf = new byte[65536];\n                        int count;\n                        while ((count = gzs.Read(buf, 0, 65536)) > 0)\n                        {\n                            ofs.Write(buf, 0, count);\n                        }\n                    }\n                }\n                Report.End();\n            }\n        }\n\n        public static Stream UnGzipFileToStream(string fileName)\n        {\n            var ofs = new MemoryStream();\n\n            Report.BeginTimed(\"decompressing {0}\", Path.GetFileName(fileName));\n            using (var ifs = new FileStream(\n                fileName, FileMode.Open, FileAccess.Read\n                ))\n            {\n                using (var gzs = new GZipStream(ifs, CompressionMode.Decompress))\n                {\n                    var buf = new byte[65536];\n                    int count;\n                    while ((count = gzs.Read(buf, 0, 65536)) > 0)\n                    {\n                        ofs.Write(buf, 0, count);\n                    }\n                }\n            }\n            Report.End();\n\n            ofs.Seek(0, SeekOrigin.Begin);\n            return ofs;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/IAwakeable.cs",
    "content": "namespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// Implement this to awake an object from decoding after all fields of\n    /// the object have already been decoded. This is normally used to\n    /// initialize member variables that serve as caches.\n    /// </summary>\n    public interface IAwakeable\n    {\n        /// <summary>\n        /// This method is called directly after an object has been\n        /// deserialized. It get the version of the coded object as a\n        /// parameter.\n        /// </summary>\n        void Awake(int codedVersion);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/ICoder.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// An ICoder can either read or write objects. It declares its purpose\n    /// with the methods <see cref=\"IsReading\"/> and <see cref=\"IsWriting\"/>\n    /// one of which must return true the other one false. Depending on its\n    /// declared purpose all its <see cref=\"o:Code\"/> methods either read or\n    /// write objects via the supplied reference.\n    /// </summary>\n    public partial interface ICoder\n    {\n        int CoderVersion { get; }\n        \n        /// <summary>\n        /// The version of the current object in memory.\n        /// </summary>\n        int MemoryVersion { get; }\n\n        /// <summary>\n        /// For writing coders this is the same as the memory version, for\n        /// reading coders, an object of the stream version has to be\n        /// converted to the memory version.\n        /// </summary>\n        int StreamVersion { get; }\n\n        /// <summary>\n        /// If true all the <see cref=\"o:Code\"/> methods read objects.\n        /// </summary>\n        bool IsReading { get; }\n\n        /// <summary>\n        /// If true all the <see cref=\"o:Code\"/> methods write objects.\n        /// </summary>\n        bool IsWriting { get; }\n\n        string FileName { get; }\n        \n        void Add(TypeInfo[] typeInfoArray);\n        void Del(TypeInfo[] typeInfoArray);\n\n        void Code(ref object obj);\n\n        void CodeT<T>(ref T obj);\n        void CodeTArray<T>(ref T[] array);\n        void CodeList_of_T_<T>(ref List<T> list);\n        void CodeHashSet_of_T_<T>(ref HashSet<T> set);\n\n        void Code(Type t, ref object o);\n\n        void Code(Type t, ref Array array);\n        void Code(Type t, ref IList list);\n        void Code(Type t, ref IDictionary dict);\n\n        void Code(Type t, ref ICountableDict dict);\n        void Code(Type t, ref ICountableDictSet dictSet);\n\n        void Code(Type t, ref IArrayVector vector);\n        void Code(Type t, ref IArrayMatrix matrix);\n        void Code(Type t, ref IArrayVolume volume);\n        void Code(Type t, ref IArrayTensor4 tensor4);\n        void Code(Type t, ref IArrayTensorN tensor);\n\n        void CodeHashSet(Type t, ref object o);\n\n        void CodeEnum(Type t, ref object value);\n\n        /// <summary>\n        /// Code a symbol that is known to be a Guid.\n        /// </summary>\n        void CodeGuidSymbol(ref Symbol v);\n\n        /// <summary>\n        /// Code a Symbol that is known to be positive.\n        /// </summary>\n        void CodePositiveSymbol(ref Symbol v);\n\n        void CodeIntSet(ref IntSet v);\n        void CodeSymbolSet(ref SymbolSet v);\n\n        void CodeStructArray<T>(ref T[] a) where T : struct;\n        void CodeStructList<T>(ref List<T> l) where T : struct;\n    }\n\n    /// <summary>\n    /// This interface supplies additional functionality that is provided\n    /// by reading coders.\n    /// </summary>\n    public interface IReadingCoder : ICoder\n    {\n        int CodeCount<T>(ref T value, Func<int, T> creator) where T : class;\n    }\n\n    /// <summary>\n    /// This interface supplies additional functionality that is provided\n    /// by writing coders.\n    /// </summary>\n    public interface IWritingCoder : ICoder\n    {\n        int CodeCount<T>(ref T value, Func<T, int> counter) where T : class;\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/ICoder_auto.cs",
    "content": "using Aardvark.Base;\r\nusing System;\r\nusing System.Collections.Generic;\r\n\r\nnamespace Aardvark.Base.Coder\r\n{\r\n\r\n    // AUTO GENERATED CODE - DO NOT CHANGE\r\n\r\n    public partial interface ICoder\r\n    {\r\n        #region Struct Types\r\n\r\n        void CodeBool(ref bool value);\r\n        void CodeChar(ref char value);\r\n        void CodeString(ref string value);\r\n        void CodeType(ref Type value);\r\n        void CodeGuid(ref Guid value);\r\n        void CodeSymbol(ref Symbol value);\r\n        void CodeByte(ref byte value);\r\n        void CodeSByte(ref sbyte value);\r\n        void CodeShort(ref short value);\r\n        void CodeUShort(ref ushort value);\r\n        void CodeInt(ref int value);\r\n        void CodeUInt(ref uint value);\r\n        void CodeLong(ref long value);\r\n        void CodeULong(ref ulong value);\r\n        void CodeFloat(ref float value);\r\n        void CodeDouble(ref double value);\r\n        void CodeFraction(ref Fraction value);\r\n        void CodeV2i(ref V2i value);\r\n        void CodeV2l(ref V2l value);\r\n        void CodeV2f(ref V2f value);\r\n        void CodeV2d(ref V2d value);\r\n        void CodeV3i(ref V3i value);\r\n        void CodeV3l(ref V3l value);\r\n        void CodeV3f(ref V3f value);\r\n        void CodeV3d(ref V3d value);\r\n        void CodeV4i(ref V4i value);\r\n        void CodeV4l(ref V4l value);\r\n        void CodeV4f(ref V4f value);\r\n        void CodeV4d(ref V4d value);\r\n        void CodeM22i(ref M22i value);\r\n        void CodeM22l(ref M22l value);\r\n        void CodeM22f(ref M22f value);\r\n        void CodeM22d(ref M22d value);\r\n        void CodeM23i(ref M23i value);\r\n        void CodeM23l(ref M23l value);\r\n        void CodeM23f(ref M23f value);\r\n        void CodeM23d(ref M23d value);\r\n        void CodeM33i(ref M33i value);\r\n        void CodeM33l(ref M33l value);\r\n        void CodeM33f(ref M33f value);\r\n        void CodeM33d(ref M33d value);\r\n        void CodeM34i(ref M34i value);\r\n        void CodeM34l(ref M34l value);\r\n        void CodeM34f(ref M34f value);\r\n        void CodeM34d(ref M34d value);\r\n        void CodeM44i(ref M44i value);\r\n        void CodeM44l(ref M44l value);\r\n        void CodeM44f(ref M44f value);\r\n        void CodeM44d(ref M44d value);\r\n        void CodeC3b(ref C3b value);\r\n        void CodeC3us(ref C3us value);\r\n        void CodeC3ui(ref C3ui value);\r\n        void CodeC3f(ref C3f value);\r\n        void CodeC3d(ref C3d value);\r\n        void CodeC4b(ref C4b value);\r\n        void CodeC4us(ref C4us value);\r\n        void CodeC4ui(ref C4ui value);\r\n        void CodeC4f(ref C4f value);\r\n        void CodeC4d(ref C4d value);\r\n        void CodeRange1b(ref Range1b value);\r\n        void CodeRange1sb(ref Range1sb value);\r\n        void CodeRange1s(ref Range1s value);\r\n        void CodeRange1us(ref Range1us value);\r\n        void CodeRange1i(ref Range1i value);\r\n        void CodeRange1ui(ref Range1ui value);\r\n        void CodeRange1l(ref Range1l value);\r\n        void CodeRange1ul(ref Range1ul value);\r\n        void CodeRange1f(ref Range1f value);\r\n        void CodeRange1d(ref Range1d value);\r\n        void CodeBox2i(ref Box2i value);\r\n        void CodeBox2l(ref Box2l value);\r\n        void CodeBox2f(ref Box2f value);\r\n        void CodeBox2d(ref Box2d value);\r\n        void CodeBox3i(ref Box3i value);\r\n        void CodeBox3l(ref Box3l value);\r\n        void CodeBox3f(ref Box3f value);\r\n        void CodeBox3d(ref Box3d value);\r\n        void CodeEuclidean3f(ref Euclidean3f value);\r\n        void CodeEuclidean3d(ref Euclidean3d value);\r\n        void CodeRot2f(ref Rot2f value);\r\n        void CodeRot2d(ref Rot2d value);\r\n        void CodeRot3f(ref Rot3f value);\r\n        void CodeRot3d(ref Rot3d value);\r\n        void CodeScale3f(ref Scale3f value);\r\n        void CodeScale3d(ref Scale3d value);\r\n        void CodeShift3f(ref Shift3f value);\r\n        void CodeShift3d(ref Shift3d value);\r\n        void CodeTrafo2f(ref Trafo2f value);\r\n        void CodeTrafo2d(ref Trafo2d value);\r\n        void CodeTrafo3f(ref Trafo3f value);\r\n        void CodeTrafo3d(ref Trafo3d value);\r\n\r\n        #endregion\r\n\r\n        #region Tensors\r\n\r\n        void CodeVector_of_Byte_(ref Vector<byte> value);\r\n        void CodeVector_of_SByte_(ref Vector<sbyte> value);\r\n        void CodeVector_of_Short_(ref Vector<short> value);\r\n        void CodeVector_of_UShort_(ref Vector<ushort> value);\r\n        void CodeVector_of_Int_(ref Vector<int> value);\r\n        void CodeVector_of_UInt_(ref Vector<uint> value);\r\n        void CodeVector_of_Long_(ref Vector<long> value);\r\n        void CodeVector_of_ULong_(ref Vector<ulong> value);\r\n        void CodeVector_of_Float_(ref Vector<float> value);\r\n        void CodeVector_of_Double_(ref Vector<double> value);\r\n        void CodeVector_of_Fraction_(ref Vector<Fraction> value);\r\n        void CodeVector_of_V2i_(ref Vector<V2i> value);\r\n        void CodeVector_of_V2l_(ref Vector<V2l> value);\r\n        void CodeVector_of_V2f_(ref Vector<V2f> value);\r\n        void CodeVector_of_V2d_(ref Vector<V2d> value);\r\n        void CodeVector_of_V3i_(ref Vector<V3i> value);\r\n        void CodeVector_of_V3l_(ref Vector<V3l> value);\r\n        void CodeVector_of_V3f_(ref Vector<V3f> value);\r\n        void CodeVector_of_V3d_(ref Vector<V3d> value);\r\n        void CodeVector_of_V4i_(ref Vector<V4i> value);\r\n        void CodeVector_of_V4l_(ref Vector<V4l> value);\r\n        void CodeVector_of_V4f_(ref Vector<V4f> value);\r\n        void CodeVector_of_V4d_(ref Vector<V4d> value);\r\n        void CodeVector_of_M22i_(ref Vector<M22i> value);\r\n        void CodeVector_of_M22l_(ref Vector<M22l> value);\r\n        void CodeVector_of_M22f_(ref Vector<M22f> value);\r\n        void CodeVector_of_M22d_(ref Vector<M22d> value);\r\n        void CodeVector_of_M23i_(ref Vector<M23i> value);\r\n        void CodeVector_of_M23l_(ref Vector<M23l> value);\r\n        void CodeVector_of_M23f_(ref Vector<M23f> value);\r\n        void CodeVector_of_M23d_(ref Vector<M23d> value);\r\n        void CodeVector_of_M33i_(ref Vector<M33i> value);\r\n        void CodeVector_of_M33l_(ref Vector<M33l> value);\r\n        void CodeVector_of_M33f_(ref Vector<M33f> value);\r\n        void CodeVector_of_M33d_(ref Vector<M33d> value);\r\n        void CodeVector_of_M34i_(ref Vector<M34i> value);\r\n        void CodeVector_of_M34l_(ref Vector<M34l> value);\r\n        void CodeVector_of_M34f_(ref Vector<M34f> value);\r\n        void CodeVector_of_M34d_(ref Vector<M34d> value);\r\n        void CodeVector_of_M44i_(ref Vector<M44i> value);\r\n        void CodeVector_of_M44l_(ref Vector<M44l> value);\r\n        void CodeVector_of_M44f_(ref Vector<M44f> value);\r\n        void CodeVector_of_M44d_(ref Vector<M44d> value);\r\n        void CodeVector_of_C3b_(ref Vector<C3b> value);\r\n        void CodeVector_of_C3us_(ref Vector<C3us> value);\r\n        void CodeVector_of_C3ui_(ref Vector<C3ui> value);\r\n        void CodeVector_of_C3f_(ref Vector<C3f> value);\r\n        void CodeVector_of_C3d_(ref Vector<C3d> value);\r\n        void CodeVector_of_C4b_(ref Vector<C4b> value);\r\n        void CodeVector_of_C4us_(ref Vector<C4us> value);\r\n        void CodeVector_of_C4ui_(ref Vector<C4ui> value);\r\n        void CodeVector_of_C4f_(ref Vector<C4f> value);\r\n        void CodeVector_of_C4d_(ref Vector<C4d> value);\r\n        void CodeVector_of_Range1b_(ref Vector<Range1b> value);\r\n        void CodeVector_of_Range1sb_(ref Vector<Range1sb> value);\r\n        void CodeVector_of_Range1s_(ref Vector<Range1s> value);\r\n        void CodeVector_of_Range1us_(ref Vector<Range1us> value);\r\n        void CodeVector_of_Range1i_(ref Vector<Range1i> value);\r\n        void CodeVector_of_Range1ui_(ref Vector<Range1ui> value);\r\n        void CodeVector_of_Range1l_(ref Vector<Range1l> value);\r\n        void CodeVector_of_Range1ul_(ref Vector<Range1ul> value);\r\n        void CodeVector_of_Range1f_(ref Vector<Range1f> value);\r\n        void CodeVector_of_Range1d_(ref Vector<Range1d> value);\r\n        void CodeVector_of_Box2i_(ref Vector<Box2i> value);\r\n        void CodeVector_of_Box2l_(ref Vector<Box2l> value);\r\n        void CodeVector_of_Box2f_(ref Vector<Box2f> value);\r\n        void CodeVector_of_Box2d_(ref Vector<Box2d> value);\r\n        void CodeVector_of_Box3i_(ref Vector<Box3i> value);\r\n        void CodeVector_of_Box3l_(ref Vector<Box3l> value);\r\n        void CodeVector_of_Box3f_(ref Vector<Box3f> value);\r\n        void CodeVector_of_Box3d_(ref Vector<Box3d> value);\r\n        void CodeVector_of_Euclidean3f_(ref Vector<Euclidean3f> value);\r\n        void CodeVector_of_Euclidean3d_(ref Vector<Euclidean3d> value);\r\n        void CodeVector_of_Rot2f_(ref Vector<Rot2f> value);\r\n        void CodeVector_of_Rot2d_(ref Vector<Rot2d> value);\r\n        void CodeVector_of_Rot3f_(ref Vector<Rot3f> value);\r\n        void CodeVector_of_Rot3d_(ref Vector<Rot3d> value);\r\n        void CodeVector_of_Scale3f_(ref Vector<Scale3f> value);\r\n        void CodeVector_of_Scale3d_(ref Vector<Scale3d> value);\r\n        void CodeVector_of_Shift3f_(ref Vector<Shift3f> value);\r\n        void CodeVector_of_Shift3d_(ref Vector<Shift3d> value);\r\n        void CodeVector_of_Trafo2f_(ref Vector<Trafo2f> value);\r\n        void CodeVector_of_Trafo2d_(ref Vector<Trafo2d> value);\r\n        void CodeVector_of_Trafo3f_(ref Vector<Trafo3f> value);\r\n        void CodeVector_of_Trafo3d_(ref Vector<Trafo3d> value);\r\n        void CodeVector_of_Bool_(ref Vector<bool> value);\r\n        void CodeVector_of_Char_(ref Vector<char> value);\r\n        void CodeVector_of_String_(ref Vector<string> value);\r\n        void CodeVector_of_Type_(ref Vector<Type> value);\r\n        void CodeVector_of_Guid_(ref Vector<Guid> value);\r\n        void CodeVector_of_Symbol_(ref Vector<Symbol> value);\r\n        void CodeVector_of_Circle2d_(ref Vector<Circle2d> value);\r\n        void CodeVector_of_Line2d_(ref Vector<Line2d> value);\r\n        void CodeVector_of_Line3d_(ref Vector<Line3d> value);\r\n        void CodeVector_of_Plane2d_(ref Vector<Plane2d> value);\r\n        void CodeVector_of_Plane3d_(ref Vector<Plane3d> value);\r\n        void CodeVector_of_PlaneWithPoint3d_(ref Vector<PlaneWithPoint3d> value);\r\n        void CodeVector_of_Quad2d_(ref Vector<Quad2d> value);\r\n        void CodeVector_of_Quad3d_(ref Vector<Quad3d> value);\r\n        void CodeVector_of_Ray2d_(ref Vector<Ray2d> value);\r\n        void CodeVector_of_Ray3d_(ref Vector<Ray3d> value);\r\n        void CodeVector_of_Sphere3d_(ref Vector<Sphere3d> value);\r\n        void CodeVector_of_Triangle2d_(ref Vector<Triangle2d> value);\r\n        void CodeVector_of_Triangle3d_(ref Vector<Triangle3d> value);\r\n        void CodeVector_of_Circle2f_(ref Vector<Circle2f> value);\r\n        void CodeVector_of_Line2f_(ref Vector<Line2f> value);\r\n        void CodeVector_of_Line3f_(ref Vector<Line3f> value);\r\n        void CodeVector_of_Plane2f_(ref Vector<Plane2f> value);\r\n        void CodeVector_of_Plane3f_(ref Vector<Plane3f> value);\r\n        void CodeVector_of_PlaneWithPoint3f_(ref Vector<PlaneWithPoint3f> value);\r\n        void CodeVector_of_Quad2f_(ref Vector<Quad2f> value);\r\n        void CodeVector_of_Quad3f_(ref Vector<Quad3f> value);\r\n        void CodeVector_of_Ray2f_(ref Vector<Ray2f> value);\r\n        void CodeVector_of_Ray3f_(ref Vector<Ray3f> value);\r\n        void CodeVector_of_Sphere3f_(ref Vector<Sphere3f> value);\r\n        void CodeVector_of_Triangle2f_(ref Vector<Triangle2f> value);\r\n        void CodeVector_of_Triangle3f_(ref Vector<Triangle3f> value);\r\n        void CodeMatrix_of_Byte_(ref Matrix<byte> value);\r\n        void CodeMatrix_of_SByte_(ref Matrix<sbyte> value);\r\n        void CodeMatrix_of_Short_(ref Matrix<short> value);\r\n        void CodeMatrix_of_UShort_(ref Matrix<ushort> value);\r\n        void CodeMatrix_of_Int_(ref Matrix<int> value);\r\n        void CodeMatrix_of_UInt_(ref Matrix<uint> value);\r\n        void CodeMatrix_of_Long_(ref Matrix<long> value);\r\n        void CodeMatrix_of_ULong_(ref Matrix<ulong> value);\r\n        void CodeMatrix_of_Float_(ref Matrix<float> value);\r\n        void CodeMatrix_of_Double_(ref Matrix<double> value);\r\n        void CodeMatrix_of_Fraction_(ref Matrix<Fraction> value);\r\n        void CodeMatrix_of_V2i_(ref Matrix<V2i> value);\r\n        void CodeMatrix_of_V2l_(ref Matrix<V2l> value);\r\n        void CodeMatrix_of_V2f_(ref Matrix<V2f> value);\r\n        void CodeMatrix_of_V2d_(ref Matrix<V2d> value);\r\n        void CodeMatrix_of_V3i_(ref Matrix<V3i> value);\r\n        void CodeMatrix_of_V3l_(ref Matrix<V3l> value);\r\n        void CodeMatrix_of_V3f_(ref Matrix<V3f> value);\r\n        void CodeMatrix_of_V3d_(ref Matrix<V3d> value);\r\n        void CodeMatrix_of_V4i_(ref Matrix<V4i> value);\r\n        void CodeMatrix_of_V4l_(ref Matrix<V4l> value);\r\n        void CodeMatrix_of_V4f_(ref Matrix<V4f> value);\r\n        void CodeMatrix_of_V4d_(ref Matrix<V4d> value);\r\n        void CodeMatrix_of_M22i_(ref Matrix<M22i> value);\r\n        void CodeMatrix_of_M22l_(ref Matrix<M22l> value);\r\n        void CodeMatrix_of_M22f_(ref Matrix<M22f> value);\r\n        void CodeMatrix_of_M22d_(ref Matrix<M22d> value);\r\n        void CodeMatrix_of_M23i_(ref Matrix<M23i> value);\r\n        void CodeMatrix_of_M23l_(ref Matrix<M23l> value);\r\n        void CodeMatrix_of_M23f_(ref Matrix<M23f> value);\r\n        void CodeMatrix_of_M23d_(ref Matrix<M23d> value);\r\n        void CodeMatrix_of_M33i_(ref Matrix<M33i> value);\r\n        void CodeMatrix_of_M33l_(ref Matrix<M33l> value);\r\n        void CodeMatrix_of_M33f_(ref Matrix<M33f> value);\r\n        void CodeMatrix_of_M33d_(ref Matrix<M33d> value);\r\n        void CodeMatrix_of_M34i_(ref Matrix<M34i> value);\r\n        void CodeMatrix_of_M34l_(ref Matrix<M34l> value);\r\n        void CodeMatrix_of_M34f_(ref Matrix<M34f> value);\r\n        void CodeMatrix_of_M34d_(ref Matrix<M34d> value);\r\n        void CodeMatrix_of_M44i_(ref Matrix<M44i> value);\r\n        void CodeMatrix_of_M44l_(ref Matrix<M44l> value);\r\n        void CodeMatrix_of_M44f_(ref Matrix<M44f> value);\r\n        void CodeMatrix_of_M44d_(ref Matrix<M44d> value);\r\n        void CodeMatrix_of_C3b_(ref Matrix<C3b> value);\r\n        void CodeMatrix_of_C3us_(ref Matrix<C3us> value);\r\n        void CodeMatrix_of_C3ui_(ref Matrix<C3ui> value);\r\n        void CodeMatrix_of_C3f_(ref Matrix<C3f> value);\r\n        void CodeMatrix_of_C3d_(ref Matrix<C3d> value);\r\n        void CodeMatrix_of_C4b_(ref Matrix<C4b> value);\r\n        void CodeMatrix_of_C4us_(ref Matrix<C4us> value);\r\n        void CodeMatrix_of_C4ui_(ref Matrix<C4ui> value);\r\n        void CodeMatrix_of_C4f_(ref Matrix<C4f> value);\r\n        void CodeMatrix_of_C4d_(ref Matrix<C4d> value);\r\n        void CodeMatrix_of_Range1b_(ref Matrix<Range1b> value);\r\n        void CodeMatrix_of_Range1sb_(ref Matrix<Range1sb> value);\r\n        void CodeMatrix_of_Range1s_(ref Matrix<Range1s> value);\r\n        void CodeMatrix_of_Range1us_(ref Matrix<Range1us> value);\r\n        void CodeMatrix_of_Range1i_(ref Matrix<Range1i> value);\r\n        void CodeMatrix_of_Range1ui_(ref Matrix<Range1ui> value);\r\n        void CodeMatrix_of_Range1l_(ref Matrix<Range1l> value);\r\n        void CodeMatrix_of_Range1ul_(ref Matrix<Range1ul> value);\r\n        void CodeMatrix_of_Range1f_(ref Matrix<Range1f> value);\r\n        void CodeMatrix_of_Range1d_(ref Matrix<Range1d> value);\r\n        void CodeMatrix_of_Box2i_(ref Matrix<Box2i> value);\r\n        void CodeMatrix_of_Box2l_(ref Matrix<Box2l> value);\r\n        void CodeMatrix_of_Box2f_(ref Matrix<Box2f> value);\r\n        void CodeMatrix_of_Box2d_(ref Matrix<Box2d> value);\r\n        void CodeMatrix_of_Box3i_(ref Matrix<Box3i> value);\r\n        void CodeMatrix_of_Box3l_(ref Matrix<Box3l> value);\r\n        void CodeMatrix_of_Box3f_(ref Matrix<Box3f> value);\r\n        void CodeMatrix_of_Box3d_(ref Matrix<Box3d> value);\r\n        void CodeMatrix_of_Euclidean3f_(ref Matrix<Euclidean3f> value);\r\n        void CodeMatrix_of_Euclidean3d_(ref Matrix<Euclidean3d> value);\r\n        void CodeMatrix_of_Rot2f_(ref Matrix<Rot2f> value);\r\n        void CodeMatrix_of_Rot2d_(ref Matrix<Rot2d> value);\r\n        void CodeMatrix_of_Rot3f_(ref Matrix<Rot3f> value);\r\n        void CodeMatrix_of_Rot3d_(ref Matrix<Rot3d> value);\r\n        void CodeMatrix_of_Scale3f_(ref Matrix<Scale3f> value);\r\n        void CodeMatrix_of_Scale3d_(ref Matrix<Scale3d> value);\r\n        void CodeMatrix_of_Shift3f_(ref Matrix<Shift3f> value);\r\n        void CodeMatrix_of_Shift3d_(ref Matrix<Shift3d> value);\r\n        void CodeMatrix_of_Trafo2f_(ref Matrix<Trafo2f> value);\r\n        void CodeMatrix_of_Trafo2d_(ref Matrix<Trafo2d> value);\r\n        void CodeMatrix_of_Trafo3f_(ref Matrix<Trafo3f> value);\r\n        void CodeMatrix_of_Trafo3d_(ref Matrix<Trafo3d> value);\r\n        void CodeMatrix_of_Bool_(ref Matrix<bool> value);\r\n        void CodeMatrix_of_Char_(ref Matrix<char> value);\r\n        void CodeMatrix_of_String_(ref Matrix<string> value);\r\n        void CodeMatrix_of_Type_(ref Matrix<Type> value);\r\n        void CodeMatrix_of_Guid_(ref Matrix<Guid> value);\r\n        void CodeMatrix_of_Symbol_(ref Matrix<Symbol> value);\r\n        void CodeMatrix_of_Circle2d_(ref Matrix<Circle2d> value);\r\n        void CodeMatrix_of_Line2d_(ref Matrix<Line2d> value);\r\n        void CodeMatrix_of_Line3d_(ref Matrix<Line3d> value);\r\n        void CodeMatrix_of_Plane2d_(ref Matrix<Plane2d> value);\r\n        void CodeMatrix_of_Plane3d_(ref Matrix<Plane3d> value);\r\n        void CodeMatrix_of_PlaneWithPoint3d_(ref Matrix<PlaneWithPoint3d> value);\r\n        void CodeMatrix_of_Quad2d_(ref Matrix<Quad2d> value);\r\n        void CodeMatrix_of_Quad3d_(ref Matrix<Quad3d> value);\r\n        void CodeMatrix_of_Ray2d_(ref Matrix<Ray2d> value);\r\n        void CodeMatrix_of_Ray3d_(ref Matrix<Ray3d> value);\r\n        void CodeMatrix_of_Sphere3d_(ref Matrix<Sphere3d> value);\r\n        void CodeMatrix_of_Triangle2d_(ref Matrix<Triangle2d> value);\r\n        void CodeMatrix_of_Triangle3d_(ref Matrix<Triangle3d> value);\r\n        void CodeMatrix_of_Circle2f_(ref Matrix<Circle2f> value);\r\n        void CodeMatrix_of_Line2f_(ref Matrix<Line2f> value);\r\n        void CodeMatrix_of_Line3f_(ref Matrix<Line3f> value);\r\n        void CodeMatrix_of_Plane2f_(ref Matrix<Plane2f> value);\r\n        void CodeMatrix_of_Plane3f_(ref Matrix<Plane3f> value);\r\n        void CodeMatrix_of_PlaneWithPoint3f_(ref Matrix<PlaneWithPoint3f> value);\r\n        void CodeMatrix_of_Quad2f_(ref Matrix<Quad2f> value);\r\n        void CodeMatrix_of_Quad3f_(ref Matrix<Quad3f> value);\r\n        void CodeMatrix_of_Ray2f_(ref Matrix<Ray2f> value);\r\n        void CodeMatrix_of_Ray3f_(ref Matrix<Ray3f> value);\r\n        void CodeMatrix_of_Sphere3f_(ref Matrix<Sphere3f> value);\r\n        void CodeMatrix_of_Triangle2f_(ref Matrix<Triangle2f> value);\r\n        void CodeMatrix_of_Triangle3f_(ref Matrix<Triangle3f> value);\r\n        void CodeVolume_of_Byte_(ref Volume<byte> value);\r\n        void CodeVolume_of_SByte_(ref Volume<sbyte> value);\r\n        void CodeVolume_of_Short_(ref Volume<short> value);\r\n        void CodeVolume_of_UShort_(ref Volume<ushort> value);\r\n        void CodeVolume_of_Int_(ref Volume<int> value);\r\n        void CodeVolume_of_UInt_(ref Volume<uint> value);\r\n        void CodeVolume_of_Long_(ref Volume<long> value);\r\n        void CodeVolume_of_ULong_(ref Volume<ulong> value);\r\n        void CodeVolume_of_Float_(ref Volume<float> value);\r\n        void CodeVolume_of_Double_(ref Volume<double> value);\r\n        void CodeVolume_of_Fraction_(ref Volume<Fraction> value);\r\n        void CodeVolume_of_V2i_(ref Volume<V2i> value);\r\n        void CodeVolume_of_V2l_(ref Volume<V2l> value);\r\n        void CodeVolume_of_V2f_(ref Volume<V2f> value);\r\n        void CodeVolume_of_V2d_(ref Volume<V2d> value);\r\n        void CodeVolume_of_V3i_(ref Volume<V3i> value);\r\n        void CodeVolume_of_V3l_(ref Volume<V3l> value);\r\n        void CodeVolume_of_V3f_(ref Volume<V3f> value);\r\n        void CodeVolume_of_V3d_(ref Volume<V3d> value);\r\n        void CodeVolume_of_V4i_(ref Volume<V4i> value);\r\n        void CodeVolume_of_V4l_(ref Volume<V4l> value);\r\n        void CodeVolume_of_V4f_(ref Volume<V4f> value);\r\n        void CodeVolume_of_V4d_(ref Volume<V4d> value);\r\n        void CodeVolume_of_M22i_(ref Volume<M22i> value);\r\n        void CodeVolume_of_M22l_(ref Volume<M22l> value);\r\n        void CodeVolume_of_M22f_(ref Volume<M22f> value);\r\n        void CodeVolume_of_M22d_(ref Volume<M22d> value);\r\n        void CodeVolume_of_M23i_(ref Volume<M23i> value);\r\n        void CodeVolume_of_M23l_(ref Volume<M23l> value);\r\n        void CodeVolume_of_M23f_(ref Volume<M23f> value);\r\n        void CodeVolume_of_M23d_(ref Volume<M23d> value);\r\n        void CodeVolume_of_M33i_(ref Volume<M33i> value);\r\n        void CodeVolume_of_M33l_(ref Volume<M33l> value);\r\n        void CodeVolume_of_M33f_(ref Volume<M33f> value);\r\n        void CodeVolume_of_M33d_(ref Volume<M33d> value);\r\n        void CodeVolume_of_M34i_(ref Volume<M34i> value);\r\n        void CodeVolume_of_M34l_(ref Volume<M34l> value);\r\n        void CodeVolume_of_M34f_(ref Volume<M34f> value);\r\n        void CodeVolume_of_M34d_(ref Volume<M34d> value);\r\n        void CodeVolume_of_M44i_(ref Volume<M44i> value);\r\n        void CodeVolume_of_M44l_(ref Volume<M44l> value);\r\n        void CodeVolume_of_M44f_(ref Volume<M44f> value);\r\n        void CodeVolume_of_M44d_(ref Volume<M44d> value);\r\n        void CodeVolume_of_C3b_(ref Volume<C3b> value);\r\n        void CodeVolume_of_C3us_(ref Volume<C3us> value);\r\n        void CodeVolume_of_C3ui_(ref Volume<C3ui> value);\r\n        void CodeVolume_of_C3f_(ref Volume<C3f> value);\r\n        void CodeVolume_of_C3d_(ref Volume<C3d> value);\r\n        void CodeVolume_of_C4b_(ref Volume<C4b> value);\r\n        void CodeVolume_of_C4us_(ref Volume<C4us> value);\r\n        void CodeVolume_of_C4ui_(ref Volume<C4ui> value);\r\n        void CodeVolume_of_C4f_(ref Volume<C4f> value);\r\n        void CodeVolume_of_C4d_(ref Volume<C4d> value);\r\n        void CodeVolume_of_Range1b_(ref Volume<Range1b> value);\r\n        void CodeVolume_of_Range1sb_(ref Volume<Range1sb> value);\r\n        void CodeVolume_of_Range1s_(ref Volume<Range1s> value);\r\n        void CodeVolume_of_Range1us_(ref Volume<Range1us> value);\r\n        void CodeVolume_of_Range1i_(ref Volume<Range1i> value);\r\n        void CodeVolume_of_Range1ui_(ref Volume<Range1ui> value);\r\n        void CodeVolume_of_Range1l_(ref Volume<Range1l> value);\r\n        void CodeVolume_of_Range1ul_(ref Volume<Range1ul> value);\r\n        void CodeVolume_of_Range1f_(ref Volume<Range1f> value);\r\n        void CodeVolume_of_Range1d_(ref Volume<Range1d> value);\r\n        void CodeVolume_of_Box2i_(ref Volume<Box2i> value);\r\n        void CodeVolume_of_Box2l_(ref Volume<Box2l> value);\r\n        void CodeVolume_of_Box2f_(ref Volume<Box2f> value);\r\n        void CodeVolume_of_Box2d_(ref Volume<Box2d> value);\r\n        void CodeVolume_of_Box3i_(ref Volume<Box3i> value);\r\n        void CodeVolume_of_Box3l_(ref Volume<Box3l> value);\r\n        void CodeVolume_of_Box3f_(ref Volume<Box3f> value);\r\n        void CodeVolume_of_Box3d_(ref Volume<Box3d> value);\r\n        void CodeVolume_of_Euclidean3f_(ref Volume<Euclidean3f> value);\r\n        void CodeVolume_of_Euclidean3d_(ref Volume<Euclidean3d> value);\r\n        void CodeVolume_of_Rot2f_(ref Volume<Rot2f> value);\r\n        void CodeVolume_of_Rot2d_(ref Volume<Rot2d> value);\r\n        void CodeVolume_of_Rot3f_(ref Volume<Rot3f> value);\r\n        void CodeVolume_of_Rot3d_(ref Volume<Rot3d> value);\r\n        void CodeVolume_of_Scale3f_(ref Volume<Scale3f> value);\r\n        void CodeVolume_of_Scale3d_(ref Volume<Scale3d> value);\r\n        void CodeVolume_of_Shift3f_(ref Volume<Shift3f> value);\r\n        void CodeVolume_of_Shift3d_(ref Volume<Shift3d> value);\r\n        void CodeVolume_of_Trafo2f_(ref Volume<Trafo2f> value);\r\n        void CodeVolume_of_Trafo2d_(ref Volume<Trafo2d> value);\r\n        void CodeVolume_of_Trafo3f_(ref Volume<Trafo3f> value);\r\n        void CodeVolume_of_Trafo3d_(ref Volume<Trafo3d> value);\r\n        void CodeVolume_of_Bool_(ref Volume<bool> value);\r\n        void CodeVolume_of_Char_(ref Volume<char> value);\r\n        void CodeVolume_of_String_(ref Volume<string> value);\r\n        void CodeVolume_of_Type_(ref Volume<Type> value);\r\n        void CodeVolume_of_Guid_(ref Volume<Guid> value);\r\n        void CodeVolume_of_Symbol_(ref Volume<Symbol> value);\r\n        void CodeVolume_of_Circle2d_(ref Volume<Circle2d> value);\r\n        void CodeVolume_of_Line2d_(ref Volume<Line2d> value);\r\n        void CodeVolume_of_Line3d_(ref Volume<Line3d> value);\r\n        void CodeVolume_of_Plane2d_(ref Volume<Plane2d> value);\r\n        void CodeVolume_of_Plane3d_(ref Volume<Plane3d> value);\r\n        void CodeVolume_of_PlaneWithPoint3d_(ref Volume<PlaneWithPoint3d> value);\r\n        void CodeVolume_of_Quad2d_(ref Volume<Quad2d> value);\r\n        void CodeVolume_of_Quad3d_(ref Volume<Quad3d> value);\r\n        void CodeVolume_of_Ray2d_(ref Volume<Ray2d> value);\r\n        void CodeVolume_of_Ray3d_(ref Volume<Ray3d> value);\r\n        void CodeVolume_of_Sphere3d_(ref Volume<Sphere3d> value);\r\n        void CodeVolume_of_Triangle2d_(ref Volume<Triangle2d> value);\r\n        void CodeVolume_of_Triangle3d_(ref Volume<Triangle3d> value);\r\n        void CodeVolume_of_Circle2f_(ref Volume<Circle2f> value);\r\n        void CodeVolume_of_Line2f_(ref Volume<Line2f> value);\r\n        void CodeVolume_of_Line3f_(ref Volume<Line3f> value);\r\n        void CodeVolume_of_Plane2f_(ref Volume<Plane2f> value);\r\n        void CodeVolume_of_Plane3f_(ref Volume<Plane3f> value);\r\n        void CodeVolume_of_PlaneWithPoint3f_(ref Volume<PlaneWithPoint3f> value);\r\n        void CodeVolume_of_Quad2f_(ref Volume<Quad2f> value);\r\n        void CodeVolume_of_Quad3f_(ref Volume<Quad3f> value);\r\n        void CodeVolume_of_Ray2f_(ref Volume<Ray2f> value);\r\n        void CodeVolume_of_Ray3f_(ref Volume<Ray3f> value);\r\n        void CodeVolume_of_Sphere3f_(ref Volume<Sphere3f> value);\r\n        void CodeVolume_of_Triangle2f_(ref Volume<Triangle2f> value);\r\n        void CodeVolume_of_Triangle3f_(ref Volume<Triangle3f> value);\r\n        void CodeTensor_of_Byte_(ref Tensor<byte> value);\r\n        void CodeTensor_of_SByte_(ref Tensor<sbyte> value);\r\n        void CodeTensor_of_Short_(ref Tensor<short> value);\r\n        void CodeTensor_of_UShort_(ref Tensor<ushort> value);\r\n        void CodeTensor_of_Int_(ref Tensor<int> value);\r\n        void CodeTensor_of_UInt_(ref Tensor<uint> value);\r\n        void CodeTensor_of_Long_(ref Tensor<long> value);\r\n        void CodeTensor_of_ULong_(ref Tensor<ulong> value);\r\n        void CodeTensor_of_Float_(ref Tensor<float> value);\r\n        void CodeTensor_of_Double_(ref Tensor<double> value);\r\n        void CodeTensor_of_Fraction_(ref Tensor<Fraction> value);\r\n        void CodeTensor_of_V2i_(ref Tensor<V2i> value);\r\n        void CodeTensor_of_V2l_(ref Tensor<V2l> value);\r\n        void CodeTensor_of_V2f_(ref Tensor<V2f> value);\r\n        void CodeTensor_of_V2d_(ref Tensor<V2d> value);\r\n        void CodeTensor_of_V3i_(ref Tensor<V3i> value);\r\n        void CodeTensor_of_V3l_(ref Tensor<V3l> value);\r\n        void CodeTensor_of_V3f_(ref Tensor<V3f> value);\r\n        void CodeTensor_of_V3d_(ref Tensor<V3d> value);\r\n        void CodeTensor_of_V4i_(ref Tensor<V4i> value);\r\n        void CodeTensor_of_V4l_(ref Tensor<V4l> value);\r\n        void CodeTensor_of_V4f_(ref Tensor<V4f> value);\r\n        void CodeTensor_of_V4d_(ref Tensor<V4d> value);\r\n        void CodeTensor_of_M22i_(ref Tensor<M22i> value);\r\n        void CodeTensor_of_M22l_(ref Tensor<M22l> value);\r\n        void CodeTensor_of_M22f_(ref Tensor<M22f> value);\r\n        void CodeTensor_of_M22d_(ref Tensor<M22d> value);\r\n        void CodeTensor_of_M23i_(ref Tensor<M23i> value);\r\n        void CodeTensor_of_M23l_(ref Tensor<M23l> value);\r\n        void CodeTensor_of_M23f_(ref Tensor<M23f> value);\r\n        void CodeTensor_of_M23d_(ref Tensor<M23d> value);\r\n        void CodeTensor_of_M33i_(ref Tensor<M33i> value);\r\n        void CodeTensor_of_M33l_(ref Tensor<M33l> value);\r\n        void CodeTensor_of_M33f_(ref Tensor<M33f> value);\r\n        void CodeTensor_of_M33d_(ref Tensor<M33d> value);\r\n        void CodeTensor_of_M34i_(ref Tensor<M34i> value);\r\n        void CodeTensor_of_M34l_(ref Tensor<M34l> value);\r\n        void CodeTensor_of_M34f_(ref Tensor<M34f> value);\r\n        void CodeTensor_of_M34d_(ref Tensor<M34d> value);\r\n        void CodeTensor_of_M44i_(ref Tensor<M44i> value);\r\n        void CodeTensor_of_M44l_(ref Tensor<M44l> value);\r\n        void CodeTensor_of_M44f_(ref Tensor<M44f> value);\r\n        void CodeTensor_of_M44d_(ref Tensor<M44d> value);\r\n        void CodeTensor_of_C3b_(ref Tensor<C3b> value);\r\n        void CodeTensor_of_C3us_(ref Tensor<C3us> value);\r\n        void CodeTensor_of_C3ui_(ref Tensor<C3ui> value);\r\n        void CodeTensor_of_C3f_(ref Tensor<C3f> value);\r\n        void CodeTensor_of_C3d_(ref Tensor<C3d> value);\r\n        void CodeTensor_of_C4b_(ref Tensor<C4b> value);\r\n        void CodeTensor_of_C4us_(ref Tensor<C4us> value);\r\n        void CodeTensor_of_C4ui_(ref Tensor<C4ui> value);\r\n        void CodeTensor_of_C4f_(ref Tensor<C4f> value);\r\n        void CodeTensor_of_C4d_(ref Tensor<C4d> value);\r\n        void CodeTensor_of_Range1b_(ref Tensor<Range1b> value);\r\n        void CodeTensor_of_Range1sb_(ref Tensor<Range1sb> value);\r\n        void CodeTensor_of_Range1s_(ref Tensor<Range1s> value);\r\n        void CodeTensor_of_Range1us_(ref Tensor<Range1us> value);\r\n        void CodeTensor_of_Range1i_(ref Tensor<Range1i> value);\r\n        void CodeTensor_of_Range1ui_(ref Tensor<Range1ui> value);\r\n        void CodeTensor_of_Range1l_(ref Tensor<Range1l> value);\r\n        void CodeTensor_of_Range1ul_(ref Tensor<Range1ul> value);\r\n        void CodeTensor_of_Range1f_(ref Tensor<Range1f> value);\r\n        void CodeTensor_of_Range1d_(ref Tensor<Range1d> value);\r\n        void CodeTensor_of_Box2i_(ref Tensor<Box2i> value);\r\n        void CodeTensor_of_Box2l_(ref Tensor<Box2l> value);\r\n        void CodeTensor_of_Box2f_(ref Tensor<Box2f> value);\r\n        void CodeTensor_of_Box2d_(ref Tensor<Box2d> value);\r\n        void CodeTensor_of_Box3i_(ref Tensor<Box3i> value);\r\n        void CodeTensor_of_Box3l_(ref Tensor<Box3l> value);\r\n        void CodeTensor_of_Box3f_(ref Tensor<Box3f> value);\r\n        void CodeTensor_of_Box3d_(ref Tensor<Box3d> value);\r\n        void CodeTensor_of_Euclidean3f_(ref Tensor<Euclidean3f> value);\r\n        void CodeTensor_of_Euclidean3d_(ref Tensor<Euclidean3d> value);\r\n        void CodeTensor_of_Rot2f_(ref Tensor<Rot2f> value);\r\n        void CodeTensor_of_Rot2d_(ref Tensor<Rot2d> value);\r\n        void CodeTensor_of_Rot3f_(ref Tensor<Rot3f> value);\r\n        void CodeTensor_of_Rot3d_(ref Tensor<Rot3d> value);\r\n        void CodeTensor_of_Scale3f_(ref Tensor<Scale3f> value);\r\n        void CodeTensor_of_Scale3d_(ref Tensor<Scale3d> value);\r\n        void CodeTensor_of_Shift3f_(ref Tensor<Shift3f> value);\r\n        void CodeTensor_of_Shift3d_(ref Tensor<Shift3d> value);\r\n        void CodeTensor_of_Trafo2f_(ref Tensor<Trafo2f> value);\r\n        void CodeTensor_of_Trafo2d_(ref Tensor<Trafo2d> value);\r\n        void CodeTensor_of_Trafo3f_(ref Tensor<Trafo3f> value);\r\n        void CodeTensor_of_Trafo3d_(ref Tensor<Trafo3d> value);\r\n        void CodeTensor_of_Bool_(ref Tensor<bool> value);\r\n        void CodeTensor_of_Char_(ref Tensor<char> value);\r\n        void CodeTensor_of_String_(ref Tensor<string> value);\r\n        void CodeTensor_of_Type_(ref Tensor<Type> value);\r\n        void CodeTensor_of_Guid_(ref Tensor<Guid> value);\r\n        void CodeTensor_of_Symbol_(ref Tensor<Symbol> value);\r\n        void CodeTensor_of_Circle2d_(ref Tensor<Circle2d> value);\r\n        void CodeTensor_of_Line2d_(ref Tensor<Line2d> value);\r\n        void CodeTensor_of_Line3d_(ref Tensor<Line3d> value);\r\n        void CodeTensor_of_Plane2d_(ref Tensor<Plane2d> value);\r\n        void CodeTensor_of_Plane3d_(ref Tensor<Plane3d> value);\r\n        void CodeTensor_of_PlaneWithPoint3d_(ref Tensor<PlaneWithPoint3d> value);\r\n        void CodeTensor_of_Quad2d_(ref Tensor<Quad2d> value);\r\n        void CodeTensor_of_Quad3d_(ref Tensor<Quad3d> value);\r\n        void CodeTensor_of_Ray2d_(ref Tensor<Ray2d> value);\r\n        void CodeTensor_of_Ray3d_(ref Tensor<Ray3d> value);\r\n        void CodeTensor_of_Sphere3d_(ref Tensor<Sphere3d> value);\r\n        void CodeTensor_of_Triangle2d_(ref Tensor<Triangle2d> value);\r\n        void CodeTensor_of_Triangle3d_(ref Tensor<Triangle3d> value);\r\n        void CodeTensor_of_Circle2f_(ref Tensor<Circle2f> value);\r\n        void CodeTensor_of_Line2f_(ref Tensor<Line2f> value);\r\n        void CodeTensor_of_Line3f_(ref Tensor<Line3f> value);\r\n        void CodeTensor_of_Plane2f_(ref Tensor<Plane2f> value);\r\n        void CodeTensor_of_Plane3f_(ref Tensor<Plane3f> value);\r\n        void CodeTensor_of_PlaneWithPoint3f_(ref Tensor<PlaneWithPoint3f> value);\r\n        void CodeTensor_of_Quad2f_(ref Tensor<Quad2f> value);\r\n        void CodeTensor_of_Quad3f_(ref Tensor<Quad3f> value);\r\n        void CodeTensor_of_Ray2f_(ref Tensor<Ray2f> value);\r\n        void CodeTensor_of_Ray3f_(ref Tensor<Ray3f> value);\r\n        void CodeTensor_of_Sphere3f_(ref Tensor<Sphere3f> value);\r\n        void CodeTensor_of_Triangle2f_(ref Tensor<Triangle2f> value);\r\n        void CodeTensor_of_Triangle3f_(ref Tensor<Triangle3f> value);\r\n\r\n        #endregion\r\n\r\n        #region Arrays\r\n\r\n        void CodeBoolArray(ref bool[] value);\r\n        void CodeCharArray(ref char[] value);\r\n        void CodeStringArray(ref string[] value);\r\n        void CodeTypeArray(ref Type[] value);\r\n        void CodeGuidArray(ref Guid[] value);\r\n        void CodeSymbolArray(ref Symbol[] value);\r\n        void CodeByteArray(ref byte[] value);\r\n        void CodeSByteArray(ref sbyte[] value);\r\n        void CodeShortArray(ref short[] value);\r\n        void CodeUShortArray(ref ushort[] value);\r\n        void CodeIntArray(ref int[] value);\r\n        void CodeUIntArray(ref uint[] value);\r\n        void CodeLongArray(ref long[] value);\r\n        void CodeULongArray(ref ulong[] value);\r\n        void CodeFloatArray(ref float[] value);\r\n        void CodeDoubleArray(ref double[] value);\r\n        void CodeFractionArray(ref Fraction[] value);\r\n        void CodeV2iArray(ref V2i[] value);\r\n        void CodeV2lArray(ref V2l[] value);\r\n        void CodeV2fArray(ref V2f[] value);\r\n        void CodeV2dArray(ref V2d[] value);\r\n        void CodeV3iArray(ref V3i[] value);\r\n        void CodeV3lArray(ref V3l[] value);\r\n        void CodeV3fArray(ref V3f[] value);\r\n        void CodeV3dArray(ref V3d[] value);\r\n        void CodeV4iArray(ref V4i[] value);\r\n        void CodeV4lArray(ref V4l[] value);\r\n        void CodeV4fArray(ref V4f[] value);\r\n        void CodeV4dArray(ref V4d[] value);\r\n        void CodeM22iArray(ref M22i[] value);\r\n        void CodeM22lArray(ref M22l[] value);\r\n        void CodeM22fArray(ref M22f[] value);\r\n        void CodeM22dArray(ref M22d[] value);\r\n        void CodeM23iArray(ref M23i[] value);\r\n        void CodeM23lArray(ref M23l[] value);\r\n        void CodeM23fArray(ref M23f[] value);\r\n        void CodeM23dArray(ref M23d[] value);\r\n        void CodeM33iArray(ref M33i[] value);\r\n        void CodeM33lArray(ref M33l[] value);\r\n        void CodeM33fArray(ref M33f[] value);\r\n        void CodeM33dArray(ref M33d[] value);\r\n        void CodeM34iArray(ref M34i[] value);\r\n        void CodeM34lArray(ref M34l[] value);\r\n        void CodeM34fArray(ref M34f[] value);\r\n        void CodeM34dArray(ref M34d[] value);\r\n        void CodeM44iArray(ref M44i[] value);\r\n        void CodeM44lArray(ref M44l[] value);\r\n        void CodeM44fArray(ref M44f[] value);\r\n        void CodeM44dArray(ref M44d[] value);\r\n        void CodeC3bArray(ref C3b[] value);\r\n        void CodeC3usArray(ref C3us[] value);\r\n        void CodeC3uiArray(ref C3ui[] value);\r\n        void CodeC3fArray(ref C3f[] value);\r\n        void CodeC3dArray(ref C3d[] value);\r\n        void CodeC4bArray(ref C4b[] value);\r\n        void CodeC4usArray(ref C4us[] value);\r\n        void CodeC4uiArray(ref C4ui[] value);\r\n        void CodeC4fArray(ref C4f[] value);\r\n        void CodeC4dArray(ref C4d[] value);\r\n        void CodeRange1bArray(ref Range1b[] value);\r\n        void CodeRange1sbArray(ref Range1sb[] value);\r\n        void CodeRange1sArray(ref Range1s[] value);\r\n        void CodeRange1usArray(ref Range1us[] value);\r\n        void CodeRange1iArray(ref Range1i[] value);\r\n        void CodeRange1uiArray(ref Range1ui[] value);\r\n        void CodeRange1lArray(ref Range1l[] value);\r\n        void CodeRange1ulArray(ref Range1ul[] value);\r\n        void CodeRange1fArray(ref Range1f[] value);\r\n        void CodeRange1dArray(ref Range1d[] value);\r\n        void CodeBox2iArray(ref Box2i[] value);\r\n        void CodeBox2lArray(ref Box2l[] value);\r\n        void CodeBox2fArray(ref Box2f[] value);\r\n        void CodeBox2dArray(ref Box2d[] value);\r\n        void CodeBox3iArray(ref Box3i[] value);\r\n        void CodeBox3lArray(ref Box3l[] value);\r\n        void CodeBox3fArray(ref Box3f[] value);\r\n        void CodeBox3dArray(ref Box3d[] value);\r\n        void CodeEuclidean3fArray(ref Euclidean3f[] value);\r\n        void CodeEuclidean3dArray(ref Euclidean3d[] value);\r\n        void CodeRot2fArray(ref Rot2f[] value);\r\n        void CodeRot2dArray(ref Rot2d[] value);\r\n        void CodeRot3fArray(ref Rot3f[] value);\r\n        void CodeRot3dArray(ref Rot3d[] value);\r\n        void CodeScale3fArray(ref Scale3f[] value);\r\n        void CodeScale3dArray(ref Scale3d[] value);\r\n        void CodeShift3fArray(ref Shift3f[] value);\r\n        void CodeShift3dArray(ref Shift3d[] value);\r\n        void CodeTrafo2fArray(ref Trafo2f[] value);\r\n        void CodeTrafo2dArray(ref Trafo2d[] value);\r\n        void CodeTrafo3fArray(ref Trafo3f[] value);\r\n        void CodeTrafo3dArray(ref Trafo3d[] value);\r\n        void CodeCircle2dArray(ref Circle2d[] value);\r\n        void CodeLine2dArray(ref Line2d[] value);\r\n        void CodeLine3dArray(ref Line3d[] value);\r\n        void CodePlane2dArray(ref Plane2d[] value);\r\n        void CodePlane3dArray(ref Plane3d[] value);\r\n        void CodePlaneWithPoint3dArray(ref PlaneWithPoint3d[] value);\r\n        void CodeQuad2dArray(ref Quad2d[] value);\r\n        void CodeQuad3dArray(ref Quad3d[] value);\r\n        void CodeRay2dArray(ref Ray2d[] value);\r\n        void CodeRay3dArray(ref Ray3d[] value);\r\n        void CodeSphere3dArray(ref Sphere3d[] value);\r\n        void CodeTriangle2dArray(ref Triangle2d[] value);\r\n        void CodeTriangle3dArray(ref Triangle3d[] value);\r\n        void CodeCircle2fArray(ref Circle2f[] value);\r\n        void CodeLine2fArray(ref Line2f[] value);\r\n        void CodeLine3fArray(ref Line3f[] value);\r\n        void CodePlane2fArray(ref Plane2f[] value);\r\n        void CodePlane3fArray(ref Plane3f[] value);\r\n        void CodePlaneWithPoint3fArray(ref PlaneWithPoint3f[] value);\r\n        void CodeQuad2fArray(ref Quad2f[] value);\r\n        void CodeQuad3fArray(ref Quad3f[] value);\r\n        void CodeRay2fArray(ref Ray2f[] value);\r\n        void CodeRay3fArray(ref Ray3f[] value);\r\n        void CodeSphere3fArray(ref Sphere3f[] value);\r\n        void CodeTriangle2fArray(ref Triangle2f[] value);\r\n        void CodeTriangle3fArray(ref Triangle3f[] value);\r\n        void CodeVector_of_Byte_Array(ref Vector<byte>[] value);\r\n        void CodeVector_of_SByte_Array(ref Vector<sbyte>[] value);\r\n        void CodeVector_of_Short_Array(ref Vector<short>[] value);\r\n        void CodeVector_of_UShort_Array(ref Vector<ushort>[] value);\r\n        void CodeVector_of_Int_Array(ref Vector<int>[] value);\r\n        void CodeVector_of_UInt_Array(ref Vector<uint>[] value);\r\n        void CodeVector_of_Long_Array(ref Vector<long>[] value);\r\n        void CodeVector_of_ULong_Array(ref Vector<ulong>[] value);\r\n        void CodeVector_of_Float_Array(ref Vector<float>[] value);\r\n        void CodeVector_of_Double_Array(ref Vector<double>[] value);\r\n        void CodeVector_of_Fraction_Array(ref Vector<Fraction>[] value);\r\n        void CodeVector_of_V2i_Array(ref Vector<V2i>[] value);\r\n        void CodeVector_of_V2l_Array(ref Vector<V2l>[] value);\r\n        void CodeVector_of_V2f_Array(ref Vector<V2f>[] value);\r\n        void CodeVector_of_V2d_Array(ref Vector<V2d>[] value);\r\n        void CodeVector_of_V3i_Array(ref Vector<V3i>[] value);\r\n        void CodeVector_of_V3l_Array(ref Vector<V3l>[] value);\r\n        void CodeVector_of_V3f_Array(ref Vector<V3f>[] value);\r\n        void CodeVector_of_V3d_Array(ref Vector<V3d>[] value);\r\n        void CodeVector_of_V4i_Array(ref Vector<V4i>[] value);\r\n        void CodeVector_of_V4l_Array(ref Vector<V4l>[] value);\r\n        void CodeVector_of_V4f_Array(ref Vector<V4f>[] value);\r\n        void CodeVector_of_V4d_Array(ref Vector<V4d>[] value);\r\n        void CodeVector_of_M22i_Array(ref Vector<M22i>[] value);\r\n        void CodeVector_of_M22l_Array(ref Vector<M22l>[] value);\r\n        void CodeVector_of_M22f_Array(ref Vector<M22f>[] value);\r\n        void CodeVector_of_M22d_Array(ref Vector<M22d>[] value);\r\n        void CodeVector_of_M23i_Array(ref Vector<M23i>[] value);\r\n        void CodeVector_of_M23l_Array(ref Vector<M23l>[] value);\r\n        void CodeVector_of_M23f_Array(ref Vector<M23f>[] value);\r\n        void CodeVector_of_M23d_Array(ref Vector<M23d>[] value);\r\n        void CodeVector_of_M33i_Array(ref Vector<M33i>[] value);\r\n        void CodeVector_of_M33l_Array(ref Vector<M33l>[] value);\r\n        void CodeVector_of_M33f_Array(ref Vector<M33f>[] value);\r\n        void CodeVector_of_M33d_Array(ref Vector<M33d>[] value);\r\n        void CodeVector_of_M34i_Array(ref Vector<M34i>[] value);\r\n        void CodeVector_of_M34l_Array(ref Vector<M34l>[] value);\r\n        void CodeVector_of_M34f_Array(ref Vector<M34f>[] value);\r\n        void CodeVector_of_M34d_Array(ref Vector<M34d>[] value);\r\n        void CodeVector_of_M44i_Array(ref Vector<M44i>[] value);\r\n        void CodeVector_of_M44l_Array(ref Vector<M44l>[] value);\r\n        void CodeVector_of_M44f_Array(ref Vector<M44f>[] value);\r\n        void CodeVector_of_M44d_Array(ref Vector<M44d>[] value);\r\n        void CodeVector_of_C3b_Array(ref Vector<C3b>[] value);\r\n        void CodeVector_of_C3us_Array(ref Vector<C3us>[] value);\r\n        void CodeVector_of_C3ui_Array(ref Vector<C3ui>[] value);\r\n        void CodeVector_of_C3f_Array(ref Vector<C3f>[] value);\r\n        void CodeVector_of_C3d_Array(ref Vector<C3d>[] value);\r\n        void CodeVector_of_C4b_Array(ref Vector<C4b>[] value);\r\n        void CodeVector_of_C4us_Array(ref Vector<C4us>[] value);\r\n        void CodeVector_of_C4ui_Array(ref Vector<C4ui>[] value);\r\n        void CodeVector_of_C4f_Array(ref Vector<C4f>[] value);\r\n        void CodeVector_of_C4d_Array(ref Vector<C4d>[] value);\r\n        void CodeVector_of_Range1b_Array(ref Vector<Range1b>[] value);\r\n        void CodeVector_of_Range1sb_Array(ref Vector<Range1sb>[] value);\r\n        void CodeVector_of_Range1s_Array(ref Vector<Range1s>[] value);\r\n        void CodeVector_of_Range1us_Array(ref Vector<Range1us>[] value);\r\n        void CodeVector_of_Range1i_Array(ref Vector<Range1i>[] value);\r\n        void CodeVector_of_Range1ui_Array(ref Vector<Range1ui>[] value);\r\n        void CodeVector_of_Range1l_Array(ref Vector<Range1l>[] value);\r\n        void CodeVector_of_Range1ul_Array(ref Vector<Range1ul>[] value);\r\n        void CodeVector_of_Range1f_Array(ref Vector<Range1f>[] value);\r\n        void CodeVector_of_Range1d_Array(ref Vector<Range1d>[] value);\r\n        void CodeVector_of_Box2i_Array(ref Vector<Box2i>[] value);\r\n        void CodeVector_of_Box2l_Array(ref Vector<Box2l>[] value);\r\n        void CodeVector_of_Box2f_Array(ref Vector<Box2f>[] value);\r\n        void CodeVector_of_Box2d_Array(ref Vector<Box2d>[] value);\r\n        void CodeVector_of_Box3i_Array(ref Vector<Box3i>[] value);\r\n        void CodeVector_of_Box3l_Array(ref Vector<Box3l>[] value);\r\n        void CodeVector_of_Box3f_Array(ref Vector<Box3f>[] value);\r\n        void CodeVector_of_Box3d_Array(ref Vector<Box3d>[] value);\r\n        void CodeVector_of_Euclidean3f_Array(ref Vector<Euclidean3f>[] value);\r\n        void CodeVector_of_Euclidean3d_Array(ref Vector<Euclidean3d>[] value);\r\n        void CodeVector_of_Rot2f_Array(ref Vector<Rot2f>[] value);\r\n        void CodeVector_of_Rot2d_Array(ref Vector<Rot2d>[] value);\r\n        void CodeVector_of_Rot3f_Array(ref Vector<Rot3f>[] value);\r\n        void CodeVector_of_Rot3d_Array(ref Vector<Rot3d>[] value);\r\n        void CodeVector_of_Scale3f_Array(ref Vector<Scale3f>[] value);\r\n        void CodeVector_of_Scale3d_Array(ref Vector<Scale3d>[] value);\r\n        void CodeVector_of_Shift3f_Array(ref Vector<Shift3f>[] value);\r\n        void CodeVector_of_Shift3d_Array(ref Vector<Shift3d>[] value);\r\n        void CodeVector_of_Trafo2f_Array(ref Vector<Trafo2f>[] value);\r\n        void CodeVector_of_Trafo2d_Array(ref Vector<Trafo2d>[] value);\r\n        void CodeVector_of_Trafo3f_Array(ref Vector<Trafo3f>[] value);\r\n        void CodeVector_of_Trafo3d_Array(ref Vector<Trafo3d>[] value);\r\n        void CodeVector_of_Bool_Array(ref Vector<bool>[] value);\r\n        void CodeVector_of_Char_Array(ref Vector<char>[] value);\r\n        void CodeVector_of_String_Array(ref Vector<string>[] value);\r\n        void CodeVector_of_Type_Array(ref Vector<Type>[] value);\r\n        void CodeVector_of_Guid_Array(ref Vector<Guid>[] value);\r\n        void CodeVector_of_Symbol_Array(ref Vector<Symbol>[] value);\r\n        void CodeVector_of_Circle2d_Array(ref Vector<Circle2d>[] value);\r\n        void CodeVector_of_Line2d_Array(ref Vector<Line2d>[] value);\r\n        void CodeVector_of_Line3d_Array(ref Vector<Line3d>[] value);\r\n        void CodeVector_of_Plane2d_Array(ref Vector<Plane2d>[] value);\r\n        void CodeVector_of_Plane3d_Array(ref Vector<Plane3d>[] value);\r\n        void CodeVector_of_PlaneWithPoint3d_Array(ref Vector<PlaneWithPoint3d>[] value);\r\n        void CodeVector_of_Quad2d_Array(ref Vector<Quad2d>[] value);\r\n        void CodeVector_of_Quad3d_Array(ref Vector<Quad3d>[] value);\r\n        void CodeVector_of_Ray2d_Array(ref Vector<Ray2d>[] value);\r\n        void CodeVector_of_Ray3d_Array(ref Vector<Ray3d>[] value);\r\n        void CodeVector_of_Sphere3d_Array(ref Vector<Sphere3d>[] value);\r\n        void CodeVector_of_Triangle2d_Array(ref Vector<Triangle2d>[] value);\r\n        void CodeVector_of_Triangle3d_Array(ref Vector<Triangle3d>[] value);\r\n        void CodeVector_of_Circle2f_Array(ref Vector<Circle2f>[] value);\r\n        void CodeVector_of_Line2f_Array(ref Vector<Line2f>[] value);\r\n        void CodeVector_of_Line3f_Array(ref Vector<Line3f>[] value);\r\n        void CodeVector_of_Plane2f_Array(ref Vector<Plane2f>[] value);\r\n        void CodeVector_of_Plane3f_Array(ref Vector<Plane3f>[] value);\r\n        void CodeVector_of_PlaneWithPoint3f_Array(ref Vector<PlaneWithPoint3f>[] value);\r\n        void CodeVector_of_Quad2f_Array(ref Vector<Quad2f>[] value);\r\n        void CodeVector_of_Quad3f_Array(ref Vector<Quad3f>[] value);\r\n        void CodeVector_of_Ray2f_Array(ref Vector<Ray2f>[] value);\r\n        void CodeVector_of_Ray3f_Array(ref Vector<Ray3f>[] value);\r\n        void CodeVector_of_Sphere3f_Array(ref Vector<Sphere3f>[] value);\r\n        void CodeVector_of_Triangle2f_Array(ref Vector<Triangle2f>[] value);\r\n        void CodeVector_of_Triangle3f_Array(ref Vector<Triangle3f>[] value);\r\n        void CodeMatrix_of_Byte_Array(ref Matrix<byte>[] value);\r\n        void CodeMatrix_of_SByte_Array(ref Matrix<sbyte>[] value);\r\n        void CodeMatrix_of_Short_Array(ref Matrix<short>[] value);\r\n        void CodeMatrix_of_UShort_Array(ref Matrix<ushort>[] value);\r\n        void CodeMatrix_of_Int_Array(ref Matrix<int>[] value);\r\n        void CodeMatrix_of_UInt_Array(ref Matrix<uint>[] value);\r\n        void CodeMatrix_of_Long_Array(ref Matrix<long>[] value);\r\n        void CodeMatrix_of_ULong_Array(ref Matrix<ulong>[] value);\r\n        void CodeMatrix_of_Float_Array(ref Matrix<float>[] value);\r\n        void CodeMatrix_of_Double_Array(ref Matrix<double>[] value);\r\n        void CodeMatrix_of_Fraction_Array(ref Matrix<Fraction>[] value);\r\n        void CodeMatrix_of_V2i_Array(ref Matrix<V2i>[] value);\r\n        void CodeMatrix_of_V2l_Array(ref Matrix<V2l>[] value);\r\n        void CodeMatrix_of_V2f_Array(ref Matrix<V2f>[] value);\r\n        void CodeMatrix_of_V2d_Array(ref Matrix<V2d>[] value);\r\n        void CodeMatrix_of_V3i_Array(ref Matrix<V3i>[] value);\r\n        void CodeMatrix_of_V3l_Array(ref Matrix<V3l>[] value);\r\n        void CodeMatrix_of_V3f_Array(ref Matrix<V3f>[] value);\r\n        void CodeMatrix_of_V3d_Array(ref Matrix<V3d>[] value);\r\n        void CodeMatrix_of_V4i_Array(ref Matrix<V4i>[] value);\r\n        void CodeMatrix_of_V4l_Array(ref Matrix<V4l>[] value);\r\n        void CodeMatrix_of_V4f_Array(ref Matrix<V4f>[] value);\r\n        void CodeMatrix_of_V4d_Array(ref Matrix<V4d>[] value);\r\n        void CodeMatrix_of_M22i_Array(ref Matrix<M22i>[] value);\r\n        void CodeMatrix_of_M22l_Array(ref Matrix<M22l>[] value);\r\n        void CodeMatrix_of_M22f_Array(ref Matrix<M22f>[] value);\r\n        void CodeMatrix_of_M22d_Array(ref Matrix<M22d>[] value);\r\n        void CodeMatrix_of_M23i_Array(ref Matrix<M23i>[] value);\r\n        void CodeMatrix_of_M23l_Array(ref Matrix<M23l>[] value);\r\n        void CodeMatrix_of_M23f_Array(ref Matrix<M23f>[] value);\r\n        void CodeMatrix_of_M23d_Array(ref Matrix<M23d>[] value);\r\n        void CodeMatrix_of_M33i_Array(ref Matrix<M33i>[] value);\r\n        void CodeMatrix_of_M33l_Array(ref Matrix<M33l>[] value);\r\n        void CodeMatrix_of_M33f_Array(ref Matrix<M33f>[] value);\r\n        void CodeMatrix_of_M33d_Array(ref Matrix<M33d>[] value);\r\n        void CodeMatrix_of_M34i_Array(ref Matrix<M34i>[] value);\r\n        void CodeMatrix_of_M34l_Array(ref Matrix<M34l>[] value);\r\n        void CodeMatrix_of_M34f_Array(ref Matrix<M34f>[] value);\r\n        void CodeMatrix_of_M34d_Array(ref Matrix<M34d>[] value);\r\n        void CodeMatrix_of_M44i_Array(ref Matrix<M44i>[] value);\r\n        void CodeMatrix_of_M44l_Array(ref Matrix<M44l>[] value);\r\n        void CodeMatrix_of_M44f_Array(ref Matrix<M44f>[] value);\r\n        void CodeMatrix_of_M44d_Array(ref Matrix<M44d>[] value);\r\n        void CodeMatrix_of_C3b_Array(ref Matrix<C3b>[] value);\r\n        void CodeMatrix_of_C3us_Array(ref Matrix<C3us>[] value);\r\n        void CodeMatrix_of_C3ui_Array(ref Matrix<C3ui>[] value);\r\n        void CodeMatrix_of_C3f_Array(ref Matrix<C3f>[] value);\r\n        void CodeMatrix_of_C3d_Array(ref Matrix<C3d>[] value);\r\n        void CodeMatrix_of_C4b_Array(ref Matrix<C4b>[] value);\r\n        void CodeMatrix_of_C4us_Array(ref Matrix<C4us>[] value);\r\n        void CodeMatrix_of_C4ui_Array(ref Matrix<C4ui>[] value);\r\n        void CodeMatrix_of_C4f_Array(ref Matrix<C4f>[] value);\r\n        void CodeMatrix_of_C4d_Array(ref Matrix<C4d>[] value);\r\n        void CodeMatrix_of_Range1b_Array(ref Matrix<Range1b>[] value);\r\n        void CodeMatrix_of_Range1sb_Array(ref Matrix<Range1sb>[] value);\r\n        void CodeMatrix_of_Range1s_Array(ref Matrix<Range1s>[] value);\r\n        void CodeMatrix_of_Range1us_Array(ref Matrix<Range1us>[] value);\r\n        void CodeMatrix_of_Range1i_Array(ref Matrix<Range1i>[] value);\r\n        void CodeMatrix_of_Range1ui_Array(ref Matrix<Range1ui>[] value);\r\n        void CodeMatrix_of_Range1l_Array(ref Matrix<Range1l>[] value);\r\n        void CodeMatrix_of_Range1ul_Array(ref Matrix<Range1ul>[] value);\r\n        void CodeMatrix_of_Range1f_Array(ref Matrix<Range1f>[] value);\r\n        void CodeMatrix_of_Range1d_Array(ref Matrix<Range1d>[] value);\r\n        void CodeMatrix_of_Box2i_Array(ref Matrix<Box2i>[] value);\r\n        void CodeMatrix_of_Box2l_Array(ref Matrix<Box2l>[] value);\r\n        void CodeMatrix_of_Box2f_Array(ref Matrix<Box2f>[] value);\r\n        void CodeMatrix_of_Box2d_Array(ref Matrix<Box2d>[] value);\r\n        void CodeMatrix_of_Box3i_Array(ref Matrix<Box3i>[] value);\r\n        void CodeMatrix_of_Box3l_Array(ref Matrix<Box3l>[] value);\r\n        void CodeMatrix_of_Box3f_Array(ref Matrix<Box3f>[] value);\r\n        void CodeMatrix_of_Box3d_Array(ref Matrix<Box3d>[] value);\r\n        void CodeMatrix_of_Euclidean3f_Array(ref Matrix<Euclidean3f>[] value);\r\n        void CodeMatrix_of_Euclidean3d_Array(ref Matrix<Euclidean3d>[] value);\r\n        void CodeMatrix_of_Rot2f_Array(ref Matrix<Rot2f>[] value);\r\n        void CodeMatrix_of_Rot2d_Array(ref Matrix<Rot2d>[] value);\r\n        void CodeMatrix_of_Rot3f_Array(ref Matrix<Rot3f>[] value);\r\n        void CodeMatrix_of_Rot3d_Array(ref Matrix<Rot3d>[] value);\r\n        void CodeMatrix_of_Scale3f_Array(ref Matrix<Scale3f>[] value);\r\n        void CodeMatrix_of_Scale3d_Array(ref Matrix<Scale3d>[] value);\r\n        void CodeMatrix_of_Shift3f_Array(ref Matrix<Shift3f>[] value);\r\n        void CodeMatrix_of_Shift3d_Array(ref Matrix<Shift3d>[] value);\r\n        void CodeMatrix_of_Trafo2f_Array(ref Matrix<Trafo2f>[] value);\r\n        void CodeMatrix_of_Trafo2d_Array(ref Matrix<Trafo2d>[] value);\r\n        void CodeMatrix_of_Trafo3f_Array(ref Matrix<Trafo3f>[] value);\r\n        void CodeMatrix_of_Trafo3d_Array(ref Matrix<Trafo3d>[] value);\r\n        void CodeMatrix_of_Bool_Array(ref Matrix<bool>[] value);\r\n        void CodeMatrix_of_Char_Array(ref Matrix<char>[] value);\r\n        void CodeMatrix_of_String_Array(ref Matrix<string>[] value);\r\n        void CodeMatrix_of_Type_Array(ref Matrix<Type>[] value);\r\n        void CodeMatrix_of_Guid_Array(ref Matrix<Guid>[] value);\r\n        void CodeMatrix_of_Symbol_Array(ref Matrix<Symbol>[] value);\r\n        void CodeMatrix_of_Circle2d_Array(ref Matrix<Circle2d>[] value);\r\n        void CodeMatrix_of_Line2d_Array(ref Matrix<Line2d>[] value);\r\n        void CodeMatrix_of_Line3d_Array(ref Matrix<Line3d>[] value);\r\n        void CodeMatrix_of_Plane2d_Array(ref Matrix<Plane2d>[] value);\r\n        void CodeMatrix_of_Plane3d_Array(ref Matrix<Plane3d>[] value);\r\n        void CodeMatrix_of_PlaneWithPoint3d_Array(ref Matrix<PlaneWithPoint3d>[] value);\r\n        void CodeMatrix_of_Quad2d_Array(ref Matrix<Quad2d>[] value);\r\n        void CodeMatrix_of_Quad3d_Array(ref Matrix<Quad3d>[] value);\r\n        void CodeMatrix_of_Ray2d_Array(ref Matrix<Ray2d>[] value);\r\n        void CodeMatrix_of_Ray3d_Array(ref Matrix<Ray3d>[] value);\r\n        void CodeMatrix_of_Sphere3d_Array(ref Matrix<Sphere3d>[] value);\r\n        void CodeMatrix_of_Triangle2d_Array(ref Matrix<Triangle2d>[] value);\r\n        void CodeMatrix_of_Triangle3d_Array(ref Matrix<Triangle3d>[] value);\r\n        void CodeMatrix_of_Circle2f_Array(ref Matrix<Circle2f>[] value);\r\n        void CodeMatrix_of_Line2f_Array(ref Matrix<Line2f>[] value);\r\n        void CodeMatrix_of_Line3f_Array(ref Matrix<Line3f>[] value);\r\n        void CodeMatrix_of_Plane2f_Array(ref Matrix<Plane2f>[] value);\r\n        void CodeMatrix_of_Plane3f_Array(ref Matrix<Plane3f>[] value);\r\n        void CodeMatrix_of_PlaneWithPoint3f_Array(ref Matrix<PlaneWithPoint3f>[] value);\r\n        void CodeMatrix_of_Quad2f_Array(ref Matrix<Quad2f>[] value);\r\n        void CodeMatrix_of_Quad3f_Array(ref Matrix<Quad3f>[] value);\r\n        void CodeMatrix_of_Ray2f_Array(ref Matrix<Ray2f>[] value);\r\n        void CodeMatrix_of_Ray3f_Array(ref Matrix<Ray3f>[] value);\r\n        void CodeMatrix_of_Sphere3f_Array(ref Matrix<Sphere3f>[] value);\r\n        void CodeMatrix_of_Triangle2f_Array(ref Matrix<Triangle2f>[] value);\r\n        void CodeMatrix_of_Triangle3f_Array(ref Matrix<Triangle3f>[] value);\r\n        void CodeVolume_of_Byte_Array(ref Volume<byte>[] value);\r\n        void CodeVolume_of_SByte_Array(ref Volume<sbyte>[] value);\r\n        void CodeVolume_of_Short_Array(ref Volume<short>[] value);\r\n        void CodeVolume_of_UShort_Array(ref Volume<ushort>[] value);\r\n        void CodeVolume_of_Int_Array(ref Volume<int>[] value);\r\n        void CodeVolume_of_UInt_Array(ref Volume<uint>[] value);\r\n        void CodeVolume_of_Long_Array(ref Volume<long>[] value);\r\n        void CodeVolume_of_ULong_Array(ref Volume<ulong>[] value);\r\n        void CodeVolume_of_Float_Array(ref Volume<float>[] value);\r\n        void CodeVolume_of_Double_Array(ref Volume<double>[] value);\r\n        void CodeVolume_of_Fraction_Array(ref Volume<Fraction>[] value);\r\n        void CodeVolume_of_V2i_Array(ref Volume<V2i>[] value);\r\n        void CodeVolume_of_V2l_Array(ref Volume<V2l>[] value);\r\n        void CodeVolume_of_V2f_Array(ref Volume<V2f>[] value);\r\n        void CodeVolume_of_V2d_Array(ref Volume<V2d>[] value);\r\n        void CodeVolume_of_V3i_Array(ref Volume<V3i>[] value);\r\n        void CodeVolume_of_V3l_Array(ref Volume<V3l>[] value);\r\n        void CodeVolume_of_V3f_Array(ref Volume<V3f>[] value);\r\n        void CodeVolume_of_V3d_Array(ref Volume<V3d>[] value);\r\n        void CodeVolume_of_V4i_Array(ref Volume<V4i>[] value);\r\n        void CodeVolume_of_V4l_Array(ref Volume<V4l>[] value);\r\n        void CodeVolume_of_V4f_Array(ref Volume<V4f>[] value);\r\n        void CodeVolume_of_V4d_Array(ref Volume<V4d>[] value);\r\n        void CodeVolume_of_M22i_Array(ref Volume<M22i>[] value);\r\n        void CodeVolume_of_M22l_Array(ref Volume<M22l>[] value);\r\n        void CodeVolume_of_M22f_Array(ref Volume<M22f>[] value);\r\n        void CodeVolume_of_M22d_Array(ref Volume<M22d>[] value);\r\n        void CodeVolume_of_M23i_Array(ref Volume<M23i>[] value);\r\n        void CodeVolume_of_M23l_Array(ref Volume<M23l>[] value);\r\n        void CodeVolume_of_M23f_Array(ref Volume<M23f>[] value);\r\n        void CodeVolume_of_M23d_Array(ref Volume<M23d>[] value);\r\n        void CodeVolume_of_M33i_Array(ref Volume<M33i>[] value);\r\n        void CodeVolume_of_M33l_Array(ref Volume<M33l>[] value);\r\n        void CodeVolume_of_M33f_Array(ref Volume<M33f>[] value);\r\n        void CodeVolume_of_M33d_Array(ref Volume<M33d>[] value);\r\n        void CodeVolume_of_M34i_Array(ref Volume<M34i>[] value);\r\n        void CodeVolume_of_M34l_Array(ref Volume<M34l>[] value);\r\n        void CodeVolume_of_M34f_Array(ref Volume<M34f>[] value);\r\n        void CodeVolume_of_M34d_Array(ref Volume<M34d>[] value);\r\n        void CodeVolume_of_M44i_Array(ref Volume<M44i>[] value);\r\n        void CodeVolume_of_M44l_Array(ref Volume<M44l>[] value);\r\n        void CodeVolume_of_M44f_Array(ref Volume<M44f>[] value);\r\n        void CodeVolume_of_M44d_Array(ref Volume<M44d>[] value);\r\n        void CodeVolume_of_C3b_Array(ref Volume<C3b>[] value);\r\n        void CodeVolume_of_C3us_Array(ref Volume<C3us>[] value);\r\n        void CodeVolume_of_C3ui_Array(ref Volume<C3ui>[] value);\r\n        void CodeVolume_of_C3f_Array(ref Volume<C3f>[] value);\r\n        void CodeVolume_of_C3d_Array(ref Volume<C3d>[] value);\r\n        void CodeVolume_of_C4b_Array(ref Volume<C4b>[] value);\r\n        void CodeVolume_of_C4us_Array(ref Volume<C4us>[] value);\r\n        void CodeVolume_of_C4ui_Array(ref Volume<C4ui>[] value);\r\n        void CodeVolume_of_C4f_Array(ref Volume<C4f>[] value);\r\n        void CodeVolume_of_C4d_Array(ref Volume<C4d>[] value);\r\n        void CodeVolume_of_Range1b_Array(ref Volume<Range1b>[] value);\r\n        void CodeVolume_of_Range1sb_Array(ref Volume<Range1sb>[] value);\r\n        void CodeVolume_of_Range1s_Array(ref Volume<Range1s>[] value);\r\n        void CodeVolume_of_Range1us_Array(ref Volume<Range1us>[] value);\r\n        void CodeVolume_of_Range1i_Array(ref Volume<Range1i>[] value);\r\n        void CodeVolume_of_Range1ui_Array(ref Volume<Range1ui>[] value);\r\n        void CodeVolume_of_Range1l_Array(ref Volume<Range1l>[] value);\r\n        void CodeVolume_of_Range1ul_Array(ref Volume<Range1ul>[] value);\r\n        void CodeVolume_of_Range1f_Array(ref Volume<Range1f>[] value);\r\n        void CodeVolume_of_Range1d_Array(ref Volume<Range1d>[] value);\r\n        void CodeVolume_of_Box2i_Array(ref Volume<Box2i>[] value);\r\n        void CodeVolume_of_Box2l_Array(ref Volume<Box2l>[] value);\r\n        void CodeVolume_of_Box2f_Array(ref Volume<Box2f>[] value);\r\n        void CodeVolume_of_Box2d_Array(ref Volume<Box2d>[] value);\r\n        void CodeVolume_of_Box3i_Array(ref Volume<Box3i>[] value);\r\n        void CodeVolume_of_Box3l_Array(ref Volume<Box3l>[] value);\r\n        void CodeVolume_of_Box3f_Array(ref Volume<Box3f>[] value);\r\n        void CodeVolume_of_Box3d_Array(ref Volume<Box3d>[] value);\r\n        void CodeVolume_of_Euclidean3f_Array(ref Volume<Euclidean3f>[] value);\r\n        void CodeVolume_of_Euclidean3d_Array(ref Volume<Euclidean3d>[] value);\r\n        void CodeVolume_of_Rot2f_Array(ref Volume<Rot2f>[] value);\r\n        void CodeVolume_of_Rot2d_Array(ref Volume<Rot2d>[] value);\r\n        void CodeVolume_of_Rot3f_Array(ref Volume<Rot3f>[] value);\r\n        void CodeVolume_of_Rot3d_Array(ref Volume<Rot3d>[] value);\r\n        void CodeVolume_of_Scale3f_Array(ref Volume<Scale3f>[] value);\r\n        void CodeVolume_of_Scale3d_Array(ref Volume<Scale3d>[] value);\r\n        void CodeVolume_of_Shift3f_Array(ref Volume<Shift3f>[] value);\r\n        void CodeVolume_of_Shift3d_Array(ref Volume<Shift3d>[] value);\r\n        void CodeVolume_of_Trafo2f_Array(ref Volume<Trafo2f>[] value);\r\n        void CodeVolume_of_Trafo2d_Array(ref Volume<Trafo2d>[] value);\r\n        void CodeVolume_of_Trafo3f_Array(ref Volume<Trafo3f>[] value);\r\n        void CodeVolume_of_Trafo3d_Array(ref Volume<Trafo3d>[] value);\r\n        void CodeVolume_of_Bool_Array(ref Volume<bool>[] value);\r\n        void CodeVolume_of_Char_Array(ref Volume<char>[] value);\r\n        void CodeVolume_of_String_Array(ref Volume<string>[] value);\r\n        void CodeVolume_of_Type_Array(ref Volume<Type>[] value);\r\n        void CodeVolume_of_Guid_Array(ref Volume<Guid>[] value);\r\n        void CodeVolume_of_Symbol_Array(ref Volume<Symbol>[] value);\r\n        void CodeVolume_of_Circle2d_Array(ref Volume<Circle2d>[] value);\r\n        void CodeVolume_of_Line2d_Array(ref Volume<Line2d>[] value);\r\n        void CodeVolume_of_Line3d_Array(ref Volume<Line3d>[] value);\r\n        void CodeVolume_of_Plane2d_Array(ref Volume<Plane2d>[] value);\r\n        void CodeVolume_of_Plane3d_Array(ref Volume<Plane3d>[] value);\r\n        void CodeVolume_of_PlaneWithPoint3d_Array(ref Volume<PlaneWithPoint3d>[] value);\r\n        void CodeVolume_of_Quad2d_Array(ref Volume<Quad2d>[] value);\r\n        void CodeVolume_of_Quad3d_Array(ref Volume<Quad3d>[] value);\r\n        void CodeVolume_of_Ray2d_Array(ref Volume<Ray2d>[] value);\r\n        void CodeVolume_of_Ray3d_Array(ref Volume<Ray3d>[] value);\r\n        void CodeVolume_of_Sphere3d_Array(ref Volume<Sphere3d>[] value);\r\n        void CodeVolume_of_Triangle2d_Array(ref Volume<Triangle2d>[] value);\r\n        void CodeVolume_of_Triangle3d_Array(ref Volume<Triangle3d>[] value);\r\n        void CodeVolume_of_Circle2f_Array(ref Volume<Circle2f>[] value);\r\n        void CodeVolume_of_Line2f_Array(ref Volume<Line2f>[] value);\r\n        void CodeVolume_of_Line3f_Array(ref Volume<Line3f>[] value);\r\n        void CodeVolume_of_Plane2f_Array(ref Volume<Plane2f>[] value);\r\n        void CodeVolume_of_Plane3f_Array(ref Volume<Plane3f>[] value);\r\n        void CodeVolume_of_PlaneWithPoint3f_Array(ref Volume<PlaneWithPoint3f>[] value);\r\n        void CodeVolume_of_Quad2f_Array(ref Volume<Quad2f>[] value);\r\n        void CodeVolume_of_Quad3f_Array(ref Volume<Quad3f>[] value);\r\n        void CodeVolume_of_Ray2f_Array(ref Volume<Ray2f>[] value);\r\n        void CodeVolume_of_Ray3f_Array(ref Volume<Ray3f>[] value);\r\n        void CodeVolume_of_Sphere3f_Array(ref Volume<Sphere3f>[] value);\r\n        void CodeVolume_of_Triangle2f_Array(ref Volume<Triangle2f>[] value);\r\n        void CodeVolume_of_Triangle3f_Array(ref Volume<Triangle3f>[] value);\r\n        void CodeTensor_of_Byte_Array(ref Tensor<byte>[] value);\r\n        void CodeTensor_of_SByte_Array(ref Tensor<sbyte>[] value);\r\n        void CodeTensor_of_Short_Array(ref Tensor<short>[] value);\r\n        void CodeTensor_of_UShort_Array(ref Tensor<ushort>[] value);\r\n        void CodeTensor_of_Int_Array(ref Tensor<int>[] value);\r\n        void CodeTensor_of_UInt_Array(ref Tensor<uint>[] value);\r\n        void CodeTensor_of_Long_Array(ref Tensor<long>[] value);\r\n        void CodeTensor_of_ULong_Array(ref Tensor<ulong>[] value);\r\n        void CodeTensor_of_Float_Array(ref Tensor<float>[] value);\r\n        void CodeTensor_of_Double_Array(ref Tensor<double>[] value);\r\n        void CodeTensor_of_Fraction_Array(ref Tensor<Fraction>[] value);\r\n        void CodeTensor_of_V2i_Array(ref Tensor<V2i>[] value);\r\n        void CodeTensor_of_V2l_Array(ref Tensor<V2l>[] value);\r\n        void CodeTensor_of_V2f_Array(ref Tensor<V2f>[] value);\r\n        void CodeTensor_of_V2d_Array(ref Tensor<V2d>[] value);\r\n        void CodeTensor_of_V3i_Array(ref Tensor<V3i>[] value);\r\n        void CodeTensor_of_V3l_Array(ref Tensor<V3l>[] value);\r\n        void CodeTensor_of_V3f_Array(ref Tensor<V3f>[] value);\r\n        void CodeTensor_of_V3d_Array(ref Tensor<V3d>[] value);\r\n        void CodeTensor_of_V4i_Array(ref Tensor<V4i>[] value);\r\n        void CodeTensor_of_V4l_Array(ref Tensor<V4l>[] value);\r\n        void CodeTensor_of_V4f_Array(ref Tensor<V4f>[] value);\r\n        void CodeTensor_of_V4d_Array(ref Tensor<V4d>[] value);\r\n        void CodeTensor_of_M22i_Array(ref Tensor<M22i>[] value);\r\n        void CodeTensor_of_M22l_Array(ref Tensor<M22l>[] value);\r\n        void CodeTensor_of_M22f_Array(ref Tensor<M22f>[] value);\r\n        void CodeTensor_of_M22d_Array(ref Tensor<M22d>[] value);\r\n        void CodeTensor_of_M23i_Array(ref Tensor<M23i>[] value);\r\n        void CodeTensor_of_M23l_Array(ref Tensor<M23l>[] value);\r\n        void CodeTensor_of_M23f_Array(ref Tensor<M23f>[] value);\r\n        void CodeTensor_of_M23d_Array(ref Tensor<M23d>[] value);\r\n        void CodeTensor_of_M33i_Array(ref Tensor<M33i>[] value);\r\n        void CodeTensor_of_M33l_Array(ref Tensor<M33l>[] value);\r\n        void CodeTensor_of_M33f_Array(ref Tensor<M33f>[] value);\r\n        void CodeTensor_of_M33d_Array(ref Tensor<M33d>[] value);\r\n        void CodeTensor_of_M34i_Array(ref Tensor<M34i>[] value);\r\n        void CodeTensor_of_M34l_Array(ref Tensor<M34l>[] value);\r\n        void CodeTensor_of_M34f_Array(ref Tensor<M34f>[] value);\r\n        void CodeTensor_of_M34d_Array(ref Tensor<M34d>[] value);\r\n        void CodeTensor_of_M44i_Array(ref Tensor<M44i>[] value);\r\n        void CodeTensor_of_M44l_Array(ref Tensor<M44l>[] value);\r\n        void CodeTensor_of_M44f_Array(ref Tensor<M44f>[] value);\r\n        void CodeTensor_of_M44d_Array(ref Tensor<M44d>[] value);\r\n        void CodeTensor_of_C3b_Array(ref Tensor<C3b>[] value);\r\n        void CodeTensor_of_C3us_Array(ref Tensor<C3us>[] value);\r\n        void CodeTensor_of_C3ui_Array(ref Tensor<C3ui>[] value);\r\n        void CodeTensor_of_C3f_Array(ref Tensor<C3f>[] value);\r\n        void CodeTensor_of_C3d_Array(ref Tensor<C3d>[] value);\r\n        void CodeTensor_of_C4b_Array(ref Tensor<C4b>[] value);\r\n        void CodeTensor_of_C4us_Array(ref Tensor<C4us>[] value);\r\n        void CodeTensor_of_C4ui_Array(ref Tensor<C4ui>[] value);\r\n        void CodeTensor_of_C4f_Array(ref Tensor<C4f>[] value);\r\n        void CodeTensor_of_C4d_Array(ref Tensor<C4d>[] value);\r\n        void CodeTensor_of_Range1b_Array(ref Tensor<Range1b>[] value);\r\n        void CodeTensor_of_Range1sb_Array(ref Tensor<Range1sb>[] value);\r\n        void CodeTensor_of_Range1s_Array(ref Tensor<Range1s>[] value);\r\n        void CodeTensor_of_Range1us_Array(ref Tensor<Range1us>[] value);\r\n        void CodeTensor_of_Range1i_Array(ref Tensor<Range1i>[] value);\r\n        void CodeTensor_of_Range1ui_Array(ref Tensor<Range1ui>[] value);\r\n        void CodeTensor_of_Range1l_Array(ref Tensor<Range1l>[] value);\r\n        void CodeTensor_of_Range1ul_Array(ref Tensor<Range1ul>[] value);\r\n        void CodeTensor_of_Range1f_Array(ref Tensor<Range1f>[] value);\r\n        void CodeTensor_of_Range1d_Array(ref Tensor<Range1d>[] value);\r\n        void CodeTensor_of_Box2i_Array(ref Tensor<Box2i>[] value);\r\n        void CodeTensor_of_Box2l_Array(ref Tensor<Box2l>[] value);\r\n        void CodeTensor_of_Box2f_Array(ref Tensor<Box2f>[] value);\r\n        void CodeTensor_of_Box2d_Array(ref Tensor<Box2d>[] value);\r\n        void CodeTensor_of_Box3i_Array(ref Tensor<Box3i>[] value);\r\n        void CodeTensor_of_Box3l_Array(ref Tensor<Box3l>[] value);\r\n        void CodeTensor_of_Box3f_Array(ref Tensor<Box3f>[] value);\r\n        void CodeTensor_of_Box3d_Array(ref Tensor<Box3d>[] value);\r\n        void CodeTensor_of_Euclidean3f_Array(ref Tensor<Euclidean3f>[] value);\r\n        void CodeTensor_of_Euclidean3d_Array(ref Tensor<Euclidean3d>[] value);\r\n        void CodeTensor_of_Rot2f_Array(ref Tensor<Rot2f>[] value);\r\n        void CodeTensor_of_Rot2d_Array(ref Tensor<Rot2d>[] value);\r\n        void CodeTensor_of_Rot3f_Array(ref Tensor<Rot3f>[] value);\r\n        void CodeTensor_of_Rot3d_Array(ref Tensor<Rot3d>[] value);\r\n        void CodeTensor_of_Scale3f_Array(ref Tensor<Scale3f>[] value);\r\n        void CodeTensor_of_Scale3d_Array(ref Tensor<Scale3d>[] value);\r\n        void CodeTensor_of_Shift3f_Array(ref Tensor<Shift3f>[] value);\r\n        void CodeTensor_of_Shift3d_Array(ref Tensor<Shift3d>[] value);\r\n        void CodeTensor_of_Trafo2f_Array(ref Tensor<Trafo2f>[] value);\r\n        void CodeTensor_of_Trafo2d_Array(ref Tensor<Trafo2d>[] value);\r\n        void CodeTensor_of_Trafo3f_Array(ref Tensor<Trafo3f>[] value);\r\n        void CodeTensor_of_Trafo3d_Array(ref Tensor<Trafo3d>[] value);\r\n        void CodeTensor_of_Bool_Array(ref Tensor<bool>[] value);\r\n        void CodeTensor_of_Char_Array(ref Tensor<char>[] value);\r\n        void CodeTensor_of_String_Array(ref Tensor<string>[] value);\r\n        void CodeTensor_of_Type_Array(ref Tensor<Type>[] value);\r\n        void CodeTensor_of_Guid_Array(ref Tensor<Guid>[] value);\r\n        void CodeTensor_of_Symbol_Array(ref Tensor<Symbol>[] value);\r\n        void CodeTensor_of_Circle2d_Array(ref Tensor<Circle2d>[] value);\r\n        void CodeTensor_of_Line2d_Array(ref Tensor<Line2d>[] value);\r\n        void CodeTensor_of_Line3d_Array(ref Tensor<Line3d>[] value);\r\n        void CodeTensor_of_Plane2d_Array(ref Tensor<Plane2d>[] value);\r\n        void CodeTensor_of_Plane3d_Array(ref Tensor<Plane3d>[] value);\r\n        void CodeTensor_of_PlaneWithPoint3d_Array(ref Tensor<PlaneWithPoint3d>[] value);\r\n        void CodeTensor_of_Quad2d_Array(ref Tensor<Quad2d>[] value);\r\n        void CodeTensor_of_Quad3d_Array(ref Tensor<Quad3d>[] value);\r\n        void CodeTensor_of_Ray2d_Array(ref Tensor<Ray2d>[] value);\r\n        void CodeTensor_of_Ray3d_Array(ref Tensor<Ray3d>[] value);\r\n        void CodeTensor_of_Sphere3d_Array(ref Tensor<Sphere3d>[] value);\r\n        void CodeTensor_of_Triangle2d_Array(ref Tensor<Triangle2d>[] value);\r\n        void CodeTensor_of_Triangle3d_Array(ref Tensor<Triangle3d>[] value);\r\n        void CodeTensor_of_Circle2f_Array(ref Tensor<Circle2f>[] value);\r\n        void CodeTensor_of_Line2f_Array(ref Tensor<Line2f>[] value);\r\n        void CodeTensor_of_Line3f_Array(ref Tensor<Line3f>[] value);\r\n        void CodeTensor_of_Plane2f_Array(ref Tensor<Plane2f>[] value);\r\n        void CodeTensor_of_Plane3f_Array(ref Tensor<Plane3f>[] value);\r\n        void CodeTensor_of_PlaneWithPoint3f_Array(ref Tensor<PlaneWithPoint3f>[] value);\r\n        void CodeTensor_of_Quad2f_Array(ref Tensor<Quad2f>[] value);\r\n        void CodeTensor_of_Quad3f_Array(ref Tensor<Quad3f>[] value);\r\n        void CodeTensor_of_Ray2f_Array(ref Tensor<Ray2f>[] value);\r\n        void CodeTensor_of_Ray3f_Array(ref Tensor<Ray3f>[] value);\r\n        void CodeTensor_of_Sphere3f_Array(ref Tensor<Sphere3f>[] value);\r\n        void CodeTensor_of_Triangle2f_Array(ref Tensor<Triangle2f>[] value);\r\n        void CodeTensor_of_Triangle3f_Array(ref Tensor<Triangle3f>[] value);\r\n\r\n        #endregion\r\n\r\n        #region Multi-Dimensional Arrays\r\n\r\n        void CodeByteArray2d(ref byte[,] value);\r\n        void CodeByteArray3d(ref byte[, ,] value);\r\n        void CodeSByteArray2d(ref sbyte[,] value);\r\n        void CodeSByteArray3d(ref sbyte[, ,] value);\r\n        void CodeShortArray2d(ref short[,] value);\r\n        void CodeShortArray3d(ref short[, ,] value);\r\n        void CodeUShortArray2d(ref ushort[,] value);\r\n        void CodeUShortArray3d(ref ushort[, ,] value);\r\n        void CodeIntArray2d(ref int[,] value);\r\n        void CodeIntArray3d(ref int[, ,] value);\r\n        void CodeUIntArray2d(ref uint[,] value);\r\n        void CodeUIntArray3d(ref uint[, ,] value);\r\n        void CodeLongArray2d(ref long[,] value);\r\n        void CodeLongArray3d(ref long[, ,] value);\r\n        void CodeULongArray2d(ref ulong[,] value);\r\n        void CodeULongArray3d(ref ulong[, ,] value);\r\n        void CodeFloatArray2d(ref float[,] value);\r\n        void CodeFloatArray3d(ref float[, ,] value);\r\n        void CodeDoubleArray2d(ref double[,] value);\r\n        void CodeDoubleArray3d(ref double[, ,] value);\r\n        void CodeFractionArray2d(ref Fraction[,] value);\r\n        void CodeFractionArray3d(ref Fraction[, ,] value);\r\n        void CodeV2iArray2d(ref V2i[,] value);\r\n        void CodeV2iArray3d(ref V2i[, ,] value);\r\n        void CodeV2lArray2d(ref V2l[,] value);\r\n        void CodeV2lArray3d(ref V2l[, ,] value);\r\n        void CodeV2fArray2d(ref V2f[,] value);\r\n        void CodeV2fArray3d(ref V2f[, ,] value);\r\n        void CodeV2dArray2d(ref V2d[,] value);\r\n        void CodeV2dArray3d(ref V2d[, ,] value);\r\n        void CodeV3iArray2d(ref V3i[,] value);\r\n        void CodeV3iArray3d(ref V3i[, ,] value);\r\n        void CodeV3lArray2d(ref V3l[,] value);\r\n        void CodeV3lArray3d(ref V3l[, ,] value);\r\n        void CodeV3fArray2d(ref V3f[,] value);\r\n        void CodeV3fArray3d(ref V3f[, ,] value);\r\n        void CodeV3dArray2d(ref V3d[,] value);\r\n        void CodeV3dArray3d(ref V3d[, ,] value);\r\n        void CodeV4iArray2d(ref V4i[,] value);\r\n        void CodeV4iArray3d(ref V4i[, ,] value);\r\n        void CodeV4lArray2d(ref V4l[,] value);\r\n        void CodeV4lArray3d(ref V4l[, ,] value);\r\n        void CodeV4fArray2d(ref V4f[,] value);\r\n        void CodeV4fArray3d(ref V4f[, ,] value);\r\n        void CodeV4dArray2d(ref V4d[,] value);\r\n        void CodeV4dArray3d(ref V4d[, ,] value);\r\n        void CodeM22iArray2d(ref M22i[,] value);\r\n        void CodeM22iArray3d(ref M22i[, ,] value);\r\n        void CodeM22lArray2d(ref M22l[,] value);\r\n        void CodeM22lArray3d(ref M22l[, ,] value);\r\n        void CodeM22fArray2d(ref M22f[,] value);\r\n        void CodeM22fArray3d(ref M22f[, ,] value);\r\n        void CodeM22dArray2d(ref M22d[,] value);\r\n        void CodeM22dArray3d(ref M22d[, ,] value);\r\n        void CodeM23iArray2d(ref M23i[,] value);\r\n        void CodeM23iArray3d(ref M23i[, ,] value);\r\n        void CodeM23lArray2d(ref M23l[,] value);\r\n        void CodeM23lArray3d(ref M23l[, ,] value);\r\n        void CodeM23fArray2d(ref M23f[,] value);\r\n        void CodeM23fArray3d(ref M23f[, ,] value);\r\n        void CodeM23dArray2d(ref M23d[,] value);\r\n        void CodeM23dArray3d(ref M23d[, ,] value);\r\n        void CodeM33iArray2d(ref M33i[,] value);\r\n        void CodeM33iArray3d(ref M33i[, ,] value);\r\n        void CodeM33lArray2d(ref M33l[,] value);\r\n        void CodeM33lArray3d(ref M33l[, ,] value);\r\n        void CodeM33fArray2d(ref M33f[,] value);\r\n        void CodeM33fArray3d(ref M33f[, ,] value);\r\n        void CodeM33dArray2d(ref M33d[,] value);\r\n        void CodeM33dArray3d(ref M33d[, ,] value);\r\n        void CodeM34iArray2d(ref M34i[,] value);\r\n        void CodeM34iArray3d(ref M34i[, ,] value);\r\n        void CodeM34lArray2d(ref M34l[,] value);\r\n        void CodeM34lArray3d(ref M34l[, ,] value);\r\n        void CodeM34fArray2d(ref M34f[,] value);\r\n        void CodeM34fArray3d(ref M34f[, ,] value);\r\n        void CodeM34dArray2d(ref M34d[,] value);\r\n        void CodeM34dArray3d(ref M34d[, ,] value);\r\n        void CodeM44iArray2d(ref M44i[,] value);\r\n        void CodeM44iArray3d(ref M44i[, ,] value);\r\n        void CodeM44lArray2d(ref M44l[,] value);\r\n        void CodeM44lArray3d(ref M44l[, ,] value);\r\n        void CodeM44fArray2d(ref M44f[,] value);\r\n        void CodeM44fArray3d(ref M44f[, ,] value);\r\n        void CodeM44dArray2d(ref M44d[,] value);\r\n        void CodeM44dArray3d(ref M44d[, ,] value);\r\n        void CodeC3bArray2d(ref C3b[,] value);\r\n        void CodeC3bArray3d(ref C3b[, ,] value);\r\n        void CodeC3usArray2d(ref C3us[,] value);\r\n        void CodeC3usArray3d(ref C3us[, ,] value);\r\n        void CodeC3uiArray2d(ref C3ui[,] value);\r\n        void CodeC3uiArray3d(ref C3ui[, ,] value);\r\n        void CodeC3fArray2d(ref C3f[,] value);\r\n        void CodeC3fArray3d(ref C3f[, ,] value);\r\n        void CodeC3dArray2d(ref C3d[,] value);\r\n        void CodeC3dArray3d(ref C3d[, ,] value);\r\n        void CodeC4bArray2d(ref C4b[,] value);\r\n        void CodeC4bArray3d(ref C4b[, ,] value);\r\n        void CodeC4usArray2d(ref C4us[,] value);\r\n        void CodeC4usArray3d(ref C4us[, ,] value);\r\n        void CodeC4uiArray2d(ref C4ui[,] value);\r\n        void CodeC4uiArray3d(ref C4ui[, ,] value);\r\n        void CodeC4fArray2d(ref C4f[,] value);\r\n        void CodeC4fArray3d(ref C4f[, ,] value);\r\n        void CodeC4dArray2d(ref C4d[,] value);\r\n        void CodeC4dArray3d(ref C4d[, ,] value);\r\n        void CodeRange1bArray2d(ref Range1b[,] value);\r\n        void CodeRange1bArray3d(ref Range1b[, ,] value);\r\n        void CodeRange1sbArray2d(ref Range1sb[,] value);\r\n        void CodeRange1sbArray3d(ref Range1sb[, ,] value);\r\n        void CodeRange1sArray2d(ref Range1s[,] value);\r\n        void CodeRange1sArray3d(ref Range1s[, ,] value);\r\n        void CodeRange1usArray2d(ref Range1us[,] value);\r\n        void CodeRange1usArray3d(ref Range1us[, ,] value);\r\n        void CodeRange1iArray2d(ref Range1i[,] value);\r\n        void CodeRange1iArray3d(ref Range1i[, ,] value);\r\n        void CodeRange1uiArray2d(ref Range1ui[,] value);\r\n        void CodeRange1uiArray3d(ref Range1ui[, ,] value);\r\n        void CodeRange1lArray2d(ref Range1l[,] value);\r\n        void CodeRange1lArray3d(ref Range1l[, ,] value);\r\n        void CodeRange1ulArray2d(ref Range1ul[,] value);\r\n        void CodeRange1ulArray3d(ref Range1ul[, ,] value);\r\n        void CodeRange1fArray2d(ref Range1f[,] value);\r\n        void CodeRange1fArray3d(ref Range1f[, ,] value);\r\n        void CodeRange1dArray2d(ref Range1d[,] value);\r\n        void CodeRange1dArray3d(ref Range1d[, ,] value);\r\n        void CodeBox2iArray2d(ref Box2i[,] value);\r\n        void CodeBox2iArray3d(ref Box2i[, ,] value);\r\n        void CodeBox2lArray2d(ref Box2l[,] value);\r\n        void CodeBox2lArray3d(ref Box2l[, ,] value);\r\n        void CodeBox2fArray2d(ref Box2f[,] value);\r\n        void CodeBox2fArray3d(ref Box2f[, ,] value);\r\n        void CodeBox2dArray2d(ref Box2d[,] value);\r\n        void CodeBox2dArray3d(ref Box2d[, ,] value);\r\n        void CodeBox3iArray2d(ref Box3i[,] value);\r\n        void CodeBox3iArray3d(ref Box3i[, ,] value);\r\n        void CodeBox3lArray2d(ref Box3l[,] value);\r\n        void CodeBox3lArray3d(ref Box3l[, ,] value);\r\n        void CodeBox3fArray2d(ref Box3f[,] value);\r\n        void CodeBox3fArray3d(ref Box3f[, ,] value);\r\n        void CodeBox3dArray2d(ref Box3d[,] value);\r\n        void CodeBox3dArray3d(ref Box3d[, ,] value);\r\n        void CodeEuclidean3fArray2d(ref Euclidean3f[,] value);\r\n        void CodeEuclidean3fArray3d(ref Euclidean3f[, ,] value);\r\n        void CodeEuclidean3dArray2d(ref Euclidean3d[,] value);\r\n        void CodeEuclidean3dArray3d(ref Euclidean3d[, ,] value);\r\n        void CodeRot2fArray2d(ref Rot2f[,] value);\r\n        void CodeRot2fArray3d(ref Rot2f[, ,] value);\r\n        void CodeRot2dArray2d(ref Rot2d[,] value);\r\n        void CodeRot2dArray3d(ref Rot2d[, ,] value);\r\n        void CodeRot3fArray2d(ref Rot3f[,] value);\r\n        void CodeRot3fArray3d(ref Rot3f[, ,] value);\r\n        void CodeRot3dArray2d(ref Rot3d[,] value);\r\n        void CodeRot3dArray3d(ref Rot3d[, ,] value);\r\n        void CodeScale3fArray2d(ref Scale3f[,] value);\r\n        void CodeScale3fArray3d(ref Scale3f[, ,] value);\r\n        void CodeScale3dArray2d(ref Scale3d[,] value);\r\n        void CodeScale3dArray3d(ref Scale3d[, ,] value);\r\n        void CodeShift3fArray2d(ref Shift3f[,] value);\r\n        void CodeShift3fArray3d(ref Shift3f[, ,] value);\r\n        void CodeShift3dArray2d(ref Shift3d[,] value);\r\n        void CodeShift3dArray3d(ref Shift3d[, ,] value);\r\n        void CodeTrafo2fArray2d(ref Trafo2f[,] value);\r\n        void CodeTrafo2fArray3d(ref Trafo2f[, ,] value);\r\n        void CodeTrafo2dArray2d(ref Trafo2d[,] value);\r\n        void CodeTrafo2dArray3d(ref Trafo2d[, ,] value);\r\n        void CodeTrafo3fArray2d(ref Trafo3f[,] value);\r\n        void CodeTrafo3fArray3d(ref Trafo3f[, ,] value);\r\n        void CodeTrafo3dArray2d(ref Trafo3d[,] value);\r\n        void CodeTrafo3dArray3d(ref Trafo3d[, ,] value);\r\n\r\n        #endregion\r\n\r\n        #region Jagged Multi-Dimensional Arrays\r\n\r\n        void CodeByteArrayArray(ref byte[][] value);\r\n        void CodeByteArrayArrayArray(ref byte[][][] value);\r\n        void CodeSByteArrayArray(ref sbyte[][] value);\r\n        void CodeSByteArrayArrayArray(ref sbyte[][][] value);\r\n        void CodeShortArrayArray(ref short[][] value);\r\n        void CodeShortArrayArrayArray(ref short[][][] value);\r\n        void CodeUShortArrayArray(ref ushort[][] value);\r\n        void CodeUShortArrayArrayArray(ref ushort[][][] value);\r\n        void CodeIntArrayArray(ref int[][] value);\r\n        void CodeIntArrayArrayArray(ref int[][][] value);\r\n        void CodeUIntArrayArray(ref uint[][] value);\r\n        void CodeUIntArrayArrayArray(ref uint[][][] value);\r\n        void CodeLongArrayArray(ref long[][] value);\r\n        void CodeLongArrayArrayArray(ref long[][][] value);\r\n        void CodeULongArrayArray(ref ulong[][] value);\r\n        void CodeULongArrayArrayArray(ref ulong[][][] value);\r\n        void CodeFloatArrayArray(ref float[][] value);\r\n        void CodeFloatArrayArrayArray(ref float[][][] value);\r\n        void CodeDoubleArrayArray(ref double[][] value);\r\n        void CodeDoubleArrayArrayArray(ref double[][][] value);\r\n        void CodeFractionArrayArray(ref Fraction[][] value);\r\n        void CodeFractionArrayArrayArray(ref Fraction[][][] value);\r\n        void CodeV2iArrayArray(ref V2i[][] value);\r\n        void CodeV2iArrayArrayArray(ref V2i[][][] value);\r\n        void CodeV2lArrayArray(ref V2l[][] value);\r\n        void CodeV2lArrayArrayArray(ref V2l[][][] value);\r\n        void CodeV2fArrayArray(ref V2f[][] value);\r\n        void CodeV2fArrayArrayArray(ref V2f[][][] value);\r\n        void CodeV2dArrayArray(ref V2d[][] value);\r\n        void CodeV2dArrayArrayArray(ref V2d[][][] value);\r\n        void CodeV3iArrayArray(ref V3i[][] value);\r\n        void CodeV3iArrayArrayArray(ref V3i[][][] value);\r\n        void CodeV3lArrayArray(ref V3l[][] value);\r\n        void CodeV3lArrayArrayArray(ref V3l[][][] value);\r\n        void CodeV3fArrayArray(ref V3f[][] value);\r\n        void CodeV3fArrayArrayArray(ref V3f[][][] value);\r\n        void CodeV3dArrayArray(ref V3d[][] value);\r\n        void CodeV3dArrayArrayArray(ref V3d[][][] value);\r\n        void CodeV4iArrayArray(ref V4i[][] value);\r\n        void CodeV4iArrayArrayArray(ref V4i[][][] value);\r\n        void CodeV4lArrayArray(ref V4l[][] value);\r\n        void CodeV4lArrayArrayArray(ref V4l[][][] value);\r\n        void CodeV4fArrayArray(ref V4f[][] value);\r\n        void CodeV4fArrayArrayArray(ref V4f[][][] value);\r\n        void CodeV4dArrayArray(ref V4d[][] value);\r\n        void CodeV4dArrayArrayArray(ref V4d[][][] value);\r\n        void CodeM22iArrayArray(ref M22i[][] value);\r\n        void CodeM22iArrayArrayArray(ref M22i[][][] value);\r\n        void CodeM22lArrayArray(ref M22l[][] value);\r\n        void CodeM22lArrayArrayArray(ref M22l[][][] value);\r\n        void CodeM22fArrayArray(ref M22f[][] value);\r\n        void CodeM22fArrayArrayArray(ref M22f[][][] value);\r\n        void CodeM22dArrayArray(ref M22d[][] value);\r\n        void CodeM22dArrayArrayArray(ref M22d[][][] value);\r\n        void CodeM23iArrayArray(ref M23i[][] value);\r\n        void CodeM23iArrayArrayArray(ref M23i[][][] value);\r\n        void CodeM23lArrayArray(ref M23l[][] value);\r\n        void CodeM23lArrayArrayArray(ref M23l[][][] value);\r\n        void CodeM23fArrayArray(ref M23f[][] value);\r\n        void CodeM23fArrayArrayArray(ref M23f[][][] value);\r\n        void CodeM23dArrayArray(ref M23d[][] value);\r\n        void CodeM23dArrayArrayArray(ref M23d[][][] value);\r\n        void CodeM33iArrayArray(ref M33i[][] value);\r\n        void CodeM33iArrayArrayArray(ref M33i[][][] value);\r\n        void CodeM33lArrayArray(ref M33l[][] value);\r\n        void CodeM33lArrayArrayArray(ref M33l[][][] value);\r\n        void CodeM33fArrayArray(ref M33f[][] value);\r\n        void CodeM33fArrayArrayArray(ref M33f[][][] value);\r\n        void CodeM33dArrayArray(ref M33d[][] value);\r\n        void CodeM33dArrayArrayArray(ref M33d[][][] value);\r\n        void CodeM34iArrayArray(ref M34i[][] value);\r\n        void CodeM34iArrayArrayArray(ref M34i[][][] value);\r\n        void CodeM34lArrayArray(ref M34l[][] value);\r\n        void CodeM34lArrayArrayArray(ref M34l[][][] value);\r\n        void CodeM34fArrayArray(ref M34f[][] value);\r\n        void CodeM34fArrayArrayArray(ref M34f[][][] value);\r\n        void CodeM34dArrayArray(ref M34d[][] value);\r\n        void CodeM34dArrayArrayArray(ref M34d[][][] value);\r\n        void CodeM44iArrayArray(ref M44i[][] value);\r\n        void CodeM44iArrayArrayArray(ref M44i[][][] value);\r\n        void CodeM44lArrayArray(ref M44l[][] value);\r\n        void CodeM44lArrayArrayArray(ref M44l[][][] value);\r\n        void CodeM44fArrayArray(ref M44f[][] value);\r\n        void CodeM44fArrayArrayArray(ref M44f[][][] value);\r\n        void CodeM44dArrayArray(ref M44d[][] value);\r\n        void CodeM44dArrayArrayArray(ref M44d[][][] value);\r\n        void CodeC3bArrayArray(ref C3b[][] value);\r\n        void CodeC3bArrayArrayArray(ref C3b[][][] value);\r\n        void CodeC3usArrayArray(ref C3us[][] value);\r\n        void CodeC3usArrayArrayArray(ref C3us[][][] value);\r\n        void CodeC3uiArrayArray(ref C3ui[][] value);\r\n        void CodeC3uiArrayArrayArray(ref C3ui[][][] value);\r\n        void CodeC3fArrayArray(ref C3f[][] value);\r\n        void CodeC3fArrayArrayArray(ref C3f[][][] value);\r\n        void CodeC3dArrayArray(ref C3d[][] value);\r\n        void CodeC3dArrayArrayArray(ref C3d[][][] value);\r\n        void CodeC4bArrayArray(ref C4b[][] value);\r\n        void CodeC4bArrayArrayArray(ref C4b[][][] value);\r\n        void CodeC4usArrayArray(ref C4us[][] value);\r\n        void CodeC4usArrayArrayArray(ref C4us[][][] value);\r\n        void CodeC4uiArrayArray(ref C4ui[][] value);\r\n        void CodeC4uiArrayArrayArray(ref C4ui[][][] value);\r\n        void CodeC4fArrayArray(ref C4f[][] value);\r\n        void CodeC4fArrayArrayArray(ref C4f[][][] value);\r\n        void CodeC4dArrayArray(ref C4d[][] value);\r\n        void CodeC4dArrayArrayArray(ref C4d[][][] value);\r\n        void CodeRange1bArrayArray(ref Range1b[][] value);\r\n        void CodeRange1bArrayArrayArray(ref Range1b[][][] value);\r\n        void CodeRange1sbArrayArray(ref Range1sb[][] value);\r\n        void CodeRange1sbArrayArrayArray(ref Range1sb[][][] value);\r\n        void CodeRange1sArrayArray(ref Range1s[][] value);\r\n        void CodeRange1sArrayArrayArray(ref Range1s[][][] value);\r\n        void CodeRange1usArrayArray(ref Range1us[][] value);\r\n        void CodeRange1usArrayArrayArray(ref Range1us[][][] value);\r\n        void CodeRange1iArrayArray(ref Range1i[][] value);\r\n        void CodeRange1iArrayArrayArray(ref Range1i[][][] value);\r\n        void CodeRange1uiArrayArray(ref Range1ui[][] value);\r\n        void CodeRange1uiArrayArrayArray(ref Range1ui[][][] value);\r\n        void CodeRange1lArrayArray(ref Range1l[][] value);\r\n        void CodeRange1lArrayArrayArray(ref Range1l[][][] value);\r\n        void CodeRange1ulArrayArray(ref Range1ul[][] value);\r\n        void CodeRange1ulArrayArrayArray(ref Range1ul[][][] value);\r\n        void CodeRange1fArrayArray(ref Range1f[][] value);\r\n        void CodeRange1fArrayArrayArray(ref Range1f[][][] value);\r\n        void CodeRange1dArrayArray(ref Range1d[][] value);\r\n        void CodeRange1dArrayArrayArray(ref Range1d[][][] value);\r\n        void CodeBox2iArrayArray(ref Box2i[][] value);\r\n        void CodeBox2iArrayArrayArray(ref Box2i[][][] value);\r\n        void CodeBox2lArrayArray(ref Box2l[][] value);\r\n        void CodeBox2lArrayArrayArray(ref Box2l[][][] value);\r\n        void CodeBox2fArrayArray(ref Box2f[][] value);\r\n        void CodeBox2fArrayArrayArray(ref Box2f[][][] value);\r\n        void CodeBox2dArrayArray(ref Box2d[][] value);\r\n        void CodeBox2dArrayArrayArray(ref Box2d[][][] value);\r\n        void CodeBox3iArrayArray(ref Box3i[][] value);\r\n        void CodeBox3iArrayArrayArray(ref Box3i[][][] value);\r\n        void CodeBox3lArrayArray(ref Box3l[][] value);\r\n        void CodeBox3lArrayArrayArray(ref Box3l[][][] value);\r\n        void CodeBox3fArrayArray(ref Box3f[][] value);\r\n        void CodeBox3fArrayArrayArray(ref Box3f[][][] value);\r\n        void CodeBox3dArrayArray(ref Box3d[][] value);\r\n        void CodeBox3dArrayArrayArray(ref Box3d[][][] value);\r\n        void CodeEuclidean3fArrayArray(ref Euclidean3f[][] value);\r\n        void CodeEuclidean3fArrayArrayArray(ref Euclidean3f[][][] value);\r\n        void CodeEuclidean3dArrayArray(ref Euclidean3d[][] value);\r\n        void CodeEuclidean3dArrayArrayArray(ref Euclidean3d[][][] value);\r\n        void CodeRot2fArrayArray(ref Rot2f[][] value);\r\n        void CodeRot2fArrayArrayArray(ref Rot2f[][][] value);\r\n        void CodeRot2dArrayArray(ref Rot2d[][] value);\r\n        void CodeRot2dArrayArrayArray(ref Rot2d[][][] value);\r\n        void CodeRot3fArrayArray(ref Rot3f[][] value);\r\n        void CodeRot3fArrayArrayArray(ref Rot3f[][][] value);\r\n        void CodeRot3dArrayArray(ref Rot3d[][] value);\r\n        void CodeRot3dArrayArrayArray(ref Rot3d[][][] value);\r\n        void CodeScale3fArrayArray(ref Scale3f[][] value);\r\n        void CodeScale3fArrayArrayArray(ref Scale3f[][][] value);\r\n        void CodeScale3dArrayArray(ref Scale3d[][] value);\r\n        void CodeScale3dArrayArrayArray(ref Scale3d[][][] value);\r\n        void CodeShift3fArrayArray(ref Shift3f[][] value);\r\n        void CodeShift3fArrayArrayArray(ref Shift3f[][][] value);\r\n        void CodeShift3dArrayArray(ref Shift3d[][] value);\r\n        void CodeShift3dArrayArrayArray(ref Shift3d[][][] value);\r\n        void CodeTrafo2fArrayArray(ref Trafo2f[][] value);\r\n        void CodeTrafo2fArrayArrayArray(ref Trafo2f[][][] value);\r\n        void CodeTrafo2dArrayArray(ref Trafo2d[][] value);\r\n        void CodeTrafo2dArrayArrayArray(ref Trafo2d[][][] value);\r\n        void CodeTrafo3fArrayArray(ref Trafo3f[][] value);\r\n        void CodeTrafo3fArrayArrayArray(ref Trafo3f[][][] value);\r\n        void CodeTrafo3dArrayArray(ref Trafo3d[][] value);\r\n        void CodeTrafo3dArrayArrayArray(ref Trafo3d[][][] value);\r\n\r\n        #endregion\r\n\r\n        #region Lists\r\n\r\n        void CodeList_of_Bool_(ref List<bool> value);\r\n        void CodeList_of_Char_(ref List<char> value);\r\n        void CodeList_of_String_(ref List<string> value);\r\n        void CodeList_of_Type_(ref List<Type> value);\r\n        void CodeList_of_Guid_(ref List<Guid> value);\r\n        void CodeList_of_Symbol_(ref List<Symbol> value);\r\n        void CodeList_of_Byte_(ref List<byte> value);\r\n        void CodeList_of_SByte_(ref List<sbyte> value);\r\n        void CodeList_of_Short_(ref List<short> value);\r\n        void CodeList_of_UShort_(ref List<ushort> value);\r\n        void CodeList_of_Int_(ref List<int> value);\r\n        void CodeList_of_UInt_(ref List<uint> value);\r\n        void CodeList_of_Long_(ref List<long> value);\r\n        void CodeList_of_ULong_(ref List<ulong> value);\r\n        void CodeList_of_Float_(ref List<float> value);\r\n        void CodeList_of_Double_(ref List<double> value);\r\n        void CodeList_of_Fraction_(ref List<Fraction> value);\r\n        void CodeList_of_V2i_(ref List<V2i> value);\r\n        void CodeList_of_V2l_(ref List<V2l> value);\r\n        void CodeList_of_V2f_(ref List<V2f> value);\r\n        void CodeList_of_V2d_(ref List<V2d> value);\r\n        void CodeList_of_V3i_(ref List<V3i> value);\r\n        void CodeList_of_V3l_(ref List<V3l> value);\r\n        void CodeList_of_V3f_(ref List<V3f> value);\r\n        void CodeList_of_V3d_(ref List<V3d> value);\r\n        void CodeList_of_V4i_(ref List<V4i> value);\r\n        void CodeList_of_V4l_(ref List<V4l> value);\r\n        void CodeList_of_V4f_(ref List<V4f> value);\r\n        void CodeList_of_V4d_(ref List<V4d> value);\r\n        void CodeList_of_M22i_(ref List<M22i> value);\r\n        void CodeList_of_M22l_(ref List<M22l> value);\r\n        void CodeList_of_M22f_(ref List<M22f> value);\r\n        void CodeList_of_M22d_(ref List<M22d> value);\r\n        void CodeList_of_M23i_(ref List<M23i> value);\r\n        void CodeList_of_M23l_(ref List<M23l> value);\r\n        void CodeList_of_M23f_(ref List<M23f> value);\r\n        void CodeList_of_M23d_(ref List<M23d> value);\r\n        void CodeList_of_M33i_(ref List<M33i> value);\r\n        void CodeList_of_M33l_(ref List<M33l> value);\r\n        void CodeList_of_M33f_(ref List<M33f> value);\r\n        void CodeList_of_M33d_(ref List<M33d> value);\r\n        void CodeList_of_M34i_(ref List<M34i> value);\r\n        void CodeList_of_M34l_(ref List<M34l> value);\r\n        void CodeList_of_M34f_(ref List<M34f> value);\r\n        void CodeList_of_M34d_(ref List<M34d> value);\r\n        void CodeList_of_M44i_(ref List<M44i> value);\r\n        void CodeList_of_M44l_(ref List<M44l> value);\r\n        void CodeList_of_M44f_(ref List<M44f> value);\r\n        void CodeList_of_M44d_(ref List<M44d> value);\r\n        void CodeList_of_C3b_(ref List<C3b> value);\r\n        void CodeList_of_C3us_(ref List<C3us> value);\r\n        void CodeList_of_C3ui_(ref List<C3ui> value);\r\n        void CodeList_of_C3f_(ref List<C3f> value);\r\n        void CodeList_of_C3d_(ref List<C3d> value);\r\n        void CodeList_of_C4b_(ref List<C4b> value);\r\n        void CodeList_of_C4us_(ref List<C4us> value);\r\n        void CodeList_of_C4ui_(ref List<C4ui> value);\r\n        void CodeList_of_C4f_(ref List<C4f> value);\r\n        void CodeList_of_C4d_(ref List<C4d> value);\r\n        void CodeList_of_Range1b_(ref List<Range1b> value);\r\n        void CodeList_of_Range1sb_(ref List<Range1sb> value);\r\n        void CodeList_of_Range1s_(ref List<Range1s> value);\r\n        void CodeList_of_Range1us_(ref List<Range1us> value);\r\n        void CodeList_of_Range1i_(ref List<Range1i> value);\r\n        void CodeList_of_Range1ui_(ref List<Range1ui> value);\r\n        void CodeList_of_Range1l_(ref List<Range1l> value);\r\n        void CodeList_of_Range1ul_(ref List<Range1ul> value);\r\n        void CodeList_of_Range1f_(ref List<Range1f> value);\r\n        void CodeList_of_Range1d_(ref List<Range1d> value);\r\n        void CodeList_of_Box2i_(ref List<Box2i> value);\r\n        void CodeList_of_Box2l_(ref List<Box2l> value);\r\n        void CodeList_of_Box2f_(ref List<Box2f> value);\r\n        void CodeList_of_Box2d_(ref List<Box2d> value);\r\n        void CodeList_of_Box3i_(ref List<Box3i> value);\r\n        void CodeList_of_Box3l_(ref List<Box3l> value);\r\n        void CodeList_of_Box3f_(ref List<Box3f> value);\r\n        void CodeList_of_Box3d_(ref List<Box3d> value);\r\n        void CodeList_of_Euclidean3f_(ref List<Euclidean3f> value);\r\n        void CodeList_of_Euclidean3d_(ref List<Euclidean3d> value);\r\n        void CodeList_of_Rot2f_(ref List<Rot2f> value);\r\n        void CodeList_of_Rot2d_(ref List<Rot2d> value);\r\n        void CodeList_of_Rot3f_(ref List<Rot3f> value);\r\n        void CodeList_of_Rot3d_(ref List<Rot3d> value);\r\n        void CodeList_of_Scale3f_(ref List<Scale3f> value);\r\n        void CodeList_of_Scale3d_(ref List<Scale3d> value);\r\n        void CodeList_of_Shift3f_(ref List<Shift3f> value);\r\n        void CodeList_of_Shift3d_(ref List<Shift3d> value);\r\n        void CodeList_of_Trafo2f_(ref List<Trafo2f> value);\r\n        void CodeList_of_Trafo2d_(ref List<Trafo2d> value);\r\n        void CodeList_of_Trafo3f_(ref List<Trafo3f> value);\r\n        void CodeList_of_Trafo3d_(ref List<Trafo3d> value);\r\n        void CodeList_of_Circle2d_(ref List<Circle2d> value);\r\n        void CodeList_of_Line2d_(ref List<Line2d> value);\r\n        void CodeList_of_Line3d_(ref List<Line3d> value);\r\n        void CodeList_of_Plane2d_(ref List<Plane2d> value);\r\n        void CodeList_of_Plane3d_(ref List<Plane3d> value);\r\n        void CodeList_of_PlaneWithPoint3d_(ref List<PlaneWithPoint3d> value);\r\n        void CodeList_of_Quad2d_(ref List<Quad2d> value);\r\n        void CodeList_of_Quad3d_(ref List<Quad3d> value);\r\n        void CodeList_of_Ray2d_(ref List<Ray2d> value);\r\n        void CodeList_of_Ray3d_(ref List<Ray3d> value);\r\n        void CodeList_of_Sphere3d_(ref List<Sphere3d> value);\r\n        void CodeList_of_Triangle2d_(ref List<Triangle2d> value);\r\n        void CodeList_of_Triangle3d_(ref List<Triangle3d> value);\r\n        void CodeList_of_Circle2f_(ref List<Circle2f> value);\r\n        void CodeList_of_Line2f_(ref List<Line2f> value);\r\n        void CodeList_of_Line3f_(ref List<Line3f> value);\r\n        void CodeList_of_Plane2f_(ref List<Plane2f> value);\r\n        void CodeList_of_Plane3f_(ref List<Plane3f> value);\r\n        void CodeList_of_PlaneWithPoint3f_(ref List<PlaneWithPoint3f> value);\r\n        void CodeList_of_Quad2f_(ref List<Quad2f> value);\r\n        void CodeList_of_Quad3f_(ref List<Quad3f> value);\r\n        void CodeList_of_Ray2f_(ref List<Ray2f> value);\r\n        void CodeList_of_Ray3f_(ref List<Ray3f> value);\r\n        void CodeList_of_Sphere3f_(ref List<Sphere3f> value);\r\n        void CodeList_of_Triangle2f_(ref List<Triangle2f> value);\r\n        void CodeList_of_Triangle3f_(ref List<Triangle3f> value);\r\n        void CodeList_of_Vector_of_Byte__(ref List<Vector<byte>> value);\r\n        void CodeList_of_Vector_of_SByte__(ref List<Vector<sbyte>> value);\r\n        void CodeList_of_Vector_of_Short__(ref List<Vector<short>> value);\r\n        void CodeList_of_Vector_of_UShort__(ref List<Vector<ushort>> value);\r\n        void CodeList_of_Vector_of_Int__(ref List<Vector<int>> value);\r\n        void CodeList_of_Vector_of_UInt__(ref List<Vector<uint>> value);\r\n        void CodeList_of_Vector_of_Long__(ref List<Vector<long>> value);\r\n        void CodeList_of_Vector_of_ULong__(ref List<Vector<ulong>> value);\r\n        void CodeList_of_Vector_of_Float__(ref List<Vector<float>> value);\r\n        void CodeList_of_Vector_of_Double__(ref List<Vector<double>> value);\r\n        void CodeList_of_Vector_of_Fraction__(ref List<Vector<Fraction>> value);\r\n        void CodeList_of_Vector_of_V2i__(ref List<Vector<V2i>> value);\r\n        void CodeList_of_Vector_of_V2l__(ref List<Vector<V2l>> value);\r\n        void CodeList_of_Vector_of_V2f__(ref List<Vector<V2f>> value);\r\n        void CodeList_of_Vector_of_V2d__(ref List<Vector<V2d>> value);\r\n        void CodeList_of_Vector_of_V3i__(ref List<Vector<V3i>> value);\r\n        void CodeList_of_Vector_of_V3l__(ref List<Vector<V3l>> value);\r\n        void CodeList_of_Vector_of_V3f__(ref List<Vector<V3f>> value);\r\n        void CodeList_of_Vector_of_V3d__(ref List<Vector<V3d>> value);\r\n        void CodeList_of_Vector_of_V4i__(ref List<Vector<V4i>> value);\r\n        void CodeList_of_Vector_of_V4l__(ref List<Vector<V4l>> value);\r\n        void CodeList_of_Vector_of_V4f__(ref List<Vector<V4f>> value);\r\n        void CodeList_of_Vector_of_V4d__(ref List<Vector<V4d>> value);\r\n        void CodeList_of_Vector_of_M22i__(ref List<Vector<M22i>> value);\r\n        void CodeList_of_Vector_of_M22l__(ref List<Vector<M22l>> value);\r\n        void CodeList_of_Vector_of_M22f__(ref List<Vector<M22f>> value);\r\n        void CodeList_of_Vector_of_M22d__(ref List<Vector<M22d>> value);\r\n        void CodeList_of_Vector_of_M23i__(ref List<Vector<M23i>> value);\r\n        void CodeList_of_Vector_of_M23l__(ref List<Vector<M23l>> value);\r\n        void CodeList_of_Vector_of_M23f__(ref List<Vector<M23f>> value);\r\n        void CodeList_of_Vector_of_M23d__(ref List<Vector<M23d>> value);\r\n        void CodeList_of_Vector_of_M33i__(ref List<Vector<M33i>> value);\r\n        void CodeList_of_Vector_of_M33l__(ref List<Vector<M33l>> value);\r\n        void CodeList_of_Vector_of_M33f__(ref List<Vector<M33f>> value);\r\n        void CodeList_of_Vector_of_M33d__(ref List<Vector<M33d>> value);\r\n        void CodeList_of_Vector_of_M34i__(ref List<Vector<M34i>> value);\r\n        void CodeList_of_Vector_of_M34l__(ref List<Vector<M34l>> value);\r\n        void CodeList_of_Vector_of_M34f__(ref List<Vector<M34f>> value);\r\n        void CodeList_of_Vector_of_M34d__(ref List<Vector<M34d>> value);\r\n        void CodeList_of_Vector_of_M44i__(ref List<Vector<M44i>> value);\r\n        void CodeList_of_Vector_of_M44l__(ref List<Vector<M44l>> value);\r\n        void CodeList_of_Vector_of_M44f__(ref List<Vector<M44f>> value);\r\n        void CodeList_of_Vector_of_M44d__(ref List<Vector<M44d>> value);\r\n        void CodeList_of_Vector_of_C3b__(ref List<Vector<C3b>> value);\r\n        void CodeList_of_Vector_of_C3us__(ref List<Vector<C3us>> value);\r\n        void CodeList_of_Vector_of_C3ui__(ref List<Vector<C3ui>> value);\r\n        void CodeList_of_Vector_of_C3f__(ref List<Vector<C3f>> value);\r\n        void CodeList_of_Vector_of_C3d__(ref List<Vector<C3d>> value);\r\n        void CodeList_of_Vector_of_C4b__(ref List<Vector<C4b>> value);\r\n        void CodeList_of_Vector_of_C4us__(ref List<Vector<C4us>> value);\r\n        void CodeList_of_Vector_of_C4ui__(ref List<Vector<C4ui>> value);\r\n        void CodeList_of_Vector_of_C4f__(ref List<Vector<C4f>> value);\r\n        void CodeList_of_Vector_of_C4d__(ref List<Vector<C4d>> value);\r\n        void CodeList_of_Vector_of_Range1b__(ref List<Vector<Range1b>> value);\r\n        void CodeList_of_Vector_of_Range1sb__(ref List<Vector<Range1sb>> value);\r\n        void CodeList_of_Vector_of_Range1s__(ref List<Vector<Range1s>> value);\r\n        void CodeList_of_Vector_of_Range1us__(ref List<Vector<Range1us>> value);\r\n        void CodeList_of_Vector_of_Range1i__(ref List<Vector<Range1i>> value);\r\n        void CodeList_of_Vector_of_Range1ui__(ref List<Vector<Range1ui>> value);\r\n        void CodeList_of_Vector_of_Range1l__(ref List<Vector<Range1l>> value);\r\n        void CodeList_of_Vector_of_Range1ul__(ref List<Vector<Range1ul>> value);\r\n        void CodeList_of_Vector_of_Range1f__(ref List<Vector<Range1f>> value);\r\n        void CodeList_of_Vector_of_Range1d__(ref List<Vector<Range1d>> value);\r\n        void CodeList_of_Vector_of_Box2i__(ref List<Vector<Box2i>> value);\r\n        void CodeList_of_Vector_of_Box2l__(ref List<Vector<Box2l>> value);\r\n        void CodeList_of_Vector_of_Box2f__(ref List<Vector<Box2f>> value);\r\n        void CodeList_of_Vector_of_Box2d__(ref List<Vector<Box2d>> value);\r\n        void CodeList_of_Vector_of_Box3i__(ref List<Vector<Box3i>> value);\r\n        void CodeList_of_Vector_of_Box3l__(ref List<Vector<Box3l>> value);\r\n        void CodeList_of_Vector_of_Box3f__(ref List<Vector<Box3f>> value);\r\n        void CodeList_of_Vector_of_Box3d__(ref List<Vector<Box3d>> value);\r\n        void CodeList_of_Vector_of_Euclidean3f__(ref List<Vector<Euclidean3f>> value);\r\n        void CodeList_of_Vector_of_Euclidean3d__(ref List<Vector<Euclidean3d>> value);\r\n        void CodeList_of_Vector_of_Rot2f__(ref List<Vector<Rot2f>> value);\r\n        void CodeList_of_Vector_of_Rot2d__(ref List<Vector<Rot2d>> value);\r\n        void CodeList_of_Vector_of_Rot3f__(ref List<Vector<Rot3f>> value);\r\n        void CodeList_of_Vector_of_Rot3d__(ref List<Vector<Rot3d>> value);\r\n        void CodeList_of_Vector_of_Scale3f__(ref List<Vector<Scale3f>> value);\r\n        void CodeList_of_Vector_of_Scale3d__(ref List<Vector<Scale3d>> value);\r\n        void CodeList_of_Vector_of_Shift3f__(ref List<Vector<Shift3f>> value);\r\n        void CodeList_of_Vector_of_Shift3d__(ref List<Vector<Shift3d>> value);\r\n        void CodeList_of_Vector_of_Trafo2f__(ref List<Vector<Trafo2f>> value);\r\n        void CodeList_of_Vector_of_Trafo2d__(ref List<Vector<Trafo2d>> value);\r\n        void CodeList_of_Vector_of_Trafo3f__(ref List<Vector<Trafo3f>> value);\r\n        void CodeList_of_Vector_of_Trafo3d__(ref List<Vector<Trafo3d>> value);\r\n        void CodeList_of_Vector_of_Bool__(ref List<Vector<bool>> value);\r\n        void CodeList_of_Vector_of_Char__(ref List<Vector<char>> value);\r\n        void CodeList_of_Vector_of_String__(ref List<Vector<string>> value);\r\n        void CodeList_of_Vector_of_Type__(ref List<Vector<Type>> value);\r\n        void CodeList_of_Vector_of_Guid__(ref List<Vector<Guid>> value);\r\n        void CodeList_of_Vector_of_Symbol__(ref List<Vector<Symbol>> value);\r\n        void CodeList_of_Vector_of_Circle2d__(ref List<Vector<Circle2d>> value);\r\n        void CodeList_of_Vector_of_Line2d__(ref List<Vector<Line2d>> value);\r\n        void CodeList_of_Vector_of_Line3d__(ref List<Vector<Line3d>> value);\r\n        void CodeList_of_Vector_of_Plane2d__(ref List<Vector<Plane2d>> value);\r\n        void CodeList_of_Vector_of_Plane3d__(ref List<Vector<Plane3d>> value);\r\n        void CodeList_of_Vector_of_PlaneWithPoint3d__(ref List<Vector<PlaneWithPoint3d>> value);\r\n        void CodeList_of_Vector_of_Quad2d__(ref List<Vector<Quad2d>> value);\r\n        void CodeList_of_Vector_of_Quad3d__(ref List<Vector<Quad3d>> value);\r\n        void CodeList_of_Vector_of_Ray2d__(ref List<Vector<Ray2d>> value);\r\n        void CodeList_of_Vector_of_Ray3d__(ref List<Vector<Ray3d>> value);\r\n        void CodeList_of_Vector_of_Sphere3d__(ref List<Vector<Sphere3d>> value);\r\n        void CodeList_of_Vector_of_Triangle2d__(ref List<Vector<Triangle2d>> value);\r\n        void CodeList_of_Vector_of_Triangle3d__(ref List<Vector<Triangle3d>> value);\r\n        void CodeList_of_Vector_of_Circle2f__(ref List<Vector<Circle2f>> value);\r\n        void CodeList_of_Vector_of_Line2f__(ref List<Vector<Line2f>> value);\r\n        void CodeList_of_Vector_of_Line3f__(ref List<Vector<Line3f>> value);\r\n        void CodeList_of_Vector_of_Plane2f__(ref List<Vector<Plane2f>> value);\r\n        void CodeList_of_Vector_of_Plane3f__(ref List<Vector<Plane3f>> value);\r\n        void CodeList_of_Vector_of_PlaneWithPoint3f__(ref List<Vector<PlaneWithPoint3f>> value);\r\n        void CodeList_of_Vector_of_Quad2f__(ref List<Vector<Quad2f>> value);\r\n        void CodeList_of_Vector_of_Quad3f__(ref List<Vector<Quad3f>> value);\r\n        void CodeList_of_Vector_of_Ray2f__(ref List<Vector<Ray2f>> value);\r\n        void CodeList_of_Vector_of_Ray3f__(ref List<Vector<Ray3f>> value);\r\n        void CodeList_of_Vector_of_Sphere3f__(ref List<Vector<Sphere3f>> value);\r\n        void CodeList_of_Vector_of_Triangle2f__(ref List<Vector<Triangle2f>> value);\r\n        void CodeList_of_Vector_of_Triangle3f__(ref List<Vector<Triangle3f>> value);\r\n        void CodeList_of_Matrix_of_Byte__(ref List<Matrix<byte>> value);\r\n        void CodeList_of_Matrix_of_SByte__(ref List<Matrix<sbyte>> value);\r\n        void CodeList_of_Matrix_of_Short__(ref List<Matrix<short>> value);\r\n        void CodeList_of_Matrix_of_UShort__(ref List<Matrix<ushort>> value);\r\n        void CodeList_of_Matrix_of_Int__(ref List<Matrix<int>> value);\r\n        void CodeList_of_Matrix_of_UInt__(ref List<Matrix<uint>> value);\r\n        void CodeList_of_Matrix_of_Long__(ref List<Matrix<long>> value);\r\n        void CodeList_of_Matrix_of_ULong__(ref List<Matrix<ulong>> value);\r\n        void CodeList_of_Matrix_of_Float__(ref List<Matrix<float>> value);\r\n        void CodeList_of_Matrix_of_Double__(ref List<Matrix<double>> value);\r\n        void CodeList_of_Matrix_of_Fraction__(ref List<Matrix<Fraction>> value);\r\n        void CodeList_of_Matrix_of_V2i__(ref List<Matrix<V2i>> value);\r\n        void CodeList_of_Matrix_of_V2l__(ref List<Matrix<V2l>> value);\r\n        void CodeList_of_Matrix_of_V2f__(ref List<Matrix<V2f>> value);\r\n        void CodeList_of_Matrix_of_V2d__(ref List<Matrix<V2d>> value);\r\n        void CodeList_of_Matrix_of_V3i__(ref List<Matrix<V3i>> value);\r\n        void CodeList_of_Matrix_of_V3l__(ref List<Matrix<V3l>> value);\r\n        void CodeList_of_Matrix_of_V3f__(ref List<Matrix<V3f>> value);\r\n        void CodeList_of_Matrix_of_V3d__(ref List<Matrix<V3d>> value);\r\n        void CodeList_of_Matrix_of_V4i__(ref List<Matrix<V4i>> value);\r\n        void CodeList_of_Matrix_of_V4l__(ref List<Matrix<V4l>> value);\r\n        void CodeList_of_Matrix_of_V4f__(ref List<Matrix<V4f>> value);\r\n        void CodeList_of_Matrix_of_V4d__(ref List<Matrix<V4d>> value);\r\n        void CodeList_of_Matrix_of_M22i__(ref List<Matrix<M22i>> value);\r\n        void CodeList_of_Matrix_of_M22l__(ref List<Matrix<M22l>> value);\r\n        void CodeList_of_Matrix_of_M22f__(ref List<Matrix<M22f>> value);\r\n        void CodeList_of_Matrix_of_M22d__(ref List<Matrix<M22d>> value);\r\n        void CodeList_of_Matrix_of_M23i__(ref List<Matrix<M23i>> value);\r\n        void CodeList_of_Matrix_of_M23l__(ref List<Matrix<M23l>> value);\r\n        void CodeList_of_Matrix_of_M23f__(ref List<Matrix<M23f>> value);\r\n        void CodeList_of_Matrix_of_M23d__(ref List<Matrix<M23d>> value);\r\n        void CodeList_of_Matrix_of_M33i__(ref List<Matrix<M33i>> value);\r\n        void CodeList_of_Matrix_of_M33l__(ref List<Matrix<M33l>> value);\r\n        void CodeList_of_Matrix_of_M33f__(ref List<Matrix<M33f>> value);\r\n        void CodeList_of_Matrix_of_M33d__(ref List<Matrix<M33d>> value);\r\n        void CodeList_of_Matrix_of_M34i__(ref List<Matrix<M34i>> value);\r\n        void CodeList_of_Matrix_of_M34l__(ref List<Matrix<M34l>> value);\r\n        void CodeList_of_Matrix_of_M34f__(ref List<Matrix<M34f>> value);\r\n        void CodeList_of_Matrix_of_M34d__(ref List<Matrix<M34d>> value);\r\n        void CodeList_of_Matrix_of_M44i__(ref List<Matrix<M44i>> value);\r\n        void CodeList_of_Matrix_of_M44l__(ref List<Matrix<M44l>> value);\r\n        void CodeList_of_Matrix_of_M44f__(ref List<Matrix<M44f>> value);\r\n        void CodeList_of_Matrix_of_M44d__(ref List<Matrix<M44d>> value);\r\n        void CodeList_of_Matrix_of_C3b__(ref List<Matrix<C3b>> value);\r\n        void CodeList_of_Matrix_of_C3us__(ref List<Matrix<C3us>> value);\r\n        void CodeList_of_Matrix_of_C3ui__(ref List<Matrix<C3ui>> value);\r\n        void CodeList_of_Matrix_of_C3f__(ref List<Matrix<C3f>> value);\r\n        void CodeList_of_Matrix_of_C3d__(ref List<Matrix<C3d>> value);\r\n        void CodeList_of_Matrix_of_C4b__(ref List<Matrix<C4b>> value);\r\n        void CodeList_of_Matrix_of_C4us__(ref List<Matrix<C4us>> value);\r\n        void CodeList_of_Matrix_of_C4ui__(ref List<Matrix<C4ui>> value);\r\n        void CodeList_of_Matrix_of_C4f__(ref List<Matrix<C4f>> value);\r\n        void CodeList_of_Matrix_of_C4d__(ref List<Matrix<C4d>> value);\r\n        void CodeList_of_Matrix_of_Range1b__(ref List<Matrix<Range1b>> value);\r\n        void CodeList_of_Matrix_of_Range1sb__(ref List<Matrix<Range1sb>> value);\r\n        void CodeList_of_Matrix_of_Range1s__(ref List<Matrix<Range1s>> value);\r\n        void CodeList_of_Matrix_of_Range1us__(ref List<Matrix<Range1us>> value);\r\n        void CodeList_of_Matrix_of_Range1i__(ref List<Matrix<Range1i>> value);\r\n        void CodeList_of_Matrix_of_Range1ui__(ref List<Matrix<Range1ui>> value);\r\n        void CodeList_of_Matrix_of_Range1l__(ref List<Matrix<Range1l>> value);\r\n        void CodeList_of_Matrix_of_Range1ul__(ref List<Matrix<Range1ul>> value);\r\n        void CodeList_of_Matrix_of_Range1f__(ref List<Matrix<Range1f>> value);\r\n        void CodeList_of_Matrix_of_Range1d__(ref List<Matrix<Range1d>> value);\r\n        void CodeList_of_Matrix_of_Box2i__(ref List<Matrix<Box2i>> value);\r\n        void CodeList_of_Matrix_of_Box2l__(ref List<Matrix<Box2l>> value);\r\n        void CodeList_of_Matrix_of_Box2f__(ref List<Matrix<Box2f>> value);\r\n        void CodeList_of_Matrix_of_Box2d__(ref List<Matrix<Box2d>> value);\r\n        void CodeList_of_Matrix_of_Box3i__(ref List<Matrix<Box3i>> value);\r\n        void CodeList_of_Matrix_of_Box3l__(ref List<Matrix<Box3l>> value);\r\n        void CodeList_of_Matrix_of_Box3f__(ref List<Matrix<Box3f>> value);\r\n        void CodeList_of_Matrix_of_Box3d__(ref List<Matrix<Box3d>> value);\r\n        void CodeList_of_Matrix_of_Euclidean3f__(ref List<Matrix<Euclidean3f>> value);\r\n        void CodeList_of_Matrix_of_Euclidean3d__(ref List<Matrix<Euclidean3d>> value);\r\n        void CodeList_of_Matrix_of_Rot2f__(ref List<Matrix<Rot2f>> value);\r\n        void CodeList_of_Matrix_of_Rot2d__(ref List<Matrix<Rot2d>> value);\r\n        void CodeList_of_Matrix_of_Rot3f__(ref List<Matrix<Rot3f>> value);\r\n        void CodeList_of_Matrix_of_Rot3d__(ref List<Matrix<Rot3d>> value);\r\n        void CodeList_of_Matrix_of_Scale3f__(ref List<Matrix<Scale3f>> value);\r\n        void CodeList_of_Matrix_of_Scale3d__(ref List<Matrix<Scale3d>> value);\r\n        void CodeList_of_Matrix_of_Shift3f__(ref List<Matrix<Shift3f>> value);\r\n        void CodeList_of_Matrix_of_Shift3d__(ref List<Matrix<Shift3d>> value);\r\n        void CodeList_of_Matrix_of_Trafo2f__(ref List<Matrix<Trafo2f>> value);\r\n        void CodeList_of_Matrix_of_Trafo2d__(ref List<Matrix<Trafo2d>> value);\r\n        void CodeList_of_Matrix_of_Trafo3f__(ref List<Matrix<Trafo3f>> value);\r\n        void CodeList_of_Matrix_of_Trafo3d__(ref List<Matrix<Trafo3d>> value);\r\n        void CodeList_of_Matrix_of_Bool__(ref List<Matrix<bool>> value);\r\n        void CodeList_of_Matrix_of_Char__(ref List<Matrix<char>> value);\r\n        void CodeList_of_Matrix_of_String__(ref List<Matrix<string>> value);\r\n        void CodeList_of_Matrix_of_Type__(ref List<Matrix<Type>> value);\r\n        void CodeList_of_Matrix_of_Guid__(ref List<Matrix<Guid>> value);\r\n        void CodeList_of_Matrix_of_Symbol__(ref List<Matrix<Symbol>> value);\r\n        void CodeList_of_Matrix_of_Circle2d__(ref List<Matrix<Circle2d>> value);\r\n        void CodeList_of_Matrix_of_Line2d__(ref List<Matrix<Line2d>> value);\r\n        void CodeList_of_Matrix_of_Line3d__(ref List<Matrix<Line3d>> value);\r\n        void CodeList_of_Matrix_of_Plane2d__(ref List<Matrix<Plane2d>> value);\r\n        void CodeList_of_Matrix_of_Plane3d__(ref List<Matrix<Plane3d>> value);\r\n        void CodeList_of_Matrix_of_PlaneWithPoint3d__(ref List<Matrix<PlaneWithPoint3d>> value);\r\n        void CodeList_of_Matrix_of_Quad2d__(ref List<Matrix<Quad2d>> value);\r\n        void CodeList_of_Matrix_of_Quad3d__(ref List<Matrix<Quad3d>> value);\r\n        void CodeList_of_Matrix_of_Ray2d__(ref List<Matrix<Ray2d>> value);\r\n        void CodeList_of_Matrix_of_Ray3d__(ref List<Matrix<Ray3d>> value);\r\n        void CodeList_of_Matrix_of_Sphere3d__(ref List<Matrix<Sphere3d>> value);\r\n        void CodeList_of_Matrix_of_Triangle2d__(ref List<Matrix<Triangle2d>> value);\r\n        void CodeList_of_Matrix_of_Triangle3d__(ref List<Matrix<Triangle3d>> value);\r\n        void CodeList_of_Matrix_of_Circle2f__(ref List<Matrix<Circle2f>> value);\r\n        void CodeList_of_Matrix_of_Line2f__(ref List<Matrix<Line2f>> value);\r\n        void CodeList_of_Matrix_of_Line3f__(ref List<Matrix<Line3f>> value);\r\n        void CodeList_of_Matrix_of_Plane2f__(ref List<Matrix<Plane2f>> value);\r\n        void CodeList_of_Matrix_of_Plane3f__(ref List<Matrix<Plane3f>> value);\r\n        void CodeList_of_Matrix_of_PlaneWithPoint3f__(ref List<Matrix<PlaneWithPoint3f>> value);\r\n        void CodeList_of_Matrix_of_Quad2f__(ref List<Matrix<Quad2f>> value);\r\n        void CodeList_of_Matrix_of_Quad3f__(ref List<Matrix<Quad3f>> value);\r\n        void CodeList_of_Matrix_of_Ray2f__(ref List<Matrix<Ray2f>> value);\r\n        void CodeList_of_Matrix_of_Ray3f__(ref List<Matrix<Ray3f>> value);\r\n        void CodeList_of_Matrix_of_Sphere3f__(ref List<Matrix<Sphere3f>> value);\r\n        void CodeList_of_Matrix_of_Triangle2f__(ref List<Matrix<Triangle2f>> value);\r\n        void CodeList_of_Matrix_of_Triangle3f__(ref List<Matrix<Triangle3f>> value);\r\n        void CodeList_of_Volume_of_Byte__(ref List<Volume<byte>> value);\r\n        void CodeList_of_Volume_of_SByte__(ref List<Volume<sbyte>> value);\r\n        void CodeList_of_Volume_of_Short__(ref List<Volume<short>> value);\r\n        void CodeList_of_Volume_of_UShort__(ref List<Volume<ushort>> value);\r\n        void CodeList_of_Volume_of_Int__(ref List<Volume<int>> value);\r\n        void CodeList_of_Volume_of_UInt__(ref List<Volume<uint>> value);\r\n        void CodeList_of_Volume_of_Long__(ref List<Volume<long>> value);\r\n        void CodeList_of_Volume_of_ULong__(ref List<Volume<ulong>> value);\r\n        void CodeList_of_Volume_of_Float__(ref List<Volume<float>> value);\r\n        void CodeList_of_Volume_of_Double__(ref List<Volume<double>> value);\r\n        void CodeList_of_Volume_of_Fraction__(ref List<Volume<Fraction>> value);\r\n        void CodeList_of_Volume_of_V2i__(ref List<Volume<V2i>> value);\r\n        void CodeList_of_Volume_of_V2l__(ref List<Volume<V2l>> value);\r\n        void CodeList_of_Volume_of_V2f__(ref List<Volume<V2f>> value);\r\n        void CodeList_of_Volume_of_V2d__(ref List<Volume<V2d>> value);\r\n        void CodeList_of_Volume_of_V3i__(ref List<Volume<V3i>> value);\r\n        void CodeList_of_Volume_of_V3l__(ref List<Volume<V3l>> value);\r\n        void CodeList_of_Volume_of_V3f__(ref List<Volume<V3f>> value);\r\n        void CodeList_of_Volume_of_V3d__(ref List<Volume<V3d>> value);\r\n        void CodeList_of_Volume_of_V4i__(ref List<Volume<V4i>> value);\r\n        void CodeList_of_Volume_of_V4l__(ref List<Volume<V4l>> value);\r\n        void CodeList_of_Volume_of_V4f__(ref List<Volume<V4f>> value);\r\n        void CodeList_of_Volume_of_V4d__(ref List<Volume<V4d>> value);\r\n        void CodeList_of_Volume_of_M22i__(ref List<Volume<M22i>> value);\r\n        void CodeList_of_Volume_of_M22l__(ref List<Volume<M22l>> value);\r\n        void CodeList_of_Volume_of_M22f__(ref List<Volume<M22f>> value);\r\n        void CodeList_of_Volume_of_M22d__(ref List<Volume<M22d>> value);\r\n        void CodeList_of_Volume_of_M23i__(ref List<Volume<M23i>> value);\r\n        void CodeList_of_Volume_of_M23l__(ref List<Volume<M23l>> value);\r\n        void CodeList_of_Volume_of_M23f__(ref List<Volume<M23f>> value);\r\n        void CodeList_of_Volume_of_M23d__(ref List<Volume<M23d>> value);\r\n        void CodeList_of_Volume_of_M33i__(ref List<Volume<M33i>> value);\r\n        void CodeList_of_Volume_of_M33l__(ref List<Volume<M33l>> value);\r\n        void CodeList_of_Volume_of_M33f__(ref List<Volume<M33f>> value);\r\n        void CodeList_of_Volume_of_M33d__(ref List<Volume<M33d>> value);\r\n        void CodeList_of_Volume_of_M34i__(ref List<Volume<M34i>> value);\r\n        void CodeList_of_Volume_of_M34l__(ref List<Volume<M34l>> value);\r\n        void CodeList_of_Volume_of_M34f__(ref List<Volume<M34f>> value);\r\n        void CodeList_of_Volume_of_M34d__(ref List<Volume<M34d>> value);\r\n        void CodeList_of_Volume_of_M44i__(ref List<Volume<M44i>> value);\r\n        void CodeList_of_Volume_of_M44l__(ref List<Volume<M44l>> value);\r\n        void CodeList_of_Volume_of_M44f__(ref List<Volume<M44f>> value);\r\n        void CodeList_of_Volume_of_M44d__(ref List<Volume<M44d>> value);\r\n        void CodeList_of_Volume_of_C3b__(ref List<Volume<C3b>> value);\r\n        void CodeList_of_Volume_of_C3us__(ref List<Volume<C3us>> value);\r\n        void CodeList_of_Volume_of_C3ui__(ref List<Volume<C3ui>> value);\r\n        void CodeList_of_Volume_of_C3f__(ref List<Volume<C3f>> value);\r\n        void CodeList_of_Volume_of_C3d__(ref List<Volume<C3d>> value);\r\n        void CodeList_of_Volume_of_C4b__(ref List<Volume<C4b>> value);\r\n        void CodeList_of_Volume_of_C4us__(ref List<Volume<C4us>> value);\r\n        void CodeList_of_Volume_of_C4ui__(ref List<Volume<C4ui>> value);\r\n        void CodeList_of_Volume_of_C4f__(ref List<Volume<C4f>> value);\r\n        void CodeList_of_Volume_of_C4d__(ref List<Volume<C4d>> value);\r\n        void CodeList_of_Volume_of_Range1b__(ref List<Volume<Range1b>> value);\r\n        void CodeList_of_Volume_of_Range1sb__(ref List<Volume<Range1sb>> value);\r\n        void CodeList_of_Volume_of_Range1s__(ref List<Volume<Range1s>> value);\r\n        void CodeList_of_Volume_of_Range1us__(ref List<Volume<Range1us>> value);\r\n        void CodeList_of_Volume_of_Range1i__(ref List<Volume<Range1i>> value);\r\n        void CodeList_of_Volume_of_Range1ui__(ref List<Volume<Range1ui>> value);\r\n        void CodeList_of_Volume_of_Range1l__(ref List<Volume<Range1l>> value);\r\n        void CodeList_of_Volume_of_Range1ul__(ref List<Volume<Range1ul>> value);\r\n        void CodeList_of_Volume_of_Range1f__(ref List<Volume<Range1f>> value);\r\n        void CodeList_of_Volume_of_Range1d__(ref List<Volume<Range1d>> value);\r\n        void CodeList_of_Volume_of_Box2i__(ref List<Volume<Box2i>> value);\r\n        void CodeList_of_Volume_of_Box2l__(ref List<Volume<Box2l>> value);\r\n        void CodeList_of_Volume_of_Box2f__(ref List<Volume<Box2f>> value);\r\n        void CodeList_of_Volume_of_Box2d__(ref List<Volume<Box2d>> value);\r\n        void CodeList_of_Volume_of_Box3i__(ref List<Volume<Box3i>> value);\r\n        void CodeList_of_Volume_of_Box3l__(ref List<Volume<Box3l>> value);\r\n        void CodeList_of_Volume_of_Box3f__(ref List<Volume<Box3f>> value);\r\n        void CodeList_of_Volume_of_Box3d__(ref List<Volume<Box3d>> value);\r\n        void CodeList_of_Volume_of_Euclidean3f__(ref List<Volume<Euclidean3f>> value);\r\n        void CodeList_of_Volume_of_Euclidean3d__(ref List<Volume<Euclidean3d>> value);\r\n        void CodeList_of_Volume_of_Rot2f__(ref List<Volume<Rot2f>> value);\r\n        void CodeList_of_Volume_of_Rot2d__(ref List<Volume<Rot2d>> value);\r\n        void CodeList_of_Volume_of_Rot3f__(ref List<Volume<Rot3f>> value);\r\n        void CodeList_of_Volume_of_Rot3d__(ref List<Volume<Rot3d>> value);\r\n        void CodeList_of_Volume_of_Scale3f__(ref List<Volume<Scale3f>> value);\r\n        void CodeList_of_Volume_of_Scale3d__(ref List<Volume<Scale3d>> value);\r\n        void CodeList_of_Volume_of_Shift3f__(ref List<Volume<Shift3f>> value);\r\n        void CodeList_of_Volume_of_Shift3d__(ref List<Volume<Shift3d>> value);\r\n        void CodeList_of_Volume_of_Trafo2f__(ref List<Volume<Trafo2f>> value);\r\n        void CodeList_of_Volume_of_Trafo2d__(ref List<Volume<Trafo2d>> value);\r\n        void CodeList_of_Volume_of_Trafo3f__(ref List<Volume<Trafo3f>> value);\r\n        void CodeList_of_Volume_of_Trafo3d__(ref List<Volume<Trafo3d>> value);\r\n        void CodeList_of_Volume_of_Bool__(ref List<Volume<bool>> value);\r\n        void CodeList_of_Volume_of_Char__(ref List<Volume<char>> value);\r\n        void CodeList_of_Volume_of_String__(ref List<Volume<string>> value);\r\n        void CodeList_of_Volume_of_Type__(ref List<Volume<Type>> value);\r\n        void CodeList_of_Volume_of_Guid__(ref List<Volume<Guid>> value);\r\n        void CodeList_of_Volume_of_Symbol__(ref List<Volume<Symbol>> value);\r\n        void CodeList_of_Volume_of_Circle2d__(ref List<Volume<Circle2d>> value);\r\n        void CodeList_of_Volume_of_Line2d__(ref List<Volume<Line2d>> value);\r\n        void CodeList_of_Volume_of_Line3d__(ref List<Volume<Line3d>> value);\r\n        void CodeList_of_Volume_of_Plane2d__(ref List<Volume<Plane2d>> value);\r\n        void CodeList_of_Volume_of_Plane3d__(ref List<Volume<Plane3d>> value);\r\n        void CodeList_of_Volume_of_PlaneWithPoint3d__(ref List<Volume<PlaneWithPoint3d>> value);\r\n        void CodeList_of_Volume_of_Quad2d__(ref List<Volume<Quad2d>> value);\r\n        void CodeList_of_Volume_of_Quad3d__(ref List<Volume<Quad3d>> value);\r\n        void CodeList_of_Volume_of_Ray2d__(ref List<Volume<Ray2d>> value);\r\n        void CodeList_of_Volume_of_Ray3d__(ref List<Volume<Ray3d>> value);\r\n        void CodeList_of_Volume_of_Sphere3d__(ref List<Volume<Sphere3d>> value);\r\n        void CodeList_of_Volume_of_Triangle2d__(ref List<Volume<Triangle2d>> value);\r\n        void CodeList_of_Volume_of_Triangle3d__(ref List<Volume<Triangle3d>> value);\r\n        void CodeList_of_Volume_of_Circle2f__(ref List<Volume<Circle2f>> value);\r\n        void CodeList_of_Volume_of_Line2f__(ref List<Volume<Line2f>> value);\r\n        void CodeList_of_Volume_of_Line3f__(ref List<Volume<Line3f>> value);\r\n        void CodeList_of_Volume_of_Plane2f__(ref List<Volume<Plane2f>> value);\r\n        void CodeList_of_Volume_of_Plane3f__(ref List<Volume<Plane3f>> value);\r\n        void CodeList_of_Volume_of_PlaneWithPoint3f__(ref List<Volume<PlaneWithPoint3f>> value);\r\n        void CodeList_of_Volume_of_Quad2f__(ref List<Volume<Quad2f>> value);\r\n        void CodeList_of_Volume_of_Quad3f__(ref List<Volume<Quad3f>> value);\r\n        void CodeList_of_Volume_of_Ray2f__(ref List<Volume<Ray2f>> value);\r\n        void CodeList_of_Volume_of_Ray3f__(ref List<Volume<Ray3f>> value);\r\n        void CodeList_of_Volume_of_Sphere3f__(ref List<Volume<Sphere3f>> value);\r\n        void CodeList_of_Volume_of_Triangle2f__(ref List<Volume<Triangle2f>> value);\r\n        void CodeList_of_Volume_of_Triangle3f__(ref List<Volume<Triangle3f>> value);\r\n        void CodeList_of_Tensor_of_Byte__(ref List<Tensor<byte>> value);\r\n        void CodeList_of_Tensor_of_SByte__(ref List<Tensor<sbyte>> value);\r\n        void CodeList_of_Tensor_of_Short__(ref List<Tensor<short>> value);\r\n        void CodeList_of_Tensor_of_UShort__(ref List<Tensor<ushort>> value);\r\n        void CodeList_of_Tensor_of_Int__(ref List<Tensor<int>> value);\r\n        void CodeList_of_Tensor_of_UInt__(ref List<Tensor<uint>> value);\r\n        void CodeList_of_Tensor_of_Long__(ref List<Tensor<long>> value);\r\n        void CodeList_of_Tensor_of_ULong__(ref List<Tensor<ulong>> value);\r\n        void CodeList_of_Tensor_of_Float__(ref List<Tensor<float>> value);\r\n        void CodeList_of_Tensor_of_Double__(ref List<Tensor<double>> value);\r\n        void CodeList_of_Tensor_of_Fraction__(ref List<Tensor<Fraction>> value);\r\n        void CodeList_of_Tensor_of_V2i__(ref List<Tensor<V2i>> value);\r\n        void CodeList_of_Tensor_of_V2l__(ref List<Tensor<V2l>> value);\r\n        void CodeList_of_Tensor_of_V2f__(ref List<Tensor<V2f>> value);\r\n        void CodeList_of_Tensor_of_V2d__(ref List<Tensor<V2d>> value);\r\n        void CodeList_of_Tensor_of_V3i__(ref List<Tensor<V3i>> value);\r\n        void CodeList_of_Tensor_of_V3l__(ref List<Tensor<V3l>> value);\r\n        void CodeList_of_Tensor_of_V3f__(ref List<Tensor<V3f>> value);\r\n        void CodeList_of_Tensor_of_V3d__(ref List<Tensor<V3d>> value);\r\n        void CodeList_of_Tensor_of_V4i__(ref List<Tensor<V4i>> value);\r\n        void CodeList_of_Tensor_of_V4l__(ref List<Tensor<V4l>> value);\r\n        void CodeList_of_Tensor_of_V4f__(ref List<Tensor<V4f>> value);\r\n        void CodeList_of_Tensor_of_V4d__(ref List<Tensor<V4d>> value);\r\n        void CodeList_of_Tensor_of_M22i__(ref List<Tensor<M22i>> value);\r\n        void CodeList_of_Tensor_of_M22l__(ref List<Tensor<M22l>> value);\r\n        void CodeList_of_Tensor_of_M22f__(ref List<Tensor<M22f>> value);\r\n        void CodeList_of_Tensor_of_M22d__(ref List<Tensor<M22d>> value);\r\n        void CodeList_of_Tensor_of_M23i__(ref List<Tensor<M23i>> value);\r\n        void CodeList_of_Tensor_of_M23l__(ref List<Tensor<M23l>> value);\r\n        void CodeList_of_Tensor_of_M23f__(ref List<Tensor<M23f>> value);\r\n        void CodeList_of_Tensor_of_M23d__(ref List<Tensor<M23d>> value);\r\n        void CodeList_of_Tensor_of_M33i__(ref List<Tensor<M33i>> value);\r\n        void CodeList_of_Tensor_of_M33l__(ref List<Tensor<M33l>> value);\r\n        void CodeList_of_Tensor_of_M33f__(ref List<Tensor<M33f>> value);\r\n        void CodeList_of_Tensor_of_M33d__(ref List<Tensor<M33d>> value);\r\n        void CodeList_of_Tensor_of_M34i__(ref List<Tensor<M34i>> value);\r\n        void CodeList_of_Tensor_of_M34l__(ref List<Tensor<M34l>> value);\r\n        void CodeList_of_Tensor_of_M34f__(ref List<Tensor<M34f>> value);\r\n        void CodeList_of_Tensor_of_M34d__(ref List<Tensor<M34d>> value);\r\n        void CodeList_of_Tensor_of_M44i__(ref List<Tensor<M44i>> value);\r\n        void CodeList_of_Tensor_of_M44l__(ref List<Tensor<M44l>> value);\r\n        void CodeList_of_Tensor_of_M44f__(ref List<Tensor<M44f>> value);\r\n        void CodeList_of_Tensor_of_M44d__(ref List<Tensor<M44d>> value);\r\n        void CodeList_of_Tensor_of_C3b__(ref List<Tensor<C3b>> value);\r\n        void CodeList_of_Tensor_of_C3us__(ref List<Tensor<C3us>> value);\r\n        void CodeList_of_Tensor_of_C3ui__(ref List<Tensor<C3ui>> value);\r\n        void CodeList_of_Tensor_of_C3f__(ref List<Tensor<C3f>> value);\r\n        void CodeList_of_Tensor_of_C3d__(ref List<Tensor<C3d>> value);\r\n        void CodeList_of_Tensor_of_C4b__(ref List<Tensor<C4b>> value);\r\n        void CodeList_of_Tensor_of_C4us__(ref List<Tensor<C4us>> value);\r\n        void CodeList_of_Tensor_of_C4ui__(ref List<Tensor<C4ui>> value);\r\n        void CodeList_of_Tensor_of_C4f__(ref List<Tensor<C4f>> value);\r\n        void CodeList_of_Tensor_of_C4d__(ref List<Tensor<C4d>> value);\r\n        void CodeList_of_Tensor_of_Range1b__(ref List<Tensor<Range1b>> value);\r\n        void CodeList_of_Tensor_of_Range1sb__(ref List<Tensor<Range1sb>> value);\r\n        void CodeList_of_Tensor_of_Range1s__(ref List<Tensor<Range1s>> value);\r\n        void CodeList_of_Tensor_of_Range1us__(ref List<Tensor<Range1us>> value);\r\n        void CodeList_of_Tensor_of_Range1i__(ref List<Tensor<Range1i>> value);\r\n        void CodeList_of_Tensor_of_Range1ui__(ref List<Tensor<Range1ui>> value);\r\n        void CodeList_of_Tensor_of_Range1l__(ref List<Tensor<Range1l>> value);\r\n        void CodeList_of_Tensor_of_Range1ul__(ref List<Tensor<Range1ul>> value);\r\n        void CodeList_of_Tensor_of_Range1f__(ref List<Tensor<Range1f>> value);\r\n        void CodeList_of_Tensor_of_Range1d__(ref List<Tensor<Range1d>> value);\r\n        void CodeList_of_Tensor_of_Box2i__(ref List<Tensor<Box2i>> value);\r\n        void CodeList_of_Tensor_of_Box2l__(ref List<Tensor<Box2l>> value);\r\n        void CodeList_of_Tensor_of_Box2f__(ref List<Tensor<Box2f>> value);\r\n        void CodeList_of_Tensor_of_Box2d__(ref List<Tensor<Box2d>> value);\r\n        void CodeList_of_Tensor_of_Box3i__(ref List<Tensor<Box3i>> value);\r\n        void CodeList_of_Tensor_of_Box3l__(ref List<Tensor<Box3l>> value);\r\n        void CodeList_of_Tensor_of_Box3f__(ref List<Tensor<Box3f>> value);\r\n        void CodeList_of_Tensor_of_Box3d__(ref List<Tensor<Box3d>> value);\r\n        void CodeList_of_Tensor_of_Euclidean3f__(ref List<Tensor<Euclidean3f>> value);\r\n        void CodeList_of_Tensor_of_Euclidean3d__(ref List<Tensor<Euclidean3d>> value);\r\n        void CodeList_of_Tensor_of_Rot2f__(ref List<Tensor<Rot2f>> value);\r\n        void CodeList_of_Tensor_of_Rot2d__(ref List<Tensor<Rot2d>> value);\r\n        void CodeList_of_Tensor_of_Rot3f__(ref List<Tensor<Rot3f>> value);\r\n        void CodeList_of_Tensor_of_Rot3d__(ref List<Tensor<Rot3d>> value);\r\n        void CodeList_of_Tensor_of_Scale3f__(ref List<Tensor<Scale3f>> value);\r\n        void CodeList_of_Tensor_of_Scale3d__(ref List<Tensor<Scale3d>> value);\r\n        void CodeList_of_Tensor_of_Shift3f__(ref List<Tensor<Shift3f>> value);\r\n        void CodeList_of_Tensor_of_Shift3d__(ref List<Tensor<Shift3d>> value);\r\n        void CodeList_of_Tensor_of_Trafo2f__(ref List<Tensor<Trafo2f>> value);\r\n        void CodeList_of_Tensor_of_Trafo2d__(ref List<Tensor<Trafo2d>> value);\r\n        void CodeList_of_Tensor_of_Trafo3f__(ref List<Tensor<Trafo3f>> value);\r\n        void CodeList_of_Tensor_of_Trafo3d__(ref List<Tensor<Trafo3d>> value);\r\n        void CodeList_of_Tensor_of_Bool__(ref List<Tensor<bool>> value);\r\n        void CodeList_of_Tensor_of_Char__(ref List<Tensor<char>> value);\r\n        void CodeList_of_Tensor_of_String__(ref List<Tensor<string>> value);\r\n        void CodeList_of_Tensor_of_Type__(ref List<Tensor<Type>> value);\r\n        void CodeList_of_Tensor_of_Guid__(ref List<Tensor<Guid>> value);\r\n        void CodeList_of_Tensor_of_Symbol__(ref List<Tensor<Symbol>> value);\r\n        void CodeList_of_Tensor_of_Circle2d__(ref List<Tensor<Circle2d>> value);\r\n        void CodeList_of_Tensor_of_Line2d__(ref List<Tensor<Line2d>> value);\r\n        void CodeList_of_Tensor_of_Line3d__(ref List<Tensor<Line3d>> value);\r\n        void CodeList_of_Tensor_of_Plane2d__(ref List<Tensor<Plane2d>> value);\r\n        void CodeList_of_Tensor_of_Plane3d__(ref List<Tensor<Plane3d>> value);\r\n        void CodeList_of_Tensor_of_PlaneWithPoint3d__(ref List<Tensor<PlaneWithPoint3d>> value);\r\n        void CodeList_of_Tensor_of_Quad2d__(ref List<Tensor<Quad2d>> value);\r\n        void CodeList_of_Tensor_of_Quad3d__(ref List<Tensor<Quad3d>> value);\r\n        void CodeList_of_Tensor_of_Ray2d__(ref List<Tensor<Ray2d>> value);\r\n        void CodeList_of_Tensor_of_Ray3d__(ref List<Tensor<Ray3d>> value);\r\n        void CodeList_of_Tensor_of_Sphere3d__(ref List<Tensor<Sphere3d>> value);\r\n        void CodeList_of_Tensor_of_Triangle2d__(ref List<Tensor<Triangle2d>> value);\r\n        void CodeList_of_Tensor_of_Triangle3d__(ref List<Tensor<Triangle3d>> value);\r\n        void CodeList_of_Tensor_of_Circle2f__(ref List<Tensor<Circle2f>> value);\r\n        void CodeList_of_Tensor_of_Line2f__(ref List<Tensor<Line2f>> value);\r\n        void CodeList_of_Tensor_of_Line3f__(ref List<Tensor<Line3f>> value);\r\n        void CodeList_of_Tensor_of_Plane2f__(ref List<Tensor<Plane2f>> value);\r\n        void CodeList_of_Tensor_of_Plane3f__(ref List<Tensor<Plane3f>> value);\r\n        void CodeList_of_Tensor_of_PlaneWithPoint3f__(ref List<Tensor<PlaneWithPoint3f>> value);\r\n        void CodeList_of_Tensor_of_Quad2f__(ref List<Tensor<Quad2f>> value);\r\n        void CodeList_of_Tensor_of_Quad3f__(ref List<Tensor<Quad3f>> value);\r\n        void CodeList_of_Tensor_of_Ray2f__(ref List<Tensor<Ray2f>> value);\r\n        void CodeList_of_Tensor_of_Ray3f__(ref List<Tensor<Ray3f>> value);\r\n        void CodeList_of_Tensor_of_Sphere3f__(ref List<Tensor<Sphere3f>> value);\r\n        void CodeList_of_Tensor_of_Triangle2f__(ref List<Tensor<Triangle2f>> value);\r\n        void CodeList_of_Tensor_of_Triangle3f__(ref List<Tensor<Triangle3f>> value);\r\n\r\n        #endregion\r\n\r\n        #region Geometry Types\r\n\r\n        void CodeCircle2f(ref Circle2f v);\r\n        void CodeLine2f(ref Line2f v);\r\n        void CodeLine3f(ref Line3f v);\r\n        void CodePlane2f(ref Plane2f v);\r\n        void CodePlane3f(ref Plane3f v);\r\n        void CodePlaneWithPoint3f(ref PlaneWithPoint3f v);\r\n        void CodeQuad2f(ref Quad2f v);\r\n        void CodeQuad3f(ref Quad3f v);\r\n        void CodeRay2f(ref Ray2f v);\r\n        void CodeRay3f(ref Ray3f v);\r\n        void CodeSphere3f(ref Sphere3f v);\r\n        void CodeTriangle2f(ref Triangle2f v);\r\n        void CodeTriangle3f(ref Triangle3f v);\r\n\r\n        void CodeCircle2d(ref Circle2d v);\r\n        void CodeLine2d(ref Line2d v);\r\n        void CodeLine3d(ref Line3d v);\r\n        void CodePlane2d(ref Plane2d v);\r\n        void CodePlane3d(ref Plane3d v);\r\n        void CodePlaneWithPoint3d(ref PlaneWithPoint3d v);\r\n        void CodeQuad2d(ref Quad2d v);\r\n        void CodeQuad3d(ref Quad3d v);\r\n        void CodeRay2d(ref Ray2d v);\r\n        void CodeRay3d(ref Ray3d v);\r\n        void CodeSphere3d(ref Sphere3d v);\r\n        void CodeTriangle2d(ref Triangle2d v);\r\n        void CodeTriangle3d(ref Triangle3d v);\r\n\r\n        #endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/ICoder_template.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Coder\n{\n\n    // AUTO GENERATED CODE - DO NOT CHANGE\n\n    //# var directlyCodeableTypes = Meta.DirectlyCodeableTypes.Map(t =>t.Name);\n    //# var geometryTypes = Meta.GeometryTypes.Map(t => t.Name);\n    //# var specialSimpleTypes = new[] { \"bool\", \"char\", \"string\", \"Type\", \"Guid\", \"Symbol\" };\n    //# var structTypes = new List<string>();\n    public partial interface ICoder\n    {\n        #region Struct Types\n\n        //# foreach (var type in specialSimpleTypes.Concat(directlyCodeableTypes)) { structTypes.Add(type);\n        //# var name = Meta.GetXmlTypeName(type);\n        void Code__name__(ref __type__ value);\n        //# }\n\n        #endregion\n\n        #region Tensors\n\n        //# foreach (var t in geometryTypes) structTypes.Add(t);\n        //# var simpleTypes = directlyCodeableTypes.Concat(specialSimpleTypes).Concat(geometryTypes);\n        //# var genericTensorTypes = new[] { \"Vector\", \"Matrix\", \"Volume\", \"Tensor\" };\n        //# var genericTensorSizes = new[] { \"long\", \"V2l\", \"V3l\", \"long[]\" };\n        //# genericTensorTypes.ForEach((tt, ti) => {\n        //#     var ts = genericTensorSizes[ti];\n        //#     simpleTypes.ForEach((t, i) => {\n        //#         var type = tt + \"<\" + t + \">\";\n        //#         structTypes.Add(type);\n        //# var name = Meta.GetXmlTypeName(type);\n        void Code__name__(ref __type__ value);\n        //#     });\n        //# });\n\n        #endregion\n\n        #region Arrays\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        void Code__name__(ref __t__[] value);\n        //# });\n\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[,]\");\n        void Code__name2d__(ref __t__[,] value);\n        //# var name3d = Meta.GetXmlTypeName(t + \"[,,]\");\n        void Code__name3d__(ref __t__[, ,] value);\n        //# });\n\n        #endregion\n\n        #region Jagged Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[][]\");\n        void Code__name2d__(ref __t__[][] value);\n        //# var name3d = Meta.GetXmlTypeName(t + \"[][][]\");\n        void Code__name3d__(ref __t__[][][] value);\n        //# });\n\n        #endregion\n\n        #region Lists\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        void Code__name__(ref List<__t__> value);\n        //# });\n\n        #endregion\n\n        #region Geometry Types\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"Double\" : \"Float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        void CodeCircle2__tc__(ref Circle2__tc__ v);\n        void CodeLine2__tc__(ref Line2__tc__ v);\n        void CodeLine3__tc__(ref Line3__tc__ v);\n        void CodePlane2__tc__(ref Plane2__tc__ v);\n        void CodePlane3__tc__(ref Plane3__tc__ v);\n        void CodePlaneWithPoint3__tc__(ref PlaneWithPoint3__tc__ v);\n        void CodeQuad2__tc__(ref Quad2__tc__ v);\n        void CodeQuad3__tc__(ref Quad3__tc__ v);\n        void CodeRay2__tc__(ref Ray2__tc__ v);\n        void CodeRay3__tc__(ref Ray3__tc__ v);\n        void CodeSphere3__tc__(ref Sphere3__tc__ v);\n        void CodeTriangle2__tc__(ref Triangle2__tc__ v);\n        void CodeTriangle3__tc__(ref Triangle3__tc__ v);\n\n        //# }\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/IFieldCodeable.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// A field coder defines the name of a field and an associated coding\n    /// function which is used for both reading and writing the field.\n    /// </summary>\n    public struct FieldCoder\n    {\n        readonly int m_order;\n        string m_name;\n        readonly int m_minVersion;\n        readonly int m_maxVersion;\n        Action<ICoder, object> m_code;\n\n        #region Constructors\n\n        public FieldCoder(int order, string name,\n                          Action<ICoder, object> code)\n            : this(order, name, 0, int.MaxValue, code)\n        { }\n\n\n        /// <summary>\n        /// Defines a FieldCoder that is only used for objects with version\n        /// numbers inside the inclusive interval\n        /// [minVersionInclusive, maxVersionInclusive].\n        /// </summary>\n        public FieldCoder(int order, string name, int minVersionInclusive, int maxVersionInclusive,\n                          Action<ICoder, object> code)\n        {\n            m_order = order; m_name = name;\n            m_minVersion = minVersionInclusive; m_maxVersion = maxVersionInclusive;\n            m_code = code;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly int Order { get { return m_order; } }\n        public string Name { readonly get { return m_name; } set { m_name = value; } }\n        public readonly int MinVersion { get { return m_minVersion; } }\n        public readonly int MaxVersion { get { return m_maxVersion; } }\n        public Action<ICoder, object> Code { readonly get { return m_code; } set { m_code = value; } }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// A field-codeable needs to supply an array of <see cref=\"FieldCoder\"/>s.\n    /// </summary>\n    public interface IFieldCodeable\n    {\n        /// <summary>\n        /// Supply a <see cref=\"FieldCoder\"/>s for each field that needs to\n        /// be coded. Note that this function is normally only called once\n        /// for each type, when the first instance of this type is encountered.\n        /// </summary>\n        IEnumerable<FieldCoder> GetFieldCoders(int coderVersion);\n    }\n\n    #region FieldCoderExtensions\n\n    public static class IEnumerableOfFieldCoderExtensions\n    {\n        /// <summary>\n        /// This extension is necessary to renumber the relative order\n        /// values of the base class, if a derived class adds additional\n        /// field coders. The standard usages is:\n        /// <code>\n        /// base.GetFieldCoders().Base().Concat(additionalFieldCoders)\n        /// </code>\n        /// </summary>\n        public static IEnumerable<FieldCoder> Base(\n            this IEnumerable<FieldCoder> fieldCoders)\n        {\n            if (fieldCoders.Count() == 0) return fieldCoders;\n            int max = fieldCoders.Max(fc => fc.Order) + 1;\n            return from fc in fieldCoders\n                   select new FieldCoder(fc.Order - max, fc.Name, fc.MinVersion, fc.MaxVersion, fc.Code);\n        }\n    }\n\n    #endregion\n\n    #region FieldCoderArray\n\n    internal static class FieldCoderArray\n    {\n        private static readonly object s_lock = new object();\n        private static readonly Dictionary<(int, Type, int), FieldCoder[]> s_fieldCoderArrayMap\n                = new Dictionary<(int, Type, int), FieldCoder[]>();\n\n        public static FieldCoder[] Get(int coderVersion, Type type, int version, IFieldCodeable fieldCodeAble)\n        {\n            var key = (coderVersion, type, version);\n            FieldCoder[] fieldCoderArray;\n            lock (s_lock)\n            {\n                if (!s_fieldCoderArrayMap.TryGetValue(key, out fieldCoderArray))\n                {\n                    fieldCoderArray = fieldCodeAble.GetFieldCoders(coderVersion)\n                        .OrderBy(fc => fc.Order)\n                        .Where(fc => fc.MinVersion <= version && version <= fc.MaxVersion)\n                        .ToArray();\n                    s_fieldCoderArrayMap[key] = fieldCoderArray;\n                }\n            }\n            return fieldCoderArray;\n        }\n\n    }\n\n    #endregion\n\n    #region FieldCoderMap\n\n    internal class FieldCoderMap : Dictionary<string, Action<ICoder, object>>\n    {\n        private static readonly object s_lock = new object();\n        private static readonly Dictionary<(int, Type, int), FieldCoderMap> s_fieldCoderMapMap\n                = new Dictionary<(int, Type, int), FieldCoderMap>();\n\n        public static FieldCoderMap Get(int coderVersion, Type type, int version, IFieldCodeable fieldCodeAble)\n        {\n            var key = (coderVersion, type, version);\n            FieldCoderMap fieldCoderMap;\n            lock (s_lock)\n            {\n                if (!s_fieldCoderMapMap.TryGetValue(key, out fieldCoderMap))\n                {\n                    fieldCoderMap = new FieldCoderMap();\n                    var fieldCoders = fieldCodeAble.GetFieldCoders(coderVersion)\n                              .Where(fc => fc.MinVersion <= version && version <= fc.MaxVersion);\n                    foreach (var fc in fieldCoders)\n                        fieldCoderMap[fc.Name] = fc.Code;\n                    s_fieldCoderMapMap[key] = fieldCoderMap;\n                }\n            }\n            return fieldCoderMap;\n        }\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/ITypedMap.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Coder\n{\n    public struct FieldType\n    {\n        private string m_name;\n        private Type m_type;\n\n        #region Constructor\n\n        public FieldType(string name, Type type)\n        {\n            m_name = name; m_type = type;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public string Name { readonly get { return m_name; } set { m_name = value; } }\n        public Type Type { readonly get { return m_type; } set { m_type = value; } }\n\n        #endregion\n    }\n\n    public interface ITypedMap\n    {\n        /// <summary>\n        /// Returns the types of all fields of the ITypedMap. Note that it is\n        /// possible that this method does not report all fields of the\n        /// concrete object it was called for. It just returns fields that are\n        /// known in all instances of this class. Also, not all of the fields\n        /// for which types are known, are present in all instances of this\n        /// class.\n        /// </summary>\n        IEnumerable<FieldType> FieldTypes { get; }\n\n        /// <summary>\n        /// Returns the number of actual fields of the concrete object.\n        /// </summary>\n        int FieldCount { get; }\n\n        /// <summary>\n        /// Returns the names of all fields of the concrete object. Note that\n        /// this can return names of fields that are not reported in\n        /// <see cref=\"FieldTypes\"/>\n        /// </summary>\n        IEnumerable<string> FieldNames { get; }\n\n        /// <summary>\n        /// This provides access to all the fields by their name.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        object this[string key] { get; set; }\n    }\n\n    #region FieldTypeMap\n\n    public class TypeOfString : Dictionary<string, Type> { }\n    public static class FieldTypeMap\n    {\n        static readonly object s_lock = new object();\n        static readonly Dictionary<Type, TypeOfString> s_fieldTypeTypeMap\n                = new Dictionary<Type, TypeOfString>();\n\n        public static TypeOfString Get(Type type, ITypedMap typedMap)\n        {\n            TypeOfString fieldTypeMap;\n            lock (s_lock)\n            {\n                if (!s_fieldTypeTypeMap.TryGetValue(type, out fieldTypeMap))\n                {\n                    fieldTypeMap = new TypeOfString();\n                    foreach (FieldType ft in typedMap.FieldTypes)\n                        fieldTypeMap[ft.Name] = ft.Type;\n                    s_fieldTypeTypeMap[type] = fieldTypeMap;\n                }\n            }\n            return fieldTypeMap;\n        }\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/NetworkOrderBinaryReader.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.IO;\nusing System.Text;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// Wrapper for class BinaryReader.\n    /// The following methods are overriden in order to\n    /// return values stored in network byte order (big-endian)\n    /// in host byte order:\n    /// \n    /// short ReadInt16()\n    /// ushort ReadUInt16()\n    /// int ReadInt32()\n    /// uint ReadUInt32()\n    /// long ReadInt64()\n    /// ulong ReadUInt64()\n    /// float ReadSingle()\n    /// double ReadDouble()\n    /// \n    /// Additional methods have been added to read\n    /// vector and color values, e.g. V3f, C4f, etc.\n    /// </summary>\n    public class NetworkOrderBinaryReader : BinaryReader\n    {\n\n        #region Constructors\n\n        public NetworkOrderBinaryReader(Stream input)\n            : base(input, Encoding.UTF8)\n        {\n        }\n\n        public NetworkOrderBinaryReader(Stream input, Encoding encoding)\n            : base(input, encoding)\n        {\n            if (encoding == Encoding.Unicode ||\n                encoding == Encoding.UTF32)\n            {\n                throw new Exception(\n                    \"Encoding '\" + encoding.EncodingName +\n                    \"' uses little-endian byte order, which \" +\n                    \"makes no sense for a network (big-endian) \" +\n                    \"binary reader.\"\n                    );\n            }\n        }\n\n        #endregion\n\n        #region Read Overrides\n\n        public override short ReadInt16()\n        {\n            return (short)((base.ReadByte() << 8) | base.ReadByte());\n        }\n\n        public override ushort ReadUInt16()\n        {\n            return (ushort)((base.ReadByte() << 8) | base.ReadByte());\n        }\n\n        public override int ReadInt32()\n        {\n            return (int)((base.ReadByte() << 24) | (base.ReadByte() << 16)\n                            | (base.ReadByte() << 8) | base.ReadByte());\n        }\n\n        public override uint ReadUInt32()\n        {\n            return (uint)((base.ReadByte() << 24) | (base.ReadByte() << 16)\n                            | (base.ReadByte() << 8) | base.ReadByte());\n        }\n\n        public override long ReadInt64()\n        {\n            return (long)(((long)base.ReadByte() << 56)\n                         | ((long)base.ReadByte() << 48)\n                         | ((long)base.ReadByte() << 40)\n                         | ((long)base.ReadByte() << 32)\n                         | ((long)base.ReadByte() << 24)\n                         | ((long)base.ReadByte() << 16)\n                         | ((long)base.ReadByte() << 8)\n                         | base.ReadByte());\n        }\n\n        public override ulong ReadUInt64()\n        {\n            return (ulong)(((long)base.ReadByte() << 56)\n                         | ((long)base.ReadByte() << 48)\n                         | ((long)base.ReadByte() << 40)\n                         | ((long)base.ReadByte() << 32)\n                         | ((long)base.ReadByte() << 24)\n                         | ((long)base.ReadByte() << 16)\n                         | ((long)base.ReadByte() << 8)\n                         | base.ReadByte());\n        }\n\n        public override float ReadSingle()\n        {\n            if (BitConverter.IsLittleEndian)\n            {\n                byte[] data = new byte[4];\n                for (int i = 3; i >= 0; i--) data[i] = base.ReadByte();\n                return BitConverter.ToSingle(data, 0);\n            }\n            else\n            {\n                return base.ReadSingle();\n            }\n        }\n\n        public override double ReadDouble()\n        {\n            if (BitConverter.IsLittleEndian)\n            {\n                byte[] data = new byte[8];\n                for (int i = 7; i >= 0; i--) data[i] = base.ReadByte();\n                return BitConverter.ToDouble(data, 0);\n            }\n            else\n            {\n                return base.ReadDouble();\n            }\n        }\n\n        #endregion\n\n        #region Read V2f\n\n        public V2f ReadV2f()\n        {\n            return new V2f(ReadSingle(), ReadSingle());\n        }\n\n        public V2f ReadV2fFrom2SignedInt8()\n        {\n            return new V2f(ReadSByte(), ReadSByte());\n        }\n\n        public V2f ReadV2fFrom2Int16()\n        {\n            return new V2f(ReadInt16(), ReadInt16());\n        }\n\n        public V2f ReadV2fFrom2Int32()\n        {\n            return new V2f(ReadInt32(), ReadInt32());\n        }\n\n        #endregion\n\n        #region Read V3f\n\n        public V3f ReadV3f()\n        {\n            return new V3f(ReadSingle(), ReadSingle(), ReadSingle());\n        }\n\n        public V3f ReadV3fFrom3SignedInt8()\n        {\n            return new V3f(ReadSByte(), ReadSByte(), ReadSByte());\n        }\n\n        public V3f ReadV3fFrom3Int16()\n        {\n            return new V3f(ReadInt16(), ReadInt16(), ReadInt16());\n        }\n\n        public V3f ReadV3fFrom3Int32()\n        {\n            return new V3f(ReadInt32(), ReadInt32(), ReadInt32());\n        }\n\n        #endregion\n\n        #region Read C3f\n\n        public C3f ReadC3f()\n        {\n            return new C3f(ReadSingle(), ReadSingle(), ReadSingle());\n        }\n\n        public C3f ReadC3fFrom3SignedInt8()\n        {\n            return new C3f(ReadSByte(), ReadSByte(), ReadSByte());\n        }\n\n        public C3f ReadC3fFrom3Int16()\n        {\n            return new C3f(ReadInt16(), ReadInt16(), ReadInt16());\n        }\n\n        public C3f ReadC3fFrom3Int32()\n        {\n            return new C3f(ReadInt32(), ReadInt32(), ReadInt32());\n        }\n\n        #endregion\n\n        #region Read C4f\n\n        public C4f ReadC4f()\n        {\n            return new C4f(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());\n        }\n\n        public C4f ReadC4fFrom4SignedInt8()\n        {\n            return new C4f(ReadSByte(), ReadSByte(), ReadSByte(), ReadSByte());\n        }\n\n        public C4f ReadC4fFrom4UInt8()\n        {\n            return new C4f(ReadByte(), ReadByte(), ReadByte(), ReadByte());\n        }\n\n        public C4f ReadC4fFrom4Int16()\n        {\n            return new C4f(ReadInt16(), ReadInt16(), ReadInt16(), ReadInt16());\n        }\n\n        public C4f ReadC4fFrom4UInt16()\n        {\n            return new C4f(ReadUInt16(), ReadUInt16(), ReadUInt16(), ReadUInt16());\n        }\n\n        public C4f ReadC4fFrom4Int32()\n        {\n            return new C4f(ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32());\n        }\n\n        public C4f ReadC4fFrom4UInt32()\n        {\n            return new C4f(ReadUInt32(), ReadUInt32(), ReadUInt32(), ReadUInt32());\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/NetworkOrderBinaryWriter.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.IO;\nusing System.Text;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// Wrapper for class BinaryWriter.\n    /// The following methods are overriden in order to\n    /// write values in network byte order (big-endian):\n    /// \n    /// void Write(short)\n    /// void Write(ushort)\n    /// void Write(int)\n    /// void Write(uint)\n    /// void Write(long)\n    /// void Write(ulong)\n    /// void Write(float)\n    /// void Write(double)\n    /// \n    /// Additional methods added:\n    /// \n    /// void Write(V2f)\n    /// void Write(V2d)\n    /// void Write(V3f)\n    /// void Write(V3d)\n    /// void Write(C3f)\n    /// void Write(C4f)\n    /// \n    /// Use Encoding.BigEndianUnicode to output strings\n    /// and characters in UTF16 using big-endian byte order.\n    /// \n    /// </summary>\n    public class NetworkOrderBinaryWriter : BinaryWriter\n    {\n        public NetworkOrderBinaryWriter(Stream output)\n            : base(output, Encoding.UTF8)\n        {\n        }\n\n        public NetworkOrderBinaryWriter(Stream output, Encoding encoding)\n            : base(output, encoding)\n        {\n            if (encoding == Encoding.Unicode ||\n                encoding == Encoding.UTF32)\n            {\n                throw new Exception(\n                    \"Encoding '\" + encoding.EncodingName +\n                    \"' uses little-endian byte order, which \" +\n                    \"makes no sense for a network (big-endian) \" +\n                    \"binary writer.\"\n                    );\n            }\n        }\n\n        public override void Write(short value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value));\n        }\n\n        public override void Write(ushort value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value));\n        }\n\n        public override void Write(int value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value));\n        }\n\n        public override void Write(uint value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value));\n        }\n\n        public override void Write(long value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value));\n        }\n\n        public override void Write(ulong value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value));\n        }\n\n        public override void Write(float value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value));\n        }\n\n        public override void Write(double value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value));\n        }\n\n        public void Write(V2f value)\n        {\n            for (int i = 0; i < 2; i++)\n                base.Write(Conversion.HostToNetworkOrder(value[i]));\n        }\n\n        public void Write(V2d value)\n        {\n            for (int i = 0; i < 2; i++)\n                base.Write(Conversion.HostToNetworkOrder(value[i]));\n        }\n\n        public void Write(V3f value)\n        {\n            for (int i = 0; i < 3; i++)\n                base.Write(Conversion.HostToNetworkOrder(value[i]));\n        }\n\n        public void Write(V3d value)\n        {\n            for (int i = 0; i < 3; i++)\n                base.Write(Conversion.HostToNetworkOrder(value[i]));\n        }\n\n        public void Write(C3f value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value.R));\n            base.Write(Conversion.HostToNetworkOrder(value.G));\n            base.Write(Conversion.HostToNetworkOrder(value.B));\n        }\n\n        public void Write(C4f value)\n        {\n            base.Write(Conversion.HostToNetworkOrder(value.R));\n            base.Write(Conversion.HostToNetworkOrder(value.G));\n            base.Write(Conversion.HostToNetworkOrder(value.B));\n            base.Write(Conversion.HostToNetworkOrder(value.A));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/RegisterTypeInfoAttribute.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// Mark all classes that should be serializable with this attribute.\n    /// The class has to inherit from Map or Instance,\n    /// or implement the IFieldCodeable interface.\n    /// </summary>\n    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct,\n                    Inherited = false, AllowMultiple = false)]\n    public sealed class RegisterTypeInfoAttribute : Attribute\n    {\n        private int m_version;\n\n        public RegisterTypeInfoAttribute()\n        {\n            m_version = 0;\n        }\n\n        public int Version\n        {\n            get { return m_version; }\n            set { m_version = value; }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/StreamCodeReader.cs",
    "content": "using System;\r\nusing System.Collections.Generic;\r\nusing System.IO;\r\nusing System.Reflection;\r\nusing System.Runtime.CompilerServices;\r\nusing System.Runtime.InteropServices;\r\nusing System.Text;\r\n\r\nnamespace Aardvark.Base.Coder\r\n{\r\n    public partial class StreamCodeReader : BinaryReader\r\n    {\r\n        private byte[] m_guidBuffer = new byte[16]; // own buffer since creator requires 16-byte length\r\n\r\n        #region Constructors\r\n\r\n        public StreamCodeReader(Stream input)\r\n            : base(input)\r\n        { }\r\n\r\n        public StreamCodeReader(Stream input, Encoding encoding)\r\n            : base(input, encoding)\r\n        { }\r\n\r\n        #endregion\r\n\r\n        #region Primitive readers\r\n\r\n        public new string ReadString()\r\n        {\r\n            return base.ReadString();\r\n        }\r\n\r\n        public Guid ReadGuid()\r\n        {\r\n            return new Guid(ReadString());\r\n        }\r\n\r\n        public Symbol ReadSymbol()\r\n        {\r\n            if (ReadBoolean())\r\n                return -Symbol.Create(ReadString());\r\n            else\r\n                return Symbol.Create(ReadString());\r\n        }\r\n\r\n        public Symbol ReadGuidSymbol()\r\n        {\r\n            Read(m_guidBuffer, 0, 16);\r\n            return Symbol.Create(new Guid(m_guidBuffer));\r\n        }\r\n\r\n        public Symbol ReadPositiveSymbol() { return Symbol.Create(ReadString()); }\r\n\r\n        #endregion\r\n\r\n        #region Read Transformations\r\n\r\n        public Euclidean3f ReadEuclidean3f() { return new Euclidean3f(ReadRot3f(), ReadV3f()); }\r\n        public Euclidean3d ReadEuclidean3d() { return new Euclidean3d(ReadRot3d(), ReadV3d()); }\r\n        public Rot2f ReadRot2f() { return new Rot2f(ReadSingle()); }\r\n        public Rot2d ReadRot2d() { return new Rot2d(ReadDouble()); }\r\n        public Rot3f ReadRot3f() { return new Rot3f(ReadSingle(), ReadV3f()); }\r\n        public Rot3d ReadRot3d() { return new Rot3d(ReadDouble(), ReadV3d()); }\r\n        public Scale3f ReadScale3f() { return new Scale3f(ReadV3f()); }\r\n        public Scale3d ReadScale3d() { return new Scale3d(ReadV3d()); }\r\n        public Shift3f ReadShift3f() { return new Shift3f(ReadV3f()); }\r\n        public Shift3d ReadShift3d() { return new Shift3d(ReadV3d()); }\r\n        public Similarity3f ReadSimilarity3f() { return new Similarity3f(ReadSingle(), ReadEuclidean3f()); }\r\n        public Similarity3d ReadSimilarity3d() { return new Similarity3d(ReadDouble(), ReadEuclidean3d()); }\r\n        public Trafo2f ReadTrafo2f() { return new Trafo2f(ReadM33f(), ReadM33f()); }\r\n        public Trafo2d ReadTrafo2d() { return new Trafo2d(ReadM33d(), ReadM33d()); }\r\n        public Trafo3f ReadTrafo3f() { return new Trafo3f(ReadM44f(), ReadM44f()); }\r\n        public Trafo3d ReadTrafo3d() { return new Trafo3d(ReadM44d(), ReadM44d()); }\r\n\r\n        #endregion\r\n\r\n        #region Read Arrays and Lists\r\n\r\n        public long ReadArray(byte[] array, long index, long count)\r\n        {\r\n            if (count < 1) return 0;\r\n            return (long)Read(array, (int)index, (int)count);\r\n        }\r\n\r\n#if !NET6_0_OR_GREATER\r\n        [StructLayout(LayoutKind.Explicit)]\r\n        struct ByteArrayUnion\r\n        {\r\n            [FieldOffset(0)]\r\n            public byte[] bytes;\r\n            [FieldOffset(0)]\r\n            public Array structs;\r\n        }\r\n\r\n        private static readonly IntPtr s_byteId = GetTypeIdUncached<byte>();\r\n        private static IntPtr GetTypeIdUncached<T>() where T : struct\r\n        {\r\n            var gcHandle = GCHandle.Alloc(new T[1], GCHandleType.Pinned);\r\n            var typeField = gcHandle.AddrOfPinnedObject() - 2 * IntPtr.Size;\r\n            var typeId = Marshal.ReadIntPtr(typeField);\r\n            gcHandle.Free();\r\n            return typeId;\r\n        }\r\n#endif\r\n\r\n        public long ReadArray<T>(T[] array, long index, long count)\r\n            where T : struct\r\n        {\r\n            if (count < 1) return 0;\r\n\r\n#if NET6_0_OR_GREATER\r\n            var span = MemoryMarshal.AsBytes(array.AsSpan((int)index, (int)count));\r\n\r\n            var sizeOfT = span.Length / array.Length;\r\n            var bytesToRead = span.Length;\r\n            var offset = 0;\r\n\r\n            do\r\n            {\r\n                int finished = base.Read(span);\r\n                if (finished == 0) break;\r\n                offset += finished; bytesToRead -= finished;\r\n                span = span.Slice(offset, bytesToRead);\r\n            }\r\n            while (bytesToRead > 0);\r\n                        \r\n            return offset / sizeOfT;\r\n#else\r\n            unsafe\r\n            {\r\n                var sizeOfT = Unsafe.SizeOf<T>();\r\n                var hack = new ByteArrayUnion();\r\n                hack.structs = array;\r\n\r\n                var bytesToRead = (int)(sizeOfT * count);\r\n                IntPtr byteLen = (IntPtr)(array.Length * sizeOfT);\r\n                var offset = (int)(index * sizeOfT);\r\n\r\n                fixed (byte* pBytes = hack.bytes)\r\n                {\r\n                    IntPtr* pId = (IntPtr*)(pBytes - 2 * IntPtr.Size),\r\n                            pLen = (IntPtr*)(pBytes - IntPtr.Size);\r\n                    IntPtr backupId = *pId, backupLen = *pLen;\r\n                    *pId = s_byteId; *pLen = byteLen;\r\n\r\n                    do\r\n                    {\r\n                        int finished = base.Read(hack.bytes, offset, bytesToRead);\r\n                        if (finished == 0) break;\r\n                        offset += finished; bytesToRead -= finished;\r\n                    }\r\n                    while (bytesToRead > 0);\r\n\r\n                    *pId = backupId; *pLen = backupLen;\r\n                }\r\n                return ((long)(offset / sizeOfT) - index);\r\n            }\r\n#endif\r\n        }\r\n\r\n        public long ReadArray<T>(T[,] array, long count)\r\n            where T : struct\r\n        {\r\n            if (count < 1) return 0;\r\n\r\n#if NET6_0_OR_GREATER\r\n            var sizeOfT = Unsafe.SizeOf<T>();\r\n            var span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetArrayDataReference(array), (int)count * sizeOfT);\r\n\r\n            var bytesToRead = span.Length;\r\n            var offset = 0;\r\n\r\n            do\r\n            {\r\n                int finished = base.Read(span);\r\n                if (finished == 0) break;\r\n                offset += finished; bytesToRead -= finished;\r\n                span = span.Slice(offset, bytesToRead);\r\n            }\r\n            while (bytesToRead > 0);\r\n\r\n            return offset / sizeOfT;\r\n#else\r\n            unsafe\r\n            {\r\n                var sizeOfT = Unsafe.SizeOf<T>();\r\n                var hack = new ByteArrayUnion();\r\n                hack.structs = array;\r\n\r\n                var bytesToRead = (int)(sizeOfT * count);\r\n\r\n                var skip = 2 * 2 * sizeof(int);\r\n\r\n                IntPtr byteLen = (IntPtr)(array.Length * sizeOfT + skip);\r\n                var offset = skip;\r\n\r\n                fixed (byte* pBytes = hack.bytes)\r\n                {\r\n                    IntPtr* pId = (IntPtr*)(pBytes - 2 * IntPtr.Size),\r\n                            pLen = (IntPtr*)(pBytes - IntPtr.Size);\r\n                    IntPtr backupId = *pId, backupLen = *pLen;\r\n                    *pId = s_byteId; *pLen = byteLen;\r\n\r\n                    do\r\n                    {\r\n                        int finished = base.Read(hack.bytes, offset, bytesToRead);\r\n                        if (finished == 0) break;\r\n                        offset += finished; bytesToRead -= finished;\r\n                    }\r\n                    while (bytesToRead > 0);\r\n\r\n                    *pId = backupId; *pLen = backupLen;\r\n                }\r\n                return (long)((offset - skip) / sizeOfT);\r\n            }\r\n#endif\r\n        }\r\n\r\n        public long ReadArray<T>(T[, ,] array, long count)\r\n            where T : struct\r\n        {\r\n            if (count < 1) return 0;\r\n#if NET6_0_OR_GREATER\r\n            var sizeOfT = Unsafe.SizeOf<T>();\r\n            var span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetArrayDataReference(array), (int)count * sizeOfT);\r\n\r\n            var bytesToRead = span.Length;\r\n            var offset = 0;\r\n\r\n            do\r\n            {\r\n                int finished = base.Read(span);\r\n                if (finished == 0) break;\r\n                offset += finished; bytesToRead -= finished;\r\n                span = span.Slice(offset, bytesToRead);\r\n            }\r\n            while (bytesToRead > 0);\r\n\r\n            return offset / sizeOfT;\r\n#else\r\n            unsafe\r\n            {\r\n                var sizeOfT = Unsafe.SizeOf<T>();\r\n                var hack = new ByteArrayUnion();\r\n                hack.structs = array;\r\n\r\n                var bytesToRead = (int)(sizeOfT * count);\r\n\r\n                var skip = 3 * 2 * sizeof(int);\r\n\r\n                IntPtr byteLen = (IntPtr)(array.Length * sizeOfT + skip);\r\n                var offset = skip;\r\n\r\n                fixed (byte* pBytes = hack.bytes)\r\n                {\r\n                    IntPtr* pId = (IntPtr*)(pBytes - 2 * IntPtr.Size),\r\n                            pLen = (IntPtr*)(pBytes - IntPtr.Size);\r\n                    IntPtr backupId = *pId, backupLen = *pLen;\r\n                    *pId = s_byteId; *pLen = byteLen;\r\n\r\n                    do\r\n                    {\r\n                        int finished = base.Read(hack.bytes, offset, bytesToRead);\r\n                        if (finished == 0) break;\r\n                        offset += finished; bytesToRead -= finished;\r\n                    }\r\n                    while (bytesToRead > 0);\r\n\r\n                    *pId = backupId; *pLen = backupLen;\r\n                }\r\n                return (long)((offset - skip) / sizeOfT);\r\n            }\r\n#endif\r\n        }\r\n\r\n        public int ReadList<T>(List<T> buffer, int index, int count)\r\n            where T : struct\r\n        {\r\n            var arrayField = buffer.GetType().GetField(\"_items\", BindingFlags.NonPublic | BindingFlags.Instance);\r\n            var arrayValue = (T[])arrayField.GetValue(buffer);\r\n            var sizeField = buffer.GetType().GetField(\"_size\", BindingFlags.NonPublic | BindingFlags.Instance);\r\n            sizeField.SetValue(buffer, count);\r\n            return (int)ReadArray(arrayValue, (long)index, (long)count);\r\n        }\r\n\r\n#endregion\r\n\r\n        #region Close\r\n\r\n        public override void Close()\r\n        {\r\n            base.Close();\r\n            m_guidBuffer = null;\r\n        }\r\n\r\n        #endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/StreamCodeReader_auto.cs",
    "content": "namespace Aardvark.Base.Coder\r\n{\r\n    // AUTO GENERATED CODE - DO NOT CHANGE!\r\n\r\n    public partial class StreamCodeReader\r\n    {\r\n\r\n        #region Vectors\r\n\r\n        public V2i ReadV2i()\r\n        {\r\n            return new V2i(ReadInt32(), ReadInt32());\r\n        }\r\n\r\n        public V2ui ReadV2ui()\r\n        {\r\n            return new V2ui(ReadUInt32(), ReadUInt32());\r\n        }\r\n\r\n        public V2l ReadV2l()\r\n        {\r\n            return new V2l(ReadInt64(), ReadInt64());\r\n        }\r\n\r\n        public V2f ReadV2f()\r\n        {\r\n            return new V2f(ReadSingle(), ReadSingle());\r\n        }\r\n\r\n        public V2d ReadV2d()\r\n        {\r\n            return new V2d(ReadDouble(), ReadDouble());\r\n        }\r\n\r\n        public V3i ReadV3i()\r\n        {\r\n            return new V3i(ReadInt32(), ReadInt32(), ReadInt32());\r\n        }\r\n\r\n        public V3ui ReadV3ui()\r\n        {\r\n            return new V3ui(ReadUInt32(), ReadUInt32(), ReadUInt32());\r\n        }\r\n\r\n        public V3l ReadV3l()\r\n        {\r\n            return new V3l(ReadInt64(), ReadInt64(), ReadInt64());\r\n        }\r\n\r\n        public V3f ReadV3f()\r\n        {\r\n            return new V3f(ReadSingle(), ReadSingle(), ReadSingle());\r\n        }\r\n\r\n        public V3d ReadV3d()\r\n        {\r\n            return new V3d(ReadDouble(), ReadDouble(), ReadDouble());\r\n        }\r\n\r\n        public V4i ReadV4i()\r\n        {\r\n            return new V4i(ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32());\r\n        }\r\n\r\n        public V4ui ReadV4ui()\r\n        {\r\n            return new V4ui(ReadUInt32(), ReadUInt32(), ReadUInt32(), ReadUInt32());\r\n        }\r\n\r\n        public V4l ReadV4l()\r\n        {\r\n            return new V4l(ReadInt64(), ReadInt64(), ReadInt64(), ReadInt64());\r\n        }\r\n\r\n        public V4f ReadV4f()\r\n        {\r\n            return new V4f(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());\r\n        }\r\n\r\n        public V4d ReadV4d()\r\n        {\r\n            return new V4d(ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble());\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Matrices\r\n\r\n        public M22i ReadM22i()\r\n        {\r\n            return new M22i(\r\n                ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32()\r\n                );\r\n        }\r\n\r\n        public M22l ReadM22l()\r\n        {\r\n            return new M22l(\r\n                ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64()\r\n                );\r\n        }\r\n\r\n        public M22f ReadM22f()\r\n        {\r\n            return new M22f(\r\n                ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle()\r\n                );\r\n        }\r\n\r\n        public M22d ReadM22d()\r\n        {\r\n            return new M22d(\r\n                ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble()\r\n                );\r\n        }\r\n\r\n        public M23i ReadM23i()\r\n        {\r\n            return new M23i(\r\n                ReadInt32(), ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32(), ReadInt32()\r\n                );\r\n        }\r\n\r\n        public M23l ReadM23l()\r\n        {\r\n            return new M23l(\r\n                ReadInt64(), ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64(), ReadInt64()\r\n                );\r\n        }\r\n\r\n        public M23f ReadM23f()\r\n        {\r\n            return new M23f(\r\n                ReadSingle(), ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle(), ReadSingle()\r\n                );\r\n        }\r\n\r\n        public M23d ReadM23d()\r\n        {\r\n            return new M23d(\r\n                ReadDouble(), ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble(), ReadDouble()\r\n                );\r\n        }\r\n\r\n        public M33i ReadM33i()\r\n        {\r\n            return new M33i(\r\n                ReadInt32(), ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32(), ReadInt32()\r\n                );\r\n        }\r\n\r\n        public M33l ReadM33l()\r\n        {\r\n            return new M33l(\r\n                ReadInt64(), ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64(), ReadInt64()\r\n                );\r\n        }\r\n\r\n        public M33f ReadM33f()\r\n        {\r\n            return new M33f(\r\n                ReadSingle(), ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle(), ReadSingle()\r\n                );\r\n        }\r\n\r\n        public M33d ReadM33d()\r\n        {\r\n            return new M33d(\r\n                ReadDouble(), ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble(), ReadDouble()\r\n                );\r\n        }\r\n\r\n        public M34i ReadM34i()\r\n        {\r\n            return new M34i(\r\n                ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32()\r\n                );\r\n        }\r\n\r\n        public M34l ReadM34l()\r\n        {\r\n            return new M34l(\r\n                ReadInt64(), ReadInt64(), ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64(), ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64(), ReadInt64(), ReadInt64()\r\n                );\r\n        }\r\n\r\n        public M34f ReadM34f()\r\n        {\r\n            return new M34f(\r\n                ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()\r\n                );\r\n        }\r\n\r\n        public M34d ReadM34d()\r\n        {\r\n            return new M34d(\r\n                ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble()\r\n                );\r\n        }\r\n\r\n        public M44i ReadM44i()\r\n        {\r\n            return new M44i(\r\n                ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32(), \r\n                ReadInt32(), ReadInt32(), ReadInt32(), ReadInt32()\r\n                );\r\n        }\r\n\r\n        public M44l ReadM44l()\r\n        {\r\n            return new M44l(\r\n                ReadInt64(), ReadInt64(), ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64(), ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64(), ReadInt64(), ReadInt64(), \r\n                ReadInt64(), ReadInt64(), ReadInt64(), ReadInt64()\r\n                );\r\n        }\r\n\r\n        public M44f ReadM44f()\r\n        {\r\n            return new M44f(\r\n                ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle(), \r\n                ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()\r\n                );\r\n        }\r\n\r\n        public M44d ReadM44d()\r\n        {\r\n            return new M44d(\r\n                ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble(), \r\n                ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble()\r\n                );\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Ranges and Boxes\r\n\r\n        public Range1b ReadRange1b()\r\n        {\r\n            return new Range1b(ReadByte(), ReadByte());\r\n        }\r\n\r\n        public Range1sb ReadRange1sb()\r\n        {\r\n            return new Range1sb(ReadSByte(), ReadSByte());\r\n        }\r\n\r\n        public Range1s ReadRange1s()\r\n        {\r\n            return new Range1s(ReadInt16(), ReadInt16());\r\n        }\r\n\r\n        public Range1us ReadRange1us()\r\n        {\r\n            return new Range1us(ReadUInt16(), ReadUInt16());\r\n        }\r\n\r\n        public Range1i ReadRange1i()\r\n        {\r\n            return new Range1i(ReadInt32(), ReadInt32());\r\n        }\r\n\r\n        public Range1ui ReadRange1ui()\r\n        {\r\n            return new Range1ui(ReadUInt32(), ReadUInt32());\r\n        }\r\n\r\n        public Range1l ReadRange1l()\r\n        {\r\n            return new Range1l(ReadInt64(), ReadInt64());\r\n        }\r\n\r\n        public Range1ul ReadRange1ul()\r\n        {\r\n            return new Range1ul(ReadUInt64(), ReadUInt64());\r\n        }\r\n\r\n        public Range1f ReadRange1f()\r\n        {\r\n            return new Range1f(ReadSingle(), ReadSingle());\r\n        }\r\n\r\n        public Range1d ReadRange1d()\r\n        {\r\n            return new Range1d(ReadDouble(), ReadDouble());\r\n        }\r\n\r\n        public Box2i ReadBox2i()\r\n        {\r\n            return new Box2i(ReadV2i(), ReadV2i());\r\n        }\r\n\r\n        public Box2l ReadBox2l()\r\n        {\r\n            return new Box2l(ReadV2l(), ReadV2l());\r\n        }\r\n\r\n        public Box2f ReadBox2f()\r\n        {\r\n            return new Box2f(ReadV2f(), ReadV2f());\r\n        }\r\n\r\n        public Box2d ReadBox2d()\r\n        {\r\n            return new Box2d(ReadV2d(), ReadV2d());\r\n        }\r\n\r\n        public Box3i ReadBox3i()\r\n        {\r\n            return new Box3i(ReadV3i(), ReadV3i());\r\n        }\r\n\r\n        public Box3l ReadBox3l()\r\n        {\r\n            return new Box3l(ReadV3l(), ReadV3l());\r\n        }\r\n\r\n        public Box3f ReadBox3f()\r\n        {\r\n            return new Box3f(ReadV3f(), ReadV3f());\r\n        }\r\n\r\n        public Box3d ReadBox3d()\r\n        {\r\n            return new Box3d(ReadV3d(), ReadV3d());\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Colors\r\n\r\n        public C3b ReadC3b()\r\n        {\r\n            return new C3b(ReadByte(), ReadByte(), ReadByte());\r\n        }\r\n\r\n        public C3us ReadC3us()\r\n        {\r\n            return new C3us(ReadUInt16(), ReadUInt16(), ReadUInt16());\r\n        }\r\n\r\n        public C3ui ReadC3ui()\r\n        {\r\n            return new C3ui(ReadUInt32(), ReadUInt32(), ReadUInt32());\r\n        }\r\n\r\n        public C3f ReadC3f()\r\n        {\r\n            return new C3f(ReadSingle(), ReadSingle(), ReadSingle());\r\n        }\r\n\r\n        public C3d ReadC3d()\r\n        {\r\n            return new C3d(ReadDouble(), ReadDouble(), ReadDouble());\r\n        }\r\n\r\n        public C4b ReadC4b()\r\n        {\r\n            return new C4b(ReadByte(), ReadByte(), ReadByte(), ReadByte());\r\n        }\r\n\r\n        public C4us ReadC4us()\r\n        {\r\n            return new C4us(ReadUInt16(), ReadUInt16(), ReadUInt16(), ReadUInt16());\r\n        }\r\n\r\n        public C4ui ReadC4ui()\r\n        {\r\n            return new C4ui(ReadUInt32(), ReadUInt32(), ReadUInt32(), ReadUInt32());\r\n        }\r\n\r\n        public C4f ReadC4f()\r\n        {\r\n            return new C4f(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());\r\n        }\r\n\r\n        public C4d ReadC4d()\r\n        {\r\n            return new C4d(ReadDouble(), ReadDouble(), ReadDouble(), ReadDouble());\r\n        }\r\n\r\n        #endregion\r\n\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/StreamCodeReader_template.cs",
    "content": "namespace Aardvark.Base.Coder\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# IEnumerable<string> ignoreTypes = null;\n    public partial class StreamCodeReader\n    {\n\n        #region Vectors\n\n        //# foreach (var t in Meta.VecTypes) {\n        public __t.Name__ __t.Read__()\n        {\n            return new __t.Name__(/*# t.Len.ForEach(i => {\n                */__t.FieldType.Read__()/*# }, comma); */);\n        }\n\n        //# }\n        #endregion\n\n        #region Matrices\n\n        //# foreach (var t in Meta.MatTypes) {\n        public __t.Name__ __t.Read__()\n        {\n            return new __t.Name__(/*# t.Rows.ForEach(i => { */\n                /*# t.Cols.ForEach(j => { */__t.FieldType.Read__()/*# }, comma); }, comma); */\n                );\n        }\n\n        //# }\n        #endregion\n\n        #region Ranges and Boxes\n\n        //# foreach (var t in Meta.RangeAndBoxTypes) {\n        public __t.Name__ __t.Read__()\n        {\n            return new __t.Name__(__t.LimitType.Read__(), __t.LimitType.Read__());\n        }\n\n        //# }\n        #endregion\n\n        #region Colors\n\n        //# foreach (var t in Meta.ColorTypes) {\n        public __t.Name__ __t.Read__()\n        {\n            return new __t.Name__(/*# t.Len.ForEach(i => {\n                                   */__t.FieldType.Read__()/*# }, comma); */);\n        }\n\n        //# }\n        #endregion\n\n        //# if (ignoreTypes != null) {\n        #region Arrays\n\n        //# ignoreTypes.ForEach(t => {\n        public long ReadBig(__t__[] array, long index, long count)\n        {\n            int complete = 0;\n            unsafe\n            {\n                int itemsPerBlock = c_bufferSize / sizeof(__t__);\n                while (count > 0)\n                {\n                    int blockSize = count > (long)itemsPerBlock\n                                        ? itemsPerBlock : (int)count;\n                    int request = blockSize * sizeof(__t__);\n                    int total = 0;\n                    do\n                    {\n                        int finished = Read(m_buffer, total, request);\n                        if (finished == 0) break;\n                        total += finished; request -= finished;\n                    }\n                    while (request > 0);\n                    total /= sizeof(__t__);\n                    fixed (byte* p = m_buffer)\n                    {\n                        __t__* v = (__t__*)p;\n                        for (int i = 0; i < total; i++)\n                            array[index++] = v[i];\n                    }\n                    count -= total; complete += total;\n                    if (total < blockSize) break;\n                }\n            }\n            return complete;\n        }\n\n        //# });\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# ignoreTypes.ForEach(t => {\n        public long ReadBig(__t__[,] array, long count)\n        {\n            long complete = 0;\n            unsafe\n            {\n                int itemsPerBlock = c_bufferSize / sizeof(__t__);\n                long index = 0;\n                fixed (__t__* a = array)\n                {\n                    while (count > 0)\n                    {\n                        int blockSize = count > (long)itemsPerBlock\n                                            ? itemsPerBlock : (int)count;\n                        int request = blockSize * sizeof(__t__);\n                        int total = 0;\n                        do\n                        {\n                            int finished = Read(m_buffer, total, request);\n                            if (finished == 0) break;\n                            total += finished; request -= finished;\n                        }\n                        while (request > 0);\n                        total /= sizeof(__t__);\n                        fixed (byte* p = m_buffer)\n                        {\n                            __t__* v = (__t__*)p;\n                            for (int i = 0; i < total; i++)\n                                a[index++] = v[i];\n                        }\n                        count -= total; complete += total;\n                        if (total < blockSize) break;\n                    }\n                }\n            }\n            return complete;\n        }\n\n        public long ReadBig(__t__[, ,] array, long count)\n        {\n            long complete = 0;\n            unsafe\n            {\n                int itemsPerBlock = c_bufferSize / sizeof(__t__);\n                long index = 0;\n                fixed (__t__* a = array)\n                {\n                    while (count > 0)\n                    {\n                        int blockSize = count > (long)itemsPerBlock\n                                            ? itemsPerBlock : (int)count;\n                        int request = blockSize * sizeof(__t__);\n                        int total = 0;\n                        do\n                        {\n                            int finished = Read(m_buffer, total, request);\n                            if (finished == 0) break;\n                            total += finished; request -= finished;\n                        }\n                        while (request > 0);\n                        total /= sizeof(__t__);\n                        fixed (byte* p = m_buffer)\n                        {\n                            __t__* v = (__t__*)p;\n                            for (int i = 0; i < total; i++)\n                                a[index++] = v[i];\n                        }\n                        count -= total; complete += total;\n                        if (total < blockSize) break;\n                    }\n                }\n            }\n            return complete;\n        }\n\n        //# });\n        #endregion\n\n        #region Lists\n\n        //# ignoreTypes.ForEach(t => {\n        public int Read(List<__t__> buffer, int index, int count)\n        {\n            int end = index + count;\n            while (buffer.Count < end) buffer.Add(default(__t__));\n            int complete = 0;\n            unsafe\n            {\n                var itemsPerBlock = c_bufferSize / sizeof(__t__);\n                while (count > 0)\n                {\n                    int blockSize = Fun.Min(count, itemsPerBlock);\n                    int request = blockSize * sizeof(__t__);\n                    int total = 0;\n                    do\n                    {\n                        int finished = Read(m_buffer, total, request);\n                        if (finished == 0) break;\n                        total += finished; request -= finished;\n                    }\n                    while (request > 0);\n                    total /= sizeof(__t__);\n                    fixed (byte* p = m_buffer)\n                    {\n                        __t__* v = (__t__*)p;\n                        for (int i = 0; i < total; i++)\n                            buffer[index++] = v[i];\n                    }\n                    count -= total; complete += total;\n                    if (total < blockSize) break;\n                }\n            }\n            return complete;\n        }\n\n        //# });\n        #endregion\n\n        //# } // if (ignoreTypes != null)\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/StreamCodeWriter.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace Aardvark.Base.Coder\n{\n    public partial class StreamCodeWriter : BinaryWriter\n    {\n#if !NET6_0_OR_GREATER\n        private const int c_bufferSize = 262144;\n        private byte[] m_buffer = new byte[c_bufferSize];\n#endif\n\n        #region Constructors\n\n        public StreamCodeWriter(Stream output)\n            : base(output)\n        {\n        }\n\n        public StreamCodeWriter(Stream output, Encoding encoding)\n            : base(output, encoding)\n        {\n        }\n\n        #endregion\n\n        #region Primitive writers\n\n        public new void Write(string data)\n        {\n            base.Write(data);\n        }\n\n        public void Write(Guid data)\n        {\n            Write(data.ToString());\n        }\n\n        public void Write(Symbol value)\n        {\n            if (value.IsNegative)\n            {\n                Write(true);\n                Write((-value).ToString());\n            }\n            else\n            {\n                Write(false);\n                Write(value.ToString());\n            }\n        }\n\n        public void WriteGuidSymbol(Symbol value)\n        {\n            var bytes = value.ToGuid().ToByteArray();\n            Write(bytes, 0, 16);\n        }\n\n        public void WritePositiveSymbol(Symbol value) { Write(value.ToString()); }\n\n        #endregion\n\n        #region Write Transformations\n\n        public void Write(Euclidean3f t) { Write(t.Rot); Write(t.Trans); }\n        public void Write(Euclidean3d t) { Write(t.Rot); Write(t.Trans); }\n        public void Write(Rot2f t) { Write(t.Angle); }\n        public void Write(Rot2d t) { Write(t.Angle); }\n        public void Write(Rot3f t) { Write(t.W); Write(t.V); }\n        public void Write(Rot3d t) { Write(t.W); Write(t.V); }\n        public void Write(Scale3f t) { Write(t.V); }\n        public void Write(Scale3d t) { Write(t.V); }\n        public void Write(Shift3f t) { Write(t.V); }\n        public void Write(Shift3d t) { Write(t.V); }\n        public void Write(Similarity3f t) { Write(t.Scale); Write(t.Euclidean); }\n        public void Write(Similarity3d t) { Write(t.Scale); Write(t.Euclidean); }\n        public void Write(Trafo2f t) { Write(t.Forward); Write(t.Backward); }\n        public void Write(Trafo2d t) { Write(t.Forward); Write(t.Backward); }\n        public void Write(Trafo3f t) { Write(t.Forward); Write(t.Backward); }\n        public void Write(Trafo3d t) { Write(t.Forward); Write(t.Backward); }\n\n        #endregion\n\n        #region Write Arrays and Lists\n\n#if !NET6_0_OR_GREATER\n        [StructLayout(LayoutKind.Explicit)]\n        struct ByteArrayUnion\n        {\n            [FieldOffset(0)]\n            public byte[] bytes;\n            [FieldOffset(0)]\n            public Array structs;\n        }\n#endif\n\n        public void WriteArray(byte[] array, long index, long count)\n        {\n            Write(array, (int)index, (int)count);\n        }\n\n        public void WriteArray<T>(T[] array, long index, long count)\n                    where T : struct\n        {\n            if (count < 1) return;\n\n#if NET6_0_OR_GREATER\n            var arrSpan = array.AsSpan((int)index, (int)count);\n            var byteSpan = MemoryMarshal.AsBytes(arrSpan);\n            base.Write(byteSpan);\n#else\n            unsafe\n            {\n                var sizeOfT = Unsafe.SizeOf<T>();\n\n                var hack = new ByteArrayUnion();\n                hack.structs = array;\n\n                fixed (byte* pBytes = hack.bytes)\n                {\n                    var offset = index * sizeOfT;\n\n                    int itemsPerBlock = c_bufferSize / sizeOfT;\n                    do\n                    {\n                        int blockSize = count > (long)itemsPerBlock\n                                            ? itemsPerBlock : (int)count;\n                        var byteBlockSize = blockSize * sizeOfT;\n\n                        fixed (byte* p = m_buffer)\n                        {\n                            for (int i = 0; i < byteBlockSize; i++)\n                                p[i] = pBytes[offset++];\n                        }\n                        base.Write(m_buffer, 0, byteBlockSize);\n                        count -= (long)blockSize;\n                    }\n                    while (count > 0);\n                }\n            }\n#endif\n        }\n\n        public void WriteArray<T>(T[,] array, long count)\n                    where T : struct\n        {\n            if (count < 1) return;\n#if NET6_0_OR_GREATER\n            var sizeOfT = Unsafe.SizeOf<T>();\n            var byteSpan = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetArrayDataReference(array), (int)count * sizeOfT);\n            base.Write(byteSpan);\n#else\n            unsafe\n            {\n                var sizeOfT = Unsafe.SizeOf<T>();\n\n                var hack = new ByteArrayUnion();\n                hack.structs = array;\n\n                fixed (byte* pBytes = hack.bytes)\n                {\n                    long offset = 2 * 2 * sizeof(int);\n\n                    int itemsPerBlock = c_bufferSize / sizeOfT;\n                    do\n                    {\n                        int blockSize = count > (long)itemsPerBlock\n                                            ? itemsPerBlock : (int)count;\n                        var byteBlockSize = blockSize * sizeOfT;\n\n                        fixed (byte* p = m_buffer)\n                        {\n                            for (int i = 0; i < byteBlockSize; i++)\n                                p[i] = pBytes[offset++];\n                        }\n                        base.Write(m_buffer, 0, byteBlockSize);\n                        count -= (long)blockSize;\n                    }\n                    while (count > 0);\n                }\n            }\n#endif\n        }\n\n        public void WriteArray<T>(T[, ,] array, long count)\n                    where T : struct\n        {\n            if (count < 1) return;\n#if NET6_0_OR_GREATER\n            var sizeOfT = Unsafe.SizeOf<T>();\n            var byteSpan = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetArrayDataReference(array), (int)count * sizeOfT);\n            base.Write(byteSpan);\n#else\n            unsafe\n            {\n                var sizeOfT = Unsafe.SizeOf<T>();\n\n                var hack = new ByteArrayUnion();\n                hack.structs = array;\n\n                fixed (byte* pBytes = hack.bytes)\n                {\n                    long offset = 3 * 2 * sizeof(int);\n                    \n                    int itemsPerBlock = c_bufferSize / sizeOfT;\n                    do\n                    {\n                        int blockSize = count > (long)itemsPerBlock\n                                            ? itemsPerBlock : (int)count;\n                        var byteBlockSize = blockSize * sizeOfT;\n\n                        fixed (byte* p = m_buffer)\n                        {\n                            for (int i = 0; i < byteBlockSize; i++)\n                                p[i] = pBytes[offset++];\n                        }\n                        base.Write(m_buffer, 0, byteBlockSize);\n                        count -= (long)blockSize;\n                    }\n                    while (count > 0);\n                }\n            }\n#endif\n        }\n\n        public void WriteList<T>(List<T> buffer, int index, int count)\n            where T: struct\n        {\n            var dataObjectField = buffer.GetType().GetField(\"_items\", BindingFlags.NonPublic | BindingFlags.Instance);\n            var arrayValue = (T[])dataObjectField.GetValue(buffer);\n            WriteArray(arrayValue, (long)index, (long)count);\n        }\n\n#endregion\n\n        #region Close\n\n        public override void Close()\n        {\n            base.Close();\n#if! NET6_0_OR_GREATER\n            m_buffer = null;\n#endif\n        }\n\n#endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/StreamCodeWriter_auto.cs",
    "content": "namespace Aardvark.Base.Coder\r\n{\r\n    // AUTO GENERATED CODE - DO NOT CHANGE!\r\n\r\n    public partial class StreamCodeWriter\r\n    {\r\n\r\n        #region Vectors\r\n\r\n        public void Write(V2i x)\r\n        {\r\n            Write(x.X); Write(x.Y); \r\n        }\r\n\r\n        public void Write(V2ui x)\r\n        {\r\n            Write(x.X); Write(x.Y); \r\n        }\r\n\r\n        public void Write(V2l x)\r\n        {\r\n            Write(x.X); Write(x.Y); \r\n        }\r\n\r\n        public void Write(V2f x)\r\n        {\r\n            Write(x.X); Write(x.Y); \r\n        }\r\n\r\n        public void Write(V2d x)\r\n        {\r\n            Write(x.X); Write(x.Y); \r\n        }\r\n\r\n        public void Write(V3i x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); \r\n        }\r\n\r\n        public void Write(V3ui x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); \r\n        }\r\n\r\n        public void Write(V3l x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); \r\n        }\r\n\r\n        public void Write(V3f x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); \r\n        }\r\n\r\n        public void Write(V3d x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); \r\n        }\r\n\r\n        public void Write(V4i x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); Write(x.W); \r\n        }\r\n\r\n        public void Write(V4ui x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); Write(x.W); \r\n        }\r\n\r\n        public void Write(V4l x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); Write(x.W); \r\n        }\r\n\r\n        public void Write(V4f x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); Write(x.W); \r\n        }\r\n\r\n        public void Write(V4d x)\r\n        {\r\n            Write(x.X); Write(x.Y); Write(x.Z); Write(x.W); \r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Matrices\r\n\r\n        public void Write(M22i x)\r\n        {\r\n            Write(x.M00); Write(x.M01); \r\n            Write(x.M10); Write(x.M11); \r\n        }\r\n\r\n        public void Write(M22l x)\r\n        {\r\n            Write(x.M00); Write(x.M01); \r\n            Write(x.M10); Write(x.M11); \r\n        }\r\n\r\n        public void Write(M22f x)\r\n        {\r\n            Write(x.M00); Write(x.M01); \r\n            Write(x.M10); Write(x.M11); \r\n        }\r\n\r\n        public void Write(M22d x)\r\n        {\r\n            Write(x.M00); Write(x.M01); \r\n            Write(x.M10); Write(x.M11); \r\n        }\r\n\r\n        public void Write(M23i x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); \r\n        }\r\n\r\n        public void Write(M23l x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); \r\n        }\r\n\r\n        public void Write(M23f x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); \r\n        }\r\n\r\n        public void Write(M23d x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); \r\n        }\r\n\r\n        public void Write(M33i x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); \r\n        }\r\n\r\n        public void Write(M33l x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); \r\n        }\r\n\r\n        public void Write(M33f x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); \r\n        }\r\n\r\n        public void Write(M33d x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); \r\n        }\r\n\r\n        public void Write(M34i x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); Write(x.M03); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); Write(x.M13); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); Write(x.M23); \r\n        }\r\n\r\n        public void Write(M34l x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); Write(x.M03); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); Write(x.M13); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); Write(x.M23); \r\n        }\r\n\r\n        public void Write(M34f x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); Write(x.M03); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); Write(x.M13); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); Write(x.M23); \r\n        }\r\n\r\n        public void Write(M34d x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); Write(x.M03); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); Write(x.M13); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); Write(x.M23); \r\n        }\r\n\r\n        public void Write(M44i x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); Write(x.M03); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); Write(x.M13); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); Write(x.M23); \r\n            Write(x.M30); Write(x.M31); Write(x.M32); Write(x.M33); \r\n        }\r\n\r\n        public void Write(M44l x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); Write(x.M03); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); Write(x.M13); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); Write(x.M23); \r\n            Write(x.M30); Write(x.M31); Write(x.M32); Write(x.M33); \r\n        }\r\n\r\n        public void Write(M44f x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); Write(x.M03); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); Write(x.M13); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); Write(x.M23); \r\n            Write(x.M30); Write(x.M31); Write(x.M32); Write(x.M33); \r\n        }\r\n\r\n        public void Write(M44d x)\r\n        {\r\n            Write(x.M00); Write(x.M01); Write(x.M02); Write(x.M03); \r\n            Write(x.M10); Write(x.M11); Write(x.M12); Write(x.M13); \r\n            Write(x.M20); Write(x.M21); Write(x.M22); Write(x.M23); \r\n            Write(x.M30); Write(x.M31); Write(x.M32); Write(x.M33); \r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Ranges and Boxes\r\n\r\n        public void Write(Range1b x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1sb x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1s x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1us x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1i x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1ui x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1l x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1ul x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1f x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Range1d x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Box2i x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Box2l x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Box2f x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Box2d x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Box3i x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Box3l x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Box3f x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        public void Write(Box3d x)\r\n        {\r\n            Write(x.Min); Write(x.Max);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Colors\r\n\r\n        public void Write(C3b c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); \r\n        }\r\n\r\n        public void Write(C3us c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); \r\n        }\r\n\r\n        public void Write(C3ui c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); \r\n        }\r\n\r\n        public void Write(C3f c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); \r\n        }\r\n\r\n        public void Write(C3d c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); \r\n        }\r\n\r\n        public void Write(C4b c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); Write(c.A); \r\n        }\r\n\r\n        public void Write(C4us c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); Write(c.A); \r\n        }\r\n\r\n        public void Write(C4ui c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); Write(c.A); \r\n        }\r\n\r\n        public void Write(C4f c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); Write(c.A); \r\n        }\r\n\r\n        public void Write(C4d c)\r\n        {\r\n            Write(c.R); Write(c.G); Write(c.B); Write(c.A); \r\n        }\r\n\r\n        #endregion\r\n\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/StreamCodeWriter_template.cs",
    "content": "namespace Aardvark.Base.Coder\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# IEnumerable<string> ignoreTypes = null;\n    public partial class StreamCodeWriter\n    {\n\n        #region Vectors\n\n        //# foreach (var t in Meta.VecTypes) {\n        public void Write(__t.Name__ x)\n        {\n            /*# t.Fields.ForEach(f => { */Write(x.__f__); /*# }); */\n        }\n\n        //# }\n        #endregion\n\n        #region Matrices\n\n        //# foreach (var t in Meta.MatTypes) {\n        public void Write(__t.Name__ x)\n        {\n            //# t.Rows.ForEach(i => {\n            /*# t.Cols.ForEach(j => { */Write(x.M__i____j__); /*# }); */\n            //# });\n        }\n\n        //# }\n        #endregion\n\n        #region Ranges and Boxes\n\n        //# foreach (var t in Meta.RangeAndBoxTypes) {\n        public void Write(__t.Name__ x)\n        {\n            Write(x.Min); Write(x.Max);\n        }\n\n        //# }\n        #endregion\n\n        #region Colors\n\n        //# foreach (var t in Meta.ColorTypes) {\n        public void Write(__t.Name__ c)\n        {\n            /*# t.Fields.ForEach(f => { */Write(c.__f__); /*# }); */\n        }\n\n        //# }\n        #endregion\n\n        //# if (ignoreTypes != null) {\n        #region Arrays\n\n        //# ignoreTypes.ForEach(t => {\n        public void WriteBig(__t__[] array, long index, long count)\n        {\n            unsafe\n            {\n                int itemsPerBlock = c_bufferSize / sizeof(__t__);\n                while (count > 0)\n                {\n                    int blockSize = count > (long)itemsPerBlock\n                                        ? itemsPerBlock : (int)count;\n                    // array.CopyIntoBuffer(index, blockSize, m_buffer, 0);\n                    // index += blockSize;\n                    fixed (byte* p = m_buffer)\n                    {\n                        __t__* v = (__t__*)p;\n                        for (int i = 0; i < blockSize; i++)\n                            v[i] = array[index++];\n                    }\n                    Write(m_buffer, 0, blockSize * sizeof(__t__));\n                    count -= (long)blockSize;\n                }\n            }\n        }\n\n        //# });\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# ignoreTypes.ForEach(t => {\n        public void WriteBig(__t__[,] array, long count)\n        {\n            unsafe\n            {\n                int itemsPerBlock = c_bufferSize / sizeof(__t__);\n                long index = 0;\n                fixed (__t__* a = array)\n                {\n                    while (count > 0)\n                    {\n                        int blockSize = count > (long)itemsPerBlock\n                                            ? itemsPerBlock : (int)count;\n                        fixed (byte* p = m_buffer)\n                        {\n                            __t__* v = (__t__*)p;\n                            for (int i = 0; i < blockSize; i++)\n                                v[i] = a[index++];\n                        }\n                        Write(m_buffer, 0, blockSize * sizeof(__t__));\n                        count -= (long)blockSize;\n                    }\n                }\n            }\n        }\n\n        public void WriteBig(__t__[, ,] array, long count)\n        {\n            unsafe\n            {\n                int itemsPerBlock = c_bufferSize / sizeof(__t__);\n                long index = 0;\n                fixed (__t__* a = array)\n                {\n                    while (count > 0)\n                    {\n                        int blockSize = count > (long)itemsPerBlock\n                                            ? itemsPerBlock : (int)count;\n                        fixed (byte* p = m_buffer)\n                        {\n                            __t__* v = (__t__*)p;\n                            for (int i = 0; i < blockSize; i++)\n                                v[i] = a[index++];\n                        }\n                        Write(m_buffer, 0, blockSize * sizeof(__t__));\n                        count -= (long)blockSize;\n                    }\n                }\n            }\n        }\n\n        //# });\n        #endregion\n\n        #region Lists\n\n        //# ignoreTypes.ForEach(t => {\n        public void Write(List<__t__> buffer, int index, int count)\n        {\n            unsafe\n            {\n                var itemsPerBlock = c_bufferSize / sizeof(__t__);\n                while (count > 0)\n                {\n                    int blockSize = Fun.Min(count, itemsPerBlock);\n                    fixed (byte* p = m_buffer)\n                    {\n                        __t__* v = (__t__*)p;\n                        for (int i = 0; i < blockSize; i++)\n                            v[i] = buffer[index++];\n                    }\n                    Write(m_buffer, 0, blockSize * sizeof(__t__));\n                    count -= blockSize;\n                }\n            }\n        }\n\n        //# });\n        #endregion\n\n        //# } // if (ignoreTypes != null)\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/StreamWriter2.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Text;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// Due to a bug, it is not possible to set the FormatProvider in StreamWriter constructor.\n    /// This is a workaround.\n    /// </summary>\n    public class StreamWriter2 : StreamWriter\n    {\n        //constructors from base class\n        public StreamWriter2(Stream stream)\n            : base(stream)\n        { }\n        public StreamWriter2(string path)\n            : base(path)\n        { }\n        public StreamWriter2(Stream stream, Encoding encoding)\n            : base(stream, encoding)\n        { }\n        public StreamWriter2(string path, bool append)\n            : base(path, append)\n        { }\n        public StreamWriter2(Stream stream, Encoding encoding, int bufferSize)\n            : base(stream, encoding, bufferSize)\n        { }\n        public StreamWriter2(string path, bool append, Encoding encoding)\n            : base(path, append, encoding)\n        { }\n        public StreamWriter2(string path, bool append, Encoding encoding, int bufferSize)\n            : base(path, append, encoding, bufferSize)\n        { }\n\n        //constructors from base class with additional parameter formatProvider\n        public StreamWriter2(Stream stream, IFormatProvider formatProvider, string newLine)\n            : base(stream)\n        { m_internalFormatProvider = formatProvider; NewLine = newLine; }\n        public StreamWriter2(string path, IFormatProvider formatProvider, string newLine)\n            : base(path)\n        { m_internalFormatProvider = formatProvider; NewLine = newLine; }\n        public StreamWriter2(Stream stream, Encoding encoding, IFormatProvider formatProvider, string newLine)\n            : base(stream, encoding)\n        { m_internalFormatProvider = formatProvider; NewLine = newLine; }\n        public StreamWriter2(string path, bool append, IFormatProvider formatProvider, string newLine)\n            : base(path, append)\n        { m_internalFormatProvider = formatProvider; NewLine = newLine; }\n        public StreamWriter2(Stream stream, Encoding encoding, int bufferSize, IFormatProvider formatProvider, string newLine)\n            : base(stream, encoding, bufferSize)\n        { m_internalFormatProvider = formatProvider; NewLine = newLine; }\n        public StreamWriter2(string path, bool append, Encoding encoding, IFormatProvider formatProvider, string newLine)\n            : base(path, append, encoding)\n        { m_internalFormatProvider = formatProvider; NewLine = newLine; }\n        public StreamWriter2(string path, bool append, Encoding encoding, int bufferSize, IFormatProvider formatProvider, string newLine)\n            : base(path, append, encoding, bufferSize)\n        { m_internalFormatProvider = formatProvider; NewLine = newLine; }\n\n        //hack, to change the format provider\n        protected IFormatProvider m_internalFormatProvider = null;\n\n        public override IFormatProvider FormatProvider\n        {\n            get\n            {\n                if (this.m_internalFormatProvider == null)\n                {\n                    return base.FormatProvider;\n                }\n                return this.m_internalFormatProvider;\n            }\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/SymMap.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace Aardvark.Base.Coder\n{\n    [RegisterTypeInfo]\n    public class SymMap : SymMapBase, IFieldCodeable, ITypedMap, IEquatable<SymMap>\n    {\n        protected Symbol m_guidSymbol;\n\n        #region Constructors\n\n        public SymMap()\n            : base(Symbol.Empty, new SymbolDict<object>())\n        // guidSymbol is Empty here, in order to avoid polluting the\n        // symbol table with Guids that are never used.\n        {\n            m_guidSymbol = Symbol.Empty;\n        }\n\n        public SymMap(Symbol typeName, SymbolDict<object> ht)\n            : base(typeName, ht)\n        {\n            m_guidSymbol = Symbol.CreateNewGuid();\n        }\n\n        /// <summary>\n        /// Creates a shallow copy of the supplied map, but uses entries\n        /// in the supplied override dictionary instead of map entries\n        /// where they exist.\n        /// </summary>\n        public SymMap(SymMap map, SymbolDict<object> overrides)\n            : base(map, overrides)\n        {\n            m_guidSymbol = Symbol.CreateNewGuid();\n        }\n\n        /// <summary>\n        /// Creates a shallow copy of the supplied map, but uses entries\n        /// in the supplied override dictionary instead of map entries\n        /// where they exist.\n        /// </summary>\n        public SymMap(SymMap map, SymbolDict<object> overrides, Symbol guidSymbol)\n            : base(map, overrides)\n        {\n            m_guidSymbol = guidSymbol;\n        }\n\n        public SymMap(Symbol typeName)\n            : base(typeName)\n        {\n            m_guidSymbol = Symbol.CreateNewGuid();\n        }\n\n        public SymMap(Symbol typeName, Symbol guidSymbol)\n            : base(typeName)\n        {\n            m_guidSymbol = guidSymbol;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// A unique identifier for each SymMap that can be conveniently used\n        /// as key in a dictionary.\n        /// </summary>\n        public Symbol GuidSymbol\n        {\n            get { return m_guidSymbol; }\n        }\n\n        public void CreateNewGuidSymbolIfEmpty()\n        {\n            if (m_guidSymbol == Symbol.Empty) m_guidSymbol = Symbol.CreateNewGuid();\n        }\n\n        #endregion\n\n        #region IFieldCodeable Members\n\n        /// <summary>\n        /// Note that all types that are in this set need to implement IAwakeable\n        /// and call CreateNewGuidSymbol in the Awake method.\n        /// </summary>\n        private static readonly SymbolDict<int> s_lastMapCodedVersionMap = new SymbolDict<int>\n        {\n            { \"KdTreeSet\", 3 },\n            { \"SphereSet\", 3 },\n            { \"TriangleSet\", 3 },\n        };\n\n        public IEnumerable<FieldCoder> GetFieldCoders(int coderVersion)\n        {\n            if (coderVersion > 2)\n            {\n                if (coderVersion < 4) // change to current version\n                {\n                    // legacy files that were previously derived from Map\n\n                    int lastMapCodedVersion;\n                    if (s_lastMapCodedVersionMap.TryGetValue(m_typeName, out lastMapCodedVersion)\n                        && lastMapCodedVersion >= coderVersion)\n                    {\n                        if (m_typeName == this.GetType().GetCanonicalName()) return Array.Empty<FieldCoder>();\n                        return new FieldCoder[]\n                        {\n                           new FieldCoder(0, \"TypeName\", (c, o) => c.CodePositiveSymbol(ref ((SymMap)o).m_typeName)),\n                        };\n                    }\n                }\n\n                if (m_typeName == this.GetType().GetCanonicalName())\n                {\n                    return new FieldCoder[]\n                    {\n                        new FieldCoder(0, \"Guid\", (c, o) => c.CodeGuidSymbol(ref ((SymMap)o).m_guidSymbol)),\n                    };\n                }\n                else\n                {\n                    return new FieldCoder[]\n                    {\n                        new FieldCoder(0, \"TypeName\", (c, o) => c.CodePositiveSymbol(ref ((SymMap)o).m_typeName)),\n                        new FieldCoder(1, \"Guid\", (c, o) => c.CodeGuidSymbol(ref ((SymMap)o).m_guidSymbol)),\n                    };\n                }\n            }\n\n            if (m_typeName == this.GetType().GetCanonicalName()) return Array.Empty<FieldCoder>();\n\n            return new FieldCoder[]\n            {\n                new FieldCoder(0, \"TypeName\", (c, o) =>\n                    {\n                        if (c.IsReading)\n                        {\n                            string typeName = null;\n                            c.CodeString(ref typeName);\n                            (((SymMap)o).m_typeName) = Symbol.Create(typeName);\n                        }\n                        else\n                        {\n                            string typeName = (((SymMap)o).m_typeName).ToString();\n                            c.CodeString(ref typeName);\n                        }\n                    }),\n                new FieldCoder(0, \"Guid\", (c, o) =>\n                    {\n                        if (c.IsReading)\n                        {\n                            string guid = null;\n                            c.CodeString(ref guid);\n                            (((SymMap)o).m_guidSymbol) = Symbol.Create(guid);\n                        }\n                        else\n                        {\n                            string guid = (((SymMap)o).m_guidSymbol).ToString();\n                            c.CodeString(ref guid);\n                        }\n                    }),\n            };\n        }\n\n        #endregion\n\n        #region ITypedMap Members\n\n        public IEnumerable<FieldType> FieldTypes\n        {\n            get\n            {\n                Type type = this.GetType();\n\n                PropertyInfo[] propertyInfos = type.GetProperties();\n\n                foreach (PropertyInfo pi in propertyInfos)\n                {\n                    string name = pi.Name;\n                    Type propertyType = pi.PropertyType;\n                    yield return new FieldType(name, propertyType);\n                }\n            }\n        }\n\n        public int FieldCount { get { return m_ht.Count; } }\n\n        private IEnumerable<string> FieldNamesUnsorted\n        {\n            get { foreach (var k in m_ht.Keys) yield return k.ToString(); }\n        }\n\n        public IEnumerable<string> FieldNames\n        {\n            get { return FieldNamesUnsorted.OrderBy(k => k); }\n        }\n\n        #endregion\n\n        #region IEquatable<SymMap> Members\n\n        public bool Equals(SymMap other)\n        {\n            return this == other;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/TypeCoder.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// This associates a type with a reading function and a writing\n    /// action for the type.\n    /// </summary>\n    public readonly struct TypeReaderAndWriter\n    {\n        public readonly Type Type;\n        public readonly Func<IReadingCoder, object> Reader;\n        public readonly Action<IWritingCoder, object> Writer;\n\n        public TypeReaderAndWriter(Type type,\n                Func<IReadingCoder, object> reader,\n                Action<IWritingCoder, object> writer\n                )\n        {\n            Type = type; Reader = reader;  Writer = writer;\n        }\n    }\n\n    /// <summary>\n    /// This class provides coding of primitive types. Reading and Witing of\n    /// additional primitive types can be registered via the static\n    /// <see cref=\"Add\"/> methods.\n    /// </summary>\n    public static partial class TypeCoder\n    {\n        static readonly Dictionary<Type, Action<IWritingCoder, Type, object>> s_genericWriterMap =\n                                new Dictionary<Type, Action<IWritingCoder, Type, object>>\n        {\n            { typeof(List<>),       (c,t,o) => { var v = (IList)o; c.Code(t, ref v); } },\n            { typeof(Dictionary<,>),(c,t,o) => { var v = (IDictionary)o; c.Code(t, ref v); } },\n            { typeof(Dict<,>),      (c,t,o) => { var v = (ICountableDict)o; c.Code(t, ref v); } },\n            { typeof(IntDict<>),    (c,t,o) => { var v = (ICountableDict)o; c.Code(t, ref v); } },\n            { typeof(SymbolDict<>), (c,t,o) => { var v = (ICountableDict)o; c.Code(t, ref v); } },\n            { typeof(DictSet<>),    (c,t,o) => { var v = (ICountableDictSet)o; c.Code(t, ref v); } },\n            { typeof(Vector<>),     (c,t,o) => { var v = (IArrayVector)o; c.Code(t, ref v); } },\n            { typeof(Matrix<>),     (c,t,o) => { var v = (IArrayMatrix)o; c.Code(t, ref v); } },\n            { typeof(Volume<>),     (c,t,o) => { var v = (IArrayVolume)o; c.Code(t, ref v); } },\n            { typeof(Tensor<>),     (c,t,o) => { var v = (IArrayTensorN)o; c.Code(t, ref v); } },\n            { typeof(HashSet<>),    (c,t,o) => { c.CodeHashSet(t, ref o); } },\n        };\n\n        static readonly Dictionary<Type, Func<IReadingCoder, Type, object>> s_genericReaderMap =\n                                new Dictionary<Type, Func<IReadingCoder, Type, object>>\n        {\n            { typeof(List<>),       (c,t) => { var v = default(IList); c.Code(t, ref v); return v; } },\n            { typeof(Dictionary<,>),(c,t) => { var v = default(IDictionary); c.Code(t, ref v); return v; } },\n            { typeof(Dict<,>),      (c,t) => { var v = default(ICountableDict); c.Code(t, ref v); return v; } },\n            { typeof(IntDict<>),    (c,t) => { var v = default(ICountableDict); c.Code(t, ref v); return v; } },\n            { typeof(SymbolDict<>), (c,t) => { var v = default(ICountableDict); c.Code(t, ref v); return v; } },\n            { typeof(DictSet<>),    (c,t) => { var v = default(ICountableDictSet); c.Code(t, ref v); return v; } },\n            { typeof(Vector<>),     (c,t) => { var v = default(IArrayVector); c.Code(t, ref v); return v; } },\n            { typeof(Matrix<>),     (c,t) => { var v = default(IArrayMatrix); c.Code(t, ref v); return v; } },\n            { typeof(Volume<>),     (c,t) => { var v = default(IArrayVolume); c.Code(t, ref v); return v; } },\n            { typeof(Tensor<>),     (c,t) => { var v = default(IArrayTensorN); c.Code(t, ref v); return v; } },\n            { typeof(HashSet<>),    (c,t) => { object o = null; c.CodeHashSet(t, ref o); return o; } },\n        };\n\n        public static bool WritePrimitive(IWritingCoder coder, Type type, ref object obj)\n        {\n            Action<IWritingCoder, object> writer;\n\n            if (TypeWriterMap.TryGetValue(type, out writer))\n            {\n                writer(coder, obj);\n                return true;\n            }\n            else if (type.IsEnum)\n            {\n                coder.CodeEnum(type, ref obj);\n                return true;\n            }\n            else if (type.IsArray)\n            {\n                Array a = (Array)obj;\n                coder.Code(type, ref a);\n                return true;\n            }\n            else if (type.IsGenericType)\n            {\n                Action<IWritingCoder, Type, object> genericWriter;\n                if (s_genericWriterMap.TryGetValue(\n                        type.GetGenericTypeDefinition(),\n                        out genericWriter))\n                {\n                    genericWriter(coder, type, obj);\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Write an object based on the supplied type.\n        /// </summary>\n        public static void Write(IWritingCoder coder, Type type, ref object obj)\n        {\n            if (!WritePrimitive(coder, type, ref obj))\n                coder.Code(ref obj);\n        }\n\n        /// <summary>\n        /// Read an object based on the supplied type.\n        /// </summary>\n        public static bool ReadPrimitive(IReadingCoder coder, Type type, ref object obj)\n        {\n            Func<IReadingCoder, object> reader;\n\n            if (TypeReaderMap.TryGetValue(type, out reader))\n            {\n                obj = reader(coder);\n                return true;\n            }\n            else if (type.IsEnum)\n            {\n                coder.CodeEnum(type, ref obj);\n                return true;\n            }\n            else if (type.IsArray)\n            {\n                Array a = null;\n                coder.Code(type, ref a);\n                obj = a;\n                return true;\n            }\n            else if (type.IsGenericType)\n            {\n                Func<IReadingCoder, Type, object> genericReader;\n                Type genericType = type.GetGenericTypeDefinition();\n                if (s_genericReaderMap.TryGetValue(genericType, out genericReader))\n                {\n                    obj = genericReader(coder, type);\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Read an object based on the supplied type.\n        /// </summary>\n        public static void Read(IReadingCoder coder, Type type, ref object obj)\n        {\n            if (!ReadPrimitive(coder, type, ref obj))\n                coder.Code(ref obj);\n        }\n\n        public static bool IsDirectlyCodeable(Type type)\n        {\n            if (TypeWriterMap.ContainsKey(type)) return true;\n            if (type.IsEnum) return true;\n            if (type.IsArray) return true;\n            if (type.IsGenericType)\n            {\n                Type genericType = type.GetGenericTypeDefinition();\n                if (s_genericWriterMap.ContainsKey(genericType)) return true;\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Register an array of additional read functions and write\n        /// procedures for the data types.\n        /// </summary>\n        public static void Add(IEnumerable<TypeReaderAndWriter> typeReaderAndWriters)\n        {\n            foreach (var trw in typeReaderAndWriters)\n            {\n                TypeReaderMap[trw.Type] = trw.Reader;\n                TypeWriterMap[trw.Type] = trw.Writer;\n            }\n        }\n\n        /// <summary>\n        /// Marker class signifying coding of null pointers.\n        /// </summary>\n        public static class Null\n        { }\n\n        /// <summary>\n        /// Marker class signifying coding of references.\n        /// </summary>\n        public static class Reference\n        { }\n\n        public static partial class Default\n        {\n            private static bool s_initialized = false;\n\n            public static void Init()\n            {\n                if (s_initialized) return;\n                s_initialized = true;\n\n                TypeInfo.Add(TypeCoder.Default.Reference);\n                TypeInfo.Add(TypeCoder.Default.Null);\n                TypeInfo.Add(TypeCoder.Default.Basic);\n            }\n\n            /// <summary>\n            /// The default way of encoding null pointers.\n            /// </summary>\n            public static TypeInfo[] Null = new[]\n            {\n                new TypeInfo(\"null\", typeof(TypeCoder.Null),\n                             TypeInfo.Option.Active),\n            };\n\n            public static TypeInfo[] Reference = new[]\n            {\n                new TypeInfo(\"ref\", typeof(TypeCoder.Reference),\n                             TypeInfo.Option.Active),\n            };\n\n            public static TypeInfo[] NoNull = new[]\n            {\n                new TypeInfo(\"null\", typeof(TypeCoder.Null)),\n            };\n\n            public static TypeInfo[] NoReference = new[]\n            {\n                new TypeInfo(\"ref\", typeof(TypeCoder.Reference)),\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/TypeCoder_auto.cs",
    "content": "using Aardvark.Base;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Drawing;\r\nusing System.IO;\r\n\r\nnamespace Aardvark.Base.Coder\r\n{\r\n\r\n    // AUTO GENERATED CODE - DO NOT CHANGE!\r\n\r\n\r\n    public static partial class TypeCoder\r\n    {\r\n        internal static Dictionary<Type, Action<IWritingCoder, object>> TypeWriterMap =\r\n                                    new Dictionary<Type, Action<IWritingCoder, object>>\r\n        {\r\n            #region byte\r\n\r\n            { typeof(byte), (c,o) => { var v = (byte)o; c.CodeByte(ref v); } },\r\n            { typeof(byte[]), (c,o) => { var v = (byte[])o; c.CodeByteArray(ref v); } },\r\n            { typeof(List<byte>), (c,o) => { var v = (List<byte>)o; c.CodeList_of_Byte_(ref v); } },\r\n\r\n            { typeof(Vector<byte>), (c,o) => { var v = (Vector<byte>)o; c.CodeVector_of_Byte_(ref v); } },\r\n            { typeof(Vector<byte>[]), (c,o) => { var v = (Vector<byte>[])o; c.CodeVector_of_Byte_Array(ref v); } },\r\n            { typeof(List<Vector<byte>>), (c,o) => { var v = (List<Vector<byte>>)o; c.CodeList_of_Vector_of_Byte__(ref v); } },\r\n\r\n            { typeof(Matrix<byte>), (c,o) => { var v = (Matrix<byte>)o; c.CodeMatrix_of_Byte_(ref v); } },\r\n            { typeof(Matrix<byte>[]), (c,o) => { var v = (Matrix<byte>[])o; c.CodeMatrix_of_Byte_Array(ref v); } },\r\n            { typeof(List<Matrix<byte>>), (c,o) => { var v = (List<Matrix<byte>>)o; c.CodeList_of_Matrix_of_Byte__(ref v); } },\r\n\r\n            { typeof(Volume<byte>), (c,o) => { var v = (Volume<byte>)o; c.CodeVolume_of_Byte_(ref v); } },\r\n            { typeof(Volume<byte>[]), (c,o) => { var v = (Volume<byte>[])o; c.CodeVolume_of_Byte_Array(ref v); } },\r\n            { typeof(List<Volume<byte>>), (c,o) => { var v = (List<Volume<byte>>)o; c.CodeList_of_Volume_of_Byte__(ref v); } },\r\n\r\n            { typeof(Tensor<byte>), (c,o) => { var v = (Tensor<byte>)o; c.CodeTensor_of_Byte_(ref v); } },\r\n            { typeof(Tensor<byte>[]), (c,o) => { var v = (Tensor<byte>[])o; c.CodeTensor_of_Byte_Array(ref v); } },\r\n            { typeof(List<Tensor<byte>>), (c,o) => { var v = (List<Tensor<byte>>)o; c.CodeList_of_Tensor_of_Byte__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region sbyte\r\n\r\n            { typeof(sbyte), (c,o) => { var v = (sbyte)o; c.CodeSByte(ref v); } },\r\n            { typeof(sbyte[]), (c,o) => { var v = (sbyte[])o; c.CodeSByteArray(ref v); } },\r\n            { typeof(List<sbyte>), (c,o) => { var v = (List<sbyte>)o; c.CodeList_of_SByte_(ref v); } },\r\n\r\n            { typeof(Vector<sbyte>), (c,o) => { var v = (Vector<sbyte>)o; c.CodeVector_of_SByte_(ref v); } },\r\n            { typeof(Vector<sbyte>[]), (c,o) => { var v = (Vector<sbyte>[])o; c.CodeVector_of_SByte_Array(ref v); } },\r\n            { typeof(List<Vector<sbyte>>), (c,o) => { var v = (List<Vector<sbyte>>)o; c.CodeList_of_Vector_of_SByte__(ref v); } },\r\n\r\n            { typeof(Matrix<sbyte>), (c,o) => { var v = (Matrix<sbyte>)o; c.CodeMatrix_of_SByte_(ref v); } },\r\n            { typeof(Matrix<sbyte>[]), (c,o) => { var v = (Matrix<sbyte>[])o; c.CodeMatrix_of_SByte_Array(ref v); } },\r\n            { typeof(List<Matrix<sbyte>>), (c,o) => { var v = (List<Matrix<sbyte>>)o; c.CodeList_of_Matrix_of_SByte__(ref v); } },\r\n\r\n            { typeof(Volume<sbyte>), (c,o) => { var v = (Volume<sbyte>)o; c.CodeVolume_of_SByte_(ref v); } },\r\n            { typeof(Volume<sbyte>[]), (c,o) => { var v = (Volume<sbyte>[])o; c.CodeVolume_of_SByte_Array(ref v); } },\r\n            { typeof(List<Volume<sbyte>>), (c,o) => { var v = (List<Volume<sbyte>>)o; c.CodeList_of_Volume_of_SByte__(ref v); } },\r\n\r\n            { typeof(Tensor<sbyte>), (c,o) => { var v = (Tensor<sbyte>)o; c.CodeTensor_of_SByte_(ref v); } },\r\n            { typeof(Tensor<sbyte>[]), (c,o) => { var v = (Tensor<sbyte>[])o; c.CodeTensor_of_SByte_Array(ref v); } },\r\n            { typeof(List<Tensor<sbyte>>), (c,o) => { var v = (List<Tensor<sbyte>>)o; c.CodeList_of_Tensor_of_SByte__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region short\r\n\r\n            { typeof(short), (c,o) => { var v = (short)o; c.CodeShort(ref v); } },\r\n            { typeof(short[]), (c,o) => { var v = (short[])o; c.CodeShortArray(ref v); } },\r\n            { typeof(List<short>), (c,o) => { var v = (List<short>)o; c.CodeList_of_Short_(ref v); } },\r\n\r\n            { typeof(Vector<short>), (c,o) => { var v = (Vector<short>)o; c.CodeVector_of_Short_(ref v); } },\r\n            { typeof(Vector<short>[]), (c,o) => { var v = (Vector<short>[])o; c.CodeVector_of_Short_Array(ref v); } },\r\n            { typeof(List<Vector<short>>), (c,o) => { var v = (List<Vector<short>>)o; c.CodeList_of_Vector_of_Short__(ref v); } },\r\n\r\n            { typeof(Matrix<short>), (c,o) => { var v = (Matrix<short>)o; c.CodeMatrix_of_Short_(ref v); } },\r\n            { typeof(Matrix<short>[]), (c,o) => { var v = (Matrix<short>[])o; c.CodeMatrix_of_Short_Array(ref v); } },\r\n            { typeof(List<Matrix<short>>), (c,o) => { var v = (List<Matrix<short>>)o; c.CodeList_of_Matrix_of_Short__(ref v); } },\r\n\r\n            { typeof(Volume<short>), (c,o) => { var v = (Volume<short>)o; c.CodeVolume_of_Short_(ref v); } },\r\n            { typeof(Volume<short>[]), (c,o) => { var v = (Volume<short>[])o; c.CodeVolume_of_Short_Array(ref v); } },\r\n            { typeof(List<Volume<short>>), (c,o) => { var v = (List<Volume<short>>)o; c.CodeList_of_Volume_of_Short__(ref v); } },\r\n\r\n            { typeof(Tensor<short>), (c,o) => { var v = (Tensor<short>)o; c.CodeTensor_of_Short_(ref v); } },\r\n            { typeof(Tensor<short>[]), (c,o) => { var v = (Tensor<short>[])o; c.CodeTensor_of_Short_Array(ref v); } },\r\n            { typeof(List<Tensor<short>>), (c,o) => { var v = (List<Tensor<short>>)o; c.CodeList_of_Tensor_of_Short__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region ushort\r\n\r\n            { typeof(ushort), (c,o) => { var v = (ushort)o; c.CodeUShort(ref v); } },\r\n            { typeof(ushort[]), (c,o) => { var v = (ushort[])o; c.CodeUShortArray(ref v); } },\r\n            { typeof(List<ushort>), (c,o) => { var v = (List<ushort>)o; c.CodeList_of_UShort_(ref v); } },\r\n\r\n            { typeof(Vector<ushort>), (c,o) => { var v = (Vector<ushort>)o; c.CodeVector_of_UShort_(ref v); } },\r\n            { typeof(Vector<ushort>[]), (c,o) => { var v = (Vector<ushort>[])o; c.CodeVector_of_UShort_Array(ref v); } },\r\n            { typeof(List<Vector<ushort>>), (c,o) => { var v = (List<Vector<ushort>>)o; c.CodeList_of_Vector_of_UShort__(ref v); } },\r\n\r\n            { typeof(Matrix<ushort>), (c,o) => { var v = (Matrix<ushort>)o; c.CodeMatrix_of_UShort_(ref v); } },\r\n            { typeof(Matrix<ushort>[]), (c,o) => { var v = (Matrix<ushort>[])o; c.CodeMatrix_of_UShort_Array(ref v); } },\r\n            { typeof(List<Matrix<ushort>>), (c,o) => { var v = (List<Matrix<ushort>>)o; c.CodeList_of_Matrix_of_UShort__(ref v); } },\r\n\r\n            { typeof(Volume<ushort>), (c,o) => { var v = (Volume<ushort>)o; c.CodeVolume_of_UShort_(ref v); } },\r\n            { typeof(Volume<ushort>[]), (c,o) => { var v = (Volume<ushort>[])o; c.CodeVolume_of_UShort_Array(ref v); } },\r\n            { typeof(List<Volume<ushort>>), (c,o) => { var v = (List<Volume<ushort>>)o; c.CodeList_of_Volume_of_UShort__(ref v); } },\r\n\r\n            { typeof(Tensor<ushort>), (c,o) => { var v = (Tensor<ushort>)o; c.CodeTensor_of_UShort_(ref v); } },\r\n            { typeof(Tensor<ushort>[]), (c,o) => { var v = (Tensor<ushort>[])o; c.CodeTensor_of_UShort_Array(ref v); } },\r\n            { typeof(List<Tensor<ushort>>), (c,o) => { var v = (List<Tensor<ushort>>)o; c.CodeList_of_Tensor_of_UShort__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region int\r\n\r\n            { typeof(int), (c,o) => { var v = (int)o; c.CodeInt(ref v); } },\r\n            { typeof(int[]), (c,o) => { var v = (int[])o; c.CodeIntArray(ref v); } },\r\n            { typeof(List<int>), (c,o) => { var v = (List<int>)o; c.CodeList_of_Int_(ref v); } },\r\n\r\n            { typeof(Vector<int>), (c,o) => { var v = (Vector<int>)o; c.CodeVector_of_Int_(ref v); } },\r\n            { typeof(Vector<int>[]), (c,o) => { var v = (Vector<int>[])o; c.CodeVector_of_Int_Array(ref v); } },\r\n            { typeof(List<Vector<int>>), (c,o) => { var v = (List<Vector<int>>)o; c.CodeList_of_Vector_of_Int__(ref v); } },\r\n\r\n            { typeof(Matrix<int>), (c,o) => { var v = (Matrix<int>)o; c.CodeMatrix_of_Int_(ref v); } },\r\n            { typeof(Matrix<int>[]), (c,o) => { var v = (Matrix<int>[])o; c.CodeMatrix_of_Int_Array(ref v); } },\r\n            { typeof(List<Matrix<int>>), (c,o) => { var v = (List<Matrix<int>>)o; c.CodeList_of_Matrix_of_Int__(ref v); } },\r\n\r\n            { typeof(Volume<int>), (c,o) => { var v = (Volume<int>)o; c.CodeVolume_of_Int_(ref v); } },\r\n            { typeof(Volume<int>[]), (c,o) => { var v = (Volume<int>[])o; c.CodeVolume_of_Int_Array(ref v); } },\r\n            { typeof(List<Volume<int>>), (c,o) => { var v = (List<Volume<int>>)o; c.CodeList_of_Volume_of_Int__(ref v); } },\r\n\r\n            { typeof(Tensor<int>), (c,o) => { var v = (Tensor<int>)o; c.CodeTensor_of_Int_(ref v); } },\r\n            { typeof(Tensor<int>[]), (c,o) => { var v = (Tensor<int>[])o; c.CodeTensor_of_Int_Array(ref v); } },\r\n            { typeof(List<Tensor<int>>), (c,o) => { var v = (List<Tensor<int>>)o; c.CodeList_of_Tensor_of_Int__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region uint\r\n\r\n            { typeof(uint), (c,o) => { var v = (uint)o; c.CodeUInt(ref v); } },\r\n            { typeof(uint[]), (c,o) => { var v = (uint[])o; c.CodeUIntArray(ref v); } },\r\n            { typeof(List<uint>), (c,o) => { var v = (List<uint>)o; c.CodeList_of_UInt_(ref v); } },\r\n\r\n            { typeof(Vector<uint>), (c,o) => { var v = (Vector<uint>)o; c.CodeVector_of_UInt_(ref v); } },\r\n            { typeof(Vector<uint>[]), (c,o) => { var v = (Vector<uint>[])o; c.CodeVector_of_UInt_Array(ref v); } },\r\n            { typeof(List<Vector<uint>>), (c,o) => { var v = (List<Vector<uint>>)o; c.CodeList_of_Vector_of_UInt__(ref v); } },\r\n\r\n            { typeof(Matrix<uint>), (c,o) => { var v = (Matrix<uint>)o; c.CodeMatrix_of_UInt_(ref v); } },\r\n            { typeof(Matrix<uint>[]), (c,o) => { var v = (Matrix<uint>[])o; c.CodeMatrix_of_UInt_Array(ref v); } },\r\n            { typeof(List<Matrix<uint>>), (c,o) => { var v = (List<Matrix<uint>>)o; c.CodeList_of_Matrix_of_UInt__(ref v); } },\r\n\r\n            { typeof(Volume<uint>), (c,o) => { var v = (Volume<uint>)o; c.CodeVolume_of_UInt_(ref v); } },\r\n            { typeof(Volume<uint>[]), (c,o) => { var v = (Volume<uint>[])o; c.CodeVolume_of_UInt_Array(ref v); } },\r\n            { typeof(List<Volume<uint>>), (c,o) => { var v = (List<Volume<uint>>)o; c.CodeList_of_Volume_of_UInt__(ref v); } },\r\n\r\n            { typeof(Tensor<uint>), (c,o) => { var v = (Tensor<uint>)o; c.CodeTensor_of_UInt_(ref v); } },\r\n            { typeof(Tensor<uint>[]), (c,o) => { var v = (Tensor<uint>[])o; c.CodeTensor_of_UInt_Array(ref v); } },\r\n            { typeof(List<Tensor<uint>>), (c,o) => { var v = (List<Tensor<uint>>)o; c.CodeList_of_Tensor_of_UInt__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region long\r\n\r\n            { typeof(long), (c,o) => { var v = (long)o; c.CodeLong(ref v); } },\r\n            { typeof(long[]), (c,o) => { var v = (long[])o; c.CodeLongArray(ref v); } },\r\n            { typeof(List<long>), (c,o) => { var v = (List<long>)o; c.CodeList_of_Long_(ref v); } },\r\n\r\n            { typeof(Vector<long>), (c,o) => { var v = (Vector<long>)o; c.CodeVector_of_Long_(ref v); } },\r\n            { typeof(Vector<long>[]), (c,o) => { var v = (Vector<long>[])o; c.CodeVector_of_Long_Array(ref v); } },\r\n            { typeof(List<Vector<long>>), (c,o) => { var v = (List<Vector<long>>)o; c.CodeList_of_Vector_of_Long__(ref v); } },\r\n\r\n            { typeof(Matrix<long>), (c,o) => { var v = (Matrix<long>)o; c.CodeMatrix_of_Long_(ref v); } },\r\n            { typeof(Matrix<long>[]), (c,o) => { var v = (Matrix<long>[])o; c.CodeMatrix_of_Long_Array(ref v); } },\r\n            { typeof(List<Matrix<long>>), (c,o) => { var v = (List<Matrix<long>>)o; c.CodeList_of_Matrix_of_Long__(ref v); } },\r\n\r\n            { typeof(Volume<long>), (c,o) => { var v = (Volume<long>)o; c.CodeVolume_of_Long_(ref v); } },\r\n            { typeof(Volume<long>[]), (c,o) => { var v = (Volume<long>[])o; c.CodeVolume_of_Long_Array(ref v); } },\r\n            { typeof(List<Volume<long>>), (c,o) => { var v = (List<Volume<long>>)o; c.CodeList_of_Volume_of_Long__(ref v); } },\r\n\r\n            { typeof(Tensor<long>), (c,o) => { var v = (Tensor<long>)o; c.CodeTensor_of_Long_(ref v); } },\r\n            { typeof(Tensor<long>[]), (c,o) => { var v = (Tensor<long>[])o; c.CodeTensor_of_Long_Array(ref v); } },\r\n            { typeof(List<Tensor<long>>), (c,o) => { var v = (List<Tensor<long>>)o; c.CodeList_of_Tensor_of_Long__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region ulong\r\n\r\n            { typeof(ulong), (c,o) => { var v = (ulong)o; c.CodeULong(ref v); } },\r\n            { typeof(ulong[]), (c,o) => { var v = (ulong[])o; c.CodeULongArray(ref v); } },\r\n            { typeof(List<ulong>), (c,o) => { var v = (List<ulong>)o; c.CodeList_of_ULong_(ref v); } },\r\n\r\n            { typeof(Vector<ulong>), (c,o) => { var v = (Vector<ulong>)o; c.CodeVector_of_ULong_(ref v); } },\r\n            { typeof(Vector<ulong>[]), (c,o) => { var v = (Vector<ulong>[])o; c.CodeVector_of_ULong_Array(ref v); } },\r\n            { typeof(List<Vector<ulong>>), (c,o) => { var v = (List<Vector<ulong>>)o; c.CodeList_of_Vector_of_ULong__(ref v); } },\r\n\r\n            { typeof(Matrix<ulong>), (c,o) => { var v = (Matrix<ulong>)o; c.CodeMatrix_of_ULong_(ref v); } },\r\n            { typeof(Matrix<ulong>[]), (c,o) => { var v = (Matrix<ulong>[])o; c.CodeMatrix_of_ULong_Array(ref v); } },\r\n            { typeof(List<Matrix<ulong>>), (c,o) => { var v = (List<Matrix<ulong>>)o; c.CodeList_of_Matrix_of_ULong__(ref v); } },\r\n\r\n            { typeof(Volume<ulong>), (c,o) => { var v = (Volume<ulong>)o; c.CodeVolume_of_ULong_(ref v); } },\r\n            { typeof(Volume<ulong>[]), (c,o) => { var v = (Volume<ulong>[])o; c.CodeVolume_of_ULong_Array(ref v); } },\r\n            { typeof(List<Volume<ulong>>), (c,o) => { var v = (List<Volume<ulong>>)o; c.CodeList_of_Volume_of_ULong__(ref v); } },\r\n\r\n            { typeof(Tensor<ulong>), (c,o) => { var v = (Tensor<ulong>)o; c.CodeTensor_of_ULong_(ref v); } },\r\n            { typeof(Tensor<ulong>[]), (c,o) => { var v = (Tensor<ulong>[])o; c.CodeTensor_of_ULong_Array(ref v); } },\r\n            { typeof(List<Tensor<ulong>>), (c,o) => { var v = (List<Tensor<ulong>>)o; c.CodeList_of_Tensor_of_ULong__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region float\r\n\r\n            { typeof(float), (c,o) => { var v = (float)o; c.CodeFloat(ref v); } },\r\n            { typeof(float[]), (c,o) => { var v = (float[])o; c.CodeFloatArray(ref v); } },\r\n            { typeof(List<float>), (c,o) => { var v = (List<float>)o; c.CodeList_of_Float_(ref v); } },\r\n\r\n            { typeof(Vector<float>), (c,o) => { var v = (Vector<float>)o; c.CodeVector_of_Float_(ref v); } },\r\n            { typeof(Vector<float>[]), (c,o) => { var v = (Vector<float>[])o; c.CodeVector_of_Float_Array(ref v); } },\r\n            { typeof(List<Vector<float>>), (c,o) => { var v = (List<Vector<float>>)o; c.CodeList_of_Vector_of_Float__(ref v); } },\r\n\r\n            { typeof(Matrix<float>), (c,o) => { var v = (Matrix<float>)o; c.CodeMatrix_of_Float_(ref v); } },\r\n            { typeof(Matrix<float>[]), (c,o) => { var v = (Matrix<float>[])o; c.CodeMatrix_of_Float_Array(ref v); } },\r\n            { typeof(List<Matrix<float>>), (c,o) => { var v = (List<Matrix<float>>)o; c.CodeList_of_Matrix_of_Float__(ref v); } },\r\n\r\n            { typeof(Volume<float>), (c,o) => { var v = (Volume<float>)o; c.CodeVolume_of_Float_(ref v); } },\r\n            { typeof(Volume<float>[]), (c,o) => { var v = (Volume<float>[])o; c.CodeVolume_of_Float_Array(ref v); } },\r\n            { typeof(List<Volume<float>>), (c,o) => { var v = (List<Volume<float>>)o; c.CodeList_of_Volume_of_Float__(ref v); } },\r\n\r\n            { typeof(Tensor<float>), (c,o) => { var v = (Tensor<float>)o; c.CodeTensor_of_Float_(ref v); } },\r\n            { typeof(Tensor<float>[]), (c,o) => { var v = (Tensor<float>[])o; c.CodeTensor_of_Float_Array(ref v); } },\r\n            { typeof(List<Tensor<float>>), (c,o) => { var v = (List<Tensor<float>>)o; c.CodeList_of_Tensor_of_Float__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region double\r\n\r\n            { typeof(double), (c,o) => { var v = (double)o; c.CodeDouble(ref v); } },\r\n            { typeof(double[]), (c,o) => { var v = (double[])o; c.CodeDoubleArray(ref v); } },\r\n            { typeof(List<double>), (c,o) => { var v = (List<double>)o; c.CodeList_of_Double_(ref v); } },\r\n\r\n            { typeof(Vector<double>), (c,o) => { var v = (Vector<double>)o; c.CodeVector_of_Double_(ref v); } },\r\n            { typeof(Vector<double>[]), (c,o) => { var v = (Vector<double>[])o; c.CodeVector_of_Double_Array(ref v); } },\r\n            { typeof(List<Vector<double>>), (c,o) => { var v = (List<Vector<double>>)o; c.CodeList_of_Vector_of_Double__(ref v); } },\r\n\r\n            { typeof(Matrix<double>), (c,o) => { var v = (Matrix<double>)o; c.CodeMatrix_of_Double_(ref v); } },\r\n            { typeof(Matrix<double>[]), (c,o) => { var v = (Matrix<double>[])o; c.CodeMatrix_of_Double_Array(ref v); } },\r\n            { typeof(List<Matrix<double>>), (c,o) => { var v = (List<Matrix<double>>)o; c.CodeList_of_Matrix_of_Double__(ref v); } },\r\n\r\n            { typeof(Volume<double>), (c,o) => { var v = (Volume<double>)o; c.CodeVolume_of_Double_(ref v); } },\r\n            { typeof(Volume<double>[]), (c,o) => { var v = (Volume<double>[])o; c.CodeVolume_of_Double_Array(ref v); } },\r\n            { typeof(List<Volume<double>>), (c,o) => { var v = (List<Volume<double>>)o; c.CodeList_of_Volume_of_Double__(ref v); } },\r\n\r\n            { typeof(Tensor<double>), (c,o) => { var v = (Tensor<double>)o; c.CodeTensor_of_Double_(ref v); } },\r\n            { typeof(Tensor<double>[]), (c,o) => { var v = (Tensor<double>[])o; c.CodeTensor_of_Double_Array(ref v); } },\r\n            { typeof(List<Tensor<double>>), (c,o) => { var v = (List<Tensor<double>>)o; c.CodeList_of_Tensor_of_Double__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Fraction\r\n\r\n            { typeof(Fraction), (c,o) => { var v = (Fraction)o; c.CodeFraction(ref v); } },\r\n            { typeof(Fraction[]), (c,o) => { var v = (Fraction[])o; c.CodeFractionArray(ref v); } },\r\n            { typeof(List<Fraction>), (c,o) => { var v = (List<Fraction>)o; c.CodeList_of_Fraction_(ref v); } },\r\n\r\n            { typeof(Vector<Fraction>), (c,o) => { var v = (Vector<Fraction>)o; c.CodeVector_of_Fraction_(ref v); } },\r\n            { typeof(Vector<Fraction>[]), (c,o) => { var v = (Vector<Fraction>[])o; c.CodeVector_of_Fraction_Array(ref v); } },\r\n            { typeof(List<Vector<Fraction>>), (c,o) => { var v = (List<Vector<Fraction>>)o; c.CodeList_of_Vector_of_Fraction__(ref v); } },\r\n\r\n            { typeof(Matrix<Fraction>), (c,o) => { var v = (Matrix<Fraction>)o; c.CodeMatrix_of_Fraction_(ref v); } },\r\n            { typeof(Matrix<Fraction>[]), (c,o) => { var v = (Matrix<Fraction>[])o; c.CodeMatrix_of_Fraction_Array(ref v); } },\r\n            { typeof(List<Matrix<Fraction>>), (c,o) => { var v = (List<Matrix<Fraction>>)o; c.CodeList_of_Matrix_of_Fraction__(ref v); } },\r\n\r\n            { typeof(Volume<Fraction>), (c,o) => { var v = (Volume<Fraction>)o; c.CodeVolume_of_Fraction_(ref v); } },\r\n            { typeof(Volume<Fraction>[]), (c,o) => { var v = (Volume<Fraction>[])o; c.CodeVolume_of_Fraction_Array(ref v); } },\r\n            { typeof(List<Volume<Fraction>>), (c,o) => { var v = (List<Volume<Fraction>>)o; c.CodeList_of_Volume_of_Fraction__(ref v); } },\r\n\r\n            { typeof(Tensor<Fraction>), (c,o) => { var v = (Tensor<Fraction>)o; c.CodeTensor_of_Fraction_(ref v); } },\r\n            { typeof(Tensor<Fraction>[]), (c,o) => { var v = (Tensor<Fraction>[])o; c.CodeTensor_of_Fraction_Array(ref v); } },\r\n            { typeof(List<Tensor<Fraction>>), (c,o) => { var v = (List<Tensor<Fraction>>)o; c.CodeList_of_Tensor_of_Fraction__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V2i\r\n\r\n            { typeof(V2i), (c,o) => { var v = (V2i)o; c.CodeV2i(ref v); } },\r\n            { typeof(V2i[]), (c,o) => { var v = (V2i[])o; c.CodeV2iArray(ref v); } },\r\n            { typeof(List<V2i>), (c,o) => { var v = (List<V2i>)o; c.CodeList_of_V2i_(ref v); } },\r\n\r\n            { typeof(Vector<V2i>), (c,o) => { var v = (Vector<V2i>)o; c.CodeVector_of_V2i_(ref v); } },\r\n            { typeof(Vector<V2i>[]), (c,o) => { var v = (Vector<V2i>[])o; c.CodeVector_of_V2i_Array(ref v); } },\r\n            { typeof(List<Vector<V2i>>), (c,o) => { var v = (List<Vector<V2i>>)o; c.CodeList_of_Vector_of_V2i__(ref v); } },\r\n\r\n            { typeof(Matrix<V2i>), (c,o) => { var v = (Matrix<V2i>)o; c.CodeMatrix_of_V2i_(ref v); } },\r\n            { typeof(Matrix<V2i>[]), (c,o) => { var v = (Matrix<V2i>[])o; c.CodeMatrix_of_V2i_Array(ref v); } },\r\n            { typeof(List<Matrix<V2i>>), (c,o) => { var v = (List<Matrix<V2i>>)o; c.CodeList_of_Matrix_of_V2i__(ref v); } },\r\n\r\n            { typeof(Volume<V2i>), (c,o) => { var v = (Volume<V2i>)o; c.CodeVolume_of_V2i_(ref v); } },\r\n            { typeof(Volume<V2i>[]), (c,o) => { var v = (Volume<V2i>[])o; c.CodeVolume_of_V2i_Array(ref v); } },\r\n            { typeof(List<Volume<V2i>>), (c,o) => { var v = (List<Volume<V2i>>)o; c.CodeList_of_Volume_of_V2i__(ref v); } },\r\n\r\n            { typeof(Tensor<V2i>), (c,o) => { var v = (Tensor<V2i>)o; c.CodeTensor_of_V2i_(ref v); } },\r\n            { typeof(Tensor<V2i>[]), (c,o) => { var v = (Tensor<V2i>[])o; c.CodeTensor_of_V2i_Array(ref v); } },\r\n            { typeof(List<Tensor<V2i>>), (c,o) => { var v = (List<Tensor<V2i>>)o; c.CodeList_of_Tensor_of_V2i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V2l\r\n\r\n            { typeof(V2l), (c,o) => { var v = (V2l)o; c.CodeV2l(ref v); } },\r\n            { typeof(V2l[]), (c,o) => { var v = (V2l[])o; c.CodeV2lArray(ref v); } },\r\n            { typeof(List<V2l>), (c,o) => { var v = (List<V2l>)o; c.CodeList_of_V2l_(ref v); } },\r\n\r\n            { typeof(Vector<V2l>), (c,o) => { var v = (Vector<V2l>)o; c.CodeVector_of_V2l_(ref v); } },\r\n            { typeof(Vector<V2l>[]), (c,o) => { var v = (Vector<V2l>[])o; c.CodeVector_of_V2l_Array(ref v); } },\r\n            { typeof(List<Vector<V2l>>), (c,o) => { var v = (List<Vector<V2l>>)o; c.CodeList_of_Vector_of_V2l__(ref v); } },\r\n\r\n            { typeof(Matrix<V2l>), (c,o) => { var v = (Matrix<V2l>)o; c.CodeMatrix_of_V2l_(ref v); } },\r\n            { typeof(Matrix<V2l>[]), (c,o) => { var v = (Matrix<V2l>[])o; c.CodeMatrix_of_V2l_Array(ref v); } },\r\n            { typeof(List<Matrix<V2l>>), (c,o) => { var v = (List<Matrix<V2l>>)o; c.CodeList_of_Matrix_of_V2l__(ref v); } },\r\n\r\n            { typeof(Volume<V2l>), (c,o) => { var v = (Volume<V2l>)o; c.CodeVolume_of_V2l_(ref v); } },\r\n            { typeof(Volume<V2l>[]), (c,o) => { var v = (Volume<V2l>[])o; c.CodeVolume_of_V2l_Array(ref v); } },\r\n            { typeof(List<Volume<V2l>>), (c,o) => { var v = (List<Volume<V2l>>)o; c.CodeList_of_Volume_of_V2l__(ref v); } },\r\n\r\n            { typeof(Tensor<V2l>), (c,o) => { var v = (Tensor<V2l>)o; c.CodeTensor_of_V2l_(ref v); } },\r\n            { typeof(Tensor<V2l>[]), (c,o) => { var v = (Tensor<V2l>[])o; c.CodeTensor_of_V2l_Array(ref v); } },\r\n            { typeof(List<Tensor<V2l>>), (c,o) => { var v = (List<Tensor<V2l>>)o; c.CodeList_of_Tensor_of_V2l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V2f\r\n\r\n            { typeof(V2f), (c,o) => { var v = (V2f)o; c.CodeV2f(ref v); } },\r\n            { typeof(V2f[]), (c,o) => { var v = (V2f[])o; c.CodeV2fArray(ref v); } },\r\n            { typeof(List<V2f>), (c,o) => { var v = (List<V2f>)o; c.CodeList_of_V2f_(ref v); } },\r\n\r\n            { typeof(Vector<V2f>), (c,o) => { var v = (Vector<V2f>)o; c.CodeVector_of_V2f_(ref v); } },\r\n            { typeof(Vector<V2f>[]), (c,o) => { var v = (Vector<V2f>[])o; c.CodeVector_of_V2f_Array(ref v); } },\r\n            { typeof(List<Vector<V2f>>), (c,o) => { var v = (List<Vector<V2f>>)o; c.CodeList_of_Vector_of_V2f__(ref v); } },\r\n\r\n            { typeof(Matrix<V2f>), (c,o) => { var v = (Matrix<V2f>)o; c.CodeMatrix_of_V2f_(ref v); } },\r\n            { typeof(Matrix<V2f>[]), (c,o) => { var v = (Matrix<V2f>[])o; c.CodeMatrix_of_V2f_Array(ref v); } },\r\n            { typeof(List<Matrix<V2f>>), (c,o) => { var v = (List<Matrix<V2f>>)o; c.CodeList_of_Matrix_of_V2f__(ref v); } },\r\n\r\n            { typeof(Volume<V2f>), (c,o) => { var v = (Volume<V2f>)o; c.CodeVolume_of_V2f_(ref v); } },\r\n            { typeof(Volume<V2f>[]), (c,o) => { var v = (Volume<V2f>[])o; c.CodeVolume_of_V2f_Array(ref v); } },\r\n            { typeof(List<Volume<V2f>>), (c,o) => { var v = (List<Volume<V2f>>)o; c.CodeList_of_Volume_of_V2f__(ref v); } },\r\n\r\n            { typeof(Tensor<V2f>), (c,o) => { var v = (Tensor<V2f>)o; c.CodeTensor_of_V2f_(ref v); } },\r\n            { typeof(Tensor<V2f>[]), (c,o) => { var v = (Tensor<V2f>[])o; c.CodeTensor_of_V2f_Array(ref v); } },\r\n            { typeof(List<Tensor<V2f>>), (c,o) => { var v = (List<Tensor<V2f>>)o; c.CodeList_of_Tensor_of_V2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V2d\r\n\r\n            { typeof(V2d), (c,o) => { var v = (V2d)o; c.CodeV2d(ref v); } },\r\n            { typeof(V2d[]), (c,o) => { var v = (V2d[])o; c.CodeV2dArray(ref v); } },\r\n            { typeof(List<V2d>), (c,o) => { var v = (List<V2d>)o; c.CodeList_of_V2d_(ref v); } },\r\n\r\n            { typeof(Vector<V2d>), (c,o) => { var v = (Vector<V2d>)o; c.CodeVector_of_V2d_(ref v); } },\r\n            { typeof(Vector<V2d>[]), (c,o) => { var v = (Vector<V2d>[])o; c.CodeVector_of_V2d_Array(ref v); } },\r\n            { typeof(List<Vector<V2d>>), (c,o) => { var v = (List<Vector<V2d>>)o; c.CodeList_of_Vector_of_V2d__(ref v); } },\r\n\r\n            { typeof(Matrix<V2d>), (c,o) => { var v = (Matrix<V2d>)o; c.CodeMatrix_of_V2d_(ref v); } },\r\n            { typeof(Matrix<V2d>[]), (c,o) => { var v = (Matrix<V2d>[])o; c.CodeMatrix_of_V2d_Array(ref v); } },\r\n            { typeof(List<Matrix<V2d>>), (c,o) => { var v = (List<Matrix<V2d>>)o; c.CodeList_of_Matrix_of_V2d__(ref v); } },\r\n\r\n            { typeof(Volume<V2d>), (c,o) => { var v = (Volume<V2d>)o; c.CodeVolume_of_V2d_(ref v); } },\r\n            { typeof(Volume<V2d>[]), (c,o) => { var v = (Volume<V2d>[])o; c.CodeVolume_of_V2d_Array(ref v); } },\r\n            { typeof(List<Volume<V2d>>), (c,o) => { var v = (List<Volume<V2d>>)o; c.CodeList_of_Volume_of_V2d__(ref v); } },\r\n\r\n            { typeof(Tensor<V2d>), (c,o) => { var v = (Tensor<V2d>)o; c.CodeTensor_of_V2d_(ref v); } },\r\n            { typeof(Tensor<V2d>[]), (c,o) => { var v = (Tensor<V2d>[])o; c.CodeTensor_of_V2d_Array(ref v); } },\r\n            { typeof(List<Tensor<V2d>>), (c,o) => { var v = (List<Tensor<V2d>>)o; c.CodeList_of_Tensor_of_V2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V3i\r\n\r\n            { typeof(V3i), (c,o) => { var v = (V3i)o; c.CodeV3i(ref v); } },\r\n            { typeof(V3i[]), (c,o) => { var v = (V3i[])o; c.CodeV3iArray(ref v); } },\r\n            { typeof(List<V3i>), (c,o) => { var v = (List<V3i>)o; c.CodeList_of_V3i_(ref v); } },\r\n\r\n            { typeof(Vector<V3i>), (c,o) => { var v = (Vector<V3i>)o; c.CodeVector_of_V3i_(ref v); } },\r\n            { typeof(Vector<V3i>[]), (c,o) => { var v = (Vector<V3i>[])o; c.CodeVector_of_V3i_Array(ref v); } },\r\n            { typeof(List<Vector<V3i>>), (c,o) => { var v = (List<Vector<V3i>>)o; c.CodeList_of_Vector_of_V3i__(ref v); } },\r\n\r\n            { typeof(Matrix<V3i>), (c,o) => { var v = (Matrix<V3i>)o; c.CodeMatrix_of_V3i_(ref v); } },\r\n            { typeof(Matrix<V3i>[]), (c,o) => { var v = (Matrix<V3i>[])o; c.CodeMatrix_of_V3i_Array(ref v); } },\r\n            { typeof(List<Matrix<V3i>>), (c,o) => { var v = (List<Matrix<V3i>>)o; c.CodeList_of_Matrix_of_V3i__(ref v); } },\r\n\r\n            { typeof(Volume<V3i>), (c,o) => { var v = (Volume<V3i>)o; c.CodeVolume_of_V3i_(ref v); } },\r\n            { typeof(Volume<V3i>[]), (c,o) => { var v = (Volume<V3i>[])o; c.CodeVolume_of_V3i_Array(ref v); } },\r\n            { typeof(List<Volume<V3i>>), (c,o) => { var v = (List<Volume<V3i>>)o; c.CodeList_of_Volume_of_V3i__(ref v); } },\r\n\r\n            { typeof(Tensor<V3i>), (c,o) => { var v = (Tensor<V3i>)o; c.CodeTensor_of_V3i_(ref v); } },\r\n            { typeof(Tensor<V3i>[]), (c,o) => { var v = (Tensor<V3i>[])o; c.CodeTensor_of_V3i_Array(ref v); } },\r\n            { typeof(List<Tensor<V3i>>), (c,o) => { var v = (List<Tensor<V3i>>)o; c.CodeList_of_Tensor_of_V3i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V3l\r\n\r\n            { typeof(V3l), (c,o) => { var v = (V3l)o; c.CodeV3l(ref v); } },\r\n            { typeof(V3l[]), (c,o) => { var v = (V3l[])o; c.CodeV3lArray(ref v); } },\r\n            { typeof(List<V3l>), (c,o) => { var v = (List<V3l>)o; c.CodeList_of_V3l_(ref v); } },\r\n\r\n            { typeof(Vector<V3l>), (c,o) => { var v = (Vector<V3l>)o; c.CodeVector_of_V3l_(ref v); } },\r\n            { typeof(Vector<V3l>[]), (c,o) => { var v = (Vector<V3l>[])o; c.CodeVector_of_V3l_Array(ref v); } },\r\n            { typeof(List<Vector<V3l>>), (c,o) => { var v = (List<Vector<V3l>>)o; c.CodeList_of_Vector_of_V3l__(ref v); } },\r\n\r\n            { typeof(Matrix<V3l>), (c,o) => { var v = (Matrix<V3l>)o; c.CodeMatrix_of_V3l_(ref v); } },\r\n            { typeof(Matrix<V3l>[]), (c,o) => { var v = (Matrix<V3l>[])o; c.CodeMatrix_of_V3l_Array(ref v); } },\r\n            { typeof(List<Matrix<V3l>>), (c,o) => { var v = (List<Matrix<V3l>>)o; c.CodeList_of_Matrix_of_V3l__(ref v); } },\r\n\r\n            { typeof(Volume<V3l>), (c,o) => { var v = (Volume<V3l>)o; c.CodeVolume_of_V3l_(ref v); } },\r\n            { typeof(Volume<V3l>[]), (c,o) => { var v = (Volume<V3l>[])o; c.CodeVolume_of_V3l_Array(ref v); } },\r\n            { typeof(List<Volume<V3l>>), (c,o) => { var v = (List<Volume<V3l>>)o; c.CodeList_of_Volume_of_V3l__(ref v); } },\r\n\r\n            { typeof(Tensor<V3l>), (c,o) => { var v = (Tensor<V3l>)o; c.CodeTensor_of_V3l_(ref v); } },\r\n            { typeof(Tensor<V3l>[]), (c,o) => { var v = (Tensor<V3l>[])o; c.CodeTensor_of_V3l_Array(ref v); } },\r\n            { typeof(List<Tensor<V3l>>), (c,o) => { var v = (List<Tensor<V3l>>)o; c.CodeList_of_Tensor_of_V3l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V3f\r\n\r\n            { typeof(V3f), (c,o) => { var v = (V3f)o; c.CodeV3f(ref v); } },\r\n            { typeof(V3f[]), (c,o) => { var v = (V3f[])o; c.CodeV3fArray(ref v); } },\r\n            { typeof(List<V3f>), (c,o) => { var v = (List<V3f>)o; c.CodeList_of_V3f_(ref v); } },\r\n\r\n            { typeof(Vector<V3f>), (c,o) => { var v = (Vector<V3f>)o; c.CodeVector_of_V3f_(ref v); } },\r\n            { typeof(Vector<V3f>[]), (c,o) => { var v = (Vector<V3f>[])o; c.CodeVector_of_V3f_Array(ref v); } },\r\n            { typeof(List<Vector<V3f>>), (c,o) => { var v = (List<Vector<V3f>>)o; c.CodeList_of_Vector_of_V3f__(ref v); } },\r\n\r\n            { typeof(Matrix<V3f>), (c,o) => { var v = (Matrix<V3f>)o; c.CodeMatrix_of_V3f_(ref v); } },\r\n            { typeof(Matrix<V3f>[]), (c,o) => { var v = (Matrix<V3f>[])o; c.CodeMatrix_of_V3f_Array(ref v); } },\r\n            { typeof(List<Matrix<V3f>>), (c,o) => { var v = (List<Matrix<V3f>>)o; c.CodeList_of_Matrix_of_V3f__(ref v); } },\r\n\r\n            { typeof(Volume<V3f>), (c,o) => { var v = (Volume<V3f>)o; c.CodeVolume_of_V3f_(ref v); } },\r\n            { typeof(Volume<V3f>[]), (c,o) => { var v = (Volume<V3f>[])o; c.CodeVolume_of_V3f_Array(ref v); } },\r\n            { typeof(List<Volume<V3f>>), (c,o) => { var v = (List<Volume<V3f>>)o; c.CodeList_of_Volume_of_V3f__(ref v); } },\r\n\r\n            { typeof(Tensor<V3f>), (c,o) => { var v = (Tensor<V3f>)o; c.CodeTensor_of_V3f_(ref v); } },\r\n            { typeof(Tensor<V3f>[]), (c,o) => { var v = (Tensor<V3f>[])o; c.CodeTensor_of_V3f_Array(ref v); } },\r\n            { typeof(List<Tensor<V3f>>), (c,o) => { var v = (List<Tensor<V3f>>)o; c.CodeList_of_Tensor_of_V3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V3d\r\n\r\n            { typeof(V3d), (c,o) => { var v = (V3d)o; c.CodeV3d(ref v); } },\r\n            { typeof(V3d[]), (c,o) => { var v = (V3d[])o; c.CodeV3dArray(ref v); } },\r\n            { typeof(List<V3d>), (c,o) => { var v = (List<V3d>)o; c.CodeList_of_V3d_(ref v); } },\r\n\r\n            { typeof(Vector<V3d>), (c,o) => { var v = (Vector<V3d>)o; c.CodeVector_of_V3d_(ref v); } },\r\n            { typeof(Vector<V3d>[]), (c,o) => { var v = (Vector<V3d>[])o; c.CodeVector_of_V3d_Array(ref v); } },\r\n            { typeof(List<Vector<V3d>>), (c,o) => { var v = (List<Vector<V3d>>)o; c.CodeList_of_Vector_of_V3d__(ref v); } },\r\n\r\n            { typeof(Matrix<V3d>), (c,o) => { var v = (Matrix<V3d>)o; c.CodeMatrix_of_V3d_(ref v); } },\r\n            { typeof(Matrix<V3d>[]), (c,o) => { var v = (Matrix<V3d>[])o; c.CodeMatrix_of_V3d_Array(ref v); } },\r\n            { typeof(List<Matrix<V3d>>), (c,o) => { var v = (List<Matrix<V3d>>)o; c.CodeList_of_Matrix_of_V3d__(ref v); } },\r\n\r\n            { typeof(Volume<V3d>), (c,o) => { var v = (Volume<V3d>)o; c.CodeVolume_of_V3d_(ref v); } },\r\n            { typeof(Volume<V3d>[]), (c,o) => { var v = (Volume<V3d>[])o; c.CodeVolume_of_V3d_Array(ref v); } },\r\n            { typeof(List<Volume<V3d>>), (c,o) => { var v = (List<Volume<V3d>>)o; c.CodeList_of_Volume_of_V3d__(ref v); } },\r\n\r\n            { typeof(Tensor<V3d>), (c,o) => { var v = (Tensor<V3d>)o; c.CodeTensor_of_V3d_(ref v); } },\r\n            { typeof(Tensor<V3d>[]), (c,o) => { var v = (Tensor<V3d>[])o; c.CodeTensor_of_V3d_Array(ref v); } },\r\n            { typeof(List<Tensor<V3d>>), (c,o) => { var v = (List<Tensor<V3d>>)o; c.CodeList_of_Tensor_of_V3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V4i\r\n\r\n            { typeof(V4i), (c,o) => { var v = (V4i)o; c.CodeV4i(ref v); } },\r\n            { typeof(V4i[]), (c,o) => { var v = (V4i[])o; c.CodeV4iArray(ref v); } },\r\n            { typeof(List<V4i>), (c,o) => { var v = (List<V4i>)o; c.CodeList_of_V4i_(ref v); } },\r\n\r\n            { typeof(Vector<V4i>), (c,o) => { var v = (Vector<V4i>)o; c.CodeVector_of_V4i_(ref v); } },\r\n            { typeof(Vector<V4i>[]), (c,o) => { var v = (Vector<V4i>[])o; c.CodeVector_of_V4i_Array(ref v); } },\r\n            { typeof(List<Vector<V4i>>), (c,o) => { var v = (List<Vector<V4i>>)o; c.CodeList_of_Vector_of_V4i__(ref v); } },\r\n\r\n            { typeof(Matrix<V4i>), (c,o) => { var v = (Matrix<V4i>)o; c.CodeMatrix_of_V4i_(ref v); } },\r\n            { typeof(Matrix<V4i>[]), (c,o) => { var v = (Matrix<V4i>[])o; c.CodeMatrix_of_V4i_Array(ref v); } },\r\n            { typeof(List<Matrix<V4i>>), (c,o) => { var v = (List<Matrix<V4i>>)o; c.CodeList_of_Matrix_of_V4i__(ref v); } },\r\n\r\n            { typeof(Volume<V4i>), (c,o) => { var v = (Volume<V4i>)o; c.CodeVolume_of_V4i_(ref v); } },\r\n            { typeof(Volume<V4i>[]), (c,o) => { var v = (Volume<V4i>[])o; c.CodeVolume_of_V4i_Array(ref v); } },\r\n            { typeof(List<Volume<V4i>>), (c,o) => { var v = (List<Volume<V4i>>)o; c.CodeList_of_Volume_of_V4i__(ref v); } },\r\n\r\n            { typeof(Tensor<V4i>), (c,o) => { var v = (Tensor<V4i>)o; c.CodeTensor_of_V4i_(ref v); } },\r\n            { typeof(Tensor<V4i>[]), (c,o) => { var v = (Tensor<V4i>[])o; c.CodeTensor_of_V4i_Array(ref v); } },\r\n            { typeof(List<Tensor<V4i>>), (c,o) => { var v = (List<Tensor<V4i>>)o; c.CodeList_of_Tensor_of_V4i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V4l\r\n\r\n            { typeof(V4l), (c,o) => { var v = (V4l)o; c.CodeV4l(ref v); } },\r\n            { typeof(V4l[]), (c,o) => { var v = (V4l[])o; c.CodeV4lArray(ref v); } },\r\n            { typeof(List<V4l>), (c,o) => { var v = (List<V4l>)o; c.CodeList_of_V4l_(ref v); } },\r\n\r\n            { typeof(Vector<V4l>), (c,o) => { var v = (Vector<V4l>)o; c.CodeVector_of_V4l_(ref v); } },\r\n            { typeof(Vector<V4l>[]), (c,o) => { var v = (Vector<V4l>[])o; c.CodeVector_of_V4l_Array(ref v); } },\r\n            { typeof(List<Vector<V4l>>), (c,o) => { var v = (List<Vector<V4l>>)o; c.CodeList_of_Vector_of_V4l__(ref v); } },\r\n\r\n            { typeof(Matrix<V4l>), (c,o) => { var v = (Matrix<V4l>)o; c.CodeMatrix_of_V4l_(ref v); } },\r\n            { typeof(Matrix<V4l>[]), (c,o) => { var v = (Matrix<V4l>[])o; c.CodeMatrix_of_V4l_Array(ref v); } },\r\n            { typeof(List<Matrix<V4l>>), (c,o) => { var v = (List<Matrix<V4l>>)o; c.CodeList_of_Matrix_of_V4l__(ref v); } },\r\n\r\n            { typeof(Volume<V4l>), (c,o) => { var v = (Volume<V4l>)o; c.CodeVolume_of_V4l_(ref v); } },\r\n            { typeof(Volume<V4l>[]), (c,o) => { var v = (Volume<V4l>[])o; c.CodeVolume_of_V4l_Array(ref v); } },\r\n            { typeof(List<Volume<V4l>>), (c,o) => { var v = (List<Volume<V4l>>)o; c.CodeList_of_Volume_of_V4l__(ref v); } },\r\n\r\n            { typeof(Tensor<V4l>), (c,o) => { var v = (Tensor<V4l>)o; c.CodeTensor_of_V4l_(ref v); } },\r\n            { typeof(Tensor<V4l>[]), (c,o) => { var v = (Tensor<V4l>[])o; c.CodeTensor_of_V4l_Array(ref v); } },\r\n            { typeof(List<Tensor<V4l>>), (c,o) => { var v = (List<Tensor<V4l>>)o; c.CodeList_of_Tensor_of_V4l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V4f\r\n\r\n            { typeof(V4f), (c,o) => { var v = (V4f)o; c.CodeV4f(ref v); } },\r\n            { typeof(V4f[]), (c,o) => { var v = (V4f[])o; c.CodeV4fArray(ref v); } },\r\n            { typeof(List<V4f>), (c,o) => { var v = (List<V4f>)o; c.CodeList_of_V4f_(ref v); } },\r\n\r\n            { typeof(Vector<V4f>), (c,o) => { var v = (Vector<V4f>)o; c.CodeVector_of_V4f_(ref v); } },\r\n            { typeof(Vector<V4f>[]), (c,o) => { var v = (Vector<V4f>[])o; c.CodeVector_of_V4f_Array(ref v); } },\r\n            { typeof(List<Vector<V4f>>), (c,o) => { var v = (List<Vector<V4f>>)o; c.CodeList_of_Vector_of_V4f__(ref v); } },\r\n\r\n            { typeof(Matrix<V4f>), (c,o) => { var v = (Matrix<V4f>)o; c.CodeMatrix_of_V4f_(ref v); } },\r\n            { typeof(Matrix<V4f>[]), (c,o) => { var v = (Matrix<V4f>[])o; c.CodeMatrix_of_V4f_Array(ref v); } },\r\n            { typeof(List<Matrix<V4f>>), (c,o) => { var v = (List<Matrix<V4f>>)o; c.CodeList_of_Matrix_of_V4f__(ref v); } },\r\n\r\n            { typeof(Volume<V4f>), (c,o) => { var v = (Volume<V4f>)o; c.CodeVolume_of_V4f_(ref v); } },\r\n            { typeof(Volume<V4f>[]), (c,o) => { var v = (Volume<V4f>[])o; c.CodeVolume_of_V4f_Array(ref v); } },\r\n            { typeof(List<Volume<V4f>>), (c,o) => { var v = (List<Volume<V4f>>)o; c.CodeList_of_Volume_of_V4f__(ref v); } },\r\n\r\n            { typeof(Tensor<V4f>), (c,o) => { var v = (Tensor<V4f>)o; c.CodeTensor_of_V4f_(ref v); } },\r\n            { typeof(Tensor<V4f>[]), (c,o) => { var v = (Tensor<V4f>[])o; c.CodeTensor_of_V4f_Array(ref v); } },\r\n            { typeof(List<Tensor<V4f>>), (c,o) => { var v = (List<Tensor<V4f>>)o; c.CodeList_of_Tensor_of_V4f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region V4d\r\n\r\n            { typeof(V4d), (c,o) => { var v = (V4d)o; c.CodeV4d(ref v); } },\r\n            { typeof(V4d[]), (c,o) => { var v = (V4d[])o; c.CodeV4dArray(ref v); } },\r\n            { typeof(List<V4d>), (c,o) => { var v = (List<V4d>)o; c.CodeList_of_V4d_(ref v); } },\r\n\r\n            { typeof(Vector<V4d>), (c,o) => { var v = (Vector<V4d>)o; c.CodeVector_of_V4d_(ref v); } },\r\n            { typeof(Vector<V4d>[]), (c,o) => { var v = (Vector<V4d>[])o; c.CodeVector_of_V4d_Array(ref v); } },\r\n            { typeof(List<Vector<V4d>>), (c,o) => { var v = (List<Vector<V4d>>)o; c.CodeList_of_Vector_of_V4d__(ref v); } },\r\n\r\n            { typeof(Matrix<V4d>), (c,o) => { var v = (Matrix<V4d>)o; c.CodeMatrix_of_V4d_(ref v); } },\r\n            { typeof(Matrix<V4d>[]), (c,o) => { var v = (Matrix<V4d>[])o; c.CodeMatrix_of_V4d_Array(ref v); } },\r\n            { typeof(List<Matrix<V4d>>), (c,o) => { var v = (List<Matrix<V4d>>)o; c.CodeList_of_Matrix_of_V4d__(ref v); } },\r\n\r\n            { typeof(Volume<V4d>), (c,o) => { var v = (Volume<V4d>)o; c.CodeVolume_of_V4d_(ref v); } },\r\n            { typeof(Volume<V4d>[]), (c,o) => { var v = (Volume<V4d>[])o; c.CodeVolume_of_V4d_Array(ref v); } },\r\n            { typeof(List<Volume<V4d>>), (c,o) => { var v = (List<Volume<V4d>>)o; c.CodeList_of_Volume_of_V4d__(ref v); } },\r\n\r\n            { typeof(Tensor<V4d>), (c,o) => { var v = (Tensor<V4d>)o; c.CodeTensor_of_V4d_(ref v); } },\r\n            { typeof(Tensor<V4d>[]), (c,o) => { var v = (Tensor<V4d>[])o; c.CodeTensor_of_V4d_Array(ref v); } },\r\n            { typeof(List<Tensor<V4d>>), (c,o) => { var v = (List<Tensor<V4d>>)o; c.CodeList_of_Tensor_of_V4d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M22i\r\n\r\n            { typeof(M22i), (c,o) => { var v = (M22i)o; c.CodeM22i(ref v); } },\r\n            { typeof(M22i[]), (c,o) => { var v = (M22i[])o; c.CodeM22iArray(ref v); } },\r\n            { typeof(List<M22i>), (c,o) => { var v = (List<M22i>)o; c.CodeList_of_M22i_(ref v); } },\r\n\r\n            { typeof(Vector<M22i>), (c,o) => { var v = (Vector<M22i>)o; c.CodeVector_of_M22i_(ref v); } },\r\n            { typeof(Vector<M22i>[]), (c,o) => { var v = (Vector<M22i>[])o; c.CodeVector_of_M22i_Array(ref v); } },\r\n            { typeof(List<Vector<M22i>>), (c,o) => { var v = (List<Vector<M22i>>)o; c.CodeList_of_Vector_of_M22i__(ref v); } },\r\n\r\n            { typeof(Matrix<M22i>), (c,o) => { var v = (Matrix<M22i>)o; c.CodeMatrix_of_M22i_(ref v); } },\r\n            { typeof(Matrix<M22i>[]), (c,o) => { var v = (Matrix<M22i>[])o; c.CodeMatrix_of_M22i_Array(ref v); } },\r\n            { typeof(List<Matrix<M22i>>), (c,o) => { var v = (List<Matrix<M22i>>)o; c.CodeList_of_Matrix_of_M22i__(ref v); } },\r\n\r\n            { typeof(Volume<M22i>), (c,o) => { var v = (Volume<M22i>)o; c.CodeVolume_of_M22i_(ref v); } },\r\n            { typeof(Volume<M22i>[]), (c,o) => { var v = (Volume<M22i>[])o; c.CodeVolume_of_M22i_Array(ref v); } },\r\n            { typeof(List<Volume<M22i>>), (c,o) => { var v = (List<Volume<M22i>>)o; c.CodeList_of_Volume_of_M22i__(ref v); } },\r\n\r\n            { typeof(Tensor<M22i>), (c,o) => { var v = (Tensor<M22i>)o; c.CodeTensor_of_M22i_(ref v); } },\r\n            { typeof(Tensor<M22i>[]), (c,o) => { var v = (Tensor<M22i>[])o; c.CodeTensor_of_M22i_Array(ref v); } },\r\n            { typeof(List<Tensor<M22i>>), (c,o) => { var v = (List<Tensor<M22i>>)o; c.CodeList_of_Tensor_of_M22i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M22l\r\n\r\n            { typeof(M22l), (c,o) => { var v = (M22l)o; c.CodeM22l(ref v); } },\r\n            { typeof(M22l[]), (c,o) => { var v = (M22l[])o; c.CodeM22lArray(ref v); } },\r\n            { typeof(List<M22l>), (c,o) => { var v = (List<M22l>)o; c.CodeList_of_M22l_(ref v); } },\r\n\r\n            { typeof(Vector<M22l>), (c,o) => { var v = (Vector<M22l>)o; c.CodeVector_of_M22l_(ref v); } },\r\n            { typeof(Vector<M22l>[]), (c,o) => { var v = (Vector<M22l>[])o; c.CodeVector_of_M22l_Array(ref v); } },\r\n            { typeof(List<Vector<M22l>>), (c,o) => { var v = (List<Vector<M22l>>)o; c.CodeList_of_Vector_of_M22l__(ref v); } },\r\n\r\n            { typeof(Matrix<M22l>), (c,o) => { var v = (Matrix<M22l>)o; c.CodeMatrix_of_M22l_(ref v); } },\r\n            { typeof(Matrix<M22l>[]), (c,o) => { var v = (Matrix<M22l>[])o; c.CodeMatrix_of_M22l_Array(ref v); } },\r\n            { typeof(List<Matrix<M22l>>), (c,o) => { var v = (List<Matrix<M22l>>)o; c.CodeList_of_Matrix_of_M22l__(ref v); } },\r\n\r\n            { typeof(Volume<M22l>), (c,o) => { var v = (Volume<M22l>)o; c.CodeVolume_of_M22l_(ref v); } },\r\n            { typeof(Volume<M22l>[]), (c,o) => { var v = (Volume<M22l>[])o; c.CodeVolume_of_M22l_Array(ref v); } },\r\n            { typeof(List<Volume<M22l>>), (c,o) => { var v = (List<Volume<M22l>>)o; c.CodeList_of_Volume_of_M22l__(ref v); } },\r\n\r\n            { typeof(Tensor<M22l>), (c,o) => { var v = (Tensor<M22l>)o; c.CodeTensor_of_M22l_(ref v); } },\r\n            { typeof(Tensor<M22l>[]), (c,o) => { var v = (Tensor<M22l>[])o; c.CodeTensor_of_M22l_Array(ref v); } },\r\n            { typeof(List<Tensor<M22l>>), (c,o) => { var v = (List<Tensor<M22l>>)o; c.CodeList_of_Tensor_of_M22l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M22f\r\n\r\n            { typeof(M22f), (c,o) => { var v = (M22f)o; c.CodeM22f(ref v); } },\r\n            { typeof(M22f[]), (c,o) => { var v = (M22f[])o; c.CodeM22fArray(ref v); } },\r\n            { typeof(List<M22f>), (c,o) => { var v = (List<M22f>)o; c.CodeList_of_M22f_(ref v); } },\r\n\r\n            { typeof(Vector<M22f>), (c,o) => { var v = (Vector<M22f>)o; c.CodeVector_of_M22f_(ref v); } },\r\n            { typeof(Vector<M22f>[]), (c,o) => { var v = (Vector<M22f>[])o; c.CodeVector_of_M22f_Array(ref v); } },\r\n            { typeof(List<Vector<M22f>>), (c,o) => { var v = (List<Vector<M22f>>)o; c.CodeList_of_Vector_of_M22f__(ref v); } },\r\n\r\n            { typeof(Matrix<M22f>), (c,o) => { var v = (Matrix<M22f>)o; c.CodeMatrix_of_M22f_(ref v); } },\r\n            { typeof(Matrix<M22f>[]), (c,o) => { var v = (Matrix<M22f>[])o; c.CodeMatrix_of_M22f_Array(ref v); } },\r\n            { typeof(List<Matrix<M22f>>), (c,o) => { var v = (List<Matrix<M22f>>)o; c.CodeList_of_Matrix_of_M22f__(ref v); } },\r\n\r\n            { typeof(Volume<M22f>), (c,o) => { var v = (Volume<M22f>)o; c.CodeVolume_of_M22f_(ref v); } },\r\n            { typeof(Volume<M22f>[]), (c,o) => { var v = (Volume<M22f>[])o; c.CodeVolume_of_M22f_Array(ref v); } },\r\n            { typeof(List<Volume<M22f>>), (c,o) => { var v = (List<Volume<M22f>>)o; c.CodeList_of_Volume_of_M22f__(ref v); } },\r\n\r\n            { typeof(Tensor<M22f>), (c,o) => { var v = (Tensor<M22f>)o; c.CodeTensor_of_M22f_(ref v); } },\r\n            { typeof(Tensor<M22f>[]), (c,o) => { var v = (Tensor<M22f>[])o; c.CodeTensor_of_M22f_Array(ref v); } },\r\n            { typeof(List<Tensor<M22f>>), (c,o) => { var v = (List<Tensor<M22f>>)o; c.CodeList_of_Tensor_of_M22f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M22d\r\n\r\n            { typeof(M22d), (c,o) => { var v = (M22d)o; c.CodeM22d(ref v); } },\r\n            { typeof(M22d[]), (c,o) => { var v = (M22d[])o; c.CodeM22dArray(ref v); } },\r\n            { typeof(List<M22d>), (c,o) => { var v = (List<M22d>)o; c.CodeList_of_M22d_(ref v); } },\r\n\r\n            { typeof(Vector<M22d>), (c,o) => { var v = (Vector<M22d>)o; c.CodeVector_of_M22d_(ref v); } },\r\n            { typeof(Vector<M22d>[]), (c,o) => { var v = (Vector<M22d>[])o; c.CodeVector_of_M22d_Array(ref v); } },\r\n            { typeof(List<Vector<M22d>>), (c,o) => { var v = (List<Vector<M22d>>)o; c.CodeList_of_Vector_of_M22d__(ref v); } },\r\n\r\n            { typeof(Matrix<M22d>), (c,o) => { var v = (Matrix<M22d>)o; c.CodeMatrix_of_M22d_(ref v); } },\r\n            { typeof(Matrix<M22d>[]), (c,o) => { var v = (Matrix<M22d>[])o; c.CodeMatrix_of_M22d_Array(ref v); } },\r\n            { typeof(List<Matrix<M22d>>), (c,o) => { var v = (List<Matrix<M22d>>)o; c.CodeList_of_Matrix_of_M22d__(ref v); } },\r\n\r\n            { typeof(Volume<M22d>), (c,o) => { var v = (Volume<M22d>)o; c.CodeVolume_of_M22d_(ref v); } },\r\n            { typeof(Volume<M22d>[]), (c,o) => { var v = (Volume<M22d>[])o; c.CodeVolume_of_M22d_Array(ref v); } },\r\n            { typeof(List<Volume<M22d>>), (c,o) => { var v = (List<Volume<M22d>>)o; c.CodeList_of_Volume_of_M22d__(ref v); } },\r\n\r\n            { typeof(Tensor<M22d>), (c,o) => { var v = (Tensor<M22d>)o; c.CodeTensor_of_M22d_(ref v); } },\r\n            { typeof(Tensor<M22d>[]), (c,o) => { var v = (Tensor<M22d>[])o; c.CodeTensor_of_M22d_Array(ref v); } },\r\n            { typeof(List<Tensor<M22d>>), (c,o) => { var v = (List<Tensor<M22d>>)o; c.CodeList_of_Tensor_of_M22d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M23i\r\n\r\n            { typeof(M23i), (c,o) => { var v = (M23i)o; c.CodeM23i(ref v); } },\r\n            { typeof(M23i[]), (c,o) => { var v = (M23i[])o; c.CodeM23iArray(ref v); } },\r\n            { typeof(List<M23i>), (c,o) => { var v = (List<M23i>)o; c.CodeList_of_M23i_(ref v); } },\r\n\r\n            { typeof(Vector<M23i>), (c,o) => { var v = (Vector<M23i>)o; c.CodeVector_of_M23i_(ref v); } },\r\n            { typeof(Vector<M23i>[]), (c,o) => { var v = (Vector<M23i>[])o; c.CodeVector_of_M23i_Array(ref v); } },\r\n            { typeof(List<Vector<M23i>>), (c,o) => { var v = (List<Vector<M23i>>)o; c.CodeList_of_Vector_of_M23i__(ref v); } },\r\n\r\n            { typeof(Matrix<M23i>), (c,o) => { var v = (Matrix<M23i>)o; c.CodeMatrix_of_M23i_(ref v); } },\r\n            { typeof(Matrix<M23i>[]), (c,o) => { var v = (Matrix<M23i>[])o; c.CodeMatrix_of_M23i_Array(ref v); } },\r\n            { typeof(List<Matrix<M23i>>), (c,o) => { var v = (List<Matrix<M23i>>)o; c.CodeList_of_Matrix_of_M23i__(ref v); } },\r\n\r\n            { typeof(Volume<M23i>), (c,o) => { var v = (Volume<M23i>)o; c.CodeVolume_of_M23i_(ref v); } },\r\n            { typeof(Volume<M23i>[]), (c,o) => { var v = (Volume<M23i>[])o; c.CodeVolume_of_M23i_Array(ref v); } },\r\n            { typeof(List<Volume<M23i>>), (c,o) => { var v = (List<Volume<M23i>>)o; c.CodeList_of_Volume_of_M23i__(ref v); } },\r\n\r\n            { typeof(Tensor<M23i>), (c,o) => { var v = (Tensor<M23i>)o; c.CodeTensor_of_M23i_(ref v); } },\r\n            { typeof(Tensor<M23i>[]), (c,o) => { var v = (Tensor<M23i>[])o; c.CodeTensor_of_M23i_Array(ref v); } },\r\n            { typeof(List<Tensor<M23i>>), (c,o) => { var v = (List<Tensor<M23i>>)o; c.CodeList_of_Tensor_of_M23i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M23l\r\n\r\n            { typeof(M23l), (c,o) => { var v = (M23l)o; c.CodeM23l(ref v); } },\r\n            { typeof(M23l[]), (c,o) => { var v = (M23l[])o; c.CodeM23lArray(ref v); } },\r\n            { typeof(List<M23l>), (c,o) => { var v = (List<M23l>)o; c.CodeList_of_M23l_(ref v); } },\r\n\r\n            { typeof(Vector<M23l>), (c,o) => { var v = (Vector<M23l>)o; c.CodeVector_of_M23l_(ref v); } },\r\n            { typeof(Vector<M23l>[]), (c,o) => { var v = (Vector<M23l>[])o; c.CodeVector_of_M23l_Array(ref v); } },\r\n            { typeof(List<Vector<M23l>>), (c,o) => { var v = (List<Vector<M23l>>)o; c.CodeList_of_Vector_of_M23l__(ref v); } },\r\n\r\n            { typeof(Matrix<M23l>), (c,o) => { var v = (Matrix<M23l>)o; c.CodeMatrix_of_M23l_(ref v); } },\r\n            { typeof(Matrix<M23l>[]), (c,o) => { var v = (Matrix<M23l>[])o; c.CodeMatrix_of_M23l_Array(ref v); } },\r\n            { typeof(List<Matrix<M23l>>), (c,o) => { var v = (List<Matrix<M23l>>)o; c.CodeList_of_Matrix_of_M23l__(ref v); } },\r\n\r\n            { typeof(Volume<M23l>), (c,o) => { var v = (Volume<M23l>)o; c.CodeVolume_of_M23l_(ref v); } },\r\n            { typeof(Volume<M23l>[]), (c,o) => { var v = (Volume<M23l>[])o; c.CodeVolume_of_M23l_Array(ref v); } },\r\n            { typeof(List<Volume<M23l>>), (c,o) => { var v = (List<Volume<M23l>>)o; c.CodeList_of_Volume_of_M23l__(ref v); } },\r\n\r\n            { typeof(Tensor<M23l>), (c,o) => { var v = (Tensor<M23l>)o; c.CodeTensor_of_M23l_(ref v); } },\r\n            { typeof(Tensor<M23l>[]), (c,o) => { var v = (Tensor<M23l>[])o; c.CodeTensor_of_M23l_Array(ref v); } },\r\n            { typeof(List<Tensor<M23l>>), (c,o) => { var v = (List<Tensor<M23l>>)o; c.CodeList_of_Tensor_of_M23l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M23f\r\n\r\n            { typeof(M23f), (c,o) => { var v = (M23f)o; c.CodeM23f(ref v); } },\r\n            { typeof(M23f[]), (c,o) => { var v = (M23f[])o; c.CodeM23fArray(ref v); } },\r\n            { typeof(List<M23f>), (c,o) => { var v = (List<M23f>)o; c.CodeList_of_M23f_(ref v); } },\r\n\r\n            { typeof(Vector<M23f>), (c,o) => { var v = (Vector<M23f>)o; c.CodeVector_of_M23f_(ref v); } },\r\n            { typeof(Vector<M23f>[]), (c,o) => { var v = (Vector<M23f>[])o; c.CodeVector_of_M23f_Array(ref v); } },\r\n            { typeof(List<Vector<M23f>>), (c,o) => { var v = (List<Vector<M23f>>)o; c.CodeList_of_Vector_of_M23f__(ref v); } },\r\n\r\n            { typeof(Matrix<M23f>), (c,o) => { var v = (Matrix<M23f>)o; c.CodeMatrix_of_M23f_(ref v); } },\r\n            { typeof(Matrix<M23f>[]), (c,o) => { var v = (Matrix<M23f>[])o; c.CodeMatrix_of_M23f_Array(ref v); } },\r\n            { typeof(List<Matrix<M23f>>), (c,o) => { var v = (List<Matrix<M23f>>)o; c.CodeList_of_Matrix_of_M23f__(ref v); } },\r\n\r\n            { typeof(Volume<M23f>), (c,o) => { var v = (Volume<M23f>)o; c.CodeVolume_of_M23f_(ref v); } },\r\n            { typeof(Volume<M23f>[]), (c,o) => { var v = (Volume<M23f>[])o; c.CodeVolume_of_M23f_Array(ref v); } },\r\n            { typeof(List<Volume<M23f>>), (c,o) => { var v = (List<Volume<M23f>>)o; c.CodeList_of_Volume_of_M23f__(ref v); } },\r\n\r\n            { typeof(Tensor<M23f>), (c,o) => { var v = (Tensor<M23f>)o; c.CodeTensor_of_M23f_(ref v); } },\r\n            { typeof(Tensor<M23f>[]), (c,o) => { var v = (Tensor<M23f>[])o; c.CodeTensor_of_M23f_Array(ref v); } },\r\n            { typeof(List<Tensor<M23f>>), (c,o) => { var v = (List<Tensor<M23f>>)o; c.CodeList_of_Tensor_of_M23f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M23d\r\n\r\n            { typeof(M23d), (c,o) => { var v = (M23d)o; c.CodeM23d(ref v); } },\r\n            { typeof(M23d[]), (c,o) => { var v = (M23d[])o; c.CodeM23dArray(ref v); } },\r\n            { typeof(List<M23d>), (c,o) => { var v = (List<M23d>)o; c.CodeList_of_M23d_(ref v); } },\r\n\r\n            { typeof(Vector<M23d>), (c,o) => { var v = (Vector<M23d>)o; c.CodeVector_of_M23d_(ref v); } },\r\n            { typeof(Vector<M23d>[]), (c,o) => { var v = (Vector<M23d>[])o; c.CodeVector_of_M23d_Array(ref v); } },\r\n            { typeof(List<Vector<M23d>>), (c,o) => { var v = (List<Vector<M23d>>)o; c.CodeList_of_Vector_of_M23d__(ref v); } },\r\n\r\n            { typeof(Matrix<M23d>), (c,o) => { var v = (Matrix<M23d>)o; c.CodeMatrix_of_M23d_(ref v); } },\r\n            { typeof(Matrix<M23d>[]), (c,o) => { var v = (Matrix<M23d>[])o; c.CodeMatrix_of_M23d_Array(ref v); } },\r\n            { typeof(List<Matrix<M23d>>), (c,o) => { var v = (List<Matrix<M23d>>)o; c.CodeList_of_Matrix_of_M23d__(ref v); } },\r\n\r\n            { typeof(Volume<M23d>), (c,o) => { var v = (Volume<M23d>)o; c.CodeVolume_of_M23d_(ref v); } },\r\n            { typeof(Volume<M23d>[]), (c,o) => { var v = (Volume<M23d>[])o; c.CodeVolume_of_M23d_Array(ref v); } },\r\n            { typeof(List<Volume<M23d>>), (c,o) => { var v = (List<Volume<M23d>>)o; c.CodeList_of_Volume_of_M23d__(ref v); } },\r\n\r\n            { typeof(Tensor<M23d>), (c,o) => { var v = (Tensor<M23d>)o; c.CodeTensor_of_M23d_(ref v); } },\r\n            { typeof(Tensor<M23d>[]), (c,o) => { var v = (Tensor<M23d>[])o; c.CodeTensor_of_M23d_Array(ref v); } },\r\n            { typeof(List<Tensor<M23d>>), (c,o) => { var v = (List<Tensor<M23d>>)o; c.CodeList_of_Tensor_of_M23d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M33i\r\n\r\n            { typeof(M33i), (c,o) => { var v = (M33i)o; c.CodeM33i(ref v); } },\r\n            { typeof(M33i[]), (c,o) => { var v = (M33i[])o; c.CodeM33iArray(ref v); } },\r\n            { typeof(List<M33i>), (c,o) => { var v = (List<M33i>)o; c.CodeList_of_M33i_(ref v); } },\r\n\r\n            { typeof(Vector<M33i>), (c,o) => { var v = (Vector<M33i>)o; c.CodeVector_of_M33i_(ref v); } },\r\n            { typeof(Vector<M33i>[]), (c,o) => { var v = (Vector<M33i>[])o; c.CodeVector_of_M33i_Array(ref v); } },\r\n            { typeof(List<Vector<M33i>>), (c,o) => { var v = (List<Vector<M33i>>)o; c.CodeList_of_Vector_of_M33i__(ref v); } },\r\n\r\n            { typeof(Matrix<M33i>), (c,o) => { var v = (Matrix<M33i>)o; c.CodeMatrix_of_M33i_(ref v); } },\r\n            { typeof(Matrix<M33i>[]), (c,o) => { var v = (Matrix<M33i>[])o; c.CodeMatrix_of_M33i_Array(ref v); } },\r\n            { typeof(List<Matrix<M33i>>), (c,o) => { var v = (List<Matrix<M33i>>)o; c.CodeList_of_Matrix_of_M33i__(ref v); } },\r\n\r\n            { typeof(Volume<M33i>), (c,o) => { var v = (Volume<M33i>)o; c.CodeVolume_of_M33i_(ref v); } },\r\n            { typeof(Volume<M33i>[]), (c,o) => { var v = (Volume<M33i>[])o; c.CodeVolume_of_M33i_Array(ref v); } },\r\n            { typeof(List<Volume<M33i>>), (c,o) => { var v = (List<Volume<M33i>>)o; c.CodeList_of_Volume_of_M33i__(ref v); } },\r\n\r\n            { typeof(Tensor<M33i>), (c,o) => { var v = (Tensor<M33i>)o; c.CodeTensor_of_M33i_(ref v); } },\r\n            { typeof(Tensor<M33i>[]), (c,o) => { var v = (Tensor<M33i>[])o; c.CodeTensor_of_M33i_Array(ref v); } },\r\n            { typeof(List<Tensor<M33i>>), (c,o) => { var v = (List<Tensor<M33i>>)o; c.CodeList_of_Tensor_of_M33i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M33l\r\n\r\n            { typeof(M33l), (c,o) => { var v = (M33l)o; c.CodeM33l(ref v); } },\r\n            { typeof(M33l[]), (c,o) => { var v = (M33l[])o; c.CodeM33lArray(ref v); } },\r\n            { typeof(List<M33l>), (c,o) => { var v = (List<M33l>)o; c.CodeList_of_M33l_(ref v); } },\r\n\r\n            { typeof(Vector<M33l>), (c,o) => { var v = (Vector<M33l>)o; c.CodeVector_of_M33l_(ref v); } },\r\n            { typeof(Vector<M33l>[]), (c,o) => { var v = (Vector<M33l>[])o; c.CodeVector_of_M33l_Array(ref v); } },\r\n            { typeof(List<Vector<M33l>>), (c,o) => { var v = (List<Vector<M33l>>)o; c.CodeList_of_Vector_of_M33l__(ref v); } },\r\n\r\n            { typeof(Matrix<M33l>), (c,o) => { var v = (Matrix<M33l>)o; c.CodeMatrix_of_M33l_(ref v); } },\r\n            { typeof(Matrix<M33l>[]), (c,o) => { var v = (Matrix<M33l>[])o; c.CodeMatrix_of_M33l_Array(ref v); } },\r\n            { typeof(List<Matrix<M33l>>), (c,o) => { var v = (List<Matrix<M33l>>)o; c.CodeList_of_Matrix_of_M33l__(ref v); } },\r\n\r\n            { typeof(Volume<M33l>), (c,o) => { var v = (Volume<M33l>)o; c.CodeVolume_of_M33l_(ref v); } },\r\n            { typeof(Volume<M33l>[]), (c,o) => { var v = (Volume<M33l>[])o; c.CodeVolume_of_M33l_Array(ref v); } },\r\n            { typeof(List<Volume<M33l>>), (c,o) => { var v = (List<Volume<M33l>>)o; c.CodeList_of_Volume_of_M33l__(ref v); } },\r\n\r\n            { typeof(Tensor<M33l>), (c,o) => { var v = (Tensor<M33l>)o; c.CodeTensor_of_M33l_(ref v); } },\r\n            { typeof(Tensor<M33l>[]), (c,o) => { var v = (Tensor<M33l>[])o; c.CodeTensor_of_M33l_Array(ref v); } },\r\n            { typeof(List<Tensor<M33l>>), (c,o) => { var v = (List<Tensor<M33l>>)o; c.CodeList_of_Tensor_of_M33l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M33f\r\n\r\n            { typeof(M33f), (c,o) => { var v = (M33f)o; c.CodeM33f(ref v); } },\r\n            { typeof(M33f[]), (c,o) => { var v = (M33f[])o; c.CodeM33fArray(ref v); } },\r\n            { typeof(List<M33f>), (c,o) => { var v = (List<M33f>)o; c.CodeList_of_M33f_(ref v); } },\r\n\r\n            { typeof(Vector<M33f>), (c,o) => { var v = (Vector<M33f>)o; c.CodeVector_of_M33f_(ref v); } },\r\n            { typeof(Vector<M33f>[]), (c,o) => { var v = (Vector<M33f>[])o; c.CodeVector_of_M33f_Array(ref v); } },\r\n            { typeof(List<Vector<M33f>>), (c,o) => { var v = (List<Vector<M33f>>)o; c.CodeList_of_Vector_of_M33f__(ref v); } },\r\n\r\n            { typeof(Matrix<M33f>), (c,o) => { var v = (Matrix<M33f>)o; c.CodeMatrix_of_M33f_(ref v); } },\r\n            { typeof(Matrix<M33f>[]), (c,o) => { var v = (Matrix<M33f>[])o; c.CodeMatrix_of_M33f_Array(ref v); } },\r\n            { typeof(List<Matrix<M33f>>), (c,o) => { var v = (List<Matrix<M33f>>)o; c.CodeList_of_Matrix_of_M33f__(ref v); } },\r\n\r\n            { typeof(Volume<M33f>), (c,o) => { var v = (Volume<M33f>)o; c.CodeVolume_of_M33f_(ref v); } },\r\n            { typeof(Volume<M33f>[]), (c,o) => { var v = (Volume<M33f>[])o; c.CodeVolume_of_M33f_Array(ref v); } },\r\n            { typeof(List<Volume<M33f>>), (c,o) => { var v = (List<Volume<M33f>>)o; c.CodeList_of_Volume_of_M33f__(ref v); } },\r\n\r\n            { typeof(Tensor<M33f>), (c,o) => { var v = (Tensor<M33f>)o; c.CodeTensor_of_M33f_(ref v); } },\r\n            { typeof(Tensor<M33f>[]), (c,o) => { var v = (Tensor<M33f>[])o; c.CodeTensor_of_M33f_Array(ref v); } },\r\n            { typeof(List<Tensor<M33f>>), (c,o) => { var v = (List<Tensor<M33f>>)o; c.CodeList_of_Tensor_of_M33f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M33d\r\n\r\n            { typeof(M33d), (c,o) => { var v = (M33d)o; c.CodeM33d(ref v); } },\r\n            { typeof(M33d[]), (c,o) => { var v = (M33d[])o; c.CodeM33dArray(ref v); } },\r\n            { typeof(List<M33d>), (c,o) => { var v = (List<M33d>)o; c.CodeList_of_M33d_(ref v); } },\r\n\r\n            { typeof(Vector<M33d>), (c,o) => { var v = (Vector<M33d>)o; c.CodeVector_of_M33d_(ref v); } },\r\n            { typeof(Vector<M33d>[]), (c,o) => { var v = (Vector<M33d>[])o; c.CodeVector_of_M33d_Array(ref v); } },\r\n            { typeof(List<Vector<M33d>>), (c,o) => { var v = (List<Vector<M33d>>)o; c.CodeList_of_Vector_of_M33d__(ref v); } },\r\n\r\n            { typeof(Matrix<M33d>), (c,o) => { var v = (Matrix<M33d>)o; c.CodeMatrix_of_M33d_(ref v); } },\r\n            { typeof(Matrix<M33d>[]), (c,o) => { var v = (Matrix<M33d>[])o; c.CodeMatrix_of_M33d_Array(ref v); } },\r\n            { typeof(List<Matrix<M33d>>), (c,o) => { var v = (List<Matrix<M33d>>)o; c.CodeList_of_Matrix_of_M33d__(ref v); } },\r\n\r\n            { typeof(Volume<M33d>), (c,o) => { var v = (Volume<M33d>)o; c.CodeVolume_of_M33d_(ref v); } },\r\n            { typeof(Volume<M33d>[]), (c,o) => { var v = (Volume<M33d>[])o; c.CodeVolume_of_M33d_Array(ref v); } },\r\n            { typeof(List<Volume<M33d>>), (c,o) => { var v = (List<Volume<M33d>>)o; c.CodeList_of_Volume_of_M33d__(ref v); } },\r\n\r\n            { typeof(Tensor<M33d>), (c,o) => { var v = (Tensor<M33d>)o; c.CodeTensor_of_M33d_(ref v); } },\r\n            { typeof(Tensor<M33d>[]), (c,o) => { var v = (Tensor<M33d>[])o; c.CodeTensor_of_M33d_Array(ref v); } },\r\n            { typeof(List<Tensor<M33d>>), (c,o) => { var v = (List<Tensor<M33d>>)o; c.CodeList_of_Tensor_of_M33d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M34i\r\n\r\n            { typeof(M34i), (c,o) => { var v = (M34i)o; c.CodeM34i(ref v); } },\r\n            { typeof(M34i[]), (c,o) => { var v = (M34i[])o; c.CodeM34iArray(ref v); } },\r\n            { typeof(List<M34i>), (c,o) => { var v = (List<M34i>)o; c.CodeList_of_M34i_(ref v); } },\r\n\r\n            { typeof(Vector<M34i>), (c,o) => { var v = (Vector<M34i>)o; c.CodeVector_of_M34i_(ref v); } },\r\n            { typeof(Vector<M34i>[]), (c,o) => { var v = (Vector<M34i>[])o; c.CodeVector_of_M34i_Array(ref v); } },\r\n            { typeof(List<Vector<M34i>>), (c,o) => { var v = (List<Vector<M34i>>)o; c.CodeList_of_Vector_of_M34i__(ref v); } },\r\n\r\n            { typeof(Matrix<M34i>), (c,o) => { var v = (Matrix<M34i>)o; c.CodeMatrix_of_M34i_(ref v); } },\r\n            { typeof(Matrix<M34i>[]), (c,o) => { var v = (Matrix<M34i>[])o; c.CodeMatrix_of_M34i_Array(ref v); } },\r\n            { typeof(List<Matrix<M34i>>), (c,o) => { var v = (List<Matrix<M34i>>)o; c.CodeList_of_Matrix_of_M34i__(ref v); } },\r\n\r\n            { typeof(Volume<M34i>), (c,o) => { var v = (Volume<M34i>)o; c.CodeVolume_of_M34i_(ref v); } },\r\n            { typeof(Volume<M34i>[]), (c,o) => { var v = (Volume<M34i>[])o; c.CodeVolume_of_M34i_Array(ref v); } },\r\n            { typeof(List<Volume<M34i>>), (c,o) => { var v = (List<Volume<M34i>>)o; c.CodeList_of_Volume_of_M34i__(ref v); } },\r\n\r\n            { typeof(Tensor<M34i>), (c,o) => { var v = (Tensor<M34i>)o; c.CodeTensor_of_M34i_(ref v); } },\r\n            { typeof(Tensor<M34i>[]), (c,o) => { var v = (Tensor<M34i>[])o; c.CodeTensor_of_M34i_Array(ref v); } },\r\n            { typeof(List<Tensor<M34i>>), (c,o) => { var v = (List<Tensor<M34i>>)o; c.CodeList_of_Tensor_of_M34i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M34l\r\n\r\n            { typeof(M34l), (c,o) => { var v = (M34l)o; c.CodeM34l(ref v); } },\r\n            { typeof(M34l[]), (c,o) => { var v = (M34l[])o; c.CodeM34lArray(ref v); } },\r\n            { typeof(List<M34l>), (c,o) => { var v = (List<M34l>)o; c.CodeList_of_M34l_(ref v); } },\r\n\r\n            { typeof(Vector<M34l>), (c,o) => { var v = (Vector<M34l>)o; c.CodeVector_of_M34l_(ref v); } },\r\n            { typeof(Vector<M34l>[]), (c,o) => { var v = (Vector<M34l>[])o; c.CodeVector_of_M34l_Array(ref v); } },\r\n            { typeof(List<Vector<M34l>>), (c,o) => { var v = (List<Vector<M34l>>)o; c.CodeList_of_Vector_of_M34l__(ref v); } },\r\n\r\n            { typeof(Matrix<M34l>), (c,o) => { var v = (Matrix<M34l>)o; c.CodeMatrix_of_M34l_(ref v); } },\r\n            { typeof(Matrix<M34l>[]), (c,o) => { var v = (Matrix<M34l>[])o; c.CodeMatrix_of_M34l_Array(ref v); } },\r\n            { typeof(List<Matrix<M34l>>), (c,o) => { var v = (List<Matrix<M34l>>)o; c.CodeList_of_Matrix_of_M34l__(ref v); } },\r\n\r\n            { typeof(Volume<M34l>), (c,o) => { var v = (Volume<M34l>)o; c.CodeVolume_of_M34l_(ref v); } },\r\n            { typeof(Volume<M34l>[]), (c,o) => { var v = (Volume<M34l>[])o; c.CodeVolume_of_M34l_Array(ref v); } },\r\n            { typeof(List<Volume<M34l>>), (c,o) => { var v = (List<Volume<M34l>>)o; c.CodeList_of_Volume_of_M34l__(ref v); } },\r\n\r\n            { typeof(Tensor<M34l>), (c,o) => { var v = (Tensor<M34l>)o; c.CodeTensor_of_M34l_(ref v); } },\r\n            { typeof(Tensor<M34l>[]), (c,o) => { var v = (Tensor<M34l>[])o; c.CodeTensor_of_M34l_Array(ref v); } },\r\n            { typeof(List<Tensor<M34l>>), (c,o) => { var v = (List<Tensor<M34l>>)o; c.CodeList_of_Tensor_of_M34l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M34f\r\n\r\n            { typeof(M34f), (c,o) => { var v = (M34f)o; c.CodeM34f(ref v); } },\r\n            { typeof(M34f[]), (c,o) => { var v = (M34f[])o; c.CodeM34fArray(ref v); } },\r\n            { typeof(List<M34f>), (c,o) => { var v = (List<M34f>)o; c.CodeList_of_M34f_(ref v); } },\r\n\r\n            { typeof(Vector<M34f>), (c,o) => { var v = (Vector<M34f>)o; c.CodeVector_of_M34f_(ref v); } },\r\n            { typeof(Vector<M34f>[]), (c,o) => { var v = (Vector<M34f>[])o; c.CodeVector_of_M34f_Array(ref v); } },\r\n            { typeof(List<Vector<M34f>>), (c,o) => { var v = (List<Vector<M34f>>)o; c.CodeList_of_Vector_of_M34f__(ref v); } },\r\n\r\n            { typeof(Matrix<M34f>), (c,o) => { var v = (Matrix<M34f>)o; c.CodeMatrix_of_M34f_(ref v); } },\r\n            { typeof(Matrix<M34f>[]), (c,o) => { var v = (Matrix<M34f>[])o; c.CodeMatrix_of_M34f_Array(ref v); } },\r\n            { typeof(List<Matrix<M34f>>), (c,o) => { var v = (List<Matrix<M34f>>)o; c.CodeList_of_Matrix_of_M34f__(ref v); } },\r\n\r\n            { typeof(Volume<M34f>), (c,o) => { var v = (Volume<M34f>)o; c.CodeVolume_of_M34f_(ref v); } },\r\n            { typeof(Volume<M34f>[]), (c,o) => { var v = (Volume<M34f>[])o; c.CodeVolume_of_M34f_Array(ref v); } },\r\n            { typeof(List<Volume<M34f>>), (c,o) => { var v = (List<Volume<M34f>>)o; c.CodeList_of_Volume_of_M34f__(ref v); } },\r\n\r\n            { typeof(Tensor<M34f>), (c,o) => { var v = (Tensor<M34f>)o; c.CodeTensor_of_M34f_(ref v); } },\r\n            { typeof(Tensor<M34f>[]), (c,o) => { var v = (Tensor<M34f>[])o; c.CodeTensor_of_M34f_Array(ref v); } },\r\n            { typeof(List<Tensor<M34f>>), (c,o) => { var v = (List<Tensor<M34f>>)o; c.CodeList_of_Tensor_of_M34f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M34d\r\n\r\n            { typeof(M34d), (c,o) => { var v = (M34d)o; c.CodeM34d(ref v); } },\r\n            { typeof(M34d[]), (c,o) => { var v = (M34d[])o; c.CodeM34dArray(ref v); } },\r\n            { typeof(List<M34d>), (c,o) => { var v = (List<M34d>)o; c.CodeList_of_M34d_(ref v); } },\r\n\r\n            { typeof(Vector<M34d>), (c,o) => { var v = (Vector<M34d>)o; c.CodeVector_of_M34d_(ref v); } },\r\n            { typeof(Vector<M34d>[]), (c,o) => { var v = (Vector<M34d>[])o; c.CodeVector_of_M34d_Array(ref v); } },\r\n            { typeof(List<Vector<M34d>>), (c,o) => { var v = (List<Vector<M34d>>)o; c.CodeList_of_Vector_of_M34d__(ref v); } },\r\n\r\n            { typeof(Matrix<M34d>), (c,o) => { var v = (Matrix<M34d>)o; c.CodeMatrix_of_M34d_(ref v); } },\r\n            { typeof(Matrix<M34d>[]), (c,o) => { var v = (Matrix<M34d>[])o; c.CodeMatrix_of_M34d_Array(ref v); } },\r\n            { typeof(List<Matrix<M34d>>), (c,o) => { var v = (List<Matrix<M34d>>)o; c.CodeList_of_Matrix_of_M34d__(ref v); } },\r\n\r\n            { typeof(Volume<M34d>), (c,o) => { var v = (Volume<M34d>)o; c.CodeVolume_of_M34d_(ref v); } },\r\n            { typeof(Volume<M34d>[]), (c,o) => { var v = (Volume<M34d>[])o; c.CodeVolume_of_M34d_Array(ref v); } },\r\n            { typeof(List<Volume<M34d>>), (c,o) => { var v = (List<Volume<M34d>>)o; c.CodeList_of_Volume_of_M34d__(ref v); } },\r\n\r\n            { typeof(Tensor<M34d>), (c,o) => { var v = (Tensor<M34d>)o; c.CodeTensor_of_M34d_(ref v); } },\r\n            { typeof(Tensor<M34d>[]), (c,o) => { var v = (Tensor<M34d>[])o; c.CodeTensor_of_M34d_Array(ref v); } },\r\n            { typeof(List<Tensor<M34d>>), (c,o) => { var v = (List<Tensor<M34d>>)o; c.CodeList_of_Tensor_of_M34d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M44i\r\n\r\n            { typeof(M44i), (c,o) => { var v = (M44i)o; c.CodeM44i(ref v); } },\r\n            { typeof(M44i[]), (c,o) => { var v = (M44i[])o; c.CodeM44iArray(ref v); } },\r\n            { typeof(List<M44i>), (c,o) => { var v = (List<M44i>)o; c.CodeList_of_M44i_(ref v); } },\r\n\r\n            { typeof(Vector<M44i>), (c,o) => { var v = (Vector<M44i>)o; c.CodeVector_of_M44i_(ref v); } },\r\n            { typeof(Vector<M44i>[]), (c,o) => { var v = (Vector<M44i>[])o; c.CodeVector_of_M44i_Array(ref v); } },\r\n            { typeof(List<Vector<M44i>>), (c,o) => { var v = (List<Vector<M44i>>)o; c.CodeList_of_Vector_of_M44i__(ref v); } },\r\n\r\n            { typeof(Matrix<M44i>), (c,o) => { var v = (Matrix<M44i>)o; c.CodeMatrix_of_M44i_(ref v); } },\r\n            { typeof(Matrix<M44i>[]), (c,o) => { var v = (Matrix<M44i>[])o; c.CodeMatrix_of_M44i_Array(ref v); } },\r\n            { typeof(List<Matrix<M44i>>), (c,o) => { var v = (List<Matrix<M44i>>)o; c.CodeList_of_Matrix_of_M44i__(ref v); } },\r\n\r\n            { typeof(Volume<M44i>), (c,o) => { var v = (Volume<M44i>)o; c.CodeVolume_of_M44i_(ref v); } },\r\n            { typeof(Volume<M44i>[]), (c,o) => { var v = (Volume<M44i>[])o; c.CodeVolume_of_M44i_Array(ref v); } },\r\n            { typeof(List<Volume<M44i>>), (c,o) => { var v = (List<Volume<M44i>>)o; c.CodeList_of_Volume_of_M44i__(ref v); } },\r\n\r\n            { typeof(Tensor<M44i>), (c,o) => { var v = (Tensor<M44i>)o; c.CodeTensor_of_M44i_(ref v); } },\r\n            { typeof(Tensor<M44i>[]), (c,o) => { var v = (Tensor<M44i>[])o; c.CodeTensor_of_M44i_Array(ref v); } },\r\n            { typeof(List<Tensor<M44i>>), (c,o) => { var v = (List<Tensor<M44i>>)o; c.CodeList_of_Tensor_of_M44i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M44l\r\n\r\n            { typeof(M44l), (c,o) => { var v = (M44l)o; c.CodeM44l(ref v); } },\r\n            { typeof(M44l[]), (c,o) => { var v = (M44l[])o; c.CodeM44lArray(ref v); } },\r\n            { typeof(List<M44l>), (c,o) => { var v = (List<M44l>)o; c.CodeList_of_M44l_(ref v); } },\r\n\r\n            { typeof(Vector<M44l>), (c,o) => { var v = (Vector<M44l>)o; c.CodeVector_of_M44l_(ref v); } },\r\n            { typeof(Vector<M44l>[]), (c,o) => { var v = (Vector<M44l>[])o; c.CodeVector_of_M44l_Array(ref v); } },\r\n            { typeof(List<Vector<M44l>>), (c,o) => { var v = (List<Vector<M44l>>)o; c.CodeList_of_Vector_of_M44l__(ref v); } },\r\n\r\n            { typeof(Matrix<M44l>), (c,o) => { var v = (Matrix<M44l>)o; c.CodeMatrix_of_M44l_(ref v); } },\r\n            { typeof(Matrix<M44l>[]), (c,o) => { var v = (Matrix<M44l>[])o; c.CodeMatrix_of_M44l_Array(ref v); } },\r\n            { typeof(List<Matrix<M44l>>), (c,o) => { var v = (List<Matrix<M44l>>)o; c.CodeList_of_Matrix_of_M44l__(ref v); } },\r\n\r\n            { typeof(Volume<M44l>), (c,o) => { var v = (Volume<M44l>)o; c.CodeVolume_of_M44l_(ref v); } },\r\n            { typeof(Volume<M44l>[]), (c,o) => { var v = (Volume<M44l>[])o; c.CodeVolume_of_M44l_Array(ref v); } },\r\n            { typeof(List<Volume<M44l>>), (c,o) => { var v = (List<Volume<M44l>>)o; c.CodeList_of_Volume_of_M44l__(ref v); } },\r\n\r\n            { typeof(Tensor<M44l>), (c,o) => { var v = (Tensor<M44l>)o; c.CodeTensor_of_M44l_(ref v); } },\r\n            { typeof(Tensor<M44l>[]), (c,o) => { var v = (Tensor<M44l>[])o; c.CodeTensor_of_M44l_Array(ref v); } },\r\n            { typeof(List<Tensor<M44l>>), (c,o) => { var v = (List<Tensor<M44l>>)o; c.CodeList_of_Tensor_of_M44l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M44f\r\n\r\n            { typeof(M44f), (c,o) => { var v = (M44f)o; c.CodeM44f(ref v); } },\r\n            { typeof(M44f[]), (c,o) => { var v = (M44f[])o; c.CodeM44fArray(ref v); } },\r\n            { typeof(List<M44f>), (c,o) => { var v = (List<M44f>)o; c.CodeList_of_M44f_(ref v); } },\r\n\r\n            { typeof(Vector<M44f>), (c,o) => { var v = (Vector<M44f>)o; c.CodeVector_of_M44f_(ref v); } },\r\n            { typeof(Vector<M44f>[]), (c,o) => { var v = (Vector<M44f>[])o; c.CodeVector_of_M44f_Array(ref v); } },\r\n            { typeof(List<Vector<M44f>>), (c,o) => { var v = (List<Vector<M44f>>)o; c.CodeList_of_Vector_of_M44f__(ref v); } },\r\n\r\n            { typeof(Matrix<M44f>), (c,o) => { var v = (Matrix<M44f>)o; c.CodeMatrix_of_M44f_(ref v); } },\r\n            { typeof(Matrix<M44f>[]), (c,o) => { var v = (Matrix<M44f>[])o; c.CodeMatrix_of_M44f_Array(ref v); } },\r\n            { typeof(List<Matrix<M44f>>), (c,o) => { var v = (List<Matrix<M44f>>)o; c.CodeList_of_Matrix_of_M44f__(ref v); } },\r\n\r\n            { typeof(Volume<M44f>), (c,o) => { var v = (Volume<M44f>)o; c.CodeVolume_of_M44f_(ref v); } },\r\n            { typeof(Volume<M44f>[]), (c,o) => { var v = (Volume<M44f>[])o; c.CodeVolume_of_M44f_Array(ref v); } },\r\n            { typeof(List<Volume<M44f>>), (c,o) => { var v = (List<Volume<M44f>>)o; c.CodeList_of_Volume_of_M44f__(ref v); } },\r\n\r\n            { typeof(Tensor<M44f>), (c,o) => { var v = (Tensor<M44f>)o; c.CodeTensor_of_M44f_(ref v); } },\r\n            { typeof(Tensor<M44f>[]), (c,o) => { var v = (Tensor<M44f>[])o; c.CodeTensor_of_M44f_Array(ref v); } },\r\n            { typeof(List<Tensor<M44f>>), (c,o) => { var v = (List<Tensor<M44f>>)o; c.CodeList_of_Tensor_of_M44f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region M44d\r\n\r\n            { typeof(M44d), (c,o) => { var v = (M44d)o; c.CodeM44d(ref v); } },\r\n            { typeof(M44d[]), (c,o) => { var v = (M44d[])o; c.CodeM44dArray(ref v); } },\r\n            { typeof(List<M44d>), (c,o) => { var v = (List<M44d>)o; c.CodeList_of_M44d_(ref v); } },\r\n\r\n            { typeof(Vector<M44d>), (c,o) => { var v = (Vector<M44d>)o; c.CodeVector_of_M44d_(ref v); } },\r\n            { typeof(Vector<M44d>[]), (c,o) => { var v = (Vector<M44d>[])o; c.CodeVector_of_M44d_Array(ref v); } },\r\n            { typeof(List<Vector<M44d>>), (c,o) => { var v = (List<Vector<M44d>>)o; c.CodeList_of_Vector_of_M44d__(ref v); } },\r\n\r\n            { typeof(Matrix<M44d>), (c,o) => { var v = (Matrix<M44d>)o; c.CodeMatrix_of_M44d_(ref v); } },\r\n            { typeof(Matrix<M44d>[]), (c,o) => { var v = (Matrix<M44d>[])o; c.CodeMatrix_of_M44d_Array(ref v); } },\r\n            { typeof(List<Matrix<M44d>>), (c,o) => { var v = (List<Matrix<M44d>>)o; c.CodeList_of_Matrix_of_M44d__(ref v); } },\r\n\r\n            { typeof(Volume<M44d>), (c,o) => { var v = (Volume<M44d>)o; c.CodeVolume_of_M44d_(ref v); } },\r\n            { typeof(Volume<M44d>[]), (c,o) => { var v = (Volume<M44d>[])o; c.CodeVolume_of_M44d_Array(ref v); } },\r\n            { typeof(List<Volume<M44d>>), (c,o) => { var v = (List<Volume<M44d>>)o; c.CodeList_of_Volume_of_M44d__(ref v); } },\r\n\r\n            { typeof(Tensor<M44d>), (c,o) => { var v = (Tensor<M44d>)o; c.CodeTensor_of_M44d_(ref v); } },\r\n            { typeof(Tensor<M44d>[]), (c,o) => { var v = (Tensor<M44d>[])o; c.CodeTensor_of_M44d_Array(ref v); } },\r\n            { typeof(List<Tensor<M44d>>), (c,o) => { var v = (List<Tensor<M44d>>)o; c.CodeList_of_Tensor_of_M44d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C3b\r\n\r\n            { typeof(C3b), (c,o) => { var v = (C3b)o; c.CodeC3b(ref v); } },\r\n            { typeof(C3b[]), (c,o) => { var v = (C3b[])o; c.CodeC3bArray(ref v); } },\r\n            { typeof(List<C3b>), (c,o) => { var v = (List<C3b>)o; c.CodeList_of_C3b_(ref v); } },\r\n\r\n            { typeof(Vector<C3b>), (c,o) => { var v = (Vector<C3b>)o; c.CodeVector_of_C3b_(ref v); } },\r\n            { typeof(Vector<C3b>[]), (c,o) => { var v = (Vector<C3b>[])o; c.CodeVector_of_C3b_Array(ref v); } },\r\n            { typeof(List<Vector<C3b>>), (c,o) => { var v = (List<Vector<C3b>>)o; c.CodeList_of_Vector_of_C3b__(ref v); } },\r\n\r\n            { typeof(Matrix<C3b>), (c,o) => { var v = (Matrix<C3b>)o; c.CodeMatrix_of_C3b_(ref v); } },\r\n            { typeof(Matrix<C3b>[]), (c,o) => { var v = (Matrix<C3b>[])o; c.CodeMatrix_of_C3b_Array(ref v); } },\r\n            { typeof(List<Matrix<C3b>>), (c,o) => { var v = (List<Matrix<C3b>>)o; c.CodeList_of_Matrix_of_C3b__(ref v); } },\r\n\r\n            { typeof(Volume<C3b>), (c,o) => { var v = (Volume<C3b>)o; c.CodeVolume_of_C3b_(ref v); } },\r\n            { typeof(Volume<C3b>[]), (c,o) => { var v = (Volume<C3b>[])o; c.CodeVolume_of_C3b_Array(ref v); } },\r\n            { typeof(List<Volume<C3b>>), (c,o) => { var v = (List<Volume<C3b>>)o; c.CodeList_of_Volume_of_C3b__(ref v); } },\r\n\r\n            { typeof(Tensor<C3b>), (c,o) => { var v = (Tensor<C3b>)o; c.CodeTensor_of_C3b_(ref v); } },\r\n            { typeof(Tensor<C3b>[]), (c,o) => { var v = (Tensor<C3b>[])o; c.CodeTensor_of_C3b_Array(ref v); } },\r\n            { typeof(List<Tensor<C3b>>), (c,o) => { var v = (List<Tensor<C3b>>)o; c.CodeList_of_Tensor_of_C3b__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C3us\r\n\r\n            { typeof(C3us), (c,o) => { var v = (C3us)o; c.CodeC3us(ref v); } },\r\n            { typeof(C3us[]), (c,o) => { var v = (C3us[])o; c.CodeC3usArray(ref v); } },\r\n            { typeof(List<C3us>), (c,o) => { var v = (List<C3us>)o; c.CodeList_of_C3us_(ref v); } },\r\n\r\n            { typeof(Vector<C3us>), (c,o) => { var v = (Vector<C3us>)o; c.CodeVector_of_C3us_(ref v); } },\r\n            { typeof(Vector<C3us>[]), (c,o) => { var v = (Vector<C3us>[])o; c.CodeVector_of_C3us_Array(ref v); } },\r\n            { typeof(List<Vector<C3us>>), (c,o) => { var v = (List<Vector<C3us>>)o; c.CodeList_of_Vector_of_C3us__(ref v); } },\r\n\r\n            { typeof(Matrix<C3us>), (c,o) => { var v = (Matrix<C3us>)o; c.CodeMatrix_of_C3us_(ref v); } },\r\n            { typeof(Matrix<C3us>[]), (c,o) => { var v = (Matrix<C3us>[])o; c.CodeMatrix_of_C3us_Array(ref v); } },\r\n            { typeof(List<Matrix<C3us>>), (c,o) => { var v = (List<Matrix<C3us>>)o; c.CodeList_of_Matrix_of_C3us__(ref v); } },\r\n\r\n            { typeof(Volume<C3us>), (c,o) => { var v = (Volume<C3us>)o; c.CodeVolume_of_C3us_(ref v); } },\r\n            { typeof(Volume<C3us>[]), (c,o) => { var v = (Volume<C3us>[])o; c.CodeVolume_of_C3us_Array(ref v); } },\r\n            { typeof(List<Volume<C3us>>), (c,o) => { var v = (List<Volume<C3us>>)o; c.CodeList_of_Volume_of_C3us__(ref v); } },\r\n\r\n            { typeof(Tensor<C3us>), (c,o) => { var v = (Tensor<C3us>)o; c.CodeTensor_of_C3us_(ref v); } },\r\n            { typeof(Tensor<C3us>[]), (c,o) => { var v = (Tensor<C3us>[])o; c.CodeTensor_of_C3us_Array(ref v); } },\r\n            { typeof(List<Tensor<C3us>>), (c,o) => { var v = (List<Tensor<C3us>>)o; c.CodeList_of_Tensor_of_C3us__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C3ui\r\n\r\n            { typeof(C3ui), (c,o) => { var v = (C3ui)o; c.CodeC3ui(ref v); } },\r\n            { typeof(C3ui[]), (c,o) => { var v = (C3ui[])o; c.CodeC3uiArray(ref v); } },\r\n            { typeof(List<C3ui>), (c,o) => { var v = (List<C3ui>)o; c.CodeList_of_C3ui_(ref v); } },\r\n\r\n            { typeof(Vector<C3ui>), (c,o) => { var v = (Vector<C3ui>)o; c.CodeVector_of_C3ui_(ref v); } },\r\n            { typeof(Vector<C3ui>[]), (c,o) => { var v = (Vector<C3ui>[])o; c.CodeVector_of_C3ui_Array(ref v); } },\r\n            { typeof(List<Vector<C3ui>>), (c,o) => { var v = (List<Vector<C3ui>>)o; c.CodeList_of_Vector_of_C3ui__(ref v); } },\r\n\r\n            { typeof(Matrix<C3ui>), (c,o) => { var v = (Matrix<C3ui>)o; c.CodeMatrix_of_C3ui_(ref v); } },\r\n            { typeof(Matrix<C3ui>[]), (c,o) => { var v = (Matrix<C3ui>[])o; c.CodeMatrix_of_C3ui_Array(ref v); } },\r\n            { typeof(List<Matrix<C3ui>>), (c,o) => { var v = (List<Matrix<C3ui>>)o; c.CodeList_of_Matrix_of_C3ui__(ref v); } },\r\n\r\n            { typeof(Volume<C3ui>), (c,o) => { var v = (Volume<C3ui>)o; c.CodeVolume_of_C3ui_(ref v); } },\r\n            { typeof(Volume<C3ui>[]), (c,o) => { var v = (Volume<C3ui>[])o; c.CodeVolume_of_C3ui_Array(ref v); } },\r\n            { typeof(List<Volume<C3ui>>), (c,o) => { var v = (List<Volume<C3ui>>)o; c.CodeList_of_Volume_of_C3ui__(ref v); } },\r\n\r\n            { typeof(Tensor<C3ui>), (c,o) => { var v = (Tensor<C3ui>)o; c.CodeTensor_of_C3ui_(ref v); } },\r\n            { typeof(Tensor<C3ui>[]), (c,o) => { var v = (Tensor<C3ui>[])o; c.CodeTensor_of_C3ui_Array(ref v); } },\r\n            { typeof(List<Tensor<C3ui>>), (c,o) => { var v = (List<Tensor<C3ui>>)o; c.CodeList_of_Tensor_of_C3ui__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C3f\r\n\r\n            { typeof(C3f), (c,o) => { var v = (C3f)o; c.CodeC3f(ref v); } },\r\n            { typeof(C3f[]), (c,o) => { var v = (C3f[])o; c.CodeC3fArray(ref v); } },\r\n            { typeof(List<C3f>), (c,o) => { var v = (List<C3f>)o; c.CodeList_of_C3f_(ref v); } },\r\n\r\n            { typeof(Vector<C3f>), (c,o) => { var v = (Vector<C3f>)o; c.CodeVector_of_C3f_(ref v); } },\r\n            { typeof(Vector<C3f>[]), (c,o) => { var v = (Vector<C3f>[])o; c.CodeVector_of_C3f_Array(ref v); } },\r\n            { typeof(List<Vector<C3f>>), (c,o) => { var v = (List<Vector<C3f>>)o; c.CodeList_of_Vector_of_C3f__(ref v); } },\r\n\r\n            { typeof(Matrix<C3f>), (c,o) => { var v = (Matrix<C3f>)o; c.CodeMatrix_of_C3f_(ref v); } },\r\n            { typeof(Matrix<C3f>[]), (c,o) => { var v = (Matrix<C3f>[])o; c.CodeMatrix_of_C3f_Array(ref v); } },\r\n            { typeof(List<Matrix<C3f>>), (c,o) => { var v = (List<Matrix<C3f>>)o; c.CodeList_of_Matrix_of_C3f__(ref v); } },\r\n\r\n            { typeof(Volume<C3f>), (c,o) => { var v = (Volume<C3f>)o; c.CodeVolume_of_C3f_(ref v); } },\r\n            { typeof(Volume<C3f>[]), (c,o) => { var v = (Volume<C3f>[])o; c.CodeVolume_of_C3f_Array(ref v); } },\r\n            { typeof(List<Volume<C3f>>), (c,o) => { var v = (List<Volume<C3f>>)o; c.CodeList_of_Volume_of_C3f__(ref v); } },\r\n\r\n            { typeof(Tensor<C3f>), (c,o) => { var v = (Tensor<C3f>)o; c.CodeTensor_of_C3f_(ref v); } },\r\n            { typeof(Tensor<C3f>[]), (c,o) => { var v = (Tensor<C3f>[])o; c.CodeTensor_of_C3f_Array(ref v); } },\r\n            { typeof(List<Tensor<C3f>>), (c,o) => { var v = (List<Tensor<C3f>>)o; c.CodeList_of_Tensor_of_C3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C3d\r\n\r\n            { typeof(C3d), (c,o) => { var v = (C3d)o; c.CodeC3d(ref v); } },\r\n            { typeof(C3d[]), (c,o) => { var v = (C3d[])o; c.CodeC3dArray(ref v); } },\r\n            { typeof(List<C3d>), (c,o) => { var v = (List<C3d>)o; c.CodeList_of_C3d_(ref v); } },\r\n\r\n            { typeof(Vector<C3d>), (c,o) => { var v = (Vector<C3d>)o; c.CodeVector_of_C3d_(ref v); } },\r\n            { typeof(Vector<C3d>[]), (c,o) => { var v = (Vector<C3d>[])o; c.CodeVector_of_C3d_Array(ref v); } },\r\n            { typeof(List<Vector<C3d>>), (c,o) => { var v = (List<Vector<C3d>>)o; c.CodeList_of_Vector_of_C3d__(ref v); } },\r\n\r\n            { typeof(Matrix<C3d>), (c,o) => { var v = (Matrix<C3d>)o; c.CodeMatrix_of_C3d_(ref v); } },\r\n            { typeof(Matrix<C3d>[]), (c,o) => { var v = (Matrix<C3d>[])o; c.CodeMatrix_of_C3d_Array(ref v); } },\r\n            { typeof(List<Matrix<C3d>>), (c,o) => { var v = (List<Matrix<C3d>>)o; c.CodeList_of_Matrix_of_C3d__(ref v); } },\r\n\r\n            { typeof(Volume<C3d>), (c,o) => { var v = (Volume<C3d>)o; c.CodeVolume_of_C3d_(ref v); } },\r\n            { typeof(Volume<C3d>[]), (c,o) => { var v = (Volume<C3d>[])o; c.CodeVolume_of_C3d_Array(ref v); } },\r\n            { typeof(List<Volume<C3d>>), (c,o) => { var v = (List<Volume<C3d>>)o; c.CodeList_of_Volume_of_C3d__(ref v); } },\r\n\r\n            { typeof(Tensor<C3d>), (c,o) => { var v = (Tensor<C3d>)o; c.CodeTensor_of_C3d_(ref v); } },\r\n            { typeof(Tensor<C3d>[]), (c,o) => { var v = (Tensor<C3d>[])o; c.CodeTensor_of_C3d_Array(ref v); } },\r\n            { typeof(List<Tensor<C3d>>), (c,o) => { var v = (List<Tensor<C3d>>)o; c.CodeList_of_Tensor_of_C3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C4b\r\n\r\n            { typeof(C4b), (c,o) => { var v = (C4b)o; c.CodeC4b(ref v); } },\r\n            { typeof(C4b[]), (c,o) => { var v = (C4b[])o; c.CodeC4bArray(ref v); } },\r\n            { typeof(List<C4b>), (c,o) => { var v = (List<C4b>)o; c.CodeList_of_C4b_(ref v); } },\r\n\r\n            { typeof(Vector<C4b>), (c,o) => { var v = (Vector<C4b>)o; c.CodeVector_of_C4b_(ref v); } },\r\n            { typeof(Vector<C4b>[]), (c,o) => { var v = (Vector<C4b>[])o; c.CodeVector_of_C4b_Array(ref v); } },\r\n            { typeof(List<Vector<C4b>>), (c,o) => { var v = (List<Vector<C4b>>)o; c.CodeList_of_Vector_of_C4b__(ref v); } },\r\n\r\n            { typeof(Matrix<C4b>), (c,o) => { var v = (Matrix<C4b>)o; c.CodeMatrix_of_C4b_(ref v); } },\r\n            { typeof(Matrix<C4b>[]), (c,o) => { var v = (Matrix<C4b>[])o; c.CodeMatrix_of_C4b_Array(ref v); } },\r\n            { typeof(List<Matrix<C4b>>), (c,o) => { var v = (List<Matrix<C4b>>)o; c.CodeList_of_Matrix_of_C4b__(ref v); } },\r\n\r\n            { typeof(Volume<C4b>), (c,o) => { var v = (Volume<C4b>)o; c.CodeVolume_of_C4b_(ref v); } },\r\n            { typeof(Volume<C4b>[]), (c,o) => { var v = (Volume<C4b>[])o; c.CodeVolume_of_C4b_Array(ref v); } },\r\n            { typeof(List<Volume<C4b>>), (c,o) => { var v = (List<Volume<C4b>>)o; c.CodeList_of_Volume_of_C4b__(ref v); } },\r\n\r\n            { typeof(Tensor<C4b>), (c,o) => { var v = (Tensor<C4b>)o; c.CodeTensor_of_C4b_(ref v); } },\r\n            { typeof(Tensor<C4b>[]), (c,o) => { var v = (Tensor<C4b>[])o; c.CodeTensor_of_C4b_Array(ref v); } },\r\n            { typeof(List<Tensor<C4b>>), (c,o) => { var v = (List<Tensor<C4b>>)o; c.CodeList_of_Tensor_of_C4b__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C4us\r\n\r\n            { typeof(C4us), (c,o) => { var v = (C4us)o; c.CodeC4us(ref v); } },\r\n            { typeof(C4us[]), (c,o) => { var v = (C4us[])o; c.CodeC4usArray(ref v); } },\r\n            { typeof(List<C4us>), (c,o) => { var v = (List<C4us>)o; c.CodeList_of_C4us_(ref v); } },\r\n\r\n            { typeof(Vector<C4us>), (c,o) => { var v = (Vector<C4us>)o; c.CodeVector_of_C4us_(ref v); } },\r\n            { typeof(Vector<C4us>[]), (c,o) => { var v = (Vector<C4us>[])o; c.CodeVector_of_C4us_Array(ref v); } },\r\n            { typeof(List<Vector<C4us>>), (c,o) => { var v = (List<Vector<C4us>>)o; c.CodeList_of_Vector_of_C4us__(ref v); } },\r\n\r\n            { typeof(Matrix<C4us>), (c,o) => { var v = (Matrix<C4us>)o; c.CodeMatrix_of_C4us_(ref v); } },\r\n            { typeof(Matrix<C4us>[]), (c,o) => { var v = (Matrix<C4us>[])o; c.CodeMatrix_of_C4us_Array(ref v); } },\r\n            { typeof(List<Matrix<C4us>>), (c,o) => { var v = (List<Matrix<C4us>>)o; c.CodeList_of_Matrix_of_C4us__(ref v); } },\r\n\r\n            { typeof(Volume<C4us>), (c,o) => { var v = (Volume<C4us>)o; c.CodeVolume_of_C4us_(ref v); } },\r\n            { typeof(Volume<C4us>[]), (c,o) => { var v = (Volume<C4us>[])o; c.CodeVolume_of_C4us_Array(ref v); } },\r\n            { typeof(List<Volume<C4us>>), (c,o) => { var v = (List<Volume<C4us>>)o; c.CodeList_of_Volume_of_C4us__(ref v); } },\r\n\r\n            { typeof(Tensor<C4us>), (c,o) => { var v = (Tensor<C4us>)o; c.CodeTensor_of_C4us_(ref v); } },\r\n            { typeof(Tensor<C4us>[]), (c,o) => { var v = (Tensor<C4us>[])o; c.CodeTensor_of_C4us_Array(ref v); } },\r\n            { typeof(List<Tensor<C4us>>), (c,o) => { var v = (List<Tensor<C4us>>)o; c.CodeList_of_Tensor_of_C4us__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C4ui\r\n\r\n            { typeof(C4ui), (c,o) => { var v = (C4ui)o; c.CodeC4ui(ref v); } },\r\n            { typeof(C4ui[]), (c,o) => { var v = (C4ui[])o; c.CodeC4uiArray(ref v); } },\r\n            { typeof(List<C4ui>), (c,o) => { var v = (List<C4ui>)o; c.CodeList_of_C4ui_(ref v); } },\r\n\r\n            { typeof(Vector<C4ui>), (c,o) => { var v = (Vector<C4ui>)o; c.CodeVector_of_C4ui_(ref v); } },\r\n            { typeof(Vector<C4ui>[]), (c,o) => { var v = (Vector<C4ui>[])o; c.CodeVector_of_C4ui_Array(ref v); } },\r\n            { typeof(List<Vector<C4ui>>), (c,o) => { var v = (List<Vector<C4ui>>)o; c.CodeList_of_Vector_of_C4ui__(ref v); } },\r\n\r\n            { typeof(Matrix<C4ui>), (c,o) => { var v = (Matrix<C4ui>)o; c.CodeMatrix_of_C4ui_(ref v); } },\r\n            { typeof(Matrix<C4ui>[]), (c,o) => { var v = (Matrix<C4ui>[])o; c.CodeMatrix_of_C4ui_Array(ref v); } },\r\n            { typeof(List<Matrix<C4ui>>), (c,o) => { var v = (List<Matrix<C4ui>>)o; c.CodeList_of_Matrix_of_C4ui__(ref v); } },\r\n\r\n            { typeof(Volume<C4ui>), (c,o) => { var v = (Volume<C4ui>)o; c.CodeVolume_of_C4ui_(ref v); } },\r\n            { typeof(Volume<C4ui>[]), (c,o) => { var v = (Volume<C4ui>[])o; c.CodeVolume_of_C4ui_Array(ref v); } },\r\n            { typeof(List<Volume<C4ui>>), (c,o) => { var v = (List<Volume<C4ui>>)o; c.CodeList_of_Volume_of_C4ui__(ref v); } },\r\n\r\n            { typeof(Tensor<C4ui>), (c,o) => { var v = (Tensor<C4ui>)o; c.CodeTensor_of_C4ui_(ref v); } },\r\n            { typeof(Tensor<C4ui>[]), (c,o) => { var v = (Tensor<C4ui>[])o; c.CodeTensor_of_C4ui_Array(ref v); } },\r\n            { typeof(List<Tensor<C4ui>>), (c,o) => { var v = (List<Tensor<C4ui>>)o; c.CodeList_of_Tensor_of_C4ui__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C4f\r\n\r\n            { typeof(C4f), (c,o) => { var v = (C4f)o; c.CodeC4f(ref v); } },\r\n            { typeof(C4f[]), (c,o) => { var v = (C4f[])o; c.CodeC4fArray(ref v); } },\r\n            { typeof(List<C4f>), (c,o) => { var v = (List<C4f>)o; c.CodeList_of_C4f_(ref v); } },\r\n\r\n            { typeof(Vector<C4f>), (c,o) => { var v = (Vector<C4f>)o; c.CodeVector_of_C4f_(ref v); } },\r\n            { typeof(Vector<C4f>[]), (c,o) => { var v = (Vector<C4f>[])o; c.CodeVector_of_C4f_Array(ref v); } },\r\n            { typeof(List<Vector<C4f>>), (c,o) => { var v = (List<Vector<C4f>>)o; c.CodeList_of_Vector_of_C4f__(ref v); } },\r\n\r\n            { typeof(Matrix<C4f>), (c,o) => { var v = (Matrix<C4f>)o; c.CodeMatrix_of_C4f_(ref v); } },\r\n            { typeof(Matrix<C4f>[]), (c,o) => { var v = (Matrix<C4f>[])o; c.CodeMatrix_of_C4f_Array(ref v); } },\r\n            { typeof(List<Matrix<C4f>>), (c,o) => { var v = (List<Matrix<C4f>>)o; c.CodeList_of_Matrix_of_C4f__(ref v); } },\r\n\r\n            { typeof(Volume<C4f>), (c,o) => { var v = (Volume<C4f>)o; c.CodeVolume_of_C4f_(ref v); } },\r\n            { typeof(Volume<C4f>[]), (c,o) => { var v = (Volume<C4f>[])o; c.CodeVolume_of_C4f_Array(ref v); } },\r\n            { typeof(List<Volume<C4f>>), (c,o) => { var v = (List<Volume<C4f>>)o; c.CodeList_of_Volume_of_C4f__(ref v); } },\r\n\r\n            { typeof(Tensor<C4f>), (c,o) => { var v = (Tensor<C4f>)o; c.CodeTensor_of_C4f_(ref v); } },\r\n            { typeof(Tensor<C4f>[]), (c,o) => { var v = (Tensor<C4f>[])o; c.CodeTensor_of_C4f_Array(ref v); } },\r\n            { typeof(List<Tensor<C4f>>), (c,o) => { var v = (List<Tensor<C4f>>)o; c.CodeList_of_Tensor_of_C4f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region C4d\r\n\r\n            { typeof(C4d), (c,o) => { var v = (C4d)o; c.CodeC4d(ref v); } },\r\n            { typeof(C4d[]), (c,o) => { var v = (C4d[])o; c.CodeC4dArray(ref v); } },\r\n            { typeof(List<C4d>), (c,o) => { var v = (List<C4d>)o; c.CodeList_of_C4d_(ref v); } },\r\n\r\n            { typeof(Vector<C4d>), (c,o) => { var v = (Vector<C4d>)o; c.CodeVector_of_C4d_(ref v); } },\r\n            { typeof(Vector<C4d>[]), (c,o) => { var v = (Vector<C4d>[])o; c.CodeVector_of_C4d_Array(ref v); } },\r\n            { typeof(List<Vector<C4d>>), (c,o) => { var v = (List<Vector<C4d>>)o; c.CodeList_of_Vector_of_C4d__(ref v); } },\r\n\r\n            { typeof(Matrix<C4d>), (c,o) => { var v = (Matrix<C4d>)o; c.CodeMatrix_of_C4d_(ref v); } },\r\n            { typeof(Matrix<C4d>[]), (c,o) => { var v = (Matrix<C4d>[])o; c.CodeMatrix_of_C4d_Array(ref v); } },\r\n            { typeof(List<Matrix<C4d>>), (c,o) => { var v = (List<Matrix<C4d>>)o; c.CodeList_of_Matrix_of_C4d__(ref v); } },\r\n\r\n            { typeof(Volume<C4d>), (c,o) => { var v = (Volume<C4d>)o; c.CodeVolume_of_C4d_(ref v); } },\r\n            { typeof(Volume<C4d>[]), (c,o) => { var v = (Volume<C4d>[])o; c.CodeVolume_of_C4d_Array(ref v); } },\r\n            { typeof(List<Volume<C4d>>), (c,o) => { var v = (List<Volume<C4d>>)o; c.CodeList_of_Volume_of_C4d__(ref v); } },\r\n\r\n            { typeof(Tensor<C4d>), (c,o) => { var v = (Tensor<C4d>)o; c.CodeTensor_of_C4d_(ref v); } },\r\n            { typeof(Tensor<C4d>[]), (c,o) => { var v = (Tensor<C4d>[])o; c.CodeTensor_of_C4d_Array(ref v); } },\r\n            { typeof(List<Tensor<C4d>>), (c,o) => { var v = (List<Tensor<C4d>>)o; c.CodeList_of_Tensor_of_C4d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1b\r\n\r\n            { typeof(Range1b), (c,o) => { var v = (Range1b)o; c.CodeRange1b(ref v); } },\r\n            { typeof(Range1b[]), (c,o) => { var v = (Range1b[])o; c.CodeRange1bArray(ref v); } },\r\n            { typeof(List<Range1b>), (c,o) => { var v = (List<Range1b>)o; c.CodeList_of_Range1b_(ref v); } },\r\n\r\n            { typeof(Vector<Range1b>), (c,o) => { var v = (Vector<Range1b>)o; c.CodeVector_of_Range1b_(ref v); } },\r\n            { typeof(Vector<Range1b>[]), (c,o) => { var v = (Vector<Range1b>[])o; c.CodeVector_of_Range1b_Array(ref v); } },\r\n            { typeof(List<Vector<Range1b>>), (c,o) => { var v = (List<Vector<Range1b>>)o; c.CodeList_of_Vector_of_Range1b__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1b>), (c,o) => { var v = (Matrix<Range1b>)o; c.CodeMatrix_of_Range1b_(ref v); } },\r\n            { typeof(Matrix<Range1b>[]), (c,o) => { var v = (Matrix<Range1b>[])o; c.CodeMatrix_of_Range1b_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1b>>), (c,o) => { var v = (List<Matrix<Range1b>>)o; c.CodeList_of_Matrix_of_Range1b__(ref v); } },\r\n\r\n            { typeof(Volume<Range1b>), (c,o) => { var v = (Volume<Range1b>)o; c.CodeVolume_of_Range1b_(ref v); } },\r\n            { typeof(Volume<Range1b>[]), (c,o) => { var v = (Volume<Range1b>[])o; c.CodeVolume_of_Range1b_Array(ref v); } },\r\n            { typeof(List<Volume<Range1b>>), (c,o) => { var v = (List<Volume<Range1b>>)o; c.CodeList_of_Volume_of_Range1b__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1b>), (c,o) => { var v = (Tensor<Range1b>)o; c.CodeTensor_of_Range1b_(ref v); } },\r\n            { typeof(Tensor<Range1b>[]), (c,o) => { var v = (Tensor<Range1b>[])o; c.CodeTensor_of_Range1b_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1b>>), (c,o) => { var v = (List<Tensor<Range1b>>)o; c.CodeList_of_Tensor_of_Range1b__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1sb\r\n\r\n            { typeof(Range1sb), (c,o) => { var v = (Range1sb)o; c.CodeRange1sb(ref v); } },\r\n            { typeof(Range1sb[]), (c,o) => { var v = (Range1sb[])o; c.CodeRange1sbArray(ref v); } },\r\n            { typeof(List<Range1sb>), (c,o) => { var v = (List<Range1sb>)o; c.CodeList_of_Range1sb_(ref v); } },\r\n\r\n            { typeof(Vector<Range1sb>), (c,o) => { var v = (Vector<Range1sb>)o; c.CodeVector_of_Range1sb_(ref v); } },\r\n            { typeof(Vector<Range1sb>[]), (c,o) => { var v = (Vector<Range1sb>[])o; c.CodeVector_of_Range1sb_Array(ref v); } },\r\n            { typeof(List<Vector<Range1sb>>), (c,o) => { var v = (List<Vector<Range1sb>>)o; c.CodeList_of_Vector_of_Range1sb__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1sb>), (c,o) => { var v = (Matrix<Range1sb>)o; c.CodeMatrix_of_Range1sb_(ref v); } },\r\n            { typeof(Matrix<Range1sb>[]), (c,o) => { var v = (Matrix<Range1sb>[])o; c.CodeMatrix_of_Range1sb_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1sb>>), (c,o) => { var v = (List<Matrix<Range1sb>>)o; c.CodeList_of_Matrix_of_Range1sb__(ref v); } },\r\n\r\n            { typeof(Volume<Range1sb>), (c,o) => { var v = (Volume<Range1sb>)o; c.CodeVolume_of_Range1sb_(ref v); } },\r\n            { typeof(Volume<Range1sb>[]), (c,o) => { var v = (Volume<Range1sb>[])o; c.CodeVolume_of_Range1sb_Array(ref v); } },\r\n            { typeof(List<Volume<Range1sb>>), (c,o) => { var v = (List<Volume<Range1sb>>)o; c.CodeList_of_Volume_of_Range1sb__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1sb>), (c,o) => { var v = (Tensor<Range1sb>)o; c.CodeTensor_of_Range1sb_(ref v); } },\r\n            { typeof(Tensor<Range1sb>[]), (c,o) => { var v = (Tensor<Range1sb>[])o; c.CodeTensor_of_Range1sb_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1sb>>), (c,o) => { var v = (List<Tensor<Range1sb>>)o; c.CodeList_of_Tensor_of_Range1sb__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1s\r\n\r\n            { typeof(Range1s), (c,o) => { var v = (Range1s)o; c.CodeRange1s(ref v); } },\r\n            { typeof(Range1s[]), (c,o) => { var v = (Range1s[])o; c.CodeRange1sArray(ref v); } },\r\n            { typeof(List<Range1s>), (c,o) => { var v = (List<Range1s>)o; c.CodeList_of_Range1s_(ref v); } },\r\n\r\n            { typeof(Vector<Range1s>), (c,o) => { var v = (Vector<Range1s>)o; c.CodeVector_of_Range1s_(ref v); } },\r\n            { typeof(Vector<Range1s>[]), (c,o) => { var v = (Vector<Range1s>[])o; c.CodeVector_of_Range1s_Array(ref v); } },\r\n            { typeof(List<Vector<Range1s>>), (c,o) => { var v = (List<Vector<Range1s>>)o; c.CodeList_of_Vector_of_Range1s__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1s>), (c,o) => { var v = (Matrix<Range1s>)o; c.CodeMatrix_of_Range1s_(ref v); } },\r\n            { typeof(Matrix<Range1s>[]), (c,o) => { var v = (Matrix<Range1s>[])o; c.CodeMatrix_of_Range1s_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1s>>), (c,o) => { var v = (List<Matrix<Range1s>>)o; c.CodeList_of_Matrix_of_Range1s__(ref v); } },\r\n\r\n            { typeof(Volume<Range1s>), (c,o) => { var v = (Volume<Range1s>)o; c.CodeVolume_of_Range1s_(ref v); } },\r\n            { typeof(Volume<Range1s>[]), (c,o) => { var v = (Volume<Range1s>[])o; c.CodeVolume_of_Range1s_Array(ref v); } },\r\n            { typeof(List<Volume<Range1s>>), (c,o) => { var v = (List<Volume<Range1s>>)o; c.CodeList_of_Volume_of_Range1s__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1s>), (c,o) => { var v = (Tensor<Range1s>)o; c.CodeTensor_of_Range1s_(ref v); } },\r\n            { typeof(Tensor<Range1s>[]), (c,o) => { var v = (Tensor<Range1s>[])o; c.CodeTensor_of_Range1s_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1s>>), (c,o) => { var v = (List<Tensor<Range1s>>)o; c.CodeList_of_Tensor_of_Range1s__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1us\r\n\r\n            { typeof(Range1us), (c,o) => { var v = (Range1us)o; c.CodeRange1us(ref v); } },\r\n            { typeof(Range1us[]), (c,o) => { var v = (Range1us[])o; c.CodeRange1usArray(ref v); } },\r\n            { typeof(List<Range1us>), (c,o) => { var v = (List<Range1us>)o; c.CodeList_of_Range1us_(ref v); } },\r\n\r\n            { typeof(Vector<Range1us>), (c,o) => { var v = (Vector<Range1us>)o; c.CodeVector_of_Range1us_(ref v); } },\r\n            { typeof(Vector<Range1us>[]), (c,o) => { var v = (Vector<Range1us>[])o; c.CodeVector_of_Range1us_Array(ref v); } },\r\n            { typeof(List<Vector<Range1us>>), (c,o) => { var v = (List<Vector<Range1us>>)o; c.CodeList_of_Vector_of_Range1us__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1us>), (c,o) => { var v = (Matrix<Range1us>)o; c.CodeMatrix_of_Range1us_(ref v); } },\r\n            { typeof(Matrix<Range1us>[]), (c,o) => { var v = (Matrix<Range1us>[])o; c.CodeMatrix_of_Range1us_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1us>>), (c,o) => { var v = (List<Matrix<Range1us>>)o; c.CodeList_of_Matrix_of_Range1us__(ref v); } },\r\n\r\n            { typeof(Volume<Range1us>), (c,o) => { var v = (Volume<Range1us>)o; c.CodeVolume_of_Range1us_(ref v); } },\r\n            { typeof(Volume<Range1us>[]), (c,o) => { var v = (Volume<Range1us>[])o; c.CodeVolume_of_Range1us_Array(ref v); } },\r\n            { typeof(List<Volume<Range1us>>), (c,o) => { var v = (List<Volume<Range1us>>)o; c.CodeList_of_Volume_of_Range1us__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1us>), (c,o) => { var v = (Tensor<Range1us>)o; c.CodeTensor_of_Range1us_(ref v); } },\r\n            { typeof(Tensor<Range1us>[]), (c,o) => { var v = (Tensor<Range1us>[])o; c.CodeTensor_of_Range1us_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1us>>), (c,o) => { var v = (List<Tensor<Range1us>>)o; c.CodeList_of_Tensor_of_Range1us__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1i\r\n\r\n            { typeof(Range1i), (c,o) => { var v = (Range1i)o; c.CodeRange1i(ref v); } },\r\n            { typeof(Range1i[]), (c,o) => { var v = (Range1i[])o; c.CodeRange1iArray(ref v); } },\r\n            { typeof(List<Range1i>), (c,o) => { var v = (List<Range1i>)o; c.CodeList_of_Range1i_(ref v); } },\r\n\r\n            { typeof(Vector<Range1i>), (c,o) => { var v = (Vector<Range1i>)o; c.CodeVector_of_Range1i_(ref v); } },\r\n            { typeof(Vector<Range1i>[]), (c,o) => { var v = (Vector<Range1i>[])o; c.CodeVector_of_Range1i_Array(ref v); } },\r\n            { typeof(List<Vector<Range1i>>), (c,o) => { var v = (List<Vector<Range1i>>)o; c.CodeList_of_Vector_of_Range1i__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1i>), (c,o) => { var v = (Matrix<Range1i>)o; c.CodeMatrix_of_Range1i_(ref v); } },\r\n            { typeof(Matrix<Range1i>[]), (c,o) => { var v = (Matrix<Range1i>[])o; c.CodeMatrix_of_Range1i_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1i>>), (c,o) => { var v = (List<Matrix<Range1i>>)o; c.CodeList_of_Matrix_of_Range1i__(ref v); } },\r\n\r\n            { typeof(Volume<Range1i>), (c,o) => { var v = (Volume<Range1i>)o; c.CodeVolume_of_Range1i_(ref v); } },\r\n            { typeof(Volume<Range1i>[]), (c,o) => { var v = (Volume<Range1i>[])o; c.CodeVolume_of_Range1i_Array(ref v); } },\r\n            { typeof(List<Volume<Range1i>>), (c,o) => { var v = (List<Volume<Range1i>>)o; c.CodeList_of_Volume_of_Range1i__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1i>), (c,o) => { var v = (Tensor<Range1i>)o; c.CodeTensor_of_Range1i_(ref v); } },\r\n            { typeof(Tensor<Range1i>[]), (c,o) => { var v = (Tensor<Range1i>[])o; c.CodeTensor_of_Range1i_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1i>>), (c,o) => { var v = (List<Tensor<Range1i>>)o; c.CodeList_of_Tensor_of_Range1i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1ui\r\n\r\n            { typeof(Range1ui), (c,o) => { var v = (Range1ui)o; c.CodeRange1ui(ref v); } },\r\n            { typeof(Range1ui[]), (c,o) => { var v = (Range1ui[])o; c.CodeRange1uiArray(ref v); } },\r\n            { typeof(List<Range1ui>), (c,o) => { var v = (List<Range1ui>)o; c.CodeList_of_Range1ui_(ref v); } },\r\n\r\n            { typeof(Vector<Range1ui>), (c,o) => { var v = (Vector<Range1ui>)o; c.CodeVector_of_Range1ui_(ref v); } },\r\n            { typeof(Vector<Range1ui>[]), (c,o) => { var v = (Vector<Range1ui>[])o; c.CodeVector_of_Range1ui_Array(ref v); } },\r\n            { typeof(List<Vector<Range1ui>>), (c,o) => { var v = (List<Vector<Range1ui>>)o; c.CodeList_of_Vector_of_Range1ui__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1ui>), (c,o) => { var v = (Matrix<Range1ui>)o; c.CodeMatrix_of_Range1ui_(ref v); } },\r\n            { typeof(Matrix<Range1ui>[]), (c,o) => { var v = (Matrix<Range1ui>[])o; c.CodeMatrix_of_Range1ui_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1ui>>), (c,o) => { var v = (List<Matrix<Range1ui>>)o; c.CodeList_of_Matrix_of_Range1ui__(ref v); } },\r\n\r\n            { typeof(Volume<Range1ui>), (c,o) => { var v = (Volume<Range1ui>)o; c.CodeVolume_of_Range1ui_(ref v); } },\r\n            { typeof(Volume<Range1ui>[]), (c,o) => { var v = (Volume<Range1ui>[])o; c.CodeVolume_of_Range1ui_Array(ref v); } },\r\n            { typeof(List<Volume<Range1ui>>), (c,o) => { var v = (List<Volume<Range1ui>>)o; c.CodeList_of_Volume_of_Range1ui__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1ui>), (c,o) => { var v = (Tensor<Range1ui>)o; c.CodeTensor_of_Range1ui_(ref v); } },\r\n            { typeof(Tensor<Range1ui>[]), (c,o) => { var v = (Tensor<Range1ui>[])o; c.CodeTensor_of_Range1ui_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1ui>>), (c,o) => { var v = (List<Tensor<Range1ui>>)o; c.CodeList_of_Tensor_of_Range1ui__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1l\r\n\r\n            { typeof(Range1l), (c,o) => { var v = (Range1l)o; c.CodeRange1l(ref v); } },\r\n            { typeof(Range1l[]), (c,o) => { var v = (Range1l[])o; c.CodeRange1lArray(ref v); } },\r\n            { typeof(List<Range1l>), (c,o) => { var v = (List<Range1l>)o; c.CodeList_of_Range1l_(ref v); } },\r\n\r\n            { typeof(Vector<Range1l>), (c,o) => { var v = (Vector<Range1l>)o; c.CodeVector_of_Range1l_(ref v); } },\r\n            { typeof(Vector<Range1l>[]), (c,o) => { var v = (Vector<Range1l>[])o; c.CodeVector_of_Range1l_Array(ref v); } },\r\n            { typeof(List<Vector<Range1l>>), (c,o) => { var v = (List<Vector<Range1l>>)o; c.CodeList_of_Vector_of_Range1l__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1l>), (c,o) => { var v = (Matrix<Range1l>)o; c.CodeMatrix_of_Range1l_(ref v); } },\r\n            { typeof(Matrix<Range1l>[]), (c,o) => { var v = (Matrix<Range1l>[])o; c.CodeMatrix_of_Range1l_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1l>>), (c,o) => { var v = (List<Matrix<Range1l>>)o; c.CodeList_of_Matrix_of_Range1l__(ref v); } },\r\n\r\n            { typeof(Volume<Range1l>), (c,o) => { var v = (Volume<Range1l>)o; c.CodeVolume_of_Range1l_(ref v); } },\r\n            { typeof(Volume<Range1l>[]), (c,o) => { var v = (Volume<Range1l>[])o; c.CodeVolume_of_Range1l_Array(ref v); } },\r\n            { typeof(List<Volume<Range1l>>), (c,o) => { var v = (List<Volume<Range1l>>)o; c.CodeList_of_Volume_of_Range1l__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1l>), (c,o) => { var v = (Tensor<Range1l>)o; c.CodeTensor_of_Range1l_(ref v); } },\r\n            { typeof(Tensor<Range1l>[]), (c,o) => { var v = (Tensor<Range1l>[])o; c.CodeTensor_of_Range1l_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1l>>), (c,o) => { var v = (List<Tensor<Range1l>>)o; c.CodeList_of_Tensor_of_Range1l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1ul\r\n\r\n            { typeof(Range1ul), (c,o) => { var v = (Range1ul)o; c.CodeRange1ul(ref v); } },\r\n            { typeof(Range1ul[]), (c,o) => { var v = (Range1ul[])o; c.CodeRange1ulArray(ref v); } },\r\n            { typeof(List<Range1ul>), (c,o) => { var v = (List<Range1ul>)o; c.CodeList_of_Range1ul_(ref v); } },\r\n\r\n            { typeof(Vector<Range1ul>), (c,o) => { var v = (Vector<Range1ul>)o; c.CodeVector_of_Range1ul_(ref v); } },\r\n            { typeof(Vector<Range1ul>[]), (c,o) => { var v = (Vector<Range1ul>[])o; c.CodeVector_of_Range1ul_Array(ref v); } },\r\n            { typeof(List<Vector<Range1ul>>), (c,o) => { var v = (List<Vector<Range1ul>>)o; c.CodeList_of_Vector_of_Range1ul__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1ul>), (c,o) => { var v = (Matrix<Range1ul>)o; c.CodeMatrix_of_Range1ul_(ref v); } },\r\n            { typeof(Matrix<Range1ul>[]), (c,o) => { var v = (Matrix<Range1ul>[])o; c.CodeMatrix_of_Range1ul_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1ul>>), (c,o) => { var v = (List<Matrix<Range1ul>>)o; c.CodeList_of_Matrix_of_Range1ul__(ref v); } },\r\n\r\n            { typeof(Volume<Range1ul>), (c,o) => { var v = (Volume<Range1ul>)o; c.CodeVolume_of_Range1ul_(ref v); } },\r\n            { typeof(Volume<Range1ul>[]), (c,o) => { var v = (Volume<Range1ul>[])o; c.CodeVolume_of_Range1ul_Array(ref v); } },\r\n            { typeof(List<Volume<Range1ul>>), (c,o) => { var v = (List<Volume<Range1ul>>)o; c.CodeList_of_Volume_of_Range1ul__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1ul>), (c,o) => { var v = (Tensor<Range1ul>)o; c.CodeTensor_of_Range1ul_(ref v); } },\r\n            { typeof(Tensor<Range1ul>[]), (c,o) => { var v = (Tensor<Range1ul>[])o; c.CodeTensor_of_Range1ul_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1ul>>), (c,o) => { var v = (List<Tensor<Range1ul>>)o; c.CodeList_of_Tensor_of_Range1ul__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1f\r\n\r\n            { typeof(Range1f), (c,o) => { var v = (Range1f)o; c.CodeRange1f(ref v); } },\r\n            { typeof(Range1f[]), (c,o) => { var v = (Range1f[])o; c.CodeRange1fArray(ref v); } },\r\n            { typeof(List<Range1f>), (c,o) => { var v = (List<Range1f>)o; c.CodeList_of_Range1f_(ref v); } },\r\n\r\n            { typeof(Vector<Range1f>), (c,o) => { var v = (Vector<Range1f>)o; c.CodeVector_of_Range1f_(ref v); } },\r\n            { typeof(Vector<Range1f>[]), (c,o) => { var v = (Vector<Range1f>[])o; c.CodeVector_of_Range1f_Array(ref v); } },\r\n            { typeof(List<Vector<Range1f>>), (c,o) => { var v = (List<Vector<Range1f>>)o; c.CodeList_of_Vector_of_Range1f__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1f>), (c,o) => { var v = (Matrix<Range1f>)o; c.CodeMatrix_of_Range1f_(ref v); } },\r\n            { typeof(Matrix<Range1f>[]), (c,o) => { var v = (Matrix<Range1f>[])o; c.CodeMatrix_of_Range1f_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1f>>), (c,o) => { var v = (List<Matrix<Range1f>>)o; c.CodeList_of_Matrix_of_Range1f__(ref v); } },\r\n\r\n            { typeof(Volume<Range1f>), (c,o) => { var v = (Volume<Range1f>)o; c.CodeVolume_of_Range1f_(ref v); } },\r\n            { typeof(Volume<Range1f>[]), (c,o) => { var v = (Volume<Range1f>[])o; c.CodeVolume_of_Range1f_Array(ref v); } },\r\n            { typeof(List<Volume<Range1f>>), (c,o) => { var v = (List<Volume<Range1f>>)o; c.CodeList_of_Volume_of_Range1f__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1f>), (c,o) => { var v = (Tensor<Range1f>)o; c.CodeTensor_of_Range1f_(ref v); } },\r\n            { typeof(Tensor<Range1f>[]), (c,o) => { var v = (Tensor<Range1f>[])o; c.CodeTensor_of_Range1f_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1f>>), (c,o) => { var v = (List<Tensor<Range1f>>)o; c.CodeList_of_Tensor_of_Range1f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Range1d\r\n\r\n            { typeof(Range1d), (c,o) => { var v = (Range1d)o; c.CodeRange1d(ref v); } },\r\n            { typeof(Range1d[]), (c,o) => { var v = (Range1d[])o; c.CodeRange1dArray(ref v); } },\r\n            { typeof(List<Range1d>), (c,o) => { var v = (List<Range1d>)o; c.CodeList_of_Range1d_(ref v); } },\r\n\r\n            { typeof(Vector<Range1d>), (c,o) => { var v = (Vector<Range1d>)o; c.CodeVector_of_Range1d_(ref v); } },\r\n            { typeof(Vector<Range1d>[]), (c,o) => { var v = (Vector<Range1d>[])o; c.CodeVector_of_Range1d_Array(ref v); } },\r\n            { typeof(List<Vector<Range1d>>), (c,o) => { var v = (List<Vector<Range1d>>)o; c.CodeList_of_Vector_of_Range1d__(ref v); } },\r\n\r\n            { typeof(Matrix<Range1d>), (c,o) => { var v = (Matrix<Range1d>)o; c.CodeMatrix_of_Range1d_(ref v); } },\r\n            { typeof(Matrix<Range1d>[]), (c,o) => { var v = (Matrix<Range1d>[])o; c.CodeMatrix_of_Range1d_Array(ref v); } },\r\n            { typeof(List<Matrix<Range1d>>), (c,o) => { var v = (List<Matrix<Range1d>>)o; c.CodeList_of_Matrix_of_Range1d__(ref v); } },\r\n\r\n            { typeof(Volume<Range1d>), (c,o) => { var v = (Volume<Range1d>)o; c.CodeVolume_of_Range1d_(ref v); } },\r\n            { typeof(Volume<Range1d>[]), (c,o) => { var v = (Volume<Range1d>[])o; c.CodeVolume_of_Range1d_Array(ref v); } },\r\n            { typeof(List<Volume<Range1d>>), (c,o) => { var v = (List<Volume<Range1d>>)o; c.CodeList_of_Volume_of_Range1d__(ref v); } },\r\n\r\n            { typeof(Tensor<Range1d>), (c,o) => { var v = (Tensor<Range1d>)o; c.CodeTensor_of_Range1d_(ref v); } },\r\n            { typeof(Tensor<Range1d>[]), (c,o) => { var v = (Tensor<Range1d>[])o; c.CodeTensor_of_Range1d_Array(ref v); } },\r\n            { typeof(List<Tensor<Range1d>>), (c,o) => { var v = (List<Tensor<Range1d>>)o; c.CodeList_of_Tensor_of_Range1d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Box2i\r\n\r\n            { typeof(Box2i), (c,o) => { var v = (Box2i)o; c.CodeBox2i(ref v); } },\r\n            { typeof(Box2i[]), (c,o) => { var v = (Box2i[])o; c.CodeBox2iArray(ref v); } },\r\n            { typeof(List<Box2i>), (c,o) => { var v = (List<Box2i>)o; c.CodeList_of_Box2i_(ref v); } },\r\n\r\n            { typeof(Vector<Box2i>), (c,o) => { var v = (Vector<Box2i>)o; c.CodeVector_of_Box2i_(ref v); } },\r\n            { typeof(Vector<Box2i>[]), (c,o) => { var v = (Vector<Box2i>[])o; c.CodeVector_of_Box2i_Array(ref v); } },\r\n            { typeof(List<Vector<Box2i>>), (c,o) => { var v = (List<Vector<Box2i>>)o; c.CodeList_of_Vector_of_Box2i__(ref v); } },\r\n\r\n            { typeof(Matrix<Box2i>), (c,o) => { var v = (Matrix<Box2i>)o; c.CodeMatrix_of_Box2i_(ref v); } },\r\n            { typeof(Matrix<Box2i>[]), (c,o) => { var v = (Matrix<Box2i>[])o; c.CodeMatrix_of_Box2i_Array(ref v); } },\r\n            { typeof(List<Matrix<Box2i>>), (c,o) => { var v = (List<Matrix<Box2i>>)o; c.CodeList_of_Matrix_of_Box2i__(ref v); } },\r\n\r\n            { typeof(Volume<Box2i>), (c,o) => { var v = (Volume<Box2i>)o; c.CodeVolume_of_Box2i_(ref v); } },\r\n            { typeof(Volume<Box2i>[]), (c,o) => { var v = (Volume<Box2i>[])o; c.CodeVolume_of_Box2i_Array(ref v); } },\r\n            { typeof(List<Volume<Box2i>>), (c,o) => { var v = (List<Volume<Box2i>>)o; c.CodeList_of_Volume_of_Box2i__(ref v); } },\r\n\r\n            { typeof(Tensor<Box2i>), (c,o) => { var v = (Tensor<Box2i>)o; c.CodeTensor_of_Box2i_(ref v); } },\r\n            { typeof(Tensor<Box2i>[]), (c,o) => { var v = (Tensor<Box2i>[])o; c.CodeTensor_of_Box2i_Array(ref v); } },\r\n            { typeof(List<Tensor<Box2i>>), (c,o) => { var v = (List<Tensor<Box2i>>)o; c.CodeList_of_Tensor_of_Box2i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Box2l\r\n\r\n            { typeof(Box2l), (c,o) => { var v = (Box2l)o; c.CodeBox2l(ref v); } },\r\n            { typeof(Box2l[]), (c,o) => { var v = (Box2l[])o; c.CodeBox2lArray(ref v); } },\r\n            { typeof(List<Box2l>), (c,o) => { var v = (List<Box2l>)o; c.CodeList_of_Box2l_(ref v); } },\r\n\r\n            { typeof(Vector<Box2l>), (c,o) => { var v = (Vector<Box2l>)o; c.CodeVector_of_Box2l_(ref v); } },\r\n            { typeof(Vector<Box2l>[]), (c,o) => { var v = (Vector<Box2l>[])o; c.CodeVector_of_Box2l_Array(ref v); } },\r\n            { typeof(List<Vector<Box2l>>), (c,o) => { var v = (List<Vector<Box2l>>)o; c.CodeList_of_Vector_of_Box2l__(ref v); } },\r\n\r\n            { typeof(Matrix<Box2l>), (c,o) => { var v = (Matrix<Box2l>)o; c.CodeMatrix_of_Box2l_(ref v); } },\r\n            { typeof(Matrix<Box2l>[]), (c,o) => { var v = (Matrix<Box2l>[])o; c.CodeMatrix_of_Box2l_Array(ref v); } },\r\n            { typeof(List<Matrix<Box2l>>), (c,o) => { var v = (List<Matrix<Box2l>>)o; c.CodeList_of_Matrix_of_Box2l__(ref v); } },\r\n\r\n            { typeof(Volume<Box2l>), (c,o) => { var v = (Volume<Box2l>)o; c.CodeVolume_of_Box2l_(ref v); } },\r\n            { typeof(Volume<Box2l>[]), (c,o) => { var v = (Volume<Box2l>[])o; c.CodeVolume_of_Box2l_Array(ref v); } },\r\n            { typeof(List<Volume<Box2l>>), (c,o) => { var v = (List<Volume<Box2l>>)o; c.CodeList_of_Volume_of_Box2l__(ref v); } },\r\n\r\n            { typeof(Tensor<Box2l>), (c,o) => { var v = (Tensor<Box2l>)o; c.CodeTensor_of_Box2l_(ref v); } },\r\n            { typeof(Tensor<Box2l>[]), (c,o) => { var v = (Tensor<Box2l>[])o; c.CodeTensor_of_Box2l_Array(ref v); } },\r\n            { typeof(List<Tensor<Box2l>>), (c,o) => { var v = (List<Tensor<Box2l>>)o; c.CodeList_of_Tensor_of_Box2l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Box2f\r\n\r\n            { typeof(Box2f), (c,o) => { var v = (Box2f)o; c.CodeBox2f(ref v); } },\r\n            { typeof(Box2f[]), (c,o) => { var v = (Box2f[])o; c.CodeBox2fArray(ref v); } },\r\n            { typeof(List<Box2f>), (c,o) => { var v = (List<Box2f>)o; c.CodeList_of_Box2f_(ref v); } },\r\n\r\n            { typeof(Vector<Box2f>), (c,o) => { var v = (Vector<Box2f>)o; c.CodeVector_of_Box2f_(ref v); } },\r\n            { typeof(Vector<Box2f>[]), (c,o) => { var v = (Vector<Box2f>[])o; c.CodeVector_of_Box2f_Array(ref v); } },\r\n            { typeof(List<Vector<Box2f>>), (c,o) => { var v = (List<Vector<Box2f>>)o; c.CodeList_of_Vector_of_Box2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Box2f>), (c,o) => { var v = (Matrix<Box2f>)o; c.CodeMatrix_of_Box2f_(ref v); } },\r\n            { typeof(Matrix<Box2f>[]), (c,o) => { var v = (Matrix<Box2f>[])o; c.CodeMatrix_of_Box2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Box2f>>), (c,o) => { var v = (List<Matrix<Box2f>>)o; c.CodeList_of_Matrix_of_Box2f__(ref v); } },\r\n\r\n            { typeof(Volume<Box2f>), (c,o) => { var v = (Volume<Box2f>)o; c.CodeVolume_of_Box2f_(ref v); } },\r\n            { typeof(Volume<Box2f>[]), (c,o) => { var v = (Volume<Box2f>[])o; c.CodeVolume_of_Box2f_Array(ref v); } },\r\n            { typeof(List<Volume<Box2f>>), (c,o) => { var v = (List<Volume<Box2f>>)o; c.CodeList_of_Volume_of_Box2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Box2f>), (c,o) => { var v = (Tensor<Box2f>)o; c.CodeTensor_of_Box2f_(ref v); } },\r\n            { typeof(Tensor<Box2f>[]), (c,o) => { var v = (Tensor<Box2f>[])o; c.CodeTensor_of_Box2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Box2f>>), (c,o) => { var v = (List<Tensor<Box2f>>)o; c.CodeList_of_Tensor_of_Box2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Box2d\r\n\r\n            { typeof(Box2d), (c,o) => { var v = (Box2d)o; c.CodeBox2d(ref v); } },\r\n            { typeof(Box2d[]), (c,o) => { var v = (Box2d[])o; c.CodeBox2dArray(ref v); } },\r\n            { typeof(List<Box2d>), (c,o) => { var v = (List<Box2d>)o; c.CodeList_of_Box2d_(ref v); } },\r\n\r\n            { typeof(Vector<Box2d>), (c,o) => { var v = (Vector<Box2d>)o; c.CodeVector_of_Box2d_(ref v); } },\r\n            { typeof(Vector<Box2d>[]), (c,o) => { var v = (Vector<Box2d>[])o; c.CodeVector_of_Box2d_Array(ref v); } },\r\n            { typeof(List<Vector<Box2d>>), (c,o) => { var v = (List<Vector<Box2d>>)o; c.CodeList_of_Vector_of_Box2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Box2d>), (c,o) => { var v = (Matrix<Box2d>)o; c.CodeMatrix_of_Box2d_(ref v); } },\r\n            { typeof(Matrix<Box2d>[]), (c,o) => { var v = (Matrix<Box2d>[])o; c.CodeMatrix_of_Box2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Box2d>>), (c,o) => { var v = (List<Matrix<Box2d>>)o; c.CodeList_of_Matrix_of_Box2d__(ref v); } },\r\n\r\n            { typeof(Volume<Box2d>), (c,o) => { var v = (Volume<Box2d>)o; c.CodeVolume_of_Box2d_(ref v); } },\r\n            { typeof(Volume<Box2d>[]), (c,o) => { var v = (Volume<Box2d>[])o; c.CodeVolume_of_Box2d_Array(ref v); } },\r\n            { typeof(List<Volume<Box2d>>), (c,o) => { var v = (List<Volume<Box2d>>)o; c.CodeList_of_Volume_of_Box2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Box2d>), (c,o) => { var v = (Tensor<Box2d>)o; c.CodeTensor_of_Box2d_(ref v); } },\r\n            { typeof(Tensor<Box2d>[]), (c,o) => { var v = (Tensor<Box2d>[])o; c.CodeTensor_of_Box2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Box2d>>), (c,o) => { var v = (List<Tensor<Box2d>>)o; c.CodeList_of_Tensor_of_Box2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Box3i\r\n\r\n            { typeof(Box3i), (c,o) => { var v = (Box3i)o; c.CodeBox3i(ref v); } },\r\n            { typeof(Box3i[]), (c,o) => { var v = (Box3i[])o; c.CodeBox3iArray(ref v); } },\r\n            { typeof(List<Box3i>), (c,o) => { var v = (List<Box3i>)o; c.CodeList_of_Box3i_(ref v); } },\r\n\r\n            { typeof(Vector<Box3i>), (c,o) => { var v = (Vector<Box3i>)o; c.CodeVector_of_Box3i_(ref v); } },\r\n            { typeof(Vector<Box3i>[]), (c,o) => { var v = (Vector<Box3i>[])o; c.CodeVector_of_Box3i_Array(ref v); } },\r\n            { typeof(List<Vector<Box3i>>), (c,o) => { var v = (List<Vector<Box3i>>)o; c.CodeList_of_Vector_of_Box3i__(ref v); } },\r\n\r\n            { typeof(Matrix<Box3i>), (c,o) => { var v = (Matrix<Box3i>)o; c.CodeMatrix_of_Box3i_(ref v); } },\r\n            { typeof(Matrix<Box3i>[]), (c,o) => { var v = (Matrix<Box3i>[])o; c.CodeMatrix_of_Box3i_Array(ref v); } },\r\n            { typeof(List<Matrix<Box3i>>), (c,o) => { var v = (List<Matrix<Box3i>>)o; c.CodeList_of_Matrix_of_Box3i__(ref v); } },\r\n\r\n            { typeof(Volume<Box3i>), (c,o) => { var v = (Volume<Box3i>)o; c.CodeVolume_of_Box3i_(ref v); } },\r\n            { typeof(Volume<Box3i>[]), (c,o) => { var v = (Volume<Box3i>[])o; c.CodeVolume_of_Box3i_Array(ref v); } },\r\n            { typeof(List<Volume<Box3i>>), (c,o) => { var v = (List<Volume<Box3i>>)o; c.CodeList_of_Volume_of_Box3i__(ref v); } },\r\n\r\n            { typeof(Tensor<Box3i>), (c,o) => { var v = (Tensor<Box3i>)o; c.CodeTensor_of_Box3i_(ref v); } },\r\n            { typeof(Tensor<Box3i>[]), (c,o) => { var v = (Tensor<Box3i>[])o; c.CodeTensor_of_Box3i_Array(ref v); } },\r\n            { typeof(List<Tensor<Box3i>>), (c,o) => { var v = (List<Tensor<Box3i>>)o; c.CodeList_of_Tensor_of_Box3i__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Box3l\r\n\r\n            { typeof(Box3l), (c,o) => { var v = (Box3l)o; c.CodeBox3l(ref v); } },\r\n            { typeof(Box3l[]), (c,o) => { var v = (Box3l[])o; c.CodeBox3lArray(ref v); } },\r\n            { typeof(List<Box3l>), (c,o) => { var v = (List<Box3l>)o; c.CodeList_of_Box3l_(ref v); } },\r\n\r\n            { typeof(Vector<Box3l>), (c,o) => { var v = (Vector<Box3l>)o; c.CodeVector_of_Box3l_(ref v); } },\r\n            { typeof(Vector<Box3l>[]), (c,o) => { var v = (Vector<Box3l>[])o; c.CodeVector_of_Box3l_Array(ref v); } },\r\n            { typeof(List<Vector<Box3l>>), (c,o) => { var v = (List<Vector<Box3l>>)o; c.CodeList_of_Vector_of_Box3l__(ref v); } },\r\n\r\n            { typeof(Matrix<Box3l>), (c,o) => { var v = (Matrix<Box3l>)o; c.CodeMatrix_of_Box3l_(ref v); } },\r\n            { typeof(Matrix<Box3l>[]), (c,o) => { var v = (Matrix<Box3l>[])o; c.CodeMatrix_of_Box3l_Array(ref v); } },\r\n            { typeof(List<Matrix<Box3l>>), (c,o) => { var v = (List<Matrix<Box3l>>)o; c.CodeList_of_Matrix_of_Box3l__(ref v); } },\r\n\r\n            { typeof(Volume<Box3l>), (c,o) => { var v = (Volume<Box3l>)o; c.CodeVolume_of_Box3l_(ref v); } },\r\n            { typeof(Volume<Box3l>[]), (c,o) => { var v = (Volume<Box3l>[])o; c.CodeVolume_of_Box3l_Array(ref v); } },\r\n            { typeof(List<Volume<Box3l>>), (c,o) => { var v = (List<Volume<Box3l>>)o; c.CodeList_of_Volume_of_Box3l__(ref v); } },\r\n\r\n            { typeof(Tensor<Box3l>), (c,o) => { var v = (Tensor<Box3l>)o; c.CodeTensor_of_Box3l_(ref v); } },\r\n            { typeof(Tensor<Box3l>[]), (c,o) => { var v = (Tensor<Box3l>[])o; c.CodeTensor_of_Box3l_Array(ref v); } },\r\n            { typeof(List<Tensor<Box3l>>), (c,o) => { var v = (List<Tensor<Box3l>>)o; c.CodeList_of_Tensor_of_Box3l__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Box3f\r\n\r\n            { typeof(Box3f), (c,o) => { var v = (Box3f)o; c.CodeBox3f(ref v); } },\r\n            { typeof(Box3f[]), (c,o) => { var v = (Box3f[])o; c.CodeBox3fArray(ref v); } },\r\n            { typeof(List<Box3f>), (c,o) => { var v = (List<Box3f>)o; c.CodeList_of_Box3f_(ref v); } },\r\n\r\n            { typeof(Vector<Box3f>), (c,o) => { var v = (Vector<Box3f>)o; c.CodeVector_of_Box3f_(ref v); } },\r\n            { typeof(Vector<Box3f>[]), (c,o) => { var v = (Vector<Box3f>[])o; c.CodeVector_of_Box3f_Array(ref v); } },\r\n            { typeof(List<Vector<Box3f>>), (c,o) => { var v = (List<Vector<Box3f>>)o; c.CodeList_of_Vector_of_Box3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Box3f>), (c,o) => { var v = (Matrix<Box3f>)o; c.CodeMatrix_of_Box3f_(ref v); } },\r\n            { typeof(Matrix<Box3f>[]), (c,o) => { var v = (Matrix<Box3f>[])o; c.CodeMatrix_of_Box3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Box3f>>), (c,o) => { var v = (List<Matrix<Box3f>>)o; c.CodeList_of_Matrix_of_Box3f__(ref v); } },\r\n\r\n            { typeof(Volume<Box3f>), (c,o) => { var v = (Volume<Box3f>)o; c.CodeVolume_of_Box3f_(ref v); } },\r\n            { typeof(Volume<Box3f>[]), (c,o) => { var v = (Volume<Box3f>[])o; c.CodeVolume_of_Box3f_Array(ref v); } },\r\n            { typeof(List<Volume<Box3f>>), (c,o) => { var v = (List<Volume<Box3f>>)o; c.CodeList_of_Volume_of_Box3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Box3f>), (c,o) => { var v = (Tensor<Box3f>)o; c.CodeTensor_of_Box3f_(ref v); } },\r\n            { typeof(Tensor<Box3f>[]), (c,o) => { var v = (Tensor<Box3f>[])o; c.CodeTensor_of_Box3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Box3f>>), (c,o) => { var v = (List<Tensor<Box3f>>)o; c.CodeList_of_Tensor_of_Box3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Box3d\r\n\r\n            { typeof(Box3d), (c,o) => { var v = (Box3d)o; c.CodeBox3d(ref v); } },\r\n            { typeof(Box3d[]), (c,o) => { var v = (Box3d[])o; c.CodeBox3dArray(ref v); } },\r\n            { typeof(List<Box3d>), (c,o) => { var v = (List<Box3d>)o; c.CodeList_of_Box3d_(ref v); } },\r\n\r\n            { typeof(Vector<Box3d>), (c,o) => { var v = (Vector<Box3d>)o; c.CodeVector_of_Box3d_(ref v); } },\r\n            { typeof(Vector<Box3d>[]), (c,o) => { var v = (Vector<Box3d>[])o; c.CodeVector_of_Box3d_Array(ref v); } },\r\n            { typeof(List<Vector<Box3d>>), (c,o) => { var v = (List<Vector<Box3d>>)o; c.CodeList_of_Vector_of_Box3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Box3d>), (c,o) => { var v = (Matrix<Box3d>)o; c.CodeMatrix_of_Box3d_(ref v); } },\r\n            { typeof(Matrix<Box3d>[]), (c,o) => { var v = (Matrix<Box3d>[])o; c.CodeMatrix_of_Box3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Box3d>>), (c,o) => { var v = (List<Matrix<Box3d>>)o; c.CodeList_of_Matrix_of_Box3d__(ref v); } },\r\n\r\n            { typeof(Volume<Box3d>), (c,o) => { var v = (Volume<Box3d>)o; c.CodeVolume_of_Box3d_(ref v); } },\r\n            { typeof(Volume<Box3d>[]), (c,o) => { var v = (Volume<Box3d>[])o; c.CodeVolume_of_Box3d_Array(ref v); } },\r\n            { typeof(List<Volume<Box3d>>), (c,o) => { var v = (List<Volume<Box3d>>)o; c.CodeList_of_Volume_of_Box3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Box3d>), (c,o) => { var v = (Tensor<Box3d>)o; c.CodeTensor_of_Box3d_(ref v); } },\r\n            { typeof(Tensor<Box3d>[]), (c,o) => { var v = (Tensor<Box3d>[])o; c.CodeTensor_of_Box3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Box3d>>), (c,o) => { var v = (List<Tensor<Box3d>>)o; c.CodeList_of_Tensor_of_Box3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Euclidean3f\r\n\r\n            { typeof(Euclidean3f), (c,o) => { var v = (Euclidean3f)o; c.CodeEuclidean3f(ref v); } },\r\n            { typeof(Euclidean3f[]), (c,o) => { var v = (Euclidean3f[])o; c.CodeEuclidean3fArray(ref v); } },\r\n            { typeof(List<Euclidean3f>), (c,o) => { var v = (List<Euclidean3f>)o; c.CodeList_of_Euclidean3f_(ref v); } },\r\n\r\n            { typeof(Vector<Euclidean3f>), (c,o) => { var v = (Vector<Euclidean3f>)o; c.CodeVector_of_Euclidean3f_(ref v); } },\r\n            { typeof(Vector<Euclidean3f>[]), (c,o) => { var v = (Vector<Euclidean3f>[])o; c.CodeVector_of_Euclidean3f_Array(ref v); } },\r\n            { typeof(List<Vector<Euclidean3f>>), (c,o) => { var v = (List<Vector<Euclidean3f>>)o; c.CodeList_of_Vector_of_Euclidean3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Euclidean3f>), (c,o) => { var v = (Matrix<Euclidean3f>)o; c.CodeMatrix_of_Euclidean3f_(ref v); } },\r\n            { typeof(Matrix<Euclidean3f>[]), (c,o) => { var v = (Matrix<Euclidean3f>[])o; c.CodeMatrix_of_Euclidean3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Euclidean3f>>), (c,o) => { var v = (List<Matrix<Euclidean3f>>)o; c.CodeList_of_Matrix_of_Euclidean3f__(ref v); } },\r\n\r\n            { typeof(Volume<Euclidean3f>), (c,o) => { var v = (Volume<Euclidean3f>)o; c.CodeVolume_of_Euclidean3f_(ref v); } },\r\n            { typeof(Volume<Euclidean3f>[]), (c,o) => { var v = (Volume<Euclidean3f>[])o; c.CodeVolume_of_Euclidean3f_Array(ref v); } },\r\n            { typeof(List<Volume<Euclidean3f>>), (c,o) => { var v = (List<Volume<Euclidean3f>>)o; c.CodeList_of_Volume_of_Euclidean3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Euclidean3f>), (c,o) => { var v = (Tensor<Euclidean3f>)o; c.CodeTensor_of_Euclidean3f_(ref v); } },\r\n            { typeof(Tensor<Euclidean3f>[]), (c,o) => { var v = (Tensor<Euclidean3f>[])o; c.CodeTensor_of_Euclidean3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Euclidean3f>>), (c,o) => { var v = (List<Tensor<Euclidean3f>>)o; c.CodeList_of_Tensor_of_Euclidean3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Euclidean3d\r\n\r\n            { typeof(Euclidean3d), (c,o) => { var v = (Euclidean3d)o; c.CodeEuclidean3d(ref v); } },\r\n            { typeof(Euclidean3d[]), (c,o) => { var v = (Euclidean3d[])o; c.CodeEuclidean3dArray(ref v); } },\r\n            { typeof(List<Euclidean3d>), (c,o) => { var v = (List<Euclidean3d>)o; c.CodeList_of_Euclidean3d_(ref v); } },\r\n\r\n            { typeof(Vector<Euclidean3d>), (c,o) => { var v = (Vector<Euclidean3d>)o; c.CodeVector_of_Euclidean3d_(ref v); } },\r\n            { typeof(Vector<Euclidean3d>[]), (c,o) => { var v = (Vector<Euclidean3d>[])o; c.CodeVector_of_Euclidean3d_Array(ref v); } },\r\n            { typeof(List<Vector<Euclidean3d>>), (c,o) => { var v = (List<Vector<Euclidean3d>>)o; c.CodeList_of_Vector_of_Euclidean3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Euclidean3d>), (c,o) => { var v = (Matrix<Euclidean3d>)o; c.CodeMatrix_of_Euclidean3d_(ref v); } },\r\n            { typeof(Matrix<Euclidean3d>[]), (c,o) => { var v = (Matrix<Euclidean3d>[])o; c.CodeMatrix_of_Euclidean3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Euclidean3d>>), (c,o) => { var v = (List<Matrix<Euclidean3d>>)o; c.CodeList_of_Matrix_of_Euclidean3d__(ref v); } },\r\n\r\n            { typeof(Volume<Euclidean3d>), (c,o) => { var v = (Volume<Euclidean3d>)o; c.CodeVolume_of_Euclidean3d_(ref v); } },\r\n            { typeof(Volume<Euclidean3d>[]), (c,o) => { var v = (Volume<Euclidean3d>[])o; c.CodeVolume_of_Euclidean3d_Array(ref v); } },\r\n            { typeof(List<Volume<Euclidean3d>>), (c,o) => { var v = (List<Volume<Euclidean3d>>)o; c.CodeList_of_Volume_of_Euclidean3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Euclidean3d>), (c,o) => { var v = (Tensor<Euclidean3d>)o; c.CodeTensor_of_Euclidean3d_(ref v); } },\r\n            { typeof(Tensor<Euclidean3d>[]), (c,o) => { var v = (Tensor<Euclidean3d>[])o; c.CodeTensor_of_Euclidean3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Euclidean3d>>), (c,o) => { var v = (List<Tensor<Euclidean3d>>)o; c.CodeList_of_Tensor_of_Euclidean3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Rot2f\r\n\r\n            { typeof(Rot2f), (c,o) => { var v = (Rot2f)o; c.CodeRot2f(ref v); } },\r\n            { typeof(Rot2f[]), (c,o) => { var v = (Rot2f[])o; c.CodeRot2fArray(ref v); } },\r\n            { typeof(List<Rot2f>), (c,o) => { var v = (List<Rot2f>)o; c.CodeList_of_Rot2f_(ref v); } },\r\n\r\n            { typeof(Vector<Rot2f>), (c,o) => { var v = (Vector<Rot2f>)o; c.CodeVector_of_Rot2f_(ref v); } },\r\n            { typeof(Vector<Rot2f>[]), (c,o) => { var v = (Vector<Rot2f>[])o; c.CodeVector_of_Rot2f_Array(ref v); } },\r\n            { typeof(List<Vector<Rot2f>>), (c,o) => { var v = (List<Vector<Rot2f>>)o; c.CodeList_of_Vector_of_Rot2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Rot2f>), (c,o) => { var v = (Matrix<Rot2f>)o; c.CodeMatrix_of_Rot2f_(ref v); } },\r\n            { typeof(Matrix<Rot2f>[]), (c,o) => { var v = (Matrix<Rot2f>[])o; c.CodeMatrix_of_Rot2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Rot2f>>), (c,o) => { var v = (List<Matrix<Rot2f>>)o; c.CodeList_of_Matrix_of_Rot2f__(ref v); } },\r\n\r\n            { typeof(Volume<Rot2f>), (c,o) => { var v = (Volume<Rot2f>)o; c.CodeVolume_of_Rot2f_(ref v); } },\r\n            { typeof(Volume<Rot2f>[]), (c,o) => { var v = (Volume<Rot2f>[])o; c.CodeVolume_of_Rot2f_Array(ref v); } },\r\n            { typeof(List<Volume<Rot2f>>), (c,o) => { var v = (List<Volume<Rot2f>>)o; c.CodeList_of_Volume_of_Rot2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Rot2f>), (c,o) => { var v = (Tensor<Rot2f>)o; c.CodeTensor_of_Rot2f_(ref v); } },\r\n            { typeof(Tensor<Rot2f>[]), (c,o) => { var v = (Tensor<Rot2f>[])o; c.CodeTensor_of_Rot2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Rot2f>>), (c,o) => { var v = (List<Tensor<Rot2f>>)o; c.CodeList_of_Tensor_of_Rot2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Rot2d\r\n\r\n            { typeof(Rot2d), (c,o) => { var v = (Rot2d)o; c.CodeRot2d(ref v); } },\r\n            { typeof(Rot2d[]), (c,o) => { var v = (Rot2d[])o; c.CodeRot2dArray(ref v); } },\r\n            { typeof(List<Rot2d>), (c,o) => { var v = (List<Rot2d>)o; c.CodeList_of_Rot2d_(ref v); } },\r\n\r\n            { typeof(Vector<Rot2d>), (c,o) => { var v = (Vector<Rot2d>)o; c.CodeVector_of_Rot2d_(ref v); } },\r\n            { typeof(Vector<Rot2d>[]), (c,o) => { var v = (Vector<Rot2d>[])o; c.CodeVector_of_Rot2d_Array(ref v); } },\r\n            { typeof(List<Vector<Rot2d>>), (c,o) => { var v = (List<Vector<Rot2d>>)o; c.CodeList_of_Vector_of_Rot2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Rot2d>), (c,o) => { var v = (Matrix<Rot2d>)o; c.CodeMatrix_of_Rot2d_(ref v); } },\r\n            { typeof(Matrix<Rot2d>[]), (c,o) => { var v = (Matrix<Rot2d>[])o; c.CodeMatrix_of_Rot2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Rot2d>>), (c,o) => { var v = (List<Matrix<Rot2d>>)o; c.CodeList_of_Matrix_of_Rot2d__(ref v); } },\r\n\r\n            { typeof(Volume<Rot2d>), (c,o) => { var v = (Volume<Rot2d>)o; c.CodeVolume_of_Rot2d_(ref v); } },\r\n            { typeof(Volume<Rot2d>[]), (c,o) => { var v = (Volume<Rot2d>[])o; c.CodeVolume_of_Rot2d_Array(ref v); } },\r\n            { typeof(List<Volume<Rot2d>>), (c,o) => { var v = (List<Volume<Rot2d>>)o; c.CodeList_of_Volume_of_Rot2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Rot2d>), (c,o) => { var v = (Tensor<Rot2d>)o; c.CodeTensor_of_Rot2d_(ref v); } },\r\n            { typeof(Tensor<Rot2d>[]), (c,o) => { var v = (Tensor<Rot2d>[])o; c.CodeTensor_of_Rot2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Rot2d>>), (c,o) => { var v = (List<Tensor<Rot2d>>)o; c.CodeList_of_Tensor_of_Rot2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Rot3f\r\n\r\n            { typeof(Rot3f), (c,o) => { var v = (Rot3f)o; c.CodeRot3f(ref v); } },\r\n            { typeof(Rot3f[]), (c,o) => { var v = (Rot3f[])o; c.CodeRot3fArray(ref v); } },\r\n            { typeof(List<Rot3f>), (c,o) => { var v = (List<Rot3f>)o; c.CodeList_of_Rot3f_(ref v); } },\r\n\r\n            { typeof(Vector<Rot3f>), (c,o) => { var v = (Vector<Rot3f>)o; c.CodeVector_of_Rot3f_(ref v); } },\r\n            { typeof(Vector<Rot3f>[]), (c,o) => { var v = (Vector<Rot3f>[])o; c.CodeVector_of_Rot3f_Array(ref v); } },\r\n            { typeof(List<Vector<Rot3f>>), (c,o) => { var v = (List<Vector<Rot3f>>)o; c.CodeList_of_Vector_of_Rot3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Rot3f>), (c,o) => { var v = (Matrix<Rot3f>)o; c.CodeMatrix_of_Rot3f_(ref v); } },\r\n            { typeof(Matrix<Rot3f>[]), (c,o) => { var v = (Matrix<Rot3f>[])o; c.CodeMatrix_of_Rot3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Rot3f>>), (c,o) => { var v = (List<Matrix<Rot3f>>)o; c.CodeList_of_Matrix_of_Rot3f__(ref v); } },\r\n\r\n            { typeof(Volume<Rot3f>), (c,o) => { var v = (Volume<Rot3f>)o; c.CodeVolume_of_Rot3f_(ref v); } },\r\n            { typeof(Volume<Rot3f>[]), (c,o) => { var v = (Volume<Rot3f>[])o; c.CodeVolume_of_Rot3f_Array(ref v); } },\r\n            { typeof(List<Volume<Rot3f>>), (c,o) => { var v = (List<Volume<Rot3f>>)o; c.CodeList_of_Volume_of_Rot3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Rot3f>), (c,o) => { var v = (Tensor<Rot3f>)o; c.CodeTensor_of_Rot3f_(ref v); } },\r\n            { typeof(Tensor<Rot3f>[]), (c,o) => { var v = (Tensor<Rot3f>[])o; c.CodeTensor_of_Rot3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Rot3f>>), (c,o) => { var v = (List<Tensor<Rot3f>>)o; c.CodeList_of_Tensor_of_Rot3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Rot3d\r\n\r\n            { typeof(Rot3d), (c,o) => { var v = (Rot3d)o; c.CodeRot3d(ref v); } },\r\n            { typeof(Rot3d[]), (c,o) => { var v = (Rot3d[])o; c.CodeRot3dArray(ref v); } },\r\n            { typeof(List<Rot3d>), (c,o) => { var v = (List<Rot3d>)o; c.CodeList_of_Rot3d_(ref v); } },\r\n\r\n            { typeof(Vector<Rot3d>), (c,o) => { var v = (Vector<Rot3d>)o; c.CodeVector_of_Rot3d_(ref v); } },\r\n            { typeof(Vector<Rot3d>[]), (c,o) => { var v = (Vector<Rot3d>[])o; c.CodeVector_of_Rot3d_Array(ref v); } },\r\n            { typeof(List<Vector<Rot3d>>), (c,o) => { var v = (List<Vector<Rot3d>>)o; c.CodeList_of_Vector_of_Rot3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Rot3d>), (c,o) => { var v = (Matrix<Rot3d>)o; c.CodeMatrix_of_Rot3d_(ref v); } },\r\n            { typeof(Matrix<Rot3d>[]), (c,o) => { var v = (Matrix<Rot3d>[])o; c.CodeMatrix_of_Rot3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Rot3d>>), (c,o) => { var v = (List<Matrix<Rot3d>>)o; c.CodeList_of_Matrix_of_Rot3d__(ref v); } },\r\n\r\n            { typeof(Volume<Rot3d>), (c,o) => { var v = (Volume<Rot3d>)o; c.CodeVolume_of_Rot3d_(ref v); } },\r\n            { typeof(Volume<Rot3d>[]), (c,o) => { var v = (Volume<Rot3d>[])o; c.CodeVolume_of_Rot3d_Array(ref v); } },\r\n            { typeof(List<Volume<Rot3d>>), (c,o) => { var v = (List<Volume<Rot3d>>)o; c.CodeList_of_Volume_of_Rot3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Rot3d>), (c,o) => { var v = (Tensor<Rot3d>)o; c.CodeTensor_of_Rot3d_(ref v); } },\r\n            { typeof(Tensor<Rot3d>[]), (c,o) => { var v = (Tensor<Rot3d>[])o; c.CodeTensor_of_Rot3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Rot3d>>), (c,o) => { var v = (List<Tensor<Rot3d>>)o; c.CodeList_of_Tensor_of_Rot3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Scale3f\r\n\r\n            { typeof(Scale3f), (c,o) => { var v = (Scale3f)o; c.CodeScale3f(ref v); } },\r\n            { typeof(Scale3f[]), (c,o) => { var v = (Scale3f[])o; c.CodeScale3fArray(ref v); } },\r\n            { typeof(List<Scale3f>), (c,o) => { var v = (List<Scale3f>)o; c.CodeList_of_Scale3f_(ref v); } },\r\n\r\n            { typeof(Vector<Scale3f>), (c,o) => { var v = (Vector<Scale3f>)o; c.CodeVector_of_Scale3f_(ref v); } },\r\n            { typeof(Vector<Scale3f>[]), (c,o) => { var v = (Vector<Scale3f>[])o; c.CodeVector_of_Scale3f_Array(ref v); } },\r\n            { typeof(List<Vector<Scale3f>>), (c,o) => { var v = (List<Vector<Scale3f>>)o; c.CodeList_of_Vector_of_Scale3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Scale3f>), (c,o) => { var v = (Matrix<Scale3f>)o; c.CodeMatrix_of_Scale3f_(ref v); } },\r\n            { typeof(Matrix<Scale3f>[]), (c,o) => { var v = (Matrix<Scale3f>[])o; c.CodeMatrix_of_Scale3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Scale3f>>), (c,o) => { var v = (List<Matrix<Scale3f>>)o; c.CodeList_of_Matrix_of_Scale3f__(ref v); } },\r\n\r\n            { typeof(Volume<Scale3f>), (c,o) => { var v = (Volume<Scale3f>)o; c.CodeVolume_of_Scale3f_(ref v); } },\r\n            { typeof(Volume<Scale3f>[]), (c,o) => { var v = (Volume<Scale3f>[])o; c.CodeVolume_of_Scale3f_Array(ref v); } },\r\n            { typeof(List<Volume<Scale3f>>), (c,o) => { var v = (List<Volume<Scale3f>>)o; c.CodeList_of_Volume_of_Scale3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Scale3f>), (c,o) => { var v = (Tensor<Scale3f>)o; c.CodeTensor_of_Scale3f_(ref v); } },\r\n            { typeof(Tensor<Scale3f>[]), (c,o) => { var v = (Tensor<Scale3f>[])o; c.CodeTensor_of_Scale3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Scale3f>>), (c,o) => { var v = (List<Tensor<Scale3f>>)o; c.CodeList_of_Tensor_of_Scale3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Scale3d\r\n\r\n            { typeof(Scale3d), (c,o) => { var v = (Scale3d)o; c.CodeScale3d(ref v); } },\r\n            { typeof(Scale3d[]), (c,o) => { var v = (Scale3d[])o; c.CodeScale3dArray(ref v); } },\r\n            { typeof(List<Scale3d>), (c,o) => { var v = (List<Scale3d>)o; c.CodeList_of_Scale3d_(ref v); } },\r\n\r\n            { typeof(Vector<Scale3d>), (c,o) => { var v = (Vector<Scale3d>)o; c.CodeVector_of_Scale3d_(ref v); } },\r\n            { typeof(Vector<Scale3d>[]), (c,o) => { var v = (Vector<Scale3d>[])o; c.CodeVector_of_Scale3d_Array(ref v); } },\r\n            { typeof(List<Vector<Scale3d>>), (c,o) => { var v = (List<Vector<Scale3d>>)o; c.CodeList_of_Vector_of_Scale3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Scale3d>), (c,o) => { var v = (Matrix<Scale3d>)o; c.CodeMatrix_of_Scale3d_(ref v); } },\r\n            { typeof(Matrix<Scale3d>[]), (c,o) => { var v = (Matrix<Scale3d>[])o; c.CodeMatrix_of_Scale3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Scale3d>>), (c,o) => { var v = (List<Matrix<Scale3d>>)o; c.CodeList_of_Matrix_of_Scale3d__(ref v); } },\r\n\r\n            { typeof(Volume<Scale3d>), (c,o) => { var v = (Volume<Scale3d>)o; c.CodeVolume_of_Scale3d_(ref v); } },\r\n            { typeof(Volume<Scale3d>[]), (c,o) => { var v = (Volume<Scale3d>[])o; c.CodeVolume_of_Scale3d_Array(ref v); } },\r\n            { typeof(List<Volume<Scale3d>>), (c,o) => { var v = (List<Volume<Scale3d>>)o; c.CodeList_of_Volume_of_Scale3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Scale3d>), (c,o) => { var v = (Tensor<Scale3d>)o; c.CodeTensor_of_Scale3d_(ref v); } },\r\n            { typeof(Tensor<Scale3d>[]), (c,o) => { var v = (Tensor<Scale3d>[])o; c.CodeTensor_of_Scale3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Scale3d>>), (c,o) => { var v = (List<Tensor<Scale3d>>)o; c.CodeList_of_Tensor_of_Scale3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Shift3f\r\n\r\n            { typeof(Shift3f), (c,o) => { var v = (Shift3f)o; c.CodeShift3f(ref v); } },\r\n            { typeof(Shift3f[]), (c,o) => { var v = (Shift3f[])o; c.CodeShift3fArray(ref v); } },\r\n            { typeof(List<Shift3f>), (c,o) => { var v = (List<Shift3f>)o; c.CodeList_of_Shift3f_(ref v); } },\r\n\r\n            { typeof(Vector<Shift3f>), (c,o) => { var v = (Vector<Shift3f>)o; c.CodeVector_of_Shift3f_(ref v); } },\r\n            { typeof(Vector<Shift3f>[]), (c,o) => { var v = (Vector<Shift3f>[])o; c.CodeVector_of_Shift3f_Array(ref v); } },\r\n            { typeof(List<Vector<Shift3f>>), (c,o) => { var v = (List<Vector<Shift3f>>)o; c.CodeList_of_Vector_of_Shift3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Shift3f>), (c,o) => { var v = (Matrix<Shift3f>)o; c.CodeMatrix_of_Shift3f_(ref v); } },\r\n            { typeof(Matrix<Shift3f>[]), (c,o) => { var v = (Matrix<Shift3f>[])o; c.CodeMatrix_of_Shift3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Shift3f>>), (c,o) => { var v = (List<Matrix<Shift3f>>)o; c.CodeList_of_Matrix_of_Shift3f__(ref v); } },\r\n\r\n            { typeof(Volume<Shift3f>), (c,o) => { var v = (Volume<Shift3f>)o; c.CodeVolume_of_Shift3f_(ref v); } },\r\n            { typeof(Volume<Shift3f>[]), (c,o) => { var v = (Volume<Shift3f>[])o; c.CodeVolume_of_Shift3f_Array(ref v); } },\r\n            { typeof(List<Volume<Shift3f>>), (c,o) => { var v = (List<Volume<Shift3f>>)o; c.CodeList_of_Volume_of_Shift3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Shift3f>), (c,o) => { var v = (Tensor<Shift3f>)o; c.CodeTensor_of_Shift3f_(ref v); } },\r\n            { typeof(Tensor<Shift3f>[]), (c,o) => { var v = (Tensor<Shift3f>[])o; c.CodeTensor_of_Shift3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Shift3f>>), (c,o) => { var v = (List<Tensor<Shift3f>>)o; c.CodeList_of_Tensor_of_Shift3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Shift3d\r\n\r\n            { typeof(Shift3d), (c,o) => { var v = (Shift3d)o; c.CodeShift3d(ref v); } },\r\n            { typeof(Shift3d[]), (c,o) => { var v = (Shift3d[])o; c.CodeShift3dArray(ref v); } },\r\n            { typeof(List<Shift3d>), (c,o) => { var v = (List<Shift3d>)o; c.CodeList_of_Shift3d_(ref v); } },\r\n\r\n            { typeof(Vector<Shift3d>), (c,o) => { var v = (Vector<Shift3d>)o; c.CodeVector_of_Shift3d_(ref v); } },\r\n            { typeof(Vector<Shift3d>[]), (c,o) => { var v = (Vector<Shift3d>[])o; c.CodeVector_of_Shift3d_Array(ref v); } },\r\n            { typeof(List<Vector<Shift3d>>), (c,o) => { var v = (List<Vector<Shift3d>>)o; c.CodeList_of_Vector_of_Shift3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Shift3d>), (c,o) => { var v = (Matrix<Shift3d>)o; c.CodeMatrix_of_Shift3d_(ref v); } },\r\n            { typeof(Matrix<Shift3d>[]), (c,o) => { var v = (Matrix<Shift3d>[])o; c.CodeMatrix_of_Shift3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Shift3d>>), (c,o) => { var v = (List<Matrix<Shift3d>>)o; c.CodeList_of_Matrix_of_Shift3d__(ref v); } },\r\n\r\n            { typeof(Volume<Shift3d>), (c,o) => { var v = (Volume<Shift3d>)o; c.CodeVolume_of_Shift3d_(ref v); } },\r\n            { typeof(Volume<Shift3d>[]), (c,o) => { var v = (Volume<Shift3d>[])o; c.CodeVolume_of_Shift3d_Array(ref v); } },\r\n            { typeof(List<Volume<Shift3d>>), (c,o) => { var v = (List<Volume<Shift3d>>)o; c.CodeList_of_Volume_of_Shift3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Shift3d>), (c,o) => { var v = (Tensor<Shift3d>)o; c.CodeTensor_of_Shift3d_(ref v); } },\r\n            { typeof(Tensor<Shift3d>[]), (c,o) => { var v = (Tensor<Shift3d>[])o; c.CodeTensor_of_Shift3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Shift3d>>), (c,o) => { var v = (List<Tensor<Shift3d>>)o; c.CodeList_of_Tensor_of_Shift3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Trafo2f\r\n\r\n            { typeof(Trafo2f), (c,o) => { var v = (Trafo2f)o; c.CodeTrafo2f(ref v); } },\r\n            { typeof(Trafo2f[]), (c,o) => { var v = (Trafo2f[])o; c.CodeTrafo2fArray(ref v); } },\r\n            { typeof(List<Trafo2f>), (c,o) => { var v = (List<Trafo2f>)o; c.CodeList_of_Trafo2f_(ref v); } },\r\n\r\n            { typeof(Vector<Trafo2f>), (c,o) => { var v = (Vector<Trafo2f>)o; c.CodeVector_of_Trafo2f_(ref v); } },\r\n            { typeof(Vector<Trafo2f>[]), (c,o) => { var v = (Vector<Trafo2f>[])o; c.CodeVector_of_Trafo2f_Array(ref v); } },\r\n            { typeof(List<Vector<Trafo2f>>), (c,o) => { var v = (List<Vector<Trafo2f>>)o; c.CodeList_of_Vector_of_Trafo2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Trafo2f>), (c,o) => { var v = (Matrix<Trafo2f>)o; c.CodeMatrix_of_Trafo2f_(ref v); } },\r\n            { typeof(Matrix<Trafo2f>[]), (c,o) => { var v = (Matrix<Trafo2f>[])o; c.CodeMatrix_of_Trafo2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Trafo2f>>), (c,o) => { var v = (List<Matrix<Trafo2f>>)o; c.CodeList_of_Matrix_of_Trafo2f__(ref v); } },\r\n\r\n            { typeof(Volume<Trafo2f>), (c,o) => { var v = (Volume<Trafo2f>)o; c.CodeVolume_of_Trafo2f_(ref v); } },\r\n            { typeof(Volume<Trafo2f>[]), (c,o) => { var v = (Volume<Trafo2f>[])o; c.CodeVolume_of_Trafo2f_Array(ref v); } },\r\n            { typeof(List<Volume<Trafo2f>>), (c,o) => { var v = (List<Volume<Trafo2f>>)o; c.CodeList_of_Volume_of_Trafo2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Trafo2f>), (c,o) => { var v = (Tensor<Trafo2f>)o; c.CodeTensor_of_Trafo2f_(ref v); } },\r\n            { typeof(Tensor<Trafo2f>[]), (c,o) => { var v = (Tensor<Trafo2f>[])o; c.CodeTensor_of_Trafo2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Trafo2f>>), (c,o) => { var v = (List<Tensor<Trafo2f>>)o; c.CodeList_of_Tensor_of_Trafo2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Trafo2d\r\n\r\n            { typeof(Trafo2d), (c,o) => { var v = (Trafo2d)o; c.CodeTrafo2d(ref v); } },\r\n            { typeof(Trafo2d[]), (c,o) => { var v = (Trafo2d[])o; c.CodeTrafo2dArray(ref v); } },\r\n            { typeof(List<Trafo2d>), (c,o) => { var v = (List<Trafo2d>)o; c.CodeList_of_Trafo2d_(ref v); } },\r\n\r\n            { typeof(Vector<Trafo2d>), (c,o) => { var v = (Vector<Trafo2d>)o; c.CodeVector_of_Trafo2d_(ref v); } },\r\n            { typeof(Vector<Trafo2d>[]), (c,o) => { var v = (Vector<Trafo2d>[])o; c.CodeVector_of_Trafo2d_Array(ref v); } },\r\n            { typeof(List<Vector<Trafo2d>>), (c,o) => { var v = (List<Vector<Trafo2d>>)o; c.CodeList_of_Vector_of_Trafo2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Trafo2d>), (c,o) => { var v = (Matrix<Trafo2d>)o; c.CodeMatrix_of_Trafo2d_(ref v); } },\r\n            { typeof(Matrix<Trafo2d>[]), (c,o) => { var v = (Matrix<Trafo2d>[])o; c.CodeMatrix_of_Trafo2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Trafo2d>>), (c,o) => { var v = (List<Matrix<Trafo2d>>)o; c.CodeList_of_Matrix_of_Trafo2d__(ref v); } },\r\n\r\n            { typeof(Volume<Trafo2d>), (c,o) => { var v = (Volume<Trafo2d>)o; c.CodeVolume_of_Trafo2d_(ref v); } },\r\n            { typeof(Volume<Trafo2d>[]), (c,o) => { var v = (Volume<Trafo2d>[])o; c.CodeVolume_of_Trafo2d_Array(ref v); } },\r\n            { typeof(List<Volume<Trafo2d>>), (c,o) => { var v = (List<Volume<Trafo2d>>)o; c.CodeList_of_Volume_of_Trafo2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Trafo2d>), (c,o) => { var v = (Tensor<Trafo2d>)o; c.CodeTensor_of_Trafo2d_(ref v); } },\r\n            { typeof(Tensor<Trafo2d>[]), (c,o) => { var v = (Tensor<Trafo2d>[])o; c.CodeTensor_of_Trafo2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Trafo2d>>), (c,o) => { var v = (List<Tensor<Trafo2d>>)o; c.CodeList_of_Tensor_of_Trafo2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Trafo3f\r\n\r\n            { typeof(Trafo3f), (c,o) => { var v = (Trafo3f)o; c.CodeTrafo3f(ref v); } },\r\n            { typeof(Trafo3f[]), (c,o) => { var v = (Trafo3f[])o; c.CodeTrafo3fArray(ref v); } },\r\n            { typeof(List<Trafo3f>), (c,o) => { var v = (List<Trafo3f>)o; c.CodeList_of_Trafo3f_(ref v); } },\r\n\r\n            { typeof(Vector<Trafo3f>), (c,o) => { var v = (Vector<Trafo3f>)o; c.CodeVector_of_Trafo3f_(ref v); } },\r\n            { typeof(Vector<Trafo3f>[]), (c,o) => { var v = (Vector<Trafo3f>[])o; c.CodeVector_of_Trafo3f_Array(ref v); } },\r\n            { typeof(List<Vector<Trafo3f>>), (c,o) => { var v = (List<Vector<Trafo3f>>)o; c.CodeList_of_Vector_of_Trafo3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Trafo3f>), (c,o) => { var v = (Matrix<Trafo3f>)o; c.CodeMatrix_of_Trafo3f_(ref v); } },\r\n            { typeof(Matrix<Trafo3f>[]), (c,o) => { var v = (Matrix<Trafo3f>[])o; c.CodeMatrix_of_Trafo3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Trafo3f>>), (c,o) => { var v = (List<Matrix<Trafo3f>>)o; c.CodeList_of_Matrix_of_Trafo3f__(ref v); } },\r\n\r\n            { typeof(Volume<Trafo3f>), (c,o) => { var v = (Volume<Trafo3f>)o; c.CodeVolume_of_Trafo3f_(ref v); } },\r\n            { typeof(Volume<Trafo3f>[]), (c,o) => { var v = (Volume<Trafo3f>[])o; c.CodeVolume_of_Trafo3f_Array(ref v); } },\r\n            { typeof(List<Volume<Trafo3f>>), (c,o) => { var v = (List<Volume<Trafo3f>>)o; c.CodeList_of_Volume_of_Trafo3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Trafo3f>), (c,o) => { var v = (Tensor<Trafo3f>)o; c.CodeTensor_of_Trafo3f_(ref v); } },\r\n            { typeof(Tensor<Trafo3f>[]), (c,o) => { var v = (Tensor<Trafo3f>[])o; c.CodeTensor_of_Trafo3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Trafo3f>>), (c,o) => { var v = (List<Tensor<Trafo3f>>)o; c.CodeList_of_Tensor_of_Trafo3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Trafo3d\r\n\r\n            { typeof(Trafo3d), (c,o) => { var v = (Trafo3d)o; c.CodeTrafo3d(ref v); } },\r\n            { typeof(Trafo3d[]), (c,o) => { var v = (Trafo3d[])o; c.CodeTrafo3dArray(ref v); } },\r\n            { typeof(List<Trafo3d>), (c,o) => { var v = (List<Trafo3d>)o; c.CodeList_of_Trafo3d_(ref v); } },\r\n\r\n            { typeof(Vector<Trafo3d>), (c,o) => { var v = (Vector<Trafo3d>)o; c.CodeVector_of_Trafo3d_(ref v); } },\r\n            { typeof(Vector<Trafo3d>[]), (c,o) => { var v = (Vector<Trafo3d>[])o; c.CodeVector_of_Trafo3d_Array(ref v); } },\r\n            { typeof(List<Vector<Trafo3d>>), (c,o) => { var v = (List<Vector<Trafo3d>>)o; c.CodeList_of_Vector_of_Trafo3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Trafo3d>), (c,o) => { var v = (Matrix<Trafo3d>)o; c.CodeMatrix_of_Trafo3d_(ref v); } },\r\n            { typeof(Matrix<Trafo3d>[]), (c,o) => { var v = (Matrix<Trafo3d>[])o; c.CodeMatrix_of_Trafo3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Trafo3d>>), (c,o) => { var v = (List<Matrix<Trafo3d>>)o; c.CodeList_of_Matrix_of_Trafo3d__(ref v); } },\r\n\r\n            { typeof(Volume<Trafo3d>), (c,o) => { var v = (Volume<Trafo3d>)o; c.CodeVolume_of_Trafo3d_(ref v); } },\r\n            { typeof(Volume<Trafo3d>[]), (c,o) => { var v = (Volume<Trafo3d>[])o; c.CodeVolume_of_Trafo3d_Array(ref v); } },\r\n            { typeof(List<Volume<Trafo3d>>), (c,o) => { var v = (List<Volume<Trafo3d>>)o; c.CodeList_of_Volume_of_Trafo3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Trafo3d>), (c,o) => { var v = (Tensor<Trafo3d>)o; c.CodeTensor_of_Trafo3d_(ref v); } },\r\n            { typeof(Tensor<Trafo3d>[]), (c,o) => { var v = (Tensor<Trafo3d>[])o; c.CodeTensor_of_Trafo3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Trafo3d>>), (c,o) => { var v = (List<Tensor<Trafo3d>>)o; c.CodeList_of_Tensor_of_Trafo3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region bool\r\n\r\n            { typeof(bool), (c,o) => { var v = (bool)o; c.CodeBool(ref v); } },\r\n            { typeof(bool[]), (c,o) => { var v = (bool[])o; c.CodeBoolArray(ref v); } },\r\n            { typeof(List<bool>), (c,o) => { var v = (List<bool>)o; c.CodeList_of_Bool_(ref v); } },\r\n\r\n            { typeof(Vector<bool>), (c,o) => { var v = (Vector<bool>)o; c.CodeVector_of_Bool_(ref v); } },\r\n            { typeof(Vector<bool>[]), (c,o) => { var v = (Vector<bool>[])o; c.CodeVector_of_Bool_Array(ref v); } },\r\n            { typeof(List<Vector<bool>>), (c,o) => { var v = (List<Vector<bool>>)o; c.CodeList_of_Vector_of_Bool__(ref v); } },\r\n\r\n            { typeof(Matrix<bool>), (c,o) => { var v = (Matrix<bool>)o; c.CodeMatrix_of_Bool_(ref v); } },\r\n            { typeof(Matrix<bool>[]), (c,o) => { var v = (Matrix<bool>[])o; c.CodeMatrix_of_Bool_Array(ref v); } },\r\n            { typeof(List<Matrix<bool>>), (c,o) => { var v = (List<Matrix<bool>>)o; c.CodeList_of_Matrix_of_Bool__(ref v); } },\r\n\r\n            { typeof(Volume<bool>), (c,o) => { var v = (Volume<bool>)o; c.CodeVolume_of_Bool_(ref v); } },\r\n            { typeof(Volume<bool>[]), (c,o) => { var v = (Volume<bool>[])o; c.CodeVolume_of_Bool_Array(ref v); } },\r\n            { typeof(List<Volume<bool>>), (c,o) => { var v = (List<Volume<bool>>)o; c.CodeList_of_Volume_of_Bool__(ref v); } },\r\n\r\n            { typeof(Tensor<bool>), (c,o) => { var v = (Tensor<bool>)o; c.CodeTensor_of_Bool_(ref v); } },\r\n            { typeof(Tensor<bool>[]), (c,o) => { var v = (Tensor<bool>[])o; c.CodeTensor_of_Bool_Array(ref v); } },\r\n            { typeof(List<Tensor<bool>>), (c,o) => { var v = (List<Tensor<bool>>)o; c.CodeList_of_Tensor_of_Bool__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region char\r\n\r\n            { typeof(char), (c,o) => { var v = (char)o; c.CodeChar(ref v); } },\r\n            { typeof(char[]), (c,o) => { var v = (char[])o; c.CodeCharArray(ref v); } },\r\n            { typeof(List<char>), (c,o) => { var v = (List<char>)o; c.CodeList_of_Char_(ref v); } },\r\n\r\n            { typeof(Vector<char>), (c,o) => { var v = (Vector<char>)o; c.CodeVector_of_Char_(ref v); } },\r\n            { typeof(Vector<char>[]), (c,o) => { var v = (Vector<char>[])o; c.CodeVector_of_Char_Array(ref v); } },\r\n            { typeof(List<Vector<char>>), (c,o) => { var v = (List<Vector<char>>)o; c.CodeList_of_Vector_of_Char__(ref v); } },\r\n\r\n            { typeof(Matrix<char>), (c,o) => { var v = (Matrix<char>)o; c.CodeMatrix_of_Char_(ref v); } },\r\n            { typeof(Matrix<char>[]), (c,o) => { var v = (Matrix<char>[])o; c.CodeMatrix_of_Char_Array(ref v); } },\r\n            { typeof(List<Matrix<char>>), (c,o) => { var v = (List<Matrix<char>>)o; c.CodeList_of_Matrix_of_Char__(ref v); } },\r\n\r\n            { typeof(Volume<char>), (c,o) => { var v = (Volume<char>)o; c.CodeVolume_of_Char_(ref v); } },\r\n            { typeof(Volume<char>[]), (c,o) => { var v = (Volume<char>[])o; c.CodeVolume_of_Char_Array(ref v); } },\r\n            { typeof(List<Volume<char>>), (c,o) => { var v = (List<Volume<char>>)o; c.CodeList_of_Volume_of_Char__(ref v); } },\r\n\r\n            { typeof(Tensor<char>), (c,o) => { var v = (Tensor<char>)o; c.CodeTensor_of_Char_(ref v); } },\r\n            { typeof(Tensor<char>[]), (c,o) => { var v = (Tensor<char>[])o; c.CodeTensor_of_Char_Array(ref v); } },\r\n            { typeof(List<Tensor<char>>), (c,o) => { var v = (List<Tensor<char>>)o; c.CodeList_of_Tensor_of_Char__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region string\r\n\r\n            { typeof(string), (c,o) => { var v = (string)o; c.CodeString(ref v); } },\r\n            { typeof(string[]), (c,o) => { var v = (string[])o; c.CodeStringArray(ref v); } },\r\n            { typeof(List<string>), (c,o) => { var v = (List<string>)o; c.CodeList_of_String_(ref v); } },\r\n\r\n            { typeof(Vector<string>), (c,o) => { var v = (Vector<string>)o; c.CodeVector_of_String_(ref v); } },\r\n            { typeof(Vector<string>[]), (c,o) => { var v = (Vector<string>[])o; c.CodeVector_of_String_Array(ref v); } },\r\n            { typeof(List<Vector<string>>), (c,o) => { var v = (List<Vector<string>>)o; c.CodeList_of_Vector_of_String__(ref v); } },\r\n\r\n            { typeof(Matrix<string>), (c,o) => { var v = (Matrix<string>)o; c.CodeMatrix_of_String_(ref v); } },\r\n            { typeof(Matrix<string>[]), (c,o) => { var v = (Matrix<string>[])o; c.CodeMatrix_of_String_Array(ref v); } },\r\n            { typeof(List<Matrix<string>>), (c,o) => { var v = (List<Matrix<string>>)o; c.CodeList_of_Matrix_of_String__(ref v); } },\r\n\r\n            { typeof(Volume<string>), (c,o) => { var v = (Volume<string>)o; c.CodeVolume_of_String_(ref v); } },\r\n            { typeof(Volume<string>[]), (c,o) => { var v = (Volume<string>[])o; c.CodeVolume_of_String_Array(ref v); } },\r\n            { typeof(List<Volume<string>>), (c,o) => { var v = (List<Volume<string>>)o; c.CodeList_of_Volume_of_String__(ref v); } },\r\n\r\n            { typeof(Tensor<string>), (c,o) => { var v = (Tensor<string>)o; c.CodeTensor_of_String_(ref v); } },\r\n            { typeof(Tensor<string>[]), (c,o) => { var v = (Tensor<string>[])o; c.CodeTensor_of_String_Array(ref v); } },\r\n            { typeof(List<Tensor<string>>), (c,o) => { var v = (List<Tensor<string>>)o; c.CodeList_of_Tensor_of_String__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Type\r\n\r\n            { typeof(Type), (c,o) => { var v = (Type)o; c.CodeType(ref v); } },\r\n            { typeof(Type[]), (c,o) => { var v = (Type[])o; c.CodeTypeArray(ref v); } },\r\n            { typeof(List<Type>), (c,o) => { var v = (List<Type>)o; c.CodeList_of_Type_(ref v); } },\r\n\r\n            { typeof(Vector<Type>), (c,o) => { var v = (Vector<Type>)o; c.CodeVector_of_Type_(ref v); } },\r\n            { typeof(Vector<Type>[]), (c,o) => { var v = (Vector<Type>[])o; c.CodeVector_of_Type_Array(ref v); } },\r\n            { typeof(List<Vector<Type>>), (c,o) => { var v = (List<Vector<Type>>)o; c.CodeList_of_Vector_of_Type__(ref v); } },\r\n\r\n            { typeof(Matrix<Type>), (c,o) => { var v = (Matrix<Type>)o; c.CodeMatrix_of_Type_(ref v); } },\r\n            { typeof(Matrix<Type>[]), (c,o) => { var v = (Matrix<Type>[])o; c.CodeMatrix_of_Type_Array(ref v); } },\r\n            { typeof(List<Matrix<Type>>), (c,o) => { var v = (List<Matrix<Type>>)o; c.CodeList_of_Matrix_of_Type__(ref v); } },\r\n\r\n            { typeof(Volume<Type>), (c,o) => { var v = (Volume<Type>)o; c.CodeVolume_of_Type_(ref v); } },\r\n            { typeof(Volume<Type>[]), (c,o) => { var v = (Volume<Type>[])o; c.CodeVolume_of_Type_Array(ref v); } },\r\n            { typeof(List<Volume<Type>>), (c,o) => { var v = (List<Volume<Type>>)o; c.CodeList_of_Volume_of_Type__(ref v); } },\r\n\r\n            { typeof(Tensor<Type>), (c,o) => { var v = (Tensor<Type>)o; c.CodeTensor_of_Type_(ref v); } },\r\n            { typeof(Tensor<Type>[]), (c,o) => { var v = (Tensor<Type>[])o; c.CodeTensor_of_Type_Array(ref v); } },\r\n            { typeof(List<Tensor<Type>>), (c,o) => { var v = (List<Tensor<Type>>)o; c.CodeList_of_Tensor_of_Type__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Guid\r\n\r\n            { typeof(Guid), (c,o) => { var v = (Guid)o; c.CodeGuid(ref v); } },\r\n            { typeof(Guid[]), (c,o) => { var v = (Guid[])o; c.CodeGuidArray(ref v); } },\r\n            { typeof(List<Guid>), (c,o) => { var v = (List<Guid>)o; c.CodeList_of_Guid_(ref v); } },\r\n\r\n            { typeof(Vector<Guid>), (c,o) => { var v = (Vector<Guid>)o; c.CodeVector_of_Guid_(ref v); } },\r\n            { typeof(Vector<Guid>[]), (c,o) => { var v = (Vector<Guid>[])o; c.CodeVector_of_Guid_Array(ref v); } },\r\n            { typeof(List<Vector<Guid>>), (c,o) => { var v = (List<Vector<Guid>>)o; c.CodeList_of_Vector_of_Guid__(ref v); } },\r\n\r\n            { typeof(Matrix<Guid>), (c,o) => { var v = (Matrix<Guid>)o; c.CodeMatrix_of_Guid_(ref v); } },\r\n            { typeof(Matrix<Guid>[]), (c,o) => { var v = (Matrix<Guid>[])o; c.CodeMatrix_of_Guid_Array(ref v); } },\r\n            { typeof(List<Matrix<Guid>>), (c,o) => { var v = (List<Matrix<Guid>>)o; c.CodeList_of_Matrix_of_Guid__(ref v); } },\r\n\r\n            { typeof(Volume<Guid>), (c,o) => { var v = (Volume<Guid>)o; c.CodeVolume_of_Guid_(ref v); } },\r\n            { typeof(Volume<Guid>[]), (c,o) => { var v = (Volume<Guid>[])o; c.CodeVolume_of_Guid_Array(ref v); } },\r\n            { typeof(List<Volume<Guid>>), (c,o) => { var v = (List<Volume<Guid>>)o; c.CodeList_of_Volume_of_Guid__(ref v); } },\r\n\r\n            { typeof(Tensor<Guid>), (c,o) => { var v = (Tensor<Guid>)o; c.CodeTensor_of_Guid_(ref v); } },\r\n            { typeof(Tensor<Guid>[]), (c,o) => { var v = (Tensor<Guid>[])o; c.CodeTensor_of_Guid_Array(ref v); } },\r\n            { typeof(List<Tensor<Guid>>), (c,o) => { var v = (List<Tensor<Guid>>)o; c.CodeList_of_Tensor_of_Guid__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Symbol\r\n\r\n            { typeof(Symbol), (c,o) => { var v = (Symbol)o; c.CodeSymbol(ref v); } },\r\n            { typeof(Symbol[]), (c,o) => { var v = (Symbol[])o; c.CodeSymbolArray(ref v); } },\r\n            { typeof(List<Symbol>), (c,o) => { var v = (List<Symbol>)o; c.CodeList_of_Symbol_(ref v); } },\r\n\r\n            { typeof(Vector<Symbol>), (c,o) => { var v = (Vector<Symbol>)o; c.CodeVector_of_Symbol_(ref v); } },\r\n            { typeof(Vector<Symbol>[]), (c,o) => { var v = (Vector<Symbol>[])o; c.CodeVector_of_Symbol_Array(ref v); } },\r\n            { typeof(List<Vector<Symbol>>), (c,o) => { var v = (List<Vector<Symbol>>)o; c.CodeList_of_Vector_of_Symbol__(ref v); } },\r\n\r\n            { typeof(Matrix<Symbol>), (c,o) => { var v = (Matrix<Symbol>)o; c.CodeMatrix_of_Symbol_(ref v); } },\r\n            { typeof(Matrix<Symbol>[]), (c,o) => { var v = (Matrix<Symbol>[])o; c.CodeMatrix_of_Symbol_Array(ref v); } },\r\n            { typeof(List<Matrix<Symbol>>), (c,o) => { var v = (List<Matrix<Symbol>>)o; c.CodeList_of_Matrix_of_Symbol__(ref v); } },\r\n\r\n            { typeof(Volume<Symbol>), (c,o) => { var v = (Volume<Symbol>)o; c.CodeVolume_of_Symbol_(ref v); } },\r\n            { typeof(Volume<Symbol>[]), (c,o) => { var v = (Volume<Symbol>[])o; c.CodeVolume_of_Symbol_Array(ref v); } },\r\n            { typeof(List<Volume<Symbol>>), (c,o) => { var v = (List<Volume<Symbol>>)o; c.CodeList_of_Volume_of_Symbol__(ref v); } },\r\n\r\n            { typeof(Tensor<Symbol>), (c,o) => { var v = (Tensor<Symbol>)o; c.CodeTensor_of_Symbol_(ref v); } },\r\n            { typeof(Tensor<Symbol>[]), (c,o) => { var v = (Tensor<Symbol>[])o; c.CodeTensor_of_Symbol_Array(ref v); } },\r\n            { typeof(List<Tensor<Symbol>>), (c,o) => { var v = (List<Tensor<Symbol>>)o; c.CodeList_of_Tensor_of_Symbol__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Circle2d\r\n\r\n            { typeof(Circle2d), (c,o) => { var v = (Circle2d)o; c.CodeCircle2d(ref v); } },\r\n            { typeof(Circle2d[]), (c,o) => { var v = (Circle2d[])o; c.CodeCircle2dArray(ref v); } },\r\n            { typeof(List<Circle2d>), (c,o) => { var v = (List<Circle2d>)o; c.CodeList_of_Circle2d_(ref v); } },\r\n\r\n            { typeof(Vector<Circle2d>), (c,o) => { var v = (Vector<Circle2d>)o; c.CodeVector_of_Circle2d_(ref v); } },\r\n            { typeof(Vector<Circle2d>[]), (c,o) => { var v = (Vector<Circle2d>[])o; c.CodeVector_of_Circle2d_Array(ref v); } },\r\n            { typeof(List<Vector<Circle2d>>), (c,o) => { var v = (List<Vector<Circle2d>>)o; c.CodeList_of_Vector_of_Circle2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Circle2d>), (c,o) => { var v = (Matrix<Circle2d>)o; c.CodeMatrix_of_Circle2d_(ref v); } },\r\n            { typeof(Matrix<Circle2d>[]), (c,o) => { var v = (Matrix<Circle2d>[])o; c.CodeMatrix_of_Circle2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Circle2d>>), (c,o) => { var v = (List<Matrix<Circle2d>>)o; c.CodeList_of_Matrix_of_Circle2d__(ref v); } },\r\n\r\n            { typeof(Volume<Circle2d>), (c,o) => { var v = (Volume<Circle2d>)o; c.CodeVolume_of_Circle2d_(ref v); } },\r\n            { typeof(Volume<Circle2d>[]), (c,o) => { var v = (Volume<Circle2d>[])o; c.CodeVolume_of_Circle2d_Array(ref v); } },\r\n            { typeof(List<Volume<Circle2d>>), (c,o) => { var v = (List<Volume<Circle2d>>)o; c.CodeList_of_Volume_of_Circle2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Circle2d>), (c,o) => { var v = (Tensor<Circle2d>)o; c.CodeTensor_of_Circle2d_(ref v); } },\r\n            { typeof(Tensor<Circle2d>[]), (c,o) => { var v = (Tensor<Circle2d>[])o; c.CodeTensor_of_Circle2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Circle2d>>), (c,o) => { var v = (List<Tensor<Circle2d>>)o; c.CodeList_of_Tensor_of_Circle2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Line2d\r\n\r\n            { typeof(Line2d), (c,o) => { var v = (Line2d)o; c.CodeLine2d(ref v); } },\r\n            { typeof(Line2d[]), (c,o) => { var v = (Line2d[])o; c.CodeLine2dArray(ref v); } },\r\n            { typeof(List<Line2d>), (c,o) => { var v = (List<Line2d>)o; c.CodeList_of_Line2d_(ref v); } },\r\n\r\n            { typeof(Vector<Line2d>), (c,o) => { var v = (Vector<Line2d>)o; c.CodeVector_of_Line2d_(ref v); } },\r\n            { typeof(Vector<Line2d>[]), (c,o) => { var v = (Vector<Line2d>[])o; c.CodeVector_of_Line2d_Array(ref v); } },\r\n            { typeof(List<Vector<Line2d>>), (c,o) => { var v = (List<Vector<Line2d>>)o; c.CodeList_of_Vector_of_Line2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Line2d>), (c,o) => { var v = (Matrix<Line2d>)o; c.CodeMatrix_of_Line2d_(ref v); } },\r\n            { typeof(Matrix<Line2d>[]), (c,o) => { var v = (Matrix<Line2d>[])o; c.CodeMatrix_of_Line2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Line2d>>), (c,o) => { var v = (List<Matrix<Line2d>>)o; c.CodeList_of_Matrix_of_Line2d__(ref v); } },\r\n\r\n            { typeof(Volume<Line2d>), (c,o) => { var v = (Volume<Line2d>)o; c.CodeVolume_of_Line2d_(ref v); } },\r\n            { typeof(Volume<Line2d>[]), (c,o) => { var v = (Volume<Line2d>[])o; c.CodeVolume_of_Line2d_Array(ref v); } },\r\n            { typeof(List<Volume<Line2d>>), (c,o) => { var v = (List<Volume<Line2d>>)o; c.CodeList_of_Volume_of_Line2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Line2d>), (c,o) => { var v = (Tensor<Line2d>)o; c.CodeTensor_of_Line2d_(ref v); } },\r\n            { typeof(Tensor<Line2d>[]), (c,o) => { var v = (Tensor<Line2d>[])o; c.CodeTensor_of_Line2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Line2d>>), (c,o) => { var v = (List<Tensor<Line2d>>)o; c.CodeList_of_Tensor_of_Line2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Line3d\r\n\r\n            { typeof(Line3d), (c,o) => { var v = (Line3d)o; c.CodeLine3d(ref v); } },\r\n            { typeof(Line3d[]), (c,o) => { var v = (Line3d[])o; c.CodeLine3dArray(ref v); } },\r\n            { typeof(List<Line3d>), (c,o) => { var v = (List<Line3d>)o; c.CodeList_of_Line3d_(ref v); } },\r\n\r\n            { typeof(Vector<Line3d>), (c,o) => { var v = (Vector<Line3d>)o; c.CodeVector_of_Line3d_(ref v); } },\r\n            { typeof(Vector<Line3d>[]), (c,o) => { var v = (Vector<Line3d>[])o; c.CodeVector_of_Line3d_Array(ref v); } },\r\n            { typeof(List<Vector<Line3d>>), (c,o) => { var v = (List<Vector<Line3d>>)o; c.CodeList_of_Vector_of_Line3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Line3d>), (c,o) => { var v = (Matrix<Line3d>)o; c.CodeMatrix_of_Line3d_(ref v); } },\r\n            { typeof(Matrix<Line3d>[]), (c,o) => { var v = (Matrix<Line3d>[])o; c.CodeMatrix_of_Line3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Line3d>>), (c,o) => { var v = (List<Matrix<Line3d>>)o; c.CodeList_of_Matrix_of_Line3d__(ref v); } },\r\n\r\n            { typeof(Volume<Line3d>), (c,o) => { var v = (Volume<Line3d>)o; c.CodeVolume_of_Line3d_(ref v); } },\r\n            { typeof(Volume<Line3d>[]), (c,o) => { var v = (Volume<Line3d>[])o; c.CodeVolume_of_Line3d_Array(ref v); } },\r\n            { typeof(List<Volume<Line3d>>), (c,o) => { var v = (List<Volume<Line3d>>)o; c.CodeList_of_Volume_of_Line3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Line3d>), (c,o) => { var v = (Tensor<Line3d>)o; c.CodeTensor_of_Line3d_(ref v); } },\r\n            { typeof(Tensor<Line3d>[]), (c,o) => { var v = (Tensor<Line3d>[])o; c.CodeTensor_of_Line3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Line3d>>), (c,o) => { var v = (List<Tensor<Line3d>>)o; c.CodeList_of_Tensor_of_Line3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Plane2d\r\n\r\n            { typeof(Plane2d), (c,o) => { var v = (Plane2d)o; c.CodePlane2d(ref v); } },\r\n            { typeof(Plane2d[]), (c,o) => { var v = (Plane2d[])o; c.CodePlane2dArray(ref v); } },\r\n            { typeof(List<Plane2d>), (c,o) => { var v = (List<Plane2d>)o; c.CodeList_of_Plane2d_(ref v); } },\r\n\r\n            { typeof(Vector<Plane2d>), (c,o) => { var v = (Vector<Plane2d>)o; c.CodeVector_of_Plane2d_(ref v); } },\r\n            { typeof(Vector<Plane2d>[]), (c,o) => { var v = (Vector<Plane2d>[])o; c.CodeVector_of_Plane2d_Array(ref v); } },\r\n            { typeof(List<Vector<Plane2d>>), (c,o) => { var v = (List<Vector<Plane2d>>)o; c.CodeList_of_Vector_of_Plane2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Plane2d>), (c,o) => { var v = (Matrix<Plane2d>)o; c.CodeMatrix_of_Plane2d_(ref v); } },\r\n            { typeof(Matrix<Plane2d>[]), (c,o) => { var v = (Matrix<Plane2d>[])o; c.CodeMatrix_of_Plane2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Plane2d>>), (c,o) => { var v = (List<Matrix<Plane2d>>)o; c.CodeList_of_Matrix_of_Plane2d__(ref v); } },\r\n\r\n            { typeof(Volume<Plane2d>), (c,o) => { var v = (Volume<Plane2d>)o; c.CodeVolume_of_Plane2d_(ref v); } },\r\n            { typeof(Volume<Plane2d>[]), (c,o) => { var v = (Volume<Plane2d>[])o; c.CodeVolume_of_Plane2d_Array(ref v); } },\r\n            { typeof(List<Volume<Plane2d>>), (c,o) => { var v = (List<Volume<Plane2d>>)o; c.CodeList_of_Volume_of_Plane2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Plane2d>), (c,o) => { var v = (Tensor<Plane2d>)o; c.CodeTensor_of_Plane2d_(ref v); } },\r\n            { typeof(Tensor<Plane2d>[]), (c,o) => { var v = (Tensor<Plane2d>[])o; c.CodeTensor_of_Plane2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Plane2d>>), (c,o) => { var v = (List<Tensor<Plane2d>>)o; c.CodeList_of_Tensor_of_Plane2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Plane3d\r\n\r\n            { typeof(Plane3d), (c,o) => { var v = (Plane3d)o; c.CodePlane3d(ref v); } },\r\n            { typeof(Plane3d[]), (c,o) => { var v = (Plane3d[])o; c.CodePlane3dArray(ref v); } },\r\n            { typeof(List<Plane3d>), (c,o) => { var v = (List<Plane3d>)o; c.CodeList_of_Plane3d_(ref v); } },\r\n\r\n            { typeof(Vector<Plane3d>), (c,o) => { var v = (Vector<Plane3d>)o; c.CodeVector_of_Plane3d_(ref v); } },\r\n            { typeof(Vector<Plane3d>[]), (c,o) => { var v = (Vector<Plane3d>[])o; c.CodeVector_of_Plane3d_Array(ref v); } },\r\n            { typeof(List<Vector<Plane3d>>), (c,o) => { var v = (List<Vector<Plane3d>>)o; c.CodeList_of_Vector_of_Plane3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Plane3d>), (c,o) => { var v = (Matrix<Plane3d>)o; c.CodeMatrix_of_Plane3d_(ref v); } },\r\n            { typeof(Matrix<Plane3d>[]), (c,o) => { var v = (Matrix<Plane3d>[])o; c.CodeMatrix_of_Plane3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Plane3d>>), (c,o) => { var v = (List<Matrix<Plane3d>>)o; c.CodeList_of_Matrix_of_Plane3d__(ref v); } },\r\n\r\n            { typeof(Volume<Plane3d>), (c,o) => { var v = (Volume<Plane3d>)o; c.CodeVolume_of_Plane3d_(ref v); } },\r\n            { typeof(Volume<Plane3d>[]), (c,o) => { var v = (Volume<Plane3d>[])o; c.CodeVolume_of_Plane3d_Array(ref v); } },\r\n            { typeof(List<Volume<Plane3d>>), (c,o) => { var v = (List<Volume<Plane3d>>)o; c.CodeList_of_Volume_of_Plane3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Plane3d>), (c,o) => { var v = (Tensor<Plane3d>)o; c.CodeTensor_of_Plane3d_(ref v); } },\r\n            { typeof(Tensor<Plane3d>[]), (c,o) => { var v = (Tensor<Plane3d>[])o; c.CodeTensor_of_Plane3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Plane3d>>), (c,o) => { var v = (List<Tensor<Plane3d>>)o; c.CodeList_of_Tensor_of_Plane3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region PlaneWithPoint3d\r\n\r\n            { typeof(PlaneWithPoint3d), (c,o) => { var v = (PlaneWithPoint3d)o; c.CodePlaneWithPoint3d(ref v); } },\r\n            { typeof(PlaneWithPoint3d[]), (c,o) => { var v = (PlaneWithPoint3d[])o; c.CodePlaneWithPoint3dArray(ref v); } },\r\n            { typeof(List<PlaneWithPoint3d>), (c,o) => { var v = (List<PlaneWithPoint3d>)o; c.CodeList_of_PlaneWithPoint3d_(ref v); } },\r\n\r\n            { typeof(Vector<PlaneWithPoint3d>), (c,o) => { var v = (Vector<PlaneWithPoint3d>)o; c.CodeVector_of_PlaneWithPoint3d_(ref v); } },\r\n            { typeof(Vector<PlaneWithPoint3d>[]), (c,o) => { var v = (Vector<PlaneWithPoint3d>[])o; c.CodeVector_of_PlaneWithPoint3d_Array(ref v); } },\r\n            { typeof(List<Vector<PlaneWithPoint3d>>), (c,o) => { var v = (List<Vector<PlaneWithPoint3d>>)o; c.CodeList_of_Vector_of_PlaneWithPoint3d__(ref v); } },\r\n\r\n            { typeof(Matrix<PlaneWithPoint3d>), (c,o) => { var v = (Matrix<PlaneWithPoint3d>)o; c.CodeMatrix_of_PlaneWithPoint3d_(ref v); } },\r\n            { typeof(Matrix<PlaneWithPoint3d>[]), (c,o) => { var v = (Matrix<PlaneWithPoint3d>[])o; c.CodeMatrix_of_PlaneWithPoint3d_Array(ref v); } },\r\n            { typeof(List<Matrix<PlaneWithPoint3d>>), (c,o) => { var v = (List<Matrix<PlaneWithPoint3d>>)o; c.CodeList_of_Matrix_of_PlaneWithPoint3d__(ref v); } },\r\n\r\n            { typeof(Volume<PlaneWithPoint3d>), (c,o) => { var v = (Volume<PlaneWithPoint3d>)o; c.CodeVolume_of_PlaneWithPoint3d_(ref v); } },\r\n            { typeof(Volume<PlaneWithPoint3d>[]), (c,o) => { var v = (Volume<PlaneWithPoint3d>[])o; c.CodeVolume_of_PlaneWithPoint3d_Array(ref v); } },\r\n            { typeof(List<Volume<PlaneWithPoint3d>>), (c,o) => { var v = (List<Volume<PlaneWithPoint3d>>)o; c.CodeList_of_Volume_of_PlaneWithPoint3d__(ref v); } },\r\n\r\n            { typeof(Tensor<PlaneWithPoint3d>), (c,o) => { var v = (Tensor<PlaneWithPoint3d>)o; c.CodeTensor_of_PlaneWithPoint3d_(ref v); } },\r\n            { typeof(Tensor<PlaneWithPoint3d>[]), (c,o) => { var v = (Tensor<PlaneWithPoint3d>[])o; c.CodeTensor_of_PlaneWithPoint3d_Array(ref v); } },\r\n            { typeof(List<Tensor<PlaneWithPoint3d>>), (c,o) => { var v = (List<Tensor<PlaneWithPoint3d>>)o; c.CodeList_of_Tensor_of_PlaneWithPoint3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Quad2d\r\n\r\n            { typeof(Quad2d), (c,o) => { var v = (Quad2d)o; c.CodeQuad2d(ref v); } },\r\n            { typeof(Quad2d[]), (c,o) => { var v = (Quad2d[])o; c.CodeQuad2dArray(ref v); } },\r\n            { typeof(List<Quad2d>), (c,o) => { var v = (List<Quad2d>)o; c.CodeList_of_Quad2d_(ref v); } },\r\n\r\n            { typeof(Vector<Quad2d>), (c,o) => { var v = (Vector<Quad2d>)o; c.CodeVector_of_Quad2d_(ref v); } },\r\n            { typeof(Vector<Quad2d>[]), (c,o) => { var v = (Vector<Quad2d>[])o; c.CodeVector_of_Quad2d_Array(ref v); } },\r\n            { typeof(List<Vector<Quad2d>>), (c,o) => { var v = (List<Vector<Quad2d>>)o; c.CodeList_of_Vector_of_Quad2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Quad2d>), (c,o) => { var v = (Matrix<Quad2d>)o; c.CodeMatrix_of_Quad2d_(ref v); } },\r\n            { typeof(Matrix<Quad2d>[]), (c,o) => { var v = (Matrix<Quad2d>[])o; c.CodeMatrix_of_Quad2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Quad2d>>), (c,o) => { var v = (List<Matrix<Quad2d>>)o; c.CodeList_of_Matrix_of_Quad2d__(ref v); } },\r\n\r\n            { typeof(Volume<Quad2d>), (c,o) => { var v = (Volume<Quad2d>)o; c.CodeVolume_of_Quad2d_(ref v); } },\r\n            { typeof(Volume<Quad2d>[]), (c,o) => { var v = (Volume<Quad2d>[])o; c.CodeVolume_of_Quad2d_Array(ref v); } },\r\n            { typeof(List<Volume<Quad2d>>), (c,o) => { var v = (List<Volume<Quad2d>>)o; c.CodeList_of_Volume_of_Quad2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Quad2d>), (c,o) => { var v = (Tensor<Quad2d>)o; c.CodeTensor_of_Quad2d_(ref v); } },\r\n            { typeof(Tensor<Quad2d>[]), (c,o) => { var v = (Tensor<Quad2d>[])o; c.CodeTensor_of_Quad2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Quad2d>>), (c,o) => { var v = (List<Tensor<Quad2d>>)o; c.CodeList_of_Tensor_of_Quad2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Quad3d\r\n\r\n            { typeof(Quad3d), (c,o) => { var v = (Quad3d)o; c.CodeQuad3d(ref v); } },\r\n            { typeof(Quad3d[]), (c,o) => { var v = (Quad3d[])o; c.CodeQuad3dArray(ref v); } },\r\n            { typeof(List<Quad3d>), (c,o) => { var v = (List<Quad3d>)o; c.CodeList_of_Quad3d_(ref v); } },\r\n\r\n            { typeof(Vector<Quad3d>), (c,o) => { var v = (Vector<Quad3d>)o; c.CodeVector_of_Quad3d_(ref v); } },\r\n            { typeof(Vector<Quad3d>[]), (c,o) => { var v = (Vector<Quad3d>[])o; c.CodeVector_of_Quad3d_Array(ref v); } },\r\n            { typeof(List<Vector<Quad3d>>), (c,o) => { var v = (List<Vector<Quad3d>>)o; c.CodeList_of_Vector_of_Quad3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Quad3d>), (c,o) => { var v = (Matrix<Quad3d>)o; c.CodeMatrix_of_Quad3d_(ref v); } },\r\n            { typeof(Matrix<Quad3d>[]), (c,o) => { var v = (Matrix<Quad3d>[])o; c.CodeMatrix_of_Quad3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Quad3d>>), (c,o) => { var v = (List<Matrix<Quad3d>>)o; c.CodeList_of_Matrix_of_Quad3d__(ref v); } },\r\n\r\n            { typeof(Volume<Quad3d>), (c,o) => { var v = (Volume<Quad3d>)o; c.CodeVolume_of_Quad3d_(ref v); } },\r\n            { typeof(Volume<Quad3d>[]), (c,o) => { var v = (Volume<Quad3d>[])o; c.CodeVolume_of_Quad3d_Array(ref v); } },\r\n            { typeof(List<Volume<Quad3d>>), (c,o) => { var v = (List<Volume<Quad3d>>)o; c.CodeList_of_Volume_of_Quad3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Quad3d>), (c,o) => { var v = (Tensor<Quad3d>)o; c.CodeTensor_of_Quad3d_(ref v); } },\r\n            { typeof(Tensor<Quad3d>[]), (c,o) => { var v = (Tensor<Quad3d>[])o; c.CodeTensor_of_Quad3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Quad3d>>), (c,o) => { var v = (List<Tensor<Quad3d>>)o; c.CodeList_of_Tensor_of_Quad3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Ray2d\r\n\r\n            { typeof(Ray2d), (c,o) => { var v = (Ray2d)o; c.CodeRay2d(ref v); } },\r\n            { typeof(Ray2d[]), (c,o) => { var v = (Ray2d[])o; c.CodeRay2dArray(ref v); } },\r\n            { typeof(List<Ray2d>), (c,o) => { var v = (List<Ray2d>)o; c.CodeList_of_Ray2d_(ref v); } },\r\n\r\n            { typeof(Vector<Ray2d>), (c,o) => { var v = (Vector<Ray2d>)o; c.CodeVector_of_Ray2d_(ref v); } },\r\n            { typeof(Vector<Ray2d>[]), (c,o) => { var v = (Vector<Ray2d>[])o; c.CodeVector_of_Ray2d_Array(ref v); } },\r\n            { typeof(List<Vector<Ray2d>>), (c,o) => { var v = (List<Vector<Ray2d>>)o; c.CodeList_of_Vector_of_Ray2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Ray2d>), (c,o) => { var v = (Matrix<Ray2d>)o; c.CodeMatrix_of_Ray2d_(ref v); } },\r\n            { typeof(Matrix<Ray2d>[]), (c,o) => { var v = (Matrix<Ray2d>[])o; c.CodeMatrix_of_Ray2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Ray2d>>), (c,o) => { var v = (List<Matrix<Ray2d>>)o; c.CodeList_of_Matrix_of_Ray2d__(ref v); } },\r\n\r\n            { typeof(Volume<Ray2d>), (c,o) => { var v = (Volume<Ray2d>)o; c.CodeVolume_of_Ray2d_(ref v); } },\r\n            { typeof(Volume<Ray2d>[]), (c,o) => { var v = (Volume<Ray2d>[])o; c.CodeVolume_of_Ray2d_Array(ref v); } },\r\n            { typeof(List<Volume<Ray2d>>), (c,o) => { var v = (List<Volume<Ray2d>>)o; c.CodeList_of_Volume_of_Ray2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Ray2d>), (c,o) => { var v = (Tensor<Ray2d>)o; c.CodeTensor_of_Ray2d_(ref v); } },\r\n            { typeof(Tensor<Ray2d>[]), (c,o) => { var v = (Tensor<Ray2d>[])o; c.CodeTensor_of_Ray2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Ray2d>>), (c,o) => { var v = (List<Tensor<Ray2d>>)o; c.CodeList_of_Tensor_of_Ray2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Ray3d\r\n\r\n            { typeof(Ray3d), (c,o) => { var v = (Ray3d)o; c.CodeRay3d(ref v); } },\r\n            { typeof(Ray3d[]), (c,o) => { var v = (Ray3d[])o; c.CodeRay3dArray(ref v); } },\r\n            { typeof(List<Ray3d>), (c,o) => { var v = (List<Ray3d>)o; c.CodeList_of_Ray3d_(ref v); } },\r\n\r\n            { typeof(Vector<Ray3d>), (c,o) => { var v = (Vector<Ray3d>)o; c.CodeVector_of_Ray3d_(ref v); } },\r\n            { typeof(Vector<Ray3d>[]), (c,o) => { var v = (Vector<Ray3d>[])o; c.CodeVector_of_Ray3d_Array(ref v); } },\r\n            { typeof(List<Vector<Ray3d>>), (c,o) => { var v = (List<Vector<Ray3d>>)o; c.CodeList_of_Vector_of_Ray3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Ray3d>), (c,o) => { var v = (Matrix<Ray3d>)o; c.CodeMatrix_of_Ray3d_(ref v); } },\r\n            { typeof(Matrix<Ray3d>[]), (c,o) => { var v = (Matrix<Ray3d>[])o; c.CodeMatrix_of_Ray3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Ray3d>>), (c,o) => { var v = (List<Matrix<Ray3d>>)o; c.CodeList_of_Matrix_of_Ray3d__(ref v); } },\r\n\r\n            { typeof(Volume<Ray3d>), (c,o) => { var v = (Volume<Ray3d>)o; c.CodeVolume_of_Ray3d_(ref v); } },\r\n            { typeof(Volume<Ray3d>[]), (c,o) => { var v = (Volume<Ray3d>[])o; c.CodeVolume_of_Ray3d_Array(ref v); } },\r\n            { typeof(List<Volume<Ray3d>>), (c,o) => { var v = (List<Volume<Ray3d>>)o; c.CodeList_of_Volume_of_Ray3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Ray3d>), (c,o) => { var v = (Tensor<Ray3d>)o; c.CodeTensor_of_Ray3d_(ref v); } },\r\n            { typeof(Tensor<Ray3d>[]), (c,o) => { var v = (Tensor<Ray3d>[])o; c.CodeTensor_of_Ray3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Ray3d>>), (c,o) => { var v = (List<Tensor<Ray3d>>)o; c.CodeList_of_Tensor_of_Ray3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Sphere3d\r\n\r\n            { typeof(Sphere3d), (c,o) => { var v = (Sphere3d)o; c.CodeSphere3d(ref v); } },\r\n            { typeof(Sphere3d[]), (c,o) => { var v = (Sphere3d[])o; c.CodeSphere3dArray(ref v); } },\r\n            { typeof(List<Sphere3d>), (c,o) => { var v = (List<Sphere3d>)o; c.CodeList_of_Sphere3d_(ref v); } },\r\n\r\n            { typeof(Vector<Sphere3d>), (c,o) => { var v = (Vector<Sphere3d>)o; c.CodeVector_of_Sphere3d_(ref v); } },\r\n            { typeof(Vector<Sphere3d>[]), (c,o) => { var v = (Vector<Sphere3d>[])o; c.CodeVector_of_Sphere3d_Array(ref v); } },\r\n            { typeof(List<Vector<Sphere3d>>), (c,o) => { var v = (List<Vector<Sphere3d>>)o; c.CodeList_of_Vector_of_Sphere3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Sphere3d>), (c,o) => { var v = (Matrix<Sphere3d>)o; c.CodeMatrix_of_Sphere3d_(ref v); } },\r\n            { typeof(Matrix<Sphere3d>[]), (c,o) => { var v = (Matrix<Sphere3d>[])o; c.CodeMatrix_of_Sphere3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Sphere3d>>), (c,o) => { var v = (List<Matrix<Sphere3d>>)o; c.CodeList_of_Matrix_of_Sphere3d__(ref v); } },\r\n\r\n            { typeof(Volume<Sphere3d>), (c,o) => { var v = (Volume<Sphere3d>)o; c.CodeVolume_of_Sphere3d_(ref v); } },\r\n            { typeof(Volume<Sphere3d>[]), (c,o) => { var v = (Volume<Sphere3d>[])o; c.CodeVolume_of_Sphere3d_Array(ref v); } },\r\n            { typeof(List<Volume<Sphere3d>>), (c,o) => { var v = (List<Volume<Sphere3d>>)o; c.CodeList_of_Volume_of_Sphere3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Sphere3d>), (c,o) => { var v = (Tensor<Sphere3d>)o; c.CodeTensor_of_Sphere3d_(ref v); } },\r\n            { typeof(Tensor<Sphere3d>[]), (c,o) => { var v = (Tensor<Sphere3d>[])o; c.CodeTensor_of_Sphere3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Sphere3d>>), (c,o) => { var v = (List<Tensor<Sphere3d>>)o; c.CodeList_of_Tensor_of_Sphere3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Triangle2d\r\n\r\n            { typeof(Triangle2d), (c,o) => { var v = (Triangle2d)o; c.CodeTriangle2d(ref v); } },\r\n            { typeof(Triangle2d[]), (c,o) => { var v = (Triangle2d[])o; c.CodeTriangle2dArray(ref v); } },\r\n            { typeof(List<Triangle2d>), (c,o) => { var v = (List<Triangle2d>)o; c.CodeList_of_Triangle2d_(ref v); } },\r\n\r\n            { typeof(Vector<Triangle2d>), (c,o) => { var v = (Vector<Triangle2d>)o; c.CodeVector_of_Triangle2d_(ref v); } },\r\n            { typeof(Vector<Triangle2d>[]), (c,o) => { var v = (Vector<Triangle2d>[])o; c.CodeVector_of_Triangle2d_Array(ref v); } },\r\n            { typeof(List<Vector<Triangle2d>>), (c,o) => { var v = (List<Vector<Triangle2d>>)o; c.CodeList_of_Vector_of_Triangle2d__(ref v); } },\r\n\r\n            { typeof(Matrix<Triangle2d>), (c,o) => { var v = (Matrix<Triangle2d>)o; c.CodeMatrix_of_Triangle2d_(ref v); } },\r\n            { typeof(Matrix<Triangle2d>[]), (c,o) => { var v = (Matrix<Triangle2d>[])o; c.CodeMatrix_of_Triangle2d_Array(ref v); } },\r\n            { typeof(List<Matrix<Triangle2d>>), (c,o) => { var v = (List<Matrix<Triangle2d>>)o; c.CodeList_of_Matrix_of_Triangle2d__(ref v); } },\r\n\r\n            { typeof(Volume<Triangle2d>), (c,o) => { var v = (Volume<Triangle2d>)o; c.CodeVolume_of_Triangle2d_(ref v); } },\r\n            { typeof(Volume<Triangle2d>[]), (c,o) => { var v = (Volume<Triangle2d>[])o; c.CodeVolume_of_Triangle2d_Array(ref v); } },\r\n            { typeof(List<Volume<Triangle2d>>), (c,o) => { var v = (List<Volume<Triangle2d>>)o; c.CodeList_of_Volume_of_Triangle2d__(ref v); } },\r\n\r\n            { typeof(Tensor<Triangle2d>), (c,o) => { var v = (Tensor<Triangle2d>)o; c.CodeTensor_of_Triangle2d_(ref v); } },\r\n            { typeof(Tensor<Triangle2d>[]), (c,o) => { var v = (Tensor<Triangle2d>[])o; c.CodeTensor_of_Triangle2d_Array(ref v); } },\r\n            { typeof(List<Tensor<Triangle2d>>), (c,o) => { var v = (List<Tensor<Triangle2d>>)o; c.CodeList_of_Tensor_of_Triangle2d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Triangle3d\r\n\r\n            { typeof(Triangle3d), (c,o) => { var v = (Triangle3d)o; c.CodeTriangle3d(ref v); } },\r\n            { typeof(Triangle3d[]), (c,o) => { var v = (Triangle3d[])o; c.CodeTriangle3dArray(ref v); } },\r\n            { typeof(List<Triangle3d>), (c,o) => { var v = (List<Triangle3d>)o; c.CodeList_of_Triangle3d_(ref v); } },\r\n\r\n            { typeof(Vector<Triangle3d>), (c,o) => { var v = (Vector<Triangle3d>)o; c.CodeVector_of_Triangle3d_(ref v); } },\r\n            { typeof(Vector<Triangle3d>[]), (c,o) => { var v = (Vector<Triangle3d>[])o; c.CodeVector_of_Triangle3d_Array(ref v); } },\r\n            { typeof(List<Vector<Triangle3d>>), (c,o) => { var v = (List<Vector<Triangle3d>>)o; c.CodeList_of_Vector_of_Triangle3d__(ref v); } },\r\n\r\n            { typeof(Matrix<Triangle3d>), (c,o) => { var v = (Matrix<Triangle3d>)o; c.CodeMatrix_of_Triangle3d_(ref v); } },\r\n            { typeof(Matrix<Triangle3d>[]), (c,o) => { var v = (Matrix<Triangle3d>[])o; c.CodeMatrix_of_Triangle3d_Array(ref v); } },\r\n            { typeof(List<Matrix<Triangle3d>>), (c,o) => { var v = (List<Matrix<Triangle3d>>)o; c.CodeList_of_Matrix_of_Triangle3d__(ref v); } },\r\n\r\n            { typeof(Volume<Triangle3d>), (c,o) => { var v = (Volume<Triangle3d>)o; c.CodeVolume_of_Triangle3d_(ref v); } },\r\n            { typeof(Volume<Triangle3d>[]), (c,o) => { var v = (Volume<Triangle3d>[])o; c.CodeVolume_of_Triangle3d_Array(ref v); } },\r\n            { typeof(List<Volume<Triangle3d>>), (c,o) => { var v = (List<Volume<Triangle3d>>)o; c.CodeList_of_Volume_of_Triangle3d__(ref v); } },\r\n\r\n            { typeof(Tensor<Triangle3d>), (c,o) => { var v = (Tensor<Triangle3d>)o; c.CodeTensor_of_Triangle3d_(ref v); } },\r\n            { typeof(Tensor<Triangle3d>[]), (c,o) => { var v = (Tensor<Triangle3d>[])o; c.CodeTensor_of_Triangle3d_Array(ref v); } },\r\n            { typeof(List<Tensor<Triangle3d>>), (c,o) => { var v = (List<Tensor<Triangle3d>>)o; c.CodeList_of_Tensor_of_Triangle3d__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Circle2f\r\n\r\n            { typeof(Circle2f), (c,o) => { var v = (Circle2f)o; c.CodeCircle2f(ref v); } },\r\n            { typeof(Circle2f[]), (c,o) => { var v = (Circle2f[])o; c.CodeCircle2fArray(ref v); } },\r\n            { typeof(List<Circle2f>), (c,o) => { var v = (List<Circle2f>)o; c.CodeList_of_Circle2f_(ref v); } },\r\n\r\n            { typeof(Vector<Circle2f>), (c,o) => { var v = (Vector<Circle2f>)o; c.CodeVector_of_Circle2f_(ref v); } },\r\n            { typeof(Vector<Circle2f>[]), (c,o) => { var v = (Vector<Circle2f>[])o; c.CodeVector_of_Circle2f_Array(ref v); } },\r\n            { typeof(List<Vector<Circle2f>>), (c,o) => { var v = (List<Vector<Circle2f>>)o; c.CodeList_of_Vector_of_Circle2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Circle2f>), (c,o) => { var v = (Matrix<Circle2f>)o; c.CodeMatrix_of_Circle2f_(ref v); } },\r\n            { typeof(Matrix<Circle2f>[]), (c,o) => { var v = (Matrix<Circle2f>[])o; c.CodeMatrix_of_Circle2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Circle2f>>), (c,o) => { var v = (List<Matrix<Circle2f>>)o; c.CodeList_of_Matrix_of_Circle2f__(ref v); } },\r\n\r\n            { typeof(Volume<Circle2f>), (c,o) => { var v = (Volume<Circle2f>)o; c.CodeVolume_of_Circle2f_(ref v); } },\r\n            { typeof(Volume<Circle2f>[]), (c,o) => { var v = (Volume<Circle2f>[])o; c.CodeVolume_of_Circle2f_Array(ref v); } },\r\n            { typeof(List<Volume<Circle2f>>), (c,o) => { var v = (List<Volume<Circle2f>>)o; c.CodeList_of_Volume_of_Circle2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Circle2f>), (c,o) => { var v = (Tensor<Circle2f>)o; c.CodeTensor_of_Circle2f_(ref v); } },\r\n            { typeof(Tensor<Circle2f>[]), (c,o) => { var v = (Tensor<Circle2f>[])o; c.CodeTensor_of_Circle2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Circle2f>>), (c,o) => { var v = (List<Tensor<Circle2f>>)o; c.CodeList_of_Tensor_of_Circle2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Line2f\r\n\r\n            { typeof(Line2f), (c,o) => { var v = (Line2f)o; c.CodeLine2f(ref v); } },\r\n            { typeof(Line2f[]), (c,o) => { var v = (Line2f[])o; c.CodeLine2fArray(ref v); } },\r\n            { typeof(List<Line2f>), (c,o) => { var v = (List<Line2f>)o; c.CodeList_of_Line2f_(ref v); } },\r\n\r\n            { typeof(Vector<Line2f>), (c,o) => { var v = (Vector<Line2f>)o; c.CodeVector_of_Line2f_(ref v); } },\r\n            { typeof(Vector<Line2f>[]), (c,o) => { var v = (Vector<Line2f>[])o; c.CodeVector_of_Line2f_Array(ref v); } },\r\n            { typeof(List<Vector<Line2f>>), (c,o) => { var v = (List<Vector<Line2f>>)o; c.CodeList_of_Vector_of_Line2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Line2f>), (c,o) => { var v = (Matrix<Line2f>)o; c.CodeMatrix_of_Line2f_(ref v); } },\r\n            { typeof(Matrix<Line2f>[]), (c,o) => { var v = (Matrix<Line2f>[])o; c.CodeMatrix_of_Line2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Line2f>>), (c,o) => { var v = (List<Matrix<Line2f>>)o; c.CodeList_of_Matrix_of_Line2f__(ref v); } },\r\n\r\n            { typeof(Volume<Line2f>), (c,o) => { var v = (Volume<Line2f>)o; c.CodeVolume_of_Line2f_(ref v); } },\r\n            { typeof(Volume<Line2f>[]), (c,o) => { var v = (Volume<Line2f>[])o; c.CodeVolume_of_Line2f_Array(ref v); } },\r\n            { typeof(List<Volume<Line2f>>), (c,o) => { var v = (List<Volume<Line2f>>)o; c.CodeList_of_Volume_of_Line2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Line2f>), (c,o) => { var v = (Tensor<Line2f>)o; c.CodeTensor_of_Line2f_(ref v); } },\r\n            { typeof(Tensor<Line2f>[]), (c,o) => { var v = (Tensor<Line2f>[])o; c.CodeTensor_of_Line2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Line2f>>), (c,o) => { var v = (List<Tensor<Line2f>>)o; c.CodeList_of_Tensor_of_Line2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Line3f\r\n\r\n            { typeof(Line3f), (c,o) => { var v = (Line3f)o; c.CodeLine3f(ref v); } },\r\n            { typeof(Line3f[]), (c,o) => { var v = (Line3f[])o; c.CodeLine3fArray(ref v); } },\r\n            { typeof(List<Line3f>), (c,o) => { var v = (List<Line3f>)o; c.CodeList_of_Line3f_(ref v); } },\r\n\r\n            { typeof(Vector<Line3f>), (c,o) => { var v = (Vector<Line3f>)o; c.CodeVector_of_Line3f_(ref v); } },\r\n            { typeof(Vector<Line3f>[]), (c,o) => { var v = (Vector<Line3f>[])o; c.CodeVector_of_Line3f_Array(ref v); } },\r\n            { typeof(List<Vector<Line3f>>), (c,o) => { var v = (List<Vector<Line3f>>)o; c.CodeList_of_Vector_of_Line3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Line3f>), (c,o) => { var v = (Matrix<Line3f>)o; c.CodeMatrix_of_Line3f_(ref v); } },\r\n            { typeof(Matrix<Line3f>[]), (c,o) => { var v = (Matrix<Line3f>[])o; c.CodeMatrix_of_Line3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Line3f>>), (c,o) => { var v = (List<Matrix<Line3f>>)o; c.CodeList_of_Matrix_of_Line3f__(ref v); } },\r\n\r\n            { typeof(Volume<Line3f>), (c,o) => { var v = (Volume<Line3f>)o; c.CodeVolume_of_Line3f_(ref v); } },\r\n            { typeof(Volume<Line3f>[]), (c,o) => { var v = (Volume<Line3f>[])o; c.CodeVolume_of_Line3f_Array(ref v); } },\r\n            { typeof(List<Volume<Line3f>>), (c,o) => { var v = (List<Volume<Line3f>>)o; c.CodeList_of_Volume_of_Line3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Line3f>), (c,o) => { var v = (Tensor<Line3f>)o; c.CodeTensor_of_Line3f_(ref v); } },\r\n            { typeof(Tensor<Line3f>[]), (c,o) => { var v = (Tensor<Line3f>[])o; c.CodeTensor_of_Line3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Line3f>>), (c,o) => { var v = (List<Tensor<Line3f>>)o; c.CodeList_of_Tensor_of_Line3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Plane2f\r\n\r\n            { typeof(Plane2f), (c,o) => { var v = (Plane2f)o; c.CodePlane2f(ref v); } },\r\n            { typeof(Plane2f[]), (c,o) => { var v = (Plane2f[])o; c.CodePlane2fArray(ref v); } },\r\n            { typeof(List<Plane2f>), (c,o) => { var v = (List<Plane2f>)o; c.CodeList_of_Plane2f_(ref v); } },\r\n\r\n            { typeof(Vector<Plane2f>), (c,o) => { var v = (Vector<Plane2f>)o; c.CodeVector_of_Plane2f_(ref v); } },\r\n            { typeof(Vector<Plane2f>[]), (c,o) => { var v = (Vector<Plane2f>[])o; c.CodeVector_of_Plane2f_Array(ref v); } },\r\n            { typeof(List<Vector<Plane2f>>), (c,o) => { var v = (List<Vector<Plane2f>>)o; c.CodeList_of_Vector_of_Plane2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Plane2f>), (c,o) => { var v = (Matrix<Plane2f>)o; c.CodeMatrix_of_Plane2f_(ref v); } },\r\n            { typeof(Matrix<Plane2f>[]), (c,o) => { var v = (Matrix<Plane2f>[])o; c.CodeMatrix_of_Plane2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Plane2f>>), (c,o) => { var v = (List<Matrix<Plane2f>>)o; c.CodeList_of_Matrix_of_Plane2f__(ref v); } },\r\n\r\n            { typeof(Volume<Plane2f>), (c,o) => { var v = (Volume<Plane2f>)o; c.CodeVolume_of_Plane2f_(ref v); } },\r\n            { typeof(Volume<Plane2f>[]), (c,o) => { var v = (Volume<Plane2f>[])o; c.CodeVolume_of_Plane2f_Array(ref v); } },\r\n            { typeof(List<Volume<Plane2f>>), (c,o) => { var v = (List<Volume<Plane2f>>)o; c.CodeList_of_Volume_of_Plane2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Plane2f>), (c,o) => { var v = (Tensor<Plane2f>)o; c.CodeTensor_of_Plane2f_(ref v); } },\r\n            { typeof(Tensor<Plane2f>[]), (c,o) => { var v = (Tensor<Plane2f>[])o; c.CodeTensor_of_Plane2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Plane2f>>), (c,o) => { var v = (List<Tensor<Plane2f>>)o; c.CodeList_of_Tensor_of_Plane2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Plane3f\r\n\r\n            { typeof(Plane3f), (c,o) => { var v = (Plane3f)o; c.CodePlane3f(ref v); } },\r\n            { typeof(Plane3f[]), (c,o) => { var v = (Plane3f[])o; c.CodePlane3fArray(ref v); } },\r\n            { typeof(List<Plane3f>), (c,o) => { var v = (List<Plane3f>)o; c.CodeList_of_Plane3f_(ref v); } },\r\n\r\n            { typeof(Vector<Plane3f>), (c,o) => { var v = (Vector<Plane3f>)o; c.CodeVector_of_Plane3f_(ref v); } },\r\n            { typeof(Vector<Plane3f>[]), (c,o) => { var v = (Vector<Plane3f>[])o; c.CodeVector_of_Plane3f_Array(ref v); } },\r\n            { typeof(List<Vector<Plane3f>>), (c,o) => { var v = (List<Vector<Plane3f>>)o; c.CodeList_of_Vector_of_Plane3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Plane3f>), (c,o) => { var v = (Matrix<Plane3f>)o; c.CodeMatrix_of_Plane3f_(ref v); } },\r\n            { typeof(Matrix<Plane3f>[]), (c,o) => { var v = (Matrix<Plane3f>[])o; c.CodeMatrix_of_Plane3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Plane3f>>), (c,o) => { var v = (List<Matrix<Plane3f>>)o; c.CodeList_of_Matrix_of_Plane3f__(ref v); } },\r\n\r\n            { typeof(Volume<Plane3f>), (c,o) => { var v = (Volume<Plane3f>)o; c.CodeVolume_of_Plane3f_(ref v); } },\r\n            { typeof(Volume<Plane3f>[]), (c,o) => { var v = (Volume<Plane3f>[])o; c.CodeVolume_of_Plane3f_Array(ref v); } },\r\n            { typeof(List<Volume<Plane3f>>), (c,o) => { var v = (List<Volume<Plane3f>>)o; c.CodeList_of_Volume_of_Plane3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Plane3f>), (c,o) => { var v = (Tensor<Plane3f>)o; c.CodeTensor_of_Plane3f_(ref v); } },\r\n            { typeof(Tensor<Plane3f>[]), (c,o) => { var v = (Tensor<Plane3f>[])o; c.CodeTensor_of_Plane3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Plane3f>>), (c,o) => { var v = (List<Tensor<Plane3f>>)o; c.CodeList_of_Tensor_of_Plane3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region PlaneWithPoint3f\r\n\r\n            { typeof(PlaneWithPoint3f), (c,o) => { var v = (PlaneWithPoint3f)o; c.CodePlaneWithPoint3f(ref v); } },\r\n            { typeof(PlaneWithPoint3f[]), (c,o) => { var v = (PlaneWithPoint3f[])o; c.CodePlaneWithPoint3fArray(ref v); } },\r\n            { typeof(List<PlaneWithPoint3f>), (c,o) => { var v = (List<PlaneWithPoint3f>)o; c.CodeList_of_PlaneWithPoint3f_(ref v); } },\r\n\r\n            { typeof(Vector<PlaneWithPoint3f>), (c,o) => { var v = (Vector<PlaneWithPoint3f>)o; c.CodeVector_of_PlaneWithPoint3f_(ref v); } },\r\n            { typeof(Vector<PlaneWithPoint3f>[]), (c,o) => { var v = (Vector<PlaneWithPoint3f>[])o; c.CodeVector_of_PlaneWithPoint3f_Array(ref v); } },\r\n            { typeof(List<Vector<PlaneWithPoint3f>>), (c,o) => { var v = (List<Vector<PlaneWithPoint3f>>)o; c.CodeList_of_Vector_of_PlaneWithPoint3f__(ref v); } },\r\n\r\n            { typeof(Matrix<PlaneWithPoint3f>), (c,o) => { var v = (Matrix<PlaneWithPoint3f>)o; c.CodeMatrix_of_PlaneWithPoint3f_(ref v); } },\r\n            { typeof(Matrix<PlaneWithPoint3f>[]), (c,o) => { var v = (Matrix<PlaneWithPoint3f>[])o; c.CodeMatrix_of_PlaneWithPoint3f_Array(ref v); } },\r\n            { typeof(List<Matrix<PlaneWithPoint3f>>), (c,o) => { var v = (List<Matrix<PlaneWithPoint3f>>)o; c.CodeList_of_Matrix_of_PlaneWithPoint3f__(ref v); } },\r\n\r\n            { typeof(Volume<PlaneWithPoint3f>), (c,o) => { var v = (Volume<PlaneWithPoint3f>)o; c.CodeVolume_of_PlaneWithPoint3f_(ref v); } },\r\n            { typeof(Volume<PlaneWithPoint3f>[]), (c,o) => { var v = (Volume<PlaneWithPoint3f>[])o; c.CodeVolume_of_PlaneWithPoint3f_Array(ref v); } },\r\n            { typeof(List<Volume<PlaneWithPoint3f>>), (c,o) => { var v = (List<Volume<PlaneWithPoint3f>>)o; c.CodeList_of_Volume_of_PlaneWithPoint3f__(ref v); } },\r\n\r\n            { typeof(Tensor<PlaneWithPoint3f>), (c,o) => { var v = (Tensor<PlaneWithPoint3f>)o; c.CodeTensor_of_PlaneWithPoint3f_(ref v); } },\r\n            { typeof(Tensor<PlaneWithPoint3f>[]), (c,o) => { var v = (Tensor<PlaneWithPoint3f>[])o; c.CodeTensor_of_PlaneWithPoint3f_Array(ref v); } },\r\n            { typeof(List<Tensor<PlaneWithPoint3f>>), (c,o) => { var v = (List<Tensor<PlaneWithPoint3f>>)o; c.CodeList_of_Tensor_of_PlaneWithPoint3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Quad2f\r\n\r\n            { typeof(Quad2f), (c,o) => { var v = (Quad2f)o; c.CodeQuad2f(ref v); } },\r\n            { typeof(Quad2f[]), (c,o) => { var v = (Quad2f[])o; c.CodeQuad2fArray(ref v); } },\r\n            { typeof(List<Quad2f>), (c,o) => { var v = (List<Quad2f>)o; c.CodeList_of_Quad2f_(ref v); } },\r\n\r\n            { typeof(Vector<Quad2f>), (c,o) => { var v = (Vector<Quad2f>)o; c.CodeVector_of_Quad2f_(ref v); } },\r\n            { typeof(Vector<Quad2f>[]), (c,o) => { var v = (Vector<Quad2f>[])o; c.CodeVector_of_Quad2f_Array(ref v); } },\r\n            { typeof(List<Vector<Quad2f>>), (c,o) => { var v = (List<Vector<Quad2f>>)o; c.CodeList_of_Vector_of_Quad2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Quad2f>), (c,o) => { var v = (Matrix<Quad2f>)o; c.CodeMatrix_of_Quad2f_(ref v); } },\r\n            { typeof(Matrix<Quad2f>[]), (c,o) => { var v = (Matrix<Quad2f>[])o; c.CodeMatrix_of_Quad2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Quad2f>>), (c,o) => { var v = (List<Matrix<Quad2f>>)o; c.CodeList_of_Matrix_of_Quad2f__(ref v); } },\r\n\r\n            { typeof(Volume<Quad2f>), (c,o) => { var v = (Volume<Quad2f>)o; c.CodeVolume_of_Quad2f_(ref v); } },\r\n            { typeof(Volume<Quad2f>[]), (c,o) => { var v = (Volume<Quad2f>[])o; c.CodeVolume_of_Quad2f_Array(ref v); } },\r\n            { typeof(List<Volume<Quad2f>>), (c,o) => { var v = (List<Volume<Quad2f>>)o; c.CodeList_of_Volume_of_Quad2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Quad2f>), (c,o) => { var v = (Tensor<Quad2f>)o; c.CodeTensor_of_Quad2f_(ref v); } },\r\n            { typeof(Tensor<Quad2f>[]), (c,o) => { var v = (Tensor<Quad2f>[])o; c.CodeTensor_of_Quad2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Quad2f>>), (c,o) => { var v = (List<Tensor<Quad2f>>)o; c.CodeList_of_Tensor_of_Quad2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Quad3f\r\n\r\n            { typeof(Quad3f), (c,o) => { var v = (Quad3f)o; c.CodeQuad3f(ref v); } },\r\n            { typeof(Quad3f[]), (c,o) => { var v = (Quad3f[])o; c.CodeQuad3fArray(ref v); } },\r\n            { typeof(List<Quad3f>), (c,o) => { var v = (List<Quad3f>)o; c.CodeList_of_Quad3f_(ref v); } },\r\n\r\n            { typeof(Vector<Quad3f>), (c,o) => { var v = (Vector<Quad3f>)o; c.CodeVector_of_Quad3f_(ref v); } },\r\n            { typeof(Vector<Quad3f>[]), (c,o) => { var v = (Vector<Quad3f>[])o; c.CodeVector_of_Quad3f_Array(ref v); } },\r\n            { typeof(List<Vector<Quad3f>>), (c,o) => { var v = (List<Vector<Quad3f>>)o; c.CodeList_of_Vector_of_Quad3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Quad3f>), (c,o) => { var v = (Matrix<Quad3f>)o; c.CodeMatrix_of_Quad3f_(ref v); } },\r\n            { typeof(Matrix<Quad3f>[]), (c,o) => { var v = (Matrix<Quad3f>[])o; c.CodeMatrix_of_Quad3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Quad3f>>), (c,o) => { var v = (List<Matrix<Quad3f>>)o; c.CodeList_of_Matrix_of_Quad3f__(ref v); } },\r\n\r\n            { typeof(Volume<Quad3f>), (c,o) => { var v = (Volume<Quad3f>)o; c.CodeVolume_of_Quad3f_(ref v); } },\r\n            { typeof(Volume<Quad3f>[]), (c,o) => { var v = (Volume<Quad3f>[])o; c.CodeVolume_of_Quad3f_Array(ref v); } },\r\n            { typeof(List<Volume<Quad3f>>), (c,o) => { var v = (List<Volume<Quad3f>>)o; c.CodeList_of_Volume_of_Quad3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Quad3f>), (c,o) => { var v = (Tensor<Quad3f>)o; c.CodeTensor_of_Quad3f_(ref v); } },\r\n            { typeof(Tensor<Quad3f>[]), (c,o) => { var v = (Tensor<Quad3f>[])o; c.CodeTensor_of_Quad3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Quad3f>>), (c,o) => { var v = (List<Tensor<Quad3f>>)o; c.CodeList_of_Tensor_of_Quad3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Ray2f\r\n\r\n            { typeof(Ray2f), (c,o) => { var v = (Ray2f)o; c.CodeRay2f(ref v); } },\r\n            { typeof(Ray2f[]), (c,o) => { var v = (Ray2f[])o; c.CodeRay2fArray(ref v); } },\r\n            { typeof(List<Ray2f>), (c,o) => { var v = (List<Ray2f>)o; c.CodeList_of_Ray2f_(ref v); } },\r\n\r\n            { typeof(Vector<Ray2f>), (c,o) => { var v = (Vector<Ray2f>)o; c.CodeVector_of_Ray2f_(ref v); } },\r\n            { typeof(Vector<Ray2f>[]), (c,o) => { var v = (Vector<Ray2f>[])o; c.CodeVector_of_Ray2f_Array(ref v); } },\r\n            { typeof(List<Vector<Ray2f>>), (c,o) => { var v = (List<Vector<Ray2f>>)o; c.CodeList_of_Vector_of_Ray2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Ray2f>), (c,o) => { var v = (Matrix<Ray2f>)o; c.CodeMatrix_of_Ray2f_(ref v); } },\r\n            { typeof(Matrix<Ray2f>[]), (c,o) => { var v = (Matrix<Ray2f>[])o; c.CodeMatrix_of_Ray2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Ray2f>>), (c,o) => { var v = (List<Matrix<Ray2f>>)o; c.CodeList_of_Matrix_of_Ray2f__(ref v); } },\r\n\r\n            { typeof(Volume<Ray2f>), (c,o) => { var v = (Volume<Ray2f>)o; c.CodeVolume_of_Ray2f_(ref v); } },\r\n            { typeof(Volume<Ray2f>[]), (c,o) => { var v = (Volume<Ray2f>[])o; c.CodeVolume_of_Ray2f_Array(ref v); } },\r\n            { typeof(List<Volume<Ray2f>>), (c,o) => { var v = (List<Volume<Ray2f>>)o; c.CodeList_of_Volume_of_Ray2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Ray2f>), (c,o) => { var v = (Tensor<Ray2f>)o; c.CodeTensor_of_Ray2f_(ref v); } },\r\n            { typeof(Tensor<Ray2f>[]), (c,o) => { var v = (Tensor<Ray2f>[])o; c.CodeTensor_of_Ray2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Ray2f>>), (c,o) => { var v = (List<Tensor<Ray2f>>)o; c.CodeList_of_Tensor_of_Ray2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Ray3f\r\n\r\n            { typeof(Ray3f), (c,o) => { var v = (Ray3f)o; c.CodeRay3f(ref v); } },\r\n            { typeof(Ray3f[]), (c,o) => { var v = (Ray3f[])o; c.CodeRay3fArray(ref v); } },\r\n            { typeof(List<Ray3f>), (c,o) => { var v = (List<Ray3f>)o; c.CodeList_of_Ray3f_(ref v); } },\r\n\r\n            { typeof(Vector<Ray3f>), (c,o) => { var v = (Vector<Ray3f>)o; c.CodeVector_of_Ray3f_(ref v); } },\r\n            { typeof(Vector<Ray3f>[]), (c,o) => { var v = (Vector<Ray3f>[])o; c.CodeVector_of_Ray3f_Array(ref v); } },\r\n            { typeof(List<Vector<Ray3f>>), (c,o) => { var v = (List<Vector<Ray3f>>)o; c.CodeList_of_Vector_of_Ray3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Ray3f>), (c,o) => { var v = (Matrix<Ray3f>)o; c.CodeMatrix_of_Ray3f_(ref v); } },\r\n            { typeof(Matrix<Ray3f>[]), (c,o) => { var v = (Matrix<Ray3f>[])o; c.CodeMatrix_of_Ray3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Ray3f>>), (c,o) => { var v = (List<Matrix<Ray3f>>)o; c.CodeList_of_Matrix_of_Ray3f__(ref v); } },\r\n\r\n            { typeof(Volume<Ray3f>), (c,o) => { var v = (Volume<Ray3f>)o; c.CodeVolume_of_Ray3f_(ref v); } },\r\n            { typeof(Volume<Ray3f>[]), (c,o) => { var v = (Volume<Ray3f>[])o; c.CodeVolume_of_Ray3f_Array(ref v); } },\r\n            { typeof(List<Volume<Ray3f>>), (c,o) => { var v = (List<Volume<Ray3f>>)o; c.CodeList_of_Volume_of_Ray3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Ray3f>), (c,o) => { var v = (Tensor<Ray3f>)o; c.CodeTensor_of_Ray3f_(ref v); } },\r\n            { typeof(Tensor<Ray3f>[]), (c,o) => { var v = (Tensor<Ray3f>[])o; c.CodeTensor_of_Ray3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Ray3f>>), (c,o) => { var v = (List<Tensor<Ray3f>>)o; c.CodeList_of_Tensor_of_Ray3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Sphere3f\r\n\r\n            { typeof(Sphere3f), (c,o) => { var v = (Sphere3f)o; c.CodeSphere3f(ref v); } },\r\n            { typeof(Sphere3f[]), (c,o) => { var v = (Sphere3f[])o; c.CodeSphere3fArray(ref v); } },\r\n            { typeof(List<Sphere3f>), (c,o) => { var v = (List<Sphere3f>)o; c.CodeList_of_Sphere3f_(ref v); } },\r\n\r\n            { typeof(Vector<Sphere3f>), (c,o) => { var v = (Vector<Sphere3f>)o; c.CodeVector_of_Sphere3f_(ref v); } },\r\n            { typeof(Vector<Sphere3f>[]), (c,o) => { var v = (Vector<Sphere3f>[])o; c.CodeVector_of_Sphere3f_Array(ref v); } },\r\n            { typeof(List<Vector<Sphere3f>>), (c,o) => { var v = (List<Vector<Sphere3f>>)o; c.CodeList_of_Vector_of_Sphere3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Sphere3f>), (c,o) => { var v = (Matrix<Sphere3f>)o; c.CodeMatrix_of_Sphere3f_(ref v); } },\r\n            { typeof(Matrix<Sphere3f>[]), (c,o) => { var v = (Matrix<Sphere3f>[])o; c.CodeMatrix_of_Sphere3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Sphere3f>>), (c,o) => { var v = (List<Matrix<Sphere3f>>)o; c.CodeList_of_Matrix_of_Sphere3f__(ref v); } },\r\n\r\n            { typeof(Volume<Sphere3f>), (c,o) => { var v = (Volume<Sphere3f>)o; c.CodeVolume_of_Sphere3f_(ref v); } },\r\n            { typeof(Volume<Sphere3f>[]), (c,o) => { var v = (Volume<Sphere3f>[])o; c.CodeVolume_of_Sphere3f_Array(ref v); } },\r\n            { typeof(List<Volume<Sphere3f>>), (c,o) => { var v = (List<Volume<Sphere3f>>)o; c.CodeList_of_Volume_of_Sphere3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Sphere3f>), (c,o) => { var v = (Tensor<Sphere3f>)o; c.CodeTensor_of_Sphere3f_(ref v); } },\r\n            { typeof(Tensor<Sphere3f>[]), (c,o) => { var v = (Tensor<Sphere3f>[])o; c.CodeTensor_of_Sphere3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Sphere3f>>), (c,o) => { var v = (List<Tensor<Sphere3f>>)o; c.CodeList_of_Tensor_of_Sphere3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Triangle2f\r\n\r\n            { typeof(Triangle2f), (c,o) => { var v = (Triangle2f)o; c.CodeTriangle2f(ref v); } },\r\n            { typeof(Triangle2f[]), (c,o) => { var v = (Triangle2f[])o; c.CodeTriangle2fArray(ref v); } },\r\n            { typeof(List<Triangle2f>), (c,o) => { var v = (List<Triangle2f>)o; c.CodeList_of_Triangle2f_(ref v); } },\r\n\r\n            { typeof(Vector<Triangle2f>), (c,o) => { var v = (Vector<Triangle2f>)o; c.CodeVector_of_Triangle2f_(ref v); } },\r\n            { typeof(Vector<Triangle2f>[]), (c,o) => { var v = (Vector<Triangle2f>[])o; c.CodeVector_of_Triangle2f_Array(ref v); } },\r\n            { typeof(List<Vector<Triangle2f>>), (c,o) => { var v = (List<Vector<Triangle2f>>)o; c.CodeList_of_Vector_of_Triangle2f__(ref v); } },\r\n\r\n            { typeof(Matrix<Triangle2f>), (c,o) => { var v = (Matrix<Triangle2f>)o; c.CodeMatrix_of_Triangle2f_(ref v); } },\r\n            { typeof(Matrix<Triangle2f>[]), (c,o) => { var v = (Matrix<Triangle2f>[])o; c.CodeMatrix_of_Triangle2f_Array(ref v); } },\r\n            { typeof(List<Matrix<Triangle2f>>), (c,o) => { var v = (List<Matrix<Triangle2f>>)o; c.CodeList_of_Matrix_of_Triangle2f__(ref v); } },\r\n\r\n            { typeof(Volume<Triangle2f>), (c,o) => { var v = (Volume<Triangle2f>)o; c.CodeVolume_of_Triangle2f_(ref v); } },\r\n            { typeof(Volume<Triangle2f>[]), (c,o) => { var v = (Volume<Triangle2f>[])o; c.CodeVolume_of_Triangle2f_Array(ref v); } },\r\n            { typeof(List<Volume<Triangle2f>>), (c,o) => { var v = (List<Volume<Triangle2f>>)o; c.CodeList_of_Volume_of_Triangle2f__(ref v); } },\r\n\r\n            { typeof(Tensor<Triangle2f>), (c,o) => { var v = (Tensor<Triangle2f>)o; c.CodeTensor_of_Triangle2f_(ref v); } },\r\n            { typeof(Tensor<Triangle2f>[]), (c,o) => { var v = (Tensor<Triangle2f>[])o; c.CodeTensor_of_Triangle2f_Array(ref v); } },\r\n            { typeof(List<Tensor<Triangle2f>>), (c,o) => { var v = (List<Tensor<Triangle2f>>)o; c.CodeList_of_Tensor_of_Triangle2f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Triangle3f\r\n\r\n            { typeof(Triangle3f), (c,o) => { var v = (Triangle3f)o; c.CodeTriangle3f(ref v); } },\r\n            { typeof(Triangle3f[]), (c,o) => { var v = (Triangle3f[])o; c.CodeTriangle3fArray(ref v); } },\r\n            { typeof(List<Triangle3f>), (c,o) => { var v = (List<Triangle3f>)o; c.CodeList_of_Triangle3f_(ref v); } },\r\n\r\n            { typeof(Vector<Triangle3f>), (c,o) => { var v = (Vector<Triangle3f>)o; c.CodeVector_of_Triangle3f_(ref v); } },\r\n            { typeof(Vector<Triangle3f>[]), (c,o) => { var v = (Vector<Triangle3f>[])o; c.CodeVector_of_Triangle3f_Array(ref v); } },\r\n            { typeof(List<Vector<Triangle3f>>), (c,o) => { var v = (List<Vector<Triangle3f>>)o; c.CodeList_of_Vector_of_Triangle3f__(ref v); } },\r\n\r\n            { typeof(Matrix<Triangle3f>), (c,o) => { var v = (Matrix<Triangle3f>)o; c.CodeMatrix_of_Triangle3f_(ref v); } },\r\n            { typeof(Matrix<Triangle3f>[]), (c,o) => { var v = (Matrix<Triangle3f>[])o; c.CodeMatrix_of_Triangle3f_Array(ref v); } },\r\n            { typeof(List<Matrix<Triangle3f>>), (c,o) => { var v = (List<Matrix<Triangle3f>>)o; c.CodeList_of_Matrix_of_Triangle3f__(ref v); } },\r\n\r\n            { typeof(Volume<Triangle3f>), (c,o) => { var v = (Volume<Triangle3f>)o; c.CodeVolume_of_Triangle3f_(ref v); } },\r\n            { typeof(Volume<Triangle3f>[]), (c,o) => { var v = (Volume<Triangle3f>[])o; c.CodeVolume_of_Triangle3f_Array(ref v); } },\r\n            { typeof(List<Volume<Triangle3f>>), (c,o) => { var v = (List<Volume<Triangle3f>>)o; c.CodeList_of_Volume_of_Triangle3f__(ref v); } },\r\n\r\n            { typeof(Tensor<Triangle3f>), (c,o) => { var v = (Tensor<Triangle3f>)o; c.CodeTensor_of_Triangle3f_(ref v); } },\r\n            { typeof(Tensor<Triangle3f>[]), (c,o) => { var v = (Tensor<Triangle3f>[])o; c.CodeTensor_of_Triangle3f_Array(ref v); } },\r\n            { typeof(List<Tensor<Triangle3f>>), (c,o) => { var v = (List<Tensor<Triangle3f>>)o; c.CodeList_of_Tensor_of_Triangle3f__(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Multi-Dimensional Arrays\r\n\r\n            { typeof(byte[,]), (c,o) => { var v = (byte[,])o; c.CodeByteArray2d(ref v); } },\r\n            { typeof(byte[, ,]), (c,o) => { var v = (byte[, ,])o; c.CodeByteArray3d(ref v); } },\r\n            { typeof(sbyte[,]), (c,o) => { var v = (sbyte[,])o; c.CodeSByteArray2d(ref v); } },\r\n            { typeof(sbyte[, ,]), (c,o) => { var v = (sbyte[, ,])o; c.CodeSByteArray3d(ref v); } },\r\n            { typeof(short[,]), (c,o) => { var v = (short[,])o; c.CodeShortArray2d(ref v); } },\r\n            { typeof(short[, ,]), (c,o) => { var v = (short[, ,])o; c.CodeShortArray3d(ref v); } },\r\n            { typeof(ushort[,]), (c,o) => { var v = (ushort[,])o; c.CodeUShortArray2d(ref v); } },\r\n            { typeof(ushort[, ,]), (c,o) => { var v = (ushort[, ,])o; c.CodeUShortArray3d(ref v); } },\r\n            { typeof(int[,]), (c,o) => { var v = (int[,])o; c.CodeIntArray2d(ref v); } },\r\n            { typeof(int[, ,]), (c,o) => { var v = (int[, ,])o; c.CodeIntArray3d(ref v); } },\r\n            { typeof(uint[,]), (c,o) => { var v = (uint[,])o; c.CodeUIntArray2d(ref v); } },\r\n            { typeof(uint[, ,]), (c,o) => { var v = (uint[, ,])o; c.CodeUIntArray3d(ref v); } },\r\n            { typeof(long[,]), (c,o) => { var v = (long[,])o; c.CodeLongArray2d(ref v); } },\r\n            { typeof(long[, ,]), (c,o) => { var v = (long[, ,])o; c.CodeLongArray3d(ref v); } },\r\n            { typeof(ulong[,]), (c,o) => { var v = (ulong[,])o; c.CodeULongArray2d(ref v); } },\r\n            { typeof(ulong[, ,]), (c,o) => { var v = (ulong[, ,])o; c.CodeULongArray3d(ref v); } },\r\n            { typeof(float[,]), (c,o) => { var v = (float[,])o; c.CodeFloatArray2d(ref v); } },\r\n            { typeof(float[, ,]), (c,o) => { var v = (float[, ,])o; c.CodeFloatArray3d(ref v); } },\r\n            { typeof(double[,]), (c,o) => { var v = (double[,])o; c.CodeDoubleArray2d(ref v); } },\r\n            { typeof(double[, ,]), (c,o) => { var v = (double[, ,])o; c.CodeDoubleArray3d(ref v); } },\r\n            { typeof(Fraction[,]), (c,o) => { var v = (Fraction[,])o; c.CodeFractionArray2d(ref v); } },\r\n            { typeof(Fraction[, ,]), (c,o) => { var v = (Fraction[, ,])o; c.CodeFractionArray3d(ref v); } },\r\n            { typeof(V2i[,]), (c,o) => { var v = (V2i[,])o; c.CodeV2iArray2d(ref v); } },\r\n            { typeof(V2i[, ,]), (c,o) => { var v = (V2i[, ,])o; c.CodeV2iArray3d(ref v); } },\r\n            { typeof(V2l[,]), (c,o) => { var v = (V2l[,])o; c.CodeV2lArray2d(ref v); } },\r\n            { typeof(V2l[, ,]), (c,o) => { var v = (V2l[, ,])o; c.CodeV2lArray3d(ref v); } },\r\n            { typeof(V2f[,]), (c,o) => { var v = (V2f[,])o; c.CodeV2fArray2d(ref v); } },\r\n            { typeof(V2f[, ,]), (c,o) => { var v = (V2f[, ,])o; c.CodeV2fArray3d(ref v); } },\r\n            { typeof(V2d[,]), (c,o) => { var v = (V2d[,])o; c.CodeV2dArray2d(ref v); } },\r\n            { typeof(V2d[, ,]), (c,o) => { var v = (V2d[, ,])o; c.CodeV2dArray3d(ref v); } },\r\n            { typeof(V3i[,]), (c,o) => { var v = (V3i[,])o; c.CodeV3iArray2d(ref v); } },\r\n            { typeof(V3i[, ,]), (c,o) => { var v = (V3i[, ,])o; c.CodeV3iArray3d(ref v); } },\r\n            { typeof(V3l[,]), (c,o) => { var v = (V3l[,])o; c.CodeV3lArray2d(ref v); } },\r\n            { typeof(V3l[, ,]), (c,o) => { var v = (V3l[, ,])o; c.CodeV3lArray3d(ref v); } },\r\n            { typeof(V3f[,]), (c,o) => { var v = (V3f[,])o; c.CodeV3fArray2d(ref v); } },\r\n            { typeof(V3f[, ,]), (c,o) => { var v = (V3f[, ,])o; c.CodeV3fArray3d(ref v); } },\r\n            { typeof(V3d[,]), (c,o) => { var v = (V3d[,])o; c.CodeV3dArray2d(ref v); } },\r\n            { typeof(V3d[, ,]), (c,o) => { var v = (V3d[, ,])o; c.CodeV3dArray3d(ref v); } },\r\n            { typeof(V4i[,]), (c,o) => { var v = (V4i[,])o; c.CodeV4iArray2d(ref v); } },\r\n            { typeof(V4i[, ,]), (c,o) => { var v = (V4i[, ,])o; c.CodeV4iArray3d(ref v); } },\r\n            { typeof(V4l[,]), (c,o) => { var v = (V4l[,])o; c.CodeV4lArray2d(ref v); } },\r\n            { typeof(V4l[, ,]), (c,o) => { var v = (V4l[, ,])o; c.CodeV4lArray3d(ref v); } },\r\n            { typeof(V4f[,]), (c,o) => { var v = (V4f[,])o; c.CodeV4fArray2d(ref v); } },\r\n            { typeof(V4f[, ,]), (c,o) => { var v = (V4f[, ,])o; c.CodeV4fArray3d(ref v); } },\r\n            { typeof(V4d[,]), (c,o) => { var v = (V4d[,])o; c.CodeV4dArray2d(ref v); } },\r\n            { typeof(V4d[, ,]), (c,o) => { var v = (V4d[, ,])o; c.CodeV4dArray3d(ref v); } },\r\n            { typeof(M22i[,]), (c,o) => { var v = (M22i[,])o; c.CodeM22iArray2d(ref v); } },\r\n            { typeof(M22i[, ,]), (c,o) => { var v = (M22i[, ,])o; c.CodeM22iArray3d(ref v); } },\r\n            { typeof(M22l[,]), (c,o) => { var v = (M22l[,])o; c.CodeM22lArray2d(ref v); } },\r\n            { typeof(M22l[, ,]), (c,o) => { var v = (M22l[, ,])o; c.CodeM22lArray3d(ref v); } },\r\n            { typeof(M22f[,]), (c,o) => { var v = (M22f[,])o; c.CodeM22fArray2d(ref v); } },\r\n            { typeof(M22f[, ,]), (c,o) => { var v = (M22f[, ,])o; c.CodeM22fArray3d(ref v); } },\r\n            { typeof(M22d[,]), (c,o) => { var v = (M22d[,])o; c.CodeM22dArray2d(ref v); } },\r\n            { typeof(M22d[, ,]), (c,o) => { var v = (M22d[, ,])o; c.CodeM22dArray3d(ref v); } },\r\n            { typeof(M23i[,]), (c,o) => { var v = (M23i[,])o; c.CodeM23iArray2d(ref v); } },\r\n            { typeof(M23i[, ,]), (c,o) => { var v = (M23i[, ,])o; c.CodeM23iArray3d(ref v); } },\r\n            { typeof(M23l[,]), (c,o) => { var v = (M23l[,])o; c.CodeM23lArray2d(ref v); } },\r\n            { typeof(M23l[, ,]), (c,o) => { var v = (M23l[, ,])o; c.CodeM23lArray3d(ref v); } },\r\n            { typeof(M23f[,]), (c,o) => { var v = (M23f[,])o; c.CodeM23fArray2d(ref v); } },\r\n            { typeof(M23f[, ,]), (c,o) => { var v = (M23f[, ,])o; c.CodeM23fArray3d(ref v); } },\r\n            { typeof(M23d[,]), (c,o) => { var v = (M23d[,])o; c.CodeM23dArray2d(ref v); } },\r\n            { typeof(M23d[, ,]), (c,o) => { var v = (M23d[, ,])o; c.CodeM23dArray3d(ref v); } },\r\n            { typeof(M33i[,]), (c,o) => { var v = (M33i[,])o; c.CodeM33iArray2d(ref v); } },\r\n            { typeof(M33i[, ,]), (c,o) => { var v = (M33i[, ,])o; c.CodeM33iArray3d(ref v); } },\r\n            { typeof(M33l[,]), (c,o) => { var v = (M33l[,])o; c.CodeM33lArray2d(ref v); } },\r\n            { typeof(M33l[, ,]), (c,o) => { var v = (M33l[, ,])o; c.CodeM33lArray3d(ref v); } },\r\n            { typeof(M33f[,]), (c,o) => { var v = (M33f[,])o; c.CodeM33fArray2d(ref v); } },\r\n            { typeof(M33f[, ,]), (c,o) => { var v = (M33f[, ,])o; c.CodeM33fArray3d(ref v); } },\r\n            { typeof(M33d[,]), (c,o) => { var v = (M33d[,])o; c.CodeM33dArray2d(ref v); } },\r\n            { typeof(M33d[, ,]), (c,o) => { var v = (M33d[, ,])o; c.CodeM33dArray3d(ref v); } },\r\n            { typeof(M34i[,]), (c,o) => { var v = (M34i[,])o; c.CodeM34iArray2d(ref v); } },\r\n            { typeof(M34i[, ,]), (c,o) => { var v = (M34i[, ,])o; c.CodeM34iArray3d(ref v); } },\r\n            { typeof(M34l[,]), (c,o) => { var v = (M34l[,])o; c.CodeM34lArray2d(ref v); } },\r\n            { typeof(M34l[, ,]), (c,o) => { var v = (M34l[, ,])o; c.CodeM34lArray3d(ref v); } },\r\n            { typeof(M34f[,]), (c,o) => { var v = (M34f[,])o; c.CodeM34fArray2d(ref v); } },\r\n            { typeof(M34f[, ,]), (c,o) => { var v = (M34f[, ,])o; c.CodeM34fArray3d(ref v); } },\r\n            { typeof(M34d[,]), (c,o) => { var v = (M34d[,])o; c.CodeM34dArray2d(ref v); } },\r\n            { typeof(M34d[, ,]), (c,o) => { var v = (M34d[, ,])o; c.CodeM34dArray3d(ref v); } },\r\n            { typeof(M44i[,]), (c,o) => { var v = (M44i[,])o; c.CodeM44iArray2d(ref v); } },\r\n            { typeof(M44i[, ,]), (c,o) => { var v = (M44i[, ,])o; c.CodeM44iArray3d(ref v); } },\r\n            { typeof(M44l[,]), (c,o) => { var v = (M44l[,])o; c.CodeM44lArray2d(ref v); } },\r\n            { typeof(M44l[, ,]), (c,o) => { var v = (M44l[, ,])o; c.CodeM44lArray3d(ref v); } },\r\n            { typeof(M44f[,]), (c,o) => { var v = (M44f[,])o; c.CodeM44fArray2d(ref v); } },\r\n            { typeof(M44f[, ,]), (c,o) => { var v = (M44f[, ,])o; c.CodeM44fArray3d(ref v); } },\r\n            { typeof(M44d[,]), (c,o) => { var v = (M44d[,])o; c.CodeM44dArray2d(ref v); } },\r\n            { typeof(M44d[, ,]), (c,o) => { var v = (M44d[, ,])o; c.CodeM44dArray3d(ref v); } },\r\n            { typeof(C3b[,]), (c,o) => { var v = (C3b[,])o; c.CodeC3bArray2d(ref v); } },\r\n            { typeof(C3b[, ,]), (c,o) => { var v = (C3b[, ,])o; c.CodeC3bArray3d(ref v); } },\r\n            { typeof(C3us[,]), (c,o) => { var v = (C3us[,])o; c.CodeC3usArray2d(ref v); } },\r\n            { typeof(C3us[, ,]), (c,o) => { var v = (C3us[, ,])o; c.CodeC3usArray3d(ref v); } },\r\n            { typeof(C3ui[,]), (c,o) => { var v = (C3ui[,])o; c.CodeC3uiArray2d(ref v); } },\r\n            { typeof(C3ui[, ,]), (c,o) => { var v = (C3ui[, ,])o; c.CodeC3uiArray3d(ref v); } },\r\n            { typeof(C3f[,]), (c,o) => { var v = (C3f[,])o; c.CodeC3fArray2d(ref v); } },\r\n            { typeof(C3f[, ,]), (c,o) => { var v = (C3f[, ,])o; c.CodeC3fArray3d(ref v); } },\r\n            { typeof(C3d[,]), (c,o) => { var v = (C3d[,])o; c.CodeC3dArray2d(ref v); } },\r\n            { typeof(C3d[, ,]), (c,o) => { var v = (C3d[, ,])o; c.CodeC3dArray3d(ref v); } },\r\n            { typeof(C4b[,]), (c,o) => { var v = (C4b[,])o; c.CodeC4bArray2d(ref v); } },\r\n            { typeof(C4b[, ,]), (c,o) => { var v = (C4b[, ,])o; c.CodeC4bArray3d(ref v); } },\r\n            { typeof(C4us[,]), (c,o) => { var v = (C4us[,])o; c.CodeC4usArray2d(ref v); } },\r\n            { typeof(C4us[, ,]), (c,o) => { var v = (C4us[, ,])o; c.CodeC4usArray3d(ref v); } },\r\n            { typeof(C4ui[,]), (c,o) => { var v = (C4ui[,])o; c.CodeC4uiArray2d(ref v); } },\r\n            { typeof(C4ui[, ,]), (c,o) => { var v = (C4ui[, ,])o; c.CodeC4uiArray3d(ref v); } },\r\n            { typeof(C4f[,]), (c,o) => { var v = (C4f[,])o; c.CodeC4fArray2d(ref v); } },\r\n            { typeof(C4f[, ,]), (c,o) => { var v = (C4f[, ,])o; c.CodeC4fArray3d(ref v); } },\r\n            { typeof(C4d[,]), (c,o) => { var v = (C4d[,])o; c.CodeC4dArray2d(ref v); } },\r\n            { typeof(C4d[, ,]), (c,o) => { var v = (C4d[, ,])o; c.CodeC4dArray3d(ref v); } },\r\n            { typeof(Range1b[,]), (c,o) => { var v = (Range1b[,])o; c.CodeRange1bArray2d(ref v); } },\r\n            { typeof(Range1b[, ,]), (c,o) => { var v = (Range1b[, ,])o; c.CodeRange1bArray3d(ref v); } },\r\n            { typeof(Range1sb[,]), (c,o) => { var v = (Range1sb[,])o; c.CodeRange1sbArray2d(ref v); } },\r\n            { typeof(Range1sb[, ,]), (c,o) => { var v = (Range1sb[, ,])o; c.CodeRange1sbArray3d(ref v); } },\r\n            { typeof(Range1s[,]), (c,o) => { var v = (Range1s[,])o; c.CodeRange1sArray2d(ref v); } },\r\n            { typeof(Range1s[, ,]), (c,o) => { var v = (Range1s[, ,])o; c.CodeRange1sArray3d(ref v); } },\r\n            { typeof(Range1us[,]), (c,o) => { var v = (Range1us[,])o; c.CodeRange1usArray2d(ref v); } },\r\n            { typeof(Range1us[, ,]), (c,o) => { var v = (Range1us[, ,])o; c.CodeRange1usArray3d(ref v); } },\r\n            { typeof(Range1i[,]), (c,o) => { var v = (Range1i[,])o; c.CodeRange1iArray2d(ref v); } },\r\n            { typeof(Range1i[, ,]), (c,o) => { var v = (Range1i[, ,])o; c.CodeRange1iArray3d(ref v); } },\r\n            { typeof(Range1ui[,]), (c,o) => { var v = (Range1ui[,])o; c.CodeRange1uiArray2d(ref v); } },\r\n            { typeof(Range1ui[, ,]), (c,o) => { var v = (Range1ui[, ,])o; c.CodeRange1uiArray3d(ref v); } },\r\n            { typeof(Range1l[,]), (c,o) => { var v = (Range1l[,])o; c.CodeRange1lArray2d(ref v); } },\r\n            { typeof(Range1l[, ,]), (c,o) => { var v = (Range1l[, ,])o; c.CodeRange1lArray3d(ref v); } },\r\n            { typeof(Range1ul[,]), (c,o) => { var v = (Range1ul[,])o; c.CodeRange1ulArray2d(ref v); } },\r\n            { typeof(Range1ul[, ,]), (c,o) => { var v = (Range1ul[, ,])o; c.CodeRange1ulArray3d(ref v); } },\r\n            { typeof(Range1f[,]), (c,o) => { var v = (Range1f[,])o; c.CodeRange1fArray2d(ref v); } },\r\n            { typeof(Range1f[, ,]), (c,o) => { var v = (Range1f[, ,])o; c.CodeRange1fArray3d(ref v); } },\r\n            { typeof(Range1d[,]), (c,o) => { var v = (Range1d[,])o; c.CodeRange1dArray2d(ref v); } },\r\n            { typeof(Range1d[, ,]), (c,o) => { var v = (Range1d[, ,])o; c.CodeRange1dArray3d(ref v); } },\r\n            { typeof(Box2i[,]), (c,o) => { var v = (Box2i[,])o; c.CodeBox2iArray2d(ref v); } },\r\n            { typeof(Box2i[, ,]), (c,o) => { var v = (Box2i[, ,])o; c.CodeBox2iArray3d(ref v); } },\r\n            { typeof(Box2l[,]), (c,o) => { var v = (Box2l[,])o; c.CodeBox2lArray2d(ref v); } },\r\n            { typeof(Box2l[, ,]), (c,o) => { var v = (Box2l[, ,])o; c.CodeBox2lArray3d(ref v); } },\r\n            { typeof(Box2f[,]), (c,o) => { var v = (Box2f[,])o; c.CodeBox2fArray2d(ref v); } },\r\n            { typeof(Box2f[, ,]), (c,o) => { var v = (Box2f[, ,])o; c.CodeBox2fArray3d(ref v); } },\r\n            { typeof(Box2d[,]), (c,o) => { var v = (Box2d[,])o; c.CodeBox2dArray2d(ref v); } },\r\n            { typeof(Box2d[, ,]), (c,o) => { var v = (Box2d[, ,])o; c.CodeBox2dArray3d(ref v); } },\r\n            { typeof(Box3i[,]), (c,o) => { var v = (Box3i[,])o; c.CodeBox3iArray2d(ref v); } },\r\n            { typeof(Box3i[, ,]), (c,o) => { var v = (Box3i[, ,])o; c.CodeBox3iArray3d(ref v); } },\r\n            { typeof(Box3l[,]), (c,o) => { var v = (Box3l[,])o; c.CodeBox3lArray2d(ref v); } },\r\n            { typeof(Box3l[, ,]), (c,o) => { var v = (Box3l[, ,])o; c.CodeBox3lArray3d(ref v); } },\r\n            { typeof(Box3f[,]), (c,o) => { var v = (Box3f[,])o; c.CodeBox3fArray2d(ref v); } },\r\n            { typeof(Box3f[, ,]), (c,o) => { var v = (Box3f[, ,])o; c.CodeBox3fArray3d(ref v); } },\r\n            { typeof(Box3d[,]), (c,o) => { var v = (Box3d[,])o; c.CodeBox3dArray2d(ref v); } },\r\n            { typeof(Box3d[, ,]), (c,o) => { var v = (Box3d[, ,])o; c.CodeBox3dArray3d(ref v); } },\r\n            { typeof(Euclidean3f[,]), (c,o) => { var v = (Euclidean3f[,])o; c.CodeEuclidean3fArray2d(ref v); } },\r\n            { typeof(Euclidean3f[, ,]), (c,o) => { var v = (Euclidean3f[, ,])o; c.CodeEuclidean3fArray3d(ref v); } },\r\n            { typeof(Euclidean3d[,]), (c,o) => { var v = (Euclidean3d[,])o; c.CodeEuclidean3dArray2d(ref v); } },\r\n            { typeof(Euclidean3d[, ,]), (c,o) => { var v = (Euclidean3d[, ,])o; c.CodeEuclidean3dArray3d(ref v); } },\r\n            { typeof(Rot2f[,]), (c,o) => { var v = (Rot2f[,])o; c.CodeRot2fArray2d(ref v); } },\r\n            { typeof(Rot2f[, ,]), (c,o) => { var v = (Rot2f[, ,])o; c.CodeRot2fArray3d(ref v); } },\r\n            { typeof(Rot2d[,]), (c,o) => { var v = (Rot2d[,])o; c.CodeRot2dArray2d(ref v); } },\r\n            { typeof(Rot2d[, ,]), (c,o) => { var v = (Rot2d[, ,])o; c.CodeRot2dArray3d(ref v); } },\r\n            { typeof(Rot3f[,]), (c,o) => { var v = (Rot3f[,])o; c.CodeRot3fArray2d(ref v); } },\r\n            { typeof(Rot3f[, ,]), (c,o) => { var v = (Rot3f[, ,])o; c.CodeRot3fArray3d(ref v); } },\r\n            { typeof(Rot3d[,]), (c,o) => { var v = (Rot3d[,])o; c.CodeRot3dArray2d(ref v); } },\r\n            { typeof(Rot3d[, ,]), (c,o) => { var v = (Rot3d[, ,])o; c.CodeRot3dArray3d(ref v); } },\r\n            { typeof(Scale3f[,]), (c,o) => { var v = (Scale3f[,])o; c.CodeScale3fArray2d(ref v); } },\r\n            { typeof(Scale3f[, ,]), (c,o) => { var v = (Scale3f[, ,])o; c.CodeScale3fArray3d(ref v); } },\r\n            { typeof(Scale3d[,]), (c,o) => { var v = (Scale3d[,])o; c.CodeScale3dArray2d(ref v); } },\r\n            { typeof(Scale3d[, ,]), (c,o) => { var v = (Scale3d[, ,])o; c.CodeScale3dArray3d(ref v); } },\r\n            { typeof(Shift3f[,]), (c,o) => { var v = (Shift3f[,])o; c.CodeShift3fArray2d(ref v); } },\r\n            { typeof(Shift3f[, ,]), (c,o) => { var v = (Shift3f[, ,])o; c.CodeShift3fArray3d(ref v); } },\r\n            { typeof(Shift3d[,]), (c,o) => { var v = (Shift3d[,])o; c.CodeShift3dArray2d(ref v); } },\r\n            { typeof(Shift3d[, ,]), (c,o) => { var v = (Shift3d[, ,])o; c.CodeShift3dArray3d(ref v); } },\r\n            { typeof(Trafo2f[,]), (c,o) => { var v = (Trafo2f[,])o; c.CodeTrafo2fArray2d(ref v); } },\r\n            { typeof(Trafo2f[, ,]), (c,o) => { var v = (Trafo2f[, ,])o; c.CodeTrafo2fArray3d(ref v); } },\r\n            { typeof(Trafo2d[,]), (c,o) => { var v = (Trafo2d[,])o; c.CodeTrafo2dArray2d(ref v); } },\r\n            { typeof(Trafo2d[, ,]), (c,o) => { var v = (Trafo2d[, ,])o; c.CodeTrafo2dArray3d(ref v); } },\r\n            { typeof(Trafo3f[,]), (c,o) => { var v = (Trafo3f[,])o; c.CodeTrafo3fArray2d(ref v); } },\r\n            { typeof(Trafo3f[, ,]), (c,o) => { var v = (Trafo3f[, ,])o; c.CodeTrafo3fArray3d(ref v); } },\r\n            { typeof(Trafo3d[,]), (c,o) => { var v = (Trafo3d[,])o; c.CodeTrafo3dArray2d(ref v); } },\r\n            { typeof(Trafo3d[, ,]), (c,o) => { var v = (Trafo3d[, ,])o; c.CodeTrafo3dArray3d(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Jagged Multi-Dimensional Arrays\r\n\r\n            { typeof(byte[][]), (c,o) => { var v = (byte[][])o; c.CodeByteArrayArray(ref v); } },\r\n            { typeof(byte[][][]), (c,o) => { var v = (byte[][][])o; c.CodeByteArrayArrayArray(ref v); } },\r\n            { typeof(sbyte[][]), (c,o) => { var v = (sbyte[][])o; c.CodeSByteArrayArray(ref v); } },\r\n            { typeof(sbyte[][][]), (c,o) => { var v = (sbyte[][][])o; c.CodeSByteArrayArrayArray(ref v); } },\r\n            { typeof(short[][]), (c,o) => { var v = (short[][])o; c.CodeShortArrayArray(ref v); } },\r\n            { typeof(short[][][]), (c,o) => { var v = (short[][][])o; c.CodeShortArrayArrayArray(ref v); } },\r\n            { typeof(ushort[][]), (c,o) => { var v = (ushort[][])o; c.CodeUShortArrayArray(ref v); } },\r\n            { typeof(ushort[][][]), (c,o) => { var v = (ushort[][][])o; c.CodeUShortArrayArrayArray(ref v); } },\r\n            { typeof(int[][]), (c,o) => { var v = (int[][])o; c.CodeIntArrayArray(ref v); } },\r\n            { typeof(int[][][]), (c,o) => { var v = (int[][][])o; c.CodeIntArrayArrayArray(ref v); } },\r\n            { typeof(uint[][]), (c,o) => { var v = (uint[][])o; c.CodeUIntArrayArray(ref v); } },\r\n            { typeof(uint[][][]), (c,o) => { var v = (uint[][][])o; c.CodeUIntArrayArrayArray(ref v); } },\r\n            { typeof(long[][]), (c,o) => { var v = (long[][])o; c.CodeLongArrayArray(ref v); } },\r\n            { typeof(long[][][]), (c,o) => { var v = (long[][][])o; c.CodeLongArrayArrayArray(ref v); } },\r\n            { typeof(ulong[][]), (c,o) => { var v = (ulong[][])o; c.CodeULongArrayArray(ref v); } },\r\n            { typeof(ulong[][][]), (c,o) => { var v = (ulong[][][])o; c.CodeULongArrayArrayArray(ref v); } },\r\n            { typeof(float[][]), (c,o) => { var v = (float[][])o; c.CodeFloatArrayArray(ref v); } },\r\n            { typeof(float[][][]), (c,o) => { var v = (float[][][])o; c.CodeFloatArrayArrayArray(ref v); } },\r\n            { typeof(double[][]), (c,o) => { var v = (double[][])o; c.CodeDoubleArrayArray(ref v); } },\r\n            { typeof(double[][][]), (c,o) => { var v = (double[][][])o; c.CodeDoubleArrayArrayArray(ref v); } },\r\n            { typeof(Fraction[][]), (c,o) => { var v = (Fraction[][])o; c.CodeFractionArrayArray(ref v); } },\r\n            { typeof(Fraction[][][]), (c,o) => { var v = (Fraction[][][])o; c.CodeFractionArrayArrayArray(ref v); } },\r\n            { typeof(V2i[][]), (c,o) => { var v = (V2i[][])o; c.CodeV2iArrayArray(ref v); } },\r\n            { typeof(V2i[][][]), (c,o) => { var v = (V2i[][][])o; c.CodeV2iArrayArrayArray(ref v); } },\r\n            { typeof(V2l[][]), (c,o) => { var v = (V2l[][])o; c.CodeV2lArrayArray(ref v); } },\r\n            { typeof(V2l[][][]), (c,o) => { var v = (V2l[][][])o; c.CodeV2lArrayArrayArray(ref v); } },\r\n            { typeof(V2f[][]), (c,o) => { var v = (V2f[][])o; c.CodeV2fArrayArray(ref v); } },\r\n            { typeof(V2f[][][]), (c,o) => { var v = (V2f[][][])o; c.CodeV2fArrayArrayArray(ref v); } },\r\n            { typeof(V2d[][]), (c,o) => { var v = (V2d[][])o; c.CodeV2dArrayArray(ref v); } },\r\n            { typeof(V2d[][][]), (c,o) => { var v = (V2d[][][])o; c.CodeV2dArrayArrayArray(ref v); } },\r\n            { typeof(V3i[][]), (c,o) => { var v = (V3i[][])o; c.CodeV3iArrayArray(ref v); } },\r\n            { typeof(V3i[][][]), (c,o) => { var v = (V3i[][][])o; c.CodeV3iArrayArrayArray(ref v); } },\r\n            { typeof(V3l[][]), (c,o) => { var v = (V3l[][])o; c.CodeV3lArrayArray(ref v); } },\r\n            { typeof(V3l[][][]), (c,o) => { var v = (V3l[][][])o; c.CodeV3lArrayArrayArray(ref v); } },\r\n            { typeof(V3f[][]), (c,o) => { var v = (V3f[][])o; c.CodeV3fArrayArray(ref v); } },\r\n            { typeof(V3f[][][]), (c,o) => { var v = (V3f[][][])o; c.CodeV3fArrayArrayArray(ref v); } },\r\n            { typeof(V3d[][]), (c,o) => { var v = (V3d[][])o; c.CodeV3dArrayArray(ref v); } },\r\n            { typeof(V3d[][][]), (c,o) => { var v = (V3d[][][])o; c.CodeV3dArrayArrayArray(ref v); } },\r\n            { typeof(V4i[][]), (c,o) => { var v = (V4i[][])o; c.CodeV4iArrayArray(ref v); } },\r\n            { typeof(V4i[][][]), (c,o) => { var v = (V4i[][][])o; c.CodeV4iArrayArrayArray(ref v); } },\r\n            { typeof(V4l[][]), (c,o) => { var v = (V4l[][])o; c.CodeV4lArrayArray(ref v); } },\r\n            { typeof(V4l[][][]), (c,o) => { var v = (V4l[][][])o; c.CodeV4lArrayArrayArray(ref v); } },\r\n            { typeof(V4f[][]), (c,o) => { var v = (V4f[][])o; c.CodeV4fArrayArray(ref v); } },\r\n            { typeof(V4f[][][]), (c,o) => { var v = (V4f[][][])o; c.CodeV4fArrayArrayArray(ref v); } },\r\n            { typeof(V4d[][]), (c,o) => { var v = (V4d[][])o; c.CodeV4dArrayArray(ref v); } },\r\n            { typeof(V4d[][][]), (c,o) => { var v = (V4d[][][])o; c.CodeV4dArrayArrayArray(ref v); } },\r\n            { typeof(M22i[][]), (c,o) => { var v = (M22i[][])o; c.CodeM22iArrayArray(ref v); } },\r\n            { typeof(M22i[][][]), (c,o) => { var v = (M22i[][][])o; c.CodeM22iArrayArrayArray(ref v); } },\r\n            { typeof(M22l[][]), (c,o) => { var v = (M22l[][])o; c.CodeM22lArrayArray(ref v); } },\r\n            { typeof(M22l[][][]), (c,o) => { var v = (M22l[][][])o; c.CodeM22lArrayArrayArray(ref v); } },\r\n            { typeof(M22f[][]), (c,o) => { var v = (M22f[][])o; c.CodeM22fArrayArray(ref v); } },\r\n            { typeof(M22f[][][]), (c,o) => { var v = (M22f[][][])o; c.CodeM22fArrayArrayArray(ref v); } },\r\n            { typeof(M22d[][]), (c,o) => { var v = (M22d[][])o; c.CodeM22dArrayArray(ref v); } },\r\n            { typeof(M22d[][][]), (c,o) => { var v = (M22d[][][])o; c.CodeM22dArrayArrayArray(ref v); } },\r\n            { typeof(M23i[][]), (c,o) => { var v = (M23i[][])o; c.CodeM23iArrayArray(ref v); } },\r\n            { typeof(M23i[][][]), (c,o) => { var v = (M23i[][][])o; c.CodeM23iArrayArrayArray(ref v); } },\r\n            { typeof(M23l[][]), (c,o) => { var v = (M23l[][])o; c.CodeM23lArrayArray(ref v); } },\r\n            { typeof(M23l[][][]), (c,o) => { var v = (M23l[][][])o; c.CodeM23lArrayArrayArray(ref v); } },\r\n            { typeof(M23f[][]), (c,o) => { var v = (M23f[][])o; c.CodeM23fArrayArray(ref v); } },\r\n            { typeof(M23f[][][]), (c,o) => { var v = (M23f[][][])o; c.CodeM23fArrayArrayArray(ref v); } },\r\n            { typeof(M23d[][]), (c,o) => { var v = (M23d[][])o; c.CodeM23dArrayArray(ref v); } },\r\n            { typeof(M23d[][][]), (c,o) => { var v = (M23d[][][])o; c.CodeM23dArrayArrayArray(ref v); } },\r\n            { typeof(M33i[][]), (c,o) => { var v = (M33i[][])o; c.CodeM33iArrayArray(ref v); } },\r\n            { typeof(M33i[][][]), (c,o) => { var v = (M33i[][][])o; c.CodeM33iArrayArrayArray(ref v); } },\r\n            { typeof(M33l[][]), (c,o) => { var v = (M33l[][])o; c.CodeM33lArrayArray(ref v); } },\r\n            { typeof(M33l[][][]), (c,o) => { var v = (M33l[][][])o; c.CodeM33lArrayArrayArray(ref v); } },\r\n            { typeof(M33f[][]), (c,o) => { var v = (M33f[][])o; c.CodeM33fArrayArray(ref v); } },\r\n            { typeof(M33f[][][]), (c,o) => { var v = (M33f[][][])o; c.CodeM33fArrayArrayArray(ref v); } },\r\n            { typeof(M33d[][]), (c,o) => { var v = (M33d[][])o; c.CodeM33dArrayArray(ref v); } },\r\n            { typeof(M33d[][][]), (c,o) => { var v = (M33d[][][])o; c.CodeM33dArrayArrayArray(ref v); } },\r\n            { typeof(M34i[][]), (c,o) => { var v = (M34i[][])o; c.CodeM34iArrayArray(ref v); } },\r\n            { typeof(M34i[][][]), (c,o) => { var v = (M34i[][][])o; c.CodeM34iArrayArrayArray(ref v); } },\r\n            { typeof(M34l[][]), (c,o) => { var v = (M34l[][])o; c.CodeM34lArrayArray(ref v); } },\r\n            { typeof(M34l[][][]), (c,o) => { var v = (M34l[][][])o; c.CodeM34lArrayArrayArray(ref v); } },\r\n            { typeof(M34f[][]), (c,o) => { var v = (M34f[][])o; c.CodeM34fArrayArray(ref v); } },\r\n            { typeof(M34f[][][]), (c,o) => { var v = (M34f[][][])o; c.CodeM34fArrayArrayArray(ref v); } },\r\n            { typeof(M34d[][]), (c,o) => { var v = (M34d[][])o; c.CodeM34dArrayArray(ref v); } },\r\n            { typeof(M34d[][][]), (c,o) => { var v = (M34d[][][])o; c.CodeM34dArrayArrayArray(ref v); } },\r\n            { typeof(M44i[][]), (c,o) => { var v = (M44i[][])o; c.CodeM44iArrayArray(ref v); } },\r\n            { typeof(M44i[][][]), (c,o) => { var v = (M44i[][][])o; c.CodeM44iArrayArrayArray(ref v); } },\r\n            { typeof(M44l[][]), (c,o) => { var v = (M44l[][])o; c.CodeM44lArrayArray(ref v); } },\r\n            { typeof(M44l[][][]), (c,o) => { var v = (M44l[][][])o; c.CodeM44lArrayArrayArray(ref v); } },\r\n            { typeof(M44f[][]), (c,o) => { var v = (M44f[][])o; c.CodeM44fArrayArray(ref v); } },\r\n            { typeof(M44f[][][]), (c,o) => { var v = (M44f[][][])o; c.CodeM44fArrayArrayArray(ref v); } },\r\n            { typeof(M44d[][]), (c,o) => { var v = (M44d[][])o; c.CodeM44dArrayArray(ref v); } },\r\n            { typeof(M44d[][][]), (c,o) => { var v = (M44d[][][])o; c.CodeM44dArrayArrayArray(ref v); } },\r\n            { typeof(C3b[][]), (c,o) => { var v = (C3b[][])o; c.CodeC3bArrayArray(ref v); } },\r\n            { typeof(C3b[][][]), (c,o) => { var v = (C3b[][][])o; c.CodeC3bArrayArrayArray(ref v); } },\r\n            { typeof(C3us[][]), (c,o) => { var v = (C3us[][])o; c.CodeC3usArrayArray(ref v); } },\r\n            { typeof(C3us[][][]), (c,o) => { var v = (C3us[][][])o; c.CodeC3usArrayArrayArray(ref v); } },\r\n            { typeof(C3ui[][]), (c,o) => { var v = (C3ui[][])o; c.CodeC3uiArrayArray(ref v); } },\r\n            { typeof(C3ui[][][]), (c,o) => { var v = (C3ui[][][])o; c.CodeC3uiArrayArrayArray(ref v); } },\r\n            { typeof(C3f[][]), (c,o) => { var v = (C3f[][])o; c.CodeC3fArrayArray(ref v); } },\r\n            { typeof(C3f[][][]), (c,o) => { var v = (C3f[][][])o; c.CodeC3fArrayArrayArray(ref v); } },\r\n            { typeof(C3d[][]), (c,o) => { var v = (C3d[][])o; c.CodeC3dArrayArray(ref v); } },\r\n            { typeof(C3d[][][]), (c,o) => { var v = (C3d[][][])o; c.CodeC3dArrayArrayArray(ref v); } },\r\n            { typeof(C4b[][]), (c,o) => { var v = (C4b[][])o; c.CodeC4bArrayArray(ref v); } },\r\n            { typeof(C4b[][][]), (c,o) => { var v = (C4b[][][])o; c.CodeC4bArrayArrayArray(ref v); } },\r\n            { typeof(C4us[][]), (c,o) => { var v = (C4us[][])o; c.CodeC4usArrayArray(ref v); } },\r\n            { typeof(C4us[][][]), (c,o) => { var v = (C4us[][][])o; c.CodeC4usArrayArrayArray(ref v); } },\r\n            { typeof(C4ui[][]), (c,o) => { var v = (C4ui[][])o; c.CodeC4uiArrayArray(ref v); } },\r\n            { typeof(C4ui[][][]), (c,o) => { var v = (C4ui[][][])o; c.CodeC4uiArrayArrayArray(ref v); } },\r\n            { typeof(C4f[][]), (c,o) => { var v = (C4f[][])o; c.CodeC4fArrayArray(ref v); } },\r\n            { typeof(C4f[][][]), (c,o) => { var v = (C4f[][][])o; c.CodeC4fArrayArrayArray(ref v); } },\r\n            { typeof(C4d[][]), (c,o) => { var v = (C4d[][])o; c.CodeC4dArrayArray(ref v); } },\r\n            { typeof(C4d[][][]), (c,o) => { var v = (C4d[][][])o; c.CodeC4dArrayArrayArray(ref v); } },\r\n            { typeof(Range1b[][]), (c,o) => { var v = (Range1b[][])o; c.CodeRange1bArrayArray(ref v); } },\r\n            { typeof(Range1b[][][]), (c,o) => { var v = (Range1b[][][])o; c.CodeRange1bArrayArrayArray(ref v); } },\r\n            { typeof(Range1sb[][]), (c,o) => { var v = (Range1sb[][])o; c.CodeRange1sbArrayArray(ref v); } },\r\n            { typeof(Range1sb[][][]), (c,o) => { var v = (Range1sb[][][])o; c.CodeRange1sbArrayArrayArray(ref v); } },\r\n            { typeof(Range1s[][]), (c,o) => { var v = (Range1s[][])o; c.CodeRange1sArrayArray(ref v); } },\r\n            { typeof(Range1s[][][]), (c,o) => { var v = (Range1s[][][])o; c.CodeRange1sArrayArrayArray(ref v); } },\r\n            { typeof(Range1us[][]), (c,o) => { var v = (Range1us[][])o; c.CodeRange1usArrayArray(ref v); } },\r\n            { typeof(Range1us[][][]), (c,o) => { var v = (Range1us[][][])o; c.CodeRange1usArrayArrayArray(ref v); } },\r\n            { typeof(Range1i[][]), (c,o) => { var v = (Range1i[][])o; c.CodeRange1iArrayArray(ref v); } },\r\n            { typeof(Range1i[][][]), (c,o) => { var v = (Range1i[][][])o; c.CodeRange1iArrayArrayArray(ref v); } },\r\n            { typeof(Range1ui[][]), (c,o) => { var v = (Range1ui[][])o; c.CodeRange1uiArrayArray(ref v); } },\r\n            { typeof(Range1ui[][][]), (c,o) => { var v = (Range1ui[][][])o; c.CodeRange1uiArrayArrayArray(ref v); } },\r\n            { typeof(Range1l[][]), (c,o) => { var v = (Range1l[][])o; c.CodeRange1lArrayArray(ref v); } },\r\n            { typeof(Range1l[][][]), (c,o) => { var v = (Range1l[][][])o; c.CodeRange1lArrayArrayArray(ref v); } },\r\n            { typeof(Range1ul[][]), (c,o) => { var v = (Range1ul[][])o; c.CodeRange1ulArrayArray(ref v); } },\r\n            { typeof(Range1ul[][][]), (c,o) => { var v = (Range1ul[][][])o; c.CodeRange1ulArrayArrayArray(ref v); } },\r\n            { typeof(Range1f[][]), (c,o) => { var v = (Range1f[][])o; c.CodeRange1fArrayArray(ref v); } },\r\n            { typeof(Range1f[][][]), (c,o) => { var v = (Range1f[][][])o; c.CodeRange1fArrayArrayArray(ref v); } },\r\n            { typeof(Range1d[][]), (c,o) => { var v = (Range1d[][])o; c.CodeRange1dArrayArray(ref v); } },\r\n            { typeof(Range1d[][][]), (c,o) => { var v = (Range1d[][][])o; c.CodeRange1dArrayArrayArray(ref v); } },\r\n            { typeof(Box2i[][]), (c,o) => { var v = (Box2i[][])o; c.CodeBox2iArrayArray(ref v); } },\r\n            { typeof(Box2i[][][]), (c,o) => { var v = (Box2i[][][])o; c.CodeBox2iArrayArrayArray(ref v); } },\r\n            { typeof(Box2l[][]), (c,o) => { var v = (Box2l[][])o; c.CodeBox2lArrayArray(ref v); } },\r\n            { typeof(Box2l[][][]), (c,o) => { var v = (Box2l[][][])o; c.CodeBox2lArrayArrayArray(ref v); } },\r\n            { typeof(Box2f[][]), (c,o) => { var v = (Box2f[][])o; c.CodeBox2fArrayArray(ref v); } },\r\n            { typeof(Box2f[][][]), (c,o) => { var v = (Box2f[][][])o; c.CodeBox2fArrayArrayArray(ref v); } },\r\n            { typeof(Box2d[][]), (c,o) => { var v = (Box2d[][])o; c.CodeBox2dArrayArray(ref v); } },\r\n            { typeof(Box2d[][][]), (c,o) => { var v = (Box2d[][][])o; c.CodeBox2dArrayArrayArray(ref v); } },\r\n            { typeof(Box3i[][]), (c,o) => { var v = (Box3i[][])o; c.CodeBox3iArrayArray(ref v); } },\r\n            { typeof(Box3i[][][]), (c,o) => { var v = (Box3i[][][])o; c.CodeBox3iArrayArrayArray(ref v); } },\r\n            { typeof(Box3l[][]), (c,o) => { var v = (Box3l[][])o; c.CodeBox3lArrayArray(ref v); } },\r\n            { typeof(Box3l[][][]), (c,o) => { var v = (Box3l[][][])o; c.CodeBox3lArrayArrayArray(ref v); } },\r\n            { typeof(Box3f[][]), (c,o) => { var v = (Box3f[][])o; c.CodeBox3fArrayArray(ref v); } },\r\n            { typeof(Box3f[][][]), (c,o) => { var v = (Box3f[][][])o; c.CodeBox3fArrayArrayArray(ref v); } },\r\n            { typeof(Box3d[][]), (c,o) => { var v = (Box3d[][])o; c.CodeBox3dArrayArray(ref v); } },\r\n            { typeof(Box3d[][][]), (c,o) => { var v = (Box3d[][][])o; c.CodeBox3dArrayArrayArray(ref v); } },\r\n            { typeof(Euclidean3f[][]), (c,o) => { var v = (Euclidean3f[][])o; c.CodeEuclidean3fArrayArray(ref v); } },\r\n            { typeof(Euclidean3f[][][]), (c,o) => { var v = (Euclidean3f[][][])o; c.CodeEuclidean3fArrayArrayArray(ref v); } },\r\n            { typeof(Euclidean3d[][]), (c,o) => { var v = (Euclidean3d[][])o; c.CodeEuclidean3dArrayArray(ref v); } },\r\n            { typeof(Euclidean3d[][][]), (c,o) => { var v = (Euclidean3d[][][])o; c.CodeEuclidean3dArrayArrayArray(ref v); } },\r\n            { typeof(Rot2f[][]), (c,o) => { var v = (Rot2f[][])o; c.CodeRot2fArrayArray(ref v); } },\r\n            { typeof(Rot2f[][][]), (c,o) => { var v = (Rot2f[][][])o; c.CodeRot2fArrayArrayArray(ref v); } },\r\n            { typeof(Rot2d[][]), (c,o) => { var v = (Rot2d[][])o; c.CodeRot2dArrayArray(ref v); } },\r\n            { typeof(Rot2d[][][]), (c,o) => { var v = (Rot2d[][][])o; c.CodeRot2dArrayArrayArray(ref v); } },\r\n            { typeof(Rot3f[][]), (c,o) => { var v = (Rot3f[][])o; c.CodeRot3fArrayArray(ref v); } },\r\n            { typeof(Rot3f[][][]), (c,o) => { var v = (Rot3f[][][])o; c.CodeRot3fArrayArrayArray(ref v); } },\r\n            { typeof(Rot3d[][]), (c,o) => { var v = (Rot3d[][])o; c.CodeRot3dArrayArray(ref v); } },\r\n            { typeof(Rot3d[][][]), (c,o) => { var v = (Rot3d[][][])o; c.CodeRot3dArrayArrayArray(ref v); } },\r\n            { typeof(Scale3f[][]), (c,o) => { var v = (Scale3f[][])o; c.CodeScale3fArrayArray(ref v); } },\r\n            { typeof(Scale3f[][][]), (c,o) => { var v = (Scale3f[][][])o; c.CodeScale3fArrayArrayArray(ref v); } },\r\n            { typeof(Scale3d[][]), (c,o) => { var v = (Scale3d[][])o; c.CodeScale3dArrayArray(ref v); } },\r\n            { typeof(Scale3d[][][]), (c,o) => { var v = (Scale3d[][][])o; c.CodeScale3dArrayArrayArray(ref v); } },\r\n            { typeof(Shift3f[][]), (c,o) => { var v = (Shift3f[][])o; c.CodeShift3fArrayArray(ref v); } },\r\n            { typeof(Shift3f[][][]), (c,o) => { var v = (Shift3f[][][])o; c.CodeShift3fArrayArrayArray(ref v); } },\r\n            { typeof(Shift3d[][]), (c,o) => { var v = (Shift3d[][])o; c.CodeShift3dArrayArray(ref v); } },\r\n            { typeof(Shift3d[][][]), (c,o) => { var v = (Shift3d[][][])o; c.CodeShift3dArrayArrayArray(ref v); } },\r\n            { typeof(Trafo2f[][]), (c,o) => { var v = (Trafo2f[][])o; c.CodeTrafo2fArrayArray(ref v); } },\r\n            { typeof(Trafo2f[][][]), (c,o) => { var v = (Trafo2f[][][])o; c.CodeTrafo2fArrayArrayArray(ref v); } },\r\n            { typeof(Trafo2d[][]), (c,o) => { var v = (Trafo2d[][])o; c.CodeTrafo2dArrayArray(ref v); } },\r\n            { typeof(Trafo2d[][][]), (c,o) => { var v = (Trafo2d[][][])o; c.CodeTrafo2dArrayArrayArray(ref v); } },\r\n            { typeof(Trafo3f[][]), (c,o) => { var v = (Trafo3f[][])o; c.CodeTrafo3fArrayArray(ref v); } },\r\n            { typeof(Trafo3f[][][]), (c,o) => { var v = (Trafo3f[][][])o; c.CodeTrafo3fArrayArrayArray(ref v); } },\r\n            { typeof(Trafo3d[][]), (c,o) => { var v = (Trafo3d[][])o; c.CodeTrafo3dArrayArray(ref v); } },\r\n            { typeof(Trafo3d[][][]), (c,o) => { var v = (Trafo3d[][][])o; c.CodeTrafo3dArrayArrayArray(ref v); } },\r\n\r\n            #endregion\r\n\r\n            #region Other Types\r\n\r\n            { typeof(IntSet), (c,o) => { var v = (IntSet)o; c.CodeIntSet(ref v); } },\r\n            { typeof(SymbolSet), (c,o) => { var v = (SymbolSet)o; c.CodeSymbolSet(ref v); } },\r\n\r\n\r\n            { typeof(HashSet<string>), (c, o) => { var v = (HashSet<string>)o; c.CodeHashSet_of_T_(ref v); } },\r\n\r\n            #endregion\r\n        };\r\n\r\n        internal static Dictionary<Type, Func<IReadingCoder, object>> TypeReaderMap =\r\n                                new Dictionary<Type, Func<IReadingCoder, object>>\r\n        {\r\n            #region byte\r\n\r\n            { typeof(byte), c => { var v = default(byte); c.CodeByte(ref v); return v; } },\r\n            { typeof(byte[]), c => { var v = default(byte[]); c.CodeByteArray(ref v); return v; } },\r\n            { typeof(List<byte>), c => { var v = default(List<byte>); c.CodeList_of_Byte_(ref v); return v; } },\r\n\r\n            { typeof(Vector<byte>), c => { var v = default(Vector<byte>); c.CodeVector_of_Byte_(ref v); return v; } },\r\n            { typeof(Vector<byte>[]), c => { var v = default(Vector<byte>[]); c.CodeVector_of_Byte_Array(ref v); return v; } },\r\n            { typeof(List<Vector<byte>>), c => { var v = default(List<Vector<byte>>); c.CodeList_of_Vector_of_Byte__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<byte>), c => { var v = default(Matrix<byte>); c.CodeMatrix_of_Byte_(ref v); return v; } },\r\n            { typeof(Matrix<byte>[]), c => { var v = default(Matrix<byte>[]); c.CodeMatrix_of_Byte_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<byte>>), c => { var v = default(List<Matrix<byte>>); c.CodeList_of_Matrix_of_Byte__(ref v); return v; } },\r\n\r\n            { typeof(Volume<byte>), c => { var v = default(Volume<byte>); c.CodeVolume_of_Byte_(ref v); return v; } },\r\n            { typeof(Volume<byte>[]), c => { var v = default(Volume<byte>[]); c.CodeVolume_of_Byte_Array(ref v); return v; } },\r\n            { typeof(List<Volume<byte>>), c => { var v = default(List<Volume<byte>>); c.CodeList_of_Volume_of_Byte__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<byte>), c => { var v = default(Tensor<byte>); c.CodeTensor_of_Byte_(ref v); return v; } },\r\n            { typeof(Tensor<byte>[]), c => { var v = default(Tensor<byte>[]); c.CodeTensor_of_Byte_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<byte>>), c => { var v = default(List<Tensor<byte>>); c.CodeList_of_Tensor_of_Byte__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region sbyte\r\n\r\n            { typeof(sbyte), c => { var v = default(sbyte); c.CodeSByte(ref v); return v; } },\r\n            { typeof(sbyte[]), c => { var v = default(sbyte[]); c.CodeSByteArray(ref v); return v; } },\r\n            { typeof(List<sbyte>), c => { var v = default(List<sbyte>); c.CodeList_of_SByte_(ref v); return v; } },\r\n\r\n            { typeof(Vector<sbyte>), c => { var v = default(Vector<sbyte>); c.CodeVector_of_SByte_(ref v); return v; } },\r\n            { typeof(Vector<sbyte>[]), c => { var v = default(Vector<sbyte>[]); c.CodeVector_of_SByte_Array(ref v); return v; } },\r\n            { typeof(List<Vector<sbyte>>), c => { var v = default(List<Vector<sbyte>>); c.CodeList_of_Vector_of_SByte__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<sbyte>), c => { var v = default(Matrix<sbyte>); c.CodeMatrix_of_SByte_(ref v); return v; } },\r\n            { typeof(Matrix<sbyte>[]), c => { var v = default(Matrix<sbyte>[]); c.CodeMatrix_of_SByte_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<sbyte>>), c => { var v = default(List<Matrix<sbyte>>); c.CodeList_of_Matrix_of_SByte__(ref v); return v; } },\r\n\r\n            { typeof(Volume<sbyte>), c => { var v = default(Volume<sbyte>); c.CodeVolume_of_SByte_(ref v); return v; } },\r\n            { typeof(Volume<sbyte>[]), c => { var v = default(Volume<sbyte>[]); c.CodeVolume_of_SByte_Array(ref v); return v; } },\r\n            { typeof(List<Volume<sbyte>>), c => { var v = default(List<Volume<sbyte>>); c.CodeList_of_Volume_of_SByte__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<sbyte>), c => { var v = default(Tensor<sbyte>); c.CodeTensor_of_SByte_(ref v); return v; } },\r\n            { typeof(Tensor<sbyte>[]), c => { var v = default(Tensor<sbyte>[]); c.CodeTensor_of_SByte_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<sbyte>>), c => { var v = default(List<Tensor<sbyte>>); c.CodeList_of_Tensor_of_SByte__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region short\r\n\r\n            { typeof(short), c => { var v = default(short); c.CodeShort(ref v); return v; } },\r\n            { typeof(short[]), c => { var v = default(short[]); c.CodeShortArray(ref v); return v; } },\r\n            { typeof(List<short>), c => { var v = default(List<short>); c.CodeList_of_Short_(ref v); return v; } },\r\n\r\n            { typeof(Vector<short>), c => { var v = default(Vector<short>); c.CodeVector_of_Short_(ref v); return v; } },\r\n            { typeof(Vector<short>[]), c => { var v = default(Vector<short>[]); c.CodeVector_of_Short_Array(ref v); return v; } },\r\n            { typeof(List<Vector<short>>), c => { var v = default(List<Vector<short>>); c.CodeList_of_Vector_of_Short__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<short>), c => { var v = default(Matrix<short>); c.CodeMatrix_of_Short_(ref v); return v; } },\r\n            { typeof(Matrix<short>[]), c => { var v = default(Matrix<short>[]); c.CodeMatrix_of_Short_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<short>>), c => { var v = default(List<Matrix<short>>); c.CodeList_of_Matrix_of_Short__(ref v); return v; } },\r\n\r\n            { typeof(Volume<short>), c => { var v = default(Volume<short>); c.CodeVolume_of_Short_(ref v); return v; } },\r\n            { typeof(Volume<short>[]), c => { var v = default(Volume<short>[]); c.CodeVolume_of_Short_Array(ref v); return v; } },\r\n            { typeof(List<Volume<short>>), c => { var v = default(List<Volume<short>>); c.CodeList_of_Volume_of_Short__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<short>), c => { var v = default(Tensor<short>); c.CodeTensor_of_Short_(ref v); return v; } },\r\n            { typeof(Tensor<short>[]), c => { var v = default(Tensor<short>[]); c.CodeTensor_of_Short_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<short>>), c => { var v = default(List<Tensor<short>>); c.CodeList_of_Tensor_of_Short__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region ushort\r\n\r\n            { typeof(ushort), c => { var v = default(ushort); c.CodeUShort(ref v); return v; } },\r\n            { typeof(ushort[]), c => { var v = default(ushort[]); c.CodeUShortArray(ref v); return v; } },\r\n            { typeof(List<ushort>), c => { var v = default(List<ushort>); c.CodeList_of_UShort_(ref v); return v; } },\r\n\r\n            { typeof(Vector<ushort>), c => { var v = default(Vector<ushort>); c.CodeVector_of_UShort_(ref v); return v; } },\r\n            { typeof(Vector<ushort>[]), c => { var v = default(Vector<ushort>[]); c.CodeVector_of_UShort_Array(ref v); return v; } },\r\n            { typeof(List<Vector<ushort>>), c => { var v = default(List<Vector<ushort>>); c.CodeList_of_Vector_of_UShort__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<ushort>), c => { var v = default(Matrix<ushort>); c.CodeMatrix_of_UShort_(ref v); return v; } },\r\n            { typeof(Matrix<ushort>[]), c => { var v = default(Matrix<ushort>[]); c.CodeMatrix_of_UShort_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<ushort>>), c => { var v = default(List<Matrix<ushort>>); c.CodeList_of_Matrix_of_UShort__(ref v); return v; } },\r\n\r\n            { typeof(Volume<ushort>), c => { var v = default(Volume<ushort>); c.CodeVolume_of_UShort_(ref v); return v; } },\r\n            { typeof(Volume<ushort>[]), c => { var v = default(Volume<ushort>[]); c.CodeVolume_of_UShort_Array(ref v); return v; } },\r\n            { typeof(List<Volume<ushort>>), c => { var v = default(List<Volume<ushort>>); c.CodeList_of_Volume_of_UShort__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<ushort>), c => { var v = default(Tensor<ushort>); c.CodeTensor_of_UShort_(ref v); return v; } },\r\n            { typeof(Tensor<ushort>[]), c => { var v = default(Tensor<ushort>[]); c.CodeTensor_of_UShort_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<ushort>>), c => { var v = default(List<Tensor<ushort>>); c.CodeList_of_Tensor_of_UShort__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region int\r\n\r\n            { typeof(int), c => { var v = default(int); c.CodeInt(ref v); return v; } },\r\n            { typeof(int[]), c => { var v = default(int[]); c.CodeIntArray(ref v); return v; } },\r\n            { typeof(List<int>), c => { var v = default(List<int>); c.CodeList_of_Int_(ref v); return v; } },\r\n\r\n            { typeof(Vector<int>), c => { var v = default(Vector<int>); c.CodeVector_of_Int_(ref v); return v; } },\r\n            { typeof(Vector<int>[]), c => { var v = default(Vector<int>[]); c.CodeVector_of_Int_Array(ref v); return v; } },\r\n            { typeof(List<Vector<int>>), c => { var v = default(List<Vector<int>>); c.CodeList_of_Vector_of_Int__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<int>), c => { var v = default(Matrix<int>); c.CodeMatrix_of_Int_(ref v); return v; } },\r\n            { typeof(Matrix<int>[]), c => { var v = default(Matrix<int>[]); c.CodeMatrix_of_Int_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<int>>), c => { var v = default(List<Matrix<int>>); c.CodeList_of_Matrix_of_Int__(ref v); return v; } },\r\n\r\n            { typeof(Volume<int>), c => { var v = default(Volume<int>); c.CodeVolume_of_Int_(ref v); return v; } },\r\n            { typeof(Volume<int>[]), c => { var v = default(Volume<int>[]); c.CodeVolume_of_Int_Array(ref v); return v; } },\r\n            { typeof(List<Volume<int>>), c => { var v = default(List<Volume<int>>); c.CodeList_of_Volume_of_Int__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<int>), c => { var v = default(Tensor<int>); c.CodeTensor_of_Int_(ref v); return v; } },\r\n            { typeof(Tensor<int>[]), c => { var v = default(Tensor<int>[]); c.CodeTensor_of_Int_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<int>>), c => { var v = default(List<Tensor<int>>); c.CodeList_of_Tensor_of_Int__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region uint\r\n\r\n            { typeof(uint), c => { var v = default(uint); c.CodeUInt(ref v); return v; } },\r\n            { typeof(uint[]), c => { var v = default(uint[]); c.CodeUIntArray(ref v); return v; } },\r\n            { typeof(List<uint>), c => { var v = default(List<uint>); c.CodeList_of_UInt_(ref v); return v; } },\r\n\r\n            { typeof(Vector<uint>), c => { var v = default(Vector<uint>); c.CodeVector_of_UInt_(ref v); return v; } },\r\n            { typeof(Vector<uint>[]), c => { var v = default(Vector<uint>[]); c.CodeVector_of_UInt_Array(ref v); return v; } },\r\n            { typeof(List<Vector<uint>>), c => { var v = default(List<Vector<uint>>); c.CodeList_of_Vector_of_UInt__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<uint>), c => { var v = default(Matrix<uint>); c.CodeMatrix_of_UInt_(ref v); return v; } },\r\n            { typeof(Matrix<uint>[]), c => { var v = default(Matrix<uint>[]); c.CodeMatrix_of_UInt_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<uint>>), c => { var v = default(List<Matrix<uint>>); c.CodeList_of_Matrix_of_UInt__(ref v); return v; } },\r\n\r\n            { typeof(Volume<uint>), c => { var v = default(Volume<uint>); c.CodeVolume_of_UInt_(ref v); return v; } },\r\n            { typeof(Volume<uint>[]), c => { var v = default(Volume<uint>[]); c.CodeVolume_of_UInt_Array(ref v); return v; } },\r\n            { typeof(List<Volume<uint>>), c => { var v = default(List<Volume<uint>>); c.CodeList_of_Volume_of_UInt__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<uint>), c => { var v = default(Tensor<uint>); c.CodeTensor_of_UInt_(ref v); return v; } },\r\n            { typeof(Tensor<uint>[]), c => { var v = default(Tensor<uint>[]); c.CodeTensor_of_UInt_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<uint>>), c => { var v = default(List<Tensor<uint>>); c.CodeList_of_Tensor_of_UInt__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region long\r\n\r\n            { typeof(long), c => { var v = default(long); c.CodeLong(ref v); return v; } },\r\n            { typeof(long[]), c => { var v = default(long[]); c.CodeLongArray(ref v); return v; } },\r\n            { typeof(List<long>), c => { var v = default(List<long>); c.CodeList_of_Long_(ref v); return v; } },\r\n\r\n            { typeof(Vector<long>), c => { var v = default(Vector<long>); c.CodeVector_of_Long_(ref v); return v; } },\r\n            { typeof(Vector<long>[]), c => { var v = default(Vector<long>[]); c.CodeVector_of_Long_Array(ref v); return v; } },\r\n            { typeof(List<Vector<long>>), c => { var v = default(List<Vector<long>>); c.CodeList_of_Vector_of_Long__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<long>), c => { var v = default(Matrix<long>); c.CodeMatrix_of_Long_(ref v); return v; } },\r\n            { typeof(Matrix<long>[]), c => { var v = default(Matrix<long>[]); c.CodeMatrix_of_Long_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<long>>), c => { var v = default(List<Matrix<long>>); c.CodeList_of_Matrix_of_Long__(ref v); return v; } },\r\n\r\n            { typeof(Volume<long>), c => { var v = default(Volume<long>); c.CodeVolume_of_Long_(ref v); return v; } },\r\n            { typeof(Volume<long>[]), c => { var v = default(Volume<long>[]); c.CodeVolume_of_Long_Array(ref v); return v; } },\r\n            { typeof(List<Volume<long>>), c => { var v = default(List<Volume<long>>); c.CodeList_of_Volume_of_Long__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<long>), c => { var v = default(Tensor<long>); c.CodeTensor_of_Long_(ref v); return v; } },\r\n            { typeof(Tensor<long>[]), c => { var v = default(Tensor<long>[]); c.CodeTensor_of_Long_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<long>>), c => { var v = default(List<Tensor<long>>); c.CodeList_of_Tensor_of_Long__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region ulong\r\n\r\n            { typeof(ulong), c => { var v = default(ulong); c.CodeULong(ref v); return v; } },\r\n            { typeof(ulong[]), c => { var v = default(ulong[]); c.CodeULongArray(ref v); return v; } },\r\n            { typeof(List<ulong>), c => { var v = default(List<ulong>); c.CodeList_of_ULong_(ref v); return v; } },\r\n\r\n            { typeof(Vector<ulong>), c => { var v = default(Vector<ulong>); c.CodeVector_of_ULong_(ref v); return v; } },\r\n            { typeof(Vector<ulong>[]), c => { var v = default(Vector<ulong>[]); c.CodeVector_of_ULong_Array(ref v); return v; } },\r\n            { typeof(List<Vector<ulong>>), c => { var v = default(List<Vector<ulong>>); c.CodeList_of_Vector_of_ULong__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<ulong>), c => { var v = default(Matrix<ulong>); c.CodeMatrix_of_ULong_(ref v); return v; } },\r\n            { typeof(Matrix<ulong>[]), c => { var v = default(Matrix<ulong>[]); c.CodeMatrix_of_ULong_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<ulong>>), c => { var v = default(List<Matrix<ulong>>); c.CodeList_of_Matrix_of_ULong__(ref v); return v; } },\r\n\r\n            { typeof(Volume<ulong>), c => { var v = default(Volume<ulong>); c.CodeVolume_of_ULong_(ref v); return v; } },\r\n            { typeof(Volume<ulong>[]), c => { var v = default(Volume<ulong>[]); c.CodeVolume_of_ULong_Array(ref v); return v; } },\r\n            { typeof(List<Volume<ulong>>), c => { var v = default(List<Volume<ulong>>); c.CodeList_of_Volume_of_ULong__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<ulong>), c => { var v = default(Tensor<ulong>); c.CodeTensor_of_ULong_(ref v); return v; } },\r\n            { typeof(Tensor<ulong>[]), c => { var v = default(Tensor<ulong>[]); c.CodeTensor_of_ULong_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<ulong>>), c => { var v = default(List<Tensor<ulong>>); c.CodeList_of_Tensor_of_ULong__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region float\r\n\r\n            { typeof(float), c => { var v = default(float); c.CodeFloat(ref v); return v; } },\r\n            { typeof(float[]), c => { var v = default(float[]); c.CodeFloatArray(ref v); return v; } },\r\n            { typeof(List<float>), c => { var v = default(List<float>); c.CodeList_of_Float_(ref v); return v; } },\r\n\r\n            { typeof(Vector<float>), c => { var v = default(Vector<float>); c.CodeVector_of_Float_(ref v); return v; } },\r\n            { typeof(Vector<float>[]), c => { var v = default(Vector<float>[]); c.CodeVector_of_Float_Array(ref v); return v; } },\r\n            { typeof(List<Vector<float>>), c => { var v = default(List<Vector<float>>); c.CodeList_of_Vector_of_Float__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<float>), c => { var v = default(Matrix<float>); c.CodeMatrix_of_Float_(ref v); return v; } },\r\n            { typeof(Matrix<float>[]), c => { var v = default(Matrix<float>[]); c.CodeMatrix_of_Float_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<float>>), c => { var v = default(List<Matrix<float>>); c.CodeList_of_Matrix_of_Float__(ref v); return v; } },\r\n\r\n            { typeof(Volume<float>), c => { var v = default(Volume<float>); c.CodeVolume_of_Float_(ref v); return v; } },\r\n            { typeof(Volume<float>[]), c => { var v = default(Volume<float>[]); c.CodeVolume_of_Float_Array(ref v); return v; } },\r\n            { typeof(List<Volume<float>>), c => { var v = default(List<Volume<float>>); c.CodeList_of_Volume_of_Float__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<float>), c => { var v = default(Tensor<float>); c.CodeTensor_of_Float_(ref v); return v; } },\r\n            { typeof(Tensor<float>[]), c => { var v = default(Tensor<float>[]); c.CodeTensor_of_Float_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<float>>), c => { var v = default(List<Tensor<float>>); c.CodeList_of_Tensor_of_Float__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region double\r\n\r\n            { typeof(double), c => { var v = default(double); c.CodeDouble(ref v); return v; } },\r\n            { typeof(double[]), c => { var v = default(double[]); c.CodeDoubleArray(ref v); return v; } },\r\n            { typeof(List<double>), c => { var v = default(List<double>); c.CodeList_of_Double_(ref v); return v; } },\r\n\r\n            { typeof(Vector<double>), c => { var v = default(Vector<double>); c.CodeVector_of_Double_(ref v); return v; } },\r\n            { typeof(Vector<double>[]), c => { var v = default(Vector<double>[]); c.CodeVector_of_Double_Array(ref v); return v; } },\r\n            { typeof(List<Vector<double>>), c => { var v = default(List<Vector<double>>); c.CodeList_of_Vector_of_Double__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<double>), c => { var v = default(Matrix<double>); c.CodeMatrix_of_Double_(ref v); return v; } },\r\n            { typeof(Matrix<double>[]), c => { var v = default(Matrix<double>[]); c.CodeMatrix_of_Double_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<double>>), c => { var v = default(List<Matrix<double>>); c.CodeList_of_Matrix_of_Double__(ref v); return v; } },\r\n\r\n            { typeof(Volume<double>), c => { var v = default(Volume<double>); c.CodeVolume_of_Double_(ref v); return v; } },\r\n            { typeof(Volume<double>[]), c => { var v = default(Volume<double>[]); c.CodeVolume_of_Double_Array(ref v); return v; } },\r\n            { typeof(List<Volume<double>>), c => { var v = default(List<Volume<double>>); c.CodeList_of_Volume_of_Double__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<double>), c => { var v = default(Tensor<double>); c.CodeTensor_of_Double_(ref v); return v; } },\r\n            { typeof(Tensor<double>[]), c => { var v = default(Tensor<double>[]); c.CodeTensor_of_Double_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<double>>), c => { var v = default(List<Tensor<double>>); c.CodeList_of_Tensor_of_Double__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Fraction\r\n\r\n            { typeof(Fraction), c => { var v = default(Fraction); c.CodeFraction(ref v); return v; } },\r\n            { typeof(Fraction[]), c => { var v = default(Fraction[]); c.CodeFractionArray(ref v); return v; } },\r\n            { typeof(List<Fraction>), c => { var v = default(List<Fraction>); c.CodeList_of_Fraction_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Fraction>), c => { var v = default(Vector<Fraction>); c.CodeVector_of_Fraction_(ref v); return v; } },\r\n            { typeof(Vector<Fraction>[]), c => { var v = default(Vector<Fraction>[]); c.CodeVector_of_Fraction_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Fraction>>), c => { var v = default(List<Vector<Fraction>>); c.CodeList_of_Vector_of_Fraction__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Fraction>), c => { var v = default(Matrix<Fraction>); c.CodeMatrix_of_Fraction_(ref v); return v; } },\r\n            { typeof(Matrix<Fraction>[]), c => { var v = default(Matrix<Fraction>[]); c.CodeMatrix_of_Fraction_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Fraction>>), c => { var v = default(List<Matrix<Fraction>>); c.CodeList_of_Matrix_of_Fraction__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Fraction>), c => { var v = default(Volume<Fraction>); c.CodeVolume_of_Fraction_(ref v); return v; } },\r\n            { typeof(Volume<Fraction>[]), c => { var v = default(Volume<Fraction>[]); c.CodeVolume_of_Fraction_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Fraction>>), c => { var v = default(List<Volume<Fraction>>); c.CodeList_of_Volume_of_Fraction__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Fraction>), c => { var v = default(Tensor<Fraction>); c.CodeTensor_of_Fraction_(ref v); return v; } },\r\n            { typeof(Tensor<Fraction>[]), c => { var v = default(Tensor<Fraction>[]); c.CodeTensor_of_Fraction_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Fraction>>), c => { var v = default(List<Tensor<Fraction>>); c.CodeList_of_Tensor_of_Fraction__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V2i\r\n\r\n            { typeof(V2i), c => { var v = default(V2i); c.CodeV2i(ref v); return v; } },\r\n            { typeof(V2i[]), c => { var v = default(V2i[]); c.CodeV2iArray(ref v); return v; } },\r\n            { typeof(List<V2i>), c => { var v = default(List<V2i>); c.CodeList_of_V2i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V2i>), c => { var v = default(Vector<V2i>); c.CodeVector_of_V2i_(ref v); return v; } },\r\n            { typeof(Vector<V2i>[]), c => { var v = default(Vector<V2i>[]); c.CodeVector_of_V2i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V2i>>), c => { var v = default(List<Vector<V2i>>); c.CodeList_of_Vector_of_V2i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V2i>), c => { var v = default(Matrix<V2i>); c.CodeMatrix_of_V2i_(ref v); return v; } },\r\n            { typeof(Matrix<V2i>[]), c => { var v = default(Matrix<V2i>[]); c.CodeMatrix_of_V2i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V2i>>), c => { var v = default(List<Matrix<V2i>>); c.CodeList_of_Matrix_of_V2i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V2i>), c => { var v = default(Volume<V2i>); c.CodeVolume_of_V2i_(ref v); return v; } },\r\n            { typeof(Volume<V2i>[]), c => { var v = default(Volume<V2i>[]); c.CodeVolume_of_V2i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V2i>>), c => { var v = default(List<Volume<V2i>>); c.CodeList_of_Volume_of_V2i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V2i>), c => { var v = default(Tensor<V2i>); c.CodeTensor_of_V2i_(ref v); return v; } },\r\n            { typeof(Tensor<V2i>[]), c => { var v = default(Tensor<V2i>[]); c.CodeTensor_of_V2i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V2i>>), c => { var v = default(List<Tensor<V2i>>); c.CodeList_of_Tensor_of_V2i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V2l\r\n\r\n            { typeof(V2l), c => { var v = default(V2l); c.CodeV2l(ref v); return v; } },\r\n            { typeof(V2l[]), c => { var v = default(V2l[]); c.CodeV2lArray(ref v); return v; } },\r\n            { typeof(List<V2l>), c => { var v = default(List<V2l>); c.CodeList_of_V2l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V2l>), c => { var v = default(Vector<V2l>); c.CodeVector_of_V2l_(ref v); return v; } },\r\n            { typeof(Vector<V2l>[]), c => { var v = default(Vector<V2l>[]); c.CodeVector_of_V2l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V2l>>), c => { var v = default(List<Vector<V2l>>); c.CodeList_of_Vector_of_V2l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V2l>), c => { var v = default(Matrix<V2l>); c.CodeMatrix_of_V2l_(ref v); return v; } },\r\n            { typeof(Matrix<V2l>[]), c => { var v = default(Matrix<V2l>[]); c.CodeMatrix_of_V2l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V2l>>), c => { var v = default(List<Matrix<V2l>>); c.CodeList_of_Matrix_of_V2l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V2l>), c => { var v = default(Volume<V2l>); c.CodeVolume_of_V2l_(ref v); return v; } },\r\n            { typeof(Volume<V2l>[]), c => { var v = default(Volume<V2l>[]); c.CodeVolume_of_V2l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V2l>>), c => { var v = default(List<Volume<V2l>>); c.CodeList_of_Volume_of_V2l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V2l>), c => { var v = default(Tensor<V2l>); c.CodeTensor_of_V2l_(ref v); return v; } },\r\n            { typeof(Tensor<V2l>[]), c => { var v = default(Tensor<V2l>[]); c.CodeTensor_of_V2l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V2l>>), c => { var v = default(List<Tensor<V2l>>); c.CodeList_of_Tensor_of_V2l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V2f\r\n\r\n            { typeof(V2f), c => { var v = default(V2f); c.CodeV2f(ref v); return v; } },\r\n            { typeof(V2f[]), c => { var v = default(V2f[]); c.CodeV2fArray(ref v); return v; } },\r\n            { typeof(List<V2f>), c => { var v = default(List<V2f>); c.CodeList_of_V2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V2f>), c => { var v = default(Vector<V2f>); c.CodeVector_of_V2f_(ref v); return v; } },\r\n            { typeof(Vector<V2f>[]), c => { var v = default(Vector<V2f>[]); c.CodeVector_of_V2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V2f>>), c => { var v = default(List<Vector<V2f>>); c.CodeList_of_Vector_of_V2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V2f>), c => { var v = default(Matrix<V2f>); c.CodeMatrix_of_V2f_(ref v); return v; } },\r\n            { typeof(Matrix<V2f>[]), c => { var v = default(Matrix<V2f>[]); c.CodeMatrix_of_V2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V2f>>), c => { var v = default(List<Matrix<V2f>>); c.CodeList_of_Matrix_of_V2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V2f>), c => { var v = default(Volume<V2f>); c.CodeVolume_of_V2f_(ref v); return v; } },\r\n            { typeof(Volume<V2f>[]), c => { var v = default(Volume<V2f>[]); c.CodeVolume_of_V2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V2f>>), c => { var v = default(List<Volume<V2f>>); c.CodeList_of_Volume_of_V2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V2f>), c => { var v = default(Tensor<V2f>); c.CodeTensor_of_V2f_(ref v); return v; } },\r\n            { typeof(Tensor<V2f>[]), c => { var v = default(Tensor<V2f>[]); c.CodeTensor_of_V2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V2f>>), c => { var v = default(List<Tensor<V2f>>); c.CodeList_of_Tensor_of_V2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V2d\r\n\r\n            { typeof(V2d), c => { var v = default(V2d); c.CodeV2d(ref v); return v; } },\r\n            { typeof(V2d[]), c => { var v = default(V2d[]); c.CodeV2dArray(ref v); return v; } },\r\n            { typeof(List<V2d>), c => { var v = default(List<V2d>); c.CodeList_of_V2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V2d>), c => { var v = default(Vector<V2d>); c.CodeVector_of_V2d_(ref v); return v; } },\r\n            { typeof(Vector<V2d>[]), c => { var v = default(Vector<V2d>[]); c.CodeVector_of_V2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V2d>>), c => { var v = default(List<Vector<V2d>>); c.CodeList_of_Vector_of_V2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V2d>), c => { var v = default(Matrix<V2d>); c.CodeMatrix_of_V2d_(ref v); return v; } },\r\n            { typeof(Matrix<V2d>[]), c => { var v = default(Matrix<V2d>[]); c.CodeMatrix_of_V2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V2d>>), c => { var v = default(List<Matrix<V2d>>); c.CodeList_of_Matrix_of_V2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V2d>), c => { var v = default(Volume<V2d>); c.CodeVolume_of_V2d_(ref v); return v; } },\r\n            { typeof(Volume<V2d>[]), c => { var v = default(Volume<V2d>[]); c.CodeVolume_of_V2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V2d>>), c => { var v = default(List<Volume<V2d>>); c.CodeList_of_Volume_of_V2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V2d>), c => { var v = default(Tensor<V2d>); c.CodeTensor_of_V2d_(ref v); return v; } },\r\n            { typeof(Tensor<V2d>[]), c => { var v = default(Tensor<V2d>[]); c.CodeTensor_of_V2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V2d>>), c => { var v = default(List<Tensor<V2d>>); c.CodeList_of_Tensor_of_V2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V3i\r\n\r\n            { typeof(V3i), c => { var v = default(V3i); c.CodeV3i(ref v); return v; } },\r\n            { typeof(V3i[]), c => { var v = default(V3i[]); c.CodeV3iArray(ref v); return v; } },\r\n            { typeof(List<V3i>), c => { var v = default(List<V3i>); c.CodeList_of_V3i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V3i>), c => { var v = default(Vector<V3i>); c.CodeVector_of_V3i_(ref v); return v; } },\r\n            { typeof(Vector<V3i>[]), c => { var v = default(Vector<V3i>[]); c.CodeVector_of_V3i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V3i>>), c => { var v = default(List<Vector<V3i>>); c.CodeList_of_Vector_of_V3i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V3i>), c => { var v = default(Matrix<V3i>); c.CodeMatrix_of_V3i_(ref v); return v; } },\r\n            { typeof(Matrix<V3i>[]), c => { var v = default(Matrix<V3i>[]); c.CodeMatrix_of_V3i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V3i>>), c => { var v = default(List<Matrix<V3i>>); c.CodeList_of_Matrix_of_V3i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V3i>), c => { var v = default(Volume<V3i>); c.CodeVolume_of_V3i_(ref v); return v; } },\r\n            { typeof(Volume<V3i>[]), c => { var v = default(Volume<V3i>[]); c.CodeVolume_of_V3i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V3i>>), c => { var v = default(List<Volume<V3i>>); c.CodeList_of_Volume_of_V3i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V3i>), c => { var v = default(Tensor<V3i>); c.CodeTensor_of_V3i_(ref v); return v; } },\r\n            { typeof(Tensor<V3i>[]), c => { var v = default(Tensor<V3i>[]); c.CodeTensor_of_V3i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V3i>>), c => { var v = default(List<Tensor<V3i>>); c.CodeList_of_Tensor_of_V3i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V3l\r\n\r\n            { typeof(V3l), c => { var v = default(V3l); c.CodeV3l(ref v); return v; } },\r\n            { typeof(V3l[]), c => { var v = default(V3l[]); c.CodeV3lArray(ref v); return v; } },\r\n            { typeof(List<V3l>), c => { var v = default(List<V3l>); c.CodeList_of_V3l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V3l>), c => { var v = default(Vector<V3l>); c.CodeVector_of_V3l_(ref v); return v; } },\r\n            { typeof(Vector<V3l>[]), c => { var v = default(Vector<V3l>[]); c.CodeVector_of_V3l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V3l>>), c => { var v = default(List<Vector<V3l>>); c.CodeList_of_Vector_of_V3l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V3l>), c => { var v = default(Matrix<V3l>); c.CodeMatrix_of_V3l_(ref v); return v; } },\r\n            { typeof(Matrix<V3l>[]), c => { var v = default(Matrix<V3l>[]); c.CodeMatrix_of_V3l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V3l>>), c => { var v = default(List<Matrix<V3l>>); c.CodeList_of_Matrix_of_V3l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V3l>), c => { var v = default(Volume<V3l>); c.CodeVolume_of_V3l_(ref v); return v; } },\r\n            { typeof(Volume<V3l>[]), c => { var v = default(Volume<V3l>[]); c.CodeVolume_of_V3l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V3l>>), c => { var v = default(List<Volume<V3l>>); c.CodeList_of_Volume_of_V3l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V3l>), c => { var v = default(Tensor<V3l>); c.CodeTensor_of_V3l_(ref v); return v; } },\r\n            { typeof(Tensor<V3l>[]), c => { var v = default(Tensor<V3l>[]); c.CodeTensor_of_V3l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V3l>>), c => { var v = default(List<Tensor<V3l>>); c.CodeList_of_Tensor_of_V3l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V3f\r\n\r\n            { typeof(V3f), c => { var v = default(V3f); c.CodeV3f(ref v); return v; } },\r\n            { typeof(V3f[]), c => { var v = default(V3f[]); c.CodeV3fArray(ref v); return v; } },\r\n            { typeof(List<V3f>), c => { var v = default(List<V3f>); c.CodeList_of_V3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V3f>), c => { var v = default(Vector<V3f>); c.CodeVector_of_V3f_(ref v); return v; } },\r\n            { typeof(Vector<V3f>[]), c => { var v = default(Vector<V3f>[]); c.CodeVector_of_V3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V3f>>), c => { var v = default(List<Vector<V3f>>); c.CodeList_of_Vector_of_V3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V3f>), c => { var v = default(Matrix<V3f>); c.CodeMatrix_of_V3f_(ref v); return v; } },\r\n            { typeof(Matrix<V3f>[]), c => { var v = default(Matrix<V3f>[]); c.CodeMatrix_of_V3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V3f>>), c => { var v = default(List<Matrix<V3f>>); c.CodeList_of_Matrix_of_V3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V3f>), c => { var v = default(Volume<V3f>); c.CodeVolume_of_V3f_(ref v); return v; } },\r\n            { typeof(Volume<V3f>[]), c => { var v = default(Volume<V3f>[]); c.CodeVolume_of_V3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V3f>>), c => { var v = default(List<Volume<V3f>>); c.CodeList_of_Volume_of_V3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V3f>), c => { var v = default(Tensor<V3f>); c.CodeTensor_of_V3f_(ref v); return v; } },\r\n            { typeof(Tensor<V3f>[]), c => { var v = default(Tensor<V3f>[]); c.CodeTensor_of_V3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V3f>>), c => { var v = default(List<Tensor<V3f>>); c.CodeList_of_Tensor_of_V3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V3d\r\n\r\n            { typeof(V3d), c => { var v = default(V3d); c.CodeV3d(ref v); return v; } },\r\n            { typeof(V3d[]), c => { var v = default(V3d[]); c.CodeV3dArray(ref v); return v; } },\r\n            { typeof(List<V3d>), c => { var v = default(List<V3d>); c.CodeList_of_V3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V3d>), c => { var v = default(Vector<V3d>); c.CodeVector_of_V3d_(ref v); return v; } },\r\n            { typeof(Vector<V3d>[]), c => { var v = default(Vector<V3d>[]); c.CodeVector_of_V3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V3d>>), c => { var v = default(List<Vector<V3d>>); c.CodeList_of_Vector_of_V3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V3d>), c => { var v = default(Matrix<V3d>); c.CodeMatrix_of_V3d_(ref v); return v; } },\r\n            { typeof(Matrix<V3d>[]), c => { var v = default(Matrix<V3d>[]); c.CodeMatrix_of_V3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V3d>>), c => { var v = default(List<Matrix<V3d>>); c.CodeList_of_Matrix_of_V3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V3d>), c => { var v = default(Volume<V3d>); c.CodeVolume_of_V3d_(ref v); return v; } },\r\n            { typeof(Volume<V3d>[]), c => { var v = default(Volume<V3d>[]); c.CodeVolume_of_V3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V3d>>), c => { var v = default(List<Volume<V3d>>); c.CodeList_of_Volume_of_V3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V3d>), c => { var v = default(Tensor<V3d>); c.CodeTensor_of_V3d_(ref v); return v; } },\r\n            { typeof(Tensor<V3d>[]), c => { var v = default(Tensor<V3d>[]); c.CodeTensor_of_V3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V3d>>), c => { var v = default(List<Tensor<V3d>>); c.CodeList_of_Tensor_of_V3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V4i\r\n\r\n            { typeof(V4i), c => { var v = default(V4i); c.CodeV4i(ref v); return v; } },\r\n            { typeof(V4i[]), c => { var v = default(V4i[]); c.CodeV4iArray(ref v); return v; } },\r\n            { typeof(List<V4i>), c => { var v = default(List<V4i>); c.CodeList_of_V4i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V4i>), c => { var v = default(Vector<V4i>); c.CodeVector_of_V4i_(ref v); return v; } },\r\n            { typeof(Vector<V4i>[]), c => { var v = default(Vector<V4i>[]); c.CodeVector_of_V4i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V4i>>), c => { var v = default(List<Vector<V4i>>); c.CodeList_of_Vector_of_V4i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V4i>), c => { var v = default(Matrix<V4i>); c.CodeMatrix_of_V4i_(ref v); return v; } },\r\n            { typeof(Matrix<V4i>[]), c => { var v = default(Matrix<V4i>[]); c.CodeMatrix_of_V4i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V4i>>), c => { var v = default(List<Matrix<V4i>>); c.CodeList_of_Matrix_of_V4i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V4i>), c => { var v = default(Volume<V4i>); c.CodeVolume_of_V4i_(ref v); return v; } },\r\n            { typeof(Volume<V4i>[]), c => { var v = default(Volume<V4i>[]); c.CodeVolume_of_V4i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V4i>>), c => { var v = default(List<Volume<V4i>>); c.CodeList_of_Volume_of_V4i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V4i>), c => { var v = default(Tensor<V4i>); c.CodeTensor_of_V4i_(ref v); return v; } },\r\n            { typeof(Tensor<V4i>[]), c => { var v = default(Tensor<V4i>[]); c.CodeTensor_of_V4i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V4i>>), c => { var v = default(List<Tensor<V4i>>); c.CodeList_of_Tensor_of_V4i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V4l\r\n\r\n            { typeof(V4l), c => { var v = default(V4l); c.CodeV4l(ref v); return v; } },\r\n            { typeof(V4l[]), c => { var v = default(V4l[]); c.CodeV4lArray(ref v); return v; } },\r\n            { typeof(List<V4l>), c => { var v = default(List<V4l>); c.CodeList_of_V4l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V4l>), c => { var v = default(Vector<V4l>); c.CodeVector_of_V4l_(ref v); return v; } },\r\n            { typeof(Vector<V4l>[]), c => { var v = default(Vector<V4l>[]); c.CodeVector_of_V4l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V4l>>), c => { var v = default(List<Vector<V4l>>); c.CodeList_of_Vector_of_V4l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V4l>), c => { var v = default(Matrix<V4l>); c.CodeMatrix_of_V4l_(ref v); return v; } },\r\n            { typeof(Matrix<V4l>[]), c => { var v = default(Matrix<V4l>[]); c.CodeMatrix_of_V4l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V4l>>), c => { var v = default(List<Matrix<V4l>>); c.CodeList_of_Matrix_of_V4l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V4l>), c => { var v = default(Volume<V4l>); c.CodeVolume_of_V4l_(ref v); return v; } },\r\n            { typeof(Volume<V4l>[]), c => { var v = default(Volume<V4l>[]); c.CodeVolume_of_V4l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V4l>>), c => { var v = default(List<Volume<V4l>>); c.CodeList_of_Volume_of_V4l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V4l>), c => { var v = default(Tensor<V4l>); c.CodeTensor_of_V4l_(ref v); return v; } },\r\n            { typeof(Tensor<V4l>[]), c => { var v = default(Tensor<V4l>[]); c.CodeTensor_of_V4l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V4l>>), c => { var v = default(List<Tensor<V4l>>); c.CodeList_of_Tensor_of_V4l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V4f\r\n\r\n            { typeof(V4f), c => { var v = default(V4f); c.CodeV4f(ref v); return v; } },\r\n            { typeof(V4f[]), c => { var v = default(V4f[]); c.CodeV4fArray(ref v); return v; } },\r\n            { typeof(List<V4f>), c => { var v = default(List<V4f>); c.CodeList_of_V4f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V4f>), c => { var v = default(Vector<V4f>); c.CodeVector_of_V4f_(ref v); return v; } },\r\n            { typeof(Vector<V4f>[]), c => { var v = default(Vector<V4f>[]); c.CodeVector_of_V4f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V4f>>), c => { var v = default(List<Vector<V4f>>); c.CodeList_of_Vector_of_V4f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V4f>), c => { var v = default(Matrix<V4f>); c.CodeMatrix_of_V4f_(ref v); return v; } },\r\n            { typeof(Matrix<V4f>[]), c => { var v = default(Matrix<V4f>[]); c.CodeMatrix_of_V4f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V4f>>), c => { var v = default(List<Matrix<V4f>>); c.CodeList_of_Matrix_of_V4f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V4f>), c => { var v = default(Volume<V4f>); c.CodeVolume_of_V4f_(ref v); return v; } },\r\n            { typeof(Volume<V4f>[]), c => { var v = default(Volume<V4f>[]); c.CodeVolume_of_V4f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V4f>>), c => { var v = default(List<Volume<V4f>>); c.CodeList_of_Volume_of_V4f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V4f>), c => { var v = default(Tensor<V4f>); c.CodeTensor_of_V4f_(ref v); return v; } },\r\n            { typeof(Tensor<V4f>[]), c => { var v = default(Tensor<V4f>[]); c.CodeTensor_of_V4f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V4f>>), c => { var v = default(List<Tensor<V4f>>); c.CodeList_of_Tensor_of_V4f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region V4d\r\n\r\n            { typeof(V4d), c => { var v = default(V4d); c.CodeV4d(ref v); return v; } },\r\n            { typeof(V4d[]), c => { var v = default(V4d[]); c.CodeV4dArray(ref v); return v; } },\r\n            { typeof(List<V4d>), c => { var v = default(List<V4d>); c.CodeList_of_V4d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<V4d>), c => { var v = default(Vector<V4d>); c.CodeVector_of_V4d_(ref v); return v; } },\r\n            { typeof(Vector<V4d>[]), c => { var v = default(Vector<V4d>[]); c.CodeVector_of_V4d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<V4d>>), c => { var v = default(List<Vector<V4d>>); c.CodeList_of_Vector_of_V4d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<V4d>), c => { var v = default(Matrix<V4d>); c.CodeMatrix_of_V4d_(ref v); return v; } },\r\n            { typeof(Matrix<V4d>[]), c => { var v = default(Matrix<V4d>[]); c.CodeMatrix_of_V4d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<V4d>>), c => { var v = default(List<Matrix<V4d>>); c.CodeList_of_Matrix_of_V4d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<V4d>), c => { var v = default(Volume<V4d>); c.CodeVolume_of_V4d_(ref v); return v; } },\r\n            { typeof(Volume<V4d>[]), c => { var v = default(Volume<V4d>[]); c.CodeVolume_of_V4d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<V4d>>), c => { var v = default(List<Volume<V4d>>); c.CodeList_of_Volume_of_V4d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<V4d>), c => { var v = default(Tensor<V4d>); c.CodeTensor_of_V4d_(ref v); return v; } },\r\n            { typeof(Tensor<V4d>[]), c => { var v = default(Tensor<V4d>[]); c.CodeTensor_of_V4d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<V4d>>), c => { var v = default(List<Tensor<V4d>>); c.CodeList_of_Tensor_of_V4d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M22i\r\n\r\n            { typeof(M22i), c => { var v = default(M22i); c.CodeM22i(ref v); return v; } },\r\n            { typeof(M22i[]), c => { var v = default(M22i[]); c.CodeM22iArray(ref v); return v; } },\r\n            { typeof(List<M22i>), c => { var v = default(List<M22i>); c.CodeList_of_M22i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M22i>), c => { var v = default(Vector<M22i>); c.CodeVector_of_M22i_(ref v); return v; } },\r\n            { typeof(Vector<M22i>[]), c => { var v = default(Vector<M22i>[]); c.CodeVector_of_M22i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M22i>>), c => { var v = default(List<Vector<M22i>>); c.CodeList_of_Vector_of_M22i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M22i>), c => { var v = default(Matrix<M22i>); c.CodeMatrix_of_M22i_(ref v); return v; } },\r\n            { typeof(Matrix<M22i>[]), c => { var v = default(Matrix<M22i>[]); c.CodeMatrix_of_M22i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M22i>>), c => { var v = default(List<Matrix<M22i>>); c.CodeList_of_Matrix_of_M22i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M22i>), c => { var v = default(Volume<M22i>); c.CodeVolume_of_M22i_(ref v); return v; } },\r\n            { typeof(Volume<M22i>[]), c => { var v = default(Volume<M22i>[]); c.CodeVolume_of_M22i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M22i>>), c => { var v = default(List<Volume<M22i>>); c.CodeList_of_Volume_of_M22i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M22i>), c => { var v = default(Tensor<M22i>); c.CodeTensor_of_M22i_(ref v); return v; } },\r\n            { typeof(Tensor<M22i>[]), c => { var v = default(Tensor<M22i>[]); c.CodeTensor_of_M22i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M22i>>), c => { var v = default(List<Tensor<M22i>>); c.CodeList_of_Tensor_of_M22i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M22l\r\n\r\n            { typeof(M22l), c => { var v = default(M22l); c.CodeM22l(ref v); return v; } },\r\n            { typeof(M22l[]), c => { var v = default(M22l[]); c.CodeM22lArray(ref v); return v; } },\r\n            { typeof(List<M22l>), c => { var v = default(List<M22l>); c.CodeList_of_M22l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M22l>), c => { var v = default(Vector<M22l>); c.CodeVector_of_M22l_(ref v); return v; } },\r\n            { typeof(Vector<M22l>[]), c => { var v = default(Vector<M22l>[]); c.CodeVector_of_M22l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M22l>>), c => { var v = default(List<Vector<M22l>>); c.CodeList_of_Vector_of_M22l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M22l>), c => { var v = default(Matrix<M22l>); c.CodeMatrix_of_M22l_(ref v); return v; } },\r\n            { typeof(Matrix<M22l>[]), c => { var v = default(Matrix<M22l>[]); c.CodeMatrix_of_M22l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M22l>>), c => { var v = default(List<Matrix<M22l>>); c.CodeList_of_Matrix_of_M22l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M22l>), c => { var v = default(Volume<M22l>); c.CodeVolume_of_M22l_(ref v); return v; } },\r\n            { typeof(Volume<M22l>[]), c => { var v = default(Volume<M22l>[]); c.CodeVolume_of_M22l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M22l>>), c => { var v = default(List<Volume<M22l>>); c.CodeList_of_Volume_of_M22l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M22l>), c => { var v = default(Tensor<M22l>); c.CodeTensor_of_M22l_(ref v); return v; } },\r\n            { typeof(Tensor<M22l>[]), c => { var v = default(Tensor<M22l>[]); c.CodeTensor_of_M22l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M22l>>), c => { var v = default(List<Tensor<M22l>>); c.CodeList_of_Tensor_of_M22l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M22f\r\n\r\n            { typeof(M22f), c => { var v = default(M22f); c.CodeM22f(ref v); return v; } },\r\n            { typeof(M22f[]), c => { var v = default(M22f[]); c.CodeM22fArray(ref v); return v; } },\r\n            { typeof(List<M22f>), c => { var v = default(List<M22f>); c.CodeList_of_M22f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M22f>), c => { var v = default(Vector<M22f>); c.CodeVector_of_M22f_(ref v); return v; } },\r\n            { typeof(Vector<M22f>[]), c => { var v = default(Vector<M22f>[]); c.CodeVector_of_M22f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M22f>>), c => { var v = default(List<Vector<M22f>>); c.CodeList_of_Vector_of_M22f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M22f>), c => { var v = default(Matrix<M22f>); c.CodeMatrix_of_M22f_(ref v); return v; } },\r\n            { typeof(Matrix<M22f>[]), c => { var v = default(Matrix<M22f>[]); c.CodeMatrix_of_M22f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M22f>>), c => { var v = default(List<Matrix<M22f>>); c.CodeList_of_Matrix_of_M22f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M22f>), c => { var v = default(Volume<M22f>); c.CodeVolume_of_M22f_(ref v); return v; } },\r\n            { typeof(Volume<M22f>[]), c => { var v = default(Volume<M22f>[]); c.CodeVolume_of_M22f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M22f>>), c => { var v = default(List<Volume<M22f>>); c.CodeList_of_Volume_of_M22f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M22f>), c => { var v = default(Tensor<M22f>); c.CodeTensor_of_M22f_(ref v); return v; } },\r\n            { typeof(Tensor<M22f>[]), c => { var v = default(Tensor<M22f>[]); c.CodeTensor_of_M22f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M22f>>), c => { var v = default(List<Tensor<M22f>>); c.CodeList_of_Tensor_of_M22f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M22d\r\n\r\n            { typeof(M22d), c => { var v = default(M22d); c.CodeM22d(ref v); return v; } },\r\n            { typeof(M22d[]), c => { var v = default(M22d[]); c.CodeM22dArray(ref v); return v; } },\r\n            { typeof(List<M22d>), c => { var v = default(List<M22d>); c.CodeList_of_M22d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M22d>), c => { var v = default(Vector<M22d>); c.CodeVector_of_M22d_(ref v); return v; } },\r\n            { typeof(Vector<M22d>[]), c => { var v = default(Vector<M22d>[]); c.CodeVector_of_M22d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M22d>>), c => { var v = default(List<Vector<M22d>>); c.CodeList_of_Vector_of_M22d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M22d>), c => { var v = default(Matrix<M22d>); c.CodeMatrix_of_M22d_(ref v); return v; } },\r\n            { typeof(Matrix<M22d>[]), c => { var v = default(Matrix<M22d>[]); c.CodeMatrix_of_M22d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M22d>>), c => { var v = default(List<Matrix<M22d>>); c.CodeList_of_Matrix_of_M22d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M22d>), c => { var v = default(Volume<M22d>); c.CodeVolume_of_M22d_(ref v); return v; } },\r\n            { typeof(Volume<M22d>[]), c => { var v = default(Volume<M22d>[]); c.CodeVolume_of_M22d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M22d>>), c => { var v = default(List<Volume<M22d>>); c.CodeList_of_Volume_of_M22d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M22d>), c => { var v = default(Tensor<M22d>); c.CodeTensor_of_M22d_(ref v); return v; } },\r\n            { typeof(Tensor<M22d>[]), c => { var v = default(Tensor<M22d>[]); c.CodeTensor_of_M22d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M22d>>), c => { var v = default(List<Tensor<M22d>>); c.CodeList_of_Tensor_of_M22d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M23i\r\n\r\n            { typeof(M23i), c => { var v = default(M23i); c.CodeM23i(ref v); return v; } },\r\n            { typeof(M23i[]), c => { var v = default(M23i[]); c.CodeM23iArray(ref v); return v; } },\r\n            { typeof(List<M23i>), c => { var v = default(List<M23i>); c.CodeList_of_M23i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M23i>), c => { var v = default(Vector<M23i>); c.CodeVector_of_M23i_(ref v); return v; } },\r\n            { typeof(Vector<M23i>[]), c => { var v = default(Vector<M23i>[]); c.CodeVector_of_M23i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M23i>>), c => { var v = default(List<Vector<M23i>>); c.CodeList_of_Vector_of_M23i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M23i>), c => { var v = default(Matrix<M23i>); c.CodeMatrix_of_M23i_(ref v); return v; } },\r\n            { typeof(Matrix<M23i>[]), c => { var v = default(Matrix<M23i>[]); c.CodeMatrix_of_M23i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M23i>>), c => { var v = default(List<Matrix<M23i>>); c.CodeList_of_Matrix_of_M23i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M23i>), c => { var v = default(Volume<M23i>); c.CodeVolume_of_M23i_(ref v); return v; } },\r\n            { typeof(Volume<M23i>[]), c => { var v = default(Volume<M23i>[]); c.CodeVolume_of_M23i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M23i>>), c => { var v = default(List<Volume<M23i>>); c.CodeList_of_Volume_of_M23i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M23i>), c => { var v = default(Tensor<M23i>); c.CodeTensor_of_M23i_(ref v); return v; } },\r\n            { typeof(Tensor<M23i>[]), c => { var v = default(Tensor<M23i>[]); c.CodeTensor_of_M23i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M23i>>), c => { var v = default(List<Tensor<M23i>>); c.CodeList_of_Tensor_of_M23i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M23l\r\n\r\n            { typeof(M23l), c => { var v = default(M23l); c.CodeM23l(ref v); return v; } },\r\n            { typeof(M23l[]), c => { var v = default(M23l[]); c.CodeM23lArray(ref v); return v; } },\r\n            { typeof(List<M23l>), c => { var v = default(List<M23l>); c.CodeList_of_M23l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M23l>), c => { var v = default(Vector<M23l>); c.CodeVector_of_M23l_(ref v); return v; } },\r\n            { typeof(Vector<M23l>[]), c => { var v = default(Vector<M23l>[]); c.CodeVector_of_M23l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M23l>>), c => { var v = default(List<Vector<M23l>>); c.CodeList_of_Vector_of_M23l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M23l>), c => { var v = default(Matrix<M23l>); c.CodeMatrix_of_M23l_(ref v); return v; } },\r\n            { typeof(Matrix<M23l>[]), c => { var v = default(Matrix<M23l>[]); c.CodeMatrix_of_M23l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M23l>>), c => { var v = default(List<Matrix<M23l>>); c.CodeList_of_Matrix_of_M23l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M23l>), c => { var v = default(Volume<M23l>); c.CodeVolume_of_M23l_(ref v); return v; } },\r\n            { typeof(Volume<M23l>[]), c => { var v = default(Volume<M23l>[]); c.CodeVolume_of_M23l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M23l>>), c => { var v = default(List<Volume<M23l>>); c.CodeList_of_Volume_of_M23l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M23l>), c => { var v = default(Tensor<M23l>); c.CodeTensor_of_M23l_(ref v); return v; } },\r\n            { typeof(Tensor<M23l>[]), c => { var v = default(Tensor<M23l>[]); c.CodeTensor_of_M23l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M23l>>), c => { var v = default(List<Tensor<M23l>>); c.CodeList_of_Tensor_of_M23l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M23f\r\n\r\n            { typeof(M23f), c => { var v = default(M23f); c.CodeM23f(ref v); return v; } },\r\n            { typeof(M23f[]), c => { var v = default(M23f[]); c.CodeM23fArray(ref v); return v; } },\r\n            { typeof(List<M23f>), c => { var v = default(List<M23f>); c.CodeList_of_M23f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M23f>), c => { var v = default(Vector<M23f>); c.CodeVector_of_M23f_(ref v); return v; } },\r\n            { typeof(Vector<M23f>[]), c => { var v = default(Vector<M23f>[]); c.CodeVector_of_M23f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M23f>>), c => { var v = default(List<Vector<M23f>>); c.CodeList_of_Vector_of_M23f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M23f>), c => { var v = default(Matrix<M23f>); c.CodeMatrix_of_M23f_(ref v); return v; } },\r\n            { typeof(Matrix<M23f>[]), c => { var v = default(Matrix<M23f>[]); c.CodeMatrix_of_M23f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M23f>>), c => { var v = default(List<Matrix<M23f>>); c.CodeList_of_Matrix_of_M23f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M23f>), c => { var v = default(Volume<M23f>); c.CodeVolume_of_M23f_(ref v); return v; } },\r\n            { typeof(Volume<M23f>[]), c => { var v = default(Volume<M23f>[]); c.CodeVolume_of_M23f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M23f>>), c => { var v = default(List<Volume<M23f>>); c.CodeList_of_Volume_of_M23f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M23f>), c => { var v = default(Tensor<M23f>); c.CodeTensor_of_M23f_(ref v); return v; } },\r\n            { typeof(Tensor<M23f>[]), c => { var v = default(Tensor<M23f>[]); c.CodeTensor_of_M23f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M23f>>), c => { var v = default(List<Tensor<M23f>>); c.CodeList_of_Tensor_of_M23f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M23d\r\n\r\n            { typeof(M23d), c => { var v = default(M23d); c.CodeM23d(ref v); return v; } },\r\n            { typeof(M23d[]), c => { var v = default(M23d[]); c.CodeM23dArray(ref v); return v; } },\r\n            { typeof(List<M23d>), c => { var v = default(List<M23d>); c.CodeList_of_M23d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M23d>), c => { var v = default(Vector<M23d>); c.CodeVector_of_M23d_(ref v); return v; } },\r\n            { typeof(Vector<M23d>[]), c => { var v = default(Vector<M23d>[]); c.CodeVector_of_M23d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M23d>>), c => { var v = default(List<Vector<M23d>>); c.CodeList_of_Vector_of_M23d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M23d>), c => { var v = default(Matrix<M23d>); c.CodeMatrix_of_M23d_(ref v); return v; } },\r\n            { typeof(Matrix<M23d>[]), c => { var v = default(Matrix<M23d>[]); c.CodeMatrix_of_M23d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M23d>>), c => { var v = default(List<Matrix<M23d>>); c.CodeList_of_Matrix_of_M23d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M23d>), c => { var v = default(Volume<M23d>); c.CodeVolume_of_M23d_(ref v); return v; } },\r\n            { typeof(Volume<M23d>[]), c => { var v = default(Volume<M23d>[]); c.CodeVolume_of_M23d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M23d>>), c => { var v = default(List<Volume<M23d>>); c.CodeList_of_Volume_of_M23d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M23d>), c => { var v = default(Tensor<M23d>); c.CodeTensor_of_M23d_(ref v); return v; } },\r\n            { typeof(Tensor<M23d>[]), c => { var v = default(Tensor<M23d>[]); c.CodeTensor_of_M23d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M23d>>), c => { var v = default(List<Tensor<M23d>>); c.CodeList_of_Tensor_of_M23d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M33i\r\n\r\n            { typeof(M33i), c => { var v = default(M33i); c.CodeM33i(ref v); return v; } },\r\n            { typeof(M33i[]), c => { var v = default(M33i[]); c.CodeM33iArray(ref v); return v; } },\r\n            { typeof(List<M33i>), c => { var v = default(List<M33i>); c.CodeList_of_M33i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M33i>), c => { var v = default(Vector<M33i>); c.CodeVector_of_M33i_(ref v); return v; } },\r\n            { typeof(Vector<M33i>[]), c => { var v = default(Vector<M33i>[]); c.CodeVector_of_M33i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M33i>>), c => { var v = default(List<Vector<M33i>>); c.CodeList_of_Vector_of_M33i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M33i>), c => { var v = default(Matrix<M33i>); c.CodeMatrix_of_M33i_(ref v); return v; } },\r\n            { typeof(Matrix<M33i>[]), c => { var v = default(Matrix<M33i>[]); c.CodeMatrix_of_M33i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M33i>>), c => { var v = default(List<Matrix<M33i>>); c.CodeList_of_Matrix_of_M33i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M33i>), c => { var v = default(Volume<M33i>); c.CodeVolume_of_M33i_(ref v); return v; } },\r\n            { typeof(Volume<M33i>[]), c => { var v = default(Volume<M33i>[]); c.CodeVolume_of_M33i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M33i>>), c => { var v = default(List<Volume<M33i>>); c.CodeList_of_Volume_of_M33i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M33i>), c => { var v = default(Tensor<M33i>); c.CodeTensor_of_M33i_(ref v); return v; } },\r\n            { typeof(Tensor<M33i>[]), c => { var v = default(Tensor<M33i>[]); c.CodeTensor_of_M33i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M33i>>), c => { var v = default(List<Tensor<M33i>>); c.CodeList_of_Tensor_of_M33i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M33l\r\n\r\n            { typeof(M33l), c => { var v = default(M33l); c.CodeM33l(ref v); return v; } },\r\n            { typeof(M33l[]), c => { var v = default(M33l[]); c.CodeM33lArray(ref v); return v; } },\r\n            { typeof(List<M33l>), c => { var v = default(List<M33l>); c.CodeList_of_M33l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M33l>), c => { var v = default(Vector<M33l>); c.CodeVector_of_M33l_(ref v); return v; } },\r\n            { typeof(Vector<M33l>[]), c => { var v = default(Vector<M33l>[]); c.CodeVector_of_M33l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M33l>>), c => { var v = default(List<Vector<M33l>>); c.CodeList_of_Vector_of_M33l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M33l>), c => { var v = default(Matrix<M33l>); c.CodeMatrix_of_M33l_(ref v); return v; } },\r\n            { typeof(Matrix<M33l>[]), c => { var v = default(Matrix<M33l>[]); c.CodeMatrix_of_M33l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M33l>>), c => { var v = default(List<Matrix<M33l>>); c.CodeList_of_Matrix_of_M33l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M33l>), c => { var v = default(Volume<M33l>); c.CodeVolume_of_M33l_(ref v); return v; } },\r\n            { typeof(Volume<M33l>[]), c => { var v = default(Volume<M33l>[]); c.CodeVolume_of_M33l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M33l>>), c => { var v = default(List<Volume<M33l>>); c.CodeList_of_Volume_of_M33l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M33l>), c => { var v = default(Tensor<M33l>); c.CodeTensor_of_M33l_(ref v); return v; } },\r\n            { typeof(Tensor<M33l>[]), c => { var v = default(Tensor<M33l>[]); c.CodeTensor_of_M33l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M33l>>), c => { var v = default(List<Tensor<M33l>>); c.CodeList_of_Tensor_of_M33l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M33f\r\n\r\n            { typeof(M33f), c => { var v = default(M33f); c.CodeM33f(ref v); return v; } },\r\n            { typeof(M33f[]), c => { var v = default(M33f[]); c.CodeM33fArray(ref v); return v; } },\r\n            { typeof(List<M33f>), c => { var v = default(List<M33f>); c.CodeList_of_M33f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M33f>), c => { var v = default(Vector<M33f>); c.CodeVector_of_M33f_(ref v); return v; } },\r\n            { typeof(Vector<M33f>[]), c => { var v = default(Vector<M33f>[]); c.CodeVector_of_M33f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M33f>>), c => { var v = default(List<Vector<M33f>>); c.CodeList_of_Vector_of_M33f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M33f>), c => { var v = default(Matrix<M33f>); c.CodeMatrix_of_M33f_(ref v); return v; } },\r\n            { typeof(Matrix<M33f>[]), c => { var v = default(Matrix<M33f>[]); c.CodeMatrix_of_M33f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M33f>>), c => { var v = default(List<Matrix<M33f>>); c.CodeList_of_Matrix_of_M33f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M33f>), c => { var v = default(Volume<M33f>); c.CodeVolume_of_M33f_(ref v); return v; } },\r\n            { typeof(Volume<M33f>[]), c => { var v = default(Volume<M33f>[]); c.CodeVolume_of_M33f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M33f>>), c => { var v = default(List<Volume<M33f>>); c.CodeList_of_Volume_of_M33f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M33f>), c => { var v = default(Tensor<M33f>); c.CodeTensor_of_M33f_(ref v); return v; } },\r\n            { typeof(Tensor<M33f>[]), c => { var v = default(Tensor<M33f>[]); c.CodeTensor_of_M33f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M33f>>), c => { var v = default(List<Tensor<M33f>>); c.CodeList_of_Tensor_of_M33f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M33d\r\n\r\n            { typeof(M33d), c => { var v = default(M33d); c.CodeM33d(ref v); return v; } },\r\n            { typeof(M33d[]), c => { var v = default(M33d[]); c.CodeM33dArray(ref v); return v; } },\r\n            { typeof(List<M33d>), c => { var v = default(List<M33d>); c.CodeList_of_M33d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M33d>), c => { var v = default(Vector<M33d>); c.CodeVector_of_M33d_(ref v); return v; } },\r\n            { typeof(Vector<M33d>[]), c => { var v = default(Vector<M33d>[]); c.CodeVector_of_M33d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M33d>>), c => { var v = default(List<Vector<M33d>>); c.CodeList_of_Vector_of_M33d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M33d>), c => { var v = default(Matrix<M33d>); c.CodeMatrix_of_M33d_(ref v); return v; } },\r\n            { typeof(Matrix<M33d>[]), c => { var v = default(Matrix<M33d>[]); c.CodeMatrix_of_M33d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M33d>>), c => { var v = default(List<Matrix<M33d>>); c.CodeList_of_Matrix_of_M33d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M33d>), c => { var v = default(Volume<M33d>); c.CodeVolume_of_M33d_(ref v); return v; } },\r\n            { typeof(Volume<M33d>[]), c => { var v = default(Volume<M33d>[]); c.CodeVolume_of_M33d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M33d>>), c => { var v = default(List<Volume<M33d>>); c.CodeList_of_Volume_of_M33d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M33d>), c => { var v = default(Tensor<M33d>); c.CodeTensor_of_M33d_(ref v); return v; } },\r\n            { typeof(Tensor<M33d>[]), c => { var v = default(Tensor<M33d>[]); c.CodeTensor_of_M33d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M33d>>), c => { var v = default(List<Tensor<M33d>>); c.CodeList_of_Tensor_of_M33d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M34i\r\n\r\n            { typeof(M34i), c => { var v = default(M34i); c.CodeM34i(ref v); return v; } },\r\n            { typeof(M34i[]), c => { var v = default(M34i[]); c.CodeM34iArray(ref v); return v; } },\r\n            { typeof(List<M34i>), c => { var v = default(List<M34i>); c.CodeList_of_M34i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M34i>), c => { var v = default(Vector<M34i>); c.CodeVector_of_M34i_(ref v); return v; } },\r\n            { typeof(Vector<M34i>[]), c => { var v = default(Vector<M34i>[]); c.CodeVector_of_M34i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M34i>>), c => { var v = default(List<Vector<M34i>>); c.CodeList_of_Vector_of_M34i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M34i>), c => { var v = default(Matrix<M34i>); c.CodeMatrix_of_M34i_(ref v); return v; } },\r\n            { typeof(Matrix<M34i>[]), c => { var v = default(Matrix<M34i>[]); c.CodeMatrix_of_M34i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M34i>>), c => { var v = default(List<Matrix<M34i>>); c.CodeList_of_Matrix_of_M34i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M34i>), c => { var v = default(Volume<M34i>); c.CodeVolume_of_M34i_(ref v); return v; } },\r\n            { typeof(Volume<M34i>[]), c => { var v = default(Volume<M34i>[]); c.CodeVolume_of_M34i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M34i>>), c => { var v = default(List<Volume<M34i>>); c.CodeList_of_Volume_of_M34i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M34i>), c => { var v = default(Tensor<M34i>); c.CodeTensor_of_M34i_(ref v); return v; } },\r\n            { typeof(Tensor<M34i>[]), c => { var v = default(Tensor<M34i>[]); c.CodeTensor_of_M34i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M34i>>), c => { var v = default(List<Tensor<M34i>>); c.CodeList_of_Tensor_of_M34i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M34l\r\n\r\n            { typeof(M34l), c => { var v = default(M34l); c.CodeM34l(ref v); return v; } },\r\n            { typeof(M34l[]), c => { var v = default(M34l[]); c.CodeM34lArray(ref v); return v; } },\r\n            { typeof(List<M34l>), c => { var v = default(List<M34l>); c.CodeList_of_M34l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M34l>), c => { var v = default(Vector<M34l>); c.CodeVector_of_M34l_(ref v); return v; } },\r\n            { typeof(Vector<M34l>[]), c => { var v = default(Vector<M34l>[]); c.CodeVector_of_M34l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M34l>>), c => { var v = default(List<Vector<M34l>>); c.CodeList_of_Vector_of_M34l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M34l>), c => { var v = default(Matrix<M34l>); c.CodeMatrix_of_M34l_(ref v); return v; } },\r\n            { typeof(Matrix<M34l>[]), c => { var v = default(Matrix<M34l>[]); c.CodeMatrix_of_M34l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M34l>>), c => { var v = default(List<Matrix<M34l>>); c.CodeList_of_Matrix_of_M34l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M34l>), c => { var v = default(Volume<M34l>); c.CodeVolume_of_M34l_(ref v); return v; } },\r\n            { typeof(Volume<M34l>[]), c => { var v = default(Volume<M34l>[]); c.CodeVolume_of_M34l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M34l>>), c => { var v = default(List<Volume<M34l>>); c.CodeList_of_Volume_of_M34l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M34l>), c => { var v = default(Tensor<M34l>); c.CodeTensor_of_M34l_(ref v); return v; } },\r\n            { typeof(Tensor<M34l>[]), c => { var v = default(Tensor<M34l>[]); c.CodeTensor_of_M34l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M34l>>), c => { var v = default(List<Tensor<M34l>>); c.CodeList_of_Tensor_of_M34l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M34f\r\n\r\n            { typeof(M34f), c => { var v = default(M34f); c.CodeM34f(ref v); return v; } },\r\n            { typeof(M34f[]), c => { var v = default(M34f[]); c.CodeM34fArray(ref v); return v; } },\r\n            { typeof(List<M34f>), c => { var v = default(List<M34f>); c.CodeList_of_M34f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M34f>), c => { var v = default(Vector<M34f>); c.CodeVector_of_M34f_(ref v); return v; } },\r\n            { typeof(Vector<M34f>[]), c => { var v = default(Vector<M34f>[]); c.CodeVector_of_M34f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M34f>>), c => { var v = default(List<Vector<M34f>>); c.CodeList_of_Vector_of_M34f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M34f>), c => { var v = default(Matrix<M34f>); c.CodeMatrix_of_M34f_(ref v); return v; } },\r\n            { typeof(Matrix<M34f>[]), c => { var v = default(Matrix<M34f>[]); c.CodeMatrix_of_M34f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M34f>>), c => { var v = default(List<Matrix<M34f>>); c.CodeList_of_Matrix_of_M34f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M34f>), c => { var v = default(Volume<M34f>); c.CodeVolume_of_M34f_(ref v); return v; } },\r\n            { typeof(Volume<M34f>[]), c => { var v = default(Volume<M34f>[]); c.CodeVolume_of_M34f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M34f>>), c => { var v = default(List<Volume<M34f>>); c.CodeList_of_Volume_of_M34f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M34f>), c => { var v = default(Tensor<M34f>); c.CodeTensor_of_M34f_(ref v); return v; } },\r\n            { typeof(Tensor<M34f>[]), c => { var v = default(Tensor<M34f>[]); c.CodeTensor_of_M34f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M34f>>), c => { var v = default(List<Tensor<M34f>>); c.CodeList_of_Tensor_of_M34f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M34d\r\n\r\n            { typeof(M34d), c => { var v = default(M34d); c.CodeM34d(ref v); return v; } },\r\n            { typeof(M34d[]), c => { var v = default(M34d[]); c.CodeM34dArray(ref v); return v; } },\r\n            { typeof(List<M34d>), c => { var v = default(List<M34d>); c.CodeList_of_M34d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M34d>), c => { var v = default(Vector<M34d>); c.CodeVector_of_M34d_(ref v); return v; } },\r\n            { typeof(Vector<M34d>[]), c => { var v = default(Vector<M34d>[]); c.CodeVector_of_M34d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M34d>>), c => { var v = default(List<Vector<M34d>>); c.CodeList_of_Vector_of_M34d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M34d>), c => { var v = default(Matrix<M34d>); c.CodeMatrix_of_M34d_(ref v); return v; } },\r\n            { typeof(Matrix<M34d>[]), c => { var v = default(Matrix<M34d>[]); c.CodeMatrix_of_M34d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M34d>>), c => { var v = default(List<Matrix<M34d>>); c.CodeList_of_Matrix_of_M34d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M34d>), c => { var v = default(Volume<M34d>); c.CodeVolume_of_M34d_(ref v); return v; } },\r\n            { typeof(Volume<M34d>[]), c => { var v = default(Volume<M34d>[]); c.CodeVolume_of_M34d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M34d>>), c => { var v = default(List<Volume<M34d>>); c.CodeList_of_Volume_of_M34d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M34d>), c => { var v = default(Tensor<M34d>); c.CodeTensor_of_M34d_(ref v); return v; } },\r\n            { typeof(Tensor<M34d>[]), c => { var v = default(Tensor<M34d>[]); c.CodeTensor_of_M34d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M34d>>), c => { var v = default(List<Tensor<M34d>>); c.CodeList_of_Tensor_of_M34d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M44i\r\n\r\n            { typeof(M44i), c => { var v = default(M44i); c.CodeM44i(ref v); return v; } },\r\n            { typeof(M44i[]), c => { var v = default(M44i[]); c.CodeM44iArray(ref v); return v; } },\r\n            { typeof(List<M44i>), c => { var v = default(List<M44i>); c.CodeList_of_M44i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M44i>), c => { var v = default(Vector<M44i>); c.CodeVector_of_M44i_(ref v); return v; } },\r\n            { typeof(Vector<M44i>[]), c => { var v = default(Vector<M44i>[]); c.CodeVector_of_M44i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M44i>>), c => { var v = default(List<Vector<M44i>>); c.CodeList_of_Vector_of_M44i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M44i>), c => { var v = default(Matrix<M44i>); c.CodeMatrix_of_M44i_(ref v); return v; } },\r\n            { typeof(Matrix<M44i>[]), c => { var v = default(Matrix<M44i>[]); c.CodeMatrix_of_M44i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M44i>>), c => { var v = default(List<Matrix<M44i>>); c.CodeList_of_Matrix_of_M44i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M44i>), c => { var v = default(Volume<M44i>); c.CodeVolume_of_M44i_(ref v); return v; } },\r\n            { typeof(Volume<M44i>[]), c => { var v = default(Volume<M44i>[]); c.CodeVolume_of_M44i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M44i>>), c => { var v = default(List<Volume<M44i>>); c.CodeList_of_Volume_of_M44i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M44i>), c => { var v = default(Tensor<M44i>); c.CodeTensor_of_M44i_(ref v); return v; } },\r\n            { typeof(Tensor<M44i>[]), c => { var v = default(Tensor<M44i>[]); c.CodeTensor_of_M44i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M44i>>), c => { var v = default(List<Tensor<M44i>>); c.CodeList_of_Tensor_of_M44i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M44l\r\n\r\n            { typeof(M44l), c => { var v = default(M44l); c.CodeM44l(ref v); return v; } },\r\n            { typeof(M44l[]), c => { var v = default(M44l[]); c.CodeM44lArray(ref v); return v; } },\r\n            { typeof(List<M44l>), c => { var v = default(List<M44l>); c.CodeList_of_M44l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M44l>), c => { var v = default(Vector<M44l>); c.CodeVector_of_M44l_(ref v); return v; } },\r\n            { typeof(Vector<M44l>[]), c => { var v = default(Vector<M44l>[]); c.CodeVector_of_M44l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M44l>>), c => { var v = default(List<Vector<M44l>>); c.CodeList_of_Vector_of_M44l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M44l>), c => { var v = default(Matrix<M44l>); c.CodeMatrix_of_M44l_(ref v); return v; } },\r\n            { typeof(Matrix<M44l>[]), c => { var v = default(Matrix<M44l>[]); c.CodeMatrix_of_M44l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M44l>>), c => { var v = default(List<Matrix<M44l>>); c.CodeList_of_Matrix_of_M44l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M44l>), c => { var v = default(Volume<M44l>); c.CodeVolume_of_M44l_(ref v); return v; } },\r\n            { typeof(Volume<M44l>[]), c => { var v = default(Volume<M44l>[]); c.CodeVolume_of_M44l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M44l>>), c => { var v = default(List<Volume<M44l>>); c.CodeList_of_Volume_of_M44l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M44l>), c => { var v = default(Tensor<M44l>); c.CodeTensor_of_M44l_(ref v); return v; } },\r\n            { typeof(Tensor<M44l>[]), c => { var v = default(Tensor<M44l>[]); c.CodeTensor_of_M44l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M44l>>), c => { var v = default(List<Tensor<M44l>>); c.CodeList_of_Tensor_of_M44l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M44f\r\n\r\n            { typeof(M44f), c => { var v = default(M44f); c.CodeM44f(ref v); return v; } },\r\n            { typeof(M44f[]), c => { var v = default(M44f[]); c.CodeM44fArray(ref v); return v; } },\r\n            { typeof(List<M44f>), c => { var v = default(List<M44f>); c.CodeList_of_M44f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M44f>), c => { var v = default(Vector<M44f>); c.CodeVector_of_M44f_(ref v); return v; } },\r\n            { typeof(Vector<M44f>[]), c => { var v = default(Vector<M44f>[]); c.CodeVector_of_M44f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M44f>>), c => { var v = default(List<Vector<M44f>>); c.CodeList_of_Vector_of_M44f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M44f>), c => { var v = default(Matrix<M44f>); c.CodeMatrix_of_M44f_(ref v); return v; } },\r\n            { typeof(Matrix<M44f>[]), c => { var v = default(Matrix<M44f>[]); c.CodeMatrix_of_M44f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M44f>>), c => { var v = default(List<Matrix<M44f>>); c.CodeList_of_Matrix_of_M44f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M44f>), c => { var v = default(Volume<M44f>); c.CodeVolume_of_M44f_(ref v); return v; } },\r\n            { typeof(Volume<M44f>[]), c => { var v = default(Volume<M44f>[]); c.CodeVolume_of_M44f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M44f>>), c => { var v = default(List<Volume<M44f>>); c.CodeList_of_Volume_of_M44f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M44f>), c => { var v = default(Tensor<M44f>); c.CodeTensor_of_M44f_(ref v); return v; } },\r\n            { typeof(Tensor<M44f>[]), c => { var v = default(Tensor<M44f>[]); c.CodeTensor_of_M44f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M44f>>), c => { var v = default(List<Tensor<M44f>>); c.CodeList_of_Tensor_of_M44f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region M44d\r\n\r\n            { typeof(M44d), c => { var v = default(M44d); c.CodeM44d(ref v); return v; } },\r\n            { typeof(M44d[]), c => { var v = default(M44d[]); c.CodeM44dArray(ref v); return v; } },\r\n            { typeof(List<M44d>), c => { var v = default(List<M44d>); c.CodeList_of_M44d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<M44d>), c => { var v = default(Vector<M44d>); c.CodeVector_of_M44d_(ref v); return v; } },\r\n            { typeof(Vector<M44d>[]), c => { var v = default(Vector<M44d>[]); c.CodeVector_of_M44d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<M44d>>), c => { var v = default(List<Vector<M44d>>); c.CodeList_of_Vector_of_M44d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<M44d>), c => { var v = default(Matrix<M44d>); c.CodeMatrix_of_M44d_(ref v); return v; } },\r\n            { typeof(Matrix<M44d>[]), c => { var v = default(Matrix<M44d>[]); c.CodeMatrix_of_M44d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<M44d>>), c => { var v = default(List<Matrix<M44d>>); c.CodeList_of_Matrix_of_M44d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<M44d>), c => { var v = default(Volume<M44d>); c.CodeVolume_of_M44d_(ref v); return v; } },\r\n            { typeof(Volume<M44d>[]), c => { var v = default(Volume<M44d>[]); c.CodeVolume_of_M44d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<M44d>>), c => { var v = default(List<Volume<M44d>>); c.CodeList_of_Volume_of_M44d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<M44d>), c => { var v = default(Tensor<M44d>); c.CodeTensor_of_M44d_(ref v); return v; } },\r\n            { typeof(Tensor<M44d>[]), c => { var v = default(Tensor<M44d>[]); c.CodeTensor_of_M44d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<M44d>>), c => { var v = default(List<Tensor<M44d>>); c.CodeList_of_Tensor_of_M44d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C3b\r\n\r\n            { typeof(C3b), c => { var v = default(C3b); c.CodeC3b(ref v); return v; } },\r\n            { typeof(C3b[]), c => { var v = default(C3b[]); c.CodeC3bArray(ref v); return v; } },\r\n            { typeof(List<C3b>), c => { var v = default(List<C3b>); c.CodeList_of_C3b_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C3b>), c => { var v = default(Vector<C3b>); c.CodeVector_of_C3b_(ref v); return v; } },\r\n            { typeof(Vector<C3b>[]), c => { var v = default(Vector<C3b>[]); c.CodeVector_of_C3b_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C3b>>), c => { var v = default(List<Vector<C3b>>); c.CodeList_of_Vector_of_C3b__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C3b>), c => { var v = default(Matrix<C3b>); c.CodeMatrix_of_C3b_(ref v); return v; } },\r\n            { typeof(Matrix<C3b>[]), c => { var v = default(Matrix<C3b>[]); c.CodeMatrix_of_C3b_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C3b>>), c => { var v = default(List<Matrix<C3b>>); c.CodeList_of_Matrix_of_C3b__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C3b>), c => { var v = default(Volume<C3b>); c.CodeVolume_of_C3b_(ref v); return v; } },\r\n            { typeof(Volume<C3b>[]), c => { var v = default(Volume<C3b>[]); c.CodeVolume_of_C3b_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C3b>>), c => { var v = default(List<Volume<C3b>>); c.CodeList_of_Volume_of_C3b__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C3b>), c => { var v = default(Tensor<C3b>); c.CodeTensor_of_C3b_(ref v); return v; } },\r\n            { typeof(Tensor<C3b>[]), c => { var v = default(Tensor<C3b>[]); c.CodeTensor_of_C3b_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C3b>>), c => { var v = default(List<Tensor<C3b>>); c.CodeList_of_Tensor_of_C3b__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C3us\r\n\r\n            { typeof(C3us), c => { var v = default(C3us); c.CodeC3us(ref v); return v; } },\r\n            { typeof(C3us[]), c => { var v = default(C3us[]); c.CodeC3usArray(ref v); return v; } },\r\n            { typeof(List<C3us>), c => { var v = default(List<C3us>); c.CodeList_of_C3us_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C3us>), c => { var v = default(Vector<C3us>); c.CodeVector_of_C3us_(ref v); return v; } },\r\n            { typeof(Vector<C3us>[]), c => { var v = default(Vector<C3us>[]); c.CodeVector_of_C3us_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C3us>>), c => { var v = default(List<Vector<C3us>>); c.CodeList_of_Vector_of_C3us__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C3us>), c => { var v = default(Matrix<C3us>); c.CodeMatrix_of_C3us_(ref v); return v; } },\r\n            { typeof(Matrix<C3us>[]), c => { var v = default(Matrix<C3us>[]); c.CodeMatrix_of_C3us_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C3us>>), c => { var v = default(List<Matrix<C3us>>); c.CodeList_of_Matrix_of_C3us__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C3us>), c => { var v = default(Volume<C3us>); c.CodeVolume_of_C3us_(ref v); return v; } },\r\n            { typeof(Volume<C3us>[]), c => { var v = default(Volume<C3us>[]); c.CodeVolume_of_C3us_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C3us>>), c => { var v = default(List<Volume<C3us>>); c.CodeList_of_Volume_of_C3us__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C3us>), c => { var v = default(Tensor<C3us>); c.CodeTensor_of_C3us_(ref v); return v; } },\r\n            { typeof(Tensor<C3us>[]), c => { var v = default(Tensor<C3us>[]); c.CodeTensor_of_C3us_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C3us>>), c => { var v = default(List<Tensor<C3us>>); c.CodeList_of_Tensor_of_C3us__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C3ui\r\n\r\n            { typeof(C3ui), c => { var v = default(C3ui); c.CodeC3ui(ref v); return v; } },\r\n            { typeof(C3ui[]), c => { var v = default(C3ui[]); c.CodeC3uiArray(ref v); return v; } },\r\n            { typeof(List<C3ui>), c => { var v = default(List<C3ui>); c.CodeList_of_C3ui_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C3ui>), c => { var v = default(Vector<C3ui>); c.CodeVector_of_C3ui_(ref v); return v; } },\r\n            { typeof(Vector<C3ui>[]), c => { var v = default(Vector<C3ui>[]); c.CodeVector_of_C3ui_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C3ui>>), c => { var v = default(List<Vector<C3ui>>); c.CodeList_of_Vector_of_C3ui__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C3ui>), c => { var v = default(Matrix<C3ui>); c.CodeMatrix_of_C3ui_(ref v); return v; } },\r\n            { typeof(Matrix<C3ui>[]), c => { var v = default(Matrix<C3ui>[]); c.CodeMatrix_of_C3ui_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C3ui>>), c => { var v = default(List<Matrix<C3ui>>); c.CodeList_of_Matrix_of_C3ui__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C3ui>), c => { var v = default(Volume<C3ui>); c.CodeVolume_of_C3ui_(ref v); return v; } },\r\n            { typeof(Volume<C3ui>[]), c => { var v = default(Volume<C3ui>[]); c.CodeVolume_of_C3ui_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C3ui>>), c => { var v = default(List<Volume<C3ui>>); c.CodeList_of_Volume_of_C3ui__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C3ui>), c => { var v = default(Tensor<C3ui>); c.CodeTensor_of_C3ui_(ref v); return v; } },\r\n            { typeof(Tensor<C3ui>[]), c => { var v = default(Tensor<C3ui>[]); c.CodeTensor_of_C3ui_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C3ui>>), c => { var v = default(List<Tensor<C3ui>>); c.CodeList_of_Tensor_of_C3ui__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C3f\r\n\r\n            { typeof(C3f), c => { var v = default(C3f); c.CodeC3f(ref v); return v; } },\r\n            { typeof(C3f[]), c => { var v = default(C3f[]); c.CodeC3fArray(ref v); return v; } },\r\n            { typeof(List<C3f>), c => { var v = default(List<C3f>); c.CodeList_of_C3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C3f>), c => { var v = default(Vector<C3f>); c.CodeVector_of_C3f_(ref v); return v; } },\r\n            { typeof(Vector<C3f>[]), c => { var v = default(Vector<C3f>[]); c.CodeVector_of_C3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C3f>>), c => { var v = default(List<Vector<C3f>>); c.CodeList_of_Vector_of_C3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C3f>), c => { var v = default(Matrix<C3f>); c.CodeMatrix_of_C3f_(ref v); return v; } },\r\n            { typeof(Matrix<C3f>[]), c => { var v = default(Matrix<C3f>[]); c.CodeMatrix_of_C3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C3f>>), c => { var v = default(List<Matrix<C3f>>); c.CodeList_of_Matrix_of_C3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C3f>), c => { var v = default(Volume<C3f>); c.CodeVolume_of_C3f_(ref v); return v; } },\r\n            { typeof(Volume<C3f>[]), c => { var v = default(Volume<C3f>[]); c.CodeVolume_of_C3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C3f>>), c => { var v = default(List<Volume<C3f>>); c.CodeList_of_Volume_of_C3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C3f>), c => { var v = default(Tensor<C3f>); c.CodeTensor_of_C3f_(ref v); return v; } },\r\n            { typeof(Tensor<C3f>[]), c => { var v = default(Tensor<C3f>[]); c.CodeTensor_of_C3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C3f>>), c => { var v = default(List<Tensor<C3f>>); c.CodeList_of_Tensor_of_C3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C3d\r\n\r\n            { typeof(C3d), c => { var v = default(C3d); c.CodeC3d(ref v); return v; } },\r\n            { typeof(C3d[]), c => { var v = default(C3d[]); c.CodeC3dArray(ref v); return v; } },\r\n            { typeof(List<C3d>), c => { var v = default(List<C3d>); c.CodeList_of_C3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C3d>), c => { var v = default(Vector<C3d>); c.CodeVector_of_C3d_(ref v); return v; } },\r\n            { typeof(Vector<C3d>[]), c => { var v = default(Vector<C3d>[]); c.CodeVector_of_C3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C3d>>), c => { var v = default(List<Vector<C3d>>); c.CodeList_of_Vector_of_C3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C3d>), c => { var v = default(Matrix<C3d>); c.CodeMatrix_of_C3d_(ref v); return v; } },\r\n            { typeof(Matrix<C3d>[]), c => { var v = default(Matrix<C3d>[]); c.CodeMatrix_of_C3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C3d>>), c => { var v = default(List<Matrix<C3d>>); c.CodeList_of_Matrix_of_C3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C3d>), c => { var v = default(Volume<C3d>); c.CodeVolume_of_C3d_(ref v); return v; } },\r\n            { typeof(Volume<C3d>[]), c => { var v = default(Volume<C3d>[]); c.CodeVolume_of_C3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C3d>>), c => { var v = default(List<Volume<C3d>>); c.CodeList_of_Volume_of_C3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C3d>), c => { var v = default(Tensor<C3d>); c.CodeTensor_of_C3d_(ref v); return v; } },\r\n            { typeof(Tensor<C3d>[]), c => { var v = default(Tensor<C3d>[]); c.CodeTensor_of_C3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C3d>>), c => { var v = default(List<Tensor<C3d>>); c.CodeList_of_Tensor_of_C3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C4b\r\n\r\n            { typeof(C4b), c => { var v = default(C4b); c.CodeC4b(ref v); return v; } },\r\n            { typeof(C4b[]), c => { var v = default(C4b[]); c.CodeC4bArray(ref v); return v; } },\r\n            { typeof(List<C4b>), c => { var v = default(List<C4b>); c.CodeList_of_C4b_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C4b>), c => { var v = default(Vector<C4b>); c.CodeVector_of_C4b_(ref v); return v; } },\r\n            { typeof(Vector<C4b>[]), c => { var v = default(Vector<C4b>[]); c.CodeVector_of_C4b_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C4b>>), c => { var v = default(List<Vector<C4b>>); c.CodeList_of_Vector_of_C4b__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C4b>), c => { var v = default(Matrix<C4b>); c.CodeMatrix_of_C4b_(ref v); return v; } },\r\n            { typeof(Matrix<C4b>[]), c => { var v = default(Matrix<C4b>[]); c.CodeMatrix_of_C4b_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C4b>>), c => { var v = default(List<Matrix<C4b>>); c.CodeList_of_Matrix_of_C4b__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C4b>), c => { var v = default(Volume<C4b>); c.CodeVolume_of_C4b_(ref v); return v; } },\r\n            { typeof(Volume<C4b>[]), c => { var v = default(Volume<C4b>[]); c.CodeVolume_of_C4b_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C4b>>), c => { var v = default(List<Volume<C4b>>); c.CodeList_of_Volume_of_C4b__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C4b>), c => { var v = default(Tensor<C4b>); c.CodeTensor_of_C4b_(ref v); return v; } },\r\n            { typeof(Tensor<C4b>[]), c => { var v = default(Tensor<C4b>[]); c.CodeTensor_of_C4b_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C4b>>), c => { var v = default(List<Tensor<C4b>>); c.CodeList_of_Tensor_of_C4b__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C4us\r\n\r\n            { typeof(C4us), c => { var v = default(C4us); c.CodeC4us(ref v); return v; } },\r\n            { typeof(C4us[]), c => { var v = default(C4us[]); c.CodeC4usArray(ref v); return v; } },\r\n            { typeof(List<C4us>), c => { var v = default(List<C4us>); c.CodeList_of_C4us_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C4us>), c => { var v = default(Vector<C4us>); c.CodeVector_of_C4us_(ref v); return v; } },\r\n            { typeof(Vector<C4us>[]), c => { var v = default(Vector<C4us>[]); c.CodeVector_of_C4us_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C4us>>), c => { var v = default(List<Vector<C4us>>); c.CodeList_of_Vector_of_C4us__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C4us>), c => { var v = default(Matrix<C4us>); c.CodeMatrix_of_C4us_(ref v); return v; } },\r\n            { typeof(Matrix<C4us>[]), c => { var v = default(Matrix<C4us>[]); c.CodeMatrix_of_C4us_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C4us>>), c => { var v = default(List<Matrix<C4us>>); c.CodeList_of_Matrix_of_C4us__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C4us>), c => { var v = default(Volume<C4us>); c.CodeVolume_of_C4us_(ref v); return v; } },\r\n            { typeof(Volume<C4us>[]), c => { var v = default(Volume<C4us>[]); c.CodeVolume_of_C4us_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C4us>>), c => { var v = default(List<Volume<C4us>>); c.CodeList_of_Volume_of_C4us__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C4us>), c => { var v = default(Tensor<C4us>); c.CodeTensor_of_C4us_(ref v); return v; } },\r\n            { typeof(Tensor<C4us>[]), c => { var v = default(Tensor<C4us>[]); c.CodeTensor_of_C4us_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C4us>>), c => { var v = default(List<Tensor<C4us>>); c.CodeList_of_Tensor_of_C4us__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C4ui\r\n\r\n            { typeof(C4ui), c => { var v = default(C4ui); c.CodeC4ui(ref v); return v; } },\r\n            { typeof(C4ui[]), c => { var v = default(C4ui[]); c.CodeC4uiArray(ref v); return v; } },\r\n            { typeof(List<C4ui>), c => { var v = default(List<C4ui>); c.CodeList_of_C4ui_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C4ui>), c => { var v = default(Vector<C4ui>); c.CodeVector_of_C4ui_(ref v); return v; } },\r\n            { typeof(Vector<C4ui>[]), c => { var v = default(Vector<C4ui>[]); c.CodeVector_of_C4ui_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C4ui>>), c => { var v = default(List<Vector<C4ui>>); c.CodeList_of_Vector_of_C4ui__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C4ui>), c => { var v = default(Matrix<C4ui>); c.CodeMatrix_of_C4ui_(ref v); return v; } },\r\n            { typeof(Matrix<C4ui>[]), c => { var v = default(Matrix<C4ui>[]); c.CodeMatrix_of_C4ui_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C4ui>>), c => { var v = default(List<Matrix<C4ui>>); c.CodeList_of_Matrix_of_C4ui__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C4ui>), c => { var v = default(Volume<C4ui>); c.CodeVolume_of_C4ui_(ref v); return v; } },\r\n            { typeof(Volume<C4ui>[]), c => { var v = default(Volume<C4ui>[]); c.CodeVolume_of_C4ui_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C4ui>>), c => { var v = default(List<Volume<C4ui>>); c.CodeList_of_Volume_of_C4ui__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C4ui>), c => { var v = default(Tensor<C4ui>); c.CodeTensor_of_C4ui_(ref v); return v; } },\r\n            { typeof(Tensor<C4ui>[]), c => { var v = default(Tensor<C4ui>[]); c.CodeTensor_of_C4ui_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C4ui>>), c => { var v = default(List<Tensor<C4ui>>); c.CodeList_of_Tensor_of_C4ui__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C4f\r\n\r\n            { typeof(C4f), c => { var v = default(C4f); c.CodeC4f(ref v); return v; } },\r\n            { typeof(C4f[]), c => { var v = default(C4f[]); c.CodeC4fArray(ref v); return v; } },\r\n            { typeof(List<C4f>), c => { var v = default(List<C4f>); c.CodeList_of_C4f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C4f>), c => { var v = default(Vector<C4f>); c.CodeVector_of_C4f_(ref v); return v; } },\r\n            { typeof(Vector<C4f>[]), c => { var v = default(Vector<C4f>[]); c.CodeVector_of_C4f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C4f>>), c => { var v = default(List<Vector<C4f>>); c.CodeList_of_Vector_of_C4f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C4f>), c => { var v = default(Matrix<C4f>); c.CodeMatrix_of_C4f_(ref v); return v; } },\r\n            { typeof(Matrix<C4f>[]), c => { var v = default(Matrix<C4f>[]); c.CodeMatrix_of_C4f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C4f>>), c => { var v = default(List<Matrix<C4f>>); c.CodeList_of_Matrix_of_C4f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C4f>), c => { var v = default(Volume<C4f>); c.CodeVolume_of_C4f_(ref v); return v; } },\r\n            { typeof(Volume<C4f>[]), c => { var v = default(Volume<C4f>[]); c.CodeVolume_of_C4f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C4f>>), c => { var v = default(List<Volume<C4f>>); c.CodeList_of_Volume_of_C4f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C4f>), c => { var v = default(Tensor<C4f>); c.CodeTensor_of_C4f_(ref v); return v; } },\r\n            { typeof(Tensor<C4f>[]), c => { var v = default(Tensor<C4f>[]); c.CodeTensor_of_C4f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C4f>>), c => { var v = default(List<Tensor<C4f>>); c.CodeList_of_Tensor_of_C4f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region C4d\r\n\r\n            { typeof(C4d), c => { var v = default(C4d); c.CodeC4d(ref v); return v; } },\r\n            { typeof(C4d[]), c => { var v = default(C4d[]); c.CodeC4dArray(ref v); return v; } },\r\n            { typeof(List<C4d>), c => { var v = default(List<C4d>); c.CodeList_of_C4d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<C4d>), c => { var v = default(Vector<C4d>); c.CodeVector_of_C4d_(ref v); return v; } },\r\n            { typeof(Vector<C4d>[]), c => { var v = default(Vector<C4d>[]); c.CodeVector_of_C4d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<C4d>>), c => { var v = default(List<Vector<C4d>>); c.CodeList_of_Vector_of_C4d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<C4d>), c => { var v = default(Matrix<C4d>); c.CodeMatrix_of_C4d_(ref v); return v; } },\r\n            { typeof(Matrix<C4d>[]), c => { var v = default(Matrix<C4d>[]); c.CodeMatrix_of_C4d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<C4d>>), c => { var v = default(List<Matrix<C4d>>); c.CodeList_of_Matrix_of_C4d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<C4d>), c => { var v = default(Volume<C4d>); c.CodeVolume_of_C4d_(ref v); return v; } },\r\n            { typeof(Volume<C4d>[]), c => { var v = default(Volume<C4d>[]); c.CodeVolume_of_C4d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<C4d>>), c => { var v = default(List<Volume<C4d>>); c.CodeList_of_Volume_of_C4d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<C4d>), c => { var v = default(Tensor<C4d>); c.CodeTensor_of_C4d_(ref v); return v; } },\r\n            { typeof(Tensor<C4d>[]), c => { var v = default(Tensor<C4d>[]); c.CodeTensor_of_C4d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<C4d>>), c => { var v = default(List<Tensor<C4d>>); c.CodeList_of_Tensor_of_C4d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1b\r\n\r\n            { typeof(Range1b), c => { var v = default(Range1b); c.CodeRange1b(ref v); return v; } },\r\n            { typeof(Range1b[]), c => { var v = default(Range1b[]); c.CodeRange1bArray(ref v); return v; } },\r\n            { typeof(List<Range1b>), c => { var v = default(List<Range1b>); c.CodeList_of_Range1b_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1b>), c => { var v = default(Vector<Range1b>); c.CodeVector_of_Range1b_(ref v); return v; } },\r\n            { typeof(Vector<Range1b>[]), c => { var v = default(Vector<Range1b>[]); c.CodeVector_of_Range1b_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1b>>), c => { var v = default(List<Vector<Range1b>>); c.CodeList_of_Vector_of_Range1b__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1b>), c => { var v = default(Matrix<Range1b>); c.CodeMatrix_of_Range1b_(ref v); return v; } },\r\n            { typeof(Matrix<Range1b>[]), c => { var v = default(Matrix<Range1b>[]); c.CodeMatrix_of_Range1b_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1b>>), c => { var v = default(List<Matrix<Range1b>>); c.CodeList_of_Matrix_of_Range1b__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1b>), c => { var v = default(Volume<Range1b>); c.CodeVolume_of_Range1b_(ref v); return v; } },\r\n            { typeof(Volume<Range1b>[]), c => { var v = default(Volume<Range1b>[]); c.CodeVolume_of_Range1b_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1b>>), c => { var v = default(List<Volume<Range1b>>); c.CodeList_of_Volume_of_Range1b__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1b>), c => { var v = default(Tensor<Range1b>); c.CodeTensor_of_Range1b_(ref v); return v; } },\r\n            { typeof(Tensor<Range1b>[]), c => { var v = default(Tensor<Range1b>[]); c.CodeTensor_of_Range1b_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1b>>), c => { var v = default(List<Tensor<Range1b>>); c.CodeList_of_Tensor_of_Range1b__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1sb\r\n\r\n            { typeof(Range1sb), c => { var v = default(Range1sb); c.CodeRange1sb(ref v); return v; } },\r\n            { typeof(Range1sb[]), c => { var v = default(Range1sb[]); c.CodeRange1sbArray(ref v); return v; } },\r\n            { typeof(List<Range1sb>), c => { var v = default(List<Range1sb>); c.CodeList_of_Range1sb_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1sb>), c => { var v = default(Vector<Range1sb>); c.CodeVector_of_Range1sb_(ref v); return v; } },\r\n            { typeof(Vector<Range1sb>[]), c => { var v = default(Vector<Range1sb>[]); c.CodeVector_of_Range1sb_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1sb>>), c => { var v = default(List<Vector<Range1sb>>); c.CodeList_of_Vector_of_Range1sb__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1sb>), c => { var v = default(Matrix<Range1sb>); c.CodeMatrix_of_Range1sb_(ref v); return v; } },\r\n            { typeof(Matrix<Range1sb>[]), c => { var v = default(Matrix<Range1sb>[]); c.CodeMatrix_of_Range1sb_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1sb>>), c => { var v = default(List<Matrix<Range1sb>>); c.CodeList_of_Matrix_of_Range1sb__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1sb>), c => { var v = default(Volume<Range1sb>); c.CodeVolume_of_Range1sb_(ref v); return v; } },\r\n            { typeof(Volume<Range1sb>[]), c => { var v = default(Volume<Range1sb>[]); c.CodeVolume_of_Range1sb_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1sb>>), c => { var v = default(List<Volume<Range1sb>>); c.CodeList_of_Volume_of_Range1sb__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1sb>), c => { var v = default(Tensor<Range1sb>); c.CodeTensor_of_Range1sb_(ref v); return v; } },\r\n            { typeof(Tensor<Range1sb>[]), c => { var v = default(Tensor<Range1sb>[]); c.CodeTensor_of_Range1sb_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1sb>>), c => { var v = default(List<Tensor<Range1sb>>); c.CodeList_of_Tensor_of_Range1sb__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1s\r\n\r\n            { typeof(Range1s), c => { var v = default(Range1s); c.CodeRange1s(ref v); return v; } },\r\n            { typeof(Range1s[]), c => { var v = default(Range1s[]); c.CodeRange1sArray(ref v); return v; } },\r\n            { typeof(List<Range1s>), c => { var v = default(List<Range1s>); c.CodeList_of_Range1s_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1s>), c => { var v = default(Vector<Range1s>); c.CodeVector_of_Range1s_(ref v); return v; } },\r\n            { typeof(Vector<Range1s>[]), c => { var v = default(Vector<Range1s>[]); c.CodeVector_of_Range1s_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1s>>), c => { var v = default(List<Vector<Range1s>>); c.CodeList_of_Vector_of_Range1s__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1s>), c => { var v = default(Matrix<Range1s>); c.CodeMatrix_of_Range1s_(ref v); return v; } },\r\n            { typeof(Matrix<Range1s>[]), c => { var v = default(Matrix<Range1s>[]); c.CodeMatrix_of_Range1s_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1s>>), c => { var v = default(List<Matrix<Range1s>>); c.CodeList_of_Matrix_of_Range1s__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1s>), c => { var v = default(Volume<Range1s>); c.CodeVolume_of_Range1s_(ref v); return v; } },\r\n            { typeof(Volume<Range1s>[]), c => { var v = default(Volume<Range1s>[]); c.CodeVolume_of_Range1s_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1s>>), c => { var v = default(List<Volume<Range1s>>); c.CodeList_of_Volume_of_Range1s__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1s>), c => { var v = default(Tensor<Range1s>); c.CodeTensor_of_Range1s_(ref v); return v; } },\r\n            { typeof(Tensor<Range1s>[]), c => { var v = default(Tensor<Range1s>[]); c.CodeTensor_of_Range1s_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1s>>), c => { var v = default(List<Tensor<Range1s>>); c.CodeList_of_Tensor_of_Range1s__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1us\r\n\r\n            { typeof(Range1us), c => { var v = default(Range1us); c.CodeRange1us(ref v); return v; } },\r\n            { typeof(Range1us[]), c => { var v = default(Range1us[]); c.CodeRange1usArray(ref v); return v; } },\r\n            { typeof(List<Range1us>), c => { var v = default(List<Range1us>); c.CodeList_of_Range1us_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1us>), c => { var v = default(Vector<Range1us>); c.CodeVector_of_Range1us_(ref v); return v; } },\r\n            { typeof(Vector<Range1us>[]), c => { var v = default(Vector<Range1us>[]); c.CodeVector_of_Range1us_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1us>>), c => { var v = default(List<Vector<Range1us>>); c.CodeList_of_Vector_of_Range1us__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1us>), c => { var v = default(Matrix<Range1us>); c.CodeMatrix_of_Range1us_(ref v); return v; } },\r\n            { typeof(Matrix<Range1us>[]), c => { var v = default(Matrix<Range1us>[]); c.CodeMatrix_of_Range1us_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1us>>), c => { var v = default(List<Matrix<Range1us>>); c.CodeList_of_Matrix_of_Range1us__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1us>), c => { var v = default(Volume<Range1us>); c.CodeVolume_of_Range1us_(ref v); return v; } },\r\n            { typeof(Volume<Range1us>[]), c => { var v = default(Volume<Range1us>[]); c.CodeVolume_of_Range1us_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1us>>), c => { var v = default(List<Volume<Range1us>>); c.CodeList_of_Volume_of_Range1us__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1us>), c => { var v = default(Tensor<Range1us>); c.CodeTensor_of_Range1us_(ref v); return v; } },\r\n            { typeof(Tensor<Range1us>[]), c => { var v = default(Tensor<Range1us>[]); c.CodeTensor_of_Range1us_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1us>>), c => { var v = default(List<Tensor<Range1us>>); c.CodeList_of_Tensor_of_Range1us__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1i\r\n\r\n            { typeof(Range1i), c => { var v = default(Range1i); c.CodeRange1i(ref v); return v; } },\r\n            { typeof(Range1i[]), c => { var v = default(Range1i[]); c.CodeRange1iArray(ref v); return v; } },\r\n            { typeof(List<Range1i>), c => { var v = default(List<Range1i>); c.CodeList_of_Range1i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1i>), c => { var v = default(Vector<Range1i>); c.CodeVector_of_Range1i_(ref v); return v; } },\r\n            { typeof(Vector<Range1i>[]), c => { var v = default(Vector<Range1i>[]); c.CodeVector_of_Range1i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1i>>), c => { var v = default(List<Vector<Range1i>>); c.CodeList_of_Vector_of_Range1i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1i>), c => { var v = default(Matrix<Range1i>); c.CodeMatrix_of_Range1i_(ref v); return v; } },\r\n            { typeof(Matrix<Range1i>[]), c => { var v = default(Matrix<Range1i>[]); c.CodeMatrix_of_Range1i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1i>>), c => { var v = default(List<Matrix<Range1i>>); c.CodeList_of_Matrix_of_Range1i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1i>), c => { var v = default(Volume<Range1i>); c.CodeVolume_of_Range1i_(ref v); return v; } },\r\n            { typeof(Volume<Range1i>[]), c => { var v = default(Volume<Range1i>[]); c.CodeVolume_of_Range1i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1i>>), c => { var v = default(List<Volume<Range1i>>); c.CodeList_of_Volume_of_Range1i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1i>), c => { var v = default(Tensor<Range1i>); c.CodeTensor_of_Range1i_(ref v); return v; } },\r\n            { typeof(Tensor<Range1i>[]), c => { var v = default(Tensor<Range1i>[]); c.CodeTensor_of_Range1i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1i>>), c => { var v = default(List<Tensor<Range1i>>); c.CodeList_of_Tensor_of_Range1i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1ui\r\n\r\n            { typeof(Range1ui), c => { var v = default(Range1ui); c.CodeRange1ui(ref v); return v; } },\r\n            { typeof(Range1ui[]), c => { var v = default(Range1ui[]); c.CodeRange1uiArray(ref v); return v; } },\r\n            { typeof(List<Range1ui>), c => { var v = default(List<Range1ui>); c.CodeList_of_Range1ui_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1ui>), c => { var v = default(Vector<Range1ui>); c.CodeVector_of_Range1ui_(ref v); return v; } },\r\n            { typeof(Vector<Range1ui>[]), c => { var v = default(Vector<Range1ui>[]); c.CodeVector_of_Range1ui_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1ui>>), c => { var v = default(List<Vector<Range1ui>>); c.CodeList_of_Vector_of_Range1ui__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1ui>), c => { var v = default(Matrix<Range1ui>); c.CodeMatrix_of_Range1ui_(ref v); return v; } },\r\n            { typeof(Matrix<Range1ui>[]), c => { var v = default(Matrix<Range1ui>[]); c.CodeMatrix_of_Range1ui_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1ui>>), c => { var v = default(List<Matrix<Range1ui>>); c.CodeList_of_Matrix_of_Range1ui__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1ui>), c => { var v = default(Volume<Range1ui>); c.CodeVolume_of_Range1ui_(ref v); return v; } },\r\n            { typeof(Volume<Range1ui>[]), c => { var v = default(Volume<Range1ui>[]); c.CodeVolume_of_Range1ui_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1ui>>), c => { var v = default(List<Volume<Range1ui>>); c.CodeList_of_Volume_of_Range1ui__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1ui>), c => { var v = default(Tensor<Range1ui>); c.CodeTensor_of_Range1ui_(ref v); return v; } },\r\n            { typeof(Tensor<Range1ui>[]), c => { var v = default(Tensor<Range1ui>[]); c.CodeTensor_of_Range1ui_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1ui>>), c => { var v = default(List<Tensor<Range1ui>>); c.CodeList_of_Tensor_of_Range1ui__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1l\r\n\r\n            { typeof(Range1l), c => { var v = default(Range1l); c.CodeRange1l(ref v); return v; } },\r\n            { typeof(Range1l[]), c => { var v = default(Range1l[]); c.CodeRange1lArray(ref v); return v; } },\r\n            { typeof(List<Range1l>), c => { var v = default(List<Range1l>); c.CodeList_of_Range1l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1l>), c => { var v = default(Vector<Range1l>); c.CodeVector_of_Range1l_(ref v); return v; } },\r\n            { typeof(Vector<Range1l>[]), c => { var v = default(Vector<Range1l>[]); c.CodeVector_of_Range1l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1l>>), c => { var v = default(List<Vector<Range1l>>); c.CodeList_of_Vector_of_Range1l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1l>), c => { var v = default(Matrix<Range1l>); c.CodeMatrix_of_Range1l_(ref v); return v; } },\r\n            { typeof(Matrix<Range1l>[]), c => { var v = default(Matrix<Range1l>[]); c.CodeMatrix_of_Range1l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1l>>), c => { var v = default(List<Matrix<Range1l>>); c.CodeList_of_Matrix_of_Range1l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1l>), c => { var v = default(Volume<Range1l>); c.CodeVolume_of_Range1l_(ref v); return v; } },\r\n            { typeof(Volume<Range1l>[]), c => { var v = default(Volume<Range1l>[]); c.CodeVolume_of_Range1l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1l>>), c => { var v = default(List<Volume<Range1l>>); c.CodeList_of_Volume_of_Range1l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1l>), c => { var v = default(Tensor<Range1l>); c.CodeTensor_of_Range1l_(ref v); return v; } },\r\n            { typeof(Tensor<Range1l>[]), c => { var v = default(Tensor<Range1l>[]); c.CodeTensor_of_Range1l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1l>>), c => { var v = default(List<Tensor<Range1l>>); c.CodeList_of_Tensor_of_Range1l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1ul\r\n\r\n            { typeof(Range1ul), c => { var v = default(Range1ul); c.CodeRange1ul(ref v); return v; } },\r\n            { typeof(Range1ul[]), c => { var v = default(Range1ul[]); c.CodeRange1ulArray(ref v); return v; } },\r\n            { typeof(List<Range1ul>), c => { var v = default(List<Range1ul>); c.CodeList_of_Range1ul_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1ul>), c => { var v = default(Vector<Range1ul>); c.CodeVector_of_Range1ul_(ref v); return v; } },\r\n            { typeof(Vector<Range1ul>[]), c => { var v = default(Vector<Range1ul>[]); c.CodeVector_of_Range1ul_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1ul>>), c => { var v = default(List<Vector<Range1ul>>); c.CodeList_of_Vector_of_Range1ul__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1ul>), c => { var v = default(Matrix<Range1ul>); c.CodeMatrix_of_Range1ul_(ref v); return v; } },\r\n            { typeof(Matrix<Range1ul>[]), c => { var v = default(Matrix<Range1ul>[]); c.CodeMatrix_of_Range1ul_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1ul>>), c => { var v = default(List<Matrix<Range1ul>>); c.CodeList_of_Matrix_of_Range1ul__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1ul>), c => { var v = default(Volume<Range1ul>); c.CodeVolume_of_Range1ul_(ref v); return v; } },\r\n            { typeof(Volume<Range1ul>[]), c => { var v = default(Volume<Range1ul>[]); c.CodeVolume_of_Range1ul_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1ul>>), c => { var v = default(List<Volume<Range1ul>>); c.CodeList_of_Volume_of_Range1ul__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1ul>), c => { var v = default(Tensor<Range1ul>); c.CodeTensor_of_Range1ul_(ref v); return v; } },\r\n            { typeof(Tensor<Range1ul>[]), c => { var v = default(Tensor<Range1ul>[]); c.CodeTensor_of_Range1ul_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1ul>>), c => { var v = default(List<Tensor<Range1ul>>); c.CodeList_of_Tensor_of_Range1ul__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1f\r\n\r\n            { typeof(Range1f), c => { var v = default(Range1f); c.CodeRange1f(ref v); return v; } },\r\n            { typeof(Range1f[]), c => { var v = default(Range1f[]); c.CodeRange1fArray(ref v); return v; } },\r\n            { typeof(List<Range1f>), c => { var v = default(List<Range1f>); c.CodeList_of_Range1f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1f>), c => { var v = default(Vector<Range1f>); c.CodeVector_of_Range1f_(ref v); return v; } },\r\n            { typeof(Vector<Range1f>[]), c => { var v = default(Vector<Range1f>[]); c.CodeVector_of_Range1f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1f>>), c => { var v = default(List<Vector<Range1f>>); c.CodeList_of_Vector_of_Range1f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1f>), c => { var v = default(Matrix<Range1f>); c.CodeMatrix_of_Range1f_(ref v); return v; } },\r\n            { typeof(Matrix<Range1f>[]), c => { var v = default(Matrix<Range1f>[]); c.CodeMatrix_of_Range1f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1f>>), c => { var v = default(List<Matrix<Range1f>>); c.CodeList_of_Matrix_of_Range1f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1f>), c => { var v = default(Volume<Range1f>); c.CodeVolume_of_Range1f_(ref v); return v; } },\r\n            { typeof(Volume<Range1f>[]), c => { var v = default(Volume<Range1f>[]); c.CodeVolume_of_Range1f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1f>>), c => { var v = default(List<Volume<Range1f>>); c.CodeList_of_Volume_of_Range1f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1f>), c => { var v = default(Tensor<Range1f>); c.CodeTensor_of_Range1f_(ref v); return v; } },\r\n            { typeof(Tensor<Range1f>[]), c => { var v = default(Tensor<Range1f>[]); c.CodeTensor_of_Range1f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1f>>), c => { var v = default(List<Tensor<Range1f>>); c.CodeList_of_Tensor_of_Range1f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Range1d\r\n\r\n            { typeof(Range1d), c => { var v = default(Range1d); c.CodeRange1d(ref v); return v; } },\r\n            { typeof(Range1d[]), c => { var v = default(Range1d[]); c.CodeRange1dArray(ref v); return v; } },\r\n            { typeof(List<Range1d>), c => { var v = default(List<Range1d>); c.CodeList_of_Range1d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Range1d>), c => { var v = default(Vector<Range1d>); c.CodeVector_of_Range1d_(ref v); return v; } },\r\n            { typeof(Vector<Range1d>[]), c => { var v = default(Vector<Range1d>[]); c.CodeVector_of_Range1d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Range1d>>), c => { var v = default(List<Vector<Range1d>>); c.CodeList_of_Vector_of_Range1d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Range1d>), c => { var v = default(Matrix<Range1d>); c.CodeMatrix_of_Range1d_(ref v); return v; } },\r\n            { typeof(Matrix<Range1d>[]), c => { var v = default(Matrix<Range1d>[]); c.CodeMatrix_of_Range1d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Range1d>>), c => { var v = default(List<Matrix<Range1d>>); c.CodeList_of_Matrix_of_Range1d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Range1d>), c => { var v = default(Volume<Range1d>); c.CodeVolume_of_Range1d_(ref v); return v; } },\r\n            { typeof(Volume<Range1d>[]), c => { var v = default(Volume<Range1d>[]); c.CodeVolume_of_Range1d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Range1d>>), c => { var v = default(List<Volume<Range1d>>); c.CodeList_of_Volume_of_Range1d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Range1d>), c => { var v = default(Tensor<Range1d>); c.CodeTensor_of_Range1d_(ref v); return v; } },\r\n            { typeof(Tensor<Range1d>[]), c => { var v = default(Tensor<Range1d>[]); c.CodeTensor_of_Range1d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Range1d>>), c => { var v = default(List<Tensor<Range1d>>); c.CodeList_of_Tensor_of_Range1d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Box2i\r\n\r\n            { typeof(Box2i), c => { var v = default(Box2i); c.CodeBox2i(ref v); return v; } },\r\n            { typeof(Box2i[]), c => { var v = default(Box2i[]); c.CodeBox2iArray(ref v); return v; } },\r\n            { typeof(List<Box2i>), c => { var v = default(List<Box2i>); c.CodeList_of_Box2i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Box2i>), c => { var v = default(Vector<Box2i>); c.CodeVector_of_Box2i_(ref v); return v; } },\r\n            { typeof(Vector<Box2i>[]), c => { var v = default(Vector<Box2i>[]); c.CodeVector_of_Box2i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Box2i>>), c => { var v = default(List<Vector<Box2i>>); c.CodeList_of_Vector_of_Box2i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Box2i>), c => { var v = default(Matrix<Box2i>); c.CodeMatrix_of_Box2i_(ref v); return v; } },\r\n            { typeof(Matrix<Box2i>[]), c => { var v = default(Matrix<Box2i>[]); c.CodeMatrix_of_Box2i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Box2i>>), c => { var v = default(List<Matrix<Box2i>>); c.CodeList_of_Matrix_of_Box2i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Box2i>), c => { var v = default(Volume<Box2i>); c.CodeVolume_of_Box2i_(ref v); return v; } },\r\n            { typeof(Volume<Box2i>[]), c => { var v = default(Volume<Box2i>[]); c.CodeVolume_of_Box2i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Box2i>>), c => { var v = default(List<Volume<Box2i>>); c.CodeList_of_Volume_of_Box2i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Box2i>), c => { var v = default(Tensor<Box2i>); c.CodeTensor_of_Box2i_(ref v); return v; } },\r\n            { typeof(Tensor<Box2i>[]), c => { var v = default(Tensor<Box2i>[]); c.CodeTensor_of_Box2i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Box2i>>), c => { var v = default(List<Tensor<Box2i>>); c.CodeList_of_Tensor_of_Box2i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Box2l\r\n\r\n            { typeof(Box2l), c => { var v = default(Box2l); c.CodeBox2l(ref v); return v; } },\r\n            { typeof(Box2l[]), c => { var v = default(Box2l[]); c.CodeBox2lArray(ref v); return v; } },\r\n            { typeof(List<Box2l>), c => { var v = default(List<Box2l>); c.CodeList_of_Box2l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Box2l>), c => { var v = default(Vector<Box2l>); c.CodeVector_of_Box2l_(ref v); return v; } },\r\n            { typeof(Vector<Box2l>[]), c => { var v = default(Vector<Box2l>[]); c.CodeVector_of_Box2l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Box2l>>), c => { var v = default(List<Vector<Box2l>>); c.CodeList_of_Vector_of_Box2l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Box2l>), c => { var v = default(Matrix<Box2l>); c.CodeMatrix_of_Box2l_(ref v); return v; } },\r\n            { typeof(Matrix<Box2l>[]), c => { var v = default(Matrix<Box2l>[]); c.CodeMatrix_of_Box2l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Box2l>>), c => { var v = default(List<Matrix<Box2l>>); c.CodeList_of_Matrix_of_Box2l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Box2l>), c => { var v = default(Volume<Box2l>); c.CodeVolume_of_Box2l_(ref v); return v; } },\r\n            { typeof(Volume<Box2l>[]), c => { var v = default(Volume<Box2l>[]); c.CodeVolume_of_Box2l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Box2l>>), c => { var v = default(List<Volume<Box2l>>); c.CodeList_of_Volume_of_Box2l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Box2l>), c => { var v = default(Tensor<Box2l>); c.CodeTensor_of_Box2l_(ref v); return v; } },\r\n            { typeof(Tensor<Box2l>[]), c => { var v = default(Tensor<Box2l>[]); c.CodeTensor_of_Box2l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Box2l>>), c => { var v = default(List<Tensor<Box2l>>); c.CodeList_of_Tensor_of_Box2l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Box2f\r\n\r\n            { typeof(Box2f), c => { var v = default(Box2f); c.CodeBox2f(ref v); return v; } },\r\n            { typeof(Box2f[]), c => { var v = default(Box2f[]); c.CodeBox2fArray(ref v); return v; } },\r\n            { typeof(List<Box2f>), c => { var v = default(List<Box2f>); c.CodeList_of_Box2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Box2f>), c => { var v = default(Vector<Box2f>); c.CodeVector_of_Box2f_(ref v); return v; } },\r\n            { typeof(Vector<Box2f>[]), c => { var v = default(Vector<Box2f>[]); c.CodeVector_of_Box2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Box2f>>), c => { var v = default(List<Vector<Box2f>>); c.CodeList_of_Vector_of_Box2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Box2f>), c => { var v = default(Matrix<Box2f>); c.CodeMatrix_of_Box2f_(ref v); return v; } },\r\n            { typeof(Matrix<Box2f>[]), c => { var v = default(Matrix<Box2f>[]); c.CodeMatrix_of_Box2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Box2f>>), c => { var v = default(List<Matrix<Box2f>>); c.CodeList_of_Matrix_of_Box2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Box2f>), c => { var v = default(Volume<Box2f>); c.CodeVolume_of_Box2f_(ref v); return v; } },\r\n            { typeof(Volume<Box2f>[]), c => { var v = default(Volume<Box2f>[]); c.CodeVolume_of_Box2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Box2f>>), c => { var v = default(List<Volume<Box2f>>); c.CodeList_of_Volume_of_Box2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Box2f>), c => { var v = default(Tensor<Box2f>); c.CodeTensor_of_Box2f_(ref v); return v; } },\r\n            { typeof(Tensor<Box2f>[]), c => { var v = default(Tensor<Box2f>[]); c.CodeTensor_of_Box2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Box2f>>), c => { var v = default(List<Tensor<Box2f>>); c.CodeList_of_Tensor_of_Box2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Box2d\r\n\r\n            { typeof(Box2d), c => { var v = default(Box2d); c.CodeBox2d(ref v); return v; } },\r\n            { typeof(Box2d[]), c => { var v = default(Box2d[]); c.CodeBox2dArray(ref v); return v; } },\r\n            { typeof(List<Box2d>), c => { var v = default(List<Box2d>); c.CodeList_of_Box2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Box2d>), c => { var v = default(Vector<Box2d>); c.CodeVector_of_Box2d_(ref v); return v; } },\r\n            { typeof(Vector<Box2d>[]), c => { var v = default(Vector<Box2d>[]); c.CodeVector_of_Box2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Box2d>>), c => { var v = default(List<Vector<Box2d>>); c.CodeList_of_Vector_of_Box2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Box2d>), c => { var v = default(Matrix<Box2d>); c.CodeMatrix_of_Box2d_(ref v); return v; } },\r\n            { typeof(Matrix<Box2d>[]), c => { var v = default(Matrix<Box2d>[]); c.CodeMatrix_of_Box2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Box2d>>), c => { var v = default(List<Matrix<Box2d>>); c.CodeList_of_Matrix_of_Box2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Box2d>), c => { var v = default(Volume<Box2d>); c.CodeVolume_of_Box2d_(ref v); return v; } },\r\n            { typeof(Volume<Box2d>[]), c => { var v = default(Volume<Box2d>[]); c.CodeVolume_of_Box2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Box2d>>), c => { var v = default(List<Volume<Box2d>>); c.CodeList_of_Volume_of_Box2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Box2d>), c => { var v = default(Tensor<Box2d>); c.CodeTensor_of_Box2d_(ref v); return v; } },\r\n            { typeof(Tensor<Box2d>[]), c => { var v = default(Tensor<Box2d>[]); c.CodeTensor_of_Box2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Box2d>>), c => { var v = default(List<Tensor<Box2d>>); c.CodeList_of_Tensor_of_Box2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Box3i\r\n\r\n            { typeof(Box3i), c => { var v = default(Box3i); c.CodeBox3i(ref v); return v; } },\r\n            { typeof(Box3i[]), c => { var v = default(Box3i[]); c.CodeBox3iArray(ref v); return v; } },\r\n            { typeof(List<Box3i>), c => { var v = default(List<Box3i>); c.CodeList_of_Box3i_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Box3i>), c => { var v = default(Vector<Box3i>); c.CodeVector_of_Box3i_(ref v); return v; } },\r\n            { typeof(Vector<Box3i>[]), c => { var v = default(Vector<Box3i>[]); c.CodeVector_of_Box3i_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Box3i>>), c => { var v = default(List<Vector<Box3i>>); c.CodeList_of_Vector_of_Box3i__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Box3i>), c => { var v = default(Matrix<Box3i>); c.CodeMatrix_of_Box3i_(ref v); return v; } },\r\n            { typeof(Matrix<Box3i>[]), c => { var v = default(Matrix<Box3i>[]); c.CodeMatrix_of_Box3i_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Box3i>>), c => { var v = default(List<Matrix<Box3i>>); c.CodeList_of_Matrix_of_Box3i__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Box3i>), c => { var v = default(Volume<Box3i>); c.CodeVolume_of_Box3i_(ref v); return v; } },\r\n            { typeof(Volume<Box3i>[]), c => { var v = default(Volume<Box3i>[]); c.CodeVolume_of_Box3i_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Box3i>>), c => { var v = default(List<Volume<Box3i>>); c.CodeList_of_Volume_of_Box3i__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Box3i>), c => { var v = default(Tensor<Box3i>); c.CodeTensor_of_Box3i_(ref v); return v; } },\r\n            { typeof(Tensor<Box3i>[]), c => { var v = default(Tensor<Box3i>[]); c.CodeTensor_of_Box3i_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Box3i>>), c => { var v = default(List<Tensor<Box3i>>); c.CodeList_of_Tensor_of_Box3i__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Box3l\r\n\r\n            { typeof(Box3l), c => { var v = default(Box3l); c.CodeBox3l(ref v); return v; } },\r\n            { typeof(Box3l[]), c => { var v = default(Box3l[]); c.CodeBox3lArray(ref v); return v; } },\r\n            { typeof(List<Box3l>), c => { var v = default(List<Box3l>); c.CodeList_of_Box3l_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Box3l>), c => { var v = default(Vector<Box3l>); c.CodeVector_of_Box3l_(ref v); return v; } },\r\n            { typeof(Vector<Box3l>[]), c => { var v = default(Vector<Box3l>[]); c.CodeVector_of_Box3l_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Box3l>>), c => { var v = default(List<Vector<Box3l>>); c.CodeList_of_Vector_of_Box3l__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Box3l>), c => { var v = default(Matrix<Box3l>); c.CodeMatrix_of_Box3l_(ref v); return v; } },\r\n            { typeof(Matrix<Box3l>[]), c => { var v = default(Matrix<Box3l>[]); c.CodeMatrix_of_Box3l_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Box3l>>), c => { var v = default(List<Matrix<Box3l>>); c.CodeList_of_Matrix_of_Box3l__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Box3l>), c => { var v = default(Volume<Box3l>); c.CodeVolume_of_Box3l_(ref v); return v; } },\r\n            { typeof(Volume<Box3l>[]), c => { var v = default(Volume<Box3l>[]); c.CodeVolume_of_Box3l_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Box3l>>), c => { var v = default(List<Volume<Box3l>>); c.CodeList_of_Volume_of_Box3l__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Box3l>), c => { var v = default(Tensor<Box3l>); c.CodeTensor_of_Box3l_(ref v); return v; } },\r\n            { typeof(Tensor<Box3l>[]), c => { var v = default(Tensor<Box3l>[]); c.CodeTensor_of_Box3l_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Box3l>>), c => { var v = default(List<Tensor<Box3l>>); c.CodeList_of_Tensor_of_Box3l__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Box3f\r\n\r\n            { typeof(Box3f), c => { var v = default(Box3f); c.CodeBox3f(ref v); return v; } },\r\n            { typeof(Box3f[]), c => { var v = default(Box3f[]); c.CodeBox3fArray(ref v); return v; } },\r\n            { typeof(List<Box3f>), c => { var v = default(List<Box3f>); c.CodeList_of_Box3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Box3f>), c => { var v = default(Vector<Box3f>); c.CodeVector_of_Box3f_(ref v); return v; } },\r\n            { typeof(Vector<Box3f>[]), c => { var v = default(Vector<Box3f>[]); c.CodeVector_of_Box3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Box3f>>), c => { var v = default(List<Vector<Box3f>>); c.CodeList_of_Vector_of_Box3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Box3f>), c => { var v = default(Matrix<Box3f>); c.CodeMatrix_of_Box3f_(ref v); return v; } },\r\n            { typeof(Matrix<Box3f>[]), c => { var v = default(Matrix<Box3f>[]); c.CodeMatrix_of_Box3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Box3f>>), c => { var v = default(List<Matrix<Box3f>>); c.CodeList_of_Matrix_of_Box3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Box3f>), c => { var v = default(Volume<Box3f>); c.CodeVolume_of_Box3f_(ref v); return v; } },\r\n            { typeof(Volume<Box3f>[]), c => { var v = default(Volume<Box3f>[]); c.CodeVolume_of_Box3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Box3f>>), c => { var v = default(List<Volume<Box3f>>); c.CodeList_of_Volume_of_Box3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Box3f>), c => { var v = default(Tensor<Box3f>); c.CodeTensor_of_Box3f_(ref v); return v; } },\r\n            { typeof(Tensor<Box3f>[]), c => { var v = default(Tensor<Box3f>[]); c.CodeTensor_of_Box3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Box3f>>), c => { var v = default(List<Tensor<Box3f>>); c.CodeList_of_Tensor_of_Box3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Box3d\r\n\r\n            { typeof(Box3d), c => { var v = default(Box3d); c.CodeBox3d(ref v); return v; } },\r\n            { typeof(Box3d[]), c => { var v = default(Box3d[]); c.CodeBox3dArray(ref v); return v; } },\r\n            { typeof(List<Box3d>), c => { var v = default(List<Box3d>); c.CodeList_of_Box3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Box3d>), c => { var v = default(Vector<Box3d>); c.CodeVector_of_Box3d_(ref v); return v; } },\r\n            { typeof(Vector<Box3d>[]), c => { var v = default(Vector<Box3d>[]); c.CodeVector_of_Box3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Box3d>>), c => { var v = default(List<Vector<Box3d>>); c.CodeList_of_Vector_of_Box3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Box3d>), c => { var v = default(Matrix<Box3d>); c.CodeMatrix_of_Box3d_(ref v); return v; } },\r\n            { typeof(Matrix<Box3d>[]), c => { var v = default(Matrix<Box3d>[]); c.CodeMatrix_of_Box3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Box3d>>), c => { var v = default(List<Matrix<Box3d>>); c.CodeList_of_Matrix_of_Box3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Box3d>), c => { var v = default(Volume<Box3d>); c.CodeVolume_of_Box3d_(ref v); return v; } },\r\n            { typeof(Volume<Box3d>[]), c => { var v = default(Volume<Box3d>[]); c.CodeVolume_of_Box3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Box3d>>), c => { var v = default(List<Volume<Box3d>>); c.CodeList_of_Volume_of_Box3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Box3d>), c => { var v = default(Tensor<Box3d>); c.CodeTensor_of_Box3d_(ref v); return v; } },\r\n            { typeof(Tensor<Box3d>[]), c => { var v = default(Tensor<Box3d>[]); c.CodeTensor_of_Box3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Box3d>>), c => { var v = default(List<Tensor<Box3d>>); c.CodeList_of_Tensor_of_Box3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Euclidean3f\r\n\r\n            { typeof(Euclidean3f), c => { var v = default(Euclidean3f); c.CodeEuclidean3f(ref v); return v; } },\r\n            { typeof(Euclidean3f[]), c => { var v = default(Euclidean3f[]); c.CodeEuclidean3fArray(ref v); return v; } },\r\n            { typeof(List<Euclidean3f>), c => { var v = default(List<Euclidean3f>); c.CodeList_of_Euclidean3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Euclidean3f>), c => { var v = default(Vector<Euclidean3f>); c.CodeVector_of_Euclidean3f_(ref v); return v; } },\r\n            { typeof(Vector<Euclidean3f>[]), c => { var v = default(Vector<Euclidean3f>[]); c.CodeVector_of_Euclidean3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Euclidean3f>>), c => { var v = default(List<Vector<Euclidean3f>>); c.CodeList_of_Vector_of_Euclidean3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Euclidean3f>), c => { var v = default(Matrix<Euclidean3f>); c.CodeMatrix_of_Euclidean3f_(ref v); return v; } },\r\n            { typeof(Matrix<Euclidean3f>[]), c => { var v = default(Matrix<Euclidean3f>[]); c.CodeMatrix_of_Euclidean3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Euclidean3f>>), c => { var v = default(List<Matrix<Euclidean3f>>); c.CodeList_of_Matrix_of_Euclidean3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Euclidean3f>), c => { var v = default(Volume<Euclidean3f>); c.CodeVolume_of_Euclidean3f_(ref v); return v; } },\r\n            { typeof(Volume<Euclidean3f>[]), c => { var v = default(Volume<Euclidean3f>[]); c.CodeVolume_of_Euclidean3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Euclidean3f>>), c => { var v = default(List<Volume<Euclidean3f>>); c.CodeList_of_Volume_of_Euclidean3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Euclidean3f>), c => { var v = default(Tensor<Euclidean3f>); c.CodeTensor_of_Euclidean3f_(ref v); return v; } },\r\n            { typeof(Tensor<Euclidean3f>[]), c => { var v = default(Tensor<Euclidean3f>[]); c.CodeTensor_of_Euclidean3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Euclidean3f>>), c => { var v = default(List<Tensor<Euclidean3f>>); c.CodeList_of_Tensor_of_Euclidean3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Euclidean3d\r\n\r\n            { typeof(Euclidean3d), c => { var v = default(Euclidean3d); c.CodeEuclidean3d(ref v); return v; } },\r\n            { typeof(Euclidean3d[]), c => { var v = default(Euclidean3d[]); c.CodeEuclidean3dArray(ref v); return v; } },\r\n            { typeof(List<Euclidean3d>), c => { var v = default(List<Euclidean3d>); c.CodeList_of_Euclidean3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Euclidean3d>), c => { var v = default(Vector<Euclidean3d>); c.CodeVector_of_Euclidean3d_(ref v); return v; } },\r\n            { typeof(Vector<Euclidean3d>[]), c => { var v = default(Vector<Euclidean3d>[]); c.CodeVector_of_Euclidean3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Euclidean3d>>), c => { var v = default(List<Vector<Euclidean3d>>); c.CodeList_of_Vector_of_Euclidean3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Euclidean3d>), c => { var v = default(Matrix<Euclidean3d>); c.CodeMatrix_of_Euclidean3d_(ref v); return v; } },\r\n            { typeof(Matrix<Euclidean3d>[]), c => { var v = default(Matrix<Euclidean3d>[]); c.CodeMatrix_of_Euclidean3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Euclidean3d>>), c => { var v = default(List<Matrix<Euclidean3d>>); c.CodeList_of_Matrix_of_Euclidean3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Euclidean3d>), c => { var v = default(Volume<Euclidean3d>); c.CodeVolume_of_Euclidean3d_(ref v); return v; } },\r\n            { typeof(Volume<Euclidean3d>[]), c => { var v = default(Volume<Euclidean3d>[]); c.CodeVolume_of_Euclidean3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Euclidean3d>>), c => { var v = default(List<Volume<Euclidean3d>>); c.CodeList_of_Volume_of_Euclidean3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Euclidean3d>), c => { var v = default(Tensor<Euclidean3d>); c.CodeTensor_of_Euclidean3d_(ref v); return v; } },\r\n            { typeof(Tensor<Euclidean3d>[]), c => { var v = default(Tensor<Euclidean3d>[]); c.CodeTensor_of_Euclidean3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Euclidean3d>>), c => { var v = default(List<Tensor<Euclidean3d>>); c.CodeList_of_Tensor_of_Euclidean3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Rot2f\r\n\r\n            { typeof(Rot2f), c => { var v = default(Rot2f); c.CodeRot2f(ref v); return v; } },\r\n            { typeof(Rot2f[]), c => { var v = default(Rot2f[]); c.CodeRot2fArray(ref v); return v; } },\r\n            { typeof(List<Rot2f>), c => { var v = default(List<Rot2f>); c.CodeList_of_Rot2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Rot2f>), c => { var v = default(Vector<Rot2f>); c.CodeVector_of_Rot2f_(ref v); return v; } },\r\n            { typeof(Vector<Rot2f>[]), c => { var v = default(Vector<Rot2f>[]); c.CodeVector_of_Rot2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Rot2f>>), c => { var v = default(List<Vector<Rot2f>>); c.CodeList_of_Vector_of_Rot2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Rot2f>), c => { var v = default(Matrix<Rot2f>); c.CodeMatrix_of_Rot2f_(ref v); return v; } },\r\n            { typeof(Matrix<Rot2f>[]), c => { var v = default(Matrix<Rot2f>[]); c.CodeMatrix_of_Rot2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Rot2f>>), c => { var v = default(List<Matrix<Rot2f>>); c.CodeList_of_Matrix_of_Rot2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Rot2f>), c => { var v = default(Volume<Rot2f>); c.CodeVolume_of_Rot2f_(ref v); return v; } },\r\n            { typeof(Volume<Rot2f>[]), c => { var v = default(Volume<Rot2f>[]); c.CodeVolume_of_Rot2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Rot2f>>), c => { var v = default(List<Volume<Rot2f>>); c.CodeList_of_Volume_of_Rot2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Rot2f>), c => { var v = default(Tensor<Rot2f>); c.CodeTensor_of_Rot2f_(ref v); return v; } },\r\n            { typeof(Tensor<Rot2f>[]), c => { var v = default(Tensor<Rot2f>[]); c.CodeTensor_of_Rot2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Rot2f>>), c => { var v = default(List<Tensor<Rot2f>>); c.CodeList_of_Tensor_of_Rot2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Rot2d\r\n\r\n            { typeof(Rot2d), c => { var v = default(Rot2d); c.CodeRot2d(ref v); return v; } },\r\n            { typeof(Rot2d[]), c => { var v = default(Rot2d[]); c.CodeRot2dArray(ref v); return v; } },\r\n            { typeof(List<Rot2d>), c => { var v = default(List<Rot2d>); c.CodeList_of_Rot2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Rot2d>), c => { var v = default(Vector<Rot2d>); c.CodeVector_of_Rot2d_(ref v); return v; } },\r\n            { typeof(Vector<Rot2d>[]), c => { var v = default(Vector<Rot2d>[]); c.CodeVector_of_Rot2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Rot2d>>), c => { var v = default(List<Vector<Rot2d>>); c.CodeList_of_Vector_of_Rot2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Rot2d>), c => { var v = default(Matrix<Rot2d>); c.CodeMatrix_of_Rot2d_(ref v); return v; } },\r\n            { typeof(Matrix<Rot2d>[]), c => { var v = default(Matrix<Rot2d>[]); c.CodeMatrix_of_Rot2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Rot2d>>), c => { var v = default(List<Matrix<Rot2d>>); c.CodeList_of_Matrix_of_Rot2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Rot2d>), c => { var v = default(Volume<Rot2d>); c.CodeVolume_of_Rot2d_(ref v); return v; } },\r\n            { typeof(Volume<Rot2d>[]), c => { var v = default(Volume<Rot2d>[]); c.CodeVolume_of_Rot2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Rot2d>>), c => { var v = default(List<Volume<Rot2d>>); c.CodeList_of_Volume_of_Rot2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Rot2d>), c => { var v = default(Tensor<Rot2d>); c.CodeTensor_of_Rot2d_(ref v); return v; } },\r\n            { typeof(Tensor<Rot2d>[]), c => { var v = default(Tensor<Rot2d>[]); c.CodeTensor_of_Rot2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Rot2d>>), c => { var v = default(List<Tensor<Rot2d>>); c.CodeList_of_Tensor_of_Rot2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Rot3f\r\n\r\n            { typeof(Rot3f), c => { var v = default(Rot3f); c.CodeRot3f(ref v); return v; } },\r\n            { typeof(Rot3f[]), c => { var v = default(Rot3f[]); c.CodeRot3fArray(ref v); return v; } },\r\n            { typeof(List<Rot3f>), c => { var v = default(List<Rot3f>); c.CodeList_of_Rot3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Rot3f>), c => { var v = default(Vector<Rot3f>); c.CodeVector_of_Rot3f_(ref v); return v; } },\r\n            { typeof(Vector<Rot3f>[]), c => { var v = default(Vector<Rot3f>[]); c.CodeVector_of_Rot3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Rot3f>>), c => { var v = default(List<Vector<Rot3f>>); c.CodeList_of_Vector_of_Rot3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Rot3f>), c => { var v = default(Matrix<Rot3f>); c.CodeMatrix_of_Rot3f_(ref v); return v; } },\r\n            { typeof(Matrix<Rot3f>[]), c => { var v = default(Matrix<Rot3f>[]); c.CodeMatrix_of_Rot3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Rot3f>>), c => { var v = default(List<Matrix<Rot3f>>); c.CodeList_of_Matrix_of_Rot3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Rot3f>), c => { var v = default(Volume<Rot3f>); c.CodeVolume_of_Rot3f_(ref v); return v; } },\r\n            { typeof(Volume<Rot3f>[]), c => { var v = default(Volume<Rot3f>[]); c.CodeVolume_of_Rot3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Rot3f>>), c => { var v = default(List<Volume<Rot3f>>); c.CodeList_of_Volume_of_Rot3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Rot3f>), c => { var v = default(Tensor<Rot3f>); c.CodeTensor_of_Rot3f_(ref v); return v; } },\r\n            { typeof(Tensor<Rot3f>[]), c => { var v = default(Tensor<Rot3f>[]); c.CodeTensor_of_Rot3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Rot3f>>), c => { var v = default(List<Tensor<Rot3f>>); c.CodeList_of_Tensor_of_Rot3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Rot3d\r\n\r\n            { typeof(Rot3d), c => { var v = default(Rot3d); c.CodeRot3d(ref v); return v; } },\r\n            { typeof(Rot3d[]), c => { var v = default(Rot3d[]); c.CodeRot3dArray(ref v); return v; } },\r\n            { typeof(List<Rot3d>), c => { var v = default(List<Rot3d>); c.CodeList_of_Rot3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Rot3d>), c => { var v = default(Vector<Rot3d>); c.CodeVector_of_Rot3d_(ref v); return v; } },\r\n            { typeof(Vector<Rot3d>[]), c => { var v = default(Vector<Rot3d>[]); c.CodeVector_of_Rot3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Rot3d>>), c => { var v = default(List<Vector<Rot3d>>); c.CodeList_of_Vector_of_Rot3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Rot3d>), c => { var v = default(Matrix<Rot3d>); c.CodeMatrix_of_Rot3d_(ref v); return v; } },\r\n            { typeof(Matrix<Rot3d>[]), c => { var v = default(Matrix<Rot3d>[]); c.CodeMatrix_of_Rot3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Rot3d>>), c => { var v = default(List<Matrix<Rot3d>>); c.CodeList_of_Matrix_of_Rot3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Rot3d>), c => { var v = default(Volume<Rot3d>); c.CodeVolume_of_Rot3d_(ref v); return v; } },\r\n            { typeof(Volume<Rot3d>[]), c => { var v = default(Volume<Rot3d>[]); c.CodeVolume_of_Rot3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Rot3d>>), c => { var v = default(List<Volume<Rot3d>>); c.CodeList_of_Volume_of_Rot3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Rot3d>), c => { var v = default(Tensor<Rot3d>); c.CodeTensor_of_Rot3d_(ref v); return v; } },\r\n            { typeof(Tensor<Rot3d>[]), c => { var v = default(Tensor<Rot3d>[]); c.CodeTensor_of_Rot3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Rot3d>>), c => { var v = default(List<Tensor<Rot3d>>); c.CodeList_of_Tensor_of_Rot3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Scale3f\r\n\r\n            { typeof(Scale3f), c => { var v = default(Scale3f); c.CodeScale3f(ref v); return v; } },\r\n            { typeof(Scale3f[]), c => { var v = default(Scale3f[]); c.CodeScale3fArray(ref v); return v; } },\r\n            { typeof(List<Scale3f>), c => { var v = default(List<Scale3f>); c.CodeList_of_Scale3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Scale3f>), c => { var v = default(Vector<Scale3f>); c.CodeVector_of_Scale3f_(ref v); return v; } },\r\n            { typeof(Vector<Scale3f>[]), c => { var v = default(Vector<Scale3f>[]); c.CodeVector_of_Scale3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Scale3f>>), c => { var v = default(List<Vector<Scale3f>>); c.CodeList_of_Vector_of_Scale3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Scale3f>), c => { var v = default(Matrix<Scale3f>); c.CodeMatrix_of_Scale3f_(ref v); return v; } },\r\n            { typeof(Matrix<Scale3f>[]), c => { var v = default(Matrix<Scale3f>[]); c.CodeMatrix_of_Scale3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Scale3f>>), c => { var v = default(List<Matrix<Scale3f>>); c.CodeList_of_Matrix_of_Scale3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Scale3f>), c => { var v = default(Volume<Scale3f>); c.CodeVolume_of_Scale3f_(ref v); return v; } },\r\n            { typeof(Volume<Scale3f>[]), c => { var v = default(Volume<Scale3f>[]); c.CodeVolume_of_Scale3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Scale3f>>), c => { var v = default(List<Volume<Scale3f>>); c.CodeList_of_Volume_of_Scale3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Scale3f>), c => { var v = default(Tensor<Scale3f>); c.CodeTensor_of_Scale3f_(ref v); return v; } },\r\n            { typeof(Tensor<Scale3f>[]), c => { var v = default(Tensor<Scale3f>[]); c.CodeTensor_of_Scale3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Scale3f>>), c => { var v = default(List<Tensor<Scale3f>>); c.CodeList_of_Tensor_of_Scale3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Scale3d\r\n\r\n            { typeof(Scale3d), c => { var v = default(Scale3d); c.CodeScale3d(ref v); return v; } },\r\n            { typeof(Scale3d[]), c => { var v = default(Scale3d[]); c.CodeScale3dArray(ref v); return v; } },\r\n            { typeof(List<Scale3d>), c => { var v = default(List<Scale3d>); c.CodeList_of_Scale3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Scale3d>), c => { var v = default(Vector<Scale3d>); c.CodeVector_of_Scale3d_(ref v); return v; } },\r\n            { typeof(Vector<Scale3d>[]), c => { var v = default(Vector<Scale3d>[]); c.CodeVector_of_Scale3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Scale3d>>), c => { var v = default(List<Vector<Scale3d>>); c.CodeList_of_Vector_of_Scale3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Scale3d>), c => { var v = default(Matrix<Scale3d>); c.CodeMatrix_of_Scale3d_(ref v); return v; } },\r\n            { typeof(Matrix<Scale3d>[]), c => { var v = default(Matrix<Scale3d>[]); c.CodeMatrix_of_Scale3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Scale3d>>), c => { var v = default(List<Matrix<Scale3d>>); c.CodeList_of_Matrix_of_Scale3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Scale3d>), c => { var v = default(Volume<Scale3d>); c.CodeVolume_of_Scale3d_(ref v); return v; } },\r\n            { typeof(Volume<Scale3d>[]), c => { var v = default(Volume<Scale3d>[]); c.CodeVolume_of_Scale3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Scale3d>>), c => { var v = default(List<Volume<Scale3d>>); c.CodeList_of_Volume_of_Scale3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Scale3d>), c => { var v = default(Tensor<Scale3d>); c.CodeTensor_of_Scale3d_(ref v); return v; } },\r\n            { typeof(Tensor<Scale3d>[]), c => { var v = default(Tensor<Scale3d>[]); c.CodeTensor_of_Scale3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Scale3d>>), c => { var v = default(List<Tensor<Scale3d>>); c.CodeList_of_Tensor_of_Scale3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Shift3f\r\n\r\n            { typeof(Shift3f), c => { var v = default(Shift3f); c.CodeShift3f(ref v); return v; } },\r\n            { typeof(Shift3f[]), c => { var v = default(Shift3f[]); c.CodeShift3fArray(ref v); return v; } },\r\n            { typeof(List<Shift3f>), c => { var v = default(List<Shift3f>); c.CodeList_of_Shift3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Shift3f>), c => { var v = default(Vector<Shift3f>); c.CodeVector_of_Shift3f_(ref v); return v; } },\r\n            { typeof(Vector<Shift3f>[]), c => { var v = default(Vector<Shift3f>[]); c.CodeVector_of_Shift3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Shift3f>>), c => { var v = default(List<Vector<Shift3f>>); c.CodeList_of_Vector_of_Shift3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Shift3f>), c => { var v = default(Matrix<Shift3f>); c.CodeMatrix_of_Shift3f_(ref v); return v; } },\r\n            { typeof(Matrix<Shift3f>[]), c => { var v = default(Matrix<Shift3f>[]); c.CodeMatrix_of_Shift3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Shift3f>>), c => { var v = default(List<Matrix<Shift3f>>); c.CodeList_of_Matrix_of_Shift3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Shift3f>), c => { var v = default(Volume<Shift3f>); c.CodeVolume_of_Shift3f_(ref v); return v; } },\r\n            { typeof(Volume<Shift3f>[]), c => { var v = default(Volume<Shift3f>[]); c.CodeVolume_of_Shift3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Shift3f>>), c => { var v = default(List<Volume<Shift3f>>); c.CodeList_of_Volume_of_Shift3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Shift3f>), c => { var v = default(Tensor<Shift3f>); c.CodeTensor_of_Shift3f_(ref v); return v; } },\r\n            { typeof(Tensor<Shift3f>[]), c => { var v = default(Tensor<Shift3f>[]); c.CodeTensor_of_Shift3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Shift3f>>), c => { var v = default(List<Tensor<Shift3f>>); c.CodeList_of_Tensor_of_Shift3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Shift3d\r\n\r\n            { typeof(Shift3d), c => { var v = default(Shift3d); c.CodeShift3d(ref v); return v; } },\r\n            { typeof(Shift3d[]), c => { var v = default(Shift3d[]); c.CodeShift3dArray(ref v); return v; } },\r\n            { typeof(List<Shift3d>), c => { var v = default(List<Shift3d>); c.CodeList_of_Shift3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Shift3d>), c => { var v = default(Vector<Shift3d>); c.CodeVector_of_Shift3d_(ref v); return v; } },\r\n            { typeof(Vector<Shift3d>[]), c => { var v = default(Vector<Shift3d>[]); c.CodeVector_of_Shift3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Shift3d>>), c => { var v = default(List<Vector<Shift3d>>); c.CodeList_of_Vector_of_Shift3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Shift3d>), c => { var v = default(Matrix<Shift3d>); c.CodeMatrix_of_Shift3d_(ref v); return v; } },\r\n            { typeof(Matrix<Shift3d>[]), c => { var v = default(Matrix<Shift3d>[]); c.CodeMatrix_of_Shift3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Shift3d>>), c => { var v = default(List<Matrix<Shift3d>>); c.CodeList_of_Matrix_of_Shift3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Shift3d>), c => { var v = default(Volume<Shift3d>); c.CodeVolume_of_Shift3d_(ref v); return v; } },\r\n            { typeof(Volume<Shift3d>[]), c => { var v = default(Volume<Shift3d>[]); c.CodeVolume_of_Shift3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Shift3d>>), c => { var v = default(List<Volume<Shift3d>>); c.CodeList_of_Volume_of_Shift3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Shift3d>), c => { var v = default(Tensor<Shift3d>); c.CodeTensor_of_Shift3d_(ref v); return v; } },\r\n            { typeof(Tensor<Shift3d>[]), c => { var v = default(Tensor<Shift3d>[]); c.CodeTensor_of_Shift3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Shift3d>>), c => { var v = default(List<Tensor<Shift3d>>); c.CodeList_of_Tensor_of_Shift3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Trafo2f\r\n\r\n            { typeof(Trafo2f), c => { var v = default(Trafo2f); c.CodeTrafo2f(ref v); return v; } },\r\n            { typeof(Trafo2f[]), c => { var v = default(Trafo2f[]); c.CodeTrafo2fArray(ref v); return v; } },\r\n            { typeof(List<Trafo2f>), c => { var v = default(List<Trafo2f>); c.CodeList_of_Trafo2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Trafo2f>), c => { var v = default(Vector<Trafo2f>); c.CodeVector_of_Trafo2f_(ref v); return v; } },\r\n            { typeof(Vector<Trafo2f>[]), c => { var v = default(Vector<Trafo2f>[]); c.CodeVector_of_Trafo2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Trafo2f>>), c => { var v = default(List<Vector<Trafo2f>>); c.CodeList_of_Vector_of_Trafo2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Trafo2f>), c => { var v = default(Matrix<Trafo2f>); c.CodeMatrix_of_Trafo2f_(ref v); return v; } },\r\n            { typeof(Matrix<Trafo2f>[]), c => { var v = default(Matrix<Trafo2f>[]); c.CodeMatrix_of_Trafo2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Trafo2f>>), c => { var v = default(List<Matrix<Trafo2f>>); c.CodeList_of_Matrix_of_Trafo2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Trafo2f>), c => { var v = default(Volume<Trafo2f>); c.CodeVolume_of_Trafo2f_(ref v); return v; } },\r\n            { typeof(Volume<Trafo2f>[]), c => { var v = default(Volume<Trafo2f>[]); c.CodeVolume_of_Trafo2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Trafo2f>>), c => { var v = default(List<Volume<Trafo2f>>); c.CodeList_of_Volume_of_Trafo2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Trafo2f>), c => { var v = default(Tensor<Trafo2f>); c.CodeTensor_of_Trafo2f_(ref v); return v; } },\r\n            { typeof(Tensor<Trafo2f>[]), c => { var v = default(Tensor<Trafo2f>[]); c.CodeTensor_of_Trafo2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Trafo2f>>), c => { var v = default(List<Tensor<Trafo2f>>); c.CodeList_of_Tensor_of_Trafo2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Trafo2d\r\n\r\n            { typeof(Trafo2d), c => { var v = default(Trafo2d); c.CodeTrafo2d(ref v); return v; } },\r\n            { typeof(Trafo2d[]), c => { var v = default(Trafo2d[]); c.CodeTrafo2dArray(ref v); return v; } },\r\n            { typeof(List<Trafo2d>), c => { var v = default(List<Trafo2d>); c.CodeList_of_Trafo2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Trafo2d>), c => { var v = default(Vector<Trafo2d>); c.CodeVector_of_Trafo2d_(ref v); return v; } },\r\n            { typeof(Vector<Trafo2d>[]), c => { var v = default(Vector<Trafo2d>[]); c.CodeVector_of_Trafo2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Trafo2d>>), c => { var v = default(List<Vector<Trafo2d>>); c.CodeList_of_Vector_of_Trafo2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Trafo2d>), c => { var v = default(Matrix<Trafo2d>); c.CodeMatrix_of_Trafo2d_(ref v); return v; } },\r\n            { typeof(Matrix<Trafo2d>[]), c => { var v = default(Matrix<Trafo2d>[]); c.CodeMatrix_of_Trafo2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Trafo2d>>), c => { var v = default(List<Matrix<Trafo2d>>); c.CodeList_of_Matrix_of_Trafo2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Trafo2d>), c => { var v = default(Volume<Trafo2d>); c.CodeVolume_of_Trafo2d_(ref v); return v; } },\r\n            { typeof(Volume<Trafo2d>[]), c => { var v = default(Volume<Trafo2d>[]); c.CodeVolume_of_Trafo2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Trafo2d>>), c => { var v = default(List<Volume<Trafo2d>>); c.CodeList_of_Volume_of_Trafo2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Trafo2d>), c => { var v = default(Tensor<Trafo2d>); c.CodeTensor_of_Trafo2d_(ref v); return v; } },\r\n            { typeof(Tensor<Trafo2d>[]), c => { var v = default(Tensor<Trafo2d>[]); c.CodeTensor_of_Trafo2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Trafo2d>>), c => { var v = default(List<Tensor<Trafo2d>>); c.CodeList_of_Tensor_of_Trafo2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Trafo3f\r\n\r\n            { typeof(Trafo3f), c => { var v = default(Trafo3f); c.CodeTrafo3f(ref v); return v; } },\r\n            { typeof(Trafo3f[]), c => { var v = default(Trafo3f[]); c.CodeTrafo3fArray(ref v); return v; } },\r\n            { typeof(List<Trafo3f>), c => { var v = default(List<Trafo3f>); c.CodeList_of_Trafo3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Trafo3f>), c => { var v = default(Vector<Trafo3f>); c.CodeVector_of_Trafo3f_(ref v); return v; } },\r\n            { typeof(Vector<Trafo3f>[]), c => { var v = default(Vector<Trafo3f>[]); c.CodeVector_of_Trafo3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Trafo3f>>), c => { var v = default(List<Vector<Trafo3f>>); c.CodeList_of_Vector_of_Trafo3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Trafo3f>), c => { var v = default(Matrix<Trafo3f>); c.CodeMatrix_of_Trafo3f_(ref v); return v; } },\r\n            { typeof(Matrix<Trafo3f>[]), c => { var v = default(Matrix<Trafo3f>[]); c.CodeMatrix_of_Trafo3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Trafo3f>>), c => { var v = default(List<Matrix<Trafo3f>>); c.CodeList_of_Matrix_of_Trafo3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Trafo3f>), c => { var v = default(Volume<Trafo3f>); c.CodeVolume_of_Trafo3f_(ref v); return v; } },\r\n            { typeof(Volume<Trafo3f>[]), c => { var v = default(Volume<Trafo3f>[]); c.CodeVolume_of_Trafo3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Trafo3f>>), c => { var v = default(List<Volume<Trafo3f>>); c.CodeList_of_Volume_of_Trafo3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Trafo3f>), c => { var v = default(Tensor<Trafo3f>); c.CodeTensor_of_Trafo3f_(ref v); return v; } },\r\n            { typeof(Tensor<Trafo3f>[]), c => { var v = default(Tensor<Trafo3f>[]); c.CodeTensor_of_Trafo3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Trafo3f>>), c => { var v = default(List<Tensor<Trafo3f>>); c.CodeList_of_Tensor_of_Trafo3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Trafo3d\r\n\r\n            { typeof(Trafo3d), c => { var v = default(Trafo3d); c.CodeTrafo3d(ref v); return v; } },\r\n            { typeof(Trafo3d[]), c => { var v = default(Trafo3d[]); c.CodeTrafo3dArray(ref v); return v; } },\r\n            { typeof(List<Trafo3d>), c => { var v = default(List<Trafo3d>); c.CodeList_of_Trafo3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Trafo3d>), c => { var v = default(Vector<Trafo3d>); c.CodeVector_of_Trafo3d_(ref v); return v; } },\r\n            { typeof(Vector<Trafo3d>[]), c => { var v = default(Vector<Trafo3d>[]); c.CodeVector_of_Trafo3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Trafo3d>>), c => { var v = default(List<Vector<Trafo3d>>); c.CodeList_of_Vector_of_Trafo3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Trafo3d>), c => { var v = default(Matrix<Trafo3d>); c.CodeMatrix_of_Trafo3d_(ref v); return v; } },\r\n            { typeof(Matrix<Trafo3d>[]), c => { var v = default(Matrix<Trafo3d>[]); c.CodeMatrix_of_Trafo3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Trafo3d>>), c => { var v = default(List<Matrix<Trafo3d>>); c.CodeList_of_Matrix_of_Trafo3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Trafo3d>), c => { var v = default(Volume<Trafo3d>); c.CodeVolume_of_Trafo3d_(ref v); return v; } },\r\n            { typeof(Volume<Trafo3d>[]), c => { var v = default(Volume<Trafo3d>[]); c.CodeVolume_of_Trafo3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Trafo3d>>), c => { var v = default(List<Volume<Trafo3d>>); c.CodeList_of_Volume_of_Trafo3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Trafo3d>), c => { var v = default(Tensor<Trafo3d>); c.CodeTensor_of_Trafo3d_(ref v); return v; } },\r\n            { typeof(Tensor<Trafo3d>[]), c => { var v = default(Tensor<Trafo3d>[]); c.CodeTensor_of_Trafo3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Trafo3d>>), c => { var v = default(List<Tensor<Trafo3d>>); c.CodeList_of_Tensor_of_Trafo3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region bool\r\n\r\n            { typeof(bool), c => { var v = default(bool); c.CodeBool(ref v); return v; } },\r\n            { typeof(bool[]), c => { var v = default(bool[]); c.CodeBoolArray(ref v); return v; } },\r\n            { typeof(List<bool>), c => { var v = default(List<bool>); c.CodeList_of_Bool_(ref v); return v; } },\r\n\r\n            { typeof(Vector<bool>), c => { var v = default(Vector<bool>); c.CodeVector_of_Bool_(ref v); return v; } },\r\n            { typeof(Vector<bool>[]), c => { var v = default(Vector<bool>[]); c.CodeVector_of_Bool_Array(ref v); return v; } },\r\n            { typeof(List<Vector<bool>>), c => { var v = default(List<Vector<bool>>); c.CodeList_of_Vector_of_Bool__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<bool>), c => { var v = default(Matrix<bool>); c.CodeMatrix_of_Bool_(ref v); return v; } },\r\n            { typeof(Matrix<bool>[]), c => { var v = default(Matrix<bool>[]); c.CodeMatrix_of_Bool_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<bool>>), c => { var v = default(List<Matrix<bool>>); c.CodeList_of_Matrix_of_Bool__(ref v); return v; } },\r\n\r\n            { typeof(Volume<bool>), c => { var v = default(Volume<bool>); c.CodeVolume_of_Bool_(ref v); return v; } },\r\n            { typeof(Volume<bool>[]), c => { var v = default(Volume<bool>[]); c.CodeVolume_of_Bool_Array(ref v); return v; } },\r\n            { typeof(List<Volume<bool>>), c => { var v = default(List<Volume<bool>>); c.CodeList_of_Volume_of_Bool__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<bool>), c => { var v = default(Tensor<bool>); c.CodeTensor_of_Bool_(ref v); return v; } },\r\n            { typeof(Tensor<bool>[]), c => { var v = default(Tensor<bool>[]); c.CodeTensor_of_Bool_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<bool>>), c => { var v = default(List<Tensor<bool>>); c.CodeList_of_Tensor_of_Bool__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region char\r\n\r\n            { typeof(char), c => { var v = default(char); c.CodeChar(ref v); return v; } },\r\n            { typeof(char[]), c => { var v = default(char[]); c.CodeCharArray(ref v); return v; } },\r\n            { typeof(List<char>), c => { var v = default(List<char>); c.CodeList_of_Char_(ref v); return v; } },\r\n\r\n            { typeof(Vector<char>), c => { var v = default(Vector<char>); c.CodeVector_of_Char_(ref v); return v; } },\r\n            { typeof(Vector<char>[]), c => { var v = default(Vector<char>[]); c.CodeVector_of_Char_Array(ref v); return v; } },\r\n            { typeof(List<Vector<char>>), c => { var v = default(List<Vector<char>>); c.CodeList_of_Vector_of_Char__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<char>), c => { var v = default(Matrix<char>); c.CodeMatrix_of_Char_(ref v); return v; } },\r\n            { typeof(Matrix<char>[]), c => { var v = default(Matrix<char>[]); c.CodeMatrix_of_Char_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<char>>), c => { var v = default(List<Matrix<char>>); c.CodeList_of_Matrix_of_Char__(ref v); return v; } },\r\n\r\n            { typeof(Volume<char>), c => { var v = default(Volume<char>); c.CodeVolume_of_Char_(ref v); return v; } },\r\n            { typeof(Volume<char>[]), c => { var v = default(Volume<char>[]); c.CodeVolume_of_Char_Array(ref v); return v; } },\r\n            { typeof(List<Volume<char>>), c => { var v = default(List<Volume<char>>); c.CodeList_of_Volume_of_Char__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<char>), c => { var v = default(Tensor<char>); c.CodeTensor_of_Char_(ref v); return v; } },\r\n            { typeof(Tensor<char>[]), c => { var v = default(Tensor<char>[]); c.CodeTensor_of_Char_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<char>>), c => { var v = default(List<Tensor<char>>); c.CodeList_of_Tensor_of_Char__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region string\r\n\r\n            { typeof(string), c => { var v = default(string); c.CodeString(ref v); return v; } },\r\n            { typeof(string[]), c => { var v = default(string[]); c.CodeStringArray(ref v); return v; } },\r\n            { typeof(List<string>), c => { var v = default(List<string>); c.CodeList_of_String_(ref v); return v; } },\r\n\r\n            { typeof(Vector<string>), c => { var v = default(Vector<string>); c.CodeVector_of_String_(ref v); return v; } },\r\n            { typeof(Vector<string>[]), c => { var v = default(Vector<string>[]); c.CodeVector_of_String_Array(ref v); return v; } },\r\n            { typeof(List<Vector<string>>), c => { var v = default(List<Vector<string>>); c.CodeList_of_Vector_of_String__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<string>), c => { var v = default(Matrix<string>); c.CodeMatrix_of_String_(ref v); return v; } },\r\n            { typeof(Matrix<string>[]), c => { var v = default(Matrix<string>[]); c.CodeMatrix_of_String_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<string>>), c => { var v = default(List<Matrix<string>>); c.CodeList_of_Matrix_of_String__(ref v); return v; } },\r\n\r\n            { typeof(Volume<string>), c => { var v = default(Volume<string>); c.CodeVolume_of_String_(ref v); return v; } },\r\n            { typeof(Volume<string>[]), c => { var v = default(Volume<string>[]); c.CodeVolume_of_String_Array(ref v); return v; } },\r\n            { typeof(List<Volume<string>>), c => { var v = default(List<Volume<string>>); c.CodeList_of_Volume_of_String__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<string>), c => { var v = default(Tensor<string>); c.CodeTensor_of_String_(ref v); return v; } },\r\n            { typeof(Tensor<string>[]), c => { var v = default(Tensor<string>[]); c.CodeTensor_of_String_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<string>>), c => { var v = default(List<Tensor<string>>); c.CodeList_of_Tensor_of_String__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Type\r\n\r\n            { typeof(Type), c => { var v = default(Type); c.CodeType(ref v); return v; } },\r\n            { typeof(Type[]), c => { var v = default(Type[]); c.CodeTypeArray(ref v); return v; } },\r\n            { typeof(List<Type>), c => { var v = default(List<Type>); c.CodeList_of_Type_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Type>), c => { var v = default(Vector<Type>); c.CodeVector_of_Type_(ref v); return v; } },\r\n            { typeof(Vector<Type>[]), c => { var v = default(Vector<Type>[]); c.CodeVector_of_Type_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Type>>), c => { var v = default(List<Vector<Type>>); c.CodeList_of_Vector_of_Type__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Type>), c => { var v = default(Matrix<Type>); c.CodeMatrix_of_Type_(ref v); return v; } },\r\n            { typeof(Matrix<Type>[]), c => { var v = default(Matrix<Type>[]); c.CodeMatrix_of_Type_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Type>>), c => { var v = default(List<Matrix<Type>>); c.CodeList_of_Matrix_of_Type__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Type>), c => { var v = default(Volume<Type>); c.CodeVolume_of_Type_(ref v); return v; } },\r\n            { typeof(Volume<Type>[]), c => { var v = default(Volume<Type>[]); c.CodeVolume_of_Type_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Type>>), c => { var v = default(List<Volume<Type>>); c.CodeList_of_Volume_of_Type__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Type>), c => { var v = default(Tensor<Type>); c.CodeTensor_of_Type_(ref v); return v; } },\r\n            { typeof(Tensor<Type>[]), c => { var v = default(Tensor<Type>[]); c.CodeTensor_of_Type_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Type>>), c => { var v = default(List<Tensor<Type>>); c.CodeList_of_Tensor_of_Type__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Guid\r\n\r\n            { typeof(Guid), c => { var v = default(Guid); c.CodeGuid(ref v); return v; } },\r\n            { typeof(Guid[]), c => { var v = default(Guid[]); c.CodeGuidArray(ref v); return v; } },\r\n            { typeof(List<Guid>), c => { var v = default(List<Guid>); c.CodeList_of_Guid_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Guid>), c => { var v = default(Vector<Guid>); c.CodeVector_of_Guid_(ref v); return v; } },\r\n            { typeof(Vector<Guid>[]), c => { var v = default(Vector<Guid>[]); c.CodeVector_of_Guid_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Guid>>), c => { var v = default(List<Vector<Guid>>); c.CodeList_of_Vector_of_Guid__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Guid>), c => { var v = default(Matrix<Guid>); c.CodeMatrix_of_Guid_(ref v); return v; } },\r\n            { typeof(Matrix<Guid>[]), c => { var v = default(Matrix<Guid>[]); c.CodeMatrix_of_Guid_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Guid>>), c => { var v = default(List<Matrix<Guid>>); c.CodeList_of_Matrix_of_Guid__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Guid>), c => { var v = default(Volume<Guid>); c.CodeVolume_of_Guid_(ref v); return v; } },\r\n            { typeof(Volume<Guid>[]), c => { var v = default(Volume<Guid>[]); c.CodeVolume_of_Guid_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Guid>>), c => { var v = default(List<Volume<Guid>>); c.CodeList_of_Volume_of_Guid__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Guid>), c => { var v = default(Tensor<Guid>); c.CodeTensor_of_Guid_(ref v); return v; } },\r\n            { typeof(Tensor<Guid>[]), c => { var v = default(Tensor<Guid>[]); c.CodeTensor_of_Guid_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Guid>>), c => { var v = default(List<Tensor<Guid>>); c.CodeList_of_Tensor_of_Guid__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Symbol\r\n\r\n            { typeof(Symbol), c => { var v = default(Symbol); c.CodeSymbol(ref v); return v; } },\r\n            { typeof(Symbol[]), c => { var v = default(Symbol[]); c.CodeSymbolArray(ref v); return v; } },\r\n            { typeof(List<Symbol>), c => { var v = default(List<Symbol>); c.CodeList_of_Symbol_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Symbol>), c => { var v = default(Vector<Symbol>); c.CodeVector_of_Symbol_(ref v); return v; } },\r\n            { typeof(Vector<Symbol>[]), c => { var v = default(Vector<Symbol>[]); c.CodeVector_of_Symbol_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Symbol>>), c => { var v = default(List<Vector<Symbol>>); c.CodeList_of_Vector_of_Symbol__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Symbol>), c => { var v = default(Matrix<Symbol>); c.CodeMatrix_of_Symbol_(ref v); return v; } },\r\n            { typeof(Matrix<Symbol>[]), c => { var v = default(Matrix<Symbol>[]); c.CodeMatrix_of_Symbol_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Symbol>>), c => { var v = default(List<Matrix<Symbol>>); c.CodeList_of_Matrix_of_Symbol__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Symbol>), c => { var v = default(Volume<Symbol>); c.CodeVolume_of_Symbol_(ref v); return v; } },\r\n            { typeof(Volume<Symbol>[]), c => { var v = default(Volume<Symbol>[]); c.CodeVolume_of_Symbol_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Symbol>>), c => { var v = default(List<Volume<Symbol>>); c.CodeList_of_Volume_of_Symbol__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Symbol>), c => { var v = default(Tensor<Symbol>); c.CodeTensor_of_Symbol_(ref v); return v; } },\r\n            { typeof(Tensor<Symbol>[]), c => { var v = default(Tensor<Symbol>[]); c.CodeTensor_of_Symbol_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Symbol>>), c => { var v = default(List<Tensor<Symbol>>); c.CodeList_of_Tensor_of_Symbol__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Circle2d\r\n\r\n            { typeof(Circle2d), c => { var v = default(Circle2d); c.CodeCircle2d(ref v); return v; } },\r\n            { typeof(Circle2d[]), c => { var v = default(Circle2d[]); c.CodeCircle2dArray(ref v); return v; } },\r\n            { typeof(List<Circle2d>), c => { var v = default(List<Circle2d>); c.CodeList_of_Circle2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Circle2d>), c => { var v = default(Vector<Circle2d>); c.CodeVector_of_Circle2d_(ref v); return v; } },\r\n            { typeof(Vector<Circle2d>[]), c => { var v = default(Vector<Circle2d>[]); c.CodeVector_of_Circle2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Circle2d>>), c => { var v = default(List<Vector<Circle2d>>); c.CodeList_of_Vector_of_Circle2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Circle2d>), c => { var v = default(Matrix<Circle2d>); c.CodeMatrix_of_Circle2d_(ref v); return v; } },\r\n            { typeof(Matrix<Circle2d>[]), c => { var v = default(Matrix<Circle2d>[]); c.CodeMatrix_of_Circle2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Circle2d>>), c => { var v = default(List<Matrix<Circle2d>>); c.CodeList_of_Matrix_of_Circle2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Circle2d>), c => { var v = default(Volume<Circle2d>); c.CodeVolume_of_Circle2d_(ref v); return v; } },\r\n            { typeof(Volume<Circle2d>[]), c => { var v = default(Volume<Circle2d>[]); c.CodeVolume_of_Circle2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Circle2d>>), c => { var v = default(List<Volume<Circle2d>>); c.CodeList_of_Volume_of_Circle2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Circle2d>), c => { var v = default(Tensor<Circle2d>); c.CodeTensor_of_Circle2d_(ref v); return v; } },\r\n            { typeof(Tensor<Circle2d>[]), c => { var v = default(Tensor<Circle2d>[]); c.CodeTensor_of_Circle2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Circle2d>>), c => { var v = default(List<Tensor<Circle2d>>); c.CodeList_of_Tensor_of_Circle2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Line2d\r\n\r\n            { typeof(Line2d), c => { var v = default(Line2d); c.CodeLine2d(ref v); return v; } },\r\n            { typeof(Line2d[]), c => { var v = default(Line2d[]); c.CodeLine2dArray(ref v); return v; } },\r\n            { typeof(List<Line2d>), c => { var v = default(List<Line2d>); c.CodeList_of_Line2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Line2d>), c => { var v = default(Vector<Line2d>); c.CodeVector_of_Line2d_(ref v); return v; } },\r\n            { typeof(Vector<Line2d>[]), c => { var v = default(Vector<Line2d>[]); c.CodeVector_of_Line2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Line2d>>), c => { var v = default(List<Vector<Line2d>>); c.CodeList_of_Vector_of_Line2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Line2d>), c => { var v = default(Matrix<Line2d>); c.CodeMatrix_of_Line2d_(ref v); return v; } },\r\n            { typeof(Matrix<Line2d>[]), c => { var v = default(Matrix<Line2d>[]); c.CodeMatrix_of_Line2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Line2d>>), c => { var v = default(List<Matrix<Line2d>>); c.CodeList_of_Matrix_of_Line2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Line2d>), c => { var v = default(Volume<Line2d>); c.CodeVolume_of_Line2d_(ref v); return v; } },\r\n            { typeof(Volume<Line2d>[]), c => { var v = default(Volume<Line2d>[]); c.CodeVolume_of_Line2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Line2d>>), c => { var v = default(List<Volume<Line2d>>); c.CodeList_of_Volume_of_Line2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Line2d>), c => { var v = default(Tensor<Line2d>); c.CodeTensor_of_Line2d_(ref v); return v; } },\r\n            { typeof(Tensor<Line2d>[]), c => { var v = default(Tensor<Line2d>[]); c.CodeTensor_of_Line2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Line2d>>), c => { var v = default(List<Tensor<Line2d>>); c.CodeList_of_Tensor_of_Line2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Line3d\r\n\r\n            { typeof(Line3d), c => { var v = default(Line3d); c.CodeLine3d(ref v); return v; } },\r\n            { typeof(Line3d[]), c => { var v = default(Line3d[]); c.CodeLine3dArray(ref v); return v; } },\r\n            { typeof(List<Line3d>), c => { var v = default(List<Line3d>); c.CodeList_of_Line3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Line3d>), c => { var v = default(Vector<Line3d>); c.CodeVector_of_Line3d_(ref v); return v; } },\r\n            { typeof(Vector<Line3d>[]), c => { var v = default(Vector<Line3d>[]); c.CodeVector_of_Line3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Line3d>>), c => { var v = default(List<Vector<Line3d>>); c.CodeList_of_Vector_of_Line3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Line3d>), c => { var v = default(Matrix<Line3d>); c.CodeMatrix_of_Line3d_(ref v); return v; } },\r\n            { typeof(Matrix<Line3d>[]), c => { var v = default(Matrix<Line3d>[]); c.CodeMatrix_of_Line3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Line3d>>), c => { var v = default(List<Matrix<Line3d>>); c.CodeList_of_Matrix_of_Line3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Line3d>), c => { var v = default(Volume<Line3d>); c.CodeVolume_of_Line3d_(ref v); return v; } },\r\n            { typeof(Volume<Line3d>[]), c => { var v = default(Volume<Line3d>[]); c.CodeVolume_of_Line3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Line3d>>), c => { var v = default(List<Volume<Line3d>>); c.CodeList_of_Volume_of_Line3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Line3d>), c => { var v = default(Tensor<Line3d>); c.CodeTensor_of_Line3d_(ref v); return v; } },\r\n            { typeof(Tensor<Line3d>[]), c => { var v = default(Tensor<Line3d>[]); c.CodeTensor_of_Line3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Line3d>>), c => { var v = default(List<Tensor<Line3d>>); c.CodeList_of_Tensor_of_Line3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Plane2d\r\n\r\n            { typeof(Plane2d), c => { var v = default(Plane2d); c.CodePlane2d(ref v); return v; } },\r\n            { typeof(Plane2d[]), c => { var v = default(Plane2d[]); c.CodePlane2dArray(ref v); return v; } },\r\n            { typeof(List<Plane2d>), c => { var v = default(List<Plane2d>); c.CodeList_of_Plane2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Plane2d>), c => { var v = default(Vector<Plane2d>); c.CodeVector_of_Plane2d_(ref v); return v; } },\r\n            { typeof(Vector<Plane2d>[]), c => { var v = default(Vector<Plane2d>[]); c.CodeVector_of_Plane2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Plane2d>>), c => { var v = default(List<Vector<Plane2d>>); c.CodeList_of_Vector_of_Plane2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Plane2d>), c => { var v = default(Matrix<Plane2d>); c.CodeMatrix_of_Plane2d_(ref v); return v; } },\r\n            { typeof(Matrix<Plane2d>[]), c => { var v = default(Matrix<Plane2d>[]); c.CodeMatrix_of_Plane2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Plane2d>>), c => { var v = default(List<Matrix<Plane2d>>); c.CodeList_of_Matrix_of_Plane2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Plane2d>), c => { var v = default(Volume<Plane2d>); c.CodeVolume_of_Plane2d_(ref v); return v; } },\r\n            { typeof(Volume<Plane2d>[]), c => { var v = default(Volume<Plane2d>[]); c.CodeVolume_of_Plane2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Plane2d>>), c => { var v = default(List<Volume<Plane2d>>); c.CodeList_of_Volume_of_Plane2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Plane2d>), c => { var v = default(Tensor<Plane2d>); c.CodeTensor_of_Plane2d_(ref v); return v; } },\r\n            { typeof(Tensor<Plane2d>[]), c => { var v = default(Tensor<Plane2d>[]); c.CodeTensor_of_Plane2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Plane2d>>), c => { var v = default(List<Tensor<Plane2d>>); c.CodeList_of_Tensor_of_Plane2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Plane3d\r\n\r\n            { typeof(Plane3d), c => { var v = default(Plane3d); c.CodePlane3d(ref v); return v; } },\r\n            { typeof(Plane3d[]), c => { var v = default(Plane3d[]); c.CodePlane3dArray(ref v); return v; } },\r\n            { typeof(List<Plane3d>), c => { var v = default(List<Plane3d>); c.CodeList_of_Plane3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Plane3d>), c => { var v = default(Vector<Plane3d>); c.CodeVector_of_Plane3d_(ref v); return v; } },\r\n            { typeof(Vector<Plane3d>[]), c => { var v = default(Vector<Plane3d>[]); c.CodeVector_of_Plane3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Plane3d>>), c => { var v = default(List<Vector<Plane3d>>); c.CodeList_of_Vector_of_Plane3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Plane3d>), c => { var v = default(Matrix<Plane3d>); c.CodeMatrix_of_Plane3d_(ref v); return v; } },\r\n            { typeof(Matrix<Plane3d>[]), c => { var v = default(Matrix<Plane3d>[]); c.CodeMatrix_of_Plane3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Plane3d>>), c => { var v = default(List<Matrix<Plane3d>>); c.CodeList_of_Matrix_of_Plane3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Plane3d>), c => { var v = default(Volume<Plane3d>); c.CodeVolume_of_Plane3d_(ref v); return v; } },\r\n            { typeof(Volume<Plane3d>[]), c => { var v = default(Volume<Plane3d>[]); c.CodeVolume_of_Plane3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Plane3d>>), c => { var v = default(List<Volume<Plane3d>>); c.CodeList_of_Volume_of_Plane3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Plane3d>), c => { var v = default(Tensor<Plane3d>); c.CodeTensor_of_Plane3d_(ref v); return v; } },\r\n            { typeof(Tensor<Plane3d>[]), c => { var v = default(Tensor<Plane3d>[]); c.CodeTensor_of_Plane3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Plane3d>>), c => { var v = default(List<Tensor<Plane3d>>); c.CodeList_of_Tensor_of_Plane3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region PlaneWithPoint3d\r\n\r\n            { typeof(PlaneWithPoint3d), c => { var v = default(PlaneWithPoint3d); c.CodePlaneWithPoint3d(ref v); return v; } },\r\n            { typeof(PlaneWithPoint3d[]), c => { var v = default(PlaneWithPoint3d[]); c.CodePlaneWithPoint3dArray(ref v); return v; } },\r\n            { typeof(List<PlaneWithPoint3d>), c => { var v = default(List<PlaneWithPoint3d>); c.CodeList_of_PlaneWithPoint3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<PlaneWithPoint3d>), c => { var v = default(Vector<PlaneWithPoint3d>); c.CodeVector_of_PlaneWithPoint3d_(ref v); return v; } },\r\n            { typeof(Vector<PlaneWithPoint3d>[]), c => { var v = default(Vector<PlaneWithPoint3d>[]); c.CodeVector_of_PlaneWithPoint3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<PlaneWithPoint3d>>), c => { var v = default(List<Vector<PlaneWithPoint3d>>); c.CodeList_of_Vector_of_PlaneWithPoint3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<PlaneWithPoint3d>), c => { var v = default(Matrix<PlaneWithPoint3d>); c.CodeMatrix_of_PlaneWithPoint3d_(ref v); return v; } },\r\n            { typeof(Matrix<PlaneWithPoint3d>[]), c => { var v = default(Matrix<PlaneWithPoint3d>[]); c.CodeMatrix_of_PlaneWithPoint3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<PlaneWithPoint3d>>), c => { var v = default(List<Matrix<PlaneWithPoint3d>>); c.CodeList_of_Matrix_of_PlaneWithPoint3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<PlaneWithPoint3d>), c => { var v = default(Volume<PlaneWithPoint3d>); c.CodeVolume_of_PlaneWithPoint3d_(ref v); return v; } },\r\n            { typeof(Volume<PlaneWithPoint3d>[]), c => { var v = default(Volume<PlaneWithPoint3d>[]); c.CodeVolume_of_PlaneWithPoint3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<PlaneWithPoint3d>>), c => { var v = default(List<Volume<PlaneWithPoint3d>>); c.CodeList_of_Volume_of_PlaneWithPoint3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<PlaneWithPoint3d>), c => { var v = default(Tensor<PlaneWithPoint3d>); c.CodeTensor_of_PlaneWithPoint3d_(ref v); return v; } },\r\n            { typeof(Tensor<PlaneWithPoint3d>[]), c => { var v = default(Tensor<PlaneWithPoint3d>[]); c.CodeTensor_of_PlaneWithPoint3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<PlaneWithPoint3d>>), c => { var v = default(List<Tensor<PlaneWithPoint3d>>); c.CodeList_of_Tensor_of_PlaneWithPoint3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Quad2d\r\n\r\n            { typeof(Quad2d), c => { var v = default(Quad2d); c.CodeQuad2d(ref v); return v; } },\r\n            { typeof(Quad2d[]), c => { var v = default(Quad2d[]); c.CodeQuad2dArray(ref v); return v; } },\r\n            { typeof(List<Quad2d>), c => { var v = default(List<Quad2d>); c.CodeList_of_Quad2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Quad2d>), c => { var v = default(Vector<Quad2d>); c.CodeVector_of_Quad2d_(ref v); return v; } },\r\n            { typeof(Vector<Quad2d>[]), c => { var v = default(Vector<Quad2d>[]); c.CodeVector_of_Quad2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Quad2d>>), c => { var v = default(List<Vector<Quad2d>>); c.CodeList_of_Vector_of_Quad2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Quad2d>), c => { var v = default(Matrix<Quad2d>); c.CodeMatrix_of_Quad2d_(ref v); return v; } },\r\n            { typeof(Matrix<Quad2d>[]), c => { var v = default(Matrix<Quad2d>[]); c.CodeMatrix_of_Quad2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Quad2d>>), c => { var v = default(List<Matrix<Quad2d>>); c.CodeList_of_Matrix_of_Quad2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Quad2d>), c => { var v = default(Volume<Quad2d>); c.CodeVolume_of_Quad2d_(ref v); return v; } },\r\n            { typeof(Volume<Quad2d>[]), c => { var v = default(Volume<Quad2d>[]); c.CodeVolume_of_Quad2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Quad2d>>), c => { var v = default(List<Volume<Quad2d>>); c.CodeList_of_Volume_of_Quad2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Quad2d>), c => { var v = default(Tensor<Quad2d>); c.CodeTensor_of_Quad2d_(ref v); return v; } },\r\n            { typeof(Tensor<Quad2d>[]), c => { var v = default(Tensor<Quad2d>[]); c.CodeTensor_of_Quad2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Quad2d>>), c => { var v = default(List<Tensor<Quad2d>>); c.CodeList_of_Tensor_of_Quad2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Quad3d\r\n\r\n            { typeof(Quad3d), c => { var v = default(Quad3d); c.CodeQuad3d(ref v); return v; } },\r\n            { typeof(Quad3d[]), c => { var v = default(Quad3d[]); c.CodeQuad3dArray(ref v); return v; } },\r\n            { typeof(List<Quad3d>), c => { var v = default(List<Quad3d>); c.CodeList_of_Quad3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Quad3d>), c => { var v = default(Vector<Quad3d>); c.CodeVector_of_Quad3d_(ref v); return v; } },\r\n            { typeof(Vector<Quad3d>[]), c => { var v = default(Vector<Quad3d>[]); c.CodeVector_of_Quad3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Quad3d>>), c => { var v = default(List<Vector<Quad3d>>); c.CodeList_of_Vector_of_Quad3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Quad3d>), c => { var v = default(Matrix<Quad3d>); c.CodeMatrix_of_Quad3d_(ref v); return v; } },\r\n            { typeof(Matrix<Quad3d>[]), c => { var v = default(Matrix<Quad3d>[]); c.CodeMatrix_of_Quad3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Quad3d>>), c => { var v = default(List<Matrix<Quad3d>>); c.CodeList_of_Matrix_of_Quad3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Quad3d>), c => { var v = default(Volume<Quad3d>); c.CodeVolume_of_Quad3d_(ref v); return v; } },\r\n            { typeof(Volume<Quad3d>[]), c => { var v = default(Volume<Quad3d>[]); c.CodeVolume_of_Quad3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Quad3d>>), c => { var v = default(List<Volume<Quad3d>>); c.CodeList_of_Volume_of_Quad3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Quad3d>), c => { var v = default(Tensor<Quad3d>); c.CodeTensor_of_Quad3d_(ref v); return v; } },\r\n            { typeof(Tensor<Quad3d>[]), c => { var v = default(Tensor<Quad3d>[]); c.CodeTensor_of_Quad3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Quad3d>>), c => { var v = default(List<Tensor<Quad3d>>); c.CodeList_of_Tensor_of_Quad3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Ray2d\r\n\r\n            { typeof(Ray2d), c => { var v = default(Ray2d); c.CodeRay2d(ref v); return v; } },\r\n            { typeof(Ray2d[]), c => { var v = default(Ray2d[]); c.CodeRay2dArray(ref v); return v; } },\r\n            { typeof(List<Ray2d>), c => { var v = default(List<Ray2d>); c.CodeList_of_Ray2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Ray2d>), c => { var v = default(Vector<Ray2d>); c.CodeVector_of_Ray2d_(ref v); return v; } },\r\n            { typeof(Vector<Ray2d>[]), c => { var v = default(Vector<Ray2d>[]); c.CodeVector_of_Ray2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Ray2d>>), c => { var v = default(List<Vector<Ray2d>>); c.CodeList_of_Vector_of_Ray2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Ray2d>), c => { var v = default(Matrix<Ray2d>); c.CodeMatrix_of_Ray2d_(ref v); return v; } },\r\n            { typeof(Matrix<Ray2d>[]), c => { var v = default(Matrix<Ray2d>[]); c.CodeMatrix_of_Ray2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Ray2d>>), c => { var v = default(List<Matrix<Ray2d>>); c.CodeList_of_Matrix_of_Ray2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Ray2d>), c => { var v = default(Volume<Ray2d>); c.CodeVolume_of_Ray2d_(ref v); return v; } },\r\n            { typeof(Volume<Ray2d>[]), c => { var v = default(Volume<Ray2d>[]); c.CodeVolume_of_Ray2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Ray2d>>), c => { var v = default(List<Volume<Ray2d>>); c.CodeList_of_Volume_of_Ray2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Ray2d>), c => { var v = default(Tensor<Ray2d>); c.CodeTensor_of_Ray2d_(ref v); return v; } },\r\n            { typeof(Tensor<Ray2d>[]), c => { var v = default(Tensor<Ray2d>[]); c.CodeTensor_of_Ray2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Ray2d>>), c => { var v = default(List<Tensor<Ray2d>>); c.CodeList_of_Tensor_of_Ray2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Ray3d\r\n\r\n            { typeof(Ray3d), c => { var v = default(Ray3d); c.CodeRay3d(ref v); return v; } },\r\n            { typeof(Ray3d[]), c => { var v = default(Ray3d[]); c.CodeRay3dArray(ref v); return v; } },\r\n            { typeof(List<Ray3d>), c => { var v = default(List<Ray3d>); c.CodeList_of_Ray3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Ray3d>), c => { var v = default(Vector<Ray3d>); c.CodeVector_of_Ray3d_(ref v); return v; } },\r\n            { typeof(Vector<Ray3d>[]), c => { var v = default(Vector<Ray3d>[]); c.CodeVector_of_Ray3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Ray3d>>), c => { var v = default(List<Vector<Ray3d>>); c.CodeList_of_Vector_of_Ray3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Ray3d>), c => { var v = default(Matrix<Ray3d>); c.CodeMatrix_of_Ray3d_(ref v); return v; } },\r\n            { typeof(Matrix<Ray3d>[]), c => { var v = default(Matrix<Ray3d>[]); c.CodeMatrix_of_Ray3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Ray3d>>), c => { var v = default(List<Matrix<Ray3d>>); c.CodeList_of_Matrix_of_Ray3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Ray3d>), c => { var v = default(Volume<Ray3d>); c.CodeVolume_of_Ray3d_(ref v); return v; } },\r\n            { typeof(Volume<Ray3d>[]), c => { var v = default(Volume<Ray3d>[]); c.CodeVolume_of_Ray3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Ray3d>>), c => { var v = default(List<Volume<Ray3d>>); c.CodeList_of_Volume_of_Ray3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Ray3d>), c => { var v = default(Tensor<Ray3d>); c.CodeTensor_of_Ray3d_(ref v); return v; } },\r\n            { typeof(Tensor<Ray3d>[]), c => { var v = default(Tensor<Ray3d>[]); c.CodeTensor_of_Ray3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Ray3d>>), c => { var v = default(List<Tensor<Ray3d>>); c.CodeList_of_Tensor_of_Ray3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Sphere3d\r\n\r\n            { typeof(Sphere3d), c => { var v = default(Sphere3d); c.CodeSphere3d(ref v); return v; } },\r\n            { typeof(Sphere3d[]), c => { var v = default(Sphere3d[]); c.CodeSphere3dArray(ref v); return v; } },\r\n            { typeof(List<Sphere3d>), c => { var v = default(List<Sphere3d>); c.CodeList_of_Sphere3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Sphere3d>), c => { var v = default(Vector<Sphere3d>); c.CodeVector_of_Sphere3d_(ref v); return v; } },\r\n            { typeof(Vector<Sphere3d>[]), c => { var v = default(Vector<Sphere3d>[]); c.CodeVector_of_Sphere3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Sphere3d>>), c => { var v = default(List<Vector<Sphere3d>>); c.CodeList_of_Vector_of_Sphere3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Sphere3d>), c => { var v = default(Matrix<Sphere3d>); c.CodeMatrix_of_Sphere3d_(ref v); return v; } },\r\n            { typeof(Matrix<Sphere3d>[]), c => { var v = default(Matrix<Sphere3d>[]); c.CodeMatrix_of_Sphere3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Sphere3d>>), c => { var v = default(List<Matrix<Sphere3d>>); c.CodeList_of_Matrix_of_Sphere3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Sphere3d>), c => { var v = default(Volume<Sphere3d>); c.CodeVolume_of_Sphere3d_(ref v); return v; } },\r\n            { typeof(Volume<Sphere3d>[]), c => { var v = default(Volume<Sphere3d>[]); c.CodeVolume_of_Sphere3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Sphere3d>>), c => { var v = default(List<Volume<Sphere3d>>); c.CodeList_of_Volume_of_Sphere3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Sphere3d>), c => { var v = default(Tensor<Sphere3d>); c.CodeTensor_of_Sphere3d_(ref v); return v; } },\r\n            { typeof(Tensor<Sphere3d>[]), c => { var v = default(Tensor<Sphere3d>[]); c.CodeTensor_of_Sphere3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Sphere3d>>), c => { var v = default(List<Tensor<Sphere3d>>); c.CodeList_of_Tensor_of_Sphere3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Triangle2d\r\n\r\n            { typeof(Triangle2d), c => { var v = default(Triangle2d); c.CodeTriangle2d(ref v); return v; } },\r\n            { typeof(Triangle2d[]), c => { var v = default(Triangle2d[]); c.CodeTriangle2dArray(ref v); return v; } },\r\n            { typeof(List<Triangle2d>), c => { var v = default(List<Triangle2d>); c.CodeList_of_Triangle2d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Triangle2d>), c => { var v = default(Vector<Triangle2d>); c.CodeVector_of_Triangle2d_(ref v); return v; } },\r\n            { typeof(Vector<Triangle2d>[]), c => { var v = default(Vector<Triangle2d>[]); c.CodeVector_of_Triangle2d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Triangle2d>>), c => { var v = default(List<Vector<Triangle2d>>); c.CodeList_of_Vector_of_Triangle2d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Triangle2d>), c => { var v = default(Matrix<Triangle2d>); c.CodeMatrix_of_Triangle2d_(ref v); return v; } },\r\n            { typeof(Matrix<Triangle2d>[]), c => { var v = default(Matrix<Triangle2d>[]); c.CodeMatrix_of_Triangle2d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Triangle2d>>), c => { var v = default(List<Matrix<Triangle2d>>); c.CodeList_of_Matrix_of_Triangle2d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Triangle2d>), c => { var v = default(Volume<Triangle2d>); c.CodeVolume_of_Triangle2d_(ref v); return v; } },\r\n            { typeof(Volume<Triangle2d>[]), c => { var v = default(Volume<Triangle2d>[]); c.CodeVolume_of_Triangle2d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Triangle2d>>), c => { var v = default(List<Volume<Triangle2d>>); c.CodeList_of_Volume_of_Triangle2d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Triangle2d>), c => { var v = default(Tensor<Triangle2d>); c.CodeTensor_of_Triangle2d_(ref v); return v; } },\r\n            { typeof(Tensor<Triangle2d>[]), c => { var v = default(Tensor<Triangle2d>[]); c.CodeTensor_of_Triangle2d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Triangle2d>>), c => { var v = default(List<Tensor<Triangle2d>>); c.CodeList_of_Tensor_of_Triangle2d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Triangle3d\r\n\r\n            { typeof(Triangle3d), c => { var v = default(Triangle3d); c.CodeTriangle3d(ref v); return v; } },\r\n            { typeof(Triangle3d[]), c => { var v = default(Triangle3d[]); c.CodeTriangle3dArray(ref v); return v; } },\r\n            { typeof(List<Triangle3d>), c => { var v = default(List<Triangle3d>); c.CodeList_of_Triangle3d_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Triangle3d>), c => { var v = default(Vector<Triangle3d>); c.CodeVector_of_Triangle3d_(ref v); return v; } },\r\n            { typeof(Vector<Triangle3d>[]), c => { var v = default(Vector<Triangle3d>[]); c.CodeVector_of_Triangle3d_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Triangle3d>>), c => { var v = default(List<Vector<Triangle3d>>); c.CodeList_of_Vector_of_Triangle3d__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Triangle3d>), c => { var v = default(Matrix<Triangle3d>); c.CodeMatrix_of_Triangle3d_(ref v); return v; } },\r\n            { typeof(Matrix<Triangle3d>[]), c => { var v = default(Matrix<Triangle3d>[]); c.CodeMatrix_of_Triangle3d_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Triangle3d>>), c => { var v = default(List<Matrix<Triangle3d>>); c.CodeList_of_Matrix_of_Triangle3d__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Triangle3d>), c => { var v = default(Volume<Triangle3d>); c.CodeVolume_of_Triangle3d_(ref v); return v; } },\r\n            { typeof(Volume<Triangle3d>[]), c => { var v = default(Volume<Triangle3d>[]); c.CodeVolume_of_Triangle3d_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Triangle3d>>), c => { var v = default(List<Volume<Triangle3d>>); c.CodeList_of_Volume_of_Triangle3d__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Triangle3d>), c => { var v = default(Tensor<Triangle3d>); c.CodeTensor_of_Triangle3d_(ref v); return v; } },\r\n            { typeof(Tensor<Triangle3d>[]), c => { var v = default(Tensor<Triangle3d>[]); c.CodeTensor_of_Triangle3d_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Triangle3d>>), c => { var v = default(List<Tensor<Triangle3d>>); c.CodeList_of_Tensor_of_Triangle3d__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Circle2f\r\n\r\n            { typeof(Circle2f), c => { var v = default(Circle2f); c.CodeCircle2f(ref v); return v; } },\r\n            { typeof(Circle2f[]), c => { var v = default(Circle2f[]); c.CodeCircle2fArray(ref v); return v; } },\r\n            { typeof(List<Circle2f>), c => { var v = default(List<Circle2f>); c.CodeList_of_Circle2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Circle2f>), c => { var v = default(Vector<Circle2f>); c.CodeVector_of_Circle2f_(ref v); return v; } },\r\n            { typeof(Vector<Circle2f>[]), c => { var v = default(Vector<Circle2f>[]); c.CodeVector_of_Circle2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Circle2f>>), c => { var v = default(List<Vector<Circle2f>>); c.CodeList_of_Vector_of_Circle2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Circle2f>), c => { var v = default(Matrix<Circle2f>); c.CodeMatrix_of_Circle2f_(ref v); return v; } },\r\n            { typeof(Matrix<Circle2f>[]), c => { var v = default(Matrix<Circle2f>[]); c.CodeMatrix_of_Circle2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Circle2f>>), c => { var v = default(List<Matrix<Circle2f>>); c.CodeList_of_Matrix_of_Circle2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Circle2f>), c => { var v = default(Volume<Circle2f>); c.CodeVolume_of_Circle2f_(ref v); return v; } },\r\n            { typeof(Volume<Circle2f>[]), c => { var v = default(Volume<Circle2f>[]); c.CodeVolume_of_Circle2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Circle2f>>), c => { var v = default(List<Volume<Circle2f>>); c.CodeList_of_Volume_of_Circle2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Circle2f>), c => { var v = default(Tensor<Circle2f>); c.CodeTensor_of_Circle2f_(ref v); return v; } },\r\n            { typeof(Tensor<Circle2f>[]), c => { var v = default(Tensor<Circle2f>[]); c.CodeTensor_of_Circle2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Circle2f>>), c => { var v = default(List<Tensor<Circle2f>>); c.CodeList_of_Tensor_of_Circle2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Line2f\r\n\r\n            { typeof(Line2f), c => { var v = default(Line2f); c.CodeLine2f(ref v); return v; } },\r\n            { typeof(Line2f[]), c => { var v = default(Line2f[]); c.CodeLine2fArray(ref v); return v; } },\r\n            { typeof(List<Line2f>), c => { var v = default(List<Line2f>); c.CodeList_of_Line2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Line2f>), c => { var v = default(Vector<Line2f>); c.CodeVector_of_Line2f_(ref v); return v; } },\r\n            { typeof(Vector<Line2f>[]), c => { var v = default(Vector<Line2f>[]); c.CodeVector_of_Line2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Line2f>>), c => { var v = default(List<Vector<Line2f>>); c.CodeList_of_Vector_of_Line2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Line2f>), c => { var v = default(Matrix<Line2f>); c.CodeMatrix_of_Line2f_(ref v); return v; } },\r\n            { typeof(Matrix<Line2f>[]), c => { var v = default(Matrix<Line2f>[]); c.CodeMatrix_of_Line2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Line2f>>), c => { var v = default(List<Matrix<Line2f>>); c.CodeList_of_Matrix_of_Line2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Line2f>), c => { var v = default(Volume<Line2f>); c.CodeVolume_of_Line2f_(ref v); return v; } },\r\n            { typeof(Volume<Line2f>[]), c => { var v = default(Volume<Line2f>[]); c.CodeVolume_of_Line2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Line2f>>), c => { var v = default(List<Volume<Line2f>>); c.CodeList_of_Volume_of_Line2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Line2f>), c => { var v = default(Tensor<Line2f>); c.CodeTensor_of_Line2f_(ref v); return v; } },\r\n            { typeof(Tensor<Line2f>[]), c => { var v = default(Tensor<Line2f>[]); c.CodeTensor_of_Line2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Line2f>>), c => { var v = default(List<Tensor<Line2f>>); c.CodeList_of_Tensor_of_Line2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Line3f\r\n\r\n            { typeof(Line3f), c => { var v = default(Line3f); c.CodeLine3f(ref v); return v; } },\r\n            { typeof(Line3f[]), c => { var v = default(Line3f[]); c.CodeLine3fArray(ref v); return v; } },\r\n            { typeof(List<Line3f>), c => { var v = default(List<Line3f>); c.CodeList_of_Line3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Line3f>), c => { var v = default(Vector<Line3f>); c.CodeVector_of_Line3f_(ref v); return v; } },\r\n            { typeof(Vector<Line3f>[]), c => { var v = default(Vector<Line3f>[]); c.CodeVector_of_Line3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Line3f>>), c => { var v = default(List<Vector<Line3f>>); c.CodeList_of_Vector_of_Line3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Line3f>), c => { var v = default(Matrix<Line3f>); c.CodeMatrix_of_Line3f_(ref v); return v; } },\r\n            { typeof(Matrix<Line3f>[]), c => { var v = default(Matrix<Line3f>[]); c.CodeMatrix_of_Line3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Line3f>>), c => { var v = default(List<Matrix<Line3f>>); c.CodeList_of_Matrix_of_Line3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Line3f>), c => { var v = default(Volume<Line3f>); c.CodeVolume_of_Line3f_(ref v); return v; } },\r\n            { typeof(Volume<Line3f>[]), c => { var v = default(Volume<Line3f>[]); c.CodeVolume_of_Line3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Line3f>>), c => { var v = default(List<Volume<Line3f>>); c.CodeList_of_Volume_of_Line3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Line3f>), c => { var v = default(Tensor<Line3f>); c.CodeTensor_of_Line3f_(ref v); return v; } },\r\n            { typeof(Tensor<Line3f>[]), c => { var v = default(Tensor<Line3f>[]); c.CodeTensor_of_Line3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Line3f>>), c => { var v = default(List<Tensor<Line3f>>); c.CodeList_of_Tensor_of_Line3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Plane2f\r\n\r\n            { typeof(Plane2f), c => { var v = default(Plane2f); c.CodePlane2f(ref v); return v; } },\r\n            { typeof(Plane2f[]), c => { var v = default(Plane2f[]); c.CodePlane2fArray(ref v); return v; } },\r\n            { typeof(List<Plane2f>), c => { var v = default(List<Plane2f>); c.CodeList_of_Plane2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Plane2f>), c => { var v = default(Vector<Plane2f>); c.CodeVector_of_Plane2f_(ref v); return v; } },\r\n            { typeof(Vector<Plane2f>[]), c => { var v = default(Vector<Plane2f>[]); c.CodeVector_of_Plane2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Plane2f>>), c => { var v = default(List<Vector<Plane2f>>); c.CodeList_of_Vector_of_Plane2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Plane2f>), c => { var v = default(Matrix<Plane2f>); c.CodeMatrix_of_Plane2f_(ref v); return v; } },\r\n            { typeof(Matrix<Plane2f>[]), c => { var v = default(Matrix<Plane2f>[]); c.CodeMatrix_of_Plane2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Plane2f>>), c => { var v = default(List<Matrix<Plane2f>>); c.CodeList_of_Matrix_of_Plane2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Plane2f>), c => { var v = default(Volume<Plane2f>); c.CodeVolume_of_Plane2f_(ref v); return v; } },\r\n            { typeof(Volume<Plane2f>[]), c => { var v = default(Volume<Plane2f>[]); c.CodeVolume_of_Plane2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Plane2f>>), c => { var v = default(List<Volume<Plane2f>>); c.CodeList_of_Volume_of_Plane2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Plane2f>), c => { var v = default(Tensor<Plane2f>); c.CodeTensor_of_Plane2f_(ref v); return v; } },\r\n            { typeof(Tensor<Plane2f>[]), c => { var v = default(Tensor<Plane2f>[]); c.CodeTensor_of_Plane2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Plane2f>>), c => { var v = default(List<Tensor<Plane2f>>); c.CodeList_of_Tensor_of_Plane2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Plane3f\r\n\r\n            { typeof(Plane3f), c => { var v = default(Plane3f); c.CodePlane3f(ref v); return v; } },\r\n            { typeof(Plane3f[]), c => { var v = default(Plane3f[]); c.CodePlane3fArray(ref v); return v; } },\r\n            { typeof(List<Plane3f>), c => { var v = default(List<Plane3f>); c.CodeList_of_Plane3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Plane3f>), c => { var v = default(Vector<Plane3f>); c.CodeVector_of_Plane3f_(ref v); return v; } },\r\n            { typeof(Vector<Plane3f>[]), c => { var v = default(Vector<Plane3f>[]); c.CodeVector_of_Plane3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Plane3f>>), c => { var v = default(List<Vector<Plane3f>>); c.CodeList_of_Vector_of_Plane3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Plane3f>), c => { var v = default(Matrix<Plane3f>); c.CodeMatrix_of_Plane3f_(ref v); return v; } },\r\n            { typeof(Matrix<Plane3f>[]), c => { var v = default(Matrix<Plane3f>[]); c.CodeMatrix_of_Plane3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Plane3f>>), c => { var v = default(List<Matrix<Plane3f>>); c.CodeList_of_Matrix_of_Plane3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Plane3f>), c => { var v = default(Volume<Plane3f>); c.CodeVolume_of_Plane3f_(ref v); return v; } },\r\n            { typeof(Volume<Plane3f>[]), c => { var v = default(Volume<Plane3f>[]); c.CodeVolume_of_Plane3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Plane3f>>), c => { var v = default(List<Volume<Plane3f>>); c.CodeList_of_Volume_of_Plane3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Plane3f>), c => { var v = default(Tensor<Plane3f>); c.CodeTensor_of_Plane3f_(ref v); return v; } },\r\n            { typeof(Tensor<Plane3f>[]), c => { var v = default(Tensor<Plane3f>[]); c.CodeTensor_of_Plane3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Plane3f>>), c => { var v = default(List<Tensor<Plane3f>>); c.CodeList_of_Tensor_of_Plane3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region PlaneWithPoint3f\r\n\r\n            { typeof(PlaneWithPoint3f), c => { var v = default(PlaneWithPoint3f); c.CodePlaneWithPoint3f(ref v); return v; } },\r\n            { typeof(PlaneWithPoint3f[]), c => { var v = default(PlaneWithPoint3f[]); c.CodePlaneWithPoint3fArray(ref v); return v; } },\r\n            { typeof(List<PlaneWithPoint3f>), c => { var v = default(List<PlaneWithPoint3f>); c.CodeList_of_PlaneWithPoint3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<PlaneWithPoint3f>), c => { var v = default(Vector<PlaneWithPoint3f>); c.CodeVector_of_PlaneWithPoint3f_(ref v); return v; } },\r\n            { typeof(Vector<PlaneWithPoint3f>[]), c => { var v = default(Vector<PlaneWithPoint3f>[]); c.CodeVector_of_PlaneWithPoint3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<PlaneWithPoint3f>>), c => { var v = default(List<Vector<PlaneWithPoint3f>>); c.CodeList_of_Vector_of_PlaneWithPoint3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<PlaneWithPoint3f>), c => { var v = default(Matrix<PlaneWithPoint3f>); c.CodeMatrix_of_PlaneWithPoint3f_(ref v); return v; } },\r\n            { typeof(Matrix<PlaneWithPoint3f>[]), c => { var v = default(Matrix<PlaneWithPoint3f>[]); c.CodeMatrix_of_PlaneWithPoint3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<PlaneWithPoint3f>>), c => { var v = default(List<Matrix<PlaneWithPoint3f>>); c.CodeList_of_Matrix_of_PlaneWithPoint3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<PlaneWithPoint3f>), c => { var v = default(Volume<PlaneWithPoint3f>); c.CodeVolume_of_PlaneWithPoint3f_(ref v); return v; } },\r\n            { typeof(Volume<PlaneWithPoint3f>[]), c => { var v = default(Volume<PlaneWithPoint3f>[]); c.CodeVolume_of_PlaneWithPoint3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<PlaneWithPoint3f>>), c => { var v = default(List<Volume<PlaneWithPoint3f>>); c.CodeList_of_Volume_of_PlaneWithPoint3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<PlaneWithPoint3f>), c => { var v = default(Tensor<PlaneWithPoint3f>); c.CodeTensor_of_PlaneWithPoint3f_(ref v); return v; } },\r\n            { typeof(Tensor<PlaneWithPoint3f>[]), c => { var v = default(Tensor<PlaneWithPoint3f>[]); c.CodeTensor_of_PlaneWithPoint3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<PlaneWithPoint3f>>), c => { var v = default(List<Tensor<PlaneWithPoint3f>>); c.CodeList_of_Tensor_of_PlaneWithPoint3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Quad2f\r\n\r\n            { typeof(Quad2f), c => { var v = default(Quad2f); c.CodeQuad2f(ref v); return v; } },\r\n            { typeof(Quad2f[]), c => { var v = default(Quad2f[]); c.CodeQuad2fArray(ref v); return v; } },\r\n            { typeof(List<Quad2f>), c => { var v = default(List<Quad2f>); c.CodeList_of_Quad2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Quad2f>), c => { var v = default(Vector<Quad2f>); c.CodeVector_of_Quad2f_(ref v); return v; } },\r\n            { typeof(Vector<Quad2f>[]), c => { var v = default(Vector<Quad2f>[]); c.CodeVector_of_Quad2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Quad2f>>), c => { var v = default(List<Vector<Quad2f>>); c.CodeList_of_Vector_of_Quad2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Quad2f>), c => { var v = default(Matrix<Quad2f>); c.CodeMatrix_of_Quad2f_(ref v); return v; } },\r\n            { typeof(Matrix<Quad2f>[]), c => { var v = default(Matrix<Quad2f>[]); c.CodeMatrix_of_Quad2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Quad2f>>), c => { var v = default(List<Matrix<Quad2f>>); c.CodeList_of_Matrix_of_Quad2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Quad2f>), c => { var v = default(Volume<Quad2f>); c.CodeVolume_of_Quad2f_(ref v); return v; } },\r\n            { typeof(Volume<Quad2f>[]), c => { var v = default(Volume<Quad2f>[]); c.CodeVolume_of_Quad2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Quad2f>>), c => { var v = default(List<Volume<Quad2f>>); c.CodeList_of_Volume_of_Quad2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Quad2f>), c => { var v = default(Tensor<Quad2f>); c.CodeTensor_of_Quad2f_(ref v); return v; } },\r\n            { typeof(Tensor<Quad2f>[]), c => { var v = default(Tensor<Quad2f>[]); c.CodeTensor_of_Quad2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Quad2f>>), c => { var v = default(List<Tensor<Quad2f>>); c.CodeList_of_Tensor_of_Quad2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Quad3f\r\n\r\n            { typeof(Quad3f), c => { var v = default(Quad3f); c.CodeQuad3f(ref v); return v; } },\r\n            { typeof(Quad3f[]), c => { var v = default(Quad3f[]); c.CodeQuad3fArray(ref v); return v; } },\r\n            { typeof(List<Quad3f>), c => { var v = default(List<Quad3f>); c.CodeList_of_Quad3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Quad3f>), c => { var v = default(Vector<Quad3f>); c.CodeVector_of_Quad3f_(ref v); return v; } },\r\n            { typeof(Vector<Quad3f>[]), c => { var v = default(Vector<Quad3f>[]); c.CodeVector_of_Quad3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Quad3f>>), c => { var v = default(List<Vector<Quad3f>>); c.CodeList_of_Vector_of_Quad3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Quad3f>), c => { var v = default(Matrix<Quad3f>); c.CodeMatrix_of_Quad3f_(ref v); return v; } },\r\n            { typeof(Matrix<Quad3f>[]), c => { var v = default(Matrix<Quad3f>[]); c.CodeMatrix_of_Quad3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Quad3f>>), c => { var v = default(List<Matrix<Quad3f>>); c.CodeList_of_Matrix_of_Quad3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Quad3f>), c => { var v = default(Volume<Quad3f>); c.CodeVolume_of_Quad3f_(ref v); return v; } },\r\n            { typeof(Volume<Quad3f>[]), c => { var v = default(Volume<Quad3f>[]); c.CodeVolume_of_Quad3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Quad3f>>), c => { var v = default(List<Volume<Quad3f>>); c.CodeList_of_Volume_of_Quad3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Quad3f>), c => { var v = default(Tensor<Quad3f>); c.CodeTensor_of_Quad3f_(ref v); return v; } },\r\n            { typeof(Tensor<Quad3f>[]), c => { var v = default(Tensor<Quad3f>[]); c.CodeTensor_of_Quad3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Quad3f>>), c => { var v = default(List<Tensor<Quad3f>>); c.CodeList_of_Tensor_of_Quad3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Ray2f\r\n\r\n            { typeof(Ray2f), c => { var v = default(Ray2f); c.CodeRay2f(ref v); return v; } },\r\n            { typeof(Ray2f[]), c => { var v = default(Ray2f[]); c.CodeRay2fArray(ref v); return v; } },\r\n            { typeof(List<Ray2f>), c => { var v = default(List<Ray2f>); c.CodeList_of_Ray2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Ray2f>), c => { var v = default(Vector<Ray2f>); c.CodeVector_of_Ray2f_(ref v); return v; } },\r\n            { typeof(Vector<Ray2f>[]), c => { var v = default(Vector<Ray2f>[]); c.CodeVector_of_Ray2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Ray2f>>), c => { var v = default(List<Vector<Ray2f>>); c.CodeList_of_Vector_of_Ray2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Ray2f>), c => { var v = default(Matrix<Ray2f>); c.CodeMatrix_of_Ray2f_(ref v); return v; } },\r\n            { typeof(Matrix<Ray2f>[]), c => { var v = default(Matrix<Ray2f>[]); c.CodeMatrix_of_Ray2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Ray2f>>), c => { var v = default(List<Matrix<Ray2f>>); c.CodeList_of_Matrix_of_Ray2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Ray2f>), c => { var v = default(Volume<Ray2f>); c.CodeVolume_of_Ray2f_(ref v); return v; } },\r\n            { typeof(Volume<Ray2f>[]), c => { var v = default(Volume<Ray2f>[]); c.CodeVolume_of_Ray2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Ray2f>>), c => { var v = default(List<Volume<Ray2f>>); c.CodeList_of_Volume_of_Ray2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Ray2f>), c => { var v = default(Tensor<Ray2f>); c.CodeTensor_of_Ray2f_(ref v); return v; } },\r\n            { typeof(Tensor<Ray2f>[]), c => { var v = default(Tensor<Ray2f>[]); c.CodeTensor_of_Ray2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Ray2f>>), c => { var v = default(List<Tensor<Ray2f>>); c.CodeList_of_Tensor_of_Ray2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Ray3f\r\n\r\n            { typeof(Ray3f), c => { var v = default(Ray3f); c.CodeRay3f(ref v); return v; } },\r\n            { typeof(Ray3f[]), c => { var v = default(Ray3f[]); c.CodeRay3fArray(ref v); return v; } },\r\n            { typeof(List<Ray3f>), c => { var v = default(List<Ray3f>); c.CodeList_of_Ray3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Ray3f>), c => { var v = default(Vector<Ray3f>); c.CodeVector_of_Ray3f_(ref v); return v; } },\r\n            { typeof(Vector<Ray3f>[]), c => { var v = default(Vector<Ray3f>[]); c.CodeVector_of_Ray3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Ray3f>>), c => { var v = default(List<Vector<Ray3f>>); c.CodeList_of_Vector_of_Ray3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Ray3f>), c => { var v = default(Matrix<Ray3f>); c.CodeMatrix_of_Ray3f_(ref v); return v; } },\r\n            { typeof(Matrix<Ray3f>[]), c => { var v = default(Matrix<Ray3f>[]); c.CodeMatrix_of_Ray3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Ray3f>>), c => { var v = default(List<Matrix<Ray3f>>); c.CodeList_of_Matrix_of_Ray3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Ray3f>), c => { var v = default(Volume<Ray3f>); c.CodeVolume_of_Ray3f_(ref v); return v; } },\r\n            { typeof(Volume<Ray3f>[]), c => { var v = default(Volume<Ray3f>[]); c.CodeVolume_of_Ray3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Ray3f>>), c => { var v = default(List<Volume<Ray3f>>); c.CodeList_of_Volume_of_Ray3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Ray3f>), c => { var v = default(Tensor<Ray3f>); c.CodeTensor_of_Ray3f_(ref v); return v; } },\r\n            { typeof(Tensor<Ray3f>[]), c => { var v = default(Tensor<Ray3f>[]); c.CodeTensor_of_Ray3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Ray3f>>), c => { var v = default(List<Tensor<Ray3f>>); c.CodeList_of_Tensor_of_Ray3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Sphere3f\r\n\r\n            { typeof(Sphere3f), c => { var v = default(Sphere3f); c.CodeSphere3f(ref v); return v; } },\r\n            { typeof(Sphere3f[]), c => { var v = default(Sphere3f[]); c.CodeSphere3fArray(ref v); return v; } },\r\n            { typeof(List<Sphere3f>), c => { var v = default(List<Sphere3f>); c.CodeList_of_Sphere3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Sphere3f>), c => { var v = default(Vector<Sphere3f>); c.CodeVector_of_Sphere3f_(ref v); return v; } },\r\n            { typeof(Vector<Sphere3f>[]), c => { var v = default(Vector<Sphere3f>[]); c.CodeVector_of_Sphere3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Sphere3f>>), c => { var v = default(List<Vector<Sphere3f>>); c.CodeList_of_Vector_of_Sphere3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Sphere3f>), c => { var v = default(Matrix<Sphere3f>); c.CodeMatrix_of_Sphere3f_(ref v); return v; } },\r\n            { typeof(Matrix<Sphere3f>[]), c => { var v = default(Matrix<Sphere3f>[]); c.CodeMatrix_of_Sphere3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Sphere3f>>), c => { var v = default(List<Matrix<Sphere3f>>); c.CodeList_of_Matrix_of_Sphere3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Sphere3f>), c => { var v = default(Volume<Sphere3f>); c.CodeVolume_of_Sphere3f_(ref v); return v; } },\r\n            { typeof(Volume<Sphere3f>[]), c => { var v = default(Volume<Sphere3f>[]); c.CodeVolume_of_Sphere3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Sphere3f>>), c => { var v = default(List<Volume<Sphere3f>>); c.CodeList_of_Volume_of_Sphere3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Sphere3f>), c => { var v = default(Tensor<Sphere3f>); c.CodeTensor_of_Sphere3f_(ref v); return v; } },\r\n            { typeof(Tensor<Sphere3f>[]), c => { var v = default(Tensor<Sphere3f>[]); c.CodeTensor_of_Sphere3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Sphere3f>>), c => { var v = default(List<Tensor<Sphere3f>>); c.CodeList_of_Tensor_of_Sphere3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Triangle2f\r\n\r\n            { typeof(Triangle2f), c => { var v = default(Triangle2f); c.CodeTriangle2f(ref v); return v; } },\r\n            { typeof(Triangle2f[]), c => { var v = default(Triangle2f[]); c.CodeTriangle2fArray(ref v); return v; } },\r\n            { typeof(List<Triangle2f>), c => { var v = default(List<Triangle2f>); c.CodeList_of_Triangle2f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Triangle2f>), c => { var v = default(Vector<Triangle2f>); c.CodeVector_of_Triangle2f_(ref v); return v; } },\r\n            { typeof(Vector<Triangle2f>[]), c => { var v = default(Vector<Triangle2f>[]); c.CodeVector_of_Triangle2f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Triangle2f>>), c => { var v = default(List<Vector<Triangle2f>>); c.CodeList_of_Vector_of_Triangle2f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Triangle2f>), c => { var v = default(Matrix<Triangle2f>); c.CodeMatrix_of_Triangle2f_(ref v); return v; } },\r\n            { typeof(Matrix<Triangle2f>[]), c => { var v = default(Matrix<Triangle2f>[]); c.CodeMatrix_of_Triangle2f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Triangle2f>>), c => { var v = default(List<Matrix<Triangle2f>>); c.CodeList_of_Matrix_of_Triangle2f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Triangle2f>), c => { var v = default(Volume<Triangle2f>); c.CodeVolume_of_Triangle2f_(ref v); return v; } },\r\n            { typeof(Volume<Triangle2f>[]), c => { var v = default(Volume<Triangle2f>[]); c.CodeVolume_of_Triangle2f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Triangle2f>>), c => { var v = default(List<Volume<Triangle2f>>); c.CodeList_of_Volume_of_Triangle2f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Triangle2f>), c => { var v = default(Tensor<Triangle2f>); c.CodeTensor_of_Triangle2f_(ref v); return v; } },\r\n            { typeof(Tensor<Triangle2f>[]), c => { var v = default(Tensor<Triangle2f>[]); c.CodeTensor_of_Triangle2f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Triangle2f>>), c => { var v = default(List<Tensor<Triangle2f>>); c.CodeList_of_Tensor_of_Triangle2f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Triangle3f\r\n\r\n            { typeof(Triangle3f), c => { var v = default(Triangle3f); c.CodeTriangle3f(ref v); return v; } },\r\n            { typeof(Triangle3f[]), c => { var v = default(Triangle3f[]); c.CodeTriangle3fArray(ref v); return v; } },\r\n            { typeof(List<Triangle3f>), c => { var v = default(List<Triangle3f>); c.CodeList_of_Triangle3f_(ref v); return v; } },\r\n\r\n            { typeof(Vector<Triangle3f>), c => { var v = default(Vector<Triangle3f>); c.CodeVector_of_Triangle3f_(ref v); return v; } },\r\n            { typeof(Vector<Triangle3f>[]), c => { var v = default(Vector<Triangle3f>[]); c.CodeVector_of_Triangle3f_Array(ref v); return v; } },\r\n            { typeof(List<Vector<Triangle3f>>), c => { var v = default(List<Vector<Triangle3f>>); c.CodeList_of_Vector_of_Triangle3f__(ref v); return v; } },\r\n\r\n            { typeof(Matrix<Triangle3f>), c => { var v = default(Matrix<Triangle3f>); c.CodeMatrix_of_Triangle3f_(ref v); return v; } },\r\n            { typeof(Matrix<Triangle3f>[]), c => { var v = default(Matrix<Triangle3f>[]); c.CodeMatrix_of_Triangle3f_Array(ref v); return v; } },\r\n            { typeof(List<Matrix<Triangle3f>>), c => { var v = default(List<Matrix<Triangle3f>>); c.CodeList_of_Matrix_of_Triangle3f__(ref v); return v; } },\r\n\r\n            { typeof(Volume<Triangle3f>), c => { var v = default(Volume<Triangle3f>); c.CodeVolume_of_Triangle3f_(ref v); return v; } },\r\n            { typeof(Volume<Triangle3f>[]), c => { var v = default(Volume<Triangle3f>[]); c.CodeVolume_of_Triangle3f_Array(ref v); return v; } },\r\n            { typeof(List<Volume<Triangle3f>>), c => { var v = default(List<Volume<Triangle3f>>); c.CodeList_of_Volume_of_Triangle3f__(ref v); return v; } },\r\n\r\n            { typeof(Tensor<Triangle3f>), c => { var v = default(Tensor<Triangle3f>); c.CodeTensor_of_Triangle3f_(ref v); return v; } },\r\n            { typeof(Tensor<Triangle3f>[]), c => { var v = default(Tensor<Triangle3f>[]); c.CodeTensor_of_Triangle3f_Array(ref v); return v; } },\r\n            { typeof(List<Tensor<Triangle3f>>), c => { var v = default(List<Tensor<Triangle3f>>); c.CodeList_of_Tensor_of_Triangle3f__(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Multi-Dimensional Arrays\r\n\r\n            { typeof(byte[,]), c => { var v = default(byte[,]); c.CodeByteArray2d(ref v); return v; } },\r\n            { typeof(byte[, ,]), c => { var v = default(byte[, ,]); c.CodeByteArray3d(ref v); return v; } },\r\n            { typeof(sbyte[,]), c => { var v = default(sbyte[,]); c.CodeSByteArray2d(ref v); return v; } },\r\n            { typeof(sbyte[, ,]), c => { var v = default(sbyte[, ,]); c.CodeSByteArray3d(ref v); return v; } },\r\n            { typeof(short[,]), c => { var v = default(short[,]); c.CodeShortArray2d(ref v); return v; } },\r\n            { typeof(short[, ,]), c => { var v = default(short[, ,]); c.CodeShortArray3d(ref v); return v; } },\r\n            { typeof(ushort[,]), c => { var v = default(ushort[,]); c.CodeUShortArray2d(ref v); return v; } },\r\n            { typeof(ushort[, ,]), c => { var v = default(ushort[, ,]); c.CodeUShortArray3d(ref v); return v; } },\r\n            { typeof(int[,]), c => { var v = default(int[,]); c.CodeIntArray2d(ref v); return v; } },\r\n            { typeof(int[, ,]), c => { var v = default(int[, ,]); c.CodeIntArray3d(ref v); return v; } },\r\n            { typeof(uint[,]), c => { var v = default(uint[,]); c.CodeUIntArray2d(ref v); return v; } },\r\n            { typeof(uint[, ,]), c => { var v = default(uint[, ,]); c.CodeUIntArray3d(ref v); return v; } },\r\n            { typeof(long[,]), c => { var v = default(long[,]); c.CodeLongArray2d(ref v); return v; } },\r\n            { typeof(long[, ,]), c => { var v = default(long[, ,]); c.CodeLongArray3d(ref v); return v; } },\r\n            { typeof(ulong[,]), c => { var v = default(ulong[,]); c.CodeULongArray2d(ref v); return v; } },\r\n            { typeof(ulong[, ,]), c => { var v = default(ulong[, ,]); c.CodeULongArray3d(ref v); return v; } },\r\n            { typeof(float[,]), c => { var v = default(float[,]); c.CodeFloatArray2d(ref v); return v; } },\r\n            { typeof(float[, ,]), c => { var v = default(float[, ,]); c.CodeFloatArray3d(ref v); return v; } },\r\n            { typeof(double[,]), c => { var v = default(double[,]); c.CodeDoubleArray2d(ref v); return v; } },\r\n            { typeof(double[, ,]), c => { var v = default(double[, ,]); c.CodeDoubleArray3d(ref v); return v; } },\r\n            { typeof(Fraction[,]), c => { var v = default(Fraction[,]); c.CodeFractionArray2d(ref v); return v; } },\r\n            { typeof(Fraction[, ,]), c => { var v = default(Fraction[, ,]); c.CodeFractionArray3d(ref v); return v; } },\r\n            { typeof(V2i[,]), c => { var v = default(V2i[,]); c.CodeV2iArray2d(ref v); return v; } },\r\n            { typeof(V2i[, ,]), c => { var v = default(V2i[, ,]); c.CodeV2iArray3d(ref v); return v; } },\r\n            { typeof(V2l[,]), c => { var v = default(V2l[,]); c.CodeV2lArray2d(ref v); return v; } },\r\n            { typeof(V2l[, ,]), c => { var v = default(V2l[, ,]); c.CodeV2lArray3d(ref v); return v; } },\r\n            { typeof(V2f[,]), c => { var v = default(V2f[,]); c.CodeV2fArray2d(ref v); return v; } },\r\n            { typeof(V2f[, ,]), c => { var v = default(V2f[, ,]); c.CodeV2fArray3d(ref v); return v; } },\r\n            { typeof(V2d[,]), c => { var v = default(V2d[,]); c.CodeV2dArray2d(ref v); return v; } },\r\n            { typeof(V2d[, ,]), c => { var v = default(V2d[, ,]); c.CodeV2dArray3d(ref v); return v; } },\r\n            { typeof(V3i[,]), c => { var v = default(V3i[,]); c.CodeV3iArray2d(ref v); return v; } },\r\n            { typeof(V3i[, ,]), c => { var v = default(V3i[, ,]); c.CodeV3iArray3d(ref v); return v; } },\r\n            { typeof(V3l[,]), c => { var v = default(V3l[,]); c.CodeV3lArray2d(ref v); return v; } },\r\n            { typeof(V3l[, ,]), c => { var v = default(V3l[, ,]); c.CodeV3lArray3d(ref v); return v; } },\r\n            { typeof(V3f[,]), c => { var v = default(V3f[,]); c.CodeV3fArray2d(ref v); return v; } },\r\n            { typeof(V3f[, ,]), c => { var v = default(V3f[, ,]); c.CodeV3fArray3d(ref v); return v; } },\r\n            { typeof(V3d[,]), c => { var v = default(V3d[,]); c.CodeV3dArray2d(ref v); return v; } },\r\n            { typeof(V3d[, ,]), c => { var v = default(V3d[, ,]); c.CodeV3dArray3d(ref v); return v; } },\r\n            { typeof(V4i[,]), c => { var v = default(V4i[,]); c.CodeV4iArray2d(ref v); return v; } },\r\n            { typeof(V4i[, ,]), c => { var v = default(V4i[, ,]); c.CodeV4iArray3d(ref v); return v; } },\r\n            { typeof(V4l[,]), c => { var v = default(V4l[,]); c.CodeV4lArray2d(ref v); return v; } },\r\n            { typeof(V4l[, ,]), c => { var v = default(V4l[, ,]); c.CodeV4lArray3d(ref v); return v; } },\r\n            { typeof(V4f[,]), c => { var v = default(V4f[,]); c.CodeV4fArray2d(ref v); return v; } },\r\n            { typeof(V4f[, ,]), c => { var v = default(V4f[, ,]); c.CodeV4fArray3d(ref v); return v; } },\r\n            { typeof(V4d[,]), c => { var v = default(V4d[,]); c.CodeV4dArray2d(ref v); return v; } },\r\n            { typeof(V4d[, ,]), c => { var v = default(V4d[, ,]); c.CodeV4dArray3d(ref v); return v; } },\r\n            { typeof(M22i[,]), c => { var v = default(M22i[,]); c.CodeM22iArray2d(ref v); return v; } },\r\n            { typeof(M22i[, ,]), c => { var v = default(M22i[, ,]); c.CodeM22iArray3d(ref v); return v; } },\r\n            { typeof(M22l[,]), c => { var v = default(M22l[,]); c.CodeM22lArray2d(ref v); return v; } },\r\n            { typeof(M22l[, ,]), c => { var v = default(M22l[, ,]); c.CodeM22lArray3d(ref v); return v; } },\r\n            { typeof(M22f[,]), c => { var v = default(M22f[,]); c.CodeM22fArray2d(ref v); return v; } },\r\n            { typeof(M22f[, ,]), c => { var v = default(M22f[, ,]); c.CodeM22fArray3d(ref v); return v; } },\r\n            { typeof(M22d[,]), c => { var v = default(M22d[,]); c.CodeM22dArray2d(ref v); return v; } },\r\n            { typeof(M22d[, ,]), c => { var v = default(M22d[, ,]); c.CodeM22dArray3d(ref v); return v; } },\r\n            { typeof(M23i[,]), c => { var v = default(M23i[,]); c.CodeM23iArray2d(ref v); return v; } },\r\n            { typeof(M23i[, ,]), c => { var v = default(M23i[, ,]); c.CodeM23iArray3d(ref v); return v; } },\r\n            { typeof(M23l[,]), c => { var v = default(M23l[,]); c.CodeM23lArray2d(ref v); return v; } },\r\n            { typeof(M23l[, ,]), c => { var v = default(M23l[, ,]); c.CodeM23lArray3d(ref v); return v; } },\r\n            { typeof(M23f[,]), c => { var v = default(M23f[,]); c.CodeM23fArray2d(ref v); return v; } },\r\n            { typeof(M23f[, ,]), c => { var v = default(M23f[, ,]); c.CodeM23fArray3d(ref v); return v; } },\r\n            { typeof(M23d[,]), c => { var v = default(M23d[,]); c.CodeM23dArray2d(ref v); return v; } },\r\n            { typeof(M23d[, ,]), c => { var v = default(M23d[, ,]); c.CodeM23dArray3d(ref v); return v; } },\r\n            { typeof(M33i[,]), c => { var v = default(M33i[,]); c.CodeM33iArray2d(ref v); return v; } },\r\n            { typeof(M33i[, ,]), c => { var v = default(M33i[, ,]); c.CodeM33iArray3d(ref v); return v; } },\r\n            { typeof(M33l[,]), c => { var v = default(M33l[,]); c.CodeM33lArray2d(ref v); return v; } },\r\n            { typeof(M33l[, ,]), c => { var v = default(M33l[, ,]); c.CodeM33lArray3d(ref v); return v; } },\r\n            { typeof(M33f[,]), c => { var v = default(M33f[,]); c.CodeM33fArray2d(ref v); return v; } },\r\n            { typeof(M33f[, ,]), c => { var v = default(M33f[, ,]); c.CodeM33fArray3d(ref v); return v; } },\r\n            { typeof(M33d[,]), c => { var v = default(M33d[,]); c.CodeM33dArray2d(ref v); return v; } },\r\n            { typeof(M33d[, ,]), c => { var v = default(M33d[, ,]); c.CodeM33dArray3d(ref v); return v; } },\r\n            { typeof(M34i[,]), c => { var v = default(M34i[,]); c.CodeM34iArray2d(ref v); return v; } },\r\n            { typeof(M34i[, ,]), c => { var v = default(M34i[, ,]); c.CodeM34iArray3d(ref v); return v; } },\r\n            { typeof(M34l[,]), c => { var v = default(M34l[,]); c.CodeM34lArray2d(ref v); return v; } },\r\n            { typeof(M34l[, ,]), c => { var v = default(M34l[, ,]); c.CodeM34lArray3d(ref v); return v; } },\r\n            { typeof(M34f[,]), c => { var v = default(M34f[,]); c.CodeM34fArray2d(ref v); return v; } },\r\n            { typeof(M34f[, ,]), c => { var v = default(M34f[, ,]); c.CodeM34fArray3d(ref v); return v; } },\r\n            { typeof(M34d[,]), c => { var v = default(M34d[,]); c.CodeM34dArray2d(ref v); return v; } },\r\n            { typeof(M34d[, ,]), c => { var v = default(M34d[, ,]); c.CodeM34dArray3d(ref v); return v; } },\r\n            { typeof(M44i[,]), c => { var v = default(M44i[,]); c.CodeM44iArray2d(ref v); return v; } },\r\n            { typeof(M44i[, ,]), c => { var v = default(M44i[, ,]); c.CodeM44iArray3d(ref v); return v; } },\r\n            { typeof(M44l[,]), c => { var v = default(M44l[,]); c.CodeM44lArray2d(ref v); return v; } },\r\n            { typeof(M44l[, ,]), c => { var v = default(M44l[, ,]); c.CodeM44lArray3d(ref v); return v; } },\r\n            { typeof(M44f[,]), c => { var v = default(M44f[,]); c.CodeM44fArray2d(ref v); return v; } },\r\n            { typeof(M44f[, ,]), c => { var v = default(M44f[, ,]); c.CodeM44fArray3d(ref v); return v; } },\r\n            { typeof(M44d[,]), c => { var v = default(M44d[,]); c.CodeM44dArray2d(ref v); return v; } },\r\n            { typeof(M44d[, ,]), c => { var v = default(M44d[, ,]); c.CodeM44dArray3d(ref v); return v; } },\r\n            { typeof(C3b[,]), c => { var v = default(C3b[,]); c.CodeC3bArray2d(ref v); return v; } },\r\n            { typeof(C3b[, ,]), c => { var v = default(C3b[, ,]); c.CodeC3bArray3d(ref v); return v; } },\r\n            { typeof(C3us[,]), c => { var v = default(C3us[,]); c.CodeC3usArray2d(ref v); return v; } },\r\n            { typeof(C3us[, ,]), c => { var v = default(C3us[, ,]); c.CodeC3usArray3d(ref v); return v; } },\r\n            { typeof(C3ui[,]), c => { var v = default(C3ui[,]); c.CodeC3uiArray2d(ref v); return v; } },\r\n            { typeof(C3ui[, ,]), c => { var v = default(C3ui[, ,]); c.CodeC3uiArray3d(ref v); return v; } },\r\n            { typeof(C3f[,]), c => { var v = default(C3f[,]); c.CodeC3fArray2d(ref v); return v; } },\r\n            { typeof(C3f[, ,]), c => { var v = default(C3f[, ,]); c.CodeC3fArray3d(ref v); return v; } },\r\n            { typeof(C3d[,]), c => { var v = default(C3d[,]); c.CodeC3dArray2d(ref v); return v; } },\r\n            { typeof(C3d[, ,]), c => { var v = default(C3d[, ,]); c.CodeC3dArray3d(ref v); return v; } },\r\n            { typeof(C4b[,]), c => { var v = default(C4b[,]); c.CodeC4bArray2d(ref v); return v; } },\r\n            { typeof(C4b[, ,]), c => { var v = default(C4b[, ,]); c.CodeC4bArray3d(ref v); return v; } },\r\n            { typeof(C4us[,]), c => { var v = default(C4us[,]); c.CodeC4usArray2d(ref v); return v; } },\r\n            { typeof(C4us[, ,]), c => { var v = default(C4us[, ,]); c.CodeC4usArray3d(ref v); return v; } },\r\n            { typeof(C4ui[,]), c => { var v = default(C4ui[,]); c.CodeC4uiArray2d(ref v); return v; } },\r\n            { typeof(C4ui[, ,]), c => { var v = default(C4ui[, ,]); c.CodeC4uiArray3d(ref v); return v; } },\r\n            { typeof(C4f[,]), c => { var v = default(C4f[,]); c.CodeC4fArray2d(ref v); return v; } },\r\n            { typeof(C4f[, ,]), c => { var v = default(C4f[, ,]); c.CodeC4fArray3d(ref v); return v; } },\r\n            { typeof(C4d[,]), c => { var v = default(C4d[,]); c.CodeC4dArray2d(ref v); return v; } },\r\n            { typeof(C4d[, ,]), c => { var v = default(C4d[, ,]); c.CodeC4dArray3d(ref v); return v; } },\r\n            { typeof(Range1b[,]), c => { var v = default(Range1b[,]); c.CodeRange1bArray2d(ref v); return v; } },\r\n            { typeof(Range1b[, ,]), c => { var v = default(Range1b[, ,]); c.CodeRange1bArray3d(ref v); return v; } },\r\n            { typeof(Range1sb[,]), c => { var v = default(Range1sb[,]); c.CodeRange1sbArray2d(ref v); return v; } },\r\n            { typeof(Range1sb[, ,]), c => { var v = default(Range1sb[, ,]); c.CodeRange1sbArray3d(ref v); return v; } },\r\n            { typeof(Range1s[,]), c => { var v = default(Range1s[,]); c.CodeRange1sArray2d(ref v); return v; } },\r\n            { typeof(Range1s[, ,]), c => { var v = default(Range1s[, ,]); c.CodeRange1sArray3d(ref v); return v; } },\r\n            { typeof(Range1us[,]), c => { var v = default(Range1us[,]); c.CodeRange1usArray2d(ref v); return v; } },\r\n            { typeof(Range1us[, ,]), c => { var v = default(Range1us[, ,]); c.CodeRange1usArray3d(ref v); return v; } },\r\n            { typeof(Range1i[,]), c => { var v = default(Range1i[,]); c.CodeRange1iArray2d(ref v); return v; } },\r\n            { typeof(Range1i[, ,]), c => { var v = default(Range1i[, ,]); c.CodeRange1iArray3d(ref v); return v; } },\r\n            { typeof(Range1ui[,]), c => { var v = default(Range1ui[,]); c.CodeRange1uiArray2d(ref v); return v; } },\r\n            { typeof(Range1ui[, ,]), c => { var v = default(Range1ui[, ,]); c.CodeRange1uiArray3d(ref v); return v; } },\r\n            { typeof(Range1l[,]), c => { var v = default(Range1l[,]); c.CodeRange1lArray2d(ref v); return v; } },\r\n            { typeof(Range1l[, ,]), c => { var v = default(Range1l[, ,]); c.CodeRange1lArray3d(ref v); return v; } },\r\n            { typeof(Range1ul[,]), c => { var v = default(Range1ul[,]); c.CodeRange1ulArray2d(ref v); return v; } },\r\n            { typeof(Range1ul[, ,]), c => { var v = default(Range1ul[, ,]); c.CodeRange1ulArray3d(ref v); return v; } },\r\n            { typeof(Range1f[,]), c => { var v = default(Range1f[,]); c.CodeRange1fArray2d(ref v); return v; } },\r\n            { typeof(Range1f[, ,]), c => { var v = default(Range1f[, ,]); c.CodeRange1fArray3d(ref v); return v; } },\r\n            { typeof(Range1d[,]), c => { var v = default(Range1d[,]); c.CodeRange1dArray2d(ref v); return v; } },\r\n            { typeof(Range1d[, ,]), c => { var v = default(Range1d[, ,]); c.CodeRange1dArray3d(ref v); return v; } },\r\n            { typeof(Box2i[,]), c => { var v = default(Box2i[,]); c.CodeBox2iArray2d(ref v); return v; } },\r\n            { typeof(Box2i[, ,]), c => { var v = default(Box2i[, ,]); c.CodeBox2iArray3d(ref v); return v; } },\r\n            { typeof(Box2l[,]), c => { var v = default(Box2l[,]); c.CodeBox2lArray2d(ref v); return v; } },\r\n            { typeof(Box2l[, ,]), c => { var v = default(Box2l[, ,]); c.CodeBox2lArray3d(ref v); return v; } },\r\n            { typeof(Box2f[,]), c => { var v = default(Box2f[,]); c.CodeBox2fArray2d(ref v); return v; } },\r\n            { typeof(Box2f[, ,]), c => { var v = default(Box2f[, ,]); c.CodeBox2fArray3d(ref v); return v; } },\r\n            { typeof(Box2d[,]), c => { var v = default(Box2d[,]); c.CodeBox2dArray2d(ref v); return v; } },\r\n            { typeof(Box2d[, ,]), c => { var v = default(Box2d[, ,]); c.CodeBox2dArray3d(ref v); return v; } },\r\n            { typeof(Box3i[,]), c => { var v = default(Box3i[,]); c.CodeBox3iArray2d(ref v); return v; } },\r\n            { typeof(Box3i[, ,]), c => { var v = default(Box3i[, ,]); c.CodeBox3iArray3d(ref v); return v; } },\r\n            { typeof(Box3l[,]), c => { var v = default(Box3l[,]); c.CodeBox3lArray2d(ref v); return v; } },\r\n            { typeof(Box3l[, ,]), c => { var v = default(Box3l[, ,]); c.CodeBox3lArray3d(ref v); return v; } },\r\n            { typeof(Box3f[,]), c => { var v = default(Box3f[,]); c.CodeBox3fArray2d(ref v); return v; } },\r\n            { typeof(Box3f[, ,]), c => { var v = default(Box3f[, ,]); c.CodeBox3fArray3d(ref v); return v; } },\r\n            { typeof(Box3d[,]), c => { var v = default(Box3d[,]); c.CodeBox3dArray2d(ref v); return v; } },\r\n            { typeof(Box3d[, ,]), c => { var v = default(Box3d[, ,]); c.CodeBox3dArray3d(ref v); return v; } },\r\n            { typeof(Euclidean3f[,]), c => { var v = default(Euclidean3f[,]); c.CodeEuclidean3fArray2d(ref v); return v; } },\r\n            { typeof(Euclidean3f[, ,]), c => { var v = default(Euclidean3f[, ,]); c.CodeEuclidean3fArray3d(ref v); return v; } },\r\n            { typeof(Euclidean3d[,]), c => { var v = default(Euclidean3d[,]); c.CodeEuclidean3dArray2d(ref v); return v; } },\r\n            { typeof(Euclidean3d[, ,]), c => { var v = default(Euclidean3d[, ,]); c.CodeEuclidean3dArray3d(ref v); return v; } },\r\n            { typeof(Rot2f[,]), c => { var v = default(Rot2f[,]); c.CodeRot2fArray2d(ref v); return v; } },\r\n            { typeof(Rot2f[, ,]), c => { var v = default(Rot2f[, ,]); c.CodeRot2fArray3d(ref v); return v; } },\r\n            { typeof(Rot2d[,]), c => { var v = default(Rot2d[,]); c.CodeRot2dArray2d(ref v); return v; } },\r\n            { typeof(Rot2d[, ,]), c => { var v = default(Rot2d[, ,]); c.CodeRot2dArray3d(ref v); return v; } },\r\n            { typeof(Rot3f[,]), c => { var v = default(Rot3f[,]); c.CodeRot3fArray2d(ref v); return v; } },\r\n            { typeof(Rot3f[, ,]), c => { var v = default(Rot3f[, ,]); c.CodeRot3fArray3d(ref v); return v; } },\r\n            { typeof(Rot3d[,]), c => { var v = default(Rot3d[,]); c.CodeRot3dArray2d(ref v); return v; } },\r\n            { typeof(Rot3d[, ,]), c => { var v = default(Rot3d[, ,]); c.CodeRot3dArray3d(ref v); return v; } },\r\n            { typeof(Scale3f[,]), c => { var v = default(Scale3f[,]); c.CodeScale3fArray2d(ref v); return v; } },\r\n            { typeof(Scale3f[, ,]), c => { var v = default(Scale3f[, ,]); c.CodeScale3fArray3d(ref v); return v; } },\r\n            { typeof(Scale3d[,]), c => { var v = default(Scale3d[,]); c.CodeScale3dArray2d(ref v); return v; } },\r\n            { typeof(Scale3d[, ,]), c => { var v = default(Scale3d[, ,]); c.CodeScale3dArray3d(ref v); return v; } },\r\n            { typeof(Shift3f[,]), c => { var v = default(Shift3f[,]); c.CodeShift3fArray2d(ref v); return v; } },\r\n            { typeof(Shift3f[, ,]), c => { var v = default(Shift3f[, ,]); c.CodeShift3fArray3d(ref v); return v; } },\r\n            { typeof(Shift3d[,]), c => { var v = default(Shift3d[,]); c.CodeShift3dArray2d(ref v); return v; } },\r\n            { typeof(Shift3d[, ,]), c => { var v = default(Shift3d[, ,]); c.CodeShift3dArray3d(ref v); return v; } },\r\n            { typeof(Trafo2f[,]), c => { var v = default(Trafo2f[,]); c.CodeTrafo2fArray2d(ref v); return v; } },\r\n            { typeof(Trafo2f[, ,]), c => { var v = default(Trafo2f[, ,]); c.CodeTrafo2fArray3d(ref v); return v; } },\r\n            { typeof(Trafo2d[,]), c => { var v = default(Trafo2d[,]); c.CodeTrafo2dArray2d(ref v); return v; } },\r\n            { typeof(Trafo2d[, ,]), c => { var v = default(Trafo2d[, ,]); c.CodeTrafo2dArray3d(ref v); return v; } },\r\n            { typeof(Trafo3f[,]), c => { var v = default(Trafo3f[,]); c.CodeTrafo3fArray2d(ref v); return v; } },\r\n            { typeof(Trafo3f[, ,]), c => { var v = default(Trafo3f[, ,]); c.CodeTrafo3fArray3d(ref v); return v; } },\r\n            { typeof(Trafo3d[,]), c => { var v = default(Trafo3d[,]); c.CodeTrafo3dArray2d(ref v); return v; } },\r\n            { typeof(Trafo3d[, ,]), c => { var v = default(Trafo3d[, ,]); c.CodeTrafo3dArray3d(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Jagged Multi-Dimensional Arrays\r\n\r\n            { typeof(byte[][]), c => { var v = default(byte[][]); c.CodeByteArrayArray(ref v); return v; } },\r\n            { typeof(byte[][][]), c => { var v = default(byte[][][]); c.CodeByteArrayArrayArray(ref v); return v; } },\r\n            { typeof(sbyte[][]), c => { var v = default(sbyte[][]); c.CodeSByteArrayArray(ref v); return v; } },\r\n            { typeof(sbyte[][][]), c => { var v = default(sbyte[][][]); c.CodeSByteArrayArrayArray(ref v); return v; } },\r\n            { typeof(short[][]), c => { var v = default(short[][]); c.CodeShortArrayArray(ref v); return v; } },\r\n            { typeof(short[][][]), c => { var v = default(short[][][]); c.CodeShortArrayArrayArray(ref v); return v; } },\r\n            { typeof(ushort[][]), c => { var v = default(ushort[][]); c.CodeUShortArrayArray(ref v); return v; } },\r\n            { typeof(ushort[][][]), c => { var v = default(ushort[][][]); c.CodeUShortArrayArrayArray(ref v); return v; } },\r\n            { typeof(int[][]), c => { var v = default(int[][]); c.CodeIntArrayArray(ref v); return v; } },\r\n            { typeof(int[][][]), c => { var v = default(int[][][]); c.CodeIntArrayArrayArray(ref v); return v; } },\r\n            { typeof(uint[][]), c => { var v = default(uint[][]); c.CodeUIntArrayArray(ref v); return v; } },\r\n            { typeof(uint[][][]), c => { var v = default(uint[][][]); c.CodeUIntArrayArrayArray(ref v); return v; } },\r\n            { typeof(long[][]), c => { var v = default(long[][]); c.CodeLongArrayArray(ref v); return v; } },\r\n            { typeof(long[][][]), c => { var v = default(long[][][]); c.CodeLongArrayArrayArray(ref v); return v; } },\r\n            { typeof(ulong[][]), c => { var v = default(ulong[][]); c.CodeULongArrayArray(ref v); return v; } },\r\n            { typeof(ulong[][][]), c => { var v = default(ulong[][][]); c.CodeULongArrayArrayArray(ref v); return v; } },\r\n            { typeof(float[][]), c => { var v = default(float[][]); c.CodeFloatArrayArray(ref v); return v; } },\r\n            { typeof(float[][][]), c => { var v = default(float[][][]); c.CodeFloatArrayArrayArray(ref v); return v; } },\r\n            { typeof(double[][]), c => { var v = default(double[][]); c.CodeDoubleArrayArray(ref v); return v; } },\r\n            { typeof(double[][][]), c => { var v = default(double[][][]); c.CodeDoubleArrayArrayArray(ref v); return v; } },\r\n            { typeof(Fraction[][]), c => { var v = default(Fraction[][]); c.CodeFractionArrayArray(ref v); return v; } },\r\n            { typeof(Fraction[][][]), c => { var v = default(Fraction[][][]); c.CodeFractionArrayArrayArray(ref v); return v; } },\r\n            { typeof(V2i[][]), c => { var v = default(V2i[][]); c.CodeV2iArrayArray(ref v); return v; } },\r\n            { typeof(V2i[][][]), c => { var v = default(V2i[][][]); c.CodeV2iArrayArrayArray(ref v); return v; } },\r\n            { typeof(V2l[][]), c => { var v = default(V2l[][]); c.CodeV2lArrayArray(ref v); return v; } },\r\n            { typeof(V2l[][][]), c => { var v = default(V2l[][][]); c.CodeV2lArrayArrayArray(ref v); return v; } },\r\n            { typeof(V2f[][]), c => { var v = default(V2f[][]); c.CodeV2fArrayArray(ref v); return v; } },\r\n            { typeof(V2f[][][]), c => { var v = default(V2f[][][]); c.CodeV2fArrayArrayArray(ref v); return v; } },\r\n            { typeof(V2d[][]), c => { var v = default(V2d[][]); c.CodeV2dArrayArray(ref v); return v; } },\r\n            { typeof(V2d[][][]), c => { var v = default(V2d[][][]); c.CodeV2dArrayArrayArray(ref v); return v; } },\r\n            { typeof(V3i[][]), c => { var v = default(V3i[][]); c.CodeV3iArrayArray(ref v); return v; } },\r\n            { typeof(V3i[][][]), c => { var v = default(V3i[][][]); c.CodeV3iArrayArrayArray(ref v); return v; } },\r\n            { typeof(V3l[][]), c => { var v = default(V3l[][]); c.CodeV3lArrayArray(ref v); return v; } },\r\n            { typeof(V3l[][][]), c => { var v = default(V3l[][][]); c.CodeV3lArrayArrayArray(ref v); return v; } },\r\n            { typeof(V3f[][]), c => { var v = default(V3f[][]); c.CodeV3fArrayArray(ref v); return v; } },\r\n            { typeof(V3f[][][]), c => { var v = default(V3f[][][]); c.CodeV3fArrayArrayArray(ref v); return v; } },\r\n            { typeof(V3d[][]), c => { var v = default(V3d[][]); c.CodeV3dArrayArray(ref v); return v; } },\r\n            { typeof(V3d[][][]), c => { var v = default(V3d[][][]); c.CodeV3dArrayArrayArray(ref v); return v; } },\r\n            { typeof(V4i[][]), c => { var v = default(V4i[][]); c.CodeV4iArrayArray(ref v); return v; } },\r\n            { typeof(V4i[][][]), c => { var v = default(V4i[][][]); c.CodeV4iArrayArrayArray(ref v); return v; } },\r\n            { typeof(V4l[][]), c => { var v = default(V4l[][]); c.CodeV4lArrayArray(ref v); return v; } },\r\n            { typeof(V4l[][][]), c => { var v = default(V4l[][][]); c.CodeV4lArrayArrayArray(ref v); return v; } },\r\n            { typeof(V4f[][]), c => { var v = default(V4f[][]); c.CodeV4fArrayArray(ref v); return v; } },\r\n            { typeof(V4f[][][]), c => { var v = default(V4f[][][]); c.CodeV4fArrayArrayArray(ref v); return v; } },\r\n            { typeof(V4d[][]), c => { var v = default(V4d[][]); c.CodeV4dArrayArray(ref v); return v; } },\r\n            { typeof(V4d[][][]), c => { var v = default(V4d[][][]); c.CodeV4dArrayArrayArray(ref v); return v; } },\r\n            { typeof(M22i[][]), c => { var v = default(M22i[][]); c.CodeM22iArrayArray(ref v); return v; } },\r\n            { typeof(M22i[][][]), c => { var v = default(M22i[][][]); c.CodeM22iArrayArrayArray(ref v); return v; } },\r\n            { typeof(M22l[][]), c => { var v = default(M22l[][]); c.CodeM22lArrayArray(ref v); return v; } },\r\n            { typeof(M22l[][][]), c => { var v = default(M22l[][][]); c.CodeM22lArrayArrayArray(ref v); return v; } },\r\n            { typeof(M22f[][]), c => { var v = default(M22f[][]); c.CodeM22fArrayArray(ref v); return v; } },\r\n            { typeof(M22f[][][]), c => { var v = default(M22f[][][]); c.CodeM22fArrayArrayArray(ref v); return v; } },\r\n            { typeof(M22d[][]), c => { var v = default(M22d[][]); c.CodeM22dArrayArray(ref v); return v; } },\r\n            { typeof(M22d[][][]), c => { var v = default(M22d[][][]); c.CodeM22dArrayArrayArray(ref v); return v; } },\r\n            { typeof(M23i[][]), c => { var v = default(M23i[][]); c.CodeM23iArrayArray(ref v); return v; } },\r\n            { typeof(M23i[][][]), c => { var v = default(M23i[][][]); c.CodeM23iArrayArrayArray(ref v); return v; } },\r\n            { typeof(M23l[][]), c => { var v = default(M23l[][]); c.CodeM23lArrayArray(ref v); return v; } },\r\n            { typeof(M23l[][][]), c => { var v = default(M23l[][][]); c.CodeM23lArrayArrayArray(ref v); return v; } },\r\n            { typeof(M23f[][]), c => { var v = default(M23f[][]); c.CodeM23fArrayArray(ref v); return v; } },\r\n            { typeof(M23f[][][]), c => { var v = default(M23f[][][]); c.CodeM23fArrayArrayArray(ref v); return v; } },\r\n            { typeof(M23d[][]), c => { var v = default(M23d[][]); c.CodeM23dArrayArray(ref v); return v; } },\r\n            { typeof(M23d[][][]), c => { var v = default(M23d[][][]); c.CodeM23dArrayArrayArray(ref v); return v; } },\r\n            { typeof(M33i[][]), c => { var v = default(M33i[][]); c.CodeM33iArrayArray(ref v); return v; } },\r\n            { typeof(M33i[][][]), c => { var v = default(M33i[][][]); c.CodeM33iArrayArrayArray(ref v); return v; } },\r\n            { typeof(M33l[][]), c => { var v = default(M33l[][]); c.CodeM33lArrayArray(ref v); return v; } },\r\n            { typeof(M33l[][][]), c => { var v = default(M33l[][][]); c.CodeM33lArrayArrayArray(ref v); return v; } },\r\n            { typeof(M33f[][]), c => { var v = default(M33f[][]); c.CodeM33fArrayArray(ref v); return v; } },\r\n            { typeof(M33f[][][]), c => { var v = default(M33f[][][]); c.CodeM33fArrayArrayArray(ref v); return v; } },\r\n            { typeof(M33d[][]), c => { var v = default(M33d[][]); c.CodeM33dArrayArray(ref v); return v; } },\r\n            { typeof(M33d[][][]), c => { var v = default(M33d[][][]); c.CodeM33dArrayArrayArray(ref v); return v; } },\r\n            { typeof(M34i[][]), c => { var v = default(M34i[][]); c.CodeM34iArrayArray(ref v); return v; } },\r\n            { typeof(M34i[][][]), c => { var v = default(M34i[][][]); c.CodeM34iArrayArrayArray(ref v); return v; } },\r\n            { typeof(M34l[][]), c => { var v = default(M34l[][]); c.CodeM34lArrayArray(ref v); return v; } },\r\n            { typeof(M34l[][][]), c => { var v = default(M34l[][][]); c.CodeM34lArrayArrayArray(ref v); return v; } },\r\n            { typeof(M34f[][]), c => { var v = default(M34f[][]); c.CodeM34fArrayArray(ref v); return v; } },\r\n            { typeof(M34f[][][]), c => { var v = default(M34f[][][]); c.CodeM34fArrayArrayArray(ref v); return v; } },\r\n            { typeof(M34d[][]), c => { var v = default(M34d[][]); c.CodeM34dArrayArray(ref v); return v; } },\r\n            { typeof(M34d[][][]), c => { var v = default(M34d[][][]); c.CodeM34dArrayArrayArray(ref v); return v; } },\r\n            { typeof(M44i[][]), c => { var v = default(M44i[][]); c.CodeM44iArrayArray(ref v); return v; } },\r\n            { typeof(M44i[][][]), c => { var v = default(M44i[][][]); c.CodeM44iArrayArrayArray(ref v); return v; } },\r\n            { typeof(M44l[][]), c => { var v = default(M44l[][]); c.CodeM44lArrayArray(ref v); return v; } },\r\n            { typeof(M44l[][][]), c => { var v = default(M44l[][][]); c.CodeM44lArrayArrayArray(ref v); return v; } },\r\n            { typeof(M44f[][]), c => { var v = default(M44f[][]); c.CodeM44fArrayArray(ref v); return v; } },\r\n            { typeof(M44f[][][]), c => { var v = default(M44f[][][]); c.CodeM44fArrayArrayArray(ref v); return v; } },\r\n            { typeof(M44d[][]), c => { var v = default(M44d[][]); c.CodeM44dArrayArray(ref v); return v; } },\r\n            { typeof(M44d[][][]), c => { var v = default(M44d[][][]); c.CodeM44dArrayArrayArray(ref v); return v; } },\r\n            { typeof(C3b[][]), c => { var v = default(C3b[][]); c.CodeC3bArrayArray(ref v); return v; } },\r\n            { typeof(C3b[][][]), c => { var v = default(C3b[][][]); c.CodeC3bArrayArrayArray(ref v); return v; } },\r\n            { typeof(C3us[][]), c => { var v = default(C3us[][]); c.CodeC3usArrayArray(ref v); return v; } },\r\n            { typeof(C3us[][][]), c => { var v = default(C3us[][][]); c.CodeC3usArrayArrayArray(ref v); return v; } },\r\n            { typeof(C3ui[][]), c => { var v = default(C3ui[][]); c.CodeC3uiArrayArray(ref v); return v; } },\r\n            { typeof(C3ui[][][]), c => { var v = default(C3ui[][][]); c.CodeC3uiArrayArrayArray(ref v); return v; } },\r\n            { typeof(C3f[][]), c => { var v = default(C3f[][]); c.CodeC3fArrayArray(ref v); return v; } },\r\n            { typeof(C3f[][][]), c => { var v = default(C3f[][][]); c.CodeC3fArrayArrayArray(ref v); return v; } },\r\n            { typeof(C3d[][]), c => { var v = default(C3d[][]); c.CodeC3dArrayArray(ref v); return v; } },\r\n            { typeof(C3d[][][]), c => { var v = default(C3d[][][]); c.CodeC3dArrayArrayArray(ref v); return v; } },\r\n            { typeof(C4b[][]), c => { var v = default(C4b[][]); c.CodeC4bArrayArray(ref v); return v; } },\r\n            { typeof(C4b[][][]), c => { var v = default(C4b[][][]); c.CodeC4bArrayArrayArray(ref v); return v; } },\r\n            { typeof(C4us[][]), c => { var v = default(C4us[][]); c.CodeC4usArrayArray(ref v); return v; } },\r\n            { typeof(C4us[][][]), c => { var v = default(C4us[][][]); c.CodeC4usArrayArrayArray(ref v); return v; } },\r\n            { typeof(C4ui[][]), c => { var v = default(C4ui[][]); c.CodeC4uiArrayArray(ref v); return v; } },\r\n            { typeof(C4ui[][][]), c => { var v = default(C4ui[][][]); c.CodeC4uiArrayArrayArray(ref v); return v; } },\r\n            { typeof(C4f[][]), c => { var v = default(C4f[][]); c.CodeC4fArrayArray(ref v); return v; } },\r\n            { typeof(C4f[][][]), c => { var v = default(C4f[][][]); c.CodeC4fArrayArrayArray(ref v); return v; } },\r\n            { typeof(C4d[][]), c => { var v = default(C4d[][]); c.CodeC4dArrayArray(ref v); return v; } },\r\n            { typeof(C4d[][][]), c => { var v = default(C4d[][][]); c.CodeC4dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1b[][]), c => { var v = default(Range1b[][]); c.CodeRange1bArrayArray(ref v); return v; } },\r\n            { typeof(Range1b[][][]), c => { var v = default(Range1b[][][]); c.CodeRange1bArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1sb[][]), c => { var v = default(Range1sb[][]); c.CodeRange1sbArrayArray(ref v); return v; } },\r\n            { typeof(Range1sb[][][]), c => { var v = default(Range1sb[][][]); c.CodeRange1sbArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1s[][]), c => { var v = default(Range1s[][]); c.CodeRange1sArrayArray(ref v); return v; } },\r\n            { typeof(Range1s[][][]), c => { var v = default(Range1s[][][]); c.CodeRange1sArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1us[][]), c => { var v = default(Range1us[][]); c.CodeRange1usArrayArray(ref v); return v; } },\r\n            { typeof(Range1us[][][]), c => { var v = default(Range1us[][][]); c.CodeRange1usArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1i[][]), c => { var v = default(Range1i[][]); c.CodeRange1iArrayArray(ref v); return v; } },\r\n            { typeof(Range1i[][][]), c => { var v = default(Range1i[][][]); c.CodeRange1iArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1ui[][]), c => { var v = default(Range1ui[][]); c.CodeRange1uiArrayArray(ref v); return v; } },\r\n            { typeof(Range1ui[][][]), c => { var v = default(Range1ui[][][]); c.CodeRange1uiArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1l[][]), c => { var v = default(Range1l[][]); c.CodeRange1lArrayArray(ref v); return v; } },\r\n            { typeof(Range1l[][][]), c => { var v = default(Range1l[][][]); c.CodeRange1lArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1ul[][]), c => { var v = default(Range1ul[][]); c.CodeRange1ulArrayArray(ref v); return v; } },\r\n            { typeof(Range1ul[][][]), c => { var v = default(Range1ul[][][]); c.CodeRange1ulArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1f[][]), c => { var v = default(Range1f[][]); c.CodeRange1fArrayArray(ref v); return v; } },\r\n            { typeof(Range1f[][][]), c => { var v = default(Range1f[][][]); c.CodeRange1fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Range1d[][]), c => { var v = default(Range1d[][]); c.CodeRange1dArrayArray(ref v); return v; } },\r\n            { typeof(Range1d[][][]), c => { var v = default(Range1d[][][]); c.CodeRange1dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Box2i[][]), c => { var v = default(Box2i[][]); c.CodeBox2iArrayArray(ref v); return v; } },\r\n            { typeof(Box2i[][][]), c => { var v = default(Box2i[][][]); c.CodeBox2iArrayArrayArray(ref v); return v; } },\r\n            { typeof(Box2l[][]), c => { var v = default(Box2l[][]); c.CodeBox2lArrayArray(ref v); return v; } },\r\n            { typeof(Box2l[][][]), c => { var v = default(Box2l[][][]); c.CodeBox2lArrayArrayArray(ref v); return v; } },\r\n            { typeof(Box2f[][]), c => { var v = default(Box2f[][]); c.CodeBox2fArrayArray(ref v); return v; } },\r\n            { typeof(Box2f[][][]), c => { var v = default(Box2f[][][]); c.CodeBox2fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Box2d[][]), c => { var v = default(Box2d[][]); c.CodeBox2dArrayArray(ref v); return v; } },\r\n            { typeof(Box2d[][][]), c => { var v = default(Box2d[][][]); c.CodeBox2dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Box3i[][]), c => { var v = default(Box3i[][]); c.CodeBox3iArrayArray(ref v); return v; } },\r\n            { typeof(Box3i[][][]), c => { var v = default(Box3i[][][]); c.CodeBox3iArrayArrayArray(ref v); return v; } },\r\n            { typeof(Box3l[][]), c => { var v = default(Box3l[][]); c.CodeBox3lArrayArray(ref v); return v; } },\r\n            { typeof(Box3l[][][]), c => { var v = default(Box3l[][][]); c.CodeBox3lArrayArrayArray(ref v); return v; } },\r\n            { typeof(Box3f[][]), c => { var v = default(Box3f[][]); c.CodeBox3fArrayArray(ref v); return v; } },\r\n            { typeof(Box3f[][][]), c => { var v = default(Box3f[][][]); c.CodeBox3fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Box3d[][]), c => { var v = default(Box3d[][]); c.CodeBox3dArrayArray(ref v); return v; } },\r\n            { typeof(Box3d[][][]), c => { var v = default(Box3d[][][]); c.CodeBox3dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Euclidean3f[][]), c => { var v = default(Euclidean3f[][]); c.CodeEuclidean3fArrayArray(ref v); return v; } },\r\n            { typeof(Euclidean3f[][][]), c => { var v = default(Euclidean3f[][][]); c.CodeEuclidean3fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Euclidean3d[][]), c => { var v = default(Euclidean3d[][]); c.CodeEuclidean3dArrayArray(ref v); return v; } },\r\n            { typeof(Euclidean3d[][][]), c => { var v = default(Euclidean3d[][][]); c.CodeEuclidean3dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Rot2f[][]), c => { var v = default(Rot2f[][]); c.CodeRot2fArrayArray(ref v); return v; } },\r\n            { typeof(Rot2f[][][]), c => { var v = default(Rot2f[][][]); c.CodeRot2fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Rot2d[][]), c => { var v = default(Rot2d[][]); c.CodeRot2dArrayArray(ref v); return v; } },\r\n            { typeof(Rot2d[][][]), c => { var v = default(Rot2d[][][]); c.CodeRot2dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Rot3f[][]), c => { var v = default(Rot3f[][]); c.CodeRot3fArrayArray(ref v); return v; } },\r\n            { typeof(Rot3f[][][]), c => { var v = default(Rot3f[][][]); c.CodeRot3fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Rot3d[][]), c => { var v = default(Rot3d[][]); c.CodeRot3dArrayArray(ref v); return v; } },\r\n            { typeof(Rot3d[][][]), c => { var v = default(Rot3d[][][]); c.CodeRot3dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Scale3f[][]), c => { var v = default(Scale3f[][]); c.CodeScale3fArrayArray(ref v); return v; } },\r\n            { typeof(Scale3f[][][]), c => { var v = default(Scale3f[][][]); c.CodeScale3fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Scale3d[][]), c => { var v = default(Scale3d[][]); c.CodeScale3dArrayArray(ref v); return v; } },\r\n            { typeof(Scale3d[][][]), c => { var v = default(Scale3d[][][]); c.CodeScale3dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Shift3f[][]), c => { var v = default(Shift3f[][]); c.CodeShift3fArrayArray(ref v); return v; } },\r\n            { typeof(Shift3f[][][]), c => { var v = default(Shift3f[][][]); c.CodeShift3fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Shift3d[][]), c => { var v = default(Shift3d[][]); c.CodeShift3dArrayArray(ref v); return v; } },\r\n            { typeof(Shift3d[][][]), c => { var v = default(Shift3d[][][]); c.CodeShift3dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Trafo2f[][]), c => { var v = default(Trafo2f[][]); c.CodeTrafo2fArrayArray(ref v); return v; } },\r\n            { typeof(Trafo2f[][][]), c => { var v = default(Trafo2f[][][]); c.CodeTrafo2fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Trafo2d[][]), c => { var v = default(Trafo2d[][]); c.CodeTrafo2dArrayArray(ref v); return v; } },\r\n            { typeof(Trafo2d[][][]), c => { var v = default(Trafo2d[][][]); c.CodeTrafo2dArrayArrayArray(ref v); return v; } },\r\n            { typeof(Trafo3f[][]), c => { var v = default(Trafo3f[][]); c.CodeTrafo3fArrayArray(ref v); return v; } },\r\n            { typeof(Trafo3f[][][]), c => { var v = default(Trafo3f[][][]); c.CodeTrafo3fArrayArrayArray(ref v); return v; } },\r\n            { typeof(Trafo3d[][]), c => { var v = default(Trafo3d[][]); c.CodeTrafo3dArrayArray(ref v); return v; } },\r\n            { typeof(Trafo3d[][][]), c => { var v = default(Trafo3d[][][]); c.CodeTrafo3dArrayArrayArray(ref v); return v; } },\r\n\r\n            #endregion\r\n\r\n            #region Other Types\r\n\r\n            { typeof(IntSet), c => { var v = default(IntSet); c.CodeIntSet(ref v); return v; } },\r\n            { typeof(SymbolSet), c => { var v = default(SymbolSet); c.CodeSymbolSet(ref v); return v; } },\r\n\r\n            { typeof(HashSet<string>), c => { var v = default(HashSet<string>); c.CodeHashSet_of_T_(ref v); return v; } },\r\n\r\n            #endregion\r\n        };\r\n\r\n        public static partial class Default\r\n        {\r\n            /// <summary>\r\n            /// The default way of encoding various basic types.\r\n            /// </summary>\r\n            public static TypeInfo[] Basic = new[]\r\n            {\r\n                #region byte\r\n\r\n                new TypeInfo(\"byte\", typeof(byte), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(byte[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<byte>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<byte>\", \"Vector_of_\" + \"byte\", typeof(Vector<byte>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<byte>[]\", \"Array_of_Vector_of_\" + \"byte\", typeof(Vector<byte>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<byte>>\", \"List_of_Vector_of_\" + \"byte\", typeof(List<Vector<byte>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<byte>\", \"Matrix_of_\" + \"byte\", typeof(Matrix<byte>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<byte>[]\", \"Array_of_Matrix_of_\" + \"byte\", typeof(Matrix<byte>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<byte>>\", \"List_of_Matrix_of_\" + \"byte\", typeof(List<Matrix<byte>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<byte>\", \"Volume_of_\" + \"byte\", typeof(Volume<byte>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<byte>[]\", \"Array_of_Volume_of_\" + \"byte\", typeof(Volume<byte>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<byte>>\", \"List_of_Volume_of_\" + \"byte\", typeof(List<Volume<byte>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<byte>\", \"Tensor_of_\" + \"byte\", typeof(Tensor<byte>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<byte>[]\", \"Array_of_Tensor_of_\" + \"byte\", typeof(Tensor<byte>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<byte>>\", \"List_of_Tensor_of_\" + \"byte\", typeof(List<Tensor<byte>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region sbyte\r\n\r\n                new TypeInfo(\"sbyte\", typeof(sbyte), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(sbyte[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<sbyte>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<sbyte>\", \"Vector_of_\" + \"sbyte\", typeof(Vector<sbyte>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<sbyte>[]\", \"Array_of_Vector_of_\" + \"sbyte\", typeof(Vector<sbyte>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<sbyte>>\", \"List_of_Vector_of_\" + \"sbyte\", typeof(List<Vector<sbyte>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<sbyte>\", \"Matrix_of_\" + \"sbyte\", typeof(Matrix<sbyte>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<sbyte>[]\", \"Array_of_Matrix_of_\" + \"sbyte\", typeof(Matrix<sbyte>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<sbyte>>\", \"List_of_Matrix_of_\" + \"sbyte\", typeof(List<Matrix<sbyte>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<sbyte>\", \"Volume_of_\" + \"sbyte\", typeof(Volume<sbyte>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<sbyte>[]\", \"Array_of_Volume_of_\" + \"sbyte\", typeof(Volume<sbyte>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<sbyte>>\", \"List_of_Volume_of_\" + \"sbyte\", typeof(List<Volume<sbyte>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<sbyte>\", \"Tensor_of_\" + \"sbyte\", typeof(Tensor<sbyte>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<sbyte>[]\", \"Array_of_Tensor_of_\" + \"sbyte\", typeof(Tensor<sbyte>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<sbyte>>\", \"List_of_Tensor_of_\" + \"sbyte\", typeof(List<Tensor<sbyte>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region short\r\n\r\n                new TypeInfo(\"short\", typeof(short), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(short[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<short>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<short>\", \"Vector_of_\" + \"short\", typeof(Vector<short>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<short>[]\", \"Array_of_Vector_of_\" + \"short\", typeof(Vector<short>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<short>>\", \"List_of_Vector_of_\" + \"short\", typeof(List<Vector<short>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<short>\", \"Matrix_of_\" + \"short\", typeof(Matrix<short>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<short>[]\", \"Array_of_Matrix_of_\" + \"short\", typeof(Matrix<short>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<short>>\", \"List_of_Matrix_of_\" + \"short\", typeof(List<Matrix<short>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<short>\", \"Volume_of_\" + \"short\", typeof(Volume<short>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<short>[]\", \"Array_of_Volume_of_\" + \"short\", typeof(Volume<short>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<short>>\", \"List_of_Volume_of_\" + \"short\", typeof(List<Volume<short>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<short>\", \"Tensor_of_\" + \"short\", typeof(Tensor<short>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<short>[]\", \"Array_of_Tensor_of_\" + \"short\", typeof(Tensor<short>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<short>>\", \"List_of_Tensor_of_\" + \"short\", typeof(List<Tensor<short>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region ushort\r\n\r\n                new TypeInfo(\"ushort\", typeof(ushort), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(ushort[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<ushort>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<ushort>\", \"Vector_of_\" + \"ushort\", typeof(Vector<ushort>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<ushort>[]\", \"Array_of_Vector_of_\" + \"ushort\", typeof(Vector<ushort>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<ushort>>\", \"List_of_Vector_of_\" + \"ushort\", typeof(List<Vector<ushort>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<ushort>\", \"Matrix_of_\" + \"ushort\", typeof(Matrix<ushort>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<ushort>[]\", \"Array_of_Matrix_of_\" + \"ushort\", typeof(Matrix<ushort>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<ushort>>\", \"List_of_Matrix_of_\" + \"ushort\", typeof(List<Matrix<ushort>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<ushort>\", \"Volume_of_\" + \"ushort\", typeof(Volume<ushort>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<ushort>[]\", \"Array_of_Volume_of_\" + \"ushort\", typeof(Volume<ushort>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<ushort>>\", \"List_of_Volume_of_\" + \"ushort\", typeof(List<Volume<ushort>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<ushort>\", \"Tensor_of_\" + \"ushort\", typeof(Tensor<ushort>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<ushort>[]\", \"Array_of_Tensor_of_\" + \"ushort\", typeof(Tensor<ushort>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<ushort>>\", \"List_of_Tensor_of_\" + \"ushort\", typeof(List<Tensor<ushort>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region int\r\n\r\n                new TypeInfo(\"int\", typeof(int), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(int[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<int>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<int>\", \"Vector_of_\" + \"int\", typeof(Vector<int>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<int>[]\", \"Array_of_Vector_of_\" + \"int\", typeof(Vector<int>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<int>>\", \"List_of_Vector_of_\" + \"int\", typeof(List<Vector<int>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<int>\", \"Matrix_of_\" + \"int\", typeof(Matrix<int>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<int>[]\", \"Array_of_Matrix_of_\" + \"int\", typeof(Matrix<int>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<int>>\", \"List_of_Matrix_of_\" + \"int\", typeof(List<Matrix<int>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<int>\", \"Volume_of_\" + \"int\", typeof(Volume<int>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<int>[]\", \"Array_of_Volume_of_\" + \"int\", typeof(Volume<int>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<int>>\", \"List_of_Volume_of_\" + \"int\", typeof(List<Volume<int>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<int>\", \"Tensor_of_\" + \"int\", typeof(Tensor<int>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<int>[]\", \"Array_of_Tensor_of_\" + \"int\", typeof(Tensor<int>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<int>>\", \"List_of_Tensor_of_\" + \"int\", typeof(List<Tensor<int>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region uint\r\n\r\n                new TypeInfo(\"uint\", typeof(uint), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(uint[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<uint>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<uint>\", \"Vector_of_\" + \"uint\", typeof(Vector<uint>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<uint>[]\", \"Array_of_Vector_of_\" + \"uint\", typeof(Vector<uint>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<uint>>\", \"List_of_Vector_of_\" + \"uint\", typeof(List<Vector<uint>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<uint>\", \"Matrix_of_\" + \"uint\", typeof(Matrix<uint>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<uint>[]\", \"Array_of_Matrix_of_\" + \"uint\", typeof(Matrix<uint>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<uint>>\", \"List_of_Matrix_of_\" + \"uint\", typeof(List<Matrix<uint>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<uint>\", \"Volume_of_\" + \"uint\", typeof(Volume<uint>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<uint>[]\", \"Array_of_Volume_of_\" + \"uint\", typeof(Volume<uint>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<uint>>\", \"List_of_Volume_of_\" + \"uint\", typeof(List<Volume<uint>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<uint>\", \"Tensor_of_\" + \"uint\", typeof(Tensor<uint>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<uint>[]\", \"Array_of_Tensor_of_\" + \"uint\", typeof(Tensor<uint>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<uint>>\", \"List_of_Tensor_of_\" + \"uint\", typeof(List<Tensor<uint>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region long\r\n\r\n                new TypeInfo(\"long\", typeof(long), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(long[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<long>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<long>\", \"Vector_of_\" + \"long\", typeof(Vector<long>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<long>[]\", \"Array_of_Vector_of_\" + \"long\", typeof(Vector<long>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<long>>\", \"List_of_Vector_of_\" + \"long\", typeof(List<Vector<long>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<long>\", \"Matrix_of_\" + \"long\", typeof(Matrix<long>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<long>[]\", \"Array_of_Matrix_of_\" + \"long\", typeof(Matrix<long>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<long>>\", \"List_of_Matrix_of_\" + \"long\", typeof(List<Matrix<long>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<long>\", \"Volume_of_\" + \"long\", typeof(Volume<long>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<long>[]\", \"Array_of_Volume_of_\" + \"long\", typeof(Volume<long>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<long>>\", \"List_of_Volume_of_\" + \"long\", typeof(List<Volume<long>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<long>\", \"Tensor_of_\" + \"long\", typeof(Tensor<long>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<long>[]\", \"Array_of_Tensor_of_\" + \"long\", typeof(Tensor<long>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<long>>\", \"List_of_Tensor_of_\" + \"long\", typeof(List<Tensor<long>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region ulong\r\n\r\n                new TypeInfo(\"ulong\", typeof(ulong), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(ulong[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<ulong>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<ulong>\", \"Vector_of_\" + \"ulong\", typeof(Vector<ulong>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<ulong>[]\", \"Array_of_Vector_of_\" + \"ulong\", typeof(Vector<ulong>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<ulong>>\", \"List_of_Vector_of_\" + \"ulong\", typeof(List<Vector<ulong>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<ulong>\", \"Matrix_of_\" + \"ulong\", typeof(Matrix<ulong>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<ulong>[]\", \"Array_of_Matrix_of_\" + \"ulong\", typeof(Matrix<ulong>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<ulong>>\", \"List_of_Matrix_of_\" + \"ulong\", typeof(List<Matrix<ulong>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<ulong>\", \"Volume_of_\" + \"ulong\", typeof(Volume<ulong>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<ulong>[]\", \"Array_of_Volume_of_\" + \"ulong\", typeof(Volume<ulong>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<ulong>>\", \"List_of_Volume_of_\" + \"ulong\", typeof(List<Volume<ulong>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<ulong>\", \"Tensor_of_\" + \"ulong\", typeof(Tensor<ulong>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<ulong>[]\", \"Array_of_Tensor_of_\" + \"ulong\", typeof(Tensor<ulong>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<ulong>>\", \"List_of_Tensor_of_\" + \"ulong\", typeof(List<Tensor<ulong>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region float\r\n\r\n                new TypeInfo(\"float\", typeof(float), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(float[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<float>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<float>\", \"Vector_of_\" + \"float\", typeof(Vector<float>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<float>[]\", \"Array_of_Vector_of_\" + \"float\", typeof(Vector<float>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<float>>\", \"List_of_Vector_of_\" + \"float\", typeof(List<Vector<float>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<float>\", \"Matrix_of_\" + \"float\", typeof(Matrix<float>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<float>[]\", \"Array_of_Matrix_of_\" + \"float\", typeof(Matrix<float>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<float>>\", \"List_of_Matrix_of_\" + \"float\", typeof(List<Matrix<float>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<float>\", \"Volume_of_\" + \"float\", typeof(Volume<float>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<float>[]\", \"Array_of_Volume_of_\" + \"float\", typeof(Volume<float>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<float>>\", \"List_of_Volume_of_\" + \"float\", typeof(List<Volume<float>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<float>\", \"Tensor_of_\" + \"float\", typeof(Tensor<float>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<float>[]\", \"Array_of_Tensor_of_\" + \"float\", typeof(Tensor<float>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<float>>\", \"List_of_Tensor_of_\" + \"float\", typeof(List<Tensor<float>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region double\r\n\r\n                new TypeInfo(\"double\", typeof(double), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(double[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<double>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<double>\", \"Vector_of_\" + \"double\", typeof(Vector<double>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<double>[]\", \"Array_of_Vector_of_\" + \"double\", typeof(Vector<double>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<double>>\", \"List_of_Vector_of_\" + \"double\", typeof(List<Vector<double>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<double>\", \"Matrix_of_\" + \"double\", typeof(Matrix<double>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<double>[]\", \"Array_of_Matrix_of_\" + \"double\", typeof(Matrix<double>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<double>>\", \"List_of_Matrix_of_\" + \"double\", typeof(List<Matrix<double>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<double>\", \"Volume_of_\" + \"double\", typeof(Volume<double>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<double>[]\", \"Array_of_Volume_of_\" + \"double\", typeof(Volume<double>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<double>>\", \"List_of_Volume_of_\" + \"double\", typeof(List<Volume<double>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<double>\", \"Tensor_of_\" + \"double\", typeof(Tensor<double>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<double>[]\", \"Array_of_Tensor_of_\" + \"double\", typeof(Tensor<double>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<double>>\", \"List_of_Tensor_of_\" + \"double\", typeof(List<Tensor<double>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Fraction\r\n\r\n                new TypeInfo(\"Fraction\", typeof(Fraction), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Fraction[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Fraction>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Fraction>\", \"Vector_of_\" + \"Fraction\", typeof(Vector<Fraction>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Fraction>[]\", \"Array_of_Vector_of_\" + \"Fraction\", typeof(Vector<Fraction>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Fraction>>\", \"List_of_Vector_of_\" + \"Fraction\", typeof(List<Vector<Fraction>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Fraction>\", \"Matrix_of_\" + \"Fraction\", typeof(Matrix<Fraction>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Fraction>[]\", \"Array_of_Matrix_of_\" + \"Fraction\", typeof(Matrix<Fraction>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Fraction>>\", \"List_of_Matrix_of_\" + \"Fraction\", typeof(List<Matrix<Fraction>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Fraction>\", \"Volume_of_\" + \"Fraction\", typeof(Volume<Fraction>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Fraction>[]\", \"Array_of_Volume_of_\" + \"Fraction\", typeof(Volume<Fraction>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Fraction>>\", \"List_of_Volume_of_\" + \"Fraction\", typeof(List<Volume<Fraction>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Fraction>\", \"Tensor_of_\" + \"Fraction\", typeof(Tensor<Fraction>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Fraction>[]\", \"Array_of_Tensor_of_\" + \"Fraction\", typeof(Tensor<Fraction>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Fraction>>\", \"List_of_Tensor_of_\" + \"Fraction\", typeof(List<Tensor<Fraction>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V2i\r\n\r\n                new TypeInfo(\"V2i\", typeof(V2i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V2i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V2i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V2i>\", \"Vector_of_\" + \"V2i\", typeof(Vector<V2i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V2i>[]\", \"Array_of_Vector_of_\" + \"V2i\", typeof(Vector<V2i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V2i>>\", \"List_of_Vector_of_\" + \"V2i\", typeof(List<Vector<V2i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V2i>\", \"Matrix_of_\" + \"V2i\", typeof(Matrix<V2i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V2i>[]\", \"Array_of_Matrix_of_\" + \"V2i\", typeof(Matrix<V2i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V2i>>\", \"List_of_Matrix_of_\" + \"V2i\", typeof(List<Matrix<V2i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V2i>\", \"Volume_of_\" + \"V2i\", typeof(Volume<V2i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V2i>[]\", \"Array_of_Volume_of_\" + \"V2i\", typeof(Volume<V2i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V2i>>\", \"List_of_Volume_of_\" + \"V2i\", typeof(List<Volume<V2i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V2i>\", \"Tensor_of_\" + \"V2i\", typeof(Tensor<V2i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V2i>[]\", \"Array_of_Tensor_of_\" + \"V2i\", typeof(Tensor<V2i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V2i>>\", \"List_of_Tensor_of_\" + \"V2i\", typeof(List<Tensor<V2i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V2l\r\n\r\n                new TypeInfo(\"V2l\", typeof(V2l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V2l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V2l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V2l>\", \"Vector_of_\" + \"V2l\", typeof(Vector<V2l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V2l>[]\", \"Array_of_Vector_of_\" + \"V2l\", typeof(Vector<V2l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V2l>>\", \"List_of_Vector_of_\" + \"V2l\", typeof(List<Vector<V2l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V2l>\", \"Matrix_of_\" + \"V2l\", typeof(Matrix<V2l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V2l>[]\", \"Array_of_Matrix_of_\" + \"V2l\", typeof(Matrix<V2l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V2l>>\", \"List_of_Matrix_of_\" + \"V2l\", typeof(List<Matrix<V2l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V2l>\", \"Volume_of_\" + \"V2l\", typeof(Volume<V2l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V2l>[]\", \"Array_of_Volume_of_\" + \"V2l\", typeof(Volume<V2l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V2l>>\", \"List_of_Volume_of_\" + \"V2l\", typeof(List<Volume<V2l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V2l>\", \"Tensor_of_\" + \"V2l\", typeof(Tensor<V2l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V2l>[]\", \"Array_of_Tensor_of_\" + \"V2l\", typeof(Tensor<V2l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V2l>>\", \"List_of_Tensor_of_\" + \"V2l\", typeof(List<Tensor<V2l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V2f\r\n\r\n                new TypeInfo(\"V2f\", typeof(V2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V2f>\", \"Vector_of_\" + \"V2f\", typeof(Vector<V2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V2f>[]\", \"Array_of_Vector_of_\" + \"V2f\", typeof(Vector<V2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V2f>>\", \"List_of_Vector_of_\" + \"V2f\", typeof(List<Vector<V2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V2f>\", \"Matrix_of_\" + \"V2f\", typeof(Matrix<V2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V2f>[]\", \"Array_of_Matrix_of_\" + \"V2f\", typeof(Matrix<V2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V2f>>\", \"List_of_Matrix_of_\" + \"V2f\", typeof(List<Matrix<V2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V2f>\", \"Volume_of_\" + \"V2f\", typeof(Volume<V2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V2f>[]\", \"Array_of_Volume_of_\" + \"V2f\", typeof(Volume<V2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V2f>>\", \"List_of_Volume_of_\" + \"V2f\", typeof(List<Volume<V2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V2f>\", \"Tensor_of_\" + \"V2f\", typeof(Tensor<V2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V2f>[]\", \"Array_of_Tensor_of_\" + \"V2f\", typeof(Tensor<V2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V2f>>\", \"List_of_Tensor_of_\" + \"V2f\", typeof(List<Tensor<V2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V2d\r\n\r\n                new TypeInfo(\"V2d\", typeof(V2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V2d>\", \"Vector_of_\" + \"V2d\", typeof(Vector<V2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V2d>[]\", \"Array_of_Vector_of_\" + \"V2d\", typeof(Vector<V2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V2d>>\", \"List_of_Vector_of_\" + \"V2d\", typeof(List<Vector<V2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V2d>\", \"Matrix_of_\" + \"V2d\", typeof(Matrix<V2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V2d>[]\", \"Array_of_Matrix_of_\" + \"V2d\", typeof(Matrix<V2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V2d>>\", \"List_of_Matrix_of_\" + \"V2d\", typeof(List<Matrix<V2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V2d>\", \"Volume_of_\" + \"V2d\", typeof(Volume<V2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V2d>[]\", \"Array_of_Volume_of_\" + \"V2d\", typeof(Volume<V2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V2d>>\", \"List_of_Volume_of_\" + \"V2d\", typeof(List<Volume<V2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V2d>\", \"Tensor_of_\" + \"V2d\", typeof(Tensor<V2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V2d>[]\", \"Array_of_Tensor_of_\" + \"V2d\", typeof(Tensor<V2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V2d>>\", \"List_of_Tensor_of_\" + \"V2d\", typeof(List<Tensor<V2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V3i\r\n\r\n                new TypeInfo(\"V3i\", typeof(V3i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V3i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V3i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V3i>\", \"Vector_of_\" + \"V3i\", typeof(Vector<V3i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V3i>[]\", \"Array_of_Vector_of_\" + \"V3i\", typeof(Vector<V3i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V3i>>\", \"List_of_Vector_of_\" + \"V3i\", typeof(List<Vector<V3i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V3i>\", \"Matrix_of_\" + \"V3i\", typeof(Matrix<V3i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V3i>[]\", \"Array_of_Matrix_of_\" + \"V3i\", typeof(Matrix<V3i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V3i>>\", \"List_of_Matrix_of_\" + \"V3i\", typeof(List<Matrix<V3i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V3i>\", \"Volume_of_\" + \"V3i\", typeof(Volume<V3i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V3i>[]\", \"Array_of_Volume_of_\" + \"V3i\", typeof(Volume<V3i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V3i>>\", \"List_of_Volume_of_\" + \"V3i\", typeof(List<Volume<V3i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V3i>\", \"Tensor_of_\" + \"V3i\", typeof(Tensor<V3i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V3i>[]\", \"Array_of_Tensor_of_\" + \"V3i\", typeof(Tensor<V3i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V3i>>\", \"List_of_Tensor_of_\" + \"V3i\", typeof(List<Tensor<V3i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V3l\r\n\r\n                new TypeInfo(\"V3l\", typeof(V3l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V3l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V3l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V3l>\", \"Vector_of_\" + \"V3l\", typeof(Vector<V3l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V3l>[]\", \"Array_of_Vector_of_\" + \"V3l\", typeof(Vector<V3l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V3l>>\", \"List_of_Vector_of_\" + \"V3l\", typeof(List<Vector<V3l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V3l>\", \"Matrix_of_\" + \"V3l\", typeof(Matrix<V3l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V3l>[]\", \"Array_of_Matrix_of_\" + \"V3l\", typeof(Matrix<V3l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V3l>>\", \"List_of_Matrix_of_\" + \"V3l\", typeof(List<Matrix<V3l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V3l>\", \"Volume_of_\" + \"V3l\", typeof(Volume<V3l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V3l>[]\", \"Array_of_Volume_of_\" + \"V3l\", typeof(Volume<V3l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V3l>>\", \"List_of_Volume_of_\" + \"V3l\", typeof(List<Volume<V3l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V3l>\", \"Tensor_of_\" + \"V3l\", typeof(Tensor<V3l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V3l>[]\", \"Array_of_Tensor_of_\" + \"V3l\", typeof(Tensor<V3l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V3l>>\", \"List_of_Tensor_of_\" + \"V3l\", typeof(List<Tensor<V3l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V3f\r\n\r\n                new TypeInfo(\"V3f\", typeof(V3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V3f>\", \"Vector_of_\" + \"V3f\", typeof(Vector<V3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V3f>[]\", \"Array_of_Vector_of_\" + \"V3f\", typeof(Vector<V3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V3f>>\", \"List_of_Vector_of_\" + \"V3f\", typeof(List<Vector<V3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V3f>\", \"Matrix_of_\" + \"V3f\", typeof(Matrix<V3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V3f>[]\", \"Array_of_Matrix_of_\" + \"V3f\", typeof(Matrix<V3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V3f>>\", \"List_of_Matrix_of_\" + \"V3f\", typeof(List<Matrix<V3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V3f>\", \"Volume_of_\" + \"V3f\", typeof(Volume<V3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V3f>[]\", \"Array_of_Volume_of_\" + \"V3f\", typeof(Volume<V3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V3f>>\", \"List_of_Volume_of_\" + \"V3f\", typeof(List<Volume<V3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V3f>\", \"Tensor_of_\" + \"V3f\", typeof(Tensor<V3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V3f>[]\", \"Array_of_Tensor_of_\" + \"V3f\", typeof(Tensor<V3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V3f>>\", \"List_of_Tensor_of_\" + \"V3f\", typeof(List<Tensor<V3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V3d\r\n\r\n                new TypeInfo(\"V3d\", typeof(V3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V3d>\", \"Vector_of_\" + \"V3d\", typeof(Vector<V3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V3d>[]\", \"Array_of_Vector_of_\" + \"V3d\", typeof(Vector<V3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V3d>>\", \"List_of_Vector_of_\" + \"V3d\", typeof(List<Vector<V3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V3d>\", \"Matrix_of_\" + \"V3d\", typeof(Matrix<V3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V3d>[]\", \"Array_of_Matrix_of_\" + \"V3d\", typeof(Matrix<V3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V3d>>\", \"List_of_Matrix_of_\" + \"V3d\", typeof(List<Matrix<V3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V3d>\", \"Volume_of_\" + \"V3d\", typeof(Volume<V3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V3d>[]\", \"Array_of_Volume_of_\" + \"V3d\", typeof(Volume<V3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V3d>>\", \"List_of_Volume_of_\" + \"V3d\", typeof(List<Volume<V3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V3d>\", \"Tensor_of_\" + \"V3d\", typeof(Tensor<V3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V3d>[]\", \"Array_of_Tensor_of_\" + \"V3d\", typeof(Tensor<V3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V3d>>\", \"List_of_Tensor_of_\" + \"V3d\", typeof(List<Tensor<V3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V4i\r\n\r\n                new TypeInfo(\"V4i\", typeof(V4i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V4i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V4i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V4i>\", \"Vector_of_\" + \"V4i\", typeof(Vector<V4i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V4i>[]\", \"Array_of_Vector_of_\" + \"V4i\", typeof(Vector<V4i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V4i>>\", \"List_of_Vector_of_\" + \"V4i\", typeof(List<Vector<V4i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V4i>\", \"Matrix_of_\" + \"V4i\", typeof(Matrix<V4i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V4i>[]\", \"Array_of_Matrix_of_\" + \"V4i\", typeof(Matrix<V4i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V4i>>\", \"List_of_Matrix_of_\" + \"V4i\", typeof(List<Matrix<V4i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V4i>\", \"Volume_of_\" + \"V4i\", typeof(Volume<V4i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V4i>[]\", \"Array_of_Volume_of_\" + \"V4i\", typeof(Volume<V4i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V4i>>\", \"List_of_Volume_of_\" + \"V4i\", typeof(List<Volume<V4i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V4i>\", \"Tensor_of_\" + \"V4i\", typeof(Tensor<V4i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V4i>[]\", \"Array_of_Tensor_of_\" + \"V4i\", typeof(Tensor<V4i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V4i>>\", \"List_of_Tensor_of_\" + \"V4i\", typeof(List<Tensor<V4i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V4l\r\n\r\n                new TypeInfo(\"V4l\", typeof(V4l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V4l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V4l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V4l>\", \"Vector_of_\" + \"V4l\", typeof(Vector<V4l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V4l>[]\", \"Array_of_Vector_of_\" + \"V4l\", typeof(Vector<V4l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V4l>>\", \"List_of_Vector_of_\" + \"V4l\", typeof(List<Vector<V4l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V4l>\", \"Matrix_of_\" + \"V4l\", typeof(Matrix<V4l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V4l>[]\", \"Array_of_Matrix_of_\" + \"V4l\", typeof(Matrix<V4l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V4l>>\", \"List_of_Matrix_of_\" + \"V4l\", typeof(List<Matrix<V4l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V4l>\", \"Volume_of_\" + \"V4l\", typeof(Volume<V4l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V4l>[]\", \"Array_of_Volume_of_\" + \"V4l\", typeof(Volume<V4l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V4l>>\", \"List_of_Volume_of_\" + \"V4l\", typeof(List<Volume<V4l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V4l>\", \"Tensor_of_\" + \"V4l\", typeof(Tensor<V4l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V4l>[]\", \"Array_of_Tensor_of_\" + \"V4l\", typeof(Tensor<V4l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V4l>>\", \"List_of_Tensor_of_\" + \"V4l\", typeof(List<Tensor<V4l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V4f\r\n\r\n                new TypeInfo(\"V4f\", typeof(V4f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V4f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V4f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V4f>\", \"Vector_of_\" + \"V4f\", typeof(Vector<V4f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V4f>[]\", \"Array_of_Vector_of_\" + \"V4f\", typeof(Vector<V4f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V4f>>\", \"List_of_Vector_of_\" + \"V4f\", typeof(List<Vector<V4f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V4f>\", \"Matrix_of_\" + \"V4f\", typeof(Matrix<V4f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V4f>[]\", \"Array_of_Matrix_of_\" + \"V4f\", typeof(Matrix<V4f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V4f>>\", \"List_of_Matrix_of_\" + \"V4f\", typeof(List<Matrix<V4f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V4f>\", \"Volume_of_\" + \"V4f\", typeof(Volume<V4f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V4f>[]\", \"Array_of_Volume_of_\" + \"V4f\", typeof(Volume<V4f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V4f>>\", \"List_of_Volume_of_\" + \"V4f\", typeof(List<Volume<V4f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V4f>\", \"Tensor_of_\" + \"V4f\", typeof(Tensor<V4f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V4f>[]\", \"Array_of_Tensor_of_\" + \"V4f\", typeof(Tensor<V4f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V4f>>\", \"List_of_Tensor_of_\" + \"V4f\", typeof(List<Tensor<V4f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region V4d\r\n\r\n                new TypeInfo(\"V4d\", typeof(V4d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(V4d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<V4d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<V4d>\", \"Vector_of_\" + \"V4d\", typeof(Vector<V4d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<V4d>[]\", \"Array_of_Vector_of_\" + \"V4d\", typeof(Vector<V4d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<V4d>>\", \"List_of_Vector_of_\" + \"V4d\", typeof(List<Vector<V4d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<V4d>\", \"Matrix_of_\" + \"V4d\", typeof(Matrix<V4d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<V4d>[]\", \"Array_of_Matrix_of_\" + \"V4d\", typeof(Matrix<V4d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<V4d>>\", \"List_of_Matrix_of_\" + \"V4d\", typeof(List<Matrix<V4d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<V4d>\", \"Volume_of_\" + \"V4d\", typeof(Volume<V4d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<V4d>[]\", \"Array_of_Volume_of_\" + \"V4d\", typeof(Volume<V4d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<V4d>>\", \"List_of_Volume_of_\" + \"V4d\", typeof(List<Volume<V4d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<V4d>\", \"Tensor_of_\" + \"V4d\", typeof(Tensor<V4d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<V4d>[]\", \"Array_of_Tensor_of_\" + \"V4d\", typeof(Tensor<V4d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<V4d>>\", \"List_of_Tensor_of_\" + \"V4d\", typeof(List<Tensor<V4d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M22i\r\n\r\n                new TypeInfo(\"M22i\", typeof(M22i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M22i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M22i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M22i>\", \"Vector_of_\" + \"M22i\", typeof(Vector<M22i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M22i>[]\", \"Array_of_Vector_of_\" + \"M22i\", typeof(Vector<M22i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M22i>>\", \"List_of_Vector_of_\" + \"M22i\", typeof(List<Vector<M22i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M22i>\", \"Matrix_of_\" + \"M22i\", typeof(Matrix<M22i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M22i>[]\", \"Array_of_Matrix_of_\" + \"M22i\", typeof(Matrix<M22i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M22i>>\", \"List_of_Matrix_of_\" + \"M22i\", typeof(List<Matrix<M22i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M22i>\", \"Volume_of_\" + \"M22i\", typeof(Volume<M22i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M22i>[]\", \"Array_of_Volume_of_\" + \"M22i\", typeof(Volume<M22i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M22i>>\", \"List_of_Volume_of_\" + \"M22i\", typeof(List<Volume<M22i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M22i>\", \"Tensor_of_\" + \"M22i\", typeof(Tensor<M22i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M22i>[]\", \"Array_of_Tensor_of_\" + \"M22i\", typeof(Tensor<M22i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M22i>>\", \"List_of_Tensor_of_\" + \"M22i\", typeof(List<Tensor<M22i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M22l\r\n\r\n                new TypeInfo(\"M22l\", typeof(M22l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M22l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M22l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M22l>\", \"Vector_of_\" + \"M22l\", typeof(Vector<M22l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M22l>[]\", \"Array_of_Vector_of_\" + \"M22l\", typeof(Vector<M22l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M22l>>\", \"List_of_Vector_of_\" + \"M22l\", typeof(List<Vector<M22l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M22l>\", \"Matrix_of_\" + \"M22l\", typeof(Matrix<M22l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M22l>[]\", \"Array_of_Matrix_of_\" + \"M22l\", typeof(Matrix<M22l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M22l>>\", \"List_of_Matrix_of_\" + \"M22l\", typeof(List<Matrix<M22l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M22l>\", \"Volume_of_\" + \"M22l\", typeof(Volume<M22l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M22l>[]\", \"Array_of_Volume_of_\" + \"M22l\", typeof(Volume<M22l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M22l>>\", \"List_of_Volume_of_\" + \"M22l\", typeof(List<Volume<M22l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M22l>\", \"Tensor_of_\" + \"M22l\", typeof(Tensor<M22l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M22l>[]\", \"Array_of_Tensor_of_\" + \"M22l\", typeof(Tensor<M22l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M22l>>\", \"List_of_Tensor_of_\" + \"M22l\", typeof(List<Tensor<M22l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M22f\r\n\r\n                new TypeInfo(\"M22f\", typeof(M22f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M22f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M22f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M22f>\", \"Vector_of_\" + \"M22f\", typeof(Vector<M22f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M22f>[]\", \"Array_of_Vector_of_\" + \"M22f\", typeof(Vector<M22f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M22f>>\", \"List_of_Vector_of_\" + \"M22f\", typeof(List<Vector<M22f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M22f>\", \"Matrix_of_\" + \"M22f\", typeof(Matrix<M22f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M22f>[]\", \"Array_of_Matrix_of_\" + \"M22f\", typeof(Matrix<M22f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M22f>>\", \"List_of_Matrix_of_\" + \"M22f\", typeof(List<Matrix<M22f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M22f>\", \"Volume_of_\" + \"M22f\", typeof(Volume<M22f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M22f>[]\", \"Array_of_Volume_of_\" + \"M22f\", typeof(Volume<M22f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M22f>>\", \"List_of_Volume_of_\" + \"M22f\", typeof(List<Volume<M22f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M22f>\", \"Tensor_of_\" + \"M22f\", typeof(Tensor<M22f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M22f>[]\", \"Array_of_Tensor_of_\" + \"M22f\", typeof(Tensor<M22f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M22f>>\", \"List_of_Tensor_of_\" + \"M22f\", typeof(List<Tensor<M22f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M22d\r\n\r\n                new TypeInfo(\"M22d\", typeof(M22d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M22d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M22d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M22d>\", \"Vector_of_\" + \"M22d\", typeof(Vector<M22d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M22d>[]\", \"Array_of_Vector_of_\" + \"M22d\", typeof(Vector<M22d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M22d>>\", \"List_of_Vector_of_\" + \"M22d\", typeof(List<Vector<M22d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M22d>\", \"Matrix_of_\" + \"M22d\", typeof(Matrix<M22d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M22d>[]\", \"Array_of_Matrix_of_\" + \"M22d\", typeof(Matrix<M22d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M22d>>\", \"List_of_Matrix_of_\" + \"M22d\", typeof(List<Matrix<M22d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M22d>\", \"Volume_of_\" + \"M22d\", typeof(Volume<M22d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M22d>[]\", \"Array_of_Volume_of_\" + \"M22d\", typeof(Volume<M22d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M22d>>\", \"List_of_Volume_of_\" + \"M22d\", typeof(List<Volume<M22d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M22d>\", \"Tensor_of_\" + \"M22d\", typeof(Tensor<M22d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M22d>[]\", \"Array_of_Tensor_of_\" + \"M22d\", typeof(Tensor<M22d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M22d>>\", \"List_of_Tensor_of_\" + \"M22d\", typeof(List<Tensor<M22d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M23i\r\n\r\n                new TypeInfo(\"M23i\", typeof(M23i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M23i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M23i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M23i>\", \"Vector_of_\" + \"M23i\", typeof(Vector<M23i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M23i>[]\", \"Array_of_Vector_of_\" + \"M23i\", typeof(Vector<M23i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M23i>>\", \"List_of_Vector_of_\" + \"M23i\", typeof(List<Vector<M23i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M23i>\", \"Matrix_of_\" + \"M23i\", typeof(Matrix<M23i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M23i>[]\", \"Array_of_Matrix_of_\" + \"M23i\", typeof(Matrix<M23i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M23i>>\", \"List_of_Matrix_of_\" + \"M23i\", typeof(List<Matrix<M23i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M23i>\", \"Volume_of_\" + \"M23i\", typeof(Volume<M23i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M23i>[]\", \"Array_of_Volume_of_\" + \"M23i\", typeof(Volume<M23i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M23i>>\", \"List_of_Volume_of_\" + \"M23i\", typeof(List<Volume<M23i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M23i>\", \"Tensor_of_\" + \"M23i\", typeof(Tensor<M23i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M23i>[]\", \"Array_of_Tensor_of_\" + \"M23i\", typeof(Tensor<M23i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M23i>>\", \"List_of_Tensor_of_\" + \"M23i\", typeof(List<Tensor<M23i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M23l\r\n\r\n                new TypeInfo(\"M23l\", typeof(M23l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M23l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M23l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M23l>\", \"Vector_of_\" + \"M23l\", typeof(Vector<M23l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M23l>[]\", \"Array_of_Vector_of_\" + \"M23l\", typeof(Vector<M23l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M23l>>\", \"List_of_Vector_of_\" + \"M23l\", typeof(List<Vector<M23l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M23l>\", \"Matrix_of_\" + \"M23l\", typeof(Matrix<M23l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M23l>[]\", \"Array_of_Matrix_of_\" + \"M23l\", typeof(Matrix<M23l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M23l>>\", \"List_of_Matrix_of_\" + \"M23l\", typeof(List<Matrix<M23l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M23l>\", \"Volume_of_\" + \"M23l\", typeof(Volume<M23l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M23l>[]\", \"Array_of_Volume_of_\" + \"M23l\", typeof(Volume<M23l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M23l>>\", \"List_of_Volume_of_\" + \"M23l\", typeof(List<Volume<M23l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M23l>\", \"Tensor_of_\" + \"M23l\", typeof(Tensor<M23l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M23l>[]\", \"Array_of_Tensor_of_\" + \"M23l\", typeof(Tensor<M23l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M23l>>\", \"List_of_Tensor_of_\" + \"M23l\", typeof(List<Tensor<M23l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M23f\r\n\r\n                new TypeInfo(\"M23f\", typeof(M23f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M23f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M23f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M23f>\", \"Vector_of_\" + \"M23f\", typeof(Vector<M23f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M23f>[]\", \"Array_of_Vector_of_\" + \"M23f\", typeof(Vector<M23f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M23f>>\", \"List_of_Vector_of_\" + \"M23f\", typeof(List<Vector<M23f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M23f>\", \"Matrix_of_\" + \"M23f\", typeof(Matrix<M23f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M23f>[]\", \"Array_of_Matrix_of_\" + \"M23f\", typeof(Matrix<M23f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M23f>>\", \"List_of_Matrix_of_\" + \"M23f\", typeof(List<Matrix<M23f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M23f>\", \"Volume_of_\" + \"M23f\", typeof(Volume<M23f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M23f>[]\", \"Array_of_Volume_of_\" + \"M23f\", typeof(Volume<M23f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M23f>>\", \"List_of_Volume_of_\" + \"M23f\", typeof(List<Volume<M23f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M23f>\", \"Tensor_of_\" + \"M23f\", typeof(Tensor<M23f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M23f>[]\", \"Array_of_Tensor_of_\" + \"M23f\", typeof(Tensor<M23f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M23f>>\", \"List_of_Tensor_of_\" + \"M23f\", typeof(List<Tensor<M23f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M23d\r\n\r\n                new TypeInfo(\"M23d\", typeof(M23d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M23d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M23d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M23d>\", \"Vector_of_\" + \"M23d\", typeof(Vector<M23d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M23d>[]\", \"Array_of_Vector_of_\" + \"M23d\", typeof(Vector<M23d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M23d>>\", \"List_of_Vector_of_\" + \"M23d\", typeof(List<Vector<M23d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M23d>\", \"Matrix_of_\" + \"M23d\", typeof(Matrix<M23d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M23d>[]\", \"Array_of_Matrix_of_\" + \"M23d\", typeof(Matrix<M23d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M23d>>\", \"List_of_Matrix_of_\" + \"M23d\", typeof(List<Matrix<M23d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M23d>\", \"Volume_of_\" + \"M23d\", typeof(Volume<M23d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M23d>[]\", \"Array_of_Volume_of_\" + \"M23d\", typeof(Volume<M23d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M23d>>\", \"List_of_Volume_of_\" + \"M23d\", typeof(List<Volume<M23d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M23d>\", \"Tensor_of_\" + \"M23d\", typeof(Tensor<M23d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M23d>[]\", \"Array_of_Tensor_of_\" + \"M23d\", typeof(Tensor<M23d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M23d>>\", \"List_of_Tensor_of_\" + \"M23d\", typeof(List<Tensor<M23d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M33i\r\n\r\n                new TypeInfo(\"M33i\", typeof(M33i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M33i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M33i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M33i>\", \"Vector_of_\" + \"M33i\", typeof(Vector<M33i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M33i>[]\", \"Array_of_Vector_of_\" + \"M33i\", typeof(Vector<M33i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M33i>>\", \"List_of_Vector_of_\" + \"M33i\", typeof(List<Vector<M33i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M33i>\", \"Matrix_of_\" + \"M33i\", typeof(Matrix<M33i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M33i>[]\", \"Array_of_Matrix_of_\" + \"M33i\", typeof(Matrix<M33i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M33i>>\", \"List_of_Matrix_of_\" + \"M33i\", typeof(List<Matrix<M33i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M33i>\", \"Volume_of_\" + \"M33i\", typeof(Volume<M33i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M33i>[]\", \"Array_of_Volume_of_\" + \"M33i\", typeof(Volume<M33i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M33i>>\", \"List_of_Volume_of_\" + \"M33i\", typeof(List<Volume<M33i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M33i>\", \"Tensor_of_\" + \"M33i\", typeof(Tensor<M33i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M33i>[]\", \"Array_of_Tensor_of_\" + \"M33i\", typeof(Tensor<M33i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M33i>>\", \"List_of_Tensor_of_\" + \"M33i\", typeof(List<Tensor<M33i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M33l\r\n\r\n                new TypeInfo(\"M33l\", typeof(M33l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M33l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M33l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M33l>\", \"Vector_of_\" + \"M33l\", typeof(Vector<M33l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M33l>[]\", \"Array_of_Vector_of_\" + \"M33l\", typeof(Vector<M33l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M33l>>\", \"List_of_Vector_of_\" + \"M33l\", typeof(List<Vector<M33l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M33l>\", \"Matrix_of_\" + \"M33l\", typeof(Matrix<M33l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M33l>[]\", \"Array_of_Matrix_of_\" + \"M33l\", typeof(Matrix<M33l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M33l>>\", \"List_of_Matrix_of_\" + \"M33l\", typeof(List<Matrix<M33l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M33l>\", \"Volume_of_\" + \"M33l\", typeof(Volume<M33l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M33l>[]\", \"Array_of_Volume_of_\" + \"M33l\", typeof(Volume<M33l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M33l>>\", \"List_of_Volume_of_\" + \"M33l\", typeof(List<Volume<M33l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M33l>\", \"Tensor_of_\" + \"M33l\", typeof(Tensor<M33l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M33l>[]\", \"Array_of_Tensor_of_\" + \"M33l\", typeof(Tensor<M33l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M33l>>\", \"List_of_Tensor_of_\" + \"M33l\", typeof(List<Tensor<M33l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M33f\r\n\r\n                new TypeInfo(\"M33f\", typeof(M33f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M33f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M33f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M33f>\", \"Vector_of_\" + \"M33f\", typeof(Vector<M33f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M33f>[]\", \"Array_of_Vector_of_\" + \"M33f\", typeof(Vector<M33f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M33f>>\", \"List_of_Vector_of_\" + \"M33f\", typeof(List<Vector<M33f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M33f>\", \"Matrix_of_\" + \"M33f\", typeof(Matrix<M33f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M33f>[]\", \"Array_of_Matrix_of_\" + \"M33f\", typeof(Matrix<M33f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M33f>>\", \"List_of_Matrix_of_\" + \"M33f\", typeof(List<Matrix<M33f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M33f>\", \"Volume_of_\" + \"M33f\", typeof(Volume<M33f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M33f>[]\", \"Array_of_Volume_of_\" + \"M33f\", typeof(Volume<M33f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M33f>>\", \"List_of_Volume_of_\" + \"M33f\", typeof(List<Volume<M33f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M33f>\", \"Tensor_of_\" + \"M33f\", typeof(Tensor<M33f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M33f>[]\", \"Array_of_Tensor_of_\" + \"M33f\", typeof(Tensor<M33f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M33f>>\", \"List_of_Tensor_of_\" + \"M33f\", typeof(List<Tensor<M33f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M33d\r\n\r\n                new TypeInfo(\"M33d\", typeof(M33d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M33d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M33d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M33d>\", \"Vector_of_\" + \"M33d\", typeof(Vector<M33d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M33d>[]\", \"Array_of_Vector_of_\" + \"M33d\", typeof(Vector<M33d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M33d>>\", \"List_of_Vector_of_\" + \"M33d\", typeof(List<Vector<M33d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M33d>\", \"Matrix_of_\" + \"M33d\", typeof(Matrix<M33d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M33d>[]\", \"Array_of_Matrix_of_\" + \"M33d\", typeof(Matrix<M33d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M33d>>\", \"List_of_Matrix_of_\" + \"M33d\", typeof(List<Matrix<M33d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M33d>\", \"Volume_of_\" + \"M33d\", typeof(Volume<M33d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M33d>[]\", \"Array_of_Volume_of_\" + \"M33d\", typeof(Volume<M33d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M33d>>\", \"List_of_Volume_of_\" + \"M33d\", typeof(List<Volume<M33d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M33d>\", \"Tensor_of_\" + \"M33d\", typeof(Tensor<M33d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M33d>[]\", \"Array_of_Tensor_of_\" + \"M33d\", typeof(Tensor<M33d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M33d>>\", \"List_of_Tensor_of_\" + \"M33d\", typeof(List<Tensor<M33d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M34i\r\n\r\n                new TypeInfo(\"M34i\", typeof(M34i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M34i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M34i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M34i>\", \"Vector_of_\" + \"M34i\", typeof(Vector<M34i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M34i>[]\", \"Array_of_Vector_of_\" + \"M34i\", typeof(Vector<M34i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M34i>>\", \"List_of_Vector_of_\" + \"M34i\", typeof(List<Vector<M34i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M34i>\", \"Matrix_of_\" + \"M34i\", typeof(Matrix<M34i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M34i>[]\", \"Array_of_Matrix_of_\" + \"M34i\", typeof(Matrix<M34i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M34i>>\", \"List_of_Matrix_of_\" + \"M34i\", typeof(List<Matrix<M34i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M34i>\", \"Volume_of_\" + \"M34i\", typeof(Volume<M34i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M34i>[]\", \"Array_of_Volume_of_\" + \"M34i\", typeof(Volume<M34i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M34i>>\", \"List_of_Volume_of_\" + \"M34i\", typeof(List<Volume<M34i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M34i>\", \"Tensor_of_\" + \"M34i\", typeof(Tensor<M34i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M34i>[]\", \"Array_of_Tensor_of_\" + \"M34i\", typeof(Tensor<M34i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M34i>>\", \"List_of_Tensor_of_\" + \"M34i\", typeof(List<Tensor<M34i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M34l\r\n\r\n                new TypeInfo(\"M34l\", typeof(M34l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M34l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M34l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M34l>\", \"Vector_of_\" + \"M34l\", typeof(Vector<M34l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M34l>[]\", \"Array_of_Vector_of_\" + \"M34l\", typeof(Vector<M34l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M34l>>\", \"List_of_Vector_of_\" + \"M34l\", typeof(List<Vector<M34l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M34l>\", \"Matrix_of_\" + \"M34l\", typeof(Matrix<M34l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M34l>[]\", \"Array_of_Matrix_of_\" + \"M34l\", typeof(Matrix<M34l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M34l>>\", \"List_of_Matrix_of_\" + \"M34l\", typeof(List<Matrix<M34l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M34l>\", \"Volume_of_\" + \"M34l\", typeof(Volume<M34l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M34l>[]\", \"Array_of_Volume_of_\" + \"M34l\", typeof(Volume<M34l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M34l>>\", \"List_of_Volume_of_\" + \"M34l\", typeof(List<Volume<M34l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M34l>\", \"Tensor_of_\" + \"M34l\", typeof(Tensor<M34l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M34l>[]\", \"Array_of_Tensor_of_\" + \"M34l\", typeof(Tensor<M34l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M34l>>\", \"List_of_Tensor_of_\" + \"M34l\", typeof(List<Tensor<M34l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M34f\r\n\r\n                new TypeInfo(\"M34f\", typeof(M34f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M34f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M34f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M34f>\", \"Vector_of_\" + \"M34f\", typeof(Vector<M34f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M34f>[]\", \"Array_of_Vector_of_\" + \"M34f\", typeof(Vector<M34f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M34f>>\", \"List_of_Vector_of_\" + \"M34f\", typeof(List<Vector<M34f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M34f>\", \"Matrix_of_\" + \"M34f\", typeof(Matrix<M34f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M34f>[]\", \"Array_of_Matrix_of_\" + \"M34f\", typeof(Matrix<M34f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M34f>>\", \"List_of_Matrix_of_\" + \"M34f\", typeof(List<Matrix<M34f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M34f>\", \"Volume_of_\" + \"M34f\", typeof(Volume<M34f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M34f>[]\", \"Array_of_Volume_of_\" + \"M34f\", typeof(Volume<M34f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M34f>>\", \"List_of_Volume_of_\" + \"M34f\", typeof(List<Volume<M34f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M34f>\", \"Tensor_of_\" + \"M34f\", typeof(Tensor<M34f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M34f>[]\", \"Array_of_Tensor_of_\" + \"M34f\", typeof(Tensor<M34f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M34f>>\", \"List_of_Tensor_of_\" + \"M34f\", typeof(List<Tensor<M34f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M34d\r\n\r\n                new TypeInfo(\"M34d\", typeof(M34d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M34d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M34d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M34d>\", \"Vector_of_\" + \"M34d\", typeof(Vector<M34d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M34d>[]\", \"Array_of_Vector_of_\" + \"M34d\", typeof(Vector<M34d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M34d>>\", \"List_of_Vector_of_\" + \"M34d\", typeof(List<Vector<M34d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M34d>\", \"Matrix_of_\" + \"M34d\", typeof(Matrix<M34d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M34d>[]\", \"Array_of_Matrix_of_\" + \"M34d\", typeof(Matrix<M34d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M34d>>\", \"List_of_Matrix_of_\" + \"M34d\", typeof(List<Matrix<M34d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M34d>\", \"Volume_of_\" + \"M34d\", typeof(Volume<M34d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M34d>[]\", \"Array_of_Volume_of_\" + \"M34d\", typeof(Volume<M34d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M34d>>\", \"List_of_Volume_of_\" + \"M34d\", typeof(List<Volume<M34d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M34d>\", \"Tensor_of_\" + \"M34d\", typeof(Tensor<M34d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M34d>[]\", \"Array_of_Tensor_of_\" + \"M34d\", typeof(Tensor<M34d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M34d>>\", \"List_of_Tensor_of_\" + \"M34d\", typeof(List<Tensor<M34d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M44i\r\n\r\n                new TypeInfo(\"M44i\", typeof(M44i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M44i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M44i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M44i>\", \"Vector_of_\" + \"M44i\", typeof(Vector<M44i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M44i>[]\", \"Array_of_Vector_of_\" + \"M44i\", typeof(Vector<M44i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M44i>>\", \"List_of_Vector_of_\" + \"M44i\", typeof(List<Vector<M44i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M44i>\", \"Matrix_of_\" + \"M44i\", typeof(Matrix<M44i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M44i>[]\", \"Array_of_Matrix_of_\" + \"M44i\", typeof(Matrix<M44i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M44i>>\", \"List_of_Matrix_of_\" + \"M44i\", typeof(List<Matrix<M44i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M44i>\", \"Volume_of_\" + \"M44i\", typeof(Volume<M44i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M44i>[]\", \"Array_of_Volume_of_\" + \"M44i\", typeof(Volume<M44i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M44i>>\", \"List_of_Volume_of_\" + \"M44i\", typeof(List<Volume<M44i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M44i>\", \"Tensor_of_\" + \"M44i\", typeof(Tensor<M44i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M44i>[]\", \"Array_of_Tensor_of_\" + \"M44i\", typeof(Tensor<M44i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M44i>>\", \"List_of_Tensor_of_\" + \"M44i\", typeof(List<Tensor<M44i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M44l\r\n\r\n                new TypeInfo(\"M44l\", typeof(M44l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M44l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M44l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M44l>\", \"Vector_of_\" + \"M44l\", typeof(Vector<M44l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M44l>[]\", \"Array_of_Vector_of_\" + \"M44l\", typeof(Vector<M44l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M44l>>\", \"List_of_Vector_of_\" + \"M44l\", typeof(List<Vector<M44l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M44l>\", \"Matrix_of_\" + \"M44l\", typeof(Matrix<M44l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M44l>[]\", \"Array_of_Matrix_of_\" + \"M44l\", typeof(Matrix<M44l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M44l>>\", \"List_of_Matrix_of_\" + \"M44l\", typeof(List<Matrix<M44l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M44l>\", \"Volume_of_\" + \"M44l\", typeof(Volume<M44l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M44l>[]\", \"Array_of_Volume_of_\" + \"M44l\", typeof(Volume<M44l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M44l>>\", \"List_of_Volume_of_\" + \"M44l\", typeof(List<Volume<M44l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M44l>\", \"Tensor_of_\" + \"M44l\", typeof(Tensor<M44l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M44l>[]\", \"Array_of_Tensor_of_\" + \"M44l\", typeof(Tensor<M44l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M44l>>\", \"List_of_Tensor_of_\" + \"M44l\", typeof(List<Tensor<M44l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M44f\r\n\r\n                new TypeInfo(\"M44f\", typeof(M44f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M44f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M44f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M44f>\", \"Vector_of_\" + \"M44f\", typeof(Vector<M44f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M44f>[]\", \"Array_of_Vector_of_\" + \"M44f\", typeof(Vector<M44f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M44f>>\", \"List_of_Vector_of_\" + \"M44f\", typeof(List<Vector<M44f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M44f>\", \"Matrix_of_\" + \"M44f\", typeof(Matrix<M44f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M44f>[]\", \"Array_of_Matrix_of_\" + \"M44f\", typeof(Matrix<M44f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M44f>>\", \"List_of_Matrix_of_\" + \"M44f\", typeof(List<Matrix<M44f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M44f>\", \"Volume_of_\" + \"M44f\", typeof(Volume<M44f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M44f>[]\", \"Array_of_Volume_of_\" + \"M44f\", typeof(Volume<M44f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M44f>>\", \"List_of_Volume_of_\" + \"M44f\", typeof(List<Volume<M44f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M44f>\", \"Tensor_of_\" + \"M44f\", typeof(Tensor<M44f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M44f>[]\", \"Array_of_Tensor_of_\" + \"M44f\", typeof(Tensor<M44f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M44f>>\", \"List_of_Tensor_of_\" + \"M44f\", typeof(List<Tensor<M44f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region M44d\r\n\r\n                new TypeInfo(\"M44d\", typeof(M44d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(M44d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<M44d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<M44d>\", \"Vector_of_\" + \"M44d\", typeof(Vector<M44d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<M44d>[]\", \"Array_of_Vector_of_\" + \"M44d\", typeof(Vector<M44d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<M44d>>\", \"List_of_Vector_of_\" + \"M44d\", typeof(List<Vector<M44d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<M44d>\", \"Matrix_of_\" + \"M44d\", typeof(Matrix<M44d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<M44d>[]\", \"Array_of_Matrix_of_\" + \"M44d\", typeof(Matrix<M44d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<M44d>>\", \"List_of_Matrix_of_\" + \"M44d\", typeof(List<Matrix<M44d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<M44d>\", \"Volume_of_\" + \"M44d\", typeof(Volume<M44d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<M44d>[]\", \"Array_of_Volume_of_\" + \"M44d\", typeof(Volume<M44d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<M44d>>\", \"List_of_Volume_of_\" + \"M44d\", typeof(List<Volume<M44d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<M44d>\", \"Tensor_of_\" + \"M44d\", typeof(Tensor<M44d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<M44d>[]\", \"Array_of_Tensor_of_\" + \"M44d\", typeof(Tensor<M44d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<M44d>>\", \"List_of_Tensor_of_\" + \"M44d\", typeof(List<Tensor<M44d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C3b\r\n\r\n                new TypeInfo(\"C3b\", typeof(C3b), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C3b[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C3b>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C3b>\", \"Vector_of_\" + \"C3b\", typeof(Vector<C3b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C3b>[]\", \"Array_of_Vector_of_\" + \"C3b\", typeof(Vector<C3b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C3b>>\", \"List_of_Vector_of_\" + \"C3b\", typeof(List<Vector<C3b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C3b>\", \"Matrix_of_\" + \"C3b\", typeof(Matrix<C3b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C3b>[]\", \"Array_of_Matrix_of_\" + \"C3b\", typeof(Matrix<C3b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C3b>>\", \"List_of_Matrix_of_\" + \"C3b\", typeof(List<Matrix<C3b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C3b>\", \"Volume_of_\" + \"C3b\", typeof(Volume<C3b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C3b>[]\", \"Array_of_Volume_of_\" + \"C3b\", typeof(Volume<C3b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C3b>>\", \"List_of_Volume_of_\" + \"C3b\", typeof(List<Volume<C3b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C3b>\", \"Tensor_of_\" + \"C3b\", typeof(Tensor<C3b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C3b>[]\", \"Array_of_Tensor_of_\" + \"C3b\", typeof(Tensor<C3b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C3b>>\", \"List_of_Tensor_of_\" + \"C3b\", typeof(List<Tensor<C3b>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C3us\r\n\r\n                new TypeInfo(\"C3us\", typeof(C3us), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C3us[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C3us>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C3us>\", \"Vector_of_\" + \"C3us\", typeof(Vector<C3us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C3us>[]\", \"Array_of_Vector_of_\" + \"C3us\", typeof(Vector<C3us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C3us>>\", \"List_of_Vector_of_\" + \"C3us\", typeof(List<Vector<C3us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C3us>\", \"Matrix_of_\" + \"C3us\", typeof(Matrix<C3us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C3us>[]\", \"Array_of_Matrix_of_\" + \"C3us\", typeof(Matrix<C3us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C3us>>\", \"List_of_Matrix_of_\" + \"C3us\", typeof(List<Matrix<C3us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C3us>\", \"Volume_of_\" + \"C3us\", typeof(Volume<C3us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C3us>[]\", \"Array_of_Volume_of_\" + \"C3us\", typeof(Volume<C3us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C3us>>\", \"List_of_Volume_of_\" + \"C3us\", typeof(List<Volume<C3us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C3us>\", \"Tensor_of_\" + \"C3us\", typeof(Tensor<C3us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C3us>[]\", \"Array_of_Tensor_of_\" + \"C3us\", typeof(Tensor<C3us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C3us>>\", \"List_of_Tensor_of_\" + \"C3us\", typeof(List<Tensor<C3us>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C3ui\r\n\r\n                new TypeInfo(\"C3ui\", typeof(C3ui), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C3ui[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C3ui>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C3ui>\", \"Vector_of_\" + \"C3ui\", typeof(Vector<C3ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C3ui>[]\", \"Array_of_Vector_of_\" + \"C3ui\", typeof(Vector<C3ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C3ui>>\", \"List_of_Vector_of_\" + \"C3ui\", typeof(List<Vector<C3ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C3ui>\", \"Matrix_of_\" + \"C3ui\", typeof(Matrix<C3ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C3ui>[]\", \"Array_of_Matrix_of_\" + \"C3ui\", typeof(Matrix<C3ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C3ui>>\", \"List_of_Matrix_of_\" + \"C3ui\", typeof(List<Matrix<C3ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C3ui>\", \"Volume_of_\" + \"C3ui\", typeof(Volume<C3ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C3ui>[]\", \"Array_of_Volume_of_\" + \"C3ui\", typeof(Volume<C3ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C3ui>>\", \"List_of_Volume_of_\" + \"C3ui\", typeof(List<Volume<C3ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C3ui>\", \"Tensor_of_\" + \"C3ui\", typeof(Tensor<C3ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C3ui>[]\", \"Array_of_Tensor_of_\" + \"C3ui\", typeof(Tensor<C3ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C3ui>>\", \"List_of_Tensor_of_\" + \"C3ui\", typeof(List<Tensor<C3ui>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C3f\r\n\r\n                new TypeInfo(\"C3f\", typeof(C3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C3f>\", \"Vector_of_\" + \"C3f\", typeof(Vector<C3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C3f>[]\", \"Array_of_Vector_of_\" + \"C3f\", typeof(Vector<C3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C3f>>\", \"List_of_Vector_of_\" + \"C3f\", typeof(List<Vector<C3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C3f>\", \"Matrix_of_\" + \"C3f\", typeof(Matrix<C3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C3f>[]\", \"Array_of_Matrix_of_\" + \"C3f\", typeof(Matrix<C3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C3f>>\", \"List_of_Matrix_of_\" + \"C3f\", typeof(List<Matrix<C3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C3f>\", \"Volume_of_\" + \"C3f\", typeof(Volume<C3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C3f>[]\", \"Array_of_Volume_of_\" + \"C3f\", typeof(Volume<C3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C3f>>\", \"List_of_Volume_of_\" + \"C3f\", typeof(List<Volume<C3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C3f>\", \"Tensor_of_\" + \"C3f\", typeof(Tensor<C3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C3f>[]\", \"Array_of_Tensor_of_\" + \"C3f\", typeof(Tensor<C3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C3f>>\", \"List_of_Tensor_of_\" + \"C3f\", typeof(List<Tensor<C3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C3d\r\n\r\n                new TypeInfo(\"C3d\", typeof(C3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C3d>\", \"Vector_of_\" + \"C3d\", typeof(Vector<C3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C3d>[]\", \"Array_of_Vector_of_\" + \"C3d\", typeof(Vector<C3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C3d>>\", \"List_of_Vector_of_\" + \"C3d\", typeof(List<Vector<C3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C3d>\", \"Matrix_of_\" + \"C3d\", typeof(Matrix<C3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C3d>[]\", \"Array_of_Matrix_of_\" + \"C3d\", typeof(Matrix<C3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C3d>>\", \"List_of_Matrix_of_\" + \"C3d\", typeof(List<Matrix<C3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C3d>\", \"Volume_of_\" + \"C3d\", typeof(Volume<C3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C3d>[]\", \"Array_of_Volume_of_\" + \"C3d\", typeof(Volume<C3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C3d>>\", \"List_of_Volume_of_\" + \"C3d\", typeof(List<Volume<C3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C3d>\", \"Tensor_of_\" + \"C3d\", typeof(Tensor<C3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C3d>[]\", \"Array_of_Tensor_of_\" + \"C3d\", typeof(Tensor<C3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C3d>>\", \"List_of_Tensor_of_\" + \"C3d\", typeof(List<Tensor<C3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C4b\r\n\r\n                new TypeInfo(\"C4b\", typeof(C4b), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C4b[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C4b>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C4b>\", \"Vector_of_\" + \"C4b\", typeof(Vector<C4b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C4b>[]\", \"Array_of_Vector_of_\" + \"C4b\", typeof(Vector<C4b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C4b>>\", \"List_of_Vector_of_\" + \"C4b\", typeof(List<Vector<C4b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C4b>\", \"Matrix_of_\" + \"C4b\", typeof(Matrix<C4b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C4b>[]\", \"Array_of_Matrix_of_\" + \"C4b\", typeof(Matrix<C4b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C4b>>\", \"List_of_Matrix_of_\" + \"C4b\", typeof(List<Matrix<C4b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C4b>\", \"Volume_of_\" + \"C4b\", typeof(Volume<C4b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C4b>[]\", \"Array_of_Volume_of_\" + \"C4b\", typeof(Volume<C4b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C4b>>\", \"List_of_Volume_of_\" + \"C4b\", typeof(List<Volume<C4b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C4b>\", \"Tensor_of_\" + \"C4b\", typeof(Tensor<C4b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C4b>[]\", \"Array_of_Tensor_of_\" + \"C4b\", typeof(Tensor<C4b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C4b>>\", \"List_of_Tensor_of_\" + \"C4b\", typeof(List<Tensor<C4b>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C4us\r\n\r\n                new TypeInfo(\"C4us\", typeof(C4us), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C4us[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C4us>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C4us>\", \"Vector_of_\" + \"C4us\", typeof(Vector<C4us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C4us>[]\", \"Array_of_Vector_of_\" + \"C4us\", typeof(Vector<C4us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C4us>>\", \"List_of_Vector_of_\" + \"C4us\", typeof(List<Vector<C4us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C4us>\", \"Matrix_of_\" + \"C4us\", typeof(Matrix<C4us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C4us>[]\", \"Array_of_Matrix_of_\" + \"C4us\", typeof(Matrix<C4us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C4us>>\", \"List_of_Matrix_of_\" + \"C4us\", typeof(List<Matrix<C4us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C4us>\", \"Volume_of_\" + \"C4us\", typeof(Volume<C4us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C4us>[]\", \"Array_of_Volume_of_\" + \"C4us\", typeof(Volume<C4us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C4us>>\", \"List_of_Volume_of_\" + \"C4us\", typeof(List<Volume<C4us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C4us>\", \"Tensor_of_\" + \"C4us\", typeof(Tensor<C4us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C4us>[]\", \"Array_of_Tensor_of_\" + \"C4us\", typeof(Tensor<C4us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C4us>>\", \"List_of_Tensor_of_\" + \"C4us\", typeof(List<Tensor<C4us>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C4ui\r\n\r\n                new TypeInfo(\"C4ui\", typeof(C4ui), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C4ui[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C4ui>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C4ui>\", \"Vector_of_\" + \"C4ui\", typeof(Vector<C4ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C4ui>[]\", \"Array_of_Vector_of_\" + \"C4ui\", typeof(Vector<C4ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C4ui>>\", \"List_of_Vector_of_\" + \"C4ui\", typeof(List<Vector<C4ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C4ui>\", \"Matrix_of_\" + \"C4ui\", typeof(Matrix<C4ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C4ui>[]\", \"Array_of_Matrix_of_\" + \"C4ui\", typeof(Matrix<C4ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C4ui>>\", \"List_of_Matrix_of_\" + \"C4ui\", typeof(List<Matrix<C4ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C4ui>\", \"Volume_of_\" + \"C4ui\", typeof(Volume<C4ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C4ui>[]\", \"Array_of_Volume_of_\" + \"C4ui\", typeof(Volume<C4ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C4ui>>\", \"List_of_Volume_of_\" + \"C4ui\", typeof(List<Volume<C4ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C4ui>\", \"Tensor_of_\" + \"C4ui\", typeof(Tensor<C4ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C4ui>[]\", \"Array_of_Tensor_of_\" + \"C4ui\", typeof(Tensor<C4ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C4ui>>\", \"List_of_Tensor_of_\" + \"C4ui\", typeof(List<Tensor<C4ui>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C4f\r\n\r\n                new TypeInfo(\"C4f\", typeof(C4f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C4f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C4f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C4f>\", \"Vector_of_\" + \"C4f\", typeof(Vector<C4f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C4f>[]\", \"Array_of_Vector_of_\" + \"C4f\", typeof(Vector<C4f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C4f>>\", \"List_of_Vector_of_\" + \"C4f\", typeof(List<Vector<C4f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C4f>\", \"Matrix_of_\" + \"C4f\", typeof(Matrix<C4f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C4f>[]\", \"Array_of_Matrix_of_\" + \"C4f\", typeof(Matrix<C4f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C4f>>\", \"List_of_Matrix_of_\" + \"C4f\", typeof(List<Matrix<C4f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C4f>\", \"Volume_of_\" + \"C4f\", typeof(Volume<C4f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C4f>[]\", \"Array_of_Volume_of_\" + \"C4f\", typeof(Volume<C4f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C4f>>\", \"List_of_Volume_of_\" + \"C4f\", typeof(List<Volume<C4f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C4f>\", \"Tensor_of_\" + \"C4f\", typeof(Tensor<C4f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C4f>[]\", \"Array_of_Tensor_of_\" + \"C4f\", typeof(Tensor<C4f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C4f>>\", \"List_of_Tensor_of_\" + \"C4f\", typeof(List<Tensor<C4f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region C4d\r\n\r\n                new TypeInfo(\"C4d\", typeof(C4d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(C4d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<C4d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<C4d>\", \"Vector_of_\" + \"C4d\", typeof(Vector<C4d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<C4d>[]\", \"Array_of_Vector_of_\" + \"C4d\", typeof(Vector<C4d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<C4d>>\", \"List_of_Vector_of_\" + \"C4d\", typeof(List<Vector<C4d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<C4d>\", \"Matrix_of_\" + \"C4d\", typeof(Matrix<C4d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<C4d>[]\", \"Array_of_Matrix_of_\" + \"C4d\", typeof(Matrix<C4d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<C4d>>\", \"List_of_Matrix_of_\" + \"C4d\", typeof(List<Matrix<C4d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<C4d>\", \"Volume_of_\" + \"C4d\", typeof(Volume<C4d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<C4d>[]\", \"Array_of_Volume_of_\" + \"C4d\", typeof(Volume<C4d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<C4d>>\", \"List_of_Volume_of_\" + \"C4d\", typeof(List<Volume<C4d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<C4d>\", \"Tensor_of_\" + \"C4d\", typeof(Tensor<C4d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<C4d>[]\", \"Array_of_Tensor_of_\" + \"C4d\", typeof(Tensor<C4d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<C4d>>\", \"List_of_Tensor_of_\" + \"C4d\", typeof(List<Tensor<C4d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1b\r\n\r\n                new TypeInfo(\"Range1b\", typeof(Range1b), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1b[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1b>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1b>\", \"Vector_of_\" + \"Range1b\", typeof(Vector<Range1b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1b>[]\", \"Array_of_Vector_of_\" + \"Range1b\", typeof(Vector<Range1b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1b>>\", \"List_of_Vector_of_\" + \"Range1b\", typeof(List<Vector<Range1b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1b>\", \"Matrix_of_\" + \"Range1b\", typeof(Matrix<Range1b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1b>[]\", \"Array_of_Matrix_of_\" + \"Range1b\", typeof(Matrix<Range1b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1b>>\", \"List_of_Matrix_of_\" + \"Range1b\", typeof(List<Matrix<Range1b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1b>\", \"Volume_of_\" + \"Range1b\", typeof(Volume<Range1b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1b>[]\", \"Array_of_Volume_of_\" + \"Range1b\", typeof(Volume<Range1b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1b>>\", \"List_of_Volume_of_\" + \"Range1b\", typeof(List<Volume<Range1b>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1b>\", \"Tensor_of_\" + \"Range1b\", typeof(Tensor<Range1b>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1b>[]\", \"Array_of_Tensor_of_\" + \"Range1b\", typeof(Tensor<Range1b>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1b>>\", \"List_of_Tensor_of_\" + \"Range1b\", typeof(List<Tensor<Range1b>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1sb\r\n\r\n                new TypeInfo(\"Range1sb\", typeof(Range1sb), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1sb[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1sb>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1sb>\", \"Vector_of_\" + \"Range1sb\", typeof(Vector<Range1sb>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1sb>[]\", \"Array_of_Vector_of_\" + \"Range1sb\", typeof(Vector<Range1sb>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1sb>>\", \"List_of_Vector_of_\" + \"Range1sb\", typeof(List<Vector<Range1sb>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1sb>\", \"Matrix_of_\" + \"Range1sb\", typeof(Matrix<Range1sb>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1sb>[]\", \"Array_of_Matrix_of_\" + \"Range1sb\", typeof(Matrix<Range1sb>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1sb>>\", \"List_of_Matrix_of_\" + \"Range1sb\", typeof(List<Matrix<Range1sb>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1sb>\", \"Volume_of_\" + \"Range1sb\", typeof(Volume<Range1sb>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1sb>[]\", \"Array_of_Volume_of_\" + \"Range1sb\", typeof(Volume<Range1sb>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1sb>>\", \"List_of_Volume_of_\" + \"Range1sb\", typeof(List<Volume<Range1sb>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1sb>\", \"Tensor_of_\" + \"Range1sb\", typeof(Tensor<Range1sb>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1sb>[]\", \"Array_of_Tensor_of_\" + \"Range1sb\", typeof(Tensor<Range1sb>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1sb>>\", \"List_of_Tensor_of_\" + \"Range1sb\", typeof(List<Tensor<Range1sb>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1s\r\n\r\n                new TypeInfo(\"Range1s\", typeof(Range1s), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1s[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1s>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1s>\", \"Vector_of_\" + \"Range1s\", typeof(Vector<Range1s>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1s>[]\", \"Array_of_Vector_of_\" + \"Range1s\", typeof(Vector<Range1s>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1s>>\", \"List_of_Vector_of_\" + \"Range1s\", typeof(List<Vector<Range1s>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1s>\", \"Matrix_of_\" + \"Range1s\", typeof(Matrix<Range1s>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1s>[]\", \"Array_of_Matrix_of_\" + \"Range1s\", typeof(Matrix<Range1s>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1s>>\", \"List_of_Matrix_of_\" + \"Range1s\", typeof(List<Matrix<Range1s>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1s>\", \"Volume_of_\" + \"Range1s\", typeof(Volume<Range1s>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1s>[]\", \"Array_of_Volume_of_\" + \"Range1s\", typeof(Volume<Range1s>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1s>>\", \"List_of_Volume_of_\" + \"Range1s\", typeof(List<Volume<Range1s>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1s>\", \"Tensor_of_\" + \"Range1s\", typeof(Tensor<Range1s>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1s>[]\", \"Array_of_Tensor_of_\" + \"Range1s\", typeof(Tensor<Range1s>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1s>>\", \"List_of_Tensor_of_\" + \"Range1s\", typeof(List<Tensor<Range1s>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1us\r\n\r\n                new TypeInfo(\"Range1us\", typeof(Range1us), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1us[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1us>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1us>\", \"Vector_of_\" + \"Range1us\", typeof(Vector<Range1us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1us>[]\", \"Array_of_Vector_of_\" + \"Range1us\", typeof(Vector<Range1us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1us>>\", \"List_of_Vector_of_\" + \"Range1us\", typeof(List<Vector<Range1us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1us>\", \"Matrix_of_\" + \"Range1us\", typeof(Matrix<Range1us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1us>[]\", \"Array_of_Matrix_of_\" + \"Range1us\", typeof(Matrix<Range1us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1us>>\", \"List_of_Matrix_of_\" + \"Range1us\", typeof(List<Matrix<Range1us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1us>\", \"Volume_of_\" + \"Range1us\", typeof(Volume<Range1us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1us>[]\", \"Array_of_Volume_of_\" + \"Range1us\", typeof(Volume<Range1us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1us>>\", \"List_of_Volume_of_\" + \"Range1us\", typeof(List<Volume<Range1us>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1us>\", \"Tensor_of_\" + \"Range1us\", typeof(Tensor<Range1us>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1us>[]\", \"Array_of_Tensor_of_\" + \"Range1us\", typeof(Tensor<Range1us>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1us>>\", \"List_of_Tensor_of_\" + \"Range1us\", typeof(List<Tensor<Range1us>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1i\r\n\r\n                new TypeInfo(\"Range1i\", typeof(Range1i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1i>\", \"Vector_of_\" + \"Range1i\", typeof(Vector<Range1i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1i>[]\", \"Array_of_Vector_of_\" + \"Range1i\", typeof(Vector<Range1i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1i>>\", \"List_of_Vector_of_\" + \"Range1i\", typeof(List<Vector<Range1i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1i>\", \"Matrix_of_\" + \"Range1i\", typeof(Matrix<Range1i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1i>[]\", \"Array_of_Matrix_of_\" + \"Range1i\", typeof(Matrix<Range1i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1i>>\", \"List_of_Matrix_of_\" + \"Range1i\", typeof(List<Matrix<Range1i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1i>\", \"Volume_of_\" + \"Range1i\", typeof(Volume<Range1i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1i>[]\", \"Array_of_Volume_of_\" + \"Range1i\", typeof(Volume<Range1i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1i>>\", \"List_of_Volume_of_\" + \"Range1i\", typeof(List<Volume<Range1i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1i>\", \"Tensor_of_\" + \"Range1i\", typeof(Tensor<Range1i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1i>[]\", \"Array_of_Tensor_of_\" + \"Range1i\", typeof(Tensor<Range1i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1i>>\", \"List_of_Tensor_of_\" + \"Range1i\", typeof(List<Tensor<Range1i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1ui\r\n\r\n                new TypeInfo(\"Range1ui\", typeof(Range1ui), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1ui[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1ui>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1ui>\", \"Vector_of_\" + \"Range1ui\", typeof(Vector<Range1ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1ui>[]\", \"Array_of_Vector_of_\" + \"Range1ui\", typeof(Vector<Range1ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1ui>>\", \"List_of_Vector_of_\" + \"Range1ui\", typeof(List<Vector<Range1ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1ui>\", \"Matrix_of_\" + \"Range1ui\", typeof(Matrix<Range1ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1ui>[]\", \"Array_of_Matrix_of_\" + \"Range1ui\", typeof(Matrix<Range1ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1ui>>\", \"List_of_Matrix_of_\" + \"Range1ui\", typeof(List<Matrix<Range1ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1ui>\", \"Volume_of_\" + \"Range1ui\", typeof(Volume<Range1ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1ui>[]\", \"Array_of_Volume_of_\" + \"Range1ui\", typeof(Volume<Range1ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1ui>>\", \"List_of_Volume_of_\" + \"Range1ui\", typeof(List<Volume<Range1ui>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1ui>\", \"Tensor_of_\" + \"Range1ui\", typeof(Tensor<Range1ui>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1ui>[]\", \"Array_of_Tensor_of_\" + \"Range1ui\", typeof(Tensor<Range1ui>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1ui>>\", \"List_of_Tensor_of_\" + \"Range1ui\", typeof(List<Tensor<Range1ui>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1l\r\n\r\n                new TypeInfo(\"Range1l\", typeof(Range1l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1l>\", \"Vector_of_\" + \"Range1l\", typeof(Vector<Range1l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1l>[]\", \"Array_of_Vector_of_\" + \"Range1l\", typeof(Vector<Range1l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1l>>\", \"List_of_Vector_of_\" + \"Range1l\", typeof(List<Vector<Range1l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1l>\", \"Matrix_of_\" + \"Range1l\", typeof(Matrix<Range1l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1l>[]\", \"Array_of_Matrix_of_\" + \"Range1l\", typeof(Matrix<Range1l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1l>>\", \"List_of_Matrix_of_\" + \"Range1l\", typeof(List<Matrix<Range1l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1l>\", \"Volume_of_\" + \"Range1l\", typeof(Volume<Range1l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1l>[]\", \"Array_of_Volume_of_\" + \"Range1l\", typeof(Volume<Range1l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1l>>\", \"List_of_Volume_of_\" + \"Range1l\", typeof(List<Volume<Range1l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1l>\", \"Tensor_of_\" + \"Range1l\", typeof(Tensor<Range1l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1l>[]\", \"Array_of_Tensor_of_\" + \"Range1l\", typeof(Tensor<Range1l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1l>>\", \"List_of_Tensor_of_\" + \"Range1l\", typeof(List<Tensor<Range1l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1ul\r\n\r\n                new TypeInfo(\"Range1ul\", typeof(Range1ul), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1ul[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1ul>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1ul>\", \"Vector_of_\" + \"Range1ul\", typeof(Vector<Range1ul>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1ul>[]\", \"Array_of_Vector_of_\" + \"Range1ul\", typeof(Vector<Range1ul>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1ul>>\", \"List_of_Vector_of_\" + \"Range1ul\", typeof(List<Vector<Range1ul>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1ul>\", \"Matrix_of_\" + \"Range1ul\", typeof(Matrix<Range1ul>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1ul>[]\", \"Array_of_Matrix_of_\" + \"Range1ul\", typeof(Matrix<Range1ul>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1ul>>\", \"List_of_Matrix_of_\" + \"Range1ul\", typeof(List<Matrix<Range1ul>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1ul>\", \"Volume_of_\" + \"Range1ul\", typeof(Volume<Range1ul>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1ul>[]\", \"Array_of_Volume_of_\" + \"Range1ul\", typeof(Volume<Range1ul>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1ul>>\", \"List_of_Volume_of_\" + \"Range1ul\", typeof(List<Volume<Range1ul>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1ul>\", \"Tensor_of_\" + \"Range1ul\", typeof(Tensor<Range1ul>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1ul>[]\", \"Array_of_Tensor_of_\" + \"Range1ul\", typeof(Tensor<Range1ul>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1ul>>\", \"List_of_Tensor_of_\" + \"Range1ul\", typeof(List<Tensor<Range1ul>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1f\r\n\r\n                new TypeInfo(\"Range1f\", typeof(Range1f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1f>\", \"Vector_of_\" + \"Range1f\", typeof(Vector<Range1f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1f>[]\", \"Array_of_Vector_of_\" + \"Range1f\", typeof(Vector<Range1f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1f>>\", \"List_of_Vector_of_\" + \"Range1f\", typeof(List<Vector<Range1f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1f>\", \"Matrix_of_\" + \"Range1f\", typeof(Matrix<Range1f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1f>[]\", \"Array_of_Matrix_of_\" + \"Range1f\", typeof(Matrix<Range1f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1f>>\", \"List_of_Matrix_of_\" + \"Range1f\", typeof(List<Matrix<Range1f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1f>\", \"Volume_of_\" + \"Range1f\", typeof(Volume<Range1f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1f>[]\", \"Array_of_Volume_of_\" + \"Range1f\", typeof(Volume<Range1f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1f>>\", \"List_of_Volume_of_\" + \"Range1f\", typeof(List<Volume<Range1f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1f>\", \"Tensor_of_\" + \"Range1f\", typeof(Tensor<Range1f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1f>[]\", \"Array_of_Tensor_of_\" + \"Range1f\", typeof(Tensor<Range1f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1f>>\", \"List_of_Tensor_of_\" + \"Range1f\", typeof(List<Tensor<Range1f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Range1d\r\n\r\n                new TypeInfo(\"Range1d\", typeof(Range1d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Range1d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Range1d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Range1d>\", \"Vector_of_\" + \"Range1d\", typeof(Vector<Range1d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Range1d>[]\", \"Array_of_Vector_of_\" + \"Range1d\", typeof(Vector<Range1d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Range1d>>\", \"List_of_Vector_of_\" + \"Range1d\", typeof(List<Vector<Range1d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Range1d>\", \"Matrix_of_\" + \"Range1d\", typeof(Matrix<Range1d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Range1d>[]\", \"Array_of_Matrix_of_\" + \"Range1d\", typeof(Matrix<Range1d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Range1d>>\", \"List_of_Matrix_of_\" + \"Range1d\", typeof(List<Matrix<Range1d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Range1d>\", \"Volume_of_\" + \"Range1d\", typeof(Volume<Range1d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Range1d>[]\", \"Array_of_Volume_of_\" + \"Range1d\", typeof(Volume<Range1d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Range1d>>\", \"List_of_Volume_of_\" + \"Range1d\", typeof(List<Volume<Range1d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Range1d>\", \"Tensor_of_\" + \"Range1d\", typeof(Tensor<Range1d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Range1d>[]\", \"Array_of_Tensor_of_\" + \"Range1d\", typeof(Tensor<Range1d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Range1d>>\", \"List_of_Tensor_of_\" + \"Range1d\", typeof(List<Tensor<Range1d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Box2i\r\n\r\n                new TypeInfo(\"Box2i\", typeof(Box2i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Box2i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Box2i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Box2i>\", \"Vector_of_\" + \"Box2i\", typeof(Vector<Box2i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Box2i>[]\", \"Array_of_Vector_of_\" + \"Box2i\", typeof(Vector<Box2i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Box2i>>\", \"List_of_Vector_of_\" + \"Box2i\", typeof(List<Vector<Box2i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Box2i>\", \"Matrix_of_\" + \"Box2i\", typeof(Matrix<Box2i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Box2i>[]\", \"Array_of_Matrix_of_\" + \"Box2i\", typeof(Matrix<Box2i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Box2i>>\", \"List_of_Matrix_of_\" + \"Box2i\", typeof(List<Matrix<Box2i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Box2i>\", \"Volume_of_\" + \"Box2i\", typeof(Volume<Box2i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Box2i>[]\", \"Array_of_Volume_of_\" + \"Box2i\", typeof(Volume<Box2i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Box2i>>\", \"List_of_Volume_of_\" + \"Box2i\", typeof(List<Volume<Box2i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Box2i>\", \"Tensor_of_\" + \"Box2i\", typeof(Tensor<Box2i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Box2i>[]\", \"Array_of_Tensor_of_\" + \"Box2i\", typeof(Tensor<Box2i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Box2i>>\", \"List_of_Tensor_of_\" + \"Box2i\", typeof(List<Tensor<Box2i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Box2l\r\n\r\n                new TypeInfo(\"Box2l\", typeof(Box2l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Box2l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Box2l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Box2l>\", \"Vector_of_\" + \"Box2l\", typeof(Vector<Box2l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Box2l>[]\", \"Array_of_Vector_of_\" + \"Box2l\", typeof(Vector<Box2l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Box2l>>\", \"List_of_Vector_of_\" + \"Box2l\", typeof(List<Vector<Box2l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Box2l>\", \"Matrix_of_\" + \"Box2l\", typeof(Matrix<Box2l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Box2l>[]\", \"Array_of_Matrix_of_\" + \"Box2l\", typeof(Matrix<Box2l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Box2l>>\", \"List_of_Matrix_of_\" + \"Box2l\", typeof(List<Matrix<Box2l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Box2l>\", \"Volume_of_\" + \"Box2l\", typeof(Volume<Box2l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Box2l>[]\", \"Array_of_Volume_of_\" + \"Box2l\", typeof(Volume<Box2l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Box2l>>\", \"List_of_Volume_of_\" + \"Box2l\", typeof(List<Volume<Box2l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Box2l>\", \"Tensor_of_\" + \"Box2l\", typeof(Tensor<Box2l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Box2l>[]\", \"Array_of_Tensor_of_\" + \"Box2l\", typeof(Tensor<Box2l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Box2l>>\", \"List_of_Tensor_of_\" + \"Box2l\", typeof(List<Tensor<Box2l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Box2f\r\n\r\n                new TypeInfo(\"Box2f\", typeof(Box2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Box2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Box2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Box2f>\", \"Vector_of_\" + \"Box2f\", typeof(Vector<Box2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Box2f>[]\", \"Array_of_Vector_of_\" + \"Box2f\", typeof(Vector<Box2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Box2f>>\", \"List_of_Vector_of_\" + \"Box2f\", typeof(List<Vector<Box2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Box2f>\", \"Matrix_of_\" + \"Box2f\", typeof(Matrix<Box2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Box2f>[]\", \"Array_of_Matrix_of_\" + \"Box2f\", typeof(Matrix<Box2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Box2f>>\", \"List_of_Matrix_of_\" + \"Box2f\", typeof(List<Matrix<Box2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Box2f>\", \"Volume_of_\" + \"Box2f\", typeof(Volume<Box2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Box2f>[]\", \"Array_of_Volume_of_\" + \"Box2f\", typeof(Volume<Box2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Box2f>>\", \"List_of_Volume_of_\" + \"Box2f\", typeof(List<Volume<Box2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Box2f>\", \"Tensor_of_\" + \"Box2f\", typeof(Tensor<Box2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Box2f>[]\", \"Array_of_Tensor_of_\" + \"Box2f\", typeof(Tensor<Box2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Box2f>>\", \"List_of_Tensor_of_\" + \"Box2f\", typeof(List<Tensor<Box2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Box2d\r\n\r\n                new TypeInfo(\"Box2d\", typeof(Box2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Box2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Box2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Box2d>\", \"Vector_of_\" + \"Box2d\", typeof(Vector<Box2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Box2d>[]\", \"Array_of_Vector_of_\" + \"Box2d\", typeof(Vector<Box2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Box2d>>\", \"List_of_Vector_of_\" + \"Box2d\", typeof(List<Vector<Box2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Box2d>\", \"Matrix_of_\" + \"Box2d\", typeof(Matrix<Box2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Box2d>[]\", \"Array_of_Matrix_of_\" + \"Box2d\", typeof(Matrix<Box2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Box2d>>\", \"List_of_Matrix_of_\" + \"Box2d\", typeof(List<Matrix<Box2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Box2d>\", \"Volume_of_\" + \"Box2d\", typeof(Volume<Box2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Box2d>[]\", \"Array_of_Volume_of_\" + \"Box2d\", typeof(Volume<Box2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Box2d>>\", \"List_of_Volume_of_\" + \"Box2d\", typeof(List<Volume<Box2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Box2d>\", \"Tensor_of_\" + \"Box2d\", typeof(Tensor<Box2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Box2d>[]\", \"Array_of_Tensor_of_\" + \"Box2d\", typeof(Tensor<Box2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Box2d>>\", \"List_of_Tensor_of_\" + \"Box2d\", typeof(List<Tensor<Box2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Box3i\r\n\r\n                new TypeInfo(\"Box3i\", typeof(Box3i), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Box3i[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Box3i>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Box3i>\", \"Vector_of_\" + \"Box3i\", typeof(Vector<Box3i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Box3i>[]\", \"Array_of_Vector_of_\" + \"Box3i\", typeof(Vector<Box3i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Box3i>>\", \"List_of_Vector_of_\" + \"Box3i\", typeof(List<Vector<Box3i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Box3i>\", \"Matrix_of_\" + \"Box3i\", typeof(Matrix<Box3i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Box3i>[]\", \"Array_of_Matrix_of_\" + \"Box3i\", typeof(Matrix<Box3i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Box3i>>\", \"List_of_Matrix_of_\" + \"Box3i\", typeof(List<Matrix<Box3i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Box3i>\", \"Volume_of_\" + \"Box3i\", typeof(Volume<Box3i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Box3i>[]\", \"Array_of_Volume_of_\" + \"Box3i\", typeof(Volume<Box3i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Box3i>>\", \"List_of_Volume_of_\" + \"Box3i\", typeof(List<Volume<Box3i>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Box3i>\", \"Tensor_of_\" + \"Box3i\", typeof(Tensor<Box3i>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Box3i>[]\", \"Array_of_Tensor_of_\" + \"Box3i\", typeof(Tensor<Box3i>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Box3i>>\", \"List_of_Tensor_of_\" + \"Box3i\", typeof(List<Tensor<Box3i>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Box3l\r\n\r\n                new TypeInfo(\"Box3l\", typeof(Box3l), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Box3l[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Box3l>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Box3l>\", \"Vector_of_\" + \"Box3l\", typeof(Vector<Box3l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Box3l>[]\", \"Array_of_Vector_of_\" + \"Box3l\", typeof(Vector<Box3l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Box3l>>\", \"List_of_Vector_of_\" + \"Box3l\", typeof(List<Vector<Box3l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Box3l>\", \"Matrix_of_\" + \"Box3l\", typeof(Matrix<Box3l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Box3l>[]\", \"Array_of_Matrix_of_\" + \"Box3l\", typeof(Matrix<Box3l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Box3l>>\", \"List_of_Matrix_of_\" + \"Box3l\", typeof(List<Matrix<Box3l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Box3l>\", \"Volume_of_\" + \"Box3l\", typeof(Volume<Box3l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Box3l>[]\", \"Array_of_Volume_of_\" + \"Box3l\", typeof(Volume<Box3l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Box3l>>\", \"List_of_Volume_of_\" + \"Box3l\", typeof(List<Volume<Box3l>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Box3l>\", \"Tensor_of_\" + \"Box3l\", typeof(Tensor<Box3l>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Box3l>[]\", \"Array_of_Tensor_of_\" + \"Box3l\", typeof(Tensor<Box3l>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Box3l>>\", \"List_of_Tensor_of_\" + \"Box3l\", typeof(List<Tensor<Box3l>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Box3f\r\n\r\n                new TypeInfo(\"Box3f\", typeof(Box3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Box3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Box3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Box3f>\", \"Vector_of_\" + \"Box3f\", typeof(Vector<Box3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Box3f>[]\", \"Array_of_Vector_of_\" + \"Box3f\", typeof(Vector<Box3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Box3f>>\", \"List_of_Vector_of_\" + \"Box3f\", typeof(List<Vector<Box3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Box3f>\", \"Matrix_of_\" + \"Box3f\", typeof(Matrix<Box3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Box3f>[]\", \"Array_of_Matrix_of_\" + \"Box3f\", typeof(Matrix<Box3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Box3f>>\", \"List_of_Matrix_of_\" + \"Box3f\", typeof(List<Matrix<Box3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Box3f>\", \"Volume_of_\" + \"Box3f\", typeof(Volume<Box3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Box3f>[]\", \"Array_of_Volume_of_\" + \"Box3f\", typeof(Volume<Box3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Box3f>>\", \"List_of_Volume_of_\" + \"Box3f\", typeof(List<Volume<Box3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Box3f>\", \"Tensor_of_\" + \"Box3f\", typeof(Tensor<Box3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Box3f>[]\", \"Array_of_Tensor_of_\" + \"Box3f\", typeof(Tensor<Box3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Box3f>>\", \"List_of_Tensor_of_\" + \"Box3f\", typeof(List<Tensor<Box3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Box3d\r\n\r\n                new TypeInfo(\"Box3d\", typeof(Box3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Box3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Box3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Box3d>\", \"Vector_of_\" + \"Box3d\", typeof(Vector<Box3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Box3d>[]\", \"Array_of_Vector_of_\" + \"Box3d\", typeof(Vector<Box3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Box3d>>\", \"List_of_Vector_of_\" + \"Box3d\", typeof(List<Vector<Box3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Box3d>\", \"Matrix_of_\" + \"Box3d\", typeof(Matrix<Box3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Box3d>[]\", \"Array_of_Matrix_of_\" + \"Box3d\", typeof(Matrix<Box3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Box3d>>\", \"List_of_Matrix_of_\" + \"Box3d\", typeof(List<Matrix<Box3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Box3d>\", \"Volume_of_\" + \"Box3d\", typeof(Volume<Box3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Box3d>[]\", \"Array_of_Volume_of_\" + \"Box3d\", typeof(Volume<Box3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Box3d>>\", \"List_of_Volume_of_\" + \"Box3d\", typeof(List<Volume<Box3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Box3d>\", \"Tensor_of_\" + \"Box3d\", typeof(Tensor<Box3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Box3d>[]\", \"Array_of_Tensor_of_\" + \"Box3d\", typeof(Tensor<Box3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Box3d>>\", \"List_of_Tensor_of_\" + \"Box3d\", typeof(List<Tensor<Box3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Euclidean3f\r\n\r\n                new TypeInfo(\"Euclidean3f\", typeof(Euclidean3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Euclidean3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Euclidean3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Euclidean3f>\", \"Vector_of_\" + \"Euclidean3f\", typeof(Vector<Euclidean3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Euclidean3f>[]\", \"Array_of_Vector_of_\" + \"Euclidean3f\", typeof(Vector<Euclidean3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Euclidean3f>>\", \"List_of_Vector_of_\" + \"Euclidean3f\", typeof(List<Vector<Euclidean3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Euclidean3f>\", \"Matrix_of_\" + \"Euclidean3f\", typeof(Matrix<Euclidean3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Euclidean3f>[]\", \"Array_of_Matrix_of_\" + \"Euclidean3f\", typeof(Matrix<Euclidean3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Euclidean3f>>\", \"List_of_Matrix_of_\" + \"Euclidean3f\", typeof(List<Matrix<Euclidean3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Euclidean3f>\", \"Volume_of_\" + \"Euclidean3f\", typeof(Volume<Euclidean3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Euclidean3f>[]\", \"Array_of_Volume_of_\" + \"Euclidean3f\", typeof(Volume<Euclidean3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Euclidean3f>>\", \"List_of_Volume_of_\" + \"Euclidean3f\", typeof(List<Volume<Euclidean3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Euclidean3f>\", \"Tensor_of_\" + \"Euclidean3f\", typeof(Tensor<Euclidean3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Euclidean3f>[]\", \"Array_of_Tensor_of_\" + \"Euclidean3f\", typeof(Tensor<Euclidean3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Euclidean3f>>\", \"List_of_Tensor_of_\" + \"Euclidean3f\", typeof(List<Tensor<Euclidean3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Euclidean3d\r\n\r\n                new TypeInfo(\"Euclidean3d\", typeof(Euclidean3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Euclidean3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Euclidean3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Euclidean3d>\", \"Vector_of_\" + \"Euclidean3d\", typeof(Vector<Euclidean3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Euclidean3d>[]\", \"Array_of_Vector_of_\" + \"Euclidean3d\", typeof(Vector<Euclidean3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Euclidean3d>>\", \"List_of_Vector_of_\" + \"Euclidean3d\", typeof(List<Vector<Euclidean3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Euclidean3d>\", \"Matrix_of_\" + \"Euclidean3d\", typeof(Matrix<Euclidean3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Euclidean3d>[]\", \"Array_of_Matrix_of_\" + \"Euclidean3d\", typeof(Matrix<Euclidean3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Euclidean3d>>\", \"List_of_Matrix_of_\" + \"Euclidean3d\", typeof(List<Matrix<Euclidean3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Euclidean3d>\", \"Volume_of_\" + \"Euclidean3d\", typeof(Volume<Euclidean3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Euclidean3d>[]\", \"Array_of_Volume_of_\" + \"Euclidean3d\", typeof(Volume<Euclidean3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Euclidean3d>>\", \"List_of_Volume_of_\" + \"Euclidean3d\", typeof(List<Volume<Euclidean3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Euclidean3d>\", \"Tensor_of_\" + \"Euclidean3d\", typeof(Tensor<Euclidean3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Euclidean3d>[]\", \"Array_of_Tensor_of_\" + \"Euclidean3d\", typeof(Tensor<Euclidean3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Euclidean3d>>\", \"List_of_Tensor_of_\" + \"Euclidean3d\", typeof(List<Tensor<Euclidean3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Rot2f\r\n\r\n                new TypeInfo(\"Rot2f\", typeof(Rot2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Rot2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Rot2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Rot2f>\", \"Vector_of_\" + \"Rot2f\", typeof(Vector<Rot2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Rot2f>[]\", \"Array_of_Vector_of_\" + \"Rot2f\", typeof(Vector<Rot2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Rot2f>>\", \"List_of_Vector_of_\" + \"Rot2f\", typeof(List<Vector<Rot2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Rot2f>\", \"Matrix_of_\" + \"Rot2f\", typeof(Matrix<Rot2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Rot2f>[]\", \"Array_of_Matrix_of_\" + \"Rot2f\", typeof(Matrix<Rot2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Rot2f>>\", \"List_of_Matrix_of_\" + \"Rot2f\", typeof(List<Matrix<Rot2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Rot2f>\", \"Volume_of_\" + \"Rot2f\", typeof(Volume<Rot2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Rot2f>[]\", \"Array_of_Volume_of_\" + \"Rot2f\", typeof(Volume<Rot2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Rot2f>>\", \"List_of_Volume_of_\" + \"Rot2f\", typeof(List<Volume<Rot2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Rot2f>\", \"Tensor_of_\" + \"Rot2f\", typeof(Tensor<Rot2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Rot2f>[]\", \"Array_of_Tensor_of_\" + \"Rot2f\", typeof(Tensor<Rot2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Rot2f>>\", \"List_of_Tensor_of_\" + \"Rot2f\", typeof(List<Tensor<Rot2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Rot2d\r\n\r\n                new TypeInfo(\"Rot2d\", typeof(Rot2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Rot2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Rot2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Rot2d>\", \"Vector_of_\" + \"Rot2d\", typeof(Vector<Rot2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Rot2d>[]\", \"Array_of_Vector_of_\" + \"Rot2d\", typeof(Vector<Rot2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Rot2d>>\", \"List_of_Vector_of_\" + \"Rot2d\", typeof(List<Vector<Rot2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Rot2d>\", \"Matrix_of_\" + \"Rot2d\", typeof(Matrix<Rot2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Rot2d>[]\", \"Array_of_Matrix_of_\" + \"Rot2d\", typeof(Matrix<Rot2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Rot2d>>\", \"List_of_Matrix_of_\" + \"Rot2d\", typeof(List<Matrix<Rot2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Rot2d>\", \"Volume_of_\" + \"Rot2d\", typeof(Volume<Rot2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Rot2d>[]\", \"Array_of_Volume_of_\" + \"Rot2d\", typeof(Volume<Rot2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Rot2d>>\", \"List_of_Volume_of_\" + \"Rot2d\", typeof(List<Volume<Rot2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Rot2d>\", \"Tensor_of_\" + \"Rot2d\", typeof(Tensor<Rot2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Rot2d>[]\", \"Array_of_Tensor_of_\" + \"Rot2d\", typeof(Tensor<Rot2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Rot2d>>\", \"List_of_Tensor_of_\" + \"Rot2d\", typeof(List<Tensor<Rot2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Rot3f\r\n\r\n                new TypeInfo(\"Rot3f\", typeof(Rot3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Rot3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Rot3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Rot3f>\", \"Vector_of_\" + \"Rot3f\", typeof(Vector<Rot3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Rot3f>[]\", \"Array_of_Vector_of_\" + \"Rot3f\", typeof(Vector<Rot3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Rot3f>>\", \"List_of_Vector_of_\" + \"Rot3f\", typeof(List<Vector<Rot3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Rot3f>\", \"Matrix_of_\" + \"Rot3f\", typeof(Matrix<Rot3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Rot3f>[]\", \"Array_of_Matrix_of_\" + \"Rot3f\", typeof(Matrix<Rot3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Rot3f>>\", \"List_of_Matrix_of_\" + \"Rot3f\", typeof(List<Matrix<Rot3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Rot3f>\", \"Volume_of_\" + \"Rot3f\", typeof(Volume<Rot3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Rot3f>[]\", \"Array_of_Volume_of_\" + \"Rot3f\", typeof(Volume<Rot3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Rot3f>>\", \"List_of_Volume_of_\" + \"Rot3f\", typeof(List<Volume<Rot3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Rot3f>\", \"Tensor_of_\" + \"Rot3f\", typeof(Tensor<Rot3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Rot3f>[]\", \"Array_of_Tensor_of_\" + \"Rot3f\", typeof(Tensor<Rot3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Rot3f>>\", \"List_of_Tensor_of_\" + \"Rot3f\", typeof(List<Tensor<Rot3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Rot3d\r\n\r\n                new TypeInfo(\"Rot3d\", typeof(Rot3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Rot3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Rot3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Rot3d>\", \"Vector_of_\" + \"Rot3d\", typeof(Vector<Rot3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Rot3d>[]\", \"Array_of_Vector_of_\" + \"Rot3d\", typeof(Vector<Rot3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Rot3d>>\", \"List_of_Vector_of_\" + \"Rot3d\", typeof(List<Vector<Rot3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Rot3d>\", \"Matrix_of_\" + \"Rot3d\", typeof(Matrix<Rot3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Rot3d>[]\", \"Array_of_Matrix_of_\" + \"Rot3d\", typeof(Matrix<Rot3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Rot3d>>\", \"List_of_Matrix_of_\" + \"Rot3d\", typeof(List<Matrix<Rot3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Rot3d>\", \"Volume_of_\" + \"Rot3d\", typeof(Volume<Rot3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Rot3d>[]\", \"Array_of_Volume_of_\" + \"Rot3d\", typeof(Volume<Rot3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Rot3d>>\", \"List_of_Volume_of_\" + \"Rot3d\", typeof(List<Volume<Rot3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Rot3d>\", \"Tensor_of_\" + \"Rot3d\", typeof(Tensor<Rot3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Rot3d>[]\", \"Array_of_Tensor_of_\" + \"Rot3d\", typeof(Tensor<Rot3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Rot3d>>\", \"List_of_Tensor_of_\" + \"Rot3d\", typeof(List<Tensor<Rot3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Scale3f\r\n\r\n                new TypeInfo(\"Scale3f\", typeof(Scale3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Scale3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Scale3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Scale3f>\", \"Vector_of_\" + \"Scale3f\", typeof(Vector<Scale3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Scale3f>[]\", \"Array_of_Vector_of_\" + \"Scale3f\", typeof(Vector<Scale3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Scale3f>>\", \"List_of_Vector_of_\" + \"Scale3f\", typeof(List<Vector<Scale3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Scale3f>\", \"Matrix_of_\" + \"Scale3f\", typeof(Matrix<Scale3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Scale3f>[]\", \"Array_of_Matrix_of_\" + \"Scale3f\", typeof(Matrix<Scale3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Scale3f>>\", \"List_of_Matrix_of_\" + \"Scale3f\", typeof(List<Matrix<Scale3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Scale3f>\", \"Volume_of_\" + \"Scale3f\", typeof(Volume<Scale3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Scale3f>[]\", \"Array_of_Volume_of_\" + \"Scale3f\", typeof(Volume<Scale3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Scale3f>>\", \"List_of_Volume_of_\" + \"Scale3f\", typeof(List<Volume<Scale3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Scale3f>\", \"Tensor_of_\" + \"Scale3f\", typeof(Tensor<Scale3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Scale3f>[]\", \"Array_of_Tensor_of_\" + \"Scale3f\", typeof(Tensor<Scale3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Scale3f>>\", \"List_of_Tensor_of_\" + \"Scale3f\", typeof(List<Tensor<Scale3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Scale3d\r\n\r\n                new TypeInfo(\"Scale3d\", typeof(Scale3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Scale3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Scale3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Scale3d>\", \"Vector_of_\" + \"Scale3d\", typeof(Vector<Scale3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Scale3d>[]\", \"Array_of_Vector_of_\" + \"Scale3d\", typeof(Vector<Scale3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Scale3d>>\", \"List_of_Vector_of_\" + \"Scale3d\", typeof(List<Vector<Scale3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Scale3d>\", \"Matrix_of_\" + \"Scale3d\", typeof(Matrix<Scale3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Scale3d>[]\", \"Array_of_Matrix_of_\" + \"Scale3d\", typeof(Matrix<Scale3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Scale3d>>\", \"List_of_Matrix_of_\" + \"Scale3d\", typeof(List<Matrix<Scale3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Scale3d>\", \"Volume_of_\" + \"Scale3d\", typeof(Volume<Scale3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Scale3d>[]\", \"Array_of_Volume_of_\" + \"Scale3d\", typeof(Volume<Scale3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Scale3d>>\", \"List_of_Volume_of_\" + \"Scale3d\", typeof(List<Volume<Scale3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Scale3d>\", \"Tensor_of_\" + \"Scale3d\", typeof(Tensor<Scale3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Scale3d>[]\", \"Array_of_Tensor_of_\" + \"Scale3d\", typeof(Tensor<Scale3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Scale3d>>\", \"List_of_Tensor_of_\" + \"Scale3d\", typeof(List<Tensor<Scale3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Shift3f\r\n\r\n                new TypeInfo(\"Shift3f\", typeof(Shift3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Shift3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Shift3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Shift3f>\", \"Vector_of_\" + \"Shift3f\", typeof(Vector<Shift3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Shift3f>[]\", \"Array_of_Vector_of_\" + \"Shift3f\", typeof(Vector<Shift3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Shift3f>>\", \"List_of_Vector_of_\" + \"Shift3f\", typeof(List<Vector<Shift3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Shift3f>\", \"Matrix_of_\" + \"Shift3f\", typeof(Matrix<Shift3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Shift3f>[]\", \"Array_of_Matrix_of_\" + \"Shift3f\", typeof(Matrix<Shift3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Shift3f>>\", \"List_of_Matrix_of_\" + \"Shift3f\", typeof(List<Matrix<Shift3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Shift3f>\", \"Volume_of_\" + \"Shift3f\", typeof(Volume<Shift3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Shift3f>[]\", \"Array_of_Volume_of_\" + \"Shift3f\", typeof(Volume<Shift3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Shift3f>>\", \"List_of_Volume_of_\" + \"Shift3f\", typeof(List<Volume<Shift3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Shift3f>\", \"Tensor_of_\" + \"Shift3f\", typeof(Tensor<Shift3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Shift3f>[]\", \"Array_of_Tensor_of_\" + \"Shift3f\", typeof(Tensor<Shift3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Shift3f>>\", \"List_of_Tensor_of_\" + \"Shift3f\", typeof(List<Tensor<Shift3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Shift3d\r\n\r\n                new TypeInfo(\"Shift3d\", typeof(Shift3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Shift3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Shift3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Shift3d>\", \"Vector_of_\" + \"Shift3d\", typeof(Vector<Shift3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Shift3d>[]\", \"Array_of_Vector_of_\" + \"Shift3d\", typeof(Vector<Shift3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Shift3d>>\", \"List_of_Vector_of_\" + \"Shift3d\", typeof(List<Vector<Shift3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Shift3d>\", \"Matrix_of_\" + \"Shift3d\", typeof(Matrix<Shift3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Shift3d>[]\", \"Array_of_Matrix_of_\" + \"Shift3d\", typeof(Matrix<Shift3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Shift3d>>\", \"List_of_Matrix_of_\" + \"Shift3d\", typeof(List<Matrix<Shift3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Shift3d>\", \"Volume_of_\" + \"Shift3d\", typeof(Volume<Shift3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Shift3d>[]\", \"Array_of_Volume_of_\" + \"Shift3d\", typeof(Volume<Shift3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Shift3d>>\", \"List_of_Volume_of_\" + \"Shift3d\", typeof(List<Volume<Shift3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Shift3d>\", \"Tensor_of_\" + \"Shift3d\", typeof(Tensor<Shift3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Shift3d>[]\", \"Array_of_Tensor_of_\" + \"Shift3d\", typeof(Tensor<Shift3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Shift3d>>\", \"List_of_Tensor_of_\" + \"Shift3d\", typeof(List<Tensor<Shift3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Trafo2f\r\n\r\n                new TypeInfo(\"Trafo2f\", typeof(Trafo2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Trafo2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Trafo2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Trafo2f>\", \"Vector_of_\" + \"Trafo2f\", typeof(Vector<Trafo2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Trafo2f>[]\", \"Array_of_Vector_of_\" + \"Trafo2f\", typeof(Vector<Trafo2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Trafo2f>>\", \"List_of_Vector_of_\" + \"Trafo2f\", typeof(List<Vector<Trafo2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Trafo2f>\", \"Matrix_of_\" + \"Trafo2f\", typeof(Matrix<Trafo2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Trafo2f>[]\", \"Array_of_Matrix_of_\" + \"Trafo2f\", typeof(Matrix<Trafo2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Trafo2f>>\", \"List_of_Matrix_of_\" + \"Trafo2f\", typeof(List<Matrix<Trafo2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Trafo2f>\", \"Volume_of_\" + \"Trafo2f\", typeof(Volume<Trafo2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Trafo2f>[]\", \"Array_of_Volume_of_\" + \"Trafo2f\", typeof(Volume<Trafo2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Trafo2f>>\", \"List_of_Volume_of_\" + \"Trafo2f\", typeof(List<Volume<Trafo2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Trafo2f>\", \"Tensor_of_\" + \"Trafo2f\", typeof(Tensor<Trafo2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Trafo2f>[]\", \"Array_of_Tensor_of_\" + \"Trafo2f\", typeof(Tensor<Trafo2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Trafo2f>>\", \"List_of_Tensor_of_\" + \"Trafo2f\", typeof(List<Tensor<Trafo2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Trafo2d\r\n\r\n                new TypeInfo(\"Trafo2d\", typeof(Trafo2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Trafo2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Trafo2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Trafo2d>\", \"Vector_of_\" + \"Trafo2d\", typeof(Vector<Trafo2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Trafo2d>[]\", \"Array_of_Vector_of_\" + \"Trafo2d\", typeof(Vector<Trafo2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Trafo2d>>\", \"List_of_Vector_of_\" + \"Trafo2d\", typeof(List<Vector<Trafo2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Trafo2d>\", \"Matrix_of_\" + \"Trafo2d\", typeof(Matrix<Trafo2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Trafo2d>[]\", \"Array_of_Matrix_of_\" + \"Trafo2d\", typeof(Matrix<Trafo2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Trafo2d>>\", \"List_of_Matrix_of_\" + \"Trafo2d\", typeof(List<Matrix<Trafo2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Trafo2d>\", \"Volume_of_\" + \"Trafo2d\", typeof(Volume<Trafo2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Trafo2d>[]\", \"Array_of_Volume_of_\" + \"Trafo2d\", typeof(Volume<Trafo2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Trafo2d>>\", \"List_of_Volume_of_\" + \"Trafo2d\", typeof(List<Volume<Trafo2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Trafo2d>\", \"Tensor_of_\" + \"Trafo2d\", typeof(Tensor<Trafo2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Trafo2d>[]\", \"Array_of_Tensor_of_\" + \"Trafo2d\", typeof(Tensor<Trafo2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Trafo2d>>\", \"List_of_Tensor_of_\" + \"Trafo2d\", typeof(List<Tensor<Trafo2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Trafo3f\r\n\r\n                new TypeInfo(\"Trafo3f\", typeof(Trafo3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Trafo3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Trafo3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Trafo3f>\", \"Vector_of_\" + \"Trafo3f\", typeof(Vector<Trafo3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Trafo3f>[]\", \"Array_of_Vector_of_\" + \"Trafo3f\", typeof(Vector<Trafo3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Trafo3f>>\", \"List_of_Vector_of_\" + \"Trafo3f\", typeof(List<Vector<Trafo3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Trafo3f>\", \"Matrix_of_\" + \"Trafo3f\", typeof(Matrix<Trafo3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Trafo3f>[]\", \"Array_of_Matrix_of_\" + \"Trafo3f\", typeof(Matrix<Trafo3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Trafo3f>>\", \"List_of_Matrix_of_\" + \"Trafo3f\", typeof(List<Matrix<Trafo3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Trafo3f>\", \"Volume_of_\" + \"Trafo3f\", typeof(Volume<Trafo3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Trafo3f>[]\", \"Array_of_Volume_of_\" + \"Trafo3f\", typeof(Volume<Trafo3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Trafo3f>>\", \"List_of_Volume_of_\" + \"Trafo3f\", typeof(List<Volume<Trafo3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Trafo3f>\", \"Tensor_of_\" + \"Trafo3f\", typeof(Tensor<Trafo3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Trafo3f>[]\", \"Array_of_Tensor_of_\" + \"Trafo3f\", typeof(Tensor<Trafo3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Trafo3f>>\", \"List_of_Tensor_of_\" + \"Trafo3f\", typeof(List<Tensor<Trafo3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Trafo3d\r\n\r\n                new TypeInfo(\"Trafo3d\", typeof(Trafo3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Trafo3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Trafo3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Trafo3d>\", \"Vector_of_\" + \"Trafo3d\", typeof(Vector<Trafo3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Trafo3d>[]\", \"Array_of_Vector_of_\" + \"Trafo3d\", typeof(Vector<Trafo3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Trafo3d>>\", \"List_of_Vector_of_\" + \"Trafo3d\", typeof(List<Vector<Trafo3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Trafo3d>\", \"Matrix_of_\" + \"Trafo3d\", typeof(Matrix<Trafo3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Trafo3d>[]\", \"Array_of_Matrix_of_\" + \"Trafo3d\", typeof(Matrix<Trafo3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Trafo3d>>\", \"List_of_Matrix_of_\" + \"Trafo3d\", typeof(List<Matrix<Trafo3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Trafo3d>\", \"Volume_of_\" + \"Trafo3d\", typeof(Volume<Trafo3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Trafo3d>[]\", \"Array_of_Volume_of_\" + \"Trafo3d\", typeof(Volume<Trafo3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Trafo3d>>\", \"List_of_Volume_of_\" + \"Trafo3d\", typeof(List<Volume<Trafo3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Trafo3d>\", \"Tensor_of_\" + \"Trafo3d\", typeof(Tensor<Trafo3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Trafo3d>[]\", \"Array_of_Tensor_of_\" + \"Trafo3d\", typeof(Tensor<Trafo3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Trafo3d>>\", \"List_of_Tensor_of_\" + \"Trafo3d\", typeof(List<Tensor<Trafo3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region bool\r\n\r\n                new TypeInfo(\"bool\", typeof(bool), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(bool[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<bool>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<bool>\", \"Vector_of_\" + \"bool\", typeof(Vector<bool>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<bool>[]\", \"Array_of_Vector_of_\" + \"bool\", typeof(Vector<bool>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<bool>>\", \"List_of_Vector_of_\" + \"bool\", typeof(List<Vector<bool>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<bool>\", \"Matrix_of_\" + \"bool\", typeof(Matrix<bool>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<bool>[]\", \"Array_of_Matrix_of_\" + \"bool\", typeof(Matrix<bool>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<bool>>\", \"List_of_Matrix_of_\" + \"bool\", typeof(List<Matrix<bool>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<bool>\", \"Volume_of_\" + \"bool\", typeof(Volume<bool>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<bool>[]\", \"Array_of_Volume_of_\" + \"bool\", typeof(Volume<bool>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<bool>>\", \"List_of_Volume_of_\" + \"bool\", typeof(List<Volume<bool>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<bool>\", \"Tensor_of_\" + \"bool\", typeof(Tensor<bool>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<bool>[]\", \"Array_of_Tensor_of_\" + \"bool\", typeof(Tensor<bool>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<bool>>\", \"List_of_Tensor_of_\" + \"bool\", typeof(List<Tensor<bool>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region char\r\n\r\n                new TypeInfo(\"char\", typeof(char), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(char[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<char>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<char>\", \"Vector_of_\" + \"char\", typeof(Vector<char>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<char>[]\", \"Array_of_Vector_of_\" + \"char\", typeof(Vector<char>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<char>>\", \"List_of_Vector_of_\" + \"char\", typeof(List<Vector<char>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<char>\", \"Matrix_of_\" + \"char\", typeof(Matrix<char>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<char>[]\", \"Array_of_Matrix_of_\" + \"char\", typeof(Matrix<char>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<char>>\", \"List_of_Matrix_of_\" + \"char\", typeof(List<Matrix<char>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<char>\", \"Volume_of_\" + \"char\", typeof(Volume<char>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<char>[]\", \"Array_of_Volume_of_\" + \"char\", typeof(Volume<char>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<char>>\", \"List_of_Volume_of_\" + \"char\", typeof(List<Volume<char>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<char>\", \"Tensor_of_\" + \"char\", typeof(Tensor<char>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<char>[]\", \"Array_of_Tensor_of_\" + \"char\", typeof(Tensor<char>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<char>>\", \"List_of_Tensor_of_\" + \"char\", typeof(List<Tensor<char>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region string\r\n\r\n                new TypeInfo(\"string\", typeof(string), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(string[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<string>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<string>\", \"Vector_of_\" + \"string\", typeof(Vector<string>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<string>[]\", \"Array_of_Vector_of_\" + \"string\", typeof(Vector<string>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<string>>\", \"List_of_Vector_of_\" + \"string\", typeof(List<Vector<string>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<string>\", \"Matrix_of_\" + \"string\", typeof(Matrix<string>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<string>[]\", \"Array_of_Matrix_of_\" + \"string\", typeof(Matrix<string>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<string>>\", \"List_of_Matrix_of_\" + \"string\", typeof(List<Matrix<string>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<string>\", \"Volume_of_\" + \"string\", typeof(Volume<string>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<string>[]\", \"Array_of_Volume_of_\" + \"string\", typeof(Volume<string>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<string>>\", \"List_of_Volume_of_\" + \"string\", typeof(List<Volume<string>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<string>\", \"Tensor_of_\" + \"string\", typeof(Tensor<string>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<string>[]\", \"Array_of_Tensor_of_\" + \"string\", typeof(Tensor<string>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<string>>\", \"List_of_Tensor_of_\" + \"string\", typeof(List<Tensor<string>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Type\r\n\r\n                new TypeInfo(\"Type\", typeof(Type), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Type[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Type>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Type>\", \"Vector_of_\" + \"Type\", typeof(Vector<Type>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Type>[]\", \"Array_of_Vector_of_\" + \"Type\", typeof(Vector<Type>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Type>>\", \"List_of_Vector_of_\" + \"Type\", typeof(List<Vector<Type>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Type>\", \"Matrix_of_\" + \"Type\", typeof(Matrix<Type>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Type>[]\", \"Array_of_Matrix_of_\" + \"Type\", typeof(Matrix<Type>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Type>>\", \"List_of_Matrix_of_\" + \"Type\", typeof(List<Matrix<Type>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Type>\", \"Volume_of_\" + \"Type\", typeof(Volume<Type>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Type>[]\", \"Array_of_Volume_of_\" + \"Type\", typeof(Volume<Type>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Type>>\", \"List_of_Volume_of_\" + \"Type\", typeof(List<Volume<Type>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Type>\", \"Tensor_of_\" + \"Type\", typeof(Tensor<Type>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Type>[]\", \"Array_of_Tensor_of_\" + \"Type\", typeof(Tensor<Type>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Type>>\", \"List_of_Tensor_of_\" + \"Type\", typeof(List<Tensor<Type>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Guid\r\n\r\n                new TypeInfo(\"Guid\", typeof(Guid), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Guid[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Guid>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Guid>\", \"Vector_of_\" + \"Guid\", typeof(Vector<Guid>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Guid>[]\", \"Array_of_Vector_of_\" + \"Guid\", typeof(Vector<Guid>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Guid>>\", \"List_of_Vector_of_\" + \"Guid\", typeof(List<Vector<Guid>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Guid>\", \"Matrix_of_\" + \"Guid\", typeof(Matrix<Guid>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Guid>[]\", \"Array_of_Matrix_of_\" + \"Guid\", typeof(Matrix<Guid>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Guid>>\", \"List_of_Matrix_of_\" + \"Guid\", typeof(List<Matrix<Guid>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Guid>\", \"Volume_of_\" + \"Guid\", typeof(Volume<Guid>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Guid>[]\", \"Array_of_Volume_of_\" + \"Guid\", typeof(Volume<Guid>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Guid>>\", \"List_of_Volume_of_\" + \"Guid\", typeof(List<Volume<Guid>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Guid>\", \"Tensor_of_\" + \"Guid\", typeof(Tensor<Guid>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Guid>[]\", \"Array_of_Tensor_of_\" + \"Guid\", typeof(Tensor<Guid>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Guid>>\", \"List_of_Tensor_of_\" + \"Guid\", typeof(List<Tensor<Guid>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Symbol\r\n\r\n                new TypeInfo(\"Symbol\", typeof(Symbol), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Symbol[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Symbol>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Symbol>\", \"Vector_of_\" + \"Symbol\", typeof(Vector<Symbol>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Symbol>[]\", \"Array_of_Vector_of_\" + \"Symbol\", typeof(Vector<Symbol>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Symbol>>\", \"List_of_Vector_of_\" + \"Symbol\", typeof(List<Vector<Symbol>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Symbol>\", \"Matrix_of_\" + \"Symbol\", typeof(Matrix<Symbol>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Symbol>[]\", \"Array_of_Matrix_of_\" + \"Symbol\", typeof(Matrix<Symbol>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Symbol>>\", \"List_of_Matrix_of_\" + \"Symbol\", typeof(List<Matrix<Symbol>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Symbol>\", \"Volume_of_\" + \"Symbol\", typeof(Volume<Symbol>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Symbol>[]\", \"Array_of_Volume_of_\" + \"Symbol\", typeof(Volume<Symbol>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Symbol>>\", \"List_of_Volume_of_\" + \"Symbol\", typeof(List<Volume<Symbol>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Symbol>\", \"Tensor_of_\" + \"Symbol\", typeof(Tensor<Symbol>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Symbol>[]\", \"Array_of_Tensor_of_\" + \"Symbol\", typeof(Tensor<Symbol>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Symbol>>\", \"List_of_Tensor_of_\" + \"Symbol\", typeof(List<Tensor<Symbol>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Circle2d\r\n\r\n                new TypeInfo(\"Circle2d\", typeof(Circle2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Circle2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Circle2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Circle2d>\", \"Vector_of_\" + \"Circle2d\", typeof(Vector<Circle2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Circle2d>[]\", \"Array_of_Vector_of_\" + \"Circle2d\", typeof(Vector<Circle2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Circle2d>>\", \"List_of_Vector_of_\" + \"Circle2d\", typeof(List<Vector<Circle2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Circle2d>\", \"Matrix_of_\" + \"Circle2d\", typeof(Matrix<Circle2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Circle2d>[]\", \"Array_of_Matrix_of_\" + \"Circle2d\", typeof(Matrix<Circle2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Circle2d>>\", \"List_of_Matrix_of_\" + \"Circle2d\", typeof(List<Matrix<Circle2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Circle2d>\", \"Volume_of_\" + \"Circle2d\", typeof(Volume<Circle2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Circle2d>[]\", \"Array_of_Volume_of_\" + \"Circle2d\", typeof(Volume<Circle2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Circle2d>>\", \"List_of_Volume_of_\" + \"Circle2d\", typeof(List<Volume<Circle2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Circle2d>\", \"Tensor_of_\" + \"Circle2d\", typeof(Tensor<Circle2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Circle2d>[]\", \"Array_of_Tensor_of_\" + \"Circle2d\", typeof(Tensor<Circle2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Circle2d>>\", \"List_of_Tensor_of_\" + \"Circle2d\", typeof(List<Tensor<Circle2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Line2d\r\n\r\n                new TypeInfo(\"Line2d\", typeof(Line2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Line2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Line2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Line2d>\", \"Vector_of_\" + \"Line2d\", typeof(Vector<Line2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Line2d>[]\", \"Array_of_Vector_of_\" + \"Line2d\", typeof(Vector<Line2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Line2d>>\", \"List_of_Vector_of_\" + \"Line2d\", typeof(List<Vector<Line2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Line2d>\", \"Matrix_of_\" + \"Line2d\", typeof(Matrix<Line2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Line2d>[]\", \"Array_of_Matrix_of_\" + \"Line2d\", typeof(Matrix<Line2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Line2d>>\", \"List_of_Matrix_of_\" + \"Line2d\", typeof(List<Matrix<Line2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Line2d>\", \"Volume_of_\" + \"Line2d\", typeof(Volume<Line2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Line2d>[]\", \"Array_of_Volume_of_\" + \"Line2d\", typeof(Volume<Line2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Line2d>>\", \"List_of_Volume_of_\" + \"Line2d\", typeof(List<Volume<Line2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Line2d>\", \"Tensor_of_\" + \"Line2d\", typeof(Tensor<Line2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Line2d>[]\", \"Array_of_Tensor_of_\" + \"Line2d\", typeof(Tensor<Line2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Line2d>>\", \"List_of_Tensor_of_\" + \"Line2d\", typeof(List<Tensor<Line2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Line3d\r\n\r\n                new TypeInfo(\"Line3d\", typeof(Line3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Line3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Line3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Line3d>\", \"Vector_of_\" + \"Line3d\", typeof(Vector<Line3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Line3d>[]\", \"Array_of_Vector_of_\" + \"Line3d\", typeof(Vector<Line3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Line3d>>\", \"List_of_Vector_of_\" + \"Line3d\", typeof(List<Vector<Line3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Line3d>\", \"Matrix_of_\" + \"Line3d\", typeof(Matrix<Line3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Line3d>[]\", \"Array_of_Matrix_of_\" + \"Line3d\", typeof(Matrix<Line3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Line3d>>\", \"List_of_Matrix_of_\" + \"Line3d\", typeof(List<Matrix<Line3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Line3d>\", \"Volume_of_\" + \"Line3d\", typeof(Volume<Line3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Line3d>[]\", \"Array_of_Volume_of_\" + \"Line3d\", typeof(Volume<Line3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Line3d>>\", \"List_of_Volume_of_\" + \"Line3d\", typeof(List<Volume<Line3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Line3d>\", \"Tensor_of_\" + \"Line3d\", typeof(Tensor<Line3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Line3d>[]\", \"Array_of_Tensor_of_\" + \"Line3d\", typeof(Tensor<Line3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Line3d>>\", \"List_of_Tensor_of_\" + \"Line3d\", typeof(List<Tensor<Line3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Plane2d\r\n\r\n                new TypeInfo(\"Plane2d\", typeof(Plane2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Plane2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Plane2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Plane2d>\", \"Vector_of_\" + \"Plane2d\", typeof(Vector<Plane2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Plane2d>[]\", \"Array_of_Vector_of_\" + \"Plane2d\", typeof(Vector<Plane2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Plane2d>>\", \"List_of_Vector_of_\" + \"Plane2d\", typeof(List<Vector<Plane2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Plane2d>\", \"Matrix_of_\" + \"Plane2d\", typeof(Matrix<Plane2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Plane2d>[]\", \"Array_of_Matrix_of_\" + \"Plane2d\", typeof(Matrix<Plane2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Plane2d>>\", \"List_of_Matrix_of_\" + \"Plane2d\", typeof(List<Matrix<Plane2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Plane2d>\", \"Volume_of_\" + \"Plane2d\", typeof(Volume<Plane2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Plane2d>[]\", \"Array_of_Volume_of_\" + \"Plane2d\", typeof(Volume<Plane2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Plane2d>>\", \"List_of_Volume_of_\" + \"Plane2d\", typeof(List<Volume<Plane2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Plane2d>\", \"Tensor_of_\" + \"Plane2d\", typeof(Tensor<Plane2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Plane2d>[]\", \"Array_of_Tensor_of_\" + \"Plane2d\", typeof(Tensor<Plane2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Plane2d>>\", \"List_of_Tensor_of_\" + \"Plane2d\", typeof(List<Tensor<Plane2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Plane3d\r\n\r\n                new TypeInfo(\"Plane3d\", typeof(Plane3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Plane3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Plane3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Plane3d>\", \"Vector_of_\" + \"Plane3d\", typeof(Vector<Plane3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Plane3d>[]\", \"Array_of_Vector_of_\" + \"Plane3d\", typeof(Vector<Plane3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Plane3d>>\", \"List_of_Vector_of_\" + \"Plane3d\", typeof(List<Vector<Plane3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Plane3d>\", \"Matrix_of_\" + \"Plane3d\", typeof(Matrix<Plane3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Plane3d>[]\", \"Array_of_Matrix_of_\" + \"Plane3d\", typeof(Matrix<Plane3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Plane3d>>\", \"List_of_Matrix_of_\" + \"Plane3d\", typeof(List<Matrix<Plane3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Plane3d>\", \"Volume_of_\" + \"Plane3d\", typeof(Volume<Plane3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Plane3d>[]\", \"Array_of_Volume_of_\" + \"Plane3d\", typeof(Volume<Plane3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Plane3d>>\", \"List_of_Volume_of_\" + \"Plane3d\", typeof(List<Volume<Plane3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Plane3d>\", \"Tensor_of_\" + \"Plane3d\", typeof(Tensor<Plane3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Plane3d>[]\", \"Array_of_Tensor_of_\" + \"Plane3d\", typeof(Tensor<Plane3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Plane3d>>\", \"List_of_Tensor_of_\" + \"Plane3d\", typeof(List<Tensor<Plane3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region PlaneWithPoint3d\r\n\r\n                new TypeInfo(\"PlaneWithPoint3d\", typeof(PlaneWithPoint3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(PlaneWithPoint3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<PlaneWithPoint3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<PlaneWithPoint3d>\", \"Vector_of_\" + \"PlaneWithPoint3d\", typeof(Vector<PlaneWithPoint3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<PlaneWithPoint3d>[]\", \"Array_of_Vector_of_\" + \"PlaneWithPoint3d\", typeof(Vector<PlaneWithPoint3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<PlaneWithPoint3d>>\", \"List_of_Vector_of_\" + \"PlaneWithPoint3d\", typeof(List<Vector<PlaneWithPoint3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<PlaneWithPoint3d>\", \"Matrix_of_\" + \"PlaneWithPoint3d\", typeof(Matrix<PlaneWithPoint3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<PlaneWithPoint3d>[]\", \"Array_of_Matrix_of_\" + \"PlaneWithPoint3d\", typeof(Matrix<PlaneWithPoint3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<PlaneWithPoint3d>>\", \"List_of_Matrix_of_\" + \"PlaneWithPoint3d\", typeof(List<Matrix<PlaneWithPoint3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<PlaneWithPoint3d>\", \"Volume_of_\" + \"PlaneWithPoint3d\", typeof(Volume<PlaneWithPoint3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<PlaneWithPoint3d>[]\", \"Array_of_Volume_of_\" + \"PlaneWithPoint3d\", typeof(Volume<PlaneWithPoint3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<PlaneWithPoint3d>>\", \"List_of_Volume_of_\" + \"PlaneWithPoint3d\", typeof(List<Volume<PlaneWithPoint3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<PlaneWithPoint3d>\", \"Tensor_of_\" + \"PlaneWithPoint3d\", typeof(Tensor<PlaneWithPoint3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<PlaneWithPoint3d>[]\", \"Array_of_Tensor_of_\" + \"PlaneWithPoint3d\", typeof(Tensor<PlaneWithPoint3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<PlaneWithPoint3d>>\", \"List_of_Tensor_of_\" + \"PlaneWithPoint3d\", typeof(List<Tensor<PlaneWithPoint3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Quad2d\r\n\r\n                new TypeInfo(\"Quad2d\", typeof(Quad2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Quad2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Quad2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Quad2d>\", \"Vector_of_\" + \"Quad2d\", typeof(Vector<Quad2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Quad2d>[]\", \"Array_of_Vector_of_\" + \"Quad2d\", typeof(Vector<Quad2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Quad2d>>\", \"List_of_Vector_of_\" + \"Quad2d\", typeof(List<Vector<Quad2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Quad2d>\", \"Matrix_of_\" + \"Quad2d\", typeof(Matrix<Quad2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Quad2d>[]\", \"Array_of_Matrix_of_\" + \"Quad2d\", typeof(Matrix<Quad2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Quad2d>>\", \"List_of_Matrix_of_\" + \"Quad2d\", typeof(List<Matrix<Quad2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Quad2d>\", \"Volume_of_\" + \"Quad2d\", typeof(Volume<Quad2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Quad2d>[]\", \"Array_of_Volume_of_\" + \"Quad2d\", typeof(Volume<Quad2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Quad2d>>\", \"List_of_Volume_of_\" + \"Quad2d\", typeof(List<Volume<Quad2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Quad2d>\", \"Tensor_of_\" + \"Quad2d\", typeof(Tensor<Quad2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Quad2d>[]\", \"Array_of_Tensor_of_\" + \"Quad2d\", typeof(Tensor<Quad2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Quad2d>>\", \"List_of_Tensor_of_\" + \"Quad2d\", typeof(List<Tensor<Quad2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Quad3d\r\n\r\n                new TypeInfo(\"Quad3d\", typeof(Quad3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Quad3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Quad3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Quad3d>\", \"Vector_of_\" + \"Quad3d\", typeof(Vector<Quad3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Quad3d>[]\", \"Array_of_Vector_of_\" + \"Quad3d\", typeof(Vector<Quad3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Quad3d>>\", \"List_of_Vector_of_\" + \"Quad3d\", typeof(List<Vector<Quad3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Quad3d>\", \"Matrix_of_\" + \"Quad3d\", typeof(Matrix<Quad3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Quad3d>[]\", \"Array_of_Matrix_of_\" + \"Quad3d\", typeof(Matrix<Quad3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Quad3d>>\", \"List_of_Matrix_of_\" + \"Quad3d\", typeof(List<Matrix<Quad3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Quad3d>\", \"Volume_of_\" + \"Quad3d\", typeof(Volume<Quad3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Quad3d>[]\", \"Array_of_Volume_of_\" + \"Quad3d\", typeof(Volume<Quad3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Quad3d>>\", \"List_of_Volume_of_\" + \"Quad3d\", typeof(List<Volume<Quad3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Quad3d>\", \"Tensor_of_\" + \"Quad3d\", typeof(Tensor<Quad3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Quad3d>[]\", \"Array_of_Tensor_of_\" + \"Quad3d\", typeof(Tensor<Quad3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Quad3d>>\", \"List_of_Tensor_of_\" + \"Quad3d\", typeof(List<Tensor<Quad3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Ray2d\r\n\r\n                new TypeInfo(\"Ray2d\", typeof(Ray2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Ray2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Ray2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Ray2d>\", \"Vector_of_\" + \"Ray2d\", typeof(Vector<Ray2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Ray2d>[]\", \"Array_of_Vector_of_\" + \"Ray2d\", typeof(Vector<Ray2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Ray2d>>\", \"List_of_Vector_of_\" + \"Ray2d\", typeof(List<Vector<Ray2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Ray2d>\", \"Matrix_of_\" + \"Ray2d\", typeof(Matrix<Ray2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Ray2d>[]\", \"Array_of_Matrix_of_\" + \"Ray2d\", typeof(Matrix<Ray2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Ray2d>>\", \"List_of_Matrix_of_\" + \"Ray2d\", typeof(List<Matrix<Ray2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Ray2d>\", \"Volume_of_\" + \"Ray2d\", typeof(Volume<Ray2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Ray2d>[]\", \"Array_of_Volume_of_\" + \"Ray2d\", typeof(Volume<Ray2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Ray2d>>\", \"List_of_Volume_of_\" + \"Ray2d\", typeof(List<Volume<Ray2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Ray2d>\", \"Tensor_of_\" + \"Ray2d\", typeof(Tensor<Ray2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Ray2d>[]\", \"Array_of_Tensor_of_\" + \"Ray2d\", typeof(Tensor<Ray2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Ray2d>>\", \"List_of_Tensor_of_\" + \"Ray2d\", typeof(List<Tensor<Ray2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Ray3d\r\n\r\n                new TypeInfo(\"Ray3d\", typeof(Ray3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Ray3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Ray3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Ray3d>\", \"Vector_of_\" + \"Ray3d\", typeof(Vector<Ray3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Ray3d>[]\", \"Array_of_Vector_of_\" + \"Ray3d\", typeof(Vector<Ray3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Ray3d>>\", \"List_of_Vector_of_\" + \"Ray3d\", typeof(List<Vector<Ray3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Ray3d>\", \"Matrix_of_\" + \"Ray3d\", typeof(Matrix<Ray3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Ray3d>[]\", \"Array_of_Matrix_of_\" + \"Ray3d\", typeof(Matrix<Ray3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Ray3d>>\", \"List_of_Matrix_of_\" + \"Ray3d\", typeof(List<Matrix<Ray3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Ray3d>\", \"Volume_of_\" + \"Ray3d\", typeof(Volume<Ray3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Ray3d>[]\", \"Array_of_Volume_of_\" + \"Ray3d\", typeof(Volume<Ray3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Ray3d>>\", \"List_of_Volume_of_\" + \"Ray3d\", typeof(List<Volume<Ray3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Ray3d>\", \"Tensor_of_\" + \"Ray3d\", typeof(Tensor<Ray3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Ray3d>[]\", \"Array_of_Tensor_of_\" + \"Ray3d\", typeof(Tensor<Ray3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Ray3d>>\", \"List_of_Tensor_of_\" + \"Ray3d\", typeof(List<Tensor<Ray3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Sphere3d\r\n\r\n                new TypeInfo(\"Sphere3d\", typeof(Sphere3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Sphere3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Sphere3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Sphere3d>\", \"Vector_of_\" + \"Sphere3d\", typeof(Vector<Sphere3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Sphere3d>[]\", \"Array_of_Vector_of_\" + \"Sphere3d\", typeof(Vector<Sphere3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Sphere3d>>\", \"List_of_Vector_of_\" + \"Sphere3d\", typeof(List<Vector<Sphere3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Sphere3d>\", \"Matrix_of_\" + \"Sphere3d\", typeof(Matrix<Sphere3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Sphere3d>[]\", \"Array_of_Matrix_of_\" + \"Sphere3d\", typeof(Matrix<Sphere3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Sphere3d>>\", \"List_of_Matrix_of_\" + \"Sphere3d\", typeof(List<Matrix<Sphere3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Sphere3d>\", \"Volume_of_\" + \"Sphere3d\", typeof(Volume<Sphere3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Sphere3d>[]\", \"Array_of_Volume_of_\" + \"Sphere3d\", typeof(Volume<Sphere3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Sphere3d>>\", \"List_of_Volume_of_\" + \"Sphere3d\", typeof(List<Volume<Sphere3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Sphere3d>\", \"Tensor_of_\" + \"Sphere3d\", typeof(Tensor<Sphere3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Sphere3d>[]\", \"Array_of_Tensor_of_\" + \"Sphere3d\", typeof(Tensor<Sphere3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Sphere3d>>\", \"List_of_Tensor_of_\" + \"Sphere3d\", typeof(List<Tensor<Sphere3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Triangle2d\r\n\r\n                new TypeInfo(\"Triangle2d\", typeof(Triangle2d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Triangle2d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Triangle2d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Triangle2d>\", \"Vector_of_\" + \"Triangle2d\", typeof(Vector<Triangle2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Triangle2d>[]\", \"Array_of_Vector_of_\" + \"Triangle2d\", typeof(Vector<Triangle2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Triangle2d>>\", \"List_of_Vector_of_\" + \"Triangle2d\", typeof(List<Vector<Triangle2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Triangle2d>\", \"Matrix_of_\" + \"Triangle2d\", typeof(Matrix<Triangle2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Triangle2d>[]\", \"Array_of_Matrix_of_\" + \"Triangle2d\", typeof(Matrix<Triangle2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Triangle2d>>\", \"List_of_Matrix_of_\" + \"Triangle2d\", typeof(List<Matrix<Triangle2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Triangle2d>\", \"Volume_of_\" + \"Triangle2d\", typeof(Volume<Triangle2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Triangle2d>[]\", \"Array_of_Volume_of_\" + \"Triangle2d\", typeof(Volume<Triangle2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Triangle2d>>\", \"List_of_Volume_of_\" + \"Triangle2d\", typeof(List<Volume<Triangle2d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Triangle2d>\", \"Tensor_of_\" + \"Triangle2d\", typeof(Tensor<Triangle2d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Triangle2d>[]\", \"Array_of_Tensor_of_\" + \"Triangle2d\", typeof(Tensor<Triangle2d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Triangle2d>>\", \"List_of_Tensor_of_\" + \"Triangle2d\", typeof(List<Tensor<Triangle2d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Triangle3d\r\n\r\n                new TypeInfo(\"Triangle3d\", typeof(Triangle3d), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Triangle3d[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Triangle3d>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Triangle3d>\", \"Vector_of_\" + \"Triangle3d\", typeof(Vector<Triangle3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Triangle3d>[]\", \"Array_of_Vector_of_\" + \"Triangle3d\", typeof(Vector<Triangle3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Triangle3d>>\", \"List_of_Vector_of_\" + \"Triangle3d\", typeof(List<Vector<Triangle3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Triangle3d>\", \"Matrix_of_\" + \"Triangle3d\", typeof(Matrix<Triangle3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Triangle3d>[]\", \"Array_of_Matrix_of_\" + \"Triangle3d\", typeof(Matrix<Triangle3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Triangle3d>>\", \"List_of_Matrix_of_\" + \"Triangle3d\", typeof(List<Matrix<Triangle3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Triangle3d>\", \"Volume_of_\" + \"Triangle3d\", typeof(Volume<Triangle3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Triangle3d>[]\", \"Array_of_Volume_of_\" + \"Triangle3d\", typeof(Volume<Triangle3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Triangle3d>>\", \"List_of_Volume_of_\" + \"Triangle3d\", typeof(List<Volume<Triangle3d>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Triangle3d>\", \"Tensor_of_\" + \"Triangle3d\", typeof(Tensor<Triangle3d>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Triangle3d>[]\", \"Array_of_Tensor_of_\" + \"Triangle3d\", typeof(Tensor<Triangle3d>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Triangle3d>>\", \"List_of_Tensor_of_\" + \"Triangle3d\", typeof(List<Tensor<Triangle3d>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Circle2f\r\n\r\n                new TypeInfo(\"Circle2f\", typeof(Circle2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Circle2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Circle2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Circle2f>\", \"Vector_of_\" + \"Circle2f\", typeof(Vector<Circle2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Circle2f>[]\", \"Array_of_Vector_of_\" + \"Circle2f\", typeof(Vector<Circle2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Circle2f>>\", \"List_of_Vector_of_\" + \"Circle2f\", typeof(List<Vector<Circle2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Circle2f>\", \"Matrix_of_\" + \"Circle2f\", typeof(Matrix<Circle2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Circle2f>[]\", \"Array_of_Matrix_of_\" + \"Circle2f\", typeof(Matrix<Circle2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Circle2f>>\", \"List_of_Matrix_of_\" + \"Circle2f\", typeof(List<Matrix<Circle2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Circle2f>\", \"Volume_of_\" + \"Circle2f\", typeof(Volume<Circle2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Circle2f>[]\", \"Array_of_Volume_of_\" + \"Circle2f\", typeof(Volume<Circle2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Circle2f>>\", \"List_of_Volume_of_\" + \"Circle2f\", typeof(List<Volume<Circle2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Circle2f>\", \"Tensor_of_\" + \"Circle2f\", typeof(Tensor<Circle2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Circle2f>[]\", \"Array_of_Tensor_of_\" + \"Circle2f\", typeof(Tensor<Circle2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Circle2f>>\", \"List_of_Tensor_of_\" + \"Circle2f\", typeof(List<Tensor<Circle2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Line2f\r\n\r\n                new TypeInfo(\"Line2f\", typeof(Line2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Line2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Line2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Line2f>\", \"Vector_of_\" + \"Line2f\", typeof(Vector<Line2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Line2f>[]\", \"Array_of_Vector_of_\" + \"Line2f\", typeof(Vector<Line2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Line2f>>\", \"List_of_Vector_of_\" + \"Line2f\", typeof(List<Vector<Line2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Line2f>\", \"Matrix_of_\" + \"Line2f\", typeof(Matrix<Line2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Line2f>[]\", \"Array_of_Matrix_of_\" + \"Line2f\", typeof(Matrix<Line2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Line2f>>\", \"List_of_Matrix_of_\" + \"Line2f\", typeof(List<Matrix<Line2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Line2f>\", \"Volume_of_\" + \"Line2f\", typeof(Volume<Line2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Line2f>[]\", \"Array_of_Volume_of_\" + \"Line2f\", typeof(Volume<Line2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Line2f>>\", \"List_of_Volume_of_\" + \"Line2f\", typeof(List<Volume<Line2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Line2f>\", \"Tensor_of_\" + \"Line2f\", typeof(Tensor<Line2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Line2f>[]\", \"Array_of_Tensor_of_\" + \"Line2f\", typeof(Tensor<Line2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Line2f>>\", \"List_of_Tensor_of_\" + \"Line2f\", typeof(List<Tensor<Line2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Line3f\r\n\r\n                new TypeInfo(\"Line3f\", typeof(Line3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Line3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Line3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Line3f>\", \"Vector_of_\" + \"Line3f\", typeof(Vector<Line3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Line3f>[]\", \"Array_of_Vector_of_\" + \"Line3f\", typeof(Vector<Line3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Line3f>>\", \"List_of_Vector_of_\" + \"Line3f\", typeof(List<Vector<Line3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Line3f>\", \"Matrix_of_\" + \"Line3f\", typeof(Matrix<Line3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Line3f>[]\", \"Array_of_Matrix_of_\" + \"Line3f\", typeof(Matrix<Line3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Line3f>>\", \"List_of_Matrix_of_\" + \"Line3f\", typeof(List<Matrix<Line3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Line3f>\", \"Volume_of_\" + \"Line3f\", typeof(Volume<Line3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Line3f>[]\", \"Array_of_Volume_of_\" + \"Line3f\", typeof(Volume<Line3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Line3f>>\", \"List_of_Volume_of_\" + \"Line3f\", typeof(List<Volume<Line3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Line3f>\", \"Tensor_of_\" + \"Line3f\", typeof(Tensor<Line3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Line3f>[]\", \"Array_of_Tensor_of_\" + \"Line3f\", typeof(Tensor<Line3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Line3f>>\", \"List_of_Tensor_of_\" + \"Line3f\", typeof(List<Tensor<Line3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Plane2f\r\n\r\n                new TypeInfo(\"Plane2f\", typeof(Plane2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Plane2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Plane2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Plane2f>\", \"Vector_of_\" + \"Plane2f\", typeof(Vector<Plane2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Plane2f>[]\", \"Array_of_Vector_of_\" + \"Plane2f\", typeof(Vector<Plane2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Plane2f>>\", \"List_of_Vector_of_\" + \"Plane2f\", typeof(List<Vector<Plane2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Plane2f>\", \"Matrix_of_\" + \"Plane2f\", typeof(Matrix<Plane2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Plane2f>[]\", \"Array_of_Matrix_of_\" + \"Plane2f\", typeof(Matrix<Plane2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Plane2f>>\", \"List_of_Matrix_of_\" + \"Plane2f\", typeof(List<Matrix<Plane2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Plane2f>\", \"Volume_of_\" + \"Plane2f\", typeof(Volume<Plane2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Plane2f>[]\", \"Array_of_Volume_of_\" + \"Plane2f\", typeof(Volume<Plane2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Plane2f>>\", \"List_of_Volume_of_\" + \"Plane2f\", typeof(List<Volume<Plane2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Plane2f>\", \"Tensor_of_\" + \"Plane2f\", typeof(Tensor<Plane2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Plane2f>[]\", \"Array_of_Tensor_of_\" + \"Plane2f\", typeof(Tensor<Plane2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Plane2f>>\", \"List_of_Tensor_of_\" + \"Plane2f\", typeof(List<Tensor<Plane2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Plane3f\r\n\r\n                new TypeInfo(\"Plane3f\", typeof(Plane3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Plane3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Plane3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Plane3f>\", \"Vector_of_\" + \"Plane3f\", typeof(Vector<Plane3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Plane3f>[]\", \"Array_of_Vector_of_\" + \"Plane3f\", typeof(Vector<Plane3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Plane3f>>\", \"List_of_Vector_of_\" + \"Plane3f\", typeof(List<Vector<Plane3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Plane3f>\", \"Matrix_of_\" + \"Plane3f\", typeof(Matrix<Plane3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Plane3f>[]\", \"Array_of_Matrix_of_\" + \"Plane3f\", typeof(Matrix<Plane3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Plane3f>>\", \"List_of_Matrix_of_\" + \"Plane3f\", typeof(List<Matrix<Plane3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Plane3f>\", \"Volume_of_\" + \"Plane3f\", typeof(Volume<Plane3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Plane3f>[]\", \"Array_of_Volume_of_\" + \"Plane3f\", typeof(Volume<Plane3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Plane3f>>\", \"List_of_Volume_of_\" + \"Plane3f\", typeof(List<Volume<Plane3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Plane3f>\", \"Tensor_of_\" + \"Plane3f\", typeof(Tensor<Plane3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Plane3f>[]\", \"Array_of_Tensor_of_\" + \"Plane3f\", typeof(Tensor<Plane3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Plane3f>>\", \"List_of_Tensor_of_\" + \"Plane3f\", typeof(List<Tensor<Plane3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region PlaneWithPoint3f\r\n\r\n                new TypeInfo(\"PlaneWithPoint3f\", typeof(PlaneWithPoint3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(PlaneWithPoint3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<PlaneWithPoint3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<PlaneWithPoint3f>\", \"Vector_of_\" + \"PlaneWithPoint3f\", typeof(Vector<PlaneWithPoint3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<PlaneWithPoint3f>[]\", \"Array_of_Vector_of_\" + \"PlaneWithPoint3f\", typeof(Vector<PlaneWithPoint3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<PlaneWithPoint3f>>\", \"List_of_Vector_of_\" + \"PlaneWithPoint3f\", typeof(List<Vector<PlaneWithPoint3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<PlaneWithPoint3f>\", \"Matrix_of_\" + \"PlaneWithPoint3f\", typeof(Matrix<PlaneWithPoint3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<PlaneWithPoint3f>[]\", \"Array_of_Matrix_of_\" + \"PlaneWithPoint3f\", typeof(Matrix<PlaneWithPoint3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<PlaneWithPoint3f>>\", \"List_of_Matrix_of_\" + \"PlaneWithPoint3f\", typeof(List<Matrix<PlaneWithPoint3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<PlaneWithPoint3f>\", \"Volume_of_\" + \"PlaneWithPoint3f\", typeof(Volume<PlaneWithPoint3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<PlaneWithPoint3f>[]\", \"Array_of_Volume_of_\" + \"PlaneWithPoint3f\", typeof(Volume<PlaneWithPoint3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<PlaneWithPoint3f>>\", \"List_of_Volume_of_\" + \"PlaneWithPoint3f\", typeof(List<Volume<PlaneWithPoint3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<PlaneWithPoint3f>\", \"Tensor_of_\" + \"PlaneWithPoint3f\", typeof(Tensor<PlaneWithPoint3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<PlaneWithPoint3f>[]\", \"Array_of_Tensor_of_\" + \"PlaneWithPoint3f\", typeof(Tensor<PlaneWithPoint3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<PlaneWithPoint3f>>\", \"List_of_Tensor_of_\" + \"PlaneWithPoint3f\", typeof(List<Tensor<PlaneWithPoint3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Quad2f\r\n\r\n                new TypeInfo(\"Quad2f\", typeof(Quad2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Quad2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Quad2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Quad2f>\", \"Vector_of_\" + \"Quad2f\", typeof(Vector<Quad2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Quad2f>[]\", \"Array_of_Vector_of_\" + \"Quad2f\", typeof(Vector<Quad2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Quad2f>>\", \"List_of_Vector_of_\" + \"Quad2f\", typeof(List<Vector<Quad2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Quad2f>\", \"Matrix_of_\" + \"Quad2f\", typeof(Matrix<Quad2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Quad2f>[]\", \"Array_of_Matrix_of_\" + \"Quad2f\", typeof(Matrix<Quad2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Quad2f>>\", \"List_of_Matrix_of_\" + \"Quad2f\", typeof(List<Matrix<Quad2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Quad2f>\", \"Volume_of_\" + \"Quad2f\", typeof(Volume<Quad2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Quad2f>[]\", \"Array_of_Volume_of_\" + \"Quad2f\", typeof(Volume<Quad2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Quad2f>>\", \"List_of_Volume_of_\" + \"Quad2f\", typeof(List<Volume<Quad2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Quad2f>\", \"Tensor_of_\" + \"Quad2f\", typeof(Tensor<Quad2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Quad2f>[]\", \"Array_of_Tensor_of_\" + \"Quad2f\", typeof(Tensor<Quad2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Quad2f>>\", \"List_of_Tensor_of_\" + \"Quad2f\", typeof(List<Tensor<Quad2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Quad3f\r\n\r\n                new TypeInfo(\"Quad3f\", typeof(Quad3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Quad3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Quad3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Quad3f>\", \"Vector_of_\" + \"Quad3f\", typeof(Vector<Quad3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Quad3f>[]\", \"Array_of_Vector_of_\" + \"Quad3f\", typeof(Vector<Quad3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Quad3f>>\", \"List_of_Vector_of_\" + \"Quad3f\", typeof(List<Vector<Quad3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Quad3f>\", \"Matrix_of_\" + \"Quad3f\", typeof(Matrix<Quad3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Quad3f>[]\", \"Array_of_Matrix_of_\" + \"Quad3f\", typeof(Matrix<Quad3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Quad3f>>\", \"List_of_Matrix_of_\" + \"Quad3f\", typeof(List<Matrix<Quad3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Quad3f>\", \"Volume_of_\" + \"Quad3f\", typeof(Volume<Quad3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Quad3f>[]\", \"Array_of_Volume_of_\" + \"Quad3f\", typeof(Volume<Quad3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Quad3f>>\", \"List_of_Volume_of_\" + \"Quad3f\", typeof(List<Volume<Quad3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Quad3f>\", \"Tensor_of_\" + \"Quad3f\", typeof(Tensor<Quad3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Quad3f>[]\", \"Array_of_Tensor_of_\" + \"Quad3f\", typeof(Tensor<Quad3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Quad3f>>\", \"List_of_Tensor_of_\" + \"Quad3f\", typeof(List<Tensor<Quad3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Ray2f\r\n\r\n                new TypeInfo(\"Ray2f\", typeof(Ray2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Ray2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Ray2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Ray2f>\", \"Vector_of_\" + \"Ray2f\", typeof(Vector<Ray2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Ray2f>[]\", \"Array_of_Vector_of_\" + \"Ray2f\", typeof(Vector<Ray2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Ray2f>>\", \"List_of_Vector_of_\" + \"Ray2f\", typeof(List<Vector<Ray2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Ray2f>\", \"Matrix_of_\" + \"Ray2f\", typeof(Matrix<Ray2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Ray2f>[]\", \"Array_of_Matrix_of_\" + \"Ray2f\", typeof(Matrix<Ray2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Ray2f>>\", \"List_of_Matrix_of_\" + \"Ray2f\", typeof(List<Matrix<Ray2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Ray2f>\", \"Volume_of_\" + \"Ray2f\", typeof(Volume<Ray2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Ray2f>[]\", \"Array_of_Volume_of_\" + \"Ray2f\", typeof(Volume<Ray2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Ray2f>>\", \"List_of_Volume_of_\" + \"Ray2f\", typeof(List<Volume<Ray2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Ray2f>\", \"Tensor_of_\" + \"Ray2f\", typeof(Tensor<Ray2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Ray2f>[]\", \"Array_of_Tensor_of_\" + \"Ray2f\", typeof(Tensor<Ray2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Ray2f>>\", \"List_of_Tensor_of_\" + \"Ray2f\", typeof(List<Tensor<Ray2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Ray3f\r\n\r\n                new TypeInfo(\"Ray3f\", typeof(Ray3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Ray3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Ray3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Ray3f>\", \"Vector_of_\" + \"Ray3f\", typeof(Vector<Ray3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Ray3f>[]\", \"Array_of_Vector_of_\" + \"Ray3f\", typeof(Vector<Ray3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Ray3f>>\", \"List_of_Vector_of_\" + \"Ray3f\", typeof(List<Vector<Ray3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Ray3f>\", \"Matrix_of_\" + \"Ray3f\", typeof(Matrix<Ray3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Ray3f>[]\", \"Array_of_Matrix_of_\" + \"Ray3f\", typeof(Matrix<Ray3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Ray3f>>\", \"List_of_Matrix_of_\" + \"Ray3f\", typeof(List<Matrix<Ray3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Ray3f>\", \"Volume_of_\" + \"Ray3f\", typeof(Volume<Ray3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Ray3f>[]\", \"Array_of_Volume_of_\" + \"Ray3f\", typeof(Volume<Ray3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Ray3f>>\", \"List_of_Volume_of_\" + \"Ray3f\", typeof(List<Volume<Ray3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Ray3f>\", \"Tensor_of_\" + \"Ray3f\", typeof(Tensor<Ray3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Ray3f>[]\", \"Array_of_Tensor_of_\" + \"Ray3f\", typeof(Tensor<Ray3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Ray3f>>\", \"List_of_Tensor_of_\" + \"Ray3f\", typeof(List<Tensor<Ray3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Sphere3f\r\n\r\n                new TypeInfo(\"Sphere3f\", typeof(Sphere3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Sphere3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Sphere3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Sphere3f>\", \"Vector_of_\" + \"Sphere3f\", typeof(Vector<Sphere3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Sphere3f>[]\", \"Array_of_Vector_of_\" + \"Sphere3f\", typeof(Vector<Sphere3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Sphere3f>>\", \"List_of_Vector_of_\" + \"Sphere3f\", typeof(List<Vector<Sphere3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Sphere3f>\", \"Matrix_of_\" + \"Sphere3f\", typeof(Matrix<Sphere3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Sphere3f>[]\", \"Array_of_Matrix_of_\" + \"Sphere3f\", typeof(Matrix<Sphere3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Sphere3f>>\", \"List_of_Matrix_of_\" + \"Sphere3f\", typeof(List<Matrix<Sphere3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Sphere3f>\", \"Volume_of_\" + \"Sphere3f\", typeof(Volume<Sphere3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Sphere3f>[]\", \"Array_of_Volume_of_\" + \"Sphere3f\", typeof(Volume<Sphere3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Sphere3f>>\", \"List_of_Volume_of_\" + \"Sphere3f\", typeof(List<Volume<Sphere3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Sphere3f>\", \"Tensor_of_\" + \"Sphere3f\", typeof(Tensor<Sphere3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Sphere3f>[]\", \"Array_of_Tensor_of_\" + \"Sphere3f\", typeof(Tensor<Sphere3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Sphere3f>>\", \"List_of_Tensor_of_\" + \"Sphere3f\", typeof(List<Tensor<Sphere3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Triangle2f\r\n\r\n                new TypeInfo(\"Triangle2f\", typeof(Triangle2f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Triangle2f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Triangle2f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Triangle2f>\", \"Vector_of_\" + \"Triangle2f\", typeof(Vector<Triangle2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Triangle2f>[]\", \"Array_of_Vector_of_\" + \"Triangle2f\", typeof(Vector<Triangle2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Triangle2f>>\", \"List_of_Vector_of_\" + \"Triangle2f\", typeof(List<Vector<Triangle2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Triangle2f>\", \"Matrix_of_\" + \"Triangle2f\", typeof(Matrix<Triangle2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Triangle2f>[]\", \"Array_of_Matrix_of_\" + \"Triangle2f\", typeof(Matrix<Triangle2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Triangle2f>>\", \"List_of_Matrix_of_\" + \"Triangle2f\", typeof(List<Matrix<Triangle2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Triangle2f>\", \"Volume_of_\" + \"Triangle2f\", typeof(Volume<Triangle2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Triangle2f>[]\", \"Array_of_Volume_of_\" + \"Triangle2f\", typeof(Volume<Triangle2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Triangle2f>>\", \"List_of_Volume_of_\" + \"Triangle2f\", typeof(List<Volume<Triangle2f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Triangle2f>\", \"Tensor_of_\" + \"Triangle2f\", typeof(Tensor<Triangle2f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Triangle2f>[]\", \"Array_of_Tensor_of_\" + \"Triangle2f\", typeof(Tensor<Triangle2f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Triangle2f>>\", \"List_of_Tensor_of_\" + \"Triangle2f\", typeof(List<Tensor<Triangle2f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n                #region Triangle3f\r\n\r\n                new TypeInfo(\"Triangle3f\", typeof(Triangle3f), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(Triangle3f[]), TypeInfo.Option.None),\r\n                new TypeInfo(typeof(List<Triangle3f>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Vector<Triangle3f>\", \"Vector_of_\" + \"Triangle3f\", typeof(Vector<Triangle3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Vector<Triangle3f>[]\", \"Array_of_Vector_of_\" + \"Triangle3f\", typeof(Vector<Triangle3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Vector<Triangle3f>>\", \"List_of_Vector_of_\" + \"Triangle3f\", typeof(List<Vector<Triangle3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Matrix<Triangle3f>\", \"Matrix_of_\" + \"Triangle3f\", typeof(Matrix<Triangle3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Matrix<Triangle3f>[]\", \"Array_of_Matrix_of_\" + \"Triangle3f\", typeof(Matrix<Triangle3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Matrix<Triangle3f>>\", \"List_of_Matrix_of_\" + \"Triangle3f\", typeof(List<Matrix<Triangle3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Volume<Triangle3f>\", \"Volume_of_\" + \"Triangle3f\", typeof(Volume<Triangle3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Volume<Triangle3f>[]\", \"Array_of_Volume_of_\" + \"Triangle3f\", typeof(Volume<Triangle3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Volume<Triangle3f>>\", \"List_of_Volume_of_\" + \"Triangle3f\", typeof(List<Volume<Triangle3f>>), TypeInfo.Option.None),\r\n\r\n                new TypeInfo(\"Tensor<Triangle3f>\", \"Tensor_of_\" + \"Triangle3f\", typeof(Tensor<Triangle3f>), TypeInfo.Option.None),\r\n                new TypeInfo(\"Tensor<Triangle3f>[]\", \"Array_of_Tensor_of_\" + \"Triangle3f\", typeof(Tensor<Triangle3f>[]), TypeInfo.Option.None),\r\n                new TypeInfo(\"List<Tensor<Triangle3f>>\", \"List_of_Tensor_of_\" + \"Triangle3f\", typeof(List<Tensor<Triangle3f>>), TypeInfo.Option.None),\r\n\r\n                #endregion\r\n\r\n\r\n                new TypeInfo(\"HashSet<string>\", \"HashSet_of_string\", typeof(HashSet<string>), TypeInfo.Option.None),\r\n            };\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/TypeCoder_template.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.IO;\n\nnamespace Aardvark.Base.Coder\n{\n\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var directlyCodeableTypes = Meta.DirectlyCodeableTypes.Map(t => t.Name);\n    //# var specialSimpleTypes = new[] { \"bool\", \"char\", \"string\", \"Type\", \"Guid\", \"Symbol\" };\n    //# var geometryTypes = Meta.GeometryTypes.Map(t => t.Name);\n    //# var allTypes = directlyCodeableTypes.Concat(specialSimpleTypes).Concat(geometryTypes);\n\n    public static partial class TypeCoder\n    {\n        internal static Dictionary<Type, Action<IWritingCoder, object>> TypeWriterMap =\n                                    new Dictionary<Type, Action<IWritingCoder, object>>\n        {\n            //# allTypes.ForEach((t, i) => {\n            #region __t__\n\n            //# var n = Meta.GetXmlTypeName(t);\n            { typeof(__t__), (c,o) => { var v = (__t__)o; c.Code__n__(ref v); } },\n            //# var na = Meta.GetXmlTypeName(t + \"[]\");\n            { typeof(__t__[]), (c,o) => { var v = (__t__[])o; c.Code__na__(ref v); } },\n            //# var ln = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n            { typeof(List<__t__>), (c,o) => { var v = (List<__t__>)o; c.Code__ln__(ref v); } },\n\n            //# var vet = \"Vector<\" + t + \">\";\n            //# var ven = Meta.GetXmlTypeName(vet);\n            { typeof(Vector<__t__>), (c,o) => { var v = (Vector<__t__>)o; c.Code__ven__(ref v); } },\n            //# var vena = Meta.GetXmlTypeName(vet + \"[]\");\n            { typeof(Vector<__t__>[]), (c,o) => { var v = (Vector<__t__>[])o; c.Code__vena__(ref v); } },\n            //# var lven = Meta.GetXmlTypeName(\"List<\" + vet + \">\");\n            { typeof(List<Vector<__t__>>), (c,o) => { var v = (List<Vector<__t__>>)o; c.Code__lven__(ref v); } },\n\n            //# var mat = \"Matrix<\" + t + \">\";\n            //# var man = Meta.GetXmlTypeName(mat);\n            { typeof(Matrix<__t__>), (c,o) => { var v = (Matrix<__t__>)o; c.Code__man__(ref v); } },\n            //# var mana = Meta.GetXmlTypeName(mat + \"[]\");\n            { typeof(Matrix<__t__>[]), (c,o) => { var v = (Matrix<__t__>[])o; c.Code__mana__(ref v); } },\n            //# var lman = Meta.GetXmlTypeName(\"List<\" + mat + \">\");\n            { typeof(List<Matrix<__t__>>), (c,o) => { var v = (List<Matrix<__t__>>)o; c.Code__lman__(ref v); } },\n\n            //# var vot = \"Volume<\" + t + \">\";\n            //# var von = Meta.GetXmlTypeName(vot);\n            { typeof(Volume<__t__>), (c,o) => { var v = (Volume<__t__>)o; c.Code__von__(ref v); } },\n            //# var vona = Meta.GetXmlTypeName(vot + \"[]\");\n            { typeof(Volume<__t__>[]), (c,o) => { var v = (Volume<__t__>[])o; c.Code__vona__(ref v); } },\n            //# var lvon = Meta.GetXmlTypeName(\"List<\" + vot + \">\");\n            { typeof(List<Volume<__t__>>), (c,o) => { var v = (List<Volume<__t__>>)o; c.Code__lvon__(ref v); } },\n\n            //# var tet = \"Tensor<\" + t + \">\";\n            //# var ten = Meta.GetXmlTypeName(tet);\n            { typeof(Tensor<__t__>), (c,o) => { var v = (Tensor<__t__>)o; c.Code__ten__(ref v); } },\n            //# var tena = Meta.GetXmlTypeName(tet + \"[]\");\n            { typeof(Tensor<__t__>[]), (c,o) => { var v = (Tensor<__t__>[])o; c.Code__tena__(ref v); } },\n            //# var lten = Meta.GetXmlTypeName(\"List<\" + tet + \">\");\n            { typeof(List<Tensor<__t__>>), (c,o) => { var v = (List<Tensor<__t__>>)o; c.Code__lten__(ref v); } },\n\n            #endregion\n\n            //# });\n            #region Multi-Dimensional Arrays\n\n            //# directlyCodeableTypes.ForEach((t, i) => {\n            //# var n2d = Meta.GetXmlTypeName(t + \"[,]\");\n            { typeof(__t__[,]), (c,o) => { var v = (__t__[,])o; c.Code__n2d__(ref v); } },\n            //# var n3d = Meta.GetXmlTypeName(t + \"[,,]\");\n            { typeof(__t__[, ,]), (c,o) => { var v = (__t__[, ,])o; c.Code__n3d__(ref v); } },\n            //# });\n\n            #endregion\n\n            #region Jagged Multi-Dimensional Arrays\n\n            //# directlyCodeableTypes.ForEach((t, i) => {\n            //# var n2d = Meta.GetXmlTypeName(t + \"[][]\");\n            { typeof(__t__[][]), (c,o) => { var v = (__t__[][])o; c.Code__n2d__(ref v); } },\n            //# var n3d = Meta.GetXmlTypeName(t + \"[][][]\");\n            { typeof(__t__[][][]), (c,o) => { var v = (__t__[][][])o; c.Code__n3d__(ref v); } },\n            //# });\n\n            #endregion\n\n            #region Other Types\n\n            { typeof(IntSet), (c,o) => { var v = (IntSet)o; c.CodeIntSet(ref v); } },\n            { typeof(SymbolSet), (c,o) => { var v = (SymbolSet)o; c.CodeSymbolSet(ref v); } },\n\n\n            { typeof(HashSet<string>), (c, o) => { var v = (HashSet<string>)o; c.CodeHashSet_of_T_(ref v); } },\n\n            #endregion\n        };\n\n        internal static Dictionary<Type, Func<IReadingCoder, object>> TypeReaderMap =\n                                new Dictionary<Type, Func<IReadingCoder, object>>\n        {\n            //# allTypes.ForEach((t, i) => {\n            #region __t__\n\n            //# var n = Meta.GetXmlTypeName(t);\n            { typeof(__t__), c => { var v = default(__t__); c.Code__n__(ref v); return v; } },\n            //# var na = Meta.GetXmlTypeName(t + \"[]\");\n            { typeof(__t__[]), c => { var v = default(__t__[]); c.Code__na__(ref v); return v; } },\n            //# var ln = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n            { typeof(List<__t__>), c => { var v = default(List<__t__>); c.Code__ln__(ref v); return v; } },\n\n            //# var vet = \"Vector<\" + t + \">\";\n            //# var ven = Meta.GetXmlTypeName(vet);\n            { typeof(Vector<__t__>), c => { var v = default(Vector<__t__>); c.Code__ven__(ref v); return v; } },\n            //# var vena = Meta.GetXmlTypeName(vet + \"[]\");\n            { typeof(Vector<__t__>[]), c => { var v = default(Vector<__t__>[]); c.Code__vena__(ref v); return v; } },\n            //# var lven = Meta.GetXmlTypeName(\"List<\" + vet + \">\");\n            { typeof(List<Vector<__t__>>), c => { var v = default(List<Vector<__t__>>); c.Code__lven__(ref v); return v; } },\n\n            //# var mat = \"Matrix<\" + t + \">\";\n            //# var man = Meta.GetXmlTypeName(mat);\n            { typeof(Matrix<__t__>), c => { var v = default(Matrix<__t__>); c.Code__man__(ref v); return v; } },\n            //# var mana = Meta.GetXmlTypeName(mat + \"[]\");\n            { typeof(Matrix<__t__>[]), c => { var v = default(Matrix<__t__>[]); c.Code__mana__(ref v); return v; } },\n            //# var lman = Meta.GetXmlTypeName(\"List<\" + mat + \">\");\n            { typeof(List<Matrix<__t__>>), c => { var v = default(List<Matrix<__t__>>); c.Code__lman__(ref v); return v; } },\n\n            //# var vot = \"Volume<\" + t + \">\";\n            //# var von = Meta.GetXmlTypeName(vot);\n            { typeof(Volume<__t__>), c => { var v = default(Volume<__t__>); c.Code__von__(ref v); return v; } },\n            //# var vona = Meta.GetXmlTypeName(vot + \"[]\");\n            { typeof(Volume<__t__>[]), c => { var v = default(Volume<__t__>[]); c.Code__vona__(ref v); return v; } },\n            //# var lvon = Meta.GetXmlTypeName(\"List<\" + vot + \">\");\n            { typeof(List<Volume<__t__>>), c => { var v = default(List<Volume<__t__>>); c.Code__lvon__(ref v); return v; } },\n\n            //# var tet = \"Tensor<\" + t + \">\";\n            //# var ten = Meta.GetXmlTypeName(tet);\n            { typeof(Tensor<__t__>), c => { var v = default(Tensor<__t__>); c.Code__ten__(ref v); return v; } },\n            //# var tena = Meta.GetXmlTypeName(tet + \"[]\");\n            { typeof(Tensor<__t__>[]), c => { var v = default(Tensor<__t__>[]); c.Code__tena__(ref v); return v; } },\n            //# var lten = Meta.GetXmlTypeName(\"List<\" + tet + \">\");\n            { typeof(List<Tensor<__t__>>), c => { var v = default(List<Tensor<__t__>>); c.Code__lten__(ref v); return v; } },\n\n            #endregion\n\n            //# });\n            #region Multi-Dimensional Arrays\n\n            //# directlyCodeableTypes.ForEach((t, i) => {\n            //# var n2d = Meta.GetXmlTypeName(t + \"[,]\");\n            { typeof(__t__[,]), c => { var v = default(__t__[,]); c.Code__n2d__(ref v); return v; } },\n            //# var n3d = Meta.GetXmlTypeName(t + \"[,,]\");\n            { typeof(__t__[, ,]), c => { var v = default(__t__[, ,]); c.Code__n3d__(ref v); return v; } },\n            //# });\n\n            #endregion\n\n            #region Jagged Multi-Dimensional Arrays\n\n            //# directlyCodeableTypes.ForEach((t, i) => {\n            //# var n2d = Meta.GetXmlTypeName(t + \"[][]\");\n            { typeof(__t__[][]), c => { var v = default(__t__[][]); c.Code__n2d__(ref v); return v; } },\n            //# var n3d = Meta.GetXmlTypeName(t + \"[][][]\");\n            { typeof(__t__[][][]), c => { var v = default(__t__[][][]); c.Code__n3d__(ref v); return v; } },\n            //# });\n\n            #endregion\n\n            #region Other Types\n\n            { typeof(IntSet), c => { var v = default(IntSet); c.CodeIntSet(ref v); return v; } },\n            { typeof(SymbolSet), c => { var v = default(SymbolSet); c.CodeSymbolSet(ref v); return v; } },\n\n            { typeof(HashSet<string>), c => { var v = default(HashSet<string>); c.CodeHashSet_of_T_(ref v); return v; } },\n\n            #endregion\n        };\n\n        public static partial class Default\n        {\n            /// <summary>\n            /// The default way of encoding various basic types.\n            /// </summary>\n            public static TypeInfo[] Basic = new[]\n            {\n                //# allTypes.ForEach((t, i) => {\n                #region __t__\n\n                new TypeInfo(\"__t__\", typeof(__t__), TypeInfo.Option.None),\n                new TypeInfo(typeof(__t__[]), TypeInfo.Option.None),\n                new TypeInfo(typeof(List<__t__>), TypeInfo.Option.None),\n\n                new TypeInfo(\"Vector<__t__>\", \"Vector_of_\" + \"__t__\", typeof(Vector<__t__>), TypeInfo.Option.None),\n                new TypeInfo(\"Vector<__t__>[]\", \"Array_of_Vector_of_\" + \"__t__\", typeof(Vector<__t__>[]), TypeInfo.Option.None),\n                new TypeInfo(\"List<Vector<__t__>>\", \"List_of_Vector_of_\" + \"__t__\", typeof(List<Vector<__t__>>), TypeInfo.Option.None),\n\n                new TypeInfo(\"Matrix<__t__>\", \"Matrix_of_\" + \"__t__\", typeof(Matrix<__t__>), TypeInfo.Option.None),\n                new TypeInfo(\"Matrix<__t__>[]\", \"Array_of_Matrix_of_\" + \"__t__\", typeof(Matrix<__t__>[]), TypeInfo.Option.None),\n                new TypeInfo(\"List<Matrix<__t__>>\", \"List_of_Matrix_of_\" + \"__t__\", typeof(List<Matrix<__t__>>), TypeInfo.Option.None),\n\n                new TypeInfo(\"Volume<__t__>\", \"Volume_of_\" + \"__t__\", typeof(Volume<__t__>), TypeInfo.Option.None),\n                new TypeInfo(\"Volume<__t__>[]\", \"Array_of_Volume_of_\" + \"__t__\", typeof(Volume<__t__>[]), TypeInfo.Option.None),\n                new TypeInfo(\"List<Volume<__t__>>\", \"List_of_Volume_of_\" + \"__t__\", typeof(List<Volume<__t__>>), TypeInfo.Option.None),\n\n                new TypeInfo(\"Tensor<__t__>\", \"Tensor_of_\" + \"__t__\", typeof(Tensor<__t__>), TypeInfo.Option.None),\n                new TypeInfo(\"Tensor<__t__>[]\", \"Array_of_Tensor_of_\" + \"__t__\", typeof(Tensor<__t__>[]), TypeInfo.Option.None),\n                new TypeInfo(\"List<Tensor<__t__>>\", \"List_of_Tensor_of_\" + \"__t__\", typeof(List<Tensor<__t__>>), TypeInfo.Option.None),\n\n                #endregion\n\n                //# });\n\n                new TypeInfo(\"HashSet<string>\", \"HashSet_of_string\", typeof(HashSet<string>), TypeInfo.Option.None),\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/TypeExtensions.cs",
    "content": "﻿using System;\nusing System.Linq;\n\nnamespace Aardvark.Base.Coder\n{\n    public static class TypeFun\n    {\n        static readonly string[] c_genericSeparators = new[] { \"<\", \",\", \">\" };\n        public static string GetCanonicalName(this Type self)\n        {\n            return GetCanonicalName(self, c_genericSeparators, false);\n        }\n\n        static readonly string[] c_xmlGenericSeparators = new[] { \"_of_\", \"_\", \"\" };\n        public static string GetCanonicalXmlName(this Type self)\n        {\n            return GetCanonicalName(self, c_xmlGenericSeparators, true);\n        }\n\n        public static string GetCanonicalName(\n                this Type self, string[] separators, bool xml)\n        {\n            var typeName = self.Name;\n            if (self.IsGenericType)\n            {\n                var subTypeNames = (from t in self.GetGenericArguments()\n                                    select t.GetCanonicalName(separators,\n                                                              xml)\n                                    ).ToArray();\n\n                int quote = typeName.LastIndexOf(\"`\");\n\n                string numberString = (xml && subTypeNames.Length > 1)\n                        ? subTypeNames.Length.ToString() + separators[1]\n                        : \"\";\n\n                return typeName.Substring(0, quote)\n                        + separators[0]\n                        + numberString\n                        + String.Join(separators[1], subTypeNames)\n                        + separators[2];\n            }\n            if (self.IsArray)\n            {\n                if (xml)\n                {\n                    var d = self.GetArrayRank();\n                    return self.GetElementType().GetCanonicalName(separators, true)\n                            + \"_Array\" + (d == 1 ? \"\" : d.ToString() + \"d\");\n                }\n                return typeName;\n            }\n            return typeName;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/TypeInfo.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// This represents the association between a type, its short name,\n    /// and its XML-name. Options can be specified for more control of\n    /// these associations.\n    /// </summary>\n    public class TypeInfo\n    {\n        private Type m_type;\n        private string m_name;\n        private readonly string m_xmlName;\n        private readonly int m_version;\n        private Option m_options;\n        private Dictionary<int, TypeInfo> m_versionMap;\n        private readonly Func<object> m_creator;\n        private object m_typeOptions;\n\n        public Type ProxyType;  // if this != null m_creator must create a proxy object\n        public Func<object, IFieldCodeable> Object2ProxyFun;\n        public Func<IFieldCodeable, object> Proxy2ObjectFun;\n\n\n        #region Constructors\n\n        private TypeInfo(Type type, string name, string xmlName, int version,\n                        Option options, Dictionary<int, TypeInfo> versionMap,\n                        Func<object> creator, object typeOptions)\n        {\n            m_type = type; m_name = name; m_xmlName = xmlName;\n            m_version = version; m_options = options;\n            m_versionMap = versionMap;\n            m_creator = creator;\n            m_typeOptions = typeOptions;\n        }\n\n        public TypeInfo(Type type, string name, string xmlName, int version,\n                        Option options, Func<object> creator)\n        {\n            m_type = type; m_name = name; m_xmlName = xmlName;\n            m_version = version; m_options = options;\n            m_versionMap = null;\n            m_creator = creator;\n        }\n\n        public TypeInfo(TypeInfo ti)\n            : this(ti.m_type, ti.m_name, ti.m_xmlName, ti.m_version, ti.m_options,\n                   ti.m_versionMap, ti.m_creator, ti.m_typeOptions)\n        { }\n\n        public TypeInfo(TypeInfo ti, int version)\n            : this(ti.m_type, ti.m_name, ti.m_xmlName, version, ti.m_options,\n                   ti.m_versionMap, ti.m_creator, ti.m_typeOptions)\n        { }\n\n        public TypeInfo(string name, Type type, int version = 0)\n            : this(type, name, name, version, Option.Version | Option.Size, null)\n        { }\n\n        public TypeInfo(Type type, int version = 0)\n            : this(type, type.GetCanonicalName(), type.GetCanonicalXmlName(),\n                   version, Option.Version|Option.Size, null)\n        { }\n\n        public TypeInfo(string name, Type type, Option codeInfo)\n            : this(type, name, name, 0, codeInfo, null)\n        { }\n\n        public TypeInfo(string name, string xmlName, Type type, Option codeInfo)\n            : this(type, name, xmlName, 0, codeInfo, null)\n        { }\n\n        public TypeInfo(Type type, Option codeInfo)\n            : this(type, type.GetCanonicalName(), type.GetCanonicalXmlName(),\n                   0, codeInfo, null)\n        { }\n\n        public TypeInfo(\n                string name, Type type, Option codeInfo,\n                Func<object> creator)\n            : this(type, name, name, 0, codeInfo, creator)\n        { }\n\n        public TypeInfo(\n                Type type, Option codeInfo,\n                Func<object> creator)\n            : this(type, type.GetCanonicalName(), type.GetCanonicalXmlName(),\n                   0, codeInfo, creator)\n        { }\n\n        public TypeInfo(\n                Type type,\n                Func<object> creator)\n            : this (type, type.GetCanonicalName(), type.GetCanonicalXmlName(),\n                   0, Option.Version | Option.Size, creator)\n        { }\n\n\n        /// <summary>\n        /// Creates a type info for a type that uses the IFieldCodeable\n        /// implementation of a proxy type for coding.\n        /// </summary>\n        /// <param name=\"type\">the that needs to be coded</param>\n        /// <param name=\"proxyType\">the type of the proxy object</param>\n        /// <param name=\"proxyCreator\">creates a proxy object for reading</param>\n        /// <param name=\"proxyToObjectFun\">converts the proxy object that was used for reading\n        /// into the actual object</param>\n        /// <param name=\"objectToProxyFun\">converts the actual object into a proxy object that\n        /// is used for writing</param>\n        public TypeInfo(\n                Type type,\n                Type proxyType,\n                Func<object> proxyCreator,\n                Func<IFieldCodeable, object> proxyToObjectFun, // used for reading\n                Func<object, IFieldCodeable> objectToProxyFun // used for writing\n                )\n                : this (type, proxyCreator)\n        {\n            ProxyType = proxyType;\n            Proxy2ObjectFun = proxyToObjectFun;\n            Object2ProxyFun = objectToProxyFun;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public Type Type { get { return m_type; } set { m_type = value; } }\n        public string Name { get { return m_name; } set { m_name = value; } }\n        public string XmlName { get { return m_xmlName; } }\n        public int Version { get { return m_version; } }\n        public object TypeOptions { get { return m_typeOptions; } set { m_typeOptions = value; } }\n\n        public Dictionary<int, TypeInfo> VersionMap\n        {\n            get { return m_versionMap != null ? m_versionMap : s_emptyVersionMap; }\n        }\n\n        public Option Options\n        {\n            get { return m_options; }\n            set { m_options = value; }\n        }\n        public Func<object> Creator { get { return m_creator; } }\n\n        #endregion\n\n        #region Option\n\n        [Flags]\n        public enum Option\n        {\n            None = 0x00,\n            Active = 0x01, // currently only used for nulls and refs\n            Version = 0x02,\n            Size = 0x04,\n            Ignore = 0x08,\n        }\n\n        #endregion\n\n        #region Private Methods\n\n        public void AddVersion(TypeInfo oldTypeInfo)\n        {\n            if (m_versionMap == null) m_versionMap = new Dictionary<int, TypeInfo>();\n            m_versionMap.Add(oldTypeInfo.m_version, oldTypeInfo);\n        }\n\n        #endregion\n\n        #region Private Static Members\n\n        private static readonly object s_lock = new object();\n\n        private static readonly Dictionary<int, TypeInfo> s_emptyVersionMap\n                = new Dictionary<int, TypeInfo>();\n\n        private static readonly Dictionary<Type, TypeInfo> s_ofType =\n            new Dictionary<Type, TypeInfo>();\n        private static readonly Dictionary<string, TypeInfo> s_ofName =\n            new Dictionary<string, TypeInfo>();\n        private static readonly Dictionary<string, TypeInfo> s_ofXmlName =\n            new Dictionary<string, TypeInfo>();\n\n        #endregion\n\n        #region Public Static Members\n\n        public static Dictionary<Type, TypeInfo> OfType\n        {\n            get { return s_ofType; }\n        }\n        public static Dictionary<string, TypeInfo> OfName\n        {\n            get { return s_ofName; }\n        }\n        public static Dictionary<string, TypeInfo> OfXmlName\n        {\n            get { return s_ofXmlName; }\n        }\n\n        private static readonly Regex s_symbolRegex\n                = new Regex(@\"([A-Za-z_][0-9A-Za-z_]*)(\\.[A-Za-z_][0-9A-Za-z_]*)*\");\n\n\n\n        public static bool TryGetOfFullName(string fullName, out TypeInfo typeInfo)\n        {\n            var isArray = false;\n            var match = s_symbolRegex.Match(fullName);\n            if (!match.Success) { typeInfo = default(TypeInfo); return false; }\n            if (fullName.Substring(match.Index + match.Length).StartsWith(\"[]\")) isArray = true;\n            var dotName = match.Value;\n            var name = dotName.Substring(dotName.LastIndexOf('.') + 1);\n            lock (s_lock)\n            {\n                if (OfName.TryGetValue(name, out typeInfo))\n                {\n                    if (!isArray) { OfName[fullName] = typeInfo; return true; }\n                    var newFullName = typeInfo.Type.AssemblyQualifiedName;\n                    var newMatch = s_symbolRegex.Match(newFullName);\n                    if (!newMatch.Success) { typeInfo = default(TypeInfo); return false; }\n                    var newShortName = newMatch.Value; var pos = newMatch.Index + newMatch.Length;\n                    var newName = newFullName.Substring(0, pos) + \"[]\" + newFullName.Substring(pos);\n                    typeInfo = new TypeInfo(typeInfo.Name + \"[]\", Type.GetType(newName), TypeInfo.Option.Size | TypeInfo.Option.Version);\n                    return true;\n                }\n                return false;\n            }\n        }\n\n#if FUTURE\n        public static TypeInfo OfType(Type type)\n        {\n            TypeInfo typeInfo;\n            lock (s_lock)\n            {\n                if (!s_ofType.TryGetValue(type, out typeInfo))\n                    typeInfo = null;\n            }\n            return typeInfo;\n        }\n\n        public static TypeInfo OfName(string name)\n        {\n            TypeInfo typeInfo;\n            lock (s_lock)\n            {\n                if (!s_ofName.TryGetValue(name, out typeInfo))\n                    typeInfo = null;\n            }\n            return typeInfo;\n        }\n\n        public static TypeInfo OfXmlName(string xmlName)\n        {\n            TypeInfo typeInfo;\n            lock (s_lock)\n            {\n                if (!s_ofXmlName.TryGetValue(xmlName, out typeInfo))\n                    typeInfo = null;\n            }\n            return typeInfo;\n        }\n#endif\n\n        #endregion\n\n        #region Private Static Methods\n\n        private static void AddName(string name, TypeInfo typeInfo)\n        {\n            TypeInfo used;\n            if (s_ofName.TryGetValue(name, out used))\n            {\n                throw new ArgumentException(\n                    String.Format(\"type name \\\"{0}\\\" cannot be added for\"\n                                  + \" \\\"{1}\\\" since it is already in use by\"\n                                  + \" \\\"{2}\\\"\",\n                                  name, typeInfo.Type.AssemblyQualifiedName,\n                                  used.Type.AssemblyQualifiedName));\n            }\n            s_ofName.Add(name, typeInfo);\n        }\n\n        private static void AddXmlName(string xmlName, TypeInfo typeInfo)\n        {\n            TypeInfo used;\n            if (s_ofXmlName.TryGetValue(xmlName, out used))\n            {\n                throw new ArgumentException(\n                    String.Format(\"xml type name \\\"{0}\\\" cannot be added for\"\n                                  + \" \\\"{1}\\\" since it is already in use by\"\n                                  + \" \\\"{2}\\\"\",\n                                  xmlName, typeInfo.Type.AssemblyQualifiedName,\n                                  used.Type.AssemblyQualifiedName));\n            }\n            s_ofXmlName.Add(xmlName, typeInfo);\n        }\n\n        #endregion\n\n        #region Public Static Methods\n\n        public static void Add(TypeInfo typeInfo)\n        {\n            lock (s_lock)\n            {\n                if (!s_ofType.ContainsKey(typeInfo.Type))\n                {\n                    AddName(typeInfo.Name, typeInfo);\n                    AddXmlName(typeInfo.XmlName, typeInfo);\n                    s_ofType.Add(typeInfo.Type, typeInfo);\n                }\n            }\n        }\n\n        public static void Add(IEnumerable<TypeInfo> typeInfos)\n        {\n            lock (s_lock)\n            {\n                foreach (var ti in typeInfos) Add(ti);\n            }\n        }\n\n        public static void Add(Type type, int version = 0)\n        {\n            lock (s_lock)\n            {\n                if (!s_ofType.ContainsKey(type))\n                    Add(new TypeInfo(type, version));\n            }\n        }\n\n        public static void Add(IEnumerable<Type> types)\n        {\n            lock (s_lock)\n            {\n                foreach (var type in types)\n                    if (!s_ofType.ContainsKey(type))\n                        Add(new TypeInfo(type, 0));\n            }\n        }\n\n\n        public static void Add(TypeInfo typeInfo, params string[] alternateNames)\n        {\n            lock (s_lock)\n            {\n                if (!s_ofType.ContainsKey(typeInfo.Type))\n                {\n                    Add(typeInfo);\n                    foreach (string name in alternateNames)\n                        AddName(name, typeInfo);\n                }\n            }\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/TypeInfoVersion.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Coder\n{\n    public static class TypeInfoVersion\n    {\n        public static void Add(Type type, int version)\n        {\n            Add(type, version, null, null, null);\n        }\n\n        public static void Add(\n                Type type, int version,\n                Type targetType, Type newestType,\n                Action<Convertible, Convertible> converter)\n        {\n            lock (s_lock)\n            {\n                TypeInfo.Add(type, version);\n                TypeInfo typeInfo = TypeInfo.OfType[type];\n\n                List<Type> oldTypes;\n                if (s_oldTypeListOfType.TryGetValue(typeInfo.Type,\n                                                    out oldTypes))\n                {\n                    foreach (var oldType in oldTypes)\n                        typeInfo.AddVersion(TypeInfo.OfType[oldType]);\n                    s_oldTypeListOfType.Remove(typeInfo.Type);\n                }\n\n                (string, Action<Convertible, Convertible>) conversion;\n                if (s_conversionOfTargetType.TryGetValue(typeInfo.Type,\n                                                         out conversion))\n                {\n                    Converter.Global.Register(conversion.Item1, typeInfo.Name, conversion.Item2);\n                    s_conversionOfTargetType.Remove(typeInfo.Type);\n                }\n\n                if (newestType == null) return;\n\n                TypeInfo newestTypeInfo;\n                if (!TypeInfo.OfType.TryGetValue(newestType, out newestTypeInfo))\n                {\n                    List<Type> oldTypeList;\n                    if (!s_oldTypeListOfType.TryGetValue(newestType, out oldTypeList))\n                    {\n                        oldTypeList = new List<Type>();\n                        s_oldTypeListOfType.Add(newestType, oldTypeList);\n                    }\n                    oldTypeList.Add(type);\n                }\n                else\n                    newestTypeInfo.AddVersion(typeInfo);\n\n                TypeInfo targetTypeInfo;\n                if (!TypeInfo.OfType.TryGetValue(targetType, out targetTypeInfo))\n                    s_conversionOfTargetType.Add(targetType, (typeInfo.Name, converter));\n                else\n                    Converter.Global.Register(typeInfo.Name, targetTypeInfo.Name, converter);\n            }\n        }\n\n        private static readonly Dictionary<Type, List<Type>> s_oldTypeListOfType =\n            new Dictionary<Type, List<Type>>();\n\n        private static readonly Dictionary<Type, (string, Action<Convertible, Convertible>)>\n            s_conversionOfTargetType\n            = new Dictionary<Type, (string, Action<Convertible, Convertible>)>();\n\n        private static readonly object s_lock = new object();\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/UberStream.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.IO;\nusing System.Linq;\n\nnamespace Aardvark.Base.Coder\n{\n    /// <summary>\n    /// To bundle multiple streams to one or create a sub-stream for an existing stream.\n    /// </summary>\n    public class UberStream : Stream\n    {\n        private struct SubStream\n        {\n            public Stream Stream;\n            public long StartPos; // start position in underlying stream\n            public long Length; // number of elements the substream covers\n            public long PosOffset; // pos offset in UberStream\n        }\n\n        #region private fields\n\n        private long m_position;\n        private readonly long m_totalLength;\n        private readonly SubStream[] m_streams;\n\n        #endregion\n\n        #region validation\n\n        private static void ValidateStartAndLength(long startPos, long numOfBytes)\n        {\n            if (startPos < 0)\n                throw new ArgumentOutOfRangeException(nameof(startPos), \"startPos can not be less than 0.\");\n\n            if (numOfBytes < 0)\n                throw new ArgumentOutOfRangeException(nameof(numOfBytes), \"numOfBytes can not be less than 0.\");\n        }\n\n        private static void ValidateUberStreamBufferArguments(byte[] buffer, int offset, int count)\n        {\n            if (buffer == null)\n                throw new ArgumentNullException(nameof(buffer));\n\n            if (offset < 0)\n                throw new ArgumentOutOfRangeException(nameof(offset));\n\n            if (count < 0)\n                throw new ArgumentOutOfRangeException(nameof(count));\n\n            if (offset > buffer.Length - count)\n                throw new ArgumentException(\"Offset and count do not describe a valid range in the buffer.\", nameof(count));\n        }\n\n        #endregion\n\n        #region private methods\n\n        private int DoItSo(byte[] buffer, int offset, int count, Func<Stream, byte[], int, int, int> func)\n        {\n            if (m_position < 0 || m_position >= m_totalLength) return 0;\n\n            var firstId = m_streams.FindIndex(true, sub => sub.PosOffset + sub.Length > m_position);\n\n            var haveBeenDone = 0;\n            var shouldBeenDone = 0;\n            for (int i = firstId;\n                shouldBeenDone < count && i < m_streams.Count();\n                i++)\n            {\n                var sub = m_streams[i];\n                var subPosition = m_position + shouldBeenDone - sub.PosOffset;\n\n                // set position in sub-stream\n                if (sub.StartPos != 0 || subPosition != 0)\n                    sub.Stream.Position = sub.StartPos + subPosition;\n\n                // calculate bytes to process in sub-stream\n                var bytesToDo = (int)(sub.Length - subPosition);\n                if (bytesToDo > count - shouldBeenDone)\n                    bytesToDo = count - shouldBeenDone;\n\n                // do it so\n                haveBeenDone += func(sub.Stream, buffer, offset + shouldBeenDone, bytesToDo);\n                shouldBeenDone += bytesToDo;\n            }\n            m_position += shouldBeenDone;\n\n            return haveBeenDone;\n        }\n\n        #endregion\n        \n        #region constructors\n\n        /// <summary>\n        /// Create Sub-stream.\n        /// </summary>\n        /// <param name=\"stream\"></param>\n        /// <param name=\"startPos\"></param>\n        /// <param name=\"numOfBytes\"></param>\n        public UberStream(Stream stream, long startPos, long numOfBytes)\n            : base()\n        {\n            if (stream == null)\n                throw new ArgumentNullException(nameof(stream));\n\n            ValidateStartAndLength(startPos, numOfBytes);\n\n            if (stream.CanSeek && startPos > stream.Length - numOfBytes)\n                throw new ArgumentOutOfRangeException(nameof(numOfBytes));\n\n            m_streams = new SubStream[]\n            {\n                new SubStream()\n                {\n                    Stream = stream,\n                    StartPos = startPos,\n                    Length = numOfBytes,\n                    PosOffset = 0\n                }\n            };\n\n            m_position = 0;\n            m_totalLength = numOfBytes;\n        }\n\n        /// <summary>\n        /// Bundle streams to one in given order.\n        /// Stream-1 (startPos->End) ... Stream-n (Begin->End) ... Stream-last (Begin->endPos)\n        /// endPos = Stream-last.length - (AllStreams.length - startPos - numOfBytes)\n        /// </summary>\n        /// <param name=\"streams\"></param>\n        /// <param name=\"startPos\">Position in first stream, where bundle should begin.</param>\n        /// <param name=\"numOfBytes\">Number of bytes the uber-stream covers.</param>\n        public UberStream(Stream[] streams, long startPos, long numOfBytes)\n            : base()\n        {\n            if (streams == null)\n                throw new ArgumentNullException(nameof(streams));\n\n            if (streams.Length == 0)\n                throw new ArgumentException(\"At least one stream is required.\", nameof(streams));\n\n            ValidateStartAndLength(startPos, numOfBytes);\n\n            if (streams.Any(s => s == null))\n                throw new ArgumentNullException(nameof(streams), \"Stream array can not contain null entries.\");\n\n            if (streams.All(s => s.CanSeek) && startPos > streams.Select(s => s.Length).Sum() - numOfBytes)\n                throw new ArgumentOutOfRangeException(nameof(numOfBytes));\n\n            m_position = 0;\n            m_totalLength = numOfBytes;\n\n            m_streams = new SubStream[streams.Count()];\n\n            // set first element\n            if (streams.First().Length < startPos)\n                throw new ArgumentException(\"First stream is shorter than startPos.\");\n\n            m_streams[0] = new SubStream()\n            {\n                Stream = streams.First(),\n                StartPos = startPos,\n                Length = streams.First().Length - startPos,\n                PosOffset = 0\n            };\n\n            // set elements\n            for (var i = 1; i < streams.Count(); i++)\n            {\n                m_streams[i] = new SubStream()\n                {\n                    Stream = streams[i],\n                    StartPos = 0,\n                    Length = streams[i].Length,\n                    PosOffset = m_streams[i - 1].PosOffset + m_streams[i - 1].Length\n                };\n            }\n\n            // set last element\n            var streamsTotalLength = streams.Select(stream => stream.Length).Sum();\n            var diff = streamsTotalLength - startPos - numOfBytes;\n\n            if (diff < 0)\n                throw new ArgumentException(\"streams don't have enough length (< startPos + numOfBytes).\");\n\n            if (streams.Last().Length < diff)\n                throw new ArgumentException(\"Last stream is shorter than the requested bytes.\");\n\n            m_streams[m_streams.Length - 1] = new SubStream()\n            {\n                Stream = m_streams[m_streams.Length - 1].Stream,\n                StartPos = m_streams[m_streams.Length - 1].StartPos,\n                Length = m_streams[m_streams.Length - 1].Length - diff,\n                PosOffset = m_streams[m_streams.Length - 1].PosOffset // numOfBytes - Length // also: streamsTotalLength - streams.Last().Length - startPos\n            };\n        }\n\n        //public UberStream(IEnumerable<Tup<Stream, long, long>> streams)\n        //{\n        //}\n\n        #endregion\n\n        #region implement Stream\n\n        public override bool CanRead\n        {\n            get { return m_streams.All(sub => sub.Stream.CanRead); }\n        }\n\n        public override bool CanSeek\n        {\n            get { return m_streams.All(sub => sub.Stream.CanSeek); }\n        }\n\n        public override bool CanWrite\n        {\n            get { return m_streams.All(sub => sub.Stream.CanWrite); }\n        }\n\n        public override long Length\n        {\n            get { return m_totalLength; }\n        }\n\n        public override long Position\n        {\n            get\n            {\n                return m_position;\n            }\n            set\n            {\n                Seek(value, SeekOrigin.Begin);\n            }\n        }\n\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing)\n                foreach (var subStream in m_streams)\n                    subStream.Stream.Dispose();\n\n            base.Dispose(disposing);\n        }\n\n        public override void Flush()\n        {\n            foreach (var sub in m_streams)\n                sub.Stream.Flush();\n        }\n\n        public override int Read(byte[] buffer, int offset, int count)\n        {\n            ValidateUberStreamBufferArguments(buffer, offset, count);\n\n            if (!CanRead)\n                throw new NotSupportedException();\n\n            //throw new ObjectDisposedException();\n\n            return DoItSo(buffer, offset, count,\n                (s, b, o, c) => s.Read(b, o, c));\n        }\n\n        public override long Seek(long offset, SeekOrigin origin)\n        {\n            if (!CanSeek) throw new NotSupportedException();\n            //throw new IOException();\n            //throw new ObjectDisposedException();\n\n            switch (origin)\n            {\n                case SeekOrigin.Begin:\n                    m_position = offset;\n                    break;\n                case SeekOrigin.End:\n                    m_position = m_totalLength + offset;\n                    break;\n                case SeekOrigin.Current:\n                    m_position += offset;\n                    break;\n            }\n\n            return m_position;\n        }\n\n        public override void SetLength(long value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public override void Write(byte[] buffer, int offset, int count)\n        {\n            ValidateUberStreamBufferArguments(buffer, offset, count);\n\n            if (!CanWrite)\n                throw new NotSupportedException();\n\n            DoItSo(buffer, offset, count,\n                (s, b, o, c) => { s.Write(b, o, c); return c; });\n        }\n\n        #endregion\n    }\n\n    //public class SubStream : Stream\n    //{\n    //    #region private fields\n    //    private Stream m_stream;\n    //    private long m_startPos; // start position in underlying stream\n    //    private long m_length; // number of elements the substream covers\n    //    #endregion\n\n    //    #region constructors\n\n    //    public SubStream(Stream stream, long startPos, long numOfElements)\n    //        : base()\n    //    {\n    //        m_stream = stream;\n    //        m_startPos = startPos;\n    //        m_length = numOfElements;\n    //    }\n\n    //    #endregion\n\n    //    #region implement Stream\n\n    //    public override bool CanRead\n    //    {\n    //        get { return m_stream.CanRead; }\n    //    }\n\n    //    public override bool CanSeek\n    //    {\n    //        get { return m_stream.CanSeek; }\n    //    }\n\n    //    public override bool CanWrite\n    //    {\n    //        get { return m_stream.CanWrite; }\n    //    }\n\n    //    public override void Flush()\n    //    {\n    //        m_stream.Flush();\n    //    }\n\n    //    public override long Length\n    //    {\n    //        get { return m_length; }\n    //    }\n\n    //    public override long Position\n    //    {\n    //        get\n    //        {\n    //            return m_stream.Position - m_startPos;\n    //        }\n    //        set\n    //        {\n    //            m_stream.Position = m_startPos + value;\n    //        }\n    //    }\n\n    //    public override int Read(byte[] buffer, int offset, int count)\n    //    {\n    //        if ((Position + count) > m_length)\n    //            count = (int)(m_length - Position);\n\n    //        return m_stream.Read(buffer, offset, count);\n    //    }\n\n    //    public override long Seek(long offset, SeekOrigin origin)\n    //    {\n    //        switch (origin)\n    //        {\n    //            case SeekOrigin.Begin:\n    //                offset += m_startPos;\n    //                break;\n    //            case SeekOrigin.End:\n    //                offset += m_length - m_stream.Length;\n    //                break;\n    //            //case SeekOrigin.Current:\n    //        }\n\n    //        return m_stream.Seek(offset, origin);\n    //    }\n\n    //    public override void SetLength(long value)\n    //    {\n    //        m_length = value;\n\n    //        if ((value + m_startPos) > m_stream.Length)\n    //            m_stream.SetLength(m_startPos + value);\n    //    }\n\n    //    public override void Write(byte[] buffer, int offset, int count)\n    //    {\n    //        m_stream.Write(buffer, offset, count);\n    //    }\n\n    //    #endregion\n    //}\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/WorkDir.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base.Coder\n{\n    public static class Dir\n    {\n        /// <summary>\n        /// Converts the absolute directory path into a relative one, relative\n        /// to the provided relativeTo directory path. Returns null if not possible\n        /// (e.g. paths are on different drives).\n        /// </summary>\n        /// <param name=\"absoluteDir\">The directory where the result should point at.</param>\n        /// <param name=\"relativeToDir\">The directory from where the result should start from.</param>\n        /// <returns>The relative path from <paramref name=\"relativeToDir\"/> to <paramref name=\"absoluteDir\"/> \n        /// or null if no relative path can be found.</returns>\n        public static string RelativeDir(string absoluteDir, string relativeToDir)\n        {\n            return RelativeDir(new DirectoryInfo(absoluteDir), new DirectoryInfo(relativeToDir));\n        }\n\n        /// <summary>\n        /// Converts the absolute directory path into a relative one, relative\n        /// to the provided relativeTo directory path. Returns null if not possible\n        /// (e.g. paths are on different drives).\n        /// </summary>\n        /// <param name=\"absoluteDir\">The directory where the result should point at.</param>\n        /// <param name=\"relativeToDir\">The directory from where the result should start from.</param>\n        /// <returns>The relative path from <paramref name=\"relativeToDir\"/> to <paramref name=\"absoluteDir\"/> \n        /// or null if no relative path can be found.</returns>\n        public static string RelativeDir(DirectoryInfo absoluteDir, DirectoryInfo relativeToDir)\n        {\n            var absoluteDirS = absoluteDir.FullName;\n            var relativeToDirS = relativeToDir.FullName;\n\n            var separators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };\n            string[] absoluteDirectories = Path.GetFullPath(absoluteDirS).Split(separators, StringSplitOptions.RemoveEmptyEntries);\n            string[] relativeDirectories = Path.GetFullPath(relativeToDirS).Split(separators, StringSplitOptions.RemoveEmptyEntries);\n\n            // get the shortest of the two paths\n            int length = System.Math.Min(absoluteDirectories.Length, relativeDirectories.Length);\n\n\n            // find common root\n            int index;\n            for (index = 0; index < length; index++)\n                if (absoluteDirectories[index].ToLower() != relativeDirectories[index].ToLower())\n                    break;\n            // use to determine where in the loop we exited\n            int lastCommonRoot = index - 1;\n\n            // if we didn't find a common prefix then return null\n            if (lastCommonRoot < 0)\n                return null;\n\n            // build up the relative path\n            StringBuilder relativePath = new StringBuilder();\n\n            // add on the ..\n            for (index = lastCommonRoot + 1; index < relativeDirectories.Length; index++)\n                if (relativeDirectories[index].Length > 0)\n                    relativePath.Append(\"..\" + Path.DirectorySeparatorChar);\n\n            // add on the folders\n            for (index = lastCommonRoot + 1; index < absoluteDirectories.Length; index++)\n                relativePath.Append(absoluteDirectories[index] + Path.DirectorySeparatorChar);\n\n            return relativePath.ToString();\n        }\n\n        /// <summary>\n        /// Converts the absolute file path into a relative one, relative\n        /// to the provided relativeTo directory path. Returns null if not possible\n        /// (e.g. paths are on different drives).\n        /// </summary>\n        /// <param name=\"absoluteFile\">The file where the result should point at.</param>\n        /// <param name=\"relativeTo\">The directory from where the result should start from.</param>\n        /// <returns>The relative path from <paramref name=\"relativeTo\"/> to <paramref name=\"absoluteFile\"/> \n        /// or null if no relative path can be found.</returns>\n        public static string RelativeFile(FileInfo absoluteFile, DirectoryInfo relativeTo)\n        {\n            return RelativeDir(absoluteFile.Directory, relativeTo) + absoluteFile.Name;\n        }\n\n        /// <summary>\n        /// Converts the absolute file path into a relative one, relative\n        /// to the provided relativeTo directory path. Returns null if not possible\n        /// (e.g. paths are on different drives).\n        /// </summary>\n        /// <param name=\"absoluteFile\">The file where the result should point at.</param>\n        /// <param name=\"relativeTo\">The directory from where the result should start from.</param>\n        /// <returns>The relative path from <paramref name=\"relativeTo\"/> to <paramref name=\"absoluteFile\"/> \n        /// or null if no relative path can be found.</returns>\n        public static string RelativeFile(string absoluteFile, string relativeTo)\n        {\n            return RelativeFile(new FileInfo(absoluteFile), new DirectoryInfo(relativeTo));\n        }\n\n        /// <summary>\n        /// Returns the relative directory path if possible, if not it returns the absolute path if\n        /// UseAbsolutePathsIfNecessary is set to true (default behaviour) else returns String.Empty.\n        /// </summary>\n        public static string TryGetRelativeDir(string absoluteDir, string relativeTo, bool useAbsolutePathsIfNecessary)\n        {\n            if (string.IsNullOrEmpty(absoluteDir))\n                return String.Empty;\n\n            var relDirName = Dir.RelativeDir(absoluteDir, relativeTo);\n\n            // if no relative filename was found, store the absolute path (if not disabled)\n            if (relDirName == null)\n            {\n                if (useAbsolutePathsIfNecessary)\n                    relDirName = absoluteDir;\n                else\n                    relDirName = String.Empty;\n            }\n\n            return relDirName;\n        }\n\n        /// <summary>\n        /// Returns the relative file path if possible, if not it returns the absolute path if\n        /// UseAbsolutePathsIfNecessary is set to true (default behaviour) else returns String.Empty.\n        /// </summary>\n        public static string TryGetRelativeFileName(string absoluteFile, string relativeTo, bool useAbsolutePathsIfNecessary)\n        {\n            if (string.IsNullOrEmpty(absoluteFile))\n                return String.Empty;\n\n            var relFileName = Dir.RelativeFile(absoluteFile, relativeTo);\n\n            // if no relative filename was found, store the absolute path (if not disabled)\n            if (relFileName == null)\n            {\n                if (useAbsolutePathsIfNecessary)\n                    relFileName = absoluteFile;\n                else\n                    relFileName = String.Empty;\n            }\n\n            return relFileName;\n        }\n\n        public static string GetAbsoluteFileName(string fileName, string rootPath, bool useAbsolutePathsIfNecessary = true)\n        {\n            if (string.IsNullOrEmpty(fileName))\n                return String.Empty;\n\n            // check if fileName is relative\n            if (!Path.IsPathRooted(fileName))\n                return Path.Combine(rootPath, fileName);\n            else if (useAbsolutePathsIfNecessary)\n                return fileName;\n            else\n                return String.Empty;\n        }\n    }\n\n    public static class WorkDir\n    {\n        private const string c_workDirNameEnvVariable = \"AARDVARK_WORKDIR\";\n        private static string s_workDirName = null;\n\n        private static readonly string[] s_fallbackWorkDirNames =\n        {\n            @\"C:\\Aardwork\",\n            @\"C:\\Data\\Aardwork\",\n        };\n\n        static WorkDir()\n        {\n            s_workDirName = Environment.GetEnvironmentVariable(c_workDirNameEnvVariable);\n\n            if (s_workDirName == null)\n            {\n                foreach (var s in s_fallbackWorkDirNames)\n                {\n                    try\n                    {\n                        if (Directory.Exists(s))\n                        {\n                            s_workDirName = s;\n                            return;\n                        }\n                    }\n                    catch\n                    {\n                    }\n                }\n            }\n        }\n\n        public static string Name\n        {\n            get { return s_workDirName; }\n            set\n            {\n                if (!Directory.Exists(value))\n                    throw new ArgumentException(\"directory does not exist: \" + value);\n                s_workDirName = value;\n            }\n        }\n\n        public static bool Exists { get { return s_workDirName != null; } }\n\n        public static string FindFile(string fileName)\n        {\n            if (!Exists) throw new InvalidOperationException(\n                \"Aardvark work dir is undefined. Set env variable \" + c_workDirNameEnvVariable);\n\n            var result = FindFileBreadthFirst(\n                fileName, new string[] { Name }\n                );\n\n            return result;\n        }\n\n        public static IEnumerable<string> FindFiles(IEnumerable<string> fileNames)\n        {\n            if (!Exists) throw new InvalidOperationException(\n                   \"Aardvark work dir is undefined. Set env variable \" + c_workDirNameEnvVariable);\n\n            return from fileName in fileNames select FindFile(fileName);\n        }\n\n        private static string FindFileBreadthFirst(\n            string pattern, IEnumerable<string> dirs\n            )\n        {\n            if (dirs.Count() == 0) return null;\n\n            var fileNames =\n                from dir in dirs\n                from file in Directory.GetFiles(dir, pattern)\n                select file;\n\n            var result = fileNames.FirstOrDefault();\n            if (result != null) return result;\n\n            return FindFileBreadthFirst(\n                pattern,\n                from dir in dirs\n                from subdir in Directory.GetDirectories(dir)\n                select subdir\n                );\n        }\n\n        public static string FindDir(string dirName)\n        {\n            if (!Exists) throw new InvalidOperationException(\n                   \"Aardvark work dir is undefined. Set env variable \" + c_workDirNameEnvVariable);\n\n            if (dirName == \".\") return Name;\n\n            var result = FindDirBreadthFirst(\n                dirName, new string[] { Name }\n                );\n\n            if (result == null)\n            {\n                result = Path.Combine(Name, dirName);\n                Directory.CreateDirectory(result);\n            }\n\n            return result;\n        }\n\n        private static string FindDirBreadthFirst(\n            string pattern, IEnumerable<string> dirs\n            )\n        {\n            if (dirs.Count() == 0) return null;\n\n            var result = (\n                from dir in dirs\n                from subdir in Directory.GetDirectories(dir, pattern)\n                select subdir\n                ).FirstOrDefault();\n\n            if (result != null) return result;\n\n            return FindDirBreadthFirst(\n                pattern,\n                from dir in dirs\n                from subdir in Directory.GetDirectories(dir)\n                select subdir\n                );\n        }\n\n        /// <summary>\n        /// Converts the absolute path into a path relative to the \n        /// AARDVARK_WORKDIR or Null if not possible.\n        /// </summary>\n        public static string FindRelativePath(string absolutePath)\n        {\n            if (!Exists) throw new InvalidOperationException(\n                   \"Aardvark work dir is undefined. Set env variable \" + c_workDirNameEnvVariable);\n\n            return Dir.RelativeDir(absolutePath, WorkDir.Name);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/XmlParser.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    #region IXml Interfaces\n\n    public interface IXml\n    {\n        void WriteTo(StreamWriter writer, int indent = 0);\n    }\n\n    public interface IXmlText\n    {\n        Text GetText();\n    }\n\n    public interface IXmlItemProperty\n    {\n        XmlItem XmlItem { get; set; }\n    }\n\n    public interface IXmlDocProperty\n    {\n        XmlDoc XmlDoc { get; set; }\n    }\n\n    #endregion\n\n    #region XmlAtt\n\n    public struct XmlAtt : IXml\n    {\n        public Symbol Key;\n        public Text Value;\n\n        public XmlAtt(Symbol key, string value)\n        {\n            Key = key;\n            Value = value.ToText();\n        }\n\n        public XmlAtt(Text key, Text value)\n        {\n            Key = Symbol.Create(key.ToString()); Value = value;\n        }\n\n        public readonly void WriteTo(StreamWriter writer, int indent = 0)\n        {\n            writer.Write(Key.ToString()); writer.Write(\"=\\\"\");\n            writer.Write(Value.ToString()); writer.Write('\"');\n        }\n    }\n\n    #endregion\n\n    #region XmlItem\n\n    public class XmlItem : IXml\n    {\n        public Symbol Name;\n        public List<XmlAtt> AttList;\n        public List<IXml> SubList;\n\n        #region Constructors\n\n        public XmlItem()\n            : this(default(Symbol))\n        { }\n\n        public XmlItem(Symbol name, params XmlAtt[] atts)\n        {\n            Name = name;\n            AttList = new List<XmlAtt>(atts);\n            SubList = new List<IXml>();\n        }\n\n        public XmlItem(Symbol name, string str)\n            : this(name, str.ToText())\n        { }\n\n        public XmlItem(Symbol name, Text text)\n            : this(name)\n        {\n            SubList.Add(new XmlDirectText(text));\n        }\n\n        public XmlItem(Symbol name, object obj)\n            : this(name, obj.ToString())\n        { }\n\n        public XmlItem(Symbol name, IXml xmlItem, params IXml[] xmlItems)\n            : this(name)\n        {\n            Add(xmlItem);\n            foreach (var item in xmlItems) Add(item);\n        }\n\n        #endregion\n\n        #region Properties\n\n        public void Add(XmlAtt att)\n        {\n            AttList.Add(att);\n        }\n\n        public int Count\n        {\n            get { return SubList.Count; }\n        }\n\n        public IXml this[int index]\n        {\n            get { return SubList[index]; }\n            set { SubList[index] = value; }\n        }\n\n        #endregion\n\n        #region Query Methods\n\n        public int SubCount<T>()\n            where T : class\n        {\n            int count = 0;\n            foreach (var xml in SubList) if (xml is T) ++count;\n            return count;\n        }\n\n        public Text Attribute(Symbol symbol)\n        {\n            foreach (var att in AttList)\n                if (att.Key == symbol)\n                    return att.Value;\n            return default(Text);\n        }\n\n        public T FirstSub<T>()\n            where T : class\n        {\n            T item;\n            if (NextSubIndex(out item) < 0)\n                return null;\n            return item;\n        }\n\n        public T FirstSub<T>(out int index)\n            where T : class\n        {\n            T item;\n            if ((index = NextSubIndex(out item)) < 0) return null;\n            return item;\n        }\n\n        public T NextSub<T>(ref int index)\n            where T : class\n        {\n            T item;\n            if ((index = NextSubIndex(out item, index)) < 0) return null;\n            return item;\n        }\n\n        public XmlItem FirstSubItemWithName(string name)\n        {\n            return FirstSubItemWithName(Symbol.Create(name));\n        }\n\n        public XmlItem FirstSubItemWithName(Symbol name)\n        {\n            return FirstSub<XmlItem>(i => i.Name == name);\n        }\n\n        public T FirstSub<T>(Func<T, bool> predicate)\n            where T : class\n        {\n            T item;\n            int index;\n            if ((index = NextSubIndex(out item)) < 0) return null;\n            while (!predicate(item))\n            {\n                if ((index = NextSubIndex(out item, index)) < 0) return null;\n            }\n            return item;\n        }\n\n        public XmlItem FirstSubItemWithName(string name, out int index)\n        {\n            return FirstSubItemWithName(Symbol.Create(name), out index);\n        }\n\n        public XmlItem FirstSubItemWithName(Symbol name, out int index)\n        {\n            return FirstSub<XmlItem>(i => i.Name == name, out index);\n        }\n\n        public T FirstSub<T>(Func<T, bool> predicate, out int index)\n            where T : class\n        {\n            T item;\n            if ((index = NextSubIndex(out item)) < 0) return null;\n            while (!predicate(item))\n            {\n                if ((index = NextSubIndex(out item, index)) < 0) return null;\n            }\n            return item;\n        }\n\n        public XmlItem NextSubItemWithName(string name, ref int index)\n        {\n            return NextSubItemWithName(Symbol.Create(name), ref index);\n        }\n\n        public XmlItem NextSubItemWithName(Symbol name, ref int index)\n        {\n            return NextSub<XmlItem>(i => i.Name == name, ref index);\n        }\n\n        public IEnumerable<XmlItem> SubItemsWithName(Symbol name)\n        {\n            XmlItem item; int index = -1;\n            while ((item = NextSub<XmlItem>(i => i.Name == name, ref index)) != null)\n                yield return item;\n        }\n\n        public T NextSub<T>(Func<T, bool> predicate, ref int index)\n            where T : class\n        {\n            T item;\n            do\n            {\n                if ((index = NextSubIndex(out item, index)) < 0) return null;\n            }\n            while (!predicate(item));\n            return item;\n        }\n\n        public XmlItem RequiredSubItemWithName(string name)\n        {\n            return RequiredSubItemWithName(Symbol.Create(name));\n        }\n\n        public string RequiredSubItemStringOnlyWithName(Symbol name)\n        {\n            return RequiredSubItemWithName(name).RequiredOnlySubString;\n        }\n\n        public XmlItem RequiredSubItemWithName(Symbol name)\n        {\n            return RequiredSub<XmlItem>(i => i.Name == name);\n        }\n\n        public T RequiredSub<T>(Func<T, bool> predicate)\n            where T : class\n        {\n            int index = -1;\n            T item;\n            do\n            {\n                if ((index = NextSubIndex(out item, index)) < 0)\n                    throw new ArgumentException();\n            }\n            while (!predicate(item));\n            return item;\n        }\n\n        public XmlItem SubItemWithName(string name)\n        {\n            return SubItemWithName(Symbol.Create(name));\n        }\n\n        public XmlItem SubItemWithName(Symbol name)\n        {\n            return Sub<XmlItem>(i => i.Name == name);\n        }\n\n        public T Sub<T>(Func<T, bool> predicate)\n            where T : class\n        {\n            int index = -1;\n            T item;\n            do\n            {\n                if ((index = NextSubIndex(out item, index)) < 0) return null;\n            }\n            while (!predicate(item));\n            return item;\n        }\n\n        public XmlItem RequiredSubItemWithName(string name, out int index)\n        {\n            return RequiredSubItemWithName(Symbol.Create(name), out index);\n        }\n\n        public XmlItem RequiredSubItemWithName(Symbol name, out int index)\n        {\n            return RequiredSub<XmlItem>(i => i.Name == name, out index);\n        }\n\n        public T RequiredSub<T>(Func<T, bool> predicate, out int index)\n            where T : class\n        {\n            index = -1;\n            T item;\n            do\n            {\n                if ((index = NextSubIndex(out item, index)) < 0)\n                    throw new ArgumentException();\n            }\n            while (!predicate(item));\n            return item;\n        }\n\n        public XmlItem SubItemWithName(string name, out int index)\n        {\n            return SubItemWithName(Symbol.Create(name), out index);\n        }\n\n        public XmlItem SubItemWithName(Symbol name, out int index)\n        {\n            return Sub<XmlItem>(i => i.Name == name, out index);\n        }\n\n        public T Sub<T>(Func<T, bool> predicate, out int index)\n            where T : class\n        {\n            index = -1;\n            T item;\n            do\n            {\n                if ((index = NextSubIndex(out item, index)) < 0) return null;\n            }\n            while (!predicate(item));\n            return item;\n        }\n\n        #endregion\n\n        #region Required Sub\n\n        public string RequiredOnlySubString\n        {\n            get\n            {\n                return RequiredOnlySubText.ToString();\n            }\n        }\n\n        public Text RequiredOnlySubText\n        {\n            get\n            {\n                var text = RequiredOnlySub<IXmlText>();\n                return text.GetText();\n            }\n        }\n\n        public T RequiredOnlySub<T>()\n            where T : class\n        {\n            if (SubList.Count != 1) throw new ArgumentException();\n            var sub = SubList[0] as T;\n            if (sub == null) throw new ArgumentException();\n            return sub;\n        }\n\n        #endregion\n\n        #region SubNodes by Index\n\n        public int NextSubIndex<T>(int i = -1)\n            where T : class\n        {\n            ++i;\n            for (int c = SubList.Count; i < c; i++)\n                if (SubList[i] is T) return i;\n            return -1;\n        }\n\n        public int NextSubIndex<T>(out T item, int i = -1)\n            where T : class\n        {\n            ++i;\n            for (int c = SubList.Count; i < c; i++)\n            {\n                var node = SubList[i] as T;\n                if (node != null) { item = node; return i; }\n            }\n            item = default(T);\n            return -1;\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        public void Add(Text text)\n        {\n            SubList.Add(new XmlDirectText(text));\n        }\n\n        public void Add(IXml node)\n        {\n            if (node != null) SubList.Add(node);\n        }\n\n        public IXml Remove()\n        {\n            var last = SubList.Count - 1;\n            var xml = SubList[last];\n            SubList.RemoveAt(last);\n            return xml;\n        }\n\n        #endregion\n\n        #region IXml Members\n\n        public void WriteTo(StreamWriter writer, int indent = 0)\n        {\n            var name = Name.ToString();\n            var subItemCount = SubCount<XmlItem>();\n            if (indent > 0) for (int i = 0; i < indent; i++) writer.Write(\"  \");\n            writer.Write('<'); writer.Write(name);\n            if (AttList.Count > 0)\n                foreach (var att in AttList)\n                {\n                    writer.Write(' '); att.WriteTo(writer);\n                }\n            if (SubList.Count == 0)\n            {\n                if (AttList.Count > 0)\n                    writer.WriteLine(\" />\");\n                else\n                    writer.WriteLine(\"/>\");\n            }\n            else\n            {\n                writer.Write('>');\n                if (subItemCount == 0)\n                {\n                    foreach (var xml in SubList) xml.WriteTo(writer);\n                }\n                else\n                {\n                    writer.WriteLine();\n                    foreach (var xml in SubList)\n                        xml.WriteTo(writer, indent + 1);\n                    if (indent > 0)\n                        for (int i = 0; i < indent; i++) writer.Write(\"  \");\n                }\n                writer.Write(\"</\");\n                writer.Write(name); writer.WriteLine('>');\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region XmlDirectText\n\n    public class XmlDirectText : IXml, IXmlText\n    {\n        public Text Text;\n\n        #region Constructors\n\n        public XmlDirectText(Text text)\n        {\n            Text = text;\n        }\n\n        public XmlDirectText(string str)\n            : this(str.ToText())\n        { }\n\n        #endregion\n\n        #region IXml Members\n\n        public void WriteTo(StreamWriter writer, int indent = 0)\n        {\n            if (indent == 0)\n                writer.Write(Text.ToString());\n            else if (Text.SkipWhiteSpace() < Text.Count)\n            {\n                for (int i = 0; i < indent; i++) writer.Write(\"  \");\n                writer.Write(Text.ToString());\n                writer.WriteLine();\n            }\n        }\n\n        #endregion\n\n        #region IXmlText Members\n\n        public Text GetText() { return Text; }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region XmlLazyText\n\n    public class XmlLazyText : IXml, IXmlText\n    {\n        public Action<StreamWriter> WriteAct;\n\n        public XmlLazyText(Action<StreamWriter> writeAct)\n        {\n            WriteAct = writeAct;\n        }\n\n        #region IXml Members\n\n        public void WriteTo(StreamWriter writer, int indent = 0)\n        {\n            if (indent > 0) for (int i = 0; i < indent; i++) writer.Write(\"  \");\n            WriteAct(writer);\n            if (indent > 0) writer.WriteLine();\n        }\n\n        #endregion\n\n        #region IXmlText Members\n\n        public Text GetText()\n        {\n            var stream = new MemoryStream();\n            WriteAct(new StreamWriter(stream));\n            return new StreamReader(stream).ReadToEnd().ToText();\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region XmlDoc\n\n    public class XmlDoc : XmlItem, IXml\n    {\n        #region Constructor\n\n        public XmlDoc(string version = null, string encoding = null)\n            : base(XmlSymbol)\n        {\n            if (version != null) Add(new XmlAtt(\"version\", version));\n            if (encoding != null) Add(new XmlAtt(\"encoding\", encoding));\n        }\n\n        public XmlDoc(XmlItem item, string version = null, string encoding = null)\n            : this(version, encoding)\n        {\n            Add(item);\n        }\n\n        #endregion\n\n        #region Constants\n\n        public static readonly Symbol XmlSymbol = Symbol.Create(\"xml\");\n\n        #endregion\n\n        #region IO\n\n        public void SaveTo(string filePath)\n        {\n            using (var streamWriter = new StreamWriter(filePath))\n                WriteTo(streamWriter, 0);\n        }\n\n        public static XmlDoc LoadFrom(string filePath)\n        {\n            return LoadFrom(filePath, Encoding.Default);\n        }\n\n        public static XmlDoc LoadFrom(string filePath, Encoding encoding)\n        {\n            var fileString = File.ReadAllText(filePath, encoding);\n\n            var parser = new XmlParser(); var doc = new XmlDoc();\n            try\n            {\n                parser.Parse(fileString, doc);\n            }\n            catch (ParserException<XmlParser> e)\n            {\n                Console.WriteLine(\"(line {0}, col {1}): {2}\",\n                                  e.Parser.UserLine, e.Parser.UserColumn, e.Message);\n            }\n\n            return doc;\n        }\n\n        #endregion\n\n        #region IXml Members\n\n        public new void WriteTo(StreamWriter writer, int indent = 0)\n        {\n            if (AttList.Count > 0)\n            {\n                writer.Write(\"<?xml\");\n                foreach (var att in AttList)\n                {\n                    writer.Write(' '); att.WriteTo(writer);\n                }\n                writer.WriteLine(\"?>\");\n            }\n            foreach (var xml in SubList)\n            {\n                var text = xml as XmlDirectText;\n                if (text != null && text.Text.IsWhiteSpace) continue;\n                xml.WriteTo(writer, indent);\n            }\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region XmlParser\n\n    public class XmlParser : TextParser<XmlParser>\n    {\n        public bool SeenName;\n        public bool SeenSlash;\n        public bool PreserveWhiteSpace;\n        public bool SimpleNames;\n        public char Separator;\n\n        public void Parse(string text, XmlItem node)\n        {\n            SeenName = false;\n            SeenSlash = false;\n            PreserveWhiteSpace = true;\n            SimpleNames = true;\n            Separator = ':';\n            Parse(new Text(text), this, TextState, node);\n        }\n\n        /// <summary>\n        /// A parser state is initialized with an array of cases which\n        /// represent the state transitions. A state transition is chosen if\n        /// its specified regular expression is the first one (closest to the\n        /// current position) that matches. The specified function is\n        /// performed when the transition is chosen, and the function needs\n        /// to return the next state. If the 'null' state is returned, or the\n        /// whole input is consumed, the parsing function that performs all\n        /// transitions terminates. Since recursive descent also calls this\n        /// parsing function, returning the 'null' state also signals return\n        /// from recursive descent.\n        /// </summary>\n        public static readonly State<XmlParser, XmlItem> TextState\n                            = new State<XmlParser, XmlItem>(new[] {\n                new Case<XmlParser, XmlItem>(@\"<\\?xml\", (p, n) =>\n                    {   if (!(n is XmlDoc))\n                        {\n                            p.Skip(1);\n                            throw new ParserException<XmlParser>(p, \"illegal character\");\n                        }\n                        p.Skip(); p.SeenName = true; p.SeenSlash = false;\n                        return TagState; }),\n                new Case<XmlParser, XmlItem>(@\"<!DOCTYPE\", (p, n) =>\n                    { n.Add(p.GetToEndOf('>')); return TextState; }),\n                new Case<XmlParser, XmlItem>(@\"<!--\", (p, n) =>\n                    { p.SkipToEndOf(\"-->\"); return TextState; }),\n                new Case<XmlParser, XmlItem>(@\"<\", (p, n) =>\n                    { p.Skip(); p.SeenName = p.SeenSlash = false;\n                        return TagState; }),\n                new Case<XmlParser, XmlItem>(@\"&\", (p, n) =>\n                    { n.Add(p.GetToEndOf(';')); return TextState; }),\n            },\n            // If the following action is specified, all cases are search\n            // operations that skip text which is supplied to the action.\n            // In the Xml case, this is used to add the text between xml\n            // tags to the node.\n            (p, n, t) =>  { if (p.PreserveWhiteSpace || !t.IsWhiteSpace) n.Add(t); }\n        );\n\n        public static readonly Rx SymbolRx = new Rx(@\"[A-Za-z_][0-9A-Za-z_]*\");\n\n        public static readonly State<XmlParser, XmlItem> TagState = new State<XmlParser, XmlItem>(new[] {\n                new Case<XmlParser, XmlItem>(SymbolRx, (p, n) =>\n                    {\n                        var namePos = p.Pos;\n                        Text nameText;\n                        if (p.SimpleNames)\n                            nameText = p.Get();\n                        else\n                        {\n                            p.Skip();\n                            while (p.TrySkip(p.Separator))\n                                p.Skip(SymbolRx);\n                            nameText = p.GetFrom(namePos);\n                        }\n                        if (p.EndOfText)\n                            throw new ParserException<XmlParser>(p,\n                                        \"end of file after tag name\");\n                        var name = Symbol.Create(nameText.ToString());\n                        if (p.SeenName) // its an attribute\n                        {\n                            if (namePos != p.LastWhiteSpace)\n                            {\n                                p.Pos = namePos; // adjust for error msg\n                                throw new ParserException<XmlParser>(p,\n                                            \"missing required whitespace\");\n                            }\n                            p.SkipWhiteSpace();\n                            if (!p.TryGet('='))\n                                throw new ParserException<XmlParser>(p,\n                                            \"tag attribute missing '='\");\n                            p.SkipWhiteSpace();\n                            var quote = p.Peek;\n                            if (quote != '\"' && quote != '\\'')\n                                throw new ParserException<XmlParser>(p,\n                                            \"tag attribute not quoted\");\n                            p.Skip(1);  // skip quote\n                            var value = p.GetToStartOf(quote);\n                            p.Skip();   // skip quote\n                            n.AttList.Add(new XmlAtt(nameText, value));\n                            return TagState;\n                        }\n                        p.SeenName = true;\n                        if (n.Name == null)\n                        {\n                            n.Name = name;\n                            return TagState;\n                        }\n                        if (p.SeenSlash)\n                        {\n                            if (name != n.Name)\n                                throw new ParserException<XmlParser>(p,\n                                            \"ending tag does not match\");\n                            return TagState;\n                        }\n                        var subNode = new XmlItem(name);    // node to parse into\n                        Parse(p, TagState, subNode);        // recurse to parse xml-tree\n                        n.Add(subNode);                     // add parsed node\n                        return TextState;\n                    }),\n                new Case<XmlParser, XmlItem>(@\"\\?>\", (p, n) =>\n                    {\n                        if (!(n is XmlDoc))\n                            throw new ParserException<XmlParser>(p,  \"illegal character\");\n                        p.Skip();\n                        return TextState;\n                    }),\n                new Case<XmlParser, XmlItem>(@\">\", (p, n) =>\n                    {\n                        if (p.SeenSlash)\n                        {\n                            if (!p.SeenName)\n                                throw new ParserException<XmlParser>(p,  \"ending tag without name\");\n                            p.Skip();\n                            return null; // no next state == recursion end\n                        }\n                        p.Skip();\n                        return TextState;\n                    }),\n                new Case<XmlParser, XmlItem>(@\"/\", (p, n) =>\n                    {\n                        if (p.SeenSlash)\n                            throw new ParserException<XmlParser>(p, \"second slash in tag\");\n                        p.SeenSlash = true;\n                        p.Skip();\n                        return TagState;\n                    }),\n                // If a state has a default case, all cases represent\n                // non-searching patterns, that need to match at the\n                // start of the non-consumed input. If non of the other\n                // cases match at this point, the default case is taken.\n                // In the xml case the state inside tags is non-searching,\n                // and its default case handles white space and illegal\n                // chraracters insided tags.\n                new Case<XmlParser, XmlItem>((p, n) =>  // default used for eating white space\n                    {   \n                        p.SkipWhiteSpaceAndCheckProgress(); return TagState;\n                    }),\n            });\n    }\n\n    #endregion\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/XmlReadingCoder.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Xml.Linq;\n\nnamespace Aardvark.Base.Coder\n{\n    public partial class NewXmlReadingCoder\n        : BaseReadingCoder, IReadingCoder, IDisposable\n    {\n        private readonly Stack<State> m_stateStack;\n        private State m_state;\n        private readonly int m_coderVersion;\n        private readonly Stream m_stream;\n        private readonly bool m_disposeStream;\n        private string m_fileName;\n\n        #region Constructors\n\n        public NewXmlReadingCoder(XmlDoc doc)\n            : base()\n        {\n            m_stateStack = new Stack<State>();\n            m_state.Item = doc.FirstSub<XmlItem>();\n            if (m_state.Item == null || m_state.Item.Name != AardvarkSymbol)\n                throw new InvalidOperationException(\"could not read file as xml\");\n            m_state.Index = 0;\n            m_coderVersion = m_state.Item.Attribute(VersionSymbol).ParseInt();\n            if (m_coderVersion < 0\n                || m_coderVersion > c_coderVersion)\n                throw new InvalidOperationException(\n                        \"attempted read on an Aardvark file with an \"\n                        + \"unsupported coder version\");\n            m_disposeStream = false;\n        }\n\n        private static XmlDoc XmlFromStream(Stream stream)\n        {\n            XmlDoc root = new XmlDoc();\n            using (var reader = new StreamReader(stream, Encoding.UTF8))\n            {\n                new XmlParser().Parse(reader.ReadToEnd(), root);\n            }\n            return root;\n        }\n\n        public NewXmlReadingCoder(Stream stream)\n            : this(XmlFromStream(stream))\n        {\n            m_stream = stream;\n        }\n\n        public NewXmlReadingCoder(string fileName)\n            : this(File.Open(fileName, FileMode.Open))\n        {\n            m_fileName = fileName;\n            m_disposeStream = true;\n        }\n\n        #endregion\n\n        private struct State\n        {\n            public XmlItem Item;\n            public int Index;\n\n            public State(XmlItem node, int index)\n            {\n                Item = node; Index = index;\n            }\n\n            public readonly bool Valid { get { return Index >= 0; } }\n\n            public void Advance()\n            {\n                Index = Item.NextSubIndex<XmlItem>(Index);\n            }\n\n            public readonly XmlItem Current\n            {\n                get { return Item[Index] as XmlItem; }\n            }\n        }\n\n        #region ICoder Members\n\n        public string FileName\n        {\n            get { return m_fileName; }\n            set { m_fileName = value; }\n        }\n\n        public int CoderVersion { get { return m_coderVersion; } }\n\n        public int StreamVersion { get { return m_version; } }\n\n        public int MemoryVersion { get { return m_typeInfoStack.Peek().Version; } }\n\n        internal bool TryGetTypeInfo(string name, out TypeInfo ti)\n        {\n            if (m_typeInfoOfName.TryGetValue(name, out ti)) return true;\n            return TypeInfo.OfXmlName.TryGetValue(name, out ti);\n        }\n\n        public void Code(ref object obj)\n        {\n            // if (m_state.Enumerator.Current == null) return;\n\n            var typeName = m_state.Current.Name.ToString();\n            TypeInfo newTypeInfo = null;\n            TypeInfo typeInfo;\n\n            if (TryGetTypeInfo(typeName, out typeInfo))\n            {\n                if (typeInfo.Type == typeof(TypeCoder.Null))\n                {\n                    obj = null;\n                    m_state.Advance();\n                    return;\n                }\n                if (typeInfo.Type == typeof(TypeCoder.Reference))\n                {\n                    if ((typeInfo.Options & TypeInfo.Option.Active) != 0)\n                    {\n                        int num = m_state.Current.Attribute(NumSymbol).ParseInt();\n                        obj = m_refs[num];\n                        m_state.Advance();\n                        return;\n                    }\n                    else\n                        throw new Exception(\n                            \"cannot decode multiply referenced object \"\n                            + \"- change by configuring coder with \"\n                            + \"\\\"coder.Add(TypeCoder.Default.Reference);\\\"\");\n                }\n            }\n            else\n            {\n                if (typeName == \"object\")\n                {\n                    typeName = m_state.Current.Attribute(TypeSymbol).ToString();\n                    if (!TypeInfo.TryGetOfFullName(typeName, out typeInfo))\n                        typeInfo = new TypeInfo(typeName, Type.GetType(typeName),\n                                    TypeInfo.Option.Size | TypeInfo.Option.Version);\n                    if (typeInfo.Type == null)\n                    {\n                        Report.Warn(\"skipping unkown object of type \\\"\"\n                                    + typeName + '\"');\n                    }\n                    else\n                    {\n                        if ((m_debugMode & CoderDebugMode.ReportQualifiedNames) != 0)\n                            Report.Line(\"qualified name \\\"{0}\\\"\", typeName);\n                    }\n                }\n                else\n                {\n                    if (typeName == \"null\")\n                        throw new Exception(\"cannot decode null object \"\n                            + \"- change by configuring coder with \"\n                            + \"\\\"coder.Add(TypeCoder.Default.Null);\\\"\");\n                    Report.Warn(\"skipping unknown object \\\"\" + typeName + '\"');\n                    typeInfo = new TypeInfo(typeName, null);\n                }\n            }\n\n            if ((typeInfo.Options & TypeInfo.Option.Version) != 0)\n            {\n                m_versionStack.Push(m_version);\n                var attribute = m_state.Current.Attribute(VersionSymbol);\n                m_version = attribute != default(Text) ? attribute.ParseInt() : 0;\n                if (m_version < typeInfo.Version)\n                {\n                    TypeInfo oldTypeInfo;\n                    if (typeInfo.VersionMap.TryGetValue(m_version, out oldTypeInfo))\n                    {\n                        newTypeInfo = typeInfo; typeInfo = oldTypeInfo;\n                    }\n                }\n            }\n\n            m_stateStack.Push(m_state);\n            m_state = new State(m_state.Current, 0);\n\n            if (typeInfo.Type != null)\n            {\n                if (!TypeCoder.ReadPrimitive(this, typeInfo.Type, ref obj))\n                {\n                    if ((typeInfo.Options & TypeInfo.Option.Ignore) != 0)\n                    {\n                        obj = null;\n                    }\n                    else\n                    {\n                        var codedVersion = m_version;\n\n                        m_typeInfoStack.Push(typeInfo);\n\n                        if (typeInfo.Creator != null)\n                            obj = typeInfo.Creator();\n                        else\n                            obj = FastObjectFactory.ObjectFactory(typeInfo.Type)();\n\n                        if (m_doRefs) m_refs.Add(obj);\n\n                        var fcobj = obj as IFieldCodeable;\n                        if (fcobj != null)\n                        {\n                            CodeFields(typeInfo.Type, codedVersion, fcobj);\n                            var tmobj = obj as ITypedMap;\n                            if (tmobj != null) CodeFields(typeInfo.Type, tmobj);\n                        }\n                        else\n                        {\n                            Report.Warn(\"skipping uncodeable object of type \\\"\"\n                                        + typeInfo.Name + '\"');\n                        }\n\n                        var aobj = obj as IAwakeable;\n                        if (aobj != null) aobj.Awake(codedVersion);\n\n                        m_typeInfoStack.Pop();\n                    }\n                }\n            }\n\n            m_state = m_stateStack.Pop();\n\n            if ((typeInfo.Options & TypeInfo.Option.Version) != 0)\n            {\n                m_version = m_versionStack.Pop();\n                if (obj != null && newTypeInfo != null)\n                {\n                    var source = new Convertible(typeInfo.Name, obj);\n                    var target = new Convertible(newTypeInfo.Name, null);\n                    source.ConvertInto(target);\n                    obj = target.Data;\n                }\n            }\n            m_state.Advance();\n        }\n\n        private void CodeFields(Type type, int version, IFieldCodeable obj)\n        {\n            FieldCoderMap fcm = FieldCoderMap.Get(m_coderVersion, type, version, obj);\n            while (m_state.Valid)\n            {\n                string fieldName = m_state.Current.Name.ToString();\n\n                Action<ICoder, object> code;\n\n                if (fcm.TryGetValue(fieldName, out code))\n                {\n                    m_stateStack.Push(m_state);\n                    m_state = new State(m_state.Current, 0);\n                    code(this, obj);\n                    m_state = m_stateStack.Pop();\n                }\n                else\n                {\n                    if (obj is ITypedMap) return;\n                    Report.Warn(\"skipping unknown field \\\"\"\n                                + fieldName + '\"');\n                }\n                m_state.Advance();\n            }\n        }\n\n        private void CodeFields(Type type, ITypedMap obj)\n        {\n            TypeOfString fieldTypeMap = FieldTypeMap.Get(type, obj);\n\n            while (m_state.Valid)\n            {\n                string fieldName = m_state.Current.Name.ToString();\n                Type fieldType;\n                string fieldTypeName = null;\n                TypeInfo typeInfo;\n\n                if (fieldTypeMap.TryGetValue(fieldName, out fieldType))\n                {\n                    if (TryGetTypeInfo(fieldName, out typeInfo))\n                        fieldTypeName = typeInfo.Name;\n                }\n                else\n                {\n                    fieldTypeName = m_state.Current.Attribute(TypeSymbol).ToString();\n                    if (TryGetTypeInfo(fieldTypeName, out typeInfo))\n                        fieldType = typeInfo.Type;\n                    else\n                    {\n                        fieldType = Type.GetType(fieldTypeName);\n                        if (fieldName == \"object\")\n                        {\n                            fieldTypeName = fieldType.Name;\n                            fieldName = fieldType.Name;\n                        }\n                    }\n                }\n\n                if (fieldTypeName != fieldName || TypeCoder.IsDirectlyCodeable(fieldType))\n                {\n                    m_stateStack.Push(m_state);\n                    m_state = new State(m_state.Current, 0);\n                }\n                object value = null;\n                TypeCoder.Read(this, fieldType, ref value);\n                obj[fieldName] = value;\n                if (fieldTypeName != fieldName || TypeCoder.IsDirectlyCodeable(fieldType))\n                {\n                    m_state = m_stateStack.Pop();\n                    m_state.Advance();\n                }\n            }\n        }\n\n        public void CodeT<T>(ref T obj)\n        {\n            object o = default(T);\n            var type = typeof(T);\n            if (type == typeof(Array))\n                Code(ref o);\n            else\n                TypeCoder.Read(this, type, ref o);\n            obj = (T)o;\n        }\n\n        private bool CodeNull<T>(ref T value) where T : class\n        {\n            if (m_coderVersion > 0)\n            {\n                XmlItem item;\n                if (m_state.Current.SubList.Count == 1\n                    && (item = (m_state.Current[0] as XmlItem)) != null\n                    && item.Name == NullSymbol)\n                {\n                    value = null;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public int CodeCount<T>(ref T value, Func<int, T> creator) where T : class\n        {\n            if (m_coderVersion < 2)\n            {\n                var text = m_state.Current.FirstSub<XmlDirectText>();\n                if (text != null && text.Text == \"null\")\n                {\n                    value = null; return -1;\n                }\n            }\n            var item = m_state.Current.FirstSub<XmlItem>();\n            if (item != null)\n            {\n                if (item.Name == NullSymbol)\n                {\n                    value = null; return -1;\n                }\n                if (item.Name == RefSymbol)\n                {\n                    int refNum = item.Attribute(NumSymbol).ParseInt();\n                    if (refNum >= m_refs.Count)\n                    {\n                        Report.Warn(\"skipping invalid reference to \" + refNum);\n                        value = null;\n                    }\n                    else\n                        value = (T)m_refs[refNum];\n                    return -2;\n                }\n            }\n\n            int count = 0;\n            Text attribute = m_state.Current.Attribute(CountSymbol);\n            if (attribute != default(Text))\n                count = attribute.ParseInt();\n            value = creator(count);\n            if (m_doRefs) m_refs.Add(value);\n            return count;\n        }\n\n        private int CodeCount<T>(ref T[] array)\n        {\n            return CodeCount(ref array, n => new T[n]);\n        }\n\n        private int CodeCount<T>(ref List<T> list)\n        {\n            return CodeCount(ref list, n => new List<T>(n));\n        }\n\n        public void CodeTArray<T>(ref T[] value)\n        {\n            int count = CodeCount(ref value, n => new T[n]);\n            if (count < 1) return;\n            int i = 0;\n            while (m_state.Valid)\n            {\n                object o = default(T); Code(ref o); value[i++] = (T)o;\n            }\n        }\n\n        public void CodeList_of_T_<T>(ref List<T> value)\n        {\n            int count = CodeCount(ref value, n => new List<T>(n));\n            if (count < 1) return;\n            while (m_state.Valid)\n            {\n                object o = default(T); Code(ref o); value.Add((T)o);\n            }\n        }\n\n        public void CodeHashSet_of_T_<T>(ref HashSet<T> value)\n        {\n            int count = CodeCount(ref value, n => new HashSet<T>());\n            if (count < 1) return;\n            while (m_state.Valid)\n            {\n                object o = default(T); Code(ref o); value.Add((T)o);\n            }\n        }\n\n        public void Code(Type t, ref object o)\n        {\n            TypeCoder.Read(this, t, ref o);\n        }\n\n        public void Code(Type t, ref Array value)\n        {\n            int count = CodeCount(ref value, n => Array.CreateInstance(t, n));\n            if (count < 1) return;\n            int i = 0;\n            while (m_state.Valid)\n            {\n                object o = null; Code(ref o); value.SetValue(o, i++);\n            }\n        }\n\n        public void Code(Type t, ref IList value)\n        {\n            int count = CodeCount(ref value,\n                                  n => (IList)Activator.CreateInstance(t, n));\n            if (count < 1) return;\n            while (m_state.Valid)\n            {\n                object o = null; Code(ref o); value.Add(o);\n            }\n        }\n\n        public void Code(Type t, ref IDictionary dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref ICountableDict dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref ICountableDictSet dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayVector value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayMatrix value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayVolume value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayTensor4 value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayTensorN value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeHashSet(Type t, ref object o)\n        {\n            throw new NotImplementedException(\"only possible whith a non-generic ISet interface)\");\n        }\n\n        public void CodeEnum(Type t, ref object value)\n        {\n            throw new NotImplementedException();\n        }\n        \n        #endregion\n\n        #region Code Primitives\n\n        private Text CurrentText()\n        {\n            return m_state.Current.FirstSub<XmlDirectText>().Text;\n        }\n\n        public void CodeBool(ref bool v) { throw new NotImplementedException(); }\n        public void CodeByte(ref byte v) { v = CurrentText().ParseByte(); }\n        public void CodeSByte(ref sbyte v) { v = CurrentText().ParseSByte(); }\n        public void CodeShort(ref short v) { v = CurrentText().ParseShort(); }\n        public void CodeUShort(ref ushort v) { v = CurrentText().ParseUShort(); }\n        public void CodeInt(ref int v) { v = CurrentText().ParseInt(); }\n        public void CodeUInt(ref uint v) { v = CurrentText().ParseUInt(); }\n        public void CodeLong(ref long v) { v = CurrentText().ParseLong(); }\n        public void CodeULong(ref ulong v) { v = CurrentText().ParseULong(); }\n        public void CodeFloat(ref float v) { v = CurrentText().ParseFloat(); }\n        public void CodeDouble(ref double v) { v = CurrentText().ParseDouble(); }\n\n        public void CodeChar(ref char v) { throw new NotImplementedException(); }\n\n        public void CodeString(ref string v) { v = CurrentText().ToString(); }\n\n        public void CodeType(ref Type value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeGuid(ref Guid v) { throw new NotImplementedException(); }\n\n        public void CodeSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodeGuidSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodePositiveSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodeIntSet(ref IntSet set) { throw new NotImplementedException(); }\n\n        public void CodeSymbolSet(ref SymbolSet set) { throw new NotImplementedException(); }\n\n        public void CodeFraction(ref Fraction v) { throw new NotImplementedException(); }\n\n        public void CodeStructArray<T>(ref T[] a) where T : struct\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeStructList<T>(ref List<T> l) where T : struct\n        {\n            throw new NotImplementedException();\n        }\n\n        internal void CodeArray<T>(\n                ref T[] value, Func<string, IEnumerable<string>> splitter,\n                Func<string, T> creator)\n        {\n            throw new NotImplementedException();\n        }\n\n        internal void CodeList<T>(ref List<T> value,\n                Func<string, IEnumerable<string>> splitter, Func<string, T> creator)\n        {\n            throw new NotImplementedException();\n        }\n\n        internal void CodeArray<T>(ref T[] v, Func<string, T> fromString)\n        {\n            throw new NotImplementedException();\n        }\n\n        internal void CodeList<T>(ref List<T> v, Func<string, T> fromString)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeBoolArray(ref bool[] v) { throw new NotImplementedException(); }\n        public void CodeByteArray(ref byte[] v) { throw new NotImplementedException(); }\n        public void CodeSByteArray(ref sbyte[] v) { throw new NotImplementedException(); }\n        public void CodeShortArray(ref short[] v) { throw new NotImplementedException(); }\n        public void CodeUShortArray(ref ushort[] v) { throw new NotImplementedException(); }\n        public void CodeIntArray(ref int[] v) { throw new NotImplementedException(); }\n        public void CodeUIntArray(ref uint[] v) { throw new NotImplementedException(); }\n        public void CodeLongArray(ref long[] v) { throw new NotImplementedException(); }\n        public void CodeULongArray(ref ulong[] v) { throw new NotImplementedException(); }\n\n        public void CodeFloatArray(ref float[] v)\n        {\n            throw new NotImplementedException();\n        }\n        public void CodeDoubleArray(ref double[] v)\n        {\n            throw new NotImplementedException();\n        }\n\n        // private static readonly char[] s_charSeparators = new[] { ',', ' ' };\n\n        public void CodeCharArray(ref char[] v)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeStringArray(ref string[] value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeTypeArray(ref Type[] value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeGuidArray(ref Guid[] v) { throw new NotImplementedException(); }\n\n        public void CodeSymbolArray(ref Symbol[] v) { throw new NotImplementedException(); }\n\n        public void CodeFractionArray(ref Fraction[] v) { throw new NotImplementedException(); }\n\n        public void Code(ref List<object> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_Bool_(ref List<bool> v) { throw new NotImplementedException(); }\n        public void CodeList_of_Byte_(ref List<byte> v) { throw new NotImplementedException(); }\n        public void CodeList_of_SByte_(ref List<sbyte> v) { throw new NotImplementedException(); }\n        public void CodeList_of_Short_(ref List<short> v) { throw new NotImplementedException(); }\n        public void CodeList_of_UShort_(ref List<ushort> v) { throw new NotImplementedException(); }\n        public void CodeList_of_Int_(ref List<int> v) { throw new NotImplementedException(); }\n        public void CodeList_of_UInt_(ref List<uint> v) { throw new NotImplementedException(); }\n        public void CodeList_of_Long_(ref List<long> v) { throw new NotImplementedException(); }\n        public void CodeList_of_ULong_(ref List<ulong> v) { throw new NotImplementedException(); }\n\n        public void CodeList_of_Float_(ref List<float> v)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_Double_(ref List<double> v)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_Char_(ref List<char> v)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_String_(ref List<string> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_Type_(ref List<Type> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_Guid_(ref List<Guid> v) { throw new NotImplementedException(); }\n        public void CodeList_of_Symbol_(ref List<Symbol> v) { throw new NotImplementedException(); }\n        public void CodeList_of_Fraction_(ref List<Fraction> v) { throw new NotImplementedException(); }\n\n        #endregion\n\n        #region IDisposable Members\n\n        public void Dispose()\n        {\n            if (m_disposeStream)\n                m_stream.Dispose();\n        }\n\n        #endregion    \n    }\n\n    public partial class XmlReadingCoder\n        : BaseReadingCoder, IReadingCoder, IDisposable\n    {\n        private readonly Stack<State> m_stateStack;\n        private State m_state;\n        private readonly Stream m_stream;\n        private string m_fileName;\n        private readonly int m_coderVersion;\n        private readonly bool m_disposeStream = false;\n\n        #region Constructors\n\n        public XmlReadingCoder(XElement container) : base()\n        {\n            m_stateStack = new Stack<State>();\n            m_state.Element = container;\n            m_state.Enumerator = container.Elements().GetEnumerator();\n            m_fileName = null;\n            m_stream = null;\n            XAttribute attribute = container.Attribute(\"version\");\n            m_coderVersion = attribute != null ? int.Parse(attribute.Value) : 0;\n            if (m_coderVersion < 0\n                || m_coderVersion > c_coderVersion)\n                throw new InvalidOperationException(\n                        \"attempted read on an Aardvark file with an \"\n                        + \"unsupported coder version\");\n        }\n\n        private static XElement XElementFromStream(Stream stream)\n        {\n            XElement root;\n            using (var reader = new StreamReader(stream, Encoding.UTF8))\n                root = XElement.Load(reader, LoadOptions.PreserveWhitespace);\n            return root;\n        }\n\n        public XmlReadingCoder(Stream stream)\n            : this(XElementFromStream(stream))\n        {\n            m_stream = stream;\n        }\n\n        public XmlReadingCoder(string fileName)\n            : this(File.Open(fileName, FileMode.Open))\n        {\n            m_fileName = fileName;\n            m_disposeStream = true;\n        }\n\n        #endregion\n\n        #region Private Data Structure\n\n        struct State\n        {\n            IEnumerator<XElement> m_enumerator;\n            XElement m_element;\n            bool m_valid;\n\n            public bool Valid\n            {\n                readonly get { return m_valid; }\n                set { m_valid = value; }\n            }\n            public XElement Element\n            {\n                readonly get { return m_element; }\n                set { m_element = value; }\n            }\n            public IEnumerator<XElement> Enumerator\n            {\n                readonly get { return m_enumerator; }\n                set\n                {\n                    m_enumerator = value;\n                    m_valid = m_enumerator.MoveNext();\n                }\n            }\n            public void Advance()\n            {\n                m_valid = m_enumerator.MoveNext();\n            }\n        }\n\n        #endregion\n\n        #region Properties\n\n        public XElement ContainerElement\n        {\n            get { return m_state.Element; }\n        }\n\n        #endregion\n\n        #region Static Convenience Functions\n\n        public static object ReadFirstObject(string fileName)\n        {\n            object first = null;\n            using (var coder = new XmlReadingCoder(fileName))\n                coder.Code(ref first);\n            return first;\n        }\n\n        public static object ReadFirstObject(Stream stream)\n        {\n            object first = null;\n            using (var coder = new XmlReadingCoder(stream))\n                coder.Code(ref first);\n            return first;\n        }\n\n        public static T ReadFirst<T>(string fileName)\n        {\n            T first = default(T);\n            using (var coder = new XmlReadingCoder(fileName))\n                coder.CodeT(ref first);\n            return first;\n        }\n\n        public static T ReadFirst<T>(Stream stream)\n        {\n            T first = default(T);\n            using (var coder = new XmlReadingCoder(stream))\n                coder.CodeT(ref first);\n            return first;\n        }\n\n        #endregion\n\n        #region Private Convenience Functions\n\n        private string CurrentValue()\n        {\n            return m_state.Element.Value;\n        }\n\n        #endregion\n\n        #region ICoder Members\n\n        public string FileName \n        { \n            get { return m_fileName; }\n            set { m_fileName = value; }\n        }\n\n        public int CoderVersion { get { return m_coderVersion; } }\n\n        public int StreamVersion { get { return m_version; } }\n\n        public int MemoryVersion { get { return m_typeInfoStack.Peek().Version; } }\n        \n        internal bool TryGetTypeInfo(string name, out TypeInfo ti)\n        {\n            if (m_typeInfoOfName.TryGetValue(name, out ti)) return true;\n            return TypeInfo.OfXmlName.TryGetValue(name, out ti);\n        }\n\n        public void Code(ref object obj)\n        {\n            if (m_state.Enumerator.Current == null) return;\n\n            m_state.Element = m_state.Enumerator.Current;\n            var typeName = m_state.Element.Name.ToString();\n            TypeInfo newTypeInfo = null;\n            TypeInfo typeInfo;\n\n            if (TryGetTypeInfo(typeName, out typeInfo))\n            {\n                if (typeInfo.Type == typeof(TypeCoder.Null))\n                {\n                    obj = null;\n                    m_state.Advance();\n                    return;\n                }\n                if (typeInfo.Type == typeof(TypeCoder.Reference))\n                {\n                    if ((typeInfo.Options & TypeInfo.Option.Active) != 0)\n                    {\n                        int num = m_state.Element.Attribute(\"num\").Value.ToInt();\n                        obj = m_refs[num];\n                        m_state.Advance();\n                        return;\n                    }\n                    else\n                        throw new Exception(\n                            \"cannot decode multiply referenced object \"\n                            + \"- change by configuring coder with \"\n                            + \"\\\"coder.Add(TypeCoder.Default.Reference);\\\"\");\n                }\n            }\n            else\n            {\n                if (typeName == \"object\")\n                {\n                    typeName = m_state.Element.Attribute(\"type\").Value;\n                    if (!TypeInfo.TryGetOfFullName(typeName, out typeInfo))\n                        typeInfo = new TypeInfo(typeName, Type.GetType(typeName),\n                                    TypeInfo.Option.Size | TypeInfo.Option.Version);\n                    if (typeInfo.Type == null)\n                    {\n                        Report.Warn(\"skipping unkown object of type \\\"\"\n                                    + typeName + '\"');\n                    }\n                    else\n                    {\n                        if ((m_debugMode & CoderDebugMode.ReportQualifiedNames) != 0)\n                            Report.Line(\"qualified name \\\"{0}\\\"\", typeName);\n                    }\n                }\n                else\n                {\n                    if (typeName == \"null\")\n                        throw new Exception(\"cannot decode null object \"\n                            + \"- change by configuring coder with \"\n                            + \"\\\"coder.Add(TypeCoder.Default.Null);\\\"\");\n                    Report.Warn(\"skipping unknown object \\\"\" + typeName + '\"');\n                    typeInfo = new TypeInfo(typeName, null);\n                }\n            }\n\n            if ((typeInfo.Options & TypeInfo.Option.Version) != 0)\n            {\n                m_versionStack.Push(m_version);\n                XAttribute attribute = m_state.Element.Attribute(\"version\");\n                m_version = attribute != null ? int.Parse(attribute.Value) : 0;\n                if (m_version < typeInfo.Version)\n                {\n                    TypeInfo oldTypeInfo;\n                    if (typeInfo.VersionMap.TryGetValue(m_version, out oldTypeInfo))\n                    {\n                        newTypeInfo = typeInfo; typeInfo = oldTypeInfo;\n                    }\n                }\n            }\n\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n\n            if (typeInfo.Type != null)\n            {\n                if (! TypeCoder.ReadPrimitive(this, typeInfo.Type, ref obj))\n                {\n                    if ((typeInfo.Options & TypeInfo.Option.Ignore) != 0)\n                    {\n                        obj = null;\n                    }\n                    else\n                    {\n                        int codedVersion = m_version;\n\n                        m_typeInfoStack.Push(typeInfo);\n\n                        if (typeInfo.Creator != null)\n                            obj = typeInfo.Creator();\n                        else\n                            obj = FastObjectFactory.ObjectFactory(typeInfo.Type)();\n\n                        if (m_doRefs) m_refs.Add(obj);\n\n                        var fcobj = obj as IFieldCodeable;\n                        if (fcobj != null)\n                        {\n                            CodeFields(typeInfo.Type, m_version, fcobj);\n                            var tmobj = obj as ITypedMap;\n                            if (tmobj != null) CodeFields(typeInfo.Type, tmobj);\n                        }\n                        else\n                        {\n                            Report.Warn(\"skipping uncodeable object of type \\\"\"\n                                        + typeInfo.Name + '\"');\n                        }\n\n                        var aobj = obj as IAwakeable;\n                        if (aobj != null) aobj.Awake(codedVersion);\n\n                        m_typeInfoStack.Pop();\n                    }\n                }\n            }\n\n            m_state = m_stateStack.Pop();\n\n            if ((typeInfo.Options & TypeInfo.Option.Version) != 0)\n            {\n                m_version = m_versionStack.Pop();\n                if (obj != null && newTypeInfo != null)\n                {\n                    var source = new Convertible(typeInfo.Name, obj);\n                    var target = new Convertible(newTypeInfo.Name, null);\n                    source.ConvertInto(target);\n                    obj = target.Data;\n                }\n            }\n            m_state.Advance();\n        }\n\n        private void CodeFields(Type type, int version, IFieldCodeable obj)\n        {\n            FieldCoderMap fcm = FieldCoderMap.Get(m_coderVersion, type, version, obj);\n            while (m_state.Valid)\n            {\n                m_state.Element = m_state.Enumerator.Current;\n                string fieldName = m_state.Element.Name.ToString();\n\n                Action<ICoder, object> code;\n\n                if (fcm.TryGetValue(fieldName, out code))\n                {\n                    m_stateStack.Push(m_state);\n                    m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n                    code(this, obj);\n                    m_state = m_stateStack.Pop();\n                }\n                else\n                {\n                    if (obj is ITypedMap) return;\n                    Report.Warn(\"skipping unknown field \\\"\"\n                                + fieldName + '\"');\n                }\n                m_state.Advance();\n            }\n        }\n\n        private void CodeFields(Type type, ITypedMap obj)\n        {\n            TypeOfString fieldTypeMap = FieldTypeMap.Get(type, obj);\n\n            while (m_state.Valid)\n            {\n                m_state.Element = m_state.Enumerator.Current;\n                string fieldName = m_state.Element.Name.ToString();\n                Type fieldType;\n                string fieldTypeName = null;\n                TypeInfo typeInfo;\n\n                if (fieldTypeMap.TryGetValue(fieldName, out fieldType))\n                {\n                    if (TryGetTypeInfo(fieldName, out typeInfo))\n                        fieldTypeName = typeInfo.Name;\n                }\n                else\n                {\n                    fieldTypeName = m_state.Element.Attribute(\"type\").Value.ToString();\n                    if (TryGetTypeInfo(fieldTypeName, out typeInfo))\n                        fieldType = typeInfo.Type;\n                    else\n                    {\n                        fieldType = Type.GetType(fieldTypeName);\n                        if (fieldName == \"object\")\n                        {\n                            fieldTypeName = fieldType.Name;\n                            fieldName = fieldType.Name;\n                        }\n                    }\n                }\n\n                if (fieldTypeName != fieldName || TypeCoder.IsDirectlyCodeable(fieldType))\n                {\n                    m_stateStack.Push(m_state);\n                    m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n                }\n                object value = null;\n                TypeCoder.Read(this, fieldType, ref value);\n                obj[fieldName] = value;\n                if (fieldTypeName != fieldName || TypeCoder.IsDirectlyCodeable(fieldType))\n                {\n                    m_state = m_stateStack.Pop();\n                    m_state.Advance();\n                }\n            }\n        }\n\n        public void CodeT<T>(ref T obj)\n        {\n            object o = default(T);\n            var type = typeof(T);\n            if (type == typeof(Array))\n                Code(ref o);\n            else\n                TypeCoder.Read(this, type, ref o);\n            obj = (T)o;\n        }\n\n        private bool CodeNull<T>(ref T value) where T : class\n        {\n            if (m_coderVersion > 0)\n            {\n                var subElements = m_state.Element.Elements();\n                if (subElements.Count() == 1 && subElements.First().Name == \"null\")\n                {\n                    value = null;\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public int CodeCount<T>(ref T value, Func<int, T> creator) where T : class\n        {\n            if (m_coderVersion < 2)\n            {\n                if (CurrentValue() == \"null\") { value = null; return -1; }\n            }\n            var subElements = m_state.Element.Elements();\n            if (subElements.Count() == 1)\n            {\n                var firstSubElement = subElements.First();\n                var name = firstSubElement.Name;\n                if (name == \"null\")\n                {\n                    value = null;\n                    return -1;\n                }\n                if (name == \"ref\")\n                {\n                    int refNum = firstSubElement.Attribute(\"num\").Value.ToInt();\n                    if (refNum >= m_refs.Count)\n                    {\n                        Report.Warn(\"skipping invalid reference to \" + refNum);\n                        value = null;\n                    }\n                    else\n                        value = (T)m_refs[refNum];\n                    return -2;\n                }\n            }\n            int count = 0;\n            XAttribute attribute = m_state.Element.Attribute(\"count\");\n            if (attribute != null)\n                count = int.Parse(attribute.Value);\n\n            value = creator(count);\n            if (m_doRefs) m_refs.Add(value);\n            return count;\n        }\n\n        private int CodeCount<T>(ref T[] array)\n        {\n            return CodeCount(ref array, n => new T[n]);\n        }\n\n        private int CodeCount<T>(ref List<T> list)\n        {\n            return CodeCount(ref list, n => new List<T>(n));\n        }\n\n        public void CodeTArray<T>(ref T[] value)\n        {\n            int count = CodeCount(ref value, n => new T[n]);\n            if (count < 1) return;\n            int i = 0;\n            while (m_state.Valid)\n            {\n                object o = default(T); Code(ref o); value[i++] = (T)o;\n            }\n        }\n\n        public void CodeList_of_T_<T>(ref List<T> value)\n        {\n            int count = CodeCount(ref value, n => new List<T>(n));\n            if (count < 1) return;\n            while (m_state.Valid)\n            {\n                object o = default(T); Code(ref o); value.Add((T)o);\n            }\n        }\n\n        public void CodeHashSet_of_T_<T>(ref HashSet<T> value)\n        {\n            int count = CodeCount(ref value, n => new HashSet<T>());\n            if (count < 1) return;\n            while (m_state.Valid)\n            {\n                object o = default(T); Code(ref o); value.Add((T)o);\n            }\n        }\n\n        public void Code(Type t, ref object o)\n        {\n            TypeCoder.Read(this, t, ref o);\n        }\n\n        public void Code(Type t, ref Array value)\n        {\n            int count = CodeCount(ref value, n => Array.CreateInstance(t, n));\n            if (count < 1) return;\n            int i = 0;\n            while (m_state.Valid)\n            {\n                object o = null; Code(ref o); value.SetValue(o, i++);\n            }\n        }\n\n        public void Code(Type t, ref IList value)\n        {\n            int count = CodeCount(ref value,\n                                  n => (IList)Activator.CreateInstance(t, n));\n            if (count < 1) return;\n            while (m_state.Valid)\n            {\n                object o = null; Code(ref o);  value.Add(o);\n            }\n        }\n\n        public void Code(Type t, ref IDictionary dict)\n        {\n            int count = CodeCount(ref dict, n => (IDictionary)Activator.CreateInstance(t));\n            if (count < 1) return;\n\n            Type[] subTypeArray = t.GetGenericArguments();\n\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n\n            while (m_state.Valid)\n            {\n                m_state.Element = m_state.Enumerator.Current;\n\n                m_stateStack.Push(m_state);\n                m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n                m_state.Element = m_state.Enumerator.Current;\n\n                object key = null;\n                TypeCoder.Read(this, subTypeArray[0], ref key);\n                m_state.Advance();\n\n                m_state.Element = m_state.Enumerator.Current;\n                object val = null;\n                if (!TypeCoder.ReadPrimitive(this, subTypeArray[1], ref val))\n                {\n                    m_stateStack.Push(m_state);\n                    m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n                    m_state.Element = m_state.Enumerator.Current;\n                    Code(ref val);\n                    m_state = m_stateStack.Pop();\n                }\n                m_state = m_stateStack.Pop();\n\n                m_state.Advance();\n\n                dict[key] = val;\n            }\n            m_state = m_stateStack.Pop();\n        }\n\n        public void Code(Type t, ref ICountableDict dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref ICountableDictSet dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        private T CodeTensorDim<T>()\n        {\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            T dim = default(T);\n            CodeT(ref dim);\n\n            m_state.Advance();\n            m_state.Element = m_state.Enumerator.Current;\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n\n            return dim;\n        }\n\n        public void Code(Type t, ref IArrayVector value)\n        {\n            value = (IArrayVector)Activator.CreateInstance(t);\n\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long length = 0L; CodeLong(ref length); value.Size = length;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long delta = 0L; CodeLong(ref delta); value.Delta = delta;\n\n            m_state = m_stateStack.Pop();\n            m_state = m_stateStack.Pop();\n        }\n\n        public void Code(Type t, ref IArrayMatrix value)\n        {\n            value = (IArrayMatrix)Activator.CreateInstance(t);\n\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            V2l length = default(V2l); CodeV2l(ref length); value.Size = length;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            V2l delta = default(V2l); CodeV2l(ref delta); value.Delta = delta;\n\n            m_state = m_stateStack.Pop();\n            m_state = m_stateStack.Pop();\n        }\n\n        public void Code(Type t, ref IArrayVolume value)\n        {\n            value = (IArrayVolume)Activator.CreateInstance(t);\n\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            V3l length = default(V3l); CodeV3l(ref length); value.Size = length;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            V3l delta = default(V3l); CodeV3l(ref delta); value.Delta = delta;\n\n            m_state = m_stateStack.Pop();\n            m_state = m_stateStack.Pop();\n        }\n\n        public void Code(Type t, ref IArrayTensor4 value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayTensorN value)\n        {\n            value = (IArrayTensorN)Activator.CreateInstance(t);\n\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            Array array = null; Code(value.ArrayType, ref array); value.Array = array;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long origin = 0L; CodeLong(ref origin); value.Origin = origin;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long[] length = null; CodeLongArray(ref length); value.Size = length;\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long[] delta = null; CodeLongArray(ref delta); value.Delta = delta;\n\n            m_state = m_stateStack.Pop();\n            m_state = m_stateStack.Pop();\n        }\n\n        public void CodeHashSet(Type t, ref object o)\n        {\n            throw new NotImplementedException(\"only possible whith a non-generic ISet interface)\");\n        }\n\n        public void CodeEnum(Type t, ref object value)\n        {\n            value = Enum.Parse(t, CurrentValue(), true);\n        }\n\n        #endregion\n\n        #region Code Primitives\n\n        public void CodeBool(ref bool v) { v = bool.Parse(CurrentValue()); }\n        public void CodeByte(ref byte v) { v = byte.Parse(CurrentValue()); }\n        public void CodeSByte(ref sbyte v) { v = sbyte.Parse(CurrentValue()); }\n        public void CodeShort(ref short v) { v = short.Parse(CurrentValue()); }\n        public void CodeUShort(ref ushort v) { v = ushort.Parse(CurrentValue()); }\n        public void CodeInt(ref int v) { v = int.Parse(CurrentValue()); }\n        public void CodeUInt(ref uint v) { v = uint.Parse(CurrentValue()); }\n        public void CodeLong(ref long v) { v = long.Parse(CurrentValue()); }\n        public void CodeULong(ref ulong v) { v = ulong.Parse(CurrentValue()); }\n\n        public void CodeFloat(ref float value)\n        {\n            value = float.Parse(CurrentValue(), CultureInfo.InvariantCulture);\n        }\n\n        public void CodeDouble(ref double value)\n        {\n            value = double.Parse(CurrentValue(), CultureInfo.InvariantCulture);\n        }\n\n        public void CodeChar(ref char v) { v = Char.Parse(CurrentValue()); }\n\n        public void CodeString(ref string value)\n        {\n            if (CodeNull(ref value)) return;\n            value = CurrentValue();\n        }\n\n        public void CodeType(ref Type value)\n        {\n            var typeName = CurrentValue();\n            TypeInfo ti;\n            if (TryGetTypeInfo(typeName, out ti))\n                value = ti.Type;\n            else\n                value = Type.GetType(typeName);\n        }\n\n        public void CodeGuid(ref Guid v) { v = new Guid(CurrentValue()); }\n\n        public void CodeSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodeGuidSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodePositiveSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodeIntSet(ref IntSet set) { throw new NotImplementedException(); }\n\n        public void CodeSymbolSet(ref SymbolSet set) { throw new NotImplementedException(); }\n\n        public void CodeFraction(ref Fraction v) { v = Fraction.Parse(CurrentValue()); }\n\n        public void CodeStructArray<T>(ref T[] a) where T : struct\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeStructList<T>(ref List<T> l) where T : struct\n        {\n            throw new NotImplementedException();\n        }\n\n        private readonly Func<string, IEnumerable<string>> s_nestedBracketSplitter =\n            s => s.NestedBracketSplit(0);\n\n        internal void CodeArray<T>(\n                ref T[] value, Func<string, IEnumerable<string>> splitter,\n                Func<string, T> creator)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            var items = splitter(CurrentValue());\n            var v = value;\n            items.ForEach((s, i) => { v[i] = creator(s); });\n        }\n\n        internal void CodeList<T>(ref List<T> value,\n                Func<string, IEnumerable<string>> splitter, Func<string, T> creator)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            var items = splitter(CurrentValue());\n            var v = value;\n            items.ForEach(s => { v.Add(creator(s)); });\n        }\n\n        static readonly char[] s_itemSeparator = new[] { ',' };\n\n        internal void CodeArray<T>(ref T[] v, Func<string, T> fromString)\n        {\n            CodeArray(ref v, s => s.Split(s_itemSeparator), fromString);\n        }\n\n        internal void CodeList<T>(ref List<T> v, Func<string, T> fromString)\n        {\n            CodeList(ref v, s => s.Split(s_itemSeparator), fromString);\n        }\n\n        public void CodeBoolArray(ref bool[] v) { CodeArray(ref v, s => bool.Parse(s)); }\n        public void CodeByteArray(ref byte[] v) { CodeArray(ref v, s => byte.Parse(s)); }\n        public void CodeSByteArray(ref sbyte[] v) { CodeArray(ref v, s => sbyte.Parse(s)); }\n        public void CodeShortArray(ref short[] v) { CodeArray(ref v, s => short.Parse(s)); }\n        public void CodeUShortArray(ref ushort[] v) { CodeArray(ref v, s => ushort.Parse(s)); }\n        public void CodeIntArray(ref int[] v) { CodeArray(ref v, s => int.Parse(s)); }\n        public void CodeUIntArray(ref uint[] v) { CodeArray(ref v, s => uint.Parse(s)); }\n        public void CodeLongArray(ref long[] v) { CodeArray(ref v, s => long.Parse(s)); }\n        public void CodeULongArray(ref ulong[] v) { CodeArray(ref v, s => ulong.Parse(s)); }\n        public void CodeFloatArray(ref float[] v)\n        {\n            CodeArray(ref v, s => float.Parse(s, CultureInfo.InvariantCulture));\n        }\n        public void CodeDoubleArray(ref double[] v)\n        {\n            CodeArray(ref v, s => double.Parse(s, CultureInfo.InvariantCulture));\n        }\n\n        private static readonly char[] s_charSeparators = new[] { ',', ' ' };\n\n        public void CodeCharArray(ref char[] v)\n        {\n            CodeArray(ref v,\n                 s => s.Split(s_charSeparators,\n                              StringSplitOptions.RemoveEmptyEntries),\n                 s => char.Parse(s));\n        }\n\n        public void CodeStringArray(ref string[] value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n\n            int i = 0;\n            while (m_state.Valid)\n            {\n                value[i++] = m_state.Enumerator.Current.Value;\n                m_state.Advance();\n            }\n            m_state = m_stateStack.Pop();\n        }\n\n        public void CodeTypeArray(ref Type[] value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            string[] items = CurrentValue().Split(s_itemSeparator);\n            for (int i = 0; i < items.Length; i++)\n            {\n                var typeName = items[i];\n                TypeInfo ti;\n\n                if (TryGetTypeInfo(typeName, out ti))\n                    value[i] = ti.Type;\n                else\n                    value[i] = Type.GetType(typeName);\n            }\n        }\n\n        public void CodeGuidArray(ref Guid[] v) { CodeArray(ref v, s => new Guid(s)); }\n\n        public void CodeSymbolArray(ref Symbol[] v)\n        {\n            throw new NotImplementedException();\n        }        \n        \n        public void CodeFractionArray(ref Fraction[] v) { CodeArray(ref v, s => Fraction.Parse(s)); }\n\n        public void Code(ref List<object> value)\n        {\n            throw new Exception(\"The method or operation is not implemented.\");\n        }\n\n        public void CodeList_of_Bool_(ref List<bool> v) { CodeList(ref v, s => bool.Parse(s)); }\n        public void CodeList_of_Byte_(ref List<byte> v) { CodeList(ref v, s => byte.Parse(s)); }\n        public void CodeList_of_SByte_(ref List<sbyte> v) { CodeList(ref v, s => sbyte.Parse(s)); }\n        public void CodeList_of_Short_(ref List<short> v) { CodeList(ref v, s => short.Parse(s)); }\n        public void CodeList_of_UShort_(ref List<ushort> v) { CodeList(ref v, s => ushort.Parse(s)); }\n        public void CodeList_of_Int_(ref List<int> v) { CodeList(ref v, s => int.Parse(s)); }\n        public void CodeList_of_UInt_(ref List<uint> v) { CodeList(ref v, s => uint.Parse(s)); }\n        public void CodeList_of_Long_(ref List<long> v) { CodeList(ref v, s => long.Parse(s)); }\n        public void CodeList_of_ULong_(ref List<ulong> v) { CodeList(ref v, s => ulong.Parse(s)); }\n        public void CodeList_of_Float_(ref List<float> v)\n        {\n            CodeList(ref v, s => float.Parse(s, CultureInfo.InvariantCulture)); \n        }\n        public void CodeList_of_Double_(ref List<double> v)\n        {\n            CodeList(ref v, s => double.Parse(s, CultureInfo.InvariantCulture));\n        }\n\n        public void CodeList_of_Char_(ref List<char> v)\n        {\n            CodeList(ref v,\n                 s => s.Split(s_charSeparators,\n                              StringSplitOptions.RemoveEmptyEntries),\n                 s => char.Parse(s));\n        }\n\n        public void CodeList_of_String_(ref List<string> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n\n            while (m_state.Valid)\n            {\n                value.Add(m_state.Enumerator.Current.Value);\n                m_state.Advance();\n            }\n            m_state = m_stateStack.Pop();\n        }\n\n        public void CodeList_of_Type_(ref List<Type> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            string[] items = CurrentValue().Split(s_itemSeparator);\n\n            for (int i = 0; i < items.Length; i++)\n            {\n                var typeName = items[i];\n                TypeInfo ti;\n\n                if (TryGetTypeInfo(typeName, out ti))\n                    value.Add(ti.Type);\n                else\n                    value.Add(Type.GetType(typeName));\n            }\n        }\n\n        public void CodeList_of_Guid_(ref List<Guid> v) { CodeList(ref v, s => new Guid(s)); }\n\n        public void CodeList_of_Symbol_(ref List<Symbol> v)\n        {\n            throw new NotImplementedException();\n        }        \n        \n        public void CodeList_of_Fraction_(ref List<Fraction> v) { CodeList(ref v, s => Fraction.Parse(s)); }\n\n        #endregion\n\n        #region IDisposable Members\n\n        public void Dispose()\n        {\n            if (m_disposeStream)\n                m_stream.Dispose();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/XmlReadingCoder_auto.cs",
    "content": "using Aardvark.Base;\r\nusing System;\r\nusing System.Collections.Generic;\r\n\r\nnamespace Aardvark.Base.Coder\r\n{\r\n    // AUTO GENERATED CODE - DO NOT CHANGE!\r\n\r\n    public partial class NewXmlReadingCoder\r\n    {\r\n        #region Vectors\r\n\r\n        public void CodeV2i(ref V2i v) { throw new NotImplementedException(); }\r\n        public void CodeV2ui(ref V2ui v) { throw new NotImplementedException(); }\r\n        public void CodeV2l(ref V2l v) { throw new NotImplementedException(); }\r\n        public void CodeV2f(ref V2f v) { throw new NotImplementedException(); }\r\n        public void CodeV2d(ref V2d v) { throw new NotImplementedException(); }\r\n        public void CodeV3i(ref V3i v) { throw new NotImplementedException(); }\r\n        public void CodeV3ui(ref V3ui v) { throw new NotImplementedException(); }\r\n        public void CodeV3l(ref V3l v) { throw new NotImplementedException(); }\r\n        public void CodeV3f(ref V3f v) { throw new NotImplementedException(); }\r\n        public void CodeV3d(ref V3d v) { throw new NotImplementedException(); }\r\n        public void CodeV4i(ref V4i v) { throw new NotImplementedException(); }\r\n        public void CodeV4ui(ref V4ui v) { throw new NotImplementedException(); }\r\n        public void CodeV4l(ref V4l v) { throw new NotImplementedException(); }\r\n        public void CodeV4f(ref V4f v) { throw new NotImplementedException(); }\r\n        public void CodeV4d(ref V4d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Matrices\r\n\r\n        public void CodeM22i(ref M22i v) { throw new NotImplementedException(); }\r\n        public void CodeM22l(ref M22l v) { throw new NotImplementedException(); }\r\n        public void CodeM22f(ref M22f v) { throw new NotImplementedException(); }\r\n        public void CodeM22d(ref M22d v) { throw new NotImplementedException(); }\r\n        public void CodeM23i(ref M23i v) { throw new NotImplementedException(); }\r\n        public void CodeM23l(ref M23l v) { throw new NotImplementedException(); }\r\n        public void CodeM23f(ref M23f v) { throw new NotImplementedException(); }\r\n        public void CodeM23d(ref M23d v) { throw new NotImplementedException(); }\r\n        public void CodeM33i(ref M33i v) { throw new NotImplementedException(); }\r\n        public void CodeM33l(ref M33l v) { throw new NotImplementedException(); }\r\n        public void CodeM33f(ref M33f v) { throw new NotImplementedException(); }\r\n        public void CodeM33d(ref M33d v) { throw new NotImplementedException(); }\r\n        public void CodeM34i(ref M34i v) { throw new NotImplementedException(); }\r\n        public void CodeM34l(ref M34l v) { throw new NotImplementedException(); }\r\n        public void CodeM34f(ref M34f v) { throw new NotImplementedException(); }\r\n        public void CodeM34d(ref M34d v) { throw new NotImplementedException(); }\r\n        public void CodeM44i(ref M44i v) { throw new NotImplementedException(); }\r\n        public void CodeM44l(ref M44l v) { throw new NotImplementedException(); }\r\n        public void CodeM44f(ref M44f v) { throw new NotImplementedException(); }\r\n        public void CodeM44d(ref M44d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Ranges and Boxes\r\n\r\n        public void CodeRange1b(ref Range1b v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sb(ref Range1sb v) { throw new NotImplementedException(); }\r\n        public void CodeRange1s(ref Range1s v) { throw new NotImplementedException(); }\r\n        public void CodeRange1us(ref Range1us v) { throw new NotImplementedException(); }\r\n        public void CodeRange1i(ref Range1i v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ui(ref Range1ui v) { throw new NotImplementedException(); }\r\n        public void CodeRange1l(ref Range1l v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ul(ref Range1ul v) { throw new NotImplementedException(); }\r\n        public void CodeRange1f(ref Range1f v) { throw new NotImplementedException(); }\r\n        public void CodeRange1d(ref Range1d v) { throw new NotImplementedException(); }\r\n        public void CodeBox2i(ref Box2i v) { throw new NotImplementedException(); }\r\n        public void CodeBox2l(ref Box2l v) { throw new NotImplementedException(); }\r\n        public void CodeBox2f(ref Box2f v) { throw new NotImplementedException(); }\r\n        public void CodeBox2d(ref Box2d v) { throw new NotImplementedException(); }\r\n        public void CodeBox3i(ref Box3i v) { throw new NotImplementedException(); }\r\n        public void CodeBox3l(ref Box3l v) { throw new NotImplementedException(); }\r\n        public void CodeBox3f(ref Box3f v) { throw new NotImplementedException(); }\r\n        public void CodeBox3d(ref Box3d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Geometry Types\r\n\r\n        public void CodeCircle2f(ref Circle2f v) { throw new NotImplementedException(); }\r\n        public void CodeLine2f(ref Line2f v) { throw new NotImplementedException(); }\r\n        public void CodeLine3f(ref Line3f v) { throw new NotImplementedException(); }\r\n        public void CodePlane2f(ref Plane2f v) { throw new NotImplementedException(); }\r\n        public void CodePlane3f(ref Plane3f v) { throw new NotImplementedException(); }\r\n        public void CodePlaneWithPoint3f(ref PlaneWithPoint3f v) { throw new NotImplementedException(); }\r\n        public void CodeQuad2f(ref Quad2f v) { throw new NotImplementedException(); }\r\n        public void CodeQuad3f(ref Quad3f v) { throw new NotImplementedException(); }\r\n        public void CodeRay2f(ref Ray2f v) { throw new NotImplementedException(); }\r\n        public void CodeRay3f(ref Ray3f v) { throw new NotImplementedException(); }\r\n        public void CodeSphere3f(ref Sphere3f v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle2f(ref Triangle2f v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle3f(ref Triangle3f v) { throw new NotImplementedException(); }\r\n\r\n        public void CodeCircle2d(ref Circle2d v) { throw new NotImplementedException(); }\r\n        public void CodeLine2d(ref Line2d v) { throw new NotImplementedException(); }\r\n        public void CodeLine3d(ref Line3d v) { throw new NotImplementedException(); }\r\n        public void CodePlane2d(ref Plane2d v) { throw new NotImplementedException(); }\r\n        public void CodePlane3d(ref Plane3d v) { throw new NotImplementedException(); }\r\n        public void CodePlaneWithPoint3d(ref PlaneWithPoint3d v) { throw new NotImplementedException(); }\r\n        public void CodeQuad2d(ref Quad2d v) { throw new NotImplementedException(); }\r\n        public void CodeQuad3d(ref Quad3d v) { throw new NotImplementedException(); }\r\n        public void CodeRay2d(ref Ray2d v) { throw new NotImplementedException(); }\r\n        public void CodeRay3d(ref Ray3d v) { throw new NotImplementedException(); }\r\n        public void CodeSphere3d(ref Sphere3d v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle2d(ref Triangle2d v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle3d(ref Triangle3d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Colors\r\n\r\n        public void CodeC3b(ref C3b v) { throw new NotImplementedException(); }\r\n        public void CodeC3us(ref C3us v) { throw new NotImplementedException(); }\r\n        public void CodeC3ui(ref C3ui v) { throw new NotImplementedException(); }\r\n        public void CodeC3f(ref C3f v) { throw new NotImplementedException(); }\r\n        public void CodeC3d(ref C3d v) { throw new NotImplementedException(); }\r\n        public void CodeC4b(ref C4b v) { throw new NotImplementedException(); }\r\n        public void CodeC4us(ref C4us v) { throw new NotImplementedException(); }\r\n        public void CodeC4ui(ref C4ui v) { throw new NotImplementedException(); }\r\n        public void CodeC4f(ref C4f v) { throw new NotImplementedException(); }\r\n        public void CodeC4d(ref C4d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Trafos\r\n\r\n        public void CodeEuclidean3f(ref Euclidean3f v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3d(ref Euclidean3d v) { throw new NotImplementedException(); }\r\n        public void CodeRot2f(ref Rot2f v) { throw new NotImplementedException(); }\r\n        public void CodeRot2d(ref Rot2d v) { throw new NotImplementedException(); }\r\n        public void CodeRot3f(ref Rot3f v) { throw new NotImplementedException(); }\r\n        public void CodeRot3d(ref Rot3d v) { throw new NotImplementedException(); }\r\n        public void CodeScale3f(ref Scale3f v) { throw new NotImplementedException(); }\r\n        public void CodeScale3d(ref Scale3d v) { throw new NotImplementedException(); }\r\n        public void CodeShift3f(ref Shift3f v) { throw new NotImplementedException(); }\r\n        public void CodeShift3d(ref Shift3d v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2f(ref Trafo2f v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2d(ref Trafo2d v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3f(ref Trafo3f v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3d(ref Trafo3d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Tensors\r\n\r\n        public void CodeVector_of_Byte_(ref Vector<byte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_SByte_(ref Vector<sbyte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Short_(ref Vector<short> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_UShort_(ref Vector<ushort> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Int_(ref Vector<int> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_UInt_(ref Vector<uint> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Long_(ref Vector<long> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_ULong_(ref Vector<ulong> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Float_(ref Vector<float> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Double_(ref Vector<double> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_(ref Vector<Fraction> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2i_(ref Vector<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2l_(ref Vector<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2f_(ref Vector<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2d_(ref Vector<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3i_(ref Vector<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3l_(ref Vector<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3f_(ref Vector<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3d_(ref Vector<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4i_(ref Vector<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4l_(ref Vector<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4f_(ref Vector<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4d_(ref Vector<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22i_(ref Vector<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22l_(ref Vector<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22f_(ref Vector<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22d_(ref Vector<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23i_(ref Vector<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23l_(ref Vector<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23f_(ref Vector<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23d_(ref Vector<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33i_(ref Vector<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33l_(ref Vector<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33f_(ref Vector<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33d_(ref Vector<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34i_(ref Vector<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34l_(ref Vector<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34f_(ref Vector<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34d_(ref Vector<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44i_(ref Vector<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44l_(ref Vector<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44f_(ref Vector<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44d_(ref Vector<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3b_(ref Vector<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3us_(ref Vector<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_(ref Vector<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3f_(ref Vector<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3d_(ref Vector<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4b_(ref Vector<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4us_(ref Vector<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_(ref Vector<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4f_(ref Vector<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4d_(ref Vector<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_(ref Vector<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_(ref Vector<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_(ref Vector<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_(ref Vector<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_(ref Vector<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_(ref Vector<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_(ref Vector<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_(ref Vector<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_(ref Vector<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_(ref Vector<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_(ref Vector<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_(ref Vector<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_(ref Vector<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_(ref Vector<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_(ref Vector<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_(ref Vector<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_(ref Vector<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_(ref Vector<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_(ref Vector<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_(ref Vector<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_(ref Vector<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_(ref Vector<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_(ref Vector<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_(ref Vector<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_(ref Vector<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_(ref Vector<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_(ref Vector<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_(ref Vector<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_(ref Vector<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_(ref Vector<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_(ref Vector<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_(ref Vector<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Bool_(ref Vector<bool> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Char_(ref Vector<char> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_String_(ref Vector<string> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Type_(ref Vector<Type> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Guid_(ref Vector<Guid> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_(ref Vector<Symbol> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_(ref Vector<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_(ref Vector<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_(ref Vector<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_(ref Vector<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_(ref Vector<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_(ref Vector<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_(ref Vector<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_(ref Vector<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_(ref Vector<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_(ref Vector<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_(ref Vector<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_(ref Vector<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_(ref Vector<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_(ref Vector<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_(ref Vector<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_(ref Vector<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_(ref Vector<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_(ref Vector<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_(ref Vector<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_(ref Vector<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_(ref Vector<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_(ref Vector<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_(ref Vector<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_(ref Vector<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_(ref Vector<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_(ref Vector<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_(ref Matrix<byte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_(ref Matrix<sbyte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_(ref Matrix<short> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_(ref Matrix<ushort> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_(ref Matrix<int> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_(ref Matrix<uint> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_(ref Matrix<long> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_(ref Matrix<ulong> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_(ref Matrix<float> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_(ref Matrix<double> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_(ref Matrix<Fraction> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_(ref Matrix<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_(ref Matrix<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_(ref Matrix<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_(ref Matrix<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_(ref Matrix<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_(ref Matrix<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_(ref Matrix<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_(ref Matrix<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_(ref Matrix<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_(ref Matrix<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_(ref Matrix<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_(ref Matrix<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_(ref Matrix<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_(ref Matrix<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_(ref Matrix<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_(ref Matrix<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_(ref Matrix<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_(ref Matrix<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_(ref Matrix<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_(ref Matrix<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_(ref Matrix<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_(ref Matrix<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_(ref Matrix<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_(ref Matrix<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_(ref Matrix<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_(ref Matrix<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_(ref Matrix<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_(ref Matrix<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_(ref Matrix<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_(ref Matrix<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_(ref Matrix<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_(ref Matrix<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_(ref Matrix<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_(ref Matrix<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_(ref Matrix<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_(ref Matrix<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_(ref Matrix<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_(ref Matrix<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_(ref Matrix<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_(ref Matrix<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_(ref Matrix<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_(ref Matrix<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_(ref Matrix<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_(ref Matrix<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_(ref Matrix<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_(ref Matrix<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_(ref Matrix<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_(ref Matrix<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_(ref Matrix<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_(ref Matrix<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_(ref Matrix<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_(ref Matrix<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_(ref Matrix<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_(ref Matrix<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_(ref Matrix<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_(ref Matrix<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_(ref Matrix<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_(ref Matrix<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_(ref Matrix<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_(ref Matrix<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_(ref Matrix<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_(ref Matrix<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_(ref Matrix<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_(ref Matrix<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_(ref Matrix<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_(ref Matrix<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_(ref Matrix<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_(ref Matrix<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_(ref Matrix<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_(ref Matrix<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_(ref Matrix<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_(ref Matrix<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_(ref Matrix<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_(ref Matrix<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_(ref Matrix<bool> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_(ref Matrix<char> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_String_(ref Matrix<string> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_(ref Matrix<Type> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_(ref Matrix<Guid> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_(ref Matrix<Symbol> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_(ref Matrix<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_(ref Matrix<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_(ref Matrix<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_(ref Matrix<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_(ref Matrix<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_(ref Matrix<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_(ref Matrix<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_(ref Matrix<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_(ref Matrix<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_(ref Matrix<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_(ref Matrix<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_(ref Matrix<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_(ref Matrix<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_(ref Matrix<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_(ref Matrix<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_(ref Matrix<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_(ref Matrix<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_(ref Matrix<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_(ref Matrix<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_(ref Matrix<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_(ref Matrix<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_(ref Matrix<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_(ref Matrix<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_(ref Matrix<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_(ref Matrix<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_(ref Matrix<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_(ref Volume<byte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_(ref Volume<sbyte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Short_(ref Volume<short> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_(ref Volume<ushort> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Int_(ref Volume<int> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_(ref Volume<uint> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Long_(ref Volume<long> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_(ref Volume<ulong> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Float_(ref Volume<float> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Double_(ref Volume<double> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_(ref Volume<Fraction> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_(ref Volume<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_(ref Volume<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_(ref Volume<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_(ref Volume<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_(ref Volume<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_(ref Volume<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_(ref Volume<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_(ref Volume<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_(ref Volume<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_(ref Volume<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_(ref Volume<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_(ref Volume<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_(ref Volume<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_(ref Volume<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_(ref Volume<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_(ref Volume<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_(ref Volume<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_(ref Volume<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_(ref Volume<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_(ref Volume<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_(ref Volume<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_(ref Volume<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_(ref Volume<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_(ref Volume<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_(ref Volume<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_(ref Volume<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_(ref Volume<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_(ref Volume<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_(ref Volume<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_(ref Volume<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_(ref Volume<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_(ref Volume<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_(ref Volume<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_(ref Volume<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_(ref Volume<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_(ref Volume<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_(ref Volume<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_(ref Volume<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_(ref Volume<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_(ref Volume<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_(ref Volume<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_(ref Volume<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_(ref Volume<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_(ref Volume<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_(ref Volume<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_(ref Volume<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_(ref Volume<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_(ref Volume<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_(ref Volume<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_(ref Volume<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_(ref Volume<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_(ref Volume<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_(ref Volume<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_(ref Volume<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_(ref Volume<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_(ref Volume<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_(ref Volume<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_(ref Volume<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_(ref Volume<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_(ref Volume<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_(ref Volume<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_(ref Volume<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_(ref Volume<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_(ref Volume<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_(ref Volume<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_(ref Volume<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_(ref Volume<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_(ref Volume<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_(ref Volume<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_(ref Volume<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_(ref Volume<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_(ref Volume<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_(ref Volume<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_(ref Volume<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_(ref Volume<bool> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Char_(ref Volume<char> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_String_(ref Volume<string> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Type_(ref Volume<Type> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_(ref Volume<Guid> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_(ref Volume<Symbol> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_(ref Volume<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_(ref Volume<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_(ref Volume<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_(ref Volume<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_(ref Volume<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_(ref Volume<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_(ref Volume<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_(ref Volume<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_(ref Volume<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_(ref Volume<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_(ref Volume<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_(ref Volume<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_(ref Volume<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_(ref Volume<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_(ref Volume<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_(ref Volume<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_(ref Volume<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_(ref Volume<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_(ref Volume<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_(ref Volume<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_(ref Volume<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_(ref Volume<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_(ref Volume<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_(ref Volume<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_(ref Volume<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_(ref Volume<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_(ref Tensor<byte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_(ref Tensor<sbyte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Short_(ref Tensor<short> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_(ref Tensor<ushort> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Int_(ref Tensor<int> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_(ref Tensor<uint> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Long_(ref Tensor<long> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_(ref Tensor<ulong> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Float_(ref Tensor<float> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Double_(ref Tensor<double> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_(ref Tensor<Fraction> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_(ref Tensor<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_(ref Tensor<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_(ref Tensor<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_(ref Tensor<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_(ref Tensor<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_(ref Tensor<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_(ref Tensor<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_(ref Tensor<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_(ref Tensor<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_(ref Tensor<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_(ref Tensor<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_(ref Tensor<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_(ref Tensor<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_(ref Tensor<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_(ref Tensor<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_(ref Tensor<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_(ref Tensor<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_(ref Tensor<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_(ref Tensor<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_(ref Tensor<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_(ref Tensor<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_(ref Tensor<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_(ref Tensor<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_(ref Tensor<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_(ref Tensor<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_(ref Tensor<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_(ref Tensor<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_(ref Tensor<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_(ref Tensor<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_(ref Tensor<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_(ref Tensor<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_(ref Tensor<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_(ref Tensor<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_(ref Tensor<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_(ref Tensor<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_(ref Tensor<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_(ref Tensor<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_(ref Tensor<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_(ref Tensor<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_(ref Tensor<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_(ref Tensor<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_(ref Tensor<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_(ref Tensor<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_(ref Tensor<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_(ref Tensor<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_(ref Tensor<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_(ref Tensor<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_(ref Tensor<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_(ref Tensor<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_(ref Tensor<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_(ref Tensor<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_(ref Tensor<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_(ref Tensor<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_(ref Tensor<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_(ref Tensor<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_(ref Tensor<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_(ref Tensor<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_(ref Tensor<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_(ref Tensor<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_(ref Tensor<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_(ref Tensor<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_(ref Tensor<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_(ref Tensor<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_(ref Tensor<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_(ref Tensor<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_(ref Tensor<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_(ref Tensor<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_(ref Tensor<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_(ref Tensor<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_(ref Tensor<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_(ref Tensor<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_(ref Tensor<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_(ref Tensor<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_(ref Tensor<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_(ref Tensor<bool> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Char_(ref Tensor<char> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_String_(ref Tensor<string> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Type_(ref Tensor<Type> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_(ref Tensor<Guid> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_(ref Tensor<Symbol> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_(ref Tensor<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_(ref Tensor<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_(ref Tensor<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_(ref Tensor<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_(ref Tensor<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_(ref Tensor<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_(ref Tensor<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_(ref Tensor<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_(ref Tensor<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_(ref Tensor<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_(ref Tensor<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_(ref Tensor<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_(ref Tensor<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_(ref Tensor<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_(ref Tensor<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_(ref Tensor<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_(ref Tensor<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_(ref Tensor<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_(ref Tensor<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_(ref Tensor<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_(ref Tensor<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_(ref Tensor<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_(ref Tensor<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_(ref Tensor<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_(ref Tensor<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_(ref Tensor<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Arrays\r\n\r\n        public void CodeV2iArray(ref V2i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV2uiArray(ref V2ui[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV2lArray(ref V2l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV2fArray(ref V2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV2dArray(ref V2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV3iArray(ref V3i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV3uiArray(ref V3ui[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV3lArray(ref V3l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV3fArray(ref V3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV3dArray(ref V3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV4iArray(ref V4i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV4uiArray(ref V4ui[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV4lArray(ref V4l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV4fArray(ref V4f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeV4dArray(ref V4d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM22iArray(ref M22i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM22lArray(ref M22l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM22fArray(ref M22f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM22dArray(ref M22d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM23iArray(ref M23i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM23lArray(ref M23l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM23fArray(ref M23f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM23dArray(ref M23d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM33iArray(ref M33i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM33lArray(ref M33l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM33fArray(ref M33f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM33dArray(ref M33d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM34iArray(ref M34i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM34lArray(ref M34l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM34fArray(ref M34f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM34dArray(ref M34d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM44iArray(ref M44i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM44lArray(ref M44l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM44fArray(ref M44f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeM44dArray(ref M44d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1bArray(ref Range1b[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1sbArray(ref Range1sb[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1sArray(ref Range1s[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1usArray(ref Range1us[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1iArray(ref Range1i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1uiArray(ref Range1ui[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1lArray(ref Range1l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1ulArray(ref Range1ul[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1fArray(ref Range1f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRange1dArray(ref Range1d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeBox2iArray(ref Box2i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeBox2lArray(ref Box2l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeBox2fArray(ref Box2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeBox2dArray(ref Box2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeBox3iArray(ref Box3i[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeBox3lArray(ref Box3l[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeBox3fArray(ref Box3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeBox3dArray(ref Box3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC3bArray(ref C3b[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC3usArray(ref C3us[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC3uiArray(ref C3ui[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC3fArray(ref C3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC3dArray(ref C3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC4bArray(ref C4b[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC4usArray(ref C4us[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC4uiArray(ref C4ui[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC4fArray(ref C4f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeC4dArray(ref C4d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeEuclidean3fArray(ref Euclidean3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeEuclidean3dArray(ref Euclidean3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRot2fArray(ref Rot2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRot2dArray(ref Rot2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRot3fArray(ref Rot3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRot3dArray(ref Rot3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeScale3fArray(ref Scale3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeScale3dArray(ref Scale3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeShift3fArray(ref Shift3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeShift3dArray(ref Shift3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTrafo2fArray(ref Trafo2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTrafo2dArray(ref Trafo2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTrafo3fArray(ref Trafo3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTrafo3dArray(ref Trafo3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeCircle2dArray(ref Circle2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeLine2dArray(ref Line2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeLine3dArray(ref Line3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodePlane2dArray(ref Plane2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodePlane3dArray(ref Plane3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodePlaneWithPoint3dArray(ref PlaneWithPoint3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeQuad2dArray(ref Quad2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeQuad3dArray(ref Quad3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRay2dArray(ref Ray2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRay3dArray(ref Ray3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeSphere3dArray(ref Sphere3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTriangle2dArray(ref Triangle2d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTriangle3dArray(ref Triangle3d[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeCircle2fArray(ref Circle2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeLine2fArray(ref Line2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeLine3fArray(ref Line3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodePlane2fArray(ref Plane2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodePlane3fArray(ref Plane3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodePlaneWithPoint3fArray(ref PlaneWithPoint3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeQuad2fArray(ref Quad2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeQuad3fArray(ref Quad3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRay2fArray(ref Ray2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeRay3fArray(ref Ray3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeSphere3fArray(ref Sphere3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTriangle2fArray(ref Triangle2f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTriangle3fArray(ref Triangle3f[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArray2d(ref byte[,] value) { throw new NotImplementedException(); }\r\n        public void CodeByteArray3d(ref byte[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeSByteArray2d(ref sbyte[,] value) { throw new NotImplementedException(); }\r\n        public void CodeSByteArray3d(ref sbyte[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShortArray2d(ref short[,] value) { throw new NotImplementedException(); }\r\n        public void CodeShortArray3d(ref short[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeUShortArray2d(ref ushort[,] value) { throw new NotImplementedException(); }\r\n        public void CodeUShortArray3d(ref ushort[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeIntArray2d(ref int[,] value) { throw new NotImplementedException(); }\r\n        public void CodeIntArray3d(ref int[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeUIntArray2d(ref uint[,] value) { throw new NotImplementedException(); }\r\n        public void CodeUIntArray3d(ref uint[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeLongArray2d(ref long[,] value) { throw new NotImplementedException(); }\r\n        public void CodeLongArray3d(ref long[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeULongArray2d(ref ulong[,] value) { throw new NotImplementedException(); }\r\n        public void CodeULongArray3d(ref ulong[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeFloatArray2d(ref float[,] value) { throw new NotImplementedException(); }\r\n        public void CodeFloatArray3d(ref float[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeDoubleArray2d(ref double[,] value) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArray3d(ref double[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeFractionArray2d(ref Fraction[,] value) { throw new NotImplementedException(); }\r\n        public void CodeFractionArray3d(ref Fraction[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2iArray2d(ref V2i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV2iArray3d(ref V2i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2lArray2d(ref V2l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV2lArray3d(ref V2l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2fArray2d(ref V2f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV2fArray3d(ref V2f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2dArray2d(ref V2d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV2dArray3d(ref V2d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3iArray2d(ref V3i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV3iArray3d(ref V3i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3lArray2d(ref V3l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV3lArray3d(ref V3l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3fArray2d(ref V3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV3fArray3d(ref V3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3dArray2d(ref V3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV3dArray3d(ref V3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4iArray2d(ref V4i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV4iArray3d(ref V4i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4lArray2d(ref V4l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV4lArray3d(ref V4l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4fArray2d(ref V4f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV4fArray3d(ref V4f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4dArray2d(ref V4d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV4dArray3d(ref V4d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22iArray2d(ref M22i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM22iArray3d(ref M22i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22lArray2d(ref M22l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM22lArray3d(ref M22l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22fArray2d(ref M22f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM22fArray3d(ref M22f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22dArray2d(ref M22d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM22dArray3d(ref M22d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23iArray2d(ref M23i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM23iArray3d(ref M23i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23lArray2d(ref M23l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM23lArray3d(ref M23l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23fArray2d(ref M23f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM23fArray3d(ref M23f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23dArray2d(ref M23d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM23dArray3d(ref M23d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33iArray2d(ref M33i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM33iArray3d(ref M33i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33lArray2d(ref M33l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM33lArray3d(ref M33l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33fArray2d(ref M33f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM33fArray3d(ref M33f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33dArray2d(ref M33d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM33dArray3d(ref M33d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34iArray2d(ref M34i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM34iArray3d(ref M34i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34lArray2d(ref M34l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM34lArray3d(ref M34l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34fArray2d(ref M34f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM34fArray3d(ref M34f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34dArray2d(ref M34d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM34dArray3d(ref M34d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44iArray2d(ref M44i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM44iArray3d(ref M44i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44lArray2d(ref M44l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM44lArray3d(ref M44l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44fArray2d(ref M44f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM44fArray3d(ref M44f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44dArray2d(ref M44d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM44dArray3d(ref M44d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3bArray2d(ref C3b[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3bArray3d(ref C3b[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3usArray2d(ref C3us[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3usArray3d(ref C3us[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3uiArray2d(ref C3ui[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArray3d(ref C3ui[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3fArray2d(ref C3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3fArray3d(ref C3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3dArray2d(ref C3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3dArray3d(ref C3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4bArray2d(ref C4b[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4bArray3d(ref C4b[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4usArray2d(ref C4us[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4usArray3d(ref C4us[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4uiArray2d(ref C4ui[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArray3d(ref C4ui[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4fArray2d(ref C4f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4fArray3d(ref C4f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4dArray2d(ref C4d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4dArray3d(ref C4d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1bArray2d(ref Range1b[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArray3d(ref Range1b[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1sbArray2d(ref Range1sb[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArray3d(ref Range1sb[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1sArray2d(ref Range1s[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArray3d(ref Range1s[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1usArray2d(ref Range1us[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArray3d(ref Range1us[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1iArray2d(ref Range1i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArray3d(ref Range1i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1uiArray2d(ref Range1ui[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArray3d(ref Range1ui[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1lArray2d(ref Range1l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArray3d(ref Range1l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1ulArray2d(ref Range1ul[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArray3d(ref Range1ul[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1fArray2d(ref Range1f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArray3d(ref Range1f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1dArray2d(ref Range1d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArray3d(ref Range1d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2iArray2d(ref Box2i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArray3d(ref Box2i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2lArray2d(ref Box2l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArray3d(ref Box2l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2fArray2d(ref Box2f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArray3d(ref Box2f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2dArray2d(ref Box2d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArray3d(ref Box2d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3iArray2d(ref Box3i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArray3d(ref Box3i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3lArray2d(ref Box3l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArray3d(ref Box3l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3fArray2d(ref Box3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArray3d(ref Box3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3dArray2d(ref Box3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArray3d(ref Box3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeEuclidean3fArray2d(ref Euclidean3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArray3d(ref Euclidean3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeEuclidean3dArray2d(ref Euclidean3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArray3d(ref Euclidean3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot2fArray2d(ref Rot2f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArray3d(ref Rot2f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot2dArray2d(ref Rot2d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArray3d(ref Rot2d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot3fArray2d(ref Rot3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArray3d(ref Rot3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot3dArray2d(ref Rot3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArray3d(ref Rot3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeScale3fArray2d(ref Scale3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArray3d(ref Scale3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeScale3dArray2d(ref Scale3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArray3d(ref Scale3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShift3fArray2d(ref Shift3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArray3d(ref Shift3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShift3dArray2d(ref Shift3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArray3d(ref Shift3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo2fArray2d(ref Trafo2f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArray3d(ref Trafo2f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo2dArray2d(ref Trafo2d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArray3d(ref Trafo2d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo3fArray2d(ref Trafo3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArray3d(ref Trafo3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo3dArray2d(ref Trafo3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArray3d(ref Trafo3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Jagged Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArrayArray(ref byte[][] value) { throw new NotImplementedException(); }\r\n        public void CodeByteArrayArrayArray(ref byte[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeSByteArrayArray(ref sbyte[][] value) { throw new NotImplementedException(); }\r\n        public void CodeSByteArrayArrayArray(ref sbyte[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShortArrayArray(ref short[][] value) { throw new NotImplementedException(); }\r\n        public void CodeShortArrayArrayArray(ref short[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeUShortArrayArray(ref ushort[][] value) { throw new NotImplementedException(); }\r\n        public void CodeUShortArrayArrayArray(ref ushort[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeIntArrayArray(ref int[][] value) { throw new NotImplementedException(); }\r\n        public void CodeIntArrayArrayArray(ref int[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeUIntArrayArray(ref uint[][] value) { throw new NotImplementedException(); }\r\n        public void CodeUIntArrayArrayArray(ref uint[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeLongArrayArray(ref long[][] value) { throw new NotImplementedException(); }\r\n        public void CodeLongArrayArrayArray(ref long[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeULongArrayArray(ref ulong[][] value) { throw new NotImplementedException(); }\r\n        public void CodeULongArrayArrayArray(ref ulong[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeFloatArrayArray(ref float[][] value) { throw new NotImplementedException(); }\r\n        public void CodeFloatArrayArrayArray(ref float[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeDoubleArrayArray(ref double[][] value) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArrayArrayArray(ref double[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeFractionArrayArray(ref Fraction[][] value) { throw new NotImplementedException(); }\r\n        public void CodeFractionArrayArrayArray(ref Fraction[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2iArrayArray(ref V2i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV2iArrayArrayArray(ref V2i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2lArrayArray(ref V2l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV2lArrayArrayArray(ref V2l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2fArrayArray(ref V2f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV2fArrayArrayArray(ref V2f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2dArrayArray(ref V2d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV2dArrayArrayArray(ref V2d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3iArrayArray(ref V3i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV3iArrayArrayArray(ref V3i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3lArrayArray(ref V3l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV3lArrayArrayArray(ref V3l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3fArrayArray(ref V3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV3fArrayArrayArray(ref V3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3dArrayArray(ref V3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV3dArrayArrayArray(ref V3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4iArrayArray(ref V4i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV4iArrayArrayArray(ref V4i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4lArrayArray(ref V4l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV4lArrayArrayArray(ref V4l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4fArrayArray(ref V4f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV4fArrayArrayArray(ref V4f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4dArrayArray(ref V4d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV4dArrayArrayArray(ref V4d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22iArrayArray(ref M22i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM22iArrayArrayArray(ref M22i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22lArrayArray(ref M22l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM22lArrayArrayArray(ref M22l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22fArrayArray(ref M22f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM22fArrayArrayArray(ref M22f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22dArrayArray(ref M22d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM22dArrayArrayArray(ref M22d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23iArrayArray(ref M23i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM23iArrayArrayArray(ref M23i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23lArrayArray(ref M23l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM23lArrayArrayArray(ref M23l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23fArrayArray(ref M23f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM23fArrayArrayArray(ref M23f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23dArrayArray(ref M23d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM23dArrayArrayArray(ref M23d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33iArrayArray(ref M33i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM33iArrayArrayArray(ref M33i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33lArrayArray(ref M33l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM33lArrayArrayArray(ref M33l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33fArrayArray(ref M33f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM33fArrayArrayArray(ref M33f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33dArrayArray(ref M33d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM33dArrayArrayArray(ref M33d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34iArrayArray(ref M34i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM34iArrayArrayArray(ref M34i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34lArrayArray(ref M34l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM34lArrayArrayArray(ref M34l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34fArrayArray(ref M34f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM34fArrayArrayArray(ref M34f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34dArrayArray(ref M34d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM34dArrayArrayArray(ref M34d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44iArrayArray(ref M44i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM44iArrayArrayArray(ref M44i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44lArrayArray(ref M44l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM44lArrayArrayArray(ref M44l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44fArrayArray(ref M44f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM44fArrayArrayArray(ref M44f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44dArrayArray(ref M44d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM44dArrayArrayArray(ref M44d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3bArrayArray(ref C3b[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3bArrayArrayArray(ref C3b[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3usArrayArray(ref C3us[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3usArrayArrayArray(ref C3us[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3uiArrayArray(ref C3ui[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArrayArrayArray(ref C3ui[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3fArrayArray(ref C3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3fArrayArrayArray(ref C3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3dArrayArray(ref C3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3dArrayArrayArray(ref C3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4bArrayArray(ref C4b[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4bArrayArrayArray(ref C4b[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4usArrayArray(ref C4us[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4usArrayArrayArray(ref C4us[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4uiArrayArray(ref C4ui[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArrayArrayArray(ref C4ui[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4fArrayArray(ref C4f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4fArrayArrayArray(ref C4f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4dArrayArray(ref C4d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4dArrayArrayArray(ref C4d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1bArrayArray(ref Range1b[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArrayArrayArray(ref Range1b[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1sbArrayArray(ref Range1sb[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArrayArrayArray(ref Range1sb[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1sArrayArray(ref Range1s[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArrayArrayArray(ref Range1s[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1usArrayArray(ref Range1us[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArrayArrayArray(ref Range1us[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1iArrayArray(ref Range1i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArrayArrayArray(ref Range1i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1uiArrayArray(ref Range1ui[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArrayArrayArray(ref Range1ui[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1lArrayArray(ref Range1l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArrayArrayArray(ref Range1l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1ulArrayArray(ref Range1ul[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArrayArrayArray(ref Range1ul[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1fArrayArray(ref Range1f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArrayArrayArray(ref Range1f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1dArrayArray(ref Range1d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArrayArrayArray(ref Range1d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2iArrayArray(ref Box2i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArrayArrayArray(ref Box2i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2lArrayArray(ref Box2l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArrayArrayArray(ref Box2l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2fArrayArray(ref Box2f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArrayArrayArray(ref Box2f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2dArrayArray(ref Box2d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArrayArrayArray(ref Box2d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3iArrayArray(ref Box3i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArrayArrayArray(ref Box3i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3lArrayArray(ref Box3l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArrayArrayArray(ref Box3l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3fArrayArray(ref Box3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArrayArrayArray(ref Box3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3dArrayArray(ref Box3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArrayArrayArray(ref Box3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeEuclidean3fArrayArray(ref Euclidean3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArrayArrayArray(ref Euclidean3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeEuclidean3dArrayArray(ref Euclidean3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArrayArrayArray(ref Euclidean3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot2fArrayArray(ref Rot2f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArrayArrayArray(ref Rot2f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot2dArrayArray(ref Rot2d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArrayArrayArray(ref Rot2d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot3fArrayArray(ref Rot3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArrayArrayArray(ref Rot3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot3dArrayArray(ref Rot3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArrayArrayArray(ref Rot3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeScale3fArrayArray(ref Scale3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArrayArrayArray(ref Scale3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeScale3dArrayArray(ref Scale3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArrayArrayArray(ref Scale3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShift3fArrayArray(ref Shift3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArrayArrayArray(ref Shift3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShift3dArrayArray(ref Shift3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArrayArrayArray(ref Shift3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo2fArrayArray(ref Trafo2f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArrayArrayArray(ref Trafo2f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo2dArrayArray(ref Trafo2d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArrayArrayArray(ref Trafo2d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo3fArrayArray(ref Trafo3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArrayArrayArray(ref Trafo3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo3dArrayArray(ref Trafo3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArrayArrayArray(ref Trafo3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Lists\r\n\r\n        public void CodeList_of_V2i_(ref List<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V2ui_(ref List<V2ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V2l_(ref List<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V2f_(ref List<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V2d_(ref List<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V3i_(ref List<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V3ui_(ref List<V3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V3l_(ref List<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V3f_(ref List<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V3d_(ref List<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V4i_(ref List<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V4ui_(ref List<V4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V4l_(ref List<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V4f_(ref List<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_V4d_(ref List<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M22i_(ref List<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M22l_(ref List<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M22f_(ref List<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M22d_(ref List<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M23i_(ref List<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M23l_(ref List<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M23f_(ref List<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M23d_(ref List<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M33i_(ref List<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M33l_(ref List<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M33f_(ref List<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M33d_(ref List<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M34i_(ref List<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M34l_(ref List<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M34f_(ref List<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M34d_(ref List<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M44i_(ref List<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M44l_(ref List<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M44f_(ref List<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_M44d_(ref List<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1b_(ref List<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1sb_(ref List<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1s_(ref List<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1us_(ref List<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1i_(ref List<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1ui_(ref List<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1l_(ref List<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1ul_(ref List<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1f_(ref List<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Range1d_(ref List<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Box2i_(ref List<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Box2l_(ref List<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Box2f_(ref List<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Box2d_(ref List<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Box3i_(ref List<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Box3l_(ref List<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Box3f_(ref List<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Box3d_(ref List<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C3b_(ref List<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C3us_(ref List<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C3ui_(ref List<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C3f_(ref List<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C3d_(ref List<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C4b_(ref List<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C4us_(ref List<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C4ui_(ref List<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C4f_(ref List<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_C4d_(ref List<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Euclidean3f_(ref List<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Euclidean3d_(ref List<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Rot2f_(ref List<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Rot2d_(ref List<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Rot3f_(ref List<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Rot3d_(ref List<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Scale3f_(ref List<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Scale3d_(ref List<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Shift3f_(ref List<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Shift3d_(ref List<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Trafo2f_(ref List<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Trafo2d_(ref List<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Trafo3f_(ref List<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Trafo3d_(ref List<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Circle2d_(ref List<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Line2d_(ref List<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Line3d_(ref List<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Plane2d_(ref List<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Plane3d_(ref List<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_PlaneWithPoint3d_(ref List<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Quad2d_(ref List<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Quad3d_(ref List<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Ray2d_(ref List<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Ray3d_(ref List<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Sphere3d_(ref List<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Triangle2d_(ref List<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Triangle3d_(ref List<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Circle2f_(ref List<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Line2f_(ref List<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Line3f_(ref List<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Plane2f_(ref List<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Plane3f_(ref List<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_PlaneWithPoint3f_(ref List<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Quad2f_(ref List<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Quad3f_(ref List<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Ray2f_(ref List<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Ray3f_(ref List<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Sphere3f_(ref List<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Triangle2f_(ref List<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Triangle3f_(ref List<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Arrays of Tensors\r\n\r\n        public void CodeVector_of_Byte_Array(ref Vector<byte>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_SByte_Array(ref Vector<sbyte>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Short_Array(ref Vector<short>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_UShort_Array(ref Vector<ushort>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Int_Array(ref Vector<int>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_UInt_Array(ref Vector<uint>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Long_Array(ref Vector<long>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_ULong_Array(ref Vector<ulong>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Float_Array(ref Vector<float>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Double_Array(ref Vector<double>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_Array(ref Vector<Fraction>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2i_Array(ref Vector<V2i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2l_Array(ref Vector<V2l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2f_Array(ref Vector<V2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2d_Array(ref Vector<V2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3i_Array(ref Vector<V3i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3l_Array(ref Vector<V3l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3f_Array(ref Vector<V3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3d_Array(ref Vector<V3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4i_Array(ref Vector<V4i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4l_Array(ref Vector<V4l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4f_Array(ref Vector<V4f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4d_Array(ref Vector<V4d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22i_Array(ref Vector<M22i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22l_Array(ref Vector<M22l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22f_Array(ref Vector<M22f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22d_Array(ref Vector<M22d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23i_Array(ref Vector<M23i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23l_Array(ref Vector<M23l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23f_Array(ref Vector<M23f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23d_Array(ref Vector<M23d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33i_Array(ref Vector<M33i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33l_Array(ref Vector<M33l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33f_Array(ref Vector<M33f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33d_Array(ref Vector<M33d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34i_Array(ref Vector<M34i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34l_Array(ref Vector<M34l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34f_Array(ref Vector<M34f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34d_Array(ref Vector<M34d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44i_Array(ref Vector<M44i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44l_Array(ref Vector<M44l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44f_Array(ref Vector<M44f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44d_Array(ref Vector<M44d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3b_Array(ref Vector<C3b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3us_Array(ref Vector<C3us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_Array(ref Vector<C3ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3f_Array(ref Vector<C3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3d_Array(ref Vector<C3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4b_Array(ref Vector<C4b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4us_Array(ref Vector<C4us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_Array(ref Vector<C4ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4f_Array(ref Vector<C4f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4d_Array(ref Vector<C4d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_Array(ref Vector<Range1b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_Array(ref Vector<Range1sb>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_Array(ref Vector<Range1s>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_Array(ref Vector<Range1us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_Array(ref Vector<Range1i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_Array(ref Vector<Range1ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_Array(ref Vector<Range1l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_Array(ref Vector<Range1ul>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_Array(ref Vector<Range1f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_Array(ref Vector<Range1d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_Array(ref Vector<Box2i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_Array(ref Vector<Box2l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_Array(ref Vector<Box2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_Array(ref Vector<Box2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_Array(ref Vector<Box3i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_Array(ref Vector<Box3l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_Array(ref Vector<Box3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_Array(ref Vector<Box3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_Array(ref Vector<Euclidean3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_Array(ref Vector<Euclidean3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_Array(ref Vector<Rot2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_Array(ref Vector<Rot2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_Array(ref Vector<Rot3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_Array(ref Vector<Rot3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_Array(ref Vector<Scale3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_Array(ref Vector<Scale3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_Array(ref Vector<Shift3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_Array(ref Vector<Shift3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_Array(ref Vector<Trafo2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_Array(ref Vector<Trafo2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_Array(ref Vector<Trafo3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_Array(ref Vector<Trafo3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Bool_Array(ref Vector<bool>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Char_Array(ref Vector<char>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_String_Array(ref Vector<string>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Type_Array(ref Vector<Type>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Guid_Array(ref Vector<Guid>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_Array(ref Vector<Symbol>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_Array(ref Vector<Circle2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_Array(ref Vector<Line2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_Array(ref Vector<Line3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_Array(ref Vector<Plane2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_Array(ref Vector<Plane3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_Array(ref Vector<PlaneWithPoint3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_Array(ref Vector<Quad2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_Array(ref Vector<Quad3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_Array(ref Vector<Ray2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_Array(ref Vector<Ray3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_Array(ref Vector<Sphere3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_Array(ref Vector<Triangle2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_Array(ref Vector<Triangle3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_Array(ref Vector<Circle2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_Array(ref Vector<Line2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_Array(ref Vector<Line3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_Array(ref Vector<Plane2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_Array(ref Vector<Plane3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_Array(ref Vector<PlaneWithPoint3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_Array(ref Vector<Quad2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_Array(ref Vector<Quad3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_Array(ref Vector<Ray2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_Array(ref Vector<Ray3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_Array(ref Vector<Sphere3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_Array(ref Vector<Triangle2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_Array(ref Vector<Triangle3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_Array(ref Matrix<byte>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_Array(ref Matrix<sbyte>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_Array(ref Matrix<short>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_Array(ref Matrix<ushort>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_Array(ref Matrix<int>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_Array(ref Matrix<uint>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_Array(ref Matrix<long>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_Array(ref Matrix<ulong>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_Array(ref Matrix<float>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_Array(ref Matrix<double>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_Array(ref Matrix<Fraction>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_Array(ref Matrix<V2i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_Array(ref Matrix<V2l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_Array(ref Matrix<V2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_Array(ref Matrix<V2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_Array(ref Matrix<V3i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_Array(ref Matrix<V3l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_Array(ref Matrix<V3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_Array(ref Matrix<V3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_Array(ref Matrix<V4i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_Array(ref Matrix<V4l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_Array(ref Matrix<V4f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_Array(ref Matrix<V4d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_Array(ref Matrix<M22i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_Array(ref Matrix<M22l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_Array(ref Matrix<M22f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_Array(ref Matrix<M22d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_Array(ref Matrix<M23i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_Array(ref Matrix<M23l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_Array(ref Matrix<M23f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_Array(ref Matrix<M23d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_Array(ref Matrix<M33i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_Array(ref Matrix<M33l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_Array(ref Matrix<M33f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_Array(ref Matrix<M33d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_Array(ref Matrix<M34i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_Array(ref Matrix<M34l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_Array(ref Matrix<M34f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_Array(ref Matrix<M34d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_Array(ref Matrix<M44i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_Array(ref Matrix<M44l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_Array(ref Matrix<M44f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_Array(ref Matrix<M44d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_Array(ref Matrix<C3b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_Array(ref Matrix<C3us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_Array(ref Matrix<C3ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_Array(ref Matrix<C3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_Array(ref Matrix<C3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_Array(ref Matrix<C4b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_Array(ref Matrix<C4us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_Array(ref Matrix<C4ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_Array(ref Matrix<C4f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_Array(ref Matrix<C4d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_Array(ref Matrix<Range1b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_Array(ref Matrix<Range1sb>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_Array(ref Matrix<Range1s>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_Array(ref Matrix<Range1us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_Array(ref Matrix<Range1i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_Array(ref Matrix<Range1ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_Array(ref Matrix<Range1l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_Array(ref Matrix<Range1ul>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_Array(ref Matrix<Range1f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_Array(ref Matrix<Range1d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_Array(ref Matrix<Box2i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_Array(ref Matrix<Box2l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_Array(ref Matrix<Box2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_Array(ref Matrix<Box2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_Array(ref Matrix<Box3i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_Array(ref Matrix<Box3l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_Array(ref Matrix<Box3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_Array(ref Matrix<Box3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_Array(ref Matrix<Euclidean3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_Array(ref Matrix<Euclidean3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_Array(ref Matrix<Rot2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_Array(ref Matrix<Rot2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_Array(ref Matrix<Rot3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_Array(ref Matrix<Rot3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_Array(ref Matrix<Scale3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_Array(ref Matrix<Scale3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_Array(ref Matrix<Shift3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_Array(ref Matrix<Shift3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_Array(ref Matrix<Trafo2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_Array(ref Matrix<Trafo2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_Array(ref Matrix<Trafo3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_Array(ref Matrix<Trafo3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_Array(ref Matrix<bool>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_Array(ref Matrix<char>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_String_Array(ref Matrix<string>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_Array(ref Matrix<Type>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_Array(ref Matrix<Guid>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_Array(ref Matrix<Symbol>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_Array(ref Matrix<Circle2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_Array(ref Matrix<Line2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_Array(ref Matrix<Line3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_Array(ref Matrix<Plane2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_Array(ref Matrix<Plane3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_Array(ref Matrix<PlaneWithPoint3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_Array(ref Matrix<Quad2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_Array(ref Matrix<Quad3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_Array(ref Matrix<Ray2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_Array(ref Matrix<Ray3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_Array(ref Matrix<Sphere3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_Array(ref Matrix<Triangle2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_Array(ref Matrix<Triangle3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_Array(ref Matrix<Circle2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_Array(ref Matrix<Line2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_Array(ref Matrix<Line3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_Array(ref Matrix<Plane2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_Array(ref Matrix<Plane3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_Array(ref Matrix<PlaneWithPoint3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_Array(ref Matrix<Quad2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_Array(ref Matrix<Quad3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_Array(ref Matrix<Ray2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_Array(ref Matrix<Ray3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_Array(ref Matrix<Sphere3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_Array(ref Matrix<Triangle2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_Array(ref Matrix<Triangle3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_Array(ref Volume<byte>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_Array(ref Volume<sbyte>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Short_Array(ref Volume<short>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_Array(ref Volume<ushort>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Int_Array(ref Volume<int>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_Array(ref Volume<uint>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Long_Array(ref Volume<long>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_Array(ref Volume<ulong>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Float_Array(ref Volume<float>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Double_Array(ref Volume<double>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_Array(ref Volume<Fraction>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_Array(ref Volume<V2i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_Array(ref Volume<V2l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_Array(ref Volume<V2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_Array(ref Volume<V2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_Array(ref Volume<V3i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_Array(ref Volume<V3l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_Array(ref Volume<V3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_Array(ref Volume<V3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_Array(ref Volume<V4i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_Array(ref Volume<V4l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_Array(ref Volume<V4f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_Array(ref Volume<V4d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_Array(ref Volume<M22i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_Array(ref Volume<M22l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_Array(ref Volume<M22f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_Array(ref Volume<M22d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_Array(ref Volume<M23i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_Array(ref Volume<M23l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_Array(ref Volume<M23f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_Array(ref Volume<M23d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_Array(ref Volume<M33i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_Array(ref Volume<M33l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_Array(ref Volume<M33f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_Array(ref Volume<M33d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_Array(ref Volume<M34i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_Array(ref Volume<M34l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_Array(ref Volume<M34f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_Array(ref Volume<M34d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_Array(ref Volume<M44i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_Array(ref Volume<M44l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_Array(ref Volume<M44f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_Array(ref Volume<M44d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_Array(ref Volume<C3b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_Array(ref Volume<C3us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_Array(ref Volume<C3ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_Array(ref Volume<C3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_Array(ref Volume<C3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_Array(ref Volume<C4b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_Array(ref Volume<C4us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_Array(ref Volume<C4ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_Array(ref Volume<C4f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_Array(ref Volume<C4d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_Array(ref Volume<Range1b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_Array(ref Volume<Range1sb>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_Array(ref Volume<Range1s>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_Array(ref Volume<Range1us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_Array(ref Volume<Range1i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_Array(ref Volume<Range1ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_Array(ref Volume<Range1l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_Array(ref Volume<Range1ul>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_Array(ref Volume<Range1f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_Array(ref Volume<Range1d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_Array(ref Volume<Box2i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_Array(ref Volume<Box2l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_Array(ref Volume<Box2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_Array(ref Volume<Box2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_Array(ref Volume<Box3i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_Array(ref Volume<Box3l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_Array(ref Volume<Box3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_Array(ref Volume<Box3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_Array(ref Volume<Euclidean3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_Array(ref Volume<Euclidean3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_Array(ref Volume<Rot2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_Array(ref Volume<Rot2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_Array(ref Volume<Rot3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_Array(ref Volume<Rot3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_Array(ref Volume<Scale3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_Array(ref Volume<Scale3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_Array(ref Volume<Shift3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_Array(ref Volume<Shift3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_Array(ref Volume<Trafo2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_Array(ref Volume<Trafo2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_Array(ref Volume<Trafo3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_Array(ref Volume<Trafo3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_Array(ref Volume<bool>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Char_Array(ref Volume<char>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_String_Array(ref Volume<string>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Type_Array(ref Volume<Type>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_Array(ref Volume<Guid>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_Array(ref Volume<Symbol>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_Array(ref Volume<Circle2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_Array(ref Volume<Line2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_Array(ref Volume<Line3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_Array(ref Volume<Plane2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_Array(ref Volume<Plane3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_Array(ref Volume<PlaneWithPoint3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_Array(ref Volume<Quad2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_Array(ref Volume<Quad3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_Array(ref Volume<Ray2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_Array(ref Volume<Ray3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_Array(ref Volume<Sphere3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_Array(ref Volume<Triangle2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_Array(ref Volume<Triangle3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_Array(ref Volume<Circle2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_Array(ref Volume<Line2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_Array(ref Volume<Line3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_Array(ref Volume<Plane2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_Array(ref Volume<Plane3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_Array(ref Volume<PlaneWithPoint3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_Array(ref Volume<Quad2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_Array(ref Volume<Quad3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_Array(ref Volume<Ray2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_Array(ref Volume<Ray3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_Array(ref Volume<Sphere3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_Array(ref Volume<Triangle2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_Array(ref Volume<Triangle3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_Array(ref Tensor<byte>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_Array(ref Tensor<sbyte>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Short_Array(ref Tensor<short>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_Array(ref Tensor<ushort>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Int_Array(ref Tensor<int>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_Array(ref Tensor<uint>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Long_Array(ref Tensor<long>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_Array(ref Tensor<ulong>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Float_Array(ref Tensor<float>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Double_Array(ref Tensor<double>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_Array(ref Tensor<Fraction>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_Array(ref Tensor<V2i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_Array(ref Tensor<V2l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_Array(ref Tensor<V2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_Array(ref Tensor<V2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_Array(ref Tensor<V3i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_Array(ref Tensor<V3l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_Array(ref Tensor<V3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_Array(ref Tensor<V3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_Array(ref Tensor<V4i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_Array(ref Tensor<V4l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_Array(ref Tensor<V4f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_Array(ref Tensor<V4d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_Array(ref Tensor<M22i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_Array(ref Tensor<M22l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_Array(ref Tensor<M22f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_Array(ref Tensor<M22d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_Array(ref Tensor<M23i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_Array(ref Tensor<M23l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_Array(ref Tensor<M23f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_Array(ref Tensor<M23d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_Array(ref Tensor<M33i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_Array(ref Tensor<M33l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_Array(ref Tensor<M33f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_Array(ref Tensor<M33d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_Array(ref Tensor<M34i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_Array(ref Tensor<M34l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_Array(ref Tensor<M34f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_Array(ref Tensor<M34d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_Array(ref Tensor<M44i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_Array(ref Tensor<M44l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_Array(ref Tensor<M44f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_Array(ref Tensor<M44d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_Array(ref Tensor<C3b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_Array(ref Tensor<C3us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_Array(ref Tensor<C3ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_Array(ref Tensor<C3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_Array(ref Tensor<C3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_Array(ref Tensor<C4b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_Array(ref Tensor<C4us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_Array(ref Tensor<C4ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_Array(ref Tensor<C4f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_Array(ref Tensor<C4d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_Array(ref Tensor<Range1b>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_Array(ref Tensor<Range1sb>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_Array(ref Tensor<Range1s>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_Array(ref Tensor<Range1us>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_Array(ref Tensor<Range1i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_Array(ref Tensor<Range1ui>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_Array(ref Tensor<Range1l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_Array(ref Tensor<Range1ul>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_Array(ref Tensor<Range1f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_Array(ref Tensor<Range1d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_Array(ref Tensor<Box2i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_Array(ref Tensor<Box2l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_Array(ref Tensor<Box2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_Array(ref Tensor<Box2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_Array(ref Tensor<Box3i>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_Array(ref Tensor<Box3l>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_Array(ref Tensor<Box3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_Array(ref Tensor<Box3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_Array(ref Tensor<Euclidean3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_Array(ref Tensor<Euclidean3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_Array(ref Tensor<Rot2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_Array(ref Tensor<Rot2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_Array(ref Tensor<Rot3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_Array(ref Tensor<Rot3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_Array(ref Tensor<Scale3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_Array(ref Tensor<Scale3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_Array(ref Tensor<Shift3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_Array(ref Tensor<Shift3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_Array(ref Tensor<Trafo2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_Array(ref Tensor<Trafo2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_Array(ref Tensor<Trafo3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_Array(ref Tensor<Trafo3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_Array(ref Tensor<bool>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Char_Array(ref Tensor<char>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_String_Array(ref Tensor<string>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Type_Array(ref Tensor<Type>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_Array(ref Tensor<Guid>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_Array(ref Tensor<Symbol>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_Array(ref Tensor<Circle2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_Array(ref Tensor<Line2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_Array(ref Tensor<Line3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_Array(ref Tensor<Plane2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_Array(ref Tensor<Plane3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_Array(ref Tensor<PlaneWithPoint3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_Array(ref Tensor<Quad2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_Array(ref Tensor<Quad3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_Array(ref Tensor<Ray2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_Array(ref Tensor<Ray3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_Array(ref Tensor<Sphere3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_Array(ref Tensor<Triangle2d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_Array(ref Tensor<Triangle3d>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_Array(ref Tensor<Circle2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_Array(ref Tensor<Line2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_Array(ref Tensor<Line3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_Array(ref Tensor<Plane2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_Array(ref Tensor<Plane3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_Array(ref Tensor<PlaneWithPoint3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_Array(ref Tensor<Quad2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_Array(ref Tensor<Quad3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_Array(ref Tensor<Ray2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_Array(ref Tensor<Ray3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_Array(ref Tensor<Sphere3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_Array(ref Tensor<Triangle2f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_Array(ref Tensor<Triangle3f>[] value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Lists of Tensors\r\n\r\n        public void CodeList_of_Vector_of_Byte__(ref List<Vector<byte>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_SByte__(ref List<Vector<sbyte>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Short__(ref List<Vector<short>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_UShort__(ref List<Vector<ushort>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Int__(ref List<Vector<int>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_UInt__(ref List<Vector<uint>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Long__(ref List<Vector<long>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_ULong__(ref List<Vector<ulong>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Float__(ref List<Vector<float>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Double__(ref List<Vector<double>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Fraction__(ref List<Vector<Fraction>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2i__(ref List<Vector<V2i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2l__(ref List<Vector<V2l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2f__(ref List<Vector<V2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2d__(ref List<Vector<V2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3i__(ref List<Vector<V3i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3l__(ref List<Vector<V3l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3f__(ref List<Vector<V3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3d__(ref List<Vector<V3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4i__(ref List<Vector<V4i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4l__(ref List<Vector<V4l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4f__(ref List<Vector<V4f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4d__(ref List<Vector<V4d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22i__(ref List<Vector<M22i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22l__(ref List<Vector<M22l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22f__(ref List<Vector<M22f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22d__(ref List<Vector<M22d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23i__(ref List<Vector<M23i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23l__(ref List<Vector<M23l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23f__(ref List<Vector<M23f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23d__(ref List<Vector<M23d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33i__(ref List<Vector<M33i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33l__(ref List<Vector<M33l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33f__(ref List<Vector<M33f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33d__(ref List<Vector<M33d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34i__(ref List<Vector<M34i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34l__(ref List<Vector<M34l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34f__(ref List<Vector<M34f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34d__(ref List<Vector<M34d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44i__(ref List<Vector<M44i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44l__(ref List<Vector<M44l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44f__(ref List<Vector<M44f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44d__(ref List<Vector<M44d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3b__(ref List<Vector<C3b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3us__(ref List<Vector<C3us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3ui__(ref List<Vector<C3ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3f__(ref List<Vector<C3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3d__(ref List<Vector<C3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4b__(ref List<Vector<C4b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4us__(ref List<Vector<C4us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4ui__(ref List<Vector<C4ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4f__(ref List<Vector<C4f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4d__(ref List<Vector<C4d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1b__(ref List<Vector<Range1b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1sb__(ref List<Vector<Range1sb>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1s__(ref List<Vector<Range1s>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1us__(ref List<Vector<Range1us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1i__(ref List<Vector<Range1i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1ui__(ref List<Vector<Range1ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1l__(ref List<Vector<Range1l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1ul__(ref List<Vector<Range1ul>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1f__(ref List<Vector<Range1f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1d__(ref List<Vector<Range1d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2i__(ref List<Vector<Box2i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2l__(ref List<Vector<Box2l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2f__(ref List<Vector<Box2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2d__(ref List<Vector<Box2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3i__(ref List<Vector<Box3i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3l__(ref List<Vector<Box3l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3f__(ref List<Vector<Box3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3d__(ref List<Vector<Box3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Euclidean3f__(ref List<Vector<Euclidean3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Euclidean3d__(ref List<Vector<Euclidean3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot2f__(ref List<Vector<Rot2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot2d__(ref List<Vector<Rot2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot3f__(ref List<Vector<Rot3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot3d__(ref List<Vector<Rot3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Scale3f__(ref List<Vector<Scale3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Scale3d__(ref List<Vector<Scale3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Shift3f__(ref List<Vector<Shift3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Shift3d__(ref List<Vector<Shift3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo2f__(ref List<Vector<Trafo2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo2d__(ref List<Vector<Trafo2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo3f__(ref List<Vector<Trafo3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo3d__(ref List<Vector<Trafo3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Bool__(ref List<Vector<bool>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Char__(ref List<Vector<char>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_String__(ref List<Vector<string>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Type__(ref List<Vector<Type>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Guid__(ref List<Vector<Guid>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Symbol__(ref List<Vector<Symbol>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Circle2d__(ref List<Vector<Circle2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line2d__(ref List<Vector<Line2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line3d__(ref List<Vector<Line3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane2d__(ref List<Vector<Plane2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane3d__(ref List<Vector<Plane3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3d__(ref List<Vector<PlaneWithPoint3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad2d__(ref List<Vector<Quad2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad3d__(ref List<Vector<Quad3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray2d__(ref List<Vector<Ray2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray3d__(ref List<Vector<Ray3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Sphere3d__(ref List<Vector<Sphere3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle2d__(ref List<Vector<Triangle2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle3d__(ref List<Vector<Triangle3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Circle2f__(ref List<Vector<Circle2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line2f__(ref List<Vector<Line2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line3f__(ref List<Vector<Line3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane2f__(ref List<Vector<Plane2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane3f__(ref List<Vector<Plane3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3f__(ref List<Vector<PlaneWithPoint3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad2f__(ref List<Vector<Quad2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad3f__(ref List<Vector<Quad3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray2f__(ref List<Vector<Ray2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray3f__(ref List<Vector<Ray3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Sphere3f__(ref List<Vector<Sphere3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle2f__(ref List<Vector<Triangle2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle3f__(ref List<Vector<Triangle3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Byte__(ref List<Matrix<byte>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_SByte__(ref List<Matrix<sbyte>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Short__(ref List<Matrix<short>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_UShort__(ref List<Matrix<ushort>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Int__(ref List<Matrix<int>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_UInt__(ref List<Matrix<uint>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Long__(ref List<Matrix<long>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_ULong__(ref List<Matrix<ulong>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Float__(ref List<Matrix<float>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Double__(ref List<Matrix<double>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Fraction__(ref List<Matrix<Fraction>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2i__(ref List<Matrix<V2i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2l__(ref List<Matrix<V2l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2f__(ref List<Matrix<V2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2d__(ref List<Matrix<V2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3i__(ref List<Matrix<V3i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3l__(ref List<Matrix<V3l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3f__(ref List<Matrix<V3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3d__(ref List<Matrix<V3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4i__(ref List<Matrix<V4i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4l__(ref List<Matrix<V4l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4f__(ref List<Matrix<V4f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4d__(ref List<Matrix<V4d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22i__(ref List<Matrix<M22i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22l__(ref List<Matrix<M22l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22f__(ref List<Matrix<M22f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22d__(ref List<Matrix<M22d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23i__(ref List<Matrix<M23i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23l__(ref List<Matrix<M23l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23f__(ref List<Matrix<M23f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23d__(ref List<Matrix<M23d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33i__(ref List<Matrix<M33i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33l__(ref List<Matrix<M33l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33f__(ref List<Matrix<M33f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33d__(ref List<Matrix<M33d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34i__(ref List<Matrix<M34i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34l__(ref List<Matrix<M34l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34f__(ref List<Matrix<M34f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34d__(ref List<Matrix<M34d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44i__(ref List<Matrix<M44i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44l__(ref List<Matrix<M44l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44f__(ref List<Matrix<M44f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44d__(ref List<Matrix<M44d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3b__(ref List<Matrix<C3b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3us__(ref List<Matrix<C3us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3ui__(ref List<Matrix<C3ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3f__(ref List<Matrix<C3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3d__(ref List<Matrix<C3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4b__(ref List<Matrix<C4b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4us__(ref List<Matrix<C4us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4ui__(ref List<Matrix<C4ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4f__(ref List<Matrix<C4f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4d__(ref List<Matrix<C4d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1b__(ref List<Matrix<Range1b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1sb__(ref List<Matrix<Range1sb>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1s__(ref List<Matrix<Range1s>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1us__(ref List<Matrix<Range1us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1i__(ref List<Matrix<Range1i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1ui__(ref List<Matrix<Range1ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1l__(ref List<Matrix<Range1l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1ul__(ref List<Matrix<Range1ul>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1f__(ref List<Matrix<Range1f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1d__(ref List<Matrix<Range1d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2i__(ref List<Matrix<Box2i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2l__(ref List<Matrix<Box2l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2f__(ref List<Matrix<Box2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2d__(ref List<Matrix<Box2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3i__(ref List<Matrix<Box3i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3l__(ref List<Matrix<Box3l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3f__(ref List<Matrix<Box3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3d__(ref List<Matrix<Box3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Euclidean3f__(ref List<Matrix<Euclidean3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Euclidean3d__(ref List<Matrix<Euclidean3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot2f__(ref List<Matrix<Rot2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot2d__(ref List<Matrix<Rot2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot3f__(ref List<Matrix<Rot3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot3d__(ref List<Matrix<Rot3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Scale3f__(ref List<Matrix<Scale3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Scale3d__(ref List<Matrix<Scale3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Shift3f__(ref List<Matrix<Shift3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Shift3d__(ref List<Matrix<Shift3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo2f__(ref List<Matrix<Trafo2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo2d__(ref List<Matrix<Trafo2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo3f__(ref List<Matrix<Trafo3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo3d__(ref List<Matrix<Trafo3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Bool__(ref List<Matrix<bool>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Char__(ref List<Matrix<char>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_String__(ref List<Matrix<string>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Type__(ref List<Matrix<Type>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Guid__(ref List<Matrix<Guid>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Symbol__(ref List<Matrix<Symbol>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Circle2d__(ref List<Matrix<Circle2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line2d__(ref List<Matrix<Line2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line3d__(ref List<Matrix<Line3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane2d__(ref List<Matrix<Plane2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane3d__(ref List<Matrix<Plane3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3d__(ref List<Matrix<PlaneWithPoint3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad2d__(ref List<Matrix<Quad2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad3d__(ref List<Matrix<Quad3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray2d__(ref List<Matrix<Ray2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray3d__(ref List<Matrix<Ray3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Sphere3d__(ref List<Matrix<Sphere3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle2d__(ref List<Matrix<Triangle2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle3d__(ref List<Matrix<Triangle3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Circle2f__(ref List<Matrix<Circle2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line2f__(ref List<Matrix<Line2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line3f__(ref List<Matrix<Line3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane2f__(ref List<Matrix<Plane2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane3f__(ref List<Matrix<Plane3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3f__(ref List<Matrix<PlaneWithPoint3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad2f__(ref List<Matrix<Quad2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad3f__(ref List<Matrix<Quad3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray2f__(ref List<Matrix<Ray2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray3f__(ref List<Matrix<Ray3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Sphere3f__(ref List<Matrix<Sphere3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle2f__(ref List<Matrix<Triangle2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle3f__(ref List<Matrix<Triangle3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Byte__(ref List<Volume<byte>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_SByte__(ref List<Volume<sbyte>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Short__(ref List<Volume<short>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_UShort__(ref List<Volume<ushort>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Int__(ref List<Volume<int>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_UInt__(ref List<Volume<uint>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Long__(ref List<Volume<long>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_ULong__(ref List<Volume<ulong>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Float__(ref List<Volume<float>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Double__(ref List<Volume<double>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Fraction__(ref List<Volume<Fraction>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2i__(ref List<Volume<V2i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2l__(ref List<Volume<V2l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2f__(ref List<Volume<V2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2d__(ref List<Volume<V2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3i__(ref List<Volume<V3i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3l__(ref List<Volume<V3l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3f__(ref List<Volume<V3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3d__(ref List<Volume<V3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4i__(ref List<Volume<V4i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4l__(ref List<Volume<V4l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4f__(ref List<Volume<V4f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4d__(ref List<Volume<V4d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22i__(ref List<Volume<M22i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22l__(ref List<Volume<M22l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22f__(ref List<Volume<M22f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22d__(ref List<Volume<M22d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23i__(ref List<Volume<M23i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23l__(ref List<Volume<M23l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23f__(ref List<Volume<M23f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23d__(ref List<Volume<M23d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33i__(ref List<Volume<M33i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33l__(ref List<Volume<M33l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33f__(ref List<Volume<M33f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33d__(ref List<Volume<M33d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34i__(ref List<Volume<M34i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34l__(ref List<Volume<M34l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34f__(ref List<Volume<M34f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34d__(ref List<Volume<M34d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44i__(ref List<Volume<M44i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44l__(ref List<Volume<M44l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44f__(ref List<Volume<M44f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44d__(ref List<Volume<M44d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3b__(ref List<Volume<C3b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3us__(ref List<Volume<C3us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3ui__(ref List<Volume<C3ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3f__(ref List<Volume<C3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3d__(ref List<Volume<C3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4b__(ref List<Volume<C4b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4us__(ref List<Volume<C4us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4ui__(ref List<Volume<C4ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4f__(ref List<Volume<C4f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4d__(ref List<Volume<C4d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1b__(ref List<Volume<Range1b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1sb__(ref List<Volume<Range1sb>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1s__(ref List<Volume<Range1s>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1us__(ref List<Volume<Range1us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1i__(ref List<Volume<Range1i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1ui__(ref List<Volume<Range1ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1l__(ref List<Volume<Range1l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1ul__(ref List<Volume<Range1ul>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1f__(ref List<Volume<Range1f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1d__(ref List<Volume<Range1d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2i__(ref List<Volume<Box2i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2l__(ref List<Volume<Box2l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2f__(ref List<Volume<Box2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2d__(ref List<Volume<Box2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3i__(ref List<Volume<Box3i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3l__(ref List<Volume<Box3l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3f__(ref List<Volume<Box3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3d__(ref List<Volume<Box3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Euclidean3f__(ref List<Volume<Euclidean3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Euclidean3d__(ref List<Volume<Euclidean3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot2f__(ref List<Volume<Rot2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot2d__(ref List<Volume<Rot2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot3f__(ref List<Volume<Rot3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot3d__(ref List<Volume<Rot3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Scale3f__(ref List<Volume<Scale3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Scale3d__(ref List<Volume<Scale3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Shift3f__(ref List<Volume<Shift3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Shift3d__(ref List<Volume<Shift3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo2f__(ref List<Volume<Trafo2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo2d__(ref List<Volume<Trafo2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo3f__(ref List<Volume<Trafo3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo3d__(ref List<Volume<Trafo3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Bool__(ref List<Volume<bool>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Char__(ref List<Volume<char>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_String__(ref List<Volume<string>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Type__(ref List<Volume<Type>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Guid__(ref List<Volume<Guid>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Symbol__(ref List<Volume<Symbol>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Circle2d__(ref List<Volume<Circle2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line2d__(ref List<Volume<Line2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line3d__(ref List<Volume<Line3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane2d__(ref List<Volume<Plane2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane3d__(ref List<Volume<Plane3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3d__(ref List<Volume<PlaneWithPoint3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad2d__(ref List<Volume<Quad2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad3d__(ref List<Volume<Quad3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray2d__(ref List<Volume<Ray2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray3d__(ref List<Volume<Ray3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Sphere3d__(ref List<Volume<Sphere3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle2d__(ref List<Volume<Triangle2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle3d__(ref List<Volume<Triangle3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Circle2f__(ref List<Volume<Circle2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line2f__(ref List<Volume<Line2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line3f__(ref List<Volume<Line3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane2f__(ref List<Volume<Plane2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane3f__(ref List<Volume<Plane3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3f__(ref List<Volume<PlaneWithPoint3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad2f__(ref List<Volume<Quad2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad3f__(ref List<Volume<Quad3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray2f__(ref List<Volume<Ray2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray3f__(ref List<Volume<Ray3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Sphere3f__(ref List<Volume<Sphere3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle2f__(ref List<Volume<Triangle2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle3f__(ref List<Volume<Triangle3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Byte__(ref List<Tensor<byte>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_SByte__(ref List<Tensor<sbyte>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Short__(ref List<Tensor<short>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_UShort__(ref List<Tensor<ushort>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Int__(ref List<Tensor<int>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_UInt__(ref List<Tensor<uint>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Long__(ref List<Tensor<long>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_ULong__(ref List<Tensor<ulong>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Float__(ref List<Tensor<float>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Double__(ref List<Tensor<double>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Fraction__(ref List<Tensor<Fraction>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2i__(ref List<Tensor<V2i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2l__(ref List<Tensor<V2l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2f__(ref List<Tensor<V2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2d__(ref List<Tensor<V2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3i__(ref List<Tensor<V3i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3l__(ref List<Tensor<V3l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3f__(ref List<Tensor<V3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3d__(ref List<Tensor<V3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4i__(ref List<Tensor<V4i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4l__(ref List<Tensor<V4l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4f__(ref List<Tensor<V4f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4d__(ref List<Tensor<V4d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22i__(ref List<Tensor<M22i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22l__(ref List<Tensor<M22l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22f__(ref List<Tensor<M22f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22d__(ref List<Tensor<M22d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23i__(ref List<Tensor<M23i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23l__(ref List<Tensor<M23l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23f__(ref List<Tensor<M23f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23d__(ref List<Tensor<M23d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33i__(ref List<Tensor<M33i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33l__(ref List<Tensor<M33l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33f__(ref List<Tensor<M33f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33d__(ref List<Tensor<M33d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34i__(ref List<Tensor<M34i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34l__(ref List<Tensor<M34l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34f__(ref List<Tensor<M34f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34d__(ref List<Tensor<M34d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44i__(ref List<Tensor<M44i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44l__(ref List<Tensor<M44l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44f__(ref List<Tensor<M44f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44d__(ref List<Tensor<M44d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3b__(ref List<Tensor<C3b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3us__(ref List<Tensor<C3us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3ui__(ref List<Tensor<C3ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3f__(ref List<Tensor<C3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3d__(ref List<Tensor<C3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4b__(ref List<Tensor<C4b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4us__(ref List<Tensor<C4us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4ui__(ref List<Tensor<C4ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4f__(ref List<Tensor<C4f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4d__(ref List<Tensor<C4d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1b__(ref List<Tensor<Range1b>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1sb__(ref List<Tensor<Range1sb>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1s__(ref List<Tensor<Range1s>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1us__(ref List<Tensor<Range1us>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1i__(ref List<Tensor<Range1i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1ui__(ref List<Tensor<Range1ui>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1l__(ref List<Tensor<Range1l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1ul__(ref List<Tensor<Range1ul>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1f__(ref List<Tensor<Range1f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1d__(ref List<Tensor<Range1d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2i__(ref List<Tensor<Box2i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2l__(ref List<Tensor<Box2l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2f__(ref List<Tensor<Box2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2d__(ref List<Tensor<Box2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3i__(ref List<Tensor<Box3i>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3l__(ref List<Tensor<Box3l>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3f__(ref List<Tensor<Box3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3d__(ref List<Tensor<Box3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Euclidean3f__(ref List<Tensor<Euclidean3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Euclidean3d__(ref List<Tensor<Euclidean3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot2f__(ref List<Tensor<Rot2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot2d__(ref List<Tensor<Rot2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot3f__(ref List<Tensor<Rot3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot3d__(ref List<Tensor<Rot3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Scale3f__(ref List<Tensor<Scale3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Scale3d__(ref List<Tensor<Scale3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Shift3f__(ref List<Tensor<Shift3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Shift3d__(ref List<Tensor<Shift3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo2f__(ref List<Tensor<Trafo2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo2d__(ref List<Tensor<Trafo2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo3f__(ref List<Tensor<Trafo3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo3d__(ref List<Tensor<Trafo3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Bool__(ref List<Tensor<bool>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Char__(ref List<Tensor<char>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_String__(ref List<Tensor<string>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Type__(ref List<Tensor<Type>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Guid__(ref List<Tensor<Guid>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Symbol__(ref List<Tensor<Symbol>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Circle2d__(ref List<Tensor<Circle2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line2d__(ref List<Tensor<Line2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line3d__(ref List<Tensor<Line3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane2d__(ref List<Tensor<Plane2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane3d__(ref List<Tensor<Plane3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3d__(ref List<Tensor<PlaneWithPoint3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad2d__(ref List<Tensor<Quad2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad3d__(ref List<Tensor<Quad3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray2d__(ref List<Tensor<Ray2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray3d__(ref List<Tensor<Ray3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Sphere3d__(ref List<Tensor<Sphere3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle2d__(ref List<Tensor<Triangle2d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle3d__(ref List<Tensor<Triangle3d>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Circle2f__(ref List<Tensor<Circle2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line2f__(ref List<Tensor<Line2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line3f__(ref List<Tensor<Line3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane2f__(ref List<Tensor<Plane2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane3f__(ref List<Tensor<Plane3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3f__(ref List<Tensor<PlaneWithPoint3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad2f__(ref List<Tensor<Quad2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad3f__(ref List<Tensor<Quad3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray2f__(ref List<Tensor<Ray2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray3f__(ref List<Tensor<Ray3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Sphere3f__(ref List<Tensor<Sphere3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle2f__(ref List<Tensor<Triangle2f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle3f__(ref List<Tensor<Triangle3f>> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        #endregion\r\n    }\r\n\r\n    public partial class XmlReadingCoder\r\n    {\r\n        #region Vectors\r\n\r\n        public void CodeV2i(ref V2i v) { v = V2i.Parse(CurrentValue()); }\r\n        public void CodeV2ui(ref V2ui v) { v = V2ui.Parse(CurrentValue()); }\r\n        public void CodeV2l(ref V2l v) { v = V2l.Parse(CurrentValue()); }\r\n        public void CodeV2f(ref V2f v) { v = V2f.Parse(CurrentValue()); }\r\n        public void CodeV2d(ref V2d v) { v = V2d.Parse(CurrentValue()); }\r\n        public void CodeV3i(ref V3i v) { v = V3i.Parse(CurrentValue()); }\r\n        public void CodeV3ui(ref V3ui v) { v = V3ui.Parse(CurrentValue()); }\r\n        public void CodeV3l(ref V3l v) { v = V3l.Parse(CurrentValue()); }\r\n        public void CodeV3f(ref V3f v) { v = V3f.Parse(CurrentValue()); }\r\n        public void CodeV3d(ref V3d v) { v = V3d.Parse(CurrentValue()); }\r\n        public void CodeV4i(ref V4i v) { v = V4i.Parse(CurrentValue()); }\r\n        public void CodeV4ui(ref V4ui v) { v = V4ui.Parse(CurrentValue()); }\r\n        public void CodeV4l(ref V4l v) { v = V4l.Parse(CurrentValue()); }\r\n        public void CodeV4f(ref V4f v) { v = V4f.Parse(CurrentValue()); }\r\n        public void CodeV4d(ref V4d v) { v = V4d.Parse(CurrentValue()); }\r\n\r\n        #endregion\r\n\r\n        #region Matrices\r\n\r\n        public void CodeM22i(ref M22i v) { v = M22i.Parse(CurrentValue()); }\r\n        public void CodeM22l(ref M22l v) { v = M22l.Parse(CurrentValue()); }\r\n        public void CodeM22f(ref M22f v) { v = M22f.Parse(CurrentValue()); }\r\n        public void CodeM22d(ref M22d v) { v = M22d.Parse(CurrentValue()); }\r\n        public void CodeM23i(ref M23i v) { v = M23i.Parse(CurrentValue()); }\r\n        public void CodeM23l(ref M23l v) { v = M23l.Parse(CurrentValue()); }\r\n        public void CodeM23f(ref M23f v) { v = M23f.Parse(CurrentValue()); }\r\n        public void CodeM23d(ref M23d v) { v = M23d.Parse(CurrentValue()); }\r\n        public void CodeM33i(ref M33i v) { v = M33i.Parse(CurrentValue()); }\r\n        public void CodeM33l(ref M33l v) { v = M33l.Parse(CurrentValue()); }\r\n        public void CodeM33f(ref M33f v) { v = M33f.Parse(CurrentValue()); }\r\n        public void CodeM33d(ref M33d v) { v = M33d.Parse(CurrentValue()); }\r\n        public void CodeM34i(ref M34i v) { v = M34i.Parse(CurrentValue()); }\r\n        public void CodeM34l(ref M34l v) { v = M34l.Parse(CurrentValue()); }\r\n        public void CodeM34f(ref M34f v) { v = M34f.Parse(CurrentValue()); }\r\n        public void CodeM34d(ref M34d v) { v = M34d.Parse(CurrentValue()); }\r\n        public void CodeM44i(ref M44i v) { v = M44i.Parse(CurrentValue()); }\r\n        public void CodeM44l(ref M44l v) { v = M44l.Parse(CurrentValue()); }\r\n        public void CodeM44f(ref M44f v) { v = M44f.Parse(CurrentValue()); }\r\n        public void CodeM44d(ref M44d v) { v = M44d.Parse(CurrentValue()); }\r\n\r\n        #endregion\r\n\r\n        #region Ranges and Boxes\r\n\r\n        public void CodeRange1b(ref Range1b v) { v = Range1b.Parse(CurrentValue()); }\r\n        public void CodeRange1sb(ref Range1sb v) { v = Range1sb.Parse(CurrentValue()); }\r\n        public void CodeRange1s(ref Range1s v) { v = Range1s.Parse(CurrentValue()); }\r\n        public void CodeRange1us(ref Range1us v) { v = Range1us.Parse(CurrentValue()); }\r\n        public void CodeRange1i(ref Range1i v) { v = Range1i.Parse(CurrentValue()); }\r\n        public void CodeRange1ui(ref Range1ui v) { v = Range1ui.Parse(CurrentValue()); }\r\n        public void CodeRange1l(ref Range1l v) { v = Range1l.Parse(CurrentValue()); }\r\n        public void CodeRange1ul(ref Range1ul v) { v = Range1ul.Parse(CurrentValue()); }\r\n        public void CodeRange1f(ref Range1f v) { v = Range1f.Parse(CurrentValue()); }\r\n        public void CodeRange1d(ref Range1d v) { v = Range1d.Parse(CurrentValue()); }\r\n        public void CodeBox2i(ref Box2i v) { v = Box2i.Parse(CurrentValue()); }\r\n        public void CodeBox2l(ref Box2l v) { v = Box2l.Parse(CurrentValue()); }\r\n        public void CodeBox2f(ref Box2f v) { v = Box2f.Parse(CurrentValue()); }\r\n        public void CodeBox2d(ref Box2d v) { v = Box2d.Parse(CurrentValue()); }\r\n        public void CodeBox3i(ref Box3i v) { v = Box3i.Parse(CurrentValue()); }\r\n        public void CodeBox3l(ref Box3l v) { v = Box3l.Parse(CurrentValue()); }\r\n        public void CodeBox3f(ref Box3f v) { v = Box3f.Parse(CurrentValue()); }\r\n        public void CodeBox3d(ref Box3d v) { v = Box3d.Parse(CurrentValue()); }\r\n\r\n        #endregion\r\n\r\n        #region Geometry Types\r\n\r\n        public void CodeCircle2f(ref Circle2f v) { v = Circle2f.Parse(CurrentValue()); }\r\n        public void CodeLine2f(ref Line2f v) { v = Line2f.Parse(CurrentValue()); }\r\n        public void CodeLine3f(ref Line3f v) { v = Line3f.Parse(CurrentValue()); }\r\n        public void CodePlane2f(ref Plane2f v) { v = Plane2f.Parse(CurrentValue()); }\r\n        public void CodePlane3f(ref Plane3f v) { v = Plane3f.Parse(CurrentValue()); }\r\n        public void CodePlaneWithPoint3f(ref PlaneWithPoint3f v) { v = PlaneWithPoint3f.Parse(CurrentValue()); }\r\n        public void CodeQuad2f(ref Quad2f v) { v = Quad2f.Parse(CurrentValue()); }\r\n        public void CodeQuad3f(ref Quad3f v) { v = Quad3f.Parse(CurrentValue()); }\r\n        public void CodeRay2f(ref Ray2f v) { v = Ray2f.Parse(CurrentValue()); }\r\n        public void CodeRay3f(ref Ray3f v) { v = Ray3f.Parse(CurrentValue()); }\r\n        public void CodeSphere3f(ref Sphere3f v) { v = Sphere3f.Parse(CurrentValue()); }\r\n        public void CodeTriangle2f(ref Triangle2f v) { v = Triangle2f.Parse(CurrentValue()); }\r\n        public void CodeTriangle3f(ref Triangle3f v) { v = Triangle3f.Parse(CurrentValue()); }\r\n\r\n        public void CodeCircle2d(ref Circle2d v) { v = Circle2d.Parse(CurrentValue()); }\r\n        public void CodeLine2d(ref Line2d v) { v = Line2d.Parse(CurrentValue()); }\r\n        public void CodeLine3d(ref Line3d v) { v = Line3d.Parse(CurrentValue()); }\r\n        public void CodePlane2d(ref Plane2d v) { v = Plane2d.Parse(CurrentValue()); }\r\n        public void CodePlane3d(ref Plane3d v) { v = Plane3d.Parse(CurrentValue()); }\r\n        public void CodePlaneWithPoint3d(ref PlaneWithPoint3d v) { v = PlaneWithPoint3d.Parse(CurrentValue()); }\r\n        public void CodeQuad2d(ref Quad2d v) { v = Quad2d.Parse(CurrentValue()); }\r\n        public void CodeQuad3d(ref Quad3d v) { v = Quad3d.Parse(CurrentValue()); }\r\n        public void CodeRay2d(ref Ray2d v) { v = Ray2d.Parse(CurrentValue()); }\r\n        public void CodeRay3d(ref Ray3d v) { v = Ray3d.Parse(CurrentValue()); }\r\n        public void CodeSphere3d(ref Sphere3d v) { v = Sphere3d.Parse(CurrentValue()); }\r\n        public void CodeTriangle2d(ref Triangle2d v) { v = Triangle2d.Parse(CurrentValue()); }\r\n        public void CodeTriangle3d(ref Triangle3d v) { v = Triangle3d.Parse(CurrentValue()); }\r\n\r\n        #endregion\r\n\r\n        #region Colors\r\n\r\n        public void CodeC3b(ref C3b v) { v = C3b.Parse(CurrentValue()); }\r\n        public void CodeC3us(ref C3us v) { v = C3us.Parse(CurrentValue()); }\r\n        public void CodeC3ui(ref C3ui v) { v = C3ui.Parse(CurrentValue()); }\r\n        public void CodeC3f(ref C3f v) { v = C3f.Parse(CurrentValue()); }\r\n        public void CodeC3d(ref C3d v) { v = C3d.Parse(CurrentValue()); }\r\n        public void CodeC4b(ref C4b v) { v = C4b.Parse(CurrentValue()); }\r\n        public void CodeC4us(ref C4us v) { v = C4us.Parse(CurrentValue()); }\r\n        public void CodeC4ui(ref C4ui v) { v = C4ui.Parse(CurrentValue()); }\r\n        public void CodeC4f(ref C4f v) { v = C4f.Parse(CurrentValue()); }\r\n        public void CodeC4d(ref C4d v) { v = C4d.Parse(CurrentValue()); }\r\n\r\n        #endregion\r\n\r\n        #region Trafos\r\n\r\n        public void CodeEuclidean3f(ref Euclidean3f v) { v = Euclidean3f.Parse(CurrentValue()); }\r\n        public void CodeEuclidean3d(ref Euclidean3d v) { v = Euclidean3d.Parse(CurrentValue()); }\r\n        public void CodeRot2f(ref Rot2f v) { v = Rot2f.Parse(CurrentValue()); }\r\n        public void CodeRot2d(ref Rot2d v) { v = Rot2d.Parse(CurrentValue()); }\r\n        public void CodeRot3f(ref Rot3f v) { v = Rot3f.Parse(CurrentValue()); }\r\n        public void CodeRot3d(ref Rot3d v) { v = Rot3d.Parse(CurrentValue()); }\r\n        public void CodeScale3f(ref Scale3f v) { v = Scale3f.Parse(CurrentValue()); }\r\n        public void CodeScale3d(ref Scale3d v) { v = Scale3d.Parse(CurrentValue()); }\r\n        public void CodeShift3f(ref Shift3f v) { v = Shift3f.Parse(CurrentValue()); }\r\n        public void CodeShift3d(ref Shift3d v) { v = Shift3d.Parse(CurrentValue()); }\r\n        public void CodeTrafo2f(ref Trafo2f v) { v = Trafo2f.Parse(CurrentValue()); }\r\n        public void CodeTrafo2d(ref Trafo2d v) { v = Trafo2d.Parse(CurrentValue()); }\r\n        public void CodeTrafo3f(ref Trafo3f v) { v = Trafo3f.Parse(CurrentValue()); }\r\n        public void CodeTrafo3d(ref Trafo3d v) { v = Trafo3d.Parse(CurrentValue()); }\r\n\r\n        #endregion\r\n\r\n        #region Tensors\r\n\r\n        public void CodeVector_of_Byte_(ref Vector<byte> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            byte[] data = null; CodeByteArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<byte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_SByte_(ref Vector<sbyte> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            sbyte[] data = null; CodeSByteArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<sbyte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Short_(ref Vector<short> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            short[] data = null; CodeShortArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<short>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_UShort_(ref Vector<ushort> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            ushort[] data = null; CodeUShortArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<ushort>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Int_(ref Vector<int> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            int[] data = null; CodeIntArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<int>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_UInt_(ref Vector<uint> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            uint[] data = null; CodeUIntArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<uint>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Long_(ref Vector<long> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] data = null; CodeLongArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<long>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_ULong_(ref Vector<ulong> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            ulong[] data = null; CodeULongArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<ulong>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Float_(ref Vector<float> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            float[] data = null; CodeFloatArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<float>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Double_(ref Vector<double> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            double[] data = null; CodeDoubleArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<double>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_(ref Vector<Fraction> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Fraction[] data = null; CodeFractionArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Fraction>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2i_(ref Vector<V2i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2i[] data = null; CodeV2iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2l_(ref Vector<V2l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l[] data = null; CodeV2lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2f_(ref Vector<V2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2f[] data = null; CodeV2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V2d_(ref Vector<V2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2d[] data = null; CodeV2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3i_(ref Vector<V3i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3i[] data = null; CodeV3iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3l_(ref Vector<V3l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l[] data = null; CodeV3lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3f_(ref Vector<V3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3f[] data = null; CodeV3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V3d_(ref Vector<V3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3d[] data = null; CodeV3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4i_(ref Vector<V4i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4i[] data = null; CodeV4iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V4i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4l_(ref Vector<V4l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4l[] data = null; CodeV4lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V4l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4f_(ref Vector<V4f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4f[] data = null; CodeV4fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_V4d_(ref Vector<V4d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4d[] data = null; CodeV4dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<V4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22i_(ref Vector<M22i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22i[] data = null; CodeM22iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M22i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22l_(ref Vector<M22l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22l[] data = null; CodeM22lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M22l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22f_(ref Vector<M22f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22f[] data = null; CodeM22fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M22f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M22d_(ref Vector<M22d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22d[] data = null; CodeM22dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M22d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23i_(ref Vector<M23i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23i[] data = null; CodeM23iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M23i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23l_(ref Vector<M23l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23l[] data = null; CodeM23lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M23l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23f_(ref Vector<M23f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23f[] data = null; CodeM23fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M23f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M23d_(ref Vector<M23d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23d[] data = null; CodeM23dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M23d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33i_(ref Vector<M33i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33i[] data = null; CodeM33iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M33i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33l_(ref Vector<M33l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33l[] data = null; CodeM33lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M33l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33f_(ref Vector<M33f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33f[] data = null; CodeM33fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M33f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M33d_(ref Vector<M33d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33d[] data = null; CodeM33dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M33d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34i_(ref Vector<M34i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34i[] data = null; CodeM34iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M34i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34l_(ref Vector<M34l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34l[] data = null; CodeM34lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M34l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34f_(ref Vector<M34f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34f[] data = null; CodeM34fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M34f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M34d_(ref Vector<M34d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34d[] data = null; CodeM34dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M34d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44i_(ref Vector<M44i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44i[] data = null; CodeM44iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M44i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44l_(ref Vector<M44l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44l[] data = null; CodeM44lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M44l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44f_(ref Vector<M44f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44f[] data = null; CodeM44fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M44f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_M44d_(ref Vector<M44d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44d[] data = null; CodeM44dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<M44d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3b_(ref Vector<C3b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3b[] data = null; CodeC3bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C3b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3us_(ref Vector<C3us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3us[] data = null; CodeC3usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C3us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_(ref Vector<C3ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3ui[] data = null; CodeC3uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C3ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3f_(ref Vector<C3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3f[] data = null; CodeC3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C3d_(ref Vector<C3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3d[] data = null; CodeC3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4b_(ref Vector<C4b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4b[] data = null; CodeC4bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C4b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4us_(ref Vector<C4us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4us[] data = null; CodeC4usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C4us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_(ref Vector<C4ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4ui[] data = null; CodeC4uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C4ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4f_(ref Vector<C4f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4f[] data = null; CodeC4fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_C4d_(ref Vector<C4d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4d[] data = null; CodeC4dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<C4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_(ref Vector<Range1b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1b[] data = null; CodeRange1bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_(ref Vector<Range1sb> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1sb[] data = null; CodeRange1sbArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1sb>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_(ref Vector<Range1s> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1s[] data = null; CodeRange1sArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1s>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_(ref Vector<Range1us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1us[] data = null; CodeRange1usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_(ref Vector<Range1i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1i[] data = null; CodeRange1iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_(ref Vector<Range1ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1ui[] data = null; CodeRange1uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_(ref Vector<Range1l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1l[] data = null; CodeRange1lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_(ref Vector<Range1ul> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1ul[] data = null; CodeRange1ulArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1ul>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_(ref Vector<Range1f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1f[] data = null; CodeRange1fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_(ref Vector<Range1d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1d[] data = null; CodeRange1dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Range1d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_(ref Vector<Box2i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2i[] data = null; CodeBox2iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Box2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_(ref Vector<Box2l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2l[] data = null; CodeBox2lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Box2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_(ref Vector<Box2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2f[] data = null; CodeBox2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Box2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_(ref Vector<Box2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2d[] data = null; CodeBox2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Box2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_(ref Vector<Box3i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3i[] data = null; CodeBox3iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Box3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_(ref Vector<Box3l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3l[] data = null; CodeBox3lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Box3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_(ref Vector<Box3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3f[] data = null; CodeBox3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Box3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_(ref Vector<Box3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3d[] data = null; CodeBox3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Box3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_(ref Vector<Euclidean3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Euclidean3f[] data = null; CodeEuclidean3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Euclidean3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_(ref Vector<Euclidean3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Euclidean3d[] data = null; CodeEuclidean3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Euclidean3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_(ref Vector<Rot2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot2f[] data = null; CodeRot2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Rot2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_(ref Vector<Rot2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot2d[] data = null; CodeRot2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Rot2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_(ref Vector<Rot3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot3f[] data = null; CodeRot3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Rot3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_(ref Vector<Rot3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot3d[] data = null; CodeRot3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Rot3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_(ref Vector<Scale3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Scale3f[] data = null; CodeScale3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Scale3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_(ref Vector<Scale3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Scale3d[] data = null; CodeScale3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Scale3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_(ref Vector<Shift3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Shift3f[] data = null; CodeShift3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Shift3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_(ref Vector<Shift3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Shift3d[] data = null; CodeShift3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Shift3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_(ref Vector<Trafo2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo2f[] data = null; CodeTrafo2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Trafo2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_(ref Vector<Trafo2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo2d[] data = null; CodeTrafo2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Trafo2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_(ref Vector<Trafo3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo3f[] data = null; CodeTrafo3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Trafo3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_(ref Vector<Trafo3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo3d[] data = null; CodeTrafo3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Trafo3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Bool_(ref Vector<bool> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            bool[] data = null; CodeBoolArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<bool>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Char_(ref Vector<char> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            char[] data = null; CodeCharArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<char>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_String_(ref Vector<string> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            string[] data = null; CodeStringArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<string>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Type_(ref Vector<Type> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Type[] data = null; CodeTypeArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Type>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Guid_(ref Vector<Guid> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Guid[] data = null; CodeGuidArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Guid>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_(ref Vector<Symbol> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Symbol[] data = null; CodeSymbolArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Symbol>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_(ref Vector<Circle2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Circle2d[] data = null; CodeCircle2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Circle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_(ref Vector<Line2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line2d[] data = null; CodeLine2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Line2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_(ref Vector<Line3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line3d[] data = null; CodeLine3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Line3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_(ref Vector<Plane2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane2d[] data = null; CodePlane2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Plane2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_(ref Vector<Plane3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane3d[] data = null; CodePlane3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Plane3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_(ref Vector<PlaneWithPoint3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            PlaneWithPoint3d[] data = null; CodePlaneWithPoint3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<PlaneWithPoint3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_(ref Vector<Quad2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad2d[] data = null; CodeQuad2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Quad2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_(ref Vector<Quad3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad3d[] data = null; CodeQuad3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Quad3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_(ref Vector<Ray2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray2d[] data = null; CodeRay2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Ray2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_(ref Vector<Ray3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray3d[] data = null; CodeRay3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Ray3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_(ref Vector<Sphere3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Sphere3d[] data = null; CodeSphere3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Sphere3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_(ref Vector<Triangle2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle2d[] data = null; CodeTriangle2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Triangle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_(ref Vector<Triangle3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle3d[] data = null; CodeTriangle3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Triangle3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_(ref Vector<Circle2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Circle2f[] data = null; CodeCircle2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Circle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_(ref Vector<Line2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line2f[] data = null; CodeLine2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Line2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_(ref Vector<Line3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line3f[] data = null; CodeLine3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Line3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_(ref Vector<Plane2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane2f[] data = null; CodePlane2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Plane2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_(ref Vector<Plane3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane3f[] data = null; CodePlane3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Plane3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_(ref Vector<PlaneWithPoint3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            PlaneWithPoint3f[] data = null; CodePlaneWithPoint3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<PlaneWithPoint3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_(ref Vector<Quad2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad2f[] data = null; CodeQuad2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Quad2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_(ref Vector<Quad3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad3f[] data = null; CodeQuad3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Quad3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_(ref Vector<Ray2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray2f[] data = null; CodeRay2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Ray2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_(ref Vector<Ray3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray3f[] data = null; CodeRay3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Ray3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_(ref Vector<Sphere3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Sphere3f[] data = null; CodeSphere3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Sphere3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_(ref Vector<Triangle2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle2f[] data = null; CodeTriangle2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Triangle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_(ref Vector<Triangle3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle3f[] data = null; CodeTriangle3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long size = default(long); CodeLong(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long delta = default(long); CodeLong(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Vector<Triangle3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_(ref Matrix<byte> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            byte[] data = null; CodeByteArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<byte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_(ref Matrix<sbyte> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            sbyte[] data = null; CodeSByteArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<sbyte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_(ref Matrix<short> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            short[] data = null; CodeShortArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<short>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_(ref Matrix<ushort> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            ushort[] data = null; CodeUShortArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<ushort>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_(ref Matrix<int> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            int[] data = null; CodeIntArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<int>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_(ref Matrix<uint> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            uint[] data = null; CodeUIntArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<uint>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_(ref Matrix<long> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] data = null; CodeLongArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<long>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_(ref Matrix<ulong> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            ulong[] data = null; CodeULongArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<ulong>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_(ref Matrix<float> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            float[] data = null; CodeFloatArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<float>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_(ref Matrix<double> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            double[] data = null; CodeDoubleArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<double>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_(ref Matrix<Fraction> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Fraction[] data = null; CodeFractionArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Fraction>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_(ref Matrix<V2i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2i[] data = null; CodeV2iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_(ref Matrix<V2l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l[] data = null; CodeV2lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_(ref Matrix<V2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2f[] data = null; CodeV2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_(ref Matrix<V2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2d[] data = null; CodeV2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_(ref Matrix<V3i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3i[] data = null; CodeV3iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_(ref Matrix<V3l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l[] data = null; CodeV3lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_(ref Matrix<V3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3f[] data = null; CodeV3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_(ref Matrix<V3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3d[] data = null; CodeV3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_(ref Matrix<V4i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4i[] data = null; CodeV4iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V4i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_(ref Matrix<V4l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4l[] data = null; CodeV4lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V4l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_(ref Matrix<V4f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4f[] data = null; CodeV4fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_(ref Matrix<V4d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4d[] data = null; CodeV4dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<V4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_(ref Matrix<M22i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22i[] data = null; CodeM22iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M22i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_(ref Matrix<M22l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22l[] data = null; CodeM22lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M22l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_(ref Matrix<M22f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22f[] data = null; CodeM22fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M22f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_(ref Matrix<M22d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22d[] data = null; CodeM22dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M22d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_(ref Matrix<M23i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23i[] data = null; CodeM23iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M23i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_(ref Matrix<M23l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23l[] data = null; CodeM23lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M23l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_(ref Matrix<M23f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23f[] data = null; CodeM23fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M23f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_(ref Matrix<M23d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23d[] data = null; CodeM23dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M23d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_(ref Matrix<M33i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33i[] data = null; CodeM33iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M33i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_(ref Matrix<M33l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33l[] data = null; CodeM33lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M33l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_(ref Matrix<M33f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33f[] data = null; CodeM33fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M33f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_(ref Matrix<M33d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33d[] data = null; CodeM33dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M33d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_(ref Matrix<M34i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34i[] data = null; CodeM34iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M34i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_(ref Matrix<M34l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34l[] data = null; CodeM34lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M34l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_(ref Matrix<M34f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34f[] data = null; CodeM34fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M34f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_(ref Matrix<M34d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34d[] data = null; CodeM34dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M34d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_(ref Matrix<M44i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44i[] data = null; CodeM44iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M44i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_(ref Matrix<M44l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44l[] data = null; CodeM44lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M44l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_(ref Matrix<M44f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44f[] data = null; CodeM44fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M44f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_(ref Matrix<M44d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44d[] data = null; CodeM44dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<M44d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_(ref Matrix<C3b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3b[] data = null; CodeC3bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C3b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_(ref Matrix<C3us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3us[] data = null; CodeC3usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C3us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_(ref Matrix<C3ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3ui[] data = null; CodeC3uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C3ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_(ref Matrix<C3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3f[] data = null; CodeC3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_(ref Matrix<C3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3d[] data = null; CodeC3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_(ref Matrix<C4b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4b[] data = null; CodeC4bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C4b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_(ref Matrix<C4us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4us[] data = null; CodeC4usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C4us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_(ref Matrix<C4ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4ui[] data = null; CodeC4uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C4ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_(ref Matrix<C4f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4f[] data = null; CodeC4fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_(ref Matrix<C4d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4d[] data = null; CodeC4dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<C4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_(ref Matrix<Range1b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1b[] data = null; CodeRange1bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_(ref Matrix<Range1sb> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1sb[] data = null; CodeRange1sbArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1sb>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_(ref Matrix<Range1s> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1s[] data = null; CodeRange1sArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1s>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_(ref Matrix<Range1us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1us[] data = null; CodeRange1usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_(ref Matrix<Range1i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1i[] data = null; CodeRange1iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_(ref Matrix<Range1ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1ui[] data = null; CodeRange1uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_(ref Matrix<Range1l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1l[] data = null; CodeRange1lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_(ref Matrix<Range1ul> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1ul[] data = null; CodeRange1ulArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1ul>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_(ref Matrix<Range1f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1f[] data = null; CodeRange1fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_(ref Matrix<Range1d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1d[] data = null; CodeRange1dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Range1d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_(ref Matrix<Box2i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2i[] data = null; CodeBox2iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Box2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_(ref Matrix<Box2l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2l[] data = null; CodeBox2lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Box2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_(ref Matrix<Box2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2f[] data = null; CodeBox2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Box2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_(ref Matrix<Box2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2d[] data = null; CodeBox2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Box2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_(ref Matrix<Box3i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3i[] data = null; CodeBox3iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Box3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_(ref Matrix<Box3l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3l[] data = null; CodeBox3lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Box3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_(ref Matrix<Box3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3f[] data = null; CodeBox3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Box3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_(ref Matrix<Box3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3d[] data = null; CodeBox3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Box3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_(ref Matrix<Euclidean3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Euclidean3f[] data = null; CodeEuclidean3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Euclidean3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_(ref Matrix<Euclidean3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Euclidean3d[] data = null; CodeEuclidean3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Euclidean3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_(ref Matrix<Rot2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot2f[] data = null; CodeRot2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Rot2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_(ref Matrix<Rot2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot2d[] data = null; CodeRot2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Rot2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_(ref Matrix<Rot3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot3f[] data = null; CodeRot3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Rot3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_(ref Matrix<Rot3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot3d[] data = null; CodeRot3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Rot3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_(ref Matrix<Scale3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Scale3f[] data = null; CodeScale3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Scale3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_(ref Matrix<Scale3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Scale3d[] data = null; CodeScale3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Scale3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_(ref Matrix<Shift3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Shift3f[] data = null; CodeShift3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Shift3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_(ref Matrix<Shift3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Shift3d[] data = null; CodeShift3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Shift3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_(ref Matrix<Trafo2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo2f[] data = null; CodeTrafo2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Trafo2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_(ref Matrix<Trafo2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo2d[] data = null; CodeTrafo2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Trafo2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_(ref Matrix<Trafo3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo3f[] data = null; CodeTrafo3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Trafo3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_(ref Matrix<Trafo3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo3d[] data = null; CodeTrafo3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Trafo3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_(ref Matrix<bool> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            bool[] data = null; CodeBoolArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<bool>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_(ref Matrix<char> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            char[] data = null; CodeCharArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<char>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_String_(ref Matrix<string> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            string[] data = null; CodeStringArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<string>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_(ref Matrix<Type> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Type[] data = null; CodeTypeArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Type>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_(ref Matrix<Guid> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Guid[] data = null; CodeGuidArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Guid>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_(ref Matrix<Symbol> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Symbol[] data = null; CodeSymbolArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Symbol>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_(ref Matrix<Circle2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Circle2d[] data = null; CodeCircle2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Circle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_(ref Matrix<Line2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line2d[] data = null; CodeLine2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Line2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_(ref Matrix<Line3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line3d[] data = null; CodeLine3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Line3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_(ref Matrix<Plane2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane2d[] data = null; CodePlane2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Plane2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_(ref Matrix<Plane3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane3d[] data = null; CodePlane3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Plane3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_(ref Matrix<PlaneWithPoint3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            PlaneWithPoint3d[] data = null; CodePlaneWithPoint3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<PlaneWithPoint3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_(ref Matrix<Quad2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad2d[] data = null; CodeQuad2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Quad2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_(ref Matrix<Quad3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad3d[] data = null; CodeQuad3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Quad3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_(ref Matrix<Ray2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray2d[] data = null; CodeRay2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Ray2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_(ref Matrix<Ray3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray3d[] data = null; CodeRay3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Ray3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_(ref Matrix<Sphere3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Sphere3d[] data = null; CodeSphere3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Sphere3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_(ref Matrix<Triangle2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle2d[] data = null; CodeTriangle2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Triangle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_(ref Matrix<Triangle3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle3d[] data = null; CodeTriangle3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Triangle3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_(ref Matrix<Circle2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Circle2f[] data = null; CodeCircle2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Circle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_(ref Matrix<Line2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line2f[] data = null; CodeLine2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Line2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_(ref Matrix<Line3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line3f[] data = null; CodeLine3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Line3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_(ref Matrix<Plane2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane2f[] data = null; CodePlane2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Plane2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_(ref Matrix<Plane3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane3f[] data = null; CodePlane3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Plane3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_(ref Matrix<PlaneWithPoint3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            PlaneWithPoint3f[] data = null; CodePlaneWithPoint3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<PlaneWithPoint3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_(ref Matrix<Quad2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad2f[] data = null; CodeQuad2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Quad2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_(ref Matrix<Quad3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad3f[] data = null; CodeQuad3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Quad3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_(ref Matrix<Ray2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray2f[] data = null; CodeRay2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Ray2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_(ref Matrix<Ray3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray3f[] data = null; CodeRay3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Ray3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_(ref Matrix<Sphere3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Sphere3f[] data = null; CodeSphere3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Sphere3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_(ref Matrix<Triangle2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle2f[] data = null; CodeTriangle2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Triangle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_(ref Matrix<Triangle3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle3f[] data = null; CodeTriangle3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l size = default(V2l); CodeV2l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l delta = default(V2l); CodeV2l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Matrix<Triangle3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_(ref Volume<byte> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            byte[] data = null; CodeByteArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<byte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_(ref Volume<sbyte> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            sbyte[] data = null; CodeSByteArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<sbyte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Short_(ref Volume<short> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            short[] data = null; CodeShortArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<short>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_(ref Volume<ushort> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            ushort[] data = null; CodeUShortArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<ushort>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Int_(ref Volume<int> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            int[] data = null; CodeIntArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<int>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_(ref Volume<uint> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            uint[] data = null; CodeUIntArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<uint>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Long_(ref Volume<long> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] data = null; CodeLongArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<long>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_(ref Volume<ulong> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            ulong[] data = null; CodeULongArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<ulong>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Float_(ref Volume<float> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            float[] data = null; CodeFloatArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<float>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Double_(ref Volume<double> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            double[] data = null; CodeDoubleArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<double>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_(ref Volume<Fraction> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Fraction[] data = null; CodeFractionArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Fraction>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_(ref Volume<V2i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2i[] data = null; CodeV2iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_(ref Volume<V2l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l[] data = null; CodeV2lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_(ref Volume<V2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2f[] data = null; CodeV2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_(ref Volume<V2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2d[] data = null; CodeV2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_(ref Volume<V3i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3i[] data = null; CodeV3iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_(ref Volume<V3l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l[] data = null; CodeV3lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_(ref Volume<V3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3f[] data = null; CodeV3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_(ref Volume<V3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3d[] data = null; CodeV3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_(ref Volume<V4i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4i[] data = null; CodeV4iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V4i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_(ref Volume<V4l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4l[] data = null; CodeV4lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V4l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_(ref Volume<V4f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4f[] data = null; CodeV4fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_(ref Volume<V4d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4d[] data = null; CodeV4dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<V4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_(ref Volume<M22i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22i[] data = null; CodeM22iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M22i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_(ref Volume<M22l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22l[] data = null; CodeM22lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M22l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_(ref Volume<M22f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22f[] data = null; CodeM22fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M22f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_(ref Volume<M22d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22d[] data = null; CodeM22dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M22d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_(ref Volume<M23i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23i[] data = null; CodeM23iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M23i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_(ref Volume<M23l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23l[] data = null; CodeM23lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M23l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_(ref Volume<M23f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23f[] data = null; CodeM23fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M23f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_(ref Volume<M23d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23d[] data = null; CodeM23dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M23d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_(ref Volume<M33i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33i[] data = null; CodeM33iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M33i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_(ref Volume<M33l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33l[] data = null; CodeM33lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M33l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_(ref Volume<M33f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33f[] data = null; CodeM33fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M33f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_(ref Volume<M33d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33d[] data = null; CodeM33dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M33d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_(ref Volume<M34i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34i[] data = null; CodeM34iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M34i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_(ref Volume<M34l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34l[] data = null; CodeM34lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M34l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_(ref Volume<M34f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34f[] data = null; CodeM34fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M34f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_(ref Volume<M34d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34d[] data = null; CodeM34dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M34d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_(ref Volume<M44i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44i[] data = null; CodeM44iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M44i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_(ref Volume<M44l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44l[] data = null; CodeM44lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M44l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_(ref Volume<M44f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44f[] data = null; CodeM44fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M44f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_(ref Volume<M44d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44d[] data = null; CodeM44dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<M44d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_(ref Volume<C3b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3b[] data = null; CodeC3bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C3b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_(ref Volume<C3us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3us[] data = null; CodeC3usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C3us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_(ref Volume<C3ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3ui[] data = null; CodeC3uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C3ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_(ref Volume<C3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3f[] data = null; CodeC3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_(ref Volume<C3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3d[] data = null; CodeC3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_(ref Volume<C4b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4b[] data = null; CodeC4bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C4b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_(ref Volume<C4us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4us[] data = null; CodeC4usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C4us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_(ref Volume<C4ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4ui[] data = null; CodeC4uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C4ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_(ref Volume<C4f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4f[] data = null; CodeC4fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_(ref Volume<C4d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4d[] data = null; CodeC4dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<C4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_(ref Volume<Range1b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1b[] data = null; CodeRange1bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_(ref Volume<Range1sb> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1sb[] data = null; CodeRange1sbArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1sb>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_(ref Volume<Range1s> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1s[] data = null; CodeRange1sArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1s>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_(ref Volume<Range1us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1us[] data = null; CodeRange1usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_(ref Volume<Range1i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1i[] data = null; CodeRange1iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_(ref Volume<Range1ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1ui[] data = null; CodeRange1uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_(ref Volume<Range1l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1l[] data = null; CodeRange1lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_(ref Volume<Range1ul> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1ul[] data = null; CodeRange1ulArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1ul>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_(ref Volume<Range1f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1f[] data = null; CodeRange1fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_(ref Volume<Range1d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1d[] data = null; CodeRange1dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Range1d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_(ref Volume<Box2i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2i[] data = null; CodeBox2iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Box2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_(ref Volume<Box2l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2l[] data = null; CodeBox2lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Box2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_(ref Volume<Box2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2f[] data = null; CodeBox2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Box2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_(ref Volume<Box2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2d[] data = null; CodeBox2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Box2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_(ref Volume<Box3i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3i[] data = null; CodeBox3iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Box3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_(ref Volume<Box3l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3l[] data = null; CodeBox3lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Box3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_(ref Volume<Box3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3f[] data = null; CodeBox3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Box3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_(ref Volume<Box3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3d[] data = null; CodeBox3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Box3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_(ref Volume<Euclidean3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Euclidean3f[] data = null; CodeEuclidean3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Euclidean3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_(ref Volume<Euclidean3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Euclidean3d[] data = null; CodeEuclidean3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Euclidean3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_(ref Volume<Rot2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot2f[] data = null; CodeRot2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Rot2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_(ref Volume<Rot2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot2d[] data = null; CodeRot2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Rot2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_(ref Volume<Rot3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot3f[] data = null; CodeRot3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Rot3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_(ref Volume<Rot3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot3d[] data = null; CodeRot3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Rot3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_(ref Volume<Scale3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Scale3f[] data = null; CodeScale3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Scale3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_(ref Volume<Scale3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Scale3d[] data = null; CodeScale3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Scale3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_(ref Volume<Shift3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Shift3f[] data = null; CodeShift3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Shift3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_(ref Volume<Shift3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Shift3d[] data = null; CodeShift3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Shift3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_(ref Volume<Trafo2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo2f[] data = null; CodeTrafo2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Trafo2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_(ref Volume<Trafo2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo2d[] data = null; CodeTrafo2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Trafo2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_(ref Volume<Trafo3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo3f[] data = null; CodeTrafo3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Trafo3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_(ref Volume<Trafo3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo3d[] data = null; CodeTrafo3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Trafo3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_(ref Volume<bool> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            bool[] data = null; CodeBoolArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<bool>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Char_(ref Volume<char> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            char[] data = null; CodeCharArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<char>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_String_(ref Volume<string> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            string[] data = null; CodeStringArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<string>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Type_(ref Volume<Type> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Type[] data = null; CodeTypeArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Type>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_(ref Volume<Guid> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Guid[] data = null; CodeGuidArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Guid>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_(ref Volume<Symbol> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Symbol[] data = null; CodeSymbolArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Symbol>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_(ref Volume<Circle2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Circle2d[] data = null; CodeCircle2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Circle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_(ref Volume<Line2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line2d[] data = null; CodeLine2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Line2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_(ref Volume<Line3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line3d[] data = null; CodeLine3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Line3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_(ref Volume<Plane2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane2d[] data = null; CodePlane2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Plane2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_(ref Volume<Plane3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane3d[] data = null; CodePlane3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Plane3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_(ref Volume<PlaneWithPoint3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            PlaneWithPoint3d[] data = null; CodePlaneWithPoint3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<PlaneWithPoint3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_(ref Volume<Quad2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad2d[] data = null; CodeQuad2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Quad2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_(ref Volume<Quad3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad3d[] data = null; CodeQuad3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Quad3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_(ref Volume<Ray2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray2d[] data = null; CodeRay2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Ray2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_(ref Volume<Ray3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray3d[] data = null; CodeRay3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Ray3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_(ref Volume<Sphere3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Sphere3d[] data = null; CodeSphere3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Sphere3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_(ref Volume<Triangle2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle2d[] data = null; CodeTriangle2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Triangle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_(ref Volume<Triangle3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle3d[] data = null; CodeTriangle3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Triangle3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_(ref Volume<Circle2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Circle2f[] data = null; CodeCircle2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Circle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_(ref Volume<Line2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line2f[] data = null; CodeLine2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Line2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_(ref Volume<Line3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line3f[] data = null; CodeLine3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Line3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_(ref Volume<Plane2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane2f[] data = null; CodePlane2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Plane2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_(ref Volume<Plane3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane3f[] data = null; CodePlane3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Plane3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_(ref Volume<PlaneWithPoint3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            PlaneWithPoint3f[] data = null; CodePlaneWithPoint3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<PlaneWithPoint3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_(ref Volume<Quad2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad2f[] data = null; CodeQuad2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Quad2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_(ref Volume<Quad3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad3f[] data = null; CodeQuad3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Quad3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_(ref Volume<Ray2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray2f[] data = null; CodeRay2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Ray2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_(ref Volume<Ray3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray3f[] data = null; CodeRay3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Ray3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_(ref Volume<Sphere3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Sphere3f[] data = null; CodeSphere3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Sphere3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_(ref Volume<Triangle2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle2f[] data = null; CodeTriangle2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Triangle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_(ref Volume<Triangle3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle3f[] data = null; CodeTriangle3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l size = default(V3l); CodeV3l(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l delta = default(V3l); CodeV3l(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Volume<Triangle3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_(ref Tensor<byte> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            byte[] data = null; CodeByteArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<byte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_(ref Tensor<sbyte> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            sbyte[] data = null; CodeSByteArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<sbyte>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Short_(ref Tensor<short> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            short[] data = null; CodeShortArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<short>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_(ref Tensor<ushort> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            ushort[] data = null; CodeUShortArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<ushort>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Int_(ref Tensor<int> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            int[] data = null; CodeIntArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<int>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_(ref Tensor<uint> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            uint[] data = null; CodeUIntArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<uint>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Long_(ref Tensor<long> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] data = null; CodeLongArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<long>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_(ref Tensor<ulong> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            ulong[] data = null; CodeULongArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<ulong>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Float_(ref Tensor<float> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            float[] data = null; CodeFloatArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<float>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Double_(ref Tensor<double> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            double[] data = null; CodeDoubleArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<double>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_(ref Tensor<Fraction> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Fraction[] data = null; CodeFractionArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Fraction>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_(ref Tensor<V2i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2i[] data = null; CodeV2iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_(ref Tensor<V2l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2l[] data = null; CodeV2lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_(ref Tensor<V2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2f[] data = null; CodeV2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_(ref Tensor<V2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V2d[] data = null; CodeV2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_(ref Tensor<V3i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3i[] data = null; CodeV3iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_(ref Tensor<V3l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3l[] data = null; CodeV3lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_(ref Tensor<V3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3f[] data = null; CodeV3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_(ref Tensor<V3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V3d[] data = null; CodeV3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_(ref Tensor<V4i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4i[] data = null; CodeV4iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V4i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_(ref Tensor<V4l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4l[] data = null; CodeV4lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V4l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_(ref Tensor<V4f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4f[] data = null; CodeV4fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_(ref Tensor<V4d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            V4d[] data = null; CodeV4dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<V4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_(ref Tensor<M22i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22i[] data = null; CodeM22iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M22i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_(ref Tensor<M22l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22l[] data = null; CodeM22lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M22l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_(ref Tensor<M22f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22f[] data = null; CodeM22fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M22f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_(ref Tensor<M22d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M22d[] data = null; CodeM22dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M22d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_(ref Tensor<M23i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23i[] data = null; CodeM23iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M23i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_(ref Tensor<M23l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23l[] data = null; CodeM23lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M23l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_(ref Tensor<M23f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23f[] data = null; CodeM23fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M23f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_(ref Tensor<M23d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M23d[] data = null; CodeM23dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M23d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_(ref Tensor<M33i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33i[] data = null; CodeM33iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M33i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_(ref Tensor<M33l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33l[] data = null; CodeM33lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M33l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_(ref Tensor<M33f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33f[] data = null; CodeM33fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M33f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_(ref Tensor<M33d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M33d[] data = null; CodeM33dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M33d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_(ref Tensor<M34i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34i[] data = null; CodeM34iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M34i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_(ref Tensor<M34l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34l[] data = null; CodeM34lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M34l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_(ref Tensor<M34f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34f[] data = null; CodeM34fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M34f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_(ref Tensor<M34d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M34d[] data = null; CodeM34dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M34d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_(ref Tensor<M44i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44i[] data = null; CodeM44iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M44i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_(ref Tensor<M44l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44l[] data = null; CodeM44lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M44l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_(ref Tensor<M44f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44f[] data = null; CodeM44fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M44f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_(ref Tensor<M44d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            M44d[] data = null; CodeM44dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<M44d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_(ref Tensor<C3b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3b[] data = null; CodeC3bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C3b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_(ref Tensor<C3us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3us[] data = null; CodeC3usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C3us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_(ref Tensor<C3ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3ui[] data = null; CodeC3uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C3ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_(ref Tensor<C3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3f[] data = null; CodeC3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_(ref Tensor<C3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C3d[] data = null; CodeC3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_(ref Tensor<C4b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4b[] data = null; CodeC4bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C4b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_(ref Tensor<C4us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4us[] data = null; CodeC4usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C4us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_(ref Tensor<C4ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4ui[] data = null; CodeC4uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C4ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_(ref Tensor<C4f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4f[] data = null; CodeC4fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C4f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_(ref Tensor<C4d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            C4d[] data = null; CodeC4dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<C4d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_(ref Tensor<Range1b> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1b[] data = null; CodeRange1bArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1b>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_(ref Tensor<Range1sb> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1sb[] data = null; CodeRange1sbArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1sb>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_(ref Tensor<Range1s> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1s[] data = null; CodeRange1sArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1s>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_(ref Tensor<Range1us> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1us[] data = null; CodeRange1usArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1us>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_(ref Tensor<Range1i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1i[] data = null; CodeRange1iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_(ref Tensor<Range1ui> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1ui[] data = null; CodeRange1uiArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1ui>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_(ref Tensor<Range1l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1l[] data = null; CodeRange1lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_(ref Tensor<Range1ul> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1ul[] data = null; CodeRange1ulArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1ul>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_(ref Tensor<Range1f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1f[] data = null; CodeRange1fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_(ref Tensor<Range1d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Range1d[] data = null; CodeRange1dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Range1d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_(ref Tensor<Box2i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2i[] data = null; CodeBox2iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Box2i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_(ref Tensor<Box2l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2l[] data = null; CodeBox2lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Box2l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_(ref Tensor<Box2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2f[] data = null; CodeBox2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Box2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_(ref Tensor<Box2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box2d[] data = null; CodeBox2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Box2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_(ref Tensor<Box3i> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3i[] data = null; CodeBox3iArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Box3i>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_(ref Tensor<Box3l> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3l[] data = null; CodeBox3lArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Box3l>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_(ref Tensor<Box3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3f[] data = null; CodeBox3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Box3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_(ref Tensor<Box3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Box3d[] data = null; CodeBox3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Box3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_(ref Tensor<Euclidean3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Euclidean3f[] data = null; CodeEuclidean3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Euclidean3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_(ref Tensor<Euclidean3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Euclidean3d[] data = null; CodeEuclidean3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Euclidean3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_(ref Tensor<Rot2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot2f[] data = null; CodeRot2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Rot2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_(ref Tensor<Rot2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot2d[] data = null; CodeRot2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Rot2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_(ref Tensor<Rot3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot3f[] data = null; CodeRot3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Rot3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_(ref Tensor<Rot3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Rot3d[] data = null; CodeRot3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Rot3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_(ref Tensor<Scale3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Scale3f[] data = null; CodeScale3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Scale3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_(ref Tensor<Scale3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Scale3d[] data = null; CodeScale3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Scale3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_(ref Tensor<Shift3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Shift3f[] data = null; CodeShift3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Shift3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_(ref Tensor<Shift3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Shift3d[] data = null; CodeShift3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Shift3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_(ref Tensor<Trafo2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo2f[] data = null; CodeTrafo2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Trafo2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_(ref Tensor<Trafo2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo2d[] data = null; CodeTrafo2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Trafo2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_(ref Tensor<Trafo3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo3f[] data = null; CodeTrafo3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Trafo3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_(ref Tensor<Trafo3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Trafo3d[] data = null; CodeTrafo3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Trafo3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_(ref Tensor<bool> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            bool[] data = null; CodeBoolArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<bool>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Char_(ref Tensor<char> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            char[] data = null; CodeCharArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<char>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_String_(ref Tensor<string> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            string[] data = null; CodeStringArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<string>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Type_(ref Tensor<Type> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Type[] data = null; CodeTypeArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Type>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_(ref Tensor<Guid> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Guid[] data = null; CodeGuidArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Guid>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_(ref Tensor<Symbol> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Symbol[] data = null; CodeSymbolArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Symbol>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_(ref Tensor<Circle2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Circle2d[] data = null; CodeCircle2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Circle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_(ref Tensor<Line2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line2d[] data = null; CodeLine2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Line2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_(ref Tensor<Line3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line3d[] data = null; CodeLine3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Line3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_(ref Tensor<Plane2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane2d[] data = null; CodePlane2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Plane2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_(ref Tensor<Plane3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane3d[] data = null; CodePlane3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Plane3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_(ref Tensor<PlaneWithPoint3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            PlaneWithPoint3d[] data = null; CodePlaneWithPoint3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<PlaneWithPoint3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_(ref Tensor<Quad2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad2d[] data = null; CodeQuad2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Quad2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_(ref Tensor<Quad3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad3d[] data = null; CodeQuad3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Quad3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_(ref Tensor<Ray2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray2d[] data = null; CodeRay2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Ray2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_(ref Tensor<Ray3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray3d[] data = null; CodeRay3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Ray3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_(ref Tensor<Sphere3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Sphere3d[] data = null; CodeSphere3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Sphere3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_(ref Tensor<Triangle2d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle2d[] data = null; CodeTriangle2dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Triangle2d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_(ref Tensor<Triangle3d> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle3d[] data = null; CodeTriangle3dArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Triangle3d>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_(ref Tensor<Circle2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Circle2f[] data = null; CodeCircle2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Circle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_(ref Tensor<Line2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line2f[] data = null; CodeLine2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Line2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_(ref Tensor<Line3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Line3f[] data = null; CodeLine3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Line3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_(ref Tensor<Plane2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane2f[] data = null; CodePlane2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Plane2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_(ref Tensor<Plane3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Plane3f[] data = null; CodePlane3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Plane3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_(ref Tensor<PlaneWithPoint3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            PlaneWithPoint3f[] data = null; CodePlaneWithPoint3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<PlaneWithPoint3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_(ref Tensor<Quad2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad2f[] data = null; CodeQuad2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Quad2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_(ref Tensor<Quad3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Quad3f[] data = null; CodeQuad3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Quad3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_(ref Tensor<Ray2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray2f[] data = null; CodeRay2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Ray2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_(ref Tensor<Ray3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Ray3f[] data = null; CodeRay3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Ray3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_(ref Tensor<Sphere3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Sphere3f[] data = null; CodeSphere3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Sphere3f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_(ref Tensor<Triangle2f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle2f[] data = null; CodeTriangle2fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Triangle2f>(data, origin, size, delta);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_(ref Tensor<Triangle3f> value)\r\n        {\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            Triangle3f[] data = null; CodeTriangle3fArray(ref data);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long origin = 0L; CodeLong(ref origin);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] size = default(long[]); CodeLongArray(ref size);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state.Advance();\r\n            m_stateStack.Push(m_state);\r\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\r\n            m_state.Element = m_state.Enumerator.Current;\r\n\r\n            long[] delta = default(long[]); CodeLongArray(ref delta);\r\n\r\n            m_state = m_stateStack.Pop();\r\n            m_state = m_stateStack.Pop();\r\n\r\n            value = new Tensor<Triangle3f>(data, origin, size, delta);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Arrays\r\n\r\n        public void CodeV2iArray(ref V2i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V2i.Parse(s));\r\n        }\r\n\r\n        public void CodeV2uiArray(ref V2ui[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V2ui.Parse(s));\r\n        }\r\n\r\n        public void CodeV2lArray(ref V2l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V2l.Parse(s));\r\n        }\r\n\r\n        public void CodeV2fArray(ref V2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V2f.Parse(s));\r\n        }\r\n\r\n        public void CodeV2dArray(ref V2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V2d.Parse(s));\r\n        }\r\n\r\n        public void CodeV3iArray(ref V3i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V3i.Parse(s));\r\n        }\r\n\r\n        public void CodeV3uiArray(ref V3ui[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V3ui.Parse(s));\r\n        }\r\n\r\n        public void CodeV3lArray(ref V3l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V3l.Parse(s));\r\n        }\r\n\r\n        public void CodeV3fArray(ref V3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V3f.Parse(s));\r\n        }\r\n\r\n        public void CodeV3dArray(ref V3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V3d.Parse(s));\r\n        }\r\n\r\n        public void CodeV4iArray(ref V4i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V4i.Parse(s));\r\n        }\r\n\r\n        public void CodeV4uiArray(ref V4ui[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V4ui.Parse(s));\r\n        }\r\n\r\n        public void CodeV4lArray(ref V4l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V4l.Parse(s));\r\n        }\r\n\r\n        public void CodeV4fArray(ref V4f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V4f.Parse(s));\r\n        }\r\n\r\n        public void CodeV4dArray(ref V4d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => V4d.Parse(s));\r\n        }\r\n\r\n        public void CodeM22iArray(ref M22i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M22i.Parse(s));\r\n        }\r\n\r\n        public void CodeM22lArray(ref M22l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M22l.Parse(s));\r\n        }\r\n\r\n        public void CodeM22fArray(ref M22f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M22f.Parse(s));\r\n        }\r\n\r\n        public void CodeM22dArray(ref M22d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M22d.Parse(s));\r\n        }\r\n\r\n        public void CodeM23iArray(ref M23i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M23i.Parse(s));\r\n        }\r\n\r\n        public void CodeM23lArray(ref M23l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M23l.Parse(s));\r\n        }\r\n\r\n        public void CodeM23fArray(ref M23f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M23f.Parse(s));\r\n        }\r\n\r\n        public void CodeM23dArray(ref M23d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M23d.Parse(s));\r\n        }\r\n\r\n        public void CodeM33iArray(ref M33i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M33i.Parse(s));\r\n        }\r\n\r\n        public void CodeM33lArray(ref M33l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M33l.Parse(s));\r\n        }\r\n\r\n        public void CodeM33fArray(ref M33f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M33f.Parse(s));\r\n        }\r\n\r\n        public void CodeM33dArray(ref M33d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M33d.Parse(s));\r\n        }\r\n\r\n        public void CodeM34iArray(ref M34i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M34i.Parse(s));\r\n        }\r\n\r\n        public void CodeM34lArray(ref M34l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M34l.Parse(s));\r\n        }\r\n\r\n        public void CodeM34fArray(ref M34f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M34f.Parse(s));\r\n        }\r\n\r\n        public void CodeM34dArray(ref M34d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M34d.Parse(s));\r\n        }\r\n\r\n        public void CodeM44iArray(ref M44i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M44i.Parse(s));\r\n        }\r\n\r\n        public void CodeM44lArray(ref M44l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M44l.Parse(s));\r\n        }\r\n\r\n        public void CodeM44fArray(ref M44f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M44f.Parse(s));\r\n        }\r\n\r\n        public void CodeM44dArray(ref M44d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => M44d.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1bArray(ref Range1b[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1b.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1sbArray(ref Range1sb[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1sb.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1sArray(ref Range1s[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1s.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1usArray(ref Range1us[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1us.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1iArray(ref Range1i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1i.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1uiArray(ref Range1ui[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1ui.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1lArray(ref Range1l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1l.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1ulArray(ref Range1ul[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1ul.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1fArray(ref Range1f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1f.Parse(s));\r\n        }\r\n\r\n        public void CodeRange1dArray(ref Range1d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Range1d.Parse(s));\r\n        }\r\n\r\n        public void CodeBox2iArray(ref Box2i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Box2i.Parse(s));\r\n        }\r\n\r\n        public void CodeBox2lArray(ref Box2l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Box2l.Parse(s));\r\n        }\r\n\r\n        public void CodeBox2fArray(ref Box2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Box2f.Parse(s));\r\n        }\r\n\r\n        public void CodeBox2dArray(ref Box2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Box2d.Parse(s));\r\n        }\r\n\r\n        public void CodeBox3iArray(ref Box3i[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Box3i.Parse(s));\r\n        }\r\n\r\n        public void CodeBox3lArray(ref Box3l[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Box3l.Parse(s));\r\n        }\r\n\r\n        public void CodeBox3fArray(ref Box3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Box3f.Parse(s));\r\n        }\r\n\r\n        public void CodeBox3dArray(ref Box3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Box3d.Parse(s));\r\n        }\r\n\r\n        public void CodeC3bArray(ref C3b[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C3b.Parse(s));\r\n        }\r\n\r\n        public void CodeC3usArray(ref C3us[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C3us.Parse(s));\r\n        }\r\n\r\n        public void CodeC3uiArray(ref C3ui[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C3ui.Parse(s));\r\n        }\r\n\r\n        public void CodeC3fArray(ref C3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C3f.Parse(s));\r\n        }\r\n\r\n        public void CodeC3dArray(ref C3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C3d.Parse(s));\r\n        }\r\n\r\n        public void CodeC4bArray(ref C4b[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C4b.Parse(s));\r\n        }\r\n\r\n        public void CodeC4usArray(ref C4us[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C4us.Parse(s));\r\n        }\r\n\r\n        public void CodeC4uiArray(ref C4ui[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C4ui.Parse(s));\r\n        }\r\n\r\n        public void CodeC4fArray(ref C4f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C4f.Parse(s));\r\n        }\r\n\r\n        public void CodeC4dArray(ref C4d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => C4d.Parse(s));\r\n        }\r\n\r\n        public void CodeEuclidean3fArray(ref Euclidean3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Euclidean3f.Parse(s));\r\n        }\r\n\r\n        public void CodeEuclidean3dArray(ref Euclidean3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Euclidean3d.Parse(s));\r\n        }\r\n\r\n        public void CodeRot2fArray(ref Rot2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Rot2f.Parse(s));\r\n        }\r\n\r\n        public void CodeRot2dArray(ref Rot2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Rot2d.Parse(s));\r\n        }\r\n\r\n        public void CodeRot3fArray(ref Rot3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Rot3f.Parse(s));\r\n        }\r\n\r\n        public void CodeRot3dArray(ref Rot3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Rot3d.Parse(s));\r\n        }\r\n\r\n        public void CodeScale3fArray(ref Scale3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Scale3f.Parse(s));\r\n        }\r\n\r\n        public void CodeScale3dArray(ref Scale3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Scale3d.Parse(s));\r\n        }\r\n\r\n        public void CodeShift3fArray(ref Shift3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Shift3f.Parse(s));\r\n        }\r\n\r\n        public void CodeShift3dArray(ref Shift3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Shift3d.Parse(s));\r\n        }\r\n\r\n        public void CodeTrafo2fArray(ref Trafo2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Trafo2f.Parse(s));\r\n        }\r\n\r\n        public void CodeTrafo2dArray(ref Trafo2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Trafo2d.Parse(s));\r\n        }\r\n\r\n        public void CodeTrafo3fArray(ref Trafo3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Trafo3f.Parse(s));\r\n        }\r\n\r\n        public void CodeTrafo3dArray(ref Trafo3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Trafo3d.Parse(s));\r\n        }\r\n\r\n        public void CodeCircle2dArray(ref Circle2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Circle2d.Parse(s));\r\n        }\r\n\r\n        public void CodeLine2dArray(ref Line2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Line2d.Parse(s));\r\n        }\r\n\r\n        public void CodeLine3dArray(ref Line3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Line3d.Parse(s));\r\n        }\r\n\r\n        public void CodePlane2dArray(ref Plane2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Plane2d.Parse(s));\r\n        }\r\n\r\n        public void CodePlane3dArray(ref Plane3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Plane3d.Parse(s));\r\n        }\r\n\r\n        public void CodePlaneWithPoint3dArray(ref PlaneWithPoint3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => PlaneWithPoint3d.Parse(s));\r\n        }\r\n\r\n        public void CodeQuad2dArray(ref Quad2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Quad2d.Parse(s));\r\n        }\r\n\r\n        public void CodeQuad3dArray(ref Quad3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Quad3d.Parse(s));\r\n        }\r\n\r\n        public void CodeRay2dArray(ref Ray2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Ray2d.Parse(s));\r\n        }\r\n\r\n        public void CodeRay3dArray(ref Ray3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Ray3d.Parse(s));\r\n        }\r\n\r\n        public void CodeSphere3dArray(ref Sphere3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Sphere3d.Parse(s));\r\n        }\r\n\r\n        public void CodeTriangle2dArray(ref Triangle2d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Triangle2d.Parse(s));\r\n        }\r\n\r\n        public void CodeTriangle3dArray(ref Triangle3d[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Triangle3d.Parse(s));\r\n        }\r\n\r\n        public void CodeCircle2fArray(ref Circle2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Circle2f.Parse(s));\r\n        }\r\n\r\n        public void CodeLine2fArray(ref Line2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Line2f.Parse(s));\r\n        }\r\n\r\n        public void CodeLine3fArray(ref Line3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Line3f.Parse(s));\r\n        }\r\n\r\n        public void CodePlane2fArray(ref Plane2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Plane2f.Parse(s));\r\n        }\r\n\r\n        public void CodePlane3fArray(ref Plane3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Plane3f.Parse(s));\r\n        }\r\n\r\n        public void CodePlaneWithPoint3fArray(ref PlaneWithPoint3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => PlaneWithPoint3f.Parse(s));\r\n        }\r\n\r\n        public void CodeQuad2fArray(ref Quad2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Quad2f.Parse(s));\r\n        }\r\n\r\n        public void CodeQuad3fArray(ref Quad3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Quad3f.Parse(s));\r\n        }\r\n\r\n        public void CodeRay2fArray(ref Ray2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Ray2f.Parse(s));\r\n        }\r\n\r\n        public void CodeRay3fArray(ref Ray3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Ray3f.Parse(s));\r\n        }\r\n\r\n        public void CodeSphere3fArray(ref Sphere3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Sphere3f.Parse(s));\r\n        }\r\n\r\n        public void CodeTriangle2fArray(ref Triangle2f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Triangle2f.Parse(s));\r\n        }\r\n\r\n        public void CodeTriangle3fArray(ref Triangle3f[] value)\r\n        {\r\n            CodeArray(ref value, s_nestedBracketSplitter, s => Triangle3f.Parse(s));\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArray2d(ref byte[,] value) { throw new NotImplementedException(); }\r\n        public void CodeByteArray3d(ref byte[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeSByteArray2d(ref sbyte[,] value) { throw new NotImplementedException(); }\r\n        public void CodeSByteArray3d(ref sbyte[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShortArray2d(ref short[,] value) { throw new NotImplementedException(); }\r\n        public void CodeShortArray3d(ref short[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeUShortArray2d(ref ushort[,] value) { throw new NotImplementedException(); }\r\n        public void CodeUShortArray3d(ref ushort[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeIntArray2d(ref int[,] value) { throw new NotImplementedException(); }\r\n        public void CodeIntArray3d(ref int[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeUIntArray2d(ref uint[,] value) { throw new NotImplementedException(); }\r\n        public void CodeUIntArray3d(ref uint[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeLongArray2d(ref long[,] value) { throw new NotImplementedException(); }\r\n        public void CodeLongArray3d(ref long[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeULongArray2d(ref ulong[,] value) { throw new NotImplementedException(); }\r\n        public void CodeULongArray3d(ref ulong[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeFloatArray2d(ref float[,] value) { throw new NotImplementedException(); }\r\n        public void CodeFloatArray3d(ref float[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeDoubleArray2d(ref double[,] value) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArray3d(ref double[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeFractionArray2d(ref Fraction[,] value) { throw new NotImplementedException(); }\r\n        public void CodeFractionArray3d(ref Fraction[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2iArray2d(ref V2i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV2iArray3d(ref V2i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2lArray2d(ref V2l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV2lArray3d(ref V2l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2fArray2d(ref V2f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV2fArray3d(ref V2f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2dArray2d(ref V2d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV2dArray3d(ref V2d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3iArray2d(ref V3i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV3iArray3d(ref V3i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3lArray2d(ref V3l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV3lArray3d(ref V3l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3fArray2d(ref V3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV3fArray3d(ref V3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3dArray2d(ref V3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV3dArray3d(ref V3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4iArray2d(ref V4i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV4iArray3d(ref V4i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4lArray2d(ref V4l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV4lArray3d(ref V4l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4fArray2d(ref V4f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV4fArray3d(ref V4f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4dArray2d(ref V4d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeV4dArray3d(ref V4d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22iArray2d(ref M22i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM22iArray3d(ref M22i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22lArray2d(ref M22l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM22lArray3d(ref M22l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22fArray2d(ref M22f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM22fArray3d(ref M22f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22dArray2d(ref M22d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM22dArray3d(ref M22d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23iArray2d(ref M23i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM23iArray3d(ref M23i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23lArray2d(ref M23l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM23lArray3d(ref M23l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23fArray2d(ref M23f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM23fArray3d(ref M23f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23dArray2d(ref M23d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM23dArray3d(ref M23d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33iArray2d(ref M33i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM33iArray3d(ref M33i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33lArray2d(ref M33l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM33lArray3d(ref M33l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33fArray2d(ref M33f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM33fArray3d(ref M33f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33dArray2d(ref M33d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM33dArray3d(ref M33d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34iArray2d(ref M34i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM34iArray3d(ref M34i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34lArray2d(ref M34l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM34lArray3d(ref M34l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34fArray2d(ref M34f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM34fArray3d(ref M34f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34dArray2d(ref M34d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM34dArray3d(ref M34d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44iArray2d(ref M44i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM44iArray3d(ref M44i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44lArray2d(ref M44l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM44lArray3d(ref M44l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44fArray2d(ref M44f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM44fArray3d(ref M44f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44dArray2d(ref M44d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeM44dArray3d(ref M44d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3bArray2d(ref C3b[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3bArray3d(ref C3b[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3usArray2d(ref C3us[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3usArray3d(ref C3us[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3uiArray2d(ref C3ui[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArray3d(ref C3ui[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3fArray2d(ref C3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3fArray3d(ref C3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3dArray2d(ref C3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC3dArray3d(ref C3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4bArray2d(ref C4b[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4bArray3d(ref C4b[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4usArray2d(ref C4us[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4usArray3d(ref C4us[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4uiArray2d(ref C4ui[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArray3d(ref C4ui[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4fArray2d(ref C4f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4fArray3d(ref C4f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4dArray2d(ref C4d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeC4dArray3d(ref C4d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1bArray2d(ref Range1b[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArray3d(ref Range1b[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1sbArray2d(ref Range1sb[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArray3d(ref Range1sb[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1sArray2d(ref Range1s[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArray3d(ref Range1s[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1usArray2d(ref Range1us[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArray3d(ref Range1us[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1iArray2d(ref Range1i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArray3d(ref Range1i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1uiArray2d(ref Range1ui[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArray3d(ref Range1ui[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1lArray2d(ref Range1l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArray3d(ref Range1l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1ulArray2d(ref Range1ul[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArray3d(ref Range1ul[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1fArray2d(ref Range1f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArray3d(ref Range1f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1dArray2d(ref Range1d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArray3d(ref Range1d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2iArray2d(ref Box2i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArray3d(ref Box2i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2lArray2d(ref Box2l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArray3d(ref Box2l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2fArray2d(ref Box2f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArray3d(ref Box2f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2dArray2d(ref Box2d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArray3d(ref Box2d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3iArray2d(ref Box3i[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArray3d(ref Box3i[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3lArray2d(ref Box3l[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArray3d(ref Box3l[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3fArray2d(ref Box3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArray3d(ref Box3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3dArray2d(ref Box3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArray3d(ref Box3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeEuclidean3fArray2d(ref Euclidean3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArray3d(ref Euclidean3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeEuclidean3dArray2d(ref Euclidean3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArray3d(ref Euclidean3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot2fArray2d(ref Rot2f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArray3d(ref Rot2f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot2dArray2d(ref Rot2d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArray3d(ref Rot2d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot3fArray2d(ref Rot3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArray3d(ref Rot3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot3dArray2d(ref Rot3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArray3d(ref Rot3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeScale3fArray2d(ref Scale3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArray3d(ref Scale3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeScale3dArray2d(ref Scale3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArray3d(ref Scale3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShift3fArray2d(ref Shift3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArray3d(ref Shift3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShift3dArray2d(ref Shift3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArray3d(ref Shift3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo2fArray2d(ref Trafo2f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArray3d(ref Trafo2f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo2dArray2d(ref Trafo2d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArray3d(ref Trafo2d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo3fArray2d(ref Trafo3f[,] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArray3d(ref Trafo3f[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo3dArray2d(ref Trafo3d[,] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArray3d(ref Trafo3d[, ,] value) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Jagged Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArrayArray(ref byte[][] value) { throw new NotImplementedException(); }\r\n        public void CodeByteArrayArrayArray(ref byte[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeSByteArrayArray(ref sbyte[][] value) { throw new NotImplementedException(); }\r\n        public void CodeSByteArrayArrayArray(ref sbyte[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShortArrayArray(ref short[][] value) { throw new NotImplementedException(); }\r\n        public void CodeShortArrayArrayArray(ref short[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeUShortArrayArray(ref ushort[][] value) { throw new NotImplementedException(); }\r\n        public void CodeUShortArrayArrayArray(ref ushort[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeIntArrayArray(ref int[][] value) { throw new NotImplementedException(); }\r\n        public void CodeIntArrayArrayArray(ref int[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeUIntArrayArray(ref uint[][] value) { throw new NotImplementedException(); }\r\n        public void CodeUIntArrayArrayArray(ref uint[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeLongArrayArray(ref long[][] value) { throw new NotImplementedException(); }\r\n        public void CodeLongArrayArrayArray(ref long[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeULongArrayArray(ref ulong[][] value) { throw new NotImplementedException(); }\r\n        public void CodeULongArrayArrayArray(ref ulong[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeFloatArrayArray(ref float[][] value) { throw new NotImplementedException(); }\r\n        public void CodeFloatArrayArrayArray(ref float[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeDoubleArrayArray(ref double[][] value) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArrayArrayArray(ref double[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeFractionArrayArray(ref Fraction[][] value) { throw new NotImplementedException(); }\r\n        public void CodeFractionArrayArrayArray(ref Fraction[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2iArrayArray(ref V2i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV2iArrayArrayArray(ref V2i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2lArrayArray(ref V2l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV2lArrayArrayArray(ref V2l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2fArrayArray(ref V2f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV2fArrayArrayArray(ref V2f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV2dArrayArray(ref V2d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV2dArrayArrayArray(ref V2d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3iArrayArray(ref V3i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV3iArrayArrayArray(ref V3i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3lArrayArray(ref V3l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV3lArrayArrayArray(ref V3l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3fArrayArray(ref V3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV3fArrayArrayArray(ref V3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV3dArrayArray(ref V3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV3dArrayArrayArray(ref V3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4iArrayArray(ref V4i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV4iArrayArrayArray(ref V4i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4lArrayArray(ref V4l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV4lArrayArrayArray(ref V4l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4fArrayArray(ref V4f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV4fArrayArrayArray(ref V4f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeV4dArrayArray(ref V4d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeV4dArrayArrayArray(ref V4d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22iArrayArray(ref M22i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM22iArrayArrayArray(ref M22i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22lArrayArray(ref M22l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM22lArrayArrayArray(ref M22l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22fArrayArray(ref M22f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM22fArrayArrayArray(ref M22f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM22dArrayArray(ref M22d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM22dArrayArrayArray(ref M22d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23iArrayArray(ref M23i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM23iArrayArrayArray(ref M23i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23lArrayArray(ref M23l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM23lArrayArrayArray(ref M23l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23fArrayArray(ref M23f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM23fArrayArrayArray(ref M23f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM23dArrayArray(ref M23d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM23dArrayArrayArray(ref M23d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33iArrayArray(ref M33i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM33iArrayArrayArray(ref M33i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33lArrayArray(ref M33l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM33lArrayArrayArray(ref M33l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33fArrayArray(ref M33f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM33fArrayArrayArray(ref M33f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM33dArrayArray(ref M33d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM33dArrayArrayArray(ref M33d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34iArrayArray(ref M34i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM34iArrayArrayArray(ref M34i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34lArrayArray(ref M34l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM34lArrayArrayArray(ref M34l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34fArrayArray(ref M34f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM34fArrayArrayArray(ref M34f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM34dArrayArray(ref M34d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM34dArrayArrayArray(ref M34d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44iArrayArray(ref M44i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM44iArrayArrayArray(ref M44i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44lArrayArray(ref M44l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM44lArrayArrayArray(ref M44l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44fArrayArray(ref M44f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM44fArrayArrayArray(ref M44f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeM44dArrayArray(ref M44d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeM44dArrayArrayArray(ref M44d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3bArrayArray(ref C3b[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3bArrayArrayArray(ref C3b[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3usArrayArray(ref C3us[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3usArrayArrayArray(ref C3us[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3uiArrayArray(ref C3ui[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArrayArrayArray(ref C3ui[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3fArrayArray(ref C3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3fArrayArrayArray(ref C3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC3dArrayArray(ref C3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC3dArrayArrayArray(ref C3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4bArrayArray(ref C4b[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4bArrayArrayArray(ref C4b[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4usArrayArray(ref C4us[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4usArrayArrayArray(ref C4us[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4uiArrayArray(ref C4ui[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArrayArrayArray(ref C4ui[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4fArrayArray(ref C4f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4fArrayArrayArray(ref C4f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeC4dArrayArray(ref C4d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeC4dArrayArrayArray(ref C4d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1bArrayArray(ref Range1b[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArrayArrayArray(ref Range1b[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1sbArrayArray(ref Range1sb[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArrayArrayArray(ref Range1sb[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1sArrayArray(ref Range1s[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArrayArrayArray(ref Range1s[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1usArrayArray(ref Range1us[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArrayArrayArray(ref Range1us[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1iArrayArray(ref Range1i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArrayArrayArray(ref Range1i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1uiArrayArray(ref Range1ui[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArrayArrayArray(ref Range1ui[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1lArrayArray(ref Range1l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArrayArrayArray(ref Range1l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1ulArrayArray(ref Range1ul[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArrayArrayArray(ref Range1ul[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1fArrayArray(ref Range1f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArrayArrayArray(ref Range1f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRange1dArrayArray(ref Range1d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArrayArrayArray(ref Range1d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2iArrayArray(ref Box2i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArrayArrayArray(ref Box2i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2lArrayArray(ref Box2l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArrayArrayArray(ref Box2l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2fArrayArray(ref Box2f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArrayArrayArray(ref Box2f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox2dArrayArray(ref Box2d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArrayArrayArray(ref Box2d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3iArrayArray(ref Box3i[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArrayArrayArray(ref Box3i[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3lArrayArray(ref Box3l[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArrayArrayArray(ref Box3l[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3fArrayArray(ref Box3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArrayArrayArray(ref Box3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeBox3dArrayArray(ref Box3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArrayArrayArray(ref Box3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeEuclidean3fArrayArray(ref Euclidean3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArrayArrayArray(ref Euclidean3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeEuclidean3dArrayArray(ref Euclidean3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArrayArrayArray(ref Euclidean3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot2fArrayArray(ref Rot2f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArrayArrayArray(ref Rot2f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot2dArrayArray(ref Rot2d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArrayArrayArray(ref Rot2d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot3fArrayArray(ref Rot3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArrayArrayArray(ref Rot3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeRot3dArrayArray(ref Rot3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArrayArrayArray(ref Rot3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeScale3fArrayArray(ref Scale3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArrayArrayArray(ref Scale3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeScale3dArrayArray(ref Scale3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArrayArrayArray(ref Scale3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShift3fArrayArray(ref Shift3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArrayArrayArray(ref Shift3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeShift3dArrayArray(ref Shift3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArrayArrayArray(ref Shift3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo2fArrayArray(ref Trafo2f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArrayArrayArray(ref Trafo2f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo2dArrayArray(ref Trafo2d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArrayArrayArray(ref Trafo2d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo3fArrayArray(ref Trafo3f[][] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArrayArrayArray(ref Trafo3f[][][] value) { throw new NotImplementedException(); }\r\n\r\n        public void CodeTrafo3dArrayArray(ref Trafo3d[][] value) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArrayArrayArray(ref Trafo3d[][][] value) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Lists\r\n\r\n        public void CodeList_of_V2i_(ref List<V2i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V2i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V2ui_(ref List<V2ui> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V2ui.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V2l_(ref List<V2l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V2l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V2f_(ref List<V2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V2d_(ref List<V2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V3i_(ref List<V3i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V3i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V3ui_(ref List<V3ui> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V3ui.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V3l_(ref List<V3l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V3l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V3f_(ref List<V3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V3d_(ref List<V3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V4i_(ref List<V4i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V4i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V4ui_(ref List<V4ui> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V4ui.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V4l_(ref List<V4l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V4l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V4f_(ref List<V4f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V4f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_V4d_(ref List<V4d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => V4d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M22i_(ref List<M22i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M22i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M22l_(ref List<M22l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M22l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M22f_(ref List<M22f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M22f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M22d_(ref List<M22d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M22d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M23i_(ref List<M23i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M23i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M23l_(ref List<M23l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M23l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M23f_(ref List<M23f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M23f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M23d_(ref List<M23d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M23d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M33i_(ref List<M33i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M33i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M33l_(ref List<M33l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M33l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M33f_(ref List<M33f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M33f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M33d_(ref List<M33d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M33d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M34i_(ref List<M34i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M34i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M34l_(ref List<M34l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M34l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M34f_(ref List<M34f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M34f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M34d_(ref List<M34d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M34d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M44i_(ref List<M44i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M44i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M44l_(ref List<M44l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M44l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M44f_(ref List<M44f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M44f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_M44d_(ref List<M44d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => M44d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1b_(ref List<Range1b> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1b.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1sb_(ref List<Range1sb> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1sb.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1s_(ref List<Range1s> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1s.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1us_(ref List<Range1us> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1us.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1i_(ref List<Range1i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1ui_(ref List<Range1ui> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1ui.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1l_(ref List<Range1l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1ul_(ref List<Range1ul> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1ul.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1f_(ref List<Range1f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Range1d_(ref List<Range1d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Range1d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Box2i_(ref List<Box2i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Box2i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Box2l_(ref List<Box2l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Box2l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Box2f_(ref List<Box2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Box2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Box2d_(ref List<Box2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Box2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Box3i_(ref List<Box3i> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Box3i.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Box3l_(ref List<Box3l> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Box3l.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Box3f_(ref List<Box3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Box3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Box3d_(ref List<Box3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Box3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C3b_(ref List<C3b> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C3b.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C3us_(ref List<C3us> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C3us.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C3ui_(ref List<C3ui> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C3ui.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C3f_(ref List<C3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C3d_(ref List<C3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C4b_(ref List<C4b> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C4b.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C4us_(ref List<C4us> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C4us.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C4ui_(ref List<C4ui> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C4ui.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C4f_(ref List<C4f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C4f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_C4d_(ref List<C4d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => C4d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Euclidean3f_(ref List<Euclidean3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Euclidean3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Euclidean3d_(ref List<Euclidean3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Euclidean3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Rot2f_(ref List<Rot2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Rot2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Rot2d_(ref List<Rot2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Rot2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Rot3f_(ref List<Rot3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Rot3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Rot3d_(ref List<Rot3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Rot3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Scale3f_(ref List<Scale3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Scale3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Scale3d_(ref List<Scale3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Scale3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Shift3f_(ref List<Shift3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Shift3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Shift3d_(ref List<Shift3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Shift3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Trafo2f_(ref List<Trafo2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Trafo2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Trafo2d_(ref List<Trafo2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Trafo2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Trafo3f_(ref List<Trafo3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Trafo3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Trafo3d_(ref List<Trafo3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Trafo3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Circle2d_(ref List<Circle2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Circle2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Line2d_(ref List<Line2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Line2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Line3d_(ref List<Line3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Line3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Plane2d_(ref List<Plane2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Plane2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Plane3d_(ref List<Plane3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Plane3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_PlaneWithPoint3d_(ref List<PlaneWithPoint3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => PlaneWithPoint3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Quad2d_(ref List<Quad2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Quad2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Quad3d_(ref List<Quad3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Quad3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Ray2d_(ref List<Ray2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Ray2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Ray3d_(ref List<Ray3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Ray3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Sphere3d_(ref List<Sphere3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Sphere3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Triangle2d_(ref List<Triangle2d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Triangle2d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Triangle3d_(ref List<Triangle3d> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Triangle3d.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Circle2f_(ref List<Circle2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Circle2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Line2f_(ref List<Line2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Line2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Line3f_(ref List<Line3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Line3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Plane2f_(ref List<Plane2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Plane2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Plane3f_(ref List<Plane3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Plane3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_PlaneWithPoint3f_(ref List<PlaneWithPoint3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => PlaneWithPoint3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Quad2f_(ref List<Quad2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Quad2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Quad3f_(ref List<Quad3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Quad3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Ray2f_(ref List<Ray2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Ray2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Ray3f_(ref List<Ray3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Ray3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Sphere3f_(ref List<Sphere3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Sphere3f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Triangle2f_(ref List<Triangle2f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Triangle2f.Parse(s));\r\n        }\r\n\r\n        public void CodeList_of_Triangle3f_(ref List<Triangle3f> value)\r\n        {\r\n            CodeList(ref value, s_nestedBracketSplitter, s => Triangle3f.Parse(s));\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Arrays of Tensors\r\n\r\n        public void CodeVector_of_Byte_Array(ref Vector<byte>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<byte> item = default(Vector<byte>); CodeVector_of_Byte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_SByte_Array(ref Vector<sbyte>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<sbyte> item = default(Vector<sbyte>); CodeVector_of_SByte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Short_Array(ref Vector<short>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<short> item = default(Vector<short>); CodeVector_of_Short_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_UShort_Array(ref Vector<ushort>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<ushort> item = default(Vector<ushort>); CodeVector_of_UShort_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Int_Array(ref Vector<int>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<int> item = default(Vector<int>); CodeVector_of_Int_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_UInt_Array(ref Vector<uint>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<uint> item = default(Vector<uint>); CodeVector_of_UInt_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Long_Array(ref Vector<long>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<long> item = default(Vector<long>); CodeVector_of_Long_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_ULong_Array(ref Vector<ulong>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<ulong> item = default(Vector<ulong>); CodeVector_of_ULong_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Float_Array(ref Vector<float>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<float> item = default(Vector<float>); CodeVector_of_Float_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Double_Array(ref Vector<double>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<double> item = default(Vector<double>); CodeVector_of_Double_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_Array(ref Vector<Fraction>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Fraction> item = default(Vector<Fraction>); CodeVector_of_Fraction_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V2i_Array(ref Vector<V2i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V2i> item = default(Vector<V2i>); CodeVector_of_V2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V2l_Array(ref Vector<V2l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V2l> item = default(Vector<V2l>); CodeVector_of_V2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V2f_Array(ref Vector<V2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V2f> item = default(Vector<V2f>); CodeVector_of_V2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V2d_Array(ref Vector<V2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V2d> item = default(Vector<V2d>); CodeVector_of_V2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V3i_Array(ref Vector<V3i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V3i> item = default(Vector<V3i>); CodeVector_of_V3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V3l_Array(ref Vector<V3l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V3l> item = default(Vector<V3l>); CodeVector_of_V3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V3f_Array(ref Vector<V3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V3f> item = default(Vector<V3f>); CodeVector_of_V3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V3d_Array(ref Vector<V3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V3d> item = default(Vector<V3d>); CodeVector_of_V3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V4i_Array(ref Vector<V4i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V4i> item = default(Vector<V4i>); CodeVector_of_V4i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V4l_Array(ref Vector<V4l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V4l> item = default(Vector<V4l>); CodeVector_of_V4l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V4f_Array(ref Vector<V4f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V4f> item = default(Vector<V4f>); CodeVector_of_V4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_V4d_Array(ref Vector<V4d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V4d> item = default(Vector<V4d>); CodeVector_of_V4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M22i_Array(ref Vector<M22i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M22i> item = default(Vector<M22i>); CodeVector_of_M22i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M22l_Array(ref Vector<M22l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M22l> item = default(Vector<M22l>); CodeVector_of_M22l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M22f_Array(ref Vector<M22f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M22f> item = default(Vector<M22f>); CodeVector_of_M22f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M22d_Array(ref Vector<M22d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M22d> item = default(Vector<M22d>); CodeVector_of_M22d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M23i_Array(ref Vector<M23i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M23i> item = default(Vector<M23i>); CodeVector_of_M23i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M23l_Array(ref Vector<M23l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M23l> item = default(Vector<M23l>); CodeVector_of_M23l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M23f_Array(ref Vector<M23f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M23f> item = default(Vector<M23f>); CodeVector_of_M23f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M23d_Array(ref Vector<M23d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M23d> item = default(Vector<M23d>); CodeVector_of_M23d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M33i_Array(ref Vector<M33i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M33i> item = default(Vector<M33i>); CodeVector_of_M33i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M33l_Array(ref Vector<M33l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M33l> item = default(Vector<M33l>); CodeVector_of_M33l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M33f_Array(ref Vector<M33f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M33f> item = default(Vector<M33f>); CodeVector_of_M33f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M33d_Array(ref Vector<M33d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M33d> item = default(Vector<M33d>); CodeVector_of_M33d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M34i_Array(ref Vector<M34i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M34i> item = default(Vector<M34i>); CodeVector_of_M34i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M34l_Array(ref Vector<M34l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M34l> item = default(Vector<M34l>); CodeVector_of_M34l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M34f_Array(ref Vector<M34f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M34f> item = default(Vector<M34f>); CodeVector_of_M34f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M34d_Array(ref Vector<M34d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M34d> item = default(Vector<M34d>); CodeVector_of_M34d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M44i_Array(ref Vector<M44i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M44i> item = default(Vector<M44i>); CodeVector_of_M44i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M44l_Array(ref Vector<M44l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M44l> item = default(Vector<M44l>); CodeVector_of_M44l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M44f_Array(ref Vector<M44f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M44f> item = default(Vector<M44f>); CodeVector_of_M44f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_M44d_Array(ref Vector<M44d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M44d> item = default(Vector<M44d>); CodeVector_of_M44d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C3b_Array(ref Vector<C3b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3b> item = default(Vector<C3b>); CodeVector_of_C3b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C3us_Array(ref Vector<C3us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3us> item = default(Vector<C3us>); CodeVector_of_C3us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_Array(ref Vector<C3ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3ui> item = default(Vector<C3ui>); CodeVector_of_C3ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C3f_Array(ref Vector<C3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3f> item = default(Vector<C3f>); CodeVector_of_C3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C3d_Array(ref Vector<C3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3d> item = default(Vector<C3d>); CodeVector_of_C3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C4b_Array(ref Vector<C4b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4b> item = default(Vector<C4b>); CodeVector_of_C4b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C4us_Array(ref Vector<C4us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4us> item = default(Vector<C4us>); CodeVector_of_C4us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_Array(ref Vector<C4ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4ui> item = default(Vector<C4ui>); CodeVector_of_C4ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C4f_Array(ref Vector<C4f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4f> item = default(Vector<C4f>); CodeVector_of_C4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_C4d_Array(ref Vector<C4d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4d> item = default(Vector<C4d>); CodeVector_of_C4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_Array(ref Vector<Range1b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1b> item = default(Vector<Range1b>); CodeVector_of_Range1b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_Array(ref Vector<Range1sb>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1sb> item = default(Vector<Range1sb>); CodeVector_of_Range1sb_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_Array(ref Vector<Range1s>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1s> item = default(Vector<Range1s>); CodeVector_of_Range1s_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_Array(ref Vector<Range1us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1us> item = default(Vector<Range1us>); CodeVector_of_Range1us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_Array(ref Vector<Range1i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1i> item = default(Vector<Range1i>); CodeVector_of_Range1i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_Array(ref Vector<Range1ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1ui> item = default(Vector<Range1ui>); CodeVector_of_Range1ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_Array(ref Vector<Range1l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1l> item = default(Vector<Range1l>); CodeVector_of_Range1l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_Array(ref Vector<Range1ul>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1ul> item = default(Vector<Range1ul>); CodeVector_of_Range1ul_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_Array(ref Vector<Range1f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1f> item = default(Vector<Range1f>); CodeVector_of_Range1f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_Array(ref Vector<Range1d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1d> item = default(Vector<Range1d>); CodeVector_of_Range1d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_Array(ref Vector<Box2i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box2i> item = default(Vector<Box2i>); CodeVector_of_Box2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_Array(ref Vector<Box2l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box2l> item = default(Vector<Box2l>); CodeVector_of_Box2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_Array(ref Vector<Box2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box2f> item = default(Vector<Box2f>); CodeVector_of_Box2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_Array(ref Vector<Box2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box2d> item = default(Vector<Box2d>); CodeVector_of_Box2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_Array(ref Vector<Box3i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box3i> item = default(Vector<Box3i>); CodeVector_of_Box3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_Array(ref Vector<Box3l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box3l> item = default(Vector<Box3l>); CodeVector_of_Box3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_Array(ref Vector<Box3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box3f> item = default(Vector<Box3f>); CodeVector_of_Box3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_Array(ref Vector<Box3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box3d> item = default(Vector<Box3d>); CodeVector_of_Box3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_Array(ref Vector<Euclidean3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Euclidean3f> item = default(Vector<Euclidean3f>); CodeVector_of_Euclidean3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_Array(ref Vector<Euclidean3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Euclidean3d> item = default(Vector<Euclidean3d>); CodeVector_of_Euclidean3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_Array(ref Vector<Rot2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Rot2f> item = default(Vector<Rot2f>); CodeVector_of_Rot2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_Array(ref Vector<Rot2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Rot2d> item = default(Vector<Rot2d>); CodeVector_of_Rot2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_Array(ref Vector<Rot3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Rot3f> item = default(Vector<Rot3f>); CodeVector_of_Rot3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_Array(ref Vector<Rot3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Rot3d> item = default(Vector<Rot3d>); CodeVector_of_Rot3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_Array(ref Vector<Scale3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Scale3f> item = default(Vector<Scale3f>); CodeVector_of_Scale3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_Array(ref Vector<Scale3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Scale3d> item = default(Vector<Scale3d>); CodeVector_of_Scale3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_Array(ref Vector<Shift3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Shift3f> item = default(Vector<Shift3f>); CodeVector_of_Shift3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_Array(ref Vector<Shift3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Shift3d> item = default(Vector<Shift3d>); CodeVector_of_Shift3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_Array(ref Vector<Trafo2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Trafo2f> item = default(Vector<Trafo2f>); CodeVector_of_Trafo2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_Array(ref Vector<Trafo2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Trafo2d> item = default(Vector<Trafo2d>); CodeVector_of_Trafo2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_Array(ref Vector<Trafo3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Trafo3f> item = default(Vector<Trafo3f>); CodeVector_of_Trafo3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_Array(ref Vector<Trafo3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Trafo3d> item = default(Vector<Trafo3d>); CodeVector_of_Trafo3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Bool_Array(ref Vector<bool>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<bool> item = default(Vector<bool>); CodeVector_of_Bool_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Char_Array(ref Vector<char>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<char> item = default(Vector<char>); CodeVector_of_Char_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_String_Array(ref Vector<string>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<string> item = default(Vector<string>); CodeVector_of_String_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Type_Array(ref Vector<Type>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Type> item = default(Vector<Type>); CodeVector_of_Type_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Guid_Array(ref Vector<Guid>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Guid> item = default(Vector<Guid>); CodeVector_of_Guid_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_Array(ref Vector<Symbol>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Symbol> item = default(Vector<Symbol>); CodeVector_of_Symbol_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_Array(ref Vector<Circle2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Circle2d> item = default(Vector<Circle2d>); CodeVector_of_Circle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_Array(ref Vector<Line2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Line2d> item = default(Vector<Line2d>); CodeVector_of_Line2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_Array(ref Vector<Line3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Line3d> item = default(Vector<Line3d>); CodeVector_of_Line3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_Array(ref Vector<Plane2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Plane2d> item = default(Vector<Plane2d>); CodeVector_of_Plane2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_Array(ref Vector<Plane3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Plane3d> item = default(Vector<Plane3d>); CodeVector_of_Plane3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_Array(ref Vector<PlaneWithPoint3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<PlaneWithPoint3d> item = default(Vector<PlaneWithPoint3d>); CodeVector_of_PlaneWithPoint3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_Array(ref Vector<Quad2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Quad2d> item = default(Vector<Quad2d>); CodeVector_of_Quad2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_Array(ref Vector<Quad3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Quad3d> item = default(Vector<Quad3d>); CodeVector_of_Quad3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_Array(ref Vector<Ray2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Ray2d> item = default(Vector<Ray2d>); CodeVector_of_Ray2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_Array(ref Vector<Ray3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Ray3d> item = default(Vector<Ray3d>); CodeVector_of_Ray3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_Array(ref Vector<Sphere3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Sphere3d> item = default(Vector<Sphere3d>); CodeVector_of_Sphere3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_Array(ref Vector<Triangle2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Triangle2d> item = default(Vector<Triangle2d>); CodeVector_of_Triangle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_Array(ref Vector<Triangle3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Triangle3d> item = default(Vector<Triangle3d>); CodeVector_of_Triangle3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_Array(ref Vector<Circle2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Circle2f> item = default(Vector<Circle2f>); CodeVector_of_Circle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_Array(ref Vector<Line2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Line2f> item = default(Vector<Line2f>); CodeVector_of_Line2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_Array(ref Vector<Line3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Line3f> item = default(Vector<Line3f>); CodeVector_of_Line3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_Array(ref Vector<Plane2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Plane2f> item = default(Vector<Plane2f>); CodeVector_of_Plane2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_Array(ref Vector<Plane3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Plane3f> item = default(Vector<Plane3f>); CodeVector_of_Plane3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_Array(ref Vector<PlaneWithPoint3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<PlaneWithPoint3f> item = default(Vector<PlaneWithPoint3f>); CodeVector_of_PlaneWithPoint3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_Array(ref Vector<Quad2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Quad2f> item = default(Vector<Quad2f>); CodeVector_of_Quad2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_Array(ref Vector<Quad3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Quad3f> item = default(Vector<Quad3f>); CodeVector_of_Quad3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_Array(ref Vector<Ray2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Ray2f> item = default(Vector<Ray2f>); CodeVector_of_Ray2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_Array(ref Vector<Ray3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Ray3f> item = default(Vector<Ray3f>); CodeVector_of_Ray3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_Array(ref Vector<Sphere3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Sphere3f> item = default(Vector<Sphere3f>); CodeVector_of_Sphere3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_Array(ref Vector<Triangle2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Triangle2f> item = default(Vector<Triangle2f>); CodeVector_of_Triangle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_Array(ref Vector<Triangle3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Triangle3f> item = default(Vector<Triangle3f>); CodeVector_of_Triangle3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_Array(ref Matrix<byte>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<byte> item = default(Matrix<byte>); CodeMatrix_of_Byte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_Array(ref Matrix<sbyte>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<sbyte> item = default(Matrix<sbyte>); CodeMatrix_of_SByte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_Array(ref Matrix<short>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<short> item = default(Matrix<short>); CodeMatrix_of_Short_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_Array(ref Matrix<ushort>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<ushort> item = default(Matrix<ushort>); CodeMatrix_of_UShort_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_Array(ref Matrix<int>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<int> item = default(Matrix<int>); CodeMatrix_of_Int_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_Array(ref Matrix<uint>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<uint> item = default(Matrix<uint>); CodeMatrix_of_UInt_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_Array(ref Matrix<long>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<long> item = default(Matrix<long>); CodeMatrix_of_Long_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_Array(ref Matrix<ulong>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<ulong> item = default(Matrix<ulong>); CodeMatrix_of_ULong_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_Array(ref Matrix<float>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<float> item = default(Matrix<float>); CodeMatrix_of_Float_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_Array(ref Matrix<double>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<double> item = default(Matrix<double>); CodeMatrix_of_Double_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_Array(ref Matrix<Fraction>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Fraction> item = default(Matrix<Fraction>); CodeMatrix_of_Fraction_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_Array(ref Matrix<V2i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V2i> item = default(Matrix<V2i>); CodeMatrix_of_V2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_Array(ref Matrix<V2l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V2l> item = default(Matrix<V2l>); CodeMatrix_of_V2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_Array(ref Matrix<V2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V2f> item = default(Matrix<V2f>); CodeMatrix_of_V2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_Array(ref Matrix<V2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V2d> item = default(Matrix<V2d>); CodeMatrix_of_V2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_Array(ref Matrix<V3i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V3i> item = default(Matrix<V3i>); CodeMatrix_of_V3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_Array(ref Matrix<V3l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V3l> item = default(Matrix<V3l>); CodeMatrix_of_V3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_Array(ref Matrix<V3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V3f> item = default(Matrix<V3f>); CodeMatrix_of_V3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_Array(ref Matrix<V3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V3d> item = default(Matrix<V3d>); CodeMatrix_of_V3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_Array(ref Matrix<V4i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V4i> item = default(Matrix<V4i>); CodeMatrix_of_V4i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_Array(ref Matrix<V4l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V4l> item = default(Matrix<V4l>); CodeMatrix_of_V4l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_Array(ref Matrix<V4f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V4f> item = default(Matrix<V4f>); CodeMatrix_of_V4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_Array(ref Matrix<V4d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V4d> item = default(Matrix<V4d>); CodeMatrix_of_V4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_Array(ref Matrix<M22i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M22i> item = default(Matrix<M22i>); CodeMatrix_of_M22i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_Array(ref Matrix<M22l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M22l> item = default(Matrix<M22l>); CodeMatrix_of_M22l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_Array(ref Matrix<M22f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M22f> item = default(Matrix<M22f>); CodeMatrix_of_M22f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_Array(ref Matrix<M22d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M22d> item = default(Matrix<M22d>); CodeMatrix_of_M22d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_Array(ref Matrix<M23i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M23i> item = default(Matrix<M23i>); CodeMatrix_of_M23i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_Array(ref Matrix<M23l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M23l> item = default(Matrix<M23l>); CodeMatrix_of_M23l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_Array(ref Matrix<M23f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M23f> item = default(Matrix<M23f>); CodeMatrix_of_M23f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_Array(ref Matrix<M23d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M23d> item = default(Matrix<M23d>); CodeMatrix_of_M23d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_Array(ref Matrix<M33i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M33i> item = default(Matrix<M33i>); CodeMatrix_of_M33i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_Array(ref Matrix<M33l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M33l> item = default(Matrix<M33l>); CodeMatrix_of_M33l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_Array(ref Matrix<M33f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M33f> item = default(Matrix<M33f>); CodeMatrix_of_M33f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_Array(ref Matrix<M33d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M33d> item = default(Matrix<M33d>); CodeMatrix_of_M33d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_Array(ref Matrix<M34i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M34i> item = default(Matrix<M34i>); CodeMatrix_of_M34i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_Array(ref Matrix<M34l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M34l> item = default(Matrix<M34l>); CodeMatrix_of_M34l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_Array(ref Matrix<M34f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M34f> item = default(Matrix<M34f>); CodeMatrix_of_M34f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_Array(ref Matrix<M34d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M34d> item = default(Matrix<M34d>); CodeMatrix_of_M34d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_Array(ref Matrix<M44i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M44i> item = default(Matrix<M44i>); CodeMatrix_of_M44i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_Array(ref Matrix<M44l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M44l> item = default(Matrix<M44l>); CodeMatrix_of_M44l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_Array(ref Matrix<M44f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M44f> item = default(Matrix<M44f>); CodeMatrix_of_M44f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_Array(ref Matrix<M44d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M44d> item = default(Matrix<M44d>); CodeMatrix_of_M44d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_Array(ref Matrix<C3b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3b> item = default(Matrix<C3b>); CodeMatrix_of_C3b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_Array(ref Matrix<C3us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3us> item = default(Matrix<C3us>); CodeMatrix_of_C3us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_Array(ref Matrix<C3ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3ui> item = default(Matrix<C3ui>); CodeMatrix_of_C3ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_Array(ref Matrix<C3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3f> item = default(Matrix<C3f>); CodeMatrix_of_C3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_Array(ref Matrix<C3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3d> item = default(Matrix<C3d>); CodeMatrix_of_C3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_Array(ref Matrix<C4b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4b> item = default(Matrix<C4b>); CodeMatrix_of_C4b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_Array(ref Matrix<C4us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4us> item = default(Matrix<C4us>); CodeMatrix_of_C4us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_Array(ref Matrix<C4ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4ui> item = default(Matrix<C4ui>); CodeMatrix_of_C4ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_Array(ref Matrix<C4f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4f> item = default(Matrix<C4f>); CodeMatrix_of_C4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_Array(ref Matrix<C4d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4d> item = default(Matrix<C4d>); CodeMatrix_of_C4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_Array(ref Matrix<Range1b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1b> item = default(Matrix<Range1b>); CodeMatrix_of_Range1b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_Array(ref Matrix<Range1sb>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1sb> item = default(Matrix<Range1sb>); CodeMatrix_of_Range1sb_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_Array(ref Matrix<Range1s>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1s> item = default(Matrix<Range1s>); CodeMatrix_of_Range1s_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_Array(ref Matrix<Range1us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1us> item = default(Matrix<Range1us>); CodeMatrix_of_Range1us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_Array(ref Matrix<Range1i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1i> item = default(Matrix<Range1i>); CodeMatrix_of_Range1i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_Array(ref Matrix<Range1ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1ui> item = default(Matrix<Range1ui>); CodeMatrix_of_Range1ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_Array(ref Matrix<Range1l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1l> item = default(Matrix<Range1l>); CodeMatrix_of_Range1l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_Array(ref Matrix<Range1ul>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1ul> item = default(Matrix<Range1ul>); CodeMatrix_of_Range1ul_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_Array(ref Matrix<Range1f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1f> item = default(Matrix<Range1f>); CodeMatrix_of_Range1f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_Array(ref Matrix<Range1d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1d> item = default(Matrix<Range1d>); CodeMatrix_of_Range1d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_Array(ref Matrix<Box2i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box2i> item = default(Matrix<Box2i>); CodeMatrix_of_Box2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_Array(ref Matrix<Box2l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box2l> item = default(Matrix<Box2l>); CodeMatrix_of_Box2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_Array(ref Matrix<Box2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box2f> item = default(Matrix<Box2f>); CodeMatrix_of_Box2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_Array(ref Matrix<Box2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box2d> item = default(Matrix<Box2d>); CodeMatrix_of_Box2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_Array(ref Matrix<Box3i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box3i> item = default(Matrix<Box3i>); CodeMatrix_of_Box3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_Array(ref Matrix<Box3l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box3l> item = default(Matrix<Box3l>); CodeMatrix_of_Box3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_Array(ref Matrix<Box3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box3f> item = default(Matrix<Box3f>); CodeMatrix_of_Box3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_Array(ref Matrix<Box3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box3d> item = default(Matrix<Box3d>); CodeMatrix_of_Box3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_Array(ref Matrix<Euclidean3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Euclidean3f> item = default(Matrix<Euclidean3f>); CodeMatrix_of_Euclidean3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_Array(ref Matrix<Euclidean3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Euclidean3d> item = default(Matrix<Euclidean3d>); CodeMatrix_of_Euclidean3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_Array(ref Matrix<Rot2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Rot2f> item = default(Matrix<Rot2f>); CodeMatrix_of_Rot2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_Array(ref Matrix<Rot2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Rot2d> item = default(Matrix<Rot2d>); CodeMatrix_of_Rot2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_Array(ref Matrix<Rot3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Rot3f> item = default(Matrix<Rot3f>); CodeMatrix_of_Rot3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_Array(ref Matrix<Rot3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Rot3d> item = default(Matrix<Rot3d>); CodeMatrix_of_Rot3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_Array(ref Matrix<Scale3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Scale3f> item = default(Matrix<Scale3f>); CodeMatrix_of_Scale3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_Array(ref Matrix<Scale3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Scale3d> item = default(Matrix<Scale3d>); CodeMatrix_of_Scale3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_Array(ref Matrix<Shift3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Shift3f> item = default(Matrix<Shift3f>); CodeMatrix_of_Shift3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_Array(ref Matrix<Shift3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Shift3d> item = default(Matrix<Shift3d>); CodeMatrix_of_Shift3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_Array(ref Matrix<Trafo2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Trafo2f> item = default(Matrix<Trafo2f>); CodeMatrix_of_Trafo2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_Array(ref Matrix<Trafo2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Trafo2d> item = default(Matrix<Trafo2d>); CodeMatrix_of_Trafo2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_Array(ref Matrix<Trafo3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Trafo3f> item = default(Matrix<Trafo3f>); CodeMatrix_of_Trafo3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_Array(ref Matrix<Trafo3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Trafo3d> item = default(Matrix<Trafo3d>); CodeMatrix_of_Trafo3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_Array(ref Matrix<bool>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<bool> item = default(Matrix<bool>); CodeMatrix_of_Bool_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_Array(ref Matrix<char>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<char> item = default(Matrix<char>); CodeMatrix_of_Char_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_String_Array(ref Matrix<string>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<string> item = default(Matrix<string>); CodeMatrix_of_String_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_Array(ref Matrix<Type>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Type> item = default(Matrix<Type>); CodeMatrix_of_Type_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_Array(ref Matrix<Guid>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Guid> item = default(Matrix<Guid>); CodeMatrix_of_Guid_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_Array(ref Matrix<Symbol>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Symbol> item = default(Matrix<Symbol>); CodeMatrix_of_Symbol_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_Array(ref Matrix<Circle2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Circle2d> item = default(Matrix<Circle2d>); CodeMatrix_of_Circle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_Array(ref Matrix<Line2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Line2d> item = default(Matrix<Line2d>); CodeMatrix_of_Line2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_Array(ref Matrix<Line3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Line3d> item = default(Matrix<Line3d>); CodeMatrix_of_Line3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_Array(ref Matrix<Plane2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Plane2d> item = default(Matrix<Plane2d>); CodeMatrix_of_Plane2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_Array(ref Matrix<Plane3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Plane3d> item = default(Matrix<Plane3d>); CodeMatrix_of_Plane3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_Array(ref Matrix<PlaneWithPoint3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<PlaneWithPoint3d> item = default(Matrix<PlaneWithPoint3d>); CodeMatrix_of_PlaneWithPoint3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_Array(ref Matrix<Quad2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Quad2d> item = default(Matrix<Quad2d>); CodeMatrix_of_Quad2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_Array(ref Matrix<Quad3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Quad3d> item = default(Matrix<Quad3d>); CodeMatrix_of_Quad3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_Array(ref Matrix<Ray2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Ray2d> item = default(Matrix<Ray2d>); CodeMatrix_of_Ray2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_Array(ref Matrix<Ray3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Ray3d> item = default(Matrix<Ray3d>); CodeMatrix_of_Ray3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_Array(ref Matrix<Sphere3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Sphere3d> item = default(Matrix<Sphere3d>); CodeMatrix_of_Sphere3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_Array(ref Matrix<Triangle2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Triangle2d> item = default(Matrix<Triangle2d>); CodeMatrix_of_Triangle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_Array(ref Matrix<Triangle3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Triangle3d> item = default(Matrix<Triangle3d>); CodeMatrix_of_Triangle3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_Array(ref Matrix<Circle2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Circle2f> item = default(Matrix<Circle2f>); CodeMatrix_of_Circle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_Array(ref Matrix<Line2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Line2f> item = default(Matrix<Line2f>); CodeMatrix_of_Line2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_Array(ref Matrix<Line3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Line3f> item = default(Matrix<Line3f>); CodeMatrix_of_Line3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_Array(ref Matrix<Plane2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Plane2f> item = default(Matrix<Plane2f>); CodeMatrix_of_Plane2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_Array(ref Matrix<Plane3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Plane3f> item = default(Matrix<Plane3f>); CodeMatrix_of_Plane3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_Array(ref Matrix<PlaneWithPoint3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<PlaneWithPoint3f> item = default(Matrix<PlaneWithPoint3f>); CodeMatrix_of_PlaneWithPoint3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_Array(ref Matrix<Quad2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Quad2f> item = default(Matrix<Quad2f>); CodeMatrix_of_Quad2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_Array(ref Matrix<Quad3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Quad3f> item = default(Matrix<Quad3f>); CodeMatrix_of_Quad3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_Array(ref Matrix<Ray2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Ray2f> item = default(Matrix<Ray2f>); CodeMatrix_of_Ray2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_Array(ref Matrix<Ray3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Ray3f> item = default(Matrix<Ray3f>); CodeMatrix_of_Ray3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_Array(ref Matrix<Sphere3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Sphere3f> item = default(Matrix<Sphere3f>); CodeMatrix_of_Sphere3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_Array(ref Matrix<Triangle2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Triangle2f> item = default(Matrix<Triangle2f>); CodeMatrix_of_Triangle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_Array(ref Matrix<Triangle3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Triangle3f> item = default(Matrix<Triangle3f>); CodeMatrix_of_Triangle3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_Array(ref Volume<byte>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<byte> item = default(Volume<byte>); CodeVolume_of_Byte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_Array(ref Volume<sbyte>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<sbyte> item = default(Volume<sbyte>); CodeVolume_of_SByte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Short_Array(ref Volume<short>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<short> item = default(Volume<short>); CodeVolume_of_Short_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_Array(ref Volume<ushort>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<ushort> item = default(Volume<ushort>); CodeVolume_of_UShort_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Int_Array(ref Volume<int>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<int> item = default(Volume<int>); CodeVolume_of_Int_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_Array(ref Volume<uint>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<uint> item = default(Volume<uint>); CodeVolume_of_UInt_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Long_Array(ref Volume<long>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<long> item = default(Volume<long>); CodeVolume_of_Long_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_Array(ref Volume<ulong>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<ulong> item = default(Volume<ulong>); CodeVolume_of_ULong_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Float_Array(ref Volume<float>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<float> item = default(Volume<float>); CodeVolume_of_Float_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Double_Array(ref Volume<double>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<double> item = default(Volume<double>); CodeVolume_of_Double_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_Array(ref Volume<Fraction>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Fraction> item = default(Volume<Fraction>); CodeVolume_of_Fraction_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_Array(ref Volume<V2i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V2i> item = default(Volume<V2i>); CodeVolume_of_V2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_Array(ref Volume<V2l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V2l> item = default(Volume<V2l>); CodeVolume_of_V2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_Array(ref Volume<V2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V2f> item = default(Volume<V2f>); CodeVolume_of_V2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_Array(ref Volume<V2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V2d> item = default(Volume<V2d>); CodeVolume_of_V2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_Array(ref Volume<V3i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V3i> item = default(Volume<V3i>); CodeVolume_of_V3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_Array(ref Volume<V3l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V3l> item = default(Volume<V3l>); CodeVolume_of_V3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_Array(ref Volume<V3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V3f> item = default(Volume<V3f>); CodeVolume_of_V3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_Array(ref Volume<V3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V3d> item = default(Volume<V3d>); CodeVolume_of_V3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_Array(ref Volume<V4i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V4i> item = default(Volume<V4i>); CodeVolume_of_V4i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_Array(ref Volume<V4l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V4l> item = default(Volume<V4l>); CodeVolume_of_V4l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_Array(ref Volume<V4f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V4f> item = default(Volume<V4f>); CodeVolume_of_V4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_Array(ref Volume<V4d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V4d> item = default(Volume<V4d>); CodeVolume_of_V4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_Array(ref Volume<M22i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M22i> item = default(Volume<M22i>); CodeVolume_of_M22i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_Array(ref Volume<M22l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M22l> item = default(Volume<M22l>); CodeVolume_of_M22l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_Array(ref Volume<M22f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M22f> item = default(Volume<M22f>); CodeVolume_of_M22f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_Array(ref Volume<M22d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M22d> item = default(Volume<M22d>); CodeVolume_of_M22d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_Array(ref Volume<M23i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M23i> item = default(Volume<M23i>); CodeVolume_of_M23i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_Array(ref Volume<M23l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M23l> item = default(Volume<M23l>); CodeVolume_of_M23l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_Array(ref Volume<M23f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M23f> item = default(Volume<M23f>); CodeVolume_of_M23f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_Array(ref Volume<M23d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M23d> item = default(Volume<M23d>); CodeVolume_of_M23d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_Array(ref Volume<M33i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M33i> item = default(Volume<M33i>); CodeVolume_of_M33i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_Array(ref Volume<M33l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M33l> item = default(Volume<M33l>); CodeVolume_of_M33l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_Array(ref Volume<M33f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M33f> item = default(Volume<M33f>); CodeVolume_of_M33f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_Array(ref Volume<M33d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M33d> item = default(Volume<M33d>); CodeVolume_of_M33d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_Array(ref Volume<M34i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M34i> item = default(Volume<M34i>); CodeVolume_of_M34i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_Array(ref Volume<M34l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M34l> item = default(Volume<M34l>); CodeVolume_of_M34l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_Array(ref Volume<M34f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M34f> item = default(Volume<M34f>); CodeVolume_of_M34f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_Array(ref Volume<M34d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M34d> item = default(Volume<M34d>); CodeVolume_of_M34d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_Array(ref Volume<M44i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M44i> item = default(Volume<M44i>); CodeVolume_of_M44i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_Array(ref Volume<M44l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M44l> item = default(Volume<M44l>); CodeVolume_of_M44l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_Array(ref Volume<M44f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M44f> item = default(Volume<M44f>); CodeVolume_of_M44f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_Array(ref Volume<M44d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M44d> item = default(Volume<M44d>); CodeVolume_of_M44d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_Array(ref Volume<C3b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3b> item = default(Volume<C3b>); CodeVolume_of_C3b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_Array(ref Volume<C3us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3us> item = default(Volume<C3us>); CodeVolume_of_C3us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_Array(ref Volume<C3ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3ui> item = default(Volume<C3ui>); CodeVolume_of_C3ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_Array(ref Volume<C3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3f> item = default(Volume<C3f>); CodeVolume_of_C3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_Array(ref Volume<C3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3d> item = default(Volume<C3d>); CodeVolume_of_C3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_Array(ref Volume<C4b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4b> item = default(Volume<C4b>); CodeVolume_of_C4b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_Array(ref Volume<C4us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4us> item = default(Volume<C4us>); CodeVolume_of_C4us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_Array(ref Volume<C4ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4ui> item = default(Volume<C4ui>); CodeVolume_of_C4ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_Array(ref Volume<C4f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4f> item = default(Volume<C4f>); CodeVolume_of_C4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_Array(ref Volume<C4d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4d> item = default(Volume<C4d>); CodeVolume_of_C4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_Array(ref Volume<Range1b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1b> item = default(Volume<Range1b>); CodeVolume_of_Range1b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_Array(ref Volume<Range1sb>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1sb> item = default(Volume<Range1sb>); CodeVolume_of_Range1sb_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_Array(ref Volume<Range1s>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1s> item = default(Volume<Range1s>); CodeVolume_of_Range1s_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_Array(ref Volume<Range1us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1us> item = default(Volume<Range1us>); CodeVolume_of_Range1us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_Array(ref Volume<Range1i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1i> item = default(Volume<Range1i>); CodeVolume_of_Range1i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_Array(ref Volume<Range1ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1ui> item = default(Volume<Range1ui>); CodeVolume_of_Range1ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_Array(ref Volume<Range1l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1l> item = default(Volume<Range1l>); CodeVolume_of_Range1l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_Array(ref Volume<Range1ul>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1ul> item = default(Volume<Range1ul>); CodeVolume_of_Range1ul_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_Array(ref Volume<Range1f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1f> item = default(Volume<Range1f>); CodeVolume_of_Range1f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_Array(ref Volume<Range1d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1d> item = default(Volume<Range1d>); CodeVolume_of_Range1d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_Array(ref Volume<Box2i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box2i> item = default(Volume<Box2i>); CodeVolume_of_Box2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_Array(ref Volume<Box2l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box2l> item = default(Volume<Box2l>); CodeVolume_of_Box2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_Array(ref Volume<Box2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box2f> item = default(Volume<Box2f>); CodeVolume_of_Box2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_Array(ref Volume<Box2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box2d> item = default(Volume<Box2d>); CodeVolume_of_Box2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_Array(ref Volume<Box3i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box3i> item = default(Volume<Box3i>); CodeVolume_of_Box3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_Array(ref Volume<Box3l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box3l> item = default(Volume<Box3l>); CodeVolume_of_Box3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_Array(ref Volume<Box3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box3f> item = default(Volume<Box3f>); CodeVolume_of_Box3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_Array(ref Volume<Box3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box3d> item = default(Volume<Box3d>); CodeVolume_of_Box3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_Array(ref Volume<Euclidean3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Euclidean3f> item = default(Volume<Euclidean3f>); CodeVolume_of_Euclidean3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_Array(ref Volume<Euclidean3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Euclidean3d> item = default(Volume<Euclidean3d>); CodeVolume_of_Euclidean3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_Array(ref Volume<Rot2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Rot2f> item = default(Volume<Rot2f>); CodeVolume_of_Rot2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_Array(ref Volume<Rot2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Rot2d> item = default(Volume<Rot2d>); CodeVolume_of_Rot2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_Array(ref Volume<Rot3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Rot3f> item = default(Volume<Rot3f>); CodeVolume_of_Rot3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_Array(ref Volume<Rot3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Rot3d> item = default(Volume<Rot3d>); CodeVolume_of_Rot3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_Array(ref Volume<Scale3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Scale3f> item = default(Volume<Scale3f>); CodeVolume_of_Scale3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_Array(ref Volume<Scale3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Scale3d> item = default(Volume<Scale3d>); CodeVolume_of_Scale3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_Array(ref Volume<Shift3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Shift3f> item = default(Volume<Shift3f>); CodeVolume_of_Shift3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_Array(ref Volume<Shift3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Shift3d> item = default(Volume<Shift3d>); CodeVolume_of_Shift3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_Array(ref Volume<Trafo2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Trafo2f> item = default(Volume<Trafo2f>); CodeVolume_of_Trafo2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_Array(ref Volume<Trafo2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Trafo2d> item = default(Volume<Trafo2d>); CodeVolume_of_Trafo2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_Array(ref Volume<Trafo3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Trafo3f> item = default(Volume<Trafo3f>); CodeVolume_of_Trafo3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_Array(ref Volume<Trafo3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Trafo3d> item = default(Volume<Trafo3d>); CodeVolume_of_Trafo3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_Array(ref Volume<bool>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<bool> item = default(Volume<bool>); CodeVolume_of_Bool_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Char_Array(ref Volume<char>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<char> item = default(Volume<char>); CodeVolume_of_Char_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_String_Array(ref Volume<string>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<string> item = default(Volume<string>); CodeVolume_of_String_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Type_Array(ref Volume<Type>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Type> item = default(Volume<Type>); CodeVolume_of_Type_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_Array(ref Volume<Guid>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Guid> item = default(Volume<Guid>); CodeVolume_of_Guid_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_Array(ref Volume<Symbol>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Symbol> item = default(Volume<Symbol>); CodeVolume_of_Symbol_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_Array(ref Volume<Circle2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Circle2d> item = default(Volume<Circle2d>); CodeVolume_of_Circle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_Array(ref Volume<Line2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Line2d> item = default(Volume<Line2d>); CodeVolume_of_Line2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_Array(ref Volume<Line3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Line3d> item = default(Volume<Line3d>); CodeVolume_of_Line3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_Array(ref Volume<Plane2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Plane2d> item = default(Volume<Plane2d>); CodeVolume_of_Plane2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_Array(ref Volume<Plane3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Plane3d> item = default(Volume<Plane3d>); CodeVolume_of_Plane3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_Array(ref Volume<PlaneWithPoint3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<PlaneWithPoint3d> item = default(Volume<PlaneWithPoint3d>); CodeVolume_of_PlaneWithPoint3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_Array(ref Volume<Quad2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Quad2d> item = default(Volume<Quad2d>); CodeVolume_of_Quad2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_Array(ref Volume<Quad3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Quad3d> item = default(Volume<Quad3d>); CodeVolume_of_Quad3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_Array(ref Volume<Ray2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Ray2d> item = default(Volume<Ray2d>); CodeVolume_of_Ray2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_Array(ref Volume<Ray3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Ray3d> item = default(Volume<Ray3d>); CodeVolume_of_Ray3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_Array(ref Volume<Sphere3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Sphere3d> item = default(Volume<Sphere3d>); CodeVolume_of_Sphere3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_Array(ref Volume<Triangle2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Triangle2d> item = default(Volume<Triangle2d>); CodeVolume_of_Triangle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_Array(ref Volume<Triangle3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Triangle3d> item = default(Volume<Triangle3d>); CodeVolume_of_Triangle3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_Array(ref Volume<Circle2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Circle2f> item = default(Volume<Circle2f>); CodeVolume_of_Circle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_Array(ref Volume<Line2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Line2f> item = default(Volume<Line2f>); CodeVolume_of_Line2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_Array(ref Volume<Line3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Line3f> item = default(Volume<Line3f>); CodeVolume_of_Line3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_Array(ref Volume<Plane2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Plane2f> item = default(Volume<Plane2f>); CodeVolume_of_Plane2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_Array(ref Volume<Plane3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Plane3f> item = default(Volume<Plane3f>); CodeVolume_of_Plane3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_Array(ref Volume<PlaneWithPoint3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<PlaneWithPoint3f> item = default(Volume<PlaneWithPoint3f>); CodeVolume_of_PlaneWithPoint3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_Array(ref Volume<Quad2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Quad2f> item = default(Volume<Quad2f>); CodeVolume_of_Quad2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_Array(ref Volume<Quad3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Quad3f> item = default(Volume<Quad3f>); CodeVolume_of_Quad3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_Array(ref Volume<Ray2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Ray2f> item = default(Volume<Ray2f>); CodeVolume_of_Ray2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_Array(ref Volume<Ray3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Ray3f> item = default(Volume<Ray3f>); CodeVolume_of_Ray3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_Array(ref Volume<Sphere3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Sphere3f> item = default(Volume<Sphere3f>); CodeVolume_of_Sphere3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_Array(ref Volume<Triangle2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Triangle2f> item = default(Volume<Triangle2f>); CodeVolume_of_Triangle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_Array(ref Volume<Triangle3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Triangle3f> item = default(Volume<Triangle3f>); CodeVolume_of_Triangle3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_Array(ref Tensor<byte>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<byte> item = default(Tensor<byte>); CodeTensor_of_Byte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_Array(ref Tensor<sbyte>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<sbyte> item = default(Tensor<sbyte>); CodeTensor_of_SByte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Short_Array(ref Tensor<short>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<short> item = default(Tensor<short>); CodeTensor_of_Short_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_Array(ref Tensor<ushort>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<ushort> item = default(Tensor<ushort>); CodeTensor_of_UShort_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Int_Array(ref Tensor<int>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<int> item = default(Tensor<int>); CodeTensor_of_Int_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_Array(ref Tensor<uint>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<uint> item = default(Tensor<uint>); CodeTensor_of_UInt_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Long_Array(ref Tensor<long>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<long> item = default(Tensor<long>); CodeTensor_of_Long_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_Array(ref Tensor<ulong>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<ulong> item = default(Tensor<ulong>); CodeTensor_of_ULong_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Float_Array(ref Tensor<float>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<float> item = default(Tensor<float>); CodeTensor_of_Float_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Double_Array(ref Tensor<double>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<double> item = default(Tensor<double>); CodeTensor_of_Double_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_Array(ref Tensor<Fraction>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Fraction> item = default(Tensor<Fraction>); CodeTensor_of_Fraction_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_Array(ref Tensor<V2i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V2i> item = default(Tensor<V2i>); CodeTensor_of_V2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_Array(ref Tensor<V2l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V2l> item = default(Tensor<V2l>); CodeTensor_of_V2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_Array(ref Tensor<V2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V2f> item = default(Tensor<V2f>); CodeTensor_of_V2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_Array(ref Tensor<V2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V2d> item = default(Tensor<V2d>); CodeTensor_of_V2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_Array(ref Tensor<V3i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V3i> item = default(Tensor<V3i>); CodeTensor_of_V3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_Array(ref Tensor<V3l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V3l> item = default(Tensor<V3l>); CodeTensor_of_V3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_Array(ref Tensor<V3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V3f> item = default(Tensor<V3f>); CodeTensor_of_V3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_Array(ref Tensor<V3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V3d> item = default(Tensor<V3d>); CodeTensor_of_V3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_Array(ref Tensor<V4i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V4i> item = default(Tensor<V4i>); CodeTensor_of_V4i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_Array(ref Tensor<V4l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V4l> item = default(Tensor<V4l>); CodeTensor_of_V4l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_Array(ref Tensor<V4f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V4f> item = default(Tensor<V4f>); CodeTensor_of_V4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_Array(ref Tensor<V4d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V4d> item = default(Tensor<V4d>); CodeTensor_of_V4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_Array(ref Tensor<M22i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M22i> item = default(Tensor<M22i>); CodeTensor_of_M22i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_Array(ref Tensor<M22l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M22l> item = default(Tensor<M22l>); CodeTensor_of_M22l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_Array(ref Tensor<M22f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M22f> item = default(Tensor<M22f>); CodeTensor_of_M22f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_Array(ref Tensor<M22d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M22d> item = default(Tensor<M22d>); CodeTensor_of_M22d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_Array(ref Tensor<M23i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M23i> item = default(Tensor<M23i>); CodeTensor_of_M23i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_Array(ref Tensor<M23l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M23l> item = default(Tensor<M23l>); CodeTensor_of_M23l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_Array(ref Tensor<M23f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M23f> item = default(Tensor<M23f>); CodeTensor_of_M23f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_Array(ref Tensor<M23d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M23d> item = default(Tensor<M23d>); CodeTensor_of_M23d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_Array(ref Tensor<M33i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M33i> item = default(Tensor<M33i>); CodeTensor_of_M33i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_Array(ref Tensor<M33l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M33l> item = default(Tensor<M33l>); CodeTensor_of_M33l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_Array(ref Tensor<M33f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M33f> item = default(Tensor<M33f>); CodeTensor_of_M33f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_Array(ref Tensor<M33d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M33d> item = default(Tensor<M33d>); CodeTensor_of_M33d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_Array(ref Tensor<M34i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M34i> item = default(Tensor<M34i>); CodeTensor_of_M34i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_Array(ref Tensor<M34l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M34l> item = default(Tensor<M34l>); CodeTensor_of_M34l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_Array(ref Tensor<M34f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M34f> item = default(Tensor<M34f>); CodeTensor_of_M34f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_Array(ref Tensor<M34d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M34d> item = default(Tensor<M34d>); CodeTensor_of_M34d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_Array(ref Tensor<M44i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M44i> item = default(Tensor<M44i>); CodeTensor_of_M44i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_Array(ref Tensor<M44l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M44l> item = default(Tensor<M44l>); CodeTensor_of_M44l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_Array(ref Tensor<M44f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M44f> item = default(Tensor<M44f>); CodeTensor_of_M44f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_Array(ref Tensor<M44d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M44d> item = default(Tensor<M44d>); CodeTensor_of_M44d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_Array(ref Tensor<C3b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3b> item = default(Tensor<C3b>); CodeTensor_of_C3b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_Array(ref Tensor<C3us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3us> item = default(Tensor<C3us>); CodeTensor_of_C3us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_Array(ref Tensor<C3ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3ui> item = default(Tensor<C3ui>); CodeTensor_of_C3ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_Array(ref Tensor<C3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3f> item = default(Tensor<C3f>); CodeTensor_of_C3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_Array(ref Tensor<C3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3d> item = default(Tensor<C3d>); CodeTensor_of_C3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_Array(ref Tensor<C4b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4b> item = default(Tensor<C4b>); CodeTensor_of_C4b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_Array(ref Tensor<C4us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4us> item = default(Tensor<C4us>); CodeTensor_of_C4us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_Array(ref Tensor<C4ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4ui> item = default(Tensor<C4ui>); CodeTensor_of_C4ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_Array(ref Tensor<C4f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4f> item = default(Tensor<C4f>); CodeTensor_of_C4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_Array(ref Tensor<C4d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4d> item = default(Tensor<C4d>); CodeTensor_of_C4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_Array(ref Tensor<Range1b>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1b> item = default(Tensor<Range1b>); CodeTensor_of_Range1b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_Array(ref Tensor<Range1sb>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1sb> item = default(Tensor<Range1sb>); CodeTensor_of_Range1sb_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_Array(ref Tensor<Range1s>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1s> item = default(Tensor<Range1s>); CodeTensor_of_Range1s_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_Array(ref Tensor<Range1us>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1us> item = default(Tensor<Range1us>); CodeTensor_of_Range1us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_Array(ref Tensor<Range1i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1i> item = default(Tensor<Range1i>); CodeTensor_of_Range1i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_Array(ref Tensor<Range1ui>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1ui> item = default(Tensor<Range1ui>); CodeTensor_of_Range1ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_Array(ref Tensor<Range1l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1l> item = default(Tensor<Range1l>); CodeTensor_of_Range1l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_Array(ref Tensor<Range1ul>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1ul> item = default(Tensor<Range1ul>); CodeTensor_of_Range1ul_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_Array(ref Tensor<Range1f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1f> item = default(Tensor<Range1f>); CodeTensor_of_Range1f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_Array(ref Tensor<Range1d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1d> item = default(Tensor<Range1d>); CodeTensor_of_Range1d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_Array(ref Tensor<Box2i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box2i> item = default(Tensor<Box2i>); CodeTensor_of_Box2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_Array(ref Tensor<Box2l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box2l> item = default(Tensor<Box2l>); CodeTensor_of_Box2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_Array(ref Tensor<Box2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box2f> item = default(Tensor<Box2f>); CodeTensor_of_Box2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_Array(ref Tensor<Box2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box2d> item = default(Tensor<Box2d>); CodeTensor_of_Box2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_Array(ref Tensor<Box3i>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box3i> item = default(Tensor<Box3i>); CodeTensor_of_Box3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_Array(ref Tensor<Box3l>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box3l> item = default(Tensor<Box3l>); CodeTensor_of_Box3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_Array(ref Tensor<Box3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box3f> item = default(Tensor<Box3f>); CodeTensor_of_Box3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_Array(ref Tensor<Box3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box3d> item = default(Tensor<Box3d>); CodeTensor_of_Box3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_Array(ref Tensor<Euclidean3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Euclidean3f> item = default(Tensor<Euclidean3f>); CodeTensor_of_Euclidean3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_Array(ref Tensor<Euclidean3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Euclidean3d> item = default(Tensor<Euclidean3d>); CodeTensor_of_Euclidean3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_Array(ref Tensor<Rot2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Rot2f> item = default(Tensor<Rot2f>); CodeTensor_of_Rot2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_Array(ref Tensor<Rot2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Rot2d> item = default(Tensor<Rot2d>); CodeTensor_of_Rot2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_Array(ref Tensor<Rot3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Rot3f> item = default(Tensor<Rot3f>); CodeTensor_of_Rot3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_Array(ref Tensor<Rot3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Rot3d> item = default(Tensor<Rot3d>); CodeTensor_of_Rot3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_Array(ref Tensor<Scale3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Scale3f> item = default(Tensor<Scale3f>); CodeTensor_of_Scale3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_Array(ref Tensor<Scale3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Scale3d> item = default(Tensor<Scale3d>); CodeTensor_of_Scale3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_Array(ref Tensor<Shift3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Shift3f> item = default(Tensor<Shift3f>); CodeTensor_of_Shift3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_Array(ref Tensor<Shift3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Shift3d> item = default(Tensor<Shift3d>); CodeTensor_of_Shift3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_Array(ref Tensor<Trafo2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Trafo2f> item = default(Tensor<Trafo2f>); CodeTensor_of_Trafo2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_Array(ref Tensor<Trafo2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Trafo2d> item = default(Tensor<Trafo2d>); CodeTensor_of_Trafo2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_Array(ref Tensor<Trafo3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Trafo3f> item = default(Tensor<Trafo3f>); CodeTensor_of_Trafo3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_Array(ref Tensor<Trafo3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Trafo3d> item = default(Tensor<Trafo3d>); CodeTensor_of_Trafo3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_Array(ref Tensor<bool>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<bool> item = default(Tensor<bool>); CodeTensor_of_Bool_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Char_Array(ref Tensor<char>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<char> item = default(Tensor<char>); CodeTensor_of_Char_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_String_Array(ref Tensor<string>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<string> item = default(Tensor<string>); CodeTensor_of_String_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Type_Array(ref Tensor<Type>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Type> item = default(Tensor<Type>); CodeTensor_of_Type_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_Array(ref Tensor<Guid>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Guid> item = default(Tensor<Guid>); CodeTensor_of_Guid_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_Array(ref Tensor<Symbol>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Symbol> item = default(Tensor<Symbol>); CodeTensor_of_Symbol_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_Array(ref Tensor<Circle2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Circle2d> item = default(Tensor<Circle2d>); CodeTensor_of_Circle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_Array(ref Tensor<Line2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Line2d> item = default(Tensor<Line2d>); CodeTensor_of_Line2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_Array(ref Tensor<Line3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Line3d> item = default(Tensor<Line3d>); CodeTensor_of_Line3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_Array(ref Tensor<Plane2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Plane2d> item = default(Tensor<Plane2d>); CodeTensor_of_Plane2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_Array(ref Tensor<Plane3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Plane3d> item = default(Tensor<Plane3d>); CodeTensor_of_Plane3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_Array(ref Tensor<PlaneWithPoint3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<PlaneWithPoint3d> item = default(Tensor<PlaneWithPoint3d>); CodeTensor_of_PlaneWithPoint3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_Array(ref Tensor<Quad2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Quad2d> item = default(Tensor<Quad2d>); CodeTensor_of_Quad2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_Array(ref Tensor<Quad3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Quad3d> item = default(Tensor<Quad3d>); CodeTensor_of_Quad3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_Array(ref Tensor<Ray2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Ray2d> item = default(Tensor<Ray2d>); CodeTensor_of_Ray2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_Array(ref Tensor<Ray3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Ray3d> item = default(Tensor<Ray3d>); CodeTensor_of_Ray3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_Array(ref Tensor<Sphere3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Sphere3d> item = default(Tensor<Sphere3d>); CodeTensor_of_Sphere3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_Array(ref Tensor<Triangle2d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Triangle2d> item = default(Tensor<Triangle2d>); CodeTensor_of_Triangle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_Array(ref Tensor<Triangle3d>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Triangle3d> item = default(Tensor<Triangle3d>); CodeTensor_of_Triangle3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_Array(ref Tensor<Circle2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Circle2f> item = default(Tensor<Circle2f>); CodeTensor_of_Circle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_Array(ref Tensor<Line2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Line2f> item = default(Tensor<Line2f>); CodeTensor_of_Line2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_Array(ref Tensor<Line3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Line3f> item = default(Tensor<Line3f>); CodeTensor_of_Line3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_Array(ref Tensor<Plane2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Plane2f> item = default(Tensor<Plane2f>); CodeTensor_of_Plane2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_Array(ref Tensor<Plane3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Plane3f> item = default(Tensor<Plane3f>); CodeTensor_of_Plane3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_Array(ref Tensor<PlaneWithPoint3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<PlaneWithPoint3f> item = default(Tensor<PlaneWithPoint3f>); CodeTensor_of_PlaneWithPoint3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_Array(ref Tensor<Quad2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Quad2f> item = default(Tensor<Quad2f>); CodeTensor_of_Quad2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_Array(ref Tensor<Quad3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Quad3f> item = default(Tensor<Quad3f>); CodeTensor_of_Quad3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_Array(ref Tensor<Ray2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Ray2f> item = default(Tensor<Ray2f>); CodeTensor_of_Ray2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_Array(ref Tensor<Ray3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Ray3f> item = default(Tensor<Ray3f>); CodeTensor_of_Ray3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_Array(ref Tensor<Sphere3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Sphere3f> item = default(Tensor<Sphere3f>); CodeTensor_of_Sphere3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_Array(ref Tensor<Triangle2f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Triangle2f> item = default(Tensor<Triangle2f>); CodeTensor_of_Triangle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_Array(ref Tensor<Triangle3f>[] value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Triangle3f> item = default(Tensor<Triangle3f>); CodeTensor_of_Triangle3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Lists of Tensors\r\n\r\n        public void CodeList_of_Vector_of_Byte__(ref List<Vector<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<byte> item = default(Vector<byte>); CodeVector_of_Byte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_SByte__(ref List<Vector<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<sbyte> item = default(Vector<sbyte>); CodeVector_of_SByte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Short__(ref List<Vector<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<short> item = default(Vector<short>); CodeVector_of_Short_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_UShort__(ref List<Vector<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<ushort> item = default(Vector<ushort>); CodeVector_of_UShort_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Int__(ref List<Vector<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<int> item = default(Vector<int>); CodeVector_of_Int_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_UInt__(ref List<Vector<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<uint> item = default(Vector<uint>); CodeVector_of_UInt_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Long__(ref List<Vector<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<long> item = default(Vector<long>); CodeVector_of_Long_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_ULong__(ref List<Vector<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<ulong> item = default(Vector<ulong>); CodeVector_of_ULong_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Float__(ref List<Vector<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<float> item = default(Vector<float>); CodeVector_of_Float_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Double__(ref List<Vector<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<double> item = default(Vector<double>); CodeVector_of_Double_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Fraction__(ref List<Vector<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Fraction> item = default(Vector<Fraction>); CodeVector_of_Fraction_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2i__(ref List<Vector<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V2i> item = default(Vector<V2i>); CodeVector_of_V2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2l__(ref List<Vector<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V2l> item = default(Vector<V2l>); CodeVector_of_V2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2f__(ref List<Vector<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V2f> item = default(Vector<V2f>); CodeVector_of_V2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V2d__(ref List<Vector<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V2d> item = default(Vector<V2d>); CodeVector_of_V2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3i__(ref List<Vector<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V3i> item = default(Vector<V3i>); CodeVector_of_V3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3l__(ref List<Vector<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V3l> item = default(Vector<V3l>); CodeVector_of_V3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3f__(ref List<Vector<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V3f> item = default(Vector<V3f>); CodeVector_of_V3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V3d__(ref List<Vector<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V3d> item = default(Vector<V3d>); CodeVector_of_V3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4i__(ref List<Vector<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V4i> item = default(Vector<V4i>); CodeVector_of_V4i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4l__(ref List<Vector<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V4l> item = default(Vector<V4l>); CodeVector_of_V4l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4f__(ref List<Vector<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V4f> item = default(Vector<V4f>); CodeVector_of_V4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_V4d__(ref List<Vector<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<V4d> item = default(Vector<V4d>); CodeVector_of_V4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22i__(ref List<Vector<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M22i> item = default(Vector<M22i>); CodeVector_of_M22i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22l__(ref List<Vector<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M22l> item = default(Vector<M22l>); CodeVector_of_M22l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22f__(ref List<Vector<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M22f> item = default(Vector<M22f>); CodeVector_of_M22f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M22d__(ref List<Vector<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M22d> item = default(Vector<M22d>); CodeVector_of_M22d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23i__(ref List<Vector<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M23i> item = default(Vector<M23i>); CodeVector_of_M23i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23l__(ref List<Vector<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M23l> item = default(Vector<M23l>); CodeVector_of_M23l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23f__(ref List<Vector<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M23f> item = default(Vector<M23f>); CodeVector_of_M23f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M23d__(ref List<Vector<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M23d> item = default(Vector<M23d>); CodeVector_of_M23d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33i__(ref List<Vector<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M33i> item = default(Vector<M33i>); CodeVector_of_M33i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33l__(ref List<Vector<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M33l> item = default(Vector<M33l>); CodeVector_of_M33l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33f__(ref List<Vector<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M33f> item = default(Vector<M33f>); CodeVector_of_M33f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M33d__(ref List<Vector<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M33d> item = default(Vector<M33d>); CodeVector_of_M33d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34i__(ref List<Vector<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M34i> item = default(Vector<M34i>); CodeVector_of_M34i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34l__(ref List<Vector<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M34l> item = default(Vector<M34l>); CodeVector_of_M34l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34f__(ref List<Vector<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M34f> item = default(Vector<M34f>); CodeVector_of_M34f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M34d__(ref List<Vector<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M34d> item = default(Vector<M34d>); CodeVector_of_M34d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44i__(ref List<Vector<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M44i> item = default(Vector<M44i>); CodeVector_of_M44i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44l__(ref List<Vector<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M44l> item = default(Vector<M44l>); CodeVector_of_M44l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44f__(ref List<Vector<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M44f> item = default(Vector<M44f>); CodeVector_of_M44f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_M44d__(ref List<Vector<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<M44d> item = default(Vector<M44d>); CodeVector_of_M44d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3b__(ref List<Vector<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3b> item = default(Vector<C3b>); CodeVector_of_C3b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3us__(ref List<Vector<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3us> item = default(Vector<C3us>); CodeVector_of_C3us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3ui__(ref List<Vector<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3ui> item = default(Vector<C3ui>); CodeVector_of_C3ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3f__(ref List<Vector<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3f> item = default(Vector<C3f>); CodeVector_of_C3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C3d__(ref List<Vector<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C3d> item = default(Vector<C3d>); CodeVector_of_C3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4b__(ref List<Vector<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4b> item = default(Vector<C4b>); CodeVector_of_C4b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4us__(ref List<Vector<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4us> item = default(Vector<C4us>); CodeVector_of_C4us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4ui__(ref List<Vector<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4ui> item = default(Vector<C4ui>); CodeVector_of_C4ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4f__(ref List<Vector<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4f> item = default(Vector<C4f>); CodeVector_of_C4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_C4d__(ref List<Vector<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<C4d> item = default(Vector<C4d>); CodeVector_of_C4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1b__(ref List<Vector<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1b> item = default(Vector<Range1b>); CodeVector_of_Range1b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1sb__(ref List<Vector<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1sb> item = default(Vector<Range1sb>); CodeVector_of_Range1sb_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1s__(ref List<Vector<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1s> item = default(Vector<Range1s>); CodeVector_of_Range1s_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1us__(ref List<Vector<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1us> item = default(Vector<Range1us>); CodeVector_of_Range1us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1i__(ref List<Vector<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1i> item = default(Vector<Range1i>); CodeVector_of_Range1i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1ui__(ref List<Vector<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1ui> item = default(Vector<Range1ui>); CodeVector_of_Range1ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1l__(ref List<Vector<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1l> item = default(Vector<Range1l>); CodeVector_of_Range1l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1ul__(ref List<Vector<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1ul> item = default(Vector<Range1ul>); CodeVector_of_Range1ul_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1f__(ref List<Vector<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1f> item = default(Vector<Range1f>); CodeVector_of_Range1f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Range1d__(ref List<Vector<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Range1d> item = default(Vector<Range1d>); CodeVector_of_Range1d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2i__(ref List<Vector<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box2i> item = default(Vector<Box2i>); CodeVector_of_Box2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2l__(ref List<Vector<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box2l> item = default(Vector<Box2l>); CodeVector_of_Box2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2f__(ref List<Vector<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box2f> item = default(Vector<Box2f>); CodeVector_of_Box2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box2d__(ref List<Vector<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box2d> item = default(Vector<Box2d>); CodeVector_of_Box2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3i__(ref List<Vector<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box3i> item = default(Vector<Box3i>); CodeVector_of_Box3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3l__(ref List<Vector<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box3l> item = default(Vector<Box3l>); CodeVector_of_Box3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3f__(ref List<Vector<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box3f> item = default(Vector<Box3f>); CodeVector_of_Box3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Box3d__(ref List<Vector<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Box3d> item = default(Vector<Box3d>); CodeVector_of_Box3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Euclidean3f__(ref List<Vector<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Euclidean3f> item = default(Vector<Euclidean3f>); CodeVector_of_Euclidean3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Euclidean3d__(ref List<Vector<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Euclidean3d> item = default(Vector<Euclidean3d>); CodeVector_of_Euclidean3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot2f__(ref List<Vector<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Rot2f> item = default(Vector<Rot2f>); CodeVector_of_Rot2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot2d__(ref List<Vector<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Rot2d> item = default(Vector<Rot2d>); CodeVector_of_Rot2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot3f__(ref List<Vector<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Rot3f> item = default(Vector<Rot3f>); CodeVector_of_Rot3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Rot3d__(ref List<Vector<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Rot3d> item = default(Vector<Rot3d>); CodeVector_of_Rot3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Scale3f__(ref List<Vector<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Scale3f> item = default(Vector<Scale3f>); CodeVector_of_Scale3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Scale3d__(ref List<Vector<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Scale3d> item = default(Vector<Scale3d>); CodeVector_of_Scale3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Shift3f__(ref List<Vector<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Shift3f> item = default(Vector<Shift3f>); CodeVector_of_Shift3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Shift3d__(ref List<Vector<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Shift3d> item = default(Vector<Shift3d>); CodeVector_of_Shift3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo2f__(ref List<Vector<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Trafo2f> item = default(Vector<Trafo2f>); CodeVector_of_Trafo2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo2d__(ref List<Vector<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Trafo2d> item = default(Vector<Trafo2d>); CodeVector_of_Trafo2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo3f__(ref List<Vector<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Trafo3f> item = default(Vector<Trafo3f>); CodeVector_of_Trafo3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Trafo3d__(ref List<Vector<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Trafo3d> item = default(Vector<Trafo3d>); CodeVector_of_Trafo3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Bool__(ref List<Vector<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<bool> item = default(Vector<bool>); CodeVector_of_Bool_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Char__(ref List<Vector<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<char> item = default(Vector<char>); CodeVector_of_Char_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_String__(ref List<Vector<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<string> item = default(Vector<string>); CodeVector_of_String_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Type__(ref List<Vector<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Type> item = default(Vector<Type>); CodeVector_of_Type_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Guid__(ref List<Vector<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Guid> item = default(Vector<Guid>); CodeVector_of_Guid_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Symbol__(ref List<Vector<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Symbol> item = default(Vector<Symbol>); CodeVector_of_Symbol_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Circle2d__(ref List<Vector<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Circle2d> item = default(Vector<Circle2d>); CodeVector_of_Circle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line2d__(ref List<Vector<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Line2d> item = default(Vector<Line2d>); CodeVector_of_Line2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line3d__(ref List<Vector<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Line3d> item = default(Vector<Line3d>); CodeVector_of_Line3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane2d__(ref List<Vector<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Plane2d> item = default(Vector<Plane2d>); CodeVector_of_Plane2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane3d__(ref List<Vector<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Plane3d> item = default(Vector<Plane3d>); CodeVector_of_Plane3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3d__(ref List<Vector<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<PlaneWithPoint3d> item = default(Vector<PlaneWithPoint3d>); CodeVector_of_PlaneWithPoint3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad2d__(ref List<Vector<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Quad2d> item = default(Vector<Quad2d>); CodeVector_of_Quad2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad3d__(ref List<Vector<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Quad3d> item = default(Vector<Quad3d>); CodeVector_of_Quad3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray2d__(ref List<Vector<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Ray2d> item = default(Vector<Ray2d>); CodeVector_of_Ray2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray3d__(ref List<Vector<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Ray3d> item = default(Vector<Ray3d>); CodeVector_of_Ray3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Sphere3d__(ref List<Vector<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Sphere3d> item = default(Vector<Sphere3d>); CodeVector_of_Sphere3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle2d__(ref List<Vector<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Triangle2d> item = default(Vector<Triangle2d>); CodeVector_of_Triangle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle3d__(ref List<Vector<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Triangle3d> item = default(Vector<Triangle3d>); CodeVector_of_Triangle3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Circle2f__(ref List<Vector<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Circle2f> item = default(Vector<Circle2f>); CodeVector_of_Circle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line2f__(ref List<Vector<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Line2f> item = default(Vector<Line2f>); CodeVector_of_Line2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Line3f__(ref List<Vector<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Line3f> item = default(Vector<Line3f>); CodeVector_of_Line3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane2f__(ref List<Vector<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Plane2f> item = default(Vector<Plane2f>); CodeVector_of_Plane2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Plane3f__(ref List<Vector<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Plane3f> item = default(Vector<Plane3f>); CodeVector_of_Plane3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3f__(ref List<Vector<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<PlaneWithPoint3f> item = default(Vector<PlaneWithPoint3f>); CodeVector_of_PlaneWithPoint3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad2f__(ref List<Vector<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Quad2f> item = default(Vector<Quad2f>); CodeVector_of_Quad2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Quad3f__(ref List<Vector<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Quad3f> item = default(Vector<Quad3f>); CodeVector_of_Quad3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray2f__(ref List<Vector<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Ray2f> item = default(Vector<Ray2f>); CodeVector_of_Ray2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Ray3f__(ref List<Vector<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Ray3f> item = default(Vector<Ray3f>); CodeVector_of_Ray3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Sphere3f__(ref List<Vector<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Sphere3f> item = default(Vector<Sphere3f>); CodeVector_of_Sphere3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle2f__(ref List<Vector<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Triangle2f> item = default(Vector<Triangle2f>); CodeVector_of_Triangle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Vector_of_Triangle3f__(ref List<Vector<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Vector<Triangle3f> item = default(Vector<Triangle3f>); CodeVector_of_Triangle3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Byte__(ref List<Matrix<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<byte> item = default(Matrix<byte>); CodeMatrix_of_Byte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_SByte__(ref List<Matrix<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<sbyte> item = default(Matrix<sbyte>); CodeMatrix_of_SByte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Short__(ref List<Matrix<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<short> item = default(Matrix<short>); CodeMatrix_of_Short_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_UShort__(ref List<Matrix<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<ushort> item = default(Matrix<ushort>); CodeMatrix_of_UShort_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Int__(ref List<Matrix<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<int> item = default(Matrix<int>); CodeMatrix_of_Int_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_UInt__(ref List<Matrix<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<uint> item = default(Matrix<uint>); CodeMatrix_of_UInt_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Long__(ref List<Matrix<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<long> item = default(Matrix<long>); CodeMatrix_of_Long_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_ULong__(ref List<Matrix<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<ulong> item = default(Matrix<ulong>); CodeMatrix_of_ULong_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Float__(ref List<Matrix<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<float> item = default(Matrix<float>); CodeMatrix_of_Float_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Double__(ref List<Matrix<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<double> item = default(Matrix<double>); CodeMatrix_of_Double_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Fraction__(ref List<Matrix<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Fraction> item = default(Matrix<Fraction>); CodeMatrix_of_Fraction_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2i__(ref List<Matrix<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V2i> item = default(Matrix<V2i>); CodeMatrix_of_V2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2l__(ref List<Matrix<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V2l> item = default(Matrix<V2l>); CodeMatrix_of_V2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2f__(ref List<Matrix<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V2f> item = default(Matrix<V2f>); CodeMatrix_of_V2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V2d__(ref List<Matrix<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V2d> item = default(Matrix<V2d>); CodeMatrix_of_V2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3i__(ref List<Matrix<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V3i> item = default(Matrix<V3i>); CodeMatrix_of_V3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3l__(ref List<Matrix<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V3l> item = default(Matrix<V3l>); CodeMatrix_of_V3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3f__(ref List<Matrix<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V3f> item = default(Matrix<V3f>); CodeMatrix_of_V3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V3d__(ref List<Matrix<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V3d> item = default(Matrix<V3d>); CodeMatrix_of_V3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4i__(ref List<Matrix<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V4i> item = default(Matrix<V4i>); CodeMatrix_of_V4i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4l__(ref List<Matrix<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V4l> item = default(Matrix<V4l>); CodeMatrix_of_V4l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4f__(ref List<Matrix<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V4f> item = default(Matrix<V4f>); CodeMatrix_of_V4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_V4d__(ref List<Matrix<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<V4d> item = default(Matrix<V4d>); CodeMatrix_of_V4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22i__(ref List<Matrix<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M22i> item = default(Matrix<M22i>); CodeMatrix_of_M22i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22l__(ref List<Matrix<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M22l> item = default(Matrix<M22l>); CodeMatrix_of_M22l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22f__(ref List<Matrix<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M22f> item = default(Matrix<M22f>); CodeMatrix_of_M22f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M22d__(ref List<Matrix<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M22d> item = default(Matrix<M22d>); CodeMatrix_of_M22d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23i__(ref List<Matrix<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M23i> item = default(Matrix<M23i>); CodeMatrix_of_M23i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23l__(ref List<Matrix<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M23l> item = default(Matrix<M23l>); CodeMatrix_of_M23l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23f__(ref List<Matrix<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M23f> item = default(Matrix<M23f>); CodeMatrix_of_M23f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M23d__(ref List<Matrix<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M23d> item = default(Matrix<M23d>); CodeMatrix_of_M23d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33i__(ref List<Matrix<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M33i> item = default(Matrix<M33i>); CodeMatrix_of_M33i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33l__(ref List<Matrix<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M33l> item = default(Matrix<M33l>); CodeMatrix_of_M33l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33f__(ref List<Matrix<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M33f> item = default(Matrix<M33f>); CodeMatrix_of_M33f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M33d__(ref List<Matrix<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M33d> item = default(Matrix<M33d>); CodeMatrix_of_M33d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34i__(ref List<Matrix<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M34i> item = default(Matrix<M34i>); CodeMatrix_of_M34i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34l__(ref List<Matrix<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M34l> item = default(Matrix<M34l>); CodeMatrix_of_M34l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34f__(ref List<Matrix<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M34f> item = default(Matrix<M34f>); CodeMatrix_of_M34f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M34d__(ref List<Matrix<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M34d> item = default(Matrix<M34d>); CodeMatrix_of_M34d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44i__(ref List<Matrix<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M44i> item = default(Matrix<M44i>); CodeMatrix_of_M44i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44l__(ref List<Matrix<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M44l> item = default(Matrix<M44l>); CodeMatrix_of_M44l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44f__(ref List<Matrix<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M44f> item = default(Matrix<M44f>); CodeMatrix_of_M44f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_M44d__(ref List<Matrix<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<M44d> item = default(Matrix<M44d>); CodeMatrix_of_M44d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3b__(ref List<Matrix<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3b> item = default(Matrix<C3b>); CodeMatrix_of_C3b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3us__(ref List<Matrix<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3us> item = default(Matrix<C3us>); CodeMatrix_of_C3us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3ui__(ref List<Matrix<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3ui> item = default(Matrix<C3ui>); CodeMatrix_of_C3ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3f__(ref List<Matrix<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3f> item = default(Matrix<C3f>); CodeMatrix_of_C3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C3d__(ref List<Matrix<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C3d> item = default(Matrix<C3d>); CodeMatrix_of_C3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4b__(ref List<Matrix<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4b> item = default(Matrix<C4b>); CodeMatrix_of_C4b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4us__(ref List<Matrix<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4us> item = default(Matrix<C4us>); CodeMatrix_of_C4us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4ui__(ref List<Matrix<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4ui> item = default(Matrix<C4ui>); CodeMatrix_of_C4ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4f__(ref List<Matrix<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4f> item = default(Matrix<C4f>); CodeMatrix_of_C4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_C4d__(ref List<Matrix<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<C4d> item = default(Matrix<C4d>); CodeMatrix_of_C4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1b__(ref List<Matrix<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1b> item = default(Matrix<Range1b>); CodeMatrix_of_Range1b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1sb__(ref List<Matrix<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1sb> item = default(Matrix<Range1sb>); CodeMatrix_of_Range1sb_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1s__(ref List<Matrix<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1s> item = default(Matrix<Range1s>); CodeMatrix_of_Range1s_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1us__(ref List<Matrix<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1us> item = default(Matrix<Range1us>); CodeMatrix_of_Range1us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1i__(ref List<Matrix<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1i> item = default(Matrix<Range1i>); CodeMatrix_of_Range1i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1ui__(ref List<Matrix<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1ui> item = default(Matrix<Range1ui>); CodeMatrix_of_Range1ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1l__(ref List<Matrix<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1l> item = default(Matrix<Range1l>); CodeMatrix_of_Range1l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1ul__(ref List<Matrix<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1ul> item = default(Matrix<Range1ul>); CodeMatrix_of_Range1ul_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1f__(ref List<Matrix<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1f> item = default(Matrix<Range1f>); CodeMatrix_of_Range1f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Range1d__(ref List<Matrix<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Range1d> item = default(Matrix<Range1d>); CodeMatrix_of_Range1d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2i__(ref List<Matrix<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box2i> item = default(Matrix<Box2i>); CodeMatrix_of_Box2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2l__(ref List<Matrix<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box2l> item = default(Matrix<Box2l>); CodeMatrix_of_Box2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2f__(ref List<Matrix<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box2f> item = default(Matrix<Box2f>); CodeMatrix_of_Box2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box2d__(ref List<Matrix<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box2d> item = default(Matrix<Box2d>); CodeMatrix_of_Box2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3i__(ref List<Matrix<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box3i> item = default(Matrix<Box3i>); CodeMatrix_of_Box3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3l__(ref List<Matrix<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box3l> item = default(Matrix<Box3l>); CodeMatrix_of_Box3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3f__(ref List<Matrix<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box3f> item = default(Matrix<Box3f>); CodeMatrix_of_Box3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Box3d__(ref List<Matrix<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Box3d> item = default(Matrix<Box3d>); CodeMatrix_of_Box3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Euclidean3f__(ref List<Matrix<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Euclidean3f> item = default(Matrix<Euclidean3f>); CodeMatrix_of_Euclidean3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Euclidean3d__(ref List<Matrix<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Euclidean3d> item = default(Matrix<Euclidean3d>); CodeMatrix_of_Euclidean3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot2f__(ref List<Matrix<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Rot2f> item = default(Matrix<Rot2f>); CodeMatrix_of_Rot2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot2d__(ref List<Matrix<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Rot2d> item = default(Matrix<Rot2d>); CodeMatrix_of_Rot2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot3f__(ref List<Matrix<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Rot3f> item = default(Matrix<Rot3f>); CodeMatrix_of_Rot3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Rot3d__(ref List<Matrix<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Rot3d> item = default(Matrix<Rot3d>); CodeMatrix_of_Rot3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Scale3f__(ref List<Matrix<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Scale3f> item = default(Matrix<Scale3f>); CodeMatrix_of_Scale3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Scale3d__(ref List<Matrix<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Scale3d> item = default(Matrix<Scale3d>); CodeMatrix_of_Scale3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Shift3f__(ref List<Matrix<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Shift3f> item = default(Matrix<Shift3f>); CodeMatrix_of_Shift3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Shift3d__(ref List<Matrix<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Shift3d> item = default(Matrix<Shift3d>); CodeMatrix_of_Shift3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo2f__(ref List<Matrix<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Trafo2f> item = default(Matrix<Trafo2f>); CodeMatrix_of_Trafo2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo2d__(ref List<Matrix<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Trafo2d> item = default(Matrix<Trafo2d>); CodeMatrix_of_Trafo2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo3f__(ref List<Matrix<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Trafo3f> item = default(Matrix<Trafo3f>); CodeMatrix_of_Trafo3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Trafo3d__(ref List<Matrix<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Trafo3d> item = default(Matrix<Trafo3d>); CodeMatrix_of_Trafo3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Bool__(ref List<Matrix<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<bool> item = default(Matrix<bool>); CodeMatrix_of_Bool_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Char__(ref List<Matrix<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<char> item = default(Matrix<char>); CodeMatrix_of_Char_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_String__(ref List<Matrix<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<string> item = default(Matrix<string>); CodeMatrix_of_String_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Type__(ref List<Matrix<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Type> item = default(Matrix<Type>); CodeMatrix_of_Type_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Guid__(ref List<Matrix<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Guid> item = default(Matrix<Guid>); CodeMatrix_of_Guid_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Symbol__(ref List<Matrix<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Symbol> item = default(Matrix<Symbol>); CodeMatrix_of_Symbol_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Circle2d__(ref List<Matrix<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Circle2d> item = default(Matrix<Circle2d>); CodeMatrix_of_Circle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line2d__(ref List<Matrix<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Line2d> item = default(Matrix<Line2d>); CodeMatrix_of_Line2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line3d__(ref List<Matrix<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Line3d> item = default(Matrix<Line3d>); CodeMatrix_of_Line3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane2d__(ref List<Matrix<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Plane2d> item = default(Matrix<Plane2d>); CodeMatrix_of_Plane2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane3d__(ref List<Matrix<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Plane3d> item = default(Matrix<Plane3d>); CodeMatrix_of_Plane3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3d__(ref List<Matrix<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<PlaneWithPoint3d> item = default(Matrix<PlaneWithPoint3d>); CodeMatrix_of_PlaneWithPoint3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad2d__(ref List<Matrix<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Quad2d> item = default(Matrix<Quad2d>); CodeMatrix_of_Quad2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad3d__(ref List<Matrix<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Quad3d> item = default(Matrix<Quad3d>); CodeMatrix_of_Quad3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray2d__(ref List<Matrix<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Ray2d> item = default(Matrix<Ray2d>); CodeMatrix_of_Ray2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray3d__(ref List<Matrix<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Ray3d> item = default(Matrix<Ray3d>); CodeMatrix_of_Ray3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Sphere3d__(ref List<Matrix<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Sphere3d> item = default(Matrix<Sphere3d>); CodeMatrix_of_Sphere3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle2d__(ref List<Matrix<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Triangle2d> item = default(Matrix<Triangle2d>); CodeMatrix_of_Triangle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle3d__(ref List<Matrix<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Triangle3d> item = default(Matrix<Triangle3d>); CodeMatrix_of_Triangle3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Circle2f__(ref List<Matrix<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Circle2f> item = default(Matrix<Circle2f>); CodeMatrix_of_Circle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line2f__(ref List<Matrix<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Line2f> item = default(Matrix<Line2f>); CodeMatrix_of_Line2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Line3f__(ref List<Matrix<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Line3f> item = default(Matrix<Line3f>); CodeMatrix_of_Line3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane2f__(ref List<Matrix<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Plane2f> item = default(Matrix<Plane2f>); CodeMatrix_of_Plane2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Plane3f__(ref List<Matrix<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Plane3f> item = default(Matrix<Plane3f>); CodeMatrix_of_Plane3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3f__(ref List<Matrix<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<PlaneWithPoint3f> item = default(Matrix<PlaneWithPoint3f>); CodeMatrix_of_PlaneWithPoint3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad2f__(ref List<Matrix<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Quad2f> item = default(Matrix<Quad2f>); CodeMatrix_of_Quad2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Quad3f__(ref List<Matrix<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Quad3f> item = default(Matrix<Quad3f>); CodeMatrix_of_Quad3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray2f__(ref List<Matrix<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Ray2f> item = default(Matrix<Ray2f>); CodeMatrix_of_Ray2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Ray3f__(ref List<Matrix<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Ray3f> item = default(Matrix<Ray3f>); CodeMatrix_of_Ray3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Sphere3f__(ref List<Matrix<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Sphere3f> item = default(Matrix<Sphere3f>); CodeMatrix_of_Sphere3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle2f__(ref List<Matrix<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Triangle2f> item = default(Matrix<Triangle2f>); CodeMatrix_of_Triangle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Matrix_of_Triangle3f__(ref List<Matrix<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Matrix<Triangle3f> item = default(Matrix<Triangle3f>); CodeMatrix_of_Triangle3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Byte__(ref List<Volume<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<byte> item = default(Volume<byte>); CodeVolume_of_Byte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_SByte__(ref List<Volume<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<sbyte> item = default(Volume<sbyte>); CodeVolume_of_SByte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Short__(ref List<Volume<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<short> item = default(Volume<short>); CodeVolume_of_Short_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_UShort__(ref List<Volume<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<ushort> item = default(Volume<ushort>); CodeVolume_of_UShort_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Int__(ref List<Volume<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<int> item = default(Volume<int>); CodeVolume_of_Int_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_UInt__(ref List<Volume<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<uint> item = default(Volume<uint>); CodeVolume_of_UInt_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Long__(ref List<Volume<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<long> item = default(Volume<long>); CodeVolume_of_Long_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_ULong__(ref List<Volume<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<ulong> item = default(Volume<ulong>); CodeVolume_of_ULong_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Float__(ref List<Volume<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<float> item = default(Volume<float>); CodeVolume_of_Float_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Double__(ref List<Volume<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<double> item = default(Volume<double>); CodeVolume_of_Double_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Fraction__(ref List<Volume<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Fraction> item = default(Volume<Fraction>); CodeVolume_of_Fraction_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2i__(ref List<Volume<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V2i> item = default(Volume<V2i>); CodeVolume_of_V2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2l__(ref List<Volume<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V2l> item = default(Volume<V2l>); CodeVolume_of_V2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2f__(ref List<Volume<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V2f> item = default(Volume<V2f>); CodeVolume_of_V2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V2d__(ref List<Volume<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V2d> item = default(Volume<V2d>); CodeVolume_of_V2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3i__(ref List<Volume<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V3i> item = default(Volume<V3i>); CodeVolume_of_V3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3l__(ref List<Volume<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V3l> item = default(Volume<V3l>); CodeVolume_of_V3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3f__(ref List<Volume<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V3f> item = default(Volume<V3f>); CodeVolume_of_V3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V3d__(ref List<Volume<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V3d> item = default(Volume<V3d>); CodeVolume_of_V3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4i__(ref List<Volume<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V4i> item = default(Volume<V4i>); CodeVolume_of_V4i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4l__(ref List<Volume<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V4l> item = default(Volume<V4l>); CodeVolume_of_V4l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4f__(ref List<Volume<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V4f> item = default(Volume<V4f>); CodeVolume_of_V4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_V4d__(ref List<Volume<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<V4d> item = default(Volume<V4d>); CodeVolume_of_V4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22i__(ref List<Volume<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M22i> item = default(Volume<M22i>); CodeVolume_of_M22i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22l__(ref List<Volume<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M22l> item = default(Volume<M22l>); CodeVolume_of_M22l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22f__(ref List<Volume<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M22f> item = default(Volume<M22f>); CodeVolume_of_M22f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M22d__(ref List<Volume<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M22d> item = default(Volume<M22d>); CodeVolume_of_M22d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23i__(ref List<Volume<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M23i> item = default(Volume<M23i>); CodeVolume_of_M23i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23l__(ref List<Volume<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M23l> item = default(Volume<M23l>); CodeVolume_of_M23l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23f__(ref List<Volume<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M23f> item = default(Volume<M23f>); CodeVolume_of_M23f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M23d__(ref List<Volume<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M23d> item = default(Volume<M23d>); CodeVolume_of_M23d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33i__(ref List<Volume<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M33i> item = default(Volume<M33i>); CodeVolume_of_M33i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33l__(ref List<Volume<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M33l> item = default(Volume<M33l>); CodeVolume_of_M33l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33f__(ref List<Volume<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M33f> item = default(Volume<M33f>); CodeVolume_of_M33f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M33d__(ref List<Volume<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M33d> item = default(Volume<M33d>); CodeVolume_of_M33d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34i__(ref List<Volume<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M34i> item = default(Volume<M34i>); CodeVolume_of_M34i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34l__(ref List<Volume<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M34l> item = default(Volume<M34l>); CodeVolume_of_M34l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34f__(ref List<Volume<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M34f> item = default(Volume<M34f>); CodeVolume_of_M34f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M34d__(ref List<Volume<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M34d> item = default(Volume<M34d>); CodeVolume_of_M34d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44i__(ref List<Volume<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M44i> item = default(Volume<M44i>); CodeVolume_of_M44i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44l__(ref List<Volume<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M44l> item = default(Volume<M44l>); CodeVolume_of_M44l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44f__(ref List<Volume<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M44f> item = default(Volume<M44f>); CodeVolume_of_M44f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_M44d__(ref List<Volume<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<M44d> item = default(Volume<M44d>); CodeVolume_of_M44d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3b__(ref List<Volume<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3b> item = default(Volume<C3b>); CodeVolume_of_C3b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3us__(ref List<Volume<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3us> item = default(Volume<C3us>); CodeVolume_of_C3us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3ui__(ref List<Volume<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3ui> item = default(Volume<C3ui>); CodeVolume_of_C3ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3f__(ref List<Volume<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3f> item = default(Volume<C3f>); CodeVolume_of_C3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C3d__(ref List<Volume<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C3d> item = default(Volume<C3d>); CodeVolume_of_C3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4b__(ref List<Volume<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4b> item = default(Volume<C4b>); CodeVolume_of_C4b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4us__(ref List<Volume<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4us> item = default(Volume<C4us>); CodeVolume_of_C4us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4ui__(ref List<Volume<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4ui> item = default(Volume<C4ui>); CodeVolume_of_C4ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4f__(ref List<Volume<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4f> item = default(Volume<C4f>); CodeVolume_of_C4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_C4d__(ref List<Volume<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<C4d> item = default(Volume<C4d>); CodeVolume_of_C4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1b__(ref List<Volume<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1b> item = default(Volume<Range1b>); CodeVolume_of_Range1b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1sb__(ref List<Volume<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1sb> item = default(Volume<Range1sb>); CodeVolume_of_Range1sb_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1s__(ref List<Volume<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1s> item = default(Volume<Range1s>); CodeVolume_of_Range1s_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1us__(ref List<Volume<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1us> item = default(Volume<Range1us>); CodeVolume_of_Range1us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1i__(ref List<Volume<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1i> item = default(Volume<Range1i>); CodeVolume_of_Range1i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1ui__(ref List<Volume<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1ui> item = default(Volume<Range1ui>); CodeVolume_of_Range1ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1l__(ref List<Volume<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1l> item = default(Volume<Range1l>); CodeVolume_of_Range1l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1ul__(ref List<Volume<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1ul> item = default(Volume<Range1ul>); CodeVolume_of_Range1ul_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1f__(ref List<Volume<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1f> item = default(Volume<Range1f>); CodeVolume_of_Range1f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Range1d__(ref List<Volume<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Range1d> item = default(Volume<Range1d>); CodeVolume_of_Range1d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2i__(ref List<Volume<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box2i> item = default(Volume<Box2i>); CodeVolume_of_Box2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2l__(ref List<Volume<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box2l> item = default(Volume<Box2l>); CodeVolume_of_Box2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2f__(ref List<Volume<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box2f> item = default(Volume<Box2f>); CodeVolume_of_Box2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box2d__(ref List<Volume<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box2d> item = default(Volume<Box2d>); CodeVolume_of_Box2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3i__(ref List<Volume<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box3i> item = default(Volume<Box3i>); CodeVolume_of_Box3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3l__(ref List<Volume<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box3l> item = default(Volume<Box3l>); CodeVolume_of_Box3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3f__(ref List<Volume<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box3f> item = default(Volume<Box3f>); CodeVolume_of_Box3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Box3d__(ref List<Volume<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Box3d> item = default(Volume<Box3d>); CodeVolume_of_Box3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Euclidean3f__(ref List<Volume<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Euclidean3f> item = default(Volume<Euclidean3f>); CodeVolume_of_Euclidean3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Euclidean3d__(ref List<Volume<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Euclidean3d> item = default(Volume<Euclidean3d>); CodeVolume_of_Euclidean3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot2f__(ref List<Volume<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Rot2f> item = default(Volume<Rot2f>); CodeVolume_of_Rot2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot2d__(ref List<Volume<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Rot2d> item = default(Volume<Rot2d>); CodeVolume_of_Rot2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot3f__(ref List<Volume<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Rot3f> item = default(Volume<Rot3f>); CodeVolume_of_Rot3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Rot3d__(ref List<Volume<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Rot3d> item = default(Volume<Rot3d>); CodeVolume_of_Rot3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Scale3f__(ref List<Volume<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Scale3f> item = default(Volume<Scale3f>); CodeVolume_of_Scale3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Scale3d__(ref List<Volume<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Scale3d> item = default(Volume<Scale3d>); CodeVolume_of_Scale3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Shift3f__(ref List<Volume<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Shift3f> item = default(Volume<Shift3f>); CodeVolume_of_Shift3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Shift3d__(ref List<Volume<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Shift3d> item = default(Volume<Shift3d>); CodeVolume_of_Shift3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo2f__(ref List<Volume<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Trafo2f> item = default(Volume<Trafo2f>); CodeVolume_of_Trafo2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo2d__(ref List<Volume<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Trafo2d> item = default(Volume<Trafo2d>); CodeVolume_of_Trafo2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo3f__(ref List<Volume<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Trafo3f> item = default(Volume<Trafo3f>); CodeVolume_of_Trafo3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Trafo3d__(ref List<Volume<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Trafo3d> item = default(Volume<Trafo3d>); CodeVolume_of_Trafo3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Bool__(ref List<Volume<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<bool> item = default(Volume<bool>); CodeVolume_of_Bool_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Char__(ref List<Volume<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<char> item = default(Volume<char>); CodeVolume_of_Char_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_String__(ref List<Volume<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<string> item = default(Volume<string>); CodeVolume_of_String_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Type__(ref List<Volume<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Type> item = default(Volume<Type>); CodeVolume_of_Type_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Guid__(ref List<Volume<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Guid> item = default(Volume<Guid>); CodeVolume_of_Guid_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Symbol__(ref List<Volume<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Symbol> item = default(Volume<Symbol>); CodeVolume_of_Symbol_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Circle2d__(ref List<Volume<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Circle2d> item = default(Volume<Circle2d>); CodeVolume_of_Circle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line2d__(ref List<Volume<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Line2d> item = default(Volume<Line2d>); CodeVolume_of_Line2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line3d__(ref List<Volume<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Line3d> item = default(Volume<Line3d>); CodeVolume_of_Line3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane2d__(ref List<Volume<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Plane2d> item = default(Volume<Plane2d>); CodeVolume_of_Plane2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane3d__(ref List<Volume<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Plane3d> item = default(Volume<Plane3d>); CodeVolume_of_Plane3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3d__(ref List<Volume<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<PlaneWithPoint3d> item = default(Volume<PlaneWithPoint3d>); CodeVolume_of_PlaneWithPoint3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad2d__(ref List<Volume<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Quad2d> item = default(Volume<Quad2d>); CodeVolume_of_Quad2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad3d__(ref List<Volume<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Quad3d> item = default(Volume<Quad3d>); CodeVolume_of_Quad3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray2d__(ref List<Volume<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Ray2d> item = default(Volume<Ray2d>); CodeVolume_of_Ray2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray3d__(ref List<Volume<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Ray3d> item = default(Volume<Ray3d>); CodeVolume_of_Ray3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Sphere3d__(ref List<Volume<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Sphere3d> item = default(Volume<Sphere3d>); CodeVolume_of_Sphere3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle2d__(ref List<Volume<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Triangle2d> item = default(Volume<Triangle2d>); CodeVolume_of_Triangle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle3d__(ref List<Volume<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Triangle3d> item = default(Volume<Triangle3d>); CodeVolume_of_Triangle3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Circle2f__(ref List<Volume<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Circle2f> item = default(Volume<Circle2f>); CodeVolume_of_Circle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line2f__(ref List<Volume<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Line2f> item = default(Volume<Line2f>); CodeVolume_of_Line2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Line3f__(ref List<Volume<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Line3f> item = default(Volume<Line3f>); CodeVolume_of_Line3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane2f__(ref List<Volume<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Plane2f> item = default(Volume<Plane2f>); CodeVolume_of_Plane2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Plane3f__(ref List<Volume<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Plane3f> item = default(Volume<Plane3f>); CodeVolume_of_Plane3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3f__(ref List<Volume<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<PlaneWithPoint3f> item = default(Volume<PlaneWithPoint3f>); CodeVolume_of_PlaneWithPoint3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad2f__(ref List<Volume<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Quad2f> item = default(Volume<Quad2f>); CodeVolume_of_Quad2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Quad3f__(ref List<Volume<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Quad3f> item = default(Volume<Quad3f>); CodeVolume_of_Quad3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray2f__(ref List<Volume<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Ray2f> item = default(Volume<Ray2f>); CodeVolume_of_Ray2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Ray3f__(ref List<Volume<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Ray3f> item = default(Volume<Ray3f>); CodeVolume_of_Ray3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Sphere3f__(ref List<Volume<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Sphere3f> item = default(Volume<Sphere3f>); CodeVolume_of_Sphere3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle2f__(ref List<Volume<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Triangle2f> item = default(Volume<Triangle2f>); CodeVolume_of_Triangle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Volume_of_Triangle3f__(ref List<Volume<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Volume<Triangle3f> item = default(Volume<Triangle3f>); CodeVolume_of_Triangle3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Byte__(ref List<Tensor<byte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<byte> item = default(Tensor<byte>); CodeTensor_of_Byte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_SByte__(ref List<Tensor<sbyte>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<sbyte> item = default(Tensor<sbyte>); CodeTensor_of_SByte_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Short__(ref List<Tensor<short>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<short> item = default(Tensor<short>); CodeTensor_of_Short_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_UShort__(ref List<Tensor<ushort>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<ushort> item = default(Tensor<ushort>); CodeTensor_of_UShort_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Int__(ref List<Tensor<int>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<int> item = default(Tensor<int>); CodeTensor_of_Int_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_UInt__(ref List<Tensor<uint>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<uint> item = default(Tensor<uint>); CodeTensor_of_UInt_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Long__(ref List<Tensor<long>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<long> item = default(Tensor<long>); CodeTensor_of_Long_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_ULong__(ref List<Tensor<ulong>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<ulong> item = default(Tensor<ulong>); CodeTensor_of_ULong_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Float__(ref List<Tensor<float>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<float> item = default(Tensor<float>); CodeTensor_of_Float_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Double__(ref List<Tensor<double>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<double> item = default(Tensor<double>); CodeTensor_of_Double_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Fraction__(ref List<Tensor<Fraction>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Fraction> item = default(Tensor<Fraction>); CodeTensor_of_Fraction_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2i__(ref List<Tensor<V2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V2i> item = default(Tensor<V2i>); CodeTensor_of_V2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2l__(ref List<Tensor<V2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V2l> item = default(Tensor<V2l>); CodeTensor_of_V2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2f__(ref List<Tensor<V2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V2f> item = default(Tensor<V2f>); CodeTensor_of_V2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V2d__(ref List<Tensor<V2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V2d> item = default(Tensor<V2d>); CodeTensor_of_V2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3i__(ref List<Tensor<V3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V3i> item = default(Tensor<V3i>); CodeTensor_of_V3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3l__(ref List<Tensor<V3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V3l> item = default(Tensor<V3l>); CodeTensor_of_V3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3f__(ref List<Tensor<V3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V3f> item = default(Tensor<V3f>); CodeTensor_of_V3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V3d__(ref List<Tensor<V3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V3d> item = default(Tensor<V3d>); CodeTensor_of_V3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4i__(ref List<Tensor<V4i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V4i> item = default(Tensor<V4i>); CodeTensor_of_V4i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4l__(ref List<Tensor<V4l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V4l> item = default(Tensor<V4l>); CodeTensor_of_V4l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4f__(ref List<Tensor<V4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V4f> item = default(Tensor<V4f>); CodeTensor_of_V4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_V4d__(ref List<Tensor<V4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<V4d> item = default(Tensor<V4d>); CodeTensor_of_V4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22i__(ref List<Tensor<M22i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M22i> item = default(Tensor<M22i>); CodeTensor_of_M22i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22l__(ref List<Tensor<M22l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M22l> item = default(Tensor<M22l>); CodeTensor_of_M22l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22f__(ref List<Tensor<M22f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M22f> item = default(Tensor<M22f>); CodeTensor_of_M22f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M22d__(ref List<Tensor<M22d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M22d> item = default(Tensor<M22d>); CodeTensor_of_M22d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23i__(ref List<Tensor<M23i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M23i> item = default(Tensor<M23i>); CodeTensor_of_M23i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23l__(ref List<Tensor<M23l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M23l> item = default(Tensor<M23l>); CodeTensor_of_M23l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23f__(ref List<Tensor<M23f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M23f> item = default(Tensor<M23f>); CodeTensor_of_M23f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M23d__(ref List<Tensor<M23d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M23d> item = default(Tensor<M23d>); CodeTensor_of_M23d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33i__(ref List<Tensor<M33i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M33i> item = default(Tensor<M33i>); CodeTensor_of_M33i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33l__(ref List<Tensor<M33l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M33l> item = default(Tensor<M33l>); CodeTensor_of_M33l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33f__(ref List<Tensor<M33f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M33f> item = default(Tensor<M33f>); CodeTensor_of_M33f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M33d__(ref List<Tensor<M33d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M33d> item = default(Tensor<M33d>); CodeTensor_of_M33d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34i__(ref List<Tensor<M34i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M34i> item = default(Tensor<M34i>); CodeTensor_of_M34i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34l__(ref List<Tensor<M34l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M34l> item = default(Tensor<M34l>); CodeTensor_of_M34l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34f__(ref List<Tensor<M34f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M34f> item = default(Tensor<M34f>); CodeTensor_of_M34f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M34d__(ref List<Tensor<M34d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M34d> item = default(Tensor<M34d>); CodeTensor_of_M34d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44i__(ref List<Tensor<M44i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M44i> item = default(Tensor<M44i>); CodeTensor_of_M44i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44l__(ref List<Tensor<M44l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M44l> item = default(Tensor<M44l>); CodeTensor_of_M44l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44f__(ref List<Tensor<M44f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M44f> item = default(Tensor<M44f>); CodeTensor_of_M44f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_M44d__(ref List<Tensor<M44d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<M44d> item = default(Tensor<M44d>); CodeTensor_of_M44d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3b__(ref List<Tensor<C3b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3b> item = default(Tensor<C3b>); CodeTensor_of_C3b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3us__(ref List<Tensor<C3us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3us> item = default(Tensor<C3us>); CodeTensor_of_C3us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3ui__(ref List<Tensor<C3ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3ui> item = default(Tensor<C3ui>); CodeTensor_of_C3ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3f__(ref List<Tensor<C3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3f> item = default(Tensor<C3f>); CodeTensor_of_C3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C3d__(ref List<Tensor<C3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C3d> item = default(Tensor<C3d>); CodeTensor_of_C3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4b__(ref List<Tensor<C4b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4b> item = default(Tensor<C4b>); CodeTensor_of_C4b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4us__(ref List<Tensor<C4us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4us> item = default(Tensor<C4us>); CodeTensor_of_C4us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4ui__(ref List<Tensor<C4ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4ui> item = default(Tensor<C4ui>); CodeTensor_of_C4ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4f__(ref List<Tensor<C4f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4f> item = default(Tensor<C4f>); CodeTensor_of_C4f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_C4d__(ref List<Tensor<C4d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<C4d> item = default(Tensor<C4d>); CodeTensor_of_C4d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1b__(ref List<Tensor<Range1b>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1b> item = default(Tensor<Range1b>); CodeTensor_of_Range1b_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1sb__(ref List<Tensor<Range1sb>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1sb> item = default(Tensor<Range1sb>); CodeTensor_of_Range1sb_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1s__(ref List<Tensor<Range1s>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1s> item = default(Tensor<Range1s>); CodeTensor_of_Range1s_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1us__(ref List<Tensor<Range1us>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1us> item = default(Tensor<Range1us>); CodeTensor_of_Range1us_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1i__(ref List<Tensor<Range1i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1i> item = default(Tensor<Range1i>); CodeTensor_of_Range1i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1ui__(ref List<Tensor<Range1ui>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1ui> item = default(Tensor<Range1ui>); CodeTensor_of_Range1ui_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1l__(ref List<Tensor<Range1l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1l> item = default(Tensor<Range1l>); CodeTensor_of_Range1l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1ul__(ref List<Tensor<Range1ul>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1ul> item = default(Tensor<Range1ul>); CodeTensor_of_Range1ul_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1f__(ref List<Tensor<Range1f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1f> item = default(Tensor<Range1f>); CodeTensor_of_Range1f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Range1d__(ref List<Tensor<Range1d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Range1d> item = default(Tensor<Range1d>); CodeTensor_of_Range1d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2i__(ref List<Tensor<Box2i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box2i> item = default(Tensor<Box2i>); CodeTensor_of_Box2i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2l__(ref List<Tensor<Box2l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box2l> item = default(Tensor<Box2l>); CodeTensor_of_Box2l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2f__(ref List<Tensor<Box2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box2f> item = default(Tensor<Box2f>); CodeTensor_of_Box2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box2d__(ref List<Tensor<Box2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box2d> item = default(Tensor<Box2d>); CodeTensor_of_Box2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3i__(ref List<Tensor<Box3i>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box3i> item = default(Tensor<Box3i>); CodeTensor_of_Box3i_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3l__(ref List<Tensor<Box3l>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box3l> item = default(Tensor<Box3l>); CodeTensor_of_Box3l_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3f__(ref List<Tensor<Box3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box3f> item = default(Tensor<Box3f>); CodeTensor_of_Box3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Box3d__(ref List<Tensor<Box3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Box3d> item = default(Tensor<Box3d>); CodeTensor_of_Box3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Euclidean3f__(ref List<Tensor<Euclidean3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Euclidean3f> item = default(Tensor<Euclidean3f>); CodeTensor_of_Euclidean3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Euclidean3d__(ref List<Tensor<Euclidean3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Euclidean3d> item = default(Tensor<Euclidean3d>); CodeTensor_of_Euclidean3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot2f__(ref List<Tensor<Rot2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Rot2f> item = default(Tensor<Rot2f>); CodeTensor_of_Rot2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot2d__(ref List<Tensor<Rot2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Rot2d> item = default(Tensor<Rot2d>); CodeTensor_of_Rot2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot3f__(ref List<Tensor<Rot3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Rot3f> item = default(Tensor<Rot3f>); CodeTensor_of_Rot3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Rot3d__(ref List<Tensor<Rot3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Rot3d> item = default(Tensor<Rot3d>); CodeTensor_of_Rot3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Scale3f__(ref List<Tensor<Scale3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Scale3f> item = default(Tensor<Scale3f>); CodeTensor_of_Scale3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Scale3d__(ref List<Tensor<Scale3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Scale3d> item = default(Tensor<Scale3d>); CodeTensor_of_Scale3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Shift3f__(ref List<Tensor<Shift3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Shift3f> item = default(Tensor<Shift3f>); CodeTensor_of_Shift3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Shift3d__(ref List<Tensor<Shift3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Shift3d> item = default(Tensor<Shift3d>); CodeTensor_of_Shift3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo2f__(ref List<Tensor<Trafo2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Trafo2f> item = default(Tensor<Trafo2f>); CodeTensor_of_Trafo2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo2d__(ref List<Tensor<Trafo2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Trafo2d> item = default(Tensor<Trafo2d>); CodeTensor_of_Trafo2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo3f__(ref List<Tensor<Trafo3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Trafo3f> item = default(Tensor<Trafo3f>); CodeTensor_of_Trafo3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Trafo3d__(ref List<Tensor<Trafo3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Trafo3d> item = default(Tensor<Trafo3d>); CodeTensor_of_Trafo3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Bool__(ref List<Tensor<bool>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<bool> item = default(Tensor<bool>); CodeTensor_of_Bool_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Char__(ref List<Tensor<char>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<char> item = default(Tensor<char>); CodeTensor_of_Char_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_String__(ref List<Tensor<string>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<string> item = default(Tensor<string>); CodeTensor_of_String_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Type__(ref List<Tensor<Type>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Type> item = default(Tensor<Type>); CodeTensor_of_Type_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Guid__(ref List<Tensor<Guid>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Guid> item = default(Tensor<Guid>); CodeTensor_of_Guid_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Symbol__(ref List<Tensor<Symbol>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Symbol> item = default(Tensor<Symbol>); CodeTensor_of_Symbol_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Circle2d__(ref List<Tensor<Circle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Circle2d> item = default(Tensor<Circle2d>); CodeTensor_of_Circle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line2d__(ref List<Tensor<Line2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Line2d> item = default(Tensor<Line2d>); CodeTensor_of_Line2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line3d__(ref List<Tensor<Line3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Line3d> item = default(Tensor<Line3d>); CodeTensor_of_Line3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane2d__(ref List<Tensor<Plane2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Plane2d> item = default(Tensor<Plane2d>); CodeTensor_of_Plane2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane3d__(ref List<Tensor<Plane3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Plane3d> item = default(Tensor<Plane3d>); CodeTensor_of_Plane3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3d__(ref List<Tensor<PlaneWithPoint3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<PlaneWithPoint3d> item = default(Tensor<PlaneWithPoint3d>); CodeTensor_of_PlaneWithPoint3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad2d__(ref List<Tensor<Quad2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Quad2d> item = default(Tensor<Quad2d>); CodeTensor_of_Quad2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad3d__(ref List<Tensor<Quad3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Quad3d> item = default(Tensor<Quad3d>); CodeTensor_of_Quad3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray2d__(ref List<Tensor<Ray2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Ray2d> item = default(Tensor<Ray2d>); CodeTensor_of_Ray2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray3d__(ref List<Tensor<Ray3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Ray3d> item = default(Tensor<Ray3d>); CodeTensor_of_Ray3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Sphere3d__(ref List<Tensor<Sphere3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Sphere3d> item = default(Tensor<Sphere3d>); CodeTensor_of_Sphere3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle2d__(ref List<Tensor<Triangle2d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Triangle2d> item = default(Tensor<Triangle2d>); CodeTensor_of_Triangle2d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle3d__(ref List<Tensor<Triangle3d>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Triangle3d> item = default(Tensor<Triangle3d>); CodeTensor_of_Triangle3d_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Circle2f__(ref List<Tensor<Circle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Circle2f> item = default(Tensor<Circle2f>); CodeTensor_of_Circle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line2f__(ref List<Tensor<Line2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Line2f> item = default(Tensor<Line2f>); CodeTensor_of_Line2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Line3f__(ref List<Tensor<Line3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Line3f> item = default(Tensor<Line3f>); CodeTensor_of_Line3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane2f__(ref List<Tensor<Plane2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Plane2f> item = default(Tensor<Plane2f>); CodeTensor_of_Plane2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Plane3f__(ref List<Tensor<Plane3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Plane3f> item = default(Tensor<Plane3f>); CodeTensor_of_Plane3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3f__(ref List<Tensor<PlaneWithPoint3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<PlaneWithPoint3f> item = default(Tensor<PlaneWithPoint3f>); CodeTensor_of_PlaneWithPoint3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad2f__(ref List<Tensor<Quad2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Quad2f> item = default(Tensor<Quad2f>); CodeTensor_of_Quad2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Quad3f__(ref List<Tensor<Quad3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Quad3f> item = default(Tensor<Quad3f>); CodeTensor_of_Quad3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray2f__(ref List<Tensor<Ray2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Ray2f> item = default(Tensor<Ray2f>); CodeTensor_of_Ray2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Ray3f__(ref List<Tensor<Ray3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Ray3f> item = default(Tensor<Ray3f>); CodeTensor_of_Ray3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Sphere3f__(ref List<Tensor<Sphere3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Sphere3f> item = default(Tensor<Sphere3f>); CodeTensor_of_Sphere3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle2f__(ref List<Tensor<Triangle2f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Triangle2f> item = default(Tensor<Triangle2f>); CodeTensor_of_Triangle2f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        public void CodeList_of_Tensor_of_Triangle3f__(ref List<Tensor<Triangle3f>> value)\r\n        {\r\n            int count = CodeCount(ref value);\r\n            if (count < 1) return;\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                Tensor<Triangle3f> item = default(Tensor<Triangle3f>); CodeTensor_of_Triangle3f_(ref item); value[i] = item;\r\n                m_state.Advance();\r\n            }\r\n        }\r\n\r\n        #endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Aardvark.Base.IO/XmlReadingCoder_template.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Coder\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var directlyCodeableTypes = Meta.DirectlyCodeableTypes.Map(t =>t.Name);\n    //# var geometryTypes = Meta.GeometryTypes.Map(t => t.Name);\n    //# var specialSimpleTypes = new[] { \"bool\", \"char\", \"string\", \"Type\", \"Guid\", \"Symbol\" };\n    //# {\n    //# var structTypes = new List<string>();\n    //# var tensorTypes = new List<string>();\n    public partial class NewXmlReadingCoder\n    {\n        #region Vectors\n\n        //# foreach (var t in Meta.VecTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Matrices\n\n        //# foreach (var t in Meta.MatTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Ranges and Boxes\n\n        //# foreach (var t in Meta.RangeAndBoxTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Geometry Types\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"Double\" : \"Float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        public void CodeCircle2__tc__(ref Circle2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeLine2__tc__(ref Line2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeLine3__tc__(ref Line3__tc__ v) { throw new NotImplementedException(); }\n        public void CodePlane2__tc__(ref Plane2__tc__ v) { throw new NotImplementedException(); }\n        public void CodePlane3__tc__(ref Plane3__tc__ v) { throw new NotImplementedException(); }\n        public void CodePlaneWithPoint3__tc__(ref PlaneWithPoint3__tc__ v) { throw new NotImplementedException(); }\n        public void CodeQuad2__tc__(ref Quad2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeQuad3__tc__(ref Quad3__tc__ v) { throw new NotImplementedException(); }\n        public void CodeRay2__tc__(ref Ray2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeRay3__tc__(ref Ray3__tc__ v) { throw new NotImplementedException(); }\n        public void CodeSphere3__tc__(ref Sphere3__tc__ v) { throw new NotImplementedException(); }\n        public void CodeTriangle2__tc__(ref Triangle2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeTriangle3__tc__(ref Triangle3__tc__ v) { throw new NotImplementedException(); }\n\n        //# }\n        #endregion\n\n        #region Colors\n\n        //# foreach (var t in Meta.ColorTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Trafos\n\n        //# foreach (var t in Meta.TrafoTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Tensors\n\n        //# foreach (var t in geometryTypes) structTypes.Add(t);\n        //# var simpleTypes = directlyCodeableTypes.Concat(specialSimpleTypes).Concat(geometryTypes);\n        //# var genericTensorTypes = new[] { \"Vector\", \"Matrix\", \"Volume\", \"Tensor\" };\n        //# var genericTensorSizes = new[] { \"long\", \"V2l\", \"V3l\", \"long[]\" };\n        //# genericTensorTypes.ForEach((tt, ti) => {\n        //#     var ts = genericTensorSizes[ti];\n        //#     simpleTypes.ForEach((t, i) => {\n        //#         var type = tt + \"<\" + t + \">\";\n        //#         tensorTypes.Add(type);\n        //# var name = Meta.GetXmlTypeName(type);\n        public void Code__name__(ref __type__ value)\n        {\n            throw new NotImplementedException();\n        }\n\n        //#     });\n        //# });\n        #endregion\n\n        #region Arrays\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] value)\n        {\n            throw new NotImplementedException();\n        }\n\n        //# });\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[,]\");\n        public void Code__name2d__(ref __t__[,] value) { throw new NotImplementedException(); }\n        //# var name3d = Meta.GetXmlTypeName(t + \"[,,]\");\n        public void Code__name3d__(ref __t__[, ,] value) { throw new NotImplementedException(); }\n\n        //# });\n        #endregion\n\n        #region Jagged Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[][]\");\n        public void Code__name2d__(ref __t__[][] value) { throw new NotImplementedException(); }\n        //# var name3d = Meta.GetXmlTypeName(t + \"[][][]\");\n        public void Code__name3d__(ref __t__[][][] value) { throw new NotImplementedException(); }\n\n        //# });\n        #endregion\n\n        #region Lists\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        //# });\n        #endregion\n\n        #region Arrays of Tensors\n\n        //# tensorTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] value)\n        {\n            throw new NotImplementedException();\n        }\n\n        //# });\n        #endregion\n\n        #region Lists of Tensors\n\n        //# tensorTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        //# });\n        #endregion\n    }\n\n    //# } {\n    //# var structTypes = new List<string>();\n    //# var tensorTypes = new List<string>();\n    public partial class XmlReadingCoder\n    {\n        #region Vectors\n\n        //# foreach (var t in Meta.VecTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { v = __t.Name__.Parse(CurrentValue()); }\n        //# }\n\n        #endregion\n\n        #region Matrices\n\n        //# foreach (var t in Meta.MatTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { v = __t.Name__.Parse(CurrentValue()); }\n        //# }\n\n        #endregion\n\n        #region Ranges and Boxes\n\n        //# foreach (var t in Meta.RangeAndBoxTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { v = __t.Name__.Parse(CurrentValue()); }\n        //# }\n\n        #endregion\n\n        #region Geometry Types\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"Double\" : \"Float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        public void CodeCircle2__tc__(ref Circle2__tc__ v) { v = Circle2__tc__.Parse(CurrentValue()); }\n        public void CodeLine2__tc__(ref Line2__tc__ v) { v = Line2__tc__.Parse(CurrentValue()); }\n        public void CodeLine3__tc__(ref Line3__tc__ v) { v = Line3__tc__.Parse(CurrentValue()); }\n        public void CodePlane2__tc__(ref Plane2__tc__ v) { v = Plane2__tc__.Parse(CurrentValue()); }\n        public void CodePlane3__tc__(ref Plane3__tc__ v) { v = Plane3__tc__.Parse(CurrentValue()); }\n        public void CodePlaneWithPoint3__tc__(ref PlaneWithPoint3__tc__ v) { v = PlaneWithPoint3__tc__.Parse(CurrentValue()); }\n        public void CodeQuad2__tc__(ref Quad2__tc__ v) { v = Quad2__tc__.Parse(CurrentValue()); }\n        public void CodeQuad3__tc__(ref Quad3__tc__ v) { v = Quad3__tc__.Parse(CurrentValue()); }\n        public void CodeRay2__tc__(ref Ray2__tc__ v) { v = Ray2__tc__.Parse(CurrentValue()); }\n        public void CodeRay3__tc__(ref Ray3__tc__ v) { v = Ray3__tc__.Parse(CurrentValue()); }\n        public void CodeSphere3__tc__(ref Sphere3__tc__ v) { v = Sphere3__tc__.Parse(CurrentValue()); }\n        public void CodeTriangle2__tc__(ref Triangle2__tc__ v) { v = Triangle2__tc__.Parse(CurrentValue()); }\n        public void CodeTriangle3__tc__(ref Triangle3__tc__ v) { v = Triangle3__tc__.Parse(CurrentValue()); }\n\n        //# }\n        #endregion\n\n        #region Colors\n\n        //# foreach (var t in Meta.ColorTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { v = __t.Name__.Parse(CurrentValue()); }\n        //# }\n\n        #endregion\n\n        #region Trafos\n\n        //# foreach (var t in Meta.TrafoTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { v = __t.Name__.Parse(CurrentValue()); }\n        //# }\n\n        #endregion\n\n        #region Tensors\n\n        //# foreach (var t in geometryTypes) structTypes.Add(t);\n        //# var simpleTypes = directlyCodeableTypes.Concat(specialSimpleTypes).Concat(geometryTypes);\n        //# var genericTensorTypes = new[] { \"Vector\", \"Matrix\", \"Volume\", \"Tensor\" };\n        //# var genericTensorSizes = new[] { \"long\", \"V2l\", \"V3l\", \"long[]\" };\n        //# genericTensorTypes.ForEach((tt, ti) => {\n        //#     var ts = genericTensorSizes[ti]; var tsn = Meta.GetXmlTypeName(ts);\n        //#     simpleTypes.ForEach((t, i) => {\n        //#         var type = tt + \"<\" + t + \">\";\n        //#         tensorTypes.Add(type);\n        //# var dname = Meta.GetXmlTypeName(t + \"[]\");\n        //# var name = Meta.GetXmlTypeName(type);\n        public void Code__name__(ref __type__ value)\n        {\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            __t__[] data = null; Code__dname__(ref data);\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            long origin = 0L; CodeLong(ref origin);\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            __ts__ size = default(__ts__); Code__tsn__(ref size);\n\n            m_state = m_stateStack.Pop();\n            m_state.Advance();\n            m_stateStack.Push(m_state);\n            m_state.Enumerator = m_state.Element.Elements().GetEnumerator();\n            m_state.Element = m_state.Enumerator.Current;\n\n            __ts__ delta = default(__ts__); Code__tsn__(ref delta);\n\n            m_state = m_stateStack.Pop();\n            m_state = m_stateStack.Pop();\n\n            value = new __type__(data, origin, size, delta);\n        }\n\n        //#     });\n        //# });\n        #endregion\n\n        #region Arrays\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] value)\n        {\n            CodeArray(ref value, s_nestedBracketSplitter, s => __t__.Parse(s));\n        }\n\n        //# });\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[,]\");\n        public void Code__name2d__(ref __t__[,] value) { throw new NotImplementedException(); }\n        //# var name3d = Meta.GetXmlTypeName(t + \"[,,]\");\n        public void Code__name3d__(ref __t__[, ,] value) { throw new NotImplementedException(); }\n\n        //# });\n        #endregion\n\n        #region Jagged Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[][]\");\n        public void Code__name2d__(ref __t__[][] value) { throw new NotImplementedException(); }\n        //# var name3d = Meta.GetXmlTypeName(t + \"[][][]\");\n        public void Code__name3d__(ref __t__[][][] value) { throw new NotImplementedException(); }\n\n        //# });\n        #endregion\n\n        #region Lists\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> value)\n        {\n            CodeList(ref value, s_nestedBracketSplitter, s => __t__.Parse(s));\n        }\n\n        //# });\n        #endregion\n\n        #region Arrays of Tensors\n\n        //# tensorTypes.ForEach(t => {\n        //# var ename = Meta.GetXmlTypeName(t);\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                __t__ item = default(__t__); Code__ename__(ref item); value[i] = item;\n                m_state.Advance();\n            }\n        }\n\n        //# });\n        #endregion\n\n        #region Lists of Tensors\n\n        //# tensorTypes.ForEach(t => {\n        //# var ename = Meta.GetXmlTypeName(t);\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                __t__ item = default(__t__); Code__ename__(ref item); value[i] = item;\n                m_state.Advance();\n            }\n        }\n\n        //# });\n        #endregion\n    }\n    //# }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/XmlWritingCoder.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.IO;\nusing System.Text;\nusing System.Xml.Linq;\n\nnamespace Aardvark.Base.Coder\n{\n    public partial class NewXmlWritingCoder\n        : BaseWritingCoder, IWritingCoder, IDisposable\n    {\n        public Stack<XmlItem> m_itemStack;\n        private readonly XmlItem m_item;\n        private readonly Stream m_stream;\n        readonly bool m_disposeStream;\n        private string m_fileName;\n        // bool m_writeRefNumbers;\n\n        #region Constructors\n\n        public NewXmlWritingCoder(XmlDoc doc) : base()\n        {\n            m_itemStack = new Stack<XmlItem>();\n            m_item = new XmlItem(AardvarkSymbol);\n            m_stream = null;\n            m_fileName = null;\n            // m_writeRefNumbers = true;\n            m_disposeStream = false;\n        }\n\n        public NewXmlWritingCoder(Stream stream)\n            : this(new XmlDoc())\n        {\n            m_stream = stream;\n        }\n\n        public NewXmlWritingCoder(string fileName)\n            : this(File.Open(fileName, FileMode.Create))\n        {\n            m_fileName = fileName;\n            m_disposeStream = true;\n        }\n\n        #endregion\n\n        #region ICoder Members\n\n        public int CoderVersion { get { return c_coderVersion; } }\n\n        public int StreamVersion { get { throw new NotImplementedException(); } }\n\n        public int MemoryVersion { get { throw new NotImplementedException(); } }\n\n        public string FileName\n        {\n            get { return m_fileName; }\n            set { m_fileName = value; }\n        }\n\n        public void Code(ref object obj)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeFields(Type type, int version, IFieldCodeable obj)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeFields(Type type, ITypedMap obj)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeT<T>(ref T obj)\n        {\n            throw new NotImplementedException();\n        }\n\n        private bool CodeNull<T>(ref T value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public int CodeCount<T>(ref T value, Func<T, int> counter) where T : class\n        {\n            throw new NotImplementedException();\n        }\n\n        private int CodeCount<T>(ref T[] array)\n        {\n            throw new NotImplementedException();\n        }\n\n        private int CodeCount<T>(ref List<T> list)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeTArray<T>(ref T[] value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_T_<T>(ref List<T> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeHashSet_of_T_<T>(ref HashSet<T> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref object o)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref Array value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IList value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IDictionary dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref ICountableDict dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref ICountableDictSet dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayVector value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayMatrix value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayVolume value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayTensor4 value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayTensorN value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeHashSet(Type t, ref object o)\n        {\n            throw new NotImplementedException(\"only possible whith a non-generic ISet interface)\");\n        }\n\n        public void CodeEnum(Type t, ref object value)\n        {\n            throw new NotImplementedException();\n        }\n\n        #endregion\n\n        #region Code Primitives\n\n        public void CodeBool(ref bool v) { throw new NotImplementedException(); }\n        public void CodeByte(ref byte v) { throw new NotImplementedException(); }\n        public void CodeSByte(ref sbyte v) { throw new NotImplementedException(); }\n        public void CodeShort(ref short v) { throw new NotImplementedException(); }\n        public void CodeUShort(ref ushort v) { throw new NotImplementedException(); }\n        public void CodeInt(ref int v) { throw new NotImplementedException(); }\n        public void CodeUInt(ref uint v) { throw new NotImplementedException(); }\n        public void CodeLong(ref long v) { throw new NotImplementedException(); }\n        public void CodeULong(ref ulong v) { throw new NotImplementedException(); }\n\n        public void CodeFloat(ref float value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeDouble(ref double value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeChar(ref char v) { throw new NotImplementedException(); }\n        public void CodeString(ref string value) { throw new NotImplementedException(); }\n\n        public void CodeType(ref Type value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeGuid(ref Guid v) { throw new NotImplementedException(); }\n\n        public void CodeSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodeGuidSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodePositiveSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodeIntSet(ref IntSet set) { throw new NotImplementedException(); }\n\n        public void CodeSymbolSet(ref SymbolSet set) { throw new NotImplementedException(); }\n\n        public void CodeFraction(ref Fraction v) { throw new NotImplementedException(); }\n\n        public void CodeStructArray<T>(ref T[] a) where T : struct\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeStructList<T>(ref List<T> l) where T : struct\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeBoolArray(ref bool[] value) { throw new NotImplementedException(); }\n        public void CodeByteArray(ref byte[] value) { throw new NotImplementedException(); }\n        public void CodeSByteArray(ref sbyte[] value) { throw new NotImplementedException(); }\n        public void CodeShortArray(ref short[] value) { throw new NotImplementedException(); }\n        public void CodeUShortArray(ref ushort[] value) { throw new NotImplementedException(); }\n        public void CodeIntArray(ref int[] value) { throw new NotImplementedException(); }\n        public void CodeUIntArray(ref uint[] value) { throw new NotImplementedException(); }\n        public void CodeLongArray(ref long[] value) { throw new NotImplementedException(); }\n        public void CodeULongArray(ref ulong[] value) { throw new NotImplementedException(); }\n        public void CodeFloatArray(ref float[] value) { throw new NotImplementedException(); }\n        public void CodeDoubleArray(ref double[] value) { throw new NotImplementedException(); }\n\n        public void CodeCharArray(ref char[] value) { throw new NotImplementedException(); }\n        public void CodeStringArray(ref string[] value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeTypeArray(ref Type[] value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeGuidArray(ref Guid[] v) { throw new NotImplementedException(); }\n\n        public void CodeSymbolArray(ref Symbol[] v) { throw new NotImplementedException(); }\n\n        public void CodeFractionArray(ref Fraction[] v) { throw new NotImplementedException(); }\n\n        public void CodeList_of_Bool_(ref List<bool> value) { throw new NotImplementedException(); }\n        public void CodeList_of_Byte_(ref List<byte> value) { throw new NotImplementedException(); }\n        public void CodeList_of_SByte_(ref List<sbyte> value) { throw new NotImplementedException(); }\n        public void CodeList_of_Short_(ref List<short> value) { throw new NotImplementedException(); }\n        public void CodeList_of_UShort_(ref List<ushort> value) { throw new NotImplementedException(); }\n        public void CodeList_of_Int_(ref List<int> value) { throw new NotImplementedException(); }\n        public void CodeList_of_UInt_(ref List<uint> value) { throw new NotImplementedException(); }\n        public void CodeList_of_Long_(ref List<long> value) { throw new NotImplementedException(); }\n        public void CodeList_of_ULong_(ref List<ulong> value) { throw new NotImplementedException(); }\n        public void CodeList_of_Float_(ref List<float> value) { throw new NotImplementedException(); }\n        public void CodeList_of_Double_(ref List<double> value) { throw new NotImplementedException(); }\n\n        public void CodeList_of_Char_(ref List<char> value) { throw new NotImplementedException(); }\n        public void CodeList_of_String_(ref List<string> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_Type_(ref List<Type> value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeList_of_Fraction_(ref List<Fraction> v) { throw new NotImplementedException(); }\n        public void CodeList_of_Symbol_(ref List<Symbol> v) { throw new NotImplementedException(); }\n        public void CodeList_of_Guid_(ref List<Guid> v) { throw new NotImplementedException(); }\n\n        #endregion\n\n        #region IDisposable Members\n\n        public void Dispose()\n        {\n            if (m_stream == null)\n                return;\n\n            var writer = new StreamWriter(m_stream, Encoding.UTF8);\n            m_item.WriteTo(writer);\n\n            if (m_disposeStream)\n                writer.Close();\n            else\n                writer.Flush();\n        }\n\n        #endregion\n    }\n\n    public partial class XmlWritingCoder\n        : BaseWritingCoder, IWritingCoder, IDisposable\n    {\n        private readonly Stack<XElement> m_elementStack;\n        protected XElement m_element;\n        private readonly XElement m_container;\n        private readonly Stream m_stream;\n        private string m_fileName;\n        bool m_writeRefNumbers;\n        readonly bool m_disposeStream = false;\n\n        #region Constructors\n\n        public XmlWritingCoder(XElement container) : base()\n        {\n            m_container = container;\n            m_elementStack = new Stack<XElement>();\n            m_element = container;\n            m_stream = null;\n            m_fileName = null;\n            m_writeRefNumbers = true;\n            m_container.Add(new XAttribute(\"version\", c_coderVersion));\n        }\n\n        public XmlWritingCoder(Stream stream)\n            : this(new XElement(\"Aardvark\"))\n        {\n            m_stream = stream;\n        }\n\n        public XmlWritingCoder(string fileName)\n            : this(File.Open(fileName, FileMode.Create))\n        {\n            m_fileName = fileName;\n            m_disposeStream = true;\n        }\n\n        #endregion\n\n        #region Properties\n\n        public XElement ContainerElement\n        {\n            set { m_element = value; }\n        }\n\n        /// <summary>\n        /// By setting this debugging option to true all objects are written\n        /// to the Xml file with their reference numbers as additional\n        /// Xml attribute.\n        /// </summary>\n        public bool WriteRefNumbers\n        {\n            get { return m_writeRefNumbers; }\n            set { m_writeRefNumbers = value; }\n        }\n\n        #endregion\n\n        #region Static Convenience Methods\n\n        public static void WriteObject(string fileName, object obj)\n        {\n            using (var coder = new XmlWritingCoder(fileName))\n                coder.Code(ref obj);\n        }\n\n        public static void WriteObject(Stream stream, object obj)\n        {\n            using (var coder = new XmlWritingCoder(stream))\n                coder.Code(ref obj);\n        }\n\n        #endregion\n\n        #region Private Convenience Methods\n\n        private void AddValue(object value)\n        {\n            m_element.Add(value);\n        }\n\n        #endregion\n\n        #region ICoder Members\n\n        public int CoderVersion { get { return c_coderVersion; } }\n\n        public int StreamVersion { get { return m_version; } }\n\n        public int MemoryVersion { get { return m_version; } }\n\n        public string FileName\n        {\n            get { return m_fileName; }\n            set { m_fileName = value; }\n        }\n\n        private bool HandleRef(ref object obj)\n        {\n            if (m_doRefs)\n            {\n                int index;\n                if (m_refs.TryGetValue(obj, out index))\n                {\n                    TypeInfo typeInfo;\n                    if (TryGetTypeInfo(typeof(TypeCoder.Reference), out typeInfo))\n                    {\n                        XElement refElement = new XElement(typeInfo.XmlName);\n                        refElement.Add(new XAttribute(\"num\", m_refs[obj]));\n                        AddValue(refElement);\n                        return true;\n                    }\n                    else\n                        throw new Exception(\n                                \"cannot encode multiply referenced object \"\n                                + \"- change by configuring coder with \"\n                                + \"\\\"coder.Add(TypeCoder.Default.Reference);\\\"\");\n                }\n\n                m_refs[obj] = m_refs.Count;\n            }\n            return false;\n        }\n\n        public void Code(ref object obj)\n        {\n            TypeInfo typeInfo;\n            if (obj == null)\n            {\n                if (TryGetTypeInfo(typeof(TypeCoder.Null), out typeInfo)\n                    && ((typeInfo.Options & TypeInfo.Option.Active) != 0))\n                {\n                    AddValue(new XElement(typeInfo.XmlName));\n                    return;\n                }\n                else\n                {\n                    throw new Exception(\"cannot encode null object \"\n                            + \"- change by configuring coder with \"\n                            + \"\\\"coder.Add(TypeCoder.Default.Null);\\\"\");\n                }\n            }\n\n            Type type = obj.GetType();\n\n            if (!TypeCoder.IsDirectlyCodeable(type))\n                if (HandleRef(ref obj)) return;\n\n            string elementName;\n            string typeName = null;\n            TypeInfo.Option typeOptions = TypeInfo.Option.Size\n                                            | TypeInfo.Option.Version;\n\n            if (TryGetTypeInfo(type, out typeInfo))\n            {\n                elementName = typeInfo.XmlName;\n                typeOptions = typeInfo.Options;\n            }\n            else\n            {\n                typeName = type.AssemblyQualifiedName;\n                elementName = \"object\";\n                if ((m_debugMode & CoderDebugMode.ReportQualifiedNames) != 0)\n                    Report.Line(\"qualified name \\\"{0}\\\"\", typeName);\n            }\n\n            XElement element = new XElement(elementName);\n            if (typeName != null)\n                element.Add(new XAttribute(\"type\", typeName));\n\n            if ((typeOptions & TypeInfo.Option.Version) != 0)\n            {\n                m_versionStack.Push(m_version);\n                m_version = typeInfo != null ? typeInfo.Version : 0;\n                element.Add(new XAttribute(\"version\", m_version));\n            }\n\n            if (!TypeCoder.IsDirectlyCodeable(type))\n                if (m_doRefs && m_writeRefNumbers)\n                    element.Add(new XAttribute(\"num\", m_refs.Count - 1));\n\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            #region code fields based on supported interface\n\n            if (!TypeCoder.WritePrimitive(this, type, ref obj))\n            {\n                m_typeInfoStack.Push(typeInfo);\n\n                var fcobj = obj as IFieldCodeable;\n                if (fcobj != null)\n                {\n                    CodeFields(type, m_version, fcobj);\n                    var tmobj = obj as ITypedMap;\n                    if (tmobj != null) CodeFields(type, tmobj);\n                }\n                else\n                {\n                    throw new Exception(string.Format(\"uncodeable object: {0}\", obj.GetType()));\n                }\n\n                m_typeInfoStack.Pop();\n            }\n\n            #endregion\n\n            m_element = m_elementStack.Pop();\n            AddValue(element);\n\n            if ((typeOptions & TypeInfo.Option.Version) != 0)\n                m_version = m_versionStack.Pop();\n        }\n\n        public void CodeFields(Type type, int version, IFieldCodeable obj)\n        {\n            FieldCoder[] fca = FieldCoderArray.Get(c_coderVersion, type, version, obj);\n            foreach (var fc in fca)\n            {\n                var element = new XElement(fc.Name);\n                m_elementStack.Push(m_element);\n                m_element = element;\n                fc.Code(this, obj);\n                m_element = m_elementStack.Pop();\n                AddValue(element);\n            }\n        }\n\n        public void CodeFields(Type type, ITypedMap obj)\n        {\n            TypeOfString fieldTypeMap = FieldTypeMap.Get(type, obj);\n\n            foreach (string fieldName in obj.FieldNames)\n            {\n                XElement element = null;\n                XAttribute attribute = null;\n                object value = obj[fieldName];\n                Type fieldType;\n                string fieldTypeName = null;\n                if (!fieldTypeMap.TryGetValue(fieldName, out fieldType))\n                {\n                    TypeInfo typeInfo;\n                    fieldType = value.GetType();\n                    if (TryGetTypeInfo(fieldType, out typeInfo))\n                        fieldTypeName = typeInfo.XmlName;\n                    else\n                        fieldTypeName = fieldType.AssemblyQualifiedName;\n                    attribute = new XAttribute(\"type\", fieldTypeName);\n                }\n                else\n                {\n                    fieldTypeName = fieldType.Name;\n                }\n\n                if (fieldTypeName != fieldName || TypeCoder.IsDirectlyCodeable(fieldType))\n                {\n                    element = new XElement(fieldName);\n                    if (attribute != null) element.Add(attribute);\n                    m_elementStack.Push(m_element);\n                    m_element = element;\n                }\n                TypeCoder.Write(this, fieldType, ref value);\n                if (fieldTypeName != fieldName || TypeCoder.IsDirectlyCodeable(fieldType))\n                {\n                    m_element = m_elementStack.Pop();\n                    AddValue(element);\n                }\n            }\n        }\n\n        public void CodeT<T>(ref T obj)\n        {\n            object o = obj;\n            if (typeof(T) == typeof(Array) || obj == null)\n                Code(ref o);\n            else\n                TypeCoder.Write(this, obj.GetType(), ref o);\n        }\n\n        private bool CodeNull<T>(ref T value)\n        {\n            if (value != null) return false;\n            AddValue(new XElement(\"null\"));\n            return true;\n        }\n\n        public int CodeCount<T>(ref T value, Func<T, int> counter) where T : class\n        {\n            if (value == null)\n            {\n                AddValue(new XElement(\"null\")); return -1;\n            }\n            object obj = value;\n\n            if (m_doRefs)\n            {\n                int index;\n                if (m_refs.TryGetValue(obj, out index))\n                {\n                    TypeInfo typeInfo;\n                    if (TryGetTypeInfo(typeof(TypeCoder.Reference), out typeInfo))\n                    {\n                        XElement refElement = new XElement(typeInfo.XmlName);\n                        refElement.Add(new XAttribute(\"num\", m_refs[obj]));\n                        AddValue(refElement);\n                        return -2;\n                    }\n                    throw new Exception(\n                            \"cannot encode multiply referenced object \"\n                            + \"- change by configuring coder with \"\n                            + \"\\\"coder.Add(TypeCoder.Default.Reference);\\\"\");\n                }\n            }            \n            int count = counter(value);\n            if (m_doRefs)\n            {\n                int refNum = m_refs.Count;\n                m_refs[obj] = refNum;\n                if (m_writeRefNumbers)\n                    AddValue(new XAttribute(\"num\", refNum));\n            }\n            AddValue(new XAttribute(\"count\", count));\n            return count;\n        }\n\n        private int CodeCount<T>(ref T[] array)\n        {\n            return CodeCount(ref array, v => v.Length);\n        }\n\n        private int CodeCount<T>(ref List<T> list)\n        {\n            return CodeCount(ref list, v => v.Count);\n        }\n\n        public void CodeTArray<T>(ref T[] value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n                CodeT(ref value[i]);\n        }\n\n        public void CodeList_of_T_<T>(ref List<T> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                object o = value[i];\n                Code(ref o);\n            }\n        }\n\n        public void CodeHashSet_of_T_<T>(ref HashSet<T> value)\n        {\n            int count = CodeCount(ref value, s => s.Count);\n            if (count < 1) return;\n            foreach (var k in value)\n            {\n                object o = k;\n                Code(ref o);\n            }\n        }\n\n        public void Code(Type t, ref object o)\n        {\n            TypeCoder.Write(this, t, ref o);\n        }\n\n        public void Code(Type t, ref Array value)\n        {\n            int count = CodeCount(ref value, a => a.Length);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                object o = value.GetValue(i);\n                Code(ref o);\n            }\n        }\n        public void Code(Type t, ref IList value)\n        {\n            int count = CodeCount(ref value, l => l.Count);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                object o = value[i];\n                Code(ref o);\n            }\n        }\n\n        public void Code(Type t, ref IDictionary dict)\n        {\n            int count = CodeCount(ref dict, d => d.Count);\n            if (count < 1) return;\n            XElement element;\n            Type[] subTypeArray = t.GetGenericArguments();\n            var keys = dict.Keys;\n            foreach (object k in keys)\n            {\n                var item = new XElement(\"item\");\n                m_elementStack.Push(m_element);\n                m_element = item;\n\n                object key = k;\n                element = new XElement(\"key\");\n                m_elementStack.Push(m_element);\n                m_element = element;\n                TypeCoder.Write(this, subTypeArray[0], ref key);\n                m_element = m_elementStack.Pop();\n                AddValue(element);\n                object val = dict[key];\n                element = new XElement(\"val\");\n                m_elementStack.Push(m_element);\n                m_element = element;\n                TypeCoder.Write(this, subTypeArray[1], ref val);\n                m_element = m_elementStack.Pop();\n                AddValue(element);\n\n                m_element = m_elementStack.Pop();\n                AddValue(item);\n            }\n        }\n\n        public void Code(Type t, ref ICountableDict dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref ICountableDictSet dict)\n        {\n            throw new NotImplementedException();\n        }\n\n        private void CodeTensor<T>(T dim, Action dataWriter)\n        {\n            var element = new XElement(\"dim\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            CodeT(ref dim);\n\n            m_element = m_elementStack.Pop();\n            AddValue(element);\n\n            element = new XElement(\"data\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            dataWriter();\n\n            m_element = m_elementStack.Pop();\n            AddValue(element);\n        }\n\n        public void Code(Type t, ref IArrayVector value)\n        {\n            var item = new XElement(\"Vector\");\n            m_elementStack.Push(m_element);\n            m_element = item;\n\n            var element = new XElement(\"Data\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var array = value.Array; Code(value.ArrayType, ref array);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Origin\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var origin = value.Origin; CodeLong(ref origin);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Length\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var length = value.Size; CodeLong(ref length);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Delta\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var delta = value.Delta; CodeLong(ref delta);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            m_element = m_elementStack.Pop();\n            AddValue(item);\n        }\n\n        public void Code(Type t, ref IArrayMatrix value)\n        {\n            var item = new XElement(\"Matrix\");\n            m_elementStack.Push(m_element);\n            m_element = item;\n\n            var element = new XElement(\"Data\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var array = value.Array; Code(value.ArrayType, ref array);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Origin\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var origin = value.Origin; CodeLong(ref origin);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Length\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var length = value.Size; CodeV2l(ref length);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Delta\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var delta = value.Delta; CodeV2l(ref delta);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            m_element = m_elementStack.Pop();\n            AddValue(item);\n        }\n\n        public void Code(Type t, ref IArrayVolume value)\n        {\n            var item = new XElement(\"Volume\");\n            m_elementStack.Push(m_element);\n            m_element = item;\n\n            var element = new XElement(\"Data\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var array = value.Array; Code(value.ArrayType, ref array);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Origin\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var origin = value.Origin; CodeLong(ref origin);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Length\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var length = value.Size; CodeV3l(ref length);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Delta\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var delta = value.Delta; CodeV3l(ref delta);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            m_element = m_elementStack.Pop();\n            AddValue(item);\n        }\n\n        public void Code(Type t, ref IArrayTensor4 value)\n        {\n            throw new NotImplementedException();\n        }\n\n        public void Code(Type t, ref IArrayTensorN value)\n        {\n            var item = new XElement(\"Tensor\");\n            m_elementStack.Push(m_element);\n            m_element = item;\n\n            var element = new XElement(\"Data\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var array = value.Array; Code(value.ArrayType, ref array);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Origin\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var origin = value.Origin; CodeLong(ref origin);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Length\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var length = value.Size; CodeLongArray(ref length);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Delta\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var delta = value.Delta; CodeLongArray(ref delta);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            m_element = m_elementStack.Pop();\n            AddValue(item);\n        }\n\n        public void CodeHashSet(Type t, ref object o)\n        {\n            throw new NotImplementedException(\"only possible whith a non-generic ISet interface)\");\n        }\n\n        public void CodeEnum(Type t, ref object value)\n        {\n            var name = value.ToString();\n            AddValue(name);\n        }\n\n        #endregion\n\n        #region Code Primitives\n\n        public void CodeBool(ref bool v) { AddValue(v.ToString()); }\n        public void CodeByte(ref byte v) { AddValue(v.ToString()); }\n        public void CodeSByte(ref sbyte v) { AddValue(v.ToString()); }\n        public void CodeShort(ref short v) { AddValue(v.ToString()); }\n        public void CodeUShort(ref ushort v) { AddValue(v.ToString()); }\n        public void CodeInt(ref int v) { AddValue(v.ToString()); }\n        public void CodeUInt(ref uint v) { AddValue(v.ToString()); }\n        public void CodeLong(ref long v) { AddValue(v.ToString()); }\n        public void CodeULong(ref ulong v) { AddValue(v.ToString()); }\n\n        public void CodeFloat(ref float value)\n        {\n            AddValue(value.ToString(CultureInfo.InvariantCulture));\n        }\n\n        public void CodeDouble(ref double value)\n        {\n            AddValue(value.ToString(CultureInfo.InvariantCulture));\n        }\n\n        private static readonly char[] s_stringSplitChars = new[]\n        {\n            '\\0',\n            Convert.ToChar(0x19),\n            Convert.ToChar(0x01),\n            Convert.ToChar(0x1e),\n        };\n\n        private void CodeStringHelper(string value)\n        {\n            if (CodeNull(ref value)) return;\n            foreach (string s in value.Split(s_stringSplitChars))\n                AddValue(s);\n        }\n\n        public void CodeChar(ref char v) { AddValue(v.ToString()); }\n        public void CodeString(ref string value) { CodeStringHelper(value); }\n\n        public void CodeType(ref Type value)\n        {\n            string typeName;\n            TypeInfo ti;\n            if (TryGetTypeInfo(value, out ti))\n                typeName = ti.Name;\n            else\n                typeName = value.AssemblyQualifiedName;\n            AddValue(typeName);\n        }\n\n        public void CodeGuid(ref Guid v) { AddValue(v.ToString()); }\n\n        public void CodeSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodeGuidSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodePositiveSymbol(ref Symbol v) { throw new NotImplementedException(); }\n\n        public void CodeIntSet(ref IntSet set) { throw new NotImplementedException(); }\n\n        public void CodeSymbolSet(ref SymbolSet set) { throw new NotImplementedException(); }\n\n        public void CodeFraction(ref Fraction v) { AddValue(v.ToString()); }\n\n        public void CodeStructArray<T>(ref T[] a) where T : struct\n        {\n            throw new NotImplementedException();\n        }\n\n        public void CodeStructList<T>(ref List<T> l) where T : struct\n        {\n            throw new NotImplementedException();\n        }\n\n        private void CodeFormattableArray<T>(T[] value) where T : IFormattable\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            var text = new StringBuilder();\n            for (int i = 0; i < count - 1; i++)\n            {\n                text.Append(value[i].ToString(null, CultureInfo.InvariantCulture));\n                text.Append(\", \");\n            }\n            text.Append(value[count - 1].ToString(null, CultureInfo.InvariantCulture));\n            AddValue(text.ToString());\n        }\n\n        private void CodeFormattableList<T>(List<T> value) where T : IFormattable\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            var text = new StringBuilder();\n            for (int i = 0; i < count - 1; i++)\n            {\n                text.Append(value[i].ToString(null, CultureInfo.InvariantCulture));\n                text.Append(\", \");\n            }\n            text.Append(value[count - 1].ToString(null, CultureInfo.InvariantCulture));\n            AddValue(text.ToString());\n        }\n\n        private void CodeArrayOfStruct<T>(T[] value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            var text = new StringBuilder();\n            for (int i = 0; i < count - 1; i++)\n            {\n                text.Append(value[i].ToString());\n                text.Append(\", \");\n            }\n            text.Append(value[count - 1].ToString());\n            AddValue(text.ToString());\n        }\n\n        private void CodeListOfStruct<T>(List<T> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            var text = new StringBuilder();\n            for (int i = 0; i < count - 1; i++)\n            {\n                text.Append(value[i].ToString());\n                text.Append(\", \");\n            }\n            text.Append(value[count - 1].ToString());\n            AddValue(text.ToString());\n        }\n\n        private void CodeArrayOf<T>(T[] value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                var item = value[i]; CodeT(ref item);\n            }\n        }\n\n        private void CodeListOf<T>(List<T> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            for (int i = 0; i < count; i++)\n            {\n                var item = value[i]; CodeT(ref item);\n            }\n        }\n\n        public void CodeBoolArray(ref bool[] value) { CodeArrayOfStruct(value); }\n        public void CodeByteArray(ref byte[] value) { CodeArrayOfStruct(value); }\n        public void CodeSByteArray(ref sbyte[] value) { CodeArrayOfStruct(value); }\n        public void CodeShortArray(ref short[] value) { CodeArrayOfStruct(value); }\n        public void CodeUShortArray(ref ushort[] value) { CodeArrayOfStruct(value); }\n        public void CodeIntArray(ref int[] value) { CodeArrayOfStruct(value); }\n        public void CodeUIntArray(ref uint[] value) { CodeArrayOfStruct(value); }\n        public void CodeLongArray(ref long[] value) { CodeArrayOfStruct(value); }\n        public void CodeULongArray(ref ulong[] value) { CodeArrayOfStruct(value); }\n        public void CodeFloatArray(ref float[] value) { CodeFormattableArray(value); }\n        public void CodeDoubleArray(ref double[] value) { CodeFormattableArray(value); }\n\n        public void CodeCharArray(ref char[] value) { CodeArrayOfStruct(value); }\n        public void CodeStringArray(ref string[] value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            XElement element;\n            foreach (string s in value)\n            {\n                element = new XElement(\"str\");\n                m_elementStack.Push(m_element);\n                m_element = element;\n                CodeStringHelper(s);\n                m_element = m_elementStack.Pop();\n                AddValue(element);\n            }\n        }\n\n        public void CodeTypeArray(ref Type[] value) \n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            var text = new StringBuilder();\n\n            for (int i = 0; i < count; i++)\n            {\n                string typeName;\n                TypeInfo ti;\n                if (TryGetTypeInfo(value[i], out ti))\n                    typeName = ti.Name;\n                else\n                    typeName = value[i].AssemblyQualifiedName;\n\n                text.Append(typeName);\n\n                if (i < count - 1)\n                    text.Append(\", \");\n            }\n            AddValue(text.ToString());\n        }\n\n        public void CodeGuidArray(ref Guid[] v) { CodeArrayOfStruct(v); }\n\n        public void CodeSymbolArray(ref Symbol[] v) { throw new NotImplementedException(); }\n        \n        public void CodeFractionArray(ref Fraction[] v) { CodeArrayOfStruct(v); }\n\n        public void CodeList_of_Bool_(ref List<bool> value) { CodeListOfStruct(value); }\n        public void CodeList_of_Byte_(ref List<byte> value) { CodeListOfStruct(value); }\n        public void CodeList_of_SByte_(ref List<sbyte> value) { CodeListOfStruct(value); }\n        public void CodeList_of_Short_(ref List<short> value) { CodeListOfStruct(value); }\n        public void CodeList_of_UShort_(ref List<ushort> value) { CodeListOfStruct(value); }\n        public void CodeList_of_Int_(ref List<int> value) { CodeListOfStruct(value); }\n        public void CodeList_of_UInt_(ref List<uint> value) { CodeListOfStruct(value); }\n        public void CodeList_of_Long_(ref List<long> value) { CodeListOfStruct(value); }\n        public void CodeList_of_ULong_(ref List<ulong> value) { CodeListOfStruct(value); }\n        public void CodeList_of_Float_(ref List<float> value) { CodeFormattableList(value); }\n        public void CodeList_of_Double_(ref List<double> value) { CodeFormattableList(value); }\n\n        public void CodeList_of_Char_(ref List<char> value) { CodeListOfStruct(value); }\n        public void CodeList_of_String_(ref List<string> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            XElement element;\n            foreach (string s in value)\n            {\n                element = new XElement(\"string\");\n                m_elementStack.Push(m_element);\n                m_element = element;\n                CodeStringHelper(s);\n                m_element = m_elementStack.Pop();\n                AddValue(element);\n            }\n        }\n\n        public void CodeList_of_Type_(ref List<Type> value)\n        {\n            int count = CodeCount(ref value);\n            if (count < 1) return;\n            var text = new StringBuilder();\n\n            for (int i = 0; i < count; i++)\n            {\n                string typeName;\n                TypeInfo ti;\n                if (TryGetTypeInfo(value[i], out ti))\n                    typeName = ti.Name;\n                else\n                    typeName = value[i].AssemblyQualifiedName;\n\n                text.Append(typeName);\n\n                if (i < count - 1)\n                    text.Append(\", \");\n            }\n            AddValue(text.ToString());\n        }\n\n        public void CodeList_of_Fraction_(ref List<Fraction> v) { CodeListOfStruct(v); }\n        public void CodeList_of_Guid_(ref List<Guid> v) { CodeListOfStruct(v); }\n        public void CodeList_of_Symbol_(ref List<Symbol> v) { throw new NotImplementedException(); }\n\n        #endregion\n\n        #region IDisposable Members\n\n        public void Dispose()\n        {\n            if (m_stream == null)\n                return;\n\n            var writer = new StreamWriter(m_stream, Encoding.UTF8);\n            m_element.Save(writer);\n\n            if (m_disposeStream)\n                writer.Close();\n            else\n                writer.Flush();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/XmlWritingCoder_auto.cs",
    "content": "using Aardvark.Base;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Xml.Linq;\r\n\r\nnamespace Aardvark.Base.Coder\r\n{\r\n    // AUTO GENERATED CODE - DO NOT CHANGE!\r\n\r\n    public partial class NewXmlWritingCoder\r\n    {\r\n        #region Vectors\r\n\r\n        public void CodeV2i(ref V2i v) { throw new NotImplementedException(); }\r\n        public void CodeV2ui(ref V2ui v) { throw new NotImplementedException(); }\r\n        public void CodeV2l(ref V2l v) { throw new NotImplementedException(); }\r\n        public void CodeV2f(ref V2f v) { throw new NotImplementedException(); }\r\n        public void CodeV2d(ref V2d v) { throw new NotImplementedException(); }\r\n        public void CodeV3i(ref V3i v) { throw new NotImplementedException(); }\r\n        public void CodeV3ui(ref V3ui v) { throw new NotImplementedException(); }\r\n        public void CodeV3l(ref V3l v) { throw new NotImplementedException(); }\r\n        public void CodeV3f(ref V3f v) { throw new NotImplementedException(); }\r\n        public void CodeV3d(ref V3d v) { throw new NotImplementedException(); }\r\n        public void CodeV4i(ref V4i v) { throw new NotImplementedException(); }\r\n        public void CodeV4ui(ref V4ui v) { throw new NotImplementedException(); }\r\n        public void CodeV4l(ref V4l v) { throw new NotImplementedException(); }\r\n        public void CodeV4f(ref V4f v) { throw new NotImplementedException(); }\r\n        public void CodeV4d(ref V4d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Matrices\r\n\r\n        public void CodeM22i(ref M22i v) { throw new NotImplementedException(); }\r\n        public void CodeM22l(ref M22l v) { throw new NotImplementedException(); }\r\n        public void CodeM22f(ref M22f v) { throw new NotImplementedException(); }\r\n        public void CodeM22d(ref M22d v) { throw new NotImplementedException(); }\r\n        public void CodeM23i(ref M23i v) { throw new NotImplementedException(); }\r\n        public void CodeM23l(ref M23l v) { throw new NotImplementedException(); }\r\n        public void CodeM23f(ref M23f v) { throw new NotImplementedException(); }\r\n        public void CodeM23d(ref M23d v) { throw new NotImplementedException(); }\r\n        public void CodeM33i(ref M33i v) { throw new NotImplementedException(); }\r\n        public void CodeM33l(ref M33l v) { throw new NotImplementedException(); }\r\n        public void CodeM33f(ref M33f v) { throw new NotImplementedException(); }\r\n        public void CodeM33d(ref M33d v) { throw new NotImplementedException(); }\r\n        public void CodeM34i(ref M34i v) { throw new NotImplementedException(); }\r\n        public void CodeM34l(ref M34l v) { throw new NotImplementedException(); }\r\n        public void CodeM34f(ref M34f v) { throw new NotImplementedException(); }\r\n        public void CodeM34d(ref M34d v) { throw new NotImplementedException(); }\r\n        public void CodeM44i(ref M44i v) { throw new NotImplementedException(); }\r\n        public void CodeM44l(ref M44l v) { throw new NotImplementedException(); }\r\n        public void CodeM44f(ref M44f v) { throw new NotImplementedException(); }\r\n        public void CodeM44d(ref M44d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Ranges and Boxes\r\n\r\n        public void CodeRange1b(ref Range1b v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sb(ref Range1sb v) { throw new NotImplementedException(); }\r\n        public void CodeRange1s(ref Range1s v) { throw new NotImplementedException(); }\r\n        public void CodeRange1us(ref Range1us v) { throw new NotImplementedException(); }\r\n        public void CodeRange1i(ref Range1i v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ui(ref Range1ui v) { throw new NotImplementedException(); }\r\n        public void CodeRange1l(ref Range1l v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ul(ref Range1ul v) { throw new NotImplementedException(); }\r\n        public void CodeRange1f(ref Range1f v) { throw new NotImplementedException(); }\r\n        public void CodeRange1d(ref Range1d v) { throw new NotImplementedException(); }\r\n        public void CodeBox2i(ref Box2i v) { throw new NotImplementedException(); }\r\n        public void CodeBox2l(ref Box2l v) { throw new NotImplementedException(); }\r\n        public void CodeBox2f(ref Box2f v) { throw new NotImplementedException(); }\r\n        public void CodeBox2d(ref Box2d v) { throw new NotImplementedException(); }\r\n        public void CodeBox3i(ref Box3i v) { throw new NotImplementedException(); }\r\n        public void CodeBox3l(ref Box3l v) { throw new NotImplementedException(); }\r\n        public void CodeBox3f(ref Box3f v) { throw new NotImplementedException(); }\r\n        public void CodeBox3d(ref Box3d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Geometry Types\r\n\r\n        public void CodeCircle2f(ref Circle2f v) { throw new NotImplementedException(); }\r\n        public void CodeLine2f(ref Line2f v) { throw new NotImplementedException(); }\r\n        public void CodeLine3f(ref Line3f v) { throw new NotImplementedException(); }\r\n        public void CodePlane2f(ref Plane2f v) { throw new NotImplementedException(); }\r\n        public void CodePlane3f(ref Plane3f v) { throw new NotImplementedException(); }\r\n        public void CodePlaneWithPoint3f(ref PlaneWithPoint3f v) { throw new NotImplementedException(); }\r\n        public void CodeQuad2f(ref Quad2f v) { throw new NotImplementedException(); }\r\n        public void CodeQuad3f(ref Quad3f v) { throw new NotImplementedException(); }\r\n        public void CodeRay2f(ref Ray2f v) { throw new NotImplementedException(); }\r\n        public void CodeRay3f(ref Ray3f v) { throw new NotImplementedException(); }\r\n        public void CodeSphere3f(ref Sphere3f v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle2f(ref Triangle2f v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle3f(ref Triangle3f v) { throw new NotImplementedException(); }\r\n\r\n        public void CodeCircle2d(ref Circle2d v) { throw new NotImplementedException(); }\r\n        public void CodeLine2d(ref Line2d v) { throw new NotImplementedException(); }\r\n        public void CodeLine3d(ref Line3d v) { throw new NotImplementedException(); }\r\n        public void CodePlane2d(ref Plane2d v) { throw new NotImplementedException(); }\r\n        public void CodePlane3d(ref Plane3d v) { throw new NotImplementedException(); }\r\n        public void CodePlaneWithPoint3d(ref PlaneWithPoint3d v) { throw new NotImplementedException(); }\r\n        public void CodeQuad2d(ref Quad2d v) { throw new NotImplementedException(); }\r\n        public void CodeQuad3d(ref Quad3d v) { throw new NotImplementedException(); }\r\n        public void CodeRay2d(ref Ray2d v) { throw new NotImplementedException(); }\r\n        public void CodeRay3d(ref Ray3d v) { throw new NotImplementedException(); }\r\n        public void CodeSphere3d(ref Sphere3d v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle2d(ref Triangle2d v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle3d(ref Triangle3d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Colors\r\n\r\n        public void CodeC3b(ref C3b v) { throw new NotImplementedException(); }\r\n        public void CodeC3us(ref C3us v) { throw new NotImplementedException(); }\r\n        public void CodeC3ui(ref C3ui v) { throw new NotImplementedException(); }\r\n        public void CodeC3f(ref C3f v) { throw new NotImplementedException(); }\r\n        public void CodeC3d(ref C3d v) { throw new NotImplementedException(); }\r\n        public void CodeC4b(ref C4b v) { throw new NotImplementedException(); }\r\n        public void CodeC4us(ref C4us v) { throw new NotImplementedException(); }\r\n        public void CodeC4ui(ref C4ui v) { throw new NotImplementedException(); }\r\n        public void CodeC4f(ref C4f v) { throw new NotImplementedException(); }\r\n        public void CodeC4d(ref C4d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Trafos\r\n\r\n        public void CodeEuclidean3f(ref Euclidean3f v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3d(ref Euclidean3d v) { throw new NotImplementedException(); }\r\n        public void CodeRot2f(ref Rot2f v) { throw new NotImplementedException(); }\r\n        public void CodeRot2d(ref Rot2d v) { throw new NotImplementedException(); }\r\n        public void CodeRot3f(ref Rot3f v) { throw new NotImplementedException(); }\r\n        public void CodeRot3d(ref Rot3d v) { throw new NotImplementedException(); }\r\n        public void CodeScale3f(ref Scale3f v) { throw new NotImplementedException(); }\r\n        public void CodeScale3d(ref Scale3d v) { throw new NotImplementedException(); }\r\n        public void CodeShift3f(ref Shift3f v) { throw new NotImplementedException(); }\r\n        public void CodeShift3d(ref Shift3d v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2f(ref Trafo2f v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2d(ref Trafo2d v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3f(ref Trafo3f v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3d(ref Trafo3d v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Tensors\r\n\r\n        public void CodeVector_of_Byte_(ref Vector<byte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_SByte_(ref Vector<sbyte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Short_(ref Vector<short> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_UShort_(ref Vector<ushort> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Int_(ref Vector<int> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_UInt_(ref Vector<uint> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Long_(ref Vector<long> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_ULong_(ref Vector<ulong> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Float_(ref Vector<float> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Double_(ref Vector<double> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_(ref Vector<Fraction> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2i_(ref Vector<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2l_(ref Vector<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2f_(ref Vector<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V2d_(ref Vector<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3i_(ref Vector<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3l_(ref Vector<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3f_(ref Vector<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V3d_(ref Vector<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4i_(ref Vector<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4l_(ref Vector<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4f_(ref Vector<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_V4d_(ref Vector<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22i_(ref Vector<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22l_(ref Vector<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22f_(ref Vector<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M22d_(ref Vector<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23i_(ref Vector<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23l_(ref Vector<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23f_(ref Vector<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M23d_(ref Vector<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33i_(ref Vector<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33l_(ref Vector<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33f_(ref Vector<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M33d_(ref Vector<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34i_(ref Vector<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34l_(ref Vector<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34f_(ref Vector<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M34d_(ref Vector<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44i_(ref Vector<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44l_(ref Vector<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44f_(ref Vector<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_M44d_(ref Vector<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3b_(ref Vector<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3us_(ref Vector<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_(ref Vector<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3f_(ref Vector<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C3d_(ref Vector<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4b_(ref Vector<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4us_(ref Vector<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_(ref Vector<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4f_(ref Vector<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_C4d_(ref Vector<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_(ref Vector<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_(ref Vector<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_(ref Vector<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_(ref Vector<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_(ref Vector<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_(ref Vector<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_(ref Vector<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_(ref Vector<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_(ref Vector<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_(ref Vector<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_(ref Vector<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_(ref Vector<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_(ref Vector<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_(ref Vector<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_(ref Vector<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_(ref Vector<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_(ref Vector<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_(ref Vector<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_(ref Vector<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_(ref Vector<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_(ref Vector<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_(ref Vector<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_(ref Vector<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_(ref Vector<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_(ref Vector<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_(ref Vector<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_(ref Vector<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_(ref Vector<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_(ref Vector<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_(ref Vector<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_(ref Vector<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_(ref Vector<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Bool_(ref Vector<bool> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Char_(ref Vector<char> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_String_(ref Vector<string> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Type_(ref Vector<Type> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Guid_(ref Vector<Guid> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_(ref Vector<Symbol> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_(ref Vector<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_(ref Vector<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_(ref Vector<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_(ref Vector<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_(ref Vector<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_(ref Vector<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_(ref Vector<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_(ref Vector<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_(ref Vector<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_(ref Vector<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_(ref Vector<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_(ref Vector<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_(ref Vector<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_(ref Vector<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_(ref Vector<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_(ref Vector<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_(ref Vector<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_(ref Vector<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_(ref Vector<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_(ref Vector<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_(ref Vector<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_(ref Vector<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_(ref Vector<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_(ref Vector<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_(ref Vector<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_(ref Vector<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_(ref Matrix<byte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_(ref Matrix<sbyte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_(ref Matrix<short> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_(ref Matrix<ushort> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_(ref Matrix<int> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_(ref Matrix<uint> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_(ref Matrix<long> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_(ref Matrix<ulong> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_(ref Matrix<float> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_(ref Matrix<double> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_(ref Matrix<Fraction> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_(ref Matrix<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_(ref Matrix<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_(ref Matrix<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_(ref Matrix<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_(ref Matrix<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_(ref Matrix<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_(ref Matrix<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_(ref Matrix<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_(ref Matrix<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_(ref Matrix<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_(ref Matrix<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_(ref Matrix<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_(ref Matrix<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_(ref Matrix<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_(ref Matrix<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_(ref Matrix<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_(ref Matrix<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_(ref Matrix<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_(ref Matrix<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_(ref Matrix<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_(ref Matrix<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_(ref Matrix<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_(ref Matrix<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_(ref Matrix<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_(ref Matrix<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_(ref Matrix<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_(ref Matrix<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_(ref Matrix<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_(ref Matrix<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_(ref Matrix<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_(ref Matrix<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_(ref Matrix<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_(ref Matrix<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_(ref Matrix<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_(ref Matrix<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_(ref Matrix<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_(ref Matrix<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_(ref Matrix<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_(ref Matrix<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_(ref Matrix<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_(ref Matrix<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_(ref Matrix<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_(ref Matrix<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_(ref Matrix<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_(ref Matrix<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_(ref Matrix<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_(ref Matrix<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_(ref Matrix<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_(ref Matrix<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_(ref Matrix<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_(ref Matrix<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_(ref Matrix<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_(ref Matrix<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_(ref Matrix<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_(ref Matrix<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_(ref Matrix<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_(ref Matrix<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_(ref Matrix<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_(ref Matrix<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_(ref Matrix<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_(ref Matrix<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_(ref Matrix<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_(ref Matrix<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_(ref Matrix<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_(ref Matrix<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_(ref Matrix<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_(ref Matrix<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_(ref Matrix<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_(ref Matrix<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_(ref Matrix<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_(ref Matrix<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_(ref Matrix<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_(ref Matrix<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_(ref Matrix<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_(ref Matrix<bool> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_(ref Matrix<char> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_String_(ref Matrix<string> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_(ref Matrix<Type> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_(ref Matrix<Guid> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_(ref Matrix<Symbol> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_(ref Matrix<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_(ref Matrix<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_(ref Matrix<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_(ref Matrix<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_(ref Matrix<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_(ref Matrix<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_(ref Matrix<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_(ref Matrix<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_(ref Matrix<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_(ref Matrix<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_(ref Matrix<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_(ref Matrix<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_(ref Matrix<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_(ref Matrix<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_(ref Matrix<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_(ref Matrix<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_(ref Matrix<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_(ref Matrix<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_(ref Matrix<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_(ref Matrix<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_(ref Matrix<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_(ref Matrix<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_(ref Matrix<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_(ref Matrix<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_(ref Matrix<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_(ref Matrix<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_(ref Volume<byte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_(ref Volume<sbyte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Short_(ref Volume<short> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_(ref Volume<ushort> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Int_(ref Volume<int> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_(ref Volume<uint> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Long_(ref Volume<long> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_(ref Volume<ulong> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Float_(ref Volume<float> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Double_(ref Volume<double> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_(ref Volume<Fraction> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_(ref Volume<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_(ref Volume<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_(ref Volume<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_(ref Volume<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_(ref Volume<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_(ref Volume<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_(ref Volume<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_(ref Volume<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_(ref Volume<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_(ref Volume<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_(ref Volume<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_(ref Volume<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_(ref Volume<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_(ref Volume<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_(ref Volume<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_(ref Volume<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_(ref Volume<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_(ref Volume<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_(ref Volume<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_(ref Volume<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_(ref Volume<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_(ref Volume<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_(ref Volume<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_(ref Volume<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_(ref Volume<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_(ref Volume<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_(ref Volume<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_(ref Volume<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_(ref Volume<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_(ref Volume<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_(ref Volume<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_(ref Volume<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_(ref Volume<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_(ref Volume<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_(ref Volume<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_(ref Volume<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_(ref Volume<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_(ref Volume<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_(ref Volume<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_(ref Volume<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_(ref Volume<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_(ref Volume<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_(ref Volume<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_(ref Volume<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_(ref Volume<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_(ref Volume<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_(ref Volume<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_(ref Volume<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_(ref Volume<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_(ref Volume<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_(ref Volume<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_(ref Volume<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_(ref Volume<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_(ref Volume<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_(ref Volume<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_(ref Volume<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_(ref Volume<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_(ref Volume<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_(ref Volume<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_(ref Volume<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_(ref Volume<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_(ref Volume<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_(ref Volume<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_(ref Volume<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_(ref Volume<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_(ref Volume<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_(ref Volume<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_(ref Volume<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_(ref Volume<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_(ref Volume<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_(ref Volume<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_(ref Volume<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_(ref Volume<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_(ref Volume<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_(ref Volume<bool> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Char_(ref Volume<char> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_String_(ref Volume<string> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Type_(ref Volume<Type> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_(ref Volume<Guid> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_(ref Volume<Symbol> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_(ref Volume<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_(ref Volume<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_(ref Volume<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_(ref Volume<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_(ref Volume<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_(ref Volume<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_(ref Volume<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_(ref Volume<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_(ref Volume<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_(ref Volume<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_(ref Volume<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_(ref Volume<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_(ref Volume<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_(ref Volume<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_(ref Volume<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_(ref Volume<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_(ref Volume<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_(ref Volume<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_(ref Volume<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_(ref Volume<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_(ref Volume<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_(ref Volume<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_(ref Volume<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_(ref Volume<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_(ref Volume<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_(ref Volume<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_(ref Tensor<byte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_(ref Tensor<sbyte> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Short_(ref Tensor<short> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_(ref Tensor<ushort> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Int_(ref Tensor<int> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_(ref Tensor<uint> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Long_(ref Tensor<long> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_(ref Tensor<ulong> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Float_(ref Tensor<float> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Double_(ref Tensor<double> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_(ref Tensor<Fraction> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_(ref Tensor<V2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_(ref Tensor<V2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_(ref Tensor<V2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_(ref Tensor<V2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_(ref Tensor<V3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_(ref Tensor<V3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_(ref Tensor<V3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_(ref Tensor<V3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_(ref Tensor<V4i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_(ref Tensor<V4l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_(ref Tensor<V4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_(ref Tensor<V4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_(ref Tensor<M22i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_(ref Tensor<M22l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_(ref Tensor<M22f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_(ref Tensor<M22d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_(ref Tensor<M23i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_(ref Tensor<M23l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_(ref Tensor<M23f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_(ref Tensor<M23d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_(ref Tensor<M33i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_(ref Tensor<M33l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_(ref Tensor<M33f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_(ref Tensor<M33d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_(ref Tensor<M34i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_(ref Tensor<M34l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_(ref Tensor<M34f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_(ref Tensor<M34d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_(ref Tensor<M44i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_(ref Tensor<M44l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_(ref Tensor<M44f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_(ref Tensor<M44d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_(ref Tensor<C3b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_(ref Tensor<C3us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_(ref Tensor<C3ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_(ref Tensor<C3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_(ref Tensor<C3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_(ref Tensor<C4b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_(ref Tensor<C4us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_(ref Tensor<C4ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_(ref Tensor<C4f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_(ref Tensor<C4d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_(ref Tensor<Range1b> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_(ref Tensor<Range1sb> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_(ref Tensor<Range1s> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_(ref Tensor<Range1us> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_(ref Tensor<Range1i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_(ref Tensor<Range1ui> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_(ref Tensor<Range1l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_(ref Tensor<Range1ul> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_(ref Tensor<Range1f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_(ref Tensor<Range1d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_(ref Tensor<Box2i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_(ref Tensor<Box2l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_(ref Tensor<Box2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_(ref Tensor<Box2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_(ref Tensor<Box3i> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_(ref Tensor<Box3l> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_(ref Tensor<Box3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_(ref Tensor<Box3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_(ref Tensor<Euclidean3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_(ref Tensor<Euclidean3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_(ref Tensor<Rot2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_(ref Tensor<Rot2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_(ref Tensor<Rot3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_(ref Tensor<Rot3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_(ref Tensor<Scale3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_(ref Tensor<Scale3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_(ref Tensor<Shift3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_(ref Tensor<Shift3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_(ref Tensor<Trafo2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_(ref Tensor<Trafo2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_(ref Tensor<Trafo3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_(ref Tensor<Trafo3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_(ref Tensor<bool> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Char_(ref Tensor<char> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_String_(ref Tensor<string> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Type_(ref Tensor<Type> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_(ref Tensor<Guid> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_(ref Tensor<Symbol> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_(ref Tensor<Circle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_(ref Tensor<Line2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_(ref Tensor<Line3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_(ref Tensor<Plane2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_(ref Tensor<Plane3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_(ref Tensor<PlaneWithPoint3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_(ref Tensor<Quad2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_(ref Tensor<Quad3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_(ref Tensor<Ray2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_(ref Tensor<Ray3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_(ref Tensor<Sphere3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_(ref Tensor<Triangle2d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_(ref Tensor<Triangle3d> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_(ref Tensor<Circle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_(ref Tensor<Line2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_(ref Tensor<Line3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_(ref Tensor<Plane2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_(ref Tensor<Plane3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_(ref Tensor<PlaneWithPoint3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_(ref Tensor<Quad2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_(ref Tensor<Quad3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_(ref Tensor<Ray2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_(ref Tensor<Ray3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_(ref Tensor<Sphere3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_(ref Tensor<Triangle2f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_(ref Tensor<Triangle3f> value)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Arrays\r\n\r\n        public void CodeV2iArray(ref V2i[] v) { throw new NotImplementedException(); }\r\n        public void CodeV2uiArray(ref V2ui[] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArray(ref V2l[] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArray(ref V2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArray(ref V2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArray(ref V3i[] v) { throw new NotImplementedException(); }\r\n        public void CodeV3uiArray(ref V3ui[] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArray(ref V3l[] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArray(ref V3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArray(ref V3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArray(ref V4i[] v) { throw new NotImplementedException(); }\r\n        public void CodeV4uiArray(ref V4ui[] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArray(ref V4l[] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArray(ref V4f[] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArray(ref V4d[] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArray(ref M22i[] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArray(ref M22l[] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArray(ref M22f[] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArray(ref M22d[] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArray(ref M23i[] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArray(ref M23l[] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArray(ref M23f[] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArray(ref M23d[] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArray(ref M33i[] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArray(ref M33l[] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArray(ref M33f[] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArray(ref M33d[] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArray(ref M34i[] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArray(ref M34l[] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArray(ref M34f[] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArray(ref M34d[] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArray(ref M44i[] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArray(ref M44l[] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArray(ref M44f[] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArray(ref M44d[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArray(ref Range1b[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArray(ref Range1sb[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArray(ref Range1s[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArray(ref Range1us[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArray(ref Range1i[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArray(ref Range1ui[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArray(ref Range1l[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArray(ref Range1ul[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArray(ref Range1f[] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArray(ref Range1d[] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArray(ref Box2i[] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArray(ref Box2l[] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArray(ref Box2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArray(ref Box2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArray(ref Box3i[] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArray(ref Box3l[] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArray(ref Box3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArray(ref Box3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArray(ref C3b[] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArray(ref C3us[] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArray(ref C3ui[] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArray(ref C3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArray(ref C3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArray(ref C4b[] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArray(ref C4us[] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArray(ref C4ui[] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArray(ref C4f[] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArray(ref C4d[] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArray(ref Euclidean3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArray(ref Euclidean3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArray(ref Rot2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArray(ref Rot2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArray(ref Rot3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArray(ref Rot3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArray(ref Scale3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArray(ref Scale3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArray(ref Shift3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArray(ref Shift3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArray(ref Trafo2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArray(ref Trafo2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArray(ref Trafo3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArray(ref Trafo3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeCircle2dArray(ref Circle2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeLine2dArray(ref Line2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeLine3dArray(ref Line3d[] v) { throw new NotImplementedException(); }\r\n        public void CodePlane2dArray(ref Plane2d[] v) { throw new NotImplementedException(); }\r\n        public void CodePlane3dArray(ref Plane3d[] v) { throw new NotImplementedException(); }\r\n        public void CodePlaneWithPoint3dArray(ref PlaneWithPoint3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeQuad2dArray(ref Quad2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeQuad3dArray(ref Quad3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeRay2dArray(ref Ray2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeRay3dArray(ref Ray3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeSphere3dArray(ref Sphere3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle2dArray(ref Triangle2d[] v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle3dArray(ref Triangle3d[] v) { throw new NotImplementedException(); }\r\n        public void CodeCircle2fArray(ref Circle2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeLine2fArray(ref Line2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeLine3fArray(ref Line3f[] v) { throw new NotImplementedException(); }\r\n        public void CodePlane2fArray(ref Plane2f[] v) { throw new NotImplementedException(); }\r\n        public void CodePlane3fArray(ref Plane3f[] v) { throw new NotImplementedException(); }\r\n        public void CodePlaneWithPoint3fArray(ref PlaneWithPoint3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeQuad2fArray(ref Quad2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeQuad3fArray(ref Quad3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeRay2fArray(ref Ray2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeRay3fArray(ref Ray3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeSphere3fArray(ref Sphere3f[] v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle2fArray(ref Triangle2f[] v) { throw new NotImplementedException(); }\r\n        public void CodeTriangle3fArray(ref Triangle3f[] v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArray2d(ref byte[,] v) { throw new NotImplementedException(); }\r\n        public void CodeByteArray3d(ref byte[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeSByteArray2d(ref sbyte[,] v) { throw new NotImplementedException(); }\r\n        public void CodeSByteArray3d(ref sbyte[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeShortArray2d(ref short[,] v) { throw new NotImplementedException(); }\r\n        public void CodeShortArray3d(ref short[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeUShortArray2d(ref ushort[,] v) { throw new NotImplementedException(); }\r\n        public void CodeUShortArray3d(ref ushort[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeIntArray2d(ref int[,] v) { throw new NotImplementedException(); }\r\n        public void CodeIntArray3d(ref int[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeUIntArray2d(ref uint[,] v) { throw new NotImplementedException(); }\r\n        public void CodeUIntArray3d(ref uint[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeLongArray2d(ref long[,] v) { throw new NotImplementedException(); }\r\n        public void CodeLongArray3d(ref long[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeULongArray2d(ref ulong[,] v) { throw new NotImplementedException(); }\r\n        public void CodeULongArray3d(ref ulong[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeFloatArray2d(ref float[,] v) { throw new NotImplementedException(); }\r\n        public void CodeFloatArray3d(ref float[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArray2d(ref double[,] v) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArray3d(ref double[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeFractionArray2d(ref Fraction[,] v) { throw new NotImplementedException(); }\r\n        public void CodeFractionArray3d(ref Fraction[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2iArray2d(ref V2i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2iArray3d(ref V2i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArray2d(ref V2l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArray3d(ref V2l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArray2d(ref V2f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArray3d(ref V2f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArray2d(ref V2d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArray3d(ref V2d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArray2d(ref V3i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArray3d(ref V3i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArray2d(ref V3l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArray3d(ref V3l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArray2d(ref V3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArray3d(ref V3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArray2d(ref V3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArray3d(ref V3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArray2d(ref V4i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArray3d(ref V4i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArray2d(ref V4l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArray3d(ref V4l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArray2d(ref V4f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArray3d(ref V4f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArray2d(ref V4d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArray3d(ref V4d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArray2d(ref M22i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArray3d(ref M22i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArray2d(ref M22l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArray3d(ref M22l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArray2d(ref M22f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArray3d(ref M22f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArray2d(ref M22d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArray3d(ref M22d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArray2d(ref M23i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArray3d(ref M23i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArray2d(ref M23l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArray3d(ref M23l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArray2d(ref M23f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArray3d(ref M23f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArray2d(ref M23d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArray3d(ref M23d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArray2d(ref M33i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArray3d(ref M33i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArray2d(ref M33l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArray3d(ref M33l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArray2d(ref M33f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArray3d(ref M33f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArray2d(ref M33d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArray3d(ref M33d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArray2d(ref M34i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArray3d(ref M34i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArray2d(ref M34l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArray3d(ref M34l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArray2d(ref M34f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArray3d(ref M34f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArray2d(ref M34d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArray3d(ref M34d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArray2d(ref M44i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArray3d(ref M44i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArray2d(ref M44l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArray3d(ref M44l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArray2d(ref M44f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArray3d(ref M44f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArray2d(ref M44d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArray3d(ref M44d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArray2d(ref C3b[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArray3d(ref C3b[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArray2d(ref C3us[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArray3d(ref C3us[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArray2d(ref C3ui[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArray3d(ref C3ui[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArray2d(ref C3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArray3d(ref C3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArray2d(ref C3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArray3d(ref C3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArray2d(ref C4b[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArray3d(ref C4b[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArray2d(ref C4us[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArray3d(ref C4us[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArray2d(ref C4ui[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArray3d(ref C4ui[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArray2d(ref C4f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArray3d(ref C4f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArray2d(ref C4d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArray3d(ref C4d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArray2d(ref Range1b[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArray3d(ref Range1b[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArray2d(ref Range1sb[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArray3d(ref Range1sb[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArray2d(ref Range1s[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArray3d(ref Range1s[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArray2d(ref Range1us[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArray3d(ref Range1us[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArray2d(ref Range1i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArray3d(ref Range1i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArray2d(ref Range1ui[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArray3d(ref Range1ui[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArray2d(ref Range1l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArray3d(ref Range1l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArray2d(ref Range1ul[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArray3d(ref Range1ul[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArray2d(ref Range1f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArray3d(ref Range1f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArray2d(ref Range1d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArray3d(ref Range1d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArray2d(ref Box2i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArray3d(ref Box2i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArray2d(ref Box2l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArray3d(ref Box2l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArray2d(ref Box2f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArray3d(ref Box2f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArray2d(ref Box2d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArray3d(ref Box2d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArray2d(ref Box3i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArray3d(ref Box3i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArray2d(ref Box3l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArray3d(ref Box3l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArray2d(ref Box3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArray3d(ref Box3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArray2d(ref Box3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArray3d(ref Box3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArray2d(ref Euclidean3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArray3d(ref Euclidean3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArray2d(ref Euclidean3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArray3d(ref Euclidean3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArray2d(ref Rot2f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArray3d(ref Rot2f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArray2d(ref Rot2d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArray3d(ref Rot2d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArray2d(ref Rot3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArray3d(ref Rot3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArray2d(ref Rot3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArray3d(ref Rot3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArray2d(ref Scale3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArray3d(ref Scale3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArray2d(ref Scale3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArray3d(ref Scale3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArray2d(ref Shift3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArray3d(ref Shift3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArray2d(ref Shift3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArray3d(ref Shift3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArray2d(ref Trafo2f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArray3d(ref Trafo2f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArray2d(ref Trafo2d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArray3d(ref Trafo2d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArray2d(ref Trafo3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArray3d(ref Trafo3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArray2d(ref Trafo3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArray3d(ref Trafo3d[, ,] v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Jagged Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArrayArray(ref byte[][] v) { throw new NotImplementedException(); }\r\n        public void CodeByteArrayArrayArray(ref byte[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeSByteArrayArray(ref sbyte[][] v) { throw new NotImplementedException(); }\r\n        public void CodeSByteArrayArrayArray(ref sbyte[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeShortArrayArray(ref short[][] v) { throw new NotImplementedException(); }\r\n        public void CodeShortArrayArrayArray(ref short[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeUShortArrayArray(ref ushort[][] v) { throw new NotImplementedException(); }\r\n        public void CodeUShortArrayArrayArray(ref ushort[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeIntArrayArray(ref int[][] v) { throw new NotImplementedException(); }\r\n        public void CodeIntArrayArrayArray(ref int[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeUIntArrayArray(ref uint[][] v) { throw new NotImplementedException(); }\r\n        public void CodeUIntArrayArrayArray(ref uint[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeLongArrayArray(ref long[][] v) { throw new NotImplementedException(); }\r\n        public void CodeLongArrayArrayArray(ref long[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeULongArrayArray(ref ulong[][] v) { throw new NotImplementedException(); }\r\n        public void CodeULongArrayArrayArray(ref ulong[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeFloatArrayArray(ref float[][] v) { throw new NotImplementedException(); }\r\n        public void CodeFloatArrayArrayArray(ref float[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArrayArray(ref double[][] v) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArrayArrayArray(ref double[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeFractionArrayArray(ref Fraction[][] v) { throw new NotImplementedException(); }\r\n        public void CodeFractionArrayArrayArray(ref Fraction[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2iArrayArray(ref V2i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2iArrayArrayArray(ref V2i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArrayArray(ref V2l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArrayArrayArray(ref V2l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArrayArray(ref V2f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArrayArrayArray(ref V2f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArrayArray(ref V2d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArrayArrayArray(ref V2d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArrayArray(ref V3i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArrayArrayArray(ref V3i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArrayArray(ref V3l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArrayArrayArray(ref V3l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArrayArray(ref V3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArrayArrayArray(ref V3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArrayArray(ref V3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArrayArrayArray(ref V3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArrayArray(ref V4i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArrayArrayArray(ref V4i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArrayArray(ref V4l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArrayArrayArray(ref V4l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArrayArray(ref V4f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArrayArrayArray(ref V4f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArrayArray(ref V4d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArrayArrayArray(ref V4d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArrayArray(ref M22i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArrayArrayArray(ref M22i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArrayArray(ref M22l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArrayArrayArray(ref M22l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArrayArray(ref M22f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArrayArrayArray(ref M22f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArrayArray(ref M22d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArrayArrayArray(ref M22d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArrayArray(ref M23i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArrayArrayArray(ref M23i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArrayArray(ref M23l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArrayArrayArray(ref M23l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArrayArray(ref M23f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArrayArrayArray(ref M23f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArrayArray(ref M23d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArrayArrayArray(ref M23d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArrayArray(ref M33i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArrayArrayArray(ref M33i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArrayArray(ref M33l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArrayArrayArray(ref M33l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArrayArray(ref M33f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArrayArrayArray(ref M33f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArrayArray(ref M33d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArrayArrayArray(ref M33d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArrayArray(ref M34i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArrayArrayArray(ref M34i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArrayArray(ref M34l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArrayArrayArray(ref M34l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArrayArray(ref M34f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArrayArrayArray(ref M34f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArrayArray(ref M34d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArrayArrayArray(ref M34d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArrayArray(ref M44i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArrayArrayArray(ref M44i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArrayArray(ref M44l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArrayArrayArray(ref M44l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArrayArray(ref M44f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArrayArrayArray(ref M44f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArrayArray(ref M44d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArrayArrayArray(ref M44d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArrayArray(ref C3b[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArrayArrayArray(ref C3b[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArrayArray(ref C3us[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArrayArrayArray(ref C3us[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArrayArray(ref C3ui[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArrayArrayArray(ref C3ui[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArrayArray(ref C3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArrayArrayArray(ref C3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArrayArray(ref C3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArrayArrayArray(ref C3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArrayArray(ref C4b[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArrayArrayArray(ref C4b[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArrayArray(ref C4us[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArrayArrayArray(ref C4us[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArrayArray(ref C4ui[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArrayArrayArray(ref C4ui[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArrayArray(ref C4f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArrayArrayArray(ref C4f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArrayArray(ref C4d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArrayArrayArray(ref C4d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArrayArray(ref Range1b[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArrayArrayArray(ref Range1b[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArrayArray(ref Range1sb[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArrayArrayArray(ref Range1sb[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArrayArray(ref Range1s[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArrayArrayArray(ref Range1s[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArrayArray(ref Range1us[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArrayArrayArray(ref Range1us[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArrayArray(ref Range1i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArrayArrayArray(ref Range1i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArrayArray(ref Range1ui[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArrayArrayArray(ref Range1ui[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArrayArray(ref Range1l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArrayArrayArray(ref Range1l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArrayArray(ref Range1ul[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArrayArrayArray(ref Range1ul[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArrayArray(ref Range1f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArrayArrayArray(ref Range1f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArrayArray(ref Range1d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArrayArrayArray(ref Range1d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArrayArray(ref Box2i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArrayArrayArray(ref Box2i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArrayArray(ref Box2l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArrayArrayArray(ref Box2l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArrayArray(ref Box2f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArrayArrayArray(ref Box2f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArrayArray(ref Box2d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArrayArrayArray(ref Box2d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArrayArray(ref Box3i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArrayArrayArray(ref Box3i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArrayArray(ref Box3l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArrayArrayArray(ref Box3l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArrayArray(ref Box3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArrayArrayArray(ref Box3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArrayArray(ref Box3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArrayArrayArray(ref Box3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArrayArray(ref Euclidean3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArrayArrayArray(ref Euclidean3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArrayArray(ref Euclidean3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArrayArrayArray(ref Euclidean3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArrayArray(ref Rot2f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArrayArrayArray(ref Rot2f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArrayArray(ref Rot2d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArrayArrayArray(ref Rot2d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArrayArray(ref Rot3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArrayArrayArray(ref Rot3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArrayArray(ref Rot3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArrayArrayArray(ref Rot3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArrayArray(ref Scale3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArrayArrayArray(ref Scale3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArrayArray(ref Scale3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArrayArrayArray(ref Scale3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArrayArray(ref Shift3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArrayArrayArray(ref Shift3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArrayArray(ref Shift3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArrayArrayArray(ref Shift3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArrayArray(ref Trafo2f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArrayArrayArray(ref Trafo2f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArrayArray(ref Trafo2d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArrayArrayArray(ref Trafo2d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArrayArray(ref Trafo3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArrayArrayArray(ref Trafo3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArrayArray(ref Trafo3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArrayArrayArray(ref Trafo3d[][][] v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Lists\r\n\r\n        public void CodeList_of_V2i_(ref List<V2i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V2ui_(ref List<V2ui> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V2l_(ref List<V2l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V2f_(ref List<V2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V2d_(ref List<V2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V3i_(ref List<V3i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V3ui_(ref List<V3ui> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V3l_(ref List<V3l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V3f_(ref List<V3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V3d_(ref List<V3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V4i_(ref List<V4i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V4ui_(ref List<V4ui> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V4l_(ref List<V4l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V4f_(ref List<V4f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_V4d_(ref List<V4d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M22i_(ref List<M22i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M22l_(ref List<M22l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M22f_(ref List<M22f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M22d_(ref List<M22d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M23i_(ref List<M23i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M23l_(ref List<M23l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M23f_(ref List<M23f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M23d_(ref List<M23d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M33i_(ref List<M33i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M33l_(ref List<M33l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M33f_(ref List<M33f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M33d_(ref List<M33d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M34i_(ref List<M34i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M34l_(ref List<M34l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M34f_(ref List<M34f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M34d_(ref List<M34d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M44i_(ref List<M44i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M44l_(ref List<M44l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M44f_(ref List<M44f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_M44d_(ref List<M44d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1b_(ref List<Range1b> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1sb_(ref List<Range1sb> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1s_(ref List<Range1s> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1us_(ref List<Range1us> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1i_(ref List<Range1i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1ui_(ref List<Range1ui> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1l_(ref List<Range1l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1ul_(ref List<Range1ul> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1f_(ref List<Range1f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Range1d_(ref List<Range1d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Box2i_(ref List<Box2i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Box2l_(ref List<Box2l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Box2f_(ref List<Box2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Box2d_(ref List<Box2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Box3i_(ref List<Box3i> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Box3l_(ref List<Box3l> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Box3f_(ref List<Box3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Box3d_(ref List<Box3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C3b_(ref List<C3b> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C3us_(ref List<C3us> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C3ui_(ref List<C3ui> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C3f_(ref List<C3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C3d_(ref List<C3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C4b_(ref List<C4b> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C4us_(ref List<C4us> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C4ui_(ref List<C4ui> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C4f_(ref List<C4f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_C4d_(ref List<C4d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Euclidean3f_(ref List<Euclidean3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Euclidean3d_(ref List<Euclidean3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Rot2f_(ref List<Rot2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Rot2d_(ref List<Rot2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Rot3f_(ref List<Rot3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Rot3d_(ref List<Rot3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Scale3f_(ref List<Scale3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Scale3d_(ref List<Scale3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Shift3f_(ref List<Shift3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Shift3d_(ref List<Shift3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Trafo2f_(ref List<Trafo2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Trafo2d_(ref List<Trafo2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Trafo3f_(ref List<Trafo3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Trafo3d_(ref List<Trafo3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Circle2d_(ref List<Circle2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Line2d_(ref List<Line2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Line3d_(ref List<Line3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Plane2d_(ref List<Plane2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Plane3d_(ref List<Plane3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_PlaneWithPoint3d_(ref List<PlaneWithPoint3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Quad2d_(ref List<Quad2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Quad3d_(ref List<Quad3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Ray2d_(ref List<Ray2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Ray3d_(ref List<Ray3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Sphere3d_(ref List<Sphere3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Triangle2d_(ref List<Triangle2d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Triangle3d_(ref List<Triangle3d> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Circle2f_(ref List<Circle2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Line2f_(ref List<Line2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Line3f_(ref List<Line3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Plane2f_(ref List<Plane2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Plane3f_(ref List<Plane3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_PlaneWithPoint3f_(ref List<PlaneWithPoint3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Quad2f_(ref List<Quad2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Quad3f_(ref List<Quad3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Ray2f_(ref List<Ray2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Ray3f_(ref List<Ray3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Sphere3f_(ref List<Sphere3f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Triangle2f_(ref List<Triangle2f> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Triangle3f_(ref List<Triangle3f> v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Arrays of Tensors\r\n\r\n        public void CodeVector_of_Byte_Array(ref Vector<byte>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_SByte_Array(ref Vector<sbyte>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Short_Array(ref Vector<short>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_UShort_Array(ref Vector<ushort>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Int_Array(ref Vector<int>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_UInt_Array(ref Vector<uint>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Long_Array(ref Vector<long>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_ULong_Array(ref Vector<ulong>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Float_Array(ref Vector<float>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Double_Array(ref Vector<double>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Fraction_Array(ref Vector<Fraction>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V2i_Array(ref Vector<V2i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V2l_Array(ref Vector<V2l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V2f_Array(ref Vector<V2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V2d_Array(ref Vector<V2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V3i_Array(ref Vector<V3i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V3l_Array(ref Vector<V3l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V3f_Array(ref Vector<V3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V3d_Array(ref Vector<V3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V4i_Array(ref Vector<V4i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V4l_Array(ref Vector<V4l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V4f_Array(ref Vector<V4f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_V4d_Array(ref Vector<V4d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M22i_Array(ref Vector<M22i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M22l_Array(ref Vector<M22l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M22f_Array(ref Vector<M22f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M22d_Array(ref Vector<M22d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M23i_Array(ref Vector<M23i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M23l_Array(ref Vector<M23l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M23f_Array(ref Vector<M23f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M23d_Array(ref Vector<M23d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M33i_Array(ref Vector<M33i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M33l_Array(ref Vector<M33l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M33f_Array(ref Vector<M33f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M33d_Array(ref Vector<M33d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M34i_Array(ref Vector<M34i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M34l_Array(ref Vector<M34l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M34f_Array(ref Vector<M34f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M34d_Array(ref Vector<M34d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M44i_Array(ref Vector<M44i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M44l_Array(ref Vector<M44l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M44f_Array(ref Vector<M44f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_M44d_Array(ref Vector<M44d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C3b_Array(ref Vector<C3b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C3us_Array(ref Vector<C3us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C3ui_Array(ref Vector<C3ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C3f_Array(ref Vector<C3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C3d_Array(ref Vector<C3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C4b_Array(ref Vector<C4b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C4us_Array(ref Vector<C4us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C4ui_Array(ref Vector<C4ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C4f_Array(ref Vector<C4f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_C4d_Array(ref Vector<C4d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1b_Array(ref Vector<Range1b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1sb_Array(ref Vector<Range1sb>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1s_Array(ref Vector<Range1s>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1us_Array(ref Vector<Range1us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1i_Array(ref Vector<Range1i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1ui_Array(ref Vector<Range1ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1l_Array(ref Vector<Range1l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1ul_Array(ref Vector<Range1ul>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1f_Array(ref Vector<Range1f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Range1d_Array(ref Vector<Range1d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Box2i_Array(ref Vector<Box2i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Box2l_Array(ref Vector<Box2l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Box2f_Array(ref Vector<Box2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Box2d_Array(ref Vector<Box2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Box3i_Array(ref Vector<Box3i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Box3l_Array(ref Vector<Box3l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Box3f_Array(ref Vector<Box3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Box3d_Array(ref Vector<Box3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Euclidean3f_Array(ref Vector<Euclidean3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Euclidean3d_Array(ref Vector<Euclidean3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Rot2f_Array(ref Vector<Rot2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Rot2d_Array(ref Vector<Rot2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Rot3f_Array(ref Vector<Rot3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Rot3d_Array(ref Vector<Rot3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Scale3f_Array(ref Vector<Scale3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Scale3d_Array(ref Vector<Scale3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Shift3f_Array(ref Vector<Shift3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Shift3d_Array(ref Vector<Shift3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Trafo2f_Array(ref Vector<Trafo2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Trafo2d_Array(ref Vector<Trafo2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Trafo3f_Array(ref Vector<Trafo3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Trafo3d_Array(ref Vector<Trafo3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Bool_Array(ref Vector<bool>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Char_Array(ref Vector<char>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_String_Array(ref Vector<string>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Type_Array(ref Vector<Type>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Guid_Array(ref Vector<Guid>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Symbol_Array(ref Vector<Symbol>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Circle2d_Array(ref Vector<Circle2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Line2d_Array(ref Vector<Line2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Line3d_Array(ref Vector<Line3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Plane2d_Array(ref Vector<Plane2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Plane3d_Array(ref Vector<Plane3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_PlaneWithPoint3d_Array(ref Vector<PlaneWithPoint3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Quad2d_Array(ref Vector<Quad2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Quad3d_Array(ref Vector<Quad3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Ray2d_Array(ref Vector<Ray2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Ray3d_Array(ref Vector<Ray3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Sphere3d_Array(ref Vector<Sphere3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Triangle2d_Array(ref Vector<Triangle2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Triangle3d_Array(ref Vector<Triangle3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Circle2f_Array(ref Vector<Circle2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Line2f_Array(ref Vector<Line2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Line3f_Array(ref Vector<Line3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Plane2f_Array(ref Vector<Plane2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Plane3f_Array(ref Vector<Plane3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_PlaneWithPoint3f_Array(ref Vector<PlaneWithPoint3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Quad2f_Array(ref Vector<Quad2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Quad3f_Array(ref Vector<Quad3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Ray2f_Array(ref Vector<Ray2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Ray3f_Array(ref Vector<Ray3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Sphere3f_Array(ref Vector<Sphere3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Triangle2f_Array(ref Vector<Triangle2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVector_of_Triangle3f_Array(ref Vector<Triangle3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Byte_Array(ref Matrix<byte>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_SByte_Array(ref Matrix<sbyte>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Short_Array(ref Matrix<short>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_UShort_Array(ref Matrix<ushort>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Int_Array(ref Matrix<int>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_UInt_Array(ref Matrix<uint>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Long_Array(ref Matrix<long>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_ULong_Array(ref Matrix<ulong>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Float_Array(ref Matrix<float>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Double_Array(ref Matrix<double>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Fraction_Array(ref Matrix<Fraction>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V2i_Array(ref Matrix<V2i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V2l_Array(ref Matrix<V2l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V2f_Array(ref Matrix<V2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V2d_Array(ref Matrix<V2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V3i_Array(ref Matrix<V3i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V3l_Array(ref Matrix<V3l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V3f_Array(ref Matrix<V3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V3d_Array(ref Matrix<V3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V4i_Array(ref Matrix<V4i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V4l_Array(ref Matrix<V4l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V4f_Array(ref Matrix<V4f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_V4d_Array(ref Matrix<V4d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M22i_Array(ref Matrix<M22i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M22l_Array(ref Matrix<M22l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M22f_Array(ref Matrix<M22f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M22d_Array(ref Matrix<M22d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M23i_Array(ref Matrix<M23i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M23l_Array(ref Matrix<M23l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M23f_Array(ref Matrix<M23f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M23d_Array(ref Matrix<M23d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M33i_Array(ref Matrix<M33i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M33l_Array(ref Matrix<M33l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M33f_Array(ref Matrix<M33f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M33d_Array(ref Matrix<M33d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M34i_Array(ref Matrix<M34i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M34l_Array(ref Matrix<M34l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M34f_Array(ref Matrix<M34f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M34d_Array(ref Matrix<M34d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M44i_Array(ref Matrix<M44i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M44l_Array(ref Matrix<M44l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M44f_Array(ref Matrix<M44f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_M44d_Array(ref Matrix<M44d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C3b_Array(ref Matrix<C3b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C3us_Array(ref Matrix<C3us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C3ui_Array(ref Matrix<C3ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C3f_Array(ref Matrix<C3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C3d_Array(ref Matrix<C3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C4b_Array(ref Matrix<C4b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C4us_Array(ref Matrix<C4us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C4ui_Array(ref Matrix<C4ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C4f_Array(ref Matrix<C4f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_C4d_Array(ref Matrix<C4d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1b_Array(ref Matrix<Range1b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1sb_Array(ref Matrix<Range1sb>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1s_Array(ref Matrix<Range1s>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1us_Array(ref Matrix<Range1us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1i_Array(ref Matrix<Range1i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1ui_Array(ref Matrix<Range1ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1l_Array(ref Matrix<Range1l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1ul_Array(ref Matrix<Range1ul>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1f_Array(ref Matrix<Range1f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Range1d_Array(ref Matrix<Range1d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Box2i_Array(ref Matrix<Box2i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Box2l_Array(ref Matrix<Box2l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Box2f_Array(ref Matrix<Box2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Box2d_Array(ref Matrix<Box2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Box3i_Array(ref Matrix<Box3i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Box3l_Array(ref Matrix<Box3l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Box3f_Array(ref Matrix<Box3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Box3d_Array(ref Matrix<Box3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Euclidean3f_Array(ref Matrix<Euclidean3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Euclidean3d_Array(ref Matrix<Euclidean3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Rot2f_Array(ref Matrix<Rot2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Rot2d_Array(ref Matrix<Rot2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Rot3f_Array(ref Matrix<Rot3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Rot3d_Array(ref Matrix<Rot3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Scale3f_Array(ref Matrix<Scale3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Scale3d_Array(ref Matrix<Scale3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Shift3f_Array(ref Matrix<Shift3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Shift3d_Array(ref Matrix<Shift3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Trafo2f_Array(ref Matrix<Trafo2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Trafo2d_Array(ref Matrix<Trafo2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Trafo3f_Array(ref Matrix<Trafo3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Trafo3d_Array(ref Matrix<Trafo3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Bool_Array(ref Matrix<bool>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Char_Array(ref Matrix<char>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_String_Array(ref Matrix<string>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Type_Array(ref Matrix<Type>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Guid_Array(ref Matrix<Guid>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Symbol_Array(ref Matrix<Symbol>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Circle2d_Array(ref Matrix<Circle2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Line2d_Array(ref Matrix<Line2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Line3d_Array(ref Matrix<Line3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Plane2d_Array(ref Matrix<Plane2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Plane3d_Array(ref Matrix<Plane3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_PlaneWithPoint3d_Array(ref Matrix<PlaneWithPoint3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Quad2d_Array(ref Matrix<Quad2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Quad3d_Array(ref Matrix<Quad3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Ray2d_Array(ref Matrix<Ray2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Ray3d_Array(ref Matrix<Ray3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Sphere3d_Array(ref Matrix<Sphere3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Triangle2d_Array(ref Matrix<Triangle2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Triangle3d_Array(ref Matrix<Triangle3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Circle2f_Array(ref Matrix<Circle2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Line2f_Array(ref Matrix<Line2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Line3f_Array(ref Matrix<Line3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Plane2f_Array(ref Matrix<Plane2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Plane3f_Array(ref Matrix<Plane3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_PlaneWithPoint3f_Array(ref Matrix<PlaneWithPoint3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Quad2f_Array(ref Matrix<Quad2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Quad3f_Array(ref Matrix<Quad3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Ray2f_Array(ref Matrix<Ray2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Ray3f_Array(ref Matrix<Ray3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Sphere3f_Array(ref Matrix<Sphere3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Triangle2f_Array(ref Matrix<Triangle2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeMatrix_of_Triangle3f_Array(ref Matrix<Triangle3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Byte_Array(ref Volume<byte>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_SByte_Array(ref Volume<sbyte>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Short_Array(ref Volume<short>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_UShort_Array(ref Volume<ushort>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Int_Array(ref Volume<int>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_UInt_Array(ref Volume<uint>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Long_Array(ref Volume<long>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_ULong_Array(ref Volume<ulong>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Float_Array(ref Volume<float>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Double_Array(ref Volume<double>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Fraction_Array(ref Volume<Fraction>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V2i_Array(ref Volume<V2i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V2l_Array(ref Volume<V2l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V2f_Array(ref Volume<V2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V2d_Array(ref Volume<V2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V3i_Array(ref Volume<V3i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V3l_Array(ref Volume<V3l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V3f_Array(ref Volume<V3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V3d_Array(ref Volume<V3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V4i_Array(ref Volume<V4i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V4l_Array(ref Volume<V4l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V4f_Array(ref Volume<V4f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_V4d_Array(ref Volume<V4d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M22i_Array(ref Volume<M22i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M22l_Array(ref Volume<M22l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M22f_Array(ref Volume<M22f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M22d_Array(ref Volume<M22d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M23i_Array(ref Volume<M23i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M23l_Array(ref Volume<M23l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M23f_Array(ref Volume<M23f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M23d_Array(ref Volume<M23d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M33i_Array(ref Volume<M33i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M33l_Array(ref Volume<M33l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M33f_Array(ref Volume<M33f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M33d_Array(ref Volume<M33d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M34i_Array(ref Volume<M34i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M34l_Array(ref Volume<M34l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M34f_Array(ref Volume<M34f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M34d_Array(ref Volume<M34d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M44i_Array(ref Volume<M44i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M44l_Array(ref Volume<M44l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M44f_Array(ref Volume<M44f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_M44d_Array(ref Volume<M44d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C3b_Array(ref Volume<C3b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C3us_Array(ref Volume<C3us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C3ui_Array(ref Volume<C3ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C3f_Array(ref Volume<C3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C3d_Array(ref Volume<C3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C4b_Array(ref Volume<C4b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C4us_Array(ref Volume<C4us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C4ui_Array(ref Volume<C4ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C4f_Array(ref Volume<C4f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_C4d_Array(ref Volume<C4d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1b_Array(ref Volume<Range1b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1sb_Array(ref Volume<Range1sb>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1s_Array(ref Volume<Range1s>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1us_Array(ref Volume<Range1us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1i_Array(ref Volume<Range1i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1ui_Array(ref Volume<Range1ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1l_Array(ref Volume<Range1l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1ul_Array(ref Volume<Range1ul>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1f_Array(ref Volume<Range1f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Range1d_Array(ref Volume<Range1d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Box2i_Array(ref Volume<Box2i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Box2l_Array(ref Volume<Box2l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Box2f_Array(ref Volume<Box2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Box2d_Array(ref Volume<Box2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Box3i_Array(ref Volume<Box3i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Box3l_Array(ref Volume<Box3l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Box3f_Array(ref Volume<Box3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Box3d_Array(ref Volume<Box3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Euclidean3f_Array(ref Volume<Euclidean3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Euclidean3d_Array(ref Volume<Euclidean3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Rot2f_Array(ref Volume<Rot2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Rot2d_Array(ref Volume<Rot2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Rot3f_Array(ref Volume<Rot3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Rot3d_Array(ref Volume<Rot3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Scale3f_Array(ref Volume<Scale3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Scale3d_Array(ref Volume<Scale3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Shift3f_Array(ref Volume<Shift3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Shift3d_Array(ref Volume<Shift3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Trafo2f_Array(ref Volume<Trafo2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Trafo2d_Array(ref Volume<Trafo2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Trafo3f_Array(ref Volume<Trafo3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Trafo3d_Array(ref Volume<Trafo3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Bool_Array(ref Volume<bool>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Char_Array(ref Volume<char>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_String_Array(ref Volume<string>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Type_Array(ref Volume<Type>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Guid_Array(ref Volume<Guid>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Symbol_Array(ref Volume<Symbol>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Circle2d_Array(ref Volume<Circle2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Line2d_Array(ref Volume<Line2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Line3d_Array(ref Volume<Line3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Plane2d_Array(ref Volume<Plane2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Plane3d_Array(ref Volume<Plane3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_PlaneWithPoint3d_Array(ref Volume<PlaneWithPoint3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Quad2d_Array(ref Volume<Quad2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Quad3d_Array(ref Volume<Quad3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Ray2d_Array(ref Volume<Ray2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Ray3d_Array(ref Volume<Ray3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Sphere3d_Array(ref Volume<Sphere3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Triangle2d_Array(ref Volume<Triangle2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Triangle3d_Array(ref Volume<Triangle3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Circle2f_Array(ref Volume<Circle2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Line2f_Array(ref Volume<Line2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Line3f_Array(ref Volume<Line3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Plane2f_Array(ref Volume<Plane2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Plane3f_Array(ref Volume<Plane3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_PlaneWithPoint3f_Array(ref Volume<PlaneWithPoint3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Quad2f_Array(ref Volume<Quad2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Quad3f_Array(ref Volume<Quad3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Ray2f_Array(ref Volume<Ray2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Ray3f_Array(ref Volume<Ray3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Sphere3f_Array(ref Volume<Sphere3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Triangle2f_Array(ref Volume<Triangle2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeVolume_of_Triangle3f_Array(ref Volume<Triangle3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Byte_Array(ref Tensor<byte>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_SByte_Array(ref Tensor<sbyte>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Short_Array(ref Tensor<short>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_UShort_Array(ref Tensor<ushort>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Int_Array(ref Tensor<int>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_UInt_Array(ref Tensor<uint>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Long_Array(ref Tensor<long>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_ULong_Array(ref Tensor<ulong>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Float_Array(ref Tensor<float>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Double_Array(ref Tensor<double>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Fraction_Array(ref Tensor<Fraction>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V2i_Array(ref Tensor<V2i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V2l_Array(ref Tensor<V2l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V2f_Array(ref Tensor<V2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V2d_Array(ref Tensor<V2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V3i_Array(ref Tensor<V3i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V3l_Array(ref Tensor<V3l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V3f_Array(ref Tensor<V3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V3d_Array(ref Tensor<V3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V4i_Array(ref Tensor<V4i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V4l_Array(ref Tensor<V4l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V4f_Array(ref Tensor<V4f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_V4d_Array(ref Tensor<V4d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M22i_Array(ref Tensor<M22i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M22l_Array(ref Tensor<M22l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M22f_Array(ref Tensor<M22f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M22d_Array(ref Tensor<M22d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M23i_Array(ref Tensor<M23i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M23l_Array(ref Tensor<M23l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M23f_Array(ref Tensor<M23f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M23d_Array(ref Tensor<M23d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M33i_Array(ref Tensor<M33i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M33l_Array(ref Tensor<M33l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M33f_Array(ref Tensor<M33f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M33d_Array(ref Tensor<M33d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M34i_Array(ref Tensor<M34i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M34l_Array(ref Tensor<M34l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M34f_Array(ref Tensor<M34f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M34d_Array(ref Tensor<M34d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M44i_Array(ref Tensor<M44i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M44l_Array(ref Tensor<M44l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M44f_Array(ref Tensor<M44f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_M44d_Array(ref Tensor<M44d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C3b_Array(ref Tensor<C3b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C3us_Array(ref Tensor<C3us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C3ui_Array(ref Tensor<C3ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C3f_Array(ref Tensor<C3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C3d_Array(ref Tensor<C3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C4b_Array(ref Tensor<C4b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C4us_Array(ref Tensor<C4us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C4ui_Array(ref Tensor<C4ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C4f_Array(ref Tensor<C4f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_C4d_Array(ref Tensor<C4d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1b_Array(ref Tensor<Range1b>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1sb_Array(ref Tensor<Range1sb>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1s_Array(ref Tensor<Range1s>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1us_Array(ref Tensor<Range1us>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1i_Array(ref Tensor<Range1i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1ui_Array(ref Tensor<Range1ui>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1l_Array(ref Tensor<Range1l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1ul_Array(ref Tensor<Range1ul>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1f_Array(ref Tensor<Range1f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Range1d_Array(ref Tensor<Range1d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Box2i_Array(ref Tensor<Box2i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Box2l_Array(ref Tensor<Box2l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Box2f_Array(ref Tensor<Box2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Box2d_Array(ref Tensor<Box2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Box3i_Array(ref Tensor<Box3i>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Box3l_Array(ref Tensor<Box3l>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Box3f_Array(ref Tensor<Box3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Box3d_Array(ref Tensor<Box3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Euclidean3f_Array(ref Tensor<Euclidean3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Euclidean3d_Array(ref Tensor<Euclidean3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Rot2f_Array(ref Tensor<Rot2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Rot2d_Array(ref Tensor<Rot2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Rot3f_Array(ref Tensor<Rot3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Rot3d_Array(ref Tensor<Rot3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Scale3f_Array(ref Tensor<Scale3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Scale3d_Array(ref Tensor<Scale3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Shift3f_Array(ref Tensor<Shift3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Shift3d_Array(ref Tensor<Shift3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Trafo2f_Array(ref Tensor<Trafo2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Trafo2d_Array(ref Tensor<Trafo2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Trafo3f_Array(ref Tensor<Trafo3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Trafo3d_Array(ref Tensor<Trafo3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Bool_Array(ref Tensor<bool>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Char_Array(ref Tensor<char>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_String_Array(ref Tensor<string>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Type_Array(ref Tensor<Type>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Guid_Array(ref Tensor<Guid>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Symbol_Array(ref Tensor<Symbol>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Circle2d_Array(ref Tensor<Circle2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Line2d_Array(ref Tensor<Line2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Line3d_Array(ref Tensor<Line3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Plane2d_Array(ref Tensor<Plane2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Plane3d_Array(ref Tensor<Plane3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_PlaneWithPoint3d_Array(ref Tensor<PlaneWithPoint3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Quad2d_Array(ref Tensor<Quad2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Quad3d_Array(ref Tensor<Quad3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Ray2d_Array(ref Tensor<Ray2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Ray3d_Array(ref Tensor<Ray3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Sphere3d_Array(ref Tensor<Sphere3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Triangle2d_Array(ref Tensor<Triangle2d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Triangle3d_Array(ref Tensor<Triangle3d>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Circle2f_Array(ref Tensor<Circle2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Line2f_Array(ref Tensor<Line2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Line3f_Array(ref Tensor<Line3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Plane2f_Array(ref Tensor<Plane2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Plane3f_Array(ref Tensor<Plane3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_PlaneWithPoint3f_Array(ref Tensor<PlaneWithPoint3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Quad2f_Array(ref Tensor<Quad2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Quad3f_Array(ref Tensor<Quad3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Ray2f_Array(ref Tensor<Ray2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Ray3f_Array(ref Tensor<Ray3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Sphere3f_Array(ref Tensor<Sphere3f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Triangle2f_Array(ref Tensor<Triangle2f>[] v) { throw new NotImplementedException(); }\r\n        public void CodeTensor_of_Triangle3f_Array(ref Tensor<Triangle3f>[] v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Lists of Tensors\r\n\r\n        public void CodeList_of_Vector_of_Byte__(ref List<Vector<byte>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_SByte__(ref List<Vector<sbyte>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Short__(ref List<Vector<short>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_UShort__(ref List<Vector<ushort>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Int__(ref List<Vector<int>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_UInt__(ref List<Vector<uint>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Long__(ref List<Vector<long>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_ULong__(ref List<Vector<ulong>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Float__(ref List<Vector<float>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Double__(ref List<Vector<double>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Fraction__(ref List<Vector<Fraction>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V2i__(ref List<Vector<V2i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V2l__(ref List<Vector<V2l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V2f__(ref List<Vector<V2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V2d__(ref List<Vector<V2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V3i__(ref List<Vector<V3i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V3l__(ref List<Vector<V3l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V3f__(ref List<Vector<V3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V3d__(ref List<Vector<V3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V4i__(ref List<Vector<V4i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V4l__(ref List<Vector<V4l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V4f__(ref List<Vector<V4f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_V4d__(ref List<Vector<V4d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M22i__(ref List<Vector<M22i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M22l__(ref List<Vector<M22l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M22f__(ref List<Vector<M22f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M22d__(ref List<Vector<M22d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M23i__(ref List<Vector<M23i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M23l__(ref List<Vector<M23l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M23f__(ref List<Vector<M23f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M23d__(ref List<Vector<M23d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M33i__(ref List<Vector<M33i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M33l__(ref List<Vector<M33l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M33f__(ref List<Vector<M33f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M33d__(ref List<Vector<M33d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M34i__(ref List<Vector<M34i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M34l__(ref List<Vector<M34l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M34f__(ref List<Vector<M34f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M34d__(ref List<Vector<M34d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M44i__(ref List<Vector<M44i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M44l__(ref List<Vector<M44l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M44f__(ref List<Vector<M44f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_M44d__(ref List<Vector<M44d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C3b__(ref List<Vector<C3b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C3us__(ref List<Vector<C3us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C3ui__(ref List<Vector<C3ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C3f__(ref List<Vector<C3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C3d__(ref List<Vector<C3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C4b__(ref List<Vector<C4b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C4us__(ref List<Vector<C4us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C4ui__(ref List<Vector<C4ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C4f__(ref List<Vector<C4f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_C4d__(ref List<Vector<C4d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1b__(ref List<Vector<Range1b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1sb__(ref List<Vector<Range1sb>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1s__(ref List<Vector<Range1s>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1us__(ref List<Vector<Range1us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1i__(ref List<Vector<Range1i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1ui__(ref List<Vector<Range1ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1l__(ref List<Vector<Range1l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1ul__(ref List<Vector<Range1ul>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1f__(ref List<Vector<Range1f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Range1d__(ref List<Vector<Range1d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Box2i__(ref List<Vector<Box2i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Box2l__(ref List<Vector<Box2l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Box2f__(ref List<Vector<Box2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Box2d__(ref List<Vector<Box2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Box3i__(ref List<Vector<Box3i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Box3l__(ref List<Vector<Box3l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Box3f__(ref List<Vector<Box3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Box3d__(ref List<Vector<Box3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Euclidean3f__(ref List<Vector<Euclidean3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Euclidean3d__(ref List<Vector<Euclidean3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Rot2f__(ref List<Vector<Rot2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Rot2d__(ref List<Vector<Rot2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Rot3f__(ref List<Vector<Rot3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Rot3d__(ref List<Vector<Rot3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Scale3f__(ref List<Vector<Scale3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Scale3d__(ref List<Vector<Scale3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Shift3f__(ref List<Vector<Shift3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Shift3d__(ref List<Vector<Shift3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Trafo2f__(ref List<Vector<Trafo2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Trafo2d__(ref List<Vector<Trafo2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Trafo3f__(ref List<Vector<Trafo3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Trafo3d__(ref List<Vector<Trafo3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Bool__(ref List<Vector<bool>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Char__(ref List<Vector<char>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_String__(ref List<Vector<string>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Type__(ref List<Vector<Type>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Guid__(ref List<Vector<Guid>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Symbol__(ref List<Vector<Symbol>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Circle2d__(ref List<Vector<Circle2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Line2d__(ref List<Vector<Line2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Line3d__(ref List<Vector<Line3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Plane2d__(ref List<Vector<Plane2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Plane3d__(ref List<Vector<Plane3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3d__(ref List<Vector<PlaneWithPoint3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Quad2d__(ref List<Vector<Quad2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Quad3d__(ref List<Vector<Quad3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Ray2d__(ref List<Vector<Ray2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Ray3d__(ref List<Vector<Ray3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Sphere3d__(ref List<Vector<Sphere3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Triangle2d__(ref List<Vector<Triangle2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Triangle3d__(ref List<Vector<Triangle3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Circle2f__(ref List<Vector<Circle2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Line2f__(ref List<Vector<Line2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Line3f__(ref List<Vector<Line3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Plane2f__(ref List<Vector<Plane2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Plane3f__(ref List<Vector<Plane3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3f__(ref List<Vector<PlaneWithPoint3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Quad2f__(ref List<Vector<Quad2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Quad3f__(ref List<Vector<Quad3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Ray2f__(ref List<Vector<Ray2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Ray3f__(ref List<Vector<Ray3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Sphere3f__(ref List<Vector<Sphere3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Triangle2f__(ref List<Vector<Triangle2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Vector_of_Triangle3f__(ref List<Vector<Triangle3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Byte__(ref List<Matrix<byte>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_SByte__(ref List<Matrix<sbyte>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Short__(ref List<Matrix<short>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_UShort__(ref List<Matrix<ushort>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Int__(ref List<Matrix<int>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_UInt__(ref List<Matrix<uint>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Long__(ref List<Matrix<long>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_ULong__(ref List<Matrix<ulong>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Float__(ref List<Matrix<float>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Double__(ref List<Matrix<double>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Fraction__(ref List<Matrix<Fraction>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V2i__(ref List<Matrix<V2i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V2l__(ref List<Matrix<V2l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V2f__(ref List<Matrix<V2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V2d__(ref List<Matrix<V2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V3i__(ref List<Matrix<V3i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V3l__(ref List<Matrix<V3l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V3f__(ref List<Matrix<V3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V3d__(ref List<Matrix<V3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V4i__(ref List<Matrix<V4i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V4l__(ref List<Matrix<V4l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V4f__(ref List<Matrix<V4f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_V4d__(ref List<Matrix<V4d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M22i__(ref List<Matrix<M22i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M22l__(ref List<Matrix<M22l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M22f__(ref List<Matrix<M22f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M22d__(ref List<Matrix<M22d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M23i__(ref List<Matrix<M23i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M23l__(ref List<Matrix<M23l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M23f__(ref List<Matrix<M23f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M23d__(ref List<Matrix<M23d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M33i__(ref List<Matrix<M33i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M33l__(ref List<Matrix<M33l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M33f__(ref List<Matrix<M33f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M33d__(ref List<Matrix<M33d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M34i__(ref List<Matrix<M34i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M34l__(ref List<Matrix<M34l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M34f__(ref List<Matrix<M34f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M34d__(ref List<Matrix<M34d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M44i__(ref List<Matrix<M44i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M44l__(ref List<Matrix<M44l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M44f__(ref List<Matrix<M44f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_M44d__(ref List<Matrix<M44d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C3b__(ref List<Matrix<C3b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C3us__(ref List<Matrix<C3us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C3ui__(ref List<Matrix<C3ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C3f__(ref List<Matrix<C3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C3d__(ref List<Matrix<C3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C4b__(ref List<Matrix<C4b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C4us__(ref List<Matrix<C4us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C4ui__(ref List<Matrix<C4ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C4f__(ref List<Matrix<C4f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_C4d__(ref List<Matrix<C4d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1b__(ref List<Matrix<Range1b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1sb__(ref List<Matrix<Range1sb>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1s__(ref List<Matrix<Range1s>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1us__(ref List<Matrix<Range1us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1i__(ref List<Matrix<Range1i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1ui__(ref List<Matrix<Range1ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1l__(ref List<Matrix<Range1l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1ul__(ref List<Matrix<Range1ul>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1f__(ref List<Matrix<Range1f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Range1d__(ref List<Matrix<Range1d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Box2i__(ref List<Matrix<Box2i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Box2l__(ref List<Matrix<Box2l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Box2f__(ref List<Matrix<Box2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Box2d__(ref List<Matrix<Box2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Box3i__(ref List<Matrix<Box3i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Box3l__(ref List<Matrix<Box3l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Box3f__(ref List<Matrix<Box3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Box3d__(ref List<Matrix<Box3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Euclidean3f__(ref List<Matrix<Euclidean3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Euclidean3d__(ref List<Matrix<Euclidean3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Rot2f__(ref List<Matrix<Rot2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Rot2d__(ref List<Matrix<Rot2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Rot3f__(ref List<Matrix<Rot3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Rot3d__(ref List<Matrix<Rot3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Scale3f__(ref List<Matrix<Scale3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Scale3d__(ref List<Matrix<Scale3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Shift3f__(ref List<Matrix<Shift3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Shift3d__(ref List<Matrix<Shift3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Trafo2f__(ref List<Matrix<Trafo2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Trafo2d__(ref List<Matrix<Trafo2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Trafo3f__(ref List<Matrix<Trafo3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Trafo3d__(ref List<Matrix<Trafo3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Bool__(ref List<Matrix<bool>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Char__(ref List<Matrix<char>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_String__(ref List<Matrix<string>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Type__(ref List<Matrix<Type>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Guid__(ref List<Matrix<Guid>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Symbol__(ref List<Matrix<Symbol>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Circle2d__(ref List<Matrix<Circle2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Line2d__(ref List<Matrix<Line2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Line3d__(ref List<Matrix<Line3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Plane2d__(ref List<Matrix<Plane2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Plane3d__(ref List<Matrix<Plane3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3d__(ref List<Matrix<PlaneWithPoint3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Quad2d__(ref List<Matrix<Quad2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Quad3d__(ref List<Matrix<Quad3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Ray2d__(ref List<Matrix<Ray2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Ray3d__(ref List<Matrix<Ray3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Sphere3d__(ref List<Matrix<Sphere3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Triangle2d__(ref List<Matrix<Triangle2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Triangle3d__(ref List<Matrix<Triangle3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Circle2f__(ref List<Matrix<Circle2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Line2f__(ref List<Matrix<Line2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Line3f__(ref List<Matrix<Line3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Plane2f__(ref List<Matrix<Plane2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Plane3f__(ref List<Matrix<Plane3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3f__(ref List<Matrix<PlaneWithPoint3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Quad2f__(ref List<Matrix<Quad2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Quad3f__(ref List<Matrix<Quad3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Ray2f__(ref List<Matrix<Ray2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Ray3f__(ref List<Matrix<Ray3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Sphere3f__(ref List<Matrix<Sphere3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Triangle2f__(ref List<Matrix<Triangle2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Matrix_of_Triangle3f__(ref List<Matrix<Triangle3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Byte__(ref List<Volume<byte>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_SByte__(ref List<Volume<sbyte>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Short__(ref List<Volume<short>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_UShort__(ref List<Volume<ushort>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Int__(ref List<Volume<int>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_UInt__(ref List<Volume<uint>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Long__(ref List<Volume<long>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_ULong__(ref List<Volume<ulong>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Float__(ref List<Volume<float>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Double__(ref List<Volume<double>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Fraction__(ref List<Volume<Fraction>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V2i__(ref List<Volume<V2i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V2l__(ref List<Volume<V2l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V2f__(ref List<Volume<V2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V2d__(ref List<Volume<V2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V3i__(ref List<Volume<V3i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V3l__(ref List<Volume<V3l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V3f__(ref List<Volume<V3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V3d__(ref List<Volume<V3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V4i__(ref List<Volume<V4i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V4l__(ref List<Volume<V4l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V4f__(ref List<Volume<V4f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_V4d__(ref List<Volume<V4d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M22i__(ref List<Volume<M22i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M22l__(ref List<Volume<M22l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M22f__(ref List<Volume<M22f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M22d__(ref List<Volume<M22d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M23i__(ref List<Volume<M23i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M23l__(ref List<Volume<M23l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M23f__(ref List<Volume<M23f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M23d__(ref List<Volume<M23d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M33i__(ref List<Volume<M33i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M33l__(ref List<Volume<M33l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M33f__(ref List<Volume<M33f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M33d__(ref List<Volume<M33d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M34i__(ref List<Volume<M34i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M34l__(ref List<Volume<M34l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M34f__(ref List<Volume<M34f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M34d__(ref List<Volume<M34d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M44i__(ref List<Volume<M44i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M44l__(ref List<Volume<M44l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M44f__(ref List<Volume<M44f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_M44d__(ref List<Volume<M44d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C3b__(ref List<Volume<C3b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C3us__(ref List<Volume<C3us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C3ui__(ref List<Volume<C3ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C3f__(ref List<Volume<C3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C3d__(ref List<Volume<C3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C4b__(ref List<Volume<C4b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C4us__(ref List<Volume<C4us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C4ui__(ref List<Volume<C4ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C4f__(ref List<Volume<C4f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_C4d__(ref List<Volume<C4d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1b__(ref List<Volume<Range1b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1sb__(ref List<Volume<Range1sb>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1s__(ref List<Volume<Range1s>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1us__(ref List<Volume<Range1us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1i__(ref List<Volume<Range1i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1ui__(ref List<Volume<Range1ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1l__(ref List<Volume<Range1l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1ul__(ref List<Volume<Range1ul>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1f__(ref List<Volume<Range1f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Range1d__(ref List<Volume<Range1d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Box2i__(ref List<Volume<Box2i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Box2l__(ref List<Volume<Box2l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Box2f__(ref List<Volume<Box2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Box2d__(ref List<Volume<Box2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Box3i__(ref List<Volume<Box3i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Box3l__(ref List<Volume<Box3l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Box3f__(ref List<Volume<Box3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Box3d__(ref List<Volume<Box3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Euclidean3f__(ref List<Volume<Euclidean3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Euclidean3d__(ref List<Volume<Euclidean3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Rot2f__(ref List<Volume<Rot2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Rot2d__(ref List<Volume<Rot2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Rot3f__(ref List<Volume<Rot3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Rot3d__(ref List<Volume<Rot3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Scale3f__(ref List<Volume<Scale3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Scale3d__(ref List<Volume<Scale3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Shift3f__(ref List<Volume<Shift3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Shift3d__(ref List<Volume<Shift3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Trafo2f__(ref List<Volume<Trafo2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Trafo2d__(ref List<Volume<Trafo2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Trafo3f__(ref List<Volume<Trafo3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Trafo3d__(ref List<Volume<Trafo3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Bool__(ref List<Volume<bool>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Char__(ref List<Volume<char>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_String__(ref List<Volume<string>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Type__(ref List<Volume<Type>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Guid__(ref List<Volume<Guid>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Symbol__(ref List<Volume<Symbol>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Circle2d__(ref List<Volume<Circle2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Line2d__(ref List<Volume<Line2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Line3d__(ref List<Volume<Line3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Plane2d__(ref List<Volume<Plane2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Plane3d__(ref List<Volume<Plane3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3d__(ref List<Volume<PlaneWithPoint3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Quad2d__(ref List<Volume<Quad2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Quad3d__(ref List<Volume<Quad3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Ray2d__(ref List<Volume<Ray2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Ray3d__(ref List<Volume<Ray3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Sphere3d__(ref List<Volume<Sphere3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Triangle2d__(ref List<Volume<Triangle2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Triangle3d__(ref List<Volume<Triangle3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Circle2f__(ref List<Volume<Circle2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Line2f__(ref List<Volume<Line2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Line3f__(ref List<Volume<Line3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Plane2f__(ref List<Volume<Plane2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Plane3f__(ref List<Volume<Plane3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3f__(ref List<Volume<PlaneWithPoint3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Quad2f__(ref List<Volume<Quad2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Quad3f__(ref List<Volume<Quad3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Ray2f__(ref List<Volume<Ray2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Ray3f__(ref List<Volume<Ray3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Sphere3f__(ref List<Volume<Sphere3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Triangle2f__(ref List<Volume<Triangle2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Volume_of_Triangle3f__(ref List<Volume<Triangle3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Byte__(ref List<Tensor<byte>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_SByte__(ref List<Tensor<sbyte>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Short__(ref List<Tensor<short>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_UShort__(ref List<Tensor<ushort>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Int__(ref List<Tensor<int>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_UInt__(ref List<Tensor<uint>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Long__(ref List<Tensor<long>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_ULong__(ref List<Tensor<ulong>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Float__(ref List<Tensor<float>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Double__(ref List<Tensor<double>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Fraction__(ref List<Tensor<Fraction>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V2i__(ref List<Tensor<V2i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V2l__(ref List<Tensor<V2l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V2f__(ref List<Tensor<V2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V2d__(ref List<Tensor<V2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V3i__(ref List<Tensor<V3i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V3l__(ref List<Tensor<V3l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V3f__(ref List<Tensor<V3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V3d__(ref List<Tensor<V3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V4i__(ref List<Tensor<V4i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V4l__(ref List<Tensor<V4l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V4f__(ref List<Tensor<V4f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_V4d__(ref List<Tensor<V4d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M22i__(ref List<Tensor<M22i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M22l__(ref List<Tensor<M22l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M22f__(ref List<Tensor<M22f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M22d__(ref List<Tensor<M22d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M23i__(ref List<Tensor<M23i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M23l__(ref List<Tensor<M23l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M23f__(ref List<Tensor<M23f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M23d__(ref List<Tensor<M23d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M33i__(ref List<Tensor<M33i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M33l__(ref List<Tensor<M33l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M33f__(ref List<Tensor<M33f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M33d__(ref List<Tensor<M33d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M34i__(ref List<Tensor<M34i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M34l__(ref List<Tensor<M34l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M34f__(ref List<Tensor<M34f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M34d__(ref List<Tensor<M34d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M44i__(ref List<Tensor<M44i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M44l__(ref List<Tensor<M44l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M44f__(ref List<Tensor<M44f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_M44d__(ref List<Tensor<M44d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C3b__(ref List<Tensor<C3b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C3us__(ref List<Tensor<C3us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C3ui__(ref List<Tensor<C3ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C3f__(ref List<Tensor<C3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C3d__(ref List<Tensor<C3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C4b__(ref List<Tensor<C4b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C4us__(ref List<Tensor<C4us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C4ui__(ref List<Tensor<C4ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C4f__(ref List<Tensor<C4f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_C4d__(ref List<Tensor<C4d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1b__(ref List<Tensor<Range1b>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1sb__(ref List<Tensor<Range1sb>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1s__(ref List<Tensor<Range1s>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1us__(ref List<Tensor<Range1us>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1i__(ref List<Tensor<Range1i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1ui__(ref List<Tensor<Range1ui>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1l__(ref List<Tensor<Range1l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1ul__(ref List<Tensor<Range1ul>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1f__(ref List<Tensor<Range1f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Range1d__(ref List<Tensor<Range1d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Box2i__(ref List<Tensor<Box2i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Box2l__(ref List<Tensor<Box2l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Box2f__(ref List<Tensor<Box2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Box2d__(ref List<Tensor<Box2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Box3i__(ref List<Tensor<Box3i>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Box3l__(ref List<Tensor<Box3l>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Box3f__(ref List<Tensor<Box3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Box3d__(ref List<Tensor<Box3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Euclidean3f__(ref List<Tensor<Euclidean3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Euclidean3d__(ref List<Tensor<Euclidean3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Rot2f__(ref List<Tensor<Rot2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Rot2d__(ref List<Tensor<Rot2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Rot3f__(ref List<Tensor<Rot3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Rot3d__(ref List<Tensor<Rot3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Scale3f__(ref List<Tensor<Scale3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Scale3d__(ref List<Tensor<Scale3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Shift3f__(ref List<Tensor<Shift3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Shift3d__(ref List<Tensor<Shift3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Trafo2f__(ref List<Tensor<Trafo2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Trafo2d__(ref List<Tensor<Trafo2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Trafo3f__(ref List<Tensor<Trafo3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Trafo3d__(ref List<Tensor<Trafo3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Bool__(ref List<Tensor<bool>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Char__(ref List<Tensor<char>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_String__(ref List<Tensor<string>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Type__(ref List<Tensor<Type>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Guid__(ref List<Tensor<Guid>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Symbol__(ref List<Tensor<Symbol>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Circle2d__(ref List<Tensor<Circle2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Line2d__(ref List<Tensor<Line2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Line3d__(ref List<Tensor<Line3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Plane2d__(ref List<Tensor<Plane2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Plane3d__(ref List<Tensor<Plane3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3d__(ref List<Tensor<PlaneWithPoint3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Quad2d__(ref List<Tensor<Quad2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Quad3d__(ref List<Tensor<Quad3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Ray2d__(ref List<Tensor<Ray2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Ray3d__(ref List<Tensor<Ray3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Sphere3d__(ref List<Tensor<Sphere3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Triangle2d__(ref List<Tensor<Triangle2d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Triangle3d__(ref List<Tensor<Triangle3d>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Circle2f__(ref List<Tensor<Circle2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Line2f__(ref List<Tensor<Line2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Line3f__(ref List<Tensor<Line3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Plane2f__(ref List<Tensor<Plane2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Plane3f__(ref List<Tensor<Plane3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3f__(ref List<Tensor<PlaneWithPoint3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Quad2f__(ref List<Tensor<Quad2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Quad3f__(ref List<Tensor<Quad3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Ray2f__(ref List<Tensor<Ray2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Ray3f__(ref List<Tensor<Ray3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Sphere3f__(ref List<Tensor<Sphere3f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Triangle2f__(ref List<Tensor<Triangle2f>> v) { throw new NotImplementedException(); }\r\n        public void CodeList_of_Tensor_of_Triangle3f__(ref List<Tensor<Triangle3f>> v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n    }\r\n\r\n    public partial class XmlWritingCoder\r\n    {\r\n        #region Vectors\r\n\r\n        public void CodeV2i(ref V2i v) { AddValue(v.ToString()); }\r\n        public void CodeV2ui(ref V2ui v) { AddValue(v.ToString()); }\r\n        public void CodeV2l(ref V2l v) { AddValue(v.ToString()); }\r\n        public void CodeV2f(ref V2f v) { AddValue(v.ToString()); }\r\n        public void CodeV2d(ref V2d v) { AddValue(v.ToString()); }\r\n        public void CodeV3i(ref V3i v) { AddValue(v.ToString()); }\r\n        public void CodeV3ui(ref V3ui v) { AddValue(v.ToString()); }\r\n        public void CodeV3l(ref V3l v) { AddValue(v.ToString()); }\r\n        public void CodeV3f(ref V3f v) { AddValue(v.ToString()); }\r\n        public void CodeV3d(ref V3d v) { AddValue(v.ToString()); }\r\n        public void CodeV4i(ref V4i v) { AddValue(v.ToString()); }\r\n        public void CodeV4ui(ref V4ui v) { AddValue(v.ToString()); }\r\n        public void CodeV4l(ref V4l v) { AddValue(v.ToString()); }\r\n        public void CodeV4f(ref V4f v) { AddValue(v.ToString()); }\r\n        public void CodeV4d(ref V4d v) { AddValue(v.ToString()); }\r\n\r\n        #endregion\r\n\r\n        #region Matrices\r\n\r\n        public void CodeM22i(ref M22i v) { AddValue(v.ToString()); }\r\n        public void CodeM22l(ref M22l v) { AddValue(v.ToString()); }\r\n        public void CodeM22f(ref M22f v) { AddValue(v.ToString()); }\r\n        public void CodeM22d(ref M22d v) { AddValue(v.ToString()); }\r\n        public void CodeM23i(ref M23i v) { AddValue(v.ToString()); }\r\n        public void CodeM23l(ref M23l v) { AddValue(v.ToString()); }\r\n        public void CodeM23f(ref M23f v) { AddValue(v.ToString()); }\r\n        public void CodeM23d(ref M23d v) { AddValue(v.ToString()); }\r\n        public void CodeM33i(ref M33i v) { AddValue(v.ToString()); }\r\n        public void CodeM33l(ref M33l v) { AddValue(v.ToString()); }\r\n        public void CodeM33f(ref M33f v) { AddValue(v.ToString()); }\r\n        public void CodeM33d(ref M33d v) { AddValue(v.ToString()); }\r\n        public void CodeM34i(ref M34i v) { AddValue(v.ToString()); }\r\n        public void CodeM34l(ref M34l v) { AddValue(v.ToString()); }\r\n        public void CodeM34f(ref M34f v) { AddValue(v.ToString()); }\r\n        public void CodeM34d(ref M34d v) { AddValue(v.ToString()); }\r\n        public void CodeM44i(ref M44i v) { AddValue(v.ToString()); }\r\n        public void CodeM44l(ref M44l v) { AddValue(v.ToString()); }\r\n        public void CodeM44f(ref M44f v) { AddValue(v.ToString()); }\r\n        public void CodeM44d(ref M44d v) { AddValue(v.ToString()); }\r\n\r\n        #endregion\r\n\r\n        #region Ranges and Boxes\r\n\r\n        public void CodeRange1b(ref Range1b v) { AddValue(v.ToString()); }\r\n        public void CodeRange1sb(ref Range1sb v) { AddValue(v.ToString()); }\r\n        public void CodeRange1s(ref Range1s v) { AddValue(v.ToString()); }\r\n        public void CodeRange1us(ref Range1us v) { AddValue(v.ToString()); }\r\n        public void CodeRange1i(ref Range1i v) { AddValue(v.ToString()); }\r\n        public void CodeRange1ui(ref Range1ui v) { AddValue(v.ToString()); }\r\n        public void CodeRange1l(ref Range1l v) { AddValue(v.ToString()); }\r\n        public void CodeRange1ul(ref Range1ul v) { AddValue(v.ToString()); }\r\n        public void CodeRange1f(ref Range1f v) { AddValue(v.ToString()); }\r\n        public void CodeRange1d(ref Range1d v) { AddValue(v.ToString()); }\r\n        public void CodeBox2i(ref Box2i v) { AddValue(v.ToString()); }\r\n        public void CodeBox2l(ref Box2l v) { AddValue(v.ToString()); }\r\n        public void CodeBox2f(ref Box2f v) { AddValue(v.ToString()); }\r\n        public void CodeBox2d(ref Box2d v) { AddValue(v.ToString()); }\r\n        public void CodeBox3i(ref Box3i v) { AddValue(v.ToString()); }\r\n        public void CodeBox3l(ref Box3l v) { AddValue(v.ToString()); }\r\n        public void CodeBox3f(ref Box3f v) { AddValue(v.ToString()); }\r\n        public void CodeBox3d(ref Box3d v) { AddValue(v.ToString()); }\r\n\r\n        #endregion\r\n\r\n        #region Geometry Types\r\n\r\n        public void CodeCircle2f(ref Circle2f v) { AddValue(v.ToString()); }\r\n        public void CodeLine2f(ref Line2f v) { AddValue(v.ToString()); }\r\n        public void CodeLine3f(ref Line3f v) { AddValue(v.ToString()); }\r\n        public void CodePlane2f(ref Plane2f v) { AddValue(v.ToString()); }\r\n        public void CodePlane3f(ref Plane3f v) { AddValue(v.ToString()); }\r\n        public void CodePlaneWithPoint3f(ref PlaneWithPoint3f v) { AddValue(v.ToString()); }\r\n        public void CodeQuad2f(ref Quad2f v) { AddValue(v.ToString()); }\r\n        public void CodeQuad3f(ref Quad3f v) { AddValue(v.ToString()); }\r\n        public void CodeRay2f(ref Ray2f v) { AddValue(v.ToString()); }\r\n        public void CodeRay3f(ref Ray3f v) { AddValue(v.ToString()); }\r\n        public void CodeSphere3f(ref Sphere3f v) { AddValue(v.ToString()); }\r\n        public void CodeTriangle2f(ref Triangle2f v) { AddValue(v.ToString()); }\r\n        public void CodeTriangle3f(ref Triangle3f v) { AddValue(v.ToString()); }\r\n\r\n        public void CodeCircle2d(ref Circle2d v) { AddValue(v.ToString()); }\r\n        public void CodeLine2d(ref Line2d v) { AddValue(v.ToString()); }\r\n        public void CodeLine3d(ref Line3d v) { AddValue(v.ToString()); }\r\n        public void CodePlane2d(ref Plane2d v) { AddValue(v.ToString()); }\r\n        public void CodePlane3d(ref Plane3d v) { AddValue(v.ToString()); }\r\n        public void CodePlaneWithPoint3d(ref PlaneWithPoint3d v) { AddValue(v.ToString()); }\r\n        public void CodeQuad2d(ref Quad2d v) { AddValue(v.ToString()); }\r\n        public void CodeQuad3d(ref Quad3d v) { AddValue(v.ToString()); }\r\n        public void CodeRay2d(ref Ray2d v) { AddValue(v.ToString()); }\r\n        public void CodeRay3d(ref Ray3d v) { AddValue(v.ToString()); }\r\n        public void CodeSphere3d(ref Sphere3d v) { AddValue(v.ToString()); }\r\n        public void CodeTriangle2d(ref Triangle2d v) { AddValue(v.ToString()); }\r\n        public void CodeTriangle3d(ref Triangle3d v) { AddValue(v.ToString()); }\r\n\r\n        #endregion\r\n\r\n        #region Colors\r\n\r\n        public void CodeC3b(ref C3b v) { AddValue(v.ToString()); }\r\n        public void CodeC3us(ref C3us v) { AddValue(v.ToString()); }\r\n        public void CodeC3ui(ref C3ui v) { AddValue(v.ToString()); }\r\n        public void CodeC3f(ref C3f v) { AddValue(v.ToString()); }\r\n        public void CodeC3d(ref C3d v) { AddValue(v.ToString()); }\r\n        public void CodeC4b(ref C4b v) { AddValue(v.ToString()); }\r\n        public void CodeC4us(ref C4us v) { AddValue(v.ToString()); }\r\n        public void CodeC4ui(ref C4ui v) { AddValue(v.ToString()); }\r\n        public void CodeC4f(ref C4f v) { AddValue(v.ToString()); }\r\n        public void CodeC4d(ref C4d v) { AddValue(v.ToString()); }\r\n\r\n        #endregion\r\n\r\n        #region Trafos\r\n\r\n        public void CodeEuclidean3f(ref Euclidean3f v) { AddValue(v.ToString()); }\r\n        public void CodeEuclidean3d(ref Euclidean3d v) { AddValue(v.ToString()); }\r\n        public void CodeRot2f(ref Rot2f v) { AddValue(v.ToString()); }\r\n        public void CodeRot2d(ref Rot2d v) { AddValue(v.ToString()); }\r\n        public void CodeRot3f(ref Rot3f v) { AddValue(v.ToString()); }\r\n        public void CodeRot3d(ref Rot3d v) { AddValue(v.ToString()); }\r\n        public void CodeScale3f(ref Scale3f v) { AddValue(v.ToString()); }\r\n        public void CodeScale3d(ref Scale3d v) { AddValue(v.ToString()); }\r\n        public void CodeShift3f(ref Shift3f v) { AddValue(v.ToString()); }\r\n        public void CodeShift3d(ref Shift3d v) { AddValue(v.ToString()); }\r\n        public void CodeTrafo2f(ref Trafo2f v) { AddValue(v.ToString()); }\r\n        public void CodeTrafo2d(ref Trafo2d v) { AddValue(v.ToString()); }\r\n        public void CodeTrafo3f(ref Trafo3f v) { AddValue(v.ToString()); }\r\n        public void CodeTrafo3d(ref Trafo3d v) { AddValue(v.ToString()); }\r\n\r\n        #endregion\r\n\r\n        #region Tensors\r\n\r\n        public void CodeVector_of_Byte_(ref Vector<byte> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeByteArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_SByte_(ref Vector<sbyte> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSByteArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Short_(ref Vector<short> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShortArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_UShort_(ref Vector<ushort> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeUShortArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Int_(ref Vector<int> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeIntArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_UInt_(ref Vector<uint> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeUIntArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Long_(ref Vector<long> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLongArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_ULong_(ref Vector<ulong> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeULongArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Float_(ref Vector<float> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeFloatArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Double_(ref Vector<double> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeDoubleArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Fraction_(ref Vector<Fraction> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeFractionArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V2i_(ref Vector<V2i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V2l_(ref Vector<V2l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V2f_(ref Vector<V2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V2d_(ref Vector<V2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V3i_(ref Vector<V3i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V3l_(ref Vector<V3l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V3f_(ref Vector<V3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V3d_(ref Vector<V3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V4i_(ref Vector<V4i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V4l_(ref Vector<V4l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V4f_(ref Vector<V4f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_V4d_(ref Vector<V4d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M22i_(ref Vector<M22i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M22l_(ref Vector<M22l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M22f_(ref Vector<M22f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M22d_(ref Vector<M22d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M23i_(ref Vector<M23i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M23l_(ref Vector<M23l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M23f_(ref Vector<M23f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M23d_(ref Vector<M23d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M33i_(ref Vector<M33i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M33l_(ref Vector<M33l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M33f_(ref Vector<M33f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M33d_(ref Vector<M33d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M34i_(ref Vector<M34i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M34l_(ref Vector<M34l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M34f_(ref Vector<M34f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M34d_(ref Vector<M34d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M44i_(ref Vector<M44i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M44l_(ref Vector<M44l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M44f_(ref Vector<M44f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_M44d_(ref Vector<M44d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C3b_(ref Vector<C3b> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C3us_(ref Vector<C3us> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C3ui_(ref Vector<C3ui> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C3f_(ref Vector<C3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C3d_(ref Vector<C3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C4b_(ref Vector<C4b> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C4us_(ref Vector<C4us> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C4ui_(ref Vector<C4ui> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C4f_(ref Vector<C4f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_C4d_(ref Vector<C4d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1b_(ref Vector<Range1b> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1sb_(ref Vector<Range1sb> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1sbArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1s_(ref Vector<Range1s> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1sArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1us_(ref Vector<Range1us> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1i_(ref Vector<Range1i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ui_(ref Vector<Range1ui> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1l_(ref Vector<Range1l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1ul_(ref Vector<Range1ul> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1ulArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1f_(ref Vector<Range1f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Range1d_(ref Vector<Range1d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Box2i_(ref Vector<Box2i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Box2l_(ref Vector<Box2l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Box2f_(ref Vector<Box2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Box2d_(ref Vector<Box2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Box3i_(ref Vector<Box3i> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Box3l_(ref Vector<Box3l> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Box3f_(ref Vector<Box3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Box3d_(ref Vector<Box3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3f_(ref Vector<Euclidean3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeEuclidean3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Euclidean3d_(ref Vector<Euclidean3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeEuclidean3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2f_(ref Vector<Rot2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Rot2d_(ref Vector<Rot2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3f_(ref Vector<Rot3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Rot3d_(ref Vector<Rot3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3f_(ref Vector<Scale3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeScale3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Scale3d_(ref Vector<Scale3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeScale3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3f_(ref Vector<Shift3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShift3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Shift3d_(ref Vector<Shift3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShift3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2f_(ref Vector<Trafo2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo2d_(ref Vector<Trafo2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3f_(ref Vector<Trafo3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Trafo3d_(ref Vector<Trafo3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Bool_(ref Vector<bool> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBoolArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Char_(ref Vector<char> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCharArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_String_(ref Vector<string> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeStringArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Type_(ref Vector<Type> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTypeArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Guid_(ref Vector<Guid> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeGuidArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Symbol_(ref Vector<Symbol> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSymbolArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2d_(ref Vector<Circle2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCircle2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Line2d_(ref Vector<Line2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Line3d_(ref Vector<Line3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2d_(ref Vector<Plane2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3d_(ref Vector<Plane3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3d_(ref Vector<PlaneWithPoint3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlaneWithPoint3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2d_(ref Vector<Quad2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3d_(ref Vector<Quad3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2d_(ref Vector<Ray2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3d_(ref Vector<Ray3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3d_(ref Vector<Sphere3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSphere3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2d_(ref Vector<Triangle2d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3d_(ref Vector<Triangle3d> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Circle2f_(ref Vector<Circle2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCircle2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Line2f_(ref Vector<Line2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Line3f_(ref Vector<Line3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Plane2f_(ref Vector<Plane2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Plane3f_(ref Vector<Plane3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_PlaneWithPoint3f_(ref Vector<PlaneWithPoint3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlaneWithPoint3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Quad2f_(ref Vector<Quad2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Quad3f_(ref Vector<Quad3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Ray2f_(ref Vector<Ray2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Ray3f_(ref Vector<Ray3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Sphere3f_(ref Vector<Sphere3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSphere3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle2f_(ref Vector<Triangle2f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVector_of_Triangle3f_(ref Vector<Triangle3f> value)\r\n        {\r\n            var item = new XElement(\"Vector\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLong(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLong(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Byte_(ref Matrix<byte> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeByteArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_SByte_(ref Matrix<sbyte> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSByteArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Short_(ref Matrix<short> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShortArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_UShort_(ref Matrix<ushort> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeUShortArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Int_(ref Matrix<int> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeIntArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_UInt_(ref Matrix<uint> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeUIntArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Long_(ref Matrix<long> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLongArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_ULong_(ref Matrix<ulong> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeULongArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Float_(ref Matrix<float> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeFloatArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Double_(ref Matrix<double> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeDoubleArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Fraction_(ref Matrix<Fraction> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeFractionArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2i_(ref Matrix<V2i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2l_(ref Matrix<V2l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2f_(ref Matrix<V2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V2d_(ref Matrix<V2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3i_(ref Matrix<V3i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3l_(ref Matrix<V3l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3f_(ref Matrix<V3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V3d_(ref Matrix<V3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4i_(ref Matrix<V4i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4l_(ref Matrix<V4l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4f_(ref Matrix<V4f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_V4d_(ref Matrix<V4d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22i_(ref Matrix<M22i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22l_(ref Matrix<M22l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22f_(ref Matrix<M22f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M22d_(ref Matrix<M22d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23i_(ref Matrix<M23i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23l_(ref Matrix<M23l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23f_(ref Matrix<M23f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M23d_(ref Matrix<M23d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33i_(ref Matrix<M33i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33l_(ref Matrix<M33l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33f_(ref Matrix<M33f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M33d_(ref Matrix<M33d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34i_(ref Matrix<M34i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34l_(ref Matrix<M34l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34f_(ref Matrix<M34f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M34d_(ref Matrix<M34d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44i_(ref Matrix<M44i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44l_(ref Matrix<M44l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44f_(ref Matrix<M44f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_M44d_(ref Matrix<M44d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3b_(ref Matrix<C3b> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3us_(ref Matrix<C3us> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3ui_(ref Matrix<C3ui> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3f_(ref Matrix<C3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C3d_(ref Matrix<C3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4b_(ref Matrix<C4b> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4us_(ref Matrix<C4us> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4ui_(ref Matrix<C4ui> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4f_(ref Matrix<C4f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_C4d_(ref Matrix<C4d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1b_(ref Matrix<Range1b> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1sb_(ref Matrix<Range1sb> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1sbArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1s_(ref Matrix<Range1s> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1sArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1us_(ref Matrix<Range1us> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1i_(ref Matrix<Range1i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ui_(ref Matrix<Range1ui> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1l_(ref Matrix<Range1l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1ul_(ref Matrix<Range1ul> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1ulArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1f_(ref Matrix<Range1f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Range1d_(ref Matrix<Range1d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2i_(ref Matrix<Box2i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2l_(ref Matrix<Box2l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2f_(ref Matrix<Box2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box2d_(ref Matrix<Box2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3i_(ref Matrix<Box3i> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3l_(ref Matrix<Box3l> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3f_(ref Matrix<Box3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Box3d_(ref Matrix<Box3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3f_(ref Matrix<Euclidean3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeEuclidean3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Euclidean3d_(ref Matrix<Euclidean3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeEuclidean3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2f_(ref Matrix<Rot2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot2d_(ref Matrix<Rot2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3f_(ref Matrix<Rot3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Rot3d_(ref Matrix<Rot3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3f_(ref Matrix<Scale3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeScale3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Scale3d_(ref Matrix<Scale3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeScale3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3f_(ref Matrix<Shift3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShift3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Shift3d_(ref Matrix<Shift3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShift3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2f_(ref Matrix<Trafo2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo2d_(ref Matrix<Trafo2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3f_(ref Matrix<Trafo3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Trafo3d_(ref Matrix<Trafo3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Bool_(ref Matrix<bool> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBoolArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Char_(ref Matrix<char> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCharArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_String_(ref Matrix<string> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeStringArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Type_(ref Matrix<Type> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTypeArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Guid_(ref Matrix<Guid> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeGuidArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Symbol_(ref Matrix<Symbol> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSymbolArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2d_(ref Matrix<Circle2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCircle2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2d_(ref Matrix<Line2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3d_(ref Matrix<Line3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2d_(ref Matrix<Plane2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3d_(ref Matrix<Plane3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3d_(ref Matrix<PlaneWithPoint3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlaneWithPoint3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2d_(ref Matrix<Quad2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3d_(ref Matrix<Quad3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2d_(ref Matrix<Ray2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3d_(ref Matrix<Ray3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3d_(ref Matrix<Sphere3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSphere3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2d_(ref Matrix<Triangle2d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3d_(ref Matrix<Triangle3d> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Circle2f_(ref Matrix<Circle2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCircle2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line2f_(ref Matrix<Line2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Line3f_(ref Matrix<Line3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane2f_(ref Matrix<Plane2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Plane3f_(ref Matrix<Plane3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_PlaneWithPoint3f_(ref Matrix<PlaneWithPoint3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlaneWithPoint3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad2f_(ref Matrix<Quad2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Quad3f_(ref Matrix<Quad3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray2f_(ref Matrix<Ray2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Ray3f_(ref Matrix<Ray3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Sphere3f_(ref Matrix<Sphere3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSphere3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle2f_(ref Matrix<Triangle2f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeMatrix_of_Triangle3f_(ref Matrix<Triangle3f> value)\r\n        {\r\n            var item = new XElement(\"Matrix\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV2l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV2l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Byte_(ref Volume<byte> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeByteArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_SByte_(ref Volume<sbyte> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSByteArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Short_(ref Volume<short> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShortArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_UShort_(ref Volume<ushort> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeUShortArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Int_(ref Volume<int> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeIntArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_UInt_(ref Volume<uint> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeUIntArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Long_(ref Volume<long> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLongArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_ULong_(ref Volume<ulong> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeULongArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Float_(ref Volume<float> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeFloatArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Double_(ref Volume<double> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeDoubleArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Fraction_(ref Volume<Fraction> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeFractionArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V2i_(ref Volume<V2i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V2l_(ref Volume<V2l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V2f_(ref Volume<V2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V2d_(ref Volume<V2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V3i_(ref Volume<V3i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V3l_(ref Volume<V3l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V3f_(ref Volume<V3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V3d_(ref Volume<V3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V4i_(ref Volume<V4i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V4l_(ref Volume<V4l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V4f_(ref Volume<V4f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_V4d_(ref Volume<V4d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M22i_(ref Volume<M22i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M22l_(ref Volume<M22l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M22f_(ref Volume<M22f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M22d_(ref Volume<M22d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M23i_(ref Volume<M23i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M23l_(ref Volume<M23l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M23f_(ref Volume<M23f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M23d_(ref Volume<M23d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M33i_(ref Volume<M33i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M33l_(ref Volume<M33l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M33f_(ref Volume<M33f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M33d_(ref Volume<M33d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M34i_(ref Volume<M34i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M34l_(ref Volume<M34l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M34f_(ref Volume<M34f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M34d_(ref Volume<M34d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M44i_(ref Volume<M44i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M44l_(ref Volume<M44l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M44f_(ref Volume<M44f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_M44d_(ref Volume<M44d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C3b_(ref Volume<C3b> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C3us_(ref Volume<C3us> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C3ui_(ref Volume<C3ui> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C3f_(ref Volume<C3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C3d_(ref Volume<C3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C4b_(ref Volume<C4b> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C4us_(ref Volume<C4us> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C4ui_(ref Volume<C4ui> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C4f_(ref Volume<C4f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_C4d_(ref Volume<C4d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1b_(ref Volume<Range1b> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1sb_(ref Volume<Range1sb> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1sbArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1s_(ref Volume<Range1s> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1sArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1us_(ref Volume<Range1us> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1i_(ref Volume<Range1i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ui_(ref Volume<Range1ui> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1l_(ref Volume<Range1l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1ul_(ref Volume<Range1ul> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1ulArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1f_(ref Volume<Range1f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Range1d_(ref Volume<Range1d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2i_(ref Volume<Box2i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2l_(ref Volume<Box2l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2f_(ref Volume<Box2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Box2d_(ref Volume<Box2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3i_(ref Volume<Box3i> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3l_(ref Volume<Box3l> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3f_(ref Volume<Box3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Box3d_(ref Volume<Box3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3f_(ref Volume<Euclidean3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeEuclidean3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Euclidean3d_(ref Volume<Euclidean3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeEuclidean3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2f_(ref Volume<Rot2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot2d_(ref Volume<Rot2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3f_(ref Volume<Rot3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Rot3d_(ref Volume<Rot3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3f_(ref Volume<Scale3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeScale3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Scale3d_(ref Volume<Scale3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeScale3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3f_(ref Volume<Shift3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShift3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Shift3d_(ref Volume<Shift3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShift3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2f_(ref Volume<Trafo2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo2d_(ref Volume<Trafo2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3f_(ref Volume<Trafo3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Trafo3d_(ref Volume<Trafo3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Bool_(ref Volume<bool> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBoolArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Char_(ref Volume<char> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCharArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_String_(ref Volume<string> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeStringArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Type_(ref Volume<Type> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTypeArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Guid_(ref Volume<Guid> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeGuidArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Symbol_(ref Volume<Symbol> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSymbolArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2d_(ref Volume<Circle2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCircle2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2d_(ref Volume<Line2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3d_(ref Volume<Line3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2d_(ref Volume<Plane2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3d_(ref Volume<Plane3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3d_(ref Volume<PlaneWithPoint3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlaneWithPoint3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2d_(ref Volume<Quad2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3d_(ref Volume<Quad3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2d_(ref Volume<Ray2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3d_(ref Volume<Ray3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3d_(ref Volume<Sphere3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSphere3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2d_(ref Volume<Triangle2d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3d_(ref Volume<Triangle3d> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Circle2f_(ref Volume<Circle2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCircle2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Line2f_(ref Volume<Line2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Line3f_(ref Volume<Line3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane2f_(ref Volume<Plane2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Plane3f_(ref Volume<Plane3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_PlaneWithPoint3f_(ref Volume<PlaneWithPoint3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlaneWithPoint3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad2f_(ref Volume<Quad2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Quad3f_(ref Volume<Quad3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray2f_(ref Volume<Ray2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Ray3f_(ref Volume<Ray3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Sphere3f_(ref Volume<Sphere3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSphere3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle2f_(ref Volume<Triangle2f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeVolume_of_Triangle3f_(ref Volume<Triangle3f> value)\r\n        {\r\n            var item = new XElement(\"Volume\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeV3l(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeV3l(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Byte_(ref Tensor<byte> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeByteArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_SByte_(ref Tensor<sbyte> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSByteArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Short_(ref Tensor<short> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShortArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_UShort_(ref Tensor<ushort> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeUShortArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Int_(ref Tensor<int> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeIntArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_UInt_(ref Tensor<uint> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeUIntArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Long_(ref Tensor<long> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLongArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_ULong_(ref Tensor<ulong> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeULongArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Float_(ref Tensor<float> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeFloatArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Double_(ref Tensor<double> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeDoubleArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Fraction_(ref Tensor<Fraction> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeFractionArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V2i_(ref Tensor<V2i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V2l_(ref Tensor<V2l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V2f_(ref Tensor<V2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V2d_(ref Tensor<V2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V3i_(ref Tensor<V3i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V3l_(ref Tensor<V3l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V3f_(ref Tensor<V3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V3d_(ref Tensor<V3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V4i_(ref Tensor<V4i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V4l_(ref Tensor<V4l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V4f_(ref Tensor<V4f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_V4d_(ref Tensor<V4d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeV4dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M22i_(ref Tensor<M22i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M22l_(ref Tensor<M22l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M22f_(ref Tensor<M22f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M22d_(ref Tensor<M22d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM22dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M23i_(ref Tensor<M23i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M23l_(ref Tensor<M23l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M23f_(ref Tensor<M23f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M23d_(ref Tensor<M23d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM23dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M33i_(ref Tensor<M33i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M33l_(ref Tensor<M33l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M33f_(ref Tensor<M33f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M33d_(ref Tensor<M33d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM33dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M34i_(ref Tensor<M34i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M34l_(ref Tensor<M34l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M34f_(ref Tensor<M34f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M34d_(ref Tensor<M34d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM34dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M44i_(ref Tensor<M44i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M44l_(ref Tensor<M44l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M44f_(ref Tensor<M44f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_M44d_(ref Tensor<M44d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeM44dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C3b_(ref Tensor<C3b> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C3us_(ref Tensor<C3us> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C3ui_(ref Tensor<C3ui> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C3f_(ref Tensor<C3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C3d_(ref Tensor<C3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C4b_(ref Tensor<C4b> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C4us_(ref Tensor<C4us> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C4ui_(ref Tensor<C4ui> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C4f_(ref Tensor<C4f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_C4d_(ref Tensor<C4d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeC4dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1b_(ref Tensor<Range1b> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1bArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1sb_(ref Tensor<Range1sb> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1sbArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1s_(ref Tensor<Range1s> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1sArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1us_(ref Tensor<Range1us> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1usArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1i_(ref Tensor<Range1i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ui_(ref Tensor<Range1ui> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1uiArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1l_(ref Tensor<Range1l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1ul_(ref Tensor<Range1ul> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1ulArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1f_(ref Tensor<Range1f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Range1d_(ref Tensor<Range1d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRange1dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2i_(ref Tensor<Box2i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2l_(ref Tensor<Box2l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2f_(ref Tensor<Box2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Box2d_(ref Tensor<Box2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3i_(ref Tensor<Box3i> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3iArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3l_(ref Tensor<Box3l> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3lArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3f_(ref Tensor<Box3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Box3d_(ref Tensor<Box3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBox3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3f_(ref Tensor<Euclidean3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeEuclidean3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Euclidean3d_(ref Tensor<Euclidean3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeEuclidean3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2f_(ref Tensor<Rot2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot2d_(ref Tensor<Rot2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3f_(ref Tensor<Rot3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Rot3d_(ref Tensor<Rot3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRot3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3f_(ref Tensor<Scale3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeScale3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Scale3d_(ref Tensor<Scale3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeScale3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3f_(ref Tensor<Shift3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShift3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Shift3d_(ref Tensor<Shift3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeShift3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2f_(ref Tensor<Trafo2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo2d_(ref Tensor<Trafo2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3f_(ref Tensor<Trafo3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Trafo3d_(ref Tensor<Trafo3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTrafo3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Bool_(ref Tensor<bool> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeBoolArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Char_(ref Tensor<char> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCharArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_String_(ref Tensor<string> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeStringArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Type_(ref Tensor<Type> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTypeArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Guid_(ref Tensor<Guid> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeGuidArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Symbol_(ref Tensor<Symbol> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSymbolArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2d_(ref Tensor<Circle2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCircle2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2d_(ref Tensor<Line2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3d_(ref Tensor<Line3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2d_(ref Tensor<Plane2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3d_(ref Tensor<Plane3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3d_(ref Tensor<PlaneWithPoint3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlaneWithPoint3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2d_(ref Tensor<Quad2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3d_(ref Tensor<Quad3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2d_(ref Tensor<Ray2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3d_(ref Tensor<Ray3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3d_(ref Tensor<Sphere3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSphere3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2d_(ref Tensor<Triangle2d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle2dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3d_(ref Tensor<Triangle3d> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle3dArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Circle2f_(ref Tensor<Circle2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeCircle2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Line2f_(ref Tensor<Line2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Line3f_(ref Tensor<Line3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeLine3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane2f_(ref Tensor<Plane2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Plane3f_(ref Tensor<Plane3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlane3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_PlaneWithPoint3f_(ref Tensor<PlaneWithPoint3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodePlaneWithPoint3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad2f_(ref Tensor<Quad2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Quad3f_(ref Tensor<Quad3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeQuad3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray2f_(ref Tensor<Ray2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Ray3f_(ref Tensor<Ray3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeRay3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Sphere3f_(ref Tensor<Sphere3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeSphere3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle2f_(ref Tensor<Triangle2f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle2fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        public void CodeTensor_of_Triangle3f_(ref Tensor<Triangle3f> value)\r\n        {\r\n            var item = new XElement(\"Tensor\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = item;\r\n\r\n            var element = new XElement(\"Data\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var data = value.Data; CodeTriangle3fArray(ref data);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Origin\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var origin = value.Origin; CodeLong(ref origin);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Length\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var size = value.Size; CodeLongArray(ref size);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            element = new XElement(\"Delta\");\r\n            m_elementStack.Push(m_element);\r\n            m_element = element;\r\n\r\n            var delta = value.Delta; CodeLongArray(ref delta);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            m_element.Add(element);\r\n\r\n            m_element = m_elementStack.Pop();\r\n            AddValue(item);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region Arrays\r\n\r\n        public void CodeV2iArray(ref V2i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV2uiArray(ref V2ui[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV2lArray(ref V2l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV2fArray(ref V2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV2dArray(ref V2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV3iArray(ref V3i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV3uiArray(ref V3ui[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV3lArray(ref V3l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV3fArray(ref V3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV3dArray(ref V3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV4iArray(ref V4i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV4uiArray(ref V4ui[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV4lArray(ref V4l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV4fArray(ref V4f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeV4dArray(ref V4d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM22iArray(ref M22i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM22lArray(ref M22l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM22fArray(ref M22f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM22dArray(ref M22d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM23iArray(ref M23i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM23lArray(ref M23l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM23fArray(ref M23f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM23dArray(ref M23d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM33iArray(ref M33i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM33lArray(ref M33l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM33fArray(ref M33f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM33dArray(ref M33d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM34iArray(ref M34i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM34lArray(ref M34l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM34fArray(ref M34f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM34dArray(ref M34d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM44iArray(ref M44i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM44lArray(ref M44l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM44fArray(ref M44f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeM44dArray(ref M44d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1bArray(ref Range1b[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1sbArray(ref Range1sb[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1sArray(ref Range1s[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1usArray(ref Range1us[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1iArray(ref Range1i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1uiArray(ref Range1ui[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1lArray(ref Range1l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1ulArray(ref Range1ul[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1fArray(ref Range1f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRange1dArray(ref Range1d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeBox2iArray(ref Box2i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeBox2lArray(ref Box2l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeBox2fArray(ref Box2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeBox2dArray(ref Box2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeBox3iArray(ref Box3i[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeBox3lArray(ref Box3l[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeBox3fArray(ref Box3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeBox3dArray(ref Box3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC3bArray(ref C3b[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC3usArray(ref C3us[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC3uiArray(ref C3ui[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC3fArray(ref C3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC3dArray(ref C3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC4bArray(ref C4b[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC4usArray(ref C4us[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC4uiArray(ref C4ui[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC4fArray(ref C4f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeC4dArray(ref C4d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeEuclidean3fArray(ref Euclidean3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeEuclidean3dArray(ref Euclidean3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRot2fArray(ref Rot2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRot2dArray(ref Rot2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRot3fArray(ref Rot3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRot3dArray(ref Rot3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeScale3fArray(ref Scale3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeScale3dArray(ref Scale3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeShift3fArray(ref Shift3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeShift3dArray(ref Shift3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeTrafo2fArray(ref Trafo2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeTrafo2dArray(ref Trafo2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeTrafo3fArray(ref Trafo3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeTrafo3dArray(ref Trafo3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeCircle2dArray(ref Circle2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeLine2dArray(ref Line2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeLine3dArray(ref Line3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodePlane2dArray(ref Plane2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodePlane3dArray(ref Plane3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodePlaneWithPoint3dArray(ref PlaneWithPoint3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeQuad2dArray(ref Quad2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeQuad3dArray(ref Quad3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRay2dArray(ref Ray2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRay3dArray(ref Ray3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeSphere3dArray(ref Sphere3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeTriangle2dArray(ref Triangle2d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeTriangle3dArray(ref Triangle3d[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeCircle2fArray(ref Circle2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeLine2fArray(ref Line2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeLine3fArray(ref Line3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodePlane2fArray(ref Plane2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodePlane3fArray(ref Plane3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodePlaneWithPoint3fArray(ref PlaneWithPoint3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeQuad2fArray(ref Quad2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeQuad3fArray(ref Quad3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRay2fArray(ref Ray2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeRay3fArray(ref Ray3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeSphere3fArray(ref Sphere3f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeTriangle2fArray(ref Triangle2f[] v) { CodeArrayOfStruct(v); }\r\n        public void CodeTriangle3fArray(ref Triangle3f[] v) { CodeArrayOfStruct(v); }\r\n\r\n        #endregion\r\n\r\n        #region Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArray2d(ref byte[,] v) { throw new NotImplementedException(); }\r\n        public void CodeByteArray3d(ref byte[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeSByteArray2d(ref sbyte[,] v) { throw new NotImplementedException(); }\r\n        public void CodeSByteArray3d(ref sbyte[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeShortArray2d(ref short[,] v) { throw new NotImplementedException(); }\r\n        public void CodeShortArray3d(ref short[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeUShortArray2d(ref ushort[,] v) { throw new NotImplementedException(); }\r\n        public void CodeUShortArray3d(ref ushort[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeIntArray2d(ref int[,] v) { throw new NotImplementedException(); }\r\n        public void CodeIntArray3d(ref int[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeUIntArray2d(ref uint[,] v) { throw new NotImplementedException(); }\r\n        public void CodeUIntArray3d(ref uint[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeLongArray2d(ref long[,] v) { throw new NotImplementedException(); }\r\n        public void CodeLongArray3d(ref long[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeULongArray2d(ref ulong[,] v) { throw new NotImplementedException(); }\r\n        public void CodeULongArray3d(ref ulong[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeFloatArray2d(ref float[,] v) { throw new NotImplementedException(); }\r\n        public void CodeFloatArray3d(ref float[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArray2d(ref double[,] v) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArray3d(ref double[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeFractionArray2d(ref Fraction[,] v) { throw new NotImplementedException(); }\r\n        public void CodeFractionArray3d(ref Fraction[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2iArray2d(ref V2i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2iArray3d(ref V2i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArray2d(ref V2l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArray3d(ref V2l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArray2d(ref V2f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArray3d(ref V2f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArray2d(ref V2d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArray3d(ref V2d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArray2d(ref V3i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArray3d(ref V3i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArray2d(ref V3l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArray3d(ref V3l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArray2d(ref V3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArray3d(ref V3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArray2d(ref V3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArray3d(ref V3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArray2d(ref V4i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArray3d(ref V4i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArray2d(ref V4l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArray3d(ref V4l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArray2d(ref V4f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArray3d(ref V4f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArray2d(ref V4d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArray3d(ref V4d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArray2d(ref M22i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArray3d(ref M22i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArray2d(ref M22l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArray3d(ref M22l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArray2d(ref M22f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArray3d(ref M22f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArray2d(ref M22d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArray3d(ref M22d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArray2d(ref M23i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArray3d(ref M23i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArray2d(ref M23l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArray3d(ref M23l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArray2d(ref M23f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArray3d(ref M23f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArray2d(ref M23d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArray3d(ref M23d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArray2d(ref M33i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArray3d(ref M33i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArray2d(ref M33l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArray3d(ref M33l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArray2d(ref M33f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArray3d(ref M33f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArray2d(ref M33d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArray3d(ref M33d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArray2d(ref M34i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArray3d(ref M34i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArray2d(ref M34l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArray3d(ref M34l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArray2d(ref M34f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArray3d(ref M34f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArray2d(ref M34d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArray3d(ref M34d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArray2d(ref M44i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArray3d(ref M44i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArray2d(ref M44l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArray3d(ref M44l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArray2d(ref M44f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArray3d(ref M44f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArray2d(ref M44d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArray3d(ref M44d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArray2d(ref C3b[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArray3d(ref C3b[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArray2d(ref C3us[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArray3d(ref C3us[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArray2d(ref C3ui[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArray3d(ref C3ui[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArray2d(ref C3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArray3d(ref C3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArray2d(ref C3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArray3d(ref C3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArray2d(ref C4b[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArray3d(ref C4b[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArray2d(ref C4us[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArray3d(ref C4us[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArray2d(ref C4ui[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArray3d(ref C4ui[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArray2d(ref C4f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArray3d(ref C4f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArray2d(ref C4d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArray3d(ref C4d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArray2d(ref Range1b[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArray3d(ref Range1b[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArray2d(ref Range1sb[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArray3d(ref Range1sb[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArray2d(ref Range1s[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArray3d(ref Range1s[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArray2d(ref Range1us[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArray3d(ref Range1us[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArray2d(ref Range1i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArray3d(ref Range1i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArray2d(ref Range1ui[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArray3d(ref Range1ui[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArray2d(ref Range1l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArray3d(ref Range1l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArray2d(ref Range1ul[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArray3d(ref Range1ul[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArray2d(ref Range1f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArray3d(ref Range1f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArray2d(ref Range1d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArray3d(ref Range1d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArray2d(ref Box2i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArray3d(ref Box2i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArray2d(ref Box2l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArray3d(ref Box2l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArray2d(ref Box2f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArray3d(ref Box2f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArray2d(ref Box2d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArray3d(ref Box2d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArray2d(ref Box3i[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArray3d(ref Box3i[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArray2d(ref Box3l[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArray3d(ref Box3l[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArray2d(ref Box3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArray3d(ref Box3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArray2d(ref Box3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArray3d(ref Box3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArray2d(ref Euclidean3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArray3d(ref Euclidean3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArray2d(ref Euclidean3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArray3d(ref Euclidean3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArray2d(ref Rot2f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArray3d(ref Rot2f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArray2d(ref Rot2d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArray3d(ref Rot2d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArray2d(ref Rot3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArray3d(ref Rot3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArray2d(ref Rot3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArray3d(ref Rot3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArray2d(ref Scale3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArray3d(ref Scale3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArray2d(ref Scale3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArray3d(ref Scale3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArray2d(ref Shift3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArray3d(ref Shift3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArray2d(ref Shift3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArray3d(ref Shift3d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArray2d(ref Trafo2f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArray3d(ref Trafo2f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArray2d(ref Trafo2d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArray3d(ref Trafo2d[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArray2d(ref Trafo3f[,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArray3d(ref Trafo3f[, ,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArray2d(ref Trafo3d[,] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArray3d(ref Trafo3d[, ,] v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Multi-Dimensional Arrays\r\n\r\n        public void CodeByteArrayArray(ref byte[][] v) { throw new NotImplementedException(); }\r\n        public void CodeByteArrayArrayArray(ref byte[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeSByteArrayArray(ref sbyte[][] v) { throw new NotImplementedException(); }\r\n        public void CodeSByteArrayArrayArray(ref sbyte[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeShortArrayArray(ref short[][] v) { throw new NotImplementedException(); }\r\n        public void CodeShortArrayArrayArray(ref short[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeUShortArrayArray(ref ushort[][] v) { throw new NotImplementedException(); }\r\n        public void CodeUShortArrayArrayArray(ref ushort[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeIntArrayArray(ref int[][] v) { throw new NotImplementedException(); }\r\n        public void CodeIntArrayArrayArray(ref int[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeUIntArrayArray(ref uint[][] v) { throw new NotImplementedException(); }\r\n        public void CodeUIntArrayArrayArray(ref uint[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeLongArrayArray(ref long[][] v) { throw new NotImplementedException(); }\r\n        public void CodeLongArrayArrayArray(ref long[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeULongArrayArray(ref ulong[][] v) { throw new NotImplementedException(); }\r\n        public void CodeULongArrayArrayArray(ref ulong[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeFloatArrayArray(ref float[][] v) { throw new NotImplementedException(); }\r\n        public void CodeFloatArrayArrayArray(ref float[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArrayArray(ref double[][] v) { throw new NotImplementedException(); }\r\n        public void CodeDoubleArrayArrayArray(ref double[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeFractionArrayArray(ref Fraction[][] v) { throw new NotImplementedException(); }\r\n        public void CodeFractionArrayArrayArray(ref Fraction[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2iArrayArray(ref V2i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2iArrayArrayArray(ref V2i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArrayArray(ref V2l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2lArrayArrayArray(ref V2l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArrayArray(ref V2f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2fArrayArrayArray(ref V2f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArrayArray(ref V2d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV2dArrayArrayArray(ref V2d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArrayArray(ref V3i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3iArrayArrayArray(ref V3i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArrayArray(ref V3l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3lArrayArrayArray(ref V3l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArrayArray(ref V3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3fArrayArrayArray(ref V3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArrayArray(ref V3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV3dArrayArrayArray(ref V3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArrayArray(ref V4i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4iArrayArrayArray(ref V4i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArrayArray(ref V4l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4lArrayArrayArray(ref V4l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArrayArray(ref V4f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4fArrayArrayArray(ref V4f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArrayArray(ref V4d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeV4dArrayArrayArray(ref V4d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArrayArray(ref M22i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22iArrayArrayArray(ref M22i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArrayArray(ref M22l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22lArrayArrayArray(ref M22l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArrayArray(ref M22f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22fArrayArrayArray(ref M22f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArrayArray(ref M22d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM22dArrayArrayArray(ref M22d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArrayArray(ref M23i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23iArrayArrayArray(ref M23i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArrayArray(ref M23l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23lArrayArrayArray(ref M23l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArrayArray(ref M23f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23fArrayArrayArray(ref M23f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArrayArray(ref M23d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM23dArrayArrayArray(ref M23d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArrayArray(ref M33i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33iArrayArrayArray(ref M33i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArrayArray(ref M33l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33lArrayArrayArray(ref M33l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArrayArray(ref M33f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33fArrayArrayArray(ref M33f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArrayArray(ref M33d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM33dArrayArrayArray(ref M33d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArrayArray(ref M34i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34iArrayArrayArray(ref M34i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArrayArray(ref M34l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34lArrayArrayArray(ref M34l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArrayArray(ref M34f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34fArrayArrayArray(ref M34f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArrayArray(ref M34d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM34dArrayArrayArray(ref M34d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArrayArray(ref M44i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44iArrayArrayArray(ref M44i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArrayArray(ref M44l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44lArrayArrayArray(ref M44l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArrayArray(ref M44f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44fArrayArrayArray(ref M44f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArrayArray(ref M44d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeM44dArrayArrayArray(ref M44d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArrayArray(ref C3b[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3bArrayArrayArray(ref C3b[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArrayArray(ref C3us[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3usArrayArrayArray(ref C3us[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArrayArray(ref C3ui[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3uiArrayArrayArray(ref C3ui[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArrayArray(ref C3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3fArrayArrayArray(ref C3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArrayArray(ref C3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC3dArrayArrayArray(ref C3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArrayArray(ref C4b[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4bArrayArrayArray(ref C4b[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArrayArray(ref C4us[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4usArrayArrayArray(ref C4us[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArrayArray(ref C4ui[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4uiArrayArrayArray(ref C4ui[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArrayArray(ref C4f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4fArrayArrayArray(ref C4f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArrayArray(ref C4d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeC4dArrayArrayArray(ref C4d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArrayArray(ref Range1b[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1bArrayArrayArray(ref Range1b[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArrayArray(ref Range1sb[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sbArrayArrayArray(ref Range1sb[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArrayArray(ref Range1s[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1sArrayArrayArray(ref Range1s[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArrayArray(ref Range1us[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1usArrayArrayArray(ref Range1us[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArrayArray(ref Range1i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1iArrayArrayArray(ref Range1i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArrayArray(ref Range1ui[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1uiArrayArrayArray(ref Range1ui[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArrayArray(ref Range1l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1lArrayArrayArray(ref Range1l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArrayArray(ref Range1ul[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1ulArrayArrayArray(ref Range1ul[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArrayArray(ref Range1f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1fArrayArrayArray(ref Range1f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArrayArray(ref Range1d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRange1dArrayArrayArray(ref Range1d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArrayArray(ref Box2i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2iArrayArrayArray(ref Box2i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArrayArray(ref Box2l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2lArrayArrayArray(ref Box2l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArrayArray(ref Box2f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2fArrayArrayArray(ref Box2f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArrayArray(ref Box2d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox2dArrayArrayArray(ref Box2d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArrayArray(ref Box3i[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3iArrayArrayArray(ref Box3i[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArrayArray(ref Box3l[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3lArrayArrayArray(ref Box3l[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArrayArray(ref Box3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3fArrayArrayArray(ref Box3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArrayArray(ref Box3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeBox3dArrayArrayArray(ref Box3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArrayArray(ref Euclidean3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3fArrayArrayArray(ref Euclidean3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArrayArray(ref Euclidean3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeEuclidean3dArrayArrayArray(ref Euclidean3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArrayArray(ref Rot2f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2fArrayArrayArray(ref Rot2f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArrayArray(ref Rot2d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot2dArrayArrayArray(ref Rot2d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArrayArray(ref Rot3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3fArrayArrayArray(ref Rot3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArrayArray(ref Rot3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeRot3dArrayArrayArray(ref Rot3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArrayArray(ref Scale3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3fArrayArrayArray(ref Scale3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArrayArray(ref Scale3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeScale3dArrayArrayArray(ref Scale3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArrayArray(ref Shift3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3fArrayArrayArray(ref Shift3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArrayArray(ref Shift3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeShift3dArrayArrayArray(ref Shift3d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArrayArray(ref Trafo2f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2fArrayArrayArray(ref Trafo2f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArrayArray(ref Trafo2d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo2dArrayArrayArray(ref Trafo2d[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArrayArray(ref Trafo3f[][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3fArrayArrayArray(ref Trafo3f[][][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArrayArray(ref Trafo3d[][] v) { throw new NotImplementedException(); }\r\n        public void CodeTrafo3dArrayArrayArray(ref Trafo3d[][][] v) { throw new NotImplementedException(); }\r\n\r\n        #endregion\r\n\r\n        #region Lists\r\n\r\n        public void CodeList_of_V2i_(ref List<V2i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V2ui_(ref List<V2ui> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V2l_(ref List<V2l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V2f_(ref List<V2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V2d_(ref List<V2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V3i_(ref List<V3i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V3ui_(ref List<V3ui> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V3l_(ref List<V3l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V3f_(ref List<V3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V3d_(ref List<V3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V4i_(ref List<V4i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V4ui_(ref List<V4ui> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V4l_(ref List<V4l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V4f_(ref List<V4f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_V4d_(ref List<V4d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M22i_(ref List<M22i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M22l_(ref List<M22l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M22f_(ref List<M22f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M22d_(ref List<M22d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M23i_(ref List<M23i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M23l_(ref List<M23l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M23f_(ref List<M23f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M23d_(ref List<M23d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M33i_(ref List<M33i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M33l_(ref List<M33l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M33f_(ref List<M33f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M33d_(ref List<M33d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M34i_(ref List<M34i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M34l_(ref List<M34l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M34f_(ref List<M34f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M34d_(ref List<M34d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M44i_(ref List<M44i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M44l_(ref List<M44l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M44f_(ref List<M44f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_M44d_(ref List<M44d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1b_(ref List<Range1b> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1sb_(ref List<Range1sb> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1s_(ref List<Range1s> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1us_(ref List<Range1us> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1i_(ref List<Range1i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1ui_(ref List<Range1ui> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1l_(ref List<Range1l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1ul_(ref List<Range1ul> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1f_(ref List<Range1f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Range1d_(ref List<Range1d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Box2i_(ref List<Box2i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Box2l_(ref List<Box2l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Box2f_(ref List<Box2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Box2d_(ref List<Box2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Box3i_(ref List<Box3i> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Box3l_(ref List<Box3l> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Box3f_(ref List<Box3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Box3d_(ref List<Box3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C3b_(ref List<C3b> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C3us_(ref List<C3us> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C3ui_(ref List<C3ui> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C3f_(ref List<C3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C3d_(ref List<C3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C4b_(ref List<C4b> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C4us_(ref List<C4us> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C4ui_(ref List<C4ui> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C4f_(ref List<C4f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_C4d_(ref List<C4d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Euclidean3f_(ref List<Euclidean3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Euclidean3d_(ref List<Euclidean3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Rot2f_(ref List<Rot2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Rot2d_(ref List<Rot2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Rot3f_(ref List<Rot3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Rot3d_(ref List<Rot3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Scale3f_(ref List<Scale3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Scale3d_(ref List<Scale3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Shift3f_(ref List<Shift3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Shift3d_(ref List<Shift3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Trafo2f_(ref List<Trafo2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Trafo2d_(ref List<Trafo2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Trafo3f_(ref List<Trafo3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Trafo3d_(ref List<Trafo3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Circle2d_(ref List<Circle2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Line2d_(ref List<Line2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Line3d_(ref List<Line3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Plane2d_(ref List<Plane2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Plane3d_(ref List<Plane3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_PlaneWithPoint3d_(ref List<PlaneWithPoint3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Quad2d_(ref List<Quad2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Quad3d_(ref List<Quad3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Ray2d_(ref List<Ray2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Ray3d_(ref List<Ray3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Sphere3d_(ref List<Sphere3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Triangle2d_(ref List<Triangle2d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Triangle3d_(ref List<Triangle3d> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Circle2f_(ref List<Circle2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Line2f_(ref List<Line2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Line3f_(ref List<Line3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Plane2f_(ref List<Plane2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Plane3f_(ref List<Plane3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_PlaneWithPoint3f_(ref List<PlaneWithPoint3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Quad2f_(ref List<Quad2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Quad3f_(ref List<Quad3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Ray2f_(ref List<Ray2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Ray3f_(ref List<Ray3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Sphere3f_(ref List<Sphere3f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Triangle2f_(ref List<Triangle2f> v) { CodeListOfStruct(v); }\r\n        public void CodeList_of_Triangle3f_(ref List<Triangle3f> v) { CodeListOfStruct(v); }\r\n\r\n        #endregion\r\n\r\n        #region Arrays of Tensors\r\n\r\n        public void CodeVector_of_Byte_Array(ref Vector<byte>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_SByte_Array(ref Vector<sbyte>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Short_Array(ref Vector<short>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_UShort_Array(ref Vector<ushort>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Int_Array(ref Vector<int>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_UInt_Array(ref Vector<uint>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Long_Array(ref Vector<long>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_ULong_Array(ref Vector<ulong>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Float_Array(ref Vector<float>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Double_Array(ref Vector<double>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Fraction_Array(ref Vector<Fraction>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V2i_Array(ref Vector<V2i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V2l_Array(ref Vector<V2l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V2f_Array(ref Vector<V2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V2d_Array(ref Vector<V2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V3i_Array(ref Vector<V3i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V3l_Array(ref Vector<V3l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V3f_Array(ref Vector<V3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V3d_Array(ref Vector<V3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V4i_Array(ref Vector<V4i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V4l_Array(ref Vector<V4l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V4f_Array(ref Vector<V4f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_V4d_Array(ref Vector<V4d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M22i_Array(ref Vector<M22i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M22l_Array(ref Vector<M22l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M22f_Array(ref Vector<M22f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M22d_Array(ref Vector<M22d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M23i_Array(ref Vector<M23i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M23l_Array(ref Vector<M23l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M23f_Array(ref Vector<M23f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M23d_Array(ref Vector<M23d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M33i_Array(ref Vector<M33i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M33l_Array(ref Vector<M33l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M33f_Array(ref Vector<M33f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M33d_Array(ref Vector<M33d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M34i_Array(ref Vector<M34i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M34l_Array(ref Vector<M34l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M34f_Array(ref Vector<M34f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M34d_Array(ref Vector<M34d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M44i_Array(ref Vector<M44i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M44l_Array(ref Vector<M44l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M44f_Array(ref Vector<M44f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_M44d_Array(ref Vector<M44d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C3b_Array(ref Vector<C3b>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C3us_Array(ref Vector<C3us>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C3ui_Array(ref Vector<C3ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C3f_Array(ref Vector<C3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C3d_Array(ref Vector<C3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C4b_Array(ref Vector<C4b>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C4us_Array(ref Vector<C4us>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C4ui_Array(ref Vector<C4ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C4f_Array(ref Vector<C4f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_C4d_Array(ref Vector<C4d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1b_Array(ref Vector<Range1b>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1sb_Array(ref Vector<Range1sb>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1s_Array(ref Vector<Range1s>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1us_Array(ref Vector<Range1us>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1i_Array(ref Vector<Range1i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1ui_Array(ref Vector<Range1ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1l_Array(ref Vector<Range1l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1ul_Array(ref Vector<Range1ul>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1f_Array(ref Vector<Range1f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Range1d_Array(ref Vector<Range1d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Box2i_Array(ref Vector<Box2i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Box2l_Array(ref Vector<Box2l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Box2f_Array(ref Vector<Box2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Box2d_Array(ref Vector<Box2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Box3i_Array(ref Vector<Box3i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Box3l_Array(ref Vector<Box3l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Box3f_Array(ref Vector<Box3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Box3d_Array(ref Vector<Box3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Euclidean3f_Array(ref Vector<Euclidean3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Euclidean3d_Array(ref Vector<Euclidean3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Rot2f_Array(ref Vector<Rot2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Rot2d_Array(ref Vector<Rot2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Rot3f_Array(ref Vector<Rot3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Rot3d_Array(ref Vector<Rot3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Scale3f_Array(ref Vector<Scale3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Scale3d_Array(ref Vector<Scale3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Shift3f_Array(ref Vector<Shift3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Shift3d_Array(ref Vector<Shift3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Trafo2f_Array(ref Vector<Trafo2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Trafo2d_Array(ref Vector<Trafo2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Trafo3f_Array(ref Vector<Trafo3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Trafo3d_Array(ref Vector<Trafo3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Bool_Array(ref Vector<bool>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Char_Array(ref Vector<char>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_String_Array(ref Vector<string>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Type_Array(ref Vector<Type>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Guid_Array(ref Vector<Guid>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Symbol_Array(ref Vector<Symbol>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Circle2d_Array(ref Vector<Circle2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Line2d_Array(ref Vector<Line2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Line3d_Array(ref Vector<Line3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Plane2d_Array(ref Vector<Plane2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Plane3d_Array(ref Vector<Plane3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_PlaneWithPoint3d_Array(ref Vector<PlaneWithPoint3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Quad2d_Array(ref Vector<Quad2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Quad3d_Array(ref Vector<Quad3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Ray2d_Array(ref Vector<Ray2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Ray3d_Array(ref Vector<Ray3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Sphere3d_Array(ref Vector<Sphere3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Triangle2d_Array(ref Vector<Triangle2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Triangle3d_Array(ref Vector<Triangle3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Circle2f_Array(ref Vector<Circle2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Line2f_Array(ref Vector<Line2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Line3f_Array(ref Vector<Line3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Plane2f_Array(ref Vector<Plane2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Plane3f_Array(ref Vector<Plane3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_PlaneWithPoint3f_Array(ref Vector<PlaneWithPoint3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Quad2f_Array(ref Vector<Quad2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Quad3f_Array(ref Vector<Quad3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Ray2f_Array(ref Vector<Ray2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Ray3f_Array(ref Vector<Ray3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Sphere3f_Array(ref Vector<Sphere3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Triangle2f_Array(ref Vector<Triangle2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVector_of_Triangle3f_Array(ref Vector<Triangle3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Byte_Array(ref Matrix<byte>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_SByte_Array(ref Matrix<sbyte>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Short_Array(ref Matrix<short>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_UShort_Array(ref Matrix<ushort>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Int_Array(ref Matrix<int>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_UInt_Array(ref Matrix<uint>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Long_Array(ref Matrix<long>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_ULong_Array(ref Matrix<ulong>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Float_Array(ref Matrix<float>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Double_Array(ref Matrix<double>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Fraction_Array(ref Matrix<Fraction>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V2i_Array(ref Matrix<V2i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V2l_Array(ref Matrix<V2l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V2f_Array(ref Matrix<V2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V2d_Array(ref Matrix<V2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V3i_Array(ref Matrix<V3i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V3l_Array(ref Matrix<V3l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V3f_Array(ref Matrix<V3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V3d_Array(ref Matrix<V3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V4i_Array(ref Matrix<V4i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V4l_Array(ref Matrix<V4l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V4f_Array(ref Matrix<V4f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_V4d_Array(ref Matrix<V4d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M22i_Array(ref Matrix<M22i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M22l_Array(ref Matrix<M22l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M22f_Array(ref Matrix<M22f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M22d_Array(ref Matrix<M22d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M23i_Array(ref Matrix<M23i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M23l_Array(ref Matrix<M23l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M23f_Array(ref Matrix<M23f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M23d_Array(ref Matrix<M23d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M33i_Array(ref Matrix<M33i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M33l_Array(ref Matrix<M33l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M33f_Array(ref Matrix<M33f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M33d_Array(ref Matrix<M33d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M34i_Array(ref Matrix<M34i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M34l_Array(ref Matrix<M34l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M34f_Array(ref Matrix<M34f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M34d_Array(ref Matrix<M34d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M44i_Array(ref Matrix<M44i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M44l_Array(ref Matrix<M44l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M44f_Array(ref Matrix<M44f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_M44d_Array(ref Matrix<M44d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C3b_Array(ref Matrix<C3b>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C3us_Array(ref Matrix<C3us>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C3ui_Array(ref Matrix<C3ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C3f_Array(ref Matrix<C3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C3d_Array(ref Matrix<C3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C4b_Array(ref Matrix<C4b>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C4us_Array(ref Matrix<C4us>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C4ui_Array(ref Matrix<C4ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C4f_Array(ref Matrix<C4f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_C4d_Array(ref Matrix<C4d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1b_Array(ref Matrix<Range1b>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1sb_Array(ref Matrix<Range1sb>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1s_Array(ref Matrix<Range1s>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1us_Array(ref Matrix<Range1us>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1i_Array(ref Matrix<Range1i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1ui_Array(ref Matrix<Range1ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1l_Array(ref Matrix<Range1l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1ul_Array(ref Matrix<Range1ul>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1f_Array(ref Matrix<Range1f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Range1d_Array(ref Matrix<Range1d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Box2i_Array(ref Matrix<Box2i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Box2l_Array(ref Matrix<Box2l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Box2f_Array(ref Matrix<Box2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Box2d_Array(ref Matrix<Box2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Box3i_Array(ref Matrix<Box3i>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Box3l_Array(ref Matrix<Box3l>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Box3f_Array(ref Matrix<Box3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Box3d_Array(ref Matrix<Box3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Euclidean3f_Array(ref Matrix<Euclidean3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Euclidean3d_Array(ref Matrix<Euclidean3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Rot2f_Array(ref Matrix<Rot2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Rot2d_Array(ref Matrix<Rot2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Rot3f_Array(ref Matrix<Rot3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Rot3d_Array(ref Matrix<Rot3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Scale3f_Array(ref Matrix<Scale3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Scale3d_Array(ref Matrix<Scale3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Shift3f_Array(ref Matrix<Shift3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Shift3d_Array(ref Matrix<Shift3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Trafo2f_Array(ref Matrix<Trafo2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Trafo2d_Array(ref Matrix<Trafo2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Trafo3f_Array(ref Matrix<Trafo3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Trafo3d_Array(ref Matrix<Trafo3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Bool_Array(ref Matrix<bool>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Char_Array(ref Matrix<char>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_String_Array(ref Matrix<string>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Type_Array(ref Matrix<Type>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Guid_Array(ref Matrix<Guid>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Symbol_Array(ref Matrix<Symbol>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Circle2d_Array(ref Matrix<Circle2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Line2d_Array(ref Matrix<Line2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Line3d_Array(ref Matrix<Line3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Plane2d_Array(ref Matrix<Plane2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Plane3d_Array(ref Matrix<Plane3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_PlaneWithPoint3d_Array(ref Matrix<PlaneWithPoint3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Quad2d_Array(ref Matrix<Quad2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Quad3d_Array(ref Matrix<Quad3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Ray2d_Array(ref Matrix<Ray2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Ray3d_Array(ref Matrix<Ray3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Sphere3d_Array(ref Matrix<Sphere3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Triangle2d_Array(ref Matrix<Triangle2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Triangle3d_Array(ref Matrix<Triangle3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Circle2f_Array(ref Matrix<Circle2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Line2f_Array(ref Matrix<Line2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Line3f_Array(ref Matrix<Line3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Plane2f_Array(ref Matrix<Plane2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Plane3f_Array(ref Matrix<Plane3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_PlaneWithPoint3f_Array(ref Matrix<PlaneWithPoint3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Quad2f_Array(ref Matrix<Quad2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Quad3f_Array(ref Matrix<Quad3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Ray2f_Array(ref Matrix<Ray2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Ray3f_Array(ref Matrix<Ray3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Sphere3f_Array(ref Matrix<Sphere3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Triangle2f_Array(ref Matrix<Triangle2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeMatrix_of_Triangle3f_Array(ref Matrix<Triangle3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Byte_Array(ref Volume<byte>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_SByte_Array(ref Volume<sbyte>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Short_Array(ref Volume<short>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_UShort_Array(ref Volume<ushort>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Int_Array(ref Volume<int>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_UInt_Array(ref Volume<uint>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Long_Array(ref Volume<long>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_ULong_Array(ref Volume<ulong>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Float_Array(ref Volume<float>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Double_Array(ref Volume<double>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Fraction_Array(ref Volume<Fraction>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V2i_Array(ref Volume<V2i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V2l_Array(ref Volume<V2l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V2f_Array(ref Volume<V2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V2d_Array(ref Volume<V2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V3i_Array(ref Volume<V3i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V3l_Array(ref Volume<V3l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V3f_Array(ref Volume<V3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V3d_Array(ref Volume<V3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V4i_Array(ref Volume<V4i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V4l_Array(ref Volume<V4l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V4f_Array(ref Volume<V4f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_V4d_Array(ref Volume<V4d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M22i_Array(ref Volume<M22i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M22l_Array(ref Volume<M22l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M22f_Array(ref Volume<M22f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M22d_Array(ref Volume<M22d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M23i_Array(ref Volume<M23i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M23l_Array(ref Volume<M23l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M23f_Array(ref Volume<M23f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M23d_Array(ref Volume<M23d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M33i_Array(ref Volume<M33i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M33l_Array(ref Volume<M33l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M33f_Array(ref Volume<M33f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M33d_Array(ref Volume<M33d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M34i_Array(ref Volume<M34i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M34l_Array(ref Volume<M34l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M34f_Array(ref Volume<M34f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M34d_Array(ref Volume<M34d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M44i_Array(ref Volume<M44i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M44l_Array(ref Volume<M44l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M44f_Array(ref Volume<M44f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_M44d_Array(ref Volume<M44d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C3b_Array(ref Volume<C3b>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C3us_Array(ref Volume<C3us>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C3ui_Array(ref Volume<C3ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C3f_Array(ref Volume<C3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C3d_Array(ref Volume<C3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C4b_Array(ref Volume<C4b>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C4us_Array(ref Volume<C4us>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C4ui_Array(ref Volume<C4ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C4f_Array(ref Volume<C4f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_C4d_Array(ref Volume<C4d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1b_Array(ref Volume<Range1b>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1sb_Array(ref Volume<Range1sb>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1s_Array(ref Volume<Range1s>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1us_Array(ref Volume<Range1us>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1i_Array(ref Volume<Range1i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1ui_Array(ref Volume<Range1ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1l_Array(ref Volume<Range1l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1ul_Array(ref Volume<Range1ul>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1f_Array(ref Volume<Range1f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Range1d_Array(ref Volume<Range1d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Box2i_Array(ref Volume<Box2i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Box2l_Array(ref Volume<Box2l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Box2f_Array(ref Volume<Box2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Box2d_Array(ref Volume<Box2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Box3i_Array(ref Volume<Box3i>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Box3l_Array(ref Volume<Box3l>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Box3f_Array(ref Volume<Box3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Box3d_Array(ref Volume<Box3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Euclidean3f_Array(ref Volume<Euclidean3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Euclidean3d_Array(ref Volume<Euclidean3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Rot2f_Array(ref Volume<Rot2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Rot2d_Array(ref Volume<Rot2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Rot3f_Array(ref Volume<Rot3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Rot3d_Array(ref Volume<Rot3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Scale3f_Array(ref Volume<Scale3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Scale3d_Array(ref Volume<Scale3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Shift3f_Array(ref Volume<Shift3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Shift3d_Array(ref Volume<Shift3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Trafo2f_Array(ref Volume<Trafo2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Trafo2d_Array(ref Volume<Trafo2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Trafo3f_Array(ref Volume<Trafo3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Trafo3d_Array(ref Volume<Trafo3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Bool_Array(ref Volume<bool>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Char_Array(ref Volume<char>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_String_Array(ref Volume<string>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Type_Array(ref Volume<Type>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Guid_Array(ref Volume<Guid>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Symbol_Array(ref Volume<Symbol>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Circle2d_Array(ref Volume<Circle2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Line2d_Array(ref Volume<Line2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Line3d_Array(ref Volume<Line3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Plane2d_Array(ref Volume<Plane2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Plane3d_Array(ref Volume<Plane3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_PlaneWithPoint3d_Array(ref Volume<PlaneWithPoint3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Quad2d_Array(ref Volume<Quad2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Quad3d_Array(ref Volume<Quad3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Ray2d_Array(ref Volume<Ray2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Ray3d_Array(ref Volume<Ray3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Sphere3d_Array(ref Volume<Sphere3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Triangle2d_Array(ref Volume<Triangle2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Triangle3d_Array(ref Volume<Triangle3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Circle2f_Array(ref Volume<Circle2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Line2f_Array(ref Volume<Line2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Line3f_Array(ref Volume<Line3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Plane2f_Array(ref Volume<Plane2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Plane3f_Array(ref Volume<Plane3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_PlaneWithPoint3f_Array(ref Volume<PlaneWithPoint3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Quad2f_Array(ref Volume<Quad2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Quad3f_Array(ref Volume<Quad3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Ray2f_Array(ref Volume<Ray2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Ray3f_Array(ref Volume<Ray3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Sphere3f_Array(ref Volume<Sphere3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Triangle2f_Array(ref Volume<Triangle2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeVolume_of_Triangle3f_Array(ref Volume<Triangle3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Byte_Array(ref Tensor<byte>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_SByte_Array(ref Tensor<sbyte>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Short_Array(ref Tensor<short>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_UShort_Array(ref Tensor<ushort>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Int_Array(ref Tensor<int>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_UInt_Array(ref Tensor<uint>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Long_Array(ref Tensor<long>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_ULong_Array(ref Tensor<ulong>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Float_Array(ref Tensor<float>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Double_Array(ref Tensor<double>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Fraction_Array(ref Tensor<Fraction>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V2i_Array(ref Tensor<V2i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V2l_Array(ref Tensor<V2l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V2f_Array(ref Tensor<V2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V2d_Array(ref Tensor<V2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V3i_Array(ref Tensor<V3i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V3l_Array(ref Tensor<V3l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V3f_Array(ref Tensor<V3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V3d_Array(ref Tensor<V3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V4i_Array(ref Tensor<V4i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V4l_Array(ref Tensor<V4l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V4f_Array(ref Tensor<V4f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_V4d_Array(ref Tensor<V4d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M22i_Array(ref Tensor<M22i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M22l_Array(ref Tensor<M22l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M22f_Array(ref Tensor<M22f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M22d_Array(ref Tensor<M22d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M23i_Array(ref Tensor<M23i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M23l_Array(ref Tensor<M23l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M23f_Array(ref Tensor<M23f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M23d_Array(ref Tensor<M23d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M33i_Array(ref Tensor<M33i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M33l_Array(ref Tensor<M33l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M33f_Array(ref Tensor<M33f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M33d_Array(ref Tensor<M33d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M34i_Array(ref Tensor<M34i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M34l_Array(ref Tensor<M34l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M34f_Array(ref Tensor<M34f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M34d_Array(ref Tensor<M34d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M44i_Array(ref Tensor<M44i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M44l_Array(ref Tensor<M44l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M44f_Array(ref Tensor<M44f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_M44d_Array(ref Tensor<M44d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C3b_Array(ref Tensor<C3b>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C3us_Array(ref Tensor<C3us>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C3ui_Array(ref Tensor<C3ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C3f_Array(ref Tensor<C3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C3d_Array(ref Tensor<C3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C4b_Array(ref Tensor<C4b>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C4us_Array(ref Tensor<C4us>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C4ui_Array(ref Tensor<C4ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C4f_Array(ref Tensor<C4f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_C4d_Array(ref Tensor<C4d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1b_Array(ref Tensor<Range1b>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1sb_Array(ref Tensor<Range1sb>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1s_Array(ref Tensor<Range1s>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1us_Array(ref Tensor<Range1us>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1i_Array(ref Tensor<Range1i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1ui_Array(ref Tensor<Range1ui>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1l_Array(ref Tensor<Range1l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1ul_Array(ref Tensor<Range1ul>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1f_Array(ref Tensor<Range1f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Range1d_Array(ref Tensor<Range1d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Box2i_Array(ref Tensor<Box2i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Box2l_Array(ref Tensor<Box2l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Box2f_Array(ref Tensor<Box2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Box2d_Array(ref Tensor<Box2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Box3i_Array(ref Tensor<Box3i>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Box3l_Array(ref Tensor<Box3l>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Box3f_Array(ref Tensor<Box3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Box3d_Array(ref Tensor<Box3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Euclidean3f_Array(ref Tensor<Euclidean3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Euclidean3d_Array(ref Tensor<Euclidean3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Rot2f_Array(ref Tensor<Rot2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Rot2d_Array(ref Tensor<Rot2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Rot3f_Array(ref Tensor<Rot3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Rot3d_Array(ref Tensor<Rot3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Scale3f_Array(ref Tensor<Scale3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Scale3d_Array(ref Tensor<Scale3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Shift3f_Array(ref Tensor<Shift3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Shift3d_Array(ref Tensor<Shift3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Trafo2f_Array(ref Tensor<Trafo2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Trafo2d_Array(ref Tensor<Trafo2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Trafo3f_Array(ref Tensor<Trafo3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Trafo3d_Array(ref Tensor<Trafo3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Bool_Array(ref Tensor<bool>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Char_Array(ref Tensor<char>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_String_Array(ref Tensor<string>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Type_Array(ref Tensor<Type>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Guid_Array(ref Tensor<Guid>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Symbol_Array(ref Tensor<Symbol>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Circle2d_Array(ref Tensor<Circle2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Line2d_Array(ref Tensor<Line2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Line3d_Array(ref Tensor<Line3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Plane2d_Array(ref Tensor<Plane2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Plane3d_Array(ref Tensor<Plane3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_PlaneWithPoint3d_Array(ref Tensor<PlaneWithPoint3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Quad2d_Array(ref Tensor<Quad2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Quad3d_Array(ref Tensor<Quad3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Ray2d_Array(ref Tensor<Ray2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Ray3d_Array(ref Tensor<Ray3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Sphere3d_Array(ref Tensor<Sphere3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Triangle2d_Array(ref Tensor<Triangle2d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Triangle3d_Array(ref Tensor<Triangle3d>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Circle2f_Array(ref Tensor<Circle2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Line2f_Array(ref Tensor<Line2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Line3f_Array(ref Tensor<Line3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Plane2f_Array(ref Tensor<Plane2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Plane3f_Array(ref Tensor<Plane3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_PlaneWithPoint3f_Array(ref Tensor<PlaneWithPoint3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Quad2f_Array(ref Tensor<Quad2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Quad3f_Array(ref Tensor<Quad3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Ray2f_Array(ref Tensor<Ray2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Ray3f_Array(ref Tensor<Ray3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Sphere3f_Array(ref Tensor<Sphere3f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Triangle2f_Array(ref Tensor<Triangle2f>[] v) { CodeArrayOf(v); }\r\n        public void CodeTensor_of_Triangle3f_Array(ref Tensor<Triangle3f>[] v) { CodeArrayOf(v); }\r\n\r\n        #endregion\r\n\r\n        #region Lists of Tensors\r\n\r\n        public void CodeList_of_Vector_of_Byte__(ref List<Vector<byte>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_SByte__(ref List<Vector<sbyte>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Short__(ref List<Vector<short>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_UShort__(ref List<Vector<ushort>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Int__(ref List<Vector<int>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_UInt__(ref List<Vector<uint>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Long__(ref List<Vector<long>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_ULong__(ref List<Vector<ulong>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Float__(ref List<Vector<float>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Double__(ref List<Vector<double>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Fraction__(ref List<Vector<Fraction>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V2i__(ref List<Vector<V2i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V2l__(ref List<Vector<V2l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V2f__(ref List<Vector<V2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V2d__(ref List<Vector<V2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V3i__(ref List<Vector<V3i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V3l__(ref List<Vector<V3l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V3f__(ref List<Vector<V3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V3d__(ref List<Vector<V3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V4i__(ref List<Vector<V4i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V4l__(ref List<Vector<V4l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V4f__(ref List<Vector<V4f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_V4d__(ref List<Vector<V4d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M22i__(ref List<Vector<M22i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M22l__(ref List<Vector<M22l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M22f__(ref List<Vector<M22f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M22d__(ref List<Vector<M22d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M23i__(ref List<Vector<M23i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M23l__(ref List<Vector<M23l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M23f__(ref List<Vector<M23f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M23d__(ref List<Vector<M23d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M33i__(ref List<Vector<M33i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M33l__(ref List<Vector<M33l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M33f__(ref List<Vector<M33f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M33d__(ref List<Vector<M33d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M34i__(ref List<Vector<M34i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M34l__(ref List<Vector<M34l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M34f__(ref List<Vector<M34f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M34d__(ref List<Vector<M34d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M44i__(ref List<Vector<M44i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M44l__(ref List<Vector<M44l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M44f__(ref List<Vector<M44f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_M44d__(ref List<Vector<M44d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C3b__(ref List<Vector<C3b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C3us__(ref List<Vector<C3us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C3ui__(ref List<Vector<C3ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C3f__(ref List<Vector<C3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C3d__(ref List<Vector<C3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C4b__(ref List<Vector<C4b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C4us__(ref List<Vector<C4us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C4ui__(ref List<Vector<C4ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C4f__(ref List<Vector<C4f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_C4d__(ref List<Vector<C4d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1b__(ref List<Vector<Range1b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1sb__(ref List<Vector<Range1sb>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1s__(ref List<Vector<Range1s>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1us__(ref List<Vector<Range1us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1i__(ref List<Vector<Range1i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1ui__(ref List<Vector<Range1ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1l__(ref List<Vector<Range1l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1ul__(ref List<Vector<Range1ul>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1f__(ref List<Vector<Range1f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Range1d__(ref List<Vector<Range1d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Box2i__(ref List<Vector<Box2i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Box2l__(ref List<Vector<Box2l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Box2f__(ref List<Vector<Box2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Box2d__(ref List<Vector<Box2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Box3i__(ref List<Vector<Box3i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Box3l__(ref List<Vector<Box3l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Box3f__(ref List<Vector<Box3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Box3d__(ref List<Vector<Box3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Euclidean3f__(ref List<Vector<Euclidean3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Euclidean3d__(ref List<Vector<Euclidean3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Rot2f__(ref List<Vector<Rot2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Rot2d__(ref List<Vector<Rot2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Rot3f__(ref List<Vector<Rot3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Rot3d__(ref List<Vector<Rot3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Scale3f__(ref List<Vector<Scale3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Scale3d__(ref List<Vector<Scale3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Shift3f__(ref List<Vector<Shift3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Shift3d__(ref List<Vector<Shift3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Trafo2f__(ref List<Vector<Trafo2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Trafo2d__(ref List<Vector<Trafo2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Trafo3f__(ref List<Vector<Trafo3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Trafo3d__(ref List<Vector<Trafo3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Bool__(ref List<Vector<bool>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Char__(ref List<Vector<char>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_String__(ref List<Vector<string>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Type__(ref List<Vector<Type>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Guid__(ref List<Vector<Guid>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Symbol__(ref List<Vector<Symbol>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Circle2d__(ref List<Vector<Circle2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Line2d__(ref List<Vector<Line2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Line3d__(ref List<Vector<Line3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Plane2d__(ref List<Vector<Plane2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Plane3d__(ref List<Vector<Plane3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3d__(ref List<Vector<PlaneWithPoint3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Quad2d__(ref List<Vector<Quad2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Quad3d__(ref List<Vector<Quad3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Ray2d__(ref List<Vector<Ray2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Ray3d__(ref List<Vector<Ray3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Sphere3d__(ref List<Vector<Sphere3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Triangle2d__(ref List<Vector<Triangle2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Triangle3d__(ref List<Vector<Triangle3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Circle2f__(ref List<Vector<Circle2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Line2f__(ref List<Vector<Line2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Line3f__(ref List<Vector<Line3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Plane2f__(ref List<Vector<Plane2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Plane3f__(ref List<Vector<Plane3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_PlaneWithPoint3f__(ref List<Vector<PlaneWithPoint3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Quad2f__(ref List<Vector<Quad2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Quad3f__(ref List<Vector<Quad3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Ray2f__(ref List<Vector<Ray2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Ray3f__(ref List<Vector<Ray3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Sphere3f__(ref List<Vector<Sphere3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Triangle2f__(ref List<Vector<Triangle2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Vector_of_Triangle3f__(ref List<Vector<Triangle3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Byte__(ref List<Matrix<byte>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_SByte__(ref List<Matrix<sbyte>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Short__(ref List<Matrix<short>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_UShort__(ref List<Matrix<ushort>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Int__(ref List<Matrix<int>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_UInt__(ref List<Matrix<uint>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Long__(ref List<Matrix<long>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_ULong__(ref List<Matrix<ulong>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Float__(ref List<Matrix<float>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Double__(ref List<Matrix<double>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Fraction__(ref List<Matrix<Fraction>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V2i__(ref List<Matrix<V2i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V2l__(ref List<Matrix<V2l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V2f__(ref List<Matrix<V2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V2d__(ref List<Matrix<V2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V3i__(ref List<Matrix<V3i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V3l__(ref List<Matrix<V3l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V3f__(ref List<Matrix<V3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V3d__(ref List<Matrix<V3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V4i__(ref List<Matrix<V4i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V4l__(ref List<Matrix<V4l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V4f__(ref List<Matrix<V4f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_V4d__(ref List<Matrix<V4d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M22i__(ref List<Matrix<M22i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M22l__(ref List<Matrix<M22l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M22f__(ref List<Matrix<M22f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M22d__(ref List<Matrix<M22d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M23i__(ref List<Matrix<M23i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M23l__(ref List<Matrix<M23l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M23f__(ref List<Matrix<M23f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M23d__(ref List<Matrix<M23d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M33i__(ref List<Matrix<M33i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M33l__(ref List<Matrix<M33l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M33f__(ref List<Matrix<M33f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M33d__(ref List<Matrix<M33d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M34i__(ref List<Matrix<M34i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M34l__(ref List<Matrix<M34l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M34f__(ref List<Matrix<M34f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M34d__(ref List<Matrix<M34d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M44i__(ref List<Matrix<M44i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M44l__(ref List<Matrix<M44l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M44f__(ref List<Matrix<M44f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_M44d__(ref List<Matrix<M44d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C3b__(ref List<Matrix<C3b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C3us__(ref List<Matrix<C3us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C3ui__(ref List<Matrix<C3ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C3f__(ref List<Matrix<C3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C3d__(ref List<Matrix<C3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C4b__(ref List<Matrix<C4b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C4us__(ref List<Matrix<C4us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C4ui__(ref List<Matrix<C4ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C4f__(ref List<Matrix<C4f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_C4d__(ref List<Matrix<C4d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1b__(ref List<Matrix<Range1b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1sb__(ref List<Matrix<Range1sb>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1s__(ref List<Matrix<Range1s>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1us__(ref List<Matrix<Range1us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1i__(ref List<Matrix<Range1i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1ui__(ref List<Matrix<Range1ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1l__(ref List<Matrix<Range1l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1ul__(ref List<Matrix<Range1ul>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1f__(ref List<Matrix<Range1f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Range1d__(ref List<Matrix<Range1d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Box2i__(ref List<Matrix<Box2i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Box2l__(ref List<Matrix<Box2l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Box2f__(ref List<Matrix<Box2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Box2d__(ref List<Matrix<Box2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Box3i__(ref List<Matrix<Box3i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Box3l__(ref List<Matrix<Box3l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Box3f__(ref List<Matrix<Box3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Box3d__(ref List<Matrix<Box3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Euclidean3f__(ref List<Matrix<Euclidean3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Euclidean3d__(ref List<Matrix<Euclidean3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Rot2f__(ref List<Matrix<Rot2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Rot2d__(ref List<Matrix<Rot2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Rot3f__(ref List<Matrix<Rot3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Rot3d__(ref List<Matrix<Rot3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Scale3f__(ref List<Matrix<Scale3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Scale3d__(ref List<Matrix<Scale3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Shift3f__(ref List<Matrix<Shift3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Shift3d__(ref List<Matrix<Shift3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Trafo2f__(ref List<Matrix<Trafo2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Trafo2d__(ref List<Matrix<Trafo2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Trafo3f__(ref List<Matrix<Trafo3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Trafo3d__(ref List<Matrix<Trafo3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Bool__(ref List<Matrix<bool>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Char__(ref List<Matrix<char>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_String__(ref List<Matrix<string>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Type__(ref List<Matrix<Type>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Guid__(ref List<Matrix<Guid>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Symbol__(ref List<Matrix<Symbol>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Circle2d__(ref List<Matrix<Circle2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Line2d__(ref List<Matrix<Line2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Line3d__(ref List<Matrix<Line3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Plane2d__(ref List<Matrix<Plane2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Plane3d__(ref List<Matrix<Plane3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3d__(ref List<Matrix<PlaneWithPoint3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Quad2d__(ref List<Matrix<Quad2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Quad3d__(ref List<Matrix<Quad3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Ray2d__(ref List<Matrix<Ray2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Ray3d__(ref List<Matrix<Ray3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Sphere3d__(ref List<Matrix<Sphere3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Triangle2d__(ref List<Matrix<Triangle2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Triangle3d__(ref List<Matrix<Triangle3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Circle2f__(ref List<Matrix<Circle2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Line2f__(ref List<Matrix<Line2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Line3f__(ref List<Matrix<Line3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Plane2f__(ref List<Matrix<Plane2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Plane3f__(ref List<Matrix<Plane3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_PlaneWithPoint3f__(ref List<Matrix<PlaneWithPoint3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Quad2f__(ref List<Matrix<Quad2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Quad3f__(ref List<Matrix<Quad3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Ray2f__(ref List<Matrix<Ray2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Ray3f__(ref List<Matrix<Ray3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Sphere3f__(ref List<Matrix<Sphere3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Triangle2f__(ref List<Matrix<Triangle2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Matrix_of_Triangle3f__(ref List<Matrix<Triangle3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Byte__(ref List<Volume<byte>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_SByte__(ref List<Volume<sbyte>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Short__(ref List<Volume<short>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_UShort__(ref List<Volume<ushort>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Int__(ref List<Volume<int>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_UInt__(ref List<Volume<uint>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Long__(ref List<Volume<long>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_ULong__(ref List<Volume<ulong>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Float__(ref List<Volume<float>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Double__(ref List<Volume<double>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Fraction__(ref List<Volume<Fraction>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V2i__(ref List<Volume<V2i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V2l__(ref List<Volume<V2l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V2f__(ref List<Volume<V2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V2d__(ref List<Volume<V2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V3i__(ref List<Volume<V3i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V3l__(ref List<Volume<V3l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V3f__(ref List<Volume<V3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V3d__(ref List<Volume<V3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V4i__(ref List<Volume<V4i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V4l__(ref List<Volume<V4l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V4f__(ref List<Volume<V4f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_V4d__(ref List<Volume<V4d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M22i__(ref List<Volume<M22i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M22l__(ref List<Volume<M22l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M22f__(ref List<Volume<M22f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M22d__(ref List<Volume<M22d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M23i__(ref List<Volume<M23i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M23l__(ref List<Volume<M23l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M23f__(ref List<Volume<M23f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M23d__(ref List<Volume<M23d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M33i__(ref List<Volume<M33i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M33l__(ref List<Volume<M33l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M33f__(ref List<Volume<M33f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M33d__(ref List<Volume<M33d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M34i__(ref List<Volume<M34i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M34l__(ref List<Volume<M34l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M34f__(ref List<Volume<M34f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M34d__(ref List<Volume<M34d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M44i__(ref List<Volume<M44i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M44l__(ref List<Volume<M44l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M44f__(ref List<Volume<M44f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_M44d__(ref List<Volume<M44d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C3b__(ref List<Volume<C3b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C3us__(ref List<Volume<C3us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C3ui__(ref List<Volume<C3ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C3f__(ref List<Volume<C3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C3d__(ref List<Volume<C3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C4b__(ref List<Volume<C4b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C4us__(ref List<Volume<C4us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C4ui__(ref List<Volume<C4ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C4f__(ref List<Volume<C4f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_C4d__(ref List<Volume<C4d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1b__(ref List<Volume<Range1b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1sb__(ref List<Volume<Range1sb>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1s__(ref List<Volume<Range1s>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1us__(ref List<Volume<Range1us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1i__(ref List<Volume<Range1i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1ui__(ref List<Volume<Range1ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1l__(ref List<Volume<Range1l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1ul__(ref List<Volume<Range1ul>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1f__(ref List<Volume<Range1f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Range1d__(ref List<Volume<Range1d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Box2i__(ref List<Volume<Box2i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Box2l__(ref List<Volume<Box2l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Box2f__(ref List<Volume<Box2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Box2d__(ref List<Volume<Box2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Box3i__(ref List<Volume<Box3i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Box3l__(ref List<Volume<Box3l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Box3f__(ref List<Volume<Box3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Box3d__(ref List<Volume<Box3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Euclidean3f__(ref List<Volume<Euclidean3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Euclidean3d__(ref List<Volume<Euclidean3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Rot2f__(ref List<Volume<Rot2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Rot2d__(ref List<Volume<Rot2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Rot3f__(ref List<Volume<Rot3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Rot3d__(ref List<Volume<Rot3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Scale3f__(ref List<Volume<Scale3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Scale3d__(ref List<Volume<Scale3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Shift3f__(ref List<Volume<Shift3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Shift3d__(ref List<Volume<Shift3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Trafo2f__(ref List<Volume<Trafo2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Trafo2d__(ref List<Volume<Trafo2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Trafo3f__(ref List<Volume<Trafo3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Trafo3d__(ref List<Volume<Trafo3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Bool__(ref List<Volume<bool>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Char__(ref List<Volume<char>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_String__(ref List<Volume<string>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Type__(ref List<Volume<Type>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Guid__(ref List<Volume<Guid>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Symbol__(ref List<Volume<Symbol>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Circle2d__(ref List<Volume<Circle2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Line2d__(ref List<Volume<Line2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Line3d__(ref List<Volume<Line3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Plane2d__(ref List<Volume<Plane2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Plane3d__(ref List<Volume<Plane3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3d__(ref List<Volume<PlaneWithPoint3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Quad2d__(ref List<Volume<Quad2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Quad3d__(ref List<Volume<Quad3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Ray2d__(ref List<Volume<Ray2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Ray3d__(ref List<Volume<Ray3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Sphere3d__(ref List<Volume<Sphere3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Triangle2d__(ref List<Volume<Triangle2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Triangle3d__(ref List<Volume<Triangle3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Circle2f__(ref List<Volume<Circle2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Line2f__(ref List<Volume<Line2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Line3f__(ref List<Volume<Line3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Plane2f__(ref List<Volume<Plane2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Plane3f__(ref List<Volume<Plane3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_PlaneWithPoint3f__(ref List<Volume<PlaneWithPoint3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Quad2f__(ref List<Volume<Quad2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Quad3f__(ref List<Volume<Quad3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Ray2f__(ref List<Volume<Ray2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Ray3f__(ref List<Volume<Ray3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Sphere3f__(ref List<Volume<Sphere3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Triangle2f__(ref List<Volume<Triangle2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Volume_of_Triangle3f__(ref List<Volume<Triangle3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Byte__(ref List<Tensor<byte>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_SByte__(ref List<Tensor<sbyte>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Short__(ref List<Tensor<short>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_UShort__(ref List<Tensor<ushort>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Int__(ref List<Tensor<int>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_UInt__(ref List<Tensor<uint>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Long__(ref List<Tensor<long>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_ULong__(ref List<Tensor<ulong>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Float__(ref List<Tensor<float>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Double__(ref List<Tensor<double>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Fraction__(ref List<Tensor<Fraction>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V2i__(ref List<Tensor<V2i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V2l__(ref List<Tensor<V2l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V2f__(ref List<Tensor<V2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V2d__(ref List<Tensor<V2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V3i__(ref List<Tensor<V3i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V3l__(ref List<Tensor<V3l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V3f__(ref List<Tensor<V3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V3d__(ref List<Tensor<V3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V4i__(ref List<Tensor<V4i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V4l__(ref List<Tensor<V4l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V4f__(ref List<Tensor<V4f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_V4d__(ref List<Tensor<V4d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M22i__(ref List<Tensor<M22i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M22l__(ref List<Tensor<M22l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M22f__(ref List<Tensor<M22f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M22d__(ref List<Tensor<M22d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M23i__(ref List<Tensor<M23i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M23l__(ref List<Tensor<M23l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M23f__(ref List<Tensor<M23f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M23d__(ref List<Tensor<M23d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M33i__(ref List<Tensor<M33i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M33l__(ref List<Tensor<M33l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M33f__(ref List<Tensor<M33f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M33d__(ref List<Tensor<M33d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M34i__(ref List<Tensor<M34i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M34l__(ref List<Tensor<M34l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M34f__(ref List<Tensor<M34f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M34d__(ref List<Tensor<M34d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M44i__(ref List<Tensor<M44i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M44l__(ref List<Tensor<M44l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M44f__(ref List<Tensor<M44f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_M44d__(ref List<Tensor<M44d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C3b__(ref List<Tensor<C3b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C3us__(ref List<Tensor<C3us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C3ui__(ref List<Tensor<C3ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C3f__(ref List<Tensor<C3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C3d__(ref List<Tensor<C3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C4b__(ref List<Tensor<C4b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C4us__(ref List<Tensor<C4us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C4ui__(ref List<Tensor<C4ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C4f__(ref List<Tensor<C4f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_C4d__(ref List<Tensor<C4d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1b__(ref List<Tensor<Range1b>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1sb__(ref List<Tensor<Range1sb>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1s__(ref List<Tensor<Range1s>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1us__(ref List<Tensor<Range1us>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1i__(ref List<Tensor<Range1i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1ui__(ref List<Tensor<Range1ui>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1l__(ref List<Tensor<Range1l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1ul__(ref List<Tensor<Range1ul>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1f__(ref List<Tensor<Range1f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Range1d__(ref List<Tensor<Range1d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Box2i__(ref List<Tensor<Box2i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Box2l__(ref List<Tensor<Box2l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Box2f__(ref List<Tensor<Box2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Box2d__(ref List<Tensor<Box2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Box3i__(ref List<Tensor<Box3i>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Box3l__(ref List<Tensor<Box3l>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Box3f__(ref List<Tensor<Box3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Box3d__(ref List<Tensor<Box3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Euclidean3f__(ref List<Tensor<Euclidean3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Euclidean3d__(ref List<Tensor<Euclidean3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Rot2f__(ref List<Tensor<Rot2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Rot2d__(ref List<Tensor<Rot2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Rot3f__(ref List<Tensor<Rot3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Rot3d__(ref List<Tensor<Rot3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Scale3f__(ref List<Tensor<Scale3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Scale3d__(ref List<Tensor<Scale3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Shift3f__(ref List<Tensor<Shift3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Shift3d__(ref List<Tensor<Shift3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Trafo2f__(ref List<Tensor<Trafo2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Trafo2d__(ref List<Tensor<Trafo2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Trafo3f__(ref List<Tensor<Trafo3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Trafo3d__(ref List<Tensor<Trafo3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Bool__(ref List<Tensor<bool>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Char__(ref List<Tensor<char>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_String__(ref List<Tensor<string>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Type__(ref List<Tensor<Type>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Guid__(ref List<Tensor<Guid>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Symbol__(ref List<Tensor<Symbol>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Circle2d__(ref List<Tensor<Circle2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Line2d__(ref List<Tensor<Line2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Line3d__(ref List<Tensor<Line3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Plane2d__(ref List<Tensor<Plane2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Plane3d__(ref List<Tensor<Plane3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3d__(ref List<Tensor<PlaneWithPoint3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Quad2d__(ref List<Tensor<Quad2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Quad3d__(ref List<Tensor<Quad3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Ray2d__(ref List<Tensor<Ray2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Ray3d__(ref List<Tensor<Ray3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Sphere3d__(ref List<Tensor<Sphere3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Triangle2d__(ref List<Tensor<Triangle2d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Triangle3d__(ref List<Tensor<Triangle3d>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Circle2f__(ref List<Tensor<Circle2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Line2f__(ref List<Tensor<Line2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Line3f__(ref List<Tensor<Line3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Plane2f__(ref List<Tensor<Plane2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Plane3f__(ref List<Tensor<Plane3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_PlaneWithPoint3f__(ref List<Tensor<PlaneWithPoint3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Quad2f__(ref List<Tensor<Quad2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Quad3f__(ref List<Tensor<Quad3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Ray2f__(ref List<Tensor<Ray2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Ray3f__(ref List<Tensor<Ray3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Sphere3f__(ref List<Tensor<Sphere3f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Triangle2f__(ref List<Tensor<Triangle2f>> v) { CodeListOf(v); }\r\n        public void CodeList_of_Tensor_of_Triangle3f__(ref List<Tensor<Triangle3f>> v) { CodeListOf(v); }\r\n\r\n        #endregion\r\n    }\r\n}"
  },
  {
    "path": "src/Aardvark.Base.IO/XmlWritingCoder_template.cs",
    "content": "using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Xml.Linq;\n\nnamespace Aardvark.Base.Coder\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var directlyCodeableTypes = Meta.DirectlyCodeableTypes.Map(t =>t.Name);\n    //# var geometryTypes = Meta.GeometryTypes.Map(t => t.Name);\n    //# var specialSimpleTypes = new[] { \"bool\", \"char\", \"string\", \"Type\", \"Guid\", \"Symbol\" };\n    //# {\n    //# var structTypes = new List<string>();\n    //# var tensorTypes = new List<string>();\n    public partial class NewXmlWritingCoder\n    {\n        #region Vectors\n\n        //# foreach (var t in Meta.VecTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Matrices\n\n        //# foreach (var t in Meta.MatTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Ranges and Boxes\n\n        //# foreach (var t in Meta.RangeAndBoxTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Geometry Types\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"Double\" : \"Float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        public void CodeCircle2__tc__(ref Circle2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeLine2__tc__(ref Line2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeLine3__tc__(ref Line3__tc__ v) { throw new NotImplementedException(); }\n        public void CodePlane2__tc__(ref Plane2__tc__ v) { throw new NotImplementedException(); }\n        public void CodePlane3__tc__(ref Plane3__tc__ v) { throw new NotImplementedException(); }\n        public void CodePlaneWithPoint3__tc__(ref PlaneWithPoint3__tc__ v) { throw new NotImplementedException(); }\n        public void CodeQuad2__tc__(ref Quad2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeQuad3__tc__(ref Quad3__tc__ v) { throw new NotImplementedException(); }\n        public void CodeRay2__tc__(ref Ray2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeRay3__tc__(ref Ray3__tc__ v) { throw new NotImplementedException(); }\n        public void CodeSphere3__tc__(ref Sphere3__tc__ v) { throw new NotImplementedException(); }\n        public void CodeTriangle2__tc__(ref Triangle2__tc__ v) { throw new NotImplementedException(); }\n        public void CodeTriangle3__tc__(ref Triangle3__tc__ v) { throw new NotImplementedException(); }\n\n        //# }\n        #endregion\n\n        #region Colors\n\n        //# foreach (var t in Meta.ColorTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Trafos\n\n        //# foreach (var t in Meta.TrafoTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { throw new NotImplementedException(); }\n        //# }\n\n        #endregion\n\n        #region Tensors\n\n        //# foreach (var t in geometryTypes) structTypes.Add(t);\n        //# var simpleTypes = directlyCodeableTypes.Concat(specialSimpleTypes).Concat(geometryTypes);\n        //# var genericTensorTypes = new[] { \"Vector\", \"Matrix\", \"Volume\", \"Tensor\" };\n        //# genericTensorTypes.ForEach(tt => {\n        //#     simpleTypes.ForEach(t => {\n        //#         var type = tt + \"<\" + t + \">\";\n        //#         tensorTypes.Add(type);\n        //# var name = Meta.GetXmlTypeName(type);\n        public void Code__name__(ref __type__ value)\n        {\n            throw new NotImplementedException();\n        }\n\n        //#     });\n        //# });\n        #endregion\n\n        #region Arrays\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] v) { throw new NotImplementedException(); }\n        //# });\n\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[,]\");\n        public void Code__name2d__(ref __t__[,] v) { throw new NotImplementedException(); }\n        //# var name3d = Meta.GetXmlTypeName(t + \"[,,]\");\n        public void Code__name3d__(ref __t__[, ,] v) { throw new NotImplementedException(); }\n        //# });\n\n        #endregion\n\n        #region Jagged Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[][]\");\n        public void Code__name2d__(ref __t__[][] v) { throw new NotImplementedException(); }\n        //# var name3d = Meta.GetXmlTypeName(t + \"[][][]\");\n        public void Code__name3d__(ref __t__[][][] v) { throw new NotImplementedException(); }\n        //# });\n\n        #endregion\n\n        #region Lists\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> v) { throw new NotImplementedException(); }\n        //# });\n\n        #endregion\n\n        #region Arrays of Tensors\n\n        //# tensorTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] v) { throw new NotImplementedException(); }\n        //# });\n\n        #endregion\n\n        #region Lists of Tensors\n\n        //# tensorTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> v) { throw new NotImplementedException(); }\n        //# });\n\n        #endregion\n    }\n\n    //# } {\n    //# var structTypes = new List<string>();\n    //# var tensorTypes = new List<string>();\n    public partial class XmlWritingCoder\n    {\n        #region Vectors\n\n        //# foreach (var t in Meta.VecTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { AddValue(v.ToString()); }\n        //# }\n\n        #endregion\n\n        #region Matrices\n\n        //# foreach (var t in Meta.MatTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { AddValue(v.ToString()); }\n        //# }\n\n        #endregion\n\n        #region Ranges and Boxes\n\n        //# foreach (var t in Meta.RangeAndBoxTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { AddValue(v.ToString()); }\n        //# }\n\n        #endregion\n\n        #region Geometry Types\n\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ftype = isDouble ? \"Double\" : \"Float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        public void CodeCircle2__tc__(ref Circle2__tc__ v) { AddValue(v.ToString()); }\n        public void CodeLine2__tc__(ref Line2__tc__ v) { AddValue(v.ToString()); }\n        public void CodeLine3__tc__(ref Line3__tc__ v) { AddValue(v.ToString()); }\n        public void CodePlane2__tc__(ref Plane2__tc__ v) { AddValue(v.ToString()); }\n        public void CodePlane3__tc__(ref Plane3__tc__ v) { AddValue(v.ToString()); }\n        public void CodePlaneWithPoint3__tc__(ref PlaneWithPoint3__tc__ v) { AddValue(v.ToString()); }\n        public void CodeQuad2__tc__(ref Quad2__tc__ v) { AddValue(v.ToString()); }\n        public void CodeQuad3__tc__(ref Quad3__tc__ v) { AddValue(v.ToString()); }\n        public void CodeRay2__tc__(ref Ray2__tc__ v) { AddValue(v.ToString()); }\n        public void CodeRay3__tc__(ref Ray3__tc__ v) { AddValue(v.ToString()); }\n        public void CodeSphere3__tc__(ref Sphere3__tc__ v) { AddValue(v.ToString()); }\n        public void CodeTriangle2__tc__(ref Triangle2__tc__ v) { AddValue(v.ToString()); }\n        public void CodeTriangle3__tc__(ref Triangle3__tc__ v) { AddValue(v.ToString()); }\n\n        //# }\n        #endregion\n\n        #region Colors\n\n        //# foreach (var t in Meta.ColorTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { AddValue(v.ToString()); }\n        //# }\n\n        #endregion\n\n        #region Trafos\n\n        //# foreach (var t in Meta.TrafoTypes) { structTypes.Add(t.Name);\n        //# var name = Meta.GetXmlTypeName(t.Name);\n        public void Code__name__(ref __t.Name__ v) { AddValue(v.ToString()); }\n        //# }\n\n        #endregion\n\n        #region Tensors\n\n        //# foreach (var t in geometryTypes) structTypes.Add(t);\n        //# var simpleTypes = directlyCodeableTypes.Concat(specialSimpleTypes).Concat(geometryTypes);\n        //# var genericTensorTypes = new[] { \"Vector\", \"Matrix\", \"Volume\", \"Tensor\" };\n        //# var genericTensorSizes = new[] { \"long\", \"V2l\", \"V3l\", \"long[]\" };\n        //# genericTensorTypes.ForEach((tt, ti) => {\n        //#     var ts = genericTensorSizes[ti]; var tsn = Meta.GetXmlTypeName(ts);\n        //#     simpleTypes.ForEach(t => {\n        //#         var type = tt + \"<\" + t + \">\";\n        //#         tensorTypes.Add(type);\n        //# var dname = Meta.GetXmlTypeName(t + \"[]\");\n        //# var name = Meta.GetXmlTypeName(type);\n        public void Code__name__(ref __type__ value)\n        {\n            var item = new XElement(\"__tt__\");\n            m_elementStack.Push(m_element);\n            m_element = item;\n\n            var element = new XElement(\"Data\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var data = value.Data; Code__dname__(ref data);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Origin\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var origin = value.Origin; CodeLong(ref origin);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Length\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var size = value.Size; Code__tsn__(ref size);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            element = new XElement(\"Delta\");\n            m_elementStack.Push(m_element);\n            m_element = element;\n\n            var delta = value.Delta; Code__tsn__(ref delta);\n\n            m_element = m_elementStack.Pop();\n            m_element.Add(element);\n\n            m_element = m_elementStack.Pop();\n            AddValue(item);\n        }\n\n        //#     });\n        //# });\n        #endregion\n\n        #region Arrays\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] v) { CodeArrayOfStruct(v); }\n        //# });\n\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[,]\");\n        public void Code__name2d__(ref __t__[,] v) { throw new NotImplementedException(); }\n        //# var name3d = Meta.GetXmlTypeName(t + \"[,,]\");\n        public void Code__name3d__(ref __t__[, ,] v) { throw new NotImplementedException(); }\n        //# });\n\n        #endregion\n\n        #region Multi-Dimensional Arrays\n\n        //# directlyCodeableTypes.ForEach(t => {\n        //# var name2d = Meta.GetXmlTypeName(t + \"[][]\");\n        public void Code__name2d__(ref __t__[][] v) { throw new NotImplementedException(); }\n        //# var name3d = Meta.GetXmlTypeName(t + \"[][][]\");\n        public void Code__name3d__(ref __t__[][][] v) { throw new NotImplementedException(); }\n        //# });\n\n        #endregion\n\n        #region Lists\n\n        //# structTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> v) { CodeListOfStruct(v); }\n        //# });\n\n        #endregion\n\n        #region Arrays of Tensors\n\n        //# tensorTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(t + \"[]\");\n        public void Code__name__(ref __t__[] v) { CodeArrayOf(v); }\n        //# });\n\n        #endregion\n\n        #region Lists of Tensors\n\n        //# tensorTypes.ForEach(t => {\n        //# var name = Meta.GetXmlTypeName(\"List<\" + t + \">\");\n        public void Code__name__(ref List<__t__> v) { CodeListOf(v); }\n        //# });\n\n        #endregion\n    }\n    //# }\n}"
  },
  {
    "path": "src/Aardvark.Base.IO/ZipFileContainer.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\n\n// Important: .NET 4.5 contains full zip support.\nnamespace Aardvark.Base.Coder.Legacy\n{\n    /// <summary>\n    /// Important: .NET 4.5 contains full zip support.\n    /// Read-Only access to ZipFiles.\n    /// </summary>\n    public class ZipFile : IDisposable\n    {\n        #region private fields\n\n        private struct SubFileHeader\n        {\n            public int ZipFileIndex;\n            public long LocalHeaderOffset;\n            public long LocalHeaderSize;\n            public long CompressedSize;\n            public long UncompressedSize;\n        }\n\n        private string[] m_ZipFileNames = Array.Empty<string>();\n        private WeakReference[] m_ZipFileStreams = Array.Empty<WeakReference>();\n        private readonly SymbolDict<SubFileHeader> m_Files = new SymbolDict<SubFileHeader>();\n        private readonly SymbolSet m_Directories = new SymbolSet();\n        private readonly bool m_contentCaseSensitive = false;\n\n        #endregion\n\n        #region public properties or fields\n\n        /// <summary>\n        /// Returns the Name of the Container Parts.\n        /// if different parts: e.g. OPC.z01, OPC.z02, ..., OPC.zip\n        /// if single part: e.g. OPC.zip\n        /// </summary>\n        public string[] ZipFileNames\n        {\n            get { return m_ZipFileNames; }\n        }\n\n        public string MainZipFileName\n        {\n            get { return m_ZipFileNames.Last(); }\n        }\n\n        /// <summary>\n        /// Names of files inside of the ZipFile.\n        /// </summary>\n        public IEnumerable<string> FileNames\n        {\n            get { return m_Files.Keys.Select(sym => sym.ToString()); }\n        }\n\n        /// <summary>\n        /// Naems of directories inside of the ZipFile.\n        /// </summary>\n        public IEnumerable<string> DirectoryNames\n        {\n            get { return m_Directories.Keys.Select(sym => sym.ToString()); }\n        }\n\n        #endregion\n\n        public ZipFile() { }\n\n        /// <summary>\n        /// Initializes container.\n        /// </summary>\n        /// <param name=\"containerPath\"></param>\n        public ZipFile(string containerPath)\n        {\n            Init(containerPath);\n        }\n\n        /// <summary>\n        /// </summary>\n        /// <param name=\"contentCaseSensitive\">Load and handle content case sensitive.</param>\n        public ZipFile(bool contentCaseSensitive)\n        {\n            m_contentCaseSensitive = contentCaseSensitive;\n        }\n\n        /// <summary>\n        /// Reads Zip file central directory for later access.\n        /// </summary>\n        /// <param name=\"containerPath\">Path to main zip container (e.g. MyZip.zip).</param>\n        /// <returns></returns>\n        public bool Init(string containerPath)\n        {\n            if (string.IsNullOrWhiteSpace(containerPath)) throw new ArgumentNullException(nameof(containerPath));\n            Report.BeginTimed(\"Init Zip container '\" + containerPath + \"'.\");\n\n            FileStream mainFileStream = null;\n            FileStream[] zipStreams = Array.Empty<FileStream>();\n\n            try\n            {\n                mainFileStream = File.Open(containerPath, FileMode.Open, FileAccess.Read, FileShare.None);\n\n                // Load End Of Central Directory Record\n                var zipEoCDR = new TZipEndOfCentralDirectoryRecord();\n                zipEoCDR.Load(mainFileStream);\n\n                if (zipEoCDR.Position < 0)\n                    throw new Exception(\"ZipFile: couldn't find central directory record.\");\n\n                int numberOfEntries = zipEoCDR.cd_totalEntries;\n                long cd_offset = zipEoCDR.cd_offset;\n                int cd_diskId = zipEoCDR.cd_diskId;\n\n                // init number of zip containers\n                m_ZipFileNames = new string[zipEoCDR.cd_diskId + 1];\n                m_ZipFileNames[zipEoCDR.cd_diskId] = containerPath;\n\n                zipStreams = new FileStream[zipEoCDR.cd_diskId + 1];\n                zipStreams[zipEoCDR.cd_diskId] = mainFileStream;\n\n                // Load all parts of a multi zip\n                if (zipEoCDR.cd_diskId > 0)\n                {\n                    Report.Line(\"Is multi zip container.\");\n\n                    // Segment 1 = filename.z01\n                    // Segment n-1 = filename.z(n-1)\n                    // Segment n = filename.zip\n\n                    var baseName =\n                        0 == containerPath.Substring(containerPath.Length - 4).ToLower().CompareTo(\".zip\") ?\n                        containerPath.Substring(0, containerPath.Length - 4) :\n                        containerPath;\n                    baseName += \".z\";\n\n                    for (int i = 0; i < zipEoCDR.cd_diskId; i++)\n                    {\n                        m_ZipFileNames[i] = baseName + (i+1).ToString(\"D2\");\n                        zipStreams[i] = File.Open(m_ZipFileNames[i], FileMode.Open, FileAccess.Read, FileShare.None);\n                    }\n                }\n\n                // Try to load Zip64 End Of Central Directory Locator\n                var zip64Locator = new TZip64EndOfCentralDirectoryLocator();\n                zip64Locator.Load(mainFileStream, zipEoCDR.Position);\n\n                if (zip64Locator.IsValid)\n                {\n                    Report.Line(\"Is Zip64 container.\");\n\n                    // Load Zip64 End of Central Directory Record\n                    var zip64EoCDR = new TZip64EndOfCentralDirectoryRecord();\n                    zip64EoCDR.Load(\n                        zipStreams[zip64Locator.ecd64_diskId],\n                        (long)zip64Locator.ecd64_relOffset\n                        );\n\n                    numberOfEntries = (int)zip64EoCDR.cd_totalEntries;\n                    cd_offset = (long)zip64EoCDR.cd_offset;\n                    cd_diskId = (int)zip64EoCDR.cd_diskId;\n                }\n\n                // Load file headers in central directory\n                this.ReadZipCentralDirectoryFileHeaders(zipStreams, cd_diskId, cd_offset, numberOfEntries);\n\n                // save weak links to streams\n                m_ZipFileStreams = new WeakReference[zipStreams.Length];\n                for (int i = 0; i < zipStreams.Length; i++)\n                    m_ZipFileStreams[i] = new WeakReference(zipStreams[i]);\n            }\n            catch (Exception)\n            {\n                Report.Warn(\"Error initializing container.\");\n                Report.End();\n\n                foreach (var stream in zipStreams)\n                    if (stream != null) stream.Close();\n\n                if (mainFileStream != null) mainFileStream.Close();\n\n                return false;\n            }\n\n            Report.End(\"Init Zip container finished.\");\n            return true;\n        }\n\n        public static bool IsZipFile(string fileName)\n        {\n            if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentNullException(nameof(fileName));\n\n            using (var fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None))\n            {\n                // Load End Of Central Directory Record\n                var zipEoCDR = new TZipEndOfCentralDirectoryRecord();\n                zipEoCDR.Load(fileStream);\n\n                if (zipEoCDR.Position > 0) return true;\n            }\n\n            return false;\n        }\n\n        /// <summary>\n        /// Tests if a requested file, indexed by fileName, exists in the ContainerFile.\n        /// </summary>\n        /// <param name=\"fileName\">Name of the requested file.</param>\n        /// <returns>Indication wheter the file exists or not.</returns>\n        public bool FileExists(string fileName)\n        {\n            fileName = SanitizeFilename(fileName);\n            return m_Files.ContainsKey(fileName);\n        }\n\n        /// <summary>\n        /// Tests if a requested directory, indexed by its path, exists in the ContainerFile.\n        /// </summary>\n        /// <param name=\"path\">Path of the requested directory.</param>\n        /// <returns>Indication wheter the directory exists or not.</returns>\n        public bool DirectoryExists(string path)\n        {\n            path = SanitizeFilename(path);\n            return this.m_Directories.Contains(path);\n        }\n\n        /// <summary>\n        /// Get directories of local path in ZipFile.\n        /// </summary>\n        /// <param name=\"path\"></param>\n        /// <returns></returns>\n        public string[] GetDirectories(string path)\n        {\n            path = SanitizeFilename(path);\n            var dirs = m_Directories\n                .Select(dirSym => dirSym.ToString())\n                .Where(dir => dir.StartsWith(path));\n\n            if (dirs.IsEmpty()) throw new DirectoryNotFoundException();\n\n            var dirLevel = path.Count(c => c == '\\\\');\n\n            return dirs\n                .Where(dir => dir.Count(c => c == '\\\\') == dirLevel + 1)\n                .ToArray();\n        }\n\n        /// <summary>\n        /// Get files of local path in ZipFile.\n        /// </summary>\n        /// <param name=\"path\"></param>\n        /// <returns></returns>\n        public string[] GetFiles(string path)\n        {\n            path = SanitizeFilename(path);\n            var dirs = m_Files.Keys\n                .Select(dirSym => dirSym.ToString())\n                .Where(dir => dir.StartsWith(path));\n\n            if (dirs.IsEmpty()) throw new DirectoryNotFoundException();\n\n            var dirLevel = path.Count(c => c == '\\\\');\n\n            return dirs\n                .Where(dir => dir.Count(c => c == '\\\\') == dirLevel + 1)\n                .ToArray();\n        }\n\n        public Stream GetStream(string fileName)\n        {\n            fileName = SanitizeFilename(fileName);\n            return GetStream((Symbol)fileName);\n        }\n        public Stream GetStream(Symbol fileName)\n        {\n            SubFileHeader fileHeader;\n            if (m_Files.TryGetValue(fileName, out fileHeader))\n            {\n                var totalStreamsLength = 0L;\n                var fileIndex = fileHeader.ZipFileIndex;\n                var fileStreams = new List<FileStream>();\n\n                // check header size\n                if (fileHeader.LocalHeaderSize <= 0)\n                {\n                    var fileStream = GetZipFileStream(fileIndex);\n                    fileStream.Seek(fileHeader.LocalHeaderOffset, SeekOrigin.Begin);\n\n                    var localFileHeader = new TZipLocalFileHeader();\n                    localFileHeader.Load(fileStream);\n\n                    fileHeader.LocalHeaderSize = localFileHeader.Length;\n                }\n\n                // open streams\n                while (totalStreamsLength < (fileHeader.LocalHeaderOffset + fileHeader.LocalHeaderSize + fileHeader.CompressedSize))\n                {\n                    fileStreams.Add(GetZipFileStream(fileIndex++));\n                    totalStreamsLength += fileStreams.Last().Length;\n                }\n\n                return new UberStream(fileStreams.ToArray(), fileHeader.LocalHeaderOffset + fileHeader.LocalHeaderSize, fileHeader.UncompressedSize);\n            }\n            else return null;\n        }\n\n        public void CloseAllFileStreams()\n        {\n            for (int i = 0; i < m_ZipFileStreams.Length; i++)\n            {\n                if (m_ZipFileStreams[i].Target != null)\n                {\n                    var stream = m_ZipFileStreams[i].Target as FileStream;\n                    stream.Close();\n                    m_ZipFileStreams[i].Target = null;\n                }\n            }\n        }\n\n        #region implement IDisposable\n\n        public void Dispose()\n        {\n            CloseAllFileStreams();\n        }\n\n        #endregion\n\n        #region private methods\n\n        private FileStream GetZipFileStream(int fileIndex)\n        {\n            FileStream stream = null;\n\n            if (m_ZipFileStreams[fileIndex].Target != null)\n                stream = m_ZipFileStreams[fileIndex].Target as FileStream;\n\n            if (stream == null || !stream.CanRead)\n            {\n                if (stream != null) stream.Close();\n                stream = File.Open(m_ZipFileNames[fileIndex],\n                    FileMode.Open, FileAccess.Read, FileShare.Read);\n                m_ZipFileStreams[fileIndex].Target = stream;\n            }\n\n            return stream;\n        }\n\n        /// <summary>\n        /// Reads directory of ZipFiles.\n        /// </summary>\n        /// <param name=\"streams\">FileStreams of zip container.</param>\n        /// <param name=\"cd_diskId\">Id of central directory in streams.</param>\n        /// <param name=\"cd_offset\">Offset of central directory in stream.</param>\n        /// <param name=\"numberOfEntries\">Number of entries in central directory.</param>\n        private void ReadZipCentralDirectoryFileHeaders(FileStream[] streams, int cd_diskId, long cd_offset, int numberOfEntries)\n        {\n            var mainFileStream = streams[cd_diskId];\n            mainFileStream.Seek(cd_offset, SeekOrigin.Begin);\n\n            //Deserialize stream data according to number of Entries\n            for (uint i = 0; i < numberOfEntries; i++)\n            {\n                var cd_fileHeader = new TZipCentralDirectoryFileHeader();\n                cd_fileHeader.Load(mainFileStream);\n\n                // is file or directory?\n                var fileName = SanitizeFilename(cd_fileHeader.filename);\n                if (fileName.Last() != '\\\\')\n                {\n                    m_Files.Add(fileName,\n                        new SubFileHeader()\n                        {\n                            ZipFileIndex = cd_fileHeader.diskStart,\n                            CompressedSize = (long)cd_fileHeader.sizeComp,\n                            UncompressedSize = (long)cd_fileHeader.sizeUncomp,\n                            LocalHeaderOffset = (long)cd_fileHeader.hdrRelOffset,\n                            LocalHeaderSize = 0\n                        });\n                }\n                else\n                {\n                    this.m_Directories.Add(fileName.Substring(0, cd_fileHeader.filename.Length - 1));\n                }\n            }\n        }\n\n        private string SanitizeFilename(string fileName)\n        {\n            if (!m_contentCaseSensitive)\n                fileName = fileName.ToLower();\n\n            return fileName\n                .Replace('/', '\\\\');\n            //.Replace('?', 'ä');\n        }\n\n        #endregion\n\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/ZipFileHeader.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Text;\n\n// Important: .NET 4.5 contains full zip support.\nnamespace Aardvark.Base.Coder.Legacy\n{\n    // Based on .ZIP File Format Specification Version 6.3.3\n\n    // ZIP file format:\n    //\n    // [local file header 1]\n    // [encryption header 1]\n    // [file data 1]\n    // [data descriptor 1] (optional)\n    // ...\n    // ...\n    // [local file header n]\n    // [encryption header n]\n    // [file data n]\n    // [data descriptor n]\n    // [archive decryption header] (necessary if central directory is encrypted)\n    // [archive extra data record] (optional)\n    // [central directory header 1]\n    // ...\n    // ...\n    // [central directory header n]\n    // [zip64 end of central directory record]\n    // [zip64 end of central directory locator]\n    // [end of central directory record]\n\n    // Zip Signatures:\n    //\n    //PK = 0x4b50,\n    //LocalFileHeader = 0x04034b50,\n    //DataDescriptor = 0x08074b50,\n    //ArchiveExtraDataRecord = 0x08064b50,\n    //CentralDirectoryFileHeader = 0x02014b50,\n    //DigitalSignature = 0x05054b50,\n    //Zip64EndOfCentralDirectoryRecord = 0x06064b50,\n    //Zip64EndOfCentralDirectoryLocator = 0x07064b50,\n    //EndOfCentralDirectoryRecord = 0x06054b50,\n    //Zip64ExtendedInfoExtraField = 0x0001\n\n    /// <summary>\n    /// Important: .NET 4.5 contains full zip support.\n    /// </summary>\n    public struct TZipLocalFileHeader\n    {\n        public const UInt32 c_Signature = 0x04034b50;\n        public const long MinLength = 30;\n        public const long MaxLength = MinLength + 2 * UInt16.MaxValue;\n\n        public readonly long Length\n        {\n            get { return MinLength + lengthFileName + lengthExtra; }\n        }\n\n        #region public fields and properties\n\n        /// <summary>\n        /// version needed to extract\n        /// </summary>\n        public UInt16 verNeeded;\n        /// <summary>\n        /// general purpose bit flag\n        /// </summary>\n        public UInt16 flag;\n        /// <summary>\n        /// compression method\n        /// </summary>\n        public UInt16 compression;\n        /// <summary>\n        /// last mod file time\n        /// </summary>\n        public UInt16 modTime;\n        /// <summary>\n        /// last mod file date\n        /// </summary>\n        public UInt16 modDate;\n        /// <summary>\n        /// crc-32\n        /// </summary>\n        public UInt32 crc32;\n        /// <summary>\n        /// compressed size\n        /// </summary>\n        public UInt32 sizeComp;\n        /// <summary>\n        /// uncompressed size\n        /// </summary>\n        public UInt32 sizeUncomp;\n        /// <summary>\n        /// file name length\n        /// </summary>\n        public UInt16 lengthFileName;\n        /// <summary>\n        /// extra field length\n        /// </summary>\n        public UInt16 lengthExtra;\n\n        public string filename;\n        ///// <summary>\n        ///// extra field (variable size)\n        ///// </summary>\n        //public UInt32 xtraField;\n\n        #endregion\n\n        /// <summary>\n        /// Loads header from the stream at the current position.\n        /// </summary>\n        /// <param name=\"stream\"></param>\n        /// <returns></returns>\n        public TZipLocalFileHeader Load(Stream stream)\n        {\n            return Load(new BinaryReader(stream));\n        }\n\n        public TZipLocalFileHeader Load(BinaryReader binReader)\n        {\n            if (c_Signature != binReader.ReadUInt32())\n                throw new Exception(\"Zip: wrong signature of local-file-header.\");\n\n            verNeeded = binReader.ReadUInt16();\n            flag = binReader.ReadUInt16();\n            compression = binReader.ReadUInt16();\n            modTime = binReader.ReadUInt16();\n            modDate = binReader.ReadUInt16();\n            crc32 = binReader.ReadUInt32();\n            sizeComp = binReader.ReadUInt32();\n            sizeUncomp = binReader.ReadUInt32();\n            lengthFileName = binReader.ReadUInt16();\n            lengthExtra = binReader.ReadUInt16();\n\n            //Deserialize the filename, depending on fNameLen and save in string\n            byte[] fileNameByte = new byte[lengthFileName];\n            binReader.Read(fileNameByte, 0, (int)lengthFileName);\n            filename = ASCIIEncoding.ASCII.GetString(fileNameByte);\n\n            // skip rest of header\n            binReader.BaseStream.Seek(lengthExtra, SeekOrigin.Current);\n\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Important: .NET 4.5 contains full zip support.\n    /// </summary>\n    public struct TZipCentralDirectoryFileHeader\n    {\n        public const UInt32 c_Signature = 0x02014b50;\n        public const UInt32 c_Zip64ExtInfoExtraFieldSignature = 0x0001;\n        //public const long MinLength = 46;\n        //public const long MaxLength = MinLength + 3 * UInt16.MaxValue;\n\n        //public long Length\n        //{\n        //    get { return MinLength + lengthFileName + lengthExtra + lengthComment; }\n        //}\n\n        #region public fields and properties\n\n        /// <summary>\n        /// version made by\n        /// </summary>\n        public UInt16 verMade;\n        /// <summary>\n        /// version needed to extract\n        /// </summary>\n        public UInt16 verNeeded;\n        /// <summary>\n        /// general purpose bit flag\n        /// </summary>\n        public UInt16 flag;\n        /// <summary>\n        /// compression method\n        /// </summary>\n        public UInt16 compression;\n        /// <summary>\n        /// last mod file time\n        /// </summary>\n        public UInt16 modTime;\n        /// <summary>\n        /// last mod file date\n        /// </summary>\n        public UInt16 modDate;\n        /// <summary>\n        /// crc-32\n        /// </summary>\n        public UInt32 crc32;\n        /// <summary>\n        /// compressed size\n        /// </summary>\n        public UInt32 sizeComp;\n        /// <summary>\n        /// uncompressed size\n        /// </summary>\n        public UInt32 sizeUncomp;\n        /// <summary>\n        /// file name length\n        /// </summary>\n        public UInt16 lengthFileName;\n        /// <summary>\n        /// extra field length\n        /// </summary>\n        public UInt16 lengthExtra;\n        /// <summary>\n        /// file comment length\n        /// </summary>\n        public UInt16 lengthComment;\n        /// <summary>\n        /// disk number start\n        /// </summary>\n        public UInt16 diskStart;\n        /// <summary>\n        /// internal file attributes\n        /// </summary>\n        public UInt16 attrInt;\n        /// <summary>\n        /// external file attributes\n        /// </summary>\n        public UInt32 attrExt;\n        /// <summary>\n        /// relative offset of local header\n        /// </summary>\n        public UInt64 hdrRelOffset; // 32bit in Zip, 64bit in Zip64\n        /// <summary>\n        /// file name (variable size)\n        /// </summary>\n        public string filename;\n        ///// <summary>\n        ///// extra field (variable size)\n        ///// </summary>\n        //public UInt32 xtraField;\n        ///// <summary>\n        ///// file comment (variable size)\n        ///// </summary>\n        //public string fileComment;\n\n        #endregion\n\n        /// <summary>\n        /// Loads header from the stream at the current position.\n        /// </summary>\n        /// <param name=\"stream\"></param>\n        /// <returns></returns>\n        public TZipCentralDirectoryFileHeader Load(Stream stream)\n        {\n            return Load(new BinaryReader(stream));\n        }\n\n        public TZipCentralDirectoryFileHeader Load(BinaryReader binReader)\n        {\n            if (c_Signature != binReader.ReadUInt32())\n                throw new Exception(\"Zip: wrong signature of central-direcory-file-header.\");\n\n            verMade = binReader.ReadUInt16();\n            verNeeded = binReader.ReadUInt16();\n            flag = binReader.ReadUInt16();\n            compression = binReader.ReadUInt16();\n            modTime = binReader.ReadUInt16();\n            modDate = binReader.ReadUInt16();\n            crc32 = binReader.ReadUInt32();\n            sizeComp = binReader.ReadUInt32();\n            sizeUncomp = binReader.ReadUInt32();\n            lengthFileName = binReader.ReadUInt16();\n            lengthExtra = binReader.ReadUInt16();\n            lengthComment = binReader.ReadUInt16();\n            diskStart = binReader.ReadUInt16();\n            attrInt = binReader.ReadUInt16();\n            attrExt = binReader.ReadUInt32();\n            hdrRelOffset = binReader.ReadUInt32();\n\n            //Deserialize the filename, depending on fNameLen and save in string\n            byte[] fileNameByte = new byte[lengthFileName];\n            binReader.Read(fileNameByte, 0, (int)lengthFileName);\n            filename = ASCIIEncoding.ASCII.GetString(fileNameByte);\n\n            if (hdrRelOffset == 0xFFFFFFFF)\n            {\n                if (c_Zip64ExtInfoExtraFieldSignature == binReader.ReadUInt16())\n                {\n                    /* var size = */ binReader.ReadUInt16();\n                    hdrRelOffset = binReader.ReadUInt64();\n                }\n\n                // skip rest of header\n                binReader.BaseStream.Seek(lengthExtra - 12 + lengthComment, SeekOrigin.Current);\n            }\n            else\n            {   // skip rest of header\n                binReader.BaseStream.Seek(lengthExtra + lengthComment, SeekOrigin.Current);\n            }\n\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Important: .NET 4.5 contains full zip support.\n    /// </summary>\n    public struct TZip64EndOfCentralDirectoryRecord\n    {\n        public const UInt32 signature = 0x06064b50;\n        //public const long MinLength = 56;\n        //public const long MaxLength = 12L + (long)UInt64.MaxValue;\n\n        //public long Length\n        //{\n        //    get { return 12L + (long)recordSize; }\n        //}\n\n\n        #region public fields\n\n        /// <summary>\n        /// size of zip64 end of central directory record (without leading 12bits)\n        /// </summary>\n        public UInt64 recordSize;\n        /// <summary>\n        /// version made by\n        /// </summary>\n        public UInt16 verMade;\n        /// <summary>\n        /// version needed to extract\n        /// </summary>\n        public UInt16 verNeeded;\n        /// <summary>\n        /// number of this disk\n        /// </summary>\n        public UInt32 diskId;\n        /// <summary>\n        /// number of the disk with the start of the central directory\n        /// </summary>\n        public UInt32 cd_diskId;\n        /// <summary>\n        /// total number of entries in the central directory on this disk\n        /// </summary>\n        public UInt64 cd_totalDirEntriesOnDisk;\n        /// <summary>\n        /// total number of entries in the central directory\n        /// </summary>\n        public UInt64 cd_totalEntries;\n        /// <summary>\n        /// size of the central directory\n        /// </summary>\n        public UInt64 cd_size;\n        /// <summary>\n        /// offset of start of central directory with respect to the starting disk number\n        /// </summary>\n        public UInt64 cd_offset;\n        ///// <summary>\n        ///// zip64 extensible data sector\n        ///// </summary>\n        //public ?? extData;\n\n        #endregion\n\n        /// <summary>\n        /// Loads record from stream at current position.\n        /// </summary>\n        /// <param name=\"stream\"></param>\n        /// <param name=\"position\">Position of record in given stream.</param>\n        /// <returns></returns>\n        public TZip64EndOfCentralDirectoryRecord Load(Stream stream, long position)\n        {\n            return Load(new BinaryReader(stream), position);\n        }\n\n        public TZip64EndOfCentralDirectoryRecord Load(BinaryReader binReader, long position)\n        {\n            binReader.BaseStream.Seek(position, SeekOrigin.Begin);\n\n            if (signature != binReader.ReadUInt32())\n                throw new Exception(\"Zip64: wrong signature of end-of-central-direcory-record.\");\n\n            recordSize = binReader.ReadUInt64();\n            verMade = binReader.ReadUInt16();\n            verNeeded = binReader.ReadUInt16();\n            diskId = binReader.ReadUInt32();\n            cd_diskId = binReader.ReadUInt32();\n            cd_totalDirEntriesOnDisk = binReader.ReadUInt64();\n            cd_totalEntries = binReader.ReadUInt64();\n            cd_size = binReader.ReadUInt64();\n            cd_offset = binReader.ReadUInt64();\n\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Important: .NET 4.5 contains full zip support.\n    /// </summary>\n    public struct TZip64EndOfCentralDirectoryLocator\n    {\n        public const UInt32 signature = 0x07064b50;\n        public const long Length = 20;\n\n        /// <summary>\n        /// True if Locator exists.\n        /// </summary>\n        public bool IsValid;\n\n        #region public fields\n\n        /// <summary>\n        /// number of the disk with the start of the zip64 end of central directory\n        /// </summary>\n        public UInt32 ecd64_diskId;\n        /// <summary>\n        /// relative offset of the zip64 end of central directory record\n        /// </summary>\n        public UInt64 ecd64_relOffset;\n        /// <summary>\n        /// total number of disks\n        /// </summary>\n        public UInt32 totalDisks;\n\n        #endregion\n\n        /// <summary>\n        /// Loads Locator from the stream.\n        /// </summary>\n        /// <param name=\"stream\"></param>\n        /// <param name=\"ecd_position\">Position of the 'End of Central Directory Record'</param>\n        /// <returns></returns>\n        public TZip64EndOfCentralDirectoryLocator Load(Stream stream, long ecd_position)\n        {\n            return Load(new BinaryReader(stream), ecd_position);\n        }\n\n        public TZip64EndOfCentralDirectoryLocator Load(BinaryReader binReader, long ecd_position)\n        {\n            // Seek to the beginning of the possible Zip64 Locator.\n            binReader.BaseStream.Seek(ecd_position - Length, SeekOrigin.Begin);\n\n            IsValid = signature == binReader.ReadUInt32();\n\n            if (IsValid)\n            {\n                ecd64_diskId = binReader.ReadUInt32();\n                ecd64_relOffset = binReader.ReadUInt64();\n                totalDisks = binReader.ReadUInt32();\n            }\n\n            return this;\n        }\n\n    }\n\n    /// <summary>\n    /// Important: .NET 4.5 contains full zip support.\n    /// </summary>\n    public struct TZipEndOfCentralDirectoryRecord\n    {\n        public const UInt32 signature = 0x06054b50;\n        public const long MinLength = 22;\n        public const long MaxLength = MinLength + UInt16.MaxValue;\n\n        public readonly long Length\n        {\n            get { return MinLength + cmntLen; }\n        }\n\n        public long Position;\n\n        #region public fields read from zip\n\n        /// <summary>\n        /// Number of this disk\n        /// </summary>\n        public UInt16 diskId;\n        /// <summary>\n        /// number of the disk with the start of the central directory\n        /// </summary>\n        public UInt16 cd_diskId;\n        /// <summary>\n        /// total number of entries in the central directory on this disk\n        /// </summary>\n        public UInt16 cd_totalDirEntriesOnDisk;\n        /// <summary>\n        /// total number of entries in the central directory\n        /// </summary>\n        public UInt16 cd_totalEntries;\n        /// <summary>\n        /// size of the central directory\n        /// </summary>\n        public UInt32 cd_size;\n        /// <summary>\n        /// offset of start of central directory with respect to the starting disk number\n        /// </summary>\n        public UInt32 cd_offset;\n        /// <summary>\n        /// .ZIP file comment length\n        /// </summary>\n        public UInt16 cmntLen;\n        ///// <summary>\n        ///// .ZIP file comment (variable size)\n        ///// </summary>\n        //public string comment;\n\n        #endregion\n\n        /// <summary>\n        /// Finds position of record and loads it.\n        /// </summary>\n        /// <param name=\"stream\"></param>\n        /// <returns></returns>\n        public TZipEndOfCentralDirectoryRecord Load(Stream stream)\n        {\n            Position = FindPositionOfRecord(stream);\n            if (Position < 0) return this;\n\n            var binReader = new BinaryReader(stream);\n            binReader.BaseStream.Seek(Position + 4, SeekOrigin.Begin);\n\n            diskId = binReader.ReadUInt16();\n            cd_diskId = binReader.ReadUInt16();\n            cd_totalDirEntriesOnDisk = binReader.ReadUInt16();\n            cd_totalEntries = binReader.ReadUInt16();\n            cd_size = binReader.ReadUInt32();\n            cd_offset = binReader.ReadUInt32();\n            cmntLen = binReader.ReadUInt16();\n\n            return this;\n        }\n\n        static private long FindPositionOfRecord(Stream stream)\n        {\n            var pos = MinLength;\n            var binReader = new BinaryReader(stream);\n\n            while (pos <= MaxLength && pos < stream.Length)\n            {\n                // find signature\n                stream.Seek(-pos, SeekOrigin.End);\n                if (signature == binReader.ReadUInt32())\n                {\n                    // check total length of record to verify\n                    stream.Seek(16, SeekOrigin.Current);\n                    var commentLength = binReader.ReadUInt16();\n\n                    if ((MinLength + commentLength) == pos)\n                        return stream.Length - pos;\n                }\n\n                pos += 8; // jump to next element for checking\n            }\n\n            //throw new Exception(\"Zip: wrong signature of end-of-central-direcory-record.\");\n            return -1;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.IO/paket.references",
    "content": "Aardvark.Build\nSystem.Dynamic.Runtime"
  },
  {
    "path": "src/Aardvark.Base.IO/paket.template",
    "content": "type project\nid Aardvark.Base.IO\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.Base.Incremental/Aardvark.Base.Incremental.fsproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <AssemblyName>Aardvark.Base.Incremental</AssemblyName>\r\n    <OutputType>Library</OutputType>\r\n    <TargetFramework>netstandard2.0</TargetFramework>\r\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\r\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n    <WarnOn>3389;3390;3395</WarnOn>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug\\</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"../Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj\">\r\n      <Name>Aardvark.Base.FSharp</Name>\r\n      <Project>{692a3617-719b-4ea2-abc1-407ae20094ae}</Project>\r\n      <Private>False</Private>\r\n    </ProjectReference>\r\n    <ProjectReference Include=\"..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"ChangeTracker.fs\" />\r\n    <Compile Include=\"AdaptiveFunc/AdaptiveFunc.fs\" />\r\n    <Compile Include=\"Builders.fs\" />\r\n    <Compile Include=\"IncrementalBvh.fs\" />\r\n    <Compile Include=\"Proc/Proc.fs\" />\r\n    <Compile Include=\"Proc/ProcList.fs\" />\r\n    <Compile Include=\"Proc/ThreadPool.fs\" />\r\n    <Compile Include=\"AgInterop.fs\" />\r\n    <None Include=\"paket.references\" />\r\n    <None Include=\"paket.template\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.Incremental/AdaptiveFunc/AdaptiveFunc.fs",
    "content": "﻿namespace FSharp.Data.Adaptive\n\nopen FSharp.Data.Adaptive\n\n[<CompiledName(\"IAdaptiveFunc\")>]\ntype afun<'a, 'b> =\n    inherit IAdaptiveObject\n    abstract member Evaluate : AdaptiveToken * 'a -> 'b\n\nmodule AFun =\n\n    type AdaptiveFun<'a, 'b>(f : aval<AdaptiveToken -> 'a -> 'b>) =\n        inherit AdaptiveObject()\n\n        member x.Evaluate (caller, v) = \n            x.EvaluateAlways caller (fun token ->\n                x.OutOfDate <- true\n                f.GetValue token token v\n            )\n\n        interface afun<'a, 'b> with\n            member x.Evaluate (c, v) = x.Evaluate(c, v)\n\n        new(f) = AdaptiveFun (AVal.constant f)\n\n    type ConstantFun<'a, 'b>(value : aval<'b>) =\n        inherit AdaptiveObject()\n\n        member x.Evaluate (token : AdaptiveToken, v : 'a) = \n            x.EvaluateAlways token (fun token ->\n                value.GetValue token\n            )\n\n        interface afun<'a, 'b> with\n            member x.Evaluate (token, v) = x.Evaluate (token, v)\n\n    let run (v : 'a) (f : afun<'a, 'b>) =\n        AVal.custom (fun s -> \n            f.Evaluate (s, v)\n        )\n\n    let apply (v : aval<'a>) (f : afun<'a, 'b>) =\n        AVal.custom (fun s -> \n            f.Evaluate (s, v.GetValue s)\n        )\n\n    let create (f : 'a -> 'b) =\n        AdaptiveFun(fun _ -> f) :> afun<_,_>\n\n    let constant (v : 'b) : afun<'a, 'b> =\n        ConstantFun(AVal.constant v) :> afun<_,_>\n\n    let ofAVal (f : aval<'a -> 'b>) =\n        AdaptiveFun(f |> AVal.map (fun f _ -> f)) :> afun<_,_>\n\n    let bind (f : 'a -> afun<'x, 'y>) (m : aval<'a>) =\n        let mf = m |> AVal.map f\n\n        let inner = ref None\n        let self = ref Unchecked.defaultof<_>\n        self :=\n            AdaptiveFun(fun token x ->\n                let f = mf.GetValue(token)\n\n                match !inner with\n                    | Some f' when f' <> f ->\n                        f'.Outputs.Remove !self |> ignore\n                    | _ ->\n                        ()\n                mf.GetValue(token).Evaluate(token, x)\n            )\n\n        !self :> afun<_,_>\n\n    let compose (g : afun<'b, 'c>) (f : afun<'a, 'b>) =\n        AdaptiveFun(fun token v -> g.Evaluate(token, f.Evaluate(token, v))) :> afun<_,_>\n\n    let zipWith (combine : 'b -> 'c -> 'd) (f : afun<'a,'b>) (g : afun<'a, 'c>) =\n        AdaptiveFun(fun token v -> combine (f.Evaluate(token, v)) (g.Evaluate(token, v))) :> afun<_,_>\n\n    let zip (f : afun<'a,'b>) (g : afun<'a, 'c>) =\n        zipWith (fun a b -> (a,b)) f g\n\n    let rec chain (l : list<afun<'a, 'a>>) =\n        match l with\n            | [] -> create id\n            | [f] -> f\n            | f::fs -> compose (chain fs) f\n\n    let chainM (l : aval<list<afun<'a, 'a>>>) =\n        l |> AVal.map chain |> bind id\n\n    let runChain l initial =\n        l |> chain |> run initial\n\n    let integrate (f : afun<'a, 'a>) (initial : 'a) =\n        let input = AVal.init initial\n        let inputChanged = ChangeTracker.track<'a>\n        initial |> inputChanged |> ignore\n\n        AVal.custom (fun s -> \n            let v = input.GetValue s\n            let res = f.Evaluate(s, v)\n            if inputChanged res then\n                AdaptiveObject.RunAfterEvaluate(fun () ->\n                    input.Value <- res\n                )\n\n            res\n        )\n\n[<AutoOpen>]\nmodule ``AFun Builder`` =\n\n    type AFunBuilder() =\n        member x.Bind(m : aval<'a>, f : 'a -> afun<'x, 'y>) =\n            AFun.bind f m\n\n        member x.Return(f : 'a -> 'b) =\n            AFun.create f\n\n        member x.ReturnFrom(f : afun<'a, 'b>) = \n            f\n\n        member x.ReturnFrom(m : aval<'a -> 'b>) =\n            AFun.ofAVal m\n\n    let inline (>>.) (f : afun<'a, 'b>) (g : afun<'b, 'c>) =\n        AFun.compose g f\n\n    let inline (<<.) (g : afun<'b, 'c>) (f : afun<'a, 'b>) =\n        AFun.compose g f\n\n    let afun = AFunBuilder()\n\n\n\n[<CompiledName(\"IAdaptiveState\")>]\ntype astate<'s, 'a> = { [<CompiledName(\"RunState\")>] runState : afun<'s, 's * 'a> }\n\nmodule AState =\n    let create (v : 'a) =\n        { runState = AFun.create (fun s -> s,v) }\n\n    let map (f : 'a -> 'b) (m : astate<'s, 'a>) =\n        let changed = ChangeTracker.track<'a>\n        let cache = ref None\n        { runState = \n            m.runState \n                |> AFun.compose (\n                    AFun.create (fun (s,v) -> \n                        let c = changed v\n                        match !cache with\n                            | Some o when not c -> (s,o)\n                            | _ ->\n                                let n = f v\n                                cache := Some n\n                                (s,n)\n                    )\n                   ) \n        }\n\n    let bind (f : 'a -> astate<'s, 'b>) (m : astate<'s, 'a>) =\n        let cache : ref<Option<afun<_,_>>> = ref None\n        let tracker = ChangeTracker.track<'a>\n\n        let self = \n            AFun.AdaptiveFun(fun token s ->\n                let (s, v) = m.runState.Evaluate (token, s)\n\n                let c = tracker v\n                match !cache with\n                    | Some old when not c ->\n                        old.Evaluate (token, s)\n                    | _ ->\n                        let inner = (f v).runState\n                        match !cache with\n                            | Some old -> old.Outputs.Remove token.Caller.Value |> ignore\n                            | None -> ()\n                        cache := Some inner\n\n                        inner.Evaluate (token, s)\n            )\n\n        { runState = self }\n\n    let bindAVal (f : 'a -> astate<'s, 'b>) (m : aval<'a>) =\n        let mf = m |> AVal.map f\n\n        let inner : ref<Option<afun<_,_>>> = ref None\n        let self =\n            AFun.AdaptiveFun(fun token s -> \n                let run = mf.GetValue(token).runState\n                \n                match !inner with\n                    | Some old when old <> run ->\n                        old.Outputs.Remove token.Caller.Value |> ignore\n\n                    | _ -> ()\n\n                inner := Some run \n                run.Evaluate (token, s)\n            )\n\n        { runState = self :> afun<_,_> }\n\n    let ofAVal (m : aval<'a>) : astate<'s, 'a> =\n        let run = AFun.ofAVal(m |> AVal.map (fun v s -> (s,v)))\n        { runState = run }\n\n    let ofAFun (m : afun<'a, 'b>) : astate<'s, 'a -> 'b> =\n        let run = AFun.AdaptiveFun(fun token s -> (s,fun v -> m.Evaluate(token,v)))\n        { runState = run }\n\n    let getState<'s> = { runState = AFun.create (fun s -> (s,s)) }\n    let putState (s : 's) = { runState = AFun.create (fun _ -> (s,())) }\n    let modifyState (f : 's -> 's) = { runState = AFun.create (fun s -> (f s,())) }\n    let modifyState' (f : 's -> 's) = { runState = AFun.create (fun s -> (f s,s)) }\n\n\n[<AutoOpen>]\nmodule ``AState Builder`` =\n    type AStateBuilder() =\n        member x.Bind(m : astate<'s, 'a>, f : 'a -> astate<'s, 'b>) =\n            AState.bind f m\n\n        member x.Bind(m : aval<'a>, f : 'a -> astate<'s, 'b>) =\n            AState.bindAVal f m\n\n        member x.Return(v : 'a) =\n            AState.create v\n\n    let astate = AStateBuilder()\n\n\n\ntype ControllerState = { prev : HashMap<obj, obj>; pulled : HashMap<obj, obj> }\ntype Controller<'a> = astate<ControllerState, 'a>\n\n[<AutoOpen>]\nmodule ``Controller Builder`` =\n    open AState\n\n    let preWith (f : 'a -> 'a -> 'b) (m : aval<'a>) =\n        if m.IsConstant then\n            let v = m.GetValue(AdaptiveToken.Top)\n            AState.create (f v v)\n        else\n            m |> AState.bindAVal (fun v ->\n                modifyState' (fun s -> { s with pulled = HashMap.add (m :> obj) (v :> obj) s.pulled })\n                    |> AState.map (fun s ->\n                        let last =\n                            match HashMap.tryFind (m :> obj) s.prev with\n                                | Some (:? 'a as v) -> v\n                                | _ -> v\n                        f last v\n                       )\n            )\n\n    let inline withLast (m : aval<'a>) = preWith (fun a b -> (a,b)) m\n\n    let inline pre (m : aval<'a>) = preWith (fun a _ -> a) m\n\n    let inline differentiate (m : aval<'a>) = preWith (fun o n -> n - o) m\n\n\n\n    type ControllerBuilder() =\n\n        member x.Bind(m : Controller<'a>, f : 'a -> Controller<'b>) : Controller<'b> =\n            AState.bind f m\n\n        member x.Bind(m : aval<'a>, f : 'a -> Controller<'b>) : Controller<'b> =\n            AState.bindAVal f m\n\n        member x.Return(v : 'a) : Controller<'a> =\n            AState.create v\n\n        member x.ReturnFrom(v : aval<'a -> 'b>) : Controller<'a -> 'b> =\n            AState.ofAVal v\n\n        member x.ReturnFrom(v : afun<'a, 'b>) : Controller<'a -> 'b> =\n            AState.ofAFun v\n\n        member x.Zero() : Controller<'a -> 'a> =\n            AState.create id\n\n        member x.Run(c : Controller<'a -> 'b>) : afun<'a, 'b> =\n            let initial = { prev = HashMap.empty; pulled = HashMap.empty }\n            let state = AVal.init initial\n            let res = c.runState |> AFun.apply state\n            let stateChanged = ChangeTracker.track<ControllerState>\n            initial |> stateChanged |> ignore\n\n            let mf =\n                res |> AVal.map (fun (newState, v) ->\n                    AdaptiveObject.RunAfterEvaluate(fun () ->\n                        state.Value <- { prev = newState.pulled; pulled = HashMap.empty }\n                    )\n                    v\n                )\n            AFun.ofAVal mf\n\n    let controller = ControllerBuilder()\n"
  },
  {
    "path": "src/Aardvark.Base.Incremental/AdaptiveStream/AdaptiveStream.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Experimental\n\nopen System\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\n\nmodule AStream =\n    open AStreamReaders\n\n    type private ConstantStream<'a>(values : list<'a>) =\n        interface astream<'a> with\n            member x.GetReader() =\n                let t = DateTime.Now\n                new OneShotReader<'a>(History (values |> List.map (fun v -> (t,v)))) :> IStreamReader<_>\n\n    type private AdaptiveStream<'a>(newReader : unit -> IStreamReader<'a>) =\n        let l = obj()\n        let readers = WeakSet<CopyReader<'a>>()\n\n        let mutable inputReader = None\n        let getReader() =\n            match inputReader with\n                | Some r -> r\n                | None ->\n                    let r = newReader()\n                    inputReader <- Some r\n                    r\n\n        member x.GetReader() =\n            lock l (fun () ->\n                let r = getReader()\n\n                let remove ri =\n                    r.RemoveOutput ri\n                    readers.Remove ri |> ignore\n\n                    if readers.IsEmpty then\n                        r.Dispose()\n                        inputReader <- None\n\n                let reader = new CopyReader<'a>(r, remove)\n                readers.Add reader |> ignore\n\n                reader :> IStreamReader<_>\n            )\n\n        interface astream<'a> with\n            member x.GetReader() = x.GetReader()\n\n    type private EmptyStreamImpl<'a>() =\n        static let emptyStream = ConstantStream [] :> astream<'a>\n\n        static member Instance = emptyStream\n\n\n    let empty<'a> : astream<'a> = EmptyStreamImpl.Instance\n\n    let single (v : 'a) = ConstantStream [v] :> astream<_>\n\n    let ofSeq (v : seq<'a>) = ConstantStream (Seq.toList v) :> astream<_>\n\n    let ofList (v : list<'a>) = ConstantStream v :> astream<_>\n\n    let ofArray (v : 'a[]) = ConstantStream (Array.toList v) :> astream<_>\n\n    let ofMod (m : IMod<'a>) =\n        if m.IsConstant then\n            ConstantStream [m.GetValue(null)] :> astream<_>\n        else\n            AdaptiveStream(fun () -> ofMod m) :> astream<_>\n\n    let map (f : 'a -> 'b) (input : astream<'a>) = \n        let scope = Ag.getContext()\n        AdaptiveStream(fun () -> input.GetReader() |> map scope f) :> astream<'b>\n\n    let collect (f : 'a -> astream<'b>) (input : aset<'a>) = \n        let scope = Ag.getContext()\n        AdaptiveStream(fun () -> input.GetReader() |> collect scope (fun v -> (f v).GetReader())) :> astream<'b>\n\n    let bind (f : 'a -> astream<'b>) (input : IMod<'a>) =\n        let scope = Ag.getContext()\n        AdaptiveStream(fun () -> bind scope (fun v -> (f v).GetReader()) input) :> astream<_>\n"
  },
  {
    "path": "src/Aardvark.Base.Incremental/AdaptiveStream/AdaptiveStreamCore.fs",
    "content": "namespace Aardvark.Base.Incremental.Experimental\n\nopen System\nopen System.Collections.Generic\nopen System.Collections.Concurrent\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\n\ntype EventHistory<'a> =\n    | Cancel\n    | Faulted of Exception\n    | History of list<DateTime * 'a>\n\nmodule EventHistory =\n\n    type private EmptyImpl<'a>() =\n        static let instance : EventHistory<'a> = History []\n        static member Instance = instance\n \n    let rec private concatTimeLists (l : list<DateTime * 'a>) (r : list<DateTime * 'a>) =\n        match l, r with\n            | [], r -> r\n            | l, [] -> l\n            | (lt,lv)::lr, (rt,rv)::rr ->\n                if lt < rt then (lt,lv)::(concatTimeLists lr r)\n                else (rt,rv)::(concatTimeLists l rr)\n\n\n\n\n    let empty<'a> : EventHistory<'a> = EmptyImpl<'a>.Instance\n\n    let isEmpty (h : EventHistory<'a>) =\n        match h with\n            | Cancel -> true\n            | Faulted _ -> true\n            | History l -> List.isEmpty l\n\n    let map (f : 'a -> 'b) (h : EventHistory<'a>) =\n        match h with\n            | Cancel -> Cancel\n            | Faulted e -> Faulted e\n            | History a -> a |> List.map (fun (t,v) -> (t,f v)) |> History\n\n    let collectSeq (f : 'a -> EventHistory<'b>) (h : seq<'a>) =\n        h |> Seq.fold (fun r hi ->\n            match r with\n                | History current ->\n                    match f hi with\n                        | Cancel -> History current\n                        | Faulted e -> Faulted e\n                        | History vi -> History (current @ vi)\n                | _ -> r\n        ) (History [])\n  \n\n    let collect (f : 'a -> EventHistory<'b>) (h : EventHistory<'a>) =\n        match h with\n            | Cancel -> Cancel\n            | Faulted e -> Faulted e\n            | History a ->\n                a |> List.fold (fun r (_,hi) ->\n                    match r with\n                        | History current ->\n                            match f hi with\n                                | Cancel -> History current\n                                | Faulted e -> Faulted e\n                                | History vi -> History (current @ vi)\n                        | _ -> r\n                ) (History [])\n  \n    let choose (f : 'a -> Option<'b>) (h : EventHistory<'a>) =\n        match h with\n            | Cancel -> Cancel\n            | Faulted e -> Faulted e\n            | History h ->\n                h |> List.choose (fun (t,v) ->\n                    match f v with\n                        | Some r -> Some(t,r)\n                        | None -> None\n                ) |> History\n\n    let filter (f : 'a -> bool) (h : EventHistory<'a>) =\n        match h with\n            | Cancel -> Cancel\n            | Faulted e -> Faulted e\n            | History h ->\n                h |> List.filter (fun (t,v) -> f v)\n                  |> History\n\n    \n    let union (l : EventHistory<'a>) (r : EventHistory<'a>) =\n        match l,r with\n            | Cancel, r -> r\n            | l, Cancel -> l\n\n            | Faulted l, Faulted r -> Faulted (AggregateException(l,r))\n            | Faulted e, _ -> Faulted e\n            | _, Faulted e -> Faulted e\n\n\n            | History l, History r ->\n                History (concatTimeLists l r)\n            \n    let rec concat (histories : list<EventHistory<'a>>) =\n        match histories with\n            | [] -> empty\n            | [h] -> h\n            | f::rest ->\n                union f (concat rest)\n\ntype IStreamReader<'a> =\n    inherit IDisposable\n    inherit IAdaptiveObject\n    abstract member GetHistory : IAdaptiveObject -> EventHistory<'a>\n    abstract member SubscribeOnEvaluate : (EventHistory<'a> -> unit) -> IDisposable\n\n[<CompiledName(\"IAdaptiveStream\")>]\ntype astream<'a> =\n    abstract member GetReader : unit -> IStreamReader<'a>\n\nmodule AStreamReaders =\n    \n    [<AbstractClass>]\n    type AbstractReader<'a>() =\n        inherit AdaptiveObject()\n\n        let callbacks = HashSet<EventHistory<'a> -> unit>()\n\n        member x.Callbacks = callbacks\n\n        abstract member Release : unit -> unit\n        abstract member ComputeHistory : unit -> EventHistory<'a>\n        abstract member GetHistory : IAdaptiveObject -> EventHistory<'a>\n \n        default x.GetHistory(caller) =\n            x.EvaluateIfNeeded caller EventHistory.empty (fun () ->\n                let deltas = x.ComputeHistory()\n\n                if not (EventHistory.isEmpty deltas) then\n                    for cb in callbacks do cb deltas\n\n                deltas\n            )\n\n        override x.Finalize() =\n            try x.Dispose false\n            with _ -> ()\n\n        member x.Dispose disposing =\n            x.Release()\n            if disposing then callbacks.Clear()\n\n        member x.Dispose() =\n            x.Dispose true\n            GC.SuppressFinalize x\n\n        member x.SubscribeOnEvaluate (cb : EventHistory<'a> -> unit) =\n            lock x (fun () ->\n                if callbacks.Add cb then\n                    { new IDisposable with \n                        member __.Dispose() = \n                            lock x (fun () ->\n                                callbacks.Remove cb |> ignore \n                            )\n                    }\n                else\n                    { new IDisposable with member __.Dispose() = () }\n            )\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n        interface IStreamReader<'a> with\n            member x.GetHistory(caller) = x.GetHistory(caller)\n            member x.SubscribeOnEvaluate cb = x.SubscribeOnEvaluate cb\n\n\n    type FixedSizeCache<'a, 'b>(scope : Ag.Scope, size : int, f : 'a -> 'b) =\n        let history = Queue<'a>()\n        let cache = Dictionary<obj, 'b>()\n\n        let invoke (v : 'a) =\n            match cache.TryGetValue (v :> obj) with\n                | (true, r) -> r\n                | _ -> \n                    let r = Ag.useScope scope (fun () -> f v)\n                    history.Enqueue v\n                    cache.[v] <- r\n                    if history.Count > size then\n                        let fst = history.Dequeue()\n                        cache.Remove fst |> ignore\n                    r\n\n        member x.Invoke(v) = invoke v\n\n        member x.Clear(f : 'b -> unit) =\n            for e in cache.Values do\n                f e\n            cache.Clear()\n            history.Clear()\n\n\n    type MapReader<'a, 'b>(scope : Ag.Scope, source : IStreamReader<'a>, f : 'a -> 'b) as this =\n        inherit AbstractReader<'b>()\n        do source.AddOutput this  \n\n        let cache = FixedSizeCache(scope, 32, f)\n\n        override x.Release() =\n            source.RemoveOutput this\n            source.Dispose()\n            cache.Clear(ignore)\n\n        override x.ComputeHistory() =\n            source.GetHistory(x) |> EventHistory.map (fun a ->\n                cache.Invoke a\n            )\n\n    type CollectSetReader<'a, 'b>(scope : Ag.Scope, source : IReader<'a>, f : 'a -> IStreamReader<'b>) as this =\n        inherit AbstractReader<'b>()\n        do source.AddOutput this\n\n        let dirtyInner = VolatileDirtySet(fun (r : IStreamReader<'b>) -> r.GetHistory(this))\n        let f = Cache(scope, f)\n\n        override x.Release() =\n            source.RemoveOutput this\n            source.Dispose()\n            f.Clear(fun r -> r.RemoveOutput this; r.Dispose())\n            dirtyInner.Clear()\n\n        override x.InputChanged(t, o : IAdaptiveObject) =\n            match o with\n                | :? IStreamReader<'b> as o -> dirtyInner.Push o\n                | _ -> ()\n\n        override x.ComputeHistory() =\n            for d in source.GetDelta(x) do\n                match d with\n                    | Add v ->\n                        let r = f.Invoke v\n\n                        // we're an output of the new reader\n                        r.AddOutput this\n\n                        // listen to marking of r (reader cannot be OutOfDate due to GetDelta above)\n                        dirtyInner.Add r\n\n\n                    | Rem v ->\n                        let (last,r) = f.RevokeAndGetDeleted v\n\n                        // remove the reader from the listen-set\n                        dirtyInner.Remove r\n\n                        // since the reader is no longer contained we don't want\n                        // to be notified anymore\n                        r.RemoveOutput this\n\n                        // if the reader's reference count got 0 we dispose it \n                        // since no one can ever reference it again\n                        if last then r.Dispose()\n\n            dirtyInner.Evaluate() |> EventHistory.concat\n\n    type ChooseReader<'a, 'b>(scope : Ag.Scope, source : IStreamReader<'a>, f : 'a -> Option<'b>) as this =\n        inherit AbstractReader<'b>()\n        do source.AddOutput this  \n\n        let cache = FixedSizeCache(scope, 32, f)\n\n        override x.Release() =\n            source.RemoveOutput this\n            source.Dispose()\n            cache.Clear(ignore)\n\n        override x.ComputeHistory() =\n            source.GetHistory(x) |> EventHistory.choose (fun a ->\n                cache.Invoke a\n            )\n\n    type ModReader<'a>(source : IMod<'a>) as this =\n        inherit AbstractReader<'a>()\n        do source.AddOutput this\n\n        override x.Release() = ()\n\n        override x.ComputeHistory() =\n            History [(DateTime.Now, source.GetValue(this))]\n\n    type OneShotReader<'a>(deltas : EventHistory<'a>) =  \n        inherit AbstractReader<'a>()\n        \n        let mutable deltas = deltas\n\n        override x.ComputeHistory() =\n            let res = deltas\n            deltas <- EventHistory.empty\n            res\n\n        override x.Release() =\n            deltas <- EventHistory.empty\n\n\n    type CopyReader<'a>(inputReader : IStreamReader<'a>, dispose : CopyReader<'a> -> unit) as this =\n        inherit AbstractReader<'a>()\n            \n        let mutable deltas = EventHistory.empty\n\n        let emit (d : EventHistory<'a>) =\n            lock this (fun () ->\n//                if reset.IsNone then\n//                    let N = inputReader.Content.Count\n//                    let M = this.Content.Count\n//                    let D = deltas.Count + (List.length d)\n//                    if D > N + 2 * M then\n//                        reset <- Some (inputReader.Content :> _)\n//                        deltas.Clear()\n//                    else\n//                        deltas.AddRange d\n\n                deltas <- EventHistory.union deltas d\n            \n                if not this.OutOfDate then \n                    // TODO: why is that happening sometimes?\n\n                    // A good case: \n                    //     Suppose the inputReader and this one have been marked and\n                    //     a \"neighbour\" reader (of this one) has not yet been marked.\n                    //     In that case the neighbouring reader will not be OutOfDate when\n                    //     its emit function is called.\n                    //     However it should be on the marking-queue since the input was\n                    //     marked and therefore the reader should get \"eventually consistent\"\n                    // Thoughts:\n                    //     Since the CopyReader's GetDelta starts with acquiring the lock\n                    //     to the inputReader only one CopyReader will be able to call its ComputeDelta\n                    //     at a time. Therefore only one can call inputReader.Update() at a time and \n                    //     again therefore only one thread may call emit here.\n                    // To conclude I could find one good case and couldn't come up with\n                    // a bad one. Nevertheless this is not really a proof of its inexistence (hence the print)\n                    Aardvark.Base.Log.warn \"[AStreamReaders.CopyReader] potentially bad emit with: %A\" d\n            )\n\n        do inputReader.AddOutput this\n        let subscription = inputReader.SubscribeOnEvaluate emit\n\n        override x.GetHistory(caller) =\n            lock inputReader (fun () ->\n                x.EvaluateIfNeeded caller EventHistory.empty (fun () ->\n                    let deltas = x.ComputeHistory()\n\n                    if not (EventHistory.isEmpty deltas) then\n                        for cb in x.Callbacks do cb deltas\n\n                    deltas\n                )\n            )\n\n        override x.ComputeHistory() =\n            inputReader.GetHistory(x) |> ignore\n\n            let res = deltas\n            deltas <- EventHistory.empty\n            res\n\n        override x.Release() =\n            inputReader.RemoveOutput x\n            subscription.Dispose()\n            dispose(x)\n\n\n    // finally some utility functions reducing \"noise\" in the code using readers\n    let map scope (f : 'a -> 'b) (input : IStreamReader<'a>) =\n        new MapReader<_, _>(scope, input, f) :> IStreamReader<_>\n\n    let collect scope (f : 'a -> IStreamReader<'b>) (input : IReader<'a>) =\n        new CollectSetReader<_, _>(scope, input, f) :> IStreamReader<_>\n\n    let bind scope (f : 'a -> IStreamReader<'b>) (input : IMod<'a>) =\n        new CollectSetReader<_,_>(scope, new ASetReaders.ModReader<_>(input), f) :> IStreamReader<_>\n\n    let bind2 scope (f : 'a -> 'b -> IStreamReader<'c>) (ma : IMod<'a>)  (mb : IMod<'b>)=\n        let tup = Mod.map2 (fun a b -> (a,b)) ma mb\n        new CollectSetReader<_,_>(scope, new ASetReaders.ModReader<_>(tup),  fun (a,b) -> f a b) :> IStreamReader<_>\n\n    let choose scope (f : 'a -> Option<'b>) (input : IStreamReader<'a>) =\n        new ChooseReader<_, _>(scope, input, f) :> IStreamReader<_>\n\n    let ofMod (m : IMod<'a>) =\n        new ModReader<_>(m) :> IStreamReader<_>\n"
  },
  {
    "path": "src/Aardvark.Base.Incremental/AgInterop.fs",
    "content": "﻿namespace FSharp.Data.Adaptive\n\n//open Aardvark.Base\n//open FSharp.Data.Traceable\n\n//[<AutoOpen>]\n//module AgInterop = \n\n//    type private ScopedReader<'d>(scope : Ag.Scope, empty : 'd, inner : IOpReader<'d>) =\n//        inherit AbstractReader<'d>(empty)\n\n//        override x.Compute(token : AdaptiveToken) =\n//            Ag.useScope scope (fun () ->\n//                inner.GetChanges token\n//            )\n\n\n\n//    module AVal =\n//        let withScope (scope : Ag.Scope) (value : aval<'a>) =\n//            AVal.custom (fun token ->\n//                Ag.useScope scope (fun () ->\n//                    value.GetValue token\n//                )\n//            )\n\n//        let scoped (value : aval<'a>) =\n//            let scope = Ag.getContext()\n//            withScope scope value\n            \n//    module ASet =\n//        let withScope (scope : Ag.Scope) (value : aset<'a>) =\n//            ASet.ofReader (fun () ->\n//                ScopedReader(scope, HashSetDelta.empty, value.GetReader())\n//            )\n\n//        let scoped (value : aset<'a>) =\n//            let scope = Ag.getContext()\n//            withScope scope value\n            \n//    module AMap =\n//        let withScope (scope : Ag.Scope) (value : amap<'a, 'b>) =\n//            AMap.ofReader (fun () ->\n//                ScopedReader(scope, HashMapDelta.empty, value.GetReader())\n//            )\n\n//        let scoped (value : amap<'a, 'b>) =\n//            let scope = Ag.getContext()\n//            withScope scope value\n\n//    module AList =\n//        let withScope (scope : Ag.Scope) (value : alist<'a>) =\n//            AList.ofReader (fun () ->\n//                ScopedReader(scope, IndexListDelta.empty, value.GetReader())\n//            )\n\n//        let scoped (value : alist<'a>) =\n//            let scope = Ag.getContext()\n//            withScope scope value"
  },
  {
    "path": "src/Aardvark.Base.Incremental/Builders.fs",
    "content": "﻿namespace FSharp.Data.Adaptive\n\nopen FSharp.Data.Adaptive\n\n/// provides special operators for composing IMods\nmodule Operators =\n    \n    /// adaptively adds two values\n    let inline (%+) (l : aval<'a>) (r : aval<'b>) = AVal.map2 (+) l r\n\n    /// adaptively subtracts two values\n    let inline (%-) (l : aval<'a>) (r : aval<'b>) = AVal.map2 (-) l r\n\n    /// adaptively mutiplies two values\n    let inline (%*) (l : aval<'a>) (r : aval<'b>) = AVal.map2 (*) l r\n\n    /// adaptively divides two values\n    let inline (%/) (l : aval<'a>) (r : aval<'b>) = AVal.map2 (/) l r\n\n    /// creates an adaptive cell providing the value of \"l && r\"\n    let inline (%&&) (l : aval<bool>) (r : aval<bool>) = AVal.map2 (&&) l r\n\n    /// creates an adaptive cell providing the value of \"l || r\"\n    let inline (%||) (l : aval<bool>) (r : aval<bool>) = AVal.map2 (||) l r\n\n    /// expresses an adaptive \"if then else\" expression (e.g. m %? a %. b <=> if m then a else b)\n    let (%?) (l : aval<bool>) (vt : 'a) : 'a -> aval<'a> = fun vf -> l |> AVal.map (fun v -> if v then vt else vf)\n\n    /// expresses an adaptive \"if then else\" expression (e.g. m %? a %. b <=> if m then a else b)\n    let (%.) (l : 'a -> aval<'a>) (r : 'a) =  l r\n\n    /// forces the value of a cell\n    let inline (!!) (m : aval<'a>) = AVal.force m\n\n    /// creates a constant cell containing the given value\n    let inline (~~) (v : 'a) = AVal.constant v\n\n[<AutoOpen>]\nmodule EvaluationExtensions =\n\n    type IAdaptiveValue with\n        member inline x.GetValue() = x.GetValueUntyped(AdaptiveToken.Top)\n\n    type IAdaptiveValue<'T> with\n        member inline x.GetValue() = x.GetValue(AdaptiveToken.Top)\n        \n    type FSharp.Data.Traceable.IOpReader<'a> with\n        member inline x.GetChanges() = x.GetChanges(AdaptiveToken.Top)\n        member inline x.Update() = x.GetChanges(AdaptiveToken.Top) |> ignore\n\n    type afun<'a, 'b> with \n        member x.Evaluate(v : 'a) = x.Evaluate(AdaptiveToken.Top, v)\n"
  },
  {
    "path": "src/Aardvark.Base.Incremental/ChangeTracker.fs",
    "content": "namespace FSharp.Data.Adaptive\n\n\nmodule ChangeTracker =\n    type private ChangeTracker<'a>() =\n        static let createSimpleTracker : (Option<'a -> 'a -> bool>) -> 'a -> bool =\n            fun eq ->\n                let eq = defaultArg eq (fun a b -> System.Object.Equals(a,b))\n                let old = ref None\n                fun n ->\n                    match !old with\n                        | None -> \n                            old := Some n\n                            true\n                        | Some o ->\n                            if eq o n then \n                                false\n                            else \n                                old := Some n\n                                true\n\n\n        static member CreateTracker eq = createSimpleTracker eq\n        static member CreateDefaultTracker() = createSimpleTracker None\n        static member CreateCustomTracker eq = createSimpleTracker (Some eq)\n\n    let track<'a> : 'a -> bool =\n        ChangeTracker<'a>.CreateDefaultTracker()\n\n    let trackCustom<'a> (eq : Option<'a -> 'a -> bool>) : 'a -> bool =\n        ChangeTracker<'a>.CreateTracker eq\n\n"
  },
  {
    "path": "src/Aardvark.Base.Incremental/IncrementalBvh.fs",
    "content": "﻿namespace FSharp.Data.Adaptive\n\nopen Aardvark.Base\nopen Aardvark.Base.Geometry\nopen FSharp.Data.Adaptive\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule BvhTree =\n\n    type private ASetBvh<'a>(objects : aset<'a>, getBounds : 'a -> aval<Box3d>) =\n        inherit AVal.AbstractVal<BvhTree<'a>>()\n\n        let reader = objects.GetReader()\n        let boundsCache = Dict()\n\n        override x.Compute(token) =\n            let ops = reader.GetChanges token\n\n            for op in HashSetDelta.toSeq ops do\n                match op with\n                | Add(_,key) ->\n                    boundsCache.GetOrCreate(key, getBounds) |> ignore\n\n                | Rem(_,key) ->\n                    match boundsCache.TryRemove key with\n                    | true, bounds ->\n                        bounds.Outputs.Remove x |> ignore\n                    | _ ->\n                        failwith \"[Bvh] unexpected removal\"\n\n            let data = boundsCache |> Dict.toArrayV |> Array.map (fun struct (k,v) -> k, v.GetValue(token))\n            BvhTree(data)\n\n    type private AMapBvh<'a>(objects : amap<'a, aval<Box3d>>) =\n        inherit AVal.AbstractVal<BvhTree<'a>>()\n\n        let reader = objects.GetReader()\n        let boundsCache = Dict<'a, aval<Box3d>>()\n\n        override x.Compute(token) =\n            let ops = reader.GetChanges token\n            for key, op in HashMapDelta.toSeq ops do\n                match op with\n                | Set bounds ->\n                    match boundsCache.TryRemove key with\n                    | true, old -> old.Outputs.Remove x |> ignore\n                    | _ -> ()\n\n                    boundsCache.[key] <- bounds\n\n                | Remove ->\n                    match boundsCache.TryRemove key with\n                    | true, bounds ->\n                        bounds.Outputs.Remove x |> ignore\n                    | _ ->\n                        failwith \"[Bvh] unexpected removal\"\n\n            let data = boundsCache |> Dict.toArrayV |> Array.map (fun struct (k,v) -> k, v.GetValue(token))\n            BvhTree(data)\n\n    let ofASet (getBounds : 'a -> aval<Box3d>) (objects : aset<'a>) =\n        new ASetBvh<'a>(objects, getBounds) :> aval<_>\n\n    let ofAMap (objects : amap<'a, aval<Box3d>>) =\n        new AMapBvh<'a>(objects) :> aval<_>"
  },
  {
    "path": "src/Aardvark.Base.Incremental/Proc/Proc.fs",
    "content": "﻿namespace FSharp.Data.Adaptive\n\nopen System.Threading\nopen System.Threading.Tasks\nopen System.Runtime.CompilerServices\n\nopen Aardvark.Base\n\n[<AutoOpen>]\nmodule private Utilities =\n\n    [<return: Struct>]\n    let inline (|CancelExn|_|) (e : exn) =\n        match e with\n        | :? System.OperationCanceledException\n        | :? TaskCanceledException ->\n            ValueSome()\n        | _ ->\n            ValueNone\n\n    [<return: Struct>]\n    let inline (|AggregateExn|_|) (e : exn) =\n        match e with\n        | :? System.AggregateException as e ->\n            let l = e.InnerExceptions |> Seq.toList\n            ValueSome l\n        | _ ->\n            ValueNone\n\ntype ProcState =\n    {\n        ct : CancellationToken\n    }\n\ntype ProcResult<'a> =\n    | Value of 'a\n    | Cancelled\n    | Faulted of exn\n\nand Proc<'a, 'r>(runWhenCancelled : bool, cont : ProcState -> (ProcResult<'a> -> 'r) -> 'r) =\n    member x.RunWhenCancelled = runWhenCancelled\n    member x.ContinueWith s c = \n        if not runWhenCancelled && s.ct.IsCancellationRequested then\n            c Cancelled\n        else\n            cont s c \n\n    new(cont : ProcState -> (ProcResult<'a> -> 'r) -> 'r) = Proc(false, cont)\n\n[<AutoOpen>]\nmodule ``ProcResult Smart Constructors`` =\n    let internal cancelexn = System.OperationCanceledException()\n    let rec Faulted (e : exn) =\n        match e with\n            | AggregateExn [inner] -> Faulted inner\n            | CancelExn -> Cancelled\n            | e -> ProcResult.Faulted e\n\n    type ProcResult<'a> with\n        static member Faulted e =\n            Faulted e\n\n[<Extension>]\ntype Proc =\n    static member Create (v : 'a) =\n        Proc<'a, 'r>(fun state cont ->\n            cont (Value v)\n        )\n            \n    [<Extension>]\n    static member Await (t : Task<'a>) =\n        Proc<'a, unit>(fun state cont ->\n            if state.ct.IsCancellationRequested then\n                cont Cancelled\n            else\n                let s = state.ct.Register(fun () -> cont Cancelled)\n                let c (t : Task<'a>) =\n                    s.Dispose()\n                    if state.ct.IsCancellationRequested || t.Status = TaskStatus.Canceled then\n                        cont Cancelled\n                    elif t.Status = TaskStatus.Faulted then\n                        cont (Faulted t.Exception)\n                    else\n                        cont (Value t.Result)\n\n                t.ContinueWith(c, state.ct) |> ignore\n        )\n            \n    [<Extension>]\n    static member Await (t : Task) =\n        Proc<unit, unit>(fun state cont ->\n            if state.ct.IsCancellationRequested then\n                cont Cancelled\n            else\n                let s = state.ct.Register(fun () -> cont Cancelled)\n                let c (t : Task) =\n                    s.Dispose()\n                    if state.ct.IsCancellationRequested || t.Status = TaskStatus.Canceled then\n                        cont Cancelled\n                    elif t.Status = TaskStatus.Faulted then\n                        cont (Faulted t.Exception)\n                    else\n                        cont (Value ())\n\n                t.ContinueWith(c, state.ct) |> ignore\n        )\n        \n    [<Extension>]\n    static member Await (a : Async<'a>) =\n        Proc<'a, unit>(fun state cont ->\n            if state.ct.IsCancellationRequested then\n                cont Cancelled\n            else\n                Async.StartWithContinuations(\n                    a,\n                    (fun v -> cont (Value v)),\n                    (fun e -> cont (Faulted e)),\n                    (fun _ -> cont (Cancelled)),\n                    state.ct\n                )\n        )\n\n    [<Extension>]\n    static member Await(sem : SemaphoreSlim) =\n        sem.WaitAsync() |> Proc.Await\n\n    static member Sleep (ms : int) =\n        Task.Delay(ms) |> Proc.Await\n\n    static member Bind (m : Proc<'a, 'r>, mapping : 'a -> Proc<'b, 'r>) =\n        Proc (fun state cont ->\n            m.ContinueWith state (fun res ->\n                match res with\n                    | Value v -> \n                        try mapping(v).ContinueWith state cont\n                        with e -> cont (Faulted e)\n                    | Cancelled -> cont Cancelled\n                    | Faulted e -> cont (Faulted e)\n            )\n        )\n\n    static member Map (m : Proc<'a, 'r>, f : 'a -> 'b) =\n        Proc<'b, 'r>(fun state cont ->\n            m.ContinueWith state (fun res ->\n                match res with\n                    | Value v -> \n                        try cont (Value (f v))\n                        with e -> cont (Faulted e)\n                    | Cancelled -> cont Cancelled\n                    | Faulted e -> cont (Faulted e)\n            )\n        )\n    \n    static member TryFinally (m : Proc<'a, 'r>, fin : unit -> unit) =\n        Proc(fun state cont ->\n            m.ContinueWith state (fun res ->\n                match res with\n                    | Value v -> fin(); cont (Value v)\n                    | Cancelled -> fin(); cont Cancelled\n                    | Faulted e -> fin(); cont (Faulted e)\n            )\n        )\n\n    static member TryWith (m : Proc<'a, 'r>, comp : exn -> unit) =\n        Proc<_,_>(fun state cont ->\n            m.ContinueWith state (fun res ->\n                match res with\n                    | Faulted e -> comp(e); cont(Faulted e) //.ContinueWith state cont\n                    | Cancelled -> comp(cancelexn); cont(Cancelled) //.ContinueWith state cont\n                    | Value c -> cont(Value c)\n            )  \n        ) \n\n    static member Append (l : Proc<unit, 'r>, r : Proc<'a, 'r>) =\n        Proc (fun state cont ->\n            l.ContinueWith state (fun res ->\n                match res with\n                    | Value () -> r.ContinueWith state cont\n                    | Cancelled -> cont Cancelled\n                    | Faulted e -> cont (Faulted e)\n            )\n        )\n\n    static member SwitchToThreadPool() =\n        Proc(fun state cont ->\n            Task.Factory.StartNew(fun () ->\n                cont (Value ())\n            ) |> ignore\n        )\n\n    static member SwitchToNewThread() =\n        Proc(fun state cont ->\n            let run () = cont (Value())\n            let thread = new Thread(ThreadStart(run), IsBackground = true)\n            thread.Start()\n        )\n\n    static member RunSynchronously(m : Proc<'a, unit>, ?cancellationToken : CancellationToken) =\n        let ct = defaultArg cancellationToken Unchecked.defaultof<_>\n        use v = new ManualResetEventSlim(false)\n        let mutable res = Unchecked.defaultof<_>\n        m.ContinueWith { ct = ct } (fun r ->\n            res <- r\n            v.Set()\n        )\n        v.Wait()\n        res\n            \n    static member StartAsTask(m : Proc<'a, unit>, ?cancellationToken : CancellationToken) =\n        let ct = defaultArg cancellationToken Unchecked.defaultof<_>\n        let tcs = TaskCompletionSource<ProcResult<'a>>()\n        m.ContinueWith { ct = ct } (fun r ->\n            tcs.SetResult(r)\n        )\n        tcs.Task\n\n    static member Start(m : Proc<unit, unit>, ?cancellationToken : CancellationToken) =\n        let ct = defaultArg cancellationToken Unchecked.defaultof<_>\n        m.ContinueWith { ct = ct } ignore\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Proc =\n    let inline create v = Proc.Create v\n    let inline map (mapping : 'a -> 'b) (m : Proc<'a, 'r>) = Proc.Map(m, mapping)\n    let inline bind (mapping : 'a -> Proc<'b, 'r>) (m : Proc<'a, 'r>) = Proc.Bind(m, mapping)\n    let inline append (l : Proc<unit, 'r>) (r : Proc<'a, 'r>) = Proc.Append(l, r)\n\ntype ProcBuilder() =\n    member x.Zero() = Proc.Create ()\n    member x.Return v = Proc.Create v\n    member x.ReturnFrom (p : Proc<_,_>) = p\n    member x.Bind(m,f) = Proc.Bind(m,f)\n    member x.Bind(m : Task<'a>,f) = Proc.Bind(Proc.Await m,f)\n    member x.Bind(m : Task,f) = Proc.Bind(Proc.Await m,f)\n    member x.Bind(m : Async<'a>,f) = Proc.Bind(Proc.Await m,f)\n    member x.Combine(l,r) = Proc.Append(l,r)\n    member x.Delay(f : unit -> Proc<'a, 'r>) = Proc<_,_>(fun state cont -> f().ContinueWith state cont)\n    member x.TryFinally(m, fin) = Proc.TryFinally(m, fin)\n    member x.TryWith(m, handler : exn -> Proc<unit, unit>) = \n        Proc.TryWith(m, fun e ->\n            handler e |> Proc.RunSynchronously |> ignore\n        )\n    member x.For(s : seq<'a>, f : 'a -> Proc<unit, 'r>) =\n        let rec build (l : list<'a>) =\n            match l with\n                | [] -> Proc.Create ()\n                | h :: rest ->\n                    Proc.Append(f h, build rest)\n\n        s |> Seq.toList |> build\n\n    member x.Using<'a, 'b, 'r when 'a :> System.IDisposable> (v : 'a, f : 'a -> Proc<'b, 'r>) =\n        Proc(true, fun state cont ->\n            if state.ct.IsCancellationRequested then\n                v.Dispose()\n                cont Cancelled\n            else\n                try\n                    f(v).ContinueWith state (fun res ->\n                        match res with\n                            | Cancelled -> v.Dispose(); cont (Cancelled)\n                            | Faulted e -> v.Dispose(); cont (Faulted e)\n                            | Value res -> v.Dispose(); cont (Value res)\n                    )\n                with e ->\n                    v.Dispose()\n                    cont (Faulted e)\n                        \n        )\n\n[<AutoOpen>]\nmodule ``Proc Builder`` =\n    let proc = ProcBuilder()\n"
  },
  {
    "path": "src/Aardvark.Base.Incremental/Proc/ProcList.fs",
    "content": "﻿namespace FSharp.Data.Adaptive\n\nopen System\nopen System.Threading\nopen System.Threading.Tasks\n\nopen Aardvark.Base\n\n[<RequireQualifiedAccess>]\ntype ProcListValue<'a, 'r> =\n    | Nil\n    | Cons of 'a * ProcList<'a, 'r>\n\nand ProcList<'a, 'r>(run : Proc<ProcListValue<'a, 'r>, 'r>) =\n    static let empty = ProcList<'a, 'r>(Proc.Create ProcListValue.Nil)\n\n    static member Empty = empty\n\n    member x.run = run\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule ProcList =\n    let empty<'a, 'r> = ProcList<'a, 'r>.Empty\n\n    let single (v : 'a) : ProcList<'a, 'r> = \n        ProcList<'a, 'r>(Proc.create <| ProcListValue.Cons(v, empty))\n\n    let ofSeq (v : seq<'a>) : ProcList<'a, 'r> = \n        use e = v.GetEnumerator()\n        let rec build() =\n            if e.MoveNext() then\n                let v = e.Current\n                let rest = build()\n                ProcList(Proc.create <| ProcListValue.Cons(v, rest))\n            else\n                empty\n        build()\n\n    let rec ofList (l : list<'a>) : ProcList<'a, 'r> =\n        match l with\n            | [] -> \n                empty\n\n            | h :: rest ->\n                ProcListValue.Cons(h, ofList rest)\n                    |> Proc.Create\n                    |> ProcList\n    \n    let ofArray (arr : 'a[]) : ProcList<'a, 'r> =\n        let rec build (i : int) (arr : 'a[]) =\n            if i >= arr.Length then\n                empty\n            else\n                ProcList(Proc.create <| ProcListValue.Cons(arr.[i], build (i+1) arr))\n        build 0 arr\n\n\n    let rec map (mapping : 'a -> 'b) (list : ProcList<'a, 'r>) : ProcList<'b, 'r> =\n        ProcList(\n            proc {\n                let! c = list.run\n                match c with\n                | ProcListValue.Nil -> \n                    return ProcListValue.Nil\n\n                | ProcListValue.Cons(h,tail) ->\n                    return ProcListValue.Cons(mapping h, map mapping tail)\n            }\n        )\n\n    let rec choose (mapping : 'a -> Option<'b>) (list : ProcList<'a, 'r>) : ProcList<'b, 'r> =\n        ProcList(\n            proc {\n                let! c = list.run\n                match c with\n                | ProcListValue.Nil -> \n                    return ProcListValue.Nil\n\n                | ProcListValue.Cons(h,tail) ->\n                    match mapping h with\n                        | Some v ->\n                            return ProcListValue.Cons(v, choose mapping tail)\n                        | None ->\n                            return! (choose mapping tail).run\n            }\n        )\n\n    let rec filter (predicate : 'a -> bool) (list : ProcList<'a, 'r>) : ProcList<'a, 'r> =\n        ProcList (\n            proc {\n                let! l = list.run\n                match l with\n                | ProcListValue.Nil -> return ProcListValue.Nil\n                | ProcListValue.Cons(h,tail) ->\n                    if predicate h then\n                        return ProcListValue.Cons(h, filter predicate tail)\n                    else\n                        return! (filter predicate tail).run\n            }\n        )\n\n    let rec append (l : ProcList<'a, 'r>) (r : ProcList<'a, 'r>) =\n        ProcList (\n            proc {\n                let! l = l.run\n                match l with\n                | ProcListValue.Nil -> return! r.run\n                | ProcListValue.Cons(h,tail) -> return ProcListValue.Cons(h, append tail r)\n            }\n        )\n\n    let rec concat (l : ProcList<ProcList<'a, 'r>, 'r>) =\n        ProcList(\n            proc {\n                let! l = l.run\n                match l with\n                | ProcListValue.Nil -> \n                    return ProcListValue.Nil\n\n                | ProcListValue.Cons(h,t) ->\n                    return! (append h (concat t)).run\n            }\n        )\n\n    let rec bind (mapping : 'a -> ProcList<'b, 'r>) (m : Proc<'a, 'r>) : ProcList<'b, 'r> =\n        ProcList (\n            proc {\n                let! res = m\n                return! (mapping res).run\n            }\n        )\n\n    let rec collect (mapping : 'a -> ProcList<'b, 'r>) (list : ProcList<'a, 'r>) : ProcList<'b, 'r> =\n        ProcList (\n            proc {\n                let! list = list.run\n                match list with\n                | ProcListValue.Nil -> \n                    return ProcListValue.Nil\n\n                | ProcListValue.Cons(h,tail) ->\n                    let res = append (mapping h) (collect mapping tail)\n                    return! res.run\n            }\n        )\n\n    let delay (f : unit -> ProcList<'a, 'r>) =\n        ProcList(\n            proc {\n                return! f().run\n            }\n        )\n\ntype ProcListBuilder() =\n    member x.Bind(m,f) = ProcList.bind f m\n    member x.Bind(m : Task<'a>,f) = ProcList.bind f (m.Await())\n    member x.Bind(m : Task,f) = ProcList.bind f (m.Await())\n    member x.Bind(m : Async<'a>,f) = ProcList.bind f (m.Await())\n    member x.Zero() = ProcList.empty\n    member x.Yield v = ProcList.single v\n    member x.Combine(l,r) = ProcList.append l r\n    member x.Delay(f) = ProcList.delay f\n    member x.YieldFrom(l : Proc<'a, 'r>) = l |> ProcList.bind ProcList.single\n    member x.YieldFrom(l : Task<'a>) = l.Await() |> ProcList.bind ProcList.single\n    member x.YieldFrom(l : Task) = l.Await() |> ProcList.bind ProcList.single\n    member x.YieldFrom(l : Async<'a>) = l.Await() |> ProcList.bind ProcList.single\n    member x.YieldFrom(l : ProcList<'a, 'r>) = l\n    member x.YieldFrom(s : seq<'a>) = ProcList.ofSeq s\n    member x.YieldFrom(s : list<'a>) = ProcList.ofList s\n    member x.YieldFrom(s : array<'a>) = ProcList.ofArray s\n    member x.For(m : ProcList<'a, 'r>, f : 'a -> ProcList<'b, 'r>) = ProcList.collect f m\n    member x.For(m : seq<'a>, f : 'a -> ProcList<'b, 'r>) = ProcList.collect f (ProcList.ofSeq m)\n\n[<AutoOpen>]\nmodule ``ProcList Builder`` =\n    let proclist = ProcListBuilder()"
  },
  {
    "path": "src/Aardvark.Base.Incremental/Proc/ThreadPool.fs",
    "content": "﻿namespace FSharp.Data.Adaptive\n\nopen System\nopen System.Threading\nopen FSharp.Data.Adaptive\n\n[<AbstractClass>]\ntype Command<'a>() =\n    abstract member Start : ('a -> unit) -> unit\n    abstract member Stop : unit -> unit\n\ntype LeafCommand<'a>(p : ProcList<'a, unit>) =\n    inherit Command<'a>()\n\n    let name = Guid.NewGuid()\n    let cancel = new CancellationTokenSource()\n\n    let rec run (ct : CancellationToken) (f : 'a -> unit) (p : ProcList<'a, unit>) =\n        proc {\n            let! res = p.run\n            match res with\n                | ProcListValue.Nil -> \n                    ()\n                | ProcListValue.Cons(msg, cont) ->\n                    if not ct.IsCancellationRequested then \n                        f msg\n                        do! run ct f cont\n        }\n\n    override x.Start(f : 'a -> unit) =\n        let runner = run cancel.Token f p\n        Proc.Start(runner, cancel.Token)\n\n    override x.Stop() =\n        cancel.Cancel()\n\n\ntype ThreadPool<'a>(_store : HashMap<string, Command<'a>>) =\n    static let empty = ThreadPool<'a>(HashMap.empty)\n\n    static member Empty = empty\n    \n    member x.store = _store\n\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule ThreadPool =\n    \n    let empty<'msg> = ThreadPool<'msg>.Empty\n\n    let map (mapping : 'a -> 'b) (pool : ThreadPool<'a>) =\n        ThreadPool(\n            pool.store |> HashMap.map (fun _ v -> \n                { new Command<'b>() with\n                    member x.Start(f) = v.Start(mapping >> f)\n                    member x.Stop() = v.Stop()\n                }\n            )\n        )\n\n    let add (id : string) (proc : ProcList<'a, unit>) (p : ThreadPool<'a>) =\n        ThreadPool(HashMap.add id (LeafCommand(proc) :> Command<_>) p.store)\n\n    let remove (id : string) (p : ThreadPool<'a>) =\n        ThreadPool(HashMap.remove id p.store)\n\n    let start (proc : ProcList<'a, unit>) (p : ThreadPool<'a>) =\n        let id = Guid.NewGuid() |> string\n        ThreadPool(HashMap.add id (LeafCommand(proc) :> Command<_>) p.store)\n\n    let union (l : ThreadPool<'a>) (r : ThreadPool<'a>) =\n        ThreadPool(HashMap.union l.store r.store)"
  },
  {
    "path": "src/Aardvark.Base.Incremental/Scripts/load-project.fsx",
    "content": "// Warning: generated file; your changes could be lost when a new file is generated.\n#I __SOURCE_DIRECTORY__\n#load @\"load-references.fsx\"\n#load @\"..\\Core\\PriorityQueue.fs\"\n      @\"..\\Core\\WeakSet.fs\"\n      @\"..\\Core\\Delta.fs\"\n      @\"..\\Core\\ReferenceCountingSet.fs\"\n      @\"..\\Core\\TimeList.fs\"\n      @\"..\\Core\\Cache.fs\"\n      @\"..\\Core\\Core.fs\"\n      @\"..\\Mod\\Mod.fs\"\n      @\"..\\AdaptiveSet\\AdaptiveSetCore.fs\"\n      @\"..\\AdaptiveSet\\ChangeableSet.fs\"\n      @\"..\\AdaptiveSet\\AdaptiveSet.fs\"\n      @\"..\\AdaptiveList\\AdaptiveListCore.fs\"\n      @\"..\\AdaptiveList\\ChangeableList.fs\"\n      @\"..\\AdaptiveList\\AdaptiveList.fs\"\n      @\"..\\Builders.fs\"\n      @\"..\\CSharp.fs\"\n      @\"..\\Adapters\\EventAdapter.fs\"\n      @\"..\\Tests\\AdaptiveSetReference.fs\"\n      @\"..\\Tests\\ASetUtilities.fs\"\n      @\"..\\Tests\\ModTests.fs\"\n      @\"..\\Tests\\ASetTests.fs\"\n      @\"..\\Tests\\AListTests.fs\"\n"
  },
  {
    "path": "src/Aardvark.Base.Incremental/Scripts/load-references.fsx",
    "content": "// Warning: generated file; your changes could be lost when a new file is generated.\n#I __SOURCE_DIRECTORY__\n#r @\"..\\..\\..\\packages\\NUnit.2.6.4\\lib\\nunit.framework.dll\"\n#r @\"..\\..\\..\\bin\\Debug\\Aardvark.Base.dll\"\n#r @\"..\\..\\..\\bin\\Debug\\Aardvark.Base.Essentials.dll\"\n#r @\"..\\..\\..\\bin\\Debug\\Aardvark.Base.FSharp.dll\"\n#r @\"..\\..\\..\\bin\\Debug\\Aardvark.Base.TypeProviders.dll\"\n#r @\"..\\..\\..\\packages\\FsUnit.1.3.0.1\\Lib\\Net40\\FsUnit.NUnit.dll\"\n#r @\"System.Core.dll\"\n#r @\"System.dll\"\n#r @\"System.Drawing.dll\"\n#r @\"System.Numerics.dll\"\n#r @\"..\\..\\..\\packages\\Rx-Core.2.2.5\\lib\\net45\\System.Reactive.Core.dll\"\n#r @\"..\\..\\..\\packages\\Rx-Interfaces.2.2.5\\lib\\net45\\System.Reactive.Interfaces.dll\"\n#r @\"..\\..\\..\\packages\\Rx-Linq.2.2.5\\lib\\net45\\System.Reactive.Linq.dll\"\n#r @\"..\\..\\..\\packages\\Rx-PlatformServices.2.2.5\\lib\\net45\\System.Reactive.PlatformServices.dll\""
  },
  {
    "path": "src/Aardvark.Base.Incremental/paket.references",
    "content": "FSharp.Core\nAardvark.Build\nFsPickler\nAardvark.Base.TypeProviders\nFSharp.Data.Adaptive"
  },
  {
    "path": "src/Aardvark.Base.Incremental/paket.template",
    "content": "type project\nid Aardvark.Base.Incremental\nversion 1.0\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.Base.Runtime/Aardvark.Base.Runtime.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <TargetFramework>netstandard2.0</TargetFramework>\r\n    <AssemblyName>Aardvark.Base.Runtime</AssemblyName>\r\n    <OutputType>Library</OutputType>\r\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\r\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n    <WarnOn>3389;3390;3395</WarnOn>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug\\</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"Coder\\Utilities.fs\" />\r\n    <Compile Include=\"Coder\\State.fs\" />\r\n    <Compile Include=\"Coder\\Code.fs\" />\r\n    <Compile Include=\"Coder\\Core.fs\" />\r\n    <Compile Include=\"Coder\\ValueCoders.fs\" />\r\n    <None Include=\"paket.references\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\">\r\n      <Name>Aardvark.Base.FSharp</Name>\r\n      <Project>{692a3617-719b-4ea2-abc1-407ae20094ae}</Project>\r\n      <Private>True</Private>\r\n    </ProjectReference>\r\n    <ProjectReference Include=\"..\\Aardvark.Base.Incremental\\Aardvark.Base.Incremental.fsproj\">\r\n      <Name>Aardvark.Base.Incremental</Name>\r\n      <Project>{9623ae28-1f72-46e9-a3a7-85fc1a321a73}</Project>\r\n      <Private>True</Private>\r\n    </ProjectReference>\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.Runtime/Coder/Code.fs",
    "content": "﻿namespace Aardvark.Base.Runtime\r\n\r\nopen System\r\nopen System.Reflection\r\nopen System.Runtime.CompilerServices\r\nopen System.Runtime.InteropServices\r\nopen Aardvark.Base\r\nopen Aardvark.Base.Runtime\r\n\r\ntype IDatabase =\r\n    abstract member TryStore    : value : 'a    * [<Out>] id : byref<Guid>      -> bool\r\n    abstract member TryLoad     : id : Guid     * [<Out>] value : byref<'a>     -> bool\r\n    \r\ntype CodeState =\r\n    {\r\n        Version         : Version\r\n        MemberStack     : list<MemberInfo>\r\n        References      : RefMap<obj, Guid>\r\n        Values          : Map<Guid, obj>\r\n        Database        : IDatabase\r\n    }\r\n\r\ntype Code<'a> = State<CodeState, 'a>\r\n\r\nmodule Code =\r\n    let version =\r\n        { new Code<Version>() with\r\n            override x.Run(s) = s.Version\r\n        }\r\n\r\n    let push (m : MemberInfo) =\r\n        { new Code<unit>() with\r\n            override x.RunUnit(s) =\r\n                s <- { s with MemberStack = m::s.MemberStack }\r\n        }\r\n\r\n    let pop =\r\n        { new Code<unit>() with\r\n            override x.RunUnit(s) =\r\n                s <- { s with MemberStack = List.tail s.MemberStack }\r\n        }\r\n\r\n    let peek =\r\n        { new Code<MemberInfo>() with\r\n            override x.Run(s) =\r\n                List.head s.MemberStack\r\n        }\r\n\r\n    let tryStoreLocal (value : 'a) =\r\n        { new Code<bool * Guid>() with\r\n            override x.Run(s) =\r\n                let v = value :> obj\r\n                match RefMap.tryFind v s.References with\r\n                    | Some id ->\r\n                        (false, id)\r\n                    | None ->\r\n                        let id = Guid.NewGuid()\r\n                        s <- { s with References = RefMap.add v id s.References }\r\n                        (true, id)\r\n        }\r\n\r\n    let tryLoadLocal (id : Guid) =\r\n        { new Code<Option<'a>>() with\r\n            override x.Run(s) =\r\n                Map.tryFind id s.Values |> Option.map unbox\r\n        }\r\n\r\n    let storeLocal (id : Guid) (value : 'a) =\r\n        { new Code<unit>() with\r\n            override x.RunUnit(s) =\r\n                s <- { s with Values = Map.add id (value :> obj) s.Values }\r\n        }\r\n\r\n\r\n    let tryStore (value : 'a) =\r\n        { new Code<bool * Guid>() with\r\n            override x.Run(s) =\r\n                let v = value :> obj\r\n                match RefMap.tryFind v s.References with\r\n                    | Some id ->\r\n                        (false, id)\r\n                    | None ->\r\n                        match s.Database.TryStore value with\r\n                            | (true, id) -> (false, id)\r\n                            | _ ->\r\n                                let id = Guid.NewGuid()\r\n                                s <- { s with References = RefMap.add v id s.References }\r\n                                (true, id)\r\n        }\r\n\r\n    let tryLoad (id : Guid) : Code<Option<'a>> =\r\n        { new Code<Option<'a>>() with\r\n            override x.Run(s) =\r\n                match Map.tryFind id s.Values with\r\n                    | Some v -> Some (unbox<'a> v)\r\n                    | None ->\r\n                        match s.Database.TryLoad id with\r\n                            | (true, v) ->\r\n                                s <- { s with Values = Map.add id (v :> obj) s.Values } \r\n                                Some v\r\n                            | _ -> \r\n                                None\r\n        }\r\n\r\n\r\n\r\n\r\n[<AutoOpen>]\r\nmodule CodeBuilder =\r\n\r\n    type CodeBuilder() =\r\n        inherit SpecificStateBuilder<CodeState>()\r\n\r\n        member x.Run(v : Code<'a>) : Code<'a> =\r\n            v\r\n\r\n    let code = CodeBuilder()\r\n\r\n\r\n\r\n"
  },
  {
    "path": "src/Aardvark.Base.Runtime/Coder/Core.fs",
    "content": "﻿namespace Aardvark.Base.Runtime\r\n\r\nopen System\r\nopen System.Reflection\r\nopen System.Runtime.CompilerServices\r\nopen Aardvark.Base.Runtime\r\n\r\ntype IReader =\r\n    abstract member ReadPrimitive<'a when 'a : unmanaged> : unit -> Code<'a>\r\n    abstract member ReadPrimitiveArray<'a when 'a : unmanaged> : unit -> Code<'a[]>\r\n    abstract member ReadString : unit -> Code<string>\r\n    abstract member ReadBool : unit -> Code<bool>\r\n\r\ntype IWriter =\r\n    abstract member WritePrimitive<'a when 'a : unmanaged> : 'a -> Code<unit>\r\n    abstract member WritePrimitiveArray<'a when 'a : unmanaged> : 'a[] -> Code<unit>\r\n    abstract member WriteString : string -> Code<unit>\r\n    abstract member WriteBool : bool -> Code<unit>\r\n\r\ntype ICoder =   \r\n    inherit IReader\r\n    inherit IWriter\r\n    abstract member IsReading : bool\r\n\r\n\r\n\r\ntype IValueCoder =\r\n    abstract member ValueType : Type\r\n    abstract member ReadUnsafe : IReader -> Code<'a>\r\n    abstract member WriteUnsafe : IWriter * 'a -> Code<unit>\r\n\r\ntype IValueCoder<'a> =\r\n    inherit IValueCoder\r\n    abstract member Read : IReader -> Code<'a>\r\n    abstract member Write : IWriter * 'a -> Code<unit>\r\n\r\n\r\ntype IReferenceCoder =\r\n    abstract member WithInternalStore : IValueCoder\r\n    abstract member WithExternalStore : IValueCoder\r\n\r\n\r\n\r\n[<AbstractClass; Sealed; Extension>]\r\ntype ValueCoderExtensions private() =\r\n    static let read = typeof<ValueCoderExtensions>.GetMethod(\"ReadState\", BindingFlags.AnyStatic)\r\n    static let write = typeof<ValueCoderExtensions>.GetMethod(\"WriteState\", BindingFlags.AnyStatic)\r\n    static let readUnsafe = typeof<ValueCoderExtensions>.GetMethod(\"ReadStateUnsafe\", BindingFlags.AnyStatic)\r\n    static let writeUnsafe = typeof<ValueCoderExtensions>.GetMethod(\"WriteStateUnsafe\", BindingFlags.AnyStatic)\r\n\r\n    [<Extension>]\r\n    static member ReadState (this : IValueCoder<'a>, r : IReader, state : byref<CodeState>) =\r\n        this.Read(r).Run(&state)\r\n\r\n    [<Extension>]\r\n    static member WriteState (this : IValueCoder<'a>, w : IWriter, value : 'a, state : byref<CodeState>) =\r\n        this.Write(w,value).RunUnit(&state)\r\n\r\n    [<Extension>]\r\n    static member ReadStateUnsafe (this : IValueCoder, r : IReader, state : byref<CodeState>) =\r\n        this.ReadUnsafe(r).Run(&state)\r\n\r\n    [<Extension>]\r\n    static member WriteStateUnsafe (this : IValueCoder, w : IWriter, value : 'a, state : byref<CodeState>) =\r\n        this.WriteUnsafe(w,value).RunUnit(&state)\r\n\r\n\r\n    static member GetReadMethod(coderType : Type, resType : Type) =\r\n        let generic = coderType.GetInterface(typedefof<IValueCoder<_>>.AssemblyQualifiedName)\r\n        if isNull generic then\r\n            readUnsafe.MakeGenericMethod [|resType|]\r\n        else\r\n            let coderValueType = generic.GetGenericArguments().[0]\r\n            if coderValueType = resType then read.MakeGenericMethod [|resType|]\r\n            else readUnsafe.MakeGenericMethod [|resType|]\r\n\r\n    static member GetWriteMethod(coderType : Type, valueType : Type) =\r\n        let generic = coderType.GetInterface(typedefof<IValueCoder<_>>.AssemblyQualifiedName)\r\n        if isNull generic then\r\n            writeUnsafe.MakeGenericMethod [|valueType|]\r\n        else\r\n            let coderValueType = generic.GetGenericArguments().[0]\r\n            if coderValueType = valueType then write.MakeGenericMethod [|valueType|]\r\n            else writeUnsafe.MakeGenericMethod [|valueType|]\r\n\r\n[<AbstractClass>]\r\ntype AbstractValueCoder<'a>() =\r\n    abstract member Write : IWriter * 'a -> Code<unit>\r\n    abstract member Read : IReader -> Code<'a>\r\n\r\n    abstract member CodesType : bool\r\n    default x.CodesType = false\r\n\r\n    interface IValueCoder with\r\n        member x.ValueType = typeof<'a>\r\n        member x.WriteUnsafe(w : IWriter,v : 'b) = \r\n            if isNull (v :> obj) then x.Write(w, Unchecked.defaultof<'a>)\r\n            else x.Write(w, unbox v)\r\n\r\n        member x.ReadUnsafe(r : IReader) : Code<'b> = \r\n            x.Read(r) |> State.map (fun v ->\r\n                if isNull (v :> obj) then \r\n                    Unchecked.defaultof<'b>\r\n                else\r\n                    unbox v\r\n            )\r\n\r\n    interface IValueCoder<'a> with\r\n        member x.Write(w,v) = x.Write(w, v)\r\n        member x.Read(r) = x.Read(r)\r\n\r\n\r\ntype private NewObj<'a>() =\r\n    static member Create() : 'a =\r\n        System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(typeof<'a>) |> unbox<'a>\r\n\r\n\r\n\r\n[<AbstractClass>]\r\ntype AbstractByRefValueCoder<'a>(useExternalStore : bool) =\r\n    inherit AbstractValueCoder<'a>()\r\n    let mutable useExternalStore = useExternalStore\r\n\r\n    member private x.UseExternalStore \r\n        with get() = useExternalStore\r\n        and set v = useExternalStore <- v\r\n\r\n    abstract member WriteState : IWriter * 'a * byref<CodeState> -> unit\r\n    abstract member ReadState : IReader * byref<'a> * byref<CodeState> -> unit\r\n    abstract member WithStore : bool -> AbstractByRefValueCoder<'a>\r\n\r\n    default x.WithStore ext =\r\n        let res = base.MemberwiseClone() |> unbox<AbstractByRefValueCoder<'a>>\r\n        res.UseExternalStore <- ext\r\n        res |> unbox<_>\r\n\r\n    interface IReferenceCoder with\r\n        member x.WithInternalStore = \r\n            if useExternalStore then x.WithStore true :> IValueCoder\r\n            else x :> IValueCoder\r\n\r\n        member x.WithExternalStore = \r\n            if useExternalStore then x :> IValueCoder\r\n            else x.WithStore false :> IValueCoder\r\n\r\n    override x.Read(r) =\r\n        { new Code<'a>() with\r\n            override __.Run(s) = \r\n                let id = r.ReadPrimitive().Run(&s)\r\n\r\n                if id = Guid.Empty then\r\n                    Unchecked.defaultof<'a>\r\n                else\r\n                    let load = \r\n                        if useExternalStore then Code.tryLoad id\r\n                        else Code.tryLoadLocal id\r\n\r\n                    match load.Run(&s) with\r\n                        | Some v -> v\r\n                        | _ ->\r\n                            let mutable self = NewObj<'a>.Create()\r\n                            (Code.storeLocal id self).Run(&s)\r\n                            s <- { s with Values = Map.add id (self :> obj) s.Values }\r\n                            x.ReadState(r, &self, &s)\r\n                            self\r\n        }\r\n\r\n    override x.Write(w,v) =\r\n        { new Code<unit>() with\r\n            override __.RunUnit(s) = \r\n                if isNull (v :> obj) then\r\n                    w.WritePrimitive(Guid.Empty).Run(&s)\r\n                else\r\n                    let store =\r\n                        if useExternalStore then Code.tryStore v\r\n                        else Code.tryStoreLocal v\r\n                \r\n                    let (isNew, id) = store.Run(&s)\r\n                    w.WritePrimitive(id).Run(&s)\r\n\r\n                    if isNew then\r\n                        x.WriteState(w, v, &s)\r\n        }\r\n\r\n    new() = AbstractByRefValueCoder(false)\r\n\r\n\r\n[<AbstractClass>]\r\ntype CustomCoder<'a>() =\r\n    inherit AbstractValueCoder<'a>()\r\n\r\n    abstract member WriteState : IWriter * 'a * byref<CodeState> -> unit\r\n    abstract member ReadState : IReader * byref<CodeState> -> 'a\r\n\r\n\r\n    override x.Read(r) =\r\n        { new Code<'a>() with\r\n            override __.Run(s) = x.ReadState(r, &s)\r\n        }\r\n\r\n    override x.Write(w,v) =\r\n        { new Code<unit>() with\r\n            override __.RunUnit(s) = x.WriteState(w, v, &s)\r\n        }\r\n\r\n\r\n\r\n"
  },
  {
    "path": "src/Aardvark.Base.Runtime/Coder/State.fs",
    "content": "namespace Aardvark.Base.Runtime\r\n\r\nopen System\r\nopen System.Runtime.CompilerServices\r\nopen Aardvark.Base\r\n\r\n\r\n[<AbstractClass>]\r\ntype State<'s, 'a>() =\r\n    abstract member Run : byref<'s> -> 'a\r\n    abstract member RunUnit : byref<'s> -> unit\r\n\r\n    default x.Run(s) = x.RunUnit(&s); Unchecked.defaultof<'a>\r\n    default x.RunUnit(s) = x.Run(&s) |> ignore\r\n\r\n\r\nmodule State =\r\n    \r\n\r\n    type private EmptyState<'s>() =\r\n        inherit State<'s, unit>()\r\n        static let instance = EmptyState<'s>() :> State<'s, unit>\r\n        override x.RunUnit(s) = ()\r\n        static member Instance = instance\r\n\r\n    type private GetState<'s>() =\r\n        inherit State<'s, 's>()\r\n        static let instance = GetState<'s>() :> State<'s, 's>\r\n        override x.Run(s) = s\r\n        static member Instance = instance\r\n\r\n    type private PutState<'s>(value : 's) =\r\n        inherit State<'s, unit>()\r\n        override x.RunUnit(s) = s <- value\r\n\r\n    type private ModifyState<'s>(value : 's -> 's) =\r\n        inherit State<'s, unit>()\r\n        override x.RunUnit(s) = s <- value s\r\n\r\n    let empty<'s> = EmptyState<'s>.Instance\r\n\r\n    let ofValue (v : 'a) =\r\n        { new State<'s, 'a>() with\r\n            override x.Run(s) = v\r\n        }\r\n\r\n    let map (f : 'a -> 'b) (m : State<'s, 'a>) =\r\n        { new State<'s, 'b>() with\r\n            override x.Run(s) = m.Run(&s) |> f\r\n        }\r\n\r\n    let bind (f : 'a -> State<'s, 'b>) (m : State<'s, 'a>) =\r\n        { new State<'s, 'b>() with\r\n            override x.Run(s) = \r\n                let v = m.Run(&s)\r\n                (f v).Run(&s)\r\n        }\r\n\r\n    let delay (f : unit -> State<'s, 'a>) =\r\n        { new State<'s, 'a>() with\r\n            override x.Run(s) = f().Run(&s)\r\n        }\r\n\r\n    let combine (l : State<'s, unit>) (r : State<'s, 'a>) =\r\n        { new State<'s, 'a>() with\r\n            override x.Run(s) =\r\n                l.RunUnit(&s)\r\n                r.Run(&s)\r\n        }\r\n\r\n\r\n    let get<'s> = GetState<'s>.Instance\r\n\r\n    let put (s : 's) = PutState(s) :> State<_,_>\r\n\r\n    let modify (f : 's -> 's) = ModifyState(f) :> State<_,_>\r\n\r\n    let run (state : 's) (m : State<'s, 'a>) =\r\n        let mutable state = state\r\n        let v = m.Run(&state)\r\n        state, v\r\n\r\nmodule StateSeq =\r\n    open System.Collections.Generic\r\n\r\n    let map (f : 'a -> State<'s, 'b>) (elements : seq<'a>) =\r\n        { new State<'s, seq<'b>>() with\r\n            override x.Run(s) =\r\n                let res = List<'b>()\r\n                for e in elements do\r\n                    (f e).Run(&s) |> res.Add\r\n\r\n                res :> seq<_>\r\n        }\r\n\r\n    let choose (f : 'a -> State<'s, Option<'b>>) (elements : seq<'a>) =\r\n        { new State<'s, seq<'b>>() with\r\n            override x.Run(s) =\r\n                let res = List<'b>()\r\n                for e in elements do\r\n                    match (f e).Run(&s) with\r\n                        | Some v -> res.Add v\r\n                        | None -> ()\r\n\r\n                res :> seq<_>\r\n        }\r\n\r\n    let filter (f : 'a -> State<'s, bool>) (elements : seq<'a>) =\r\n        { new State<'s, seq<'a>>() with\r\n            override x.Run(s) =\r\n                let res = List<'a>()\r\n                for e in elements do\r\n                    if (f e).Run(&s) then\r\n                        res.Add e\r\n\r\n                res :> seq<_>\r\n        }\r\n\r\n    let collect (f : 'a -> State<'s, #seq<'b>>) (elements : seq<'a>) =\r\n        { new State<'s, seq<'b>>() with\r\n            override x.Run(s) =\r\n                let res = List<'b>()\r\n                for e in elements do\r\n                    let elems = (f e).Run(&s)\r\n                    res.AddRange elems\r\n\r\n                res :> seq<_>\r\n        }\r\n\r\nmodule StateList =\r\n    open System.Collections.Generic\r\n\r\n    let map (f : 'a -> State<'s, 'b>) (elements : list<'a>) =\r\n        { new State<'s, list<'b>>() with\r\n            override x.Run(s) =\r\n                let res = List<'b>()\r\n                for e in elements do\r\n                    (f e).Run(&s) |> res.Add\r\n\r\n                res |> CSharpList.toList\r\n        }\r\n\r\n    let choose (f : 'a -> State<'s, Option<'b>>) (elements : list<'a>) =\r\n        { new State<'s, list<'b>>() with\r\n            override x.Run(s) =\r\n                let res = List<'b>()\r\n                for e in elements do\r\n                    match (f e).Run(&s) with\r\n                        | Some v -> res.Add v\r\n                        | None -> ()\r\n\r\n                res |> CSharpList.toList\r\n        }\r\n\r\n    let filter (f : 'a -> State<'s, bool>) (elements : list<'a>) =\r\n        { new State<'s, list<'a>>() with\r\n            override x.Run(s) =\r\n                let res = List<'a>()\r\n                for e in elements do\r\n                    if (f e).Run(&s) then\r\n                        res.Add e\r\n\r\n                res |> CSharpList.toList\r\n        }\r\n\r\n    let collect (f : 'a -> State<'s, list<'b>>) (elements : list<'a>) =\r\n        { new State<'s, list<'b>>() with\r\n            override x.Run(s) =\r\n                let res = List<'b>()\r\n                for e in elements do\r\n                    let elems = (f e).Run(&s)\r\n                    res.AddRange elems\r\n\r\n                res |> CSharpList.toList\r\n        }\r\n\r\n[<AbstractClass; Sealed; Extension>]\r\ntype StateExtensions private() =\r\n    \r\n    [<Extension>]\r\n    static member run(this : State<'s, 'a>, state : 's) =\r\n        let mutable state = state\r\n        let res = this.Run(&state)\r\n        state, res\r\n\r\n\r\n\r\n[<AutoOpen>]\r\nmodule StateBuilder =\r\n    \r\n\r\n    type StateBuilder() =\r\n        member inline x.Bind(m : State<'s, 'a>, f : 'a -> State<'s, 'b>) = State.bind f m\r\n        member inline x.Return(v : 'a) = State.ofValue v\r\n        member inline x.ReturnFrom(s : State<'s, 'a>) = s\r\n        member inline x.Delay(f : unit -> State<'s, 'a>) = State.delay f\r\n        member inline x.Combine(l : State<'s, unit>, r : State<'s, 'a>) = State.combine l r\r\n        member inline x.Zero() = State.empty\r\n        member inline x.For (elements : seq<'a>, f : 'a -> State<'s, unit>) =\r\n            { new State<'s, unit>() with\r\n                override x.RunUnit(s) =\r\n                    for e in elements do\r\n                        (f e).RunUnit(&s)\r\n            }\r\n        member inline x.While (guard : unit -> bool, body : State<'s, unit>) =\r\n            { new State<'s, unit>() with\r\n                override x.RunUnit(s) =\r\n                    while guard() do\r\n                        body.Run(&s)\r\n            }\r\n\r\n    type SpecificStateBuilder<'s>() =\r\n        member inline x.Bind(m : State<'s, 'a>, f : 'a -> State<'s, 'b>) = State.bind f m\r\n        member inline x.Return(v : 'a) = State.ofValue v\r\n        member inline x.ReturnFrom(s : State<'s, 'a>) = s\r\n        member inline x.Delay(f : unit -> State<'s, 'a>) = State.delay f\r\n        member inline x.Combine(l : State<'s, unit>, r : State<'s, 'a>) = State.combine l r\r\n        member inline x.Zero() = State.empty\r\n        member inline x.For (elements : seq<'a>, f : 'a -> State<'s, unit>) =\r\n            { new State<'s, unit>() with\r\n                override x.RunUnit(s) =\r\n                    for e in elements do\r\n                        (f e).RunUnit(&s)\r\n            }\r\n        member inline x.While (guard : unit -> bool, body : State<'s, unit>) =\r\n            { new State<'s, unit>() with\r\n                override x.RunUnit(s) =\r\n                    while guard() do\r\n                        body.Run(&s)\r\n            }\r\n\r\n\r\n    let state = StateBuilder()\r\n"
  },
  {
    "path": "src/Aardvark.Base.Runtime/Coder/Utilities.fs",
    "content": "﻿namespace Aardvark.Base.Runtime\r\n\r\nopen System\r\nopen System.Reflection\r\nopen System.Collections.Generic\r\nopen System.Runtime.CompilerServices\r\nopen Microsoft.FSharp.Reflection\r\nopen Aardvark.Base\r\nopen FSharp.Data.Adaptive\r\n\r\n\r\n[<CustomEquality; NoComparison>]\r\ntype private R<'a when 'a : not struct> =\r\n    struct\r\n        val mutable public Value : 'a\r\n\r\n        override x.GetHashCode() = System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(x.Value)\r\n        override x.Equals o =\r\n            match o with\r\n                | :? R<'a> as o -> Object.ReferenceEquals(x.Value, o.Value)\r\n                | _ -> false\r\n\r\n        new(v) = { Value = v }\r\n    end\r\n\r\ntype RefMap<'a, 'b when 'a : not struct> = private { store : HashMap<R<'a>, 'b> }\r\n\r\nmodule RefMap =\r\n    type private EmptyImpl<'a, 'b when 'a : not struct>() =\r\n        static let instance = { store = HashMap.empty<R<'a>, 'b> }\r\n        static member Instance = instance\r\n\r\n    let empty<'a, 'b when 'a : not struct> = EmptyImpl<'a, 'b>.Instance\r\n\r\n    let add (key : 'a) (value : 'b) (m : RefMap<'a, 'b>) =\r\n        { store = HashMap.add (R key) value m.store }\r\n\r\n    let remove (key : 'a) (m : RefMap<'a, 'b>) =\r\n        { store = HashMap.remove (R key) m.store }\r\n\r\n    let containsKey (key : 'a) (m : RefMap<'a, 'b>) =\r\n        HashMap.containsKey (R key) m.store\r\n\r\n    let update (key : 'a) (f : Option<'b> -> 'b) (m : RefMap<'a, 'b>) =\r\n        let key = R key\r\n        { store = HashMap.update key f m.store }\r\n\r\n    let tryFind (key : 'a) (m : RefMap<'a, 'b>) =\r\n        HashMap.tryFind (R key) m.store\r\n\r\n\r\n\r\n[<AutoOpen>]\r\nmodule TypePropertyExtensions =\r\n    open System.Runtime.InteropServices\r\n    open System.Collections.Concurrent\r\n\r\n    type private TypePropertyImpl<'a> private() =\r\n        static let isBlittable =\r\n            if typeof<'a>.IsValueType then\r\n                try\r\n                    let gc = GCHandle.Alloc(Unchecked.defaultof<'a>, GCHandleType.Pinned)\r\n                    gc.Free()\r\n                    true\r\n                with _ ->\r\n                    false\r\n            else\r\n                false\r\n\r\n        static member IsBlittable = isBlittable\r\n\r\n    let blittable<'a> = TypePropertyImpl<'a>.IsBlittable\r\n\r\n    let private blittableCache = ConcurrentDictionary<Type, bool>()\r\n\r\n    type BindingFlags with\r\n        static member AnyInstance = \r\n            BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Instance\r\n\r\n        static member AnyStatic = \r\n            BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Static\r\n\r\n        static member Any = \r\n            BindingFlags.NonPublic ||| BindingFlags.Public ||| BindingFlags.Static ||| BindingFlags.Instance\r\n\r\n    type Type with\r\n        member x.IsBlittable =\r\n            blittableCache.GetOrAdd(x, fun x ->\r\n                let x = \r\n                    if x.IsByRef then x.GetElementType()\r\n                    else x\r\n\r\n                let tb = typedefof<TypePropertyImpl<_>>.MakeGenericType [|x|]\r\n                let prop = tb.GetProperty(\"IsBlittable\", BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic)\r\n                prop.GetValue(null) |> unbox<bool>\r\n            )\r\n\r\n[<AutoOpen>]\r\nmodule ReflectionReferenceHelpers = \r\n    open System.Reflection.Emit\r\n\r\n    type Clone<'a when 'a : not struct> private() =\r\n        static let copyFields =\r\n            let t = typeof<'a>\r\n            let fields = t.GetFields(BindingFlags.AnyInstance)\r\n\r\n            let copyMeth =\r\n                DynamicMethod(\r\n                    sprintf \"CopyAllFields_%A\" t,\r\n                    typeof<Void>,\r\n                    [| t; t |],\r\n                    t,\r\n                    true\r\n                )\r\n\r\n            let il = copyMeth.GetILGenerator()\r\n\r\n            for f in fields do\r\n                il.Emit(OpCodes.Ldarg_0)\r\n                il.Emit(OpCodes.Ldarg_1)\r\n                il.Emit(OpCodes.Ldfld, f)\r\n                il.Emit(OpCodes.Stfld, f)\r\n\r\n            il.Emit(OpCodes.Ret)\r\n\r\n            copyMeth.CreateDelegate(typeof<Action<'a, 'a>>)\r\n                |> unbox<Action<'a, 'a>>\r\n\r\n        static member CopyFields (target : 'a, source : 'a) =\r\n            copyFields.Invoke(target, source)\r\n\r\n    let copyAllFields (target : 'a) (source : 'a) =\r\n        Clone<'a>.CopyFields(target, source)\r\n\r\n\r\nmodule OverloadResolution =\r\n    type ExtensionMethod =\r\n        {\r\n            definition  : MethodInfo\r\n            selfType    : Type\r\n            parameters  : Type[]\r\n        }\r\n\r\n    let private extensions =\r\n        Introspection.GetAllMethodsWithAttribute<ExtensionAttribute>()\r\n            |> Seq.choose (fun struct (meth, _) ->\r\n\r\n                let parameterTypes = meth.GetParameters() |> Array.map (fun p -> p.ParameterType)\r\n                \r\n                if parameterTypes.Length > 0 then\r\n                    //printfn \"extension %s(%s)\" meth.Name parameterTypes.[0].FullName\r\n                    Some {\r\n                        definition = meth\r\n                        selfType = parameterTypes.[0]\r\n                        parameters = Array.sub parameterTypes 1 (parameterTypes.Length-1)\r\n                    }\r\n                else\r\n                    None\r\n               )\r\n            |> Seq.toArray\r\n            |> Seq.groupBy (fun m -> m.definition.Name)\r\n            |> Seq.map (fun (name, exts) -> name, Seq.toArray (System.Collections.Generic.HashSet exts))\r\n            |> Dictionary.ofSeq\r\n\r\n    let tryUnifyTypes (decl : Type) (real : Type) =\r\n        let assignment = Dictionary<Type, Type>()\r\n\r\n        let rec recurse (decl : Type) (real : Type) =\r\n            if decl = real then\r\n                true\r\n\r\n            elif decl.IsGenericParameter then\r\n                match assignment.TryGetValue decl with\r\n                    | (true, old) ->\r\n                        if old.IsAssignableFrom real then \r\n                            true\r\n\r\n                        elif real.IsAssignableFrom old then\r\n                            assignment.[decl] <- real\r\n                            true\r\n\r\n                        else \r\n                            false\r\n                    | _ ->\r\n                        assignment.[decl] <- real\r\n                        true\r\n            \r\n            elif decl.IsArray then\r\n                if real.IsArray then\r\n                    let de = decl.GetElementType()\r\n                    let re = real.GetElementType()\r\n                    recurse de re\r\n                else\r\n                    false\r\n\r\n            elif decl.ContainsGenericParameters then\r\n                let dgen = decl.GetGenericTypeDefinition()\r\n                let rgen = \r\n                    if real.IsGenericType then real.GetGenericTypeDefinition()\r\n                    else real\r\n\r\n                if dgen = rgen then\r\n                    let dargs = decl.GetGenericArguments()\r\n                    let rargs = real.GetGenericArguments()\r\n                    Array.forall2 recurse dargs rargs\r\n\r\n                elif dgen.IsInterface then\r\n                    let rface = real.GetInterface(dgen.FullName)\r\n                    if isNull rface then\r\n                        false\r\n                    else\r\n                        recurse decl rface\r\n\r\n                elif not (isNull real.BaseType) then\r\n                    recurse decl real.BaseType\r\n\r\n                else\r\n                    false\r\n\r\n            elif decl.IsAssignableFrom real then\r\n                true\r\n\r\n            else\r\n                false\r\n\r\n\r\n        if recurse decl real then\r\n            Some (assignment |> Dictionary.toSeq |> HashMap.ofSeq)\r\n        else\r\n            None\r\n\r\n    let trySpecialize (self : Type) (m : ExtensionMethod)  =\r\n        match tryUnifyTypes m.selfType self with\r\n            | Some ass ->\r\n                if m.definition.IsGenericMethodDefinition then\r\n                    let holes = m.definition.GetGenericArguments()\r\n\r\n                    let filled = \r\n                        holes |> Array.map (fun h ->\r\n                            match HashMap.tryFind h ass with\r\n                                | Some r -> r\r\n                                | None -> h\r\n                        )\r\n\r\n                    let grounded = \r\n                        filled |> Array.forall (fun t -> t.ContainsGenericParameters |> not)\r\n\r\n                    if grounded then\r\n                        let m = m.definition.MakeGenericMethod filled\r\n                        let parTypes = m.GetParameters() |> Array.map (fun p -> p.ParameterType)\r\n                        Some {\r\n                            definition = m\r\n                            selfType = parTypes.[0]\r\n                            parameters = Array.skip 1 parTypes\r\n                        }\r\n                    else\r\n                        None\r\n\r\n                else\r\n                    Some m\r\n            \r\n            | _ ->\r\n                None\r\n\r\n    let tryFindExtension (self : Type) (name : string) (args : Type[]) =\r\n        match extensions.TryGetValue name with\r\n            | (true, possible) ->\r\n                let good = \r\n                    possible \r\n                        |> Array.filter (fun ext -> ext.parameters.Length = args.Length)\r\n                        |> Array.choose (trySpecialize self)\r\n                        |> Array.filter (fun ext ->\r\n                            Array.forall2 (fun (l : Type) r -> l.IsAssignableFrom r) ext.parameters args\r\n                           )\r\n\r\n                if good.Length = 0 then\r\n                    None\r\n                elif good.Length = 1 then\r\n                    Some good.[0].definition\r\n                else\r\n                    let selected = \r\n                        Type.DefaultBinder.SelectMethod(\r\n                            BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Instance ||| BindingFlags.Static,\r\n                            good |> Array.map (fun m -> m.definition :> MethodBase),\r\n                            Array.append [|self|] args,\r\n                            null\r\n                        )\r\n\r\n                    if isNull selected then None\r\n                    else Some (unbox<MethodInfo> selected)\r\n            \r\n            | _ -> None\r\n\r\n[<AbstractClass; Sealed; Extension>]\r\ntype TypeExtensions private() =\r\n\r\n        [<Extension>]\r\n        static member TryUnifyWith (x : Type, concrete : Type) =\r\n            OverloadResolution.tryUnifyTypes x concrete\r\n\r\n        [<Extension>]\r\n        static member TryGetExtensionMethod(x : Type, name : string, args : Type[]) =\r\n            OverloadResolution.tryFindExtension x name args\r\n\r\n        [<Extension>]\r\n        static member UnifyWith (x : Type, concrete : Type) =\r\n            OverloadResolution.tryUnifyTypes x concrete |> Option.get\r\n\r\n        [<Extension>]\r\n        static member GetExtensionMethod(x : Type, name : string, args : Type[]) =\r\n            match OverloadResolution.tryFindExtension x name args with\r\n                | Some mi -> mi\r\n                | None -> null\r\n\r\n        [<Extension>]\r\n        static member GetMethodOrExtension(x : Type, name : string, args : Type[]) =\r\n            let meth = x.GetMethod(name, BindingFlags.AnyInstance, Type.DefaultBinder, args, null)\r\n            if isNull meth then\r\n                match OverloadResolution.tryFindExtension x name args with\r\n                    | Some mi -> mi\r\n                    | None -> null\r\n            else\r\n                meth\r\n\r\n"
  },
  {
    "path": "src/Aardvark.Base.Runtime/Coder/ValueCoders.fs",
    "content": "﻿namespace Aardvark.Base.Runtime\r\n\r\nopen System\r\nopen System.Reflection\r\nopen System.Reflection.Emit\r\nopen System.Collections.Concurrent\r\nopen System.Runtime.InteropServices\r\nopen System.Runtime.CompilerServices\r\nopen Microsoft.FSharp.Reflection\r\nopen Aardvark.Base\r\nopen Aardvark.Base.Runtime\r\n\r\nmodule AutoCoders =\r\n    open Aardvark.Base.IL\r\n    open Aardvark.Base.IL.TypeBuilder\r\n\r\n    type private NewObj<'a>() =\r\n        static member Create() : 'a =\r\n            System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(typeof<'a>) |> unbox<'a>\r\n\r\n    // creates a ValueCoder-Type for the given valueType\r\n    // reading/writing all fields sequentially (currently ordered by name)\r\n    // NOTE: the generated type provides a constructor expecting a\r\n    //       \"FieldInfo -> IValueCoder\" function as argument\r\n    let createFieldCoder (valueType : Type) =\r\n        let baseType = typedefof<AbstractByRefValueCoder<_>>.MakeGenericType [|valueType|]\r\n        let stateRefType = typeof<CodeState>.MakeByRefType()\r\n\r\n        // TODO: find appropriate order and think about versioning\r\n        let fields = \r\n            valueType.GetFields(BindingFlags.AnyInstance)\r\n                |> Array.sortBy (fun fi -> fi.Name)\r\n\r\n\r\n        newtype {\r\n            do! inh baseType\r\n\r\n            // define fields holding coder instances for\r\n            // all of the valueType's fields\r\n            let coderFields = Array.zeroCreate fields.Length\r\n            for i in 0..fields.Length-1 do\r\n                let coderFieldType = typedefof<IValueCoder<_>>.MakeGenericType [| fields.[i].FieldType |]\r\n                let! coderField = fld (sprintf \"m_coder_%s\" fields.[i].Name) coderFieldType\r\n                coderFields.[i] <- coderField\r\n\r\n            // override WriteState\r\n            do! mem typeof<Void> \"WriteState\" [ typeof<IWriter>; valueType; stateRefType ] (\r\n                    codegen {\r\n                        \r\n                        for fi in 0..fields.Length-1 do\r\n                            let valueField = fields.[fi]\r\n                            let coderField = coderFields.[fi]\r\n\r\n                            // the following sets up arguments for the call to:\r\n                            // ValueCoderExtensions.WriteState (this : IValueCoder<'a>, w : IWriter, value : 'a, state : byref<CodeState>)\r\n\r\n                            // load the associated valuecoder\r\n                            //   stack = [valueCoder]\r\n                            do! IL.ldarg 0\r\n                            do! IL.ldfld coderField\r\n\r\n                            // load the writer\r\n                            //   stack = [writer; valueCoder]\r\n                            do! IL.ldarg 1\r\n\r\n                            // load the value\r\n                            //   stack = [value; writer; valueCoder]\r\n                            do! IL.ldarg 2\r\n\r\n                            // load the field \r\n                            //   stack = [value.field; writer; valueCoder]\r\n                            do! IL.ldfld valueField\r\n\r\n                            // load the ref containing state\r\n                            //   stack = [&state; value.field; writer; valueCoder]\r\n                            do! IL.ldarg 3\r\n\r\n                            // call the coder's write method\r\n                            //   stack = []\r\n                            let meth = ValueCoderExtensions.GetWriteMethod(coderField.FieldType, valueField.FieldType)\r\n                            do! IL.call meth\r\n\r\n                        do! IL.ret\r\n                    }\r\n                )\r\n\r\n            // override ReadState\r\n            do! mem typeof<Void> \"ReadState\" [ typeof<IReader>; valueType.MakeByRefType(); stateRefType ] (\r\n                    codegen {\r\n//                        // create a new instance of the given type\r\n//                        //   stack = [result]\r\n//                        let not = typedefof<NewObj<_>>.MakeGenericType [|valueType|]\r\n//                        do! IL.call (not.GetMethod(\"Create\", BindingFlags.AnyStatic))\r\n//\r\n//                        // store the result to a local ref\r\n//                        //   stack = []\r\n//                        let! result = IL.newlocal valueType\r\n//                        do! IL.stloc result\r\n\r\n                        \r\n                        for fi in 0..fields.Length-1 do\r\n                            let valueField : FieldInfo = fields.[fi]\r\n                            let coderField = coderFields.[fi]\r\n\r\n                            // the following sets up arguments for the call to:\r\n                            // ValueCoderExtensions.ReadState (this : IValueCoder<'a>, w : IReader, state : byref<CodeState>)\r\n                            \r\n                            // load the overall result\r\n                            //   stack = [result]\r\n                            do! IL.ldarg 2\r\n                            if not valueType.IsValueType then\r\n                                do! IL.ldind ValueType.Object\r\n\r\n\r\n                            // load the associated valuecoder\r\n                            //   stack = [valueCoder; result]\r\n                            do! IL.ldarg 0\r\n                            do! IL.ldfld coderField\r\n\r\n                            // load the writer\r\n                            //   stack = [reader; valueCoder; result]\r\n                            do! IL.ldarg 1\r\n\r\n                            // load the state ref\r\n                            //   stack = [&state; writer; valueCoder; result]\r\n                            do! IL.ldarg 3\r\n\r\n                            // read the value\r\n                            //   stack = [value; result]\r\n                            let meth = ValueCoderExtensions.GetReadMethod(coderField.FieldType, valueField.FieldType)\r\n                            do! IL.call meth\r\n\r\n                            // store the value we just read\r\n                            //   stack = []\r\n                            do! IL.stfld valueField\r\n   \r\n                        // load and return the result\r\n                        do! IL.ret\r\n                    }\r\n                )\r\n\r\n            // define a ctor resolving all needed value-coders\r\n            do! ctor [ typeof<FieldInfo -> IValueCoder> ] (\r\n                    codegen {\r\n                        do! IL.ldarg 0\r\n                        do! IL.call (baseType.GetConstructor [||])\r\n\r\n                        for fi in 0..fields.Length-1 do\r\n                            let f = fields.[fi]\r\n                            let coderField = coderFields.[fi]\r\n\r\n                            // load this\r\n                            //   stack = [this]\r\n                            do! IL.ldarg 0\r\n\r\n                            // load the resolve-lambda\r\n                            //   stack = [resolve; this]\r\n                            do! IL.ldarg 1\r\n\r\n                            // load the fieldInfo\r\n                            //   stack = [fieldInfo; resolve; this]\r\n                            do! IL.ldtoken f\r\n                            do! IL.ldtoken valueType\r\n                            do! IL.call <@ FieldInfo.GetFieldFromHandle : _ * _ -> _ @>\r\n\r\n                            // resolve the field-coder\r\n                            //   stack = [IValueCoder; this]\r\n                            do! IL.call ( typeof<FieldInfo -> IValueCoder>.GetMethod \"Invoke\" )\r\n\r\n                            // store the resolved coder\r\n                            //   stack = []\r\n                            do! IL.stfld coderField\r\n\r\n                        do! IL.ret\r\n                    }\r\n                )\r\n\r\n        }\r\n\r\n\r\nmodule CustomCoders =\r\n    open Aardvark.Base.IL\r\n    open Aardvark.Base.IL.TypeBuilder\r\n\r\n    let private extensions =\r\n        Introspection.GetAllMethodsWithAttribute<ExtensionAttribute>()\r\n            |> Seq.choose (fun struct (meth, _) ->\r\n                let args = meth.GetParameters() |> Array.map (fun p -> p.ParameterType)\r\n                \r\n                if meth.Name = \"Code\" && args.Length = 2 && args.[0] = typeof<ICoder> then\r\n                    let codedType = args.[1]\r\n                    let ret = meth.ReturnType\r\n                    if codedType.IsGenericType && codedType.GetGenericTypeDefinition() = typedefof<ref<_>> && ret = typeof<Code<unit>> then\r\n                        let valueType = codedType.GetGenericArguments().[0]\r\n\r\n                        if valueType.ContainsGenericParameters then\r\n                            Some (valueType.GetGenericTypeDefinition(), meth)\r\n                        else\r\n                            Some (valueType, meth)\r\n                    else\r\n                        None\r\n\r\n                else\r\n                    None\r\n                    \r\n               )\r\n            |> Dictionary.ofSeq\r\n\r\n    type Ref<'a>() =\r\n        static member Create() = ref Unchecked.defaultof<'a>\r\n\r\n    let buildCustomCoder (valueType : Type) (codeMethod : MethodInfo) =\r\n        \r\n        let baseType = typedefof<CustomCoder<_>>.MakeGenericType [|valueType|]\r\n        let stateRefType = typeof<CodeState>.MakeByRefType()\r\n        let run = typeof<State<CodeState, unit>>.GetMethod \"RunUnit\"\r\n\r\n        let valueRef = typedefof<ref<_>>.MakeGenericType [|valueType|]\r\n        let refField = valueRef.GetField(\"contents@\")\r\n\r\n        let emptyRef = typedefof<Ref<_>>.MakeGenericType([|valueType|]).GetMethod(\"Create\", BindingFlags.AnyStatic)\r\n\r\n        newtype {\r\n            do! inh baseType\r\n\r\n            // override WriteState\r\n            do! mem typeof<Void> \"WriteState\" [ typeof<IWriter>; valueType; stateRefType ] (\r\n                    codegen {\r\n                        // load writer\r\n                        //   stack = [writer]\r\n                        do! IL.ldarg 1\r\n\r\n                        // load the value and wrap it in a ref\r\n                        //   stack = [ref value; writer]\r\n                        do! IL.ldarg 2\r\n                        let ctor = valueRef.GetConstructor [|valueType|]\r\n                        do! IL.newobj ctor\r\n\r\n                        // call the code method\r\n                        //   stack = [coder]\r\n                        do! IL.call codeMethod\r\n\r\n                        // load state-ref\r\n                        //   stack = [&state; coder]\r\n                        do! IL.ldarg 3\r\n\r\n                        // call Code<unit>.RunUnit\r\n                        //   stack = []\r\n                        do! IL.call run\r\n\r\n                        do! IL.ret\r\n                    }\r\n                )\r\n\r\n            // override ReadState\r\n            do! mem valueType \"ReadState\" [ typeof<IReader>; stateRefType ] (\r\n                    codegen {\r\n                        let! r = IL.newlocal valueRef\r\n                        \r\n                        // load reader \r\n                        //   stack = [reader]\r\n                        do! IL.ldarg 1\r\n\r\n\r\n                        // create a ref and load it onto the stack\r\n                        //   stack = [ref value; reader]\r\n                        do! IL.call emptyRef\r\n                        do! IL.stloc r\r\n                        do! IL.ldloc r\r\n\r\n                        // call the code method\r\n                        //   stack = [coder]\r\n                        do! IL.call codeMethod\r\n\r\n                        // load state-ref\r\n                        //   stack = [&state; coder]\r\n                        do! IL.ldarg 2\r\n\r\n                        // call Code<unit>.RunUnit\r\n                        //   stack = []\r\n                        do! IL.call run\r\n\r\n\r\n                        // dereference the ref\r\n                        //   stack = [!ref]\r\n                        do! IL.ldloc r\r\n                        do! IL.ldfld refField\r\n\r\n\r\n                        do! IL.ret\r\n                    }\r\n                )\r\n\r\n            // define a ctor resolving all needed value-coders\r\n            do! ctor [ ] (\r\n                    codegen {\r\n                        do! IL.ldarg 0\r\n                        do! IL.call (baseType.GetConstructor [||])\r\n                        do! IL.ret\r\n                    }\r\n                )\r\n        }\r\n\r\n\r\n\r\n\r\n    let tryGetCustomCoderType (valueType : Type) =\r\n\r\n        let valueType =\r\n            if valueType.IsByRef then valueType.GetElementType()\r\n            else valueType\r\n\r\n        let meth = valueType.GetMethod(\"Code\", BindingFlags.AnyStatic, Type.DefaultBinder, [|typeof<ICoder>; valueType.MakeByRefType()|], null)\r\n\r\n        if not (isNull meth) && meth.ReturnType = typeof<Code<unit>> then\r\n            let coder = buildCustomCoder valueType meth\r\n            Some coder\r\n        else\r\n            let lookup = \r\n                if valueType.IsGenericType then valueType.GetGenericTypeDefinition()\r\n                else valueType \r\n\r\n            match extensions.TryGetValue lookup with\r\n                | (true, meth) ->\r\n                    let meth = \r\n                        if lookup = valueType then Some meth\r\n                        else \r\n                            let parType = meth.GetParameters().[1].ParameterType.GetGenericArguments().[0]\r\n\r\n                            let assignment =\r\n                                Array.zip (parType.GetGenericArguments()) (valueType.GetGenericArguments())\r\n                                    |> Dictionary.ofArray\r\n\r\n                            let methArgs = \r\n                                meth.GetGenericArguments()\r\n                                    |> Array.map (fun a -> assignment.[a])\r\n\r\n                            let meth = meth.MakeGenericMethod methArgs\r\n\r\n                            Some meth\r\n\r\n                    match meth with\r\n                        | Some meth ->    \r\n                            let coder = buildCustomCoder valueType meth\r\n                            Some coder\r\n                        | _ ->\r\n                            None\r\n                | _ ->\r\n                    None\r\n\r\ntype VersionRangeAttribute(min : int, max : int) =\r\n    inherit Attribute()\r\n\r\n    member x.Min = min\r\n    member x.Max = max\r\n\r\n    new (max : int) = VersionRangeAttribute(Int32.MinValue, max)\r\n          \r\ntype VersionAttribute(v : int) =\r\n    inherit Attribute()\r\n        \r\n    member x.Version = v  \r\n\r\n[<StructuredFormatDisplay(\"{AsString}\")>]\r\ntype PartialCoder =\r\n    | Field of FieldInfo * IValueCoder\r\n    | Property of PropertyInfo * IValueCoder\r\n    | Skip of IValueCoder\r\n\r\n    member private x.AsString =\r\n        match x with\r\n            | Field(f,e) -> sprintf \"this.%s <- %A\" f.Name e\r\n            | Property(f,e) -> sprintf \"this.%s <- %A\" f.Name e\r\n            | Skip e -> sprintf \"skip %A\" e\r\n\r\nmodule FieldCoders =\r\n    open System\r\n    open System.Reflection\r\n    open Aardvark.Base.IL\r\n    open Aardvark.Base.IL.TypeBuilder\r\n    open Microsoft.FSharp.Quotations\r\n    open Microsoft.FSharp.Quotations.Patterns\r\n\r\n\r\n    let (<->) (l : 'a) (r : IValueCoder<'a>) =\r\n        r \r\n\r\n    let (|>>) (l : IValueCoder<'a>) (f : 'a -> 'b) =\r\n        { new AbstractValueCoder<'b>() with\r\n            override x.Read(r) =\r\n                l.Read(r) |> State.map f\r\n            override x.Write(w,v) =\r\n                failwith \"[Coder] cannot write\"\r\n        } :> IValueCoder<_>\r\n\r\n    let (<<|) (f : 'a -> 'b) (l : IValueCoder<'a>) = l |>> f\r\n        \r\n    let skip (l : IValueCoder<'a>) = l\r\n\r\n    type FieldCoderBuilder() =\r\n        \r\n\r\n\r\n        member x.Bind(coder : PartialCoder, f : unit -> list<PartialCoder>) =\r\n            coder :: f()\r\n\r\n        member x.Bind([<ReflectedDefinition(true)>] coder : Expr<IValueCoder<'a>>, f : unit -> list<PartialCoder>) =\r\n            let partial = \r\n                match coder.Raw with\r\n                    | WithValue(:? IValueCoder<'a> as v, _, Call(None, mi, [FieldGet(_,f);r])) ->\r\n                        match mi with\r\n                            | Method(\"op_LessMinusGreater\",_) -> \r\n                                Some(Field(f, v))\r\n\r\n                            | _ ->\r\n                                None\r\n\r\n                    | WithValue(:? IValueCoder<'a> as v, _, Call(None, mi, [PropertyGet(_,p,_);r])) ->\r\n                        match mi with\r\n                            | Method(\"op_LessMinusGreater\",_) -> \r\n                                Some(Property(p, v))\r\n\r\n                            | _ ->\r\n                                None\r\n\r\n                    | WithValue(:? IValueCoder<'a> as v, _, Call(None, mi, [r])) ->\r\n                        match mi with\r\n                            | MethodQuote <@ skip @> _ -> \r\n                                Some(Skip v)\r\n\r\n                            | _ ->\r\n                                None\r\n\r\n                    | _ ->\r\n                        None\r\n\r\n            match partial with\r\n                | Some p -> p::f()\r\n                | _ -> failwithf \"could not create PartialCoder from Expression: %A\" coder\r\n\r\n        member x.Delay(f : unit -> list<PartialCoder>) = f\r\n\r\n        member x.Combine(l : list<PartialCoder>, r : unit -> list<PartialCoder>) =\r\n            List.append l (r())\r\n\r\n        member x.Run(f : unit -> list<PartialCoder>) = f()\r\n\r\n        member x.Zero() : list<PartialCoder> =\r\n            []\r\n\r\n        member x.Return (u : unit) : list<PartialCoder> = \r\n            []\r\n\r\n    let coders = FieldCoderBuilder()\r\n\r\n\r\n\r\n    let private tryGetPartialCodersForVersion (version : int) (t : Type) =\r\n        let coders = t.GetMethodOrExtension(\"Coders\", [|typeof<int>|])\r\n        match coders with\r\n            | null -> None\r\n            | mi ->\r\n                let instance =\r\n                    if t.IsValueType then Activator.CreateInstance(t)\r\n                    else System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(t)\r\n\r\n                let res = \r\n                    if mi.IsStatic then mi.Invoke(null, [|instance; version|]) \r\n                    else mi.Invoke(instance, [|version|]) \r\n\r\n                res |> unbox<list<PartialCoder>>\r\n                    |> Some\r\n\r\n    let private getHeadVersion (valueType : Type) =\r\n        match valueType.GetCustomAttributes<VersionAttribute>() |> Seq.toList with\r\n                | [] -> \r\n                    let coders = valueType.GetMethodOrExtension(\"Coders\", [|typeof<int>|])\r\n                    match coders with\r\n                        | null -> 0\r\n                        | _ ->\r\n                            match coders.GetCustomAttributes<VersionAttribute>() |> Seq.toList  with\r\n                                | [] -> 0\r\n                                | vatt::_ -> vatt.Version\r\n\r\n                | vatt::_ -> vatt.Version\r\n\r\n    type private IReaderExtensions private() =\r\n        \r\n\r\n        static member ReadPrimitiveState(this : IReader, s : byref<CodeState>) : 'a=\r\n            this.ReadPrimitive().Run(&s)\r\n\r\n        static member WritePrimitiveState(this : IWriter, value : 'a, s : byref<CodeState>) : unit=\r\n            this.WritePrimitive(value).Run(&s)\r\n\r\n    let tryBuildFieldCoders (valueType : Type) =\r\n        let headVersion = getHeadVersion valueType\r\n\r\n        match valueType |> tryGetPartialCodersForVersion headVersion with\r\n            | Some headCoders ->\r\n                let readingCoders = \r\n                    Map.ofList [\r\n                        for v in 0..headVersion-1 do\r\n                            let coders = valueType |> tryGetPartialCodersForVersion v |> Option.get\r\n                            yield v, coders\r\n\r\n                        yield headVersion, headCoders\r\n                    ]\r\n\r\n\r\n                let baseType = typedefof<AbstractByRefValueCoder<_>>.MakeGenericType [|valueType|]\r\n                let stateRefType = typeof<CodeState>.MakeByRefType()\r\n                let readPrimitive = typeof<IReaderExtensions>.GetMethod(\"ReadPrimitiveState\", BindingFlags.AnyStatic)\r\n                let writePrimitive = typeof<IReaderExtensions>.GetMethod(\"WritePrimitiveState\", BindingFlags.AnyStatic)\r\n                \r\n                let coderFields = Dict<IValueCoder, FieldBuilder>()\r\n                      \r\n                let coders = ref [||]  \r\n\r\n                let resultType =\r\n                    newtype {\r\n                        for (_,v) in Map.toSeq readingCoders do\r\n                            for c in v do\r\n                                match c with\r\n                                    | Field(_,c) ->\r\n                                        if not (coderFields.ContainsKey(c)) then\r\n                                            let name = sprintf \"s_coder%d\" coderFields.Count\r\n                                            let! f = sfld name (c.GetType())\r\n                                            coderFields.[c] <- f\r\n\r\n                                    | Property(_,c) ->\r\n                                        if not (coderFields.ContainsKey(c)) then\r\n                                            let name = sprintf \"s_coder%d\" coderFields.Count\r\n                                            let! f = sfld name (c.GetType())\r\n                                            coderFields.[c] <- f   \r\n                                    | Skip(c) ->\r\n                                        if not (coderFields.ContainsKey(c)) then\r\n                                            let name = sprintf \"s_coder%d\" coderFields.Count\r\n                                            let! f = sfld name (c.GetType())\r\n                                            coderFields.[c] <- f                        \r\n\r\n                        coders := coderFields |> Dict.toArray\r\n                        let coderValues = !coders |> Array.map fst\r\n                        let coderTypes = !coders |> Array.map (fun (_,f) -> f.FieldType) |> Array.toList\r\n\r\n                        do! inh baseType\r\n                        \r\n                        do! mem typeof<Void> \"ReadState\" [ typeof<IReader>; valueType.MakeByRefType(); stateRefType] (\r\n                                codegen {\r\n                                    let labels = Array.zeroCreate (headVersion + 1)\r\n                                    for i in 0..headVersion do\r\n                                        let! l = IL.newlabel\r\n                                        labels.[i] <- l\r\n\r\n                                    let! version = IL.newlocal typeof<int>\r\n\r\n                                    // read and store the file-version\r\n                                    do! IL.ldarg 1\r\n                                    do! IL.ldarg 3\r\n                                    do! IL.call (readPrimitive.MakeGenericMethod [|typeof<int>|])\r\n                                    do! IL.stloc version\r\n\r\n                                    // switch based on the file-version\r\n                                    do! IL.ldloc version\r\n                                    do! CodeGen.emit(Switch labels)\r\n                                    do! IL.ret\r\n\r\n                                    for v in 0..headVersion do\r\n                                        do! IL.mark labels.[v]\r\n\r\n                                        let partials = Map.find v readingCoders\r\n\r\n                                        for p in partials do\r\n                                            let valueType, coder =\r\n                                                match p with\r\n                                                    | Field(f, coder) -> f.FieldType, coder\r\n                                                    | Property(p, coder) -> p.PropertyType, coder\r\n                                                    | Skip(coder) -> coder.ValueType, coder\r\n                    \r\n                                            let field = coderFields.[coder]\r\n                                                \r\n                                            let! value = IL.newlocal valueType\r\n                                            do! IL.ldfld field\r\n                                            do! IL.ldarg 1\r\n                                            do! IL.ldarg 3\r\n\r\n                                            // read* (this : IValueCoder, r : IReader, state : byref<CodeState>)\r\n                                            let read = ValueCoderExtensions.GetReadMethod(field.FieldType, valueType)\r\n                                            do! IL.call read\r\n                                            do! IL.stloc value\r\n\r\n                                            match p with\r\n                                                | Field(f, _) ->\r\n                                                    do! IL.ldarg 2\r\n                                                    do! IL.ldind ValueType.Object\r\n                                                    do! IL.ldloc value\r\n                                                    do! IL.stfld f\r\n\r\n                                                | Property(p, _) ->\r\n                                                    do! IL.ldarg 2\r\n                                                    do! IL.ldind ValueType.Object\r\n                                                    do! IL.ldloc value\r\n                                                    do! IL.call p.SetMethod\r\n                                                | Skip _ ->\r\n                                                    ()\r\n\r\n\r\n                                        do! IL.ret\r\n\r\n\r\n\r\n\r\n\r\n                                }\r\n                            )\r\n                          \r\n                        do! mem typeof<Void> \"WriteState\" [ typeof<IWriter>; valueType; stateRefType ] (\r\n                                codegen {\r\n                                    \r\n                                    do! IL.ldarg 1\r\n                                    do! IL.ldconst headVersion\r\n                                    do! IL.ldarg 3\r\n                                    do! IL.call (writePrimitive.MakeGenericMethod [| typeof<int> |])\r\n\r\n                                    for p in headCoders do\r\n                                        let valueType, coder =\r\n                                            match p with\r\n                                                | Field(f, coder) -> f.FieldType, coder\r\n                                                | Property(p, coder) -> p.PropertyType, coder\r\n                                                | Skip coder -> failwith \"[FieldCoder] head version may not include skip-coder\"\r\n\r\n                                        let coderField = coderFields.[coder]\r\n\r\n                                        //Write* (this : IValueCoder, w : IWriter, value : 'a, state : byref<CodeState>) =\r\n                                        let write = ValueCoderExtensions.GetWriteMethod(coderField.FieldType, valueType)\r\n\r\n                                        do! IL.ldfld coderField\r\n\r\n                                        do! IL.ldarg 1\r\n\r\n                                        do! IL.ldarg 2\r\n                                        match p with\r\n                                            | Field(f,_) -> do! IL.ldfld f\r\n                                            | Property(p,_) -> do! IL.call p.GetMethod\r\n                                            | Skip coder -> failwith \"[FieldCoder] head version may not include skip-coder\"\r\n\r\n                                        do! IL.ldarg 3\r\n                                        do! IL.call write\r\n\r\n\r\n                                    do! IL.ret\r\n                                }\r\n                            )\r\n                           \r\n\r\n                        do! ctor [] (\r\n                                codegen {\r\n                                    do! IL.ldarg 0\r\n                                    do! IL.call (baseType.GetConstructor [||])\r\n                                    do! IL.ret\r\n                                }\r\n                            )\r\n                    }\r\n\r\n                for (v,f) in !coders do\r\n                    let f = resultType.GetField(f.Name, BindingFlags.AnyStatic)\r\n                    f.SetValue(null, v)\r\n\r\n\r\n                Some resultType\r\n\r\n            | None ->\r\n                None\r\n\r\nmodule ValueCoderTypes =\r\n    \r\n    let coderTypeCache = ConcurrentDictionary<Type, Type>()\r\n    let coderCache = ConcurrentDictionary<Type, IValueCoder>()\r\n\r\n    type PrimitiveCoder<'a when 'a : unmanaged>() =\r\n        inherit AbstractValueCoder<'a>()\r\n        override x.Read(r) = r.ReadPrimitive()\r\n        override x.Write(w,v) = w.WritePrimitive(v)\r\n\r\n    type PrimitiveArrayCoder<'a when 'a : unmanaged>() =\r\n        inherit AbstractValueCoder<'a[]>()\r\n        override x.Read(r) = r.ReadPrimitiveArray()\r\n        override x.Write(w,v) = w.WritePrimitiveArray(v)\r\n\r\n\r\n    type StringCoder() =\r\n        inherit AbstractValueCoder<string>()\r\n        override x.Read(r) = r.ReadString()\r\n        override x.Write(w,v) = w.WriteString(v)\r\n\r\n    type BoolCoder() =\r\n        inherit AbstractValueCoder<bool>()\r\n        override x.Read(r) = r.ReadBool()\r\n        override x.Write(w,v) = w.WriteBool(v)\r\n\r\n    type TypeCoder() =\r\n        inherit AbstractValueCoder<Type>()\r\n\r\n        override x.Read(r) =\r\n            code {\r\n                let! name = r.ReadString()\r\n                if name = \"(null)\" then\r\n                    return null\r\n                else\r\n                    return Type.GetType name\r\n            }\r\n\r\n        override x.Write(w, t) =\r\n            if isNull t then\r\n                w.WriteString \"(null)\"\r\n            else\r\n                w.WriteString t.AssemblyQualifiedName\r\n\r\n\r\n    type Array1dCoder<'a>(useExternalStore : bool, resolve : Type -> IValueCoder) =\r\n        inherit AbstractValueCoder<'a[]>()\r\n\r\n        let elementCoder = resolve typeof<'a> |> unbox<IValueCoder<'a>>\r\n\r\n        override x.Read(r : IReader) =\r\n            code {\r\n                let! id = r.ReadPrimitive()\r\n                if id = Guid.Empty then\r\n                    return null\r\n                else\r\n                    let! ref =\r\n                        if useExternalStore then Code.tryLoad id\r\n                        else Code.tryLoadLocal id\r\n\r\n                    match ref with\r\n                        | Some r -> \r\n                            return r\r\n\r\n                        | _ ->\r\n                            let! length = r.ReadPrimitive()\r\n                            let arr = Array.zeroCreate length\r\n                            do! Code.storeLocal id arr\r\n\r\n                            for i in 0..length-1 do\r\n                                let! v = elementCoder.Read(r)\r\n                                arr.[i] <- v\r\n\r\n                            return arr\r\n\r\n            }\r\n\r\n        override x.Write(w : IWriter, value : 'a[]) =\r\n            code {\r\n                if isNull value then\r\n                    do! w.WritePrimitive Guid.Empty\r\n                else\r\n                    let! (isNew, id) = \r\n                        if useExternalStore then Code.tryStore value\r\n                        else Code.tryStoreLocal value\r\n\r\n                    do! w.WritePrimitive id\r\n                    if isNew then\r\n                        do! w.WritePrimitive value.Length\r\n\r\n                        for i in 0..value.Length-1 do\r\n                            do! elementCoder.Write(w, value.[i])\r\n\r\n\r\n\r\n\r\n            }\r\n\r\n        new(resolve) = Array1dCoder(false, resolve)\r\n\r\n    type Array2dCoder<'a>(useExternalStore : bool, resolve : Type -> IValueCoder) =\r\n        inherit AbstractValueCoder<'a[,]>()\r\n\r\n        let elementCoder = resolve typeof<'a> |> unbox<IValueCoder<'a>>\r\n\r\n        override x.Read(r : IReader) =\r\n            code {\r\n                let! id = r.ReadPrimitive()\r\n                if id = Guid.Empty then\r\n                    return null\r\n                else\r\n                    let! ref =\r\n                        if useExternalStore then Code.tryLoad id\r\n                        else Code.tryLoadLocal id\r\n\r\n                    match ref with\r\n                        | Some r -> \r\n                            return r\r\n\r\n                        | _ ->\r\n                            let! sx = r.ReadPrimitive()\r\n                            let! sy = r.ReadPrimitive()\r\n\r\n                            let arr = Array2D.zeroCreate sx sy\r\n                            do! Code.storeLocal id arr\r\n\r\n                            for x in 0..sx-1 do\r\n                                for y in 0..sy-1 do\r\n                                    let! v = elementCoder.Read(r)\r\n                                    arr.[x,y] <- v\r\n\r\n                            return arr\r\n\r\n            }\r\n\r\n        override x.Write(w : IWriter, value : 'a[,]) =\r\n            code {\r\n                if isNull value then\r\n                    do! w.WritePrimitive Guid.Empty\r\n                else\r\n                    let! (isNew, id) = \r\n                        if useExternalStore then Code.tryStore value\r\n                        else Code.tryStoreLocal value\r\n\r\n                    do! w.WritePrimitive id\r\n                    if isNew then\r\n                        let sx = value.GetLength 0\r\n                        let sy = value.GetLength 1\r\n                        do! w.WritePrimitive sx\r\n                        do! w.WritePrimitive sy\r\n\r\n                        for x in 0..sx-1 do\r\n                            for y in 0..sy-1 do\r\n                                do! elementCoder.Write(w, value.[x,y])\r\n\r\n\r\n\r\n\r\n            }\r\n\r\n        new(resolve) = Array2dCoder(false, resolve)\r\n\r\n    type Array3dCoder<'a>(useExternalStore : bool, resolve : Type -> IValueCoder) =\r\n        inherit AbstractValueCoder<'a[,,]>()\r\n\r\n        let elementCoder = resolve typeof<'a> |> unbox<IValueCoder<'a>>\r\n\r\n        override x.Read(r : IReader) =\r\n            code {\r\n                let! id = r.ReadPrimitive()\r\n                if id = Guid.Empty then\r\n                    return null\r\n                else\r\n                    let! ref =\r\n                        if useExternalStore then Code.tryLoad id\r\n                        else Code.tryLoadLocal id\r\n\r\n                    match ref with\r\n                        | Some r -> \r\n                            return r\r\n\r\n                        | _ ->\r\n                            let! sx = r.ReadPrimitive()\r\n                            let! sy = r.ReadPrimitive()\r\n                            let! sz = r.ReadPrimitive()\r\n\r\n                            let arr = Array3D.zeroCreate sx sy sz\r\n                            do! Code.storeLocal id arr\r\n\r\n                            for x in 0..sx-1 do\r\n                                for y in 0..sy-1 do\r\n                                    for z in 0..sz-1 do\r\n                                        let! v = elementCoder.Read(r)\r\n                                        arr.[x,y,z] <- v\r\n\r\n                            return arr\r\n\r\n            }\r\n\r\n        override x.Write(w : IWriter, value : 'a[,,]) =\r\n            code {\r\n                if isNull value then\r\n                    do! w.WritePrimitive Guid.Empty\r\n                else\r\n                    let! (isNew, id) = \r\n                        if useExternalStore then Code.tryStore value\r\n                        else Code.tryStoreLocal value\r\n\r\n                    do! w.WritePrimitive id\r\n                    if isNew then\r\n                        let sx = value.GetLength 0\r\n                        let sy = value.GetLength 1\r\n                        let sz = value.GetLength 2\r\n                        do! w.WritePrimitive sx\r\n                        do! w.WritePrimitive sy\r\n                        do! w.WritePrimitive sz\r\n\r\n                        for x in 0..sx-1 do\r\n                            for y in 0..sy-1 do\r\n                                for z in 0..sz-1 do\r\n                                    do! elementCoder.Write(w, value.[x,y,z])\r\n\r\n\r\n\r\n\r\n            }\r\n\r\n        new(resolve) = Array3dCoder(false, resolve)\r\n\r\n\r\n\r\n\r\n    type DynamicCoder<'a when 'a : not struct and 'a : null>(resolve : Type -> IValueCoder) =\r\n        inherit AbstractValueCoder<'a>()\r\n\r\n        static let invariantTypes = ConcurrentDictionary<Type, Type>()\r\n\r\n        let resolveInvariant (t : Type) =\r\n            let t = invariantTypes.GetOrAdd(t, fun t -> t.MakeByRefType())\r\n            resolve t\r\n\r\n        let typeCoder = resolve typeof<Type> |> unbox<IValueCoder<Type>>\r\n\r\n        override x.CodesType = true\r\n\r\n        override x.Read(r) =\r\n            code {\r\n                let! t = typeCoder.Read r\r\n                if isNull t then\r\n                    return null\r\n                else\r\n                    let coder = resolveInvariant t\r\n                    return! coder.ReadUnsafe(r)\r\n            }\r\n\r\n        override x.Write(w, v) =\r\n            code {\r\n                if isNull v then\r\n                    do! typeCoder.Write(w, null)\r\n                else\r\n                    let t = v.GetType()\r\n                    do! typeCoder.Write(w, t)\r\n                    let coder = resolveInvariant t\r\n                    do! coder.WriteUnsafe(w, v)\r\n            }\r\n\r\n    type WithTypeCoder<'a>(inner : IValueCoder<'a>, resolve : Type -> IValueCoder) =\r\n        inherit AbstractValueCoder<'a>()\r\n\r\n        let typeCoder = resolve typeof<Type> |> unbox<IValueCoder<Type>>\r\n\r\n        override x.CodesType = true\r\n\r\n        override x.Write(w,v) =\r\n            code {\r\n                do! typeCoder.Write(w, typeof<'a>)\r\n                do! inner.Write(w, v)\r\n            }\r\n\r\n        override x.Read(r) =\r\n            code {\r\n                let! t = typeCoder.Read(r)\r\n                if typeof<'a>.IsAssignableFrom t then\r\n                    return! inner.Read(r)\r\n                else\r\n                    return failwithf \"cannot reinterpret %A as %A\" t typeof<'a>\r\n            }\r\n\r\n    type EnumCoder<'e, 'v when 'v : unmanaged>() =\r\n        inherit AbstractValueCoder<'e>()\r\n        let inner = PrimitiveCoder<'v>()\r\n\r\n        override x.Read(r) =\r\n            inner.Read(r) |> State.map unbox<'e>\r\n\r\n        override x.Write(w, v) =\r\n            inner.Write(w, unbox v)\r\n\r\n    let tryGetSpecialCoderType (t : Type) : Option<Type> =\r\n        match CustomCoders.tryGetCustomCoderType t with\r\n            | Some c -> Some c\r\n            | None -> FieldCoders.tryBuildFieldCoders t \r\n\r\n    let rec resolve (valueType : Type) : Type =\r\n        match tryGetSpecialCoderType valueType with\r\n            | Some coder -> coder\r\n            | _ ->\r\n\r\n                let isInvariant =\r\n                    valueType.IsValueType || \r\n                    valueType.IsSealed || \r\n                    valueType.IsByRef ||\r\n                    FSharpType.IsTuple valueType // TODO: is that a reasonable assumption??\r\n\r\n                let valueType =\r\n                    if valueType.IsByRef then valueType.GetElementType()\r\n                    else valueType\r\n\r\n                if valueType.IsBlittable then\r\n                    typedefof<PrimitiveCoder<int>>.MakeGenericType [|valueType|]\r\n\r\n                elif valueType.IsEnum then\r\n                    let realType = valueType.GetEnumUnderlyingType()\r\n                    typedefof<EnumCoder<_,int>>.MakeGenericType [|valueType; realType|]\r\n\r\n                elif valueType = typeof<string> then\r\n                    typeof<StringCoder>\r\n\r\n                elif valueType = typeof<bool> then\r\n                    typeof<BoolCoder>\r\n\r\n                elif typeof<Type>.IsAssignableFrom valueType then\r\n                    typeof<TypeCoder>\r\n\r\n                elif valueType.IsArray then\r\n                    let rank = valueType.GetArrayRank()\r\n                    let elementType = valueType.GetElementType()\r\n\r\n                    match rank with\r\n                        | 1 -> \r\n                            if elementType.IsBlittable then\r\n                                typedefof<PrimitiveArrayCoder<int>>.MakeGenericType [|elementType|]\r\n                            else\r\n                                typedefof<Array1dCoder<_>>.MakeGenericType [|elementType|]\r\n\r\n                        | 2 -> typedefof<Array2dCoder<_>>.MakeGenericType [|elementType|]\r\n                        | 3 -> typedefof<Array3dCoder<_>>.MakeGenericType [|elementType|]\r\n                        | _ -> failwithf \"[Coder] arrays of rank %d not supported atm.\" rank\r\n\r\n\r\n                else\r\n                    if isInvariant then\r\n                        AutoCoders.createFieldCoder valueType\r\n                    else\r\n                        typedefof<DynamicCoder<_>>.MakeGenericType [| valueType |]\r\n\r\n    and get (t : Type) =\r\n        coderTypeCache.GetOrAdd(t, resolve)\r\n\r\n\r\n\r\nmodule ValueCoder =\r\n    open ValueCoderTypes\r\n\r\n    \r\n\r\n    type private Resolver private() =\r\n        \r\n        static let resolveLambas =\r\n            typeof<Resolver>.GetMethods(BindingFlags.AnyStatic)\r\n                |> Array.filter (fun mi -> mi.Name = \"GetCoder\")\r\n                |> Array.map (fun mi -> \r\n                    let t = mi.GetParameters().[0].ParameterType\r\n\r\n                    let delType = System.Linq.Expressions.Expression.GetDelegateType [|t; typeof<IValueCoder>|]\r\n                    let del = Delegate.CreateDelegate(delType, mi)\r\n                    let lambda = DelegateAdapters.wrapUntyped del\r\n\r\n                    let funType = typedefof<FSharpFunc<_,_>>.MakeGenericType [| t; typeof<IValueCoder> |]\r\n\r\n                    funType, lambda \r\n                   )\r\n                |> Dictionary.ofArray\r\n\r\n        static let coderCache = ConcurrentDictionary<obj, IValueCoder>()\r\n\r\n        static let createInstance (coderType : Type) =\r\n            let ctors = \r\n                coderType.GetConstructors(BindingFlags.AnyInstance)\r\n                    |> Array.filter (fun c -> c.GetParameters().Length = 1)\r\n\r\n            let instance =\r\n                ctors |> Array.tryPick (fun ctor ->\r\n                    let arg = ctor.GetParameters().[0].ParameterType\r\n                    match resolveLambas.TryGetValue arg with\r\n                        | (true, arg) -> ctor.Invoke [|arg|] |> unbox<IValueCoder> |> Some\r\n                        | _ -> None\r\n                )\r\n\r\n            match instance with\r\n                | Some i -> i\r\n                | None ->\r\n                    let emptyCtor = coderType.GetConstructor(BindingFlags.AnyInstance, Type.DefaultBinder, [||], null)\r\n                    if isNull emptyCtor then failwithf \"[Resolver] cannot create coder of type: %A\" coderType\r\n                    else emptyCtor.Invoke [||] |> unbox<IValueCoder>\r\n\r\n\r\n\r\n        static member GetCoder (f : FieldInfo) : IValueCoder =\r\n            coderCache.GetOrAdd(f, fun _ ->\r\n                let typeCoder = Resolver.GetCoder(f.FieldType)\r\n\r\n                match typeCoder with\r\n                    | :? IReferenceCoder as r ->\r\n                        let useExternStore = false // TODO: real logic here\r\n                        if useExternStore then r.WithExternalStore\r\n                        else r.WithInternalStore\r\n                    | _ ->\r\n                        typeCoder\r\n            )\r\n\r\n        static member GetCoder (t : Type) : IValueCoder =\r\n            coderCache.GetOrAdd(t, fun _ ->\r\n                let coderType = get t\r\n                let coder = createInstance coderType\r\n                coder\r\n            )\r\n\r\n    let get (t : Type) = Resolver.GetCoder t\r\n    let getField (f : FieldInfo) = Resolver.GetCoder f\r\n\r\n    type private CoderGenericImpl<'a>() =\r\n        static let coder = Resolver.GetCoder typeof<'a> |> unbox<IValueCoder<'a>>\r\n\r\n        static let topLevelCoder =\r\n            match coder with\r\n                | :? AbstractValueCoder<'a> as c when c.CodesType -> \r\n                    coder\r\n                | _ ->\r\n                    WithTypeCoder<'a>(coder, Resolver.GetCoder) :> IValueCoder<'a>\r\n\r\n        static member Coder = coder\r\n        static member TopLevelCoder = topLevelCoder\r\n\r\n    let coder<'a> : IValueCoder<'a> = \r\n        CoderGenericImpl<'a>.Coder\r\n\r\n    let topLevelCoder<'a> : IValueCoder<'a> =\r\n        CoderGenericImpl<'a>.TopLevelCoder\r\n\r\n\r\n[<AbstractClass; Sealed; Extension>]\r\ntype ReaderWriterExtensions() =\r\n    static let emptyState =\r\n        {\r\n            Version         = Version(0,0,1)\r\n            MemberStack     = []\r\n            References      = RefMap.empty\r\n            Values          = Map.empty\r\n            Database        = Unchecked.defaultof<_>\r\n        }\r\n\r\n    [<Extension>]\r\n    static member Write(this : IWriter, value : 'a) =\r\n        let c = ValueCoder.topLevelCoder<'a>\r\n        let mutable s = emptyState\r\n        c.Write(this, value).Run(&s)\r\n\r\n    [<Extension>]\r\n    static member Read(this : IReader) : 'a =\r\n        let c = ValueCoder.topLevelCoder<'a>\r\n        let mutable s = emptyState\r\n        c.Read(this).Run(&s)\r\n\r\n\r\n\r\n    [<Extension>]\r\n    static member WriteState(this : IWriter, value : 'a) =\r\n        let c = ValueCoder.coder<'a>\r\n        c.Write(this, value)\r\n\r\n    [<Extension>]\r\n    static member ReadState(this : IReader) : Code<'a> =\r\n        let c = ValueCoder.coder<'a>\r\n        c.Read(this)\r\n\r\n\r\n\r\n"
  },
  {
    "path": "src/Aardvark.Base.Runtime/paket.references",
    "content": "FSharp.Core\nAardvark.Build\nFsPickler\nAardvark.Base.TypeProviders\nFSharp.Data.Adaptive"
  },
  {
    "path": "src/Aardvark.Base.Runtime/paket.template",
    "content": "type project\nid Aardvark.Base.Runtime\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/Aardvark.Base.Telemetry.csproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <TargetFramework>netstandard2.0</TargetFramework>\r\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n    <NoWarn>1701;1702;1705;1591</NoWarn>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/Debug.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Dynamic;\n\nnamespace Aardvark.Base\n{\n    public static partial class Telemetry\n    {\n        public static class Debug\n        {\n            private static readonly List<Action<string, IProbe>> s_registrationActions = new List<Action<string, IProbe>>();\n\n            /// <summary>\n            /// e.g.: using (Telemetry.Debug.CpuTimers.YourTimerNameHere) { /* stuff to time */ }\n            /// </summary>\n            public static readonly dynamic CpuTimers = new DynamicCpuTimeProvider();\n\n            /// <summary>\n            /// e.g.: Telemetry.Debug.Counters.YourCounterNameHere.Increment();\n            /// </summary>\n            public static readonly dynamic Counters = new DynamicCounterProvider();\n            \n            /// <summary>\n            /// Use this to register a custom action that will be called each time\n            /// someone creates a dynamic CpuTimer (with Telemetry.Debug.CpuTimers.YourTimerNameHere).\n            /// The parameters are the user-provided name (e.g. \"YourTimerNameHere\" in the\n            /// above example and the created CpuTimer. E.g. the kernel registers an action\n            /// that for each timer automatically creates a derived probe showing the values\n            /// per cycle.\n            /// </summary>\n            public static void AddCustomRegistrationAction(Action<string, IProbe> action)\n            {\n                if (action is null) throw new ArgumentNullException(nameof(action));\n                s_registrationActions.Add(action);\n            }\n\n            static Debug() => AddCustomRegistrationAction(\n                (name, probe) => Register(name + \"/s\", probe.RatePerSecond())\n                );\n\n            private class DynamicCpuTimeProvider : DynamicObject\n            {\n                private readonly Dictionary<string, CpuTime> m_probes = new Dictionary<string, CpuTime>();\n\n                public override IEnumerable<string> GetDynamicMemberNames() => m_probes.Keys;\n\n                public override bool TryGetMember(GetMemberBinder binder, out object result)\n                {\n                    if (m_probes.TryGetValue(binder.Name, out CpuTime x))\n                    {\n                        result = x.Timer;\n                    }\n                    else\n                    {\n                        x = new CpuTime();\n                        m_probes[binder.Name] = x;\n                        Register(binder.Name, x);\n                        s_registrationActions.ForEach(a => a(binder.Name, x));\n                        result = x.Timer;\n                    }\n\n                    return true;\n                }\n            }\n\n            private class DynamicCounterProvider : DynamicObject\n            {\n                private readonly Dictionary<string, Counter> m_probes = new Dictionary<string, Counter>();\n\n                public override IEnumerable<string> GetDynamicMemberNames() => m_probes.Keys;\n\n                public override bool TryGetMember(GetMemberBinder binder, out object result)\n                {\n                    if (m_probes.TryGetValue(binder.Name, out Counter x))\n                    {\n                        result = x;\n                    }\n                    else\n                    {\n                        x = new Counter();\n                        m_probes[binder.Name] = x;\n                        Register(binder.Name, x);\n                        s_registrationActions.ForEach(a => a(binder.Name, x));\n                        result = x;\n                    }\n\n                    return true;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/Environment.cs",
    "content": "﻿using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Dynamic;\n\nnamespace Aardvark.Base\n{\n    public static partial class Telemetry\n    {\n        public class Env : DynamicObject, IEnumerable<NamedProbe>\n        {\n            private readonly Dictionary<string, NamedProbe> m_probes =\n                new Dictionary<string, NamedProbe>();\n\n            public void SetMember(string name, IProbe probe)\n            {\n                if (probe == null) throw new ArgumentNullException();\n                m_probes[name] = new NamedProbe(name, probe);\n            }\n\n            public IProbe GetMember(string name)\n                => m_probes.TryGetValue(name, out NamedProbe x) ? x.Probe : null;\n\n            public override IEnumerable<string> GetDynamicMemberNames() => m_probes.Keys;\n\n            public override bool TryGetMember(GetMemberBinder binder, out object result)\n            {\n                result = GetMember(binder.Name);\n                return result != null;\n            }\n\n            public override bool TrySetMember(SetMemberBinder binder, object value)\n            {\n                var probe = value as IProbe;\n                if (probe == null) throw new ArgumentException();\n                SetMember(binder.Name, probe);\n                return true;\n            }\n\n            public IEnumerator<NamedProbe> GetEnumerator()\n                => ((IEnumerable<NamedProbe>)m_probes.Values).GetEnumerator();\n\n            IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/HardwareThread.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing System.Threading;\n\nnamespace Aardvark.Base\n{\n    public static class HardwareThread\n    {\n        private static readonly Dictionary<int, ProcessThread> s_pts = new Dictionary<int, ProcessThread>();\n        private static SpinLock s_ptsLock = new SpinLock();\n\n        public static ProcessThread GetProcessThread(int tid)\n        {\n            ProcessThread result = null;\n\n            bool lockTaken = false;\n            try\n            {\n                s_ptsLock.Enter(ref lockTaken);\n                if (s_pts.TryGetValue(tid, out result)) return result;\n            }\n            finally\n            {\n                if (lockTaken) s_ptsLock.Exit();\n            }\n\n            foreach (ProcessThread t in Process.GetCurrentProcess().Threads)\n            {\n                if (t.Id == tid)\n                {\n                    lockTaken = false;\n                    try\n                    {\n                        s_ptsLock.Enter(ref lockTaken);\n                        s_pts[tid] = t;\n                    }\n                    finally\n                    {\n                        if (lockTaken) s_ptsLock.Exit();\n                    }\n                    return t;\n                }\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/IProbe.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public static partial class Telemetry\n    {\n        public interface IProbe\n        {\n            /// <summary>\n            /// Current value of probe.\n            /// </summary>\n            double ValueDouble { get; }\n        }\n\n        public interface IProbe<T> : IProbe\n        {\n            /// <summary>\n            /// Current typed value of probe.\n            /// </summary>\n            T Value { get; }\n        }\n\n        public class NamedProbe\n        {\n            public readonly string Name;\n            public readonly IProbe Probe;\n\n            public NamedProbe(string name, IProbe probe)\n            {\n                if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException();\n\n                Name = name;\n                Probe = probe ?? throw new ArgumentNullException();\n            }\n        }\n\n        /// <summary>\n        /// Global reset of all telemetry probes to zero (or the equivalent).\n        /// This is mainly used for benchmarking, e.g. to cleanly restart telemetry\n        /// after a warm up phase or before a new benchmark iteration.\n        /// Custom IProbe implementations must handle the Telemetry.OnReset event.\n        /// </summary>\n        public static void ResetTelemetrySystem() => OnReset?.Invoke(null, EventArgs.Empty);\n\n        /// <summary>\n        /// Signals that ResetTelemetrySystem has been called.\n        /// Custom IProbe implementations must handle the Telemetry.OnReset event.\n        /// </summary>\n        public static event EventHandler OnReset;\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/Probes.cs",
    "content": "﻿#pragma warning disable 618\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Threading;\n\nnamespace Aardvark.Base\n{\n    public static partial class Telemetry\n    {\n        #region Counters\n\n        public class Counter : IProbe<long>\n        {\n            private long m_value = 0;\n\n            public Counter() => OnReset += (s, e) => Interlocked.Exchange(ref m_value, 0);\n\n            public void Increment() => Interlocked.Increment(ref m_value);\n\n            public void Increment(long x) => Interlocked.Add(ref m_value, x);\n\n            public void Decrement() => Interlocked.Decrement(ref m_value);\n\n            public void Decrement(long x) => Interlocked.Add(ref m_value, -x);\n\n            public void Set(long x) => m_value = x;\n            \n            public long Value => m_value;\n\n            public double ValueDouble => m_value;\n        }\n\n        #endregion\n\n        #region Timers\n\n        /// <summary>\n        /// Uses a StopWatch to time the code block.\n        /// Measurement also includes times when the thread is blocked.\n        /// </summary>\n        public class StopWatchTime : IProbe<TimeSpan>\n        {\n            private long m_sum = 0;\n\n            public StopWatchTime() => OnReset += (s, e) => Interlocked.Exchange(ref m_sum, 0);\n\n            public StopWatchTimeTimer Timer => new StopWatchTimeTimer(this, Stopwatch.StartNew());\n\n            public struct StopWatchTimeTimer : IDisposable\n            {\n                StopWatchTime Source;\n                readonly Stopwatch Watch;\n\n                internal StopWatchTimeTimer(StopWatchTime source, Stopwatch watch) { Source = source; Watch = watch; }\n                public void Dispose()\n                {\n                    if (Source == null) return;\n                    Interlocked.Add(ref Source.m_sum, Watch.Elapsed.Ticks);\n                    Source = null;\n                }\n            }\n\n            public TimeSpan Value => TimeSpan.FromTicks(m_sum);\n\n            public double ValueDouble => Value.TotalSeconds;\n        }\n\n        /// <summary>\n        /// Overlapping timings from multiple threads will not be accumulated.\n        /// For example, if 4 threads simultanously time a code block at 1 second\n        /// using the same WallClockTime object, then recorded time will show 1 second.\n        /// This is in contrast to CpuTime where it would show 4 seconds.\n        /// </summary>\n        public class WallClockTime : IProbe<TimeSpan>\n        {\n            private int m_actives = 0;\n            private readonly Stopwatch m_stopwatch = new Stopwatch();\n\n            public WallClockTime() => OnReset += (s, e) => m_stopwatch.Reset();\n            \n            public WallClockTimer Timer\n            {\n                get\n                {\n                    if (Interlocked.Increment(ref m_actives) == 1)\n                        m_stopwatch.Start();\n\n                    return new WallClockTimer(this);\n                }\n            }\n\n            public struct WallClockTimer : IDisposable\n            {\n                WallClockTime Source;\n                internal WallClockTimer(WallClockTime source) { Source = source; }\n                public void Dispose()\n                {\n                    var source = Source;\n                    if (source == null) return;\n\n                    Source = null;\n\n                    if (Interlocked.Decrement(ref source.m_actives) == 0)\n                    {\n                        source.m_stopwatch.Stop();\n                    }\n                }\n            }\n\n            public TimeSpan Value => m_stopwatch.Elapsed;\n\n            public double ValueDouble => Value.TotalSeconds;\n        }\n\n        /// <summary>\n        /// Measures the amount of time that the thread has spent using\n        /// the processor (application code + operating system code).\n        /// </summary>\n        public class CpuTime : IProbe<TimeSpan>\n        {\n            private ProcessThread GetCurrentProcessThread()\n            {\n                Thread.BeginThreadAffinity();\n                try\n                {\n                    var tid = AppDomain.GetCurrentThreadId();\n                    if (m_threadLocalWin32ThreadId.Value != tid || m_threadLocalProcessThread.Value == null)\n                    {\n                        m_threadLocalWin32ThreadId.Value = tid;\n                        m_threadLocalProcessThread.Value = HardwareThread.GetProcessThread(tid);\n                    }\n                    return m_threadLocalProcessThread.Value;\n                }\n                finally\n                {\n                    Thread.EndThreadAffinity();\n                }\n            }\n            \n            private readonly ThreadLocal<int> m_threadLocalWin32ThreadId = new ThreadLocal<int>(() => -1);\n            private readonly ThreadLocal<ProcessThread> m_threadLocalProcessThread = new ThreadLocal<ProcessThread>();\n            \n            private readonly ThreadLocal<bool> m_active = new ThreadLocal<bool>(() => false);\n\n            private long m_sum = 0;\n\n            private bool m_measureUserTime = false;\n            private long m_sumUser = 0;\n            private IProbe<TimeSpan> m_probeUser = null;\n\n            private bool m_measurePrivilegedTime = false;\n            private long m_sumPrivileged = 0;\n            private IProbe<TimeSpan> m_probePrivileged = null;\n\n            public CpuTime() => OnReset += (s, e) =>\n            {\n                Interlocked.Exchange(ref m_sum, 0);\n                Interlocked.Exchange(ref m_sumUser, 0);\n                Interlocked.Exchange(ref m_sumPrivileged, 0);\n            };\n\n            public CpuTimeTimer Timer\n            {\n                get\n                {\n                    if (m_active.Value) throw new InvalidOperationException(\n                        \"Telemetry.StopWatchTime: nested start on same thread.\");\n\n                    long t0User = 0, t0Privileged = 0;\n                    \n                    var pt = GetCurrentProcessThread();\n                    if (pt == null) return new CpuTimeTimer();\n                    var t0 = pt.TotalProcessorTime.Ticks;\n                    if (m_measureUserTime) t0User = pt.UserProcessorTime.Ticks;\n                    if (m_measurePrivilegedTime) t0Privileged = pt.PrivilegedProcessorTime.Ticks;\n\n                    m_active.Value = true;\n\n                    return new CpuTimeTimer(this, t0, t0User, t0Privileged);\n                }\n            }\n\n            public struct CpuTimeTimer : IDisposable\n            {\n                CpuTime Source;\n                readonly long T0, T0User, T0Privileged;\n\n                internal CpuTimeTimer(CpuTime source, long t0, long t0user, long t0priv) { Source = source; T0 = t0; T0User = t0user; T0Privileged = t0priv; }\n                \n                public void Dispose()\n                {\n                    var source = Source;\n                    if (source == null) return;\n\n                    try\n                    {\n                        var pt = source.GetCurrentProcessThread();\n                        if (pt != null)\n                        {\n                            Interlocked.Add(ref source.m_sum, pt.TotalProcessorTime.Ticks - T0);\n                            if (source.m_measureUserTime) Interlocked.Add(ref source.m_sumUser, pt.UserProcessorTime.Ticks - T0User);\n                            if (source.m_measurePrivilegedTime) Interlocked.Add(ref source.m_sumPrivileged, pt.PrivilegedProcessorTime.Ticks - T0Privileged);\n                        }\n                    }\n                    finally\n                    {\n                        source.m_active.Value = false;\n                        Source = null;\n                    }\n                }\n            }\n\n            /// <summary>\n            /// Gets the time that was spent in application code.\n            /// </summary>\n            public IProbe<TimeSpan> UserTime\n            {\n                get\n                {\n                    if (!m_measureUserTime)\n                    {\n                        m_measureUserTime = true;\n                        m_probeUser = new CustomProbeTimeSpan(() => TimeSpan.FromTicks(m_sumUser));\n                    }\n                    return m_probeUser;\n                }\n            }\n\n            /// <summary>\n            /// Gets the time that was spent in operating system code.\n            /// </summary>\n            public IProbe<TimeSpan> PrivilegedTime\n            {\n                get\n                {\n                    if (!m_measurePrivilegedTime)\n                    {\n                        m_measurePrivilegedTime = true;\n                        m_probePrivileged = new CustomProbeTimeSpan(() => TimeSpan.FromTicks(m_sumPrivileged));\n                    }\n                    return m_probePrivileged;\n                }\n            }\n\n            public TimeSpan Value => TimeSpan.FromTicks(m_sum);\n\n            public double ValueDouble => Value.TotalSeconds;\n        }\n\n        /// <summary>\n        /// Measures the amount of time that the thread has spent using\n        /// the processor inside the application.\n        /// </summary>\n        public class CpuTimeUser : IProbe<TimeSpan>\n        {\n            private ProcessThread GetCurrentProcessThread()\n            {\n                Thread.BeginThreadAffinity();\n                try\n                {\n                    var tid = AppDomain.GetCurrentThreadId();\n                    if (m_threadLocalWin32ThreadId.Value != tid || m_threadLocalProcessThread.Value == null)\n                    {\n                        m_threadLocalWin32ThreadId.Value = tid;\n                        m_threadLocalProcessThread.Value = HardwareThread.GetProcessThread(tid);\n                    }\n                    return m_threadLocalProcessThread.Value;\n                }\n                finally\n                {\n                    Thread.EndThreadAffinity();\n                }\n            }\n\n            private readonly ThreadLocal<int> m_threadLocalWin32ThreadId = new ThreadLocal<int>(() => -1);\n            private readonly ThreadLocal<ProcessThread> m_threadLocalProcessThread = new ThreadLocal<ProcessThread>();\n\n            private readonly HashSet<int> m_threadIds = new HashSet<int>();\n            private TimeSpan m_sum = TimeSpan.Zero;\n\n            public CpuTimeUser() => OnReset += (s, e) => { lock (m_threadIds) m_sum = TimeSpan.Zero; };\n            \n            public CpuTimeUserTimer Timer\n            {\n                get\n                {\n                    int threadId = Thread.CurrentThread.ManagedThreadId;\n                    lock (m_threadIds)\n                    {\n                        if (m_threadIds.Contains(threadId))\n                        {\n                            throw new InvalidOperationException(\n                                \"Telemetry.CpuTime: nested start on same thread.\"\n                                );\n                        }\n                        else\n                        {\n                            var p = GetCurrentProcessThread();\n                            if (p == null) return new CpuTimeUserTimer();\n                            var t0 = p.UserProcessorTime;\n                            m_threadIds.Add(threadId);\n                            return new CpuTimeUserTimer(this, t0, threadId);\n                        }\n                    }\n                }\n            }\n\n            public struct CpuTimeUserTimer : IDisposable\n            {\n                CpuTimeUser Source;\n                TimeSpan T0;\n                readonly int ThreadId;\n                \n                internal CpuTimeUserTimer(CpuTimeUser source, TimeSpan t0, int threadId) { Source = source; T0 = t0; ThreadId = threadId; }\n\n                public void Dispose()\n                {\n                    var source = Source;\n                    if (source == null) return;\n\n                    try\n                    {\n                        var p2 = source.GetCurrentProcessThread();\n                        lock (source.m_threadIds)\n                        {\n                            if (p2 != null)\n                            {\n                                var t1 = p2.UserProcessorTime;\n                                source.m_sum += t1 - T0;\n                            }\n                            source.m_threadIds.Remove(ThreadId);\n                        }\n                    }\n                    finally\n                    {\n                        Source = null;\n                    }\n                }\n            }\n\n            public TimeSpan Value\n            {\n                get\n                {\n                    lock (m_threadIds) return m_sum;\n                }\n            }\n\n            public double ValueDouble => Value.TotalSeconds;\n        }\n\n        /// <summary>\n        /// Measures the amount of time that the thread has spent using\n        /// the processor inside the operating system core.\n        /// </summary>\n        public class CpuTimePrivileged : IProbe<TimeSpan>\n        {\n            private ProcessThread GetCurrentProcessThread()\n            {\n                Thread.BeginThreadAffinity();\n                try\n                {\n                    var tid = AppDomain.GetCurrentThreadId();\n                    if (m_threadLocalWin32ThreadId.Value != tid || m_threadLocalProcessThread.Value == null)\n                    {\n                        m_threadLocalWin32ThreadId.Value = tid;\n                        m_threadLocalProcessThread.Value = HardwareThread.GetProcessThread(tid);\n                    }\n                    return m_threadLocalProcessThread.Value;\n                }\n                finally\n                {\n                    Thread.EndThreadAffinity();\n                }\n            }\n            private readonly ThreadLocal<int> m_threadLocalWin32ThreadId = new ThreadLocal<int>(() => -1);\n            private readonly ThreadLocal<ProcessThread> m_threadLocalProcessThread = new ThreadLocal<ProcessThread>();\n\n            private readonly HashSet<int> m_threadIds = new HashSet<int>();\n            private TimeSpan m_sum = TimeSpan.Zero;\n\n            public CpuTimePrivileged()\n            {\n                OnReset += (s, e) => { lock (m_threadIds) m_sum = TimeSpan.Zero; };\n            }\n\n            public CpuTimePrivilegedTimer Timer\n            {\n                get\n                {\n                    int threadId = Thread.CurrentThread.ManagedThreadId;\n                    lock (m_threadIds)\n                    {\n                        if (m_threadIds.Contains(threadId))\n                        {\n                            throw new InvalidOperationException(\n                                \"Telemetry.CpuTime: nested start on same thread.\"\n                                );\n                        }\n                        else\n                        {\n                            // /* var tid = */ HardwareThread.GetCurrentWin32ThreadId(); sm?\n                            var p = GetCurrentProcessThread();\n                            if (p == null) return new CpuTimePrivilegedTimer();\n                            var t0 = p.PrivilegedProcessorTime;\n                            m_threadIds.Add(threadId);\n                            return new CpuTimePrivilegedTimer(this, t0, threadId);\n                        }\n                    }\n                }\n            }\n\n            public struct CpuTimePrivilegedTimer : IDisposable\n            {\n                CpuTimePrivileged Source;\n                TimeSpan T0;\n                readonly int ThreadId;\n\n                internal CpuTimePrivilegedTimer(CpuTimePrivileged source, TimeSpan t0, int threadId) { Source = source; T0 = t0; ThreadId = threadId; }\n\n                public void Dispose()\n                {\n                    var source = Source;\n                    if (source == null) return;\n\n                    try\n                    {\n                        var p2 = source.GetCurrentProcessThread();\n                        lock (source.m_threadIds)\n                        {\n                            if (p2 != null)\n                            {\n                                var t1 = p2.PrivilegedProcessorTime;\n                                source.m_sum += t1 - T0;\n                            }\n                            source.m_threadIds.Remove(ThreadId);\n                        }\n                    }\n                    finally\n                    {\n                        Source = null;\n                    }\n                }\n            }\n\n            public TimeSpan Value\n            {\n                get\n                {\n                    lock (m_threadIds) return m_sum;\n                }\n            }\n            public double ValueDouble => Value.TotalSeconds;\n        }\n\n        #endregion\n\n        #region Custom probes\n\n        public class CustomProbeDouble : IProbe<double>\n        {\n            private readonly Func<double> m_value;\n\n            public CustomProbeDouble(Func<double> valueFunc) => m_value = valueFunc;\n\n            public double Value => m_value();\n            \n            public double ValueDouble => m_value();\n        }\n\n        public class CustomProbeLong : IProbe<long>\n        {\n            private readonly Func<long> m_value;\n\n            public CustomProbeLong(Func<long> valueFunc) => m_value = valueFunc;\n\n            public long Value => m_value();\n\n            public double ValueDouble => m_value();\n        }\n\n        public class CustomProbeTimeSpan : IProbe<TimeSpan>\n        {\n            private Func<TimeSpan> m_value;\n\n            public CustomProbeTimeSpan(Func<TimeSpan> valueFunc) => m_value = valueFunc;\n\n            public TimeSpan Value => m_value();\n\n            public Func<TimeSpan> Getter { set { m_value = value; } }\n\n            public double ValueDouble => m_value().TotalSeconds;\n        }\n\n        public class CustomProbeString : IProbe<string>\n        {\n            private readonly Func<string> m_value;\n\n            public CustomProbeString(Func<string> valueFunc) => m_value = valueFunc;\n\n            public string Value => m_value();\n\n            public double ValueDouble => 0.0;\n        }\n\n        #endregion\n\n        #region Snapshot probes\n\n        /// <summary>\n        /// Reports difference to current value of probe.\n        /// </summary>\n        public class SnapshotProbeLong : IProbe<long>\n        {\n            private readonly IProbe<long> m_probe;\n            private long m_base;\n\n            /// <summary>\n            /// Reports difference to current value of probe.\n            /// </summary>\n            public SnapshotProbeLong(IProbe<long> probe)\n            {\n                m_probe = probe ?? throw new ArgumentNullException();\n                m_base = -probe.Value;\n                OnReset += (s, e) => m_base = 0;\n            }\n\n            public long Value => m_base + m_probe.Value;\n\n            public double ValueDouble => m_base + m_probe.Value;\n        }\n\n        /// <summary>\n        /// Reports difference to current value of probe.\n        /// </summary>\n        public class SnapshotProbeDouble : IProbe<double>\n        {\n            private readonly IProbe<double> m_probe;\n            private double m_base;\n\n            /// <summary>\n            /// Reports difference to current value of probe.\n            /// </summary>\n            public SnapshotProbeDouble(IProbe<double> probe)\n            {\n                m_probe = probe ?? throw new ArgumentNullException();\n                m_base = -probe.Value;\n                OnReset += (s, e) => m_base = 0;\n            }\n\n            public double Value => m_base + m_probe.Value;\n\n            public double ValueDouble => m_base + m_probe.Value;\n        }\n\n        /// <summary>\n        /// Reports difference to current value of probe.\n        /// </summary>\n        public class SnapshotProbeTimeSpan : IProbe<TimeSpan>\n        {\n            private readonly IProbe<TimeSpan> m_probe;\n            private long m_base;\n\n            /// <summary>\n            /// Reports difference to current value of probe.\n            /// </summary>\n            public SnapshotProbeTimeSpan(IProbe<TimeSpan> probe)\n            {\n                m_probe = probe ?? throw new ArgumentNullException();\n                m_base = -probe.Value.Ticks;\n                OnReset += (s, e) => m_base = 0;\n            }\n\n            public TimeSpan Value => TimeSpan.FromTicks(m_base + m_probe.Value.Ticks);\n\n            public double ValueDouble => Value.TotalSeconds;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/Registry.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    public static partial class Telemetry\n    {\n        private static readonly Dictionary<string, IProbe> s_namedProbes\n            = new Dictionary<string, IProbe>();\n        private static readonly Dictionary<string, Func<IEnumerable<TimingStats>>> s_providersForTimingStats\n            = new Dictionary<string, Func<IEnumerable<TimingStats>>>();\n\n        public static Tuple<string, IProbe>[] NamedProbes\n        {\n            get\n            {\n                lock (s_namedProbes)\n                {\n                    return s_namedProbes\n                        .Select(x => Tuple.Create(x.Key, x.Value))\n                        .ToArray()\n                        ;\n                }\n            }\n        }\n        \n        public static IProbe GetNamedProbe(string name)\n        {\n            lock (s_namedProbes)\n            {\n                return s_namedProbes.ContainsKey(name) ? s_namedProbes[name] : null;\n            }\n        }\n        \n        private class Disposable : IDisposable\n        {\n            private Action m_disposeAction;\n            public static IDisposable Create(Action disposeAction) { return new Disposable() { m_disposeAction = disposeAction }; }\n            public void Dispose() { m_disposeAction(); }\n        }\n        \n        public static IDisposable Register(string name, IProbe probe)\n        {\n            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));\n            if (probe is null) throw new ArgumentNullException(nameof(probe));\n\n            lock (s_namedProbes)\n                s_namedProbes[name] = probe;\n\n            return Disposable.Create(\n                () => { lock (s_namedProbes) s_namedProbes.Remove(name); }\n                );\n        }\n\n        public static void Register(string name, Func<IEnumerable<TimingStats>> provider)\n        {\n            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));\n            if (provider is null) throw new ArgumentNullException(nameof(provider));\n\n            lock (s_providersForTimingStats)\n                s_providersForTimingStats[name] = provider;\n        }\n        \n        public static Tuple<string, Func<IEnumerable<TimingStats>>>[] ProvidersForTimingStats\n        {\n            get\n            {\n                lock (s_providersForTimingStats)\n                {\n                    return s_providersForTimingStats\n                        .Select(x => Tuple.Create(x.Key, x.Value))\n                        .ToArray()\n                        ;\n                }\n            }\n        }\n        \n        public static Func<IEnumerable<TimingStats>> GetProviderForTimingStats(string name)\n        {\n            lock (s_providersForTimingStats)\n            {\n                return s_providersForTimingStats.ContainsKey(name)\n                    ? s_providersForTimingStats[name] : null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/TelemetryExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    public static class TelemetryExtensions\n    {\n        public static Telemetry.RatePerSecondView RatePerSecond(this Telemetry.IProbe self)\n            => new Telemetry.RatePerSecondView(self);\n\n        public static Telemetry.UtilizationView Utilization(this Telemetry.IProbe<TimeSpan> self)\n            => new Telemetry.UtilizationView(self);\n\n        public static Telemetry.RatioView Per(this Telemetry.IProbe self, Telemetry.IProbe denominator)\n            => new Telemetry.RatioView(self, denominator);\n\n        public static Telemetry.RatioView Per(this Telemetry.IProbe self, double denominator)\n            => new Telemetry.RatioView(self, denominator);\n        \n        public static Telemetry.SumView Sum(this Telemetry.IProbe self, params Telemetry.IProbe[] others)\n            => new Telemetry.SumView(self, others);\n\n        public static Telemetry.SumView Sum(this Telemetry.IProbe self, IEnumerable<Telemetry.IProbe> others)\n            => new Telemetry.SumView(self, others.ToArray());\n\n        public static Telemetry.SumView Sum(this Telemetry.IProbe self, Telemetry.IProbe value)\n            => new Telemetry.SumView(self, value);\n\n        public static Telemetry.SumView Sum(this Telemetry.IProbe self, double value)\n            => new Telemetry.SumView(self, value);\n\n        public static Telemetry.SumView Sum(this Telemetry.IProbe self, params double[] values)\n            => new Telemetry.SumView(self, values);\n                \n        public static Telemetry.SumView Add(this Telemetry.IProbe self, params Telemetry.IProbe[] others)\n            => new Telemetry.SumView(self, others);\n\n        public static Telemetry.SumView Add(this Telemetry.IProbe self, IEnumerable<Telemetry.IProbe> others)\n            => new Telemetry.SumView(self, others.ToArray());\n\n        public static Telemetry.SumView Add(this Telemetry.IProbe self, Telemetry.IProbe value)\n            => new Telemetry.SumView(self, value);\n\n        public static Telemetry.SumView Add(this Telemetry.IProbe self, double value)\n            => new Telemetry.SumView(self, value);\n\n        public static Telemetry.SumView Add(this Telemetry.IProbe self, params double[] values)\n            => new Telemetry.SumView(self, values);\n                \n        public static Telemetry.SubtractView Subtract(this Telemetry.IProbe self, params Telemetry.IProbe[] others)\n            => new Telemetry.SubtractView(self, others);\n\n        public static Telemetry.SubtractView Subtract(this Telemetry.IProbe self, IEnumerable<Telemetry.IProbe> others)\n            => new Telemetry.SubtractView(self, others.ToArray());\n\n        public static Telemetry.SubtractView Subtract(this Telemetry.IProbe self, Telemetry.IProbe value)\n            => new Telemetry.SubtractView(self, value);\n\n        public static Telemetry.SubtractView Subtract(this Telemetry.IProbe self, double value)\n            => new Telemetry.SubtractView(self, value);\n\n        public static Telemetry.SubtractView Subtract(this Telemetry.IProbe self, params double[] values)\n            => new Telemetry.SubtractView(self, values);\n        \n        public static Telemetry.MultiplyView Multiply(this Telemetry.IProbe self, Telemetry.IProbe value)\n            => new Telemetry.MultiplyView(self, value);\n\n        public static Telemetry.MultiplyView Multiply(this Telemetry.IProbe self, double value)\n            => new Telemetry.MultiplyView(self, value);\n                \n        public static Telemetry.MinView Min(this Telemetry.IProbe self, params Telemetry.IProbe[] others)\n            => new Telemetry.MinView(self, others);\n\n        public static Telemetry.MinView Min(this Telemetry.IProbe self, IEnumerable<Telemetry.IProbe> others)\n            => new Telemetry.MinView(self, others.ToArray());\n\n        public static Telemetry.MinView Min(this Telemetry.IProbe self, Telemetry.IProbe value)\n            => new Telemetry.MinView(self, value);\n\n        public static Telemetry.MinView Min(this Telemetry.IProbe self, double value)\n            => new Telemetry.MinView(self, value);\n\n        public static Telemetry.MinView Min(this Telemetry.IProbe self, params double[] values)\n            => new Telemetry.MinView(self, values);\n        \n        public static Telemetry.MaxView Max(this Telemetry.IProbe self, params Telemetry.IProbe[] others)\n            => new Telemetry.MaxView(self, others);\n\n        public static Telemetry.MaxView Max(this Telemetry.IProbe self, IEnumerable<Telemetry.IProbe> others)\n            => new Telemetry.MaxView(self, others.ToArray());\n\n        public static Telemetry.MaxView Max(this Telemetry.IProbe self, Telemetry.IProbe value)\n            => new Telemetry.MaxView(self, value);\n\n        public static Telemetry.MaxView Max(this Telemetry.IProbe self, double value)\n            => new Telemetry.MaxView(self, value);\n\n        public static Telemetry.MaxView Max(this Telemetry.IProbe self, params double[] values)\n            => new Telemetry.MaxView(self, values);\n        \n        public static Telemetry.AvgView Avg(this Telemetry.IProbe self, params Telemetry.IProbe[] others)\n            => new Telemetry.AvgView(self, others);\n\n        public static Telemetry.AvgView Avg(this Telemetry.IProbe self, IEnumerable<Telemetry.IProbe> others)\n            => new Telemetry.AvgView(self, others.ToArray());\n\n        public static Telemetry.AvgView Avg(this Telemetry.IProbe self, Telemetry.IProbe value)\n            => new Telemetry.AvgView(self, value);\n\n        public static Telemetry.AvgView Avg(this Telemetry.IProbe self, double value)\n            => new Telemetry.AvgView(self, value);\n\n        public static Telemetry.AvgView Avg(this Telemetry.IProbe self, params double[] values)\n            => new Telemetry.AvgView(self, values);\n        \n        public static Telemetry.IProbe<T> Snapshot<T>(this Telemetry.IProbe<T> probe)\n        {\n            if (typeof(T) == typeof(long)) return (Telemetry.IProbe<T>)\n                new Telemetry.SnapshotProbeLong((Telemetry.IProbe<long>)probe);\n\n            if (typeof(T) == typeof(double)) return (Telemetry.IProbe<T>)\n                new Telemetry.SnapshotProbeDouble((Telemetry.IProbe<double>)probe);\n\n            if (typeof(T) == typeof(TimeSpan)) return (Telemetry.IProbe<T>)\n                new Telemetry.SnapshotProbeTimeSpan((Telemetry.IProbe<TimeSpan>)probe);\n\n            throw new NotImplementedException(string.Format(\n                \"Telemetry.IProbe<{0}>.Snapshot() not implemented.\", typeof(T).Name\n                ));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/TimingStats.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public static partial class Telemetry\n    {\n        public class TimingStats\n        {\n            public Type Type { get; }\n            public long Count { get; private set; }\n            public TimeSpan Current { get; private set; }\n            public TimeSpan Total { get; private set; }\n            public TimeSpan Min { get; private set; } = TimeSpan.MaxValue;\n            public TimeSpan Max { get; private set; } = TimeSpan.MinValue;\n            public TimeSpan Avg { get; private set; }\n\n            public TimingStats(Type type)\n            {\n                if (type is null) throw new ArgumentNullException(nameof(type));\n                Type = type;\n            }\n\n            public void AddSample(TimeSpan x)\n            {\n                if (x < Min) Min = x;\n                if (x > Max) Max = x;\n                Count++;\n                Current = x;\n                Total += x;\n                double w = 1.0 / Count;\n                double a = Avg.Ticks * (1.0 - w);\n                double b = x.Ticks * w;\n                Avg = TimeSpan.FromTicks((long)(a + b));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/Views.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    public static partial class Telemetry\n    {\n        public class UtilizationView : IProbe<double>\n        {\n            private readonly Stopwatch m_stopwatch = new Stopwatch();\n            private readonly Func<TimeSpan> m_baseValue;\n\n            private UtilizationView(Func<TimeSpan> baseValue)\n            {\n                m_baseValue = baseValue;\n                m_stopwatch.Start();\n\n                OnReset += (s, e) =>\n                {\n                    m_stopwatch.Restart();\n                };\n            }\n\n            public UtilizationView(IProbe<TimeSpan> time)\n                : this(() => time.Value)\n            {\n            }\n\n            public double Value => m_baseValue().Ticks / m_stopwatch.Elapsed.Ticks;\n\n            public double ValueDouble => Value;\n        }\n\n        public class RatePerSecondView : IProbe<double>\n        {\n            private readonly IProbe m_counter;\n            private readonly Stopwatch m_stopwatch = new Stopwatch();\n            private double m_lastValue;\n            private long m_lastTicks;\n            private double m_result;\n\n            public RatePerSecondView(IProbe counter)\n            {\n                if (counter is null) throw new ArgumentNullException(nameof(counter));\n                m_counter = counter;\n                m_stopwatch.Start();\n                m_lastValue = counter.ValueDouble;\n\n                OnReset += (s, e) =>\n                {\n                    m_stopwatch.Restart();\n                    m_lastValue = 0;\n                    m_lastTicks = 0;\n                    m_result = 0;\n                };\n            }\n\n            /// <summary>\n            /// Rate per second.\n            /// </summary>\n            public double Value\n            {\n                get\n                {\n                    var t = m_stopwatch.ElapsedTicks;\n                    var dt = t - m_lastTicks;\n\n                    if (dt > Stopwatch.Frequency)\n                    {\n                        var x = m_counter.ValueDouble;\n                        var dx = x - m_lastValue;\n                        m_lastTicks = t;\n                        m_lastValue = x;\n                        m_result = (dx * Stopwatch.Frequency) / (double)dt;\n                    }\n\n                    return m_result;\n                }\n            }\n\n            public double ValueDouble => Value;\n        }\n\n        public class RatioView : IProbe<double>\n        {\n            private readonly Func<double> m_f;\n\n            public RatioView(IProbe nominator, IProbe denominator)\n            {\n                if (nominator is null) throw new ArgumentNullException(nameof(nominator));\n                if (denominator is null) throw new ArgumentNullException(nameof(denominator));\n                m_f = () => nominator.ValueDouble / denominator.ValueDouble;\n            }\n\n            public RatioView(IProbe nominator, double denominator)\n            {\n                if (nominator is null) throw new ArgumentNullException(nameof(nominator));\n                if (denominator == 0.0) throw new ArgumentOutOfRangeException(nameof(denominator));\n                m_f = () => nominator.ValueDouble / denominator;\n            }\n\n            /// <summary>\n            /// Ratio.\n            /// </summary>\n            public double Value => m_f();\n\n            public double ValueDouble => Value;\n        }\n\n        public class SumView : IProbe<double>\n        {\n            private readonly Func<double> m_f;\n\n            public SumView(IProbe one, params IProbe[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n                m_f = () => one.ValueDouble + others.Sum(x => x.ValueDouble);\n            }\n\n            public SumView(IProbe one, params double[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n                var x = others.Sum();\n                m_f = () => one.ValueDouble + x;\n            }\n\n            /// <summary>\n            /// Ratio.\n            /// </summary>\n            public double Value => m_f();\n\n            public double ValueDouble => Value;\n        }\n\n        public class SubtractView : IProbe<double>\n        {\n            private readonly Func<double> m_f;\n\n            public SubtractView(IProbe one, params IProbe[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n                m_f = () => one.ValueDouble - others.Sum(x => x.ValueDouble);\n            }\n\n            public SubtractView(IProbe one, params double[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n                var x = others.Sum();\n                m_f = () => one.ValueDouble - x;\n            }\n\n            /// <summary>\n            /// Ratio.\n            /// </summary>\n            public double Value => m_f();\n\n            public double ValueDouble => Value;\n        }\n\n        public class MultiplyView : IProbe<double>\n        {\n            private readonly Func<double> m_f;\n\n            public MultiplyView(IProbe one, IProbe other)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (other is null) throw new ArgumentNullException(nameof(other));\n                m_f = () => one.ValueDouble * other.ValueDouble;\n            }\n\n            public MultiplyView(IProbe one, double other)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                m_f = () => one.ValueDouble * other;\n            }\n\n            /// <summary>\n            /// Ratio.\n            /// </summary>\n            public double Value => m_f();\n\n            public double ValueDouble => Value;\n        }\n\n        public class MinView : IProbe<double>\n        {\n            private readonly Func<double> m_f;\n\n            public MinView(IProbe one, params IProbe[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n                m_f = () => Math.Min(one.ValueDouble, others.Min(x => x.ValueDouble));\n            }\n\n            public MinView(IProbe one, params double[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n                var x = others.Min();\n                m_f = () => Math.Min(one.ValueDouble, x);\n            }\n\n            /// <summary>\n            /// Ratio.\n            /// </summary>\n            public double Value => m_f();\n\n            public double ValueDouble => Value;\n        }\n\n        public class MaxView : IProbe<double>\n        {\n            private readonly Func<double> m_f;\n\n            public MaxView(IProbe one, params IProbe[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n                m_f = () => Math.Max(one.ValueDouble, others.Max(x => x.ValueDouble));\n            }\n\n            public MaxView(IProbe one, params double[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n                var x = others.Max();\n                m_f = () => Math.Max(one.ValueDouble, x);\n            }\n\n            /// <summary>\n            /// Ratio.\n            /// </summary>\n            public double Value => m_f();\n\n            public double ValueDouble => Value;\n        }\n\n        public class AvgView : IProbe<double>\n        {\n            private readonly Func<double> m_f;\n\n            public AvgView(IProbe one, params IProbe[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n\n                double d = (1 + others.Length);\n                m_f = () => (one.ValueDouble + others.Sum(x => x.ValueDouble)) / d;\n            }\n\n            public AvgView(IProbe one, params double[] others)\n            {\n                if (one is null) throw new ArgumentNullException(nameof(one));\n                if (others is null) throw new ArgumentNullException(nameof(others));\n\n                var x = others.Sum();\n                double d = (1 + others.Length);\n                m_f = () => (one.ValueDouble + x) / d;\n            }\n\n            /// <summary>\n            /// Ratio.\n            /// </summary>\n            public double Value => m_f();\n\n            public double ValueDouble => Value;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/paket.references",
    "content": "Aardvark.Build"
  },
  {
    "path": "src/Aardvark.Base.Telemetry/paket.template",
    "content": "type project\nid Aardvark.Base.Telemetry\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Aardvark.Base.Tensors.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <WarnOn>3389;3390;3395</WarnOn>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\bin\\Debug\\</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\n  </PropertyGroup>\n  <ItemGroup>\n    <None Include=\"Native\\NativeTensorGenerator.fsx\" />\n    <Compile Include=\"Native\\NativeTensorGenerated.fs\" />\n    <Compile Include=\"Native\\NativeTensorExtensions.fs\" />\n    <None Include=\"Extensions\\TensorUtilitiesGenerator.fsx\" />\n    <Compile Include=\"Extensions\\TensorUtilitiesGenerated.fs\" />\n    <Compile Include=\"Extensions\\TensorMath.fs\" />\n    <Compile Include=\"Extensions\\TensorSlicing.fs\" />\n    <Compile Include=\"PixImage\\ImageTrafo.fs\" />\n    <Compile Include=\"PixImage\\PixImageErrorMetric.fs\" />\n    <Compile Include=\"PixImage\\PixCube.fs\" />\n    <Compile Include=\"Algorithms\\QR.fs\" />\n    <Compile Include=\"Algorithms\\SVD.fs\" />\n    <Compile Include=\"Algorithms\\Solver.fs\" />\n    <None Include=\"Algorithms\\Generator.fsx\" />\n    <None Include=\"paket.references\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\n    <ProjectReference Include=\"..\\Aardvark.Base.Tensors.CSharp\\Aardvark.Base.Tensors.CSharp.csproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Algorithms/Generator.fsx",
    "content": "﻿open System\nopen System.IO\nopen System.Text\nopen System.Text.RegularExpressions\n\nlet qrDecompose = Regex @\"([ \\t]*)//[ \\t]*__MATRIX_QR_DECOMPOSE__[ \\t]*\"\nlet rqDecompose = Regex @\"([ \\t]*)//[ \\t]*__MATRIX_RQ_DECOMPOSE__[ \\t]*\"\nlet qrBidiagonalize = Regex @\"([ \\t]*)//[ \\t]*__MATRIX_QR_BIDIAGONALIZE__[ \\t]*\"\nlet svdDecompose = Regex @\"([ \\t]*)//[ \\t]*__MATRIX_SVD_DECOMPOSE__[ \\t]*\"\n\n\nlet svdFile = Path.Combine(__SOURCE_DIRECTORY__, \"SVD.fs\")\nlet qrFile = Path.Combine(__SOURCE_DIRECTORY__, \"QR.fs\")\n\nlet qrDecomposeCode (indent : string) =\n    let b = StringBuilder()\n    let printfn fmt =fmt |> Printf.kprintf (fun str -> b.Append indent |> ignore; b.AppendLine str |> ignore) \n    for (c, t) in [\"f\", \"float32\"; \"d\", \"float\"] do\n        for rows in 2 .. 4 do\n            for cols in rows .. min 4 (rows + 1) do\n                let mat = sprintf \"M%d%d%s\" rows cols c\n                let qmat = sprintf \"M%d%d%s\" rows rows c\n\n                printfn \"[<MethodImpl(MethodImplOptions.NoInlining)>]\"\n                printfn \"static member DecomposeV(m : %s) = \" mat\n                printfn \"    let pQ = NativePtr.stackalloc<%s> 1\" qmat\n                printfn \"    let pR = NativePtr.stackalloc<%s> 1\" mat\n                printfn \"    NativePtr.write pR m\"\n                printfn \"    let tQ = NativeMatrix<%s>(NativePtr.cast pQ, MatrixInfo(0L,V2l(%d,%d),V2l(1,%d)))\" t rows rows rows\n                printfn \"    let tR = NativeMatrix<%s>(NativePtr.cast pR, MatrixInfo(0L,V2l(%d,%d),V2l(1,%d)))\" t cols rows cols\n                printfn \"    QR.DecomposeInPlace(tQ, tR)\"\n                printfn \"    struct(NativePtr.read pQ, NativePtr.read pR)\"\n                printfn \"\"\n                printfn \"static member Decompose(m : %s) = \" mat\n                printfn \"    let struct(q, r) = QR.DecomposeV(m)\"\n                printfn \"    (q,r)\"\n                printfn \"\"\n    b.ToString()\n\nlet qrBidiagonalizeCode (indent : string) =\n    let b = StringBuilder()\n    let printfn fmt =fmt |> Printf.kprintf (fun str -> b.Append indent |> ignore; b.AppendLine str |> ignore) \n    for (c, t) in [\"f\", \"float32\"; \"d\", \"float\"] do\n        for rows in 2 .. 4 do\n            for cols in rows .. min 4 (rows + 1) do\n                let mat = sprintf \"M%d%d%s\" rows cols c\n                let lmat = sprintf \"M%d%d%s\" rows rows c\n                let rmat = sprintf \"M%d%d%s\" cols cols c\n            \n                printfn \"[<MethodImpl(MethodImplOptions.NoInlining)>]\"\n                printfn \"static member BidiagonalizeV(m : %s) = \" mat\n                printfn \"    let pU = NativePtr.stackalloc<%s> 1\" lmat\n                printfn \"    let pB = NativePtr.stackalloc<%s> 1\" mat\n                printfn \"    let pV = NativePtr.stackalloc<%s> 1\" rmat\n                printfn \"    NativePtr.write pB m\"\n                printfn \"    let tU = NativeMatrix<%s>(NativePtr.cast pU, MatrixInfo(0L, V2l(%d,%d), V2l(1, %d)))\" t rows rows rows\n                printfn \"    let tB = NativeMatrix<%s>(NativePtr.cast pB, MatrixInfo(0L, V2l(%d,%d), V2l(1, %d)))\" t cols rows cols\n                printfn \"    let tV = NativeMatrix<%s>(NativePtr.cast pV, MatrixInfo(0L, V2l(%d,%d), V2l(1, %d)))\" t cols cols cols\n                printfn \"    QR.BidiagonalizeInPlace(tU,tB,tV)\"\n                printfn \"    struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\"\n                printfn \"\"\n                printfn \"static member Bidiagonalize(m : %s) = \" mat\n                printfn \"    let struct(u, b, vt) = QR.BidiagonalizeV(m)\"\n                printfn \"    (u, b, vt)\"\n                printfn \"\"\n    b.ToString()\n\nlet rqDecomposeCode (indent : string) =\n    let b = StringBuilder()\n    let printfn fmt =fmt |> Printf.kprintf (fun str -> b.Append indent |> ignore; b.AppendLine str |> ignore) \n    for (c, t) in [\"f\", \"float32\"; \"d\", \"float\"] do\n        for rows in 2 .. 4 do\n            for cols in rows .. min 4 (rows + 1) do\n                let mat = sprintf \"M%d%d%s\" rows cols c\n                let qmat = sprintf \"M%d%d%s\" cols cols c\n\n                printfn \"[<MethodImpl(MethodImplOptions.NoInlining)>]\"\n                printfn \"static member DecomposeV(m : %s) = \" mat\n                printfn \"    let pR = NativePtr.stackalloc<%s> 1\" mat\n                printfn \"    let pQ = NativePtr.stackalloc<%s> 1\" qmat\n                printfn \"    NativePtr.write pR m\"\n                printfn \"    let tR = NativeMatrix<%s>(NativePtr.cast pR, MatrixInfo(0L,V2l(%d,%d),V2l(1,%d)))\" t cols rows cols\n                printfn \"    let tQ = NativeMatrix<%s>(NativePtr.cast pQ, MatrixInfo(0L,V2l(%d,%d),V2l(1,%d)))\" t cols cols cols\n                printfn \"    RQ.DecomposeInPlace(tR, tQ)\"\n                printfn \"    struct(NativePtr.read pR, NativePtr.read pQ)\"\n                printfn \"\"\n                printfn \"static member Decompose(m : %s) = \" mat\n                printfn \"    let struct(r, q) = RQ.DecomposeV(m)\"\n                printfn \"    (r, q)\"\n                printfn \"\"\n    b.ToString()\n\nlet qrReplacements =\n    [\n        qrDecompose, qrDecomposeCode\n        qrBidiagonalize, qrBidiagonalizeCode\n        rqDecompose, rqDecomposeCode\n    ]\n\ndo\n    let mutable text = File.ReadAllText qrFile\n\n    for (pattern, repl) in qrReplacements do\n        let m0 = pattern.Match text\n        if m0.Success then\n            let m1 = pattern.Match(text, m0.Index + m0.Length)\n            if m1.Success then\n                let pre = text.Substring(0, m0.Index + m0.Length)\n                let post = text.Substring(m1.Index)\n\n                let indent = m0.Groups.[1].Value\n                let repl = repl indent\n\n                text <- pre + \"\\r\\n\" + repl + post\n\n    File.WriteAllText(qrFile, text)\n\n\nlet svdDecomposeCode (indent : string) =\n    let b = StringBuilder()\n    let printfn fmt =fmt |> Printf.kprintf (fun str -> b.Append indent |> ignore; b.AppendLine str |> ignore) \n    for (c, t) in [\"f\", \"float32\"; \"d\", \"float\"] do\n        for rows in 2 .. 4 do\n            for cols in rows .. min 4 (rows + 1) do\n                let mat = sprintf \"M%d%d%s\" rows cols c\n                let lmat = sprintf \"M%d%d%s\" rows rows c\n                let rmat = sprintf \"M%d%d%s\" cols cols c\n            \n                printfn \"[<MethodImpl(MethodImplOptions.NoInlining)>]\"\n                printfn \"static member DecomposeV(m : %s) = \" mat\n                printfn \"    let pU  = NativePtr.stackalloc<%s> 1\" lmat\n                printfn \"    let pS  = NativePtr.stackalloc<%s> 1\" mat\n                printfn \"    let pVt = NativePtr.stackalloc<%s> 1\" rmat\n                printfn \"    NativePtr.write pS m\"\n                printfn \"    let tU  = NativeMatrix<%s>(NativePtr.cast pU,  MatrixInfo(0L, V2l(%d,%d), V2l(1, %d)))\" t rows rows rows\n                printfn \"    let tS  = NativeMatrix<%s>(NativePtr.cast pS,  MatrixInfo(0L, V2l(%d,%d), V2l(1, %d)))\" t cols rows cols\n                printfn \"    let tVt = NativeMatrix<%s>(NativePtr.cast pVt, MatrixInfo(0L, V2l(%d,%d), V2l(1, %d)))\" t cols cols cols\n                printfn \"    if SVD.DecomposeInPlace(tU,tS,tVt) then\"\n                printfn \"        ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\"\n                printfn \"    else\"\n                printfn \"        ValueNone\"\n                printfn \"\"\n                printfn \"static member Decompose(m : %s) = \" mat\n                printfn \"    match SVD.DecomposeV(m) with\"\n                printfn \"    | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\"\n                printfn \"    | ValueNone -> None\"\n                printfn \"\"\n    b.ToString()\n\n\nlet svdReplacements =\n    [\n        svdDecompose, svdDecomposeCode\n    ]\n\ndo\n    let mutable text = File.ReadAllText svdFile\n\n    for (pattern, repl) in svdReplacements do\n        let m0 = pattern.Match text\n        if m0.Success then\n            let m1 = pattern.Match(text, m0.Index + m0.Length)\n            if m1.Success then\n                let pre = text.Substring(0, m0.Index + m0.Length)\n                let post = text.Substring(m1.Index)\n\n                let indent = m0.Groups.[1].Value\n                let repl = repl indent\n\n                text <- pre + \"\\r\\n\" + repl + post\n\n    File.WriteAllText(svdFile, text)\n\n\n\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Algorithms/QR.fs",
    "content": "namespace Aardvark.Base\n\nopen Microsoft.FSharp.NativeInterop\nopen System.Runtime.CompilerServices\n\n#nowarn \"9\"\n\n[<AutoOpen>]\nmodule internal QRHelpers =\n\n    let inline sgn v = if v < LanguagePrimitives.GenericZero then -LanguagePrimitives.GenericOne else LanguagePrimitives.GenericOne\n\n    let inline tiny (eps : 'a) (v : 'a) =\n        abs v <= eps\n\n    let inline applyGivensMat (mat : NativeMatrix< ^a >) (c : int) (r : int) (cos : ^a) (sin : ^a) =\n#if DEBUG\n        let s = min mat.SX mat.SY |> int\n        if c < 0 || c >= s || r < 0 || r >= s then failwithf \"bad givens (%d, %d)\" c r\n#endif\n        let ptrQ = NativePtr.toNativeInt mat.Pointer\n        let dcQ = nativeint sizeof< ^a > * nativeint mat.DX\n        let drQ = nativeint sizeof< ^a > * nativeint mat.DY\n        let rows = int mat.SY\n\n        let mutable p0 = ptrQ + nativeint c * dcQ \n        let mutable p1 = ptrQ + nativeint r * dcQ      \n        // adjust affected elements\n        for _ in 0 .. rows - 1 do\n            let A = NativeInt.read< ^a > p0 //mat.[ci, c]\n            let B = NativeInt.read< ^a > p1 //mat.[ci, r]\n\n            //mat.[ci, c] <-  cos * A + sin * B\n            //mat.[ci, r] <- -sin * A + cos * B\n            NativeInt.write p0 ( cos * A + sin * B )\n            NativeInt.write p1 (-sin * A + cos * B )\n\n            p0 <- p0 + drQ\n            p1 <- p1 + drQ\n                \n    let inline applyGivensTransposedMat (mat : NativeMatrix< ^a >) (c : int) (r : int) (cos : ^a) (sin :  ^a) =\n#if DEBUG\n        let s = min mat.SX mat.SY |> int\n        if c < 0 || c >= s || r < 0 || r >= s then failwithf \"bad givens (%d, %d)\" c r\n#endif\n        let ptrQ = NativePtr.toNativeInt mat.Pointer\n        let dcQ = nativeint sizeof< ^a > * nativeint mat.DX\n        let drQ = nativeint sizeof< ^a > * nativeint mat.DY\n        let cols = int mat.SX\n\n        let mutable p0 = ptrQ + nativeint c * drQ \n        let mutable p1 = ptrQ + nativeint r * drQ      \n        // adjust affected elements\n        for _ in 0 .. cols - 1 do\n            let A = NativeInt.read< ^a > p0\n            let B = NativeInt.read< ^a > p1\n            NativeInt.write p0 ( cos * A + sin * B )\n            NativeInt.write p1 (-sin * A + cos * B )\n\n            p0 <- p0 + dcQ\n            p1 <- p1 + dcQ\n            \n    let inline qrDecomposeNative (eps : ^a) (pQ : NativeMatrix< ^a >) (pR : NativeMatrix< ^a >) =\n        let rows = int pR.SY\n        let cols = int pR.SX\n\n        // pQ <- identity\n        pQ.SetByCoord (fun (v : V2i) -> if v.X = v.Y then LanguagePrimitives.GenericOne else LanguagePrimitives.GenericZero)\n        \n        let sa = nativeint sizeof< ^a >\n        let drR = nativeint pR.DY * sa\n        let dcR = nativeint pR.DX * sa\n\n        let pr = NativePtr.toNativeInt pR.Pointer\n\n#if DEBUG\n        let maxp = nativeint (rows * cols) * sa\n#endif\n        let inline read (p : nativeint) : ^a =\n#if DEBUG    \n            if p < 0n || p > maxp then failwithf \"[QR] bad read: %A outside %A\" p maxp\n#endif        \n            NativeInt.read< ^a > (pr + p)\n\n        let inline write (p : nativeint) (v : ^a ) : unit =\n#if DEBUG    \n            if p < 0n || p > maxp then failwithf \"[RQ] bad write: %A outside %A\" p maxp\n#endif        \n            NativeInt.write< ^a > (pr + p) v\n\n        let mutable pc0 = 0n\n        let mutable pcc = 0n\n        for c in 0 .. cols - 1 do\n            // wiki performs this loop backwards (should not really matter)\n            let mutable prc = pcc + drR\n            let mutable pr0 = pc0 + drR\n            for r in c + 1 .. rows - 1 do \n                let vcc : ^a = read pcc // important since R.[c,c] changes\n                let vrc : ^a = read prc \n\n                // if the dst-element is not already zero then make it zero\n                if not (tiny eps vrc) then\n\n                    // find givens rotation\n                    let rho = sgn vcc * sqrt (vcc * vcc + vrc * vrc)\n                    let cos = vcc / rho\n                    let sin = vrc / rho\n                    \n                    let mutable p0 = pcc\n                    let mutable p1 = prc \n                    // adjust affected elements\n                    for ci in c .. cols - 1 do\n                        let A = read p0\n                        let B = read p1\n                        \n                        write p0 ( cos * A + sin * B )\n                        write p1 (-sin * A + cos * B )\n                        \n                        p0 <- p0 + dcR\n                        p1 <- p1 + dcR\n\n                        \n                    // adjust the resulting Q matrix\n                    applyGivensMat pQ c r cos sin\n                \n                pr0 <- pr0 + drR\n                prc <- prc + drR\n            \n            pc0 <- pc0 + drR\n            pcc <- pcc + drR + dcR\n            \n    let inline rqDecomposeNative (eps : ^a) (pR : NativeMatrix< ^a >) (pQ : NativeMatrix< ^a >) =\n        let rows = int pR.SY\n        let cols = int pR.SX\n#if DEBUG    \n        if rows > cols then failwithf \"cannot RQ decompose matrix with %d rows > %d cols\" rows cols\n#endif\n        // pQ <- identity\n        pQ.SetByCoord (fun (v : V2i) -> if v.X = v.Y then LanguagePrimitives.GenericOne else LanguagePrimitives.GenericZero)\n\n        let sa = nativeint sizeof< ^a >\n        let drR = nativeint pR.DY * sa\n        let dcR = nativeint pR.DX * sa\n\n        let pr = NativePtr.toNativeInt pR.Pointer\n\n#if DEBUG\n        let maxp = nativeint (rows * cols) * sa\n#endif    \n        let inline read (p : nativeint) : ^a = \n#if DEBUG    \n            if p < 0n || p > maxp then failwithf \"[RQ] bad read: %A outside %A\" p maxp\n#endif        \n            NativeInt.read< ^a > (pr + p)\n        \n        let inline write (p : nativeint) (v : ^a ) : unit = \n#if DEBUG\n            if p < 0n || p > maxp then failwithf \"[RQ] bad write: %A outside %A\" p maxp\n#endif    \n            NativeInt.write< ^a > (pr + p) v\n\n\n        let diag = min cols rows\n        let mutable pdd = (dcR + drR) * nativeint (diag - 1)   //ptr (diag - 1) (diag - 1)\n        let mutable pd0 = drR * nativeint (diag - 1)           //ptr (diag - 1) 0\n        let mutable p0d = dcR * nativeint (diag - 1)           //ptr 0 (diag - 1)\n\n        for d in 1 .. diag - 1 do\n            let d = diag - d\n\n            let mutable pdc = pd0\n            let mutable p0c = 0n\n            for c in 0 .. d - 1 do\n                let vcc : ^a = read pdd // important since R.[d,d] changes\n                let vrc : ^a = read pdc\n                \n                // if the dst-element is not already zero then make it zero\n                if not (tiny eps vrc) then\n\n                    // find givens rotation\n                    let rho = sgn vcc * sqrt (vcc * vcc + vrc * vrc)\n                    let cos = vcc / rho\n                    let sin = vrc / rho\n                    \n                    let mutable p0 = p0d\n                    let mutable p1 = p0c\n\n                    // adjust affected elements\n                    for ri in 0 .. d do\n                        //let p0 = ptr ri d\n                        //let p1 = ptr ri c\n                        let A = read p0\n                        let B = read p1\n                        \n                        write p0 ( cos * A + sin * B )\n                        write p1 (-sin * A + cos * B )\n                        p0 <- p0 + drR\n                        p1 <- p1 + drR\n                        \n                    // adjust the resulting Q matrix\n                    applyGivensTransposedMat pQ d c cos sin\n           \n                pdc <- pdc + dcR\n                p0c <- p0c + dcR\n\n            pdd <- pdd - drR - dcR\n            pd0 <- pd0 - drR\n            p0d <- p0d - dcR\n\n            \n\n    /// creates a (in-place) decomposition B = U * B' * Vt where\n    /// U and V a orthonormal rotations and B' is upper bidiagonal\n    /// returns the \"anorm\" of the resulting B matrix\n    let inline qrBidiagonalizeNative (eps : ^a) (U : NativeMatrix< ^a >) (B : NativeMatrix< ^a >) (Vt : NativeMatrix< ^a >) =\n        let rows = int B.SY\n        let cols = int B.SX\n\n        // set u and v to identity\n        U.SetByCoord(fun (v : V2i) -> if v.X = v.Y then LanguagePrimitives.GenericOne else LanguagePrimitives.GenericZero)\n        Vt.SetByCoord(fun (v : V2i) -> if v.X = v.Y then LanguagePrimitives.GenericOne else LanguagePrimitives.GenericZero)\n\n        let pbSize = nativeint B.SX * nativeint B.SY * nativeint sizeof< ^a >\n\n        let sa = nativeint sizeof< ^a >\n        let pB = NativePtr.toNativeInt B.Pointer\n        let dbr = nativeint B.DY * sa\n        let dbc = nativeint B.DX * sa\n        \n        let inline read (ptr : nativeint) : ^a = \n#if DEBUG\n             let dist = ptr - pB\n             if dist < 0n || dist >= pbSize then \n                 failwithf \"bad offset: %A\" (int64 pbSize / int64 sizeof< ^a >)\n#endif\n             NativeInt.read< ^a> ptr\n\n        let inline write (ptr : nativeint) (value : ^a) =  \n#if DEBUG\n             let dist = ptr - pB\n             if dist < 0n || dist >= pbSize then \n                 failwithf \"bad offset: %A\" (int64 pbSize / int64 sizeof< ^a >)\n#endif\n             NativeInt.write< ^a > ptr value\n\n        let mutable anorm = LanguagePrimitives.GenericZero\n\n        let mutable pii = pB\n        let s = min rows cols \n        for i in 0 .. s - 1 do\n\n            // make the subdiagonal column 0\n            let mutable pi1i = pii + dbr\n            for j in i + 1 .. rows - 1 do\n                let vcc = read pii     //B.[i,i]\n                let vrc = read pi1i    //B.[j,i]\n\n                // if the dst-element is not already zero then make it zero\n                if not (tiny eps vrc) then\n\n                    // find givens rotation\n                    let rho = sgn vcc * sqrt (vcc * vcc + vrc * vrc)\n                    let cos = vcc / rho\n                    let sin = vrc / rho\n                    \n                    // adjust affected elements\n                    let mutable pr0 = pii \n                    let mutable pr1 = pi1i\n\n                    // first iteration\n                    let a = read pr0 //B.[r0,ci]\n                    let b = read pr1 //B.[r1,ci]\n                    write pr0 ( cos * a + sin * b )\n                    write pr1 LanguagePrimitives.GenericZero\n                    pr1 <- pr1 + dbc\n                    pr0 <- pr0 + dbc\n\n                    for _ in i+1 .. cols - 1 do\n                        let a = read pr0 //B.[r0,ci]\n                        let b = read pr1 //B.[r1,ci]\n                        write pr0 ( cos * a + sin * b )\n                        write pr1 (-sin * a + cos * b )\n                        pr1 <- pr1 + dbc\n                        pr0 <- pr0 + dbc\n\n                    // adjust the resulting U matrix\n                    applyGivensMat U i j cos sin\n                    \n                pi1i <- pi1i + dbr\n\n                \n            // step one to the right\n            pii <- pii + dbc\n            let i = i + 1\n            let mutable pij = pii + dbc\n            \n            // make the 2nd superdiagonal row 0\n            for j in i + 1 .. cols - 1 do\n                let vcc = read pii     //B.[i,i+1] // important since R.[c,c] changes\n                let vrc = read pij     //B.[i,j]\n\n                // if the dst-element is not already zero then make it zero\n                if not (tiny eps vrc) then\n\n                    // find givens rotation\n                    let rho = sgn vcc * sqrt (vcc * vcc + vrc * vrc)\n                    let sin = vrc / rho\n                    let cos = vcc / rho\n                    \n                    // adjust affected elements\n                    let mutable pc0 = pii\n                    let mutable pc1 = pij\n                    \n                    // first iteration\n                    let a = read pc0 //B.[r0,ci]\n                    let b = read pc1 //B.[r1,ci]\n                    write pc0 ( cos * a + sin * b )\n                    write pc1 LanguagePrimitives.GenericZero\n                    pc0 <- pc0 + dbr\n                    pc1 <- pc1 + dbr\n\n                    for _ in i+1 .. rows do\n                        let a = read pc0 //B.[r0,ci]\n                        let b = read pc1 //B.[r1,ci]\n                        write pc0 ( cos * a + sin * b )\n                        write pc1 (-sin * a + cos * b )\n                        pc0 <- pc0 + dbr\n                        pc1 <- pc1 + dbr\n                        \n                    // adjust the resulting Vt matrix\n                    applyGivensTransposedMat Vt i j cos sin\n                    \n                pij <- pij + dbc\n                \n            let pd = pii - dbc\n            let i = i - 1\n            let normv =\n                if i > 0 then \n                    // abs B.[i-1,i] + abs B.[i,i]\n                    abs (read (pd - dbc)) + abs (read pd)\n                else \n                    // abs B.[i,i]\n                    abs (read pd)\n\n            anorm <- max anorm normv\n            pii <- pii + dbr\n\n        anorm\n\n\n\n[<AbstractClass; Sealed>]\ntype QR private() =\n\n    static let doubleEps = 1E-20\n    static let floatEps =  float32 1E-6\n\n\n    static member DecomposeInPlace(Q : float[,], R : float[,]) =\n        let mutable Q = Q\n        let mutable R = R\n        tensor {\n            let! pQ = &Q\n            let! pR = &R\n            qrDecomposeNative doubleEps pQ pR\n        }\n\n    static member DecomposeInPlace(Q : float32[,], R : float32[,]) =\n        let mutable Q = Q\n        let mutable R = R\n        tensor {\n            let! pQ = &Q\n            let! pR = &R\n            qrDecomposeNative floatEps pQ pR\n        }\n\n    static member DecomposeInPlace(Q : NativeMatrix<float>, R : NativeMatrix<float>) =\n        qrDecomposeNative doubleEps Q R\n        \n    static member DecomposeInPlace(Q : NativeMatrix<float32>, R : NativeMatrix<float32>) =\n        qrDecomposeNative floatEps Q R\n        \n    static member DecomposeInPlace(Q : Matrix<float>, R : Matrix<float>) =\n        let mutable Q = Q\n        let mutable R = R\n        tensor {\n            let! pQ = &Q\n            let! pR = &R\n            qrDecomposeNative doubleEps pQ pR\n        }\n        \n    static member DecomposeInPlace(Q : Matrix<float32>, R : Matrix<float32>) =\n        let mutable Q = Q\n        let mutable R = R\n        tensor {\n            let! pQ = &Q\n            let! pR = &R\n            qrDecomposeNative floatEps pQ pR\n        }\n        \n    static member Decompose (m : float[,]) =\n        let rows = m.GetLength(0)\n        let R = Array2D.copy m\n        let Q = Array2D.zeroCreate rows rows\n        QR.DecomposeInPlace(Q, R)\n        Q, R\n        \n    static member Decompose (m : Matrix<float>) =\n        let R = m.Copy()\n        let Q = Matrix<float>(m.SY, m.SY)\n        QR.DecomposeInPlace(Q, R)\n        Q, R\n   \n    static member Decompose (m : float32[,]) =\n        let rows = m.GetLength(0)\n        let R = Array2D.copy m\n        let Q = Array2D.zeroCreate rows rows\n        QR.DecomposeInPlace(Q, R)\n        Q, R\n        \n    static member Decompose (m : Matrix<float32>) =\n        let R = m.Copy()\n        let Q = Matrix<float32>(m.SY, m.SY)\n        QR.DecomposeInPlace(Q, R)\n        Q, R\n\n    static member BidiagonalizeInPlaceWithNorm(U : NativeMatrix<float>, B : NativeMatrix<float>, Vt : NativeMatrix<float>) =\n        qrBidiagonalizeNative doubleEps U B Vt\n        \n    static member BidiagonalizeInPlace(U : NativeMatrix<float>, B : NativeMatrix<float>, Vt : NativeMatrix<float>) =\n        qrBidiagonalizeNative doubleEps U B Vt |> ignore\n        \n    static member BidiagonalizeInPlace(U : NativeMatrix<float32>, B : NativeMatrix<float32>, Vt : NativeMatrix<float32>) =\n        qrBidiagonalizeNative floatEps U B Vt |> ignore\n\n    static member BidiagonalizeInPlace(U : Matrix<float>, B : Matrix<float>, Vt : Matrix<float>) =\n        let mutable U = U\n        let mutable B = B\n        let mutable Vt = Vt\n\n        tensor {\n            let! pU = &U\n            let! pB = &B\n            let! pVt = &Vt\n            return qrBidiagonalizeNative doubleEps pU pB pVt |> ignore\n        }\n\n    static member BidiagonalizeInPlace(U : Matrix<float32>, B : Matrix<float32>, Vt : Matrix<float32>) =\n        let mutable U = U\n        let mutable B = B\n        let mutable Vt = Vt\n\n        tensor {\n            let! pU = &U\n            let! pB = &B\n            let! pVt = &Vt\n            return qrBidiagonalizeNative floatEps pU pB pVt |> ignore\n        }\n\n    static member BidiagonalizeInPlace(U : float[,], B : float[,], Vt : float[,]) =\n        let mutable U = U\n        let mutable B = B\n        let mutable Vt = Vt\n\n        tensor {\n            let! pU = &U\n            let! pB = &B\n            let! pVt = &Vt\n            return qrBidiagonalizeNative doubleEps pU pB pVt |> ignore\n        }\n\n    static member BidiagonalizeInPlace(U : float32[,], B : float32[,], Vt : float32[,]) =\n        let mutable U = U\n        let mutable B = B\n        let mutable Vt = Vt\n\n        tensor {\n            let! pU = &U\n            let! pB = &B\n            let! pVt = &Vt\n            return qrBidiagonalizeNative floatEps pU pB pVt |> ignore\n        }\n\n    static member Bidiagonalize(m : Matrix<float>) =\n        let U = Matrix<float>(m.SY, m.SY)\n        let B = m.Copy()\n        let Vt = Matrix<float>(m.SX, m.SX)\n        QR.BidiagonalizeInPlace(U, B, Vt) |> ignore\n        U, B, Vt\n\n    static member Bidiagonalize(m : float[,]) =\n        let r = m.GetLength(0)\n        let c = m.GetLength(1)\n        let U = Array2D.zeroCreate r r\n        let B = Array2D.copy m\n        let Vt = Array2D.zeroCreate c c\n        QR.BidiagonalizeInPlace(U, B, Vt) |> ignore\n        U, B, Vt       \n\n    static member Bidiagonalize(m : Matrix<float32>) =\n        let U = Matrix<float32>(m.SY, m.SY)\n        let B = m.Copy()\n        let Vt = Matrix<float32>(m.SX, m.SX)\n        QR.BidiagonalizeInPlace(U, B, Vt) |> ignore\n        U, B, Vt\n\n    static member Bidiagonalize(m : float32[,]) =\n        let r = m.GetLength(0)\n        let c = m.GetLength(1)\n        let U = Array2D.zeroCreate r r\n        let B = Array2D.copy m\n        let Vt = Array2D.zeroCreate c c\n        QR.BidiagonalizeInPlace(U, B, Vt) |> ignore\n        U, B, Vt       \n       \n    // __MATRIX_QR_DECOMPOSE__\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M22f) = \n        let pQ = NativePtr.stackalloc<M22f> 1\n        let pR = NativePtr.stackalloc<M22f> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M22f) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M23f) = \n        let pQ = NativePtr.stackalloc<M22f> 1\n        let pR = NativePtr.stackalloc<M23f> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(3,2),V2l(1,3)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M23f) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M33f) = \n        let pQ = NativePtr.stackalloc<M33f> 1\n        let pR = NativePtr.stackalloc<M33f> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M33f) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M34f) = \n        let pQ = NativePtr.stackalloc<M33f> 1\n        let pR = NativePtr.stackalloc<M34f> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(4,3),V2l(1,4)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M34f) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M44f) = \n        let pQ = NativePtr.stackalloc<M44f> 1\n        let pR = NativePtr.stackalloc<M44f> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M44f) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M22d) = \n        let pQ = NativePtr.stackalloc<M22d> 1\n        let pR = NativePtr.stackalloc<M22d> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M22d) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M23d) = \n        let pQ = NativePtr.stackalloc<M22d> 1\n        let pR = NativePtr.stackalloc<M23d> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(3,2),V2l(1,3)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M23d) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M33d) = \n        let pQ = NativePtr.stackalloc<M33d> 1\n        let pR = NativePtr.stackalloc<M33d> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M33d) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M34d) = \n        let pQ = NativePtr.stackalloc<M33d> 1\n        let pR = NativePtr.stackalloc<M34d> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(4,3),V2l(1,4)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M34d) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M44d) = \n        let pQ = NativePtr.stackalloc<M44d> 1\n        let pR = NativePtr.stackalloc<M44d> 1\n        NativePtr.write pR m\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        QR.DecomposeInPlace(tQ, tR)\n        struct(NativePtr.read pQ, NativePtr.read pR)\n    \n    static member Decompose(m : M44d) = \n        let struct(q, r) = QR.DecomposeV(m)\n        (q,r)\n    \n    // __MATRIX_QR_DECOMPOSE__\n\n    // __MATRIX_QR_BIDIAGONALIZE__\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M22f) = \n        let pU = NativePtr.stackalloc<M22f> 1\n        let pB = NativePtr.stackalloc<M22f> 1\n        let pV = NativePtr.stackalloc<M22f> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float32>(NativePtr.cast pU, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tB = NativeMatrix<float32>(NativePtr.cast pB, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tV = NativeMatrix<float32>(NativePtr.cast pV, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M22f) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M23f) = \n        let pU = NativePtr.stackalloc<M22f> 1\n        let pB = NativePtr.stackalloc<M23f> 1\n        let pV = NativePtr.stackalloc<M33f> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float32>(NativePtr.cast pU, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tB = NativeMatrix<float32>(NativePtr.cast pB, MatrixInfo(0L, V2l(3,2), V2l(1, 3)))\n        let tV = NativeMatrix<float32>(NativePtr.cast pV, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M23f) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M33f) = \n        let pU = NativePtr.stackalloc<M33f> 1\n        let pB = NativePtr.stackalloc<M33f> 1\n        let pV = NativePtr.stackalloc<M33f> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float32>(NativePtr.cast pU, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tB = NativeMatrix<float32>(NativePtr.cast pB, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tV = NativeMatrix<float32>(NativePtr.cast pV, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M33f) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M34f) = \n        let pU = NativePtr.stackalloc<M33f> 1\n        let pB = NativePtr.stackalloc<M34f> 1\n        let pV = NativePtr.stackalloc<M44f> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float32>(NativePtr.cast pU, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tB = NativeMatrix<float32>(NativePtr.cast pB, MatrixInfo(0L, V2l(4,3), V2l(1, 4)))\n        let tV = NativeMatrix<float32>(NativePtr.cast pV, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M34f) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M44f) = \n        let pU = NativePtr.stackalloc<M44f> 1\n        let pB = NativePtr.stackalloc<M44f> 1\n        let pV = NativePtr.stackalloc<M44f> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float32>(NativePtr.cast pU, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        let tB = NativeMatrix<float32>(NativePtr.cast pB, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        let tV = NativeMatrix<float32>(NativePtr.cast pV, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M44f) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M22d) = \n        let pU = NativePtr.stackalloc<M22d> 1\n        let pB = NativePtr.stackalloc<M22d> 1\n        let pV = NativePtr.stackalloc<M22d> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float>(NativePtr.cast pU, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tB = NativeMatrix<float>(NativePtr.cast pB, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tV = NativeMatrix<float>(NativePtr.cast pV, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M22d) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M23d) = \n        let pU = NativePtr.stackalloc<M22d> 1\n        let pB = NativePtr.stackalloc<M23d> 1\n        let pV = NativePtr.stackalloc<M33d> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float>(NativePtr.cast pU, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tB = NativeMatrix<float>(NativePtr.cast pB, MatrixInfo(0L, V2l(3,2), V2l(1, 3)))\n        let tV = NativeMatrix<float>(NativePtr.cast pV, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M23d) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M33d) = \n        let pU = NativePtr.stackalloc<M33d> 1\n        let pB = NativePtr.stackalloc<M33d> 1\n        let pV = NativePtr.stackalloc<M33d> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float>(NativePtr.cast pU, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tB = NativeMatrix<float>(NativePtr.cast pB, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tV = NativeMatrix<float>(NativePtr.cast pV, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M33d) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M34d) = \n        let pU = NativePtr.stackalloc<M33d> 1\n        let pB = NativePtr.stackalloc<M34d> 1\n        let pV = NativePtr.stackalloc<M44d> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float>(NativePtr.cast pU, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tB = NativeMatrix<float>(NativePtr.cast pB, MatrixInfo(0L, V2l(4,3), V2l(1, 4)))\n        let tV = NativeMatrix<float>(NativePtr.cast pV, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M34d) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member BidiagonalizeV(m : M44d) = \n        let pU = NativePtr.stackalloc<M44d> 1\n        let pB = NativePtr.stackalloc<M44d> 1\n        let pV = NativePtr.stackalloc<M44d> 1\n        NativePtr.write pB m\n        let tU = NativeMatrix<float>(NativePtr.cast pU, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        let tB = NativeMatrix<float>(NativePtr.cast pB, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        let tV = NativeMatrix<float>(NativePtr.cast pV, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        QR.BidiagonalizeInPlace(tU,tB,tV)\n        struct(NativePtr.read pU, NativePtr.read pB, NativePtr.read pV)\n    \n    static member Bidiagonalize(m : M44d) = \n        let struct(u, b, vt) = QR.BidiagonalizeV(m)\n        (u, b, vt)\n    \n    // __MATRIX_QR_BIDIAGONALIZE__\n\nmodule QR =\n    let inline private dec< ^a, ^c, ^d when (^a or ^d) : (static member Decompose : ^a -> ^c) > (d : ^d) (m : ^a) : ^c =\n        ((^a or ^d) : (static member Decompose : ^a -> ^c) (m))\n        \n    let inline private decip< ^a, ^b, ^c, ^d when (^a or ^d) : (static member DecomposeInPlace : ^a * ^b -> ^c) > (d : ^d) (m1 : ^a) (m2 : ^b) : ^c =\n        ((^a or ^d) : (static member DecomposeInPlace : ^a * ^b -> ^c) (m1, m2))\n        \n    let inline private bidiag< ^a, ^c, ^d when (^a or ^d) : (static member Bidiagonalize : ^a -> ^c) > (d : ^d) (m : ^a) : ^c =\n        ((^a or ^d) : (static member Bidiagonalize : ^a -> ^c) (m))\n        \n    let inline private bidiagip< ^a, ^b, ^c, ^d, ^x when (^a or ^d) : (static member BidiagonalizeInPlace : ^a * ^b * ^c -> ^x) > (d : ^d) (m1 : ^a) (m2 : ^b) (m3 : ^c) : ^x =\n        ((^a or ^d) : (static member BidiagonalizeInPlace : ^a * ^b * ^c -> ^x) (m1, m2, m3))\n        \n    let inline decompose m = dec Unchecked.defaultof<QR> m\n    let inline decomposeInPlace a b  = decip Unchecked.defaultof<QR> a b\n    let inline bidiagonalize m = bidiag Unchecked.defaultof<QR> m\n    let inline bidiagonalizeInPlace a b c = bidiagip Unchecked.defaultof<QR> a b c\n\n\n\n[<AbstractClass; Sealed>]\ntype RQ private() =\n\n    static let doubleEps = 1E-20\n    static let floatEps =  float32 1E-6\n\n\n    static member DecomposeInPlace(R : float[,], Q : float[,]) =\n        let mutable R = R\n        let mutable Q = Q\n        tensor {\n            let! pQ = &Q\n            let! pR = &R\n            rqDecomposeNative doubleEps pR pQ\n        }\n\n    static member DecomposeInPlace(R : float32[,], Q : float32[,]) =\n        let mutable R = R\n        let mutable Q = Q\n        tensor {\n            let! pQ = &Q\n            let! pR = &R\n            rqDecomposeNative floatEps pR pQ\n        }\n\n    static member DecomposeInPlace(R : NativeMatrix<float>, Q : NativeMatrix<float>) =\n        rqDecomposeNative doubleEps R Q\n        \n    static member DecomposeInPlace(R : NativeMatrix<float32>, Q : NativeMatrix<float32>) =\n        rqDecomposeNative floatEps R Q\n        \n    static member DecomposeInPlace(R : Matrix<float>, Q : Matrix<float>) =\n        let mutable R = R\n        let mutable Q = Q\n        tensor {\n            let! pR = &R\n            let! pQ = &Q\n            rqDecomposeNative doubleEps pR pQ\n        }\n        \n    static member DecomposeInPlace(R : Matrix<float32>, Q : Matrix<float32>) =\n        let mutable R = R\n        let mutable Q = Q\n        tensor {\n            let! pR = &R\n            let! pQ = &Q\n            rqDecomposeNative floatEps pR pQ\n        }\n        \n    static member Decompose (m : float[,]) =\n        let cols = m.GetLength(1)\n        let R = Array2D.copy m\n        let Q = Array2D.zeroCreate cols cols\n        RQ.DecomposeInPlace(R, Q)\n        R, Q\n        \n    static member Decompose (m : Matrix<float>) =\n        let R = m.Copy()\n        let Q = Matrix<float>(m.SX, m.SX)\n        RQ.DecomposeInPlace(R, Q)\n        R, Q\n\n    static member Decompose (m : float32[,]) =\n        let cols = m.GetLength(1)\n        let R = Array2D.copy m\n        let Q = Array2D.zeroCreate cols cols\n        RQ.DecomposeInPlace(R, Q)\n        R, Q\n        \n    static member Decompose (m : Matrix<float32>) =\n        let R = m.Copy()\n        let Q = Matrix<float32>(m.SX, m.SX)\n        RQ.DecomposeInPlace(R, Q)\n        R, Q\n        \n    // __MATRIX_RQ_DECOMPOSE__\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M22f) = \n        let pR = NativePtr.stackalloc<M22f> 1\n        let pQ = NativePtr.stackalloc<M22f> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M22f) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M23f) = \n        let pR = NativePtr.stackalloc<M23f> 1\n        let pQ = NativePtr.stackalloc<M33f> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(3,2),V2l(1,3)))\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M23f) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M33f) = \n        let pR = NativePtr.stackalloc<M33f> 1\n        let pQ = NativePtr.stackalloc<M33f> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M33f) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M34f) = \n        let pR = NativePtr.stackalloc<M34f> 1\n        let pQ = NativePtr.stackalloc<M44f> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(4,3),V2l(1,4)))\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M34f) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M44f) = \n        let pR = NativePtr.stackalloc<M44f> 1\n        let pQ = NativePtr.stackalloc<M44f> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float32>(NativePtr.cast pR, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        let tQ = NativeMatrix<float32>(NativePtr.cast pQ, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M44f) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M22d) = \n        let pR = NativePtr.stackalloc<M22d> 1\n        let pQ = NativePtr.stackalloc<M22d> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(2,2),V2l(1,2)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M22d) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M23d) = \n        let pR = NativePtr.stackalloc<M23d> 1\n        let pQ = NativePtr.stackalloc<M33d> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(3,2),V2l(1,3)))\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M23d) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M33d) = \n        let pR = NativePtr.stackalloc<M33d> 1\n        let pQ = NativePtr.stackalloc<M33d> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(3,3),V2l(1,3)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M33d) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M34d) = \n        let pR = NativePtr.stackalloc<M34d> 1\n        let pQ = NativePtr.stackalloc<M44d> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(4,3),V2l(1,4)))\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M34d) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M44d) = \n        let pR = NativePtr.stackalloc<M44d> 1\n        let pQ = NativePtr.stackalloc<M44d> 1\n        NativePtr.write pR m\n        let tR = NativeMatrix<float>(NativePtr.cast pR, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        let tQ = NativeMatrix<float>(NativePtr.cast pQ, MatrixInfo(0L,V2l(4,4),V2l(1,4)))\n        RQ.DecomposeInPlace(tR, tQ)\n        struct(NativePtr.read pR, NativePtr.read pQ)\n    \n    static member Decompose(m : M44d) = \n        let struct(r, q) = RQ.DecomposeV(m)\n        (r, q)\n    \n    // __MATRIX_RQ_DECOMPOSE__\n\nmodule RQ =\n    let inline private dec< ^a, ^c, ^d when (^a or ^d) : (static member Decompose : ^a -> ^c) > (d : ^d) (m : ^a) : ^c =\n        ((^a or ^d) : (static member Decompose : ^a -> ^c) (m))\n        \n    let inline private decip< ^a, ^b, ^c, ^d when (^a or ^d) : (static member DecomposeInPlace : ^a * ^b -> ^c) > (d : ^d) (m1 : ^a) (m2 : ^b) : ^c =\n        ((^a or ^d) : (static member DecomposeInPlace : ^a * ^b -> ^c) (m1, m2))\n        \n    let inline decompose m = dec Unchecked.defaultof<RQ> m\n    let inline decomposeInPlace a b  = decip Unchecked.defaultof<RQ> a b\n\n\nmodule private QROverloadTest = \n    let test() =\n        let a = QR.bidiagonalize M34d.Zero\n        let a = QR.decompose M44d.Identity\n\n        let a = Matrix<float>()\n        let b = Matrix<float>()\n        let c = Matrix<float>()\n\n        QR.decomposeInPlace a b\n        QR.bidiagonalizeInPlace a b c\n\n        let (R, Q) = RQ.decompose (M23d())\n\n        let arr = Array2D.init 10 10 (fun i j -> 0.1)\n        let (U, B, Vt) = QR.bidiagonalize arr\n\n        ()"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Algorithms/SVD.fs",
    "content": "namespace Aardvark.Base\n\nopen Microsoft.FSharp.NativeInterop\nopen System.Runtime.CompilerServices\n\n#nowarn \"9\"\n\n[<AutoOpen>]\nmodule private SVDHelpers =\n    let inline pythag a b = sqrt (a*a + b*b)\n    \n    let inline svdBidiagonalNative (anorm : ^a) (U : NativeMatrix< ^a >) (B : NativeMatrix< ^a >) (Vt : NativeMatrix< ^a >) : bool =\n        let two = LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne\n        let mutable c : ^a = LanguagePrimitives.GenericZero\n        let mutable s = LanguagePrimitives.GenericZero\n        let mutable rvl0 = LanguagePrimitives.GenericZero\n        let mutable suc = true\n\n        let inline istiny v =\n            anorm + v = anorm\n\n        let n = int B.SY\n        let m = min (int B.SX) n\n\n        let pB = NativePtr.toNativeInt B.Pointer\n        let sa = nativeint sizeof< ^a >\n        let dbc = nativeint B.DX * sa\n        let dbr = nativeint B.DY * sa\n\n        let pw = pB\n        let dw = dbc + dbr\n\n        let prvl = pB + dbc\n        let drvl = dw\n\n        let inline rvl (i : int) : ^a =\n#if DEBUG\n            if i < 0 || i >= n then failwithf \"rvl %d\" i\n#endif\n            if i = 0 then rvl0\n            else NativeInt.read< ^a > (prvl + nativeint (i - 1) * drvl) //B.[i-1,i]\n                \n        let inline setrvl (i : int) (v : ^a) =\n#if DEBUG\n            if i < 0 || i >= n then failwithf \"setrvl %d %A\" i v\n#endif\n            if i = 0 then rvl0 <- v\n            else NativeInt.write (prvl + nativeint (i - 1) * drvl) v //B.[i-1,i] <- v\n\n        let inline w (i : int) : ^a =\n#if DEBUG\n            if i < 0 || i >= n then failwithf \"w %d\" i\n#endif\n            NativeInt.read< ^a > (pw + nativeint i * dw)\n            \n        let inline setw (i : int) (v :  ^a) =\n#if DEBUG\n            if i < 0 || i >= n then failwithf \"setw %d %A\" i v\n#endif\n            NativeInt.write (pw + nativeint i * dw) v\n             \n        let mutable f : ^a = LanguagePrimitives.GenericZero\n        let mutable g : ^a = LanguagePrimitives.GenericZero\n        let mutable h : ^a = LanguagePrimitives.GenericZero\n        \n        let mutable x : ^a = LanguagePrimitives.GenericZero\n        let mutable y : ^a = LanguagePrimitives.GenericZero\n        let mutable z : ^a = LanguagePrimitives.GenericZero\n\n        for k in m - 1 .. -1 .. 0 do \n            let mutable conv = false\n            let mutable iterations = 0\n            while not conv && iterations <= 30 do\n                inc &iterations\n                let mutable flag = true\n                let mutable nm = 0\n                let mutable l = k\n                let mutable testing = true\n                while testing && l >= 0 do\n                    nm <- l - 1\n                    if l = 0 || abs (rvl l) + anorm = anorm then\n                        flag <- false\n                        testing <- false\n                    elif (abs (w nm) + anorm = anorm) then\n                        testing <- false    \n                    else\n                        dec &l\n\n                    \n                if flag then\n                    c <- LanguagePrimitives.GenericZero\n                    s <- LanguagePrimitives.GenericOne\n                    let mutable i = l\n                    while i <= k do\n                        f <- s * rvl i\n                        setrvl i (c * rvl i)\n                        if abs f + anorm <> anorm then\n                            g <- w i //B.[i,i]\n                            h <- pythag f g\n                            setw i h // B.[i,i] <- h\n                            h <- LanguagePrimitives.GenericOne / h\n                            c <- g * h\n                            s <- -f * h\n\n                            applyGivensMat U nm i c s\n                            i <- i + 1\n                        else\n                            i <- k+1\n\n                z <- w k //B.[k,k] \n                if l = k then\n                    conv <- true\n                else\n\n                    if (iterations >= 30) then\n                        //failwith \"no convergence after 30 iterations\"\n                        suc <- false\n\n                    // shift from bottom 2 x 2 minor\n                    x <- w l //B.[l,l];\n                    nm <- k - 1;\n                    y <- w nm //B.[nm, nm];\n                    \n                    g <- rvl nm;\n                    h <- rvl k;\n                    f <- ((y - z) * (y + z) + (g - h) * (g + h)) / (two * h * y)\n                    g <- sqrt (f*f + LanguagePrimitives.GenericOne)\n                    f <- ((x - z) * (x + z) + h * ((y / (f + (if (f >= LanguagePrimitives.GenericZero) then abs(g) else -abs(g)))) - h)) / x\n\n                    // next QR transformation\n                    c <- LanguagePrimitives.GenericOne //1.0\n                    s <- LanguagePrimitives.GenericOne //1.0\n\n                    for j in l .. nm do\n                        let i = j + 1\n                        g <- rvl i\n                        y <- w i //B.[i,i]\n                        h <- s * g\n                        g <- c * g\n                        z <- pythag f h //Fun.Pythag(f, h)\n                        setrvl j z\n                        c <- f / z\n                        s <- h / z\n                        f <- x * c + g * s\n                        g <- g * c - x * s\n                        h <- y * s\n                        y <- y * c\n                        applyGivensTransposedMat Vt j i c s\n\n                        z <- pythag f h // Fun.Pythag(f, h)\n                        setw j z //B.[j,j] <- z\n\n                        if not (istiny z) then\n                            z <- LanguagePrimitives.GenericOne / z\n                            c <- f * z\n                            s <- h * z\n\n                        f <- (c * g) + (s * y)\n                        x <- (c * y) - (s * g)\n                        applyGivensMat U j i c s\n                    \n                    setrvl l LanguagePrimitives.GenericZero\n                    setrvl k f\n                    setw k x // B.[k,k] <- x\n        \n\n        for i in 1 .. m - 1 do\n            setrvl i LanguagePrimitives.GenericZero\n\n        let inline swap i0 i1 =\n            applyGivensMat U i0 i1 LanguagePrimitives.GenericZero LanguagePrimitives.GenericOne\n            let t = w i0\n            setw i0 (w i1)\n            setw i1 t\n            applyGivensTransposedMat Vt i0 i1 LanguagePrimitives.GenericZero LanguagePrimitives.GenericOne\n\n        let cmp =\n            { new System.Collections.Generic.IComparer< ^a > with\n                member x.Compare(l, r) =\n                    compare (abs l) (abs r)\n            }\n\n        let values = \n            //SortedSetExt< ^a * _ >(cmp)\n            System.Collections.Generic.SortedDictionary< ^a, _ >(cmp)\n        for i in 0 .. m - 1 do\n            let v = w i //B.[i,i]\n            match values.TryGetValue(v) with\n            | (true,o) -> \n                values.[v] <- i::o\n            | _ -> \n                values.[v] <- [i]\n                // values <- \n                //     MapExt.alter v (fun o ->\n                //         let o = defaultArg o []\n                //         Some (i :: o)\n                //     ) values\n                \n        for i0 in 0..m-1 do\n            let biggestIdx =\n                let (KeyValue(key,indices)) = values |> Seq.last\n                //let (key, indices) = MapExt.tryItem (values.Count - 1) values |> Option.get\n                match indices with\n                    | [i0] -> \n                        values.Remove(key) |> ignore\n                        //values <- MapExt.remove key values\n                        i0\n                    | i0 :: r ->\n                        values.[key] <- r\n                        //values <- MapExt.add key r values\n                        i0\n                    | _ ->\n                        failwith \"\"\n                \n            if biggestIdx <> i0 then\n                let v0 = w i0 //B.[i0, i0]\n                swap i0 biggestIdx\n               \n                match values.TryGetValue(v0) with\n                | (true,o) -> \n                    values.[v0] <- o |> List.map (fun ii -> if ii = i0 then biggestIdx else ii)\n                | _ -> \n                    values.[v0] <- []                \n                // values <- \n                //     MapExt.alter v0 (fun o ->\n                //         let o = Option.defaultValue [] o\n                //         o |> List.map (fun ii -> if ii = i0 then biggestIdx else ii) |> Some\n                //     ) values\n\n    \n        for i0 in 0..m-2 do\n            if w i0 < LanguagePrimitives.GenericZero then\n                let i1 = m-1\n                setw i0 (-w i0)\n                setw i1 (-w i1)\n                applyGivensTransposedMat Vt i0 i1 -LanguagePrimitives.GenericOne LanguagePrimitives.GenericZero\n\n        suc\n\n[<AbstractClass; Sealed>]\ntype SVD private() =\n\n    static let doubleEps = 1E-20\n    static let floatEps = float32 1E-6\n\n    static member DecomposeInPlace(U : NativeMatrix<float>, S : NativeMatrix<float>, Vt : NativeMatrix<float>) =\n        if S.SX <= S.SY then\n            let anorm = qrBidiagonalizeNative doubleEps U S Vt\n            svdBidiagonalNative anorm U S Vt\n        else\n            // B = U * B' * Vt\n            // Bt = V * Bt' * Ut\n            let Ut = U.Transposed\n            let V = Vt.Transposed\n            let St = S.Transposed\n            let anorm = qrBidiagonalizeNative doubleEps V St Ut\n            svdBidiagonalNative anorm V St Ut\n\n    static member DecomposeInPlace(U : NativeMatrix<float32>, S : NativeMatrix<float32>, Vt : NativeMatrix<float32>) =\n        if S.SX <= S.SY then\n            let anorm = qrBidiagonalizeNative floatEps U S Vt\n            svdBidiagonalNative anorm U S Vt\n        else\n            // B = U * B' * Vt\n            // Bt = V * Bt' * Ut\n            let Ut = U.Transposed\n            let V = Vt.Transposed\n            let St = S.Transposed\n            let anorm = qrBidiagonalizeNative floatEps V St Ut\n            svdBidiagonalNative anorm V St Ut\n            \n    static member DecomposeInPlace(U : Matrix<float>, S : Matrix<float>, Vt : Matrix<float>) =\n        let mutable U = U\n        let mutable S = S\n        let mutable Vt = Vt\n        let mutable suc = false\n        tensor {\n            let! pU = &U\n            let! pS = &S\n            let! pVt = &Vt\n            suc <- SVD.DecomposeInPlace(pU, pS, pVt)\n        }\n        suc\n        \n    static member DecomposeInPlace(U : Matrix<float32>, S : Matrix<float32>, Vt : Matrix<float32>) =\n        let mutable U = U\n        let mutable S = S\n        let mutable Vt = Vt\n        let mutable suc = false\n        tensor {\n            let! pU = &U\n            let! pS = &S\n            let! pVt = &Vt\n            suc <- SVD.DecomposeInPlace(pU, pS, pVt)\n        }\n        suc\n        \n    static member DecomposeInPlace(U : float[,], S : float[,], Vt : float[,]) =\n        let mutable U = U\n        let mutable S = S\n        let mutable Vt = Vt\n        let mutable suc = false\n        tensor {\n            let! pU = &U\n            let! pS = &S\n            let! pVt = &Vt\n            suc <- SVD.DecomposeInPlace(pU, pS, pVt)\n        }    \n        suc     \n\n    static member DecomposeInPlace(U : float32[,], S : float32[,], Vt : float32[,]) =\n        let mutable U = U\n        let mutable S = S\n        let mutable Vt = Vt\n        let mutable suc = false\n        tensor {\n            let! pU = &U\n            let! pS = &S\n            let! pVt = &Vt\n            suc <- SVD.DecomposeInPlace(pU, pS, pVt)\n        }\n        suc\n\n    static member Decompose(m : Matrix<float>) =\n        let r = m.SY\n        let c = m.SX\n        let U = Matrix<float>(r,r)\n        let S = m.Copy()\n        let Vt = Matrix<float>(c,c)\n        if SVD.DecomposeInPlace(U, S, Vt) then\n            Some (U, S, Vt)\n        else\n            None\n\n    static member Decompose(m : Matrix<float32>) =\n        let r = m.SY\n        let c = m.SX\n        let U = Matrix<float32>(r,r)\n        let S = m.Copy()\n        let Vt = Matrix<float32>(c,c)\n        if SVD.DecomposeInPlace(U, S, Vt) then\n            Some (U, S, Vt)\n        else\n            None\n\n    static member Decompose(m : float[,]) =\n        let r = m.GetLength(0)\n        let c = m.GetLength(1)\n        let U = Array2D.zeroCreate r r\n        let S = Array2D.copy m\n        let Vt = Array2D.zeroCreate c c\n        if SVD.DecomposeInPlace(U, S, Vt) then\n            Some (U, S, Vt)\n        else\n            None\n        \n    static member Decompose(m : float32[,]) =\n        let r = m.GetLength(0)\n        let c = m.GetLength(1)\n        let U = Array2D.zeroCreate r r\n        let S = Array2D.copy m\n        let Vt = Array2D.zeroCreate c c\n        if SVD.DecomposeInPlace(U, S, Vt) then\n            Some (U, S, Vt)\n        else\n            None\n        \n        \n    // __MATRIX_SVD_DECOMPOSE__\n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M22f) = \n        let pU  = NativePtr.stackalloc<M22f> 1\n        let pS  = NativePtr.stackalloc<M22f> 1\n        let pVt = NativePtr.stackalloc<M22f> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float32>(NativePtr.cast pU,  MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tS  = NativeMatrix<float32>(NativePtr.cast pS,  MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tVt = NativeMatrix<float32>(NativePtr.cast pVt, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M22f) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M23f) = \n        let pU  = NativePtr.stackalloc<M22f> 1\n        let pS  = NativePtr.stackalloc<M23f> 1\n        let pVt = NativePtr.stackalloc<M33f> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float32>(NativePtr.cast pU,  MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tS  = NativeMatrix<float32>(NativePtr.cast pS,  MatrixInfo(0L, V2l(3,2), V2l(1, 3)))\n        let tVt = NativeMatrix<float32>(NativePtr.cast pVt, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M23f) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M33f) = \n        let pU  = NativePtr.stackalloc<M33f> 1\n        let pS  = NativePtr.stackalloc<M33f> 1\n        let pVt = NativePtr.stackalloc<M33f> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float32>(NativePtr.cast pU,  MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tS  = NativeMatrix<float32>(NativePtr.cast pS,  MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tVt = NativeMatrix<float32>(NativePtr.cast pVt, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M33f) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M34f) = \n        let pU  = NativePtr.stackalloc<M33f> 1\n        let pS  = NativePtr.stackalloc<M34f> 1\n        let pVt = NativePtr.stackalloc<M44f> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float32>(NativePtr.cast pU,  MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tS  = NativeMatrix<float32>(NativePtr.cast pS,  MatrixInfo(0L, V2l(4,3), V2l(1, 4)))\n        let tVt = NativeMatrix<float32>(NativePtr.cast pVt, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M34f) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M44f) = \n        let pU  = NativePtr.stackalloc<M44f> 1\n        let pS  = NativePtr.stackalloc<M44f> 1\n        let pVt = NativePtr.stackalloc<M44f> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float32>(NativePtr.cast pU,  MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        let tS  = NativeMatrix<float32>(NativePtr.cast pS,  MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        let tVt = NativeMatrix<float32>(NativePtr.cast pVt, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M44f) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M22d) = \n        let pU  = NativePtr.stackalloc<M22d> 1\n        let pS  = NativePtr.stackalloc<M22d> 1\n        let pVt = NativePtr.stackalloc<M22d> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float>(NativePtr.cast pU,  MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tS  = NativeMatrix<float>(NativePtr.cast pS,  MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tVt = NativeMatrix<float>(NativePtr.cast pVt, MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M22d) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M23d) = \n        let pU  = NativePtr.stackalloc<M22d> 1\n        let pS  = NativePtr.stackalloc<M23d> 1\n        let pVt = NativePtr.stackalloc<M33d> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float>(NativePtr.cast pU,  MatrixInfo(0L, V2l(2,2), V2l(1, 2)))\n        let tS  = NativeMatrix<float>(NativePtr.cast pS,  MatrixInfo(0L, V2l(3,2), V2l(1, 3)))\n        let tVt = NativeMatrix<float>(NativePtr.cast pVt, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M23d) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M33d) = \n        let pU  = NativePtr.stackalloc<M33d> 1\n        let pS  = NativePtr.stackalloc<M33d> 1\n        let pVt = NativePtr.stackalloc<M33d> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float>(NativePtr.cast pU,  MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tS  = NativeMatrix<float>(NativePtr.cast pS,  MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tVt = NativeMatrix<float>(NativePtr.cast pVt, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M33d) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M34d) = \n        let pU  = NativePtr.stackalloc<M33d> 1\n        let pS  = NativePtr.stackalloc<M34d> 1\n        let pVt = NativePtr.stackalloc<M44d> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float>(NativePtr.cast pU,  MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tS  = NativeMatrix<float>(NativePtr.cast pS,  MatrixInfo(0L, V2l(4,3), V2l(1, 4)))\n        let tVt = NativeMatrix<float>(NativePtr.cast pVt, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M34d) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    [<MethodImpl(MethodImplOptions.NoInlining)>]\n    static member DecomposeV(m : M44d) = \n        let pU  = NativePtr.stackalloc<M44d> 1\n        let pS  = NativePtr.stackalloc<M44d> 1\n        let pVt = NativePtr.stackalloc<M44d> 1\n        NativePtr.write pS m\n        let tU  = NativeMatrix<float>(NativePtr.cast pU,  MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        let tS  = NativeMatrix<float>(NativePtr.cast pS,  MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        let tVt = NativeMatrix<float>(NativePtr.cast pVt, MatrixInfo(0L, V2l(4,4), V2l(1, 4)))\n        if SVD.DecomposeInPlace(tU,tS,tVt) then\n            ValueSome(struct(NativePtr.read pU, NativePtr.read pS, NativePtr.read pVt))\n        else\n            ValueNone\n    \n    static member Decompose(m : M44d) = \n        match SVD.DecomposeV(m) with\n        | ValueSome(struct(u, s, vt)) -> Some(u, s, vt)\n        | ValueNone -> None\n    \n    // __MATRIX_SVD_DECOMPOSE__\n        \n\nmodule SVD =\n    let inline private dec< ^a, ^c, ^d when (^a or ^d) : (static member Decompose : ^a -> ^c) > (d : ^d) (m : ^a) : ^c =\n        ((^a or ^d) : (static member Decompose : ^a -> ^c) (m))\n        \n    let inline private decip< ^a, ^b, ^c, ^d, ^x when (^a or ^d) : (static member DecomposeInPlace : ^a * ^b * ^c -> ^x) > (d : ^d) (m1 : ^a) (m2 : ^b) (m3 : ^c) : ^x =\n        ((^a or ^d) : (static member DecomposeInPlace : ^a * ^b * ^c -> ^x) (m1, m2, m3))\n        \n    let inline decompose m = dec Unchecked.defaultof<SVD> m\n    let inline decomposeInPlace a b  = decip Unchecked.defaultof<SVD> a b\n\n\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Algorithms/Solver.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System.Runtime.CompilerServices\n\nmodule private MatrixSolver =\n\n\n    let inline multiply (m0 : Matrix< ^a >) (m1 : Matrix< ^a >) =\n        if m0.SX <> m1.SY then raise <| System.ArgumentException(\"m0.SX != m1.SY\")\n\n        let result = Matrix< ^a >(m1.SX, m0.SY)\n\n        let data = result.Data\n        let data0 = m0.Data\n        let data1 = m1.Data\n\n        let mutable i = result.FirstIndex\n        let yj = result.JY\n        let my0 = m0.DY\n\n        let xs = result.DSX\n        let mf1 = m1.FirstIndex\n        let xj = result.JX\n        let mx1 = m1.DX\n\n        let ds0 = m0.DSX\n        let d0 = m0.DX\n        let d1 = m1.DY\n\n        let mutable ye = i + result.DSY\n        let mutable f0 = m0.FirstIndex\n        let mutable e0 = f0 + ds0\n        while i <> ye do\n\n            let mutable xe = i + xs\n            let mutable f1 = mf1\n\n            while i <> xe do\n                let mutable dot = LanguagePrimitives.GenericZero< ^a >\n\n                let mutable i0 = f0\n                let mutable i1 = f1\n                while i0 <> e0 do\n                    dot <- dot + data0.[int i0] * data1.[int i1]\n                    \n                    i0 <- i0 + d0\n                    i1 <- i1 + d1\n                data.[int i] <- dot\n\n                i <- i + xj\n                f1 <- f1 + mx1\n\n            i <- i + yj\n            f0 <- f0 + my0\n            e0 <- e0 + my0\n\n        result\n        \n    let inline multiplyVec (mat : Matrix< ^a >) (vec : Vector< ^a >) =\n        if mat.SX <> vec.Size then raise <| System.ArgumentException(\"mat.SX != vec.Size\")\n\n        let result = Array.zeroCreate (int mat.Dim.Y)\n\n        let data0 = mat.Data\n        let data1 = vec.Data\n        let my0 = mat.DY\n        let d1 = vec.D\n        let mf1 = vec.FirstIndex\n        let ds0 = mat.DSX\n        let d0 = mat.DX\n\n\n        let mutable ri = 0L\n        let mutable ye = mat.FirstIndex + mat.DSY\n        let mutable f0 = mat.FirstIndex\n        let mutable e0 = f0 + ds0\n        while f0 <> ye do\n            \n            let mutable dot = LanguagePrimitives.GenericZero< ^a >\n            let mutable i0 = f0\n            let mutable i1 = mf1\n            while i0 <> e0 do\n                dot <- dot + data0.[int i0] * data1.[int i1]\n                i0 <- i0 + d0\n                i1 <- i1 + d1\n            result.[int ri] <- dot\n\n            f0 <- f0 + my0\n            e0 <- e0 + my0\n            ri <- ri + 1L\n\n        Vector.Create result\n\n    let inline addVec (v0 : Vector< ^a >) (v1 : Vector< ^a >) =\n        if v0.Size <> v1.Size then failwith \"wrong vector sizes\"\n\n        let res = Array.zeroCreate (int v0.Size)\n        let mutable i0 = v0.Origin\n        let mutable i1 = v1.Origin\n        let e0 = i0 + v0.Size * v0.Delta\n        let d0 = v0.Delta\n        let d1 = v1.Delta\n        let v0 = v0.Data\n        let v1 = v1.Data\n        let mutable oi = 0\n\n\n        while i0 <> e0 do\n            res.[oi] <- v0.[int i0] + v1.[int i1]\n            i0 <- i0 + d0\n            i1 <- i1 + d1\n            oi <- oi + 1\n\n        Vector.Create res\n \n    let inline subVec (v0 : Vector< ^a >) (v1 : Vector< ^a >) =\n        if v0.Size <> v1.Size then failwith \"wrong vector sizes\"\n\n        let res = Array.zeroCreate (int v0.Size)\n        let mutable i0 = v0.Origin\n        let mutable i1 = v1.Origin\n        let e0 = i0 + v0.Size * v0.Delta\n        let d0 = v0.Delta\n        let d1 = v1.Delta\n        let v0 = v0.Data\n        let v1 = v1.Data\n        let mutable oi = 0\n\n\n        while i0 <> e0 do\n            res.[oi] <- v0.[int i0] - v1.[int i1]\n            i0 <- i0 + d0\n            i1 <- i1 + d1\n            oi <- oi + 1\n\n        Vector.Create res\n\n    [<AutoOpen>]\n    module Helpers = \n\n        let inline luFactorizeAux (dummy : ^d) (a : Matrix< ^a >) =\n            ((^d or ^a or ^b) : (static member LuFactorize : Matrix< ^a > -> int[]) (a))\n\n        let inline luSolveAux (dummy : ^d) (a : Matrix< ^a >) (perm : int[]) (b : Vector< ^c >) =\n            ((^d or ^a) : (static member LuSolve : Matrix< ^a > * int[] * Vector< ^c > -> Vector< ^c > ) (a, perm, b))\n            \n        let inline luFactorize a = luFactorizeAux Unchecked.defaultof<TensorNumericExtensions> a\n        let inline luSolve a b c = luSolveAux Unchecked.defaultof<TensorNumericExtensions> a b c\n\n    let inline solve (copy : bool) (mat : Matrix< ^a >) (vec : Vector< ^a >) (known : Map<int, ^a >) =\n        if vec.Size <> mat.SY then failwithf \"vec.Size <> mat.SY (%d vs %d)\" vec.Size mat.SY\n\n        let known = known |> Map.filter (fun i _ -> i >= 0 && i < int mat.SX)\n        if Map.isEmpty known then\n            if mat.SX > mat.SY then\n                failwith \"cannot solve underconstrained system\"\n\n            elif mat.SX = mat.SY then\n                let a = if copy then mat.Copy() else mat\n                let perm = luFactorize a\n                luSolve a perm vec\n            else\n                let a1 = multiply mat.Transposed mat\n                let b1 = multiplyVec mat.Transposed vec\n                let perm = luFactorize a1\n                luSolve a1 perm b1\n        else    \n            \n            let unknown = \n                let unknown = System.Collections.Generic.List<int>()\n                use e = (known :> seq<_>).GetEnumerator()\n                let mutable i = 0\n                while e.MoveNext() do\n                    while i < e.Current.Key do\n                        // add all unknown until the next known variable\n                        unknown.Add i\n                        i <- i + 1\n\n                    // skip the known variable\n                    i <- i + 1\n                \n                // add all remaining unknowns\n                while i < int mat.SX do\n                    unknown.Add i\n                    i <- i + 1\n\n                unknown\n\n\n            if unknown.Count > int mat.SY then failwith \"cannot solve underconstrained system\"\n\n            let res = Matrix< ^a >(int64 unknown.Count, mat.SY)\n            let mutable bb = Vector< ^a >(mat.SY)\n\n            for ri in 0 .. int mat.SY - 1 do\n                let mutable mRow = mat.GetRow(ri)\n                let mutable resRow = res.GetRow(ri)\n                let mutable i = 0\n                for ci in unknown do\n                    resRow.[i] <- mRow.[ci]\n                    i <- i + 1\n            \n                let mutable rhs = vec.[ri]\n                for KeyValue(id, value) in known do\n                    rhs <- rhs - value * mRow.[id]\n\n                bb.[ri] <- rhs\n\n            let xx = \n                if res.SX = res.SY then\n                    let perm = luFactorize res\n                    luSolve res perm bb\n                else\n                    let a1 = multiply res.Transposed res\n                    let b1 = multiplyVec res.Transposed bb\n                    let perm = luFactorize a1\n                    luSolve a1 perm b1\n\n            let mutable x = Vector< ^a >(int mat.SX)\n            for KeyValue(i, v) in known do\n                x.[i] <- v\n\n            let mutable i = 0\n            for id in unknown do\n                x.[id] <- xx.[i]\n                i <- i + 1\n\n            x\n\n    \n\n[<AbstractClass; Sealed; Extension>]\ntype Solver private() =\n\n    [<Extension>]\n    static member Multiply(m0 : Matrix<ComplexD>, m1 : Matrix<ComplexD>) =\n        MatrixSolver.multiply m0 m1\n\n    /// Multiply matrix with vector as column vector. \n    /// Vector must have save length as columns of matrix.\n    /// Returns a vector with size of matrix rows.\n    [<Extension>]\n    static member Multiply(mat : Matrix<ComplexD>, vec : Vector<ComplexD>) =\n        MatrixSolver.multiplyVec mat vec\n\n    [<Extension>]\n    static member Multiply(m0 : Matrix<ComplexF>, m1 : Matrix<ComplexF>) =\n        MatrixSolver.multiply m0 m1\n\n    /// Multiply matrix with vector as column vector. \n    /// Vector must have save length as columns of matrix.\n    /// Returns a vector with size of matrix rows.\n    [<Extension>]\n    static member Multiply(mat : Matrix<ComplexF>, vec : Vector<ComplexF>) =\n        MatrixSolver.multiplyVec mat vec\n        \n        \n    [<Extension>]\n    static member Add(v0 : Vector<ComplexD>, v1 : Vector<ComplexD>) =\n        MatrixSolver.addVec v0 v1\n        \n    [<Extension>]\n    static member Add(v0 : Vector<ComplexF>, v1 : Vector<ComplexF>) =\n        MatrixSolver.addVec v0 v1\n\n        \n    [<Extension>]\n    static member Subtract(v0 : Vector<ComplexD>, v1 : Vector<ComplexD>) =\n        MatrixSolver.subVec v0 v1\n        \n    [<Extension>]\n    static member Subtract(v0 : Vector<ComplexF>, v1 : Vector<ComplexF>) =\n        MatrixSolver.subVec v0 v1\n        \n    [<Extension>]\n    static member NormSquared(vec : Vector<ComplexF>) =\n        let mutable i = vec.Origin\n        let e = i + vec.Size * vec.Delta\n        let d = vec.Delta\n        let data = vec.Data\n        let mutable sum = 0.0f\n        while i <> e do\n            sum <- sum + data.[int i].NormSquared\n            i <- i + d\n\n        sum\n\n    [<Extension>]\n    static member NormSquared(vec : Vector<ComplexD>) =\n        let mutable i = vec.Origin\n        let e = i + vec.Size * vec.Delta\n        let d = vec.Delta\n        let data = vec.Data\n        let mutable sum = 0.0\n        while i <> e do\n            sum <- sum + data.[int i].NormSquared\n            i <- i + d\n\n        sum\n        \n    [<Extension>]\n    static member Norm(vec : Vector<ComplexD>) =\n        Solver.NormSquared(vec) |> sqrt\n        \n    [<Extension>]\n    static member Norm(vec : Vector<ComplexF>) =\n        Solver.NormSquared(vec) |> sqrt\n\n\n    /// solves `mat*x = vec` with some known `xi`. For over-constrained systems this will\n    /// return a least-squares solution.\n    [<Extension>]\n    static member Solve (mat : Matrix<ComplexD>, vec : Vector<ComplexD>, ?known : Map<int, ComplexD>) =\n        MatrixSolver.solve true mat vec (defaultArg known Map.empty)\n        \n        \n    /// solves `mat*x = vec` with some known `xi`. For over-constrained systems this will\n    /// return a least-squares solution.\n    [<Extension>]\n    static member Solve (mat : Matrix<float>, vec : Vector<float>, ?known : Map<int, float>) =\n        MatrixSolver.solve true mat vec (defaultArg known Map.empty)\n        \n    /// solves `mat*x = vec` with some known `xi`. For over-constrained systems this will\n    /// return a least-squares solution.\n    /// NOTE that this will solve the system in double-precision.\n    [<Extension>]\n    static member Solve (mat : Matrix<float32>, vec : Vector<float32>, ?known : Map<int, float32>) =\n        let mat1 = mat.Map(float)\n        let vec1 = vec.Map(float)\n        let known1 = defaultArg known Map.empty |> Map.map (fun _ v -> float v)\n        let res = MatrixSolver.solve false mat1 vec1 known1\n        res.Map(float32)\n        \n    /// solves `mat*x = vec` with some known `xi`. For over-constrained systems this will\n    /// return a least-squares solution.\n    /// NOTE that this will solve the system in double-precision.\n    [<Extension>]\n    static member Solve (mat : Matrix<ComplexF>, vec : Vector<ComplexF>, ?known : Map<int, ComplexF>) =\n        let mat1 = mat.Map(fun c -> ComplexD(float c.Real, float c.Imag))\n        let vec1 = vec.Map(fun c -> ComplexD(float c.Real, float c.Imag))\n        let known1 = defaultArg known Map.empty |> Map.map (fun _ c -> ComplexD(float c.Real, float c.Imag))\n        let res = MatrixSolver.solve false mat1 vec1 known1\n        res.Map(fun c -> ComplexF(float32 c.Real, float32 c.Imag))\n\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Extensions/TensorMath.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\n\n[<AutoOpen>]\nmodule FSharpTensorMath =\n\n    module Vector =\n\n        /// Computes the dot product of two vectors.\n        let inline dot (v1: Vector<'T>) (v2: Vector<'T>) : 'U =\n            Vector.mapReduce2 (*) (+) v1 v2\n\n        /// Computes the squared Euclidean distance between two vectors.\n        let inline distanceSquared (v1: Vector<'T>) (v2: Vector<'T>) : 'U =\n            Vector.mapReduce2 (fun x y -> sqr (x - y)) (+) v1 v2\n\n        /// Computes the Euclidean distance between two vectors.\n        let inline distance (v1: Vector<'T>) (v2: Vector<'T>) : 'U =\n            sqrt (distanceSquared v1 v2)\n\n        /// Computes the Manhatten (or 1-) distance between two vectors.\n        let inline distance1 (v1: Vector<'T>) (v2: Vector<'T>) : 'U =\n            Vector.mapReduce2 (fun x y -> if x > y then x - y else y - x) (+) v1 v2\n\n        /// Computes the minimum distance between two vectors.\n        let inline distanceMin (v1: Vector<'T>) (v2: Vector<'T>) : 'U =\n            Vector.mapReduce2 (fun x y -> if x > y then x - y else y - x) min v1 v2\n\n        /// Computes the maximum distance between two vectors.\n        let inline distanceMax (v1: Vector<'T>) (v2: Vector<'T>) : 'U =\n            Vector.mapReduce2 (fun x y -> if x > y then x - y else y - x) max v1 v2\n\n        /// Computes the squared length of a vector.\n        let inline lengthSquared (v: Vector<'T>) : 'U =\n            Vector.mapReduce sqr (+) v\n\n        /// Computes the length of a vector.\n        let inline length (v: Vector<'T>) : 'U =\n            sqrt (lengthSquared v)\n\n        /// Computes the Manhatten (or 1-) norm of a vector.\n        let inline norm1 (v: Vector<'T>) : 'T =\n            Vector.mapReduce (fun x -> if x < LanguagePrimitives.GenericZero<'T> then -x else x) (+) v\n\n        /// Computes the minimum norm of a vector.\n        let inline normMin (v: Vector<'T>) : 'T =\n            Vector.mapReduce (fun x -> if x < LanguagePrimitives.GenericZero<'T> then -x else x) min v\n\n        /// Computes the maximum norm of a vector.\n        let inline normMax (v: Vector<'T>) : 'T =\n            Vector.mapReduce (fun x -> if x < LanguagePrimitives.GenericZero<'T> then -x else x) max v\n\n        /// Computes the component-wise sum of two vectors.\n        let inline add (v1: Vector<'T1>) (v2: Vector<'T2>) : Vector<'T3> =\n            Vector.map2 (+) v1 v2\n\n        /// Computes the component-wise difference of two vectors.\n        let inline subtract (v1: Vector<'T1>) (v2: Vector<'T2>) : Vector<'T3> =\n            Vector.map2 (-) v1 v2\n\n        /// Computes the component-wise product of two vectors.\n        let inline multiply (v1: Vector<'T1>) (v2: Vector<'T2>) : Vector<'T3> =\n            Vector.map2 (*) v1 v2\n\n        /// Computes the component-wise fraction of two vectors.\n        let inline divide (v1: Vector<'T1>) (v2: Vector<'T2>) : Vector<'T3> =\n            Vector.map2 (/) v1 v2\n\n        /// Computes the matrix product of a column vector and a row vector.\n        let inline multiplyTransposed (v1: Vector<'T1>) (v2: Vector<'T2>) : Matrix<'T3> =\n            let data = Array.zeroCreate (int v1.Size * int v2.Size)\n            let mutable j = 0\n\n            // Manually inline the inner loop to avoid unnecessary recomputations\n            let f1 = v2.FirstIndex\n            let x1e = f1 + v2.DSX\n            let d1 = v2.Data\n            let xj1 = v2.JX\n\n            v1 |> Vector.iter (fun x ->\n                let mutable i1 = f1\n\n                while i1 <> x1e do\n                    data.[j] <- x * d1.[int i1]\n                    j <- j + 1\n                    i1 <- i1 + xj1\n            )\n\n            Matrix<'T3>(data, v2.Size, v1.Size)\n\n    module Matrix =\n\n        /// Computes the component-wise sum of two matrices.\n        let inline add (v1: Matrix<'T1>) (v2: Matrix<'T2>) : Matrix<'T3> =\n            Matrix.map2 (+) v1 v2\n\n        /// Computes the component-wise difference of two matrices.\n        let inline subtract (v1: Matrix<'T1>) (v2: Matrix<'T2>) : Matrix<'T3> =\n            Matrix.map2 (-) v1 v2\n\n        /// Computes the component-wise fraction of two matrices.\n        let inline divide (v1: Matrix<'T1>) (v2: Matrix<'T2>) : Matrix<'T3> =\n            Matrix.map2 (/) v1 v2\n\n        /// Transforms a column vector by a matrix, i.e. computes m x v.\n        let inline transform (m: Matrix<'T1>) (v: Vector<'T2>) : Vector<'T3> =\n            if m.SX <> v.Size then\n                raise <| ArgumentException($\"Cannot multiply matrix of size {m.Size} with column vector of size {v.Size}.\")\n\n            let dm = m.Data\n            let dv = v.Data\n            let dmX = m.DX\n            let dmY = m.DY\n            let dvX = v.DX\n\n            let mutable fim = m.FirstIndex\n            let em = fim + m.DSY\n            let fiv = v.FirstIndex\n            let ev = fiv + v.DSX\n\n            let result = Array.zeroCreate <| int m.SY\n            let mutable j = 0\n\n            while fim <> em do\n                let mutable im = fim\n                let mutable iv = fiv\n                let mutable sum = Unchecked.defaultof<'T3>\n\n                while iv <> ev do\n                    sum <- sum + dv.[int iv] * dm.[int im]\n                    im <- im + dmX\n                    iv <- iv + dvX\n\n                result.[j] <- sum\n                j <- j + 1\n                fim <- fim + dmY\n\n            Vector<'T3> result\n\n        /// Computes the product of two matrices.\n        let inline multiply (m1: Matrix<'T1>) (m2: Matrix<'T2>) : Matrix<'T3> =\n            if m1.SX <> m2.SY then\n                raise <| ArgumentException($\"Cannot multiply matrices of size {m1.Size} and {m2.Size}.\")\n\n            let d1 = m1.Data\n            let d2 = m2.Data\n            let dX1 = m1.DX\n            let dY1 = m1.DY\n            let dX2 = m2.DX\n            let dY2 = m2.DY\n            let fi2 = m2.FirstIndex\n            let eX2 = fi2 + m2.DSX\n\n            let result = Array.zeroCreate (int m1.SY * int m2.SX)\n            let mutable j = 0\n\n            let mutable r1 = m1.FirstIndex\n            let mutable eX1 = r1 + m1.DSX\n            let eY1 = r1 + m1.DSY\n\n            while r1 <> eY1 do\n                let mutable c2 = fi2\n\n                while c2 <> eX2 do\n                    let mutable i1 = r1\n                    let mutable i2 = c2\n                    let mutable sum = Unchecked.defaultof<'T3>\n\n                    while i1 <> eX1 do\n                        sum <- sum + d1.[int i1] * d2.[int i2]\n                        i1 <- i1 + dX1\n                        i2 <- i2 + dY2\n\n                    result.[j] <- sum\n                    j <- j + 1\n                    c2 <- c2 + dX2\n\n                r1 <- r1 + dY1\n                eX1 <- eX1 + dY1\n\n            Matrix<'T3>(result, m2.SX, m1.SY)\n\n    module Volume =\n\n        /// Computes the component-wise sum of two volumes.\n        let inline add (v1: Volume<'T1>) (v2: Volume<'T2>) : Volume<'T3> =\n            Volume.map2 (+) v1 v2\n\n        /// Computes the component-wise difference of two volumes.\n        let inline subtract (v1: Volume<'T1>) (v2: Volume<'T2>) : Volume<'T3> =\n            Volume.map2 (-) v1 v2\n\n        /// Computes the component-wise product of two volumes.\n        let inline multiply (v1: Volume<'T1>) (v2: Volume<'T2>) : Volume<'T3> =\n            Volume.map2 (*) v1 v2\n\n        /// Computes the component-wise fraction of two volumes.\n        let inline divide (v1: Volume<'T1>) (v2: Volume<'T2>) : Volume<'T3> =\n            Volume.map2 (/) v1 v2\n\n    module Tensor4 =\n\n        /// Computes the component-wise sum of two 4D tensors.\n        let inline add (v1: Tensor4<'T1>) (v2: Tensor4<'T2>) : Tensor4<'T3> =\n            Tensor4.map2 (+) v1 v2\n\n        /// Computes the component-wise difference of two 4D tensors.\n        let inline subtract (v1: Tensor4<'T1>) (v2: Tensor4<'T2>) : Tensor4<'T3> =\n            Tensor4.map2 (-) v1 v2\n\n        /// Computes the component-wise product of two 4D tensors.\n        let inline multiply (v1: Tensor4<'T1>) (v2: Tensor4<'T2>) : Tensor4<'T3> =\n            Tensor4.map2 (*) v1 v2\n\n        /// Computes the component-wise fraction of two 4D tensors.\n        let inline divide (v1: Tensor4<'T1>) (v2: Tensor4<'T2>) : Tensor4<'T3> =\n            Tensor4.map2 (/) v1 v2"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Extensions/TensorSlicing.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<AutoOpen>]\nmodule ``Tensor Slice Extensions`` =\n\n    type Vector<'a> with\n        member x.GetSlice(min : Option<int>, max : Option<int>) =\n            let size = int x.Size\n            let min = defaultArg min 0                  // |> clamp 0 (size-1)\n            let max = defaultArg max (int x.Size - 1)   // |> clamp 0 (size-1)\n            x.SubVector(min, 1 + max - min)\n\n    type Vector<'a, 'b> with\n        member x.GetSlice(min : Option<int>, max : Option<int>) =\n            let size = int x.Size\n            let min = defaultArg min 0                  // |> clamp 0 (size-1)\n            let max = defaultArg max (int x.Size - 1)   // |> clamp 0 (size-1)\n            x.SubVector(min, 1 + max - min)\n\n\n\n    type Matrix<'a> with\n        member x.GetSlice(col : int, min : Option<int>, max : Option<int>) =\n            x.Col(int64 col).GetSlice(min, max)\n\n        member x.GetSlice(min : Option<int>, max : Option<int>, row : int) =\n            x.Row(int64 row).GetSlice(min, max)\n\n        member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>) =\n            let size = V2i x.Size\n\n            let minX = defaultArg minX 0                // |> clamp 0 (size.X-1)\n            let maxX = defaultArg maxX (size.X - 1)     // |> clamp 0 (size.X-1)\n            let minY = defaultArg minY 0                // |> clamp 0 (size.Y-1)\n            let maxY = defaultArg maxY (size.Y - 1)     // |> clamp 0 (size.Y-1)\n\n            x.SubMatrix(int64 minX, int64 minY, 1L + int64 (maxX - minX), 1L + int64 (maxY - minY))\n\n        member x.GetSlice(min : Option<V2i>, max : Option<V2i>) =\n            let min = defaultArg min V2i.Zero\n            let max = defaultArg max (V2i x.Size - V2i.II)\n            x.SubMatrix(int64 min.X, int64 min.Y, 1L + int64 (max.X - min.X), 1L + int64 (max.Y - min.Y))\n\n    type Matrix<'a, 'b> with\n        member x.GetSlice(col : int, min : Option<int>, max : Option<int>) =\n            x.Col(int64 col).GetSlice(min, max)\n\n        member x.GetSlice(min : Option<int>, max : Option<int>, row : int) =\n            x.Row(int64 row).GetSlice(min, max)\n\n        member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>) =\n            let size = V2i x.Size\n\n            let minX = defaultArg minX 0                // |> clamp 0 (size.X-1)\n            let maxX = defaultArg maxX (size.X - 1)     // |> clamp 0 (size.X-1)\n            let minY = defaultArg minY 0                // |> clamp 0 (size.Y-1)\n            let maxY = defaultArg maxY (size.Y - 1)     // |> clamp 0 (size.Y-1)\n\n            x.SubMatrix(int64 minX, int64 minY, 1L + int64 (maxX - minX), 1L + int64 (maxY - minY))\n\n        member x.GetSlice(min : Option<V2i>, max : Option<V2i>) =\n            let min = defaultArg min V2i.Zero\n            let max = defaultArg max (V2i x.Size - V2i.II)\n            x.SubMatrix(int64 min.X, int64 min.Y, 1L + int64 (max.X - min.X), 1L + int64 (max.Y - min.Y))\n\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Extensions/TensorUtilitiesGenerated.fs",
    "content": "namespace Aardvark.Base\n\nopen System\n\n[<AutoOpen>]\nmodule FSharpTensorExtensions =\n\n    module Vector =\n\n        /// Returns if two vectors are equal according to the given comparison function.\n        let inline equalsWith ([<InlineIfLambda>] compare : 'T1 -> 'T2 -> bool) (v1: Vector<'T1>) (v2: Vector<'T2>) =\n            if v1.Size <> v2.Size then\n                false\n            else\n                let s0_1 = v1.DSX\n                let j0_1 = v1.JX\n                let j0_2 = v2.JX\n                let mutable i1 = v1.FirstIndex\n                let mutable i2 = v2.FirstIndex\n\n                let d1 = v1.Data\n                let d2 = v2.Data\n                let mutable result = true\n\n                let e0_1 = i1 + s0_1\n                while i1 <> e0_1 && result do\n                    result <- compare d1.[int i1] d2.[int i2]\n                    i1 <- i1 + j0_1\n                    i2 <- i2 + j0_2\n\n                result\n\n        /// Returns if two vectors are equal.\n        let inline equals (v1: Vector<'T>) (v2: Vector<'T>) =\n            equalsWith (=) v1 v2\n\n        /// Returns if two vectors are equal, i.e. the absolute difference between two corresponding elements does not exceed the given epsilon value.\n        let inline equalsWithin (epsilon: 'T) (v1: Vector<'T>) (v2: Vector<'T>) =\n            equalsWith (fun x y -> if x > y then x - y <= epsilon else y - x <= epsilon) v1 v2\n\n        /// Invokes the given function for each index of a vector.\n        let inline iteri ([<InlineIfLambda>] action: int64 -> unit) (v: Vector<'T>) =\n            let s0 = v.DSX\n            let j0 = v.JX\n            let mutable i = v.FirstIndex\n\n            let e0 = i + s0\n            while i <> e0 do\n                action i\n                i <- i + j0\n\n        /// Invokes the given function for each element of a vector.\n        let inline iter ([<InlineIfLambda>] action: 'T -> unit) (v: Vector<'T>) =\n            let d = v.Data\n            v |> iteri (fun i -> action d.[int i])\n\n        /// Computes a new vector by applying the given mapping function to each element of a vector.\n        let inline map ([<InlineIfLambda>] mapping: 'T -> 'U) (v: Vector<'T>) =\n            let result = Array.zeroCreate <| int (v.SX)\n            let mutable j = 0\n\n            v |> iter (fun x ->\n                result.[j] <- mapping x\n                j <- j + 1\n            )\n\n            Vector<'U>(result, 0L, v.Size, 1L)\n\n        /// Applies the given mapping function to each element of a vector. Returns the modified input vector.\n        let inline mapInPlace ([<InlineIfLambda>] mapping: 'T -> 'T) (v: Vector<'T>) =\n            let d = v.Data\n            v |> iteri (fun i -> d.[int i] <- mapping d.[int i])\n            v\n\n        /// Applies the given mapping function to each element of a vector, accumulating the results using the given reduction function.\n        let inline mapReduce ([<InlineIfLambda>] mapping: 'T -> 'U) ([<InlineIfLambda>] reduction: 'U -> 'U -> 'U) (v: Vector<'T>) =\n            let d = v.Data\n            let fi = v.FirstIndex\n            let j = v.JX\n            let e = fi + v.DSX\n            let mutable result = mapping d.[int fi]\n            let mutable i = fi + j\n            while i <> e do\n                result <- reduction result (mapping d.[int i])\n                i <- i + j\n            result\n\n        /// Invokes the given function for each index of two vectors. The vectors must match in size.\n        let inline iteri2 ([<InlineIfLambda>] action: int64 -> int64 -> unit) (v1: Vector<'T1>) (v2: Vector<'T2>) =\n            if v1.Size <> v2.Size then\n                raise <| ArgumentException($\"Mismatching Vector size ({v1.Size} != {v2.Size})\")\n\n            let s0_1 = v1.DSX\n            let j0_1 = v1.JX\n            let j0_2 = v2.JX\n            let mutable i1 = v1.FirstIndex\n            let mutable i2 = v2.FirstIndex\n\n            let e0_1 = i1 + s0_1\n            while i1 <> e0_1 do\n                action i1 i2\n                i1 <- i1 + j0_1\n                i2 <- i2 + j0_2\n\n        /// Invokes the given function for each element of two vectors. The vectors must match in size.\n        let inline iter2 ([<InlineIfLambda>] action: 'T1 -> 'T2 -> unit) (v1: Vector<'T1>) (v2: Vector<'T2>) =\n            let d1 = v1.Data\n            let d2 = v2.Data\n            iteri2 (fun i1 i2 -> action d1.[int i1] d2.[int i2]) v1 v2\n\n        /// Computes a new vector by applying the given mapping function to each element of two vectors. The vectors must match in size.\n        let inline map2 ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T3) (v1: Vector<'T1>) (v2: Vector<'T2>) =\n            let result = Array.zeroCreate <| int (v1.SX)\n            let mutable j = 0\n\n            iter2 (fun x y ->\n                result.[j] <- mapping x y\n                j <- j + 1\n            ) v1 v2\n\n            Vector<'T3>(result, 0L, v1.Size, 1L)\n\n        /// Applies the given mapping function to each element of two vectors. Returns v2 where the computed values are stored.\n        /// The vectors must match in size.\n        let inline map2InPlace ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T2) (v1: Vector<'T1>) (v2: Vector<'T2>) =\n            let d1 = v1.Data\n            let d2 = v2.Data\n            iteri2 (fun i1 i2 -> d2.[int i2] <- mapping d1.[int i1] d2.[int i2]) v1 v2\n            v2\n\n        /// Applies the given mapping function to each element of two vectors, accumulating the results using the given reduction function.\n        /// The vectors must match in size.\n        let inline mapReduce2 ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T3) ([<InlineIfLambda>] reduction: 'T3 -> 'T3 -> 'T3) (v1: Vector<'T1>) (v2: Vector<'T2>) =\n            if v1.Size <> v2.Size then\n                raise <| ArgumentException($\"Mismatching Vector size ({v1.Size} != {v2.Size})\")\n            let d1 = v1.Data\n            let d2 = v2.Data\n            let fi1 = v1.FirstIndex\n            let fi2 = v2.FirstIndex\n            let j1 = v1.JX\n            let j2 = v2.JX\n            let e1 = fi1 + v1.DSX\n            let mutable result = mapping d1.[int fi1] d2.[int fi2]\n            let mutable i1 = fi1 + j1\n            let mutable i2 = fi2 + j2\n            while i1 <> e1 do\n                result <- reduction result (mapping d1.[int i1] d2.[int i2])\n                i1 <- i1 + j1\n                i2 <- i2 + j2\n            result\n\n    module Matrix =\n\n        /// Returns if two matrices are equal according to the given comparison function.\n        let inline equalsWith ([<InlineIfLambda>] compare : 'T1 -> 'T2 -> bool) (m1: Matrix<'T1>) (m2: Matrix<'T2>) =\n            if m1.Size <> m2.Size then\n                false\n            else\n                let mutable s0_1 = 0L\n                let mutable j0_1 = 0L\n                let mutable j0_2 = 0L\n                let mutable s1_1 = 0L\n                let mutable j1_1 = 0L\n                let mutable j1_2 = 0L\n\n                if abs m2.DX < abs m2.DY then\n                    s0_1 <- m1.DSX; j0_1 <- m1.Info.JX0; j0_2 <- m2.Info.JX0\n                    s1_1 <- m1.DSY; j1_1 <- m1.Info.JYX; j1_2 <- m2.Info.JYX\n                else\n                    s0_1 <- m1.DSY; j0_1 <- m1.Info.JY0; j0_2 <- m2.Info.JY0\n                    s1_1 <- m1.DSX; j1_1 <- m1.Info.JXY; j1_2 <- m2.Info.JXY\n\n                let mutable i1 = m1.FirstIndex\n                let mutable i2 = m2.FirstIndex\n\n                let d1 = m1.Data\n                let d2 = m2.Data\n                let mutable result = true\n\n                let e1_1 = i1 + s1_1\n                while i1 <> e1_1 && result do\n                    let e0_1 = i1 + s0_1\n                    while i1 <> e0_1 && result do\n                        result <- compare d1.[int i1] d2.[int i2]\n                        i1 <- i1 + j0_1\n                        i2 <- i2 + j0_2\n                    i1 <- i1 + j1_1\n                    i2 <- i2 + j1_2\n\n                result\n\n        /// Returns if two matrices are equal.\n        let inline equals (m1: Matrix<'T>) (m2: Matrix<'T>) =\n            equalsWith (=) m1 m2\n\n        /// Returns if two matrices are equal, i.e. the absolute difference between two corresponding elements does not exceed the given epsilon value.\n        let inline equalsWithin (epsilon: 'T) (m1: Matrix<'T>) (m2: Matrix<'T>) =\n            equalsWith (fun x y -> if x > y then x - y <= epsilon else y - x <= epsilon) m1 m2\n\n        /// Invokes the given function for each index of a matrix.\n        let inline iteri ([<InlineIfLambda>] action: int64 -> unit) (m: Matrix<'T>) =\n            let mutable s0 = 0L\n            let mutable j0 = 0L\n            let mutable s1 = 0L\n            let mutable j1 = 0L\n\n            if abs m.DX < abs m.DY then\n                s0 <- m.DSX; j0 <- m.Info.JX0\n                s1 <- m.DSY; j1 <- m.Info.JYX\n            else\n                s0 <- m.DSY; j0 <- m.Info.JY0\n                s1 <- m.DSX; j1 <- m.Info.JXY\n\n            let mutable i = m.FirstIndex\n\n            let e1 = i + s1\n            while i <> e1 do\n                let e0 = i + s0\n                while i <> e0 do\n                    action i\n                    i <- i + j0\n                i <- i + j1\n\n        /// Invokes the given function for each element of a matrix.\n        let inline iter ([<InlineIfLambda>] action: 'T -> unit) (m: Matrix<'T>) =\n            let d = m.Data\n            m |> iteri (fun i -> action d.[int i])\n\n        /// Computes a new matrix by applying the given mapping function to each element of a matrix.\n        let inline map ([<InlineIfLambda>] mapping: 'T -> 'U) (m: Matrix<'T>) =\n            let result = Array.zeroCreate <| int (m.SX * m.SY)\n\n            let delta =\n                if abs m.DX < abs m.DY then\n                    V2l(1L, m.SX)\n                else\n                    V2l(m.SY, 1L)\n\n            let mutable j = 0\n\n            m |> iter (fun x ->\n                result.[j] <- mapping x\n                j <- j + 1\n            )\n\n            Matrix<'U>(result, 0L, m.Size, delta)\n\n        /// Applies the given mapping function to each element of a matrix. Returns the modified input matrix.\n        let inline mapInPlace ([<InlineIfLambda>] mapping: 'T -> 'T) (m: Matrix<'T>) =\n            let d = m.Data\n            m |> iteri (fun i -> d.[int i] <- mapping d.[int i])\n            m\n\n        /// Invokes the given function for each index of two matrices. The matrices must match in size.\n        let inline iteri2 ([<InlineIfLambda>] action: int64 -> int64 -> unit) (m1: Matrix<'T1>) (m2: Matrix<'T2>) =\n            if m1.Size <> m2.Size then\n                raise <| ArgumentException($\"Mismatching Matrix size ({m1.Size} != {m2.Size})\")\n\n            let mutable s0_1 = 0L\n            let mutable j0_1 = 0L\n            let mutable j0_2 = 0L\n            let mutable s1_1 = 0L\n            let mutable j1_1 = 0L\n            let mutable j1_2 = 0L\n\n            if abs m2.DX < abs m2.DY then\n                s0_1 <- m1.DSX; j0_1 <- m1.Info.JX0; j0_2 <- m2.Info.JX0\n                s1_1 <- m1.DSY; j1_1 <- m1.Info.JYX; j1_2 <- m2.Info.JYX\n            else\n                s0_1 <- m1.DSY; j0_1 <- m1.Info.JY0; j0_2 <- m2.Info.JY0\n                s1_1 <- m1.DSX; j1_1 <- m1.Info.JXY; j1_2 <- m2.Info.JXY\n\n            let mutable i1 = m1.FirstIndex\n            let mutable i2 = m2.FirstIndex\n\n            let e1_1 = i1 + s1_1\n            while i1 <> e1_1 do\n                let e0_1 = i1 + s0_1\n                while i1 <> e0_1 do\n                    action i1 i2\n                    i1 <- i1 + j0_1\n                    i2 <- i2 + j0_2\n                i1 <- i1 + j1_1\n                i2 <- i2 + j1_2\n\n        /// Invokes the given function for each element of two matrices. The matrices must match in size.\n        let inline iter2 ([<InlineIfLambda>] action: 'T1 -> 'T2 -> unit) (m1: Matrix<'T1>) (m2: Matrix<'T2>) =\n            let d1 = m1.Data\n            let d2 = m2.Data\n            iteri2 (fun i1 i2 -> action d1.[int i1] d2.[int i2]) m1 m2\n\n        /// Computes a new matrix by applying the given mapping function to each element of two matrices. The matrices must match in size.\n        let inline map2 ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T3) (m1: Matrix<'T1>) (m2: Matrix<'T2>) =\n            let result = Array.zeroCreate <| int (m1.SX * m1.SY)\n\n            let delta =\n                if abs m2.DX < abs m2.DY then\n                    V2l(1L, m2.SX)\n                else\n                    V2l(m2.SY, 1L)\n\n            let mutable j = 0\n\n            iter2 (fun x y ->\n                result.[j] <- mapping x y\n                j <- j + 1\n            ) m1 m2\n\n            Matrix<'T3>(result, 0L, m1.Size, delta)\n\n        /// Applies the given mapping function to each element of two matrices. Returns m2 where the computed values are stored.\n        /// The matrices must match in size.\n        let inline map2InPlace ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T2) (m1: Matrix<'T1>) (m2: Matrix<'T2>) =\n            let d1 = m1.Data\n            let d2 = m2.Data\n            iteri2 (fun i1 i2 -> d2.[int i2] <- mapping d1.[int i1] d2.[int i2]) m1 m2\n            m2\n\n    module Volume =\n\n        /// Returns if two volumes are equal according to the given comparison function.\n        let inline equalsWith ([<InlineIfLambda>] compare : 'T1 -> 'T2 -> bool) (v1: Volume<'T1>) (v2: Volume<'T2>) =\n            if v1.Size <> v2.Size then\n                false\n            else\n                let mutable s0_1 = 0L\n                let mutable j0_1 = 0L\n                let mutable j0_2 = 0L\n                let mutable s1_1 = 0L\n                let mutable j1_1 = 0L\n                let mutable j1_2 = 0L\n                let mutable s2_1 = 0L\n                let mutable j2_1 = 0L\n                let mutable j2_2 = 0L\n\n                if abs v2.DX < abs v2.DZ then\n                    if abs v2.DX < abs v2.DY then\n                        s0_1 <- v1.DSX; j0_1 <- v1.Info.JX0; j0_2 <- v2.Info.JX0\n                        s1_1 <- v1.DSY; j1_1 <- v1.Info.JYX; j1_2 <- v2.Info.JYX\n                        s2_1 <- v1.DSZ; j2_1 <- v1.Info.JZY; j2_2 <- v2.Info.JZY\n                    else\n                        s0_1 <- v1.DSY; j0_1 <- v1.Info.JY0; j0_2 <- v2.Info.JY0\n                        s1_1 <- v1.DSX; j1_1 <- v1.Info.JXY; j1_2 <- v2.Info.JXY\n                        s2_1 <- v1.DSZ; j2_1 <- v1.Info.JZX; j2_2 <- v2.Info.JZX\n                else\n                    if abs v2.DX < abs v2.DY then\n                        s0_1 <- v1.DSZ; j0_1 <- v1.Info.JZ0; j0_2 <- v2.Info.JZ0\n                        s1_1 <- v1.DSX; j1_1 <- v1.Info.JXZ; j1_2 <- v2.Info.JXZ\n                        s2_1 <- v1.DSY; j2_1 <- v1.Info.JYX; j2_2 <- v2.Info.JYX\n                    else\n                        s0_1 <- v1.DSZ; j0_1 <- v1.Info.JZ0; j0_2 <- v2.Info.JZ0\n                        s1_1 <- v1.DSY; j1_1 <- v1.Info.JYZ; j1_2 <- v2.Info.JYZ\n                        s2_1 <- v1.DSX; j2_1 <- v1.Info.JXY; j2_2 <- v2.Info.JXY\n\n                let mutable i1 = v1.FirstIndex\n                let mutable i2 = v2.FirstIndex\n\n                let d1 = v1.Data\n                let d2 = v2.Data\n                let mutable result = true\n\n                let e2_1 = i1 + s2_1\n                while i1 <> e2_1 && result do\n                    let e1_1 = i1 + s1_1\n                    while i1 <> e1_1 && result do\n                        let e0_1 = i1 + s0_1\n                        while i1 <> e0_1 && result do\n                            result <- compare d1.[int i1] d2.[int i2]\n                            i1 <- i1 + j0_1\n                            i2 <- i2 + j0_2\n                        i1 <- i1 + j1_1\n                        i2 <- i2 + j1_2\n                    i1 <- i1 + j2_1\n                    i2 <- i2 + j2_2\n\n                result\n\n        /// Returns if two volumes are equal.\n        let inline equals (v1: Volume<'T>) (v2: Volume<'T>) =\n            equalsWith (=) v1 v2\n\n        /// Returns if two volumes are equal, i.e. the absolute difference between two corresponding elements does not exceed the given epsilon value.\n        let inline equalsWithin (epsilon: 'T) (v1: Volume<'T>) (v2: Volume<'T>) =\n            equalsWith (fun x y -> if x > y then x - y <= epsilon else y - x <= epsilon) v1 v2\n\n        /// Invokes the given function for each index of a volume.\n        let inline iteri ([<InlineIfLambda>] action: int64 -> unit) (v: Volume<'T>) =\n            let mutable s0 = 0L\n            let mutable j0 = 0L\n            let mutable s1 = 0L\n            let mutable j1 = 0L\n            let mutable s2 = 0L\n            let mutable j2 = 0L\n\n            if abs v.DX < abs v.DZ then\n                if abs v.DX < abs v.DY then\n                    s0 <- v.DSX; j0 <- v.Info.JX0\n                    s1 <- v.DSY; j1 <- v.Info.JYX\n                    s2 <- v.DSZ; j2 <- v.Info.JZY\n                else\n                    s0 <- v.DSY; j0 <- v.Info.JY0\n                    s1 <- v.DSX; j1 <- v.Info.JXY\n                    s2 <- v.DSZ; j2 <- v.Info.JZX\n            else\n                if abs v.DX < abs v.DY then\n                    s0 <- v.DSZ; j0 <- v.Info.JZ0\n                    s1 <- v.DSX; j1 <- v.Info.JXZ\n                    s2 <- v.DSY; j2 <- v.Info.JYX\n                else\n                    s0 <- v.DSZ; j0 <- v.Info.JZ0\n                    s1 <- v.DSY; j1 <- v.Info.JYZ\n                    s2 <- v.DSX; j2 <- v.Info.JXY\n\n            let mutable i = v.FirstIndex\n\n            let e2 = i + s2\n            while i <> e2 do\n                let e1 = i + s1\n                while i <> e1 do\n                    let e0 = i + s0\n                    while i <> e0 do\n                        action i\n                        i <- i + j0\n                    i <- i + j1\n                i <- i + j2\n\n        /// Invokes the given function for each element of a volume.\n        let inline iter ([<InlineIfLambda>] action: 'T -> unit) (v: Volume<'T>) =\n            let d = v.Data\n            v |> iteri (fun i -> action d.[int i])\n\n        /// Computes a new volume by applying the given mapping function to each element of a volume.\n        let inline map ([<InlineIfLambda>] mapping: 'T -> 'U) (v: Volume<'T>) =\n            let result = Array.zeroCreate <| int (v.SX * v.SY * v.SZ)\n\n            let delta =\n                if abs v.DX < abs v.DZ then\n                    if abs v.DX < abs v.DY then\n                        V3l(1L, v.SX, v.SX * v.SY)\n                    else\n                        V3l(v.SY, 1L, v.SY * v.SX)\n                else\n                    if abs v.DX < abs v.DY then\n                        V3l(v.SZ, v.SZ * v.SX, 1L)\n                    else\n                        V3l(v.SZ * v.SY, v.SZ, 1L)\n\n            let mutable j = 0\n\n            v |> iter (fun x ->\n                result.[j] <- mapping x\n                j <- j + 1\n            )\n\n            Volume<'U>(result, 0L, v.Size, delta)\n\n        /// Applies the given mapping function to each element of a volume. Returns the modified input volume.\n        let inline mapInPlace ([<InlineIfLambda>] mapping: 'T -> 'T) (v: Volume<'T>) =\n            let d = v.Data\n            v |> iteri (fun i -> d.[int i] <- mapping d.[int i])\n            v\n\n        /// Invokes the given function for each index of two volumes. The volumes must match in size.\n        let inline iteri2 ([<InlineIfLambda>] action: int64 -> int64 -> unit) (v1: Volume<'T1>) (v2: Volume<'T2>) =\n            if v1.Size <> v2.Size then\n                raise <| ArgumentException($\"Mismatching Volume size ({v1.Size} != {v2.Size})\")\n\n            let mutable s0_1 = 0L\n            let mutable j0_1 = 0L\n            let mutable j0_2 = 0L\n            let mutable s1_1 = 0L\n            let mutable j1_1 = 0L\n            let mutable j1_2 = 0L\n            let mutable s2_1 = 0L\n            let mutable j2_1 = 0L\n            let mutable j2_2 = 0L\n\n            if abs v2.DX < abs v2.DZ then\n                if abs v2.DX < abs v2.DY then\n                    s0_1 <- v1.DSX; j0_1 <- v1.Info.JX0; j0_2 <- v2.Info.JX0\n                    s1_1 <- v1.DSY; j1_1 <- v1.Info.JYX; j1_2 <- v2.Info.JYX\n                    s2_1 <- v1.DSZ; j2_1 <- v1.Info.JZY; j2_2 <- v2.Info.JZY\n                else\n                    s0_1 <- v1.DSY; j0_1 <- v1.Info.JY0; j0_2 <- v2.Info.JY0\n                    s1_1 <- v1.DSX; j1_1 <- v1.Info.JXY; j1_2 <- v2.Info.JXY\n                    s2_1 <- v1.DSZ; j2_1 <- v1.Info.JZX; j2_2 <- v2.Info.JZX\n            else\n                if abs v2.DX < abs v2.DY then\n                    s0_1 <- v1.DSZ; j0_1 <- v1.Info.JZ0; j0_2 <- v2.Info.JZ0\n                    s1_1 <- v1.DSX; j1_1 <- v1.Info.JXZ; j1_2 <- v2.Info.JXZ\n                    s2_1 <- v1.DSY; j2_1 <- v1.Info.JYX; j2_2 <- v2.Info.JYX\n                else\n                    s0_1 <- v1.DSZ; j0_1 <- v1.Info.JZ0; j0_2 <- v2.Info.JZ0\n                    s1_1 <- v1.DSY; j1_1 <- v1.Info.JYZ; j1_2 <- v2.Info.JYZ\n                    s2_1 <- v1.DSX; j2_1 <- v1.Info.JXY; j2_2 <- v2.Info.JXY\n\n            let mutable i1 = v1.FirstIndex\n            let mutable i2 = v2.FirstIndex\n\n            let e2_1 = i1 + s2_1\n            while i1 <> e2_1 do\n                let e1_1 = i1 + s1_1\n                while i1 <> e1_1 do\n                    let e0_1 = i1 + s0_1\n                    while i1 <> e0_1 do\n                        action i1 i2\n                        i1 <- i1 + j0_1\n                        i2 <- i2 + j0_2\n                    i1 <- i1 + j1_1\n                    i2 <- i2 + j1_2\n                i1 <- i1 + j2_1\n                i2 <- i2 + j2_2\n\n        /// Invokes the given function for each element of two volumes. The volumes must match in size.\n        let inline iter2 ([<InlineIfLambda>] action: 'T1 -> 'T2 -> unit) (v1: Volume<'T1>) (v2: Volume<'T2>) =\n            let d1 = v1.Data\n            let d2 = v2.Data\n            iteri2 (fun i1 i2 -> action d1.[int i1] d2.[int i2]) v1 v2\n\n        /// Computes a new volume by applying the given mapping function to each element of two volumes. The volumes must match in size.\n        let inline map2 ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T3) (v1: Volume<'T1>) (v2: Volume<'T2>) =\n            let result = Array.zeroCreate <| int (v1.SX * v1.SY * v1.SZ)\n\n            let delta =\n                if abs v2.DX < abs v2.DZ then\n                    if abs v2.DX < abs v2.DY then\n                        V3l(1L, v2.SX, v2.SX * v2.SY)\n                    else\n                        V3l(v2.SY, 1L, v2.SY * v2.SX)\n                else\n                    if abs v2.DX < abs v2.DY then\n                        V3l(v2.SZ, v2.SZ * v2.SX, 1L)\n                    else\n                        V3l(v2.SZ * v2.SY, v2.SZ, 1L)\n\n            let mutable j = 0\n\n            iter2 (fun x y ->\n                result.[j] <- mapping x y\n                j <- j + 1\n            ) v1 v2\n\n            Volume<'T3>(result, 0L, v1.Size, delta)\n\n        /// Applies the given mapping function to each element of two volumes. Returns v2 where the computed values are stored.\n        /// The volumes must match in size.\n        let inline map2InPlace ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T2) (v1: Volume<'T1>) (v2: Volume<'T2>) =\n            let d1 = v1.Data\n            let d2 = v2.Data\n            iteri2 (fun i1 i2 -> d2.[int i2] <- mapping d1.[int i1] d2.[int i2]) v1 v2\n            v2\n\n    module Tensor4 =\n\n        /// Returns if two 4D tensors are equal according to the given comparison function.\n        let inline equalsWith ([<InlineIfLambda>] compare : 'T1 -> 'T2 -> bool) (t1: Tensor4<'T1>) (t2: Tensor4<'T2>) =\n            if t1.Size <> t2.Size then\n                false\n            else\n                let mutable s0_1 = 0L\n                let mutable j0_1 = 0L\n                let mutable j0_2 = 0L\n                let mutable s1_1 = 0L\n                let mutable j1_1 = 0L\n                let mutable j1_2 = 0L\n                let mutable s2_1 = 0L\n                let mutable j2_1 = 0L\n                let mutable j2_2 = 0L\n                let mutable s3_1 = 0L\n                let mutable j3_1 = 0L\n                let mutable j3_2 = 0L\n\n                if abs t2.DX < abs t2.DW then\n                    if abs t2.DX < abs t2.DY then\n                        s0_1 <- t1.DSX; j0_1 <- t1.Info.JX0; j0_2 <- t2.Info.JX0\n                        s1_1 <- t1.DSY; j1_1 <- t1.Info.JYX; j1_2 <- t2.Info.JYX\n                        s2_1 <- t1.DSZ; j2_1 <- t1.Info.JZY; j2_2 <- t2.Info.JZY\n                        s3_1 <- t1.DSW; j3_1 <- t1.Info.JWZ; j3_2 <- t2.Info.JWZ\n                    else\n                        s0_1 <- t1.DSY; j0_1 <- t1.Info.JY0; j0_2 <- t2.Info.JY0\n                        s1_1 <- t1.DSX; j1_1 <- t1.Info.JXY; j1_2 <- t2.Info.JXY\n                        s2_1 <- t1.DSZ; j2_1 <- t1.Info.JZX; j2_2 <- t2.Info.JZX\n                        s3_1 <- t1.DSW; j3_1 <- t1.Info.JWZ; j3_2 <- t2.Info.JWZ\n                else\n                    if abs t2.DX < abs t2.DY then\n                        s0_1 <- t1.DSW; j0_1 <- t1.Info.JW0; j0_2 <- t2.Info.JW0\n                        s1_1 <- t1.DSX; j1_1 <- t1.Info.JXW; j1_2 <- t2.Info.JXW\n                        s2_1 <- t1.DSY; j2_1 <- t1.Info.JYX; j2_2 <- t2.Info.JYX\n                        s3_1 <- t1.DSZ; j3_1 <- t1.Info.JZY; j3_2 <- t2.Info.JZY\n                    else\n                        s0_1 <- t1.DSW; j0_1 <- t1.Info.JW0; j0_2 <- t2.Info.JW0\n                        s1_1 <- t1.DSY; j1_1 <- t1.Info.JYW; j1_2 <- t2.Info.JYW\n                        s2_1 <- t1.DSX; j2_1 <- t1.Info.JXY; j2_2 <- t2.Info.JXY\n                        s3_1 <- t1.DSZ; j3_1 <- t1.Info.JZX; j3_2 <- t2.Info.JZX\n\n                let mutable i1 = t1.FirstIndex\n                let mutable i2 = t2.FirstIndex\n\n                let d1 = t1.Data\n                let d2 = t2.Data\n                let mutable result = true\n\n                let e3_1 = i1 + s3_1\n                while i1 <> e3_1 && result do\n                    let e2_1 = i1 + s2_1\n                    while i1 <> e2_1 && result do\n                        let e1_1 = i1 + s1_1\n                        while i1 <> e1_1 && result do\n                            let e0_1 = i1 + s0_1\n                            while i1 <> e0_1 && result do\n                                result <- compare d1.[int i1] d2.[int i2]\n                                i1 <- i1 + j0_1\n                                i2 <- i2 + j0_2\n                            i1 <- i1 + j1_1\n                            i2 <- i2 + j1_2\n                        i1 <- i1 + j2_1\n                        i2 <- i2 + j2_2\n                    i1 <- i1 + j3_1\n                    i2 <- i2 + j3_2\n\n                result\n\n        /// Returns if two 4D tensors are equal.\n        let inline equals (t1: Tensor4<'T>) (t2: Tensor4<'T>) =\n            equalsWith (=) t1 t2\n\n        /// Returns if two 4D tensors are equal, i.e. the absolute difference between two corresponding elements does not exceed the given epsilon value.\n        let inline equalsWithin (epsilon: 'T) (t1: Tensor4<'T>) (t2: Tensor4<'T>) =\n            equalsWith (fun x y -> if x > y then x - y <= epsilon else y - x <= epsilon) t1 t2\n\n        /// Invokes the given function for each index of a 4D tensor.\n        let inline iteri ([<InlineIfLambda>] action: int64 -> unit) (t: Tensor4<'T>) =\n            let mutable s0 = 0L\n            let mutable j0 = 0L\n            let mutable s1 = 0L\n            let mutable j1 = 0L\n            let mutable s2 = 0L\n            let mutable j2 = 0L\n            let mutable s3 = 0L\n            let mutable j3 = 0L\n\n            if abs t.DX < abs t.DW then\n                if abs t.DX < abs t.DY then\n                    s0 <- t.DSX; j0 <- t.Info.JX0\n                    s1 <- t.DSY; j1 <- t.Info.JYX\n                    s2 <- t.DSZ; j2 <- t.Info.JZY\n                    s3 <- t.DSW; j3 <- t.Info.JWZ\n                else\n                    s0 <- t.DSY; j0 <- t.Info.JY0\n                    s1 <- t.DSX; j1 <- t.Info.JXY\n                    s2 <- t.DSZ; j2 <- t.Info.JZX\n                    s3 <- t.DSW; j3 <- t.Info.JWZ\n            else\n                if abs t.DX < abs t.DY then\n                    s0 <- t.DSW; j0 <- t.Info.JW0\n                    s1 <- t.DSX; j1 <- t.Info.JXW\n                    s2 <- t.DSY; j2 <- t.Info.JYX\n                    s3 <- t.DSZ; j3 <- t.Info.JZY\n                else\n                    s0 <- t.DSW; j0 <- t.Info.JW0\n                    s1 <- t.DSY; j1 <- t.Info.JYW\n                    s2 <- t.DSX; j2 <- t.Info.JXY\n                    s3 <- t.DSZ; j3 <- t.Info.JZX\n\n            let mutable i = t.FirstIndex\n\n            let e3 = i + s3\n            while i <> e3 do\n                let e2 = i + s2\n                while i <> e2 do\n                    let e1 = i + s1\n                    while i <> e1 do\n                        let e0 = i + s0\n                        while i <> e0 do\n                            action i\n                            i <- i + j0\n                        i <- i + j1\n                    i <- i + j2\n                i <- i + j3\n\n        /// Invokes the given function for each element of a 4D tensor.\n        let inline iter ([<InlineIfLambda>] action: 'T -> unit) (t: Tensor4<'T>) =\n            let d = t.Data\n            t |> iteri (fun i -> action d.[int i])\n\n        /// Computes a new 4D tensor by applying the given mapping function to each element of a 4D tensor.\n        let inline map ([<InlineIfLambda>] mapping: 'T -> 'U) (t: Tensor4<'T>) =\n            let result = Array.zeroCreate <| int (t.SX * t.SY * t.SZ * t.SW)\n\n            let delta =\n                if abs t.DX < abs t.DW then\n                    if abs t.DX < abs t.DY then\n                        V4l(1L, t.SX, t.SX * t.SY, t.SX * t.SY * t.SZ)\n                    else\n                        V4l(t.SY, 1L, t.SY * t.SX, t.SY * t.SX * t.SZ)\n                else\n                    if abs t.DX < abs t.DY then\n                        V4l(t.SW, t.SW * t.SX, t.SW * t.SX * t.SY, 1L)\n                    else\n                        V4l(t.SW * t.SY, t.SW, t.SW * t.SY * t.SX, 1L)\n\n            let mutable j = 0\n\n            t |> iter (fun x ->\n                result.[j] <- mapping x\n                j <- j + 1\n            )\n\n            Tensor4<'U>(result, 0L, t.Size, delta)\n\n        /// Applies the given mapping function to each element of a 4D tensor. Returns the modified input 4D tensor.\n        let inline mapInPlace ([<InlineIfLambda>] mapping: 'T -> 'T) (t: Tensor4<'T>) =\n            let d = t.Data\n            t |> iteri (fun i -> d.[int i] <- mapping d.[int i])\n            t\n\n        /// Invokes the given function for each index of two 4D tensors. The 4D tensors must match in size.\n        let inline iteri2 ([<InlineIfLambda>] action: int64 -> int64 -> unit) (t1: Tensor4<'T1>) (t2: Tensor4<'T2>) =\n            if t1.Size <> t2.Size then\n                raise <| ArgumentException($\"Mismatching Tensor4 size ({t1.Size} != {t2.Size})\")\n\n            let mutable s0_1 = 0L\n            let mutable j0_1 = 0L\n            let mutable j0_2 = 0L\n            let mutable s1_1 = 0L\n            let mutable j1_1 = 0L\n            let mutable j1_2 = 0L\n            let mutable s2_1 = 0L\n            let mutable j2_1 = 0L\n            let mutable j2_2 = 0L\n            let mutable s3_1 = 0L\n            let mutable j3_1 = 0L\n            let mutable j3_2 = 0L\n\n            if abs t2.DX < abs t2.DW then\n                if abs t2.DX < abs t2.DY then\n                    s0_1 <- t1.DSX; j0_1 <- t1.Info.JX0; j0_2 <- t2.Info.JX0\n                    s1_1 <- t1.DSY; j1_1 <- t1.Info.JYX; j1_2 <- t2.Info.JYX\n                    s2_1 <- t1.DSZ; j2_1 <- t1.Info.JZY; j2_2 <- t2.Info.JZY\n                    s3_1 <- t1.DSW; j3_1 <- t1.Info.JWZ; j3_2 <- t2.Info.JWZ\n                else\n                    s0_1 <- t1.DSY; j0_1 <- t1.Info.JY0; j0_2 <- t2.Info.JY0\n                    s1_1 <- t1.DSX; j1_1 <- t1.Info.JXY; j1_2 <- t2.Info.JXY\n                    s2_1 <- t1.DSZ; j2_1 <- t1.Info.JZX; j2_2 <- t2.Info.JZX\n                    s3_1 <- t1.DSW; j3_1 <- t1.Info.JWZ; j3_2 <- t2.Info.JWZ\n            else\n                if abs t2.DX < abs t2.DY then\n                    s0_1 <- t1.DSW; j0_1 <- t1.Info.JW0; j0_2 <- t2.Info.JW0\n                    s1_1 <- t1.DSX; j1_1 <- t1.Info.JXW; j1_2 <- t2.Info.JXW\n                    s2_1 <- t1.DSY; j2_1 <- t1.Info.JYX; j2_2 <- t2.Info.JYX\n                    s3_1 <- t1.DSZ; j3_1 <- t1.Info.JZY; j3_2 <- t2.Info.JZY\n                else\n                    s0_1 <- t1.DSW; j0_1 <- t1.Info.JW0; j0_2 <- t2.Info.JW0\n                    s1_1 <- t1.DSY; j1_1 <- t1.Info.JYW; j1_2 <- t2.Info.JYW\n                    s2_1 <- t1.DSX; j2_1 <- t1.Info.JXY; j2_2 <- t2.Info.JXY\n                    s3_1 <- t1.DSZ; j3_1 <- t1.Info.JZX; j3_2 <- t2.Info.JZX\n\n            let mutable i1 = t1.FirstIndex\n            let mutable i2 = t2.FirstIndex\n\n            let e3_1 = i1 + s3_1\n            while i1 <> e3_1 do\n                let e2_1 = i1 + s2_1\n                while i1 <> e2_1 do\n                    let e1_1 = i1 + s1_1\n                    while i1 <> e1_1 do\n                        let e0_1 = i1 + s0_1\n                        while i1 <> e0_1 do\n                            action i1 i2\n                            i1 <- i1 + j0_1\n                            i2 <- i2 + j0_2\n                        i1 <- i1 + j1_1\n                        i2 <- i2 + j1_2\n                    i1 <- i1 + j2_1\n                    i2 <- i2 + j2_2\n                i1 <- i1 + j3_1\n                i2 <- i2 + j3_2\n\n        /// Invokes the given function for each element of two 4D tensors. The 4D tensors must match in size.\n        let inline iter2 ([<InlineIfLambda>] action: 'T1 -> 'T2 -> unit) (t1: Tensor4<'T1>) (t2: Tensor4<'T2>) =\n            let d1 = t1.Data\n            let d2 = t2.Data\n            iteri2 (fun i1 i2 -> action d1.[int i1] d2.[int i2]) t1 t2\n\n        /// Computes a new 4D tensor by applying the given mapping function to each element of two 4D tensors. The 4D tensors must match in size.\n        let inline map2 ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T3) (t1: Tensor4<'T1>) (t2: Tensor4<'T2>) =\n            let result = Array.zeroCreate <| int (t1.SX * t1.SY * t1.SZ * t1.SW)\n\n            let delta =\n                if abs t2.DX < abs t2.DW then\n                    if abs t2.DX < abs t2.DY then\n                        V4l(1L, t2.SX, t2.SX * t2.SY, t2.SX * t2.SY * t2.SZ)\n                    else\n                        V4l(t2.SY, 1L, t2.SY * t2.SX, t2.SY * t2.SX * t2.SZ)\n                else\n                    if abs t2.DX < abs t2.DY then\n                        V4l(t2.SW, t2.SW * t2.SX, t2.SW * t2.SX * t2.SY, 1L)\n                    else\n                        V4l(t2.SW * t2.SY, t2.SW, t2.SW * t2.SY * t2.SX, 1L)\n\n            let mutable j = 0\n\n            iter2 (fun x y ->\n                result.[j] <- mapping x y\n                j <- j + 1\n            ) t1 t2\n\n            Tensor4<'T3>(result, 0L, t1.Size, delta)\n\n        /// Applies the given mapping function to each element of two 4D tensors. Returns t2 where the computed values are stored.\n        /// The 4D tensors must match in size.\n        let inline map2InPlace ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T2) (t1: Tensor4<'T1>) (t2: Tensor4<'T2>) =\n            let d1 = t1.Data\n            let d2 = t2.Data\n            iteri2 (fun i1 i2 -> d2.[int i2] <- mapping d1.[int i1] d2.[int i2]) t1 t2\n            t2\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Extensions/TensorUtilitiesGenerator.fsx",
    "content": "﻿open System\n\nmodule Generator =\n\n    let tensorNames =\n        Map.ofList [\n            1, \"Vector\"\n            2, \"Matrix\"\n            3, \"Volume\"\n        ]\n\n    let tensorReadableNames =\n        Map.ofList [\n            4, \"4D tensor\"\n        ]\n\n    let tensorPluralNames =\n        Map.ofList [\n            2, \"matrices\"\n        ]\n\n    let componentNames = [| \"X\"; \"Y\"; \"Z\"; \"W\" |]\n\n    // We only check for a subset of common permutations (XY swap, last dimension most inner or outer).\n    // For all other permutations, iteration will be suboptimal.\n    let getOptimizedPermutation (innerZW: bool) (swapXY: bool) (dim: int) =\n        let str =\n            let xy = if swapXY then \"YX\" else \"XY\"\n            if dim > 2 then\n                let xyz = if dim > 3 then xy + \"Z\" else xy\n                let w = componentNames.[dim - 1]\n                if innerZW then w + xyz else xyz + w\n            else\n                xy\n\n        str.ToCharArray() |> List.ofArray\n\n    let getDelta (size: string) (permutation: char list) =\n        let dim = permutation.Length\n\n        let index i =\n            componentNames |> Array.findIndex (fun x -> x.[0] = permutation.[i])\n\n        (\"1L\", permutation) ||> List.scan (fun s c ->\n            if s = \"1L\" then $\"{size}{c}\"\n            else $\"{s} * {size}{c}\"\n        )\n        |> List.take dim\n        |> List.permute index\n\n    let getName (dim : int) =\n        match Map.tryFind dim tensorNames with\n        | Some n -> n\n        | None -> sprintf \"Tensor%d\" dim\n\n    let getReadableName (dim: int) =\n        match Map.tryFind dim tensorReadableNames with\n        | Some n -> n\n        | None -> (getName dim).ToLowerInvariant()\n\n    let getReadablePluralName (dim : int) =\n        match Map.tryFind dim tensorPluralNames with\n        | Some n -> n\n        | None -> getReadableName dim + \"s\"\n\n    let builder = System.Text.StringBuilder()\n\n    let write (str : string) = builder.Append(str) |> ignore\n\n    let mutable indent = \"\"\n    let blank() = write \"\\r\\n\"\n    let line fmt = Printf.kprintf (fun str -> write indent; write str; write \"\\r\\n\") fmt\n    let start fmt = Printf.kprintf (fun str -> write indent; write str; write \"\\r\\n\"; indent <- indent + \"    \") fmt\n    let stop() = indent <- indent.Substring(4)\n\n    let forEachPermutation (action: char list -> unit) (dim: int) (t: string) =\n        let lc = componentNames.[dim - 1]\n\n        let rec perm (decisions : bool list) =\n            match decisions with\n            | [] | [_] ->\n                let o = if decisions.Length = 1 then \"Y\" else lc\n                start $\"if abs {t}.DX < abs {t}.D{o} then\"\n                perm (false :: decisions)\n                stop()\n                start \"else\"\n                perm (true :: decisions)\n                stop()\n\n            | swapXY :: innerZW :: _ ->\n                action <| getOptimizedPermutation innerZW swapXY dim\n\n        if dim > 2 then perm []\n        else perm [true]\n\n    let genericIter (components: string[]) (t: string) (iter2: bool)\n                    (continueWhile: string option)\n                    (sizefail: unit -> bool) (preamble: unit -> unit) (action: unit -> unit) (postamble: unit -> unit) =\n        let dim = components.Length\n        let sfx1 = if iter2 then \"_1\" else \"\"\n        let t1 = if iter2 then t + \"1\" else t\n        let t2 = if iter2 then t + \"2\" else t\n        let it1 = if iter2 then \"i1\" else \"i\"\n\n        let continueWhile =\n            match continueWhile with\n            | Some ee -> \" && \" + ee\n            | _ -> \"\"\n\n        let cont =\n            if iter2 then\n                start $\"if {t}1.Size <> {t}2.Size then\"\n                let cont = sizefail()\n                stop()\n                if cont then\n                    start \"else\"\n                    true\n                else\n                    blank()\n                    false\n            else\n                false\n\n        if dim > 1 then\n            for i = 0 to dim - 1 do\n                line $\"let mutable s{i}{sfx1} = 0L\"\n                line $\"let mutable j{i}{sfx1} = 0L\"\n                if iter2 then\n                    line $\"let mutable j{i}_2 = 0L\"\n\n            blank()\n\n            (dim, t2) ||> forEachPermutation (fun p ->\n                p |> List.iteri (fun i c ->\n                    let l = if i = 0 then '0' else p.[i - 1]\n\n                    let mutable ass = $\"s{i}{sfx1} <- {t1}.DS{c}; j{i}{sfx1} <- {t1}.Info.J{c}{l}\"\n                    if iter2 then\n                        ass <- ass + $\"; j{i}_2 <- {t}2.Info.J{c}{l}\"\n\n                    line \"%s\" ass\n                )\n            )\n\n            blank()\n        else\n            line $\"let s0{sfx1} = {t1}.DSX\"\n            line $\"let j0{sfx1} = {t1}.JX\"\n            if iter2 then\n                line $\"let j0_2 = {t2}.JX\"\n\n        line $\"let mutable {it1} = {t1}.FirstIndex\"\n        if iter2 then\n            line $\"let mutable i2 = {t2}.FirstIndex\"\n        blank()\n\n        preamble()\n\n        let rec buildLoop (i: int) =\n            if i < 0 then\n                action()\n            else\n                line $\"let e{i}{sfx1} = {it1} + s{i}{sfx1}\"\n                start $\"while {it1} <> e{i}{sfx1}{continueWhile} do\"\n                buildLoop (i - 1)\n                line $\"{it1} <- {it1} + j{i}{sfx1}\"\n                if iter2 then\n                    line $\"i2 <- i2 + j{i}_2\"\n                stop()\n\n        buildLoop (dim - 1)\n\n        postamble()\n\n        // End of size check\n        if cont then stop()\n\n    let equalsWith (name: string) (components: string[]) (t: string) =\n        start $\"let inline equalsWith ([<InlineIfLambda>] compare : 'T1 -> 'T2 -> bool) ({t}1: {name}<'T1>) ({t}2: {name}<'T2>) =\"\n\n        genericIter components t true\n            (Some \"result\")\n            (fun () -> line \"false\"; true )\n            (fun () ->\n                line $\"let d1 = {t}1.Data\"\n                line $\"let d2 = {t}2.Data\"\n                line \"let mutable result = true\"\n                blank()\n            )\n            (fun () -> line \"result <- compare d1.[int i1] d2.[int i2]\")\n            (fun () ->\n                blank()\n                line \"result\"\n            )\n\n        stop()\n\n    let equals (name: string) (t: string) =\n        start $\"let inline equals ({t}1: {name}<'T>) ({t}2: {name}<'T>) =\"\n        line $\"equalsWith (=) {t}1 {t}2\"\n        stop()\n\n    let equalsWithin (name: string) (t: string) =\n        start $\"let inline equalsWithin (epsilon: 'T) ({t}1: {name}<'T>) ({t}2: {name}<'T>) =\"\n        line $\"equalsWith (fun x y -> if x > y then x - y <= epsilon else y - x <= epsilon) {t}1 {t}2\"\n        stop()\n\n    let iteri (name: string) (components: string[]) (t: string) =\n        start $\"let inline iteri ([<InlineIfLambda>] action: int64 -> unit) ({t}: {name}<'T>) =\"\n\n        genericIter components t false None\n            (fun () -> false)\n            (fun () -> ())\n            (fun () -> line \"action i\")\n            (fun () -> ())\n\n        stop()\n\n    let iter (name: string) (t: string) =\n        start $\"let inline iter ([<InlineIfLambda>] action: 'T -> unit) ({t}: {name}<'T>) =\"\n        line $\"let d = {t}.Data\"\n        line $\"{t} |> iteri (fun i -> action d.[int i])\"\n        stop()\n\n    let map (name: string) (dim: int) (arraySize: string -> string) (t: string) =\n        start $\"let inline map ([<InlineIfLambda>] mapping: 'T -> 'U) ({t}: {name}<'T>) =\"\n        line $\"let result = Array.zeroCreate <| {arraySize t}\"\n\n        if dim > 1 then\n            blank()\n            start \"let delta =\"\n            (dim, t) ||> forEachPermutation (fun p ->\n                let delta = p |> getDelta $\"{t}.S\" |> String.concat \", \"\n                line $\"V{dim}l({delta})\"\n            )\n            stop()\n            blank()\n\n        line \"let mutable j = 0\"\n        blank()\n\n        start $\"{t} |> iter (fun x ->\"\n        line \"result.[j] <- mapping x\"\n        line \"j <- j + 1\"\n        stop()\n        line \")\"\n\n        let delta = if dim = 1 then \"1L\" else \"delta\"\n        blank()\n        line $\"{name}<'U>(result, 0L, {t}.Size, {delta})\"\n        stop()\n\n    let mapInPlace (name: string) (t: string) =\n        start $\"let inline mapInPlace ([<InlineIfLambda>] mapping: 'T -> 'T) ({t}: {name}<'T>) =\"\n        line $\"let d = {t}.Data\"\n        line $\"{t} |> iteri (fun i -> d.[int i] <- mapping d.[int i])\"\n        line $\"{t}\"\n        stop()\n\n    let mapReduce (name: string) (t: string) =\n        start $\"let inline mapReduce ([<InlineIfLambda>] mapping: 'T -> 'U) ([<InlineIfLambda>] reduction: 'U -> 'U -> 'U) ({t}: {name}<'T>) =\"\n        line $\"let d = {t}.Data\"\n        line $\"let fi = {t}.FirstIndex\"\n        line $\"let j = {t}.JX\"\n        line $\"let e = fi + {t}.DSX\"\n\n        line $\"let mutable result = mapping d.[int fi]\"\n        line $\"let mutable i = fi + j\"\n\n        start $\"while i <> e do\"\n        line $\"result <- reduction result (mapping d.[int i])\"\n        line $\"i <- i + j\"\n        stop()\n\n        line $\"result\"\n        stop()\n\n    let iteri2 (name: string) (components: string[]) (t: string) =\n        start $\"let inline iteri2 ([<InlineIfLambda>] action: int64 -> int64 -> unit) ({t}1: {name}<'T1>) ({t}2: {name}<'T2>) =\"\n\n        genericIter components t true None\n            (fun () ->\n                line \"\"\"raise <| ArgumentException($\"Mismatching %s size ({%s1.Size} != {%s2.Size})\")\"\"\" name t t\n                false\n            )\n            (fun () -> ())\n            (fun () -> line \"action i1 i2\")\n            (fun () -> ())\n\n        stop()\n\n    let iter2 (name: string) (t: string) =\n        start $\"let inline iter2 ([<InlineIfLambda>] action: 'T1 -> 'T2 -> unit) ({t}1: {name}<'T1>) ({t}2: {name}<'T2>) =\"\n        line $\"let d1 = {t}1.Data\"\n        line $\"let d2 = {t}2.Data\"\n        line $\"iteri2 (fun i1 i2 -> action d1.[int i1] d2.[int i2]) {t}1 {t}2\"\n        stop()\n\n    let map2 (name: string) (dim: int) (arraySize: string -> string) (t: string) =\n        let t1 = t + \"1\"\n        let t2 = t + \"2\"\n        start $\"let inline map2 ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T3) ({t}1: {name}<'T1>) ({t}2: {name}<'T2>) =\"\n        line $\"let result = Array.zeroCreate <| {arraySize t1}\"\n\n        if dim > 1 then\n            blank()\n            start \"let delta =\"\n            (dim, t2) ||> forEachPermutation (fun p ->\n                let delta = p |> getDelta $\"{t2}.S\" |> String.concat \", \"\n                line $\"V{dim}l({delta})\"\n            )\n            stop()\n            blank()\n\n        line \"let mutable j = 0\"\n        blank()\n\n        start $\"iter2 (fun x y ->\"\n        line \"result.[j] <- mapping x y\"\n        line \"j <- j + 1\"\n        stop()\n        line $\") {t1} {t2}\"\n\n        let delta = if dim = 1 then \"1L\" else \"delta\"\n        blank()\n        line $\"{name}<'T3>(result, 0L, {t1}.Size, {delta})\"\n        stop()\n\n    let map2InPlace (name: string) (t: string) =\n        start $\"let inline map2InPlace ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T2) ({t}1: {name}<'T1>) ({t}2: {name}<'T2>) =\"\n        line $\"let d1 = {t}1.Data\"\n        line $\"let d2 = {t}2.Data\"\n        line $\"iteri2 (fun i1 i2 -> d2.[int i2] <- mapping d1.[int i1] d2.[int i2]) {t}1 {t}2\"\n        line $\"{t}2\"\n        stop()\n\n    let mapReduce2 (name: string) (t: string) =\n        start $\"let inline mapReduce2 ([<InlineIfLambda>] mapping: 'T1 -> 'T2 -> 'T3) ([<InlineIfLambda>] reduction: 'T3 -> 'T3 -> 'T3) ({t}1: {name}<'T1>) ({t}2: {name}<'T2>) =\"\n\n        start $\"if {t}1.Size <> {t}2.Size then\"\n        line \"\"\"raise <| ArgumentException($\"Mismatching %s size ({%s1.Size} != {%s2.Size})\")\"\"\" name t t\n        stop()\n\n        line $\"let d1 = {t}1.Data\"\n        line $\"let d2 = {t}2.Data\"\n        line $\"let fi1 = {t}1.FirstIndex\"\n        line $\"let fi2 = {t}2.FirstIndex\"\n        line $\"let j1 = {t}1.JX\"\n        line $\"let j2 = {t}2.JX\"\n        line $\"let e1 = fi1 + {t}1.DSX\"\n\n        line $\"let mutable result = mapping d1.[int fi1] d2.[int fi2]\"\n        line $\"let mutable i1 = fi1 + j1\"\n        line $\"let mutable i2 = fi2 + j2\"\n\n        start $\"while i1 <> e1 do\"\n        line $\"result <- reduction result (mapping d1.[int i1] d2.[int i2])\"\n        line $\"i1 <- i1 + j1\"\n        line $\"i2 <- i2 + j2\"\n        stop()\n\n        line $\"result\"\n        stop()\n\n    let tensor (dim: int) =\n        let name = getName dim\n        let rname = getReadableName dim\n        let rnames = getReadablePluralName dim\n        let t = string <| Char.ToLowerInvariant name.[0]\n        let componentNames = Array.take dim componentNames\n\n        let arraySize (t: string) =\n            componentNames\n            |> Array.map (fun c -> $\"{t}.S{c}\")\n            |> String.concat \" * \"\n            |> (fun total -> $\"int ({total})\")\n\n        blank()\n        start \"module %s =\" name\n\n        blank()\n        line $\"/// Returns if two {rnames} are equal according to the given comparison function.\"\n        equalsWith name componentNames t\n\n        blank()\n        line $\"/// Returns if two {rnames} are equal.\"\n        equals name t\n\n        blank()\n        line $\"/// Returns if two {rnames} are equal, i.e. the absolute difference between two corresponding elements does not exceed the given epsilon value.\"\n        equalsWithin name t\n\n        blank()\n        line $\"/// Invokes the given function for each index of a {rname}.\"\n        iteri name componentNames t\n\n        blank()\n        line $\"/// Invokes the given function for each element of a {rname}.\"\n        iter name t\n\n        blank()\n        line $\"/// Computes a new {rname} by applying the given mapping function to each element of a {rname}.\"\n        map name dim arraySize t\n\n        blank()\n        line $\"/// Applies the given mapping function to each element of a {rname}. Returns the modified input {rname}.\"\n        mapInPlace name t\n\n        if dim = 1 then\n            blank()\n            line $\"/// Applies the given mapping function to each element of a {rname}, accumulating the results using the given reduction function.\"\n            mapReduce name t\n\n        blank()\n        line $\"/// Invokes the given function for each index of two {rnames}. The {rnames} must match in size.\"\n        iteri2 name componentNames t\n\n        blank()\n        line $\"/// Invokes the given function for each element of two {rnames}. The {rnames} must match in size.\"\n        iter2 name t\n\n        blank()\n        line $\"/// Computes a new {rname} by applying the given mapping function to each element of two {rnames}. The {rnames} must match in size.\"\n        map2 name dim arraySize t\n\n        blank()\n        line $\"/// Applies the given mapping function to each element of two {rnames}. Returns {t}2 where the computed values are stored.\"\n        line $\"/// The {rnames} must match in size.\"\n        map2InPlace name t\n\n        if dim = 1 then\n            blank()\n            line $\"/// Applies the given mapping function to each element of two {rnames}, accumulating the results using the given reduction function.\"\n            line $\"/// The {rnames} must match in size.\"\n            mapReduce2 name t\n\n        stop()\n\n        ()\n\n    let run() =\n        line \"namespace Aardvark.Base\"\n        line \"\"\n        line \"open System\"\n        line \"\"\n        line \"[<AutoOpen>]\"\n        start \"module FSharpTensorExtensions =\"\n        for d in 1 .. 4 do\n            tensor d\n        stop()\n\n        let str = builder.ToString()\n        System.IO.File.WriteAllText(System.IO.Path.Combine(__SOURCE_DIRECTORY__, @\"TensorUtilitiesGenerated.fs\"), str)\n\nGenerator.run()"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Native/NativeTensorExtensions.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen Microsoft.FSharp.NativeInterop\nopen System.Runtime.InteropServices\nopen System.Runtime.CompilerServices\n\n\n#nowarn \"9\"\n#nowarn \"51\"\n#nowarn \"1337\"\n\n[<AutoOpen>]\nmodule ``NativeTensor Pinning`` =\n\n    type Pinning private() =\n\n        static let pin (a : 'a) (f : nativeint -> 'r) =\n            let gc = GCHandle.Alloc(a, GCHandleType.Pinned)\n            try f (gc.AddrOfPinnedObject())\n            finally gc.Free()\n\n        // =======================================================================================\n        // ARRAYS and TENSORS\n        // =======================================================================================\n        static member Using(m : byref<Vector<'a>>, action : NativeVector<'a> -> 'r) =\n            NativeVector.using m action\n            \n        static member Using(m : byref<'a[]>, action : NativeVector<'a> -> 'r) =\n            use ptr = fixed m\n            let vector =\n                NativeVector<'a>(\n                    ptr,\n                    VectorInfo(\n                        0L,\n                        int64 m.Length,\n                        1L\n                    )\n                )\n            action vector\n\n        static member Using(m : byref<Matrix<'a>>, action : NativeMatrix<'a> -> 'r) =\n            NativeMatrix.using m action\n            \n        static member Using(m : byref<'a[,]>, action : NativeMatrix<'a> -> 'r) =\n            let r = m.GetLongLength(0)\n            let c = m.GetLongLength(1)\n            pin m (fun pM ->\n                let matrix =\n                    NativeMatrix<'a>(\n                        NativePtr.ofNativeInt pM,\n                        MatrixInfo(\n                            0L,\n                            V2l(c, r),\n                            V2l(1L, c)\n                        )\n                    )\n                action matrix\n            )\n\n        // =======================================================================================\n        // VECTORS\n        // =======================================================================================\n\n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V2i>, action : NativeVector<int> -> 'r) =\n            let vector =\n                NativeVector<int>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        2L,\n                        1L\n                    )\n                )\n            action vector\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V3i>, action : NativeVector<int> -> 'r) =\n            let vector =\n                NativeVector<int>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        3L,\n                        1L\n                    )\n                )\n            action vector\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V4i>, action : NativeVector<int> -> 'r) =\n            let vector =\n                NativeVector<int>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        4L,\n                        1L\n                    )\n                )\n            action vector\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V2l>, action : NativeVector<int64> -> 'r) =\n            let vector =\n                NativeVector<int64>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        2L,\n                        1L\n                    )\n                )\n            action vector\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V3l>, action : NativeVector<int64> -> 'r) =\n            let vector =\n                NativeVector<int64>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        3L,\n                        1L\n                    )\n                )\n            action vector\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V4l>, action : NativeVector<int64> -> 'r) =\n            let vector =\n                NativeVector<int64>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        4L,\n                        1L\n                    )\n                )\n            action vector\n   \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V2f>, action : NativeVector<float32> -> 'r) =\n            let vector =\n                NativeVector<float32>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        2L,\n                        1L\n                    )\n                )\n            action vector\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V3f>, action : NativeVector<float32> -> 'r) =\n            let vector =\n                NativeVector<float32>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        3L,\n                        1L\n                    )\n                )\n            action vector\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V4f>, action : NativeVector<float32> -> 'r) =\n            let vector =\n                NativeVector<float32>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        4L,\n                        1L\n                    )\n                )\n            action vector\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V2d>, action : NativeVector<float> -> 'r) =\n            let vector =\n                NativeVector<float>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        2L,\n                        1L\n                    )\n                )\n            action vector\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V3d>, action : NativeVector<float> -> 'r) =\n            let vector =\n                NativeVector<float>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        3L,\n                        1L\n                    )\n                )\n            action vector\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<V4d>, action : NativeVector<float> -> 'r) =\n            let vector =\n                NativeVector<float>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        4L,\n                        1L\n                    )\n                )\n            action vector\n \n        // =======================================================================================\n        // COLORS\n        // =======================================================================================\n        \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<C3b>, action : NativeVector<byte> -> 'r) =\n            let vector =\n                NativeVector<byte>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        3L,\n                        1L\n                    )\n                )\n            action vector\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<C4b>, action : NativeVector<byte> -> 'r) =\n            let vector =\n                NativeVector<byte>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        4L,\n                        1L\n                    )\n                )\n            action vector\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<C3us>, action : NativeVector<uint16> -> 'r) =\n            let vector =\n                NativeVector<uint16>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        3L,\n                        1L\n                    )\n                )\n            action vector\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<C4us>, action : NativeVector<uint16> -> 'r) =\n            let vector =\n                NativeVector<uint16>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        4L,\n                        1L\n                    )\n                )\n            action vector\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<C3ui>, action : NativeVector<uint32> -> 'r) =\n            let vector =\n                NativeVector<uint32>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        3L,\n                        1L\n                    )\n                )\n            action vector\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<C4ui>, action : NativeVector<uint32> -> 'r) =\n            let vector =\n                NativeVector<uint32>(\n                    NativePtr.cast &&m,\n                    VectorInfo(\n                        0L,\n                        4L,\n                        1L\n                    )\n                )\n            action vector\n \n        // =======================================================================================\n        // MATRICES\n        // =======================================================================================\n        \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M22d>, action : NativeMatrix<float> -> 'r) =\n            let matrix =\n                NativeMatrix<float>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(2, 2),\n                        V2l(1, 2)\n                    )\n                )\n            action matrix\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M23d>, action : NativeMatrix<float> -> 'r) =\n            let matrix =\n                NativeMatrix<float>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(3, 2),\n                        V2l(1, 3)\n                    )\n                )\n            action matrix\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M33d>, action : NativeMatrix<float> -> 'r) =\n            let matrix =\n                NativeMatrix<float>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(3, 3),\n                        V2l(1, 3)\n                    )\n                )\n            action matrix\n        \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M34d>, action : NativeMatrix<float> -> 'r) =\n            let matrix =\n                NativeMatrix<float>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(4, 3),\n                        V2l(1, 4)\n                    )\n                )\n            action matrix\n        \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M44d>, action : NativeMatrix<float> -> 'r) =\n            let matrix =\n                NativeMatrix<float>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(4, 4),\n                        V2l(1, 4)\n                    )\n                )\n            action matrix\n\n            \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M22f>, action : NativeMatrix<float32> -> 'r) =\n            let matrix =\n                NativeMatrix<float32>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(2, 2),\n                        V2l(1, 2)\n                    )\n                )\n            action matrix\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M23f>, action : NativeMatrix<float32> -> 'r) =\n            let matrix =\n                NativeMatrix<float32>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(3, 2),\n                        V2l(1, 3)\n                    )\n                )\n            action matrix\n \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M33f>, action : NativeMatrix<float32> -> 'r) =\n            let matrix =\n                NativeMatrix<float32>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(3, 3),\n                        V2l(1, 3)\n                    )\n                )\n            action matrix\n        \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M34f>, action : NativeMatrix<float32> -> 'r) =\n            let matrix =\n                NativeMatrix<float32>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(4, 3),\n                        V2l(1, 4)\n                    )\n                )\n            action matrix\n        \n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        static member Using(m : byref<M44f>, action : NativeMatrix<float32> -> 'r) =\n            let matrix =\n                NativeMatrix<float32>(\n                    NativePtr.cast &&m,\n                    MatrixInfo(\n                        0L,\n                        V2l(4, 4),\n                        V2l(1, 4)\n                    )\n                )\n            action matrix\n    \n    module NativeTensor =\n\n        let inline us< ^p, ^m, ^n, ^r, ^x when (^m or ^p) : (static member Using : byref< ^m > * (^n -> ^r) -> ^x) > (p : ^p) (m :  byref< ^m >) (action : ^n -> ^r) : ^x =\n            ((^m or ^p) : (static member Using : byref< ^m >  * (^n -> ^r) -> ^x) (&m, action))\n\n        let inline using (m : byref<_>) action = us Unchecked.defaultof<Pinning> &m action\n        \n        type PinBuilder() =\n            member inline x.Bind(m : byref<_>, f) = using &m f\n            member inline x.Delay(f : unit -> 'a) = f\n            member inline x.Return v = v\n            member inline x.Run(f : unit -> 'a) = f()\n            member inline x.Combine(l : unit, r : unit -> 'a) = r()\n            member inline x.For(s,a) = for e in s do a s\n            member inline x.TryFinally(l : unit -> 'r, r : unit -> unit) = try l() finally r()\n            member inline x.TryWith(l : unit -> 'r, r : exn -> 'r) = try l() with e -> r e\n            member inline x.Using<'a, 'r when 'a :> IDisposable> (a : 'a, f : 'a -> 'r) : 'r = try f a finally a.Dispose()\n            member inline x.While(g,b) = while g() do b()\n            member inline x.Zero() = ()\n\n    let tensor = NativeTensor.PinBuilder()\n\n    let private test() =\n        let mutable a = M22d()\n        let b = M33d()\n            \n        let mutable v2i = V2i()\n        let mutable c3b = C3b.Green\n            \n        let mutable v = Vector<float>()\n        let mutable m = Matrix<float>()\n        let mutable a2d : float[,] = Array2D.zeroCreate 10 10\n        let mutable arr = [|1;2;3|]\n        tensor {\n            try\n                try\n                    use x = { new IDisposable with member x.Dispose() = () }\n                    let! p0 = &a\n                    let! p1 = &arr\n\n                    let! p2 = &v2i\n                    let! p3 = &c3b\n\n                    let! p4 = &m\n                    let! p5 = &v\n                    for i in 1 .. 100 do\n                        let! p6 = &a2d\n                        ()\n\n                    while p4.[0,0] > 1.0 do\n                        let! p7 = &arr\n                        p4.[0,0] <- 1.0\n                        ()\n                    ()\n                with e ->\n                    ()\n            finally\n                printfn \"asdasd\"\n        }\n\n        ()\n\n    type NativeMatrix<'a when 'a : unmanaged> with\n        member x.Transposed = NativeMatrix<'a>(x.Pointer, x.Info.Transposed)\n\n[<AbstractClass; Sealed; Extension>]\ntype NativeTensorExtensions private() =\n\n    [<Extension>]\n    static member MirrorX(this : NativeVector<'a>) =\n        NativeVector<'a>(\n            this.Pointer,\n            VectorInfo(\n                (this.SX - 1L) * this.DX,\n                this.SX,\n                -this.DX\n            )\n        )\n\n    [<Extension>]\n    static member MirrorX(this : NativeMatrix<'a>) =\n        NativeMatrix<'a>(\n            this.Pointer,\n            MatrixInfo(\n                this.Info.Index(this.SX - 1L, 0L),\n                this.Size,\n                V2l(-this.DX, this.DY)\n            )\n        )\n        \n    [<Extension>]\n    static member MirrorX(this : NativeVolume<'a>) =\n        NativeVolume<'a>(\n            this.Pointer,\n            VolumeInfo(\n                this.Info.Index(this.SX - 1L, 0L, 0L),\n                this.Size,\n                V3l(-this.DX, this.DY, this.DZ)\n            )\n        )\n\n    [<Extension>]\n    static member MirrorX(this : NativeTensor4<'a>) =\n        NativeTensor4<'a>(\n            this.Pointer,\n            Tensor4Info(\n                this.Info.Index(this.SX - 1L, 0L, 0L, 0L),\n                this.Size,\n                V4l(-this.DX, this.DY, this.DZ, this.DW)\n            )\n        )\n \n    [<Extension>]\n    static member MirrorY(this : NativeMatrix<'a>) =\n        NativeMatrix<'a>(\n            this.Pointer,\n            MatrixInfo(\n                this.Info.Index(0L, this.SY - 1L),\n                this.Size,\n                V2l(this.DX, -this.DY)\n            )\n        )\n        \n    [<Extension>]\n    static member MirrorY(this : NativeVolume<'a>) =\n        NativeVolume<'a>(\n            this.Pointer,\n            VolumeInfo(\n                this.Info.Index(0L, this.SY - 1L, 0L),\n                this.Size,\n                V3l(this.DX, -this.DY, this.DZ)\n            )\n        )\n        \n    [<Extension>]\n    static member MirrorY(this : NativeTensor4<'a>) =\n        NativeTensor4<'a>(\n            this.Pointer,\n            Tensor4Info(\n                this.Info.Index(0L, this.SY - 1L, 0L, 0L),\n                this.Size,\n                V4l(this.DX, -this.DY, this.DZ, this.DW)\n            )\n        )        \n\n    [<Extension>]\n    static member MirrorZ(this : NativeVolume<'a>) =\n        NativeVolume<'a>(\n            this.Pointer,\n            VolumeInfo(\n                this.Info.Index(0L, 0L, this.SZ - 1L),\n                this.Size,\n                V3l(this.DX, this.DY, -this.DZ)\n            )\n        )\n        \n    [<Extension>]\n    static member MirrorZ(this : NativeTensor4<'a>) =\n        NativeTensor4<'a>(\n            this.Pointer,\n            Tensor4Info(\n                this.Info.Index(0L, 0L, this.SZ - 1L, 0L),\n                this.Size,\n                V4l(this.DX, this.DY, -this.DZ, this.DW)\n            )\n        )\n\n    [<Extension>]\n    static member MirrorW(this : NativeTensor4<'a>) =\n        NativeTensor4<'a>(\n            this.Pointer,\n            Tensor4Info(\n                this.Info.Index(0L, 0L, 0L, this.SW - 1L),\n                this.Size,\n                V4l(this.DX, this.DY, this.DZ, -this.DW)\n            )\n        )\n\n\n\n    [<Extension>]\n    static member ToXYWTensor4(this : NativeVolume<'a>) =\n        let info = this.Info\n        let li = 1L + Vec.dot info.Delta (info.S - V3l.III)\n        \n        NativeTensor4<'a>(\n            this.Pointer,\n            Tensor4Info(\n                info.Origin,\n                V4l(info.SX, info.SY, 1L, info.SZ),\n                V4l(info.DX, info.DY, li, info.DZ)\n            )\n        )"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Native/NativeTensorGenerated.fs",
    "content": "namespace Aardvark.Base\n\nopen Microsoft.FSharp.NativeInterop\nopen System\nopen System.Collections.Concurrent\nopen System.Runtime.InteropServices\nopen System.Reflection\n\n#nowarn \"9\"\n\n[<Sealed>]\ntype NativeVector<'a when 'a : unmanaged>(ptr : nativeptr<'a>, info : VectorInfo) = \n    member x.Pointer = ptr\n    member x.Address = NativePtr.toNativeInt ptr\n    member x.Info = info\n    member x.Size = info.Size\n    member x.Delta = info.Delta\n    member x.Origin = info.Origin\n    member x.SX = info.SX\n    member x.DX = info.DX\n    member inline private x.SetX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n            ptr <- ptr + jX\n    member x.Set(value : 'a) = \n        x.SetX(value)\n    member inline private x.SetByCoordX(getValue : int64 -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = 0L\n        let step = 1L\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n            coord <- coord + step\n            ptr <- ptr + jX\n    member x.SetByCoord(value : int64 -> 'a) = \n        x.SetByCoordX(value)\n    member inline private x.SetByCoordX(getValue : int -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = 0\n        let step = 1\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n            coord <- coord + step\n            ptr <- ptr + jX\n    member x.SetByCoord(value : int -> 'a) = \n        x.SetByCoordX(value)\n    member inline private x.SetByCoordX(getValue : float -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = 0.5 / float(x.Size)\n        let step = 1.0 / float(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n            coord <- coord + step\n            ptr <- ptr + jX\n    member x.SetByCoord(value : float -> 'a) = \n        x.SetByCoordX(value)\n    member inline private x.IterPtrX(action : int64 -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<int64, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = 0L\n        let eX = ptr + sX\n        while ptr <> eX do\n            action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n            coord <- coord + 1L\n            ptr <- ptr + jX\n    member x.IterPtr(action : int64 -> nativeptr<'a> -> unit) = \n        x.IterPtrX(action)\n    member inline private x.IterPtrX(action : int -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<int, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = 0\n        let eX = ptr + sX\n        while ptr <> eX do\n            action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n            coord <- coord + 1\n            ptr <- ptr + jX\n    member x.IterPtr(action : int -> nativeptr<'a> -> unit) = \n        x.IterPtrX(action)\n    member inline private x.IterPtrX(action : float -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<float, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = 0.5 / float(x.Size)\n        let step = 1.0 / float(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n            coord <- coord + step\n            ptr <- ptr + jX\n    member x.IterPtr(action : float -> nativeptr<'a> -> unit) = \n        x.IterPtrX(action)\n    member x.Iter(action : int64 -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member x.Iter(action : int -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member x.Iter(action : float -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member inline private x.IterPtr2X(other : NativeVector<'b>, action : int64 -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<int64, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = 0L\n        let eX = ia + sX\n        while ia <> eX do\n            action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n            coord <- coord + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member x.IterPtr2(other : NativeVector<'b>, action : int64 -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeVector size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        x.IterPtr2X(other, action)\n    member inline private x.IterPtr2X(other : NativeVector<'b>, action : int -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<int, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = 0\n        let eX = ia + sX\n        while ia <> eX do\n            action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n            coord <- coord + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member x.IterPtr2(other : NativeVector<'b>, action : int -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeVector size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        x.IterPtr2X(other, action)\n    member inline private x.IterPtr2X(other : NativeVector<'b>, action : float -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<float, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = 0.5 / float(x.Size)\n        let step = 1.0 / float(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n            coord <- coord + step\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member x.IterPtr2(other : NativeVector<'b>, action : float -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeVector size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        x.IterPtr2X(other, action)\n    member x.Iter2(other : NativeVector<'b>, action : int64 -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member x.Iter2(other : NativeVector<'b>, action : int -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member x.Iter2(other : NativeVector<'b>, action : float -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member inline private x.BlitToInternalX(y : NativeVector<'a>, srcOffset : float, srcSize : float, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (float(x.Size) * srcSize) / float(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * float(x.Size) - 0.5\n        let initialiCoord = int64(floor initialCoord)\n        let initialFrac = initialCoord - float(initialiCoord)\n        let step = 1.0 * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord\n        let yeX = py + ysX\n        while py <> yeX do\n            let v0 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n            let v1 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n            // lerp X\n            let vx = lerp.Invoke(frac, v0, v1)\n            NativePtr.write (NativePtr.ofNativeInt<'a> py) vx\n            py <- py + yjX\n            coord <- coord + step\n            let ni = int64 (floor coord)\n            px <- px + xdX * nativeint (ni - icoord)\n            icoord <- ni\n            frac <- coord - float(icoord)\n    member inline private x.BlitToInternalXE(y : NativeVector<'a>, srcOffset : float, srcSize : float, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (float(x.Size) * srcSize) / float(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * float(x.Size) - 0.5\n        let initialiCoord = int64(floor initialCoord)\n        let initialFrac = initialCoord - float(initialiCoord)\n        let step = 1.0 * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord\n        let yeX = py + ysX\n        while py <> yeX do\n            let v0 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n            NativePtr.write (NativePtr.ofNativeInt<'a> py) v0\n            py <- py + yjX\n            px <- px + xjX\n            coord <- coord + step\n            icoord <- icoord + 1L\n    member inline private x.BlitToX(y : NativeVector<'a>, srcOffset : float, srcSize : float, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size > x.Size then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset = 0.0 && srcSize = 1.0 then x.BlitToInternalXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalX(y, srcOffset, srcSize, lerp)\n    member x.BlitTo(y : NativeVector<'a>, srcOffset : float, srcSize : float, lerp : float -> 'a -> 'a -> 'a) = \n        x.BlitToX(y, srcOffset, srcSize, lerp)\n    member x.BlitTo(y : NativeVector<'a>, lerp : float -> 'a -> 'a -> 'a) = x.BlitTo(y, 0.0, 1.0, lerp)\n    member x.Item\n        with get(c0 : int64) : 'a = \n            let i = x.Delta * c0\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : int64) (value : 'a) =\n            let i = x.Delta * c0\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : int) : 'a = \n            let i = x.Delta * int64(c0)\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : int) (value : 'a) =\n            let i = x.Delta * int64(c0)\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member inline private x.CopyToX(y : NativeVector<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member x.CopyTo(y : NativeVector<'a>) = \n        if info.Size <> y.Size then\n            failwithf \"NativeVector size mismatch: { src = %A; dst = %A }\" info.Size y.Size\n        x.CopyToX(y)\n    member inline private x.CopyToX<'b when 'b : unmanaged>(y : NativeVector<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member x.CopyTo(y : NativeVector<'b>, f : 'a -> 'b) = \n        if info.Size <> y.Size then\n            failwithf \"NativeVector size mismatch: { src = %A; dst = %A }\" info.Size y.Size\n        x.CopyToX(y, f)\n    static member Using<'b> (m : Vector<'a>, f : NativeVector<'a> -> 'b) = \n        let gc = GCHandle.Alloc(m.Data, GCHandleType.Pinned)\n        try f (NativeVector<'a>(NativePtr.ofNativeInt (gc.AddrOfPinnedObject()), m.Info))\n        finally gc.Free()\n    member x.SubVector(beginX : int64, sizeX : int64, deltaX : int64) = NativeVector<'a>(ptr, info.SubVector(beginX, sizeX, deltaX))\n    member x.SubVector(beginX : int64, sizeX : int64) = NativeVector<'a>(ptr, info.SubVector(beginX, sizeX))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let info = VectorInfo(info.Index(beginX), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let info = VectorInfo(info.Index(beginX), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let info = VectorInfo(info.Index(beginX), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let info = VectorInfo(info.Index(beginX), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, src : NativeVector<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let info = VectorInfo(info.Index(beginX), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, src : NativeVector<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let info = VectorInfo(info.Index(beginX), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, src : Vector<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let info = VectorInfo(info.Index(beginX), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, src : Vector<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let info = VectorInfo(info.Index(beginX), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n\n/// The NativeVector module providers convenient F#-style functions for accessing NativeVectors\nmodule NativeVector =\n    /// Creates a new NativeVector from the given address and info struct\n    let inline ofNativeInt<'a when 'a : unmanaged> (info : VectorInfo) (address : nativeint) = NativeVector<'a>(NativePtr.ofNativeInt address, info)\n    \n    let inline private lerpy< ^a, ^b when (^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b)> (_ : ^a) (t : float) (a : ^b) (b : ^b) =\n        ((^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b) (t, a,b))\n    let inline private lerper t a b = lerpy (Unchecked.defaultof<Fun>) t a b\n    /// Sets the entire Vector to the given value\n    let inline set (value : 'a) (dst : NativeVector<'a>) = dst.Set(value)\n    \n    /// Sets each entry to the value computed by getValue\n    let inline setByCoord (getValue : int64 -> 'a) (m : NativeVector<'a>) = m.SetByCoord(getValue)\n    \n    let inline blit (src : NativeVector<'a>) (dst : NativeVector<'a>) = src.BlitTo(dst, lerper)\n    \n    /// Copies the content of 'src' to 'dst'\n    let inline copy (src : NativeVector<'a>) (dst : NativeVector<'a>) = src.CopyTo(dst)\n    \n    /// Copies the content of 'src' to 'dst' by applying the given function\n    let inline copyWith (f : 'a -> 'b) (src : NativeVector<'a>) (dst : NativeVector<'b>) = src.CopyTo(dst, f)\n    \n    /// Temporarily pins a Vector making it available as NativeVector\n    let using (m : Vector<'a>) (f : NativeVector<'a> -> 'b) = NativeVector<'a>.Using(m, f)\n    \n    /// Iterates over all entries of the given NativeVector and executes the given action\n    let inline iter (action : int64 -> 'a -> unit) (m : NativeVector<'a>) = m.Iter(action)\n    \n    /// Iterates over all entries of the given NativeVector and executes the given action\n    let inline iterPtr (action : int64 -> nativeptr<'a> -> unit) (m : NativeVector<'a>) = m.IterPtr(action)\n    \n    /// Iterates over all entries of both of the given NativeVectors and executes the given action\n    let inline iter2 (action : int64 -> 'a -> 'b -> unit) (l : NativeVector<'a>) (r : NativeVector<'b>) = l.Iter2(r, action)\n    \n    /// Iterates over all entries of both of the given NativeVectors and executes the given action\n    let inline iterPtr2 (action : int64 -> nativeptr<'a> -> nativeptr<'b> -> unit) (l : NativeVector<'a>) (r : NativeVector<'b>) = l.IterPtr2(r, action)\n\n\n[<Sealed>]\ntype NativeMatrix<'a when 'a : unmanaged>(ptr : nativeptr<'a>, info : MatrixInfo) = \n    member x.Pointer = ptr\n    member x.Address = NativePtr.toNativeInt ptr\n    member x.Info = info\n    member x.Size = info.Size\n    member x.Delta = info.Delta\n    member x.Origin = info.Origin\n    member x.SX = info.SX\n    member x.SY = info.SY\n    member x.DX = info.DX\n    member x.DY = info.DY\n    member inline private x.SetXY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            while ptr <> eY do\n                NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                ptr <- ptr + jY\n            ptr <- ptr + jX\n    member inline private x.SetYX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            while ptr <> eX do\n                NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                ptr <- ptr + jX\n            ptr <- ptr + jY\n    member x.Set(value : 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.SetXY(value)\n        else x.SetYX(value)\n    member inline private x.SetByCoordXY(getValue : V2l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V2l.Zero\n        let step = V2l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYX(getValue : V2l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V2l.Zero\n        let step = V2l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member x.SetByCoord(value : V2l -> 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.SetByCoordXY(value)\n        else x.SetByCoordYX(value)\n    member inline private x.SetByCoordXY(getValue : V2i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V2i.Zero\n        let step = V2i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYX(getValue : V2i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V2i.Zero\n        let step = V2i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member x.SetByCoord(value : V2i -> 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.SetByCoordXY(value)\n        else x.SetByCoordYX(value)\n    member inline private x.SetByCoordXY(getValue : V2d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V2d(0.5, 0.5) / V2d(x.Size)\n        let step = V2d.One / V2d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYX(getValue : V2d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V2d(0.5, 0.5) / V2d(x.Size)\n        let step = V2d.One / V2d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member x.SetByCoord(value : V2d -> 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.SetByCoordXY(value)\n        else x.SetByCoordYX(value)\n    member inline private x.IterPtrXY(action : V2l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V2l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrYX(action : V2l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V2l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member x.IterPtr(action : V2l -> nativeptr<'a> -> unit) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.IterPtrXY(action)\n        else x.IterPtrYX(action)\n    member inline private x.IterPtrXY(action : V2i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V2i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrYX(action : V2i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V2i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member x.IterPtr(action : V2i -> nativeptr<'a> -> unit) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.IterPtrXY(action)\n        else x.IterPtrYX(action)\n    member inline private x.IterPtrXY(action : V2d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V2d(0.5, 0.5) / V2d(x.Size)\n        let step = V2d.One / V2d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrYX(action : V2d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V2d(0.5, 0.5) / V2d(x.Size)\n        let step = V2d.One / V2d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member x.IterPtr(action : V2d -> nativeptr<'a> -> unit) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.IterPtrXY(action)\n        else x.IterPtrYX(action)\n    member x.Iter(action : V2l -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member x.Iter(action : V2i -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member x.Iter(action : V2d -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member inline private x.IterPtr2XY(other : NativeMatrix<'b>, action : V2l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V2l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YX(other : NativeMatrix<'b>, action : V2l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V2l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member x.IterPtr2(other : NativeMatrix<'b>, action : V2l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeMatrix size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.IterPtr2XY(other, action)\n        else x.IterPtr2YX(other, action)\n    member inline private x.IterPtr2XY(other : NativeMatrix<'b>, action : V2i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V2i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YX(other : NativeMatrix<'b>, action : V2i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V2i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member x.IterPtr2(other : NativeMatrix<'b>, action : V2i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeMatrix size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.IterPtr2XY(other, action)\n        else x.IterPtr2YX(other, action)\n    member inline private x.IterPtr2XY(other : NativeMatrix<'b>, action : V2d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V2d(0.5, 0.5) / V2d(x.Size)\n        let step = V2d.One / V2d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YX(other : NativeMatrix<'b>, action : V2d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V2d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V2d(0.5, 0.5) / V2d(x.Size)\n        let step = V2d.One / V2d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member x.IterPtr2(other : NativeMatrix<'b>, action : V2d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeMatrix size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.IterPtr2XY(other, action)\n        else x.IterPtr2YX(other, action)\n    member x.Iter2(other : NativeMatrix<'b>, action : V2l -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member x.Iter2(other : NativeMatrix<'b>, action : V2i -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member x.Iter2(other : NativeMatrix<'b>, action : V2d -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member inline private x.BlitToInternalXY(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V2d(x.Size) * srcSize) / V2d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V2d(x.Size) - V2d.Half\n        let initialiCoord = V2l(floor initialCoord)\n        let initialFrac = initialCoord - V2d(initialiCoord)\n        let step = V2d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                let v01 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                let v10 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                let v11 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                // lerp X\n                let vx0 = lerp.Invoke(frac.X, v00, v10)\n                let vx1 = lerp.Invoke(frac.X, v01, v11)\n                // lerp Y\n                let vxx = lerp.Invoke(frac.Y, vx0, vx1)\n                NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYE(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V2d(x.Size) * srcSize) / V2d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V2d(x.Size) - V2d.Half\n        let initialiCoord = V2l(floor initialCoord)\n        let initialFrac = initialCoord - V2d(initialiCoord)\n        let step = V2d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                let v10 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                // lerp X\n                let vx0 = lerp.Invoke(frac.X, v00, v10)\n                NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEY(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V2d(x.Size) * srcSize) / V2d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V2d(x.Size) - V2d.Half\n        let initialiCoord = V2l(floor initialCoord)\n        let initialFrac = initialCoord - V2d(initialiCoord)\n        let step = V2d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                let v01 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                // lerp Y\n                let v0x = lerp.Invoke(frac.Y, v00, v01)\n                NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYE(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V2d(x.Size) * srcSize) / V2d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V2d(x.Size) - V2d.Half\n        let initialiCoord = V2l(floor initialCoord)\n        let initialFrac = initialCoord - V2d(initialiCoord)\n        let step = V2d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                NativePtr.write (NativePtr.ofNativeInt<'a> py) v00\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXY(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYX(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V2d(x.Size) * srcSize) / V2d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V2d(x.Size) - V2d.Half\n        let initialiCoord = V2l(floor initialCoord)\n        let initialFrac = initialCoord - V2d(initialiCoord)\n        let step = V2d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                let v01 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                let v10 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                let v11 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                // lerp X\n                let vx0 = lerp.Invoke(frac.X, v00, v10)\n                let vx1 = lerp.Invoke(frac.X, v01, v11)\n                // lerp Y\n                let vxx = lerp.Invoke(frac.Y, vx0, vx1)\n                NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXE(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V2d(x.Size) * srcSize) / V2d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V2d(x.Size) - V2d.Half\n        let initialiCoord = V2l(floor initialCoord)\n        let initialFrac = initialCoord - V2d(initialiCoord)\n        let step = V2d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                let v10 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                // lerp X\n                let vx0 = lerp.Invoke(frac.X, v00, v10)\n                NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEX(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V2d(x.Size) * srcSize) / V2d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V2d(x.Size) - V2d.Half\n        let initialiCoord = V2l(floor initialCoord)\n        let initialFrac = initialCoord - V2d(initialiCoord)\n        let step = V2d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                let v01 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                // lerp Y\n                let v0x = lerp.Invoke(frac.Y, v00, v01)\n                NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXE(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V2d(x.Size) * srcSize) / V2d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V2d(x.Size) - V2d.Half\n        let initialiCoord = V2l(floor initialCoord)\n        let initialFrac = initialCoord - V2d(initialiCoord)\n        let step = V2d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                NativePtr.write (NativePtr.ofNativeInt<'a> py) v00\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYX(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYX(y, srcOffset, srcSize, lerp)\n    member x.BlitTo(y : NativeMatrix<'a>, srcOffset : V2d, srcSize : V2d, lerp : float -> 'a -> 'a -> 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.BlitToXY(y, srcOffset, srcSize, lerp)\n        else x.BlitToYX(y, srcOffset, srcSize, lerp)\n    member x.BlitTo(y : NativeMatrix<'a>, lerp : float -> 'a -> 'a -> 'a) = x.BlitTo(y, V2d.Zero, V2d.One, lerp)\n    member x.Item\n        with get(c0 : V2l) : 'a = \n            let i = Vec.Dot(x.Delta, c0)\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : V2l) (value : 'a) =\n            let i = Vec.Dot(x.Delta, c0)\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : V2i) : 'a = \n            let i = Vec.Dot(x.Delta, V2l(c0))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : V2i) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V2l(c0))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : int, c1 : int) : 'a = \n            let i = Vec.Dot(x.Delta, V2l(c0, c1))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : int, c1 : int) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V2l(c0, c1))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : int64, c1 : int64) : 'a = \n            let i = Vec.Dot(x.Delta, V2l(c0, c1))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : int64, c1 : int64) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V2l(c0, c1))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member inline private x.CopyToXY(y : NativeMatrix<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eY = xptr + sY\n            while xptr <> eY do\n                NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToYX(y : NativeMatrix<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eX = xptr + sX\n            while xptr <> eX do\n                NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member x.CopyTo(y : NativeMatrix<'a>) = \n        if info.Size <> y.Size then\n            failwithf \"NativeMatrix size mismatch: { src = %A; dst = %A }\" info.Size y.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.CopyToXY(y)\n        else x.CopyToYX(y)\n    member inline private x.CopyToXY<'b when 'b : unmanaged>(y : NativeMatrix<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eY = xptr + sY\n            while xptr <> eY do\n                NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToYX<'b when 'b : unmanaged>(y : NativeMatrix<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eX = xptr + sX\n            while xptr <> eX do\n                NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member x.CopyTo(y : NativeMatrix<'b>, f : 'a -> 'b) = \n        if info.Size <> y.Size then\n            failwithf \"NativeMatrix size mismatch: { src = %A; dst = %A }\" info.Size y.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        if cXY >= 0  then x.CopyToXY(y, f)\n        else x.CopyToYX(y, f)\n    member x.SampleNearest(coord : float) : 'a[] = \n        let p0f = coord * float x.Size.X\n        let mutable nearest = int64 (Fun.Round p0f)\n        if nearest < 0L then nearest <- 0L\n        else if nearest >= x.Size.X then nearest <- x.Size.X - 1L\n        let sa = nativeint sizeof<'a>\n        let ptr = NativePtr.toNativeInt x.Pointer + nativeint (nearest * x.Delta.X) * sa\n        let dY = nativeint x.DY * sa\n        Array.init (int x.Size.Y) (fun i -> NativePtr.read (NativePtr.ofNativeInt (ptr + nativeint i * dY)))\n    member x.SampleLinear(coord : V2d, lerp : float -> 'a -> 'a -> 'a) : 'a = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let coord = Fun.Min(Fun.Max(coord, V2d.Zero), V2d.One)\n        let p0f = coord * V2d x.Size.XY - V2d(0.5, 0.5)\n        let mutable p0 = V2l(int64 (floor p0f.X), int64 (floor p0f.Y))\n        let frac = p0f - V2d p0\n        let sa = nativeint sizeof<'a>\n        let dX = nativeint x.DX * sa\n        let dY = nativeint x.DY * sa\n        if p0.X >= 0L && p0.X < x.Size.X - 1L && p0.Y >= 0L && p0.Y < x.Size.Y - 1L then\n            let ptr0 = NativePtr.toNativeInt x.Pointer + nativeint (Vec.Dot(p0, x.Delta.XY)) * sa\n            let v00 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0))\n            let v01 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dY))\n            let v10 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX))\n            let v11 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dY))\n            let vx0 = lerp.Invoke(frac.X, v00, v10)\n            let vx1 = lerp.Invoke(frac.X, v01, v11)\n            let vxx = lerp.Invoke(frac.Y, vx0, vx1)\n            vxx\n        else\n            let max = x.Size - V2l.One\n            let v00 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V2l.Zero, p0), max))) * sa))\n            let v01 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V2l.Zero, p0 + V2l(0L, 1L)), max))) * sa))\n            let v10 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V2l.Zero, p0 + V2l(1L, 0L)), max))) * sa))\n            let v11 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V2l.Zero, p0 + V2l(1L, 1L)), max))) * sa))\n            let vx0 = lerp.Invoke(frac.X, v00, v10)\n            let vx1 = lerp.Invoke(frac.X, v01, v11)\n            let vxx = lerp.Invoke(frac.Y, vx0, vx1)\n            vxx\n    static member Using<'b> (m : Matrix<'a>, f : NativeMatrix<'a> -> 'b) = \n        let gc = GCHandle.Alloc(m.Data, GCHandleType.Pinned)\n        try f (NativeMatrix<'a>(NativePtr.ofNativeInt (gc.AddrOfPinnedObject()), m.Info))\n        finally gc.Free()\n    member x.SubMatrix(beginX : int64, beginY : int64, sizeX : int64, sizeY : int64, deltaX : int64, deltaY : int64) = NativeMatrix<'a>(ptr, info.SubMatrix(beginX, beginY, sizeX, sizeY, deltaX, deltaY))\n    member x.SubMatrix(beginX : int64, beginY : int64, sizeX : int64, sizeY : int64) = NativeMatrix<'a>(ptr, info.SubMatrix(beginX, beginY, sizeX, sizeY))\n    member x.SubMatrix(offset : V2l, size : V2l) = NativeMatrix<'a>(ptr, info.SubMatrix(offset, size))\n    member x.SubMatrix(offset : V2l, size : V2l, delta : V2l) = NativeMatrix<'a>(ptr, info.SubMatrix(offset, size, delta))\n    member x.SubMatrix(offset : V2i, size : V2i) = NativeMatrix<'a>(ptr, info.SubMatrix(offset, size))\n    member x.SubMatrix(offset : V2i, size : V2i, delta : V2i) = NativeMatrix<'a>(ptr, info.SubMatrix(offset, size, delta))\n    member x.GetSlice(minX : int, minY : Option<int>, maxY : Option<int>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, value : 'a) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, src : NativeVector<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, src : NativeVector<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, src : Vector<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, src : Vector<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : int) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let info = VectorInfo(info.Index(beginX, beginY), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let info = VectorInfo(info.Index(beginX, beginY), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, src : NativeVector<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let info = VectorInfo(info.Index(beginX, beginY), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, src : NativeVector<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, src : Vector<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let info = VectorInfo(info.Index(beginX, beginY), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, src : Vector<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let info = VectorInfo(info.Index(beginX, beginY), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let info = MatrixInfo(info.Index(beginX, beginY), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let info = MatrixInfo(info.Index(beginX, beginY), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let info = MatrixInfo(info.Index(beginX, beginY), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let info = MatrixInfo(info.Index(beginX, beginY), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let info = MatrixInfo(info.Index(beginX, beginY), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let info = MatrixInfo(info.Index(beginX, beginY), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let info = MatrixInfo(info.Index(beginX, beginY), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let info = MatrixInfo(info.Index(beginX, beginY), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n\n/// The NativeMatrix module providers convenient F#-style functions for accessing NativeMatrixs\nmodule NativeMatrix =\n    /// Creates a new NativeMatrix from the given address and info struct\n    let inline ofNativeInt<'a when 'a : unmanaged> (info : MatrixInfo) (address : nativeint) = NativeMatrix<'a>(NativePtr.ofNativeInt address, info)\n    \n    let inline private lerpy< ^a, ^b when (^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b)> (_ : ^a) (t : float) (a : ^b) (b : ^b) =\n        ((^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b) (t, a,b))\n    let inline private lerper t a b = lerpy (Unchecked.defaultof<Fun>) t a b\n    /// Sets the entire Matrix to the given value\n    let inline set (value : 'a) (dst : NativeMatrix<'a>) = dst.Set(value)\n    \n    /// Sets each entry to the value computed by getValue\n    let inline setByCoord (getValue : V2l -> 'a) (m : NativeMatrix<'a>) = m.SetByCoord(getValue)\n    \n    let inline sample (location : V2d) (m : NativeMatrix<'a>) = m.SampleLinear(location, lerper)\n    \n    let inline blit (src : NativeMatrix<'a>) (dst : NativeMatrix<'a>) = src.BlitTo(dst, lerper)\n    \n    /// Copies the content of 'src' to 'dst'\n    let inline copy (src : NativeMatrix<'a>) (dst : NativeMatrix<'a>) = src.CopyTo(dst)\n    \n    /// Copies the content of 'src' to 'dst' by applying the given function\n    let inline copyWith (f : 'a -> 'b) (src : NativeMatrix<'a>) (dst : NativeMatrix<'b>) = src.CopyTo(dst, f)\n    \n    /// Temporarily pins a Matrix making it available as NativeMatrix\n    let using (m : Matrix<'a>) (f : NativeMatrix<'a> -> 'b) = NativeMatrix<'a>.Using(m, f)\n    \n    /// Iterates over all entries of the given NativeMatrix and executes the given action\n    let inline iter (action : V2l -> 'a -> unit) (m : NativeMatrix<'a>) = m.Iter(action)\n    \n    /// Iterates over all entries of the given NativeMatrix and executes the given action\n    let inline iterPtr (action : V2l -> nativeptr<'a> -> unit) (m : NativeMatrix<'a>) = m.IterPtr(action)\n    \n    /// Iterates over all entries of both of the given NativeMatrixs and executes the given action\n    let inline iter2 (action : V2l -> 'a -> 'b -> unit) (l : NativeMatrix<'a>) (r : NativeMatrix<'b>) = l.Iter2(r, action)\n    \n    /// Iterates over all entries of both of the given NativeMatrixs and executes the given action\n    let inline iterPtr2 (action : V2l -> nativeptr<'a> -> nativeptr<'b> -> unit) (l : NativeMatrix<'a>) (r : NativeMatrix<'b>) = l.IterPtr2(r, action)\n\n\n[<Sealed>]\ntype NativeVolume<'a when 'a : unmanaged>(ptr : nativeptr<'a>, info : VolumeInfo) = \n    member x.Pointer = ptr\n    member x.Address = NativePtr.toNativeInt ptr\n    member x.Info = info\n    member x.Size = info.Size\n    member x.Delta = info.Delta\n    member x.Origin = info.Origin\n    member x.SX = info.SX\n    member x.SY = info.SY\n    member x.SZ = info.SZ\n    member x.DX = info.DX\n    member x.DY = info.DY\n    member x.DZ = info.DZ\n    member inline private x.SetXYZ(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                while ptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                    ptr <- ptr + jZ\n                ptr <- ptr + jY\n            ptr <- ptr + jX\n    member inline private x.SetYXZ(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                while ptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                    ptr <- ptr + jZ\n                ptr <- ptr + jX\n            ptr <- ptr + jY\n    member inline private x.SetYZX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            while ptr <> eZ do\n                let eX = ptr + sX\n                while ptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                    ptr <- ptr + jX\n                ptr <- ptr + jZ\n            ptr <- ptr + jY\n    member inline private x.SetXZY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            while ptr <> eZ do\n                let eY = ptr + sY\n                while ptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                    ptr <- ptr + jY\n                ptr <- ptr + jZ\n            ptr <- ptr + jX\n    member inline private x.SetZXY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            while ptr <> eX do\n                let eY = ptr + sY\n                while ptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                    ptr <- ptr + jY\n                ptr <- ptr + jX\n            ptr <- ptr + jZ\n    member inline private x.SetZYX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            while ptr <> eY do\n                let eX = ptr + sX\n                while ptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                    ptr <- ptr + jX\n                ptr <- ptr + jY\n            ptr <- ptr + jZ\n    member x.Set(value : 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.SetXYZ(value)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.SetYXZ(value)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.SetYZX(value)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.SetXZY(value)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.SetZXY(value)\n        else x.SetZYX(value)\n    member inline private x.SetByCoordXYZ(getValue : V3l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V3l.Zero\n        let step = V3l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXZ(getValue : V3l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V3l.Zero\n        let step = V3l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZX(getValue : V3l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V3l.Zero\n        let step = V3l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXZY(getValue : V3l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V3l.Zero\n        let step = V3l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXY(getValue : V3l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V3l.Zero\n        let step = V3l.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYX(getValue : V3l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V3l.Zero\n        let step = V3l.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member x.SetByCoord(value : V3l -> 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.SetByCoordXYZ(value)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.SetByCoordYXZ(value)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.SetByCoordYZX(value)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.SetByCoordXZY(value)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.SetByCoordZXY(value)\n        else x.SetByCoordZYX(value)\n    member inline private x.SetByCoordXYZ(getValue : V3i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V3i.Zero\n        let step = V3i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXZ(getValue : V3i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V3i.Zero\n        let step = V3i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZX(getValue : V3i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V3i.Zero\n        let step = V3i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXZY(getValue : V3i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V3i.Zero\n        let step = V3i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXY(getValue : V3i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V3i.Zero\n        let step = V3i.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYX(getValue : V3i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V3i.Zero\n        let step = V3i.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member x.SetByCoord(value : V3i -> 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.SetByCoordXYZ(value)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.SetByCoordYXZ(value)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.SetByCoordYZX(value)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.SetByCoordXZY(value)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.SetByCoordZXY(value)\n        else x.SetByCoordZYX(value)\n    member inline private x.SetByCoordXYZ(getValue : V3d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXZ(getValue : V3d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZX(getValue : V3d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXZY(getValue : V3d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXY(getValue : V3d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYX(getValue : V3d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member x.SetByCoord(value : V3d -> 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.SetByCoordXYZ(value)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.SetByCoordYXZ(value)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.SetByCoordYZX(value)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.SetByCoordXZY(value)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.SetByCoordZXY(value)\n        else x.SetByCoordZYX(value)\n    member inline private x.IterPtrXYZ(action : V3l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V3l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- 0L\n                while ptr <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Z <- coord.Z + 1L\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXZ(action : V3l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V3l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- 0L\n                while ptr <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Z <- coord.Z + 1L\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZX(action : V3l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V3l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- 0L\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- 0L\n                while ptr <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.X <- coord.X + 1L\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + 1L\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member inline private x.IterPtrXZY(action : V3l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V3l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- 0L\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- 0L\n                while ptr <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Y <- coord.Y + 1L\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + 1L\n                ptr <- ptr + jZ\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXY(action : V3l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V3l.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- 0L\n                while ptr <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Y <- coord.Y + 1L\n                    ptr <- ptr + jY\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + 1L\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYX(action : V3l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V3l.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- 0L\n                while ptr <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.X <- coord.X + 1L\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + 1L\n            ptr <- ptr + jZ\n    member x.IterPtr(action : V3l -> nativeptr<'a> -> unit) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.IterPtrXYZ(action)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.IterPtrYXZ(action)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.IterPtrYZX(action)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.IterPtrXZY(action)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.IterPtrZXY(action)\n        else x.IterPtrZYX(action)\n    member inline private x.IterPtrXYZ(action : V3i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V3i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- 0\n                while ptr <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Z <- coord.Z + 1\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXZ(action : V3i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V3i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- 0\n                while ptr <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Z <- coord.Z + 1\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZX(action : V3i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V3i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- 0\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- 0\n                while ptr <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.X <- coord.X + 1\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + 1\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member inline private x.IterPtrXZY(action : V3i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V3i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- 0\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- 0\n                while ptr <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Y <- coord.Y + 1\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + 1\n                ptr <- ptr + jZ\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXY(action : V3i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V3i.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- 0\n                while ptr <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Y <- coord.Y + 1\n                    ptr <- ptr + jY\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + 1\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYX(action : V3i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V3i.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- 0\n                while ptr <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.X <- coord.X + 1\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + 1\n            ptr <- ptr + jZ\n    member x.IterPtr(action : V3i -> nativeptr<'a> -> unit) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.IterPtrXYZ(action)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.IterPtrYXZ(action)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.IterPtrYZX(action)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.IterPtrXZY(action)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.IterPtrZXY(action)\n        else x.IterPtrZYX(action)\n    member inline private x.IterPtrXYZ(action : V3d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXZ(action : V3d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZX(action : V3d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.IterPtrXZY(action : V3d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXY(action : V3d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYX(action : V3d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member x.IterPtr(action : V3d -> nativeptr<'a> -> unit) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.IterPtrXYZ(action)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.IterPtrYXZ(action)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.IterPtrYZX(action)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.IterPtrXZY(action)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.IterPtrZXY(action)\n        else x.IterPtrZYX(action)\n    member x.Iter(action : V3l -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member x.Iter(action : V3i -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member x.Iter(action : V3d -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member inline private x.IterPtr2XYZ(other : NativeVolume<'b>, action : V3l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V3l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- 0L\n                while ia <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Z <- coord.Z + 1L\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXZ(other : NativeVolume<'b>, action : V3l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V3l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- 0L\n                while ia <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Z <- coord.Z + 1L\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZX(other : NativeVolume<'b>, action : V3l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V3l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- 0L\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- 0L\n                while ia <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.X <- coord.X + 1L\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + 1L\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XZY(other : NativeVolume<'b>, action : V3l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V3l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- 0L\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- 0L\n                while ia <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Y <- coord.Y + 1L\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + 1L\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXY(other : NativeVolume<'b>, action : V3l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V3l.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- 0L\n                while ia <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Y <- coord.Y + 1L\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + 1L\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYX(other : NativeVolume<'b>, action : V3l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V3l.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- 0L\n                while ia <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.X <- coord.X + 1L\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + 1L\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member x.IterPtr2(other : NativeVolume<'b>, action : V3l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeVolume size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.IterPtr2XYZ(other, action)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.IterPtr2YXZ(other, action)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.IterPtr2YZX(other, action)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.IterPtr2XZY(other, action)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.IterPtr2ZXY(other, action)\n        else x.IterPtr2ZYX(other, action)\n    member inline private x.IterPtr2XYZ(other : NativeVolume<'b>, action : V3i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V3i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- 0\n                while ia <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Z <- coord.Z + 1\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXZ(other : NativeVolume<'b>, action : V3i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V3i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- 0\n                while ia <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Z <- coord.Z + 1\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZX(other : NativeVolume<'b>, action : V3i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V3i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- 0\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- 0\n                while ia <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.X <- coord.X + 1\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + 1\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XZY(other : NativeVolume<'b>, action : V3i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V3i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- 0\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- 0\n                while ia <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Y <- coord.Y + 1\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + 1\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXY(other : NativeVolume<'b>, action : V3i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V3i.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- 0\n                while ia <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Y <- coord.Y + 1\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + 1\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYX(other : NativeVolume<'b>, action : V3i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V3i.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- 0\n                while ia <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.X <- coord.X + 1\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + 1\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member x.IterPtr2(other : NativeVolume<'b>, action : V3i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeVolume size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.IterPtr2XYZ(other, action)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.IterPtr2YXZ(other, action)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.IterPtr2YZX(other, action)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.IterPtr2XZY(other, action)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.IterPtr2ZXY(other, action)\n        else x.IterPtr2ZYX(other, action)\n    member inline private x.IterPtr2XYZ(other : NativeVolume<'b>, action : V3d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- initialCoord.Z\n                while ia <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Z <- coord.Z + step.Z\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXZ(other : NativeVolume<'b>, action : V3d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- initialCoord.Z\n                while ia <> eZ do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Z <- coord.Z + step.Z\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZX(other : NativeVolume<'b>, action : V3d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- initialCoord.Z\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- initialCoord.X\n                while ia <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.X <- coord.X + step.X\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + step.Z\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XZY(other : NativeVolume<'b>, action : V3d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- initialCoord.Z\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- initialCoord.Y\n                while ia <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Y <- coord.Y + step.Y\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + step.Z\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXY(other : NativeVolume<'b>, action : V3d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- initialCoord.Y\n                while ia <> eY do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.Y <- coord.Y + step.Y\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + step.Z\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYX(other : NativeVolume<'b>, action : V3d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V3d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V3d(0.5, 0.5, 0.5) / V3d(x.Size)\n        let step = V3d.One / V3d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- initialCoord.X\n                while ia <> eX do\n                    action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                    coord.X <- coord.X + step.X\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + step.Z\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member x.IterPtr2(other : NativeVolume<'b>, action : V3d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeVolume size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.IterPtr2XYZ(other, action)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.IterPtr2YXZ(other, action)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.IterPtr2YZX(other, action)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.IterPtr2XZY(other, action)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.IterPtr2ZXY(other, action)\n        else x.IterPtr2ZYX(other, action)\n    member x.Iter2(other : NativeVolume<'b>, action : V3l -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member x.Iter2(other : NativeVolume<'b>, action : V3i -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member x.Iter2(other : NativeVolume<'b>, action : V3d -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member inline private x.BlitToInternalXYZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    let v111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    let vx11 = lerp.Invoke(frac.X, v011, v111)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    let vxx1 = lerp.Invoke(frac.Y, vx01, vx11)\n                    // lerp Z\n                    let vxxx = lerp.Invoke(frac.Z, vxx0, vxx1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYZE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    // lerp Z\n                    let vx0x = lerp.Invoke(frac.Z, vx00, vx01)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEZE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEYZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    let v0x1 = lerp.Invoke(frac.Y, v001, v011)\n                    // lerp Z\n                    let v0xx = lerp.Invoke(frac.Z, v0x0, v0x1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYZE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    // lerp Z\n                    let v00x = lerp.Invoke(frac.Z, v000, v001)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEZE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v000\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXYZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEYZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEYZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXYZE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXYZ(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYXZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    let v111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    let vx11 = lerp.Invoke(frac.X, v011, v111)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    let vxx1 = lerp.Invoke(frac.Y, vx01, vx11)\n                    // lerp Z\n                    let vxxx = lerp.Invoke(frac.Z, vxx0, vxx1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXZE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    // lerp Z\n                    let vx0x = lerp.Invoke(frac.Z, vx00, vx01)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEZE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEXZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    let v0x1 = lerp.Invoke(frac.Y, v001, v011)\n                    // lerp Z\n                    let v0xx = lerp.Invoke(frac.Z, v0x0, v0x1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXZE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    // lerp Z\n                    let v00x = lerp.Invoke(frac.Z, v000, v001)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEZE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v000\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYXZ(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEXZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEXZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYXZE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYXZ(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYZX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    let v111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    let vx11 = lerp.Invoke(frac.X, v011, v111)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    let vxx1 = lerp.Invoke(frac.Y, vx01, vx11)\n                    // lerp Z\n                    let vxxx = lerp.Invoke(frac.Z, vxx0, vxx1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZXE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    // lerp Z\n                    let vx0x = lerp.Invoke(frac.Z, vx00, vx01)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEXE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEZX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    let v0x1 = lerp.Invoke(frac.Y, v001, v011)\n                    // lerp Z\n                    let v0xx = lerp.Invoke(frac.Z, v0x0, v0x1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZXE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    // lerp Z\n                    let v00x = lerp.Invoke(frac.Z, v000, v001)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEXE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v000\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYZX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEZEX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEZXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEZX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYZEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYZXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYZX(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalXZY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    let v111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    let vx11 = lerp.Invoke(frac.X, v011, v111)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    let vxx1 = lerp.Invoke(frac.Y, vx01, vx11)\n                    // lerp Z\n                    let vxxx = lerp.Invoke(frac.Z, vxx0, vxx1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZYE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    // lerp Z\n                    let vx0x = lerp.Invoke(frac.Z, vx00, vx01)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEYE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEZY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    let v0x1 = lerp.Invoke(frac.Y, v001, v011)\n                    // lerp Z\n                    let v0xx = lerp.Invoke(frac.Z, v0x0, v0x1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZYE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    // lerp Z\n                    let v00x = lerp.Invoke(frac.Z, v000, v001)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEYE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v000\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXZY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEZEY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEZYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEZY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXZEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXZYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXZY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalZXY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    let v111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    let vx11 = lerp.Invoke(frac.X, v011, v111)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    let vxx1 = lerp.Invoke(frac.Y, vx01, vx11)\n                    // lerp Z\n                    let vxxx = lerp.Invoke(frac.Z, vxx0, vxx1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXYE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    // lerp Z\n                    let vx0x = lerp.Invoke(frac.Z, vx00, vx01)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEYE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZEXY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    let v0x1 = lerp.Invoke(frac.Y, v001, v011)\n                    // lerp Z\n                    let v0xx = lerp.Invoke(frac.Z, v0x0, v0x1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXYE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    // lerp Z\n                    let v00x = lerp.Invoke(frac.Z, v000, v001)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEYE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v000\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToZXY(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEXEY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEXYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalZEXY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZXEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZXYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalZXY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalZYX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    let v111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    let vx11 = lerp.Invoke(frac.X, v011, v111)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    let vxx1 = lerp.Invoke(frac.Y, vx01, vx11)\n                    // lerp Z\n                    let vxxx = lerp.Invoke(frac.Z, vxx0, vxx1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYXE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx10 = lerp.Invoke(frac.X, v010, v110)\n                    // lerp Y\n                    let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    let vx01 = lerp.Invoke(frac.X, v001, v101)\n                    // lerp Z\n                    let vx0x = lerp.Invoke(frac.Z, vx00, vx01)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEXE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                    // lerp X\n                    let vx00 = lerp.Invoke(frac.X, v000, v100)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZEYX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    let v0x1 = lerp.Invoke(frac.Y, v001, v011)\n                    // lerp Z\n                    let v0xx = lerp.Invoke(frac.Z, v0x0, v0x1)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYXE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                    // lerp Y\n                    let v0x0 = lerp.Invoke(frac.Y, v000, v010)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                    // lerp Z\n                    let v00x = lerp.Invoke(frac.Z, v000, v001)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEXE(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V3d(x.Size) * srcSize) / V3d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V3d(x.Size) - V3d.Half\n        let initialiCoord = V3l(floor initialCoord)\n        let initialFrac = initialCoord - V3d(initialiCoord)\n        let step = V3d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                    NativePtr.write (NativePtr.ofNativeInt<'a> py) v000\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToZYX(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEYEX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEYXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalZEYX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZYEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZYXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalZYX(y, srcOffset, srcSize, lerp)\n    member x.BlitTo(y : NativeVolume<'a>, srcOffset : V3d, srcSize : V3d, lerp : float -> 'a -> 'a -> 'a) = \n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.BlitToXYZ(y, srcOffset, srcSize, lerp)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.BlitToYXZ(y, srcOffset, srcSize, lerp)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.BlitToYZX(y, srcOffset, srcSize, lerp)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.BlitToXZY(y, srcOffset, srcSize, lerp)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.BlitToZXY(y, srcOffset, srcSize, lerp)\n        else x.BlitToZYX(y, srcOffset, srcSize, lerp)\n    member x.BlitTo(y : NativeVolume<'a>, lerp : float -> 'a -> 'a -> 'a) = x.BlitTo(y, V3d.Zero, V3d.One, lerp)\n    member x.Item\n        with get(c0 : V3l) : 'a = \n            let i = Vec.Dot(x.Delta, c0)\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : V3l) (value : 'a) =\n            let i = Vec.Dot(x.Delta, c0)\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : V3i) : 'a = \n            let i = Vec.Dot(x.Delta, V3l(c0))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : V3i) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V3l(c0))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : int, c1 : int, c2 : int) : 'a = \n            let i = Vec.Dot(x.Delta, V3l(c0, c1, c2))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : int, c1 : int, c2 : int) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V3l(c0, c1, c2))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : int64, c1 : int64, c2 : int64) : 'a = \n            let i = Vec.Dot(x.Delta, V3l(c0, c1, c2))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : int64, c1 : int64, c2 : int64) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V3l(c0, c1, c2))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member inline private x.CopyToXYZ(y : NativeVolume<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToYXZ(y : NativeVolume<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYZX(y : NativeVolume<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToXZY(y : NativeVolume<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToZXY(y : NativeVolume<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZYX(y : NativeVolume<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member x.CopyTo(y : NativeVolume<'a>) = \n        if info.Size <> y.Size then\n            failwithf \"NativeVolume size mismatch: { src = %A; dst = %A }\" info.Size y.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.CopyToXYZ(y)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.CopyToYXZ(y)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.CopyToYZX(y)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.CopyToXZY(y)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.CopyToZXY(y)\n        else x.CopyToZYX(y)\n    member inline private x.CopyToXYZ<'b when 'b : unmanaged>(y : NativeVolume<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToYXZ<'b when 'b : unmanaged>(y : NativeVolume<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYZX<'b when 'b : unmanaged>(y : NativeVolume<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToXZY<'b when 'b : unmanaged>(y : NativeVolume<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToZXY<'b when 'b : unmanaged>(y : NativeVolume<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZYX<'b when 'b : unmanaged>(y : NativeVolume<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member x.CopyTo(y : NativeVolume<'b>, f : 'a -> 'b) = \n        if info.Size <> y.Size then\n            failwithf \"NativeVolume size mismatch: { src = %A; dst = %A }\" info.Size y.Size\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        if cXY >= 0  && cXZ >= 0  && cYZ >= 0  then x.CopyToXYZ(y, f)\n        elif cXY <= 0 && cXZ >= 0  && cYZ >= 0  then x.CopyToYXZ(y, f)\n        elif cXY <= 0 && cXZ <= 0 && cYZ >= 0  then x.CopyToYZX(y, f)\n        elif cXY >= 0  && cXZ >= 0  && cYZ <= 0 then x.CopyToXZY(y, f)\n        elif cXY >= 0  && cXZ <= 0 && cYZ <= 0 then x.CopyToZXY(y, f)\n        else x.CopyToZYX(y, f)\n    member x.SampleNearest(coord : V2d) : 'a[] = \n        let p0f = coord * V2d x.Size.XY\n        let mutable nearest = V2l(int64 (Fun.Round p0f.X), int64 (Fun.Round p0f.Y))\n        if nearest.X < 0L then nearest.X <- 0L\n        else if nearest.X >= x.SX then nearest.X <- x.SX - 1L\n        if nearest.Y < 0L then nearest.Y <- 0L\n        else if nearest.Y >= x.SY then nearest.Y <- x.SY - 1L\n        let sa = nativeint sizeof<'a>\n        let ptr = NativePtr.toNativeInt x.Pointer + nativeint (Vec.Dot(nearest, x.Delta.XY)) * sa\n        let dZ = nativeint x.DZ * sa\n        Array.init (int x.Size.Z) (fun i -> NativePtr.read (NativePtr.ofNativeInt (ptr + nativeint i * dZ)))\n    member x.SampleLinear(coord : V3d, lerp : float -> 'a -> 'a -> 'a) : 'a = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let coord = Fun.Min(Fun.Max(coord, V3d.Zero), V3d.One)\n        let p0f = coord * V3d x.Size.XYZ - V3d(0.5, 0.5, 0.5)\n        let mutable p0 = V3l(int64 (floor p0f.X), int64 (floor p0f.Y), int64 (floor p0f.Z))\n        let frac = p0f - V3d p0\n        let sa = nativeint sizeof<'a>\n        let dX = nativeint x.DX * sa\n        let dY = nativeint x.DY * sa\n        let dZ = nativeint x.DZ * sa\n        if p0.X >= 0L && p0.X < x.Size.X - 1L && p0.Y >= 0L && p0.Y < x.Size.Y - 1L && p0.Z >= 0L && p0.Z < x.Size.Z - 1L then\n            let ptr0 = NativePtr.toNativeInt x.Pointer + nativeint (Vec.Dot(p0, x.Delta.XYZ)) * sa\n            let v000 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0))\n            let v001 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dZ))\n            let v010 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dY))\n            let v011 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dY + dZ))\n            let v100 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX))\n            let v101 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dZ))\n            let v110 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dY))\n            let v111 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dY + dZ))\n            let vx00 = lerp.Invoke(frac.X, v000, v100)\n            let vx01 = lerp.Invoke(frac.X, v001, v101)\n            let vx10 = lerp.Invoke(frac.X, v010, v110)\n            let vx11 = lerp.Invoke(frac.X, v011, v111)\n            let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n            let vxx1 = lerp.Invoke(frac.Y, vx01, vx11)\n            let vxxx = lerp.Invoke(frac.Z, vxx0, vxx1)\n            vxxx\n        else\n            let max = x.Size - V3l.One\n            let v000 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V3l.Zero, p0), max))) * sa))\n            let v001 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V3l.Zero, p0 + V3l(0L, 0L, 1L)), max))) * sa))\n            let v010 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V3l.Zero, p0 + V3l(0L, 1L, 0L)), max))) * sa))\n            let v011 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V3l.Zero, p0 + V3l(0L, 1L, 1L)), max))) * sa))\n            let v100 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V3l.Zero, p0 + V3l(1L, 0L, 0L)), max))) * sa))\n            let v101 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V3l.Zero, p0 + V3l(1L, 0L, 1L)), max))) * sa))\n            let v110 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V3l.Zero, p0 + V3l(1L, 1L, 0L)), max))) * sa))\n            let v111 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V3l.Zero, p0 + V3l(1L, 1L, 1L)), max))) * sa))\n            let vx00 = lerp.Invoke(frac.X, v000, v100)\n            let vx01 = lerp.Invoke(frac.X, v001, v101)\n            let vx10 = lerp.Invoke(frac.X, v010, v110)\n            let vx11 = lerp.Invoke(frac.X, v011, v111)\n            let vxx0 = lerp.Invoke(frac.Y, vx00, vx10)\n            let vxx1 = lerp.Invoke(frac.Y, vx01, vx11)\n            let vxxx = lerp.Invoke(frac.Z, vxx0, vxx1)\n            vxxx\n    static member Using<'b> (m : Volume<'a>, f : NativeVolume<'a> -> 'b) = \n        let gc = GCHandle.Alloc(m.Data, GCHandleType.Pinned)\n        try f (NativeVolume<'a>(NativePtr.ofNativeInt (gc.AddrOfPinnedObject()), m.Info))\n        finally gc.Free()\n    member x.SubVolume(beginX : int64, beginY : int64, beginZ : int64, sizeX : int64, sizeY : int64, sizeZ : int64, deltaX : int64, deltaY : int64, deltaZ : int64) = NativeVolume<'a>(ptr, info.SubVolume(beginX, beginY, beginZ, sizeX, sizeY, sizeZ, deltaX, deltaY, deltaZ))\n    member x.SubVolume(beginX : int64, beginY : int64, beginZ : int64, sizeX : int64, sizeY : int64, sizeZ : int64) = NativeVolume<'a>(ptr, info.SubVolume(beginX, beginY, beginZ, sizeX, sizeY, sizeZ))\n    member x.SubVolume(offset : V3l, size : V3l) = NativeVolume<'a>(ptr, info.SubVolume(offset, size))\n    member x.SubVolume(offset : V3l, size : V3l, delta : V3l) = NativeVolume<'a>(ptr, info.SubVolume(offset, size, delta))\n    member x.SubVolume(offset : V3i, size : V3i) = NativeVolume<'a>(ptr, info.SubVolume(offset, size))\n    member x.SubVolume(offset : V3i, size : V3i, delta : V3i) = NativeVolume<'a>(ptr, info.SubVolume(offset, size, delta))\n    member x.GetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, value : 'a) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, src : NativeVector<'a>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, src : NativeVector<'a>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, src : Vector<'a>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, src : Vector<'a>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, value : 'a) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, src : NativeVector<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, src : NativeVector<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, src : Vector<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, src : Vector<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, value : 'a) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, src : NativeMatrix<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, src : NativeMatrix<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, src : Matrix<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, src : Matrix<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, src : NativeVector<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, src : NativeVector<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, src : Vector<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, src : Vector<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, src : NativeVolume<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, src : NativeVolume<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, src : Volume<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, src : Volume<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n\n/// The NativeVolume module providers convenient F#-style functions for accessing NativeVolumes\nmodule NativeVolume =\n    /// Creates a new NativeVolume from the given address and info struct\n    let inline ofNativeInt<'a when 'a : unmanaged> (info : VolumeInfo) (address : nativeint) = NativeVolume<'a>(NativePtr.ofNativeInt address, info)\n    \n    let inline private lerpy< ^a, ^b when (^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b)> (_ : ^a) (t : float) (a : ^b) (b : ^b) =\n        ((^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b) (t, a,b))\n    let inline private lerper t a b = lerpy (Unchecked.defaultof<Fun>) t a b\n    /// Sets the entire Volume to the given value\n    let inline set (value : 'a) (dst : NativeVolume<'a>) = dst.Set(value)\n    \n    /// Sets each entry to the value computed by getValue\n    let inline setByCoord (getValue : V3l -> 'a) (m : NativeVolume<'a>) = m.SetByCoord(getValue)\n    \n    let inline sample (location : V3d) (m : NativeVolume<'a>) = m.SampleLinear(location, lerper)\n    \n    let inline blit (src : NativeVolume<'a>) (dst : NativeVolume<'a>) = src.BlitTo(dst, lerper)\n    \n    /// Copies the content of 'src' to 'dst'\n    let inline copy (src : NativeVolume<'a>) (dst : NativeVolume<'a>) = src.CopyTo(dst)\n    \n    /// Copies the content of 'src' to 'dst' by applying the given function\n    let inline copyWith (f : 'a -> 'b) (src : NativeVolume<'a>) (dst : NativeVolume<'b>) = src.CopyTo(dst, f)\n    \n    /// Temporarily pins a Volume making it available as NativeVolume\n    let using (m : Volume<'a>) (f : NativeVolume<'a> -> 'b) = NativeVolume<'a>.Using(m, f)\n    \n    /// Iterates over all entries of the given NativeVolume and executes the given action\n    let inline iter (action : V3l -> 'a -> unit) (m : NativeVolume<'a>) = m.Iter(action)\n    \n    /// Iterates over all entries of the given NativeVolume and executes the given action\n    let inline iterPtr (action : V3l -> nativeptr<'a> -> unit) (m : NativeVolume<'a>) = m.IterPtr(action)\n    \n    /// Iterates over all entries of both of the given NativeVolumes and executes the given action\n    let inline iter2 (action : V3l -> 'a -> 'b -> unit) (l : NativeVolume<'a>) (r : NativeVolume<'b>) = l.Iter2(r, action)\n    \n    /// Iterates over all entries of both of the given NativeVolumes and executes the given action\n    let inline iterPtr2 (action : V3l -> nativeptr<'a> -> nativeptr<'b> -> unit) (l : NativeVolume<'a>) (r : NativeVolume<'b>) = l.IterPtr2(r, action)\n\n[<AutoOpen>]\nmodule PixImageTensorExtensions =\n    module PixImage =\n        /// Pins the given PixImage as a NativeVolume and executes the given action\n        let inline pin (pi : PixImage<'a>) (f : NativeVolume<'a> -> 'b) : 'b =\n            NativeVolume.using pi.Volume f\n        \n        /// Pins the given PixImages as a NativeVolumes and executes the given action\n        let inline pin2 (l : PixImage<'a>) (r : PixImage<'b>) (f : NativeVolume<'a> -> NativeVolume<'b> -> 'c)  : 'c =\n            pin l (fun lv -> pin r (fun rv -> f lv rv))\n        \n        /// Copies the given PixImage to the given NativeVolume\n        let inline copyToNativeVolume (dst : NativeVolume<'a>) (pix : PixImage<'a>)  =\n            pin pix (fun src -> NativeVolume.copy src dst)\n        \n        /// Copies from the given NativeVolume to the given PixImage\n        let inline copyFromNativeVolume (src : NativeVolume<'a>) (pix : PixImage<'a>) =\n            pin pix (fun dst -> NativeVolume.copy src dst)\n        \n        [<AutoOpen>]\n        module private CopyDispatch =\n            let private flags = BindingFlags.Static ||| BindingFlags.NonPublic ||| BindingFlags.Public\n            \n            type private Dispatcher() =\n                static member CopyImageToNative<'a when 'a : unmanaged>(src : PixImage<'a>, dst : nativeint, dstInfo : VolumeInfo) =\n                    let dst = dst |> NativeVolume.ofNativeInt dstInfo\n                    src |> copyToNativeVolume dst\n                \n                static member CopyNativeToImage<'a when 'a : unmanaged>(src : nativeint, srcInfo : VolumeInfo, dst : PixImage<'a>) =\n                    let src = src |> NativeVolume.ofNativeInt srcInfo\n                    dst |> copyFromNativeVolume src\n            \n            module ImageToNative =\n                let private def = typeof<Dispatcher>.GetMethod(nameof Dispatcher.CopyImageToNative, flags)\n                let private lookup = ConcurrentDictionary<Type, MethodInfo>()\n                let getGenericMethod (t: Type) = lookup.GetOrAdd(t, fun t -> def.MakeGenericMethod t)\n            \n            module NativeToImage =\n                let private def = typeof<Dispatcher>.GetMethod(nameof Dispatcher.CopyNativeToImage, flags)\n                let private lookup = ConcurrentDictionary<Type, MethodInfo>()\n                let getGenericMethod (t: Type) = lookup.GetOrAdd(t, fun t -> def.MakeGenericMethod t)\n            \n        /// Copies the given untyped PixImage to the given native address\n        let copyToNative (dst : nativeint) (dstInfo : VolumeInfo) (pix : PixImage) =\n            let mi = ImageToNative.getGenericMethod pix.PixFormat.Type\n            mi.Invoke(null, [|pix; dst; dstInfo|]) |> ignore\n        \n        /// Copies from the given native address to the given untyped PixImage\n        let copyFromNative (src : nativeint) (srcInfo : VolumeInfo) (pix : PixImage) =\n            let mi = NativeToImage.getGenericMethod pix.PixFormat.Type\n            mi.Invoke(null, [|src; srcInfo; pix|]) |> ignore\n        \n\n\n[<Sealed>]\ntype NativeTensor4<'a when 'a : unmanaged>(ptr : nativeptr<'a>, info : Tensor4Info) = \n    member x.Pointer = ptr\n    member x.Address = NativePtr.toNativeInt ptr\n    member x.Info = info\n    member x.Size = info.Size\n    member x.Delta = info.Delta\n    member x.Origin = info.Origin\n    member x.SX = info.SX\n    member x.SY = info.SY\n    member x.SZ = info.SZ\n    member x.SW = info.SW\n    member x.DX = info.DX\n    member x.DY = info.DY\n    member x.DZ = info.DZ\n    member x.DW = info.DW\n    member inline private x.SetXYZW(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jW\n                    ptr <- ptr + jZ\n                ptr <- ptr + jY\n            ptr <- ptr + jX\n    member inline private x.SetYXZW(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jW\n                    ptr <- ptr + jZ\n                ptr <- ptr + jX\n            ptr <- ptr + jY\n    member inline private x.SetYZXW(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            while ptr <> eZ do\n                let eX = ptr + sX\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jW\n                    ptr <- ptr + jX\n                ptr <- ptr + jZ\n            ptr <- ptr + jY\n    member inline private x.SetYZWX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            while ptr <> eZ do\n                let eW = ptr + sW\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jX\n                    ptr <- ptr + jW\n                ptr <- ptr + jZ\n            ptr <- ptr + jY\n    member inline private x.SetXZYW(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            while ptr <> eZ do\n                let eY = ptr + sY\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jW\n                    ptr <- ptr + jY\n                ptr <- ptr + jZ\n            ptr <- ptr + jX\n    member inline private x.SetZXYW(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            while ptr <> eX do\n                let eY = ptr + sY\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jW\n                    ptr <- ptr + jY\n                ptr <- ptr + jX\n            ptr <- ptr + jZ\n    member inline private x.SetZYXW(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            while ptr <> eY do\n                let eX = ptr + sX\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jW\n                    ptr <- ptr + jX\n                ptr <- ptr + jY\n            ptr <- ptr + jZ\n    member inline private x.SetZYWX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            while ptr <> eY do\n                let eW = ptr + sW\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jX\n                    ptr <- ptr + jW\n                ptr <- ptr + jY\n            ptr <- ptr + jZ\n    member inline private x.SetXZWY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            while ptr <> eZ do\n                let eW = ptr + sW\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jY\n                    ptr <- ptr + jW\n                ptr <- ptr + jZ\n            ptr <- ptr + jX\n    member inline private x.SetZXWY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            while ptr <> eX do\n                let eW = ptr + sW\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jY\n                    ptr <- ptr + jW\n                ptr <- ptr + jX\n            ptr <- ptr + jZ\n    member inline private x.SetZWXY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            while ptr <> eW do\n                let eX = ptr + sX\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jY\n                    ptr <- ptr + jX\n                ptr <- ptr + jW\n            ptr <- ptr + jZ\n    member inline private x.SetZWYX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            while ptr <> eW do\n                let eY = ptr + sY\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jX\n                    ptr <- ptr + jY\n                ptr <- ptr + jW\n            ptr <- ptr + jZ\n    member inline private x.SetXYWZ(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            while ptr <> eY do\n                let eW = ptr + sW\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jZ\n                    ptr <- ptr + jW\n                ptr <- ptr + jY\n            ptr <- ptr + jX\n    member inline private x.SetYXWZ(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            while ptr <> eX do\n                let eW = ptr + sW\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jZ\n                    ptr <- ptr + jW\n                ptr <- ptr + jX\n            ptr <- ptr + jY\n    member inline private x.SetYWXZ(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            while ptr <> eW do\n                let eX = ptr + sX\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jZ\n                    ptr <- ptr + jX\n                ptr <- ptr + jW\n            ptr <- ptr + jY\n    member inline private x.SetYWZX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jX\n                    ptr <- ptr + jZ\n                ptr <- ptr + jW\n            ptr <- ptr + jY\n    member inline private x.SetXWYZ(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            while ptr <> eW do\n                let eY = ptr + sY\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jZ\n                    ptr <- ptr + jY\n                ptr <- ptr + jW\n            ptr <- ptr + jX\n    member inline private x.SetWXYZ(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            while ptr <> eX do\n                let eY = ptr + sY\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jZ\n                    ptr <- ptr + jY\n                ptr <- ptr + jX\n            ptr <- ptr + jW\n    member inline private x.SetWYXZ(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            while ptr <> eY do\n                let eX = ptr + sX\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jZ\n                    ptr <- ptr + jX\n                ptr <- ptr + jY\n            ptr <- ptr + jW\n    member inline private x.SetWYZX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jX\n                    ptr <- ptr + jZ\n                ptr <- ptr + jY\n            ptr <- ptr + jW\n    member inline private x.SetXWZY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jY\n                    ptr <- ptr + jZ\n                ptr <- ptr + jW\n            ptr <- ptr + jX\n    member inline private x.SetWXZY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jY\n                    ptr <- ptr + jZ\n                ptr <- ptr + jX\n            ptr <- ptr + jW\n    member inline private x.SetWZXY(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            while ptr <> eZ do\n                let eX = ptr + sX\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jY\n                    ptr <- ptr + jX\n                ptr <- ptr + jZ\n            ptr <- ptr + jW\n    member inline private x.SetWZYX(value : 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            while ptr <> eZ do\n                let eY = ptr + sY\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\n                        ptr <- ptr + jX\n                    ptr <- ptr + jY\n                ptr <- ptr + jZ\n            ptr <- ptr + jW\n    member x.Set(value : 'a) = \n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetXYZW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetYXZW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetYZXW(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetYZWX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetXZYW(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetZXYW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetZYXW(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetZYWX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetXZWY(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetZXWY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetZWXY(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetZWYX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetXYWZ(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetYXWZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetYWXZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetYWZX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetXWYZ(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetWXYZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetWYXZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetWYZX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetXWZY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetWXZY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetWZXY(value)\n        else x.SetWZYX(value)\n    member inline private x.SetByCoordXYZW(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXZW(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZXW(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZWX(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXZYW(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXYW(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYXW(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYWX(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordXZWY(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXWY(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZWXY(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZWYX(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordXYWZ(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXWZ(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYWXZ(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYWZX(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXWYZ(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordWXYZ(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWYXZ(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWYZX(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordXWZY(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordWXZY(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWZXY(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWZYX(getValue : V4l -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4l.Zero\n        let step = V4l.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member x.SetByCoord(value : V4l -> 'a) = \n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordXYZW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYXZW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYZXW(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYZWX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordXZYW(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZXYW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZYXW(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZYWX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordXZWY(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZXWY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZWXY(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZWYX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordXYWZ(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYXWZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYWXZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYWZX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordXWYZ(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWXYZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWYXZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWYZX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordXWZY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordWXZY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordWZXY(value)\n        else x.SetByCoordWZYX(value)\n    member inline private x.SetByCoordXYZW(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXZW(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZXW(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZWX(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXZYW(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXYW(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYXW(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYWX(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordXZWY(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXWY(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZWXY(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZWYX(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordXYWZ(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXWZ(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYWXZ(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYWZX(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXWYZ(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordWXYZ(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWYXZ(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWYZX(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordXWZY(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordWXZY(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWZXY(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWZYX(getValue : V4i -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4i.Zero\n        let step = V4i.One\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member x.SetByCoord(value : V4i -> 'a) = \n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordXYZW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYXZW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYZXW(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYZWX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordXZYW(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZXYW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZYXW(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZYWX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordXZWY(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZXWY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZWXY(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZWYX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordXYWZ(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYXWZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYWXZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYWZX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordXWYZ(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWXYZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWYXZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWYZX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordXWZY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordWXZY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordWZXY(value)\n        else x.SetByCoordWZYX(value)\n    member inline private x.SetByCoordXYZW(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXZW(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZXW(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYZWX(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXZYW(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXYW(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYXW(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZYWX(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordXZWY(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordZXWY(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZWXY(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordZWYX(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.SetByCoordXYWZ(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordYXWZ(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYWXZ(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordYWZX(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.SetByCoordXWYZ(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordWXYZ(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWYXZ(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWYZX(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordXWZY(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.SetByCoordWXZY(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWZXY(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.SetByCoordWZYX(getValue : V4d -> 'a) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member x.SetByCoord(value : V4d -> 'a) = \n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordXYZW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYXZW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYZXW(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.SetByCoordYZWX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordXZYW(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZXYW(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZYXW(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.SetByCoordZYWX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordXZWY(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZXWY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZWXY(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.SetByCoordZWYX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordXYWZ(value)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYXWZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYWXZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.SetByCoordYWZX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordXWYZ(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWXYZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWYXZ(value)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.SetByCoordWYZX(value)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordXWZY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordWXZY(value)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.SetByCoordWZXY(value)\n        else x.SetByCoordWZYX(value)\n    member inline private x.IterPtrXYZW(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- 0L\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- 0L\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1L\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + 1L\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXZW(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- 0L\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- 0L\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1L\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + 1L\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZXW(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- 0L\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- 0L\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- 0L\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1L\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + 1L\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + 1L\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZWX(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- 0L\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- 0L\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- 0L\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1L\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + 1L\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + 1L\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member inline private x.IterPtrXZYW(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- 0L\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- 0L\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- 0L\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1L\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + 1L\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + 1L\n                ptr <- ptr + jZ\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXYW(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4l.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- 0L\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- 0L\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1L\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + 1L\n                    ptr <- ptr + jY\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + 1L\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYXW(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4l.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- 0L\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- 0L\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1L\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + 1L\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + 1L\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYWX(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4l.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- 0L\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- 0L\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1L\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + 1L\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + 1L\n            ptr <- ptr + jZ\n    member inline private x.IterPtrXZWY(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- 0L\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- 0L\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- 0L\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1L\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + 1L\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + 1L\n                ptr <- ptr + jZ\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXWY(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4l.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- 0L\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- 0L\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1L\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + 1L\n                    ptr <- ptr + jW\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + 1L\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZWXY(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4l.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- 0L\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- 0L\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- 0L\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1L\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + 1L\n                    ptr <- ptr + jX\n                coord.W <- coord.W + 1L\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + 1L\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZWYX(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4l.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- 0L\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- 0L\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- 0L\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1L\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + 1L\n                    ptr <- ptr + jY\n                coord.W <- coord.W + 1L\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + 1L\n            ptr <- ptr + jZ\n    member inline private x.IterPtrXYWZ(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- 0L\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0L\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1L\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + 1L\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXWZ(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- 0L\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0L\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1L\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + 1L\n                    ptr <- ptr + jW\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member inline private x.IterPtrYWXZ(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- 0L\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- 0L\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0L\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1L\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + 1L\n                    ptr <- ptr + jX\n                coord.W <- coord.W + 1L\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member inline private x.IterPtrYWZX(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4l.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- 0L\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- 0L\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- 0L\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1L\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + 1L\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + 1L\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + 1L\n            ptr <- ptr + jY\n    member inline private x.IterPtrXWYZ(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- 0L\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- 0L\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0L\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1L\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + 1L\n                    ptr <- ptr + jY\n                coord.W <- coord.W + 1L\n                ptr <- ptr + jW\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrWXYZ(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4l.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- 0L\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0L\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1L\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + 1L\n                    ptr <- ptr + jY\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.W <- coord.W + 1L\n            ptr <- ptr + jW\n    member inline private x.IterPtrWYXZ(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4l.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- 0L\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0L\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1L\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + 1L\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.W <- coord.W + 1L\n            ptr <- ptr + jW\n    member inline private x.IterPtrWYZX(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4l.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- 0L\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- 0L\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- 0L\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1L\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + 1L\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + 1L\n                ptr <- ptr + jY\n            coord.W <- coord.W + 1L\n            ptr <- ptr + jW\n    member inline private x.IterPtrXWZY(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4l.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- 0L\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- 0L\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- 0L\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1L\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + 1L\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + 1L\n                ptr <- ptr + jW\n            coord.X <- coord.X + 1L\n            ptr <- ptr + jX\n    member inline private x.IterPtrWXZY(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4l.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- 0L\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- 0L\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- 0L\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1L\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + 1L\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + 1L\n                ptr <- ptr + jX\n            coord.W <- coord.W + 1L\n            ptr <- ptr + jW\n    member inline private x.IterPtrWZXY(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4l.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- 0L\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- 0L\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- 0L\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1L\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + 1L\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + 1L\n                ptr <- ptr + jZ\n            coord.W <- coord.W + 1L\n            ptr <- ptr + jW\n    member inline private x.IterPtrWZYX(action : V4l -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4l.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- 0L\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- 0L\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- 0L\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1L\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + 1L\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + 1L\n                ptr <- ptr + jZ\n            coord.W <- coord.W + 1L\n            ptr <- ptr + jW\n    member x.IterPtr(action : V4l -> nativeptr<'a> -> unit) = \n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrXYZW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYXZW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYZXW(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYZWX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrXZYW(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZXYW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZYXW(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZYWX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrXZWY(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZXWY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZWXY(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZWYX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrXYWZ(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYXWZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYWXZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYWZX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrXWYZ(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWXYZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWYXZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWYZX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrXWZY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrWXZY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrWZXY(action)\n        else x.IterPtrWZYX(action)\n    member inline private x.IterPtrXYZW(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- 0\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- 0\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + 1\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXZW(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- 0\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- 0\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + 1\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZXW(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- 0\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- 0\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- 0\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + 1\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + 1\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZWX(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- 0\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- 0\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- 0\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + 1\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + 1\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member inline private x.IterPtrXZYW(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- 0\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- 0\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- 0\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + 1\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + 1\n                ptr <- ptr + jZ\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXYW(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4i.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- 0\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- 0\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + 1\n                    ptr <- ptr + jY\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + 1\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYXW(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let mutable coord = V4i.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- 0\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- 0\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + 1\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + 1\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + 1\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYWX(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4i.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- 0\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- 0\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + 1\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + 1\n            ptr <- ptr + jZ\n    member inline private x.IterPtrXZWY(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- 0\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- 0\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- 0\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + 1\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + 1\n                ptr <- ptr + jZ\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXWY(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4i.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- 0\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- 0\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + 1\n                    ptr <- ptr + jW\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + 1\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZWXY(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4i.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- 0\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- 0\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- 0\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + 1\n                    ptr <- ptr + jX\n                coord.W <- coord.W + 1\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + 1\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZWYX(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4i.Zero\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- 0\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- 0\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- 0\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + 1\n                    ptr <- ptr + jY\n                coord.W <- coord.W + 1\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + 1\n            ptr <- ptr + jZ\n    member inline private x.IterPtrXYWZ(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- 0\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + 1\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXWZ(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- 0\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + 1\n                    ptr <- ptr + jW\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member inline private x.IterPtrYWXZ(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- 0\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- 0\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + 1\n                    ptr <- ptr + jX\n                coord.W <- coord.W + 1\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member inline private x.IterPtrYWZX(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4i.Zero\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- 0\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- 0\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- 0\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + 1\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + 1\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + 1\n            ptr <- ptr + jY\n    member inline private x.IterPtrXWYZ(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- 0\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- 0\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + 1\n                    ptr <- ptr + jY\n                coord.W <- coord.W + 1\n                ptr <- ptr + jW\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrWXYZ(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4i.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- 0\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + 1\n                    ptr <- ptr + jY\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.W <- coord.W + 1\n            ptr <- ptr + jW\n    member inline private x.IterPtrWYXZ(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let mutable coord = V4i.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- 0\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- 0\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + 1\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + 1\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.W <- coord.W + 1\n            ptr <- ptr + jW\n    member inline private x.IterPtrWYZX(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4i.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- 0\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- 0\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- 0\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + 1\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + 1\n                ptr <- ptr + jY\n            coord.W <- coord.W + 1\n            ptr <- ptr + jW\n    member inline private x.IterPtrXWZY(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4i.Zero\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- 0\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- 0\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- 0\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + 1\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + 1\n                ptr <- ptr + jW\n            coord.X <- coord.X + 1\n            ptr <- ptr + jX\n    member inline private x.IterPtrWXZY(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4i.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- 0\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- 0\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- 0\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + 1\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + 1\n                ptr <- ptr + jX\n            coord.W <- coord.W + 1\n            ptr <- ptr + jW\n    member inline private x.IterPtrWZXY(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let mutable coord = V4i.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- 0\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- 0\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- 0\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + 1\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + 1\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + 1\n                ptr <- ptr + jZ\n            coord.W <- coord.W + 1\n            ptr <- ptr + jW\n    member inline private x.IterPtrWZYX(action : V4i -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let mutable coord = V4i.Zero\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- 0\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- 0\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- 0\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + 1\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + 1\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + 1\n                ptr <- ptr + jZ\n            coord.W <- coord.W + 1\n            ptr <- ptr + jW\n    member x.IterPtr(action : V4i -> nativeptr<'a> -> unit) = \n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrXYZW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYXZW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYZXW(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYZWX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrXZYW(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZXYW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZYXW(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZYWX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrXZWY(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZXWY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZWXY(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZWYX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrXYWZ(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYXWZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYWXZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYWZX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrXWYZ(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWXYZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWYXZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWYZX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrXWZY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrWXZY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrWZXY(action)\n        else x.IterPtrWZYX(action)\n    member inline private x.IterPtrXYZW(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXZW(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZXW(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.IterPtrYZWX(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.IterPtrXZYW(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXYW(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYXW(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eW = ptr + sW\n                    coord.W <- initialCoord.W\n                    while ptr <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.W <- coord.W + step.W\n                        ptr <- ptr + jW\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZYWX(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.IterPtrXZWY(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrZXWY(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZWXY(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.IterPtrZWYX(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ptr + sZ\n        while ptr <> eZ do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Z <- coord.Z + step.Z\n            ptr <- ptr + jZ\n    member inline private x.IterPtrXYWZ(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrYXWZ(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eW = ptr + sW\n                coord.W <- initialCoord.W\n                while ptr <> eW do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.W <- coord.W + step.W\n                    ptr <- ptr + jW\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.IterPtrYWXZ(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.IterPtrYWZX(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ptr + sY\n        while ptr <> eY do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.Y <- coord.Y + step.Y\n            ptr <- ptr + jY\n    member inline private x.IterPtrXWYZ(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrWXYZ(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.IterPtrWYXZ(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eZ = ptr + sZ\n                    coord.Z <- initialCoord.Z\n                    while ptr <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Z <- coord.Z + step.Z\n                        ptr <- ptr + jZ\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.IterPtrWYZX(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eY = ptr + sY\n            coord.Y <- initialCoord.Y\n            while ptr <> eY do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.Y <- coord.Y + step.Y\n                ptr <- ptr + jY\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.IterPtrXWZY(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SW * info.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ptr + sX\n        while ptr <> eX do\n            let eW = ptr + sW\n            coord.W <- initialCoord.W\n            while ptr <> eW do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.W <- coord.W + step.W\n                ptr <- ptr + jW\n            coord.X <- coord.X + step.X\n            ptr <- ptr + jX\n    member inline private x.IterPtrWXZY(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eX = ptr + sX\n            coord.X <- initialCoord.X\n            while ptr <> eX do\n                let eZ = ptr + sZ\n                coord.Z <- initialCoord.Z\n                while ptr <> eZ do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.Z <- coord.Z + step.Z\n                    ptr <- ptr + jZ\n                coord.X <- coord.X + step.X\n                ptr <- ptr + jX\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.IterPtrWZXY(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eX = ptr + sX\n                coord.X <- initialCoord.X\n                while ptr <> eX do\n                    let eY = ptr + sY\n                    coord.Y <- initialCoord.Y\n                    while ptr <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.Y <- coord.Y + step.Y\n                        ptr <- ptr + jY\n                    coord.X <- coord.X + step.X\n                    ptr <- ptr + jX\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member inline private x.IterPtrWZYX(action : V4d -> nativeptr<'a> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let mutable ptr = ptr |> NativePtr.toNativeInt\n        ptr <- ptr + nativeint info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jY = nativeint (info.DY - info.SX * info.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jX = nativeint (info.DX) * sa\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ptr + sW\n        while ptr <> eW do\n            let eZ = ptr + sZ\n            coord.Z <- initialCoord.Z\n            while ptr <> eZ do\n                let eY = ptr + sY\n                coord.Y <- initialCoord.Y\n                while ptr <> eY do\n                    let eX = ptr + sX\n                    coord.X <- initialCoord.X\n                    while ptr <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\n                        coord.X <- coord.X + step.X\n                        ptr <- ptr + jX\n                    coord.Y <- coord.Y + step.Y\n                    ptr <- ptr + jY\n                coord.Z <- coord.Z + step.Z\n                ptr <- ptr + jZ\n            coord.W <- coord.W + step.W\n            ptr <- ptr + jW\n    member x.IterPtr(action : V4d -> nativeptr<'a> -> unit) = \n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrXYZW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYXZW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYZXW(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtrYZWX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrXZYW(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZXYW(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZYXW(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtrZYWX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrXZWY(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZXWY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZWXY(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtrZWYX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrXYWZ(action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYXWZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYWXZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtrYWZX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrXWYZ(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWXYZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWYXZ(action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtrWYZX(action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrXWZY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrWXZY(action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtrWZXY(action)\n        else x.IterPtrWZYX(action)\n    member x.Iter(action : V4l -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member x.Iter(action : V4i -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member x.Iter(action : V4d -> 'a -> unit) = \n        x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\n    member inline private x.IterPtr2XYZW(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- 0L\n                while ia <> eZ do\n                    let eW = ia + sW\n                    coord.W <- 0L\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1L\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Z <- coord.Z + 1L\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXZW(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- 0L\n                while ia <> eZ do\n                    let eW = ia + sW\n                    coord.W <- 0L\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1L\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Z <- coord.Z + 1L\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZXW(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- 0L\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- 0L\n                while ia <> eX do\n                    let eW = ia + sW\n                    coord.W <- 0L\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1L\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.X <- coord.X + 1L\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + 1L\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZWX(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- 0L\n            while ia <> eZ do\n                let eW = ia + sW\n                coord.W <- 0L\n                while ia <> eW do\n                    let eX = ia + sX\n                    coord.X <- 0L\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1L\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.W <- coord.W + 1L\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Z <- coord.Z + 1L\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XZYW(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- 0L\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- 0L\n                while ia <> eY do\n                    let eW = ia + sW\n                    coord.W <- 0L\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1L\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Y <- coord.Y + 1L\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + 1L\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXYW(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4l.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- 0L\n                while ia <> eY do\n                    let eW = ia + sW\n                    coord.W <- 0L\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1L\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Y <- coord.Y + 1L\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + 1L\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYXW(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4l.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- 0L\n                while ia <> eX do\n                    let eW = ia + sW\n                    coord.W <- 0L\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1L\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.X <- coord.X + 1L\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + 1L\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYWX(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4l.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                let eW = ia + sW\n                coord.W <- 0L\n                while ia <> eW do\n                    let eX = ia + sX\n                    coord.X <- 0L\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1L\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.W <- coord.W + 1L\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + 1L\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2XZWY(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- 0L\n            while ia <> eZ do\n                let eW = ia + sW\n                coord.W <- 0L\n                while ia <> eW do\n                    let eY = ia + sY\n                    coord.Y <- 0L\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1L\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.W <- coord.W + 1L\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Z <- coord.Z + 1L\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXWY(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4l.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                let eW = ia + sW\n                coord.W <- 0L\n                while ia <> eW do\n                    let eY = ia + sY\n                    coord.Y <- 0L\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1L\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.W <- coord.W + 1L\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + 1L\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZWXY(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4l.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eW = ia + sW\n            coord.W <- 0L\n            while ia <> eW do\n                let eX = ia + sX\n                coord.X <- 0L\n                while ia <> eX do\n                    let eY = ia + sY\n                    coord.Y <- 0L\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1L\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.X <- coord.X + 1L\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.W <- coord.W + 1L\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Z <- coord.Z + 1L\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZWYX(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4l.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eW = ia + sW\n            coord.W <- 0L\n            while ia <> eW do\n                let eY = ia + sY\n                coord.Y <- 0L\n                while ia <> eY do\n                    let eX = ia + sX\n                    coord.X <- 0L\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1L\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Y <- coord.Y + 1L\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.W <- coord.W + 1L\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Z <- coord.Z + 1L\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2XYWZ(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                let eW = ia + sW\n                coord.W <- 0L\n                while ia <> eW do\n                    let eZ = ia + sZ\n                    coord.Z <- 0L\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1L\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.W <- coord.W + 1L\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXWZ(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                let eW = ia + sW\n                coord.W <- 0L\n                while ia <> eW do\n                    let eZ = ia + sZ\n                    coord.Z <- 0L\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1L\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.W <- coord.W + 1L\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YWXZ(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eW = ia + sW\n            coord.W <- 0L\n            while ia <> eW do\n                let eX = ia + sX\n                coord.X <- 0L\n                while ia <> eX do\n                    let eZ = ia + sZ\n                    coord.Z <- 0L\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1L\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.X <- coord.X + 1L\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.W <- coord.W + 1L\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YWZX(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4l.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eW = ia + sW\n            coord.W <- 0L\n            while ia <> eW do\n                let eZ = ia + sZ\n                coord.Z <- 0L\n                while ia <> eZ do\n                    let eX = ia + sX\n                    coord.X <- 0L\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1L\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Z <- coord.Z + 1L\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.W <- coord.W + 1L\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Y <- coord.Y + 1L\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XWYZ(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eW = ia + sW\n            coord.W <- 0L\n            while ia <> eW do\n                let eY = ia + sY\n                coord.Y <- 0L\n                while ia <> eY do\n                    let eZ = ia + sZ\n                    coord.Z <- 0L\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1L\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.Y <- coord.Y + 1L\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.W <- coord.W + 1L\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2WXYZ(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4l.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- 0L\n                while ia <> eY do\n                    let eZ = ia + sZ\n                    coord.Z <- 0L\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1L\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.Y <- coord.Y + 1L\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.W <- coord.W + 1L\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WYXZ(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4l.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- 0L\n                while ia <> eX do\n                    let eZ = ia + sZ\n                    coord.Z <- 0L\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1L\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.X <- coord.X + 1L\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.W <- coord.W + 1L\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WYZX(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4l.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eY = ia + sY\n            coord.Y <- 0L\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- 0L\n                while ia <> eZ do\n                    let eX = ia + sX\n                    coord.X <- 0L\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1L\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Z <- coord.Z + 1L\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + 1L\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.W <- coord.W + 1L\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2XWZY(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4l.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eW = ia + sW\n            coord.W <- 0L\n            while ia <> eW do\n                let eZ = ia + sZ\n                coord.Z <- 0L\n                while ia <> eZ do\n                    let eY = ia + sY\n                    coord.Y <- 0L\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1L\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.Z <- coord.Z + 1L\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.W <- coord.W + 1L\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.X <- coord.X + 1L\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2WXZY(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4l.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eX = ia + sX\n            coord.X <- 0L\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- 0L\n                while ia <> eZ do\n                    let eY = ia + sY\n                    coord.Y <- 0L\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1L\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.Z <- coord.Z + 1L\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + 1L\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.W <- coord.W + 1L\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WZXY(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4l.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eZ = ia + sZ\n            coord.Z <- 0L\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- 0L\n                while ia <> eX do\n                    let eY = ia + sY\n                    coord.Y <- 0L\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1L\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.X <- coord.X + 1L\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + 1L\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.W <- coord.W + 1L\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WZYX(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4l, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4l.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eZ = ia + sZ\n            coord.Z <- 0L\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- 0L\n                while ia <> eY do\n                    let eX = ia + sX\n                    coord.X <- 0L\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1L\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Y <- coord.Y + 1L\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + 1L\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.W <- coord.W + 1L\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member x.IterPtr2(other : NativeTensor4<'b>, action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeTensor4 size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2XYZW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YXZW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YZXW(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YZWX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2XZYW(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZXYW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZYXW(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZYWX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2XZWY(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZXWY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZWXY(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZWYX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2XYWZ(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YXWZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YWXZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YWZX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2XWYZ(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WXYZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WYXZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WYZX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2XWZY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2WXZY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2WZXY(other, action)\n        else x.IterPtr2WZYX(other, action)\n    member inline private x.IterPtr2XYZW(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- 0\n                while ia <> eZ do\n                    let eW = ia + sW\n                    coord.W <- 0\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Z <- coord.Z + 1\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXZW(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- 0\n                while ia <> eZ do\n                    let eW = ia + sW\n                    coord.W <- 0\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Z <- coord.Z + 1\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZXW(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- 0\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- 0\n                while ia <> eX do\n                    let eW = ia + sW\n                    coord.W <- 0\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.X <- coord.X + 1\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + 1\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZWX(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- 0\n            while ia <> eZ do\n                let eW = ia + sW\n                coord.W <- 0\n                while ia <> eW do\n                    let eX = ia + sX\n                    coord.X <- 0\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.W <- coord.W + 1\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Z <- coord.Z + 1\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XZYW(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- 0\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- 0\n                while ia <> eY do\n                    let eW = ia + sW\n                    coord.W <- 0\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Y <- coord.Y + 1\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + 1\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXYW(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4i.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- 0\n                while ia <> eY do\n                    let eW = ia + sW\n                    coord.W <- 0\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Y <- coord.Y + 1\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + 1\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYXW(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let mutable coord = V4i.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- 0\n                while ia <> eX do\n                    let eW = ia + sW\n                    coord.W <- 0\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + 1\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.X <- coord.X + 1\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + 1\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYWX(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4i.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                let eW = ia + sW\n                coord.W <- 0\n                while ia <> eW do\n                    let eX = ia + sX\n                    coord.X <- 0\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.W <- coord.W + 1\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + 1\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2XZWY(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- 0\n            while ia <> eZ do\n                let eW = ia + sW\n                coord.W <- 0\n                while ia <> eW do\n                    let eY = ia + sY\n                    coord.Y <- 0\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.W <- coord.W + 1\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Z <- coord.Z + 1\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXWY(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4i.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                let eW = ia + sW\n                coord.W <- 0\n                while ia <> eW do\n                    let eY = ia + sY\n                    coord.Y <- 0\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.W <- coord.W + 1\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + 1\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZWXY(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4i.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eW = ia + sW\n            coord.W <- 0\n            while ia <> eW do\n                let eX = ia + sX\n                coord.X <- 0\n                while ia <> eX do\n                    let eY = ia + sY\n                    coord.Y <- 0\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.X <- coord.X + 1\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.W <- coord.W + 1\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Z <- coord.Z + 1\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZWYX(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4i.Zero\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eW = ia + sW\n            coord.W <- 0\n            while ia <> eW do\n                let eY = ia + sY\n                coord.Y <- 0\n                while ia <> eY do\n                    let eX = ia + sX\n                    coord.X <- 0\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Y <- coord.Y + 1\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.W <- coord.W + 1\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Z <- coord.Z + 1\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2XYWZ(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                let eW = ia + sW\n                coord.W <- 0\n                while ia <> eW do\n                    let eZ = ia + sZ\n                    coord.Z <- 0\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.W <- coord.W + 1\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXWZ(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                let eW = ia + sW\n                coord.W <- 0\n                while ia <> eW do\n                    let eZ = ia + sZ\n                    coord.Z <- 0\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.W <- coord.W + 1\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YWXZ(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eW = ia + sW\n            coord.W <- 0\n            while ia <> eW do\n                let eX = ia + sX\n                coord.X <- 0\n                while ia <> eX do\n                    let eZ = ia + sZ\n                    coord.Z <- 0\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.X <- coord.X + 1\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.W <- coord.W + 1\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YWZX(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4i.Zero\n        let eY = ia + sY\n        while ia <> eY do\n            let eW = ia + sW\n            coord.W <- 0\n            while ia <> eW do\n                let eZ = ia + sZ\n                coord.Z <- 0\n                while ia <> eZ do\n                    let eX = ia + sX\n                    coord.X <- 0\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Z <- coord.Z + 1\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.W <- coord.W + 1\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Y <- coord.Y + 1\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XWYZ(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eW = ia + sW\n            coord.W <- 0\n            while ia <> eW do\n                let eY = ia + sY\n                coord.Y <- 0\n                while ia <> eY do\n                    let eZ = ia + sZ\n                    coord.Z <- 0\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.Y <- coord.Y + 1\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.W <- coord.W + 1\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2WXYZ(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4i.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- 0\n                while ia <> eY do\n                    let eZ = ia + sZ\n                    coord.Z <- 0\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.Y <- coord.Y + 1\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.W <- coord.W + 1\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WYXZ(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let mutable coord = V4i.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- 0\n                while ia <> eX do\n                    let eZ = ia + sZ\n                    coord.Z <- 0\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + 1\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.X <- coord.X + 1\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.W <- coord.W + 1\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WYZX(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4i.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eY = ia + sY\n            coord.Y <- 0\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- 0\n                while ia <> eZ do\n                    let eX = ia + sX\n                    coord.X <- 0\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Z <- coord.Z + 1\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + 1\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.W <- coord.W + 1\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2XWZY(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4i.Zero\n        let eX = ia + sX\n        while ia <> eX do\n            let eW = ia + sW\n            coord.W <- 0\n            while ia <> eW do\n                let eZ = ia + sZ\n                coord.Z <- 0\n                while ia <> eZ do\n                    let eY = ia + sY\n                    coord.Y <- 0\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.Z <- coord.Z + 1\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.W <- coord.W + 1\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.X <- coord.X + 1\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2WXZY(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4i.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eX = ia + sX\n            coord.X <- 0\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- 0\n                while ia <> eZ do\n                    let eY = ia + sY\n                    coord.Y <- 0\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.Z <- coord.Z + 1\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + 1\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.W <- coord.W + 1\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WZXY(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let mutable coord = V4i.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eZ = ia + sZ\n            coord.Z <- 0\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- 0\n                while ia <> eX do\n                    let eY = ia + sY\n                    coord.Y <- 0\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + 1\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.X <- coord.X + 1\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + 1\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.W <- coord.W + 1\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WZYX(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4i, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let mutable coord = V4i.Zero\n        let eW = ia + sW\n        while ia <> eW do\n            let eZ = ia + sZ\n            coord.Z <- 0\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- 0\n                while ia <> eY do\n                    let eX = ia + sX\n                    coord.X <- 0\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + 1\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Y <- coord.Y + 1\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + 1\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.W <- coord.W + 1\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member x.IterPtr2(other : NativeTensor4<'b>, action : V4i -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeTensor4 size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2XYZW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YXZW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YZXW(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YZWX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2XZYW(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZXYW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZYXW(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZYWX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2XZWY(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZXWY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZWXY(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZWYX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2XYWZ(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YXWZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YWXZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YWZX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2XWYZ(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WXYZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WYXZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WYZX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2XWZY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2WXZY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2WZXY(other, action)\n        else x.IterPtr2WZYX(other, action)\n    member inline private x.IterPtr2XYZW(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- initialCoord.Z\n                while ia <> eZ do\n                    let eW = ia + sW\n                    coord.W <- initialCoord.W\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + step.W\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Z <- coord.Z + step.Z\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXZW(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- initialCoord.Z\n                while ia <> eZ do\n                    let eW = ia + sW\n                    coord.W <- initialCoord.W\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + step.W\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Z <- coord.Z + step.Z\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZXW(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- initialCoord.Z\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- initialCoord.X\n                while ia <> eX do\n                    let eW = ia + sW\n                    coord.W <- initialCoord.W\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + step.W\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.X <- coord.X + step.X\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + step.Z\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YZWX(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eZ = ia + sZ\n            coord.Z <- initialCoord.Z\n            while ia <> eZ do\n                let eW = ia + sW\n                coord.W <- initialCoord.W\n                while ia <> eW do\n                    let eX = ia + sX\n                    coord.X <- initialCoord.X\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + step.X\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.W <- coord.W + step.W\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Z <- coord.Z + step.Z\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XZYW(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- initialCoord.Z\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- initialCoord.Y\n                while ia <> eY do\n                    let eW = ia + sW\n                    coord.W <- initialCoord.W\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + step.W\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Y <- coord.Y + step.Y\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + step.Z\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXYW(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- initialCoord.Y\n                while ia <> eY do\n                    let eW = ia + sW\n                    coord.W <- initialCoord.W\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + step.W\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.Y <- coord.Y + step.Y\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + step.Z\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYXW(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW) * sa\n        let jbW = nativeint (other.Info.DW) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- initialCoord.X\n                while ia <> eX do\n                    let eW = ia + sW\n                    coord.W <- initialCoord.W\n                    while ia <> eW do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.W <- coord.W + step.W\n                        ia <- ia + jaW\n                        ib <- ib + jbW\n                    coord.X <- coord.X + step.X\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + step.Z\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZYWX(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                let eW = ia + sW\n                coord.W <- initialCoord.W\n                while ia <> eW do\n                    let eX = ia + sX\n                    coord.X <- initialCoord.X\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + step.X\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.W <- coord.W + step.W\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.Z <- coord.Z + step.Z\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2XZWY(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eZ = ia + sZ\n            coord.Z <- initialCoord.Z\n            while ia <> eZ do\n                let eW = ia + sW\n                coord.W <- initialCoord.W\n                while ia <> eW do\n                    let eY = ia + sY\n                    coord.Y <- initialCoord.Y\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + step.Y\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.W <- coord.W + step.W\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Z <- coord.Z + step.Z\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2ZXWY(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                let eW = ia + sW\n                coord.W <- initialCoord.W\n                while ia <> eW do\n                    let eY = ia + sY\n                    coord.Y <- initialCoord.Y\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + step.Y\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.W <- coord.W + step.W\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Z <- coord.Z + step.Z\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZWXY(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eW = ia + sW\n            coord.W <- initialCoord.W\n            while ia <> eW do\n                let eX = ia + sX\n                coord.X <- initialCoord.X\n                while ia <> eX do\n                    let eY = ia + sY\n                    coord.Y <- initialCoord.Y\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + step.Y\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.X <- coord.X + step.X\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.W <- coord.W + step.W\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Z <- coord.Z + step.Z\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2ZWYX(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eZ = ia + sZ\n        while ia <> eZ do\n            let eW = ia + sW\n            coord.W <- initialCoord.W\n            while ia <> eW do\n                let eY = ia + sY\n                coord.Y <- initialCoord.Y\n                while ia <> eY do\n                    let eX = ia + sX\n                    coord.X <- initialCoord.X\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + step.X\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Y <- coord.Y + step.Y\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.W <- coord.W + step.W\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Z <- coord.Z + step.Z\n            ia <- ia + jaZ\n            ib <- ib + jbZ\n    member inline private x.IterPtr2XYWZ(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                let eW = ia + sW\n                coord.W <- initialCoord.W\n                while ia <> eW do\n                    let eZ = ia + sZ\n                    coord.Z <- initialCoord.Z\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + step.Z\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.W <- coord.W + step.W\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2YXWZ(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                let eW = ia + sW\n                coord.W <- initialCoord.W\n                while ia <> eW do\n                    let eZ = ia + sZ\n                    coord.Z <- initialCoord.Z\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + step.Z\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.W <- coord.W + step.W\n                    ia <- ia + jaW\n                    ib <- ib + jbW\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YWXZ(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eW = ia + sW\n            coord.W <- initialCoord.W\n            while ia <> eW do\n                let eX = ia + sX\n                coord.X <- initialCoord.X\n                while ia <> eX do\n                    let eZ = ia + sZ\n                    coord.Z <- initialCoord.Z\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + step.Z\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.X <- coord.X + step.X\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.W <- coord.W + step.W\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2YWZX(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SW * info.DW) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eY = ia + sY\n        while ia <> eY do\n            let eW = ia + sW\n            coord.W <- initialCoord.W\n            while ia <> eW do\n                let eZ = ia + sZ\n                coord.Z <- initialCoord.Z\n                while ia <> eZ do\n                    let eX = ia + sX\n                    coord.X <- initialCoord.X\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + step.X\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Z <- coord.Z + step.Z\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.W <- coord.W + step.W\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.Y <- coord.Y + step.Y\n            ia <- ia + jaY\n            ib <- ib + jbY\n    member inline private x.IterPtr2XWYZ(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eW = ia + sW\n            coord.W <- initialCoord.W\n            while ia <> eW do\n                let eY = ia + sY\n                coord.Y <- initialCoord.Y\n                while ia <> eY do\n                    let eZ = ia + sZ\n                    coord.Z <- initialCoord.Z\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + step.Z\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.Y <- coord.Y + step.Y\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.W <- coord.W + step.W\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2WXYZ(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ia + sW\n        while ia <> eW do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                let eY = ia + sY\n                coord.Y <- initialCoord.Y\n                while ia <> eY do\n                    let eZ = ia + sZ\n                    coord.Z <- initialCoord.Z\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + step.Z\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.Y <- coord.Y + step.Y\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.W <- coord.W + step.W\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WYXZ(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ) * sa\n        let jbZ = nativeint (other.Info.DZ) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ia + sW\n        while ia <> eW do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                let eX = ia + sX\n                coord.X <- initialCoord.X\n                while ia <> eX do\n                    let eZ = ia + sZ\n                    coord.Z <- initialCoord.Z\n                    while ia <> eZ do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Z <- coord.Z + step.Z\n                        ia <- ia + jaZ\n                        ib <- ib + jbZ\n                    coord.X <- coord.X + step.X\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.W <- coord.W + step.W\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WYZX(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SY * info.DY) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ia + sW\n        while ia <> eW do\n            let eY = ia + sY\n            coord.Y <- initialCoord.Y\n            while ia <> eY do\n                let eZ = ia + sZ\n                coord.Z <- initialCoord.Z\n                while ia <> eZ do\n                    let eX = ia + sX\n                    coord.X <- initialCoord.X\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + step.X\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Z <- coord.Z + step.Z\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.Y <- coord.Y + step.Y\n                ia <- ia + jaY\n                ib <- ib + jbY\n            coord.W <- coord.W + step.W\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2XWZY(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SW * info.DW) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SW * other.Info.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eX = ia + sX\n        while ia <> eX do\n            let eW = ia + sW\n            coord.W <- initialCoord.W\n            while ia <> eW do\n                let eZ = ia + sZ\n                coord.Z <- initialCoord.Z\n                while ia <> eZ do\n                    let eY = ia + sY\n                    coord.Y <- initialCoord.Y\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + step.Y\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.Z <- coord.Z + step.Z\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.W <- coord.W + step.W\n                ia <- ia + jaW\n                ib <- ib + jbW\n            coord.X <- coord.X + step.X\n            ia <- ia + jaX\n            ib <- ib + jbX\n    member inline private x.IterPtr2WXZY(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SX * info.DX) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ia + sW\n        while ia <> eW do\n            let eX = ia + sX\n            coord.X <- initialCoord.X\n            while ia <> eX do\n                let eZ = ia + sZ\n                coord.Z <- initialCoord.Z\n                while ia <> eZ do\n                    let eY = ia + sY\n                    coord.Y <- initialCoord.Y\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + step.Y\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.Z <- coord.Z + step.Z\n                    ia <- ia + jaZ\n                    ib <- ib + jbZ\n                coord.X <- coord.X + step.X\n                ia <- ia + jaX\n                ib <- ib + jbX\n            coord.W <- coord.W + step.W\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WZXY(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX - info.SY * info.DY) * sa\n        let jbX = nativeint (other.Info.DX - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY) * sa\n        let jbY = nativeint (other.Info.DY) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ia + sW\n        while ia <> eW do\n            let eZ = ia + sZ\n            coord.Z <- initialCoord.Z\n            while ia <> eZ do\n                let eX = ia + sX\n                coord.X <- initialCoord.X\n                while ia <> eX do\n                    let eY = ia + sY\n                    coord.Y <- initialCoord.Y\n                    while ia <> eY do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.Y <- coord.Y + step.Y\n                        ia <- ia + jaY\n                        ib <- ib + jbY\n                    coord.X <- coord.X + step.X\n                    ia <- ia + jaX\n                    ib <- ib + jbX\n                coord.Z <- coord.Z + step.Z\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.W <- coord.W + step.W\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member inline private x.IterPtr2WZYX(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        let action = OptimizedClosures.FSharpFunc<V4d, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\n        let sa = nativeint (sizeof<'a>)\n        let sb = nativeint (sizeof<'b>)\n        let mutable ia = ptr |> NativePtr.toNativeInt\n        let mutable ib = other.Pointer |> NativePtr.toNativeInt\n        ia <- ia + nativeint info.Origin * sa\n        ib <- ib + nativeint other.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let jaW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let jbW = nativeint (other.Info.DW - other.Info.SZ * other.Info.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let jaZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let jbZ = nativeint (other.Info.DZ - other.Info.SY * other.Info.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let jaY = nativeint (info.DY - info.SX * info.DX) * sa\n        let jbY = nativeint (other.Info.DY - other.Info.SX * other.Info.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let jaX = nativeint (info.DX) * sa\n        let jbX = nativeint (other.Info.DX) * sb\n        let initialCoord = V4d(0.5, 0.5, 0.5, 0.5) / V4d(x.Size)\n        let step = V4d.One / V4d(x.Size)\n        let mutable coord = initialCoord\n        let eW = ia + sW\n        while ia <> eW do\n            let eZ = ia + sZ\n            coord.Z <- initialCoord.Z\n            while ia <> eZ do\n                let eY = ia + sY\n                coord.Y <- initialCoord.Y\n                while ia <> eY do\n                    let eX = ia + sX\n                    coord.X <- initialCoord.X\n                    while ia <> eX do\n                        action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\n                        coord.X <- coord.X + step.X\n                        ia <- ia + jaX\n                        ib <- ib + jbX\n                    coord.Y <- coord.Y + step.Y\n                    ia <- ia + jaY\n                    ib <- ib + jbY\n                coord.Z <- coord.Z + step.Z\n                ia <- ia + jaZ\n                ib <- ib + jbZ\n            coord.W <- coord.W + step.W\n            ia <- ia + jaW\n            ib <- ib + jbW\n    member x.IterPtr2(other : NativeTensor4<'b>, action : V4d -> nativeptr<'a> -> nativeptr<'b> -> unit) = \n        if info.Size <> other.Info.Size then\n            failwithf \"NativeTensor4 size mismatch: { src = %A; dst = %A }\" info.Size other.Info.Size\n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2XYZW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YXZW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YZXW(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.IterPtr2YZWX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2XZYW(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZXYW(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZYXW(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZYWX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2XZWY(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZXWY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZWXY(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.IterPtr2ZWYX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2XYWZ(other, action)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YXWZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YWXZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.IterPtr2YWZX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2XWYZ(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WXYZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WYXZ(other, action)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.IterPtr2WYZX(other, action)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2XWZY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2WXZY(other, action)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.IterPtr2WZXY(other, action)\n        else x.IterPtr2WZYX(other, action)\n    member x.Iter2(other : NativeTensor4<'b>, action : V4l -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member x.Iter2(other : NativeTensor4<'b>, action : V4i -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member x.Iter2(other : NativeTensor4<'b>, action : V4d -> 'a -> 'b -> unit) = \n        x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\n    member inline private x.BlitToInternalXYZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYZWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYZEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYZEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEZWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEZEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEZEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEYZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYZWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYZEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYZEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEZWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEZEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEZEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXYZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEYEZEWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEYEZEW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEYEZWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEYZEWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXYEZEWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEYEZW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEYZEW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEYZWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXYEZEW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXYEZWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXYZEWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEYZW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXYEZW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXYZEW(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXYZWE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXYZW(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYXZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXZWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXZEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXZEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEZWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEZEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEZEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEXZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXZWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXZEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXZEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEZWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEZEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEZEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYXZW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEXEZEWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEXEZEW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEXEZWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEXZEWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYXEZEWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEXEZW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEXZEW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEXZWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYXEZEW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYXEZWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYXZEWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEXZW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYXEZW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYXZEW(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYXZWE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYXZW(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYZXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZXWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZXEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZXEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEXWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEXEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEXEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEZXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZXWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZXEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZXEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEXWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEXEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEXEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYZXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEZEXEWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEZEXEW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEZEXWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEZXEWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYZEXEWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEZEXW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEZXEW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEZXWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYZEXEW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYZEXWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYZXEWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEZXW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYZEXW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYZXEW(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYZXWE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYZXW(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYZWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZWXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZWEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZWEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEWXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEWEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYZEWEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEZWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZWXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZWEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZWEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEWXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEWEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEZEWEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYZWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEZEWEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEZEWEX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEZEWXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEZWEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYZEWEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEZEWX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEZWEX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEZWXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYZEWEX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYZEWXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYZWEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEZWX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYZEWX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYZWEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYZWXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYZWX(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalXZYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZYWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZYEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZYEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEYWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEYEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEYEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEZYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZYWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZYEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZYEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEYWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEYEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEYEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXZYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEZEYEWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEZEYEW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEZEYWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEZYEWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXZEYEWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEZEYW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEZYEW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEZYWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXZEYEW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXZEYWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXZYEWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEZYW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXZEYW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXZYEW(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXZYWE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXZYW(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalZXYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXYWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXYEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXYEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEYWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEYEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEYEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZEXYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXYWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXYEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXYEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEYWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEYEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEYEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToZXYW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEXEYEWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEXEYEW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEXEYWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEXYEWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZXEYEWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEXEYW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEXYEW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEXYWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZXEYEW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZXEYWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZXYEWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalZEXYW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZXEYW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZXYEW(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZXYWE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalZXYW(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalZYXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYXWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYXEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYXEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEXWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEXEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEXEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZEYXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYXWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYXEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYXEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEXWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEXEW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    frac.W <- initialFrac.W\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjW\n                        coord.W <- coord.W + step.W\n                        let ni = int64 (floor coord.W)\n                        px <- px + xdW * nativeint (ni - icoord.W)\n                        icoord.W <- ni\n                        frac.W <- coord.W - float(icoord.W)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEXEWE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint y.DW * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeW = py + ysW\n                    coord.W <- initialCoord.W\n                    px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                    icoord.W <- initialiCoord.W\n                    while py <> yeW do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjW\n                        px <- px + xjW\n                        coord.W <- coord.W + step.W\n                        icoord.W <- icoord.W + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToZYXW(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEYEXEWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEYEXEW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEYEXWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEYXEWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZYEXEWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEYEXW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEYXEW(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEYXWE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZYEXEW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZYEXWE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZYXEWE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalZEYXW(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZYEXW(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZYXEW(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZYXWE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalZYXW(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalZYWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYWXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYWEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYWEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEWXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEWEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZYEWEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZEYWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYWXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYWEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYWEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEWXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEWEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEYEWEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToZYWX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEYEWEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEYEWEX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEYEWXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEYWEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZYEWEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEYEWX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEYWEX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEYWXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZYEWEX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZYEWXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZYWEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalZEYWX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZYEWX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZYWEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZYWXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalZYWX(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalXZWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZWYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZWEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZWEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEWYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEWEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXZEWEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEZWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZWYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZWEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZWEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEWYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEWEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEZEWEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXZWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEZEWEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEZEWEY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEZEWYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEZWEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXZEWEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEZEWY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEZWEY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEZWYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXZEWEY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXZEWYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXZWEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEZWY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXZEWY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXZWEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXZWYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXZWY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalZXWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXWYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXWEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXWEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEWYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEWEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZXEWEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZEXWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXWYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXWEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXWEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEWYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEWEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEXEWEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToZXWY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEXEWEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEXEWEY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEXEWYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEXWEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZXEWEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEXEWY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEXWEY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEXWYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZXEWEY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZXEWYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZXWEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalZEXWY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZXEWY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZXWEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZXWYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalZXWY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalZWXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWXYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWXEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWXEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWEXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWEXYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWEXEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWEXEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZEWXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWXYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWXEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWXEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWEXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWEXYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWEXEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWEXEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToZWXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEWEXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEWEXEY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEWEXYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEWXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZWEXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEWEXY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEWXEY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEWXYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZWEXEY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZWEXYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZWXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalZEWXY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZWEXY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZWXEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZWXYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalZWXY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalZWYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWYXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWYEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWYEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWEYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWEYXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWEYEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZWEYEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            coord.Z <- coord.Z + step.Z\n            let ni = int64 (floor coord.Z)\n            px <- px + xdZ * nativeint (ni - icoord.Z)\n            icoord.Z <- ni\n            frac.Z <- coord.Z - float(icoord.Z)\n    member inline private x.BlitToInternalZEWYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWYXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWYEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWYEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWEYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWEYXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWEYEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToInternalZEWEYEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SW * x.DW) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdZ * nativeint icoord.Z + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeZ = py + ysZ\n        while py <> yeZ do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjZ\n            px <- px + xjZ\n            coord.Z <- coord.Z + step.Z\n            icoord.Z <- icoord.Z + 1L\n    member inline private x.BlitToZWYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEWEYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEWEYEX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEWEYXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEWYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZWEYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZEWEYX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZEWYEX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZEWYXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZWEYEX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZWEYXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZWYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalZEWYX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalZWEYX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalZWYEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalZWYXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalZWYX(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalXYWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYWZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYWEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYWEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEWZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEWEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXYEWEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEYWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYWZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYWEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYWEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEWZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEWEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEYEWEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXYWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEYEWEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEYEWEZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEYEWZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEYWEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXYEWEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEYEWZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEYWEZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEYWZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXYEWEZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXYEWZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXYWEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEYWZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXYEWZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXYWEZ(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXYWZE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXYWZ(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYXWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXWZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXWEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXWEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEWZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEWEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYXEWEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEXWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXWZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXWEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXWEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEWZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                frac.W <- initialFrac.W\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    coord.W <- coord.W + step.W\n                    let ni = int64 (floor coord.W)\n                    px <- px + xdW * nativeint (ni - icoord.W)\n                    icoord.W <- ni\n                    frac.W <- coord.W - float(icoord.W)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEWEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEXEWEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeW = py + ysW\n                coord.W <- initialCoord.W\n                px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n                icoord.W <- initialiCoord.W\n                while py <> yeW do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjW\n                    px <- px + xjW\n                    coord.W <- coord.W + step.W\n                    icoord.W <- icoord.W + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYXWZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEXEWEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEXEWEZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEXEWZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEXWEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYXEWEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEXEWZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEXWEZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEXWZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYXEWEZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYXEWZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYXWEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEXWZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYXEWZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYXWEZ(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYXWZE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYXWZ(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYWXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWXZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWXEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWXEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWEXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWEXZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWEXEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWEXEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEWXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWXZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWXEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWXEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWEXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWEXZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWEXEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWEXEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYWXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEWEXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEWEXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEWEXZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEWXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYWEXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEWEXZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEWXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEWXZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYWEXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYWEXZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYWXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEWXZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYWEXZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYWXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYWXZE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYWXZ(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalYWZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWZXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWZEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWZEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWEZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWEZXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWEZEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYWEZEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            coord.Y <- coord.Y + step.Y\n            let ni = int64 (floor coord.Y)\n            px <- px + xdY * nativeint (ni - icoord.Y)\n            icoord.Y <- ni\n            frac.Y <- coord.Y - float(icoord.Y)\n    member inline private x.BlitToInternalYEWZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWZXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWZEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWZEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWEZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWEZXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWEZEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToInternalYEWEZEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SW * x.DW) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdY * nativeint icoord.Y + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeY = py + ysY\n        while py <> yeY do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjY\n            px <- px + xjY\n            coord.Y <- coord.Y + step.Y\n            icoord.Y <- icoord.Y + 1L\n    member inline private x.BlitToYWZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEWEZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEWEZEX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEWEZXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEWZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYWEZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYEWEZX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYEWZEX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYEWZXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYWEZEX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYWEZXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYWZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalYEWZX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalYWEZX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalYWZEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalYWZXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalYWZX(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalXWYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWYZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWYEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWYEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWEYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWEYZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWEYEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWEYEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEWYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWYZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWYEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWYEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWEYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWEYZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWEYEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWEYEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXWYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEWEYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEWEYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEWEYZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEWYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXWEYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEWEYZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEWYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEWYZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXWEYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXWEYZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXWYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEWYZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXWEYZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXWYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXWYZE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXWYZ(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalWXYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXYZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXYEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXYEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXEYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXEYZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXEYEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXEYEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWEXYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXYZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXYEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXYEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXEYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXEYZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXEYEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXEYEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToWXYZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEXEYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEXEYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEXEYZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEXYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWXEYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEXEYZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEXYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEXYZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWXEYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWXEYZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWXYEZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalWEXYZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWXEYZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWXYEZ(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWXYZE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalWXYZ(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalWYXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYXZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYXEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYXEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYEXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYEXZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYEXEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYEXEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWEYXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYXZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYXEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYXEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYEXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYEXZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYEXEZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    frac.Z <- initialFrac.Z\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjZ\n                        coord.Z <- coord.Z + step.Z\n                        let ni = int64 (floor coord.Z)\n                        px <- px + xdZ * nativeint (ni - icoord.Z)\n                        icoord.Z <- ni\n                        frac.Z <- coord.Z - float(icoord.Z)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYEXEZE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint y.DZ * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeZ = py + ysZ\n                    coord.Z <- initialCoord.Z\n                    px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                    icoord.Z <- initialiCoord.Z\n                    while py <> yeZ do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjZ\n                        px <- px + xjZ\n                        coord.Z <- coord.Z + step.Z\n                        icoord.Z <- icoord.Z + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToWYXZ(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEYEXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEYEXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEYEXZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEYXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWYEXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEYEXZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEYXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEYXZE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWYEXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWYEXZE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWYXEZE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalWEYXZ(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWYEXZ(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWYXEZ(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWYXZE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalWYXZ(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalWYZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYZXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYZEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYZEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYEZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYEZXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYEZEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWYEZEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWEYZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYZXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYZEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYZEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            frac.Y <- initialFrac.Y\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                coord.Y <- coord.Y + step.Y\n                let ni = int64 (floor coord.Y)\n                px <- px + xdY * nativeint (ni - icoord.Y)\n                icoord.Y <- ni\n                frac.Y <- coord.Y - float(icoord.Y)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYEZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYEZXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYEZEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEYEZEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SY * x.DY) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SZ * x.DZ) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdY * nativeint icoord.Y + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeY = py + ysY\n            coord.Y <- initialCoord.Y\n            px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n            icoord.Y <- initialiCoord.Y\n            while py <> yeY do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjY\n                px <- px + xjY\n                coord.Y <- coord.Y + step.Y\n                icoord.Y <- icoord.Y + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToWYZX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEYEZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEYEZEX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEYEZXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEYZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWYEZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEYEZX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEYZEX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEYZXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWYEZEX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWYEZXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWYZEXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalWEYZX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWYEZX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWYZEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWYZXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalWYZX(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalXWZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWZYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWZEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWZEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWEZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWEZYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWEZEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXWEZEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            coord.X <- coord.X + step.X\n            let ni = int64 (floor coord.X)\n            px <- px + xdX * nativeint (ni - icoord.X)\n            icoord.X <- ni\n            frac.X <- coord.X - float(icoord.X)\n    member inline private x.BlitToInternalXEWZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWZYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWZEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWZEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            frac.W <- initialFrac.W\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                coord.W <- coord.W + step.W\n                let ni = int64 (floor coord.W)\n                px <- px + xdW * nativeint (ni - icoord.W)\n                icoord.W <- ni\n                frac.W <- coord.W - float(icoord.W)\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWEZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWEZYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWEZEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToInternalXEWEZEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SW * x.DW) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdX * nativeint icoord.X + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeX = py + ysX\n        while py <> yeX do\n            let yeW = py + ysW\n            coord.W <- initialCoord.W\n            px <- px + xdW * nativeint (initialiCoord.W - icoord.W)\n            icoord.W <- initialiCoord.W\n            while py <> yeW do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjW\n                px <- px + xjW\n                coord.W <- coord.W + step.W\n                icoord.W <- icoord.W + 1L\n            py <- py + yjX\n            px <- px + xjX\n            coord.X <- coord.X + step.X\n            icoord.X <- icoord.X + 1L\n    member inline private x.BlitToXWZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEWEZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEWEZEY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEWEZYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEWZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXWEZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXEWEZY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXEWZEY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXEWZYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXWEZEY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXWEZYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXWZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalXEWZY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalXWEZY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalXWZEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalXWZYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalXWZY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalWXZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXZYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXZEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXZEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXEZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXEZYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXEZEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWXEZEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWEXZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXZYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXZEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXZEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            frac.X <- initialFrac.X\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                coord.X <- coord.X + step.X\n                let ni = int64 (floor coord.X)\n                px <- px + xdX * nativeint (ni - icoord.X)\n                icoord.X <- ni\n                frac.X <- coord.X - float(icoord.X)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXEZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXEZYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                frac.Z <- initialFrac.Z\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    coord.Z <- coord.Z + step.Z\n                    let ni = int64 (floor coord.Z)\n                    px <- px + xdZ * nativeint (ni - icoord.Z)\n                    icoord.Z <- ni\n                    frac.Z <- coord.Z - float(icoord.Z)\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXEZEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEXEZEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SX * x.DX) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SZ * x.DZ) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdX * nativeint icoord.X + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeX = py + ysX\n            coord.X <- initialCoord.X\n            px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n            icoord.X <- initialiCoord.X\n            while py <> yeX do\n                let yeZ = py + ysZ\n                coord.Z <- initialCoord.Z\n                px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n                icoord.Z <- initialiCoord.Z\n                while py <> yeZ do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjZ\n                    px <- px + xjZ\n                    coord.Z <- coord.Z + step.Z\n                    icoord.Z <- icoord.Z + 1L\n                py <- py + yjX\n                px <- px + xjX\n                coord.X <- coord.X + step.X\n                icoord.X <- icoord.X + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToWXZY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEXEZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEXEZEY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEXEZYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEXZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWXEZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEXEZY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEXZEY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEXZYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWXEZEY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWXEZYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWXZEYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalWEXZY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWXEZY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWXZEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWXZYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalWXZY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalWZXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZXYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZXEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZXEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZEXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZEXYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZEXEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZEXEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWEZXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZXYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZXEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZXEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZEXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZEXYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                frac.X <- initialFrac.X\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    coord.X <- coord.X + step.X\n                    let ni = int64 (floor coord.X)\n                    px <- px + xdX * nativeint (ni - icoord.X)\n                    icoord.X <- ni\n                    frac.X <- coord.X - float(icoord.X)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZEXEY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    frac.Y <- initialFrac.Y\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjY\n                        coord.Y <- coord.Y + step.Y\n                        let ni = int64 (floor coord.Y)\n                        px <- px + xdY * nativeint (ni - icoord.Y)\n                        icoord.Y <- ni\n                        frac.Y <- coord.Y - float(icoord.Y)\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZEXEYE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SX * x.DX) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint (x.DX - x.SY * x.DY) * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint y.DY * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdX * nativeint icoord.X + xdY * nativeint icoord.Y\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeX = py + ysX\n                coord.X <- initialCoord.X\n                px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                icoord.X <- initialiCoord.X\n                while py <> yeX do\n                    let yeY = py + ysY\n                    coord.Y <- initialCoord.Y\n                    px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                    icoord.Y <- initialiCoord.Y\n                    while py <> yeY do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjY\n                        px <- px + xjY\n                        coord.Y <- coord.Y + step.Y\n                        icoord.Y <- icoord.Y + 1L\n                    py <- py + yjX\n                    px <- px + xjX\n                    coord.X <- coord.X + step.X\n                    icoord.X <- icoord.X + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToWZXY(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEZEXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEZEXEY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEZEXYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEZXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWZEXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEZEXY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEZXEY(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEZXYE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWZEXEY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWZEXYE(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWZXEYE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalWEZXY(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWZEXY(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWZXEY(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWZXYE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalWZXY(y, srcOffset, srcSize, lerp)\n    member inline private x.BlitToInternalWZYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n                        // lerp W\n                        let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZYXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n                        // lerp Z\n                        let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxxx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZYEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n                        // lerp W\n                        let vxx0x = lerp.Invoke(frac.W, vxx00, vxx01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZYEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdY))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n                        // lerp Y\n                        let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vxx00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZEYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        let vx0x1 = lerp.Invoke(frac.Z, vx001, vx011)\n                        // lerp W\n                        let vx0xx = lerp.Invoke(frac.W, vx0x0, vx0x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZEYXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdZ))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n                        // lerp Z\n                        let vx0x0 = lerp.Invoke(frac.Z, vx000, vx010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx0x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZEYEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX + xdW))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n                        // lerp W\n                        let vx00x = lerp.Invoke(frac.W, vx000, vx001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx00x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWZEYEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdX))\n                        // lerp X\n                        let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) vx000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            coord.W <- coord.W + step.W\n            let ni = int64 (floor coord.W)\n            px <- px + xdW * nativeint (ni - icoord.W)\n            icoord.W <- ni\n            frac.W <- coord.W - float(icoord.W)\n    member inline private x.BlitToInternalWEZYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        let v0x11 = lerp.Invoke(frac.Y, v0011, v0111)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        let v0xx1 = lerp.Invoke(frac.Z, v0x01, v0x11)\n                        // lerp W\n                        let v0xxx = lerp.Invoke(frac.W, v0xx0, v0xx1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xxx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZYXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdZ))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x10 = lerp.Invoke(frac.Y, v0010, v0110)\n                        // lerp Z\n                        let v0xx0 = lerp.Invoke(frac.Z, v0x00, v0x10)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0xx0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZYEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY + xdW))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        let v0x01 = lerp.Invoke(frac.Y, v0001, v0101)\n                        // lerp W\n                        let v0x0x = lerp.Invoke(frac.W, v0x00, v0x01)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x0x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZYEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            frac.Z <- initialFrac.Z\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdY))\n                        // lerp Y\n                        let v0x00 = lerp.Invoke(frac.Y, v0000, v0100)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0x00\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                coord.Z <- coord.Z + step.Z\n                let ni = int64 (floor coord.Z)\n                px <- px + xdZ * nativeint (ni - icoord.Z)\n                icoord.Z <- ni\n                frac.Z <- coord.Z - float(icoord.Z)\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZEYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ + xdW))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        let v00x1 = lerp.Invoke(frac.Z, v0001, v0011)\n                        // lerp W\n                        let v00xx = lerp.Invoke(frac.W, v00x0, v00x1)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00xx\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZEYXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                frac.Y <- initialFrac.Y\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdZ))\n                        // lerp Z\n                        let v00x0 = lerp.Invoke(frac.Z, v0000, v0010)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v00x0\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    coord.Y <- coord.Y + step.Y\n                    let ni = int64 (floor coord.Y)\n                    px <- px + xdY * nativeint (ni - icoord.Y)\n                    icoord.Y <- ni\n                    frac.Y <- coord.Y - float(icoord.Y)\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZEYEX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    frac.X <- initialFrac.X\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (px + xdW))\n                        // lerp W\n                        let v000x = lerp.Invoke(frac.W, v0000, v0001)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v000x\n                        py <- py + yjX\n                        coord.X <- coord.X + step.X\n                        let ni = int64 (floor coord.X)\n                        px <- px + xdX * nativeint (ni - icoord.X)\n                        icoord.X <- ni\n                        frac.X <- coord.X - float(icoord.X)\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToInternalWEZEYEXE(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let sa = nativeint (sizeof<'a>)\n        let mutable py = y.Pointer |> NativePtr.toNativeInt\n        py <- py + nativeint y.Info.Origin * sa\n        let mutable px = x.Pointer |> NativePtr.toNativeInt\n        px <- px + nativeint x.Info.Origin * sa\n        let xdW = nativeint x.DW * sa\n        let xjW = nativeint (x.DW - x.SZ * x.DZ) * sa\n        let ysW = nativeint (y.SW * y.DW) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let xdZ = nativeint x.DZ * sa\n        let xjZ = nativeint (x.DZ - x.SY * x.DY) * sa\n        let ysZ = nativeint (y.SZ * y.DZ) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let xdY = nativeint x.DY * sa\n        let xjY = nativeint (x.DY - x.SX * x.DX) * sa\n        let ysY = nativeint (y.SY * y.DY) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let xdX = nativeint x.DX * sa\n        let xjX = nativeint x.DX * sa\n        let ysX = nativeint (y.SX * y.DX) * sa\n        let yjX = nativeint y.DX * sa\n        let ratio = (V4d(x.Size) * srcSize) / V4d(y.Size)\n        let initialCoord = (0.5 * ratio) + srcOffset * V4d(x.Size) - V4d.Half\n        let initialiCoord = V4l(floor initialCoord)\n        let initialFrac = initialCoord - V4d(initialiCoord)\n        let step = V4d.One * ratio\n        let mutable coord = initialCoord\n        let mutable icoord = initialiCoord\n        let mutable frac = initialFrac\n        px <- px + xdW * nativeint icoord.W + xdZ * nativeint icoord.Z + xdY * nativeint icoord.Y + xdX * nativeint icoord.X\n        let yeW = py + ysW\n        while py <> yeW do\n            let yeZ = py + ysZ\n            coord.Z <- initialCoord.Z\n            px <- px + xdZ * nativeint (initialiCoord.Z - icoord.Z)\n            icoord.Z <- initialiCoord.Z\n            while py <> yeZ do\n                let yeY = py + ysY\n                coord.Y <- initialCoord.Y\n                px <- px + xdY * nativeint (initialiCoord.Y - icoord.Y)\n                icoord.Y <- initialiCoord.Y\n                while py <> yeY do\n                    let yeX = py + ysX\n                    coord.X <- initialCoord.X\n                    px <- px + xdX * nativeint (initialiCoord.X - icoord.X)\n                    icoord.X <- initialiCoord.X\n                    while py <> yeX do\n                        let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt px)\n                        NativePtr.write (NativePtr.ofNativeInt<'a> py) v0000\n                        py <- py + yjX\n                        px <- px + xjX\n                        coord.X <- coord.X + step.X\n                        icoord.X <- icoord.X + 1L\n                    py <- py + yjY\n                    px <- px + xjY\n                    coord.Y <- coord.Y + step.Y\n                    icoord.Y <- icoord.Y + 1L\n                py <- py + yjZ\n                px <- px + xjZ\n                coord.Z <- coord.Z + step.Z\n                icoord.Z <- icoord.Z + 1L\n            py <- py + yjW\n            px <- px + xjW\n            coord.W <- coord.W + step.W\n            icoord.W <- icoord.W + 1L\n    member inline private x.BlitToWZYX(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        if y.Size.AnyGreater(x.Size) then failwith \"[NativeTensor] upsampling not implemented\"\n        if x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEZEYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEZEYEX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEZEYXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEZYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWZEYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWEZEYX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWEZYEX(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWEZYXE(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWZEYEX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWZEYXE(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 && x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWZYEXE(y, srcOffset, srcSize, lerp)\n        elif x.SW = y.SW && srcOffset.W = 0.0 && srcSize.W = 1.0 then x.BlitToInternalWEZYX(y, srcOffset, srcSize, lerp)\n        elif x.SZ = y.SZ && srcOffset.Z = 0.0 && srcSize.Z = 1.0 then x.BlitToInternalWZEYX(y, srcOffset, srcSize, lerp)\n        elif x.SY = y.SY && srcOffset.Y = 0.0 && srcSize.Y = 1.0 then x.BlitToInternalWZYEX(y, srcOffset, srcSize, lerp)\n        elif x.SX = y.SX && srcOffset.X = 0.0 && srcSize.X = 1.0 then x.BlitToInternalWZYXE(y, srcOffset, srcSize, lerp)\n        else x.BlitToInternalWZYX(y, srcOffset, srcSize, lerp)\n    member x.BlitTo(y : NativeTensor4<'a>, srcOffset : V4d, srcSize : V4d, lerp : float -> 'a -> 'a -> 'a) = \n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.BlitToXYZW(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.BlitToYXZW(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.BlitToYZXW(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.BlitToYZWX(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.BlitToXZYW(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.BlitToZXYW(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.BlitToZYXW(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.BlitToZYWX(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.BlitToXZWY(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.BlitToZXWY(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.BlitToZWXY(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.BlitToZWYX(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.BlitToXYWZ(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.BlitToYXWZ(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.BlitToYWXZ(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.BlitToYWZX(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.BlitToXWYZ(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.BlitToWXYZ(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.BlitToWYXZ(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.BlitToWYZX(y, srcOffset, srcSize, lerp)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.BlitToXWZY(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.BlitToWXZY(y, srcOffset, srcSize, lerp)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.BlitToWZXY(y, srcOffset, srcSize, lerp)\n        else x.BlitToWZYX(y, srcOffset, srcSize, lerp)\n    member x.BlitTo(y : NativeTensor4<'a>, lerp : float -> 'a -> 'a -> 'a) = x.BlitTo(y, V4d.Zero, V4d.One, lerp)\n    member x.Item\n        with get(c0 : V4l) : 'a = \n            let i = Vec.Dot(x.Delta, c0)\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : V4l) (value : 'a) =\n            let i = Vec.Dot(x.Delta, c0)\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : V4i) : 'a = \n            let i = Vec.Dot(x.Delta, V4l(c0))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : V4i) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V4l(c0))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : int, c1 : int, c2 : int, c3 : int) : 'a = \n            let i = Vec.Dot(x.Delta, V4l(c0, c1, c2, c3))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : int, c1 : int, c2 : int, c3 : int) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V4l(c0, c1, c2, c3))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member x.Item\n        with get(c0 : int64, c1 : int64, c2 : int64, c3 : int64) : 'a = \n            let i = Vec.Dot(x.Delta, V4l(c0, c1, c2, c3))\n            NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\n        and set (c0 : int64, c1 : int64, c2 : int64, c3 : int64) (value : 'a) =\n            let i = Vec.Dot(x.Delta, V4l(c0, c1, c2, c3))\n            NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\n    member inline private x.CopyToXYZW(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToYXZW(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYZXW(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYZWX(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToXZYW(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToZXYW(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sa\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZYXW(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sa\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZYWX(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToXZWY(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToZXWY(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZWXY(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZWYX(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToXYWZ(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToYXWZ(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYWXZ(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYWZX(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToXWYZ(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToWXYZ(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sa\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToWYXZ(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sa\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToWYZX(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToXWZY(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToWXZY(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToWZXY(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sa\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToWZYX(y : NativeTensor4<'a>) = \n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sa\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sa\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sa\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sa\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sa\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'a> yptr) (NativePtr.read (NativePtr.ofNativeInt<'a> xptr))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member x.CopyTo(y : NativeTensor4<'a>) = \n        if info.Size <> y.Size then\n            failwithf \"NativeTensor4 size mismatch: { src = %A; dst = %A }\" info.Size y.Size\n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.CopyToXYZW(y)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.CopyToYXZW(y)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.CopyToYZXW(y)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.CopyToYZWX(y)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.CopyToXZYW(y)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.CopyToZXYW(y)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.CopyToZYXW(y)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.CopyToZYWX(y)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.CopyToXZWY(y)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.CopyToZXWY(y)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.CopyToZWXY(y)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.CopyToZWYX(y)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.CopyToXYWZ(y)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.CopyToYXWZ(y)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.CopyToYWXZ(y)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.CopyToYWZX(y)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.CopyToXWYZ(y)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.CopyToWXYZ(y)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.CopyToWYXZ(y)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.CopyToWYZX(y)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.CopyToXWZY(y)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.CopyToWXZY(y)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.CopyToWZXY(y)\n        else x.CopyToWZYX(y)\n    member inline private x.CopyToXYZW<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToYXZW<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYZXW<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYZWX<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToXZYW<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToZXYW<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sb\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZYXW<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW) * sa\n        let yjW = nativeint (y.DW) * sb\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eW = xptr + sW\n                    while xptr <> eW do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjW\n                        yptr <- yptr + yjW\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZYWX<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToXZWY<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToZXWY<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZWXY<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToZWYX<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SW * info.DW) * sa\n        let yjZ = nativeint (y.DZ - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eZ = xptr + sZ\n        while xptr <> eZ do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjZ\n            yptr <- yptr + yjZ\n    member inline private x.CopyToXYWZ<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToYXWZ<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eW = xptr + sW\n                while xptr <> eW do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjW\n                    yptr <- yptr + yjW\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYWXZ<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToYWZX<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SW * info.DW) * sa\n        let yjY = nativeint (y.DY - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eY = xptr + sY\n        while xptr <> eY do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjY\n            yptr <- yptr + yjY\n    member inline private x.CopyToXWYZ<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToWXYZ<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sb\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToWYXZ<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ) * sa\n        let yjZ = nativeint (y.DZ) * sb\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eZ = xptr + sZ\n                    while xptr <> eZ do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjZ\n                        yptr <- yptr + yjZ\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToWYZX<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SY * info.DY) * sa\n        let yjW = nativeint (y.DW - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SZ * info.DZ) * sa\n        let yjY = nativeint (y.DY - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eY = xptr + sY\n            while xptr <> eY do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjY\n                yptr <- yptr + yjY\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToXWZY<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SW * info.DW) * sa\n        let yjX = nativeint (y.DX - y.SW * y.DW) * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eX = xptr + sX\n        while xptr <> eX do\n            let eW = xptr + sW\n            while xptr <> eW do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjW\n                yptr <- yptr + yjW\n            xptr <- xptr + xjX\n            yptr <- yptr + yjX\n    member inline private x.CopyToWXZY<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SX * info.DX) * sa\n        let yjW = nativeint (y.DW - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SZ * info.DZ) * sa\n        let yjX = nativeint (y.DX - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eX = xptr + sX\n            while xptr <> eX do\n                let eZ = xptr + sZ\n                while xptr <> eZ do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjZ\n                    yptr <- yptr + yjZ\n                xptr <- xptr + xjX\n                yptr <- yptr + yjX\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToWZXY<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SX * info.DX) * sa\n        let yjZ = nativeint (y.DZ - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX - info.SY * info.DY) * sa\n        let yjX = nativeint (y.DX - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY) * sa\n        let yjY = nativeint (y.DY) * sb\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eX = xptr + sX\n                while xptr <> eX do\n                    let eY = xptr + sY\n                    while xptr <> eY do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjY\n                        yptr <- yptr + yjY\n                    xptr <- xptr + xjX\n                    yptr <- yptr + yjX\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member inline private x.CopyToWZYX<'b when 'b : unmanaged>(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        let sb = nativeint (sizeof<'b>)\n        let sa = nativeint (sizeof<'a>)\n        let mutable xptr = ptr |> NativePtr.toNativeInt\n        xptr <- xptr + nativeint info.Origin * sa\n        let mutable yptr = y.Pointer |> NativePtr.toNativeInt\n        yptr <- yptr + nativeint y.Info.Origin * sb\n        let sW = nativeint (info.SW * info.DW) * sa\n        let xjW = nativeint (info.DW - info.SZ * info.DZ) * sa\n        let yjW = nativeint (y.DW - y.SZ * y.DZ) * sb\n        let sZ = nativeint (info.SZ * info.DZ) * sa\n        let xjZ = nativeint (info.DZ - info.SY * info.DY) * sa\n        let yjZ = nativeint (y.DZ - y.SY * y.DY) * sb\n        let sY = nativeint (info.SY * info.DY) * sa\n        let xjY = nativeint (info.DY - info.SX * info.DX) * sa\n        let yjY = nativeint (y.DY - y.SX * y.DX) * sb\n        let sX = nativeint (info.SX * info.DX) * sa\n        let xjX = nativeint (info.DX) * sa\n        let yjX = nativeint (y.DX) * sb\n        let eW = xptr + sW\n        while xptr <> eW do\n            let eZ = xptr + sZ\n            while xptr <> eZ do\n                let eY = xptr + sY\n                while xptr <> eY do\n                    let eX = xptr + sX\n                    while xptr <> eX do\n                        NativePtr.write (NativePtr.ofNativeInt<'b> yptr) (f (NativePtr.read (NativePtr.ofNativeInt<'a> xptr)))\n                        xptr <- xptr + xjX\n                        yptr <- yptr + yjX\n                    xptr <- xptr + xjY\n                    yptr <- yptr + yjY\n                xptr <- xptr + xjZ\n                yptr <- yptr + yjZ\n            xptr <- xptr + xjW\n            yptr <- yptr + yjW\n    member x.CopyTo(y : NativeTensor4<'b>, f : 'a -> 'b) = \n        if info.Size <> y.Size then\n            failwithf \"NativeTensor4 size mismatch: { src = %A; dst = %A }\" info.Size y.Size\n        let cXW = compare (abs info.DX) (abs info.DW)\n        let cXY = compare (abs info.DX) (abs info.DY)\n        let cXZ = compare (abs info.DX) (abs info.DZ)\n        let cYW = compare (abs info.DY) (abs info.DW)\n        let cYZ = compare (abs info.DY) (abs info.DZ)\n        let cZW = compare (abs info.DZ) (abs info.DW)\n        if cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.CopyToXYZW(y, f)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.CopyToYXZW(y, f)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.CopyToYZXW(y, f)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW >= 0  then x.CopyToYZWX(y, f)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.CopyToXZYW(y, f)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.CopyToZXYW(y, f)\n        elif cXW >= 0  && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.CopyToZYXW(y, f)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ <= 0 && cZW >= 0  then x.CopyToZYWX(y, f)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.CopyToXZWY(y, f)\n        elif cXW >= 0  && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.CopyToZXWY(y, f)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.CopyToZWXY(y, f)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW >= 0  then x.CopyToZWYX(y, f)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.CopyToXYWZ(y, f)\n        elif cXW >= 0  && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.CopyToYXWZ(y, f)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.CopyToYWXZ(y, f)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW >= 0  && cYZ >= 0  && cZW <= 0 then x.CopyToYWZX(y, f)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.CopyToXWYZ(y, f)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.CopyToWXYZ(y, f)\n        elif cXW <= 0 && cXY <= 0 && cXZ >= 0  && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.CopyToWYXZ(y, f)\n        elif cXW <= 0 && cXY <= 0 && cXZ <= 0 && cYW <= 0 && cYZ >= 0  && cZW <= 0 then x.CopyToWYZX(y, f)\n        elif cXW >= 0  && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.CopyToXWZY(y, f)\n        elif cXW <= 0 && cXY >= 0  && cXZ >= 0  && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.CopyToWXZY(y, f)\n        elif cXW <= 0 && cXY >= 0  && cXZ <= 0 && cYW <= 0 && cYZ <= 0 && cZW <= 0 then x.CopyToWZXY(y, f)\n        else x.CopyToWZYX(y, f)\n    member x.SampleNearest(coord : V3d) : 'a[] = \n        let p0f = coord * V3d x.Size.XYZ\n        let mutable nearest = V3l(int64 (Fun.Round p0f.X), int64 (Fun.Round p0f.Y), int64 (Fun.Round p0f.Z))\n        if nearest.X < 0L then nearest.X <- 0L\n        else if nearest.X >= x.SX then nearest.X <- x.SX - 1L\n        if nearest.Y < 0L then nearest.Y <- 0L\n        else if nearest.Y >= x.SY then nearest.Y <- x.SY - 1L\n        if nearest.Z < 0L then nearest.Z <- 0L\n        else if nearest.Z >= x.SZ then nearest.Z <- x.SZ - 1L\n        let sa = nativeint sizeof<'a>\n        let ptr = NativePtr.toNativeInt x.Pointer + nativeint (Vec.Dot(nearest, x.Delta.XYZ)) * sa\n        let dW = nativeint x.DW * sa\n        Array.init (int x.Size.W) (fun i -> NativePtr.read (NativePtr.ofNativeInt (ptr + nativeint i * dW)))\n    member x.SampleLinear(coord : V4d, lerp : float -> 'a -> 'a -> 'a) : 'a = \n        let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\n        let coord = Fun.Min(Fun.Max(coord, V4d.Zero), V4d.One)\n        let p0f = coord * V4d x.Size.XYZW - V4d(0.5, 0.5, 0.5, 0.5)\n        let mutable p0 = V4l(int64 (floor p0f.X), int64 (floor p0f.Y), int64 (floor p0f.Z), int64 (floor p0f.W))\n        let frac = p0f - V4d p0\n        let sa = nativeint sizeof<'a>\n        let dX = nativeint x.DX * sa\n        let dY = nativeint x.DY * sa\n        let dZ = nativeint x.DZ * sa\n        let dW = nativeint x.DW * sa\n        if p0.X >= 0L && p0.X < x.Size.X - 1L && p0.Y >= 0L && p0.Y < x.Size.Y - 1L && p0.Z >= 0L && p0.Z < x.Size.Z - 1L && p0.W >= 0L && p0.W < x.Size.W - 1L then\n            let ptr0 = NativePtr.toNativeInt x.Pointer + nativeint (Vec.Dot(p0, x.Delta.XYZW)) * sa\n            let v0000 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0))\n            let v0001 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dW))\n            let v0010 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dZ))\n            let v0011 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dZ + dW))\n            let v0100 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dY))\n            let v0101 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dY + dW))\n            let v0110 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dY + dZ))\n            let v0111 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dY + dZ + dW))\n            let v1000 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX))\n            let v1001 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dW))\n            let v1010 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dZ))\n            let v1011 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dZ + dW))\n            let v1100 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dY))\n            let v1101 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dY + dW))\n            let v1110 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dY + dZ))\n            let v1111 : 'a =  NativePtr.read (NativePtr.ofNativeInt (ptr0 + dX + dY + dZ + dW))\n            let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n            let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n            let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n            let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n            let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n            let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n            let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n            let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n            let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n            let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n            let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n            let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n            let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n            let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n            let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n            vxxxx\n        else\n            let max = x.Size - V4l.One\n            let v0000 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0), max))) * sa))\n            let v0001 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(0L, 0L, 0L, 1L)), max))) * sa))\n            let v0010 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(0L, 0L, 1L, 0L)), max))) * sa))\n            let v0011 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(0L, 0L, 1L, 1L)), max))) * sa))\n            let v0100 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(0L, 1L, 0L, 0L)), max))) * sa))\n            let v0101 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(0L, 1L, 0L, 1L)), max))) * sa))\n            let v0110 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(0L, 1L, 1L, 0L)), max))) * sa))\n            let v0111 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(0L, 1L, 1L, 1L)), max))) * sa))\n            let v1000 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(1L, 0L, 0L, 0L)), max))) * sa))\n            let v1001 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(1L, 0L, 0L, 1L)), max))) * sa))\n            let v1010 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(1L, 0L, 1L, 0L)), max))) * sa))\n            let v1011 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(1L, 0L, 1L, 1L)), max))) * sa))\n            let v1100 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(1L, 1L, 0L, 0L)), max))) * sa))\n            let v1101 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(1L, 1L, 0L, 1L)), max))) * sa))\n            let v1110 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(1L, 1L, 1L, 0L)), max))) * sa))\n            let v1111 : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(Vec.Dot(x.Delta, Fun.Min(Fun.Max(V4l.Zero, p0 + V4l(1L, 1L, 1L, 1L)), max))) * sa))\n            let vx000 = lerp.Invoke(frac.X, v0000, v1000)\n            let vx001 = lerp.Invoke(frac.X, v0001, v1001)\n            let vx010 = lerp.Invoke(frac.X, v0010, v1010)\n            let vx011 = lerp.Invoke(frac.X, v0011, v1011)\n            let vx100 = lerp.Invoke(frac.X, v0100, v1100)\n            let vx101 = lerp.Invoke(frac.X, v0101, v1101)\n            let vx110 = lerp.Invoke(frac.X, v0110, v1110)\n            let vx111 = lerp.Invoke(frac.X, v0111, v1111)\n            let vxx00 = lerp.Invoke(frac.Y, vx000, vx100)\n            let vxx01 = lerp.Invoke(frac.Y, vx001, vx101)\n            let vxx10 = lerp.Invoke(frac.Y, vx010, vx110)\n            let vxx11 = lerp.Invoke(frac.Y, vx011, vx111)\n            let vxxx0 = lerp.Invoke(frac.Z, vxx00, vxx10)\n            let vxxx1 = lerp.Invoke(frac.Z, vxx01, vxx11)\n            let vxxxx = lerp.Invoke(frac.W, vxxx0, vxxx1)\n            vxxxx\n    static member Using<'b> (m : Tensor4<'a>, f : NativeTensor4<'a> -> 'b) = \n        let gc = GCHandle.Alloc(m.Data, GCHandleType.Pinned)\n        try f (NativeTensor4<'a>(NativePtr.ofNativeInt (gc.AddrOfPinnedObject()), m.Info))\n        finally gc.Free()\n    member x.SubTensor4(beginX : int64, beginY : int64, beginZ : int64, beginW : int64, sizeX : int64, sizeY : int64, sizeZ : int64, sizeW : int64, deltaX : int64, deltaY : int64, deltaZ : int64, deltaW : int64) = NativeTensor4<'a>(ptr, info.SubTensor4(beginX, beginY, beginZ, beginW, sizeX, sizeY, sizeZ, sizeW, deltaX, deltaY, deltaZ, deltaW))\n    member x.SubTensor4(beginX : int64, beginY : int64, beginZ : int64, beginW : int64, sizeX : int64, sizeY : int64, sizeZ : int64, sizeW : int64) = NativeTensor4<'a>(ptr, info.SubTensor4(beginX, beginY, beginZ, beginW, sizeX, sizeY, sizeZ, sizeW))\n    member x.SubTensor4(offset : V4l, size : V4l) = NativeTensor4<'a>(ptr, info.SubTensor4(offset, size))\n    member x.SubTensor4(offset : V4l, size : V4l, delta : V4l) = NativeTensor4<'a>(ptr, info.SubTensor4(offset, size, delta))\n    member x.SubTensor4(offset : V4i, size : V4i) = NativeTensor4<'a>(ptr, info.SubTensor4(offset, size))\n    member x.SubTensor4(offset : V4i, size : V4i, delta : V4i) = NativeTensor4<'a>(ptr, info.SubTensor4(offset, size, delta))\n    member x.GetSlice(minX : int, minY : int, minZ : int, minW : Option<int>, maxW : Option<int>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeW, info.DW)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : int64, minZ : int64, minW : Option<int64>, maxW : Option<int64>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeW, info.DW)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : int, minZ : int, minW : Option<int>, maxW : Option<int>, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeW, info.DW)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : int64, minZ : int64, minW : Option<int64>, maxW : Option<int64>, value : 'a) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeW, info.DW)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : int, minZ : int, minW : Option<int>, maxW : Option<int>, src : NativeVector<'a>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeW, info.DW)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : int64, minZ : int64, minW : Option<int64>, maxW : Option<int64>, src : NativeVector<'a>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeW, info.DW)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : int, minZ : int, minW : Option<int>, maxW : Option<int>, src : Vector<'a>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeW, info.DW)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : int64, minZ : int64, minW : Option<int64>, maxW : Option<int64>, src : Vector<'a>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeW, info.DW)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : int) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : int64) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : int, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, value : 'a) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : int, src : NativeVector<'a>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, src : NativeVector<'a>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : int, src : Vector<'a>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, src : Vector<'a>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeZ, info.DZ)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeZ, sizeW), V2l(info.DZ, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeZ, sizeW), V2l(info.DZ, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeZ, sizeW), V2l(info.DZ, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, value : 'a) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeZ, sizeW), V2l(info.DZ, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, src : NativeMatrix<'a>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeZ, sizeW), V2l(info.DZ, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, src : NativeMatrix<'a>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeZ, sizeW), V2l(info.DZ, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, src : Matrix<'a>) = \n        let beginX = minX |> int64\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeZ, sizeW), V2l(info.DZ, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, src : Matrix<'a>) = \n        let beginX = minX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeZ, sizeW), V2l(info.DZ, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, minW : int) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : int64) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, minW : int, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : int64, value : 'a) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, minW : int, src : NativeVector<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : int64, src : NativeVector<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, minW : int, src : Vector<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : int64, src : Vector<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeY, info.DY)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, minW : Option<int>, maxW : Option<int>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeW), V2l(info.DY, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : Option<int64>, maxW : Option<int64>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeW), V2l(info.DY, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, minW : Option<int>, maxW : Option<int>, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeW), V2l(info.DY, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : Option<int64>, maxW : Option<int64>, value : 'a) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeW), V2l(info.DY, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, minW : Option<int>, maxW : Option<int>, src : NativeMatrix<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeW), V2l(info.DY, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : Option<int64>, maxW : Option<int64>, src : NativeMatrix<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeW), V2l(info.DY, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : int, minW : Option<int>, maxW : Option<int>, src : Matrix<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeW), V2l(info.DY, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : Option<int64>, maxW : Option<int64>, src : Matrix<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeW), V2l(info.DY, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : int) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : int64) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : int, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, value : 'a) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : int, src : NativeMatrix<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, src : NativeMatrix<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : int, src : Matrix<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, src : Matrix<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeY, sizeZ), V2l(info.DY, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeY, sizeZ, sizeW), V3l(info.DY, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeY, sizeZ, sizeW), V3l(info.DY, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, value : 'a) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeY, sizeZ, sizeW), V3l(info.DY, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, value : 'a) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeY, sizeZ, sizeW), V3l(info.DY, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, src : NativeVolume<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeY, sizeZ, sizeW), V3l(info.DY, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, src : NativeVolume<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeY, sizeZ, sizeW), V3l(info.DY, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : int, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, src : Volume<'a>) = \n        let beginX = minX |> int64\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeY, sizeZ, sizeW), V3l(info.DY, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : int64, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, src : Volume<'a>) = \n        let beginX = minX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeY, sizeZ, sizeW), V3l(info.DY, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, minW : int) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, minW : int64) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, minW : int, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, minW : int64, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, minW : int, src : NativeVector<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, minW : int64, src : NativeVector<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, minW : int, src : Vector<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, minW : int64, src : Vector<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = minW\n        let info = VectorInfo(info.Index(beginX, beginY, beginZ, beginW), sizeX, info.DX)\n        let res = NativeVector<'a>(ptr, info)\n        NativeVector<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, minW : Option<int>, maxW : Option<int>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeW), V2l(info.DX, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, minW : Option<int64>, maxW : Option<int64>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeW), V2l(info.DX, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, minW : Option<int>, maxW : Option<int>, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeW), V2l(info.DX, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, minW : Option<int64>, maxW : Option<int64>, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeW), V2l(info.DX, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, minW : Option<int>, maxW : Option<int>, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeW), V2l(info.DX, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, minW : Option<int64>, maxW : Option<int64>, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeW), V2l(info.DX, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : int, minW : Option<int>, maxW : Option<int>, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeW), V2l(info.DX, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : int64, minW : Option<int64>, maxW : Option<int64>, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeW), V2l(info.DX, info.DW))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : int) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : int64) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : int, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : int, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : int, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeZ), V2l(info.DX, info.DZ))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeZ, sizeW), V3l(info.DX, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeZ, sizeW), V3l(info.DX, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeZ, sizeW), V3l(info.DX, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeZ, sizeW), V3l(info.DX, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, src : NativeVolume<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeZ, sizeW), V3l(info.DX, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, src : NativeVolume<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeZ, sizeW), V3l(info.DX, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : int, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, src : Volume<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY |> int64\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeZ, sizeW), V3l(info.DX, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : int64, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, src : Volume<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = minY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeZ, sizeW), V3l(info.DX, info.DZ, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, minW : int) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : int64) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, minW : int, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : int64, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, minW : int, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : int64, src : NativeMatrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, minW : int, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = minW |> int64\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : int64, src : Matrix<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = minW\n        let info = MatrixInfo(info.Index(beginX, beginY, beginZ, beginW), V2l(sizeX, sizeY), V2l(info.DX, info.DY))\n        let res = NativeMatrix<'a>(ptr, info)\n        NativeMatrix<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, minW : Option<int>, maxW : Option<int>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeW), V3l(info.DX, info.DY, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : Option<int64>, maxW : Option<int64>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeW), V3l(info.DX, info.DY, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, minW : Option<int>, maxW : Option<int>, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeW), V3l(info.DX, info.DY, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : Option<int64>, maxW : Option<int64>, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeW), V3l(info.DX, info.DY, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, minW : Option<int>, maxW : Option<int>, src : NativeVolume<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeW), V3l(info.DX, info.DY, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : Option<int64>, maxW : Option<int64>, src : NativeVolume<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeW), V3l(info.DX, info.DY, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : int, minW : Option<int>, maxW : Option<int>, src : Volume<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ |> int64\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeW), V3l(info.DX, info.DY, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : int64, minW : Option<int64>, maxW : Option<int64>, src : Volume<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = minZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeW), V3l(info.DX, info.DY, info.DW))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : int) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : int64) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : int, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : int, src : NativeVolume<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, src : NativeVolume<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : int, src : Volume<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW |> int64\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : int64, src : Volume<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = minW\n        let info = VolumeInfo(info.Index(beginX, beginY, beginZ, beginW), V3l(sizeX, sizeY, sizeZ), V3l(info.DX, info.DY, info.DZ))\n        let res = NativeVolume<'a>(ptr, info)\n        NativeVolume<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.GetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = Tensor4Info(info.Index(beginX, beginY, beginZ, beginW), V4l(sizeX, sizeY, sizeZ, sizeW), V4l(info.DX, info.DY, info.DZ, info.DW))\n        let res = NativeTensor4<'a>(ptr, info)\n        res\n    member x.GetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = Tensor4Info(info.Index(beginX, beginY, beginZ, beginW), V4l(sizeX, sizeY, sizeZ, sizeW), V4l(info.DX, info.DY, info.DZ, info.DW))\n        let res = NativeTensor4<'a>(ptr, info)\n        res\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, value : 'a) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = Tensor4Info(info.Index(beginX, beginY, beginZ, beginW), V4l(sizeX, sizeY, sizeZ, sizeW), V4l(info.DX, info.DY, info.DZ, info.DW))\n        let res = NativeTensor4<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, value : 'a) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = Tensor4Info(info.Index(beginX, beginY, beginZ, beginW), V4l(sizeX, sizeY, sizeZ, sizeW), V4l(info.DX, info.DY, info.DZ, info.DW))\n        let res = NativeTensor4<'a>(ptr, info)\n        res.Set(value)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, src : NativeTensor4<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = Tensor4Info(info.Index(beginX, beginY, beginZ, beginW), V4l(sizeX, sizeY, sizeZ, sizeW), V4l(info.DX, info.DY, info.DZ, info.DW))\n        let res = NativeTensor4<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, src : NativeTensor4<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = Tensor4Info(info.Index(beginX, beginY, beginZ, beginW), V4l(sizeX, sizeY, sizeZ, sizeW), V4l(info.DX, info.DY, info.DZ, info.DW))\n        let res = NativeTensor4<'a>(ptr, info)\n        src.CopyTo(res)\n    member x.SetSlice(minX : Option<int>, maxX : Option<int>, minY : Option<int>, maxY : Option<int>, minZ : Option<int>, maxZ : Option<int>, minW : Option<int>, maxW : Option<int>, src : Tensor4<'a>) = \n        let beginX = defaultArg minX 0 |> int64\n        let maxX = defaultArg maxX (int info.SX - 1) |> int64\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0 |> int64\n        let maxY = defaultArg maxY (int info.SY - 1) |> int64\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0 |> int64\n        let maxZ = defaultArg maxZ (int info.SZ - 1) |> int64\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0 |> int64\n        let maxW = defaultArg maxW (int info.SW - 1) |> int64\n        let sizeW = 1L + maxW - beginW\n        let info = Tensor4Info(info.Index(beginX, beginY, beginZ, beginW), V4l(sizeX, sizeY, sizeZ, sizeW), V4l(info.DX, info.DY, info.DZ, info.DW))\n        let res = NativeTensor4<'a>(ptr, info)\n        NativeTensor4<'a>.Using(src, fun src -> src.CopyTo(res))\n    member x.SetSlice(minX : Option<int64>, maxX : Option<int64>, minY : Option<int64>, maxY : Option<int64>, minZ : Option<int64>, maxZ : Option<int64>, minW : Option<int64>, maxW : Option<int64>, src : Tensor4<'a>) = \n        let beginX = defaultArg minX 0L\n        let maxX = defaultArg maxX (info.SX - 1L)\n        let sizeX = 1L + maxX - beginX\n        let beginY = defaultArg minY 0L\n        let maxY = defaultArg maxY (info.SY - 1L)\n        let sizeY = 1L + maxY - beginY\n        let beginZ = defaultArg minZ 0L\n        let maxZ = defaultArg maxZ (info.SZ - 1L)\n        let sizeZ = 1L + maxZ - beginZ\n        let beginW = defaultArg minW 0L\n        let maxW = defaultArg maxW (info.SW - 1L)\n        let sizeW = 1L + maxW - beginW\n        let info = Tensor4Info(info.Index(beginX, beginY, beginZ, beginW), V4l(sizeX, sizeY, sizeZ, sizeW), V4l(info.DX, info.DY, info.DZ, info.DW))\n        let res = NativeTensor4<'a>(ptr, info)\n        NativeTensor4<'a>.Using(src, fun src -> src.CopyTo(res))\n\n/// The NativeTensor4 module providers convenient F#-style functions for accessing NativeTensor4s\nmodule NativeTensor4 =\n    /// Creates a new NativeTensor4 from the given address and info struct\n    let inline ofNativeInt<'a when 'a : unmanaged> (info : Tensor4Info) (address : nativeint) = NativeTensor4<'a>(NativePtr.ofNativeInt address, info)\n    \n    let inline private lerpy< ^a, ^b when (^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b)> (_ : ^a) (t : float) (a : ^b) (b : ^b) =\n        ((^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b) (t, a,b))\n    let inline private lerper t a b = lerpy (Unchecked.defaultof<Fun>) t a b\n    /// Sets the entire Tensor4 to the given value\n    let inline set (value : 'a) (dst : NativeTensor4<'a>) = dst.Set(value)\n    \n    /// Sets each entry to the value computed by getValue\n    let inline setByCoord (getValue : V4l -> 'a) (m : NativeTensor4<'a>) = m.SetByCoord(getValue)\n    \n    let inline sample (location : V4d) (m : NativeTensor4<'a>) = m.SampleLinear(location, lerper)\n    \n    let inline blit (src : NativeTensor4<'a>) (dst : NativeTensor4<'a>) = src.BlitTo(dst, lerper)\n    \n    /// Copies the content of 'src' to 'dst'\n    let inline copy (src : NativeTensor4<'a>) (dst : NativeTensor4<'a>) = src.CopyTo(dst)\n    \n    /// Copies the content of 'src' to 'dst' by applying the given function\n    let inline copyWith (f : 'a -> 'b) (src : NativeTensor4<'a>) (dst : NativeTensor4<'b>) = src.CopyTo(dst, f)\n    \n    /// Temporarily pins a Tensor4 making it available as NativeTensor4\n    let using (m : Tensor4<'a>) (f : NativeTensor4<'a> -> 'b) = NativeTensor4<'a>.Using(m, f)\n    \n    /// Iterates over all entries of the given NativeTensor4 and executes the given action\n    let inline iter (action : V4l -> 'a -> unit) (m : NativeTensor4<'a>) = m.Iter(action)\n    \n    /// Iterates over all entries of the given NativeTensor4 and executes the given action\n    let inline iterPtr (action : V4l -> nativeptr<'a> -> unit) (m : NativeTensor4<'a>) = m.IterPtr(action)\n    \n    /// Iterates over all entries of both of the given NativeTensor4s and executes the given action\n    let inline iter2 (action : V4l -> 'a -> 'b -> unit) (l : NativeTensor4<'a>) (r : NativeTensor4<'b>) = l.Iter2(r, action)\n    \n    /// Iterates over all entries of both of the given NativeTensor4s and executes the given action\n    let inline iterPtr2 (action : V4l -> nativeptr<'a> -> nativeptr<'b> -> unit) (l : NativeTensor4<'a>) (r : NativeTensor4<'b>) = l.IterPtr2(r, action)\n\n[<AutoOpen>]\nmodule PixVolumeTensorExtensions =\n    module PixVolume =\n        /// Pins the given PixVolume as a NativeTensor4 and executes the given action\n        let inline pin (pi : PixVolume<'a>) (f : NativeTensor4<'a> -> 'b) : 'b =\n            NativeTensor4.using pi.Tensor4 f\n        \n        /// Pins the given PixVolumes as a NativeTensor4s and executes the given action\n        let inline pin2 (l : PixVolume<'a>) (r : PixVolume<'b>) (f : NativeTensor4<'a> -> NativeTensor4<'b> -> 'c)  : 'c =\n            pin l (fun lv -> pin r (fun rv -> f lv rv))\n        \n        /// Copies the given PixVolume to the given NativeTensor4\n        let inline copyToNativeTensor4 (dst : NativeTensor4<'a>) (pix : PixVolume<'a>)  =\n            pin pix (fun src -> NativeTensor4.copy src dst)\n        \n        /// Copies from the given NativeTensor4 to the given PixVolume\n        let inline copyFromNativeTensor4 (src : NativeTensor4<'a>) (pix : PixVolume<'a>) =\n            pin pix (fun dst -> NativeTensor4.copy src dst)\n        \n        [<AutoOpen>]\n        module private CopyDispatch =\n            let private flags = BindingFlags.Static ||| BindingFlags.NonPublic ||| BindingFlags.Public\n            \n            type private Dispatcher() =\n                static member CopyImageToNative<'a when 'a : unmanaged>(src : PixVolume<'a>, dst : nativeint, dstInfo : Tensor4Info) =\n                    let dst = dst |> NativeTensor4.ofNativeInt dstInfo\n                    src |> copyToNativeTensor4 dst\n                \n                static member CopyNativeToImage<'a when 'a : unmanaged>(src : nativeint, srcInfo : Tensor4Info, dst : PixVolume<'a>) =\n                    let src = src |> NativeTensor4.ofNativeInt srcInfo\n                    dst |> copyFromNativeTensor4 src\n            \n            module ImageToNative =\n                let private def = typeof<Dispatcher>.GetMethod(nameof Dispatcher.CopyImageToNative, flags)\n                let private lookup = ConcurrentDictionary<Type, MethodInfo>()\n                let getGenericMethod (t: Type) = lookup.GetOrAdd(t, fun t -> def.MakeGenericMethod t)\n            \n            module NativeToImage =\n                let private def = typeof<Dispatcher>.GetMethod(nameof Dispatcher.CopyNativeToImage, flags)\n                let private lookup = ConcurrentDictionary<Type, MethodInfo>()\n                let getGenericMethod (t: Type) = lookup.GetOrAdd(t, fun t -> def.MakeGenericMethod t)\n            \n        /// Copies the given untyped PixVolume to the given native address\n        let copyToNative (dst : nativeint) (dstInfo : Tensor4Info) (pix : PixVolume) =\n            let mi = ImageToNative.getGenericMethod pix.PixFormat.Type\n            mi.Invoke(null, [|pix; dst; dstInfo|]) |> ignore\n        \n        /// Copies from the given native address to the given untyped PixVolume\n        let copyFromNative (src : nativeint) (srcInfo : Tensor4Info) (pix : PixVolume) =\n            let mi = NativeToImage.getGenericMethod pix.PixFormat.Type\n            mi.Invoke(null, [|src; srcInfo; pix|]) |> ignore\n        \n\n\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors/Native/NativeTensorGenerator.fsx",
    "content": "﻿\n\n\n\nmodule Generator =\n\n    type Blubber<'a> = class end\n\n    type Bla<'a>() =\n\n    \n        member x.GetSlice(fixedX : int, maxX : Option<int>, maxY : Option<int>) : Blubber<'a> =\n            failwith \"\"\n        member x.GetSlice(minX : Option<int>, minY : Option<int>, fixedY) : Blubber<'a> =\n            failwith \"\"\n\n        member x.GetSlice(minX : Option<int>, minY : Option<int>, maxX : Option<int>, maxY : Option<int>) : Bla<'a> =\n            failwith \"\"\n        member x.SetSlice(minX : Option<int>, minY : Option<int>, maxX : Option<int>, maxY : Option<int>, value : 'a) : Bla<'a> =\n            failwith \"\"\n\n    let test (bla : Bla<int>) =\n        let a = bla.[*, 1]\n        ()\n\n    \n    let tensorNames =\n        Map.ofList [\n            1, \"Vector\"\n            2, \"Matrix\"\n            3, \"Volume\"\n        ]\n\n    let componentNames = [| \"X\"; \"Y\"; \"Z\"; \"W\" |]\n\n    let vectorNames =\n        Map.ofList [\n            2, (\"V2l\", \"V2i\")\n            3, (\"V3l\", \"V3i\")\n            4, (\"V4l\", \"V4i\")\n        ]\n        \n    let floatVectorNames =\n        Map.ofList [\n            2, (\"V2d\", \"V2f\")\n            3, (\"V3d\", \"V3f\")\n            4, (\"V4d\", \"V4f\")\n        ]\n\n    let pixNames =\n        Map.ofList [\n            3, \"PixImage\"\n            4, \"PixVolume\"\n        ]\n\n    let getManagedName (dim : int) =\n        match Map.tryFind dim tensorNames with\n            | Some n -> n\n            | None -> sprintf \"Tensor%d\" dim\n\n    let getNativeName (dim : int) =\n        match Map.tryFind dim tensorNames with\n            | Some n -> \"Native\" + n\n            | None -> sprintf \"NativeTensor%d\" dim\n\n\n    \n    let rec allAssignments (values : list<'a>) (len : int) =\n        if len < 0 then\n            []\n        elif len = 0 then\n            [[]]\n        else\n            let inner = allAssignments values (len - 1)\n            [\n                for v in values do\n                    for a in inner do yield v :: a\n            ]\n\n    let builder = System.Text.StringBuilder()\n\n    let write (str : string) = builder.Append(str) |> ignore\n    \n    let mutable indent = \"\"\n    let line fmt = Printf.kprintf (fun str -> write indent; write str; write \"\\r\\n\") fmt\n    let start fmt = Printf.kprintf (fun str -> write indent; write str; write \"\\r\\n\"; indent <- indent + \"    \") fmt\n    let stop() = indent <- indent.Substring(4)\n\n    let rec insert (v : 'a) (l : list<'a>) =\n        match l with\n            | [] -> [[v]]\n            | h :: rest ->\n                (v :: h :: rest) ::\n                (insert v rest |> List.map (fun l -> h::l))\n\n    let rec allPermutations (l : list<'a>) =\n        match l with\n            | [] -> [[]]\n            | h :: rest ->\n                allPermutations rest |> List.collect (insert h)\n             \n    let rec take2 (l : list<'a>) =\n        match l with\n            | [] -> Set.empty\n            | [e] -> Set.empty\n            | [a;b] -> Set.ofList [(a,b)]\n            | a :: rest ->\n                take2 rest |> Seq.collect (fun (a',b') ->       \n                    [ (a, a'); (a, b'); (a', b')]\n                ) |> Set.ofSeq\n\n    let rec allComparisons (acc : Map<string * string, string>) (seen : list<string>) (perm : list<string>) =\n        match perm with\n            | [] -> acc\n            | a :: rest -> \n                let mutable res = seen |> List.fold (fun m s -> m |> Map.add (a,s) \"<= 0\" |> Map.add (s, a) \">= 0 \") acc\n                allComparisons res (a :: seen) rest\n\n\n    let rec private allSubsetsInternal (s : list<'a>) =\n        match s with\n            | [] -> [Set.empty]\n            | h :: rest ->\n                let r = allSubsetsInternal rest\n                (r |> List.map (Set.add h)) @ r\n\n    let allSubsets (s : list<'a>) =\n        allSubsetsInternal s\n\n\n    let setter (components : string[]) =\n        let suffix = components |> String.concat \"\"\n        start \"member inline private x.Set%s(value : 'a) = \" suffix\n        line \"let sa = nativeint (sizeof<'a>)\"\n        line \"let mutable ptr = ptr |> NativePtr.toNativeInt\"\n        line \"ptr <- ptr + nativeint info.Origin * sa\"\n\n        for d in 0 .. components.Length-2 do\n            let mine = components.[d]\n            let next = components.[d + 1]\n            line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n            line \"let j%s = nativeint (info.D%s - info.S%s * info.D%s) * sa\" mine mine next next\n\n\n        let mine = components.[components.Length-1]\n        line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n        line \"let j%s = nativeint (info.D%s) * sa\" mine mine\n\n        let rec buildLoop (index : int) =\n            if index >= components.Length then\n                line \"NativePtr.write (NativePtr.ofNativeInt<'a> ptr) value\"\n            else\n                let mine = components.[index]\n                line \"let e%s = ptr + s%s\" mine mine\n                start \"while ptr <> e%s do\" mine \n                buildLoop (index + 1)\n                line \"ptr <- ptr + j%s\" mine\n                stop()\n\n        buildLoop 0\n        stop()\n\n\n    let zeros =\n        Map.ofList [\n            \"int\", \"0\"\n            \"int64\", \"0L\"\n            \"V2i\", \"V2i.Zero\"\n            \"V2l\", \"V2l.Zero\"\n            \"V3i\", \"V3i.Zero\"\n            \"V3l\", \"V3l.Zero\"\n            \"V4i\", \"V4i.Zero\"\n            \"V4l\", \"V4l.Zero\"\n\n            \"float\", \"0.0\"\n            \"float32\", \"0.0f\"\n            \"double\", \"0.0\"\n            \"V2f\", \"V2f.Zero\"\n            \"V2d\", \"V2d.Zero\"\n            \"V3f\", \"V3f.Zero\"\n            \"V3d\", \"V3d.Zero\"\n            \"V4f\", \"V4f.Zero\"\n            \"V4d\", \"V4d.Zero\"\n        ]\n\n    type CoordDescription =\n        {\n            dim     : int\n            typ     : string\n            \n            init    : string -> string\n            step    : string -> string\n            set     : string -> string -> string -> string\n            get     : string -> string -> string\n            integral : bool\n            compInit : string -> string -> string\n            compStep  : string -> string -> string\n        }\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module CoordDescription =\n        \n        let int64 (dim : int) =\n            if dim > 1 then       \n                let lv, iv = vectorNames.[dim]\n                {\n                    dim = dim\n                    typ = lv\n                    init = fun _ -> sprintf \"%s.Zero\" lv\n                    step = fun _ -> sprintf \"%s.One\" lv\n                    get = fun v i -> sprintf \"%s.%s\" v i\n                    set = fun v i r -> sprintf \"%s.%s <- %s\" v i r\n                    integral = true\n                    compInit = fun _ _ -> \"0L\"\n                    compStep = fun _ _ -> \"1L\"\n                }\n\n            else\n                {\n                    dim = dim\n                    typ = \"int64\"\n                    init = fun _ -> \"0L\"\n                    step = fun _ -> \"1L\"\n                    get = fun v _ -> v\n                    set = fun v _ r -> sprintf \"%s <- %s\" v r\n                    integral = true\n                    compInit = fun _ _ -> \"0L\"\n                    compStep = fun _ _ -> \"1L\"\n                }\n\n        let int (dim : int) =\n            if dim > 1 then    \n                let lv, iv = vectorNames.[dim]\n                {\n                    dim = dim\n                    typ = iv\n                    init = fun _ -> sprintf \"%s.Zero\" iv\n                    step = fun _ -> sprintf \"%s.One\" iv\n                    get = fun v i -> sprintf \"%s.%s\" v i\n                    set = fun v i r -> sprintf \"%s.%s <- %s\" v i r\n                    integral = true\n                    compInit = fun _ _ -> \"0\"\n                    compStep = fun _ _ -> \"1\"\n                }\n\n            else\n                {\n                    dim = dim\n                    typ = \"int\"\n                    init = fun _ -> \"0\"\n                    step = fun _ -> \"1\"\n                    get = fun v _ -> v\n                    set = fun v _ r -> sprintf \"%s <- %s\" v r\n                    integral = true\n                    compInit = fun _ _ -> \"0\"\n                    compStep = fun _ _ -> \"1\"\n                }\n\n        let float (dim : int) =\n            if dim > 1 then    \n                let dv, _ = floatVectorNames.[dim]\n\n                let value v = \n                    let args = Array.create dim v |> String.concat \", \"\n                    sprintf \"%s(%s)\" dv args\n\n                {\n                    dim = dim\n                    typ = dv\n                    init = fun s -> sprintf \"%s / %s(%s)\" (value \"0.5\") dv s \n                    step = fun s -> sprintf \"%s.One / %s(%s)\" (dv) dv s \n                    get = fun v i -> sprintf \"%s.%s\" v i\n                    set = fun v i r -> sprintf \"%s.%s <- %s\" v i r\n                    integral = false\n                    \n                    compInit = fun s d -> sprintf \"0.5 / %s.%s\" s d\n                    compStep = fun s d -> sprintf \"1.0 / %s.%s\" s d\n                }\n\n            else\n                {\n                    dim = dim\n                    typ = \"float\"\n                    init = fun s -> sprintf \"0.5 / float(%s)\"  s \n                    step = fun s -> sprintf \"1.0 / float(%s)\" s \n                    get = fun v _ -> v\n                    set = fun v _ r -> sprintf \"%s <- %s\" v r\n                    integral = false\n                    compInit = fun s _ -> sprintf \"0.5 / float(%s)\" s \n                    compStep = fun s _ -> sprintf \"1.0 / float(%s)\" s \n                }\n\n        let all (dim : int) =\n            [\n                int64 dim\n                int dim\n                float dim\n            ]\n\n    let iterPtr (coord : CoordDescription) (components : string[]) =\n        let suffix = components |> String.concat \"\"\n\n        start \"member inline private x.IterPtr%s(action : %s -> nativeptr<'a> -> unit) = \" suffix coord.typ\n        line \"let action = OptimizedClosures.FSharpFunc<%s, nativeptr<'a>, unit>.Adapt(action)\" coord.typ\n        line \"let sa = nativeint (sizeof<'a>)\"\n        line \"let mutable ptr = ptr |> NativePtr.toNativeInt\"\n        line \"ptr <- ptr + nativeint info.Origin * sa\"\n\n        for d in 0 .. components.Length-2 do\n            let mine = components.[d]\n            let next = components.[d + 1]\n            line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n            line \"let j%s = nativeint (info.D%s - info.S%s * info.D%s) * sa\" mine mine next next\n\n\n        let mine = components.[components.Length-1]\n        line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n        line \"let j%s = nativeint (info.D%s) * sa\" mine mine\n        \n        if not coord.integral then\n            line \"let initialCoord = %s\" (coord.init \"x.Size\")\n            line \"let step = %s\" (coord.step \"x.Size\")\n            line \"let mutable coord = initialCoord\"\n        else\n            line \"let mutable coord = %s\" (coord.init \"x.Size\")\n\n        let rec buildLoop (index : int) =\n            if index >= components.Length then\n                //line \"let c = %s\" (coord.view \"coord\" \"x.Size\")\n                line \"action.Invoke(coord, NativePtr.ofNativeInt<'a> ptr)\"\n                //line \"NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\"\n            else\n                let mine = components.[index]\n                line \"let e%s = ptr + s%s\" mine mine\n                if index <> 0 then \n                    if coord.integral then line \"%s\" (coord.set \"coord\" mine (coord.compInit \"x.Size\" mine))\n                    else line \"%s\" (coord.set \"coord\" mine (coord.get \"initialCoord\" mine))\n                start \"while ptr <> e%s do\" mine \n                buildLoop (index + 1)\n                if coord.integral then line \"%s\" (coord.set \"coord\" mine (sprintf \"%s + %s\" (coord.get \"coord\" mine) (coord.compStep \"x.Size\" mine)))\n                else line \"%s\" (coord.set \"coord\" mine (sprintf \"%s + %s\" (coord.get \"coord\" mine) (coord.get \"step\" mine)))\n                line \"ptr <- ptr + j%s\" mine\n                stop()\n\n        buildLoop 0\n        stop()\n\n    let iterPtr2 (coord : CoordDescription) (components : string[]) =\n        let name = getNativeName coord.dim\n        let suffix = components |> String.concat \"\"\n\n        start \"member inline private x.IterPtr2%s(other : %s<'b>, action : %s -> nativeptr<'a> -> nativeptr<'b> -> unit) = \" suffix name coord.typ\n        line \"let action = OptimizedClosures.FSharpFunc<%s, nativeptr<'a>, nativeptr<'b>, unit>.Adapt(action)\" coord.typ\n        line \"let sa = nativeint (sizeof<'a>)\"\n        line \"let sb = nativeint (sizeof<'b>)\"\n        line \"let mutable ia = ptr |> NativePtr.toNativeInt\"\n        line \"let mutable ib = other.Pointer |> NativePtr.toNativeInt\"\n        line \"ia <- ia + nativeint info.Origin * sa\"\n        line \"ib <- ib + nativeint other.Info.Origin * sb\"\n\n        for d in 0 .. components.Length-2 do\n            let mine = components.[d]\n            let next = components.[d + 1]\n            line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n            line \"let ja%s = nativeint (info.D%s - info.S%s * info.D%s) * sa\" mine mine next next\n            line \"let jb%s = nativeint (other.Info.D%s - other.Info.S%s * other.Info.D%s) * sb\" mine mine next next\n\n        let mine = components.[components.Length-1]\n        line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n        line \"let ja%s = nativeint (info.D%s) * sa\" mine mine\n        line \"let jb%s = nativeint (other.Info.D%s) * sb\" mine mine\n\n        if not coord.integral then\n            line \"let initialCoord = %s\" (coord.init \"x.Size\")\n            line \"let step = %s\" (coord.step \"x.Size\")\n            line \"let mutable coord = initialCoord\"\n        else\n            line \"let mutable coord = %s\" (coord.init \"x.Size\")\n\n        let rec buildLoop (index : int) =\n            if index >= components.Length then\n                line \"action.Invoke(coord, NativePtr.ofNativeInt<'a> ia, NativePtr.ofNativeInt<'b> ib)\"\n            else\n                let mine = components.[index]\n                line \"let e%s = ia + s%s\" mine mine\n                if index <> 0 then \n                    if coord.integral then line \"%s\" (coord.set \"coord\" mine (coord.compInit \"x.Size\" mine))\n                    else line \"%s\" (coord.set \"coord\" mine (coord.get \"initialCoord\" mine))\n                start \"while ia <> e%s do\" mine \n                buildLoop (index + 1)\n                if coord.integral then line \"%s\" (coord.set \"coord\" mine (sprintf \"%s + %s\" (coord.get \"coord\" mine) (coord.compStep \"x.Size\" mine)))\n                else line \"%s\" (coord.set \"coord\" mine (sprintf \"%s + %s\" (coord.get \"coord\" mine) (coord.get \"step\" mine)))\n                line \"ia <- ia + ja%s\" mine\n                line \"ib <- ib + jb%s\" mine\n                stop()\n\n        buildLoop 0\n        stop()\n\n    let coordSetter (coord : CoordDescription) (components : string[]) =\n        let suffix = components |> String.concat \"\"\n\n        start \"member inline private x.SetByCoord%s(getValue : %s -> 'a) = \" suffix coord.typ\n        line \"let sa = nativeint (sizeof<'a>)\"\n        line \"let mutable ptr = ptr |> NativePtr.toNativeInt\"\n        line \"ptr <- ptr + nativeint info.Origin * sa\"\n\n        for d in 0 .. components.Length-2 do\n            let mine = components.[d]\n            let next = components.[d + 1]\n            line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n            line \"let j%s = nativeint (info.D%s - info.S%s * info.D%s) * sa\" mine mine next next\n\n\n        let mine = components.[components.Length-1]\n        line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n        line \"let j%s = nativeint (info.D%s) * sa\" mine mine\n        \n        line \"let initialCoord = %s\" (coord.init \"x.Size\")\n        line \"let step = %s\" (coord.step \"x.Size\")\n\n        line \"let mutable coord = initialCoord\"\n\n        let rec buildLoop (index : int) =\n            if index >= components.Length then\n                //line \"let c = %s\" (coord.view \"coord\" \"x.Size\")\n                line \"NativePtr.write (NativePtr.ofNativeInt<'a> ptr) (getValue coord)\"\n            else\n                let mine = components.[index]\n                line \"let e%s = ptr + s%s\" mine mine\n                if index <> 0 then line \"%s\" (coord.set \"coord\" mine (coord.get \"initialCoord\" mine))\n                start \"while ptr <> e%s do\" mine \n                buildLoop (index + 1)\n                line \"%s\" (coord.set \"coord\" mine (sprintf \"%s + %s\" (coord.get \"coord\" mine) (coord.get \"step\" mine)))\n                line \"ptr <- ptr + j%s\" mine\n                stop()\n\n        buildLoop 0\n        stop()\n\n    let sampleNearest (dim : int) =\n        if dim > 1 then\n            let coordType = \n                match dim with\n                    | 2 -> \"float\"\n                    | 3 -> \"V2d\"\n                    | 4 -> \"V3d\"\n                    | _ -> failwith \"invalid dim\"\n\n            start \"member x.SampleNearest(coord : %s) : 'a[] = \" coordType\n            \n            let dim = dim - 1\n\n            let lv, iv = \n                match Map.tryFind dim vectorNames with\n                    | Some t -> t\n                    | None -> \"int64\", \"int\"\n\n            let swizzle = Array.take dim componentNames  |> String.concat \"\"\n\n            line \"let p0f = coord * %s x.Size.%s\" coordType swizzle\n            line \"let mutable nearest = %s\" (\n                if dim = 1 then\n                    \"int64 (Fun.Round p0f)\"\n                else\n                    Array.take dim componentNames \n                        |> Array.map (sprintf \"int64 (Fun.Round p0f.%s)\") \n                        |> String.concat \", \"\n                        |> sprintf \"%s(%s)\" lv\n            )\n\n            if dim = 1 then\n                line \"if nearest < 0L then nearest <- 0L\"\n                line \"else if nearest >= x.Size.%s then nearest <- x.Size.%s - 1L\" swizzle swizzle\n            else\n                for c in Array.take dim componentNames do\n                    line \"if nearest.%s < 0L then nearest.%s <- 0L\" c c\n                    line \"else if nearest.%s >= x.S%s then nearest.%s <- x.S%s - 1L\" c c c c\n\n            let idot =\n                match dim with\n                    | 1 -> \"{0} * {1}\"\n                    | _ -> \"Vec.Dot({0}, {1})\"\n            \n            line \"let sa = nativeint sizeof<'a>\"\n            line \"let ptr = NativePtr.toNativeInt x.Pointer + nativeint (%s) * sa\" (System.String.Format(idot, \"nearest\", sprintf \"x.Delta.%s\" swizzle))\n\n            let lastComp = componentNames.[dim]\n            line \"let d%s = nativeint x.D%s * sa\" lastComp lastComp\n            line \"Array.init (int x.Size.%s) (fun i -> NativePtr.read (NativePtr.ofNativeInt (ptr + nativeint i * d%s)))\" lastComp lastComp\n            \n            stop()\n\n    let blitInternalEq (components : string[]) (different : bool[]) =\n        let dim = components.Length\n\n        let selfType = getNativeName dim\n        let suffix = Array.zip components different |> Array.map (fun (c,d) -> if d then c else c + \"E\") |> String.concat \"\"\n        \n        let tInt = \n            match Map.tryFind dim vectorNames with\n                | Some (dv,_) -> dv\n                | None -> \"int64\"\n\n        let tFloat = \n            match Map.tryFind dim floatVectorNames with\n                | Some (dv,_) -> dv\n                | None -> \"float\"\n\n        let zFloat =\n            if dim = 1 then \"0.0\"\n            else sprintf \"%s.Zero\" tFloat\n        \n        let hFloat =\n            if dim = 1 then \"0.5\"\n            else sprintf \"%s.Half\" tFloat\n            \n        let oFloat =\n            if dim = 1 then \"1.0\"\n            else sprintf \"%s.One\" tFloat\n\n        let set (v : string) (d : int) (value : string) =\n            if dim > 1 then\n                let c = components.[d]\n                sprintf \"%s.%s <- %s\" v c value\n            else\n                sprintf \"%s <- %s\" v value\n\n        let get (v : string) (d : int) =\n            if dim > 1 then\n                let c = components.[d]\n                sprintf \"%s.%s\" v c\n            else\n                sprintf \"%s\" v\n\n        let floor (v : string) =\n            sprintf \"floor %s\" v\n            (*\n            if dim = 1 then sprintf \"floor(%s)\" v\n            else sprintf \"%s.Floor()\" v*)\n\n        start \"member inline private x.BlitToInternal%s(y : %s<'a>, srcOffset : %s, srcSize : %s, lerp : float -> 'a -> 'a -> 'a) = \" suffix selfType tFloat tFloat\n\n        line \"let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\"\n        line \"let sa = nativeint (sizeof<'a>)\"\n        line \"let mutable py = y.Pointer |> NativePtr.toNativeInt\"\n        line \"py <- py + nativeint y.Info.Origin * sa\"\n        line \"let mutable px = x.Pointer |> NativePtr.toNativeInt\"\n        line \"px <- px + nativeint x.Info.Origin * sa\"\n\n        for d in 0 .. components.Length-1 do\n            let mine = components.[d]\n            let next = \n                if d < components.Length - 1 then Some components.[d + 1]\n                else None\n                \n            //line \"let xs%s = nativeint (x.S%s * x.D%s) * sa\" mine mine mine\n            line \"let xd%s = nativeint x.D%s * sa\" mine mine\n            if not different.[d] then\n                match next with\n                    | Some next -> \n                        line \"let xj%s = nativeint (x.D%s - x.S%s * x.D%s) * sa\" mine mine next next\n                    | None ->\n                        line \"let xj%s = nativeint x.D%s * sa\" mine mine\n\n            line \"let ys%s = nativeint (y.S%s * y.D%s) * sa\" mine mine mine\n            match next with\n                | Some next -> \n                    line \"let yj%s = nativeint (y.D%s - y.S%s * y.D%s) * sa\" mine mine next next\n                | None ->\n                    line \"let yj%s = nativeint y.D%s * sa\" mine mine\n                    \n        // let initialCoord = V2d(0.5, 0.5) / V2d(y.Size)\n        // let cx = coord * V2d(x.Size) - V2d.Half\n\n        // 0.5 * (V2d(x.Size) / V2d(y.Size)) - V2d(0.5, 0.5)\n        line \"let ratio = (%s(x.Size) * srcSize) / %s(y.Size)\" tFloat tFloat\n        line \"let initialCoord = (0.5 * ratio) + srcOffset * %s(x.Size) - %s\" tFloat hFloat\n        line \"let initialiCoord = %s(%s)\" tInt (floor \"initialCoord\")\n        line \"let initialFrac = initialCoord - %s(initialiCoord)\" tFloat \n        line \"let step = %s * ratio\" oFloat\n        line \"let mutable coord = initialCoord\"\n        line \"let mutable icoord = initialiCoord\" \n        line \"let mutable frac = initialFrac\"\n\n        let deltas = components |> Seq.mapi (fun  i c -> sprintf \"xd%s * nativeint %s\" c (get \"icoord\" i)) |> String.concat \" + \"\n        line \"px <- px + %s\" deltas\n\n        let rec buildLoop (index : int) =\n            if index >= components.Length then\n                let offsets = allAssignments [0;1] dim\n\n                let offsets = \n                    offsets |> List.filter (fun offset ->\n                        let offset = List.toArray offset\n                        Seq.init dim id |> Seq.forall (fun i ->\n                            different.[i] || offset.[i] = 0\n                        )\n                    )\n\n                for o in offsets do\n                    let str = o |> List.map string |> String.concat \"\"\n                    let delta = o |> List.mapi (fun i -> function 0 -> None | _ -> Some (sprintf \"xd%s\" componentNames.[i])) |> List.choose id |> String.concat \" + \"\n                    if delta <> \"\" then\n                        line \"let v%s : 'a = NativePtr.read (NativePtr.ofNativeInt (px + %s))\" str delta\n                    else\n                        line \"let v%s : 'a = NativePtr.read (NativePtr.ofNativeInt px)\" str\n                        \n\n                let rec buildSample (prefix : string) (d : int) (offsets : list<list<int>>) =\n                    if d >= dim then\n                        line \"NativePtr.write (NativePtr.ofNativeInt<'a> py) v%s\" prefix\n                    else\n                        let r = dim - d\n\n                        let first = offsets |> List.map List.head |> Set.ofList\n\n                        let offsets = offsets |> List.map (List.skip 1) |> Set.ofList |> Set.toList //allAssignments [0;1] (r - 1)\n                    \n                        let frac = \n                            if dim = 1 then \"frac\"\n                            else sprintf \"frac.%s\" (componentNames.[d])\n\n                        if different.[d] then\n                            line \"// lerp %s\" (componentNames.[d])\n                            for offset in offsets do\n                                let vName = offset |> List.map string |> String.concat \"\" |> sprintf \"v%sx%s\" prefix\n                                let i0 = 0 :: offset |> List.map string |> String.concat \"\" |> sprintf \"v%s%s\" prefix\n                                let i1 = 1 :: offset |> List.map string |> String.concat \"\" |> sprintf \"v%s%s\" prefix\n                                line \"let %s = lerp.Invoke(%s, %s, %s)\" vName frac i0 i1\n                            buildSample (prefix + \"x\") (d + 1) offsets \n                        else\n                            buildSample (prefix + \"0\") (d + 1) offsets\n\n            \n                buildSample \"\" 0 offsets\n                //line \"NativePtr.write (NativePtr.ofNativeInt<'a> py) Unchecked.defaultof<'a>\"\n            else\n                let mine = components.[index]\n                line \"let ye%s = py + ys%s\" mine mine\n                if index > 0 then\n                    line \"%s\" (set \"coord\" index (get \"initialCoord\" index))\n                    line \"px <- px + xd%s * nativeint (%s - %s)\" mine (get \"initialiCoord\" index) (get \"icoord\" index)\n                    if different.[index] then \n                        line \"%s\" (set \"frac\" index (get \"initialFrac\" index))\n                    line \"%s\" (set \"icoord\" index (get \"initialiCoord\" index))\n\n                start \"while py <> ye%s do\" mine \n                buildLoop (index + 1)\n                line \"py <- py + yj%s\" mine\n\n                if different.[index] then\n                    line \"%s\" (set \"coord\" index (sprintf \"%s + %s\" (get \"coord\" index) (get \"step\" index)))\n                    line \"let ni = int64 (floor %s)\" (get \"coord\" index)\n                    line \"px <- px + xd%s * nativeint (ni - %s)\" mine (get \"icoord\" index)\n                    line \"%s\" (set \"icoord\" index \"ni\")\n                    line \"%s\" (set \"frac\" index (sprintf \"%s - float(%s)\" (get \"coord\" index) (get \"icoord\" index)))\n                else\n                    line \"px <- px + xj%s\" mine\n                    line \"%s\" (set \"coord\" index (sprintf \"%s + %s\" (get \"coord\" index) (get \"step\" index)))\n                    line \"%s\" (set \"icoord\" index (sprintf \"%s + 1L\" (get \"icoord\" index)))\n                stop()\n\n        buildLoop 0        \n\n        stop()\n\n    let blitInternal (components : string[]) =\n        let dim = components.Length\n        let all = allAssignments [true; false] dim\n        for a in all do blitInternalEq components (List.toArray a)\n        \n        let selfType = getNativeName dim\n\n        let tFloat = \n            match Map.tryFind dim floatVectorNames with\n                | Some (dv,_) -> dv\n                | None -> \"float\"\n\n        let suffix = components |> String.concat \"\"\n        let callInner (d : bool[]) = \n            let suffix = Array.zip components d |> Array.map (fun (c,d) -> if d then c + \"E\" else c) |> String.concat \"\"\n            sprintf \"x.BlitToInternal%s(y, srcOffset, srcSize, lerp)\" suffix\n\n        start \"member inline private x.BlitTo%s(y : %s<'a>, srcOffset : %s, srcSize : %s, lerp : float -> 'a -> 'a -> 'a) = \" suffix selfType tFloat tFloat\n\n        if dim <= 1 then\n            line \"if y.Size > x.Size then failwith \\\"[NativeTensor] upsampling not implemented\\\"\"\n        else\n            line \"if y.Size.AnyGreater(x.Size) then failwith \\\"[NativeTensor] upsampling not implemented\\\"\"\n\n\n        let rec dispatch (i : int) (a : list<string * list<bool>>) =\n            match a with\n                | [(c,a)] ->\n                    if i > 0 then \n                        line \"else %s\" (callInner (List.toArray a))\n                    else\n                        line \"%s\" (callInner (List.toArray a))\n                | (check, a) :: r ->\n                    if i > 0 then\n                        line \"elif %s then %s\" check (callInner (List.toArray a))\n                    else\n                        line \"if %s then %s\" check (callInner (List.toArray a))\n\n\n                    dispatch (i + 1) r\n                | [] ->\n                    failwith \"\"\n\n\n        let conditions = \n            all |> List.map (fun a ->\n                let cond =\n                    a |> List.mapi (fun i a ->\n                        let mine = components.[i]\n                        \n                        if a then \n                            if dim = 1 then\n                                Some (sprintf \"x.S%s = y.S%s && srcOffset = 0.0 && srcSize = 1.0\" mine mine)\n                            else\n                                Some (sprintf \"x.S%s = y.S%s && srcOffset.%s = 0.0 && srcSize.%s = 1.0\" mine mine mine mine)\n                        else None\n                    ) |> List.choose id |> String.concat \" && \"\n\n                cond, a\n            )\n\n        let conditions = conditions |> List.sortByDescending (fst >> String.length)\n        dispatch 0 conditions\n\n            \n\n\n        stop()\n\n    let item (dim : int) =\n        \n        let lv, iv =\n            match Map.tryFind dim vectorNames with\n                | Some t -> t\n                | None -> \"int64\", \"int\"\n\n\n\n        let coordTypes =\n            [\n                yield [lv], \"{0}\"\n                yield [iv], sprintf \"%s({0})\" lv\n                if dim > 1 then\n                    yield (List.init dim (fun _ -> \"int\"), List.init dim (sprintf \"{%d}\") |> String.concat \", \" |> sprintf \"%s(%s)\" lv)\n                    yield (List.init dim (fun _ -> \"int64\"), List.init dim (sprintf \"{%d}\") |> String.concat \", \" |> sprintf \"%s(%s)\" lv)\n            ]\n\n        let idot =\n            if dim = 1 then \"{0} * {1}\"\n            else \"Vec.Dot({0}, {1})\"\n\n        for (ct, convert) in coordTypes do\n            start \"member x.Item\"\n            let argDef = ct |> List.mapi (fun i t -> sprintf \"c%d : %s\" i t) |> String.concat \", \"\n            let argRef = System.String.Format(convert, List.init dim (fun i -> sprintf \"c%d\" i :> obj) |> List.toArray)\n\n            start \"with get(%s) : 'a = \" argDef\n            line \"let i = %s\" (System.String.Format(idot, \"x.Delta\", argRef))\n            line \"NativePtr.read (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i)))\"\n            stop()\n\n            start \"and set (%s) (value : 'a) =\" argDef\n            line \"let i = %s\" (System.String.Format(idot, \"x.Delta\", argRef))\n            line \"NativePtr.write (NativePtr.ofNativeInt<'a> (NativePtr.toNativeInt x.Pointer + nativeint sizeof<'a> * (nativeint x.Origin + nativeint i))) value\"\n            stop()\n\n            stop()\n\n\n\n    let sampleLinear (dim : int) =\n        if dim > 1 then\n            let coordType = \n                match dim with\n                    | 1 -> \"float\"\n                    | 2 -> \"V2d\"\n                    | 3 -> \"V3d\"\n                    | 4 -> \"V4d\"\n                    | _ -> failwith \"invalid dim\"\n\n            let resType = \"'a\"\n\n            start \"member x.SampleLinear(coord : %s, lerp : float -> 'a -> 'a -> 'a) : %s = \" coordType resType\n            line \"let lerp = OptimizedClosures.FSharpFunc<float, 'a, 'a, 'a>.Adapt(lerp)\"\n            line \"let coord = Fun.Min(Fun.Max(coord, %s.Zero), %s.One)\" coordType coordType\n\n\n            let lv, iv = \n                match Map.tryFind dim vectorNames with\n                    | Some t -> t\n                    | None -> \"int64\", \"int\"\n\n            //let componentNames = Array.take dim componentNames\n            let swizzle = Array.take dim componentNames  |> String.concat \"\"\n            let half = sprintf \"%s(%s)\" coordType (Array.create dim \"0.5\" |> String.concat \", \")\n            if dim > 1 then\n                line \"let p0f = coord * %s x.Size.%s - %s\" coordType swizzle half\n            else\n                line \"let p0f = coord * %s x.Size - %s\" coordType half\n\n            line \"let mutable p0 = %s\" (\n                if dim = 1 then\n                    \"int64 (floor p0f)\"\n                else\n                    Array.take dim componentNames\n                        |> Array.map (sprintf \"int64 (floor p0f.%s)\") \n                        |> String.concat \", \"\n                        |> sprintf \"%s(%s)\" lv\n            )\n\n            line \"let frac = p0f - %s p0\" coordType\n\n            let fullyInside =\n                Array.take dim componentNames |> Array.map (fun c -> sprintf \"p0.%s >= 0L && p0.%s < x.Size.%s - 1L\" c c c) |> String.concat \" && \"\n\n            let idot =\n                match dim with\n                    | 1 -> \"{0} * {1}\"\n                    | _ -> \"Vec.Dot({0}, {1})\"\n\n\n            line \"let sa = nativeint sizeof<'a>\"\n\n            for c in Array.take dim componentNames do\n                line \"let d%s = nativeint x.D%s * sa\" c c\n            start \"if %s then\" fullyInside\n\n            line \"let ptr0 = NativePtr.toNativeInt x.Pointer + nativeint (%s) * sa\" (System.String.Format(idot, \"p0\", sprintf \"x.Delta.%s\" swizzle))\n\n\n\n            let getPtr (offsets : list<int>) =\n                offsets \n                    |> List.mapi (fun d -> function 0 -> None | 1 -> Some (sprintf \"d%s\" componentNames.[d]) | v -> Some (sprintf \"d%s * %d\" componentNames.[d] v))\n                    |> List.choose id\n                    |> List.append [ \"ptr0\" ]\n                    |> String.concat \" + \"\n\n            let rec buildSample (prefix : string) (d : int) =\n                if d >= dim then\n                    let res = Array.create dim \"x\" |> String.concat \"\" |> sprintf \"v%s\"\n                    line \"%s\" res\n                else\n                    let r = dim - d\n                    let offsets = allAssignments [0;1] (r - 1)\n                    \n                    let frac = \n                        if dim = 1 then \"frac\"\n                        else sprintf \"frac.%s\" (componentNames.[d])\n\n                    for offset in offsets do\n                        let vName = offset |> List.map string |> String.concat \"\" |> sprintf \"v%sx%s\" prefix\n                        let i0 = 0 :: offset |> List.map string |> String.concat \"\" |> sprintf \"v%s%s\" prefix\n                        let i1 = 1 :: offset |> List.map string |> String.concat \"\" |> sprintf \"v%s%s\" prefix\n                        line \"let %s = lerp.Invoke(%s, %s, %s)\" vName frac i0 i1\n                    buildSample (prefix + \"x\") (d + 1)\n            \n         \n            let offsets = allAssignments [0;1] dim\n\n            for offset in offsets do\n                let ptr0Name = \n                    offset |> List.map (fun _ -> \"0\") |> String.concat \"\" |> sprintf \"pp%s\"\n                    \n                let valueName = \n                    offset |> List.map string |> String.concat \"\" |> sprintf \"v%s\"\n                    \n                let ptrName = \n                    offset |> List.map string |> String.concat \"\" |> sprintf \"pp%s\"\n\n                line \"let %s : 'a =  NativePtr.read (NativePtr.ofNativeInt (%s))\" valueName (getPtr offset)\n\n\n\n            //for offset in offsets do\n            //    let valueName = offset |> List.map string |> String.concat \"\" |> sprintf \"v%s\"\n            //    let ptrName = offset |> List.map string |> String.concat \"\" |> sprintf \"pp%s\"\n            //    line \"let %s : 'a = NativePtr.read %s\" valueName ptrName\n\n            buildSample \"\" 0\n            stop()\n\n            start \"else\"\n\n            line \"let max = x.Size - %s.One\" lv\n            for offset in offsets do\n                let ptr0Name = \n                    offset |> List.map (fun _ -> \"0\") |> String.concat \"\" |> sprintf \"pp%s\"\n                    \n                let valueName = \n                    offset |> List.map string |> String.concat \"\" |> sprintf \"v%s\"\n                    \n                let ptrName = \n                    offset |> List.map string |> String.concat \"\" |> sprintf \"pp%s\"\n\n                let offsetVec = offset |> List.map (sprintf \"%dL\") |> String.concat \", \" |> sprintf \"%s(%s)\" lv\n\n                let offset = \n                    if offset |> List.forall ((=) 0) then\n                        System.String.Format(idot, \"x.Delta\", sprintf \"Fun.Min(Fun.Max(%s.Zero, p0), max)\" lv)\n                    else\n                        System.String.Format(idot, \"x.Delta\", sprintf \"Fun.Min(Fun.Max(%s.Zero, p0 + %s), max)\" lv offsetVec)\n                        \n                //line \"let %s : nativeptr<'a> = NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(%s) * sa)\" ptrName offset\n                line \"let %s : 'a = NativePtr.read (NativePtr.ofNativeInt (NativePtr.toNativeInt x.Pointer + nativeint(%s) * sa))\" valueName offset\n\n            buildSample \"\" 0\n                \n            stop()  \n            stop()\n\n    let copyToInternal (otherType : string) (otherGenArg : string) (args : list<string * string>) (op : string -> string -> string) (components : string[]) =\n        let suffix = components |> String.concat \"\"\n        let argDef = ((\"y\", sprintf \"%s<%s>\" otherType otherGenArg) :: args) |> Seq.map (fun (n,t) -> sprintf \"%s : %s\" n t) |> String.concat \", \"\n        \n        let sb = \n            if otherGenArg <> \"'a\" then \n                start \"member inline private x.CopyTo%s<%s when %s : unmanaged>(%s) = \" suffix otherGenArg otherGenArg argDef\n                line \"let sb = nativeint (sizeof<%s>)\" otherGenArg\n                \"sb\"\n            else\n                start \"member inline private x.CopyTo%s(%s) = \" suffix argDef\n                \"sa\"\n\n        line \"let sa = nativeint (sizeof<'a>)\"\n        \n        line \"let mutable xptr = ptr |> NativePtr.toNativeInt\"\n        line \"xptr <- xptr + nativeint info.Origin * sa\"\n        line \"let mutable yptr = y.Pointer |> NativePtr.toNativeInt\"\n        line \"yptr <- yptr + nativeint y.Info.Origin * %s\" sb\n\n        for d in 0 .. components.Length-2 do\n            let mine = components.[d]\n            let next = components.[d + 1]\n            line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n            line \"let xj%s = nativeint (info.D%s - info.S%s * info.D%s) * sa\" mine mine next next\n            line \"let yj%s = nativeint (y.D%s - y.S%s * y.D%s) * %s\" mine mine next next sb\n\n\n        let mine = components.[components.Length-1]\n        line \"let s%s = nativeint (info.S%s * info.D%s) * sa\" mine mine mine\n        line \"let xj%s = nativeint (info.D%s) * sa\" mine mine\n        line \"let yj%s = nativeint (y.D%s) * %s\" mine mine sb\n\n        let rec buildLoop (index : int) =\n            if index >= components.Length then\n                let str = op \"xptr\" \"yptr\"\n                line \"%s\" str\n            else\n                let mine = components.[index]\n                line \"let e%s = xptr + s%s\" mine mine\n                start \"while xptr <> e%s do\" mine \n                buildLoop (index + 1)\n                line \"xptr <- xptr + xj%s\" mine\n                line \"yptr <- yptr + yj%s\" mine\n                stop()\n\n        buildLoop 0\n        stop()\n\n    let dispatcher (check : unit -> unit) (componentNames : list<string>) (name : string) (args : list<string * string>) =\n        let argDef = (args |> Seq.map (fun (n,t) -> sprintf \"%s : %s\" n t) |> String.concat \", \")\n        let argRef = args |> Seq.map fst |> String.concat \", \"\n        start \"member x.%s(%s) = \" name argDef\n        check()\n        let comparisons = take2 componentNames\n        for (a,b) in comparisons do\n            line \"let c%s%s = compare (abs info.D%s) (abs info.D%s)\" a b a b\n        let rec printDispatcher (first : bool) (perms : list<list<string>>) =\n            match perms with\n                | [] -> ()\n                | [perm] ->\n                    let suffix = perm |> String.concat \"\"\n                    if first then\n                        line \"x.%s%s(%s)\" name suffix argRef\n                    else\n                        line \"else x.%s%s(%s)\" name suffix argRef\n                | perm :: rest ->\n                    let suffix = perm |> String.concat \"\"\n                    let cond = if first then \"if\" else \"elif\"\n                    let all = allComparisons Map.empty [] perm\n                    let condition = all |> Map.filter (fun k _ -> Set.contains k comparisons) |> Map.toSeq |> Seq.map (fun ((a,b),c) -> sprintf \"c%s%s %s\" a b c) |> String.concat \" && \"\n                    line \"%s %s then x.%s%s(%s)\" cond condition name suffix argRef\n                    printDispatcher false rest\n                    \n                    \n        printDispatcher true (allPermutations componentNames)\n        stop()\n\n    let copyTo (componentNames : list<string>) (otherName : string) (otherGenArg : string) (args : list<string * string>) (op : string -> string -> string) =\n        for perm in allPermutations componentNames do copyToInternal otherName otherGenArg args op (List.toArray perm)\n        \n        let check () =\n            start \"if info.Size <> y.Size then\"\n            line \"failwithf \\\"%s size mismatch: { src = %%A; dst = %%A }\\\" info.Size y.Size\" otherName \n            stop()\n        \n        dispatcher check componentNames \"CopyTo\" ((\"y\", sprintf \"%s<%s>\" otherName otherGenArg) :: args)\n        \n\n\n\n    let sliced (name : string) (args : int -> list<string * string>) (op : int -> string -> string) (pinned : Set<string>) (componentNames : list<string>) =\n        \n        let free = Set.difference (Set.ofList componentNames) pinned\n        let viewDim = Set.count free\n        if viewDim > 0 then\n            \n            let lastManaged = getManagedName viewDim\n            let lastName = getNativeName viewDim\n            let otherComponents = componentNames |> List.filter (fun c -> not (Set.contains c pinned))\n\n            for long in [false; true] do\n                let indexType = if long then \"int64\" else \"int\"\n                let optionType = if long then \"Option<int64>\" else \"Option<int>\"\n                let zero = if long then \"0L\" else \"0\"\n                let one = if long then \"1L\" else \"1\"\n                let cast = if long then \"\" else \" |> int64\"\n                let intCast = if long then \"\" else \"int \"\n\n                let minMaxArgs = \n                    componentNames |> List.collect (fun c -> \n                        if Set.contains c pinned then [sprintf \"min%s\" c, indexType ]\n                        else [sprintf \"min%s\" c, optionType; sprintf \"max%s\" c, optionType]\n                    )\n                let args = args viewDim\n                let argDef = (minMaxArgs @ args) |> List.map (fun (n, t) -> sprintf \"%s : %s\" n t) |> String.concat \", \"\n                start \"member x.%s(%s) = \" name argDef\n                for c in componentNames do\n                    if Set.contains c pinned then\n                        line \"let begin%s = min%s%s\" c c cast\n                    else\n                        line \"let begin%s = defaultArg min%s %s%s\" c c zero cast\n                        line \"let max%s = defaultArg max%s (%sinfo.S%s - %s)%s\" c c intCast c one cast\n                        line \"let size%s = 1L + max%s - begin%s\" c c c \n                \n\n                let offsetRef = componentNames |> List.map (sprintf \"begin%s\") |> String.concat \", \"\n                let sizeRef = otherComponents |> List.map (sprintf \"size%s\") |> String.concat \", \"\n                let deltaRef = otherComponents |> List.map (sprintf \"info.D%s\") |> String.concat \", \"\n                \n                match Map.tryFind viewDim vectorNames with\n                    | Some (longName, _) ->\n                        line \"let info = %sInfo(info.Index(%s), %s(%s), %s(%s))\" lastManaged offsetRef longName sizeRef longName deltaRef\n                    | None -> \n                        line \"let info = %sInfo(info.Index(%s), %s, %s)\" lastManaged offsetRef sizeRef deltaRef\n                line \"let res = %s<'a>(ptr, info)\" lastName\n                line \"%s\" (op viewDim \"res\")\n                stop()\n\n\n    let tensor (dim : int) =\n        let managedName = getManagedName dim\n        let infoName = managedName + \"Info\"\n        let name = getNativeName dim\n        let componentNames = Array.take dim componentNames |> Array.toList\n        let pixName = Map.tryFind dim pixNames\n\n\n        let tFloat = \n            match Map.tryFind dim floatVectorNames with\n                | Some (dv,_) -> dv\n                | None -> \"float\"\n\n        let zFloat =\n            if dim = 1 then \"0.0\"\n            else sprintf \"%s.Zero\" tFloat\n        \n        let oFloat =\n            if dim = 1 then \"1.0\"\n            else sprintf \"%s.One\" tFloat\n\n        line \"[<Sealed>]\"\n        start \"type %s<'a when 'a : unmanaged>(ptr : nativeptr<'a>, info : %s) = \" name infoName\n        line \"member x.Pointer = ptr\"\n        line \"member x.Address = NativePtr.toNativeInt ptr\"\n        line \"member x.Info = info\"\n        line \"member x.Size = info.Size\"\n        line \"member x.Delta = info.Delta\"\n        line \"member x.Origin = info.Origin\"\n\n        for c in componentNames do\n            line \"member x.S%s = info.S%s\" c c\n        for c in componentNames do\n            line \"member x.D%s = info.D%s\" c c\n        \n\n        // Set (value)\n        for perm in allPermutations componentNames do setter (List.toArray perm)\n        dispatcher id componentNames \"Set\" [\"value\", \"'a\"]\n        \n        // SetByCoord (value)\n        for coord in CoordDescription.all dim do\n            for perm in allPermutations componentNames do coordSetter coord (List.toArray perm)\n            dispatcher id componentNames \"SetByCoord\" [\"value\", sprintf \"%s -> 'a\" coord.typ]\n\n        // IterPtr (action)\n        for coord in CoordDescription.all dim do\n            for perm in allPermutations componentNames do iterPtr coord (List.toArray perm)\n            dispatcher id componentNames \"IterPtr\" [\"action\", sprintf \"%s -> nativeptr<'a> -> unit\" coord.typ]\n\n        // Iter (action)\n        for coord in CoordDescription.all dim do\n            start \"member x.Iter(action : %s -> 'a -> unit) = \" coord.typ\n            line \"x.IterPtr(fun coord ptr -> action coord (NativePtr.read ptr))\"\n            stop()\n\n        // IterPtr2 (other, action)\n        for coord in CoordDescription.all dim do\n            for perm in allPermutations componentNames do iterPtr2 coord (List.toArray perm)\n\n            let check () =\n                start \"if info.Size <> other.Info.Size then\"\n                line \"failwithf \\\"%s size mismatch: { src = %%A; dst = %%A }\\\" info.Size other.Info.Size\" name\n                stop()\n\n            dispatcher check componentNames \"IterPtr2\" [\n                    \"other\", sprintf \"%s<'b>\" name\n                    \"action\", sprintf \"%s -> nativeptr<'a> -> nativeptr<'b> -> unit\" coord.typ\n                ]\n\n        // Iter2 (other, action)\n        for coord in CoordDescription.all dim do\n            start \"member x.Iter2(other : %s<'b>, action : %s -> 'a -> 'b -> unit) = \" name coord.typ\n            line \"x.IterPtr2(other, fun coord p1 p2 -> action coord (NativePtr.read p1) (NativePtr.read p2))\"\n            stop()\n\n        // BlitTo(other, lerp) \n        for perm in allPermutations componentNames do \n            blitInternal (List.toArray perm)\n        dispatcher id componentNames \"BlitTo\" [\"y\", sprintf \"%s<'a>\" name; \"srcOffset\", tFloat; \"srcSize\", tFloat; \"lerp\", \"float -> 'a -> 'a -> 'a\"]\n\n        line \"member x.BlitTo(y : %s<'a>, lerp : float -> 'a -> 'a -> 'a) = x.BlitTo(y, %s, %s, lerp)\" name zFloat oFloat\n        \n        // Item\n        item dim\n\n        // CopyTo(other)\n        copyTo componentNames name \"'a\" [] (fun l r -> sprintf \"NativePtr.write (NativePtr.ofNativeInt<'a> %s) (NativePtr.read (NativePtr.ofNativeInt<'a> %s))\" r l)\n        \n        // CopyTo(other, transform)\n        copyTo componentNames name \"'b\" [\"f\", \"'a -> 'b\"] (fun l r -> sprintf \"NativePtr.write (NativePtr.ofNativeInt<'b> %s) (f (NativePtr.read (NativePtr.ofNativeInt<'a> %s)))\" r l)\n\n        sampleNearest dim\n        //sampleLinear dim true\n        sampleLinear dim\n\n        let offsets = componentNames |> List.map (sprintf \"begin%s\")\n        let sizes = componentNames |> List.map (sprintf \"size%s\")\n        let deltas = componentNames |> List.map (sprintf \"delta%s\")\n\n        let offsetDef = offsets |> List.map (sprintf \"%s : int64\") |> String.concat \", \"\n        let offsetRef = offsets |> String.concat \", \"\n        let sizeDef = sizes |> List.map (sprintf \"%s : int64\") |> String.concat \", \"\n        let sizeRef = sizes |> String.concat \", \"\n        let deltaDef = deltas |> List.map (sprintf \"%s : int64\") |> String.concat \", \"\n        let deltaRef = deltas |> String.concat \", \"\n\n\n        start \"static member Using<'b> (m : %s<'a>, f : %s<'a> -> 'b) = \" managedName name \n        line \"let gc = GCHandle.Alloc(m.Data, GCHandleType.Pinned)\"\n        line \"try f (%s<'a>(NativePtr.ofNativeInt (gc.AddrOfPinnedObject()), m.Info))\" name\n        line \"finally gc.Free()\"\n        stop()\n\n        \n        line \"member x.Sub%s(%s, %s, %s) = %s<'a>(ptr, info.Sub%s(%s, %s, %s))\" managedName offsetDef sizeDef deltaDef name managedName offsetRef sizeRef deltaRef\n        line \"member x.Sub%s(%s, %s) = %s<'a>(ptr, info.Sub%s(%s, %s))\" managedName offsetDef sizeDef name managedName offsetRef sizeRef\n        \n        match Map.tryFind dim vectorNames with\n            | Some (longName, intName) ->\n                line \"member x.Sub%s(offset : %s, size : %s) = %s<'a>(ptr, info.Sub%s(offset, size))\" managedName longName longName name managedName\n                line \"member x.Sub%s(offset : %s, size : %s, delta : %s) = %s<'a>(ptr, info.Sub%s(offset, size, delta))\" managedName longName longName longName name managedName\n                line \"member x.Sub%s(offset : %s, size : %s) = %s<'a>(ptr, info.Sub%s(offset, size))\" managedName intName intName name managedName\n                line \"member x.Sub%s(offset : %s, size : %s, delta : %s) = %s<'a>(ptr, info.Sub%s(offset, size, delta))\" managedName intName intName intName name managedName\n            | _ ->\n                ()\n\n        for pinned in allSubsets componentNames do\n            // GetSlice()\n            sliced \"GetSlice\" (fun _ -> []) (fun _ v -> v) pinned componentNames\n\n            // SetSlice(value)\n            sliced \"SetSlice\" (fun _ -> [\"value\", \"'a\"]) (fun _ -> sprintf \"%s.Set(value)\") pinned componentNames \n\n            //SetSlice(NativeTensor)\n            sliced \"SetSlice\" (fun view -> [\"src\", sprintf \"%s<'a>\" (getNativeName view)]) (fun _ -> sprintf \"src.CopyTo(%s)\") pinned componentNames \n\n            //SetSlice(ManagedTensor)\n            sliced \"SetSlice\" (fun view -> [\"src\", sprintf \"%s<'a>\" (getManagedName view)]) (fun dim res -> sprintf \"%s<'a>.Using(src, fun src -> src.CopyTo(%s))\" (getNativeName dim) res) pinned componentNames \n\n\n        stop()\n        line \"\"\n        \n        let lv, iv = \n            match Map.tryFind dim vectorNames with\n                | Some t -> t\n                | None -> \"int64\", \"int\"\n\n        let dv, fv = \n            match Map.tryFind dim floatVectorNames with\n                | Some t -> t\n                | None -> \"float\", \"float32\"\n\n        line \"/// The %s module providers convenient F#-style functions for accessing %ss\" name name\n        start \"module %s =\" name\n\n        line \"/// Creates a new %s from the given address and info struct\" name\n        line \"let inline ofNativeInt<'a when 'a : unmanaged> (info : %s) (address : nativeint) = %s<'a>(NativePtr.ofNativeInt address, info)\" infoName name\n        line \"\"\n\n        start \"let inline private lerpy< ^a, ^b when (^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b)> (_ : ^a) (t : float) (a : ^b) (b : ^b) =\"\n        line \"((^a or ^b) : (static member Lerp : float * ^b * ^b -> ^b) (t, a,b))\"\n        stop()\n\n        line \"let inline private lerper t a b = lerpy (Unchecked.defaultof<Fun>) t a b\"\n\n\n\n        line \"/// Sets the entire %s to the given value\" managedName\n        line \"let inline set (value : 'a) (dst : %s<'a>) = dst.Set(value)\" name \n        \n        line \"\"\n        line \"/// Sets each entry to the value computed by getValue\"\n        line \"let inline setByCoord (getValue : %s -> 'a) (m : %s<'a>) = m.SetByCoord(getValue)\" lv name \n        \n        if dim > 1 then\n            line \"\"\n            line \"let inline sample (location : %s) (m : %s<'a>) = m.SampleLinear(location, lerper)\" dv name \n        \n        line \"\"\n        line \"let inline blit (src : %s<'a>) (dst : %s<'a>) = src.BlitTo(dst, lerper)\" name name \n        \n        line \"\"\n        line \"/// Copies the content of 'src' to 'dst'\"\n        line \"let inline copy (src : %s<'a>) (dst : %s<'a>) = src.CopyTo(dst)\" name name \n        line \"\"\n        line \"/// Copies the content of 'src' to 'dst' by applying the given function\"\n        line \"let inline copyWith (f : 'a -> 'b) (src : %s<'a>) (dst : %s<'b>) = src.CopyTo(dst, f)\" name name \n        line \"\"\n        line \"/// Temporarily pins a %s making it available as %s\" managedName name\n        line \"let using (m : %s<'a>) (f : %s<'a> -> 'b) = %s<'a>.Using(m, f)\" managedName name  name\n        line \"\"\n        line \"/// Iterates over all entries of the given %s and executes the given action\" name\n        line \"let inline iter (action : %s -> 'a -> unit) (m : %s<'a>) = m.Iter(action)\" lv name\n        line \"\"\n        line \"/// Iterates over all entries of the given %s and executes the given action\" name\n        line \"let inline iterPtr (action : %s -> nativeptr<'a> -> unit) (m : %s<'a>) = m.IterPtr(action)\" lv name \n        line \"\"\n        line \"/// Iterates over all entries of both of the given %ss and executes the given action\" name\n        line \"let inline iter2 (action : %s -> 'a -> 'b -> unit) (l : %s<'a>) (r : %s<'b>) = l.Iter2(r, action)\" lv name name\n        line \"\"\n        line \"/// Iterates over all entries of both of the given %ss and executes the given action\" name\n        line \"let inline iterPtr2 (action : %s -> nativeptr<'a> -> nativeptr<'b> -> unit) (l : %s<'a>) (r : %s<'b>) = l.IterPtr2(r, action)\" lv name name\n\n        stop()\n        line \"\"\n\n        match pixName with\n        | Some pix ->\n            line \"[<AutoOpen>]\"\n            start \"module %sTensorExtensions =\" pix\n            start \"module %s =\" pix\n\n            line \"/// Pins the given %s as a %s and executes the given action\" pix name\n            start \"let inline pin (pi : %s<'a>) (f : %s<'a> -> 'b) : 'b =\" pix name\n            line \"%s.using pi.%s f\" name managedName\n            stop()\n            line \"\"\n\n            line \"/// Pins the given %ss as a %ss and executes the given action\" pix name\n            start \"let inline pin2 (l : %s<'a>) (r : %s<'b>) (f : %s<'a> -> %s<'b> -> 'c)  : 'c =\" pix pix name name\n            line \"pin l (fun lv -> pin r (fun rv -> f lv rv))\"\n            stop()\n            line \"\"\n\n            line \"/// Copies the given %s to the given %s\" pix name\n            start \"let inline copyTo%s (dst : %s<'a>) (pix : %s<'a>)  =\" name name pix\n            line \"pin pix (fun src -> %s.copy src dst)\" name\n            stop()\n            line \"\"\n\n            line \"/// Copies from the given %s to the given %s\" name pix\n            start \"let inline copyFrom%s (src : %s<'a>) (pix : %s<'a>) =\" name name pix\n            line \"pin pix (fun dst -> %s.copy src dst)\" name\n            stop()\n            line \"\"\n\n            line \"[<AutoOpen>]\"\n            start \"module private CopyDispatch =\"\n            line \"let private flags = BindingFlags.Static ||| BindingFlags.NonPublic ||| BindingFlags.Public\"\n            line \"\"\n            start \"type private Dispatcher() =\"\n            start \"static member CopyImageToNative<'a when 'a : unmanaged>(src : %s<'a>, dst : nativeint, dstInfo : %sInfo) =\" pix managedName\n            line \"let dst = dst |> %s.ofNativeInt dstInfo\" name\n            line \"src |> copyTo%s dst\" name\n            stop()\n            line \"\"\n\n            start \"static member CopyNativeToImage<'a when 'a : unmanaged>(src : nativeint, srcInfo : %sInfo, dst : %s<'a>) =\" managedName pix\n            line \"let src = src |> %s.ofNativeInt srcInfo\" name\n            line \"dst |> copyFrom%s src\" name\n            stop()\n\n            stop() // Dispatcher end\n            line \"\"\n\n\n            start \"module ImageToNative =\"\n            line \"let private def = typeof<Dispatcher>.GetMethod(nameof Dispatcher.CopyImageToNative, flags)\"\n            line \"let private lookup = ConcurrentDictionary<Type, MethodInfo>()\"\n            line \"let getGenericMethod (t: Type) = lookup.GetOrAdd(t, fun t -> def.MakeGenericMethod t)\"\n            stop()\n            line \"\"\n\n            start \"module NativeToImage =\"\n            line \"let private def = typeof<Dispatcher>.GetMethod(nameof Dispatcher.CopyNativeToImage, flags)\"\n            line \"let private lookup = ConcurrentDictionary<Type, MethodInfo>()\"\n            line \"let getGenericMethod (t: Type) = lookup.GetOrAdd(t, fun t -> def.MakeGenericMethod t)\"\n            stop()\n            line \"\"\n\n            stop() // CopyDispatch end\n\n            line \"/// Copies the given untyped %s to the given native address\" pix\n            start \"let copyToNative (dst : nativeint) (dstInfo : %sInfo) (pix : %s) =\" managedName pix\n            line \"let mi = ImageToNative.getGenericMethod pix.PixFormat.Type\"\n            line \"mi.Invoke(null, [|pix; dst; dstInfo|]) |> ignore\"\n            stop()\n            line \"\"\n\n            line \"/// Copies from the given native address to the given untyped %s\" pix\n            start \"let copyFromNative (src : nativeint) (srcInfo : %sInfo) (pix : %s) =\" managedName pix\n            line \"let mi = NativeToImage.getGenericMethod pix.PixFormat.Type\"\n            line \"mi.Invoke(null, [|src; srcInfo; pix|]) |> ignore\"\n            stop()\n            line \"\"\n\n            stop()\n            stop()\n            line \"\"\n\n        | _ -> ()\n\n        line \"\"\n\n    let run() =\n        line \"namespace Aardvark.Base\"\n        line \"\"\n        line \"open Microsoft.FSharp.NativeInterop\"\n        line \"open System\"\n        line \"open System.Collections.Concurrent\"\n        line \"open System.Runtime.InteropServices\"\n        line \"open System.Reflection\"\n        line \"\"\n        line \"#nowarn \\\"9\\\"\"\n        line \"\"\n        for d in 1 .. 4 do\n            tensor d\n\n\n        let str = builder.ToString()\n        System.IO.File.WriteAllText(System.IO.Path.Combine(__SOURCE_DIRECTORY__, @\"NativeTensorGenerated.fs\"), str)\n\ndo Generator.run()"
  },
  {
    "path": "src/Aardvark.Base.Tensors/PixImage/ImageTrafo.fs",
    "content": "﻿namespace Aardvark.Base\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule ImageTrafo =\n    let private composeTable =\n        LookupTable.lookup [\n            struct (ImageTrafo.Identity, ImageTrafo.Identity), ImageTrafo.Identity\n            struct (ImageTrafo.Identity, ImageTrafo.Rot90), ImageTrafo.Rot90\n            struct (ImageTrafo.Identity, ImageTrafo.Rot180), ImageTrafo.Rot180\n            struct (ImageTrafo.Identity, ImageTrafo.Rot270), ImageTrafo.Rot270\n            struct (ImageTrafo.Identity, ImageTrafo.MirrorX), ImageTrafo.MirrorX\n            struct (ImageTrafo.Identity, ImageTrafo.Transpose), ImageTrafo.Transpose\n            struct (ImageTrafo.Identity, ImageTrafo.MirrorY), ImageTrafo.MirrorY\n            struct (ImageTrafo.Identity, ImageTrafo.Transverse), ImageTrafo.Transverse\n            struct (ImageTrafo.Rot90, ImageTrafo.Identity), ImageTrafo.Rot90\n            struct (ImageTrafo.Rot90, ImageTrafo.Rot90), ImageTrafo.Rot180\n            struct (ImageTrafo.Rot90, ImageTrafo.Rot180), ImageTrafo.Rot270\n            struct (ImageTrafo.Rot90, ImageTrafo.Rot270), ImageTrafo.Identity\n            struct (ImageTrafo.Rot90, ImageTrafo.MirrorX), ImageTrafo.Transverse\n            struct (ImageTrafo.Rot90, ImageTrafo.Transpose), ImageTrafo.MirrorX\n            struct (ImageTrafo.Rot90, ImageTrafo.MirrorY), ImageTrafo.Transpose\n            struct (ImageTrafo.Rot90, ImageTrafo.Transverse), ImageTrafo.MirrorY\n            struct (ImageTrafo.Rot180, ImageTrafo.Identity), ImageTrafo.Rot180\n            struct (ImageTrafo.Rot180, ImageTrafo.Rot90), ImageTrafo.Rot270\n            struct (ImageTrafo.Rot180, ImageTrafo.Rot180), ImageTrafo.Identity\n            struct (ImageTrafo.Rot180, ImageTrafo.Rot270), ImageTrafo.Rot90\n            struct (ImageTrafo.Rot180, ImageTrafo.MirrorX), ImageTrafo.MirrorY\n            struct (ImageTrafo.Rot180, ImageTrafo.Transpose), ImageTrafo.Transverse\n            struct (ImageTrafo.Rot180, ImageTrafo.MirrorY), ImageTrafo.MirrorX\n            struct (ImageTrafo.Rot180, ImageTrafo.Transverse), ImageTrafo.Transpose\n            struct (ImageTrafo.Rot270, ImageTrafo.Identity), ImageTrafo.Rot270\n            struct (ImageTrafo.Rot270, ImageTrafo.Rot90), ImageTrafo.Identity\n            struct (ImageTrafo.Rot270, ImageTrafo.Rot180), ImageTrafo.Rot90\n            struct (ImageTrafo.Rot270, ImageTrafo.Rot270), ImageTrafo.Rot180\n            struct (ImageTrafo.Rot270, ImageTrafo.MirrorX), ImageTrafo.Transpose\n            struct (ImageTrafo.Rot270, ImageTrafo.Transpose), ImageTrafo.MirrorY\n            struct (ImageTrafo.Rot270, ImageTrafo.MirrorY), ImageTrafo.Transverse\n            struct (ImageTrafo.Rot270, ImageTrafo.Transverse), ImageTrafo.MirrorX\n            struct (ImageTrafo.MirrorX, ImageTrafo.Identity), ImageTrafo.MirrorX\n            struct (ImageTrafo.MirrorX, ImageTrafo.Rot90), ImageTrafo.Transpose\n            struct (ImageTrafo.MirrorX, ImageTrafo.Rot180), ImageTrafo.MirrorY\n            struct (ImageTrafo.MirrorX, ImageTrafo.Rot270), ImageTrafo.Transverse\n            struct (ImageTrafo.MirrorX, ImageTrafo.MirrorX), ImageTrafo.Identity\n            struct (ImageTrafo.MirrorX, ImageTrafo.Transpose), ImageTrafo.Rot90\n            struct (ImageTrafo.MirrorX, ImageTrafo.MirrorY), ImageTrafo.Rot180\n            struct (ImageTrafo.MirrorX, ImageTrafo.Transverse), ImageTrafo.Rot270\n            struct (ImageTrafo.Transpose, ImageTrafo.Identity), ImageTrafo.Transpose\n            struct (ImageTrafo.Transpose, ImageTrafo.Rot90), ImageTrafo.MirrorY\n            struct (ImageTrafo.Transpose, ImageTrafo.Rot180), ImageTrafo.Transverse\n            struct (ImageTrafo.Transpose, ImageTrafo.Rot270), ImageTrafo.MirrorX\n            struct (ImageTrafo.Transpose, ImageTrafo.MirrorX), ImageTrafo.Rot270\n            struct (ImageTrafo.Transpose, ImageTrafo.Transpose), ImageTrafo.Identity\n            struct (ImageTrafo.Transpose, ImageTrafo.MirrorY), ImageTrafo.Rot90\n            struct (ImageTrafo.Transpose, ImageTrafo.Transverse), ImageTrafo.Rot180\n            struct (ImageTrafo.MirrorY, ImageTrafo.Identity), ImageTrafo.MirrorY\n            struct (ImageTrafo.MirrorY, ImageTrafo.Rot90), ImageTrafo.Transverse\n            struct (ImageTrafo.MirrorY, ImageTrafo.Rot180), ImageTrafo.MirrorX\n            struct (ImageTrafo.MirrorY, ImageTrafo.Rot270), ImageTrafo.Transpose\n            struct (ImageTrafo.MirrorY, ImageTrafo.MirrorX), ImageTrafo.Rot180\n            struct (ImageTrafo.MirrorY, ImageTrafo.Transpose), ImageTrafo.Rot270\n            struct (ImageTrafo.MirrorY, ImageTrafo.MirrorY), ImageTrafo.Identity\n            struct (ImageTrafo.MirrorY, ImageTrafo.Transverse), ImageTrafo.Rot90\n            struct (ImageTrafo.Transverse, ImageTrafo.Identity), ImageTrafo.Transverse\n            struct (ImageTrafo.Transverse, ImageTrafo.Rot90), ImageTrafo.MirrorX\n            struct (ImageTrafo.Transverse, ImageTrafo.Rot180), ImageTrafo.Transpose\n            struct (ImageTrafo.Transverse, ImageTrafo.Rot270), ImageTrafo.MirrorY\n            struct (ImageTrafo.Transverse, ImageTrafo.MirrorX), ImageTrafo.Rot90\n            struct (ImageTrafo.Transverse, ImageTrafo.Transpose), ImageTrafo.Rot180\n            struct (ImageTrafo.Transverse, ImageTrafo.MirrorY), ImageTrafo.Rot270\n            struct (ImageTrafo.Transverse, ImageTrafo.Transverse), ImageTrafo.Identity\n        ]\n\n    let compose (l : ImageTrafo) (r : ImageTrafo) =\n        composeTable (struct (l, r))\n\n    let inverse =\n        LookupTable.lookup [\n            ImageTrafo.MirrorX, ImageTrafo.MirrorX\n            ImageTrafo.MirrorY, ImageTrafo.MirrorY\n            ImageTrafo.Identity, ImageTrafo.Identity\n            ImageTrafo.Rot180, ImageTrafo.Rot180\n            ImageTrafo.Rot270, ImageTrafo.Rot90\n            ImageTrafo.Rot90, ImageTrafo.Rot270\n            ImageTrafo.Transpose, ImageTrafo.Transpose\n            ImageTrafo.Transverse, ImageTrafo.Transverse\n        ]\n\n    let transformSize (s : V2i) (t : ImageTrafo) =\n        match t with\n        | ImageTrafo.Identity | ImageTrafo.Rot180 | ImageTrafo.MirrorX | ImageTrafo.MirrorY -> s\n        | ImageTrafo.Rot270 | ImageTrafo.Rot90 | ImageTrafo.Transpose | ImageTrafo.Transverse -> V2i(s.Y, s.X)\n        | _ -> failwithf \"[ImageTrafo] unknown value %A\" t\n\n    let inverseTransformSize (s : V2i) (t : ImageTrafo) =\n        transformSize s t"
  },
  {
    "path": "src/Aardvark.Base.Tensors/PixImage/PixCube.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System.Runtime.CompilerServices\nopen System.Runtime.InteropServices\n\n[<AutoOpen>]\nmodule FSharpPixCubeExtensions =\n\n    type PixCube with\n\n        member x.Transformed (m : CubeSide -> CubeSide * ImageTrafo) =\n            PixCube(\n                x.MipMapArray\n                    |> Array.mapi (fun i mipMap ->\n                        let side = unbox<CubeSide> i\n                        let (newSide, trafo) = m side\n                        newSide, PixImageMipMap (mipMap.ImageArray |> Array.map _.TransformedPixImage(trafo))\n                    )\n                    |> Map.ofArray\n                    |> Map.toArray\n                    |> Array.map snd\n            )\n\n        member x.Transformed (m : Map<CubeSide, CubeSide * ImageTrafo>) =\n            x.Transformed (fun side ->\n                match Map.tryFind side m with\n                    | Some t -> t\n                    | None ->\n                        Log.warn \"incomplete CubeMap trafo\"\n                        (side, ImageTrafo.Identity)\n\n            )\n\n        static member Create (images : Map<CubeSide, PixImageMipMap>) =\n            PixCube(images |> Map.toArray |> Array.map snd)\n\n        static member Create (images : Map<CubeSide, PixImage>) =\n            PixCube(images |> Map.toArray |> Array.map (fun (_,pi) -> PixImageMipMap [|pi|]))\n\n        static member Load (images : Map<CubeSide, string>, [<Optional; DefaultParameterValue(null : IPixLoader)>] loader : IPixLoader) =\n            PixCube(images |> Map.toArray |> Array.map (fun (_,file) -> PixImageMipMap [|PixImage.Load(file, loader)|]))\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module PixCube =\n\n        module Trafo =\n\n            let private identity =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.PositiveX, ImageTrafo.Identity)\n                    CubeSide.PositiveY, (CubeSide.PositiveY, ImageTrafo.Identity)\n                    CubeSide.PositiveZ, (CubeSide.PositiveZ, ImageTrafo.Identity)\n                    CubeSide.NegativeX, (CubeSide.NegativeX, ImageTrafo.Identity)\n                    CubeSide.NegativeY, (CubeSide.NegativeY, ImageTrafo.Identity)\n                    CubeSide.NegativeZ, (CubeSide.NegativeZ, ImageTrafo.Identity)\n                ]\n\n            let private compose (l : Map<CubeSide, CubeSide * ImageTrafo>) (r : Map<CubeSide, CubeSide * ImageTrafo>) : Map<CubeSide, CubeSide * ImageTrafo> =\n                l |> Map.map (fun s (ts, lt) ->\n                    match Map.tryFind ts r with\n                        | Some (fs, rt) -> fs, ImageTrafo.compose lt rt\n                        | None -> ts, lt\n                )\n\n            let private all (l : seq<Map<CubeSide, CubeSide * ImageTrafo>>) =\n                l |> Seq.fold compose identity\n\n            let RotX90 =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.PositiveX, ImageTrafo.Rot90)\n                    CubeSide.NegativeX, (CubeSide.NegativeX, ImageTrafo.Rot270)\n                    CubeSide.PositiveZ, (CubeSide.NegativeY, ImageTrafo.Identity)\n                    CubeSide.NegativeZ, (CubeSide.PositiveY, ImageTrafo.Rot180)\n                    CubeSide.PositiveY, (CubeSide.PositiveZ, ImageTrafo.Identity)\n                    CubeSide.NegativeY, (CubeSide.NegativeZ, ImageTrafo.Rot180)\n                ]\n\n            let RotX180 = compose RotX90 RotX90\n            let RotX270 = compose RotX180 RotX90\n\n\n            let RotY90 =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.NegativeZ, ImageTrafo.Identity)\n                    CubeSide.NegativeX, (CubeSide.PositiveZ, ImageTrafo.Identity)\n                    CubeSide.PositiveZ, (CubeSide.PositiveX, ImageTrafo.Identity)\n                    CubeSide.NegativeZ, (CubeSide.NegativeX, ImageTrafo.Identity)\n                    CubeSide.NegativeY, (CubeSide.NegativeY, ImageTrafo.Rot270)\n                    CubeSide.PositiveY, (CubeSide.PositiveY, ImageTrafo.Rot90)\n                ]\n\n            let RotY180 = compose RotY90 RotY90\n            let RotY270 = compose RotY180 RotY90\n\n            let RotZ90 =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.PositiveY, ImageTrafo.Rot90)\n                    CubeSide.NegativeX, (CubeSide.NegativeY, ImageTrafo.Rot90)\n                    CubeSide.PositiveZ, (CubeSide.PositiveZ, ImageTrafo.Rot90)\n                    CubeSide.NegativeZ, (CubeSide.NegativeZ, ImageTrafo.Rot270)\n                    CubeSide.PositiveY, (CubeSide.NegativeX, ImageTrafo.Rot90)\n                    CubeSide.NegativeY, (CubeSide.PositiveX, ImageTrafo.Rot90)\n                ]\n\n            let RotZ180 = compose RotZ90 RotZ90\n            let RotZ270 = compose RotZ180 RotZ90\n\n            let InvertX =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.NegativeX, ImageTrafo.MirrorX)\n                    CubeSide.NegativeX, (CubeSide.PositiveX, ImageTrafo.MirrorX)\n                    CubeSide.PositiveZ, (CubeSide.PositiveZ, ImageTrafo.MirrorX)\n                    CubeSide.NegativeZ, (CubeSide.NegativeZ, ImageTrafo.MirrorX)\n                    CubeSide.NegativeY, (CubeSide.NegativeY, ImageTrafo.MirrorX)\n                    CubeSide.PositiveY, (CubeSide.PositiveY, ImageTrafo.MirrorX)\n                ]\n\n            let InvertY =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.PositiveX, ImageTrafo.MirrorY)\n                    CubeSide.NegativeX, (CubeSide.NegativeX, ImageTrafo.MirrorY)\n                    CubeSide.PositiveY, (CubeSide.NegativeY, ImageTrafo.MirrorY)\n                    CubeSide.NegativeY, (CubeSide.PositiveY, ImageTrafo.MirrorY)\n                    CubeSide.PositiveZ, (CubeSide.PositiveZ, ImageTrafo.MirrorY)\n                    CubeSide.NegativeZ, (CubeSide.NegativeZ, ImageTrafo.MirrorY)\n                ]\n\n            let InvertZ =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.PositiveX, ImageTrafo.MirrorX)\n                    CubeSide.NegativeX, (CubeSide.NegativeX, ImageTrafo.MirrorX)\n                    CubeSide.PositiveZ, (CubeSide.NegativeZ, ImageTrafo.MirrorX)\n                    CubeSide.NegativeZ, (CubeSide.PositiveZ, ImageTrafo.MirrorX)\n                    CubeSide.NegativeY, (CubeSide.NegativeY, ImageTrafo.MirrorY)\n                    CubeSide.PositiveY, (CubeSide.PositiveY, ImageTrafo.MirrorY)\n                ]\n\n            let OfOpenGlConventionTrafo =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.PositiveX, ImageTrafo.MirrorX)\n                    CubeSide.NegativeX, (CubeSide.NegativeX, ImageTrafo.MirrorX)\n                    CubeSide.PositiveZ, (CubeSide.NegativeZ, ImageTrafo.MirrorX)\n                    CubeSide.NegativeZ, (CubeSide.PositiveZ, ImageTrafo.MirrorX)\n                    CubeSide.NegativeY, (CubeSide.NegativeY, ImageTrafo.MirrorY)\n                    CubeSide.PositiveY, (CubeSide.PositiveY, ImageTrafo.MirrorY)\n                ]\n\n            let ToOpenGlConventionTrafo =\n                Map.ofList [\n                    CubeSide.PositiveX, (CubeSide.PositiveX, ImageTrafo.MirrorY)\n                    CubeSide.NegativeX, (CubeSide.NegativeX, ImageTrafo.MirrorY)\n                    CubeSide.PositiveZ, (CubeSide.NegativeZ, ImageTrafo.Rot180)\n                    CubeSide.NegativeZ, (CubeSide.PositiveZ, ImageTrafo.Rot180)\n                    CubeSide.PositiveY, (CubeSide.PositiveY, ImageTrafo.Identity)\n                    CubeSide.NegativeY, (CubeSide.NegativeY, ImageTrafo.Identity)\n                ]\n\n        let load (faceFiles : list<CubeSide * string>) =\n            let faces =\n                faceFiles\n                    |> List.map (fun (s,file) -> s, PixImageMipMap [| PixImage.Load(file) |])\n                    |> List.sortBy fst\n                    |> List.map snd\n                    |> List.toArray\n\n            PixCube(faces)\n\n        let rotX90 (c : PixCube) =\n            c.Transformed Trafo.RotX90\n\n        let rotX180 (c : PixCube) =\n            c.Transformed Trafo.RotX180\n\n        let rotX270 (c : PixCube) =\n            c.Transformed Trafo.RotX270\n\n        let rotY90 (c : PixCube) =\n            c.Transformed Trafo.RotY90\n\n        let rotY180 (c : PixCube) =\n            c.Transformed Trafo.RotY180\n\n        let rotY270 (c : PixCube) =\n            c.Transformed Trafo.RotY270\n\n        let rotZ90 (c : PixCube) =\n            c.Transformed Trafo.RotZ90\n\n        let rotZ180 (c : PixCube) =\n            c.Transformed Trafo.RotZ180\n\n        let rotZ270 (c : PixCube) =\n            c.Transformed Trafo.RotZ270\n\n        let invertX (c : PixCube) =\n            c.Transformed Trafo.InvertX\n\n        let invertY (c : PixCube) =\n            c.Transformed Trafo.InvertY\n\n        let invertZ (c : PixCube) =\n            c.Transformed Trafo.InvertZ\n\n        let ofOpenGlConvention (c : PixCube) =\n            c.Transformed Trafo.OfOpenGlConventionTrafo\n\n        let toOpenGlConvention (c : PixCube) =\n            c.Transformed Trafo.ToOpenGlConventionTrafo\n\n[<AbstractClass; Sealed; Extension>]\ntype PixCubeExtensions private() =\n\n    [<Extension>]\n    static member Transformed(x : PixCube, f : System.Func<CubeSide, Tup<CubeSide, ImageTrafo>>) =\n        x.Transformed(fun side ->\n            let t = f.Invoke(side)\n            t.E0, t.E1\n        )\n\n    [<Extension>]\n    static member Transformed(x : PixCube, d : System.Collections.Generic.Dictionary<CubeSide, Tup<CubeSide, ImageTrafo>>) =\n        x.Transformed (fun side ->\n            match d.TryGetValue side with\n                | (true, t) -> t.E0, t.E1\n                | _ ->\n                    Log.warn \"incomplete CubeMap trafo\"\n                    side, ImageTrafo.Identity\n        )\n\n\n    [<Extension>] static member RotX90(x : PixCube) = PixCube.rotX90 x\n    [<Extension>] static member RotX180(x : PixCube) = PixCube.rotX180 x\n    [<Extension>] static member RotX270(x : PixCube) = PixCube.rotX270 x\n\n    [<Extension>] static member RotY90(x : PixCube) = PixCube.rotY90 x\n    [<Extension>] static member RotY180(x : PixCube) = PixCube.rotY180 x\n    [<Extension>] static member RotY270(x : PixCube) = PixCube.rotY270 x\n\n    [<Extension>] static member RotZ90(x : PixCube) = PixCube.rotZ90 x\n    [<Extension>] static member RotZ180(x : PixCube) = PixCube.rotZ180 x\n    [<Extension>] static member RotZ270(x : PixCube) = PixCube.rotZ270 x\n\n    [<Extension>] static member InvertX(x : PixCube) = PixCube.invertX x\n    [<Extension>] static member InvertY(x : PixCube) = PixCube.invertY x\n    [<Extension>] static member InvertZ(x : PixCube) = PixCube.invertZ x\n    [<Extension>] static member FromOpenGlConvention(x : PixCube) = PixCube.ofOpenGlConvention x\n    [<Extension>] static member ToOpenGlConvention(x : PixCube) = PixCube.toOpenGlConvention x"
  },
  {
    "path": "src/Aardvark.Base.Tensors/PixImage/PixImageErrorMetric.fs",
    "content": "﻿namespace Aardvark.Base\n\nopen System\nopen System.ComponentModel\n\n[<AutoOpen>]\nmodule FSharpPixImageErrorMetricExtensions =\n\n    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\n    module PixImage =\n\n        [<EditorBrowsable(EditorBrowsableState.Never)>]\n        module ErrorMetricHelpers =\n\n            let maxValues =\n                LookupTable.lookup [\n                    typeof<uint8>,   255.0\n                    typeof<int8>,    255.0\n                    typeof<uint16>,  65535.0\n                    typeof<int16>,   65535.0\n                    typeof<int32>,   4294967295.0\n                    typeof<uint32>,  4294967295.0\n                    typeof<float16>, 1.0\n                    typeof<float32>, 1.0\n                    typeof<float>,   1.0\n                ]\n\n        open ErrorMetricHelpers\n\n        /// Computes the mean squared error between two images.\n        /// The images may have different channel counts, excess channels are ignored.\n        let inline meanSquaredError (input : PixImage<'T>) (output : PixImage<'T>) =\n            if input.Size <> output.Size then\n                raise <| ArgumentException(\"Image sizes do not match.\")\n\n            let mutable error = KahanSum()\n            let channels = min input.ChannelCount output.ChannelCount\n            let count = output.Size.X * output.Size.Y * channels\n\n            for x in 0 .. output.Size.X - 1 do\n                for y in 0 .. output.Size.Y - 1 do\n                    for c in 0 .. channels - 1 do\n                        let inputData = input.GetChannel(int64 c)\n                        let outputData = output.GetChannel(int64 c)\n\n                        let diff = float inputData.[x, y] - float outputData.[x, y]\n                        error.Add ((diff * diff) / float count)\n\n            error.Value\n\n        /// Computes the peak signal-to-noise ratio between two images.\n        /// The images may have different channel counts, excess channels are ignored.\n        let inline peakSignalToNoiseRatio' (maxValue : float) (input : PixImage<'T>) (output : PixImage<'T>) =\n            20.0 * (log10 maxValue) - 10.0 * log10 (meanSquaredError input output)\n\n        /// Computes the peak signal-to-noise ratio between two images.\n        /// The images may have different channel counts, excess channels are ignored.\n        let inline peakSignalToNoiseRatio (input : PixImage<'T>) (output : PixImage<'T>) =\n            let maxValue = maxValues typeof<'T>\n            peakSignalToNoiseRatio' maxValue input output"
  },
  {
    "path": "src/Aardvark.Base.Tensors/paket.references",
    "content": "FSharp.Core\nAardvark.Build"
  },
  {
    "path": "src/Aardvark.Base.Tensors/paket.template",
    "content": "type project\nid Aardvark.Base.Tensors\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true\ninclude-referenced-projects true"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Aardvark.Base.Tensors.CSharp.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <OutputType>Library</OutputType>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <LangVersion>10.0</LangVersion>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <NoWarn>1591</NoWarn>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\bin\\Debug\\</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Remove=\"**\\*_template.cs\" />\n    <Compile Remove=\"**\\*_generator.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"**\\*_template.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Aardvark.Base\\Aardvark.Base.csproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Algorithms/LuFactorization.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static partial class TensorNumericExtensions\n    {\n        #region Partially pivoting LU factorization of Matrix<float>\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is returned as a permutation vector, and the supplied matrix A is\n        /// overwritten with its factorization LU, both in the parameter\n        /// inputAndLuMatrix. If the supplied matrix is singular, null is\n        /// returned.\n        /// </summary>\n        public static int[] LuFactorize(this Matrix<float> inputAndLuMatrix)\n        {\n            var n = inputAndLuMatrix.SX;\n            if (n != inputAndLuMatrix.SY) throw new ArgumentException(\"cannot factorize non-square matrix\");\n            var p = new int[n];\n            if (inputAndLuMatrix.Data.LuFactorize(inputAndLuMatrix.Origin,\n                        inputAndLuMatrix.DX, inputAndLuMatrix.DY, p))\n                return p;\n            return null;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The solution vector x is returned.\n        /// </summary>\n        public static Vector<float> LuSolve(this Matrix<float> luMatrix, int[] p, Vector<float> b)\n        {\n            var x = new Vector<float>(b.Info);\n            luMatrix.Data.LuSolve(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                  b.Data, b.Origin, b.Delta, x.Data, x.Origin, x.Delta);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is the right hand side\n        /// supplied as a matrix. The solution matrix x is returned.\n        /// </summary>\n        public static Matrix<float> LuSolve(this Matrix<float> luMatrix, int[] p, Matrix<float> b)\n        {\n            var x = new Matrix<float>(b.Info);\n            luMatrix.Data.LuSolve(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                  b.SX, b.Data, b.Origin, b.DX, b.DY, x.Data, x.Origin, x.DX, x.DY);\n            return x;\n        }\n\n        /// <summary>\n        /// Compute the inverse of an PLU factorized matrix, i.e LU x = P I.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and I is the square identity matrix.\n        /// The inverse matrix x is returned.\n        /// </summary>\n        public static Matrix<float> LuInverse(this Matrix<float> luMatrix, int[] p)\n        {\n            var inv = new Matrix<float>(luMatrix.Info);\n            luMatrix.Data.LuInverse(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                    inv.Data, inv.Origin, inv.DX, inv.DY);\n            return inv;\n        }\n\n        /// <summary>\n        /// Compute the inverse of a square matrix using PLU factorization.\n        /// The inverse matrix x is returned. Returns an invalid matrix if\n        /// the factorization failed.\n        /// </summary>\n        public static Matrix<float> LuInverse(this Matrix<float> matrix)\n        {\n            var n = matrix.SX;\n            if (n != matrix.SY) throw new ArgumentException(\"cannot invert non-square matrix\");\n            var lu = matrix.Copy();\n            var p = new int[n];\n            if (!lu.Data.LuFactorize(lu.Origin, lu.DX, lu.DY, p))\n                return default(Matrix<float>);\n            var inv = new Matrix<float>(matrix.Info);\n            lu.Data.LuInverse(lu.Origin, lu.DX, lu.DY, p, inv.Data, inv.Origin, inv.DX, inv.DY);\n            return inv;\n        }\n\n        /// <summary>\n        /// Invert square matrix using PLU factorization in-place.\n        /// If the factorization fails, the matrix is unchanged and\n        /// false is returned.\n        /// </summary>\n        public static bool LuInvert(this Matrix<float> matrix)\n        {\n            var n = matrix.SX;\n            if (n != matrix.SY) throw new ArgumentException(\"cannot invert non-square matrix\");\n            var lu = matrix.Copy();\n            var p = new int[n];\n            if (!lu.Data.LuFactorize(lu.Origin, lu.DX, lu.DY, p)) return false;\n            lu.Data.LuInverse(lu.Origin, lu.DX, lu.DY, p, matrix.Data, matrix.Origin, matrix.DX, matrix.DY);\n            return true;\n        }\n\n        #endregion\n\n        #region Partially pivoting LU factorization of Matrix<double>\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is returned as a permutation vector, and the supplied matrix A is\n        /// overwritten with its factorization LU, both in the parameter\n        /// inputAndLuMatrix. If the supplied matrix is singular, null is\n        /// returned.\n        /// </summary>\n        public static int[] LuFactorize(this Matrix<double> inputAndLuMatrix)\n        {\n            var n = inputAndLuMatrix.SX;\n            if (n != inputAndLuMatrix.SY) throw new ArgumentException(\"cannot factorize non-square matrix\");\n            var p = new int[n];\n            if (inputAndLuMatrix.Data.LuFactorize(inputAndLuMatrix.Origin,\n                        inputAndLuMatrix.DX, inputAndLuMatrix.DY, p))\n                return p;\n            return null;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The solution vector x is returned.\n        /// </summary>\n        public static Vector<double> LuSolve(this Matrix<double> luMatrix, int[] p, Vector<double> b)\n        {\n            var x = new Vector<double>(b.Info);\n            luMatrix.Data.LuSolve(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                  b.Data, b.Origin, b.Delta, x.Data, x.Origin, x.Delta);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is the right hand side\n        /// supplied as a matrix. The solution matrix x is returned.\n        /// </summary>\n        public static Matrix<double> LuSolve(this Matrix<double> luMatrix, int[] p, Matrix<double> b)\n        {\n            var x = new Matrix<double>(b.Info);\n            luMatrix.Data.LuSolve(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                  b.SX, b.Data, b.Origin, b.DX, b.DY, x.Data, x.Origin, x.DX, x.DY);\n            return x;\n        }\n\n        /// <summary>\n        /// Compute the inverse of an PLU factorized matrix, i.e LU x = P I.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and I is the square identity matrix.\n        /// The inverse matrix x is returned.\n        /// </summary>\n        public static Matrix<double> LuInverse(this Matrix<double> luMatrix, int[] p)\n        {\n            var inv = new Matrix<double>(luMatrix.Info);\n            luMatrix.Data.LuInverse(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                    inv.Data, inv.Origin, inv.DX, inv.DY);\n            return inv;\n        }\n\n        /// <summary>\n        /// Compute the inverse of a square matrix using PLU factorization.\n        /// The inverse matrix x is returned. Returns an invalid matrix if\n        /// the factorization failed.\n        /// </summary>\n        public static Matrix<double> LuInverse(this Matrix<double> matrix)\n        {\n            var n = matrix.SX;\n            if (n != matrix.SY) throw new ArgumentException(\"cannot invert non-square matrix\");\n            var lu = matrix.Copy();\n            var p = new int[n];\n            if (!lu.Data.LuFactorize(lu.Origin, lu.DX, lu.DY, p))\n                return default(Matrix<double>);\n            var inv = new Matrix<double>(matrix.Info);\n            lu.Data.LuInverse(lu.Origin, lu.DX, lu.DY, p, inv.Data, inv.Origin, inv.DX, inv.DY);\n            return inv;\n        }\n\n        /// <summary>\n        /// Invert square matrix using PLU factorization in-place.\n        /// If the factorization fails, the matrix is unchanged and\n        /// false is returned.\n        /// </summary>\n        public static bool LuInvert(this Matrix<double> matrix)\n        {\n            var n = matrix.SX;\n            if (n != matrix.SY) throw new ArgumentException(\"cannot invert non-square matrix\");\n            var lu = matrix.Copy();\n            var p = new int[n];\n            if (!lu.Data.LuFactorize(lu.Origin, lu.DX, lu.DY, p)) return false;\n            lu.Data.LuInverse(lu.Origin, lu.DX, lu.DY, p, matrix.Data, matrix.Origin, matrix.DX, matrix.DY);\n            return true;\n        }\n\n        #endregion\n\n        #region Partially pivoting LU factorization of Matrix<ComplexD>\n\n        /// <summary>\n        /// Perform a partially pivoting LU factorization of the supplied\n        /// matrix in-place, i.e A = inv(P) LU, so that any matrix equation\n        /// A x = b can be solved using LU x = P b. The permutation matrix P\n        /// is returned as a permutation vector, and the supplied matrix A is\n        /// overwritten with its factorization LU, both in the parameter\n        /// inputAndLuMatrix. If the supplied matrix is singular, null is\n        /// returned.\n        /// </summary>\n        public static int[] LuFactorize(this Matrix<ComplexD> inputAndLuMatrix)\n        {\n            var n = inputAndLuMatrix.SX;\n            if (n != inputAndLuMatrix.SY) throw new ArgumentException(\"cannot factorize non-square matrix\");\n            var p = new int[n];\n            if (inputAndLuMatrix.Data.LuFactorize(inputAndLuMatrix.Origin,\n                        inputAndLuMatrix.DX, inputAndLuMatrix.DY, p))\n                return p;\n            return null;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix lu, P is a permutation matrix\n        /// supplied as a permutation array p, and b is the right hand side\n        /// supplied as a vector. The solution vector x is returned.\n        /// </summary>\n        public static Vector<ComplexD> LuSolve(this Matrix<ComplexD> luMatrix, int[] p, Vector<ComplexD> b)\n        {\n            var x = new Vector<ComplexD>(b.Info);\n            luMatrix.Data.LuSolve(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                  b.Data, b.Origin, b.Delta, x.Data, x.Origin, x.Delta);\n            return x;\n        }\n\n        /// <summary>\n        /// Solve a matrix equation of the form LU x = P b.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and b is the right hand side\n        /// supplied as a matrix. The solution matrix x is returned.\n        /// </summary>\n        public static Matrix<ComplexD> LuSolve(this Matrix<ComplexD> luMatrix, int[] p, Matrix<ComplexD> b)\n        {\n            var x = new Matrix<ComplexD>(b.Info);\n            luMatrix.Data.LuSolve(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                  b.SX, b.Data, b.Origin, b.DX, b.DY, x.Data, x.Origin, x.DX, x.DY);\n            return x;\n        }\n\n        /// <summary>\n        /// Compute the inverse of an PLU factorized matrix, i.e LU x = P I.\n        /// LU is the supplied factorized matrix, P is a permutation matrix\n        /// supplied as a permutation array, and I is the square identity matrix.\n        /// The inverse matrix x is returned.\n        /// </summary>\n        public static Matrix<ComplexD> LuInverse(this Matrix<ComplexD> luMatrix, int[] p)\n        {\n            var inv = new Matrix<ComplexD>(luMatrix.Info);\n            luMatrix.Data.LuInverse(luMatrix.Origin, luMatrix.DX, luMatrix.DY, p,\n                                    inv.Data, inv.Origin, inv.DX, inv.DY);\n            return inv;\n        }\n\n        /// <summary>\n        /// Compute the inverse of a square matrix using PLU factorization.\n        /// The inverse matrix x is returned. Returns an invalid matrix if\n        /// the factorization failed.\n        /// </summary>\n        public static Matrix<ComplexD> LuInverse(this Matrix<ComplexD> matrix)\n        {\n            var n = matrix.SX;\n            if (n != matrix.SY) throw new ArgumentException(\"cannot invert non-square matrix\");\n            var lu = matrix.Copy();\n            var p = new int[n];\n            if (!lu.Data.LuFactorize(lu.Origin, lu.DX, lu.DY, p))\n                return default(Matrix<ComplexD>);\n            var inv = new Matrix<ComplexD>(matrix.Info);\n            lu.Data.LuInverse(lu.Origin, lu.DX, lu.DY, p, inv.Data, inv.Origin, inv.DX, inv.DY);\n            return inv;\n        }\n\n        /// <summary>\n        /// Invert square matrix using PLU factorization in-place.\n        /// If the factorization fails, the matrix is unchanged and\n        /// false is returned.\n        /// </summary>\n        public static bool LuInvert(this Matrix<ComplexD> matrix)\n        {\n            var n = matrix.SX;\n            if (n != matrix.SY) throw new ArgumentException(\"cannot invert non-square matrix\");\n            var lu = matrix.Copy();\n            var p = new int[n];\n            if (!lu.Data.LuFactorize(lu.Origin, lu.DX, lu.DY, p)) return false;\n            lu.Data.LuInverse(lu.Origin, lu.DX, lu.DY, p, matrix.Data, matrix.Origin, matrix.DX, matrix.DY);\n            return true;\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Algorithms/QrFactorization.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static partial class TensorNumericExtensions\n    {\n        #region Matrix<double> helpers\n\n        /// <summary>\n        /// L2 norm of complete matrix row.\n        /// </summary>\n        public static double RowNorm2(\n                this Matrix<double> matrix, long row)\n        {\n            return matrix.Data.RowNorm2(matrix.Origin, matrix.DX, matrix.DY, row, matrix.FX, matrix.EX);\n        }\n\n        /// <summary>\n        /// L2 norm of complete matrix column.\n        /// </summary>\n        public static double ColNorm2(\n                this Matrix<double> matrix, long col)\n        {\n            return matrix.Data.ColNorm2(matrix.Origin, matrix.DX, matrix.DY, col, matrix.FY, matrix.EY);\n        }\n\n        /// <summary>\n        /// L2 norm of matrix row elemnts including start and excluding end. \n        /// </summary>\n        public static double RowNorm2(\n                this Matrix<double> matrix, long row, long start, long end)\n        {\n            return matrix.Data.RowNorm2(matrix.Origin, matrix.DX, matrix.DY, row, start, end);\n        }\n\n        /// <summary>\n        /// L2 norm of matrix column elemnts including start and excluding end. \n        /// </summary>\n        public static double ColNorm2(\n                this Matrix<double> matrix, long col, long start, long end)\n        {\n            return matrix.Data.ColNorm2(matrix.Origin, matrix.DX, matrix.DY, col, start, end);\n        }\n\n        /// <summary>\n        /// Dot product of complete matrix rows.\n        /// </summary>\n        public static double RowDotRow(\n                this Matrix<double> matrix, long row0, long row1)\n        {\n            return matrix.Data.RowDotRow(matrix.Origin, matrix.DX, matrix.DY, row0, row1, matrix.FX, matrix.EX);\n        }\n\n        /// <summary>\n        /// Dot product of complete matrix columns.\n        /// </summary>\n        public static double ColDotCol(\n                this Matrix<double> matrix, long col0, long col1)\n        {\n            return matrix.Data.ColDotCol(matrix.Origin, matrix.DX, matrix.DY, col0, col1, matrix.FY, matrix.EY);\n        }\n\n        /// <summary>\n        /// Dot product of matrix row elements including start and excluding end.\n        /// </summary>\n        public static double RowDotRow(\n                this Matrix<double> matrix, long row0, long row1, long start, long end)\n        {\n            return matrix.Data.RowDotRow(matrix.Origin, matrix.DX, matrix.DY, row0, row1, start, end);\n        }\n\n        /// <summary>\n        /// Dot product of matrix column elements including start and excluding end.\n        /// </summary>\n        public static double ColDotCol(\n                this Matrix<double> matrix, long col0, long col1, long start, long end)\n        {\n            return matrix.Data.ColDotCol(matrix.Origin, matrix.DX, matrix.DY, col0, col1, start, end);\n        }\n\n        #endregion\n\n        #region QR factorization of Matrix<double> using Householder transformations\n\n        /// <summary>\n        /// Perform a QR factorization of the supplied m x n matrix using\n        /// Householder transofmations, i.e. A = QR, where Q is orthogonal\n        /// (a product of n-2 Householder-Transformations) and R is a right\n        /// upper n x n triangular matrix. An array of the diagonal elements\n        /// of R is returned. WARNING: the supplied matrix A is overwritten\n        ///  with its factorization QR, both in the parameter aqr.\n        /// </summary>\n        public static double[] QrFactorize(\n                this Matrix<double> aqr)\n        {\n            double[] diag = new double[Fun.Min(aqr.SX, aqr.SY)];\n            aqr.Data.QrFactorize(aqr.Origin, aqr.DX, aqr.DY, aqr.SX, aqr.SY, diag);\n            return diag;\n        }\n\n        /// <summary>\n        /// Solves the Equation QR x = b. QR must be a factorized matrix (QrFactorize).\n        /// diag provides the diagonal elements of R (QrFactorize)\n        /// If QR is not quadratic the x where |QR x - b| == min is returned.\n        /// </summary>\n        public static Vector<double> QrSolve(\n                this Matrix<double> qr, double[] diag, Vector<double> b)\n        {\n            double unusedResidual;\n            var x = new Vector<double>(qr.SX);\n            qr.Data.QrSolve(qr.Origin, qr.DX, qr.DY, qr.SX, qr.SY, diag,\n                            b.Data, b.Origin, b.Delta, x.Data, x.Origin, x.Delta, out unusedResidual);\n            return x;\n        }\n\n        /// <summary>\n        /// Solves the Equation QR x = b. QR must be a factorized matrix (QrFactorize).\n        /// diag provides the diagonal elements of R (QrFactorize)\n        /// If QR is not quadratic the x where |QR x - b| == min is returned\n        /// residual holds the minimal value of |QR x - b|\n        /// </summary>\n        public static Vector<double> QrSolve(\n                this Matrix<double> qr, double[] diag, Vector<double> b, out double residual)\n        {\n            var x = new Vector<double>(qr.SX);\n            qr.Data.QrSolve(qr.Origin, qr.DX, qr.DY, qr.SX, qr.SY, diag,\n                            b.Data, b.Origin, b.Delta, x.Data, x.Origin, x.Delta, out residual);\n            return x;\n        }\n\n        /// <summary>\n        /// Solves the Equation QR x = b, where x and b are matrices and each column of x\n        /// is the solution of the eqation with the corresponding column of b.\n        /// QR must be a factorized matrix (QrFactorize). diag provides the diagonal elements\n        /// of R (QrFactorize) If QR is not quadratic the x where |QR x - b| == min is returned\n        /// </summary>\n        public static Matrix<double> QrSolve(\n                this Matrix<double> qr, double[] diag, Matrix<double> b)\n        {\n            var x = new Matrix<double>(b.SX, qr.SX);\n            for (long i = 0, b0 = b.Origin, x0 = x.Origin; i < b.SX; i++, b0 += b.DX, x0 += x.DX)\n            {\n                double unusedResidual;\n                qr.Data.QrSolve(qr.Origin, qr.DX, qr.DY, qr.SX, qr.SY, diag,\n                                b.Data, b0, b.DY, x.Data, x0, x.DY, out unusedResidual);\n            }\n            return x;\n        }\n\n        /// <summary>\n        /// Solves the Equation QR x = b, where x and b are matrices and each column of x\n        /// is the solution of the eqation with the corresponding column of b.\n        /// QR must be a factorized matrix (QrFactorize). diag provides the diagonal elements\n        /// of R (QrFactorize) If QR is not quadratic the x where |QR x - b| == min is returned\n        /// The residual vector holds the minimal value of |QR x - b| for each column of x.\n        /// </summary>\n        public static Matrix<double> QrSolve(\n                this Matrix<double> qr, double[] diag, Matrix<double> b, Vector<double> residual)\n        {\n            if (b.SX != residual.Size)\n                throw new ArgumentException(\"b.SX != residual.Size\");\n            var x = new Matrix<double>(b.SX, qr.SX);\n            for (long i = 0, b0 = b.Origin, x0 = x.Origin, ri = residual.Origin;\n                 i < b.SX; i++, b0 += b.DX, x0 += x.DX, ri += residual.Delta)\n            {\n                qr.Data.QrSolve(qr.Origin, qr.DX, qr.DY, qr.SX, qr.SY, diag,\n                                b.Data, b0, b.DY, x.Data, x0, x.DY, out residual.Data[ri]);\n            }\n            return x;\n        }\n\n        /// <summary>\n        /// Calculates the inverse of a matrix given its QR factorization using\n        /// Householder transformations. The matrix has to be quadratic.\n        /// </summary>\n        public static Matrix<double> QrInverse(\n                this Matrix<double> qr, double[] diag)\n        {\n            long n = qr.SX;\n            if (n != qr.SY) throw new ArgumentException(\"Can only invert quadratic matrices\");\n\n            double[] b = new double[n];\n\n            Matrix<double> inv = new Matrix<double>(n, n);\n\n            for (long i = 0, io = inv.Origin; i < n; i++, io += inv.DX)\n            {\n                double unusedResidual;\n                for (int j = 0; j < n; j++) b[j] = (i == j ? 1.0 : 0.0);\n                qr.Data.QrSolve(qr.Origin, qr.DX, qr.DY, qr.SX, qr.SY, diag,\n                                b, 0, 1, inv.Data, io, inv.DY, out unusedResidual);\n            }\n            return inv;\n        }\n\n        /// <summary>\n        /// Calculates the inverse matrix using Householder transformations.\n        /// The matrix has to be quadratic.\n        /// </summary>\n        public static Matrix<double> QrInverse(\n                this Matrix<double> matrix)\n        {\n            var qr = matrix.Copy();\n            double[] diag = qr.QrFactorize();\n            return qr.QrInverse(diag);\n        }\n\n        /// <summary>\n        /// Calculates the inverse matrix using Householder transformations\n        /// </summary>\n        public static M22d QrInverse(this M22d mat)\n        {\n            var qr = new Matrix<double>((double[])mat, 2, 2);\n            var diag = qr.QrFactorize();\n            return (M22d)(qr.QrInverse(diag).Data);\n        }\n\n        /// <summary>\n        /// Calculates the inverse matrix using Householder transformations\n        /// </summary>\n        public static M33d QrInverse(this M33d mat)\n        {\n            var qr = new Matrix<double>((double[])mat, 3, 3);\n            var diag = qr.QrFactorize();\n            return (M33d)(qr.QrInverse(diag).Data);\n        }\n\n        /// <summary>\n        /// Calculates the inverse matrix using Householder transformations\n        /// </summary>\n        public static M44d QrInverse(this M44d mat)\n        {\n            var qr = new Matrix<double>((double[])mat, 4, 4);\n            var diag = qr.QrFactorize();\n            return (M44d)(qr.QrInverse(diag).Data);\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/EdgeFilter.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    public enum EdgeFilter : int\n    {\n        Sharr, Sobel, Roberts, Simoncelli,\n    }\n\n    public enum EdgeDirection : int\n    {\n        Horizontal, Vertical, Both,\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/IPix.cs",
    "content": "﻿namespace Aardvark.Base\n{\n    /// <summary>\n    /// Common interface for image classes such as <see cref=\"PixImage\"/> and <see cref=\"PixVolume\"/>.\n    /// </summary>\n    public interface IPix\n    {\n        PixFormat PixFormat { get; }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/ImageLoadException.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Exception that is thrown when loading or saving an image fails.\n    /// </summary>\n    public class ImageLoadException : Exception\n    {\n        /// <summary>\n        /// Creates a new ImageLoadException with the given error message.\n        /// </summary>\n        /// <param name=\"message\">A description of the error.</param>\n        public ImageLoadException(string message)\n            : base(message)\n        {  }\n\n        /// <summary>\n        /// Creates a new ImageLoadException with the given error message and inner exception.\n        /// </summary>\n        /// <param name=\"message\">A description of the error.</param>\n        /// <param name=\"inner\">The exception that caused the current exception.</param>\n        public ImageLoadException(string message, Exception inner)\n            : base(message, inner)\n        { }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/PixCube.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Enumerates the six faces of a cube map.\n    /// </summary>\n    /// <remarks>\n    /// The integer value of each member matches the index of the corresponding face\n    /// in a texture array that represents a cube map. This is the conventional order\n    /// used throughout the library.\n    /// </remarks>\n    public enum CubeSide\n    {\n        PositiveX = 0,\n        NegativeX = 1,\n        PositiveY = 2,\n        NegativeY = 3,\n        PositiveZ = 4,\n        NegativeZ = 5,\n    }\n\n    /// <summary>\n    /// Bitmask flags for selecting cube faces.\n    /// </summary>\n    /// <remarks>\n    /// The bit position of each flag corresponds to the <see cref=\"CubeSide\"/> index.\n    /// </remarks>\n    [Flags]\n    public enum CubeSideFlags\n    {\n        PositiveX = 0x1,\n        NegativeX = 0x2,\n        PositiveY = 0x4,\n        NegativeY = 0x8,\n        PositiveZ = 0x10,\n        NegativeZ = 0x20,\n        All = 0x3f,\n    }\n\n    /// <summary>\n    /// Represents a cube map consisting of six image mipmap chains (one per face).\n    /// </summary>\n    /// <seealso cref=\"PixImageMipMap\"/>\n    /// <seealso cref=\"CubeSide\"/>\n    public class PixCube : IPix\n    {\n        /// <summary>\n        /// The six mipmap chains that make up the cube map, ordered by <see cref=\"CubeSide\"/>.\n        /// </summary>\n        /// <remarks>\n        /// May have more than six elements, excess ones are ignored.\n        /// </remarks>\n        public PixImageMipMap[] MipMapArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Initializes a new <see cref=\"PixCube\"/> with six <c>null</c> faces.\n        /// </summary>\n        public PixCube() => MipMapArray = new PixImageMipMap[6];\n\n        /// <summary>\n        /// Initializes a new <see cref=\"PixCube\"/> from an array of mipmap chains.\n        /// The order of the array must follow the <see cref=\"CubeSide\"/> enumeration.\n        /// </summary>\n        /// <param name=\"sides\">The six mipmap chains representing the cube faces.</param>\n        /// <exception cref=\"ArgumentNullException\">if <paramref name=\"sides\"/> is <c>null</c>.</exception>\n        /// <exception cref=\"ArgumentException\">if <paramref name=\"sides\"/> has fewer than six elements.</exception>\n        public PixCube(PixImageMipMap[] sides)\n        {\n            if (sides == null) throw new ArgumentNullException(nameof(sides));\n            if (sides.Length < 6) throw new ArgumentException($\"Image array must have at least 6 elements, but only has {sides.Length}.\", nameof(sides));\n            MipMapArray = sides;\n        }\n\n\n        /// <summary>\n        /// Initializes a new <see cref=\"PixCube\"/> from an array of base-level images.\n        /// The order of the array must follow the <see cref=\"CubeSide\"/> enumeration.\n        /// </summary>\n        /// <param name=\"sides\">The six images representing the cube faces.</param>\n        /// <exception cref=\"ArgumentNullException\">if <paramref name=\"sides\"/> is <c>null</c>.</exception>\n        /// <exception cref=\"ArgumentException\">if <paramref name=\"sides\"/> has fewer than six elements.</exception>\n        public PixCube(PixImage[] sides)\n            => MipMapArray = sides?.Map(image => new PixImageMipMap(image));\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Returns whether the cube map is empty (i.e. all six faces are <c>null</c> or empty).\n        /// </summary>\n        public bool IsEmpty\n        {\n            get\n            {\n                for (int side = 0; side < 6; side++) { if (!(MipMapArray[side]?.IsEmpty ?? true)) return false; }\n                return true;\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the mipmap chain for the specified cube <paramref name=\"side\"/>.\n        /// </summary>\n        public PixImageMipMap this[CubeSide side]\n        {\n            get => MipMapArray[(int)side];\n            set => MipMapArray[(int)side] = value;\n        }\n\n        /// <summary>\n        /// Gets the pixel format of the cube map (taken from the first non-null and non-empty face).\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">if all faces are <c>null</c> or empty.</exception>\n        public PixFormat PixFormat\n        {\n            get\n            {\n                for (int side = 0; side < 6; side++) { if (!(MipMapArray[side]?.IsEmpty ?? true)) return MipMapArray[side].PixFormat; }\n                throw new InvalidOperationException(\"Cannot determine format of empty PixCube.\");\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/PixImage.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Collections.Concurrent;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing System.Threading;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Supported file formats for loading and saving images.\n    /// </summary>\n    public enum PixFileFormat\n    {\n        Unknown,\n        Bmp,\n        Ico,\n        Jpeg,\n        Jng,\n        Koala,\n        Lbm,\n        Iff,\n        Mng,\n        Pbm,\n        PbmRaw,\n        Pcd,\n        Pcx,\n        Pgm,\n        PgmRaw,\n        Png,\n        Ppm,\n        PpmRaw,\n        Ras,\n        Targa,\n        Tiff,\n        Wbmp,\n        Psd,\n        Cut,\n        Xbm,\n        Xpm,\n        Dds,\n        Gif,\n        Hdr,\n        Faxg3,\n        Sgi,\n        Exr,\n        J2k,\n        Jp2,\n        Pfm,\n        Pict,\n        Raw,\n        Wmp, // not in FreeImage ?\n        Webp\n    }\n\n    /// <summary>\n    /// Defines a visitor for strongly typed PixImage instances.\n    /// Use this to dispatch operations based on the underlying pixel data type without reflection.\n    /// </summary>\n    /// <typeparam name=\"TResult\">The result type produced by the visitor.</typeparam>\n    public interface IPixImageVisitor<TResult>\n    {\n        /// <summary>\n        /// Visits the given PixImage with element type <typeparamref name=\"TData\"/>.\n        /// </summary>\n        /// <typeparam name=\"TData\">The pixel element type (e.g. byte, float, etc.).</typeparam>\n        /// <param name=\"image\">The typed PixImage instance to visit.</param>\n        /// <returns>The visitor-specific result.</returns>\n        TResult Visit<TData>(PixImage<TData> image);\n    }\n\n    /// <summary>\n    /// Lightweight description of a <see cref=\"PixImage\"/>, containing its pixel format and dimensions.\n    /// </summary>\n    /// <param name=\"Format\">The pixel format (channel type and color format).</param>\n    /// <param name=\"Size\">The 2D size in pixels (X = width, Y = height).</param>\n    public record PixImageInfo(PixFormat Format, V2i Size);\n\n    /// <summary>\n    /// Base (non-generic) 2D pixel container abstraction. Provides format, size and conversion utilities\n    /// for images independent of the underlying element type.\n    /// </summary>\n    [Serializable]\n    public abstract partial class PixImage : IPix\n    {\n        /// <summary>\n        /// Color format describing the channel layout and semantics.\n        /// </summary>\n        public Col.Format Format;\n\n        #region Loaders\n\n        #region PgmPixLoader\n\n        /// <summary>\n        /// Loader for saving PGM images. Reading is not supported.\n        /// </summary>\n        private class PgmPixLoader : IPixLoader\n        {\n            public string Name => \"Aardvark PGM\";\n\n            public bool CanEncode => true;\n\n            public bool CanDecode => false;\n\n            public PixImage LoadFromFile(string filename) => null;\n\n            public PixImage LoadFromStream(Stream stream) => null;\n\n            public void SaveToFile(string filename, PixImage image, PixSaveParams saveParams)\n            {\n                using var stream = File.OpenWrite(filename);\n                SaveToStream(stream, image, saveParams);\n            }\n\n            public void SaveToStream(Stream stream, PixImage image, PixSaveParams saveParams)\n            {\n                if (saveParams.Format != PixFileFormat.Pgm || image.PixFormat != PixFormat.ByteGray)\n                    throw new NotSupportedException($\"{Name} loader only supports PixFormat.ByteGray and PixFileFormat.Pgm\");\n\n                var img = image.ToPixImage<byte>().ToImageLayout();\n\n                var sw = new StreamWriter(stream, Encoding.ASCII);\n                sw.NewLine = \"\\n\";\n                sw.WriteLine(\"P5\");\n                sw.WriteLine(\"# Created by Aardvark\");\n                sw.WriteLine(\"{0} {1}\", img.Size.X, img.Size.Y);\n                sw.WriteLine(\"255\");\n                sw.Flush();\n                stream.Write(img.Volume.Data, 0, img.Volume.Data.Length);\n            }\n\n            public PixImageInfo GetInfoFromFile(string filename) => null;\n\n            public PixImageInfo GetInfoFromStream(Stream stream) => null;\n        }\n\n        #endregion\n\n        private static readonly Dictionary<IPixLoader, int> s_loaders = new();\n\n        /// <summary>\n        /// Sets the priority of a PixImage loader.\n        /// The priority determines the order in which loaders are invoked to load or save an image.\n        /// Loaders with higher priority are invoked first.\n        /// If the loader does not exist, it is added with the given priority.\n        /// </summary>\n        /// <param name=\"loader\">The loader to modify.</param>\n        /// <param name=\"priority\">The priority to set.</param>\n        public static void SetLoader(IPixLoader loader, int priority)\n        {\n            lock (s_loaders)\n            {\n                s_loaders[loader] = priority;\n            }\n        }\n\n        /// <summary>\n        /// Adds a PixImage loader.\n        /// Assigns a priority that is greater than the highest priority among existing loaders, resulting in a LIFO order.\n        /// If the loader already exists, the priority is modified.\n        /// </summary>\n        /// <param name=\"loader\">The loader to add.</param>\n        public static void AddLoader(IPixLoader loader)\n        {\n            lock (s_loaders)\n            {\n                var loaders = s_loaders.ToList();\n                loaders.Sort((x, y) => y.Value - x.Value);\n                SetLoader(loader, loaders.Map(x => x.Value).FirstOrDefault(-1) + 1);\n            }\n        }\n\n        /// <summary>\n        /// Removes a PixImage loader.\n        /// </summary>\n        /// <param name=\"loader\">The loader to remove.</param>\n        public static void RemoveLoader(IPixLoader loader)\n        {\n            lock (s_loaders)\n            {\n                s_loaders.Remove(loader);\n            }\n        }\n\n        /// <summary>\n        /// Gets a dictionary of registered loaders with their associated priority.\n        /// </summary>\n        /// <returns>A dictionary of registered loaders.</returns>\n        public static Dictionary<IPixLoader, int> GetLoadersWithPriority()\n        {\n            lock (s_loaders)\n            {\n                return new Dictionary<IPixLoader, int>(s_loaders);\n            }\n        }\n\n        /// <summary>\n        /// Gets a list of registered loaders sorted by priority in descending order.\n        /// </summary>\n        /// <returns>A list of registered loaders.</returns>\n        public static List<IPixLoader> GetLoaders()\n        {\n            lock (s_loaders)\n            {\n                var list = s_loaders.ToList();\n                list.Sort((x, y) => y.Value - x.Value);\n                return list.Map(x => x.Key);\n            }\n        }\n\n        /// <summary>\n        /// Gets a list of registered loaders with encoding support sorted by priority in descending order.\n        /// </summary>\n        /// <returns>A list of registered loaders that support encoding.</returns>\n        public static List<IPixLoader> GetEncoders()\n        {\n            var list = GetLoaders();\n            list.RemoveAll(loader => !loader.CanEncode);\n            return list;\n        }\n\n        /// <summary>\n        /// Gets a list of registered loaders with decoding support sorted by priority in descending order.\n        /// </summary>\n        /// <returns>A list of registered loaders that support decoding.</returns>\n        public static List<IPixLoader> GetDecoders()\n        {\n            var list = GetLoaders();\n            list.RemoveAll(loader => !loader.CanDecode);\n            return list;\n        }\n\n        internal static Result InvokeLoader<Result>(\n                        IPixLoader loader, Func<IPixLoader, Result> invoke,\n                        Func<Result, bool> isValid,\n                        string operationDescription)\n        {\n            Report.BeginTimed(3, $\"Trying to {operationDescription} with {loader.Name} loader\");\n\n            try\n            {\n                var result = invoke(loader);\n                if (isValid(result))\n                {\n                    Report.EndTimed(3, \": success in\");\n                    return result;\n                }\n                else\n                {\n                    Report.EndTimed(3, \": failed in\");\n                }\n            }\n            catch (Exception e)\n            {\n                Report.EndTimed(3, \": failed in\");\n                Report.Line(3, $\"Failed to {operationDescription} with {loader.Name} loader: {e.Message}\");\n                throw;\n            }\n\n            return default;\n        }\n\n        internal enum LoaderType { Encoder, Decoder, Any };\n\n        internal static Result InvokeLoaders<Input, Result>(\n                                LoaderType loaderType, IPixLoader loader, Input input,\n                                Func<IPixLoader, Input, Result> invoke,\n                                Action<Input> resetInput,\n                                Func<Result, bool> isValid,\n                                string errorMessage)\n        {\n            Dictionary<IPixLoader, Exception> exceptions = null;\n\n            if (loader != null)\n            {\n                if (loaderType == LoaderType.Encoder && !loader.CanEncode)\n                    throw new ImageLoadException(errorMessage + \" - Encoding not supported.\");\n\n                if (loaderType == LoaderType.Decoder && !loader.CanDecode)\n                    throw new ImageLoadException(errorMessage + \" - Decoding not supported.\");\n\n                try\n                {\n                    var result = invoke(loader, input);\n                    if (isValid(result)) { return result; }\n                }\n                catch (Exception e)\n                {\n                    exceptions = new Dictionary<IPixLoader, Exception>(1) { [loader] = e };\n                    errorMessage += $\" with {loader.Name} - {e.Message}\";\n                }\n            }\n            else\n            {\n                var loaders =\n                    loaderType switch\n                    {\n                        LoaderType.Encoder => GetEncoders(),\n                        LoaderType.Decoder => GetDecoders(),\n                        _ => GetLoaders()\n                    };\n\n                for (int i = 0; i < loaders.Count; i++)\n                {\n                    if (i != 0) resetInput(input);\n\n                    try\n                    {\n                        var result = invoke(loaders[i], input);\n                        if (isValid(result)) return result;\n                    }\n                    catch (Exception e)\n                    {\n                        exceptions ??= new Dictionary<IPixLoader, Exception>();\n                        exceptions[loaders[i]] = e;\n                    }\n                }\n\n                var loaderDesc =\n                    loaderType switch\n                    {\n                        LoaderType.Encoder => \"encoder\",\n                        LoaderType.Decoder => \"decoder\",\n                        _ => \"loader\"\n                    };\n\n                if (loaders.Count == 0)\n                {\n                    errorMessage += $\" - No {loaderDesc}s available. Install {loaderDesc}s by referencing Aardvark.PixImage.* packages.\";\n                }\n                else\n                {\n                    errorMessage += $\" - All available {loaderDesc}s failed:{Environment.NewLine}\";\n\n                    for (var i = 0; i < loaders.Count; i++)\n                    {\n                        string error;\n\n                        if (exceptions != null && exceptions.TryGetValue(loaders[i], out var exn))\n                        {\n                            error = Regex.Replace(exn.Message, @\"(\\r\\n?|\\n)\\z\", \"\"); // Remove last line break in multi-line message\n                        }\n                        else\n                        {\n                            error = \"Failed\";\n                        }\n\n                        errorMessage += $\"{i + 1}. {loaders[i].Name}: {error}\" + Environment.NewLine;\n                    }\n                }\n            }\n\n            var innerException = exceptions?.Values.Count switch\n            {\n                0 or null => null,\n                1 => exceptions.Values.First(),\n                _ => new AggregateException(exceptions.Values)\n            };\n\n            throw new ImageLoadException(errorMessage, innerException);\n        }\n\n        internal static Result InvokeLoadersWithStream<Result>(\n                        LoaderType loaderType, IPixLoader loader, Stream stream,\n                        Func<IPixLoader, Stream, Result> invoke,\n                        Func<Result, bool> isValid,\n                        string errorMessage)\n        {\n            var initialPosition = stream.Position;\n\n            return InvokeLoaders(\n                loaderType, loader, stream, invoke,\n                s => s.Seek(initialPosition, SeekOrigin.Begin),\n                isValid, errorMessage\n            );\n        }\n\n        internal static void Ignore<T>(T _) { }\n\n        internal static bool NotNull<T>(T x) => x != null;\n\n        internal static bool Identity(bool x) => x;\n\n        #endregion\n\n        #region Processors\n\n        private static readonly Dictionary<IPixProcessor, int> s_processors = new()\n        {\n            { PixProcessor.Instance, 1 }\n        };\n\n        /// <summary>\n        /// Sets the priority of a PixImage processor.\n        /// The priority determines the order in which proocessors are invoked to scale, rotate, or remap an image.\n        /// Processors with higher priority are invoked first.\n        /// If the processor does not exist, it is added with the given priority.\n        /// </summary>\n        /// <param name=\"processor\">The processor to modify.</param>\n        /// <param name=\"priority\">The priority to set.</param>\n        public static void SetProcessor(IPixProcessor processor, int priority)\n        {\n            lock (s_processors)\n            {\n                s_processors[processor] = priority;\n            }\n        }\n\n        /// <summary>\n        /// Adds a PixImage processor.\n        /// Assigns a priority that is greater than the highest priority among existing processors, resulting in a LIFO order.\n        /// If the processor already exists, the priority is modified.\n        /// </summary>\n        /// <param name=\"processor\">The processor to add.</param>\n        public static void AddProcessor(IPixProcessor processor)\n        {\n            lock (s_processors)\n            {\n                var maxPriority = s_processors.Values.Max(-1);\n                s_processors[processor] = maxPriority + 1;\n            }\n        }\n\n        /// <summary>\n        /// Removes a PixImage processor.\n        /// </summary>\n        /// <param name=\"processor\">The processor to remove.</param>\n        public static void RemoveProcessor(IPixProcessor processor)\n        {\n            lock (s_processors) { s_processors.Remove(processor); }\n        }\n\n        /// <summary>\n        /// Gets a dictionary of registered processors with their associated priority.\n        /// Only returns processors that have at least the given minimum capabilities.\n        /// </summary>\n        /// <param name=\"minCapabilities\">The minimum capabilities for a processor to be considered.</param>\n        /// <returns>A dictionary of registered processors.</returns>\n        public static Dictionary<IPixProcessor, int> GetProcessorsWithPriority(PixProcessorCaps minCapabilities = PixProcessorCaps.None)\n        {\n            lock (s_processors)\n            {\n                var result = new Dictionary<IPixProcessor, int>();\n\n                foreach (var p in s_processors)\n                {\n                    if (p.Key.Capabilities.HasFlag(minCapabilities))\n                        result[p.Key] = p.Value;\n                }\n\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Gets a list of registered processors sorted by priority in descending order.\n        /// Only returns processors that have at least the given minimum capabilities.\n        /// </summary>\n        /// <param name=\"minCapabilities\">The minimum capabilities for a processor to be considered.</param>\n        /// <returns>A list of registered processors.</returns>\n        public static List<IPixProcessor> GetProcessors(PixProcessorCaps minCapabilities = PixProcessorCaps.None)\n        {\n            lock (s_processors)\n            {\n                var list = new List<KeyValuePair<IPixProcessor, int>>();\n\n                foreach (var p in s_processors)\n                {\n                    if (p.Key.Capabilities.HasFlag(minCapabilities))\n                        list.Add(p);\n                }\n\n                list.Sort((x, y) => y.Value - x.Value);\n                return list.Map(x => x.Key);\n            }\n        }\n\n        internal static PixImage<T> InvokeProcessors<T>(\n                        Func<IPixProcessor, PixImage<T>> invoke,\n                        PixProcessorCaps minCapabilities,\n                        string operationDescription)\n        {\n            Dictionary<IPixProcessor, Exception> exceptions = null;\n\n            foreach (var p in GetProcessors(minCapabilities))\n            {\n                try\n                {\n                    var result = invoke(p);\n                    if (result != null) return result;\n                }\n                catch (Exception e)\n                {\n                    exceptions ??= new Dictionary<IPixProcessor, Exception>();\n                    exceptions[p] = e;\n                }\n            }\n\n            var processors = GetProcessors();\n            var errorMessage = $\"Cannot {operationDescription}\";\n\n            if (processors.Count == 0)\n            {\n                errorMessage += \" - No image processors available.\";\n            }\n            else\n            {\n                errorMessage += \" - All available image processors failed:\" + Environment.NewLine;\n\n                for (var i = 0; i < processors.Count; i++)\n                {\n                    string error;\n\n                    if (exceptions != null && exceptions.TryGetValue(processors[i], out var exn))\n                    {\n                        error = Regex.Replace(exn.Message, @\"(\\r\\n?|\\n)\\z\", \"\"); // Remove last line break in multi-line message\n                    }\n                    else\n                    {\n                        error = processors[i].Capabilities.HasFlag(minCapabilities) ? \"Failed\" : $\"{minCapabilities} not supported\";\n                    }\n\n                    errorMessage += $\"{i + 1}. {processors[i].Name}: {error}\" + Environment.NewLine;\n                }\n            }\n\n            var innerException = exceptions?.Values.Count switch\n            {\n                0 or null => null,\n                1 => exceptions.Values.First(),\n                _ => new AggregateException(exceptions.Values)\n            };\n\n            throw new NotSupportedException(errorMessage, innerException);\n        }\n\n        #endregion\n\n        #region Constructors\n\n        static PixImage()\n        {\n            AddLoader(new PgmPixLoader());\n        }\n\n        public PixImage() : this(Col.Format.None) { }\n\n        public PixImage(Col.Format format)\n        {\n            Format = format;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the underlying storage as a System.Array of the element type.\n        /// </summary>\n        public abstract Array Array { get; }\n\n        /// <summary>\n        /// Gets the pixel format of the image (channel type and color format).\n        /// </summary>\n        public abstract PixFormat PixFormat { get; }\n\n        /// <summary>\n        /// Gets structural information about the underlying 3D tensor including size and layout.\n        /// </summary>\n        public abstract VolumeInfo VolumeInfo { get; }\n\n        /// <summary>\n        /// Gets the size in bytes of a single channel element (e.g. 1 for byte, 4 for float).\n        /// </summary>\n        public abstract int BytesPerChannel { get; }\n\n        /// <summary>\n        /// Gets a lightweight summary of this image's format and size.\n        /// </summary>\n        public PixImageInfo Info => new(PixFormat, Size);\n\n        /// <summary>\n        /// Gets the total number of pixels (Width * Height).\n        /// </summary>\n        public int NumberOfPixels => Size.X * Size.Y;\n\n        /// <summary>\n        /// Gets the aspect ratio defined as Width / Height.\n        /// </summary>\n        public double AspectRatio => Size.X / (double)Size.Y;\n\n        /// <summary>\n        /// Gets the 2D size of the image in pixels.\n        /// </summary>\n        public V2i Size => (V2i)VolumeInfo.Size.XY;\n\n        /// <summary>\n        /// Gets the 2D size of the image in pixels as 64-bit integers.\n        /// </summary>\n        public V2l SizeL => VolumeInfo.Size.XY;\n\n        /// <summary>\n        /// Gets the image width in pixels.\n        /// </summary>\n        public int Width => Size.X;\n\n        /// <summary>\n        /// Gets the image width in pixels as a 64-bit integer.\n        /// </summary>\n        public long WidthL => SizeL.X;\n\n        /// <summary>\n        /// Gets the image height in pixels.\n        /// </summary>\n        public int Height => Size.Y;\n\n        /// <summary>\n        /// Gets the image height in pixels as a 64-bit integer.\n        /// </summary>\n        public long HeightL => SizeL.Y;\n\n        /// <summary>\n        /// Gets the number of channels per pixel.\n        /// </summary>\n        public int ChannelCount => (int)VolumeInfo.Size.Z;\n\n        /// <summary>\n        /// Gets the number of channels per pixel as a 64-bit integer.\n        /// </summary>\n        public long ChannelCountL => VolumeInfo.Size.Z;\n\n        /// <summary>\n        /// Gets the stride (number of bytes between two vertically adjacent pixels).\n        /// </summary>\n        public int Stride => BytesPerChannel * (int)VolumeInfo.DY;\n\n        /// <summary>\n        /// Gets the stride (number of bytes between two vertically adjacent pixels) as a 64-bit integer.\n        /// </summary>\n        public long StrideL => BytesPerChannel * VolumeInfo.DY;\n\n        #region Obsolete\n\n        [Obsolete(\"Use Stride instead.\")]\n        public int IntStride => Stride;\n\n        #endregion\n\n        #endregion\n\n        #region Static Tables and Methods\n\n        #region Format file extensions\n\n        private static readonly Dictionary<string, PixFileFormat> s_formatOfExtension = new()\n        {\n            { \".bmp\", PixFileFormat.Bmp },\n            { \".ico\", PixFileFormat.Ico },\n            { \".jpg\", PixFileFormat.Jpeg },\n            { \".jpeg\", PixFileFormat.Jpeg },\n            { \".jng\", PixFileFormat.Jng },\n            { \".koa\", PixFileFormat.Koala },\n            { \".lbm\", PixFileFormat.Lbm },\n            { \".iff\", PixFileFormat.Iff },\n            { \".mng\", PixFileFormat.Mng },\n            { \".pbm\", PixFileFormat.Pbm },\n            { \".pcd\", PixFileFormat.Pcd },\n            { \".pcx\", PixFileFormat.Pcx },\n            { \".pgm\", PixFileFormat.Pgm },\n            { \".png\", PixFileFormat.Png },\n            { \".ppm\", PixFileFormat.Ppm },\n            { \".ras\", PixFileFormat.Ras },\n            { \".targa\", PixFileFormat.Targa },\n            { \".tga\", PixFileFormat.Targa },\n            { \".tif\", PixFileFormat.Tiff },\n            { \".tiff\", PixFileFormat.Tiff },\n            { \".wap\", PixFileFormat.Wbmp },\n            { \".wbm\", PixFileFormat.Wbmp },\n            { \".wbmp\", PixFileFormat.Wbmp },\n            { \".psd\", PixFileFormat.Psd },\n            { \".cut\", PixFileFormat.Cut },\n            { \".xbm\", PixFileFormat.Xbm },\n            { \".xpm\", PixFileFormat.Xpm },\n            { \".dds\", PixFileFormat.Dds },\n            { \".gif\", PixFileFormat.Gif },\n            { \".hdr\", PixFileFormat.Hdr },\n            { \".g3\", PixFileFormat.Faxg3 },\n            { \".sgi\", PixFileFormat.Sgi },\n            { \".exr\", PixFileFormat.Exr },\n            { \".j2c\", PixFileFormat.J2k },\n            { \".j2k\", PixFileFormat.J2k },\n            { \".jp2\", PixFileFormat.Jp2 },\n            { \".pfm\", PixFileFormat.Pfm },\n            { \".pic\", PixFileFormat.Pict },\n            { \".pict\", PixFileFormat.Pict },\n            { \".pct\", PixFileFormat.Pict },\n            { \".raw\", PixFileFormat.Raw },\n            { \".wmp\", PixFileFormat.Wmp },\n            { \".webp\", PixFileFormat.Webp },\n        };\n\n        private static readonly Lazy<Dictionary<PixFileFormat, string>> s_preferredExtensionOfFormat = new(() =>\n            {\n                var result = new Dictionary<PixFileFormat, string>();\n                foreach (var kvp in s_formatOfExtension)\n                {\n                    result[kvp.Value] = kvp.Key;\n                }\n                result[PixFileFormat.PbmRaw] = result[PixFileFormat.Pbm];\n                result[PixFileFormat.PgmRaw] = result[PixFileFormat.Pgm];\n                result[PixFileFormat.PpmRaw] = result[PixFileFormat.Ppm];\n                return result;\n            },\n            LazyThreadSafetyMode.PublicationOnly\n            );\n\n        /// <summary>\n        /// Gets the image file format from a file path.\n        /// Throws exception if file name has no extension, or extension is unknown format.\n        /// </summary>\n        protected static PixFileFormat GetFormatOfExtension(string filename)\n        {\n            if (!Path.HasExtension(filename))\n                throw new ArgumentException(\"File name has no extension: \" + filename);\n\n            var ext = Path.GetExtension(filename).ToLowerInvariant();\n            if (s_formatOfExtension.TryGetValue(ext, out var format))\n                return format;\n            else\n                throw new ArgumentException(\"File name has unknown extension: \" + ext);\n        }\n\n        public static string GetPreferredExtensionOfFormat(PixFileFormat format)\n        {\n            return s_preferredExtensionOfFormat.Value[format];\n        }\n\n        #endregion\n\n        #region Grayscale conversion\n\n        private static void ToGray<T, Tv, R>(PixImage src, object dst, Func<Tv, R> toGray)\n        {\n            ((Matrix<R>)dst).SetMap(src.AsPixImage<T>().GetMatrix<Tv>(), toGray);\n        }\n\n        protected static readonly Dictionary<(Type, Type), Action<PixImage, object>> s_rgbToGrayMap = new()\n            {\n                { (typeof(byte), typeof(byte)),     (src, dst) => ToGray<byte, C3b, byte>(src, dst, Col.ToGrayByte) },\n                { (typeof(ushort), typeof(ushort)), (src, dst) => ToGray<ushort, C3us, ushort>(src, dst, Col.ToGrayUShort) },\n                { (typeof(uint), typeof(uint)),     (src, dst) => ToGray<uint, C3ui, uint>(src, dst, Col.ToGrayUInt) },\n                { (typeof(float), typeof(float)),   (src, dst) => ToGray<float, C3f, float>(src, dst, Col.ToGrayFloat) },\n                { (typeof(double), typeof(double)), (src, dst) => ToGray<double, C3d, double>(src, dst, Col.ToGrayDouble) },\n            };\n\n        #endregion\n\n        #region Create dispatcher\n\n        // Helper class to create PixImage from given Type\n        private static class Dispatch\n        {\n            private delegate PixImage CreateDelegate(Col.Format format, long width, long height, long channels);\n            private delegate PixImage CreateArrayDelegate(Array data, Col.Format format, long width, long height, long channels);\n\n            private static class CreateDispatcher\n            {\n                public static PixImage Create<T>(Col.Format format, long width, long height, long channels)\n                    => new PixImage<T>(format, width, height, channels);\n\n                public static PixImage CreateArray<T>(Array data, Col.Format format, long width, long height, long channels)\n                    => new PixImage<T>(format, (T[])data, width, height, channels);\n            }\n\n            private const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;\n\n            private static readonly MethodInfo s_createMethod = typeof(CreateDispatcher).GetMethod(nameof(CreateDispatcher.Create), flags);\n            private static readonly ConcurrentDictionary<Type, CreateDelegate> s_createDelegates = new();\n\n            private static readonly MethodInfo s_createArrayMethod = typeof(CreateDispatcher).GetMethod(nameof(CreateDispatcher.CreateArray), flags);\n            private static readonly ConcurrentDictionary<Type, CreateArrayDelegate> s_createArrayDelegates = new();\n\n            public static PixImage Create(PixFormat format, long width, long height, long channels)\n            {\n                var create = s_createDelegates.GetOrAdd(format.Type, t => {\n                    var mi = s_createMethod.MakeGenericMethod(t);\n                    return (CreateDelegate)Delegate.CreateDelegate(typeof(CreateDelegate), mi);\n                });\n\n                return create(format.Format, width, height, channels);\n            }\n\n            public static PixImage Create(Array array, Col.Format format, long width, long height, long channels)\n            {\n                var create = s_createArrayDelegates.GetOrAdd(array.GetType().GetElementType(), t => {\n                    var mi = s_createArrayMethod.MakeGenericMethod(t);\n                    return (CreateArrayDelegate)Delegate.CreateDelegate(typeof(CreateArrayDelegate), mi);\n                });\n\n                return create(array, format, width, height, channels);\n            }\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static Creator Functions\n\n        /// <summary>\n        /// Creates a new PixImage with the specified pixel format and dimensions.\n        /// </summary>\n        /// <param name=\"format\">The pixel format (defines channel type and color format).</param>\n        /// <param name=\"width\">The image width in pixels.</param>\n        /// <param name=\"height\">The image height in pixels.</param>\n        /// <param name=\"channels\">The number of channels per pixel.</param>\n        /// <returns>A new PixImage instance.</returns>\n        public static PixImage Create(PixFormat format, long width, long height, long channels)\n            => Dispatch.Create(format, width, height, channels);\n\n        /// <summary>\n        /// Creates a new PixImage with the specified format and dimensions using the format's default channel count.\n        /// </summary>\n        /// <param name=\"format\">The pixel format (defines channel type and color format).</param>\n        /// <param name=\"width\">The image width in pixels.</param>\n        /// <param name=\"height\">The image height in pixels.</param>\n        /// <returns>A new PixImage instance.</returns>\n        public static PixImage Create(PixFormat format, long width, long height)\n            => Dispatch.Create(format, width, height, format.ChannelCount);\n\n        /// <summary>\n        /// Wraps the given array as a PixImage using the provided color format and dimensions.\n        /// </summary>\n        /// <param name=\"array\">The underlying data array.</param>\n        /// <param name=\"format\">The color format describing the channel layout and semantics.</param>\n        /// <param name=\"width\">The image width in pixels.</param>\n        /// <param name=\"height\">The image height in pixels.</param>\n        /// <param name=\"channels\">The number of channels per pixel.</param>\n        /// <returns>A new PixImage instance referencing the provided array.</returns>\n        public static PixImage Create(Array array, Col.Format format, long width, long height, long channels)\n            => Dispatch.Create(array, format, width, height, channels);\n\n        /// <summary>\n        /// Wraps the given array as a PixImage using the format's default channel count.\n        /// </summary>\n        /// <param name=\"array\">The underlying data array.</param>\n        /// <param name=\"format\">The color format describing the channel layout and semantics.</param>\n        /// <param name=\"width\">The image width in pixels.</param>\n        /// <param name=\"height\">The image height in pixels.</param>\n        /// <returns>A new PixImage instance referencing the provided array.</returns>\n        public static PixImage Create(Array array, Col.Format format, long width, long height)\n            => Dispatch.Create(array, format, width, height, format.ChannelCount());\n\n        /// <summary>\n        /// Creates a 3D volume with image-friendly memory layout for the given size.\n        /// </summary>\n        /// <typeparam name=\"T\">Element type of the volume.</typeparam>\n        /// <param name=\"size\">The volume size as (width, height, channels).</param>\n        /// <returns>A new volume with the requested size.</returns>\n        public static Volume<T> CreateVolume<T>(V3i size) => size.ToV3l().CreateImageVolume<T>();\n\n        /// <inheritdoc cref=\"CreateVolume{T}(V3i)\"/>\n        public static Volume<T> CreateVolume<T>(V3l size) => size.CreateImageVolume<T>();\n\n        /// <summary>\n        /// Creates a 3D volume with image-friendly memory layout for the given dimensions.\n        /// </summary>\n        /// <typeparam name=\"T\">Element type of the volume.</typeparam>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        /// <returns>A new volume with the requested size.</returns>\n        public static Volume<T> CreateVolume<T>(long width, long height, long channels)\n            => new V3l(width, height, channels).CreateImageVolume<T>();\n\n        #endregion\n\n        #region Load from file\n\n        private static PixImage LoadFromFileWithLoader(IPixLoader loader, string filename)\n            => InvokeLoader(\n                    loader, l => l.LoadFromFile(filename), NotNull,\n                    $\"load image from file '{filename}'\"\n            );\n\n        /// <summary>\n        /// Loads an image from the given file without doing any conversions.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The image file to load.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>The loaded image.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        public static PixImage LoadRaw(string filename, IPixLoader loader = null)\n            => InvokeLoaders(\n                    LoaderType.Decoder, loader, filename, LoadFromFileWithLoader, Ignore, NotNull,\n                    $\"Could not load image from file '{filename}'\"\n            );\n\n        /// <summary>\n        /// Loads an image from the given file.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The image file to load.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>The loaded image.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        public static PixImage Load(string filename, IPixLoader loader = null)\n        {\n            var loadImage = LoadRaw(filename, loader);\n            return loadImage.ToPixImage(loadImage.Format);\n        }\n\n        #endregion\n\n        #region Load from stream\n\n        internal static string GetStreamDescription(Stream stream)\n            => (stream is FileStream fs) ? $\"file stream '{fs.Name}'\" : \"stream\";\n\n        private static PixImage LoadFromStreamWithLoader(IPixLoader loader, Stream stream)\n            => InvokeLoader(\n                    loader, l => l.LoadFromStream(stream), NotNull,\n                    $\"load image from {GetStreamDescription(stream)}\"\n            );\n\n        /// <summary>\n        /// Loads an image from the given stream without doing any conversions.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The image stream to load.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>The loaded image.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        /// <exception cref=\"NotSupportedException\">if the stream is not seekable and multiple loaders are invoked.</exception>\n        public static PixImage LoadRaw(Stream stream, IPixLoader loader = null)\n            => InvokeLoadersWithStream(\n                LoaderType.Decoder, loader, stream, LoadFromStreamWithLoader, NotNull,\n                $\"Could not load image from {GetStreamDescription(stream)}\"\n            );\n\n        /// <summary>\n        /// Loads an image from the given stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The image stream to load.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>The loaded image.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        /// <exception cref=\"NotSupportedException\">if the stream is not seekable and multiple loaders are invoked.</exception>\n        public static PixImage Load(Stream stream, IPixLoader loader = null)\n        {\n            var loadImage = LoadRaw(stream, loader);\n            return loadImage.ToPixImage(loadImage.Format);\n        }\n\n        #endregion\n\n        #region Save to file\n\n        /// <summary>\n        /// Makes the file name valid for the given format.\n        /// </summary>\n        /// <example>\n        /// E.g. for <see cref=\"PixFileFormat.Png\"/>:\n        /// <code>\n        /// \"foo.png\" -> \"foo.png\"\n        /// \"foo\" -> \"foo.png\"\n        /// \"foo.jpg\" -> \"foo.jpg.png\"\n        /// \"foo.2011\" -> \"foo.2011.png\"\n        /// </code>\n        /// </example>\n        public static string NormalizedFileName(string fileName, PixFileFormat format)\n        {\n            bool appendExtension = false;\n            if (Path.HasExtension(fileName))\n            {\n                var ext = Path.GetExtension(fileName).ToLowerInvariant();\n                if (s_formatOfExtension.TryGetValue(ext, out var value))\n                {\n                    if (value != format)\n                    {\n                        // conflicting extension\n                        // e.g. NormalizedFileName(\"foo.jpg\", PixFileFormat.Png)\n                        appendExtension = true;\n                    }\n                }\n                else\n                {\n                    // unknown extension\n                    // e.g. NormalizedFileName(\"foo.123.2011\", PixFileFormat.Png)\n                    appendExtension = true;\n                }\n            }\n            else\n            {\n                // no extension\n                // e.g. NormalizedFileName(\"foo\", PixFileFormat.Png)\n                appendExtension = true;\n            }\n\n            if (appendExtension)\n            {\n                fileName += GetPreferredExtensionOfFormat(format);\n            }\n\n            return fileName;\n        }\n\n        private bool SaveToFileWithLoader(IPixLoader loader, string filename, PixSaveParams saveParams)\n            => InvokeLoader(\n                    loader, l => { l.SaveToFile(filename, this, saveParams); return true; }, Identity,\n                    $\"save image to file '{filename}'\"\n            );\n\n        /// <summary>\n        /// Saves the image to the given file.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The file to save the image to.</param>\n        /// <param name=\"saveParams\">The save parameters to use.</param>\n        /// <param name=\"normalizeFilename\">Indicates if the filename is to be normalized according to the image file format.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        public void Save(string filename, PixSaveParams saveParams, bool normalizeFilename = true, IPixLoader loader = null)\n        {\n            if (normalizeFilename)\n                filename = NormalizedFileName(filename, saveParams.Format);\n\n            InvokeLoaders(\n                LoaderType.Encoder, loader, filename, (l, f) => SaveToFileWithLoader(l, f, saveParams), Ignore, Identity,\n                $\"Could not save image to file '{filename}'\"\n            );\n        }\n\n        /// <summary>\n        /// Saves the image to the given file.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The file to save the image to.</param>\n        /// <param name=\"fileFormat\">The image format of the file.</param>\n        /// <param name=\"normalizeFilename\">Indicates if the filename is to be normalized according to the image file format.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        public void Save(string filename, PixFileFormat fileFormat, bool normalizeFilename = true, IPixLoader loader = null)\n            => Save(filename, new PixSaveParams(fileFormat), normalizeFilename, loader);\n\n        /// <summary>\n        /// Saves the image to the given file.\n        /// The image file format is determined by the extension of the filename.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The file to save the image to.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        /// <exception cref=\"ArgumentException\">if the filename extension is missing or unknown.</exception>\n        public void Save(string filename, IPixLoader loader = null)\n            => Save(filename, GetFormatOfExtension(filename), false, loader);\n\n        /// <summary>\n        /// Saves the image to the given JPEG file.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The file to save the image to.</param>\n        /// <param name=\"quality\">The quality of the JPEG file. Must be within 0 - 100.</param>\n        /// <param name=\"normalizeFilename\">Indicates if the filename is to be normalized according to the image file format.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        public void SaveAsJpeg(string filename, int quality = PixJpegSaveParams.DefaultQuality,\n                               bool normalizeFilename = true, IPixLoader loader = null)\n            => Save(filename, new PixJpegSaveParams(quality), normalizeFilename, loader);\n\n        /// <summary>\n        /// Saves the image to the given PNG file.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The file to save the image to.</param>\n        /// <param name=\"compressionLevel\">The compression level of the PNG file. Must be within 0 - 9.</param>\n        /// <param name=\"normalizeFilename\">Indicates if the filename is to be normalized according to the image file format.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        public void SaveAsPng(string filename, int compressionLevel = PixPngSaveParams.DefaultCompressionLevel,\n                              bool normalizeFilename = true, IPixLoader loader = null)\n            => Save(filename, new PixPngSaveParams(compressionLevel), normalizeFilename, loader);\n\n        #endregion\n\n        #region Save to stream\n\n        private bool SaveToStreamWithLoader(IPixLoader loader, Stream stream, PixSaveParams saveParams)\n            => InvokeLoader(\n                    loader, l => { l.SaveToStream(stream, this, saveParams); return true; }, Identity,\n                    \"save image to stream\"\n            );\n\n        /// <summary>\n        /// Saves the image to the given stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The stream to save the image to.</param>\n        /// <param name=\"saveParams\">The save parameters to use.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        /// <exception cref=\"NotSupportedException\">if the stream is not seekable and multiple loaders are invoked.</exception>\n        public void Save(Stream stream, PixSaveParams saveParams, IPixLoader loader = null)\n            => InvokeLoadersWithStream(\n                LoaderType.Encoder, loader, stream, (l, s) => SaveToStreamWithLoader(l, s, saveParams), Identity,\n                \"Could not save image to stream\"\n            );\n\n        /// <summary>\n        /// Saves the image to the given stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The stream to save the image to.</param>\n        /// <param name=\"fileFormat\">The image format of the stream.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        /// <exception cref=\"NotSupportedException\">if the stream is not seekable and multiple loaders are invoked.</exception>\n        public void Save(Stream stream, PixFileFormat fileFormat, IPixLoader loader = null)\n            => Save(stream, new PixSaveParams(fileFormat), loader);\n\n        /// <summary>\n        /// Saves the image to the given JPEG stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The stream to save the image to.</param>\n        /// <param name=\"quality\">The quality of the JPEG file. Must be within 0 - 100.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        /// <exception cref=\"NotSupportedException\">if the stream is not seekable and multiple loaders are invoked.</exception>\n        public void SaveAsJpeg(Stream stream, int quality = PixJpegSaveParams.DefaultQuality, IPixLoader loader = null)\n            => Save(stream, new PixJpegSaveParams(quality), loader);\n\n        /// <summary>\n        /// Saves the image to the given PNG stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The file to save the image to.</param>\n        /// <param name=\"compressionLevel\">The compression level of the PNG file. Must be within 0 - 9.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        /// <exception cref=\"NotSupportedException\">if the stream is not seekable and multiple loaders are invoked.</exception>\n        public void SaveAsPng(Stream stream, int compressionLevel = PixPngSaveParams.DefaultCompressionLevel, IPixLoader loader = null)\n            => Save(stream, new PixPngSaveParams(compressionLevel), loader);\n\n        /// <summary>\n        /// Writes the image to a memory stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"saveParams\">The save parameters to use.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>A memory stream containing the image data.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        public MemoryStream ToMemoryStream(PixSaveParams saveParams, IPixLoader loader = null)\n        {\n            var stream = new MemoryStream();\n            Save(stream, saveParams, loader);\n            return stream;\n        }\n\n        /// <summary>\n        /// Writes the image to a memory stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"fileFormat\">The image format of the stream.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>A memory stream containing the image data.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        public MemoryStream ToMemoryStream(PixFileFormat fileFormat, IPixLoader loader = null)\n            => ToMemoryStream(new PixSaveParams(fileFormat), loader);\n\n        /// <summary>\n        /// Writes the image to a JPEG memory stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"quality\">The quality of the JPEG file. Must be within 0 - 100.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>A memory stream containing the image data.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        public MemoryStream ToMemoryStreamAsJpeg(int quality = PixJpegSaveParams.DefaultQuality, IPixLoader loader = null)\n            => ToMemoryStream(new PixJpegSaveParams(quality), loader);\n\n        /// <summary>\n        /// Writes the image to a PNG memory stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"compressionLevel\">The compression level of the PNG file. Must be within 0 - 9.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>A memory stream containing the image data.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        public MemoryStream ToMemoryStreamAsPng(int compressionLevel = PixPngSaveParams.DefaultCompressionLevel, IPixLoader loader = null)\n            => ToMemoryStream(new PixJpegSaveParams(compressionLevel), loader);\n\n        #endregion\n\n        #region Query info from file\n\n        private static PixImageInfo GetInfoFromFileWithLoader(IPixLoader loader, string filename)\n            => InvokeLoader(\n                    loader, l => l.GetInfoFromFile(filename), NotNull,\n                    $\"get image info from file '{filename}'\"\n            );\n\n        /// <summary>\n        /// Loads basic information about an image from a file without loading its content.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The image file to load.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>A PixImageInfo instance containing basic information about the image.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        public static PixImageInfo GetInfoFromFile(string filename, IPixLoader loader = null)\n            => InvokeLoaders(\n                    LoaderType.Any, loader, filename, GetInfoFromFileWithLoader, Ignore, NotNull,\n                    $\"Could not get image info from file '{filename}'\"\n            );\n\n        #endregion\n\n        #region Query info from stream\n\n        private static PixImageInfo GetInfoFromStreamWithLoader(IPixLoader loader, Stream stream)\n            => InvokeLoader(\n                    loader, l => l.GetInfoFromStream(stream), NotNull,\n                    \"get image info from stream\"\n            );\n\n        /// <summary>\n        /// Loads basic information about an image from a stream without loading its content.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The image stream to load.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <returns>A PixImageInfo instance containing basic information about the image.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        /// <exception cref=\"NotSupportedException\">if the stream is not seekable and multiple loaders are invoked.</exception>\n        public static PixImageInfo GetInfoFromStream(Stream stream, IPixLoader loader = null)\n            => InvokeLoadersWithStream(\n                    LoaderType.Any, loader, stream, GetInfoFromStreamWithLoader, NotNull,\n                    $\"Could not get image info from stream\"\n            );\n\n        #endregion\n\n        #region Conversions\n\n        /// <summary>\n        /// Attempts to cast this instance to <see cref=\"PixImage{T}\"/>. Returns null if the element type differs.\n        /// </summary>\n        /// <typeparam name=\"T\">Target element type.</typeparam>\n        /// <returns>The typed image or null.</returns>\n        public PixImage<T> AsPixImage<T>() => this as PixImage<T>;\n\n        /// <summary>\n        /// Returns a typed view of this image. If the element type differs, a new image with converted element type is created by copying.\n        /// </summary>\n        /// <typeparam name=\"T\">Target element type.</typeparam>\n        /// <returns>A typed image of <typeparamref name=\"T\"/>.</returns>\n        public PixImage<T> ToPixImage<T>() => AsPixImage<T>() ?? new PixImage<T>(this);\n\n        /// <summary>\n        /// Converts this image to the specified color format while keeping the underlying element type.\n        /// If this image already has the requested format, returns the same instance;\n        /// in that case no data conversion or additional allocation is performed.\n        /// </summary>\n        /// <param name=\"format\">Target color format.</param>\n        /// <returns>An image in the requested format; this instance if no conversion is required.</returns>\n        public abstract PixImage ToPixImage(Col.Format format);\n\n        /// <summary>\n        /// Converts this image to the specified color format and element type.\n        /// If this image already has the requested format and element type, returns the same instance;\n        /// in that case no data conversion or additional allocation is performed.\n        /// </summary>\n        /// <param name=\"format\">Target color format.</param>\n        /// <typeparam name=\"T\">Target element type.</typeparam>\n        /// <returns>A typed image in the requested format; this instance if no conversion is required.</returns>\n        public PixImage<T> ToPixImage<T>(Col.Format format)\n        {\n            if (this is PixImage<T> image && image.Format == format && image.ChannelCount == format.ChannelCount()) return image;\n            return new PixImage<T>(format, this);\n        }\n\n        /// <summary>\n        /// Returns a representation with canonical, densely packed memory layout.\n        /// If this image is already in the correct layout, returns the same instance;\n        /// in that case no data conversion or additional allocation is performed.\n        /// </summary>\n        public abstract PixImage ToCanonicalDenseLayout();\n\n        #endregion\n\n        #region Copy\n\n        /// <summary>\n        /// Copies a single channel to the target matrix (must match in size).\n        /// If the element type differs, the data are reinterpreted.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element type of the destination matrix.</typeparam>\n        /// <param name=\"channelIndex\">Index of the channel in this matrix.</param>\n        /// <param name=\"target\">Destination matrix receiving the channel data.</param>\n        /// <exception cref=\"NotSupportedException\">if the element type <typeparamref name=\"Tv\"/> is invalid.</exception>\n        public abstract void CopyChannelTo<Tv>(long channelIndex, Matrix<Tv> target);\n\n        /// <summary>\n        /// Copies the entire underlying volume to the given target volume (must match in size).\n        /// If the element type differs, the data are reinterpreted.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element type of the destination volume.</typeparam>\n        /// <param name=\"target\">Destination volume.</param>\n        /// <exception cref=\"NotSupportedException\">if the element type <typeparamref name=\"Tv\"/> is invalid.</exception>\n        public abstract void CopyVolumeTo<Tv>(Volume<Tv> target);\n\n        /// <summary>\n        /// Creates a deep copy of this image.\n        /// </summary>\n        public abstract PixImage CopyToPixImage();\n\n        /// <summary>\n        /// Creates a deep copy of this image using the canonical dense memory layout.\n        /// </summary>\n        public abstract PixImage CopyToPixImageWithCanonicalDenseLayout();\n\n        #endregion\n\n        #region Image Manipulation\n\n        /// <summary>\n        /// Returns a transformed copy of this image using the specified image transformation.\n        /// </summary>\n        /// <param name=\"trafo\">The image transformation to apply.</param>\n        /// <returns>A new PixImage with the transformation applied.</returns>\n        public abstract PixImage TransformedPixImage(ImageTrafo trafo);\n\n        /// <summary>\n        /// Returns a remapped copy of this image using the provided per-pixel coordinate maps.\n        /// </summary>\n        /// <param name=\"mapX\">Matrix of X-coordinate samples mapping destination pixels to source X.</param>\n        /// <param name=\"mapY\">Matrix of Y-coordinate samples mapping destination pixels to source Y.</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <returns>A new PixImage generated by sampling the source with the given maps.</returns>\n        public abstract PixImage RemappedPixImage(Matrix<float> mapX, Matrix<float> mapY, ImageInterpolation interpolation = ImageInterpolation.Cubic);\n\n        /// <summary>\n        /// Returns a resized copy of this image.\n        /// </summary>\n        /// <param name=\"size\">Requested output size in pixels.</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <returns>A new PixImage with the given size.</returns>\n        public abstract PixImage ResizedPixImage(V2i size, ImageInterpolation interpolation = ImageInterpolation.Cubic);\n\n        /// <summary>\n        /// Returns a rotated copy of this image around its center.\n        /// </summary>\n        /// <param name=\"angleInRadians\">Rotation angle in radians, counter-clockwise.</param>\n        /// <param name=\"resize\">When <c>true</c>, the output image is resized to fully contain the rotated content; otherwise it keeps the original size.</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <returns>A new PixImage containing the rotated image.</returns>\n        public abstract PixImage RotatedPixImage(double angleInRadians, bool resize = true, ImageInterpolation interpolation = ImageInterpolation.Cubic);\n\n        /// <summary>\n        /// Returns a scaled copy of this image by the given factors.\n        /// </summary>\n        /// <param name=\"scaleFactor\">The scale factor to apply in X and Y (1.0 keeps the size).</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <returns>A new PixImage scaled by the given factors.</returns>\n        public abstract PixImage ScaledPixImage(V2d scaleFactor, ImageInterpolation interpolation = ImageInterpolation.Cubic);\n\n        #endregion\n\n        #region Static Utility Methods\n\n        /// <summary>\n        /// Compress BW images from 8 bits per byte to 1 bit per byte.\n        /// </summary>\n        public static void CompressPixels(PixImage<byte> pixImage, PixImage<byte> bitImage)\n        {\n            var bitData = bitImage.Volume.Data; int bi = 0; byte bit = 0x80;\n            var pixData = pixImage.Volume.Data;\n\n            // compress pixels\n            pixImage.Volume.Info.ForeachYXIndex(\n                () => { if (bit != 0x80) { bit = 0x80; bi++; } },\n                i =>\n                {\n                    if ((pixData[i] & 0x80) != 0) bitData[bi] |= bit;\n                    bit >>= 1; if (bit == 0) { bit = 0x80; bi++; }\n                }\n            );\n        }\n\n        /// <summary>\n        /// Expand BW images from 1 bit per byte to 8 bits per byte.\n        /// </summary>\n        public static void ExpandPixels(PixImage<byte> bitImage, PixImage<byte> pixImage)\n        {\n            var bitData = bitImage.Volume.Data; int bi = 0; byte bit = 0x80;\n            var pixData = pixImage.Volume.Data;\n\n            // expand pixels\n            pixImage.Volume.Info.ForeachYXIndex(\n                () => { if (bit != 0x80) { bit = 0x80; bi++; } },\n                i =>\n                {\n                    pixData[i] = ((bitData[bi] & bit) != 0) ? (byte)255 : (byte)0;\n                    bit >>= 1; if (bit == 0) { bit = 0x80; bi++; }\n                }\n            );\n        }\n\n        #endregion\n\n        #region IPixImageVisitor\n\n        /// <summary>\n        /// Dispatches the current instance to a visitor based on its element type.\n        /// </summary>\n        /// <typeparam name=\"TResult\">The result type produced by the visitor.</typeparam>\n        /// <param name=\"visitor\">The visitor implementation.</param>\n        /// <returns>The visitor-specific result.</returns>\n        public abstract TResult Visit<TResult>(IPixImageVisitor<TResult> visitor);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// 2D pixel container with element type <typeparamref name=\"T\"/>.\n    /// Provides access to the underlying 3D volume.\n    /// </summary>\n    /// <typeparam name=\"T\">Per-channel element type.</typeparam>\n    [Serializable]\n    public class PixImage<T> : PixImage\n    {\n        /// <summary>\n        /// The underlying 3D volume storing the image data.\n        /// </summary>\n        public Volume<T> Volume;\n\n        #region Constructors\n\n        #region  Default\n\n        /// <summary>\n        /// Initializes a new empty PixImage instance without allocating storage.\n        /// Intended for serializers or deferred initialization scenarios. The\n        /// <see cref=\"Volume\"/> field must be assigned before use.\n        /// </summary>\n        public PixImage() { }\n\n\n        #endregion\n\n        #region From Volume\n\n        /// <summary>\n        /// Creates a new PixImage backed by the given volume and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"volume\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"volume\">Backing volume in image layout. Not copied.</param>\n        public PixImage(Col.Format format, Volume<T> volume)\n            : base(format)\n        {\n            Volume = volume;\n        }\n\n        /// <summary>\n        /// Creates a new PixImage backed by the given volume and using the default color format for the element type.\n        /// No data is copied; the instance takes a reference to <paramref name=\"volume\"/>.\n        /// </summary>\n        /// <param name=\"volume\">Backing volume in image layout. Not copied.</param>\n        public PixImage(Volume<T> volume)\n            : this(Col.FormatDefaultOf(typeof(T), volume.SZ), volume)\n        { }\n\n        #endregion\n\n        #region  From Dimensions\n\n        /// <summary>\n        /// Allocates a new image with the given 2D size and channel count using the default color format for the element type.\n        /// </summary>\n        /// <param name=\"size\">Image size in pixels (width, height).</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixImage(V2i size, int channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), CreateVolume<T>(size.X, size.Y, channels))\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(V2i, int)\"/>\n        public PixImage(V2l size, long channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), CreateVolume<T>(size.X, size.Y, channels))\n        { }\n\n        /// <summary>\n        /// Allocates a new image with the given dimensions and channel count using the default color format for the element type.\n        /// </summary>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixImage(int width, int height, int channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), CreateVolume<T>(width, height, channels))\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(int, int, int)\"/>\n        public PixImage(long width, long height, long channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), CreateVolume<T>(width, height, channels))\n        { }\n\n        /// <summary>\n        /// Allocates a new image with the given size and channel format. The number of channels is\n        /// derived from <paramref name=\"format\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"size\">Image size in pixels (width, height).</param>\n        public PixImage(Col.Format format, V2i size)\n            : this(format, CreateVolume<T>(size.X, size.Y, format.ChannelCount()))\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, V2i)\"/>\n        public PixImage(Col.Format format, V2l size)\n            : this(format, CreateVolume<T>(size.X, size.Y, format.ChannelCount()))\n        { }\n\n        /// <summary>\n        /// Allocates a new image with the given dimensions and channel format. The number of channels is\n        /// derived from <paramref name=\"format\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        public PixImage(Col.Format format, int width, int height)\n            : this(format, CreateVolume<T>(width, height, format.ChannelCount()))\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, int, int)\"/>\n        public PixImage(Col.Format format, long width, long height)\n            : this(format, CreateVolume<T>(width, height, format.ChannelCount()))\n        { }\n\n        /// <summary>\n        /// Allocates a new image with the given size, explicit channel count and format.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"size\">Image size in pixels (width, height).</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixImage(Col.Format format, V2i size, int channels)\n            : this(format, CreateVolume<T>(size.X, size.Y, channels))\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, V2i, int)\"/>\n        public PixImage(Col.Format format, V2l size, long channels)\n            : this(format, CreateVolume<T>(size.X, size.Y, channels))\n        { }\n\n        [Obsolete(\"Use PixImage<T>(Col.Format, V2i, int) or PixImage<T>(Col.Format, V2l, long) instead.\")]\n        public PixImage(Col.Format format, V2i size, long channels)\n            : this(format, CreateVolume<T>(size.X, size.Y, channels))\n        { }\n\n        /// <summary>\n        /// Allocates a new image with the given dimensions, explicit channel count and format.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixImage(Col.Format format, int width, int height, int channels)\n            : this(format, CreateVolume<T>(width, height, channels))\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, int, int, int)\"/>\n        public PixImage(Col.Format format, long width, long height, long channels)\n            : this(format, CreateVolume<T>(width, height, channels))\n        { }\n\n        #endregion\n\n        #region From PixImageInfo\n\n        /// <summary>\n        /// Initializes a new image from meta information (without loading pixel data).\n        /// </summary>\n        /// <param name=\"info\">Image metadata (size, format, type).</param>\n        /// <exception cref=\"ArgumentException\">if the element type <typeparamref name=\"T\"/> does not match <c>info.Format.Type</c>.</exception>\n        public PixImage(PixImageInfo info)\n            : this(info.Format.Format, info.Size)\n        {\n            if (info.Format.Type != typeof(T)) throw new ArgumentException($\"Expected element type {typeof(T)} but format has type {info.Format.Type}.\");\n        }\n\n        #endregion\n\n        #region From Channel Matrices\n\n        /// <summary>\n        /// Creates an image from the given channel matrices with the default color format.\n        /// The channel data are copied to a newly allocated volume.\n        /// </summary>\n        /// <param name=\"channels\">Sequence of channel matrices in canonical order (red, green, blue, alpha).</param>\n        /// <exception cref=\"ArgumentException\">if <paramref name=\"channels\"/> is null or empty.</exception>\n        /// <exception cref=\"ArgumentException\">if fewer channels are provided than expected by the default color format.</exception>\n        /// <exception cref=\"ArgumentException\">if the channel matrices differ in size.</exception>\n        public PixImage(IEnumerable<Matrix<T>> channels)\n            : this(channels.ToArray())\n        { }\n\n        /// <summary>\n        /// Creates an image from the given channel matrices with the default color format.\n        /// The channel data are copied to a newly allocated volume.\n        /// </summary>\n        /// <param name=\"channels\">Array of channel matrices in canonical order (red, green, blue, alpha).</param>\n        /// <exception cref=\"ArgumentException\">if <paramref name=\"channels\"/> is null or empty.</exception>\n        /// <exception cref=\"ArgumentException\">if fewer channels are provided than expected by the default color format.</exception>\n        /// <exception cref=\"ArgumentException\">if the channel matrices differ in size.</exception>\n        public PixImage(params Matrix<T>[] channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels.Length), channels)\n        { }\n\n        /// <summary>\n        /// Creates an image from the given channel matrices and color format.\n        /// The channel data are copied to a newly allocated volume.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"channels\">Sequence of channel matrices in canonical order (red, green, blue, alpha).</param>\n        /// <exception cref=\"ArgumentException\">if <paramref name=\"channels\"/> is null or empty.</exception>\n        /// <exception cref=\"ArgumentException\">if fewer channels are provided than expected by <paramref name=\"format\"/>.</exception>\n        /// <exception cref=\"ArgumentException\">if the channel matrices differ in size.</exception>\n        public PixImage(Col.Format format, IEnumerable<Matrix<T>> channels)\n            : this(format, channels.ToArray())\n        { }\n\n        /// <summary>\n        /// Creates an image from the given channel matrices and color format.\n        /// The channel data are copied to a newly allocated volume.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"channels\">Array of channel matrices in canonical order (red, green, blue, alpha).</param>\n        /// <exception cref=\"ArgumentException\">if <paramref name=\"channels\"/> is null or empty.</exception>\n        /// <exception cref=\"ArgumentException\">if fewer channels are provided than expected by <paramref name=\"format\"/>.</exception>\n        /// <exception cref=\"ArgumentException\">if the channel matrices differ in size.</exception>\n        public PixImage(Col.Format format, params Matrix<T>[] channels)\n            : base(format)\n        {\n            int channelCount = format.ChannelCount();\n            if (channels.IsEmptyOrNull()) throw new ArgumentException(\"Channels cannot be null or empty.\");\n            if (channels.Length < channelCount) throw new ArgumentException($\"Color format expects {channelCount} but got only {channels.Length}.\");\n\n            var ch0 = channels[0];\n\n            var sx = ch0.SX;\n            var sy = ch0.SY;\n\n            var volume = CreateVolume<T>(sx, sy, channelCount);\n            var order = format.ChannelOrder();\n\n            for (int i = 0; i < channelCount; i++)\n            {\n                var mat = volume.SubXYMatrix(order[i]);\n                var channel = channels[i];\n                if (channel.IsValid) mat.Set(channel);\n            }\n\n            Volume = volume;\n        }\n\n        #endregion\n\n        #region From Array\n\n        /// <summary>\n        /// Creates a new PixImage backed by the given array and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image volume with the specified dimensions.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixImage(Col.Format format, T[] data, int width, int height, int channels)\n            : this(format, data.CreateImageVolume(new V3l(width, height, channels)))\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, T[], int, int, int)\"/>\n        public PixImage(Col.Format format, T[] data, long width, long height, long channels)\n            : this(format, data.CreateImageVolume(new V3l(width, height, channels)))\n        { }\n\n        /// <summary>\n        /// Creates a new PixImage backed by the given array and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image volume with the specified dimensions.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"size\">Image size in pixels (width, height).</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixImage(Col.Format format, T[] data, V2i size, int channels)\n            : this(format, data, size.X, size.Y, channels)\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, T[], V2i, int)\"/>\n        public PixImage(Col.Format format, T[] data, V2l size, long channels)\n            : this(format, data, size.X, size.Y, channels)\n        { }\n\n        /// <summary>\n        /// Creates a new PixImage backed by the given array and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image volume with the specified dimensions.\n        /// The number of channels is derived from <paramref name=\"format\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        public PixImage(Col.Format format, T[] data, int width, int height)\n            : this(format, data, width, height, format.ChannelCount())\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, T[], int, int)\"/>\n        public PixImage(Col.Format format, T[] data, long width, long height)\n            : this(format, data, width, height, format.ChannelCount())\n        { }\n\n        /// <summary>\n        /// Creates a new PixImage backed by the given array and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image volume with the specified dimensions.\n        /// The number of channels is derived from <paramref name=\"format\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"size\">Image size in pixels (width, height).</param>\n        public PixImage(Col.Format format, T[] data, V2i size)\n            : this(format, data, size.X, size.Y)\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, T[], V2i)\"/>\n        public PixImage(Col.Format format, T[] data, V2l size)\n            : this(format, data, size.X, size.Y)\n        { }\n\n        /// <summary>\n        /// Creates a new PixImage backed by the given array and using the default color format for the element type.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image volume with the specified dimensions.\n        /// </summary>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixImage(T[] data, int width, int height, int channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), data, width, height, channels)\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(T[], int, int, int)\"/>\n        public PixImage(T[] data, long width, long height, long channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), data, width, height, channels)\n        { }\n\n        /// <summary>\n        /// Creates a new PixImage backed by the given array and using the default color format for the element type.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image volume with the specified dimensions.\n        /// </summary>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"size\">Image size in pixels (width, height).</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixImage(T[] data, V2i size, int channels)\n            : this(data, size.X, size.Y, channels)\n        { }\n\n        /// <inheritdoc cref=\"PixImage{T}(T[], V2i, int)\"/>\n        public PixImage(T[] data, V2l size, long channels)\n            : this(data, size.X, size.Y, channels)\n        { }\n\n        #endregion\n\n        #region From Copy\n\n        /// <summary>\n        /// Creates a typed copy of the given image. Always allocates new storage and copies data.\n        /// The channel count is taken from <paramref name=\"source\"/>, the element type becomes\n        /// <typeparamref name=\"T\"/> (conversion may occur).\n        /// </summary>\n        /// <param name=\"source\">Source image to copy from.</param>\n        /// <remarks>\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, PixImage)\" path=\"/remarks\"/>\n        /// </remarks>\n        public PixImage(PixImage source)\n            : this(Col.FormatDefaultOf(typeof(T), source.Format.ChannelCount()), source)\n        { }\n\n        /// <summary>\n        /// Creates a typed copy of the given image in the requested color format. Always allocates new storage\n        /// and copies or converts channel data as needed.\n        /// </summary>\n        /// <param name=\"format\">Target color format for the new image.</param>\n        /// <param name=\"source\">Source image to copy from.</param>\n        /// <remarks>\n        /// <list type=\"bullet\">\n        /// <item>\n        /// Premultiplied state must match between <paramref name=\"format\"/> and <paramref name=\"source\"/>;\n        /// otherwise a <see cref=\"NotImplementedException\"/> is thrown.\n        /// </item>\n        /// <item>\n        /// If the formats match and sizes are equal, a straight copy is performed.\n        /// </item>\n        /// <item>\n        /// Missing alpha is filled with the maximum value of <typeparamref name=\"T\"/>.\n        /// </item>\n        /// <item>\n        /// Gray can be computed from RGB for a few common element types; unsupported combinations throw.\n        /// </item>\n        /// <item>\n        /// Expanding RG to RGB sets blue to zero.\n        /// </item>\n        /// <item>\n        /// Other unmapped conversions throw <see cref=\"NotSupportedException\"/>.\n        /// </item>\n        /// </list>\n        /// </remarks>\n        public PixImage(Col.Format format, PixImage source)\n        {\n            if (format.IsPremultiplied() != source.Format.IsPremultiplied())\n            {\n                throw new NotImplementedException(\n                    \"Conversion between alpha and premultiplied alpha formats not implemented yet.\"\n                );\n            }\n\n            var srcInfo = source.VolumeInfo;\n            var dstChannels = Col.ChannelsOfFormat(format);\n            var volume = CreateVolume<T>(srcInfo.Size.X, srcInfo.Size.Y, dstChannels.Length);\n            volume.F = srcInfo.F;\n\n            if (format == source.Format && srcInfo.Size == volume.Size)\n            {\n                source.CopyVolumeTo(volume);\n            }\n            else\n            {\n                var srcChannels = Col.ChannelsOfFormat(source.Format);\n\n                for (int dstIndex = 0; dstIndex < dstChannels.Length; dstIndex++)\n                {\n                    var channel = dstChannels[dstIndex];\n                    var matrix = volume.SubXYMatrix(dstIndex);\n                    var srcIndex = srcChannels.IndexOf(channel);\n\n                    // If we have an RGB channel, we may also just copy a Gray or BW channel\n                    if (srcIndex == -1 && (channel == Col.Channel.Red || channel == Col.Channel.Green || channel == Col.Channel.Blue))\n                    {\n                        var bw = srcChannels.IndexOf(Col.Channel.BW);\n                        var gray = srcChannels.IndexOf(Col.Channel.Gray);\n                        srcIndex = Fun.Max(bw, gray);\n                    }\n\n                    if (srcIndex > -1)\n                    {\n                        // Channel exists in source image, just copy\n                        if (source is PixImage<T> pi)\n                        {\n                            matrix.Set(pi.GetChannelInFormatOrder(srcIndex));\n                        }\n                        else\n                        {\n                            var order = source.Format.ChannelOrder();\n                            source.CopyChannelTo(order[srcIndex], matrix); // CopyChannelTo uses canonical order\n                        }\n                    }\n                    else if (channel == Col.Channel.Alpha || channel == Col.Channel.PremultipliedAlpha)\n                    {\n                        // Alpha channel does not exist in source image, fill with max value\n                        matrix.Set(Col.Info<T>.MaxValue);\n                    }\n                    else if (channel == Col.Channel.Gray &&\n                             srcChannels.Contains(Col.Channel.Red) &&\n                             srcChannels.Contains(Col.Channel.Green) &&\n                             srcChannels.Contains(Col.Channel.Blue))\n                    {\n                        var t1 = source.PixFormat.Type;\n                        var t2 = typeof(T);\n\n                        if (s_rgbToGrayMap.TryGetValue((t1, t2), out var toGray))\n                        {\n                            toGray(source, matrix);\n                        }\n                        else\n                        {\n                            throw new NotImplementedException(\n                                $\"Conversion from {t1} image with format {source.Format} to {t2} grayscale not implemented.\"\n                            );\n                        }\n                    }\n                    else if (channel == Col.Channel.Blue &&\n                             source.Format == Col.Format.RG &&\n                             dstChannels.Contains(Col.Channel.Red) &&\n                             dstChannels.Contains(Col.Channel.Green))\n                    {\n                        // Allow expanding from RG to RGB formats, blue channel is set to zero\n                    }\n                    else\n                    {\n                        throw new NotSupportedException(\n                            $\"Conversion from format {source.Format} to format {format} is not supported.\"\n                        );\n                    }\n                }\n            }\n\n            Volume = volume;\n            Format = format;\n        }\n\n        #endregion\n\n        #region From File / Stream\n\n        /// <summary>\n        /// Loads an image from the given file.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The image file to load.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        public PixImage(string filename, IPixLoader loader = null)\n        {\n            var loadImage = LoadRaw(filename, loader);\n            var channels = loadImage.Format.ChannelCount();\n\n            if (loadImage is not PixImage<T> image || image.ChannelCount != channels)\n                image = new PixImage<T>(loadImage);\n\n            Volume = image.Volume;\n            Format = image.Format;\n        }\n\n        /// <summary>\n        /// Loads an image from the given stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The image stream to load.</param>\n        /// <param name=\"loader\">The loader to use, or null if no specific loader is to be used.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        public PixImage(Stream stream, IPixLoader loader = null)\n        {\n            var loadImage = LoadRaw(stream, loader);\n            var channels = loadImage.Format.ChannelCount();\n\n            if (loadImage is not PixImage<T> image || image.ChannelCount != channels)\n                image = new PixImage<T>(loadImage);\n\n            Volume = image.Volume;\n            Format = image.Format;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Static Creator Functions\n\n        /// <inheritdoc cref=\"PixImage{T}(Matrix{T}[])\"/>\n        public static PixImage<T> Create(params Matrix<T>[] channels)\n            => new(channels);\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, Matrix{T}[])\"/>\n        public static PixImage<T> Create(Col.Format format, params Matrix<T>[] channels)\n            => new(format, channels);\n\n        /// <inheritdoc cref=\"PixImage{T}(Col.Format, Matrix{T}[])\"/>\n        public static PixImage<T> Create<Td>(Col.Format format, params Matrix<Td, T>[] channels)\n        {\n            int channelCount = format.ChannelCount();\n            if (channels.IsEmptyOrNull()) throw new ArgumentException(\"Channels cannot be null or empty.\");\n            if (channels.Length < channelCount) throw new ArgumentException($\"Color format expects {channelCount} but got only {channels.Length}.\");\n\n            var ch0 = channels[0];\n\n            var sx = ch0.SX;\n            var sy = ch0.SY;\n\n            var volume = CreateVolume<T>(sx, sy, channelCount);\n            var order = format.ChannelOrder();\n\n            for (int i = 0; i < channelCount; i++)\n            {\n                var mat = volume.SubXYMatrix(order[i]);\n                var channel = channels[i];\n                if (channel.IsValid) mat.Set(channel);\n            }\n\n            return new PixImage<T>(format, volume);\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the underlying storage as a <typeparamref name=\"T\"/> array.\n        /// </summary>\n        public T[] Data => Volume.Data;\n\n        /// <inheritdoc />\n        public override Array Array => Volume.Array;\n\n        /// <inheritdoc />\n        public override PixFormat PixFormat => new PixFormat(typeof(T), Format);\n\n        /// <inheritdoc />\n        public override VolumeInfo VolumeInfo => Volume.Info;\n\n        /// <inheritdoc />\n        public override int BytesPerChannel => typeof(T).GetCLRSize();\n\n        /// <summary>\n        /// Gets the channel matrices of the image in canonical order (red, green, blue, alpha).\n        /// </summary>\n        public IEnumerable<Matrix<T>> Channels\n        {\n            get\n            {\n                long[] order = Format.ChannelOrder();\n                for (long i = 0; i < order.Length; i++)\n                    yield return GetChannelInFormatOrder(order[i]);\n            }\n        }\n\n        /// <summary>\n        /// Gets the channel matrices of the image as array in canonical order (red, green, blue, alpha).\n        /// </summary>\n        public Matrix<T>[] ChannelArray => Channels.ToArray();\n\n        /// <summary>\n        /// Returns the matrix representation of the volume if there is only one channel.\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">if there are multiple channels.</exception>\n        public Matrix<T> Matrix => Volume.AsMatrixWindow();\n\n        #endregion\n\n        #region Image Manipulation\n\n        #region Transformed\n\n        /// <inheritdoc />\n        public override PixImage TransformedPixImage(ImageTrafo trafo)\n            => Transformed(trafo);\n\n        /// <inheritdoc cref=\"TransformedPixImage\" />\n        public PixImage<T> Transformed(ImageTrafo trafo) => new(Format, Volume.Transformed(trafo));\n\n        #endregion\n\n        #region Remapped\n\n        /// <inheritdoc />\n        public override PixImage RemappedPixImage(Matrix<float> mapX, Matrix<float> mapY, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n            => Remapped(mapX, mapX, interpolation);\n\n        /// <inheritdoc cref=\"RemappedPixImage\" />\n        public PixImage<T> Remapped(Matrix<float> mapX, Matrix<float> mapY, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n        {\n            return InvokeProcessors(\n                (p) => p.Remap(this, mapX, mapY, interpolation),\n                PixProcessorCaps.Remap, \"remap image\"\n            );\n        }\n\n        [Obsolete(\"Use the PixImage processor API instead.\")]\n        public static void SetRemappedFun(Func<Volume<T>, Matrix<float>, Matrix<float>, ImageInterpolation, Volume<T>> remappedFun)\n        {\n            LegacyPixProcessor.Instance.SetRemapFun<T>(\n                (remappedFun == null) ? null : (pi, xMap, yMap, ip) => new PixImage<T>(pi.Format, remappedFun(pi.Volume, xMap, yMap, ip))\n            );\n\n            if (LegacyPixProcessor.Instance.Capabilities != PixProcessorCaps.None)\n                SetProcessor(LegacyPixProcessor.Instance, 0);\n            else\n                RemoveProcessor(LegacyPixProcessor.Instance);\n        }\n\n        #endregion\n\n        #region Resized\n\n        /// <inheritdoc />\n        public override PixImage ResizedPixImage(V2i size, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n            => Scaled((V2d)size / (V2d)Size, interpolation);\n\n        /// <inheritdoc cref=\"ResizedPixImage\" />\n        public PixImage<T> Resized(V2i size, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n            => Scaled((V2d)size / (V2d)Size, interpolation);\n\n        /// <summary>\n        /// Returns a resized copy of this image.\n        /// </summary>\n        /// <param name=\"width\">Requested output width in pixels.</param>\n        /// <param name=\"height\">Requested output height in pixels.</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <returns>A new PixImage with the given size.</returns>\n        public PixImage<T> Resized(int width, int height, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n            => Scaled(new V2d(width, height) / (V2d)Size, interpolation);\n\n        #endregion\n\n        #region Rotated\n\n        /// <inheritdoc />\n        public override PixImage RotatedPixImage(double angleInRadians, bool resize = true, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n            => Rotated(angleInRadians, resize, interpolation);\n\n        /// <inheritdoc cref=\"RotatedPixImage\" />\n        public PixImage<T> Rotated(double angleInRadians, bool resize = true, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n        {\n            return InvokeProcessors(\n                (p) => p.Rotate(this, angleInRadians, resize, interpolation),\n                PixProcessorCaps.Rotate, \"rotate image\"\n            );\n        }\n\n        [Obsolete(\"Use the PixImage processor API instead.\")]\n        public static void SetRotatedFun(Func<Volume<T>, double, bool, ImageInterpolation, Volume<T>> rotatedFun)\n        {\n            LegacyPixProcessor.Instance.SetRotateFun<T>(\n                (rotatedFun == null) ? null : (pi, angle, resize, ip) => new PixImage<T>(pi.Format, rotatedFun(pi.Volume, angle, resize, ip))\n            );\n\n            if (LegacyPixProcessor.Instance.Capabilities != PixProcessorCaps.None)\n                SetProcessor(LegacyPixProcessor.Instance, 0);\n            else\n                RemoveProcessor(LegacyPixProcessor.Instance);\n        }\n\n        #endregion\n\n        #region Scaled\n\n        /// <inheritdoc />\n        public override PixImage ScaledPixImage(V2d scaleFactor, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n            => Scaled(scaleFactor, interpolation);\n\n        /// <inheritdoc cref=\"ScaledPixImage\" />\n        public PixImage<T> Scaled(V2d scaleFactor, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n        {\n            if (scaleFactor.AnySmallerOrEqual(0))\n                throw new ArgumentOutOfRangeException($\"Scale factor must be positive ({scaleFactor}).\");\n\n            // SuperSample is only available for scale factors < 1; fall back to Cubic\n            if (scaleFactor.AnyGreater(1.0) && interpolation == ImageInterpolation.SuperSample)\n                interpolation = ImageInterpolation.Cubic;\n\n            return InvokeProcessors(\n                (p) => p.Scale(this, scaleFactor, interpolation),\n                PixProcessorCaps.Scale, \"scale image\"\n            );\n        }\n\n        [Obsolete(\"Use the PixImage processor API instead.\")]\n        public static void SetScaledFun(Func<Volume<T>, V2d, ImageInterpolation, Volume<T>> scaledFun)\n        {\n            LegacyPixProcessor.Instance.SetScaleFun<T>(\n                (scaledFun == null) ? null : (pi, scaleFactor, ip) => new PixImage<T>(pi.Format, scaledFun(pi.Volume, scaleFactor, ip))\n            );\n\n            if (LegacyPixProcessor.Instance.Capabilities != PixProcessorCaps.None)\n                SetProcessor(LegacyPixProcessor.Instance, 0);\n            else\n                RemoveProcessor(LegacyPixProcessor.Instance);\n        }\n\n\n        /// <inheritdoc cref=\"ScaledPixImage\" />\n        public PixImage<T> Scaled(double scaleFactor, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n            => Scaled(new V2d(scaleFactor, scaleFactor), interpolation);\n\n        /// <summary>\n        /// Returns a scaled copy of this image by the given factors.\n        /// </summary>\n        /// <param name=\"scaleFactorX\">The scale factor to apply in X (1.0 keeps the width).</param>\n        /// <param name=\"scaleFactorY\">The scale factor to apply in Y (1.0 keeps the height).</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <returns>A new PixImage scaled by the given factors.</returns>\n        public PixImage<T> Scaled(double scaleFactorX, double scaleFactorY, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n            => Scaled(new V2d(scaleFactorX, scaleFactorY), interpolation);\n\n        #endregion\n\n        #endregion\n\n        #region SubImages\n\n        /// <summary>\n        /// Returns the specified region as new PixImage.\n        /// No data is copied, the internal <see cref=\"Volume{T}\"/> is only a view of the original one.\n        /// </summary>\n        /// <exception cref=\"ArgumentOutOfRangeException\">if the region is out of bounds.</exception>\n        public PixImage<T> SubImage(long x, long y, long width, long height)\n        {\n            if (x < 0 || y < 0 || x + width > Size.X || y + height > Size.Y)\n                throw new ArgumentOutOfRangeException(null, \"Subregion out of image boundary.\");\n            return new PixImage<T>(Format, Volume.SubVolume(x, y, 0, width, height, ChannelCount));\n        }\n\n        /// <inheritdoc cref=\"SubImage(long, long, long, long)\"/>\n        public PixImage<T> SubImage(V2i offset, V2i size) => SubImage(offset.X, offset.Y, size.X, size.Y);\n\n        /// <inheritdoc cref=\"SubImage(long, long, long, long)\"/>\n        public PixImage<T> SubImage(V2l offset, V2l size) => SubImage(offset.X, offset.Y, size.X, size.Y);\n\n        /// <inheritdoc cref=\"SubImage(long, long, long, long)\"/>\n        public PixImage<T> SubImage(Box2i box) => SubImage(box.Min, box.Size);\n\n        /// <summary>\n        /// Returns a square region around the center as new PixImage.\n        /// <paramref name=\"squareRadius\"/> is the given radius around the center.\n        /// No data is copied, the internal <see cref=\"Volume{T}\"/> is only a view of the original one.\n        /// </summary>\n        /// <exception cref=\"ArgumentOutOfRangeException\">if the region is out of bounds.</exception>\n        public PixImage<T> SubImage(V2i center, int squareRadius)\n            => SubImage(center - squareRadius, V2i.II * squareRadius * 2 + 1);\n\n        /// <summary>\n        /// Returns a specified region as a new PixImage.\n        /// The supplied offset and size are rounded to the nearest integer.\n        /// Note that this may be different from <see cref=\"SubImage(Box2d)\"/>, since\n        /// rounding the size and rounding the Max of the box may\n        /// result in different integer sizes.\n        /// No data is copied, the internal <see cref=\"Volume{T}\"/> is only a view onf the original one.\n        /// </summary>\n        /// <exception cref=\"ArgumentOutOfRangeException\">if the region is out of bounds.</exception>\n        public PixImage<T> SubImage(V2d offset, V2d size) => SubImage(new V2i(offset + 0.5), new V2i(size + 0.5));\n\n        /// <summary>\n        /// Returns a specified region as a new PixImage.\n        /// Min and Max of the supplied box are rounded to the nearest integer.\n        /// Note that this may be different from <see cref=\"SubImage(V2d, V2d)\"/>,\n        /// since rounding the Max of the box and rounding the size may\n        /// result in different integer sizes.\n        /// No data is copied, the internal <see cref=\"Volume{T}\"/> is only a view onf the original one.\n        /// </summary>\n        /// <exception cref=\"ArgumentOutOfRangeException\">if the region is out of bounds.</exception>\n        public PixImage<T> SubImage(Box2d box)\n        {\n            var min = new V2i(box.Min + 0.5);\n            return SubImage(min, new V2i(box.Max + 0.5) - min);\n        }\n\n        /// <summary>\n        /// Coords in normalized [0, 1] coords of 'this'.\n        /// The supplied pos and size are converted to pixel coordinates and\n        /// rounded to the nearest integer. Note that this may be different\n        /// from <see cref=\"SubImage01(Box2d)\"/> since rounding the size and rounding\n        /// the Max of the box may result in different integer sizes.\n        /// No data is copied, the internal <see cref=\"Volume{T}\"/> is only a view onf the original one.\n        /// </summary>\n        /// <exception cref=\"ArgumentOutOfRangeException\">if the region is out of bounds.</exception>\n        public PixImage<T> SubImage01(V2d offset, V2d size)\n        {\n            var iPos = (V2i)(offset * (V2d)Size + 0.5);\n            var iSize = (V2i)(size * (V2d)Size + 0.5);\n            return SubImage(iPos, iSize);\n        }\n\n        /// <summary>\n        /// Coords in normalized [0, 1] coords of 'this'.\n        /// Min and Max of the supplied box are converted to pixel coordinates\n        /// and rounded to the nearest integer. Note that this may be different\n        /// from <see cref=\"SubImage01(V2d, V2d)\"/>, since rounding the Max of the\n        /// box and rounding the size may result in different integer sizes.\n        /// No data is copied, the internal <see cref=\"Volume{T}\"/> is only a view onf the original one.\n        /// </summary>\n        /// <exception cref=\"ArgumentOutOfRangeException\">if the region is out of bounds.</exception>\n        public PixImage<T> SubImage01(Box2d bounds)\n        {\n            var iMin = (V2i)(bounds.Min * (V2d)Size + 0.5);\n            var iMax = (V2i)(bounds.Max * (V2d)Size + 0.5);\n            return SubImage(iMin, iMax - iMin);\n        }\n\n        #endregion\n\n        #region Setting\n\n        /// <summary>\n        /// Set a subregion of the image to the contents of another image.\n        /// The size of the subregion is determined by the other image.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\">if the format of <paramref name=\"image\"/> does not match the format of this instance.</exception>\n        /// <exception cref=\"ArgumentOutOfRangeException\">if the region is out of bounds.</exception>\n        public void Set(int x, int y, PixImage<T> image) => Set(new V2i(x, y), image);\n\n        /// <inheritdoc cref=\"Set(int, int, PixImage{T})\"/>\n        public void Set(V2i offset, PixImage<T> image) => SubImage(offset, image.Size).Set(image);\n\n        /// <summary>\n        /// Set the image contents of the image to the contents of another image.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\">if the format of <paramref name=\"image\"/> does not match the format of this instance.</exception>\n        /// <exception cref=\"ArgumentException\">if the size of <paramref name=\"image\"/> does not match the size of this instance.</exception>\n        public void Set(PixImage<T> image)\n        {\n            if (Format != image.Format) throw new ArgumentException($\"Format mismatch. Expected {Format} but got {image.Format}.\");\n            if (Size != image.Size) throw new ArgumentException($\"Size mismatch. Expected  {Size} but got {image.Size}.\");\n            Volume.Set(image.Volume);\n        }\n\n        /// <summary>\n        /// Set the image contents of the image to the contents of another image.\n        /// The contents of the other image are resized to match.\n        /// </summary>\n        /// <exception cref=\"ArgumentException\">if the format of <paramref name=\"image\"/> does not match the format of this instance.</exception>\n        public void SetResized(PixImage<T> image, ImageInterpolation interpolation = ImageInterpolation.Cubic)\n        {\n            if (Format != image.Format) throw new ArgumentException($\"Format mismatch. Expected {Format} but got {image.Format}.\");\n            Volume.Set(Size == image.Size ? image.Volume : image.Resized(Size, interpolation).Volume);\n        }\n\n        #endregion\n\n        #region Conversions\n\n        /// <inheritdoc cref=\"ToFormat\"/>\n        public override PixImage ToPixImage(Col.Format format) => ToFormat(format);\n\n        /// <summary>\n        /// Converts this image to the specified color format. If the current format already matches\n        /// and the channel counts are equal, the current instance is returned; otherwise a new instance\n        /// with converted channels is created.\n        /// </summary>\n        /// <param name=\"format\">Target color format.</param>\n        /// <returns>An image in the requested format.</returns>\n        public PixImage<T> ToFormat(Col.Format format)\n        {\n            if (Format == format && ChannelCount == format.ChannelCount()) return this;\n            return new PixImage<T>(format, this);\n        }\n\n        /// <inheritdoc cref=\"ToCanonicalDenseLayout\" />\n        public PixImage<T> ToImageLayout() => !Volume.HasImageLayout() ? new PixImage<T>(Format, this) : this;\n\n        /// <inheritdoc />\n        public override PixImage ToCanonicalDenseLayout() => ToImageLayout();\n\n        #endregion\n\n        #region Copy\n\n        /// <inheritdoc />\n        public override void CopyChannelTo<Tv>(long channelIndex, Matrix<Tv> target)\n        {\n            var subMatrix = GetChannel<Tv>(channelIndex);\n            target.Set(subMatrix);\n        }\n\n        /// <inheritdoc />\n        public override void CopyVolumeTo<Tv>(Volume<Tv> target)\n        {\n            if (Volume is Volume<Tv> source)\n                target.Set(source);\n            else\n                target.Set(Volume.AsVolume<T, Tv>());\n        }\n\n        /// <summary>\n        /// Creates a deep copy using canonical image layout regardless of the current layout.\n        /// If already in image layout, the data is copied; otherwise, data is transformed to image layout.\n        /// </summary>\n        public PixImage<T> CopyToImageLayout()\n        {\n            return Volume.HasImageLayout() ? new PixImage<T>(Format, Volume.CopyToImage()) : new PixImage<T>(this);\n        }\n\n        /// <inheritdoc cref=\"CopyToPixImage\" />\n        public PixImage<T> Copy() => new(Format, Volume.CopyToImageWindow());\n\n        /// <inheritdoc />\n        public override PixImage CopyToPixImage() => Copy();\n\n        /// <inheritdoc />\n        public override PixImage CopyToPixImageWithCanonicalDenseLayout() => CopyToImageLayout();\n\n        /// <summary>\n        /// Applies a per-pixel conversion function and returns a new image in the same color format.\n        /// </summary>\n        /// <typeparam name=\"Tv\">View type used for the conversion (e.g. a color type such as <see cref=\"C3f\"/> or <see cref=\"C4ui\"/>).</typeparam>\n        /// <param name=\"mapping\">Unary transformation applied to each pixel value.</param>\n        /// <exception cref=\"NotSupportedException\">if the view type is invalid for the format and element type.</exception>\n        public PixImage<T> Copy<Tv>(Func<Tv, Tv> mapping) => Copy(mapping, Format);\n\n        /// <summary>\n        /// Applies a per-pixel conversion function and returns a new image with the specified color format.\n        /// </summary>\n        /// <typeparam name=\"Tv\">View type used for the conversion (e.g. a color type such as <see cref=\"C3f\"/> or <see cref=\"C4ui\"/>).</typeparam>\n        /// <param name=\"mapping\">Unary transformation applied to each pixel value.</param>\n        /// <param name=\"format\">Target color format.</param>\n        /// <exception cref=\"NotSupportedException\">if the view type is invalid for the format and element type.</exception>\n        public PixImage<T> Copy<Tv>(Func<Tv, Tv> mapping, Col.Format format)\n        {\n            var mat = GetMatrix<Tv>().MapWindow(mapping);\n            var vol = new Volume<T>(mat.Data, Volume.Info);\n            return new PixImage<T>(format, vol);\n        }\n\n        #endregion\n\n        #region Obtaining Matrices\n\n        /// <summary>\n        /// Returns the specified channel using the canonical order (red, green, blue, alpha).\n        /// </summary>\n        /// <param name=\"channelIndex\">Index within the canonical order of channels.</param>\n        /// <returns>A matrix window over the selected channel.</returns>\n        public Matrix<T> GetChannel(long channelIndex)\n        {\n            var order = Format.ChannelOrder();\n            return GetChannelInFormatOrder(order[channelIndex]);\n        }\n\n        /// <summary>\n        /// Returns the specified channel by semantic name according to the current format.\n        /// </summary>\n        /// <param name=\"channel\">The channel to access (e.g. Red, Green, Blue, Alpha, Gray).</param>\n        /// <returns>A matrix window over the selected channel.</returns>\n        public Matrix<T> GetChannel(Col.Channel channel)\n            => GetChannelInFormatOrder(Format.ChannelIndex(channel));\n\n        /// <summary>\n        /// Returns the specified channel (using the canonical order) with a different view type.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element view type of the returned matrix.</typeparam>\n        /// <param name=\"channelIndex\">Index within the canonical order of channels.</param>\n        /// <returns>A typed matrix window over the selected channel.</returns>\n        /// <exception cref=\"NotSupportedException\">if the element type and view type are incompatible.</exception>\n        public Matrix<T, Tv> GetChannel<Tv>(long channelIndex)\n            => GetChannelInFormatOrder<Tv>(Format.ChannelOrder()[channelIndex]);\n\n        /// <summary>\n        /// Returns the specified channel based on the order of the color format.\n        /// </summary>\n        /// <param name=\"formatChannelIndex\">Index of the channel in the current format's order.</param>\n        /// <returns>A matrix window over the selected channel.</returns>\n        public Matrix<T> GetChannelInFormatOrder(long formatChannelIndex)\n            => Volume.SubXYMatrixWindow(formatChannelIndex);\n\n        /// <summary>\n        /// Returns the specified channel based on the order of the color format with a different view type.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element view type of the returned matrix.</typeparam>\n        /// <param name=\"formatChannelIndex\">Index of the channel in the current format's order.</param>\n        /// <returns>A typed matrix window over the selected channel.</returns>\n        /// <exception cref=\"NotSupportedException\">if the element type and view type are incompatible.</exception>\n        public Matrix<T, Tv> GetChannelInFormatOrder<Tv>(long formatChannelIndex)\n        {\n            var matrix = Volume.SubXYMatrix<Tv>(formatChannelIndex);\n            matrix.Accessors = TensorAccessors.Get<T, Tv>(TensorAccessors.Intent.ColorChannel, Volume.DeltaArray);\n            return matrix;\n        }\n\n        /// <summary>\n        /// Reinterprets the underlying 3D image volume as a matrix of the specified type.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element view type of the returned matrix (e.g. a color type such as <see cref=\"C3f\"/> or <see cref=\"C4ui\"/>).</typeparam>\n        /// <returns>A typed matrix window over the whole 3D image volume.</returns>\n        /// <exception cref=\"NotSupportedException\">if the view type is invalid for the format and element type.</exception>\n        public Matrix<T, Tv> GetMatrix<Tv>() => Volume.GetMatrix<T, Tv>(Format.GetIntent());\n\n        #endregion\n\n        #region IPixImageVisitor\n\n        /// <inheritdoc/>\n        public override TResult Visit<TResult>(IPixImageVisitor<TResult> visitor) => visitor.Visit(this);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/PixImageCreators.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public partial class PixImage\n    {\n        private static readonly V3d[] s_v0 =\n            { new(-1, -1, 1), new(-1,  1, 1), new(1,  1,  1),\n              new( 1, -1, 1), new(-1, -1, 1), new(-1, 1, -1) };\n\n        private static readonly V3d[] s_dx =\n            { new( 0, 2, 0), new(2, 0, 0), new(0, -2, 0),\n              new(-2, 0, 0), new(2, 0, 0), new(2,  0, 0) };\n\n        private static readonly V3d[] s_dy =\n            { new(0, 0, -2), new(0, 0, -2), new(0,  0, -2),\n              new(0, 0, -2), new(0, 2,  0), new(0, -2,  0) };\n\n        /// <summary>\n        /// Creates a single cube-map side image by evaluating a function on the unit cube directions.\n        /// The cube faces are arranged in a right-handed layout (XN YP XP YN ZP ZN) as illustrated below.\n        /// <code>\n        /// UV ->\n        /// |       | 4 |\n        /// v   | 0 | 1 | 2 | 3 |\n        ///         | 5 |\n        /// </code>\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel channel storage type (e.g. byte, float).</typeparam>\n        /// <typeparam name=\"Tcol\">The color vector type used to write into the matrix (e.g. C3b, C4f).</typeparam>\n        /// <param name=\"cubeSide\">Index of the cube side in the range [0..5]. See <see cref=\"CubeSide\"/>.</param>\n        /// <param name=\"size\">The width and height of the square side in pixels.</param>\n        /// <param name=\"channelCount\">Number of channels in the created image.</param>\n        /// <param name=\"vec_colFun\">Function that maps a normalized 3D direction vector to a color value.</param>\n        /// <returns>A newly created image containing the requested cube side.</returns>\n        public static PixImage<T> CreateCubeMapSide<T, Tcol>(\n                int cubeSide, int size, int channelCount, Func<V3d, Tcol> vec_colFun)\n        {\n            var image = new PixImage<T>(size, size, channelCount);\n            var mat = image.GetMatrix<Tcol>();\n            var d = 1.0 / size;\n            V3d dx = d * s_dx[cubeSide], dy = d * s_dy[cubeSide], v0 = s_v0[cubeSide] + 0.5 * dx + 0.5 * dy;\n            mat.SetByCoordParallelY((x, y) => { var v = v0 + x * dx + y * dy; return vec_colFun(v.Normalized); });\n            return image;\n        }\n\n        /// <summary>\n        /// Creates a single monochrome cube-map side image by evaluating a function on the unit cube directions.\n        /// The cube faces are arranged in a right-handed layout (XN YP XP YN ZP ZN) as illustrated below.\n        /// <code>\n        /// UV ->\n        /// |       | 4 |\n        /// v   | 0 | 1 | 2 | 3 |\n        ///         | 5 |\n        /// </code>\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel storage type (e.g. byte, float).</typeparam>\n        /// <param name=\"cubeSide\">Index of the cube side in the range [0..5]. See <see cref=\"CubeSide\"/>.</param>\n        /// <param name=\"size\">The width and height of the square side in pixels.</param>\n        /// <param name=\"vec_valueFun\">Function that maps a normalized 3D direction vector to a channel value.</param>\n        /// <returns>A newly created single-channel image containing the requested cube side.</returns>\n        public static PixImage<T> CreateCubeMapSide<T>(\n                int cubeSide, int size, Func<V3d, T> vec_valueFun)\n        {\n            var image = new PixImage<T>(size, size, 1);\n            var mat = image.Matrix;\n            var d = 1.0 / size;\n            V3d dx = d * s_dx[cubeSide], dy = d * s_dy[cubeSide], v0 = s_v0[cubeSide] + 0.5 * dx + 0.5 * dy;\n            mat.SetByCoordParallelY((x, y) => { var v = v0 + x * dx + y * dy; return vec_valueFun(v.Normalized); });\n            return image;\n        }\n\n        /// <summary>\n        /// Creates an image representing a cylindrical environment parameterized by (phi, theta).\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel channel storage type.</typeparam>\n        /// <typeparam name=\"Tcol\">The color vector type used to write into the matrix.</typeparam>\n        /// <param name=\"width\">Width of the generated image in pixels.</param>\n        /// <param name=\"height\">Height of the generated image in pixels.</param>\n        /// <param name=\"channelCount\">Number of channels in the created image.</param>\n        /// <param name=\"phi_theta_colFun\">Function mapping (phi, theta) to a color value, where phi is in [0, 2pi) and theta in [0, pi/2].</param>\n        /// <returns>The generated image.</returns>\n        public static PixImage<T> CreateCylinder<T, Tcol>(\n                int width, int height, int channelCount,\n                Func<double, double, Tcol> phi_theta_colFun)\n        {\n            var image = new PixImage<T>(width, height, channelCount);\n            var mat = image.GetMatrix<Tcol>();\n            double dx = Constant.PiTimesTwo / width, dy = 1.0 / height;\n            double x0 = 0.5 * dx, y0 = 1.0 - 0.5 * dy;\n\n            mat.SetByCoordParallelY((x, y) => phi_theta_colFun(x0 + x * dx, Fun.Acos(y0 - y * dy)));\n\n            return image;\n        }\n\n        /// <summary>\n        /// Creates an image representing a hemispherical dome parameterized by (phi, theta).\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel channel storage type.</typeparam>\n        /// <typeparam name=\"Tcol\">The color vector type used to write into the matrix.</typeparam>\n        /// <param name=\"width\">Width of the generated image in pixels.</param>\n        /// <param name=\"height\">Height of the generated image in pixels.</param>\n        /// <param name=\"channelCount\">Number of channels in the created image.</param>\n        /// <param name=\"phi_theta_colFun\">Function mapping (phi, theta) to a color value, where phi is in [0, 2pi) and theta in [0, pi/2].</param>\n        /// <returns>The generated image.</returns>\n        public static PixImage<T> CreateDome<T, Tcol>(\n                int width, int height, int channelCount,\n                Func<double, double, Tcol> phi_theta_colFun)\n        {\n            var image = new PixImage<T>(width, height, channelCount);\n            var mat = image.GetMatrix<Tcol>();\n            double dx = Constant.PiTimesTwo / width, dy = Constant.PiHalf / height;\n            double x0 = 0.5 * dx, y0 = 0.5 * dy;\n\n            mat.SetByCoordParallelY((x, y) => phi_theta_colFun(x0 + x * dx, y0 + y * dy));\n\n            return image;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/PixImageExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Concurrent;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Extension methods for common PixImage conversions and utilities.\n    /// </summary>\n    public static class PixImageExtensions\n    {\n        #region Black and White Conversions\n\n        /// <summary>\n        /// Converts a single-channel byte image to a black and white matrix using the specified threshold.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image (must have one channel).</param>\n        /// <param name=\"threshold\">Threshold in [0,255]; below yields 0, above or equal yields 255.</param>\n        /// <returns>A thresholded matrix with values 0 or 255.</returns>\n        public static Matrix<byte> ToBlackAndWhiteMatrix(this PixImage<byte> pixImage, int threshold)\n        {\n            if (pixImage.ChannelCount != 1) throw new ArgumentOutOfRangeException(nameof(pixImage.ChannelCount));\n            return pixImage.GetChannel(Col.Channel.Gray).MapWindow(b => (byte)(b < threshold ? 0 : 255));\n        }\n\n        /// <summary>\n        /// Converts a single-channel byte image to a black and white matrix using a default threshold of 128.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image (must have one channel).</param>\n        /// <returns>A thresholded matrix with values 0 or 255.</returns>\n        public static Matrix<byte> ToBlackAndWhiteMatrix(this PixImage<byte> pixImage)\n        {\n            return pixImage.ToBlackAndWhiteMatrix(128);\n        }\n\n        /// <summary>\n        /// Converts a single-channel byte image to a black and white PixImage using the specified threshold.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image (must have one channel).</param>\n        /// <param name=\"threshold\">Threshold in [0,255]; below yields 0, above or equal yields 255.</param>\n        /// <returns>A new black and white PixImage.</returns>\n        public static PixImage<byte> ToBlackAndWhitePixImage(this PixImage<byte> pixImage, int threshold)\n        {\n            return new PixImage<byte>(Col.Format.BW, pixImage.ToBlackAndWhiteMatrix(threshold));\n        }\n\n        /// <summary>\n        /// Converts a single-channel byte image to a black and white PixImage using a default threshold of 128.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image (must have one channel).</param>\n        /// <returns>A new black and white PixImage.</returns>\n        public static PixImage<byte> ToBlackAndWhitePixImage(this PixImage<byte> pixImage)\n        {\n            return new PixImage<byte>(Col.Format.BW, pixImage.ToBlackAndWhiteMatrix());\n        }\n\n        #endregion\n\n        #region Grayscale Conversions\n\n        /// <summary>\n        /// Converts a byte PixImage to a single-channel grayscale matrix.\n        /// If the image already has a single channel in BW or Gray format, the channel is returned as-is.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image.</param>\n        /// <returns>A grayscale matrix of bytes.</returns>\n        public static Matrix<byte> ToGrayscaleMatrix(this PixImage<byte> pixImage)\n        {\n            if (pixImage.ChannelCount == 1L && pixImage.Format is Col.Format.BW or Col.Format.Gray) return pixImage.Volume.AsMatrixWindow();\n            return pixImage.GetMatrix<C3b>().MapWindow(Col.ToGrayByte);\n        }\n\n        /// <summary>\n        /// Converts a byte PixImage to a single-channel grayscale PixImage.\n        /// If the image already has a single channel in Gray format, it is returned unmodified.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image.</param>\n        /// <returns>A grayscale PixImage of bytes.</returns>\n        public static PixImage<byte> ToGrayscalePixImage(this PixImage<byte> pixImage)\n        {\n            if (pixImage.ChannelCount == 1L && pixImage.Format == Col.Format.Gray) return pixImage;\n            return new PixImage<byte>(pixImage.ToGrayscaleMatrix());\n        }\n\n        /// <summary>\n        /// Converts an ushort PixImage to a single-channel grayscale matrix.\n        /// If the image already has a single channel in BW or Gray format, the channel is returned as-is.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image.</param>\n        /// <returns>A grayscale matrix of ushorts.</returns>\n        public static Matrix<ushort> ToGrayscaleMatrix(this PixImage<ushort> pixImage)\n        {\n            if (pixImage.ChannelCount == 1L && pixImage.Format is Col.Format.BW or Col.Format.Gray) return pixImage.Volume.AsMatrixWindow();\n            return pixImage.GetMatrix<C3us>().MapWindow(Col.ToGrayUShort);\n        }\n\n        /// <summary>\n        /// Converts an ushort PixImage to a single-channel grayscale PixImage.\n        /// If the image already has a single channel in Gray format, it is returned unmodified.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image.</param>\n        /// <returns>A grayscale PixImage of ushorts.</returns>\n        public static PixImage<ushort> ToGrayscalePixImage(this PixImage<ushort> pixImage)\n        {\n            if (pixImage.ChannelCount == 1L && pixImage.Format == Col.Format.Gray) return pixImage;\n            return new PixImage<ushort>(pixImage.ToGrayscaleMatrix());\n        }\n\n        /// <summary>\n        /// Converts a float PixImage to a single-channel grayscale matrix.\n        /// If the image already has a single channel in BW or Gray format, the channel is returned as-is.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image.</param>\n        /// <returns>A grayscale matrix of floats.</returns>\n        public static Matrix<float> ToGrayscaleMatrix(this PixImage<float> pixImage)\n        {\n            if (pixImage.ChannelCount == 1L && pixImage.Format is Col.Format.BW or Col.Format.Gray) return pixImage.Volume.AsMatrixWindow();\n            return pixImage.GetMatrix<C3f>().MapWindow(Col.ToGrayFloat);\n        }\n\n        /// <summary>\n        /// Converts a float PixImage to a single-channel grayscale PixImage.\n        /// If the image already has a single channel in Gray format, it is returned unmodified.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image.</param>\n        /// <returns>A grayscale PixImage of floats.</returns>\n        public static PixImage<float> ToGrayscalePixImage(this PixImage<float> pixImage)\n        {\n            if (pixImage.ChannelCount == 1L && pixImage.Format == Col.Format.Gray) return pixImage;\n            return new PixImage<float>(pixImage.ToGrayscaleMatrix());\n        }\n\n        /// <summary>\n        /// Converts a float PixImage to a single-channel grayscale matrix and clamps the result to [0,1].\n        /// If the image already has a single channel in BW or Gray format, the channel is returned as-is.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image.</param>\n        /// <returns>A grayscale matrix of floats in [0,1].</returns>\n        public static Matrix<float> ToClampedGrayscaleMatrix(this PixImage<float> pixImage)\n        {\n            if (pixImage.ChannelCount == 1L && pixImage.Format is Col.Format.BW or Col.Format.Gray) return pixImage.Volume.AsMatrixWindow();\n            return pixImage.GetMatrix<C3f>().MapWindow(Col.ToGrayFloatClamped);\n        }\n\n        /// <summary>\n        /// Converts a float PixImage to a single-channel grayscale PixImage with values clamped to [0,1].\n        /// If the image already has a single channel in Gray format, it is returned unmodified.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image.</param>\n        /// <returns>A grayscale PixImage of floats in [0,1].</returns>\n        public static PixImage<float> ToClampedGrayscalePixImage(this PixImage<float> pixImage)\n        {\n            if (pixImage.ChannelCount == 1L && pixImage.Format == Col.Format.Gray) return pixImage;\n            return new PixImage<float>(pixImage.ToClampedGrayscaleMatrix());\n        }\n\n        #endregion\n\n        #region Inversion\n\n        /// <summary>\n        /// Creates a new image with each pixel value inverted as <c>255 - value</c>.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image; it is not modified.</param>\n        /// <returns>A new PixImage containing the inverted pixel values.</returns>\n        public static PixImage<byte> Inverted(this PixImage<byte> pixImage)\n        {\n            return new PixImage<byte>(pixImage.Volume.MapToImageWindow(b => (byte)(255 - b)));\n        }\n\n        /// <summary>\n        /// Creates a new image with each pixel value inverted as <c>0xFFFF - value</c>.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image; it is not modified.</param>\n        /// <returns>A new PixImage containing the inverted pixel values.</returns>\n        public static PixImage<ushort> Inverted(this PixImage<ushort> pixImage)\n        {\n            return new PixImage<ushort>(pixImage.Volume.MapToImageWindow(us => (ushort)(65535 - us)));\n        }\n\n        /// <summary>\n        /// Creates a new image with each pixel value inverted as <c>0xFFFFFFFF - value</c>.\n        /// </summary>\n        /// <param name=\"pixImage\">The source image; it is not modified.</param>\n        /// <returns>A new PixImage containing the inverted pixel values.</returns>\n        public static PixImage<uint> Inverted(this PixImage<uint> pixImage)\n        {\n            return new PixImage<uint>(pixImage.Volume.MapToImageWindow(ui => 0xffffffffu - ui));\n        }\n\n        /// <summary>\n        /// Creates a new image with each pixel value inverted as <c>1 - value</c>.\n        /// </summary>\n        /// <remarks>\n        /// Values are assumed to be normalized to [0,1]; this method does not clamp out-of-range values.\n        /// </remarks>\n        /// <param name=\"pixImage\">The source image; it is not modified.</param>\n        /// <returns>A new PixImage containing the inverted pixel values.</returns>\n        public static PixImage<float> Inverted(this PixImage<float> pixImage)\n        {\n            return new PixImage<float>(pixImage.Volume.MapToImageWindow(f => 1.0f - f));\n        }\n\n        /// <summary>\n        /// Creates a new image with each pixel value inverted as <c>1 - value</c>.\n        /// </summary>\n        /// <remarks>\n        /// Values are assumed to be normalized to [0,1]; this method does not clamp out-of-range values.\n        /// </remarks>\n        /// <param name=\"pixImage\">The source image; it is not modified.</param>\n        /// <returns>A new PixImage containing the inverted pixel values.</returns>\n        public static PixImage<double> Inverted(this PixImage<double> pixImage)\n        {\n            return new PixImage<double>(pixImage.Volume.MapToImageWindow(d => 1.0 - d));\n        }\n\n        /// <summary>\n        /// Inverts pixel values in place as <c>255 - value</c>. No copy is created.\n        /// </summary>\n        /// <param name=\"pixImage\">The image to invert; the same instance is returned.</param>\n        /// <returns>The same instance after in-place inversion.</returns>\n        public static PixImage<byte> Invert(this PixImage<byte> pixImage)\n        {\n            pixImage.Volume.Apply(b => (byte)(255 - b));\n            return pixImage;\n        }\n\n        /// <summary>\n        /// Inverts pixel values in place as <c>0xFFFF - value</c>. No copy is created.\n        /// </summary>\n        /// <param name=\"pixImage\">The image to invert; the same instance is returned.</param>\n        /// <returns>The same instance after in-place inversion.</returns>\n        public static PixImage<ushort> Invert(this PixImage<ushort> pixImage)\n        {\n            pixImage.Volume.Apply(us => (ushort)(65535 - us));\n            return pixImage;\n        }\n\n        /// <summary>\n        /// Inverts pixel values in place as <c>0xFFFFFFFF - value</c>. No copy is created.\n        /// </summary>\n        /// <param name=\"pixImage\">The image to invert; the same instance is returned.</param>\n        /// <returns>The same instance after in-place inversion.</returns>\n        public static PixImage<uint> Invert(this PixImage<uint> pixImage)\n        {\n            pixImage.Volume.Apply(ui => 0xffffffffu - ui);\n            return pixImage;\n        }\n\n        /// <summary>\n        /// Inverts pixel values in place as <c>1 - value</c>. No copy is created.\n        /// </summary>\n        /// <remarks>\n        /// Values are assumed to be normalized to [0,1]; this method does not clamp out-of-range values.\n        /// </remarks>\n        /// <param name=\"pixImage\">The image to invert; the same instance is returned.</param>\n        /// <returns>The same instance after in-place inversion.</returns>\n        public static PixImage<float> Invert(this PixImage<float> pixImage)\n        {\n            pixImage.Volume.Apply(f => 1.0f - f);\n            return pixImage;\n        }\n\n        /// <summary>\n        /// Inverts pixel values in place as <c>1 - value</c>. No copy is created.\n        /// </summary>\n        /// <remarks>\n        /// Values are assumed to be normalized to [0,1]; this method does not clamp out-of-range values.\n        /// </remarks>\n        /// <param name=\"pixImage\">The image to invert; the same instance is returned.</param>\n        /// <returns>The same instance after in-place inversion.</returns>\n        public static PixImage<double> Invert(this PixImage<double> pixImage)\n        {\n            pixImage.Volume.Apply(d => 1.0 - d);\n            return pixImage;\n        }\n\n        #endregion\n\n        #region Stitching\n\n        #region  Dispatch\n\n        private static class Dispatch\n        {\n            private delegate PixImage StitchDelegate(PixImage[][] images, Col.Format format);\n            private delegate PixImage StitchSquareDelegate(PixImage[] images, Col.Format format);\n\n            private static class StitchDispatcher\n            {\n                public static PixImage Stitch<T>(PixImage[][] images, Col.Format format)\n                    => images.Map(ia => ia.Map(pi => pi?.ToPixImage<T>(format))).Stitch();\n\n                public static PixImage StitchSquare<T>(PixImage[] images, Col.Format format)\n                    => images.Map(pi => pi?.ToPixImage<T>(format)).StitchSquare();\n            }\n\n            private const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;\n\n            private static readonly MethodInfo s_stitchMethod = typeof(StitchDispatcher).GetMethod(nameof(StitchDispatcher.Stitch), flags);\n            private static readonly ConcurrentDictionary<Type, StitchDelegate> s_stitchDelegates = new();\n\n            private static readonly MethodInfo s_stitchSquareMethod = typeof(StitchDispatcher).GetMethod(nameof(StitchDispatcher.StitchSquare), flags);\n            private static readonly ConcurrentDictionary<Type, StitchSquareDelegate> s_stitchSquareDelegates = new();\n\n            public static PixImage Stitch(PixImage[][] images)\n            {\n                var first = images.SelectMany(ia => ia).WhereNotNull().First();\n\n                var stitch = s_stitchDelegates.GetOrAdd(first.PixFormat.Type, t => {\n                    var mi = s_stitchMethod.MakeGenericMethod(t);\n                    return (StitchDelegate)Delegate.CreateDelegate(typeof(StitchDelegate), mi);\n                });\n\n                return stitch(images, first.PixFormat.Format);\n            }\n\n            public static PixImage StitchSquare(PixImage[] images)\n            {\n                var first = images.WhereNotNull().First();\n\n                var stitch = s_stitchSquareDelegates.GetOrAdd(first.PixFormat.Type, t => {\n                    var mi = s_stitchSquareMethod.MakeGenericMethod(t);\n                    return (StitchSquareDelegate)Delegate.CreateDelegate(typeof(StitchSquareDelegate), mi);\n                });\n\n                return stitch(images, first.PixFormat.Format);\n            }\n        }\n\n        #endregion\n\n        /// <summary>\n        /// Stitches the images provided in the 2D jagged array into one large image according to their positions.\n        /// The outer array enumerates rows (Y), the inner arrays enumerate columns (X).\n        /// For example, the array<br/>\n        /// {{1, 2, 3}}<br/>\n        /// {{4, 5, 6}}<br/>\n        /// produces the image<br/>\n        /// 1 2 3<br/>\n        /// 4 5 6<br/>\n        /// Null entries are allowed and result in black gaps at the corresponding positions.\n        /// All images must share the same color format.\n        /// </summary>\n        /// <param name=\"images\">The 2D image array that should be stitched.</param>\n        /// <returns>The stitched image, or null if the input is null or empty.</returns>\n        public static PixImage<T> Stitch<T>(this PixImage<T>[][] images)\n        {\n            if (images.IsEmptyOrNull()) return null;\n\n            // Find largest extensions\n            var numRows = images.Length;\n            var numColumns = images.Max(img => img.Length);\n\n            // Find largest X Y\n            var sizesX = new int[numColumns].SetByIndex(c => images.Max(ic => (ic[c] == null) ? 0 : ic[c].Size.X));\n            var sizesY = images.Map(img => img.Max(img2 => (img2 == null) ? 0 : img2.Size.Y));\n            var width = sizesX.Sum();\n            var height = sizesY.Sum();\n\n            // The first image in the array, used to determine the color format\n            var fst = images.First(img => img.Length > 0).First(img => img != null);\n\n            // Assure that the color format fits\n            if (images.TrueForAny(imgs => imgs.Where(i => i != null).TrueForAny(img => img.Format != fst.Format)))\n            {\n                throw new ArgumentException(\"Mismatching color formats.\");\n            }\n\n            // Allocate new image\n            var target = new PixImage<T>(fst.Format, new V2i(width, height));\n\n            for (int r = 0, y = 0; r < numRows; r++)\n            {\n                for (int c = 0, x = 0; c < Fun.Max(numColumns, images[r].Length); c++)\n                {\n                    var source = images[r][c];\n                    if (source != null)\n                        target.Set(x, y, source);\n                    x += sizesX[c];\n                }\n                y += sizesY[r];\n            }\n            return target;\n        }\n\n        /// <summary>\n        /// Stitches the images provided in the 2D jagged array into one large image according to their positions.\n        /// The outer array enumerates rows (Y), the inner arrays enumerate columns (X).\n        /// For example, the array<br/>\n        /// {{1, 2, 3}}<br/>\n        /// {{4, 5, 6}}<br/>\n        /// produces the image<br/>\n        /// 1 2 3<br/>\n        /// 4 5 6<br/>\n        /// Null entries are allowed and result in black gaps at the corresponding positions.\n        /// All images must share the same color format. The pixel type will be inferred from the first non-null image.\n        /// </summary>\n        /// <param name=\"images\">The 2D image array that should be stitched.</param>\n        /// <returns>The stitched image.</returns>\n        public static PixImage Stitch(this PixImage[][] images)\n            => images.IsEmptyOrNull() ? null : Dispatch.Stitch(images);\n\n        /// <summary>\n        /// Stitches the provided images into a new image arranged in a near-square grid.\n        /// All images must share the same color format. If the last row is incomplete, missing cells are left black.\n        /// </summary>\n        /// <example>\n        /// {1, 2} -> {1, 2}<br/>\n        /// {1, 2, 3} -> {1, 2}, {3}<br/>\n        /// {1, 2, 3, 4, 5} -> {1, 2, 3}, {4, 5}<br/>\n        /// </example>\n        /// <param name=\"images\">The image array that should be stitched.</param>\n        /// <returns>The stitched image, or null if the input is empty or null.</returns>\n        public static PixImage<T> StitchSquare<T>(this PixImage<T>[] images)\n        {\n            if (images.IsEmptyOrNull()) return null;\n\n            var squareSize = (int)Fun.Ceiling(Fun.Sqrt(images.Length));\n            var array =\n                new PixImage<T>[squareSize][].SetByIndex(\n                    row => new PixImage<T>[squareSize].SetByIndex(\n                        col => { var ii = squareSize * row + col; return ii < images.Length ? images[ii] : null; }\n                    )\n                );\n            return array.Stitch();\n        }\n\n        /// <summary>\n        /// Stitches the provided images into a new image arranged in a near-square grid.\n        /// All images must share the same color format. If the last row is incomplete, missing cells are left black.\n        /// The pixel type will be inferred from the first non-null image.\n        /// </summary>\n        /// <example>\n        /// {1, 2} -> {1, 2}<br/>\n        /// {1, 2, 3} -> {1, 2}, {3}<br/>\n        /// {1, 2, 3, 4, 5} -> {1, 2, 3}, {4, 5}<br/>\n        /// </example>\n        /// <param name=\"images\">The image array that should be stitched.</param>\n        /// <returns>The stitched image, or null if the input is empty or null.</returns>\n        public static PixImage StitchSquare(this PixImage[] images)\n            => images.IsEmptyOrNull() ? null : Dispatch.StitchSquare(images);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/PixImageMipMap.cs",
    "content": "﻿using System;\nusing System.IO;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Represents a collection of downsampled images (mipmap levels) derived from a base image.\n    /// A mipmap typically contains the original image at level 0 and successively smaller images\n    /// at higher levels, which can be used for efficient rendering, filtering, and sampling.\n    /// </summary>\n    public class PixImageMipMap : IPix\n    {\n        /// <summary>\n        /// Array of images representing the mipmap levels.\n        /// </summary>\n        public PixImage[] ImageArray;\n\n        #region Constructors\n\n        /// <summary>\n        /// Creates an empty mipmap.\n        /// </summary>\n        public PixImageMipMap() => ImageArray = Array.Empty<PixImage>();\n\n        /// <summary>\n        /// Creates a mipmap from the given images.\n        /// </summary>\n        /// <param name=\"images\">An array of images representing the mipmap levels.</param>\n        public PixImageMipMap(params PixImage[] images) => ImageArray = images;\n\n        /// <summary>\n        /// Creates a mipmap consisting of a single image.\n        /// </summary>\n        /// <param name=\"image\">The single image of the mipmap.</param>\n        public PixImageMipMap(PixImage image) => ImageArray = new[] { image };\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Number of images in the mipmap array.\n        /// </summary>\n        public int LevelCount => ImageArray?.Length ?? 0;\n\n        /// <summary>\n        /// Returns whether the mipmap array is <c>null</c> or empty.\n        /// </summary>\n        public bool IsEmpty => LevelCount == 0;\n\n        /// <summary>\n        /// Returns the base image of the mipmap array or null if it is empty.\n        /// </summary>\n        public PixImage BaseImage => LevelCount > 0 ? ImageArray[0] : null;\n\n        /// <summary>\n        /// Returns the size of the base image, or V2i.Zero if the mipmap array is empty.\n        /// </summary>\n        public V2i BaseSize => BaseImage?.Size ?? V2i.Zero;\n\n        /// <summary>\n        /// Gets the pixel format of the base image.\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">if the mipmap is empty.</exception>\n        public PixFormat PixFormat => BaseImage?.PixFormat ?? throw new InvalidOperationException(\"Cannot determine format of empty PixImageMipMap.\");\n\n        /// <summary>\n        /// Gets or sets an image at the specified mipmap level.\n        /// </summary>\n        /// <param name=\"index\">Zero-based mipmap level index, where 0 is the base image.</param>\n        /// <returns>The image at the requested mipmap level.</returns>\n        /// <exception cref=\"IndexOutOfRangeException\">if <paramref name=\"index\"/> is outside the valid range [0, <see cref=\"LevelCount\"/>-1].</exception>\n        public PixImage this[int index]\n        {\n            get => ImageArray[index];\n            set => ImageArray[index] = value;\n        }\n\n        #region Obsolete\n\n        [Obsolete(\"Use LevelCount instead.\")]\n        public int ImageCount => LevelCount;\n\n        [Obsolete(\"Use ImageArray instead.\")]\n        public PixImage[] Images => ImageArray;\n\n        [Obsolete(\"Use BaseSize instead.\")]\n        public V2i BaseImageSize => BaseSize;\n\n        #endregion\n\n        #endregion\n\n        #region Load from file\n\n        private static PixImageMipMap LoadMipmapFromFileWithLoader(IPixLoader loader, string filename)\n        {\n            if (loader is IPixMipmapLoader mipLoader)\n            {\n                return mipLoader.LoadMipmapFromFile(filename);\n            }\n\n            var pi = loader.LoadFromFile(filename);\n            return (pi != null) ? new PixImageMipMap(pi) : null;\n        }\n\n        private static PixImageMipMap LoadFromFileWithLoader(IPixLoader loader, string filename)\n            => PixImage.InvokeLoader(\n                    loader, l => LoadMipmapFromFileWithLoader(l, filename), PixImage.NotNull,\n                    $\"load image mipmap from file '{filename}'\"\n            );\n\n        /// <summary>\n        /// Loads an image mipmap from the given file.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"filename\">The image file to load.</param>\n        /// <param name=\"loader\">The loader to use first, or null if no specific loader is to be used.</param>\n        /// <returns>The loaded image mipmap.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        public static PixImageMipMap Load(string filename, IPixLoader loader = null)\n            => PixImage.InvokeLoaders(\n                    PixImage.LoaderType.Decoder, loader, filename, LoadFromFileWithLoader, PixImage.Ignore, PixImage.NotNull,\n                    $\"Could not load image mipmap from file '{filename}'\"\n            );\n\n        #endregion\n\n        #region Load from stream\n\n        private static PixImageMipMap LoadMipmapFromStreamWithLoader(IPixLoader loader, Stream stream)\n        {\n            if (loader is IPixMipmapLoader mipLoader)\n            {\n                return mipLoader.LoadMipmapFromStream(stream);\n            }\n            else\n            {\n                var pi = loader.LoadFromStream(stream);\n                return (pi != null) ? new PixImageMipMap(pi) : null;\n            }\n        }\n\n        private static PixImageMipMap LoadFromStreamWithLoader(IPixLoader loader, Stream stream)\n            => PixImage.InvokeLoader(\n                    loader, l => LoadMipmapFromStreamWithLoader(l, stream), PixImage.NotNull,\n                    $\"load image mipmap from {PixImage.GetStreamDescription(stream)}\"\n            );\n\n        /// <summary>\n        /// Loads an image mipmap from the given stream.\n        /// </summary>\n        /// <remarks>\n        /// Install image loaders by referencing Aardvark.PixImage.* packages or by\n        /// manually calling <see cref=\"PixImage.AddLoader\"/> or <see cref=\"PixImage.SetLoader\"/>.\n        /// </remarks>\n        /// <param name=\"stream\">The image stream to load.</param>\n        /// <param name=\"loader\">The loader to use first, or null if no specific loader is to be used.</param>\n        /// <returns>The loaded image mipmap.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        /// <exception cref=\"NotSupportedException\">if the stream is not seekable and multiple loaders are invoked.</exception>\n        public static PixImageMipMap Load(Stream stream, IPixLoader loader = null)\n            => PixImage.InvokeLoadersWithStream(\n                PixImage.LoaderType.Decoder, loader, stream, LoadFromStreamWithLoader, PixImage.NotNull,\n                $\"Could not load image mipmap from {PixImage.GetStreamDescription(stream)}\"\n            );\n\n        #endregion\n\n        #region Generation\n\n        /// <summary>\n        /// Builds a full mipmap chain for the given image, optionally resizing to power-of-two dimensions\n        /// and/or limiting the number of levels.\n        /// </summary>\n        /// <param name=\"image\">The base image of the mipmap (level 0).</param>\n        /// <param name=\"interpolation\">The interpolation method used when downsampling between levels.</param>\n        /// <param name=\"maxCount\">Optional maximum number of mipmap levels to generate. If less than or equal to 0, all valid levels are generated.</param>\n        /// <param name=\"powerOfTwo\">If true and the base image size is not already a power of two, the image is resized to the next power-of-two size before building the chain.</param>\n        /// <returns>A new <see cref=\"PixImageMipMap\"/> where index 0 contains the (possibly resized) base image and higher indices contain successively downsampled images until the minimum size is reached or <paramref name=\"maxCount\"/> is satisfied.</returns>\n        public static PixImageMipMap Create(PixImage image, ImageInterpolation interpolation = ImageInterpolation.Linear, int maxCount = 0, bool powerOfTwo = false)\n        {\n            var baseSize = image.Size;\n            var baseImage = image;\n\n            if (powerOfTwo && (!Fun.IsPowerOfTwo(baseSize.X) || !Fun.IsPowerOfTwo(baseSize.Y)))\n            {\n                baseSize = Fun.NextPowerOfTwo(baseSize);\n                baseImage = image.ResizedPixImage(baseSize, interpolation);\n            }\n\n            var count = Fun.MipmapLevels(baseSize);\n            if (maxCount > 0 && count > maxCount) count = maxCount;\n\n            var images = new PixImage[count];\n            images[0] = baseImage;\n\n            for (var i = 1; i < count; i++)\n            {\n                var size = Fun.MipmapLevelSize(baseSize, i);\n                images[i] = images[i - 1].ResizedPixImage(size, interpolation);\n            }\n\n            return new PixImageMipMap(images);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/PixLoader.cs",
    "content": "﻿using System;\nusing System.IO;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Base class for save parameters.\n    /// Derived classes provide format-specific parameters and settings.\n    /// </summary>\n    public class PixSaveParams\n    {\n        /// <summary>\n        /// The format of the file to save.\n        /// </summary>\n        public PixFileFormat Format { get; }\n\n        public PixSaveParams(PixFileFormat format)\n        {\n            Format = format;\n        }\n    }\n\n    /// <summary>\n    /// Save parameters for JPEG images.\n    /// </summary>\n    public class PixJpegSaveParams : PixSaveParams\n    {\n        /// <summary>\n        /// Compression quality within 0 - 100.\n        /// </summary>\n        public int Quality { get; }\n\n        /// <summary>\n        /// Creates JPEG save parameters.\n        /// </summary>\n        /// <param name=\"quality\">Compression quality from 0 (lowest) to 100 (highest). Default is <see cref=\"DefaultQuality\"/>.</param>\n        /// <exception cref=\"ArgumentException\">Thrown if <paramref name=\"quality\"/> is outside the range 0–100.</exception>\n        public PixJpegSaveParams(int quality = DefaultQuality) : base(PixFileFormat.Jpeg)\n        {\n            if (quality is < 0 or > 100)\n                throw new ArgumentException($\"Quality must be within 0 - 100, is {quality}.\");\n            Quality = quality;\n        }\n\n        public const int DefaultQuality = 90;\n    }\n\n    /// <summary>\n    /// Save parameters for WebP images.\n    /// </summary>\n    public class PixWebpSaveParams : PixSaveParams\n    {\n        /// <summary>\n        /// Compression quality within 0 - 100.\n        /// For lossy compression, higher quality results in better results with a larger file size.\n        /// For lossless compression, higher quality results in a smaller file size but higher processing time.\n        /// </summary>\n        public int Quality { get; }\n\n        /// <summary>\n        /// Whether to use lossless or lossy compression. Default is lossy.\n        /// </summary>\n        public bool Lossless { get; }\n\n        /// <summary>\n        /// Creates WebP save parameters.\n        /// </summary>\n        /// <param name=\"quality\">Compression quality from 0 (lowest) to 100 (highest). Default is <see cref=\"DefaultQuality\"/>.</param>\n        /// <param name=\"lossless\">True to use lossless compression; false for lossy (default).</param>\n        /// <exception cref=\"ArgumentException\">Thrown if <paramref name=\"quality\"/> is outside the range 0–100.</exception>\n        public PixWebpSaveParams(int quality = DefaultQuality, bool lossless = false) : base(PixFileFormat.Webp)\n        {\n            if (quality is < 0 or > 100)\n                throw new ArgumentException($\"Quality must be within 0 - 100, is {quality}.\");\n            Quality = quality;\n            Lossless = lossless;\n        }\n\n        public const int DefaultQuality = 75;\n    }\n\n    /// <summary>\n    /// Save parameters for PNG images.\n    /// </summary>\n    public class PixPngSaveParams : PixSaveParams\n    {\n        /// <summary>\n        /// Compression level within 0 - 9.\n        /// </summary>\n        public int CompressionLevel { get; }\n\n        /// <summary>\n        /// Creates PNG save parameters.\n        /// </summary>\n        /// <param name=\"compressionLevel\">Compression level from 0 (no compression) to 9 (maximum compression). Default is <see cref=\"DefaultCompressionLevel\"/>.</param>\n        /// <exception cref=\"ArgumentException\">Thrown if <paramref name=\"compressionLevel\"/> is outside the range 0–9.</exception>\n        public PixPngSaveParams(int compressionLevel = DefaultCompressionLevel) : base(PixFileFormat.Png)\n        {\n            if (compressionLevel is < 0 or > 9)\n                throw new ArgumentException($\"Compression level must be within 0 - 9, is {compressionLevel}.\");\n            CompressionLevel = compressionLevel;\n        }\n\n        public const int DefaultCompressionLevel = 6;\n    }\n\n    /// <summary>\n    /// Supported compression schemes for TIFF files.\n    /// </summary>\n    public enum PixTiffCompression\n    {\n        /// <summary>\n        /// Compression scheme is chosen by the image library.\n        /// </summary>\n        Default = 0,\n\n        /// <summary>\n        /// Do not compress the image data.\n        /// </summary>\n        None = 1,\n\n        /// <summary>\n        /// CCITT Group 3 fax encoding.\n        /// </summary>\n        Ccitt3 = 2,\n\n        /// <summary>\n        /// CCITT Group 4 fax encoding.\n        /// </summary>\n        Ccitt4 = 3,\n\n        /// <summary>\n        /// LZW compression.\n        /// </summary>\n        Lzw = 4,\n\n        /// <summary>\n        /// JPEG compression.\n        /// </summary>\n        Jpeg = 5,\n\n        /// <summary>\n        /// Deflate compression, also known as ZLIB compression.\n        /// </summary>\n        Deflate = 6,\n\n        /// <summary>\n        /// PackBits compression.\n        /// </summary>\n        PackBits = 7,\n    }\n\n    /// <summary>\n    /// Save parameters for TIFF images.\n    /// </summary>\n    public class PixTiffSaveParams : PixSaveParams\n    {\n        /// <summary>\n        /// Used compression scheme.\n        /// </summary>\n        public PixTiffCompression Compression { get; }\n\n        /// <summary>\n        /// Creates TIFF save parameters.\n        /// </summary>\n        /// <param name=\"compression\">The compression scheme to use. Default is <see cref=\"PixTiffCompression.Default\"/>.</param>\n        public PixTiffSaveParams(PixTiffCompression compression = PixTiffCompression.Default) : base(PixFileFormat.Tiff)\n        {\n            Compression = compression;\n        }\n    }\n\n    /// <summary>\n    /// Supported compression schemes for OpenEXR (EXR) files.\n    /// </summary>\n    public enum PixExrCompression\n    {\n        /// <summary>\n        /// Compression scheme is chosen by the image library.\n        /// </summary>\n        Default = 0,\n\n        /// <summary>\n        /// Do not compress the image data.\n        /// </summary>\n        None = 1,\n\n        /// <summary>\n        /// ZLIB compression, in blocks of 16 scan lines.\n        /// </summary>\n        Zip = 2,\n\n        /// <summary>\n        /// PIZ-based wavelet compression.\n        /// </summary>\n        Piz = 3,\n\n        /// <summary>\n        /// 24-bit float compression (lossy).\n        /// </summary>\n        Pxr24 = 4,\n\n        /// <summary>\n        /// 44% float compression (lossy).\n        /// </summary>\n        B44 = 5,\n    }\n\n    /// <summary>\n    /// Save parameters for OpenEXR (EXR) images.\n    /// </summary>\n    public class PixExrSaveParams : PixSaveParams\n    {\n        /// <summary>\n        /// Used compression scheme.\n        /// </summary>\n        public PixExrCompression Compression { get; }\n\n        /// <summary>\n        /// Encode with one luminance and two chroma channels (lossy compression).\n        /// </summary>\n        public bool LuminanceChroma { get; }\n\n        /// <summary>\n        /// Creates OpenEXR (EXR) save parameters.\n        /// </summary>\n        /// <param name=\"compression\">The compression scheme to use. Default is <see cref=\"PixExrCompression.Default\"/>.</param>\n        /// <param name=\"luminanceChroma\">If true, encodes as one luminance and two chroma channels (lossy).</param>\n        public PixExrSaveParams(PixExrCompression compression = PixExrCompression.Default, bool luminanceChroma = false) : base(PixFileFormat.Exr)\n        {\n            Compression = compression;\n            LuminanceChroma = luminanceChroma;\n        }\n    }\n\n    /// <summary>\n    /// Interface for PixImage loaders.\n    /// </summary>\n    public interface IPixLoader\n    {\n        /// <summary>\n        /// The name of the loader.\n        /// </summary>\n        string Name { get; }\n\n        /// <summary>\n        /// Returns whether the loader supports encoding images (i.e. saving to files and streams).\n        /// </summary>\n        bool CanEncode { get; }\n\n        /// <summary>\n        /// Returns whether the loader supports decoding images (i.e. loading from files and streams).\n        /// </summary>\n        bool CanDecode { get; }\n\n        /// <summary>\n        /// Loads a PixImage from a file.\n        /// </summary>\n        /// <param name=\"filename\">The file to load.</param>\n        /// <returns>The loaded PixImage.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        PixImage LoadFromFile(string filename);\n\n        /// <summary>\n        /// Loads a PixImage from a stream.\n        /// </summary>\n        /// <param name=\"stream\">The stream to load.</param>\n        /// <returns>The loaded PixImage.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        PixImage LoadFromStream(Stream stream);\n\n        /// <summary>\n        /// Saves a PixImage to a file.\n        /// </summary>\n        /// <param name=\"filename\">The file to save to.</param>\n        /// <param name=\"image\">The image to save.</param>\n        /// <param name=\"saveParams\">Format-specific parameters and settings.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        void SaveToFile(string filename, PixImage image, PixSaveParams saveParams);\n\n        /// <summary>\n        /// Saves a PixImage to a stream.\n        /// </summary>\n        /// <param name=\"stream\">The stream to save to.</param>\n        /// <param name=\"image\">The image to save.</param>\n        /// <param name=\"saveParams\">Format-specific parameters and settings.</param>\n        /// <exception cref=\"ImageLoadException\">if the image could not be saved.</exception>\n        void SaveToStream(Stream stream, PixImage image, PixSaveParams saveParams);\n\n        /// <summary>\n        /// Loads basic information about an image from a file without loading its content.\n        /// </summary>\n        /// <param name=\"filename\">The file to load.</param>\n        /// <returns>A PixImageInfo instance containing basic information about the image.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        PixImageInfo GetInfoFromFile(string filename);\n\n        /// <summary>\n        /// Loads basic information about an image from a stream without loading its content.\n        /// </summary>\n        /// <param name=\"stream\">The stream to load.</param>\n        /// <returns>A PixImageInfo instance containing basic information about the image.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        PixImageInfo GetInfoFromStream(Stream stream);\n    }\n\n    /// <summary>\n    /// Interface for PixImage loaders supporting loading mipmap chains.\n    /// </summary>\n    public interface IPixMipmapLoader : IPixLoader\n    {\n        /// <summary>\n        /// Loads a PixImageMipMap from a file.\n        /// </summary>\n        /// <param name=\"filename\">The file to load.</param>\n        /// <returns>The loaded PixImageMipMap.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        PixImageMipMap LoadMipmapFromFile(string filename);\n\n        /// <summary>\n        /// Loads a PixImageMipMap from a stream.\n        /// </summary>\n        /// <param name=\"stream\">The stream to load.</param>\n        /// <returns>The loaded PixImageMipMap.</returns>\n        /// <exception cref=\"ImageLoadException\">if the image could not be loaded.</exception>\n        PixImageMipMap LoadMipmapFromStream(Stream stream);\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/PixProcessor.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Describes the feature set supported by an <see cref=\"IPixProcessor\"/> implementation.\n    /// </summary>\n    [Flags]\n    public enum PixProcessorCaps\n    {\n        /// <summary>\n        /// No capabilities are supported.\n        /// </summary>\n        None = 0,\n\n        /// <summary>\n        /// Supports scaling operations.\n        /// </summary>\n        Scale = 1,\n\n        /// <summary>\n        /// Supports rotation operations.\n        /// </summary>\n        Rotate = 2,\n\n        /// <summary>\n        /// Supports generic geometric remapping operations.\n        /// </summary>\n        Remap = 4,\n\n        /// <summary>\n        /// Convenience value for enabling all capabilities (<see cref=\"Scale\"/>, <see cref=\"Rotate\"/>, <see cref=\"Remap\"/>).\n        /// </summary>\n        All = Scale | Rotate | Remap,\n    }\n\n    /// <summary>\n    /// Defines a pluggable image processor that can perform common operations\n    /// such as scaling, rotating, and remapping pixel images.\n    /// </summary>\n    /// <remarks>\n    /// Implementations may not support all operations for all pixel formats. In such cases, methods\n    /// are expected to return <c>null</c> to indicate that the specific operation is not available.\n    /// Check <see cref=\"Capabilities\"/> before invoking an operation to avoid unnecessary work.\n    /// </remarks>\n    /// <seealso cref=\"PixProcessor\"/>\n    /// <seealso cref=\"LegacyPixProcessor\"/>\n    public interface IPixProcessor\n    {\n        /// <summary>\n        /// Gets the human-readable name of the processor implementation.\n        /// </summary>\n        string Name { get; }\n\n        /// <summary>\n        /// Gets the set of capabilities supported by this processor.\n        /// </summary>\n        PixProcessorCaps Capabilities { get; }\n\n        /// <summary>\n        /// Scales the given image by the provided factors.\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel component type of the image.</typeparam>\n        /// <param name=\"image\">The image to scale. Must not be <c>null</c>.</param>\n        /// <param name=\"scaleFactor\">The scale factor to apply in X and Y (1.0 keeps the size).</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <returns>\n        /// A new <see cref=\"PixImage{T}\"/> containing the scaled image, or <c>null</c> if scaling is not supported.\n        /// </returns>\n        PixImage<T> Scale<T>(PixImage<T> image, V2d scaleFactor, ImageInterpolation interpolation);\n\n        /// <summary>\n        /// Rotates an image counter-clockwise by the given angle in radians.\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel component type of the image.</typeparam>\n        /// <param name=\"image\">The image to rotate. Must not be <c>null</c>.</param>\n        /// <param name=\"angleInRadians\">The rotation angle in radians (counter-clockwise).</param>\n        /// <param name=\"resize\">When <c>true</c>, the output image is resized to fully contain the rotated content; otherwise it keeps the original size.</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <param name=\"borderType\">How to evaluate pixels that sample outside the source image.</param>\n        /// <param name=\"border\">Border value used when <paramref name=\"borderType\"/> is <see cref=\"ImageBorderType.Const\"/>.</param>\n        /// <returns>\n        /// A new <see cref=\"PixImage{T}\"/> containing the rotated image, or <c>null</c> if rotation is not supported.\n        /// </returns>\n        PixImage<T> Rotate<T>(PixImage<T> image, double angleInRadians, bool resize, ImageInterpolation interpolation,\n                              ImageBorderType borderType = ImageBorderType.Const,\n                              T border = default);\n\n        /// <summary>\n        /// Applies a generic geometric transformation to the given image by remapping destination\n        /// pixel coordinates to source coordinates.\n        /// </summary>\n        /// <remarks>\n        /// The resulting image is computed as f(x, y) = <paramref name=\"image\"/>[<paramref name=\"mapX\"/>(x, y), <paramref name=\"mapY\"/>(x, y)].\n        /// </remarks>\n        /// <typeparam name=\"T\">The pixel component type of the image.</typeparam>\n        /// <param name=\"image\">The image to transform. Must not be <c>null</c>.</param>\n        /// <param name=\"mapX\">Matrix of X-coordinate samples mapping destination pixels to source X.</param>\n        /// <param name=\"mapY\">Matrix of Y-coordinate samples mapping destination pixels to source Y.</param>\n        /// <param name=\"interpolation\">The interpolation method to use during resampling.</param>\n        /// <param name=\"borderType\">How to evaluate pixels that sample outside the source image.</param>\n        /// <param name=\"border\">Border value used when <paramref name=\"borderType\"/> is <see cref=\"ImageBorderType.Const\"/>.</param>\n        /// <returns>\n        /// A new <see cref=\"PixImage{T}\"/> containing the remapped image, or <c>null</c> if remapping is not supported.\n        /// </returns>\n        PixImage<T> Remap<T>(PixImage<T> image, Matrix<float> mapX, Matrix<float> mapY, ImageInterpolation interpolation,\n                             ImageBorderType borderType = ImageBorderType.Const,\n                             T border = default);\n    }\n\n    /// <summary>\n    /// Basic image processor using built-in Aardvark algorithms.\n    /// </summary>\n    /// <remarks>\n    /// Currently only scaling is implemented; rotation and remapping return <c>null</c>.\n    /// </remarks>\n    /// <seealso cref=\"IPixProcessor\"/>\n    public sealed class PixProcessor : IPixProcessor\n    {\n        /// <inheritdoc/>\n        public string Name => \"Aardvark\";\n\n        /// <inheritdoc/>\n        public PixProcessorCaps Capabilities => PixProcessorCaps.Scale;\n\n        /// <inheritdoc/>\n        public PixImage<T> Scale<T>(PixImage<T> image, V2d scaleFactor, ImageInterpolation interpolation)\n            => new(image.Format, TensorExtensions.Scaled(image.Volume, scaleFactor, interpolation));\n\n        /// <inheritdoc/>\n        public PixImage<T> Rotate<T>(PixImage<T> image, double angleInRadians, bool resize, ImageInterpolation interpolation,\n                                     ImageBorderType borderType = ImageBorderType.Const,\n                                     T border = default)\n            => null;\n\n        /// <inheritdoc/>\n        public PixImage<T> Remap<T>(PixImage<T> image, Matrix<float> mapX, Matrix<float> mapY, ImageInterpolation interpolation,\n                                    ImageBorderType borderType = ImageBorderType.Const,\n                                    T border = default)\n            => null;\n\n        private PixProcessor() { }\n\n        private static readonly Lazy<PixProcessor> _instance = new(() => new PixProcessor());\n\n        /// <summary>\n        /// Gets the singleton instance of the default <see cref=\"PixProcessor\"/>.\n        /// </summary>\n        public static PixProcessor Instance { get; } = _instance.Value;\n    }\n\n    /// <summary>\n    /// Image processor that maintains compatibility with a legacy API by allowing\n    /// clients to register per-type delegate implementations for the various operations.\n    /// </summary>\n    /// <remarks>\n    /// If no delegate is registered for a given pixel type and operation, the corresponding method\n    /// returns <c>null</c> to signal that the operation is unsupported.\n    /// </remarks>\n    /// <seealso cref=\"IPixProcessor\"/>\n    public sealed class LegacyPixProcessor : IPixProcessor\n    {\n        private readonly Dictionary<Type, Func<PixImage, V2d, ImageInterpolation, PixImage>> scaleFuns = new();\n        private readonly Dictionary<Type, Func<PixImage, double, bool, ImageInterpolation, PixImage>> rotateFuns = new();\n        private readonly Dictionary<Type, Func<PixImage, Matrix<float>, Matrix<float>, ImageInterpolation, PixImage>> remapFuns = new();\n\n        /// <inheritdoc/>\n        public string Name => \"Aardvark (Legacy)\";\n\n        /// <summary>\n        /// Gets the computed set of capabilities based on the registered delegates.\n        /// </summary>\n        public PixProcessorCaps Capabilities\n        {\n            get\n            {\n                var result = PixProcessorCaps.None;\n                if (scaleFuns.Count > 0) result |= PixProcessorCaps.Scale;\n                if (rotateFuns.Count > 0) result |= PixProcessorCaps.Rotate;\n                if (remapFuns.Count > 0) result |= PixProcessorCaps.Remap;\n                return result;\n            }\n        }\n\n        /// <summary>\n        /// Registers or unregisters the scaling function for pixel type <typeparamref name=\"T\"/>.\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel component type.</typeparam>\n        /// <param name=\"scaleFun\">The scaling function to register; pass <c>null</c> to unregister.</param>\n        public void SetScaleFun<T>(Func<PixImage<T>, V2d, ImageInterpolation, PixImage<T>> scaleFun)\n        {\n            if (scaleFun != null)\n                scaleFuns[typeof(T)] = (p, s, i) => scaleFun((PixImage<T>)p, s, i);\n            else\n                scaleFuns.Remove(typeof(T));\n        }\n\n        /// <inheritdoc/>\n        public PixImage<T> Scale<T>(PixImage<T> image, V2d scaleFactor, ImageInterpolation interpolation)\n        {\n            if (scaleFuns.TryGetValue(typeof(T), out var fun))\n                return (PixImage<T>)fun(image, scaleFactor, interpolation);\n            else\n                return null;\n        }\n\n        /// <summary>\n        /// Registers or unregisters the rotation function for pixel type <typeparamref name=\"T\"/>.\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel component type.</typeparam>\n        /// <param name=\"rotateFun\">The rotation function to register; pass <c>null</c> to unregister.</param>\n        public void SetRotateFun<T>(Func<PixImage<T>, double, bool, ImageInterpolation, PixImage<T>> rotateFun)\n        {\n            if (rotateFun != null)\n                rotateFuns[typeof(T)] = (p, a, r, i) => rotateFun((PixImage<T>)p, a, r, i);\n            else\n                rotateFuns.Remove(typeof(T));\n        }\n\n        /// <inheritdoc/>\n        public PixImage<T> Rotate<T>(PixImage<T> image, double angleInRadians, bool resize, ImageInterpolation interpolation,\n                                     ImageBorderType borderType = ImageBorderType.Const,\n                                     T border = default)\n        {\n            if (rotateFuns.TryGetValue(typeof(T), out var fun))\n                return (PixImage<T>)fun(image, angleInRadians, resize, interpolation);\n            else\n                return null;\n        }\n\n        /// <summary>\n        /// Registers or unregisters the remapping function for pixel type <typeparamref name=\"T\"/>.\n        /// </summary>\n        /// <typeparam name=\"T\">The pixel component type.</typeparam>\n        /// <param name=\"remapFun\">The remapping function to register; pass <c>null</c> to unregister.</param>\n        public void SetRemapFun<T>(Func<PixImage<T>, Matrix<float>, Matrix<float>, ImageInterpolation, PixImage<T>> remapFun)\n        {\n            if (remapFun != null)\n                remapFuns[typeof(T)] = (p, x, y, i) => remapFun((PixImage<T>)p, x, y, i);\n            else\n                remapFuns.Remove(typeof(T));\n        }\n\n        /// <inheritdoc/>\n        public PixImage<T> Remap<T>(PixImage<T> image, Matrix<float> mapX, Matrix<float> mapY, ImageInterpolation interpolation,\n                                    ImageBorderType borderType = ImageBorderType.Const,\n                                    T border = default)\n        {\n            if (remapFuns.TryGetValue(typeof(T), out var fun))\n                return (PixImage<T>)fun(image, mapX, mapY, interpolation);\n            else\n                return null;\n        }\n\n        private LegacyPixProcessor() { }\n\n        private static readonly Lazy<LegacyPixProcessor> _instance = new(() => new LegacyPixProcessor());\n\n        /// <summary>\n        /// Gets the singleton instance of the <see cref=\"LegacyPixProcessor\"/>.\n        /// </summary>\n        public static LegacyPixProcessor Instance { get; } = _instance.Value;\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/PixImage/PixVolume.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Defines a visitor for strongly typed PixVolume instances.\n    /// Use this to dispatch operations based on the underlying pixel data type without reflection.\n    /// </summary>\n    /// <typeparam name=\"TResult\">The result type produced by the visitor.</typeparam>\n    public interface IPixVolumeVisitor<TResult>\n    {\n        /// <summary>\n        /// Visits the given PixVolume with element type <typeparamref name=\"TData\"/>.\n        /// </summary>\n        /// <typeparam name=\"TData\">The pixel element type (e.g. byte, float, etc.).</typeparam>\n        /// <param name=\"volume\">The typed PixVolume instance to visit.</param>\n        /// <returns>The visitor-specific result.</returns>\n        TResult Visit<TData>(PixVolume<TData> volume);\n    }\n\n    /// <summary>\n    /// Lightweight description of a <see cref=\"PixVolume\"/>, containing its pixel format and dimensions.\n    /// </summary>\n    /// <param name=\"Format\">The pixel format (channel type and color format).</param>\n    /// <param name=\"Size\">The 3D size in pixels (X = width, Y = height, Z = depth).</param>\n    public record PixVolumeInfo(PixFormat Format, V3i Size);\n\n    /// <summary>\n    /// Base (non-generic) 3D pixel container abstraction. Provides format, size and conversion utilities\n    /// for image volumes independent of the underlying element type.\n    /// </summary>\n    public abstract class PixVolume : IPix\n    {\n        /// <summary>\n        /// Color format describing channel layout and semantics.\n        /// </summary>\n        public Col.Format Format;\n\n        #region Constructors\n\n        public PixVolume() : this(Col.Format.None) { }\n\n        public PixVolume(Col.Format format)\n        {\n            Format = format;\n        }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the underlying storage as a System.Array of the element type.\n        /// </summary>\n        public abstract Array Array { get; }\n\n        /// <summary>\n        /// Gets the pixel format of the volume (channel type and color format).\n        /// </summary>\n        public abstract PixFormat PixFormat { get; }\n\n        /// <summary>\n        /// Gets structural information about the underlying 4D tensor including size and layout.\n        /// </summary>\n        public abstract Tensor4Info Tensor4Info { get; }\n\n        /// <summary>\n        /// Gets the size in bytes of a single channel element (e.g. 1 for byte, 4 for float).\n        /// </summary>\n        public abstract int BytesPerChannel { get; }\n\n        /// <summary>\n        /// Gets a lightweight summary of this volume's format and size.\n        /// </summary>\n        public PixVolumeInfo Info => new(PixFormat, Size);\n\n        /// <summary>\n        /// Gets the 3D size of the volume in pixels.\n        /// </summary>\n        public V3i Size => (V3i)Tensor4Info.Size.XYZ;\n\n        /// <summary>\n        /// Gets the 3D size of the volume in pixels as 64-bit integers.\n        /// </summary>\n        public V3l SizeL => Tensor4Info.Size.XYZ;\n\n        /// <summary>\n        /// Gets the width of the volume in pixels.\n        /// </summary>\n        public int Width => Size.X;\n\n        /// <summary>\n        /// Gets the width of the volume in pixels as a 64-bit integer.\n        /// </summary>\n        public long WidthL => SizeL.X;\n\n        /// <summary>\n        /// Gets the height of the volume in pixels.\n        /// </summary>\n        public int Height => Size.Y;\n\n        /// <summary>\n        /// Gets the height of the volume in pixels as a 64-bit integer.\n        /// </summary>\n        public long HeightL => SizeL.Y;\n\n        /// <summary>\n        /// Gets the depth of the volume in pixels.\n        /// </summary>\n        public int Depth => Size.Z;\n\n        /// <summary>\n        /// Gets the depth of the volume in pixels as a 64-bit integer.\n        /// </summary>\n        public long DepthL => SizeL.Z;\n\n        /// <summary>\n        /// Gets the number of channels per voxel.\n        /// </summary>\n        public int ChannelCount => (int)Tensor4Info.Size.W;\n\n        /// <summary>\n        /// Gets the number of channels per voxel as a 64-bit integer.\n        /// </summary>\n        public long ChannelCountL => Tensor4Info.Size.W;\n\n        #endregion\n\n        #region Static Creator Functions\n\n        /// <summary>\n        /// Creates a 4D tensor with image-friendly memory layout for the given size.\n        /// </summary>\n        /// <typeparam name=\"T\">Element type of the tensor.</typeparam>\n        /// <param name=\"size\">The tensor size as (width, height, depth, channels).</param>\n        /// <returns>A new tensor with the requested size.</returns>\n        public static Tensor4<T> CreateTensor4<T>(V4l size)\n        {\n            return size.CreateImageTensor4<T>();\n        }\n\n        /// <summary>\n        /// Creates a 4D tensor with image-friendly memory layout for the given dimensions.\n        /// </summary>\n        /// <typeparam name=\"T\">Element type of the tensor.</typeparam>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"depth\">Depth in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        /// <returns>A new tensor with the requested size.</returns>\n        public static Tensor4<T> CreateTensor4<T>(long width, long height, long depth, long channels)\n        {\n            return new V4l(width, height, depth, channels).CreateImageTensor4<T>();\n        }\n\n        #endregion\n\n        #region Conversions\n\n        private static void ToGray<T, Tv, R>(PixVolume src, object dst, Func<Tv, R> toGray)\n        {\n            ((Volume<R>)dst).SetMap(src.AsPixVolume<T>().GetVolume<Tv>(), toGray);\n        }\n\n        protected static readonly Dictionary<(Type, Type), Action<PixVolume, object>> s_rgbToGrayMap = new()\n            {\n                { (typeof(byte), typeof(byte)),     (src, dst) => ToGray<byte, C3b, byte>(src, dst, Col.ToGrayByte) },\n                { (typeof(ushort), typeof(ushort)), (src, dst) => ToGray<ushort, C3us, ushort>(src, dst, Col.ToGrayUShort) },\n                { (typeof(uint), typeof(uint)),     (src, dst) => ToGray<uint, C3ui, uint>(src, dst, Col.ToGrayUInt) },\n                { (typeof(float), typeof(float)),   (src, dst) => ToGray<float, C3f, float>(src, dst, Col.ToGrayFloat) },\n                { (typeof(double), typeof(double)), (src, dst) => ToGray<double, C3d, double>(src, dst, Col.ToGrayDouble) },\n            };\n\n        /// <summary>\n        /// Attempts to cast this instance to <see cref=\"PixVolume{T}\"/>. Returns null if the element type differs.\n        /// </summary>\n        /// <typeparam name=\"T\">Target element type.</typeparam>\n        /// <returns>The typed volume or null.</returns>\n        public PixVolume<T> AsPixVolume<T>() => this as PixVolume<T>;\n\n        /// <summary>\n        /// Returns a typed view of this volume. If the element type differs, a new volume with converted element type is created by copying.\n        /// </summary>\n        /// <typeparam name=\"T\">Target element type.</typeparam>\n        /// <returns>A typed volume of <typeparamref name=\"T\"/>.</returns>\n        public PixVolume<T> ToPixVolume<T>() => AsPixVolume<T>() ?? new PixVolume<T>(this);\n\n        /// <summary>\n        /// Converts this volume to the specified color format while keeping the underlying element type.\n        /// If this volume already has the requested format, returns the same instance;\n        /// in that case no data conversion or additional allocation is performed.\n        /// </summary>\n        /// <param name=\"format\">Target color format.</param>\n        /// <returns>A volume in the requested format; this instance if no conversion is required.</returns>\n        public abstract PixVolume ToPixVolume(Col.Format format);\n\n        /// <summary>\n        /// Converts this volume to the specified color format and element type.\n        /// If this volume already has the requested format and element type, returns the same instance;\n        /// in that case no data conversion or additional allocation is performed.\n        /// </summary>\n        /// <param name=\"format\">Target color format.</param>\n        /// <typeparam name=\"T\">Target element type.</typeparam>\n        /// <returns>A typed volume in the requested format; this instance if no conversion is required.</returns>\n        public PixVolume<T> ToPixVolume<T>(Col.Format format)\n        {\n            if (this is PixVolume<T> volume && volume.Format == format && volume.ChannelCount == format.ChannelCount()) return volume;\n            return new PixVolume<T>(format, this);\n        }\n\n        /// <summary>\n        /// Returns a representation with canonical, densely packed memory layout.\n        /// If this volume is already in the correct layout, returns the same instance;\n        /// in that case no data conversion or additional allocation is performed.\n        /// </summary>\n        public abstract PixVolume ToCanonicalDenseLayout();\n\n        #endregion\n\n        #region Copy\n\n        /// <summary>\n        /// Copies a single channel to the target volume (must match in size).\n        /// If the element type differs, the data are reinterpreted.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element type of the destination volume.</typeparam>\n        /// <param name=\"channelIndex\">Index of the channel in this volume.</param>\n        /// <param name=\"target\">Destination volume receiving the channel data.</param>\n        /// <exception cref=\"NotSupportedException\">if the element type <typeparamref name=\"Tv\"/> is invalid.</exception>\n        public abstract void CopyChannelTo<Tv>(long channelIndex, Volume<Tv> target);\n\n        /// <summary>\n        /// Copies the entire underlying tensor to the given target tensor (must match in size).\n        /// If the element type differs, the data are reinterpreted.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element type of the destination tensor.</typeparam>\n        /// <param name=\"target\">Destination tensor.</param>\n        /// <exception cref=\"NotSupportedException\">if the element type <typeparamref name=\"Tv\"/> is invalid.</exception>\n        public abstract void CopyTensor4To<Tv>(Tensor4<Tv> target);\n\n        /// <summary>\n        /// Creates a deep copy of this volume.\n        /// </summary>\n        public abstract PixVolume CopyToPixVolume();\n\n        /// <summary>\n        /// Creates a deep copy of this volume with canonical dense layout.\n        /// </summary>\n        public abstract PixVolume CopyToPixVolumeWithCanonicalDenseLayout();\n\n        #endregion\n\n        #region IPixVolumeVisitor\n\n        /// <summary>\n        /// Dispatches the current instance to a visitor based on its element type.\n        /// </summary>\n        /// <typeparam name=\"TResult\">The result type produced by the visitor.</typeparam>\n        /// <param name=\"visitor\">The visitor implementation.</param>\n        /// <returns>The visitor-specific result.</returns>\n        public abstract TResult Visit<TResult>(IPixVolumeVisitor<TResult> visitor);\n\n        #endregion\n    }\n\n    /// <summary>\n    /// 3D pixel container with element type <typeparamref name=\"T\"/>.\n    /// Provides access to the underlying 4D tensor.\n    /// </summary>\n    /// <typeparam name=\"T\">Per-channel element type.</typeparam>\n    public class PixVolume<T> : PixVolume\n    {\n        /// <summary>\n        /// The underlying 4D tensor storing the volume data.\n        /// </summary>\n        public Tensor4<T> Tensor4;\n\n        #region Constructors\n\n        #region  Default\n\n        /// <summary>\n        /// Initializes a new empty PixVolume instance without allocating storage.\n        /// Intended for serializers or deferred initialization scenarios. The\n        /// <see cref=\"Tensor4\"/> field must be assigned before use.\n        /// </summary>\n        public PixVolume() { }\n\n        #endregion\n\n        #region From Tensor\n\n        /// <summary>\n        /// Creates a new PixVolume backed by the given tensor and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"tensor4\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"tensor4\">Backing tensor in image layout. Not copied.</param>\n        public PixVolume(Col.Format format, Tensor4<T> tensor4)\n            : base(format)\n        {\n            Tensor4 = tensor4;\n        }\n\n        /// <summary>\n        /// Creates a new PixVolume backed by the given tensor and using the default color format for the element type.\n        /// No data is copied; the instance takes a reference to <paramref name=\"tensor4\"/>.\n        /// </summary>\n        /// <param name=\"tensor4\">Backing tensor in image layout. Not copied.</param>\n        public PixVolume(Tensor4<T> tensor4)\n            : this(Col.FormatDefaultOf(typeof(T), tensor4.SW), tensor4)\n        { }\n\n        #endregion\n\n        #region From Dimensions\n\n        /// <summary>\n        /// Allocates a new volume with the given 3D size and channel count using the default color format for the element type.\n        /// </summary>\n        /// <param name=\"size\">Volume size in pixels (width, height, depth).</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixVolume(V3i size, int channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), CreateTensor4<T>(size.X, size.Y, size.Z, channels))\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(V3i, int)\"/>\n        public PixVolume(V3l size, long channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), CreateTensor4<T>(size.X, size.Y, size.Z, channels))\n        { }\n\n        /// <summary>\n        /// Allocates a new volume with the given dimensions and channel count using the default color format for the element type.\n        /// </summary>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"depth\">Depth in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixVolume(int width, int height, int depth, int channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), CreateTensor4<T>(width, height, depth, channels))\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(int, int, int, int)\"/>\n        public PixVolume(long width, long height, long depth, long channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), CreateTensor4<T>(width, height, depth, channels))\n        { }\n\n        /// <summary>\n        /// Allocates a new volume with the given size and channel format. The number of channels is\n        /// derived from <paramref name=\"format\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"size\">Volume size in pixels (width, height, depth).</param>\n        public PixVolume(Col.Format format, V3i size)\n            : this(format, CreateTensor4<T>(size.X, size.Y, size.Z, Col.ChannelCount(format)))\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, V3i)\"/>\n        public PixVolume(Col.Format format, V3l size)\n            : this(format, CreateTensor4<T>(size.X, size.Y, size.Z, Col.ChannelCount(format)))\n        { }\n\n        /// <summary>\n        /// Allocates a new volume with the given dimensions and channel format. The number of channels is\n        /// derived from <paramref name=\"format\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"depth\">Depth in pixels.</param>\n        public PixVolume(Col.Format format, int width, int height, int depth)\n            : this(format, CreateTensor4<T>(width, height, depth, Col.ChannelCount(format)))\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, int, int, int)\"/>\n        public PixVolume(Col.Format format, long width, long height, long depth)\n            : this(format, CreateTensor4<T>(width, height, depth, Col.ChannelCount(format)))\n        { }\n\n        /// <summary>\n        /// Allocates a new volume with the given size, explicit channel count and format.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"size\">Volume size in pixels (width, height, depth).</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixVolume(Col.Format format, V3i size, int channels)\n            : this(format, CreateTensor4<T>(size.X, size.Y, size.Z, channels))\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, V3i, int)\"/>\n        public PixVolume(Col.Format format, V3l size, long channels)\n            : this(format, CreateTensor4<T>(size.X, size.Y, size.Z, channels))\n        { }\n\n        /// <summary>\n        /// Allocates a new volume with the given dimensions, explicit channel count and format.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"depth\">Depth in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixVolume(Col.Format format, int width, int height, int depth, int channels)\n            : this(format, CreateTensor4<T>(width, height, depth, channels))\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, int, int, int, int)\"/>\n        public PixVolume(Col.Format format, long width, long height, long depth, long channels)\n            : this(format, CreateTensor4<T>(width, height, depth, channels))\n        { }\n\n        #endregion\n\n        #region From Array\n\n        /// <summary>\n        /// Creates a new PixVolume backed by the given array and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image tensor with the specified dimensions.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"depth\">Depth in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixVolume(Col.Format format, T[] data, int width, int height, int depth, int channels)\n            : this(format, data.CreateImageTensor4(new V4l(width, height, depth, channels)))\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, T[], int, int, int, int)\"/>\n        public PixVolume(Col.Format format, T[] data, long width, long height, long depth, long channels)\n            : this(format, data.CreateImageTensor4(new V4l(width, height, depth, channels)))\n        { }\n\n        /// <summary>\n        /// Creates a new PixVolume backed by the given array and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image tensor with the specified dimensions.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"size\">Volume size in pixels (width, height, depth).</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixVolume(Col.Format format, T[] data, V3i size, int channels)\n            : this(format, data, size.X, size.Y, size.Z, channels)\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, T[], V3i, int)\"/>\n        public PixVolume(Col.Format format, T[] data, V3l size, long channels)\n            : this(format, data, size.X, size.Y, size.Z, channels)\n        { }\n\n        /// <summary>\n        /// Creates a new PixVolume backed by the given array and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image tensor with the specified dimensions.\n        /// The number of channels is derived from <paramref name=\"format\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"depth\">Depth in pixels.</param>\n        public PixVolume(Col.Format format, T[] data, int width, int height, int depth)\n            : this(format, data, width, height, depth, format.ChannelCount())\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, T[], int, int, int)\"/>\n        public PixVolume(Col.Format format, T[] data, long width, long height, long depth)\n            : this(format, data, width, height, depth, format.ChannelCount())\n        { }\n\n        /// <summary>\n        /// Creates a new PixVolume backed by the given array and using the specified color format.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image tensor with the specified dimensions.\n        /// The number of channels is derived from <paramref name=\"format\"/>.\n        /// </summary>\n        /// <param name=\"format\">Color format describing the channel layout and semantics.</param>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"size\">Volume size in pixels (width, height, depth).</param>\n        public PixVolume(Col.Format format, T[] data, V3i size)\n            : this(format, data, size.X, size.Y, size.Z)\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, T[], V3i)\"/>\n        public PixVolume(Col.Format format, T[] data, V3l size)\n            : this(format, data, size.X, size.Y, size.Z)\n        { }\n\n        /// <summary>\n        /// Creates a new PixVolume backed by the given array and using the default color format for the element type.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image tensor with the specified dimensions.\n        /// </summary>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"width\">Width in pixels.</param>\n        /// <param name=\"height\">Height in pixels.</param>\n        /// <param name=\"depth\">Depth in pixels.</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixVolume(T[] data, int width, int height, int depth, int channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), data, width, height, depth, channels)\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(T[], int, int, int, int)\"/>\n        public PixVolume(T[] data, long width, long height, long depth, long channels)\n            : this(Col.FormatDefaultOf(typeof(T), channels), data, width, height, depth, channels)\n        { }\n\n        /// <summary>\n        /// Creates a new PixVolume backed by the given array and using the default color format for the element type.\n        /// No data is copied; the instance takes a reference to <paramref name=\"data\"/>.\n        /// The data array is interpreted as an image tensor with the specified dimensions.\n        /// </summary>\n        /// <param name=\"data\">Backing array in image layout. Not copied.</param>\n        /// <param name=\"size\">Volume size in pixels (width, height, depth).</param>\n        /// <param name=\"channels\">Number of channels.</param>\n        public PixVolume(T[] data, V3i size, int channels)\n            : this(data, size.X, size.Y, size.Z, channels)\n        { }\n\n        /// <inheritdoc cref=\"PixVolume{T}(T[], V3i, int)\"/>\n        public PixVolume(T[] data, V3l size, long channels)\n            : this(data, size.X, size.Y, size.Z, channels)\n        { }\n\n        #endregion\n\n        #region From Copy\n\n        /// <summary>\n        /// Creates a typed copy of the given volume. Always allocates new storage and copies data.\n        /// The channel count is taken from <paramref name=\"source\"/>, the element type becomes\n        /// <typeparamref name=\"T\"/> (conversion may occur).\n        /// </summary>\n        /// <param name=\"source\">Source volume to copy from.</param>\n        /// <remarks>\n        /// <inheritdoc cref=\"PixVolume{T}(Col.Format, PixVolume)\" path=\"/remarks\"/>\n        /// </remarks>\n        public PixVolume(PixVolume source)\n            : this(Col.FormatDefaultOf(typeof(T), source.Format.ChannelCount()), source)\n        { }\n\n        /// <summary>\n        /// Creates a typed copy of the given volume in the requested color format. Always allocates new storage\n        /// and copies or converts channel data as needed.\n        /// </summary>\n        /// <param name=\"format\">Target color format for the new volume.</param>\n        /// <param name=\"source\">Source volume to copy from.</param>\n        /// <remarks>\n        /// <list type=\"bullet\">\n        /// <item>\n        /// Premultiplied state must match between <paramref name=\"format\"/> and <paramref name=\"source\"/>; otherwise a\n        ///   <see cref=\"NotImplementedException\"/> is thrown.\n        /// </item>\n        /// <item>\n        /// If the formats match and sizes are equal, a straight copy is performed.\n        /// </item>\n        /// <item>\n        /// Missing alpha is filled with the maximum value of <typeparamref name=\"T\"/>.\n        /// </item>\n        /// <item>\n        /// Gray can be computed from RGB for a few common element types; unsupported combinations throw.\n        /// </item>\n        /// <item>\n        /// Expanding RG to RGB sets blue to zero.\n        /// </item>\n        /// <item>\n        /// Other unmapped conversions throw <see cref=\"NotSupportedException\"/>.\n        /// </item>\n        /// </list>\n        /// </remarks>\n        public PixVolume(Col.Format format, PixVolume source)\n        {\n            if (format.IsPremultiplied() != source.Format.IsPremultiplied())\n            {\n                throw new NotImplementedException(\n                    \"Conversion between alpha and premultiplied alpha formats not implemented yet.\"\n                );\n            }\n\n            var srcInfo = source.Tensor4Info;\n            var dstChannels = Col.ChannelsOfFormat(format);\n            var tensor4 = CreateTensor4<T>(srcInfo.Size.X, srcInfo.Size.Y, srcInfo.Size.Z, dstChannels.Length);\n            tensor4.F = source.Tensor4Info.F;\n\n            if (format == source.Format && srcInfo.Size == tensor4.Size)\n            {\n                source.CopyTensor4To(tensor4);\n            }\n            else\n            {\n                var srcChannels = Col.ChannelsOfFormat(source.Format);\n\n                for (int dstIndex = 0; dstIndex < dstChannels.Length; dstIndex++)\n                {\n                    var channel = dstChannels[dstIndex];\n                    var volume = tensor4.SubXYZVolume(dstIndex);\n                    var srcIndex = srcChannels.IndexOf(channel);\n\n                    // If we have an RGB channel, we may also just copy a Gray or BW channel\n                    if (srcIndex == -1 && channel is Col.Channel.Red or Col.Channel.Green or Col.Channel.Blue)\n                    {\n                        var bw = srcChannels.IndexOf(Col.Channel.BW);\n                        var gray = srcChannels.IndexOf(Col.Channel.Gray);\n                        srcIndex = Fun.Max(bw, gray);\n                    }\n\n                    if (srcIndex > -1)\n                    {\n                        // Channel exists in source image, just copy\n                        if (source is PixVolume<T> pi)\n                        {\n                            volume.Set(pi.GetChannelInFormatOrder(srcIndex));\n                        }\n                        else\n                        {\n                            var order = source.Format.ChannelOrder();\n                            source.CopyChannelTo(order[srcIndex], volume); // CopyChannelTo uses canonical order\n                        }\n                    }\n                    else if (channel is Col.Channel.Alpha or Col.Channel.PremultipliedAlpha)\n                    {\n                        // Alpha channel does not exist in source image, fill with max value\n                        volume.Set(Col.Info<T>.MaxValue);\n                    }\n                    else if (channel == Col.Channel.Gray &&\n                             srcChannels.Contains(Col.Channel.Red) &&\n                             srcChannels.Contains(Col.Channel.Green) &&\n                             srcChannels.Contains(Col.Channel.Blue))\n                    {\n                        var t1 = source.PixFormat.Type;\n                        var t2 = typeof(T);\n\n                        if (s_rgbToGrayMap.TryGetValue((t1, t2), out var toGray))\n                        {\n                            toGray(source, volume);\n                        }\n                        else\n                        {\n                            throw new NotImplementedException(\n                                $\"Conversion from {t1} image with format {source.Format} to {t2} grayscale not implemented.\"\n                            );\n                        }\n                    }\n                    else if (channel == Col.Channel.Blue &&\n                             source.Format == Col.Format.RG &&\n                             dstChannels.Contains(Col.Channel.Red) &&\n                             dstChannels.Contains(Col.Channel.Green))\n                    {\n                        // Allow expanding from RG to RGB formats, blue channel is set to zero\n                    }\n                    else\n                    {\n                        throw new NotSupportedException(\n                            $\"Conversion from format {source.Format} to format {format} is not supported.\"\n                        );\n                    }\n                }\n            }\n\n            Tensor4 = tensor4;\n            Format = format;\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Gets the underlying storage as a <typeparamref name=\"T\"/> array.\n        /// </summary>\n        public T[] Data => Tensor4.Data;\n\n        /// <inheritdoc />\n        public override Array Array => Tensor4.Data;\n\n        /// <inheritdoc />\n        public override PixFormat PixFormat => new(typeof(T), Format);\n\n        /// <inheritdoc />\n        public override Tensor4Info Tensor4Info => Tensor4.Info;\n\n        /// <inheritdoc />\n        public override int BytesPerChannel => typeof(T).GetCLRSize();\n\n        /// <summary>\n        /// Gets the channel volumes in canonical order (red, green, blue, alpha).\n        /// </summary>\n        public IEnumerable<Volume<T>> Channels\n        {\n            get\n            {\n                long[] order = Format.ChannelOrder();\n                for (long i = 0; i < order.Length; i++)\n                    yield return GetChannelInFormatOrder(order[i]);\n            }\n        }\n\n        /// <summary>\n        /// Gets the channel volumes as array in canonical order (red, green, blue, alpha).\n        /// </summary>\n        public Volume<T>[] ChannelArray => Channels.ToArray();\n\n        /// <summary>\n        /// Returns the volume representation of the 4D tensor if there is only one channel.\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">if there are multiple channels.</exception>\n        public Volume<T> Volume => Tensor4.AsVolumeWindow();\n\n        #endregion\n\n        #region Conversions\n\n        /// <inheritdoc cref=\"ToFormat\"/>\n        public override PixVolume ToPixVolume(Col.Format format) => ToFormat(format);\n\n        /// <summary>\n        /// Converts this volume to the specified color format. If the current format already matches\n        /// and the channel counts are equal, the current instance is returned; otherwise a new instance\n        /// with converted channels is created.\n        /// </summary>\n        /// <param name=\"format\">Target color format.</param>\n        /// <returns>A volume in the requested format.</returns>\n        public PixVolume<T> ToFormat(Col.Format format)\n        {\n            if (Format == format && ChannelCount == format.ChannelCount()) return this;\n            return new PixVolume<T>(format, this);\n        }\n\n        /// <inheritdoc cref=\"ToCanonicalDenseLayout\" />\n        public PixVolume<T> ToImageLayout() => !Tensor4.HasImageLayout() ? new PixVolume<T>(Format, this) : this;\n\n        /// <inheritdoc />\n        public override PixVolume ToCanonicalDenseLayout() => ToImageLayout();\n\n        #endregion\n\n        #region Copy\n\n        /// <inheritdoc />\n        public override void CopyChannelTo<Tv>(long channelIndex, Volume<Tv> target)\n        {\n            var subMatrix = GetChannel<Tv>(channelIndex);\n            target.Set(subMatrix);\n        }\n\n        /// <inheritdoc />\n        public override void CopyTensor4To<Tv>(Tensor4<Tv> target)\n        {\n            if (Tensor4 is Tensor4<Tv> source)\n                target.Set(source);\n            else\n                target.Set(Tensor4.AsTensor4<T, Tv>());\n        }\n\n        /// <summary>\n        /// Creates a deep copy using canonical image layout regardless of the current layout.\n        /// If already in image layout, the data is copied; otherwise, data is transformed to image layout.\n        /// </summary>\n        public PixVolume<T> CopyToImageLayout()\n        {\n            return Tensor4.HasImageLayout() ? new PixVolume<T>(Format, Tensor4.CopyToImage()) : new PixVolume<T>(this);\n        }\n\n        /// <inheritdoc cref=\"CopyToPixVolume\" />\n        public PixVolume<T> Copy() => new(Format, Tensor4.CopyToImageWindow());\n\n        /// <inheritdoc />\n        public override PixVolume CopyToPixVolume() => Copy();\n\n        /// <inheritdoc />\n        public override PixVolume CopyToPixVolumeWithCanonicalDenseLayout() => CopyToImageLayout();\n\n        [Obsolete(\"Should return PixVolume.\")]\n        public PixImage<T> Copy<Tv>(Func<Tv, Tv> fun)\n        {\n            return Copy(fun, Format);\n        }\n\n        [Obsolete(\"Should return PixVolume.\")]\n        public PixImage<T> Copy<Tv>(Func<Tv, Tv> fun, Col.Format format)\n        {\n            var mat = GetVolume<Tv>().MapWindow(fun);\n            var vol = new Volume<T>(mat.Data, Volume.Info);\n            return new PixImage<T>(format, vol);\n        }\n\n        #endregion\n\n        #region Obtaining Volumes\n\n        /// <summary>\n        /// Returns the specified channel using the canonical order (red, green, blue, alpha).\n        /// </summary>\n        /// <param name=\"channelIndex\">Index within the canonical order of channels.</param>\n        /// <returns>A volume window over the selected channel.</returns>\n        public Volume<T> GetChannel(long channelIndex)\n        {\n            var order = Format.ChannelOrder();\n            return GetChannelInFormatOrder(order[channelIndex]);\n        }\n\n        /// <summary>\n        /// Returns the specified channel by semantic name according to the current format.\n        /// </summary>\n        /// <param name=\"channel\">The channel to access (e.g. Red, Green, Blue, Alpha, Gray).</param>\n        /// <returns>A volume window over the selected channel.</returns>\n        public Volume<T> GetChannel(Col.Channel channel)\n        {\n            return GetChannelInFormatOrder(Format.ChannelIndex(channel));\n        }\n\n\n        /// <summary>\n        /// Returns the specified channel (using the canonical order) with a different view type.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element view type of the returned volume.</typeparam>\n        /// <param name=\"channelIndex\">Index within the canonical order of channels.</param>\n        /// <returns>A typed volume window over the selected channel.</returns>\n        /// <exception cref=\"NotSupportedException\">if the element type and view type are incompatible.</exception>\n        public Volume<T, Tv> GetChannel<Tv>(long channelIndex)\n        {\n            return GetChannelInFormatOrder<Tv>(Format.ChannelOrder()[channelIndex]);\n        }\n\n        /// <summary>\n        /// Returns the specified channel based on the order of the color format.\n        /// </summary>\n        /// <param name=\"formatChannelIndex\">Index of the channel in the current format's order.</param>\n        /// <returns>A volume window over the selected channel.</returns>\n        public Volume<T> GetChannelInFormatOrder(long formatChannelIndex)\n        {\n            return Tensor4.SubXYZVolumeWindow(formatChannelIndex);\n        }\n\n        /// <summary>\n        /// Returns the specified channel based on the order of the color format with a different view type.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element view type of the returned volume.</typeparam>\n        /// <param name=\"formatChannelIndex\">Index of the channel in the current format's order.</param>\n        /// <returns>A typed volume window over the selected channel.</returns>\n        /// <exception cref=\"NotSupportedException\">if the element type and view type are incompatible.</exception>\n        public Volume<T, Tv> GetChannelInFormatOrder<Tv>(long formatChannelIndex)\n        {\n            var volume = Tensor4.SubXYZVolume<Tv>(formatChannelIndex);\n            volume.Accessors = TensorAccessors.Get<T, Tv>(TensorAccessors.Intent.ColorChannel, Tensor4.DeltaArray);\n            return volume;\n        }\n\n        /// <summary>\n        /// Reinterprets the underlying 4D image tensor as a volume of the specified type.\n        /// </summary>\n        /// <typeparam name=\"Tv\">Element view type of the returned volume (e.g. a color type such as <see cref=\"C3f\"/> or <see cref=\"C4ui\"/>).</typeparam>\n        /// <returns>A typed volume window over the whole 4D image tensor.</returns>\n        /// <exception cref=\"NotSupportedException\">if the view type is invalid for the format and element type.</exception>\n        public Volume<T, Tv> GetVolume<Tv>() => Tensor4.GetVolume<T, Tv>(Format.GetIntent());\n\n        #endregion\n\n        #region IPixVolumeVisitor\n\n        /// <inheritdoc />\n        public override TResult Visit<TResult>(IPixVolumeVisitor<TResult> visitor)\n        {\n            return visitor.Visit(this);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensor.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static partial class Tensor\n    {\n        /// <summary>\n        /// Raw sample access without checks.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup2<long>>\n            Index2SamplesRaw = (i, min, max, d) => new Tup2<long>(0L, d);\n\n        /// <summary>\n        /// Provides sample clamping to the border value.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup2<long>>\n            Index2SamplesClamped = (i, first, end, d) =>\n            {\n                long i0 = i - first;\n                if (i0 < 0) return new Tup2<long>(-i0 * d);\n                long i1 = i - end + 1;\n                if (i1 >= 0) return new Tup2<long>(-i1 * d);\n                return new Tup2<long>(0L, d);\n            };\n\n        /// <summary>\n        /// Provides cyclic handling within one cycle of the original.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup2<long>>\n            Index2SamplesCyclic1 = (i, first, end, d) =>\n            {\n                long i0 = i - first;\n                if (i0 < 0)\n                {\n                    var s = (end - first) * d;\n                    if (i0 < -1) return new Tup2<long>(s, s + d);\n                    return new Tup2<long>(s, d);\n                }\n                long i1 = i - end + 1;\n                if (i1 >= 0)\n                {\n                    var s = (first - end) * d;\n                    if (i1 >= 1) return new Tup2<long>(s, s + d);\n                    return new Tup2<long>(0, s + d);\n                }\n                return new Tup2<long>(0L, d);\n            };\n\n        /// <summary>\n        /// Raw sample access without checks.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup3<long>>\n            Index3SamplesRaw = (i, first, end, d) => new Tup3<long>(-d, 0L, d);\n\n        /// <summary>\n        /// Provides sample clamping to the border value.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup3<long>>\n            Index3SamplesClamped = (i, first, end, d) =>\n            {\n                long i0 = i - first, i1 = i - end + 1;\n                return i0 > 0 ? (i1 < 0 ? new Tup3<long>(-d, 0L, d)\n                                            : (i1 == 0 ? new Tup3<long>(-d, 0L, 0L)\n                                                        : new Tup3<long>(-i1 * d)))\n                                : (i0 == 0 ? (i1 < 0 ? new Tup3<long>(0L, 0L, d)\n                                                        : new Tup3<long>(0L))\n                                            : new Tup3<long>(-i0 * d));\n            };\n\n        /// <summary>\n        /// Raw sample access without checks.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup4<long>>\n            Index4SamplesRaw = (i, first, end, d) => new Tup4<long>(-d, 0L, d, d + d);\n\n        /// <summary>\n        /// Provides sample clamping to the border value.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup4<long>>\n            Index4SamplesClamped = (i, first, end, d) =>\n            {\n                long i0 = i - first, i1 = i - end + 1;\n                if (i0 < 1)\n                {\n                    if (i0 < 0)\n                    {\n                        if (i0 < -1) return new Tup4<long>(-i0 * d);\n                        if (i1 >= -1) return new Tup4<long>(d);\n                        return new Tup4<long>(d, d, d, d + d);\n                    }\n                    if (i1 >= -1)\n                    {\n                        if (i1 >= 0) return new Tup4<long>(0L);\n                        return new Tup4<long>(0L, 0L, d, d);\n                    }\n                    return new Tup4<long>(0L, 0L, d, d + d);\n                }\n                if (i1 >= -1)\n                {\n                    if (i1 >= 0)\n                    {\n                        if (i1 >= 1) return new Tup4<long>(-i1 * d);\n                        return new Tup4<long>(-d, 0L, 0L, 0L);\n                    }\n                    return new Tup4<long>(-d, 0L, d, d);\n                }\n                return new Tup4<long>(-d, 0L, d, d + d);\n            };\n\n        /// <summary>\n        /// Provides cyclic handling within one cycle of the original.\n        /// Note that this does not handle regions with less than four\n        /// samples.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup4<long>>\n            Index4SamplesCyclic1 = (i, first, end, d) =>\n            {\n                long i0 = i - first, i1 = i - end + 1;\n                if (i0 < 1)\n                {\n                    var s = (end - first) * d;\n                    if (i0 < -1)\n                    {\n                        if (i0 < -2) return new Tup4<long>(s - d, s, s + d, s + d + d);\n                        return new Tup4<long>(s - d, s, s + d, d + d);\n                    }\n                    if (i0 < 0) return new Tup4<long>(s - d, s, d, d + d);\n                    return new Tup4<long>(s - d, 0L, d, d + d);\n                }\n                if (i1 >= -1)\n                {\n                    var s = (first - end) * d;\n                    if (i1 >= 1)\n                    {\n                        if (i1 >= 2) return new Tup4<long>(s - d, s, s + d, s + d + d);\n                        return new Tup4<long>(-d, s, s + d, s + d + d);\n                    }\n                    if (i1 >= 0) return new Tup4<long>(-d, 0L, s + d, s + d + d);\n                    return new Tup4<long>(-d, 0L, d, s + d + d);\n                }\n                return new Tup4<long>(-d, 0L, d, d + d);\n            };\n\n        /// <summary>\n        /// Raw sample access without checks.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup6<long>>\n            Index6SamplesRaw = (i, first, end, d) =>\n            {\n                var d2 = d + d; return new Tup6<long>(-d2, -d, 0L, d, d2, d2 + d);\n            };\n\n\n        /// <summary>\n        /// Provides sample clamping to the border value. Note that this\n        /// function currently requires that max - min >= 5! i.e. it \n        /// does not work for too small source tensors.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup5<long>>\n            Index5SamplesClamped = (i, first, end, d) =>\n            {\n                long i0 = i - first, i1 = i - end + 1;\n                long d2 = d + d;\n                if (i0 < 2)\n                {\n                    switch (i0)\n                    {\n                        case 1: return new Tup5<long>(-d, -d, 0L, d, d2);\n                        case 0: return new Tup5<long>(0L, 0L, 0L, d, d2);\n                        case -1: return new Tup5<long>(d, d, d, d, d2);\n                        default: return new Tup5<long>(-i0 * d);\n                    }\n                }\n                if (i1 > -2)\n                {\n                    switch (i1)\n                    {\n                        case -1: return new Tup5<long>(-d2, d, 0L, d, d);\n                        case 0: return new Tup5<long>(-d2, d, 0L, 0L, 0L);\n                        case 1: return new Tup5<long>(-d2, -d, -d, -d, -d);\n                        default: return new Tup5<long>(-i1 * d);\n                    }\n                }\n                return new Tup5<long>(-d2, -d, 0L, d, d2);\n            };\n\n\n        /// <summary>\n        /// Provides sample clamping to the border value. Note that this\n        /// function currently requires that max - min >= 5! i.e. it \n        /// does not work for too small source tensors.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup6<long>>\n            Index6SamplesClamped = (i, first, end, d) =>\n            {\n                long i0 = i - first, i1 = i - end + 1;\n                long d2 = d + d;\n                if (i0 < 2)\n                {\n                    switch (i0)\n                    {\n                        case 1: return new Tup6<long>(-d, -d, 0L, d, d2, d2 + d);\n                        case 0: return new Tup6<long>(0L, 0L, 0L, d, d2, d2 + d);\n                        case -1: return new Tup6<long>(d, d, d, d, d2, d2 + d);\n                        case -2: return new Tup6<long>(d2, d2, d2, d2, d2, d2 + d);\n                        default: return new Tup6<long>(-i0 * d);\n                    }\n                }\n                if (i1 > -3)\n                {\n                    switch (i1)\n                    {\n                        case -2: return new Tup6<long>(-d2, -d, 0L, d, d2, d2);\n                        case -1: return new Tup6<long>(-d2, -d, 0L, d, d, d);\n                        case 0: return new Tup6<long>(-d2, -d, 0L, 0L, 0L, 0L);\n                        case 1: return new Tup6<long>(-d2, -d, -d, -d, -d, -d);\n                        default: return new Tup6<long>(-i1 * d);\n                    }\n                }\n                return new Tup6<long>(-d2, -d, 0L, d, d2, d2 + d);\n            };\n\n        /// <summary>\n        /// Provides sample clamping to the border value. Note that this\n        /// function currently requires that max - min >= 5! i.e. it \n        /// does not work for too small source tensors.\n        /// </summary>\n        public static readonly Func<long, long, long, long, Tup7<long>>\n            Index7SamplesClamped = (i, first, end, d) =>\n            {\n                long i0 = i - first, i1 = i - end + 1;\n                long d2 = d + d;\n                if (i0 < 3)\n                {\n                    switch (i0)\n                    {\n                        case 2: return new Tup7<long>(-d2, -d2, -d, 0L, d, d2, d2 + d);\n                        case 1: return new Tup7<long>(-d, -d, -d, 0L, d, d2, d2 + d);\n                        case 0: return new Tup7<long>(0L, 0L, 0L, 0L, d, d2, d2 + d);\n                        case -1: return new Tup7<long>(d, d, d, d, d, d2, d2 + d);\n                        case -2: return new Tup7<long>(d2, d2, d2, d2, d2, d2, d2 + d);\n                        default: return new Tup7<long>(-i0 * d);\n                    }\n                }\n                if (i1 > -3)\n                {\n                    switch (i1)\n                    {\n                        case -2: return new Tup7<long>(-d2 - d, -d2, -d, 0L, d, d2, d2);\n                        case -1: return new Tup7<long>(-d2 - d, -d2, -d, 0L, d, d, d);\n                        case 0: return new Tup7<long>(-d2 - d, -d2, -d, 0L, 0L, 0L, 0L);\n                        case 1: return new Tup7<long>(-d2 - d, -d2, -d, -d, -d, -d, -d);\n                        case 2: return new Tup7<long>(-d2 - d, -d2, -d2, -d2, -d2, -d2, -d2);\n                        default: return new Tup7<long>(-i1 * d);\n                    }\n                }\n                return new Tup7<long>(-d2 - d, -d2, -d, 0L, d, d2, d2 + d);\n            };\n\n    }\n\n    /// <summary>\n    /// Generic tensor of elements in r dimensons, each of arbitrary size\n    /// with arbitrary strides in each dimension. All sizes are given as\n    /// r-dimensional array of longs, with the dimensions ordered from\n    /// inner to outer dimension.\n    /// The tensor does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays, matrices, volumes, and    \n    /// tensors. Operations on tensors are supported by function arguments\n    /// which can be easily exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure.\n    /// </summary>\n    /// <typeparam name=\"T\">Element type.</typeparam>\n    public struct Tensor<T> : IValidity, ITensor<T>, IArrayTensorN\n    {\n        private T[] m_data;\n        private long m_origin;\n        private int m_rank;\n        private long[] m_size;\n        private long[] m_delta;\n\n        #region Constructors\n\n        public Tensor(long[] size)\n        {\n            m_rank = size.Length;\n            m_size = size.Copy();            \n            long total;\n            m_delta = Tools.DenseDelta(m_size, out total);\n            m_data = new T[total];\n            m_origin = 0;\n        }\n\n        public Tensor(int[] size)\n            : this(size.Map(x => (long)x))\n        { }\n\n        public Tensor(long[] size, T value)\n        {\n            m_rank = size.Length;\n            m_size = size.Copy();\n            long total;\n            m_delta = Tools.DenseDelta(m_size, out total);\n            m_data = new T[total];\n            for (long i = 0; i < total; i++) m_data[i] = value;\n            m_origin = 0;\n        }\n\n        public Tensor(int[] size, T value)\n            : this(size.Map(x => (long)x), value)\n        { }\n\n        public Tensor(T[] data, long origin, int[] size)\n        {\n            m_data = data;\n            m_rank = (int)size.Length;\n            m_origin = origin;\n            m_size = size.Map(x => (long)x);\n            long total;\n            m_delta = Tools.DenseDelta(m_size, out total);\n        }\n\n        public Tensor(T[] data, long origin, long[] size)\n        {\n            m_data = data;\n            m_rank = size.Length;\n            m_origin = origin;\n            m_size = size.Copy();\n            long total;\n            m_delta = Tools.DenseDelta(size, out total);\n        }\n\n        public Tensor(\n                T[] data, long origin,\n                long[] size, long[] delta\n                )\n        {\n            m_data = data;\n            m_rank = size.Length;\n            m_origin = origin;\n            m_size = size.Copy();\n            m_delta = delta.Copy();\n        }\n\n        #endregion\n\n        #region Properties\n\n        public readonly bool IsValid { get { return m_data != null; } }\n        public readonly bool IsInvalid { get { return m_data == null; } }\n\n        /// <summary>\n        /// Underlying data array. Not exclusively owned by the tensor.\n        /// </summary>\n        public readonly T[] Data { get { return m_data; } }\n\n        /// <summary>\n        /// Origin index in the unerlying data array.\n        /// </summary>\n        public long Origin { readonly get { return m_origin; } set { m_origin = value; }  }\n\n        /// <summary>\n        /// The total number of contravariant and covariant indices.\n        /// </summary>\n        public readonly int Rank { get { return m_rank; } }\n\n        /// <summary>\n        /// Length is copied out and in, emulating a value property.\n        /// Setting the size property also sets the rank of the tensor.\n        /// </summary>\n        public long[] Size\n        {\n            readonly get { return m_size.Copy(); }\n            set { m_size = value.Copy(); m_rank = m_size.Length; }\n        }\n\n        public readonly long Count\n        {\n            get\n            {\n                long c = 1;\n                foreach (long len in m_size) c *= len;\n                return c;\n            }\n        }\n\n        /// <summary>\n        /// Delta is copied out and in, emulating a value property.\n        /// </summary>\n        public long[] Delta\n        {\n            readonly get { return m_delta.Copy(); }\n            set\n            {\n                if (m_delta.Length != m_rank)\n                    throw new ArgumentException(\"delta of wrong rank\");\n                m_delta = value.Copy();\n            }\n        }\n\n        public long OriginIndex { readonly get { return m_origin; } set { m_origin = value; } }\n\n        public long[] SizeArray\n        {\n            readonly get { return Size; }\n            set { Size = value; }\n        }\n\n        public long[] DeltaArray\n        {\n            readonly get { return Delta; }\n            set { Delta = value; }\n        }\n\n        public long[] FirstArray\n        {\n            get { throw new NotImplementedException(); }\n            set { throw new NotImplementedException(); }\n        }\n\n        /// <summary>\n        /// Rank\n        /// </summary>\n        public readonly int R { get { return m_rank; } }\n        /// <summary>\n        /// Length\n        /// </summary>\n        public readonly long[] L { get { return m_size; } }\n        /// <summary>\n        /// Delta\n        /// </summary>\n        public readonly long[] D { get { return m_delta; } }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<T> Elements\n        {\n            get\n            {\n                long i = Origin; var ve = Init();\n                for (long ee = ve[R - 1]; i != ee; i = Next(i, ref ve))\n                {\n                    for (long e = ve[0], d = D[0]; i != e; i += d)\n                        yield return m_data[i];\n                }\n            }\n        }\n\n        public readonly Type ArrayType\n        {\n            get { return typeof(T[]); }\n        }\n\n        public Array Array\n        {\n            readonly get { return m_data; }\n            set { m_data = (T[])value; }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        public readonly T this[Vector<int> vi]\n        {\n            get { return m_data[Index(vi)]; }\n\n            set { m_data[Index(vi)] = value; }\n        }\n\n        public readonly T this[Vector<long> vi]\n        {\n            get { return m_data[Index(vi)]; }\n\n            set { m_data[Index(vi)] = value; }\n        }\n\n        public readonly T this[params int[] vi]\n        {\n            get { return m_data[Index(vi)]; }\n\n            set { m_data[Index(vi)] = value; }\n        }\n\n        public readonly T this[params long[] vi]\n        {\n            get { return m_data[Index(vi)]; }\n\n            set { m_data[Index(vi)] = value; }\n        }\n\n        #endregion\n\n        #region Indexing Helper Methods\n\n        public readonly long[] Init()\n        {\n            var ve = new long[R];\n            for (int r = 0; r < R; r++)\n                ve[r] = Origin + DLR(r);\n            return ve;\n        }\n        public readonly long Next(long i, ref long[] ve)\n        {\n            for (int r = 1; r < R; r++)\n            {\n                i += SR(r);\n                if (i == ve[r]) continue;\n                while (--r >= 0)\n                    ve[r] = i + DLR(r);\n                break;\n            }\n            return i;\n        }\n\n        public readonly long Next(long i, ref long[] ve, ref long[] vi)\n        {\n            for (int r = 1; r < R; r++)\n            {\n                i += SR(r); vi[r]++;\n                if (i == ve[r]) continue;\n                while (--r >= 0)\n                {\n                    ve[r] = i + DLR(r);\n                    vi[r] = 0;\n                }\n                break;\n            }\n            return i;\n        }\n\n        /// <summary>\n        /// Cummulative delta for all elements in dimension r.\n        /// </summary>\n        public readonly long DLR(int r) { return m_size[r] * m_delta[r]; }\n\n        /// <summary>\n        /// Skip this many elements in the underlying data array when\n        /// stepping between subtensors of rank r (required: r > 0).\n        /// </summary>\n        public readonly long SR(int r) { return m_delta[r] - m_size[r - 1] * m_delta[r - 1]; }\n\n        /// <summary>\n        /// Calculate element index for underlying data array. \n        /// </summary>\n        /// <param name=\"vi\"></param>\n        public readonly long Index(Vector<int> vi)\n        {\n            var i = Origin;\n            for (long r = 0; r < R; r++) i += vi[r] * D[r];\n            return i;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array. \n        /// </summary>\n        /// <param name=\"vi\"></param>\n        public readonly long Index(Vector<long> vi)\n        {\n            var i = Origin;\n            for (long r = 0; r < R; r++) i += vi[r] * D[r];\n            return i;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array. \n        /// </summary>\n        public readonly long Index(params int[] vi)\n        {\n            var i = Origin;\n            for (long r = 0; r < R; r++) i += vi[r] * D[r];\n            return i;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array. \n        /// </summary>\n        public readonly long Index(params long[] vi)\n        {\n            var i = Origin;\n            for (long r = 0; r < R; r++) i += vi[r] * D[r];\n            return i;\n        }\n        #endregion\n\n        #region Reinterpretation and Parts\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<T> SubVector(long[] origin, long size, long delta)\n        {\n            return new Vector<T>(m_data, Index(origin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<T> SubMatrix(long[] origin, V2l size, V2l delta)\n        {\n            return new Matrix<T>(m_data, Index(origin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<T> SubVolume(long[] origin, V3l size, V3l delta)\n        {\n            return new Volume<T>(m_data, Index(origin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubTensor does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor<T> SubTensor(long[] origin, long[] size)\n        {\n            return new Tensor<T>(m_data, Index(origin), size, m_delta);\n        }\n\n        /// <summary>\n        /// A SubTensor does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor<T> SubTensor(\n                long[] origin, long[] size, long[] delta\n                )\n        {\n            return new Tensor<T>(m_data, Index(origin), size, delta);\n        }\n\n        #endregion\n\n        #region Copying\n        /// <summary>\n        /// Elementwise copy.\n        /// </summary>\n        public readonly Tensor<T> Copy()\n        {\n            return new Tensor<T>(L).Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// </summary>\n        public readonly Tensor<Tr> Copy<Tr>(Func<T, Tr> fun)\n        {\n            return new Tensor<Tr>(L).Set(this, fun);\n        }\n        #endregion\n\n        #region Manipulation Methods\n\n        public readonly Tensor<T> Set(ITensor<T> t)\n        {\n            var ve = Init(); var vi = new long[R];\n            long i = Origin;\n            for (long ee = ve[R - 1]; i != ee; i = Next(i, ref ve, ref vi))\n            {\n                for (long e = ve[0], d = D[0], ix = 0; i != e; i += d, ix++)\n                {\n                    vi[0] = ix; m_data[i] = t[vi];\n                }\n            }\n            return this;\n        }\n\n        public readonly Tensor<T> Set<T1>(ITensor<T1> t, Func<T1,T> fun)\n        {\n            var ve = Init(); var vi = new long[R];\n            long i = Origin;\n            for (long ee = ve[R - 1]; i != ee; i = Next(i, ref ve, ref vi))\n            {\n                for (long e = ve[0], d = D[0], ix = 0; i != e; i += d, ix++)\n                {\n                    vi[0] = ix; m_data[i] = fun(t[vi]);\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor<T> SetByCoord(Func<long[], T> fun)\n        {\n            var ve = Init(); var vi = new long[R];\n            long i = Origin;\n            for (long ee = ve[R - 1]; i != ee; i = Next(i, ref ve, ref vi))\n            {\n                for (long e = ve[0], d = D[0], ix = 0; i != e; i += d, ix++)\n                {\n                    vi[0] = ix;  m_data[i] = fun(vi);\n                }\n            }\n            return this;\n        }\n\n        public readonly Tensor<T> SetByIndex<T1>(Tensor<T1> t1, Func<long, T> fun)\n        {\n            var ve = Init(); var ve1 = t1.Init();\n            long i = Origin, i1 = t1.Origin;\n            for (long ee = ve[R - 1]; i != ee;\n                      i = Next(i, ref ve), i1 = t1.Next(i1, ref ve1))\n            {\n                for (long e = ve[0], d = D[0], d1 = t1.D[0];\n                          i != e; i += d, i1 += d1)\n                    m_data[i] = fun(i1);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another tensor.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor<T> Set(Tensor<T> t1)\n        {\n            var ve = Init(); var ve1 = t1.Init();\n            long i = Origin, i1 = t1.Origin;\n            for (long ee = ve[R - 1]; i != ee;\n                      i = Next(i, ref ve), i1 = t1.Next(i1, ref ve1))\n            {\n                for (long e = ve[0], d = D[0], d1 = t1.D[0];\n                          i != e; i += d, i1 += d1)\n                    m_data[i] = t1.Data[i1];\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// the elements of the supplied tensor.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor<T> Set<T1>(Tensor<T1> t1, Func<T1, T> fun)\n        {\n            var ve = Init(); var ve1 = t1.Init();\n            long i = Origin, i1 = t1.Origin;\n            for (long ee = ve[R - 1]; i != ee;\n                      i = Next(i, ref ve), i1 = t1.Next(i1, ref ve1))\n            {\n                for (long e = ve[0], d = D[0], d1 = t1.D[0];\n                          i != e; i += d, i1 += d1)\n                    m_data[i] = fun(t1.Data[i1]);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor<T> Set<T1, T2>(\n                Tensor<T1> t1, Tensor<T2> t2, Func<T1, T2, T> fun)\n        {\n            var ve = Init(); var ve1 = t1.Init(); var ve2 = t2.Init();\n            long i = Origin, i1 = t1.Origin, i2 = t2.Origin;\n            for (long ee = ve[R - 1]; i != ee;\n                      i = Next(i, ref ve), i1 = t1.Next(i1, ref ve1),\n                      i2 = t2.Next(i2, ref ve2))\n            {\n                for (long e = ve[0], d = D[0], d1 = t1.D[0], d2 = t2.D[0];\n                          i != e; i += d, i1 += d1, i2 += d2)\n                    m_data[i] = fun(t1.Data[i1], t2.Data[i2]);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor<T> Set<T1, T2, T3>(\n                Tensor<T1> t1, Tensor<T2> t2, Tensor<T3> t3,\n                Func<T1, T2, T3, T> fun)\n        {\n            var ve = Init(); var ve1 = t1.Init();\n            var ve2 = t2.Init(); var ve3 = t3.Init();\n            long i = Origin, i1 = t1.Origin, i2 = t2.Origin, i3 = t3.Origin;\n            for (long ee = ve[R - 1]; i != ee;\n                      i = Next(i, ref ve), i1 = t1.Next(i1, ref ve1),\n                      i2 = t2.Next(i2, ref ve2), i3 = t3.Next(i3, ref ve3))\n            {\n                for (long e = ve[0], d = D[0], d1 = t1.D[0],\n                          d2 = t2.D[0], d3 = t3.D[0];\n                          i != e; i += d, i1 += d1, i2 += d2, i3 += d3)\n                    m_data[i] = fun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n            }\n            return this;\n        }\n        #endregion\n\n        #region Creator Functions\n\n        public static Tensor<T> Create(ITensor<T> t)\n        {\n            return new Tensor<T>(t.Dim).Set(t);\n        }\n\n        public static Tensor<T> Create<T1>(ITensor<T1> t, Func<T1, T> fun)\n        {\n            return new Tensor<T>(t.Dim).Set(t, fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor by applying a function to each element of the\n        /// supplied tensor.\n        /// </summary>\n        static Tensor<T> Create<T1>(Tensor<T1> t1, Func<T1, T> fun)\n        {\n            return new Tensor<T>(t1.L).Set(t1, fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor by applying a function to each corresponding\n        /// pair of elements of the two supplied tensors.\n        /// </summary>\n        static Tensor<T> Create<T1, T2>(Tensor<T1> t1, Tensor<T2> t2, Func<T1, T2, T> fun)\n        {\n            return new Tensor<T>(t1.L).Set(t1, t2, fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor by applying a function to each corresponding\n        /// triple of elements of the three supplied tensors.\n        /// </summary>\n        static Tensor<T> Create<T1, T2, T3>(Tensor<T1> t1, Tensor<T2> t2, Tensor<T3> t3, Func<T1, T2, T3, T> fun)\n        {\n            return new Tensor<T>(t1.L).Set(t1, t2, t3, fun);\n        }\n        #endregion\n\n        #region ITensor\n\n        public readonly long[] Dim { get { return m_size; } }\n\n        public readonly object GetValue(params long[] v)\n        {\n            return (object)this[v];\n        }\n\n        public void SetValue(object value, params long[] v)\n        {\n            this[v] = (T)value;\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Symmetric operations with a scalar or non-tensor result.\n    /// </summary>\n    public static partial class Tensor\n    {\n        #region Scalar Functions\n\n        public static Ts InnerProduct<T1, T2, Tm, Ts>(\n                Tensor<T1> t1, Tensor<T2> t2, Func<T1, T2, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun\n                )\n        {\n            Ts result = bias;\n            var ve1 = t1.Init(); var ve2 = t2.Init();\n            long i1 = t1.Origin, i2 = t2.Origin;\n            for (long ee1 = ve1[t1.R - 1]; i1 != ee1;\n                      i1 = t1.Next(i1, ref ve1), i2 = t2.Next(i2, ref ve2))\n            {\n                for (long e1 = ve1[0], d1 = t1.D[0], d2 = t2.D[0];\n                          i1 != e1; i1 += d1, i2 += d2)\n                    result = sumFun(result, mulFun(t1.Data[i1], t2.Data[i2]));\n            }\n            return result;\n        }\n\n        #endregion    \n    }\n\n    public partial struct Matrix<Td>\n    {\n        public readonly TRes Sample4<T1, TRes>(\n                long d0, Tup4<long> d1, Tup4<T1> w,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, TRes> smp) =>\n            smp(Data[d0 + d1.E0], Data[d0 + d1.E1],Data[d0 + d1.E2], Data[d0 + d1.E3], ref w);\n    }\n\n    public partial struct Matrix<Td, Tv>\n    {\n\n        public readonly TRes Sample4<T1, TRes>(\n                long d0, Tup4<long> d1, Tup4<T1> w,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, TRes> smp) =>\n            smp(Getter(Data, d0 + d1.E0), Getter(Data, d0 + d1.E1),\n                Getter(Data, d0 + d1.E2), Getter(Data, d0 + d1.E3), ref w);\n\n\n        public readonly void SetScaled16InDevelopment<T1, T2, T3>(Matrix<Td, Tv> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, Tv> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            var dxa = new Tup4<long>[SX];\n            var wxa = new Tup4<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi; dx.E3 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n\n            var mat = new Matrix<T3>(SX, sourceMat.SY);\n\n            {\n                var srcdy = sourceMat.DY;\n                var data = mat.Data;\n                long i = mat.FirstIndex;\n                long ys = mat.Info.DSY, yj = mat.Info.JY;\n                long xs = mat.Info.SX;\n                for (long ye = i + ys, y = FY, dy = sourceMat.Origin; i != ye; i += yj, y++, dy += srcdy)\n                    for (long xe = i + xs, x = FX; i != xe; i++, x++)\n                        data[i] = sourceMat.Sample4(dy, dxa[x], wxa[x], xsmp);\n            }\n\n            var dya = new Tup4<long>[SY];\n            var wya = new Tup4<T2>[SY];\n            long fy = mat.FY, ey = mat.EY, dy1 = mat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = yi * dy1; dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi; dy.E3 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            {\n                var matdx = mat.DX;\n                var data = Data;\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                    {\n                        for (long xe = i + xs, x = FX, dx = 0; i != xe; i++, x++, dx += matdx)\n                        {\n                            Setter(data, i, mat.Sample4(dx, dya[y], wya[y], ysmp));\n                        }\n                    }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs, x = FX, dx = 0; i != xe; i += xj, x++, dx += matdx)\n                    {\n                        for (long ye = i + ys, y = FY; i != ye; i++, y++)\n                        {\n                            Setter(data, i, mat.Sample4(dx, dya[y], wya[y], ysmp));\n                        }\n                    }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                    {\n                        for (long xe = i + xs, x = FX, dx = 0; i != xe; i += xj, x++, dx += matdx)\n                        {\n                            Setter(data, i, mat.Sample4(dx, dya[y], wya[y], ysmp));\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/TensorExtensions.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Wrappers for the best (fastest) available implementation of the respective tensor operation.\n    /// </summary>\n    public static partial class TensorExtensions\n    {\n        #region Conversions (Matrix, Volume) to PixImage<T>\n\n        public static PixImage<T> ToPixImage<T>(this Matrix<T> matrix)\n        {\n            return matrix.AsVolume().ToPixImage();\n        }\n\n        public static PixImage<T> ToPixImage<T>(this Volume<T> volume)\n        {\n            return new PixImage<T>(volume.ToImage());\n        }\n\n        public static PixImage<T> ToPixImage<T>(this Volume<T> volume, Col.Format format)\n        {\n            var ch = format.ChannelCount();\n            if (ch > volume.Size.Z)\n                throw new ArgumentException(\"volume has not enough channels for requested format\");\n            if (ch < volume.Size.Z)\n                volume = volume.SubVolume(V3l.Zero, new V3l(volume.SX, volume.SY, ch)); \n            return new PixImage<T>(format, volume.ToImage());\n        }\n\n        public static PixImage<T> ToPixImage<T>(this Matrix<C3b> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Size);\n            pixImage.GetMatrix<C3b>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this Matrix<C3us> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Size);\n            pixImage.GetMatrix<C3us>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this Matrix<C3f> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Size);\n            pixImage.GetMatrix<C3f>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this Matrix<C4b> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Size);\n            pixImage.GetMatrix<C4b>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this Matrix<C4us> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Size);\n            pixImage.GetMatrix<C4us>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this Matrix<C4f> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Size);\n            pixImage.GetMatrix<C4f>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T, TMatrixData>(this Matrix<TMatrixData, C3b> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Size);\n            pixImage.GetMatrix<C3b>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T, TMatrixData>(this Matrix<TMatrixData, C3us> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Size);\n            pixImage.GetMatrix<C3us>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T, TMatrixData>(this Matrix<TMatrixData, C3f> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Size);\n            pixImage.GetMatrix<C3f>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T, TMatrixData>(this Matrix<TMatrixData, C4b> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Size);\n            pixImage.GetMatrix<C4b>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T, TMatrixData>(this Matrix<TMatrixData, C4us> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Size);\n            pixImage.GetMatrix<C4us>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T, TMatrixData>(this Matrix<TMatrixData, C4f> matrix)\n        {\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Size);\n            pixImage.GetMatrix<C4f>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this IMatrix<C3b> matrix)\n        {\n            if (matrix is Matrix<byte, C3b>)\n                return ((Matrix<byte, C3b>)matrix).ToPixImage<T, byte>(); ;\n\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Dim);\n            pixImage.GetMatrix<C3b>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this IMatrix<C3us> matrix)\n        {\n            if (matrix is Matrix<ushort, C3us>)\n                return ((Matrix<ushort, C3us>)matrix).ToPixImage<T, ushort>(); ;\n\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Dim);\n            pixImage.GetMatrix<C3us>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this IMatrix<C3f> matrix)\n        {\n            if (matrix is Matrix<float, C3f>)\n                return ((Matrix<float, C3f>)matrix).ToPixImage<T, float>(); ;\n\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 3), (V2i)matrix.Dim);\n            pixImage.GetMatrix<C3f>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this IMatrix<C4b> matrix)\n        {\n            if (matrix is Matrix<byte, C4b>)\n                return ((Matrix<byte, C4b>)matrix).ToPixImage<T, byte>(); ;\n\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Dim);\n            pixImage.GetMatrix<C4b>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this IMatrix<C4us> matrix)\n        {\n            if (matrix is Matrix<ushort, C4us>)\n                return ((Matrix<ushort, C4us>)matrix).ToPixImage<T, ushort>(); ;\n\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Dim);\n            pixImage.GetMatrix<C4us>().Set(matrix);\n            return pixImage;\n        }\n\n        public static PixImage<T> ToPixImage<T>(this IMatrix<C4f> matrix)\n        {\n            if (matrix is Matrix<float, C4f>)\n                return ((Matrix<float, C4f>)matrix).ToPixImage<T, float>(); ;\n\n            var pixImage = new PixImage<T>(Col.FormatDefaultOf(typeof(T), 4), (V2i)matrix.Dim);\n            pixImage.GetMatrix<C4f>().Set(matrix);\n            return pixImage;\n        }\n\n        #endregion\n\n        #region Get/Set Matrix Rows/Cols\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Vector<T> GetRow<T>(this Matrix<T> m, int i)\n        {\n            return m.SubXVector(i);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Vector<T> GetCol<T>(this Matrix<T> m, int i)\n        {\n            return m.SubYVector(i);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void SetRow<T>(this Matrix<T> m, int i, ref Vector<T> data)\n        {\n            m.SubXVector(i).Set(data);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static void SetCol<T>(this Matrix<T> m, int i, ref Vector<T> data)\n        {\n            m.SubYVector(i).Set(data);\n        }\n\n        #endregion\n\n        #region Transformed (Matrix, Volume) [CSharp]\n\n        public static MatrixInfo Transformed(this MatrixInfo info, ImageTrafo trafo)\n        {\n            long sx = info.Size.X, sy = info.Size.Y;\n            long dx = info.Delta.X, dy = info.Delta.Y;\n            switch (trafo)\n            {\n                case ImageTrafo.Identity: return info;\n                case ImageTrafo.Rot90: return info.SubMatrix(sx - 1, 0, sy, sx, dy, -dx);\n                case ImageTrafo.Rot180: return info.SubMatrix(sx - 1, sy - 1, sx, sy, -dx, -dy);\n                case ImageTrafo.Rot270: return info.SubMatrix(0, sy - 1, sy, sx, -dy, dx);\n                case ImageTrafo.MirrorX: return info.SubMatrix(sx - 1, 0, sx, sy, -dx, dy);\n                case ImageTrafo.Transpose: return info.SubMatrix(0, 0, sy, sx, dy, dx);\n                case ImageTrafo.MirrorY: return info.SubMatrix(0, sy - 1, sx, sy, dx, -dy);\n                case ImageTrafo.Transverse: return info.SubMatrix(sx - 1, sy - 1, sy, sx, -dy, -dx);\n            }\n            throw new ArgumentException();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Matrix<T> Transformed<T>(this Matrix<T> matrix, ImageTrafo trafo)\n            => new Matrix<T>(matrix.Data, matrix.Info.Transformed(trafo));\n\n        public static VolumeInfo Transformed(this VolumeInfo info, ImageTrafo trafo)\n        {\n            long sx = info.Size.X, sy = info.Size.Y, sz = info.Size.Z;\n            long dx = info.Delta.X, dy = info.Delta.Y, dz = info.Delta.Z;\n            switch (trafo)\n            {\n                case ImageTrafo.Identity: return info;\n                case ImageTrafo.Rot90: return info.SubVolume(sx - 1, 0, 0, sy, sx, sz, dy, -dx, dz);\n                case ImageTrafo.Rot180: return info.SubVolume(sx - 1, sy - 1, 0, sx, sy, sz, -dx, -dy, dz);\n                case ImageTrafo.Rot270: return info.SubVolume(0, sy - 1, 0, sy, sx, sz, -dy, dx, dz);\n                case ImageTrafo.MirrorX: return info.SubVolume(sx - 1, 0, 0, sx, sy, sz, -dx, dy, dz);\n                case ImageTrafo.Transpose: return info.SubVolume(0, 0, 0, sy, sx, sz, dy, dx, dz);\n                case ImageTrafo.MirrorY: return info.SubVolume(0, sy - 1, 0, sx, sy, sz, dx, -dy, dz);\n                case ImageTrafo.Transverse: return info.SubVolume(sx - 1, sy - 1, 0, sy, sx, sz, -dy, -dx, dz);\n            }\n            throw new ArgumentException();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> Transformed<T>(this Volume<T> volume, ImageTrafo trafo)\n            => new Volume<T>(volume.Data, volume.Info.Transformed(trafo));\n\n        #endregion\n\n        #region Scaling\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static Half LerpHalf(double t, Half x, Half y) => Fun.Lerp((Half)t, x, y);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static float LerpFloat(double t, float x, float y) => Fun.Lerp((float)t, x, y);\n\n        private static readonly Dictionary<Type, Action<object, object>> scaleNearestTable =\n            new Dictionary<Type, Action<object, object>>()\n            {\n                {typeof(byte),   (src, dst) => ((Matrix<byte>)dst).SetScaledNearest((Matrix<byte>)src)},\n                {typeof(ushort), (src, dst) => ((Matrix<ushort>)dst).SetScaledNearest((Matrix<ushort>)src)},\n                {typeof(uint),   (src, dst) => ((Matrix<uint>)dst).SetScaledNearest((Matrix<uint>)src)},\n                {typeof(Half),   (src, dst) => ((Matrix<Half>)dst).SetScaledNearest((Matrix<Half>)src)},\n                {typeof(float),  (src, dst) => ((Matrix<float>)dst).SetScaledNearest((Matrix<float>)src)},\n                {typeof(double), (src, dst) => ((Matrix<double>)dst).SetScaledNearest((Matrix<double>)src)}\n            };\n\n        private static readonly Dictionary<Type, Action<object, object>> scaleLinearTable =\n            new Dictionary<Type, Action<object, object>>()\n            {\n                {typeof(byte),   (src, dst) => ((Matrix<byte>)dst).SetScaledLinear((Matrix<byte>)src, Fun.Lerp, Fun.Lerp)},\n                {typeof(ushort), (src, dst) => ((Matrix<ushort>)dst).SetScaledLinear((Matrix<ushort>)src, Fun.Lerp, Fun.Lerp)},\n                {typeof(uint),   (src, dst) => ((Matrix<uint>)dst).SetScaledLinear((Matrix<uint>)src, Fun.Lerp, Fun.Lerp)},\n                {typeof(Half),   (src, dst) => ((Matrix<Half>)dst).SetScaledLinear((Matrix<Half>)src, LerpHalf, LerpHalf)},\n                {typeof(float),  (src, dst) => ((Matrix<float>)dst).SetScaledLinear((Matrix<float>)src, LerpFloat, LerpFloat)},\n                {typeof(double), (src, dst) => ((Matrix<double>)dst).SetScaledLinear((Matrix<double>)src, Fun.Lerp, Fun.Lerp)}\n            };\n\n        private static readonly Dictionary<Type, Action<object, object>> scaleCubicTable =\n            new Dictionary<Type, Action<object, object>>()\n            {\n                {typeof(byte),   (src, dst) => ((Matrix<byte>)dst).SetScaledCubic((Matrix<byte>)src)},\n                {typeof(ushort), (src, dst) => ((Matrix<ushort>)dst).SetScaledCubic((Matrix<ushort>)src)},\n                {typeof(uint),   (src, dst) => ((Matrix<uint>)dst).SetScaledCubic((Matrix<uint>)src)},\n                {typeof(Half),   (src, dst) => ((Matrix<Half>)dst).SetScaledCubic((Matrix<Half>)src)},\n                {typeof(float),  (src, dst) => ((Matrix<float>)dst).SetScaledCubic((Matrix<float>)src)},\n                {typeof(double), (src, dst) => ((Matrix<double>)dst).SetScaledCubic((Matrix<double>)src)}\n            };\n\n        private static readonly Dictionary<Type, Action<object, object>> scaleLanczosTable =\n            new Dictionary<Type, Action<object, object>>()\n            {\n                {typeof(byte),   (src, dst) => ((Matrix<byte>)dst).SetScaledLanczos((Matrix<byte>)src)},\n                {typeof(ushort), (src, dst) => ((Matrix<ushort>)dst).SetScaledLanczos((Matrix<ushort>)src)},\n                {typeof(uint),   (src, dst) => ((Matrix<uint>)dst).SetScaledLanczos((Matrix<uint>)src)},\n                {typeof(Half),   (src, dst) => ((Matrix<Half>)dst).SetScaledLanczos((Matrix<Half>)src)},\n                {typeof(float),  (src, dst) => ((Matrix<float>)dst).SetScaledLanczos((Matrix<float>)src)},\n                {typeof(double), (src, dst) => ((Matrix<double>)dst).SetScaledLanczos((Matrix<double>)src)}\n            };\n\n        private static void SetScaled<T>(Dictionary<Type, Action<object, object>> table, Matrix<T> src, Matrix<T> dst)\n        {\n            if (table.TryGetValue(typeof(T), out var setScaled))\n            {\n                setScaled(src, dst);\n            }\n            else\n            {\n                throw new InvalidOperationException($\"Cannot invoke Scaled() for Matrix<{typeof(T).Name}>\");\n            }\n        }\n\n        public static Volume<T> Scaled<T>(this Volume<T> source, V2d scaleFactor, ImageInterpolation interpolation)\n        {\n            if (scaleFactor.AnySmaller(0.0))\n            {\n                throw new ArgumentException(\"Scale factor cannot be negative\");\n            }\n\n            var table =\n                interpolation switch\n                {\n                    ImageInterpolation.Near => scaleNearestTable,\n                    ImageInterpolation.Linear => scaleLinearTable,\n                    ImageInterpolation.Cubic => scaleCubicTable,\n                    ImageInterpolation.Lanczos => scaleLanczosTable,\n                    _ => throw new NotImplementedException($\"{interpolation} filter not supported.\")\n                };\n\n            var size = (V2d.Half + scaleFactor * (V2d)source.Size.XY).ToV2l();\n            var channels = source.Size.Z;\n            var target = ImageTensors.CreateImageVolume<T>(new V3l(size.XY, channels));\n\n            for (int c = 0; c < channels; c++)\n            {\n                SetScaled(table, source.SubXYMatrixWindow(c), target.SubXYMatrixWindow(c));\n            }\n\n            return target;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/TensorExtensions_auto.cs",
    "content": "using System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Wrappers for the best (fastest) available implementation of the respective tensor operation.\n    /// </summary>\n    public static partial class TensorExtensions\n    {\n        #region Image Scaling\n\n        public static void SetScaledNearest(this Matrix<byte> targetMat, Matrix<byte> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<byte> targetMat, Matrix<byte> sourceMat,\n                                           Func<double, byte, byte, T1> xinterpolator,\n                                           Func<double, T1, T1, byte> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<byte> targetMat, Matrix<byte> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<byte> targetMat, Matrix<byte> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<byte> targetMat, Matrix<byte> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Fun.LinComRawF, Fun.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  Col.ByteInFloatToByteClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<byte> targetMat, Matrix<byte> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<byte> targetMat, Matrix<byte> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<byte> targetMat, Matrix<byte> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Fun.LinComRawF, Fun.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  Col.ByteInFloatToByteClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<ushort> targetMat, Matrix<ushort> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<ushort> targetMat, Matrix<ushort> sourceMat,\n                                           Func<double, ushort, ushort, T1> xinterpolator,\n                                           Func<double, T1, T1, ushort> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<ushort> targetMat, Matrix<ushort> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<ushort> targetMat, Matrix<ushort> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<ushort> targetMat, Matrix<ushort> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Fun.LinComRawF, Fun.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  Col.UShortInFloatToUShortClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<ushort> targetMat, Matrix<ushort> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<ushort> targetMat, Matrix<ushort> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<ushort> targetMat, Matrix<ushort> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Fun.LinComRawF, Fun.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  Col.UShortInFloatToUShortClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<uint> targetMat, Matrix<uint> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<uint> targetMat, Matrix<uint> sourceMat,\n                                           Func<double, uint, uint, T1> xinterpolator,\n                                           Func<double, T1, T1, uint> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<uint> targetMat, Matrix<uint> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4d(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<uint> targetMat, Matrix<uint> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3d);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<uint> targetMat, Matrix<uint> sourceMat,\n                                          Func<double, Tup4<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Fun.LinComRawD, Fun.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  Col.UIntInDoubleToUIntClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<uint> targetMat, Matrix<uint> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5d);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<uint> targetMat, Matrix<uint> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3d);\n        }\n\n        public static void SetScaledOrder5(this Matrix<uint> targetMat, Matrix<uint> sourceMat,\n                                           Func<double, Tup6<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Fun.LinComRawD, Fun.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  Col.UIntInDoubleToUIntClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<Half> targetMat, Matrix<Half> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<Half> targetMat, Matrix<Half> sourceMat,\n                                           Func<double, Half, Half, T1> xinterpolator,\n                                           Func<double, T1, T1, Half> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<Half> targetMat, Matrix<Half> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4h(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<Half> targetMat, Matrix<Half> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3h);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<Half> targetMat, Matrix<Half> sourceMat,\n                                          Func<double, Tup4<Half>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Fun.LinCom, Fun.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<Half> targetMat, Matrix<Half> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5h);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<Half> targetMat, Matrix<Half> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3h);\n        }\n\n        public static void SetScaledOrder5(this Matrix<Half> targetMat, Matrix<Half> sourceMat,\n                                           Func<double, Tup6<Half>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Fun.LinCom, Fun.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<float> targetMat, Matrix<float> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<float> targetMat, Matrix<float> sourceMat,\n                                           Func<double, float, float, T1> xinterpolator,\n                                           Func<double, T1, T1, float> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<float> targetMat, Matrix<float> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<float> targetMat, Matrix<float> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<float> targetMat, Matrix<float> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Fun.LinCom, Fun.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<float> targetMat, Matrix<float> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<float> targetMat, Matrix<float> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<float> targetMat, Matrix<float> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Fun.LinCom, Fun.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<double> targetMat, Matrix<double> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<double> targetMat, Matrix<double> sourceMat,\n                                           Func<double, double, double, T1> xinterpolator,\n                                           Func<double, T1, T1, double> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<double> targetMat, Matrix<double> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4d(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<double> targetMat, Matrix<double> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3d);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<double> targetMat, Matrix<double> sourceMat,\n                                          Func<double, Tup4<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Fun.LinCom, Fun.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<double> targetMat, Matrix<double> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5d);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<double> targetMat, Matrix<double> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3d);\n        }\n\n        public static void SetScaledOrder5(this Matrix<double> targetMat, Matrix<double> sourceMat,\n                                           Func<double, Tup6<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Fun.LinCom, Fun.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<byte, C3b> targetMat, Matrix<byte, C3b> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<byte, C3b> targetMat, Matrix<byte, C3b> sourceMat,\n                                           Func<double, C3b, C3b, T1> xinterpolator,\n                                           Func<double, T1, T1, C3b> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<byte, C3b> targetMat, Matrix<byte, C3b> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<byte, C3b> targetMat, Matrix<byte, C3b> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<byte, C3b> targetMat, Matrix<byte, C3b> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinComRawF, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  col => col.Map(Col.ByteInFloatToByteClamped));\n        }\n\n        public static void SetScaledBSpline5(this Matrix<byte, C3b> targetMat, Matrix<byte, C3b> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<byte, C3b> targetMat, Matrix<byte, C3b> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<byte, C3b> targetMat, Matrix<byte, C3b> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinComRawF, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  col => col.Map(Col.ByteInFloatToByteClamped));\n        }\n\n        public static void SetScaledNearest(this Matrix<ushort, C3us> targetMat, Matrix<ushort, C3us> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<ushort, C3us> targetMat, Matrix<ushort, C3us> sourceMat,\n                                           Func<double, C3us, C3us, T1> xinterpolator,\n                                           Func<double, T1, T1, C3us> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<ushort, C3us> targetMat, Matrix<ushort, C3us> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<ushort, C3us> targetMat, Matrix<ushort, C3us> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<ushort, C3us> targetMat, Matrix<ushort, C3us> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinComRawF, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  col => col.Map(Col.UShortInFloatToUShortClamped));\n        }\n\n        public static void SetScaledBSpline5(this Matrix<ushort, C3us> targetMat, Matrix<ushort, C3us> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<ushort, C3us> targetMat, Matrix<ushort, C3us> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<ushort, C3us> targetMat, Matrix<ushort, C3us> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinComRawF, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  col => col.Map(Col.UShortInFloatToUShortClamped));\n        }\n\n        public static void SetScaledNearest(this Matrix<uint, C3ui> targetMat, Matrix<uint, C3ui> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<uint, C3ui> targetMat, Matrix<uint, C3ui> sourceMat,\n                                           Func<double, C3ui, C3ui, T1> xinterpolator,\n                                           Func<double, T1, T1, C3ui> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<uint, C3ui> targetMat, Matrix<uint, C3ui> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4d(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<uint, C3ui> targetMat, Matrix<uint, C3ui> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3d);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<uint, C3ui> targetMat, Matrix<uint, C3ui> sourceMat,\n                                          Func<double, Tup4<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinComRawD, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  col => col.Map(Col.UIntInDoubleToUIntClamped));\n        }\n\n        public static void SetScaledBSpline5(this Matrix<uint, C3ui> targetMat, Matrix<uint, C3ui> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5d);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<uint, C3ui> targetMat, Matrix<uint, C3ui> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3d);\n        }\n\n        public static void SetScaledOrder5(this Matrix<uint, C3ui> targetMat, Matrix<uint, C3ui> sourceMat,\n                                           Func<double, Tup6<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinComRawD, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  col => col.Map(Col.UIntInDoubleToUIntClamped));\n        }\n\n        public static void SetScaledNearest(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat,\n                                           Func<double, C3f, C3f, T1> xinterpolator,\n                                           Func<double, T1, T1, C3f> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinCom, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinCom, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<double, C3d> targetMat, Matrix<double, C3d> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<double, C3d> targetMat, Matrix<double, C3d> sourceMat,\n                                           Func<double, C3d, C3d, T1> xinterpolator,\n                                           Func<double, T1, T1, C3d> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<double, C3d> targetMat, Matrix<double, C3d> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4d(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<double, C3d> targetMat, Matrix<double, C3d> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3d);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<double, C3d> targetMat, Matrix<double, C3d> sourceMat,\n                                          Func<double, Tup4<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinCom, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<double, C3d> targetMat, Matrix<double, C3d> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5d);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<double, C3d> targetMat, Matrix<double, C3d> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3d);\n        }\n\n        public static void SetScaledOrder5(this Matrix<double, C3d> targetMat, Matrix<double, C3d> sourceMat,\n                                           Func<double, Tup6<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinCom, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<byte, C4b> targetMat, Matrix<byte, C4b> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<byte, C4b> targetMat, Matrix<byte, C4b> sourceMat,\n                                           Func<double, C4b, C4b, T1> xinterpolator,\n                                           Func<double, T1, T1, C4b> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<byte, C4b> targetMat, Matrix<byte, C4b> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<byte, C4b> targetMat, Matrix<byte, C4b> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<byte, C4b> targetMat, Matrix<byte, C4b> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinComRawF, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  col => col.Map(Col.ByteInFloatToByteClamped));\n        }\n\n        public static void SetScaledBSpline5(this Matrix<byte, C4b> targetMat, Matrix<byte, C4b> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<byte, C4b> targetMat, Matrix<byte, C4b> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<byte, C4b> targetMat, Matrix<byte, C4b> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinComRawF, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  col => col.Map(Col.ByteInFloatToByteClamped));\n        }\n\n        public static void SetScaledNearest(this Matrix<ushort, C4us> targetMat, Matrix<ushort, C4us> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<ushort, C4us> targetMat, Matrix<ushort, C4us> sourceMat,\n                                           Func<double, C4us, C4us, T1> xinterpolator,\n                                           Func<double, T1, T1, C4us> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<ushort, C4us> targetMat, Matrix<ushort, C4us> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<ushort, C4us> targetMat, Matrix<ushort, C4us> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<ushort, C4us> targetMat, Matrix<ushort, C4us> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinComRawF, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  col => col.Map(Col.UShortInFloatToUShortClamped));\n        }\n\n        public static void SetScaledBSpline5(this Matrix<ushort, C4us> targetMat, Matrix<ushort, C4us> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<ushort, C4us> targetMat, Matrix<ushort, C4us> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<ushort, C4us> targetMat, Matrix<ushort, C4us> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinComRawF, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  col => col.Map(Col.UShortInFloatToUShortClamped));\n        }\n\n        public static void SetScaledNearest(this Matrix<uint, C4ui> targetMat, Matrix<uint, C4ui> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<uint, C4ui> targetMat, Matrix<uint, C4ui> sourceMat,\n                                           Func<double, C4ui, C4ui, T1> xinterpolator,\n                                           Func<double, T1, T1, C4ui> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<uint, C4ui> targetMat, Matrix<uint, C4ui> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4d(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<uint, C4ui> targetMat, Matrix<uint, C4ui> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3d);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<uint, C4ui> targetMat, Matrix<uint, C4ui> sourceMat,\n                                          Func<double, Tup4<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinComRawD, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped,\n                                  col => col.Map(Col.UIntInDoubleToUIntClamped));\n        }\n\n        public static void SetScaledBSpline5(this Matrix<uint, C4ui> targetMat, Matrix<uint, C4ui> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5d);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<uint, C4ui> targetMat, Matrix<uint, C4ui> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3d);\n        }\n\n        public static void SetScaledOrder5(this Matrix<uint, C4ui> targetMat, Matrix<uint, C4ui> sourceMat,\n                                           Func<double, Tup6<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinComRawD, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped,\n                                  col => col.Map(Col.UIntInDoubleToUIntClamped));\n        }\n\n        public static void SetScaledNearest(this Matrix<float, C4f> targetMat, Matrix<float, C4f> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<float, C4f> targetMat, Matrix<float, C4f> sourceMat,\n                                           Func<double, C4f, C4f, T1> xinterpolator,\n                                           Func<double, T1, T1, C4f> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<float, C4f> targetMat, Matrix<float, C4f> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<float, C4f> targetMat, Matrix<float, C4f> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3f);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<float, C4f> targetMat, Matrix<float, C4f> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinCom, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<float, C4f> targetMat, Matrix<float, C4f> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5f);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<float, C4f> targetMat, Matrix<float, C4f> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3f);\n        }\n\n        public static void SetScaledOrder5(this Matrix<float, C4f> targetMat, Matrix<float, C4f> sourceMat,\n                                           Func<double, Tup6<float>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinCom, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public static void SetScaledNearest(this Matrix<double, C4d> targetMat, Matrix<double, C4d> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<double, C4d> targetMat, Matrix<double, C4d> sourceMat,\n                                           Func<double, C4d, C4d, T1> xinterpolator,\n                                           Func<double, T1, T1, C4d> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<double, C4d> targetMat, Matrix<double, C4d> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4d(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<double, C4d> targetMat, Matrix<double, C4d> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3d);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<double, C4d> targetMat, Matrix<double, C4d> sourceMat,\n                                          Func<double, Tup4<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, Col.LinCom, Col.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<double, C4d> targetMat, Matrix<double, C4d> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5d);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<double, C4d> targetMat, Matrix<double, C4d> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3d);\n        }\n\n        public static void SetScaledOrder5(this Matrix<double, C4d> targetMat, Matrix<double, C4d> sourceMat,\n                                           Func<double, Tup6<double>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, Col.LinCom, Col.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        #endregion\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/TensorExtensions_template.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Wrappers for the best (fastest) available implementation of the respective tensor operation.\n    /// </summary>\n    public static partial class TensorExtensions\n    {\n        #region Image Scaling\n\n        //# var intConfigs = new []\n        //# {\n        //#     Tup.Create(Meta.ByteType,    Meta.FloatType,  \"Fun\",  \"Fun\"),\n        //#     Tup.Create(Meta.UShortType,  Meta.FloatType,  \"Fun\",  \"Fun\"),\n        //#     Tup.Create(Meta.UIntType,    Meta.DoubleType, \"Fun\",  \"Fun\"),\n        //#     Tup.Create(Meta.HalfType,    Meta.HalfType,   \"Fun\",  \"Fun\"),\n        //#     Tup.Create(Meta.FloatType,   Meta.FloatType,  \"Fun\",  \"Fun\"),\n        //#     Tup.Create(Meta.DoubleType,  Meta.DoubleType, \"Fun\",  \"Fun\"),\n        //#\n        //#     Tup.Create(Meta.ByteType,    Meta.FloatType,  \"C3b\",  \"C3f\"),\n        //#     Tup.Create(Meta.UShortType,  Meta.FloatType,  \"C3us\", \"C3f\"),\n        //#     Tup.Create(Meta.UIntType,    Meta.DoubleType, \"C3ui\", \"C3d\"),\n        //#     Tup.Create(Meta.FloatType,   Meta.FloatType,  \"C3f\",  \"C3f\"),\n        //#     Tup.Create(Meta.DoubleType,  Meta.DoubleType, \"C3d\",  \"C3d\"),\n        //#\n        //#     Tup.Create(Meta.ByteType,    Meta.FloatType,  \"C4b\",  \"C4f\"),\n        //#     Tup.Create(Meta.UShortType,  Meta.FloatType,  \"C4us\", \"C4f\"),\n        //#     Tup.Create(Meta.UIntType,    Meta.DoubleType, \"C4ui\", \"C4d\"),\n        //#     Tup.Create(Meta.FloatType,   Meta.FloatType,  \"C4f\",  \"C4f\"),\n        //#     Tup.Create(Meta.DoubleType,  Meta.DoubleType, \"C4d\",  \"C4d\"),\n        //# };\n        //# intConfigs.ForEach((dtype, ftype, ct, fct) => {\n        //#     var isReal = dtype.IsReal;\n        //#     var fun = ct == \"Fun\" ? ct : \"Col\";\n        //#     var clampVal = !isReal && ct == \"Fun\";\n        //#     var clampMap = !isReal && ct != \"Fun\";\n        //#     var dt = dtype.Name;\n        //#     var dtn = dtype.Caps;\n        //#     var ft = ftype.Name;\n        //#     var ftn = ftype.Caps;\n        //#     var ftc = ftype.Char;\n        //#     var rfct = isReal ? \"\" : \"Raw\" + ftc.ToUpper();\n        //#     var dtct = ct == \"Fun\" ? dt : dt + \", \" + ct;\n        //#     var it = ct == \"Fun\" ? dt : ct;\n        public static void SetScaledNearest(this Matrix<__dtct__> targetMat, Matrix<__dtct__> sourceMat)\n        {\n            targetMat.SetScaledLinear(sourceMat, (x, a, b) => x < 0.5 ? a : b,\n                                                 (x, a, b) => x < 0.5 ? a : b);\n        }\n\n        /// <summary>\n        /// Use supplied linear interpolators in x and y to scale the source matrix into the target\n        /// matrix.\n        /// </summary>\n        public static void SetScaledLinear<T1>(this Matrix<__dtct__> targetMat, Matrix<__dtct__> sourceMat,\n                                           Func<double, __it__, __it__, T1> xinterpolator,\n                                           Func<double, T1, T1, __it__> yinterpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled4(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 xinterpolator, yinterpolator,\n                                 Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Use Cubic Spline interpolation to scale the source matrix into the target matrix.\n        /// The supplied parameter selects the spline to use. The default value of -0.5 generates\n        /// Hermite Splines. If you call this repeatedly with the same selection parameter,\n        /// build the cubic weighting function with 'Fun.CreateCubicTup4f(par)' and use the\n        /// result as a paramter to the function call.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<__dtct__> targetMat, Matrix<__dtct__> sourceMat,\n                                            double par = -0.5)\n        {\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4__ftc__(par);\n            targetMat.SetScaledCubic(sourceMat, hermiteSpline);\n        }\n\n        public static void SetScaledBSpline3(this Matrix<__dtct__> targetMat, Matrix<__dtct__> sourceMat)\n        {\n            targetMat.SetScaledCubic(sourceMat, Fun.BSpline3__ftc__);\n        }\n\n        /// <summary>\n        /// Use a supplied cubic interpolator to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledCubic(this Matrix<__dtct__> targetMat, Matrix<__dtct__> sourceMat,\n                                          Func<double, Tup4<__ft__>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled16(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                 interpolator, interpolator, __fun__.LinCom__rfct__, __fun__.LinCom,\n                                 Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped/*#\n                                  if (clampVal) { */,\n                                  Col.__dtn__In__ftn__To__dtn__Clamped/*#\n                                  } else if (clampMap) { */,\n                                  col => col.Map(Col.__dtn__In__ftn__To__dtn__Clamped)/*# } */);\n        }\n\n        public static void SetScaledBSpline5(this Matrix<__dtct__> targetMat, Matrix<__dtct__> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.BSpline5__ftc__);\n        }\n\n        /// <summary>\n        /// Use Lanczos Interpolation to scale the source matrix into the target matrix.\n        /// </summary>\n        public static void SetScaledLanczos(this Matrix<__dtct__> targetMat, Matrix<__dtct__> sourceMat)\n        {\n            targetMat.SetScaledOrder5(sourceMat, Fun.Lanczos3__ftc__);\n        }\n\n        public static void SetScaledOrder5(this Matrix<__dtct__> targetMat, Matrix<__dtct__> sourceMat,\n                                           Func<double, Tup6<__ft__>> interpolator)\n        {\n            var scale = sourceMat.Size.ToV2d() / targetMat.Size.ToV2d();\n            targetMat.SetScaled36(sourceMat, scale.X, scale.Y, 0.5 * scale.X - 0.5, 0.5 * scale.Y - 0.5,\n                                  interpolator, interpolator, __fun__.LinCom__rfct__, __fun__.LinCom,\n                                  Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped/*#\n                                  if (clampVal) { */,\n                                  Col.__dtn__In__ftn__To__dtn__Clamped/*#\n                                  } else if (clampMap) { */,\n                                  col => col.Map(Col.__dtn__In__ftn__To__dtn__Clamped)/*# } */);\n        }\n\n        //# }); // configs\n        #endregion\n    }\n}"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/TensorMathExt_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static class Vector\n    {\n        /// <summary>\n        /// Vector constructor from a given array that does not require to write generic type\n        /// </summary>\n        public static Vector<T> Create<T>(T[] array)\n        {\n            return new Vector<T>(array);\n        }\n    }\n\n    public static class Matrix\n    {\n        /// <summary>\n        /// Matrix constructor from a given array that does not require to write generic type.\n        /// </summary>\n        public static Matrix<T> Create<T>(T[] array, int sx, int sy)\n        {\n            if (array.Length != sx * sy) throw new ArgumentException(\"Data array of matrix does not match given size\");\n            return new Matrix<T>(array, sx, sy);\n        }\n\n        /// <summary>\n        /// Matrix constructor from a given array that does not require to write generic type.\n        /// </summary>\n        public static Matrix<T> Create<T>(T[] array, long sx, long sy)\n        {\n            if (array.Length != sx * sy) throw new ArgumentException(\"Data array of matrix does not match given size\");\n            return new Matrix<T>(array, sx, sy);\n        }\n    }\n\n    public static class TensorMathExt\n    {\n        #region Vector Extensions\n\n        /// <summary>\n        /// Calculates the dot product of two vectors:\n        /// a dot b = Sum(a0*b0 + a1*b1 + ... aN*bN)\n        /// </summary>\n        public static float DotProduct(this Vector<float> v0, Vector<float> v1)\n        {\n            float result = 0.0f;\n            float[] a0 = v0.Data, a1 = v1.Data;\n            for (long i0 = v0.Origin, i1 = v1.Origin, e0 = i0 + v0.DSX, d0 = v0.D, d1 = v1.D;\n                i0 != e0; i0 += d0, i1 += d1)\n                result += a0[i0] * a1[i1];\n            return result;\n        }\n\n        /// <summary>\n        /// Calculates the squared norm of a vector:\n        /// ||a|| = Sum(a0*a0 + a1*a1 + ... aN*aN)\n        /// </summary>\n        public static float NormSquared(this Vector<float> v)\n        {\n            float result = 0.0f;\n            float[] a = v.Data;\n            for (long i = v.Origin, e = i + v.DSX, d = v.D; i != e; i += d)\n                result += a[i] * a[i];\n            return result;\n        }\n\n        public static float Dist1(this Vector<float> v0, Vector<float> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Abs(x1 - x0), 0.0f, (s, p) => s + p);\n\n        public static float Dist2Squared(this Vector<float> v0, Vector<float> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Square(x1 - x0), 0.0f, (s, p) => s + p);\n\n        public static float Dist2(this Vector<float> v0, Vector<float> v1)\n            => Fun.Sqrt(v0.Dist2Squared(v1));\n\n        public static float DistMax(this Vector<float> v0, Vector<float> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Abs(x1 - x0), 0.0f, Fun.Max);\n\n        public static Vector<float> Multiply(this Vector<float> a, Vector<float> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(\"Cannot multiply vectors with different lengths!\");\n\n            var result = new float[a.Dim];\n            float[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] * a1[i1];\n            return Vector.Create(result);\n        }\n\n        /// <summary>\n        /// Multiply vector a as column vector with vector b as row vector resulting a matrix [b.Dim x a.Dim]\n        /// </summary>\n        public static Matrix<float> MultiplyTransposed(this Vector<float> a, Vector<float> b)\n        {\n            var result = new float[b.Dim * a.Dim];\n            float[] a0 = a.Data, a1 = b.Data;\n            long f1 = b.Origin, e1 = f1 + b.DSX, d1 = b.D;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0)\n                for (long i1 = f1; i1 != e1; i1 += d1, ri++)\n                    result[ri] = a0[i0] * a1[i1];\n            return Matrix.Create(result, b.Dim, a.Dim);\n        }\n\n        public static Vector<float> Multiply(this Vector<float> vec, float s)\n        {\n            var result = new float[vec.Dim];\n            float[] a0 = vec.Data;\n            for (long i0 = vec.Origin, ri = 0, e0 = i0 + vec.DSX, d0 = vec.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] * s;\n            return Vector.Create(result);\n        }\n\n        public static Vector<float> Subtract(this Vector<float> a, Vector<float> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract vectors with length {0} and {1}\", a.Dim, b.Dim));\n            \n            var result = new float[a.Dim];\n            float[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] - a1[i1];\n            return Vector.Create(result);\n        }\n\n        public static Vector<float> Subtract(this Vector<float> a, float b)\n        {\n            var result = new float[a.Dim];\n            float[] a0 = a.Data;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] - b;\n            return Vector.Create(result);\n        }\n\n        public static Vector<float> Add(this Vector<float> a, Vector<float> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract vectors with length {0} and {1}\", a.Dim, b.Dim));\n\n            var result = new float[a.Dim];\n            float[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] + a1[i1];\n            return Vector.Create(result);\n        }\n\n        public static Vector<float> Add(this Vector<float> a, float b)\n        {\n            var result = new float[a.Dim];\n            float[] a0 = a.Data;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] + b;\n            return Vector.Create(result);\n        }\n\n        public static bool EqualTo(this Vector<float> a, Vector<float> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(\"Cannot compare vectors with different lengths!\");\n            bool eq = true;\n            a.ForeachCoord(crd => eq &= a[crd] == b[crd]);\n            return eq;\n        }\n\n        #endregion\n\n        #region Matrix Extensions\n\n        /// <summary>\n        /// Multiply matrix with vector as column vector. \n        /// Vector must have save length as columns of matrix.\n        /// Returns a vector with size of matrix rows.\n        /// </summary>\n        public static Vector<float> Multiply(this Matrix<float> mat, Vector<float> vec)\n        {\n            if (mat.Dim.X != vec.Dim) throw new InvalidOperationException(String.Format(\"Cannot multiply matrix {0} with vector of size {1}\", mat.Dim, vec.Dim));\n            \n            var result = new float[mat.Dim.Y];\n\n            var data0 = mat.Data; var data1 = vec.Data;\n            long my0 = mat.DY, d1 = vec.D;\n            long mf1 = vec.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n                f0 != ye; f0 += my0, e0 += my0, ri++)\n            {\n                float dot = 0.0f;\n                for (long i0 = f0, i1 = mf1; i0 != e0; i0 += d0, i1 += d1)\n                    dot += data0[i0] * data1[i1];\n\n                result[ri] = dot;\n            }\n            return Vector.Create(result);\n        }\n        \n        public static Matrix<float> Multiply(this Matrix<float> m0, Matrix<float> m1)\n        {\n            if (m0.SX != m1.SY)\n                throw new ArgumentException(\"m0.SX != m1.SY\");\n\n            var result = new Matrix<float>(m1.SX, m0.SY);\n\n            var data = result.Data; var data0 = m0.Data; var data1 = m1.Data;\n            long i = result.FirstIndex, yj = result.JY, my0 = m0.DY;\n            long xs = result.DSX, mf1 = m1.FirstIndex, xj = result.JX, mx1 = m1.DX;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DY;\n            for (long ye = i + result.DSY, f0 = m0.FirstIndex, e0 = f0 + ds0;\n                i != ye; i += yj, f0 += my0, e0 += my0)\n                for (long xe = i + xs, f1 = mf1; i != xe; i += xj, f1 += mx1)\n                {\n                    float dot = 0.0f;\n                    for (long i0 = f0, i1 = f1; i0 != e0; i0 += d0, i1 += d1)\n                        dot += data0[i0] * data1[i1];\n                    data[i] = dot;\n                }\n            return result;\n        }\n\n        public static Matrix<float> Multiply(this Matrix<float> mat, float a)\n        {\n            var result = new float[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] * a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static Matrix<float> Subtract(this Matrix<float> m0, Matrix<float> m1)\n        {\n            if (m0.Dim != m1.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract matrix A={0} and matrix B={1}\", m0.Dim, m1.Dim));\n\n            var result = new float[m0.SX * m0.SY];\n\n            var data0 = m0.Data; var data1 = m1.Data;\n            long mf0 = m0.FirstIndex, my0 = m0.DY, my1 = m1.DY;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DX;\n            for (long ye = mf0 + m0.DSY, f0 = mf0, f1 = m1.FirstIndex, ri = 0;\n                f0 != ye; f0 += my0, f1 += my1)\n                for (long xe = f0 + ds0, i0 = f0, i1 = f1; i0 != xe; i0 += d0, i1 += d1, ri++)\n                    result[ri] = data0[i0] - data1[i1];\n            return Matrix.Create(result, m0.SX, m0.SY);\n        }\n\n        public static Matrix<float> Subtract(this Matrix<float> mat, float a)\n        {\n            var result = new float[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] - a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static Matrix<float> Add(this Matrix<float> m0, Matrix<float> m1)\n        {\n            if (m0.Dim != m1.Dim) throw new InvalidOperationException(String.Format(\"Cannot add matrix A={0} and matrix B={1}\", m0.Dim, m1.Dim));\n\n            var result = new float[m0.SX * m0.SY];\n\n            var data0 = m0.Data; var data1 = m1.Data;\n            long mf0 = m0.FirstIndex, my0 = m0.DY, my1 = m1.DY;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DX;\n            for (long ye = mf0 + m0.DSY, f0 = mf0, f1 = m1.FirstIndex, ri = 0;\n                f0 != ye; f0 += my0, f1 += my1)\n                for (long xe = f0 + ds0, i0 = f0, i1 = f1; i0 != xe; i0 += d0, i1 += d1, ri++)\n                    result[ri] = data0[i0] + data1[i1];\n            return Matrix.Create(result, m0.SX, m0.SY);\n        }\n\n        public static Matrix<float> Add(this Matrix<float> mat, float a)\n        {\n            var result = new float[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] + a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static bool EqualTo(this Matrix<float> a, Matrix<float> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot compare matrix A={0} and matrix B={1}\", a.Dim, b.Dim));\n            bool eq = true;\n            a.ForeachCoord(crd => eq &= a[crd] == b[crd]);\n            return eq;\n        }\n\n        #endregion\n\n        #region Vector Extensions\n\n        /// <summary>\n        /// Calculates the dot product of two vectors:\n        /// a dot b = Sum(a0*b0 + a1*b1 + ... aN*bN)\n        /// </summary>\n        public static double DotProduct(this Vector<double> v0, Vector<double> v1)\n        {\n            double result = 0.0;\n            double[] a0 = v0.Data, a1 = v1.Data;\n            for (long i0 = v0.Origin, i1 = v1.Origin, e0 = i0 + v0.DSX, d0 = v0.D, d1 = v1.D;\n                i0 != e0; i0 += d0, i1 += d1)\n                result += a0[i0] * a1[i1];\n            return result;\n        }\n\n        /// <summary>\n        /// Calculates the squared norm of a vector:\n        /// ||a|| = Sum(a0*a0 + a1*a1 + ... aN*aN)\n        /// </summary>\n        public static double NormSquared(this Vector<double> v)\n        {\n            double result = 0.0;\n            double[] a = v.Data;\n            for (long i = v.Origin, e = i + v.DSX, d = v.D; i != e; i += d)\n                result += a[i] * a[i];\n            return result;\n        }\n\n        public static double Dist1(this Vector<double> v0, Vector<double> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Abs(x1 - x0), 0.0, (s, p) => s + p);\n\n        public static double Dist2Squared(this Vector<double> v0, Vector<double> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Square(x1 - x0), 0.0, (s, p) => s + p);\n\n        public static double Dist2(this Vector<double> v0, Vector<double> v1)\n            => Fun.Sqrt(v0.Dist2Squared(v1));\n\n        public static double DistMax(this Vector<double> v0, Vector<double> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Abs(x1 - x0), 0.0, Fun.Max);\n\n        public static Vector<double> Multiply(this Vector<double> a, Vector<double> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(\"Cannot multiply vectors with different lengths!\");\n\n            var result = new double[a.Dim];\n            double[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] * a1[i1];\n            return Vector.Create(result);\n        }\n\n        /// <summary>\n        /// Multiply vector a as column vector with vector b as row vector resulting a matrix [b.Dim x a.Dim]\n        /// </summary>\n        public static Matrix<double> MultiplyTransposed(this Vector<double> a, Vector<double> b)\n        {\n            var result = new double[b.Dim * a.Dim];\n            double[] a0 = a.Data, a1 = b.Data;\n            long f1 = b.Origin, e1 = f1 + b.DSX, d1 = b.D;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0)\n                for (long i1 = f1; i1 != e1; i1 += d1, ri++)\n                    result[ri] = a0[i0] * a1[i1];\n            return Matrix.Create(result, b.Dim, a.Dim);\n        }\n\n        public static Vector<double> Multiply(this Vector<double> vec, double s)\n        {\n            var result = new double[vec.Dim];\n            double[] a0 = vec.Data;\n            for (long i0 = vec.Origin, ri = 0, e0 = i0 + vec.DSX, d0 = vec.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] * s;\n            return Vector.Create(result);\n        }\n\n        public static Vector<double> Subtract(this Vector<double> a, Vector<double> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract vectors with length {0} and {1}\", a.Dim, b.Dim));\n            \n            var result = new double[a.Dim];\n            double[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] - a1[i1];\n            return Vector.Create(result);\n        }\n\n        public static Vector<double> Subtract(this Vector<double> a, double b)\n        {\n            var result = new double[a.Dim];\n            double[] a0 = a.Data;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] - b;\n            return Vector.Create(result);\n        }\n\n        public static Vector<double> Add(this Vector<double> a, Vector<double> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract vectors with length {0} and {1}\", a.Dim, b.Dim));\n\n            var result = new double[a.Dim];\n            double[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] + a1[i1];\n            return Vector.Create(result);\n        }\n\n        public static Vector<double> Add(this Vector<double> a, double b)\n        {\n            var result = new double[a.Dim];\n            double[] a0 = a.Data;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] + b;\n            return Vector.Create(result);\n        }\n\n        public static bool EqualTo(this Vector<double> a, Vector<double> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(\"Cannot compare vectors with different lengths!\");\n            bool eq = true;\n            a.ForeachCoord(crd => eq &= a[crd] == b[crd]);\n            return eq;\n        }\n\n        #endregion\n\n        #region Matrix Extensions\n\n        /// <summary>\n        /// Multiply matrix with vector as column vector. \n        /// Vector must have save length as columns of matrix.\n        /// Returns a vector with size of matrix rows.\n        /// </summary>\n        public static Vector<double> Multiply(this Matrix<double> mat, Vector<double> vec)\n        {\n            if (mat.Dim.X != vec.Dim) throw new InvalidOperationException(String.Format(\"Cannot multiply matrix {0} with vector of size {1}\", mat.Dim, vec.Dim));\n            \n            var result = new double[mat.Dim.Y];\n\n            var data0 = mat.Data; var data1 = vec.Data;\n            long my0 = mat.DY, d1 = vec.D;\n            long mf1 = vec.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n                f0 != ye; f0 += my0, e0 += my0, ri++)\n            {\n                double dot = 0.0;\n                for (long i0 = f0, i1 = mf1; i0 != e0; i0 += d0, i1 += d1)\n                    dot += data0[i0] * data1[i1];\n\n                result[ri] = dot;\n            }\n            return Vector.Create(result);\n        }\n        \n        public static Matrix<double> Multiply(this Matrix<double> m0, Matrix<double> m1)\n        {\n            if (m0.SX != m1.SY)\n                throw new ArgumentException(\"m0.SX != m1.SY\");\n\n            var result = new Matrix<double>(m1.SX, m0.SY);\n\n            var data = result.Data; var data0 = m0.Data; var data1 = m1.Data;\n            long i = result.FirstIndex, yj = result.JY, my0 = m0.DY;\n            long xs = result.DSX, mf1 = m1.FirstIndex, xj = result.JX, mx1 = m1.DX;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DY;\n            for (long ye = i + result.DSY, f0 = m0.FirstIndex, e0 = f0 + ds0;\n                i != ye; i += yj, f0 += my0, e0 += my0)\n                for (long xe = i + xs, f1 = mf1; i != xe; i += xj, f1 += mx1)\n                {\n                    double dot = 0.0;\n                    for (long i0 = f0, i1 = f1; i0 != e0; i0 += d0, i1 += d1)\n                        dot += data0[i0] * data1[i1];\n                    data[i] = dot;\n                }\n            return result;\n        }\n\n        public static Matrix<double> Multiply(this Matrix<double> mat, double a)\n        {\n            var result = new double[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] * a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static Matrix<double> Subtract(this Matrix<double> m0, Matrix<double> m1)\n        {\n            if (m0.Dim != m1.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract matrix A={0} and matrix B={1}\", m0.Dim, m1.Dim));\n\n            var result = new double[m0.SX * m0.SY];\n\n            var data0 = m0.Data; var data1 = m1.Data;\n            long mf0 = m0.FirstIndex, my0 = m0.DY, my1 = m1.DY;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DX;\n            for (long ye = mf0 + m0.DSY, f0 = mf0, f1 = m1.FirstIndex, ri = 0;\n                f0 != ye; f0 += my0, f1 += my1)\n                for (long xe = f0 + ds0, i0 = f0, i1 = f1; i0 != xe; i0 += d0, i1 += d1, ri++)\n                    result[ri] = data0[i0] - data1[i1];\n            return Matrix.Create(result, m0.SX, m0.SY);\n        }\n\n        public static Matrix<double> Subtract(this Matrix<double> mat, double a)\n        {\n            var result = new double[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] - a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static Matrix<double> Add(this Matrix<double> m0, Matrix<double> m1)\n        {\n            if (m0.Dim != m1.Dim) throw new InvalidOperationException(String.Format(\"Cannot add matrix A={0} and matrix B={1}\", m0.Dim, m1.Dim));\n\n            var result = new double[m0.SX * m0.SY];\n\n            var data0 = m0.Data; var data1 = m1.Data;\n            long mf0 = m0.FirstIndex, my0 = m0.DY, my1 = m1.DY;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DX;\n            for (long ye = mf0 + m0.DSY, f0 = mf0, f1 = m1.FirstIndex, ri = 0;\n                f0 != ye; f0 += my0, f1 += my1)\n                for (long xe = f0 + ds0, i0 = f0, i1 = f1; i0 != xe; i0 += d0, i1 += d1, ri++)\n                    result[ri] = data0[i0] + data1[i1];\n            return Matrix.Create(result, m0.SX, m0.SY);\n        }\n\n        public static Matrix<double> Add(this Matrix<double> mat, double a)\n        {\n            var result = new double[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] + a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static bool EqualTo(this Matrix<double> a, Matrix<double> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot compare matrix A={0} and matrix B={1}\", a.Dim, b.Dim));\n            bool eq = true;\n            a.ForeachCoord(crd => eq &= a[crd] == b[crd]);\n            return eq;\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/TensorMathExt_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static class Vector\n    {\n        /// <summary>\n        /// Vector constructor from a given array that does not require to write generic type\n        /// </summary>\n        public static Vector<T> Create<T>(T[] array)\n        {\n            return new Vector<T>(array);\n        }\n    }\n\n    public static class Matrix\n    {\n        /// <summary>\n        /// Matrix constructor from a given array that does not require to write generic type.\n        /// </summary>\n        public static Matrix<T> Create<T>(T[] array, int sx, int sy)\n        {\n            if (array.Length != sx * sy) throw new ArgumentException(\"Data array of matrix does not match given size\");\n            return new Matrix<T>(array, sx, sy);\n        }\n\n        /// <summary>\n        /// Matrix constructor from a given array that does not require to write generic type.\n        /// </summary>\n        public static Matrix<T> Create<T>(T[] array, long sx, long sy)\n        {\n            if (array.Length != sx * sy) throw new ArgumentException(\"Data array of matrix does not match given size\");\n            return new Matrix<T>(array, sx, sy);\n        }\n    }\n\n    public static class TensorMathExt\n    {\n        //# foreach (var isDouble in new[] { false, true }) {\n        //#   var ft = isDouble ? \"double\" : \"float\";\n        //#   var tc = isDouble ? \"d\" : \"f\";\n        //#   var zero = isDouble ? \"0.0\" : \"0.0f\";\n        #region Vector Extensions\n\n        /// <summary>\n        /// Calculates the dot product of two vectors:\n        /// a dot b = Sum(a0*b0 + a1*b1 + ... aN*bN)\n        /// </summary>\n        public static __ft__ DotProduct(this Vector<__ft__> v0, Vector<__ft__> v1)\n        {\n            __ft__ result = __zero__;\n            __ft__[] a0 = v0.Data, a1 = v1.Data;\n            for (long i0 = v0.Origin, i1 = v1.Origin, e0 = i0 + v0.DSX, d0 = v0.D, d1 = v1.D;\n                i0 != e0; i0 += d0, i1 += d1)\n                result += a0[i0] * a1[i1];\n            return result;\n        }\n\n        /// <summary>\n        /// Calculates the squared norm of a vector:\n        /// ||a|| = Sum(a0*a0 + a1*a1 + ... aN*aN)\n        /// </summary>\n        public static __ft__ NormSquared(this Vector<__ft__> v)\n        {\n            __ft__ result = __zero__;\n            __ft__[] a = v.Data;\n            for (long i = v.Origin, e = i + v.DSX, d = v.D; i != e; i += d)\n                result += a[i] * a[i];\n            return result;\n        }\n\n        public static __ft__ Dist1(this Vector<__ft__> v0, Vector<__ft__> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Abs(x1 - x0), __zero__, (s, p) => s + p);\n\n        public static __ft__ Dist2Squared(this Vector<__ft__> v0, Vector<__ft__> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Square(x1 - x0), __zero__, (s, p) => s + p);\n\n        public static __ft__ Dist2(this Vector<__ft__> v0, Vector<__ft__> v1)\n            => Fun.Sqrt(v0.Dist2Squared(v1));\n\n        public static __ft__ DistMax(this Vector<__ft__> v0, Vector<__ft__> v1)\n            => v0.InnerProduct(v1, (x0, x1) => Fun.Abs(x1 - x0), __zero__, Fun.Max);\n\n        public static Vector<__ft__> Multiply(this Vector<__ft__> a, Vector<__ft__> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(\"Cannot multiply vectors with different lengths!\");\n\n            var result = new __ft__[a.Dim];\n            __ft__[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] * a1[i1];\n            return Vector.Create(result);\n        }\n\n        /// <summary>\n        /// Multiply vector a as column vector with vector b as row vector resulting a matrix [b.Dim x a.Dim]\n        /// </summary>\n        public static Matrix<__ft__> MultiplyTransposed(this Vector<__ft__> a, Vector<__ft__> b)\n        {\n            var result = new __ft__[b.Dim * a.Dim];\n            __ft__[] a0 = a.Data, a1 = b.Data;\n            long f1 = b.Origin, e1 = f1 + b.DSX, d1 = b.D;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0)\n                for (long i1 = f1; i1 != e1; i1 += d1, ri++)\n                    result[ri] = a0[i0] * a1[i1];\n            return Matrix.Create(result, b.Dim, a.Dim);\n        }\n\n        public static Vector<__ft__> Multiply(this Vector<__ft__> vec, __ft__ s)\n        {\n            var result = new __ft__[vec.Dim];\n            __ft__[] a0 = vec.Data;\n            for (long i0 = vec.Origin, ri = 0, e0 = i0 + vec.DSX, d0 = vec.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] * s;\n            return Vector.Create(result);\n        }\n\n        public static Vector<__ft__> Subtract(this Vector<__ft__> a, Vector<__ft__> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract vectors with length {0} and {1}\", a.Dim, b.Dim));\n            \n            var result = new __ft__[a.Dim];\n            __ft__[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] - a1[i1];\n            return Vector.Create(result);\n        }\n\n        public static Vector<__ft__> Subtract(this Vector<__ft__> a, __ft__ b)\n        {\n            var result = new __ft__[a.Dim];\n            __ft__[] a0 = a.Data;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] - b;\n            return Vector.Create(result);\n        }\n\n        public static Vector<__ft__> Add(this Vector<__ft__> a, Vector<__ft__> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract vectors with length {0} and {1}\", a.Dim, b.Dim));\n\n            var result = new __ft__[a.Dim];\n            __ft__[] a0 = a.Data, a1 = b.Data;\n            for (long i0 = a.Origin, ri = 0, i1 = b.Origin, e0 = i0 + a.DSX, d0 = a.D, d1 = b.D;\n                i0 != e0; i0 += d0, i1 += d1, ri++)\n                result[ri] = a0[i0] + a1[i1];\n            return Vector.Create(result);\n        }\n\n        public static Vector<__ft__> Add(this Vector<__ft__> a, __ft__ b)\n        {\n            var result = new __ft__[a.Dim];\n            __ft__[] a0 = a.Data;\n            for (long i0 = a.Origin, ri = 0, e0 = i0 + a.DSX, d0 = a.D; i0 != e0; i0 += d0, ri++)\n                result[ri] = a0[i0] + b;\n            return Vector.Create(result);\n        }\n\n        public static bool EqualTo(this Vector<__ft__> a, Vector<__ft__> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(\"Cannot compare vectors with different lengths!\");\n            bool eq = true;\n            a.ForeachCoord(crd => eq &= a[crd] == b[crd]);\n            return eq;\n        }\n\n        #endregion\n\n        #region Matrix Extensions\n\n        /// <summary>\n        /// Multiply matrix with vector as column vector. \n        /// Vector must have save length as columns of matrix.\n        /// Returns a vector with size of matrix rows.\n        /// </summary>\n        public static Vector<__ft__> Multiply(this Matrix<__ft__> mat, Vector<__ft__> vec)\n        {\n            if (mat.Dim.X != vec.Dim) throw new InvalidOperationException(String.Format(\"Cannot multiply matrix {0} with vector of size {1}\", mat.Dim, vec.Dim));\n            \n            var result = new __ft__[mat.Dim.Y];\n\n            var data0 = mat.Data; var data1 = vec.Data;\n            long my0 = mat.DY, d1 = vec.D;\n            long mf1 = vec.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n                f0 != ye; f0 += my0, e0 += my0, ri++)\n            {\n                __ft__ dot = __zero__;\n                for (long i0 = f0, i1 = mf1; i0 != e0; i0 += d0, i1 += d1)\n                    dot += data0[i0] * data1[i1];\n\n                result[ri] = dot;\n            }\n            return Vector.Create(result);\n        }\n        \n        public static Matrix<__ft__> Multiply(this Matrix<__ft__> m0, Matrix<__ft__> m1)\n        {\n            if (m0.SX != m1.SY)\n                throw new ArgumentException(\"m0.SX != m1.SY\");\n\n            var result = new Matrix<__ft__>(m1.SX, m0.SY);\n\n            var data = result.Data; var data0 = m0.Data; var data1 = m1.Data;\n            long i = result.FirstIndex, yj = result.JY, my0 = m0.DY;\n            long xs = result.DSX, mf1 = m1.FirstIndex, xj = result.JX, mx1 = m1.DX;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DY;\n            for (long ye = i + result.DSY, f0 = m0.FirstIndex, e0 = f0 + ds0;\n                i != ye; i += yj, f0 += my0, e0 += my0)\n                for (long xe = i + xs, f1 = mf1; i != xe; i += xj, f1 += mx1)\n                {\n                    __ft__ dot = __zero__;\n                    for (long i0 = f0, i1 = f1; i0 != e0; i0 += d0, i1 += d1)\n                        dot += data0[i0] * data1[i1];\n                    data[i] = dot;\n                }\n            return result;\n        }\n\n        public static Matrix<__ft__> Multiply(this Matrix<__ft__> mat, __ft__ a)\n        {\n            var result = new __ft__[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] * a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static Matrix<__ft__> Subtract(this Matrix<__ft__> m0, Matrix<__ft__> m1)\n        {\n            if (m0.Dim != m1.Dim) throw new InvalidOperationException(String.Format(\"Cannot subtract matrix A={0} and matrix B={1}\", m0.Dim, m1.Dim));\n\n            var result = new __ft__[m0.SX * m0.SY];\n\n            var data0 = m0.Data; var data1 = m1.Data;\n            long mf0 = m0.FirstIndex, my0 = m0.DY, my1 = m1.DY;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DX;\n            for (long ye = mf0 + m0.DSY, f0 = mf0, f1 = m1.FirstIndex, ri = 0;\n                f0 != ye; f0 += my0, f1 += my1)\n                for (long xe = f0 + ds0, i0 = f0, i1 = f1; i0 != xe; i0 += d0, i1 += d1, ri++)\n                    result[ri] = data0[i0] - data1[i1];\n            return Matrix.Create(result, m0.SX, m0.SY);\n        }\n\n        public static Matrix<__ft__> Subtract(this Matrix<__ft__> mat, __ft__ a)\n        {\n            var result = new __ft__[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] - a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static Matrix<__ft__> Add(this Matrix<__ft__> m0, Matrix<__ft__> m1)\n        {\n            if (m0.Dim != m1.Dim) throw new InvalidOperationException(String.Format(\"Cannot add matrix A={0} and matrix B={1}\", m0.Dim, m1.Dim));\n\n            var result = new __ft__[m0.SX * m0.SY];\n\n            var data0 = m0.Data; var data1 = m1.Data;\n            long mf0 = m0.FirstIndex, my0 = m0.DY, my1 = m1.DY;\n            long ds0 = m0.DSX, d0 = m0.DX, d1 = m1.DX;\n            for (long ye = mf0 + m0.DSY, f0 = mf0, f1 = m1.FirstIndex, ri = 0;\n                f0 != ye; f0 += my0, f1 += my1)\n                for (long xe = f0 + ds0, i0 = f0, i1 = f1; i0 != xe; i0 += d0, i1 += d1, ri++)\n                    result[ri] = data0[i0] + data1[i1];\n            return Matrix.Create(result, m0.SX, m0.SY);\n        }\n\n        public static Matrix<__ft__> Add(this Matrix<__ft__> mat, __ft__ a)\n        {\n            var result = new __ft__[mat.SX * mat.SY];\n\n            var data0 = mat.Data;\n            long my0 = mat.DY;\n            long mf0 = mat.FirstIndex;\n            long ds0 = mat.DSX, d0 = mat.DX;\n            for (long ri = 0, ye = mat.FirstIndex + mat.DSY, f0 = mat.FirstIndex, e0 = f0 + ds0;\n            f0 != ye; f0 += my0, e0 += my0)\n            {\n                for (long i0 = f0; i0 != e0; i0 += d0, ri++)\n                    result[ri] = data0[i0] + a;\n            }\n            return Matrix.Create(result, mat.SX, mat.SY);\n        }\n\n        public static bool EqualTo(this Matrix<__ft__> a, Matrix<__ft__> b)\n        {\n            if (a.Dim != b.Dim) throw new InvalidOperationException(String.Format(\"Cannot compare matrix A={0} and matrix B={1}\", a.Dim, b.Dim));\n            bool eq = true;\n            a.ForeachCoord(crd => eq &= a[crd] == b[crd]);\n            return eq;\n        }\n\n        #endregion\n\n        //# }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensor_auto.cs",
    "content": "using System;\nusing System.Diagnostics;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    #region VectorInfo\n\n    /// <summary>\n    /// A vector info contains the complete indexing information for a vector, but no data array.\n    /// </summary>\n    [Serializable]\n    public struct VectorInfo : ITensorInfo\n    {\n        /// <summary>\n        /// Index of element with coordinate 0 in the underlying data array.\n        /// </summary>\n        public long Origin;\n\n        /// <summary>\n        /// Size of the vector.\n        /// </summary>\n        public long Size;\n\n        /// <summary>\n        /// Element stride.\n        /// </summary>\n        public long Delta;\n\n        /// <summary>\n        /// Coordinates of the first element.\n        /// May differ from coordinate 0 for subwindows that retain the original coordinate space.\n        /// </summary>\n        public long First;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a VectorInfo given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the vector.</param>\n        /// <param name=\"delta\">Element stride.</param>\n        /// <param name=\"first\">Coordinates of the first element.</param>\n        public VectorInfo(long origin, long size, long delta, long first)\n        {\n            Origin = origin;\n            Size = size;\n            Delta = delta;\n            First = first;\n        }\n\n        /// <summary>\n        /// Construct a VectorInfo given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the vector.</param>\n        /// <param name=\"delta\">Element stride.</param>\n        public VectorInfo(long origin, long size, long delta)\n            : this(origin, size, delta, 0L)\n        { }\n\n        /// <summary>\n        /// Construct vector info of specified size.\n        /// </summary>\n        public VectorInfo(long size)\n            : this(0L, size, 1L)\n        { }\n\n        public VectorInfo(VectorInfo info)\n            : this(0L, info.Size, 1L)\n        {\n            F = info.F;\n        }\n\n        /// <summary>\n        /// Construct vector info of specified size.\n        /// </summary>\n        public VectorInfo(int size)\n            : this((long)size)\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the the vector (1).\n        /// </summary>\n        public readonly int Rank { get { return 1; } }\n\n        /// <summary>\n        /// Total number of element in the vector.\n        /// </summary>\n        public readonly long Count { get { return Size; } }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        public readonly long End { get { return First + Size; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long O { get { return First; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long I { get { return First + Size; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long S { readonly get { return Size; } set { Size = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long D { readonly get { return Delta; } set { Delta = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long F { readonly get { return First; } set { Origin -= Delta * (value - First); First = value; } }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long E { get { return First + Size; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DS { get { return Delta * Size; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Size; } set { Size = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Delta; } set { Delta = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return First; } set { Origin -= Delta * (value - First); First = value; } }\n\n        /// <summary>\n        /// End (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return First + Size; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Delta * Size; } }\n\n        /// <summary>\n        /// Jump\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Delta; } }\n\n\n        /// <summary>\n        /// Return the index of the first element in the underlying data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Index(First); } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long OriginIndex { readonly get { return Origin; } set { Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return new long[] { SX }; }\n            set { SX = value[0];  }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return new long[] { DX }; }\n            set { DX = value[0];  }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return new long[] { FX }; }\n            set { FX = value[0];  }\n        }\n\n        #endregion\n\n        #region Indexing Helper Methods\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(long coord) { return Origin + coord * Delta; }\n\n        #endregion\n\n        #region Interpretation and Parts\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly VectorInfo SubVectorWindow(long begin, long size)\n        {\n            return new VectorInfo(Origin, size, Delta, begin);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(long begin, long size)\n        {\n            return new VectorInfo(Index(begin), size, Delta);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly VectorInfo SubVectorWindow(int begin, int size)\n        {\n            return new VectorInfo(Origin, (long)size, Delta, (long)begin);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(int begin, int size)\n        {\n            return new VectorInfo(Index((long)begin), (long)size, Delta);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly VectorInfo SubVectorWindow(long begin, long size, long delta)\n        {\n            return new VectorInfo(Origin, size, delta, begin);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(long begin, long size, long delta)\n        {\n            return new VectorInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly VectorInfo SubVectorWindow(int begin, int size, int delta)\n        {\n            return new VectorInfo(Origin, (long)size, (long)delta, (long)begin);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(int begin, int size, int delta)\n        {\n            return new VectorInfo(Index((long)begin), (long)size, (long)delta);\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long xs = SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    i_action(i);\n                }\n            }\n            else\n            {\n                long xs = DSX, xj = JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    i_action(i);\n                }\n            }\n        }\n\n        public readonly void ForeachIndex(Action<long, long> x_i_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long xs = SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    x_i_action(x, i);\n                }\n            }\n            else\n            {\n                long xs = DSX, xj = JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    x_i_action(x, i);\n                }\n            }\n        }\n\n        public readonly void ForeachCoord(Action<long> v_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long xs = SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    v_action(x);\n                }\n            }\n            else\n            {\n                long xs = DSX, xj = JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    v_action(x);\n                }\n            }\n        }\n\n        public readonly void ForeachIndex(VectorInfo t1, Action<long, long> i_i1_act)\n        {\n            CheckMatchingSize(t1);\n            if (HasMatchingLayout(t1))\n            {\n                long i = FirstIndex;\n                if (DX == 1)\n                {\n                    long xs = SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        i_i1_act(i, i);\n                    }\n                }\n                else\n                {\n                    long xs = DSX, xj = JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        i_i1_act(i, i);\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (DX == 1 && t1.DX == 1)\n                {\n                    long xs = SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        i_i1_act(i, i1);\n                    }\n                }\n                else\n                {\n                    long xs = DSX, xj = JX, xj1 = t1.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        i_i1_act(i, i1);\n                    }\n                }\n            }\n        }\n\n        #endregion\n\n        #region Checking\n\n        public readonly void CheckMatchingSize(VectorInfo t1)\n        {\n            if (Size != t1.Size) throw new ArgumentException(\"size mismatch\");\n        }\n\n        public readonly void CheckMatchingSize(VectorInfo t1, VectorInfo t2)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2);\n        }\n\n        public readonly void CheckMatchingSize(VectorInfo t1, VectorInfo t2, VectorInfo t3)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2); CheckMatchingSize(t3);\n        }\n\n        public readonly bool HasMatchingLayout(VectorInfo t1)\n        {\n            return First == t1.First && Origin == t1.Origin && Delta == t1.Delta;\n        }\n\n        public readonly bool HasMatchingLayout(VectorInfo t1, VectorInfo t2)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2);\n        }\n\n        public readonly bool HasMatchingLayout(VectorInfo t1, VectorInfo t2, VectorInfo t3)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2) && HasMatchingLayout(t3);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Vector<Td>\n\n    /// <summary>\n    /// Generic vector of elements with arbitrary stride.\n    /// All sizes are given as 1-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The vector does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on vectors are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// 1 stride direction(s) are called DX, DY, aso.\n    /// </summary>\n    /// <typeparam name=\"Td\">data element type</typeparam>\n    [Serializable]\n    public partial struct Vector<Td> : IValidity, IVector<Td>, IArrayVector\n    {\n        public Td[] Data;\n        public VectorInfo Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public Vector(Td[] data, VectorInfo info)\n        {\n            Data = data;\n            Info = info;\n        }\n\n        /// <summary>\n        /// Construct vector of specified size.\n        /// </summary>\n        public Vector(long size)\n            : this(new Td[size], new VectorInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct vector of specified size.\n        /// </summary>\n        public Vector(int size)\n            : this((long)size)\n        { }\n\n        /// <summary>\n        /// Construct vector with specified info.\n        /// </summary>\n        public Vector(VectorInfo info)\n            : this(new Td[info.Count], new VectorInfo(info))\n        { }\n\n        /// <summary>\n        /// Construct from data array without copying.\n        /// </summary>\n        public Vector(Td[] data)\n            : this(data, new VectorInfo(data.Length))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Vector(Td[] data, long size)\n            : this(data, new VectorInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Vector(Td[] data, int size)\n            : this(data, new VectorInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct vector of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Vector(long size, Td value)\n            : this(new Td[size], new VectorInfo(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Vector(int size, Td value)\n            : this((long)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Vector(Td[] data, long origin, long size, long delta)\n            : this(data, new VectorInfo(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Vector(Td[] data, long origin, long size, long delta, long first)\n            : this(data, new VectorInfo(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public Vector(long origin, long size, long delta)\n            : this(new Td[size],\n                   new VectorInfo(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the vector (1).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public long Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public long Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public long First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        /// <summary>\n        /// Returns true if the vector has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the vector does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly long End { get { return Info.E; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long O { get { return Info.O; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long I { get { return Info.I; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long E { get { return Info.E; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DS { get { return Info.D; } }\n\n        /// <summary>\n        /// Size in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Info.SX; } set { Info.SX = value; } }\n\n        /// <summary>\n        /// Delta in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Info.DX; } set { Info.DX = value; } }\n\n        /// <summary>\n        /// First in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return Info.FX; } set { Info.FX = value; } }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return Info.EX; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Info.JX; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Info.DSX; } }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<Td> Elements\n        {\n            get\n            {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    yield return Data[i];\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    yield return Data[i];\n                }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(Td[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (Td[])value; }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Td this[long x]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + x * Info.Delta];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + x * Info.Delta] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Td this[int x]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + (long)x * Info.Delta];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + (long)x * Info.Delta] = value;\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        public readonly void ForeachIndex(Action<long, long> x_i_action)\n        {\n            Info.ForeachIndex(x_i_action);\n        }\n\n        public readonly void ForeachCoord(Action<long> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(VectorInfo t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td> SubVectorWindow(long begin, long size)\n        {\n            return new Vector<Td>(Data, Info.SubVectorWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> SubVector(long begin, long size)\n        {\n            return new Vector<Td>(Data, Info.SubVector(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td> SubVectorWindow(int begin, int size)\n        {\n            return new Vector<Td>(Data, Info.SubVectorWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> SubVector(int begin, int size)\n        {\n            return new Vector<Td>(Data, Info.SubVector(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td> SubVectorWindow(long begin, long size, long delta)\n        {\n            return new Vector<Td>(Data, Info.SubVectorWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> SubVector(long begin, long size, long delta)\n        {\n            return new Vector<Td>(Data, Info.SubVector(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td> SubVectorWindow(int begin, int size, int delta)\n        {\n            return new Vector<Td>(Data, Info.SubVectorWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> SubVector(int begin, int size, int delta)\n        {\n            return new Vector<Td>(Data, Info.SubVector(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVectorWindow<T1>(long begin, long size)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVectorWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(long begin, long size)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVectorWindow<T1>(int begin, int size)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVectorWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(int begin, int size)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVectorWindow<T1>(long begin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVectorWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(long begin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVectorWindow<T1>(int begin, int size, int delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVectorWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(int begin, int size, int delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(begin, size, delta));\n        }\n\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> Copy()\n        {\n            return new Vector<Td>(Info.S).Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original Vector.\n        /// </summary>\n        public readonly Vector<Td> CopyWindow()\n        {\n            return new Vector<Td>(Info.S)\n                    { F = F,  }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<T1> Map<T1>(Func<Td, T1> fun)\n        {\n            return new Vector<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original Vector.\n        /// </summary>\n        public readonly Vector<T1> MapWindow<T1>(Func<Td, T1> fun)\n        {\n            return new Vector<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Returns a tensor repeated in each dimension by the specified\n        /// count.\n        /// </summary>\n        public readonly Vector<Td> Repeated(long count)\n        {\n            var size = Size;\n            count *= size;\n            var t = new Vector<Td>(count);\n            for (long p = 0; p < count; p += size)\n                t.SubVector(p, size).Set(this);\n            return t;\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the vector.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> Apply(Func<Td, Td> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long xe = i + Info.SX; i != xe; i++)\n                    Data[i] = element_elementFun(Data[i]);\n            }\n            else\n            {\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj)\n                    Data[i] = element_elementFun(Data[i]);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original vector and the supplied vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> Apply<T1>(\n                Vector<T1> t1, Func<Td, T1, Td> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original vector and the supplied vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> Apply<T1d, T1>(\n                Vector<T1d, T1> t1, Func<Td, T1, Td> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> ApplyByCoord(Func<Td, long, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    Data[i] = fun(Data[i], x);\n            }\n            else\n            {\n                for (long xe = i + Info.DSX, xj = Info.JX, x = Info.FX; i != xe; i += xj, x++)\n                    Data[i] = fun(Data[i], x);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> Set(Td v)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    Data[i] = v;\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Data[i] = v;\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByCoord(Func<long, Td> x_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Data[i] = x_elementFun(x);\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Data[i] = x_elementFun(x);\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex(Func<long, Td> index_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    Data[i] = index_elementFun(i);\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Data[i] = index_elementFun(i);\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly Vector<Td> Set(IVector<Td> it1)\n        {\n            if (it1 is Vector<Td>) return Set((Vector<Td>)it1);\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Data[i] = it1[x];\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Data[i] = it1[x];\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> Set(Vector<Td> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = t1.Data[i];\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = t1.Data[i];\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = t1.Data[i1];\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = t1.Data[i1];\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// the elements of the supplied vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap<T1>(\n                Vector<T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1>(\n                Vector<T1> t1, Func<long, Td> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_elementFun(i);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_elementFun(i);\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = index1_elementFun(i1);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> Set<T1>(Vector<T1, Td> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// the elements of the supplied vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap<T1d, T1>(\n                Vector<T1d, T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1d, T1>(\n                Vector<T1d, T1> t1, Func<long, Td> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = index1_elementFun(i1);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap2<T1, T2>(\n                    Vector<T1> t1, Vector<T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1, T2>(\n                Vector<T1> t1, Vector<T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap2<T1, T2d, T2>(\n                    Vector<T1> t1, Vector<T2d, T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1, T2d, T2>(\n                Vector<T1> t1, Vector<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap2<T1d, T1, T2>(\n                    Vector<T1d, T1> t1, Vector<T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1d, T1, T2>(\n                Vector<T1d, T1> t1, Vector<T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap2<T1d, T1, T2d, T2>(\n                    Vector<T1d, T1> t1, Vector<T2d, T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1d, T1, T2d, T2>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap3<T1, T2, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info, t3.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1, T2, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info, t3.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap3<T1, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap3<T1, T2d, T2, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1, T2d, T2, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap3<T1, T2d, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1, T2d, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap3<T1d, T1, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1d, T1, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap3<T1d, T1, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1d, T1, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap3<T1d, T1, T2d, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1d, T1, T2d, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetMap3<T1d, T1, T2d, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td> SetByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the vector to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly Vector<Td> SetConvolution<Ti, Tf, Tm, Ts>(\n                Vector<Ti> image, Vector<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Td> castFun)\n        {\n            Info.CheckMatchingSize(new VectorInfo(1L + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.SubVector(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Td, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Data[i]));\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Data[i], x));\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Data[i], x));\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Vector<T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Vector<T1d, T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    }\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Td, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Data[i], x));\n                    if (breakIfTrueFun(result)) return result;\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Data[i], x));\n                    if (breakIfTrueFun(result)) return result;\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Vector<T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Vector<T1d, T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creator Functions\n\n        /// <summary>\n        /// Create a new vector as copy of the supplied vector.\n        /// </summary>\n        public static Vector<Td> Create(\n                Vector<Td> t1)\n        {\n            return new Vector<Td>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new vector as copy of the supplied vector.\n        /// </summary>\n        public static Vector<Td> Create<T1d>(\n                Vector<T1d, Td> t1)\n        {\n            return new Vector<Td>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map<T1>(\n                Vector<T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1>(\n                Vector<T1> t1, Func<long, Td> index1_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map<T1d, T1>(\n                Vector<T1d, T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1d, T1>(\n                Vector<T1d, T1> t1, Func<long, Td> index1_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map2<T1, T2>(\n                Vector<T1> t1, Vector<T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1, T2>(\n                Vector<T1> t1, Vector<T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map2<T1, T2d, T2>(\n                Vector<T1> t1, Vector<T2d, T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1, T2d, T2>(\n                Vector<T1> t1, Vector<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map2<T1d, T1, T2>(\n                Vector<T1d, T1> t1, Vector<T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1d, T1, T2>(\n                Vector<T1d, T1> t1, Vector<T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map2<T1d, T1, T2d, T2>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1d, T1, T2d, T2>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map3<T1, T2, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1, T2, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map3<T1, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map3<T1, T2d, T2, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1, T2d, T2, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map3<T1, T2d, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1, T2d, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map3<T1d, T1, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1d, T1, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map3<T1d, T1, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1d, T1, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map3<T1d, T1, T2d, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1d, T1, T2d, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td> Map3<T1d, T1, T2d, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td> CreateByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to the coordinates of\n        /// the elements the newly created vector.\n        /// </summary>\n        public static Vector<Td> Create(long size, Func<long, Td> fun)\n        {\n            return new Vector<Td>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new Vector by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting Vector.\n        /// </summary>\n        public static Vector<Td> CreateConvolution<Ti, Tf, Tm, Ts>(\n                Vector<Ti> image, Vector<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Td> castFun)\n        {\n            long size = 1 + image.S - filter.S;\n            if (size <= 0) throw new Exception(\"filter to large\");\n            return new Vector<Td>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        #endregion\n\n        #region Sampling\n\n        /// <summary>\n        /// Sample the vector using 2 samples and the supplied\n        /// interpolation function. If an integer coordinte is\n        /// supplied the returned value is the same as the indexer\n        /// of the vector. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw2<TRes>(\n                double x,\n                Func<double, Td, Td, TRes> ipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; long d = Info.Delta;\n            long i = Info.Origin + xi * d;\n            return ipl(x - xid, Data[i], Data[i + d]);\n        }\n\n        public readonly TRes Sample2Clamped<TRes>(\n                double x,\n                Func<double, Td, Td, TRes> ipl)\n        {\n            return Sample2(x, ipl, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Sample the vector using 2 samples and the supplied\n        /// interpolation function. If an integer coordinte is\n        /// supplied the returned value is the same as the indexer\n        /// of the vector.\n        /// </summary>\n        public readonly TRes Sample2<TRes>(\n                double x,\n                Func<double, Td, Td, TRes> ipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            long i = Info.Origin + xi * d1;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            return ipl(xf, Data[i + d.E0], Data[i + d.E1]);\n        }\n\n        public readonly TRes SampleRaw4<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, TRes> smp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d = Info.Delta;\n            long i1 = Info.Origin + xi * d, i2 = i1 + d;\n            var w = ipl(xf);\n            return smp(Data[i1 - d], Data[i1], Data[i2], Data[i2 + d], ref w);\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, TRes> smp)\n        {\n            return Sample4(x, ipl, smp, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample4<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, TRes> smp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            long i = Info.Origin + xi * d1;\n            var w = ipl(xf);\n            return smp(Data[i + d.E0], Data[i + d.E1], Data[i + d.E2], Data[i + d.E3], ref w);\n        }\n\n        public readonly TRes SampleRaw6<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, TRes> smp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d = Info.Delta;\n            long i2 = Info.Origin + xi * d, i1 = i2 - d, i3 = i2 + d, i4 = i3 + d;\n            var w = ipl(xf);\n            return smp(Data[i1 - d], Data[i1], Data[i2], Data[i3], Data[i4], Data[i4 + d], ref w);\n        }\n\n        public readonly TRes Sample6Clamped<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, TRes> smp)\n        {\n            return Sample6(x, ipl, smp, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample6<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, TRes> smp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            long i = Info.Origin + xi * d1;\n            var w = ipl(xf);\n            return smp(Data[i + d.E0], Data[i + d.E1], Data[i + d.E2], Data[i + d.E3], Data[i + d.E4], Data[i + d.E5], ref w);\n        }\n\n        #endregion\n\n        #region IVector\n\n        /// <summary>\n        /// Dimension of the generic Vector.\n        /// </summary>\n        public readonly long Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(long x)\n        {\n            return (object)this[x];\n        }\n\n        public readonly void SetValue(object value, long x)\n        {\n            this[x] = (Td)value;\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    #region Vector<Td, Tv>\n\n    /// <summary>\n    /// Generic vector of elements with arbitrary stride.\n    /// All sizes are given as 1-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The vector does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on vectors are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// 1 stride direction(s) are called DX, DY, aso.\n    /// The vector has different view and data element types, i.e. although\n    /// all data is stored using the data element type, in its interfaces it\n    /// acts as a vector of view element types.\n    /// </summary>\n    /// <typeparam name=\"Td\">data element type</typeparam>\n    /// <typeparam name=\"Tv\">view element type</typeparam>\n    [Serializable]\n    public partial struct Vector<Td, Tv> : IValidity, IVector<Tv>, IArrayVector\n    {\n        public Td[] Data;\n        public Func<Td[], long, Tv> Getter;\n        public Action<Td[], long, Tv> Setter;\n        public VectorInfo Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public Vector(Td[] data, VectorInfo info)\n        {\n            Data = data;\n            Info = info;\n            Getter = null;\n            Setter = null;\n        }\n\n        /// <summary>\n        /// Construct vector of specified size.\n        /// </summary>\n        public Vector(long size)\n            : this(new Td[size], new VectorInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct vector of specified size.\n        /// </summary>\n        public Vector(int size)\n            : this((long)size)\n        { }\n\n        /// <summary>\n        /// Construct vector with specified info.\n        /// </summary>\n        public Vector(VectorInfo info)\n            : this(new Td[info.Count], new VectorInfo(info))\n        { }\n\n        /// <summary>\n        /// Construct from data array without copying.\n        /// </summary>\n        public Vector(Td[] data)\n            : this(data, new VectorInfo(data.Length))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Vector(Td[] data, long size)\n            : this(data, new VectorInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Vector(Td[] data, int size)\n            : this(data, new VectorInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct vector of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Vector(long size, Tv value)\n            : this(new Td[size], new VectorInfo(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Vector(int size, Tv value)\n            : this((long)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Vector(Td[] data, long origin, long size, long delta)\n            : this(data, new VectorInfo(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Vector(Td[] data, long origin, long size, long delta, long first)\n            : this(data, new VectorInfo(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public Vector(long origin, long size, long delta)\n            : this(new Td[size],\n                   new VectorInfo(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the vector (1).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public long Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public long Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public long First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        public TensorAccessors<Td, Tv> Accessors\n        {\n            readonly get\n            {\n                return new TensorAccessors<Td, Tv>()\n                                { Getter = Getter, Setter = Setter };\n            }\n            set { Getter = value.Getter; Setter = value.Setter; }\n        }\n\n        /// <summary>\n        /// Returns true if the vector has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the vector does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly long End { get { return Info.E; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long O { get { return Info.O; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long I { get { return Info.I; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long E { get { return Info.E; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DS { get { return Info.D; } }\n\n        /// <summary>\n        /// Size in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Info.SX; } set { Info.SX = value; } }\n\n        /// <summary>\n        /// Delta in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Info.DX; } set { Info.DX = value; } }\n\n        /// <summary>\n        /// First in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return Info.FX; } set { Info.FX = value; } }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return Info.EX; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Info.JX; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Info.DSX; } }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<Tv> Elements\n        {\n            get\n            {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    yield return Getter(Data, i);\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    yield return Getter(Data, i);\n                }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(Td[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (Td[])value; }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Tv this[long x]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + x * Info.Delta);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + x * Info.Delta, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Tv this[int x]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + (long)x * Info.Delta);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + (long)x * Info.Delta, value);\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        public readonly void ForeachIndex(Action<long, long> x_i_action)\n        {\n            Info.ForeachIndex(x_i_action);\n        }\n\n        public readonly void ForeachCoord(Action<long> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(VectorInfo t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVectorWindow(long begin, long size)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVectorWindow(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(long begin, long size)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVectorWindow(int begin, int size)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVectorWindow(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(int begin, int size)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVectorWindow(long begin, long size, long delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVectorWindow(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(long begin, long size, long delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVectorWindow(int begin, int size, int delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVectorWindow(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(int begin, int size, int delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVectorWindow<T1>(long begin, long size)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVectorWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(long begin, long size)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVectorWindow<T1>(int begin, int size)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVectorWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(int begin, int size)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVectorWindow<T1>(long begin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVectorWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(long begin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Vector.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVectorWindow<T1>(int begin, int size, int delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVectorWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(int begin, int size, int delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(begin, size, delta));\n        }\n\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> Copy()\n        {\n            return new Vector<Td, Tv>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original Vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> CopyWindow()\n        {\n            return new Vector<Td, Tv>(Info.S)\n                    { F = F, Getter = Getter, Setter = Setter }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<T1> Map<T1>(Func<Tv, T1> fun)\n        {\n            return new Vector<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original Vector.\n        /// </summary>\n        public readonly Vector<T1> MapWindow<T1>(Func<Tv, T1> fun)\n        {\n            return new Vector<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        public readonly Vector<Tv> CopyView()\n        {\n            return new Vector<Tv>(Info.S).Set(this);\n        }\n\n        public readonly Vector<Tv> CopyViewWindow()\n        {\n            return new Vector<Tv>(Info.S) { F = F }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> Map(Func<Tv, Tv> fun)\n        {\n            return new Vector<Td, Tv>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the complete layout of the original Vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> MapWindow(Func<Tv, Tv> fun)\n        {\n            return new Vector<Td, Tv>(new Td[Data.LongLength], Info)\n                        { F = F, Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the vector.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> Apply(Func<Tv, Tv> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long xe = i + Info.SX; i != xe; i++)\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n            }\n            else\n            {\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj)\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original vector and the supplied vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> Apply<T1>(\n                Vector<T1> t1, Func<Tv, T1, Tv> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original vector and the supplied vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> Apply<T1d, T1>(\n                Vector<T1d, T1> t1, Func<Tv, T1, Tv> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> ApplyByCoord(Func<Tv, long, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    Setter(Data, i, fun(Getter(Data, i), x));\n            }\n            else\n            {\n                for (long xe = i + Info.DSX, xj = Info.JX, x = Info.FX; i != xe; i += xj, x++)\n                    Setter(Data, i, fun(Getter(Data, i), x));\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> Set(Tv v)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    Setter(Data, i, v);\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Setter(Data, i, v);\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByCoord(Func<long, Tv> x_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(Data, i, x_elementFun(x));\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, x_elementFun(x));\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex(Func<long, Tv> index_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    Setter(Data, i, index_elementFun(i));\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Setter(Data, i, index_elementFun(i));\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly Vector<Td, Tv> Set(IVector<Tv> it1)\n        {\n            if (it1 is Vector<Tv>) return Set((Vector<Tv>)it1);\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(Data, i, it1[x]);\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, it1[x]);\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> Set(Vector<Tv> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, t1.Data[i1]);\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, t1.Data[i1]);\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// the elements of the supplied vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap<T1>(\n                Vector<T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1>(\n                Vector<T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> Set<T1>(Vector<T1, Tv> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// the elements of the supplied vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap<T1d, T1>(\n                Vector<T1d, T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1d, T1>(\n                Vector<T1d, T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap2<T1, T2>(\n                    Vector<T1> t1, Vector<T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1, T2>(\n                Vector<T1> t1, Vector<T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap2<T1, T2d, T2>(\n                    Vector<T1> t1, Vector<T2d, T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1, T2d, T2>(\n                Vector<T1> t1, Vector<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap2<T1d, T1, T2>(\n                    Vector<T1d, T1> t1, Vector<T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1d, T1, T2>(\n                Vector<T1d, T1> t1, Vector<T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a vector to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap2<T1d, T1, T2d, T2>(\n                    Vector<T1d, T1> t1, Vector<T2d, T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1d, T1, T2d, T2>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap3<T1, T2, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1, T2, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap3<T1, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap3<T1, T2d, T2, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1, T2d, T2, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap3<T1, T2d, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1, T2d, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap3<T1d, T1, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1d, T1, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap3<T1d, T1, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1d, T1, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap3<T1d, T1, T2d, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1d, T1, T2d, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetMap3<T1d, T1, T2d, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the\n        /// vector.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Vector<Td, Tv> SetByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the vector to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly Vector<Td, Tv> SetConvolution<Ti, Tf, Tm, Ts>(\n                Vector<Ti> image, Vector<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Tv> castFun)\n        {\n            Info.CheckMatchingSize(new VectorInfo(1L + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.SubVector(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Tv, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x));\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x));\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Vector<T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Vector<T1d, T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    }\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Tv, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long xs = Info.SX;\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x));\n                    if (breakIfTrueFun(result)) return result;\n                }\n            }\n            else\n            {\n                long xs = Info.DSX, xj = Info.JX;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x));\n                    if (breakIfTrueFun(result)) return result;\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Vector<T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Vector<T1d, T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long xs = Info.SX;\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n                else\n                {\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    }\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creator Functions\n\n        /// <summary>\n        /// Create a new vector as copy of the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Create(\n                Vector<Tv> t1)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new vector as copy of the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Create<T1d>(\n                Vector<T1d, Tv> t1)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map<T1>(\n                Vector<T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1>(\n                Vector<T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map<T1d, T1>(\n                Vector<T1d, T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1d, T1>(\n                Vector<T1d, T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map2<T1, T2>(\n                Vector<T1> t1, Vector<T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1, T2>(\n                Vector<T1> t1, Vector<T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map2<T1, T2d, T2>(\n                Vector<T1> t1, Vector<T2d, T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1, T2d, T2>(\n                Vector<T1> t1, Vector<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map2<T1d, T1, T2>(\n                Vector<T1d, T1> t1, Vector<T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1d, T1, T2>(\n                Vector<T1d, T1> t1, Vector<T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map2<T1d, T1, T2d, T2>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1d, T1, T2d, T2>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map3<T1, T2, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1, T2, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map3<T1, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map3<T1, T2d, T2, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1, T2d, T2, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map3<T1, T2d, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1, T2d, T2, T3d, T3>(\n                Vector<T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map3<T1d, T1, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1d, T1, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map3<T1d, T1, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1d, T1, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map3<T1d, T1, T2d, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1d, T1, T2d, T2, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function on each element of\n        /// the supplied vector.\n        /// </summary>\n        public static Vector<Td, Tv> Map3<T1d, T1, T2d, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to each index of the\n        /// elements of the supplied vector. The function may access the\n        /// elements of the supplied vector to compute the elements of the new\n        /// vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Vector<T1d, T1> t1, Vector<T2d, T2> t2, Vector<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Vector<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new vector by applying a function to the coordinates of\n        /// the elements the newly created vector.\n        /// </summary>\n        public static Vector<Td, Tv> Create(long size, Func<long, Tv> fun)\n        {\n            return new Vector<Td, Tv>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new Vector by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting Vector.\n        /// </summary>\n        public static Vector<Td, Tv> CreateConvolution<Ti, Tf, Tm, Ts>(\n                Vector<Ti> image, Vector<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Tv> castFun)\n        {\n            long size = 1 + image.S - filter.S;\n            if (size <= 0) throw new Exception(\"filter to large\");\n            return new Vector<Td, Tv>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        #endregion\n\n        #region Sampling\n\n        /// <summary>\n        /// Sample the vector using 2 samples and the supplied\n        /// interpolation function. If an integer coordinte is\n        /// supplied the returned value is the same as the indexer\n        /// of the vector. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw2<TRes>(\n                double x,\n                Func<double, Tv, Tv, TRes> ipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; long d = Info.Delta;\n            long i = Info.Origin + xi * d;\n            return ipl(x - xid, Getter(Data, i), Getter(Data, i + d));\n        }\n\n        public readonly TRes Sample2Clamped<TRes>(\n                double x,\n                Func<double, Tv, Tv, TRes> ipl)\n        {\n            return Sample2(x, ipl, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Sample the vector using 2 samples and the supplied\n        /// interpolation function. If an integer coordinte is\n        /// supplied the returned value is the same as the indexer\n        /// of the vector.\n        /// </summary>\n        public readonly TRes Sample2<TRes>(\n                double x,\n                Func<double, Tv, Tv, TRes> ipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            long i = Info.Origin + xi * d1;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            return ipl(xf, Getter(Data, i + d.E0), Getter(Data, i + d.E1));\n        }\n\n        public readonly TRes SampleRaw4<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, TRes> smp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d = Info.Delta;\n            long i1 = Info.Origin + xi * d, i2 = i1 + d;\n            var w = ipl(xf);\n            return smp(Getter(Data, i1 - d), Getter(Data, i1), Getter(Data, i2), Getter(Data, i2 + d), ref w);\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, TRes> smp)\n        {\n            return Sample4(x, ipl, smp, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample4<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, TRes> smp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            long i = Info.Origin + xi * d1;\n            var w = ipl(xf);\n            return smp(Getter(Data, i + d.E0), Getter(Data, i + d.E1), Getter(Data, i + d.E2), Getter(Data, i + d.E3), ref w);\n        }\n\n        public readonly TRes SampleRaw6<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, TRes> smp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d = Info.Delta;\n            long i2 = Info.Origin + xi * d, i1 = i2 - d, i3 = i2 + d, i4 = i3 + d;\n            var w = ipl(xf);\n            return smp(Getter(Data, i1 - d), Getter(Data, i1), Getter(Data, i2), Getter(Data, i3), Getter(Data, i4), Getter(Data, i4 + d), ref w);\n        }\n\n        public readonly TRes Sample6Clamped<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, TRes> smp)\n        {\n            return Sample6(x, ipl, smp, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample6<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, TRes> smp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            long i = Info.Origin + xi * d1;\n            var w = ipl(xf);\n            return smp(Getter(Data, i + d.E0), Getter(Data, i + d.E1), Getter(Data, i + d.E2), Getter(Data, i + d.E3), Getter(Data, i + d.E4), Getter(Data, i + d.E5), ref w);\n        }\n\n        #endregion\n\n        #region IVector\n\n        /// <summary>\n        /// Dimension of the generic Vector.\n        /// </summary>\n        public readonly long Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(long x)\n        {\n            return (object)this[x];\n        }\n\n        public readonly void SetValue(object value, long x)\n        {\n            this[x] = (Tv)value;\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    #region MatrixInfo\n\n    /// <summary>\n    /// A matrix info contains the complete indexing information for a matrix, but no data array.\n    /// </summary>\n    [Serializable]\n    public struct MatrixInfo : ITensorInfo\n    {\n        /// <summary>\n        /// Index of element with coordinates [0, 0] in the underlying data array.\n        /// </summary>\n        public long Origin;\n\n        /// <summary>\n        /// Size of the matrix.\n        /// </summary>\n        public V2l Size;\n\n        /// <summary>\n        /// Element and line stride.\n        /// </summary>\n        public V2l Delta;\n\n        /// <summary>\n        /// Coordinates of the first element.\n        /// May differ from coordinates [0, 0] for subwindows that retain the original coordinate space.\n        /// </summary>\n        public V2l First;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a MatrixInfo given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the matrix.</param>\n        /// <param name=\"delta\">Element and line stride.</param>\n        /// <param name=\"first\">Coordinates of the first element.</param>\n        public MatrixInfo(long origin, V2l size, V2l delta, V2l first)\n        {\n            Origin = origin;\n            Size = size;\n            Delta = delta;\n            First = first;\n        }\n\n        /// <summary>\n        /// Construct a MatrixInfo given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the matrix.</param>\n        /// <param name=\"delta\">Element and line stride.</param>\n        public MatrixInfo(long origin, V2l size, V2l delta)\n            : this(origin, size, delta, V2l.Zero)\n        { }\n\n        private static V2l NewDelta(V2l size)\n        {\n            return new V2l(1L, size.X);\n        }\n\n        private static V2l NewDelta(V2l size, V2l delta)\n        {\n            if (delta.Y == 1L) return new V2l(size.Y, 1L);\n            return NewDelta(size);\n        }\n\n        /// <summary>\n        /// Construct matrix info of specified size.\n        /// </summary>\n        public MatrixInfo(V2l size)\n            : this(0L, size, NewDelta(size))\n        { }\n\n        /// <summary>\n        /// Construct matrix info of specified size and delta.\n        /// </summary>\n        public MatrixInfo(V2l size, V2l delta)\n            : this(0L, size, NewDelta(size, delta))\n        { }\n\n        public MatrixInfo(MatrixInfo info)\n            : this(0L, info.Size, NewDelta(info.Size, info.Delta))\n        {\n            F = info.F;\n        }\n\n        /// <summary>\n        /// Construct matrix info of specified size.\n        /// </summary>\n        public MatrixInfo(V2i size)\n            : this((V2l)size)\n        { }\n\n        /// <summary>\n        /// Construct matrix info of specified size and delta.\n        /// </summary>\n        public MatrixInfo(V2i size, V2i delta)\n            : this((V2l)size, (V2l)delta)\n        { }\n\n        /// <summary>\n        /// Construct matrix info of specified size.\n        /// </summary>\n        public MatrixInfo(long sizeX, long sizeY)\n            : this(new V2l(sizeX, sizeY))\n        { }\n\n        /// <summary>\n        /// Construct matrix info of specified size.\n        /// </summary>\n        public MatrixInfo(int sizeX, int sizeY)\n            : this(new V2l(sizeX, sizeY))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the the matrix (2).\n        /// </summary>\n        public readonly int Rank { get { return 2; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return  Size.X *  Size.Y; } }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        public readonly V2l End { get { return First + Size; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OO { get { return First; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IO { get { return new V2l(First.X + Size.X, First.Y); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OI { get { return new V2l(First.X, First.Y + Size.Y); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l II { get { return First + Size; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l S { readonly get { return Size; } set { Size = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l D { readonly get { return Delta; } set { Delta = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l F { readonly get { return First; } set { Origin -= Delta.Dot(value - First); First = value; } }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l E { get { return First + Size; } }\n\n        /// <summary>\n        /// Size.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Size.X; } set { Size.X = value; } }\n\n        /// <summary>\n        /// Size.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Size.Y; } set { Size.Y = value; } }\n\n        /// <summary>\n        /// Delta.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Delta.X; } set { Delta.X = value; } }\n\n        /// <summary>\n        /// Delta.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Delta.Y; } set { Delta.Y = value; } }\n\n        /// <summary>\n        /// First.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX\n        {\n            readonly get { return First.X; }\n            set { Origin -= Delta.X * (value - First.X); First.X = value; }\n        }\n\n        /// <summary>\n        /// First.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY\n        {\n            readonly get { return First.Y; }\n            set { Origin -= Delta.Y * (value - First.Y); First.Y = value; }\n        }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX\n        {\n            get { return First.X + Size.X; }\n        }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY\n        {\n            get { return First.Y + Size.Y; }\n        }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Size.X * Delta.X; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Size.Y * Delta.Y; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Delta.X; } }\n\n        public readonly long GetJX(V2l size)\n        {\n            return Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Delta.Y - Size.X * Delta.X; } }\n\n        public readonly long GetJY(V2l size)\n        {\n            return Delta.Y - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX0 { get { return Delta.X; } }\n\n        public readonly long GetJX0(V2l size)\n        {\n            return Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JXY { get { return Delta.X - Size.Y * Delta.Y; } }\n\n        public readonly long GetJXY(V2l size)\n        {\n            return Delta.X - size.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JYX { get { return Delta.Y - Size.X * Delta.X; } }\n\n        public readonly long GetJYX(V2l size)\n        {\n            return Delta.Y - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY0 { get { return Delta.Y; } }\n\n        public readonly long GetJY0(V2l size)\n        {\n            return Delta.Y;\n        }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Index(First); } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long OriginIndex { readonly get { return Origin; } set { Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return new long[] { SX, SY }; }\n            set { SX = value[0]; SY = value[1];  }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return new long[] { DX, DY }; }\n            set { DX = value[0]; DY = value[1];  }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return new long[] { FX, FY }; }\n            set { FX = value[0]; FY = value[1];  }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        public readonly MatrixInfo Transposed\n        {\n            get { return new MatrixInfo(Origin, Size.YX, Delta.YX, First.YX); }\n        }\n\n        #endregion\n\n        #region Indexing Helper Methods\n\n        public readonly long Dv(long dx, long dy)\n        {\n            return dx * Delta.X + dy * Delta.Y;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(long x, long y)\n        {\n            return Origin + x * Delta.X + y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(V2l v)\n        {\n            return Origin + v.X * Delta.X + v.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(V2i v)\n        {\n            return Origin + v.X * Delta.X + v.Y * Delta.Y;\n        }\n\n        #endregion\n\n        #region Interpretation and Parts\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly MatrixInfo SubMatrixWindow(V2l begin, V2l size)\n        {\n            return new MatrixInfo(Origin, size, Delta, begin);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(V2l begin, V2l size)\n        {\n            return new MatrixInfo(Index(begin), size, Delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly MatrixInfo SubMatrixWindow(V2i begin, V2i size)\n        {\n            return new MatrixInfo(Origin, (V2l)size, Delta, (V2l)begin);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(V2i begin, V2i size)\n        {\n            return new MatrixInfo(Index((V2l)begin), (V2l)size, Delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly MatrixInfo SubMatrixWindow(V2l begin, V2l size, V2l delta)\n        {\n            return new MatrixInfo(Origin, size, delta, begin);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(V2l begin, V2l size, V2l delta)\n        {\n            return new MatrixInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly MatrixInfo SubMatrixWindow(V2i begin, V2i size, V2i delta)\n        {\n            return new MatrixInfo(Origin, (V2l)size, (V2l)delta, (V2l)begin);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(V2i begin, V2i size, V2i delta)\n        {\n            return new MatrixInfo(Index((V2l)begin), (V2l)size, (V2l)delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly MatrixInfo SubMatrixWindow(V2l begin, V2l size, V2l delta, V2l first)\n        {\n            return new MatrixInfo(Index(begin), size, delta) { F = first };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly MatrixInfo SubMatrixWindow(V2i begin, V2i size, V2i delta, V2i first)\n        {\n            return new MatrixInfo(Index((V2l)begin), (V2l)size, (V2l)delta)\n                            { F = (V2l)first };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly MatrixInfo SubMatrixWindow(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new MatrixInfo(Origin, new V2l(sizeX, sizeY),\n                                  Delta, new V2l(beginX, beginY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new MatrixInfo(Index(beginX, beginY),\n                                  new V2l(sizeX, sizeY),\n                                  Delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly MatrixInfo SubMatrixWindow(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new MatrixInfo(Origin, new V2l(sizeX, sizeY),\n                                  new V2l(deltaX, deltaY),\n                                  new V2l(beginX, beginY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new MatrixInfo(Index(beginX, beginY),\n                                  new V2l(sizeX, sizeY),\n                                  new V2l(deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(V2l begin, long size, long delta)\n        {\n            return new VectorInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(V2i begin, long size, long delta)\n        {\n            return new VectorInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// If the lines of the matrix are stored consecutively without gaps,\n        /// the whole matrix can be viewed as a single vector.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo AsVector()\n        {\n            if (JY != 0)\n                throw new Exception(\"cannot represent this matrix as vector\");\n            return new VectorInfo(Origin, SX * SY, DX);\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo Col(long x)\n        {\n            return new VectorInfo(Index(x, FY), S.Y, D.Y);\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly VectorInfo ColWindow(long x)\n        {\n            return new VectorInfo(Index(x, FY), S.Y, D.Y)\n            { F = F.Y };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo Row(long y)\n        {\n            return new VectorInfo(Index(FX, y), S.X, D.X);\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly VectorInfo RowWindow(long y)\n        {\n            return new VectorInfo(Index(FX, y), S.X, D.X)\n            { F = F.X };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubYVector(long x)\n        {\n            return new VectorInfo(Index(x, FY), S.Y, D.Y);\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubYVectorAsReadOnlyMatrix(long x, long sizex)\n        {\n            return new MatrixInfo(Index(x, FY), new V2l(sizex, SY), D.OY);\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly VectorInfo SubYVectorWindow(long x)\n        {\n            return new VectorInfo(Index(x, FY), S.Y, D.Y) { F = F.Y };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly MatrixInfo SubYVectorAsReadOnlyMatrixWindow(long x, long sizex)\n        {\n            return new MatrixInfo(Index(x, FY), new V2l(sizex, SY), D.OY) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubXVector(long y)\n        {\n            return new VectorInfo(Index(FX, y), S.X, D.X);\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubXVectorAsReadOnlyMatrix(long y, long sizey)\n        {\n            return new MatrixInfo(Index(FX, y), new V2l(SX, sizey), D.XO);\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly VectorInfo SubXVectorWindow(long y)\n        {\n            return new VectorInfo(Index(FX, y), S.X, D.X) { F = F.X };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly MatrixInfo SubXVectorAsReadOnlyMatrixWindow(long y, long sizey)\n        {\n            return new MatrixInfo(Index(FX, y), new V2l(SX, sizey), D.XO) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubItemAsReadOnlyMatrix(long x, long y, long sizex, long sizey)\n        {\n            return new MatrixInfo(Index(x, y), new V2l(sizex, sizey), V2l.Zero);\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly MatrixInfo SubItemAsReadOnlyMatrixWindow(long x, long y, long sizex, long sizey)\n        {\n            return new MatrixInfo(Index(x, y), new V2l(sizex, sizey), V2l.Zero) { F = F };\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    i_action(i);\n                } }\n            }\n            else if (DY == 1)\n            {\n                long xs = DSX, xj = JXY;\n                long ys = SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    i_action(i);\n                } }\n            }\n            else\n            {\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    i_action(i);\n                } }\n            }\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long> x_y_i_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    x_y_i_action(x, y, i);\n                } }\n            }\n            else if (DY == 1)\n            {\n                long xs = DSX, xj = JXY;\n                long ys = SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    x_y_i_action(x, y, i);\n                } }\n            }\n            else\n            {\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    x_y_i_action(x, y, i);\n                } }\n            }\n        }\n\n        public readonly void ForeachCoord(Action<V2l> v_action)\n        {\n            long i = FirstIndex; V2l v;\n            if (DX == 1)\n            {\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    v_action(v);\n                } }\n            }\n            else if (DY == 1)\n            {\n                long xs = DSX, xj = JXY;\n                long ys = SY;\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i++, v.Y++) {\n                    v_action(v);\n                } }\n            }\n            else\n            {\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    v_action(v);\n                } }\n            }\n        }\n\n        public readonly void ForeachIndex(MatrixInfo t1, Action<long, long> i_i1_act)\n        {\n            CheckMatchingSize(t1);\n            if (HasMatchingLayout(t1))\n            {\n                long i = FirstIndex;\n                if (DX == 1)\n                {\n                    long ys = DSY, yj = JY;\n                    long xs = SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        i_i1_act(i, i);\n                    } }\n                }\n                else if (DY == 1)\n                {\n                    long xs = DSX, xj = JXY;\n                    long ys = SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        i_i1_act(i, i);\n                    } }\n                }\n                else\n                {\n                    long ys = DSY, yj = JY;\n                    long xs = DSX, xj = JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        i_i1_act(i, i);\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (DX == 1 && t1.DX == 1)\n                {\n                    long ys = DSY, yj = JY, yj1 = t1.JY;\n                    long xs = SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        i_i1_act(i, i1);\n                    } }\n                }\n                else if (DY == 1 && t1.DY == 1)\n                {\n                    long xs = DSX, xj = JXY, xj1 = t1.JXY;\n                    long ys = SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        i_i1_act(i, i1);\n                    } }\n                }\n                else\n                {\n                    long ys = DSY, yj = JY, yj1 = t1.JY;\n                    long xs = DSX, xj = JX, xj1 = t1.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        i_i1_act(i, i1);\n                    } }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0, x = FX; i != xe; i += xj, x++)\n                x_elementAct(x);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0, y = FY; i != ye; i += yj, y++)\n                y_elementAct(y);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0, x = FX; i != xe; i += xj, x++)\n                x_i_elementAct(x, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0, y = FY; i != ye; i += yj, y++)\n                y_i_elementAct(y, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(MatrixInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + DSX, xj = JX0, xj1 = t1.JX0; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(MatrixInfo t1, \n                Action<long, long, long> x_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + DSX, xj = JX0, xj1 = t1.JX0, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                x_i_i1_elementAct(x, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(MatrixInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + DSY, yj = JY0, yj1 = t1.JY0; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(MatrixInfo t1, \n                Action<long, long, long> y_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + DSY, yj = JY0, yj1 = t1.JY0, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                y_i_i1_elementAct(y, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(MatrixInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(MatrixInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(MatrixInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(MatrixInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(MatrixInfo t1, \n                Action<long, long, long, long> x_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(MatrixInfo t1, \n                Action<long, long, long, long> x_y_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(MatrixInfo t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(MatrixInfo t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_y_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(MatrixInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(MatrixInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(MatrixInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(MatrixInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(MatrixInfo t1, \n                Action<long, long, long, long> y_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(MatrixInfo t1, \n                Action<long, long, long, long> y_x_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(MatrixInfo t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(MatrixInfo t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_x_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        #endregion\n\n        #region Checking\n\n        public readonly void CheckMatchingSize(MatrixInfo t1)\n        {\n            if (Size != t1.Size) throw new ArgumentException(\"size mismatch\");\n        }\n\n        public readonly void CheckMatchingSize(MatrixInfo t1, MatrixInfo t2)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2);\n        }\n\n        public readonly void CheckMatchingSize(MatrixInfo t1, MatrixInfo t2, MatrixInfo t3)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2); CheckMatchingSize(t3);\n        }\n\n        public readonly bool HasMatchingLayout(MatrixInfo t1)\n        {\n            return First == t1.First && Origin == t1.Origin && Delta == t1.Delta;\n        }\n\n        public readonly bool HasMatchingLayout(MatrixInfo t1, MatrixInfo t2)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2);\n        }\n\n        public readonly bool HasMatchingLayout(MatrixInfo t1, MatrixInfo t2, MatrixInfo t3)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2) && HasMatchingLayout(t3);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Matrix<Td>\n\n    /// <summary>\n    /// Generic matrix of elements with arbitrary stride.\n    /// All sizes are given as 2-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The matrix does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on matrixs are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// 2 stride direction(s) are called DX, DY, aso.\n    /// </summary>\n    /// <typeparam name=\"Td\">data element type</typeparam>\n    [Serializable]\n    public partial struct Matrix<Td> : IValidity, IMatrix<Td>, IArrayMatrix\n    {\n        public Td[] Data;\n        public MatrixInfo Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public Matrix(Td[] data, MatrixInfo info)\n        {\n            Data = data;\n            Info = info;\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size.\n        /// </summary>\n        public Matrix(V2l size)\n            : this(new Td[size.X * size.Y], new MatrixInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct matrix of specified size.\n        /// </summary>\n        public Matrix(V2i size)\n            : this((V2l)size)\n        { }\n\n        /// <summary>\n        /// Construct matrix with specified info.\n        /// </summary>\n        public Matrix(MatrixInfo info)\n            : this(new Td[info.Count], new MatrixInfo(info))\n        { }\n\n        /// <summary>\n        /// Construct matrix of specified size.\n        /// </summary>\n        public Matrix(long sx, long sy)\n            : this(new V2l(sx, sy))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Matrix(Td[] data, long sx, long sy)\n            : this(data, new MatrixInfo(sx, sy))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and sets all elements to the supplied value.\n        /// </summary>\n        public Matrix(long sx, long sy, Td value)\n            : this(new V2l(sx, sy), value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Matrix(Td[] data, V2l size)\n            : this(data, new MatrixInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Matrix(Td[] data, V2i size)\n            : this(data, new MatrixInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Matrix(V2l size, Td value)\n            : this(new Td[size.X * size.Y], new MatrixInfo(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Matrix(V2i size, Td value)\n            : this((V2l)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Matrix(Td[] data, long origin, V2l size, V2l delta)\n            : this(data, new MatrixInfo(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Matrix(Td[] data, long origin, V2l size, V2l delta, V2l first)\n            : this(data, new MatrixInfo(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public Matrix(long origin, V2l size, V2l delta)\n            : this(new Td[size.X * size.Y],\n                   new MatrixInfo(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the matrix (2).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public V2l Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public V2l Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public V2l First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        /// <summary>\n        /// Returns true if the matrix has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the matrix does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly V2l End { get { return Info.E; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OO { get { return Info.OO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IO { get { return Info.IO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OI { get { return Info.OI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l II { get { return Info.II; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l E { get { return Info.E; } }\n\n        /// <summary>\n        /// Size in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Info.SX; } set { Info.SX = value; } }\n\n        /// <summary>\n        /// Size in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Info.SY; } set { Info.SY = value; } }\n\n        /// <summary>\n        /// Delta in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Info.DX; } set { Info.DX = value; } }\n\n        /// <summary>\n        /// Delta in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Info.DY; } set { Info.DY = value; } }\n\n        /// <summary>\n        /// First in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return Info.FX; } set { Info.FX = value; } }\n\n        /// <summary>\n        /// First in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY { readonly get { return Info.FY; } set { Info.FY = value; } }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return Info.EX; } }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY { get { return Info.EY; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Info.JX; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Info.JY; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Info.DSX; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Info.DSY; } }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<Td> Elements\n        {\n            get\n            {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    yield return Data[i];\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    yield return Data[i];\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    yield return Data[i];\n                } }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(Td[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (Td[])value; }\n        }\n\n        /// <summary>\n        /// Returns a matrix that represents a view on the same data with flipped coordinates.\n        /// </summary>\n        public readonly Matrix<Td> Transposed\n        {\n            get\n            {\n                return new Matrix<Td>(Data, Info.Transposed);\n            }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Td this[V2l v]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + v.X * Info.Delta.X + v.Y * Info.Delta.Y];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + v.X * Info.Delta.X + v.Y * Info.Delta.Y] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Td this[V2i v]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at the specified index in the underlying data array.\n        /// </summary>\n        public readonly Td this[long index]\n        {\n            get\n            {\n                return Data[index];\n            }\n            set\n            {\n                Data[index] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Td this[long x, long y]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + x * Info.Delta.X + y * Info.Delta.Y];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + x * Info.Delta.X + y * Info.Delta.Y] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Td this[int x, int y]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + (long)x * Info.Delta.X + (long)y * Info.Delta.Y];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + (long)x * Info.Delta.X + (long)y * Info.Delta.Y] = value;\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long> x_y_i_action)\n        {\n            Info.ForeachIndex(x_y_i_action);\n        }\n\n        public readonly void ForeachCoord(Action<V2l> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(MatrixInfo t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            Info.ForeachX(x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            Info.ForeachY(y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            Info.ForeachXIndex(x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            Info.ForeachYIndex(y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrixWindow(V2l begin, V2l size)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrixWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(V2l begin, V2l size)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrix(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrixWindow(V2i begin, V2i size)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrixWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(V2i begin, V2i size)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrix(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrixWindow(V2l begin, V2l size, V2l delta)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrixWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(V2l begin, V2l size, V2l delta)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrix(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrixWindow(V2i begin, V2i size, V2i delta)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrixWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(V2i begin, V2i size, V2i delta)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrix(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrixWindow(V2l begin, V2l size, V2l delta, V2l first)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrixWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrixWindow(V2i begin, V2i size, V2i delta, V2i first)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrixWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrixWindow(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new Matrix<Td>(Data,\n                            Info.SubMatrixWindow(beginX, beginY,\n                                           sizeX, sizeY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new Matrix<Td>(Data,\n                            Info.SubMatrix(beginX, beginY,\n                                               sizeX, sizeY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrixWindow(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new Matrix<Td>(Data,\n                            Info.SubMatrixWindow(beginX, beginY,\n                                           sizeX, sizeY,\n                                           deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new Matrix<Td>(Data,\n                            Info.SubMatrix(beginX, beginY,\n                                               sizeX, sizeY,\n                                               deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// If the lines of the matrix are stored consecutively without gaps,\n        /// the whole matrix can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td> AsVector()\n        {\n            return new Vector<Td>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td> SubVector(V2l origin, long size, long delta)\n        {\n            return new Vector<Td>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td> SubVector(V2i origin, long size, long delta)\n        {\n            return new Vector<Td>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> Col(long x)\n        {\n            return new Vector<Td>(Data, Info.Col(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td> ColWindow(long x)\n        {\n            return new Vector<Td>(Data, Info.ColWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> Row(long y)\n        {\n            return new Vector<Td>(Data, Info.Row(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td> RowWindow(long y)\n        {\n            return new Vector<Td>(Data, Info.RowWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> SubYVector(long x)\n        {\n            return new Vector<Td>(Data, Info.SubYVector(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubYVectorAsReadOnlyMatrix(long x, long sizex)\n        {\n            return new Matrix<Td>(Data, Info.SubYVectorAsReadOnlyMatrix(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td> SubYVectorWindow(long x)\n        {\n            return new Vector<Td>(Data, Info.SubYVectorWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubYVectorAsReadOnlyMatrixWindow(long x, long sizex)\n        {\n            return new Matrix<Td>(Data, Info.SubYVectorAsReadOnlyMatrixWindow(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td> SubXVector(long y)\n        {\n            return new Vector<Td>(Data, Info.SubXVector(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubXVectorAsReadOnlyMatrix(long y, long sizey)\n        {\n            return new Matrix<Td>(Data, Info.SubXVectorAsReadOnlyMatrix(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td> SubXVectorWindow(long y)\n        {\n            return new Vector<Td>(Data, Info.SubXVectorWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubXVectorAsReadOnlyMatrixWindow(long y, long sizey)\n        {\n            return new Matrix<Td>(Data, Info.SubXVectorAsReadOnlyMatrixWindow(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubItemAsReadOnlyMatrix(long x, long y, long sizex, long sizey)\n        {\n            return new Matrix<Td>(Data, Info.SubItemAsReadOnlyMatrix(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td> SubItemAsReadOnlyMatrixWindow(long x, long y, long sizex, long sizey)\n        {\n            return new Matrix<Td>(Data, Info.SubItemAsReadOnlyMatrixWindow(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2l begin, V2l size)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V2l begin, V2l size)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2i begin, V2i size)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V2i begin, V2i size)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2l begin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V2l begin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2i begin, V2i size, V2i delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V2i begin, V2i size, V2i delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2l begin, V2l size, V2l delta, V2l first)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2i begin, V2i size, V2i delta, V2i first)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new Matrix<Td, T1>(Data,\n                            Info.SubMatrixWindow(beginX, beginY,\n                                           sizeX, sizeY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new Matrix<Td, T1>(Data,\n                            Info.SubMatrix(beginX, beginY,\n                                               sizeX, sizeY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new Matrix<Td, T1>(Data,\n                            Info.SubMatrixWindow(beginX, beginY,\n                                           sizeX, sizeY,\n                                           deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new Matrix<Td, T1>(Data,\n                            Info.SubMatrix(beginX, beginY,\n                                               sizeX, sizeY,\n                                               deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// If the lines of the matrix are stored consecutively without gaps,\n        /// the whole matrix can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, T1> AsVector<T1>()\n        {\n            return new Vector<Td, T1>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V2l origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V2i origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> Col<T1>(long x)\n        {\n            return new Vector<Td, T1>(Data, Info.Col(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, T1> ColWindow<T1>(long x)\n        {\n            return new Vector<Td, T1>(Data, Info.ColWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> Row<T1>(long y)\n        {\n            return new Vector<Td, T1>(Data, Info.Row(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, T1> RowWindow<T1>(long y)\n        {\n            return new Vector<Td, T1>(Data, Info.RowWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubYVector<T1>(long x)\n        {\n            return new Vector<Td, T1>(Data, Info.SubYVector(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubYVectorAsReadOnlyMatrix<T1>(long x, long sizex)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubYVectorAsReadOnlyMatrix(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, T1> SubYVectorWindow<T1>(long x)\n        {\n            return new Vector<Td, T1>(Data, Info.SubYVectorWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubYVectorAsReadOnlyMatrixWindow<T1>(long x, long sizex)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubYVectorAsReadOnlyMatrixWindow(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubXVector<T1>(long y)\n        {\n            return new Vector<Td, T1>(Data, Info.SubXVector(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXVectorAsReadOnlyMatrix<T1>(long y, long sizey)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXVectorAsReadOnlyMatrix(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, T1> SubXVectorWindow<T1>(long y)\n        {\n            return new Vector<Td, T1>(Data, Info.SubXVectorWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXVectorAsReadOnlyMatrixWindow<T1>(long y, long sizey)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXVectorAsReadOnlyMatrixWindow(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubItemAsReadOnlyMatrix<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubItemAsReadOnlyMatrix(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubItemAsReadOnlyMatrixWindow<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubItemAsReadOnlyMatrixWindow(x, y, sizex, sizey));\n        }\n\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> Copy()\n        {\n            return new Matrix<Td>(Info.S).Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original Matrix.\n        /// </summary>\n        public readonly Matrix<Td> CopyWindow()\n        {\n            return new Matrix<Td>(Info.S)\n                    { F = F,  }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<T1> Map<T1>(Func<Td, T1> fun)\n        {\n            return new Matrix<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original Matrix.\n        /// </summary>\n        public readonly Matrix<T1> MapWindow<T1>(Func<Td, T1> fun)\n        {\n            return new Matrix<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Returns a tensor repeated in each dimension by the specified\n        /// count.\n        /// </summary>\n        public readonly Matrix<Td> Repeated(V2l count)\n        {\n            var size = Size;\n            count *= size;\n            var t = new Matrix<Td>(count);\n            V2l p;\n            for (p.Y = 0; p.Y < count.Y; p.Y += size.Y)\n            for (p.X = 0; p.X < count.X; p.X += size.X)\n                t.SubMatrix(p, size).Set(this);\n            return t;\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the matrix.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> Apply(Func<Td, Td> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.SX; i != xe; i++)\n                    Data[i] = element_elementFun(Data[i]);\n            }\n            else\n            {\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj)\n                    Data[i] = element_elementFun(Data[i]);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original matrix and the supplied matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> Apply<T1>(\n                Matrix<T1> t1, Func<Td, T1, Td> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original matrix and the supplied matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> Apply<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<Td, T1, Td> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the matrix.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> ApplyByCoord(Func<Td, V2l, Td> element_crd_elementFun)\n        {\n            long i = FirstIndex; V2l vi;\n            if (Info.JX == 1)\n            {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.SX; i != xe; i++, vi.X++)\n                    Data[i] = element_crd_elementFun(Data[i], vi);\n                }\n            }\n            else\n            {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj, vi.X++)\n                {\n                    Data[i] = element_crd_elementFun(Data[i], vi);\n                }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> ApplyByCoord(Func<Td, long, long, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    Data[i] = fun(Data[i], x, y);\n            }\n            else\n            {\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.DSX, xj = Info.JX, x = Info.FX; i != xe; i += xj, x++)\n                    Data[i] = fun(Data[i], x, y);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> Set(Td v)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Data[i] = v;\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    Data[i] = v;\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Data[i] = v;\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByCoord(Func<long, long, Td> x_y_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Data[i] = x_y_elementFun(x, y);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Data[i] = x_y_elementFun(x, y);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Data[i] = x_y_elementFun(x, y);\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByCoord(Func<V2l, Td> crd_elementFun)\n        {\n            long i = FirstIndex; V2l v;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    Data[i] = crd_elementFun(v);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i++, v.Y++) {\n                    Data[i] = crd_elementFun(v);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    Data[i] = crd_elementFun(v);\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByCoord<Ty>(\n                Func<long, Ty> yFun,\n                Func<long, long, Ty, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(y);\n                for (long xe = i + xs, x = Info.FX; i != xe; i++, x++) {\n                    Data[i] = fun(y, x, yVal);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(y);\n                for (long xe = i + xs, x = Info.FX; i != xe; i += xj, x++) {\n                    Data[i] = fun(y, x, yVal);\n                } }\n            }\n\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex(Func<long, Td> index_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Data[i] = index_elementFun(i);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    Data[i] = index_elementFun(i);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Data[i] = index_elementFun(i);\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly Matrix<Td> Set(IMatrix<Td> it1)\n        {\n            if (it1 is Matrix<Td>) return Set((Matrix<Td>)it1);\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Data[i] = it1[x, y];\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Data[i] = it1[x, y];\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Data[i] = it1[x, y];\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> Set(Matrix<Td> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = t1.Data[i];\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        Data[i] = t1.Data[i];\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = t1.Data[i];\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = t1.Data[i1];\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Data[i] = t1.Data[i1];\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = t1.Data[i1];\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// the elements of the supplied matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap<T1>(\n                Matrix<T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1>(\n                Matrix<T1> t1, Func<long, Td> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_elementFun(i);\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        Data[i] = index1_elementFun(i);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_elementFun(i);\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = index1_elementFun(i1);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> Set<T1>(Matrix<T1, Td> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// the elements of the supplied matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<long, Td> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = index1_elementFun(i1);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap2<T1, T2>(\n                    Matrix<T1> t1, Matrix<T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1, T2>(\n                Matrix<T1> t1, Matrix<T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap2<T1, T2d, T2>(\n                    Matrix<T1> t1, Matrix<T2d, T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1, T2d, T2>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap2<T1d, T1, T2>(\n                    Matrix<T1d, T1> t1, Matrix<T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1d, T1, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap2<T1d, T1, T2d, T2>(\n                    Matrix<T1d, T1> t1, Matrix<T2d, T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1d, T1, T2d, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap3<T1, T2, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info, t3.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1, T2, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info, t3.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap3<T1, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap3<T1, T2d, T2, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1, T2d, T2, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap3<T1, T2d, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1, T2d, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap3<T1d, T1, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1d, T1, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap3<T1d, T1, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1d, T1, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap3<T1d, T1, T2d, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1d, T1, T2d, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetMap3<T1d, T1, T2d, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly Matrix<Td> SetConvolution<Ti, Tf, Tm, Ts>(\n                Matrix<Ti> image, Matrix<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Td> castFun)\n        {\n            Info.CheckMatchingSize(new MatrixInfo(V2l.One + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.SubMatrix(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetOuterProduct<Tx, Ty>(\n                    Vector<Tx> tx, Vector<Ty> ty,\n                    Func<Tx, Ty, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2]);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2]);\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetOuterProduct<Tx, Tyd, Ty>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty,\n                    Func<Tx, Ty, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2));\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetOuterProduct<Txd, Tx, Ty>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty,\n                    Func<Tx, Ty, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2]);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2]);\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td> SetOuterProduct<Txd, Tx, Tyd, Ty>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty,\n                    Func<Tx, Ty, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2));\n                } }\n            }\n            return this;\n        }\n\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Td, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    result = sumFun(result, elementFun(Data[i], x, y));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y));\n                } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, V2l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V2l v;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i++, v.Y++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Matrix<T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Matrix<T1d, T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Td, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    result = sumFun(result, elementFun(Data[i], x, y));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, V2l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V2l v;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i++, v.Y++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Matrix<T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else if (Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ye = i + ys; i != ye; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Matrix<T1d, T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creator Functions\n\n        /// <summary>\n        /// Create a new matrix as copy of the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Create(\n                Matrix<Td> t1)\n        {\n            return new Matrix<Td>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new matrix as copy of the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Create<T1d>(\n                Matrix<T1d, Td> t1)\n        {\n            return new Matrix<Td>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map<T1>(\n                Matrix<T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1>(\n                Matrix<T1> t1, Func<long, Td> index1_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<long, Td> index1_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map2<T1, T2>(\n                Matrix<T1> t1, Matrix<T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1, T2>(\n                Matrix<T1> t1, Matrix<T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map2<T1, T2d, T2>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1, T2d, T2>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map2<T1d, T1, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1d, T1, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map2<T1d, T1, T2d, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1d, T1, T2d, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map3<T1, T2, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1, T2, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map3<T1, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map3<T1, T2d, T2, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1, T2d, T2, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map3<T1, T2d, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1, T2d, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map3<T1d, T1, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1d, T1, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map3<T1d, T1, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1d, T1, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map3<T1d, T1, T2d, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1d, T1, T2d, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td> Map3<T1d, T1, T2d, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td> CreateByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to the coordinates of\n        /// the elements the newly created matrix.\n        /// </summary>\n        public static Matrix<Td> Create(V2l size, Func<V2l, Td> fun)\n        {\n            return new Matrix<Td>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new Matrix by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting Matrix.\n        /// </summary>\n        public static Matrix<Td> CreateConvolution<Ti, Tf, Tm, Ts>(\n                Matrix<Ti> image, Matrix<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Td> castFun)\n        {\n            V2l size = 1 + image.S - filter.S;\n            if (size.Y <= 0 ||size.X <= 0) throw new Exception(\"filter to large\");\n            return new Matrix<Td>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static Matrix<Td> CreateOuterProduct<Tx, Ty>(\n                    Vector<Tx> tx, Vector<Ty> ty,\n                    Func<Tx, Ty, Td> fun)\n        {\n            return new Matrix<Td>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<Tx, Ty>(tx, ty, fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static Matrix<Td> CreateOuterProduct<Tx, Tyd, Ty>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty,\n                    Func<Tx, Ty, Td> fun)\n        {\n            return new Matrix<Td>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<Tx, Tyd, Ty>(tx, ty, fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static Matrix<Td> CreateOuterProduct<Txd, Tx, Ty>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty,\n                    Func<Tx, Ty, Td> fun)\n        {\n            return new Matrix<Td>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<Txd, Tx, Ty>(tx, ty, fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static Matrix<Td> CreateOuterProduct<Txd, Tx, Tyd, Ty>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty,\n                    Func<Tx, Ty, Td> fun)\n        {\n            return new Matrix<Td>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty>(tx, ty, fun);\n        }\n\n        #endregion\n\n        #region Sampling\n\n        public readonly TRes SampleRaw4<T1, TRes>(\n                V2d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return SampleRaw4(v.X, v.Y, xipl, yipl);\n        }\n\n        /// <summary>\n        /// Sample the matrix using 4 samples and the supplied\n        /// interpolation function. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the matrix, i.e. pixel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw4<T1, TRes>(\n                double x, double y,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long i0 = Info.Origin + xi * dx + yi * dy, i1 = i0 + dy;\n            return yipl(yf, xipl(xf, Data[i0], Data[i0 + dx]),\n                            xipl(xf, Data[i1], Data[i1 + dx]));\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                V2d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return Sample4(v.X, v.Y, xipl, yipl,\n                           Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                double x, double y,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return Sample4(x, y, xipl, yipl,\n                           Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample4<T1, TRes>(\n                V2d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, TRes> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample4(v.X, v.Y, xipl, yipl,\n                           index_min_max_delta_xIndexFun,\n                           index_min_max_delta_yIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the matrix using 4 samples and the supplied\n        /// interpolation functions., If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the matrix, i.e. pixel centers are assumed to be on\n        /// integer coordinates.\n        /// </summary>\n        public readonly TRes Sample4<T1, TRes>(\n                double x, double y,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, TRes> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            return yipl(yf, xipl(xf, Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0]),\n                            xipl(xf, Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1]));\n        }\n\n        public readonly void SetScaled4<T1>(Matrix<Td> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, Td> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun)\n        {\n            var dxa = new Tup2<long>[SX];\n            var xfa = new double[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi;\n                dxa[tix] = dx; xfa[tix] = xf;\n            }\n            var dya = new Tup2<long>[SY];\n            var yfa = new double[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi;\n                dya[tiy] = dy; yfa[tiy] = yf;\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    data[i] = sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    data[i] = sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    data[i] = sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl);\n                } }\n            }\n        }\n\n        public readonly void SetScaled4<T1, T2>(Matrix<Td> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<T2, Td> clampFun)\n        {\n            var dxa = new Tup2<long>[SX];\n            var xfa = new double[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi;\n                dxa[tix] = dx; xfa[tix] = xf;\n            }\n            var dya = new Tup2<long>[SY];\n            var yfa = new double[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi;\n                dya[tiy] = dy; yfa[tiy] = yf;\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    data[i] = clampFun(sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    data[i] = clampFun(sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    data[i] = clampFun(sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl));\n                } }\n            }\n        }\n\n        public readonly TRes Sample4<T1, TRes>(\n                Tup2<long> dx, Tup2<long> dy, double xf, double yf,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return yipl(yf, xipl(xf, Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0]),\n                            xipl(xf, Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1]));\n        }\n\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return SampleRaw16(v.X, v.Y, xipl, yipl, xsmp, ysmp);\n        }\n\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long d2 = dx + dx;\n            long i1 = Info.Origin + xi * dx + yi * dy, i0 = i1 - dy, i2 = i1 + dy, i3 = i2 + dy;\n            var wx = xipl(xf); var wy = yipl(yf);\n            return ysmp(xsmp(Data[i0 - dx], Data[i0], Data[i0 + dx], Data[i0 + d2], ref wx),\n                        xsmp(Data[i1 - dx], Data[i1], Data[i1 + dx], Data[i1 + d2], ref wx),\n                        xsmp(Data[i2 - dx], Data[i2], Data[i2 + dx], Data[i2 + d2], ref wx),\n                        xsmp(Data[i3 - dx], Data[i3], Data[i3 + dx], Data[i3 + d2], ref wx), ref wy);\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return Sample16(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return Sample16(x, y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample16(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            var wx = xipl(xf); var wy = yipl(yf);\n            return ysmp(xsmp(Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0], Data[dx.E2 + dy.E0], Data[dx.E3 + dy.E0], ref wx),\n                        xsmp(Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1], Data[dx.E2 + dy.E1], Data[dx.E3 + dy.E1], ref wx),\n                        xsmp(Data[dx.E0 + dy.E2], Data[dx.E1 + dy.E2], Data[dx.E2 + dy.E2], Data[dx.E3 + dy.E2], ref wx),\n                        xsmp(Data[dx.E0 + dy.E3], Data[dx.E1 + dy.E3], Data[dx.E2 + dy.E3], Data[dx.E3 + dy.E3], ref wx), ref wy);\n        }\n\n        public readonly void SetScaled16<T1,T2, T3>(Matrix<Td> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, Td> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            var dxa = new Tup4<long>[SX];\n            var wxa = new Tup4<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi; dx.E3 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup4<long>[SY];\n            var wya = new Tup4<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi; dy.E3 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    data[i] = sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    data[i] = sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    data[i] = sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp);\n                } }\n            }\n        }\n\n        public readonly void SetScaled16<T1,T2, T3, T4>(Matrix<Td> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, T4> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun,\n                Func<T4, Td> clampFun)\n        {\n            var dxa = new Tup4<long>[SX];\n            var wxa = new Tup4<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi; dx.E3 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup4<long>[SY];\n            var wya = new Tup4<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi; dy.E3 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    data[i] = clampFun(sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    data[i] = clampFun(sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    data[i] = clampFun(sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                Tup4<long> dx, Tup4<long> dy, Tup4<T1> wx, Tup4<T2> wy,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return ysmp(xsmp(Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0], Data[dx.E2 + dy.E0], Data[dx.E3 + dy.E0], ref wx),\n                        xsmp(Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1], Data[dx.E2 + dy.E1], Data[dx.E3 + dy.E1], ref wx),\n                        xsmp(Data[dx.E0 + dy.E2], Data[dx.E1 + dy.E2], Data[dx.E2 + dy.E2], Data[dx.E3 + dy.E2], ref wx),\n                        xsmp(Data[dx.E0 + dy.E3], Data[dx.E1 + dy.E3], Data[dx.E2 + dy.E3], Data[dx.E3 + dy.E3], ref wx), ref wy);\n        }\n\n        public readonly TRes SampleRaw36<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return SampleRaw36(v.X, v.Y, xipl, yipl, xsmp, ysmp);\n        }\n\n        public readonly TRes SampleRaw36<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long i2 = Info.Origin + xi * dx + yi * dy;\n            long i1 = i2 - dy, i0 = i1 - dy, i3 = i2 + dy, i4 = i3 + dy, i5 = i4 + dy;\n            long d2 = dx + dx, d3 = d2 + dx;\n            var wx = xipl(xf); var wy = yipl(yf);\n            return ysmp(xsmp(Data[i0 - d2], Data[i0 - dx], Data[i0], Data[i0 + dx], Data[i0 + d2], Data[i0 + d3], ref wx),\n                        xsmp(Data[i1 - d2], Data[i1 - dx], Data[i1], Data[i1 + dx], Data[i1 + d2], Data[i1 + d3], ref wx),\n                        xsmp(Data[i2 - d2], Data[i2 - dx], Data[i2], Data[i2 + dx], Data[i2 + d2], Data[i2 + d3], ref wx),\n                        xsmp(Data[i3 - d2], Data[i3 - dx], Data[i3], Data[i3 + dx], Data[i3 + d2], Data[i3 + d3], ref wx),\n                        xsmp(Data[i4 - d2], Data[i4 - dx], Data[i4], Data[i4 + dx], Data[i4 + d2], Data[i4 + d3], ref wx),\n                        xsmp(Data[i5 - d2], Data[i5 - dx], Data[i5], Data[i5 + dx], Data[i5 + d2], Data[i5 + d3], ref wx), ref wy);\n        }\n\n        public readonly TRes Sample36Clamped<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return Sample36(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample36Clamped<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return Sample36(x, y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample36(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun);\n        }\n\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i; dx.E4 += i; dx.E5 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            var wx = xipl(xf); var wy = yipl(yf);\n            return ysmp(xsmp(Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0], Data[dx.E2 + dy.E0], Data[dx.E3 + dy.E0], Data[dx.E4 + dy.E0], Data[dx.E5 + dy.E0], ref wx),\n                        xsmp(Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1], Data[dx.E2 + dy.E1], Data[dx.E3 + dy.E1], Data[dx.E4 + dy.E1], Data[dx.E5 + dy.E1], ref wx),\n                        xsmp(Data[dx.E0 + dy.E2], Data[dx.E1 + dy.E2], Data[dx.E2 + dy.E2], Data[dx.E3 + dy.E2], Data[dx.E4 + dy.E2], Data[dx.E5 + dy.E2], ref wx),\n                        xsmp(Data[dx.E0 + dy.E3], Data[dx.E1 + dy.E3], Data[dx.E2 + dy.E3], Data[dx.E3 + dy.E3], Data[dx.E4 + dy.E3], Data[dx.E5 + dy.E3], ref wx),\n                        xsmp(Data[dx.E0 + dy.E4], Data[dx.E1 + dy.E4], Data[dx.E2 + dy.E4], Data[dx.E3 + dy.E4], Data[dx.E4 + dy.E4], Data[dx.E5 + dy.E4], ref wx),\n                        xsmp(Data[dx.E0 + dy.E5], Data[dx.E1 + dy.E5], Data[dx.E2 + dy.E5], Data[dx.E3 + dy.E5], Data[dx.E4 + dy.E5], Data[dx.E5 + dy.E5], ref wx), ref wy);\n        }\n\n        public readonly void SetScaled36<T1, T2, T3>(Matrix<Td> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, Td> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun)\n        {\n            var dxa = new Tup6<long>[SX];\n            var wxa = new Tup6<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1;\n                dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi;\n                dx.E3 += dxi; dx.E4 += dxi; dx.E5 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup6<long>[SY];\n            var wya = new Tup6<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1;\n                dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi;\n                dy.E3 += dyi; dy.E4 += dyi; dy.E5 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    data[i] = sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    data[i] = sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    data[i] = sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp);\n                } }\n            }\n        }\n\n        public readonly void SetScaled36<T1, T2, T3, T4>(Matrix<Td> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, T4> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun,\n                Func<T4, Td> clampFun)\n        {\n            var dxa = new Tup6<long>[SX];\n            var wxa = new Tup6<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1;\n                dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi;\n                dx.E3 += dxi; dx.E4 += dxi; dx.E5 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup6<long>[SY];\n            var wya = new Tup6<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1;\n                dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi;\n                dy.E3 += dyi; dy.E4 += dyi; dy.E5 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    data[i] = clampFun(sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    data[i] = clampFun(sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    data[i] = clampFun(sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n        }\n\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                Tup6<long> dx, Tup6<long> dy, Tup6<T1> wx, Tup6<T2> wy,\n                FuncRef1<Td, Td, Td, Td, Td, Td, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return ysmp(xsmp(Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0], Data[dx.E2 + dy.E0], Data[dx.E3 + dy.E0], Data[dx.E4 + dy.E0], Data[dx.E5 + dy.E0], ref wx),\n                        xsmp(Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1], Data[dx.E2 + dy.E1], Data[dx.E3 + dy.E1], Data[dx.E4 + dy.E1], Data[dx.E5 + dy.E1], ref wx),\n                        xsmp(Data[dx.E0 + dy.E2], Data[dx.E1 + dy.E2], Data[dx.E2 + dy.E2], Data[dx.E3 + dy.E2], Data[dx.E4 + dy.E2], Data[dx.E5 + dy.E2], ref wx),\n                        xsmp(Data[dx.E0 + dy.E3], Data[dx.E1 + dy.E3], Data[dx.E2 + dy.E3], Data[dx.E3 + dy.E3], Data[dx.E4 + dy.E3], Data[dx.E5 + dy.E3], ref wx),\n                        xsmp(Data[dx.E0 + dy.E4], Data[dx.E1 + dy.E4], Data[dx.E2 + dy.E4], Data[dx.E3 + dy.E4], Data[dx.E4 + dy.E4], Data[dx.E5 + dy.E4], ref wx),\n                        xsmp(Data[dx.E0 + dy.E5], Data[dx.E1 + dy.E5], Data[dx.E2 + dy.E5], Data[dx.E3 + dy.E5], Data[dx.E4 + dy.E5], Data[dx.E5 + dy.E5], ref wx), ref wy);\n        }\n        #endregion\n\n        #region Drawing\n\n        /// <summary>\n        /// Draws a horizontal line. The parameters x0, x1, and y are rounded\n        /// to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetLineX(double x0, double x1, double y, Td value)\n        {\n            SetLineX((long)(x0 + 0.5), (long)(x1 + 0.5), (long)(y + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical line. The parameters x, y0, and y1 are rounded\n        /// to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetLineY(double x, double y0, double y1, Td value)\n        {\n            SetLineY((long)(x + 0.5), (long)(y0 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a horizontal line.\n        /// </summary>\n        public readonly void SetLineX(long x0, long x1, long y, Td value)\n        {\n            long xmin = Fun.Max(Fun.Min(x0, x1), Info.First.X);\n            long xmax = Fun.Min(Fun.Max(x0, x1), Info.First.X + Info.Size.X - 1);\n            if (y >= Info.First.Y && y < Info.First.Y + Info.Size.Y)\n                for (long x = xmin; x <= xmax; x++) this[x, y] = value;\n        }\n\n        /// <summary>\n        /// Draws a vertical line.\n        /// </summary>\n        public readonly void SetLineY(long x, long y0, long y1, Td value)\n        {\n            long ymin = Fun.Max(Fun.Min(y0, y1), Info.First.Y);\n            long ymax = Fun.Min(Fun.Max(y0, y1), Info.First.Y + Info.Size.Y - 1);\n            if (x >= Info.First.X && x < Info.First.X + Info.Size.X)\n                for (long y = ymin; y <= ymax; y++) this[x, y] = value;\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame. The corner positions are\n        /// rounded to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetRectangle(V2d p0, V2d p1, Td value)\n        {\n            SetRectangle((long)(p0.X + 0.5), (long)(p0.Y + 0.5),\n                         (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n        /// <summary>\n        /// Draws a rectangular frame. The parameters x0, x1, y0, and y1 are\n        /// rounded to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetRectangle(double x0, double y0, double x1, double y1, Td value)\n        {\n            SetRectangle((long)(x0 + 0.5), (long)(y0 + 0.5),\n                         (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(V2i p0, V2i p1, Td value)\n        {\n            SetRectangle((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(V2l v0, V2l v1, Td value)\n        {\n            SetRectangle(v0.X, v0.Y, v1.X, v1.Y, value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(long x0, long y0, long x1, long y1, Td value)\n        {\n            long ymin = Fun.Min(y0, y1), ymax = Fun.Max(y0, y1);\n            SetLineX(x0, x1, ymin, value);\n            SetLineY(x0, ymin + 1L, ymax - 1L, value);\n            SetLineY(x1, ymin + 1L, ymax - 1L, value);\n            SetLineX(x0, x1, ymax, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle and its interior to the supplied value.\n        /// Note that the coordinates are rounded to the nearest integer coordinate.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2d p0, V2d p1, Td value)\n        {\n            SetRectangleFilled((long)(p0.X + 0.5), (long)(p0.Y + 0.5),\n                               (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle and its interior to the supplied value.\n        /// Note that the coordinates are rounded to the nearest integer coordinate.\n        /// </summary>\n        public readonly void SetRectangleFilled(double x0, double y0, double x1, double y1, Td value)\n        {\n            SetRectangleFilled((long)(x0 + 0.5), (long)(y0 + 0.5),\n                               (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// position vectors and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2i p0, V2i p1, Td value)\n        {\n            SetRectangleFilled((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// position vectors and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2l p0, V2l p1, Td value)\n        {\n            SetRectangleFilled(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// coordinates and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(long x0, long y0, long x1, long y1, Td value)\n        {\n            long xmin = Fun.Max(Fun.Min(x0, x1), Info.First.X);\n            long xmax = Fun.Min(Fun.Max(x0, x1), Info.First.X + Info.Size.X - 1);\n            if (xmin > xmax) return;\n            long ymin = Fun.Max(Fun.Min(y0, y1), Info.First.Y);\n            long ymax = Fun.Min(Fun.Max(y0, y1), Info.First.Y + Info.Size.Y - 1);\n            if (ymin > ymax) return;\n\n            SubMatrix(x0, y0, 1 + x1 - x0, 1 + y1 - y0).Set(value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2d p, double radius, Td value)\n        {\n            SetCross((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around [x,y].\n        /// </summary>\n        public readonly void SetCross(double x, double y, double radius, Td value)\n        {\n            SetCross((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2i p, int radius, Td value)\n        {\n            SetCross((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2l p, long radius, Td value)\n        {\n            SetCross(p.X, p.Y, radius, value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around [x, y].\n        /// </summary>\n        public readonly void SetCross(long x, long y, long radius, Td value)\n        {\n            SetLineX(x - radius, x + radius, y, value);\n            SetLineY(x, y - radius, y + radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2d p, double radius, Td value)\n        {\n            SetCrossX((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(double x, double y, double radius, Td value)\n        {\n            SetCrossX((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2i p, int radius, Td value)\n        {\n            SetCrossX((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2l p, long radius, Td value)\n        {\n            SetCrossX(p.X, p.Y, radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(long x, long y, long radius, Td value)\n        {\n            SetLine(x - radius, y - radius, x + radius, y + radius, value);\n            SetLine(x + radius, y - radius, x - radius, y + radius, value);\n        }\n\n        public readonly void SetSquare(\n                V2d p, double radius, Td value)\n        {\n            SetSquare((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquare(\n                double x, double y, double radius, Td value)\n        {\n            SetSquare((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquare(\n                V2i p, int radius, Td value)\n        {\n            SetSquare((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetSquare(\n                V2l p, long radius, Td value)\n        {\n            SetSquare(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetSquare(\n                long x, long y, long radius, Td value)\n        {\n            SetRectangle(x - radius, y - radius, x + radius, y + radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2d p, double radius, Td value)\n        {\n            SetSquareFilled((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquareFilled(\n                double x, double y, double radius, Td value)\n        {\n            SetSquareFilled((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2i p, int radius, Td value)\n        {\n            SetSquareFilled((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2l p, long radius, Td value)\n        {\n            SetSquareFilled(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                long x, long y, long radius, Td value)\n        {\n            SetRectangleFilled(x - radius, y - radius, x + radius, y + radius, value);\n        }\n\n        public readonly void SetLine(\n                V2d p0, V2d p1, Td value)\n        {\n            SetLine((long)(p0.X + 0.5), (long)(p0.Y + 0.5), (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n\n        public readonly void SetLine(\n                double x0, double y0, double x1, double y1, Td value)\n        {\n            SetLine((long)(x0 + 0.5), (long)(y0 + 0.5), (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        public readonly void SetLine(\n                V2i p0, V2i p1, Td value)\n        {\n            SetLine((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        public readonly void SetLine(\n                V2l p0, V2l p1, Td value)\n        {\n            SetLine(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        ///  Bresenham Line Algorithm\n        /// </summary>\n        public readonly void SetLine(\n                long x0, long y0, long x1, long y1, Td value)\n        {\n            //-- Trivial Cases\n            if (x0 == x1) { SetLineY(x0, y0, y1, value); return; }\n            if (y0 == y1) { SetLineX(x0, x1, y1, value); return; }\n\n            //-- Bresenham\n            long dx, dy;\n            long incx, incy;\n\n            if (x1 >= x0)\n            {\n                dx = x1 - x0; incx = 1;\n            }\n            else\n            {\n                dx = x0 - x1; incx = -1;\n            }\n\n            if (y1 >= y0)\n            {\n                dy = y1 - y0;  incy = 1;\n            }\n            else\n            {\n                dy = y0 - y1; incy = -1;\n            }\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n            bool xok = x0 >= xmin && x0 <= xmax;\n            bool yok = y0 >= ymin && y0 <= ymax;\n            long balance;\n\n            if (dx >= dy)\n            {\n                dy <<= 1;\n                balance = dy - dx;\n                dx <<= 1;\n\n                while (x0 != x1)\n                {\n                    if (xok && yok) this[x0, y0] = value;\n                    if (balance >= 0)\n                    {\n                        y0 += incy; yok = y0 >= ymin && y0 <= ymax;\n                        balance -= dx;\n                    }\n                    balance += dy;\n                    x0 += incx; xok = x0 >= xmin && x0 <= xmax;\n                }\n                if (xok && yok) this[x0, y0] = value;\n            }\n            else\n            {\n                dx <<= 1;\n                balance = dx - dy;\n                dy <<= 1;\n\n                while (y0 != y1)\n                {\n                    if (xok && yok) this[x0, y0] = value;\n                    if (balance >= 0)\n                    {\n                        x0 += incx; xok = x0 >= xmin && x0 <= xmax;\n                        balance -= dy;\n                    }\n                    balance += dx;\n                    y0 += incy; yok = y0 >= ymin && y0 <= ymax;\n                }\n                if (xok && yok) this[x0, y0] = value;\n            }\n        }\n\n        /// <summary>\n        /// Set all pixels whose square region is intersected by the line from p0 to p1\n        /// to the supplied value. Does not perform any bounds checks.\n        /// </summary>\n        public readonly void SetLineAllTouchedRaw(V2d p0, V2d p1, Td value)\n        {\n            SetLineAllTouchedRaw(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        /// Set all pixels whose square region is intersected by the line from (x0,y0) to (x1,y1)\n        /// to the supplied value. Does not perform any bounds checks.\n        /// </summary>\n        public readonly void SetLineAllTouchedRaw(double x0, double y0, double x1, double y1, Td value)\n        {\n            var ix = (long)Fun.Floor(x0);\n            var iy = (long)Fun.Floor(y0);\n            var dx = x1 - x0;\n            var dy = y1 - y0;\n\n            var len = Fun.Sqrt(dx * dx + dy * dy);\n\n            double tx, ty, dtx, dty;\n            long dix, diy;\n\n            if (dx > 0.0)       { dtx = len / dx; tx = dtx * (1.0 - (x0 - ix)); dix = Info.DX; }\n            else if (dx < 0.0)  { dtx = -len / dx; tx = dtx * (x0 - ix); dix = -Info.DX; }\n            else                { dtx = 0.0; tx = len; dix = 0; }\n\n            if (dy > 0.0)       { dty = len / dy; ty = dty * (1.0 - (y0 - iy)); diy = Info.DY; }\n            else if (dy < 0.0)  { dty = -len / dy; ty = dty * (y0 - iy); diy = -Info.DY; }\n            else                { dty = 0.0; ty = len; diy = 0; }\n\n            var mdata = Data;\n            double t = 0.0;\n            long index = Info.Origin + ix * Info.DX + iy * Info.DY;\n            do\n            {\n                mdata[index] = value;\n                if (tx < ty)    { t = tx; tx += dtx; index += dix; }\n                else            { t = ty; ty += dty; index += diy; }\n            }\n            while (t < len);\n        }\n\n        public readonly void SetCircle(\n                V2d p, double radius, Td value)\n        {\n            SetCircle((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircle(\n                double x, double y, double radius, Td value)\n        {\n            SetCircle((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircle(\n                V2i p, int radius, Td value)\n        {\n            SetCircle((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetCircle(\n                V2l p, long radius, Td value)\n        {\n            SetCircle(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetCircle(\n                long x, long y, long radius, Td value)\n        {\n            long f = 1 - radius;\n            long ddF_x = 0;\n            long ddF_y = -2 * radius;\n            long rx = 0;\n            long ry = radius;\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n\n            if (x >= xmin && x <= xmax)\n            {\n                var ym = y - radius; if (ym >= ymin && ym <= ymax) this[x, ym] = value;\n                var yp = y + radius; if (yp >= ymin && yp <= ymax) this[x, yp] = value;\n            }\n            if (y >= xmin && y <= ymax)\n            {\n                var xm = x - radius; if (xm >= xmin && xm <= xmax) this[xm, y] = value;\n                var xp = x + radius; if (xp >= xmin && xp <= xmax) this[xp, y] = value;\n            }\n            bool xmxOk = true, xpxOk = true, xmyOk = true, xpyOk = true;\n            while (rx < ry)\n            {\n                if (f >= 0)\n                {\n                    ry--; ddF_y += 2; f += ddF_y;\n                }\n                rx++;\n                ddF_x += 2;\n                f += ddF_x + 1;\n\n                long xmx = x - rx; xmxOk = xmx >= xmin && xmx <= xmax;\n                long xpx = x + rx; xpxOk = xpx >= xmin && xpx <= xmax;\n                long xmy = x - ry; xmyOk = xmy >= xmin && xmy <= xmax;\n                long xpy = x + ry; xpyOk = xpy >= xmin && xpy <= xmax;\n                long ymx = y - rx, ypx = y + rx;\n                long ymy = y - ry, ypy = y + ry;\n\n                if (ymx >= ymin && ymx <= ymax)\n                {\n                    if (xmyOk) this[xmy, ymx] = value;\n                    if (xpyOk) this[xpy, ymx] = value;\n                }\n                if (ypx >= ymin && ypx <= ymax)\n                {\n                    if (xmyOk) this[xmy, ypx] = value;\n                    if (xpyOk) this[xpy, ypx] = value;\n                }\n                if (ymy >= ymin && ymy <= ymax)\n                {\n                    if (xmxOk) this[xmx, ymy] = value;\n                    if (xpxOk) this[xpx, ymy] = value;\n                }\n                if (ypy >= ymin && ypy <= ymax)\n                {\n                    if (xmxOk) this[xmx, ypy] = value;\n                    if (xpxOk) this[xpx, ypy] = value;\n                }\n            }\n        }\n\n        public readonly void SetCircleFilled(\n                V2d p, double radius, Td value)\n        {\n            SetCircleFilled((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircleFilled(\n                double x, double y, double radius, Td value)\n        {\n            SetCircleFilled((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircleFilled(\n                V2i p, int radius, Td value)\n        {\n            SetCircleFilled((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetCircleFilled(\n                V2l p, long radius, Td value)\n        {\n            SetCircleFilled(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetCircleFilled(\n                long x0, long y0, long radius, Td value)\n        {\n            long x = radius;\n            long y = 0;\n            long xChange = 1 - (radius << 1);\n            long yChange = 0;\n            long radiusError = 0;\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n\n            long mdx = DX; var mdata = Data;\n\n            while (x >= y)\n            {\n                if (y0 + y >= ymin && y0 + y <= ymax)\n                {\n                    var xb = Fun.Max(x0 - x, xmin); var xe = Fun.Min(x0 + x, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 + y), e = Info.Index(xe + 1, y0 + y); i != e; i += mdx)\n                        mdata[i] = value;\n                }\n                if (y0 - y >= ymin && y0 - y <= ymax)\n                {\n                    var xb = Fun.Max(x0 - x, xmin); var xe = Fun.Min(x0 + x, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 - y), e = Info.Index(xe + 1, y0 - y); i != e; i += mdx)\n                            mdata[i] = value;\n                }\n                if (y0 + x >= ymin && y0 + x <= ymax)\n                {\n                    var xb = Fun.Max(x0 - y, xmin); var xe = Fun.Min(x0 + y, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 + x), e = Info.Index(xe + 1, y0 + x); i != e; i += mdx)\n                            mdata[i] = value;\n                }\n                if (y0 - x >= ymin && y0 - x <= ymax)\n                {\n                    var xb = Fun.Max(x0 - y, xmin); var xe = Fun.Min(x0 + y, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 - x), e = Info.Index(xe + 1, y0 - x); i != e; i += mdx)\n                            mdata[i] = value;\n                }\n                y++;\n                radiusError += yChange;\n                yChange += 2;\n                if (((radiusError << 1) + xChange) > 0)\n                {\n                    x--;\n                    radiusError += xChange;\n                    xChange += 2;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Set all matrix pixels inside the specified polygon to the supplied\n        /// value. This is a raw routine that does no clipping and assumes that\n        /// all pixels that need to be set are within the matrix. The polygon\n        /// is assumed to consist of two y-monotone point sequences between\n        /// the points with minimum and maximum y-coordinate. Note that convex\n        /// and non-concave polygons automatically fullfill this condition.\n        /// Rasterization is performed according to DirextX11 rules.\n        /// </summary>\n        public readonly void SetMonotonePolygonFilledRaw(\n                V2d[] polygon,\n                Td value,\n                Winding winding = Winding.CCW,\n                double eps = 1e-8)\n        {\n            var pc = polygon.Length;\n            int diLeft = winding == Winding.CCW ? 1 : pc - 1;\n            int diRight = winding == Winding.CCW ? pc - 1 : 1;\n            int eLeft = 0, end = 0;\n            double yeLeft = polygon[0].Y;\n            for (int pi = 1; pi < pc; pi++) // find min in (y)eLeft and max in end\n            {\n                var y = polygon[pi].Y;\n                if (y < yeLeft) { eLeft = pi; yeLeft = y; }\n                if (y > polygon[end].Y) end = pi;\n            }\n            int eRight = eLeft, sLeft = 0, sRight = 0;\n            double yeRight = yeLeft;\n            double xfLeft = 0, fdeltaLeft = 0.0, xfRight = 0, fdeltaRight = 0.0;\n            long iLeft = 0, ideltaLeft = 0, iRight = 0, ideltaRight = 0;\n            long mdx = DX, mdy = DY; var mdata = Data;\n            long yi = (long)Fun.Ceiling(yeLeft - 0.5), yieLeft = yi, yieRight = yi;\n            var lineOrigin = Origin + yi * mdy;\n            bool exit = false;\n            while (true)\n            {\n                if (yi == yieLeft) // next left edge\n                {\n                    double ysLeft = 0.0;\n                    do\n                    {\n                        sLeft = eLeft; if (sLeft == end) { exit = true; break; }\n                        eLeft = (sLeft + diLeft) % pc;\n                        ysLeft = yeLeft;\n                        yeLeft = polygon[eLeft].Y;\n                        yieLeft = (long)Fun.Ceiling(yeLeft - 0.5);\n                    }\n                    while (yi == yieLeft); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaLeft = yeLeft - ysLeft;\n                    if (deltaLeft < 0.0) { exit = true; break; }\n                    if (deltaLeft < eps) deltaLeft = eps;\n                    deltaLeft = (polygon[eLeft].X - polygon[sLeft].X) / deltaLeft;\n                    ideltaLeft = (long)Fun.Ceiling(deltaLeft);\n                    fdeltaLeft = deltaLeft - (double)ideltaLeft;\n                    double xLeft = polygon[sLeft].X + (0.5 + (double)yi - ysLeft) * deltaLeft;\n                    iLeft = (long)Fun.Ceiling(xLeft - 0.5);\n                    xfLeft = xLeft - (double)iLeft + 0.5 - eps; // offset for stable 0.0 comparison\n                    iLeft = lineOrigin + iLeft * mdx;\n                    ideltaLeft = mdy + ideltaLeft * mdx;\n                }\n                if (exit) break;\n                if (yi == yieRight) // next right edge\n                {\n                    double ysRight = 0.0;\n                    do\n                    {\n                        sRight = eRight; if (sRight == end) { exit = true; break; }\n                        eRight = (sRight + diRight) % pc;\n                        ysRight = yeRight;\n                        yeRight = polygon[eRight].Y;\n                        yieRight = (long)Fun.Ceiling(yeRight - 0.5);\n                    }\n                    while (yi == yieRight); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaRight = yeRight - ysRight;\n                    if (deltaRight < 0.0) { exit = true; break; }\n                    if (deltaRight < eps) deltaRight = eps;\n                    deltaRight = (polygon[eRight].X - polygon[sRight].X) / deltaRight;\n                    ideltaRight = (long)Fun.Ceiling(deltaRight);\n                    fdeltaRight = deltaRight - (double)ideltaRight;\n                    double xRight = polygon[sRight].X + (0.5 + (double)yi - ysRight) * deltaRight;\n                    iRight = (long)Fun.Ceiling(xRight - 0.5);\n                    xfRight = xRight - (double)iRight + 0.5 - eps; // offset for stable 0.0 comparison\n                    iRight = lineOrigin + iRight * mdx;\n                    ideltaRight = mdy + ideltaRight * mdx;\n                }\n                if (exit) break;\n                long yimin = Fun.Min(yieLeft, yieRight);\n                while (yi < yimin)\n                {\n                    for (long i = iLeft; i < iRight; i += mdx)\n                    {\n                        mdata[i] = value;\n                    }\n                    iLeft += ideltaLeft; xfLeft += fdeltaLeft;\n                    if (xfLeft < 0.0) { xfLeft += 1.0; iLeft -= mdx; }\n                    iRight += ideltaRight; xfRight += fdeltaRight;\n                    if (xfRight < 0.0) { xfRight += 1.0; iRight -= mdx; }\n                    ++yi; lineOrigin += mdy;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Set all matrix pixels inside the specified polygon to the supplied\n        /// value. This is a raw routine that does no clipping and assumes that\n        /// all pixels that need to be set are within the matrix. The polygon\n        /// is assumed to consist of two y-monotone point sequences between\n        /// the points with minimum and maximum y-coordinate. Note that convex\n        /// and non-concave polygons automatically fullfill this condition.\n        /// Rasterization is performed according to DirextX11 rules.\n        /// </summary>\n        public readonly void SetMonotonePolygonFilledRaw(\n                int[] polygon, V2d[] vertexArray,\n                Td value,\n                Winding winding = Winding.CCW,\n                double eps = 1e-8)\n        {\n            var pc = polygon.Length;\n            int diLeft = winding == Winding.CCW ? 1 : pc - 1;\n            int diRight = winding == Winding.CCW ? pc - 1 : 1;\n            int eLeft = 0, end = 0;\n            double yeLeft = vertexArray[polygon[0]].Y;\n            for (int pi = 1; pi < pc; pi++) // find min in (y)eLeft and max in end\n            {\n                var y = vertexArray[polygon[pi]].Y;\n                if (y < yeLeft) { eLeft = pi; yeLeft = y; }\n                if (y > vertexArray[polygon[end]].Y) end = pi;\n            }\n            int eRight = eLeft, sLeft = 0, sRight = 0;\n            double yeRight = yeLeft;\n            double xfLeft = 0, fdeltaLeft = 0.0, xfRight = 0, fdeltaRight = 0.0;\n            long iLeft = 0, ideltaLeft = 0, iRight = 0, ideltaRight = 0;\n            long mdx = DX, mdy = DY; var mdata = Data;\n            long yi = (long)Fun.Ceiling(yeLeft - 0.5), yieLeft = yi, yieRight = yi;\n            var lineOrigin = Origin + yi * mdy;\n            bool exit = false;\n            while (true)\n            {\n                if (yi == yieLeft) // next left edge\n                {\n                    double ysLeft = 0.0;\n                    do\n                    {\n                        sLeft = eLeft; if (sLeft == end) { exit = true; break; }\n                        eLeft = (sLeft + diLeft) % pc;\n                        ysLeft = yeLeft;\n                        yeLeft = vertexArray[polygon[eLeft]].Y;\n                        yieLeft = (long)Fun.Ceiling(yeLeft - 0.5);\n                    }\n                    while (yi == yieLeft); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaLeft = yeLeft - ysLeft;\n                    if (deltaLeft < 0.0) { exit = true; break; }\n                    if (deltaLeft < eps) deltaLeft = eps;\n                    deltaLeft = (vertexArray[polygon[eLeft]].X - vertexArray[polygon[sLeft]].X) / deltaLeft;\n                    ideltaLeft = (long)Fun.Ceiling(deltaLeft);\n                    fdeltaLeft = deltaLeft - (double)ideltaLeft;\n                    double xLeft = vertexArray[polygon[sLeft]].X + (0.5 + (double)yi - ysLeft) * deltaLeft;\n                    iLeft = (long)Fun.Ceiling(xLeft - 0.5);\n                    xfLeft = xLeft - (double)iLeft + 0.5 - eps; // offset for stable 0.0 comparison\n                    iLeft = lineOrigin + iLeft * mdx;\n                    ideltaLeft = mdy + ideltaLeft * mdx;\n                }\n                if (exit) break;\n                if (yi == yieRight) // next right edge\n                {\n                    double ysRight = 0.0;\n                    do\n                    {\n                        sRight = eRight; if (sRight == end) { exit = true; break; }\n                        eRight = (sRight + diRight) % pc;\n                        ysRight = yeRight;\n                        yeRight = vertexArray[polygon[eRight]].Y;\n                        yieRight = (long)Fun.Ceiling(yeRight - 0.5);\n                    }\n                    while (yi == yieRight); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaRight = yeRight - ysRight;\n                    if (deltaRight < 0.0) { exit = true; break; }\n                    if (deltaRight < eps) deltaRight = eps;\n                    deltaRight = (vertexArray[polygon[eRight]].X - vertexArray[polygon[sRight]].X) / deltaRight;\n                    ideltaRight = (long)Fun.Ceiling(deltaRight);\n                    fdeltaRight = deltaRight - (double)ideltaRight;\n                    double xRight = vertexArray[polygon[sRight]].X + (0.5 + (double)yi - ysRight) * deltaRight;\n                    iRight = (long)Fun.Ceiling(xRight - 0.5);\n                    xfRight = xRight - (double)iRight + 0.5 - eps; // offset for stable 0.0 comparison\n                    iRight = lineOrigin + iRight * mdx;\n                    ideltaRight = mdy + ideltaRight * mdx;\n                }\n                if (exit) break;\n                long yimin = Fun.Min(yieLeft, yieRight);\n                while (yi < yimin)\n                {\n                    for (long i = iLeft; i < iRight; i += mdx)\n                    {\n                        mdata[i] = value;\n                    }\n                    iLeft += ideltaLeft; xfLeft += fdeltaLeft;\n                    if (xfLeft < 0.0) { xfLeft += 1.0; iLeft -= mdx; }\n                    iRight += ideltaRight; xfRight += fdeltaRight;\n                    if (xfRight < 0.0) { xfRight += 1.0; iRight -= mdx; }\n                    ++yi; lineOrigin += mdy;\n                }\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        /// <summary>\n        /// Dimension of the generic Matrix.\n        /// </summary>\n        public readonly V2l Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[x, y];\n        }\n\n        public readonly void SetValue(object value, long x, long y)\n        {\n            this[x, y] = (Td)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[v];\n        }\n\n        public readonly void SetValue(object value, V2l v)\n        {\n            this[v] = (Td)value;\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    #region Matrix<Td, Tv>\n\n    /// <summary>\n    /// Generic matrix of elements with arbitrary stride.\n    /// All sizes are given as 2-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The matrix does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on matrixs are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// 2 stride direction(s) are called DX, DY, aso.\n    /// The matrix has different view and data element types, i.e. although\n    /// all data is stored using the data element type, in its interfaces it\n    /// acts as a matrix of view element types.\n    /// </summary>\n    /// <typeparam name=\"Td\">data element type</typeparam>\n    /// <typeparam name=\"Tv\">view element type</typeparam>\n    [Serializable]\n    public partial struct Matrix<Td, Tv> : IValidity, IMatrix<Tv>, IArrayMatrix\n    {\n        public Td[] Data;\n        public Func<Td[], long, Tv> Getter;\n        public Action<Td[], long, Tv> Setter;\n        public MatrixInfo Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public Matrix(Td[] data, MatrixInfo info)\n        {\n            Data = data;\n            Info = info;\n            Getter = null;\n            Setter = null;\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size.\n        /// </summary>\n        public Matrix(V2l size)\n            : this(new Td[size.X * size.Y], new MatrixInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct matrix of specified size.\n        /// </summary>\n        public Matrix(V2i size)\n            : this((V2l)size)\n        { }\n\n        /// <summary>\n        /// Construct matrix with specified info.\n        /// </summary>\n        public Matrix(MatrixInfo info)\n            : this(new Td[info.Count], new MatrixInfo(info))\n        { }\n\n        /// <summary>\n        /// Construct matrix of specified size.\n        /// </summary>\n        public Matrix(long sx, long sy)\n            : this(new V2l(sx, sy))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Matrix(Td[] data, long sx, long sy)\n            : this(data, new MatrixInfo(sx, sy))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and sets all elements to the supplied value.\n        /// </summary>\n        public Matrix(long sx, long sy, Tv value)\n            : this(new V2l(sx, sy), value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Matrix(Td[] data, V2l size)\n            : this(data, new MatrixInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Matrix(Td[] data, V2i size)\n            : this(data, new MatrixInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Matrix(V2l size, Tv value)\n            : this(new Td[size.X * size.Y], new MatrixInfo(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Matrix(V2i size, Tv value)\n            : this((V2l)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Matrix(Td[] data, long origin, V2l size, V2l delta)\n            : this(data, new MatrixInfo(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Matrix(Td[] data, long origin, V2l size, V2l delta, V2l first)\n            : this(data, new MatrixInfo(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public Matrix(long origin, V2l size, V2l delta)\n            : this(new Td[size.X * size.Y],\n                   new MatrixInfo(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the matrix (2).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public V2l Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public V2l Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public V2l First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        public TensorAccessors<Td, Tv> Accessors\n        {\n            readonly get\n            {\n                return new TensorAccessors<Td, Tv>()\n                                { Getter = Getter, Setter = Setter };\n            }\n            set { Getter = value.Getter; Setter = value.Setter; }\n        }\n\n        /// <summary>\n        /// Returns true if the matrix has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the matrix does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly V2l End { get { return Info.E; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OO { get { return Info.OO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l IO { get { return Info.IO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l OI { get { return Info.OI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l II { get { return Info.II; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V2l F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V2l E { get { return Info.E; } }\n\n        /// <summary>\n        /// Size in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Info.SX; } set { Info.SX = value; } }\n\n        /// <summary>\n        /// Size in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Info.SY; } set { Info.SY = value; } }\n\n        /// <summary>\n        /// Delta in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Info.DX; } set { Info.DX = value; } }\n\n        /// <summary>\n        /// Delta in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Info.DY; } set { Info.DY = value; } }\n\n        /// <summary>\n        /// First in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return Info.FX; } set { Info.FX = value; } }\n\n        /// <summary>\n        /// First in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY { readonly get { return Info.FY; } set { Info.FY = value; } }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return Info.EX; } }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY { get { return Info.EY; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Info.JX; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Info.JY; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Info.DSX; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Info.DSY; } }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<Tv> Elements\n        {\n            get\n            {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    yield return Getter(Data, i);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    yield return Getter(Data, i);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    yield return Getter(Data, i);\n                } }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(Td[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (Td[])value; }\n        }\n\n        /// <summary>\n        /// Returns a matrix that represents a view on the same data with flipped coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> Transposed\n        {\n            get\n            {\n                return new Matrix<Td, Tv>(Data, Info.Transposed)\n                                        { Getter = Getter, Setter = Setter };\n            }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Tv this[V2l v]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + v.X * Info.Delta.X + v.Y * Info.Delta.Y);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + v.X * Info.Delta.X + v.Y * Info.Delta.Y, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Tv this[V2i v]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at the specified index in the underlying data array.\n        /// </summary>\n        public readonly Tv this[long index]\n        {\n            get\n            {\n                return Getter(Data, index);\n            }\n            set\n            {\n                Setter(Data, index, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Tv this[long x, long y]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + x * Info.Delta.X + y * Info.Delta.Y);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + x * Info.Delta.X + y * Info.Delta.Y, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Tv this[int x, int y]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + (long)x * Info.Delta.X + (long)y * Info.Delta.Y);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + (long)x * Info.Delta.X + (long)y * Info.Delta.Y, value);\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long> x_y_i_action)\n        {\n            Info.ForeachIndex(x_y_i_action);\n        }\n\n        public readonly void ForeachCoord(Action<V2l> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(MatrixInfo t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            Info.ForeachX(x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            Info.ForeachY(y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            Info.ForeachXIndex(x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            Info.ForeachYIndex(y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrixWindow(V2l begin, V2l size)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrixWindow(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(V2l begin, V2l size)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrix(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrixWindow(V2i begin, V2i size)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrixWindow(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(V2i begin, V2i size)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrix(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrixWindow(V2l begin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrixWindow(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(V2l begin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrix(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrixWindow(V2i begin, V2i size, V2i delta)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrixWindow(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(V2i begin, V2i size, V2i delta)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrix(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrixWindow(V2l begin, V2l size, V2l delta, V2l first)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrixWindow(begin, size, delta, first))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrixWindow(V2i begin, V2i size, V2i delta, V2i first)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrixWindow(begin, size, delta, first))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrixWindow(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new Matrix<Td, Tv>(Data,\n                            Info.SubMatrixWindow(beginX, beginY,\n                                           sizeX, sizeY))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new Matrix<Td, Tv>(Data,\n                            Info.SubMatrix(beginX, beginY,\n                                               sizeX, sizeY))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrixWindow(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new Matrix<Td, Tv>(Data,\n                            Info.SubMatrixWindow(beginX, beginY,\n                                           sizeX, sizeY,\n                                           deltaX, deltaY))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new Matrix<Td, Tv>(Data,\n                            Info.SubMatrix(beginX, beginY,\n                                               sizeX, sizeY,\n                                               deltaX, deltaY))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// If the lines of the matrix are stored consecutively without gaps,\n        /// the whole matrix can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> AsVector()\n        {\n            return new Vector<Td, Tv>(Data, Info.AsVector())\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(V2l origin, long size, long delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(origin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(V2i origin, long size, long delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(origin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> Col(long x)\n        {\n            return new Vector<Td, Tv>(Data, Info.Col(x))\n            { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, Tv> ColWindow(long x)\n        {\n            return new Vector<Td, Tv>(Data, Info.ColWindow(x))\n            { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> Row(long y)\n        {\n            return new Vector<Td, Tv>(Data, Info.Row(y))\n            { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, Tv> RowWindow(long y)\n        {\n            return new Vector<Td, Tv>(Data, Info.RowWindow(y))\n            { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubYVector(long x)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubYVector(x))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubYVectorAsReadOnlyMatrix(long x, long sizex)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubYVectorAsReadOnlyMatrix(x, sizex))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubYVectorWindow(long x)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubYVectorWindow(x))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubYVectorAsReadOnlyMatrixWindow(long x, long sizex)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubYVectorAsReadOnlyMatrixWindow(x, sizex))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubXVector(long y)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubXVector(y))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubXVectorAsReadOnlyMatrix(long y, long sizey)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubXVectorAsReadOnlyMatrix(y, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubXVectorWindow(long y)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubXVectorWindow(y))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubXVectorAsReadOnlyMatrixWindow(long y, long sizey)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubXVectorAsReadOnlyMatrixWindow(y, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubItemAsReadOnlyMatrix(long x, long y, long sizex, long sizey)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubItemAsReadOnlyMatrix(x, y, sizex, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubItemAsReadOnlyMatrixWindow(long x, long y, long sizex, long sizey)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubItemAsReadOnlyMatrixWindow(x, y, sizex, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2l begin, V2l size)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V2l begin, V2l size)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2i begin, V2i size)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V2i begin, V2i size)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(begin, size));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2l begin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V2l begin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2i begin, V2i size, V2i delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V2i begin, V2i size, V2i delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2l begin, V2l size, V2l delta, V2l first)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(V2i begin, V2i size, V2i delta, V2i first)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrixWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new Matrix<Td, T1>(Data,\n                            Info.SubMatrixWindow(beginX, beginY,\n                                           sizeX, sizeY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(\n                long beginX, long beginY,\n                long sizeX, long sizeY)\n        {\n            return new Matrix<Td, T1>(Data,\n                            Info.SubMatrix(beginX, beginY,\n                                               sizeX, sizeY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrixWindow<T1>(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new Matrix<Td, T1>(Data,\n                            Info.SubMatrixWindow(beginX, beginY,\n                                           sizeX, sizeY,\n                                           deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(\n                long beginX, long beginY,\n                long sizeX, long sizeY,\n                long deltaX, long deltaY)\n        {\n            return new Matrix<Td, T1>(Data,\n                            Info.SubMatrix(beginX, beginY,\n                                               sizeX, sizeY,\n                                               deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// If the lines of the matrix are stored consecutively without gaps,\n        /// the whole matrix can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, T1> AsVector<T1>()\n        {\n            return new Vector<Td, T1>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V2l origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V2i origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> Col<T1>(long x)\n        {\n            return new Vector<Td, T1>(Data, Info.Col(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, T1> ColWindow<T1>(long x)\n        {\n            return new Vector<Td, T1>(Data, Info.ColWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> Row<T1>(long y)\n        {\n            return new Vector<Td, T1>(Data, Info.Row(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, T1> RowWindow<T1>(long y)\n        {\n            return new Vector<Td, T1>(Data, Info.RowWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubYVector<T1>(long x)\n        {\n            return new Vector<Td, T1>(Data, Info.SubYVector(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubYVectorAsReadOnlyMatrix<T1>(long x, long sizex)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubYVectorAsReadOnlyMatrix(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, T1> SubYVectorWindow<T1>(long x)\n        {\n            return new Vector<Td, T1>(Data, Info.SubYVectorWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubYVectorAsReadOnlyMatrixWindow<T1>(long x, long sizex)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubYVectorAsReadOnlyMatrixWindow(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Vector<Td, T1> SubXVector<T1>(long y)\n        {\n            return new Vector<Td, T1>(Data, Info.SubXVector(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a vector with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXVectorAsReadOnlyMatrix<T1>(long y, long sizey)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXVectorAsReadOnlyMatrix(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Vector<Td, T1> SubXVectorWindow<T1>(long y)\n        {\n            return new Vector<Td, T1>(Data, Info.SubXVectorWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the matrix as a special matrix\n        /// that replicates the vector the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXVectorAsReadOnlyMatrixWindow<T1>(long y, long sizey)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXVectorAsReadOnlyMatrixWindow(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubItemAsReadOnlyMatrix<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubItemAsReadOnlyMatrix(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full  item slice of the matrix as a special matrix\n        /// that replicates the item the supplied number of times. The special\n        /// matrix can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubItemAsReadOnlyMatrixWindow<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubItemAsReadOnlyMatrixWindow(x, y, sizex, sizey));\n        }\n\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> Copy()\n        {\n            return new Matrix<Td, Tv>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original Matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> CopyWindow()\n        {\n            return new Matrix<Td, Tv>(Info.S)\n                    { F = F, Getter = Getter, Setter = Setter }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<T1> Map<T1>(Func<Tv, T1> fun)\n        {\n            return new Matrix<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original Matrix.\n        /// </summary>\n        public readonly Matrix<T1> MapWindow<T1>(Func<Tv, T1> fun)\n        {\n            return new Matrix<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        public readonly Matrix<Tv> CopyView()\n        {\n            return new Matrix<Tv>(Info.S).Set(this);\n        }\n\n        public readonly Matrix<Tv> CopyViewWindow()\n        {\n            return new Matrix<Tv>(Info.S) { F = F }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> Map(Func<Tv, Tv> fun)\n        {\n            return new Matrix<Td, Tv>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the complete layout of the original Matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> MapWindow(Func<Tv, Tv> fun)\n        {\n            return new Matrix<Td, Tv>(new Td[Data.LongLength], Info)\n                        { F = F, Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the matrix.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> Apply(Func<Tv, Tv> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.SX; i != xe; i++)\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n            }\n            else\n            {\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj)\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original matrix and the supplied matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> Apply<T1>(\n                Matrix<T1> t1, Func<Tv, T1, Tv> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original matrix and the supplied matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> Apply<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<Tv, T1, Tv> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the matrix.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> ApplyByCoord(Func<Tv, V2l, Tv> element_crd_elementFun)\n        {\n            long i = FirstIndex; V2l vi;\n            if (Info.JX == 1)\n            {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.SX; i != xe; i++, vi.X++)\n                    Setter(Data, i, element_crd_elementFun(Getter(Data, i), vi));\n                }\n            }\n            else\n            {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj, vi.X++)\n                {\n                    Setter(Data, i, element_crd_elementFun(Getter(Data, i), vi));\n                }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> ApplyByCoord(Func<Tv, long, long, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    Setter(Data, i, fun(Getter(Data, i), x, y));\n            }\n            else\n            {\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.DSX, xj = Info.JX, x = Info.FX; i != xe; i += xj, x++)\n                    Setter(Data, i, fun(Getter(Data, i), x, y));\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> Set(Tv v)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Setter(Data, i, v);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    Setter(Data, i, v);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Setter(Data, i, v);\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByCoord(Func<long, long, Tv> x_y_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(Data, i, x_y_elementFun(x, y));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Setter(Data, i, x_y_elementFun(x, y));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, x_y_elementFun(x, y));\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByCoord(Func<V2l, Tv> crd_elementFun)\n        {\n            long i = FirstIndex; V2l v;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i++, v.Y++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByCoord<Ty>(\n                Func<long, Ty> yFun,\n                Func<long, long, Ty, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(y);\n                for (long xe = i + xs, x = Info.FX; i != xe; i++, x++) {\n                    Setter(Data, i, fun(y, x, yVal));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(y);\n                for (long xe = i + xs, x = Info.FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, fun(y, x, yVal));\n                } }\n            }\n\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex(Func<long, Tv> index_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Setter(Data, i, index_elementFun(i));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    Setter(Data, i, index_elementFun(i));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Setter(Data, i, index_elementFun(i));\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly Matrix<Td, Tv> Set(IMatrix<Tv> it1)\n        {\n            if (it1 is Matrix<Tv>) return Set((Matrix<Tv>)it1);\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(Data, i, it1[x, y]);\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Setter(Data, i, it1[x, y]);\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, it1[x, y]);\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> Set(Matrix<Tv> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// the elements of the supplied matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap<T1>(\n                Matrix<T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1>(\n                Matrix<T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> Set<T1>(Matrix<T1, Tv> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// the elements of the supplied matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap2<T1, T2>(\n                    Matrix<T1> t1, Matrix<T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1, T2>(\n                Matrix<T1> t1, Matrix<T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap2<T1, T2d, T2>(\n                    Matrix<T1> t1, Matrix<T2d, T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1, T2d, T2>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap2<T1d, T1, T2>(\n                    Matrix<T1d, T1> t1, Matrix<T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1d, T1, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a matrix to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap2<T1d, T1, T2d, T2>(\n                    Matrix<T1d, T1> t1, Matrix<T2d, T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1d, T1, T2d, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap3<T1, T2, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1, T2, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap3<T1, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap3<T1, T2d, T2, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1, T2d, T2, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap3<T1, T2d, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1, T2d, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap3<T1d, T1, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1d, T1, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap3<T1d, T1, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1d, T1, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap3<T1d, T1, T2d, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1d, T1, T2d, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetMap3<T1d, T1, T2d, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the\n        /// matrix.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1 && t2.Info.DY == 1 && t3.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY, xj2 = t2.Info.JXY, xj3 = t3.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ye = i + ys; i != ye; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SetConvolution<Ti, Tf, Tm, Ts>(\n                Matrix<Ti> image, Matrix<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Tv> castFun)\n        {\n            Info.CheckMatchingSize(new MatrixInfo(V2l.One + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.SubMatrix(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetOuterProduct<Tx, Ty>(\n                    Vector<Tx> tx, Vector<Ty> ty,\n                    Func<Tx, Ty, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2]));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2]));\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetOuterProduct<Tx, Tyd, Ty>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty,\n                    Func<Tx, Ty, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2)));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2)));\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetOuterProduct<Txd, Tx, Ty>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty,\n                    Func<Tx, Ty, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2]));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2]));\n                } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Matrix<Td, Tv> SetOuterProduct<Txd, Tx, Tyd, Ty>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty,\n                    Func<Tx, Ty, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2)));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2)));\n                } }\n            }\n            return this;\n        }\n\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Tv, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y));\n                } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, V2l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V2l v;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i++, v.Y++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Matrix<T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Matrix<T1d, T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Tv, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ye = i + ys; i != ye; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, V2l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V2l v;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i++, v.Y++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Matrix<T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Matrix<T1d, T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else if (Info.DY == 1 && t1.Info.DY == 1)\n                {\n                    long xs = Info.DSX, xj = Info.JXY, xj1 = t1.Info.JXY;\n                    long ys = Info.SY;\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ye = i + ys; i != ye; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n                else\n                {\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } }\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creator Functions\n\n        /// <summary>\n        /// Create a new matrix as copy of the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Create(\n                Matrix<Tv> t1)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new matrix as copy of the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Create<T1d>(\n                Matrix<T1d, Tv> t1)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map<T1>(\n                Matrix<T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1>(\n                Matrix<T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1d, T1>(\n                Matrix<T1d, T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map2<T1, T2>(\n                Matrix<T1> t1, Matrix<T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1, T2>(\n                Matrix<T1> t1, Matrix<T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map2<T1, T2d, T2>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1, T2d, T2>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map2<T1d, T1, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1d, T1, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map2<T1d, T1, T2d, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1d, T1, T2d, T2>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map3<T1, T2, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1, T2, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map3<T1, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map3<T1, T2d, T2, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1, T2d, T2, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map3<T1, T2d, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1, T2d, T2, T3d, T3>(\n                Matrix<T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map3<T1d, T1, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1d, T1, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map3<T1d, T1, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1d, T1, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map3<T1d, T1, T2d, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1d, T1, T2d, T2, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function on each element of\n        /// the supplied matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Map3<T1d, T1, T2d, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to each index of the\n        /// elements of the supplied matrix. The function may access the\n        /// elements of the supplied matrix to compute the elements of the new\n        /// matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Matrix<T1d, T1> t1, Matrix<T2d, T2> t2, Matrix<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Matrix<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix by applying a function to the coordinates of\n        /// the elements the newly created matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> Create(V2l size, Func<V2l, Tv> fun)\n        {\n            return new Matrix<Td, Tv>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new Matrix by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting Matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateConvolution<Ti, Tf, Tm, Ts>(\n                Matrix<Ti> image, Matrix<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Tv> castFun)\n        {\n            V2l size = 1 + image.S - filter.S;\n            if (size.Y <= 0 ||size.X <= 0) throw new Exception(\"filter to large\");\n            return new Matrix<Td, Tv>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateOuterProduct<Tx, Ty>(\n                    Vector<Tx> tx, Vector<Ty> ty,\n                    Func<Tx, Ty, Tv> fun)\n        {\n            return new Matrix<Td, Tv>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<Tx, Ty>(tx, ty, fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateOuterProduct<Tx, Tyd, Ty>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty,\n                    Func<Tx, Ty, Tv> fun)\n        {\n            return new Matrix<Td, Tv>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<Tx, Tyd, Ty>(tx, ty, fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateOuterProduct<Txd, Tx, Ty>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty,\n                    Func<Tx, Ty, Tv> fun)\n        {\n            return new Matrix<Td, Tv>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<Txd, Tx, Ty>(tx, ty, fun);\n        }\n\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static Matrix<Td, Tv> CreateOuterProduct<Txd, Tx, Tyd, Ty>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty,\n                    Func<Tx, Ty, Tv> fun)\n        {\n            return new Matrix<Td, Tv>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty>(tx, ty, fun);\n        }\n\n        #endregion\n\n        #region Sampling\n\n        public readonly TRes SampleRaw4<T1, TRes>(\n                V2d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return SampleRaw4(v.X, v.Y, xipl, yipl);\n        }\n\n        /// <summary>\n        /// Sample the matrix using 4 samples and the supplied\n        /// interpolation function. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the matrix, i.e. pixel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw4<T1, TRes>(\n                double x, double y,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long i0 = Info.Origin + xi * dx + yi * dy, i1 = i0 + dy;\n            return yipl(yf, xipl(xf, Getter(Data, i0), Getter(Data, i0 + dx)),\n                            xipl(xf, Getter(Data, i1), Getter(Data, i1 + dx)));\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                V2d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return Sample4(v.X, v.Y, xipl, yipl,\n                           Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                double x, double y,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return Sample4(x, y, xipl, yipl,\n                           Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample4<T1, TRes>(\n                V2d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, TRes> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample4(v.X, v.Y, xipl, yipl,\n                           index_min_max_delta_xIndexFun,\n                           index_min_max_delta_yIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the matrix using 4 samples and the supplied\n        /// interpolation functions., If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the matrix, i.e. pixel centers are assumed to be on\n        /// integer coordinates.\n        /// </summary>\n        public readonly TRes Sample4<T1, TRes>(\n                double x, double y,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, TRes> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            return yipl(yf, xipl(xf, Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0)),\n                            xipl(xf, Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1)));\n        }\n\n        public readonly void SetScaled4<T1>(Matrix<Td, Tv> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, Tv> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun)\n        {\n            var dxa = new Tup2<long>[SX];\n            var xfa = new double[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi;\n                dxa[tix] = dx; xfa[tix] = xf;\n            }\n            var dya = new Tup2<long>[SY];\n            var yfa = new double[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi;\n                dya[tiy] = dy; yfa[tiy] = yf;\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(data, i, sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Setter(data, i, sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(data, i, sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl));\n                } }\n            }\n        }\n\n        public readonly void SetScaled4<T1, T2>(Matrix<Td, Tv> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<T2, Tv> clampFun)\n        {\n            var dxa = new Tup2<long>[SX];\n            var xfa = new double[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi;\n                dxa[tix] = dx; xfa[tix] = xf;\n            }\n            var dya = new Tup2<long>[SY];\n            var yfa = new double[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi;\n                dya[tiy] = dy; yfa[tiy] = yf;\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(data, i, clampFun(sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl)));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Setter(data, i, clampFun(sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl)));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(data, i, clampFun(sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl)));\n                } }\n            }\n        }\n\n        public readonly TRes Sample4<T1, TRes>(\n                Tup2<long> dx, Tup2<long> dy, double xf, double yf,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return yipl(yf, xipl(xf, Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0)),\n                            xipl(xf, Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1)));\n        }\n\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return SampleRaw16(v.X, v.Y, xipl, yipl, xsmp, ysmp);\n        }\n\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long d2 = dx + dx;\n            long i1 = Info.Origin + xi * dx + yi * dy, i0 = i1 - dy, i2 = i1 + dy, i3 = i2 + dy;\n            var wx = xipl(xf); var wy = yipl(yf);\n            return ysmp(xsmp(Getter(Data, i0 - dx), Getter(Data, i0), Getter(Data, i0 + dx), Getter(Data, i0 + d2), ref wx),\n                        xsmp(Getter(Data, i1 - dx), Getter(Data, i1), Getter(Data, i1 + dx), Getter(Data, i1 + d2), ref wx),\n                        xsmp(Getter(Data, i2 - dx), Getter(Data, i2), Getter(Data, i2 + dx), Getter(Data, i2 + d2), ref wx),\n                        xsmp(Getter(Data, i3 - dx), Getter(Data, i3), Getter(Data, i3 + dx), Getter(Data, i3 + d2), ref wx), ref wy);\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return Sample16(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return Sample16(x, y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample16(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            var wx = xipl(xf); var wy = yipl(yf);\n            return ysmp(xsmp(Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0), Getter(Data, dx.E2 + dy.E0), Getter(Data, dx.E3 + dy.E0), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1), Getter(Data, dx.E2 + dy.E1), Getter(Data, dx.E3 + dy.E1), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E2), Getter(Data, dx.E1 + dy.E2), Getter(Data, dx.E2 + dy.E2), Getter(Data, dx.E3 + dy.E2), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E3), Getter(Data, dx.E1 + dy.E3), Getter(Data, dx.E2 + dy.E3), Getter(Data, dx.E3 + dy.E3), ref wx), ref wy);\n        }\n\n        public readonly void SetScaled16<T1,T2, T3>(Matrix<Td, Tv> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, Tv> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            var dxa = new Tup4<long>[SX];\n            var wxa = new Tup4<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi; dx.E3 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup4<long>[SY];\n            var wya = new Tup4<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi; dy.E3 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(data, i, sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Setter(data, i, sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(data, i, sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n        }\n\n        public readonly void SetScaled16<T1,T2, T3, T4>(Matrix<Td, Tv> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, T4> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun,\n                Func<T4, Tv> clampFun)\n        {\n            var dxa = new Tup4<long>[SX];\n            var wxa = new Tup4<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi; dx.E3 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup4<long>[SY];\n            var wya = new Tup4<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi; dy.E3 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(data, i, clampFun(sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp)));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Setter(data, i, clampFun(sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp)));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(data, i, clampFun(sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp)));\n                } }\n            }\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                Tup4<long> dx, Tup4<long> dy, Tup4<T1> wx, Tup4<T2> wy,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return ysmp(xsmp(Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0), Getter(Data, dx.E2 + dy.E0), Getter(Data, dx.E3 + dy.E0), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1), Getter(Data, dx.E2 + dy.E1), Getter(Data, dx.E3 + dy.E1), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E2), Getter(Data, dx.E1 + dy.E2), Getter(Data, dx.E2 + dy.E2), Getter(Data, dx.E3 + dy.E2), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E3), Getter(Data, dx.E1 + dy.E3), Getter(Data, dx.E2 + dy.E3), Getter(Data, dx.E3 + dy.E3), ref wx), ref wy);\n        }\n\n        public readonly TRes SampleRaw36<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return SampleRaw36(v.X, v.Y, xipl, yipl, xsmp, ysmp);\n        }\n\n        public readonly TRes SampleRaw36<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long i2 = Info.Origin + xi * dx + yi * dy;\n            long i1 = i2 - dy, i0 = i1 - dy, i3 = i2 + dy, i4 = i3 + dy, i5 = i4 + dy;\n            long d2 = dx + dx, d3 = d2 + dx;\n            var wx = xipl(xf); var wy = yipl(yf);\n            return ysmp(xsmp(Getter(Data, i0 - d2), Getter(Data, i0 - dx), Getter(Data, i0), Getter(Data, i0 + dx), Getter(Data, i0 + d2), Getter(Data, i0 + d3), ref wx),\n                        xsmp(Getter(Data, i1 - d2), Getter(Data, i1 - dx), Getter(Data, i1), Getter(Data, i1 + dx), Getter(Data, i1 + d2), Getter(Data, i1 + d3), ref wx),\n                        xsmp(Getter(Data, i2 - d2), Getter(Data, i2 - dx), Getter(Data, i2), Getter(Data, i2 + dx), Getter(Data, i2 + d2), Getter(Data, i2 + d3), ref wx),\n                        xsmp(Getter(Data, i3 - d2), Getter(Data, i3 - dx), Getter(Data, i3), Getter(Data, i3 + dx), Getter(Data, i3 + d2), Getter(Data, i3 + d3), ref wx),\n                        xsmp(Getter(Data, i4 - d2), Getter(Data, i4 - dx), Getter(Data, i4), Getter(Data, i4 + dx), Getter(Data, i4 + d2), Getter(Data, i4 + d3), ref wx),\n                        xsmp(Getter(Data, i5 - d2), Getter(Data, i5 - dx), Getter(Data, i5), Getter(Data, i5 + dx), Getter(Data, i5 + d2), Getter(Data, i5 + d3), ref wx), ref wy);\n        }\n\n        public readonly TRes Sample36Clamped<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return Sample36(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample36Clamped<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return Sample36(x, y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample36(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun);\n        }\n\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i; dx.E4 += i; dx.E5 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            var wx = xipl(xf); var wy = yipl(yf);\n            return ysmp(xsmp(Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0), Getter(Data, dx.E2 + dy.E0), Getter(Data, dx.E3 + dy.E0), Getter(Data, dx.E4 + dy.E0), Getter(Data, dx.E5 + dy.E0), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1), Getter(Data, dx.E2 + dy.E1), Getter(Data, dx.E3 + dy.E1), Getter(Data, dx.E4 + dy.E1), Getter(Data, dx.E5 + dy.E1), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E2), Getter(Data, dx.E1 + dy.E2), Getter(Data, dx.E2 + dy.E2), Getter(Data, dx.E3 + dy.E2), Getter(Data, dx.E4 + dy.E2), Getter(Data, dx.E5 + dy.E2), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E3), Getter(Data, dx.E1 + dy.E3), Getter(Data, dx.E2 + dy.E3), Getter(Data, dx.E3 + dy.E3), Getter(Data, dx.E4 + dy.E3), Getter(Data, dx.E5 + dy.E3), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E4), Getter(Data, dx.E1 + dy.E4), Getter(Data, dx.E2 + dy.E4), Getter(Data, dx.E3 + dy.E4), Getter(Data, dx.E4 + dy.E4), Getter(Data, dx.E5 + dy.E4), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E5), Getter(Data, dx.E1 + dy.E5), Getter(Data, dx.E2 + dy.E5), Getter(Data, dx.E3 + dy.E5), Getter(Data, dx.E4 + dy.E5), Getter(Data, dx.E5 + dy.E5), ref wx), ref wy);\n        }\n\n        public readonly void SetScaled36<T1, T2, T3>(Matrix<Td, Tv> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, Tv> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun)\n        {\n            var dxa = new Tup6<long>[SX];\n            var wxa = new Tup6<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1;\n                dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi;\n                dx.E3 += dxi; dx.E4 += dxi; dx.E5 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup6<long>[SY];\n            var wya = new Tup6<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1;\n                dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi;\n                dy.E3 += dyi; dy.E4 += dyi; dy.E5 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(data, i, sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Setter(data, i, sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(data, i, sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                } }\n            }\n        }\n\n        public readonly void SetScaled36<T1, T2, T3, T4>(Matrix<Td, Tv> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, T4> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun,\n                Func<T4, Tv> clampFun)\n        {\n            var dxa = new Tup6<long>[SX];\n            var wxa = new Tup6<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1;\n                dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi;\n                dx.E3 += dxi; dx.E4 += dxi; dx.E5 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup6<long>[SY];\n            var wya = new Tup6<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1;\n                dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi;\n                dy.E3 += dyi; dy.E4 += dyi; dy.E5 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(data, i, clampFun(sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp)));\n                } }\n            }\n            else if (Info.DY == 1)\n            {\n                long xs = Info.DSX, xj = Info.JXY;\n                long ys = Info.SY;\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ye = i + ys, y = FY; i != ye; i++, y++) {\n                    Setter(data, i, clampFun(sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp)));\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(data, i, clampFun(sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp)));\n                } }\n            }\n        }\n\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                Tup6<long> dx, Tup6<long> dy, Tup6<T1> wx, Tup6<T2> wy,\n                FuncRef1<Tv, Tv, Tv, Tv, Tv, Tv, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return ysmp(xsmp(Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0), Getter(Data, dx.E2 + dy.E0), Getter(Data, dx.E3 + dy.E0), Getter(Data, dx.E4 + dy.E0), Getter(Data, dx.E5 + dy.E0), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1), Getter(Data, dx.E2 + dy.E1), Getter(Data, dx.E3 + dy.E1), Getter(Data, dx.E4 + dy.E1), Getter(Data, dx.E5 + dy.E1), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E2), Getter(Data, dx.E1 + dy.E2), Getter(Data, dx.E2 + dy.E2), Getter(Data, dx.E3 + dy.E2), Getter(Data, dx.E4 + dy.E2), Getter(Data, dx.E5 + dy.E2), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E3), Getter(Data, dx.E1 + dy.E3), Getter(Data, dx.E2 + dy.E3), Getter(Data, dx.E3 + dy.E3), Getter(Data, dx.E4 + dy.E3), Getter(Data, dx.E5 + dy.E3), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E4), Getter(Data, dx.E1 + dy.E4), Getter(Data, dx.E2 + dy.E4), Getter(Data, dx.E3 + dy.E4), Getter(Data, dx.E4 + dy.E4), Getter(Data, dx.E5 + dy.E4), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E5), Getter(Data, dx.E1 + dy.E5), Getter(Data, dx.E2 + dy.E5), Getter(Data, dx.E3 + dy.E5), Getter(Data, dx.E4 + dy.E5), Getter(Data, dx.E5 + dy.E5), ref wx), ref wy);\n        }\n        #endregion\n\n        #region Drawing\n\n        /// <summary>\n        /// Draws a horizontal line. The parameters x0, x1, and y are rounded\n        /// to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetLineX(double x0, double x1, double y, Tv value)\n        {\n            SetLineX((long)(x0 + 0.5), (long)(x1 + 0.5), (long)(y + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical line. The parameters x, y0, and y1 are rounded\n        /// to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetLineY(double x, double y0, double y1, Tv value)\n        {\n            SetLineY((long)(x + 0.5), (long)(y0 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a horizontal line.\n        /// </summary>\n        public readonly void SetLineX(long x0, long x1, long y, Tv value)\n        {\n            long xmin = Fun.Max(Fun.Min(x0, x1), Info.First.X);\n            long xmax = Fun.Min(Fun.Max(x0, x1), Info.First.X + Info.Size.X - 1);\n            if (y >= Info.First.Y && y < Info.First.Y + Info.Size.Y)\n                for (long x = xmin; x <= xmax; x++) this[x, y] = value;\n        }\n\n        /// <summary>\n        /// Draws a vertical line.\n        /// </summary>\n        public readonly void SetLineY(long x, long y0, long y1, Tv value)\n        {\n            long ymin = Fun.Max(Fun.Min(y0, y1), Info.First.Y);\n            long ymax = Fun.Min(Fun.Max(y0, y1), Info.First.Y + Info.Size.Y - 1);\n            if (x >= Info.First.X && x < Info.First.X + Info.Size.X)\n                for (long y = ymin; y <= ymax; y++) this[x, y] = value;\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame. The corner positions are\n        /// rounded to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetRectangle(V2d p0, V2d p1, Tv value)\n        {\n            SetRectangle((long)(p0.X + 0.5), (long)(p0.Y + 0.5),\n                         (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n        /// <summary>\n        /// Draws a rectangular frame. The parameters x0, x1, y0, and y1 are\n        /// rounded to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetRectangle(double x0, double y0, double x1, double y1, Tv value)\n        {\n            SetRectangle((long)(x0 + 0.5), (long)(y0 + 0.5),\n                         (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(V2i p0, V2i p1, Tv value)\n        {\n            SetRectangle((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(V2l v0, V2l v1, Tv value)\n        {\n            SetRectangle(v0.X, v0.Y, v1.X, v1.Y, value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(long x0, long y0, long x1, long y1, Tv value)\n        {\n            long ymin = Fun.Min(y0, y1), ymax = Fun.Max(y0, y1);\n            SetLineX(x0, x1, ymin, value);\n            SetLineY(x0, ymin + 1L, ymax - 1L, value);\n            SetLineY(x1, ymin + 1L, ymax - 1L, value);\n            SetLineX(x0, x1, ymax, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle and its interior to the supplied value.\n        /// Note that the coordinates are rounded to the nearest integer coordinate.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2d p0, V2d p1, Tv value)\n        {\n            SetRectangleFilled((long)(p0.X + 0.5), (long)(p0.Y + 0.5),\n                               (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle and its interior to the supplied value.\n        /// Note that the coordinates are rounded to the nearest integer coordinate.\n        /// </summary>\n        public readonly void SetRectangleFilled(double x0, double y0, double x1, double y1, Tv value)\n        {\n            SetRectangleFilled((long)(x0 + 0.5), (long)(y0 + 0.5),\n                               (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// position vectors and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2i p0, V2i p1, Tv value)\n        {\n            SetRectangleFilled((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// position vectors and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2l p0, V2l p1, Tv value)\n        {\n            SetRectangleFilled(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// coordinates and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(long x0, long y0, long x1, long y1, Tv value)\n        {\n            long xmin = Fun.Max(Fun.Min(x0, x1), Info.First.X);\n            long xmax = Fun.Min(Fun.Max(x0, x1), Info.First.X + Info.Size.X - 1);\n            if (xmin > xmax) return;\n            long ymin = Fun.Max(Fun.Min(y0, y1), Info.First.Y);\n            long ymax = Fun.Min(Fun.Max(y0, y1), Info.First.Y + Info.Size.Y - 1);\n            if (ymin > ymax) return;\n\n            SubMatrix(x0, y0, 1 + x1 - x0, 1 + y1 - y0).Set(value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2d p, double radius, Tv value)\n        {\n            SetCross((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around [x,y].\n        /// </summary>\n        public readonly void SetCross(double x, double y, double radius, Tv value)\n        {\n            SetCross((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2i p, int radius, Tv value)\n        {\n            SetCross((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2l p, long radius, Tv value)\n        {\n            SetCross(p.X, p.Y, radius, value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around [x, y].\n        /// </summary>\n        public readonly void SetCross(long x, long y, long radius, Tv value)\n        {\n            SetLineX(x - radius, x + radius, y, value);\n            SetLineY(x, y - radius, y + radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2d p, double radius, Tv value)\n        {\n            SetCrossX((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(double x, double y, double radius, Tv value)\n        {\n            SetCrossX((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2i p, int radius, Tv value)\n        {\n            SetCrossX((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2l p, long radius, Tv value)\n        {\n            SetCrossX(p.X, p.Y, radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(long x, long y, long radius, Tv value)\n        {\n            SetLine(x - radius, y - radius, x + radius, y + radius, value);\n            SetLine(x + radius, y - radius, x - radius, y + radius, value);\n        }\n\n        public readonly void SetSquare(\n                V2d p, double radius, Tv value)\n        {\n            SetSquare((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquare(\n                double x, double y, double radius, Tv value)\n        {\n            SetSquare((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquare(\n                V2i p, int radius, Tv value)\n        {\n            SetSquare((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetSquare(\n                V2l p, long radius, Tv value)\n        {\n            SetSquare(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetSquare(\n                long x, long y, long radius, Tv value)\n        {\n            SetRectangle(x - radius, y - radius, x + radius, y + radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2d p, double radius, Tv value)\n        {\n            SetSquareFilled((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquareFilled(\n                double x, double y, double radius, Tv value)\n        {\n            SetSquareFilled((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2i p, int radius, Tv value)\n        {\n            SetSquareFilled((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2l p, long radius, Tv value)\n        {\n            SetSquareFilled(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                long x, long y, long radius, Tv value)\n        {\n            SetRectangleFilled(x - radius, y - radius, x + radius, y + radius, value);\n        }\n\n        public readonly void SetLine(\n                V2d p0, V2d p1, Tv value)\n        {\n            SetLine((long)(p0.X + 0.5), (long)(p0.Y + 0.5), (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n\n        public readonly void SetLine(\n                double x0, double y0, double x1, double y1, Tv value)\n        {\n            SetLine((long)(x0 + 0.5), (long)(y0 + 0.5), (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        public readonly void SetLine(\n                V2i p0, V2i p1, Tv value)\n        {\n            SetLine((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        public readonly void SetLine(\n                V2l p0, V2l p1, Tv value)\n        {\n            SetLine(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        ///  Bresenham Line Algorithm\n        /// </summary>\n        public readonly void SetLine(\n                long x0, long y0, long x1, long y1, Tv value)\n        {\n            //-- Trivial Cases\n            if (x0 == x1) { SetLineY(x0, y0, y1, value); return; }\n            if (y0 == y1) { SetLineX(x0, x1, y1, value); return; }\n\n            //-- Bresenham\n            long dx, dy;\n            long incx, incy;\n\n            if (x1 >= x0)\n            {\n                dx = x1 - x0; incx = 1;\n            }\n            else\n            {\n                dx = x0 - x1; incx = -1;\n            }\n\n            if (y1 >= y0)\n            {\n                dy = y1 - y0;  incy = 1;\n            }\n            else\n            {\n                dy = y0 - y1; incy = -1;\n            }\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n            bool xok = x0 >= xmin && x0 <= xmax;\n            bool yok = y0 >= ymin && y0 <= ymax;\n            long balance;\n\n            if (dx >= dy)\n            {\n                dy <<= 1;\n                balance = dy - dx;\n                dx <<= 1;\n\n                while (x0 != x1)\n                {\n                    if (xok && yok) this[x0, y0] = value;\n                    if (balance >= 0)\n                    {\n                        y0 += incy; yok = y0 >= ymin && y0 <= ymax;\n                        balance -= dx;\n                    }\n                    balance += dy;\n                    x0 += incx; xok = x0 >= xmin && x0 <= xmax;\n                }\n                if (xok && yok) this[x0, y0] = value;\n            }\n            else\n            {\n                dx <<= 1;\n                balance = dx - dy;\n                dy <<= 1;\n\n                while (y0 != y1)\n                {\n                    if (xok && yok) this[x0, y0] = value;\n                    if (balance >= 0)\n                    {\n                        x0 += incx; xok = x0 >= xmin && x0 <= xmax;\n                        balance -= dy;\n                    }\n                    balance += dx;\n                    y0 += incy; yok = y0 >= ymin && y0 <= ymax;\n                }\n                if (xok && yok) this[x0, y0] = value;\n            }\n        }\n\n        /// <summary>\n        /// Set all pixels whose square region is intersected by the line from p0 to p1\n        /// to the supplied value. Does not perform any bounds checks.\n        /// </summary>\n        public readonly void SetLineAllTouchedRaw(V2d p0, V2d p1, Tv value)\n        {\n            SetLineAllTouchedRaw(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        /// Set all pixels whose square region is intersected by the line from (x0,y0) to (x1,y1)\n        /// to the supplied value. Does not perform any bounds checks.\n        /// </summary>\n        public readonly void SetLineAllTouchedRaw(double x0, double y0, double x1, double y1, Tv value)\n        {\n            var ix = (long)Fun.Floor(x0);\n            var iy = (long)Fun.Floor(y0);\n            var dx = x1 - x0;\n            var dy = y1 - y0;\n\n            var len = Fun.Sqrt(dx * dx + dy * dy);\n\n            double tx, ty, dtx, dty;\n            long dix, diy;\n\n            if (dx > 0.0)       { dtx = len / dx; tx = dtx * (1.0 - (x0 - ix)); dix = Info.DX; }\n            else if (dx < 0.0)  { dtx = -len / dx; tx = dtx * (x0 - ix); dix = -Info.DX; }\n            else                { dtx = 0.0; tx = len; dix = 0; }\n\n            if (dy > 0.0)       { dty = len / dy; ty = dty * (1.0 - (y0 - iy)); diy = Info.DY; }\n            else if (dy < 0.0)  { dty = -len / dy; ty = dty * (y0 - iy); diy = -Info.DY; }\n            else                { dty = 0.0; ty = len; diy = 0; }\n\n            var mdata = Data; var mset = Setter;\n            double t = 0.0;\n            long index = Info.Origin + ix * Info.DX + iy * Info.DY;\n            do\n            {\n                mset(mdata, index, value);\n                if (tx < ty)    { t = tx; tx += dtx; index += dix; }\n                else            { t = ty; ty += dty; index += diy; }\n            }\n            while (t < len);\n        }\n\n        public readonly void SetCircle(\n                V2d p, double radius, Tv value)\n        {\n            SetCircle((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircle(\n                double x, double y, double radius, Tv value)\n        {\n            SetCircle((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircle(\n                V2i p, int radius, Tv value)\n        {\n            SetCircle((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetCircle(\n                V2l p, long radius, Tv value)\n        {\n            SetCircle(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetCircle(\n                long x, long y, long radius, Tv value)\n        {\n            long f = 1 - radius;\n            long ddF_x = 0;\n            long ddF_y = -2 * radius;\n            long rx = 0;\n            long ry = radius;\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n\n            if (x >= xmin && x <= xmax)\n            {\n                var ym = y - radius; if (ym >= ymin && ym <= ymax) this[x, ym] = value;\n                var yp = y + radius; if (yp >= ymin && yp <= ymax) this[x, yp] = value;\n            }\n            if (y >= xmin && y <= ymax)\n            {\n                var xm = x - radius; if (xm >= xmin && xm <= xmax) this[xm, y] = value;\n                var xp = x + radius; if (xp >= xmin && xp <= xmax) this[xp, y] = value;\n            }\n            bool xmxOk = true, xpxOk = true, xmyOk = true, xpyOk = true;\n            while (rx < ry)\n            {\n                if (f >= 0)\n                {\n                    ry--; ddF_y += 2; f += ddF_y;\n                }\n                rx++;\n                ddF_x += 2;\n                f += ddF_x + 1;\n\n                long xmx = x - rx; xmxOk = xmx >= xmin && xmx <= xmax;\n                long xpx = x + rx; xpxOk = xpx >= xmin && xpx <= xmax;\n                long xmy = x - ry; xmyOk = xmy >= xmin && xmy <= xmax;\n                long xpy = x + ry; xpyOk = xpy >= xmin && xpy <= xmax;\n                long ymx = y - rx, ypx = y + rx;\n                long ymy = y - ry, ypy = y + ry;\n\n                if (ymx >= ymin && ymx <= ymax)\n                {\n                    if (xmyOk) this[xmy, ymx] = value;\n                    if (xpyOk) this[xpy, ymx] = value;\n                }\n                if (ypx >= ymin && ypx <= ymax)\n                {\n                    if (xmyOk) this[xmy, ypx] = value;\n                    if (xpyOk) this[xpy, ypx] = value;\n                }\n                if (ymy >= ymin && ymy <= ymax)\n                {\n                    if (xmxOk) this[xmx, ymy] = value;\n                    if (xpxOk) this[xpx, ymy] = value;\n                }\n                if (ypy >= ymin && ypy <= ymax)\n                {\n                    if (xmxOk) this[xmx, ypy] = value;\n                    if (xpxOk) this[xpx, ypy] = value;\n                }\n            }\n        }\n\n        public readonly void SetCircleFilled(\n                V2d p, double radius, Tv value)\n        {\n            SetCircleFilled((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircleFilled(\n                double x, double y, double radius, Tv value)\n        {\n            SetCircleFilled((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircleFilled(\n                V2i p, int radius, Tv value)\n        {\n            SetCircleFilled((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetCircleFilled(\n                V2l p, long radius, Tv value)\n        {\n            SetCircleFilled(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetCircleFilled(\n                long x0, long y0, long radius, Tv value)\n        {\n            long x = radius;\n            long y = 0;\n            long xChange = 1 - (radius << 1);\n            long yChange = 0;\n            long radiusError = 0;\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n\n            long mdx = DX; var mdata = Data; var mset = Setter;\n\n            while (x >= y)\n            {\n                if (y0 + y >= ymin && y0 + y <= ymax)\n                {\n                    var xb = Fun.Max(x0 - x, xmin); var xe = Fun.Min(x0 + x, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 + y), e = Info.Index(xe + 1, y0 + y); i != e; i += mdx)\n                        mset(mdata, i, value);\n                }\n                if (y0 - y >= ymin && y0 - y <= ymax)\n                {\n                    var xb = Fun.Max(x0 - x, xmin); var xe = Fun.Min(x0 + x, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 - y), e = Info.Index(xe + 1, y0 - y); i != e; i += mdx)\n                            mset(mdata, i, value);\n                }\n                if (y0 + x >= ymin && y0 + x <= ymax)\n                {\n                    var xb = Fun.Max(x0 - y, xmin); var xe = Fun.Min(x0 + y, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 + x), e = Info.Index(xe + 1, y0 + x); i != e; i += mdx)\n                            mset(mdata, i, value);\n                }\n                if (y0 - x >= ymin && y0 - x <= ymax)\n                {\n                    var xb = Fun.Max(x0 - y, xmin); var xe = Fun.Min(x0 + y, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 - x), e = Info.Index(xe + 1, y0 - x); i != e; i += mdx)\n                            mset(mdata, i, value);\n                }\n                y++;\n                radiusError += yChange;\n                yChange += 2;\n                if (((radiusError << 1) + xChange) > 0)\n                {\n                    x--;\n                    radiusError += xChange;\n                    xChange += 2;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Set all matrix pixels inside the specified polygon to the supplied\n        /// value. This is a raw routine that does no clipping and assumes that\n        /// all pixels that need to be set are within the matrix. The polygon\n        /// is assumed to consist of two y-monotone point sequences between\n        /// the points with minimum and maximum y-coordinate. Note that convex\n        /// and non-concave polygons automatically fullfill this condition.\n        /// Rasterization is performed according to DirextX11 rules.\n        /// </summary>\n        public readonly void SetMonotonePolygonFilledRaw(\n                V2d[] polygon,\n                Tv value,\n                Winding winding = Winding.CCW,\n                double eps = 1e-8)\n        {\n            var pc = polygon.Length;\n            int diLeft = winding == Winding.CCW ? 1 : pc - 1;\n            int diRight = winding == Winding.CCW ? pc - 1 : 1;\n            int eLeft = 0, end = 0;\n            double yeLeft = polygon[0].Y;\n            for (int pi = 1; pi < pc; pi++) // find min in (y)eLeft and max in end\n            {\n                var y = polygon[pi].Y;\n                if (y < yeLeft) { eLeft = pi; yeLeft = y; }\n                if (y > polygon[end].Y) end = pi;\n            }\n            int eRight = eLeft, sLeft = 0, sRight = 0;\n            double yeRight = yeLeft;\n            double xfLeft = 0, fdeltaLeft = 0.0, xfRight = 0, fdeltaRight = 0.0;\n            long iLeft = 0, ideltaLeft = 0, iRight = 0, ideltaRight = 0;\n            long mdx = DX, mdy = DY; var mdata = Data; var mset = Setter;\n            long yi = (long)Fun.Ceiling(yeLeft - 0.5), yieLeft = yi, yieRight = yi;\n            var lineOrigin = Origin + yi * mdy;\n            bool exit = false;\n            while (true)\n            {\n                if (yi == yieLeft) // next left edge\n                {\n                    double ysLeft = 0.0;\n                    do\n                    {\n                        sLeft = eLeft; if (sLeft == end) { exit = true; break; }\n                        eLeft = (sLeft + diLeft) % pc;\n                        ysLeft = yeLeft;\n                        yeLeft = polygon[eLeft].Y;\n                        yieLeft = (long)Fun.Ceiling(yeLeft - 0.5);\n                    }\n                    while (yi == yieLeft); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaLeft = yeLeft - ysLeft;\n                    if (deltaLeft < 0.0) { exit = true; break; }\n                    if (deltaLeft < eps) deltaLeft = eps;\n                    deltaLeft = (polygon[eLeft].X - polygon[sLeft].X) / deltaLeft;\n                    ideltaLeft = (long)Fun.Ceiling(deltaLeft);\n                    fdeltaLeft = deltaLeft - (double)ideltaLeft;\n                    double xLeft = polygon[sLeft].X + (0.5 + (double)yi - ysLeft) * deltaLeft;\n                    iLeft = (long)Fun.Ceiling(xLeft - 0.5);\n                    xfLeft = xLeft - (double)iLeft + 0.5 - eps; // offset for stable 0.0 comparison\n                    iLeft = lineOrigin + iLeft * mdx;\n                    ideltaLeft = mdy + ideltaLeft * mdx;\n                }\n                if (exit) break;\n                if (yi == yieRight) // next right edge\n                {\n                    double ysRight = 0.0;\n                    do\n                    {\n                        sRight = eRight; if (sRight == end) { exit = true; break; }\n                        eRight = (sRight + diRight) % pc;\n                        ysRight = yeRight;\n                        yeRight = polygon[eRight].Y;\n                        yieRight = (long)Fun.Ceiling(yeRight - 0.5);\n                    }\n                    while (yi == yieRight); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaRight = yeRight - ysRight;\n                    if (deltaRight < 0.0) { exit = true; break; }\n                    if (deltaRight < eps) deltaRight = eps;\n                    deltaRight = (polygon[eRight].X - polygon[sRight].X) / deltaRight;\n                    ideltaRight = (long)Fun.Ceiling(deltaRight);\n                    fdeltaRight = deltaRight - (double)ideltaRight;\n                    double xRight = polygon[sRight].X + (0.5 + (double)yi - ysRight) * deltaRight;\n                    iRight = (long)Fun.Ceiling(xRight - 0.5);\n                    xfRight = xRight - (double)iRight + 0.5 - eps; // offset for stable 0.0 comparison\n                    iRight = lineOrigin + iRight * mdx;\n                    ideltaRight = mdy + ideltaRight * mdx;\n                }\n                if (exit) break;\n                long yimin = Fun.Min(yieLeft, yieRight);\n                while (yi < yimin)\n                {\n                    for (long i = iLeft; i < iRight; i += mdx)\n                    {\n                        mset(mdata, i, value);\n                    }\n                    iLeft += ideltaLeft; xfLeft += fdeltaLeft;\n                    if (xfLeft < 0.0) { xfLeft += 1.0; iLeft -= mdx; }\n                    iRight += ideltaRight; xfRight += fdeltaRight;\n                    if (xfRight < 0.0) { xfRight += 1.0; iRight -= mdx; }\n                    ++yi; lineOrigin += mdy;\n                }\n            }\n        }\n\n        /// <summary>\n        /// Set all matrix pixels inside the specified polygon to the supplied\n        /// value. This is a raw routine that does no clipping and assumes that\n        /// all pixels that need to be set are within the matrix. The polygon\n        /// is assumed to consist of two y-monotone point sequences between\n        /// the points with minimum and maximum y-coordinate. Note that convex\n        /// and non-concave polygons automatically fullfill this condition.\n        /// Rasterization is performed according to DirextX11 rules.\n        /// </summary>\n        public readonly void SetMonotonePolygonFilledRaw(\n                int[] polygon, V2d[] vertexArray,\n                Tv value,\n                Winding winding = Winding.CCW,\n                double eps = 1e-8)\n        {\n            var pc = polygon.Length;\n            int diLeft = winding == Winding.CCW ? 1 : pc - 1;\n            int diRight = winding == Winding.CCW ? pc - 1 : 1;\n            int eLeft = 0, end = 0;\n            double yeLeft = vertexArray[polygon[0]].Y;\n            for (int pi = 1; pi < pc; pi++) // find min in (y)eLeft and max in end\n            {\n                var y = vertexArray[polygon[pi]].Y;\n                if (y < yeLeft) { eLeft = pi; yeLeft = y; }\n                if (y > vertexArray[polygon[end]].Y) end = pi;\n            }\n            int eRight = eLeft, sLeft = 0, sRight = 0;\n            double yeRight = yeLeft;\n            double xfLeft = 0, fdeltaLeft = 0.0, xfRight = 0, fdeltaRight = 0.0;\n            long iLeft = 0, ideltaLeft = 0, iRight = 0, ideltaRight = 0;\n            long mdx = DX, mdy = DY; var mdata = Data; var mset = Setter;\n            long yi = (long)Fun.Ceiling(yeLeft - 0.5), yieLeft = yi, yieRight = yi;\n            var lineOrigin = Origin + yi * mdy;\n            bool exit = false;\n            while (true)\n            {\n                if (yi == yieLeft) // next left edge\n                {\n                    double ysLeft = 0.0;\n                    do\n                    {\n                        sLeft = eLeft; if (sLeft == end) { exit = true; break; }\n                        eLeft = (sLeft + diLeft) % pc;\n                        ysLeft = yeLeft;\n                        yeLeft = vertexArray[polygon[eLeft]].Y;\n                        yieLeft = (long)Fun.Ceiling(yeLeft - 0.5);\n                    }\n                    while (yi == yieLeft); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaLeft = yeLeft - ysLeft;\n                    if (deltaLeft < 0.0) { exit = true; break; }\n                    if (deltaLeft < eps) deltaLeft = eps;\n                    deltaLeft = (vertexArray[polygon[eLeft]].X - vertexArray[polygon[sLeft]].X) / deltaLeft;\n                    ideltaLeft = (long)Fun.Ceiling(deltaLeft);\n                    fdeltaLeft = deltaLeft - (double)ideltaLeft;\n                    double xLeft = vertexArray[polygon[sLeft]].X + (0.5 + (double)yi - ysLeft) * deltaLeft;\n                    iLeft = (long)Fun.Ceiling(xLeft - 0.5);\n                    xfLeft = xLeft - (double)iLeft + 0.5 - eps; // offset for stable 0.0 comparison\n                    iLeft = lineOrigin + iLeft * mdx;\n                    ideltaLeft = mdy + ideltaLeft * mdx;\n                }\n                if (exit) break;\n                if (yi == yieRight) // next right edge\n                {\n                    double ysRight = 0.0;\n                    do\n                    {\n                        sRight = eRight; if (sRight == end) { exit = true; break; }\n                        eRight = (sRight + diRight) % pc;\n                        ysRight = yeRight;\n                        yeRight = vertexArray[polygon[eRight]].Y;\n                        yieRight = (long)Fun.Ceiling(yeRight - 0.5);\n                    }\n                    while (yi == yieRight); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaRight = yeRight - ysRight;\n                    if (deltaRight < 0.0) { exit = true; break; }\n                    if (deltaRight < eps) deltaRight = eps;\n                    deltaRight = (vertexArray[polygon[eRight]].X - vertexArray[polygon[sRight]].X) / deltaRight;\n                    ideltaRight = (long)Fun.Ceiling(deltaRight);\n                    fdeltaRight = deltaRight - (double)ideltaRight;\n                    double xRight = vertexArray[polygon[sRight]].X + (0.5 + (double)yi - ysRight) * deltaRight;\n                    iRight = (long)Fun.Ceiling(xRight - 0.5);\n                    xfRight = xRight - (double)iRight + 0.5 - eps; // offset for stable 0.0 comparison\n                    iRight = lineOrigin + iRight * mdx;\n                    ideltaRight = mdy + ideltaRight * mdx;\n                }\n                if (exit) break;\n                long yimin = Fun.Min(yieLeft, yieRight);\n                while (yi < yimin)\n                {\n                    for (long i = iLeft; i < iRight; i += mdx)\n                    {\n                        mset(mdata, i, value);\n                    }\n                    iLeft += ideltaLeft; xfLeft += fdeltaLeft;\n                    if (xfLeft < 0.0) { xfLeft += 1.0; iLeft -= mdx; }\n                    iRight += ideltaRight; xfRight += fdeltaRight;\n                    if (xfRight < 0.0) { xfRight += 1.0; iRight -= mdx; }\n                    ++yi; lineOrigin += mdy;\n                }\n            }\n        }\n\n        #endregion\n\n        #region IMatrix\n\n        /// <summary>\n        /// Dimension of the generic Matrix.\n        /// </summary>\n        public readonly V2l Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(long x, long y)\n        {\n            return (object)this[x, y];\n        }\n\n        public readonly void SetValue(object value, long x, long y)\n        {\n            this[x, y] = (Tv)value;\n        }\n\n        public readonly object GetValue(V2l v)\n        {\n            return (object)this[v];\n        }\n\n        public readonly void SetValue(object value, V2l v)\n        {\n            this[v] = (Tv)value;\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    #region VolumeInfo\n\n    /// <summary>\n    /// A volume info contains the complete indexing information for a volume, but no data array.\n    /// </summary>\n    [Serializable]\n    public struct VolumeInfo : ITensorInfo\n    {\n        /// <summary>\n        /// Index of element with coordinates [0, 0, 0] in the underlying data array.\n        /// </summary>\n        public long Origin;\n\n        /// <summary>\n        /// Size of the volume.\n        /// </summary>\n        public V3l Size;\n\n        /// <summary>\n        /// Stride in each dimension.\n        /// </summary>\n        public V3l Delta;\n\n        /// <summary>\n        /// Coordinates of the first element.\n        /// May differ from coordinates [0, 0, 0] for subwindows that retain the original coordinate space.\n        /// </summary>\n        public V3l First;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a VolumeInfo given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the volume.</param>\n        /// <param name=\"delta\">Stride in each dimension.</param>\n        /// <param name=\"first\">Coordinates of the first element.</param>\n        public VolumeInfo(long origin, V3l size, V3l delta, V3l first)\n        {\n            Origin = origin;\n            Size = size;\n            Delta = delta;\n            First = first;\n        }\n\n        /// <summary>\n        /// Construct a VolumeInfo given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the volume.</param>\n        /// <param name=\"delta\">Stride in each dimension.</param>\n        public VolumeInfo(long origin, V3l size, V3l delta)\n            : this(origin, size, delta, V3l.Zero)\n        { }\n\n        private static V3l NewDelta(V3l size)\n        {\n            return new V3l(1L, size.X, size.X * size.Y);\n        }\n\n        private static V3l NewDelta(V3l size, V3l delta)\n        {\n            if (delta.Z == 1L) return new V3l(size.Z, size.Z * size.X, 1L);\n            if (delta.Y == 1L) return new V3l(size.Y * size.Z, 1L, size.Y);\n            return NewDelta(size);\n        }\n\n        /// <summary>\n        /// Construct volume info of specified size.\n        /// </summary>\n        public VolumeInfo(V3l size)\n            : this(0L, size, NewDelta(size))\n        { }\n\n        /// <summary>\n        /// Construct volume info of specified size and delta.\n        /// </summary>\n        public VolumeInfo(V3l size, V3l delta)\n            : this(0L, size, NewDelta(size, delta))\n        { }\n\n        public VolumeInfo(VolumeInfo info)\n            : this(0L, info.Size, NewDelta(info.Size, info.Delta))\n        {\n            F = info.F;\n        }\n\n        /// <summary>\n        /// Construct volume info of specified size.\n        /// </summary>\n        public VolumeInfo(V3i size)\n            : this((V3l)size)\n        { }\n\n        /// <summary>\n        /// Construct volume info of specified size and delta.\n        /// </summary>\n        public VolumeInfo(V3i size, V3i delta)\n            : this((V3l)size, (V3l)delta)\n        { }\n\n        /// <summary>\n        /// Construct volume info of specified size.\n        /// </summary>\n        public VolumeInfo(long sizeX, long sizeY, long sizeZ)\n            : this(new V3l(sizeX, sizeY, sizeZ))\n        { }\n\n        /// <summary>\n        /// Construct volume info of specified size.\n        /// </summary>\n        public VolumeInfo(int sizeX, int sizeY, int sizeZ)\n            : this(new V3l(sizeX, sizeY, sizeZ))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the the volume (3).\n        /// </summary>\n        public readonly int Rank { get { return 3; } }\n\n        /// <summary>\n        /// Total number of element in the volume.\n        /// </summary>\n        public readonly long Count { get { return  Size.X *  Size.Y *  Size.Z; } }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        public readonly V3l End { get { return First + Size; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOO { get { return First; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOO { get { return new V3l(First.X + Size.X, First.Y, First.Z); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIO { get { return new V3l(First.X, First.Y + Size.Y, First.Z); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIO { get { return new V3l(First.X + Size.X, First.Y + Size.Y, First.Z); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOI { get { return new V3l(First.X, First.Y, First.Z + Size.Z); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOI { get { return new V3l(First.X + Size.X, First.Y, First.Z + Size.Z); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OII { get { return new V3l(First.X, First.Y + Size.Y, First.Z + Size.Z); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l III { get { return First + Size; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l S { readonly get { return Size; } set { Size = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l D { readonly get { return Delta; } set { Delta = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l F { readonly get { return First; } set { Origin -= Delta.Dot(value - First); First = value; } }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l E { get { return First + Size; } }\n\n        /// <summary>\n        /// Size.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Size.X; } set { Size.X = value; } }\n\n        /// <summary>\n        /// Size.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Size.Y; } set { Size.Y = value; } }\n\n        /// <summary>\n        /// Size.Z\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SZ { readonly get { return Size.Z; } set { Size.Z = value; } }\n\n        /// <summary>\n        /// Delta.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Delta.X; } set { Delta.X = value; } }\n\n        /// <summary>\n        /// Delta.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Delta.Y; } set { Delta.Y = value; } }\n\n        /// <summary>\n        /// Delta.Z\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DZ { readonly get { return Delta.Z; } set { Delta.Z = value; } }\n\n        /// <summary>\n        /// First.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX\n        {\n            readonly get { return First.X; }\n            set { Origin -= Delta.X * (value - First.X); First.X = value; }\n        }\n\n        /// <summary>\n        /// First.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY\n        {\n            readonly get { return First.Y; }\n            set { Origin -= Delta.Y * (value - First.Y); First.Y = value; }\n        }\n\n        /// <summary>\n        /// First.Z\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FZ\n        {\n            readonly get { return First.Z; }\n            set { Origin -= Delta.Z * (value - First.Z); First.Z = value; }\n        }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX\n        {\n            get { return First.X + Size.X; }\n        }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY\n        {\n            get { return First.Y + Size.Y; }\n        }\n\n        /// <summary>\n        /// End in dimension Z (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EZ\n        {\n            get { return First.Z + Size.Z; }\n        }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Size.X * Delta.X; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Size.Y * Delta.Y; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSZ { get { return Size.Z * Delta.Z; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Delta.X; } }\n\n        public readonly long GetJX(V3l size)\n        {\n            return Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Delta.Y - Size.X * Delta.X; } }\n\n        public readonly long GetJY(V3l size)\n        {\n            return Delta.Y - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZ { get { return Delta.Z - Size.Y * Delta.Y; } }\n\n        public readonly long GetJZ(V3l size)\n        {\n            return Delta.Z - size.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX0 { get { return Delta.X; } }\n\n        public readonly long GetJX0(V3l size)\n        {\n            return Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JXY { get { return Delta.X - Size.Y * Delta.Y; } }\n\n        public readonly long GetJXY(V3l size)\n        {\n            return Delta.X - size.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JXZ { get { return Delta.X - Size.Z * Delta.Z; } }\n\n        public readonly long GetJXZ(V3l size)\n        {\n            return Delta.X - size.Z * Delta.Z;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JYX { get { return Delta.Y - Size.X * Delta.X; } }\n\n        public readonly long GetJYX(V3l size)\n        {\n            return Delta.Y - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY0 { get { return Delta.Y; } }\n\n        public readonly long GetJY0(V3l size)\n        {\n            return Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JYZ { get { return Delta.Y - Size.Z * Delta.Z; } }\n\n        public readonly long GetJYZ(V3l size)\n        {\n            return Delta.Y - size.Z * Delta.Z;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z in a loop around another loop\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZX { get { return Delta.Z - Size.X * Delta.X; } }\n\n        public readonly long GetJZX(V3l size)\n        {\n            return Delta.Z - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z in a loop around another loop\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZY { get { return Delta.Z - Size.Y * Delta.Y; } }\n\n        public readonly long GetJZY(V3l size)\n        {\n            return Delta.Z - size.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZ0 { get { return Delta.Z; } }\n\n        public readonly long GetJZ0(V3l size)\n        {\n            return Delta.Z;\n        }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Index(First); } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long OriginIndex { readonly get { return Origin; } set { Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return new long[] { SX, SY, SZ }; }\n            set { SX = value[0]; SY = value[1]; SZ = value[2];  }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return new long[] { DX, DY, DZ }; }\n            set { DX = value[0]; DY = value[1]; DZ = value[2];  }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return new long[] { FX, FY, FZ }; }\n            set { FX = value[0]; FY = value[1]; FZ = value[2];  }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXYZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXZY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYXZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYZX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZXY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZYX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Indexing Helper Methods\n\n        public readonly long Dv(long dx, long dy, long dz)\n        {\n            return dx * Delta.X + dy * Delta.Y + dz * Delta.Z;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(long x, long y, long z)\n        {\n            return Origin + x * Delta.X + y * Delta.Y + z * Delta.Z;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(V3l v)\n        {\n            return Origin + v.X * Delta.X + v.Y * Delta.Y + v.Z * Delta.Z;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(V3i v)\n        {\n            return Origin + v.X * Delta.X + v.Y * Delta.Y + v.Z * Delta.Z;\n        }\n\n        #endregion\n\n        #region Interpretation and Parts\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly VolumeInfo SubVolumeWindow(V3l begin, V3l size)\n        {\n            return new VolumeInfo(Origin, size, Delta, begin);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubVolume(V3l begin, V3l size)\n        {\n            return new VolumeInfo(Index(begin), size, Delta);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly VolumeInfo SubVolumeWindow(V3i begin, V3i size)\n        {\n            return new VolumeInfo(Origin, (V3l)size, Delta, (V3l)begin);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubVolume(V3i begin, V3i size)\n        {\n            return new VolumeInfo(Index((V3l)begin), (V3l)size, Delta);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly VolumeInfo SubVolumeWindow(V3l begin, V3l size, V3l delta)\n        {\n            return new VolumeInfo(Origin, size, delta, begin);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubVolume(V3l begin, V3l size, V3l delta)\n        {\n            return new VolumeInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly VolumeInfo SubVolumeWindow(V3i begin, V3i size, V3i delta)\n        {\n            return new VolumeInfo(Origin, (V3l)size, (V3l)delta, (V3l)begin);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubVolume(V3i begin, V3i size, V3i delta)\n        {\n            return new VolumeInfo(Index((V3l)begin), (V3l)size, (V3l)delta);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly VolumeInfo SubVolumeWindow(V3l begin, V3l size, V3l delta, V3l first)\n        {\n            return new VolumeInfo(Index(begin), size, delta) { F = first };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly VolumeInfo SubVolumeWindow(V3i begin, V3i size, V3i delta, V3i first)\n        {\n            return new VolumeInfo(Index((V3l)begin), (V3l)size, (V3l)delta)\n                            { F = (V3l)first };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly VolumeInfo SubVolumeWindow(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new VolumeInfo(Origin, new V3l(sizeX, sizeY, sizeZ),\n                                  Delta, new V3l(beginX, beginY, beginZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubVolume(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new VolumeInfo(Index(beginX, beginY, beginZ),\n                                  new V3l(sizeX, sizeY, sizeZ),\n                                  Delta);\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly VolumeInfo SubVolumeWindow(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new VolumeInfo(Origin, new V3l(sizeX, sizeY, sizeZ),\n                                  new V3l(deltaX, deltaY, deltaZ),\n                                  new V3l(beginX, beginY, beginZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubVolume(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new VolumeInfo(Index(beginX, beginY, beginZ),\n                                  new V3l(sizeX, sizeY, sizeZ),\n                                  new V3l(deltaX, deltaY, deltaZ));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(V3l begin, long size, long delta)\n        {\n            return new VectorInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(V3i begin, long size, long delta)\n        {\n            return new VectorInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo AsVector()\n        {\n            if (JX != 0 || JY != 0)\n                throw new Exception(\"cannot represent this volume as vector\");\n            return new VectorInfo(Origin, SX * SY * SZ, DX);\n        }\n\n        /// <summary>\n        /// If the lines of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo AsMatrixXYxZ()\n        {\n            if (JY != 0)\n                throw new Exception(\"cannot represent this volume as matrix\");\n            return new MatrixInfo(Origin, new V2l(SX * SY, SZ), D.XZ);\n        }\n\n        /// <summary>\n        /// If the planes of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo AsMatrixXxYZ()\n        {\n            if (JZ != 0)\n                throw new Exception(\"cannot represent this volume as matrix\");\n            return new MatrixInfo(Origin, new V2l(SX, SY * SZ), D.XY);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(V3l origin, V2l size, V2l delta)\n        {\n            return new MatrixInfo(Index(origin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(V3i origin, V2i size, V2l delta)\n        {\n            return new MatrixInfo(Index(origin), (V2l)size, delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubMatrix(\n                long bx, long by, long bz,\n                long sx, long sy, long dx, long dy)\n        {\n            return new MatrixInfo(Index(bx, by, bz), new V2l(sx, sy), new V2l(dx, dy));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubYZMatrix(long x)\n        {\n            return new MatrixInfo(Index(x, FY, FZ), S.YZ, D.YZ);\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubYZMatrixAsReadOnlyVolume(long x, long sizex)\n        {\n            return new VolumeInfo(Index(x, FY, FZ), new V3l(sizex, SY, SZ), D.OYZ);\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly MatrixInfo SubYZMatrixWindow(long x)\n        {\n            return new MatrixInfo(Index(x, FY, FZ), S.YZ, D.YZ) { F = F.YZ };\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly VolumeInfo SubYZMatrixAsReadOnlyVolumeWindow(long x, long sizex)\n        {\n            return new VolumeInfo(Index(x, FY, FZ), new V3l(sizex, SY, SZ), D.OYZ) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubXZMatrix(long y)\n        {\n            return new MatrixInfo(Index(FX, y, FZ), S.XZ, D.XZ);\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubXZMatrixAsReadOnlyVolume(long y, long sizey)\n        {\n            return new VolumeInfo(Index(FX, y, FZ), new V3l(SX, sizey, SZ), D.XOZ);\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly MatrixInfo SubXZMatrixWindow(long y)\n        {\n            return new MatrixInfo(Index(FX, y, FZ), S.XZ, D.XZ) { F = F.XZ };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly VolumeInfo SubXZMatrixAsReadOnlyVolumeWindow(long y, long sizey)\n        {\n            return new VolumeInfo(Index(FX, y, FZ), new V3l(SX, sizey, SZ), D.XOZ) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly MatrixInfo SubXYMatrix(long z)\n        {\n            return new MatrixInfo(Index(FX, FY, z), S.XY, D.XY);\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubXYMatrixAsReadOnlyVolume(long z, long sizez)\n        {\n            return new VolumeInfo(Index(FX, FY, z), new V3l(SX, SY, sizez), D.XYO);\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly MatrixInfo SubXYMatrixWindow(long z)\n        {\n            return new MatrixInfo(Index(FX, FY, z), S.XY, D.XY) { F = F.XY };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly VolumeInfo SubXYMatrixAsReadOnlyVolumeWindow(long z, long sizez)\n        {\n            return new VolumeInfo(Index(FX, FY, z), new V3l(SX, SY, sizez), D.XYO) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubZVectorAsReadOnlyVolume(long x, long y, long sizex, long sizey)\n        {\n            return new VolumeInfo(Index(x, y, FZ), new V3l(sizex, sizey, SZ), D.OOZ);\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly VolumeInfo SubZVectorAsReadOnlyVolumeWindow(long x, long y, long sizex, long sizey)\n        {\n            return new VolumeInfo(Index(x, y, FZ), new V3l(sizex, sizey, SZ), D.OOZ) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubYVectorAsReadOnlyVolume(long x, long z, long sizex, long sizez)\n        {\n            return new VolumeInfo(Index(x, FY, z), new V3l(sizex, SY, sizez), D.OYO);\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly VolumeInfo SubYVectorAsReadOnlyVolumeWindow(long x, long z, long sizex, long sizez)\n        {\n            return new VolumeInfo(Index(x, FY, z), new V3l(sizex, SY, sizez), D.OYO) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubXVectorAsReadOnlyVolume(long y, long z, long sizey, long sizez)\n        {\n            return new VolumeInfo(Index(FX, y, z), new V3l(SX, sizey, sizez), D.XOO);\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly VolumeInfo SubXVectorAsReadOnlyVolumeWindow(long y, long z, long sizey, long sizez)\n        {\n            return new VolumeInfo(Index(FX, y, z), new V3l(SX, sizey, sizez), D.XOO) { F = F };\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    i_action(i);\n                } } }\n            }\n            else if (DZ == 1)\n            {\n                long ys = DSY, yj = JYX;\n                long xs = DSX, xj = JXZ;\n                long zs = SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    i_action(i);\n                } } }\n            }\n            else\n            {\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    i_action(i);\n                } } }\n            }\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long, long> x_y_z_i_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    x_y_z_i_action(x, y, z, i);\n                } } }\n            }\n            else if (DZ == 1)\n            {\n                long ys = DSY, yj = JYX;\n                long xs = DSX, xj = JXZ;\n                long zs = SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    x_y_z_i_action(x, y, z, i);\n                } } }\n            }\n            else\n            {\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    x_y_z_i_action(x, y, z, i);\n                } } }\n            }\n        }\n\n        public readonly void ForeachCoord(Action<V3l> v_action)\n        {\n            long i = FirstIndex; V3l v;\n            if (DX == 1)\n            {\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    v_action(v);\n                } } }\n            }\n            else if (DZ == 1)\n            {\n                long ys = DSY, yj = JYX;\n                long xs = DSX, xj = JXZ;\n                long zs = SZ;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i++, v.Z++) {\n                    v_action(v);\n                } } }\n            }\n            else\n            {\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    v_action(v);\n                } } }\n            }\n        }\n\n        public readonly void ForeachIndex(VolumeInfo t1, Action<long, long> i_i1_act)\n        {\n            CheckMatchingSize(t1);\n            if (HasMatchingLayout(t1))\n            {\n                long i = FirstIndex;\n                if (DX == 1)\n                {\n                    long zs = DSZ, zj = JZ;\n                    long ys = DSY, yj = JY;\n                    long xs = SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        i_i1_act(i, i);\n                    } } }\n                }\n                else if (DZ == 1)\n                {\n                    long ys = DSY, yj = JYX;\n                    long xs = DSX, xj = JXZ;\n                    long zs = SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        i_i1_act(i, i);\n                    } } }\n                }\n                else\n                {\n                    long zs = DSZ, zj = JZ;\n                    long ys = DSY, yj = JY;\n                    long xs = DSX, xj = JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        i_i1_act(i, i);\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (DX == 1 && t1.DX == 1)\n                {\n                    long zs = DSZ, zj = JZ, zj1 = t1.JZ;\n                    long ys = DSY, yj = JY, yj1 = t1.JY;\n                    long xs = SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        i_i1_act(i, i1);\n                    } } }\n                }\n                else if (DZ == 1 && t1.DZ == 1)\n                {\n                    long ys = DSY, yj = JYX, yj1 = t1.JYX;\n                    long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n                    long zs = SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        i_i1_act(i, i1);\n                    } } }\n                }\n                else\n                {\n                    long zs = DSZ, zj = JZ, zj1 = t1.JZ;\n                    long ys = DSY, yj = JY, yj1 = t1.JY;\n                    long xs = DSX, xj = JX, xj1 = t1.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        i_i1_act(i, i1);\n                    } } }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0, x = FX; i != xe; i += xj, x++)\n                x_elementAct(x);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0, y = FY; i != ye; i += yj, y++)\n                y_elementAct(y);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZ(\n                Action<long> z_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0, z = FZ; i != ze; i += zj, z++)\n                z_elementAct(z);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_elementAct(x, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_elementAct(x, z);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_elementAct(x, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_elementAct(x, z);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_elementAct(y, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_elementAct(y, z);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_elementAct(y, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_elementAct(y, z);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_elementAct(z, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_elementAct(z, x);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_elementAct(z, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_elementAct(z, x);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_elementAct(z, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_elementAct(z, y);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_elementAct(z, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_elementAct(z, y);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_elementAct(x, y, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_elementAct(x, y, z);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_elementAct(x, y, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_elementAct(x, y, z);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_elementAct(x, z, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_elementAct(x, z, y);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_elementAct(x, z, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_elementAct(x, z, y);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_elementAct(y, x, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_elementAct(y, x, z);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_elementAct(y, x, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_elementAct(y, x, z);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_elementAct(y, z, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_elementAct(y, z, x);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_elementAct(y, z, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_elementAct(y, z, x);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_elementAct(z, x, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_elementAct(z, x, y);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_elementAct(z, x, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_elementAct(z, x, y);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_elementAct(z, y, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_elementAct(z, y, x);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_elementAct(z, y, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_elementAct(z, y, x);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0, x = FX; i != xe; i += xj, x++)\n                x_i_elementAct(x, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0, y = FY; i != ye; i += yj, y++)\n                y_i_elementAct(y, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long, long> z_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0, z = FZ; i != ze; i += zj, z++)\n                z_i_elementAct(z, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_i_elementAct(x, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_i_elementAct(x, z, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_i_elementAct(x, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_i_elementAct(x, z, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_i_elementAct(y, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_i_elementAct(y, z, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_i_elementAct(y, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_i_elementAct(y, z, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_i_elementAct(z, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_i_elementAct(z, x, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_i_elementAct(z, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_i_elementAct(z, x, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_i_elementAct(z, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_i_elementAct(z, y, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_i_elementAct(z, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_i_elementAct(z, y, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_i_elementAct(x, y, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_i_elementAct(x, y, z, i);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_i_elementAct(x, y, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_i_elementAct(x, y, z, i);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_i_elementAct(x, z, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_i_elementAct(x, z, y, i);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_i_elementAct(x, z, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_i_elementAct(x, z, y, i);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_i_elementAct(y, x, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_i_elementAct(y, x, z, i);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_i_elementAct(y, x, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_i_elementAct(y, x, z, i);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_i_elementAct(y, z, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_i_elementAct(y, z, x, i);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_i_elementAct(y, z, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_i_elementAct(y, z, x, i);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_i_elementAct(z, x, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_i_elementAct(z, x, y, i);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_i_elementAct(z, x, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_i_elementAct(z, x, y, i);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_i_elementAct(z, y, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_i_elementAct(z, y, x, i);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_i_elementAct(z, y, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_i_elementAct(z, y, x, i);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + DSX, xj = JX0, xj1 = t1.JX0; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(VolumeInfo t1, \n                Action<long, long, long> x_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + DSX, xj = JX0, xj1 = t1.JX0, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                x_i_i1_elementAct(x, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + DSY, yj = JY0, yj1 = t1.JY0; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(VolumeInfo t1, \n                Action<long, long, long> y_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + DSY, yj = JY0, yj1 = t1.JY0, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                y_i_i1_elementAct(y, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0, zj1 = t1.JZ0; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(VolumeInfo t1, \n                Action<long, long, long> z_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0, zj1 = t1.JZ0, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                z_i_i1_elementAct(z, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(VolumeInfo t1, \n                Action<long, long, long, long> x_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(VolumeInfo t1, \n                Action<long, long, long, long> x_y_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(VolumeInfo t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(VolumeInfo t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_y_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(VolumeInfo t1, \n                Action<long, long, long, long> x_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_z_i_i1_elementAct(x, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(VolumeInfo t1, \n                Action<long, long, long, long> x_z_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_z_i_i1_elementAct(x, z, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(VolumeInfo t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_z_i_i1_elementAct(x, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(VolumeInfo t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_z_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_z_i_i1_elementAct(x, z, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(VolumeInfo t1, \n                Action<long, long, long, long> y_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(VolumeInfo t1, \n                Action<long, long, long, long> y_x_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(VolumeInfo t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(VolumeInfo t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_x_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(VolumeInfo t1, \n                Action<long, long, long, long> y_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_z_i_i1_elementAct(y, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(VolumeInfo t1, \n                Action<long, long, long, long> y_z_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_z_i_i1_elementAct(y, z, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(VolumeInfo t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_z_i_i1_elementAct(y, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(VolumeInfo t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_z_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_z_i_i1_elementAct(y, z, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(VolumeInfo t1, \n                Action<long, long, long, long> z_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_x_i_i1_elementAct(z, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(VolumeInfo t1, \n                Action<long, long, long, long> z_x_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_x_i_i1_elementAct(z, x, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(VolumeInfo t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_x_i_i1_elementAct(z, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(VolumeInfo t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_x_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_x_i_i1_elementAct(z, x, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(VolumeInfo t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(VolumeInfo t1, \n                Action<long, long, long, long> z_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_y_i_i1_elementAct(z, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(VolumeInfo t1, \n                Action<long, long, long, long> z_y_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_y_i_i1_elementAct(z, y, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(VolumeInfo t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_y_i_i1_elementAct(z, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(VolumeInfo t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_y_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_y_i_i1_elementAct(z, y, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> x_y_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_z_i_i1_elementAct(x, y, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> x_y_z_i_i1_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_z_i_i1_elementAct(x, y, z, i, i1);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(VolumeInfo t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long, long> x_y_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_z_i_i1_elementAct(x, y, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(VolumeInfo t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long, long> x_y_z_i_i1_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_z_i_i1_elementAct(x, y, z, i, i1);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> x_z_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_y_i_i1_elementAct(x, z, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> x_z_y_i_i1_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_y_i_i1_elementAct(x, z, y, i, i1);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(VolumeInfo t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long, long> x_z_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_y_i_i1_elementAct(x, z, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(VolumeInfo t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long, long> x_z_y_i_i1_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_y_i_i1_elementAct(x, z, y, i, i1);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> y_x_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_z_i_i1_elementAct(y, x, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> y_x_z_i_i1_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_z_i_i1_elementAct(y, x, z, i, i1);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(VolumeInfo t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long, long> y_x_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_z_i_i1_elementAct(y, x, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(VolumeInfo t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long, long> y_x_z_i_i1_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_z_i_i1_elementAct(y, x, z, i, i1);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> y_z_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_x_i_i1_elementAct(y, z, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> y_z_x_i_i1_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_x_i_i1_elementAct(y, z, x, i, i1);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(VolumeInfo t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long, long> y_z_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_x_i_i1_elementAct(y, z, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(VolumeInfo t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long, long> y_z_x_i_i1_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_x_i_i1_elementAct(y, z, x, i, i1);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> z_x_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_y_i_i1_elementAct(z, x, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> z_x_y_i_i1_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_y_i_i1_elementAct(z, x, y, i, i1);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(VolumeInfo t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long, long> z_x_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_y_i_i1_elementAct(z, x, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(VolumeInfo t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long, long> z_x_y_i_i1_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_y_i_i1_elementAct(z, x, y, i, i1);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(VolumeInfo t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(VolumeInfo t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> z_y_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_x_i_i1_elementAct(z, y, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(VolumeInfo t1, \n                Action<long, long, long, long, long> z_y_x_i_i1_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_x_i_i1_elementAct(z, y, x, i, i1);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(VolumeInfo t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long, long> z_y_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_x_i_i1_elementAct(z, y, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(VolumeInfo t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long, long> z_y_x_i_i1_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_x_i_i1_elementAct(z, y, x, i, i1);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        #endregion\n\n        #region Checking\n\n        public readonly void CheckMatchingSize(VolumeInfo t1)\n        {\n            if (Size != t1.Size) throw new ArgumentException(\"size mismatch\");\n        }\n\n        public readonly void CheckMatchingSize(VolumeInfo t1, VolumeInfo t2)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2);\n        }\n\n        public readonly void CheckMatchingSize(VolumeInfo t1, VolumeInfo t2, VolumeInfo t3)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2); CheckMatchingSize(t3);\n        }\n\n        public readonly bool HasMatchingLayout(VolumeInfo t1)\n        {\n            return First == t1.First && Origin == t1.Origin && Delta == t1.Delta;\n        }\n\n        public readonly bool HasMatchingLayout(VolumeInfo t1, VolumeInfo t2)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2);\n        }\n\n        public readonly bool HasMatchingLayout(VolumeInfo t1, VolumeInfo t2, VolumeInfo t3)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2) && HasMatchingLayout(t3);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Volume<Td>\n\n    /// <summary>\n    /// Generic volume of elements with arbitrary stride.\n    /// All sizes are given as 3-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The volume does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on volumes are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// 3 stride direction(s) are called DX, DY, aso.\n    /// </summary>\n    /// <typeparam name=\"Td\">data element type</typeparam>\n    [Serializable]\n    public partial struct Volume<Td> : IValidity, IVolume<Td>, IArrayVolume\n    {\n        public Td[] Data;\n        public VolumeInfo Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public Volume(Td[] data, VolumeInfo info)\n        {\n            Data = data;\n            Info = info;\n        }\n\n        /// <summary>\n        /// Construct volume of specified size.\n        /// </summary>\n        public Volume(V3l size)\n            : this(new Td[size.X * size.Y * size.Z], new VolumeInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct volume of specified size.\n        /// </summary>\n        public Volume(V3i size)\n            : this((V3l)size)\n        { }\n\n        /// <summary>\n        /// Construct volume with specified info.\n        /// </summary>\n        public Volume(VolumeInfo info)\n            : this(new Td[info.Count], new VolumeInfo(info))\n        { }\n\n        /// <summary>\n        /// Construct volume of specified size.\n        /// </summary>\n        public Volume(long sx, long sy, long sz)\n            : this(new V3l(sx, sy, sz))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Volume(Td[] data, long sx, long sy, long sz)\n            : this(data, new VolumeInfo(sx, sy, sz))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and sets all elements to the supplied value.\n        /// </summary>\n        public Volume(long sx, long sy, long sz, Td value)\n            : this(new V3l(sx, sy, sz), value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Volume(Td[] data, V3l size)\n            : this(data, new VolumeInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Volume(Td[] data, V3i size)\n            : this(data, new VolumeInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct volume of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Volume(V3l size, Td value)\n            : this(new Td[size.X * size.Y * size.Z], new VolumeInfo(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Volume(V3i size, Td value)\n            : this((V3l)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Volume(Td[] data, long origin, V3l size, V3l delta)\n            : this(data, new VolumeInfo(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Volume(Td[] data, long origin, V3l size, V3l delta, V3l first)\n            : this(data, new VolumeInfo(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public Volume(long origin, V3l size, V3l delta)\n            : this(new Td[size.X * size.Y * size.Z],\n                   new VolumeInfo(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the volume (3).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public V3l Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public V3l Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public V3l First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        /// <summary>\n        /// Returns true if the volume has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the volume does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly V3l End { get { return Info.E; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOO { get { return Info.OOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOO { get { return Info.IOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIO { get { return Info.OIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIO { get { return Info.IIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOI { get { return Info.OOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOI { get { return Info.IOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OII { get { return Info.OII; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l III { get { return Info.III; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l E { get { return Info.E; } }\n\n        /// <summary>\n        /// Size in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Info.SX; } set { Info.SX = value; } }\n\n        /// <summary>\n        /// Size in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Info.SY; } set { Info.SY = value; } }\n\n        /// <summary>\n        /// Size in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SZ { readonly get { return Info.SZ; } set { Info.SZ = value; } }\n\n        /// <summary>\n        /// Delta in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Info.DX; } set { Info.DX = value; } }\n\n        /// <summary>\n        /// Delta in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Info.DY; } set { Info.DY = value; } }\n\n        /// <summary>\n        /// Delta in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DZ { readonly get { return Info.DZ; } set { Info.DZ = value; } }\n\n        /// <summary>\n        /// First in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return Info.FX; } set { Info.FX = value; } }\n\n        /// <summary>\n        /// First in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY { readonly get { return Info.FY; } set { Info.FY = value; } }\n\n        /// <summary>\n        /// First in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FZ { readonly get { return Info.FZ; } set { Info.FZ = value; } }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return Info.EX; } }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY { get { return Info.EY; } }\n\n        /// <summary>\n        /// End in dimension Z (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EZ { get { return Info.EZ; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Info.JX; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Info.JY; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZ { get { return Info.JZ; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Info.DSX; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Info.DSY; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSZ { get { return Info.DSZ; } }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<Td> Elements\n        {\n            get\n            {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    yield return Data[i];\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    yield return Data[i];\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    yield return Data[i];\n                } } }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(Td[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (Td[])value; }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Td this[V3l v]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + v.X * Info.Delta.X + v.Y * Info.Delta.Y + v.Z * Info.Delta.Z];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + v.X * Info.Delta.X + v.Y * Info.Delta.Y + v.Z * Info.Delta.Z] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Td this[V3i v]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y + (long)v.Z * Info.Delta.Z];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y + (long)v.Z * Info.Delta.Z] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at the specified index in the underlying data array.\n        /// </summary>\n        public readonly Td this[long index]\n        {\n            get\n            {\n                return Data[index];\n            }\n            set\n            {\n                Data[index] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Td this[long x, long y, long z]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + x * Info.Delta.X + y * Info.Delta.Y + z * Info.Delta.Z];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + x * Info.Delta.X + y * Info.Delta.Y + z * Info.Delta.Z] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Td this[int x, int y, int z]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + (long)x * Info.Delta.X + (long)y * Info.Delta.Y + (long)z * Info.Delta.Z];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + (long)x * Info.Delta.X + (long)y * Info.Delta.Y + (long)z * Info.Delta.Z] = value;\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long, long> x_y_z_i_action)\n        {\n            Info.ForeachIndex(x_y_z_i_action);\n        }\n\n        public readonly void ForeachCoord(Action<V3l> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(VolumeInfo t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            Info.ForeachX(x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            Info.ForeachY(y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZ(\n                Action<long> z_elementAct)\n        {\n            Info.ForeachZ(z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct)\n        {\n            Info.ForeachXZ(\n                    x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZ(\n                    x_z_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct)\n        {\n            Info.ForeachXZ(\n                    x_preLineAct,\n                    x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZ(\n                    x_preLineAct,\n                    x_z_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct)\n        {\n            Info.ForeachYZ(\n                    y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZ(\n                    y_z_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct)\n        {\n            Info.ForeachYZ(\n                    y_preLineAct,\n                    y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZ(\n                    y_preLineAct,\n                    y_z_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct)\n        {\n            Info.ForeachZX(\n                    z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZX(\n                    z_x_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct)\n        {\n            Info.ForeachZX(\n                    z_preLineAct,\n                    z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZX(\n                    z_preLineAct,\n                    z_x_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct)\n        {\n            Info.ForeachZY(\n                    z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZY(\n                    z_y_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct)\n        {\n            Info.ForeachZY(\n                    z_preLineAct,\n                    z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZY(\n                    z_preLineAct,\n                    z_y_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            Info.ForeachXIndex(x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            Info.ForeachYIndex(y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long, long> z_i_elementAct)\n        {\n            Info.ForeachZIndex(z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    x_z_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    x_preLineAct,\n                    x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    x_preLineAct,\n                    x_z_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    y_z_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    y_preLineAct,\n                    y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    y_preLineAct,\n                    y_z_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    z_x_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    z_preLineAct,\n                    z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    z_preLineAct,\n                    z_x_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    z_y_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    z_preLineAct,\n                    z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    z_preLineAct,\n                    z_y_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            Info.ForeachXYZ(\n                    x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZ(\n                    x_y_z_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            Info.ForeachXYZ(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZ(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            Info.ForeachXZY(\n                    x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZY(\n                    x_z_y_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            Info.ForeachXZY(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZY(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            Info.ForeachYXZ(\n                    y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZ(\n                    y_x_z_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            Info.ForeachYXZ(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZ(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            Info.ForeachYZX(\n                    y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZX(\n                    y_z_x_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            Info.ForeachYZX(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZX(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            Info.ForeachZXY(\n                    z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXY(\n                    z_x_y_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            Info.ForeachZXY(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXY(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            Info.ForeachZYX(\n                    z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYX(\n                    z_y_x_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            Info.ForeachZYX(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYX(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_y_z_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_z_y_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_x_z_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_z_x_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_x_y_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_y_x_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td> SubVolumeWindow(V3l begin, V3l size)\n        {\n            return new Volume<Td>(Data, Info.SubVolumeWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubVolume(V3l begin, V3l size)\n        {\n            return new Volume<Td>(Data, Info.SubVolume(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td> SubVolumeWindow(V3i begin, V3i size)\n        {\n            return new Volume<Td>(Data, Info.SubVolumeWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubVolume(V3i begin, V3i size)\n        {\n            return new Volume<Td>(Data, Info.SubVolume(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td> SubVolumeWindow(V3l begin, V3l size, V3l delta)\n        {\n            return new Volume<Td>(Data, Info.SubVolumeWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubVolume(V3l begin, V3l size, V3l delta)\n        {\n            return new Volume<Td>(Data, Info.SubVolume(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td> SubVolumeWindow(V3i begin, V3i size, V3i delta)\n        {\n            return new Volume<Td>(Data, Info.SubVolumeWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubVolume(V3i begin, V3i size, V3i delta)\n        {\n            return new Volume<Td>(Data, Info.SubVolume(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<Td> SubVolumeWindow(V3l begin, V3l size, V3l delta, V3l first)\n        {\n            return new Volume<Td>(Data, Info.SubVolumeWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<Td> SubVolumeWindow(V3i begin, V3i size, V3i delta, V3i first)\n        {\n            return new Volume<Td>(Data, Info.SubVolumeWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td> SubVolumeWindow(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new Volume<Td>(Data,\n                            Info.SubVolumeWindow(beginX, beginY, beginZ,\n                                           sizeX, sizeY, sizeZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubVolume(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new Volume<Td>(Data,\n                            Info.SubVolume(beginX, beginY, beginZ,\n                                               sizeX, sizeY, sizeZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td> SubVolumeWindow(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new Volume<Td>(Data,\n                            Info.SubVolumeWindow(beginX, beginY, beginZ,\n                                           sizeX, sizeY, sizeZ,\n                                           deltaX, deltaY, deltaZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubVolume(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new Volume<Td>(Data,\n                            Info.SubVolume(beginX, beginY, beginZ,\n                                               sizeX, sizeY, sizeZ,\n                                               deltaX, deltaY, deltaZ));\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td> AsVector()\n        {\n            return new Vector<Td>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td> SubVector(V3l origin, long size, long delta)\n        {\n            return new Vector<Td>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td> SubVector(V3i origin, long size, long delta)\n        {\n            return new Vector<Td>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// If the lines of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly Matrix<Td> AsMatrixXYxZ()\n        {\n            return new Matrix<Td>(Data, Info.AsMatrixXYxZ());\n        }\n\n        /// <summary>\n        /// If the planes of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly Matrix<Td> AsMatrixXxYZ()\n        {\n            return new Matrix<Td>(Data, Info.AsMatrixXxYZ());\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(V3l origin, V2l size, V2l delta)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrix(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(V3i origin, V2i size, V2l delta)\n        {\n            return new Matrix<Td>(Data, Info.SubMatrix(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td> SubMatrix(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long deltaX, long deltaY)\n        {\n            return new Matrix<Td>(Data,\n                    Info.SubMatrix(beginX, beginY, beginZ,\n                                         sizeX, sizeY, deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubYZMatrix(long x)\n        {\n            return new Matrix<Td>(Data, Info.SubYZMatrix(x));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubYZMatrixAsReadOnlyVolume(long x, long sizex)\n        {\n            return new Volume<Td>(Data, Info.SubYZMatrixAsReadOnlyVolume(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td> SubYZMatrixWindow(long x)\n        {\n            return new Matrix<Td>(Data, Info.SubYZMatrixWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td> SubYZMatrixAsReadOnlyVolumeWindow(long x, long sizex)\n        {\n            return new Volume<Td>(Data, Info.SubYZMatrixAsReadOnlyVolumeWindow(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubXZMatrix(long y)\n        {\n            return new Matrix<Td>(Data, Info.SubXZMatrix(y));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubXZMatrixAsReadOnlyVolume(long y, long sizey)\n        {\n            return new Volume<Td>(Data, Info.SubXZMatrixAsReadOnlyVolume(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td> SubXZMatrixWindow(long y)\n        {\n            return new Matrix<Td>(Data, Info.SubXZMatrixWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td> SubXZMatrixAsReadOnlyVolumeWindow(long y, long sizey)\n        {\n            return new Volume<Td>(Data, Info.SubXZMatrixAsReadOnlyVolumeWindow(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td> SubXYMatrix(long z)\n        {\n            return new Matrix<Td>(Data, Info.SubXYMatrix(z));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubXYMatrixAsReadOnlyVolume(long z, long sizez)\n        {\n            return new Volume<Td>(Data, Info.SubXYMatrixAsReadOnlyVolume(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td> SubXYMatrixWindow(long z)\n        {\n            return new Matrix<Td>(Data, Info.SubXYMatrixWindow(z));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td> SubXYMatrixAsReadOnlyVolumeWindow(long z, long sizez)\n        {\n            return new Volume<Td>(Data, Info.SubXYMatrixAsReadOnlyVolumeWindow(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubZVectorAsReadOnlyVolume(long x, long y, long sizex, long sizey)\n        {\n            return new Volume<Td>(Data, Info.SubZVectorAsReadOnlyVolume(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td> SubZVectorAsReadOnlyVolumeWindow(long x, long y, long sizex, long sizey)\n        {\n            return new Volume<Td>(Data, Info.SubZVectorAsReadOnlyVolumeWindow(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubYVectorAsReadOnlyVolume(long x, long z, long sizex, long sizez)\n        {\n            return new Volume<Td>(Data, Info.SubYVectorAsReadOnlyVolume(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td> SubYVectorAsReadOnlyVolumeWindow(long x, long z, long sizex, long sizez)\n        {\n            return new Volume<Td>(Data, Info.SubYVectorAsReadOnlyVolumeWindow(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubXVectorAsReadOnlyVolume(long y, long z, long sizey, long sizez)\n        {\n            return new Volume<Td>(Data, Info.SubXVectorAsReadOnlyVolume(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td> SubXVectorAsReadOnlyVolumeWindow(long y, long z, long sizey, long sizez)\n        {\n            return new Volume<Td>(Data, Info.SubXVectorAsReadOnlyVolumeWindow(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3l begin, V3l size)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(V3l begin, V3l size)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolume(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3i begin, V3i size)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(V3i begin, V3i size)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolume(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3l begin, V3l size, V3l delta)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(V3l begin, V3l size, V3l delta)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolume(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3i begin, V3i size, V3i delta)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(V3i begin, V3i size, V3i delta)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolume(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3l begin, V3l size, V3l delta, V3l first)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3i begin, V3i size, V3i delta, V3i first)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new Volume<Td, T1>(Data,\n                            Info.SubVolumeWindow(beginX, beginY, beginZ,\n                                           sizeX, sizeY, sizeZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new Volume<Td, T1>(Data,\n                            Info.SubVolume(beginX, beginY, beginZ,\n                                               sizeX, sizeY, sizeZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new Volume<Td, T1>(Data,\n                            Info.SubVolumeWindow(beginX, beginY, beginZ,\n                                           sizeX, sizeY, sizeZ,\n                                           deltaX, deltaY, deltaZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new Volume<Td, T1>(Data,\n                            Info.SubVolume(beginX, beginY, beginZ,\n                                               sizeX, sizeY, sizeZ,\n                                               deltaX, deltaY, deltaZ));\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, T1> AsVector<T1>()\n        {\n            return new Vector<Td, T1>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V3l origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V3i origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// If the lines of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> AsMatrixXYxZ<T1>()\n        {\n            return new Matrix<Td, T1>(Data, Info.AsMatrixXYxZ());\n        }\n\n        /// <summary>\n        /// If the planes of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> AsMatrixXxYZ<T1>()\n        {\n            return new Matrix<Td, T1>(Data, Info.AsMatrixXxYZ());\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V3l origin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V3i origin, V2i size, V2l delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long deltaX, long deltaY)\n        {\n            return new Matrix<Td, T1>(Data,\n                    Info.SubMatrix(beginX, beginY, beginZ,\n                                         sizeX, sizeY, deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubYZMatrix<T1>(long x)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubYZMatrix(x));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYZMatrixAsReadOnlyVolume<T1>(long x, long sizex)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYZMatrixAsReadOnlyVolume(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubYZMatrixWindow<T1>(long x)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubYZMatrixWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYZMatrixAsReadOnlyVolumeWindow<T1>(long x, long sizex)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYZMatrixAsReadOnlyVolumeWindow(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXZMatrix<T1>(long y)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXZMatrix(y));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXZMatrixAsReadOnlyVolume<T1>(long y, long sizey)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXZMatrixAsReadOnlyVolume(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXZMatrixWindow<T1>(long y)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXZMatrixWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXZMatrixAsReadOnlyVolumeWindow<T1>(long y, long sizey)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXZMatrixAsReadOnlyVolumeWindow(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXYMatrix<T1>(long z)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXYMatrix(z));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYMatrixAsReadOnlyVolume<T1>(long z, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYMatrixAsReadOnlyVolume(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXYMatrixWindow<T1>(long z)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXYMatrixWindow(z));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYMatrixAsReadOnlyVolumeWindow<T1>(long z, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYMatrixAsReadOnlyVolumeWindow(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubZVectorAsReadOnlyVolume<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Volume<Td, T1>(Data, Info.SubZVectorAsReadOnlyVolume(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubZVectorAsReadOnlyVolumeWindow<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Volume<Td, T1>(Data, Info.SubZVectorAsReadOnlyVolumeWindow(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYVectorAsReadOnlyVolume<T1>(long x, long z, long sizex, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYVectorAsReadOnlyVolume(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYVectorAsReadOnlyVolumeWindow<T1>(long x, long z, long sizex, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYVectorAsReadOnlyVolumeWindow(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXVectorAsReadOnlyVolume<T1>(long y, long z, long sizey, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXVectorAsReadOnlyVolume(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXVectorAsReadOnlyVolumeWindow<T1>(long y, long z, long sizey, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXVectorAsReadOnlyVolumeWindow(y, z, sizey, sizez));\n        }\n\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> Copy()\n        {\n            return new Volume<Td>(Info.S).Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original Volume.\n        /// </summary>\n        public readonly Volume<Td> CopyWindow()\n        {\n            return new Volume<Td>(Info.S)\n                    { F = F,  }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<T1> Map<T1>(Func<Td, T1> fun)\n        {\n            return new Volume<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original Volume.\n        /// </summary>\n        public readonly Volume<T1> MapWindow<T1>(Func<Td, T1> fun)\n        {\n            return new Volume<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Returns a tensor repeated in each dimension by the specified\n        /// count.\n        /// </summary>\n        public readonly Volume<Td> Repeated(V3l count)\n        {\n            var size = Size;\n            count *= size;\n            var t = new Volume<Td>(count);\n            V3l p;\n            for (p.Z = 0; p.Z < count.Z; p.Z += size.Z)\n            for (p.Y = 0; p.Y < count.Y; p.Y += size.Y)\n            for (p.X = 0; p.X < count.X; p.X += size.X)\n                t.SubVolume(p, size).Set(this);\n            return t;\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the volume.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> Apply(Func<Td, Td> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj)\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.SX; i != xe; i++)\n                    Data[i] = element_elementFun(Data[i]);\n            }\n            else\n            {\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj)\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj)\n                    Data[i] = element_elementFun(Data[i]);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original volume and the supplied volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> Apply<T1>(\n                Volume<T1> t1, Func<Td, T1, Td> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original volume and the supplied volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> Apply<T1d, T1>(\n                Volume<T1d, T1> t1, Func<Td, T1, Td> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the volume.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> ApplyByCoord(Func<Td, V3l, Td> element_crd_elementFun)\n        {\n            long i = FirstIndex; V3l vi;\n            if (Info.JX == 1)\n            {\n                vi.Z = First.Z;\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj, vi.Z++)\n                {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.SX; i != xe; i++, vi.X++)\n                    Data[i] = element_crd_elementFun(Data[i], vi);\n                }\n                }\n            }\n            else\n            {\n                vi.Z = First.Z;\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj, vi.Z++)\n                {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj, vi.X++)\n                {\n                    Data[i] = element_crd_elementFun(Data[i], vi);\n                }\n                }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> ApplyByCoord(Func<Td, long, long, long, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long ze = i + Info.DSZ, zj = Info.JZ, z = Info.FZ; i != ze; i += zj, z++)\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    Data[i] = fun(Data[i], x, y, z);\n            }\n            else\n            {\n                for (long ze = i + Info.DSZ, zj = Info.JZ, z = Info.FZ; i != ze; i += zj, z++)\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.DSX, xj = Info.JX, x = Info.FX; i != xe; i += xj, x++)\n                    Data[i] = fun(Data[i], x, y, z);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> Set(Td v)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Data[i] = v;\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    Data[i] = v;\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Data[i] = v;\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByCoord(Func<long, long, long, Td> x_y_z_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Data[i] = x_y_z_elementFun(x, y, z);\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    Data[i] = x_y_z_elementFun(x, y, z);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Data[i] = x_y_z_elementFun(x, y, z);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByCoord(Func<V3l, Td> crd_elementFun)\n        {\n            long i = FirstIndex; V3l v;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    Data[i] = crd_elementFun(v);\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i++, v.Z++) {\n                    Data[i] = crd_elementFun(v);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    Data[i] = crd_elementFun(v);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByCoord<Tz, Ty>(\n                Func<long, Tz> zFun,\n                Func<long, long, Tz, Ty> yFun,\n                Func<long, long, long, Tz, Ty, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = Info.FZ; i != ze; i += zj, z++) {\n                    var zVal = zFun(z);\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(z, y, zVal);\n                for (long xe = i + xs, x = Info.FX; i != xe; i++, x++) {\n                    Data[i] = fun(z, y, x, zVal, yVal);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = Info.FZ; i != ze; i += zj, z++) {\n                    var zVal = zFun(z);\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(z, y, zVal);\n                for (long xe = i + xs, x = Info.FX; i != xe; i += xj, x++) {\n                    Data[i] = fun(z, y, x, zVal, yVal);\n                } } }\n            }\n\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex(Func<long, Td> index_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Data[i] = index_elementFun(i);\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    Data[i] = index_elementFun(i);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Data[i] = index_elementFun(i);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly Volume<Td> Set(IVolume<Td> it1)\n        {\n            if (it1 is Volume<Td>) return Set((Volume<Td>)it1);\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Data[i] = it1[x, y, z];\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    Data[i] = it1[x, y, z];\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Data[i] = it1[x, y, z];\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> Set(Volume<Td> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = t1.Data[i];\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        Data[i] = t1.Data[i];\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = t1.Data[i];\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = t1.Data[i1];\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Data[i] = t1.Data[i1];\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = t1.Data[i1];\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// the elements of the supplied volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap<T1>(\n                Volume<T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1>(\n                Volume<T1> t1, Func<long, Td> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_elementFun(i);\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        Data[i] = index1_elementFun(i);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_elementFun(i);\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = index1_elementFun(i1);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> Set<T1>(Volume<T1, Td> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// the elements of the supplied volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap<T1d, T1>(\n                Volume<T1d, T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1d, T1>(\n                Volume<T1d, T1> t1, Func<long, Td> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = index1_elementFun(i1);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap2<T1, T2>(\n                    Volume<T1> t1, Volume<T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1, T2>(\n                Volume<T1> t1, Volume<T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap2<T1, T2d, T2>(\n                    Volume<T1> t1, Volume<T2d, T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1, T2d, T2>(\n                Volume<T1> t1, Volume<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap2<T1d, T1, T2>(\n                    Volume<T1d, T1> t1, Volume<T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1d, T1, T2>(\n                Volume<T1d, T1> t1, Volume<T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap2<T1d, T1, T2d, T2>(\n                    Volume<T1d, T1> t1, Volume<T2d, T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1d, T1, T2d, T2>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap3<T1, T2, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info, t3.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1, T2, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info, t3.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap3<T1, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap3<T1, T2d, T2, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1, T2d, T2, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap3<T1, T2d, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1, T2d, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap3<T1d, T1, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1d, T1, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap3<T1d, T1, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1d, T1, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap3<T1d, T1, T2d, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1d, T1, T2d, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetMap3<T1d, T1, T2d, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly Volume<Td> SetConvolution<Ti, Tf, Tm, Ts>(\n                Volume<Ti> image, Volume<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Td> castFun)\n        {\n            Info.CheckMatchingSize(new VolumeInfo(V3l.One + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.SubVolume(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetOuterProduct<Tx, Ty, Tz>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Data[i3]);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Data[i3]);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetOuterProduct<Tx, Ty, Tzd, Tz>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetOuterProduct<Tx, Tyd, Ty, Tz>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3]);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3]);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetOuterProduct<Txd, Tx, Ty, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3]);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3]);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetOuterProduct<Txd, Tx, Ty, Tzd, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetOuterProduct<Txd, Tx, Tyd, Ty, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3]);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3]);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td> SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3));\n                } } }\n            }\n            return this;\n        }\n\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Td, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, long, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z));\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, V3l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V3l v;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i++, v.Z++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Volume<T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Volume<T1d, T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Td, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, long, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, V3l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V3l v;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i++, v.Z++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Volume<T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else if (Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long ze = i + zs; i != ze; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Volume<T1d, T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creator Functions\n\n        /// <summary>\n        /// Create a new volume as copy of the supplied volume.\n        /// </summary>\n        public static Volume<Td> Create(\n                Volume<Td> t1)\n        {\n            return new Volume<Td>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new volume as copy of the supplied volume.\n        /// </summary>\n        public static Volume<Td> Create<T1d>(\n                Volume<T1d, Td> t1)\n        {\n            return new Volume<Td>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map<T1>(\n                Volume<T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1>(\n                Volume<T1> t1, Func<long, Td> index1_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map<T1d, T1>(\n                Volume<T1d, T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1d, T1>(\n                Volume<T1d, T1> t1, Func<long, Td> index1_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map2<T1, T2>(\n                Volume<T1> t1, Volume<T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1, T2>(\n                Volume<T1> t1, Volume<T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map2<T1, T2d, T2>(\n                Volume<T1> t1, Volume<T2d, T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1, T2d, T2>(\n                Volume<T1> t1, Volume<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map2<T1d, T1, T2>(\n                Volume<T1d, T1> t1, Volume<T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1d, T1, T2>(\n                Volume<T1d, T1> t1, Volume<T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map2<T1d, T1, T2d, T2>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1d, T1, T2d, T2>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map3<T1, T2, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1, T2, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map3<T1, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map3<T1, T2d, T2, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1, T2d, T2, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map3<T1, T2d, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1, T2d, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map3<T1d, T1, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1d, T1, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map3<T1d, T1, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1d, T1, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map3<T1d, T1, T2d, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1d, T1, T2d, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td> Map3<T1d, T1, T2d, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td> CreateByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to the coordinates of\n        /// the elements the newly created volume.\n        /// </summary>\n        public static Volume<Td> Create(V3l size, Func<V3l, Td> fun)\n        {\n            return new Volume<Td>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new Volume by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting Volume.\n        /// </summary>\n        public static Volume<Td> CreateConvolution<Ti, Tf, Tm, Ts>(\n                Volume<Ti> image, Volume<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Td> castFun)\n        {\n            V3l size = 1 + image.S - filter.S;\n            if (size.Z <= 0 ||size.Y <= 0 ||size.X <= 0) throw new Exception(\"filter to large\");\n            return new Volume<Td>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td> CreateOuterProduct<Tx, Ty, Tz>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            return new Volume<Td>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Tx, Ty, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td> CreateOuterProduct<Tx, Ty, Tzd, Tz>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            return new Volume<Td>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Tx, Ty, Tzd, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td> CreateOuterProduct<Tx, Tyd, Ty, Tz>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            return new Volume<Td>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td> CreateOuterProduct<Tx, Tyd, Ty, Tzd, Tz>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            return new Volume<Td>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td> CreateOuterProduct<Txd, Tx, Ty, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            return new Volume<Td>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td> CreateOuterProduct<Txd, Tx, Ty, Tzd, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            return new Volume<Td>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tzd, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            return new Volume<Td>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Td> fun)\n        {\n            return new Volume<Td>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz>(tx, ty, tz, fun);\n        }\n\n        #endregion\n\n        #region Sampling\n\n\n\n        public readonly TRes SampleRaw8<T1, T2, TRes>(\n                V3d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return SampleRaw8(v.X, v.Y, v.Z, xipl, yipl, zipl);\n        }\n\n        /// <summary>\n        /// Sample the volume using 8 samples and the supplied\n        /// interpolation functions. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the volume, i.e. voxel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw8<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            long i = Info.Origin + xi * Info.Delta.X + yi * Info.Delta.Y + zi * Info.Delta.Z;\n            long ix = i + dx; long iy = i + dy; long ixy = ix + dy;\n            return zipl(zf, yipl(yf, xipl(xf, Data[i], Data[ix]),\n                                     xipl(xf, Data[iy], Data[ixy])),\n                            yipl(yf, xipl(xf, Data[i + dz], Data[ix + dz]),\n                                     xipl(xf, Data[iy + dz], Data[ixy + dz])));\n        }\n\n        public readonly TRes Sample8Clamped<T1, T2, TRes>(\n                V3d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return Sample8(v.X, v.Y, v.Z, xipl, yipl, zipl,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample8Clamped<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return Sample8(x, y, z, xipl, yipl, zipl,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample8<T1, T2, TRes>(\n                V3d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun)\n        {\n            return Sample8(v.X, v.Y, v.Z, xipl, yipl, zipl,\n                           index_min_max_delta_xIndexFun,\n                           index_min_max_delta_yIndexFun,\n                           index_min_max_delta_zIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the volume using 8 samples and the supplied\n        /// interpolation functions. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the volume, i.e. voxel centers are assumed to be on\n        /// integer coordinates.\n        /// </summary>\n        public readonly TRes Sample8<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1); dx.E0 += i; dx.E1 += i;\n            var dyz = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                   index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1));\n            return zipl(zf, yipl(yf, xipl(xf, Data[dx.E0 + dyz.E0], Data[dx.E1 + dyz.E0]),\n                                     xipl(xf, Data[dx.E0 + dyz.E1], Data[dx.E1 + dyz.E1])),\n                            yipl(yf, xipl(xf, Data[dx.E0 + dyz.E2], Data[dx.E1 + dyz.E2]),\n                                     xipl(xf, Data[dx.E0 + dyz.E3], Data[dx.E1 + dyz.E3])));\n        }\n\n        public readonly TRes SampleRaw64<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return SampleRaw64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp);\n        }\n\n        public readonly TRes SampleRaw64<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            long i11 = Info.Origin + xi * dx + yi * dy + zi * dz;\n            long d2 = dx + dx;\n            long i10 = i11 - dy, i12 = i11 + dy, i13 = i12 + dy;\n            long i00 = i10 - dz, i01 = i11 - dz, i02 = i12 - dz, i03 = i13 - dz;\n            long i20 = i10 + dz, i21 = i11 + dz, i22 = i12 + dz, i23 = i13 + dz;\n            long i30 = i20 + dz, i31 = i21 + dz, i32 = i22 + dz, i33 = i23 + dz;\n            var wx = xipl(xf); var wy = yipl(yf); var wz = zipl(zf);\n            return zsmp(ysmp(xsmp(Data[i00 - dx], Data[i00], Data[i00 + dx], Data[i00 + d2], ref wx),\n                             xsmp(Data[i01 - dx], Data[i01], Data[i01 + dx], Data[i01 + d2], ref wx),\n                             xsmp(Data[i02 - dx], Data[i02], Data[i02 + dx], Data[i02 + d2], ref wx),\n                             xsmp(Data[i03 - dx], Data[i03], Data[i03 + dx], Data[i03 + d2], ref wx), ref wy),\n                        ysmp(xsmp(Data[i10 - dx], Data[i10], Data[i10 + dx], Data[i10 + d2], ref wx),\n                             xsmp(Data[i11 - dx], Data[i11], Data[i11 + dx], Data[i11 + d2], ref wx),\n                             xsmp(Data[i12 - dx], Data[i12], Data[i12 + dx], Data[i12 + d2], ref wx),\n                             xsmp(Data[i13 - dx], Data[i13], Data[i13 + dx], Data[i13 + d2], ref wx), ref wy),\n                        ysmp(xsmp(Data[i20 - dx], Data[i20], Data[i20 + dx], Data[i20 + d2], ref wx),\n                             xsmp(Data[i21 - dx], Data[i21], Data[i21 + dx], Data[i21 + d2], ref wx),\n                             xsmp(Data[i22 - dx], Data[i22], Data[i22 + dx], Data[i22 + d2], ref wx),\n                             xsmp(Data[i23 - dx], Data[i23], Data[i23 + dx], Data[i23 + d2], ref wx), ref wy),\n                        ysmp(xsmp(Data[i30 - dx], Data[i30], Data[i30 + dx], Data[i30 + d2], ref wx),\n                             xsmp(Data[i31 - dx], Data[i31], Data[i31 + dx], Data[i31 + d2], ref wx),\n                             xsmp(Data[i32 - dx], Data[i32], Data[i32 + dx], Data[i32 + d2], ref wx),\n                             xsmp(Data[i33 - dx], Data[i33], Data[i33 + dx], Data[i33 + d2], ref wx), ref wy), ref wz);\n        }\n\n        public readonly TRes Sample64Clamped<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return Sample64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample64Clamped<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return Sample64(x, y, z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample64<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_zIndexFun)\n        {\n            return Sample64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun,\n                            index_min_max_delta_zIndexFun);\n        }\n\n        public readonly TRes Sample64<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Td, Td, Td, Td, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_zIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i;\n            var dyz = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                   index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1));\n            var wx = xipl(xf); var wy = yipl(yf); var wz = zipl(zf);\n            return zsmp(ysmp(xsmp(Data[dx.E0 + dyz.E00], Data[dx.E1 + dyz.E00], Data[dx.E2 + dyz.E00], Data[dx.E3 + dyz.E00], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E01], Data[dx.E1 + dyz.E01], Data[dx.E2 + dyz.E01], Data[dx.E3 + dyz.E01], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E02], Data[dx.E1 + dyz.E02], Data[dx.E2 + dyz.E02], Data[dx.E3 + dyz.E02], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E03], Data[dx.E1 + dyz.E03], Data[dx.E2 + dyz.E03], Data[dx.E3 + dyz.E03], ref wx), ref wy),\n                        ysmp(xsmp(Data[dx.E0 + dyz.E04], Data[dx.E1 + dyz.E04], Data[dx.E2 + dyz.E04], Data[dx.E3 + dyz.E04], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E05], Data[dx.E1 + dyz.E05], Data[dx.E2 + dyz.E05], Data[dx.E3 + dyz.E05], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E06], Data[dx.E1 + dyz.E06], Data[dx.E2 + dyz.E06], Data[dx.E3 + dyz.E06], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E07], Data[dx.E1 + dyz.E07], Data[dx.E2 + dyz.E07], Data[dx.E3 + dyz.E07], ref wx), ref wy),\n                        ysmp(xsmp(Data[dx.E0 + dyz.E08], Data[dx.E1 + dyz.E08], Data[dx.E2 + dyz.E08], Data[dx.E3 + dyz.E08], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E09], Data[dx.E1 + dyz.E09], Data[dx.E2 + dyz.E09], Data[dx.E3 + dyz.E09], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E10], Data[dx.E1 + dyz.E10], Data[dx.E2 + dyz.E10], Data[dx.E3 + dyz.E10], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E11], Data[dx.E1 + dyz.E11], Data[dx.E2 + dyz.E11], Data[dx.E3 + dyz.E11], ref wx), ref wy),\n                        ysmp(xsmp(Data[dx.E0 + dyz.E12], Data[dx.E1 + dyz.E12], Data[dx.E2 + dyz.E12], Data[dx.E3 + dyz.E12], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E13], Data[dx.E1 + dyz.E13], Data[dx.E2 + dyz.E13], Data[dx.E3 + dyz.E13], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E14], Data[dx.E1 + dyz.E14], Data[dx.E2 + dyz.E14], Data[dx.E3 + dyz.E14], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E15], Data[dx.E1 + dyz.E15], Data[dx.E2 + dyz.E15], Data[dx.E3 + dyz.E15], ref wx), ref wy), ref wz);\n        }\n\n        #endregion\n\n        #region IVolume\n\n        /// <summary>\n        /// Dimension of the generic Volume.\n        /// </summary>\n        public readonly V3l Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(long x, long y, long z)\n        {\n            return (object)this[x, y, z];\n        }\n\n        public readonly void SetValue(object value, long x, long y, long z)\n        {\n            this[x, y, z] = (Td)value;\n        }\n\n        public readonly object GetValue(V3l v)\n        {\n            return (object)this[v];\n        }\n\n        public readonly void SetValue(object value, V3l v)\n        {\n            this[v] = (Td)value;\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    #region Volume<Td, Tv>\n\n    /// <summary>\n    /// Generic volume of elements with arbitrary stride.\n    /// All sizes are given as 3-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The volume does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on volumes are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// 3 stride direction(s) are called DX, DY, aso.\n    /// The volume has different view and data element types, i.e. although\n    /// all data is stored using the data element type, in its interfaces it\n    /// acts as a volume of view element types.\n    /// </summary>\n    /// <typeparam name=\"Td\">data element type</typeparam>\n    /// <typeparam name=\"Tv\">view element type</typeparam>\n    [Serializable]\n    public partial struct Volume<Td, Tv> : IValidity, IVolume<Tv>, IArrayVolume\n    {\n        public Td[] Data;\n        public Func<Td[], long, Tv> Getter;\n        public Action<Td[], long, Tv> Setter;\n        public VolumeInfo Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public Volume(Td[] data, VolumeInfo info)\n        {\n            Data = data;\n            Info = info;\n            Getter = null;\n            Setter = null;\n        }\n\n        /// <summary>\n        /// Construct volume of specified size.\n        /// </summary>\n        public Volume(V3l size)\n            : this(new Td[size.X * size.Y * size.Z], new VolumeInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct volume of specified size.\n        /// </summary>\n        public Volume(V3i size)\n            : this((V3l)size)\n        { }\n\n        /// <summary>\n        /// Construct volume with specified info.\n        /// </summary>\n        public Volume(VolumeInfo info)\n            : this(new Td[info.Count], new VolumeInfo(info))\n        { }\n\n        /// <summary>\n        /// Construct volume of specified size.\n        /// </summary>\n        public Volume(long sx, long sy, long sz)\n            : this(new V3l(sx, sy, sz))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Volume(Td[] data, long sx, long sy, long sz)\n            : this(data, new VolumeInfo(sx, sy, sz))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and sets all elements to the supplied value.\n        /// </summary>\n        public Volume(long sx, long sy, long sz, Tv value)\n            : this(new V3l(sx, sy, sz), value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Volume(Td[] data, V3l size)\n            : this(data, new VolumeInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Volume(Td[] data, V3i size)\n            : this(data, new VolumeInfo(size))\n        { }\n\n        /// <summary>\n        /// Construct volume of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Volume(V3l size, Tv value)\n            : this(new Td[size.X * size.Y * size.Z], new VolumeInfo(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Volume(V3i size, Tv value)\n            : this((V3l)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Volume(Td[] data, long origin, V3l size, V3l delta)\n            : this(data, new VolumeInfo(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Volume(Td[] data, long origin, V3l size, V3l delta, V3l first)\n            : this(data, new VolumeInfo(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public Volume(long origin, V3l size, V3l delta)\n            : this(new Td[size.X * size.Y * size.Z],\n                   new VolumeInfo(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the volume (3).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public V3l Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public V3l Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public V3l First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        public TensorAccessors<Td, Tv> Accessors\n        {\n            readonly get\n            {\n                return new TensorAccessors<Td, Tv>()\n                                { Getter = Getter, Setter = Setter };\n            }\n            set { Getter = value.Getter; Setter = value.Setter; }\n        }\n\n        /// <summary>\n        /// Returns true if the volume has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the volume does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly V3l End { get { return Info.E; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOO { get { return Info.OOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOO { get { return Info.IOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OIO { get { return Info.OIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IIO { get { return Info.IIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OOI { get { return Info.OOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l IOI { get { return Info.IOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l OII { get { return Info.OII; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l III { get { return Info.III; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V3l F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V3l E { get { return Info.E; } }\n\n        /// <summary>\n        /// Size in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Info.SX; } set { Info.SX = value; } }\n\n        /// <summary>\n        /// Size in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Info.SY; } set { Info.SY = value; } }\n\n        /// <summary>\n        /// Size in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SZ { readonly get { return Info.SZ; } set { Info.SZ = value; } }\n\n        /// <summary>\n        /// Delta in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Info.DX; } set { Info.DX = value; } }\n\n        /// <summary>\n        /// Delta in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Info.DY; } set { Info.DY = value; } }\n\n        /// <summary>\n        /// Delta in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DZ { readonly get { return Info.DZ; } set { Info.DZ = value; } }\n\n        /// <summary>\n        /// First in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return Info.FX; } set { Info.FX = value; } }\n\n        /// <summary>\n        /// First in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY { readonly get { return Info.FY; } set { Info.FY = value; } }\n\n        /// <summary>\n        /// First in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FZ { readonly get { return Info.FZ; } set { Info.FZ = value; } }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return Info.EX; } }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY { get { return Info.EY; } }\n\n        /// <summary>\n        /// End in dimension Z (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EZ { get { return Info.EZ; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Info.JX; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Info.JY; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZ { get { return Info.JZ; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Info.DSX; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Info.DSY; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSZ { get { return Info.DSZ; } }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<Tv> Elements\n        {\n            get\n            {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    yield return Getter(Data, i);\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    yield return Getter(Data, i);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    yield return Getter(Data, i);\n                } } }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(Td[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (Td[])value; }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Tv this[V3l v]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + v.X * Info.Delta.X + v.Y * Info.Delta.Y + v.Z * Info.Delta.Z);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + v.X * Info.Delta.X + v.Y * Info.Delta.Y + v.Z * Info.Delta.Z, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Tv this[V3i v]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y + (long)v.Z * Info.Delta.Z);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y + (long)v.Z * Info.Delta.Z, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at the specified index in the underlying data array.\n        /// </summary>\n        public readonly Tv this[long index]\n        {\n            get\n            {\n                return Getter(Data, index);\n            }\n            set\n            {\n                Setter(Data, index, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Tv this[long x, long y, long z]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + x * Info.Delta.X + y * Info.Delta.Y + z * Info.Delta.Z);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + x * Info.Delta.X + y * Info.Delta.Y + z * Info.Delta.Z, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Tv this[int x, int y, int z]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + (long)x * Info.Delta.X + (long)y * Info.Delta.Y + (long)z * Info.Delta.Z);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + (long)x * Info.Delta.X + (long)y * Info.Delta.Y + (long)z * Info.Delta.Z, value);\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long, long> x_y_z_i_action)\n        {\n            Info.ForeachIndex(x_y_z_i_action);\n        }\n\n        public readonly void ForeachCoord(Action<V3l> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(VolumeInfo t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            Info.ForeachX(x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            Info.ForeachY(y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZ(\n                Action<long> z_elementAct)\n        {\n            Info.ForeachZ(z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct)\n        {\n            Info.ForeachXZ(\n                    x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZ(\n                    x_z_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct)\n        {\n            Info.ForeachXZ(\n                    x_preLineAct,\n                    x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZ(\n                    x_preLineAct,\n                    x_z_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct)\n        {\n            Info.ForeachYZ(\n                    y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZ(\n                    y_z_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct)\n        {\n            Info.ForeachYZ(\n                    y_preLineAct,\n                    y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZ(\n                    y_preLineAct,\n                    y_z_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct)\n        {\n            Info.ForeachZX(\n                    z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZX(\n                    z_x_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct)\n        {\n            Info.ForeachZX(\n                    z_preLineAct,\n                    z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZX(\n                    z_preLineAct,\n                    z_x_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct)\n        {\n            Info.ForeachZY(\n                    z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZY(\n                    z_y_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct)\n        {\n            Info.ForeachZY(\n                    z_preLineAct,\n                    z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZY(\n                    z_preLineAct,\n                    z_y_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            Info.ForeachXIndex(x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            Info.ForeachYIndex(y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long, long> z_i_elementAct)\n        {\n            Info.ForeachZIndex(z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    x_z_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    x_preLineAct,\n                    x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    x_preLineAct,\n                    x_z_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    y_z_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    y_preLineAct,\n                    y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    y_preLineAct,\n                    y_z_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    z_x_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    z_preLineAct,\n                    z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    z_preLineAct,\n                    z_x_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    z_y_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    z_preLineAct,\n                    z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    z_preLineAct,\n                    z_y_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            Info.ForeachXYZ(\n                    x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZ(\n                    x_y_z_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            Info.ForeachXYZ(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZ(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            Info.ForeachXZY(\n                    x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZY(\n                    x_z_y_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            Info.ForeachXZY(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZY(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            Info.ForeachYXZ(\n                    y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZ(\n                    y_x_z_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            Info.ForeachYXZ(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZ(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            Info.ForeachYZX(\n                    y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZX(\n                    y_z_x_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            Info.ForeachYZX(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZX(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            Info.ForeachZXY(\n                    z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXY(\n                    z_x_y_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            Info.ForeachZXY(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXY(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            Info.ForeachZYX(\n                    z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYX(\n                    z_y_x_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            Info.ForeachZYX(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYX(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_y_z_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_z_y_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_x_z_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_z_x_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_x_y_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_y_x_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolumeWindow(V3l begin, V3l size)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolumeWindow(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolume(V3l begin, V3l size)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolume(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolumeWindow(V3i begin, V3i size)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolumeWindow(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolume(V3i begin, V3i size)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolume(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolumeWindow(V3l begin, V3l size, V3l delta)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolumeWindow(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolume(V3l begin, V3l size, V3l delta)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolume(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolumeWindow(V3i begin, V3i size, V3i delta)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolumeWindow(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolume(V3i begin, V3i size, V3i delta)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolume(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolumeWindow(V3l begin, V3l size, V3l delta, V3l first)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolumeWindow(begin, size, delta, first))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolumeWindow(V3i begin, V3i size, V3i delta, V3i first)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubVolumeWindow(begin, size, delta, first))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolumeWindow(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new Volume<Td, Tv>(Data,\n                            Info.SubVolumeWindow(beginX, beginY, beginZ,\n                                           sizeX, sizeY, sizeZ))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolume(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new Volume<Td, Tv>(Data,\n                            Info.SubVolume(beginX, beginY, beginZ,\n                                               sizeX, sizeY, sizeZ))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolumeWindow(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new Volume<Td, Tv>(Data,\n                            Info.SubVolumeWindow(beginX, beginY, beginZ,\n                                           sizeX, sizeY, sizeZ,\n                                           deltaX, deltaY, deltaZ))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubVolume(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new Volume<Td, Tv>(Data,\n                            Info.SubVolume(beginX, beginY, beginZ,\n                                               sizeX, sizeY, sizeZ,\n                                               deltaX, deltaY, deltaZ))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> AsVector()\n        {\n            return new Vector<Td, Tv>(Data, Info.AsVector())\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(V3l origin, long size, long delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(origin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(V3i origin, long size, long delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(origin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// If the lines of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> AsMatrixXYxZ()\n        {\n            return new Matrix<Td, Tv>(Data, Info.AsMatrixXYxZ())\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// If the planes of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly Matrix<Td, Tv> AsMatrixXxYZ()\n        {\n            return new Matrix<Td, Tv>(Data, Info.AsMatrixXxYZ())\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(V3l origin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrix(origin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(V3i origin, V2i size, V2l delta)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubMatrix(origin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubMatrix(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long deltaX, long deltaY)\n        {\n            return new Matrix<Td, Tv>(Data,\n                    Info.SubMatrix(beginX, beginY, beginZ,\n                                         sizeX, sizeY, deltaX, deltaY))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubYZMatrix(long x)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubYZMatrix(x))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubYZMatrixAsReadOnlyVolume(long x, long sizex)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubYZMatrixAsReadOnlyVolume(x, sizex))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubYZMatrixWindow(long x)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubYZMatrixWindow(x))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubYZMatrixAsReadOnlyVolumeWindow(long x, long sizex)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubYZMatrixAsReadOnlyVolumeWindow(x, sizex))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubXZMatrix(long y)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubXZMatrix(y))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXZMatrixAsReadOnlyVolume(long y, long sizey)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXZMatrixAsReadOnlyVolume(y, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubXZMatrixWindow(long y)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubXZMatrixWindow(y))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXZMatrixAsReadOnlyVolumeWindow(long y, long sizey)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXZMatrixAsReadOnlyVolumeWindow(y, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubXYMatrix(long z)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubXYMatrix(z))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXYMatrixAsReadOnlyVolume(long z, long sizez)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXYMatrixAsReadOnlyVolume(z, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, Tv> SubXYMatrixWindow(long z)\n        {\n            return new Matrix<Td, Tv>(Data, Info.SubXYMatrixWindow(z))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXYMatrixAsReadOnlyVolumeWindow(long z, long sizez)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXYMatrixAsReadOnlyVolumeWindow(z, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubZVectorAsReadOnlyVolume(long x, long y, long sizex, long sizey)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubZVectorAsReadOnlyVolume(x, y, sizex, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubZVectorAsReadOnlyVolumeWindow(long x, long y, long sizex, long sizey)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubZVectorAsReadOnlyVolumeWindow(x, y, sizex, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubYVectorAsReadOnlyVolume(long x, long z, long sizex, long sizez)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubYVectorAsReadOnlyVolume(x, z, sizex, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubYVectorAsReadOnlyVolumeWindow(long x, long z, long sizex, long sizez)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubYVectorAsReadOnlyVolumeWindow(x, z, sizex, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXVectorAsReadOnlyVolume(long y, long z, long sizey, long sizez)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXVectorAsReadOnlyVolume(y, z, sizey, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXVectorAsReadOnlyVolumeWindow(long y, long z, long sizey, long sizez)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXVectorAsReadOnlyVolumeWindow(y, z, sizey, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3l begin, V3l size)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(V3l begin, V3l size)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolume(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3i begin, V3i size)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(V3i begin, V3i size)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolume(begin, size));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3l begin, V3l size, V3l delta)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(V3l begin, V3l size, V3l delta)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolume(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3i begin, V3i size, V3i delta)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(V3i begin, V3i size, V3i delta)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolume(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3l begin, V3l size, V3l delta, V3l first)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(V3i begin, V3i size, V3i delta, V3i first)\n        {\n            return new Volume<Td, T1>(Data, Info.SubVolumeWindow(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new Volume<Td, T1>(Data,\n                            Info.SubVolumeWindow(beginX, beginY, beginZ,\n                                           sizeX, sizeY, sizeZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ)\n        {\n            return new Volume<Td, T1>(Data,\n                            Info.SubVolume(beginX, beginY, beginZ,\n                                               sizeX, sizeY, sizeZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolumeWindow<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new Volume<Td, T1>(Data,\n                            Info.SubVolumeWindow(beginX, beginY, beginZ,\n                                           sizeX, sizeY, sizeZ,\n                                           deltaX, deltaY, deltaZ));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubVolume<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long sizeZ,\n                long deltaX, long deltaY, long deltaZ)\n        {\n            return new Volume<Td, T1>(Data,\n                            Info.SubVolume(beginX, beginY, beginZ,\n                                               sizeX, sizeY, sizeZ,\n                                               deltaX, deltaY, deltaZ));\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, T1> AsVector<T1>()\n        {\n            return new Vector<Td, T1>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V3l origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V3i origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// If the lines of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> AsMatrixXYxZ<T1>()\n        {\n            return new Matrix<Td, T1>(Data, Info.AsMatrixXYxZ());\n        }\n\n        /// <summary>\n        /// If the planes of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly Matrix<Td, T1> AsMatrixXxYZ<T1>()\n        {\n            return new Matrix<Td, T1>(Data, Info.AsMatrixXxYZ());\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V3l origin, V2l size, V2l delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(V3i origin, V2i size, V2l delta)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubMatrix(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVolume does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubMatrix<T1>(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long deltaX, long deltaY)\n        {\n            return new Matrix<Td, T1>(Data,\n                    Info.SubMatrix(beginX, beginY, beginZ,\n                                         sizeX, sizeY, deltaX, deltaY));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubYZMatrix<T1>(long x)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubYZMatrix(x));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYZMatrixAsReadOnlyVolume<T1>(long x, long sizex)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYZMatrixAsReadOnlyVolume(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubYZMatrixWindow<T1>(long x)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubYZMatrixWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYZMatrixAsReadOnlyVolumeWindow<T1>(long x, long sizex)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYZMatrixAsReadOnlyVolumeWindow(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXZMatrix<T1>(long y)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXZMatrix(y));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXZMatrixAsReadOnlyVolume<T1>(long y, long sizey)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXZMatrixAsReadOnlyVolume(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXZMatrixWindow<T1>(long y)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXZMatrixWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXZMatrixAsReadOnlyVolumeWindow<T1>(long y, long sizey)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXZMatrixAsReadOnlyVolumeWindow(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXYMatrix<T1>(long z)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXYMatrix(z));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a matrix with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYMatrixAsReadOnlyVolume<T1>(long z, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYMatrixAsReadOnlyVolume(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Matrix<Td, T1> SubXYMatrixWindow<T1>(long z)\n        {\n            return new Matrix<Td, T1>(Data, Info.SubXYMatrixWindow(z));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the volume as a special volume\n        /// that replicates the matrix the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYMatrixAsReadOnlyVolumeWindow<T1>(long z, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYMatrixAsReadOnlyVolumeWindow(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubZVectorAsReadOnlyVolume<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Volume<Td, T1>(Data, Info.SubZVectorAsReadOnlyVolume(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full Z vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubZVectorAsReadOnlyVolumeWindow<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Volume<Td, T1>(Data, Info.SubZVectorAsReadOnlyVolumeWindow(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYVectorAsReadOnlyVolume<T1>(long x, long z, long sizex, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYVectorAsReadOnlyVolume(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full Y vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYVectorAsReadOnlyVolumeWindow<T1>(long x, long z, long sizex, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYVectorAsReadOnlyVolumeWindow(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXVectorAsReadOnlyVolume<T1>(long y, long z, long sizey, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXVectorAsReadOnlyVolume(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full X vector slice of the volume as a special volume\n        /// that replicates the vector the supplied number of times. The special\n        /// volume can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent volume.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXVectorAsReadOnlyVolumeWindow<T1>(long y, long z, long sizey, long sizez)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXVectorAsReadOnlyVolumeWindow(y, z, sizey, sizez));\n        }\n\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> Copy()\n        {\n            return new Volume<Td, Tv>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original Volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> CopyWindow()\n        {\n            return new Volume<Td, Tv>(Info.S)\n                    { F = F, Getter = Getter, Setter = Setter }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<T1> Map<T1>(Func<Tv, T1> fun)\n        {\n            return new Volume<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original Volume.\n        /// </summary>\n        public readonly Volume<T1> MapWindow<T1>(Func<Tv, T1> fun)\n        {\n            return new Volume<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        public readonly Volume<Tv> CopyView()\n        {\n            return new Volume<Tv>(Info.S).Set(this);\n        }\n\n        public readonly Volume<Tv> CopyViewWindow()\n        {\n            return new Volume<Tv>(Info.S) { F = F }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> Map(Func<Tv, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the complete layout of the original Volume.\n        /// </summary>\n        public readonly Volume<Td, Tv> MapWindow(Func<Tv, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new Td[Data.LongLength], Info)\n                        { F = F, Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the volume.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> Apply(Func<Tv, Tv> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj)\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.SX; i != xe; i++)\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n            }\n            else\n            {\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj)\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj)\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original volume and the supplied volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> Apply<T1>(\n                Volume<T1> t1, Func<Tv, T1, Tv> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original volume and the supplied volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> Apply<T1d, T1>(\n                Volume<T1d, T1> t1, Func<Tv, T1, Tv> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the volume.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> ApplyByCoord(Func<Tv, V3l, Tv> element_crd_elementFun)\n        {\n            long i = FirstIndex; V3l vi;\n            if (Info.JX == 1)\n            {\n                vi.Z = First.Z;\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj, vi.Z++)\n                {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.SX; i != xe; i++, vi.X++)\n                    Setter(Data, i, element_crd_elementFun(Getter(Data, i), vi));\n                }\n                }\n            }\n            else\n            {\n                vi.Z = First.Z;\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj, vi.Z++)\n                {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj, vi.X++)\n                {\n                    Setter(Data, i, element_crd_elementFun(Getter(Data, i), vi));\n                }\n                }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> ApplyByCoord(Func<Tv, long, long, long, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long ze = i + Info.DSZ, zj = Info.JZ, z = Info.FZ; i != ze; i += zj, z++)\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    Setter(Data, i, fun(Getter(Data, i), x, y, z));\n            }\n            else\n            {\n                for (long ze = i + Info.DSZ, zj = Info.JZ, z = Info.FZ; i != ze; i += zj, z++)\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.DSX, xj = Info.JX, x = Info.FX; i != xe; i += xj, x++)\n                    Setter(Data, i, fun(Getter(Data, i), x, y, z));\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> Set(Tv v)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Setter(Data, i, v);\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    Setter(Data, i, v);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Setter(Data, i, v);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByCoord(Func<long, long, long, Tv> x_y_z_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(Data, i, x_y_z_elementFun(x, y, z));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    Setter(Data, i, x_y_z_elementFun(x, y, z));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, x_y_z_elementFun(x, y, z));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByCoord(Func<V3l, Tv> crd_elementFun)\n        {\n            long i = FirstIndex; V3l v;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i++, v.Z++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByCoord<Tz, Ty>(\n                Func<long, Tz> zFun,\n                Func<long, long, Tz, Ty> yFun,\n                Func<long, long, long, Tz, Ty, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = Info.FZ; i != ze; i += zj, z++) {\n                    var zVal = zFun(z);\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(z, y, zVal);\n                for (long xe = i + xs, x = Info.FX; i != xe; i++, x++) {\n                    Setter(Data, i, fun(z, y, x, zVal, yVal));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = Info.FZ; i != ze; i += zj, z++) {\n                    var zVal = zFun(z);\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(z, y, zVal);\n                for (long xe = i + xs, x = Info.FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, fun(z, y, x, zVal, yVal));\n                } } }\n            }\n\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex(Func<long, Tv> index_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Setter(Data, i, index_elementFun(i));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    Setter(Data, i, index_elementFun(i));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Setter(Data, i, index_elementFun(i));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly Volume<Td, Tv> Set(IVolume<Tv> it1)\n        {\n            if (it1 is Volume<Tv>) return Set((Volume<Tv>)it1);\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(Data, i, it1[x, y, z]);\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    Setter(Data, i, it1[x, y, z]);\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, it1[x, y, z]);\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> Set(Volume<Tv> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// the elements of the supplied volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap<T1>(\n                Volume<T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1>(\n                Volume<T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> Set<T1>(Volume<T1, Tv> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// the elements of the supplied volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap<T1d, T1>(\n                Volume<T1d, T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1d, T1>(\n                Volume<T1d, T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap2<T1, T2>(\n                    Volume<T1> t1, Volume<T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1, T2>(\n                Volume<T1> t1, Volume<T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap2<T1, T2d, T2>(\n                    Volume<T1> t1, Volume<T2d, T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1, T2d, T2>(\n                Volume<T1> t1, Volume<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap2<T1d, T1, T2>(\n                    Volume<T1d, T1> t1, Volume<T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1d, T1, T2>(\n                Volume<T1d, T1> t1, Volume<T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a volume to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap2<T1d, T1, T2d, T2>(\n                    Volume<T1d, T1> t1, Volume<T2d, T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1d, T1, T2d, T2>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap3<T1, T2, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1, T2, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap3<T1, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap3<T1, T2d, T2, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1, T2d, T2, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap3<T1, T2d, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1, T2d, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap3<T1d, T1, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1d, T1, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap3<T1d, T1, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1d, T1, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap3<T1d, T1, T2d, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1d, T1, T2d, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetMap3<T1d, T1, T2d, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the\n        /// volume.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1 && t2.Info.DZ == 1 && t3.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ, xj2 = t2.Info.JXZ, xj3 = t3.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long ze = i + zs; i != ze; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly Volume<Td, Tv> SetConvolution<Ti, Tf, Tm, Ts>(\n                Volume<Ti> image, Volume<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Tv> castFun)\n        {\n            Info.CheckMatchingSize(new VolumeInfo(V3l.One + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.SubVolume(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetOuterProduct<Tx, Ty, Tz>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Data[i3]));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Data[i3]));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetOuterProduct<Tx, Ty, Tzd, Tz>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3)));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3)));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetOuterProduct<Tx, Tyd, Ty, Tz>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3]));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3]));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3)));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3)));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetOuterProduct<Txd, Tx, Ty, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3]));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3]));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetOuterProduct<Txd, Tx, Ty, Tzd, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3)));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3)));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetOuterProduct<Txd, Tx, Tyd, Ty, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3]));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3]));\n                } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Volume<Td, Tv> SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3)));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3)));\n                } } }\n            }\n            return this;\n        }\n\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Tv, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, long, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z));\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, V3l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V3l v;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i++, v.Z++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Volume<T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Volume<T1d, T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Tv, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long ze = i + zs; i != ze; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, long, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long ze = i + zs, z = FZ; i != ze; i++, z++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, V3l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V3l v;\n            if (Info.DX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else if (Info.DZ == 1)\n            {\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXZ;\n                long zs = Info.SZ;\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i++, v.Z++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Volume<T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Volume<T1d, T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else if (Info.DZ == 1 && t1.Info.DZ == 1)\n                {\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXZ, xj1 = t1.Info.JXZ;\n                    long zs = Info.SZ;\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long ze = i + zs; i != ze; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n                else\n                {\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } }\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creator Functions\n\n        /// <summary>\n        /// Create a new volume as copy of the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Create(\n                Volume<Tv> t1)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new volume as copy of the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Create<T1d>(\n                Volume<T1d, Tv> t1)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map<T1>(\n                Volume<T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1>(\n                Volume<T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map<T1d, T1>(\n                Volume<T1d, T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1d, T1>(\n                Volume<T1d, T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map2<T1, T2>(\n                Volume<T1> t1, Volume<T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1, T2>(\n                Volume<T1> t1, Volume<T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map2<T1, T2d, T2>(\n                Volume<T1> t1, Volume<T2d, T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1, T2d, T2>(\n                Volume<T1> t1, Volume<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map2<T1d, T1, T2>(\n                Volume<T1d, T1> t1, Volume<T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1d, T1, T2>(\n                Volume<T1d, T1> t1, Volume<T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map2<T1d, T1, T2d, T2>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1d, T1, T2d, T2>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map3<T1, T2, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1, T2, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map3<T1, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map3<T1, T2d, T2, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1, T2d, T2, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map3<T1, T2d, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1, T2d, T2, T3d, T3>(\n                Volume<T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map3<T1d, T1, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1d, T1, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map3<T1d, T1, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1d, T1, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map3<T1d, T1, T2d, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1d, T1, T2d, T2, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function on each element of\n        /// the supplied volume.\n        /// </summary>\n        public static Volume<Td, Tv> Map3<T1d, T1, T2d, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to each index of the\n        /// elements of the supplied volume. The function may access the\n        /// elements of the supplied volume to compute the elements of the new\n        /// volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Volume<T1d, T1> t1, Volume<T2d, T2> t2, Volume<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Volume<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new volume by applying a function to the coordinates of\n        /// the elements the newly created volume.\n        /// </summary>\n        public static Volume<Td, Tv> Create(V3l size, Func<V3l, Tv> fun)\n        {\n            return new Volume<Td, Tv>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new Volume by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting Volume.\n        /// </summary>\n        public static Volume<Td, Tv> CreateConvolution<Ti, Tf, Tm, Ts>(\n                Volume<Ti> image, Volume<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Tv> castFun)\n        {\n            V3l size = 1 + image.S - filter.S;\n            if (size.Z <= 0 ||size.Y <= 0 ||size.X <= 0) throw new Exception(\"filter to large\");\n            return new Volume<Td, Tv>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td, Tv> CreateOuterProduct<Tx, Ty, Tz>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Tx, Ty, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td, Tv> CreateOuterProduct<Tx, Ty, Tzd, Tz>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Tx, Ty, Tzd, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td, Tv> CreateOuterProduct<Tx, Tyd, Ty, Tz>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td, Tv> CreateOuterProduct<Tx, Tyd, Ty, Tzd, Tz>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td, Tv> CreateOuterProduct<Txd, Tx, Ty, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td, Tv> CreateOuterProduct<Txd, Tx, Ty, Tzd, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tzd, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td, Tv> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tz>(tx, ty, tz, fun);\n        }\n\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly Volume<Td, Tv> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz,\n                    Func<Tx, Ty, Tz, Tv> fun)\n        {\n            return new Volume<Td, Tv>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz>(tx, ty, tz, fun);\n        }\n\n        #endregion\n\n        #region Sampling\n\n\n\n        public readonly TRes SampleRaw8<T1, T2, TRes>(\n                V3d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return SampleRaw8(v.X, v.Y, v.Z, xipl, yipl, zipl);\n        }\n\n        /// <summary>\n        /// Sample the volume using 8 samples and the supplied\n        /// interpolation functions. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the volume, i.e. voxel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw8<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            long i = Info.Origin + xi * Info.Delta.X + yi * Info.Delta.Y + zi * Info.Delta.Z;\n            long ix = i + dx; long iy = i + dy; long ixy = ix + dy;\n            return zipl(zf, yipl(yf, xipl(xf, Getter(Data, i), Getter(Data, ix)),\n                                     xipl(xf, Getter(Data, iy), Getter(Data, ixy))),\n                            yipl(yf, xipl(xf, Getter(Data, i + dz), Getter(Data, ix + dz)),\n                                     xipl(xf, Getter(Data, iy + dz), Getter(Data, ixy + dz))));\n        }\n\n        public readonly TRes Sample8Clamped<T1, T2, TRes>(\n                V3d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return Sample8(v.X, v.Y, v.Z, xipl, yipl, zipl,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample8Clamped<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return Sample8(x, y, z, xipl, yipl, zipl,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample8<T1, T2, TRes>(\n                V3d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun)\n        {\n            return Sample8(v.X, v.Y, v.Z, xipl, yipl, zipl,\n                           index_min_max_delta_xIndexFun,\n                           index_min_max_delta_yIndexFun,\n                           index_min_max_delta_zIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the volume using 8 samples and the supplied\n        /// interpolation functions. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the volume, i.e. voxel centers are assumed to be on\n        /// integer coordinates.\n        /// </summary>\n        public readonly TRes Sample8<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1); dx.E0 += i; dx.E1 += i;\n            var dyz = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                   index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1));\n            return zipl(zf, yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyz.E0), Getter(Data, dx.E1 + dyz.E0)),\n                                     xipl(xf, Getter(Data, dx.E0 + dyz.E1), Getter(Data, dx.E1 + dyz.E1))),\n                            yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyz.E2), Getter(Data, dx.E1 + dyz.E2)),\n                                     xipl(xf, Getter(Data, dx.E0 + dyz.E3), Getter(Data, dx.E1 + dyz.E3))));\n        }\n\n        public readonly TRes SampleRaw64<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return SampleRaw64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp);\n        }\n\n        public readonly TRes SampleRaw64<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            long i11 = Info.Origin + xi * dx + yi * dy + zi * dz;\n            long d2 = dx + dx;\n            long i10 = i11 - dy, i12 = i11 + dy, i13 = i12 + dy;\n            long i00 = i10 - dz, i01 = i11 - dz, i02 = i12 - dz, i03 = i13 - dz;\n            long i20 = i10 + dz, i21 = i11 + dz, i22 = i12 + dz, i23 = i13 + dz;\n            long i30 = i20 + dz, i31 = i21 + dz, i32 = i22 + dz, i33 = i23 + dz;\n            var wx = xipl(xf); var wy = yipl(yf); var wz = zipl(zf);\n            return zsmp(ysmp(xsmp(Getter(Data, i00 - dx), Getter(Data, i00), Getter(Data, i00 + dx), Getter(Data, i00 + d2), ref wx),\n                             xsmp(Getter(Data, i01 - dx), Getter(Data, i01), Getter(Data, i01 + dx), Getter(Data, i01 + d2), ref wx),\n                             xsmp(Getter(Data, i02 - dx), Getter(Data, i02), Getter(Data, i02 + dx), Getter(Data, i02 + d2), ref wx),\n                             xsmp(Getter(Data, i03 - dx), Getter(Data, i03), Getter(Data, i03 + dx), Getter(Data, i03 + d2), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, i10 - dx), Getter(Data, i10), Getter(Data, i10 + dx), Getter(Data, i10 + d2), ref wx),\n                             xsmp(Getter(Data, i11 - dx), Getter(Data, i11), Getter(Data, i11 + dx), Getter(Data, i11 + d2), ref wx),\n                             xsmp(Getter(Data, i12 - dx), Getter(Data, i12), Getter(Data, i12 + dx), Getter(Data, i12 + d2), ref wx),\n                             xsmp(Getter(Data, i13 - dx), Getter(Data, i13), Getter(Data, i13 + dx), Getter(Data, i13 + d2), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, i20 - dx), Getter(Data, i20), Getter(Data, i20 + dx), Getter(Data, i20 + d2), ref wx),\n                             xsmp(Getter(Data, i21 - dx), Getter(Data, i21), Getter(Data, i21 + dx), Getter(Data, i21 + d2), ref wx),\n                             xsmp(Getter(Data, i22 - dx), Getter(Data, i22), Getter(Data, i22 + dx), Getter(Data, i22 + d2), ref wx),\n                             xsmp(Getter(Data, i23 - dx), Getter(Data, i23), Getter(Data, i23 + dx), Getter(Data, i23 + d2), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, i30 - dx), Getter(Data, i30), Getter(Data, i30 + dx), Getter(Data, i30 + d2), ref wx),\n                             xsmp(Getter(Data, i31 - dx), Getter(Data, i31), Getter(Data, i31 + dx), Getter(Data, i31 + d2), ref wx),\n                             xsmp(Getter(Data, i32 - dx), Getter(Data, i32), Getter(Data, i32 + dx), Getter(Data, i32 + d2), ref wx),\n                             xsmp(Getter(Data, i33 - dx), Getter(Data, i33), Getter(Data, i33 + dx), Getter(Data, i33 + d2), ref wx), ref wy), ref wz);\n        }\n\n        public readonly TRes Sample64Clamped<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return Sample64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample64Clamped<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return Sample64(x, y, z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample64<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_zIndexFun)\n        {\n            return Sample64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun,\n                            index_min_max_delta_zIndexFun);\n        }\n\n        public readonly TRes Sample64<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<Tv, Tv, Tv, Tv, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_zIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i;\n            var dyz = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                   index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1));\n            var wx = xipl(xf); var wy = yipl(yf); var wz = zipl(zf);\n            return zsmp(ysmp(xsmp(Getter(Data, dx.E0 + dyz.E00), Getter(Data, dx.E1 + dyz.E00), Getter(Data, dx.E2 + dyz.E00), Getter(Data, dx.E3 + dyz.E00), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E01), Getter(Data, dx.E1 + dyz.E01), Getter(Data, dx.E2 + dyz.E01), Getter(Data, dx.E3 + dyz.E01), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E02), Getter(Data, dx.E1 + dyz.E02), Getter(Data, dx.E2 + dyz.E02), Getter(Data, dx.E3 + dyz.E02), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E03), Getter(Data, dx.E1 + dyz.E03), Getter(Data, dx.E2 + dyz.E03), Getter(Data, dx.E3 + dyz.E03), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, dx.E0 + dyz.E04), Getter(Data, dx.E1 + dyz.E04), Getter(Data, dx.E2 + dyz.E04), Getter(Data, dx.E3 + dyz.E04), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E05), Getter(Data, dx.E1 + dyz.E05), Getter(Data, dx.E2 + dyz.E05), Getter(Data, dx.E3 + dyz.E05), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E06), Getter(Data, dx.E1 + dyz.E06), Getter(Data, dx.E2 + dyz.E06), Getter(Data, dx.E3 + dyz.E06), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E07), Getter(Data, dx.E1 + dyz.E07), Getter(Data, dx.E2 + dyz.E07), Getter(Data, dx.E3 + dyz.E07), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, dx.E0 + dyz.E08), Getter(Data, dx.E1 + dyz.E08), Getter(Data, dx.E2 + dyz.E08), Getter(Data, dx.E3 + dyz.E08), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E09), Getter(Data, dx.E1 + dyz.E09), Getter(Data, dx.E2 + dyz.E09), Getter(Data, dx.E3 + dyz.E09), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E10), Getter(Data, dx.E1 + dyz.E10), Getter(Data, dx.E2 + dyz.E10), Getter(Data, dx.E3 + dyz.E10), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E11), Getter(Data, dx.E1 + dyz.E11), Getter(Data, dx.E2 + dyz.E11), Getter(Data, dx.E3 + dyz.E11), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, dx.E0 + dyz.E12), Getter(Data, dx.E1 + dyz.E12), Getter(Data, dx.E2 + dyz.E12), Getter(Data, dx.E3 + dyz.E12), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E13), Getter(Data, dx.E1 + dyz.E13), Getter(Data, dx.E2 + dyz.E13), Getter(Data, dx.E3 + dyz.E13), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E14), Getter(Data, dx.E1 + dyz.E14), Getter(Data, dx.E2 + dyz.E14), Getter(Data, dx.E3 + dyz.E14), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E15), Getter(Data, dx.E1 + dyz.E15), Getter(Data, dx.E2 + dyz.E15), Getter(Data, dx.E3 + dyz.E15), ref wx), ref wy), ref wz);\n        }\n\n        #endregion\n\n        #region IVolume\n\n        /// <summary>\n        /// Dimension of the generic Volume.\n        /// </summary>\n        public readonly V3l Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(long x, long y, long z)\n        {\n            return (object)this[x, y, z];\n        }\n\n        public readonly void SetValue(object value, long x, long y, long z)\n        {\n            this[x, y, z] = (Tv)value;\n        }\n\n        public readonly object GetValue(V3l v)\n        {\n            return (object)this[v];\n        }\n\n        public readonly void SetValue(object value, V3l v)\n        {\n            this[v] = (Tv)value;\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    #region Tensor4Info\n\n    /// <summary>\n    /// A tensor4 info contains the complete indexing information for a tensor4, but no data array.\n    /// </summary>\n    [Serializable]\n    public struct Tensor4Info : ITensorInfo\n    {\n        /// <summary>\n        /// Index of element with coordinates [0, 0, 0, 0] in the underlying data array.\n        /// </summary>\n        public long Origin;\n\n        /// <summary>\n        /// Size of the tensor4.\n        /// </summary>\n        public V4l Size;\n\n        /// <summary>\n        /// Stride in each dimension.\n        /// </summary>\n        public V4l Delta;\n\n        /// <summary>\n        /// Coordinates of the first element.\n        /// May differ from coordinates [0, 0, 0, 0] for subwindows that retain the original coordinate space.\n        /// </summary>\n        public V4l First;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a Tensor4Info given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the tensor4.</param>\n        /// <param name=\"delta\">Stride in each dimension.</param>\n        /// <param name=\"first\">Coordinates of the first element.</param>\n        public Tensor4Info(long origin, V4l size, V4l delta, V4l first)\n        {\n            Origin = origin;\n            Size = size;\n            Delta = delta;\n            First = first;\n        }\n\n        /// <summary>\n        /// Construct a Tensor4Info given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the tensor4.</param>\n        /// <param name=\"delta\">Stride in each dimension.</param>\n        public Tensor4Info(long origin, V4l size, V4l delta)\n            : this(origin, size, delta, V4l.Zero)\n        { }\n\n        private static V4l NewDelta(V4l size)\n        {\n            return new V4l(1L, size.X, size.X * size.Y, size.X * size.Y * size.Z);\n        }\n\n        private static V4l NewDelta(V4l size, V4l delta)\n        {\n            if (delta.W == 1L) return new V4l(size.W, size.W * size.X, size.W * size.X * size.Y, 1L);\n            if (delta.Z == 1L) return new V4l(size.Z * size.W, size.Z * size.W * size.X, 1L, size.Z);\n            if (delta.Y == 1L) return new V4l(size.Y * size.Z * size.W, 1L, size.Y, size.Y * size.Z);\n            return NewDelta(size);\n        }\n\n        /// <summary>\n        /// Construct tensor4 info of specified size.\n        /// </summary>\n        public Tensor4Info(V4l size)\n            : this(0L, size, NewDelta(size))\n        { }\n\n        /// <summary>\n        /// Construct tensor4 info of specified size and delta.\n        /// </summary>\n        public Tensor4Info(V4l size, V4l delta)\n            : this(0L, size, NewDelta(size, delta))\n        { }\n\n        public Tensor4Info(Tensor4Info info)\n            : this(0L, info.Size, NewDelta(info.Size, info.Delta))\n        {\n            F = info.F;\n        }\n\n        /// <summary>\n        /// Construct tensor4 info of specified size.\n        /// </summary>\n        public Tensor4Info(V4i size)\n            : this((V4l)size)\n        { }\n\n        /// <summary>\n        /// Construct tensor4 info of specified size and delta.\n        /// </summary>\n        public Tensor4Info(V4i size, V4i delta)\n            : this((V4l)size, (V4l)delta)\n        { }\n\n        /// <summary>\n        /// Construct tensor4 info of specified size.\n        /// </summary>\n        public Tensor4Info(long sizeX, long sizeY, long sizeZ, long sizeW)\n            : this(new V4l(sizeX, sizeY, sizeZ, sizeW))\n        { }\n\n        /// <summary>\n        /// Construct tensor4 info of specified size.\n        /// </summary>\n        public Tensor4Info(int sizeX, int sizeY, int sizeZ, int sizeW)\n            : this(new V4l(sizeX, sizeY, sizeZ, sizeW))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the the tensor4 (4).\n        /// </summary>\n        public readonly int Rank { get { return 4; } }\n\n        /// <summary>\n        /// Total number of element in the tensor4.\n        /// </summary>\n        public readonly long Count { get { return  Size.X *  Size.Y *  Size.Z *  Size.W; } }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        public readonly V4l End { get { return First + Size; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOO { get { return First; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOO { get { return new V4l(First.X + Size.X, First.Y, First.Z, First.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOO { get { return new V4l(First.X, First.Y + Size.Y, First.Z, First.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOO { get { return new V4l(First.X + Size.X, First.Y + Size.Y, First.Z, First.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIO { get { return new V4l(First.X, First.Y, First.Z + Size.Z, First.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIO { get { return new V4l(First.X + Size.X, First.Y, First.Z + Size.Z, First.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIO { get { return new V4l(First.X, First.Y + Size.Y, First.Z + Size.Z, First.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIO { get { return new V4l(First.X + Size.X, First.Y + Size.Y, First.Z + Size.Z, First.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOI { get { return new V4l(First.X, First.Y, First.Z, First.W + Size.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOI { get { return new V4l(First.X + Size.X, First.Y, First.Z, First.W + Size.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOI { get { return new V4l(First.X, First.Y + Size.Y, First.Z, First.W + Size.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOI { get { return new V4l(First.X + Size.X, First.Y + Size.Y, First.Z, First.W + Size.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOII { get { return new V4l(First.X, First.Y, First.Z + Size.Z, First.W + Size.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOII { get { return new V4l(First.X + Size.X, First.Y, First.Z + Size.Z, First.W + Size.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIII { get { return new V4l(First.X, First.Y + Size.Y, First.Z + Size.Z, First.W + Size.W); } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIII { get { return First + Size; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l S { readonly get { return Size; } set { Size = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l D { readonly get { return Delta; } set { Delta = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l F { readonly get { return First; } set { Origin -= Delta.Dot(value - First); First = value; } }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l E { get { return First + Size; } }\n\n        /// <summary>\n        /// Size.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Size.X; } set { Size.X = value; } }\n\n        /// <summary>\n        /// Size.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Size.Y; } set { Size.Y = value; } }\n\n        /// <summary>\n        /// Size.Z\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SZ { readonly get { return Size.Z; } set { Size.Z = value; } }\n\n        /// <summary>\n        /// Size.W\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SW { readonly get { return Size.W; } set { Size.W = value; } }\n\n        /// <summary>\n        /// Delta.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Delta.X; } set { Delta.X = value; } }\n\n        /// <summary>\n        /// Delta.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Delta.Y; } set { Delta.Y = value; } }\n\n        /// <summary>\n        /// Delta.Z\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DZ { readonly get { return Delta.Z; } set { Delta.Z = value; } }\n\n        /// <summary>\n        /// Delta.W\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DW { readonly get { return Delta.W; } set { Delta.W = value; } }\n\n        /// <summary>\n        /// First.X\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX\n        {\n            readonly get { return First.X; }\n            set { Origin -= Delta.X * (value - First.X); First.X = value; }\n        }\n\n        /// <summary>\n        /// First.Y\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY\n        {\n            readonly get { return First.Y; }\n            set { Origin -= Delta.Y * (value - First.Y); First.Y = value; }\n        }\n\n        /// <summary>\n        /// First.Z\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FZ\n        {\n            readonly get { return First.Z; }\n            set { Origin -= Delta.Z * (value - First.Z); First.Z = value; }\n        }\n\n        /// <summary>\n        /// First.W\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FW\n        {\n            readonly get { return First.W; }\n            set { Origin -= Delta.W * (value - First.W); First.W = value; }\n        }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX\n        {\n            get { return First.X + Size.X; }\n        }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY\n        {\n            get { return First.Y + Size.Y; }\n        }\n\n        /// <summary>\n        /// End in dimension Z (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EZ\n        {\n            get { return First.Z + Size.Z; }\n        }\n\n        /// <summary>\n        /// End in dimension W (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EW\n        {\n            get { return First.W + Size.W; }\n        }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Size.X * Delta.X; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Size.Y * Delta.Y; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSZ { get { return Size.Z * Delta.Z; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSW { get { return Size.W * Delta.W; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Delta.X; } }\n\n        public readonly long GetJX(V4l size)\n        {\n            return Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Delta.Y - Size.X * Delta.X; } }\n\n        public readonly long GetJY(V4l size)\n        {\n            return Delta.Y - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZ { get { return Delta.Z - Size.Y * Delta.Y; } }\n\n        public readonly long GetJZ(V4l size)\n        {\n            return Delta.Z - size.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JW { get { return Delta.W - Size.Z * Delta.Z; } }\n\n        public readonly long GetJW(V4l size)\n        {\n            return Delta.W - size.Z * Delta.Z;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX0 { get { return Delta.X; } }\n\n        public readonly long GetJX0(V4l size)\n        {\n            return Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JXY { get { return Delta.X - Size.Y * Delta.Y; } }\n\n        public readonly long GetJXY(V4l size)\n        {\n            return Delta.X - size.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JXZ { get { return Delta.X - Size.Z * Delta.Z; } }\n\n        public readonly long GetJXZ(V4l size)\n        {\n            return Delta.X - size.Z * Delta.Z;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension X in a loop around another loop\n        /// in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JXW { get { return Delta.X - Size.W * Delta.W; } }\n\n        public readonly long GetJXW(V4l size)\n        {\n            return Delta.X - size.W * Delta.W;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JYX { get { return Delta.Y - Size.X * Delta.X; } }\n\n        public readonly long GetJYX(V4l size)\n        {\n            return Delta.Y - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY0 { get { return Delta.Y; } }\n\n        public readonly long GetJY0(V4l size)\n        {\n            return Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JYZ { get { return Delta.Y - Size.Z * Delta.Z; } }\n\n        public readonly long GetJYZ(V4l size)\n        {\n            return Delta.Y - size.Z * Delta.Z;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Y in a loop around another loop\n        /// in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JYW { get { return Delta.Y - Size.W * Delta.W; } }\n\n        public readonly long GetJYW(V4l size)\n        {\n            return Delta.Y - size.W * Delta.W;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z in a loop around another loop\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZX { get { return Delta.Z - Size.X * Delta.X; } }\n\n        public readonly long GetJZX(V4l size)\n        {\n            return Delta.Z - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z in a loop around another loop\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZY { get { return Delta.Z - Size.Y * Delta.Y; } }\n\n        public readonly long GetJZY(V4l size)\n        {\n            return Delta.Z - size.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZ0 { get { return Delta.Z; } }\n\n        public readonly long GetJZ0(V4l size)\n        {\n            return Delta.Z;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension Z in a loop around another loop\n        /// in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZW { get { return Delta.Z - Size.W * Delta.W; } }\n\n        public readonly long GetJZW(V4l size)\n        {\n            return Delta.Z - size.W * Delta.W;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension W in a loop around another loop\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JWX { get { return Delta.W - Size.X * Delta.X; } }\n\n        public readonly long GetJWX(V4l size)\n        {\n            return Delta.W - size.X * Delta.X;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension W in a loop around another loop\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JWY { get { return Delta.W - Size.Y * Delta.Y; } }\n\n        public readonly long GetJWY(V4l size)\n        {\n            return Delta.W - size.Y * Delta.Y;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension W in a loop around another loop\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JWZ { get { return Delta.W - Size.Z * Delta.Z; } }\n\n        public readonly long GetJWZ(V4l size)\n        {\n            return Delta.W - size.Z * Delta.Z;\n        }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension W in a loop around another loop\n        /// in dimension 0.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JW0 { get { return Delta.W; } }\n\n        public readonly long GetJW0(V4l size)\n        {\n            return Delta.W;\n        }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Index(First); } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long OriginIndex { readonly get { return Origin; } set { Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return new long[] { SX, SY, SZ, SW }; }\n            set { SX = value[0]; SY = value[1]; SZ = value[2]; SW = value[3];  }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return new long[] { DX, DY, DZ, DW }; }\n            set { DX = value[0]; DY = value[1]; DZ = value[2]; DW = value[3];  }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return new long[] { FX, FY, FZ, FW }; }\n            set { FX = value[0]; FY = value[1]; FZ = value[2]; FW = value[3];  }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXYZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXYW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXZY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXZW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXWY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXWZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYXZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYXW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYZX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYZW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYWX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYWZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZXY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZXW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZYX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZYW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZWX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZWY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWXY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWXZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWYX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWYZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWZX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWZY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXYZW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXYWZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXZYW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXZWY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXWYZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesXWZY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYXZW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYXWZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYZXW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYZWX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYWXZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesYWZX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZXYW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZXWY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZYXW\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JXW; i != xe; i += xj)\n                for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZYWX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZW; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JYW; i != ye; i += yj)\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZWXY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesZWYX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWXYZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWXZY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWYXZ\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JXZ; i != xe; i += xj)\n                for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWYZX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWZ; i != we; i += wj)\n                for (long ye = i + DSY, yj = JYZ; i != ye; i += yj)\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWZXY\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWX; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZX; i != ze; i += zj)\n                for (long xe = i + DSX, xj = JXY; i != xe; i += xj)\n                for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                    yield return i;\n            }\n        }\n\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> IndicesWZYX\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long we = i + DSW, wj = JWY; i != we; i += wj)\n                for (long ze = i + DSZ, zj = JZY; i != ze; i += zj)\n                for (long ye = i + DSY, yj = JYX; i != ye; i += yj)\n                for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                    yield return i;\n            }\n        }\n\n        #endregion\n\n        #region Indexing Helper Methods\n\n        public readonly long Dv(long dx, long dy, long dz, long dw)\n        {\n            return dx * Delta.X + dy * Delta.Y + dz * Delta.Z + dw * Delta.W;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(long x, long y, long z, long w)\n        {\n            return Origin + x * Delta.X + y * Delta.Y + z * Delta.Z + w * Delta.W;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(V4l v)\n        {\n            return Origin + v.X * Delta.X + v.Y * Delta.Y + v.Z * Delta.Z + v.W * Delta.W;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(V4i v)\n        {\n            return Origin + v.X * Delta.X + v.Y * Delta.Y + v.Z * Delta.Z + v.W * Delta.W;\n        }\n\n        #endregion\n\n        #region Interpretation and Parts\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4Window(V4l begin, V4l size)\n        {\n            return new Tensor4Info(Origin, size, Delta, begin);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4(V4l begin, V4l size)\n        {\n            return new Tensor4Info(Index(begin), size, Delta);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4Window(V4i begin, V4i size)\n        {\n            return new Tensor4Info(Origin, (V4l)size, Delta, (V4l)begin);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4(V4i begin, V4i size)\n        {\n            return new Tensor4Info(Index((V4l)begin), (V4l)size, Delta);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4Window(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4Info(Origin, size, delta, begin);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4Info(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4Window(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4Info(Origin, (V4l)size, (V4l)delta, (V4l)begin);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4Info(Index((V4l)begin), (V4l)size, (V4l)delta);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4Window(V4l begin, V4l size, V4l delta, V4l first)\n        {\n            return new Tensor4Info(Index(begin), size, delta) { F = first };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4Window(V4i begin, V4i size, V4i delta, V4i first)\n        {\n            return new Tensor4Info(Index((V4l)begin), (V4l)size, (V4l)delta)\n                            { F = (V4l)first };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4Window(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4Info(Origin, new V4l(sizeX, sizeY, sizeZ, sizeW),\n                                  Delta, new V4l(beginX, beginY, beginZ, beginW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4Info(Index(beginX, beginY, beginZ, beginW),\n                                  new V4l(sizeX, sizeY, sizeZ, sizeW),\n                                  Delta);\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4Window(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4Info(Origin, new V4l(sizeX, sizeY, sizeZ, sizeW),\n                                  new V4l(deltaX, deltaY, deltaZ, deltaW),\n                                  new V4l(beginX, beginY, beginZ, beginW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubTensor4(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4Info(Index(beginX, beginY, beginZ, beginW),\n                                  new V4l(sizeX, sizeY, sizeZ, sizeW),\n                                  new V4l(deltaX, deltaY, deltaZ, deltaW));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(V4l begin, long size, long delta)\n        {\n            return new VectorInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo SubVector(V4i begin, long size, long delta)\n        {\n            return new VectorInfo(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// This methods returns a Vector with zero as first coordinates.\n        /// </summary>\n        public readonly VectorInfo AsVector()\n        {\n            if (JX != 0 || JY != 0 || JZ != 0)\n                throw new Exception(\"cannot represent this tensor4 as vector\");\n            return new VectorInfo(Origin, SX * SY * SZ * SW, DX);\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubYZWVolume(long x)\n        {\n            return new VolumeInfo(Index(x, FY, FZ, FW), S.YZW, D.YZW);\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubYZWVolumeAsReadOnlyTensor4(long x, long sizex)\n        {\n            return new Tensor4Info(Index(x, FY, FZ, FW), new V4l(sizex, SY, SZ, SW), D.OYZW);\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly VolumeInfo SubYZWVolumeWindow(long x)\n        {\n            return new VolumeInfo(Index(x, FY, FZ, FW), S.YZW, D.YZW) { F = F.YZW };\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubYZWVolumeAsReadOnlyTensor4Window(long x, long sizex)\n        {\n            return new Tensor4Info(Index(x, FY, FZ, FW), new V4l(sizex, SY, SZ, SW), D.OYZW) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubXZWVolume(long y)\n        {\n            return new VolumeInfo(Index(FX, y, FZ, FW), S.XZW, D.XZW);\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubXZWVolumeAsReadOnlyTensor4(long y, long sizey)\n        {\n            return new Tensor4Info(Index(FX, y, FZ, FW), new V4l(SX, sizey, SZ, SW), D.XOZW);\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly VolumeInfo SubXZWVolumeWindow(long y)\n        {\n            return new VolumeInfo(Index(FX, y, FZ, FW), S.XZW, D.XZW) { F = F.XZW };\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubXZWVolumeAsReadOnlyTensor4Window(long y, long sizey)\n        {\n            return new Tensor4Info(Index(FX, y, FZ, FW), new V4l(SX, sizey, SZ, SW), D.XOZW) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubXYWVolume(long z)\n        {\n            return new VolumeInfo(Index(FX, FY, z, FW), S.XYW, D.XYW);\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubXYWVolumeAsReadOnlyTensor4(long z, long sizez)\n        {\n            return new Tensor4Info(Index(FX, FY, z, FW), new V4l(SX, SY, sizez, SW), D.XYOW);\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly VolumeInfo SubXYWVolumeWindow(long z)\n        {\n            return new VolumeInfo(Index(FX, FY, z, FW), S.XYW, D.XYW) { F = F.XYW };\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubXYWVolumeAsReadOnlyTensor4Window(long z, long sizez)\n        {\n            return new Tensor4Info(Index(FX, FY, z, FW), new V4l(SX, SY, sizez, SW), D.XYOW) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly VolumeInfo SubXYZVolume(long w)\n        {\n            return new VolumeInfo(Index(FX, FY, FZ, w), S.XYZ, D.XYZ);\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubXYZVolumeAsReadOnlyTensor4(long w, long sizew)\n        {\n            return new Tensor4Info(Index(FX, FY, FZ, w), new V4l(SX, SY, SZ, sizew), D.XYZO);\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly VolumeInfo SubXYZVolumeWindow(long w)\n        {\n            return new VolumeInfo(Index(FX, FY, FZ, w), S.XYZ, D.XYZ) { F = F.XYZ };\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubXYZVolumeAsReadOnlyTensor4Window(long w, long sizew)\n        {\n            return new Tensor4Info(Index(FX, FY, FZ, w), new V4l(SX, SY, SZ, sizew), D.XYZO) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubZWMatrixAsReadOnlyTensor4(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4Info(Index(x, y, FZ, FW), new V4l(sizex, sizey, SZ, SW), D.OOZW);\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubZWMatrixAsReadOnlyTensor4Window(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4Info(Index(x, y, FZ, FW), new V4l(sizex, sizey, SZ, SW), D.OOZW) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubYWMatrixAsReadOnlyTensor4(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4Info(Index(x, FY, z, FW), new V4l(sizex, SY, sizez, SW), D.OYOW);\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubYWMatrixAsReadOnlyTensor4Window(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4Info(Index(x, FY, z, FW), new V4l(sizex, SY, sizez, SW), D.OYOW) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubYZMatrixAsReadOnlyTensor4(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4Info(Index(x, FY, FZ, w), new V4l(sizex, SY, SZ, sizew), D.OYZO);\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubYZMatrixAsReadOnlyTensor4Window(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4Info(Index(x, FY, FZ, w), new V4l(sizex, SY, SZ, sizew), D.OYZO) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubXWMatrixAsReadOnlyTensor4(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4Info(Index(FX, y, z, FW), new V4l(SX, sizey, sizez, SW), D.XOOW);\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubXWMatrixAsReadOnlyTensor4Window(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4Info(Index(FX, y, z, FW), new V4l(SX, sizey, sizez, SW), D.XOOW) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubXZMatrixAsReadOnlyTensor4(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4Info(Index(FX, y, FZ, w), new V4l(SX, sizey, SZ, sizew), D.XOZO);\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubXZMatrixAsReadOnlyTensor4Window(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4Info(Index(FX, y, FZ, w), new V4l(SX, sizey, SZ, sizew), D.XOZO) { F = F };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4Info SubXYMatrixAsReadOnlyTensor4(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4Info(Index(FX, FY, z, w), new V4l(SX, SY, sizez, sizew), D.XYOO);\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4Info SubXYMatrixAsReadOnlyTensor4Window(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4Info(Index(FX, FY, z, w), new V4l(SX, SY, sizez, sizew), D.XYOO) { F = F };\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long ws = DSW, wj = JW;\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    i_action(i);\n                } } } }\n            }\n            else if (DW == 1)\n            {\n                long zs = DSZ, zj = JZY;\n                long ys = DSY, yj = JYX;\n                long xs = DSX, xj = JXW;\n                long ws = SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    i_action(i);\n                } } } }\n            }\n            else\n            {\n                long ws = DSW, wj = JW;\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    i_action(i);\n                } } } }\n            }\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long, long, long> x_y_z_w_i_action)\n        {\n            long i = FirstIndex;\n            if (DX == 1)\n            {\n                long ws = DSW, wj = JW;\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    x_y_z_w_i_action(x, y, z, w, i);\n                } } } }\n            }\n            else if (DW == 1)\n            {\n                long zs = DSZ, zj = JZY;\n                long ys = DSY, yj = JYX;\n                long xs = DSX, xj = JXW;\n                long ws = SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    x_y_z_w_i_action(x, y, z, w, i);\n                } } } }\n            }\n            else\n            {\n                long ws = DSW, wj = JW;\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    x_y_z_w_i_action(x, y, z, w, i);\n                } } } }\n            }\n        }\n\n        public readonly void ForeachCoord(Action<V4l> v_action)\n        {\n            long i = FirstIndex; V4l v;\n            if (DX == 1)\n            {\n                long ws = DSW, wj = JW;\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = SX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    v_action(v);\n                } } } }\n            }\n            else if (DW == 1)\n            {\n                long zs = DSZ, zj = JZY;\n                long ys = DSY, yj = JYX;\n                long xs = DSX, xj = JXW;\n                long ws = SW;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.W = FW; for (long we = i + ws; i != we; i++, v.W++) {\n                    v_action(v);\n                } } } }\n            }\n            else\n            {\n                long ws = DSW, wj = JW;\n                long zs = DSZ, zj = JZ;\n                long ys = DSY, yj = JY;\n                long xs = DSX, xj = JX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    v_action(v);\n                } } } }\n            }\n        }\n\n        public readonly void ForeachIndex(Tensor4Info t1, Action<long, long> i_i1_act)\n        {\n            CheckMatchingSize(t1);\n            if (HasMatchingLayout(t1))\n            {\n                long i = FirstIndex;\n                if (DX == 1)\n                {\n                    long ws = DSW, wj = JW;\n                    long zs = DSZ, zj = JZ;\n                    long ys = DSY, yj = JY;\n                    long xs = SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        i_i1_act(i, i);\n                    } } } }\n                }\n                else if (DW == 1)\n                {\n                    long zs = DSZ, zj = JZY;\n                    long ys = DSY, yj = JYX;\n                    long xs = DSX, xj = JXW;\n                    long ws = SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        i_i1_act(i, i);\n                    } } } }\n                }\n                else\n                {\n                    long ws = DSW, wj = JW;\n                    long zs = DSZ, zj = JZ;\n                    long ys = DSY, yj = JY;\n                    long xs = DSX, xj = JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        i_i1_act(i, i);\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (DX == 1 && t1.DX == 1)\n                {\n                    long ws = DSW, wj = JW, wj1 = t1.JW;\n                    long zs = DSZ, zj = JZ, zj1 = t1.JZ;\n                    long ys = DSY, yj = JY, yj1 = t1.JY;\n                    long xs = SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        i_i1_act(i, i1);\n                    } } } }\n                }\n                else if (DW == 1 && t1.DW == 1)\n                {\n                    long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n                    long ys = DSY, yj = JYX, yj1 = t1.JYX;\n                    long xs = DSX, xj = JXW, xj1 = t1.JXW;\n                    long ws = SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        i_i1_act(i, i1);\n                    } } } }\n                }\n                else\n                {\n                    long ws = DSW, wj = JW, wj1 = t1.JW;\n                    long zs = DSZ, zj = JZ, zj1 = t1.JZ;\n                    long ys = DSY, yj = JY, yj1 = t1.JY;\n                    long xs = DSX, xj = JX, xj1 = t1.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        i_i1_act(i, i1);\n                    } } } }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0, x = FX; i != xe; i += xj, x++)\n                x_elementAct(x);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0, y = FY; i != ye; i += yj, y++)\n                y_elementAct(y);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZ(\n                Action<long> z_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0, z = FZ; i != ze; i += zj, z++)\n                z_elementAct(z);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachW(\n                Action<long> w_elementAct)\n        {\n            long i = FirstIndex;\n            for (long we = i + DSW, wj = JW0, w = FW; i != we; i += wj, w++)\n                w_elementAct(w);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_elementAct(x, y);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_elementAct(x, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_elementAct(x, z);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_elementAct(x, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_elementAct(x, z);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long, long> x_w_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_w_elementAct(x, w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long, long> x_w_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_w_elementAct(x, w);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long> x_preLineAct,\n                Action<long, long> x_w_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_w_elementAct(x, w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long> x_preLineAct,\n                Action<long, long> x_w_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_w_elementAct(x, w);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_elementAct(y, x);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_elementAct(y, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_elementAct(y, z);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_elementAct(y, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_elementAct(y, z);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long, long> y_w_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_w_elementAct(y, w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long, long> y_w_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_w_elementAct(y, w);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long> y_preLineAct,\n                Action<long, long> y_w_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_w_elementAct(y, w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long> y_preLineAct,\n                Action<long, long> y_w_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_w_elementAct(y, w);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_elementAct(z, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_elementAct(z, x);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_elementAct(z, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_elementAct(z, x);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_elementAct(z, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_elementAct(z, y);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_elementAct(z, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_elementAct(z, y);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long, long> z_w_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_w_elementAct(z, w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long, long> z_w_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_w_elementAct(z, w);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long> z_preLineAct,\n                Action<long, long> z_w_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_w_elementAct(z, w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long> z_preLineAct,\n                Action<long, long> z_w_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_w_elementAct(z, w);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long, long> w_x_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_x_elementAct(w, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long, long> w_x_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_x_elementAct(w, x);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long> w_preLineAct,\n                Action<long, long> w_x_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_x_elementAct(w, x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long> w_preLineAct,\n                Action<long, long> w_x_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_x_elementAct(w, x);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long, long> w_y_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_y_elementAct(w, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long, long> w_y_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_y_elementAct(w, y);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long> w_preLineAct,\n                Action<long, long> w_y_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_y_elementAct(w, y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long> w_preLineAct,\n                Action<long, long> w_y_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_y_elementAct(w, y);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long, long> w_z_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_z_elementAct(w, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long, long> w_z_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_z_elementAct(w, z);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long> w_preLineAct,\n                Action<long, long> w_z_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_z_elementAct(w, z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long> w_preLineAct,\n                Action<long, long> w_z_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_z_elementAct(w, z);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_elementAct(x, y, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_elementAct(x, y, z);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_elementAct(x, y, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_elementAct(x, y, z);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long, long, long> x_y_w_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_w_elementAct(x, y, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long, long, long> x_y_w_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_w_elementAct(x, y, w);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_w_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_w_elementAct(x, y, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_w_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_w_elementAct(x, y, w);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_elementAct(x, z, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_elementAct(x, z, y);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_elementAct(x, z, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_elementAct(x, z, y);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long, long, long> x_z_w_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_w_elementAct(x, z, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long, long, long> x_z_w_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_w_elementAct(x, z, w);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_w_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_w_elementAct(x, z, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_w_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_w_elementAct(x, z, w);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long, long, long> x_w_y_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_y_elementAct(x, w, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long, long, long> x_w_y_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_y_elementAct(x, w, y);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_y_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_y_elementAct(x, w, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_y_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_y_elementAct(x, w, y);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long, long, long> x_w_z_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_z_elementAct(x, w, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long, long, long> x_w_z_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_z_elementAct(x, w, z);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_z_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_z_elementAct(x, w, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_z_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_z_elementAct(x, w, z);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_elementAct(y, x, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_elementAct(y, x, z);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_elementAct(y, x, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_elementAct(y, x, z);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long, long, long> y_x_w_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_w_elementAct(y, x, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long, long, long> y_x_w_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_w_elementAct(y, x, w);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_w_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_w_elementAct(y, x, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_w_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_w_elementAct(y, x, w);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_elementAct(y, z, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_elementAct(y, z, x);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_elementAct(y, z, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_elementAct(y, z, x);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long, long, long> y_z_w_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_w_elementAct(y, z, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long, long, long> y_z_w_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_w_elementAct(y, z, w);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_w_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_w_elementAct(y, z, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_w_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_w_elementAct(y, z, w);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long, long, long> y_w_x_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_x_elementAct(y, w, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long, long, long> y_w_x_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_x_elementAct(y, w, x);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_x_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_x_elementAct(y, w, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_x_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_x_elementAct(y, w, x);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long, long, long> y_w_z_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_z_elementAct(y, w, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long, long, long> y_w_z_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_z_elementAct(y, w, z);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_z_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_z_elementAct(y, w, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_z_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_z_elementAct(y, w, z);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_elementAct(z, x, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_elementAct(z, x, y);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_elementAct(z, x, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_elementAct(z, x, y);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long, long, long> z_x_w_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_w_elementAct(z, x, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long, long, long> z_x_w_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_w_elementAct(z, x, w);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_w_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_w_elementAct(z, x, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_w_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_w_elementAct(z, x, w);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_elementAct(z, y, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_elementAct(z, y, x);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_elementAct(z, y, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_elementAct(z, y, x);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long, long, long> z_y_w_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_w_elementAct(z, y, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long, long, long> z_y_w_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_w_elementAct(z, y, w);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_w_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_w_elementAct(z, y, w);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_w_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_w_elementAct(z, y, w);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long, long, long> z_w_x_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_x_elementAct(z, w, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long, long, long> z_w_x_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_x_elementAct(z, w, x);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_x_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_x_elementAct(z, w, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_x_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_x_elementAct(z, w, x);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long, long, long> z_w_y_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_y_elementAct(z, w, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long, long, long> z_w_y_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_y_elementAct(z, w, y);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_y_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_y_elementAct(z, w, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_y_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_y_elementAct(z, w, y);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long, long, long> w_x_y_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_y_elementAct(w, x, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long, long, long> w_x_y_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_y_elementAct(w, x, y);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_y_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_y_elementAct(w, x, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_y_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_y_elementAct(w, x, y);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long, long, long> w_x_z_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_z_elementAct(w, x, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long, long, long> w_x_z_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_z_elementAct(w, x, z);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_z_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_z_elementAct(w, x, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_z_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_z_elementAct(w, x, z);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long, long, long> w_y_x_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_x_elementAct(w, y, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long, long, long> w_y_x_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_x_elementAct(w, y, x);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_x_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_x_elementAct(w, y, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_x_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_x_elementAct(w, y, x);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long, long, long> w_y_z_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_z_elementAct(w, y, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long, long, long> w_y_z_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_z_elementAct(w, y, z);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_z_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_z_elementAct(w, y, z);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_z_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_z_elementAct(w, y, z);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long, long, long> w_z_x_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_x_elementAct(w, z, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long, long, long> w_z_x_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_x_elementAct(w, z, x);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_x_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_x_elementAct(w, z, x);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_x_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_x_elementAct(w, z, x);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long, long, long> w_z_y_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_y_elementAct(w, z, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long, long, long> w_z_y_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_y_elementAct(w, z, y);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_y_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_y_elementAct(w, z, y);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_y_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_y_elementAct(w, z, y);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long, long, long, long> x_y_z_w_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_z_w_elementAct(x, y, z, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long, long, long, long> x_y_z_w_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_z_w_elementAct(x, y, z, w);\n            x_y_z_postLineAct(x, y, z);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long> x_y_z_w_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_y_z_preLineAct(x, y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_z_w_elementAct(x, y, z, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long> x_y_z_w_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_y_z_preLineAct(x, y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_z_w_elementAct(x, y, z, w);\n            x_y_z_postLineAct(x, y, z);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long, long, long, long> x_y_w_z_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_w_z_elementAct(x, y, w, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long, long, long, long> x_y_w_z_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_w_z_elementAct(x, y, w, z);\n            x_y_w_postLineAct(x, y, w);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long> x_y_w_z_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_y_w_preLineAct(x, y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_w_z_elementAct(x, y, w, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long> x_y_w_z_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_y_w_preLineAct(x, y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_w_z_elementAct(x, y, w, z);\n            x_y_w_postLineAct(x, y, w);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long, long, long, long> x_z_y_w_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_y_w_elementAct(x, z, y, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long, long, long, long> x_z_y_w_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_y_w_elementAct(x, z, y, w);\n            x_z_y_postLineAct(x, z, y);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long> x_z_y_w_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_z_y_preLineAct(x, z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_y_w_elementAct(x, z, y, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long> x_z_y_w_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_z_y_preLineAct(x, z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_y_w_elementAct(x, z, y, w);\n            x_z_y_postLineAct(x, z, y);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long, long, long, long> x_z_w_y_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_w_y_elementAct(x, z, w, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long, long, long, long> x_z_w_y_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_w_y_elementAct(x, z, w, y);\n            x_z_w_postLineAct(x, z, w);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long> x_z_w_y_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_z_w_preLineAct(x, z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_w_y_elementAct(x, z, w, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long> x_z_w_y_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_z_w_preLineAct(x, z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_w_y_elementAct(x, z, w, y);\n            x_z_w_postLineAct(x, z, w);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long, long, long, long> x_w_y_z_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_y_z_elementAct(x, w, y, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long, long, long, long> x_w_y_z_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_y_z_elementAct(x, w, y, z);\n            x_w_y_postLineAct(x, w, y);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long> x_w_y_z_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_w_y_preLineAct(x, w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_y_z_elementAct(x, w, y, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long> x_w_y_z_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_w_y_preLineAct(x, w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_y_z_elementAct(x, w, y, z);\n            x_w_y_postLineAct(x, w, y);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long, long, long, long> x_w_z_y_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_z_y_elementAct(x, w, z, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long, long, long, long> x_w_z_y_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_z_y_elementAct(x, w, z, y);\n            x_w_z_postLineAct(x, w, z);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long> x_w_z_y_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_w_z_preLineAct(x, w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_z_y_elementAct(x, w, z, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long> x_w_z_y_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_w_z_preLineAct(x, w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_z_y_elementAct(x, w, z, y);\n            x_w_z_postLineAct(x, w, z);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long, long, long, long> y_x_z_w_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_z_w_elementAct(y, x, z, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long, long, long, long> y_x_z_w_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_z_w_elementAct(y, x, z, w);\n            y_x_z_postLineAct(y, x, z);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long> y_x_z_w_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_x_z_preLineAct(y, x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_z_w_elementAct(y, x, z, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long> y_x_z_w_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_x_z_preLineAct(y, x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_z_w_elementAct(y, x, z, w);\n            y_x_z_postLineAct(y, x, z);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long, long, long, long> y_x_w_z_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_w_z_elementAct(y, x, w, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long, long, long, long> y_x_w_z_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_w_z_elementAct(y, x, w, z);\n            y_x_w_postLineAct(y, x, w);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long> y_x_w_z_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_x_w_preLineAct(y, x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_w_z_elementAct(y, x, w, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long> y_x_w_z_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_x_w_preLineAct(y, x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_w_z_elementAct(y, x, w, z);\n            y_x_w_postLineAct(y, x, w);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long, long, long, long> y_z_x_w_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_x_w_elementAct(y, z, x, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long, long, long, long> y_z_x_w_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_x_w_elementAct(y, z, x, w);\n            y_z_x_postLineAct(y, z, x);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long> y_z_x_w_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_z_x_preLineAct(y, z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_x_w_elementAct(y, z, x, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long> y_z_x_w_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_z_x_preLineAct(y, z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_x_w_elementAct(y, z, x, w);\n            y_z_x_postLineAct(y, z, x);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long, long, long, long> y_z_w_x_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_w_x_elementAct(y, z, w, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long, long, long, long> y_z_w_x_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_w_x_elementAct(y, z, w, x);\n            y_z_w_postLineAct(y, z, w);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long> y_z_w_x_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_z_w_preLineAct(y, z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_w_x_elementAct(y, z, w, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long> y_z_w_x_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_z_w_preLineAct(y, z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_w_x_elementAct(y, z, w, x);\n            y_z_w_postLineAct(y, z, w);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long, long, long, long> y_w_x_z_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_x_z_elementAct(y, w, x, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long, long, long, long> y_w_x_z_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_x_z_elementAct(y, w, x, z);\n            y_w_x_postLineAct(y, w, x);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long> y_w_x_z_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_w_x_preLineAct(y, w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_x_z_elementAct(y, w, x, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long> y_w_x_z_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_w_x_preLineAct(y, w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_x_z_elementAct(y, w, x, z);\n            y_w_x_postLineAct(y, w, x);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long, long, long, long> y_w_z_x_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_z_x_elementAct(y, w, z, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long, long, long, long> y_w_z_x_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_z_x_elementAct(y, w, z, x);\n            y_w_z_postLineAct(y, w, z);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long> y_w_z_x_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_w_z_preLineAct(y, w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_z_x_elementAct(y, w, z, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long> y_w_z_x_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_w_z_preLineAct(y, w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_z_x_elementAct(y, w, z, x);\n            y_w_z_postLineAct(y, w, z);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long, long, long, long> z_x_y_w_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_y_w_elementAct(z, x, y, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long, long, long, long> z_x_y_w_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_y_w_elementAct(z, x, y, w);\n            z_x_y_postLineAct(z, x, y);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long> z_x_y_w_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_x_y_preLineAct(z, x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_y_w_elementAct(z, x, y, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long> z_x_y_w_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_x_y_preLineAct(z, x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_y_w_elementAct(z, x, y, w);\n            z_x_y_postLineAct(z, x, y);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long, long, long, long> z_x_w_y_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_w_y_elementAct(z, x, w, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long, long, long, long> z_x_w_y_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_w_y_elementAct(z, x, w, y);\n            z_x_w_postLineAct(z, x, w);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long> z_x_w_y_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_x_w_preLineAct(z, x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_w_y_elementAct(z, x, w, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long> z_x_w_y_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_x_w_preLineAct(z, x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_w_y_elementAct(z, x, w, y);\n            z_x_w_postLineAct(z, x, w);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long, long, long, long> z_y_x_w_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_x_w_elementAct(z, y, x, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long, long, long, long> z_y_x_w_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_x_w_elementAct(z, y, x, w);\n            z_y_x_postLineAct(z, y, x);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long> z_y_x_w_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_y_x_preLineAct(z, y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_x_w_elementAct(z, y, x, w);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long> z_y_x_w_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_y_x_preLineAct(z, y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_x_w_elementAct(z, y, x, w);\n            z_y_x_postLineAct(z, y, x);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long, long, long, long> z_y_w_x_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_w_x_elementAct(z, y, w, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long, long, long, long> z_y_w_x_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_w_x_elementAct(z, y, w, x);\n            z_y_w_postLineAct(z, y, w);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long> z_y_w_x_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_y_w_preLineAct(z, y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_w_x_elementAct(z, y, w, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long> z_y_w_x_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_y_w_preLineAct(z, y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_w_x_elementAct(z, y, w, x);\n            z_y_w_postLineAct(z, y, w);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long, long, long, long> z_w_x_y_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_x_y_elementAct(z, w, x, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long, long, long, long> z_w_x_y_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_x_y_elementAct(z, w, x, y);\n            z_w_x_postLineAct(z, w, x);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long> z_w_x_y_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_w_x_preLineAct(z, w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_x_y_elementAct(z, w, x, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long> z_w_x_y_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_w_x_preLineAct(z, w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_x_y_elementAct(z, w, x, y);\n            z_w_x_postLineAct(z, w, x);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long, long, long, long> z_w_y_x_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_y_x_elementAct(z, w, y, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long, long, long, long> z_w_y_x_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_y_x_elementAct(z, w, y, x);\n            z_w_y_postLineAct(z, w, y);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long> z_w_y_x_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_w_y_preLineAct(z, w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_y_x_elementAct(z, w, y, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long> z_w_y_x_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_w_y_preLineAct(z, w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_y_x_elementAct(z, w, y, x);\n            z_w_y_postLineAct(z, w, y);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long, long, long, long> w_x_y_z_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_y_z_elementAct(w, x, y, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long, long, long, long> w_x_y_z_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_y_z_elementAct(w, x, y, z);\n            w_x_y_postLineAct(w, x, y);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long> w_x_y_z_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_x_y_preLineAct(w, x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_y_z_elementAct(w, x, y, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long> w_x_y_z_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_x_y_preLineAct(w, x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_y_z_elementAct(w, x, y, z);\n            w_x_y_postLineAct(w, x, y);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long, long, long, long> w_x_z_y_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_z_y_elementAct(w, x, z, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long, long, long, long> w_x_z_y_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_z_y_elementAct(w, x, z, y);\n            w_x_z_postLineAct(w, x, z);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long> w_x_z_y_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_x_z_preLineAct(w, x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_z_y_elementAct(w, x, z, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long> w_x_z_y_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_x_z_preLineAct(w, x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_z_y_elementAct(w, x, z, y);\n            w_x_z_postLineAct(w, x, z);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long, long, long, long> w_y_x_z_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_x_z_elementAct(w, y, x, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long, long, long, long> w_y_x_z_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_x_z_elementAct(w, y, x, z);\n            w_y_x_postLineAct(w, y, x);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long> w_y_x_z_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_y_x_preLineAct(w, y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_x_z_elementAct(w, y, x, z);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long> w_y_x_z_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_y_x_preLineAct(w, y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_x_z_elementAct(w, y, x, z);\n            w_y_x_postLineAct(w, y, x);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long, long, long, long> w_y_z_x_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_z_x_elementAct(w, y, z, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long, long, long, long> w_y_z_x_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_z_x_elementAct(w, y, z, x);\n            w_y_z_postLineAct(w, y, z);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long> w_y_z_x_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_y_z_preLineAct(w, y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_z_x_elementAct(w, y, z, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long> w_y_z_x_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_y_z_preLineAct(w, y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_z_x_elementAct(w, y, z, x);\n            w_y_z_postLineAct(w, y, z);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long, long, long, long> w_z_x_y_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_x_y_elementAct(w, z, x, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long, long, long, long> w_z_x_y_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_x_y_elementAct(w, z, x, y);\n            w_z_x_postLineAct(w, z, x);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long> w_z_x_y_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_z_x_preLineAct(w, z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_x_y_elementAct(w, z, x, y);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long> w_z_x_y_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_z_x_preLineAct(w, z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_x_y_elementAct(w, z, x, y);\n            w_z_x_postLineAct(w, z, x);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long, long, long, long> w_z_y_x_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_y_x_elementAct(w, z, y, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long, long, long, long> w_z_y_x_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_y_x_elementAct(w, z, y, x);\n            w_z_y_postLineAct(w, z, y);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long> w_z_y_x_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_z_y_preLineAct(w, z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_y_x_elementAct(w, z, y, x);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long> w_z_y_x_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_z_y_preLineAct(w, z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_y_x_elementAct(w, z, y, x);\n            w_z_y_postLineAct(w, z, y);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0; i != xe; i += xj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long xe = i + DSX, xj = JX0, x = FX; i != xe; i += xj, x++)\n                x_i_elementAct(x, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0; i != ye; i += yj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ye = i + DSY, yj = JY0, y = FY; i != ye; i += yj, y++)\n                y_i_elementAct(y, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0; i != ze; i += zj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long, long> z_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0, z = FZ; i != ze; i += zj, z++)\n                z_i_elementAct(z, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachWIndex(\n                Action<long> i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long we = i + DSW, wj = JW0; i != we; i += wj)\n                i_elementAct(i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachWIndex(\n                Action<long, long> w_i_elementAct)\n        {\n            long i = FirstIndex;\n            for (long we = i + DSW, wj = JW0, w = FW; i != we; i += wj, w++)\n                w_i_elementAct(w, i);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_y_i_elementAct(x, y, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_i_elementAct(x, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_i_elementAct(x, z, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_i_elementAct(x, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_z_i_elementAct(x, z, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long, long, long> x_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_w_i_elementAct(x, w, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long, long, long> x_w_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_w_i_elementAct(x, w, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_w_i_elementAct(x, w, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_w_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preLineAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_w_i_elementAct(x, w, i);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_x_i_elementAct(y, x, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_i_elementAct(y, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_i_elementAct(y, z, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_i_elementAct(y, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_z_i_elementAct(y, z, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long, long, long> y_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_w_i_elementAct(y, w, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long, long, long> y_w_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_w_i_elementAct(y, w, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_w_i_elementAct(y, w, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_w_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preLineAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_w_i_elementAct(y, w, i);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_i_elementAct(z, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_i_elementAct(z, x, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_i_elementAct(z, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_x_i_elementAct(z, x, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_i_elementAct(z, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_i_elementAct(z, y, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_i_elementAct(z, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_y_i_elementAct(z, y, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long, long, long> z_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_w_i_elementAct(z, w, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long, long, long> z_w_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_w_i_elementAct(z, w, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_w_i_elementAct(z, w, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_w_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preLineAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_w_i_elementAct(z, w, i);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long, long, long> w_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_x_i_elementAct(w, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long, long, long> w_x_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_x_i_elementAct(w, x, i);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_x_i_elementAct(w, x, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_x_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_x_i_elementAct(w, x, i);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long, long, long> w_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_y_i_elementAct(w, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long, long, long> w_y_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_y_i_elementAct(w, y, i);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_y_i_elementAct(w, y, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_y_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_y_i_elementAct(w, y, i);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long, long, long> w_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_z_i_elementAct(w, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long, long, long> w_z_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_z_i_elementAct(w, z, i);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_z_i_elementAct(w, z, i);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_z_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preLineAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_z_i_elementAct(w, z, i);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_i_elementAct(x, y, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_i_elementAct(x, y, z, i);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_i_elementAct(x, y, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_z_i_elementAct(x, y, z, i);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long, long, long, long> x_y_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_w_i_elementAct(x, y, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long, long, long, long> x_y_w_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_w_i_elementAct(x, y, w, i);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_w_i_elementAct(x, y, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_w_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_w_i_elementAct(x, y, w, i);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_i_elementAct(x, z, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_i_elementAct(x, z, y, i);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_i_elementAct(x, z, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_y_i_elementAct(x, z, y, i);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long, long, long, long> x_z_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_w_i_elementAct(x, z, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long, long, long, long> x_z_w_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_w_i_elementAct(x, z, w, i);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_w_i_elementAct(x, z, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_w_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_w_i_elementAct(x, z, w, i);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long, long, long, long> x_w_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_y_i_elementAct(x, w, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long, long, long, long> x_w_y_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_y_i_elementAct(x, w, y, i);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_y_i_elementAct(x, w, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_y_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_y_i_elementAct(x, w, y, i);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long, long, long, long> x_w_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_z_i_elementAct(x, w, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long, long, long, long> x_w_z_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_z_i_elementAct(x, w, z, i);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_z_i_elementAct(x, w, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_z_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_z_i_elementAct(x, w, z, i);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_i_elementAct(y, x, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_i_elementAct(y, x, z, i);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_i_elementAct(y, x, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_z_i_elementAct(y, x, z, i);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long, long, long, long> y_x_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_w_i_elementAct(y, x, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long, long, long, long> y_x_w_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_w_i_elementAct(y, x, w, i);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_w_i_elementAct(y, x, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_w_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_w_i_elementAct(y, x, w, i);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_i_elementAct(y, z, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_i_elementAct(y, z, x, i);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_i_elementAct(y, z, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_x_i_elementAct(y, z, x, i);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long, long, long, long> y_z_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_w_i_elementAct(y, z, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long, long, long, long> y_z_w_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_w_i_elementAct(y, z, w, i);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_w_i_elementAct(y, z, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_w_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_w_i_elementAct(y, z, w, i);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long, long, long, long> y_w_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_x_i_elementAct(y, w, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long, long, long, long> y_w_x_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_x_i_elementAct(y, w, x, i);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_x_i_elementAct(y, w, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_x_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_x_i_elementAct(y, w, x, i);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long, long, long, long> y_w_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_z_i_elementAct(y, w, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long, long, long, long> y_w_z_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_z_i_elementAct(y, w, z, i);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_z_i_elementAct(y, w, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_z_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_z_i_elementAct(y, w, z, i);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_i_elementAct(z, x, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_i_elementAct(z, x, y, i);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_i_elementAct(z, x, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_y_i_elementAct(z, x, y, i);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long, long, long, long> z_x_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_w_i_elementAct(z, x, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long, long, long, long> z_x_w_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_w_i_elementAct(z, x, w, i);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_w_i_elementAct(z, x, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_w_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_w_i_elementAct(z, x, w, i);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_i_elementAct(z, y, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_i_elementAct(z, y, x, i);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_i_elementAct(z, y, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_x_i_elementAct(z, y, x, i);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long, long, long, long> z_y_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_w_i_elementAct(z, y, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long, long, long, long> z_y_w_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_w_i_elementAct(z, y, w, i);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_w_i_elementAct(z, y, w, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_w_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_w_i_elementAct(z, y, w, i);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long, long, long, long> z_w_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_x_i_elementAct(z, w, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long, long, long, long> z_w_x_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_x_i_elementAct(z, w, x, i);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_x_i_elementAct(z, w, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_x_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_x_i_elementAct(z, w, x, i);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long, long, long, long> z_w_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_y_i_elementAct(z, w, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long, long, long, long> z_w_y_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_y_i_elementAct(z, w, y, i);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_y_i_elementAct(z, w, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_y_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_y_i_elementAct(z, w, y, i);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long, long, long, long> w_x_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_y_i_elementAct(w, x, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long, long, long, long> w_x_y_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_y_i_elementAct(w, x, y, i);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_y_i_elementAct(w, x, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_y_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_y_i_elementAct(w, x, y, i);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long, long, long, long> w_x_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_z_i_elementAct(w, x, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long, long, long, long> w_x_z_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_z_i_elementAct(w, x, z, i);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_z_i_elementAct(w, x, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_z_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_z_i_elementAct(w, x, z, i);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long, long, long, long> w_y_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_x_i_elementAct(w, y, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long, long, long, long> w_y_x_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_x_i_elementAct(w, y, x, i);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_x_i_elementAct(w, y, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_x_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_x_i_elementAct(w, y, x, i);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long, long, long, long> w_y_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_z_i_elementAct(w, y, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long, long, long, long> w_y_z_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_z_i_elementAct(w, y, z, i);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_z_i_elementAct(w, y, z, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_z_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_z_i_elementAct(w, y, z, i);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long, long, long, long> w_z_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_x_i_elementAct(w, z, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long, long, long, long> w_z_x_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_x_i_elementAct(w, z, x, i);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_x_i_elementAct(w, z, x, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_x_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_x_i_elementAct(w, z, x, i);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long, long, long, long> w_z_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_y_i_elementAct(w, z, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long, long, long, long> w_z_y_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_y_i_elementAct(w, z, y, i);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_y_i_elementAct(w, z, y, i);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_y_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_y_i_elementAct(w, z, y, i);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_z_w_i_elementAct(x, y, z, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_z_w_i_elementAct(x, y, z, w, i);\n            x_y_z_postLineAct(x, y, z);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_y_z_preLineAct(x, y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_z_w_i_elementAct(x, y, z, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_y_z_preLineAct(x, y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_y_z_w_i_elementAct(x, y, z, w, i);\n            x_y_z_postLineAct(x, y, z);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_w_z_i_elementAct(x, y, w, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_w_z_i_elementAct(x, y, w, z, i);\n            x_y_w_postLineAct(x, y, w);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_y_w_preLineAct(x, y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_w_z_i_elementAct(x, y, w, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_y_w_preLineAct(x, y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_y_w_z_i_elementAct(x, y, w, z, i);\n            x_y_w_postLineAct(x, y, w);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_y_w_i_elementAct(x, z, y, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_y_w_i_elementAct(x, z, y, w, i);\n            x_z_y_postLineAct(x, z, y);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_z_y_preLineAct(x, z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_y_w_i_elementAct(x, z, y, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_z_y_preLineAct(x, z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                x_z_y_w_i_elementAct(x, z, y, w, i);\n            x_z_y_postLineAct(x, z, y);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_w_y_i_elementAct(x, z, w, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_w_y_i_elementAct(x, z, w, y, i);\n            x_z_w_postLineAct(x, z, w);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_z_w_preLineAct(x, z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_w_y_i_elementAct(x, z, w, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_z_w_preLineAct(x, z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_z_w_y_i_elementAct(x, z, w, y, i);\n            x_z_w_postLineAct(x, z, w);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_y_z_i_elementAct(x, w, y, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_y_z_i_elementAct(x, w, y, z, i);\n            x_w_y_postLineAct(x, w, y);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_w_y_preLineAct(x, w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_y_z_i_elementAct(x, w, y, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            x_w_y_preLineAct(x, w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                x_w_y_z_i_elementAct(x, w, y, z, i);\n            x_w_y_postLineAct(x, w, y);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_z_y_i_elementAct(x, w, z, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_z_y_i_elementAct(x, w, z, y, i);\n            x_w_z_postLineAct(x, w, z);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_w_z_preLineAct(x, w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_z_y_i_elementAct(x, w, z, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            x_w_z_preLineAct(x, w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                x_w_z_y_i_elementAct(x, w, z, y, i);\n            x_w_z_postLineAct(x, w, z);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_z_w_i_elementAct(y, x, z, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_z_w_i_elementAct(y, x, z, w, i);\n            y_x_z_postLineAct(y, x, z);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_x_z_preLineAct(y, x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_z_w_i_elementAct(y, x, z, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_x_z_preLineAct(y, x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_x_z_w_i_elementAct(y, x, z, w, i);\n            y_x_z_postLineAct(y, x, z);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_w_z_i_elementAct(y, x, w, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_w_z_i_elementAct(y, x, w, z, i);\n            y_x_w_postLineAct(y, x, w);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_x_w_preLineAct(y, x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_w_z_i_elementAct(y, x, w, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_x_w_preLineAct(y, x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_x_w_z_i_elementAct(y, x, w, z, i);\n            y_x_w_postLineAct(y, x, w);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_x_w_i_elementAct(y, z, x, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_x_w_i_elementAct(y, z, x, w, i);\n            y_z_x_postLineAct(y, z, x);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_z_x_preLineAct(y, z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_x_w_i_elementAct(y, z, x, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_z_x_preLineAct(y, z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                y_z_x_w_i_elementAct(y, z, x, w, i);\n            y_z_x_postLineAct(y, z, x);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_w_x_i_elementAct(y, z, w, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_w_x_i_elementAct(y, z, w, x, i);\n            y_z_w_postLineAct(y, z, w);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_z_w_preLineAct(y, z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_w_x_i_elementAct(y, z, w, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_z_w_preLineAct(y, z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_z_w_x_i_elementAct(y, z, w, x, i);\n            y_z_w_postLineAct(y, z, w);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_x_z_i_elementAct(y, w, x, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_x_z_i_elementAct(y, w, x, z, i);\n            y_w_x_postLineAct(y, w, x);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_w_x_preLineAct(y, w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_x_z_i_elementAct(y, w, x, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            y_w_x_preLineAct(y, w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                y_w_x_z_i_elementAct(y, w, x, z, i);\n            y_w_x_postLineAct(y, w, x);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_z_x_i_elementAct(y, w, z, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_z_x_i_elementAct(y, w, z, x, i);\n            y_w_z_postLineAct(y, w, z);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_w_z_preLineAct(y, w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_z_x_i_elementAct(y, w, z, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            y_w_z_preLineAct(y, w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                y_w_z_x_i_elementAct(y, w, z, x, i);\n            y_w_z_postLineAct(y, w, z);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_y_w_i_elementAct(z, x, y, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_y_w_i_elementAct(z, x, y, w, i);\n            z_x_y_postLineAct(z, x, y);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_x_y_preLineAct(z, x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_y_w_i_elementAct(z, x, y, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_x_y_preLineAct(z, x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_x_y_w_i_elementAct(z, x, y, w, i);\n            z_x_y_postLineAct(z, x, y);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_w_y_i_elementAct(z, x, w, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_w_y_i_elementAct(z, x, w, y, i);\n            z_x_w_postLineAct(z, x, w);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_x_w_preLineAct(z, x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_w_y_i_elementAct(z, x, w, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_x_w_preLineAct(z, x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_x_w_y_i_elementAct(z, x, w, y, i);\n            z_x_w_postLineAct(z, x, w);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_x_w_i_elementAct(z, y, x, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_x_w_i_elementAct(z, y, x, w, i);\n            z_y_x_postLineAct(z, y, x);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_y_x_preLineAct(z, y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_x_w_i_elementAct(z, y, x, w, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXW;\n            long ws = DSW, wj = JW0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_y_x_preLineAct(z, y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n                z_y_x_w_i_elementAct(z, y, x, w, i);\n            z_y_x_postLineAct(z, y, x);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_w_x_i_elementAct(z, y, w, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_w_x_i_elementAct(z, y, w, x, i);\n            z_y_w_postLineAct(z, y, w);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_y_w_preLineAct(z, y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_w_x_i_elementAct(z, y, w, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_y_w_preLineAct(z, y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_y_w_x_i_elementAct(z, y, w, x, i);\n            z_y_w_postLineAct(z, y, w);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_x_y_i_elementAct(z, w, x, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_x_y_i_elementAct(z, w, x, y, i);\n            z_w_x_postLineAct(z, w, x);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_w_x_preLineAct(z, w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_x_y_i_elementAct(z, w, x, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            z_w_x_preLineAct(z, w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                z_w_x_y_i_elementAct(z, w, x, y, i);\n            z_w_x_postLineAct(z, w, x);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_y_x_i_elementAct(z, w, y, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_y_x_i_elementAct(z, w, y, x, i);\n            z_w_y_postLineAct(z, w, y);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_w_y_preLineAct(z, w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_y_x_i_elementAct(z, w, y, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW;\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            z_w_y_preLineAct(z, w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                z_w_y_x_i_elementAct(z, w, y, x, i);\n            z_w_y_postLineAct(z, w, y);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_y_z_i_elementAct(w, x, y, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_y_z_i_elementAct(w, x, y, z, i);\n            w_x_y_postLineAct(w, x, y);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_x_y_preLineAct(w, x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_y_z_i_elementAct(w, x, y, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_x_y_preLineAct(w, x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_x_y_z_i_elementAct(w, x, y, z, i);\n            w_x_y_postLineAct(w, x, y);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_z_y_i_elementAct(w, x, z, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_z_y_i_elementAct(w, x, z, y, i);\n            w_x_z_postLineAct(w, x, z);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_x_z_preLineAct(w, x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_z_y_i_elementAct(w, x, z, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_x_z_preLineAct(w, x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_x_z_y_i_elementAct(w, x, z, y, i);\n            w_x_z_postLineAct(w, x, z);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_x_z_i_elementAct(w, y, x, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_x_z_i_elementAct(w, y, x, z, i);\n            w_y_x_postLineAct(w, y, x);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_y_x_preLineAct(w, y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_x_z_i_elementAct(w, y, x, z, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JXZ;\n            long zs = DSZ, zj = JZ0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_y_x_preLineAct(w, y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n                w_y_x_z_i_elementAct(w, y, x, z, i);\n            w_y_x_postLineAct(w, y, x);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_z_x_i_elementAct(w, y, z, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_z_x_i_elementAct(w, y, z, x, i);\n            w_y_z_postLineAct(w, y, z);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_y_z_preLineAct(w, y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_z_x_i_elementAct(w, y, z, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY;\n            long ys = DSY, yj = JYZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_y_z_preLineAct(w, y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_y_z_x_i_elementAct(w, y, z, x, i);\n            w_y_z_postLineAct(w, y, z);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_x_y_i_elementAct(w, z, x, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_x_y_i_elementAct(w, z, x, y, i);\n            w_z_x_postLineAct(w, z, x);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_z_x_preLineAct(w, z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_x_y_i_elementAct(w, z, x, y, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZX;\n            long xs = DSX, xj = JXY;\n            long ys = DSY, yj = JY0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n            {\n            w_z_x_preLineAct(w, z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n                w_z_x_y_i_elementAct(w, z, x, y, i);\n            w_z_x_postLineAct(w, z, x);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws; i != we; i += wj)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj)\n                i_elementAct(i);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_y_x_i_elementAct(w, z, y, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_y_x_i_elementAct(w, z, y, x, i);\n            w_z_y_postLineAct(w, z, y);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_z_y_preLineAct(w, z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_y_x_i_elementAct(w, z, y, x, i);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ;\n            long zs = DSZ, zj = JZY;\n            long ys = DSY, yj = JYX;\n            long xs = DSX, xj = JX0;\n            long i = FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, y++)\n            {\n            w_z_y_preLineAct(w, z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, x++)\n                w_z_y_x_i_elementAct(w, z, y, x, i);\n            w_z_y_postLineAct(w, z, y);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + DSX, xj = JX0, xj1 = t1.JX0; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(Tensor4Info t1, \n                Action<long, long, long> x_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + DSX, xj = JX0, xj1 = t1.JX0, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                x_i_i1_elementAct(x, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + DSY, yj = JY0, yj1 = t1.JY0; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(Tensor4Info t1, \n                Action<long, long, long> y_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + DSY, yj = JY0, yj1 = t1.JY0, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                y_i_i1_elementAct(y, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0, zj1 = t1.JZ0; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(Tensor4Info t1, \n                Action<long, long, long> z_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + DSZ, zj = JZ0, zj1 = t1.JZ0, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                z_i_i1_elementAct(z, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + DSW, wj = JW0, wj1 = t1.JW0; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachWIndex(Tensor4Info t1, \n                Action<long, long, long> w_i_i1_elementAct)\n        {\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + DSW, wj = JW0, wj1 = t1.JW0, w = FW; i != we; i += wj, i1 += wj1, w++)\n                w_i_i1_elementAct(w, i, i1);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(Tensor4Info t1, \n                Action<long, long, long, long> x_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(Tensor4Info t1, \n                Action<long, long, long, long> x_y_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(Tensor4Info t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(Tensor4Info t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_y_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_y_i_i1_elementAct(x, y, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(Tensor4Info t1, \n                Action<long, long, long, long> x_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_z_i_i1_elementAct(x, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(Tensor4Info t1, \n                Action<long, long, long, long> x_z_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_z_i_i1_elementAct(x, z, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(Tensor4Info t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_z_i_i1_elementAct(x, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(Tensor4Info t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_z_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_z_i_i1_elementAct(x, z, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(Tensor4Info t1, \n                Action<long, long, long, long> x_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_w_i_i1_elementAct(x, w, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(Tensor4Info t1, \n                Action<long, long, long, long> x_w_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_w_i_i1_elementAct(x, w, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(Tensor4Info t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_w_i_i1_elementAct(x, w, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(Tensor4Info t1, \n                Action<long> x_preLineAct,\n                Action<long, long, long, long> x_w_i_i1_elementAct,\n                Action<long> x_postLineAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preLineAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_w_i_i1_elementAct(x, w, i, i1);\n            x_postLineAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(Tensor4Info t1, \n                Action<long, long, long, long> y_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(Tensor4Info t1, \n                Action<long, long, long, long> y_x_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(Tensor4Info t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(Tensor4Info t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_x_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_x_i_i1_elementAct(y, x, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(Tensor4Info t1, \n                Action<long, long, long, long> y_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_z_i_i1_elementAct(y, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(Tensor4Info t1, \n                Action<long, long, long, long> y_z_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_z_i_i1_elementAct(y, z, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(Tensor4Info t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_z_i_i1_elementAct(y, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(Tensor4Info t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_z_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_z_i_i1_elementAct(y, z, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(Tensor4Info t1, \n                Action<long, long, long, long> y_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_w_i_i1_elementAct(y, w, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(Tensor4Info t1, \n                Action<long, long, long, long> y_w_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_w_i_i1_elementAct(y, w, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(Tensor4Info t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_w_i_i1_elementAct(y, w, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(Tensor4Info t1, \n                Action<long> y_preLineAct,\n                Action<long, long, long, long> y_w_i_i1_elementAct,\n                Action<long> y_postLineAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preLineAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_w_i_i1_elementAct(y, w, i, i1);\n            y_postLineAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(Tensor4Info t1, \n                Action<long, long, long, long> z_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_x_i_i1_elementAct(z, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(Tensor4Info t1, \n                Action<long, long, long, long> z_x_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_x_i_i1_elementAct(z, x, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(Tensor4Info t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_x_i_i1_elementAct(z, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(Tensor4Info t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_x_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_x_i_i1_elementAct(z, x, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(Tensor4Info t1, \n                Action<long, long, long, long> z_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_y_i_i1_elementAct(z, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(Tensor4Info t1, \n                Action<long, long, long, long> z_y_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_y_i_i1_elementAct(z, y, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(Tensor4Info t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_y_i_i1_elementAct(z, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(Tensor4Info t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_y_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_y_i_i1_elementAct(z, y, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(Tensor4Info t1, \n                Action<long, long, long, long> z_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_w_i_i1_elementAct(z, w, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(Tensor4Info t1, \n                Action<long, long, long, long> z_w_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_w_i_i1_elementAct(z, w, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(Tensor4Info t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_w_i_i1_elementAct(z, w, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(Tensor4Info t1, \n                Action<long> z_preLineAct,\n                Action<long, long, long, long> z_w_i_i1_elementAct,\n                Action<long> z_postLineAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preLineAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_w_i_i1_elementAct(z, w, i, i1);\n            z_postLineAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(Tensor4Info t1, \n                Action<long, long, long, long> w_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_x_i_i1_elementAct(w, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(Tensor4Info t1, \n                Action<long, long, long, long> w_x_i_i1_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_x_i_i1_elementAct(w, x, i, i1);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(Tensor4Info t1, \n                Action<long> w_preLineAct,\n                Action<long, long, long, long> w_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preLineAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_x_i_i1_elementAct(w, x, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(Tensor4Info t1, \n                Action<long> w_preLineAct,\n                Action<long, long, long, long> w_x_i_i1_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preLineAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_x_i_i1_elementAct(w, x, i, i1);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(Tensor4Info t1, \n                Action<long, long, long, long> w_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_y_i_i1_elementAct(w, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(Tensor4Info t1, \n                Action<long, long, long, long> w_y_i_i1_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_y_i_i1_elementAct(w, y, i, i1);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(Tensor4Info t1, \n                Action<long> w_preLineAct,\n                Action<long, long, long, long> w_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preLineAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_y_i_i1_elementAct(w, y, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(Tensor4Info t1, \n                Action<long> w_preLineAct,\n                Action<long, long, long, long> w_y_i_i1_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preLineAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_y_i_i1_elementAct(w, y, i, i1);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(Tensor4Info t1, \n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(Tensor4Info t1, \n                Action<long, long, long, long> w_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_z_i_i1_elementAct(w, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(Tensor4Info t1, \n                Action<long, long, long, long> w_z_i_i1_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_z_i_i1_elementAct(w, z, i, i1);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(Tensor4Info t1, \n                Action<long> w_preLineAct,\n                Action<long, long, long, long> w_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preLineAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_z_i_i1_elementAct(w, z, i, i1);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(Tensor4Info t1, \n                Action<long> w_preLineAct,\n                Action<long, long, long, long> w_z_i_i1_elementAct,\n                Action<long> w_postLineAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preLineAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_z_i_i1_elementAct(w, z, i, i1);\n            w_postLineAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_y_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_z_i_i1_elementAct(x, y, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_y_z_i_i1_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_z_i_i1_elementAct(x, y, z, i, i1);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long, long> x_y_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_z_i_i1_elementAct(x, y, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long, long> x_y_z_i_i1_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_z_i_i1_elementAct(x, y, z, i, i1);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_y_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_y_w_i_i1_elementAct(x, y, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_y_w_i_i1_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_y_w_i_i1_elementAct(x, y, w, i, i1);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long, long> x_y_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_y_w_i_i1_elementAct(x, y, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long, long> x_y_w_i_i1_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_preLineAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_y_w_i_i1_elementAct(x, y, w, i, i1);\n            x_y_postLineAct(x, y);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_z_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_y_i_i1_elementAct(x, z, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_z_y_i_i1_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_y_i_i1_elementAct(x, z, y, i, i1);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long, long> x_z_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_y_i_i1_elementAct(x, z, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long, long> x_z_y_i_i1_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_y_i_i1_elementAct(x, z, y, i, i1);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_z_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_z_w_i_i1_elementAct(x, z, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_z_w_i_i1_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_z_w_i_i1_elementAct(x, z, w, i, i1);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long, long> x_z_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_z_w_i_i1_elementAct(x, z, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long, long> x_z_w_i_i1_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_preLineAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_z_w_i_i1_elementAct(x, z, w, i, i1);\n            x_z_postLineAct(x, z);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_w_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_w_y_i_i1_elementAct(x, w, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_w_y_i_i1_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_w_y_i_i1_elementAct(x, w, y, i, i1);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long, long> x_w_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_w_y_i_i1_elementAct(x, w, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long, long> x_w_y_i_i1_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_w_y_i_i1_elementAct(x, w, y, i, i1);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_w_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_w_z_i_i1_elementAct(x, w, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> x_w_z_i_i1_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_w_z_i_i1_elementAct(x, w, z, i, i1);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long, long> x_w_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_w_z_i_i1_elementAct(x, w, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(Tensor4Info t1, \n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long, long> x_w_z_i_i1_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_prePlaneAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_w_preLineAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_w_z_i_i1_elementAct(x, w, z, i, i1);\n            x_w_postLineAct(x, w);\n            }\n            x_postPlaneAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_x_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_z_i_i1_elementAct(y, x, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_x_z_i_i1_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_z_i_i1_elementAct(y, x, z, i, i1);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long, long> y_x_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_z_i_i1_elementAct(y, x, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long, long> y_x_z_i_i1_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_z_i_i1_elementAct(y, x, z, i, i1);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_x_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_x_w_i_i1_elementAct(y, x, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_x_w_i_i1_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_x_w_i_i1_elementAct(y, x, w, i, i1);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long, long> y_x_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_x_w_i_i1_elementAct(y, x, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long, long> y_x_w_i_i1_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_preLineAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_x_w_i_i1_elementAct(y, x, w, i, i1);\n            y_x_postLineAct(y, x);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_z_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_x_i_i1_elementAct(y, z, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_z_x_i_i1_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_x_i_i1_elementAct(y, z, x, i, i1);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long, long> y_z_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_x_i_i1_elementAct(y, z, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long, long> y_z_x_i_i1_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_x_i_i1_elementAct(y, z, x, i, i1);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_z_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_z_w_i_i1_elementAct(y, z, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_z_w_i_i1_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_z_w_i_i1_elementAct(y, z, w, i, i1);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long, long> y_z_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_z_w_i_i1_elementAct(y, z, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long, long> y_z_w_i_i1_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_preLineAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_z_w_i_i1_elementAct(y, z, w, i, i1);\n            y_z_postLineAct(y, z);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_w_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_w_x_i_i1_elementAct(y, w, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_w_x_i_i1_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_w_x_i_i1_elementAct(y, w, x, i, i1);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long, long> y_w_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_w_x_i_i1_elementAct(y, w, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long, long> y_w_x_i_i1_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_w_x_i_i1_elementAct(y, w, x, i, i1);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_w_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_w_z_i_i1_elementAct(y, w, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> y_w_z_i_i1_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_w_z_i_i1_elementAct(y, w, z, i, i1);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long, long> y_w_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_w_z_i_i1_elementAct(y, w, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(Tensor4Info t1, \n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long, long> y_w_z_i_i1_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_prePlaneAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_w_preLineAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_w_z_i_i1_elementAct(y, w, z, i, i1);\n            y_w_postLineAct(y, w);\n            }\n            y_postPlaneAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_x_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_y_i_i1_elementAct(z, x, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_x_y_i_i1_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_y_i_i1_elementAct(z, x, y, i, i1);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long, long> z_x_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_y_i_i1_elementAct(z, x, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long, long> z_x_y_i_i1_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_y_i_i1_elementAct(z, x, y, i, i1);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_x_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_x_w_i_i1_elementAct(z, x, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_x_w_i_i1_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_x_w_i_i1_elementAct(z, x, w, i, i1);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long, long> z_x_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_x_w_i_i1_elementAct(z, x, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long, long> z_x_w_i_i1_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_preLineAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_x_w_i_i1_elementAct(z, x, w, i, i1);\n            z_x_postLineAct(z, x);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_y_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_x_i_i1_elementAct(z, y, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_y_x_i_i1_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_x_i_i1_elementAct(z, y, x, i, i1);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long, long> z_y_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_x_i_i1_elementAct(z, y, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long, long> z_y_x_i_i1_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_x_i_i1_elementAct(z, y, x, i, i1);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_y_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_y_w_i_i1_elementAct(z, y, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_y_w_i_i1_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_y_w_i_i1_elementAct(z, y, w, i, i1);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long, long> z_y_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_y_w_i_i1_elementAct(z, y, w, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long, long> z_y_w_i_i1_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_preLineAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_y_w_i_i1_elementAct(z, y, w, i, i1);\n            z_y_postLineAct(z, y);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_w_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_w_x_i_i1_elementAct(z, w, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_w_x_i_i1_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_w_x_i_i1_elementAct(z, w, x, i, i1);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long, long> z_w_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_w_x_i_i1_elementAct(z, w, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long, long> z_w_x_i_i1_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_w_x_i_i1_elementAct(z, w, x, i, i1);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_w_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_w_y_i_i1_elementAct(z, w, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> z_w_y_i_i1_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_w_y_i_i1_elementAct(z, w, y, i, i1);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long, long> z_w_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_w_y_i_i1_elementAct(z, w, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(Tensor4Info t1, \n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long, long> z_w_y_i_i1_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_prePlaneAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_w_preLineAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_w_y_i_i1_elementAct(z, w, y, i, i1);\n            z_w_postLineAct(z, w);\n            }\n            z_postPlaneAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_x_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_x_y_i_i1_elementAct(w, x, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_x_y_i_i1_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_x_y_i_i1_elementAct(w, x, y, i, i1);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long, long> w_x_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_x_y_i_i1_elementAct(w, x, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long, long> w_x_y_i_i1_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_x_y_i_i1_elementAct(w, x, y, i, i1);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_x_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_x_z_i_i1_elementAct(w, x, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_x_z_i_i1_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_x_z_i_i1_elementAct(w, x, z, i, i1);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long, long> w_x_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_x_z_i_i1_elementAct(w, x, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long, long> w_x_z_i_i1_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_x_preLineAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_x_z_i_i1_elementAct(w, x, z, i, i1);\n            w_x_postLineAct(w, x);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_y_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_y_x_i_i1_elementAct(w, y, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_y_x_i_i1_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_y_x_i_i1_elementAct(w, y, x, i, i1);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long, long> w_y_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_y_x_i_i1_elementAct(w, y, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long, long> w_y_x_i_i1_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_y_x_i_i1_elementAct(w, y, x, i, i1);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_y_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_y_z_i_i1_elementAct(w, y, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_y_z_i_i1_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_y_z_i_i1_elementAct(w, y, z, i, i1);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long, long> w_y_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_y_z_i_i1_elementAct(w, y, z, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long, long> w_y_z_i_i1_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_y_preLineAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_y_z_i_i1_elementAct(w, y, z, i, i1);\n            w_y_postLineAct(w, y);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_z_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_z_x_i_i1_elementAct(w, z, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_z_x_i_i1_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_z_x_i_i1_elementAct(w, z, x, i, i1);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long, long> w_z_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_z_x_i_i1_elementAct(w, z, x, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long, long> w_z_x_i_i1_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_z_x_i_i1_elementAct(w, z, x, i, i1);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(Tensor4Info t1, \n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_z_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_z_y_i_i1_elementAct(w, z, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long> w_z_y_i_i1_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_z_y_i_i1_elementAct(w, z, y, i, i1);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long, long> w_z_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_z_y_i_i1_elementAct(w, z, y, i, i1);\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(Tensor4Info t1, \n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long, long> w_z_y_i_i1_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_prePlaneAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_z_preLineAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_z_y_i_i1_elementAct(w, z, y, i, i1);\n            w_z_postLineAct(w, z);\n            }\n            w_postPlaneAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_y_z_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_y_z_w_i_i1_elementAct(x, y, z, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_y_z_w_i_i1_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_y_z_w_i_i1_elementAct(x, y, z, w, i, i1);\n            x_y_z_postLineAct(x, y, z);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long, long, long> x_y_z_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_y_z_preLineAct(x, y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_y_z_w_i_i1_elementAct(x, y, z, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long, long, long> x_y_z_w_i_i1_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_y_z_preLineAct(x, y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_y_z_w_i_i1_elementAct(x, y, z, w, i, i1);\n            x_y_z_postLineAct(x, y, z);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_y_w_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_w_z_i_i1_elementAct(x, y, w, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_y_w_z_i_i1_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_w_z_i_i1_elementAct(x, y, w, z, i, i1);\n            x_y_w_postLineAct(x, y, w);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long, long, long> x_y_w_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_y_w_preLineAct(x, y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_w_z_i_i1_elementAct(x, y, w, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long, long, long> x_y_w_z_i_i1_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_y_prePlaneAct(x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_y_w_preLineAct(x, y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_y_w_z_i_i1_elementAct(x, y, w, z, i, i1);\n            x_y_w_postLineAct(x, y, w);\n            }\n            x_y_postPlaneAct(x, y);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_z_y_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_z_y_w_i_i1_elementAct(x, z, y, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_z_y_w_i_i1_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_z_y_w_i_i1_elementAct(x, z, y, w, i, i1);\n            x_z_y_postLineAct(x, z, y);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long, long, long> x_z_y_w_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_z_y_preLineAct(x, z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_z_y_w_i_i1_elementAct(x, z, y, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long, long, long> x_z_y_w_i_i1_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_z_y_preLineAct(x, z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                x_z_y_w_i_i1_elementAct(x, z, y, w, i, i1);\n            x_z_y_postLineAct(x, z, y);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_z_w_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_w_y_i_i1_elementAct(x, z, w, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_z_w_y_i_i1_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_w_y_i_i1_elementAct(x, z, w, y, i, i1);\n            x_z_w_postLineAct(x, z, w);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long, long, long> x_z_w_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_z_w_preLineAct(x, z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_w_y_i_i1_elementAct(x, z, w, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long, long, long> x_z_w_y_i_i1_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_z_prePlaneAct(x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_z_w_preLineAct(x, z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_z_w_y_i_i1_elementAct(x, z, w, y, i, i1);\n            x_z_w_postLineAct(x, z, w);\n            }\n            x_z_postPlaneAct(x, z);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_w_y_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_w_y_z_i_i1_elementAct(x, w, y, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_w_y_z_i_i1_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_w_y_z_i_i1_elementAct(x, w, y, z, i, i1);\n            x_w_y_postLineAct(x, w, y);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long, long, long> x_w_y_z_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_w_y_preLineAct(x, w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_w_y_z_i_i1_elementAct(x, w, y, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long, long, long> x_w_y_z_i_i1_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            x_w_y_preLineAct(x, w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                x_w_y_z_i_i1_elementAct(x, w, y, z, i, i1);\n            x_w_y_postLineAct(x, w, y);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_w_z_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_w_z_y_i_i1_elementAct(x, w, z, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> x_w_z_y_i_i1_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_w_z_y_i_i1_elementAct(x, w, z, y, i, i1);\n            x_w_z_postLineAct(x, w, z);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long, long, long> x_w_z_y_i_i1_elementAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_w_z_preLineAct(x, w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_w_z_y_i_i1_elementAct(x, w, z, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(Tensor4Info t1, \n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long, long, long> x_w_z_y_i_i1_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            x_preVolumeAct(x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            x_w_prePlaneAct(x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            x_w_z_preLineAct(x, w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                x_w_z_y_i_i1_elementAct(x, w, z, y, i, i1);\n            x_w_z_postLineAct(x, w, z);\n            }\n            x_w_postPlaneAct(x, w);\n            }\n            x_postVolumeAct(x);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_x_z_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_x_z_w_i_i1_elementAct(y, x, z, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_x_z_w_i_i1_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_x_z_w_i_i1_elementAct(y, x, z, w, i, i1);\n            y_x_z_postLineAct(y, x, z);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long, long, long> y_x_z_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_x_z_preLineAct(y, x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_x_z_w_i_i1_elementAct(y, x, z, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long, long, long> y_x_z_w_i_i1_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_x_z_preLineAct(y, x, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_x_z_w_i_i1_elementAct(y, x, z, w, i, i1);\n            y_x_z_postLineAct(y, x, z);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_x_w_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_w_z_i_i1_elementAct(y, x, w, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_x_w_z_i_i1_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_w_z_i_i1_elementAct(y, x, w, z, i, i1);\n            y_x_w_postLineAct(y, x, w);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long, long, long> y_x_w_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_x_w_preLineAct(y, x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_w_z_i_i1_elementAct(y, x, w, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long, long, long> y_x_w_z_i_i1_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_x_prePlaneAct(y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_x_w_preLineAct(y, x, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_x_w_z_i_i1_elementAct(y, x, w, z, i, i1);\n            y_x_w_postLineAct(y, x, w);\n            }\n            y_x_postPlaneAct(y, x);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_z_x_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_z_x_w_i_i1_elementAct(y, z, x, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_z_x_w_i_i1_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_z_x_w_i_i1_elementAct(y, z, x, w, i, i1);\n            y_z_x_postLineAct(y, z, x);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long, long, long> y_z_x_w_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_z_x_preLineAct(y, z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_z_x_w_i_i1_elementAct(y, z, x, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long, long, long> y_z_x_w_i_i1_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_z_x_preLineAct(y, z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                y_z_x_w_i_i1_elementAct(y, z, x, w, i, i1);\n            y_z_x_postLineAct(y, z, x);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_z_w_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_w_x_i_i1_elementAct(y, z, w, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_z_w_x_i_i1_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_w_x_i_i1_elementAct(y, z, w, x, i, i1);\n            y_z_w_postLineAct(y, z, w);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long, long, long> y_z_w_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_z_w_preLineAct(y, z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_w_x_i_i1_elementAct(y, z, w, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long, long, long> y_z_w_x_i_i1_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_z_prePlaneAct(y, z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_z_w_preLineAct(y, z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_z_w_x_i_i1_elementAct(y, z, w, x, i, i1);\n            y_z_w_postLineAct(y, z, w);\n            }\n            y_z_postPlaneAct(y, z);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_w_x_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_w_x_z_i_i1_elementAct(y, w, x, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_w_x_z_i_i1_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_w_x_z_i_i1_elementAct(y, w, x, z, i, i1);\n            y_w_x_postLineAct(y, w, x);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long, long, long> y_w_x_z_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_w_x_preLineAct(y, w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_w_x_z_i_i1_elementAct(y, w, x, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long, long, long> y_w_x_z_i_i1_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            y_w_x_preLineAct(y, w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                y_w_x_z_i_i1_elementAct(y, w, x, z, i, i1);\n            y_w_x_postLineAct(y, w, x);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_w_z_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_w_z_x_i_i1_elementAct(y, w, z, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> y_w_z_x_i_i1_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_w_z_x_i_i1_elementAct(y, w, z, x, i, i1);\n            y_w_z_postLineAct(y, w, z);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long, long, long> y_w_z_x_i_i1_elementAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_w_z_preLineAct(y, w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_w_z_x_i_i1_elementAct(y, w, z, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(Tensor4Info t1, \n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long, long, long> y_w_z_x_i_i1_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            y_preVolumeAct(y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            y_w_prePlaneAct(y, w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            y_w_z_preLineAct(y, w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                y_w_z_x_i_i1_elementAct(y, w, z, x, i, i1);\n            y_w_z_postLineAct(y, w, z);\n            }\n            y_w_postPlaneAct(y, w);\n            }\n            y_postVolumeAct(y);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_x_y_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_x_y_w_i_i1_elementAct(z, x, y, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_x_y_w_i_i1_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_x_y_w_i_i1_elementAct(z, x, y, w, i, i1);\n            z_x_y_postLineAct(z, x, y);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long, long, long> z_x_y_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_x_y_preLineAct(z, x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_x_y_w_i_i1_elementAct(z, x, y, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long, long, long> z_x_y_w_i_i1_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_x_y_preLineAct(z, x, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_x_y_w_i_i1_elementAct(z, x, y, w, i, i1);\n            z_x_y_postLineAct(z, x, y);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_x_w_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_w_y_i_i1_elementAct(z, x, w, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_x_w_y_i_i1_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_w_y_i_i1_elementAct(z, x, w, y, i, i1);\n            z_x_w_postLineAct(z, x, w);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long, long, long> z_x_w_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_x_w_preLineAct(z, x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_w_y_i_i1_elementAct(z, x, w, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long, long, long> z_x_w_y_i_i1_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_x_prePlaneAct(z, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_x_w_preLineAct(z, x, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_x_w_y_i_i1_elementAct(z, x, w, y, i, i1);\n            z_x_w_postLineAct(z, x, w);\n            }\n            z_x_postPlaneAct(z, x);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_y_x_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_y_x_w_i_i1_elementAct(z, y, x, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_y_x_w_i_i1_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_y_x_w_i_i1_elementAct(z, y, x, w, i, i1);\n            z_y_x_postLineAct(z, y, x);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long, long, long> z_y_x_w_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_y_x_preLineAct(z, y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_y_x_w_i_i1_elementAct(z, y, x, w, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long, long, long> z_y_x_w_i_i1_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXW, xj1 = t1.JXW;\n            long ws = DSW, wj = JW0, wj1 = t1.JW0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_y_x_preLineAct(z, y, x);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n                z_y_x_w_i_i1_elementAct(z, y, x, w, i, i1);\n            z_y_x_postLineAct(z, y, x);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_y_w_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_w_x_i_i1_elementAct(z, y, w, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_y_w_x_i_i1_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_w_x_i_i1_elementAct(z, y, w, x, i, i1);\n            z_y_w_postLineAct(z, y, w);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long, long, long> z_y_w_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_y_w_preLineAct(z, y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_w_x_i_i1_elementAct(z, y, w, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long, long, long> z_y_w_x_i_i1_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYW, yj1 = t1.JYW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_y_prePlaneAct(z, y);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_y_w_preLineAct(z, y, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_y_w_x_i_i1_elementAct(z, y, w, x, i, i1);\n            z_y_w_postLineAct(z, y, w);\n            }\n            z_y_postPlaneAct(z, y);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_w_x_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_w_x_y_i_i1_elementAct(z, w, x, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_w_x_y_i_i1_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_w_x_y_i_i1_elementAct(z, w, x, y, i, i1);\n            z_w_x_postLineAct(z, w, x);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long, long, long> z_w_x_y_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_w_x_preLineAct(z, w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_w_x_y_i_i1_elementAct(z, w, x, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long, long, long> z_w_x_y_i_i1_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            z_w_x_preLineAct(z, w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                z_w_x_y_i_i1_elementAct(z, w, x, y, i, i1);\n            z_w_x_postLineAct(z, w, x);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preVolumeAct();\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_w_y_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_w_y_x_i_i1_elementAct(z, w, y, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> z_w_y_x_i_i1_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_w_y_x_i_i1_elementAct(z, w, y, x, i, i1);\n            z_w_y_postLineAct(z, w, y);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long, long, long> z_w_y_x_i_i1_elementAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_w_y_preLineAct(z, w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_w_y_x_i_i1_elementAct(z, w, y, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(Tensor4Info t1, \n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long, long, long> z_w_y_x_i_i1_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            long zs = DSZ, zj = JZW, zj1 = t1.JZW;\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            z_preVolumeAct(z);\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            z_w_prePlaneAct(z, w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            z_w_y_preLineAct(z, w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                z_w_y_x_i_i1_elementAct(z, w, y, x, i, i1);\n            z_w_y_postLineAct(z, w, y);\n            }\n            z_w_postPlaneAct(z, w);\n            }\n            z_postVolumeAct(z);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_x_y_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_x_y_z_i_i1_elementAct(w, x, y, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_x_y_z_i_i1_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_x_y_z_i_i1_elementAct(w, x, y, z, i, i1);\n            w_x_y_postLineAct(w, x, y);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long, long, long> w_x_y_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_x_y_preLineAct(w, x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_x_y_z_i_i1_elementAct(w, x, y, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long, long, long> w_x_y_z_i_i1_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_x_y_preLineAct(w, x, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_x_y_z_i_i1_elementAct(w, x, y, z, i, i1);\n            w_x_y_postLineAct(w, x, y);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_x_z_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_x_z_y_i_i1_elementAct(w, x, z, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_x_z_y_i_i1_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_x_z_y_i_i1_elementAct(w, x, z, y, i, i1);\n            w_x_z_postLineAct(w, x, z);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long, long, long> w_x_z_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_x_z_preLineAct(w, x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_x_z_y_i_i1_elementAct(w, x, z, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long, long, long> w_x_z_y_i_i1_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWX, wj1 = t1.JWX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_x_prePlaneAct(w, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_x_z_preLineAct(w, x, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_x_z_y_i_i1_elementAct(w, x, z, y, i, i1);\n            w_x_z_postLineAct(w, x, z);\n            }\n            w_x_postPlaneAct(w, x);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_y_x_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_y_x_z_i_i1_elementAct(w, y, x, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_y_x_z_i_i1_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_y_x_z_i_i1_elementAct(w, y, x, z, i, i1);\n            w_y_x_postLineAct(w, y, x);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long, long, long> w_y_x_z_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_y_x_preLineAct(w, y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_y_x_z_i_i1_elementAct(w, y, x, z, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long, long, long> w_y_x_z_i_i1_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JXZ, xj1 = t1.JXZ;\n            long zs = DSZ, zj = JZ0, zj1 = t1.JZ0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_y_x_preLineAct(w, y, x);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n                w_y_x_z_i_i1_elementAct(w, y, x, z, i, i1);\n            w_y_x_postLineAct(w, y, x);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            prePlaneAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_y_z_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_y_z_x_i_i1_elementAct(w, y, z, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_y_z_x_i_i1_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_y_z_x_i_i1_elementAct(w, y, z, x, i, i1);\n            w_y_z_postLineAct(w, y, z);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long, long, long> w_y_z_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_y_z_preLineAct(w, y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_y_z_x_i_i1_elementAct(w, y, z, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long, long, long> w_y_z_x_i_i1_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWY, wj1 = t1.JWY;\n            long ys = DSY, yj = JYZ, yj1 = t1.JYZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_y_prePlaneAct(w, y);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_y_z_preLineAct(w, y, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_y_z_x_i_i1_elementAct(w, y, z, x, i, i1);\n            w_y_z_postLineAct(w, y, z);\n            }\n            w_y_postPlaneAct(w, y);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n            {\n            preLineAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_z_x_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_z_x_y_i_i1_elementAct(w, z, x, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_z_x_y_i_i1_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_z_x_y_i_i1_elementAct(w, z, x, y, i, i1);\n            w_z_x_postLineAct(w, z, x);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long, long, long> w_z_x_y_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_z_x_preLineAct(w, z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_z_x_y_i_i1_elementAct(w, z, x, y, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long, long, long> w_z_x_y_i_i1_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZX, zj1 = t1.JZX;\n            long xs = DSX, xj = JXY, xj1 = t1.JXY;\n            long ys = DSY, yj = JY0, yj1 = t1.JY0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n            {\n            w_z_x_preLineAct(w, z, x);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n                w_z_x_y_i_i1_elementAct(w, z, x, y, i, i1);\n            w_z_x_postLineAct(w, z, x);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(Tensor4Info t1, \n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(Tensor4Info t1, \n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long, long> i_i1_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws; i != we; i += wj, i1 += wj1)\n            {\n            preVolumeAct();\n            for (long ze = i + zs; i != ze; i += zj, i1 += zj1)\n            {\n            prePlaneAct();\n            for (long ye = i + ys; i != ye; i += yj, i1 += yj1)\n            {\n            preLineAct();\n            for (long xe = i + xs; i != xe; i += xj, i1 += xj1)\n                i_i1_elementAct(i, i1);\n            postLineAct();\n            }\n            postPlaneAct();\n            }\n            postVolumeAct();\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_z_y_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_z_y_x_i_i1_elementAct(w, z, y, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(Tensor4Info t1, \n                Action<long, long, long, long, long, long> w_z_y_x_i_i1_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_z_y_x_i_i1_elementAct(w, z, y, x, i, i1);\n            w_z_y_postLineAct(w, z, y);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long, long, long> w_z_y_x_i_i1_elementAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_z_y_preLineAct(w, z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_z_y_x_i_i1_elementAct(w, z, y, x, i, i1);\n            }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(Tensor4Info t1, \n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long, long, long> w_z_y_x_i_i1_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            long ws = DSW, wj = JWZ, wj1 = t1.JWZ;\n            long zs = DSZ, zj = JZY, zj1 = t1.JZY;\n            long ys = DSY, yj = JYX, yj1 = t1.JYX;\n            long xs = DSX, xj = JX0, xj1 = t1.JX0;\n            long i = FirstIndex, i1 = t1.FirstIndex;\n            for (long we = i + ws, w = FW; i != we; i += wj, i1 += wj1, w++)\n            {\n            w_preVolumeAct(w);\n            for (long ze = i + zs, z = FZ; i != ze; i += zj, i1 += zj1, z++)\n            {\n            w_z_prePlaneAct(w, z);\n            for (long ye = i + ys, y = FY; i != ye; i += yj, i1 += yj1, y++)\n            {\n            w_z_y_preLineAct(w, z, y);\n            for (long xe = i + xs, x = FX; i != xe; i += xj, i1 += xj1, x++)\n                w_z_y_x_i_i1_elementAct(w, z, y, x, i, i1);\n            w_z_y_postLineAct(w, z, y);\n            }\n            w_z_postPlaneAct(w, z);\n            }\n            w_postVolumeAct(w);\n            }\n        }\n\n        #endregion\n\n        #region Checking\n\n        public readonly void CheckMatchingSize(Tensor4Info t1)\n        {\n            if (Size != t1.Size) throw new ArgumentException(\"size mismatch\");\n        }\n\n        public readonly void CheckMatchingSize(Tensor4Info t1, Tensor4Info t2)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2);\n        }\n\n        public readonly void CheckMatchingSize(Tensor4Info t1, Tensor4Info t2, Tensor4Info t3)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2); CheckMatchingSize(t3);\n        }\n\n        public readonly bool HasMatchingLayout(Tensor4Info t1)\n        {\n            return First == t1.First && Origin == t1.Origin && Delta == t1.Delta;\n        }\n\n        public readonly bool HasMatchingLayout(Tensor4Info t1, Tensor4Info t2)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2);\n        }\n\n        public readonly bool HasMatchingLayout(Tensor4Info t1, Tensor4Info t2, Tensor4Info t3)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2) && HasMatchingLayout(t3);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Tensor4<Td>\n\n    /// <summary>\n    /// Generic tensor4 of elements with arbitrary stride.\n    /// All sizes are given as 4-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The tensor4 does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on tensor4s are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// 4 stride direction(s) are called DX, DY, aso.\n    /// </summary>\n    /// <typeparam name=\"Td\">data element type</typeparam>\n    [Serializable]\n    public partial struct Tensor4<Td> : IValidity, ITensor4<Td>, IArrayTensor4\n    {\n        public Td[] Data;\n        public Tensor4Info Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public Tensor4(Td[] data, Tensor4Info info)\n        {\n            Data = data;\n            Info = info;\n        }\n\n        /// <summary>\n        /// Construct tensor4 of specified size.\n        /// </summary>\n        public Tensor4(V4l size)\n            : this(new Td[size.X * size.Y * size.Z * size.W], new Tensor4Info(size))\n        { }\n\n        /// <summary>\n        /// Construct tensor4 of specified size.\n        /// </summary>\n        public Tensor4(V4i size)\n            : this((V4l)size)\n        { }\n\n        /// <summary>\n        /// Construct tensor4 with specified info.\n        /// </summary>\n        public Tensor4(Tensor4Info info)\n            : this(new Td[info.Count], new Tensor4Info(info))\n        { }\n\n        /// <summary>\n        /// Construct tensor4 of specified size.\n        /// </summary>\n        public Tensor4(long sx, long sy, long sz, long sw)\n            : this(new V4l(sx, sy, sz, sw))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Tensor4(Td[] data, long sx, long sy, long sz, long sw)\n            : this(data, new Tensor4Info(sx, sy, sz, sw))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and sets all elements to the supplied value.\n        /// </summary>\n        public Tensor4(long sx, long sy, long sz, long sw, Td value)\n            : this(new V4l(sx, sy, sz, sw), value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Tensor4(Td[] data, V4l size)\n            : this(data, new Tensor4Info(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Tensor4(Td[] data, V4i size)\n            : this(data, new Tensor4Info(size))\n        { }\n\n        /// <summary>\n        /// Construct tensor4 of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Tensor4(V4l size, Td value)\n            : this(new Td[size.X * size.Y * size.Z * size.W], new Tensor4Info(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Tensor4(V4i size, Td value)\n            : this((V4l)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Tensor4(Td[] data, long origin, V4l size, V4l delta)\n            : this(data, new Tensor4Info(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Tensor4(Td[] data, long origin, V4l size, V4l delta, V4l first)\n            : this(data, new Tensor4Info(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public Tensor4(long origin, V4l size, V4l delta)\n            : this(new Td[size.X * size.Y * size.Z * size.W],\n                   new Tensor4Info(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the tensor4 (4).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public V4l Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public V4l Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public V4l First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        /// <summary>\n        /// Returns true if the tensor4 has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the tensor4 does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly V4l End { get { return Info.E; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOO { get { return Info.OOOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOO { get { return Info.IOOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOO { get { return Info.OIOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOO { get { return Info.IIOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIO { get { return Info.OOIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIO { get { return Info.IOIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIO { get { return Info.OIIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIO { get { return Info.IIIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOI { get { return Info.OOOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOI { get { return Info.IOOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOI { get { return Info.OIOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOI { get { return Info.IIOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOII { get { return Info.OOII; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOII { get { return Info.IOII; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIII { get { return Info.OIII; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIII { get { return Info.IIII; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l E { get { return Info.E; } }\n\n        /// <summary>\n        /// Size in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Info.SX; } set { Info.SX = value; } }\n\n        /// <summary>\n        /// Size in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Info.SY; } set { Info.SY = value; } }\n\n        /// <summary>\n        /// Size in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SZ { readonly get { return Info.SZ; } set { Info.SZ = value; } }\n\n        /// <summary>\n        /// Size in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SW { readonly get { return Info.SW; } set { Info.SW = value; } }\n\n        /// <summary>\n        /// Delta in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Info.DX; } set { Info.DX = value; } }\n\n        /// <summary>\n        /// Delta in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Info.DY; } set { Info.DY = value; } }\n\n        /// <summary>\n        /// Delta in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DZ { readonly get { return Info.DZ; } set { Info.DZ = value; } }\n\n        /// <summary>\n        /// Delta in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DW { readonly get { return Info.DW; } set { Info.DW = value; } }\n\n        /// <summary>\n        /// First in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return Info.FX; } set { Info.FX = value; } }\n\n        /// <summary>\n        /// First in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY { readonly get { return Info.FY; } set { Info.FY = value; } }\n\n        /// <summary>\n        /// First in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FZ { readonly get { return Info.FZ; } set { Info.FZ = value; } }\n\n        /// <summary>\n        /// First in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FW { readonly get { return Info.FW; } set { Info.FW = value; } }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return Info.EX; } }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY { get { return Info.EY; } }\n\n        /// <summary>\n        /// End in dimension Z (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EZ { get { return Info.EZ; } }\n\n        /// <summary>\n        /// End in dimension W (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EW { get { return Info.EW; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Info.JX; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Info.JY; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZ { get { return Info.JZ; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JW { get { return Info.JW; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Info.DSX; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Info.DSY; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSZ { get { return Info.DSZ; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSW { get { return Info.DSW; } }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<Td> Elements\n        {\n            get\n            {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    yield return Data[i];\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    yield return Data[i];\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    yield return Data[i];\n                } } } }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(Td[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (Td[])value; }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Td this[V4l v]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + v.X * Info.Delta.X + v.Y * Info.Delta.Y + v.Z * Info.Delta.Z + v.W * Info.Delta.W];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + v.X * Info.Delta.X + v.Y * Info.Delta.Y + v.Z * Info.Delta.Z + v.W * Info.Delta.W] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Td this[V4i v]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y + (long)v.Z * Info.Delta.Z + (long)v.W * Info.Delta.W];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y + (long)v.Z * Info.Delta.Z + (long)v.W * Info.Delta.W] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at the specified index in the underlying data array.\n        /// </summary>\n        public readonly Td this[long index]\n        {\n            get\n            {\n                return Data[index];\n            }\n            set\n            {\n                Data[index] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Td this[long x, long y, long z, long w]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + x * Info.Delta.X + y * Info.Delta.Y + z * Info.Delta.Z + w * Info.Delta.W];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + x * Info.Delta.X + y * Info.Delta.Y + z * Info.Delta.Z + w * Info.Delta.W] = value;\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Td this[int x, int y, int z, int w]\n        {\n            get\n            {\n                return Data[Info.Origin\n                              + (long)x * Info.Delta.X + (long)y * Info.Delta.Y + (long)z * Info.Delta.Z + (long)w * Info.Delta.W];\n            }\n            set\n            {\n                Data[Info.Origin\n                       + (long)x * Info.Delta.X + (long)y * Info.Delta.Y + (long)z * Info.Delta.Z + (long)w * Info.Delta.W] = value;\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long, long, long> x_y_z_w_i_action)\n        {\n            Info.ForeachIndex(x_y_z_w_i_action);\n        }\n\n        public readonly void ForeachCoord(Action<V4l> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(Tensor4Info t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            Info.ForeachX(x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            Info.ForeachY(y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZ(\n                Action<long> z_elementAct)\n        {\n            Info.ForeachZ(z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachW(\n                Action<long> w_elementAct)\n        {\n            Info.ForeachW(w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct)\n        {\n            Info.ForeachXZ(\n                    x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZ(\n                    x_z_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct)\n        {\n            Info.ForeachXZ(\n                    x_preLineAct,\n                    x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZ(\n                    x_preLineAct,\n                    x_z_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long, long> x_w_elementAct)\n        {\n            Info.ForeachXW(\n                    x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long, long> x_w_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXW(\n                    x_w_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long> x_preLineAct,\n                Action<long, long> x_w_elementAct)\n        {\n            Info.ForeachXW(\n                    x_preLineAct,\n                    x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long> x_preLineAct,\n                Action<long, long> x_w_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXW(\n                    x_preLineAct,\n                    x_w_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct)\n        {\n            Info.ForeachYZ(\n                    y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZ(\n                    y_z_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct)\n        {\n            Info.ForeachYZ(\n                    y_preLineAct,\n                    y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZ(\n                    y_preLineAct,\n                    y_z_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long, long> y_w_elementAct)\n        {\n            Info.ForeachYW(\n                    y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long, long> y_w_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYW(\n                    y_w_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long> y_preLineAct,\n                Action<long, long> y_w_elementAct)\n        {\n            Info.ForeachYW(\n                    y_preLineAct,\n                    y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long> y_preLineAct,\n                Action<long, long> y_w_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYW(\n                    y_preLineAct,\n                    y_w_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct)\n        {\n            Info.ForeachZX(\n                    z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZX(\n                    z_x_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct)\n        {\n            Info.ForeachZX(\n                    z_preLineAct,\n                    z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZX(\n                    z_preLineAct,\n                    z_x_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct)\n        {\n            Info.ForeachZY(\n                    z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZY(\n                    z_y_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct)\n        {\n            Info.ForeachZY(\n                    z_preLineAct,\n                    z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZY(\n                    z_preLineAct,\n                    z_y_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long, long> z_w_elementAct)\n        {\n            Info.ForeachZW(\n                    z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long, long> z_w_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZW(\n                    z_w_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long> z_preLineAct,\n                Action<long, long> z_w_elementAct)\n        {\n            Info.ForeachZW(\n                    z_preLineAct,\n                    z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long> z_preLineAct,\n                Action<long, long> z_w_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZW(\n                    z_preLineAct,\n                    z_w_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long, long> w_x_elementAct)\n        {\n            Info.ForeachWX(\n                    w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long, long> w_x_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWX(\n                    w_x_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long> w_preLineAct,\n                Action<long, long> w_x_elementAct)\n        {\n            Info.ForeachWX(\n                    w_preLineAct,\n                    w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long> w_preLineAct,\n                Action<long, long> w_x_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWX(\n                    w_preLineAct,\n                    w_x_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long, long> w_y_elementAct)\n        {\n            Info.ForeachWY(\n                    w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long, long> w_y_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWY(\n                    w_y_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long> w_preLineAct,\n                Action<long, long> w_y_elementAct)\n        {\n            Info.ForeachWY(\n                    w_preLineAct,\n                    w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long> w_preLineAct,\n                Action<long, long> w_y_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWY(\n                    w_preLineAct,\n                    w_y_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long, long> w_z_elementAct)\n        {\n            Info.ForeachWZ(\n                    w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long, long> w_z_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWZ(\n                    w_z_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long> w_preLineAct,\n                Action<long, long> w_z_elementAct)\n        {\n            Info.ForeachWZ(\n                    w_preLineAct,\n                    w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long> w_preLineAct,\n                Action<long, long> w_z_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWZ(\n                    w_preLineAct,\n                    w_z_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            Info.ForeachXIndex(x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            Info.ForeachYIndex(y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long, long> z_i_elementAct)\n        {\n            Info.ForeachZIndex(z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachWIndex(\n                Action<long, long> w_i_elementAct)\n        {\n            Info.ForeachWIndex(w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    x_z_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    x_preLineAct,\n                    x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    x_preLineAct,\n                    x_z_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXWIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXWIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long, long, long> x_w_i_elementAct)\n        {\n            Info.ForeachXWIndex(\n                    x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long, long, long> x_w_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXWIndex(\n                    x_w_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_w_i_elementAct)\n        {\n            Info.ForeachXWIndex(\n                    x_preLineAct,\n                    x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_w_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXWIndex(\n                    x_preLineAct,\n                    x_w_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    y_z_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    y_preLineAct,\n                    y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    y_preLineAct,\n                    y_z_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYWIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYWIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long, long, long> y_w_i_elementAct)\n        {\n            Info.ForeachYWIndex(\n                    y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long, long, long> y_w_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYWIndex(\n                    y_w_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_w_i_elementAct)\n        {\n            Info.ForeachYWIndex(\n                    y_preLineAct,\n                    y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_w_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYWIndex(\n                    y_preLineAct,\n                    y_w_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    z_x_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    z_preLineAct,\n                    z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    z_preLineAct,\n                    z_x_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    z_y_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    z_preLineAct,\n                    z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    z_preLineAct,\n                    z_y_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZWIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZWIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long, long, long> z_w_i_elementAct)\n        {\n            Info.ForeachZWIndex(\n                    z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long, long, long> z_w_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZWIndex(\n                    z_w_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_w_i_elementAct)\n        {\n            Info.ForeachZWIndex(\n                    z_preLineAct,\n                    z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_w_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZWIndex(\n                    z_preLineAct,\n                    z_w_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long, long, long> w_x_i_elementAct)\n        {\n            Info.ForeachWXIndex(\n                    w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long, long, long> w_x_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWXIndex(\n                    w_x_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_x_i_elementAct)\n        {\n            Info.ForeachWXIndex(\n                    w_preLineAct,\n                    w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_x_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWXIndex(\n                    w_preLineAct,\n                    w_x_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long, long, long> w_y_i_elementAct)\n        {\n            Info.ForeachWYIndex(\n                    w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long, long, long> w_y_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWYIndex(\n                    w_y_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_y_i_elementAct)\n        {\n            Info.ForeachWYIndex(\n                    w_preLineAct,\n                    w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_y_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWYIndex(\n                    w_preLineAct,\n                    w_y_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long, long, long> w_z_i_elementAct)\n        {\n            Info.ForeachWZIndex(\n                    w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long, long, long> w_z_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWZIndex(\n                    w_z_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_z_i_elementAct)\n        {\n            Info.ForeachWZIndex(\n                    w_preLineAct,\n                    w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_z_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWZIndex(\n                    w_preLineAct,\n                    w_z_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            Info.ForeachXYZ(\n                    x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZ(\n                    x_y_z_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            Info.ForeachXYZ(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZ(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long, long, long> x_y_w_elementAct)\n        {\n            Info.ForeachXYW(\n                    x_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long, long, long> x_y_w_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYW(\n                    x_y_w_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_w_elementAct)\n        {\n            Info.ForeachXYW(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_w_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYW(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_w_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            Info.ForeachXZY(\n                    x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZY(\n                    x_z_y_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            Info.ForeachXZY(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZY(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long, long, long> x_z_w_elementAct)\n        {\n            Info.ForeachXZW(\n                    x_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long, long, long> x_z_w_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZW(\n                    x_z_w_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_w_elementAct)\n        {\n            Info.ForeachXZW(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_w_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZW(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_w_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long, long, long> x_w_y_elementAct)\n        {\n            Info.ForeachXWY(\n                    x_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long, long, long> x_w_y_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWY(\n                    x_w_y_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_y_elementAct)\n        {\n            Info.ForeachXWY(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_y_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWY(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_y_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long, long, long> x_w_z_elementAct)\n        {\n            Info.ForeachXWZ(\n                    x_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long, long, long> x_w_z_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWZ(\n                    x_w_z_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_z_elementAct)\n        {\n            Info.ForeachXWZ(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_z_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWZ(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_z_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            Info.ForeachYXZ(\n                    y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZ(\n                    y_x_z_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            Info.ForeachYXZ(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZ(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long, long, long> y_x_w_elementAct)\n        {\n            Info.ForeachYXW(\n                    y_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long, long, long> y_x_w_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXW(\n                    y_x_w_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_w_elementAct)\n        {\n            Info.ForeachYXW(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_w_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXW(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_w_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            Info.ForeachYZX(\n                    y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZX(\n                    y_z_x_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            Info.ForeachYZX(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZX(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long, long, long> y_z_w_elementAct)\n        {\n            Info.ForeachYZW(\n                    y_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long, long, long> y_z_w_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZW(\n                    y_z_w_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_w_elementAct)\n        {\n            Info.ForeachYZW(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_w_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZW(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_w_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long, long, long> y_w_x_elementAct)\n        {\n            Info.ForeachYWX(\n                    y_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long, long, long> y_w_x_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWX(\n                    y_w_x_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_x_elementAct)\n        {\n            Info.ForeachYWX(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_x_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWX(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_x_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long, long, long> y_w_z_elementAct)\n        {\n            Info.ForeachYWZ(\n                    y_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long, long, long> y_w_z_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWZ(\n                    y_w_z_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_z_elementAct)\n        {\n            Info.ForeachYWZ(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_z_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWZ(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_z_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            Info.ForeachZXY(\n                    z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXY(\n                    z_x_y_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            Info.ForeachZXY(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXY(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long, long, long> z_x_w_elementAct)\n        {\n            Info.ForeachZXW(\n                    z_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long, long, long> z_x_w_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXW(\n                    z_x_w_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_w_elementAct)\n        {\n            Info.ForeachZXW(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_w_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXW(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_w_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            Info.ForeachZYX(\n                    z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYX(\n                    z_y_x_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            Info.ForeachZYX(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYX(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long, long, long> z_y_w_elementAct)\n        {\n            Info.ForeachZYW(\n                    z_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long, long, long> z_y_w_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYW(\n                    z_y_w_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_w_elementAct)\n        {\n            Info.ForeachZYW(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_w_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYW(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_w_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long, long, long> z_w_x_elementAct)\n        {\n            Info.ForeachZWX(\n                    z_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long, long, long> z_w_x_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWX(\n                    z_w_x_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_x_elementAct)\n        {\n            Info.ForeachZWX(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_x_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWX(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_x_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long, long, long> z_w_y_elementAct)\n        {\n            Info.ForeachZWY(\n                    z_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long, long, long> z_w_y_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWY(\n                    z_w_y_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_y_elementAct)\n        {\n            Info.ForeachZWY(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_y_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWY(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_y_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long, long, long> w_x_y_elementAct)\n        {\n            Info.ForeachWXY(\n                    w_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long, long, long> w_x_y_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXY(\n                    w_x_y_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_y_elementAct)\n        {\n            Info.ForeachWXY(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_y_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXY(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_y_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long, long, long> w_x_z_elementAct)\n        {\n            Info.ForeachWXZ(\n                    w_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long, long, long> w_x_z_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXZ(\n                    w_x_z_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_z_elementAct)\n        {\n            Info.ForeachWXZ(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_z_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXZ(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_z_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long, long, long> w_y_x_elementAct)\n        {\n            Info.ForeachWYX(\n                    w_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long, long, long> w_y_x_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYX(\n                    w_y_x_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_x_elementAct)\n        {\n            Info.ForeachWYX(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_x_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYX(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_x_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long, long, long> w_y_z_elementAct)\n        {\n            Info.ForeachWYZ(\n                    w_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long, long, long> w_y_z_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYZ(\n                    w_y_z_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_z_elementAct)\n        {\n            Info.ForeachWYZ(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_z_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYZ(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_z_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long, long, long> w_z_x_elementAct)\n        {\n            Info.ForeachWZX(\n                    w_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long, long, long> w_z_x_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZX(\n                    w_z_x_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_x_elementAct)\n        {\n            Info.ForeachWZX(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_x_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZX(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_x_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long, long, long> w_z_y_elementAct)\n        {\n            Info.ForeachWZY(\n                    w_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long, long, long> w_z_y_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZY(\n                    w_z_y_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_y_elementAct)\n        {\n            Info.ForeachWZY(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_y_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZY(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_y_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_y_z_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long, long, long, long> x_y_w_i_elementAct)\n        {\n            Info.ForeachXYWIndex(\n                    x_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long, long, long, long> x_y_w_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYWIndex(\n                    x_y_w_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_w_i_elementAct)\n        {\n            Info.ForeachXYWIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_w_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYWIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_w_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_z_y_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long, long, long, long> x_z_w_i_elementAct)\n        {\n            Info.ForeachXZWIndex(\n                    x_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long, long, long, long> x_z_w_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZWIndex(\n                    x_z_w_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_w_i_elementAct)\n        {\n            Info.ForeachXZWIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_w_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZWIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_w_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXWYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXWYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long, long, long, long> x_w_y_i_elementAct)\n        {\n            Info.ForeachXWYIndex(\n                    x_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long, long, long, long> x_w_y_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWYIndex(\n                    x_w_y_i_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_y_i_elementAct)\n        {\n            Info.ForeachXWYIndex(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_y_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWYIndex(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_y_i_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXWZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXWZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long, long, long, long> x_w_z_i_elementAct)\n        {\n            Info.ForeachXWZIndex(\n                    x_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long, long, long, long> x_w_z_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWZIndex(\n                    x_w_z_i_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_z_i_elementAct)\n        {\n            Info.ForeachXWZIndex(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_z_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWZIndex(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_z_i_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_x_z_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long, long, long, long> y_x_w_i_elementAct)\n        {\n            Info.ForeachYXWIndex(\n                    y_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long, long, long, long> y_x_w_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXWIndex(\n                    y_x_w_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_w_i_elementAct)\n        {\n            Info.ForeachYXWIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_w_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXWIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_w_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_z_x_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long, long, long, long> y_z_w_i_elementAct)\n        {\n            Info.ForeachYZWIndex(\n                    y_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long, long, long, long> y_z_w_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZWIndex(\n                    y_z_w_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_w_i_elementAct)\n        {\n            Info.ForeachYZWIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_w_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZWIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_w_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYWXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYWXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long, long, long, long> y_w_x_i_elementAct)\n        {\n            Info.ForeachYWXIndex(\n                    y_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long, long, long, long> y_w_x_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWXIndex(\n                    y_w_x_i_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_x_i_elementAct)\n        {\n            Info.ForeachYWXIndex(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_x_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWXIndex(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_x_i_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYWZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYWZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long, long, long, long> y_w_z_i_elementAct)\n        {\n            Info.ForeachYWZIndex(\n                    y_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long, long, long, long> y_w_z_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWZIndex(\n                    y_w_z_i_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_z_i_elementAct)\n        {\n            Info.ForeachYWZIndex(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_z_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWZIndex(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_z_i_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_x_y_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long, long, long, long> z_x_w_i_elementAct)\n        {\n            Info.ForeachZXWIndex(\n                    z_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long, long, long, long> z_x_w_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXWIndex(\n                    z_x_w_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_w_i_elementAct)\n        {\n            Info.ForeachZXWIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_w_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXWIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_w_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_y_x_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long, long, long, long> z_y_w_i_elementAct)\n        {\n            Info.ForeachZYWIndex(\n                    z_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long, long, long, long> z_y_w_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYWIndex(\n                    z_y_w_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_w_i_elementAct)\n        {\n            Info.ForeachZYWIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_w_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYWIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_w_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZWXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZWXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long, long, long, long> z_w_x_i_elementAct)\n        {\n            Info.ForeachZWXIndex(\n                    z_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long, long, long, long> z_w_x_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWXIndex(\n                    z_w_x_i_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_x_i_elementAct)\n        {\n            Info.ForeachZWXIndex(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_x_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWXIndex(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_x_i_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZWYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZWYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long, long, long, long> z_w_y_i_elementAct)\n        {\n            Info.ForeachZWYIndex(\n                    z_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long, long, long, long> z_w_y_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWYIndex(\n                    z_w_y_i_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_y_i_elementAct)\n        {\n            Info.ForeachZWYIndex(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_y_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWYIndex(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_y_i_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long, long, long, long> w_x_y_i_elementAct)\n        {\n            Info.ForeachWXYIndex(\n                    w_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long, long, long, long> w_x_y_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXYIndex(\n                    w_x_y_i_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_y_i_elementAct)\n        {\n            Info.ForeachWXYIndex(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_y_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXYIndex(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_y_i_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long, long, long, long> w_x_z_i_elementAct)\n        {\n            Info.ForeachWXZIndex(\n                    w_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long, long, long, long> w_x_z_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXZIndex(\n                    w_x_z_i_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_z_i_elementAct)\n        {\n            Info.ForeachWXZIndex(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_z_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXZIndex(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_z_i_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long, long, long, long> w_y_x_i_elementAct)\n        {\n            Info.ForeachWYXIndex(\n                    w_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long, long, long, long> w_y_x_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYXIndex(\n                    w_y_x_i_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_x_i_elementAct)\n        {\n            Info.ForeachWYXIndex(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_x_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYXIndex(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_x_i_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long, long, long, long> w_y_z_i_elementAct)\n        {\n            Info.ForeachWYZIndex(\n                    w_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long, long, long, long> w_y_z_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYZIndex(\n                    w_y_z_i_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_z_i_elementAct)\n        {\n            Info.ForeachWYZIndex(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_z_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYZIndex(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_z_i_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long, long, long, long> w_z_x_i_elementAct)\n        {\n            Info.ForeachWZXIndex(\n                    w_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long, long, long, long> w_z_x_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZXIndex(\n                    w_z_x_i_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_x_i_elementAct)\n        {\n            Info.ForeachWZXIndex(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_x_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZXIndex(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_x_i_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long, long, long, long> w_z_y_i_elementAct)\n        {\n            Info.ForeachWZYIndex(\n                    w_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long, long, long, long> w_z_y_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZYIndex(\n                    w_z_y_i_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_y_i_elementAct)\n        {\n            Info.ForeachWZYIndex(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_y_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZYIndex(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_y_i_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long, long, long, long> x_y_z_w_elementAct)\n        {\n            Info.ForeachXYZW(\n                    x_y_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long, long, long, long> x_y_z_w_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYZW(\n                    x_y_z_w_elementAct,\n                    x_y_z_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long> x_y_z_w_elementAct)\n        {\n            Info.ForeachXYZW(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_z_preLineAct,\n                    x_y_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long> x_y_z_w_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYZW(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_z_preLineAct,\n                    x_y_z_w_elementAct,\n                    x_y_z_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long, long, long, long> x_y_w_z_elementAct)\n        {\n            Info.ForeachXYWZ(\n                    x_y_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long, long, long, long> x_y_w_z_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYWZ(\n                    x_y_w_z_elementAct,\n                    x_y_w_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long> x_y_w_z_elementAct)\n        {\n            Info.ForeachXYWZ(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_w_preLineAct,\n                    x_y_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long> x_y_w_z_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYWZ(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_w_preLineAct,\n                    x_y_w_z_elementAct,\n                    x_y_w_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long, long, long, long> x_z_y_w_elementAct)\n        {\n            Info.ForeachXZYW(\n                    x_z_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long, long, long, long> x_z_y_w_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZYW(\n                    x_z_y_w_elementAct,\n                    x_z_y_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long> x_z_y_w_elementAct)\n        {\n            Info.ForeachXZYW(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_y_preLineAct,\n                    x_z_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long> x_z_y_w_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZYW(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_y_preLineAct,\n                    x_z_y_w_elementAct,\n                    x_z_y_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long, long, long, long> x_z_w_y_elementAct)\n        {\n            Info.ForeachXZWY(\n                    x_z_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long, long, long, long> x_z_w_y_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZWY(\n                    x_z_w_y_elementAct,\n                    x_z_w_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long> x_z_w_y_elementAct)\n        {\n            Info.ForeachXZWY(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_w_preLineAct,\n                    x_z_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long> x_z_w_y_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZWY(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_w_preLineAct,\n                    x_z_w_y_elementAct,\n                    x_z_w_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long, long, long, long> x_w_y_z_elementAct)\n        {\n            Info.ForeachXWYZ(\n                    x_w_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long, long, long, long> x_w_y_z_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWYZ(\n                    x_w_y_z_elementAct,\n                    x_w_y_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long> x_w_y_z_elementAct)\n        {\n            Info.ForeachXWYZ(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_y_preLineAct,\n                    x_w_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long> x_w_y_z_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWYZ(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_y_preLineAct,\n                    x_w_y_z_elementAct,\n                    x_w_y_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long, long, long, long> x_w_z_y_elementAct)\n        {\n            Info.ForeachXWZY(\n                    x_w_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long, long, long, long> x_w_z_y_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWZY(\n                    x_w_z_y_elementAct,\n                    x_w_z_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long> x_w_z_y_elementAct)\n        {\n            Info.ForeachXWZY(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_z_preLineAct,\n                    x_w_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long> x_w_z_y_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWZY(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_z_preLineAct,\n                    x_w_z_y_elementAct,\n                    x_w_z_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long, long, long, long> y_x_z_w_elementAct)\n        {\n            Info.ForeachYXZW(\n                    y_x_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long, long, long, long> y_x_z_w_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXZW(\n                    y_x_z_w_elementAct,\n                    y_x_z_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long> y_x_z_w_elementAct)\n        {\n            Info.ForeachYXZW(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_z_preLineAct,\n                    y_x_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long> y_x_z_w_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXZW(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_z_preLineAct,\n                    y_x_z_w_elementAct,\n                    y_x_z_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long, long, long, long> y_x_w_z_elementAct)\n        {\n            Info.ForeachYXWZ(\n                    y_x_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long, long, long, long> y_x_w_z_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXWZ(\n                    y_x_w_z_elementAct,\n                    y_x_w_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long> y_x_w_z_elementAct)\n        {\n            Info.ForeachYXWZ(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_w_preLineAct,\n                    y_x_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long> y_x_w_z_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXWZ(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_w_preLineAct,\n                    y_x_w_z_elementAct,\n                    y_x_w_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long, long, long, long> y_z_x_w_elementAct)\n        {\n            Info.ForeachYZXW(\n                    y_z_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long, long, long, long> y_z_x_w_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZXW(\n                    y_z_x_w_elementAct,\n                    y_z_x_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long> y_z_x_w_elementAct)\n        {\n            Info.ForeachYZXW(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_x_preLineAct,\n                    y_z_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long> y_z_x_w_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZXW(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_x_preLineAct,\n                    y_z_x_w_elementAct,\n                    y_z_x_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long, long, long, long> y_z_w_x_elementAct)\n        {\n            Info.ForeachYZWX(\n                    y_z_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long, long, long, long> y_z_w_x_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZWX(\n                    y_z_w_x_elementAct,\n                    y_z_w_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long> y_z_w_x_elementAct)\n        {\n            Info.ForeachYZWX(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_w_preLineAct,\n                    y_z_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long> y_z_w_x_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZWX(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_w_preLineAct,\n                    y_z_w_x_elementAct,\n                    y_z_w_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long, long, long, long> y_w_x_z_elementAct)\n        {\n            Info.ForeachYWXZ(\n                    y_w_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long, long, long, long> y_w_x_z_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWXZ(\n                    y_w_x_z_elementAct,\n                    y_w_x_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long> y_w_x_z_elementAct)\n        {\n            Info.ForeachYWXZ(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_x_preLineAct,\n                    y_w_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long> y_w_x_z_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWXZ(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_x_preLineAct,\n                    y_w_x_z_elementAct,\n                    y_w_x_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long, long, long, long> y_w_z_x_elementAct)\n        {\n            Info.ForeachYWZX(\n                    y_w_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long, long, long, long> y_w_z_x_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWZX(\n                    y_w_z_x_elementAct,\n                    y_w_z_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long> y_w_z_x_elementAct)\n        {\n            Info.ForeachYWZX(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_z_preLineAct,\n                    y_w_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long> y_w_z_x_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWZX(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_z_preLineAct,\n                    y_w_z_x_elementAct,\n                    y_w_z_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long, long, long, long> z_x_y_w_elementAct)\n        {\n            Info.ForeachZXYW(\n                    z_x_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long, long, long, long> z_x_y_w_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXYW(\n                    z_x_y_w_elementAct,\n                    z_x_y_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long> z_x_y_w_elementAct)\n        {\n            Info.ForeachZXYW(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_y_preLineAct,\n                    z_x_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long> z_x_y_w_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXYW(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_y_preLineAct,\n                    z_x_y_w_elementAct,\n                    z_x_y_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long, long, long, long> z_x_w_y_elementAct)\n        {\n            Info.ForeachZXWY(\n                    z_x_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long, long, long, long> z_x_w_y_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXWY(\n                    z_x_w_y_elementAct,\n                    z_x_w_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long> z_x_w_y_elementAct)\n        {\n            Info.ForeachZXWY(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_w_preLineAct,\n                    z_x_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long> z_x_w_y_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXWY(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_w_preLineAct,\n                    z_x_w_y_elementAct,\n                    z_x_w_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long, long, long, long> z_y_x_w_elementAct)\n        {\n            Info.ForeachZYXW(\n                    z_y_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long, long, long, long> z_y_x_w_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYXW(\n                    z_y_x_w_elementAct,\n                    z_y_x_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long> z_y_x_w_elementAct)\n        {\n            Info.ForeachZYXW(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_x_preLineAct,\n                    z_y_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long> z_y_x_w_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYXW(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_x_preLineAct,\n                    z_y_x_w_elementAct,\n                    z_y_x_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long, long, long, long> z_y_w_x_elementAct)\n        {\n            Info.ForeachZYWX(\n                    z_y_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long, long, long, long> z_y_w_x_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYWX(\n                    z_y_w_x_elementAct,\n                    z_y_w_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long> z_y_w_x_elementAct)\n        {\n            Info.ForeachZYWX(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_w_preLineAct,\n                    z_y_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long> z_y_w_x_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYWX(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_w_preLineAct,\n                    z_y_w_x_elementAct,\n                    z_y_w_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long, long, long, long> z_w_x_y_elementAct)\n        {\n            Info.ForeachZWXY(\n                    z_w_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long, long, long, long> z_w_x_y_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWXY(\n                    z_w_x_y_elementAct,\n                    z_w_x_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long> z_w_x_y_elementAct)\n        {\n            Info.ForeachZWXY(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_x_preLineAct,\n                    z_w_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long> z_w_x_y_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWXY(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_x_preLineAct,\n                    z_w_x_y_elementAct,\n                    z_w_x_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long, long, long, long> z_w_y_x_elementAct)\n        {\n            Info.ForeachZWYX(\n                    z_w_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long, long, long, long> z_w_y_x_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWYX(\n                    z_w_y_x_elementAct,\n                    z_w_y_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long> z_w_y_x_elementAct)\n        {\n            Info.ForeachZWYX(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_y_preLineAct,\n                    z_w_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long> z_w_y_x_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWYX(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_y_preLineAct,\n                    z_w_y_x_elementAct,\n                    z_w_y_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long, long, long, long> w_x_y_z_elementAct)\n        {\n            Info.ForeachWXYZ(\n                    w_x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long, long, long, long> w_x_y_z_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXYZ(\n                    w_x_y_z_elementAct,\n                    w_x_y_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long> w_x_y_z_elementAct)\n        {\n            Info.ForeachWXYZ(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_y_preLineAct,\n                    w_x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long> w_x_y_z_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXYZ(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_y_preLineAct,\n                    w_x_y_z_elementAct,\n                    w_x_y_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long, long, long, long> w_x_z_y_elementAct)\n        {\n            Info.ForeachWXZY(\n                    w_x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long, long, long, long> w_x_z_y_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXZY(\n                    w_x_z_y_elementAct,\n                    w_x_z_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long> w_x_z_y_elementAct)\n        {\n            Info.ForeachWXZY(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_z_preLineAct,\n                    w_x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long> w_x_z_y_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXZY(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_z_preLineAct,\n                    w_x_z_y_elementAct,\n                    w_x_z_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long, long, long, long> w_y_x_z_elementAct)\n        {\n            Info.ForeachWYXZ(\n                    w_y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long, long, long, long> w_y_x_z_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYXZ(\n                    w_y_x_z_elementAct,\n                    w_y_x_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long> w_y_x_z_elementAct)\n        {\n            Info.ForeachWYXZ(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_x_preLineAct,\n                    w_y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long> w_y_x_z_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYXZ(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_x_preLineAct,\n                    w_y_x_z_elementAct,\n                    w_y_x_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long, long, long, long> w_y_z_x_elementAct)\n        {\n            Info.ForeachWYZX(\n                    w_y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long, long, long, long> w_y_z_x_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYZX(\n                    w_y_z_x_elementAct,\n                    w_y_z_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long> w_y_z_x_elementAct)\n        {\n            Info.ForeachWYZX(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_z_preLineAct,\n                    w_y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long> w_y_z_x_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYZX(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_z_preLineAct,\n                    w_y_z_x_elementAct,\n                    w_y_z_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long, long, long, long> w_z_x_y_elementAct)\n        {\n            Info.ForeachWZXY(\n                    w_z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long, long, long, long> w_z_x_y_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZXY(\n                    w_z_x_y_elementAct,\n                    w_z_x_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long> w_z_x_y_elementAct)\n        {\n            Info.ForeachWZXY(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_x_preLineAct,\n                    w_z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long> w_z_x_y_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZXY(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_x_preLineAct,\n                    w_z_x_y_elementAct,\n                    w_z_x_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long, long, long, long> w_z_y_x_elementAct)\n        {\n            Info.ForeachWZYX(\n                    w_z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long, long, long, long> w_z_y_x_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZYX(\n                    w_z_y_x_elementAct,\n                    w_z_y_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long> w_z_y_x_elementAct)\n        {\n            Info.ForeachWZYX(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_y_preLineAct,\n                    w_z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long> w_z_y_x_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZYX(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_y_preLineAct,\n                    w_z_y_x_elementAct,\n                    w_z_y_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXYZWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXYZWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct)\n        {\n            Info.ForeachXYZWIndex(\n                    x_y_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYZWIndex(\n                    x_y_z_w_i_elementAct,\n                    x_y_z_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct)\n        {\n            Info.ForeachXYZWIndex(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_z_preLineAct,\n                    x_y_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYZWIndex(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_z_preLineAct,\n                    x_y_z_w_i_elementAct,\n                    x_y_z_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXYWZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYWZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXYWZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct)\n        {\n            Info.ForeachXYWZIndex(\n                    x_y_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYWZIndex(\n                    x_y_w_z_i_elementAct,\n                    x_y_w_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct)\n        {\n            Info.ForeachXYWZIndex(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_w_preLineAct,\n                    x_y_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYWZIndex(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_w_preLineAct,\n                    x_y_w_z_i_elementAct,\n                    x_y_w_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXZYWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXZYWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct)\n        {\n            Info.ForeachXZYWIndex(\n                    x_z_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZYWIndex(\n                    x_z_y_w_i_elementAct,\n                    x_z_y_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct)\n        {\n            Info.ForeachXZYWIndex(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_y_preLineAct,\n                    x_z_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZYWIndex(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_y_preLineAct,\n                    x_z_y_w_i_elementAct,\n                    x_z_y_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXZWYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZWYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXZWYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct)\n        {\n            Info.ForeachXZWYIndex(\n                    x_z_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZWYIndex(\n                    x_z_w_y_i_elementAct,\n                    x_z_w_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct)\n        {\n            Info.ForeachXZWYIndex(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_w_preLineAct,\n                    x_z_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZWYIndex(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_w_preLineAct,\n                    x_z_w_y_i_elementAct,\n                    x_z_w_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXWYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWYZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXWYZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct)\n        {\n            Info.ForeachXWYZIndex(\n                    x_w_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWYZIndex(\n                    x_w_y_z_i_elementAct,\n                    x_w_y_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct)\n        {\n            Info.ForeachXWYZIndex(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_y_preLineAct,\n                    x_w_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWYZIndex(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_y_preLineAct,\n                    x_w_y_z_i_elementAct,\n                    x_w_y_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXWZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWZYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXWZYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct)\n        {\n            Info.ForeachXWZYIndex(\n                    x_w_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWZYIndex(\n                    x_w_z_y_i_elementAct,\n                    x_w_z_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct)\n        {\n            Info.ForeachXWZYIndex(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_z_preLineAct,\n                    x_w_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWZYIndex(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_z_preLineAct,\n                    x_w_z_y_i_elementAct,\n                    x_w_z_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYXZWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYXZWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct)\n        {\n            Info.ForeachYXZWIndex(\n                    y_x_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXZWIndex(\n                    y_x_z_w_i_elementAct,\n                    y_x_z_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct)\n        {\n            Info.ForeachYXZWIndex(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_z_preLineAct,\n                    y_x_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXZWIndex(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_z_preLineAct,\n                    y_x_z_w_i_elementAct,\n                    y_x_z_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYXWZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXWZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYXWZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct)\n        {\n            Info.ForeachYXWZIndex(\n                    y_x_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXWZIndex(\n                    y_x_w_z_i_elementAct,\n                    y_x_w_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct)\n        {\n            Info.ForeachYXWZIndex(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_w_preLineAct,\n                    y_x_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXWZIndex(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_w_preLineAct,\n                    y_x_w_z_i_elementAct,\n                    y_x_w_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYZXWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYZXWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct)\n        {\n            Info.ForeachYZXWIndex(\n                    y_z_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZXWIndex(\n                    y_z_x_w_i_elementAct,\n                    y_z_x_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct)\n        {\n            Info.ForeachYZXWIndex(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_x_preLineAct,\n                    y_z_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZXWIndex(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_x_preLineAct,\n                    y_z_x_w_i_elementAct,\n                    y_z_x_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYZWXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZWXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYZWXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct)\n        {\n            Info.ForeachYZWXIndex(\n                    y_z_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZWXIndex(\n                    y_z_w_x_i_elementAct,\n                    y_z_w_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct)\n        {\n            Info.ForeachYZWXIndex(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_w_preLineAct,\n                    y_z_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZWXIndex(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_w_preLineAct,\n                    y_z_w_x_i_elementAct,\n                    y_z_w_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYWXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWXZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYWXZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct)\n        {\n            Info.ForeachYWXZIndex(\n                    y_w_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWXZIndex(\n                    y_w_x_z_i_elementAct,\n                    y_w_x_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct)\n        {\n            Info.ForeachYWXZIndex(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_x_preLineAct,\n                    y_w_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWXZIndex(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_x_preLineAct,\n                    y_w_x_z_i_elementAct,\n                    y_w_x_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYWZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWZXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYWZXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct)\n        {\n            Info.ForeachYWZXIndex(\n                    y_w_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWZXIndex(\n                    y_w_z_x_i_elementAct,\n                    y_w_z_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct)\n        {\n            Info.ForeachYWZXIndex(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_z_preLineAct,\n                    y_w_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWZXIndex(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_z_preLineAct,\n                    y_w_z_x_i_elementAct,\n                    y_w_z_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZXYWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZXYWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct)\n        {\n            Info.ForeachZXYWIndex(\n                    z_x_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXYWIndex(\n                    z_x_y_w_i_elementAct,\n                    z_x_y_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct)\n        {\n            Info.ForeachZXYWIndex(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_y_preLineAct,\n                    z_x_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXYWIndex(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_y_preLineAct,\n                    z_x_y_w_i_elementAct,\n                    z_x_y_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZXWYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXWYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZXWYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct)\n        {\n            Info.ForeachZXWYIndex(\n                    z_x_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXWYIndex(\n                    z_x_w_y_i_elementAct,\n                    z_x_w_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct)\n        {\n            Info.ForeachZXWYIndex(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_w_preLineAct,\n                    z_x_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXWYIndex(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_w_preLineAct,\n                    z_x_w_y_i_elementAct,\n                    z_x_w_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZYXWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZYXWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct)\n        {\n            Info.ForeachZYXWIndex(\n                    z_y_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYXWIndex(\n                    z_y_x_w_i_elementAct,\n                    z_y_x_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct)\n        {\n            Info.ForeachZYXWIndex(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_x_preLineAct,\n                    z_y_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYXWIndex(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_x_preLineAct,\n                    z_y_x_w_i_elementAct,\n                    z_y_x_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZYWXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYWXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZYWXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct)\n        {\n            Info.ForeachZYWXIndex(\n                    z_y_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYWXIndex(\n                    z_y_w_x_i_elementAct,\n                    z_y_w_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct)\n        {\n            Info.ForeachZYWXIndex(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_w_preLineAct,\n                    z_y_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYWXIndex(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_w_preLineAct,\n                    z_y_w_x_i_elementAct,\n                    z_y_w_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZWXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWXYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZWXYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct)\n        {\n            Info.ForeachZWXYIndex(\n                    z_w_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWXYIndex(\n                    z_w_x_y_i_elementAct,\n                    z_w_x_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct)\n        {\n            Info.ForeachZWXYIndex(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_x_preLineAct,\n                    z_w_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWXYIndex(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_x_preLineAct,\n                    z_w_x_y_i_elementAct,\n                    z_w_x_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZWYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWYXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZWYXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct)\n        {\n            Info.ForeachZWYXIndex(\n                    z_w_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWYXIndex(\n                    z_w_y_x_i_elementAct,\n                    z_w_y_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct)\n        {\n            Info.ForeachZWYXIndex(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_y_preLineAct,\n                    z_w_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWYXIndex(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_y_preLineAct,\n                    z_w_y_x_i_elementAct,\n                    z_w_y_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWXYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXYZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWXYZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct)\n        {\n            Info.ForeachWXYZIndex(\n                    w_x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXYZIndex(\n                    w_x_y_z_i_elementAct,\n                    w_x_y_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct)\n        {\n            Info.ForeachWXYZIndex(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_y_preLineAct,\n                    w_x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXYZIndex(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_y_preLineAct,\n                    w_x_y_z_i_elementAct,\n                    w_x_y_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWXZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXZYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWXZYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct)\n        {\n            Info.ForeachWXZYIndex(\n                    w_x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXZYIndex(\n                    w_x_z_y_i_elementAct,\n                    w_x_z_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct)\n        {\n            Info.ForeachWXZYIndex(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_z_preLineAct,\n                    w_x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXZYIndex(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_z_preLineAct,\n                    w_x_z_y_i_elementAct,\n                    w_x_z_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWYXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYXZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWYXZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct)\n        {\n            Info.ForeachWYXZIndex(\n                    w_y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYXZIndex(\n                    w_y_x_z_i_elementAct,\n                    w_y_x_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct)\n        {\n            Info.ForeachWYXZIndex(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_x_preLineAct,\n                    w_y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYXZIndex(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_x_preLineAct,\n                    w_y_x_z_i_elementAct,\n                    w_y_x_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWYZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYZXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWYZXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct)\n        {\n            Info.ForeachWYZXIndex(\n                    w_y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYZXIndex(\n                    w_y_z_x_i_elementAct,\n                    w_y_z_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct)\n        {\n            Info.ForeachWYZXIndex(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_z_preLineAct,\n                    w_y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYZXIndex(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_z_preLineAct,\n                    w_y_z_x_i_elementAct,\n                    w_y_z_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWZXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZXYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWZXYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct)\n        {\n            Info.ForeachWZXYIndex(\n                    w_z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZXYIndex(\n                    w_z_x_y_i_elementAct,\n                    w_z_x_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct)\n        {\n            Info.ForeachWZXYIndex(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_x_preLineAct,\n                    w_z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZXYIndex(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_x_preLineAct,\n                    w_z_x_y_i_elementAct,\n                    w_z_x_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWZYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZYXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWZYXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct)\n        {\n            Info.ForeachWZYXIndex(\n                    w_z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZYXIndex(\n                    w_z_y_x_i_elementAct,\n                    w_z_y_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct)\n        {\n            Info.ForeachWZYXIndex(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_y_preLineAct,\n                    w_z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZYXIndex(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_y_preLineAct,\n                    w_z_y_x_i_elementAct,\n                    w_z_y_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4Window(V4l begin, V4l size)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4Window(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4(V4l begin, V4l size)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4Window(V4i begin, V4i size)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4Window(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4(V4i begin, V4i size)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4Window(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4Window(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4Window(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4Window(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4Window(V4l begin, V4l size, V4l delta, V4l first)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4Window(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4Window(V4i begin, V4i size, V4i delta, V4i first)\n        {\n            return new Tensor4<Td>(Data, Info.SubTensor4Window(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4Window(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4<Td>(Data,\n                            Info.SubTensor4Window(beginX, beginY, beginZ, beginW,\n                                           sizeX, sizeY, sizeZ, sizeW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4<Td>(Data,\n                            Info.SubTensor4(beginX, beginY, beginZ, beginW,\n                                               sizeX, sizeY, sizeZ, sizeW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4Window(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4<Td>(Data,\n                            Info.SubTensor4Window(beginX, beginY, beginZ, beginW,\n                                           sizeX, sizeY, sizeZ, sizeW,\n                                           deltaX, deltaY, deltaZ, deltaW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubTensor4(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4<Td>(Data,\n                            Info.SubTensor4(beginX, beginY, beginZ, beginW,\n                                               sizeX, sizeY, sizeZ, sizeW,\n                                               deltaX, deltaY, deltaZ, deltaW));\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td> AsVector()\n        {\n            return new Vector<Td>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td> SubVector(V4l origin, long size, long delta)\n        {\n            return new Vector<Td>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td> SubVector(V4i origin, long size, long delta)\n        {\n            return new Vector<Td>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubYZWVolume(long x)\n        {\n            return new Volume<Td>(Data, Info.SubYZWVolume(x));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubYZWVolumeAsReadOnlyTensor4(long x, long sizex)\n        {\n            return new Tensor4<Td>(Data, Info.SubYZWVolumeAsReadOnlyTensor4(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td> SubYZWVolumeWindow(long x)\n        {\n            return new Volume<Td>(Data, Info.SubYZWVolumeWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubYZWVolumeAsReadOnlyTensor4Window(long x, long sizex)\n        {\n            return new Tensor4<Td>(Data, Info.SubYZWVolumeAsReadOnlyTensor4Window(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubXZWVolume(long y)\n        {\n            return new Volume<Td>(Data, Info.SubXZWVolume(y));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubXZWVolumeAsReadOnlyTensor4(long y, long sizey)\n        {\n            return new Tensor4<Td>(Data, Info.SubXZWVolumeAsReadOnlyTensor4(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td> SubXZWVolumeWindow(long y)\n        {\n            return new Volume<Td>(Data, Info.SubXZWVolumeWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubXZWVolumeAsReadOnlyTensor4Window(long y, long sizey)\n        {\n            return new Tensor4<Td>(Data, Info.SubXZWVolumeAsReadOnlyTensor4Window(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubXYWVolume(long z)\n        {\n            return new Volume<Td>(Data, Info.SubXYWVolume(z));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubXYWVolumeAsReadOnlyTensor4(long z, long sizez)\n        {\n            return new Tensor4<Td>(Data, Info.SubXYWVolumeAsReadOnlyTensor4(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td> SubXYWVolumeWindow(long z)\n        {\n            return new Volume<Td>(Data, Info.SubXYWVolumeWindow(z));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubXYWVolumeAsReadOnlyTensor4Window(long z, long sizez)\n        {\n            return new Tensor4<Td>(Data, Info.SubXYWVolumeAsReadOnlyTensor4Window(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td> SubXYZVolume(long w)\n        {\n            return new Volume<Td>(Data, Info.SubXYZVolume(w));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubXYZVolumeAsReadOnlyTensor4(long w, long sizew)\n        {\n            return new Tensor4<Td>(Data, Info.SubXYZVolumeAsReadOnlyTensor4(w, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td> SubXYZVolumeWindow(long w)\n        {\n            return new Volume<Td>(Data, Info.SubXYZVolumeWindow(w));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubXYZVolumeAsReadOnlyTensor4Window(long w, long sizew)\n        {\n            return new Tensor4<Td>(Data, Info.SubXYZVolumeAsReadOnlyTensor4Window(w, sizew));\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubZWMatrixAsReadOnlyTensor4(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4<Td>(Data, Info.SubZWMatrixAsReadOnlyTensor4(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubZWMatrixAsReadOnlyTensor4Window(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4<Td>(Data, Info.SubZWMatrixAsReadOnlyTensor4Window(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubYWMatrixAsReadOnlyTensor4(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4<Td>(Data, Info.SubYWMatrixAsReadOnlyTensor4(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubYWMatrixAsReadOnlyTensor4Window(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4<Td>(Data, Info.SubYWMatrixAsReadOnlyTensor4Window(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubYZMatrixAsReadOnlyTensor4(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4<Td>(Data, Info.SubYZMatrixAsReadOnlyTensor4(x, w, sizex, sizew));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubYZMatrixAsReadOnlyTensor4Window(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4<Td>(Data, Info.SubYZMatrixAsReadOnlyTensor4Window(x, w, sizex, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubXWMatrixAsReadOnlyTensor4(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4<Td>(Data, Info.SubXWMatrixAsReadOnlyTensor4(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubXWMatrixAsReadOnlyTensor4Window(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4<Td>(Data, Info.SubXWMatrixAsReadOnlyTensor4Window(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubXZMatrixAsReadOnlyTensor4(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4<Td>(Data, Info.SubXZMatrixAsReadOnlyTensor4(y, w, sizey, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubXZMatrixAsReadOnlyTensor4Window(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4<Td>(Data, Info.SubXZMatrixAsReadOnlyTensor4Window(y, w, sizey, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> SubXYMatrixAsReadOnlyTensor4(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4<Td>(Data, Info.SubXYMatrixAsReadOnlyTensor4(z, w, sizez, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> SubXYMatrixAsReadOnlyTensor4Window(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4<Td>(Data, Info.SubXYMatrixAsReadOnlyTensor4Window(z, w, sizez, sizew));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4l begin, V4l size)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(V4l begin, V4l size)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4i begin, V4i size)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(V4i begin, V4i size)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4l begin, V4l size, V4l delta, V4l first)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4i begin, V4i size, V4i delta, V4i first)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4<Td, T1>(Data,\n                            Info.SubTensor4Window(beginX, beginY, beginZ, beginW,\n                                           sizeX, sizeY, sizeZ, sizeW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4<Td, T1>(Data,\n                            Info.SubTensor4(beginX, beginY, beginZ, beginW,\n                                               sizeX, sizeY, sizeZ, sizeW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4<Td, T1>(Data,\n                            Info.SubTensor4Window(beginX, beginY, beginZ, beginW,\n                                           sizeX, sizeY, sizeZ, sizeW,\n                                           deltaX, deltaY, deltaZ, deltaW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4<Td, T1>(Data,\n                            Info.SubTensor4(beginX, beginY, beginZ, beginW,\n                                               sizeX, sizeY, sizeZ, sizeW,\n                                               deltaX, deltaY, deltaZ, deltaW));\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, T1> AsVector<T1>()\n        {\n            return new Vector<Td, T1>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V4l origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V4i origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYZWVolume<T1>(long x)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYZWVolume(x));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYZWVolumeAsReadOnlyTensor4<T1>(long x, long sizex)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYZWVolumeAsReadOnlyTensor4(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYZWVolumeWindow<T1>(long x)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYZWVolumeWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYZWVolumeAsReadOnlyTensor4Window<T1>(long x, long sizex)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYZWVolumeAsReadOnlyTensor4Window(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXZWVolume<T1>(long y)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXZWVolume(y));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXZWVolumeAsReadOnlyTensor4<T1>(long y, long sizey)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXZWVolumeAsReadOnlyTensor4(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXZWVolumeWindow<T1>(long y)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXZWVolumeWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXZWVolumeAsReadOnlyTensor4Window<T1>(long y, long sizey)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXZWVolumeAsReadOnlyTensor4Window(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYWVolume<T1>(long z)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYWVolume(z));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYWVolumeAsReadOnlyTensor4<T1>(long z, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYWVolumeAsReadOnlyTensor4(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYWVolumeWindow<T1>(long z)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYWVolumeWindow(z));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYWVolumeAsReadOnlyTensor4Window<T1>(long z, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYWVolumeAsReadOnlyTensor4Window(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYZVolume<T1>(long w)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYZVolume(w));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYZVolumeAsReadOnlyTensor4<T1>(long w, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYZVolumeAsReadOnlyTensor4(w, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYZVolumeWindow<T1>(long w)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYZVolumeWindow(w));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYZVolumeAsReadOnlyTensor4Window<T1>(long w, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYZVolumeAsReadOnlyTensor4Window(w, sizew));\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubZWMatrixAsReadOnlyTensor4<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubZWMatrixAsReadOnlyTensor4(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubZWMatrixAsReadOnlyTensor4Window<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubZWMatrixAsReadOnlyTensor4Window(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYWMatrixAsReadOnlyTensor4<T1>(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYWMatrixAsReadOnlyTensor4(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYWMatrixAsReadOnlyTensor4Window<T1>(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYWMatrixAsReadOnlyTensor4Window(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYZMatrixAsReadOnlyTensor4<T1>(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYZMatrixAsReadOnlyTensor4(x, w, sizex, sizew));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYZMatrixAsReadOnlyTensor4Window<T1>(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYZMatrixAsReadOnlyTensor4Window(x, w, sizex, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXWMatrixAsReadOnlyTensor4<T1>(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXWMatrixAsReadOnlyTensor4(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXWMatrixAsReadOnlyTensor4Window<T1>(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXWMatrixAsReadOnlyTensor4Window(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXZMatrixAsReadOnlyTensor4<T1>(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXZMatrixAsReadOnlyTensor4(y, w, sizey, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXZMatrixAsReadOnlyTensor4Window<T1>(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXZMatrixAsReadOnlyTensor4Window(y, w, sizey, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYMatrixAsReadOnlyTensor4<T1>(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYMatrixAsReadOnlyTensor4(z, w, sizez, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYMatrixAsReadOnlyTensor4Window<T1>(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYMatrixAsReadOnlyTensor4Window(z, w, sizez, sizew));\n        }\n\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td> Copy()\n        {\n            return new Tensor4<Td>(Info.S).Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td> CopyWindow()\n        {\n            return new Tensor4<Td>(Info.S)\n                    { F = F,  }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<T1> Map<T1>(Func<Td, T1> fun)\n        {\n            return new Tensor4<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original Tensor4.\n        /// </summary>\n        public readonly Tensor4<T1> MapWindow<T1>(Func<Td, T1> fun)\n        {\n            return new Tensor4<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Returns a tensor repeated in each dimension by the specified\n        /// count.\n        /// </summary>\n        public readonly Tensor4<Td> Repeated(V4l count)\n        {\n            var size = Size;\n            count *= size;\n            var t = new Tensor4<Td>(count);\n            V4l p;\n            for (p.W = 0; p.W < count.W; p.W += size.W)\n            for (p.Z = 0; p.Z < count.Z; p.Z += size.Z)\n            for (p.Y = 0; p.Y < count.Y; p.Y += size.Y)\n            for (p.X = 0; p.X < count.X; p.X += size.X)\n                t.SubTensor4(p, size).Set(this);\n            return t;\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the tensor4.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> Apply(Func<Td, Td> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long we = i + Info.DSW, wj = Info.JW; i != we; i += wj)\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj)\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.SX; i != xe; i++)\n                    Data[i] = element_elementFun(Data[i]);\n            }\n            else\n            {\n                for (long we = i + Info.DSW, wj = Info.JW; i != we; i += wj)\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj)\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj)\n                    Data[i] = element_elementFun(Data[i]);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original tensor4 and the supplied tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> Apply<T1>(\n                Tensor4<T1> t1, Func<Td, T1, Td> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i]);\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Data[i1]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original tensor4 and the supplied tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> Apply<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<Td, T1, Td> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element_element1_elementFun(Data[i], t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the tensor4.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> ApplyByCoord(Func<Td, V4l, Td> element_crd_elementFun)\n        {\n            long i = FirstIndex; V4l vi;\n            if (Info.JX == 1)\n            {\n                vi.W = First.W;\n                for (long we = i + Info.DSW, wj = Info.JW; i != we; i += wj, vi.W++)\n                {\n                vi.Z = First.Z;\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj, vi.Z++)\n                {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.SX; i != xe; i++, vi.X++)\n                    Data[i] = element_crd_elementFun(Data[i], vi);\n                }\n                }\n                }\n            }\n            else\n            {\n                vi.W = First.W;\n                for (long we = i + Info.DSW, wj = Info.JW; i != we; i += wj, vi.W++)\n                {\n                vi.Z = First.Z;\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj, vi.Z++)\n                {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj, vi.X++)\n                {\n                    Data[i] = element_crd_elementFun(Data[i], vi);\n                }\n                }\n                }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> ApplyByCoord(Func<Td, long, long, long, long, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long we = i + Info.DSW, wj = Info.JW, w = Info.FW; i != we; i += wj, w++)\n                for (long ze = i + Info.DSZ, zj = Info.JZ, z = Info.FZ; i != ze; i += zj, z++)\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    Data[i] = fun(Data[i], x, y, z, w);\n            }\n            else\n            {\n                for (long we = i + Info.DSW, wj = Info.JW, w = Info.FW; i != we; i += wj, w++)\n                for (long ze = i + Info.DSZ, zj = Info.JZ, z = Info.FZ; i != ze; i += zj, z++)\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.DSX, xj = Info.JX, x = Info.FX; i != xe; i += xj, x++)\n                    Data[i] = fun(Data[i], x, y, z, w);\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> Set(Td v)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Data[i] = v;\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    Data[i] = v;\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Data[i] = v;\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByCoord(Func<long, long, long, long, Td> x_y_z_w_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Data[i] = x_y_z_w_elementFun(x, y, z, w);\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    Data[i] = x_y_z_w_elementFun(x, y, z, w);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Data[i] = x_y_z_w_elementFun(x, y, z, w);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByCoord(Func<V4l, Td> crd_elementFun)\n        {\n            long i = FirstIndex; V4l v;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    Data[i] = crd_elementFun(v);\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.W = FW; for (long we = i + ws; i != we; i++, v.W++) {\n                    Data[i] = crd_elementFun(v);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    Data[i] = crd_elementFun(v);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByCoord<Tw, Tz, Ty>(\n                Func<long, Tw> wFun,\n                Func<long, long, Tw, Tz> zFun,\n                Func<long, long, long, Tw, Tz, Ty> yFun,\n                Func<long, long, long, long, Tw, Tz, Ty, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = Info.FW; i != we; i += wj, w++) {\n                    var wVal = wFun(w);\n                for (long ze = i + zs, z = Info.FZ; i != ze; i += zj, z++) {\n                    var zVal = zFun(w, z, wVal);\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(w, z, y, wVal, zVal);\n                for (long xe = i + xs, x = Info.FX; i != xe; i++, x++) {\n                    Data[i] = fun(w, z, y, x, wVal, zVal, yVal);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = Info.FW; i != we; i += wj, w++) {\n                    var wVal = wFun(w);\n                for (long ze = i + zs, z = Info.FZ; i != ze; i += zj, z++) {\n                    var zVal = zFun(w, z, wVal);\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(w, z, y, wVal, zVal);\n                for (long xe = i + xs, x = Info.FX; i != xe; i += xj, x++) {\n                    Data[i] = fun(w, z, y, x, wVal, zVal, yVal);\n                } } } }\n            }\n\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex(Func<long, Td> index_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Data[i] = index_elementFun(i);\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    Data[i] = index_elementFun(i);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Data[i] = index_elementFun(i);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly Tensor4<Td> Set(ITensor4<Td> it1)\n        {\n            if (it1 is Tensor4<Td>) return Set((Tensor4<Td>)it1);\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Data[i] = it1[x, y, z, w];\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    Data[i] = it1[x, y, z, w];\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Data[i] = it1[x, y, z, w];\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> Set(Tensor4<Td> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = t1.Data[i];\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        Data[i] = t1.Data[i];\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = t1.Data[i];\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = t1.Data[i1];\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Data[i] = t1.Data[i1];\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = t1.Data[i1];\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// the elements of the supplied tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap<T1>(\n                Tensor4<T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = element1_elementFun(t1.Data[i]);\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element1_elementFun(t1.Data[i1]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1>(\n                Tensor4<T1> t1, Func<long, Td> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_elementFun(i);\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        Data[i] = index1_elementFun(i);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_elementFun(i);\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = index1_elementFun(i1);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> Set<T1>(Tensor4<T1, Td> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = t1.Getter(t1.Data, i1);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// the elements of the supplied tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = element1_elementFun(t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<long, Td> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Data[i] = index1_elementFun(i1);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Data[i] = index1_elementFun(i1);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap2<T1, T2>(\n                    Tensor4<T1> t1, Tensor4<T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n            Data[i] = element1_element2_elementFun(t1.Data[i], t2.Data[i]);\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Data[i2]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1, T2>(\n                Tensor4<T1> t1, Tensor4<T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_index2_elementFun(i, i);\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap2<T1, T2d, T2>(\n                    Tensor4<T1> t1, Tensor4<T2d, T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1, T2d, T2>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap2<T1d, T1, T2>(\n                    Tensor4<T1d, T1> t1, Tensor4<T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1d, T1, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap2<T1d, T1, T2d, T2>(\n                    Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2,\n                    Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Data[i] = element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1d, T1, T2d, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Data[i] = index1_index2_elementFun(i1, i2);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap3<T1, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info, t3.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i], t2.Data[i], t3.Data[i]);\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            if (Info.HasMatchingLayout(t1.Info, t2.Info, t3.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        Data[i] = index1_index2_index3_elementFun(i, i, i);\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap3<T1, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap3<T1, T2d, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1, T2d, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap3<T1, T2d, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1, T2d, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap3<T1d, T1, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1d, T1, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap3<T1d, T1, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1d, T1, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap3<T1d, T1, T2d, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1d, T1, T2d, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetMap3<T1d, T1, T2d, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Data[i] = element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Data[i] = index1_index2_index3_elementFun(i1, i2, i3);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the tensor4 to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly Tensor4<Td> SetConvolution<Ti, Tf, Tm, Ts>(\n                Tensor4<Ti> image, Tensor4<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Td> castFun)\n        {\n            Info.CheckMatchingSize(new Tensor4Info(V4l.One + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.SubTensor4(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Tx, Ty, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Data[i3], tw.Data[i4]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Data[i3], tw.Data[i4]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Tx, Ty, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Data[i3], tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Data[i3], tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Tx, Ty, Tzd, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3), tw.Data[i4]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3), tw.Data[i4]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Tx, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Tx, Tyd, Ty, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3], tw.Data[i4]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3], tw.Data[i4]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Tx, Tyd, Ty, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3], tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3], tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Data[i4]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Data[i4]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Txd, Tx, Ty, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3], tw.Data[i4]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3], tw.Data[i4]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Txd, Tx, Ty, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3], tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3], tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Txd, Tx, Ty, Tzd, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3), tw.Data[i4]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3), tw.Data[i4]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Txd, Tx, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Txd, Tx, Tyd, Ty, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3], tw.Data[i4]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3], tw.Data[i4]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Txd, Tx, Tyd, Ty, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3], tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3], tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Data[i4]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Data[i4]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td> SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Data[i] = fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4));\n                } } } }\n            }\n            return this;\n        }\n\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Td, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Data[i]));\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, long, long, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z, w));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z, w));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z, w));\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, V4l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V4l v;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.W = FW; for (long we = i + ws; i != we; i++, v.W++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Tensor4<T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                    } } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Tensor4<T1d, T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Td, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Data[i]));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, long, long, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z, w));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z, w));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Data[i], x, y, z, w));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Td, V4l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V4l v;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.W = FW; for (long we = i + ws; i != we; i++, v.W++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Data[i], v));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Tensor4<T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            if (Info.HasMatchingLayout(t1.Info))\n            {\n                long i = FirstIndex;\n                if (Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else if (Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                    for (long we = i + ws; i != we; i++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY;\n                    long xs = Info.DSX, xj = Info.JX;\n                    for (long we = i + ws; i != we; i += wj) {\n                    for (long ze = i + zs; i != ze; i += zj) {\n                    for (long ye = i + ys; i != ye; i += yj) {\n                    for (long xe = i + xs; i != xe; i += xj) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n            }\n            else\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Tensor4<T1d, T1> t1,\n            Func<Td, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Data[i], t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creator Functions\n\n        /// <summary>\n        /// Create a new tensor4 as copy of the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Create(\n                Tensor4<Td> t1)\n        {\n            return new Tensor4<Td>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 as copy of the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Create<T1d>(\n                Tensor4<T1d, Td> t1)\n        {\n            return new Tensor4<Td>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map<T1>(\n                Tensor4<T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1>(\n                Tensor4<T1> t1, Func<long, Td> index1_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<T1, Td> element1_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<long, Td> index1_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map2<T1, T2>(\n                Tensor4<T1> t1, Tensor4<T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1, T2>(\n                Tensor4<T1> t1, Tensor4<T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map2<T1, T2d, T2>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1, T2d, T2>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map2<T1d, T1, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1d, T1, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map2<T1d, T1, T2d, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2,\n                Func<T1, T2, Td> element1_element2_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1d, T1, T2d, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2,\n                Func<long, long, Td> index1_index2_fun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map3<T1, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map3<T1, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map3<T1, T2d, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1, T2d, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map3<T1, T2d, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1, T2d, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map3<T1d, T1, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1d, T1, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map3<T1d, T1, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1d, T1, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map3<T1d, T1, T2d, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1d, T1, T2d, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td> Map3<T1d, T1, T2d, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Td> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Td> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to the coordinates of\n        /// the elements the newly created tensor4.\n        /// </summary>\n        public static Tensor4<Td> Create(V4l size, Func<V4l, Td> fun)\n        {\n            return new Tensor4<Td>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new Tensor4 by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting Tensor4.\n        /// </summary>\n        public static Tensor4<Td> CreateConvolution<Ti, Tf, Tm, Ts>(\n                Tensor4<Ti> image, Tensor4<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Td> castFun)\n        {\n            V4l size = 1 + image.S - filter.S;\n            if (size.W <= 0 ||size.Z <= 0 ||size.Y <= 0 ||size.X <= 0) throw new Exception(\"filter to large\");\n            return new Tensor4<Td>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Tx, Ty, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Ty, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Tx, Ty, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Ty, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Tx, Ty, Tzd, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Ty, Tzd, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Tx, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Ty, Tzd, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Tx, Tyd, Ty, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Tx, Tyd, Ty, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Txd, Tx, Ty, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Txd, Tx, Ty, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Txd, Tx, Ty, Tzd, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tzd, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Txd, Tx, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tzd, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Td> fun)\n        {\n            return new Tensor4<Td>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        #endregion\n\n        #region Sampling\n\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return SampleRaw16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl);\n        }\n\n        /// <summary>\n        /// Sample the tensor4 using 16 samples and the supplied\n        /// interpolation functions. If only integer coordinates are\n        /// supplied the returned value is the same as the indexer\n        /// of the tensor4, i.e. voxel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            double wid = Fun.Floor(w); long wi = (long)wid; double wf = w - wid; long dw = Info.Delta.W;\n            long i = Info.Origin + xi * dx + yi * dy + zi * dz + wi * dw;\n            long ix = i + dx, iy = i + dy, ixy = ix + dy;\n            long iz = i + dz, ixz = ix + dz, iyz = iy + dz, ixyz = ixy + dz;\n            return wipl(wf, zipl(zf, yipl(yf, xipl(xf, Data[i], Data[ix]),\n                                              xipl(xf, Data[iy], Data[ixy])),\n                                     yipl(yf, xipl(xf, Data[iz], Data[ixz]),\n                                              xipl(xf, Data[iyz], Data[ixyz]))),\n                            zipl(zf, yipl(yf, xipl(xf, Data[i + dw], Data[ix + dw]),\n                                              xipl(xf, Data[iy + dw], Data[ixy + dw])),\n                                     yipl(yf, xipl(xf, Data[iz + dw], Data[ixz + dw]),\n                                              xipl(xf, Data[iyz + dw], Data[ixyz + dw]))));\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return Sample16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return Sample16(x, y, z, w, xipl, yipl, zipl, wipl,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_wIndexFun)\n        {\n            return Sample16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun,\n                            index_min_max_delta_zIndexFun,\n                            index_min_max_delta_wIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the tensor4 using 16 neighbouring samples and the\n        /// supplied interpolation functions and border handling functions.\n        /// If only integer coordinates are supplied the returned value is\n        /// the same as the indexer of the tensor4, i.e. voxel centers are\n        /// assumed to be on integer coordinates.\n        /// </summary>\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, Td, Td, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_wIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            double wid = Fun.Floor(w); long wi = (long)wid; double wf = w - wid; long dw1 = Info.Delta.W;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1 + wi * dw1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1); dx.E0 += i; dx.E1 += i;\n            var dyzw = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                    index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1),\n                                    index_min_max_delta_wIndexFun(wi, FW, EW, dw1));\n            return wipl(wf, zipl(zf, yipl(yf, xipl(xf, Data[dx.E0 + dyzw.E0], Data[dx.E1 + dyzw.E0]),\n                                              xipl(xf, Data[dx.E0 + dyzw.E1], Data[dx.E1 + dyzw.E1])),\n                                     yipl(yf, xipl(xf, Data[dx.E0 + dyzw.E2], Data[dx.E1 + dyzw.E2]),\n                                              xipl(xf, Data[dx.E0 + dyzw.E3], Data[dx.E1 + dyzw.E3]))),\n                            zipl(zf, yipl(yf, xipl(xf, Data[dx.E0 + dyzw.E4], Data[dx.E1 + dyzw.E4]),\n                                              xipl(xf, Data[dx.E0 + dyzw.E5], Data[dx.E1 + dyzw.E5])),\n                                     yipl(yf, xipl(xf, Data[dx.E0 + dyzw.E6], Data[dx.E1 + dyzw.E6]),\n                                              xipl(xf, Data[dx.E0 + dyzw.E7], Data[dx.E1 + dyzw.E7]))));\n        }\n\n        #endregion\n\n        #region ITensor4\n\n        /// <summary>\n        /// Dimension of the generic Tensor4.\n        /// </summary>\n        public readonly V4l Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(long x, long y, long z, long w)\n        {\n            return (object)this[x, y, z, w];\n        }\n\n        public readonly void SetValue(object value, long x, long y, long z, long w)\n        {\n            this[x, y, z, w] = (Td)value;\n        }\n\n        public readonly object GetValue(V4l v)\n        {\n            return (object)this[v];\n        }\n\n        public readonly void SetValue(object value, V4l v)\n        {\n            this[v] = (Td)value;\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n    #region Tensor4<Td, Tv>\n\n    /// <summary>\n    /// Generic tensor4 of elements with arbitrary stride.\n    /// All sizes are given as 4-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The tensor4 does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on tensor4s are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// 4 stride direction(s) are called DX, DY, aso.\n    /// The tensor4 has different view and data element types, i.e. although\n    /// all data is stored using the data element type, in its interfaces it\n    /// acts as a tensor4 of view element types.\n    /// </summary>\n    /// <typeparam name=\"Td\">data element type</typeparam>\n    /// <typeparam name=\"Tv\">view element type</typeparam>\n    [Serializable]\n    public partial struct Tensor4<Td, Tv> : IValidity, ITensor4<Tv>, IArrayTensor4\n    {\n        public Td[] Data;\n        public Func<Td[], long, Tv> Getter;\n        public Action<Td[], long, Tv> Setter;\n        public Tensor4Info Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public Tensor4(Td[] data, Tensor4Info info)\n        {\n            Data = data;\n            Info = info;\n            Getter = null;\n            Setter = null;\n        }\n\n        /// <summary>\n        /// Construct tensor4 of specified size.\n        /// </summary>\n        public Tensor4(V4l size)\n            : this(new Td[size.X * size.Y * size.Z * size.W], new Tensor4Info(size))\n        { }\n\n        /// <summary>\n        /// Construct tensor4 of specified size.\n        /// </summary>\n        public Tensor4(V4i size)\n            : this((V4l)size)\n        { }\n\n        /// <summary>\n        /// Construct tensor4 with specified info.\n        /// </summary>\n        public Tensor4(Tensor4Info info)\n            : this(new Td[info.Count], new Tensor4Info(info))\n        { }\n\n        /// <summary>\n        /// Construct tensor4 of specified size.\n        /// </summary>\n        public Tensor4(long sx, long sy, long sz, long sw)\n            : this(new V4l(sx, sy, sz, sw))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Tensor4(Td[] data, long sx, long sy, long sz, long sw)\n            : this(data, new Tensor4Info(sx, sy, sz, sw))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and sets all elements to the supplied value.\n        /// </summary>\n        public Tensor4(long sx, long sy, long sz, long sw, Tv value)\n            : this(new V4l(sx, sy, sz, sw), value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Tensor4(Td[] data, V4l size)\n            : this(data, new Tensor4Info(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public Tensor4(Td[] data, V4i size)\n            : this(data, new Tensor4Info(size))\n        { }\n\n        /// <summary>\n        /// Construct tensor4 of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Tensor4(V4l size, Tv value)\n            : this(new Td[size.X * size.Y * size.Z * size.W], new Tensor4Info(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public Tensor4(V4i size, Tv value)\n            : this((V4l)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Tensor4(Td[] data, long origin, V4l size, V4l delta)\n            : this(data, new Tensor4Info(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public Tensor4(Td[] data, long origin, V4l size, V4l delta, V4l first)\n            : this(data, new Tensor4Info(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public Tensor4(long origin, V4l size, V4l delta)\n            : this(new Td[size.X * size.Y * size.Z * size.W],\n                   new Tensor4Info(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the tensor4 (4).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public V4l Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public V4l Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public V4l First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        public TensorAccessors<Td, Tv> Accessors\n        {\n            readonly get\n            {\n                return new TensorAccessors<Td, Tv>()\n                                { Getter = Getter, Setter = Setter };\n            }\n            set { Getter = value.Getter; Setter = value.Setter; }\n        }\n\n        /// <summary>\n        /// Returns true if the tensor4 has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the tensor4 does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly V4l End { get { return Info.E; } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOO { get { return Info.OOOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOO { get { return Info.IOOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOO { get { return Info.OIOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOO { get { return Info.IIOO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOIO { get { return Info.OOIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOIO { get { return Info.IOIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIIO { get { return Info.OIIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIIO { get { return Info.IIIO; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOOI { get { return Info.OOOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOOI { get { return Info.IOOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIOI { get { return Info.OIOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIOI { get { return Info.IIOI; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OOII { get { return Info.OOII; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IOII { get { return Info.IOII; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l OIII { get { return Info.OIII; } }\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l IIII { get { return Info.IIII; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public V4l F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly V4l E { get { return Info.E; } }\n\n        /// <summary>\n        /// Size in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Info.SX; } set { Info.SX = value; } }\n\n        /// <summary>\n        /// Size in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SY { readonly get { return Info.SY; } set { Info.SY = value; } }\n\n        /// <summary>\n        /// Size in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SZ { readonly get { return Info.SZ; } set { Info.SZ = value; } }\n\n        /// <summary>\n        /// Size in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SW { readonly get { return Info.SW; } set { Info.SW = value; } }\n\n        /// <summary>\n        /// Delta in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Info.DX; } set { Info.DX = value; } }\n\n        /// <summary>\n        /// Delta in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DY { readonly get { return Info.DY; } set { Info.DY = value; } }\n\n        /// <summary>\n        /// Delta in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DZ { readonly get { return Info.DZ; } set { Info.DZ = value; } }\n\n        /// <summary>\n        /// Delta in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DW { readonly get { return Info.DW; } set { Info.DW = value; } }\n\n        /// <summary>\n        /// First in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return Info.FX; } set { Info.FX = value; } }\n\n        /// <summary>\n        /// First in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FY { readonly get { return Info.FY; } set { Info.FY = value; } }\n\n        /// <summary>\n        /// First in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FZ { readonly get { return Info.FZ; } set { Info.FZ = value; } }\n\n        /// <summary>\n        /// First in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FW { readonly get { return Info.FW; } set { Info.FW = value; } }\n\n        /// <summary>\n        /// End in dimension X (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return Info.EX; } }\n\n        /// <summary>\n        /// End in dimension Y (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EY { get { return Info.EY; } }\n\n        /// <summary>\n        /// End in dimension Z (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EZ { get { return Info.EZ; } }\n\n        /// <summary>\n        /// End in dimension W (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EW { get { return Info.EW; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension X.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Info.JX; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Y.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JY { get { return Info.JY; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension Z.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JZ { get { return Info.JZ; } }\n\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension W.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JW { get { return Info.JW; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Info.DSX; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSY { get { return Info.DSY; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSZ { get { return Info.DSZ; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSW { get { return Info.DSW; } }\n\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<Tv> Elements\n        {\n            get\n            {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    yield return Getter(Data, i);\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    yield return Getter(Data, i);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    yield return Getter(Data, i);\n                } } } }\n            }\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(Td[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (Td[])value; }\n        }\n\n        #endregion\n\n        #region Indexers\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Tv this[V4l v]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + v.X * Info.Delta.X + v.Y * Info.Delta.Y + v.Z * Info.Delta.Z + v.W * Info.Delta.W);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + v.X * Info.Delta.X + v.Y * Info.Delta.Y + v.Z * Info.Delta.Z + v.W * Info.Delta.W, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly Tv this[V4i v]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y + (long)v.Z * Info.Delta.Z + (long)v.W * Info.Delta.W);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + (long)v.X * Info.Delta.X + (long)v.Y * Info.Delta.Y + (long)v.Z * Info.Delta.Z + (long)v.W * Info.Delta.W, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at the specified index in the underlying data array.\n        /// </summary>\n        public readonly Tv this[long index]\n        {\n            get\n            {\n                return Getter(Data, index);\n            }\n            set\n            {\n                Setter(Data, index, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Tv this[long x, long y, long z, long w]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + x * Info.Delta.X + y * Info.Delta.Y + z * Info.Delta.Z + w * Info.Delta.W);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + x * Info.Delta.X + y * Info.Delta.Y + z * Info.Delta.Z + w * Info.Delta.W, value);\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly Tv this[int x, int y, int z, int w]\n        {\n            get\n            {\n                return Getter(Data, Info.Origin\n                              + (long)x * Info.Delta.X + (long)y * Info.Delta.Y + (long)z * Info.Delta.Z + (long)w * Info.Delta.W);\n            }\n            set\n            {\n                Setter(Data, Info.Origin\n                       + (long)x * Info.Delta.X + (long)y * Info.Delta.Y + (long)z * Info.Delta.Z + (long)w * Info.Delta.W, value);\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        public readonly void ForeachIndex(Action<long, long, long, long, long> x_y_z_w_i_action)\n        {\n            Info.ForeachIndex(x_y_z_w_i_action);\n        }\n\n        public readonly void ForeachCoord(Action<V4l> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(Tensor4Info t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachX(\n                Action<long> x_elementAct)\n        {\n            Info.ForeachX(x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachY(\n                Action<long> y_elementAct)\n        {\n            Info.ForeachY(y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZ(\n                Action<long> z_elementAct)\n        {\n            Info.ForeachZ(z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachW(\n                Action<long> w_elementAct)\n        {\n            Info.ForeachW(w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXY(\n                Action<long> x_preLineAct,\n                Action<long, long> x_y_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXY(\n                    x_preLineAct,\n                    x_y_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct)\n        {\n            Info.ForeachXZ(\n                    x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZ(\n                    x_z_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct)\n        {\n            Info.ForeachXZ(\n                    x_preLineAct,\n                    x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZ(\n                Action<long> x_preLineAct,\n                Action<long, long> x_z_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZ(\n                    x_preLineAct,\n                    x_z_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long, long> x_w_elementAct)\n        {\n            Info.ForeachXW(\n                    x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long, long> x_w_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXW(\n                    x_w_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long> x_preLineAct,\n                Action<long, long> x_w_elementAct)\n        {\n            Info.ForeachXW(\n                    x_preLineAct,\n                    x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXW(\n                Action<long> x_preLineAct,\n                Action<long, long> x_w_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXW(\n                    x_preLineAct,\n                    x_w_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYX(\n                Action<long> y_preLineAct,\n                Action<long, long> y_x_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYX(\n                    y_preLineAct,\n                    y_x_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct)\n        {\n            Info.ForeachYZ(\n                    y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZ(\n                    y_z_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct)\n        {\n            Info.ForeachYZ(\n                    y_preLineAct,\n                    y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZ(\n                Action<long> y_preLineAct,\n                Action<long, long> y_z_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZ(\n                    y_preLineAct,\n                    y_z_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long, long> y_w_elementAct)\n        {\n            Info.ForeachYW(\n                    y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long, long> y_w_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYW(\n                    y_w_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long> y_preLineAct,\n                Action<long, long> y_w_elementAct)\n        {\n            Info.ForeachYW(\n                    y_preLineAct,\n                    y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYW(\n                Action<long> y_preLineAct,\n                Action<long, long> y_w_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYW(\n                    y_preLineAct,\n                    y_w_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct)\n        {\n            Info.ForeachZX(\n                    z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZX(\n                    z_x_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct)\n        {\n            Info.ForeachZX(\n                    z_preLineAct,\n                    z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZX(\n                Action<long> z_preLineAct,\n                Action<long, long> z_x_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZX(\n                    z_preLineAct,\n                    z_x_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct)\n        {\n            Info.ForeachZY(\n                    z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZY(\n                    z_y_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct)\n        {\n            Info.ForeachZY(\n                    z_preLineAct,\n                    z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZY(\n                Action<long> z_preLineAct,\n                Action<long, long> z_y_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZY(\n                    z_preLineAct,\n                    z_y_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long, long> z_w_elementAct)\n        {\n            Info.ForeachZW(\n                    z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long, long> z_w_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZW(\n                    z_w_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long> z_preLineAct,\n                Action<long, long> z_w_elementAct)\n        {\n            Info.ForeachZW(\n                    z_preLineAct,\n                    z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZW(\n                Action<long> z_preLineAct,\n                Action<long, long> z_w_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZW(\n                    z_preLineAct,\n                    z_w_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long, long> w_x_elementAct)\n        {\n            Info.ForeachWX(\n                    w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long, long> w_x_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWX(\n                    w_x_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long> w_preLineAct,\n                Action<long, long> w_x_elementAct)\n        {\n            Info.ForeachWX(\n                    w_preLineAct,\n                    w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWX(\n                Action<long> w_preLineAct,\n                Action<long, long> w_x_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWX(\n                    w_preLineAct,\n                    w_x_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long, long> w_y_elementAct)\n        {\n            Info.ForeachWY(\n                    w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long, long> w_y_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWY(\n                    w_y_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long> w_preLineAct,\n                Action<long, long> w_y_elementAct)\n        {\n            Info.ForeachWY(\n                    w_preLineAct,\n                    w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWY(\n                Action<long> w_preLineAct,\n                Action<long, long> w_y_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWY(\n                    w_preLineAct,\n                    w_y_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long, long> w_z_elementAct)\n        {\n            Info.ForeachWZ(\n                    w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long, long> w_z_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWZ(\n                    w_z_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long> w_preLineAct,\n                Action<long, long> w_z_elementAct)\n        {\n            Info.ForeachWZ(\n                    w_preLineAct,\n                    w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZ(\n                Action<long> w_preLineAct,\n                Action<long, long> w_z_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWZ(\n                    w_preLineAct,\n                    w_z_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachXIndex(\n                Action<long, long> x_i_elementAct)\n        {\n            Info.ForeachXIndex(x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachYIndex(\n                Action<long, long> y_i_elementAct)\n        {\n            Info.ForeachYIndex(y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachZIndex(\n                Action<long, long> z_i_elementAct)\n        {\n            Info.ForeachZIndex(z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWIndex(i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        public readonly void ForeachWIndex(\n                Action<long, long> w_i_elementAct)\n        {\n            Info.ForeachWIndex(w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_y_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXYIndex(\n                    x_preLineAct,\n                    x_y_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    x_z_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct)\n        {\n            Info.ForeachXZIndex(\n                    x_preLineAct,\n                    x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_z_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXZIndex(\n                    x_preLineAct,\n                    x_z_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXWIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachXWIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long, long, long> x_w_i_elementAct)\n        {\n            Info.ForeachXWIndex(\n                    x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long, long, long> x_w_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXWIndex(\n                    x_w_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_w_i_elementAct)\n        {\n            Info.ForeachXWIndex(\n                    x_preLineAct,\n                    x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWIndex(\n                Action<long> x_preLineAct,\n                Action<long, long, long> x_w_i_elementAct,\n                Action<long> x_postLineAct)\n        {\n            Info.ForeachXWIndex(\n                    x_preLineAct,\n                    x_w_i_elementAct,\n                    x_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_x_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYXIndex(\n                    y_preLineAct,\n                    y_x_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    y_z_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct)\n        {\n            Info.ForeachYZIndex(\n                    y_preLineAct,\n                    y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_z_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYZIndex(\n                    y_preLineAct,\n                    y_z_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYWIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachYWIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long, long, long> y_w_i_elementAct)\n        {\n            Info.ForeachYWIndex(\n                    y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long, long, long> y_w_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYWIndex(\n                    y_w_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_w_i_elementAct)\n        {\n            Info.ForeachYWIndex(\n                    y_preLineAct,\n                    y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWIndex(\n                Action<long> y_preLineAct,\n                Action<long, long, long> y_w_i_elementAct,\n                Action<long> y_postLineAct)\n        {\n            Info.ForeachYWIndex(\n                    y_preLineAct,\n                    y_w_i_elementAct,\n                    y_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    z_x_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct)\n        {\n            Info.ForeachZXIndex(\n                    z_preLineAct,\n                    z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_x_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZXIndex(\n                    z_preLineAct,\n                    z_x_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    z_y_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct)\n        {\n            Info.ForeachZYIndex(\n                    z_preLineAct,\n                    z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_y_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZYIndex(\n                    z_preLineAct,\n                    z_y_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZWIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachZWIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long, long, long> z_w_i_elementAct)\n        {\n            Info.ForeachZWIndex(\n                    z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long, long, long> z_w_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZWIndex(\n                    z_w_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_w_i_elementAct)\n        {\n            Info.ForeachZWIndex(\n                    z_preLineAct,\n                    z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWIndex(\n                Action<long> z_preLineAct,\n                Action<long, long, long> z_w_i_elementAct,\n                Action<long> z_postLineAct)\n        {\n            Info.ForeachZWIndex(\n                    z_preLineAct,\n                    z_w_i_elementAct,\n                    z_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWXIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWXIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long, long, long> w_x_i_elementAct)\n        {\n            Info.ForeachWXIndex(\n                    w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long, long, long> w_x_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWXIndex(\n                    w_x_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_x_i_elementAct)\n        {\n            Info.ForeachWXIndex(\n                    w_preLineAct,\n                    w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_x_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWXIndex(\n                    w_preLineAct,\n                    w_x_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWYIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWYIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long, long, long> w_y_i_elementAct)\n        {\n            Info.ForeachWYIndex(\n                    w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long, long, long> w_y_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWYIndex(\n                    w_y_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_y_i_elementAct)\n        {\n            Info.ForeachWYIndex(\n                    w_preLineAct,\n                    w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_y_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWYIndex(\n                    w_preLineAct,\n                    w_y_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWZIndex(\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZIndex(\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct)\n        {\n            Info.ForeachWZIndex(\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long, long, long> w_z_i_elementAct)\n        {\n            Info.ForeachWZIndex(\n                    w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long, long, long> w_z_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWZIndex(\n                    w_z_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_z_i_elementAct)\n        {\n            Info.ForeachWZIndex(\n                    w_preLineAct,\n                    w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZIndex(\n                Action<long> w_preLineAct,\n                Action<long, long, long> w_z_i_elementAct,\n                Action<long> w_postLineAct)\n        {\n            Info.ForeachWZIndex(\n                    w_preLineAct,\n                    w_z_i_elementAct,\n                    w_postLineAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            Info.ForeachXYZ(\n                    x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZ(\n                    x_y_z_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct)\n        {\n            Info.ForeachXYZ(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_z_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZ(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long, long, long> x_y_w_elementAct)\n        {\n            Info.ForeachXYW(\n                    x_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long, long, long> x_y_w_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYW(\n                    x_y_w_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_w_elementAct)\n        {\n            Info.ForeachXYW(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long> x_y_w_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYW(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_w_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            Info.ForeachXZY(\n                    x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZY(\n                    x_z_y_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct)\n        {\n            Info.ForeachXZY(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_y_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZY(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long, long, long> x_z_w_elementAct)\n        {\n            Info.ForeachXZW(\n                    x_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long, long, long> x_z_w_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZW(\n                    x_z_w_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_w_elementAct)\n        {\n            Info.ForeachXZW(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZW(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long> x_z_w_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZW(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_w_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long, long, long> x_w_y_elementAct)\n        {\n            Info.ForeachXWY(\n                    x_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long, long, long> x_w_y_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWY(\n                    x_w_y_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_y_elementAct)\n        {\n            Info.ForeachXWY(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWY(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_y_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWY(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_y_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long, long, long> x_w_z_elementAct)\n        {\n            Info.ForeachXWZ(\n                    x_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long, long, long> x_w_z_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWZ(\n                    x_w_z_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_z_elementAct)\n        {\n            Info.ForeachXWZ(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZ(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long> x_w_z_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWZ(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_z_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            Info.ForeachYXZ(\n                    y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZ(\n                    y_x_z_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct)\n        {\n            Info.ForeachYXZ(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_z_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZ(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long, long, long> y_x_w_elementAct)\n        {\n            Info.ForeachYXW(\n                    y_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long, long, long> y_x_w_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXW(\n                    y_x_w_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_w_elementAct)\n        {\n            Info.ForeachYXW(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long> y_x_w_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXW(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_w_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            Info.ForeachYZX(\n                    y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZX(\n                    y_z_x_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct)\n        {\n            Info.ForeachYZX(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_x_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZX(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long, long, long> y_z_w_elementAct)\n        {\n            Info.ForeachYZW(\n                    y_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long, long, long> y_z_w_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZW(\n                    y_z_w_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_w_elementAct)\n        {\n            Info.ForeachYZW(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZW(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long> y_z_w_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZW(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_w_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long, long, long> y_w_x_elementAct)\n        {\n            Info.ForeachYWX(\n                    y_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long, long, long> y_w_x_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWX(\n                    y_w_x_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_x_elementAct)\n        {\n            Info.ForeachYWX(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWX(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_x_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWX(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_x_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long, long, long> y_w_z_elementAct)\n        {\n            Info.ForeachYWZ(\n                    y_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long, long, long> y_w_z_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWZ(\n                    y_w_z_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_z_elementAct)\n        {\n            Info.ForeachYWZ(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZ(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long> y_w_z_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWZ(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_z_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            Info.ForeachZXY(\n                    z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXY(\n                    z_x_y_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct)\n        {\n            Info.ForeachZXY(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_y_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXY(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long, long, long> z_x_w_elementAct)\n        {\n            Info.ForeachZXW(\n                    z_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long, long, long> z_x_w_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXW(\n                    z_x_w_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_w_elementAct)\n        {\n            Info.ForeachZXW(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long> z_x_w_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXW(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_w_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            Info.ForeachZYX(\n                    z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYX(\n                    z_y_x_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct)\n        {\n            Info.ForeachZYX(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_x_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYX(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long, long, long> z_y_w_elementAct)\n        {\n            Info.ForeachZYW(\n                    z_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long, long, long> z_y_w_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYW(\n                    z_y_w_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_w_elementAct)\n        {\n            Info.ForeachZYW(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYW(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long> z_y_w_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYW(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_w_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long, long, long> z_w_x_elementAct)\n        {\n            Info.ForeachZWX(\n                    z_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long, long, long> z_w_x_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWX(\n                    z_w_x_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_x_elementAct)\n        {\n            Info.ForeachZWX(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWX(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_x_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWX(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_x_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long, long, long> z_w_y_elementAct)\n        {\n            Info.ForeachZWY(\n                    z_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long, long, long> z_w_y_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWY(\n                    z_w_y_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_y_elementAct)\n        {\n            Info.ForeachZWY(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWY(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long> z_w_y_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWY(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_y_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long, long, long> w_x_y_elementAct)\n        {\n            Info.ForeachWXY(\n                    w_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long, long, long> w_x_y_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXY(\n                    w_x_y_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_y_elementAct)\n        {\n            Info.ForeachWXY(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_y_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXY(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_y_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long, long, long> w_x_z_elementAct)\n        {\n            Info.ForeachWXZ(\n                    w_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long, long, long> w_x_z_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXZ(\n                    w_x_z_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_z_elementAct)\n        {\n            Info.ForeachWXZ(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long> w_x_z_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXZ(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_z_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long, long, long> w_y_x_elementAct)\n        {\n            Info.ForeachWYX(\n                    w_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long, long, long> w_y_x_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYX(\n                    w_y_x_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_x_elementAct)\n        {\n            Info.ForeachWYX(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_x_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYX(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_x_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long, long, long> w_y_z_elementAct)\n        {\n            Info.ForeachWYZ(\n                    w_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long, long, long> w_y_z_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYZ(\n                    w_y_z_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_z_elementAct)\n        {\n            Info.ForeachWYZ(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZ(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long> w_y_z_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYZ(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_z_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long, long, long> w_z_x_elementAct)\n        {\n            Info.ForeachWZX(\n                    w_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long, long, long> w_z_x_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZX(\n                    w_z_x_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_x_elementAct)\n        {\n            Info.ForeachWZX(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZX(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_x_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZX(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_x_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long, long, long> w_z_y_elementAct)\n        {\n            Info.ForeachWZY(\n                    w_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long, long, long> w_z_y_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZY(\n                    w_z_y_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_y_elementAct)\n        {\n            Info.ForeachWZY(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZY(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long> w_z_y_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZY(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_y_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_y_z_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_z_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYZIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_z_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXYWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long, long, long, long> x_y_w_i_elementAct)\n        {\n            Info.ForeachXYWIndex(\n                    x_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long, long, long, long> x_y_w_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYWIndex(\n                    x_y_w_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_w_i_elementAct)\n        {\n            Info.ForeachXYWIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_y_preLineAct,\n                Action<long, long, long, long> x_y_w_i_elementAct,\n                Action<long, long> x_y_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXYWIndex(\n                    x_prePlaneAct,\n                    x_y_preLineAct,\n                    x_y_w_i_elementAct,\n                    x_y_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_z_y_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_y_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZYIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_y_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXZWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long, long, long, long> x_z_w_i_elementAct)\n        {\n            Info.ForeachXZWIndex(\n                    x_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long, long, long, long> x_z_w_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZWIndex(\n                    x_z_w_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_w_i_elementAct)\n        {\n            Info.ForeachXZWIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_z_preLineAct,\n                Action<long, long, long, long> x_z_w_i_elementAct,\n                Action<long, long> x_z_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXZWIndex(\n                    x_prePlaneAct,\n                    x_z_preLineAct,\n                    x_z_w_i_elementAct,\n                    x_z_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXWYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXWYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long, long, long, long> x_w_y_i_elementAct)\n        {\n            Info.ForeachXWYIndex(\n                    x_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long, long, long, long> x_w_y_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWYIndex(\n                    x_w_y_i_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_y_i_elementAct)\n        {\n            Info.ForeachXWYIndex(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_y_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWYIndex(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_y_i_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXWZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachXWZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long, long, long, long> x_w_z_i_elementAct)\n        {\n            Info.ForeachXWZIndex(\n                    x_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long, long, long, long> x_w_z_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWZIndex(\n                    x_w_z_i_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_z_i_elementAct)\n        {\n            Info.ForeachXWZIndex(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZIndex(\n                Action<long> x_prePlaneAct,\n                Action<long, long> x_w_preLineAct,\n                Action<long, long, long, long> x_w_z_i_elementAct,\n                Action<long, long> x_w_postLineAct,\n                Action<long> x_postPlaneAct)\n        {\n            Info.ForeachXWZIndex(\n                    x_prePlaneAct,\n                    x_w_preLineAct,\n                    x_w_z_i_elementAct,\n                    x_w_postLineAct,\n                    x_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_x_z_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_z_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXZIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_z_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYXWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long, long, long, long> y_x_w_i_elementAct)\n        {\n            Info.ForeachYXWIndex(\n                    y_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long, long, long, long> y_x_w_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXWIndex(\n                    y_x_w_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_w_i_elementAct)\n        {\n            Info.ForeachYXWIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_x_preLineAct,\n                Action<long, long, long, long> y_x_w_i_elementAct,\n                Action<long, long> y_x_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYXWIndex(\n                    y_prePlaneAct,\n                    y_x_preLineAct,\n                    y_x_w_i_elementAct,\n                    y_x_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_z_x_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_x_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZXIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_x_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYZWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long, long, long, long> y_z_w_i_elementAct)\n        {\n            Info.ForeachYZWIndex(\n                    y_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long, long, long, long> y_z_w_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZWIndex(\n                    y_z_w_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_w_i_elementAct)\n        {\n            Info.ForeachYZWIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_z_preLineAct,\n                Action<long, long, long, long> y_z_w_i_elementAct,\n                Action<long, long> y_z_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYZWIndex(\n                    y_prePlaneAct,\n                    y_z_preLineAct,\n                    y_z_w_i_elementAct,\n                    y_z_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYWXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYWXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long, long, long, long> y_w_x_i_elementAct)\n        {\n            Info.ForeachYWXIndex(\n                    y_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long, long, long, long> y_w_x_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWXIndex(\n                    y_w_x_i_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_x_i_elementAct)\n        {\n            Info.ForeachYWXIndex(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_x_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWXIndex(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_x_i_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYWZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachYWZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long, long, long, long> y_w_z_i_elementAct)\n        {\n            Info.ForeachYWZIndex(\n                    y_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long, long, long, long> y_w_z_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWZIndex(\n                    y_w_z_i_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_z_i_elementAct)\n        {\n            Info.ForeachYWZIndex(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZIndex(\n                Action<long> y_prePlaneAct,\n                Action<long, long> y_w_preLineAct,\n                Action<long, long, long, long> y_w_z_i_elementAct,\n                Action<long, long> y_w_postLineAct,\n                Action<long> y_postPlaneAct)\n        {\n            Info.ForeachYWZIndex(\n                    y_prePlaneAct,\n                    y_w_preLineAct,\n                    y_w_z_i_elementAct,\n                    y_w_postLineAct,\n                    y_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_x_y_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_y_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXYIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_y_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZXWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long, long, long, long> z_x_w_i_elementAct)\n        {\n            Info.ForeachZXWIndex(\n                    z_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long, long, long, long> z_x_w_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXWIndex(\n                    z_x_w_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_w_i_elementAct)\n        {\n            Info.ForeachZXWIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_x_preLineAct,\n                Action<long, long, long, long> z_x_w_i_elementAct,\n                Action<long, long> z_x_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZXWIndex(\n                    z_prePlaneAct,\n                    z_x_preLineAct,\n                    z_x_w_i_elementAct,\n                    z_x_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_y_x_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_x_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYXIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_x_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZYWIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long, long, long, long> z_y_w_i_elementAct)\n        {\n            Info.ForeachZYWIndex(\n                    z_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long, long, long, long> z_y_w_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYWIndex(\n                    z_y_w_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_w_i_elementAct)\n        {\n            Info.ForeachZYWIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_y_preLineAct,\n                Action<long, long, long, long> z_y_w_i_elementAct,\n                Action<long, long> z_y_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZYWIndex(\n                    z_prePlaneAct,\n                    z_y_preLineAct,\n                    z_y_w_i_elementAct,\n                    z_y_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZWXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZWXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long, long, long, long> z_w_x_i_elementAct)\n        {\n            Info.ForeachZWXIndex(\n                    z_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long, long, long, long> z_w_x_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWXIndex(\n                    z_w_x_i_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_x_i_elementAct)\n        {\n            Info.ForeachZWXIndex(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_x_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWXIndex(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_x_i_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZWYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachZWYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long, long, long, long> z_w_y_i_elementAct)\n        {\n            Info.ForeachZWYIndex(\n                    z_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long, long, long, long> z_w_y_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWYIndex(\n                    z_w_y_i_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_y_i_elementAct)\n        {\n            Info.ForeachZWYIndex(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYIndex(\n                Action<long> z_prePlaneAct,\n                Action<long, long> z_w_preLineAct,\n                Action<long, long, long, long> z_w_y_i_elementAct,\n                Action<long, long> z_w_postLineAct,\n                Action<long> z_postPlaneAct)\n        {\n            Info.ForeachZWYIndex(\n                    z_prePlaneAct,\n                    z_w_preLineAct,\n                    z_w_y_i_elementAct,\n                    z_w_postLineAct,\n                    z_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWXYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long, long, long, long> w_x_y_i_elementAct)\n        {\n            Info.ForeachWXYIndex(\n                    w_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long, long, long, long> w_x_y_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXYIndex(\n                    w_x_y_i_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_y_i_elementAct)\n        {\n            Info.ForeachWXYIndex(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_y_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXYIndex(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_y_i_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWXZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long, long, long, long> w_x_z_i_elementAct)\n        {\n            Info.ForeachWXZIndex(\n                    w_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long, long, long, long> w_x_z_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXZIndex(\n                    w_x_z_i_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_z_i_elementAct)\n        {\n            Info.ForeachWXZIndex(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_x_preLineAct,\n                Action<long, long, long, long> w_x_z_i_elementAct,\n                Action<long, long> w_x_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWXZIndex(\n                    w_prePlaneAct,\n                    w_x_preLineAct,\n                    w_x_z_i_elementAct,\n                    w_x_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWYXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long, long, long, long> w_y_x_i_elementAct)\n        {\n            Info.ForeachWYXIndex(\n                    w_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long, long, long, long> w_y_x_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYXIndex(\n                    w_y_x_i_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_x_i_elementAct)\n        {\n            Info.ForeachWYXIndex(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_x_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYXIndex(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_x_i_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWYZIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long, long, long, long> w_y_z_i_elementAct)\n        {\n            Info.ForeachWYZIndex(\n                    w_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long, long, long, long> w_y_z_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYZIndex(\n                    w_y_z_i_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_z_i_elementAct)\n        {\n            Info.ForeachWYZIndex(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_y_preLineAct,\n                Action<long, long, long, long> w_y_z_i_elementAct,\n                Action<long, long> w_y_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWYZIndex(\n                    w_prePlaneAct,\n                    w_y_preLineAct,\n                    w_y_z_i_elementAct,\n                    w_y_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWZXIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long, long, long, long> w_z_x_i_elementAct)\n        {\n            Info.ForeachWZXIndex(\n                    w_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long, long, long, long> w_z_x_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZXIndex(\n                    w_z_x_i_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_x_i_elementAct)\n        {\n            Info.ForeachWZXIndex(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_x_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZXIndex(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_x_i_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct)\n        {\n            Info.ForeachWZYIndex(\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long, long, long, long> w_z_y_i_elementAct)\n        {\n            Info.ForeachWZYIndex(\n                    w_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long, long, long, long> w_z_y_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZYIndex(\n                    w_z_y_i_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_y_i_elementAct)\n        {\n            Info.ForeachWZYIndex(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYIndex(\n                Action<long> w_prePlaneAct,\n                Action<long, long> w_z_preLineAct,\n                Action<long, long, long, long> w_z_y_i_elementAct,\n                Action<long, long> w_z_postLineAct,\n                Action<long> w_postPlaneAct)\n        {\n            Info.ForeachWZYIndex(\n                    w_prePlaneAct,\n                    w_z_preLineAct,\n                    w_z_y_i_elementAct,\n                    w_z_postLineAct,\n                    w_postPlaneAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long, long, long, long> x_y_z_w_elementAct)\n        {\n            Info.ForeachXYZW(\n                    x_y_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long, long, long, long> x_y_z_w_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYZW(\n                    x_y_z_w_elementAct,\n                    x_y_z_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long> x_y_z_w_elementAct)\n        {\n            Info.ForeachXYZW(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_z_preLineAct,\n                    x_y_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long> x_y_z_w_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYZW(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_z_preLineAct,\n                    x_y_z_w_elementAct,\n                    x_y_z_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long, long, long, long> x_y_w_z_elementAct)\n        {\n            Info.ForeachXYWZ(\n                    x_y_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long, long, long, long> x_y_w_z_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYWZ(\n                    x_y_w_z_elementAct,\n                    x_y_w_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long> x_y_w_z_elementAct)\n        {\n            Info.ForeachXYWZ(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_w_preLineAct,\n                    x_y_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long> x_y_w_z_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYWZ(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_w_preLineAct,\n                    x_y_w_z_elementAct,\n                    x_y_w_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long, long, long, long> x_z_y_w_elementAct)\n        {\n            Info.ForeachXZYW(\n                    x_z_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long, long, long, long> x_z_y_w_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZYW(\n                    x_z_y_w_elementAct,\n                    x_z_y_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long> x_z_y_w_elementAct)\n        {\n            Info.ForeachXZYW(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_y_preLineAct,\n                    x_z_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYW(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long> x_z_y_w_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZYW(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_y_preLineAct,\n                    x_z_y_w_elementAct,\n                    x_z_y_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long, long, long, long> x_z_w_y_elementAct)\n        {\n            Info.ForeachXZWY(\n                    x_z_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long, long, long, long> x_z_w_y_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZWY(\n                    x_z_w_y_elementAct,\n                    x_z_w_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long> x_z_w_y_elementAct)\n        {\n            Info.ForeachXZWY(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_w_preLineAct,\n                    x_z_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long> x_z_w_y_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZWY(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_w_preLineAct,\n                    x_z_w_y_elementAct,\n                    x_z_w_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long, long, long, long> x_w_y_z_elementAct)\n        {\n            Info.ForeachXWYZ(\n                    x_w_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long, long, long, long> x_w_y_z_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWYZ(\n                    x_w_y_z_elementAct,\n                    x_w_y_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long> x_w_y_z_elementAct)\n        {\n            Info.ForeachXWYZ(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_y_preLineAct,\n                    x_w_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZ(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long> x_w_y_z_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWYZ(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_y_preLineAct,\n                    x_w_y_z_elementAct,\n                    x_w_y_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long, long, long, long> x_w_z_y_elementAct)\n        {\n            Info.ForeachXWZY(\n                    x_w_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long, long, long, long> x_w_z_y_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWZY(\n                    x_w_z_y_elementAct,\n                    x_w_z_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long> x_w_z_y_elementAct)\n        {\n            Info.ForeachXWZY(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_z_preLineAct,\n                    x_w_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZY(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long> x_w_z_y_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWZY(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_z_preLineAct,\n                    x_w_z_y_elementAct,\n                    x_w_z_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long, long, long, long> y_x_z_w_elementAct)\n        {\n            Info.ForeachYXZW(\n                    y_x_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long, long, long, long> y_x_z_w_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXZW(\n                    y_x_z_w_elementAct,\n                    y_x_z_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long> y_x_z_w_elementAct)\n        {\n            Info.ForeachYXZW(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_z_preLineAct,\n                    y_x_z_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long> y_x_z_w_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXZW(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_z_preLineAct,\n                    y_x_z_w_elementAct,\n                    y_x_z_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long, long, long, long> y_x_w_z_elementAct)\n        {\n            Info.ForeachYXWZ(\n                    y_x_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long, long, long, long> y_x_w_z_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXWZ(\n                    y_x_w_z_elementAct,\n                    y_x_w_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long> y_x_w_z_elementAct)\n        {\n            Info.ForeachYXWZ(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_w_preLineAct,\n                    y_x_w_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long> y_x_w_z_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXWZ(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_w_preLineAct,\n                    y_x_w_z_elementAct,\n                    y_x_w_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long, long, long, long> y_z_x_w_elementAct)\n        {\n            Info.ForeachYZXW(\n                    y_z_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long, long, long, long> y_z_x_w_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZXW(\n                    y_z_x_w_elementAct,\n                    y_z_x_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long> y_z_x_w_elementAct)\n        {\n            Info.ForeachYZXW(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_x_preLineAct,\n                    y_z_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXW(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long> y_z_x_w_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZXW(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_x_preLineAct,\n                    y_z_x_w_elementAct,\n                    y_z_x_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long, long, long, long> y_z_w_x_elementAct)\n        {\n            Info.ForeachYZWX(\n                    y_z_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long, long, long, long> y_z_w_x_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZWX(\n                    y_z_w_x_elementAct,\n                    y_z_w_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long> y_z_w_x_elementAct)\n        {\n            Info.ForeachYZWX(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_w_preLineAct,\n                    y_z_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long> y_z_w_x_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZWX(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_w_preLineAct,\n                    y_z_w_x_elementAct,\n                    y_z_w_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long, long, long, long> y_w_x_z_elementAct)\n        {\n            Info.ForeachYWXZ(\n                    y_w_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long, long, long, long> y_w_x_z_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWXZ(\n                    y_w_x_z_elementAct,\n                    y_w_x_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long> y_w_x_z_elementAct)\n        {\n            Info.ForeachYWXZ(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_x_preLineAct,\n                    y_w_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZ(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long> y_w_x_z_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWXZ(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_x_preLineAct,\n                    y_w_x_z_elementAct,\n                    y_w_x_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long, long, long, long> y_w_z_x_elementAct)\n        {\n            Info.ForeachYWZX(\n                    y_w_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long, long, long, long> y_w_z_x_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWZX(\n                    y_w_z_x_elementAct,\n                    y_w_z_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long> y_w_z_x_elementAct)\n        {\n            Info.ForeachYWZX(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_z_preLineAct,\n                    y_w_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZX(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long> y_w_z_x_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWZX(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_z_preLineAct,\n                    y_w_z_x_elementAct,\n                    y_w_z_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long, long, long, long> z_x_y_w_elementAct)\n        {\n            Info.ForeachZXYW(\n                    z_x_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long, long, long, long> z_x_y_w_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXYW(\n                    z_x_y_w_elementAct,\n                    z_x_y_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long> z_x_y_w_elementAct)\n        {\n            Info.ForeachZXYW(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_y_preLineAct,\n                    z_x_y_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long> z_x_y_w_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXYW(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_y_preLineAct,\n                    z_x_y_w_elementAct,\n                    z_x_y_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long, long, long, long> z_x_w_y_elementAct)\n        {\n            Info.ForeachZXWY(\n                    z_x_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long, long, long, long> z_x_w_y_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXWY(\n                    z_x_w_y_elementAct,\n                    z_x_w_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long> z_x_w_y_elementAct)\n        {\n            Info.ForeachZXWY(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_w_preLineAct,\n                    z_x_w_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long> z_x_w_y_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXWY(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_w_preLineAct,\n                    z_x_w_y_elementAct,\n                    z_x_w_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long, long, long, long> z_y_x_w_elementAct)\n        {\n            Info.ForeachZYXW(\n                    z_y_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long, long, long, long> z_y_x_w_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYXW(\n                    z_y_x_w_elementAct,\n                    z_y_x_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long> z_y_x_w_elementAct)\n        {\n            Info.ForeachZYXW(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_x_preLineAct,\n                    z_y_x_w_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXW(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long> z_y_x_w_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYXW(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_x_preLineAct,\n                    z_y_x_w_elementAct,\n                    z_y_x_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long, long, long, long> z_y_w_x_elementAct)\n        {\n            Info.ForeachZYWX(\n                    z_y_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long, long, long, long> z_y_w_x_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYWX(\n                    z_y_w_x_elementAct,\n                    z_y_w_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long> z_y_w_x_elementAct)\n        {\n            Info.ForeachZYWX(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_w_preLineAct,\n                    z_y_w_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long> z_y_w_x_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYWX(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_w_preLineAct,\n                    z_y_w_x_elementAct,\n                    z_y_w_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long, long, long, long> z_w_x_y_elementAct)\n        {\n            Info.ForeachZWXY(\n                    z_w_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long, long, long, long> z_w_x_y_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWXY(\n                    z_w_x_y_elementAct,\n                    z_w_x_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long> z_w_x_y_elementAct)\n        {\n            Info.ForeachZWXY(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_x_preLineAct,\n                    z_w_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXY(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long> z_w_x_y_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWXY(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_x_preLineAct,\n                    z_w_x_y_elementAct,\n                    z_w_x_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long, long, long, long> z_w_y_x_elementAct)\n        {\n            Info.ForeachZWYX(\n                    z_w_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long, long, long, long> z_w_y_x_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWYX(\n                    z_w_y_x_elementAct,\n                    z_w_y_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long> z_w_y_x_elementAct)\n        {\n            Info.ForeachZWYX(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_y_preLineAct,\n                    z_w_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYX(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long> z_w_y_x_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWYX(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_y_preLineAct,\n                    z_w_y_x_elementAct,\n                    z_w_y_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long, long, long, long> w_x_y_z_elementAct)\n        {\n            Info.ForeachWXYZ(\n                    w_x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long, long, long, long> w_x_y_z_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXYZ(\n                    w_x_y_z_elementAct,\n                    w_x_y_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long> w_x_y_z_elementAct)\n        {\n            Info.ForeachWXYZ(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_y_preLineAct,\n                    w_x_y_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long> w_x_y_z_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXYZ(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_y_preLineAct,\n                    w_x_y_z_elementAct,\n                    w_x_y_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long, long, long, long> w_x_z_y_elementAct)\n        {\n            Info.ForeachWXZY(\n                    w_x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long, long, long, long> w_x_z_y_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXZY(\n                    w_x_z_y_elementAct,\n                    w_x_z_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long> w_x_z_y_elementAct)\n        {\n            Info.ForeachWXZY(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_z_preLineAct,\n                    w_x_z_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long> w_x_z_y_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXZY(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_z_preLineAct,\n                    w_x_z_y_elementAct,\n                    w_x_z_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long, long, long, long> w_y_x_z_elementAct)\n        {\n            Info.ForeachWYXZ(\n                    w_y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long, long, long, long> w_y_x_z_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYXZ(\n                    w_y_x_z_elementAct,\n                    w_y_x_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long> w_y_x_z_elementAct)\n        {\n            Info.ForeachWYXZ(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_x_preLineAct,\n                    w_y_x_z_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZ(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long> w_y_x_z_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYXZ(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_x_preLineAct,\n                    w_y_x_z_elementAct,\n                    w_y_x_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long, long, long, long> w_y_z_x_elementAct)\n        {\n            Info.ForeachWYZX(\n                    w_y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long, long, long, long> w_y_z_x_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYZX(\n                    w_y_z_x_elementAct,\n                    w_y_z_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long> w_y_z_x_elementAct)\n        {\n            Info.ForeachWYZX(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_z_preLineAct,\n                    w_y_z_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long> w_y_z_x_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYZX(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_z_preLineAct,\n                    w_y_z_x_elementAct,\n                    w_y_z_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long, long, long, long> w_z_x_y_elementAct)\n        {\n            Info.ForeachWZXY(\n                    w_z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long, long, long, long> w_z_x_y_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZXY(\n                    w_z_x_y_elementAct,\n                    w_z_x_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long> w_z_x_y_elementAct)\n        {\n            Info.ForeachWZXY(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_x_preLineAct,\n                    w_z_x_y_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXY(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long> w_z_x_y_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZXY(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_x_preLineAct,\n                    w_z_x_y_elementAct,\n                    w_z_x_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long, long, long, long> w_z_y_x_elementAct)\n        {\n            Info.ForeachWZYX(\n                    w_z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long, long, long, long> w_z_y_x_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZYX(\n                    w_z_y_x_elementAct,\n                    w_z_y_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long> w_z_y_x_elementAct)\n        {\n            Info.ForeachWZYX(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_y_preLineAct,\n                    w_z_y_x_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYX(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long> w_z_y_x_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZYX(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_y_preLineAct,\n                    w_z_y_x_elementAct,\n                    w_z_y_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXYZWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYZWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXYZWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct)\n        {\n            Info.ForeachXYZWIndex(\n                    x_y_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYZWIndex(\n                    x_y_z_w_i_elementAct,\n                    x_y_z_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct)\n        {\n            Info.ForeachXYZWIndex(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_z_preLineAct,\n                    x_y_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYZWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_z_preLineAct,\n                Action<long, long, long, long, long> x_y_z_w_i_elementAct,\n                Action<long, long, long> x_y_z_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYZWIndex(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_z_preLineAct,\n                    x_y_z_w_i_elementAct,\n                    x_y_z_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXYWZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXYWZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXYWZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct)\n        {\n            Info.ForeachXYWZIndex(\n                    x_y_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYWZIndex(\n                    x_y_w_z_i_elementAct,\n                    x_y_w_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct)\n        {\n            Info.ForeachXYWZIndex(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_w_preLineAct,\n                    x_y_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXYWZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_y_prePlaneAct,\n                Action<long, long, long> x_y_w_preLineAct,\n                Action<long, long, long, long, long> x_y_w_z_i_elementAct,\n                Action<long, long, long> x_y_w_postLineAct,\n                Action<long, long> x_y_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXYWZIndex(\n                    x_preVolumeAct,\n                    x_y_prePlaneAct,\n                    x_y_w_preLineAct,\n                    x_y_w_z_i_elementAct,\n                    x_y_w_postLineAct,\n                    x_y_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXZYWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZYWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXZYWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct)\n        {\n            Info.ForeachXZYWIndex(\n                    x_z_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZYWIndex(\n                    x_z_y_w_i_elementAct,\n                    x_z_y_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct)\n        {\n            Info.ForeachXZYWIndex(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_y_preLineAct,\n                    x_z_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZYWIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_y_preLineAct,\n                Action<long, long, long, long, long> x_z_y_w_i_elementAct,\n                Action<long, long, long> x_z_y_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZYWIndex(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_y_preLineAct,\n                    x_z_y_w_i_elementAct,\n                    x_z_y_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXZWYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXZWYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXZWYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct)\n        {\n            Info.ForeachXZWYIndex(\n                    x_z_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZWYIndex(\n                    x_z_w_y_i_elementAct,\n                    x_z_w_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct)\n        {\n            Info.ForeachXZWYIndex(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_w_preLineAct,\n                    x_z_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXZWYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_z_prePlaneAct,\n                Action<long, long, long> x_z_w_preLineAct,\n                Action<long, long, long, long, long> x_z_w_y_i_elementAct,\n                Action<long, long, long> x_z_w_postLineAct,\n                Action<long, long> x_z_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXZWYIndex(\n                    x_preVolumeAct,\n                    x_z_prePlaneAct,\n                    x_z_w_preLineAct,\n                    x_z_w_y_i_elementAct,\n                    x_z_w_postLineAct,\n                    x_z_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXWYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWYZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXWYZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct)\n        {\n            Info.ForeachXWYZIndex(\n                    x_w_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWYZIndex(\n                    x_w_y_z_i_elementAct,\n                    x_w_y_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct)\n        {\n            Info.ForeachXWYZIndex(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_y_preLineAct,\n                    x_w_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWYZIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_y_preLineAct,\n                Action<long, long, long, long, long> x_w_y_z_i_elementAct,\n                Action<long, long, long> x_w_y_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWYZIndex(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_y_preLineAct,\n                    x_w_y_z_i_elementAct,\n                    x_w_y_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXWZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachXWZYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachXWZYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct)\n        {\n            Info.ForeachXWZYIndex(\n                    x_w_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWZYIndex(\n                    x_w_z_y_i_elementAct,\n                    x_w_z_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct)\n        {\n            Info.ForeachXWZYIndex(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_z_preLineAct,\n                    x_w_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachXWZYIndex(\n                Action<long> x_preVolumeAct,\n                Action<long, long> x_w_prePlaneAct,\n                Action<long, long, long> x_w_z_preLineAct,\n                Action<long, long, long, long, long> x_w_z_y_i_elementAct,\n                Action<long, long, long> x_w_z_postLineAct,\n                Action<long, long> x_w_postPlaneAct,\n                Action<long> x_postVolumeAct)\n        {\n            Info.ForeachXWZYIndex(\n                    x_preVolumeAct,\n                    x_w_prePlaneAct,\n                    x_w_z_preLineAct,\n                    x_w_z_y_i_elementAct,\n                    x_w_z_postLineAct,\n                    x_w_postPlaneAct,\n                    x_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYXZWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXZWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYXZWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct)\n        {\n            Info.ForeachYXZWIndex(\n                    y_x_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXZWIndex(\n                    y_x_z_w_i_elementAct,\n                    y_x_z_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct)\n        {\n            Info.ForeachYXZWIndex(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_z_preLineAct,\n                    y_x_z_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXZWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_z_preLineAct,\n                Action<long, long, long, long, long> y_x_z_w_i_elementAct,\n                Action<long, long, long> y_x_z_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXZWIndex(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_z_preLineAct,\n                    y_x_z_w_i_elementAct,\n                    y_x_z_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXWZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYXWZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYXWZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYXWZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct)\n        {\n            Info.ForeachYXWZIndex(\n                    y_x_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXWZIndex(\n                    y_x_w_z_i_elementAct,\n                    y_x_w_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct)\n        {\n            Info.ForeachYXWZIndex(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_w_preLineAct,\n                    y_x_w_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYXWZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_x_prePlaneAct,\n                Action<long, long, long> y_x_w_preLineAct,\n                Action<long, long, long, long, long> y_x_w_z_i_elementAct,\n                Action<long, long, long> y_x_w_postLineAct,\n                Action<long, long> y_x_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYXWZIndex(\n                    y_preVolumeAct,\n                    y_x_prePlaneAct,\n                    y_x_w_preLineAct,\n                    y_x_w_z_i_elementAct,\n                    y_x_w_postLineAct,\n                    y_x_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYZXWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZXWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYZXWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct)\n        {\n            Info.ForeachYZXWIndex(\n                    y_z_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZXWIndex(\n                    y_z_x_w_i_elementAct,\n                    y_z_x_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct)\n        {\n            Info.ForeachYZXWIndex(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_x_preLineAct,\n                    y_z_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZXWIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_x_preLineAct,\n                Action<long, long, long, long, long> y_z_x_w_i_elementAct,\n                Action<long, long, long> y_z_x_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZXWIndex(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_x_preLineAct,\n                    y_z_x_w_i_elementAct,\n                    y_z_x_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYZWXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYZWXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYZWXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct)\n        {\n            Info.ForeachYZWXIndex(\n                    y_z_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZWXIndex(\n                    y_z_w_x_i_elementAct,\n                    y_z_w_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct)\n        {\n            Info.ForeachYZWXIndex(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_w_preLineAct,\n                    y_z_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYZWXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_z_prePlaneAct,\n                Action<long, long, long> y_z_w_preLineAct,\n                Action<long, long, long, long, long> y_z_w_x_i_elementAct,\n                Action<long, long, long> y_z_w_postLineAct,\n                Action<long, long> y_z_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYZWXIndex(\n                    y_preVolumeAct,\n                    y_z_prePlaneAct,\n                    y_z_w_preLineAct,\n                    y_z_w_x_i_elementAct,\n                    y_z_w_postLineAct,\n                    y_z_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYWXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWXZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYWXZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct)\n        {\n            Info.ForeachYWXZIndex(\n                    y_w_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWXZIndex(\n                    y_w_x_z_i_elementAct,\n                    y_w_x_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct)\n        {\n            Info.ForeachYWXZIndex(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_x_preLineAct,\n                    y_w_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWXZIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_x_preLineAct,\n                Action<long, long, long, long, long> y_w_x_z_i_elementAct,\n                Action<long, long, long> y_w_x_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWXZIndex(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_x_preLineAct,\n                    y_w_x_z_i_elementAct,\n                    y_w_x_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYWZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachYWZXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachYWZXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct)\n        {\n            Info.ForeachYWZXIndex(\n                    y_w_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWZXIndex(\n                    y_w_z_x_i_elementAct,\n                    y_w_z_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct)\n        {\n            Info.ForeachYWZXIndex(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_z_preLineAct,\n                    y_w_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachYWZXIndex(\n                Action<long> y_preVolumeAct,\n                Action<long, long> y_w_prePlaneAct,\n                Action<long, long, long> y_w_z_preLineAct,\n                Action<long, long, long, long, long> y_w_z_x_i_elementAct,\n                Action<long, long, long> y_w_z_postLineAct,\n                Action<long, long> y_w_postPlaneAct,\n                Action<long> y_postVolumeAct)\n        {\n            Info.ForeachYWZXIndex(\n                    y_preVolumeAct,\n                    y_w_prePlaneAct,\n                    y_w_z_preLineAct,\n                    y_w_z_x_i_elementAct,\n                    y_w_z_postLineAct,\n                    y_w_postPlaneAct,\n                    y_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZXYWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXYWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZXYWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct)\n        {\n            Info.ForeachZXYWIndex(\n                    z_x_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXYWIndex(\n                    z_x_y_w_i_elementAct,\n                    z_x_y_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct)\n        {\n            Info.ForeachZXYWIndex(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_y_preLineAct,\n                    z_x_y_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXYWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_y_preLineAct,\n                Action<long, long, long, long, long> z_x_y_w_i_elementAct,\n                Action<long, long, long> z_x_y_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXYWIndex(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_y_preLineAct,\n                    z_x_y_w_i_elementAct,\n                    z_x_y_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXWYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZXWYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZXWYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZXWYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct)\n        {\n            Info.ForeachZXWYIndex(\n                    z_x_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXWYIndex(\n                    z_x_w_y_i_elementAct,\n                    z_x_w_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct)\n        {\n            Info.ForeachZXWYIndex(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_w_preLineAct,\n                    z_x_w_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZXWYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_x_prePlaneAct,\n                Action<long, long, long> z_x_w_preLineAct,\n                Action<long, long, long, long, long> z_x_w_y_i_elementAct,\n                Action<long, long, long> z_x_w_postLineAct,\n                Action<long, long> z_x_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZXWYIndex(\n                    z_preVolumeAct,\n                    z_x_prePlaneAct,\n                    z_x_w_preLineAct,\n                    z_x_w_y_i_elementAct,\n                    z_x_w_postLineAct,\n                    z_x_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXWIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZYXWIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYXWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZYXWIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct)\n        {\n            Info.ForeachZYXWIndex(\n                    z_y_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYXWIndex(\n                    z_y_x_w_i_elementAct,\n                    z_y_x_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct)\n        {\n            Info.ForeachZYXWIndex(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_x_preLineAct,\n                    z_y_x_w_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYXWIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_x_preLineAct,\n                Action<long, long, long, long, long> z_y_x_w_i_elementAct,\n                Action<long, long, long> z_y_x_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYXWIndex(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_x_preLineAct,\n                    z_y_x_w_i_elementAct,\n                    z_y_x_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYWXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZYWXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZYWXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZYWXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct)\n        {\n            Info.ForeachZYWXIndex(\n                    z_y_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYWXIndex(\n                    z_y_w_x_i_elementAct,\n                    z_y_w_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct)\n        {\n            Info.ForeachZYWXIndex(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_w_preLineAct,\n                    z_y_w_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZYWXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_y_prePlaneAct,\n                Action<long, long, long> z_y_w_preLineAct,\n                Action<long, long, long, long, long> z_y_w_x_i_elementAct,\n                Action<long, long, long> z_y_w_postLineAct,\n                Action<long, long> z_y_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZYWXIndex(\n                    z_preVolumeAct,\n                    z_y_prePlaneAct,\n                    z_y_w_preLineAct,\n                    z_y_w_x_i_elementAct,\n                    z_y_w_postLineAct,\n                    z_y_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZWXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWXYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZWXYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct)\n        {\n            Info.ForeachZWXYIndex(\n                    z_w_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWXYIndex(\n                    z_w_x_y_i_elementAct,\n                    z_w_x_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct)\n        {\n            Info.ForeachZWXYIndex(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_x_preLineAct,\n                    z_w_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWXYIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_x_preLineAct,\n                Action<long, long, long, long, long> z_w_x_y_i_elementAct,\n                Action<long, long, long> z_w_x_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWXYIndex(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_x_preLineAct,\n                    z_w_x_y_i_elementAct,\n                    z_w_x_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZWYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachZWYXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachZWYXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct)\n        {\n            Info.ForeachZWYXIndex(\n                    z_w_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWYXIndex(\n                    z_w_y_x_i_elementAct,\n                    z_w_y_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct)\n        {\n            Info.ForeachZWYXIndex(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_y_preLineAct,\n                    z_w_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachZWYXIndex(\n                Action<long> z_preVolumeAct,\n                Action<long, long> z_w_prePlaneAct,\n                Action<long, long, long> z_w_y_preLineAct,\n                Action<long, long, long, long, long> z_w_y_x_i_elementAct,\n                Action<long, long, long> z_w_y_postLineAct,\n                Action<long, long> z_w_postPlaneAct,\n                Action<long> z_postVolumeAct)\n        {\n            Info.ForeachZWYXIndex(\n                    z_preVolumeAct,\n                    z_w_prePlaneAct,\n                    z_w_y_preLineAct,\n                    z_w_y_x_i_elementAct,\n                    z_w_y_postLineAct,\n                    z_w_postPlaneAct,\n                    z_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXYZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWXYZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXYZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWXYZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct)\n        {\n            Info.ForeachWXYZIndex(\n                    w_x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXYZIndex(\n                    w_x_y_z_i_elementAct,\n                    w_x_y_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct)\n        {\n            Info.ForeachWXYZIndex(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_y_preLineAct,\n                    w_x_y_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXYZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_y_preLineAct,\n                Action<long, long, long, long, long> w_x_y_z_i_elementAct,\n                Action<long, long, long> w_x_y_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXYZIndex(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_y_preLineAct,\n                    w_x_y_z_i_elementAct,\n                    w_x_y_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXZYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWXZYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWXZYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWXZYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct)\n        {\n            Info.ForeachWXZYIndex(\n                    w_x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXZYIndex(\n                    w_x_z_y_i_elementAct,\n                    w_x_z_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct)\n        {\n            Info.ForeachWXZYIndex(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_z_preLineAct,\n                    w_x_z_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWXZYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_x_prePlaneAct,\n                Action<long, long, long> w_x_z_preLineAct,\n                Action<long, long, long, long, long> w_x_z_y_i_elementAct,\n                Action<long, long, long> w_x_z_postLineAct,\n                Action<long, long> w_x_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWXZYIndex(\n                    w_preVolumeAct,\n                    w_x_prePlaneAct,\n                    w_x_z_preLineAct,\n                    w_x_z_y_i_elementAct,\n                    w_x_z_postLineAct,\n                    w_x_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYXZIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWYXZIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYXZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWYXZIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct)\n        {\n            Info.ForeachWYXZIndex(\n                    w_y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYXZIndex(\n                    w_y_x_z_i_elementAct,\n                    w_y_x_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct)\n        {\n            Info.ForeachWYXZIndex(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_x_preLineAct,\n                    w_y_x_z_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYXZIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_x_preLineAct,\n                Action<long, long, long, long, long> w_y_x_z_i_elementAct,\n                Action<long, long, long> w_y_x_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYXZIndex(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_x_preLineAct,\n                    w_y_x_z_i_elementAct,\n                    w_y_x_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYZXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWYZXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWYZXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWYZXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct)\n        {\n            Info.ForeachWYZXIndex(\n                    w_y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYZXIndex(\n                    w_y_z_x_i_elementAct,\n                    w_y_z_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct)\n        {\n            Info.ForeachWYZXIndex(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_z_preLineAct,\n                    w_y_z_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWYZXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_y_prePlaneAct,\n                Action<long, long, long> w_y_z_preLineAct,\n                Action<long, long, long, long, long> w_y_z_x_i_elementAct,\n                Action<long, long, long> w_y_z_postLineAct,\n                Action<long, long> w_y_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWYZXIndex(\n                    w_preVolumeAct,\n                    w_y_prePlaneAct,\n                    w_y_z_preLineAct,\n                    w_y_z_x_i_elementAct,\n                    w_y_z_postLineAct,\n                    w_y_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZXYIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWZXYIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZXYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWZXYIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct)\n        {\n            Info.ForeachWZXYIndex(\n                    w_z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZXYIndex(\n                    w_z_x_y_i_elementAct,\n                    w_z_x_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct)\n        {\n            Info.ForeachWZXYIndex(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_x_preLineAct,\n                    w_z_x_y_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZXYIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_x_preLineAct,\n                Action<long, long, long, long, long> w_z_x_y_i_elementAct,\n                Action<long, long, long> w_z_x_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZXYIndex(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_x_preLineAct,\n                    w_z_x_y_i_elementAct,\n                    w_z_x_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZYXIndex(\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWZYXIndex(\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct)\n        {\n            Info.ForeachWZYXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action preVolumeAct,\n                Action prePlaneAct,\n                Action preLineAct,\n                Action<long> i_elementAct,\n                Action postLineAct,\n                Action postPlaneAct,\n                Action postVolumeAct)\n        {\n            Info.ForeachWZYXIndex(\n                    preVolumeAct,\n                    prePlaneAct,\n                    preLineAct,\n                    i_elementAct,\n                    postLineAct,\n                    postPlaneAct,\n                    postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct)\n        {\n            Info.ForeachWZYXIndex(\n                    w_z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZYXIndex(\n                    w_z_y_x_i_elementAct,\n                    w_z_y_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct)\n        {\n            Info.ForeachWZYXIndex(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_y_preLineAct,\n                    w_z_y_x_i_elementAct);\n        }\n\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        public readonly void ForeachWZYXIndex(\n                Action<long> w_preVolumeAct,\n                Action<long, long> w_z_prePlaneAct,\n                Action<long, long, long> w_z_y_preLineAct,\n                Action<long, long, long, long, long> w_z_y_x_i_elementAct,\n                Action<long, long, long> w_z_y_postLineAct,\n                Action<long, long> w_z_postPlaneAct,\n                Action<long> w_postVolumeAct)\n        {\n            Info.ForeachWZYXIndex(\n                    w_preVolumeAct,\n                    w_z_prePlaneAct,\n                    w_z_y_preLineAct,\n                    w_z_y_x_i_elementAct,\n                    w_z_y_postLineAct,\n                    w_z_postPlaneAct,\n                    w_postVolumeAct);\n        }\n\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4Window(V4l begin, V4l size)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4Window(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4(V4l begin, V4l size)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4Window(V4i begin, V4i size)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4Window(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4(V4i begin, V4i size)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4(begin, size))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4Window(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4Window(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4Window(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4Window(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4(begin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4Window(V4l begin, V4l size, V4l delta, V4l first)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4Window(begin, size, delta, first))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4Window(V4i begin, V4i size, V4i delta, V4i first)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubTensor4Window(begin, size, delta, first))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4Window(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4<Td, Tv>(Data,\n                            Info.SubTensor4Window(beginX, beginY, beginZ, beginW,\n                                           sizeX, sizeY, sizeZ, sizeW))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4<Td, Tv>(Data,\n                            Info.SubTensor4(beginX, beginY, beginZ, beginW,\n                                               sizeX, sizeY, sizeZ, sizeW))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4Window(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4<Td, Tv>(Data,\n                            Info.SubTensor4Window(beginX, beginY, beginZ, beginW,\n                                           sizeX, sizeY, sizeZ, sizeW,\n                                           deltaX, deltaY, deltaZ, deltaW))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubTensor4(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4<Td, Tv>(Data,\n                            Info.SubTensor4(beginX, beginY, beginZ, beginW,\n                                               sizeX, sizeY, sizeZ, sizeW,\n                                               deltaX, deltaY, deltaZ, deltaW))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, Tv> AsVector()\n        {\n            return new Vector<Td, Tv>(Data, Info.AsVector())\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(V4l origin, long size, long delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(origin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, Tv> SubVector(V4i origin, long size, long delta)\n        {\n            return new Vector<Td, Tv>(Data, Info.SubVector(origin, size, delta))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubYZWVolume(long x)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubYZWVolume(x))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubYZWVolumeAsReadOnlyTensor4(long x, long sizex)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubYZWVolumeAsReadOnlyTensor4(x, sizex))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubYZWVolumeWindow(long x)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubYZWVolumeWindow(x))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubYZWVolumeAsReadOnlyTensor4Window(long x, long sizex)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubYZWVolumeAsReadOnlyTensor4Window(x, sizex))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXZWVolume(long y)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXZWVolume(y))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXZWVolumeAsReadOnlyTensor4(long y, long sizey)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXZWVolumeAsReadOnlyTensor4(y, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXZWVolumeWindow(long y)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXZWVolumeWindow(y))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXZWVolumeAsReadOnlyTensor4Window(long y, long sizey)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXZWVolumeAsReadOnlyTensor4Window(y, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXYWVolume(long z)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXYWVolume(z))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXYWVolumeAsReadOnlyTensor4(long z, long sizez)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXYWVolumeAsReadOnlyTensor4(z, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXYWVolumeWindow(long z)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXYWVolumeWindow(z))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXYWVolumeAsReadOnlyTensor4Window(long z, long sizez)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXYWVolumeAsReadOnlyTensor4Window(z, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXYZVolume(long w)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXYZVolume(w))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXYZVolumeAsReadOnlyTensor4(long w, long sizew)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXYZVolumeAsReadOnlyTensor4(w, sizew))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, Tv> SubXYZVolumeWindow(long w)\n        {\n            return new Volume<Td, Tv>(Data, Info.SubXYZVolumeWindow(w))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXYZVolumeAsReadOnlyTensor4Window(long w, long sizew)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXYZVolumeAsReadOnlyTensor4Window(w, sizew))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubZWMatrixAsReadOnlyTensor4(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubZWMatrixAsReadOnlyTensor4(x, y, sizex, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubZWMatrixAsReadOnlyTensor4Window(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubZWMatrixAsReadOnlyTensor4Window(x, y, sizex, sizey))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubYWMatrixAsReadOnlyTensor4(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubYWMatrixAsReadOnlyTensor4(x, z, sizex, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubYWMatrixAsReadOnlyTensor4Window(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubYWMatrixAsReadOnlyTensor4Window(x, z, sizex, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubYZMatrixAsReadOnlyTensor4(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubYZMatrixAsReadOnlyTensor4(x, w, sizex, sizew))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubYZMatrixAsReadOnlyTensor4Window(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubYZMatrixAsReadOnlyTensor4Window(x, w, sizex, sizew))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXWMatrixAsReadOnlyTensor4(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXWMatrixAsReadOnlyTensor4(y, z, sizey, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXWMatrixAsReadOnlyTensor4Window(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXWMatrixAsReadOnlyTensor4Window(y, z, sizey, sizez))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXZMatrixAsReadOnlyTensor4(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXZMatrixAsReadOnlyTensor4(y, w, sizey, sizew))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXZMatrixAsReadOnlyTensor4Window(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXZMatrixAsReadOnlyTensor4Window(y, w, sizey, sizew))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXYMatrixAsReadOnlyTensor4(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXYMatrixAsReadOnlyTensor4(z, w, sizez, sizew))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SubXYMatrixAsReadOnlyTensor4Window(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4<Td, Tv>(Data, Info.SubXYMatrixAsReadOnlyTensor4Window(z, w, sizez, sizew))\n                                    { Getter = Getter, Setter = Setter };\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4l begin, V4l size)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(V4l begin, V4l size)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4i begin, V4i size)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(V4i begin, V4i size)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4(begin, size));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(V4l begin, V4l size, V4l delta)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(V4i begin, V4i size, V4i delta)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4(begin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4l begin, V4l size, V4l delta, V4l first)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(V4i begin, V4i size, V4i delta, V4i first)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubTensor4Window(begin, size, delta, first));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4<Td, T1>(Data,\n                            Info.SubTensor4Window(beginX, beginY, beginZ, beginW,\n                                           sizeX, sizeY, sizeZ, sizeW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW)\n        {\n            return new Tensor4<Td, T1>(Data,\n                            Info.SubTensor4(beginX, beginY, beginZ, beginW,\n                                               sizeX, sizeY, sizeZ, sizeW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4Window<T1>(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4<Td, T1>(Data,\n                            Info.SubTensor4Window(beginX, beginY, beginZ, beginW,\n                                           sizeX, sizeY, sizeZ, sizeW,\n                                           deltaX, deltaY, deltaZ, deltaW));\n        }\n\n        /// <summary>\n        /// A SubTensor4 does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubTensor4<T1>(\n                long beginX, long beginY, long beginZ, long beginW,\n                long sizeX, long sizeY, long sizeZ, long sizeW,\n                long deltaX, long deltaY, long deltaZ, long deltaW)\n        {\n            return new Tensor4<Td, T1>(Data,\n                            Info.SubTensor4(beginX, beginY, beginZ, beginW,\n                                               sizeX, sizeY, sizeZ, sizeW,\n                                               deltaX, deltaY, deltaZ, deltaW));\n        }\n\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// </summary>\n        public readonly Vector<Td, T1> AsVector<T1>()\n        {\n            return new Vector<Td, T1>(Data, Info.AsVector());\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V4l origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly Vector<Td, T1> SubVector<T1>(V4i origin, long size, long delta)\n        {\n            return new Vector<Td, T1>(Data, Info.SubVector(origin, size, delta));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYZWVolume<T1>(long x)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYZWVolume(x));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYZWVolumeAsReadOnlyTensor4<T1>(long x, long sizex)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYZWVolumeAsReadOnlyTensor4(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, T1> SubYZWVolumeWindow<T1>(long x)\n        {\n            return new Volume<Td, T1>(Data, Info.SubYZWVolumeWindow(x));\n        }\n\n        /// <summary>\n        /// Return a full YZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYZWVolumeAsReadOnlyTensor4Window<T1>(long x, long sizex)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYZWVolumeAsReadOnlyTensor4Window(x, sizex));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXZWVolume<T1>(long y)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXZWVolume(y));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXZWVolumeAsReadOnlyTensor4<T1>(long y, long sizey)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXZWVolumeAsReadOnlyTensor4(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXZWVolumeWindow<T1>(long y)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXZWVolumeWindow(y));\n        }\n\n        /// <summary>\n        /// Return a full XZW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXZWVolumeAsReadOnlyTensor4Window<T1>(long y, long sizey)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXZWVolumeAsReadOnlyTensor4Window(y, sizey));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYWVolume<T1>(long z)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYWVolume(z));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYWVolumeAsReadOnlyTensor4<T1>(long z, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYWVolumeAsReadOnlyTensor4(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYWVolumeWindow<T1>(long z)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYWVolumeWindow(z));\n        }\n\n        /// <summary>\n        /// Return a full XYW volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYWVolumeAsReadOnlyTensor4Window<T1>(long z, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYWVolumeAsReadOnlyTensor4Window(z, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYZVolume<T1>(long w)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYZVolume(w));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a volume with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYZVolumeAsReadOnlyTensor4<T1>(long w, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYZVolumeAsReadOnlyTensor4(w, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Volume<Td, T1> SubXYZVolumeWindow<T1>(long w)\n        {\n            return new Volume<Td, T1>(Data, Info.SubXYZVolumeWindow(w));\n        }\n\n        /// <summary>\n        /// Return a full XYZ volume slice of the tensor4 as a special tensor4\n        /// that replicates the volume the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYZVolumeAsReadOnlyTensor4Window<T1>(long w, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYZVolumeAsReadOnlyTensor4Window(w, sizew));\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubZWMatrixAsReadOnlyTensor4<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubZWMatrixAsReadOnlyTensor4(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full ZW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubZWMatrixAsReadOnlyTensor4Window<T1>(long x, long y, long sizex, long sizey)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubZWMatrixAsReadOnlyTensor4Window(x, y, sizex, sizey));\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYWMatrixAsReadOnlyTensor4<T1>(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYWMatrixAsReadOnlyTensor4(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full YW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYWMatrixAsReadOnlyTensor4Window<T1>(long x, long z, long sizex, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYWMatrixAsReadOnlyTensor4Window(x, z, sizex, sizez));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYZMatrixAsReadOnlyTensor4<T1>(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYZMatrixAsReadOnlyTensor4(x, w, sizex, sizew));\n        }\n\n        /// <summary>\n        /// Return a full YZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubYZMatrixAsReadOnlyTensor4Window<T1>(long x, long w, long sizex, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubYZMatrixAsReadOnlyTensor4Window(x, w, sizex, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXWMatrixAsReadOnlyTensor4<T1>(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXWMatrixAsReadOnlyTensor4(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XW matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXWMatrixAsReadOnlyTensor4Window<T1>(long y, long z, long sizey, long sizez)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXWMatrixAsReadOnlyTensor4Window(y, z, sizey, sizez));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXZMatrixAsReadOnlyTensor4<T1>(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXZMatrixAsReadOnlyTensor4(y, w, sizey, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XZ matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXZMatrixAsReadOnlyTensor4Window<T1>(long y, long w, long sizey, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXZMatrixAsReadOnlyTensor4Window(y, w, sizey, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This methods returns a tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYMatrixAsReadOnlyTensor4<T1>(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYMatrixAsReadOnlyTensor4(z, w, sizez, sizew));\n        }\n\n        /// <summary>\n        /// Return a full XY matrix slice of the tensor4 as a special tensor4\n        /// that replicates the matrix the supplied number of times. The special\n        /// tensor4 can only be correctly used to read from. Other operations are not guaranteed.\n        /// This method retains the coordinates of the parent tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, T1> SubXYMatrixAsReadOnlyTensor4Window<T1>(long z, long w, long sizez, long sizew)\n        {\n            return new Tensor4<Td, T1>(Data, Info.SubXYMatrixAsReadOnlyTensor4Window(z, w, sizez, sizew));\n        }\n\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> Copy()\n        {\n            return new Tensor4<Td, Tv>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CopyWindow()\n        {\n            return new Tensor4<Td, Tv>(Info.S)\n                    { F = F, Getter = Getter, Setter = Setter }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<T1> Map<T1>(Func<Tv, T1> fun)\n        {\n            return new Tensor4<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original Tensor4.\n        /// </summary>\n        public readonly Tensor4<T1> MapWindow<T1>(Func<Tv, T1> fun)\n        {\n            return new Tensor4<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        public readonly Tensor4<Tv> CopyView()\n        {\n            return new Tensor4<Tv>(Info.S).Set(this);\n        }\n\n        public readonly Tensor4<Tv> CopyViewWindow()\n        {\n            return new Tensor4<Tv>(Info.S) { F = F }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a Tensor4 with zero as first coordinates.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> Map(Func<Tv, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the complete layout of the original Tensor4.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> MapWindow(Func<Tv, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new Td[Data.LongLength], Info)\n                        { F = F, Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the tensor4.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> Apply(Func<Tv, Tv> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long we = i + Info.DSW, wj = Info.JW; i != we; i += wj)\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj)\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.SX; i != xe; i++)\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n            }\n            else\n            {\n                for (long we = i + Info.DSW, wj = Info.JW; i != we; i += wj)\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj)\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj)\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj)\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original tensor4 and the supplied tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> Apply<T1>(\n                Tensor4<T1> t1, Func<Tv, T1, Tv> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Data[i1]));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original tensor4 and the supplied tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> Apply<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<Tv, T1, Tv> element_element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element_element1_elementFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the tensor4.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> ApplyByCoord(Func<Tv, V4l, Tv> element_crd_elementFun)\n        {\n            long i = FirstIndex; V4l vi;\n            if (Info.JX == 1)\n            {\n                vi.W = First.W;\n                for (long we = i + Info.DSW, wj = Info.JW; i != we; i += wj, vi.W++)\n                {\n                vi.Z = First.Z;\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj, vi.Z++)\n                {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.SX; i != xe; i++, vi.X++)\n                    Setter(Data, i, element_crd_elementFun(Getter(Data, i), vi));\n                }\n                }\n                }\n            }\n            else\n            {\n                vi.W = First.W;\n                for (long we = i + Info.DSW, wj = Info.JW; i != we; i += wj, vi.W++)\n                {\n                vi.Z = First.Z;\n                for (long ze = i + Info.DSZ, zj = Info.JZ; i != ze; i += zj, vi.Z++)\n                {\n                vi.Y = First.Y;\n                for (long ye = i + Info.DSY, yj = Info.JY; i != ye; i += yj, vi.Y++)\n                {\n                vi.X = First.X;\n                for (long xe = i + Info.DSX, xj = Info.JX; i != xe; i += xj, vi.X++)\n                {\n                    Setter(Data, i, element_crd_elementFun(Getter(Data, i), vi));\n                }\n                }\n                }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> ApplyByCoord(Func<Tv, long, long, long, long, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                for (long we = i + Info.DSW, wj = Info.JW, w = Info.FW; i != we; i += wj, w++)\n                for (long ze = i + Info.DSZ, zj = Info.JZ, z = Info.FZ; i != ze; i += zj, z++)\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    Setter(Data, i, fun(Getter(Data, i), x, y, z, w));\n            }\n            else\n            {\n                for (long we = i + Info.DSW, wj = Info.JW, w = Info.FW; i != we; i += wj, w++)\n                for (long ze = i + Info.DSZ, zj = Info.JZ, z = Info.FZ; i != ze; i += zj, z++)\n                for (long ye = i + Info.DSY, yj = Info.JY, y = Info.FY; i != ye; i += yj, y++)\n                for (long xe = i + Info.DSX, xj = Info.JX, x = Info.FX; i != xe; i += xj, x++)\n                    Setter(Data, i, fun(Getter(Data, i), x, y, z, w));\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> Set(Tv v)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Setter(Data, i, v);\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    Setter(Data, i, v);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Setter(Data, i, v);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByCoord(Func<long, long, long, long, Tv> x_y_z_w_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(Data, i, x_y_z_w_elementFun(x, y, z, w));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    Setter(Data, i, x_y_z_w_elementFun(x, y, z, w));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, x_y_z_w_elementFun(x, y, z, w));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByCoord(Func<V4l, Tv> crd_elementFun)\n        {\n            long i = FirstIndex; V4l v;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.W = FW; for (long we = i + ws; i != we; i++, v.W++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    Setter(Data, i, crd_elementFun(v));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByCoord<Tw, Tz, Ty>(\n                Func<long, Tw> wFun,\n                Func<long, long, Tw, Tz> zFun,\n                Func<long, long, long, Tw, Tz, Ty> yFun,\n                Func<long, long, long, long, Tw, Tz, Ty, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = Info.FW; i != we; i += wj, w++) {\n                    var wVal = wFun(w);\n                for (long ze = i + zs, z = Info.FZ; i != ze; i += zj, z++) {\n                    var zVal = zFun(w, z, wVal);\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(w, z, y, wVal, zVal);\n                for (long xe = i + xs, x = Info.FX; i != xe; i++, x++) {\n                    Setter(Data, i, fun(w, z, y, x, wVal, zVal, yVal));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = Info.FW; i != we; i += wj, w++) {\n                    var wVal = wFun(w);\n                for (long ze = i + zs, z = Info.FZ; i != ze; i += zj, z++) {\n                    var zVal = zFun(w, z, wVal);\n                for (long ye = i + ys, y = Info.FY; i != ye; i += yj, y++) {\n                    var yVal = yFun(w, z, y, wVal, zVal);\n                for (long xe = i + xs, x = Info.FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, fun(w, z, y, x, wVal, zVal, yVal));\n                } } } }\n            }\n\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex(Func<long, Tv> index_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    Setter(Data, i, index_elementFun(i));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    Setter(Data, i, index_elementFun(i));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    Setter(Data, i, index_elementFun(i));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly Tensor4<Td, Tv> Set(ITensor4<Tv> it1)\n        {\n            if (it1 is Tensor4<Tv>) return Set((Tensor4<Tv>)it1);\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    Setter(Data, i, it1[x, y, z, w]);\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    Setter(Data, i, it1[x, y, z, w]);\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    Setter(Data, i, it1[x, y, z, w]);\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> Set(Tensor4<Tv> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, t1.Data[i1]);\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// the elements of the supplied tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap<T1>(\n                Tensor4<T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element1_elementFun(t1.Data[i1]));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1>(\n                Tensor4<T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Copy all elements from another tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> Set<T1>(Tensor4<T1, Tv> t1)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, t1.Getter(t1.Data, i1));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// the elements of the supplied tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, element1_elementFun(t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        Setter(Data, i, index1_elementFun(i1));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap2<T1, T2>(\n                    Tensor4<T1> t1, Tensor4<T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Data[i2]));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1, T2>(\n                Tensor4<T1> t1, Tensor4<T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap2<T1, T2d, T2>(\n                    Tensor4<T1> t1, Tensor4<T2d, T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2)));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1, T2d, T2>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap2<T1d, T1, T2>(\n                    Tensor4<T1d, T1> t1, Tensor4<T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2]));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1d, T1, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor4 to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap2<T1d, T1, T2d, T2>(\n                    Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2,\n                    Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n            Setter(Data, i, element1_element2_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2)));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1d, T1, T2d, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2) {\n                        Setter(Data, i, index1_index2_elementFun(i1, i2));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap3<T1, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Data[i3]));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap3<T1, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap3<T1, T2d, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1, T2d, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap3<T1, T2d, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Data[i1], t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1, T2d, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap3<T1d, T1, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Data[i3]));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1d, T1, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap3<T1d, T1, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Data[i2], t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1d, T1, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap3<T1d, T1, T2d, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Data[i3]));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1d, T1, T2d, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetMap3<T1d, T1, T2d, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n            Setter(Data, i, element1_element2_element3_elementFun(t1.Getter(t1.Data, i1), t2.Getter(t2.Data, i2), t3.Getter(t3.Data, i3)));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the\n        /// tensor4.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            Info.CheckMatchingSize(t1.Info, t2.Info, t3.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex, i2 = t2.FirstIndex, i3 = t3.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1 && t2.Info.DX == 1 && t3.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1 && t2.Info.DW == 1 && t3.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY, zj2 = t2.Info.JZY, zj3 = t3.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX, yj2 = t2.Info.JYX, yj3 = t3.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW, xj2 = t2.Info.JXW, xj3 = t3.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                    for (long we = i + ws; i != we; i++, i1++, i2++, i3++) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW, wj2 = t2.Info.JW, wj3 = t3.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ, zj2 = t2.Info.JZ, zj3 = t3.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY, yj2 = t2.Info.JY, yj3 = t3.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX, xj2 = t2.Info.JX, xj3 = t3.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1, i2 += wj2, i3 += wj3) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1, i2 += zj2, i3 += zj3) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1, i2 += yj2, i3 += yj3) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1, i2 += xj2, i3 += xj3) {\n                        Setter(Data, i, index1_index2_index3_elementFun(i1, i2, i3));\n                    } } } }\n                }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the tensor4 to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> SetConvolution<Ti, Tf, Tm, Ts>(\n                Tensor4<Ti> image, Tensor4<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Tv> castFun)\n        {\n            Info.CheckMatchingSize(new Tensor4Info(V4l.One + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.SubTensor4(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Tx, Ty, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Data[i3], tw.Data[i4]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Data[i3], tw.Data[i4]));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Tx, Ty, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Data[i3], tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Data[i3], tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Tx, Ty, Tzd, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3), tw.Data[i4]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3), tw.Data[i4]));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Tx, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Data[i2], tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Tx, Tyd, Ty, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3], tw.Data[i4]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3], tw.Data[i4]));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Tx, Tyd, Ty, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3], tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Data[i3], tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Data[i4]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Data[i4]));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Data[i1], ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Txd, Tx, Ty, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3], tw.Data[i4]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3], tw.Data[i4]));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Txd, Tx, Ty, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3], tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Data[i3], tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Txd, Tx, Ty, Tzd, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3), tw.Data[i4]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3), tw.Data[i4]));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Txd, Tx, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Data[i2], tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Txd, Tx, Tyd, Ty, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3], tw.Data[i4]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3], tw.Data[i4]));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Txd, Tx, Tyd, Ty, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3], tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Data[i3], tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Data[i4]));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Data[i4]));\n                } } } }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly Tensor4<Td, Tv> SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    Setter(Data, i, fun(tx.Getter(tx.Data, i1), ty.Getter(ty.Data, i2), tz.Getter(tz.Data, i3), tw.Getter(tw.Data, i4)));\n                } } } }\n            }\n            return this;\n        }\n\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Tv, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, long, long, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z, w));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z, w));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z, w));\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, V4l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V4l v;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.W = FW; for (long we = i + ws; i != we; i++, v.W++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Tensor4<T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                    } } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Tensor4<T1d, T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                    } } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(\n                Func<Tv, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                for (long we = i + ws; i != we; i++) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws; i != we; i += wj) {\n                for (long ze = i + zs; i != ze; i += zj) {\n                for (long ye = i + ys; i != ye; i += yj) {\n                for (long xe = i + xs; i != xe; i += xj) {\n                    result = sumFun(result, elementFun(Getter(Data, i)));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, long, long, long, long, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i++, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z, w));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                for (long we = i + ws, w = FW; i != we; i++, w++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z, w));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                for (long we = i + ws, w = FW; i != we; i += wj, w++) {\n                for (long ze = i + zs, z = FZ; i != ze; i += zj, z++) {\n                for (long ye = i + ys, y = FY; i != ye; i += yj, y++) {\n                for (long xe = i + xs, x = FX; i != xe; i += xj, x++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), x, y, z, w));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<Tv, V4l, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun, Func<Tr, bool> breakIfTrueFun)\n        {\n            Tr result = bias;\n            long i = FirstIndex; V4l v;\n            if (Info.DX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i++, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else if (Info.DW == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZY;\n                long ys = Info.DSY, yj = Info.JYX;\n                long xs = Info.DSX, xj = Info.JXW;\n                long ws = Info.SW;\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                v.W = FW; for (long we = i + ws; i != we; i++, v.W++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.DSX, xj = Info.JX;\n                v.W = FW; for (long we = i + ws; i != we; i += wj, v.W++) {\n                v.Z = FZ; for (long ze = i + zs; i != ze; i += zj, v.Z++) {\n                v.Y = FY; for (long ye = i + ys; i != ye; i += yj, v.Y++) {\n                v.X = FX; for (long xe = i + xs; i != xe; i += xj, v.X++) {\n                    result = sumFun(result, elementFun(Getter(Data, i), v));\n                    if (breakIfTrueFun(result)) return result;\n                } } } }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1, Tm, Ts>(\n            Tensor4<T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Data[i1]));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n            }\n            return result;\n        }\n\n        public readonly Ts InnerProduct<T1d, T1, Tm, Ts>(\n            Tensor4<T1d, T1> t1,\n            Func<Tv, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, bool> breakIfTrueFun)\n        {\n            Ts result = bias;\n            Info.CheckMatchingSize(t1.Info);\n            {\n                long i = FirstIndex, i1 = t1.FirstIndex;\n                if (Info.DX == 1 && t1.Info.DX == 1)\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.SX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else if (Info.DW == 1 && t1.Info.DW == 1)\n                {\n                    long zs = Info.DSZ, zj = Info.JZY, zj1 = t1.Info.JZY;\n                    long ys = Info.DSY, yj = Info.JYX, yj1 = t1.Info.JYX;\n                    long xs = Info.DSX, xj = Info.JXW, xj1 = t1.Info.JXW;\n                    long ws = Info.SW;\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                    for (long we = i + ws; i != we; i++, i1++) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n                else\n                {\n                    long ws = Info.DSW, wj = Info.JW, wj1 = t1.Info.JW;\n                    long zs = Info.DSZ, zj = Info.JZ, zj1 = t1.Info.JZ;\n                    long ys = Info.DSY, yj = Info.JY, yj1 = t1.Info.JY;\n                    long xs = Info.DSX, xj = Info.JX, xj1 = t1.Info.JX;\n                    for (long we = i + ws; i != we; i += wj, i1 += wj1) {\n                    for (long ze = i + zs; i != ze; i += zj, i1 += zj1) {\n                    for (long ye = i + ys; i != ye; i += yj, i1 += yj1) {\n                    for (long xe = i + xs; i != xe; i += xj, i1 += xj1) {\n                        result = sumFun(result, mulFun(Getter(Data, i), t1.Getter(t1.Data, i1)));\n                        if (breakIfTrueFun(result)) return result;\n                    } } } }\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n        #region Creator Functions\n\n        /// <summary>\n        /// Create a new tensor4 as copy of the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Create(\n                Tensor4<Tv> t1)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 as copy of the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Create<T1d>(\n                Tensor4<T1d, Tv> t1)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).Set(t1);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map<T1>(\n                Tensor4<T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1>(\n                Tensor4<T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<T1, Tv> element1_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1d, T1>(\n                Tensor4<T1d, T1> t1, Func<long, Tv> index1_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map2<T1, T2>(\n                Tensor4<T1> t1, Tensor4<T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1, T2>(\n                Tensor4<T1> t1, Tensor4<T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map2<T1, T2d, T2>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1, T2d, T2>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map2<T1d, T1, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1d, T1, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map2<T1d, T1, T2d, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2,\n                Func<T1, T2, Tv> element1_element2_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1d, T1, T2d, T2>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2,\n                Func<long, long, Tv> index1_index2_fun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map3<T1, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map3<T1, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map3<T1, T2d, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1, T2d, T2, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map3<T1, T2d, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1, T2d, T2, T3d, T3>(\n                Tensor4<T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map3<T1d, T1, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1d, T1, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map3<T1d, T1, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1d, T1, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map3<T1d, T1, T2d, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1d, T1, T2d, T2, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function on each element of\n        /// the supplied tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Map3<T1d, T1, T2d, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<T1, T2, T3, Tv> element1_element2_element3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to each index of the\n        /// elements of the supplied tensor4. The function may access the\n        /// elements of the supplied tensor4 to compute the elements of the new\n        /// tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateByIndex<T1d, T1, T2d, T2, T3d, T3>(\n                Tensor4<T1d, T1> t1, Tensor4<T2d, T2> t2, Tensor4<T3d, T3> t3,\n                Func<long, long, long, Tv> index1_index2_index3_elementFun)\n        {\n            return new Tensor4<Td, Tv>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new tensor4 by applying a function to the coordinates of\n        /// the elements the newly created tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> Create(V4l size, Func<V4l, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new Tensor4 by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting Tensor4.\n        /// </summary>\n        public static Tensor4<Td, Tv> CreateConvolution<Ti, Tf, Tm, Ts>(\n                Tensor4<Ti> image, Tensor4<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, Tv> castFun)\n        {\n            V4l size = 1 + image.S - filter.S;\n            if (size.W <= 0 ||size.Z <= 0 ||size.Y <= 0 ||size.X <= 0) throw new Exception(\"filter to large\");\n            return new Tensor4<Td, Tv>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Tx, Ty, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Ty, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Tx, Ty, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Ty, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Tx, Ty, Tzd, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Ty, Tzd, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Tx, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Ty, Tzd, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Tx, Tyd, Ty, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Tx, Tyd, Ty, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Txd, Tx, Ty, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Txd, Tx, Ty, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Txd, Tx, Ty, Tzd, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tzd, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Txd, Tx, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Ty, Tzd, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly Tensor4<Td, Tv> CreateOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(\n                    Vector<Txd, Tx> tx, Vector<Tyd, Ty> ty, Vector<Tzd, Tz> tz, Vector<Twd, Tw> tw,\n                    Func<Tx, Ty, Tz, Tw, Tv> fun)\n        {\n            return new Tensor4<Td, Tv>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<Txd, Tx, Tyd, Ty, Tzd, Tz, Twd, Tw>(tx, ty, tz, tw, fun);\n        }\n\n        #endregion\n\n        #region Sampling\n\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return SampleRaw16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl);\n        }\n\n        /// <summary>\n        /// Sample the tensor4 using 16 samples and the supplied\n        /// interpolation functions. If only integer coordinates are\n        /// supplied the returned value is the same as the indexer\n        /// of the tensor4, i.e. voxel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            double wid = Fun.Floor(w); long wi = (long)wid; double wf = w - wid; long dw = Info.Delta.W;\n            long i = Info.Origin + xi * dx + yi * dy + zi * dz + wi * dw;\n            long ix = i + dx, iy = i + dy, ixy = ix + dy;\n            long iz = i + dz, ixz = ix + dz, iyz = iy + dz, ixyz = ixy + dz;\n            return wipl(wf, zipl(zf, yipl(yf, xipl(xf, Getter(Data, i), Getter(Data, ix)),\n                                              xipl(xf, Getter(Data, iy), Getter(Data, ixy))),\n                                     yipl(yf, xipl(xf, Getter(Data, iz), Getter(Data, ixz)),\n                                              xipl(xf, Getter(Data, iyz), Getter(Data, ixyz)))),\n                            zipl(zf, yipl(yf, xipl(xf, Getter(Data, i + dw), Getter(Data, ix + dw)),\n                                              xipl(xf, Getter(Data, iy + dw), Getter(Data, ixy + dw))),\n                                     yipl(yf, xipl(xf, Getter(Data, iz + dw), Getter(Data, ixz + dw)),\n                                              xipl(xf, Getter(Data, iyz + dw), Getter(Data, ixyz + dw)))));\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return Sample16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return Sample16(x, y, z, w, xipl, yipl, zipl, wipl,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_wIndexFun)\n        {\n            return Sample16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun,\n                            index_min_max_delta_zIndexFun,\n                            index_min_max_delta_wIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the tensor4 using 16 neighbouring samples and the\n        /// supplied interpolation functions and border handling functions.\n        /// If only integer coordinates are supplied the returned value is\n        /// the same as the indexer of the tensor4, i.e. voxel centers are\n        /// assumed to be on integer coordinates.\n        /// </summary>\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, Tv, Tv, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_wIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            double wid = Fun.Floor(w); long wi = (long)wid; double wf = w - wid; long dw1 = Info.Delta.W;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1 + wi * dw1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1); dx.E0 += i; dx.E1 += i;\n            var dyzw = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                    index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1),\n                                    index_min_max_delta_wIndexFun(wi, FW, EW, dw1));\n            return wipl(wf, zipl(zf, yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyzw.E0), Getter(Data, dx.E1 + dyzw.E0)),\n                                              xipl(xf, Getter(Data, dx.E0 + dyzw.E1), Getter(Data, dx.E1 + dyzw.E1))),\n                                     yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyzw.E2), Getter(Data, dx.E1 + dyzw.E2)),\n                                              xipl(xf, Getter(Data, dx.E0 + dyzw.E3), Getter(Data, dx.E1 + dyzw.E3)))),\n                            zipl(zf, yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyzw.E4), Getter(Data, dx.E1 + dyzw.E4)),\n                                              xipl(xf, Getter(Data, dx.E0 + dyzw.E5), Getter(Data, dx.E1 + dyzw.E5))),\n                                     yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyzw.E6), Getter(Data, dx.E1 + dyzw.E6)),\n                                              xipl(xf, Getter(Data, dx.E0 + dyzw.E7), Getter(Data, dx.E1 + dyzw.E7)))));\n        }\n\n        #endregion\n\n        #region ITensor4\n\n        /// <summary>\n        /// Dimension of the generic Tensor4.\n        /// </summary>\n        public readonly V4l Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(long x, long y, long z, long w)\n        {\n            return (object)this[x, y, z, w];\n        }\n\n        public readonly void SetValue(object value, long x, long y, long z, long w)\n        {\n            this[x, y, z, w] = (Tv)value;\n        }\n\n        public readonly object GetValue(V4l v)\n        {\n            return (object)this[v];\n        }\n\n        public readonly void SetValue(object value, V4l v)\n        {\n            this[v] = (Tv)value;\n        }\n\n        #endregion\n\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensor_template.cs",
    "content": "using System;\nusing System.Diagnostics;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    //# Action<Action> Ignore = a => {};\n    //# Action space = () => Out(\" \");\n    //# Action comma = () => Out(\", \");\n    //# Action add = () => Out(\" + \");\n    //# Action mul = () => Out(\" * \");\n    //# Action andand = () => Out(\" && \");\n    //# var bools = new[] { false, true };\n    //# Func<int, bool, string> tni = (n, v) =>\n    //#     v ? \"t\" + n + \".Getter(t\" + n + \".Data, i)\" : \"t\" + n + \".Data[i]\";\n    //# Func<int, bool, string> tnin = (n, v) =>\n    //#     v ? \"t\" + n + \".Getter(t\" + n + \".Data, i\" + n + \")\" : \"t\" + n + \".Data[i\" + n + \"]\";\n    //# Func<int, bool, string> tnt = (n, v) =>\n    //#     v ? \"T\" + n + \"d, T\" + n : \"T\" + n;\n    //# Func<int, bool, string> tdi = (n, v) =>\n    //#     v ? \"t\" + Meta.VecArgs[n-1] + \".Getter(t\" + Meta.VecArgs[n-1] + \".Data, i)\"\n    //#       : \"t\" + Meta.VecArgs[n-1] + \".Data[i]\";\n    //# Func<int, bool, string> tdin = (n, v) =>\n    //#     v ? \"t\" + Meta.VecArgs[n-1] + \".Getter(t\" + Meta.VecArgs[n-1] + \".Data, i\" + n + \")\"\n    //#       : \"t\" + Meta.VecArgs[n-1] + \".Data[i\" + n + \"]\";\n    //# Func<int, bool, string> tdt = (n, v) =>\n    //#     v ? \"T\" + Meta.VecArgs[n-1] + \"d, T\" + Meta.VecArgs[n-1] : \"T\" + Meta.VecArgs[n-1];\n    //# var itza = new[] { \"0L\", \"V2l.Zero\", \"V3l.Zero\", \"V4l.Zero\" };\n    //# var itoa = new[] { \"1L\", \"V2l.One\", \"V3l.One\", \"V4l.One\" };\n    //# var deltacomments = new[] { \"Element stride\", \"Element and line stride\", \"Stride in each dimension\", \"Stride in each dimension\" };\n    //# var zerocoords = new[] { \"coordinate 0\", \"coordinates [0, 0]\", \"coordinates [0, 0, 0]\", \"coordinates [0, 0, 0, 0]\" };\n    //# var vectn = Meta.GenericTensorTypes[0].Name;\n    //# var mattn = Meta.GenericTensorTypes[2].Name;\n    //# var voltn = Meta.GenericTensorTypes[4].Name;\n    //# var tn4tn = Meta.GenericTensorTypes[6].Name;\n    //# Meta.GenericTensorTypes.ForEach((tt, tti) => {\n    //#     var ttn = tt.Name;\n    //#     var ttsub1n = tti > 1 ? Meta.GenericTensorTypes[tti-2].Name : \"\";\n    //#     var ttsub2n = tti > 3 ? Meta.GenericTensorTypes[tti-4].Name : tti > 1 ? \"Item\" : \"\";\n    //#     var ttnl = ttn.ToLower();\n    //#     var ttsub1nl = ttsub1n.ToLower();\n    //#     var ttsub2nl = ttsub2n.ToLower();\n    //#     var dt = tt.DataType; var dtn = dt.Name;\n    //#     var vt = tt.ViewType; var vtn = vt.Name;\n    //#     var dvtn = dt == vt ? dtn : dtn + \", \" + vtn;\n    //#     var d = tt.Dim;\n    //#     var it = tt.IndexType; var itn = it.Name;\n    //#     var iit = tt.IntIndexType; var iitn = iit.Name;\n    //#     var itzero = itza[d-1];\n    //#     var itone = itoa[d-1];\n    //#     var deltacomment = deltacomments[d-1];\n    //#     var ifa = d > 1 ? ((Meta.VecType)it).Fields : new[] { \"X\" };\n    //#     var dotx = d > 1 ? \".X\" : \"\";\n    //#     var ideltas = d == 1 ? new[] { \"Delta\" } : ifa.Select(s => \"Delta.\" + s).ToArray();\n    //#     var iaa = ifa.ToLower();\n    //#     var ifa1 = ifa.Take(ifa.Count() - 1);\n    //#     var iaa1 = ifa1.ToLower();\n    //#     var rifa = ifa.Reverse().ToArray();\n    //#     var riaa = rifa.ToLower().ToArray();\n    //#     var r1ifa = rifa.Take(rifa.Count() - 1);\n    //#     var r1iaa = riaa.Take(riaa.Count() - 1);\n    //#     var fz = ifa[d-1];\n    //#     var az = iaa[d-1];\n    //#     var rifa1 = rifa.Skip(1);\n    //#     var riaa1 = riaa.Skip(1);\n    //#     var t0i = dt == vt ? \"Data[i]\" : \"Getter(Data, i)\";\n    //# Ignore(() => {\n    public class MakeIntellisense {\n        public void Happy() {\n    //# });\n    //#     Action<string, bool, Action, bool, bool> Loop = (t, info, body, crd, vec) =>\n    //#     { var ifd = info ? \"\" : \"Info.\";\n            long i = __t__FirstIndex;/*# if (vec) { */ __itn__ v;/*# } */\n            if (__t____ifd__DX == 1)\n            {\n                //# r1ifa.ForEach(r1iaa, (f, a) => {\n                long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f__;\n                //# });\n                long xs = __t____ifd__SX;\n                //# r1ifa.ForEach(r1iaa, (f, a) => {\n                /*# if (vec) { */v.__f__ = __t__F__f__; /*# } */for (long __a__e = i + __a__s/*# if (crd) { */, __a__ = __t__F__f__/*# } */; i != __a__e; i += __a__j/*# if (crd) { */, __a__++/*# } if (vec) { */, v.__f__++/*# } */) {\n                //# });\n                /*# if (vec) { */v.X = __t__FX; /*# } */for (long xe = i + xs/*# if (crd) { */, x = __t__FX/*# } */; i != xe; i++/*# if (crd) { */, x++/*# } if (vec) { */, v.X++/*# } */) {\n                    //# body();\n                }/*# r1ifa.ForEach(f => { */ }/*# }); */\n            }\n            //# if (d > 1) {\n            else if (__t____ifd__D__fz__ == 1)\n            {\n                //# rifa1.ForEach(riaa1, (f, a, fi) => { var f1 = rifa[(fi+2)%d];\n                long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f____f1__;\n                //# });\n                long __az__s = __t____ifd__S__fz__;\n                //# rifa1.ForEach(riaa1, (f, a) => {\n                /*# if (vec) { */v.__f__ = __t__F__f__; /*# } */for (long __a__e = i + __a__s/*# if (crd) { */, __a__ = __t__F__f__/*# } */; i != __a__e; i += __a__j/*# if (crd) { */, __a__++/*# } if (vec) { */, v.__f__++/*# } */) {\n                //# });\n                /*# if (vec) { */v.__fz__ = __t__F__fz__; /*# } */for (long __az__e = i + __az__s/*# if (crd) { */, __az__ = __t__F__fz__/*# } */; i != __az__e; i++/*# if (crd) { */, __az__++/*# } if (vec) { */, v.__fz__++/*# } */) {\n                    //# body();\n                }/*# r1ifa.ForEach(f => { */ }/*# }); */\n            }\n            //# }\n            else\n            {\n                //# rifa.ForEach(riaa, (f, a) => {\n                long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f__;\n                //# });\n                //# rifa.ForEach(riaa, (f, a) => {\n                /*# if (vec) { */v.__f__ = __t__F__f__; /*# } */for (long __a__e = i + __a__s/*# if (crd) { */, __a__ = __t__F__f__/*# } */; i != __a__e; i += __a__j/*# if (crd) { */, __a__++/*# } if (vec) { */, v.__f__++/*# } */) {\n                //# });\n                    //# body();\n                /*# rifa.ForEach(f => { */}/*# }, space); */\n            }\n    //#     };\n    //#     // tc: type count, pc: parallel loop count (< d)\n    //#     Action<string, bool, bool, int, int, Action<bool>> LoopN = (t, info, opt, tc, pc, body) =>\n    //#     { var ifd = info ? \"\" : \"Info.\"; var dif = info ? \"\" : \".Info\";\n            __t____ifd__CheckMatchingSize(/*# tc.ForEach(1, i => { */t__i____dif__/*# }, comma); */);\n            //# if (opt) {\n            if (__t____ifd__HasMatchingLayout(/*# tc.ForEach(1, i => { */t__i____dif__/*# }, comma); */))\n            {\n                long i = FirstIndex;\n                if (__t____ifd__DX == 1)\n                {\n                    //# r1ifa.ForEach(r1iaa, (f, a) => {\n                    long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f__;\n                    //# });\n                    long xs = __t____ifd__SX;\n                    //# r1ifa.ForEach(r1iaa, (f, a) => {\n                    for (long __a__e = i + __a__s; i != __a__e; i += __a__j) {\n                    //# });\n                    for (long xe = i + xs; i != xe; i++) {\n                        //# body(false);\n                    }/*# r1ifa.ForEach(f => { */ }/*# }); */\n                }\n                //# if (d > 1) {\n                else if (__t____ifd__D__fz__ == 1)\n                {\n                    //# rifa1.ForEach(riaa1, (f, a, fi) => { var f1 = rifa[(fi+2)%d];\n                    long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f____f1__;\n                    //# });\n                    long __az__s = __t____ifd__S__fz__;\n                    //# rifa1.ForEach(riaa1, (f, a) => {\n                    for (long __a__e = i + __a__s; i != __a__e; i += __a__j) {\n                    //# });\n                    for (long __az__e = i + __az__s; i != __az__e; i++) {\n                        //# body(false);\n                    }/*# r1ifa.ForEach(f => { */ }/*# }); */\n                }\n                //# }\n                else\n                {\n                    //# rifa.ForEach(riaa, (f, a) => {\n                    long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f__;\n                    //# });\n                    //# rifa.ForEach(riaa, (f, a) => {\n                    for (long __a__e = i + __a__s; i != __a__e; i += __a__j) {\n                    //# });\n                        //# body(false);\n                    /*# rifa.ForEach(f => { */}/*# }, space); */\n                }\n            }\n            else\n            //# }\n            {\n                long i = __t__FirstIndex/*# tc.ForEach(1, i => { */, i__i__ = t__i__.FirstIndex/*# }); */;\n                if (__t____ifd__DX == 1 && /*# tc.ForEach(1, i => { */t__i__.__ifd__DX == 1/*# }, andand); */)\n                {\n                    //# r1ifa.ForEach(r1iaa, (f, a) => {\n                    long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f__/*# tc.ForEach(1, i => { */, __a__j__i__ = t__i__.__ifd__J__f__/*# }); */;\n                    //# });\n                    long xs = __t____ifd__SX;\n                    //# r1ifa.ForEach(r1iaa, (f, a) => {\n                    for (long __a__e = i + __a__s; i != __a__e; i += __a__j/*# tc.ForEach(1, i => { */, i__i__ += __a__j__i__/*# }); */) {\n                    //# });\n                    for (long xe = i + xs; i != xe; i++/*# tc.ForEach(1, i => { */, i__i__++/*# }); */) {\n                        //# body(true);\n                    }/*# r1ifa.ForEach(f => { */ }/*# }); */\n                }\n                //# if (d > 1) {\n                else if (__t____ifd__D__fz__ == 1 && /*# tc.ForEach(1, i => { */t__i__.__ifd__D__fz__ == 1/*# }, andand); */)\n                {\n                    //# rifa1.ForEach(riaa1, (f, a, fi) => { var f1 = rifa[(fi+2)%d];\n                    long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f____f1__/*# tc.ForEach(1, i => { */, __a__j__i__ = t__i__.__ifd__J__f____f1__/*# }); */;\n                    //# });\n                    long __az__s = __t____ifd__S__fz__;\n                    //# rifa1.ForEach(riaa1, (f, a) => {\n                    for (long __a__e = i + __a__s; i != __a__e; i += __a__j/*# tc.ForEach(1, i => { */, i__i__ += __a__j__i__/*# }); */) {\n                    //# });\n                    for (long __az__e = i + __az__s; i != __az__e; i++/*# tc.ForEach(1, i => { */, i__i__++/*# }); */) {\n                        //# body(true);\n                    }/*# r1ifa.ForEach(f => { */ }/*# }); */\n                }\n                //# }\n                else\n                {\n                    //# rifa.ForEach(riaa, (f, a) => {\n                    long __a__s = __t____ifd__DS__f__, __a__j = __t____ifd__J__f__/*# tc.ForEach(1, i => { */, __a__j__i__ = t__i__.__ifd__J__f__/*# }); */;\n                    //# });\n                    //# rifa.ForEach(riaa, (f, a) => {\n                    for (long __a__e = i + __a__s; i != __a__e; i += __a__j/*# tc.ForEach(1, i => { */, i__i__ += __a__j__i__/*# }); */) {\n                    //# });\n                        //# body(true);\n                    /*# rifa.ForEach(f => { */}/*# }, space); */\n                }\n            }\n    //#     };\n    //# Ignore(() => {\n        } // Happy\n    } // MakeIntellisense\n    //# });\n    //# if (dt == vt) {\n    #region __ttn__Info\n\n    /// <summary>\n    /// A __ttnl__ info contains the complete indexing information for a __ttnl__, but no data array.\n    /// </summary>\n    [Serializable]\n    public struct __ttn__Info : ITensorInfo\n    {\n        /// <summary>\n        /// Index of element with __zerocoords[d-1]__ in the underlying data array.\n        /// </summary>\n        public long Origin;\n\n        /// <summary>\n        /// Size of the __ttnl__.\n        /// </summary>\n        public __itn__ Size;\n\n        /// <summary>\n        /// __deltacomment__.\n        /// </summary>\n        public __itn__ Delta;\n\n        /// <summary>\n        /// Coordinates of the first element.\n        /// May differ from __zerocoords[d-1]__ for subwindows that retain the original coordinate space.\n        /// </summary>\n        public __itn__ First;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct a __ttn__Info given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the __ttnl__.</param>\n        /// <param name=\"delta\">__deltacomment__.</param>\n        /// <param name=\"first\">Coordinates of the first element.</param>\n        public __ttn__Info(long origin, __itn__ size, __itn__ delta, __itn__ first)\n        {\n            Origin = origin;\n            Size = size;\n            Delta = delta;\n            First = first;\n        }\n\n        /// <summary>\n        /// Construct a __ttn__Info given a complete specification.\n        /// </summary>\n        /// <param name=\"origin\">Location of [0,0] element within data array.</param>\n        /// <param name=\"size\">Size of the __ttnl__.</param>\n        /// <param name=\"delta\">__deltacomment__.</param>\n        public __ttn__Info(long origin, __itn__ size, __itn__ delta)\n            : this(origin, size, delta, __itzero__)\n        { }\n\n        //# if (d == 1) {\n        /// <summary>\n        /// Construct __ttnl__ info of specified size.\n        /// </summary>\n        public __ttn__Info(__itn__ size)\n            : this(0L, size, 1L)\n        { }\n\n        public __ttn__Info(__ttn__Info info)\n            : this(0L, info.Size, 1L)\n        {\n            F = info.F;\n        }\n\n        //# } else {\n        private static __itn__ NewDelta(__itn__ size)\n        {\n            return new __itn__(1L/*# if (d > 1) { */, size.X/*# }\n                                     if (d > 2) { */, size.X * size.Y/*# }\n                                     if (d > 3) { */, size.X * size.Y * size.Z/*# } */);\n        }\n\n        private static __itn__ NewDelta(__itn__ size, __itn__ delta)\n        {\n            //# if (d == 2) {\n            if (delta.Y == 1L) return new __itn__(size.Y, 1L);\n            //# } else if (d == 3) {\n            if (delta.Z == 1L) return new __itn__(size.Z, size.Z * size.X, 1L);\n            if (delta.Y == 1L) return new __itn__(size.Y * size.Z, 1L, size.Y);\n            //# } else if (d == 4) {\n            if (delta.W == 1L) return new __itn__(size.W, size.W * size.X, size.W * size.X * size.Y, 1L);\n            if (delta.Z == 1L) return new __itn__(size.Z * size.W, size.Z * size.W * size.X, 1L, size.Z);\n            if (delta.Y == 1L) return new __itn__(size.Y * size.Z * size.W, 1L, size.Y, size.Y * size.Z);\n            //# }\n            return NewDelta(size);\n        }\n\n        /// <summary>\n        /// Construct __ttnl__ info of specified size.\n        /// </summary>\n        public __ttn__Info(__itn__ size)\n            : this(0L, size, NewDelta(size))\n        { }\n\n        /// <summary>\n        /// Construct __ttnl__ info of specified size and delta.\n        /// </summary>\n        public __ttn__Info(__itn__ size, __itn__ delta)\n            : this(0L, size, NewDelta(size, delta))\n        { }\n\n        public __ttn__Info(__ttn__Info info)\n            : this(0L, info.Size, NewDelta(info.Size, info.Delta))\n        {\n            F = info.F;\n        }\n\n        //# }\n        /// <summary>\n        /// Construct __ttnl__ info of specified size.\n        /// </summary>\n        public __ttn__Info(__iitn__ size)\n            : this((__itn__)size)\n        { }\n\n        //# if (d > 1) {\n        /// <summary>\n        /// Construct __ttnl__ info of specified size and delta.\n        /// </summary>\n        public __ttn__Info(__iitn__ size, __iitn__ delta)\n            : this((__itn__)size, (__itn__)delta)\n        { }\n\n        /// <summary>\n        /// Construct __ttnl__ info of specified size.\n        /// </summary>\n        public __ttn__Info(/*# ifa.ForEach(f => { */long size__f__/*# }, comma); */)\n            : this(new __itn__(/*# ifa.ForEach(f => { */size__f__/*# }, comma); */))\n        { }\n\n        /// <summary>\n        /// Construct __ttnl__ info of specified size.\n        /// </summary>\n        public __ttn__Info(/*# ifa.ForEach(f => { */int size__f__/*# }, comma); */)\n            : this(new __itn__(/*# ifa.ForEach(f => { */size__f__/*# }, comma); */))\n        { }\n\n        //# } // (d > 1)\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the the __ttnl__ (__d__).\n        /// </summary>\n        public readonly int Rank { get { return __d__; } }\n\n        /// <summary>\n        /// Total number of element in the __ttnl__.\n        /// </summary>\n        //# if (d == 1) {\n        public readonly long Count { get { return Size; } }\n        //# } else {\n        public readonly long Count { get { return /*# ifa.ForEach((f) => {*/ Size.__f__/*# }, mul);*/; } }\n        //# }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        public readonly __itn__ End { get { return First + Size; } }\n\n        //# for (int di = 0; di < (1 << d); di++) {\n        //#     var pnt = d.Range().Select(i => (di & (1 << i)) == 0 ? \"O\" : \"I\").Join();\n        //#     var arg = d.Range().Select(i => \"First.\" + ifa[i] + ((di & (1 << i)) == 0 ? \"\" : \" + Size.\" + ifa[i])).Join(\", \");\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly __itn__ __pnt__ { get { return /*# if (di == 0) {*/First;/*#}\n                                                    else if (di == (1 << d) - 1) {*/First + Size;/*#}\n                                                    else {*/new __itn__(__arg__);/*#}*/ } }\n        //# }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __itn__ S { readonly get { return Size; } set { Size = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __itn__ D { readonly get { return Delta; } set { Delta = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        //# if (d == 1) {\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __itn__ F { readonly get { return First; } set { Origin -= Delta * (value - First); First = value; } }\n        //# } else {\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __itn__ F { readonly get { return First; } set { Origin -= Delta.Dot(value - First); First = value; } }\n        //# }\n\n        /// <summary>\n        /// End (one step beyond the last element in all dimensions).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly __itn__ E { get { return First + Size; } }\n\n        //# if (d == 1) {\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DS { get { return Delta * Size; } }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long SX { readonly get { return Size; } set { Size = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long DX { readonly get { return Delta; } set { Delta = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long FX { readonly get { return First; } set { Origin -= Delta * (value - First); First = value; } }\n\n        /// <summary>\n        /// End (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long EX { get { return First + Size; } }\n\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DSX { get { return Delta * Size; } }\n\n        /// <summary>\n        /// Jump\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long JX { get { return Delta; } }\n\n\n        //# } // (d == 1)\n        //# if (d > 1) {\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// Size.__f__\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long S__f__ { readonly get { return Size.__f__; } set { Size.__f__ = value; } }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// Delta.__f__\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long D__f__ { readonly get { return Delta.__f__; } set { Delta.__f__ = value; } }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// First.__f__\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long F__f__\n        {\n            readonly get { return First.__f__; }\n            set { Origin -= Delta.__f__ * (value - First.__f__); First.__f__ = value; }\n        }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// End in dimension __f__ (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long E__f__\n        {\n            get { return First.__f__ + Size.__f__; }\n        }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DS__f__ { get { return Size.__f__ * Delta.__f__; } }\n\n        //# } // foreach\n        //# ifa.ForEach((f, i) => { var f1 = i > 0 ? Meta.VecFields[i-1] : \"\";\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension __f__.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long J__f__ { get { return Delta.__f__/*# if (i > 0) { */ - Size.__f1__ * Delta.__f1__/*# } */; } }\n\n        public readonly long GetJ__f__(__itn__ size)\n        {\n            return Delta.__f__/*# if (i > 0) { */ - size.__f1__ * Delta.__f1__/*# } */;\n        }\n\n        //# }); // ForEach\n        //# ifa.ForEach(f2 => {\n        //# ifa.ForEach(f1 => { var f0 = f1 == f2 ? \"0\" : f1;\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// between elements in dimension __f2__ in a loop around another loop\n        /// in dimension __f0__.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long J__f2____f0__ { get { return Delta.__f2__/*# if (f1 != f2) { */ - Size.__f1__ * Delta.__f1__/*# } */; } }\n\n        public readonly long GetJ__f2____f0__(__itn__ size)\n        {\n            return Delta.__f2__/*# if (f1 != f2) { */ - size.__f1__ * Delta.__f1__/*# } */;\n        }\n\n        //# }); // ifa\n        //# }); // ifa\n        //# } // (d > 1)\n        /// <summary>\n        /// Return the index of the first element in the underlying data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Index(First); } }\n\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long OriginIndex { readonly get { return Origin; } set { Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return new long[] { /*# ifa.ForEach((f) => { */S__f__/*# }, comma); */ }; }\n            set { /*# ifa.ForEach((f, i) => { */S__f__ = value[__i__]; /*# }); */ }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return new long[] { /*# ifa.ForEach((f) => { */D__f__/*# }, comma); */ }; }\n            set { /*# ifa.ForEach((f, i) => { */D__f__ = value[__i__]; /*# }); */ }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return new long[] { /*# ifa.ForEach((f) => { */F__f__/*# }, comma); */ }; }\n            set { /*# ifa.ForEach((f, i) => { */F__f__ = value[__i__]; /*# }); */ }\n        }\n\n        //# if (d > 1) {\n        //# ifa.ForEach(iaa, (f,a) => {\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> Indices__f__\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long __a__e = i + DS__f__, __a__j = J__f__0; i != __a__e; i += __a__j)\n                    yield return i;\n            }\n        }\n\n        //# });\n        //# ifa.ForEach(iaa, (f2,a2) => { var f0 = \"0\";\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2) {\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the second\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> Indices__f2____f1__\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long __a2__e = i + DS__f2__, __a2__j = J__f2____f1__; i != __a2__e; i += __a2__j)\n                for (long __a1__e = i + DS__f1__, __a1__j = J__f1____f0__; i != __a1__e; i += __a1__j)\n                    yield return i;\n            }\n        }\n\n        //# }});\n        //# });\n        //# } // (d > 1)\n        //# if (d > 2) {\n        //# ifa.ForEach(iaa, (f3,a3) => { var f0 = \"0\";\n        //# ifa.ForEach(iaa, (f2,a2) => { if (f2 != f3) {\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2 && f1 != f3) {\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> Indices__f3____f2____f1__\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long __a3__e = i + DS__f3__, __a3__j = J__f3____f2__; i != __a3__e; i += __a3__j)\n                for (long __a2__e = i + DS__f2__, __a2__j = J__f2____f1__; i != __a2__e; i += __a2__j)\n                for (long __a1__e = i + DS__f1__, __a1__j = J__f1____f0__; i != __a1__e; i += __a1__j)\n                    yield return i;\n            }\n        }\n\n        //# }});\n        //# }});\n        //# });\n        //# } // (d > 2)\n        //# if (d > 3) {\n        //# ifa.ForEach(iaa, (f4,a4) => { var f0 = \"0\";\n        //# ifa.ForEach(iaa, (f3,a3) => { if (f3 != f4) {\n        //# ifa.ForEach(iaa, (f2,a2) => { if (f2 != f3 && f2 != f4) {\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2 && f1 != f3 && f1 != f4) {\n        /// <summary>\n        /// Return the indices into the underlying data array in the specified\n        /// order, with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly IEnumerable<long> Indices__f4____f3____f2____f1__\n        {\n            get\n            {\n                long i = FirstIndex;\n                for (long __a4__e = i + DS__f4__, __a4__j = J__f4____f2__; i != __a4__e; i += __a4__j)\n                for (long __a3__e = i + DS__f3__, __a3__j = J__f3____f2__; i != __a3__e; i += __a3__j)\n                for (long __a2__e = i + DS__f2__, __a2__j = J__f2____f1__; i != __a2__e; i += __a2__j)\n                for (long __a1__e = i + DS__f1__, __a1__j = J__f1____f0__; i != __a1__e; i += __a1__j)\n                    yield return i;\n            }\n        }\n\n        //# }});\n        //# }});\n        //# }});\n        //# });\n        //# } // (d > 3)\n        //# if (d == 2) {\n        public readonly __ttn__Info Transposed\n        {\n            get { return new __ttn__Info(Origin, Size.YX, Delta.YX, First.YX); }\n        }\n\n        //# } // d == 2\n        #endregion\n\n        #region Indexing Helper Methods\n\n        //# if (d == 1) {\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(long coord) { return Origin + coord * Delta; }\n\n        //# }\n        //# if (d > 1) {\n        public readonly long Dv(/*# iaa.ForEach(a => { */long d__a__/*# }, comma); */)\n        {\n            return /*# iaa.ForEach(ifa, (a, f) => {*/d__a__ * Delta.__f__/*# }, add);*/;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(/*# iaa.ForEach(a => { */long __a__/*# }, comma); */)\n        {\n            return Origin + /*# iaa.ForEach(ifa, (a, f) => {*/__a__ * Delta.__f__/*# }, add);*/;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(__itn__ v)\n        {\n            return Origin + /*# ifa.ForEach(f => {*/v.__f__ * Delta.__f__/*# }, add);*/;\n        }\n\n        /// <summary>\n        /// Calculate element index for underlying data array.\n        /// </summary>\n        public readonly long Index(__iitn__ v)\n        {\n            return Origin + /*# ifa.ForEach(f => {*/v.__f__ * Delta.__f__/*# }, add);*/;\n        }\n\n        //# }\n        #endregion\n\n        #region Interpretation and Parts\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__Window(__itn__ begin, __itn__ size)\n        {\n            return new __ttn__Info(Origin, size, Delta, begin);\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__(__itn__ begin, __itn__ size)\n        {\n            return new __ttn__Info(Index(begin), size, Delta);\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__Window(__iitn__ begin, __iitn__ size)\n        {\n            return new __ttn__Info(Origin, (__itn__)size, Delta, (__itn__)begin);\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__(__iitn__ begin, __iitn__ size)\n        {\n            return new __ttn__Info(Index((__itn__)begin), (__itn__)size, Delta);\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__Window(__itn__ begin, __itn__ size, __itn__ delta)\n        {\n            return new __ttn__Info(Origin, size, delta, begin);\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__(__itn__ begin, __itn__ size, __itn__ delta)\n        {\n            return new __ttn__Info(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__Window(__iitn__ begin, __iitn__ size, __iitn__ delta)\n        {\n            return new __ttn__Info(Origin, (__itn__)size, (__itn__)delta, (__itn__)begin);\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__(__iitn__ begin, __iitn__ size, __iitn__ delta)\n        {\n            return new __ttn__Info(Index((__itn__)begin), (__itn__)size, (__itn__)delta);\n        }\n\n        //# if (d > 1) {\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__Window(__itn__ begin, __itn__ size, __itn__ delta, __itn__ first)\n        {\n            return new __ttn__Info(Index(begin), size, delta) { F = first };\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__Window(__iitn__ begin, __iitn__ size, __iitn__ delta, __iitn__ first)\n        {\n            return new __ttn__Info(Index((__itn__)begin), (__itn__)size, (__itn__)delta)\n                            { F = (__itn__)first };\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__Window(\n                /*# ifa.ForEach(f => { */long begin__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long size__f__/*# }, comma); */)\n        {\n            return new __ttn__Info(Origin, new __itn__(/*# ifa.ForEach(f => { */size__f__/*# }, comma); */),\n                                  Delta, new __itn__(/*# ifa.ForEach(f => { */begin__f__/*# }, comma); */));\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__(\n                /*# ifa.ForEach(f => { */long begin__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long size__f__/*# }, comma); */)\n        {\n            return new __ttn__Info(Index(/*# ifa.ForEach(f => { */begin__f__/*# }, comma); */),\n                                  new __itn__(/*# ifa.ForEach(f => { */size__f__/*# }, comma); */),\n                                  Delta);\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__Window(\n                /*# ifa.ForEach(f => { */long begin__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long size__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long delta__f__/*# }, comma); */)\n        {\n            return new __ttn__Info(Origin, new __itn__(/*# ifa.ForEach(f => { */size__f__/*# }, comma); */),\n                                  new __itn__(/*# ifa.ForEach(f => { */delta__f__/*# }, comma); */),\n                                  new __itn__(/*# ifa.ForEach(f => { */begin__f__/*# }, comma); */));\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__Info Sub__ttn__(\n                /*# ifa.ForEach(f => { */long begin__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long size__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long delta__f__/*# }, comma); */)\n        {\n            return new __ttn__Info(Index(/*# ifa.ForEach(f => { */begin__f__/*# }, comma); */),\n                                  new __itn__(/*# ifa.ForEach(f => { */size__f__/*# }, comma); */),\n                                  new __itn__(/*# ifa.ForEach(f => { */delta__f__/*# }, comma); */));\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __vectn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __vectn__Info Sub__vectn__(__itn__ begin, long size, long delta)\n        {\n            return new __vectn__Info(Index(begin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __vectn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __vectn__Info Sub__vectn__(__iitn__ begin, long size, long delta)\n        {\n            return new __vectn__Info(Index(begin), size, delta);\n        }\n\n        //# if (d == 2) {\n        /// <summary>\n        /// If the lines of the matrix are stored consecutively without gaps,\n        /// the whole matrix can be viewed as a single vector.\n        /// This methods returns a __vectn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __vectn__Info As__vectn__()\n        {\n            if (JY != 0)\n                throw new Exception(\"cannot represent this matrix as vector\");\n            return new __vectn__Info(Origin, SX * SY, DX);\n        }\n\n        //# for (int ai = 0; ai < d; ai++) {\n        //#     var a = iaa[ai];\n        //#     var fa = \"\"; ifa.ForEach((f,i) => { if (i != ai) fa = fa + f; });\n        //#     var fn = fa == \"X\" ? \"Row\" : \"Col\";\n        //#     var da = \"\"; ifa.ForEach((f,i) => { if (i != ai) da = da + f; else da = da + \"O\"; });\n        //#     foreach (var win in new bool[] { false, true }) { var winstr = win ? \"Window\" : \"\";\n        /// <summary>\n        /// Return a full __fa__ __ttsub1nl__ slice of the __ttnl__.\n        //# if (win) {\n        /// This method retains the coordinates of the parent __ttnl__.\n        //# } else {\n        /// This methods returns a __ttsub1nl__ with zero as first coordinates.\n        //# }\n        /// </summary>\n        public readonly __ttsub1n__Info __fn____winstr__(long __a__)\n        {\n            return new __ttsub1n__Info(Index(/*# ifa.ForEach((f,i) => { var ff = i != ai ? \"F\" + f : a; */__ff__/*# }, comma);\n                            */), S.__fa__, D.__fa__)/*# if (win) { */\n            { F = F.__fa__ }/*# } */;\n        }\n\n        //# } // win\n        //# } // ai\n        //# } // (d == 2)\n        //# if (d == 3) {\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// This methods returns a __vectn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __vectn__Info As__vectn__()\n        {\n            if (JX != 0 || JY != 0)\n                throw new Exception(\"cannot represent this volume as vector\");\n            return new __vectn__Info(Origin, SX * SY * SZ, DX);\n        }\n\n        /// <summary>\n        /// If the lines of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// This methods returns a __mattn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __mattn__Info As__mattn__XYxZ()\n        {\n            if (JY != 0)\n                throw new Exception(\"cannot represent this volume as matrix\");\n            return new __mattn__Info(Origin, new V2l(SX * SY, SZ), D.XZ);\n        }\n\n        /// <summary>\n        /// If the planes of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// This methods returns a __mattn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __mattn__Info As__mattn__XxYZ()\n        {\n            if (JZ != 0)\n                throw new Exception(\"cannot represent this volume as matrix\");\n            return new __mattn__Info(Origin, new V2l(SX, SY * SZ), D.XY);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __mattn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __mattn__Info Sub__mattn__(__itn__ origin, V2l size, V2l delta)\n        {\n            return new __mattn__Info(Index(origin), size, delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __mattn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __mattn__Info Sub__mattn__(__iitn__ origin, V2i size, V2l delta)\n        {\n            return new __mattn__Info(Index(origin), (V2l)size, delta);\n        }\n\n        /// <summary>\n        /// A SubMatrix does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __mattn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __mattn__Info Sub__mattn__(\n                long bx, long by, long bz,\n                long sx, long sy, long dx, long dy)\n        {\n            return new __mattn__Info(Index(bx, by, bz), new V2l(sx, sy), new V2l(dx, dy));\n        }\n\n        //# } // (d == 3)\n        //# if (d == 4) {\n        /// <summary>\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        /// This methods returns a __vectn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __vectn__Info As__vectn__()\n        {\n            if (JX != 0 || JY != 0 || JZ != 0)\n                throw new Exception(\"cannot represent this tensor4 as vector\");\n            return new __vectn__Info(Origin, SX * SY * SZ * SW, DX);\n        }\n\n        //# } // (d == 4)\n        //# for (int ai = 0; ai < d; ai++) {\n        //#     var a = iaa[ai];\n        //#     var fa = \"\"; ifa.ForEach((f,i) => { if (i != ai) fa = fa + f; });\n        //#     var da = \"\"; ifa.ForEach((f,i) => { if (i != ai) da = da + f; else da = da + \"O\"; });\n        //#     foreach (var win in new bool[] { false, true }) { var winstr = win ? \"Window\" : \"\";\n        /// <summary>\n        /// Return a full __fa__ __ttsub1nl__ slice of the __ttnl__.\n        //# if (win) {\n        /// This method retains the coordinates of the parent __ttnl__.\n        //# } else {\n        /// This methods returns a __ttsub1nl__ with zero as first coordinates.\n        //# }\n        /// </summary>\n        public readonly __ttsub1n__Info Sub__fa____ttsub1n____winstr__(long __a__)\n        {\n            return new __ttsub1n__Info(Index(/*# ifa.ForEach((f,i) => { var ff = i != ai ? \"F\" + f : a; */__ff__/*# }, comma);\n                            */), S.__fa__, D.__fa__)/*# if (win) { */ { F = F.__fa__ }/*# } */;\n        }\n\n        /// <summary>\n        /// Return a full __fa__ __ttsub1nl__ slice of the __ttnl__ as a special __ttnl__\n        /// that replicates the __ttsub1nl__ the supplied number of times. The special\n        /// __ttnl__ can only be correctly used to read from. Other operations are not guaranteed.\n        //# if (win) {\n        /// This method retains the coordinates of the parent __ttnl__.\n        //# } else {\n        /// This methods returns a __ttnl__ with zero as first coordinates.\n        //# }\n        /// </summary>\n        public readonly __ttn__Info Sub__fa____ttsub1n__AsReadOnly__ttn____winstr__(long __a__, long size__a__)\n        {\n            return new __ttn__Info(Index(/*# ifa.ForEach((f,i) => { var ff = i != ai ? \"F\" + f : a; */__ff__/*# }, comma);\n                            */), new __itn__(/*# ifa.ForEach((f,i) => { var ff = i != ai ? \"S\" + f : \"size\" + a; */__ff__/*# }, comma);\n                            */), D.__da__)/*# if (win) { */ { F = F }/*# } */;\n        }\n\n        //# } // win\n        //# } // ai\n        //# for (int ai = 0; ai < d-1; ai++) { var a = iaa[ai];\n        //# for (int bi = ai + 1; bi < d; bi++) { var b = iaa[bi];\n        //#     var fa = \"\"; ifa.ForEach((f,i) => { if (i != ai && i != bi) fa = fa + f; });\n        //#     var da = \"\"; ifa.ForEach((f,i) => { if (i != ai && i != bi) da = da + f; else da = da + \"O\"; });\n        //#     var delta = d > 2 ? \"D.\" + da : itn + \".Zero\";\n        //#     foreach (var win in new bool[] { false, true }) { var winstr = win ? \"Window\" : \"\";\n        /// <summary>\n        /// Return a full __fa__ __ttsub2nl__ slice of the __ttnl__ as a special __ttnl__\n        /// that replicates the __ttsub2nl__ the supplied number of times. The special\n        /// __ttnl__ can only be correctly used to read from. Other operations are not guaranteed.\n        //# if (win) {\n        /// This method retains the coordinates of the parent __ttnl__.\n        //# } else {\n        /// This methods returns a __ttnl__ with zero as first coordinates.\n        //# }\n        /// </summary>\n        public readonly __ttn__Info Sub__fa____ttsub2n__AsReadOnly__ttn____winstr__(long __a__, long __b__, long size__a__, long size__b__)\n        {\n            return new __ttn__Info(Index(/*# ifa.ForEach((f,i) => { var ff = i == ai ? a : i == bi ? b : \"F\" + f; */__ff__/*# }, comma);\n                            */), new __itn__(/*# ifa.ForEach((f,i) => { var ff = i == ai ? \"size\" + a : i == bi ? \"size\" + b : \"S\" + f; */__ff__/*# }, comma);\n                            */), __delta__)/*# if (win) { */ { F = F }/*# } */;\n        }\n\n        //# } // win\n        //# } // bi\n        //# } // ai\n        //# } // d > 1\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            //# Loop(\"\", true, () => {\n                    i_action(i);\n            //# }, false, false);\n        }\n\n        //# { var i_action = \"\"; iaa.ForEach(a => i_action += a + \"_\"); i_action += \"i_action\";\n        public readonly void ForeachIndex(Action</*# iaa.ForEach(f => {*/long/*# }, comma);*/, long> __i_action__)\n        {\n            //# Loop(\"\", true, () => {\n                    __i_action__(/*# iaa.ForEach(a => {*/__a__/*# }, comma);*/, i);\n            //# }, true, false);\n        }\n        //# } // var i_action\n\n        public readonly void ForeachCoord(Action<__itn__> v_action)\n        {\n            //# if (d == 1) {\n            //# Loop(\"\", true, () => {\n                    v_action(x);\n            //# }, true, false);\n            //# } else {\n            //# Loop(\"\", true, () => {\n                    v_action(v);\n            //# }, false, true);\n            //# }\n        }\n\n        public readonly void ForeachIndex(__ttn__Info t1, Action<long, long> i_i1_act)\n        {\n            //# LoopN(\"\", true, true, 2, 0, ix => { var i1 = ix ? \"i1\" : \"i\";\n                        i_i1_act(i, __i1__);\n            //# });\n        }\n\n        //# for (int itc = 1; itc < 3; itc++) { var istr = \"i_\"; for (int i1 = 1; i1 < itc; i1++) istr += \"i\" + i1 + \"_\";\n        //# foreach (bool idx in new[] { false, true }) { var idxstr = idx ? \"Index\" : \"\"; if (!idx && itc > 1) continue;\n        //# if (d > 1) {\n        //# ifa.ForEach(iaa, (f,a) => {\n        //# foreach (bool crd in new[] { false, true }) { if (!crd && !idx) continue;\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        //# var elementAct = (crd ? a + \"_\" : \"\") + (idx ? istr : \"\") + \"elementAct\";\n        public readonly void Foreach__f____idxstr__(/*# for (int i1 = 1; i1 < itc; i1++) { */__ttn__Info t__i1__, /*# } */\n                Action</*# if (crd) { */long/*# if (idx) { */, /*# }} if (idx) { */long/*# for (int i1 = 1; i1 < itc; i1++) { */, long/*# }} */> __elementAct__)\n        {\n            long i = FirstIndex/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ = t__i1__.FirstIndex/*# } */;\n            for (long __a__e = i + DS__f__, __a__j = J__f__0/*# for (int i1 = 1; i1 < itc; i1++) { */, __a__j__i1__ = t__i1__.J__f__0/*# } if (crd) { */, __a__ = F__f__/*# } */; i != __a__e; i += __a__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a__j__i1__/*# }\n                 if (crd) { */, __a__++/*# } */)\n                __elementAct__(/*# if (crd) { */__a__/*# if (idx) { */, /*# }} if (idx) { */i/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__/*# } } */);\n        }\n\n        //# } // crd\n        //# });\n        //# ifa.ForEach(iaa, (f2,a2) => { var f0 = \"0\";\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2) {\n        //# foreach (bool crd in new[] { false, true }) { if (!crd && !idx) continue;\n        //# foreach (bool pre in new[] { false, true }) {\n        //# foreach (bool post in new[] { false, true }) {\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        //# var preLineAct = (crd ? a2 + \"_\" : \"\") + \"preLineAct\";\n        //# var elementAct = (crd ? a2 + \"_\" + a1 + \"_\" : \"\") + (idx ? istr : \"\") + \"elementAct\";\n        //# var postLineAct = (crd ? a2 + \"_\" : \"\") + \"postLineAct\";\n        public readonly void Foreach__f2____f1____idxstr__(/*# for (int i1 = 1; i1 < itc; i1++) { */__ttn__Info t__i1__, /*# } */\n                /*# if (pre) { */Action/*# if (crd) { */<long>/*# } */ __preLineAct__,\n                /*# } */Action</*# if (crd) { */long, long/*# if (idx) { */, /*# }} if (idx) { */long/*# for (int i1 = 1; i1 < itc; i1++) { */, long/*# }} */> __elementAct__/*# if (post) { */,\n                Action/*# if (crd) { */<long>/*# } */ __postLineAct__/*# } */)\n        {\n            long __a2__s = DS__f2__, __a2__j = J__f2____f1__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a2__j__i1__ = t__i1__.J__f2____f1__/*# } */;\n            long __a1__s = DS__f1__, __a1__j = J__f1____f0__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a1__j__i1__ = t__i1__.J__f1____f0__/*# } */;\n            long i = FirstIndex/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ = t__i1__.FirstIndex/*# } */;\n            for (long __a2__e = i + __a2__s/*# if (crd) { */, __a2__ = F__f2__/*# } */; i != __a2__e; i += __a2__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a2__j__i1__/*# }\n                 if (crd) { */, __a2__++/*# } */)\n            {\n            //# if (pre) {\n            __preLineAct__(/*# if (crd) { */__a2__/*# } */);\n            //# }\n            for (long __a1__e = i + __a1__s/*# if (crd) { */, __a1__ = F__f1__/*# } */; i != __a1__e; i += __a1__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a1__j__i1__/*# }\n                 if (crd) { */, __a1__++/*# } */)\n                __elementAct__(/*# if (crd) { */__a2__, __a1__/*# if (idx) { */, /*# }} if (idx) { */i/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__/*# } } */);\n            //# if (post) {\n            __postLineAct__(/*# if (crd) { */__a2__/*# } */);\n            //# }\n            }\n        }\n\n        //# } // post\n        //# } // pre\n        //# } // crd\n        //# }});\n        //# });\n        //# } // (d > 1)\n        //# if (d > 2) {\n        //# ifa.ForEach(iaa, (f3,a3) => { var f0 = \"0\";\n        //# ifa.ForEach(iaa, (f2,a2) => { if (f2 != f3) {\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2 && f1 != f3) {\n        //# foreach (bool crd in new[] { false, true }) { if (!crd && !idx) continue;\n        //# foreach (bool pre in new[] { false, true }) {\n        //# foreach (bool post in new[] { false, true }) {\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        //# var prePlaneAct = (crd ? a3 + \"_\" : \"\") + \"prePlaneAct\";\n        //# var preLineAct = (crd ? a3 + \"_\" + a2 + \"_\" : \"\") + \"preLineAct\";\n        //# var elementAct = (crd ? a3 + \"_\" + a2 + \"_\" + a1 + \"_\" : \"\") + (idx ? istr : \"\") + \"elementAct\";\n        //# var postLineAct = (crd ? a3 + \"_\" + a2 + \"_\" : \"\") + \"postLineAct\";\n        //# var postPlaneAct = (crd ? a3 + \"_\" : \"\") + \"postPlaneAct\";\n        public readonly void Foreach__f3____f2____f1____idxstr__(/*# for (int i1 = 1; i1 < itc; i1++) { */__ttn__Info t__i1__, /*# } if (pre) { */\n                Action/*# if (crd) { */<long>/*# } */ __prePlaneAct__,\n                Action/*# if (crd) { */<long, long>/*# } */ __preLineAct__,/*# } */\n                Action</*# if (crd) { */long, long, long/*# if (idx) { */, /*# }} if (idx) { */long/*# for (int i1 = 1; i1 < itc; i1++) { */, long/*# }} */> __elementAct__/*# if (post) { */,\n                Action/*# if (crd) { */<long, long>/*# } */ __postLineAct__,\n                Action/*# if (crd) { */<long>/*# } */ __postPlaneAct__/*# } */)\n        {\n            long __a3__s = DS__f3__, __a3__j = J__f3____f2__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a3__j__i1__ = t__i1__.J__f3____f2__/*# } */;\n            long __a2__s = DS__f2__, __a2__j = J__f2____f1__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a2__j__i1__ = t__i1__.J__f2____f1__/*# } */;\n            long __a1__s = DS__f1__, __a1__j = J__f1____f0__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a1__j__i1__ = t__i1__.J__f1____f0__/*# } */;\n            long i = FirstIndex/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ = t__i1__.FirstIndex/*# } */;\n            for (long __a3__e = i + __a3__s/*# if (crd) { */, __a3__ = F__f3__/*# } */; i != __a3__e; i += __a3__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a3__j__i1__/*# }\n                 if (crd) { */, __a3__++/*# } */)\n            {\n            //# if (pre) {\n            __prePlaneAct__(/*# if (crd) { */__a3__/*# } */);\n            //# }\n            for (long __a2__e = i + __a2__s/*# if (crd) { */, __a2__ = F__f2__/*# } */; i != __a2__e; i += __a2__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a2__j__i1__/*# }\n                 if (crd) { */, __a2__++/*# } */)\n            {\n            //# if (pre) {\n            __preLineAct__(/*# if (crd) { */__a3__, __a2__/*# } */);\n            //# }\n            for (long __a1__e = i + __a1__s/*# if (crd) { */, __a1__ = F__f1__/*# } */; i != __a1__e; i += __a1__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a1__j__i1__/*# }\n                 if (crd) { */, __a1__++/*# } */)\n                __elementAct__(/*# if (crd) { */__a3__, __a2__, __a1__/*# if (idx) { */, /*# }} if (idx) { */i/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__/*# } } */);\n            //# if (post) {\n            __postLineAct__(/*# if (crd) { */__a3__, __a2__/*# } */);\n            //# }\n            }\n            //# if (post) {\n            __postPlaneAct__(/*# if (crd) { */__a3__/*# } */);\n            //# }\n            }\n        }\n\n        //# } // post\n        //# } // pre\n        //# } // crd\n        //# }});\n        //# }});\n        //# });\n        //# } // (d > 2)\n        //# if (d > 3) {\n        //# ifa.ForEach(iaa, (f4,a4) => { var f0 = \"0\";\n        //# ifa.ForEach(iaa, (f3,a3) => { if (f3 != f4) {\n        //# ifa.ForEach(iaa, (f2,a2) => { if (f2 != f3 && f2 != f4) {\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2 && f1 != f3 && f1 != f4) {\n        //# foreach (bool crd in new[] { false, true }) { if (!crd && !idx) continue;\n        //# foreach (bool pre in new[] { false, true }) {\n        //# foreach (bool post in new[] { false, true }) {\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        //# var preVolumeAct = (crd ? a4 + \"_\" : \"\") + \"preVolumeAct\";\n        //# var prePlaneAct = (crd ? a4 + \"_\" + a3 + \"_\" : \"\") + \"prePlaneAct\";\n        //# var preLineAct = (crd ? a4 + \"_\" + a3 + \"_\" + a2 + \"_\" : \"\") + \"preLineAct\";\n        //# var elementAct = (crd ? a4 + \"_\" + a3 + \"_\" + a2 + \"_\" + a1 + \"_\" : \"\") + (idx ? istr : \"\") + \"elementAct\";\n        //# var postLineAct = (crd ? a4 + \"_\" + a3 + \"_\" + a2 + \"_\" : \"\") + \"postLineAct\";\n        //# var postPlaneAct = (crd ? a4 + \"_\" + a3 + \"_\" : \"\") + \"postPlaneAct\";\n        //# var postVolumeAct = (crd ? a4 + \"_\" : \"\") + \"postVolumeAct\";\n        public readonly void Foreach__f4____f3____f2____f1____idxstr__(/*# for (int i1 = 1; i1 < itc; i1++) { */__ttn__Info t__i1__, /*# }  if (pre) { */\n                Action/*# if (crd) { */<long>/*# } */ __preVolumeAct__,\n                Action/*# if (crd) { */<long, long>/*# } */ __prePlaneAct__,\n                Action/*# if (crd) { */<long, long, long>/*# } */ __preLineAct__,/*# } */\n                Action</*# if (crd) { */long, long, long, long/*# if (idx) { */, /*# }} if (idx) { */long/*# for (int i1 = 1; i1 < itc; i1++) { */, long/*# }} */> __elementAct__/*# if (post) { */,\n                Action/*# if (crd) { */<long, long, long>/*# } */ __postLineAct__,\n                Action/*# if (crd) { */<long, long>/*# } */ __postPlaneAct__,\n                Action/*# if (crd) { */<long>/*# } */ __postVolumeAct__/*# } */)\n        {\n            long __a4__s = DS__f4__, __a4__j = J__f4____f3__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a4__j__i1__ = t__i1__.J__f4____f3__/*# } */;\n            long __a3__s = DS__f3__, __a3__j = J__f3____f2__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a3__j__i1__ = t__i1__.J__f3____f2__/*# } */;\n            long __a2__s = DS__f2__, __a2__j = J__f2____f1__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a2__j__i1__ = t__i1__.J__f2____f1__/*# } */;\n            long __a1__s = DS__f1__, __a1__j = J__f1____f0__/*# for (int i1 = 1; i1 < itc; i1++) { */, __a1__j__i1__ = t__i1__.J__f1____f0__/*# } */;\n            long i = FirstIndex/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ = t__i1__.FirstIndex/*# } */;\n            for (long __a4__e = i + __a4__s/*# if (crd) { */, __a4__ = F__f4__/*# } */; i != __a4__e; i += __a4__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a4__j__i1__/*# }\n                 if (crd) { */, __a4__++/*# } */)\n            {\n            //# if (pre) {\n            __preVolumeAct__(/*# if (crd) { */__a4__/*# } */);\n            //# }\n            for (long __a3__e = i + __a3__s/*# if (crd) { */, __a3__ = F__f3__/*# } */; i != __a3__e; i += __a3__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a3__j__i1__/*# }\n                 if (crd) { */, __a3__++/*# } */)\n            {\n            //# if (pre) {\n            __prePlaneAct__(/*# if (crd) { */__a4__, __a3__/*# } */);\n            //# }\n            for (long __a2__e = i + __a2__s/*# if (crd) { */, __a2__ = F__f2__/*# } */; i != __a2__e; i += __a2__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a2__j__i1__/*# }\n                 if (crd) { */, __a2__++/*# } */)\n            {\n            //# if (pre) {\n            __preLineAct__(/*# if (crd) { */__a4__, __a3__, __a2__/*# } */);\n            //# }\n            for (long __a1__e = i + __a1__s/*# if (crd) { */, __a1__ = F__f1__/*# } */; i != __a1__e; i += __a1__j/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__ += __a1__j__i1__/*# }\n                 if (crd) { */, __a1__++/*# } */)\n                __elementAct__(/*# if (crd) { */__a4__, __a3__, __a2__, __a1__/*# if (idx) { */, /*# }} if (idx) { */i/*# for (int i1 = 1; i1 < itc; i1++) { */, i__i1__/*# } } */);\n            //# if (post) {\n            __postLineAct__(/*# if (crd) { */__a4__, __a3__, __a2__/*# } */);\n            //# }\n            }\n            //# if (post) {\n            __postPlaneAct__(/*# if (crd) { */__a4__, __a3__/*# } */);\n            //# }\n            }\n            //# if (post) {\n            __postVolumeAct__(/*# if (crd) { */__a4__/*# } */);\n            //# }\n            }\n        }\n\n        //# } // post\n        //# } // pre\n        //# } // crd\n        //# }});\n        //# }});\n        //# }});\n        //# });\n        //# } // (d > 3)\n        //# } // idx\n        //# } // itc\n        #endregion\n\n        #region Checking\n\n        public readonly void CheckMatchingSize(__ttn__Info t1)\n        {\n            if (Size != t1.Size) throw new ArgumentException(\"size mismatch\");\n        }\n\n        public readonly void CheckMatchingSize(__ttn__Info t1, __ttn__Info t2)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2);\n        }\n\n        public readonly void CheckMatchingSize(__ttn__Info t1, __ttn__Info t2, __ttn__Info t3)\n        {\n            CheckMatchingSize(t1); CheckMatchingSize(t2); CheckMatchingSize(t3);\n        }\n\n        public readonly bool HasMatchingLayout(__ttn__Info t1)\n        {\n            return First == t1.First && Origin == t1.Origin && Delta == t1.Delta;\n        }\n\n        public readonly bool HasMatchingLayout(__ttn__Info t1, __ttn__Info t2)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2);\n        }\n\n        public readonly bool HasMatchingLayout(__ttn__Info t1, __ttn__Info t2, __ttn__Info t3)\n        {\n            return HasMatchingLayout(t1) && HasMatchingLayout(t2) && HasMatchingLayout(t3);\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    //# } // dt == vt\n    #region __ttn__<__dvtn__>\n\n    /// <summary>\n    /// Generic __ttnl__ of elements with arbitrary stride.\n    /// All sizes are given as __d__-dimensional vectors, with the first\n    /// parameter specifying the inner dimension.\n    /// The __ttnl__ does not exclusively own its underlying data array, it\n    /// can also serve as a window into other arrays and tensors. Operations\n    /// on __ttnl__s are supported by function arguments which can be easily\n    /// exploited by using lambda functions.\n    /// Note: stride is called Delta (or D) within this data structure, the\n    /// __d__ stride direction(s) are called DX, DY, aso.\n    //# if (dt != vt) {\n    /// The __ttnl__ has different view and data element types, i.e. although\n    /// all data is stored using the data element type, in its interfaces it\n    /// acts as a __ttnl__ of view element types.\n    //# }\n    /// </summary>\n    /// <typeparam name=\"__dtn__\">data element type</typeparam>\n    //# if (dt != vt) {\n    /// <typeparam name=\"__vtn__\">view element type</typeparam>\n    //# }\n    [Serializable]\n    public partial struct __ttn__<__dvtn__> : IValidity, I__ttn__<__vtn__>, IArray__ttn__\n    {\n        public __dtn__[] Data;\n        //# if (dt != vt) {\n        public Func<Td[], long, Tv> Getter;\n        public Action<Td[], long, Tv> Setter;\n        //# }\n        public __ttn__Info Info;\n\n        #region Constructors\n\n        /// <summary>\n        /// Construct from data array with specified info without copying.\n        /// </summary>\n        public __ttn__(__dtn__[] data, __ttn__Info info)\n        {\n            Data = data;\n            Info = info;\n            //# if (dt != vt) {\n            Getter = null;\n            Setter = null;\n            //# }\n        }\n\n        /// <summary>\n        /// Construct __ttnl__ of specified size.\n        /// </summary>\n        public __ttn__(__itn__ size)\n            : this(new __dtn__[size/*# if (d > 1) {*/.X * size.Y/*# }\n                                           if (d > 2) {*/ * size.Z/*# }\n                                               if (d > 3) {*/ * size.W/*# } */], new __ttn__Info(size))\n        { }\n\n        /// <summary>\n        /// Construct __ttnl__ of specified size.\n        /// </summary>\n        public __ttn__(__iitn__ size)\n            : this((__itn__)size)\n        { }\n\n        /// <summary>\n        /// Construct __ttnl__ with specified info.\n        /// </summary>\n        public __ttn__(__ttn__Info info)\n            : this(new __dtn__[info.Count], new __ttn__Info(info))\n        { }\n\n        //# if (d == 1) {\n        /// <summary>\n        /// Construct from data array without copying.\n        /// </summary>\n        public __ttn__(__dtn__[] data)\n            : this(data, new __ttn__Info(data.Length))\n        { }\n\n        //# } else if (d > 1) {\n        /// <summary>\n        /// Construct __ttnl__ of specified size.\n        /// </summary>\n        public __ttn__(/*# iaa.ForEach(a => { */long s__a__/*# }, comma); */)\n            : this(new __itn__(/*# iaa.ForEach(a => { */s__a__/*# }, comma); */))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public __ttn__(__dtn__[] data, /*# iaa.ForEach(a => { */long s__a__/*# }, comma); */)\n            : this(data, new __ttn__Info(/*# iaa.ForEach(a => { */s__a__/*# }, comma); */))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and sets all elements to the supplied value.\n        /// </summary>\n        public __ttn__(/*# iaa.ForEach(a => { */long s__a__/*# }, comma); */, __vtn__ value)\n            : this(new __itn__(/*# iaa.ForEach(a => { */s__a__/*# }, comma); */), value)\n        { }\n\n        //# }\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public __ttn__(__dtn__[] data, __itn__ size)\n            : this(data, new __ttn__Info(size))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size without copying.\n        /// </summary>\n        public __ttn__(__dtn__[] data, __iitn__ size)\n            : this(data, new __ttn__Info(size))\n        { }\n\n        /// <summary>\n        /// Construct __ttnl__ of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public __ttn__(__itn__ size, __vtn__ value)\n            : this(new __dtn__[size/*# if (d > 1) {*/.X * size.Y/*# }\n                                           if (d > 2) {*/ * size.Z/*# }\n                                               if (d > 3) {*/ * size.W/*# }*/], new __ttn__Info(size))\n        {\n            Set(value);\n        }\n\n        /// <summary>\n        /// Construct matrix of specified size, with all elements set to\n        /// the supplied value.\n        /// </summary>\n        public __ttn__(__iitn__ size, __vtn__ value)\n            : this((__itn__)size, value)\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public __ttn__(__dtn__[] data, long origin, __itn__ size, __itn__ delta)\n            : this(data, new __ttn__Info(origin, size, delta))\n        { }\n\n        /// <summary>\n        /// Construct from data array with specified size and delta without copying.\n        /// </summary>\n        public __ttn__(__dtn__[] data, long origin, __itn__ size, __itn__ delta, __itn__ first)\n            : this(data, new __ttn__Info(origin, size, delta, first))\n        { }\n\n        /// <summary>\n        /// Construct with specified size and delta.\n        /// </summary>\n        public __ttn__(long origin, __itn__ size, __itn__ delta)\n            : this(new __dtn__[size/*# if (d > 1) {*/.X * size.Y/*# }\n                                           if (d > 2) {*/ * size.Z/*# }\n                                              if (d > 3) {*/ * size.W/*# }\n                                                                   */],\n                   new __ttn__Info(origin, size, delta))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        /// <summary>\n        /// Return the rank or dimension of the __ttnl__ (__d__).\n        /// </summary>\n        public readonly int Rank { get { return Info.Rank; } }\n\n        public long Origin { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        public __itn__ Size { readonly get { return Info.Size; } set { Info.Size = value; } }\n\n        public __itn__ Delta { readonly get { return Info.Delta; } set { Info.Delta = value; } }\n\n        public __itn__ First { readonly get { return Info.First; } set { Info.First = value; } }\n\n        //# if (dt != vt) {\n        public TensorAccessors<__dtn__, __vtn__> Accessors\n        {\n            readonly get\n            {\n                return new TensorAccessors<__dtn__, __vtn__>()\n                                { Getter = Getter, Setter = Setter };\n            }\n            set { Getter = value.Getter; Setter = value.Setter; }\n        }\n\n        //# }\n        /// <summary>\n        /// Returns true if the __ttnl__ has a data array.\n        /// </summary>\n        public readonly bool IsValid { get { return Data != null; } }\n\n        /// <summary>\n        /// Returns true if the __ttnl__ does not have a data array.\n        /// </summary>\n        public readonly bool IsInvalid { get { return Data == null; } }\n\n        /// <summary>\n        /// Total number of element in the matrix.\n        /// </summary>\n        public readonly long Count { get { return Info.Count; } }\n\n        /// <summary>\n        /// One step beyond the last element.\n        /// </summary>\n        public readonly __itn__ End { get { return Info.E; } }\n\n        //# for (int di = 0; di < (1 << d); di++) {\n        //#     var pnt = d.Range().Select(i => (di & (1 << i)) == 0 ? \"O\" : \"I\").Join();\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly __itn__ __pnt__ { get { return Info.__pnt__; } }\n        //# }\n\n        /// <summary>\n        /// Size\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __itn__ S { readonly get { return Info.S; } set { Info.S = value; } }\n\n        /// <summary>\n        /// Delta\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __itn__ D { readonly get { return Info.D; } set { Info.D = value; } }\n\n        /// <summary>\n        /// First\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public __itn__ F { readonly get { return Info.F; } set { Info.F = value; } }\n\n        /// <summary>\n        /// End: one step beyond the last element.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly __itn__ E { get { return Info.E; } }\n\n        //# if (d == 1) {\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DS { get { return Info.D; } }\n\n        //# }\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// Size in dimension __f__.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long S__f__ { readonly get { return Info.S__f__; } set { Info.S__f__ = value; } }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// Delta in dimension __f__.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long D__f__ { readonly get { return Info.D__f__; } set { Info.D__f__ = value; } }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// First in dimension __f__.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long F__f__ { readonly get { return Info.F__f__; } set { Info.F__f__ = value; } }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// End in dimension __f__ (one step beyond the last element).\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long E__f__ { get { return Info.E__f__; } }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// Jump this many elements in the underlying data array when stepping\n        /// in dimension __f__.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long J__f__ { get { return Info.J__f__; } }\n\n        //# } // foreach\n        //# foreach (var f in ifa) {\n        /// <summary>\n        /// Cummulative delta for all elements up to this dimension.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly long DS__f__ { get { return Info.DS__f__; } }\n\n        //# } // foreach\n        /// <summary>\n        /// Return the index of the first element in the underlying\n        /// data array.\n        /// </summary>\n        public readonly long FirstIndex { get { return Info.FirstIndex; } }\n\n        public long OriginIndex { readonly get { return Info.Origin; } set { Info.Origin = value; } }\n\n        /// <summary>\n        /// Get or set the size of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] SizeArray\n        {\n            readonly get { return Info.SizeArray; }\n            set { Info.SizeArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the deltas of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] DeltaArray\n        {\n            readonly get { return Info.DeltaArray; }\n            set { Info.DeltaArray = value; }\n        }\n\n        /// <summary>\n        /// Get or set the first coords of the tensor in each dimension as an\n        /// array of longs.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public long[] FirstArray\n        {\n            readonly get { return Info.FirstArray; }\n            set { Info.FirstArray = value; }\n        }\n\n        /// <summary>\n        /// Yields all elemnts ordered by index.\n        /// </summary>\n        public readonly IEnumerable<__vtn__> Elements\n        {\n            get\n            {\n                //# Loop(\"\", false, () => {\n                    yield return __t0i__;\n                //# }, false, false);\n            }\n        }\n\n        /// <summary>\n        /// Return the type of the underlying data array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public readonly Type ArrayType\n        {\n            get { return typeof(__dtn__[]); }\n        }\n\n        /// <summary>\n        /// Return the underlying data array as an untyped array.\n        /// </summary>\n        [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n        public Array Array\n        {\n            readonly get { return Data; }\n            set { Data = (__dtn__[])value; }\n        }\n\n        //# if (d == 2) {\n        /// <summary>\n        /// Returns a matrix that represents a view on the same data with flipped coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> Transposed\n        {\n            get\n            {\n                return new __ttn__<__dvtn__>(Data, Info.Transposed)/*#\n                            if (dt != vt) { */\n                                        { Getter = Getter, Setter = Setter }/*# } */;\n            }\n        }\n\n        //# } // d == 2\n        #endregion\n\n        #region Indexers\n\n        //# if (d > 1) {\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly __vtn__ this[__itn__ v]\n        {\n            get\n            {\n                //# if (dt == vt) {\n                return Data[Info.Origin\n                              + /*# ifa.ForEach(f =>\n                                    { */v.__f__ * Info.Delta.__f__/*# }, add); */];\n                //# } else {\n                return Getter(Data, Info.Origin\n                              + /*# ifa.ForEach(f =>\n                                    { */v.__f__ * Info.Delta.__f__/*# }, add); */);\n                //# }\n            }\n            set\n            {\n                //# if (dt == vt) {\n                Data[Info.Origin\n                       + /*# ifa.ForEach(f =>\n                             { */v.__f__ * Info.Delta.__f__/*# }, add); */] = value;\n                //# } else {\n                Setter(Data, Info.Origin\n                       + /*# ifa.ForEach(f =>\n                             { */v.__f__ * Info.Delta.__f__/*# }, add); */, value);\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinate.\n        /// </summary>\n        public readonly __vtn__ this[__iitn__ v]\n        {\n            get\n            {\n                //# if (dt == vt) {\n                return Data[Info.Origin\n                              + /*# ifa.ForEach(f =>\n                                    { */(long)v.__f__ * Info.Delta.__f__/*# }, add); */];\n                //# } else {\n                return Getter(Data, Info.Origin\n                              + /*# ifa.ForEach(f =>\n                                    { */(long)v.__f__ * Info.Delta.__f__/*# }, add); */);\n                //# }\n            }\n            set\n            {\n                //# if (dt == vt) {\n                Data[Info.Origin\n                       + /*# ifa.ForEach(f =>\n                             { */(long)v.__f__ * Info.Delta.__f__/*# }, add); */] = value;\n                //# } else {\n                Setter(Data, Info.Origin\n                       + /*# ifa.ForEach(f =>\n                             { */(long)v.__f__ * Info.Delta.__f__/*# }, add); */, value);\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at the specified index in the underlying data array.\n        /// </summary>\n        public readonly __vtn__ this[long index]\n        {\n            get\n            {\n                //# if (dt == vt) {\n                return Data[index];\n                //# } else {\n                return Getter(Data, index);\n                //# }\n            }\n            set\n            {\n                //# if (dt == vt) {\n                Data[index] = value;\n                //# } else {\n                Setter(Data, index, value);\n                //# }\n            }\n        }\n\n        //# }\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly __vtn__ this[/*# iaa.ForEach(a => { */long __a__/*# }, comma); */]\n        {\n            get\n            {\n                //# if (dt == vt) {\n                return Data[Info.Origin\n                              + /*# iaa.ForEach(ideltas, (a, di) =>\n                                    { */__a__ * Info.__di__/*# }, add); */];\n                //# } else {\n                return Getter(Data, Info.Origin\n                              + /*# iaa.ForEach(ideltas, (a, di) =>\n                                    { */__a__ * Info.__di__/*# }, add); */);\n                //# }\n            }\n            set\n            {\n                //# if (dt == vt) {\n                Data[Info.Origin\n                       + /*# iaa.ForEach(ideltas, (a, di) =>\n                             { */__a__ * Info.__di__/*# }, add); */] = value;\n                //# } else {\n                Setter(Data, Info.Origin\n                       + /*# iaa.ForEach(ideltas, (a, di) =>\n                             { */__a__ * Info.__di__/*# }, add); */, value);\n                //# }\n            }\n        }\n\n        /// <summary>\n        /// Get/Set element at specified coordinates.\n        /// </summary>\n        public readonly __vtn__ this[/*# iaa.ForEach(a => { */int __a__/*# }, comma); */]\n        {\n            get\n            {\n                //# if (dt == vt) {\n                return Data[Info.Origin\n                              + /*# iaa.ForEach(ideltas, (a, di) =>\n                                    { */(long)__a__ * Info.__di__/*# }, add); */];\n                //# } else {\n                return Getter(Data, Info.Origin\n                              + /*# iaa.ForEach(ideltas, (a, di) =>\n                                    { */(long)__a__ * Info.__di__/*# }, add); */);\n                //# }\n            }\n            set\n            {\n                //# if (dt == vt) {\n                Data[Info.Origin\n                       + /*# iaa.ForEach(ideltas, (a, di) =>\n                             { */(long)__a__ * Info.__di__/*# }, add); */] = value;\n                //# } else {\n                Setter(Data, Info.Origin\n                       + /*# iaa.ForEach(ideltas, (a, di) =>\n                             { */(long)__a__ * Info.__di__/*# }, add); */, value);\n                //# }\n            }\n        }\n\n        #endregion\n\n        #region Actions for each Element\n\n        public readonly void ForeachIndex(Action<long> i_action)\n        {\n            Info.ForeachIndex(i_action);\n        }\n\n        //# { var i_action = \"\"; iaa.ForEach(a => i_action += a + \"_\"); i_action += \"i_action\";\n        public readonly void ForeachIndex(Action</*# iaa.ForEach(f => {*/long/*# }, comma);*/, long> __i_action__)\n        {\n            Info.ForeachIndex(__i_action__);\n        }\n        //# } // var i_action\n\n        public readonly void ForeachCoord(Action<__itn__> v_action)\n        {\n            Info.ForeachCoord(v_action);\n        }\n\n        public readonly void ForeachIndex(__ttn__Info t1, Action<long, long> i_i1_act)\n        {\n            Info.ForeachIndex(t1, i_i1_act);\n        }\n\n        //# if (d > 1) {\n        //# foreach (bool idx in new[] { false, true }) { var idxstr = idx ? \"Index\" : \"\";\n        //# ifa.ForEach(iaa, (f,a) => {\n        //# foreach (bool crd in new[] { false, true }) { if (!crd && !idx) continue;\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// and calls the supplied action with the index into the data\n        /// array as parameter. Optionally, the coordinates of each element\n        /// are also fed into the supplied action.\n        /// </summary>\n        //# var elementAct = (crd ? a + \"_\" : \"\") + (idx ? \"i_\" : \"\") + \"elementAct\";\n        public readonly void Foreach__f____idxstr__(\n                Action</*# if (crd) { */long/*# if (idx) { */, /*# }} if (idx) { */long/*# } */> __elementAct__)\n        {\n            Info.Foreach__f____idxstr__(__elementAct__);\n        }\n\n        //# } // crd\n        //# });\n        //# ifa.ForEach(iaa, (f2,a2) => {\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2) {\n        //# foreach (bool crd in new[] { false, true }) { if (!crd && !idx) continue;\n        //# foreach (bool pre in new[] { false, true }) {\n        //# foreach (bool post in new[] { false, true }) {\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line and post-line actions can be specified.\n        /// </summary>\n        //# var preLineAct = (crd ? a2 + \"_\" : \"\") + \"preLineAct\";\n        //# var elementAct = (crd ? a2 + \"_\" + a1 + \"_\" : \"\") + (idx ? \"i_\" : \"\") + \"elementAct\";\n        //# var postLineAct = (crd ? a2 + \"_\" : \"\") + \"postLineAct\";\n        public readonly void Foreach__f2____f1____idxstr__(\n                /*# if (pre) { */Action/*# if (crd) { */<long>/*# } */ __preLineAct__,\n                /*# } */Action</*# if (crd) { */long, long/*# if (idx) { */, /*# }} if (idx) { */long/*# } */> __elementAct__/*# if (post) { */,\n                Action/*# if (crd) { */<long>/*# } */ __postLineAct__/*# } */)\n        {\n            Info.Foreach__f2____f1____idxstr__(\n                    /*# if (pre) { */__preLineAct__,\n                    /*# } */__elementAct__/*# if (post) {  */,\n                    __postLineAct__/*# } */);\n        }\n\n        //# } // post\n        //# } // pre\n        //# } // crd\n        //# }});\n        //# });\n        //# } // idx\n        //# } // (d > 1)\n        //# if (d > 2) {\n        //# foreach (bool idx in new[] { false, true }) { var idxstr = idx ? \"Index\" : \"\";\n        //# ifa.ForEach(iaa, (f3,a3) => {\n        //# ifa.ForEach(iaa, (f2,a2) => { if (f2 != f3) {\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2 && f1 != f3) {\n        //# foreach (bool crd in new[] { false, true }) { if (!crd && !idx) continue;\n        //# foreach (bool pre in new[] { false, true }) {\n        //# foreach (bool post in new[] { false, true }) {\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        //# var prePlaneAct = (crd ? a3 + \"_\" : \"\") + \"prePlaneAct\";\n        //# var preLineAct = (crd ? a3 + \"_\" + a2 + \"_\" : \"\") + \"preLineAct\";\n        //# var elementAct = (crd ? a3 + \"_\" + a2 + \"_\" + a1 + \"_\" : \"\") + (idx ? \"i_\" : \"\") + \"elementAct\";\n        //# var postLineAct = (crd ? a3 + \"_\" + a2 + \"_\" : \"\") + \"postLineAct\";\n        //# var postPlaneAct = (crd ? a3 + \"_\" : \"\") + \"postPlaneAct\";\n        public readonly void Foreach__f3____f2____f1____idxstr__(/*# if (pre) { */\n                Action/*# if (crd) { */<long>/*# } */ __prePlaneAct__,\n                Action/*# if (crd) { */<long, long>/*# } */ __preLineAct__,/*# } */\n                Action</*# if (crd) { */long, long, long/*# if (idx) { */, /*# }} if (idx) { */long/*# } */> __elementAct__/*# if (post) { */,\n                Action/*# if (crd) { */<long, long>/*# } */ __postLineAct__,\n                Action/*# if (crd) { */<long>/*# } */ __postPlaneAct__/*# } */)\n        {\n            Info.Foreach__f3____f2____f1____idxstr__(\n                    /*# if (pre) { */__prePlaneAct__,\n                    __preLineAct__,\n                    /*# } */__elementAct__/*# if (post) {  */,\n                    __postLineAct__,\n                    __postPlaneAct__/*# } */);\n        }\n\n        //# } // post\n        //# } // pre\n        //# } // crd\n        //# }});\n        //# }});\n        //# });\n        //# } // idx\n        //# } // (d > 2)\n        //# if (d > 3) {\n        //# foreach (bool idx in new[] { false, true }) { var idxstr = idx ? \"Index\" : \"\";\n        //# ifa.ForEach(iaa, (f4,a4) => {\n        //# ifa.ForEach(iaa, (f3,a3) => { if (f3 != f4) {\n        //# ifa.ForEach(iaa, (f2,a2) => { if (f2 != f3 && f2 != f4) {\n        //# ifa.ForEach(iaa, (f1,a1) => { if (f1 != f2 && f1 != f3 && f1 != f4) {\n        //# foreach (bool crd in new[] { false, true }) { if (!crd && !idx) continue;\n        //# foreach (bool pre in new[] { false, true }) {\n        //# foreach (bool post in new[] { false, true }) {\n        /// <summary>\n        /// Loops over  the underlying data array in the specified order,\n        /// with the first coordinate being the outer loop, and the last\n        /// coordinate being the inner loop, and calls the supplied action\n        /// with the index into the data array as parameter. Optionally, the\n        /// coordinates of each element are also fed into the supplied action\n        /// (in the order specified in the name of the function), and also\n        /// optionally pre-line, post-line, pre-plane, and post-plane\n        /// actions can be specified.\n        /// </summary>\n        //# var preVolumeAct = (crd ? a4 + \"_\" : \"\") + \"preVolumeAct\";\n        //# var prePlaneAct = (crd ? a4 + \"_\" + a3 + \"_\" : \"\") + \"prePlaneAct\";\n        //# var preLineAct = (crd ? a4 + \"_\" + a3 + \"_\" + a2 + \"_\" : \"\") + \"preLineAct\";\n        //# var elementAct = (crd ? a4 + \"_\" + a3 + \"_\" + a2 + \"_\" + a1 + \"_\" : \"\") + (idx ? \"i_\" : \"\") + \"elementAct\";\n        //# var postLineAct = (crd ? a4 + \"_\" + a3 + \"_\" + a2 + \"_\" : \"\") + \"postLineAct\";\n        //# var postPlaneAct = (crd ? a4 + \"_\" + a3 + \"_\" : \"\") + \"postPlaneAct\";\n        //# var postVolumeAct = (crd ? a4 + \"_\" : \"\") + \"postVolumeAct\";\n        public readonly void Foreach__f4____f3____f2____f1____idxstr__(/*# if (pre) { */\n                Action/*# if (crd) { */<long>/*# } */ __preVolumeAct__,\n                Action/*# if (crd) { */<long, long>/*# } */ __prePlaneAct__,\n                Action/*# if (crd) { */<long, long, long>/*# } */ __preLineAct__,/*# } */\n                Action</*# if (crd) { */long, long, long, long/*# if (idx) { */, /*# }} if (idx) { */long/*# } */> __elementAct__/*# if (post) { */,\n                Action/*# if (crd) { */<long, long, long>/*# } */ __postLineAct__,\n                Action/*# if (crd) { */<long, long>/*# } */ __postPlaneAct__,\n                Action/*# if (crd) { */<long>/*# } */ __postVolumeAct__/*# } */)\n        {\n            Info.Foreach__f4____f3____f2____f1____idxstr__(\n                    /*# if (pre) { */__preVolumeAct__,\n                    __prePlaneAct__,\n                    __preLineAct__,\n                    /*# } */__elementAct__/*# if (post) {  */,\n                    __postLineAct__,\n                    __postPlaneAct__,\n                    __postVolumeAct__/*# } */);\n        }\n\n        //# } // post\n        //# } // pre\n        //# } // crd\n        //# }});\n        //# }});\n        //# }});\n        //# });\n        //# } // idx\n        //# } // (d > 3)\n        #endregion\n\n        #region Reinterpretation and Parts\n\n        //# bools.ForEach(t1v => { var pt1 = t1v ? \"<T1>\" : \"\";\n        //# var dvt1tn = dtn + (t1v ? \", T1\" : (dt != vt ? \", \" + vtn : \"\"));\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn__Window__pt1__(__itn__ begin, __itn__ size)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__Window(begin, size))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn____pt1__(__itn__ begin, __itn__ size)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__(begin, size))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn__Window__pt1__(__iitn__ begin, __iitn__ size)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__Window(begin, size))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn____pt1__(__iitn__ begin, __iitn__ size)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__(begin, size))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn__Window__pt1__(__itn__ begin, __itn__ size, __itn__ delta)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__Window(begin, size, delta))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn____pt1__(__itn__ begin, __itn__ size, __itn__ delta)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__(begin, size, delta))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn__Window__pt1__(__iitn__ begin, __iitn__ size, __iitn__ delta)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__Window(begin, size, delta))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn____pt1__(__iitn__ begin, __iitn__ size, __iitn__ delta)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__(begin, size, delta))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        //# if (d > 1) {\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn__Window__pt1__(__itn__ begin, __itn__ size, __itn__ delta, __itn__ first)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__Window(begin, size, delta, first))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn__Window__pt1__(__iitn__ begin, __iitn__ size, __iitn__ delta, __iitn__ first)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__ttn__Window(begin, size, delta, first))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn__Window__pt1__(\n                /*# ifa.ForEach(f => { */long begin__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long size__f__/*# }, comma); */)\n        {\n            return new __ttn__<__dvt1tn__>(Data,\n                            Info.Sub__ttn__Window(/*# ifa.ForEach(f => { */begin__f__/*# }, comma); */,\n                                           /*# ifa.ForEach(f => { */size__f__/*# }, comma); */))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn____pt1__(\n                /*# ifa.ForEach(f => { */long begin__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long size__f__/*# }, comma); */)\n        {\n            return new __ttn__<__dvt1tn__>(Data,\n                            Info.Sub__ttn__(/*# ifa.ForEach(f => { */begin__f__/*# }, comma); */,\n                                               /*# ifa.ForEach(f => { */size__f__/*# }, comma); */))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This method retains the coordinates of the parent __ttn__.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn__Window__pt1__(\n                /*# ifa.ForEach(f => { */long begin__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long size__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long delta__f__/*# }, comma); */)\n        {\n            return new __ttn__<__dvt1tn__>(Data,\n                            Info.Sub__ttn__Window(/*# ifa.ForEach(f => { */begin__f__/*# }, comma); */,\n                                           /*# ifa.ForEach(f => { */size__f__/*# }, comma); */,\n                                           /*# ifa.ForEach(f => { */delta__f__/*# }, comma); */))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__ttn____pt1__(\n                /*# ifa.ForEach(f => { */long begin__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long size__f__/*# }, comma); */,\n                /*# ifa.ForEach(f => { */long delta__f__/*# }, comma); */)\n        {\n            return new __ttn__<__dvt1tn__>(Data,\n                            Info.Sub__ttn__(/*# ifa.ForEach(f => { */begin__f__/*# }, comma); */,\n                                               /*# ifa.ForEach(f => { */size__f__/*# }, comma); */,\n                                               /*# ifa.ForEach(f => { */delta__f__/*# }, comma); */))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        //# if (d == 2) {\n        /// If the lines of the matrix are stored consecutively without gaps,\n        /// the whole matrix can be viewed as a single vector.\n        //# } else {\n        /// If the lines and planes of the volume are stored consecutively\n        /// without gaps, the whole volume can be viewed as a single vector.\n        //# }\n        /// </summary>\n        public readonly __vectn__<__dvt1tn__> As__vectn____pt1__()\n        {\n            return new __vectn__<__dvt1tn__>(Data, Info.As__vectn__())/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __vectn__<__dvt1tn__> Sub__vectn____pt1__(__itn__ origin, long size, long delta)\n        {\n            return new __vectn__<__dvt1tn__>(Data, Info.Sub__vectn__(origin, size, delta))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A SubVector does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __vectn__<__dvt1tn__> Sub__vectn____pt1__(__iitn__ origin, long size, long delta)\n        {\n            return new __vectn__<__dvt1tn__>(Data, Info.Sub__vectn__(origin, size, delta))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        //# if (d == 2) {\n        //# for (int ai = 0; ai < d; ai++) {var a = iaa[ai];\n        //#     var fa = \"\"; ifa.ForEach((f,i) => { if (i != ai) fa = fa + f; });\n        //#     var fn = fa == \"X\" ? \"Row\" : \"Col\";\n        //#     foreach (var win in new bool[] { false, true }) { var winstr = win ? \"Window\" : \"\";\n        /// <summary>\n        /// Return a full __fa__ __ttsub1nl__ slice of the __ttnl__.\n        //# if (win) {\n        /// This method retains the coordinates of the parent __ttnl__.\n        //# } else {\n        /// This methods returns a __ttsub1nl__ with zero as first coordinates.\n        //# }\n        /// </summary>\n        public readonly __ttsub1n__<__dvt1tn__> __fn____winstr____pt1__(long __a__)\n        {\n            return new __ttsub1n__<__dvt1tn__>(Data, Info.__fn____winstr__(__a__))/*#\n                            if (dt != vt && pt1 == \"\") { */\n            { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        //# } // win\n        //# } // ai\n        //# } // d == 2\n        //# if (d == 3) {\n        /// <summary>\n        /// If the lines of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly __mattn__<__dvt1tn__> As__mattn__XYxZ__pt1__()\n        {\n            return new __mattn__<__dvt1tn__>(Data, Info.As__mattn__XYxZ())/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// If the planes of the volume are stored consecutively without gaps,\n        /// they can be merged, and the volume can be viewed as a matrix.\n        /// </summary>\n        public readonly __mattn__<__dvt1tn__> As__mattn__XxYZ__pt1__()\n        {\n            return new __mattn__<__dvt1tn__>(Data, Info.As__mattn__XxYZ())/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __mattn__<__dvt1tn__> Sub__mattn____pt1__(__itn__ origin, V2l size, V2l delta)\n        {\n            return new __mattn__<__dvt1tn__>(Data, Info.Sub__mattn__(origin, size, delta))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __mattn__<__dvt1tn__> Sub__mattn____pt1__(__iitn__ origin, V2i size, V2l delta)\n        {\n            return new __mattn__<__dvt1tn__>(Data, Info.Sub__mattn__(origin, size, delta))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// A Sub__ttn__ does not copy any data, and thus any operations on it\n        /// are reflected in the corresponding part of the parent.\n        /// </summary>\n        public readonly __mattn__<__dvt1tn__> Sub__mattn____pt1__(\n                long beginX, long beginY, long beginZ,\n                long sizeX, long sizeY, long deltaX, long deltaY)\n        {\n            return new __mattn__<__dvt1tn__>(Data,\n                    Info.Sub__mattn__(beginX, beginY, beginZ,\n                                         sizeX, sizeY, deltaX, deltaY))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        //# } // (d == 3)\n        //# for (int ai = 0; ai < d; ai++) {\n        //#     var a = iaa[ai];\n        //#     var fa = \"\"; ifa.ForEach((f,i) => { if (i != ai) fa = fa + f; });\n        //#     foreach (var win in new bool[] { false, true }) { var winstr = win ? \"Window\" : \"\";\n        /// <summary>\n        /// Return a full __fa__ __ttsub1nl__ slice of the __ttnl__.\n        //# if (win) {\n        /// This method retains the coordinates of the parent __ttnl__.\n        //# } else {\n        /// This methods returns a __ttsub1nl__ with zero as first coordinates.\n        //# }\n        /// </summary>\n        public readonly __ttsub1n__<__dvt1tn__> Sub__fa____ttsub1n____winstr____pt1__(long __a__)\n        {\n            return new __ttsub1n__<__dvt1tn__>(Data, Info.Sub__fa____ttsub1n____winstr__(__a__))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        /// <summary>\n        /// Return a full __fa__ __ttsub1nl__ slice of the __ttnl__ as a special __ttnl__\n        /// that replicates the __ttsub1nl__ the supplied number of times. The special\n        /// __ttnl__ can only be correctly used to read from. Other operations are not guaranteed.\n        //# if (win) {\n        /// This method retains the coordinates of the parent __ttnl__.\n        //# } else {\n        /// This methods returns a __ttsub1nl__ with zero as first coordinates.\n        //# }\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__fa____ttsub1n__AsReadOnly__ttn____winstr____pt1__(long __a__, long size__a__)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__fa____ttsub1n__AsReadOnly__ttn____winstr__(__a__, size__a__))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        //# } // win\n        //# } // ai\n        //# for (int ai = 0; ai < d-1; ai++) { var a = iaa[ai];\n        //# for (int bi = ai + 1; bi < d; bi++) { var b = iaa[bi];\n        //#     var fa = \"\"; ifa.ForEach((f,i) => { if (i != ai && i != bi) fa = fa + f; });\n        //#     foreach (var win in new bool[] { false, true }) { var winstr = win ? \"Window\" : \"\";\n        /// <summary>\n        /// Return a full __fa__ __ttsub2nl__ slice of the __ttnl__ as a special __ttnl__\n        /// that replicates the __ttsub2nl__ the supplied number of times. The special\n        /// __ttnl__ can only be correctly used to read from. Other operations are not guaranteed.\n        //# if (win) {\n        /// This method retains the coordinates of the parent __ttnl__.\n        //# } else {\n        /// This methods returns a __ttnl__ with zero as first coordinates.\n        //# }\n        /// </summary>\n        public readonly __ttn__<__dvt1tn__> Sub__fa____ttsub2n__AsReadOnly__ttn____winstr____pt1__(long __a__, long __b__, long size__a__, long size__b__)\n        {\n            return new __ttn__<__dvt1tn__>(Data, Info.Sub__fa____ttsub2n__AsReadOnly__ttn____winstr__(__a__, __b__, size__a__, size__b__))/*#\n                            if (dt != vt && pt1 == \"\") { */\n                                    { Getter = Getter, Setter = Setter }/*# } */;\n        }\n\n        //# } // win\n        //# } // bi\n        //# } // ai\n        //# } // (d > 1)\n        //# }); // t1v\n        #endregion\n\n        #region Copying\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> Copy()\n        {\n            //# if (dt != vt) {\n            return new __ttn__<__dvtn__>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.Set(this);\n            //# } else {\n            return new __ttn__<__dvtn__>(Info.S).Set(this);\n            //# }\n        }\n\n        /// <summary>\n        /// Elementwise copy.\n        /// This method retains the coordinates of the original __ttn__.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> CopyWindow()\n        {\n            return new __ttn__<__dvtn__>(Info.S)\n                    { F = F, /*# if (dt != vt) { */Getter = Getter, Setter = Setter/*# } */ }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<T1> Map<T1>(Func<__vtn__, T1> fun)\n        {\n            return new __ttn__<T1>(Info.S).SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the coordinates of the original __ttn__.\n        /// </summary>\n        public readonly __ttn__<T1> MapWindow<T1>(Func<__vtn__, T1> fun)\n        {\n            return new __ttn__<T1>(Info.S) { F = F }.SetMap(this, fun);\n        }\n\n        //# if (dt != vt) {\n        public readonly __ttn__<__vtn__> CopyView()\n        {\n            return new __ttn__<__vtn__>(Info.S).Set(this);\n        }\n\n        public readonly __ttn__<__vtn__> CopyViewWindow()\n        {\n            return new __ttn__<__vtn__>(Info.S) { F = F }.Set(this);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This methods returns a __ttn__ with zero as first coordinates.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> Map(Func<__vtn__, __vtn__> fun)\n        {\n            return new __ttn__<__dvtn__>(new Td[Data.LongLength], Info) { Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        /// <summary>\n        /// Elementwise copy with function application.\n        /// This method retains the complete layout of the original __ttn__.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> MapWindow(Func<__vtn__, __vtn__> fun)\n        {\n            return new __ttn__<__dvtn__>(new Td[Data.LongLength], Info)\n                        { F = F, Getter = Getter, Setter = Setter }.SetMap(this, fun);\n        }\n\n        //# } // dt != vt\n        //# if (dt == vt) {\n        /// <summary>\n        /// Returns a tensor repeated in each dimension by the specified\n        /// count.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> Repeated(__itn__ count)\n        {\n            var size = Size;\n            count *= size;\n            var t = new __ttn__<__dvtn__>(count);\n            //# if (d == 1) {\n            for (__itn__ p = 0; p < count; p += size)\n                t.Sub__ttn__(p, size).Set(this);\n            //# } else { // d > 1\n            __itn__ p;\n            //# rifa.ForEach(f => {\n            for (p.__f__ = 0; p.__f__ < count.__f__; p.__f__ += size.__f__)\n                //# });\n                t.Sub__ttn__(p, size).Set(this);\n            //# } // d > 1\n            return t;\n        }\n\n        //# } // dt == vt\n        #endregion\n\n        #region Manipulation Methods\n\n        /// <summary>\n        /// Apply the supplied function on the elements of the __ttnl__.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> Apply(Func<__vtn__, __vtn__> element_elementFun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                //# r1ifa.ForEach(r1iaa, (f, a) => {\n                for (long __a__e = i + Info.DS__f__, __a__j = Info.J__f__; i != __a__e; i += __a__j)\n                //# });\n                for (long xe = i + Info.SX; i != xe; i++)\n                    //# if (dt != vt) {\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n                    //# } else {\n                    Data[i] = element_elementFun(Data[i]);\n                    //# }\n            }\n            else\n            {\n                //# rifa.ForEach(riaa, (f, a) => {\n                for (long __a__e = i + Info.DS__f__, __a__j = Info.J__f__; i != __a__e; i += __a__j)\n                //# }); if (dt != vt) {\n                    Setter(Data, i, element_elementFun(Getter(Data, i)));\n                    //# } else {\n                    Data[i] = element_elementFun(Data[i]);\n                    //# }\n            }\n            return this;\n        }\n\n        //# bools.ForEach(t1v => { var t1t = tnt(1, t1v); var t1i = tni(1, t1v); var t1i1 = tnin(1, t1v);\n        /// <summary>\n        /// Apply the supplied function to each pair of corresponding\n        /// elements of the original __ttnl__ and the supplied __ttnl__.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> Apply<__t1t__>(\n                __ttn__<__t1t__> t1, Func<__vtn__, T1, __vtn__> element_element1_elementFun)\n        {\n            //# LoopN(\"\", false, dt == vt && !t1v, 2, 0, ix => { var t1ix = ix ? t1i1 : t1i;\n                        //# if (dt == vt) {\n                        Data[i] = element_element1_elementFun(__t0i__, __t1ix__);\n                        //# } else {\n                        Setter(Data, i, element_element1_elementFun(__t0i__, __t1ix__));\n                        //# }\n            //# });\n            return this;\n        }\n\n        //# }); // t1v\n        //# if (d > 1) {\n        /// <summary>\n        /// Apply the supplied function on the elements of the __ttnl__.\n        /// The value of the elements is given to fun.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> ApplyByCoord(Func<__vtn__, __itn__, __vtn__> element_crd_elementFun)\n        {\n            long i = FirstIndex; __itn__ vi;\n            if (Info.JX == 1)\n            {\n                //# r1ifa.ForEach(r1iaa, (f, a) => {\n                vi.__f__ = First.__f__;\n                for (long __a__e = i + Info.DS__f__, __a__j = Info.J__f__; i != __a__e; i += __a__j, vi.__f__++)\n                {\n                //# });\n                vi.X = First.X;\n                for (long xe = i + Info.SX; i != xe; i++, vi.X++)\n                    //# if (dt == vt) {\n                    Data[i] = element_crd_elementFun(Data[i], vi);\n                    //# } else {\n                    Setter(Data, i, element_crd_elementFun(Getter(Data, i), vi));\n                    //# }\n                //# for (int i = 0; i < d - 1; i++) {\n                }\n                //# }\n            }\n            else\n            {\n                //# rifa.ForEach(riaa, (f, a) => {\n                vi.__f__ = First.__f__;\n                for (long __a__e = i + Info.DS__f__, __a__j = Info.J__f__; i != __a__e; i += __a__j, vi.__f__++)\n                {\n                //# });\n                    //# if (dt == vt) {\n                    Data[i] = element_crd_elementFun(Data[i], vi);\n                    //# } else {\n                    Setter(Data, i, element_crd_elementFun(Getter(Data, i), vi));\n                    //# }\n                //# for (int i = 0; i < d; i++) {\n                }\n                //# }\n            }\n            return this;\n        }\n\n        //# } // d > 1\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> ApplyByCoord(Func<__vtn__, /*# iaa.ForEach(a => { */long/*# }, comma); */, __vtn__> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                //# r1ifa.ForEach(r1iaa, (f, a) => {\n                for (long __a__e = i + Info.DS__f__, __a__j = Info.J__f__, __a__ = Info.F__f__; i != __a__e; i += __a__j, __a__++)\n                //# });\n                for (long xe = i + Info.SX, x = Info.FX; i != xe; i++, x++)\n                    //# if (dt == vt) {\n                    Data[i] = fun(Data[i], /*# iaa.ForEach(a => { */__a__/*# }, comma); */);\n                    //# } else {\n                    Setter(Data, i, fun(Getter(Data, i), /*# iaa.ForEach(a => { */__a__/*# }, comma); */));\n                    //# }\n            }\n            else\n            {\n                //# rifa.ForEach(riaa, (f, a) => {\n                for (long __a__e = i + Info.DS__f__, __a__j = Info.J__f__, __a__ = Info.F__f__; i != __a__e; i += __a__j, __a__++)\n                //# }); if (dt == vt) {\n                    Data[i] = fun(Data[i], /*# iaa.ForEach(a => { */__a__/*# }, comma); */);\n                    //# } else {\n                    Setter(Data, i, fun(Getter(Data, i), /*# iaa.ForEach(a => { */__a__/*# }, comma); */));\n                    //# }\n            }\n            return this;\n        }\n\n        /// <summary>\n        /// Sets all elements to the supplied value.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> Set(__vtn__ v)\n        {\n            //# Loop(\"\", false, () => {\n                    //# if (dt == vt) {\n                    Data[i] = v;\n                    //# } else {\n                    Setter(Data, i, v);\n                    //# }\n            //# }, false, false);\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        //# { string fun = \"elementFun\"; riaa.ForEach(a => { fun = a + \"_\" + fun; });\n        public readonly __ttn__<__dvtn__> SetByCoord(Func</*# iaa.ForEach(a => { */long/*# }, comma); */, __vtn__> __fun__)\n        {\n            //# Loop(\"\", false, () => {\n                    //# if (dt == vt) {\n                    Data[i] = __fun__(/*# iaa.ForEach(a => { */__a__/*# }, comma); */);\n                    //# } else {\n                    Setter(Data, i, __fun__(/*# iaa.ForEach(a => { */__a__/*# }, comma); */));\n                    //# }\n            //# }, true, false);\n            return this;\n        }\n        //# } // fun\n\n        //# if (d > 1) {\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetByCoord(Func<__itn__, __vtn__> crd_elementFun)\n        {\n            //# Loop(\"\", false, () => {\n                    //# if (dt == vt) {\n                    Data[i] = crd_elementFun(v);\n                    //# } else {\n                    Setter(Data, i, crd_elementFun(v));\n                    //# }\n            //# }, false, true);\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the element coords.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetByCoord</*# r1iaa.ForEach(a => { */T__a__/*# }, comma); */>(\n                //# r1iaa.ForEach((a, i) => {\n                Func</*# riaa.Take(i+1).ForEach(fa => { */long/*# }, comma); */, /*# riaa.Take(i+1).ForEach(fa => { */T__fa__/*# }, comma); */> __a__Fun,\n                //# });\n                Func</*# iaa.ForEach(a => { */long/*# }, comma); */, /*# r1iaa.ForEach(a => { */T__a__/*# }, comma); */, __vtn__> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1)\n            {\n                //# r1ifa.ForEach(r1iaa, (f, a) => {\n                long __a__s = Info.DS__f__, __a__j = Info.J__f__;\n                //# });\n                long xs = Info.SX;\n                //# int fi = 0;\n                //# r1ifa.ForEach(r1iaa, (f, a) => {\n                for (long __a__e = i + __a__s, __a__ = Info.F__f__; i != __a__e; i += __a__j, __a__++) {\n                    var __a__Val = __a__Fun(/*# riaa.Take(fi+1).ForEach(fa => { */__fa__/*# }, comma); riaa.Take(fi).ForEach(fa => { */, __fa__Val/*# }); */);\n                //# fi++; });\n                for (long xe = i + xs, x = Info.FX; i != xe; i++, x++) {\n                    //# if (dt == vt) {\n                    Data[i] = fun(/*# riaa.ForEach(a => { */__a__/*# }, comma); */, /*# r1iaa.ForEach(a => { */__a__Val/*# }, comma); */);\n                    //# } else {\n                    Setter(Data, i, fun(/*# riaa.ForEach(a => { */__a__/*# }, comma); */, /*# r1iaa.ForEach(a => { */__a__Val/*# }, comma); */));\n                    //# }\n                }/*# r1ifa.ForEach(f => { */ }/*# }); */\n            }\n            else\n            {\n                //# rifa.ForEach(riaa, (f, a) => {\n                long __a__s = Info.DS__f__, __a__j = Info.J__f__;\n                //# });\n                //# fi = 0;\n                //# r1ifa.ForEach(r1iaa, (f, a) => {\n                for (long __a__e = i + __a__s, __a__ = Info.F__f__; i != __a__e; i += __a__j, __a__++) {\n                    var __a__Val = __a__Fun(/*# riaa.Take(fi+1).ForEach(fa => { */__fa__/*# }, comma); riaa.Take(fi).ForEach(fa => { */, __fa__Val/*# }); */);\n                //# fi++; });\n                for (long xe = i + xs, x = Info.FX; i != xe; i += xj, x++) {\n                    //# if (dt == vt) {\n                    Data[i] = fun(/*# riaa.ForEach(a => { */__a__/*# }, comma); */, /*# r1iaa.ForEach(a => { */__a__Val/*# }, comma); */);\n                    //# } else {\n                    Setter(Data, i, fun(/*# riaa.ForEach(a => { */__a__/*# }, comma); */, /*# r1iaa.ForEach(a => { */__a__Val/*# }, comma); */));\n                    //# }\n                }/*# r1ifa.ForEach(f => { */ }/*# }); */\n            }\n\n            return this;\n        }\n\n        //# } // d > 1\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied __ttnl__. The function may access the\n        /// elements of the supplied __ttnl__ to compute the elements of the\n        /// __ttnl__.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetByIndex(Func<long, __vtn__> index_elementFun)\n        {\n            //# Loop(\"\", false, () => {\n                    //# if (dt == vt) {\n                    Data[i] = index_elementFun(i);\n                    //# } else {\n                    Setter(Data, i, index_elementFun(i));\n                    //# }\n            //# }, false, false);\n            return this;\n        }\n\n        /// <summary>\n        /// Set from a tensor that conforms to the corresponding tensor\n        /// interface. Note, that this function checks if faster set\n        /// operations are available and uses them if appropriate.\n        /// </summary>\n        /// <param name=\"it1\"></param>\n        /// <returns></returns>\n        public readonly __ttn__<__dvtn__> Set(I__ttn__<__vtn__> it1)\n        {\n            if (it1 is __ttn__<__vtn__>) return Set((__ttn__<__vtn__>)it1);\n            //# Loop(\"\", false, () => {\n                    //# if (dt == vt) {\n                    Data[i] = it1[/*# iaa.ForEach(a => { */__a__/*# }, comma); */];\n                    //# } else {\n                    Setter(Data, i, it1[/*# iaa.ForEach(a => { */__a__/*# }, comma); */]);\n                    //# }\n            //# }, true, false);\n            return this;\n        }\n\n        //# bools.ForEach(t1v => { var t1t = tnt(1, t1v); var t1i = tni(1, t1v); var t1i1 = tnin(1, t1v);\n        /// <summary>\n        /// Copy all elements from another __ttnl__.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> Set/*# if (t1v) {*/<T1>/*# }*/(__ttn__</*# if (t1v) {*/T1, /*# }*/__vtn__> t1)\n        {\n            //# LoopN(\"\", false, dt == vt && !t1v, 2, 0, ix => { var t1ix = ix ? t1i1 : t1i;\n                        //# if (dt == vt) {\n                        Data[i] = __t1ix__;\n                        //# } else {\n                        Setter(Data, i, __t1ix__);\n                        //# }\n            //# });\n            return this;\n        }\n\n        /// <summary>\n        /// Set the elements of a __ttnl__ to the result of a function of\n        /// the elements of the supplied __ttnl__.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetMap<__t1t__>(\n                __ttn__<__t1t__> t1, Func<T1, __vtn__> element1_elementFun)\n        {\n            //# LoopN(\"\", false, dt == vt && !t1v, 2, 0, ix => { var t1ix = ix ? t1i1 : t1i;\n                        //# if (dt == vt) {\n                        Data[i] = element1_elementFun(__t1ix__);\n                        //# } else {\n                        Setter(Data, i, element1_elementFun(__t1ix__));\n                        //# }\n            //# });\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied __ttnl__. The function may access the\n        /// elements of the supplied __ttnl__ to compute the elements of the\n        /// __ttnl__.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetByIndex<__t1t__>(\n                __ttn__<__t1t__> t1, Func<long, __vtn__> index1_elementFun)\n        {\n            //# LoopN(\"\", false, dt == vt && !t1v, 2, 0, ix => { var i1 = ix ? \"i1\" : \"i\";\n                        //# if (dt == vt) {\n                        Data[i] = index1_elementFun(__i1__);\n                        //# } else {\n                        Setter(Data, i, index1_elementFun(__i1__));\n                        //# }\n            //# });\n            return this;\n        }\n\n        //# }); // t1v\n        //# bools.ForEach(t1v => { var t1t = tnt(1, t1v); var t1i = tni(1, t1v); var t1i1 = tnin(1, t1v);\n        //# bools.ForEach(t2v => { var t2t = tnt(2, t2v); var t2i = tni(2, t2v); var t2i2 = tnin(2, t2v);\n        /// <summary>\n        /// Set the elements of a __ttnl__ to the result of a function of\n        /// corresponding pairs of elements of the two supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetMap2<__t1t__, __t2t__>(\n                    __ttn__<__t1t__> t1, __ttn__<__t2t__> t2,\n                    Func<T1, T2, __vtn__> element1_element2_elementFun)\n        {\n            //# LoopN(\"\", false, dt == vt && !t1v && !t2v, 3, 0, ix => {\n            //# var t1ix = ix ? t1i1 : t1i;\n            //# var t2ix = ix ? t2i2 : t2i;\n            //# if (dt == vt) {\n            Data[i] = element1_element2_elementFun(__t1ix__, __t2ix__);\n            //# } else {\n            Setter(Data, i, element1_element2_elementFun(__t1ix__, __t2ix__));\n            //# }\n            //# });\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied __ttnl__. The function may access the\n        /// elements of the supplied __ttnl__ to compute the elements of the\n        /// __ttnl__.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetByIndex<__t1t__, __t2t__>(\n                __ttn__<__t1t__> t1, __ttn__<__t2t__> t2,\n                Func<long, long, __vtn__> index1_index2_elementFun)\n        {\n            //# LoopN(\"\", false, dt == vt && !t1v && !t2v, 3, 0, ix => {\n                        //# var i1 = ix ? \"i1\" : \"i\";\n                        //# var i2 = ix ? \"i2\" : \"i\";\n                        //# if (dt == vt) {\n                        Data[i] = index1_index2_elementFun(__i1__, __i2__);\n                        //# } else {\n                        Setter(Data, i, index1_index2_elementFun(__i1__, __i2__));\n                        //# }\n            //# });\n            return this;\n        }\n\n        //# }); }); // t2v, t1v\n        //# bools.ForEach(t1v => { var t1t = tnt(1, t1v); var t1i = tni(1, t1v); var t1i1 = tnin(1, t1v);\n        //# bools.ForEach(t2v => { var t2t = tnt(2, t2v); var t2i = tni(2, t2v); var t2i2 = tnin(2, t2v);\n        //# bools.ForEach(t3v => { var t3t = tnt(3, t3v); var t3i = tni(3, t3v); var t3i3 = tnin(3, t3v);\n        /// <summary>\n        /// Set the elements of a tensor to the result of a function of\n        /// corresponding triples of elements of the three supplied tensors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetMap3<__t1t__, __t2t__, __t3t__>(\n                __ttn__<__t1t__> t1, __ttn__<__t2t__> t2, __ttn__<__t3t__> t3,\n                Func<T1, T2, T3, __vtn__> element1_element2_element3_elementFun)\n        {\n            //# LoopN(\"\", false, dt == vt && !t1v && !t2v && !t3v, 4, 0, ix => {\n            //# var t1ix = ix ? t1i1 : t1i;\n            //# var t2ix = ix ? t2i2 : t2i;\n            //# var t3ix = ix ? t3i3 : t3i;\n            //# if (dt == vt) {\n            Data[i] = element1_element2_element3_elementFun(__t1ix__, __t2ix__, __t3ix__);\n            //# } else {\n            Setter(Data, i, element1_element2_element3_elementFun(__t1ix__, __t2ix__, __t3ix__));\n            //# }\n            //# });\n            return this;\n        }\n\n        /// <summary>\n        /// Set each element to the value of a function of the index of the\n        /// elements of the supplied __ttnl__. The function may access the\n        /// elements of the supplied __ttnl__ to compute the elements of the\n        /// __ttnl__.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetByIndex<__t1t__, __t2t__, __t3t__>(\n                __ttn__<__t1t__> t1, __ttn__<__t2t__> t2, __ttn__<__t3t__> t3,\n                Func<long, long, long, __vtn__> index1_index2_index3_elementFun)\n        {\n            //# LoopN(\"\", false, dt == vt && !t1v && !t2v && !t3v, 4, 0, ix => {\n                        //# var i1 = ix ? \"i1\" : \"i\";\n                        //# var i2 = ix ? \"i2\" : \"i\";\n                        //# var i3 = ix ? \"i3\" : \"i\";\n                        //# if (dt == vt) {\n                        Data[i] = index1_index2_index3_elementFun(__i1__, __i2__, __i3__);\n                        //# } else {\n                        Setter(Data, i, index1_index2_index3_elementFun(__i1__, __i2__, __i3__));\n                        //# }\n            //# });\n            return this;\n        }\n\n        //# }); }); }); // t3v, t2v, t1v\n        /// <summary>\n        /// Set the __ttnl__ to be the convolution of the supplied image and filter tensors.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> SetConvolution<Ti, Tf, Tm, Ts>(\n                __ttn__<Ti> image, __ttn__<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, __vtn__> castFun)\n        {\n            Info.CheckMatchingSize(new __ttn__Info(__itone__ + image.S - filter.S));\n            var r = this; r.F = image.F;\n            r.SetByCoord(c => castFun(image.Sub__ttn__(c, filter.Info.S)\n                                        .InnerProduct(filter, mulFun, bias, sumFun)));\n            return this;\n        }\n\n        //# if (d == 2) {\n        //# bools.ForEach(txv => { var txt = tdt(1, txv); var txi = tdi(1, txv); var txi1 = tdin(1, txv);\n        //# bools.ForEach(tyv => { var tyt = tdt(2, tyv); var tyi = tdi(2, tyv); var tyi2 = tdin(2, tyv);\n        /// <summary>\n        /// Set the matrix to be the outer product of the two supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetOuterProduct<__txt__, __tyt__>(\n                    __vectn__<__txt__> tx, __vectn__<__tyt__> ty,\n                    Func<Tx, Ty, __vtn__> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1)\n            {\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    //# if (dt != vt) {\n                    Setter(Data, i, fun(__txi1__, __tyi2__));\n                    //# } else {\n                    Data[i] = fun(__txi1__, __tyi2__);\n                    //# }\n                } }\n            }\n            else\n            {\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    //# if (dt != vt) {\n                    Setter(Data, i, fun(__txi1__, __tyi2__));\n                    //# } else {\n                    Data[i] = fun(__txi1__, __tyi2__);\n                    //# }\n                } }\n            }\n            return this;\n        }\n\n        //# }); });\n        //# } // d == 2\n        //# if (d == 3) {\n        //# bools.ForEach(txv => { var txt = tdt(1, txv); var txi = tdi(1, txv); var txi1 = tdin(1, txv);\n        //# bools.ForEach(tyv => { var tyt = tdt(2, tyv); var tyi = tdi(2, tyv); var tyi2 = tdin(2, tyv);\n        //# bools.ForEach(tzv => { var tzt = tdt(3, tzv); var tzi = tdi(3, tzv); var tzi3 = tdin(3, tzv);\n        /// <summary>\n        /// Set the volume to be the outer product of the three supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetOuterProduct<__txt__, __tyt__, __tzt__>(\n                    __vectn__<__txt__> tx, __vectn__<__tyt__> ty, __vectn__<__tzt__> tz,\n                    Func<Tx, Ty, Tz, __vtn__> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1)\n            {\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    //# if (dt != vt) {\n                    Setter(Data, i, fun(__txi1__, __tyi2__, __tzi3__));\n                    //# } else {\n                    Data[i] = fun(__txi1__, __tyi2__, __tzi3__);\n                    //# }\n                } } }\n            }\n            else\n            {\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    //# if (dt != vt) {\n                    Setter(Data, i, fun(__txi1__, __tyi2__, __tzi3__));\n                    //# } else {\n                    Data[i] = fun(__txi1__, __tyi2__, __tzi3__);\n                    //# }\n                } } }\n            }\n            return this;\n        }\n\n        //# }); }); });\n        //# } // d == 3\n        //# if (d == 4) {\n        //# bools.ForEach(txv => { var txt = tdt(1, txv); var txi = tdi(1, txv); var txi1 = tdin(1, txv);\n        //# bools.ForEach(tyv => { var tyt = tdt(2, tyv); var tyi = tdi(2, tyv); var tyi2 = tdin(2, tyv);\n        //# bools.ForEach(tzv => { var tzt = tdt(3, tzv); var tzi = tdi(3, tzv); var tzi3 = tdin(3, tzv);\n        //# bools.ForEach(twv => { var twt = tdt(4, twv); var twi = tdi(4, twv); var twi4 = tdin(4, twv);\n        /// <summary>\n        /// Set the four-dimensional tensor to be the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        /// <returns>this</returns>\n        public readonly __ttn__<__dvtn__> SetOuterProduct<__txt__, __tyt__, __tzt__, __twt__>(\n                    __vectn__<__txt__> tx, __vectn__<__tyt__> ty, __vectn__<__tzt__> tz, __vectn__<__twt__> tw,\n                    Func<Tx, Ty, Tz, Tw, __vtn__> fun)\n        {\n            long i = FirstIndex;\n            if (Info.JX == 1 && tx.Info.JX == 1 && ty.Info.JX == 1 && tz.Info.JX == 1 && tw.Info.JX == 1)\n            {\n                long ws = Info.DSW, wj = Info.JW;\n                long zs = Info.DSZ, zj = Info.JZ;\n                long ys = Info.DSY, yj = Info.JY;\n                long xs = Info.SX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4++) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3++) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2++) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i++, i1++) {\n                    //# if (dt != vt) {\n                    Setter(Data, i, fun(__txi1__, __tyi2__, __tzi3__, __twi4__));\n                    //# } else {\n                    Data[i] = fun(__txi1__, __tyi2__, __tzi3__, __twi4__);\n                    //# }\n                } } } }\n            }\n            else\n            {\n                long ws = Info.DSW, wj = Info.JW, j4 = tw.Info.JX;\n                long zs = Info.DSZ, zj = Info.JZ, j3 = tz.Info.JX;\n                long ys = Info.DSY, yj = Info.JY, j2 = ty.Info.JX;\n                long xs = Info.DSX, xj = Info.JX, j1 = tx.Info.JX;\n                for (long we = i + ws, i4 = tw.FirstIndex; i != we; i += wj, i4 += j4) {\n                for (long ze = i + zs, i3 = tz.FirstIndex; i != ze; i += zj, i3 += j3) {\n                for (long ye = i + ys, i2 = ty.FirstIndex; i != ye; i += yj, i2 += j2) {\n                for (long xe = i + xs, i1 = tx.FirstIndex; i != xe; i += xj, i1 += j1) {\n                    //# if (dt != vt) {\n                    Setter(Data, i, fun(__txi1__, __tyi2__, __tzi3__, __twi4__));\n                    //# } else {\n                    Data[i] = fun(__txi1__, __tyi2__, __tzi3__, __twi4__);\n                    //# }\n                } } } }\n            }\n            return this;\n        }\n\n        //# }); }); }); });\n        //# } // d == 4\n        #endregion\n\n        #region Scalar Methods and Functions\n\n        //# foreach (var hasBreak in new[] { false, true }) {\n        public readonly Tr Norm<Tr, Ti>(\n                Func<__vtn__, Ti> elementFun, Tr bias, Func<Tr, Ti, Tr> sumFun/*# if (hasBreak) { */, Func<Tr, bool> breakIfTrueFun/*# } */)\n        {\n            Tr result = bias;\n            //# Loop(\"\", false, () => {\n                    result = sumFun(result, elementFun(__t0i__));\n                    //# if (hasBreak) {\n                    if (breakIfTrueFun(result)) return result;\n                    //# }\n            //# }, false, false);\n            return result;\n        }\n\n        public readonly Tr Norm<Tr, Ti>(Func<__vtn__, /*# iaa.ForEach(a => {*/long/*# }, comma);*/, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun/*# if (hasBreak) { */, Func<Tr, bool> breakIfTrueFun/*# } */)\n        {\n            Tr result = bias;\n            //# Loop(\"\", false, () => {\n                    result = sumFun(result, elementFun(__t0i__, /*# iaa.ForEach(a => {*/__a__/*# }, comma);*/));\n                    //# if (hasBreak) {\n                    if (breakIfTrueFun(result)) return result;\n                    //# }\n            //# }, true, false);\n            return result;\n        }\n\n        //# if (d > 1) {\n        public readonly Tr Norm<Tr, Ti>(Func<__vtn__, __itn__, Ti> elementFun,\n                Tr bias, Func<Tr, Ti, Tr> sumFun/*# if (hasBreak) { */, Func<Tr, bool> breakIfTrueFun/*# } */)\n        {\n            Tr result = bias;\n            //# Loop(\"\", false, () => {\n                    result = sumFun(result, elementFun(__t0i__, v));\n                    //# if (hasBreak) {\n                    if (breakIfTrueFun(result)) return result;\n                    //# }\n            //# }, false, true);\n            return result;\n        }\n\n        //# }\n        //# bools.ForEach(t1v => { var t1t = tnt(1, t1v); var t1i = tni(1, t1v); var t1i1 = tnin(1, t1v);\n        public readonly Ts InnerProduct<__t1t__, Tm, Ts>(\n            __ttn__<__t1t__> t1,\n            Func<__vtn__, T1, Tm> mulFun, Ts bias, Func<Ts, Tm, Ts> sumFun/*# if (hasBreak) { */, Func<Ts, bool> breakIfTrueFun/*# } */)\n        {\n            Ts result = bias;\n            //# LoopN(\"\", false, dt == vt && !t1v, 2, 0, ix => { var t1ix = ix ? t1i1 : t1i;\n                        result = sumFun(result, mulFun(__t0i__, __t1ix__));\n                        //# if (hasBreak) {\n                        if (breakIfTrueFun(result)) return result;\n                        //# }\n            //# });\n            return result;\n        }\n\n        //# }); // t1v\n        //# } // hasBreak\n        #endregion\n\n        #region Creator Functions\n\n        //# bools.ForEach(t1v => {\n        /// <summary>\n        /// Create a new __ttnl__ as copy of the supplied __ttnl__.\n        /// </summary>\n        public static __ttn__<__dvtn__> Create/*# if (t1v) { */<T1d>/*# } */(\n                __ttn__</*# if (t1v) { */T1d, /*# } */__vtn__> t1)\n        {\n            return new __ttn__<__dvtn__>(t1.Info.Size).Set(t1);\n        }\n\n        //# }); // t1v\n        //# bools.ForEach(t1v => { var t1t = tnt(1, t1v);\n        /// <summary>\n        /// Create a new __ttnl__ by applying a function on each element of\n        /// the supplied __ttnl__.\n        /// </summary>\n        public static __ttn__<__dvtn__> Map<__t1t__>(\n                __ttn__<__t1t__> t1, Func<T1, __vtn__> element1_elementFun)\n        {\n            return new __ttn__<__dvtn__>(t1.Info.Size).SetMap(t1, element1_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new __ttnl__ by applying a function to each index of the\n        /// elements of the supplied __ttnl__. The function may access the\n        /// elements of the supplied __ttnl__ to compute the elements of the new\n        /// __ttnl__.\n        /// </summary>\n        public static __ttn__<__dvtn__> CreateByIndex<__t1t__>(\n                __ttn__<__t1t__> t1, Func<long, __vtn__> index1_elementFun)\n        {\n            return new __ttn__<__dvtn__>(t1.Info.Size).SetByIndex(t1, index1_elementFun);\n        }\n\n        //# }); // t1v\n        //# bools.ForEach(t1v => { var t1t = tnt(1, t1v);\n        //# bools.ForEach(t2v => { var t2t = tnt(2, t2v);\n        /// <summary>\n        /// Create a new __ttnl__ by applying a function on each element of\n        /// the supplied __ttnl__.\n        /// </summary>\n        public static __ttn__<__dvtn__> Map2<__t1t__, __t2t__>(\n                __ttn__<__t1t__> t1, __ttn__<__t2t__> t2,\n                Func<T1, T2, __vtn__> element1_element2_elementFun)\n        {\n            return new __ttn__<__dvtn__>(t1.Info.Size).SetMap2(t1, t2, element1_element2_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new __ttnl__ by applying a function to each index of the\n        /// elements of the supplied __ttnl__. The function may access the\n        /// elements of the supplied __ttnl__ to compute the elements of the new\n        /// __ttnl__.\n        /// </summary>\n        public static __ttn__<__dvtn__> CreateByIndex<__t1t__, __t2t__>(\n                __ttn__<__t1t__> t1, __ttn__<__t2t__> t2,\n                Func<long, long, __vtn__> index1_index2_fun)\n        {\n            return new __ttn__<__dvtn__>(t1.Info.Size).SetByIndex(t1, t2, index1_index2_fun);\n        }\n\n        //# }); }); // t2v, t1v\n        //# bools.ForEach(t1v => { var t1t = tnt(1, t1v);\n        //# bools.ForEach(t2v => { var t2t = tnt(2, t2v);\n        //# bools.ForEach(t3v => { var t3t = tnt(3, t3v);\n        /// <summary>\n        /// Create a new __ttnl__ by applying a function on each element of\n        /// the supplied __ttnl__.\n        /// </summary>\n        public static __ttn__<__dvtn__> Map3<__t1t__, __t2t__, __t3t__>(\n                __ttn__<__t1t__> t1, __ttn__<__t2t__> t2, __ttn__<__t3t__> t3,\n                Func<T1, T2, T3, __vtn__> element1_element2_element3_elementFun)\n        {\n            return new __ttn__<__dvtn__>(t1.Info.Size).SetMap3(t1, t2, t3, element1_element2_element3_elementFun);\n        }\n\n        /// <summary>\n        /// Create a new __ttnl__ by applying a function to each index of the\n        /// elements of the supplied __ttnl__. The function may access the\n        /// elements of the supplied __ttnl__ to compute the elements of the new\n        /// __ttnl__.\n        /// </summary>\n        public static __ttn__<__dvtn__> CreateByIndex<__t1t__, __t2t__, __t3t__>(\n                __ttn__<__t1t__> t1, __ttn__<__t2t__> t2, __ttn__<__t3t__> t3,\n                Func<long, long, long, __vtn__> index1_index2_index3_elementFun)\n        {\n            return new __ttn__<__dvtn__>(t1.Info.Size).SetByIndex(t1, t2, t3, index1_index2_index3_elementFun);\n        }\n\n        //# }); }); }); // t3v, t2v, t1v\n        /// <summary>\n        /// Create a new __ttnl__ by applying a function to the coordinates of\n        /// the elements the newly created __ttnl__.\n        /// </summary>\n        public static __ttn__<__dvtn__> Create(__itn__ size, Func<__itn__, __vtn__> fun)\n        {\n            return new __ttn__<__dvtn__>(size).SetByCoord(fun);\n        }\n\n        /// <summary>\n        /// Create a new __ttn__ by convolving the image with the filter. The mulFun\n        /// is used to combine single elements of the image with the filter. The result\n        /// is summed up using the sumFun starting with bias. The complete sum is put\n        /// through the castFun and put into the resulting __ttn__.\n        /// </summary>\n        public static __ttn__<__dvtn__> CreateConvolution<Ti, Tf, Tm, Ts>(\n                __ttn__<Ti> image, __ttn__<Tf> filter, Func<Ti, Tf, Tm> mulFun,\n                Ts bias, Func<Ts, Tm, Ts> sumFun, Func<Ts, __vtn__> castFun)\n        {\n            __itn__ size = 1 + image.S - filter.S;\n            if (/*# r1ifa.ForEach(f => { */size.__f__ <= 0 ||/*# });*/size/*# if (d > 1) {*/.X/*# }*/ <= 0) throw new Exception(\"filter to large\");\n            return new __ttn__<__dvtn__>(size)\n                    .SetConvolution(image, filter, mulFun, bias, sumFun, castFun);\n        }\n\n        //# if (d == 2) {\n        //# bools.ForEach(txv => { var txt = tdt(1, txv);\n        //# bools.ForEach(tyv => { var tyt = tdt(2, tyv);\n        /// <summary>\n        /// Create a new matrix as the outer product of the two supplied vectors.\n        /// </summary>\n        public static __ttn__<__dvtn__> CreateOuterProduct<__txt__, __tyt__>(\n                    __vectn__<__txt__> tx, __vectn__<__tyt__> ty,\n                    Func<Tx, Ty, __vtn__> fun)\n        {\n            return new __ttn__<__dvtn__>(new V2l(tx.S, ty.S))\n                            { FX = tx.F, FY = ty.F }\n                            .SetOuterProduct<__txt__, __tyt__>(tx, ty, fun);\n        }\n\n        //# }); });\n        //# } // d == 2\n        //# if (d == 3) {\n        //# bools.ForEach(txv => { var txt = tdt(1, txv);\n        //# bools.ForEach(tyv => { var tyt = tdt(2, tyv);\n        //# bools.ForEach(tzv => { var tzt = tdt(3, tzv);\n        /// <summary>\n        /// Create a new volume as the outer product of the three supplied vectors.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> CreateOuterProduct<__txt__, __tyt__, __tzt__>(\n                    __vectn__<__txt__> tx, __vectn__<__tyt__> ty, __vectn__<__tzt__> tz,\n                    Func<Tx, Ty, Tz, __vtn__> fun)\n        {\n            return new __ttn__<__dvtn__>(new V3l(tx.S, ty.S, tz.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F }\n                            .SetOuterProduct<__txt__, __tyt__, __tzt__>(tx, ty, tz, fun);\n        }\n\n        //# }); }); });\n        //# } // d == 3\n        //# if (d == 4) {\n        //# bools.ForEach(txv => { var txt = tdt(1, txv);\n        //# bools.ForEach(tyv => { var tyt = tdt(2, tyv);\n        //# bools.ForEach(tzv => { var tzt = tdt(3, tzv);\n        //# bools.ForEach(twv => { var twt = tdt(4, twv);\n        /// <summary>\n        /// Create a new four-dimensional tensor as the outer product of the\n        /// four supplied vectors.\n        /// </summary>\n        public readonly __ttn__<__dvtn__> CreateOuterProduct<__txt__, __tyt__, __tzt__, __twt__>(\n                    __vectn__<__txt__> tx, __vectn__<__tyt__> ty, __vectn__<__tzt__> tz, __vectn__<__twt__> tw,\n                    Func<Tx, Ty, Tz, Tw, __vtn__> fun)\n        {\n            return new __ttn__<__dvtn__>(new V4l(tx.S, ty.S, tz.S, tw.S))\n                            { FX = tx.F, FY = ty.F, FZ = tz.F, FW = tw.F }\n                            .SetOuterProduct<__txt__, __tyt__, __tzt__, __twt__>(tx, ty, tz, tw, fun);\n        }\n\n        //# }); }); }); });\n        //# } // d == 4\n        #endregion\n\n        #region Sampling\n\n        //# if (d == 1) {\n        /// <summary>\n        /// Sample the vector using 2 samples and the supplied\n        /// interpolation function. If an integer coordinte is\n        /// supplied the returned value is the same as the indexer\n        /// of the vector. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw2<TRes>(\n                double x,\n                Func<double, __vtn__, __vtn__, TRes> ipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; long d = Info.Delta;\n            long i = Info.Origin + xi * d;\n            //# if (dt == vt) {\n            return ipl(x - xid, Data[i], Data[i + d]);\n            //# } else {\n            return ipl(x - xid, Getter(Data, i), Getter(Data, i + d));\n            //# }\n        }\n\n        public readonly TRes Sample2Clamped<TRes>(\n                double x,\n                Func<double, __vtn__, __vtn__, TRes> ipl)\n        {\n            return Sample2(x, ipl, Tensor.Index2SamplesClamped);\n        }\n\n        /// <summary>\n        /// Sample the vector using 2 samples and the supplied\n        /// interpolation function. If an integer coordinte is\n        /// supplied the returned value is the same as the indexer\n        /// of the vector.\n        /// </summary>\n        public readonly TRes Sample2<TRes>(\n                double x,\n                Func<double, __vtn__, __vtn__, TRes> ipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            long i = Info.Origin + xi * d1;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            //# if (dt == vt) {\n            return ipl(xf, Data[i + d.E0], Data[i + d.E1]);\n            //# } else {\n            return ipl(xf, Getter(Data, i + d.E0), Getter(Data, i + d.E1));\n            //# }\n        }\n\n        public readonly TRes SampleRaw4<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, TRes> smp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d = Info.Delta;\n            long i1 = Info.Origin + xi * d, i2 = i1 + d;\n            var w = ipl(xf);\n            //# if (dt == vt) {\n            return smp(Data[i1 - d], Data[i1], Data[i2], Data[i2 + d], ref w);\n            //# } else {\n            return smp(Getter(Data, i1 - d), Getter(Data, i1), Getter(Data, i2), Getter(Data, i2 + d), ref w);\n            //# }\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, TRes> smp)\n        {\n            return Sample4(x, ipl, smp, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample4<T1, TRes>(\n                double x,\n                Func<double, Tup4<T1>> ipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, TRes> smp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            long i = Info.Origin + xi * d1;\n            var w = ipl(xf);\n            //# if (dt == vt) {\n            return smp(Data[i + d.E0], Data[i + d.E1], Data[i + d.E2], Data[i + d.E3], ref w);\n            //# } else {\n            return smp(Getter(Data, i + d.E0), Getter(Data, i + d.E1), Getter(Data, i + d.E2), Getter(Data, i + d.E3), ref w);\n            //# }\n        }\n\n        public readonly TRes SampleRaw6<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, TRes> smp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d = Info.Delta;\n            long i2 = Info.Origin + xi * d, i1 = i2 - d, i3 = i2 + d, i4 = i3 + d;\n            var w = ipl(xf);\n            //# if (dt == vt) {\n            return smp(Data[i1 - d], Data[i1], Data[i2], Data[i3], Data[i4], Data[i4 + d], ref w);\n            //# } else {\n            return smp(Getter(Data, i1 - d), Getter(Data, i1), Getter(Data, i2), Getter(Data, i3), Getter(Data, i4), Getter(Data, i4 + d), ref w);\n            //# }\n        }\n\n        public readonly TRes Sample6Clamped<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, TRes> smp)\n        {\n            return Sample6(x, ipl, smp, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample6<T1, TRes>(\n                double x,\n                Func<double, Tup6<T1>> ipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, TRes> smp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_indexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long d1 = Info.Delta;\n            var d = index_min_max_delta_indexFun(xi, FX, EX, d1);\n            long i = Info.Origin + xi * d1;\n            var w = ipl(xf);\n            //# if (dt == vt) {\n            return smp(Data[i + d.E0], Data[i + d.E1], Data[i + d.E2], Data[i + d.E3], Data[i + d.E4], Data[i + d.E5], ref w);\n            //# } else {\n            return smp(Getter(Data, i + d.E0), Getter(Data, i + d.E1), Getter(Data, i + d.E2), Getter(Data, i + d.E3), Getter(Data, i + d.E4), Getter(Data, i + d.E5), ref w);\n            //# }\n        }\n\n        //# }\n        //# if (d == 2) {\n        public readonly TRes SampleRaw4<T1, TRes>(\n                V2d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return SampleRaw4(v.X, v.Y, xipl, yipl);\n        }\n\n        /// <summary>\n        /// Sample the matrix using 4 samples and the supplied\n        /// interpolation function. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the matrix, i.e. pixel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw4<T1, TRes>(\n                double x, double y,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long i0 = Info.Origin + xi * dx + yi * dy, i1 = i0 + dy;\n            //# if (dt == vt) {\n            return yipl(yf, xipl(xf, Data[i0], Data[i0 + dx]),\n                            xipl(xf, Data[i1], Data[i1 + dx]));\n            //# } else {\n            return yipl(yf, xipl(xf, Getter(Data, i0), Getter(Data, i0 + dx)),\n                            xipl(xf, Getter(Data, i1), Getter(Data, i1 + dx)));\n            //# }\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                V2d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return Sample4(v.X, v.Y, xipl, yipl,\n                           Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample4Clamped<T1, TRes>(\n                double x, double y,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            return Sample4(x, y, xipl, yipl,\n                           Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample4<T1, TRes>(\n                V2d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, TRes> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample4(v.X, v.Y, xipl, yipl,\n                           index_min_max_delta_xIndexFun,\n                           index_min_max_delta_yIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the matrix using 4 samples and the supplied\n        /// interpolation functions., If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the matrix, i.e. pixel centers are assumed to be on\n        /// integer coordinates.\n        /// </summary>\n        public readonly TRes Sample4<T1, TRes>(\n                double x, double y,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, TRes> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            //# if (dt == vt) {\n            return yipl(yf, xipl(xf, Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0]),\n                            xipl(xf, Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1]));\n            //# } else {\n            return yipl(yf, xipl(xf, Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0)),\n                            xipl(xf, Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1)));\n            //# }\n        }\n\n        //# foreach (var clampFun in new[] { false, true }) {\n        public readonly void SetScaled4<T1/*# if (clampFun) { */, T2/*# } */>(Matrix<__dvtn__> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1/*# if (clampFun) { */, T2/*# }\n                                                         else { */, __vtn__/*# } */> yipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun/*#\n                if (clampFun) { */,\n                Func<T2, __vtn__> clampFun/*# } */)\n        {\n            var dxa = new Tup2<long>[SX];\n            var xfa = new double[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi;\n                dxa[tix] = dx; xfa[tix] = xf;\n            }\n            var dya = new Tup2<long>[SY];\n            var yfa = new double[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi;\n                dya[tiy] = dy; yfa[tiy] = yf;\n            }\n            var data = Data;\n            //# Loop(\"\", false, () => {\n                //# if (dt == vt) {\n                    //# if (clampFun) {\n                    data[i] = clampFun(sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl));\n                    //# } else {\n                    data[i] = sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl);\n                    //# }\n                //# } else {\n                    //# if (clampFun) {\n                    Setter(data, i, clampFun(sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl)));\n                    //# } else {\n                    Setter(data, i, sourceMat.Sample4(dxa[x], dya[y], xfa[x], yfa[y], xipl, yipl));\n                    //# }\n                //# }\n            //# }, true, false);\n        }\n\n        //# } // clampFun\n        public readonly TRes Sample4<T1, TRes>(\n                Tup2<long> dx, Tup2<long> dy, double xf, double yf,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, TRes> yipl)\n        {\n            //# if (dt == vt) {\n            return yipl(yf, xipl(xf, Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0]),\n                            xipl(xf, Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1]));\n            //# } else {\n            return yipl(yf, xipl(xf, Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0)),\n                            xipl(xf, Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1)));\n            //# }\n        }\n\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return SampleRaw16(v.X, v.Y, xipl, yipl, xsmp, ysmp);\n        }\n\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long d2 = dx + dx;\n            long i1 = Info.Origin + xi * dx + yi * dy, i0 = i1 - dy, i2 = i1 + dy, i3 = i2 + dy;\n            var wx = xipl(xf); var wy = yipl(yf);\n            //# if (dt == vt) {\n            return ysmp(xsmp(Data[i0 - dx], Data[i0], Data[i0 + dx], Data[i0 + d2], ref wx),\n                        xsmp(Data[i1 - dx], Data[i1], Data[i1 + dx], Data[i1 + d2], ref wx),\n                        xsmp(Data[i2 - dx], Data[i2], Data[i2 + dx], Data[i2 + d2], ref wx),\n                        xsmp(Data[i3 - dx], Data[i3], Data[i3 + dx], Data[i3 + d2], ref wx), ref wy);\n            //# } else {\n            return ysmp(xsmp(Getter(Data, i0 - dx), Getter(Data, i0), Getter(Data, i0 + dx), Getter(Data, i0 + d2), ref wx),\n                        xsmp(Getter(Data, i1 - dx), Getter(Data, i1), Getter(Data, i1 + dx), Getter(Data, i1 + d2), ref wx),\n                        xsmp(Getter(Data, i2 - dx), Getter(Data, i2), Getter(Data, i2 + dx), Getter(Data, i2 + d2), ref wx),\n                        xsmp(Getter(Data, i3 - dx), Getter(Data, i3), Getter(Data, i3 + dx), Getter(Data, i3 + d2), ref wx), ref wy);\n            //# }\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return Sample16(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            return Sample16(x, y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample16(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            var wx = xipl(xf); var wy = yipl(yf);\n            //# if (dt == vt) {\n            return ysmp(xsmp(Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0], Data[dx.E2 + dy.E0], Data[dx.E3 + dy.E0], ref wx),\n                        xsmp(Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1], Data[dx.E2 + dy.E1], Data[dx.E3 + dy.E1], ref wx),\n                        xsmp(Data[dx.E0 + dy.E2], Data[dx.E1 + dy.E2], Data[dx.E2 + dy.E2], Data[dx.E3 + dy.E2], ref wx),\n                        xsmp(Data[dx.E0 + dy.E3], Data[dx.E1 + dy.E3], Data[dx.E2 + dy.E3], Data[dx.E3 + dy.E3], ref wx), ref wy);\n            //# } else {\n            return ysmp(xsmp(Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0), Getter(Data, dx.E2 + dy.E0), Getter(Data, dx.E3 + dy.E0), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1), Getter(Data, dx.E2 + dy.E1), Getter(Data, dx.E3 + dy.E1), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E2), Getter(Data, dx.E1 + dy.E2), Getter(Data, dx.E2 + dy.E2), Getter(Data, dx.E3 + dy.E2), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E3), Getter(Data, dx.E1 + dy.E3), Getter(Data, dx.E2 + dy.E3), Getter(Data, dx.E3 + dy.E3), ref wx), ref wy);\n            //# }\n        }\n\n        //# foreach (var clampFun in new[] { false, true }) {\n        public readonly void SetScaled16<T1,T2, T3/*# if (clampFun) { */, T4/*# } */>(Matrix<__dvtn__> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>/*# if (clampFun) { */, T4/*# }\n                                                         else { */, __vtn__/*# } */> ysmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun/*#\n                if (clampFun) { */,\n                Func<T4, __vtn__> clampFun/*# } */)\n        {\n            var dxa = new Tup4<long>[SX];\n            var wxa = new Tup4<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi; dx.E3 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup4<long>[SY];\n            var wya = new Tup4<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi; dy.E3 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            //# Loop(\"\", false, () => {\n                //# if (dt == vt) {\n                //# if (clampFun) {\n                    data[i] = clampFun(sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                //# } else {\n                    data[i] = sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp);\n                //# }\n                //# } else {\n                //# if (clampFun) {\n                    Setter(data, i, clampFun(sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp)));\n                //# } else {\n                    Setter(data, i, sourceMat.Sample16(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                //# }\n                //# }\n            //# }, true, false);\n        }\n\n        //# } // clampFun\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                Tup4<long> dx, Tup4<long> dy, Tup4<T1> wx, Tup4<T2> wy,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, Tup4<T2>, TRes> ysmp)\n        {\n            //# if (dt == vt) {\n            return ysmp(xsmp(Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0], Data[dx.E2 + dy.E0], Data[dx.E3 + dy.E0], ref wx),\n                        xsmp(Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1], Data[dx.E2 + dy.E1], Data[dx.E3 + dy.E1], ref wx),\n                        xsmp(Data[dx.E0 + dy.E2], Data[dx.E1 + dy.E2], Data[dx.E2 + dy.E2], Data[dx.E3 + dy.E2], ref wx),\n                        xsmp(Data[dx.E0 + dy.E3], Data[dx.E1 + dy.E3], Data[dx.E2 + dy.E3], Data[dx.E3 + dy.E3], ref wx), ref wy);\n            //# } else {\n            return ysmp(xsmp(Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0), Getter(Data, dx.E2 + dy.E0), Getter(Data, dx.E3 + dy.E0), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1), Getter(Data, dx.E2 + dy.E1), Getter(Data, dx.E3 + dy.E1), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E2), Getter(Data, dx.E1 + dy.E2), Getter(Data, dx.E2 + dy.E2), Getter(Data, dx.E3 + dy.E2), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E3), Getter(Data, dx.E1 + dy.E3), Getter(Data, dx.E2 + dy.E3), Getter(Data, dx.E3 + dy.E3), ref wx), ref wy);\n            //# }\n        }\n\n        public readonly TRes SampleRaw36<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return SampleRaw36(v.X, v.Y, xipl, yipl, xsmp, ysmp);\n        }\n\n        public readonly TRes SampleRaw36<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            long i2 = Info.Origin + xi * dx + yi * dy;\n            long i1 = i2 - dy, i0 = i1 - dy, i3 = i2 + dy, i4 = i3 + dy, i5 = i4 + dy;\n            long d2 = dx + dx, d3 = d2 + dx;\n            var wx = xipl(xf); var wy = yipl(yf);\n            //# if (dt == vt) {\n            return ysmp(xsmp(Data[i0 - d2], Data[i0 - dx], Data[i0], Data[i0 + dx], Data[i0 + d2], Data[i0 + d3], ref wx),\n                        xsmp(Data[i1 - d2], Data[i1 - dx], Data[i1], Data[i1 + dx], Data[i1 + d2], Data[i1 + d3], ref wx),\n                        xsmp(Data[i2 - d2], Data[i2 - dx], Data[i2], Data[i2 + dx], Data[i2 + d2], Data[i2 + d3], ref wx),\n                        xsmp(Data[i3 - d2], Data[i3 - dx], Data[i3], Data[i3 + dx], Data[i3 + d2], Data[i3 + d3], ref wx),\n                        xsmp(Data[i4 - d2], Data[i4 - dx], Data[i4], Data[i4 + dx], Data[i4 + d2], Data[i4 + d3], ref wx),\n                        xsmp(Data[i5 - d2], Data[i5 - dx], Data[i5], Data[i5 + dx], Data[i5 + d2], Data[i5 + d3], ref wx), ref wy);\n            //# } else {\n            return ysmp(xsmp(Getter(Data, i0 - d2), Getter(Data, i0 - dx), Getter(Data, i0), Getter(Data, i0 + dx), Getter(Data, i0 + d2), Getter(Data, i0 + d3), ref wx),\n                        xsmp(Getter(Data, i1 - d2), Getter(Data, i1 - dx), Getter(Data, i1), Getter(Data, i1 + dx), Getter(Data, i1 + d2), Getter(Data, i1 + d3), ref wx),\n                        xsmp(Getter(Data, i2 - d2), Getter(Data, i2 - dx), Getter(Data, i2), Getter(Data, i2 + dx), Getter(Data, i2 + d2), Getter(Data, i2 + d3), ref wx),\n                        xsmp(Getter(Data, i3 - d2), Getter(Data, i3 - dx), Getter(Data, i3), Getter(Data, i3 + dx), Getter(Data, i3 + d2), Getter(Data, i3 + d3), ref wx),\n                        xsmp(Getter(Data, i4 - d2), Getter(Data, i4 - dx), Getter(Data, i4), Getter(Data, i4 + dx), Getter(Data, i4 + d2), Getter(Data, i4 + d3), ref wx),\n                        xsmp(Getter(Data, i5 - d2), Getter(Data, i5 - dx), Getter(Data, i5), Getter(Data, i5 + dx), Getter(Data, i5 + d2), Getter(Data, i5 + d3), ref wx), ref wy);\n            //# }\n        }\n\n        public readonly TRes Sample36Clamped<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return Sample36(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample36Clamped<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            return Sample36(x, y, xipl, yipl, xsmp, ysmp,\n                            Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped);\n        }\n\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                V2d v,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun)\n        {\n            return Sample36(v.X, v.Y, xipl, yipl, xsmp, ysmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun);\n        }\n\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                double x, double y,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            long i = Info.Origin + xi * dx1 + yi * dy1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i; dx.E4 += i; dx.E5 += i;\n            var dy = index_min_max_delta_yIndexFun(yi, FY, EY, dy1);\n            var wx = xipl(xf); var wy = yipl(yf);\n            //# if (dt == vt) {\n            return ysmp(xsmp(Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0], Data[dx.E2 + dy.E0], Data[dx.E3 + dy.E0], Data[dx.E4 + dy.E0], Data[dx.E5 + dy.E0], ref wx),\n                        xsmp(Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1], Data[dx.E2 + dy.E1], Data[dx.E3 + dy.E1], Data[dx.E4 + dy.E1], Data[dx.E5 + dy.E1], ref wx),\n                        xsmp(Data[dx.E0 + dy.E2], Data[dx.E1 + dy.E2], Data[dx.E2 + dy.E2], Data[dx.E3 + dy.E2], Data[dx.E4 + dy.E2], Data[dx.E5 + dy.E2], ref wx),\n                        xsmp(Data[dx.E0 + dy.E3], Data[dx.E1 + dy.E3], Data[dx.E2 + dy.E3], Data[dx.E3 + dy.E3], Data[dx.E4 + dy.E3], Data[dx.E5 + dy.E3], ref wx),\n                        xsmp(Data[dx.E0 + dy.E4], Data[dx.E1 + dy.E4], Data[dx.E2 + dy.E4], Data[dx.E3 + dy.E4], Data[dx.E4 + dy.E4], Data[dx.E5 + dy.E4], ref wx),\n                        xsmp(Data[dx.E0 + dy.E5], Data[dx.E1 + dy.E5], Data[dx.E2 + dy.E5], Data[dx.E3 + dy.E5], Data[dx.E4 + dy.E5], Data[dx.E5 + dy.E5], ref wx), ref wy);\n            //# } else {\n            return ysmp(xsmp(Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0), Getter(Data, dx.E2 + dy.E0), Getter(Data, dx.E3 + dy.E0), Getter(Data, dx.E4 + dy.E0), Getter(Data, dx.E5 + dy.E0), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1), Getter(Data, dx.E2 + dy.E1), Getter(Data, dx.E3 + dy.E1), Getter(Data, dx.E4 + dy.E1), Getter(Data, dx.E5 + dy.E1), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E2), Getter(Data, dx.E1 + dy.E2), Getter(Data, dx.E2 + dy.E2), Getter(Data, dx.E3 + dy.E2), Getter(Data, dx.E4 + dy.E2), Getter(Data, dx.E5 + dy.E2), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E3), Getter(Data, dx.E1 + dy.E3), Getter(Data, dx.E2 + dy.E3), Getter(Data, dx.E3 + dy.E3), Getter(Data, dx.E4 + dy.E3), Getter(Data, dx.E5 + dy.E3), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E4), Getter(Data, dx.E1 + dy.E4), Getter(Data, dx.E2 + dy.E4), Getter(Data, dx.E3 + dy.E4), Getter(Data, dx.E4 + dy.E4), Getter(Data, dx.E5 + dy.E4), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E5), Getter(Data, dx.E1 + dy.E5), Getter(Data, dx.E2 + dy.E5), Getter(Data, dx.E3 + dy.E5), Getter(Data, dx.E4 + dy.E5), Getter(Data, dx.E5 + dy.E5), ref wx), ref wy);\n            //# }\n        }\n\n        //# foreach (var clampFun in new[] { false, true }) {\n        public readonly void SetScaled36<T1, T2, T3/*# if (clampFun) { */, T4/*# } */>(Matrix<__dvtn__> sourceMat,\n                double xScale, double yScale, double xShift, double yShift,\n                Func<double, Tup6<T1>> xipl,\n                Func<double, Tup6<T2>> yipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>/*# if (clampFun) { */, T4/*# }\n                                                         else { */, __vtn__/*# } */> ysmp,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup6<long>> index_min_max_delta_yIndexFun/*#\n                if (clampFun) { */,\n                Func<T4, __vtn__> clampFun/*# } */)\n        {\n            var dxa = new Tup6<long>[SX];\n            var wxa = new Tup6<T1>[SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            for (long tix = 0, tsx = SX; tix < tsx; tix++, xShift += xScale)\n            {\n                double xid = Fun.Floor(xShift); long xi = (long)xid; double xf = xShift - xid;\n                var dx = index_min_max_delta_xIndexFun(xi, fx, ex, dx1);\n                var dxi = xi * dx1;\n                dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi;\n                dx.E3 += dxi; dx.E4 += dxi; dx.E5 += dxi;\n                dxa[tix] = dx; wxa[tix] = xipl(xf);\n            }\n            var dya = new Tup6<long>[SY];\n            var wya = new Tup6<T2>[SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            for (long tiy = 0, tsy = SY; tiy < tsy; tiy++, yShift += yScale)\n            {\n                double yid = Fun.Floor(yShift); long yi = (long)yid; double yf = yShift - yid;\n                var dy = index_min_max_delta_yIndexFun(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1;\n                dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi;\n                dy.E3 += dyi; dy.E4 += dyi; dy.E5 += dyi;\n                dya[tiy] = dy; wya[tiy] = yipl(yf);\n            }\n            var data = Data;\n            //# Loop(\"\", false, () => {\n                //# if (dt == vt) {\n                //# if (clampFun) {\n                    data[i] = clampFun(sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                //# } else {\n                    data[i] = sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp);\n                //# }\n                //# } else {\n                //# if (clampFun) {\n                    Setter(data, i, clampFun(sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp)));\n                //# } else {\n                    Setter(data, i, sourceMat.Sample36(dxa[x], dya[y], wxa[x], wya[y], xsmp, ysmp));\n                //# }\n                //# }\n            //# }, true, false);\n        }\n\n        //# } // clampFun\n        public readonly TRes Sample36<T1, T2, T3, TRes>(\n                Tup6<long> dx, Tup6<long> dy, Tup6<T1> wx, Tup6<T2> wy,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, __vtn__, __vtn__, Tup6<T1>, T3> xsmp,\n                FuncRef1<T3, T3, T3, T3, T3, T3, Tup6<T2>, TRes> ysmp)\n        {\n            //# if (dt == vt) {\n            return ysmp(xsmp(Data[dx.E0 + dy.E0], Data[dx.E1 + dy.E0], Data[dx.E2 + dy.E0], Data[dx.E3 + dy.E0], Data[dx.E4 + dy.E0], Data[dx.E5 + dy.E0], ref wx),\n                        xsmp(Data[dx.E0 + dy.E1], Data[dx.E1 + dy.E1], Data[dx.E2 + dy.E1], Data[dx.E3 + dy.E1], Data[dx.E4 + dy.E1], Data[dx.E5 + dy.E1], ref wx),\n                        xsmp(Data[dx.E0 + dy.E2], Data[dx.E1 + dy.E2], Data[dx.E2 + dy.E2], Data[dx.E3 + dy.E2], Data[dx.E4 + dy.E2], Data[dx.E5 + dy.E2], ref wx),\n                        xsmp(Data[dx.E0 + dy.E3], Data[dx.E1 + dy.E3], Data[dx.E2 + dy.E3], Data[dx.E3 + dy.E3], Data[dx.E4 + dy.E3], Data[dx.E5 + dy.E3], ref wx),\n                        xsmp(Data[dx.E0 + dy.E4], Data[dx.E1 + dy.E4], Data[dx.E2 + dy.E4], Data[dx.E3 + dy.E4], Data[dx.E4 + dy.E4], Data[dx.E5 + dy.E4], ref wx),\n                        xsmp(Data[dx.E0 + dy.E5], Data[dx.E1 + dy.E5], Data[dx.E2 + dy.E5], Data[dx.E3 + dy.E5], Data[dx.E4 + dy.E5], Data[dx.E5 + dy.E5], ref wx), ref wy);\n            //# } else {\n            return ysmp(xsmp(Getter(Data, dx.E0 + dy.E0), Getter(Data, dx.E1 + dy.E0), Getter(Data, dx.E2 + dy.E0), Getter(Data, dx.E3 + dy.E0), Getter(Data, dx.E4 + dy.E0), Getter(Data, dx.E5 + dy.E0), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E1), Getter(Data, dx.E1 + dy.E1), Getter(Data, dx.E2 + dy.E1), Getter(Data, dx.E3 + dy.E1), Getter(Data, dx.E4 + dy.E1), Getter(Data, dx.E5 + dy.E1), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E2), Getter(Data, dx.E1 + dy.E2), Getter(Data, dx.E2 + dy.E2), Getter(Data, dx.E3 + dy.E2), Getter(Data, dx.E4 + dy.E2), Getter(Data, dx.E5 + dy.E2), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E3), Getter(Data, dx.E1 + dy.E3), Getter(Data, dx.E2 + dy.E3), Getter(Data, dx.E3 + dy.E3), Getter(Data, dx.E4 + dy.E3), Getter(Data, dx.E5 + dy.E3), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E4), Getter(Data, dx.E1 + dy.E4), Getter(Data, dx.E2 + dy.E4), Getter(Data, dx.E3 + dy.E4), Getter(Data, dx.E4 + dy.E4), Getter(Data, dx.E5 + dy.E4), ref wx),\n                        xsmp(Getter(Data, dx.E0 + dy.E5), Getter(Data, dx.E1 + dy.E5), Getter(Data, dx.E2 + dy.E5), Getter(Data, dx.E3 + dy.E5), Getter(Data, dx.E4 + dy.E5), Getter(Data, dx.E5 + dy.E5), ref wx), ref wy);\n            //# }\n        }\n        //# } // d == 2\n        //# if (d == 3) {\n\n\n        public readonly TRes SampleRaw8<T1, T2, TRes>(\n                V3d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return SampleRaw8(v.X, v.Y, v.Z, xipl, yipl, zipl);\n        }\n\n        /// <summary>\n        /// Sample the volume using 8 samples and the supplied\n        /// interpolation functions. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the volume, i.e. voxel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw8<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            long i = Info.Origin + xi * Info.Delta.X + yi * Info.Delta.Y + zi * Info.Delta.Z;\n            long ix = i + dx; long iy = i + dy; long ixy = ix + dy;\n            //# if (dt == vt) {\n            return zipl(zf, yipl(yf, xipl(xf, Data[i], Data[ix]),\n                                     xipl(xf, Data[iy], Data[ixy])),\n                            yipl(yf, xipl(xf, Data[i + dz], Data[ix + dz]),\n                                     xipl(xf, Data[iy + dz], Data[ixy + dz])));\n            //# } else {\n            return zipl(zf, yipl(yf, xipl(xf, Getter(Data, i), Getter(Data, ix)),\n                                     xipl(xf, Getter(Data, iy), Getter(Data, ixy))),\n                            yipl(yf, xipl(xf, Getter(Data, i + dz), Getter(Data, ix + dz)),\n                                     xipl(xf, Getter(Data, iy + dz), Getter(Data, ixy + dz))));\n            //# }\n        }\n\n        public readonly TRes Sample8Clamped<T1, T2, TRes>(\n                V3d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return Sample8(v.X, v.Y, v.Z, xipl, yipl, zipl,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample8Clamped<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl)\n        {\n            return Sample8(x, y, z, xipl, yipl, zipl,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped,\n                           Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample8<T1, T2, TRes>(\n                V3d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun)\n        {\n            return Sample8(v.X, v.Y, v.Z, xipl, yipl, zipl,\n                           index_min_max_delta_xIndexFun,\n                           index_min_max_delta_yIndexFun,\n                           index_min_max_delta_zIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the volume using 8 samples and the supplied\n        /// interpolation functions. If only integer coordintes are\n        /// supplied the returned value is the same as the indexer\n        /// of the volume, i.e. voxel centers are assumed to be on\n        /// integer coordinates.\n        /// </summary>\n        public readonly TRes Sample8<T1, T2, TRes>(\n                double x, double y, double z,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, TRes> zipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1); dx.E0 += i; dx.E1 += i;\n            var dyz = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                   index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1));\n            //# if (dt == vt) {\n            return zipl(zf, yipl(yf, xipl(xf, Data[dx.E0 + dyz.E0], Data[dx.E1 + dyz.E0]),\n                                     xipl(xf, Data[dx.E0 + dyz.E1], Data[dx.E1 + dyz.E1])),\n                            yipl(yf, xipl(xf, Data[dx.E0 + dyz.E2], Data[dx.E1 + dyz.E2]),\n                                     xipl(xf, Data[dx.E0 + dyz.E3], Data[dx.E1 + dyz.E3])));\n            //# } else {\n            return zipl(zf, yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyz.E0), Getter(Data, dx.E1 + dyz.E0)),\n                                     xipl(xf, Getter(Data, dx.E0 + dyz.E1), Getter(Data, dx.E1 + dyz.E1))),\n                            yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyz.E2), Getter(Data, dx.E1 + dyz.E2)),\n                                     xipl(xf, Getter(Data, dx.E0 + dyz.E3), Getter(Data, dx.E1 + dyz.E3))));\n            //# }\n        }\n\n        public readonly TRes SampleRaw64<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return SampleRaw64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp);\n        }\n\n        public readonly TRes SampleRaw64<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            long i11 = Info.Origin + xi * dx + yi * dy + zi * dz;\n            long d2 = dx + dx;\n            long i10 = i11 - dy, i12 = i11 + dy, i13 = i12 + dy;\n            long i00 = i10 - dz, i01 = i11 - dz, i02 = i12 - dz, i03 = i13 - dz;\n            long i20 = i10 + dz, i21 = i11 + dz, i22 = i12 + dz, i23 = i13 + dz;\n            long i30 = i20 + dz, i31 = i21 + dz, i32 = i22 + dz, i33 = i23 + dz;\n            var wx = xipl(xf); var wy = yipl(yf); var wz = zipl(zf);\n            //# if (dt == vt) {\n            return zsmp(ysmp(xsmp(Data[i00 - dx], Data[i00], Data[i00 + dx], Data[i00 + d2], ref wx),\n                             xsmp(Data[i01 - dx], Data[i01], Data[i01 + dx], Data[i01 + d2], ref wx),\n                             xsmp(Data[i02 - dx], Data[i02], Data[i02 + dx], Data[i02 + d2], ref wx),\n                             xsmp(Data[i03 - dx], Data[i03], Data[i03 + dx], Data[i03 + d2], ref wx), ref wy),\n                        ysmp(xsmp(Data[i10 - dx], Data[i10], Data[i10 + dx], Data[i10 + d2], ref wx),\n                             xsmp(Data[i11 - dx], Data[i11], Data[i11 + dx], Data[i11 + d2], ref wx),\n                             xsmp(Data[i12 - dx], Data[i12], Data[i12 + dx], Data[i12 + d2], ref wx),\n                             xsmp(Data[i13 - dx], Data[i13], Data[i13 + dx], Data[i13 + d2], ref wx), ref wy),\n                        ysmp(xsmp(Data[i20 - dx], Data[i20], Data[i20 + dx], Data[i20 + d2], ref wx),\n                             xsmp(Data[i21 - dx], Data[i21], Data[i21 + dx], Data[i21 + d2], ref wx),\n                             xsmp(Data[i22 - dx], Data[i22], Data[i22 + dx], Data[i22 + d2], ref wx),\n                             xsmp(Data[i23 - dx], Data[i23], Data[i23 + dx], Data[i23 + d2], ref wx), ref wy),\n                        ysmp(xsmp(Data[i30 - dx], Data[i30], Data[i30 + dx], Data[i30 + d2], ref wx),\n                             xsmp(Data[i31 - dx], Data[i31], Data[i31 + dx], Data[i31 + d2], ref wx),\n                             xsmp(Data[i32 - dx], Data[i32], Data[i32 + dx], Data[i32 + d2], ref wx),\n                             xsmp(Data[i33 - dx], Data[i33], Data[i33 + dx], Data[i33 + d2], ref wx), ref wy), ref wz);\n            //# } else {\n            return zsmp(ysmp(xsmp(Getter(Data, i00 - dx), Getter(Data, i00), Getter(Data, i00 + dx), Getter(Data, i00 + d2), ref wx),\n                             xsmp(Getter(Data, i01 - dx), Getter(Data, i01), Getter(Data, i01 + dx), Getter(Data, i01 + d2), ref wx),\n                             xsmp(Getter(Data, i02 - dx), Getter(Data, i02), Getter(Data, i02 + dx), Getter(Data, i02 + d2), ref wx),\n                             xsmp(Getter(Data, i03 - dx), Getter(Data, i03), Getter(Data, i03 + dx), Getter(Data, i03 + d2), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, i10 - dx), Getter(Data, i10), Getter(Data, i10 + dx), Getter(Data, i10 + d2), ref wx),\n                             xsmp(Getter(Data, i11 - dx), Getter(Data, i11), Getter(Data, i11 + dx), Getter(Data, i11 + d2), ref wx),\n                             xsmp(Getter(Data, i12 - dx), Getter(Data, i12), Getter(Data, i12 + dx), Getter(Data, i12 + d2), ref wx),\n                             xsmp(Getter(Data, i13 - dx), Getter(Data, i13), Getter(Data, i13 + dx), Getter(Data, i13 + d2), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, i20 - dx), Getter(Data, i20), Getter(Data, i20 + dx), Getter(Data, i20 + d2), ref wx),\n                             xsmp(Getter(Data, i21 - dx), Getter(Data, i21), Getter(Data, i21 + dx), Getter(Data, i21 + d2), ref wx),\n                             xsmp(Getter(Data, i22 - dx), Getter(Data, i22), Getter(Data, i22 + dx), Getter(Data, i22 + d2), ref wx),\n                             xsmp(Getter(Data, i23 - dx), Getter(Data, i23), Getter(Data, i23 + dx), Getter(Data, i23 + d2), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, i30 - dx), Getter(Data, i30), Getter(Data, i30 + dx), Getter(Data, i30 + d2), ref wx),\n                             xsmp(Getter(Data, i31 - dx), Getter(Data, i31), Getter(Data, i31 + dx), Getter(Data, i31 + d2), ref wx),\n                             xsmp(Getter(Data, i32 - dx), Getter(Data, i32), Getter(Data, i32 + dx), Getter(Data, i32 + d2), ref wx),\n                             xsmp(Getter(Data, i33 - dx), Getter(Data, i33), Getter(Data, i33 + dx), Getter(Data, i33 + d2), ref wx), ref wy), ref wz);\n            //# }\n        }\n\n        public readonly TRes Sample64Clamped<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return Sample64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample64Clamped<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp)\n        {\n            return Sample64(x, y, z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped,\n                            Tensor.Index4SamplesClamped);\n        }\n\n        public readonly TRes Sample64<T1, T2, T3, T4, T5, TRes>(\n                V3d v,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_zIndexFun)\n        {\n            return Sample64(v.X, v.Y, v.Z, xipl, yipl, zipl, xsmp, ysmp, zsmp,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun,\n                            index_min_max_delta_zIndexFun);\n        }\n\n        public readonly TRes Sample64<T1, T2, T3, T4, T5, TRes>(\n                double x, double y, double z,\n                Func<double, Tup4<T1>> xipl,\n                Func<double, Tup4<T2>> yipl,\n                Func<double, Tup4<T3>> zipl,\n                FuncRef1<__vtn__, __vtn__, __vtn__, __vtn__, Tup4<T1>, T4> xsmp,\n                FuncRef1<T4, T4, T4, T4, Tup4<T2>, T5> ysmp,\n                FuncRef1<T5, T5, T5, T5, Tup4<T3>, TRes> zsmp,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup4<long>> index_min_max_delta_zIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1);\n            dx.E0 += i; dx.E1 += i; dx.E2 += i; dx.E3 += i;\n            var dyz = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                   index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1));\n            var wx = xipl(xf); var wy = yipl(yf); var wz = zipl(zf);\n            //# if (dt == vt) {\n            return zsmp(ysmp(xsmp(Data[dx.E0 + dyz.E00], Data[dx.E1 + dyz.E00], Data[dx.E2 + dyz.E00], Data[dx.E3 + dyz.E00], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E01], Data[dx.E1 + dyz.E01], Data[dx.E2 + dyz.E01], Data[dx.E3 + dyz.E01], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E02], Data[dx.E1 + dyz.E02], Data[dx.E2 + dyz.E02], Data[dx.E3 + dyz.E02], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E03], Data[dx.E1 + dyz.E03], Data[dx.E2 + dyz.E03], Data[dx.E3 + dyz.E03], ref wx), ref wy),\n                        ysmp(xsmp(Data[dx.E0 + dyz.E04], Data[dx.E1 + dyz.E04], Data[dx.E2 + dyz.E04], Data[dx.E3 + dyz.E04], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E05], Data[dx.E1 + dyz.E05], Data[dx.E2 + dyz.E05], Data[dx.E3 + dyz.E05], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E06], Data[dx.E1 + dyz.E06], Data[dx.E2 + dyz.E06], Data[dx.E3 + dyz.E06], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E07], Data[dx.E1 + dyz.E07], Data[dx.E2 + dyz.E07], Data[dx.E3 + dyz.E07], ref wx), ref wy),\n                        ysmp(xsmp(Data[dx.E0 + dyz.E08], Data[dx.E1 + dyz.E08], Data[dx.E2 + dyz.E08], Data[dx.E3 + dyz.E08], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E09], Data[dx.E1 + dyz.E09], Data[dx.E2 + dyz.E09], Data[dx.E3 + dyz.E09], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E10], Data[dx.E1 + dyz.E10], Data[dx.E2 + dyz.E10], Data[dx.E3 + dyz.E10], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E11], Data[dx.E1 + dyz.E11], Data[dx.E2 + dyz.E11], Data[dx.E3 + dyz.E11], ref wx), ref wy),\n                        ysmp(xsmp(Data[dx.E0 + dyz.E12], Data[dx.E1 + dyz.E12], Data[dx.E2 + dyz.E12], Data[dx.E3 + dyz.E12], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E13], Data[dx.E1 + dyz.E13], Data[dx.E2 + dyz.E13], Data[dx.E3 + dyz.E13], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E14], Data[dx.E1 + dyz.E14], Data[dx.E2 + dyz.E14], Data[dx.E3 + dyz.E14], ref wx),\n                             xsmp(Data[dx.E0 + dyz.E15], Data[dx.E1 + dyz.E15], Data[dx.E2 + dyz.E15], Data[dx.E3 + dyz.E15], ref wx), ref wy), ref wz);\n            //# } else {\n            return zsmp(ysmp(xsmp(Getter(Data, dx.E0 + dyz.E00), Getter(Data, dx.E1 + dyz.E00), Getter(Data, dx.E2 + dyz.E00), Getter(Data, dx.E3 + dyz.E00), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E01), Getter(Data, dx.E1 + dyz.E01), Getter(Data, dx.E2 + dyz.E01), Getter(Data, dx.E3 + dyz.E01), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E02), Getter(Data, dx.E1 + dyz.E02), Getter(Data, dx.E2 + dyz.E02), Getter(Data, dx.E3 + dyz.E02), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E03), Getter(Data, dx.E1 + dyz.E03), Getter(Data, dx.E2 + dyz.E03), Getter(Data, dx.E3 + dyz.E03), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, dx.E0 + dyz.E04), Getter(Data, dx.E1 + dyz.E04), Getter(Data, dx.E2 + dyz.E04), Getter(Data, dx.E3 + dyz.E04), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E05), Getter(Data, dx.E1 + dyz.E05), Getter(Data, dx.E2 + dyz.E05), Getter(Data, dx.E3 + dyz.E05), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E06), Getter(Data, dx.E1 + dyz.E06), Getter(Data, dx.E2 + dyz.E06), Getter(Data, dx.E3 + dyz.E06), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E07), Getter(Data, dx.E1 + dyz.E07), Getter(Data, dx.E2 + dyz.E07), Getter(Data, dx.E3 + dyz.E07), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, dx.E0 + dyz.E08), Getter(Data, dx.E1 + dyz.E08), Getter(Data, dx.E2 + dyz.E08), Getter(Data, dx.E3 + dyz.E08), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E09), Getter(Data, dx.E1 + dyz.E09), Getter(Data, dx.E2 + dyz.E09), Getter(Data, dx.E3 + dyz.E09), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E10), Getter(Data, dx.E1 + dyz.E10), Getter(Data, dx.E2 + dyz.E10), Getter(Data, dx.E3 + dyz.E10), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E11), Getter(Data, dx.E1 + dyz.E11), Getter(Data, dx.E2 + dyz.E11), Getter(Data, dx.E3 + dyz.E11), ref wx), ref wy),\n                        ysmp(xsmp(Getter(Data, dx.E0 + dyz.E12), Getter(Data, dx.E1 + dyz.E12), Getter(Data, dx.E2 + dyz.E12), Getter(Data, dx.E3 + dyz.E12), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E13), Getter(Data, dx.E1 + dyz.E13), Getter(Data, dx.E2 + dyz.E13), Getter(Data, dx.E3 + dyz.E13), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E14), Getter(Data, dx.E1 + dyz.E14), Getter(Data, dx.E2 + dyz.E14), Getter(Data, dx.E3 + dyz.E14), ref wx),\n                             xsmp(Getter(Data, dx.E0 + dyz.E15), Getter(Data, dx.E1 + dyz.E15), Getter(Data, dx.E2 + dyz.E15), Getter(Data, dx.E3 + dyz.E15), ref wx), ref wy), ref wz);\n            //# }\n        }\n\n        //# } // d == 3\n        //# if (d == 4) {\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return SampleRaw16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl);\n        }\n\n        /// <summary>\n        /// Sample the tensor4 using 16 samples and the supplied\n        /// interpolation functions. If only integer coordinates are\n        /// supplied the returned value is the same as the indexer\n        /// of the tensor4, i.e. voxel centers are assumed to be on\n        /// integer coordinates. No bounds checking is performed.\n        /// </summary>\n        public readonly TRes SampleRaw16<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz = Info.Delta.Z;\n            double wid = Fun.Floor(w); long wi = (long)wid; double wf = w - wid; long dw = Info.Delta.W;\n            long i = Info.Origin + xi * dx + yi * dy + zi * dz + wi * dw;\n            long ix = i + dx, iy = i + dy, ixy = ix + dy;\n            long iz = i + dz, ixz = ix + dz, iyz = iy + dz, ixyz = ixy + dz;\n            //# if (dt == vt) {\n            return wipl(wf, zipl(zf, yipl(yf, xipl(xf, Data[i], Data[ix]),\n                                              xipl(xf, Data[iy], Data[ixy])),\n                                     yipl(yf, xipl(xf, Data[iz], Data[ixz]),\n                                              xipl(xf, Data[iyz], Data[ixyz]))),\n                            zipl(zf, yipl(yf, xipl(xf, Data[i + dw], Data[ix + dw]),\n                                              xipl(xf, Data[iy + dw], Data[ixy + dw])),\n                                     yipl(yf, xipl(xf, Data[iz + dw], Data[ixz + dw]),\n                                              xipl(xf, Data[iyz + dw], Data[ixyz + dw]))));\n            //# } else {\n            return wipl(wf, zipl(zf, yipl(yf, xipl(xf, Getter(Data, i), Getter(Data, ix)),\n                                              xipl(xf, Getter(Data, iy), Getter(Data, ixy))),\n                                     yipl(yf, xipl(xf, Getter(Data, iz), Getter(Data, ixz)),\n                                              xipl(xf, Getter(Data, iyz), Getter(Data, ixyz)))),\n                            zipl(zf, yipl(yf, xipl(xf, Getter(Data, i + dw), Getter(Data, ix + dw)),\n                                              xipl(xf, Getter(Data, iy + dw), Getter(Data, ixy + dw))),\n                                     yipl(yf, xipl(xf, Getter(Data, iz + dw), Getter(Data, ixz + dw)),\n                                              xipl(xf, Getter(Data, iyz + dw), Getter(Data, ixyz + dw)))));\n            //# }\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return Sample16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample16Clamped<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl)\n        {\n            return Sample16(x, y, z, w, xipl, yipl, zipl, wipl,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped,\n                            Tensor.Index2SamplesClamped, Tensor.Index2SamplesClamped);\n        }\n\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                V4d v,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_wIndexFun)\n        {\n            return Sample16(v.X, v.Y, v.Z, v.W, xipl, yipl, zipl, wipl,\n                            index_min_max_delta_xIndexFun,\n                            index_min_max_delta_yIndexFun,\n                            index_min_max_delta_zIndexFun,\n                            index_min_max_delta_wIndexFun);\n        }\n\n        /// <summary>\n        /// Sample the tensor4 using 16 neighbouring samples and the\n        /// supplied interpolation functions and border handling functions.\n        /// If only integer coordinates are supplied the returned value is\n        /// the same as the indexer of the tensor4, i.e. voxel centers are\n        /// assumed to be on integer coordinates.\n        /// </summary>\n        public readonly TRes Sample16<T1, T2, T3, TRes>(\n                double x, double y, double z, double w,\n                Func<double, __vtn__, __vtn__, T1> xipl,\n                Func<double, T1, T1, T2> yipl,\n                Func<double, T2, T2, T3> zipl,\n                Func<double, T3, T3, TRes> wipl,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_xIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_yIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_zIndexFun,\n                Func<long, long, long, long, Tup2<long>> index_min_max_delta_wIndexFun)\n        {\n            double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid; long dx1 = Info.Delta.X;\n            double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid; long dy1 = Info.Delta.Y;\n            double zid = Fun.Floor(z); long zi = (long)zid; double zf = z - zid; long dz1 = Info.Delta.Z;\n            double wid = Fun.Floor(w); long wi = (long)wid; double wf = w - wid; long dw1 = Info.Delta.W;\n            long i = Info.Origin + xi * dx1 + yi * dy1 + zi * dz1 + wi * dw1;\n            var dx = index_min_max_delta_xIndexFun(xi, FX, EX, dx1); dx.E0 += i; dx.E1 += i;\n            var dyzw = Fun.OuterSum(index_min_max_delta_yIndexFun(yi, FY, EY, dy1),\n                                    index_min_max_delta_zIndexFun(zi, FZ, EZ, dz1),\n                                    index_min_max_delta_wIndexFun(wi, FW, EW, dw1));\n            //# if (dt == vt) {\n            return wipl(wf, zipl(zf, yipl(yf, xipl(xf, Data[dx.E0 + dyzw.E0], Data[dx.E1 + dyzw.E0]),\n                                              xipl(xf, Data[dx.E0 + dyzw.E1], Data[dx.E1 + dyzw.E1])),\n                                     yipl(yf, xipl(xf, Data[dx.E0 + dyzw.E2], Data[dx.E1 + dyzw.E2]),\n                                              xipl(xf, Data[dx.E0 + dyzw.E3], Data[dx.E1 + dyzw.E3]))),\n                            zipl(zf, yipl(yf, xipl(xf, Data[dx.E0 + dyzw.E4], Data[dx.E1 + dyzw.E4]),\n                                              xipl(xf, Data[dx.E0 + dyzw.E5], Data[dx.E1 + dyzw.E5])),\n                                     yipl(yf, xipl(xf, Data[dx.E0 + dyzw.E6], Data[dx.E1 + dyzw.E6]),\n                                              xipl(xf, Data[dx.E0 + dyzw.E7], Data[dx.E1 + dyzw.E7]))));\n            //# } else {\n            return wipl(wf, zipl(zf, yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyzw.E0), Getter(Data, dx.E1 + dyzw.E0)),\n                                              xipl(xf, Getter(Data, dx.E0 + dyzw.E1), Getter(Data, dx.E1 + dyzw.E1))),\n                                     yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyzw.E2), Getter(Data, dx.E1 + dyzw.E2)),\n                                              xipl(xf, Getter(Data, dx.E0 + dyzw.E3), Getter(Data, dx.E1 + dyzw.E3)))),\n                            zipl(zf, yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyzw.E4), Getter(Data, dx.E1 + dyzw.E4)),\n                                              xipl(xf, Getter(Data, dx.E0 + dyzw.E5), Getter(Data, dx.E1 + dyzw.E5))),\n                                     yipl(yf, xipl(xf, Getter(Data, dx.E0 + dyzw.E6), Getter(Data, dx.E1 + dyzw.E6)),\n                                              xipl(xf, Getter(Data, dx.E0 + dyzw.E7), Getter(Data, dx.E1 + dyzw.E7)))));\n            //# }\n        }\n\n        //# }\n        #endregion\n\n        //# if (d == 2) {\n        #region Drawing\n\n        /// <summary>\n        /// Draws a horizontal line. The parameters x0, x1, and y are rounded\n        /// to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetLineX(double x0, double x1, double y, __vtn__ value)\n        {\n            SetLineX((long)(x0 + 0.5), (long)(x1 + 0.5), (long)(y + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical line. The parameters x, y0, and y1 are rounded\n        /// to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetLineY(double x, double y0, double y1, __vtn__ value)\n        {\n            SetLineY((long)(x + 0.5), (long)(y0 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a horizontal line.\n        /// </summary>\n        public readonly void SetLineX(long x0, long x1, long y, __vtn__ value)\n        {\n            long xmin = Fun.Max(Fun.Min(x0, x1), Info.First.X);\n            long xmax = Fun.Min(Fun.Max(x0, x1), Info.First.X + Info.Size.X - 1);\n            if (y >= Info.First.Y && y < Info.First.Y + Info.Size.Y)\n                for (long x = xmin; x <= xmax; x++) this[x, y] = value;\n        }\n\n        /// <summary>\n        /// Draws a vertical line.\n        /// </summary>\n        public readonly void SetLineY(long x, long y0, long y1, __vtn__ value)\n        {\n            long ymin = Fun.Max(Fun.Min(y0, y1), Info.First.Y);\n            long ymax = Fun.Min(Fun.Max(y0, y1), Info.First.Y + Info.Size.Y - 1);\n            if (x >= Info.First.X && x < Info.First.X + Info.Size.X)\n                for (long y = ymin; y <= ymax; y++) this[x, y] = value;\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame. The corner positions are\n        /// rounded to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetRectangle(V2d p0, V2d p1, __vtn__ value)\n        {\n            SetRectangle((long)(p0.X + 0.5), (long)(p0.Y + 0.5),\n                         (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n        /// <summary>\n        /// Draws a rectangular frame. The parameters x0, x1, y0, and y1 are\n        /// rounded to the nearest integer coordinates.\n        /// </summary>\n        public readonly void SetRectangle(double x0, double y0, double x1, double y1, __vtn__ value)\n        {\n            SetRectangle((long)(x0 + 0.5), (long)(y0 + 0.5),\n                         (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(V2i p0, V2i p1, __vtn__ value)\n        {\n            SetRectangle((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(V2l v0, V2l v1, __vtn__ value)\n        {\n            SetRectangle(v0.X, v0.Y, v1.X, v1.Y, value);\n        }\n\n        /// <summary>\n        /// Draws a rectangular frame given the coordinates of two opposing corners.\n        /// </summary>\n        public readonly void SetRectangle(long x0, long y0, long x1, long y1, __vtn__ value)\n        {\n            long ymin = Fun.Min(y0, y1), ymax = Fun.Max(y0, y1);\n            SetLineX(x0, x1, ymin, value);\n            SetLineY(x0, ymin + 1L, ymax - 1L, value);\n            SetLineY(x1, ymin + 1L, ymax - 1L, value);\n            SetLineX(x0, x1, ymax, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle and its interior to the supplied value.\n        /// Note that the coordinates are rounded to the nearest integer coordinate.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2d p0, V2d p1, __vtn__ value)\n        {\n            SetRectangleFilled((long)(p0.X + 0.5), (long)(p0.Y + 0.5),\n                               (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle and its interior to the supplied value.\n        /// Note that the coordinates are rounded to the nearest integer coordinate.\n        /// </summary>\n        public readonly void SetRectangleFilled(double x0, double y0, double x1, double y1, __vtn__ value)\n        {\n            SetRectangleFilled((long)(x0 + 0.5), (long)(y0 + 0.5),\n                               (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// position vectors and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2i p0, V2i p1, __vtn__ value)\n        {\n            SetRectangleFilled((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// position vectors and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(V2l p0, V2l p1, __vtn__ value)\n        {\n            SetRectangleFilled(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        /// Sets the supplied rectangle given by its minimal and maximal pixel\n        /// coordinates and its interior to the supplied value.\n        /// </summary>\n        public readonly void SetRectangleFilled(long x0, long y0, long x1, long y1, __vtn__ value)\n        {\n            long xmin = Fun.Max(Fun.Min(x0, x1), Info.First.X);\n            long xmax = Fun.Min(Fun.Max(x0, x1), Info.First.X + Info.Size.X - 1);\n            if (xmin > xmax) return;\n            long ymin = Fun.Max(Fun.Min(y0, y1), Info.First.Y);\n            long ymax = Fun.Min(Fun.Max(y0, y1), Info.First.Y + Info.Size.Y - 1);\n            if (ymin > ymax) return;\n\n            SubMatrix(x0, y0, 1 + x1 - x0, 1 + y1 - y0).Set(value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2d p, double radius, __vtn__ value)\n        {\n            SetCross((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around [x,y].\n        /// </summary>\n        public readonly void SetCross(double x, double y, double radius, __vtn__ value)\n        {\n            SetCross((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2i p, int radius, __vtn__ value)\n        {\n            SetCross((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around p.\n        /// </summary>\n        public readonly void SetCross(V2l p, long radius, __vtn__ value)\n        {\n            SetCross(p.X, p.Y, radius, value);\n        }\n\n        /// <summary>\n        /// Draws a vertical/horizontal cross around [x, y].\n        /// </summary>\n        public readonly void SetCross(long x, long y, long radius, __vtn__ value)\n        {\n            SetLineX(x - radius, x + radius, y, value);\n            SetLineY(x, y - radius, y + radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2d p, double radius, __vtn__ value)\n        {\n            SetCrossX((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(double x, double y, double radius, __vtn__ value)\n        {\n            SetCrossX((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2i p, int radius, __vtn__ value)\n        {\n            SetCrossX((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(V2l p, long radius, __vtn__ value)\n        {\n            SetCrossX(p.X, p.Y, radius, value);\n        }\n\n        /// <summary>\n        /// Draws a X-style cross around [x, y]. Note that radius\n        /// is the horizontal/vertical distance of the corner.\n        /// </summary>\n        public readonly void SetCrossX(long x, long y, long radius, __vtn__ value)\n        {\n            SetLine(x - radius, y - radius, x + radius, y + radius, value);\n            SetLine(x + radius, y - radius, x - radius, y + radius, value);\n        }\n\n        public readonly void SetSquare(\n                V2d p, double radius, __vtn__ value)\n        {\n            SetSquare((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquare(\n                double x, double y, double radius, __vtn__ value)\n        {\n            SetSquare((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquare(\n                V2i p, int radius, __vtn__ value)\n        {\n            SetSquare((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetSquare(\n                V2l p, long radius, __vtn__ value)\n        {\n            SetSquare(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetSquare(\n                long x, long y, long radius, __vtn__ value)\n        {\n            SetRectangle(x - radius, y - radius, x + radius, y + radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2d p, double radius, __vtn__ value)\n        {\n            SetSquareFilled((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquareFilled(\n                double x, double y, double radius, __vtn__ value)\n        {\n            SetSquareFilled((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2i p, int radius, __vtn__ value)\n        {\n            SetSquareFilled((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                V2l p, long radius, __vtn__ value)\n        {\n            SetSquareFilled(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetSquareFilled(\n                long x, long y, long radius, __vtn__ value)\n        {\n            SetRectangleFilled(x - radius, y - radius, x + radius, y + radius, value);\n        }\n\n        public readonly void SetLine(\n                V2d p0, V2d p1, __vtn__ value)\n        {\n            SetLine((long)(p0.X + 0.5), (long)(p0.Y + 0.5), (long)(p1.X + 0.5), (long)(p1.Y + 0.5), value);\n        }\n\n        public readonly void SetLine(\n                double x0, double y0, double x1, double y1, __vtn__ value)\n        {\n            SetLine((long)(x0 + 0.5), (long)(y0 + 0.5), (long)(x1 + 0.5), (long)(y1 + 0.5), value);\n        }\n\n        public readonly void SetLine(\n                V2i p0, V2i p1, __vtn__ value)\n        {\n            SetLine((long)p0.X, (long)p0.Y, (long)p1.X, (long)p1.Y, value);\n        }\n\n        public readonly void SetLine(\n                V2l p0, V2l p1, __vtn__ value)\n        {\n            SetLine(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        ///  Bresenham Line Algorithm\n        /// </summary>\n        public readonly void SetLine(\n                long x0, long y0, long x1, long y1, __vtn__ value)\n        {\n            //-- Trivial Cases\n            if (x0 == x1) { SetLineY(x0, y0, y1, value); return; }\n            if (y0 == y1) { SetLineX(x0, x1, y1, value); return; }\n\n            //-- Bresenham\n            long dx, dy;\n            long incx, incy;\n\n            if (x1 >= x0)\n            {\n                dx = x1 - x0; incx = 1;\n            }\n            else\n            {\n                dx = x0 - x1; incx = -1;\n            }\n\n            if (y1 >= y0)\n            {\n                dy = y1 - y0;  incy = 1;\n            }\n            else\n            {\n                dy = y0 - y1; incy = -1;\n            }\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n            bool xok = x0 >= xmin && x0 <= xmax;\n            bool yok = y0 >= ymin && y0 <= ymax;\n            long balance;\n\n            if (dx >= dy)\n            {\n                dy <<= 1;\n                balance = dy - dx;\n                dx <<= 1;\n\n                while (x0 != x1)\n                {\n                    if (xok && yok) this[x0, y0] = value;\n                    if (balance >= 0)\n                    {\n                        y0 += incy; yok = y0 >= ymin && y0 <= ymax;\n                        balance -= dx;\n                    }\n                    balance += dy;\n                    x0 += incx; xok = x0 >= xmin && x0 <= xmax;\n                }\n                if (xok && yok) this[x0, y0] = value;\n            }\n            else\n            {\n                dx <<= 1;\n                balance = dx - dy;\n                dy <<= 1;\n\n                while (y0 != y1)\n                {\n                    if (xok && yok) this[x0, y0] = value;\n                    if (balance >= 0)\n                    {\n                        x0 += incx; xok = x0 >= xmin && x0 <= xmax;\n                        balance -= dy;\n                    }\n                    balance += dx;\n                    y0 += incy; yok = y0 >= ymin && y0 <= ymax;\n                }\n                if (xok && yok) this[x0, y0] = value;\n            }\n        }\n\n        /// <summary>\n        /// Set all pixels whose square region is intersected by the line from p0 to p1\n        /// to the supplied value. Does not perform any bounds checks.\n        /// </summary>\n        public readonly void SetLineAllTouchedRaw(V2d p0, V2d p1, __vtn__ value)\n        {\n            SetLineAllTouchedRaw(p0.X, p0.Y, p1.X, p1.Y, value);\n        }\n\n        /// <summary>\n        /// Set all pixels whose square region is intersected by the line from (x0,y0) to (x1,y1)\n        /// to the supplied value. Does not perform any bounds checks.\n        /// </summary>\n        public readonly void SetLineAllTouchedRaw(double x0, double y0, double x1, double y1, __vtn__ value)\n        {\n            var ix = (long)Fun.Floor(x0);\n            var iy = (long)Fun.Floor(y0);\n            var dx = x1 - x0;\n            var dy = y1 - y0;\n\n            var len = Fun.Sqrt(dx * dx + dy * dy);\n\n            double tx, ty, dtx, dty;\n            long dix, diy;\n\n            if (dx > 0.0)       { dtx = len / dx; tx = dtx * (1.0 - (x0 - ix)); dix = Info.DX; }\n            else if (dx < 0.0)  { dtx = -len / dx; tx = dtx * (x0 - ix); dix = -Info.DX; }\n            else                { dtx = 0.0; tx = len; dix = 0; }\n\n            if (dy > 0.0)       { dty = len / dy; ty = dty * (1.0 - (y0 - iy)); diy = Info.DY; }\n            else if (dy < 0.0)  { dty = -len / dy; ty = dty * (y0 - iy); diy = -Info.DY; }\n            else                { dty = 0.0; ty = len; diy = 0; }\n\n            var mdata = Data;/*# if (dt != vt) { */ var mset = Setter;/*# } */\n            double t = 0.0;\n            long index = Info.Origin + ix * Info.DX + iy * Info.DY;\n            do\n            {\n                //# if (dt != vt) {\n                mset(mdata, index, value);\n                //# } else {\n                mdata[index] = value;\n                //# }\n                if (tx < ty)    { t = tx; tx += dtx; index += dix; }\n                else            { t = ty; ty += dty; index += diy; }\n            }\n            while (t < len);\n        }\n\n        public readonly void SetCircle(\n                V2d p, double radius, __vtn__ value)\n        {\n            SetCircle((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircle(\n                double x, double y, double radius, __vtn__ value)\n        {\n            SetCircle((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircle(\n                V2i p, int radius, __vtn__ value)\n        {\n            SetCircle((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetCircle(\n                V2l p, long radius, __vtn__ value)\n        {\n            SetCircle(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetCircle(\n                long x, long y, long radius, __vtn__ value)\n        {\n            long f = 1 - radius;\n            long ddF_x = 0;\n            long ddF_y = -2 * radius;\n            long rx = 0;\n            long ry = radius;\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n\n            if (x >= xmin && x <= xmax)\n            {\n                var ym = y - radius; if (ym >= ymin && ym <= ymax) this[x, ym] = value;\n                var yp = y + radius; if (yp >= ymin && yp <= ymax) this[x, yp] = value;\n            }\n            if (y >= xmin && y <= ymax)\n            {\n                var xm = x - radius; if (xm >= xmin && xm <= xmax) this[xm, y] = value;\n                var xp = x + radius; if (xp >= xmin && xp <= xmax) this[xp, y] = value;\n            }\n            bool xmxOk = true, xpxOk = true, xmyOk = true, xpyOk = true;\n            while (rx < ry)\n            {\n                if (f >= 0)\n                {\n                    ry--; ddF_y += 2; f += ddF_y;\n                }\n                rx++;\n                ddF_x += 2;\n                f += ddF_x + 1;\n\n                long xmx = x - rx; xmxOk = xmx >= xmin && xmx <= xmax;\n                long xpx = x + rx; xpxOk = xpx >= xmin && xpx <= xmax;\n                long xmy = x - ry; xmyOk = xmy >= xmin && xmy <= xmax;\n                long xpy = x + ry; xpyOk = xpy >= xmin && xpy <= xmax;\n                long ymx = y - rx, ypx = y + rx;\n                long ymy = y - ry, ypy = y + ry;\n\n                if (ymx >= ymin && ymx <= ymax)\n                {\n                    if (xmyOk) this[xmy, ymx] = value;\n                    if (xpyOk) this[xpy, ymx] = value;\n                }\n                if (ypx >= ymin && ypx <= ymax)\n                {\n                    if (xmyOk) this[xmy, ypx] = value;\n                    if (xpyOk) this[xpy, ypx] = value;\n                }\n                if (ymy >= ymin && ymy <= ymax)\n                {\n                    if (xmxOk) this[xmx, ymy] = value;\n                    if (xpxOk) this[xpx, ymy] = value;\n                }\n                if (ypy >= ymin && ypy <= ymax)\n                {\n                    if (xmxOk) this[xmx, ypy] = value;\n                    if (xpxOk) this[xpx, ypy] = value;\n                }\n            }\n        }\n\n        public readonly void SetCircleFilled(\n                V2d p, double radius, __vtn__ value)\n        {\n            SetCircleFilled((long)(p.X + 0.5), (long)(p.Y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircleFilled(\n                double x, double y, double radius, __vtn__ value)\n        {\n            SetCircleFilled((long)(x + 0.5), (long)(y + 0.5), (long)(radius + 0.5), value);\n        }\n\n        public readonly void SetCircleFilled(\n                V2i p, int radius, __vtn__ value)\n        {\n            SetCircleFilled((long)p.X, (long)p.Y, (long)radius, value);\n        }\n\n        public readonly void SetCircleFilled(\n                V2l p, long radius, __vtn__ value)\n        {\n            SetCircleFilled(p.X, p.Y, radius, value);\n        }\n\n        public readonly void SetCircleFilled(\n                long x0, long y0, long radius, __vtn__ value)\n        {\n            long x = radius;\n            long y = 0;\n            long xChange = 1 - (radius << 1);\n            long yChange = 0;\n            long radiusError = 0;\n\n            long xmin = Info.First.X, xmax = xmin + Info.Size.X - 1;\n            long ymin = Info.First.Y, ymax = ymin + Info.Size.Y - 1;\n\n            long mdx = DX; var mdata = Data;/*# if (dt != vt) { */ var mset = Setter;/*# } */\n\n            while (x >= y)\n            {\n                if (y0 + y >= ymin && y0 + y <= ymax)\n                {\n                    var xb = Fun.Max(x0 - x, xmin); var xe = Fun.Min(x0 + x, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 + y), e = Info.Index(xe + 1, y0 + y); i != e; i += mdx)\n                        //# if (dt != vt) {\n                        mset(mdata, i, value);\n                        //# } else {\n                        mdata[i] = value;\n                        //# }\n                }\n                if (y0 - y >= ymin && y0 - y <= ymax)\n                {\n                    var xb = Fun.Max(x0 - x, xmin); var xe = Fun.Min(x0 + x, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 - y), e = Info.Index(xe + 1, y0 - y); i != e; i += mdx)\n                            //# if (dt != vt) {\n                            mset(mdata, i, value);\n                            //# } else {\n                            mdata[i] = value;\n                            //# }\n                }\n                if (y0 + x >= ymin && y0 + x <= ymax)\n                {\n                    var xb = Fun.Max(x0 - y, xmin); var xe = Fun.Min(x0 + y, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 + x), e = Info.Index(xe + 1, y0 + x); i != e; i += mdx)\n                            //# if (dt != vt) {\n                            mset(mdata, i, value);\n                            //# } else {\n                            mdata[i] = value;\n                            //# }\n                }\n                if (y0 - x >= ymin && y0 - x <= ymax)\n                {\n                    var xb = Fun.Max(x0 - y, xmin); var xe = Fun.Min(x0 + y, xmax);\n                    if (xb <= xe)\n                        for (long i = Info.Index(xb, y0 - x), e = Info.Index(xe + 1, y0 - x); i != e; i += mdx)\n                            //# if (dt != vt) {\n                            mset(mdata, i, value);\n                            //# } else {\n                            mdata[i] = value;\n                            //# }\n                }\n                y++;\n                radiusError += yChange;\n                yChange += 2;\n                if (((radiusError << 1) + xChange) > 0)\n                {\n                    x--;\n                    radiusError += xChange;\n                    xChange += 2;\n                }\n            }\n        }\n\n        //# foreach (var hasVertexArray in new[] { false, true }) {\n        /// <summary>\n        /// Set all matrix pixels inside the specified polygon to the supplied\n        /// value. This is a raw routine that does no clipping and assumes that\n        /// all pixels that need to be set are within the matrix. The polygon\n        /// is assumed to consist of two y-monotone point sequences between\n        /// the points with minimum and maximum y-coordinate. Note that convex\n        /// and non-concave polygons automatically fullfill this condition.\n        /// Rasterization is performed according to DirextX11 rules.\n        /// </summary>\n        //# var polygon = hasVertexArray ? \"vertexArray[polygon[\" : \"polygon[\";\n        //# var q = hasVertexArray ? \"]]\" : \"]\";\n        //# var pt = hasVertexArray ? \"int\" : \"V2d\";\n        public readonly void SetMonotonePolygonFilledRaw(\n                __pt__[] polygon,/*# if (hasVertexArray) { */ V2d[] vertexArray,/*# } */\n                __vtn__ value,\n                Winding winding = Winding.CCW,\n                double eps = 1e-8)\n        {\n            var pc = polygon.Length;\n            int diLeft = winding == Winding.CCW ? 1 : pc - 1;\n            int diRight = winding == Winding.CCW ? pc - 1 : 1;\n            int eLeft = 0, end = 0;\n            double yeLeft = __polygon__0__q__.Y;\n            for (int pi = 1; pi < pc; pi++) // find min in (y)eLeft and max in end\n            {\n                var y = __polygon__pi__q__.Y;\n                if (y < yeLeft) { eLeft = pi; yeLeft = y; }\n                if (y > __polygon__end__q__.Y) end = pi;\n            }\n            int eRight = eLeft, sLeft = 0, sRight = 0;\n            double yeRight = yeLeft;\n            double xfLeft = 0, fdeltaLeft = 0.0, xfRight = 0, fdeltaRight = 0.0;\n            long iLeft = 0, ideltaLeft = 0, iRight = 0, ideltaRight = 0;\n            long mdx = DX, mdy = DY; var mdata = Data;/*# if (dt != vt) { */ var mset = Setter;/*# } */\n            long yi = (long)Fun.Ceiling(yeLeft - 0.5), yieLeft = yi, yieRight = yi;\n            var lineOrigin = Origin + yi * mdy;\n            bool exit = false;\n            while (true)\n            {\n                if (yi == yieLeft) // next left edge\n                {\n                    double ysLeft = 0.0;\n                    do\n                    {\n                        sLeft = eLeft; if (sLeft == end) { exit = true; break; }\n                        eLeft = (sLeft + diLeft) % pc;\n                        ysLeft = yeLeft;\n                        yeLeft = __polygon__eLeft__q__.Y;\n                        yieLeft = (long)Fun.Ceiling(yeLeft - 0.5);\n                    }\n                    while (yi == yieLeft); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaLeft = yeLeft - ysLeft;\n                    if (deltaLeft < 0.0) { exit = true; break; }\n                    if (deltaLeft < eps) deltaLeft = eps;\n                    deltaLeft = (__polygon__eLeft__q__.X - __polygon__sLeft__q__.X) / deltaLeft;\n                    ideltaLeft = (long)Fun.Ceiling(deltaLeft);\n                    fdeltaLeft = deltaLeft - (double)ideltaLeft;\n                    double xLeft = __polygon__sLeft__q__.X + (0.5 + (double)yi - ysLeft) * deltaLeft;\n                    iLeft = (long)Fun.Ceiling(xLeft - 0.5);\n                    xfLeft = xLeft - (double)iLeft + 0.5 - eps; // offset for stable 0.0 comparison\n                    iLeft = lineOrigin + iLeft * mdx;\n                    ideltaLeft = mdy + ideltaLeft * mdx;\n                }\n                if (exit) break;\n                if (yi == yieRight) // next right edge\n                {\n                    double ysRight = 0.0;\n                    do\n                    {\n                        sRight = eRight; if (sRight == end) { exit = true; break; }\n                        eRight = (sRight + diRight) % pc;\n                        ysRight = yeRight;\n                        yeRight = __polygon__eRight__q__.Y;\n                        yieRight = (long)Fun.Ceiling(yeRight - 0.5);\n                    }\n                    while (yi == yieRight); // ensure we have an edge that makes a difference\n                    if (exit) break;\n                    double deltaRight = yeRight - ysRight;\n                    if (deltaRight < 0.0) { exit = true; break; }\n                    if (deltaRight < eps) deltaRight = eps;\n                    deltaRight = (__polygon__eRight__q__.X - __polygon__sRight__q__.X) / deltaRight;\n                    ideltaRight = (long)Fun.Ceiling(deltaRight);\n                    fdeltaRight = deltaRight - (double)ideltaRight;\n                    double xRight = __polygon__sRight__q__.X + (0.5 + (double)yi - ysRight) * deltaRight;\n                    iRight = (long)Fun.Ceiling(xRight - 0.5);\n                    xfRight = xRight - (double)iRight + 0.5 - eps; // offset for stable 0.0 comparison\n                    iRight = lineOrigin + iRight * mdx;\n                    ideltaRight = mdy + ideltaRight * mdx;\n                }\n                if (exit) break;\n                long yimin = Fun.Min(yieLeft, yieRight);\n                while (yi < yimin)\n                {\n                    for (long i = iLeft; i < iRight; i += mdx)\n                    {\n                        //# if (dt != vt) {\n                        mset(mdata, i, value);\n                        //# } else {\n                        mdata[i] = value;\n                        //# }\n                    }\n                    iLeft += ideltaLeft; xfLeft += fdeltaLeft;\n                    if (xfLeft < 0.0) { xfLeft += 1.0; iLeft -= mdx; }\n                    iRight += ideltaRight; xfRight += fdeltaRight;\n                    if (xfRight < 0.0) { xfRight += 1.0; iRight -= mdx; }\n                    ++yi; lineOrigin += mdy;\n                }\n            }\n        }\n\n        //# } // hasVertexArray\n        #endregion\n\n        //# }\n        #region I__ttn__\n\n        /// <summary>\n        /// Dimension of the generic __ttn__.\n        /// </summary>\n        public readonly __itn__ Dim { get { return Info.Size; } }\n\n        public readonly object GetValue(/*# iaa.ForEach(a => { */long __a__/*# }, comma); */)\n        {\n            return (object)this[/*# iaa.ForEach(a => { */__a__/*# }, comma); */];\n        }\n\n        public readonly void SetValue(object value, /*# iaa.ForEach(a => { */long __a__/*# }, comma); */)\n        {\n            this[/*# iaa.ForEach(a => { */__a__/*# }, comma); */] = (__vtn__)value;\n        }\n\n        //# if (d > 1) {\n        public readonly object GetValue(__itn__ v)\n        {\n            return (object)this[v];\n        }\n\n        public readonly void SetValue(object value, __itn__ v)\n        {\n            this[v] = (__vtn__)value;\n        }\n\n        //#}\n        #endregion\n\n    }\n\n    #endregion\n\n    //# }); // tt\n}"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/Accessors.cs",
    "content": "﻿using System;\n\nnamespace Aardvark.Base\n{\n    public interface ITensorAccessors\n    {\n    }\n\n    public class TensorAccessors<Td, Tv> : ITensorAccessors\n    {\n        public Func<Td[], long, Tv> Getter;\n        public Action<Td[], long, Tv> Setter;\n    }\n\n    public static partial class TensorAccessors\n    {\n        public static class Intent\n        {\n            public static readonly Symbol BW = Col.Intent.BW;\n            public static readonly Symbol Gray = Col.Intent.Gray;\n            public static readonly Symbol Alpha = Col.Intent.Alpha;\n\n            public static readonly Symbol RGB = Col.Intent.RGB;\n            public static readonly Symbol BGR = Col.Intent.BGR;\n            public static readonly Symbol RGBA = Col.Intent.RGBA;\n            public static readonly Symbol BGRA = Col.Intent.BGRA;\n\n            public static readonly Symbol ColorChannel = \"ColorChannel\";\n        };\n\n        public static TensorAccessors<Td, Tv> Get<Td, Tv>(Symbol intent, long[] delta)\n        {\n            Type dataType = typeof(Td);\n            Type viewType = typeof(Tv);\n\n            if (s_creatorMap.TryGetValue((dataType, viewType, intent), out var creator))\n            {\n                if (creator(delta) is TensorAccessors<Td, Tv> typed) return typed;\n            }\n\n            throw new NotSupportedException($\"Cannot view {dataType} as {viewType} with intent {intent}.\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/Accessors_auto.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\n\nnamespace Aardvark.Base\n{\n    public static partial class TensorAccessors\n    {\n        #region Single channel accessors\n\n        private static ITensorAccessors GetByteAsByte(long[] delta)\n        {\n            return new TensorAccessors<byte, byte>()\n            {\n                Getter = (da, i) => (da[i]),\n                Setter = (da, i, v) => da[i] = (v),\n            };\n        }\n\n        private static ITensorAccessors GetByteAsUShort(long[] delta)\n        {\n            return new TensorAccessors<byte, ushort>()\n            {\n                Getter = (da, i) => Col.ByteToUShort(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UShortToByte(v),\n            };\n        }\n\n        private static ITensorAccessors GetByteAsUInt(long[] delta)\n        {\n            return new TensorAccessors<byte, uint>()\n            {\n                Getter = (da, i) => Col.ByteToUInt(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UIntToByte(v),\n            };\n        }\n\n        private static ITensorAccessors GetByteAsHalf(long[] delta)\n        {\n            return new TensorAccessors<byte, Half>()\n            {\n                Getter = (da, i) => Col.ByteToHalf(da[i]),\n                Setter = (da, i, v) => da[i] = Col.HalfToByte(v),\n            };\n        }\n\n        private static ITensorAccessors GetByteAsFloat(long[] delta)\n        {\n            return new TensorAccessors<byte, float>()\n            {\n                Getter = (da, i) => Col.ByteToFloat(da[i]),\n                Setter = (da, i, v) => da[i] = Col.FloatToByte(v),\n            };\n        }\n\n        private static ITensorAccessors GetByteAsDouble(long[] delta)\n        {\n            return new TensorAccessors<byte, double>()\n            {\n                Getter = (da, i) => Col.ByteToDouble(da[i]),\n                Setter = (da, i, v) => da[i] = Col.DoubleToByte(v),\n            };\n        }\n\n        private static ITensorAccessors GetUShortAsByte(long[] delta)\n        {\n            return new TensorAccessors<ushort, byte>()\n            {\n                Getter = (da, i) => Col.UShortToByte(da[i]),\n                Setter = (da, i, v) => da[i] = Col.ByteToUShort(v),\n            };\n        }\n\n        private static ITensorAccessors GetUShortAsUShort(long[] delta)\n        {\n            return new TensorAccessors<ushort, ushort>()\n            {\n                Getter = (da, i) => (da[i]),\n                Setter = (da, i, v) => da[i] = (v),\n            };\n        }\n\n        private static ITensorAccessors GetUShortAsUInt(long[] delta)\n        {\n            return new TensorAccessors<ushort, uint>()\n            {\n                Getter = (da, i) => Col.UShortToUInt(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UIntToUShort(v),\n            };\n        }\n\n        private static ITensorAccessors GetUShortAsHalf(long[] delta)\n        {\n            return new TensorAccessors<ushort, Half>()\n            {\n                Getter = (da, i) => Col.UShortToHalf(da[i]),\n                Setter = (da, i, v) => da[i] = Col.HalfToUShort(v),\n            };\n        }\n\n        private static ITensorAccessors GetUShortAsFloat(long[] delta)\n        {\n            return new TensorAccessors<ushort, float>()\n            {\n                Getter = (da, i) => Col.UShortToFloat(da[i]),\n                Setter = (da, i, v) => da[i] = Col.FloatToUShort(v),\n            };\n        }\n\n        private static ITensorAccessors GetUShortAsDouble(long[] delta)\n        {\n            return new TensorAccessors<ushort, double>()\n            {\n                Getter = (da, i) => Col.UShortToDouble(da[i]),\n                Setter = (da, i, v) => da[i] = Col.DoubleToUShort(v),\n            };\n        }\n\n        private static ITensorAccessors GetUIntAsByte(long[] delta)\n        {\n            return new TensorAccessors<uint, byte>()\n            {\n                Getter = (da, i) => Col.UIntToByte(da[i]),\n                Setter = (da, i, v) => da[i] = Col.ByteToUInt(v),\n            };\n        }\n\n        private static ITensorAccessors GetUIntAsUShort(long[] delta)\n        {\n            return new TensorAccessors<uint, ushort>()\n            {\n                Getter = (da, i) => Col.UIntToUShort(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UShortToUInt(v),\n            };\n        }\n\n        private static ITensorAccessors GetUIntAsUInt(long[] delta)\n        {\n            return new TensorAccessors<uint, uint>()\n            {\n                Getter = (da, i) => (da[i]),\n                Setter = (da, i, v) => da[i] = (v),\n            };\n        }\n\n        private static ITensorAccessors GetUIntAsHalf(long[] delta)\n        {\n            return new TensorAccessors<uint, Half>()\n            {\n                Getter = (da, i) => Col.UIntToHalf(da[i]),\n                Setter = (da, i, v) => da[i] = Col.HalfToUInt(v),\n            };\n        }\n\n        private static ITensorAccessors GetUIntAsFloat(long[] delta)\n        {\n            return new TensorAccessors<uint, float>()\n            {\n                Getter = (da, i) => Col.UIntToFloat(da[i]),\n                Setter = (da, i, v) => da[i] = Col.FloatToUInt(v),\n            };\n        }\n\n        private static ITensorAccessors GetUIntAsDouble(long[] delta)\n        {\n            return new TensorAccessors<uint, double>()\n            {\n                Getter = (da, i) => Col.UIntToDouble(da[i]),\n                Setter = (da, i, v) => da[i] = Col.DoubleToUInt(v),\n            };\n        }\n\n        private static ITensorAccessors GetHalfAsByte(long[] delta)\n        {\n            return new TensorAccessors<Half, byte>()\n            {\n                Getter = (da, i) => Col.HalfToByte(da[i]),\n                Setter = (da, i, v) => da[i] = Col.ByteToHalf(v),\n            };\n        }\n\n        private static ITensorAccessors GetHalfAsUShort(long[] delta)\n        {\n            return new TensorAccessors<Half, ushort>()\n            {\n                Getter = (da, i) => Col.HalfToUShort(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UShortToHalf(v),\n            };\n        }\n\n        private static ITensorAccessors GetHalfAsUInt(long[] delta)\n        {\n            return new TensorAccessors<Half, uint>()\n            {\n                Getter = (da, i) => Col.HalfToUInt(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UIntToHalf(v),\n            };\n        }\n\n        private static ITensorAccessors GetHalfAsHalf(long[] delta)\n        {\n            return new TensorAccessors<Half, Half>()\n            {\n                Getter = (da, i) => (da[i]),\n                Setter = (da, i, v) => da[i] = (v),\n            };\n        }\n\n        private static ITensorAccessors GetHalfAsFloat(long[] delta)\n        {\n            return new TensorAccessors<Half, float>()\n            {\n                Getter = (da, i) => Col.HalfToFloat(da[i]),\n                Setter = (da, i, v) => da[i] = Col.FloatToHalf(v),\n            };\n        }\n\n        private static ITensorAccessors GetHalfAsDouble(long[] delta)\n        {\n            return new TensorAccessors<Half, double>()\n            {\n                Getter = (da, i) => Col.HalfToDouble(da[i]),\n                Setter = (da, i, v) => da[i] = Col.DoubleToHalf(v),\n            };\n        }\n\n        private static ITensorAccessors GetFloatAsByte(long[] delta)\n        {\n            return new TensorAccessors<float, byte>()\n            {\n                Getter = (da, i) => Col.FloatToByte(da[i]),\n                Setter = (da, i, v) => da[i] = Col.ByteToFloat(v),\n            };\n        }\n\n        private static ITensorAccessors GetFloatAsUShort(long[] delta)\n        {\n            return new TensorAccessors<float, ushort>()\n            {\n                Getter = (da, i) => Col.FloatToUShort(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UShortToFloat(v),\n            };\n        }\n\n        private static ITensorAccessors GetFloatAsUInt(long[] delta)\n        {\n            return new TensorAccessors<float, uint>()\n            {\n                Getter = (da, i) => Col.FloatToUInt(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UIntToFloat(v),\n            };\n        }\n\n        private static ITensorAccessors GetFloatAsHalf(long[] delta)\n        {\n            return new TensorAccessors<float, Half>()\n            {\n                Getter = (da, i) => Col.FloatToHalf(da[i]),\n                Setter = (da, i, v) => da[i] = Col.HalfToFloat(v),\n            };\n        }\n\n        private static ITensorAccessors GetFloatAsFloat(long[] delta)\n        {\n            return new TensorAccessors<float, float>()\n            {\n                Getter = (da, i) => (da[i]),\n                Setter = (da, i, v) => da[i] = (v),\n            };\n        }\n\n        private static ITensorAccessors GetFloatAsDouble(long[] delta)\n        {\n            return new TensorAccessors<float, double>()\n            {\n                Getter = (da, i) => Col.FloatToDouble(da[i]),\n                Setter = (da, i, v) => da[i] = Col.DoubleToFloat(v),\n            };\n        }\n\n        private static ITensorAccessors GetDoubleAsByte(long[] delta)\n        {\n            return new TensorAccessors<double, byte>()\n            {\n                Getter = (da, i) => Col.DoubleToByte(da[i]),\n                Setter = (da, i, v) => da[i] = Col.ByteToDouble(v),\n            };\n        }\n\n        private static ITensorAccessors GetDoubleAsUShort(long[] delta)\n        {\n            return new TensorAccessors<double, ushort>()\n            {\n                Getter = (da, i) => Col.DoubleToUShort(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UShortToDouble(v),\n            };\n        }\n\n        private static ITensorAccessors GetDoubleAsUInt(long[] delta)\n        {\n            return new TensorAccessors<double, uint>()\n            {\n                Getter = (da, i) => Col.DoubleToUInt(da[i]),\n                Setter = (da, i, v) => da[i] = Col.UIntToDouble(v),\n            };\n        }\n\n        private static ITensorAccessors GetDoubleAsHalf(long[] delta)\n        {\n            return new TensorAccessors<double, Half>()\n            {\n                Getter = (da, i) => Col.DoubleToHalf(da[i]),\n                Setter = (da, i, v) => da[i] = Col.HalfToDouble(v),\n            };\n        }\n\n        private static ITensorAccessors GetDoubleAsFloat(long[] delta)\n        {\n            return new TensorAccessors<double, float>()\n            {\n                Getter = (da, i) => Col.DoubleToFloat(da[i]),\n                Setter = (da, i, v) => da[i] = Col.FloatToDouble(v),\n            };\n        }\n\n        private static ITensorAccessors GetDoubleAsDouble(long[] delta)\n        {\n            return new TensorAccessors<double, double>()\n            {\n                Getter = (da, i) => (da[i]),\n                Setter = (da, i, v) => da[i] = (v),\n            };\n        }\n\n        #endregion\n\n        private static readonly Dictionary<(Type, Type, Symbol),\n                                           Func<long[], ITensorAccessors>> s_creatorMap\n            = new Dictionary<(Type, Type, Symbol),\n                             Func<long[], ITensorAccessors>>()\n            {\n                #region Single channel byte as byte\n\n                { (typeof(byte), typeof(byte), Intent.ColorChannel), GetByteAsByte },\n                { (typeof(byte), typeof(byte), Intent.BW), GetByteAsByte },\n                { (typeof(byte), typeof(byte), Intent.Gray), GetByteAsByte },\n                { (typeof(byte), typeof(byte), Intent.Alpha), GetByteAsByte },\n\n                #endregion\n\n                #region Single channel byte as ushort\n\n                { (typeof(byte), typeof(ushort), Intent.ColorChannel), GetByteAsUShort },\n                { (typeof(byte), typeof(ushort), Intent.BW), GetByteAsUShort },\n                { (typeof(byte), typeof(ushort), Intent.Gray), GetByteAsUShort },\n                { (typeof(byte), typeof(ushort), Intent.Alpha), GetByteAsUShort },\n\n                #endregion\n\n                #region Single channel byte as uint\n\n                { (typeof(byte), typeof(uint), Intent.ColorChannel), GetByteAsUInt },\n                { (typeof(byte), typeof(uint), Intent.BW), GetByteAsUInt },\n                { (typeof(byte), typeof(uint), Intent.Gray), GetByteAsUInt },\n                { (typeof(byte), typeof(uint), Intent.Alpha), GetByteAsUInt },\n\n                #endregion\n\n                #region Single channel byte as Half\n\n                { (typeof(byte), typeof(Half), Intent.ColorChannel), GetByteAsHalf },\n                { (typeof(byte), typeof(Half), Intent.BW), GetByteAsHalf },\n                { (typeof(byte), typeof(Half), Intent.Gray), GetByteAsHalf },\n                { (typeof(byte), typeof(Half), Intent.Alpha), GetByteAsHalf },\n\n                #endregion\n\n                #region Single channel byte as float\n\n                { (typeof(byte), typeof(float), Intent.ColorChannel), GetByteAsFloat },\n                { (typeof(byte), typeof(float), Intent.BW), GetByteAsFloat },\n                { (typeof(byte), typeof(float), Intent.Gray), GetByteAsFloat },\n                { (typeof(byte), typeof(float), Intent.Alpha), GetByteAsFloat },\n\n                #endregion\n\n                #region Single channel byte as double\n\n                { (typeof(byte), typeof(double), Intent.ColorChannel), GetByteAsDouble },\n                { (typeof(byte), typeof(double), Intent.BW), GetByteAsDouble },\n                { (typeof(byte), typeof(double), Intent.Gray), GetByteAsDouble },\n                { (typeof(byte), typeof(double), Intent.Alpha), GetByteAsDouble },\n\n                #endregion\n\n                #region Single channel ushort as byte\n\n                { (typeof(ushort), typeof(byte), Intent.ColorChannel), GetUShortAsByte },\n                { (typeof(ushort), typeof(byte), Intent.BW), GetUShortAsByte },\n                { (typeof(ushort), typeof(byte), Intent.Gray), GetUShortAsByte },\n                { (typeof(ushort), typeof(byte), Intent.Alpha), GetUShortAsByte },\n\n                #endregion\n\n                #region Single channel ushort as ushort\n\n                { (typeof(ushort), typeof(ushort), Intent.ColorChannel), GetUShortAsUShort },\n                { (typeof(ushort), typeof(ushort), Intent.BW), GetUShortAsUShort },\n                { (typeof(ushort), typeof(ushort), Intent.Gray), GetUShortAsUShort },\n                { (typeof(ushort), typeof(ushort), Intent.Alpha), GetUShortAsUShort },\n\n                #endregion\n\n                #region Single channel ushort as uint\n\n                { (typeof(ushort), typeof(uint), Intent.ColorChannel), GetUShortAsUInt },\n                { (typeof(ushort), typeof(uint), Intent.BW), GetUShortAsUInt },\n                { (typeof(ushort), typeof(uint), Intent.Gray), GetUShortAsUInt },\n                { (typeof(ushort), typeof(uint), Intent.Alpha), GetUShortAsUInt },\n\n                #endregion\n\n                #region Single channel ushort as Half\n\n                { (typeof(ushort), typeof(Half), Intent.ColorChannel), GetUShortAsHalf },\n                { (typeof(ushort), typeof(Half), Intent.BW), GetUShortAsHalf },\n                { (typeof(ushort), typeof(Half), Intent.Gray), GetUShortAsHalf },\n                { (typeof(ushort), typeof(Half), Intent.Alpha), GetUShortAsHalf },\n\n                #endregion\n\n                #region Single channel ushort as float\n\n                { (typeof(ushort), typeof(float), Intent.ColorChannel), GetUShortAsFloat },\n                { (typeof(ushort), typeof(float), Intent.BW), GetUShortAsFloat },\n                { (typeof(ushort), typeof(float), Intent.Gray), GetUShortAsFloat },\n                { (typeof(ushort), typeof(float), Intent.Alpha), GetUShortAsFloat },\n\n                #endregion\n\n                #region Single channel ushort as double\n\n                { (typeof(ushort), typeof(double), Intent.ColorChannel), GetUShortAsDouble },\n                { (typeof(ushort), typeof(double), Intent.BW), GetUShortAsDouble },\n                { (typeof(ushort), typeof(double), Intent.Gray), GetUShortAsDouble },\n                { (typeof(ushort), typeof(double), Intent.Alpha), GetUShortAsDouble },\n\n                #endregion\n\n                #region Single channel uint as byte\n\n                { (typeof(uint), typeof(byte), Intent.ColorChannel), GetUIntAsByte },\n                { (typeof(uint), typeof(byte), Intent.BW), GetUIntAsByte },\n                { (typeof(uint), typeof(byte), Intent.Gray), GetUIntAsByte },\n                { (typeof(uint), typeof(byte), Intent.Alpha), GetUIntAsByte },\n\n                #endregion\n\n                #region Single channel uint as ushort\n\n                { (typeof(uint), typeof(ushort), Intent.ColorChannel), GetUIntAsUShort },\n                { (typeof(uint), typeof(ushort), Intent.BW), GetUIntAsUShort },\n                { (typeof(uint), typeof(ushort), Intent.Gray), GetUIntAsUShort },\n                { (typeof(uint), typeof(ushort), Intent.Alpha), GetUIntAsUShort },\n\n                #endregion\n\n                #region Single channel uint as uint\n\n                { (typeof(uint), typeof(uint), Intent.ColorChannel), GetUIntAsUInt },\n                { (typeof(uint), typeof(uint), Intent.BW), GetUIntAsUInt },\n                { (typeof(uint), typeof(uint), Intent.Gray), GetUIntAsUInt },\n                { (typeof(uint), typeof(uint), Intent.Alpha), GetUIntAsUInt },\n\n                #endregion\n\n                #region Single channel uint as Half\n\n                { (typeof(uint), typeof(Half), Intent.ColorChannel), GetUIntAsHalf },\n                { (typeof(uint), typeof(Half), Intent.BW), GetUIntAsHalf },\n                { (typeof(uint), typeof(Half), Intent.Gray), GetUIntAsHalf },\n                { (typeof(uint), typeof(Half), Intent.Alpha), GetUIntAsHalf },\n\n                #endregion\n\n                #region Single channel uint as float\n\n                { (typeof(uint), typeof(float), Intent.ColorChannel), GetUIntAsFloat },\n                { (typeof(uint), typeof(float), Intent.BW), GetUIntAsFloat },\n                { (typeof(uint), typeof(float), Intent.Gray), GetUIntAsFloat },\n                { (typeof(uint), typeof(float), Intent.Alpha), GetUIntAsFloat },\n\n                #endregion\n\n                #region Single channel uint as double\n\n                { (typeof(uint), typeof(double), Intent.ColorChannel), GetUIntAsDouble },\n                { (typeof(uint), typeof(double), Intent.BW), GetUIntAsDouble },\n                { (typeof(uint), typeof(double), Intent.Gray), GetUIntAsDouble },\n                { (typeof(uint), typeof(double), Intent.Alpha), GetUIntAsDouble },\n\n                #endregion\n\n                #region Single channel Half as byte\n\n                { (typeof(Half), typeof(byte), Intent.ColorChannel), GetHalfAsByte },\n                { (typeof(Half), typeof(byte), Intent.BW), GetHalfAsByte },\n                { (typeof(Half), typeof(byte), Intent.Gray), GetHalfAsByte },\n                { (typeof(Half), typeof(byte), Intent.Alpha), GetHalfAsByte },\n\n                #endregion\n\n                #region Single channel Half as ushort\n\n                { (typeof(Half), typeof(ushort), Intent.ColorChannel), GetHalfAsUShort },\n                { (typeof(Half), typeof(ushort), Intent.BW), GetHalfAsUShort },\n                { (typeof(Half), typeof(ushort), Intent.Gray), GetHalfAsUShort },\n                { (typeof(Half), typeof(ushort), Intent.Alpha), GetHalfAsUShort },\n\n                #endregion\n\n                #region Single channel Half as uint\n\n                { (typeof(Half), typeof(uint), Intent.ColorChannel), GetHalfAsUInt },\n                { (typeof(Half), typeof(uint), Intent.BW), GetHalfAsUInt },\n                { (typeof(Half), typeof(uint), Intent.Gray), GetHalfAsUInt },\n                { (typeof(Half), typeof(uint), Intent.Alpha), GetHalfAsUInt },\n\n                #endregion\n\n                #region Single channel Half as Half\n\n                { (typeof(Half), typeof(Half), Intent.ColorChannel), GetHalfAsHalf },\n                { (typeof(Half), typeof(Half), Intent.BW), GetHalfAsHalf },\n                { (typeof(Half), typeof(Half), Intent.Gray), GetHalfAsHalf },\n                { (typeof(Half), typeof(Half), Intent.Alpha), GetHalfAsHalf },\n\n                #endregion\n\n                #region Single channel Half as float\n\n                { (typeof(Half), typeof(float), Intent.ColorChannel), GetHalfAsFloat },\n                { (typeof(Half), typeof(float), Intent.BW), GetHalfAsFloat },\n                { (typeof(Half), typeof(float), Intent.Gray), GetHalfAsFloat },\n                { (typeof(Half), typeof(float), Intent.Alpha), GetHalfAsFloat },\n\n                #endregion\n\n                #region Single channel Half as double\n\n                { (typeof(Half), typeof(double), Intent.ColorChannel), GetHalfAsDouble },\n                { (typeof(Half), typeof(double), Intent.BW), GetHalfAsDouble },\n                { (typeof(Half), typeof(double), Intent.Gray), GetHalfAsDouble },\n                { (typeof(Half), typeof(double), Intent.Alpha), GetHalfAsDouble },\n\n                #endregion\n\n                #region Single channel float as byte\n\n                { (typeof(float), typeof(byte), Intent.ColorChannel), GetFloatAsByte },\n                { (typeof(float), typeof(byte), Intent.BW), GetFloatAsByte },\n                { (typeof(float), typeof(byte), Intent.Gray), GetFloatAsByte },\n                { (typeof(float), typeof(byte), Intent.Alpha), GetFloatAsByte },\n\n                #endregion\n\n                #region Single channel float as ushort\n\n                { (typeof(float), typeof(ushort), Intent.ColorChannel), GetFloatAsUShort },\n                { (typeof(float), typeof(ushort), Intent.BW), GetFloatAsUShort },\n                { (typeof(float), typeof(ushort), Intent.Gray), GetFloatAsUShort },\n                { (typeof(float), typeof(ushort), Intent.Alpha), GetFloatAsUShort },\n\n                #endregion\n\n                #region Single channel float as uint\n\n                { (typeof(float), typeof(uint), Intent.ColorChannel), GetFloatAsUInt },\n                { (typeof(float), typeof(uint), Intent.BW), GetFloatAsUInt },\n                { (typeof(float), typeof(uint), Intent.Gray), GetFloatAsUInt },\n                { (typeof(float), typeof(uint), Intent.Alpha), GetFloatAsUInt },\n\n                #endregion\n\n                #region Single channel float as Half\n\n                { (typeof(float), typeof(Half), Intent.ColorChannel), GetFloatAsHalf },\n                { (typeof(float), typeof(Half), Intent.BW), GetFloatAsHalf },\n                { (typeof(float), typeof(Half), Intent.Gray), GetFloatAsHalf },\n                { (typeof(float), typeof(Half), Intent.Alpha), GetFloatAsHalf },\n\n                #endregion\n\n                #region Single channel float as float\n\n                { (typeof(float), typeof(float), Intent.ColorChannel), GetFloatAsFloat },\n                { (typeof(float), typeof(float), Intent.BW), GetFloatAsFloat },\n                { (typeof(float), typeof(float), Intent.Gray), GetFloatAsFloat },\n                { (typeof(float), typeof(float), Intent.Alpha), GetFloatAsFloat },\n\n                #endregion\n\n                #region Single channel float as double\n\n                { (typeof(float), typeof(double), Intent.ColorChannel), GetFloatAsDouble },\n                { (typeof(float), typeof(double), Intent.BW), GetFloatAsDouble },\n                { (typeof(float), typeof(double), Intent.Gray), GetFloatAsDouble },\n                { (typeof(float), typeof(double), Intent.Alpha), GetFloatAsDouble },\n\n                #endregion\n\n                #region Single channel double as byte\n\n                { (typeof(double), typeof(byte), Intent.ColorChannel), GetDoubleAsByte },\n                { (typeof(double), typeof(byte), Intent.BW), GetDoubleAsByte },\n                { (typeof(double), typeof(byte), Intent.Gray), GetDoubleAsByte },\n                { (typeof(double), typeof(byte), Intent.Alpha), GetDoubleAsByte },\n\n                #endregion\n\n                #region Single channel double as ushort\n\n                { (typeof(double), typeof(ushort), Intent.ColorChannel), GetDoubleAsUShort },\n                { (typeof(double), typeof(ushort), Intent.BW), GetDoubleAsUShort },\n                { (typeof(double), typeof(ushort), Intent.Gray), GetDoubleAsUShort },\n                { (typeof(double), typeof(ushort), Intent.Alpha), GetDoubleAsUShort },\n\n                #endregion\n\n                #region Single channel double as uint\n\n                { (typeof(double), typeof(uint), Intent.ColorChannel), GetDoubleAsUInt },\n                { (typeof(double), typeof(uint), Intent.BW), GetDoubleAsUInt },\n                { (typeof(double), typeof(uint), Intent.Gray), GetDoubleAsUInt },\n                { (typeof(double), typeof(uint), Intent.Alpha), GetDoubleAsUInt },\n\n                #endregion\n\n                #region Single channel double as Half\n\n                { (typeof(double), typeof(Half), Intent.ColorChannel), GetDoubleAsHalf },\n                { (typeof(double), typeof(Half), Intent.BW), GetDoubleAsHalf },\n                { (typeof(double), typeof(Half), Intent.Gray), GetDoubleAsHalf },\n                { (typeof(double), typeof(Half), Intent.Alpha), GetDoubleAsHalf },\n\n                #endregion\n\n                #region Single channel double as float\n\n                { (typeof(double), typeof(float), Intent.ColorChannel), GetDoubleAsFloat },\n                { (typeof(double), typeof(float), Intent.BW), GetDoubleAsFloat },\n                { (typeof(double), typeof(float), Intent.Gray), GetDoubleAsFloat },\n                { (typeof(double), typeof(float), Intent.Alpha), GetDoubleAsFloat },\n\n                #endregion\n\n                #region Single channel double as double\n\n                { (typeof(double), typeof(double), Intent.ColorChannel), GetDoubleAsDouble },\n                { (typeof(double), typeof(double), Intent.BW), GetDoubleAsDouble },\n                { (typeof(double), typeof(double), Intent.Gray), GetDoubleAsDouble },\n                { (typeof(double), typeof(double), Intent.Alpha), GetDoubleAsDouble },\n\n                #endregion\n\n                #region RGB bytes as C3b\n\n                {\n                    (typeof(byte), typeof(C3b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C3b\n\n                {\n                    (typeof(byte), typeof(C3b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C3b\n\n                {\n                    (typeof(byte), typeof(C3b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C3b\n\n                {\n                    (typeof(byte), typeof(C3b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C3us\n\n                {\n                    (typeof(byte), typeof(C3us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+1]), \n                                            Col.ByteToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.R);\n                                    da[i+1] = Col.UShortToByte(v.G);\n                                    da[i+2] = Col.UShortToByte(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+d1]), \n                                            Col.ByteToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.R);\n                                    da[i+d1] = Col.UShortToByte(v.G);\n                                    da[i+d2] = Col.UShortToByte(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C3us\n\n                {\n                    (typeof(byte), typeof(C3us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.ByteToUShort(da[i+2]), \n                                            Col.ByteToUShort(da[i+1]), \n                                            Col.ByteToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.B);\n                                    da[i+1] = Col.UShortToByte(v.G);\n                                    da[i+2] = Col.UShortToByte(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.ByteToUShort(da[i+d2]), \n                                            Col.ByteToUShort(da[i+d1]), \n                                            Col.ByteToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.B);\n                                    da[i+d1] = Col.UShortToByte(v.G);\n                                    da[i+d2] = Col.UShortToByte(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C3us\n\n                {\n                    (typeof(byte), typeof(C3us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+1]), \n                                            Col.ByteToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.R);\n                                    da[i+1] = Col.UShortToByte(v.G);\n                                    da[i+2] = Col.UShortToByte(v.B);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+d1]), \n                                            Col.ByteToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.R);\n                                    da[i+d1] = Col.UShortToByte(v.G);\n                                    da[i+d2] = Col.UShortToByte(v.B);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C3us\n\n                {\n                    (typeof(byte), typeof(C3us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.ByteToUShort(da[i+2]), \n                                            Col.ByteToUShort(da[i+1]), \n                                            Col.ByteToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.B);\n                                    da[i+1] = Col.UShortToByte(v.G);\n                                    da[i+2] = Col.UShortToByte(v.R);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.ByteToUShort(da[i+d2]), \n                                            Col.ByteToUShort(da[i+d1]), \n                                            Col.ByteToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.B);\n                                    da[i+d1] = Col.UShortToByte(v.G);\n                                    da[i+d2] = Col.UShortToByte(v.R);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C3ui\n\n                {\n                    (typeof(byte), typeof(C3ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+1]), \n                                            Col.ByteToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.R);\n                                    da[i+1] = Col.UIntToByte(v.G);\n                                    da[i+2] = Col.UIntToByte(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+d1]), \n                                            Col.ByteToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.R);\n                                    da[i+d1] = Col.UIntToByte(v.G);\n                                    da[i+d2] = Col.UIntToByte(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C3ui\n\n                {\n                    (typeof(byte), typeof(C3ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.ByteToUInt(da[i+2]), \n                                            Col.ByteToUInt(da[i+1]), \n                                            Col.ByteToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.B);\n                                    da[i+1] = Col.UIntToByte(v.G);\n                                    da[i+2] = Col.UIntToByte(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.ByteToUInt(da[i+d2]), \n                                            Col.ByteToUInt(da[i+d1]), \n                                            Col.ByteToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.B);\n                                    da[i+d1] = Col.UIntToByte(v.G);\n                                    da[i+d2] = Col.UIntToByte(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C3ui\n\n                {\n                    (typeof(byte), typeof(C3ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+1]), \n                                            Col.ByteToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.R);\n                                    da[i+1] = Col.UIntToByte(v.G);\n                                    da[i+2] = Col.UIntToByte(v.B);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+d1]), \n                                            Col.ByteToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.R);\n                                    da[i+d1] = Col.UIntToByte(v.G);\n                                    da[i+d2] = Col.UIntToByte(v.B);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C3ui\n\n                {\n                    (typeof(byte), typeof(C3ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.ByteToUInt(da[i+2]), \n                                            Col.ByteToUInt(da[i+1]), \n                                            Col.ByteToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.B);\n                                    da[i+1] = Col.UIntToByte(v.G);\n                                    da[i+2] = Col.UIntToByte(v.R);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.ByteToUInt(da[i+d2]), \n                                            Col.ByteToUInt(da[i+d1]), \n                                            Col.ByteToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.B);\n                                    da[i+d1] = Col.UIntToByte(v.G);\n                                    da[i+d2] = Col.UIntToByte(v.R);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C3f\n\n                {\n                    (typeof(byte), typeof(C3f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+1]), \n                                            Col.ByteToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.R);\n                                    da[i+1] = Col.FloatToByte(v.G);\n                                    da[i+2] = Col.FloatToByte(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+d1]), \n                                            Col.ByteToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.R);\n                                    da[i+d1] = Col.FloatToByte(v.G);\n                                    da[i+d2] = Col.FloatToByte(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C3f\n\n                {\n                    (typeof(byte), typeof(C3f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.ByteToFloat(da[i+2]), \n                                            Col.ByteToFloat(da[i+1]), \n                                            Col.ByteToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.B);\n                                    da[i+1] = Col.FloatToByte(v.G);\n                                    da[i+2] = Col.FloatToByte(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.ByteToFloat(da[i+d2]), \n                                            Col.ByteToFloat(da[i+d1]), \n                                            Col.ByteToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.B);\n                                    da[i+d1] = Col.FloatToByte(v.G);\n                                    da[i+d2] = Col.FloatToByte(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C3f\n\n                {\n                    (typeof(byte), typeof(C3f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+1]), \n                                            Col.ByteToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.R);\n                                    da[i+1] = Col.FloatToByte(v.G);\n                                    da[i+2] = Col.FloatToByte(v.B);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+d1]), \n                                            Col.ByteToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.R);\n                                    da[i+d1] = Col.FloatToByte(v.G);\n                                    da[i+d2] = Col.FloatToByte(v.B);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C3f\n\n                {\n                    (typeof(byte), typeof(C3f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.ByteToFloat(da[i+2]), \n                                            Col.ByteToFloat(da[i+1]), \n                                            Col.ByteToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.B);\n                                    da[i+1] = Col.FloatToByte(v.G);\n                                    da[i+2] = Col.FloatToByte(v.R);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.ByteToFloat(da[i+d2]), \n                                            Col.ByteToFloat(da[i+d1]), \n                                            Col.ByteToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.B);\n                                    da[i+d1] = Col.FloatToByte(v.G);\n                                    da[i+d2] = Col.FloatToByte(v.R);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C3d\n\n                {\n                    (typeof(byte), typeof(C3d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+1]), \n                                            Col.ByteToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.R);\n                                    da[i+1] = Col.DoubleToByte(v.G);\n                                    da[i+2] = Col.DoubleToByte(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+d1]), \n                                            Col.ByteToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.R);\n                                    da[i+d1] = Col.DoubleToByte(v.G);\n                                    da[i+d2] = Col.DoubleToByte(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C3d\n\n                {\n                    (typeof(byte), typeof(C3d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.ByteToDouble(da[i+2]), \n                                            Col.ByteToDouble(da[i+1]), \n                                            Col.ByteToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.B);\n                                    da[i+1] = Col.DoubleToByte(v.G);\n                                    da[i+2] = Col.DoubleToByte(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.ByteToDouble(da[i+d2]), \n                                            Col.ByteToDouble(da[i+d1]), \n                                            Col.ByteToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.B);\n                                    da[i+d1] = Col.DoubleToByte(v.G);\n                                    da[i+d2] = Col.DoubleToByte(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C3d\n\n                {\n                    (typeof(byte), typeof(C3d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+1]), \n                                            Col.ByteToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.R);\n                                    da[i+1] = Col.DoubleToByte(v.G);\n                                    da[i+2] = Col.DoubleToByte(v.B);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+d1]), \n                                            Col.ByteToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.R);\n                                    da[i+d1] = Col.DoubleToByte(v.G);\n                                    da[i+d2] = Col.DoubleToByte(v.B);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C3d\n\n                {\n                    (typeof(byte), typeof(C3d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.ByteToDouble(da[i+2]), \n                                            Col.ByteToDouble(da[i+1]), \n                                            Col.ByteToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.B);\n                                    da[i+1] = Col.DoubleToByte(v.G);\n                                    da[i+2] = Col.DoubleToByte(v.R);\n                                    da[i+3] = (byte)255;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.ByteToDouble(da[i+d2]), \n                                            Col.ByteToDouble(da[i+d1]), \n                                            Col.ByteToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.B);\n                                    da[i+d1] = Col.DoubleToByte(v.G);\n                                    da[i+d2] = Col.DoubleToByte(v.R);\n                                    da[i+d3] = (byte)255;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C4b\n\n                {\n                    (typeof(byte), typeof(C4b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C4b\n\n                {\n                    (typeof(byte), typeof(C4b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C4b\n\n                {\n                    (typeof(byte), typeof(C4b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C4b\n\n                {\n                    (typeof(byte), typeof(C4b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C4us\n\n                {\n                    (typeof(byte), typeof(C4us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+1]), \n                                            Col.ByteToUShort(da[i+2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.R);\n                                    da[i+1] = Col.UShortToByte(v.G);\n                                    da[i+2] = Col.UShortToByte(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+d1]), \n                                            Col.ByteToUShort(da[i+d2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.R);\n                                    da[i+d1] = Col.UShortToByte(v.G);\n                                    da[i+d2] = Col.UShortToByte(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C4us\n\n                {\n                    (typeof(byte), typeof(C4us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.ByteToUShort(da[i+2]), \n                                            Col.ByteToUShort(da[i+1]), \n                                            Col.ByteToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.B);\n                                    da[i+1] = Col.UShortToByte(v.G);\n                                    da[i+2] = Col.UShortToByte(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.ByteToUShort(da[i+d2]), \n                                            Col.ByteToUShort(da[i+d1]), \n                                            Col.ByteToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.B);\n                                    da[i+d1] = Col.UShortToByte(v.G);\n                                    da[i+d2] = Col.UShortToByte(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C4us\n\n                {\n                    (typeof(byte), typeof(C4us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+1]), \n                                            Col.ByteToUShort(da[i+2]), \n                                            Col.ByteToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.R);\n                                    da[i+1] = Col.UShortToByte(v.G);\n                                    da[i+2] = Col.UShortToByte(v.B);\n                                    da[i+3] = Col.UShortToByte(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+d1]), \n                                            Col.ByteToUShort(da[i+d2]), \n                                            Col.ByteToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.R);\n                                    da[i+d1] = Col.UShortToByte(v.G);\n                                    da[i+d2] = Col.UShortToByte(v.B);\n                                    da[i+d3] = Col.UShortToByte(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C4us\n\n                {\n                    (typeof(byte), typeof(C4us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.ByteToUShort(da[i+2]), \n                                            Col.ByteToUShort(da[i+1]), \n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.B);\n                                    da[i+1] = Col.UShortToByte(v.G);\n                                    da[i+2] = Col.UShortToByte(v.R);\n                                    da[i+3] = Col.UShortToByte(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.ByteToUShort(da[i+d2]), \n                                            Col.ByteToUShort(da[i+d1]), \n                                            Col.ByteToUShort(da[i]), \n                                            Col.ByteToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToByte(v.B);\n                                    da[i+d1] = Col.UShortToByte(v.G);\n                                    da[i+d2] = Col.UShortToByte(v.R);\n                                    da[i+d3] = Col.UShortToByte(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C4ui\n\n                {\n                    (typeof(byte), typeof(C4ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+1]), \n                                            Col.ByteToUInt(da[i+2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.R);\n                                    da[i+1] = Col.UIntToByte(v.G);\n                                    da[i+2] = Col.UIntToByte(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+d1]), \n                                            Col.ByteToUInt(da[i+d2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.R);\n                                    da[i+d1] = Col.UIntToByte(v.G);\n                                    da[i+d2] = Col.UIntToByte(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C4ui\n\n                {\n                    (typeof(byte), typeof(C4ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.ByteToUInt(da[i+2]), \n                                            Col.ByteToUInt(da[i+1]), \n                                            Col.ByteToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.B);\n                                    da[i+1] = Col.UIntToByte(v.G);\n                                    da[i+2] = Col.UIntToByte(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.ByteToUInt(da[i+d2]), \n                                            Col.ByteToUInt(da[i+d1]), \n                                            Col.ByteToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.B);\n                                    da[i+d1] = Col.UIntToByte(v.G);\n                                    da[i+d2] = Col.UIntToByte(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C4ui\n\n                {\n                    (typeof(byte), typeof(C4ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+1]), \n                                            Col.ByteToUInt(da[i+2]), \n                                            Col.ByteToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.R);\n                                    da[i+1] = Col.UIntToByte(v.G);\n                                    da[i+2] = Col.UIntToByte(v.B);\n                                    da[i+3] = Col.UIntToByte(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+d1]), \n                                            Col.ByteToUInt(da[i+d2]), \n                                            Col.ByteToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.R);\n                                    da[i+d1] = Col.UIntToByte(v.G);\n                                    da[i+d2] = Col.UIntToByte(v.B);\n                                    da[i+d3] = Col.UIntToByte(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C4ui\n\n                {\n                    (typeof(byte), typeof(C4ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.ByteToUInt(da[i+2]), \n                                            Col.ByteToUInt(da[i+1]), \n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.B);\n                                    da[i+1] = Col.UIntToByte(v.G);\n                                    da[i+2] = Col.UIntToByte(v.R);\n                                    da[i+3] = Col.UIntToByte(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.ByteToUInt(da[i+d2]), \n                                            Col.ByteToUInt(da[i+d1]), \n                                            Col.ByteToUInt(da[i]), \n                                            Col.ByteToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToByte(v.B);\n                                    da[i+d1] = Col.UIntToByte(v.G);\n                                    da[i+d2] = Col.UIntToByte(v.R);\n                                    da[i+d3] = Col.UIntToByte(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C4f\n\n                {\n                    (typeof(byte), typeof(C4f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+1]), \n                                            Col.ByteToFloat(da[i+2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.R);\n                                    da[i+1] = Col.FloatToByte(v.G);\n                                    da[i+2] = Col.FloatToByte(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+d1]), \n                                            Col.ByteToFloat(da[i+d2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.R);\n                                    da[i+d1] = Col.FloatToByte(v.G);\n                                    da[i+d2] = Col.FloatToByte(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C4f\n\n                {\n                    (typeof(byte), typeof(C4f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.ByteToFloat(da[i+2]), \n                                            Col.ByteToFloat(da[i+1]), \n                                            Col.ByteToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.B);\n                                    da[i+1] = Col.FloatToByte(v.G);\n                                    da[i+2] = Col.FloatToByte(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.ByteToFloat(da[i+d2]), \n                                            Col.ByteToFloat(da[i+d1]), \n                                            Col.ByteToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.B);\n                                    da[i+d1] = Col.FloatToByte(v.G);\n                                    da[i+d2] = Col.FloatToByte(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C4f\n\n                {\n                    (typeof(byte), typeof(C4f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+1]), \n                                            Col.ByteToFloat(da[i+2]), \n                                            Col.ByteToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.R);\n                                    da[i+1] = Col.FloatToByte(v.G);\n                                    da[i+2] = Col.FloatToByte(v.B);\n                                    da[i+3] = Col.FloatToByte(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+d1]), \n                                            Col.ByteToFloat(da[i+d2]), \n                                            Col.ByteToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.R);\n                                    da[i+d1] = Col.FloatToByte(v.G);\n                                    da[i+d2] = Col.FloatToByte(v.B);\n                                    da[i+d3] = Col.FloatToByte(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C4f\n\n                {\n                    (typeof(byte), typeof(C4f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.ByteToFloat(da[i+2]), \n                                            Col.ByteToFloat(da[i+1]), \n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.B);\n                                    da[i+1] = Col.FloatToByte(v.G);\n                                    da[i+2] = Col.FloatToByte(v.R);\n                                    da[i+3] = Col.FloatToByte(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.ByteToFloat(da[i+d2]), \n                                            Col.ByteToFloat(da[i+d1]), \n                                            Col.ByteToFloat(da[i]), \n                                            Col.ByteToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToByte(v.B);\n                                    da[i+d1] = Col.FloatToByte(v.G);\n                                    da[i+d2] = Col.FloatToByte(v.R);\n                                    da[i+d3] = Col.FloatToByte(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB bytes as C4d\n\n                {\n                    (typeof(byte), typeof(C4d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+1]), \n                                            Col.ByteToDouble(da[i+2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.R);\n                                    da[i+1] = Col.DoubleToByte(v.G);\n                                    da[i+2] = Col.DoubleToByte(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+d1]), \n                                            Col.ByteToDouble(da[i+d2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.R);\n                                    da[i+d1] = Col.DoubleToByte(v.G);\n                                    da[i+d2] = Col.DoubleToByte(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR bytes as C4d\n\n                {\n                    (typeof(byte), typeof(C4d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.ByteToDouble(da[i+2]), \n                                            Col.ByteToDouble(da[i+1]), \n                                            Col.ByteToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.B);\n                                    da[i+1] = Col.DoubleToByte(v.G);\n                                    da[i+2] = Col.DoubleToByte(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<byte, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.ByteToDouble(da[i+d2]), \n                                            Col.ByteToDouble(da[i+d1]), \n                                            Col.ByteToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.B);\n                                    da[i+d1] = Col.DoubleToByte(v.G);\n                                    da[i+d2] = Col.DoubleToByte(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA bytes as C4d\n\n                {\n                    (typeof(byte), typeof(C4d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+1]), \n                                            Col.ByteToDouble(da[i+2]), \n                                            Col.ByteToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.R);\n                                    da[i+1] = Col.DoubleToByte(v.G);\n                                    da[i+2] = Col.DoubleToByte(v.B);\n                                    da[i+3] = Col.DoubleToByte(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+d1]), \n                                            Col.ByteToDouble(da[i+d2]), \n                                            Col.ByteToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.R);\n                                    da[i+d1] = Col.DoubleToByte(v.G);\n                                    da[i+d2] = Col.DoubleToByte(v.B);\n                                    da[i+d3] = Col.DoubleToByte(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA bytes as C4d\n\n                {\n                    (typeof(byte), typeof(C4d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<byte, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.ByteToDouble(da[i+2]), \n                                            Col.ByteToDouble(da[i+1]), \n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.B);\n                                    da[i+1] = Col.DoubleToByte(v.G);\n                                    da[i+2] = Col.DoubleToByte(v.R);\n                                    da[i+3] = Col.DoubleToByte(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<byte, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.ByteToDouble(da[i+d2]), \n                                            Col.ByteToDouble(da[i+d1]), \n                                            Col.ByteToDouble(da[i]), \n                                            Col.ByteToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToByte(v.B);\n                                    da[i+d1] = Col.DoubleToByte(v.G);\n                                    da[i+d2] = Col.DoubleToByte(v.R);\n                                    da[i+d3] = Col.DoubleToByte(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C3b\n\n                {\n                    (typeof(ushort), typeof(C3b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+1]), \n                                            Col.UShortToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.R);\n                                    da[i+1] = Col.ByteToUShort(v.G);\n                                    da[i+2] = Col.ByteToUShort(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+d1]), \n                                            Col.UShortToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.R);\n                                    da[i+d1] = Col.ByteToUShort(v.G);\n                                    da[i+d2] = Col.ByteToUShort(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C3b\n\n                {\n                    (typeof(ushort), typeof(C3b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UShortToByte(da[i+2]), \n                                            Col.UShortToByte(da[i+1]), \n                                            Col.UShortToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.B);\n                                    da[i+1] = Col.ByteToUShort(v.G);\n                                    da[i+2] = Col.ByteToUShort(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UShortToByte(da[i+d2]), \n                                            Col.UShortToByte(da[i+d1]), \n                                            Col.UShortToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.B);\n                                    da[i+d1] = Col.ByteToUShort(v.G);\n                                    da[i+d2] = Col.ByteToUShort(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C3b\n\n                {\n                    (typeof(ushort), typeof(C3b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+1]), \n                                            Col.UShortToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.R);\n                                    da[i+1] = Col.ByteToUShort(v.G);\n                                    da[i+2] = Col.ByteToUShort(v.B);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+d1]), \n                                            Col.UShortToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.R);\n                                    da[i+d1] = Col.ByteToUShort(v.G);\n                                    da[i+d2] = Col.ByteToUShort(v.B);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C3b\n\n                {\n                    (typeof(ushort), typeof(C3b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UShortToByte(da[i+2]), \n                                            Col.UShortToByte(da[i+1]), \n                                            Col.UShortToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.B);\n                                    da[i+1] = Col.ByteToUShort(v.G);\n                                    da[i+2] = Col.ByteToUShort(v.R);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UShortToByte(da[i+d2]), \n                                            Col.UShortToByte(da[i+d1]), \n                                            Col.UShortToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.B);\n                                    da[i+d1] = Col.ByteToUShort(v.G);\n                                    da[i+d2] = Col.ByteToUShort(v.R);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C3us\n\n                {\n                    (typeof(ushort), typeof(C3us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C3us\n\n                {\n                    (typeof(ushort), typeof(C3us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C3us\n\n                {\n                    (typeof(ushort), typeof(C3us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C3us\n\n                {\n                    (typeof(ushort), typeof(C3us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C3ui\n\n                {\n                    (typeof(ushort), typeof(C3ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+1]), \n                                            Col.UShortToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.R);\n                                    da[i+1] = Col.UIntToUShort(v.G);\n                                    da[i+2] = Col.UIntToUShort(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+d1]), \n                                            Col.UShortToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.R);\n                                    da[i+d1] = Col.UIntToUShort(v.G);\n                                    da[i+d2] = Col.UIntToUShort(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C3ui\n\n                {\n                    (typeof(ushort), typeof(C3ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.UShortToUInt(da[i+2]), \n                                            Col.UShortToUInt(da[i+1]), \n                                            Col.UShortToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.B);\n                                    da[i+1] = Col.UIntToUShort(v.G);\n                                    da[i+2] = Col.UIntToUShort(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.UShortToUInt(da[i+d2]), \n                                            Col.UShortToUInt(da[i+d1]), \n                                            Col.UShortToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.B);\n                                    da[i+d1] = Col.UIntToUShort(v.G);\n                                    da[i+d2] = Col.UIntToUShort(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C3ui\n\n                {\n                    (typeof(ushort), typeof(C3ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+1]), \n                                            Col.UShortToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.R);\n                                    da[i+1] = Col.UIntToUShort(v.G);\n                                    da[i+2] = Col.UIntToUShort(v.B);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+d1]), \n                                            Col.UShortToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.R);\n                                    da[i+d1] = Col.UIntToUShort(v.G);\n                                    da[i+d2] = Col.UIntToUShort(v.B);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C3ui\n\n                {\n                    (typeof(ushort), typeof(C3ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.UShortToUInt(da[i+2]), \n                                            Col.UShortToUInt(da[i+1]), \n                                            Col.UShortToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.B);\n                                    da[i+1] = Col.UIntToUShort(v.G);\n                                    da[i+2] = Col.UIntToUShort(v.R);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.UShortToUInt(da[i+d2]), \n                                            Col.UShortToUInt(da[i+d1]), \n                                            Col.UShortToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.B);\n                                    da[i+d1] = Col.UIntToUShort(v.G);\n                                    da[i+d2] = Col.UIntToUShort(v.R);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C3f\n\n                {\n                    (typeof(ushort), typeof(C3f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+1]), \n                                            Col.UShortToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.R);\n                                    da[i+1] = Col.FloatToUShort(v.G);\n                                    da[i+2] = Col.FloatToUShort(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+d1]), \n                                            Col.UShortToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.R);\n                                    da[i+d1] = Col.FloatToUShort(v.G);\n                                    da[i+d2] = Col.FloatToUShort(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C3f\n\n                {\n                    (typeof(ushort), typeof(C3f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UShortToFloat(da[i+2]), \n                                            Col.UShortToFloat(da[i+1]), \n                                            Col.UShortToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.B);\n                                    da[i+1] = Col.FloatToUShort(v.G);\n                                    da[i+2] = Col.FloatToUShort(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UShortToFloat(da[i+d2]), \n                                            Col.UShortToFloat(da[i+d1]), \n                                            Col.UShortToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.B);\n                                    da[i+d1] = Col.FloatToUShort(v.G);\n                                    da[i+d2] = Col.FloatToUShort(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C3f\n\n                {\n                    (typeof(ushort), typeof(C3f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+1]), \n                                            Col.UShortToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.R);\n                                    da[i+1] = Col.FloatToUShort(v.G);\n                                    da[i+2] = Col.FloatToUShort(v.B);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+d1]), \n                                            Col.UShortToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.R);\n                                    da[i+d1] = Col.FloatToUShort(v.G);\n                                    da[i+d2] = Col.FloatToUShort(v.B);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C3f\n\n                {\n                    (typeof(ushort), typeof(C3f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UShortToFloat(da[i+2]), \n                                            Col.UShortToFloat(da[i+1]), \n                                            Col.UShortToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.B);\n                                    da[i+1] = Col.FloatToUShort(v.G);\n                                    da[i+2] = Col.FloatToUShort(v.R);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UShortToFloat(da[i+d2]), \n                                            Col.UShortToFloat(da[i+d1]), \n                                            Col.UShortToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.B);\n                                    da[i+d1] = Col.FloatToUShort(v.G);\n                                    da[i+d2] = Col.FloatToUShort(v.R);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C3d\n\n                {\n                    (typeof(ushort), typeof(C3d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+1]), \n                                            Col.UShortToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.R);\n                                    da[i+1] = Col.DoubleToUShort(v.G);\n                                    da[i+2] = Col.DoubleToUShort(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+d1]), \n                                            Col.UShortToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.R);\n                                    da[i+d1] = Col.DoubleToUShort(v.G);\n                                    da[i+d2] = Col.DoubleToUShort(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C3d\n\n                {\n                    (typeof(ushort), typeof(C3d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UShortToDouble(da[i+2]), \n                                            Col.UShortToDouble(da[i+1]), \n                                            Col.UShortToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.B);\n                                    da[i+1] = Col.DoubleToUShort(v.G);\n                                    da[i+2] = Col.DoubleToUShort(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UShortToDouble(da[i+d2]), \n                                            Col.UShortToDouble(da[i+d1]), \n                                            Col.UShortToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.B);\n                                    da[i+d1] = Col.DoubleToUShort(v.G);\n                                    da[i+d2] = Col.DoubleToUShort(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C3d\n\n                {\n                    (typeof(ushort), typeof(C3d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+1]), \n                                            Col.UShortToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.R);\n                                    da[i+1] = Col.DoubleToUShort(v.G);\n                                    da[i+2] = Col.DoubleToUShort(v.B);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+d1]), \n                                            Col.UShortToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.R);\n                                    da[i+d1] = Col.DoubleToUShort(v.G);\n                                    da[i+d2] = Col.DoubleToUShort(v.B);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C3d\n\n                {\n                    (typeof(ushort), typeof(C3d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UShortToDouble(da[i+2]), \n                                            Col.UShortToDouble(da[i+1]), \n                                            Col.UShortToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.B);\n                                    da[i+1] = Col.DoubleToUShort(v.G);\n                                    da[i+2] = Col.DoubleToUShort(v.R);\n                                    da[i+3] = (ushort)65535;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UShortToDouble(da[i+d2]), \n                                            Col.UShortToDouble(da[i+d1]), \n                                            Col.UShortToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.B);\n                                    da[i+d1] = Col.DoubleToUShort(v.G);\n                                    da[i+d2] = Col.DoubleToUShort(v.R);\n                                    da[i+d3] = (ushort)65535;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C4b\n\n                {\n                    (typeof(ushort), typeof(C4b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+1]), \n                                            Col.UShortToByte(da[i+2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.R);\n                                    da[i+1] = Col.ByteToUShort(v.G);\n                                    da[i+2] = Col.ByteToUShort(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+d1]), \n                                            Col.UShortToByte(da[i+d2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.R);\n                                    da[i+d1] = Col.ByteToUShort(v.G);\n                                    da[i+d2] = Col.ByteToUShort(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C4b\n\n                {\n                    (typeof(ushort), typeof(C4b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UShortToByte(da[i+2]), \n                                            Col.UShortToByte(da[i+1]), \n                                            Col.UShortToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.B);\n                                    da[i+1] = Col.ByteToUShort(v.G);\n                                    da[i+2] = Col.ByteToUShort(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UShortToByte(da[i+d2]), \n                                            Col.UShortToByte(da[i+d1]), \n                                            Col.UShortToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.B);\n                                    da[i+d1] = Col.ByteToUShort(v.G);\n                                    da[i+d2] = Col.ByteToUShort(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C4b\n\n                {\n                    (typeof(ushort), typeof(C4b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+1]), \n                                            Col.UShortToByte(da[i+2]), \n                                            Col.UShortToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.R);\n                                    da[i+1] = Col.ByteToUShort(v.G);\n                                    da[i+2] = Col.ByteToUShort(v.B);\n                                    da[i+3] = Col.ByteToUShort(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+d1]), \n                                            Col.UShortToByte(da[i+d2]), \n                                            Col.UShortToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.R);\n                                    da[i+d1] = Col.ByteToUShort(v.G);\n                                    da[i+d2] = Col.ByteToUShort(v.B);\n                                    da[i+d3] = Col.ByteToUShort(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C4b\n\n                {\n                    (typeof(ushort), typeof(C4b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UShortToByte(da[i+2]), \n                                            Col.UShortToByte(da[i+1]), \n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.B);\n                                    da[i+1] = Col.ByteToUShort(v.G);\n                                    da[i+2] = Col.ByteToUShort(v.R);\n                                    da[i+3] = Col.ByteToUShort(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UShortToByte(da[i+d2]), \n                                            Col.UShortToByte(da[i+d1]), \n                                            Col.UShortToByte(da[i]), \n                                            Col.UShortToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUShort(v.B);\n                                    da[i+d1] = Col.ByteToUShort(v.G);\n                                    da[i+d2] = Col.ByteToUShort(v.R);\n                                    da[i+d3] = Col.ByteToUShort(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C4us\n\n                {\n                    (typeof(ushort), typeof(C4us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C4us\n\n                {\n                    (typeof(ushort), typeof(C4us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C4us\n\n                {\n                    (typeof(ushort), typeof(C4us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C4us\n\n                {\n                    (typeof(ushort), typeof(C4us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C4ui\n\n                {\n                    (typeof(ushort), typeof(C4ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+1]), \n                                            Col.UShortToUInt(da[i+2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.R);\n                                    da[i+1] = Col.UIntToUShort(v.G);\n                                    da[i+2] = Col.UIntToUShort(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+d1]), \n                                            Col.UShortToUInt(da[i+d2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.R);\n                                    da[i+d1] = Col.UIntToUShort(v.G);\n                                    da[i+d2] = Col.UIntToUShort(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C4ui\n\n                {\n                    (typeof(ushort), typeof(C4ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.UShortToUInt(da[i+2]), \n                                            Col.UShortToUInt(da[i+1]), \n                                            Col.UShortToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.B);\n                                    da[i+1] = Col.UIntToUShort(v.G);\n                                    da[i+2] = Col.UIntToUShort(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.UShortToUInt(da[i+d2]), \n                                            Col.UShortToUInt(da[i+d1]), \n                                            Col.UShortToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.B);\n                                    da[i+d1] = Col.UIntToUShort(v.G);\n                                    da[i+d2] = Col.UIntToUShort(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C4ui\n\n                {\n                    (typeof(ushort), typeof(C4ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+1]), \n                                            Col.UShortToUInt(da[i+2]), \n                                            Col.UShortToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.R);\n                                    da[i+1] = Col.UIntToUShort(v.G);\n                                    da[i+2] = Col.UIntToUShort(v.B);\n                                    da[i+3] = Col.UIntToUShort(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+d1]), \n                                            Col.UShortToUInt(da[i+d2]), \n                                            Col.UShortToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.R);\n                                    da[i+d1] = Col.UIntToUShort(v.G);\n                                    da[i+d2] = Col.UIntToUShort(v.B);\n                                    da[i+d3] = Col.UIntToUShort(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C4ui\n\n                {\n                    (typeof(ushort), typeof(C4ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.UShortToUInt(da[i+2]), \n                                            Col.UShortToUInt(da[i+1]), \n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.B);\n                                    da[i+1] = Col.UIntToUShort(v.G);\n                                    da[i+2] = Col.UIntToUShort(v.R);\n                                    da[i+3] = Col.UIntToUShort(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.UShortToUInt(da[i+d2]), \n                                            Col.UShortToUInt(da[i+d1]), \n                                            Col.UShortToUInt(da[i]), \n                                            Col.UShortToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToUShort(v.B);\n                                    da[i+d1] = Col.UIntToUShort(v.G);\n                                    da[i+d2] = Col.UIntToUShort(v.R);\n                                    da[i+d3] = Col.UIntToUShort(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C4f\n\n                {\n                    (typeof(ushort), typeof(C4f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+1]), \n                                            Col.UShortToFloat(da[i+2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.R);\n                                    da[i+1] = Col.FloatToUShort(v.G);\n                                    da[i+2] = Col.FloatToUShort(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+d1]), \n                                            Col.UShortToFloat(da[i+d2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.R);\n                                    da[i+d1] = Col.FloatToUShort(v.G);\n                                    da[i+d2] = Col.FloatToUShort(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C4f\n\n                {\n                    (typeof(ushort), typeof(C4f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UShortToFloat(da[i+2]), \n                                            Col.UShortToFloat(da[i+1]), \n                                            Col.UShortToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.B);\n                                    da[i+1] = Col.FloatToUShort(v.G);\n                                    da[i+2] = Col.FloatToUShort(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UShortToFloat(da[i+d2]), \n                                            Col.UShortToFloat(da[i+d1]), \n                                            Col.UShortToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.B);\n                                    da[i+d1] = Col.FloatToUShort(v.G);\n                                    da[i+d2] = Col.FloatToUShort(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C4f\n\n                {\n                    (typeof(ushort), typeof(C4f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+1]), \n                                            Col.UShortToFloat(da[i+2]), \n                                            Col.UShortToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.R);\n                                    da[i+1] = Col.FloatToUShort(v.G);\n                                    da[i+2] = Col.FloatToUShort(v.B);\n                                    da[i+3] = Col.FloatToUShort(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+d1]), \n                                            Col.UShortToFloat(da[i+d2]), \n                                            Col.UShortToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.R);\n                                    da[i+d1] = Col.FloatToUShort(v.G);\n                                    da[i+d2] = Col.FloatToUShort(v.B);\n                                    da[i+d3] = Col.FloatToUShort(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C4f\n\n                {\n                    (typeof(ushort), typeof(C4f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UShortToFloat(da[i+2]), \n                                            Col.UShortToFloat(da[i+1]), \n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.B);\n                                    da[i+1] = Col.FloatToUShort(v.G);\n                                    da[i+2] = Col.FloatToUShort(v.R);\n                                    da[i+3] = Col.FloatToUShort(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UShortToFloat(da[i+d2]), \n                                            Col.UShortToFloat(da[i+d1]), \n                                            Col.UShortToFloat(da[i]), \n                                            Col.UShortToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUShort(v.B);\n                                    da[i+d1] = Col.FloatToUShort(v.G);\n                                    da[i+d2] = Col.FloatToUShort(v.R);\n                                    da[i+d3] = Col.FloatToUShort(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB ushorts as C4d\n\n                {\n                    (typeof(ushort), typeof(C4d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+1]), \n                                            Col.UShortToDouble(da[i+2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.R);\n                                    da[i+1] = Col.DoubleToUShort(v.G);\n                                    da[i+2] = Col.DoubleToUShort(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+d1]), \n                                            Col.UShortToDouble(da[i+d2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.R);\n                                    da[i+d1] = Col.DoubleToUShort(v.G);\n                                    da[i+d2] = Col.DoubleToUShort(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR ushorts as C4d\n\n                {\n                    (typeof(ushort), typeof(C4d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UShortToDouble(da[i+2]), \n                                            Col.UShortToDouble(da[i+1]), \n                                            Col.UShortToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.B);\n                                    da[i+1] = Col.DoubleToUShort(v.G);\n                                    da[i+2] = Col.DoubleToUShort(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<ushort, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UShortToDouble(da[i+d2]), \n                                            Col.UShortToDouble(da[i+d1]), \n                                            Col.UShortToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.B);\n                                    da[i+d1] = Col.DoubleToUShort(v.G);\n                                    da[i+d2] = Col.DoubleToUShort(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA ushorts as C4d\n\n                {\n                    (typeof(ushort), typeof(C4d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+1]), \n                                            Col.UShortToDouble(da[i+2]), \n                                            Col.UShortToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.R);\n                                    da[i+1] = Col.DoubleToUShort(v.G);\n                                    da[i+2] = Col.DoubleToUShort(v.B);\n                                    da[i+3] = Col.DoubleToUShort(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+d1]), \n                                            Col.UShortToDouble(da[i+d2]), \n                                            Col.UShortToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.R);\n                                    da[i+d1] = Col.DoubleToUShort(v.G);\n                                    da[i+d2] = Col.DoubleToUShort(v.B);\n                                    da[i+d3] = Col.DoubleToUShort(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA ushorts as C4d\n\n                {\n                    (typeof(ushort), typeof(C4d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<ushort, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UShortToDouble(da[i+2]), \n                                            Col.UShortToDouble(da[i+1]), \n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.B);\n                                    da[i+1] = Col.DoubleToUShort(v.G);\n                                    da[i+2] = Col.DoubleToUShort(v.R);\n                                    da[i+3] = Col.DoubleToUShort(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<ushort, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UShortToDouble(da[i+d2]), \n                                            Col.UShortToDouble(da[i+d1]), \n                                            Col.UShortToDouble(da[i]), \n                                            Col.UShortToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUShort(v.B);\n                                    da[i+d1] = Col.DoubleToUShort(v.G);\n                                    da[i+d2] = Col.DoubleToUShort(v.R);\n                                    da[i+d3] = Col.DoubleToUShort(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C3b\n\n                {\n                    (typeof(uint), typeof(C3b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+1]), \n                                            Col.UIntToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.R);\n                                    da[i+1] = Col.ByteToUInt(v.G);\n                                    da[i+2] = Col.ByteToUInt(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+d1]), \n                                            Col.UIntToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.R);\n                                    da[i+d1] = Col.ByteToUInt(v.G);\n                                    da[i+d2] = Col.ByteToUInt(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C3b\n\n                {\n                    (typeof(uint), typeof(C3b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UIntToByte(da[i+2]), \n                                            Col.UIntToByte(da[i+1]), \n                                            Col.UIntToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.B);\n                                    da[i+1] = Col.ByteToUInt(v.G);\n                                    da[i+2] = Col.ByteToUInt(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UIntToByte(da[i+d2]), \n                                            Col.UIntToByte(da[i+d1]), \n                                            Col.UIntToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.B);\n                                    da[i+d1] = Col.ByteToUInt(v.G);\n                                    da[i+d2] = Col.ByteToUInt(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C3b\n\n                {\n                    (typeof(uint), typeof(C3b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+1]), \n                                            Col.UIntToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.R);\n                                    da[i+1] = Col.ByteToUInt(v.G);\n                                    da[i+2] = Col.ByteToUInt(v.B);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+d1]), \n                                            Col.UIntToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.R);\n                                    da[i+d1] = Col.ByteToUInt(v.G);\n                                    da[i+d2] = Col.ByteToUInt(v.B);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C3b\n\n                {\n                    (typeof(uint), typeof(C3b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UIntToByte(da[i+2]), \n                                            Col.UIntToByte(da[i+1]), \n                                            Col.UIntToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.B);\n                                    da[i+1] = Col.ByteToUInt(v.G);\n                                    da[i+2] = Col.ByteToUInt(v.R);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.UIntToByte(da[i+d2]), \n                                            Col.UIntToByte(da[i+d1]), \n                                            Col.UIntToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.B);\n                                    da[i+d1] = Col.ByteToUInt(v.G);\n                                    da[i+d2] = Col.ByteToUInt(v.R);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C3us\n\n                {\n                    (typeof(uint), typeof(C3us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+1]), \n                                            Col.UIntToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.R);\n                                    da[i+1] = Col.UShortToUInt(v.G);\n                                    da[i+2] = Col.UShortToUInt(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+d1]), \n                                            Col.UIntToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.R);\n                                    da[i+d1] = Col.UShortToUInt(v.G);\n                                    da[i+d2] = Col.UShortToUInt(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C3us\n\n                {\n                    (typeof(uint), typeof(C3us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.UIntToUShort(da[i+2]), \n                                            Col.UIntToUShort(da[i+1]), \n                                            Col.UIntToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.B);\n                                    da[i+1] = Col.UShortToUInt(v.G);\n                                    da[i+2] = Col.UShortToUInt(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.UIntToUShort(da[i+d2]), \n                                            Col.UIntToUShort(da[i+d1]), \n                                            Col.UIntToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.B);\n                                    da[i+d1] = Col.UShortToUInt(v.G);\n                                    da[i+d2] = Col.UShortToUInt(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C3us\n\n                {\n                    (typeof(uint), typeof(C3us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+1]), \n                                            Col.UIntToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.R);\n                                    da[i+1] = Col.UShortToUInt(v.G);\n                                    da[i+2] = Col.UShortToUInt(v.B);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+d1]), \n                                            Col.UIntToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.R);\n                                    da[i+d1] = Col.UShortToUInt(v.G);\n                                    da[i+d2] = Col.UShortToUInt(v.B);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C3us\n\n                {\n                    (typeof(uint), typeof(C3us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.UIntToUShort(da[i+2]), \n                                            Col.UIntToUShort(da[i+1]), \n                                            Col.UIntToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.B);\n                                    da[i+1] = Col.UShortToUInt(v.G);\n                                    da[i+2] = Col.UShortToUInt(v.R);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.UIntToUShort(da[i+d2]), \n                                            Col.UIntToUShort(da[i+d1]), \n                                            Col.UIntToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.B);\n                                    da[i+d1] = Col.UShortToUInt(v.G);\n                                    da[i+d2] = Col.UShortToUInt(v.R);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C3ui\n\n                {\n                    (typeof(uint), typeof(C3ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C3ui\n\n                {\n                    (typeof(uint), typeof(C3ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C3ui\n\n                {\n                    (typeof(uint), typeof(C3ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C3ui\n\n                {\n                    (typeof(uint), typeof(C3ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C3f\n\n                {\n                    (typeof(uint), typeof(C3f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+1]), \n                                            Col.UIntToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.R);\n                                    da[i+1] = Col.FloatToUInt(v.G);\n                                    da[i+2] = Col.FloatToUInt(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+d1]), \n                                            Col.UIntToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.R);\n                                    da[i+d1] = Col.FloatToUInt(v.G);\n                                    da[i+d2] = Col.FloatToUInt(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C3f\n\n                {\n                    (typeof(uint), typeof(C3f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UIntToFloat(da[i+2]), \n                                            Col.UIntToFloat(da[i+1]), \n                                            Col.UIntToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.B);\n                                    da[i+1] = Col.FloatToUInt(v.G);\n                                    da[i+2] = Col.FloatToUInt(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UIntToFloat(da[i+d2]), \n                                            Col.UIntToFloat(da[i+d1]), \n                                            Col.UIntToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.B);\n                                    da[i+d1] = Col.FloatToUInt(v.G);\n                                    da[i+d2] = Col.FloatToUInt(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C3f\n\n                {\n                    (typeof(uint), typeof(C3f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+1]), \n                                            Col.UIntToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.R);\n                                    da[i+1] = Col.FloatToUInt(v.G);\n                                    da[i+2] = Col.FloatToUInt(v.B);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+d1]), \n                                            Col.UIntToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.R);\n                                    da[i+d1] = Col.FloatToUInt(v.G);\n                                    da[i+d2] = Col.FloatToUInt(v.B);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C3f\n\n                {\n                    (typeof(uint), typeof(C3f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UIntToFloat(da[i+2]), \n                                            Col.UIntToFloat(da[i+1]), \n                                            Col.UIntToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.B);\n                                    da[i+1] = Col.FloatToUInt(v.G);\n                                    da[i+2] = Col.FloatToUInt(v.R);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.UIntToFloat(da[i+d2]), \n                                            Col.UIntToFloat(da[i+d1]), \n                                            Col.UIntToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.B);\n                                    da[i+d1] = Col.FloatToUInt(v.G);\n                                    da[i+d2] = Col.FloatToUInt(v.R);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C3d\n\n                {\n                    (typeof(uint), typeof(C3d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+1]), \n                                            Col.UIntToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.R);\n                                    da[i+1] = Col.DoubleToUInt(v.G);\n                                    da[i+2] = Col.DoubleToUInt(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+d1]), \n                                            Col.UIntToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.R);\n                                    da[i+d1] = Col.DoubleToUInt(v.G);\n                                    da[i+d2] = Col.DoubleToUInt(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C3d\n\n                {\n                    (typeof(uint), typeof(C3d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UIntToDouble(da[i+2]), \n                                            Col.UIntToDouble(da[i+1]), \n                                            Col.UIntToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.B);\n                                    da[i+1] = Col.DoubleToUInt(v.G);\n                                    da[i+2] = Col.DoubleToUInt(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UIntToDouble(da[i+d2]), \n                                            Col.UIntToDouble(da[i+d1]), \n                                            Col.UIntToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.B);\n                                    da[i+d1] = Col.DoubleToUInt(v.G);\n                                    da[i+d2] = Col.DoubleToUInt(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C3d\n\n                {\n                    (typeof(uint), typeof(C3d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+1]), \n                                            Col.UIntToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.R);\n                                    da[i+1] = Col.DoubleToUInt(v.G);\n                                    da[i+2] = Col.DoubleToUInt(v.B);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+d1]), \n                                            Col.UIntToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.R);\n                                    da[i+d1] = Col.DoubleToUInt(v.G);\n                                    da[i+d2] = Col.DoubleToUInt(v.B);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C3d\n\n                {\n                    (typeof(uint), typeof(C3d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UIntToDouble(da[i+2]), \n                                            Col.UIntToDouble(da[i+1]), \n                                            Col.UIntToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.B);\n                                    da[i+1] = Col.DoubleToUInt(v.G);\n                                    da[i+2] = Col.DoubleToUInt(v.R);\n                                    da[i+3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.UIntToDouble(da[i+d2]), \n                                            Col.UIntToDouble(da[i+d1]), \n                                            Col.UIntToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.B);\n                                    da[i+d1] = Col.DoubleToUInt(v.G);\n                                    da[i+d2] = Col.DoubleToUInt(v.R);\n                                    da[i+d3] = (uint)UInt32.MaxValue;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C4b\n\n                {\n                    (typeof(uint), typeof(C4b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+1]), \n                                            Col.UIntToByte(da[i+2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.R);\n                                    da[i+1] = Col.ByteToUInt(v.G);\n                                    da[i+2] = Col.ByteToUInt(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+d1]), \n                                            Col.UIntToByte(da[i+d2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.R);\n                                    da[i+d1] = Col.ByteToUInt(v.G);\n                                    da[i+d2] = Col.ByteToUInt(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C4b\n\n                {\n                    (typeof(uint), typeof(C4b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UIntToByte(da[i+2]), \n                                            Col.UIntToByte(da[i+1]), \n                                            Col.UIntToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.B);\n                                    da[i+1] = Col.ByteToUInt(v.G);\n                                    da[i+2] = Col.ByteToUInt(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UIntToByte(da[i+d2]), \n                                            Col.UIntToByte(da[i+d1]), \n                                            Col.UIntToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.B);\n                                    da[i+d1] = Col.ByteToUInt(v.G);\n                                    da[i+d2] = Col.ByteToUInt(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C4b\n\n                {\n                    (typeof(uint), typeof(C4b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+1]), \n                                            Col.UIntToByte(da[i+2]), \n                                            Col.UIntToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.R);\n                                    da[i+1] = Col.ByteToUInt(v.G);\n                                    da[i+2] = Col.ByteToUInt(v.B);\n                                    da[i+3] = Col.ByteToUInt(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+d1]), \n                                            Col.UIntToByte(da[i+d2]), \n                                            Col.UIntToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.R);\n                                    da[i+d1] = Col.ByteToUInt(v.G);\n                                    da[i+d2] = Col.ByteToUInt(v.B);\n                                    da[i+d3] = Col.ByteToUInt(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C4b\n\n                {\n                    (typeof(uint), typeof(C4b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UIntToByte(da[i+2]), \n                                            Col.UIntToByte(da[i+1]), \n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.B);\n                                    da[i+1] = Col.ByteToUInt(v.G);\n                                    da[i+2] = Col.ByteToUInt(v.R);\n                                    da[i+3] = Col.ByteToUInt(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.UIntToByte(da[i+d2]), \n                                            Col.UIntToByte(da[i+d1]), \n                                            Col.UIntToByte(da[i]), \n                                            Col.UIntToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToUInt(v.B);\n                                    da[i+d1] = Col.ByteToUInt(v.G);\n                                    da[i+d2] = Col.ByteToUInt(v.R);\n                                    da[i+d3] = Col.ByteToUInt(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C4us\n\n                {\n                    (typeof(uint), typeof(C4us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+1]), \n                                            Col.UIntToUShort(da[i+2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.R);\n                                    da[i+1] = Col.UShortToUInt(v.G);\n                                    da[i+2] = Col.UShortToUInt(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+d1]), \n                                            Col.UIntToUShort(da[i+d2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.R);\n                                    da[i+d1] = Col.UShortToUInt(v.G);\n                                    da[i+d2] = Col.UShortToUInt(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C4us\n\n                {\n                    (typeof(uint), typeof(C4us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.UIntToUShort(da[i+2]), \n                                            Col.UIntToUShort(da[i+1]), \n                                            Col.UIntToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.B);\n                                    da[i+1] = Col.UShortToUInt(v.G);\n                                    da[i+2] = Col.UShortToUInt(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.UIntToUShort(da[i+d2]), \n                                            Col.UIntToUShort(da[i+d1]), \n                                            Col.UIntToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.B);\n                                    da[i+d1] = Col.UShortToUInt(v.G);\n                                    da[i+d2] = Col.UShortToUInt(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C4us\n\n                {\n                    (typeof(uint), typeof(C4us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+1]), \n                                            Col.UIntToUShort(da[i+2]), \n                                            Col.UIntToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.R);\n                                    da[i+1] = Col.UShortToUInt(v.G);\n                                    da[i+2] = Col.UShortToUInt(v.B);\n                                    da[i+3] = Col.UShortToUInt(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+d1]), \n                                            Col.UIntToUShort(da[i+d2]), \n                                            Col.UIntToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.R);\n                                    da[i+d1] = Col.UShortToUInt(v.G);\n                                    da[i+d2] = Col.UShortToUInt(v.B);\n                                    da[i+d3] = Col.UShortToUInt(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C4us\n\n                {\n                    (typeof(uint), typeof(C4us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.UIntToUShort(da[i+2]), \n                                            Col.UIntToUShort(da[i+1]), \n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.B);\n                                    da[i+1] = Col.UShortToUInt(v.G);\n                                    da[i+2] = Col.UShortToUInt(v.R);\n                                    da[i+3] = Col.UShortToUInt(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.UIntToUShort(da[i+d2]), \n                                            Col.UIntToUShort(da[i+d1]), \n                                            Col.UIntToUShort(da[i]), \n                                            Col.UIntToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToUInt(v.B);\n                                    da[i+d1] = Col.UShortToUInt(v.G);\n                                    da[i+d2] = Col.UShortToUInt(v.R);\n                                    da[i+d3] = Col.UShortToUInt(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C4ui\n\n                {\n                    (typeof(uint), typeof(C4ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C4ui\n\n                {\n                    (typeof(uint), typeof(C4ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C4ui\n\n                {\n                    (typeof(uint), typeof(C4ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C4ui\n\n                {\n                    (typeof(uint), typeof(C4ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C4f\n\n                {\n                    (typeof(uint), typeof(C4f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+1]), \n                                            Col.UIntToFloat(da[i+2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.R);\n                                    da[i+1] = Col.FloatToUInt(v.G);\n                                    da[i+2] = Col.FloatToUInt(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+d1]), \n                                            Col.UIntToFloat(da[i+d2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.R);\n                                    da[i+d1] = Col.FloatToUInt(v.G);\n                                    da[i+d2] = Col.FloatToUInt(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C4f\n\n                {\n                    (typeof(uint), typeof(C4f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UIntToFloat(da[i+2]), \n                                            Col.UIntToFloat(da[i+1]), \n                                            Col.UIntToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.B);\n                                    da[i+1] = Col.FloatToUInt(v.G);\n                                    da[i+2] = Col.FloatToUInt(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UIntToFloat(da[i+d2]), \n                                            Col.UIntToFloat(da[i+d1]), \n                                            Col.UIntToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.B);\n                                    da[i+d1] = Col.FloatToUInt(v.G);\n                                    da[i+d2] = Col.FloatToUInt(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C4f\n\n                {\n                    (typeof(uint), typeof(C4f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+1]), \n                                            Col.UIntToFloat(da[i+2]), \n                                            Col.UIntToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.R);\n                                    da[i+1] = Col.FloatToUInt(v.G);\n                                    da[i+2] = Col.FloatToUInt(v.B);\n                                    da[i+3] = Col.FloatToUInt(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+d1]), \n                                            Col.UIntToFloat(da[i+d2]), \n                                            Col.UIntToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.R);\n                                    da[i+d1] = Col.FloatToUInt(v.G);\n                                    da[i+d2] = Col.FloatToUInt(v.B);\n                                    da[i+d3] = Col.FloatToUInt(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C4f\n\n                {\n                    (typeof(uint), typeof(C4f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UIntToFloat(da[i+2]), \n                                            Col.UIntToFloat(da[i+1]), \n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.B);\n                                    da[i+1] = Col.FloatToUInt(v.G);\n                                    da[i+2] = Col.FloatToUInt(v.R);\n                                    da[i+3] = Col.FloatToUInt(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.UIntToFloat(da[i+d2]), \n                                            Col.UIntToFloat(da[i+d1]), \n                                            Col.UIntToFloat(da[i]), \n                                            Col.UIntToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToUInt(v.B);\n                                    da[i+d1] = Col.FloatToUInt(v.G);\n                                    da[i+d2] = Col.FloatToUInt(v.R);\n                                    da[i+d3] = Col.FloatToUInt(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB uints as C4d\n\n                {\n                    (typeof(uint), typeof(C4d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+1]), \n                                            Col.UIntToDouble(da[i+2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.R);\n                                    da[i+1] = Col.DoubleToUInt(v.G);\n                                    da[i+2] = Col.DoubleToUInt(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+d1]), \n                                            Col.UIntToDouble(da[i+d2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.R);\n                                    da[i+d1] = Col.DoubleToUInt(v.G);\n                                    da[i+d2] = Col.DoubleToUInt(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR uints as C4d\n\n                {\n                    (typeof(uint), typeof(C4d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UIntToDouble(da[i+2]), \n                                            Col.UIntToDouble(da[i+1]), \n                                            Col.UIntToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.B);\n                                    da[i+1] = Col.DoubleToUInt(v.G);\n                                    da[i+2] = Col.DoubleToUInt(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<uint, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UIntToDouble(da[i+d2]), \n                                            Col.UIntToDouble(da[i+d1]), \n                                            Col.UIntToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.B);\n                                    da[i+d1] = Col.DoubleToUInt(v.G);\n                                    da[i+d2] = Col.DoubleToUInt(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA uints as C4d\n\n                {\n                    (typeof(uint), typeof(C4d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+1]), \n                                            Col.UIntToDouble(da[i+2]), \n                                            Col.UIntToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.R);\n                                    da[i+1] = Col.DoubleToUInt(v.G);\n                                    da[i+2] = Col.DoubleToUInt(v.B);\n                                    da[i+3] = Col.DoubleToUInt(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+d1]), \n                                            Col.UIntToDouble(da[i+d2]), \n                                            Col.UIntToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.R);\n                                    da[i+d1] = Col.DoubleToUInt(v.G);\n                                    da[i+d2] = Col.DoubleToUInt(v.B);\n                                    da[i+d3] = Col.DoubleToUInt(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA uints as C4d\n\n                {\n                    (typeof(uint), typeof(C4d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<uint, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UIntToDouble(da[i+2]), \n                                            Col.UIntToDouble(da[i+1]), \n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.B);\n                                    da[i+1] = Col.DoubleToUInt(v.G);\n                                    da[i+2] = Col.DoubleToUInt(v.R);\n                                    da[i+3] = Col.DoubleToUInt(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<uint, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.UIntToDouble(da[i+d2]), \n                                            Col.UIntToDouble(da[i+d1]), \n                                            Col.UIntToDouble(da[i]), \n                                            Col.UIntToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToUInt(v.B);\n                                    da[i+d1] = Col.DoubleToUInt(v.G);\n                                    da[i+d2] = Col.DoubleToUInt(v.R);\n                                    da[i+d3] = Col.DoubleToUInt(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C3b\n\n                {\n                    (typeof(Half), typeof(C3b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+1]), \n                                            Col.HalfToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.R);\n                                    da[i+1] = Col.ByteToHalf(v.G);\n                                    da[i+2] = Col.ByteToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+d1]), \n                                            Col.HalfToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.R);\n                                    da[i+d1] = Col.ByteToHalf(v.G);\n                                    da[i+d2] = Col.ByteToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C3b\n\n                {\n                    (typeof(Half), typeof(C3b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.HalfToByte(da[i+2]), \n                                            Col.HalfToByte(da[i+1]), \n                                            Col.HalfToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.B);\n                                    da[i+1] = Col.ByteToHalf(v.G);\n                                    da[i+2] = Col.ByteToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.HalfToByte(da[i+d2]), \n                                            Col.HalfToByte(da[i+d1]), \n                                            Col.HalfToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.B);\n                                    da[i+d1] = Col.ByteToHalf(v.G);\n                                    da[i+d2] = Col.ByteToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C3b\n\n                {\n                    (typeof(Half), typeof(C3b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+1]), \n                                            Col.HalfToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.R);\n                                    da[i+1] = Col.ByteToHalf(v.G);\n                                    da[i+2] = Col.ByteToHalf(v.B);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+d1]), \n                                            Col.HalfToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.R);\n                                    da[i+d1] = Col.ByteToHalf(v.G);\n                                    da[i+d2] = Col.ByteToHalf(v.B);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C3b\n\n                {\n                    (typeof(Half), typeof(C3b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.HalfToByte(da[i+2]), \n                                            Col.HalfToByte(da[i+1]), \n                                            Col.HalfToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.B);\n                                    da[i+1] = Col.ByteToHalf(v.G);\n                                    da[i+2] = Col.ByteToHalf(v.R);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.HalfToByte(da[i+d2]), \n                                            Col.HalfToByte(da[i+d1]), \n                                            Col.HalfToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.B);\n                                    da[i+d1] = Col.ByteToHalf(v.G);\n                                    da[i+d2] = Col.ByteToHalf(v.R);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C3us\n\n                {\n                    (typeof(Half), typeof(C3us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+1]), \n                                            Col.HalfToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.R);\n                                    da[i+1] = Col.UShortToHalf(v.G);\n                                    da[i+2] = Col.UShortToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+d1]), \n                                            Col.HalfToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.R);\n                                    da[i+d1] = Col.UShortToHalf(v.G);\n                                    da[i+d2] = Col.UShortToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C3us\n\n                {\n                    (typeof(Half), typeof(C3us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.HalfToUShort(da[i+2]), \n                                            Col.HalfToUShort(da[i+1]), \n                                            Col.HalfToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.B);\n                                    da[i+1] = Col.UShortToHalf(v.G);\n                                    da[i+2] = Col.UShortToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.HalfToUShort(da[i+d2]), \n                                            Col.HalfToUShort(da[i+d1]), \n                                            Col.HalfToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.B);\n                                    da[i+d1] = Col.UShortToHalf(v.G);\n                                    da[i+d2] = Col.UShortToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C3us\n\n                {\n                    (typeof(Half), typeof(C3us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+1]), \n                                            Col.HalfToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.R);\n                                    da[i+1] = Col.UShortToHalf(v.G);\n                                    da[i+2] = Col.UShortToHalf(v.B);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+d1]), \n                                            Col.HalfToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.R);\n                                    da[i+d1] = Col.UShortToHalf(v.G);\n                                    da[i+d2] = Col.UShortToHalf(v.B);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C3us\n\n                {\n                    (typeof(Half), typeof(C3us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.HalfToUShort(da[i+2]), \n                                            Col.HalfToUShort(da[i+1]), \n                                            Col.HalfToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.B);\n                                    da[i+1] = Col.UShortToHalf(v.G);\n                                    da[i+2] = Col.UShortToHalf(v.R);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.HalfToUShort(da[i+d2]), \n                                            Col.HalfToUShort(da[i+d1]), \n                                            Col.HalfToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.B);\n                                    da[i+d1] = Col.UShortToHalf(v.G);\n                                    da[i+d2] = Col.UShortToHalf(v.R);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C3ui\n\n                {\n                    (typeof(Half), typeof(C3ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+1]), \n                                            Col.HalfToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.R);\n                                    da[i+1] = Col.UIntToHalf(v.G);\n                                    da[i+2] = Col.UIntToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+d1]), \n                                            Col.HalfToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.R);\n                                    da[i+d1] = Col.UIntToHalf(v.G);\n                                    da[i+d2] = Col.UIntToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C3ui\n\n                {\n                    (typeof(Half), typeof(C3ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.HalfToUInt(da[i+2]), \n                                            Col.HalfToUInt(da[i+1]), \n                                            Col.HalfToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.B);\n                                    da[i+1] = Col.UIntToHalf(v.G);\n                                    da[i+2] = Col.UIntToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.HalfToUInt(da[i+d2]), \n                                            Col.HalfToUInt(da[i+d1]), \n                                            Col.HalfToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.B);\n                                    da[i+d1] = Col.UIntToHalf(v.G);\n                                    da[i+d2] = Col.UIntToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C3ui\n\n                {\n                    (typeof(Half), typeof(C3ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+1]), \n                                            Col.HalfToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.R);\n                                    da[i+1] = Col.UIntToHalf(v.G);\n                                    da[i+2] = Col.UIntToHalf(v.B);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+d1]), \n                                            Col.HalfToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.R);\n                                    da[i+d1] = Col.UIntToHalf(v.G);\n                                    da[i+d2] = Col.UIntToHalf(v.B);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C3ui\n\n                {\n                    (typeof(Half), typeof(C3ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.HalfToUInt(da[i+2]), \n                                            Col.HalfToUInt(da[i+1]), \n                                            Col.HalfToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.B);\n                                    da[i+1] = Col.UIntToHalf(v.G);\n                                    da[i+2] = Col.UIntToHalf(v.R);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.HalfToUInt(da[i+d2]), \n                                            Col.HalfToUInt(da[i+d1]), \n                                            Col.HalfToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.B);\n                                    da[i+d1] = Col.UIntToHalf(v.G);\n                                    da[i+d2] = Col.UIntToHalf(v.R);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C3f\n\n                {\n                    (typeof(Half), typeof(C3f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+1]), \n                                            Col.HalfToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.R);\n                                    da[i+1] = Col.FloatToHalf(v.G);\n                                    da[i+2] = Col.FloatToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+d1]), \n                                            Col.HalfToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.R);\n                                    da[i+d1] = Col.FloatToHalf(v.G);\n                                    da[i+d2] = Col.FloatToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C3f\n\n                {\n                    (typeof(Half), typeof(C3f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.HalfToFloat(da[i+2]), \n                                            Col.HalfToFloat(da[i+1]), \n                                            Col.HalfToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.B);\n                                    da[i+1] = Col.FloatToHalf(v.G);\n                                    da[i+2] = Col.FloatToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.HalfToFloat(da[i+d2]), \n                                            Col.HalfToFloat(da[i+d1]), \n                                            Col.HalfToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.B);\n                                    da[i+d1] = Col.FloatToHalf(v.G);\n                                    da[i+d2] = Col.FloatToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C3f\n\n                {\n                    (typeof(Half), typeof(C3f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+1]), \n                                            Col.HalfToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.R);\n                                    da[i+1] = Col.FloatToHalf(v.G);\n                                    da[i+2] = Col.FloatToHalf(v.B);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+d1]), \n                                            Col.HalfToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.R);\n                                    da[i+d1] = Col.FloatToHalf(v.G);\n                                    da[i+d2] = Col.FloatToHalf(v.B);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C3f\n\n                {\n                    (typeof(Half), typeof(C3f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.HalfToFloat(da[i+2]), \n                                            Col.HalfToFloat(da[i+1]), \n                                            Col.HalfToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.B);\n                                    da[i+1] = Col.FloatToHalf(v.G);\n                                    da[i+2] = Col.FloatToHalf(v.R);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.HalfToFloat(da[i+d2]), \n                                            Col.HalfToFloat(da[i+d1]), \n                                            Col.HalfToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.B);\n                                    da[i+d1] = Col.FloatToHalf(v.G);\n                                    da[i+d2] = Col.FloatToHalf(v.R);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C3d\n\n                {\n                    (typeof(Half), typeof(C3d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+1]), \n                                            Col.HalfToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.R);\n                                    da[i+1] = Col.DoubleToHalf(v.G);\n                                    da[i+2] = Col.DoubleToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+d1]), \n                                            Col.HalfToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.R);\n                                    da[i+d1] = Col.DoubleToHalf(v.G);\n                                    da[i+d2] = Col.DoubleToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C3d\n\n                {\n                    (typeof(Half), typeof(C3d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.HalfToDouble(da[i+2]), \n                                            Col.HalfToDouble(da[i+1]), \n                                            Col.HalfToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.B);\n                                    da[i+1] = Col.DoubleToHalf(v.G);\n                                    da[i+2] = Col.DoubleToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.HalfToDouble(da[i+d2]), \n                                            Col.HalfToDouble(da[i+d1]), \n                                            Col.HalfToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.B);\n                                    da[i+d1] = Col.DoubleToHalf(v.G);\n                                    da[i+d2] = Col.DoubleToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C3d\n\n                {\n                    (typeof(Half), typeof(C3d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+1]), \n                                            Col.HalfToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.R);\n                                    da[i+1] = Col.DoubleToHalf(v.G);\n                                    da[i+2] = Col.DoubleToHalf(v.B);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+d1]), \n                                            Col.HalfToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.R);\n                                    da[i+d1] = Col.DoubleToHalf(v.G);\n                                    da[i+d2] = Col.DoubleToHalf(v.B);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C3d\n\n                {\n                    (typeof(Half), typeof(C3d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.HalfToDouble(da[i+2]), \n                                            Col.HalfToDouble(da[i+1]), \n                                            Col.HalfToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.B);\n                                    da[i+1] = Col.DoubleToHalf(v.G);\n                                    da[i+2] = Col.DoubleToHalf(v.R);\n                                    da[i+3] = (Half)Half.One;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.HalfToDouble(da[i+d2]), \n                                            Col.HalfToDouble(da[i+d1]), \n                                            Col.HalfToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.B);\n                                    da[i+d1] = Col.DoubleToHalf(v.G);\n                                    da[i+d2] = Col.DoubleToHalf(v.R);\n                                    da[i+d3] = (Half)Half.One;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C4b\n\n                {\n                    (typeof(Half), typeof(C4b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+1]), \n                                            Col.HalfToByte(da[i+2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.R);\n                                    da[i+1] = Col.ByteToHalf(v.G);\n                                    da[i+2] = Col.ByteToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+d1]), \n                                            Col.HalfToByte(da[i+d2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.R);\n                                    da[i+d1] = Col.ByteToHalf(v.G);\n                                    da[i+d2] = Col.ByteToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C4b\n\n                {\n                    (typeof(Half), typeof(C4b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.HalfToByte(da[i+2]), \n                                            Col.HalfToByte(da[i+1]), \n                                            Col.HalfToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.B);\n                                    da[i+1] = Col.ByteToHalf(v.G);\n                                    da[i+2] = Col.ByteToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.HalfToByte(da[i+d2]), \n                                            Col.HalfToByte(da[i+d1]), \n                                            Col.HalfToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.B);\n                                    da[i+d1] = Col.ByteToHalf(v.G);\n                                    da[i+d2] = Col.ByteToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C4b\n\n                {\n                    (typeof(Half), typeof(C4b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+1]), \n                                            Col.HalfToByte(da[i+2]), \n                                            Col.HalfToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.R);\n                                    da[i+1] = Col.ByteToHalf(v.G);\n                                    da[i+2] = Col.ByteToHalf(v.B);\n                                    da[i+3] = Col.ByteToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+d1]), \n                                            Col.HalfToByte(da[i+d2]), \n                                            Col.HalfToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.R);\n                                    da[i+d1] = Col.ByteToHalf(v.G);\n                                    da[i+d2] = Col.ByteToHalf(v.B);\n                                    da[i+d3] = Col.ByteToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C4b\n\n                {\n                    (typeof(Half), typeof(C4b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.HalfToByte(da[i+2]), \n                                            Col.HalfToByte(da[i+1]), \n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.B);\n                                    da[i+1] = Col.ByteToHalf(v.G);\n                                    da[i+2] = Col.ByteToHalf(v.R);\n                                    da[i+3] = Col.ByteToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.HalfToByte(da[i+d2]), \n                                            Col.HalfToByte(da[i+d1]), \n                                            Col.HalfToByte(da[i]), \n                                            Col.HalfToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToHalf(v.B);\n                                    da[i+d1] = Col.ByteToHalf(v.G);\n                                    da[i+d2] = Col.ByteToHalf(v.R);\n                                    da[i+d3] = Col.ByteToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C4us\n\n                {\n                    (typeof(Half), typeof(C4us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+1]), \n                                            Col.HalfToUShort(da[i+2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.R);\n                                    da[i+1] = Col.UShortToHalf(v.G);\n                                    da[i+2] = Col.UShortToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+d1]), \n                                            Col.HalfToUShort(da[i+d2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.R);\n                                    da[i+d1] = Col.UShortToHalf(v.G);\n                                    da[i+d2] = Col.UShortToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C4us\n\n                {\n                    (typeof(Half), typeof(C4us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.HalfToUShort(da[i+2]), \n                                            Col.HalfToUShort(da[i+1]), \n                                            Col.HalfToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.B);\n                                    da[i+1] = Col.UShortToHalf(v.G);\n                                    da[i+2] = Col.UShortToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.HalfToUShort(da[i+d2]), \n                                            Col.HalfToUShort(da[i+d1]), \n                                            Col.HalfToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.B);\n                                    da[i+d1] = Col.UShortToHalf(v.G);\n                                    da[i+d2] = Col.UShortToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C4us\n\n                {\n                    (typeof(Half), typeof(C4us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+1]), \n                                            Col.HalfToUShort(da[i+2]), \n                                            Col.HalfToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.R);\n                                    da[i+1] = Col.UShortToHalf(v.G);\n                                    da[i+2] = Col.UShortToHalf(v.B);\n                                    da[i+3] = Col.UShortToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+d1]), \n                                            Col.HalfToUShort(da[i+d2]), \n                                            Col.HalfToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.R);\n                                    da[i+d1] = Col.UShortToHalf(v.G);\n                                    da[i+d2] = Col.UShortToHalf(v.B);\n                                    da[i+d3] = Col.UShortToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C4us\n\n                {\n                    (typeof(Half), typeof(C4us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.HalfToUShort(da[i+2]), \n                                            Col.HalfToUShort(da[i+1]), \n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.B);\n                                    da[i+1] = Col.UShortToHalf(v.G);\n                                    da[i+2] = Col.UShortToHalf(v.R);\n                                    da[i+3] = Col.UShortToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.HalfToUShort(da[i+d2]), \n                                            Col.HalfToUShort(da[i+d1]), \n                                            Col.HalfToUShort(da[i]), \n                                            Col.HalfToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToHalf(v.B);\n                                    da[i+d1] = Col.UShortToHalf(v.G);\n                                    da[i+d2] = Col.UShortToHalf(v.R);\n                                    da[i+d3] = Col.UShortToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C4ui\n\n                {\n                    (typeof(Half), typeof(C4ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+1]), \n                                            Col.HalfToUInt(da[i+2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.R);\n                                    da[i+1] = Col.UIntToHalf(v.G);\n                                    da[i+2] = Col.UIntToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+d1]), \n                                            Col.HalfToUInt(da[i+d2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.R);\n                                    da[i+d1] = Col.UIntToHalf(v.G);\n                                    da[i+d2] = Col.UIntToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C4ui\n\n                {\n                    (typeof(Half), typeof(C4ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.HalfToUInt(da[i+2]), \n                                            Col.HalfToUInt(da[i+1]), \n                                            Col.HalfToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.B);\n                                    da[i+1] = Col.UIntToHalf(v.G);\n                                    da[i+2] = Col.UIntToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.HalfToUInt(da[i+d2]), \n                                            Col.HalfToUInt(da[i+d1]), \n                                            Col.HalfToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.B);\n                                    da[i+d1] = Col.UIntToHalf(v.G);\n                                    da[i+d2] = Col.UIntToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C4ui\n\n                {\n                    (typeof(Half), typeof(C4ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+1]), \n                                            Col.HalfToUInt(da[i+2]), \n                                            Col.HalfToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.R);\n                                    da[i+1] = Col.UIntToHalf(v.G);\n                                    da[i+2] = Col.UIntToHalf(v.B);\n                                    da[i+3] = Col.UIntToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+d1]), \n                                            Col.HalfToUInt(da[i+d2]), \n                                            Col.HalfToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.R);\n                                    da[i+d1] = Col.UIntToHalf(v.G);\n                                    da[i+d2] = Col.UIntToHalf(v.B);\n                                    da[i+d3] = Col.UIntToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C4ui\n\n                {\n                    (typeof(Half), typeof(C4ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.HalfToUInt(da[i+2]), \n                                            Col.HalfToUInt(da[i+1]), \n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.B);\n                                    da[i+1] = Col.UIntToHalf(v.G);\n                                    da[i+2] = Col.UIntToHalf(v.R);\n                                    da[i+3] = Col.UIntToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.HalfToUInt(da[i+d2]), \n                                            Col.HalfToUInt(da[i+d1]), \n                                            Col.HalfToUInt(da[i]), \n                                            Col.HalfToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToHalf(v.B);\n                                    da[i+d1] = Col.UIntToHalf(v.G);\n                                    da[i+d2] = Col.UIntToHalf(v.R);\n                                    da[i+d3] = Col.UIntToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C4f\n\n                {\n                    (typeof(Half), typeof(C4f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+1]), \n                                            Col.HalfToFloat(da[i+2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.R);\n                                    da[i+1] = Col.FloatToHalf(v.G);\n                                    da[i+2] = Col.FloatToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+d1]), \n                                            Col.HalfToFloat(da[i+d2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.R);\n                                    da[i+d1] = Col.FloatToHalf(v.G);\n                                    da[i+d2] = Col.FloatToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C4f\n\n                {\n                    (typeof(Half), typeof(C4f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.HalfToFloat(da[i+2]), \n                                            Col.HalfToFloat(da[i+1]), \n                                            Col.HalfToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.B);\n                                    da[i+1] = Col.FloatToHalf(v.G);\n                                    da[i+2] = Col.FloatToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.HalfToFloat(da[i+d2]), \n                                            Col.HalfToFloat(da[i+d1]), \n                                            Col.HalfToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.B);\n                                    da[i+d1] = Col.FloatToHalf(v.G);\n                                    da[i+d2] = Col.FloatToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C4f\n\n                {\n                    (typeof(Half), typeof(C4f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+1]), \n                                            Col.HalfToFloat(da[i+2]), \n                                            Col.HalfToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.R);\n                                    da[i+1] = Col.FloatToHalf(v.G);\n                                    da[i+2] = Col.FloatToHalf(v.B);\n                                    da[i+3] = Col.FloatToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+d1]), \n                                            Col.HalfToFloat(da[i+d2]), \n                                            Col.HalfToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.R);\n                                    da[i+d1] = Col.FloatToHalf(v.G);\n                                    da[i+d2] = Col.FloatToHalf(v.B);\n                                    da[i+d3] = Col.FloatToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C4f\n\n                {\n                    (typeof(Half), typeof(C4f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.HalfToFloat(da[i+2]), \n                                            Col.HalfToFloat(da[i+1]), \n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.B);\n                                    da[i+1] = Col.FloatToHalf(v.G);\n                                    da[i+2] = Col.FloatToHalf(v.R);\n                                    da[i+3] = Col.FloatToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.HalfToFloat(da[i+d2]), \n                                            Col.HalfToFloat(da[i+d1]), \n                                            Col.HalfToFloat(da[i]), \n                                            Col.HalfToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToHalf(v.B);\n                                    da[i+d1] = Col.FloatToHalf(v.G);\n                                    da[i+d2] = Col.FloatToHalf(v.R);\n                                    da[i+d3] = Col.FloatToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB Halfs as C4d\n\n                {\n                    (typeof(Half), typeof(C4d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+1]), \n                                            Col.HalfToDouble(da[i+2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.R);\n                                    da[i+1] = Col.DoubleToHalf(v.G);\n                                    da[i+2] = Col.DoubleToHalf(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+d1]), \n                                            Col.HalfToDouble(da[i+d2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.R);\n                                    da[i+d1] = Col.DoubleToHalf(v.G);\n                                    da[i+d2] = Col.DoubleToHalf(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR Halfs as C4d\n\n                {\n                    (typeof(Half), typeof(C4d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.HalfToDouble(da[i+2]), \n                                            Col.HalfToDouble(da[i+1]), \n                                            Col.HalfToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.B);\n                                    da[i+1] = Col.DoubleToHalf(v.G);\n                                    da[i+2] = Col.DoubleToHalf(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<Half, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.HalfToDouble(da[i+d2]), \n                                            Col.HalfToDouble(da[i+d1]), \n                                            Col.HalfToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.B);\n                                    da[i+d1] = Col.DoubleToHalf(v.G);\n                                    da[i+d2] = Col.DoubleToHalf(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA Halfs as C4d\n\n                {\n                    (typeof(Half), typeof(C4d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+1]), \n                                            Col.HalfToDouble(da[i+2]), \n                                            Col.HalfToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.R);\n                                    da[i+1] = Col.DoubleToHalf(v.G);\n                                    da[i+2] = Col.DoubleToHalf(v.B);\n                                    da[i+3] = Col.DoubleToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+d1]), \n                                            Col.HalfToDouble(da[i+d2]), \n                                            Col.HalfToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.R);\n                                    da[i+d1] = Col.DoubleToHalf(v.G);\n                                    da[i+d2] = Col.DoubleToHalf(v.B);\n                                    da[i+d3] = Col.DoubleToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA Halfs as C4d\n\n                {\n                    (typeof(Half), typeof(C4d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<Half, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.HalfToDouble(da[i+2]), \n                                            Col.HalfToDouble(da[i+1]), \n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.B);\n                                    da[i+1] = Col.DoubleToHalf(v.G);\n                                    da[i+2] = Col.DoubleToHalf(v.R);\n                                    da[i+3] = Col.DoubleToHalf(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<Half, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.HalfToDouble(da[i+d2]), \n                                            Col.HalfToDouble(da[i+d1]), \n                                            Col.HalfToDouble(da[i]), \n                                            Col.HalfToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToHalf(v.B);\n                                    da[i+d1] = Col.DoubleToHalf(v.G);\n                                    da[i+d2] = Col.DoubleToHalf(v.R);\n                                    da[i+d3] = Col.DoubleToHalf(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C3b\n\n                {\n                    (typeof(float), typeof(C3b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+1]), \n                                            Col.FloatToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.R);\n                                    da[i+1] = Col.ByteToFloat(v.G);\n                                    da[i+2] = Col.ByteToFloat(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+d1]), \n                                            Col.FloatToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.R);\n                                    da[i+d1] = Col.ByteToFloat(v.G);\n                                    da[i+d2] = Col.ByteToFloat(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C3b\n\n                {\n                    (typeof(float), typeof(C3b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.FloatToByte(da[i+2]), \n                                            Col.FloatToByte(da[i+1]), \n                                            Col.FloatToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.B);\n                                    da[i+1] = Col.ByteToFloat(v.G);\n                                    da[i+2] = Col.ByteToFloat(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.FloatToByte(da[i+d2]), \n                                            Col.FloatToByte(da[i+d1]), \n                                            Col.FloatToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.B);\n                                    da[i+d1] = Col.ByteToFloat(v.G);\n                                    da[i+d2] = Col.ByteToFloat(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C3b\n\n                {\n                    (typeof(float), typeof(C3b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+1]), \n                                            Col.FloatToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.R);\n                                    da[i+1] = Col.ByteToFloat(v.G);\n                                    da[i+2] = Col.ByteToFloat(v.B);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+d1]), \n                                            Col.FloatToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.R);\n                                    da[i+d1] = Col.ByteToFloat(v.G);\n                                    da[i+d2] = Col.ByteToFloat(v.B);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C3b\n\n                {\n                    (typeof(float), typeof(C3b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.FloatToByte(da[i+2]), \n                                            Col.FloatToByte(da[i+1]), \n                                            Col.FloatToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.B);\n                                    da[i+1] = Col.ByteToFloat(v.G);\n                                    da[i+2] = Col.ByteToFloat(v.R);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.FloatToByte(da[i+d2]), \n                                            Col.FloatToByte(da[i+d1]), \n                                            Col.FloatToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.B);\n                                    da[i+d1] = Col.ByteToFloat(v.G);\n                                    da[i+d2] = Col.ByteToFloat(v.R);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C3us\n\n                {\n                    (typeof(float), typeof(C3us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+1]), \n                                            Col.FloatToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.R);\n                                    da[i+1] = Col.UShortToFloat(v.G);\n                                    da[i+2] = Col.UShortToFloat(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+d1]), \n                                            Col.FloatToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.R);\n                                    da[i+d1] = Col.UShortToFloat(v.G);\n                                    da[i+d2] = Col.UShortToFloat(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C3us\n\n                {\n                    (typeof(float), typeof(C3us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.FloatToUShort(da[i+2]), \n                                            Col.FloatToUShort(da[i+1]), \n                                            Col.FloatToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.B);\n                                    da[i+1] = Col.UShortToFloat(v.G);\n                                    da[i+2] = Col.UShortToFloat(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.FloatToUShort(da[i+d2]), \n                                            Col.FloatToUShort(da[i+d1]), \n                                            Col.FloatToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.B);\n                                    da[i+d1] = Col.UShortToFloat(v.G);\n                                    da[i+d2] = Col.UShortToFloat(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C3us\n\n                {\n                    (typeof(float), typeof(C3us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+1]), \n                                            Col.FloatToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.R);\n                                    da[i+1] = Col.UShortToFloat(v.G);\n                                    da[i+2] = Col.UShortToFloat(v.B);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+d1]), \n                                            Col.FloatToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.R);\n                                    da[i+d1] = Col.UShortToFloat(v.G);\n                                    da[i+d2] = Col.UShortToFloat(v.B);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C3us\n\n                {\n                    (typeof(float), typeof(C3us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.FloatToUShort(da[i+2]), \n                                            Col.FloatToUShort(da[i+1]), \n                                            Col.FloatToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.B);\n                                    da[i+1] = Col.UShortToFloat(v.G);\n                                    da[i+2] = Col.UShortToFloat(v.R);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.FloatToUShort(da[i+d2]), \n                                            Col.FloatToUShort(da[i+d1]), \n                                            Col.FloatToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.B);\n                                    da[i+d1] = Col.UShortToFloat(v.G);\n                                    da[i+d2] = Col.UShortToFloat(v.R);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C3ui\n\n                {\n                    (typeof(float), typeof(C3ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+1]), \n                                            Col.FloatToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.R);\n                                    da[i+1] = Col.UIntToFloat(v.G);\n                                    da[i+2] = Col.UIntToFloat(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+d1]), \n                                            Col.FloatToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.R);\n                                    da[i+d1] = Col.UIntToFloat(v.G);\n                                    da[i+d2] = Col.UIntToFloat(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C3ui\n\n                {\n                    (typeof(float), typeof(C3ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.FloatToUInt(da[i+2]), \n                                            Col.FloatToUInt(da[i+1]), \n                                            Col.FloatToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.B);\n                                    da[i+1] = Col.UIntToFloat(v.G);\n                                    da[i+2] = Col.UIntToFloat(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.FloatToUInt(da[i+d2]), \n                                            Col.FloatToUInt(da[i+d1]), \n                                            Col.FloatToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.B);\n                                    da[i+d1] = Col.UIntToFloat(v.G);\n                                    da[i+d2] = Col.UIntToFloat(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C3ui\n\n                {\n                    (typeof(float), typeof(C3ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+1]), \n                                            Col.FloatToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.R);\n                                    da[i+1] = Col.UIntToFloat(v.G);\n                                    da[i+2] = Col.UIntToFloat(v.B);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+d1]), \n                                            Col.FloatToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.R);\n                                    da[i+d1] = Col.UIntToFloat(v.G);\n                                    da[i+d2] = Col.UIntToFloat(v.B);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C3ui\n\n                {\n                    (typeof(float), typeof(C3ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.FloatToUInt(da[i+2]), \n                                            Col.FloatToUInt(da[i+1]), \n                                            Col.FloatToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.B);\n                                    da[i+1] = Col.UIntToFloat(v.G);\n                                    da[i+2] = Col.UIntToFloat(v.R);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.FloatToUInt(da[i+d2]), \n                                            Col.FloatToUInt(da[i+d1]), \n                                            Col.FloatToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.B);\n                                    da[i+d1] = Col.UIntToFloat(v.G);\n                                    da[i+d2] = Col.UIntToFloat(v.R);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C3f\n\n                {\n                    (typeof(float), typeof(C3f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C3f\n\n                {\n                    (typeof(float), typeof(C3f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C3f\n\n                {\n                    (typeof(float), typeof(C3f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C3f\n\n                {\n                    (typeof(float), typeof(C3f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C3d\n\n                {\n                    (typeof(float), typeof(C3d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+1]), \n                                            Col.FloatToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.R);\n                                    da[i+1] = Col.DoubleToFloat(v.G);\n                                    da[i+2] = Col.DoubleToFloat(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+d1]), \n                                            Col.FloatToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.R);\n                                    da[i+d1] = Col.DoubleToFloat(v.G);\n                                    da[i+d2] = Col.DoubleToFloat(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C3d\n\n                {\n                    (typeof(float), typeof(C3d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.FloatToDouble(da[i+2]), \n                                            Col.FloatToDouble(da[i+1]), \n                                            Col.FloatToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.B);\n                                    da[i+1] = Col.DoubleToFloat(v.G);\n                                    da[i+2] = Col.DoubleToFloat(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.FloatToDouble(da[i+d2]), \n                                            Col.FloatToDouble(da[i+d1]), \n                                            Col.FloatToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.B);\n                                    da[i+d1] = Col.DoubleToFloat(v.G);\n                                    da[i+d2] = Col.DoubleToFloat(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C3d\n\n                {\n                    (typeof(float), typeof(C3d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+1]), \n                                            Col.FloatToDouble(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.R);\n                                    da[i+1] = Col.DoubleToFloat(v.G);\n                                    da[i+2] = Col.DoubleToFloat(v.B);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+d1]), \n                                            Col.FloatToDouble(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.R);\n                                    da[i+d1] = Col.DoubleToFloat(v.G);\n                                    da[i+d2] = Col.DoubleToFloat(v.B);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C3d\n\n                {\n                    (typeof(float), typeof(C3d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.FloatToDouble(da[i+2]), \n                                            Col.FloatToDouble(da[i+1]), \n                                            Col.FloatToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.B);\n                                    da[i+1] = Col.DoubleToFloat(v.G);\n                                    da[i+2] = Col.DoubleToFloat(v.R);\n                                    da[i+3] = (float)1.0f;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            Col.FloatToDouble(da[i+d2]), \n                                            Col.FloatToDouble(da[i+d1]), \n                                            Col.FloatToDouble(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.B);\n                                    da[i+d1] = Col.DoubleToFloat(v.G);\n                                    da[i+d2] = Col.DoubleToFloat(v.R);\n                                    da[i+d3] = (float)1.0f;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C4b\n\n                {\n                    (typeof(float), typeof(C4b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+1]), \n                                            Col.FloatToByte(da[i+2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.R);\n                                    da[i+1] = Col.ByteToFloat(v.G);\n                                    da[i+2] = Col.ByteToFloat(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+d1]), \n                                            Col.FloatToByte(da[i+d2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.R);\n                                    da[i+d1] = Col.ByteToFloat(v.G);\n                                    da[i+d2] = Col.ByteToFloat(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C4b\n\n                {\n                    (typeof(float), typeof(C4b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.FloatToByte(da[i+2]), \n                                            Col.FloatToByte(da[i+1]), \n                                            Col.FloatToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.B);\n                                    da[i+1] = Col.ByteToFloat(v.G);\n                                    da[i+2] = Col.ByteToFloat(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.FloatToByte(da[i+d2]), \n                                            Col.FloatToByte(da[i+d1]), \n                                            Col.FloatToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.B);\n                                    da[i+d1] = Col.ByteToFloat(v.G);\n                                    da[i+d2] = Col.ByteToFloat(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C4b\n\n                {\n                    (typeof(float), typeof(C4b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+1]), \n                                            Col.FloatToByte(da[i+2]), \n                                            Col.FloatToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.R);\n                                    da[i+1] = Col.ByteToFloat(v.G);\n                                    da[i+2] = Col.ByteToFloat(v.B);\n                                    da[i+3] = Col.ByteToFloat(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+d1]), \n                                            Col.FloatToByte(da[i+d2]), \n                                            Col.FloatToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.R);\n                                    da[i+d1] = Col.ByteToFloat(v.G);\n                                    da[i+d2] = Col.ByteToFloat(v.B);\n                                    da[i+d3] = Col.ByteToFloat(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C4b\n\n                {\n                    (typeof(float), typeof(C4b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.FloatToByte(da[i+2]), \n                                            Col.FloatToByte(da[i+1]), \n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.B);\n                                    da[i+1] = Col.ByteToFloat(v.G);\n                                    da[i+2] = Col.ByteToFloat(v.R);\n                                    da[i+3] = Col.ByteToFloat(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.FloatToByte(da[i+d2]), \n                                            Col.FloatToByte(da[i+d1]), \n                                            Col.FloatToByte(da[i]), \n                                            Col.FloatToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToFloat(v.B);\n                                    da[i+d1] = Col.ByteToFloat(v.G);\n                                    da[i+d2] = Col.ByteToFloat(v.R);\n                                    da[i+d3] = Col.ByteToFloat(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C4us\n\n                {\n                    (typeof(float), typeof(C4us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+1]), \n                                            Col.FloatToUShort(da[i+2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.R);\n                                    da[i+1] = Col.UShortToFloat(v.G);\n                                    da[i+2] = Col.UShortToFloat(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+d1]), \n                                            Col.FloatToUShort(da[i+d2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.R);\n                                    da[i+d1] = Col.UShortToFloat(v.G);\n                                    da[i+d2] = Col.UShortToFloat(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C4us\n\n                {\n                    (typeof(float), typeof(C4us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.FloatToUShort(da[i+2]), \n                                            Col.FloatToUShort(da[i+1]), \n                                            Col.FloatToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.B);\n                                    da[i+1] = Col.UShortToFloat(v.G);\n                                    da[i+2] = Col.UShortToFloat(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.FloatToUShort(da[i+d2]), \n                                            Col.FloatToUShort(da[i+d1]), \n                                            Col.FloatToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.B);\n                                    da[i+d1] = Col.UShortToFloat(v.G);\n                                    da[i+d2] = Col.UShortToFloat(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C4us\n\n                {\n                    (typeof(float), typeof(C4us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+1]), \n                                            Col.FloatToUShort(da[i+2]), \n                                            Col.FloatToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.R);\n                                    da[i+1] = Col.UShortToFloat(v.G);\n                                    da[i+2] = Col.UShortToFloat(v.B);\n                                    da[i+3] = Col.UShortToFloat(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+d1]), \n                                            Col.FloatToUShort(da[i+d2]), \n                                            Col.FloatToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.R);\n                                    da[i+d1] = Col.UShortToFloat(v.G);\n                                    da[i+d2] = Col.UShortToFloat(v.B);\n                                    da[i+d3] = Col.UShortToFloat(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C4us\n\n                {\n                    (typeof(float), typeof(C4us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.FloatToUShort(da[i+2]), \n                                            Col.FloatToUShort(da[i+1]), \n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.B);\n                                    da[i+1] = Col.UShortToFloat(v.G);\n                                    da[i+2] = Col.UShortToFloat(v.R);\n                                    da[i+3] = Col.UShortToFloat(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.FloatToUShort(da[i+d2]), \n                                            Col.FloatToUShort(da[i+d1]), \n                                            Col.FloatToUShort(da[i]), \n                                            Col.FloatToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToFloat(v.B);\n                                    da[i+d1] = Col.UShortToFloat(v.G);\n                                    da[i+d2] = Col.UShortToFloat(v.R);\n                                    da[i+d3] = Col.UShortToFloat(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C4ui\n\n                {\n                    (typeof(float), typeof(C4ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+1]), \n                                            Col.FloatToUInt(da[i+2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.R);\n                                    da[i+1] = Col.UIntToFloat(v.G);\n                                    da[i+2] = Col.UIntToFloat(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+d1]), \n                                            Col.FloatToUInt(da[i+d2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.R);\n                                    da[i+d1] = Col.UIntToFloat(v.G);\n                                    da[i+d2] = Col.UIntToFloat(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C4ui\n\n                {\n                    (typeof(float), typeof(C4ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.FloatToUInt(da[i+2]), \n                                            Col.FloatToUInt(da[i+1]), \n                                            Col.FloatToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.B);\n                                    da[i+1] = Col.UIntToFloat(v.G);\n                                    da[i+2] = Col.UIntToFloat(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.FloatToUInt(da[i+d2]), \n                                            Col.FloatToUInt(da[i+d1]), \n                                            Col.FloatToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.B);\n                                    da[i+d1] = Col.UIntToFloat(v.G);\n                                    da[i+d2] = Col.UIntToFloat(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C4ui\n\n                {\n                    (typeof(float), typeof(C4ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+1]), \n                                            Col.FloatToUInt(da[i+2]), \n                                            Col.FloatToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.R);\n                                    da[i+1] = Col.UIntToFloat(v.G);\n                                    da[i+2] = Col.UIntToFloat(v.B);\n                                    da[i+3] = Col.UIntToFloat(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+d1]), \n                                            Col.FloatToUInt(da[i+d2]), \n                                            Col.FloatToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.R);\n                                    da[i+d1] = Col.UIntToFloat(v.G);\n                                    da[i+d2] = Col.UIntToFloat(v.B);\n                                    da[i+d3] = Col.UIntToFloat(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C4ui\n\n                {\n                    (typeof(float), typeof(C4ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.FloatToUInt(da[i+2]), \n                                            Col.FloatToUInt(da[i+1]), \n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.B);\n                                    da[i+1] = Col.UIntToFloat(v.G);\n                                    da[i+2] = Col.UIntToFloat(v.R);\n                                    da[i+3] = Col.UIntToFloat(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.FloatToUInt(da[i+d2]), \n                                            Col.FloatToUInt(da[i+d1]), \n                                            Col.FloatToUInt(da[i]), \n                                            Col.FloatToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToFloat(v.B);\n                                    da[i+d1] = Col.UIntToFloat(v.G);\n                                    da[i+d2] = Col.UIntToFloat(v.R);\n                                    da[i+d3] = Col.UIntToFloat(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C4f\n\n                {\n                    (typeof(float), typeof(C4f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C4f\n\n                {\n                    (typeof(float), typeof(C4f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C4f\n\n                {\n                    (typeof(float), typeof(C4f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C4f\n\n                {\n                    (typeof(float), typeof(C4f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB floats as C4d\n\n                {\n                    (typeof(float), typeof(C4d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+1]), \n                                            Col.FloatToDouble(da[i+2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.R);\n                                    da[i+1] = Col.DoubleToFloat(v.G);\n                                    da[i+2] = Col.DoubleToFloat(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+d1]), \n                                            Col.FloatToDouble(da[i+d2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.R);\n                                    da[i+d1] = Col.DoubleToFloat(v.G);\n                                    da[i+d2] = Col.DoubleToFloat(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR floats as C4d\n\n                {\n                    (typeof(float), typeof(C4d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.FloatToDouble(da[i+2]), \n                                            Col.FloatToDouble(da[i+1]), \n                                            Col.FloatToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.B);\n                                    da[i+1] = Col.DoubleToFloat(v.G);\n                                    da[i+2] = Col.DoubleToFloat(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<float, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.FloatToDouble(da[i+d2]), \n                                            Col.FloatToDouble(da[i+d1]), \n                                            Col.FloatToDouble(da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.B);\n                                    da[i+d1] = Col.DoubleToFloat(v.G);\n                                    da[i+d2] = Col.DoubleToFloat(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA floats as C4d\n\n                {\n                    (typeof(float), typeof(C4d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+1]), \n                                            Col.FloatToDouble(da[i+2]), \n                                            Col.FloatToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.R);\n                                    da[i+1] = Col.DoubleToFloat(v.G);\n                                    da[i+2] = Col.DoubleToFloat(v.B);\n                                    da[i+3] = Col.DoubleToFloat(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+d1]), \n                                            Col.FloatToDouble(da[i+d2]), \n                                            Col.FloatToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.R);\n                                    da[i+d1] = Col.DoubleToFloat(v.G);\n                                    da[i+d2] = Col.DoubleToFloat(v.B);\n                                    da[i+d3] = Col.DoubleToFloat(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA floats as C4d\n\n                {\n                    (typeof(float), typeof(C4d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<float, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.FloatToDouble(da[i+2]), \n                                            Col.FloatToDouble(da[i+1]), \n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.B);\n                                    da[i+1] = Col.DoubleToFloat(v.G);\n                                    da[i+2] = Col.DoubleToFloat(v.R);\n                                    da[i+3] = Col.DoubleToFloat(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<float, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            Col.FloatToDouble(da[i+d2]), \n                                            Col.FloatToDouble(da[i+d1]), \n                                            Col.FloatToDouble(da[i]), \n                                            Col.FloatToDouble(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.DoubleToFloat(v.B);\n                                    da[i+d1] = Col.DoubleToFloat(v.G);\n                                    da[i+d2] = Col.DoubleToFloat(v.R);\n                                    da[i+d3] = Col.DoubleToFloat(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C3b\n\n                {\n                    (typeof(double), typeof(C3b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+1]), \n                                            Col.DoubleToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.R);\n                                    da[i+1] = Col.ByteToDouble(v.G);\n                                    da[i+2] = Col.ByteToDouble(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+d1]), \n                                            Col.DoubleToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.R);\n                                    da[i+d1] = Col.ByteToDouble(v.G);\n                                    da[i+d2] = Col.ByteToDouble(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C3b\n\n                {\n                    (typeof(double), typeof(C3b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.DoubleToByte(da[i+2]), \n                                            Col.DoubleToByte(da[i+1]), \n                                            Col.DoubleToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.B);\n                                    da[i+1] = Col.ByteToDouble(v.G);\n                                    da[i+2] = Col.ByteToDouble(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.DoubleToByte(da[i+d2]), \n                                            Col.DoubleToByte(da[i+d1]), \n                                            Col.DoubleToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.B);\n                                    da[i+d1] = Col.ByteToDouble(v.G);\n                                    da[i+d2] = Col.ByteToDouble(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C3b\n\n                {\n                    (typeof(double), typeof(C3b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+1]), \n                                            Col.DoubleToByte(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.R);\n                                    da[i+1] = Col.ByteToDouble(v.G);\n                                    da[i+2] = Col.ByteToDouble(v.B);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+d1]), \n                                            Col.DoubleToByte(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.R);\n                                    da[i+d1] = Col.ByteToDouble(v.G);\n                                    da[i+d2] = Col.ByteToDouble(v.B);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C3b\n\n                {\n                    (typeof(double), typeof(C3b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.DoubleToByte(da[i+2]), \n                                            Col.DoubleToByte(da[i+1]), \n                                            Col.DoubleToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.B);\n                                    da[i+1] = Col.ByteToDouble(v.G);\n                                    da[i+2] = Col.ByteToDouble(v.R);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3b(\n                                            Col.DoubleToByte(da[i+d2]), \n                                            Col.DoubleToByte(da[i+d1]), \n                                            Col.DoubleToByte(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.B);\n                                    da[i+d1] = Col.ByteToDouble(v.G);\n                                    da[i+d2] = Col.ByteToDouble(v.R);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C3us\n\n                {\n                    (typeof(double), typeof(C3us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+1]), \n                                            Col.DoubleToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.R);\n                                    da[i+1] = Col.UShortToDouble(v.G);\n                                    da[i+2] = Col.UShortToDouble(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+d1]), \n                                            Col.DoubleToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.R);\n                                    da[i+d1] = Col.UShortToDouble(v.G);\n                                    da[i+d2] = Col.UShortToDouble(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C3us\n\n                {\n                    (typeof(double), typeof(C3us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.DoubleToUShort(da[i+2]), \n                                            Col.DoubleToUShort(da[i+1]), \n                                            Col.DoubleToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.B);\n                                    da[i+1] = Col.UShortToDouble(v.G);\n                                    da[i+2] = Col.UShortToDouble(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.DoubleToUShort(da[i+d2]), \n                                            Col.DoubleToUShort(da[i+d1]), \n                                            Col.DoubleToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.B);\n                                    da[i+d1] = Col.UShortToDouble(v.G);\n                                    da[i+d2] = Col.UShortToDouble(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C3us\n\n                {\n                    (typeof(double), typeof(C3us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+1]), \n                                            Col.DoubleToUShort(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.R);\n                                    da[i+1] = Col.UShortToDouble(v.G);\n                                    da[i+2] = Col.UShortToDouble(v.B);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+d1]), \n                                            Col.DoubleToUShort(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.R);\n                                    da[i+d1] = Col.UShortToDouble(v.G);\n                                    da[i+d2] = Col.UShortToDouble(v.B);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C3us\n\n                {\n                    (typeof(double), typeof(C3us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.DoubleToUShort(da[i+2]), \n                                            Col.DoubleToUShort(da[i+1]), \n                                            Col.DoubleToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.B);\n                                    da[i+1] = Col.UShortToDouble(v.G);\n                                    da[i+2] = Col.UShortToDouble(v.R);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3us(\n                                            Col.DoubleToUShort(da[i+d2]), \n                                            Col.DoubleToUShort(da[i+d1]), \n                                            Col.DoubleToUShort(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.B);\n                                    da[i+d1] = Col.UShortToDouble(v.G);\n                                    da[i+d2] = Col.UShortToDouble(v.R);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C3ui\n\n                {\n                    (typeof(double), typeof(C3ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+1]), \n                                            Col.DoubleToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.R);\n                                    da[i+1] = Col.UIntToDouble(v.G);\n                                    da[i+2] = Col.UIntToDouble(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+d1]), \n                                            Col.DoubleToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.R);\n                                    da[i+d1] = Col.UIntToDouble(v.G);\n                                    da[i+d2] = Col.UIntToDouble(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C3ui\n\n                {\n                    (typeof(double), typeof(C3ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.DoubleToUInt(da[i+2]), \n                                            Col.DoubleToUInt(da[i+1]), \n                                            Col.DoubleToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.B);\n                                    da[i+1] = Col.UIntToDouble(v.G);\n                                    da[i+2] = Col.UIntToDouble(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.DoubleToUInt(da[i+d2]), \n                                            Col.DoubleToUInt(da[i+d1]), \n                                            Col.DoubleToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.B);\n                                    da[i+d1] = Col.UIntToDouble(v.G);\n                                    da[i+d2] = Col.UIntToDouble(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C3ui\n\n                {\n                    (typeof(double), typeof(C3ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+1]), \n                                            Col.DoubleToUInt(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.R);\n                                    da[i+1] = Col.UIntToDouble(v.G);\n                                    da[i+2] = Col.UIntToDouble(v.B);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+d1]), \n                                            Col.DoubleToUInt(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.R);\n                                    da[i+d1] = Col.UIntToDouble(v.G);\n                                    da[i+d2] = Col.UIntToDouble(v.B);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C3ui\n\n                {\n                    (typeof(double), typeof(C3ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.DoubleToUInt(da[i+2]), \n                                            Col.DoubleToUInt(da[i+1]), \n                                            Col.DoubleToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.B);\n                                    da[i+1] = Col.UIntToDouble(v.G);\n                                    da[i+2] = Col.UIntToDouble(v.R);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3ui(\n                                            Col.DoubleToUInt(da[i+d2]), \n                                            Col.DoubleToUInt(da[i+d1]), \n                                            Col.DoubleToUInt(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.B);\n                                    da[i+d1] = Col.UIntToDouble(v.G);\n                                    da[i+d2] = Col.UIntToDouble(v.R);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C3f\n\n                {\n                    (typeof(double), typeof(C3f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+1]), \n                                            Col.DoubleToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.R);\n                                    da[i+1] = Col.FloatToDouble(v.G);\n                                    da[i+2] = Col.FloatToDouble(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+d1]), \n                                            Col.DoubleToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.R);\n                                    da[i+d1] = Col.FloatToDouble(v.G);\n                                    da[i+d2] = Col.FloatToDouble(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C3f\n\n                {\n                    (typeof(double), typeof(C3f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.DoubleToFloat(da[i+2]), \n                                            Col.DoubleToFloat(da[i+1]), \n                                            Col.DoubleToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.B);\n                                    da[i+1] = Col.FloatToDouble(v.G);\n                                    da[i+2] = Col.FloatToDouble(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.DoubleToFloat(da[i+d2]), \n                                            Col.DoubleToFloat(da[i+d1]), \n                                            Col.DoubleToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.B);\n                                    da[i+d1] = Col.FloatToDouble(v.G);\n                                    da[i+d2] = Col.FloatToDouble(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C3f\n\n                {\n                    (typeof(double), typeof(C3f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+1]), \n                                            Col.DoubleToFloat(da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.R);\n                                    da[i+1] = Col.FloatToDouble(v.G);\n                                    da[i+2] = Col.FloatToDouble(v.B);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+d1]), \n                                            Col.DoubleToFloat(da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.R);\n                                    da[i+d1] = Col.FloatToDouble(v.G);\n                                    da[i+d2] = Col.FloatToDouble(v.B);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C3f\n\n                {\n                    (typeof(double), typeof(C3f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.DoubleToFloat(da[i+2]), \n                                            Col.DoubleToFloat(da[i+1]), \n                                            Col.DoubleToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.B);\n                                    da[i+1] = Col.FloatToDouble(v.G);\n                                    da[i+2] = Col.FloatToDouble(v.R);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3f(\n                                            Col.DoubleToFloat(da[i+d2]), \n                                            Col.DoubleToFloat(da[i+d1]), \n                                            Col.DoubleToFloat(da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.B);\n                                    da[i+d1] = Col.FloatToDouble(v.G);\n                                    da[i+d2] = Col.FloatToDouble(v.R);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C3d\n\n                {\n                    (typeof(double), typeof(C3d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C3d\n\n                {\n                    (typeof(double), typeof(C3d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C3d\n\n                {\n                    (typeof(double), typeof(C3d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C3d\n\n                {\n                    (typeof(double), typeof(C3d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (double)1.0;\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C3d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C3d(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (double)1.0;\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C4b\n\n                {\n                    (typeof(double), typeof(C4b), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+1]), \n                                            Col.DoubleToByte(da[i+2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.R);\n                                    da[i+1] = Col.ByteToDouble(v.G);\n                                    da[i+2] = Col.ByteToDouble(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+d1]), \n                                            Col.DoubleToByte(da[i+d2]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.R);\n                                    da[i+d1] = Col.ByteToDouble(v.G);\n                                    da[i+d2] = Col.ByteToDouble(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C4b\n\n                {\n                    (typeof(double), typeof(C4b), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.DoubleToByte(da[i+2]), \n                                            Col.DoubleToByte(da[i+1]), \n                                            Col.DoubleToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.B);\n                                    da[i+1] = Col.ByteToDouble(v.G);\n                                    da[i+2] = Col.ByteToDouble(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.DoubleToByte(da[i+d2]), \n                                            Col.DoubleToByte(da[i+d1]), \n                                            Col.DoubleToByte(da[i]), \n                                            (byte)255),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.B);\n                                    da[i+d1] = Col.ByteToDouble(v.G);\n                                    da[i+d2] = Col.ByteToDouble(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C4b\n\n                {\n                    (typeof(double), typeof(C4b), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+1]), \n                                            Col.DoubleToByte(da[i+2]), \n                                            Col.DoubleToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.R);\n                                    da[i+1] = Col.ByteToDouble(v.G);\n                                    da[i+2] = Col.ByteToDouble(v.B);\n                                    da[i+3] = Col.ByteToDouble(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+d1]), \n                                            Col.DoubleToByte(da[i+d2]), \n                                            Col.DoubleToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.R);\n                                    da[i+d1] = Col.ByteToDouble(v.G);\n                                    da[i+d2] = Col.ByteToDouble(v.B);\n                                    da[i+d3] = Col.ByteToDouble(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C4b\n\n                {\n                    (typeof(double), typeof(C4b), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.DoubleToByte(da[i+2]), \n                                            Col.DoubleToByte(da[i+1]), \n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.B);\n                                    da[i+1] = Col.ByteToDouble(v.G);\n                                    da[i+2] = Col.ByteToDouble(v.R);\n                                    da[i+3] = Col.ByteToDouble(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4b>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4b(\n                                            Col.DoubleToByte(da[i+d2]), \n                                            Col.DoubleToByte(da[i+d1]), \n                                            Col.DoubleToByte(da[i]), \n                                            Col.DoubleToByte(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.ByteToDouble(v.B);\n                                    da[i+d1] = Col.ByteToDouble(v.G);\n                                    da[i+d2] = Col.ByteToDouble(v.R);\n                                    da[i+d3] = Col.ByteToDouble(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C4us\n\n                {\n                    (typeof(double), typeof(C4us), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+1]), \n                                            Col.DoubleToUShort(da[i+2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.R);\n                                    da[i+1] = Col.UShortToDouble(v.G);\n                                    da[i+2] = Col.UShortToDouble(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+d1]), \n                                            Col.DoubleToUShort(da[i+d2]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.R);\n                                    da[i+d1] = Col.UShortToDouble(v.G);\n                                    da[i+d2] = Col.UShortToDouble(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C4us\n\n                {\n                    (typeof(double), typeof(C4us), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.DoubleToUShort(da[i+2]), \n                                            Col.DoubleToUShort(da[i+1]), \n                                            Col.DoubleToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.B);\n                                    da[i+1] = Col.UShortToDouble(v.G);\n                                    da[i+2] = Col.UShortToDouble(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.DoubleToUShort(da[i+d2]), \n                                            Col.DoubleToUShort(da[i+d1]), \n                                            Col.DoubleToUShort(da[i]), \n                                            (ushort)65535),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.B);\n                                    da[i+d1] = Col.UShortToDouble(v.G);\n                                    da[i+d2] = Col.UShortToDouble(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C4us\n\n                {\n                    (typeof(double), typeof(C4us), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+1]), \n                                            Col.DoubleToUShort(da[i+2]), \n                                            Col.DoubleToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.R);\n                                    da[i+1] = Col.UShortToDouble(v.G);\n                                    da[i+2] = Col.UShortToDouble(v.B);\n                                    da[i+3] = Col.UShortToDouble(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+d1]), \n                                            Col.DoubleToUShort(da[i+d2]), \n                                            Col.DoubleToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.R);\n                                    da[i+d1] = Col.UShortToDouble(v.G);\n                                    da[i+d2] = Col.UShortToDouble(v.B);\n                                    da[i+d3] = Col.UShortToDouble(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C4us\n\n                {\n                    (typeof(double), typeof(C4us), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.DoubleToUShort(da[i+2]), \n                                            Col.DoubleToUShort(da[i+1]), \n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.B);\n                                    da[i+1] = Col.UShortToDouble(v.G);\n                                    da[i+2] = Col.UShortToDouble(v.R);\n                                    da[i+3] = Col.UShortToDouble(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4us>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4us(\n                                            Col.DoubleToUShort(da[i+d2]), \n                                            Col.DoubleToUShort(da[i+d1]), \n                                            Col.DoubleToUShort(da[i]), \n                                            Col.DoubleToUShort(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UShortToDouble(v.B);\n                                    da[i+d1] = Col.UShortToDouble(v.G);\n                                    da[i+d2] = Col.UShortToDouble(v.R);\n                                    da[i+d3] = Col.UShortToDouble(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C4ui\n\n                {\n                    (typeof(double), typeof(C4ui), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+1]), \n                                            Col.DoubleToUInt(da[i+2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.R);\n                                    da[i+1] = Col.UIntToDouble(v.G);\n                                    da[i+2] = Col.UIntToDouble(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+d1]), \n                                            Col.DoubleToUInt(da[i+d2]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.R);\n                                    da[i+d1] = Col.UIntToDouble(v.G);\n                                    da[i+d2] = Col.UIntToDouble(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C4ui\n\n                {\n                    (typeof(double), typeof(C4ui), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.DoubleToUInt(da[i+2]), \n                                            Col.DoubleToUInt(da[i+1]), \n                                            Col.DoubleToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.B);\n                                    da[i+1] = Col.UIntToDouble(v.G);\n                                    da[i+2] = Col.UIntToDouble(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.DoubleToUInt(da[i+d2]), \n                                            Col.DoubleToUInt(da[i+d1]), \n                                            Col.DoubleToUInt(da[i]), \n                                            (uint)UInt32.MaxValue),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.B);\n                                    da[i+d1] = Col.UIntToDouble(v.G);\n                                    da[i+d2] = Col.UIntToDouble(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C4ui\n\n                {\n                    (typeof(double), typeof(C4ui), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+1]), \n                                            Col.DoubleToUInt(da[i+2]), \n                                            Col.DoubleToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.R);\n                                    da[i+1] = Col.UIntToDouble(v.G);\n                                    da[i+2] = Col.UIntToDouble(v.B);\n                                    da[i+3] = Col.UIntToDouble(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+d1]), \n                                            Col.DoubleToUInt(da[i+d2]), \n                                            Col.DoubleToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.R);\n                                    da[i+d1] = Col.UIntToDouble(v.G);\n                                    da[i+d2] = Col.UIntToDouble(v.B);\n                                    da[i+d3] = Col.UIntToDouble(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C4ui\n\n                {\n                    (typeof(double), typeof(C4ui), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.DoubleToUInt(da[i+2]), \n                                            Col.DoubleToUInt(da[i+1]), \n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.B);\n                                    da[i+1] = Col.UIntToDouble(v.G);\n                                    da[i+2] = Col.UIntToDouble(v.R);\n                                    da[i+3] = Col.UIntToDouble(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4ui>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4ui(\n                                            Col.DoubleToUInt(da[i+d2]), \n                                            Col.DoubleToUInt(da[i+d1]), \n                                            Col.DoubleToUInt(da[i]), \n                                            Col.DoubleToUInt(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.UIntToDouble(v.B);\n                                    da[i+d1] = Col.UIntToDouble(v.G);\n                                    da[i+d2] = Col.UIntToDouble(v.R);\n                                    da[i+d3] = Col.UIntToDouble(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C4f\n\n                {\n                    (typeof(double), typeof(C4f), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+1]), \n                                            Col.DoubleToFloat(da[i+2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.R);\n                                    da[i+1] = Col.FloatToDouble(v.G);\n                                    da[i+2] = Col.FloatToDouble(v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+d1]), \n                                            Col.DoubleToFloat(da[i+d2]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.R);\n                                    da[i+d1] = Col.FloatToDouble(v.G);\n                                    da[i+d2] = Col.FloatToDouble(v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C4f\n\n                {\n                    (typeof(double), typeof(C4f), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.DoubleToFloat(da[i+2]), \n                                            Col.DoubleToFloat(da[i+1]), \n                                            Col.DoubleToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.B);\n                                    da[i+1] = Col.FloatToDouble(v.G);\n                                    da[i+2] = Col.FloatToDouble(v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.DoubleToFloat(da[i+d2]), \n                                            Col.DoubleToFloat(da[i+d1]), \n                                            Col.DoubleToFloat(da[i]), \n                                            (float)1.0f),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.B);\n                                    da[i+d1] = Col.FloatToDouble(v.G);\n                                    da[i+d2] = Col.FloatToDouble(v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C4f\n\n                {\n                    (typeof(double), typeof(C4f), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+1]), \n                                            Col.DoubleToFloat(da[i+2]), \n                                            Col.DoubleToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.R);\n                                    da[i+1] = Col.FloatToDouble(v.G);\n                                    da[i+2] = Col.FloatToDouble(v.B);\n                                    da[i+3] = Col.FloatToDouble(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+d1]), \n                                            Col.DoubleToFloat(da[i+d2]), \n                                            Col.DoubleToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.R);\n                                    da[i+d1] = Col.FloatToDouble(v.G);\n                                    da[i+d2] = Col.FloatToDouble(v.B);\n                                    da[i+d3] = Col.FloatToDouble(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C4f\n\n                {\n                    (typeof(double), typeof(C4f), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.DoubleToFloat(da[i+2]), \n                                            Col.DoubleToFloat(da[i+1]), \n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.B);\n                                    da[i+1] = Col.FloatToDouble(v.G);\n                                    da[i+2] = Col.FloatToDouble(v.R);\n                                    da[i+3] = Col.FloatToDouble(v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4f>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4f(\n                                            Col.DoubleToFloat(da[i+d2]), \n                                            Col.DoubleToFloat(da[i+d1]), \n                                            Col.DoubleToFloat(da[i]), \n                                            Col.DoubleToFloat(da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = Col.FloatToDouble(v.B);\n                                    da[i+d1] = Col.FloatToDouble(v.G);\n                                    da[i+d2] = Col.FloatToDouble(v.R);\n                                    da[i+d3] = Col.FloatToDouble(v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGB doubles as C4d\n\n                {\n                    (typeof(double), typeof(C4d), Intent.RGB),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGR doubles as C4d\n\n                {\n                    (typeof(double), typeof(C4d), Intent.BGR),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1;\n                            return new TensorAccessors<double, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (double)1.0),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region RGBA doubles as C4d\n\n                {\n                    (typeof(double), typeof(C4d), Intent.RGBA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            (da[i]), \n                                            (da[i+1]), \n                                            (da[i+2]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.B);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            (da[i]), \n                                            (da[i+d1]), \n                                            (da[i+d2]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.R);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.B);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                #region BGRA doubles as C4d\n\n                {\n                    (typeof(double), typeof(C4d), Intent.BGRA),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<double, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            (da[i+2]), \n                                            (da[i+1]), \n                                            (da[i]), \n                                            (da[i+3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+1] = (v.G);\n                                    da[i+2] = (v.R);\n                                    da[i+3] = (v.A);\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1, d3 = d1 + d2;\n                            return new TensorAccessors<double, C4d>()\n                            {\n                                Getter = (da, i) =>\n                                    new C4d(\n                                            (da[i+d2]), \n                                            (da[i+d1]), \n                                            (da[i]), \n                                            (da[i+d3])),\n                                Setter = (da, i, v) =>\n                                {\n                                    da[i] = (v.B);\n                                    da[i+d1] = (v.G);\n                                    da[i+d2] = (v.R);\n                                    da[i+d3] = (v.A);\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n            };\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/Accessors_template.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\n//# Action comma = () => Out(\", \");\n//# Action add = () => Out(\"+\");\n\nnamespace Aardvark.Base\n{\n    public static partial class TensorAccessors\n    {\n        #region Single channel accessors\n\n        //# foreach (var tt in Meta.ColorConvertibleTypes) { var ttype = tt.Name; var tcaps = tt.Caps;\n        //# foreach (var ct in Meta.ColorConvertibleTypes) { var ctype = ct.Name; var ccaps = ct.Caps;\n        //#     var tt_from_ct = ct == tt ? \"\" : \"Col.\" + ct.Caps + \"To\" + tt.Caps;\n        //#     var ct_from_tt = ct == tt ? \"\" : \"Col.\" + tt.Caps + \"To\" + ct.Caps;\n        private static ITensorAccessors Get__tcaps__As__ccaps__(long[] delta)\n        {\n            return new TensorAccessors<__ttype__, __ctype__>()\n            {\n                Getter = (da, i) => __ct_from_tt__(da[i]),\n                Setter = (da, i, v) => da[i] = __tt_from_ct__(v),\n            };\n        }\n\n        //# } // ct\n        //# } // tt\n        #endregion\n\n        private static readonly Dictionary<(Type, Type, Symbol),\n                                           Func<long[], ITensorAccessors>> s_creatorMap\n            = new Dictionary<(Type, Type, Symbol),\n                             Func<long[], ITensorAccessors>>()\n            {\n                //# foreach (var tt in Meta.ColorConvertibleTypes) { var ttype = tt.Name; var tcaps = tt.Caps;\n                //# foreach (var ct in Meta.ColorConvertibleTypes) { var ctype = ct.Name; var ccaps = ct.Caps;\n                //#     var tt_from_ct = ct == tt ? \"\" : \"Col.\" + ct.Caps + \"To\" + tt.Caps;\n                //#     var ct_from_tt = ct == tt ? \"\" : \"Col.\" + tt.Caps + \"To\" + ct.Caps;\n                #region Single channel __ttype__ as __ctype__\n\n                //# foreach (var intent in new [] { \"ColorChannel\", \"BW\", \"Gray\", \"Alpha\" }) {\n                { (typeof(__ttype__), typeof(__ctype__), Intent.__intent__), Get__tcaps__As__ccaps__ },\n                //# } // intent\n\n                #endregion\n\n                //# } // ct\n                //# } // tt\n                //# var intentArray = new[] { \"RGB\", \"BGR\", \"RGBA\", \"BGRA\" };\n                //# foreach (var tt in Meta.ColorConvertibleTypes) { var ttype = tt.Name;\n                //# foreach (var ct in Meta.ColorTypes) { var ctype = ct.Name;\n                //#     var cft = ct.FieldType;\n                //#     var tmax = \"(\" + ttype +\")\" + Meta.ColorConvertibleTypeMaxValue[tt];\n                //#     var cmax = \"(\" + cft.Name + \")\" + ct.MaxValue;\n                //#     string t_from_cf = \"\", cf_from_t = \"\";\n                //#     if (tt != cft) {\n                //#         t_from_cf = \"Col.\" + cft.Caps + \"To\" + tt.Caps;\n                //#         cf_from_t = \"Col.\" + tt.Caps + \"To\" + cft.Caps;\n                //#     }\n                //# foreach (var intent in intentArray) {\n                //#     var indices = (from f in ct.Fields select intent.IndexOf(f)).ToArray();\n                #region __intent__ __ttype__s as __ctype__\n\n                {\n                    (typeof(__ttype__), typeof(__ctype__), Intent.__intent__),\n                    delta =>\n                    {\n                        if (delta.Length < 3)\n                            throw new ArgumentException(\"to few dimensions in tensor\");\n                        long d1 = delta[delta.Length - 1];\n                        if (d1 == 1)\n                            return new TensorAccessors<__ttype__, __ctype__>()\n                            {\n                                Getter = (da, i) =>\n                                    new __ctype__(/*# indices.ForEach(i => { if (i >= 0) { */\n                                            __cf_from_t__(da[i/*# if (i > 0) { */+__i__/*# } */])/*# } else { */\n                                            /*# Out(cmax); } }, comma); */),\n                                Setter = (da, i, v) =>\n                                {\n                                    //# intent.ForEach((f, i) => { if (Array.IndexOf(ct.Fields, f.ToString()) >= 0) {\n                                    da[i/*# if (i > 0) { */+__i__/*# } */] = __t_from_cf__(v.__f__);\n                                    //# } else {\n                                    da[i/*# if (i > 0) { */+__i__/*# } */] = __tmax__;\n                                    //# }});\n                                }\n                            };\n                        else\n                        {\n                            long d2 = d1 + d1/*# if (intent.Length == 4) { */, d3 = d1 + d2/*# }*/;\n                            return new TensorAccessors<__ttype__, __ctype__>()\n                            {\n                                Getter = (da, i) =>\n                                    new __ctype__(/*# indices.ForEach(i => { if (i >= 0) { */\n                                            __cf_from_t__(da[i/*# if (i > 0) { */+d__i__/*# } */])/*# } else { */\n                                            /*# Out(cmax); } }, comma); */),\n                                Setter = (da, i, v) =>\n                                {\n                                    //# intent.ForEach((f, i) => { if (Array.IndexOf(ct.Fields, f.ToString()) >= 0) {\n                                    da[i/*# if (i > 0) { */+d__i__/*# } */] = __t_from_cf__(v.__f__);\n                                    //# } else {\n                                    da[i/*# if (i > 0) { */+d__i__/*# } */] = __tmax__;\n                                    //# }});\n                                }\n                            };\n                        }\n                    }\n                },\n\n                #endregion\n\n                //# } // intent\n                //# } // ct\n                //# } // tt\n            };\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/ArrayExtensions.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class TensorArrayExtensions\n    {\n        #region Bit Reversed Index\n\n        public static void BitReverseIndex<T>(\n                this T[] v, long start, long size)\n        {\n            if (size == 0 || !size.IsPowerOfTwo())\n                throw new ArgumentException(\n                        \"specified size not a power of 2\");\n            long hiBit = size >> 1, hiBit1 = hiBit >> 1, hiBit2 = hiBit1 >> 1;\n            long index = 0, rIndex = 0;\n\n            while (index < size)\n            {\n                if (index < rIndex)\n                {\n                    T help = v[start + rIndex];\n                    v[start + rIndex] = v[start + index];\n                    v[start + index] = help;\n                }\n                index++;\n                rIndex ^= hiBit;\n                if ((index & 1) == 0)\n                {\n                    rIndex ^= hiBit1;\n                    if ((index & 2) == 0)\n                    {\n                        long bit = 2, rBit = hiBit2;\n                        do { rIndex ^= rBit; bit <<= 1; rBit >>= 1; } while ((index & bit) == 0);                            \n                    }\n                }\n            }\n\n        }\n\n        public static T[] BitReversedIndexCopy<T>(\n                this T[] v, long start, long size)\n        {\n            if (size == 0 || !size.IsPowerOfTwo())\n                throw new ArgumentException(\n                        \"specified size not a power of 2\");\n\n            var r = new T[size];\n            long hiBit = size >> 1, hiBit1 = hiBit >> 1, hiBit2 = hiBit1 >> 1;\n            long index = 0, rIndex = 0;\n\n            while (index < size)\n            {\n                r[rIndex] = v[start + index];\n                index++;\n                rIndex ^= hiBit;\n                if ((index & 1) == 0)\n                {\n                    rIndex ^= hiBit1;\n                    if ((index & 2) == 0)\n                    {\n                        long bit = 2, rBit = hiBit2;\n                        do { rIndex ^= rBit; bit <<= 1; rBit >>= 1; } while ((index & bit) == 0);\n                    }\n                }\n            }\n            return r;\n        }\n\n        public static void BitReverseIndex<T>(\n                this T[] v, long start, long size, long stride)\n        {\n            if (size == 0 || !size.IsPowerOfTwo())\n                throw new ArgumentException(\n                        \"specified size not a power of 2\");\n            long hiBit = size >> 1, hiBit1 = hiBit >> 1, hiBit2 = hiBit1 >> 1;\n            long index = 0, rIndex = 0, position = start;\n\n            while (index < size)\n            {\n                if (index < rIndex) Fun.Swap(ref v[position], ref v[start + rIndex * stride]);\n                position += stride;\n                index++;\n                rIndex ^= hiBit;\n                if ((index & 1) == 0)\n                {\n                    rIndex ^= hiBit1;\n                    if ((index & 2) == 0)\n                    {\n                        long bit = 2, rBit = hiBit2;\n                        do { rIndex ^= rBit; bit <<= 1; rBit >>= 1; } while ((index & bit) == 0);\n                    }\n                }\n            }\n        }\n\n        #endregion\n\n        #region Fast Hartley Transform\n\n        public static void FastHartleyTransform(\n                this double[] v, long start, long size)\n        {\n            v.BitReverseIndex(start, size);\n\n            /* ---------------------------------------------------------------\n\t            The transforming part of the function.  It assumes that all\n                indices are already bit-reversed.  For successive evaluation\n                of the trigonometric functions the following recurrence is\n                used:\n                \n\t\t            a = 2 sin(square(d/2))\n\t\t            b  = sin d\n            \t\n\t\t            cos(t + d) = cos t - [ a * cos t + b sin t ]\n\t\t            sin(t + d) = sin t - [ a * sin t - b cos t ]\n\n\t            The algorithm is based on the following recursion:\n\n\t\t            H[f] = Heven[f]\n\t\t\t            + cos(2 PI f / n) Hodd[f]\n\t\t\t            + sin(2 PI f / n) Hodd[n-f]\tf in [0, n-1]\n\n\t\t            Heven[n/2 + g] = Heven[g]\n\t\t            Hodd [n/2 + g] = Hodd [g]\t\tg in [0, n/2-1]\n            --------------------------------------------------------------- */\n            long end = start + size;\n            for (long len = 1, oldLen = 0, newLen = 0;\n                 len < size;\n                 oldLen = len, len = newLen, newLen = 2 * len)\n            {\n                long i, j;\n                double hi, hj;\n\n                for (i = start; i < end; i += newLen)  // for all blocks\n                {\n                    j = i + len;\t\t\t\t        // special case:\n                    hi = v[i]; hj = v[j];\n                    v[i] = hi + hj;\t\t\t\t        // f = 0\n                    v[j] = hi - hj;\t\t\t\t        // f = PI\n                }\n\n                if (len < 2) continue;\n\n                for (i = start + oldLen; i < end; i += newLen)\n                {\n                    j = i + len;\t\t\t\t        // special case:\n                    hi = v[i]; hj = v[j];\n                    v[i] = hi + hj;\t\t\t\t        // f = PI/2\n                    v[j] = hi - hj;\t\t\t\t        // f = 3 * PI/2\n                }\n\n                if (len < 4) continue;\n\n                double d = Constant.PiTimesTwo / newLen;\n                double a = (d * 0.5).Sin().Square() * 2.0;  // init trig.\n                double b = d.Sin();\t\t\t\t        // recurrence\n                double ct = 1.0;\n                double st = 0.0;\n\n                /* -----------------------------------------------------------\n                    To increase the locality of references, the following two\n                    loops could be exchanged, but then the trigonometric\n                    functions need to be tabulated.\n                ----------------------------------------------------------- */\n                for (long f = 1; f < oldLen; f++)       // for all freqs in\n                {\t\t\t\t\t\t                //   the first quad\n                    double one = a * ct + b * st;\t    // trig. recurrence\n                    double two = a * st - b * ct;\n                    ct -= one;\t\t\t\t            //   cos (t + d)\n                    st -= two;\t\t\t\t            //   sin (t + d)\n\n                    for (i = start + f, j = start + len - f; // for all blocks\n                         i < end;\n                         i += newLen, j += newLen)\n                    {\n                        long k = i + len;\n                        long l = j + len;\n\n                        one = ct * v[k] + st * v[l];\n                        two = ct * v[l] - st * v[k];\n                        hi = v[i]; hj = v[j];\n                        v[i] = hi + one; v[k] = hi - one;   // all four quads\n                        v[j] = hj - two; v[l] = hj + two;\t// (i,j,k,l)\n                    }\n                }\n            }\n        }\n\n        public static double[] UntestedFastHartleyTransformedCopy(\n                this double[] v, long start, long size)\n        {\n            if (size < 2) return v.Copy(start, size);\n            var h = v.BitReversedIndexCopy(start, size);\n            h.FastHartleyTransformRaw(start, size);\n            return h;\n        }\n\n        private static void FastHartleyTransformRaw(\n                this double[] v, long start, long size)\n        {\n            if (size < 2) return;\n            /* ---------------------------------------------------------------\n\t            The transforming part of the function.  It assumes that all\n                indices are already bit-reversed.  For successive evaluation\n                of the trigonometric functions the following recurrence is\n                used:\n                \n\t\t            a = 2 sin(square(d/2))\n\t\t            b  = sin d\n            \t\n\t\t            cos(t + d) = cos t - [ a * cos t + b sin t ]\n\t\t            sin(t + d) = sin t - [ a * sin t - b cos t ]\n\n\t            The algorithm is based on the following recursion:\n\n\t\t            H[f] = Heven[f]\n\t\t\t            + cos(2 PI f / n) Hodd[f]\n\t\t\t            + sin(2 PI f / n) Hodd[n-f]\tf in [0, n-1]\n\n\t\t            Heven[n/2 + g] = Heven[g]\n\t\t            Hodd [n/2 + g] = Hodd [g]\t\tg in [0, n/2-1]\n            --------------------------------------------------------------- */\n            long end = start + size;\n\n            for (long i = start; i < end; i += 2)\n            {\n                double h0 = v[i], h1 = v[i + 1];\n                v[i] = h0 + h1; v[i + 1] = h0 - h1;     // f = 0, PI\n            }\n            if (size < 4) return;\n\n            for (long i = start; i < end; i += 4)\n            {\n                double h0 = v[i], h2 = v[i + 2];\n                v[i] = h0 + h2; v[i + 2] = h0 - h2;     // f = 0, PI\n                double h1 = v[i + 1], h3 = v[i + 3];\n                v[i + 1] = h1 + h3; v[i + 3] = h1 - h3; // f = PI/2, 3 * PI/2\n            }\n            if (size < 8) return;\n\n            for (long i = start; i < end; i += 8)\n            {\n                double h0 = v[i], h4 = v[i + 4];\n                v[i] = h0 + h4; v[i + 4] = h0 - h4;     // f = 0, PI\n                double one = Constant.Sqrt2Half * (v[i + 5] + v[i + 7]);\n                double two = Constant.Sqrt2Half * (v[i + 7] - v[i + 5]);\n                double h1 = v[i + 1], h3 = v[i + 3];\n                v[i + 1] = h1 + one; v[i + 5] = h1 - one;\n                v[i + 3] = h3 - two; v[i + 7] = h3 + two;\n                double h2 = v[i + 2], h6 = v[i + 6];\n                v[i + 2] = h2 + h6; v[i + 6] = h2 - h6; // f = PI/2, 3 * PI/2\n            }\n            if (size < 16) return;\n\n            var sTable = new double[size / 4];\n            var cTable = new double[size / 4];\n\n            for (long len = 8, lenDiv2 = 4, lenMul2 = 16;\n                 len < size;\n                 lenDiv2 = len, len = lenMul2, lenMul2 = 2 * len)\n            {\n                double d = Constant.PiTimesTwo / lenMul2;\n                double a = Fun.Sin(d * 0.5).Square() * 2.0;  // init trig. recurrence\n                double b = Fun.Sin(d);\n                double ct = 1.0, st = 0.0;\n\n                for (long f = 1; f < lenDiv2; f++)  // all freqs in the first quadrant\n                {\n                    double dct = a * ct + b * st, dst = a * st - b * ct;    // trig. rec\n                    ct -= dct; st -= dst;           // cos (t + d), sin (t + d)\n                    cTable[f] = ct; sTable[f] = st;\n                }\n\n                for (long i0 = start; i0 < end; i0 += lenMul2)\n                {\n                    long i4 = i0 + len;\n                    double h0 = v[i0], h4 = v[i4];\n                    v[i0] = h0 + h4; v[i4] = h0 - h4;   // f = 0, PI\n\n                    for (long f = 1; f < lenDiv2; f++)  // all freqs in the first quadrant\n                    {\n                        long i1 = i0 + f, i3 = i0 + len - f;\n                        long i5 = i1 + len, i7 = i3 + len;\n                        double one = cTable[f] * v[i5] + sTable[f] * v[i7];\n                        double two = cTable[f] * v[i7] - sTable[f] * v[i5];\n                        double h1 = v[i1], h3 = v[i3];\n                        v[i1] = h1 + one; v[i5] = h1 - one; // all four quadrants\n                        v[i3] = h3 - two; v[i7] = h3 + two;\t// \n                    }\n\n                    long i2 = i0 + lenDiv2, i6 = i4 + lenDiv2;\n                    double h2 = v[i2], h6 = v[i6];\n                    v[i2] = h2 + h6; v[i6] = h2 - h6;       // f = PI/2, 3 * PI/2\n                }\n            }\n        }\n\n        public static void FastHartleyTransform(\n\t            this double[] v, long start, long size, long stride)\n        {\n            v.BitReverseIndex(start, size, stride);\n\n            long strideSize = stride * size;\n            long end = start + strideSize;\n\n            for (long len = stride, oldLen = 0, newLen = 0;\n                 len != strideSize;\n                 oldLen = len, len = newLen, newLen = 2 * len)\n            {\n\t            long i, j;\n\t            double hi, hj;\n\n                for (i = start; i != end; i += newLen)\t\t// for all blocks\n\t            {\n\t                j = i + len;\t\t\t\t            // special case:\n\t                hi = v[i]; hj = v[j];\n\t                v[i] = hi + hj;\t\t\t\t            // f = 0\n\t                v[j] = hi - hj;\t\t\t\t            // f = PI\n\t            }\n\t            if (len < 2 * stride) continue;\n\n                for (i = start + oldLen; i != end + oldLen; i += newLen)\n\t            {\n\t                j = i + len;\t\t\t\t            // special case:\n\t                hi = v[i]; hj = v[j];\n\t                v[i] = hi + hj;\t\t\t\t            // f = PI/2\n\t                v[j] = hi - hj;\t\t\t\t            // f = 3 * PI/2\n\t            }\n\n            \tif (len < 4 * stride) continue;\n\n                double d = Constant.PiTimesTwo / newLen;\n                double a = (d * 0.5).Sin().Square() * 2.0;  // init trig.\n\t            double b = d.Sin();\t\t\t\t            //  recurrence\n   \t            double ct = 1.0, st = 0.0;\n\n                for (long f = stride; f != oldLen; f += stride) // all freqs in the first quad\n\t            {\n\t\t            double dct = a * ct + b * st, dst = a * st - b * ct;    // trig. recurrence\n\t\t            ct -= dct; st -= dst;\t\t\t        //  cos (t + d), sin (t + d)\n\n                    for (i = start + f, j = start + len - f; // for all blocks\n                         i != end + f;\n                         i += newLen, j += newLen)\n                    {\n                        long k = i + len;\n                        long l = j + len;\n                        double one = ct * v[k] + st * v[l];\n                        double two = ct * v[l] - st * v[k];\n                        hi = v[i]; hj = v[j];\n                        v[i] = hi + one; v[k] = hi - one;\t// all four quads\n                        v[j] = hj - two; v[l] = hj + two;\t// (i,j,k,l)\n                    }\n\t            }\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/FilterKernel.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class FilterKernelFun\n    {\n        #region Gaussian\n        /// <summary>\n        /// Return a function that computes the gauss function with mu = 0\n        /// and the specified sigma.\n        /// </summary>\n        public static Func<float, float> Gaussian(float sigma)\n        {\n            double s2 = sigma * sigma;\n            double a = 1.0 / (Constant.SqrtPiTimesTwo * sigma);\n            double b = -1.0 / (2.0 * s2);\n            return (float x) => (float)(a * Fun.Exp(b * (x * x)));\n        }\n\n        /// <summary>\n        /// Return a function that computes the derivative of the gauss\n        /// function with mu = 0 and specified sigma.\n        /// </summary>\n        public static Func<float, float> GaussianDx(float sigma)\n        {\n            double s2 = sigma * sigma;\n            double a = -1.0 / (Constant.SqrtPiTimesTwo * s2 * sigma);\n            double b = -1.0 / (2.0 * s2);\n            return (float x) => (float)(a * x * Fun.Exp(b * (x * x)));\n        }\n\n        /// <summary>\n        /// Return a function that computes the two-dimensional gauss\n        /// function with mu = (0, 0) and sigma = DiagonalMatrix(sigma).\n        /// </summary>\n        public static Func<float, float, float> Gaussian2(float sigma)\n        {\n            double s2 = sigma * sigma;\n            double a = 1.0 / (Constant.PiTimesTwo * s2);\n            double b = -1.0 / (2.0 * s2);\n            return (float x, float y) =>\n                        (float)(a * Fun.Exp(b * (x * x + y * y)));\n        }\n\n        /// <summary>\n        /// Return a function that computes the partial derivative in X of\n        /// the two-dimensional gauss function with mu = (0, 0) and\n        /// sigma = DiagonalMatrix(sigma).\n        /// </summary>\n        public static Func<float, float, float> Gaussian2Dx(float sigma)\n        {\n            double s2 = sigma * sigma;\n            double a = -1.0 / (Constant.PiTimesTwo * s2 * s2);\n            double b = -1.0 / (2.0 * s2);\n            return (float x, float y) =>\n                        (float)(a * x * Fun.Exp(b * (x * x + y * y)));\n        }\n\n        /// <summary>\n        /// Return a function that computes the partial derivative in Y of\n        /// the two-dimensional gauss function with mu = (0, 0) and\n        /// sigma = DiagonalMatrix(sigma).\n        /// </summary>\n        public static Func<float, float, float> Gaussian2Dy(float sigma)\n        {\n            double s2 = sigma * sigma;\n            double a = -1.0 / (Constant.PiTimesTwo * s2 * s2);\n            double b = -1.0 / (2.0 * s2);\n            return (float x, float y) =>\n                        (float)(a * y * Fun.Exp(b * (x * x + y * y)));\n        }\n\n        /// <summary>\n        /// Return a function that computes the difference of two\n        /// one-dimensional gauss functions (Gauss(sigma1)-Gauss(sigma2)).\n        /// </summary>\n        public static Func<float, float> DoG(float sigma1, float sigma2)\n        {\n            var g1 = Gaussian(sigma1);\n            var g2 = Gaussian(sigma2);\n            return (float x) => g1(x) - g2(x);\n        }\n\n        /// <summary>\n        /// Return a function that computes the difference of two\n        /// two-dimensional gauss functions (Gauss(sigma1)-Gauss(sigma2)).\n        /// </summary>\n        public static Func<float, float, float> DoG2(float sigma1, float sigma2)\n        {\n            var g1 = Gaussian2(sigma1);\n            var g2 = Gaussian2(sigma2);\n            return (float x, float y) => g1(x, y) - g2(x, y);\n        }\n\n        /// <summary>\n        /// Return a function that computes the one-dimensional\n        /// Laplacian of Gaussian function for a given sigma.\n        /// Also known as Marr-Hildreth-Operator or Sombrero-Filter.\n        /// </summary>\n        public static Func<float, float> LoG(float sigma)\n        {\n            float s2 = sigma * sigma;\n            float s4 = s2 * s2;\n            return x =>\n            {\n                double a = (x * x) / (2 * s2);\n                return (float)((-1 / (System.Math.PI * s4)) * System.Math.Exp(-a) * (1 - a));\n            };\n        }\n\n        /// <summary>\n        /// Return a function that computes the two-dimensional\n        /// Laplacian of Gaussian function for a given sigma.\n        /// Also known as Marr-Hildreth-Operator or Sombrero-Filter.\n        /// </summary>\n        public static Func<float, float, float> LoG2(float sigma)\n        {\n            float s2 = sigma * sigma;\n            float s4 = s2 * s2;\n            return (x, y) =>\n            {\n                double a = (x * x + y * y) / (2 * s2);\n                return (float)((-1 / (System.Math.PI * s4)) * System.Math.Exp(-a) * (1 - a));\n            };\n        }\n\n        #endregion Gaussian\n    }\n\n    /// <summary>\n    /// Convolution filter kernels.\n    /// </summary>\n    public static class FilterKernel\n    {\n\n        #region Normalization\n\n        /// <summary>\n        /// Normalizes the supplied matrix so that the sum of all entries sums to 1. MODIFIES SOURCE!\n        /// </summary>\n        /// <returns>this</returns>\n        public static Matrix<float> NormalizeToSum1(this Matrix<float> matrixWillBeModified)\n        {\n            var sum = matrixWillBeModified.Norm(x => x, 0.0, (s, x) => s + (double)x);\n            if (sum != 0.0)\n            {\n                double scale = 1.0 / sum;\n                matrixWillBeModified.Apply(x => (float)(scale * x));\n            }\n            return matrixWillBeModified;\n        }\n\n        /// <summary>\n        /// Normalizes the supplied matrix so that the sum of all entries sums to 1. MODIFIES SOURCE!\n        /// </summary>\n        /// <returns>this</returns>\n        public static Matrix<double> NormalizeToSum1(this Matrix<double> matrixWillBeModified)\n        {\n\n            var sum = matrixWillBeModified.Norm(x => x, KahanSum.Zero, (s, x) => s + x);\n            if (sum.Value != 0.0)\n            {\n                double scale = 1.0 / sum.Value;\n                matrixWillBeModified.Apply(x => scale * x);\n            }\n            return matrixWillBeModified;\n        }\n\n        /// <summary>\n        /// Normalizes the supplied vector so that the sum of all entries sums to 1. MODIFIES SOURCE!\n        /// </summary>\n        /// <returns>this</returns>\n        public static Vector<float> NormalizeToSum1(this Vector<float> vectorWillBeModified)\n        {\n            var sum = vectorWillBeModified.Norm(x => x, 0.0, (s, x) => s + (double)x);\n            if (sum != 0.0)\n            {\n                double scale = 1.0 / sum;\n                vectorWillBeModified.Apply(x => (float)(scale * x));\n            }\n            return vectorWillBeModified;\n        }\n\n        /// <summary>\n        /// Normalizes the supplied vector so that the sum of all entries sums to 1. MODIFIES SOURCE!\n        /// </summary>\n        /// <returns>this</returns>\n        public static Vector<double> NormalizeToSum1(this Vector<double> vectorWillBeModified)\n        {\n\n            var sum = vectorWillBeModified.Norm(x => x, KahanSum.Zero, (s, x) => s + x);\n            if (sum.Value != 0.0)\n            {\n                double scale = 1.0 / sum.Value;\n                vectorWillBeModified.Apply(x => scale * x);\n            }\n            return vectorWillBeModified;\n        }\n\n        #endregion\n\n        /// <summary>\n        /// Create a 1D filter kernel Vector populated by filterKernelFun,\n        /// with size S = 2 * radius + 1 and anchor in the center at index 0.\n        /// Functions to use as filterKernelFun are available in FilterKernelFun.\n        /// </summary>\n        /// <param name=\"radius\"></param>\n        /// <param name=\"filterKernelFun\">Function is evaluated at integer coordinates from -radius to +radius.</param>\n        public static Vector<float> Create1DKernel(\n                long radius, Func<float, float> filterKernelFun)\n        {\n            var kernel = new Vector<float>(2 * radius + 1) { F = -radius };\n            kernel.SetByCoord(v => filterKernelFun((float)v));\n\n            return kernel;\n        }\n\n        /// <summary>\n        /// Create a 2D filter kernel matrix populated in accordance with\n        /// filterKernelFun, with size (SX, SY) = (2 * radius + 1,\n        /// 2 * radius + 1) and anchor in the center at index (0, 0).\n        /// Functions to use as filterKernelFun are available in FilterKernelFun.\n        /// </summary>\n        /// <param name=\"radius\"></param>\n        /// <param name=\"filterKernelFun\">Function is evaluated at integer coordinates from (-radius,-radius) to (+radius,+radius).</param>\n        public static Matrix<float> Create2DKernel(\n                long radius, Func<float, float, float> filterKernelFun)\n        {\n            var kernel = new Matrix<float>(2 * radius + 1, 2 * radius + 1) { FX = -radius, FY = -radius };\n            kernel.SetByCoord((long x, long y) => filterKernelFun((float)x, (float)y));\n\n            return kernel;\n        }\n\n        /// <summary>\n        /// Create a 2D kernel from two 1D kernels via outer product.\n        /// \n        /// Swapping the two 1D kernel parameters gives the transposed 2D kernel.\n        /// </summary>\n        public static Matrix<float> Create2DKernel(\n                Vector<float> kernelX, Vector<float> kernelY)\n        {\n            return Matrix<float>.CreateOuterProduct(kernelX, kernelY, (x, y) => x * y);\n        }\n\n        /// <summary>\n        /// Create a 2D kernel Matrix corresponding to the provided 1D kernel\n        /// vector, with 1 row and kernel.Size columns.\n        /// </summary>\n        public static Matrix<float> To2DKernelX(this Vector<float> kernel)\n        {\n            return new Matrix<float>(kernel.Data, kernel.Origin,\n                        new V2l(kernel.S, 1L), new V2l(kernel.D, kernel.DSX), new V2l(kernel.F, 0));\n        }\n\n        /// <summary>\n        /// Create a 2D kernel Matrix corresponding to the provided 1D kernel\n        /// vector, with kernel.Size rows and 1 column.\n        /// </summary>\n        public static Matrix<float> To2DKernelY(this Vector<float> kernel)\n        {\n            return new Matrix<float>(kernel.Data, kernel.Origin,\n                        new V2l(1L, kernel.S), new V2l(kernel.DSX, kernel.D), new V2l(0, kernel.F));\n        }\n\n\n        /// <summary>\n        /// Creates a Gaussian FilterKernel with given sigma.\n        /// Radius is set to 3 * sigma.\n        /// </summary>\n        public static Matrix<float> Gaussian2(float sigma)\n        {\n            return Gaussian2(sigma, (int)Fun.Ceiling(3 * sigma));\n        }\n\n        /// <summary>\n        /// Creates a Gaussian FilterKernel with given sigma and radius.\n        /// </summary>\n        public static Matrix<float> Gaussian2(float sigma, int radius)\n        {\n            return Create2DKernel(radius, FilterKernelFun.Gaussian2(sigma)).NormalizeToSum1();\n        }\n\n        /// <summary>\n        /// Creates a Gaussian FilterKernel with given sigma.\n        /// Radius is set to 3 * sigma.\n        /// </summary>\n        public static Vector<float> Gaussian1(float sigma)\n        {\n            return Gaussian1(sigma, (int)Fun.Ceiling(3 * sigma));\n        }\n\n        /// <summary>\n        /// Creates a Gaussian FilterKernel with given sigma and radius.\n        /// </summary>\n        public static Vector<float> Gaussian1(float sigma, int radius)\n        {\n            return Create1DKernel(radius, FilterKernelFun.Gaussian(sigma)).NormalizeToSum1();\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/ImageBorder.cs",
    "content": "using System;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Specifies an image boder, all entries should be positive values.\n    /// </summary>\n    public struct Border2i\n    {\n        public V2i Min;\n        public V2i Max;\n\n        #region Constructors\n\n        public Border2i(V2i min, V2i max)\n        {\n            Min = min; Max = max;\n        }\n\n        public Border2i(int minx, int miny, int maxx, int maxy)\n            : this(new V2i(minx, miny), new V2i(maxx, maxy))\n        { }\n\n        public Border2i(int val)\n            : this(new V2i(val, val), new V2i(val, val))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        public readonly Border2i Flipped { get { return new Border2i(Max, Min); } }\n\n        #endregion\n\n        #region Operations\n\n        public readonly Border2l ToBorder2l()\n        {\n            return new Border2l(Min.ToV2l(), Max.ToV2l());\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// Specifies an image boder, all entries should be positive values.\n    /// </summary>\n    public struct Border2l\n    {\n        public V2l Min;\n        public V2l Max;\n\n        #region Constructors\n\n        public Border2l(V2l min, V2l max)\n        {\n            Min = min; Max = max;\n        }\n\n        public Border2l(long minx, long miny, long maxx, long maxy)\n            : this(new V2l(minx, miny), new V2l(maxx, maxy))\n        { }\n\n        public Border2l(long val)\n            : this(new V2l(val, val), new V2l(val, val))\n        { }\n\n        #endregion\n\n        #region Properties\n\n        public readonly Border2l Flipped { get { return new Border2l(Max, Min); } }\n\n        #endregion\n\n        #region Operations\n\n        public readonly Border2i ToBorder2i()\n        {\n            return new Border2i(Min.ToV2i(), Max.ToV2i());\n        }\n\n        #endregion\n    }\n\n    public static class BorderMatrixAndVolumeExtensions\n    {\n        #region Matrix Parts\n\n        /// <summary>\n        /// Get the minimal x edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMinX<T>(this Matrix<T> m, long b)\n        {\n            return m.SubMatrixWindow(m.FX, m.FY, b, m.SY);\n        }\n\n        /// <summary>\n        /// Get the minimal x edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMinX<Td, Tv>(this Matrix<Td, Tv> m, long b)\n        {\n            return m.SubMatrixWindow(m.FX, m.FY, b, m.SY);\n        }\n\n        /// <summary>\n        /// Get the maximal x edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMaxX<T>(this Matrix<T> m, long b)\n        {\n            return m.SubMatrixWindow(m.EX - b, m.FY, b, m.SY);\n        }\n\n        /// <summary>\n        /// Get the maximal x edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMaxX<Td, Tv>(this Matrix<Td, Tv> m, long b)\n        {\n            return m.SubMatrixWindow(m.EX - b, m.FY, b, m.SY);\n        }\n\n        /// <summary>\n        /// Get the minimal y edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        /// <summary>\n        /// Get the minimal y edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMinY<T>(this Matrix<T> m, long b)\n        {\n            return m.SubMatrixWindow(m.FX, m.FY, m.SX, b);\n        }\n\n        /// <summary>\n        /// Get the minimal y edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMinY<Td, Tv>(this Matrix<Td, Tv> m, long b)\n        {\n            return m.SubMatrixWindow(m.FX, m.FY, m.SX, b);\n        }\n\n        /// <summary>\n        /// Get the maximal y edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMaxY<T>(this Matrix<T> m, long b)\n        {\n            return m.SubMatrixWindow(m.FX, m.EY - b, m.SX, b);\n        }\n\n        /// <summary>\n        /// Get the maximal y edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMaxY<Td, Tv>(this Matrix<Td, Tv> m, long b)\n        {\n            return m.SubMatrixWindow(m.FX, m.EY - b, m.SX, b);\n        }\n\n        /// <summary>\n        /// Get the center part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubCenter<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX + b.Min.X, m.FY + b.Min.Y,\n                                     m.SX - b.Max.X - b.Min.X, m.SY - b.Max.Y - b.Min.Y);\n        }\n\n        /// <summary>\n        /// Get the center part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubCenter<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX + b.Min.X, m.FY + b.Min.Y,\n                                     m.SX - b.Max.X - b.Min.X, m.SY - b.Max.Y - b.Min.Y);\n        }\n\n        /// <summary>\n        /// Get the minimal x/minmal y corner part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMinXMinY<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX, m.FY,\n                                     b.Min.X, b.Min.Y);\n        }\n\n        /// <summary>\n        /// Get the minimal x/minmal y corner part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMinXMinY<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX, m.FY,\n                                     b.Min.X, b.Min.Y);\n        }\n\n        /// <summary>\n        /// Get the minimal x/maximal y corner part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMinXMaxY<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX, m.EY - b.Max.Y,\n                                     b.Min.X, b.Max.Y);\n        }\n\n        /// <summary>\n        /// Get the minimal x/maximal y corner part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMinXMaxY<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX, m.EY - b.Max.Y,\n                                     b.Min.X, b.Max.Y);\n        }\n\n        /// <summary>\n        /// Get the maximal x/minimal y corner part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMaxXMinY<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.EX - b.Max.X, m.FY,\n                                     b.Max.X, b.Min.Y);\n        }\n\n        /// <summary>\n        /// Get the maximal x/minimal y corner part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMaxXMinY<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.EX - b.Max.X, m.FY,\n                                     b.Max.X, b.Min.Y);\n        }\n\n        /// <summary>\n        /// Get the maximal x/maximal y corner part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMaxXMaxY<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.EX - b.Max.X, m.EY - b.Max.Y,\n                                     b.Max.X, b.Max.Y);\n        }\n\n        /// <summary>\n        /// Get the maximal x/maximal y corner part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMaxXMaxY<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.EX - b.Max.X, m.EY - b.Max.Y,\n                                     b.Max.X, b.Max.Y);\n        }\n\n        /// <summary>\n        /// Get the minimal x edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMinX<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX, m.FY + b.Min.Y,\n                                     b.Min.X, m.SY - b.Min.Y - b.Max.Y);\n        }\n\n        /// <summary>\n        /// Get the minimal x edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMinX<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX, m.FY + b.Min.Y,\n                                     b.Min.X, m.SY - b.Min.Y - b.Max.Y);\n        }\n\n        /// <summary>\n        /// Get the maximal x edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMaxX<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.EX - b.Max.X, m.FY + b.Min.Y,\n                                     b.Max.X, m.SY - b.Min.Y - b.Max.Y);\n        }\n\n        /// <summary>\n        /// Get the maximal x edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMaxX<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.EX - b.Max.X, m.FY + b.Min.Y,\n                                     b.Max.X, m.SY - b.Min.Y - b.Max.Y);\n        }\n\n        public static Matrix<T> SubMinY<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX + b.Min.X, m.FY,\n                                     m.SX - b.Min.X - b.Max.X, b.Min.Y);\n        }\n\n        /// <summary>\n        /// Get the minimal y edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMinY<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX + b.Min.X, m.FY,\n                                     m.SX - b.Min.X - b.Max.X, b.Min.Y);\n        }\n\n        /// <summary>\n        /// Get the maximal y edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> SubMaxY<T>(this Matrix<T> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX + b.Min.X, m.EY - b.Max.Y,\n                                     m.SX - b.Min.X - b.Max.X, b.Max.Y);\n        }\n\n        /// <summary>\n        /// Get the maximal y edge part of a matrix with the specified border.\n        /// Note that the part retains the pixel coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<Td, Tv> SubMaxY<Td, Tv>(this Matrix<Td, Tv> m, Border2l b)\n        {\n            return m.SubMatrixWindow(m.FX + b.Min.X, m.EY - b.Max.Y,\n                                     m.SX - b.Min.X - b.Max.X, b.Max.Y);\n        }\n\n        #endregion\n\n        #region Volume Parts\n\n        /// <summary>\n        /// Get the minimal x edge part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMinX<T>(this Volume<T> v, long b)\n        {\n            return v.SubVolumeWindow(v.FX, v.FY, v.FZ, b, v.SY, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the maximal x edge part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMaxX<T>(this Volume<T> v, long b)\n        {\n            return v.SubVolumeWindow(v.EX - b, v.FY, v.FZ, b, v.SY, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the minimal y edge part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMinY<T>(this Volume<T> v, long b)\n        {\n            return v.SubVolumeWindow(v.FX, v.FY, v.FZ, v.SX, b, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the maximal y edge part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMaxY<T>(this Volume<T> v, long b)\n        {\n            return v.SubVolumeWindow(v.FX, v.EY - b, v.FZ, v.SX, b, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the center part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubCenter<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.FX + b.Min.X, v.FY + b.Min.Y, v.FZ,\n                                     v.SX - b.Max.X - b.Min.X, v.SY - b.Max.Y - b.Min.Y, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the minimal x/minmal y corner part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMinXMinY<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.FX, v.FY, v.FZ,\n                                     b.Min.X, b.Min.Y, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the minimal x/maximal y corner part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMinXMaxY<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.FX, v.EY - b.Max.Y, v.FZ,\n                                     b.Min.X, b.Max.Y, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the maximal x/minimal y corner part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMaxXMinY<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.EX - b.Max.X, v.FY, v.FZ,\n                                     b.Max.X, b.Min.Y, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the maximal x/maximal y corner part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMaxXMaxY<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.EX - b.Max.X, v.EY - b.Max.Y, v.FZ,\n                                     b.Max.X, b.Max.Y, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the minimal x edge part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMinX<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.FX, v.FY + b.Min.Y, v.FZ,\n                                     b.Min.X, v.SY - b.Min.Y - b.Max.Y, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the maximal x edge part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMaxX<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.EX - b.Max.X, v.FY + b.Min.Y, v.FZ,\n                                     b.Max.X, v.SY - b.Min.Y - b.Max.Y, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the minimal y edge part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMinY<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.FX + b.Min.X, v.FY, v.FZ,\n                                     v.SX - b.Min.X - b.Max.X, b.Min.Y, v.SZ);\n        }\n\n        /// <summary>\n        /// Get the maximal y edge part of an image volume with the specified border.\n        /// Note that the part retains the pixel coordinates of the original volume.\n        /// </summary>\n        public static Volume<T> SubMaxY<T>(this Volume<T> v, Border2l b)\n        {\n            return v.SubVolumeWindow(v.FX + b.Min.X, v.EY - b.Max.Y, v.FZ,\n                                     v.SX - b.Min.X - b.Max.X, b.Max.Y, v.SZ);\n        }\n\n        #endregion\n\n        #region Generic Matrix Processing\n\n        /// <summary>\n        /// Process an image volume with specific actions for the center and border\n        /// parts.\n        /// </summary>\n        public static Matrix<T1> ProcessCenterBordersAndCorners<T, T1>(\n                this Matrix<T> source, Border2l border,\n                Action<Matrix<T>, Matrix<T1>> actCenter,\n                Action<Matrix<T>, Matrix<T1>> actMinX, Action<Matrix<T>, Matrix<T1>> actMaxX,\n                Action<Matrix<T>, Matrix<T1>> actMinY, Action<Matrix<T>, Matrix<T1>> actMaxY,\n                Action<Matrix<T>, Matrix<T1>> actMinXMinY, Action<Matrix<T>, Matrix<T1>> actMaxXMinY,\n                Action<Matrix<T>, Matrix<T1>> actMinXMaxY, Action<Matrix<T>, Matrix<T1>> actMaxXMaxY)\n        {\n            var target = new Matrix<T1>(source.Size);\n            target.F = source.F;\n\n            actCenter(source.SubCenter(border), target.SubCenter(border));\n            actMinX(source.SubMinX(border), target.SubMinX(border));\n            actMaxX(source.SubMaxX(border), target.SubMaxX(border));\n            actMinY(source.SubMinY(border), target.SubMinY(border));\n            actMaxY(source.SubMaxY(border), target.SubMaxY(border));\n            actMinXMinY(source.SubMinXMinY(border), target.SubMinXMinY(border));\n            actMaxXMinY(source.SubMaxXMinY(border), target.SubMaxXMinY(border));\n            actMinXMaxY(source.SubMinXMaxY(border), target.SubMinXMaxY(border));\n            actMaxXMaxY(source.SubMaxXMaxY(border), target.SubMaxXMaxY(border));\n\n            return target;\n        }\n\n        /// <summary>\n        /// Process an image volume with specific actions for the center and border\n        /// parts.\n        /// </summary>\n        public static void ApplyCenterBordersAndCorners<T>(\n                this Matrix<T> source, Border2l border,\n                Action<Matrix<T>> actCenter,\n                Action<Matrix<T>> actMinX, Action<Matrix<T>> actMaxX,\n                Action<Matrix<T>> actMinY, Action<Matrix<T>> actMaxY,\n                Action<Matrix<T>> actMinXMinY, Action<Matrix<T>> actMaxXMinY,\n                Action<Matrix<T>> actMinXMaxY, Action<Matrix<T>> actMaxXMaxY)\n        {\n\n            actCenter(source.SubCenter(border));\n            actMinX(source.SubMinX(border)); actMaxX(source.SubMaxX(border));\n            actMinY(source.SubMinY(border)); actMaxY(source.SubMaxY(border));\n            actMinXMinY(source.SubMinXMinY(border)); actMaxXMinY(source.SubMaxXMinY(border));\n            actMinXMaxY(source.SubMinXMaxY(border)); actMaxXMaxY(source.SubMaxXMaxY(border));\n        }\n\n        /// <summary>\n        /// Process an image volume with specific actions for the center and border\n        /// parts.\n        /// </summary>\n        public static void ApplyCenterBordersAndCorners<Td, Tv>(\n                this Matrix<Td, Tv> source, Border2l border,\n                Action<Matrix<Td, Tv>> actCenter,\n                Action<Matrix<Td, Tv>> actMinX, Action<Matrix<Td, Tv>> actMaxX,\n                Action<Matrix<Td, Tv>> actMinY, Action<Matrix<Td, Tv>> actMaxY,\n                Action<Matrix<Td, Tv>> actMinXMinY, Action<Matrix<Td, Tv>> actMaxXMinY,\n                Action<Matrix<Td, Tv>> actMinXMaxY, Action<Matrix<Td, Tv>> actMaxXMaxY)\n        {\n\n            actCenter(source.SubCenter(border));\n            actMinX(source.SubMinX(border)); actMaxX(source.SubMaxX(border));\n            actMinY(source.SubMinY(border)); actMaxY(source.SubMaxY(border));\n            actMinXMinY(source.SubMinXMinY(border)); actMaxXMinY(source.SubMaxXMinY(border));\n            actMinXMaxY(source.SubMinXMaxY(border)); actMaxXMaxY(source.SubMaxXMaxY(border));\n        }\n\n        #endregion\n\n        #region Generic Volume Processing\n\n        /// <summary>\n        /// Process an image volume with specific actions for the center and\n        /// border parts.\n        /// </summary>\n        public static Volume<T1> WithProcessedCenterBordersAndCorners<T, T1>(\n                this Volume<T> source, Border2l border,\n                Func<Volume<T>, Volume<T1>> funCenter,\n                Func<Volume<T>, Volume<T1>> funMinX, Func<Volume<T>, Volume<T1>> funMaxX,\n                Func<Volume<T>, Volume<T1>> funMinY, Func<Volume<T>, Volume<T1>> funMaxY,\n                Func<Volume<T>, Volume<T1>> funMinXMinY, Func<Volume<T>, Volume<T1>> funMaxXMinY,\n                Func<Volume<T>, Volume<T1>> funMinXMaxY, Func<Volume<T>, Volume<T1>> funMaxXMaxY)\n        {\n            var target = source.Size.CreateImageVolume<T1>();\n            target.F = source.F;\n            target.SubCenter(border).Set(funCenter(source.SubCenter(border)));\n            target.SubMinX(border).Set(funMinX(source.SubMinX(border)));\n            target.SubMaxX(border).Set(funMaxX(source.SubMaxX(border)));\n            target.SubMinY(border).Set(funMinY(source.SubMinY(border)));\n            target.SubMaxY(border).Set(funMaxY(source.SubMaxY(border)));\n            target.SubMinXMinY(border).Set(funMinXMinY(source.SubMinXMinY(border)));\n            target.SubMaxXMinY(border).Set(funMaxXMinY(source.SubMaxXMinY(border)));\n            target.SubMinXMaxY(border).Set(funMinXMaxY(source.SubMinXMaxY(border)));\n            target.SubMaxXMaxY(border).Set(funMaxXMaxY(source.SubMaxXMaxY(border)));\n            return target;\n        }\n\n        /// <summary>\n        /// Process an image volume with specific actions for the center and border\n        /// parts.\n        /// </summary>\n        public static void ApplyCenterBordersAndCorners<T>(\n                this Volume<T> source, Border2l border,\n                Action<Volume<T>> actCenter,\n                Action<Volume<T>> actMinX, Action<Volume<T>> actMaxX,\n                Action<Volume<T>> actMinY, Action<Volume<T>> actMaxY,\n                Action<Volume<T>> actMinXMinY, Action<Volume<T>> actMaxXMinY,\n                Action<Volume<T>> actMinXMaxY, Action<Volume<T>> actMaxXMaxY)\n        {\n\n            actCenter(source.SubCenter(border));\n            actMinX(source.SubMinX(border)); actMaxX(source.SubMaxX(border));\n            actMinY(source.SubMinY(border)); actMaxY(source.SubMaxY(border));\n            actMinXMinY(source.SubMinXMinY(border)); actMaxXMinY(source.SubMaxXMinY(border));\n            actMinXMaxY(source.SubMinXMaxY(border)); actMaxXMaxY(source.SubMaxXMaxY(border));\n        }\n\n        #endregion\n\n        #region Specific Matrix Border Manipulations\n\n        /// <summary>\n        /// Creates a new matrix with a border of the supplied size around the supplied matrix.\n        /// The resulting matrix retains the coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T> CopyWithBorderWindow<T>(this Matrix<T> matrix, Border2l border)\n        {\n            var bm = new Matrix<T>(matrix.SX + border.Min.X + border.Max.X,\n                                   matrix.SY + border.Min.Y + border.Max.Y)\n                        { F = new V2l(matrix.FX - border.Min.X, matrix.FY - border.Min.Y) };\n            bm.SubCenter(border).Set(matrix);\n            return bm;\n        }\n\n        /// <summary>\n        /// Creates a new matrix with a border of the supplied size around the supplied matrix.\n        /// The resulting matrix retains the coordinates of the original matrix.\n        /// </summary>\n        public static Matrix<T1> MapWithBorderWindow<T, T1>(\n                this Matrix<T> matrix, Border2l border,\n                Func<T, T1> item_fun)\n        {\n            var bm = new Matrix<T1>(matrix.SX + border.Min.X + border.Max.X,\n                                    matrix.SY + border.Min.Y + border.Max.Y)\n            { F = new V2l(matrix.FX - border.Min.X, matrix.FY - border.Min.Y) };\n            bm.SubCenter(border).SetMap(matrix, item_fun);\n            return bm;\n        }\n\n        /// <summary>\n        /// Creates a new matrix with a border of the supplied size around the supplied matrix.\n        /// the resulting matrix starts at zero coordinates.\n        /// </summary>\n        public static Matrix<T> CopyWithBorder<T>(this Matrix<T> matrix, Border2l border)\n        {\n            var bm = new Matrix<T>(matrix.SX + border.Min.X + border.Max.X,\n                                   matrix.SY + border.Min.Y + border.Max.Y);\n            bm.SubCenter(border).Set(matrix);\n            return bm;\n        }\n\n        /// <summary>\n        /// Creates a new matrix with a border of the supplied size around the supplied matrix.\n        /// the resulting matrix starts at zero coordinates.\n        /// </summary>\n        public static Matrix<T1> MapWithBorder<T, T1>(\n                this Matrix<T> matrix, Border2l border,\n                Func<T, T1> item_fun)\n        {\n            var bm = new Matrix<T1>(matrix.SX + border.Min.X + border.Max.X,\n                                   matrix.SY + border.Min.Y + border.Max.Y);\n            bm.SubCenter(border).SetMap(matrix, item_fun);\n            return bm;\n        }\n\n        /// <summary>\n        /// Set the border of a matrix to a specific value.\n        /// </summary>\n        public static void SetBorder<T>(this Matrix<T> matrix, Border2l border, T value)\n        {\n            matrix.ApplyCenterBordersAndCorners(border,\n                m => { },\n                m => m.Set(value), m => m.Set(value), m => m.Set(value), m => m.Set(value),\n                m => m.Set(value), m => m.Set(value), m => m.Set(value), m => m.Set(value));\n        }\n\n        /// <summary>\n        /// Replicate the border pixels of the center region outward.\n        /// </summary>\n        public static void ReplicateBorder<T>(this Matrix<T> matrix, Border2l border)\n        {\n            matrix.ApplyCenterBordersAndCorners(new Border2l(border.Min, border.Max),\n            m => { },\n            m => m.SetByCoord(y => m[m.EX, y], (y, x, vy) => vy),\n            m => m.SetByCoord(y => m[m.FX - 1, y], (y, x, vy) => vy),\n            m =>\n            {\n                var tm = m.SubMatrixWindow(m.F, m.S.YX, m.D.YX, m.F.YX);\n                tm.SetByCoord(y => tm[tm.EX, y], (y, x, vy) => vy);\n            },\n            m =>\n            {\n                var tm = m.SubMatrixWindow(m.F, m.S.YX, m.D.YX, m.F.YX);\n                tm.SetByCoord(y => tm[tm.FX - 1, y], (y, x, vy) => vy);\n            },\n            m => { var v = m[m.EX, m.EY]; m.SetByCoord((x, y) => v); },\n            m => { var v = m[m.FX - 1, m.EY]; m.SetByCoord((x, y) => v); },\n            m => { var v = m[m.EX, m.FY - 1]; m.SetByCoord((x, y) => v); },\n            m => { var v = m[m.FX - 1, m.FY - 1]; m.SetByCoord((x, y) => v); });\n        }\n\n        public static Matrix<T> GetMatrixFromTiles<T>(\n                this Border2l border, long x, long y, Func<long, long, Box.Flags, Matrix<T>> x_y_loadFun)\n        {\n            var flipped = border.Flipped;\n            var center = x_y_loadFun(x, y, Box.Flags.All);\n            if (center.IsInvalid) return center;\n            var result = center.CopyWithBorderWindow(border);\n\n            if (border.Min.Y > 0)\n            {\n                if (border.Min.X > 0)\n                {\n                    var tnn = x_y_loadFun(x - 1, y - 1, Box.Flags.MaxXMaxY);\n                    if (tnn.IsValid) result.SubMinXMinY(border).Set(tnn.SubMaxXMaxY(flipped));\n                }\n                var t0n = x_y_loadFun(x, y - 1, Box.Flags.MaxY);\n                if (t0n.IsValid) result.SubMinY(border).Set(t0n.SubMaxY(border.Min.Y));\n                if (border.Max.X > 0)\n                {\n                    var tpn = x_y_loadFun(x + 1, y - 1, Box.Flags.MinXMaxY);\n                    if (tpn.IsValid) result.SubMaxXMinY(border).Set(tpn.SubMinXMaxY(flipped));\n                }\n            }\n            if (border.Min.X > 0)\n            {\n                var tn0 = x_y_loadFun(x - 1, y, Box.Flags.MaxX);\n                if (tn0.IsValid) result.SubMinX(border).Set(tn0.SubMaxX(border.Min.X));\n            }\n            if (border.Max.X > 0)\n            {\n                var tp0 = x_y_loadFun(x + 1, y, Box.Flags.MinX);\n                if (tp0.IsValid) result.SubMaxX(border).Set(tp0.SubMinX(border.Max.X));\n            }\n            if (border.Max.Y > 0)\n            {\n                if (border.Min.X > 0)\n                {\n                    var tnp = x_y_loadFun(x - 1, y + 1, Box.Flags.MaxXMinY);\n                    if (tnp.IsValid) result.SubMinXMaxY(border).Set(tnp.SubMaxXMinY(flipped));\n                }\n                var t0p = x_y_loadFun(x, y + 1, Box.Flags.MinY);\n                if (t0p.IsValid) result.SubMaxY(border).Set(t0p.SubMinY(border.Max.Y));\n                if (border.Max.X > 0)\n                {\n                    var tpp = x_y_loadFun(x + 1, y + 1, Box.Flags.MinXMinY);\n                    if (tpp.IsValid) result.SubMaxXMaxY(border).Set(tpp.SubMinXMinY(flipped));\n                }\n            }\n            return result;\n        }\n\n\n        #endregion\n\n        #region Specific Volume Border Manipulations\n\n        /// <summary>\n        /// Creates a new image volume with a border of the supplied size\n        /// around the supplied image volume.\n        /// </summary>\n        public static Volume<T> CopyWithBorderWindow<T>(this Volume<T> volume, Border2l border)\n        {\n            var iv = new V3l(volume.SX + border.Min.X + border.Max.X,\n                             volume.SY + border.Min.Y + border.Max.Y,\n                             volume.SZ).CreateImageVolume<T>();\n            iv.F = new V3l(volume.FX - border.Min.X, volume.FY - border.Min.Y, volume.FZ);\n            iv.SubCenter(border).Set(volume);\n            return iv;\n        }\n\n        /// <summary>\n        /// Creates a new image volume with a border of the supplied size\n        /// around the supplied image volume.\n        /// </summary>\n        public static Volume<T1> MapWithBorderWindow<T, T1>(\n                this Volume<T> volume, Border2l border,\n                Func<T, T1> item_fun)\n        {\n            var iv = new V3l(volume.SX + border.Min.X + border.Max.X,\n                             volume.SY + border.Min.Y + border.Max.Y,\n                             volume.SZ).CreateImageVolume<T1>();\n            iv.F = new V3l(volume.FX - border.Min.X, volume.FY - border.Min.Y, volume.FZ);\n            iv.SubCenter(border).SetMap(volume, item_fun);\n            return iv;\n        }\n\n        /// <summary>\n        /// Creates a new image volume with a border of the supplied size\n        /// around the supplied image volume.\n        /// </summary>\n        public static Volume<T> CopyWithBorder<T>(this Volume<T> volume, Border2l border)\n        {\n            var iv = new V3l(volume.SX + border.Min.X + border.Max.X,\n                             volume.SY + border.Min.Y + border.Max.Y,\n                             volume.SZ).CreateImageVolume<T>();\n            iv.SubCenter(border).Set(volume);\n            return iv;\n        }\n\n        /// <summary>\n        /// Creates a new image volume with a border of the supplied size\n        /// around the supplied image volume.\n        /// </summary>\n        public static Volume<T1> MapWithBorder<T, T1>(\n                this Volume<T> volume, Border2l border,\n                Func<T, T1> item_fun)\n        {\n            var iv = new V3l(volume.SX + border.Min.X + border.Max.X,\n                             volume.SY + border.Min.Y + border.Max.Y,\n                             volume.SZ).CreateImageVolume<T1>();\n            iv.SubCenter(border).SetMap(volume, item_fun);\n            return iv;\n        }\n\n        /// <summary>\n        /// Set the border of an image volume to a specific value.\n        /// </summary>\n        public static void SetBorder<T>(this Volume<T> volume, Border2l border, T value)\n        {\n            volume.ApplyCenterBordersAndCorners(border,\n                v => { },\n                v => v.Set(value), v => v.Set(value), v => v.Set(value), v => v.Set(value),\n                v => v.Set(value), v => v.Set(value), v => v.Set(value), v => v.Set(value));\n        }\n\n        /// <summary>\n        /// Replicate the border pixels of the center region outward.\n        /// </summary>\n        public static void ReplicateBorder<T>(this Volume<T> volume, Border2l border)\n        {\n            volume.ApplyCenterBordersAndCorners(border,\n            v => { },\n            v => v.SetByCoord(z => false, (z, y, vz) => v[v.EX, y, z], (z, y, x, vz, vy) => vy),\n            v => v.SetByCoord(z => false, (z, y, vz) => v[v.FX - 1, y, z], (z, y, x, vz, vy) => vy),\n            v =>\n            {\n                var tv = v.SubVolumeWindow(v.F, v.S.YXZ, v.D.YXZ, v.F.YXZ);\n                tv.SetByCoord(z => false, (z, y, vz) => tv[tv.EX, y, z], (z, y, x, vz, vy) => vy);\n            },\n            v =>\n            {\n                var tv = v.SubVolumeWindow(v.F, v.S.YXZ, v.D.YXZ, v.F.YXZ);\n                tv.SetByCoord(z => false, (z, y, vz) => tv[tv.FX - 1, y, z], (z, y, x, vz, vy) => vy);\n            },\n            v => v.SetByCoord(z => v[v.EX, v.EY, z], (z, y, vz) => false, (z, y, x, vz, vy) => vz),\n            v => v.SetByCoord(z => v[v.FX - 1, v.EY, z], (z, y, vz) => false, (z, y, x, vz, vy) => vz),\n            v => v.SetByCoord(z => v[v.EX, v.FY - 1, z], (z, y, vz) => false, (z, y, x, vz, vy) => vz),\n            v => v.SetByCoord(z => v[v.FX - 1, v.FY - 1, z], (z, y, vz) => false, (z, y, x, vz, vy) => vz));\n        }\n\n        public static Volume<T> GetMatrixFromTiles<T>(\n                this Border2l border, long x, long y, Func<long, long, Box.Flags, Volume<T>> x_y_loadFun)\n        {\n            var flipped = border.Flipped;\n            var center = x_y_loadFun(x, y, Box.Flags.All);\n            if (center.IsInvalid) return center;\n            var result = center.CopyWithBorderWindow(border);\n\n            if (border.Min.Y > 0)\n            {\n                if (border.Min.X > 0)\n                {\n                    var tnn = x_y_loadFun(x - 1, y - 1, Box.Flags.MaxXMaxY);\n                    if (tnn.IsValid) result.SubMinXMinY(border).Set(tnn.SubMaxXMaxY(flipped));\n                }\n                var t0n = x_y_loadFun(x, y - 1, Box.Flags.MaxY);\n                if (t0n.IsValid) result.SubMinY(border).Set(t0n.SubMaxY(border.Min.Y));\n                if (border.Max.X > 0)\n                {\n                    var tpn = x_y_loadFun(x + 1, y - 1, Box.Flags.MinXMaxY);\n                    if (tpn.IsValid) result.SubMaxXMinY(border).Set(tpn.SubMinXMaxY(flipped));\n                }\n            }\n            if (border.Min.X > 0)\n            {\n                var tn0 = x_y_loadFun(x - 1, y, Box.Flags.MaxX);\n                if (tn0.IsValid) result.SubMinX(border).Set(tn0.SubMaxX(border.Min.X));\n            }\n            if (border.Max.X > 0)\n            {\n                var tp0 = x_y_loadFun(x + 1, y, Box.Flags.MinX);\n                if (tp0.IsValid) result.SubMaxX(border).Set(tp0.SubMinX(border.Max.X));\n            }\n            if (border.Max.Y > 0)\n            {\n                if (border.Min.X > 0)\n                {\n                    var tnp = x_y_loadFun(x - 1, y + 1, Box.Flags.MaxXMinY);\n                    if (tnp.IsValid) result.SubMinXMaxY(border).Set(tnp.SubMaxXMinY(flipped));\n                }\n                var t0p = x_y_loadFun(x, y + 1, Box.Flags.MinY);\n                if (t0p.IsValid) result.SubMaxY(border).Set(t0p.SubMinY(border.Max.Y));\n                if (border.Max.X > 0)\n                {\n                    var tpp = x_y_loadFun(x + 1, y + 1, Box.Flags.MinXMinY);\n                    if (tpp.IsValid) result.SubMaxXMaxY(border).Set(tpp.SubMinXMinY(flipped));\n                }\n            }\n            return result;\n        }\n\n        #endregion\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/ImageTensors.cs",
    "content": "using System;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base\n{\n    /// <summary>\n    /// Interpolation scheme.\n    /// Values correspond to IPPI_INTERP_*\n    /// </summary>\n    public enum ImageInterpolation : int\n    {\n        /// <summary>\n        /// IPPI_SMOOTH_EDGE  = (1 &lt;&lt; 31)\n        /// </summary>\n        SmoothEdge = -2147483648,\n        /// <summary>\n        /// IPPI_INTER_NN\n        /// </summary>\n        Near = 1,\n        /// <summary>\n        /// IPPI_INTER_LINEAR\n        /// </summary>\n        Linear = 2,\n        /// <summary>\n        /// IPPI_INTER_CUBIC\n        /// </summary>\n        Cubic = 4,\n        /// <summary>\n        /// IPPI_INTER_SUPER\n        /// </summary>\n        SuperSample = 8,\n        /// <summary>\n        /// IPPI_INTER_LANCZOS\n        /// </summary>\n        Lanczos = 16,\n    }\n\n    public enum ImageTrafo\n    {\n        /// <summary>No Trafo.</summary>\n        Identity = 0,\n        /// <summary>Rotate 90 CCW.</summary>\n        Rot90 = 1,\n        /// <summary>Rotate 180.</summary>\n        Rot180 = 2,\n        /// <summary>Rotate 270 CCW.</summary>\n        Rot270 = 3,\n        /// <summary>Mirror along X-direction, horizontally, about Y-Axis.</summary>\n        MirrorX = 4,\n        /// <summary>Exchange X and Y axes, flip about diagonal +x/+y.</summary>\n        Transpose = 5,\n        /// <summary>Mirror along Y-direction, vertically, about X-Axis.</summary>\n        MirrorY = 6,\n        /// <summary>Exchange X and Y axes and rotate 180, flip about diagonal +x/-y.</summary>\n        Transverse = 7,\n    };\n\n    public enum ImageBorderType\n    {\n        Const = 0,\n        Repl = 1,\n        Wrap = 2,\n        Mirror = 3,\n        MirrorR = 4,\n        Mirror2 = 5,\n        InMem = 6,\n        InMemTop = 16,\n        InMemBottom = 32,\n    }\n\n    public enum Norm\n    {\n        NormInf = 0,\n        NormL1 = 1,\n        NormL2 = 2,\n        NormFM = 3,\n    }\n\n    public static class ImageTensors\n    {\n        #region Layout\n\n        public static bool HasImageLayout<T>(this Matrix<T> matrix)\n        {\n            return matrix.First == V2l.Zero && matrix.Origin == 0L\n                    && matrix.Info.Delta.X == 1L\n                    && matrix.Info.Delta.Y == matrix.Info.Size.X\n                    && matrix.Data.LongLength >= matrix.Info.Count;\n        }\n\n        public static bool HasImageWindowLayout<T>(this Matrix<T> matrix)\n        {\n            return matrix.Info.Delta.X == 1L && matrix.Info.Delta.Y > 0L; \n        }\n\n        public static bool HasImageLayout<T>(this Volume<T> volume)\n        {\n            return volume.First == V3l.Zero && volume.Origin == 0L\n                    && volume.Info.Delta.Z == 1L\n                    && volume.Info.Delta.X == volume.Info.Size.Z\n                    && volume.Info.Delta.Y == volume.Info.Size.X * volume.Info.Delta.X\n                    && volume.Data.LongLength >= volume.Info.Size.Y * volume.Info.Delta.Y;\n        }\n\n        public static bool HasImageWindowLayout<T>(this Volume<T> vol)\n        {\n            return vol.Info.Delta.Z == 1L\n                    && vol.Info.Delta.X == vol.Info.Size.Z\n                    && vol.Info.Delta.Y > 0L;\n        }\n\n        public static bool HasImageLayout<T>(this Tensor4<T> tensor4)\n        {\n            return tensor4.First == V4l.Zero && tensor4.Origin == 0L\n                    && tensor4.Info.Delta.W == 1L\n                    && tensor4.Info.Delta.X == tensor4.Info.Size.W\n                    && tensor4.Info.Delta.Y == tensor4.Info.Size.X * tensor4.Info.Delta.X\n                    && tensor4.Info.Delta.Z == tensor4.Info.Size.Y * tensor4.Info.Delta.Y\n                    && tensor4.Data.LongLength >= tensor4.Info.Size.Z * tensor4.Info.Delta.Z;\n        }\n\n        public static bool HasImageWindowLayout<T>(this Tensor4<T> tensor4)\n        {\n            return tensor4.Info.Delta.W == 1L\n                    && tensor4.Info.Delta.X == tensor4.Info.Size.W\n                    && tensor4.Info.Delta.Y > 0L\n                    && tensor4.Info.Delta.Z > 0L;\n        }\n\n        #endregion\n\n        #region Creation\n\n        /// <summary>\n        /// Creates a valid image matrix, with stride appropriate for the\n        /// given size. Note that this is just the same as a normal matrix.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Matrix<T> CreateImageMatrix<T>(this V2l size)\n            => new (size);\n\n        /// <summary>\n        /// Creates a valid image volume, with stride appropriate for the\n        /// given size. For image volumes DZ = 1.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> CreateImageVolume<T>(this V3l size)\n            => new (0L, size, new V3l(size.Z, size.Z * size.X, 1L));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> CreateImageVolume<T>(this T[] data, V3l size)\n            => new (data, 0L, size, new V3l(size.Z, size.Z * size.X, 1L));\n\n        /// <summary>\n        /// Creates a valid image 4D tensor, with stride appropriate for the\n        /// given size.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Tensor4<T> CreateImageTensor4<T>(this V4l size)\n            => new (0L, size, new V4l(size.W, size.W * size.X, size.W * size.X * size.Y, 1L));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Tensor4<T> CreateImageTensor4<T>(this T[] data, V4l size)\n            => new(data, 0L, size, new V4l(size.W, size.W * size.X, size.W * size.X * size.Y, 1L));\n\n        #endregion\n\n        #region SubImages\n\n        /// <summary>\n        /// Returns a sub image volume beginning at the supplied pixel\n        /// coordinate with the supplied size in pixels. The sub image\n        /// retains the coordinates of the parent image.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> SubImageWindow<T>(this Volume<T> vol, V2l begin, V2l size)\n            => vol.SubVolumeWindow(new V3l(begin.XY, vol.FZ), new V3l(size.XY, vol.SZ));\n\n        /// <summary>\n        /// Returns a sub image volume beginning at the supplied pixel\n        /// coordinate with the supplied size in pixels. The sub image\n        /// retains the coordinates of the parent image.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> SubImageWindow<T>(this Volume<T> vol, long beginX, long beginY, long sizeX, long sizeY)\n            => vol.SubImageWindow(new V2l(beginX, beginY), new V2l(sizeX, sizeY));\n\n        /// <summary>\n        /// Returns a sub image tensor beginning at the supplied pixel\n        /// coordinate with the supplied size in pixels. The sub image\n        /// retains the coordinates of the parent image.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Tensor4<T> SubImageWindow<T>(this Tensor4<T> tensor4, V3l begin, V3l size)\n            => tensor4.SubTensor4Window(new V4l(begin.XYZ, tensor4.FW), new V4l(size.XYZ, tensor4.SW));\n\n        /// <summary>\n        /// Returns a sub image tensor beginning at the supplied pixel\n        /// coordinate with the supplied size in pixels. The sub image\n        /// retains the coordinates of the parent image.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Tensor4<T> SubImageWindow<T>(this Tensor4<T> tensor4, long beginX, long beginY, long beginZ, long sizeX, long sizeY, long sizeZ)\n            => tensor4.SubImageWindow(new V3l(beginX, beginY, beginZ), new V3l(sizeX, sizeY, sizeZ));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> SubImageWindowAtZ<T>(this Tensor4<T> tensor4, long z)\n            => tensor4.SubXYWVolumeWindow(z);\n\n        /// <summary>\n        /// Returns a sub image volume beginning at the supplied pixel\n        /// coordinate with the supplied size in pixels. The coordinates\n        /// of the sub image volume start at 0, 0, 0.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> SubImage<T>(this Volume<T> vol, V2l begin, V2l size)\n            => vol.SubVolume(new V3l(begin.XY, vol.FZ), new V3l(size.XY, vol.SZ));\n\n        /// <summary>\n        /// Returns a sub image volume beginning at the supplied pixel\n        /// coordinate with the supplied size in pixels. The coordinates\n        /// of the sub image volume start at 0, 0, 0.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> SubImage<T>(this Volume<T> vol, long beginX, long beginY, long sizeX, long sizeY)\n            => vol.SubImage(new V2l(beginX, beginY), new V2l(sizeX, sizeY));\n\n        /// <summary>\n        /// Returns a sub image tensor beginning at the supplied pixel\n        /// coordinate with the supplied size in pixels. The coordinates\n        /// of the sub image tensor start at 0, 0, 0, 0.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Tensor4<T> SubImage<T>(this Tensor4<T> tensor4, V3l begin, V3l size)\n            => tensor4.SubTensor4(new V4l(begin.XYZ, tensor4.FW), new V4l(size.XYZ, tensor4.SW));\n\n        /// <summary>\n        /// Returns a sub image tensor beginning at the supplied pixel\n        /// coordinate with the supplied size in pixels. The coordinates\n        /// of the sub image tensor start at 0, 0, 0, 0.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Tensor4<T> SubImage<T>(this Tensor4<T> tensor4, long beginX, long beginY, long beginZ, long sizeX, long sizeY, long sizeZ)\n            => tensor4.SubImage(new V3l(beginX, beginY, beginZ), new V3l(sizeX, sizeY, sizeZ));\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> SubImageAtZ<T>(this Tensor4<T> tensor4, long z)\n            => tensor4.SubXYWVolume(z);\n\n        /// <summary>\n        /// Returns a single image row as an image volume.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> ImageWindowRow<T>(this Volume<T> vol, long y)\n            => vol.SubImageWindow(new V2l(vol.FX, y), new V2l(vol.SX, 1));\n\n        /// <summary>\n        /// Returns a single image column as an image volume.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> ImageWindowCol<T>(this Volume<T> vol, long x)\n            => vol.SubImageWindow(new V2l(x, vol.FY), new V2l(1, vol.SY));\n\n        /// <summary>\n        /// Returns a single image row as an image volume with coordinates\n        /// starting at 0, 0, 0.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> ImageRow<T>(this Volume<T> vol, long y)\n            => vol.SubImage(new V2l(vol.FX, y), new V2l(vol.SX, 1));\n\n        /// <summary>\n        /// Returns a single image column as an image volume with coordinates\n        /// starting at 0, 0, 0.\n        /// </summary>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static Volume<T> ImageCol<T>(this Volume<T> vol, long x)\n            => vol.SubImage(new V2l(x, vol.FY), new V2l(1, vol.SY));\n\n        #endregion\n\n        #region Copy/Map Image\n\n        /// <summary>\n        /// Copies this volume to image memory layout.\n        /// Retains the coordinates of the original image.\n        /// </summary>\n        public static Volume<T> CopyToImageWindow<T>(this Volume<T> volume)\n        {\n            var copy = CreateImageVolume<T>(volume.S);\n            copy.F = volume.F;\n            copy.Set(volume);\n            return copy;\n        }\n\n        /// <summary>\n        /// Copies this volume to image memory layout.\n        /// Coordinates of the result start at [0, 0, 0].\n        /// </summary>\n        public static Volume<T> CopyToImage<T>(this Volume<T> volume)\n        {\n            var copy = CreateImageVolume<T>(volume.S);\n            copy.Set(volume);\n            return copy;\n        }\n\n        /// <summary>\n        /// Copies this volume to image memory layout, while piping all elements\n        /// through the supplied function.\n        /// Retains the coordinates of the original image.\n        /// </summary>\n        public static Volume<T1> MapToImageWindow<T, T1>(this Volume<T> volume, Func<T, T1> fun)\n        {\n            var copy = CreateImageVolume<T1>(volume.S);\n            copy.F = volume.F;\n            copy.SetMap(volume, fun);\n            return copy;\n        }\n\n        /// <summary>\n        /// Copies this volume to image memory layout, while piping all elements\n        /// through the supplied function.\n        /// Coordinates of the result start at [0, 0, 0].\n        /// </summary>\n        public static Volume<T1> MapToImage<T, T1>(this Volume<T> volume, Func<T, T1> fun)\n        {\n            var copy = CreateImageVolume<T1>(volume.S);\n            copy.SetMap(volume, fun);\n            return copy;\n        }\n\n        /// <summary>\n        /// Copies this 4D tensor to image memory layout.\n        /// Retains the coordinates of the original image.\n        /// </summary>\n        public static Tensor4<T> CopyToImageWindow<T>(this Tensor4<T> tensor4)\n        {\n            var copy = CreateImageTensor4<T>(tensor4.S);\n            copy.F = tensor4.F;\n            copy.Set(tensor4);\n            return copy;\n        }\n\n        /// <summary>\n        /// Copies this 4D tensor to image memory layout.\n        /// Coordinates of the result start at [0, 0, 0, 0].\n        /// </summary>\n        public static Tensor4<T> CopyToImage<T>(this Tensor4<T> tensor4)\n        {\n            var copy = CreateImageTensor4<T>(tensor4.S);\n            copy.Set(tensor4);\n            return copy;\n        }\n\n        /// <summary>\n        /// Copies this 4D tensor to image memory layout, while piping all elements\n        /// through the supplied function.\n        /// Retains the coordinates of the original image.\n        /// </summary>\n        public static Tensor4<T1> MapToImageWindow<T, T1>(this Tensor4<T> tensor4, Func<T, T1> fun)\n        {\n            var copy = CreateImageTensor4<T1>(tensor4.S);\n            copy.F = tensor4.F;\n            copy.SetMap(tensor4, fun);\n            return copy;\n        }\n\n        /// <summary>\n        /// Copies this 4D tensor to image memory layout, while piping all elements\n        /// through the supplied function.\n        /// Coordinates of the result start at [0, 0, 0, 0].\n        /// </summary>\n        public static Tensor4<T1> MapToImage<T, T1>(this Tensor4<T> tensor4, Func<T, T1> fun)\n        {\n            var copy = CreateImageTensor4<T1>(tensor4.S);\n            copy.SetMap(tensor4, fun);\n            return copy;\n        }\n\n        #endregion\n\n        #region ToImage\n\n        /// <summary>\n        /// Converts this matrix to image memory layout (if it is not already).\n        /// Coordinates of the result start at [0, 0].\n        /// </summary>\n        public static Matrix<T> ToImage<T>(this Matrix<T> matrix)\n        {\n            return matrix.HasImageLayout() ? matrix : matrix.Copy();\n        }\n\n        /// <summary>\n        /// Converts this matrix to image memory layout (if it is not already).\n        /// Retains coordinates of original image.\n        /// </summary>\n        public static Matrix<T> ToImageWindow<T>(this Matrix<T> matrix)\n        {\n            return matrix.HasImageWindowLayout() ? matrix : matrix.CopyWindow();\n        }\n\n        /// <summary>\n        /// Converts this volume to image memory layout (if it is not already).\n        /// Coordinates of the result start at [0, 0, 0].\n        /// </summary>\n        public static Volume<T> ToImage<T>(this Volume<T> volume)\n        {\n            return volume.HasImageLayout() ? volume : volume.CopyToImage();\n        }\n\n        /// <summary>\n        /// Converts this volume to image memory layout (if it is not already).\n        /// Retains coordinates of th original volume.\n        /// </summary>\n        public static Volume<T> ToImageWindow<T>(this Volume<T> volume)\n        {\n            return volume.HasImageWindowLayout() ? volume : volume.CopyToImageWindow();\n        }\n\n        #endregion\n\n        #region Reinterpretation\n\n        /// <summary>\n        /// Reinterprets an image volume as a matrix of colors with supplied color intent.\n        /// </summary>\n        /// <exception cref=\"NotSupportedException\">if the element type and view type are incompatible for the given intent.</exception>\n        public static Matrix<Td, Tv> GetMatrix<Td, Tv>(this Volume<Td> volume, Symbol intent)\n        {\n            var matrix = volume.SubXYMatrixWindow<Tv>(0L);\n            matrix.Accessors = TensorAccessors.Get<Td, Tv>(intent, volume.DeltaArray);\n            return matrix;\n        }\n\n        /// <summary>\n        /// Reinterprets a 4D image tensor as a volume of colors with supplied color intent.\n        /// <exception cref=\"NotSupportedException\">if the element type and view type are incompatible for the given intent.</exception>\n        /// </summary>\n        public static Volume<Td, Tv> GetVolume<Td, Tv>(this Tensor4<Td> tensor4, Symbol intent)\n        {\n            var volume = tensor4.SubXYZVolumeWindow<Tv>(0L);\n            volume.Accessors = TensorAccessors.Get<Td, Tv>(intent, tensor4.DeltaArray);\n            return volume;\n        }\n\n        /// <summary>\n        /// Reinterprets a matrix as a volume with Size.Z = 1. The new volume starts at [0, 0, 0].\n        /// </summary>\n        public static Volume<T> AsVolume<T>(this Matrix<T> matrix)\n        {\n            return new Volume<T>(matrix.Data, matrix.Origin, matrix.Size.XYI, matrix.Delta.XYI);\n        }\n\n        /// <summary>\n        /// Reinterprets a matrix as a volume with Size.Z = 1. Retain coordinates of the matrix.\n        /// </summary>\n        public static Volume<T> AsVolumeWindow<T>(this Matrix<T> matrix)\n        {\n            return new Volume<T>(matrix.Data, matrix.Origin, matrix.Size.XYI, matrix.Delta.XYI) { F = matrix.F.XYO };\n        }\n\n        /// <summary>\n        /// Reinterprets a volume as a volume of different type.\n        /// <exception cref=\"NotSupportedException\">if the element type and view type are incompatible.</exception>\n        /// </summary>\n        public static Volume<Td, Tv> AsVolume<Td, Tv>(this Volume<Td> volume)\n        {\n            var result = new Volume<Td, Tv>(volume.Data, volume.Info);\n            result.Accessors = TensorAccessors.Get<Td, Tv>(TensorAccessors.Intent.ColorChannel, volume.DeltaArray);\n            return result;\n        }\n\n        /// <summary>\n        /// Reinterprets a volume with Size.Z = 1 as matrix. The new matrix starts at [0, 0].\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">if Size.Z is not 1.</exception>\n        public static Matrix<T> AsMatrix<T>(this Volume<T> volume)\n        {\n            if (volume.SZ != 1L) throw new InvalidOperationException($\"Cannot view volume with Size.Z = {volume.SZ} as matrix.\");\n            return new Matrix<T>(volume.Data, volume.FirstIndex, volume.S.XY, volume.D.XY);\n        }\n\n        /// <summary>\n        /// Reinterprets a volume with Size.Z = 1 as matrix. Retains the coordinates of the volume.\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">if Size.Z is not 1.</exception>\n        public static Matrix<T> AsMatrixWindow<T>(this Volume<T> volume)\n        {\n            if (volume.SZ != 1L) throw new InvalidOperationException($\"Cannot view volume with Size.Z = {volume.SZ} as matrix.\");\n            return new Matrix<T>(volume.Data, volume.Info.FirstIndex, volume.S.XY, volume.D.XY) { F = volume.F.XY };\n        }\n\n        /// <summary>\n        /// Reinterprets a volume as a 4D tensor with Size.W = 1. The new 4D tensor starts at [0, 0, 0, 0].\n        /// </summary>\n        public static Tensor4<T> AsTensor4<T>(this Volume<T> volume)\n        {\n            return new Tensor4<T>(volume.Data, volume.Origin, volume.Size.XYZI, volume.Delta.XYZI);\n        }\n\n        /// <summary>\n        /// Reinterprets a volume as a 4D tensor with Size.W = 1. Retain coordinates of the volume.\n        /// </summary>\n        public static Tensor4<T> AsTensor4Window<T>(this Volume<T> volume)\n        {\n            return new Tensor4<T>(volume.Data, volume.Origin, volume.Size.XYZI, volume.Delta.XYZI) { F = volume.F.XYZO };\n        }\n\n        /// <summary>\n        /// Reinterprets a 4D tensor as a 4D tensor of different type.\n        /// </summary>\n        /// <exception cref=\"NotSupportedException\">if the element type and view type are incompatible.</exception>\n        public static Tensor4<Td, Tv> AsTensor4<Td, Tv>(this Tensor4<Td> tensor4)\n        {\n            var result = new Tensor4<Td, Tv>(tensor4.Data, tensor4.Info);\n            result.Accessors = TensorAccessors.Get<Td, Tv>(TensorAccessors.Intent.ColorChannel, tensor4.DeltaArray);\n            return result;\n        }\n\n        /// <summary>\n        /// Reinterprets a 4D tensor with Size.W = 1 as volume. The new volume starts at [0, 0, 0].\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">if Size.W is not 1.</exception>\n        public static Volume<T> AsVolume<T>(this Tensor4<T> tensor4)\n        {\n            if (tensor4.SW != 1L) throw new InvalidOperationException($\"Cannot view 4D tensor with Size.W = {tensor4.SW} as volume.\");\n            return new Volume<T>(tensor4.Data, tensor4.FirstIndex, tensor4.S.XYZ, tensor4.D.XYZ);\n        }\n\n        /// <summary>\n        /// Reinterprets a 4D tensor with Size.W = 1 as volume. Retain the coordinates of the 4D tensor.\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">if Size.W is not 1.</exception>\n        public static Volume<T> AsVolumeWindow<T>(this Tensor4<T> tensor4)\n        {\n            if (tensor4.SW != 1L) throw new InvalidOperationException($\"Cannot view 4D tensor with Size.W = {tensor4.SW} as volume.\");\n            return new Volume<T>(tensor4.Data, tensor4.FirstIndex, tensor4.S.XYZ, tensor4.D.XYZ) { F = tensor4.F.XYZ };\n        }\n\n        #endregion\n\n        #region Color Conversions\n\n        public static Matrix<ushort> ToUShortColor(this Matrix<byte> matrix)\n        {\n            return matrix.MapWindow(Col.ByteToUShort);\n        }\n\n        public static Matrix<uint> ToUIntColor(this Matrix<byte> matrix)\n        {\n            return matrix.MapWindow(Col.ByteToUInt);\n        }\n\n        public static Matrix<float> ToFloatColor(this Matrix<byte> matrix)\n        {\n            return matrix.MapWindow(Col.ByteToFloat);\n        }\n\n        public static Matrix<double> ToDoubleColor(this Matrix<byte> matrix)\n        {\n            return matrix.MapWindow(Col.ByteToDouble);\n        }\n\n        public static Matrix<byte> ToByteColor(this Matrix<ushort> matrix)\n        {\n            return matrix.MapWindow(Col.UShortToByte);\n        }\n\n        public static Matrix<uint> ToUIntColor(this Matrix<ushort> matrix)\n        {\n            return matrix.MapWindow(Col.UShortToUInt);\n        }\n\n        public static Matrix<float> ToFloatColor(this Matrix<ushort> matrix)\n        {\n            return matrix.MapWindow(Col.UShortToFloat);\n        }\n\n        public static Matrix<double> ToDoubleColor(this Matrix<ushort> matrix)\n        {\n            return matrix.MapWindow(Col.UShortToDouble);\n        }\n\n        public static Matrix<byte> ToByteColor(this Matrix<uint> matrix)\n        {\n            return matrix.MapWindow(Col.UIntToByte);\n        }\n\n        public static Matrix<ushort> ToUShortColor(this Matrix<uint> matrix)\n        {\n            return matrix.MapWindow(Col.UIntToUShort);\n        }\n\n        public static Matrix<float> ToFloatColor(this Matrix<uint> matrix)\n        {\n            return matrix.MapWindow(Col.UIntToFloat);\n        }\n\n        public static Matrix<double> ToDoubleColor(this Matrix<uint> matrix)\n        {\n            return matrix.MapWindow(Col.UIntToDouble);\n        }\n\n        public static Matrix<byte> ToByteColor(this Matrix<float> matrix)\n        {\n            return matrix.MapWindow(Col.FloatToByte);\n        }\n\n        public static Matrix<ushort> ToUShortColor(this Matrix<float> matrix)\n        {\n            return matrix.MapWindow(Col.FloatToUShort);\n        }\n\n        public static Matrix<uint> ToUIntColor(this Matrix<float> matrix)\n        {\n            return matrix.MapWindow(Col.FloatToUInt);\n        }\n\n        public static Matrix<double> ToDoubleColor(this Matrix<float> matrix)\n        {\n            return matrix.MapWindow(Col.FloatToDouble);\n        }\n\n        public static Matrix<byte> ToByteColor(this Matrix<double> matrix)\n        {\n            return matrix.MapWindow(Col.DoubleToByte);\n        }\n\n        public static Matrix<ushort> ToUShortColor(this Matrix<double> matrix)\n        {\n            return matrix.MapWindow(Col.DoubleToUShort);\n        }\n\n        public static Matrix<uint> ToUIntColor(this Matrix<double> matrix)\n        {\n            return matrix.MapWindow(Col.DoubleToUInt);\n        }\n\n        public static Matrix<float> ToFloatColor(this Matrix<double> matrix)\n        {\n            return matrix.MapWindow(Col.DoubleToFloat);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/Interfaces.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    #region ITensorLong\n\n    /// <summary>\n    /// This interface defines properties of Tensors and TensorInfos that are\n    /// independent of their dimension (rank).\n    /// </summary>\n    public interface ITensorLong\n    {\n        /// <summary>\n        /// The rank of the tensor, in our case this is equal to the tensor's\n        /// dimension.\n        /// </summary>\n        int Rank { get; }\n\n        /// <summary>\n        /// The index of the element at the origin within the tensor's data\n        /// array. Note that this index may actually lie outside the tensor's\n        /// data array if the lowest valid coordinate of the tensor (First,\n        /// FirstArray) has positive values.\n        /// </summary>\n        long OriginIndex { get; set; }\n\n        /// <summary>\n        /// The deltas or strides of the tensor indices in each dimension. \n        /// </summary>\n        long[] DeltaArray { get; set; }\n\n        /// <summary>\n        /// The size of the tensor in each dimension.\n        /// </summary>\n        long[] SizeArray { get; set; }\n\n        /// <summary>\n        /// The lowest valid coordinate of the tensor. \n        /// </summary>\n        long[] FirstArray { get; set; }\n    }\n\n    #endregion\n\n    #region ITensorInfo\n\n    /// <summary>\n    /// Dimension independent properties of tensor infos, and actions\n    /// that can be performed on tensors infos regardless of their\n    /// dimension.\n    /// </summary>\n    public interface ITensorInfo : ITensorLong\n    {\n        /// <summary>\n        /// Perform an action for each element of the tensor. The index\n        /// of each element within the tensor's data array is supplied\n        /// as a parameter to the action.\n        /// </summary>\n        /// <param name=\"i_action\"></param>\n        void ForeachIndex(Action<long> i_action);    \n    }\n\n    #endregion\n\n    #region IArrayTensorInfo\n\n    /// <summary>\n    /// All tensors built on top of arrays implement this interface.\n    /// </summary>\n    public interface IArrayTensor : ITensorLong\n    {\n        Type ArrayType { get; }\n        Array Array { get; set; }\n        long Origin { get; set; }\n    }\n\n    #endregion\n\n    #region IArrayVector\n\n    public interface IArrayVector : IArrayTensor\n    {\n        long Size { get; set; }\n        long Delta { get; set; }\n        long First { get; set; }\n    }\n\n    #endregion\n\n    #region IArrayMatrix\n\n    public interface IArrayMatrix : IArrayTensor\n    {\n        V2l Size { get; set; }\n        V2l Delta { get; set; }\n        V2l First { get; set; }\n    }\n\n    #endregion\n\n    #region IArrayVolume\n\n    public interface IArrayVolume : IArrayTensor\n    {\n        V3l Size { get; set; }\n        V3l Delta { get; set; }\n        V3l First { get; set; }\n    }\n\n    #endregion\n\n    #region IArrayTensor4\n\n    public interface IArrayTensor4 : IArrayTensor\n    {\n        V4l Size { get; set; }\n        V4l Delta { get; set; }\n        V4l First { get; set; }\n    }\n\n    #endregion\n\n    #region IArrayTensorN\n\n    public interface IArrayTensorN : IArrayTensor\n    {\n        long[] Size { get; set; }\n        long[] Delta { get; set; }\n    }\n\n    #endregion\n\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/Parallel.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base\n{\n    public static partial class Tensor\n    {\n        public static Matrix<Td> SetByCoordParallelX<Td>(\n                this Matrix<Td> mat, Func<long, long, Td> x_y_valueFun)\n        {\n            Parallel.For(mat.FX, mat.EX, x => mat.SubYVectorWindow(x).SetByCoord(y => x_y_valueFun(x, y)));\n            return mat;\n        }\n\n        public static Matrix<Td, Tv> SetByCoordParallelX<Td, Tv>(\n                this Matrix<Td, Tv> mat, Func<long, long, Tv> x_y_valueFun)\n        {\n            Parallel.For(mat.FX, mat.EX, x => mat.SubYVectorWindow(x).SetByCoord(y => x_y_valueFun(x, y)));\n            return mat;\n        }\n\n        public static Matrix<Td> SetByCoordParallelY<Td>(\n                this Matrix<Td> mat, Func<long, long, Td> x_y_valueFun)\n        {\n            Parallel.For(mat.FY, mat.EY, y => mat.SubXVectorWindow(y).SetByCoord(x => x_y_valueFun(x, y)));\n            return mat;\n        }\n\n        public static Matrix<Td, Tv> SetByCoordParallelY<Td, Tv>(\n                this Matrix<Td, Tv> mat, Func<long, long, Tv> x_y_valueFun)\n        {\n            Parallel.For(mat.FY, mat.EY, y => mat.SubXVectorWindow(y).SetByCoord(x => x_y_valueFun(x, y)));\n            return mat;\n        }\n\n        public static Volume<Td> SetByCoordParallelX<Td>(\n                this Volume<Td> vol, Func<long, long, long, Td> x_y_z_valueFun)\n        {\n            Parallel.For(vol.FX, vol.EX, x => vol.SubYZMatrixWindow(x).SetByCoord((y, z) => x_y_z_valueFun(x, y, z)));\n            return vol;\n        }\n\n        public static Volume<Td, Tv> SetByCoordParallelX<Td, Tv>(\n                this Volume<Td, Tv> vol, Func<long, long, long, Tv> x_y_z_valueFun)\n        {\n            Parallel.For(vol.FX, vol.EX, x => vol.SubYZMatrixWindow(x).SetByCoord((y, z) => x_y_z_valueFun(x, y, z)));\n            return vol;\n        }\n\n        public static Volume<Td> SetByCoordParallelY<Td>(\n                this Volume<Td> vol, Func<long, long, long, Td> x_y_z_valueFun)\n        {\n            Parallel.For(vol.FY, vol.EY, y => vol.SubXZMatrixWindow(y).SetByCoord((x, z) => x_y_z_valueFun(x, y, z)));\n            return vol;\n        }\n\n        public static Volume<Td, Tv> SetByCoordParallelY<Td, Tv>(\n                this Volume<Td, Tv> vol, Func<long, long, long, Tv> x_y_z_valueFun)\n        {\n            Parallel.For(vol.FY, vol.EY, y => vol.SubXZMatrixWindow(y).SetByCoord((x, z) => x_y_z_valueFun(x, y, z)));\n            return vol;\n        }\n\n        public static Volume<Td> SetByCoordParallelZ<Td>(\n                this Volume<Td> vol, Func<long, long, long, Td> x_y_z_valueFun)\n        {\n            Parallel.For(vol.FZ, vol.EZ, z => vol.SubXYMatrixWindow(z).SetByCoord((x, y) => x_y_z_valueFun(x, y, z)));\n            return vol;\n        }\n\n        public static Volume<Td, Tv> SetByCoordParallelZ<Td, Tv>(\n                this Volume<Td, Tv> vol, Func<long, long, long, Tv> x_y_z_valueFun)\n        {\n            Parallel.For(vol.FZ, vol.EZ, z => vol.SubXYMatrixWindow(z).SetByCoord((x, y) => x_y_z_valueFun(x, y, z)));\n            return vol;\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Tensors/Tools.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    internal static class Tools\n    {\n        public static void CheckMatching(long v1, long v2)\n        {\n            if (v1 != v2) throw new Exception(\"mismatch\");\n        }\n\n        public static void CheckMatching(long v1, long v2, long v3)\n        {\n            CheckMatching(v1, v2); CheckMatching(v1, v3);\n        }\n\n        public static void CheckMatching(long v1, long v2, long v3, long v4)\n        {\n            CheckMatching(v1, v2); CheckMatching(v1, v3); CheckMatching(v1, v4);\n        }\n\n        public static void CheckMatching(V2l v1, V2l v2)\n        {\n            if (v1 != v2) throw new Exception(\"mismatch\");\n        }\n\n        public static void CheckMatching(V2l v1, V2l v2, V2l v3)\n        {\n            CheckMatching(v1, v2); CheckMatching(v1, v3);\n        }\n\n        public static void CheckMatching(V2l v1, V2l v2, V2l v3, V2l v4)\n        {\n            CheckMatching(v1, v2); CheckMatching(v1, v3); CheckMatching(v1, v4);\n        }\n\n        public static void CheckMatching(V3l v1, V3l v2)\n        {\n            if (v1 != v2) throw new Exception(\"mismatch\");\n        }\n\n        public static void CheckMatching(V3l v1, V3l v2, V3l v3)\n        {\n            CheckMatching(v1, v2); CheckMatching(v1, v3);\n        }\n\n        public static void CheckMatching(V3l v1, V3l v2, V3l v3, V3l v4)\n        {\n            CheckMatching(v1, v2); CheckMatching(v1, v3); CheckMatching(v1, v4);\n        }\n\n        public static long[] DenseDelta(long[] length, out long total)\n        {\n            int rank = (int)length.Length;\n            var delta = new long[rank];\n            total = 1;\n            for (int r = 0; r < rank; r++)\n            {\n                delta[r] = total;\n                total *= length[r];\n            }\n            return delta;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Utilities/Polygon2dExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base\n{\n    public static class TensorPolygon2dExtensions\n    {\n        #region Rasterization\n\n        /// <summary>\n        /// Rasterizes an array of polygons into a matrix of given size.\n        /// First polygon is rasterized with label 1, second polygon with label 2, and so on.\n        /// </summary>\n        /// <param name=\"polygons\">Polygons to rasterize.</param>\n        /// <param name=\"resolution\">Resolution of result matrix.</param>\n        /// <param name=\"bb\"></param>\n        public static Matrix<int> RasterizeAsLabels(this IEnumerable<Polygon2d> polygons, V2i resolution, Box2d bb)\n        {\n            var matrix = new Matrix<int>(resolution);\n            var scale = (V2d)resolution / bb.Size;\n            int i = 1;\n            foreach (var poly in polygons)\n            {\n                RasterizePolygon(poly.ToPolygon2d(p => (p - bb.Min) * scale), matrix, i++);\n            }\n            return matrix;\n        }\n\n        /// <summary>\n        /// Rasterizes this polygon into a given matrix using the given value (label).\n        /// </summary>\n        public static void RasterizePolygon(Polygon2d polygon, Matrix<int> intoMatrix, int value)\n        {\n            var lines = polygon.GetEdgeLineArray();\n            for (int y = 0; y < intoMatrix.Size.Y; y++)\n            {\n                var scanLine = new Line2d(new V2d(0, y), new V2d(intoMatrix.Size.X, y));\n                var intersections = new List<int>();\n                foreach (var l in lines)\n                {\n                    if (scanLine.Intersects(l, out V2d p))\n                        intersections.Add((int)(p.X + 0.5));\n                }\n                intersections.Sort();\n\n                if (intersections.Count % 2 == 1) intersections.Add((int)intoMatrix.Size.X);\n                for (int i = 0; i < intersections.Count; i += 2)\n                {\n                    for (int x = intersections[i]; x < intersections[i + 1]; x++)\n                        intoMatrix[x, y] = value;\n                }\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/Utilities/SpectrumExtensions.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Linq;\n\nnamespace Aardvark.Base\n{\n    public static class SpectrumExtensions\n    {\n        public static M33d CreateConversionMatrix()\n        {\n            // for spectral to xyz conversion see: http://www.brucelindbloom.com/index.html?Eqn_Spect_to_XYZ.html\n\n            var specS0Vec = new Vector<double>(SpectralData.SpecS0_380_780_10nm);\n            var specS1Vec = new Vector<double>(SpectralData.SpecS1_380_780_10nm);\n            var specS2Vec = new Vector<double>(SpectralData.SpecS2_380_780_10nm);\n\n            var cieXVec = new Vector<double>(SpectralData.Ciexyz31X_380_780_10nm);\n            var cieYVec = new Vector<double>(SpectralData.Ciexyz31Y_380_780_10nm);\n            var cieZVec = new Vector<double>(SpectralData.Ciexyz31Z_380_780_10nm);\n\n            var specM = new M33d\n            (\n                cieXVec.DotProduct(specS0Vec), cieXVec.DotProduct(specS1Vec), cieXVec.DotProduct(specS2Vec),\n                cieYVec.DotProduct(specS0Vec), cieYVec.DotProduct(specS1Vec), cieYVec.DotProduct(specS2Vec),\n                cieZVec.DotProduct(specS0Vec), cieZVec.DotProduct(specS1Vec), cieZVec.DotProduct(specS2Vec)\n            );\n\n            var cieN = 1.0 / cieYVec.Data.Sum(); // cie response curve integral normalization\n\n            // sun spectral radiance (S0, S1, S2) is expressed in micro-meters => \n            // convert to wavelengthes in nm (unit of color matching functions) -> scale by 1/1000 \n            // the cie response functions are in 10nm steps -> scale by 10\n\n            var specN = 1.0 / 1000 * 10;         // spectrum unit converions (1 micro meter to 10 nano meter)\n\n            var norm = cieN * specN;             // normalization of color space conversion matrix\n\n            return specM * norm;\n        }\n\n        /// <summary>\n        /// conversion matrix from sun color spectrum in (S0, S1, S2) to CIE XYZ color space\n        /// </summary>\n        public static readonly M33d SecM = CreateConversionMatrix();\n\n    }\n}\n"
  },
  {
    "path": "src/Aardvark.Base.Tensors.CSharp/paket.references",
    "content": "Aardvark.Build"
  },
  {
    "path": "src/Aardvark.Geometry/Aardvark.Geometry.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <TargetFramework>netstandard2.0</TargetFramework>\r\n    <AssemblyName>Aardvark.Geometry</AssemblyName>\r\n    <OutputType>Library</OutputType>\r\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\r\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\r\n    <WarnOn>3389;3390;3395</WarnOn>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug\\</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"PolyRegion2d.fs\" />\r\n    <Compile Include=\"Region3d.fs\" />\r\n    <Compile Include=\"LinearRegression.fs\" />\r\n    <Compile Include=\"EllipsoidRegression.fs\" />\r\n    <Compile Include=\"Bvh.fs\" />\r\n    <Compile Include=\"TexturePacking.fs\" />\r\n    <None Include=\"paket.references\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\">\r\n      <Name>Aardvark.Base.FSharp</Name>\r\n      <Project>{692a3617-719b-4ea2-abc1-407ae20094ae}</Project>\r\n      <Private>True</Private>\r\n    </ProjectReference>\r\n    <ProjectReference Include=\"..\\Aardvark.Base.Tensors.CSharp\\Aardvark.Base.Tensors.CSharp.csproj\" />\r\n    <ProjectReference Include=\"..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <PackageReference Update=\"Unofficial.LibTessDotNet\" Version=\"2.0.2\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Aardvark.Geometry/Bvh.fs",
    "content": "﻿namespace Aardvark.Geometry\n\nopen Aardvark.Base\nopen Aardvark.Base.Sorting\nopen FSharp.Data.Adaptive\n\ntype internal BvhNode3d<'K, 'V> =\n    | Leaf of overflowCount : int * bounds : Box3d * values : HashMap<'K, struct(Box3d * 'V)>\n    | Node of bestCost : float * count : int * bounds : Box3d * left : BvhNode3d<'K, 'V> * right : BvhNode3d<'K, 'V>\n\nmodule internal BvhNode3d =\n\n    module HashMap =\n        let partition (predicate : 'K -> 'V -> bool) (map : HashMap<'K, 'V>) =\n            HashMap.ApplyDelta(map, map, fun k _ v ->\n                if predicate k v then struct(ValueSome v, ValueNone)\n                else struct(ValueNone, ValueSome v)\n            )\n\n    [<GeneralizableValue>]\n    let empty<'K, 'V> : option<BvhNode3d<'K, 'V>> = None\n\n    let inline getBounds (n : BvhNode3d<'K, 'V>) =\n        match n with\n        | Leaf(_,b,_)\n        | Node(_,_,b,_,_) -> b \n        \n    let inline count (n : BvhNode3d<'K, 'V>) =\n        match n with\n        | Leaf(_,_,v) -> v.Count\n        | Node(_,c,_,_,_) -> c\n\n    let cost (invVolume : float) (lBox : Box3d) (lCnt : int) (rBox : Box3d) (rCnt : int) =\n        let i = Box.Intersection(lBox, rBox)\n        let iVol = if i.IsValid then i.Volume * invVolume else 0.0\n        let lVol = lBox.Volume * invVolume\n        let rVol = rBox.Volume * invVolume\n        let cnt = lCnt + rCnt\n        let l = float lCnt / float cnt\n        let r = float rCnt / float cnt\n        (1.0 / float cnt + (l * lVol) + (r * rVol) + iVol) / 2.0\n\n    let split (invVolume : float) (elements : HashMap<'K, struct(Box3d * 'V)>) =\n        if elements.Count <= 1 then\n            None\n        else\n            let arr = elements.ToArrayV()\n            let bounds = arr |> Array.map (fun struct(k, struct(b,v)) -> b)\n\n            let mutable bestCost = System.Double.PositiveInfinity\n            let mutable bestPerm = null\n            let mutable bestSplit = -1\n            let mutable bestlBox = Unchecked.defaultof<Box3d>\n            let mutable bestrBox = Unchecked.defaultof<Box3d>\n\n\n            for dim in 0 .. 2 do\n                let getter = \n                    match dim with\n                    | 0 -> fun (v : V3d) -> v.X\n                    | 1 -> fun (v : V3d) -> v.Y\n                    | _ -> fun (v : V3d) -> v.Z\n                let mutable lBoxes = Array.zeroCreate elements.Count\n                let mutable rBoxes = Array.zeroCreate elements.Count\n\n                let perm = bounds.CreatePermutationQuickSortAscending(fun (b : Box3d) -> getter b.Center)\n\n                let mutable last = bounds.[perm.[0]]\n                lBoxes.[0] <- last\n                for i in 1 .. perm.Length - 1 do\n                    let b = bounds.[perm.[i]].Union(last)\n                    lBoxes.[i] <- b //Box3d.Union(last, b)\n                    last <- b\n\n                let mutable i = perm.Length-1\n                let mutable last = Box3d.Invalid\n                while i >= 0 do\n                    let b = bounds.[perm.[i]].Union(last)\n                    rBoxes.[i] <- b\n                    last <- b\n                    i <- i - 1\n\n\n                for lCnt in 1 .. perm.Length - 1 do\n                    let rCnt = perm.Length - lCnt\n                    let lBox = lBoxes.[lCnt-1]\n                    let rBox = rBoxes.[lCnt]\n\n                    let c = cost invVolume lBox lCnt rBox rCnt\n                    if c < bestCost then\n                        bestCost <- c\n                        bestPerm <- perm\n                        bestSplit <- lCnt\n                        bestlBox <- lBox\n                        bestrBox <- rBox\n\n            if bestCost < 1.0 then\n                let lCnt = bestSplit\n                let rCnt = arr.Length - lCnt\n\n                let left = Array.zeroCreate lCnt\n                let right = Array.zeroCreate rCnt\n\n                let mutable i = 0\n                for li in 0 .. lCnt - 1 do\n                    left.[li] <- arr.[bestPerm.[i]]\n                    i <- i + 1\n                \n                for ri in 0 .. rCnt - 1 do\n                    right.[ri] <- arr.[bestPerm.[i]]\n                    i <- i + 1\n\n                Some (bestCost, bestlBox, HashMap.ofArrayV left, bestrBox, HashMap.ofArrayV right)\n            else    \n                None\n\n    let rec build (limit : int) (bounds : Box3d) (elements : HashMap<'K, struct(Box3d * 'V)>) =\n        if elements.Count <= 0 then\n            failwith \"empty\"\n\n        elif elements.Count <= limit then\n            Leaf(0, bounds, elements)\n\n        else   \n            let bv = 1.0 / bounds.Volume\n            match split bv elements with\n            | Some (cost, lBox, lElements, rBox, rElements) ->\n                let l = build limit lBox lElements\n                let r = build limit rBox rElements\n                Node(cost, elements.Count, bounds, l, r)\n            | None ->\n                //Log.warn \"bad split %d\" elements.Count\n                Leaf(elements.Count, bounds, elements)\n\n    let rec getIntersecting (query : Box3d) (node : BvhNode3d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            if bounds.Intersects query then\n                values |> HashMap.filter (fun _ struct(b,_) -> b.Intersects query)\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            if bounds.Intersects query then\n                let l = getIntersecting query l\n                let r = getIntersecting query r\n                HashMap.union l r\n            else\n                HashMap.empty\n                \n    let rec getIntersectingFilter (query : Box3d) (filter : OptimizedClosures.FSharpFunc<'K, Box3d, 'V, bool>) (node : BvhNode3d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            if bounds.Intersects query then\n                values |> HashMap.filter (fun k struct(b,v) -> b.Intersects query && filter.Invoke(k, b, v))\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            if bounds.Intersects query then\n                let l = getIntersectingFilter query filter l\n                let r = getIntersectingFilter query filter r\n                HashMap.union l r\n            else\n                HashMap.empty\n\n    let rec toSeq (n : BvhNode3d<'K, 'V>) =\n        match n with\n        | Leaf(_,_,vs) -> vs.ToSeqV()\n        | Node(_,_,_,l,r) -> Seq.append (toSeq l) (toSeq r)\n\n    let rec add (limit : int) (key : 'K) (bounds : Box3d) (value : 'V) (node : BvhNode3d<'K, 'V>) =\n        match node with\n        | Leaf(overflowCount, b, values) ->\n            match HashMap.tryFindV key values with\n            | ValueSome (struct(ob, _ov)) ->\n                // replace\n                if bounds.Contains ob then  \n                    Leaf(overflowCount, b, HashMap.add key (struct(bounds, value)) values)\n                else\n                    let mutable bb = bounds\n                    for struct(_,struct(b,_)) in values.ToSeqV() do\n                        bb.ExtendBy b\n                    Leaf(overflowCount, bb, HashMap.add key (struct(bounds, value)) values)\n            | _ -> \n                // add\n                let b = b.ExtendedBy bounds\n                let vs = HashMap.add key (struct(bounds, value)) values\n\n                if vs.Count >= 2 * overflowCount && vs.Count > limit then \n                    build limit b vs\n                else \n                    Leaf(overflowCount, b, vs)\n\n        | Node(bestCost, _, b, l, r) ->\n            let nb = Box.Union(b, bounds)\n\n            let lb = getBounds l\n            let rb = getBounds r\n            let lc = count l\n            let rc = count r\n            let invVol = 1.0 / nb.Volume\n            let lCost = cost invVol (Box.Union(lb, bounds)) (1 + lc) rb rc\n            let rCost = cost invVol lb lc (Box.Union(rb, bounds)) (1 + rc)\n\n            if lCost < rCost then\n                // add left\n                if lCost > 2.0 * bestCost then\n                    toSeq node \n                    |> HashMap.ofSeqV \n                    |> HashMap.add key (struct(bounds, value))\n                    |> build limit nb\n                else\n                    let l = add limit key bounds value l\n                    let lb = getBounds l\n                    let lc = count l\n                    let cc = cost invVol lb lc rb rc\n                    let nb = Box.Union(lb, rb)\n                    Node(min bestCost cc, lc + rc, nb, l, r)\n            else\n                if rCost > 2.0 * bestCost then  \n                    toSeq node \n                    |> HashMap.ofSeqV \n                    |> HashMap.add key (struct(bounds, value))\n                    |> build limit nb\n                else\n                    let r = add limit key bounds value r\n                    let rb = getBounds r\n                    let rc = count r\n                    let cc = cost invVol lb lc rb rc\n                    let nb = Box.Union(lb, rb)\n                    Node(min bestCost cc, lc + rc, nb, l, r)\n            \n    let rec tryRemove (limit : int) (key : 'K) (bounds : Box3d) (node : BvhNode3d<'K, 'V>) =\n        match node with\n        | Leaf(overflowCount, b, values) ->\n            if b.Intersects bounds then\n                match HashMap.tryRemove key values with\n                | Some (struct(_,v), n) -> \n                    if n.Count > 0 then\n                        let mutable bb = Box3d.Invalid\n                        for struct(_,struct(b,_)) in n.ToSeqV() do\n                            bb.ExtendBy b\n                        Some(v, Some (Leaf(max 0 (overflowCount - 1), bb, n)))\n                    else\n                        Some (v, None)\n                | None ->\n                    None\n            else\n                None\n\n        | Node(bestCost, _, b, l, r) ->\n            if b.Intersects bounds then\n                match tryRemove limit key bounds l with\n                | Some (v, l) ->\n                    match l with\n                    | Some l -> \n                        let lc = count l\n                        let rc = count r\n                        let lb = getBounds l\n                        let rb = getBounds r\n                        let o = Box.Union(lb, rb)\n                        let cnt = lc + rc\n                        if cnt <= limit then\n                            let values = Seq.append (toSeq l) (toSeq r) |> HashMap.ofSeqV\n                            Some (v, Some (Leaf(0, o, values)))\n                        else\n                            let cost = cost (1.0 / o.Volume) lb lc rb rc\n                            Some (v, Some (Node(min cost bestCost, cnt, o, l, r)))\n                    | None ->\n                        Some (v, Some r)\n                | None ->\n                    match tryRemove limit key bounds r with\n                    | Some(v,r) ->\n                        match r with\n                        | Some r -> \n                            let lc = count l\n                            let rc = count r\n                            let lb = getBounds l\n                            let rb = getBounds r\n                            let o = Box.Union(lb, rb)\n                            let cnt = lc + rc\n                            if cnt <= limit then\n                                let values = Seq.append (toSeq l) (toSeq r) |> HashMap.ofSeqV\n                                Some (v, Some (Leaf(0, o, values)))\n                            else\n                                let cost = cost (1.0 / o.Volume) lb lc rb rc\n                                Some (v, Some (Node(min cost bestCost, cnt, o, l, r)))\n                        | None ->\n                            Some (v, Some l)\n                    | None ->\n                        None\n            else\n                None\n           \n    let remove (limit : int) (key : 'K) (bounds : Box3d) (node : BvhNode3d<'K, 'V>) =\n        match tryRemove limit key bounds node with\n        | Some (_, rest) -> rest\n        | None -> Some node\n\ntype BvhTree3d<'K, 'V> private(limit : int, root : option<BvhNode3d<'K, 'V>>, keyBounds : HashMap<'K, Box3d>) =\n    member internal x.Root = root\n\n    member x.Count =\n        match root with\n        | Some r -> BvhNode3d.count r\n        | None -> 0\n\n    member x.Add(key : 'K, bounds : Box3d, value : 'V) =\n        if bounds.IsValid then\n            let keyBounds = HashMap.add key bounds keyBounds\n            let newRoot = \n                match root with\n                | Some r -> BvhNode3d.add limit key bounds value r\n                | None -> BvhNode3d.Leaf(0, bounds, HashMap.single key (struct(bounds, value)))\n            BvhTree3d(limit, Some newRoot, keyBounds)\n        else    \n            x\n        \n    member x.Remove(key : 'K) =\n        match HashMap.tryRemove key keyBounds with\n        | Some (bounds, keyBounds) ->\n            let newRoot = \n                match root with\n                | Some r -> BvhNode3d.remove limit key bounds r\n                | None -> None\n            BvhTree3d(limit, newRoot, keyBounds)\n        | None ->\n            x\n\n    member x.TryRemove(key : 'K) =\n        match HashMap.tryRemove key keyBounds with\n        | Some (bounds, keyBounds) ->\n            let newRoot = \n                match root with\n                | Some r -> BvhNode3d.tryRemove limit key bounds r\n                | None -> None\n            match newRoot with\n            | Some (v, newRoot) ->\n                Some (v, BvhTree3d(limit, newRoot, keyBounds))\n            | None ->\n                None\n        | None ->\n            None\n         \n    member x.GetIntersecting(query : Box3d) =\n        match root with\n        | Some r ->\n            BvhNode3d.getIntersecting query r\n        | None ->\n            HashMap.empty\n            \n    member x.GetIntersecting(query : Box3d, filter : 'K -> Box3d -> 'V -> bool) =\n        match root with\n        | Some r ->\n            let opt = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt filter\n            BvhNode3d.getIntersectingFilter query opt r\n        | None ->\n            HashMap.empty\n\n    member x.ToSeq() =\n        match root with\n        | Some root -> BvhNode3d.toSeq root |> Seq.map (fun struct(k,struct(b,v)) -> k,b,v)\n        | None -> Seq.empty\n        \n    member x.ToList() = \n        x.ToSeq() |> Seq.toList\n\n    member x.ToArray() =\n        match root with\n        | Some root ->\n            let arr = Array.zeroCreate x.Count\n            let mutable i = 0\n            for struct(k,struct(b,v)) in BvhNode3d.toSeq root do\n                arr.[i] <- (k,b,v)\n            arr\n        | None ->\n            [||]\n\n    static member Build(limit : int, elements : seq<'K * Box3d * 'V>) =\n        let mutable bb = Box3d.Invalid\n        let mutable all = HashMap.empty\n        let mutable keyBounds = HashMap.empty\n        for (k, b, v) in elements do\n            bb.ExtendBy b\n            all <- HashMap.add k (struct(b, v)) all\n            keyBounds <- HashMap.add k b keyBounds\n\n        if all.Count > 0 then\n            let root = BvhNode3d.build limit bb all\n            BvhTree3d(limit, Some root, keyBounds)\n        else\n            BvhTree3d(limit, None, HashMap.empty)\n\n    static member Empty(limit : int) = BvhTree3d<'K, 'V>(limit, None, HashMap.empty)\n\nmodule BvhTree3d =\n\n    let splitLimit = 24\n\n    [<GeneralizableValue>]\n    let empty<'K, 'V> : BvhTree3d<'K, 'V> = BvhTree3d.Empty(splitLimit)\n\n    let inline add (key : 'K) (bounds : Box3d) (value : 'V) (t : BvhTree3d<'K, 'V>) = t.Add(key, bounds, value)\n    let inline remove (key : 'K) (t : BvhTree3d<'K, 'V>) = t.Remove(key)\n    let inline tryRemove (key : 'K) (t : BvhTree3d<'K, 'V>) = t.TryRemove(key)\n\n    let inline getIntersecting (query : Box3d) (tree : BvhTree3d<'K, 'V>) = tree.GetIntersecting query\n\n    let inline ofSeq (elements : seq<'K * Box3d * 'V>)= BvhTree3d.Build(splitLimit, elements)\n    let inline ofList (elements : list<'K * Box3d * 'V>)= BvhTree3d.Build(splitLimit, elements)\n    let inline ofArray (elements : array<'K * Box3d * 'V>)= BvhTree3d.Build(splitLimit, elements)\n    \n    let inline toSeq (tree : BvhTree3d<'K, 'V>)= tree.ToSeq()\n    let inline toList (tree : BvhTree3d<'K, 'V>)= tree.ToList()\n    let inline toArray (tree : BvhTree3d<'K, 'V>)= tree.ToArray()\n\n    let union (l : BvhTree3d<'K, 'V>) (r : BvhTree3d<'K, 'V>) =\n        let mutable l = l\n        for (k,b,v) in toSeq r do\n            l <- l.Add(k,b,v)\n        l\n\n\ntype internal BvhNode2d<'K, 'V> =\n    | Leaf of overflowCount : int * bounds : Box2d * values : HashMap<'K, struct(Box2d * 'V)>\n    | Node of bestCost : float * count : int * bounds : Box2d * left : BvhNode2d<'K, 'V> * right : BvhNode2d<'K, 'V>\n\nmodule internal BvhNode2d =\n\n    module HashMap =\n        let partition (predicate : 'K -> 'V -> bool) (map : HashMap<'K, 'V>) =\n            HashMap.ApplyDelta(map, map, fun k _ v ->\n                if predicate k v then struct(ValueSome v, ValueNone)\n                else struct(ValueNone, ValueSome v)\n            )\n\n    [<GeneralizableValue>]\n    let empty<'K, 'V> : option<BvhNode2d<'K, 'V>> = None\n\n    let inline getBounds (n : BvhNode2d<'K, 'V>) =\n        match n with\n        | Leaf(_,b,_)\n        | Node(_,_,b,_,_) -> b \n        \n    let inline count (n : BvhNode2d<'K, 'V>) =\n        match n with\n        | Leaf(_,_,v) -> v.Count\n        | Node(_,c,_,_,_) -> c\n\n    let cost (invArea : float) (lBox : Box2d) (lCnt : int) (rBox : Box2d) (rCnt : int) =\n        let i = Box.Intersection(lBox, rBox)\n        let iVol = if i.IsValid then i.Area * invArea else 0.0\n        let lVol = lBox.Area * invArea\n        let rVol = rBox.Area * invArea\n        let cnt = lCnt + rCnt\n        let l = float lCnt / float cnt\n        let r = float rCnt / float cnt\n        (1.0 / float cnt + (l * lVol) + (r * rVol) + iVol) / 2.0\n\n    let split (invArea : float) (elements : HashMap<'K, struct(Box2d * 'V)>) =\n        if elements.Count <= 1 then\n            None\n        else\n            let arr = elements.ToArrayV()\n            let bounds = arr |> Array.map (fun struct(k, struct(b,v)) -> b)\n\n            let mutable bestCost = System.Double.PositiveInfinity\n            let mutable bestPerm = null\n            let mutable bestSplit = -1\n            let mutable bestlBox = Unchecked.defaultof<Box2d>\n            let mutable bestrBox = Unchecked.defaultof<Box2d>\n\n\n            for dim in 0 .. 1 do\n                let getter = \n                    match dim with\n                    | 0 -> fun (v : V2d) -> v.X\n                    | _ -> fun (v : V2d) -> v.Y\n                let mutable lBoxes = Array.zeroCreate elements.Count\n                let mutable rBoxes = Array.zeroCreate elements.Count\n\n                let perm = bounds.CreatePermutationQuickSortAscending(fun (b : Box2d) -> getter b.Center)\n\n                let mutable last = bounds.[perm.[0]]\n                lBoxes.[0] <- last\n                for i in 1 .. perm.Length - 1 do\n                    let b = bounds.[perm.[i]].Union(last)\n                    lBoxes.[i] <- b //Box3d.Union(last, b)\n                    last <- b\n\n                let mutable i = perm.Length-1\n                let mutable last = Box2d.Invalid\n                while i >= 0 do\n                    let b = bounds.[perm.[i]].Union(last)\n                    rBoxes.[i] <- b\n                    last <- b\n                    i <- i - 1\n\n\n                for lCnt in 1 .. perm.Length - 1 do\n                    let rCnt = perm.Length - lCnt\n                    let lBox = lBoxes.[lCnt-1]\n                    let rBox = rBoxes.[lCnt]\n\n                    let c = cost invArea lBox lCnt rBox rCnt\n                    if c < bestCost then\n                        bestCost <- c\n                        bestPerm <- perm\n                        bestSplit <- lCnt\n                        bestlBox <- lBox\n                        bestrBox <- rBox\n\n            if bestCost < 1.0 then\n                let lCnt = bestSplit\n                let rCnt = arr.Length - lCnt\n\n                let left = Array.zeroCreate lCnt\n                let right = Array.zeroCreate rCnt\n\n                let mutable i = 0\n                for li in 0 .. lCnt - 1 do\n                    left.[li] <- arr.[bestPerm.[i]]\n                    i <- i + 1\n                \n                for ri in 0 .. rCnt - 1 do\n                    right.[ri] <- arr.[bestPerm.[i]]\n                    i <- i + 1\n\n                Some (bestCost, bestlBox, HashMap.ofArrayV left, bestrBox, HashMap.ofArrayV right)\n            else    \n                None\n\n    let rec build (limit : int) (bounds : Box2d) (elements : HashMap<'K, struct(Box2d * 'V)>) =\n        if elements.Count <= 0 then\n            failwith \"empty\"\n\n        elif elements.Count <= limit then\n            Leaf(0, bounds, elements)\n\n        else   \n            let bv = 1.0 / bounds.Area\n            match split bv elements with\n            | Some (cost, lBox, lElements, rBox, rElements) ->\n                let l = build limit lBox lElements\n                let r = build limit rBox rElements\n                Node(cost, elements.Count, bounds, l, r)\n            | None ->\n                //Log.warn \"bad split %d\" elements.Count\n                Leaf(elements.Count, bounds, elements)\n\n\n    let rec getContaining (query : Box2d) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            if bounds.Contains(query) then\n                values |> HashMap.filter (fun _ struct(b,_) -> b.Contains query)\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            if bounds.Contains(query) then\n                let l = getContaining query l\n                let r = getContaining query r\n                HashMap.union l r\n            else\n                HashMap.empty\n\n    let rec all (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(_,_,v) -> v\n        | Node(_,_,_,l,r) -> HashMap.union (all l) (all r)\n\n    let rec getContained (query : Box2d) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            if query.Contains bounds then\n                values\n\n            elif query.Intersects bounds then\n                values |> HashMap.filter (fun _ struct(b,_) -> query.Contains b)\n\n            else\n                HashMap.empty\n\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            if query.Contains bounds then\n                all node\n            elif query.Intersects bounds then\n                HashMap.union (getContained query l) (getContained query r)\n            else\n                HashMap.empty\n        \n\n    let rec getIntersecting (tests : ref<int>) (query : Box2d) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            tests := !tests + 1\n            if bounds.Intersects(query, 1E-20) then\n                tests := !tests + values.Count\n                values |> HashMap.filter (fun _ struct(b,_) -> b.Intersects query)\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            tests := !tests + 1\n            if bounds.Intersects(query, 1E-20) then\n                let l = getIntersecting tests query l\n                let r = getIntersecting tests query r\n                HashMap.union l r\n            else\n                HashMap.empty\n        \n    let rec getIntersectingFilter (query : Box2d) (filter : OptimizedClosures.FSharpFunc<'K, Box2d, 'V, option<'T>>) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(_, bounds, values) ->\n            if bounds.Intersects(query, 1E-20) then\n                values |> HashMap.choose (fun k struct(b,v) -> if b.Intersects query then filter.Invoke(k, b, v) else None)\n            else\n                HashMap.empty\n        | Node(_bestCost, _cnt, bounds, l, r) ->\n            if bounds.Intersects(query, 1E-20) then\n                let l = getIntersectingFilter query filter l\n                let r = getIntersectingFilter query filter r\n                HashMap.union l r\n            else\n                HashMap.empty\n\n    let rec toSeq (n : BvhNode2d<'K, 'V>) =\n        match n with\n        | Leaf(_,_,vs) -> vs.ToSeqV()\n        | Node(_,_,_,l,r) -> Seq.append (toSeq l) (toSeq r)\n\n    let rec add (limit : int) (key : 'K) (bounds : Box2d) (value : 'V) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(overflowCount, b, values) ->\n            match HashMap.tryFindV key values with\n            | ValueSome (struct(ob, _ov)) ->\n                // replace\n                if bounds.Contains ob then  \n                    Leaf(overflowCount, b, HashMap.add key (struct(bounds, value)) values)\n                else\n                    let mutable bb = bounds\n                    for struct(_,struct(b,_)) in values.ToSeqV() do\n                        bb.ExtendBy b\n                    Leaf(overflowCount, bb, HashMap.add key (struct(bounds, value)) values)\n            | _ -> \n                // add\n                let b = b.ExtendedBy bounds\n                let vs = HashMap.add key (struct(bounds, value)) values\n\n                if vs.Count >= 2 * overflowCount && vs.Count > limit then \n                    build limit b vs\n                else \n                    Leaf(overflowCount, b, vs)\n\n        | Node(bestCost, _, b, l, r) ->\n            let nb = Box.Union(b, bounds)\n\n            let lb = getBounds l\n            let rb = getBounds r\n            let lc = count l\n            let rc = count r\n            let invVol = 1.0 / nb.Area\n            let lCost = cost invVol (Box.Union(lb, bounds)) (1 + lc) rb rc\n            let rCost = cost invVol lb lc (Box.Union(rb, bounds)) (1 + rc)\n\n            if lCost < rCost then\n                // add left\n                if lCost > 2.0 * bestCost then\n                    toSeq node \n                    |> HashMap.ofSeqV \n                    |> HashMap.add key (struct(bounds, value))\n                    |> build limit nb\n                else\n                    let l = add limit key bounds value l\n                    let lb = getBounds l\n                    let lc = count l\n                    let cc = cost invVol lb lc rb rc\n                    let nb = Box.Union(lb, rb)\n                    Node(min bestCost cc, lc + rc, nb, l, r)\n            else\n                if rCost > 2.0 * bestCost then  \n                    toSeq node \n                    |> HashMap.ofSeqV \n                    |> HashMap.add key (struct(bounds, value))\n                    |> build limit nb\n                else\n                    let r = add limit key bounds value r\n                    let rb = getBounds r\n                    let rc = count r\n                    let cc = cost invVol lb lc rb rc\n                    let nb = Box.Union(lb, rb)\n                    Node(min bestCost cc, lc + rc, nb, l, r)\n            \n    let rec tryRemove (limit : int) (key : 'K) (bounds : Box2d) (node : BvhNode2d<'K, 'V>) =\n        match node with\n        | Leaf(overflowCount, b, values) ->\n            if b.Intersects bounds then\n                match HashMap.tryRemove key values with\n                | Some (struct(_,v), n) -> \n                    if n.Count > 0 then\n                        let mutable bb = Box2d.Invalid\n                        for struct(_,struct(b,_)) in n.ToSeqV() do\n                            bb.ExtendBy b\n                        Some(v, Some (Leaf(max 0 (overflowCount - 1), bb, n)))\n                    else\n                        Some (v, None)\n                | None ->\n                    None\n            else\n                None\n\n        | Node(bestCost, _, b, l, r) ->\n            if b.Intersects bounds then\n                match tryRemove limit key bounds l with\n                | Some (v, l) ->\n                    match l with\n                    | Some l -> \n                        let lc = count l\n                        let rc = count r\n                        let lb = getBounds l\n                        let rb = getBounds r\n                        let o = Box.Union(lb, rb)\n                        let cnt = lc + rc\n                        if cnt <= limit then\n                            let values = Seq.append (toSeq l) (toSeq r) |> HashMap.ofSeqV\n                            Some (v, Some (Leaf(0, o, values)))\n                        else\n                            let cost = cost (1.0 / o.Area) lb lc rb rc\n                            Some (v, Some (Node(min cost bestCost, cnt, o, l, r)))\n                    | None ->\n                        Some (v, Some r)\n                | None ->\n                    match tryRemove limit key bounds r with\n                    | Some(v,r) ->\n                        match r with\n                        | Some r -> \n                            let lc = count l\n                            let rc = count r\n                            let lb = getBounds l\n                            let rb = getBounds r\n                            let o = Box.Union(lb, rb)\n                            let cnt = lc + rc\n                            if cnt <= limit then\n                                let values = Seq.append (toSeq l) (toSeq r) |> HashMap.ofSeqV\n                                Some (v, Some (Leaf(0, o, values)))\n                            else\n                                let cost = cost (1.0 / o.Area) lb lc rb rc\n                                Some (v, Some (Node(min cost bestCost, cnt, o, l, r)))\n                        | None ->\n                            Some (v, Some l)\n                    | None ->\n                        None\n            else\n                None\n           \n    let remove (limit : int) (key : 'K) (bounds : Box2d) (node : BvhNode2d<'K, 'V>) =\n        match tryRemove limit key bounds node with\n        | Some (_, rest) -> rest\n        | None -> Some node\n\ntype BvhTree2d<'K, 'V> private(limit : int, root : option<BvhNode2d<'K, 'V>>, keyBounds : HashMap<'K, Box2d>) =\n    member internal x.Root = root\n\n    member x.Count =\n        match root with\n        | Some r -> BvhNode2d.count r\n        | None -> 0\n\n    member x.Add(key : 'K, bounds : Box2d, value : 'V) =\n        if bounds.IsValid then\n            let keyBounds = HashMap.add key bounds keyBounds\n            let newRoot = \n                match root with\n                | Some r -> BvhNode2d.add limit key bounds value r\n                | None -> BvhNode2d.Leaf(0, bounds, HashMap.single key (struct(bounds, value)))\n            BvhTree2d(limit, Some newRoot, keyBounds)\n        else    \n            x\n        \n    member x.Remove(key : 'K) =\n        match HashMap.tryRemove key keyBounds with\n        | Some (bounds, keyBounds) ->\n            let newRoot = \n                match root with\n                | Some r -> BvhNode2d.remove limit key bounds r\n                | None -> None\n            BvhTree2d(limit, newRoot, keyBounds)\n        | None ->\n            x\n\n    member x.TryRemove(key : 'K) =\n        match HashMap.tryRemove key keyBounds with\n        | Some (bounds, keyBounds) ->\n            let newRoot = \n                match root with\n                | Some r -> BvhNode2d.tryRemove limit key bounds r\n                | None -> None\n            match newRoot with\n            | Some (v, newRoot) ->\n                Some (v, BvhTree2d(limit, newRoot, keyBounds))\n            | None ->\n                None\n        | None ->\n            None\n         \n    member x.GetIntersecting(query : Box2d) =\n        match root with\n        | Some r ->\n            BvhNode2d.getIntersecting (ref 0) query r\n        | None ->\n            HashMap.empty\n\n    member x.GetContaining(query : Box2d) =\n        match root with\n        | Some r ->\n            BvhNode2d.getContaining query r\n        | None ->\n            HashMap.empty\n            \n    member x.GetContained(query : Box2d) =\n        match root with\n        | Some r ->\n            BvhNode2d.getContained query r\n        | None ->\n            HashMap.empty\n            \n    member x.GetIntersecting(query : Box2d, filter : 'K -> Box2d -> 'V -> option<'T>) =\n        match root with\n        | Some r ->\n            let opt = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt filter\n            BvhNode2d.getIntersectingFilter query opt r\n        | None ->\n            HashMap.empty\n\n    member x.ToSeq() =\n        match root with\n        | Some root -> BvhNode2d.toSeq root |> Seq.map (fun struct(k,struct(b,v)) -> k,b,v)\n        | None -> Seq.empty\n\n    member x.Keys() =\n        match root with\n        | Some root -> BvhNode2d.toSeq root |> Seq.map (fun struct(k,_) -> k)\n        | None -> Seq.empty\n        \n    member x.ToList() = \n        x.ToSeq() |> Seq.toList\n\n    member x.ToArray() =\n        match root with\n        | Some root ->\n            let arr = Array.zeroCreate x.Count\n            let mutable i = 0\n            for struct(k,struct(b,v)) in BvhNode2d.toSeq root do\n                arr.[i] <- (k,b,v)\n            arr\n        | None ->\n            [||]\n\n    static member Build(limit : int, elements : seq<'K * Box2d * 'V>) =\n        let mutable bb = Box2d.Invalid\n        let mutable all = HashMap.empty\n        let mutable keyBounds = HashMap.empty\n        for (k, b, v) in elements do\n            bb.ExtendBy b\n            all <- HashMap.add k (struct(b, v)) all\n            keyBounds <- HashMap.add k b keyBounds\n\n        if all.Count > 0 then\n            let root = BvhNode2d.build limit bb all\n            BvhTree2d(limit, Some root, keyBounds)\n        else\n            BvhTree2d(limit, None, HashMap.empty)\n\n    static member Empty(limit : int) = BvhTree2d<'K, 'V>(limit, None, HashMap.empty)\n\nmodule BvhTree2d =\n\n    let splitLimit = 24\n\n    [<GeneralizableValue>]\n    let empty<'K, 'V> : BvhTree2d<'K, 'V> = BvhTree2d.Empty(splitLimit)\n\n    let inline add (key : 'K) (bounds : Box2d) (value : 'V) (t : BvhTree2d<'K, 'V>) = t.Add(key, bounds, value)\n    let inline remove (key : 'K) (t : BvhTree2d<'K, 'V>) = t.Remove(key)\n    let inline tryRemove (key : 'K) (t : BvhTree2d<'K, 'V>) = t.TryRemove(key)\n\n    let inline getIntersecting (query : Box2d) (tree : BvhTree2d<'K, 'V>) = tree.GetIntersecting query\n    let inline getContained (query : Box2d) (tree : BvhTree2d<'K, 'V>) = tree.GetContained query\n    let inline getContaining (query : Box2d) (tree : BvhTree2d<'K, 'V>) = tree.GetContaining query\n\n    let inline ofSeq (elements : seq<'K * Box2d * 'V>)= BvhTree2d.Build(splitLimit, elements)\n    let inline ofList (elements : list<'K * Box2d * 'V>)= BvhTree2d.Build(splitLimit, elements)\n    let inline ofArray (elements : array<'K * Box2d * 'V>)= BvhTree2d.Build(splitLimit, elements)\n    \n    let inline keys (tree : BvhTree2d<'K, 'V>)= tree.Keys()\n    let inline toSeq (tree : BvhTree2d<'K, 'V>)= tree.ToSeq()\n    let inline toList (tree : BvhTree2d<'K, 'V>)= tree.ToList()\n    let inline toArray (tree : BvhTree2d<'K, 'V>)= tree.ToArray()\n\n    let union (l : BvhTree2d<'K, 'V>) (r : BvhTree2d<'K, 'V>) =\n        let mutable l = l\n        for (k,b,v) in toSeq r do\n            l <- l.Add(k,b,v)\n        l\n\n"
  },
  {
    "path": "src/Aardvark.Geometry/EllipsoidRegression.fs",
    "content": "﻿namespace Aardvark.Geometry\n\nopen System\nopen Microsoft.FSharp.NativeInterop\nopen Aardvark.Base\nopen System.Runtime.CompilerServices\n\n#nowarn \"9\"\n#nowarn \"51\"\n\n[<AutoOpen>]\nmodule private rec D9Math =\n    [<Struct>]\n    type V9d = \n        val mutable public C0 : float\n        val mutable public C1 : float\n        val mutable public C2 : float\n        val mutable public C3 : float\n        val mutable public C4 : float\n        val mutable public C5 : float\n        val mutable public C6 : float\n        val mutable public C7 : float\n        val mutable public C8 : float\n\n        member x.MultiplyAdd(v : V9d, f : float) =\n            x.C0 <- x.C0 + v.C0 * f\n            x.C1 <- x.C1 + v.C1 * f\n            x.C2 <- x.C2 + v.C2 * f\n            x.C3 <- x.C3 + v.C3 * f\n            x.C4 <- x.C4 + v.C4 * f\n            x.C5 <- x.C5 + v.C5 * f\n            x.C6 <- x.C6 + v.C6 * f\n            x.C7 <- x.C7 + v.C7 * f\n            x.C8 <- x.C8 + v.C8 * f\n\n        member internal x.ReadUnsafe(i : int) : float =\n            NativePtr.get (NativePtr.cast &&x) i \n            \n        member internal x.WriteUnsafe(i : int, v : float)  =\n            NativePtr.set (NativePtr.cast &&x) i v\n            \n\n        member x.SetZero() =\n            x.C0 <- 0.0\n            x.C1 <- 0.0\n            x.C2 <- 0.0\n            x.C3 <- 0.0\n            x.C4 <- 0.0\n            x.C5 <- 0.0\n            x.C6 <- 0.0\n            x.C7 <- 0.0\n            x.C8 <- 0.0\n\n        member x.ToVector() = Vector([| x.C0; x.C1; x.C2; x.C3; x.C4; x.C5; x.C6; x.C7; x.C8 |], 9L)\n\n        new(c0 : float, c1 : float, c2 : float, c3 : float, c4 : float, c5 : float, c6 : float, c7 : float, c8 : float) = { C0 = c0; C1 = c1; C2 = c2; C3 = c3; C4 = c4; C5 = c5; C6 = c6; C7 = c7; C8 = c8 }\n\n    [<Struct>]\n    type SymmetricM99d = \n        val mutable public M00 : float\n        val mutable public M01 : float\n        val mutable public M02 : float\n        val mutable public M03 : float\n        val mutable public M04 : float\n        val mutable public M05 : float\n        val mutable public M06 : float\n        val mutable public M07 : float\n        val mutable public M08 : float\n        val mutable public M11 : float\n        val mutable public M12 : float\n        val mutable public M13 : float\n        val mutable public M14 : float\n        val mutable public M15 : float\n        val mutable public M16 : float\n        val mutable public M17 : float\n        val mutable public M18 : float\n        val mutable public M22 : float\n        val mutable public M23 : float\n        val mutable public M24 : float\n        val mutable public M25 : float\n        val mutable public M26 : float\n        val mutable public M27 : float\n        val mutable public M28 : float\n        val mutable public M33 : float\n        val mutable public M34 : float\n        val mutable public M35 : float\n        val mutable public M36 : float\n        val mutable public M37 : float\n        val mutable public M38 : float\n        val mutable public M44 : float\n        val mutable public M45 : float\n        val mutable public M46 : float\n        val mutable public M47 : float\n        val mutable public M48 : float\n        val mutable public M55 : float\n        val mutable public M56 : float\n        val mutable public M57 : float\n        val mutable public M58 : float\n        val mutable public M66 : float\n        val mutable public M67 : float\n        val mutable public M68 : float\n        val mutable public M77 : float\n        val mutable public M78 : float\n        val mutable public M88 : float\n        member inline x.M10 = x.M01\n        member inline x.M20 = x.M02\n        member inline x.M21 = x.M12\n        member inline x.M30 = x.M03\n        member inline x.M31 = x.M13\n        member inline x.M32 = x.M23\n        member inline x.M40 = x.M04\n        member inline x.M41 = x.M14\n        member inline x.M42 = x.M24\n        member inline x.M43 = x.M34\n        member inline x.M50 = x.M05\n        member inline x.M51 = x.M15\n        member inline x.M52 = x.M25\n        member inline x.M53 = x.M35\n        member inline x.M54 = x.M45\n        member inline x.M60 = x.M06\n        member inline x.M61 = x.M16\n        member inline x.M62 = x.M26\n        member inline x.M63 = x.M36\n        member inline x.M64 = x.M46\n        member inline x.M65 = x.M56\n        member inline x.M70 = x.M07\n        member inline x.M71 = x.M17\n        member inline x.M72 = x.M27\n        member inline x.M73 = x.M37\n        member inline x.M74 = x.M47\n        member inline x.M75 = x.M57\n        member inline x.M76 = x.M67\n        member inline x.M80 = x.M08\n        member inline x.M81 = x.M18\n        member inline x.M82 = x.M28\n        member inline x.M83 = x.M38\n        member inline x.M84 = x.M48\n        member inline x.M85 = x.M58\n        member inline x.M86 = x.M68\n        member inline x.M87 = x.M78\n        static member Zero = SymmetricM99d(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)\n        \n        member x.AddOuterProduct(v : V9d) =\n            x.M00 <- x.M00 + v.C0*v.C0\n            x.M01 <- x.M01 + v.C0*v.C1\n            x.M02 <- x.M02 + v.C0*v.C2\n            x.M03 <- x.M03 + v.C0*v.C3\n            x.M04 <- x.M04 + v.C0*v.C4\n            x.M05 <- x.M05 + v.C0*v.C5\n            x.M06 <- x.M06 + v.C0*v.C6\n            x.M07 <- x.M07 + v.C0*v.C7\n            x.M08 <- x.M08 + v.C0*v.C8\n            x.M11 <- x.M11 + v.C1*v.C1\n            x.M12 <- x.M12 + v.C1*v.C2\n            x.M13 <- x.M13 + v.C1*v.C3\n            x.M14 <- x.M14 + v.C1*v.C4\n            x.M15 <- x.M15 + v.C1*v.C5\n            x.M16 <- x.M16 + v.C1*v.C6\n            x.M17 <- x.M17 + v.C1*v.C7\n            x.M18 <- x.M18 + v.C1*v.C8\n            x.M22 <- x.M22 + v.C2*v.C2\n            x.M23 <- x.M23 + v.C2*v.C3\n            x.M24 <- x.M24 + v.C2*v.C4\n            x.M25 <- x.M25 + v.C2*v.C5\n            x.M26 <- x.M26 + v.C2*v.C6\n            x.M27 <- x.M27 + v.C2*v.C7\n            x.M28 <- x.M28 + v.C2*v.C8\n            x.M33 <- x.M33 + v.C3*v.C3\n            x.M34 <- x.M34 + v.C3*v.C4\n            x.M35 <- x.M35 + v.C3*v.C5\n            x.M36 <- x.M36 + v.C3*v.C6\n            x.M37 <- x.M37 + v.C3*v.C7\n            x.M38 <- x.M38 + v.C3*v.C8\n            x.M44 <- x.M44 + v.C4*v.C4\n            x.M45 <- x.M45 + v.C4*v.C5\n            x.M46 <- x.M46 + v.C4*v.C6\n            x.M47 <- x.M47 + v.C4*v.C7\n            x.M48 <- x.M48 + v.C4*v.C8\n            x.M55 <- x.M55 + v.C5*v.C5\n            x.M56 <- x.M56 + v.C5*v.C6\n            x.M57 <- x.M57 + v.C5*v.C7\n            x.M58 <- x.M58 + v.C5*v.C8\n            x.M66 <- x.M66 + v.C6*v.C6\n            x.M67 <- x.M67 + v.C6*v.C7\n            x.M68 <- x.M68 + v.C6*v.C8\n            x.M77 <- x.M77 + v.C7*v.C7\n            x.M78 <- x.M78 + v.C7*v.C8\n            x.M88 <- x.M88 + v.C8*v.C8\n        \n        member x.SubOuterProduct(v : V9d) =\n            x.M00 <- x.M00 - v.C0*v.C0\n            x.M01 <- x.M01 - v.C0*v.C1\n            x.M02 <- x.M02 - v.C0*v.C2\n            x.M03 <- x.M03 - v.C0*v.C3\n            x.M04 <- x.M04 - v.C0*v.C4\n            x.M05 <- x.M05 - v.C0*v.C5\n            x.M06 <- x.M06 - v.C0*v.C6\n            x.M07 <- x.M07 - v.C0*v.C7\n            x.M08 <- x.M08 - v.C0*v.C8\n            x.M11 <- x.M11 - v.C1*v.C1\n            x.M12 <- x.M12 - v.C1*v.C2\n            x.M13 <- x.M13 - v.C1*v.C3\n            x.M14 <- x.M14 - v.C1*v.C4\n            x.M15 <- x.M15 - v.C1*v.C5\n            x.M16 <- x.M16 - v.C1*v.C6\n            x.M17 <- x.M17 - v.C1*v.C7\n            x.M18 <- x.M18 - v.C1*v.C8\n            x.M22 <- x.M22 - v.C2*v.C2\n            x.M23 <- x.M23 - v.C2*v.C3\n            x.M24 <- x.M24 - v.C2*v.C4\n            x.M25 <- x.M25 - v.C2*v.C5\n            x.M26 <- x.M26 - v.C2*v.C6\n            x.M27 <- x.M27 - v.C2*v.C7\n            x.M28 <- x.M28 - v.C2*v.C8\n            x.M33 <- x.M33 - v.C3*v.C3\n            x.M34 <- x.M34 - v.C3*v.C4\n            x.M35 <- x.M35 - v.C3*v.C5\n            x.M36 <- x.M36 - v.C3*v.C6\n            x.M37 <- x.M37 - v.C3*v.C7\n            x.M38 <- x.M38 - v.C3*v.C8\n            x.M44 <- x.M44 - v.C4*v.C4\n            x.M45 <- x.M45 - v.C4*v.C5\n            x.M46 <- x.M46 - v.C4*v.C6\n            x.M47 <- x.M47 - v.C4*v.C7\n            x.M48 <- x.M48 - v.C4*v.C8\n            x.M55 <- x.M55 - v.C5*v.C5\n            x.M56 <- x.M56 - v.C5*v.C6\n            x.M57 <- x.M57 - v.C5*v.C7\n            x.M58 <- x.M58 - v.C5*v.C8\n            x.M66 <- x.M66 - v.C6*v.C6\n            x.M67 <- x.M67 - v.C6*v.C7\n            x.M68 <- x.M68 - v.C6*v.C8\n            x.M77 <- x.M77 - v.C7*v.C7\n            x.M78 <- x.M78 - v.C7*v.C8\n            x.M88 <- x.M88 - v.C8*v.C8\n        \n        static member FromMatrix(m : Matrix<float>) =\n            if m.SX < 9L || m.SY < 9L then raise <| IndexOutOfRangeException()\n            SymmetricM99d(m.[0,0], m.[0,1], m.[0,2], m.[0,3], m.[0,4], m.[0,5], m.[0,6], m.[0,7], m.[0,8], m.[1,1], m.[1,2], m.[1,3], m.[1,4], m.[1,5], m.[1,6], m.[1,7], m.[1,8], m.[2,2], m.[2,3], m.[2,4], m.[2,5], m.[2,6], m.[2,7], m.[2,8], m.[3,3], m.[3,4], m.[3,5], m.[3,6], m.[3,7], m.[3,8], m.[4,4], m.[4,5], m.[4,6], m.[4,7], m.[4,8], m.[5,5], m.[5,6], m.[5,7], m.[5,8], m.[6,6], m.[6,7], m.[6,8], m.[7,7], m.[7,8], m.[8,8])\n\n        [<MethodImpl(MethodImplOptions.NoInlining)>]\n        member x.LuSolve(rhs : V9d) =\n\n            let ptr = NativePtr.stackalloc<V9d> 9\n            NativePtr.set ptr 0 (V9d(x.M00, x.M01, x.M02, x.M03, x.M04, x.M05, x.M06, x.M07, x.M08))\n            NativePtr.set ptr 1 (V9d(x.M10, x.M11, x.M12, x.M13, x.M14, x.M15, x.M16, x.M17, x.M18))\n            NativePtr.set ptr 2 (V9d(x.M20, x.M21, x.M22, x.M23, x.M24, x.M25, x.M26, x.M27, x.M28))\n            NativePtr.set ptr 3 (V9d(x.M30, x.M31, x.M32, x.M33, x.M34, x.M35, x.M36, x.M37, x.M38))\n            NativePtr.set ptr 4 (V9d(x.M40, x.M41, x.M42, x.M43, x.M44, x.M45, x.M46, x.M47, x.M48))\n            NativePtr.set ptr 5 (V9d(x.M50, x.M51, x.M52, x.M53, x.M54, x.M55, x.M56, x.M57, x.M58))\n            NativePtr.set ptr 6 (V9d(x.M60, x.M61, x.M62, x.M63, x.M64, x.M65, x.M66, x.M67, x.M68))\n            NativePtr.set ptr 7 (V9d(x.M70, x.M71, x.M72, x.M73, x.M74, x.M75, x.M76, x.M77, x.M78))\n            NativePtr.set ptr 8 (V9d(x.M80, x.M81, x.M82, x.M83, x.M84, x.M85, x.M86, x.M87, x.M88))\n            let pFloat : nativeptr<float> = NativePtr.cast ptr\n\n            let mutable rhs = rhs\n            \n            let inline get (r : int) (c : int) =\n                NativePtr.get pFloat (r * 9 + c)\n\n            let inline set (r : int) (c : int) (v : float) =\n                NativePtr.set pFloat (r * 9 + c) v\n                \n            let inline swapRows (ri : int) (rj : int) =\n                if ri <> rj then\n                    for c in 0 .. 8 do\n                        let t = get ri c\n                        set ri c (get rj c)\n                        set rj c t\n\n                    let t = rhs.ReadUnsafe ri\n                    rhs.WriteUnsafe(ri, rhs.ReadUnsafe rj)\n                    rhs.WriteUnsafe(rj, t)\n\n\n            let mutable i = 0\n            while i < 9 do\n                // pivoting\n                let vii = \n                    let mutable j = i\n                    let mutable vmax = get i i\n                    let mutable vmaxAbs = abs vmax\n                    for ii in i+1 .. 8 do\n                        let vii = get ii i\n                        let viiAbs = abs vii\n                        if viiAbs > vmaxAbs then\n                            j <- ii\n                            vmax <- vii\n                            vmaxAbs <- viiAbs\n\n                    swapRows i j\n                    vmax\n\n                // elimination\n                if Fun.IsTiny vii then\n                    // singular matrix\n                    i <- Int32.MaxValue\n                else\n                    for j in i + 1 .. 8 do\n                        let vji = get j i\n                        let f = -vji / vii\n\n                        rhs.WriteUnsafe(j, rhs.ReadUnsafe j + rhs.ReadUnsafe i * f)\n\n                        set j i 5.0\n                        for c in i + 1 .. 8 do\n                            set j c (get j c + get i c * f) \n                    i <- i + 1\n\n            if i > 9 then   \n                V9d()\n            else\n                // back substitution\n                let mutable res = V9d()\n                for ri in 0 .. 8 do\n                    let ri = 8 - ri\n\n                    let mutable s = rhs.ReadUnsafe(ri)\n                    for c in ri + 1 .. 8 do\n                        s <- s - get ri c * res.ReadUnsafe(c)\n\n                    res.WriteUnsafe(ri, s / get ri ri)\n\n                res\n\n\n        member x.ToMatrix() =\n            let arr = Array.zeroCreate 81\n            arr.[0] <- x.M00\n            arr.[1] <- x.M01\n            arr.[2] <- x.M02\n            arr.[3] <- x.M03\n            arr.[4] <- x.M04\n            arr.[5] <- x.M05\n            arr.[6] <- x.M06\n            arr.[7] <- x.M07\n            arr.[8] <- x.M08\n            arr.[9] <- x.M01\n            arr.[10] <- x.M11\n            arr.[11] <- x.M12\n            arr.[12] <- x.M13\n            arr.[13] <- x.M14\n            arr.[14] <- x.M15\n            arr.[15] <- x.M16\n            arr.[16] <- x.M17\n            arr.[17] <- x.M18\n            arr.[18] <- x.M02\n            arr.[19] <- x.M12\n            arr.[20] <- x.M22\n            arr.[21] <- x.M23\n            arr.[22] <- x.M24\n            arr.[23] <- x.M25\n            arr.[24] <- x.M26\n            arr.[25] <- x.M27\n            arr.[26] <- x.M28\n            arr.[27] <- x.M03\n            arr.[28] <- x.M13\n            arr.[29] <- x.M23\n            arr.[30] <- x.M33\n            arr.[31] <- x.M34\n            arr.[32] <- x.M35\n            arr.[33] <- x.M36\n            arr.[34] <- x.M37\n            arr.[35] <- x.M38\n            arr.[36] <- x.M04\n            arr.[37] <- x.M14\n            arr.[38] <- x.M24\n            arr.[39] <- x.M34\n            arr.[40] <- x.M44\n            arr.[41] <- x.M45\n            arr.[42] <- x.M46\n            arr.[43] <- x.M47\n            arr.[44] <- x.M48\n            arr.[45] <- x.M05\n            arr.[46] <- x.M15\n            arr.[47] <- x.M25\n            arr.[48] <- x.M35\n            arr.[49] <- x.M45\n            arr.[50] <- x.M55\n            arr.[51] <- x.M56\n            arr.[52] <- x.M57\n            arr.[53] <- x.M58\n            arr.[54] <- x.M06\n            arr.[55] <- x.M16\n            arr.[56] <- x.M26\n            arr.[57] <- x.M36\n            arr.[58] <- x.M46\n            arr.[59] <- x.M56\n            arr.[60] <- x.M66\n            arr.[61] <- x.M67\n            arr.[62] <- x.M68\n            arr.[63] <- x.M07\n            arr.[64] <- x.M17\n            arr.[65] <- x.M27\n            arr.[66] <- x.M37\n            arr.[67] <- x.M47\n            arr.[68] <- x.M57\n            arr.[69] <- x.M67\n            arr.[70] <- x.M77\n            arr.[71] <- x.M78\n            arr.[72] <- x.M08\n            arr.[73] <- x.M18\n            arr.[74] <- x.M28\n            arr.[75] <- x.M38\n            arr.[76] <- x.M48\n            arr.[77] <- x.M58\n            arr.[78] <- x.M68\n            arr.[79] <- x.M78\n            arr.[80] <- x.M88\n            Matrix(arr, V2l(9L, 9L))\n\n        member x.SetZero() =\n            x.M00 <- 0.0\n            x.M01 <- 0.0\n            x.M02 <- 0.0\n            x.M03 <- 0.0\n            x.M04 <- 0.0\n            x.M05 <- 0.0\n            x.M06 <- 0.0\n            x.M07 <- 0.0\n            x.M08 <- 0.0\n            x.M11 <- 0.0\n            x.M12 <- 0.0\n            x.M13 <- 0.0\n            x.M14 <- 0.0\n            x.M15 <- 0.0\n            x.M16 <- 0.0\n            x.M17 <- 0.0\n            x.M18 <- 0.0\n            x.M22 <- 0.0\n            x.M23 <- 0.0\n            x.M24 <- 0.0\n            x.M25 <- 0.0\n            x.M26 <- 0.0\n            x.M27 <- 0.0\n            x.M28 <- 0.0\n            x.M33 <- 0.0\n            x.M34 <- 0.0\n            x.M35 <- 0.0\n            x.M36 <- 0.0\n            x.M37 <- 0.0\n            x.M38 <- 0.0\n            x.M44 <- 0.0\n            x.M45 <- 0.0\n            x.M46 <- 0.0\n            x.M47 <- 0.0\n            x.M48 <- 0.0\n            x.M55 <- 0.0\n            x.M56 <- 0.0\n            x.M57 <- 0.0\n            x.M58 <- 0.0\n            x.M66 <- 0.0\n            x.M67 <- 0.0\n            x.M68 <- 0.0\n            x.M77 <- 0.0\n            x.M78 <- 0.0\n            x.M88 <- 0.0\n\n        new(m00 : float, m01 : float, m02 : float, m03 : float, m04 : float, m05 : float, m06 : float, m07 : float, m08 : float, m11 : float, m12 : float, m13 : float, m14 : float, m15 : float, m16 : float, m17 : float, m18 : float, m22 : float, m23 : float, m24 : float, m25 : float, m26 : float, m27 : float, m28 : float, m33 : float, m34 : float, m35 : float, m36 : float, m37 : float, m38 : float, m44 : float, m45 : float, m46 : float, m47 : float, m48 : float, m55 : float, m56 : float, m57 : float, m58 : float, m66 : float, m67 : float, m68 : float, m77 : float, m78 : float, m88 : float) = { M00 = m00; M01 = m01; M02 = m02; M03 = m03; M04 = m04; M05 = m05; M06 = m06; M07 = m07; M08 = m08; M11 = m11; M12 = m12; M13 = m13; M14 = m14; M15 = m15; M16 = m16; M17 = m17; M18 = m18; M22 = m22; M23 = m23; M24 = m24; M25 = m25; M26 = m26; M27 = m27; M28 = m28; M33 = m33; M34 = m34; M35 = m35; M36 = m36; M37 = m37; M38 = m38; M44 = m44; M45 = m45; M46 = m46; M47 = m47; M48 = m48; M55 = m55; M56 = m56; M57 = m57; M58 = m58; M66 = m66; M67 = m67; M68 = m68; M77 = m77; M78 = m78; M88 = m88 }\n\n    let luSolveInPlace (lhs : NativeMatrix<float>) (rhs : NativeVector<float>) (res : NativeVector<float>) =\n        if lhs.SY <> rhs.Size || lhs.SX <> rhs.Size || res.Size <> rhs.Size then raise <| IndexOutOfRangeException()\n\n        let n1 = int lhs.SY - 1\n\n        let inline get (r : int) (c : int) =\n            lhs.[r,c]\n\n        let inline set (r : int) (c : int) (v : float) =\n            lhs.[r,c] <- v\n                \n        let inline swapRows (ri : int) (rj : int) =\n            if ri <> rj then\n                for c in 0 .. n1 do\n                    let t = get ri c\n                    set ri c (get rj c)\n                    set rj c t\n\n                let t = rhs.[ri]\n                rhs.[ri] <- rhs.[rj]\n                rhs.[rj] <- t\n\n        let mutable i = 0\n        while i < n1 do\n            // pivoting\n            let vii = \n                let mutable j = i\n                let mutable vmax = get i i\n                let mutable vmaxAbs = abs vmax\n                for ii in i+1 .. n1 do\n                    let vii = get ii i\n                    let viiAbs = abs vii\n                    if viiAbs > vmaxAbs then\n                        j <- ii\n                        vmax <- vii\n                        vmaxAbs <- viiAbs\n\n                swapRows i j\n                vmax\n\n            // elimination\n            if Fun.IsTiny vii then\n                // singular matrix\n                i <- Int32.MaxValue\n            else\n                for j in i + 1 .. n1 do\n                    let vji = get j i\n                    let f = -vji / vii\n\n                    rhs.[j] <- rhs.[j] + rhs.[i] * f\n\n                    set j i 0.0\n                    for c in i + 1 .. n1 do\n                        set j c (get j c + get i c * f) \n                i <- i + 1\n\n        if i > n1 then   \n            false\n        else\n            // back substitution\n            for ri in 0 .. n1 do\n                let ri = n1 - ri\n\n                let mutable s = rhs.[ri]\n                for c in ri + 1 .. n1 do\n                    s <- s - get ri c * res.[c]\n\n                res.[ri] <- s / get ri ri\n            true\n\n    type M44d with\n        member x.LuSolveNew(rhs : V4d) =\n            let plhs = NativePtr.stackalloc 1\n            NativePtr.write plhs x\n\n            let prhs = NativePtr.stackalloc 1\n            NativePtr.write prhs rhs\n\n            let pres : nativeptr<V4d> = NativePtr.stackalloc 1\n\n            let tlhs = NativeMatrix(NativePtr.cast plhs, MatrixInfo(V2l(4,4)))\n            let trhs = NativeVector(NativePtr.cast prhs, VectorInfo(4))\n            let tres = NativeVector(NativePtr.cast pres, VectorInfo(4))\n\n            if luSolveInPlace tlhs trhs tres then\n                NativePtr.read pres\n            else\n                V4d.Zero\n\n    type M33d with\n        member x.LuSolveNew(rhs : V3d) =\n            let plhs = NativePtr.stackalloc 1\n            NativePtr.write plhs x\n\n            let prhs = NativePtr.stackalloc 1\n            NativePtr.write prhs rhs\n\n            let pres : nativeptr<V3d> = NativePtr.stackalloc 1\n\n            let tlhs = NativeMatrix(NativePtr.cast plhs, MatrixInfo(V2l(3,3)))\n            let trhs = NativeVector(NativePtr.cast prhs, VectorInfo(3))\n            let tres = NativeVector(NativePtr.cast pres, VectorInfo(3))\n\n            if luSolveInPlace tlhs trhs tres then\n                NativePtr.read pres\n            else\n                V3d.Zero\n\n[<Struct>]\ntype Ellipsoid3d (euclidean : Euclidean3d, radii : V3d) =\n    member x.Euclidean = euclidean\n    member x.Radii = radii\n    member x.Center = euclidean.Trans\n\n    member x.BoundingBox3d =\n        // TODO: tighter BB possible?\n        let m : M44d = Euclidean3d.op_Explicit euclidean\n        Box3d(-radii, radii).Transformed m\n\n    member x.Contains(pt : V3d) =\n        Vec.length (euclidean.InvTransformPos pt / radii) <= 1.0\n\n    member x.GetClosestPointAndNormal(pt0 : V3d) =\n        let pt = euclidean.InvTransformPos pt0\n\n        let a = radii.X\n        let b = radii.Y\n        let c = radii.Z\n\n        let inline ff (t : V2d) =\n            let sp = sin t.Y\n            let cp = cos t.Y\n            let st = sin t.X\n            let ct = cos t.X\n            let a2 = sqr a\n            let b2 = sqr b\n            let st2 = sqr st\n            let ct2 = sqr ct\n            let ab2 = a2 - b2\n\n            struct (\n                V2d(\n                    ab2*ct*st*cp - pt.X*a*st + pt.Y*b*ct,\n                    (a2 * ct2 + b2 * st2 - sqr c)*sp*cp - pt.X*a*sp*ct - pt.Y*b*st*sp + pt.Z*c*cp\n                ),\n                M22d(\n                    ab2*(ct2 - st2)*cp - pt.X*a*ct - pt.Y*b*st, \n                    -ab2*ct*st*sp,\n                    -2.0*ab2*ct*st*sp*cp + pt.X*a*st*sp - pt.Y*b*sp*ct, \n                    (a2*ct2 + b2*st2 - sqr c)*(sqr cp-sqr sp) - pt.X*a*cp*ct - pt.Y*b*cp*st - pt.Z*c*sp\n                )\n            )\n\n        let theta0       = atan2 (a * pt.Y) (b * pt.X)\n        let phi0         = atan2 pt.Z (c * sqrt (sqr (pt.X / a) + sqr (pt.Y / b)))\n        let mutable ti = V2d(theta0, phi0)\n        let mutable tl = V2d(123123.10, 123123123.0)\n        let mutable iter = 0\n        while not (Fun.ApproximateEquals(ti, tl, 1E-6)) && iter < 20 do\n            let struct(v, dv) = ff ti\n\n            let dvi =\n                let f = 1.0 / dv.Determinant\n                M22d(\n                     dv.M11 * f,   -dv.M01 * f,\n                    -dv.M10 * f,    dv.M00 * f\n                )\n\n            tl <- ti\n            ti <- ti - 0.8 * dvi * v\n            iter <- iter + 1\n    \n        let sp = sin ti.Y\n        let cp = cos ti.Y\n        let st = sin ti.X\n        let ct = cos ti.X\n        let closest = \n            V3d(\n                a*cp*ct,\n                b*cp*st,\n                c*sp\n            )\n        let n = closest / sqr radii |> Vec.normalize\n        struct (euclidean.TransformPos closest, euclidean.TransformDir n)\n\n    member x.GetClosestPoint(pt : V3d) =\n        let struct (p, _) = x.GetClosestPointAndNormal pt\n        p\n\n    member x.Distance(pt : V3d) =\n        let struct (p, _) = x.GetClosestPointAndNormal pt\n        Vec.distance p pt\n\n    member x.Height(pt : V3d) =\n        let struct (p, n) = x.GetClosestPointAndNormal pt\n        Vec.dot (pt - p) n\n\n    member x.SphereTrafo =\n        Trafo3d.Scale radii * Trafo3d euclidean\n\n[<Struct>]\ntype EllipsoidRegression3d =\n\n    val mutable private _reference : V3d\n    val mutable private _lhs : SymmetricM99d\n    val mutable private _rhs : V9d\n    val mutable private _count : int\n    \n    private new(reference : V3d, lhs : SymmetricM99d, rhs : V9d, count : int) =\n        { _reference = reference; _lhs = lhs; _rhs = rhs; _count = count}\n\n    new([<ParamArray>] pts : V3d[]) =\n        if pts.Length <= 0 then\n            { _reference = V3d.Zero; _lhs = SymmetricM99d(); _rhs = V9d(); _count = 0 }\n        else\n\n            let reference = pts.[0]\n            let mutable lhs = SymmetricM99d(M88 = 1.0)\n            let mutable rhs = V9d()\n            let mutable count = 1\n            for i in 1 .. pts.Length - 1 do\n                let pt = pts.[i] - reference\n                let px = pt.X\n                let py = pt.Y\n                let pz = pt.Z\n            \n                let a = sqr px + sqr py - 2.0*sqr pz\n                let b = sqr px + sqr pz - 2.0*sqr py\n                let c = 2.0 * px * py\n                let d = 2.0 * px * pz\n                let e = 2.0 * py * pz\n                let f = 2.0 * px\n                let g = 2.0 * py\n                let h = 2.0 * pz\n                let j = 1.0\n                let v = V9d(a, b, c, d, e, f, g, h, j)\n                lhs.AddOuterProduct v\n                rhs.MultiplyAdd(v, sqr px + sqr py + sqr pz)\n                count <- count + 1\n\n            { _reference = reference; _lhs = lhs; _rhs = rhs; _count = count }\n\n    new(pts : seq<V3d>) = EllipsoidRegression3d(Seq.toArray pts)\n    new(pts : list<V3d>) = EllipsoidRegression3d(List.toArray pts)\n\n    static member Empty = \n        EllipsoidRegression3d(V3d.Zero, SymmetricM99d(), V9d(), 0)\n\n    member x.Count = x._count\n\n    member x.Add(pt : V3d) =\n        if x._count <= 0 then\n            EllipsoidRegression3d(pt, D9Math.SymmetricM99d(M88 = 1.0), D9Math.V9d(), 1)\n        else\n            let pt = pt - x._reference\n            let px = pt.X\n            let py = pt.Y\n            let pz = pt.Z\n\n            let a = sqr px + sqr py - 2.0*sqr pz\n            let b = sqr px + sqr pz - 2.0*sqr py\n            let c = 2.0 * px * py\n            let d = 2.0 * px * pz\n            let e = 2.0 * py * pz\n            let f = 2.0 * px\n            let g = 2.0 * py\n            let h = 2.0 * pz\n            let j = 1.0\n\n            let mutable lhs = x._lhs\n            let mutable rhs = x._rhs\n            let v = V9d(a, b, c, d, e, f, g, h, j)\n            lhs.AddOuterProduct v\n            rhs.MultiplyAdd(v, sqr px + sqr py + sqr pz)\n            EllipsoidRegression3d(x._reference, lhs, rhs, x._count + 1)\n       \n    member x.AddInPlace(pt : V3d) =\n        if x._count <= 0 then\n            x._reference <- pt\n            x._lhs.SetZero()\n            x._lhs.M88 <- 1.0\n            x._rhs.SetZero()\n            x._count <- 1\n        else\n            let pt = pt - x._reference\n            let px = pt.X\n            let py = pt.Y\n            let pz = pt.Z\n            \n            let a = sqr px + sqr py - 2.0*sqr pz\n            let b = sqr px + sqr pz - 2.0*sqr py\n            let c = 2.0 * px * py\n            let d = 2.0 * px * pz\n            let e = 2.0 * py * pz\n            let f = 2.0 * px\n            let g = 2.0 * py\n            let h = 2.0 * pz\n            let j = 1.0\n            let v = V9d(a, b, c, d, e, f, g, h, j)\n            x._lhs.AddOuterProduct v\n            x._rhs.MultiplyAdd(v, sqr px + sqr py + sqr pz)\n            x._count <- x._count + 1\n\n    member x.Remove(pt : V3d) =\n        if x._count <= 1 then\n            EllipsoidRegression3d.Empty\n        else\n            let pt = pt - x._reference\n            let px = pt.X\n            let py = pt.Y\n            let pz = pt.Z\n\n            let a = sqr px + sqr py - 2.0*sqr pz\n            let b = sqr px + sqr pz - 2.0*sqr py\n            let c = 2.0 * px * py\n            let d = 2.0 * px * pz\n            let e = 2.0 * py * pz\n            let f = 2.0 * px\n            let g = 2.0 * py\n            let h = 2.0 * pz\n            let j = 1.0\n\n            let mutable lhs = x._lhs\n            let mutable rhs = x._rhs\n            let v = V9d(a, b, c, d, e, f, g, h, j)\n            lhs.SubOuterProduct v\n            rhs.MultiplyAdd(v, -(sqr px + sqr py + sqr pz))\n            EllipsoidRegression3d(x._reference, lhs, rhs, x._count - 1)\n\n    member x.RemoveInPlace(pt : V3d) =\n        if x._count <= 1 then\n            x._lhs.SetZero()\n            x._rhs.SetZero()\n            x._reference <- V3d.Zero\n            x._count <- 0\n        else\n            let pt = pt - x._reference\n            let px = pt.X\n            let py = pt.Y\n            let pz = pt.Z\n            \n            let a = sqr px + sqr py - 2.0*sqr pz\n            let b = sqr px + sqr pz - 2.0*sqr py\n            let c = 2.0 * px * py\n            let d = 2.0 * px * pz\n            let e = 2.0 * py * pz\n            let f = 2.0 * px\n            let g = 2.0 * py\n            let h = 2.0 * pz\n            let j = 1.0\n            let v = V9d(a, b, c, d, e, f, g, h, j)\n            x._lhs.SubOuterProduct v\n            x._rhs.MultiplyAdd(v, -(sqr px + sqr py + sqr pz))\n            x._count <- x._count - 1\n\n    member x.GetEllipsoid() =\n        if x._count < 9 then   \n            Ellipsoid3d(Euclidean3d.Identity, V3d.Zero)\n        else\n            let u = x._lhs.LuSolve x._rhs\n\n            let a = u.C0 + u.C1 - 1.0\n            let b = u.C0 - 2.0*u.C1 - 1.0\n            let c = u.C1 - 2.0*u.C0 - 1.0\n\n            let A = \n                M44d(\n                    a,      u.C2,   u.C3,   u.C5,\n                    u.C2,   b,      u.C4,   u.C6,\n                    u.C3,   u.C4,   c,      u.C7,\n                    u.C5,   u.C6,   u.C7,   u.C8\n                )\n\n\n            let lhs = -A.UpperLeftM33()\n            let rhs = V3d(u.C5, u.C6, u.C7)\n            let center = lhs.LuSolveNew rhs\n\n            let transMat =\n                M44d.FromCols(V4d.IOOO, V4d.OIOO, V4d.OOIO, V4d(center, 1.0))\n\n            let R = transMat.Transposed * A * transMat\n\n            match SVD.Decompose (R.UpperLeftM33() / -R.M33) with\n            | Some(u, s, _vt) ->\n                let evals = s.Diagonal\n                let r = sqrt (1.0 / evals.Abs())\n\n                // make rx >= ry >= rz\n                let r = r.ZYX\n                let u = M33d.FromCols(u.C2, -u.C1, u.C0)\n\n                let trafo = Euclidean3d.FromM33dAndV3d(u, x._reference + center)\n                let scale = r\n                Ellipsoid3d(trafo, scale)\n                //Trafo3d.Scale(r) * Trafo3d.FromOrthoNormalBasis(u.C0, u.C1, u.C2) * Trafo3d.Translation (reference + center)\n            | None ->\n                Ellipsoid3d(Euclidean3d.Identity, V3d.Zero)\n\nmodule EllipsoidRegression3d =\n\n    /// A regression holding no points.\n    let empty = EllipsoidRegression3d.Empty\n\n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    let inline remove (pt : V3d) (s : EllipsoidRegression3d) = s.Remove pt\n\n    /// Adds the given point to the regression.\n    let inline add (pt : V3d) (s : EllipsoidRegression3d) = s.Add pt\n\n    /// Gets the least-squares ellipsoid.\n    let inline getEllipsoid (s : EllipsoidRegression3d) = s.GetEllipsoid()\n\n    /// The total number of points added. Note that at least 9 points are required to fit an ellipsoid.\n    let inline count (s : EllipsoidRegression3d) = s.Count\n    \n    /// Creates a regression from the given points.\n    let ofSeq (points : seq<V3d>) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n        \n    /// Creates a regression from the given points.\n    let ofList (points : list<V3d>) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n        \n    /// Creates a regression from the given points.\n    let ofArray (points : V3d[]) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n\n\n[<AutoOpen>]\nmodule private rec D4Math =\n    [<Struct>]\n    type SymmetricM44d =\n        val mutable public M00 : float\n        val mutable public M01 : float\n        val mutable public M02 : float\n        val mutable public M03 : float\n        val mutable public M11 : float\n        val mutable public M12 : float\n        val mutable public M13 : float\n        val mutable public M22 : float\n        val mutable public M23 : float\n        val mutable public M33 : float\n\n        new(m00, m01, m02, m03, m11, m12, m13, m22, m23, m33) =\n            { M00 = m00; M01 = m01; M02 = m02; M03 = m03; M11 = m11; M12 = m12; M13 = m13; M22 = m22; M23 = m23; M33 = m33 }\n\n        static member Zero = SymmetricM44d(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)\n\n        member x.AddOuterProduct(v : V4d) =\n            x.M00 <- x.M00 + v.X*v.X\n            x.M01 <- x.M01 + v.X*v.Y\n            x.M02 <- x.M02 + v.X*v.Z\n            x.M03 <- x.M03 + v.X*v.W\n            x.M11 <- x.M11 + v.Y*v.Y\n            x.M12 <- x.M12 + v.Y*v.Z\n            x.M13 <- x.M13 + v.Y*v.W\n            x.M22 <- x.M22 + v.Z*v.Z\n            x.M23 <- x.M23 + v.Z*v.W\n            x.M33 <- x.M33 + v.W*v.W\n\n        member x.SubOuterProduct(v : V4d) =\n            x.M00 <- x.M00 - v.X*v.X\n            x.M01 <- x.M01 - v.X*v.Y\n            x.M02 <- x.M02 - v.X*v.Z\n            x.M03 <- x.M03 - v.X*v.W\n            x.M11 <- x.M11 - v.Y*v.Y\n            x.M12 <- x.M12 - v.Y*v.Z\n            x.M13 <- x.M13 - v.Y*v.W\n            x.M22 <- x.M22 - v.Z*v.Z\n            x.M23 <- x.M23 - v.Z*v.W\n            x.M33 <- x.M33 - v.W*v.W\n\n        static member Add(l : SymmetricM44d, r : SymmetricM44d) =\n            SymmetricM44d(\n                l.M00 + r.M00, l.M01 + r.M01, l.M02 + r.M02, l.M03 + r.M03,\n                               l.M11 + r.M11, l.M12 + r.M12, l.M13 + r.M13,\n                                              l.M22 + r.M22, l.M23 + r.M23,\n                                                             l.M33 + r.M33\n            )\n            \n        static member Sub(l : SymmetricM44d, r : SymmetricM44d) =\n            SymmetricM44d(\n                l.M00 - r.M00, l.M01 - r.M01, l.M02 - r.M02, l.M03 - r.M03,\n                               l.M11 - r.M11, l.M12 - r.M12, l.M13 - r.M13,\n                                              l.M22 - r.M22, l.M23 - r.M23,\n                                                             l.M33 - r.M33\n            )\n\n        member x.AddInPlace(o : SymmetricM44d) =\n            x.M00 <- x.M00 + o.M00\n            x.M01 <- x.M01 + o.M01\n            x.M02 <- x.M02 + o.M02\n            x.M03 <- x.M03 + o.M03\n            x.M11 <- x.M11 + o.M11\n            x.M12 <- x.M12 + o.M12\n            x.M13 <- x.M13 + o.M13\n            x.M22 <- x.M22 + o.M22\n            x.M23 <- x.M23 + o.M23\n            x.M33 <- x.M33 + o.M33\n\n        member x.SubInPlace(o : SymmetricM44d) =\n            x.M00 <- x.M00 - o.M00\n            x.M01 <- x.M01 - o.M01\n            x.M02 <- x.M02 - o.M02\n            x.M03 <- x.M03 - o.M03\n            x.M11 <- x.M11 - o.M11\n            x.M12 <- x.M12 - o.M12\n            x.M13 <- x.M13 - o.M13\n            x.M22 <- x.M22 - o.M22\n            x.M23 <- x.M23 - o.M23\n            x.M33 <- x.M33 - o.M33\n\n        member x.Inverse =\n            M44d(\n                x.M00, x.M01, x.M02, x.M03,\n                x.M01, x.M11, x.M12, x.M13,\n                x.M02, x.M12, x.M22, x.M23,\n                x.M03, x.M13, x.M23, x.M33\n            ).Inverse\n\n    [<Struct>]\n    type SymmetricM33d =\n        val mutable public M00 : float\n        val mutable public M01 : float\n        val mutable public M02 : float\n        val mutable public M11 : float\n        val mutable public M12 : float\n        val mutable public M22 : float\n\n        new(m00, m01, m02, m11, m12, m22) =\n            { M00 = m00; M01 = m01; M02 = m02; M11 = m11; M12 = m12;  M22 = m22 }\n\n        static member Zero = SymmetricM33d(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)\n\n        member x.AddOuterProduct(v : V3d) =\n            x.M00 <- x.M00 + v.X*v.X\n            x.M01 <- x.M01 + v.X*v.Y\n            x.M02 <- x.M02 + v.X*v.Z\n            x.M11 <- x.M11 + v.Y*v.Y\n            x.M12 <- x.M12 + v.Y*v.Z\n            x.M22 <- x.M22 + v.Z*v.Z\n\n        member x.SubOuterProduct(v : V3d) =\n            x.M00 <- x.M00 - v.X*v.X\n            x.M01 <- x.M01 - v.X*v.Y\n            x.M02 <- x.M02 - v.X*v.Z\n            x.M11 <- x.M11 - v.Y*v.Y\n            x.M12 <- x.M12 - v.Y*v.Z\n            x.M22 <- x.M22 - v.Z*v.Z\n\n        static member Add(l : SymmetricM33d, r : SymmetricM33d) =\n            SymmetricM33d(\n                l.M00 + r.M00, l.M01 + r.M01, l.M02 + r.M02,\n                               l.M11 + r.M11, l.M12 + r.M12,\n                                              l.M22 + r.M22      \n            )\n            \n        static member Sub(l : SymmetricM33d, r : SymmetricM33d) =\n            SymmetricM33d(\n                l.M00 - r.M00, l.M01 - r.M01, l.M02 - r.M02,\n                               l.M11 - r.M11, l.M12 - r.M12,\n                                              l.M22 - r.M22  \n            )\n\n        member x.AddInPlace(o : SymmetricM33d) =\n            x.M00 <- x.M00 + o.M00\n            x.M01 <- x.M01 + o.M01\n            x.M02 <- x.M02 + o.M02\n            x.M11 <- x.M11 + o.M11\n            x.M12 <- x.M12 + o.M12\n            x.M22 <- x.M22 + o.M22\n\n        member x.SubInPlace(o : SymmetricM33d) =\n            x.M00 <- x.M00 - o.M00\n            x.M01 <- x.M01 - o.M01\n            x.M02 <- x.M02 - o.M02\n            x.M11 <- x.M11 - o.M11\n            x.M12 <- x.M12 - o.M12\n            x.M22 <- x.M22 - o.M22\n\n        member x.Inverse =\n            M33d(\n                x.M00, x.M01, x.M02,\n                x.M01, x.M11, x.M12,\n                x.M02, x.M12, x.M22\n            ).Inverse\n\n\n[<Struct>]\ntype SphereRegression3d =\n\n    val mutable private _reference : V3d\n    val mutable private _lhs : SymmetricM33d\n    val mutable private _sum : V3d\n    val mutable private _rhs : V4d\n    val mutable private _count : int\n    \n    private new(reference : V3d, lhs : SymmetricM33d, sum : V3d, rhs : V4d, count : int) =\n        { _reference = reference; _lhs = lhs; _sum = sum; _rhs = rhs; _count = count}\n        \n    /// Creates a new regression with a single point.\n    new(point : V3d) =\n        { _reference = point; _lhs = SymmetricM33d(); _sum = V3d.Zero; _rhs = V4d.Zero; _count = 1 }\n        \n    /// Creates a new regression from the given points.\n    new([<ParamArray>] pts : V3d[]) =\n        if pts.Length <= 0 then\n            { _reference = V3d.Zero; _lhs = SymmetricM33d.Zero; _sum = V3d.Zero;  _rhs = V4d.Zero; _count = 0 }\n        else\n            let reference = pts.[0]\n            let mutable lhs = SymmetricM33d()\n            let mutable sum = V3d.Zero\n            let mutable rhs = V4d.Zero\n            let mutable count = 1\n            for i in 1 .. pts.Length - 1 do\n                let pt = pts.[i] - reference\n                lhs.AddOuterProduct pt\n                sum <- sum + pt\n                rhs <- rhs - V4d(pt, 1.0) * pt.LengthSquared\n                count <- count + 1\n\n            { _reference = reference; _lhs = lhs; _sum = sum; _rhs = rhs; _count = count }\n\n    /// Creates a new regression from the given points.\n    new(pts : seq<V3d>) =\n        let e = pts.GetEnumerator()\n        if e.MoveNext() then\n            let reference = e.Current\n            let mutable lhs = SymmetricM33d()\n            let mutable sum = V3d.Zero\n            let mutable rhs = V4d.Zero\n            let mutable count = 1\n            while e.MoveNext() do\n                let pt = e.Current - reference\n                lhs.AddOuterProduct pt\n                sum <- sum + pt\n                rhs <- rhs - V4d(pt, 1.0) * pt.LengthSquared\n                count <- count + 1\n\n            e.Dispose()\n            { _reference = reference; _lhs = lhs; _sum = sum; _rhs = rhs; _count = count }\n        else\n            e.Dispose()\n            { _reference = V3d.Zero; _lhs = SymmetricM33d.Zero; _sum = V3d.Zero; _rhs = V4d.Zero; _count = 0 }\n\n    /// Creates a new regression from the given points.\n    new(pts : list<V3d>) = SphereRegression3d(pts :> seq<_>)\n    \n    /// A regression holding no points.\n    static member Empty = \n        SphereRegression3d(V3d.Zero, SymmetricM33d.Zero, V3d.Zero, V4d.Zero, 0)\n        \n    /// A regression holding no points.\n    static member Zero = \n        SphereRegression3d(V3d.Zero, SymmetricM33d.Zero, V3d.Zero, V4d.Zero, 0)\n        \n    /// The total number of points added. Note that at least 4 points are required to fit a sphere.\n    member x.Count = x._count\n    \n    /// The centroid of all added points.\n    member x.Centroid = \n        let n = float x._count\n        x._reference + x._sum / n\n        \n    /// Gets the variances of the added points as [Var(X), Var(Y), Var(Z)]\n    member x.Variance =\n        if x._count < 2 then\n            V3d.Zero\n        else\n            let sum = x._sum\n            let sumSq = V3d(x._lhs.M00, x._lhs.M11, x._lhs.M22)\n            let n = float x._count\n            let avg = sum / n\n            let xx = (sumSq.X - avg.X * sum.X) / (n - 1.0)\n            let yy = (sumSq.Y - avg.Y * sum.Y) / (n - 1.0)\n            let zz = (sumSq.Z - avg.Z * sum.Z) / (n - 1.0)\n            V3d(xx, yy, zz)\n\n    /// Gets the covariances of the added points as [Cov(Y,Z), Cov(X,Z), Cov(X,Y)]\n    member x.Covariance =\n        if x._count < 2 then\n            V3d.Zero\n        else\n            let sum = x._sum\n            let off = V3d(x._lhs.M12, x._lhs.M02, x._lhs.M01)\n            let n = float x._count\n            let avg = sum / n\n            let xy = (off.Z - avg.X * sum.Y) / (n - 1.0)\n            let xz = (off.Y - avg.X * sum.Z) / (n - 1.0)\n            let yz = (off.X - avg.Y * sum.Z) / (n - 1.0)\n            V3d(yz, xz, xy)\n\n    /// Gets the covariance matrix of the added points as\n    /// | Cov(X,X) | Cov(X,Y) | Cov(X,Z) |\n    /// | Cov(X,Y) | Cov(Y,Y) | Cov(Y,Z) |\n    /// | Cov(X,Z) | Cov(Y,Z) | Cov(Z,Z) |\n    member x.CovarianceMatrix =\n        if x._count < 2  then\n            M33d.Zero\n        else\n            let n = float x._count\n            let sum = x._sum\n            let sumSq = V3d(x._lhs.M00, x._lhs.M11, x._lhs.M22)\n            let off = V3d(x._lhs.M12, x._lhs.M02, x._lhs.M01)\n\n            let avg = sum / n\n            let xx = (sumSq.X - avg.X * sum.X) / (n - 1.0)\n            let yy = (sumSq.Y - avg.Y * sum.Y) / (n - 1.0)\n            let zz = (sumSq.Z - avg.Z * sum.Z) / (n - 1.0)\n\n            let xy = (off.Z - avg.X * sum.Y) / (n - 1.0)\n            let xz = (off.Y - avg.X * sum.Z) / (n - 1.0)\n            let yz = (off.X - avg.Y * sum.Z) / (n - 1.0)\n        \n            M33d(\n                xx, xy, xz,\n                xy, yy, yz,\n                xz, yz, zz\n            )\n\n    member private x.WithReferencePoint(r : V3d) =\n        let c = x._reference - r\n        if x._reference + c = x._reference then\n            x\n        else\n            let sum = x._sum\n            let sumSq = V3d(x._lhs.M00, x._lhs.M11, x._lhs.M22)\n            let cov = V3d(x._lhs.M12, x._lhs.M02, x._lhs.M01)\n\n            let c2 = sqr c\n            let lc2 = c2.X + c2.Y + c2.Z\n            let cs = c * sum\n\n            let n = float x._count\n\n            // l00 = sum((x+cx)*(x+cx))\n            // = sum(x^2 + 2*cx*x + cx^2)\n            // = sum(x^2) + 2*cx*sum(x) + n*cx^2\n\n            // l01 = sum((x+cx)*(y+cy)) \n            // = sum(x*y + cx*y + cy*x + cx*cy) \n            // = sum(x*y) + cx*sum(y) + cy*sum(x) + n*cx*cy\n            let dlhs = \n                SymmetricM33d(\n                    2.0*cs.X + n*c2.X,      c.X*sum.Y + c.Y*sum.X + n*c.X*c.Y,      c.X*sum.Z + c.Z*sum.X + n*c.X*c.Z,\n                                            2.0*cs.Y + n*c2.Y,                      c.Y*sum.Z + c.Z*sum.Y + n*c.Y*c.Z,\n                                                                                    2.0*cs.Z + n*c2.Z                    \n                )\n\n            let dsum = n * c\n\n\n            // sum(x*(x^2 + y^2 + z^2))\n            // sum(x^3 + x*y^2 + x*z^2)\n            //rx = sum((x+cx) * ((x+cx)^2 + (y+cy)^2 + (z+cz)^2))\n            //rx = sum((x + cx) * (x^2 + 2*x*cx + cx^2 + y^2 + 2*y*cy + cy^2 + z^2 + 2*z*cz + cz^2)\n            // sum (\n            //     x^3 + 2*x^2*cx + x*cx^2 + x*y^2 + 2*x*y*cy + x*cy^2 + x*z^2 + 2*x*z*cz + x*cz^2 +\n            //     cx*x^2 + 2*x*cx^2 + cx^3 + cx*y^2 + 2*y*cx*cy + cx*cy^2 + cx*z^2 + 2*z*cx*cz + cx*cz^2\n            // )\n\n            // sum (cx^3 + cx*cy^2 + cx*cz^2) +\n            // 3*cx * sum(x^2) + \n            // cx * sum(y^2) +\n            // cx * sum(z^2)\n            // (3*cx^2 + cy^2 + cz^2) * sum(x) +\n            // 2*cy*sum(x*y) +\n            // 2*cz*sum(x*z) +\n            // 2*cx*cy*sum(y) +\n            // 2*cx*cz*sum(z) +\n            // n*(cx^3 + cx*cy^2 + cx*cz^2)\n\n            let drx = \n                3.0*c.X*sumSq.X + c.X*sumSq.Y + c.X*sumSq.Z +\n                (3.0*c2.X + c2.Y + c2.Z)*sum.X +\n                2.0*c.Y*cov.Z + 2.0*c.Z*cov.Y +\n                2.0*c.X*cs.Y +\n                2.0*c.X*cs.Z +\n                n * c.X * lc2\n            \n            let dry = \n                3.0*c.Y*sumSq.Y + c.Y*sumSq.X + c.Y*sumSq.Z +\n                (3.0*c2.Y + c2.X + c2.Z)*sum.Y +\n                2.0*c.X*cov.Z + 2.0*c.Z*cov.X +\n                2.0*c.Y*cs.X +\n                2.0*c.Y*cs.Z +\n                n * c.Y * lc2\n            \n            let drz = \n                3.0*c.Z*sumSq.Z + c.Z*sumSq.Y + c.Z*sumSq.X +\n                (3.0*c2.Z + c2.Y + c2.X)*sum.Z +\n                2.0*c.Y*cov.X + 2.0*c.X*cov.Y +\n                2.0*c.Z*cs.Y +\n                2.0*c.Z*cs.X +\n                n * c.Z * lc2\n\n            let drw =\n                2.0 * (cs.X + cs.Y + cs.Z) +\n                n * lc2\n\n            // sum((x+cx)^2 + (y+cy)^2 + (z+cz)^2)\n            // sum(x^2 + 2*x*cx + cx^2 + y^2 + 2*y*cy + cy^2 + z^2 + 2*z*cz + cz^2)\n            // sum(x^2) + 2*cx*sum(x) + n*cx^2 + sum(y^2) + 2*cy*sum(y) + n*cy^2 + sum(z^2) + 2*cz*sum(z) + n*cz^2\n\n        \n            // n*cx^2 + n*cy^2 + n*cz^2\n\n            // (sum(x^2) + sum(y^2) + sum(z^2)) +\n            // 2*(cx*sum(x) + cy*sum(y) + cz*sum(z) +\n            // n * (cx^2+cy^2+cz^2)\n\n\n            let mutable lhs = x._lhs\n            lhs.AddInPlace(dlhs)\n\n            SphereRegression3d(r, lhs, x._sum + dsum, x._rhs - V4d(drx, dry, drz, drw), x._count)\n        \n    /// Adds the given point to the regression.\n    member x.Add(pt : V3d) =\n        if x._count <= 0 then\n            SphereRegression3d(pt, SymmetricM33d(), V3d.Zero, V4d.Zero, 1)\n        else\n            let pt = pt - x._reference\n            let mutable lhs = x._lhs\n            let mutable rhs = x._rhs\n            lhs.AddOuterProduct pt\n            let sum = x._sum + pt\n            rhs <- rhs - V4d(pt, 1.0) * pt.LengthSquared\n            SphereRegression3d(x._reference, lhs, sum, rhs, x._count + 1)\n   \n    /// Adds the given point to the regression (mutating the regression).\n    member x.AddInPlace(pt : V3d) =\n        if x._count <= 0 then   \n            x._reference <- pt\n            x._lhs <- SymmetricM33d()\n            x._sum <- V3d.Zero\n            x._rhs <- V4d.Zero\n            x._count <- 1\n        else\n            let pt = pt - x._reference\n            x._lhs.AddOuterProduct pt\n            x._sum <- x._sum + pt\n            x._rhs <- x._rhs - V4d(pt, 1.0) * pt.LengthSquared\n            x._count <- x._count + 1\n   \n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    member x.Remove(pt : V3d) =\n        if x._count <= 1 then\n            SphereRegression3d.Empty\n        elif x._count = 2 then\n            // x._sum = (pt - reference) + (other - reference)\n            // x._sum - pt + reference = other - reference\n            // x._sum - pt + 2*reference = other\n            let other = x._sum - pt + 2.0*x._reference\n            SphereRegression3d(other, SymmetricM33d(), V3d.Zero, V4d.Zero, 1)\n        else\n            let pt = pt - x._reference\n            let mutable lhs = x._lhs\n            let mutable rhs = x._rhs\n            lhs.SubOuterProduct pt\n            let sum = x._sum - pt\n            rhs <- rhs + V4d(pt, 1.0) * pt.LengthSquared\n            SphereRegression3d(x._reference, lhs, sum, rhs, x._count - 1)\n            \n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    member x.RemoveInPlace(pt : V3d) =\n        if x._count <= 1 then\n            x._reference <- V3d.Zero\n            x._lhs <- SymmetricM33d.Zero\n            x._sum <- V3d.Zero\n            x._rhs <- V4d.Zero\n            x._count <- 0\n        elif x._count = 2 then\n            // x._sum = (pt - reference) + (other - reference)\n            // x._sum - pt + reference = other - reference\n            // x._sum - pt + 2*reference = other\n            x._reference <- x._sum - pt + 2.0*x._reference\n            x._lhs <- SymmetricM33d.Zero\n            x._sum <- V3d.Zero\n            x._rhs <- V4d.Zero\n            x._count <- 1\n        else\n            let pt = pt - x._reference\n            x._lhs.SubOuterProduct pt\n            x._sum <- x._sum - pt\n            x._rhs <- x._rhs + V4d(pt, 1.0) * pt.LengthSquared\n            x._count <- x._count - 1\n   \n    /// Gets the least-squares sphere.\n    member x.GetSphere() =\n        if x._count < 4 then   \n            Sphere3d(V3d.Zero, 0.0)\n        else\n            let m =\n                M44d(\n                    x._lhs.M00, x._lhs.M01, x._lhs.M02, x._sum.X,\n                    x._lhs.M01, x._lhs.M11, x._lhs.M12, x._sum.Y,\n                    x._lhs.M02, x._lhs.M12, x._lhs.M22, x._sum.Z,\n                    x._sum.X,   x._sum.Y,   x._sum.Z,   float x._count\n                )\n            let u = m.Inverse * x._rhs\n            let center = -u.XYZ / 2.0\n            let r = sqrt (center.LengthSquared - u.W)\n            Sphere3d(x._reference + center, r)\n\n    static member (+) (l : SphereRegression3d, r : SphereRegression3d) =\n        if l._count <= 0 then r\n        elif r._count <= 0 then l\n        elif l._count = 1 then r.Add l._reference\n        elif r._count = 1 then l.Add r._reference\n        else\n            let r = r.WithReferencePoint(l._reference)\n        \n            let mutable lhs = l._lhs\n            lhs.AddInPlace(r._lhs)\n\n            let rhs = l._rhs + r._rhs\n            let count = l._count + r._count\n            let sum = l._sum + r._sum\n\n            SphereRegression3d(l._reference, lhs, sum, rhs, count)\n       \n    static member (-) (l : SphereRegression3d, r : SphereRegression3d) =\n        if l._count <= r._count then SphereRegression3d.Empty\n        elif r._count = 0 then l\n        elif r._count = 1 then l.Remove r._reference\n        else\n            let r = r.WithReferencePoint(l._reference)\n        \n            let mutable lhs = l._lhs\n            lhs.SubInPlace(r._lhs)\n\n            let rhs = l._rhs - r._rhs\n            let count = l._count - r._count\n            let sum = l._sum - r._sum\n\n            SphereRegression3d(l._reference, lhs, sum, rhs, count)\n\n    static member (+) (l : SphereRegression3d, r : V3d) = l.Add r\n    static member (+) (l : V3d, r : SphereRegression3d) = r.Add l\n    static member (-) (l : SphereRegression3d, r : V3d) = l.Remove r\n\nmodule SphereRegression3d =\n\n    /// A regression holding no points.\n    let empty = SphereRegression3d.Empty\n\n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    let inline remove (pt : V3d) (s : SphereRegression3d) = s.Remove pt\n\n    /// Adds the given point to the regression.\n    let inline add (pt : V3d) (s : SphereRegression3d) = s.Add pt\n\n    /// Gets the least-squares sphere.\n    let inline getSphere (s : SphereRegression3d) = s.GetSphere()\n\n    /// The total number of points added. Note that at least 4 points are required to fit a sphere.\n    let inline count (s : SphereRegression3d) = s.Count\n    \n    /// Creates a regression from the given points.\n    let ofSeq (points : seq<V3d>) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n        \n    /// Creates a regression from the given points.\n    let ofList (points : list<V3d>) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n        \n    /// Creates a regression from the given points.\n    let ofArray (points : V3d[]) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n"
  },
  {
    "path": "src/Aardvark.Geometry/LinearRegression.fs",
    "content": "﻿namespace Aardvark.Geometry\n\nopen System\nopen Aardvark.Base\nopen System.Collections.Generic\n\n[<AutoOpen>]\nmodule private RegressionHelpers =\n\n    let inline sortTupleAbs (struct(a,b)) =\n        if abs a < abs b then struct(a, b)\n        else struct(b, a)\n\n    let inline sortTripleAbs (struct(a,b,c)) =\n        let aa = abs a\n        let bb = abs b\n        let cc = abs c\n        if aa < bb then   \n            // a < b\n            if bb < cc then struct(a,b,c)\n            elif aa < cc then struct(a,c,b)\n            else struct(c,a,b)\n        else\n            // b < a\n            if aa < cc then struct(b,a,c)\n            elif bb < cc then struct(b,c,a)\n            else struct(c,b,a)\n\n\n\n[<Struct>]\ntype LinearRegression2d =\n    \n    val mutable private _reference : V2d\n    val mutable private _sum : V2d\n    val mutable private _sumSq : V2d\n    val mutable private _off : float\n    val mutable private _count : int\n    \n    private new(reference : V2d, sum : V2d, sumSq : V2d, off : float, count : int) =\n        { _reference = reference; _sum = sum; _sumSq = sumSq; _off = off; _count = count }\n        \n    /// Creates a new regression with a single point.\n    new(point : V2d) =\n        { _reference = point; _sum = V2d.Zero; _sumSq = V2d.Zero; _off = 0.0; _count = 1 }\n        \n    /// Creates a new regression from the given points.\n    new([<ParamArray>] points : V2d[]) =\n        if points.Length = 0 then\n            { _reference = V2d.Zero; _sum = V2d.Zero; _sumSq = V2d.Zero; _off = 0.0; _count = 0 }\n        else\n            let reference = points.[0]\n            let mutable sum = V2d.Zero\n            let mutable sumSq = V2d.Zero\n            let mutable off = 0.0\n            let mutable count = 1\n\n            for i in 1 .. points.Length - 1 do\n                let pt = points.[i] - reference\n                sum <- sum + pt\n                sumSq <- sumSq + sqr pt\n                off <- off + pt.X*pt.Y\n                count <- count + 1\n            \n            { _reference = reference; _sum = sum; _sumSq = sumSq; _off = off; _count = count }\n         \n    /// Creates a new regression from the given points.\n    new(s : seq<V2d>) = LinearRegression2d(Seq.toArray s)\n    \n    /// Creates a new regression from the given points.\n    new(s : list<V2d>) = LinearRegression2d(List.toArray s)\n    \n    /// A regression holding no points.\n    static member Zero = LinearRegression2d(V2d.Zero, V2d.Zero, V2d.Zero, 0.0, 0)\n\n    /// A regression holding no points.\n    static member Empty = LinearRegression2d(V2d.Zero, V2d.Zero, V2d.Zero, 0.0, 0)\n   \n    /// The total number of points added. Note that at least 3 points are required to fit a plane.\n    member x.Count = x._count\n\n    member private x.WithReferencePoint(r : V2d) =\n        let d = x._reference - r\n        if r + d = r then\n            x\n        else\n            let n = float x._count\n\n            // sum ((xi+dx)*(yi+dy))\n            // sum (xi*yi + dx*yi + dy*xi + dx*dy)\n            // sum (xi*yi) + dx*sum(yi) + dy*sum(xi) + n*dx*dy\n            let vxy = d.X*x._sum.Y + d.Y*x._sum.X + n*d.X*d.Y\n\n            // sum (xi+d)^2 \n            // sum (xi^2 + 2xi*d + d^2)\n            // sum (xi^2) + 2*d*sum(xi) + n*d^2\n            LinearRegression2d(\n                r, \n                x._sum + n*d,\n                x._sumSq + 2.0*d*x._sum + n*sqr d,\n                x._off + vxy,\n                x._count\n            )\n\n    /// The centroid of all added points.\n    member x.Centroid = \n        if x._count = 0 then V2d.Zero\n        else x._reference + x._sum / float x._count\n\n\n    /// Adds the given point to the regression.\n    member x.Add(pt : V2d) =\n        if x._count = 0 then\n            LinearRegression2d(pt, V2d.Zero, V2d.Zero, 0.0, 1)\n        else\n            let pt = pt - x._reference\n            LinearRegression2d(\n                x._reference,\n                x._sum + pt,\n                x._sumSq + sqr pt,\n                x._off + pt.X*pt.Y,\n                x._count + 1\n            )\n\n    /// Adds the given point to the regression (mutating the regression).\n    member x.AddInPlace(pt : V2d) =\n        if x._count = 0 then\n            x._reference <- pt\n            x._sum <- V2d.Zero\n            x._sumSq <- V2d.Zero\n            x._off <- 0.0\n            x._count <- 1\n        else\n            let pt = pt - x._reference\n            x._sum <- x._sum + pt\n            x._sumSq <- x._sumSq + sqr pt\n            x._off <- x._off + pt.X*pt.Y\n            x._count <- x._count + 1\n    \n            \n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    member x.Remove(pt : V2d) =\n        if x._count <= 1 then\n            LinearRegression2d.Empty\n        else\n            let pt = pt - x._reference\n            LinearRegression2d(\n                x._reference,\n                x._sum - pt,\n                x._sumSq - sqr pt |> max V2d.Zero,\n                x._off - pt.X*pt.Y,\n                x._count - 1\n            )\n \n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    member x.RemoveInPlace(pt : V2d) =\n        if x._count <= 1 then\n            x._reference <- V2d.Zero\n            x._sum <- V2d.Zero\n            x._sumSq <- V2d.Zero\n            x._off <- 0.0\n            x._count <- 0\n        else\n            let pt = pt - x._reference\n            x._sum <- x._sum - pt\n            x._sumSq <- x._sumSq - sqr pt\n            x._off <- x._off - pt.X*pt.Y\n            x._count <- x._count - 1\n\n \n    /// Gets the variances as [Var(X), Var(Y), Var(Z)]\n    member x.Variance =\n        if x._count < 2 then\n            V2d.Zero\n        else\n            let n = float x._count\n            let avg = x._sum / n\n            let xx = (x._sumSq.X - avg.X * x._sum.X) / (n - 1.0)\n            let yy = (x._sumSq.Y - avg.Y * x._sum.Y) / (n - 1.0)\n            V2d(xx, yy)\n\n    /// Gets the covariance.\n    member x.Covariance =\n        if x._count < 2 then\n            0.0\n        else\n            let n = float x._count\n            let avg = x._sum / n\n            let xy = (x._off - avg.X * x._sum.Y) / (n - 1.0)\n            xy\n \n\n    /// Gets the least-squares plane and a confidence value in [0,1] where 1 stands for a perfect plane.\n    member x.GetPlaneAndConfidence() =\n        if x._count < 2 then\n            struct(Plane2d.Invalid, 0.0)\n        else\n            let n = float x._count\n            let avg = x._sum / n\n            let xx = (x._sumSq.X - avg.X * x._sum.X) / (n - 1.0)\n            let yy = (x._sumSq.Y - avg.Y * x._sum.Y) / (n - 1.0)\n\n            let xy = (x._off - avg.X * x._sum.Y) / (n - 1.0)\n            \n            // (xx-l)*(yy-l) - xy^2 = 0\n            // l^2 - l*(xx+yy) + xx*yy - xy^2 = 0\n\n\n            let _a = 1.0\n            let b = -(xx + yy)\n            let c = xx*yy - sqr xy\n\n\n            let struct (l0, l1) = sortTupleAbs (Polynomial.RealRootsOfNormed(b, c))\n            if Fun.IsTiny l1 then\n                struct(Plane2d.Invalid, 0.0)\n            else\n                let goodness = 1.0 - abs l0 / abs l1\n                \n                if goodness > 1E-5 then\n                    let a = V2d(xx - l0, xy)\n                    let b = V2d(xy, yy - l0)\n                    \n                    let dd = \n                        if Vec.length a > Vec.length b then a\n                        else b\n                        \n                    let normal = V2d(-dd.Y, dd.X) |> Vec.normalize\n                    struct(Plane2d(normal, x._reference + avg), goodness)\n                else\n                    struct(Plane2d.Invalid, goodness)\n\n    /// Gets a Trafo3d for the entire plane (using its principal components) and the respective standard deviations for each axis.\n    member x.GetTrafoAndSizes() =\n        if x._count < 2 then\n            struct(Trafo2d.Identity, V2d.Zero)\n        else\n            let n = float x._count\n            let avg = x._sum / n\n            let xx = (x._sumSq.X - avg.X * x._sum.X) / (n - 1.0)\n            let yy = (x._sumSq.Y - avg.Y * x._sum.Y) / (n - 1.0)\n\n            let xy = (x._off - avg.X * x._sum.Y) / (n - 1.0)\n            \n            let _a = 1.0\n            let b = -(xx + yy)\n            let c = xx*yy - sqr xy\n\n            let struct (l0, l1) = sortTupleAbs (Polynomial.RealRootsOfNormed(b, c))\n            if Fun.IsTiny l1 then\n                struct (Trafo2d.Identity, x._reference + avg)\n            else\n                let vx =\n                    let a = V2d(xx - l0, xy)\n                    let b = V2d(xy, yy - l0)\n                    \n                    let dd = \n                        if Vec.length a > Vec.length b then a\n                        else b\n                    Vec.normalize dd\n                let vy = V2d(-vx.Y, vx.X)\n               \n                let s0 = if l0 < 0.0 then 0.0 else sqrt l0\n                let s1 = if l1 < 0.0 then 0.0 else sqrt l1\n                let dev = V2d(s1,s0)\n\n                let trafo =\n                    let o = x._reference + avg\n                    Trafo2d(\n                        M33d(\n                            vx.X, vy.X, o.X,\n                            vx.Y, vy.Y, o.Y,\n                            0.0,  0.0,  1.0\n                        ),\n                        M33d(\n                            vx.X, vx.Y, -Vec.dot vx o,\n                            vy.X, vy.Y, -Vec.dot vy o,\n                            0.0,  0.0,   1.0\n                        )\n                    )\n                struct(trafo, dev)\n   \n    /// Gets the least-squares plane.\n    member x.GetPlane() =\n        let struct(p, _) = x.GetPlaneAndConfidence()\n        p\n        \n    /// Gets a Trafo3d for the entire plane using its principal components.\n    member x.GetTrafo() =\n        let struct(t, _) = x.GetTrafoAndSizes()\n        t\n  \n    static member (+) (l : LinearRegression2d, r : LinearRegression2d) =\n        if r.Count <= 0 then l\n        elif l.Count <= 0 then r\n        elif l.Count = 1 then r.Add l._reference\n        elif r.Count = 1 then l.Add r._reference\n        else\n            let r1 = r.WithReferencePoint l._reference\n            LinearRegression2d(\n                l._reference,\n                l._sum + r1._sum,\n                l._sumSq + r1._sumSq,\n                l._off + r1._off,\n                l._count + r1._count\n            )\n        \n    static member (-) (l : LinearRegression2d, r : LinearRegression2d) =\n        if r.Count <= 0 then l\n        elif l.Count <= r.Count then LinearRegression2d.Zero\n        elif r.Count = 1 then l.Remove r._reference\n        else\n            let r = r.WithReferencePoint l._reference\n            LinearRegression2d(\n                l._reference,\n                l._sum - r._sum,\n                l._sumSq - r._sumSq,\n                l._off - r._off,\n                l._count - r._count\n            )\n        \n    static member (+) (l : LinearRegression2d, r : V2d) =\n        l.Add r\n        \n    static member (+) (l : V2d, r : LinearRegression2d) =\n        r.Add l\n        \n    static member (-) (l : LinearRegression2d, r : V2d) =\n        l.Remove r\n\nmodule LinearRegression2d =\n\n    /// A regression holding no points.\n    let empty = LinearRegression2d.Zero\n\n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    let inline remove (pt : V2d) (s : LinearRegression2d) = s.Remove pt\n\n    /// Adds the given point to the regression.\n    let inline add (pt : V2d) (s : LinearRegression2d) = s.Add pt\n\n    /// Gets the least-squares plane.\n    let inline getPlane (s : LinearRegression2d) = s.GetPlane()\n\n    /// Gets a Trafo2d for the entire plane using its principal components.\n    let inline getTrafo (s : LinearRegression2d) = s.GetTrafo()\n    \n    /// The total number of points added. Note that at least 2 points are required to fit a line.\n    let inline count (s : LinearRegression2d) = s.Count\n    \n    /// The centroid of all added points.\n    let inline centroid (s : LinearRegression2d) = s.Centroid\n    \n    /// Gets the variances as [Var(X), Var(Y)]\n    let inline variance (s : LinearRegression2d) = s.Variance\n\n    /// Gets the covariance.\n    let inline covariance (s : LinearRegression2d) = s.Covariance\n\n    /// Creates a regression from the given points.\n    let ofSeq (points : seq<V2d>) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n        \n    /// Creates a regression from the given points.\n    let ofList (points : list<V2d>) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n        \n    /// Creates a regression from the given points.\n    let ofArray (points : V2d[]) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n\n\n\n[<Struct>]\ntype LinearRegression3d =\n    val mutable public Reference : V3d\n    val mutable public Sum : V3d\n    val mutable public SumSq : V3d\n    val mutable public Off : V3d\n    \n    /// The total number of points added. Note that at least 3 points are required to fit a plane.\n    val mutable public Count : int\n\n    new(reference : V3d, sum : V3d, sumSq : V3d, off : V3d, count : int) =\n        { Reference = reference; Sum = sum; SumSq = sumSq; Off = off; Count = count }\n\n    /// Creates a new regression with a single point.\n    new(point : V3d) =\n        { Reference = point; Sum = V3d.Zero; SumSq = V3d.Zero; Off = V3d.Zero; Count = 1 }\n        \n    /// Creates a new regression from the given points.\n    new([<ParamArray>] points : V3d[]) =\n        if points.Length = 0 then\n            { Reference = V3d.Zero; Sum = V3d.Zero; SumSq = V3d.Zero; Off = V3d.Zero; Count = 0 }\n        else\n            let reference = points.[0]\n            let mutable sum = V3d.Zero\n            let mutable sumSq = V3d.Zero\n            let mutable off = V3d.Zero\n            let mutable count = 1\n\n            for i in 1 .. points.Length - 1 do\n                let pt = points.[i] - reference\n                sum <- sum + pt\n                sumSq <- sumSq + sqr pt\n                off <- off + V3d(pt.Y*pt.Z, pt.X*pt.Z, pt.X*pt.Y)\n                count <- count + 1\n            \n            { Reference = reference; Sum = sum; SumSq = sumSq; Off = off; Count = count }\n        \n    /// Creates a new regression from the given points.\n    new(s : seq<V3d>) = LinearRegression3d(Seq.toArray s)\n    \n    /// Creates a new regression from the given points.\n    new(s : list<V3d>) = LinearRegression3d(List.toArray s)\n\n\n    /// A regression holding no points.\n    static member Zero = LinearRegression3d(V3d.Zero, V3d.Zero, V3d.Zero, V3d.Zero, 0)\n\n    /// A regression holding no points.\n    static member Empty = LinearRegression3d(V3d.Zero, V3d.Zero, V3d.Zero, V3d.Zero, 0)\n    \n    /// The total number of points added. Note that at least 3 points are required to fit a plane.\n    // member x.Count = x._count\n\n    member private x.WithReferencePoint(r : V3d) =\n        let d = x.Reference - r\n        if r + d = r then\n            x\n        else\n            let n = float x.Count\n\n            // sum ((xi+dx)*(yi+dy))\n            // sum (xi*yi + dx*yi + dy*xi + dx*dy)\n            // sum (xi*yi) + dx*sum(yi) + dy*sum(xi) + n*dx*dy\n            let vxy = d.X*x.Sum.Y + d.Y*x.Sum.X + n*d.X*d.Y\n            let vxz = d.X*x.Sum.Z + d.Z*x.Sum.X + n*d.X*d.Z\n            let vyz = d.Y*x.Sum.Z + d.Z*x.Sum.Y + n*d.Y*d.Z\n\n            // sum (xi+d)^2 \n            // sum (xi^2 + 2xi*d + d^2)\n            // sum (xi^2) + 2*d*sum(xi) + n*d^2\n\n            LinearRegression3d(\n                r, \n                x.Sum + n*d,\n                x.SumSq + 2.0*d*x.Sum + n*sqr d,\n                x.Off + V3d(vyz, vxz, vxy),\n                x.Count\n            )\n\n    /// The centroid of all added points.\n    member x.Centroid = \n        if x.Count = 0 then V3d.Zero\n        else x.Reference + x.Sum / float x.Count\n\n    /// Adds the given point to the regression.\n    member x.Add(pt : V3d) =\n        if x.Count = 0 then\n            LinearRegression3d(pt, V3d.Zero, V3d.Zero, V3d.Zero, 1)\n        else\n            let pt = pt - x.Reference\n            LinearRegression3d(\n                x.Reference,\n                x.Sum + pt,\n                x.SumSq + sqr pt,\n                x.Off + V3d(pt.Y*pt.Z, pt.X*pt.Z, pt.X*pt.Y),\n                x.Count + 1\n            )\n\n    /// Adds the given point to the regression (mutating the regression).\n    member x.AddInPlace(pt : V3d) =\n        if x.Count = 0 then\n            x.Reference <- pt\n            x.Sum <- V3d.Zero\n            x.SumSq <- V3d.Zero\n            x.Off <- V3d.Zero\n            x.Count <- 1\n        else\n            let pt = pt - x.Reference\n            x.Sum <- x.Sum + pt\n            x.SumSq <- x.SumSq + sqr pt\n            x.Off <- x.Off + V3d(pt.Y*pt.Z, pt.X*pt.Z, pt.X*pt.Y)\n            x.Count <- x.Count + 1\n            \n            \n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    member x.Remove(pt : V3d) =\n        if x.Count <= 1 then\n            LinearRegression3d.Empty\n        else\n            let pt = pt - x.Reference\n            LinearRegression3d(\n                x.Reference,\n                x.Sum - pt,\n                x.SumSq - sqr pt |> max V3d.Zero,\n                x.Off - V3d(pt.Y*pt.Z, pt.X*pt.Z, pt.X*pt.Y),\n                x.Count - 1\n            )\n \n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    member x.RemoveInPlace(pt : V3d) =\n        if x.Count <= 1 then\n            x.Reference <- V3d.Zero\n            x.Sum <- V3d.Zero\n            x.SumSq <- V3d.Zero\n            x.Off <- V3d.Zero\n            x.Count <- 0\n        else\n            let pt = pt - x.Reference\n            x.Sum <- x.Sum - pt\n            x.SumSq <- x.SumSq - sqr pt\n            x.Off <- x.Off - V3d(pt.Y*pt.Z, pt.X*pt.Z, pt.X*pt.Y)\n            x.Count <- x.Count - 1\n\n\n    /// Gets the variances as [Var(X), Var(Y), Var(Z)]\n    member x.Variance =\n        if x.Count < 2 then\n            V3d.Zero\n        else\n            let n = float x.Count\n            let avg = x.Sum / n\n            let xx = (x.SumSq.X - avg.X * x.Sum.X) / (n - 1.0)\n            let yy = (x.SumSq.Y - avg.Y * x.Sum.Y) / (n - 1.0)\n            let zz = (x.SumSq.Z - avg.Z * x.Sum.Z) / (n - 1.0)\n            V3d(xx, yy, zz)\n\n    /// Gets the covariances as [Cov(Y,Z), Cov(X,Z), Cov(X,Y)]\n    member x.Covariance =\n        if x.Count < 2 then\n            V3d.Zero\n        else\n            let n = float x.Count\n            let avg = x.Sum / n\n            let xy = (x.Off.Z - avg.X * x.Sum.Y) / (n - 1.0)\n            let xz = (x.Off.Y - avg.X * x.Sum.Z) / (n - 1.0)\n            let yz = (x.Off.X - avg.Y * x.Sum.Z) / (n - 1.0)\n            V3d(yz, xz, xy)\n\n    /// Gets the covariance matrix as\n    /// | Cov(X,X) | Cov(X,Y) | Cov(X,Z) |\n    /// | Cov(X,Y) | Cov(Y,Y) | Cov(Y,Z) |\n    /// | Cov(X,Z) | Cov(Y,Z) | Cov(Z,Z) |\n    member x.CovarianceMatrix =\n        if x.Count < 2  then\n            M33d.Zero\n        else\n            let n = float x.Count\n            let avg = x.Sum / n\n            let xx = (x.SumSq.X - avg.X * x.Sum.X) / (n - 1.0)\n            let yy = (x.SumSq.Y - avg.Y * x.Sum.Y) / (n - 1.0)\n            let zz = (x.SumSq.Z - avg.Z * x.Sum.Z) / (n - 1.0)\n\n            let xy = (x.Off.Z - avg.X * x.Sum.Y) / (n - 1.0)\n            let xz = (x.Off.Y - avg.X * x.Sum.Z) / (n - 1.0)\n            let yz = (x.Off.X - avg.Y * x.Sum.Z) / (n - 1.0)\n        \n            M33d(\n                xx, xy, xz,\n                xy, yy, yz,\n                xz, yz, zz\n            )\n\n    /// Gets the least-squares plane and a confidence value in [0,1] where 1 stands for a perfect plane.\n    member x.GetPlaneAndConfidence() =\n        if x.Count < 3 then\n            struct(Plane3d.Invalid, 0.0)\n        else\n            let n = float x.Count\n            let avg = x.Sum / n\n            let xx = (x.SumSq.X - avg.X * x.Sum.X) / (n - 1.0)\n            let yy = (x.SumSq.Y - avg.Y * x.Sum.Y) / (n - 1.0)\n            let zz = (x.SumSq.Z - avg.Z * x.Sum.Z) / (n - 1.0)\n\n            let xy = (x.Off.Z - avg.X * x.Sum.Y) / (n - 1.0)\n            let xz = (x.Off.Y - avg.X * x.Sum.Z) / (n - 1.0)\n            let yz = (x.Off.X - avg.Y * x.Sum.Z) / (n - 1.0)\n            \n            let _a = 1.0\n            let b = -xx - yy - zz\n            let c = -sqr xy - sqr xz - sqr yz + xx*yy + xx*zz + yy*zz\n            let d = -xx*yy*zz - 2.0*xy*xz*yz + sqr xz*yy + sqr xy*zz + sqr yz*xx\n\n\n            let struct (l0, l1, _l2) = sortTripleAbs (Polynomial.RealRootsOfNormed(b,c,d))\n            if Fun.IsTiny l1 then\n                struct(Plane3d.Invalid, 0.0)\n            else\n                let goodness = 1.0 - abs l0 / abs l1\n                \n                if goodness > 1E-5 then\n                    let c0 = V3d(xx - l0, xy, xz)\n                    let c1 = V3d(xy, yy - l0, yz)\n                    let c2 = V3d(xz, yz, zz - l0)\n                    let normal = \n                        let len0 = Vec.lengthSquared c0\n                        let len1 = Vec.lengthSquared c1\n                        let len2 = Vec.lengthSquared c2\n\n                        if len0 > len1 then\n                            if len2 > len1 then Vec.cross c0 c2 |> Vec.normalize\n                            else Vec.cross c0 c1 |> Vec.normalize\n                        else\n                            if len2 > len0 then Vec.cross c1 c2 |> Vec.normalize\n                            else Vec.cross c0 c1 |> Vec.normalize\n\n                    struct(Plane3d(normal, x.Reference + avg), goodness)\n                else\n                    struct(Plane3d.Invalid, goodness)\n\n    /// Gets a Trafo3d for the entire plane (using its principal components) and the respective standard deviations for each axis.\n    member x.GetTrafoAndSizes() =\n        if x.Count < 3 then\n            struct(Trafo3d.Identity, V3d.Zero)\n        else\n            let n = float x.Count\n            let avg = x.Sum / n\n            let xx = (x.SumSq.X - avg.X * x.Sum.X) / (n - 1.0)\n            let yy = (x.SumSq.Y - avg.Y * x.Sum.Y) / (n - 1.0)\n            let zz = (x.SumSq.Z - avg.Z * x.Sum.Z) / (n - 1.0)\n\n            let xy = (x.Off.Z - avg.X * x.Sum.Y) / (n - 1.0)\n            let xz = (x.Off.Y - avg.X * x.Sum.Z) / (n - 1.0)\n            let yz = (x.Off.X - avg.Y * x.Sum.Z) / (n - 1.0)\n            \n            let _a = 1.0\n            let b = -xx - yy - zz\n            let c = -sqr xy - sqr xz - sqr yz + xx*yy + xx*zz + yy*zz\n            let d = -xx*yy*zz - 2.0*xy*xz*yz + sqr xz*yy + sqr xy*zz + sqr yz*xx\n\n            let struct (l0, l1, l2) = sortTripleAbs (Polynomial.RealRootsOfNormed(b,c,d))\n            if Fun.IsTiny l1 then\n                struct (Trafo3d.Identity, x.Reference + avg)\n            else\n                let c0 = V3d(xx - l0, xy, xz)\n                let c1 = V3d(xy, yy - l0, yz)\n                let c2 = V3d(xz, yz, zz - l0)\n                let struct(vx, vy, vz) = \n                    let len0 = Vec.lengthSquared c0\n                    let len1 = Vec.lengthSquared c1\n                    let len2 = Vec.lengthSquared c2\n\n                    if len0 > len1 then\n                        if len1 > len2 then struct(c0, c1, Vec.cross c0 c1)\n                        elif len0 > len2 then struct(c0, c2, Vec.cross c0 c2)\n                        else struct(c2, c0, Vec.cross c2 c0)\n                    else (* len1 >= len0*)\n                        if len0 > len2 then struct(c1, c0, Vec.cross c1 c0)\n                        elif len1 > len2 then struct(c1, c2, Vec.cross c1 c2)\n                        else struct(c2, c1, Vec.cross c2 c1)\n\n                // orthonormalize the system (minimal numerical errors)\n                let vz = Vec.normalize vz\n                let vx = Vec.normalize (vx - vz * Vec.dot vx vz)\n                let vy = Vec.normalize (vy - vz * Vec.dot vy vz - vx * Vec.dot vy vx)\n\n                // get the stddevs for the main axes\n                let s0 = if l0 < 0.0 then 0.0 else sqrt l0\n                let s1 = if l1 < 0.0 then 0.0 else sqrt l1\n                let s2 = if l2 < 0.0 then 0.0 else sqrt l2\n                let dev = V3d(s2, s1, s0)\n\n                let trafo =\n                    let o = x.Reference + avg\n                    Trafo3d(\n                        M44d(\n                            vx.X, vy.X, vz.X, o.X,\n                            vx.Y, vy.Y, vz.Y, o.Y,\n                            vx.Z, vy.Z, vz.Z, o.Z,\n                            0.0,  0.0,  0.0,  1.0\n                        ),\n                        M44d(\n                            vx.X, vx.Y, vx.Z, -Vec.dot vx o,\n                            vy.X, vy.Y, vy.Z, -Vec.dot vy o,\n                            vz.X, vz.Y, vz.Z, -Vec.dot vz o,\n                            0.0,  0.0,  0.0,   1.0\n                        )\n                    )\n                struct(trafo, dev)\n    \n    /// Gets the least-squares plane.\n    member x.GetPlane() =\n        let struct(p, _) = x.GetPlaneAndConfidence()\n        p\n        \n    /// Gets a Trafo3d for the entire plane using its principal components.\n    member x.GetTrafo() =\n        let struct(t, _) = x.GetTrafoAndSizes()\n        t\n\n    static member (+) (l : LinearRegression3d, r : LinearRegression3d) =\n        if r.Count <= 0 then l\n        elif l.Count <= 0 then r\n        elif l.Count = 1 then r.Add l.Reference\n        elif r.Count = 1 then l.Add r.Reference\n        else\n            let r1 = r.WithReferencePoint l.Reference\n            LinearRegression3d(\n                l.Reference,\n                l.Sum + r1.Sum,\n                l.SumSq + r1.SumSq,\n                l.Off + r1.Off,\n                l.Count + r1.Count\n            )\n        \n    static member (-) (l : LinearRegression3d, r : LinearRegression3d) =\n        if r.Count <= 0 then l\n        elif l.Count <= r.Count then LinearRegression3d.Zero\n        elif r.Count = 1 then l.Remove r.Reference\n        else\n            let r = r.WithReferencePoint l.Reference\n            LinearRegression3d(\n                l.Reference,\n                l.Sum - r.Sum,\n                l.SumSq - r.SumSq,\n                l.Off - r.Off,\n                l.Count - r.Count\n            )\n        \n    static member (+) (l : LinearRegression3d, r : V3d) =\n        l.Add r\n        \n    static member (+) (l : V3d, r : LinearRegression3d) =\n        r.Add l\n        \n    static member (-) (l : LinearRegression3d, r : V3d) =\n        l.Remove r\n\nmodule LinearRegression3d =\n\n    /// A regression holding no points.\n    let empty = LinearRegression3d.Zero\n\n    /// Removes the given point from the regression assuming that it has previously been added.\n    /// NOTE: when removing non-added points the regression will produce inconsistent results.\n    let inline remove (pt : V3d) (s : LinearRegression3d) = s.Remove pt\n\n    /// Adds the given point to the regression.\n    let inline add (pt : V3d) (s : LinearRegression3d) = s.Add pt\n\n    /// Gets the least-squares plane.\n    let inline getPlane (s : LinearRegression3d) = s.GetPlane()\n\n    /// Gets a Trafo3d for the entire plane using its principal components.\n    let inline getTrafo (s : LinearRegression3d) = s.GetTrafo()\n    \n    /// The total number of points added. Note that at least 3 points are required to fit a plane.\n    let inline count (s : LinearRegression3d) = s.Count\n    \n    /// The centroid of all added points.\n    let inline centroid (s : LinearRegression3d) = s.Centroid\n    \n    /// Gets the variances as [Var(X), Var(Y), Var(Z)]\n    let inline variance (s : LinearRegression3d) = s.Variance\n\n    /// Gets the covariances as [Cov(Y,Z), Cov(X,Z), Cov(X,Y)]\n    let inline covariance (s : LinearRegression3d) = s.Covariance\n\n    /// Gets the covariance matrix as\n    /// | Cov(X,X) | Cov(X,Y) | Cov(X,Z) |\n    /// | Cov(X,Y) | Cov(Y,Y) | Cov(Y,Z) |\n    /// | Cov(X,Z) | Cov(Y,Z) | Cov(Z,Z) |\n    let inline covarianceMatrix (pt : V3d) (s : LinearRegression3d) = s.CovarianceMatrix\n\n    /// Creates a regression from the given points.\n    let ofSeq (points : seq<V3d>) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n        \n    /// Creates a regression from the given points.\n    let ofList (points : list<V3d>) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n        \n    /// Creates a regression from the given points.\n    let ofArray (points : V3d[]) =\n        let mutable r = empty\n        for p in points do r.AddInPlace p\n        r\n\n"
  },
  {
    "path": "src/Aardvark.Geometry/PolyRegion2d.fs",
    "content": "﻿namespace Aardvark.Geometry\r\n\r\nopen System\r\nopen System.Runtime.CompilerServices\r\nopen Aardvark.Base\r\nopen LibTessDotNet.Double\r\n\r\nmodule private LibTess =\r\n    let closed (path : array<V2d>) =\r\n        let isClosed = path.[0] = path.[path.Length-1]\r\n           \r\n        let arr = Array.zeroCreate (path.Length + (if isClosed then 0 else 1))\r\n\r\n        for i in 0 .. path.Length - 1 do\r\n            let pt = path.[i]\r\n            arr.[i] <- ContourVertex(Position = Vec3(X = pt.X, Y = pt.Y, Z = 0.0))\r\n                        \r\n        if not isClosed then\r\n            arr.[path.Length] <- arr.[0]\r\n\r\n\r\n        arr\r\n\r\n    let closed3 (path : array<V3d>) =\r\n        let isClosed = path.[0] = path.[path.Length-1]\r\n           \r\n        let arr = Array.zeroCreate (path.Length + (if isClosed then 0 else 1))\r\n\r\n        for i in 0 .. path.Length - 1 do\r\n            let pt = path.[i]\r\n            arr.[i] <- ContourVertex(Position = Vec3(X = pt.X, Y = pt.Y, Z = pt.Z))\r\n                        \r\n        if not isClosed then\r\n            arr.[path.Length] <- arr.[0]\r\n\r\n\r\n        arr\r\n\r\n    let nonRedundantPoints (angleEps : float) (p : V2d[]) : Option<int[]> =\r\n        if p.Length < 3 then\r\n            None\r\n        else\r\n            let inline angleTiny (eps : float) (a : V2d) (b : V2d) =\r\n                Vec.dot a b >= 0.0 && \r\n                abs (a.X * b.Y - a.Y * b.X) < eps\r\n                    \r\n            \r\n            let mutable pl = p.[p.Length - 1]\r\n            let mutable pc = p.[0]\r\n            let mutable pn = p.[1]\r\n\r\n            let mutable dlc = pc - pl |> Vec.normalize\r\n            let mutable dcn = pn - pc |> Vec.normalize\r\n\r\n            let points = System.Collections.Generic.List<int>(p.Length)\r\n            for i in 0 .. p.Length - 1 do\r\n                if not (angleTiny angleEps dlc dcn) then\r\n                    points.Add(i)\r\n\r\n                pl <- pc\r\n                pc <- pn\r\n                pn <- p.[(i + 2) % p.Length]\r\n                dlc <- dcn\r\n                dcn <- pn - pc |> Vec.normalize \r\n\r\n            if points.Count < 3 then \r\n                None\r\n            else \r\n                Some (points.ToArray())\r\n\r\n    let boundary (rule : WindingRule) (regions : seq<list<Polygon2d>>) : list<Polygon2d> =\r\n        let t = Tess()\r\n                \r\n        for r in regions do\r\n            for p in r do\r\n                let contour = closed (Seq.toArray p.Points)\r\n                t.AddContour(contour)\r\n\r\n        t.Tessellate(rule, ElementType.BoundaryContours, 3, null, Vec3(0.0, 0.0, 1.0))\r\n\r\n        if isNull t.Elements || isNull t.Vertices then \r\n            []\r\n        else\r\n       \r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun p -> V2d(p.Position.X, p.Position.Y))\r\n\r\n            let results = System.Collections.Generic.List<Polygon2d>()\r\n\r\n            for pi in 0 .. 2 .. indices.Length - 1 do\r\n                let start = indices.[pi + 0]\r\n                let count = indices.[pi + 1]\r\n                let poly = Array.init count (fun vi -> vertices.[start + vi])\r\n                match nonRedundantPoints Constant.PositiveTinyValue poly with\r\n                    | Some index -> results.Add (Polygon2d (index |> Array.map (Array.get poly)))\r\n                    | _ -> ()\r\n\r\n            results |> CSharpList.toList\r\n\r\n    let triangulate (rule : WindingRule) (region : list<Polygon2d>) : Triangle2d[] =\r\n        let t = Tess()\r\n                \r\n        for p in region do\r\n            let contour = closed (Seq.toArray p.Points)\r\n            t.AddContour(contour)\r\n\r\n        t.Tessellate(rule, ElementType.Polygons, 3, null, Vec3(0.0, 0.0, 1.0))\r\n\r\n        if isNull t.Elements || isNull t.Vertices then \r\n            [||]\r\n        else\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun p -> V2d(p.Position.X, p.Position.Y))\r\n\r\n            Array.init (indices.Length / 3) (fun pi ->\r\n                let i0 = indices.[3 * pi + 0]\r\n                let i1 = indices.[3 * pi + 1]\r\n                let i2 = indices.[3 * pi + 2]\r\n                Triangle2d(vertices.[i0], vertices.[i1], vertices.[i2])\r\n            )\r\n\r\ntype TessellationRule =\r\n    | EvenOdd = 0\r\n    | NonZero = 1\r\n    | Positive = 2\r\n    | Negative = 3\r\n    | AbsGreater1 = 4\r\n\r\ntype Triangle2d<'a> =\r\n    struct\r\n        val mutable public P0 : V2d\r\n        val mutable public P1 : V2d\r\n        val mutable public P2 : V2d\r\n\r\n        val mutable public A0 : 'a\r\n        val mutable public A1 : 'a\r\n        val mutable public A2 : 'a\r\n\r\n        new(p0, a0, p1, a1, p2, a2) = { P0 = p0; P1 = p1; P2 = p2; A0 = a0; A1 = a1; A2 = a2 }\r\n    end\r\n\r\ntype Polygon2d<'a> =\r\n    struct\r\n        val mutable public Points : V2d[]\r\n        val mutable public Attributes : 'a[]\r\n\r\n        new(p,a) = { Points = p; Attributes = a }\r\n    end\r\n\r\ntype Triangle3d<'a> =\r\n    struct\r\n        val mutable public P0 : V3d\r\n        val mutable public P1 : V3d\r\n        val mutable public P2 : V3d\r\n\r\n        val mutable public A0 : 'a\r\n        val mutable public A1 : 'a\r\n        val mutable public A2 : 'a\r\n\r\n        new(p0, a0, p1, a1, p2, a2) = { P0 = p0; P1 = p1; P2 = p2; A0 = a0; A1 = a1; A2 = a2 }\r\n    end\r\n\r\ntype Polygon3d<'a> =\r\n    struct\r\n        val mutable public Points : V3d[]\r\n        val mutable public Attributes : 'a[]\r\n\r\n        new(p,a) = { Points = p; Attributes = a }\r\n    end\r\n\r\n[<AbstractClass; Sealed; Extension>]\r\ntype PolygonTessellator private() =\r\n\r\n    [<Extension>]\r\n    static member Combine (regions : seq<V2d[] * 'a[]>, rule : TessellationRule, interpolate : float[] -> 'a[] -> 'a) =\r\n        let t = Tess()\r\n                \r\n        for (pts, att) in regions do\r\n            let contour = LibTess.closed pts\r\n            for i in 0 .. contour.Length - 1 do contour.[i].Data <- att.[i % att.Length]\r\n            t.AddContour(contour)\r\n\r\n        let combine (pos : Vec3) (data : obj[]) (weights : float[]) =\r\n            interpolate weights (data |> Array.map unbox) :> obj\r\n\r\n        t.Tessellate(unbox (int rule), ElementType.BoundaryContours, 2, CombineCallback(combine), Vec3(0.0, 0.0, 1.0))\r\n        \r\n        if isNull t.Elements || isNull t.Vertices then\r\n            []\r\n        else\r\n            let results = System.Collections.Generic.List<V2d[] * 'a[]>()\r\n\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun v -> V2d(v.Position.X, v.Position.Y), unbox<'a> v.Data)\r\n\r\n            for pi in 0 .. 2 .. indices.Length - 2 do\r\n                let start = indices.[pi + 0]\r\n                let count = indices.[pi + 1]\r\n\r\n                let points = Array.zeroCreate count\r\n                let att = Array.zeroCreate count\r\n                for vi in 0 .. count - 1 do\r\n                    let (p,a) = vertices.[start + vi]\r\n                    points.[vi] <- p\r\n                    att.[vi] <- a\r\n\r\n                results.Add(points, att)\r\n\r\n            CSharpList.toList results\r\n            \r\n    [<Extension>]\r\n    static member Combine (regions : seq<V2d[]>, rule : TessellationRule) =\r\n        let t = Tess()\r\n                \r\n        for pts in regions do\r\n            let contour = LibTess.closed pts\r\n            t.AddContour(contour)\r\n\r\n        t.Tessellate(unbox (int rule), ElementType.BoundaryContours, 2, null, Vec3(0.0, 0.0, 1.0))\r\n        \r\n        if isNull t.Elements || isNull t.Vertices then\r\n            []\r\n        else\r\n            let results = System.Collections.Generic.List<V2d[]>()\r\n\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun v -> V2d(v.Position.X, v.Position.Y))\r\n\r\n            for pi in 0 .. 2 .. indices.Length - 2 do\r\n                let start = indices.[pi + 0]\r\n                let count = indices.[pi + 1]\r\n\r\n                let points = Array.init count (fun vi -> vertices.[start + vi])\r\n                results.Add(points)\r\n\r\n            CSharpList.toList results\r\n            \r\n    [<Extension>]\r\n    static member Combine (regions : seq<Polygon2d<'a>>, rule : TessellationRule, interpolate : float[] -> 'a[] -> 'a) =\r\n        let regions = regions |> Seq.map (fun p -> p.Points, p.Attributes)\r\n        PolygonTessellator.Combine(regions, rule, interpolate)\r\n        \r\n    [<Extension>]\r\n    static member Combine (regions : seq<Polygon2d>, rule : TessellationRule) =\r\n        let regions = regions |> Seq.map (fun p -> Seq.toArray p.Points)\r\n        PolygonTessellator.Combine(regions, rule)\r\n        \r\n    [<Extension>]\r\n    static member Triangulate (regions : seq<V2d[] * 'a[]>, rule : TessellationRule, interpolate : float[] -> 'a[] -> 'a) : list<Triangle2d<'a>> =\r\n        let t = Tess()\r\n                \r\n        for (pts, att) in regions do\r\n            let contour = LibTess.closed pts\r\n            for i in 0 .. contour.Length - 1 do contour.[i].Data <- att.[i % att.Length]\r\n            t.AddContour(contour)\r\n\r\n        let combine (pos : Vec3) (data : obj[]) (weights : float[]) =\r\n            interpolate weights (data |> Array.map unbox) :> obj\r\n\r\n        t.Tessellate(unbox (int rule), ElementType.Polygons, 3, CombineCallback(combine), Vec3(0.0, 0.0, 1.0))\r\n        \r\n        if isNull t.Elements || isNull t.Vertices then\r\n            []\r\n        else\r\n            let results = System.Collections.Generic.List<Triangle2d<'a>>()\r\n\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun v -> V2d(v.Position.X, v.Position.Y), unbox<'a> v.Data)\r\n\r\n            for pi in 0 .. 3 .. indices.Length - 3 do\r\n                let i0 = indices.[pi + 0]\r\n                let i1 = indices.[pi + 1]\r\n                let i2 = indices.[pi + 2]\r\n\r\n                let (p0, a0) = vertices.[i0]\r\n                let (p1, a1) = vertices.[i1]\r\n                let (p2, a2) = vertices.[i2]\r\n\r\n                results.Add(Triangle2d<'a>(p0, a0, p1, a1, p2, a2))\r\n\r\n\r\n            CSharpList.toList results\r\n            \r\n    [<Extension>]\r\n    static member Triangulate (regions : seq<V2d[]>, rule : TessellationRule) =\r\n        let t = Tess()\r\n                \r\n        for pts in regions do\r\n            let contour = LibTess.closed pts\r\n            t.AddContour(contour)\r\n\r\n        t.Tessellate(unbox (int rule), ElementType.Polygons, 3, null, Vec3(0.0, 0.0, 1.0))\r\n        \r\n        if isNull t.Elements || isNull t.Vertices then\r\n            []\r\n        else\r\n            let results = System.Collections.Generic.List<Triangle2d>()\r\n\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun v -> V2d(v.Position.X, v.Position.Y))\r\n\r\n            for pi in 0 .. 3 .. indices.Length - 3 do\r\n                let i0 = indices.[pi + 0]\r\n                let i1 = indices.[pi + 1]\r\n                let i2 = indices.[pi + 2]\r\n\r\n                let p0 = vertices.[i0]\r\n                let p1 = vertices.[i1]\r\n                let p2 = vertices.[i2]\r\n\r\n                results.Add(Triangle2d(p0, p1, p2))\r\n\r\n\r\n            CSharpList.toList results\r\n\r\n    [<Extension>]\r\n    static member Triangulate (regions : seq<Polygon2d<'a>>, rule : TessellationRule, interpolate : float[] -> 'a[] -> 'a) =\r\n        let regions = regions |> Seq.map (fun p -> p.Points, p.Attributes)\r\n        PolygonTessellator.Triangulate(regions, rule, interpolate)\r\n        \r\n    [<Extension>]\r\n    static member Triangulate (regions : seq<Polygon2d>, rule : TessellationRule) =\r\n        let regions = regions |> Seq.map (fun p -> Seq.toArray p.Points)\r\n        PolygonTessellator.Triangulate(regions, rule)\r\n\r\n\r\n\r\n\r\n    [<Extension>]\r\n    static member Combine (regions : seq<V3d[] * 'a[]>, rule : TessellationRule, interpolate : float[] -> 'a[] -> 'a) =\r\n        let t = Tess()\r\n                \r\n        for (pts, att) in regions do\r\n            let contour = LibTess.closed3 pts\r\n            for i in 0 .. contour.Length - 1 do contour.[i].Data <- att.[i % att.Length]\r\n            t.AddContour(contour)\r\n\r\n        let combine (pos : Vec3) (data : obj[]) (weights : float[]) =\r\n            interpolate weights (data |> Array.map unbox) :> obj\r\n\r\n        t.Tessellate(unbox (int rule), ElementType.BoundaryContours, 2, CombineCallback(combine), Vec3(0.0, 0.0, 1.0))\r\n        \r\n        if isNull t.Elements || isNull t.Vertices then\r\n            []\r\n        else\r\n            let results = System.Collections.Generic.List<V3d[] * 'a[]>()\r\n\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun v -> V3d(v.Position.X, v.Position.Y, v.Position.Z), unbox<'a> v.Data)\r\n\r\n            for pi in 0 .. 2 .. indices.Length - 2 do\r\n                let start = indices.[pi + 0]\r\n                let count = indices.[pi + 1]\r\n\r\n                let points = Array.zeroCreate count\r\n                let att = Array.zeroCreate count\r\n                for vi in 0 .. count - 1 do\r\n                    let (p,a) = vertices.[start + vi]\r\n                    points.[vi] <- p\r\n                    att.[vi] <- a\r\n\r\n                results.Add(points, att)\r\n\r\n            CSharpList.toList results\r\n         \r\n    [<Extension>]\r\n    static member Combine (regions : seq<V3d[]>, rule : TessellationRule) =\r\n        let t = Tess()\r\n                \r\n        for pts in regions do\r\n            let contour = LibTess.closed3 pts\r\n            t.AddContour(contour)\r\n\r\n        t.Tessellate(unbox (int rule), ElementType.BoundaryContours, 2, null, Vec3(0.0, 0.0, 1.0))\r\n        \r\n        if isNull t.Elements || isNull t.Vertices then\r\n            []\r\n        else\r\n            let results = System.Collections.Generic.List<V3d[]>()\r\n\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun v -> V3d(v.Position.X, v.Position.Y, v.Position.Z))\r\n\r\n            for pi in 0 .. 2 .. indices.Length - 2 do\r\n                let start = indices.[pi + 0]\r\n                let count = indices.[pi + 1]\r\n\r\n                let points = Array.init count (fun vi -> vertices.[start + vi])\r\n                results.Add(points)\r\n\r\n            CSharpList.toList results\r\n\r\n    [<Extension>]\r\n    static member Combine (regions : seq<Polygon3d<'a>>, rule : TessellationRule, interpolate : float[] -> 'a[] -> 'a) =\r\n        let regions = regions |> Seq.map (fun p -> p.Points, p.Attributes)\r\n        PolygonTessellator.Combine(regions, rule, interpolate)\r\n        \r\n    [<Extension>]\r\n    static member Combine (regions : seq<Polygon3d>, rule : TessellationRule) =\r\n        let regions = regions |> Seq.map (fun p -> Seq.toArray p.Points)\r\n        PolygonTessellator.Combine(regions, rule)\r\n  \r\n    [<Extension>]\r\n    static member Triangulate (regions : seq<V3d[] * 'a[]>, rule : TessellationRule, interpolate : float[] -> 'a[] -> 'a) : list<Triangle3d<'a>> =\r\n        let t = Tess()\r\n                \r\n        for (pts, att) in regions do\r\n            let contour = LibTess.closed3 pts\r\n            for i in 0 .. contour.Length - 1 do contour.[i].Data <- att.[i % att.Length]\r\n            t.AddContour(contour)\r\n\r\n        let combine (pos : Vec3) (data : obj[]) (weights : float[]) =\r\n            interpolate weights (data |> Array.map unbox) :> obj\r\n\r\n        t.Tessellate(unbox (int rule), ElementType.Polygons, 3, CombineCallback(combine), Vec3(0.0, 0.0, 1.0))\r\n        \r\n        if isNull t.Elements || isNull t.Vertices then\r\n            []\r\n        else\r\n            let results = System.Collections.Generic.List<Triangle3d<'a>>()\r\n\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun v -> V3d(v.Position.X, v.Position.Y, v.Position.Z), unbox<'a> v.Data)\r\n\r\n            for pi in 0 .. 3 .. indices.Length - 3 do\r\n                let i0 = indices.[pi + 0]\r\n                let i1 = indices.[pi + 1]\r\n                let i2 = indices.[pi + 2]\r\n\r\n                let (p0, a0) = vertices.[i0]\r\n                let (p1, a1) = vertices.[i1]\r\n                let (p2, a2) = vertices.[i2]\r\n\r\n                results.Add(Triangle3d<'a>(p0, a0, p1, a1, p2, a2))\r\n\r\n\r\n            CSharpList.toList results\r\n    \r\n    [<Extension>]\r\n    static member Triangulate (regions : seq<V3d[]>, rule : TessellationRule) =\r\n        let t = Tess()\r\n                \r\n        for pts in regions do\r\n            let contour = LibTess.closed3 pts\r\n            t.AddContour(contour)\r\n\r\n        t.Tessellate(unbox (int rule), ElementType.Polygons, 3, null, Vec3(0.0, 0.0, 1.0))\r\n        \r\n        if isNull t.Elements || isNull t.Vertices then\r\n            []\r\n        else\r\n            let results = System.Collections.Generic.List<Triangle3d>()\r\n\r\n            let indices = t.Elements\r\n            let vertices = t.Vertices |> Array.map (fun v -> V3d(v.Position.X, v.Position.Y, v.Position.Z))\r\n\r\n            for pi in 0 .. 3 .. indices.Length - 3 do\r\n                let i0 = indices.[pi + 0]\r\n                let i1 = indices.[pi + 1]\r\n                let i2 = indices.[pi + 2]\r\n\r\n                let p0 = vertices.[i0]\r\n                let p1 = vertices.[i1]\r\n                let p2 = vertices.[i2]\r\n\r\n                results.Add(Triangle3d(p0, p1, p2))\r\n\r\n\r\n            CSharpList.toList results\r\n  \r\n    [<Extension>]\r\n    static member Triangulate (regions : seq<Polygon3d<'a>>, rule : TessellationRule, interpolate : float[] -> 'a[] -> 'a) =\r\n        let regions = regions |> Seq.map (fun p -> p.Points, p.Attributes)\r\n        PolygonTessellator.Triangulate(regions, rule, interpolate)\r\n        \r\n    [<Extension>]\r\n    static member Triangulate (regions : seq<Polygon3d>, rule : TessellationRule) =\r\n        let regions = regions |> Seq.map (fun p -> Seq.toArray p.Points)\r\n        PolygonTessellator.Triangulate(regions, rule)\r\n           \r\n\r\n/// PolyRegion represents a set of non-overlapping, counterclockwise polygons surrounding\r\n/// the intended region.\r\n/// When constructed using a polygon the implementation enforces these invariants\r\ntype PolyRegion private(polygons : list<Polygon2d>) =\r\n    static let empty = PolyRegion []\r\n    \r\n    static member Empty = empty\r\n    static member Zero = empty\r\n\r\n    member x.Polygons = polygons\r\n\r\n    member x.Triangulate() =\r\n        LibTess.triangulate WindingRule.EvenOdd polygons\r\n\r\n    member x.Transformed(m : M22d) =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Transformed m))\r\n\r\n    member x.Transformed(m : M33d) =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Transformed m))\r\n\r\n    member x.Transformed(e : Euclidean2d) =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Transformed e))\r\n\r\n    member x.Transformed(s : Similarity2d) =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Transformed s))\r\n\r\n    member x.Transformed(a : Affine2d) =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Transformed a))\r\n\r\n    member x.Transformed(s : Shift2d) =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Transformed s))\r\n\r\n    member x.Transformed(r : Rot2d) =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Transformed r))\r\n\r\n    member x.Transformed(s : Scale2d) =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Transformed s))\r\n\r\n    /// Returns a copy of the PolyRegion with the vertex order of all polygons reversed.\r\n    member x.Reversed =\r\n        PolyRegion (polygons |> List.map (fun p -> p.Reversed))\r\n\r\n    /// Reverses the vertex order of all polygons in-place.\r\n    member x.Reverse() =\r\n        polygons |> List.iter (fun p -> p.Reverse())\r\n\r\n    member x.BoundingBox =\r\n        Box2d(polygons |> Seq.collect (fun p -> p.Points))\r\n\r\n    interface IBoundingBox2d with\r\n        member x.BoundingBox2d = x.BoundingBox\r\n\r\n    member x.IsEmpty =\r\n        List.isEmpty polygons\r\n\r\n    static member Union(l : PolyRegion, r : PolyRegion) =\r\n        LibTess.boundary WindingRule.Positive [l.Polygons; r.Polygons] |> PolyRegion\r\n\r\n    static member Difference(l : PolyRegion, r : PolyRegion) =\r\n        let rev = r.Polygons |> List.map (fun p -> p.Reversed)\r\n        LibTess.boundary WindingRule.Positive [l.Polygons; rev] |> PolyRegion\r\n\r\n    static member Intersection(l : PolyRegion, r : PolyRegion) =\r\n        LibTess.boundary WindingRule.AbsGeqTwo [l.Polygons; r.Polygons] |> PolyRegion\r\n\r\n    static member Xor(l : PolyRegion, r : PolyRegion) =\r\n        LibTess.boundary WindingRule.EvenOdd [l.Polygons; r.Polygons] |> PolyRegion\r\n\r\n    static member inline (^^^) (l : PolyRegion, r : PolyRegion) = PolyRegion.Xor(l,r)\r\n    static member inline (*) (l : PolyRegion, r : PolyRegion) = PolyRegion.Intersection(l,r)\r\n    static member inline (+) (l : PolyRegion, r : PolyRegion) = PolyRegion.Union(l,r)\r\n    static member inline (-) (l : PolyRegion, r : PolyRegion) = PolyRegion.Difference(l,r)\r\n    \r\n    member x.Contains(pt : V2d) =\r\n        polygons |> Seq.exists (fun p ->\r\n            p.Contains pt\r\n        )\r\n\r\n    member x.Contains(contained : PolyRegion) =\r\n        // TODO: better implementation possible\r\n        (contained - x).IsEmpty\r\n\r\n    member x.Contains(b : Box2d) =\r\n        // TODO: better implementation possible\r\n        x.Contains(PolyRegion(b.ToPolygon2dCCW()))\r\n\r\n    member x.Overlaps(other : PolyRegion) =\r\n        // TODO: better implementation possible\r\n        (other * x).IsEmpty |> not\r\n\r\n    member x.Overlaps(b : Box2d) =\r\n        x.Overlaps(PolyRegion(b.ToPolygon2dCCW()))\r\n\r\n\r\n    new(p : Polygon2d, tess : TessellationRule) =\r\n        if p.PointCount < 3 then\r\n            PolyRegion []\r\n        else\r\n            let res = LibTess.boundary (unbox (int tess)) [[p]]\r\n            let res = res |> List.map (fun p -> if p.IsCcw() then p else p.Reversed)\r\n            PolyRegion(res)\r\n\r\n    new(p : Polygon2d) =\r\n        PolyRegion(p, TessellationRule.EvenOdd)\r\n            \r\n\r\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\r\nmodule PolyRegion =\r\n    let empty = PolyRegion.Empty\r\n\r\n    let inline ofPolygon (p : Polygon2d) = PolyRegion p\r\n    let inline ofSeq (p : seq<V2d>) = p |> Polygon2d |> ofPolygon\r\n    let inline ofList (p : list<V2d>) = p |> Polygon2d |> ofPolygon\r\n    let inline ofArray (p : array<V2d>) = p |> Polygon2d |> ofPolygon\r\n    let inline ofBox (b : Box2d) = b.ToPolygon2dCCW() |> ofPolygon\r\n    \r\n    let inline transformed (m : M33d) (r : PolyRegion) = r.Transformed m\r\n    let inline bounds (r : PolyRegion) = r.BoundingBox\r\n\r\n    let inline toPolygons (r : PolyRegion) = r.Polygons\r\n    let inline toTriangles (r : PolyRegion) = r.Triangulate()\r\n\r\n    let inline union (l : PolyRegion) (r : PolyRegion) = l + r\r\n    let inline intersection (l : PolyRegion) (r : PolyRegion) = l * r\r\n    let inline xor (l : PolyRegion) (r : PolyRegion) = l ^^^ r\r\n    let inline difference (l : PolyRegion) (r : PolyRegion) = l - r\r\n\r\n    let unionMany (l : seq<PolyRegion>) = l |> Seq.fold union empty\r\n    let intersectMany (l : seq<PolyRegion>) = l |> Seq.fold intersection empty\r\n\r\n    let inline containsPoint (pt : V2d) (r : PolyRegion) = r.Contains pt\r\n    let inline containsRegion (l : PolyRegion) (r : PolyRegion) = l.Contains r\r\n    let inline overlaps (l : PolyRegion) (r : PolyRegion) = l.Overlaps r\r\n\r\n    let inline isEmpty (r : PolyRegion) = r.IsEmpty\r\n\r\n    let private viewVolume = Box3d(-V3d.III, V3d.III)\r\n    \r\n    let internal toHull3d (viewProj : Trafo3d) =\r\n        let r0 = viewProj.Forward.R0\r\n        let r1 = viewProj.Forward.R1\r\n        let r2 = viewProj.Forward.R2\r\n        let r3 = viewProj.Forward.R3\r\n\r\n        let inline toPlane (v : V4d) =\r\n            Plane3d(-v.XYZ, v.W)\r\n\r\n        Hull3d [|\r\n            r3 - r0 |> toPlane  // right\r\n            r3 + r0 |> toPlane  // left\r\n            r3 + r1 |> toPlane  // bottom\r\n            r3 - r1 |> toPlane  // top\r\n            r3 + r2 |> toPlane  // near\r\n            //r3 - r2 |> toPlane  // far\r\n        |]\r\n\r\n    let ofProjectedBox (viewProj : Trafo3d) (b : Box3d) =\r\n        let p000 = V3d(b.Min.X, b.Min.Y, b.Min.Z)\r\n        let p001 = V3d(b.Min.X, b.Min.Y, b.Max.Z)\r\n        let p010 = V3d(b.Min.X, b.Max.Y, b.Min.Z)\r\n        let p011 = V3d(b.Min.X, b.Max.Y, b.Max.Z)\r\n        let p100 = V3d(b.Max.X, b.Min.Y, b.Min.Z)\r\n        let p101 = V3d(b.Max.X, b.Min.Y, b.Max.Z)\r\n        let p110 = V3d(b.Max.X, b.Max.Y, b.Min.Z)\r\n        let p111 = V3d(b.Max.X, b.Max.Y, b.Max.Z)\r\n                \r\n        let hull = toHull3d viewProj\r\n\r\n        let clippedByPlane (eps : float) (plane : Plane3d) (poly : V3d[]) =\r\n            let cnt = poly.Length\r\n            if cnt < 3 then\r\n                [||]\r\n            else\r\n                let result = System.Collections.Generic.List<V3d>()\r\n\r\n                let mutable p0 = poly.[cnt - 1]\r\n                let mutable h0 = plane.Height p0\r\n                let mutable h0p = h0 > eps\r\n                let mutable h0n = h0 < -eps\r\n\r\n                for i in 0 .. cnt - 1 do\r\n                    let p1 = poly.[i]\r\n                    let h1 = plane.Height p1\r\n                    let h1p = h1 > eps\r\n                    let h1n = h1 < -eps\r\n\r\n                    if h0p && h1n || h0n && h1p then\r\n                        // h0 * (1 - t) + h1 * t = 0\r\n                        // h0 - h0*t + h1 * t = 0\r\n                        // h0 = (h0 - h1) * t\r\n                        // h0 / (h0 - h1) = t\r\n                        let t = h0 / (h0 - h1)\r\n                        result.Add(p0 + (p1 - p0) * t)\r\n\r\n                    if not h1p then \r\n                        result.Add p1\r\n\r\n                    p0 <- p1\r\n                    h0 <- h1\r\n                    h0p <- h1p\r\n                    h0n <- h1n\r\n\r\n                if result.Count > 2 then\r\n                    CSharpList.toArray result\r\n                else\r\n                    [||]\r\n\r\n        let clippedByHull (eps : float) (hull : Hull3d) (polygon : V3d[]) =\r\n            hull.PlaneArray |> Array.fold (flip (clippedByPlane eps)) polygon\r\n\r\n        let projectConvex (arr : V3d[]) =\r\n\r\n            let poly =\r\n                arr |> clippedByHull Constant.PositiveTinyValue hull\r\n                    |> Array.map (viewProj.Forward.TransformPosProj >> Vec.xy)\r\n                    |> (fun a -> if a.Length = 0 then None else Some a)\r\n            \r\n            match poly with\r\n            | None -> empty\r\n            | Some poly ->\r\n                let center = (poly |> Array.fold (+) V2d.Zero) / float poly.Length\r\n                poly |> Array.map (fun p -> 1.000001 * (p - center) + center)\r\n                     |> ofArray\r\n\r\n        unionMany \r\n            [\r\n                [| p000; p001; p011; p010|] |> projectConvex\r\n                [| p100; p101; p111; p110|] |> projectConvex\r\n                        \r\n                [| p000; p001; p101; p100|] |> projectConvex\r\n                [| p010; p011; p111; p110|] |> projectConvex\r\n\r\n                [| p000; p100; p110; p010|] |> projectConvex\r\n                [| p001; p101; p111; p011|] |> projectConvex\r\n            ]\r\n            "
  },
  {
    "path": "src/Aardvark.Geometry/Region3d.fs",
    "content": "﻿namespace Aardvark.Geometry\r\n\r\nopen Aardvark.Base\r\n\r\n[<AbstractClass>]\r\ntype Intersectable3d() =\r\n    abstract member Intersects : Box3d -> bool\r\n    abstract member Contains : Box3d -> bool\r\n    abstract member Contains : V3d -> bool\r\n    default x.Contains(v : V3d) = x.Contains(Box3d(v,v))\r\n\r\n[<RequireQualifiedAccess>]\r\ntype Region3d = \r\n    | Single      of            Intersectable3d\r\n    | And         of Region3d * Region3d \r\n    | Or          of Region3d * Region3d\r\n    | Xor         of Region3d * Region3d\r\n    | Subtract    of Region3d * Region3d\r\n    | Complement  of Region3d\r\n    | Empty \r\n\r\nmodule Intersectable3d =\r\n    \r\n    let ofBox3d (b : Box3d) =\r\n        {\r\n            new Intersectable3d() with\r\n                member x.Intersects(o : Box3d) = b.Intersects(o)\r\n                member x.Contains(o : Box3d) = b.Contains(o)\r\n                member x.Contains(o : V3d) = b.Contains(o)\r\n        }\r\n\r\n    let ofSphere3d (s : Sphere3d) =\r\n        {\r\n            new Intersectable3d() with\r\n                member x.Intersects(o : Box3d) =    o.Intersects(s)\r\n                member x.Contains(o : Box3d) =      o.ComputeCorners() |> Array.forall x.Contains\r\n                member x.Contains(o : V3d) =        Vec.Distance(o, s.Center) <= s.Radius\r\n        }\r\n\r\n    let ofNearPlanePolygon (viewProj : Trafo3d) (npp : PolyRegion) =\r\n\r\n        let hull = PolyRegion.toHull3d viewProj\r\n\r\n        let intersectsBox (box : Box3d) =\r\n            if hull.Intersects box then\r\n                box \r\n                |> PolyRegion.ofProjectedBox viewProj\r\n                |> PolyRegion.overlaps npp\r\n            else\r\n                false\r\n\r\n        let containsPoint (v : V3d) =\r\n            let pp = viewProj.Forward.TransformPosProj v\r\n            if pp.Z >= -1.0 then\r\n                PolyRegion.containsPoint pp.XY npp\r\n            else\r\n                false\r\n        \r\n        let containsBox (b : Box3d) =\r\n            let corners = b.ComputeCorners()\r\n            corners |> Array.forall (fun p -> hull.Contains p && containsPoint p)\r\n            \r\n        {\r\n            new Intersectable3d() with\r\n                member x.Intersects(o : Box3d) =    intersectsBox o\r\n                member x.Contains(o : Box3d) =      containsBox   o\r\n                member x.Contains(o : V3d) =        containsPoint o\r\n        }\r\n\r\nmodule Region3d =\r\n\r\n    let empty = Region3d.Empty\r\n    let inline ofIntersectable x = Region3d.Single x\r\n    let inline ofBox3d b = Region3d.Single (Intersectable3d.ofBox3d b)\r\n    let inline ofSphere3d s = Region3d.Single (Intersectable3d.ofSphere3d s)\r\n    let inline ofNearPlanePolygon viewProj p = Region3d.Single (Intersectable3d.ofNearPlanePolygon viewProj p)\r\n\r\n    let inline intersect l r = Region3d.And(l,r)\r\n    let inline union l r = Region3d.Or(l,r)\r\n    let inline xor l r = Region3d.Xor(l,r)\r\n    let inline subtract l r = Region3d.Subtract(l,r)\r\n    let inline complement r = Region3d.Complement r\r\n    \r\n    let rec intersects (b : Box3d) (s : Region3d) =\r\n        match s with\r\n        | Region3d.Empty ->    false\r\n        | Region3d.Single x ->       x.Intersects b\r\n        | Region3d.Or (l,r) ->       intersects b r || intersects b l\r\n        | Region3d.And (l,r) ->      intersects b r && intersects b l\r\n        | Region3d.Xor (l,r) ->      intersects b (Region3d.Or(l,r)) && not (containsBox b (Region3d.And(l,r)))\r\n        | Region3d.Subtract (l,r) -> (not (containsBox b r)) && intersects b l\r\n        | Region3d.Complement (l) ->     not (containsBox b l)\r\n\r\n    and containsBox (b : Box3d) (s : Region3d) =\r\n        match s with\r\n        | Region3d.Empty ->    false\r\n        | Region3d.Single x ->       x.Contains b\r\n        | Region3d.Or (l,r) ->       intersects b (Region3d.And(Region3d.Complement(l),Region3d.Complement(r))) |> not\r\n        | Region3d.And (l,r) ->      containsBox b r && containsBox b l\r\n        | Region3d.Xor (l,r) ->      containsBox b (Region3d.Or(l,r)) && not (intersects b (Region3d.And(l,r)))\r\n        | Region3d.Subtract (l,r) -> (not (intersects b r)) && containsBox b l\r\n        | Region3d.Complement (l) -> not (intersects b l)\r\n\r\n    let rec contains (v : V3d) (s : Region3d) =\r\n        match s with\r\n        | Region3d.Empty ->    false\r\n        | Region3d.Single x ->       x.Contains v\r\n        | Region3d.Or (l,r) ->       contains v r || contains v l\r\n        | Region3d.And (l,r) ->      contains v r && contains v l\r\n        | Region3d.Xor (l,r) ->      contains v r <> contains v l\r\n        | Region3d.Subtract (l,r) -> not (contains v r) && contains v l\r\n        | Region3d.Complement (l) -> not (contains v l)"
  },
  {
    "path": "src/Aardvark.Geometry/TexturePacking.fs",
    "content": "﻿namespace Aardvark.Geometry\n\nopen System\nopen Aardvark.Base\nopen Aardvark.Base.Sorting\nopen Aardvark.Base.Geometry\nopen Aardvark.Geometry\nopen FSharp.Data.Adaptive\n\n[<AutoOpen>]\nmodule private TexturePackerHelpers =\n    let inline createBox (box : Box2i) =\n        Box2d (V2d box.Min - V2d.Half, V2d box.Max + V2d.Half)\n       \n    let inline getSize (b : Box2i) = V2i.II + b.Max - b.Min\n    \n    let inline split (a : Box2i) (b : Box2i) : list<Box2i> =\n        List.filter (fun (a : Box2i) -> a.Min.AllSmallerOrEqual a.Max) [\n            (\n                let mutable a = a\n                a.Min.X <- b.Max.X + 1\n                a\n            )\n            (\n                let mutable a = a\n                a.Max.X <- b.Min.X - 1\n                a\n            )\n            (\n                let mutable a = a\n                a.Min.Y <- b.Max.Y + 1\n                a\n            )\n            (\n                let mutable a = a\n                a.Max.Y <- b.Min.Y - 1\n                a\n            )\n        ]\n            \n\n    let inline intersects (a : Box2i) (b : Box2i) =\n        (a.Min.X <= b.Max.X) && \n        (a.Max.X >= b.Min.X) && \n        (a.Min.Y <= b.Max.Y) && \n        (a.Max.Y >= b.Min.Y)   \n\n    let maxRects (a : Box2i) (b : Box2i) =\n    \n        let inline intersects (a : Box2i) (b : Box2i) =\n            (a.Min.X <= b.Max.X + 1) && \n            (a.Max.X >= b.Min.X - 1) && \n            (a.Min.Y <= b.Max.Y + 1) && \n            (a.Max.Y >= b.Min.Y - 1)   \n\n        if intersects a b then\n            if a.Contains b then\n                [a]\n            elif b.Contains a then\n                [b]\n            else\n                let ax = a.RangeX\n                let ay = a.RangeY\n                let bx = b.RangeX\n                let by = b.RangeY\n\n                let abx = ax.Contains bx\n                let bax = bx.Contains ax\n                        \n                let aby = ay.Contains by\n                let bay = by.Contains ay\n\n                if abx && bax then\n                    [ Box2i(ax, ay.Union by) ]\n\n                elif aby && bay then\n                    [ Box2i(ax.Union bx, ay) ]\n\n                elif abx then\n                    [\n                        Box2i(bx, ay.Union by)\n                        a\n                    ] \n\n                elif bax then\n                    [\n                        Box2i(ax, ay.Union by)\n                        b\n                    ] \n\n                elif aby then\n                    [\n                        Box2i(ax.Union bx, by)\n                        a\n                    ] \n\n                elif bay then\n                    [\n                        Box2i(ax.Union bx, ay)\n                        b\n                    ] \n\n                else\n                    [\n                        Box2i(ax.Union bx, ay.Intersection by)\n                        Box2i(ax.Intersection bx, ay.Union by)\n                        a\n                        b\n                    ]  |> List.filter (fun b -> b.IsValid)\n\n\n\n\n\n\n                    \n\n        else    \n            [a;b]\n                    \n    let merge (n : Box2i) (boxes : HashSet<Box2i>) : seq<Box2i> =\n        if boxes.Count <= 0 then \n            Seq.singleton n\n        else\n            // free is non-empty\n            // boxes are maxrects (and therefore non-empty)\n            // none of boxes contains free\n\n            let mutable free = BvhTree2d.empty\n\n            let add (b : Box2i) =   \n                let q = Box2i(b.Min - V2i.II, b.Max + V2i.II)\n                let touching = \n                    free \n                    |> BvhTree2d.getIntersecting (Box2d q)\n                    |> HashMap.keys\n                    |> HashSet.filter (fun o -> intersects o q)\n                \n\n                if HashSet.isEmpty touching then\n                    free <- BvhTree2d.add b (createBox b) b free\n\n                else\n                    for o in touching do\n                        free <- BvhTree2d.remove o free\n\n                        for r in maxRects o b do\n                            let notContained = BvhTree2d.getContaining (createBox r) free |> HashMap.isEmpty\n                            if notContained then\n                                for (k,_) in BvhTree2d.getContained (createBox r) free do\n                                    free <- BvhTree2d.remove k free\n\n                                free <- BvhTree2d.add r (createBox r) r free\n\n            add n\n            for b in boxes do add b\n\n\n            BvhTree2d.keys free\n\n\n\n\n\n    let inline addFree (b : Box2i) (free : BvhTree2d<_,_>) =\n        if b.Min.AnyGreater b.Max then free\n        else \n            let c = BvhTree2d.getContaining (createBox b) free\n            if c.IsEmpty then \n                BvhTree2d.add b (createBox b) b free\n            else \n                free\n\n    module Seq =\n        let inline tryMinByV (mapping : 'a -> ValueOption<struct('b * 'c)>) (l : seq<'a>) =\n            use e = l.GetEnumerator()\n\n            let mutable best = ValueNone\n            let mutable bestScore = Unchecked.defaultof<'b>\n            while ValueOption.isNone best && e.MoveNext() do\n                let c = e.Current\n                match mapping c with\n                | ValueSome(s, v) ->\n                    bestScore <- s\n                    best <- ValueSome(struct(c, v))\n                | ValueNone ->\n                    ()\n\n            match best with\n            | ValueSome best ->\n                let mutable best = best\n\n                while e.MoveNext() do\n                    let c = e.Current\n                    match mapping c with\n                    | ValueSome(s, v) ->\n                        if s < bestScore then\n                            bestScore <- s\n                            best <- struct(c, v)\n                        \n                    | ValueNone ->\n                        ()\n\n                ValueSome best\n\n            | ValueNone ->\n                ValueNone\n\n/// TexturePacking represents an immutable 2D atlas.\ntype TexturePacking<'a when 'a : equality> private(atlasSize : V2i, allowRotate : bool, free : BvhTree2d<Box2i, Box2i>, used : HashMap<'a, Box2i>) =\n\n    let validate() =\n        \n        let u = used |> Seq.map snd |> Seq.toArray\n        let mutable all : HashSet<Box2i> = HashSet.empty\n\n\n        for minx in -1 .. u.Length do\n            for miny in -1 .. u.Length do\n                for maxx in -1 .. u.Length do\n                    for maxy in -1 .. u.Length do\n                        let lx = \n                            if minx < 0 then 0\n                            elif minx >= u.Length then atlasSize.X - 1\n                            else u.[minx].Max.X + 1\n                                        \n                        let ly = \n                            if miny < 0 then 0\n                            elif miny >= u.Length then atlasSize.Y - 1\n                            else u.[miny].Max.Y + 1\n                                        \n                        let hx = \n                            if maxx < 0 then 0\n                            elif maxx >= u.Length then atlasSize.X - 1\n                            else u.[maxx].Min.X - 1\n                                        \n                        let hy = \n                            if maxy < 0 then 0\n                            elif maxy >= u.Length then atlasSize.Y - 1\n                            else u.[maxy].Min.Y - 1\n\n                        let box = Box2i(V2i(lx, ly), V2i(hx, hy))\n                        if box.Min.AllSmallerOrEqual box.Max then\n                            let badbox = u |> Array.exists (fun u -> intersects u box)\n                            if not badbox then\n                                let n = box\n                                let isContained = all |> HashSet.exists (fun o -> o.Contains n)\n                                if not isContained then\n                                    all <- \n                                        all \n                                        |> HashSet.filter (fun o -> not (n.Contains o))\n                                        |> HashSet.add n\n\n\n        let free = BvhTree2d.keys free |> HashSet.ofSeq\n\n        let delta = HashSet.computeDelta all free\n        if not (HashSetDelta.isEmpty delta) then\n            let str = \n                String.concat \"\\r\\n\" [\n                    delta |> Seq.map (function Add(_,v) -> sprintf \"+%A\" v | Rem(_,v) -> sprintf \"-%A\" v) |> String.concat \"; \"\n                    sprintf \"%A\" all\n                    sprintf \"%A\" free\n                ]\n            //failwithf \"bad free: %s\" str\n            Log.warn \"bad free: %s\" str\n    \n    //do validate()\n\n    \n    /// All free MaxRects.\n    member x.Free = free\n\n    /// Used Rects.\n    member x.Used = used\n\n    /// Total Atlas Size.\n    member x.Size = atlasSize\n\n    /// The relative number of pixels occupied.\n    member x.Occupancy =\n        let area = \n            used |> Seq.sumBy (fun (_, b) ->\n                let s = V2i.II + b.Max - b.Min\n                float s.X * float s.Y\n            )\n        area / (float atlasSize.X * float atlasSize.Y)\n\n    /// Creates an empty TexturePacking with the given size.\n    static member Empty (size : V2i, allowRotate : bool) : TexturePacking<'a> =\n        if size.AnySmallerOrEqual 0 then\n            TexturePacking<'a>(V2i.Zero, allowRotate, BvhTree2d.empty, HashMap.empty)\n        else\n            let bb = Box2i(V2i.Zero, size - V2i.II)\n            TexturePacking<'a>(size, allowRotate, BvhTree2d.ofList [bb, createBox bb, bb], HashMap.empty)\n            \n    static member Empty (size : V2i) : TexturePacking<'a> =\n        TexturePacking<'a>.Empty(size, true)\n\n    /// Tries to add an element with the given size and (optionally) returns a new TexturePacking.\n    member x.TryAdd(id : 'a, size : V2i) : option<TexturePacking<'a>> =\n        if size.AnySmallerOrEqual 0 then\n            Some x\n        else\n            match HashMap.tryFind id used with\n            | Some b ->\n                if getSize b = size then\n                    Some x\n                else\n                    x.Remove(id).TryAdd(id, size)\n                    \n            | None ->   \n                let error (b : Box2i) : voption<struct(float * bool)> =\n                    let sh = getSize b\n\n                    let f0 = sh.AllGreaterOrEqual size\n                    let f1 = if allowRotate then sh.AllGreaterOrEqual size.YX else false\n                    let w0 = (sh.X - size.X) * (sh.Y - size.Y)\n                    let w1 = (sh.X - size.Y) * (sh.Y - size.X)\n\n                    let inline w (v : int) =\n                        float v\n                        //1.0 / (1.0 + float v)\n\n                    if f0 && f1 then\n                        if w0 < w1 then ValueSome struct(w w0, true)\n                        else ValueSome struct(w w1, false)\n\n                    elif f0 then\n                        ValueSome struct(w w0, true)\n                        \n                    elif f1 then\n                        ValueSome struct(w w1, false)\n                        \n                    else\n                        ValueNone\n\n                let fitting = \n                    free \n                    |> BvhTree2d.keys \n                    |> Seq.tryMinByV error\n\n                match fitting with\n                | ValueSome (struct(fitting, upright)) -> \n                    let size = \n                        if upright then size\n                        else size.YX\n\n                    let r0 = Box2i(fitting.Min + V2i(size.X, 0), fitting.Max)\n                    let r1 = Box2i(fitting.Min + V2i(0, size.Y), fitting.Max)\n\n                    let rect = Box2i(fitting.Min, fitting.Min + size - V2i.II)\n\n                    let free =\n                        free\n                        |> BvhTree2d.remove fitting\n                        |> addFree r0\n                        |> addFree r1\n\n                    let intersecting = \n                        BvhTree2d.getIntersecting (createBox rect) free\n\n                    let free = \n                        (free, intersecting) ||> HashMap.fold (fun free fid struct(_, other) ->\n                            (BvhTree2d.remove fid free, split other rect) \n                            ||> List.fold (fun free p -> addFree p free)\n                        )\n\n                    let result =\n                        TexturePacking(atlasSize, allowRotate, free, HashMap.add id rect used)\n\n                    Some result\n                | ValueNone ->\n                    None\n\n    /// Tries to add several elements with the given sizes and (optionally) returns a new TexturePacking.\n    member x.TryAdd(many : seq<'a * V2i>) : option<TexturePacking<'a>> =\n        use e = many.GetEnumerator()\n        let mutable res = Some x\n        while Option.isSome res && e.MoveNext() do\n            let (id, size) = e.Current\n            res <- res.Value.TryAdd(id, size)\n        res\n\n    /// Removes a given element from the TexturePacking.\n    member x.Remove(id : 'a) : TexturePacking<'a> =\n        match HashMap.tryRemoveV id used with\n        | ValueSome(rect, used) ->\n\n            let qi = Box2i(rect.Min - V2i.II, rect.Max + V2i.II)\n            let adjacent = \n                free \n                |> BvhTree2d.getIntersecting (Box2d qi)\n                |> HashMap.keys\n                |> HashSet.filter (fun b -> \n                    b.Min.X = qi.Max.X ||\n                    b.Max.X = qi.Min.X ||\n                    b.Min.Y = qi.Max.Y ||\n                    b.Max.Y = qi.Min.Y\n                )\n\n            let free = \n                (free, adjacent) \n                ||> HashSet.fold (fun free a -> BvhTree2d.remove a free)\n\n            let free = \n                (free, merge rect adjacent)\n                ||> Seq.fold (fun free a -> addFree a free)\n                \n            TexturePacking(atlasSize, allowRotate, free, used)\n        | ValueNone ->\n            x\n\n    static member FromUsed(atlasSize : V2i, allowRotate : bool, used : HashMap<'a, Box2i>) =\n        let bb = Box2i(V2i.Zero, atlasSize - V2i.II)\n        let mutable free = BvhTree2d.ofList [bb, createBox bb, bb]\n\n        for (k, v) in used do\n        \n            let fitting, _ = free.GetContaining (createBox v) |> Seq.exactlyOne\n            let rest = split fitting v\n\n            let f =\n                (BvhTree2d.remove fitting free, rest)\n                ||> List.fold (fun f r -> addFree r f)\n\n            let intersecting = \n                BvhTree2d.getIntersecting (createBox v) f\n\n            let f = \n                (f, intersecting) ||> HashMap.fold (fun free fid struct(_, other) ->\n                    (BvhTree2d.remove fid free, split other v) \n                    ||> List.fold (fun free p -> addFree p free)\n                )\n\n            free <- f\n\n\n        TexturePacking(atlasSize, allowRotate, free, used)\n\n/// TexturePacking represents an immutable 2D atlas.\nmodule TexturePacking =\n    \n    /// Creates an empty TexturePacking with the given size.\n    let inline empty (size : V2i) = TexturePacking<'a>.Empty size\n    \n    /// Checks whether the TexturePacking is empty.\n    let inline isEmpty (packing : TexturePacking<'a>) = packing.Used.Count = 0\n    \n    /// Returns the number of Rects in the TexturePacking.\n    let inline count (packing : TexturePacking<'a>) = packing.Used.Count\n    \n    /// The relative number of pixels occupied.\n    let inline occupancy (packing : TexturePacking<'a>) = packing.Occupancy\n\n    /// Tries to add an element with the given size and (optionally) returns a new TexturePacking.\n    let inline tryAdd (id : 'a) (size : V2i) (packing : TexturePacking<'a>) =\n        packing.TryAdd(id, size)\n            \n    /// Tries to add several elements with the given sizes and (optionally) returns a new TexturePacking.\n    let inline tryAddMany (elements : #seq<'a * V2i>) (packing : TexturePacking<'a>) =\n        let sorted = elements |> Seq.sortByDescending (fun (_,v) -> max v.X v.Y)\n        packing.TryAdd sorted\n\n    /// Tries to create a TexturePacking with the given size for all elements.\n    let inline tryOfSeq (size : V2i) (elements : #seq<'a * V2i>) =\n        empty size\n        |> tryAddMany elements\n            \n    /// Tries to create a TexturePacking with the given size for all elements.\n    let inline tryOfList (size : V2i) (elements : list<'a * V2i>) =\n        empty size\n        |> tryAddMany elements\n            \n    /// Tries to create a TexturePacking with the given size for all elements.\n    let inline tryOfArray (size : V2i) (elements : array<'a * V2i>) =\n        empty size\n        |> tryAddMany elements\n        \n    /// Tries to create an optimal square packing for the given elements.\n    let square (elements : seq<'a * V2i>) =\n        let elements = Seq.toArray elements\n        elements.QuickSortDescending(fun (_,v) -> max v.X v.Y)\n        if elements.Length <= 0 then\n            empty V2i.Zero\n        elif elements.Length = 1 then\n            let (id, size) = elements.[0]\n            let s = max size.X size.Y\n            empty (V2i(s,s)) |> tryAdd id size |> Option.get\n        else\n            let area = elements |> Array.sumBy (fun (_,s) -> s.X * s.Y)\n            let mutable l = floor (sqrt (float area)) |> int\n            let mutable h = Fun.NextPowerOfTwo l\n\n            let mutable best = tryOfArray (V2i(h,h)) elements\n            while Option.isNone best do\n                l <- h\n                h <- h * 2\n                best <- tryOfArray (V2i(h,h)) elements\n\n\n            let mutable bestPacking = best.Value\n            while h > l + 1 do\n                let m = (h + l) / 2\n                match tryOfArray (V2i(m, m)) elements with\n                | Some packing ->\n                    bestPacking <- packing\n                    h <- m\n                | None ->\n                    l <- m\n\n            bestPacking\n\n    /// Creates a sequence of all Rects in the packing.\n    let inline toSeq (packing : TexturePacking<'a>) =\n        packing.Used :> seq<_>\n\n    /// Creates a list of all Rects in the packing.\n    let inline toList (packing : TexturePacking<'a>) =\n        packing.Used |> HashMap.toList\n\n    /// Creates an array of all Rects in the packing.\n    let inline toArray (packing : TexturePacking<'a>) =\n        packing.Used |> HashMap.toArray\n"
  },
  {
    "path": "src/Aardvark.Geometry/paket.references",
    "content": "FSharp.Core\nAardvark.Build\nUnofficial.LibTessDotNet\nFsPickler\nAardvark.Base.TypeProviders\nFSharp.Data.Adaptive"
  },
  {
    "path": "src/Aardvark.Geometry/paket.template",
    "content": "type project\nid Aardvark.Geometry\nauthors Aardvark Platform Team\nowners Aardvark Platform Team\nprojectUrl http://github.com/aardvark-platform\nlicenseUrl http://www.apache.org/licenses/LICENSE-2.0.txt\nrepositoryType git\nrepositoryUrl https://github.com/aardvark-platform/aardvark.base\ndescription\n    Aardvark is an open-source platform for visual computing, real-time graphics and visualization.\ninclude-pdbs true"
  },
  {
    "path": "src/Aardvark.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio Version 17\r\nVisualStudioVersion = 17.2.32526.322\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.FSharp\", \"Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\", \"{692A3617-719B-4EA2-ABC1-407AE20094AE}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.Incremental\", \"Aardvark.Base.Incremental\\Aardvark.Base.Incremental.fsproj\", \"{9623AE28-1F72-46E9-A3A7-85FC1A321A73}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Demo\", \"Demo\", \"{864A9013-93AC-4073-BB2A-348CE1B00010}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"IncrementalDemo.CSharp\", \"Demo\\IncrementalDemo.CSharp\\IncrementalDemo.CSharp.csproj\", \"{4BFAAF2F-BB67-471E-A956-F533F13EA643}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Aardvark.Base.Tests\", \"Tests\\Aardvark.Base.Tests\\Aardvark.Base.Tests.csproj\", \"{90054DAF-8E70-467A-AF80-3B06EEC527F5}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Tests\", \"Tests\", \"{A79411F9-60B3-46C8-8981-6905D9B9F74C}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"PixImageDemo\", \"Demo\\PixImageDemo\\PixImageDemo.csproj\", \"{B4F29FFC-FBA2-4222-AD47-B12B962A14B0}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.FSharp.Tests\", \"Tests\\Aardvark.Base.FSharp.Tests\\Aardvark.Base.FSharp.Tests.fsproj\", \"{1B4BEB6E-96A1-4B86-9AC5-F9F5824382AE}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.Runtime\", \"Aardvark.Base.Runtime\\Aardvark.Base.Runtime.fsproj\", \"{04E146C2-1C4C-432F-922C-351D0F4CED67}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.Runtime.Tests\", \"Tests\\Aardvark.Base.Runtime.Tests\\Aardvark.Base.Runtime.Tests.fsproj\", \"{CE9B55FF-2D3E-4E13-BA0A-69FD82F0B29B}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Geometry\", \"Aardvark.Geometry\\Aardvark.Geometry.fsproj\", \"{97F4D5BB-9F48-454B-B6A5-536AE172CE50}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Aardvark.Base.IO\", \"Aardvark.Base.IO\\Aardvark.Base.IO.csproj\", \"{C2C8BA0D-992B-4BA7-8A6A-EA7A3207BBE6}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \".NetStandard\", \".NetStandard\", \"{C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"CodeGenerator\", \"CodeGenerator\\CodeGenerator.csproj\", \"{4B4A0898-4429-4E39-A916-50A0DE8E74E6}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Aardvark.Base\", \"Aardvark.Base\\Aardvark.Base.csproj\", \"{C90C041E-E076-4BBC-BBCD-B29367F649A2}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Aardvark.Base.Essentials\", \"Aardvark.Base.Essentials\\Aardvark.Base.Essentials.csproj\", \"{2E887670-5BC3-44FA-97A3-389917B27BEB}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"ExamplesCSharp\", \"Demo\\ExamplesCSharp\\ExamplesCSharp.csproj\", \"{6C6850B4-FDE7-4D75-9113-DCF9779145A6}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Scratch\", \"Demo\\Scratch\\Scratch.fsproj\", \"{39EC0F23-19DF-46FD-8273-E931D26B7209}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Aardvark.Base.Telemetry\", \"Aardvark.Base.Telemetry\\Aardvark.Base.Telemetry.csproj\", \"{B1593A50-6412-401F-AC89-433F426A8FD5}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"CoreTest\", \"Demo\\CoreTest\\CoreTest.fsproj\", \"{0EC60544-E12C-4400-BB89-BCAF059A5FBD}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"RandomSampleDemo\", \"Demo\\RandomSampleDemo\\RandomSampleDemo.csproj\", \"{ED85304F-6D46-409B-AD2F-175522A54444}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Geometry.Tests\", \"Tests\\Aardvark.Geometry.Tests\\Aardvark.Geometry.Tests.fsproj\", \"{EE0834BA-89F1-4099-8FAD-CC31AA8914E9}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Aardvark.Base.Benchmarks\", \"Tests\\Aardvark.Base.Benchmarks\\Aardvark.Base.Benchmarks.csproj\", \"{99C82F36-74DE-4ED1-B9D5-CE044FC517AC}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Aardvark.Base.Tensors.CSharp\", \"Aardvark.Base.Tensors.CSharp\\Aardvark.Base.Tensors.CSharp.csproj\", \"{06739A61-1B1C-4FC3-8DEF-926B10FACB28}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.Tensors\", \"Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\", \"{FBB17215-CDCE-4FFA-B10A-EA1B320C8638}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.FSharp.Benchmarks\", \"Tests\\Aardvark.Base.FSharp.Benchmarks\\Aardvark.Base.FSharp.Benchmarks.fsproj\", \"{F278A2F7-52FF-40CD-B16D-4D82F7DFA8C3}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"._\", \"._\", \"{61D029CD-C474-4CC5-AEF6-B898F9B3D6A3}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\t..\\.gitignore = ..\\.gitignore\r\n\t\t..\\build.cmd = ..\\build.cmd\r\n\t\t..\\build.sh = ..\\build.sh\r\n\t\t..\\generate.cmd = ..\\generate.cmd\r\n\t\t..\\generate.sh = ..\\generate.sh\r\n\t\t..\\LICENSE = ..\\LICENSE\r\n\t\t..\\PACKAGES.md = ..\\PACKAGES.md\r\n\t\t..\\paket.dependencies = ..\\paket.dependencies\r\n\t\t..\\paket.lock = ..\\paket.lock\r\n\t\t..\\README.md = ..\\README.md\r\n\t\t..\\RELEASE_NOTES.md = ..\\RELEASE_NOTES.md\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.Fonts\", \"Aardvark.Base.Fonts\\Aardvark.Base.Fonts.fsproj\", \"{C6C9C0AE-0900-4F21-86C6-2202E44A6013}\"\r\nEndProject\r\nProject(\"{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}\") = \"Aardvark.Base.Fonts.Tests\", \"Tests\\Aardvark.Base.Fonts.Tests\\Aardvark.Base.Fonts.Tests.fsproj\", \"{D45E8A40-22A3-44F5-90EA-D42D5D7A522B}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Any CPU = Debug|Any CPU\r\n\t\tRelease|Any CPU = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{692A3617-719B-4EA2-ABC1-407AE20094AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{692A3617-719B-4EA2-ABC1-407AE20094AE}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{692A3617-719B-4EA2-ABC1-407AE20094AE}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{692A3617-719B-4EA2-ABC1-407AE20094AE}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{9623AE28-1F72-46E9-A3A7-85FC1A321A73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{9623AE28-1F72-46E9-A3A7-85FC1A321A73}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{9623AE28-1F72-46E9-A3A7-85FC1A321A73}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{9623AE28-1F72-46E9-A3A7-85FC1A321A73}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{4BFAAF2F-BB67-471E-A956-F533F13EA643}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{4BFAAF2F-BB67-471E-A956-F533F13EA643}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{4BFAAF2F-BB67-471E-A956-F533F13EA643}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{4BFAAF2F-BB67-471E-A956-F533F13EA643}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{90054DAF-8E70-467A-AF80-3B06EEC527F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{90054DAF-8E70-467A-AF80-3B06EEC527F5}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{90054DAF-8E70-467A-AF80-3B06EEC527F5}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{90054DAF-8E70-467A-AF80-3B06EEC527F5}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{B4F29FFC-FBA2-4222-AD47-B12B962A14B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{B4F29FFC-FBA2-4222-AD47-B12B962A14B0}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{B4F29FFC-FBA2-4222-AD47-B12B962A14B0}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{B4F29FFC-FBA2-4222-AD47-B12B962A14B0}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{1B4BEB6E-96A1-4B86-9AC5-F9F5824382AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{1B4BEB6E-96A1-4B86-9AC5-F9F5824382AE}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{1B4BEB6E-96A1-4B86-9AC5-F9F5824382AE}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{1B4BEB6E-96A1-4B86-9AC5-F9F5824382AE}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{04E146C2-1C4C-432F-922C-351D0F4CED67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{04E146C2-1C4C-432F-922C-351D0F4CED67}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{04E146C2-1C4C-432F-922C-351D0F4CED67}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{04E146C2-1C4C-432F-922C-351D0F4CED67}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{CE9B55FF-2D3E-4E13-BA0A-69FD82F0B29B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{CE9B55FF-2D3E-4E13-BA0A-69FD82F0B29B}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{CE9B55FF-2D3E-4E13-BA0A-69FD82F0B29B}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{CE9B55FF-2D3E-4E13-BA0A-69FD82F0B29B}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{97F4D5BB-9F48-454B-B6A5-536AE172CE50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{97F4D5BB-9F48-454B-B6A5-536AE172CE50}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{97F4D5BB-9F48-454B-B6A5-536AE172CE50}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{97F4D5BB-9F48-454B-B6A5-536AE172CE50}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{C2C8BA0D-992B-4BA7-8A6A-EA7A3207BBE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{C2C8BA0D-992B-4BA7-8A6A-EA7A3207BBE6}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{C2C8BA0D-992B-4BA7-8A6A-EA7A3207BBE6}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{C2C8BA0D-992B-4BA7-8A6A-EA7A3207BBE6}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{4B4A0898-4429-4E39-A916-50A0DE8E74E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{4B4A0898-4429-4E39-A916-50A0DE8E74E6}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{4B4A0898-4429-4E39-A916-50A0DE8E74E6}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{4B4A0898-4429-4E39-A916-50A0DE8E74E6}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{C90C041E-E076-4BBC-BBCD-B29367F649A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{C90C041E-E076-4BBC-BBCD-B29367F649A2}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{C90C041E-E076-4BBC-BBCD-B29367F649A2}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{C90C041E-E076-4BBC-BBCD-B29367F649A2}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{2E887670-5BC3-44FA-97A3-389917B27BEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{2E887670-5BC3-44FA-97A3-389917B27BEB}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{2E887670-5BC3-44FA-97A3-389917B27BEB}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{2E887670-5BC3-44FA-97A3-389917B27BEB}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{6C6850B4-FDE7-4D75-9113-DCF9779145A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{6C6850B4-FDE7-4D75-9113-DCF9779145A6}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{6C6850B4-FDE7-4D75-9113-DCF9779145A6}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{6C6850B4-FDE7-4D75-9113-DCF9779145A6}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{39EC0F23-19DF-46FD-8273-E931D26B7209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{39EC0F23-19DF-46FD-8273-E931D26B7209}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{39EC0F23-19DF-46FD-8273-E931D26B7209}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{39EC0F23-19DF-46FD-8273-E931D26B7209}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{B1593A50-6412-401F-AC89-433F426A8FD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{B1593A50-6412-401F-AC89-433F426A8FD5}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{B1593A50-6412-401F-AC89-433F426A8FD5}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{B1593A50-6412-401F-AC89-433F426A8FD5}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{0EC60544-E12C-4400-BB89-BCAF059A5FBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{0EC60544-E12C-4400-BB89-BCAF059A5FBD}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{0EC60544-E12C-4400-BB89-BCAF059A5FBD}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{0EC60544-E12C-4400-BB89-BCAF059A5FBD}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{ED85304F-6D46-409B-AD2F-175522A54444}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{ED85304F-6D46-409B-AD2F-175522A54444}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{ED85304F-6D46-409B-AD2F-175522A54444}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{ED85304F-6D46-409B-AD2F-175522A54444}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{EE0834BA-89F1-4099-8FAD-CC31AA8914E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{EE0834BA-89F1-4099-8FAD-CC31AA8914E9}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{EE0834BA-89F1-4099-8FAD-CC31AA8914E9}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{EE0834BA-89F1-4099-8FAD-CC31AA8914E9}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{99C82F36-74DE-4ED1-B9D5-CE044FC517AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{99C82F36-74DE-4ED1-B9D5-CE044FC517AC}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{99C82F36-74DE-4ED1-B9D5-CE044FC517AC}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{99C82F36-74DE-4ED1-B9D5-CE044FC517AC}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{06739A61-1B1C-4FC3-8DEF-926B10FACB28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{06739A61-1B1C-4FC3-8DEF-926B10FACB28}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{06739A61-1B1C-4FC3-8DEF-926B10FACB28}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{06739A61-1B1C-4FC3-8DEF-926B10FACB28}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{FBB17215-CDCE-4FFA-B10A-EA1B320C8638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{FBB17215-CDCE-4FFA-B10A-EA1B320C8638}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{FBB17215-CDCE-4FFA-B10A-EA1B320C8638}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{FBB17215-CDCE-4FFA-B10A-EA1B320C8638}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{F278A2F7-52FF-40CD-B16D-4D82F7DFA8C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{F278A2F7-52FF-40CD-B16D-4D82F7DFA8C3}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{F278A2F7-52FF-40CD-B16D-4D82F7DFA8C3}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{F278A2F7-52FF-40CD-B16D-4D82F7DFA8C3}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{C6C9C0AE-0900-4F21-86C6-2202E44A6013}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{C6C9C0AE-0900-4F21-86C6-2202E44A6013}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{C6C9C0AE-0900-4F21-86C6-2202E44A6013}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{C6C9C0AE-0900-4F21-86C6-2202E44A6013}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{D45E8A40-22A3-44F5-90EA-D42D5D7A522B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{D45E8A40-22A3-44F5-90EA-D42D5D7A522B}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{D45E8A40-22A3-44F5-90EA-D42D5D7A522B}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{D45E8A40-22A3-44F5-90EA-D42D5D7A522B}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(NestedProjects) = preSolution\r\n\t\t{692A3617-719B-4EA2-ABC1-407AE20094AE} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{9623AE28-1F72-46E9-A3A7-85FC1A321A73} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{4BFAAF2F-BB67-471E-A956-F533F13EA643} = {864A9013-93AC-4073-BB2A-348CE1B00010}\r\n\t\t{90054DAF-8E70-467A-AF80-3B06EEC527F5} = {A79411F9-60B3-46C8-8981-6905D9B9F74C}\r\n\t\t{B4F29FFC-FBA2-4222-AD47-B12B962A14B0} = {864A9013-93AC-4073-BB2A-348CE1B00010}\r\n\t\t{1B4BEB6E-96A1-4B86-9AC5-F9F5824382AE} = {A79411F9-60B3-46C8-8981-6905D9B9F74C}\r\n\t\t{04E146C2-1C4C-432F-922C-351D0F4CED67} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{CE9B55FF-2D3E-4E13-BA0A-69FD82F0B29B} = {A79411F9-60B3-46C8-8981-6905D9B9F74C}\r\n\t\t{97F4D5BB-9F48-454B-B6A5-536AE172CE50} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{C2C8BA0D-992B-4BA7-8A6A-EA7A3207BBE6} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{C90C041E-E076-4BBC-BBCD-B29367F649A2} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{2E887670-5BC3-44FA-97A3-389917B27BEB} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{6C6850B4-FDE7-4D75-9113-DCF9779145A6} = {864A9013-93AC-4073-BB2A-348CE1B00010}\r\n\t\t{39EC0F23-19DF-46FD-8273-E931D26B7209} = {864A9013-93AC-4073-BB2A-348CE1B00010}\r\n\t\t{B1593A50-6412-401F-AC89-433F426A8FD5} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{0EC60544-E12C-4400-BB89-BCAF059A5FBD} = {864A9013-93AC-4073-BB2A-348CE1B00010}\r\n\t\t{ED85304F-6D46-409B-AD2F-175522A54444} = {864A9013-93AC-4073-BB2A-348CE1B00010}\r\n\t\t{EE0834BA-89F1-4099-8FAD-CC31AA8914E9} = {A79411F9-60B3-46C8-8981-6905D9B9F74C}\r\n\t\t{99C82F36-74DE-4ED1-B9D5-CE044FC517AC} = {A79411F9-60B3-46C8-8981-6905D9B9F74C}\r\n\t\t{06739A61-1B1C-4FC3-8DEF-926B10FACB28} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{FBB17215-CDCE-4FFA-B10A-EA1B320C8638} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{F278A2F7-52FF-40CD-B16D-4D82F7DFA8C3} = {A79411F9-60B3-46C8-8981-6905D9B9F74C}\r\n\t\t{C6C9C0AE-0900-4F21-86C6-2202E44A6013} = {C557CE9D-81EE-4EB3-AB94-B9F9CB2FA19A}\r\n\t\t{D45E8A40-22A3-44F5-90EA-D42D5D7A522B} = {A79411F9-60B3-46C8-8981-6905D9B9F74C}\r\n\tEndGlobalSection\r\n\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n\t\tSolutionGuid = {1537AED0-2BB3-4EC3-B2CB-06E22C23B002}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "src/CodeGenerator/CodeGenerator.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <OutputType>Exe</OutputType>\r\n    <TargetFramework>net8.0</TargetFramework>\r\n    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>\r\n    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/CodeGenerator/CompilerServices.cs",
    "content": "﻿using System;\nusing System.CodeDom.Compiler;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\nusing Microsoft.CSharp;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\n\nnamespace CodeGenerator\n{\n\n    public static class CompilerServices\n    {\n\n        //public static string CompilerExecutablePath = @\".\\csc.exe\";\n\n        /// <summary>\n        /// Returns compiled assembly from given source code lines.\n        /// Specify all dlls that need to be referenced when compiling (/r).\n        /// </summary>\n        public static Assembly CompileAssembly(\n            IEnumerable<string> sourceLines,\n            IEnumerable<string> dllsToReference,\n            string tmpDirectoryName,\n            out string[] errors\n            )\n        {\n            var sb = new StringBuilder();\n            foreach(var line in sourceLines) sb.AppendLine(line);\n            var syntaxTree = CSharpSyntaxTree.ParseText(sb.ToString());\n\n            var dir = Path.GetDirectoryName(typeof(CompilerServices).Assembly.Location);\n\n            var references =\n                AppDomain.CurrentDomain.GetAssemblies()\n                    .Concat(new[] { typeof(System.Xml.Linq.XName).Assembly })\n                    .Distinct()\n                    .Select(a => {\n                        if(String.IsNullOrWhiteSpace(a.Location)) return null;\n                        try { return MetadataReference.CreateFromFile(a.Location); }\n                        catch(Exception) { return null; }\n                    })\n                    .Where(r => r != null).ToArray();\n            //\n            // var references =\n            //     dllsToReference\n            //         .Select(dll => {\n            //             if(File.Exists(Path.Combine(dir, dll))) return MetadataReference.CreateFromFile(dll);\n            //             else {\n            //                 try \n            //                 {\n            //                     var aa = Assembly.Load(dll);\n            //                     return MetadataReference.CreateFromFile(aa.Location);\n            //                 }\n            //                 catch(Exception) {\n            //                     return null;\n            //                 }   \n            //             }\n            //         })\n            //         .Where(a => a != null)\n            //         .ToArray();\n\n            CSharpCompilation compilation = CSharpCompilation.Create(\n                Guid.NewGuid().ToString(),\n                new[] { syntaxTree },\n                references,\n                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));\n\n            using (var dllStream = new MemoryStream())\n            using (var pdbStream = new MemoryStream())\n            {\n                var emitResult = compilation.Emit(dllStream, pdbStream);\n                if (emitResult.Success)\n                {\n                    errors = Array.Empty<string>();\n                    return Assembly.Load(dllStream.ToArray());\n                }\n                else {\n                    errors = emitResult.Diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).Select(m => m.GetMessage()).ToArray();\n                    return null;\n                }\n            }\n        }\n\n\n    }\n\n}\n"
  },
  {
    "path": "src/CodeGenerator/InternalsVisibleTo.cs",
    "content": "using System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"Aardvark.Base.Tests\")]\n"
  },
  {
    "path": "src/CodeGenerator/Program.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\n\r\nnamespace CodeGenerator\r\n{\r\n    class Program\r\n    {\r\n        private struct TaskPattern\r\n        {\r\n            public string TemplateEnding;\r\n            public string AutoEnding;\r\n        }\r\n\r\n        private static readonly TaskPattern[] c_patterns = new[]\r\n            {\r\n                new TaskPattern\r\n                {\r\n                    TemplateEnding = \"_template.cs\",\r\n                    AutoEnding = \"_auto.cs\",\r\n                },\r\n                new TaskPattern\r\n                {\r\n                    TemplateEnding = \"_template.fs\",\r\n                    AutoEnding = \"_auto.fs\",\r\n                },\r\n                new TaskPattern\r\n                {\r\n                    TemplateEnding = \"_template.cl\",\r\n                    AutoEnding = \"_auto.cl\",\r\n                },\r\n            };\r\n\r\n        private const string c_generatorEnding = \"_generator.cs\";\r\n\r\n        private struct Task\r\n        {\r\n            public string TemplateFileName;\r\n            public string OutputFileName;\r\n            public string Base;\r\n            public string Report;\r\n            // public bool OnlyPerformIfOutputFileDoesNotExist;\r\n        }\r\n\r\n        private static bool IsOlderThan(string fileName1, string fileName2)\n        {\n            return File.GetLastWriteTimeUtc(fileName1) < File.GetLastWriteTimeUtc(fileName2);\n        }\n\n        private static void ShowUsage()\n        {\n            Console.Error.WriteLine(\n                \"Usage: CodeGenerator [-f|--force] [<directory>|<config.conf>|<template> <output>]\");\n        }\n\n        [STAThread]\n        public static void Main(string[] args)\n        {\n            Environment.Exit(Run(args));\n        }\n\n        internal static int Run(string[] args)\n        {\n            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;\n\n            try\n            {\n                var tasks = new List<Task>();\n                var positionalArgs = new List<string>();\n                string dir = null;\n                bool force = false;\n                bool writeGenerator = true;\n\n                foreach (var arg in args)\n                {\n                    switch (arg)\n                    {\n                        case \"-f\":\n                        case \"--force\":\n                            force = true;\n                            break;\n\n                        default:\n                            positionalArgs.Add(arg);\n                            break;\n                    }\n                }\n\n                if (positionalArgs.Count == 0)\n                {\n                    dir = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location),\"..\", \"..\", \"..\");\n                }\n                else if (positionalArgs.Count == 1)\n                {\n                    if (positionalArgs[0].EndsWith(\".conf\"))\n                    {\n                        foreach (var entry in ParseConfigFile(positionalArgs[0]))\n                        {\n                            tasks.Add(new Task\n                            {\n                                TemplateFileName = entry.TemplateFileName,\n                                OutputFileName = entry.OutputFileName\n                            });\n                        }\n                    }\n                    else if (Directory.Exists(positionalArgs[0]))\n                    {\n                        dir = positionalArgs[0];\n                    }\n                    else\n                    {\n                        ShowUsage();\n                        return 1;\n                    }\n                }\n                else if (positionalArgs.Count == 2)\n                {\n                    tasks.Add(new Task\n                    {\n                        TemplateFileName = positionalArgs[0],\n                        OutputFileName = positionalArgs[1]\n                    });\n                }\n                else\n                {\n                    ShowUsage();\n                    return 1;\n                }\n\n                if (dir != null)\n                {\n                    foreach (var pattern in c_patterns)\n                    {\n                        var templates = Directory.GetFiles(dir, \"*\" + pattern.TemplateEnding,\n                                                           SearchOption.AllDirectories);\n                        foreach (var name in templates)\n                        {\n                            var baseName = name.Substring(0, name.Length - pattern.TemplateEnding.Length);\n                            tasks.Add(new Task\n                            {\n                                TemplateFileName = name,\n                                Report = baseName.Substring(dir.Length),\n                                Base = baseName,\n                                OutputFileName = baseName + pattern.AutoEnding,\n                            });\n                        }\n                    }\n                }\n\n                foreach (var task in tasks)\n                {\n                    string report = task.Report ?? task.OutputFileName;\n\n                    if (!force &&\n                        task.TemplateFileName != null &&\n                        IsOlderThan(task.TemplateFileName, task.OutputFileName))\n                    {\n                        Console.WriteLine(\"- {0}\", report);\n                        continue;\n                    }\n                    Console.WriteLine(\"# {0}\", report);\n\n                    string input = File.ReadAllText(task.TemplateFileName);\n\n                    var engine = new TemplateProcessor() { Input = input };\n\n                    engine.CreateGenerator();\n\n                    if (writeGenerator)\n                    {\n                        var baseName = task.Base ?? task.OutputFileName;\n                        var genName = baseName + c_generatorEnding;\n                        var genReport = report + c_generatorEnding;\n                        File.WriteAllText(genName, engine.GeneratorSourceCode);\n                        Console.WriteLine(\"GENERATOR {0}\", genReport);\n                    }\n                    engine.CompileAndRunGenerator();\n                    if (engine.Result == null)\n                    {\n                        //File.WriteAllText(task.OutputFileName + \".debug.cs\", engine.GeneratorSourceCode);\n                        Console.WriteLine(\"WARNING: processing template failed!\");\n                    }\n                    else\n                    {\n                        int lineCountInput = engine.Input.Split('\\n').Count();\n                        int lineCountResult = engine.Result.Split('\\n').Count();\n                        double ratio = lineCountResult / (double)lineCountInput;\n                        Console.WriteLine(\"{0} lines out of {1} lines (factor {2:0.00})\",\n                            lineCountResult, lineCountInput, ratio\n                            );\n\n                        File.WriteAllText(task.OutputFileName, engine.Result);\n                    }\n                    Console.WriteLine(\"+\");\n                }\n\n                return 0;\n            }\n            catch (InvalidDataException e)\n            {\n                Console.Error.WriteLine(e.Message);\n                return 1;\n            }\n        }\n\n        internal static IReadOnlyList<(string TemplateFileName, string OutputFileName)> ParseConfigFile(string configFileName)\n        {\n            var result = new List<(string TemplateFileName, string OutputFileName)>();\n\n            int lineNumber = 0;\n            foreach (var rawLine in File.ReadAllLines(configFileName))\n            {\n                lineNumber++;\n                var line = rawLine.Trim();\n\n                if (line.Length == 0 || line.StartsWith(\"#\"))\n                    continue;\n\n                var parts = line.Split(new[] { ' ', '\\t' }, StringSplitOptions.RemoveEmptyEntries);\n                if (parts.Length != 2)\n                {\n                    throw new InvalidDataException(\n                        $\"Invalid config row in {configFileName} at line {lineNumber}: expected '<template> <output>' but got '{rawLine}'.\");\n                }\n\n                result.Add((parts[0], parts[1]));\n            }\n\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/CodeGenerator/README.md",
    "content": "# CodeGenerator\n\n## Purpose\n\nThe CodeGenerator is a code expansion tool that transforms `*_template.cs` files into `*_auto.cs` files with type-specific variants. It uses a custom template syntax embedded in comments to generate repetitive code for multiple numeric types (int, float, double, long, etc.), avoiding manual duplication.\n\nThe generator processes template files containing:\n- **C# code generation directives** (comment-based syntax)\n- **Placeholder expressions** that expand for each numeric type\n- **Custom template syntax** with embedding code that generates code\n\nThis approach keeps the codebase DRY (Don't Repeat Yourself) by maintaining a single template while automatically producing variants for all supported types.\n\n## How to Run\n\n### Using the shell script (Unix/Linux/macOS)\n```bash\n./generate.sh\n./generate.sh --force\n```\n\n### Using the command script (Windows)\n```cmd\ngenerate.cmd\ngenerate.cmd --force\n```\n\n### Using dotnet directly\n```bash\ndotnet run --project src/CodeGenerator/CodeGenerator.csproj\ndotnet run --project src/CodeGenerator/CodeGenerator.csproj -- --force\ndotnet run --project src/CodeGenerator/CodeGenerator.csproj -- path/to/tasks.conf\n```\n\nBoth wrapper scripts forward additional CLI arguments to `CodeGenerator.dll`.\n\n### Using a `.conf` file\n\nWhen invoked with a single `.conf` argument, CodeGenerator reads one generation task per line:\n\n```text\npath/to/template_template.cs path/to/output_auto.cs\npath/to/other_template.fs path/to/other_auto.fs\n```\n\nRules:\n- Each non-empty row must contain exactly two whitespace-separated paths: `<template> <output>`\n- Blank lines are ignored\n- Comment-only lines starting with `#` are ignored\n- Malformed rows fail with a clear error message and a nonzero exit code\n\n## When to Run\n\nRun the code generator **immediately after modifying any `*_template.cs` file**. The generator:\n- Detects which template files have been modified since their output was last generated\n- Only regenerates files that need updating (skips unchanged templates)\n- Can regenerate everything with `-f` / `--force`, regardless of timestamps\n- Must be run before building/testing to ensure generated code is up-to-date\n\nUse `--force` when you want a deterministic full regeneration pass, for example in CI when verifying that committed `*_auto.*` files match their templates.\n\nThe scripts print:\n- `#` prefix: Template is being processed (newer than output)\n- `-` prefix: Template is unchanged (output is up-to-date, skipped)\n\n## Input Files\n\nTemplate files matching the pattern `*_template.cs` throughout the `src/` directory. These files contain:\n\n1. **Regular C# code** that appears in the output as-is\n2. **Generator directives** in special comments:\n   - `/*# ... */` — inline code generation\n   - `/*CLASS# ... */` — code appended to a helper class\n   - `/*USING# ... */` — using statements for the generated code\n   - `//# ... */` — single-line generation directives\n   - `//BEGIN CLASS#` / `//END CLASS#` — switch output to/from class section\n3. **Placeholder expressions** using `__ ... __` syntax that are evaluated during generation\n\nExample template snippet:\n```csharp\n/*# var types = new[] { \"int\", \"float\", \"double\" }; */\n/*# foreach(var type in types) { */\n    public __type__ Max(__type__ a, __type__ b) => a > b ? a : b;\n/*# } */\n```\n\n## Output Files\n\nGenerated files matching the pattern `*_auto.cs`. These files:\n- **DO NOT EDIT MANUALLY** — all edits are lost on regeneration\n- Contain a header comment: `// AUTO GENERATED CODE - DO NOT CHANGE!`\n- Are fully expanded variants for each numeric type\n- Include all variations generated from the template\n\nExample output (from above template):\n```csharp\npublic int Max(int a, int b) => a > b ? a : b;\npublic float Max(float a, float b) => a > b ? a : b;\npublic double Max(double a, double b) => a > b ? a : b;\n```\n\n## How It Works (Technical Overview)\n\n### 1. Template Discovery\nThe CodeGenerator scans the project directory for all `*_template.cs`, `*_template.fs`, and `*_template.cl` files (supporting C#, F#, and OpenCL).\n\n### 2. Template Parsing\nEach template is parsed by `TemplateProcessor` using a custom syntax:\n- **Comment-based directives** are extracted and executed as C# code\n- **Placeholder expressions** (`__ ... __`) are evaluated and replaced\n- **Output sections** (Code, Using, Class) are accumulated\n\n### 3. Generator Creation\nA dynamic C# generator class is created from the template:\n```csharp\npublic static class SourceGenerator\n{\n    public static StringBuilder ___sb = new StringBuilder();\n    public static string Generate()\n    {\n        // Generated code from template here\n        return ___sb.ToString();\n    }\n}\n```\n\n### 4. Compilation & Execution\n- The generator code is compiled on-the-fly using Roslyn (Microsoft.CodeAnalysis)\n- The compiled `Generate()` method is invoked via reflection\n- Output is captured and written to the `*_auto.cs` file\n\n### 5. Assembly References\nThe generator can reference these assemblies during compilation:\n- `CodeGenerator.dll`\n- `System.Runtime.dll`\n- `System.Linq.dll`\n- `System.Collections.dll`\n- `System.Xml.dll` / `System.Xml.Linq.dll`\n- `Aardvark.Base.dll` (for custom types and helpers)\n\n## Generated Files Summary\n\nBelow is a representative sample of template → generated file mappings:\n\n| Template | Generated File | Purpose |\n|----------|---|---------|\n| `src/Aardvark.Base/Math/Vectors/Vector_template.cs` | `Vector_auto.cs` | Vector struct variants (V2i, V3i, V2f, V3f, V2d, V3d, etc.) |\n| `src/Aardvark.Base/Math/Trafos/Matrix_template.cs` | `Matrix_auto.cs` | Matrix struct variants for different sizes and types |\n| `src/Aardvark.Base/Math/Trafos/Rot3_template.cs` | `Rot3_auto.cs` | 3D rotation struct for multiple numeric types |\n| `src/Aardvark.Base.IO/BinaryReadingCoder_template.cs` | `BinaryReadingCoder_auto.cs` | Serialization variants for numeric types |\n| `src/Aardvark.Base/Geometry/IntersectionTests_template.cs` | `IntersectionTests_auto.cs` | Geometric intersection test functions for float/double |\n\n## Complete Generated Files List\n\nAll `*_auto.cs` files (97 total):\n\n**Aardvark.Base:**\n- Math/Vectors: `Vector_auto.cs`, `VectorIEnumerableExtensions_auto.cs`, `VectorTypeConverter_auto.cs`\n- Math/Trafos: `Matrix_auto.cs`, `M33_auto.cs`, `M44_auto.cs`, `Rot2_auto.cs`, `Rot3_auto.cs`, `Affine_auto.cs`, `Euclidean_auto.cs`, `Similarity_auto.cs`, `Scale_auto.cs`, `Shift_auto.cs`, `Trafo_auto.cs`\n- Math/Base: `Fun_auto.cs`, `Complex_auto.cs`, `Quaternion_auto.cs`, `AliasTable_auto.cs`\n- Math/Colors: `Color_auto.cs`\n- Math/RangesBoxes: `Box_auto.cs`, `OrientedBox_auto.cs`\n- Math/Interfaces: `ISize_auto.cs`\n- Geometry/Types: `Geometry_auto.cs`, `Geometry1i_auto.cs`, `Vector_auto.cs`, `Box_auto.cs`, `Capsule3_auto.cs`, `Circle2_auto.cs`, `Circle3_auto.cs`, `Cone3_auto.cs`, `Conic2_auto.cs`, `Cylinder3_auto.cs`, `Ellipse_auto.cs`, `Ellipse2_auto.cs`, `Ellipse3_auto.cs`, `Hull2_auto.cs`, `Hull3_auto.cs`, `Line2_auto.cs`, `Line3_auto.cs`, `Plane2_auto.cs`, `Plane3_auto.cs`, `Polygon2_auto.cs`, `Polygon3_auto.cs`, `PolygonExtensions_auto.cs`, `IImmutablePolygonExtensions_auto.cs`, `Quad2_auto.cs`, `Quad3_auto.cs`, `Quadric_auto.cs`, `Ray2_auto.cs`, `Ray3_auto.cs`, `Sphere3_auto.cs`, `Torus3_auto.cs`, `Triangle2_auto.cs`, `Triangle3_auto.cs`\n- Geometry/Relations: `LinearCombination_auto.cs`, `Orthogonality_auto.cs`, `Parallelism_auto.cs`, `SubPrimitives_auto.cs`\n- Geometry/Interfaces: `IBoundingBox_auto.cs`\n- Geometry/Algorithms: `Algorithms_auto.cs`, `ClippingFunctions_auto.cs`, `IntersectionTests_auto.cs`, `SpecialPoints_auto.cs`\n- Sorting: `Sorting_auto.cs`\n- Delegates: `Delegates_auto.cs`\n- Extensions: `FuncActionExtensions_auto.cs`, `SequenceExtensions_auto.cs`\n- Symbol: `Dict_auto.cs`\n- Tup: `Tuples_auto.cs`\n\n**Aardvark.Base.IO:**\n- `BinaryReadingCoder_auto.cs`, `BinaryWritingCoder_auto.cs`, `ICoder_auto.cs`, `StreamCodeReader_auto.cs`, `StreamCodeWriter_auto.cs`, `TypeCoder_auto.cs`, `XmlReadingCoder_auto.cs`, `XmlWritingCoder_auto.cs`\n\n**Aardvark.Base.Tensors.CSharp:**\n- `Tensor_auto.cs`, `TensorExtensions_auto.cs`, `TensorMathExt_auto.cs`\n- Tensors: `Accessors_auto.cs`\n\n**Benchmarks:**\n- `Indexers_auto.cs`\n- Math: `AngleBetween_auto.cs`, `DistanceRot3_auto.cs`, `IntegerPower_auto.cs`, `PowerOfTwo_auto.cs`, `Rot3GetEuler_auto.cs`, `RotateInto_auto.cs`\n- Math/Tensors: `MatrixOrthogonalize_auto.cs`\n\n## Implementation Details\n\n### TemplateProcessor Class\nLocated in `TemplateProcessor.cs`, handles:\n- Parsing template syntax using a state machine\n- Managing output sections (Code, Using, Class)\n- Creating the dynamic generator class from template directives\n- Compiling and executing the generator\n\n### Program Class\nLocated in `Program.cs`, handles:\n- Scanning directories for template files\n- Checking modification times to skip unchanged templates\n- Managing generation tasks\n- Writing output files and diagnostic reports\n\n### CompilerServices Class\nLocated in `CompilerServices.cs`, handles:\n- Compiling generated C# code on-the-fly using Roslyn\n- Resolving assembly references dynamically\n- Capturing compilation diagnostics (errors/warnings)\n\n## Example: Generating Vector Types\n\n**Template** (`Vector_template.cs` excerpt):\n```csharp\n/*# var types = new[] { typeof(int), typeof(float), typeof(double) }; */\n/*# foreach(var t in types) {\n    var typeName = \"V\" + dimensions + t.Name[0];\n*/\npublic struct __typeName__\n{\n    public __t.Name__ X, Y, Z;\n}\n/*# } */\n```\n\n**Generated** (`Vector_auto.cs` excerpt):\n```csharp\npublic struct V3i\n{\n    public int X, Y, Z;\n}\npublic struct V3f\n{\n    public float X, Y, Z;\n}\npublic struct V3d\n{\n    public double X, Y, Z;\n}\n```\n\n## Notes\n\n- The generator is intentionally lightweight and uses reflection-based runtime generation to keep build times reasonable\n- Template syntax is C#-compatible; any valid C# expressions can be used in placeholders\n- Output files use \"AUTO GENERATED CODE - DO NOT CHANGE!\" header to signal automated generation\n- The generator is run explicitly via `generate.sh`, `generate.cmd`, or direct `dotnet run` invocation when templates need regeneration\n"
  },
  {
    "path": "src/CodeGenerator/TemplateProcessor.cs",
    "content": "﻿using System;\nusing System.CodeDom.Compiler;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing Aardvark.Base;\n\nnamespace CodeGenerator\n{\n\n    public class TemplateProcessor : TextParser<TemplateProcessor>\n    {\n        public string Input;\n\n        public StringBuilder Code;\n        public StringBuilder Using;\n        public StringBuilder Class;\n\n        public StringBuilder Active;\n\n        public string GeneratorSourceCode;\n        public string Result;\n\n        #region Constructor\n\n        public TemplateProcessor()\n        {\n            Input = null;\n\n            Code = new StringBuilder();\n            Using = new StringBuilder();\n            Class = new StringBuilder();\n            Active = Code;\n\n            GeneratorSourceCode = null;\n            Result = null;\n        }\n\n        #endregion\n\n        #region Constants\n\n        public string StandardUsing = @\"using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.IO;\nusing System.Xml.Linq;\nusing CodeGenerator;\nusing Aardvark.Base;\nusing Aardvark.Base.CSharp;\n\";\n\n        public string Prologue = @\"\npublic static class SourceGenerator\n{\n    public static StringBuilder ___sb = new StringBuilder();\n    public static Func<string, string> Filter = null;\n    public static Func<string, string> ___Filter = s => Filter == null ? s : Filter(s);\n    public static Action<string> Out = s => { ___sb.Append(___Filter(s)); };\n    public static string Generate()\n    {\n\";\n\n        public string StandardClass = @\"\n        return ___sb.ToString();\n    }\n\";\n\n        public string Epilogue = @\"\n}\n\";\n\n        #endregion\n\n        #region Operations\n\n        public void Perform()\n        {\n            CreateGenerator();\n            CompileAndRunGenerator();\n        }\n\n        public void CreateGenerator() { CreateGenerator(null); }\n\n        public void CreateGenerator(string injectAfterPrologue)\n        {\n            if (injectAfterPrologue == null) injectAfterPrologue = \"\";\n\n            Parse(new Text(Input), this, State, new Nd());\n\n            GeneratorSourceCode = StandardUsing\n                                    + Using.ToString()\n                                    + Prologue\n                                    + injectAfterPrologue\n                                    + Code.ToString()\n                                    + StandardClass\n                                    + Class.ToString()\n                                    + Epilogue;\n            // ReportUsings();\n        }\n\n        public void CompileAndRunGenerator()\n        {\n            var lines = GeneratorSourceCode.Split('\\n');\n            var generatorAssembly = CompilerServices.CompileAssembly(\n                GeneratorSourceCode.IntoArray(),\n                new string[] {\n                    \"CodeGenerator.dll\",\n                    \"System.Runtime.dll\",\n                    \"System.Linq.dll\",\n                    \"System.Collections.dll\",\n                    \"System.Xml.dll\",\n                    \"System.Xml.Linq.dll\",\n                    \"Aardvark.Base.dll\"\n                    //\"System.ValueTuple.dll\"\n                },\n                \".\", out string[] errors);\n            if (generatorAssembly == null)\n            {\n                Console.WriteLine(\"WARNING: build of generator failed!\");\n                foreach (var x in errors) Console.WriteLine(\"{0}\", x);\n                Result = null;\n                return;\n            }\n            var generatorFun = generatorAssembly.GetTypes().First().GetMethods().First();\n            Result = (string)generatorFun.Invoke(null, null);\n        }\n\n        #endregion\n\n        #region Private Methods\n\n        private void ReportUsings()\n        {\n            var nonSystemUsings = FilterNonSystemUsingsIntoList(Using.ToString());\n            foreach (var use in nonSystemUsings) Console.WriteLine(\"USING {0};\", use);\n        }\n\n        private static List<string> FilterNonSystemUsingsIntoList(string usings)\n        {\n            var genUse = from use in\n                             (from rawUse in usings.Split(\n                                             new string[] { Environment.NewLine },\n                                             StringSplitOptions.RemoveEmptyEntries)\n                              let trimUse = rawUse.Trim()\n                              where trimUse.StartsWith(\"using \")\n                                      && trimUse.EndsWith(\";\")\n                              select trimUse.Substring(6, trimUse.Length - 7).Trim())\n                         where !use.StartsWith(\"System\")\n                         select use;\n            return genUse.ToList();\n        }\n\n        #endregion\n\n        #region Parser States\n\n        private class Nd { }\n\n        private static readonly State<TemplateProcessor, Nd> State\n                                    = new Cases<TemplateProcessor, Nd>\n            {\n                { @\"/\\*CLASS#\", (p, n) => { p.Skip(); p.Class.Append(p.GetToStartOf(\"*/\"));\n                                            p.Skip(); return State; } },\n                { @\"/\\*USING#\", (p, n) => { p.Skip(); p.Using.Append(p.GetToStartOf(\"*/\"));\n                                            p.Skip(); return State; } },\n                { @\"/\\*#\",      (p, n) => { p.Skip(); p.Active.Append(p.GetToStartOf(\"*/\"));\n                                            p.Skip(); return State; } },\n                { @\"//BEGIN\\sCLASS#\", (p, n) => { p.Skip(); p.SkipToEndOfOrEnd('\\n');\n                                                  p.Active = p.Class; return State; },\n                                        (p, n, t) => t.TrimmedAtEnd(CharFun.IsSpaceOrTab) },\n                { @\"//END\\sCLASS#\",   (p, n) => { p.Skip(); p.SkipToEndOfOrEnd('\\n');\n                                                  p.Active = p.Code; return State; },\n                                        (p, n, t) => t.TrimmedAtEnd(CharFun.IsSpaceOrTab) },\n                { @\"//#\",       (p, n) => { p.Skip(); p.Active.Append(p.GetToEndOfOrEnd('\\n'));\n                                            return State; },\n                                // indented //# comments eat the preceeding indentation\n                                // by trimming it from the preceeding text:\n                                (p, n, t) => t.TrimmedAtEnd(CharFun.IsSpaceOrTab) },\n                { @\"__\",        (p, n) => { p.Skip();\n                                            p.Active.Append(string.Format(\n                                                \"___sb.Append(({0}).ToString());\",\n                                                p.GetToStartOf(\"__\")));\n                                            p.Skip(); return State; } },\n            }.ToState(  (p, n, t) =>    {\n                                            if (!t.IsEmpty)\n                                            {\n                                                p.Active.Append(\n                                                    string.Format(\"___sb.Append(___Filter(@\\\"{0}\\\"));\",\n                                                                    t.ToString().Replace(\"\\\"\", \"\\\"\\\"\")));\n                                            }\n                                        });\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/CodeGenerator/app.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<configuration>\r\n    <startup> \r\n        <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.7.1\" />\r\n    </startup>\r\n</configuration>"
  },
  {
    "path": "src/CodeGenerator/paket.references",
    "content": "group CodeGenerator\n\nMicrosoft.NETFramework.ReferenceAssemblies\nMicrosoft.CodeAnalysis.CSharp"
  },
  {
    "path": "src/Demo/CoreTest/CoreTest.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n    <WarnOn>3389;3390;3395</WarnOn>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"Program.fs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Incremental\\Aardvark.Base.Incremental.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors.CSharp\\Aardvark.Base.Tensors.CSharp.csproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>"
  },
  {
    "path": "src/Demo/CoreTest/Program.fs",
    "content": "﻿// Learn more about F# at http://fsharp.org\n\nopen Aardvark.Base\n\n\nlet svd() =\n    let rand = RandomSystem()\n    let mutable evil = None\n    let mk() =\n        let morig =\n            (Trafo2d.Rotation(rand.UniformDouble()*Constant.PiTimesTwo))\n                //Trafo2d.Translation(rand.UniformV2d()))\n                .Forward\n        let m = morig\n        let vs = morig.ToArray()\n\n        match SVD.decompose m with\n        | None -> failwith \"none\"\n        | Some (u,s,vt) -> \n            let mutable res = true\n            let mt = u * s * vt\n            for i in 0..vs.Length-1 do\n                let ms = mt.ToArray()\n                if not <| (Fun.ApproximateEquals(vs.[i],ms.[i],1E-8) || Fun.ApproximateEquals(vs.[i],-ms.[i],1E-8)) then\n                    for j in 0..vs.Length-1 do\n                        Log.line \"%.5f ~ %.5f\" vs.[j] ms.[j]\n                    Log.error \"wrong %d\" i\n                    evil <- Some(m)\n                    res <- false\n            res\n\n                    \n    let ct = 100000\n    Log.startTimed \"Running\"\n    Report.Progress(0.0)\n    let mutable res = true\n    let mutable i = 0\n    while i < ct && res do\n        res <- mk()\n        i <- i+1\n        Report.Progress(float i/float ct)\n    Report.Progress(1.0)\n    Log.stop()\n    \n    let m = evil |> Option.get\n    Log.error \"EVIL\"\n    Log.line \"%A\" (SVD.decompose m |> Option.get |> (fun (u,s,vt) -> u*s*vt))\n    Log.error \"EVIL\"\n    Log.line \"%A\" (SVD.decompose m |> Option.get |> (fun (u,s,vt) -> u*s*vt))\n    Log.error \"EVIL\"\n    Log.line \"%A\" (SVD.decompose m |> Option.get |> (fun (u,s,vt) -> u*s*vt))\n    Log.error \"EVIL\"\n    Log.line \"%A\" (SVD.decompose m |> Option.get |> (fun (u,s,vt) -> u*s*vt))\n    Log.error \"EVIL\"\n    Log.line \"%A\" (SVD.decompose m |> Option.get |> (fun (u,s,vt) -> u*s*vt))\n    Log.error \"EVIL\"\n    Log.line \"%A\" (SVD.decompose m |> Option.get |> (fun (u,s,vt) -> u*s*vt))\n    Log.error \"EVIL\"\n    Log.line \"%A\" (SVD.decompose m |> Option.get |> (fun (u,s,vt) -> u*s*vt))\n    Log.error \"EVIL\"\n    Log.line \"%A\" (SVD.decompose m |> Option.get |> (fun (u,s,vt) -> u*s*vt))\n\n\n    Log.line \"ok\"\n\n[<EntryPoint>]\nlet main argv =\n    svd()\n    \n    0 \n"
  },
  {
    "path": "src/Demo/CoreTest/paket.references",
    "content": "FSharp.Core\nAardvark.Build\nFsPickler\nFsPickler.Json\nAardvark.Base.TypeProviders\nFSharp.Data.Adaptive"
  },
  {
    "path": "src/Demo/ExamplesCSharp/ExamplesCSharp.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <OutputType>Exe</OutputType>\r\n    <TargetFramework>net8.0</TargetFramework>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Essentials\\Aardvark.Base.Essentials.csproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Incremental\\Aardvark.Base.Incremental.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Demo/ExamplesCSharp/Program.cs",
    "content": "﻿/* \n\nThe purpose of this program is to demonstrate how to use the Aardvark base libraries in C#.\nC# and F# both compile to IL and therefore compose to some degree, i.e. libraries can be used\nin both directions.\nAardvark.Base is somewhat special because it makes heavy use of F# features which have no direct\nC# equivalent (except for boilerplate). \nAdditionally, our C# interfaces for F# datatypes often lack convenience and idiomatic C# API\n(are not always as complete as the real implementation).\nOne goal of this file is to show the very basic interaction techniques and motivate developers to\ncontribute to the convenience layers to C#.\n\nPS.: please help to improve this tutorial (typos, non-english etc)\n*/\n\nusing CSharp.Data.Adaptive;\nusing FSharp.Data.Adaptive;\nusing System;\nusing System.Linq;\nusing System.Reactive.Linq;\nusing System.Reactive.Subjects;\nusing static Aardvark.Base.CSharpInterop;\n\nnamespace ExamplesCSharp\n{\n    class Program\n    {\n        static void Main(string[] args)\n        {\n            #region Basic Mod usage\n\n            // Create a modref cell. can be changed via side effects\n            var input = new ChangeableValue<int>(10);\n\n            var output = input.Map(x => x * 2);\n\n            Console.WriteLine($\"output was: {output}\");\n            // Prints: output was Aardvark.Base.Incremental.ModModule+MapMod`2[System.Int32,System.Int32]\n            // not what we expected. Since mods are lazy and tostring does not force them we need\n            // to pull the value out of it.\n\n            Console.WriteLine($\"output was: {output.GetValue()}\"); // F# equivalent: Mod.force : aval<'a> -> 'a\n            // output was: 20\n\n            using (Adaptive.Transact)\n            {\n                input.Value = 20;\n            }\n\n            Console.WriteLine($\"output was: {output.GetValue()}\");\n            // output was: 40\n\n            // semantically, output now dependens on input declaratively. \n            // the dependency graph looks like:\n            //   \n            //       (x) => x * 2\n            // input ----------------> output\n            // mods are nodes, and the edges are annotated with transition functions.\n\n            // Users of Rx might see the pattern. outputs is an observer, while input is observable.\n            // so the systems are equivalent ?! but mod must be better - otherwise this tutorial is useless right?\n\n            #endregion\n\n            #region Obserable semantics\n\n            // A modref could be an observable which never ends and has an initial value.\n            var inputObs = new Subject<int>();\n            inputObs.OnNext(10);\n            var outputObs = inputObs.Select(x => x * 2);\n\n            var globalStore = 0;\n            var sideEffectToObserve = outputObs.Subscribe(x => globalStore = x);\n\n            Console.WriteLine($\"outputObs was: {globalStore}\");\n            // outputObs was: 0\n            // unexpected? no. this is due to subscription semantics.\n            // Note: ReplaySubject instead of subject has right semantics although i have doubts about memory leaks.\n\n            inputObs.OnNext(10);\n            Console.WriteLine($\"outputObs was: {globalStore}\");\n            // outputObs was: 20\n\n            inputObs.OnNext(20);\n            Console.WriteLine($\"outputObs was: {globalStore}\");\n            // outputObs was: 40\n\n\n            // what happens if we have data flow graphs with sinks (2 ingoing edges conceptually)\n\n            var inputA = new Subject<int>();\n            var inputB = new Subject<int>();\n\n            var reexCount = 0;\n\n            inputA.Merge(inputB).Subscribe(x =>\n            {\n                reexCount++;\n                Console.WriteLine($\"a+b was: {x}\");\n            });\n\n            inputA.OnNext(1);\n            inputB.OnNext(2);\n            Console.WriteLine($\"reexCount was: {reexCount}\");\n            // reexCount was: 2\n\n            // did you expect 2? of course. this is the semantics of merge.\n\n            // what iff we only want to have a batch change, say, change 2 inputs simultationusly? \n            // then we need different semantics. \n            var inputA3 = new Subject<int>();\n            var inputB3 = new Subject<int>();\n\n            reexCount = 0;\n            inputA3.SelectMany(a =>\n                inputB3.Select(b =>\n                {\n                    reexCount++;\n                    return a + b;\n                }\n                )\n            ).Subscribe(r =>\n                Console.WriteLine($\"result was: {r} reexCount was: {reexCount}\")\n            );\n\n            inputA3.OnNext(1);\n            inputB3.OnNext(2);\n            // result was: 3 reexCount was: 1\n\n            // If we switch to replay subject we get 2 again...\n            var inputA2 = new ReplaySubject<int>();\n            var inputB2 = new ReplaySubject<int>();\n\n            reexCount = 0;\n            inputA2.SelectMany(a =>\n                inputB2.Select(b =>\n                {\n                    reexCount++;\n                    return a + b;\n                }\n                )\n            ).Subscribe(r =>\n                Console.WriteLine($\"result was: {r} reexCount was: {reexCount}\")\n            );\n\n            inputA2.OnNext(1);\n            inputB2.OnNext(2);\n            // result was: 3 reexCount was: 2\n\n            // Let us see how this looks like in Mod:\n            reexCount = 0;\n            var inputAM = new ChangeableValue<int>(1);\n            var inputBM = new ChangeableValue<int>(2);\n            var aPlusB = inputAM.Map(inputBM, \n                (a, b) => {\n                    reexCount++;\n                    return a + b;\n                });\n\n            Console.WriteLine($\"mod,a+b was: {aPlusB.GetValue()}, reexCount: {reexCount}\");\n            // mod,a+b was: 3, reexCount: 1\n\n            // special note: Select2 was not defined at the time or writing of this tutorial, but\n            // it is available in F#. How could we access the F# verion?\n            var aPlusB2 = FSharp.Data.Adaptive.AValModule.map2(FSharpFuncUtil.Create<int,int,int>((a, b) => a + b), inputAM, inputBM);\n            // steps required: \n            // (1) F# map2 is defined in Mod module. usage Mod.map2 (+) a b\n            // so we need this map module. by convention, modules with colliding type names\n            // are exported with the module suffix. so the function lives in ModModule.\n            // (2) our f# function wants a f# function and not an instance of type System.Func. use a conversion\n            // (3) C# has no real type inference, so most of the time you'll need to annotate stuff.\n            // that is - we just used a f# function with no c# friendly interface in c#.\n            Console.WriteLine($\"mod,a+b was: {aPlusB2.GetValue()}, reexCount: {reexCount}\");\n\n            reexCount = 0;\n            using (Adaptive.Transact)\n            {\n                inputAM.Value = 20;\n                inputBM.Value = 30;\n            }\n\n            Console.WriteLine($\"mod,a+b was: {aPlusB.GetValue()}, reexCount: {reexCount}\");\n            // mod,a+b was: 50, reexCount: 1\n\n            // so we have batch changes in the mod system. but this is cheating, right?\n            // because we used an optimized combinator which does this, right?\n            // we can do a low level implementation instead.\n\n            var aPlusBBind = inputAM.Bind(a => inputBM.Map(b =>\n            {\n                reexCount++;\n                return a + b;\n            }));\n\n            reexCount = 0;\n            using (Adaptive.Transact)\n            {\n                inputAM.Value = 20;\n                inputBM.Value = 30;\n            }\n\n            Console.WriteLine($\"modbind,a+b was: {aPlusBBind.GetValue()}, reexCount: {reexCount}\");\n            // modbind,a+b was: 50, reexCount: 1\n            // interesting. also here we have tight reexecution count.\n\n            reexCount = 0;\n            using (Adaptive.Transact)\n            {\n                inputAM.Value = 20;\n                inputBM.Value = 30;\n            }\n\n            Console.WriteLine($\"modbind2,a+b was: {aPlusBBind.GetValue()}, reexCount: {reexCount}\");\n            // modbind2,a + b was: 50, reexCount:0\n            // aha - we have reexCount=0 because the change was a pseudo change (values changed to old values)\n\n            /*\n            So what is the result of this analysis? Rx has precise semantics. You get what you want. But\n            you need to know how you want it and there are many solutions.\n            So Mod is the same as observable, but can do less because we do not have precise control about\n            reexecution semantics (although semantics seems to be nice, right)?\n            */\n\n            // One could use the mod system as strange implementation of observable of course.\n            var inputEvil = new ChangeableValue<int>(10);\n            var outputEvil = new ChangeableValue<int>(0);\n\n\n\n            var sub = inputEvil.AddCallback(i =>\n            {\n                using (Adaptive.Transact)\n                {\n                    outputEvil.Value = i * 2;\n                }\n            });\n\n            using (Adaptive.Transact)\n            {\n                inputEvil.Value = 20;\n            }\n            Console.WriteLine($\"evilCallback: {outputEvil.GetValue()}\");\n            // evilCallback: 40\n\n            /* so this works. but this is evil.\n            /* this code has no dependency graph. all is modelled via side effects.\n            /* The following list sponsored by gh gives some reasons against callbacks:\n            1) The Mod-system is capable of handling those callbacks but their cost is massive compared to Rx\n            2) Callbacks tend to keep their closure alive(causing memory leaks)\n            3) Callbacks are hard to debug\n            4) Eager evaluation wastes time (by design and especially when using the mod-system)\n            5) Concurrency is not controlled in any way\n            6) Callers of transact suddenly block until their callbacks finish(deadlock scenarios etc.)\n            7) Rx was already invented (so why exploit our system to simulate it) */\n\n            #endregion\n\n            /*\n            So finally, the answer is: NO\n            Rx and Mod is something completly different. \n            - Mod is lazy / Obs pushes values to their subscribers immediately\n            - Mods have batch changes intrinsic to the system / in Obs semantics depends on combinators\n            - Mods build dependency graphs and try to reduce recomputation overhead / Obs don't care about algorithmic complexity, Obs cannot be used to implement adaptive data structures\n            - Mods have on goal: make the outputs consistent iff they are demaned. / Obs populates all values according to the combinators used (e.g. merge)\n            */\n\n            // As a result there are many things which do not fit to observables, others do not fit to mods.\n\n            // Given this list, Mods are particularly not immediately usable for tracking changes manually.\n            var resendOverNetwork = new ChangeableValue<bool>(false);\n            inputEvil.AddCallback(s =>\n            {\n                using (Adaptive.Transact)\n                {\n                    resendOverNetwork.Value = true;\n                }\n            }\n            );\n            resendOverNetwork.AddCallback(_ =>\n            {\n                inputEvil.GetValue().ToString(); // send new contents of inputEvil\n            });\n            // UnsafeRegisterCallbackNoGcRoot is a hack in the system to allow unproblematic side effects\n            // to be coupled with reecution. The exeuction of order of callbacks, especially callbacks\n            // which run callbacks via transactions is highly unspecified. In fact\n            // UnsafeRegisterCallbackNoGcRoot has no defined semantics.\n\n            // One little note: (in the current implementation) all callbacks are executed eventuallly, but maybe to often.\n            // This is very comparable to LINQ mixed with side effects. LINQ has lazy evaluation and using\n            // side effects inside is just nonesense. Fortunately LINQ has no public cheat API --- one cannot\n            // simply \"side-effect\" elements into an existing enumerable sequence \n            // (ok we can but peoply luckily rarely mix side effects with linq because meijer said it is evil [1]).\n            // [1] https://www.youtube.com/watch?v=UuamC0T3hv8 \n            // Of course we could restrict the mod API (by removing callbacks), but\n            // we still wanted ways to do unsafe stuff (in less than 0.01% of the code). \n            // At this point we shall mention that the complete rendering backend works without callbacks,\n            // but rendering things could be as well considered as rather imperative problem.\n            // If you really want to attach callbacks to some mod, maybe either:\n            // (1) the problem does not fit the declarative incremental computation modlel\n            // (2) the problem fits, but some parts of the current solution are not delcarative (either because of (1), because of hacks or other non-declarative parts)\n\n            /* You know might think: \"Why all this complexity. Why not just use Observables where\n            appropriate and ad hoc techniques when they not work as nice as they should. I pretty\n            lived quite good the last years without a mod system and this stuff\".\n            Cases in which the mod system is a good fit can greatly benefit from the usage of mods.\n            The changes are not local, but having a mod system at hand completely changes the way\n            on can structure programs. In fact, i think programming with mods is a completely different\n            paradigm. So Take your time and help us making the libraries better.\n            */\n\n        }\n    }\n}\n\n"
  },
  {
    "path": "src/Demo/ExamplesCSharp/paket.references",
    "content": "group Demo\n\nCSharp.Data.Adaptive\nSystem.Reactive"
  },
  {
    "path": "src/Demo/IncrementalDemo.CSharp/IncrementalDemo.CSharp.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <OutputType>Exe</OutputType>\r\n    <TargetFramework>net8.0</TargetFramework>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <None Include=\"paket.references\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Essentials\\Aardvark.Base.Essentials.csproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Incremental\\Aardvark.Base.Incremental.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Demo/IncrementalDemo.CSharp/Program.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Aardvark.Base;\nusing FSharp.Data.Adaptive;\nusing CSharp.Data.Adaptive;\nusing FSharp.Data.Traceable;\n\nnamespace IncrementalDemo.CSharp\n{\n    class Program\n    {\n        static void SimpleCallbackTest()\n        {\n            var m = new ChangeableValue<int>(0);\n            var d = m.Map(a => 2 * a);\n\n            Report.Begin(\"m = 0\");\n\n            void print ()\n            {\n                Report.Line(\"m * 2 = {0}\", d.GetValue());\n            }\n\n            Report.End();\n\n            Report.Begin(\"m = 3\");\n            using (Adaptive.Transact)\n            {\n                m.Value = 3;\n            }\n            print();\n            Report.End();\n\n\n            Report.Begin(\"m = 1; m = 2\");\n            using (Adaptive.Transact)\n            {\n                m.Value = 1;\n                m.Value = 2;\n            }\n            print();\n            Report.End();\n\n        }\n\n        static void SetContainmentTest()\n        {\n            var set = new ChangeableHashSet<int>(new [] { 1, 2, 3, 4 });\n\n\n            var greater1 = set.Filter(i => i > 1);\n\n\n            var reader = greater1.GetReader();\n\n            Report.Begin(\"set = {1,2,3,4}\");\n            void print()\n            {\n                var deltas = reader.GetChanges(AdaptiveToken.Top);\n                foreach (var d in deltas)\n                {\n                    if (d.Count > 0) Report.Line(\"add {0}\", d.Value);\n                    else Report.Line(\"rem {0}\", d.Value);\n                }\n            }\n            Report.End();\n\n            \n\n            Report.Begin(\"set = {1,2,3,4,5,6}\");\n            using (Adaptive.Transact)\n            {\n                set.Add(5); set.Add(6);\n            }\n            print();\n            Report.End();\n\n            Report.Begin(\"set = {2,4,6}\");\n            using (Adaptive.Transact)\n            {\n                set.Remove(1); set.Remove(3); set.Remove(5);\n            }\n            print();\n            Report.End();\n\n            Report.Begin(\"set = {4,6}\");\n            using (Adaptive.Transact)\n            {\n                set.Remove(2);\n            }\n            print();\n            Report.End();\n\n            Report.Begin(\"set = {4,5,6}\");\n            using (Adaptive.Transact)\n            {\n                set.Add(5);\n            }\n            print();\n            Report.End();\n\n            \n\n        }\n\n\n        static void AdvancedASetTest()\n        {\n            Action<IOpReader<CountingHashSet<int>, FSharpHashSetDelta<int>>> print = (r) =>\n            {\n                var deltas = r.GetChanges(AdaptiveToken.Top);\n                var content = r.State;\n\n                var deltaStr = deltas.Select(d => d.Count > 0 ? string.Format(\"Add {0}\", d.Value) : string.Format(\"Rem {0}\", d.Value)).Join(\", \");\n                var contentStr = content.OrderBy(a => a).Select(i => i.ToString()).Join(\", \");\n\n                Report.Line(\"deltas = [{0}]\", deltaStr);\n                Report.Line(\"content = [{0}]\", contentStr);\n            };\n\n            var i0 = new ChangeableHashSet<int>(new [] { 1, 2, 3 });\n            var i1 = new ChangeableHashSet<int>(new [] { 4, 5 });\n            var i2 = new ChangeableHashSet<int>(new [] { 6, 7 });\n            var input = new ChangeableHashSet<IAdaptiveHashSet<int>>(new [] { i0, i1 });\n\n            var flat = input.SelectMany(a => a);\n\n            Report.Begin(\"initial\");\n            var reader = flat.GetReader();\n            print(reader);\n            Report.End();\n\n\n            Report.Begin(\"add i2; i1.rem 4\");\n            Report.Line(\"all changes (inner and outer) shall be seen consistently\");\n            using (Adaptive.Transact)\n            {\n                input.Add(i2);\n                i1.Remove(4);\n            }\n            print(reader);\n            Report.End();\n\n\n            Report.Begin(\"rem i0; i0.add 10\");\n            Report.Line(\"the set shall not see the (Add 10) operation since i0 was removed as a whole\");\n            using (Adaptive.Transact)\n            {\n                input.Remove(i0);\n                i0.Add(10);\n            }\n            print(reader);\n            Report.End();\n\n\n\n            Report.Begin(\"add i0; i0.rem 10\");\n            Report.Line(\"the set shall not see the (Add 10) operation since 10 was removed from i0\");\n            using (Adaptive.Transact)\n            {\n                input.Add(i0);\n                i0.Remove(10);\n            }\n            print(reader);\n            Report.End();\n\n        }\n\n\n        static void Main(string[] args)\n        {\n            AdvancedASetTest();\n            //SetContainmentTest();\n            //SimpleCallback();\n\n        }\n    }\n}\n"
  },
  {
    "path": "src/Demo/IncrementalDemo.CSharp/paket.references",
    "content": "FSharp.Core\nAardvark.Build\nFsPickler\nAardvark.Base.TypeProviders\nFSharp.Data.Adaptive\nCSharp.Data.Adaptive"
  },
  {
    "path": "src/Demo/PixImageDemo/PixImageDemo.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <OutputType>Exe</OutputType>\r\n    <TargetFramework>net8.0</TargetFramework>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup>\r\n\t<RunWorkingDirectory>$(OutputPath)\\net8.0</RunWorkingDirectory>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Demo/PixImageDemo/Program.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.IO;\n\nnamespace PixImageDemo\n{\n    public static class Program\n    {\n        public static void Main(string[] args)\n        {\n            Aardvark.Base.Aardvark.Init();\n            var dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), \"PixImageDemo\");\n            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);\n\n            //var a = PixImage.Load(@\"C:\\Users\\hs\\Desktop\\Debug\\gah.jpg\");\n            //a.Save(@\"C:\\Users\\hs\\Desktop\\PixImageDemo\\urdar.jpg\");\n\n            PolygonDemo(dir);\n            HowManyColorsIllusion(dir);\n            ResampleDemo(dir);\n            LinearRampDemo(dir);\n            VariousDemos(dir);\n        }\n\n        public static void PolygonDemo(string dir)\n        {\n            // This code produces tiny tiff images that demonstrate the pixel-\n            // level precision of SetMonotonePolygonFilledRaw.\n\n            var tris = new[] {\n                new { Tri = new V2d[] { new V2d(7.7, 2.5), new V2d(11.7, 2.5), new V2d(9.8, 0.8) }, Col = C3b.DarkGreen },\n                new { Tri = new V2d[] { new V2d(11.7, 2.5), new V2d(7.7, 2.5), new V2d(9.5, 5.2) }, Col = C3b.Green },\n                new { Tri = new V2d[] { new V2d(7, 4), new V2d(5, 6), new V2d(8, 7) }, Col = C3b.Green },\n                new { Tri = new V2d[] { new V2d(1, 1), new V2d(2, 4), new V2d(6, 2) }, Col = C3b.Green },\n                new { Tri = new V2d[] { new V2d(7, 4), new V2d(1, 6), new V2d(5, 6) }, Col = C3b.DarkGreen },\n                new { Tri = new V2d[] { new V2d(7, 4), new V2d(8, 7), new V2d(9.5, 5.5) }, Col = C3b.DarkGreen },\n                new { Tri = new V2d[] { new V2d(13.5, 5.5), new V2d(13.5, 7.5), new V2d(15.5, 5.5) }, Col = C3b.Green },\n                new { Tri = new V2d[] { new V2d(15.5, 5.5), new V2d(13.5, 7.5), new V2d(15.5, 7.5) }, Col = C3b.DarkGreen },\n                new { Tri = new V2d[] { new V2d(15, 0), new V2d(13.5, 1.5), new V2d(14.5, 2.5) }, Col = C3b.Green },\n                new { Tri = new V2d[] { new V2d(14.5, 2.5), new V2d(13.5, 1.5), new V2d(14.5, 2.5) }, Col = C3b.Red },\n                new { Tri = new V2d[] { new V2d(7.5, 0.5), new V2d(6.5, 1.5), new V2d(7.5, 1.5) }, Col = C3b.Red },\n                new { Tri = new V2d[] { new V2d(6.3, 0.3), new V2d(5.3, 1.3), new V2d(6.3, 1.3) }, Col = C3b.Red },\n                new { Tri = new V2d[] { new V2d(11.5, 4.5), new V2d(11.5, 6.5), new V2d(12.5, 5.5) }, Col = C3b.DarkGreen },\n            };\n\n            var triImg = new PixImage<byte>(16, 8, 3);\n            var tMat = triImg.GetMatrix<C3b>();\n            Report.BeginTimed(\"polygon demo triangles\");\n            foreach (var t in tris)\n                tMat.SetMonotonePolygonFilledRaw(t.Tri, t.Col);\n            triImg.Save(Path.Combine(dir, \"polygon-triangles.tiff\"));\n            Report.End();\n\n            var polyImg = new PixImage<byte>(10, 10, 3);\n\n            var pMat = polyImg.GetMatrix<C3b>();\n\n            V2d[] poly = new V2d[] {\n                new V2d( 4,  1),\n                new V2d( 1,  3),\n                new V2d( 2,  6),\n                new V2d( 2.1,  6.1),\n                new V2d( 5,  7),\n                new V2d( 8,  5),\n                new V2d( 9,  3),\n            };\n            Report.BeginTimed(\"polygon demo polygon\");\n            pMat.SetMonotonePolygonFilledRaw(poly, C3b.Red);\n            polyImg.Save(Path.Combine(dir, \"polygon-polygon.tiff\"));\n            Report.End();\n        }\n\n        /// <summary>\n        /// Creates Images of an optical illusion that tricks the mind into\n        /// seeing more different colors (4) than are actually present in the\n        /// image (3).\n        /// </summary>\n        public static PixImage<byte> CreateHowManyColorsIllusion(int size, bool parallel = true)\n        {\n            var scale = 1024.0 / size;\n            var delta = 0.5 * (double)(size - 1);\n\n            var pixImage = new PixImage<byte>(size, size, 3);\n\n            var colorMatrix = pixImage.GetMatrix<C3b>();\n\n            var orange = new C3b(255, 150, 0);\n            var magenta = new C3b(255, 0, 255);\n            var bluegreen = new C3b(0, 255, 150);\n            Func<long, long, C3b> pixelFun = (x, y) =>\n            {\n                var xd = scale * (x - delta); var yd = scale * (y - delta);\n                var r = Fun.Sqrt(xd * xd + yd * yd);\n                var phi = Fun.Atan2(yd, xd);\n                var lp1 = phi / Constant.PiTimesFour;\n                var lp2 = phi / Constant.Pi; // TimesTwo;\n                var lr = Fun.Log(r) / Constant.E;\n                var p1 = Fun.Frac(0.05 + 4 * (lr - lp1));\n                var p2 = Fun.Frac(96 * (lr + lp2)); // 64\n                return p2 < 0.5\n                    ? (p1 >= 0.0 && p1 < 0.25 ? bluegreen : orange)\n                    : (p1 >= 0.5 && p1 < 0.75 ? bluegreen : magenta);\n            };\n\n            if (parallel)\n                colorMatrix.SetByCoordParallelY(pixelFun);\n            else\n                colorMatrix.SetByCoord(pixelFun);\n\n            return pixImage;\n        }\n        \n        public static void HowManyColorsIllusion(string dir)\n        {\n            bool parallel = true;\n\n            var sizes = new[] { 512, 576, 648, 768, 864, 1024, 1152, 1296, 1536, 1728 };\n\n            Report.BeginTimed(\"how-many-colors illusions\");\n            foreach (var size in sizes)\n            {\n                Report.BeginTimed(\"size: {0}\", size);\n                var pixImg = CreateHowManyColorsIllusion(size, parallel);\n                pixImg.Save(Path.Combine(dir, \"how-many-colors-\" + size.ToString() + \".png\"));\n                Report.End();\n            }\n            Report.End();\n\n        }\n\n        public static void SetScaledCubicFast(this Matrix<float, C3f> targetMat, Matrix<float, C3f> sourceMat,\n                                          Func<double, Tup4<float>> interpolator)\n        {\n            var dxa = new Tup4<long>[targetMat.SX];\n            var wxa = new Tup4<float>[targetMat.SX];\n            long fx = sourceMat.FX, ex = sourceMat.EX, dx1 = sourceMat.DX;\n            var scaleX = (double)sourceMat.SX / (double)targetMat.SX;\n            double x = 0.5 * scaleX - 0.5;\n            for (long tix = 0, tsx = targetMat.SX; tix < tsx; tix++, x += scaleX)\n            {\n                double xid = Fun.Floor(x); long xi = (long)xid; double xf = x - xid;\n                var dx = Tensor.Index4SamplesClamped(xi, fx, ex, dx1);\n                var dxi = xi * dx1; dx.E0 += dxi; dx.E1 += dxi; dx.E2 += dxi; dx.E3 += dxi;\n                dxa[tix] = dx; wxa[tix] = interpolator(xf);\n            }\n            var dya = new Tup4<long>[targetMat.SY];\n            var wya = new Tup4<float>[targetMat.SY];\n            long o = sourceMat.Origin, fy = sourceMat.FY, ey = sourceMat.EY, dy1 = sourceMat.DY;\n            var scaleY = (double)sourceMat.SY / (double)targetMat.SY;\n            double y = 0.5 * scaleY - 0.5;\n            for (long tiy = 0, tsy = targetMat.SY; tiy < tsy; tiy++, y += scaleY)\n            {\n                double yid = Fun.Floor(y); long yi = (long)yid; double yf = y - yid;\n                var dy = Tensor.Index4SamplesClamped(yi, fy, ey, dy1);\n                var dyi = o + yi * dy1; dy.E0 += dyi; dy.E1 += dyi; dy.E2 += dyi; dy.E3 += dyi;\n                dya[tiy] = dy; wya[tiy] = interpolator(yf);\n            }\n            targetMat.ForeachIndex((tix, tiy, i) =>\n                targetMat[i] = sourceMat.Sample16(dxa[tix], dya[tiy], wxa[tix], wya[tiy],\n                                                  Col.LinCom, Col.LinCom));\n        }\n\n        /// <summary>\n        /// Perform image resampling in software. Shows how to use higher order\n        /// resampling (e.g. Lanczos or Bicubic) on matrices. This is not a very\n        /// fast implementation, but it works on Matrices of arbitrary type!\n        /// </summary>\n        public static void ResampleDemo(string dir)\n        {\n            Report.BeginTimed(\"resample example\");\n            var inImg = CreateHowManyColorsIllusion(300);\n            var inMat = inImg.GetMatrix<C3b>();\n\n            // enlarge by a factor of Pi to see what happens\n            double scale = 1.0 / Constant.Pi;\n            double shift = -13.0;\n\n            var outImg0 = new PixImage<byte>(1024, 1024, 3);\n            var outMat0 = outImg0.GetMatrix<C3b>();\n            var outImg1 = new PixImage<byte>(1024, 1024, 3);\n            var outMat1 = outImg1.GetMatrix<C3b>();\n            var outImg2 = new PixImage<byte>(1024, 1024, 3);\n            var outMat2 = outImg2.GetMatrix<C3b>();\n            var outImg3 = new PixImage<byte>(1024, 1024, 3);\n            var outMat3 = outImg3.GetMatrix<C3b>();\n\n            // create the cubic weighting function. Parameter a=-0.5 results in the cubic Hermite spline.\n            var hermiteSpline = Fun.CreateCubicTup4f(-0.5);\n\n            outMat0.ForeachIndex((x, y, i) =>\n                {\n                    /// Note: LinComRawF in x direction results in a byte color (range 0-255) stored\n                    /// in a C3f. The second Col.LinCom for the y direction does not perform any additional\n                    /// scaling, thus we need to map the \"ByteInFloat\" color back to a byte color at the\n                    /// end (this perfoms clamping). Tensor.Tensor.Index6SamplesClamped clamps to the border\n                    /// region and allows any double pixel address.\n                    outMat0[i] = inMat.Sample36(x * scale + shift, y * scale + shift,\n                                               Fun.Lanczos3f, Fun.Lanczos3f,\n                                               Col.LinComRawF, Col.LinCom,\n                                               Tensor.Index6SamplesClamped, Tensor.Index6SamplesClamped)\n                                                .Map(Col.ByteInFloatToByteClamped);\n\n                    /// Note: LinComRawF in x direction results in a byte color (range 0-255) stored\n                    /// in a C3f. The second Col.LinCom for the y direction does not perform any additional\n                    /// scaling, thus we need to map the \"ByteInFloat\" color back to a byte color at the\n                    /// end (this perfoms clamping). Tensor.Index4SamplesClamped clamps to the border\n                    /// region and allows any double pixel address.\n                    outMat1[i] = inMat.Sample16(x * scale + shift, y * scale + shift,\n                                               hermiteSpline, hermiteSpline,\n                                               Col.LinComRawF, Col.LinCom,\n                                               Tensor.Index4SamplesClamped, Tensor.Index4SamplesClamped)\n                                                .Map(Col.ByteInFloatToByteClamped);\n\n\n                    /// Note here the two Col.LinCom calls perform the clamping immediately. Thus we have\n                    /// Five clamping calls on each sample: 4 on each x-line, and one in the final\n                    /// y-interpolation.\n                    /// Here we have cyclic border handling. Note that Tensor.Index4SamplesCyclic1 only\n                    /// handles one cycle at each side (minus some border pixels), so the addressable\n                    /// range is not quite 3x3 times the size of the original image.\n                    outMat2[i] = inMat.Sample16(x * scale + shift, y * scale + shift,\n                                               hermiteSpline, hermiteSpline,\n                                               Col.LinCom, Col.LinCom,\n                                               Tensor.Index4SamplesCyclic1, Tensor.Index4SamplesCyclic1);\n\n                    outMat3[i] = inMat.Sample4Clamped(x * scale + shift, y * scale + shift, Fun.Lerp, Fun.Lerp);\n                                            //.Map(Col.ByteFromByteInDoubleClamped);\n                });\n\n            outImg0.Save(Path.Combine(dir, \"resample-36clamped.tif\"));\n            outImg1.Save(Path.Combine(dir, \"resample-16clamped.tif\"));\n            outImg2.Save(Path.Combine(dir, \"resample-d16cyclic.tif\"));\n            outImg3.Save(Path.Combine(dir, \"resample-4clamped.tif\"));\n            Report.End();\n        }\n        \n        public static void VariousDemos(string dir)\n        {\n            bool alternative = true;\n\n            // WriteLinearRampImage();\n            // Interpolation();\n\n            Report.BeginTimed(\"various PixImage demos\");\n            // NOTE: in the following comments a byte image is an image that uses a\n            // byte for each channel of each pixel, a float image is an image that uses\n            // a float for each channel of each pixel.\n\n            var colorImage = CreateHowManyColorsIllusion(1024);\n\n            // scaling an image\n            var scaledColorImage = new PixImage<byte>(1280, 800, 3);\n            scaledColorImage.GetMatrix<C3b>().SetScaledCubic(colorImage.GetMatrix<C3b>());\n            scaledColorImage.Save(Path.Combine(dir, \"v-scaled-image.png\"));\n\n            // For shrinking images, interpoation of image values is not the optimal\n            // resampling filter. Here BSpline3 or BSpline5 approximation can be used\n            // which are 3rd order or 5th order approximations of a Gauss filter.\n            var shrunkColorImage = new PixImage<byte>(512, 512, 3);\n            shrunkColorImage.GetMatrix<C3b>().SetScaledBSpline5(colorImage.GetMatrix<C3b>());\n            shrunkColorImage.Save(Path.Combine(dir, \"v-shrunk-image.png\"));\n\n            var largeColorImage = new PixImage<byte>(4096, 4096, 3);\n            largeColorImage.GetMatrix<C3b>().SetScaledLanczos(colorImage.GetMatrix<C3b>());\n            largeColorImage.Save(Path.Combine(dir, \"v-large-lanczos-image.png\"));\n\n\n\n            var scaledColorImage2 = new PixImage<byte>(1280, 800, 3);\n            scaledColorImage2.GetMatrix<C3b>().SetScaledLanczos(colorImage.GetMatrix<C3b>());\n            scaledColorImage.Save(Path.Combine(dir, \"v-scaled-lanczos-image.png\"));\n\n            var smallColorImage = CreateHowManyColorsIllusion(256);\n\n            var nearestScaledImage = new PixImage<byte>(1024, 768, 3);\n            nearestScaledImage.GetMatrix<C3b>().SetScaledNearest(smallColorImage.GetMatrix<C3b>());\n            nearestScaledImage.Save(Path.Combine(dir, \"v-scaled-nearest-image.png\"));\n\n\n            // writing a color png image\n            colorImage.Save(Path.Combine(dir, \"v-color-image.png\"));\n\n            var grayImage = colorImage.ToGrayscalePixImage();\n\n\n            // scaling a grayscale image\n            var scaledGrayImage = new PixImage<byte>(1280, 800, 1);\n            scaledGrayImage.Matrix.SetScaledLanczos(grayImage.Matrix);\n\n            scaledGrayImage.Save(Path.Combine(dir, \"v-scaled-gray-image.png\"));\n\n            // for grayscale and black/white images the Matrix property works\n            grayImage.Matrix.SetLineY(16, 0, 100, 0);\n\n            // writing a grayscale png image\n            grayImage.Save(Path.Combine(dir, \"v-gray-image.png\"));\n\n\n            var gray2colorImage = grayImage.ToPixImage<byte>(Col.Format.BGR);\n            // writing grayxcal image as a color image\n            gray2colorImage.Save(Path.Combine(dir, \"v-gray2color-image.png\"));\n\n            // loading a 8-bit per channel color image\n            var byteImg = new PixImage<byte>(Path.Combine(dir, \"v-color-image.png\"));\n\n            //var byteImg2 = byteImg.Scaled(0.5);\n            //byteImg2.SaveAsImage(Path.Combine(dir, \"v-color-2.png\"));\n            //var byteImg4 = byteImg2.Scaled(0.5);\n            //byteImg4.SaveAsImage(Path.Combine(dir, \"v-color-4.png\"));\n            //var byteImg8 = byteImg4.Scaled(0.5);\n            //byteImg8.SaveAsImage(Path.Combine(dir, \"r-color-8.png\"));\n\n            // retrieving channel matrices from an rgb image\n            var rc = byteImg.GetChannel(Col.Channel.Red);\n            var gc = byteImg.GetChannel(Col.Channel.Green);\n            var bc = byteImg.GetChannel(Col.Channel.Blue);\n\n            // convert 8bit/channel rgb image to 16bit/channel image\n            // var ushortImage = byteImg.ToPixImage<ushort>();\n\n            // ushortImage.Rotated(30 * Constant.RadiansPerDegree, false)\n            //            .SaveAsImage(Path.Combine(odir, \"rotated_30_rgb16.png\"));\n\n            // save 16bit/channel rgb image.\n            // ushortImage.SaveAsImage(Path.Combine(odir, \"rgb8_to_rgb16.tif\"));\n\n            // load 16bit/channel rgb image\n            // var ushortImage2 = new PixImage<ushort>(Path.Combine(odir, \"rgb8_to_rgb16.tif\"));\n\n            // save again as 8bit/channel rgb image\n            // ushortImage2.ToPixImage<byte>().SaveAsImage(Path.Combine(odir, \"rgb8_to_rgb16_to_rgb8.tif\"));\n\n            // building a new rgb image from channel matrices\n            var newImg = new PixImage<byte>(rc, gc, bc);\n\n            // writing an 8-bit per channel png image\n            newImg.Save(Path.Combine(dir, \"v-recombined-color.png\"), PixFileFormat.Png);\n\n            //byteImg.Rotated(60.0 * Constant.RadiansPerDegree)\n            //        .SaveAsImage(Path.Combine(dir, \"v-rotated-60-resized.png\"));\n\n            //byteImg.Rotated(90.0 * Constant.RadiansPerDegree)\n            //        .SaveAsImage(Path.Combine(dir, \"v-rotated-90-resized.png\"));\n\n            //byteImg.Volume.Transformed(ImageTrafo.Rot90).ToPixImage()\n            //        .SaveAsImage(Path.Combine(odir, \"rotated_90_csharp_rgb8.png\"));\n\n            //byteImg.Rotated(180.0 * Constant.RadiansPerDegree)\n            //        .SaveAsImage(Path.Combine(dir, \"v-rotated-180-resized.png\"));\n\n            //byteImg.Volume.Transformed(ImageTrafo.Rot180).ToPixImage()\n            //        .SaveAsImage(Path.Combine(odir, \"rotated_180_csharp_rgb8.png\"));\n\n            //byteImg.Rotated(270.0 * Constant.RadiansPerDegree)\n            //        .SaveAsImage(Path.Combine(dir, \"v-rotated-270-resized.png\"));\n\n            //byteImg.Volume.Transformed(ImageTrafo.Rot270).ToPixImage()\n            //        .SaveAsImage(Path.Combine(odir, \"rotated_270_csharp_rgb8.png\"));\n\n            // loading an 8-bit per channel rgb image directly as a float image\n            var floatImg = new PixImage<float>(Path.Combine(dir, \"v-color-image.png\"));\n\n            // converting a float image to a byte image\n            var floatToByteImg = floatImg.ToPixImage<byte>();\n\n            // saving the converted image in png format\n            floatToByteImg.Save(Path.Combine(dir, \"v-byte2float2byte-color.png\"));\n\n            // color conversion to linear response\n            var linearFloatImg = floatImg.Copy<C3f>(Col.SRGBToLinearSRGB);\n\n            // converting the linear float image to a byte image and saving it in png format\n            linearFloatImg.ToPixImage<byte>().Save(Path.Combine(dir, \"v-linear-color.png\"));\n\n            // loading a byte image\n            var bImg = new PixImage<byte>(Path.Combine(dir, \"v-color-image.png\"));\n\n            byte threshold = 2;\n\n            var isSame = byteImg.Volume.InnerProduct(\n                                bImg.Volume, (b1, b2) => Fun.Abs(b2-b1) < threshold, \n                                true, (equal, pixEqual) => equal && pixEqual, equal => !equal);\n\n\n\n            // replacing a border of 50 pixels by replicating the 1-pixel frame inside\n            // the border outwards\n            bImg.Volume.ReplicateBorder(new Border2l(50));\n\n            // acessing pixels of a byte image as C3b's  \n            var c3bmatrix = bImg.GetMatrix<C3b>();\n\n            // var copiedMatrix = c3bmatrix.Copy();\n\n            var newC3fImage = c3bmatrix.ToPixImage<float>();\n\n            // setting a region in the matrix\n            c3bmatrix.SetRectangleFilled(48, 48, 52, 52, C3b.Black); // min x, min y, max x, max y\n\n            if (alternative)\n            {\n                // this is equivalent to:\n                c3bmatrix.SubMatrix(48, 48, 5, 5).Set(C3b.Black); // start x, start y, size x, size y\n            }\n\n            // accessing a single pixel of the matrix\n            c3bmatrix[50, 50] = C3b.VRVisGreen;\n\n            var size = c3bmatrix.Size;\n\n            // draw a bresenham line\n            c3bmatrix.SetLine(size.X - 50, 50, 50, size.Y - 50, C3b.Blue);\n\n            // draw a bresenham circle\n            c3bmatrix.SetCircle(size.X / 2, size.Y / 2, 50, C3b.Yellow);\n\n            c3bmatrix.SetCircleFilled((size.X * 3) / 4, (size.Y * 3) / 4, 50, C3b.Yellow);\n            c3bmatrix.SetCircleFilled(25, 25, 75, C3b.Yellow);\n\n\n            var cx = size.X / 2; var cy = size.Y / 2;\n\n            for (int i = 0; i < 36; i++)\n            {\n                var alpha = i * 2 * Constant.Pi / 36;\n                var dx = Fun.Cos(alpha);\n                var dy = Fun.Sin(alpha);\n\n                c3bmatrix.SetLineAllTouchedRaw(cx + 64 * dx, cy + 64 * dy, cx + 128 * dx, cy + 128 * dy,\n                                               C3b.Yellow);\n            }\n\n\n\n\n            // writing the image with the replicated border as a png\n            bImg.Save(Path.Combine(dir, \"v-border-drawing.png\"));\n\n            Report.End();\n\n        }\n\n        public static void Difference(string dir)\n        {\n            var idir = Path.Combine(dir, \"in\");\n            var odir = Path.Combine(dir, \"out\");\n            var hiliteImg = new PixImage<float>(Path.Combine(idir, \"ref_hilite.png\"));\n            var luxImg = new PixImage<float>(Path.Combine(idir, \"ref_lux.png\"));\n\n            var diffImg = new PixImage<float>(Col.Format.RGB, hiliteImg.Size);\n\n            diffImg.Volume.SetMap2(hiliteImg.Volume, luxImg.Volume, (a, b) => Fun.Abs(b - a));\n\n            var outImg = diffImg.ToPixImage<ushort>();\n\n            outImg.Save(Path.Combine(odir, \"difference.tiff\"));\n        }\n        \n        public static void CopyTest(string dir)\n        {\n            var idir = Path.Combine(dir, \"in\");\n            var odir = Path.Combine(dir, \"out\");\n            var src = new PixImage<byte>(Path.Combine(idir, \"rgb8.jpg\")); //.ToGrayscalePixImage();\n            var image = new PixImage<byte>(src.Format, src.Size);\n            var srcvolume = src.Volume;\n            // var copyvol = srcvolume.Copy(); // does not work, creates default volume layout!\n            var copyvol = srcvolume.CopyToImage(); // works since it creates default image layout!\n            image.Volume = copyvol;\n            image.Save(Path.Combine(idir, \"rgb8-copied.jpg\"));\n        }\n\n        public static void LinearRampDemo(string dir)\n        {\n            Report.BeginTimed(\"linear ramp demo\");\n            var width = 1920;\n            var height = 1080;\n            var barHeight = height/4;\n\n            var line = new byte[width].SetByIndex(\n                        i => Col.DoubleToByte((double)i / (double)(width - 1)));\n\n            // write an image with linear red, green, blue, and gray ramps\n            var linearImage = new PixImage<byte>(Col.Format.RGB, new V2i(width, height));\n            var linVol = linearImage.Volume;\n\n            linVol.SubVolume(0, 0, 0, width, barHeight, 1).AsMatrixWindow().SetByCoord((x, y) => line[x]);\n            linVol.SubVolume(0, barHeight, 1, width, barHeight, 1).AsMatrixWindow().SetByCoord((x, y) => line[x]);\n            linVol.SubVolume(0, 2 * barHeight, 2, width, barHeight, 1).AsMatrixWindow().SetByCoord((x, y) => line[x]);\n            linVol.SubVolume(0, 3 * barHeight, 0, width, barHeight, 3).SetByCoord((x, y, c) => line[x]);\n\n            linearImage.Save(Path.Combine(dir, \"linear-ramp.tiff\"));\n            Report.End();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Demo/PixImageDemo/paket.references",
    "content": "FSharp.Core\nAardvark.Build"
  },
  {
    "path": "src/Demo/RandomSampleDemo/Program.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace RandomSampleDemo\n{\n    class Program\n    {\n        static void Main(string[] args)\n        {\n            // This initialization is required to be able to use DeviL for loading and saving PixImages.\n            Aardvark.Base.Aardvark.Init();\n            \n            var rnd = new RandomSystem(1);\n\n            var series = new(string, IRandomSeries)[]\n            {\n                (\"Pseudo\", new PseudoRandomSeries(new RandomSystem(2))),\n                (\"Halton\", new HaltonRandomSeries(2, rnd)),\n                (\"Forced\", new ForcedRandomSeries(\"C:\\\\Debug\\\\forced-1024-sq.bin\", rnd)),\n            };\n\n            var size = 1024;\n            var sampleCount = 30000;\n\n            var sampleImages = series.Map(rndSeries =>\n            {\n                var img = new PixImage<byte>(size, size, 4);\n                var samples = GenerateRectSamples(sampleCount, rndSeries.Item2);\n                DrawSamples(samples, img);\n                img.Save(String.Format(\"C:\\\\Debug\\\\Samples_{0}.bmp\", rndSeries.Item1));\n                return img;\n            });\n\n            SaveStiched(sampleImages, \"C:\\\\Debug\\\\Compare_Samples.bmp\");\n\n            var diskImages = series.Map(rndSeries =>\n            {\n                var img = new PixImage<byte>(size, size, 4);\n                var samples = GenerateDiskSamples(sampleCount, rndSeries.Item2);\n                DrawSamples(samples, img);\n                img.Save(String.Format(\"C:\\\\Debug\\\\DiskSamples_{0}.bmp\", rndSeries.Item1));\n                return img;\n            });\n\n            SaveStiched(diskImages, \"C:\\\\Debug\\\\Compare_DiskSamples.bmp\");\n\n            var lambertImages = series.Map(rndSeries =>\n            {\n                var img = new PixImage<byte>(size, size, 4);\n                var samples = GenerateLambertianSamples(sampleCount, rndSeries.Item2);\n                DrawSamples(samples, img);\n                img.Save(String.Format(\"C:\\\\Debug\\\\LambertSamples_{0}.bmp\", rndSeries.Item1));\n                return img;\n            });\n\n            SaveStiched(diskImages, \"C:\\\\Debug\\\\Compare_LambertSamples.bmp\");\n\n            var triangles = GenerateTriangles(10, rnd);\n            var trianglesImage = new PixImage<byte>(size, size, 4);\n            DrawTriangles(triangles, trianglesImage);\n            trianglesImage.Save(\"C:\\\\Debug\\\\Triangles.bmp\");\n\n            var triangleImages = series.Map(rndSeries =>\n            {\n                var img = new PixImage<byte>(size, size, 4);\n                DrawTriangles(triangles, img);\n                var samples = GenerateTriangleSamples(triangles, sampleCount / 3, rnd, rndSeries.Item2);\n                DrawSamples(samples, img);\n                img.Save(String.Format(\"C:\\\\Debug\\\\TriangleSamples_{0}.bmp\", rndSeries.Item1));\n                return img;\n            });\n\n            SaveStiched(triangleImages, \"C:\\\\Debug\\\\Compare_TriangleSamples.bmp\");\n\n\n            var cdfSampleTestCount = 1000000;\n            var pdfSize = 255; // uneven values with give symmetrical pdf\n            var gaussStretch = pdfSize / 10.0;\n            var pdf = new double[pdfSize].SetByIndex(i =>\n            {\n                var x = (i - pdfSize / 2) / gaussStretch;\n                return Fun.Gauss(x, 1.0);\n            });\n\n            var cdf = new DistributionFunction(pdf);\n\n            var sc = new int[pdf.Length];\n            Report.BeginTimed(\"CDF.Sample (Binary Search)\");\n            for (int i = 0; i < cdfSampleTestCount; i++)\n            {\n                var ind = cdf.Sample(rnd.UniformDouble());\n                sc[ind]++;\n            }\n            Report.End();\n            var cdfSampling = DrawSampleDistributionCounts(sc, 1024);\n            DrawGauss(cdfSampling, gaussStretch);\n            cdfSampling.Save(\"C:\\\\Debug\\\\CDFSampling.bmp\");\n\n            var rndSampleTestCount = 10000000;\n            var counts = new int[size];\n            var stdRnd = new RandomGaussian(rnd);\n            counts.Set(0);\n\n            Report.BeginTimed(\"RandomGaussian\");\n            for (int i = 0; i < rndSampleTestCount; i++)\n            {\n                var s = (int)Fun.Round((stdRnd.GetDouble() * 0.25 + 0.5) * size);\n                if (s >= 0 && s < size)\n                    counts[s]++;\n            }\n            Report.End();\n\n            var rndGaussImg = DrawSampleDistributionCounts(counts, 1024);\n            rndGaussImg.Save(\"C:\\\\Debug\\\\RandomGaussian.bmp\");\n\n            counts.Set(0);\n            Report.BeginTimed(\"RandomUniform.Normal\");\n            for (int i = 0; i < rndSampleTestCount; i++)\n            {\n                var s = (int)Fun.Round((rnd.Gaussian(0, 1) * 0.25 + 0.5) * size);\n                if (s >= 0 && s < size)\n                    counts[s]++;\n            }\n            Report.End();\n\n            var rndGaussImg2 = DrawSampleDistributionCounts(counts, 1024);\n            rndGaussImg2.Save(\"C:\\\\Debug\\\\RandomUniform.Normal.bmp\");\n\n            SaveStiched(new [] { rndGaussImg, rndGaussImg2 }, \"C:\\\\Debug\\\\Compare_RandomGaussian.bmp\");\n        }\n        \n        static void DrawGauss(PixImage<byte> img, double gaussStretch)\n        {\n            var imgMat = img.GetMatrix<C4b>();\n            var max = Fun.Gauss(0, 1.0);\n            var lastY = 0;\n            for(int x = 0; x < img.Size.X; x++)\n            {\n                var gx = (x - (img.Size.X - 1) / 2.0) / gaussStretch * 0.25;\n                var gy = (int)(Fun.Gauss(gx, 1.0) / max * (img.Size.Y - 1));\n                if (x > 0)\n                {\n                    var last = new V2i(x - 1, img.Size.Y - 1 - lastY);\n                    var curr = new V2i(x - 1, img.Size.Y - 1 - gy);\n                    imgMat.SetLine(last, curr, C4b.Green);\n                }\n                lastY = gy;\n            }\n        }\n\n        static PixImage<byte> DrawSampleDistributionCounts(int[] counts, int size)\n        {\n            var maxCount = counts.Max();\n            var img = new PixImage<byte>(size, size, 4);\n            var imgMat = img.GetMatrix<C4b>();\n            var currentLine = 0;\n            counts.ForEach((c, i) =>\n            {\n                var h = (int)((c / (maxCount + 1.0)) * size);\n                var nextLine = ((i + 1) * size / counts.Length);\n                while (currentLine < nextLine)\n                {\n                    imgMat.SetLine(new V2i(currentLine, size - 1), new V2i(currentLine, size - 1 - h), C4b.White);\n                    currentLine++;\n                }\n            });\n            return img;\n        }\n\n        static void SaveStiched(IEnumerable<PixImage<byte>> images, string filename)\n        {\n            var size = images.First().Size.Y;\n            var offsetImage= new PixImage<byte>(size / 50, size, 4);\n\n            // interleave the sample images with an image for empty space\n            // -> Zip with stitch images + remove last\n            var cnt = images.Count();\n            var array = Aardvark.Base.EnumerableEx.Zip(images, offsetImage.Repeat(cnt)).Take(cnt * 2 - 1).ToArray().IntoArray();\n            array.Stitch().Save(filename);\n        }\n\n        static void SaveStichedSquare(PixImage<byte>[] images, string filename)\n        {\n            images.StitchSquare().Save(filename);\n        }\n\n        static double Normal(IRandomUniform rnd, double mean, double stdDev)\n        {\n            // Box-Muller Transformation\n            var u1 = 1.0 - rnd.UniformDouble();   // uniform (0,1] -> log requires > 0\n            var u2 = rnd.UniformDouble();         // uniform [0,1)\n            var randStdNormal = Fun.Sqrt(-2.0 * Fun.Log(u1)) *\n                                Fun.Sin(Constant.PiTimesTwo * u2);\n            return mean + stdDev * randStdNormal; \n        }\n\n        static Triangle2d[] GenerateTriangles(int cnt, IRandomUniform rnd)\n        {\n            // generate triangles in 2d area [0, 1]\n            var gaussRnd = new RandomGaussian(rnd);\n            \n            var ta = 1.5 / cnt; // area of triangle\n            var tr = Fun.Sqrt(ta * 0.5); // edge length of right angled triangle with area ta\n\n            var xx = new Random(1);\n\n            var triangles = new List<Triangle2d>(cnt);\n            const int maxFails = 1000;\n            var fails = 0;\n            while(triangles.Count < cnt && fails < maxFails)\n            {\n                var p0 = rnd.UniformV2d();\n                var r1 = gaussRnd.GetDouble(tr, tr * 0.5);\n                var p1 = p0 + rnd.UniformV2dDirection() * r1;\n                if (p1.AnySmaller(0.0) || p1.AnyGreater(1.0))\n                {\n                    fails++;\n                    continue;\n                }\n                var r2 = gaussRnd.GetDouble(tr, tr * 0.5);\n                var p2 = p0 + rnd.UniformV2dDirection() * r2;\n                if (p2.AnySmaller(0.0) || p2.AnyGreater(1.0))\n                {\n                    fails++;\n                    continue;\n                }\n\n                var t = new Triangle2d(p0, p1, p2);\n\n                if (t.Area < ta * 0.2)\n                {\n                    fails++;\n                    continue;\n                }\n\n                if (triangles.Any(x => x.Intersects(t)))\n                {\n                    fails++;\n                }\n                else\n                {\n                    triangles.Add(t);\n                    fails = 0;\n                }\n            }\n\n            return triangles.ToArray();\n        }\n\n        static PixImage<byte> DrawDiskSamples(int cnt, int imgSize, IRandomSeries rnd)\n        {\n            var img = new PixImage<byte>(imgSize, imgSize, 4);\n            var imgMat = img.GetMatrix<C4b>();\n\n            for (int i = 0; i < cnt; i++)\n            {\n                var p = RandomSample.Disk(rnd, 0) * 0.5 + 0.5;\n                var crd = new V2i(p * new V2d(img.Size - 1));\n                imgMat[crd.X, crd.Y] = C4b.White;\n            }\n\n            return img;\n        }\n\n        static V2d[] GenerateDiskSamples(int cnt, IRandomSeries rnd)\n        {\n            return new V2d[cnt].SetByIndex(i => RandomSample.Disk(rnd, 0).XY * 0.5 + 0.5);\n        }\n\n        static V2d[] GenerateRectSamples(int cnt, IRandomSeries rnd)\n        {\n            return new V2d[cnt].SetByIndex(i => new V2d(rnd.UniformDouble(0), rnd.UniformDouble(1)));\n        }\n\n        static V2d[] GenerateLambertianSamples(int cnt, IRandomSeries rnd)\n        {\n            return new V2d[cnt].SetByIndex(i => RandomSample.Lambertian(V3d.OOI, rnd, 0).XY * 0.5 + 0.5);\n        }\n\n        static void DrawTriangles(IEnumerable<Triangle2d> ta, PixImage<byte> img)\n        {\n            var imgMat = img.GetMatrix<C4b>();\n            var sz = new V2d(img.Size - 1);\n            foreach (var t in ta)\n            {\n                foreach (var e in t.EdgeLines)\n                    imgMat.SetLine(e.P0 * sz, e.P1 * sz, new C4b(0.5, 0.5, 1));\n            }\n        }\n\n        static void DrawSamples(IEnumerable<V2d> samples, PixImage<byte> img)\n        {\n            var imgMat = img.GetMatrix<C4b>();\n            var sz = new V2d(img.Size - 1);\n            foreach (var s in samples)\n                imgMat[new V2i(s * sz)] = C4b.White;\n        }\n\n        static V2d[] GenerateTriangleSamples(Triangle2d[] ta, int count, IRandomUniform rnd, IRandomSeries rndSeries)\n        {\n            var areas = ta.Map(t => t.Area);\n            var total = areas.Sum();\n            var samples = new List<V2d>(count);\n            ta.ForEach((t, i) =>\n            {\n                var tsc = (int)Fun.Round(areas[i] / total * count);\n                for(int s = 0; s < tsc; s++)\n                    samples.Add(RandomSample.Triangle(t, rndSeries, 0));\n            });\n            return samples.ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Demo/RandomSampleDemo/RandomSampleDemo.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup>\n\t<RunWorkingDirectory>$(OutputPath)\\net8.0</RunWorkingDirectory>\n  </PropertyGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>"
  },
  {
    "path": "src/Demo/RandomSampleDemo/paket.references",
    "content": ""
  },
  {
    "path": "src/Demo/Scratch/Program.fs",
    "content": "﻿// Learn more about F# at http://fsharp.org\n// See the 'F# Tutorial' project for more help.\n\n\nopen System \nopen System.Threading\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Runtime\nopen Aardvark.Base.Monads.State\nopen FSharp.Data.Adaptive\nopen System.IO\nopen System.Runtime.InteropServices\nopen Microsoft.FSharp.NativeInterop\nopen Aardvark.Geometry\n\n#nowarn \"44\"\n\nmodule Packer =\n  \n    let test() =\n        let rand = RandomSystem(123842112)\n\n        let data =\n            List.init 1000 (fun _ ->\n                [\n                    for i in 1 .. 1000 do\n                        yield i, rand.UniformV2i(V2i(127, 127)) + V2i.II\n                ] |> List.sortByDescending (fun (_,s) -> s.X * s.Y)\n            )\n\n        for rects in [100 .. 100 .. 1000] do\n            Log.start \"%d\" rects\n            let mutable sum = 0.0\n            let mutable cnt = 0\n            let mutable range = Range1d.Invalid\n            let sw = System.Diagnostics.Stopwatch()\n\n            use e = (data :> seq<_>).GetEnumerator()\n\n            while sw.Elapsed.TotalSeconds < 5.0 do\n                let data = \n                    [\n                        for i in 1 .. rects do\n                            yield i, rand.UniformV2i(V2i(127, 127)) + V2i.II\n                    ]\n\n                sw.Start()\n                let packing = TexturePacking.square data\n                sw.Stop()\n\n                let o = packing.Occupancy\n                range.ExtendBy o\n                sum <- sum + o\n                cnt <- cnt + 1\n\n                let all = TexturePacking.toArray packing\n                if all.Length <> rects then failwith \"bad count\"\n                for i in 0 .. all.Length - 1 do\n                    for j in i + 1 .. all.Length - 1 do\n                        let (_, bi) = all.[i]\n                        let (_, bj) = all.[j]\n\n                        if bi.Intersects bj then\n                            failwith \"bad\"\n\n\n\n                //Log.line \"packed %A (%.2f%%)\" packing.Size (100.0 * o)\n\n            Log.line \"time: %A\" (sw.MicroTime / cnt)\n            Log.line \"min:  %.2f%%\" (100.0 * range.Min)\n            Log.line \"max:  %.2f%%\" (100.0 * range.Max)\n            Log.line \"avg:  %.2f%%\" (100.0 * sum / float cnt)\n            Log.stop()\n\n        //for (id, box) in packing.Used do\n        //    let s = V2i.II + box.Max - box.Min\n        //    Log.line \"%d: (%d,%d) (%dx%d)\" id box.Min.X box.Min.Y s.X s.Y\n\n        //Log.stop()\n#nowarn \"9\"\n#nowarn \"51\"\n\ntype NativeStream() =\n    inherit Stream()\n\n    let mutable capacity = 128n\n    let mutable store = Marshal.AllocHGlobal(capacity)\n    let mutable offset = 0n\n    let mutable length = 0n\n\n    member x.Pointer = store\n        \n    override x.Dispose(disposing : bool) =\n        base.Dispose(disposing)\n        let s = Interlocked.Exchange(&store, 0n)\n        if s <> 0n then\n            Marshal.FreeHGlobal s\n            capacity <- 0n\n            offset <- 0n\n            length <- 0n\n\n    override x.CanRead = true\n    override x.CanSeek = true\n    override x.CanWrite = true\n\n    override x.Length = int64 length\n    override x.Position\n        with get() = int64 offset\n        and set o = offset <- nativeint o\n\n    override x.Flush() = ()\n\n    override x.Seek(o, origin) =\n        match origin with\n            | SeekOrigin.Begin -> offset <- nativeint o\n            | SeekOrigin.Current -> offset <- offset + nativeint o\n            | SeekOrigin.End -> offset <- length - nativeint o\n            | _ -> ()\n        int64 offset\n\n    override x.SetLength(l : int64) =\n        if l > int64 capacity then\n            let newCap = Fun.NextPowerOfTwo l |> nativeint\n            store <- Marshal.ReAllocHGlobal(store, newCap)\n            capacity <- newCap\n\n        length <- nativeint l\n\n    override x.Read(buffer : byte[], o : int, count : int) =\n        let count = min (length - nativeint offset) (nativeint count) |> int\n        Marshal.Copy(store + offset, buffer, o, count)\n        count\n\n    override x.Write(buffer : byte[], o : int, count : int) =\n        let l = offset + nativeint count\n        if l > capacity then\n            let newCap = Fun.NextPowerOfTwo (int64 l) |> nativeint\n            store <- Marshal.ReAllocHGlobal(store, newCap)\n            capacity <- newCap\n\n        Marshal.Copy(buffer, o, store + offset, count)\n        length <- length + nativeint count\n        offset <- offset + nativeint count\n\ntype MyDelegate = delegate of int * int * int * int64 * int64 -> unit // * int64 * int64 * int64 * int64 -> unit\n\nopen AMD64\n\nlet testAdd (n : int) =\n    let set = HashSetDelta.ofList (List.map Add [ 1 .. n ])\n\n    let iter = 100000\n    let results = Array.zeroCreate iter\n    let rand = RandomSystem()\n    let rems = \n        Array.init iter (fun _ -> \n            let delta = if rand.UniformDouble() > 0.5 then 1 else -1\n\n            if rand.UniformDouble() > 0.5 then\n                SetOperation(rand.UniformInt(n) + 1, delta)\n            else\n                SetOperation(rand.UniformInt(n) + n + 1, delta)\n        )\n    \n    // warmup\n    for i in 0 .. iter / 10 do\n        results.[i] <- set.Add rems.[i]\n        \n    let results = Array.zeroCreate iter\n    System.GC.Collect()\n    System.GC.WaitForFullGCComplete() |> ignore\n\n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    for i in 0 .. iter - 1 do\n        results.[i] <- set.Add rems.[i]\n    sw.Stop()\n    sw.MicroTime / iter\n\nlet testAddMany (n : int) (m : int) =\n    let set = HashSetDelta.ofList (List.map Add [ 1 .. n ])\n\n    let iter = 10000\n    let results = Array.zeroCreate iter\n    let rand = RandomSystem()\n    let rems = \n        Array.init m (fun _ -> \n            let delta = if rand.UniformDouble() > 0.5 then 1 else -1\n\n            if rand.UniformDouble() > 0.5 then\n                SetOperation(rand.UniformInt(n) + 1, delta)\n            else\n                SetOperation(rand.UniformInt(n) + n + 1, delta)\n        )\n    \n    let inline res() =\n        let mutable set = set\n        for d in rems do\n            set <- set.Add d\n        set\n\n    // warmup\n    for i in 0 .. iter / 10 do\n        results.[i] <- res()\n        \n    let results = Array.zeroCreate iter\n    System.GC.Collect()\n    System.GC.WaitForFullGCComplete() |> ignore\n\n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    for i in 0 .. iter - 1 do\n        results.[i] <- res()\n    sw.Stop()\n    sw.MicroTime / iter\n\nlet testUnion (n : int) (m : int) =\n    \n    let rand = RandomSystem()\n    let randomOp () =\n        let delta = if rand.UniformDouble() > 0.5 then 1 else -1\n        if rand.UniformDouble() > 0.5 then\n            SetOperation(rand.UniformInt(n) + 1, delta)\n        else\n            SetOperation(rand.UniformInt(n) + n + 1, delta)\n\n    let a = HashSetDelta.ofList (List.map Add [ 1 .. n ]) |> HashSetDelta.toHashMap\n    let b = HashSetDelta.ofList (List.init m (fun _ -> randomOp())) |> HashSetDelta.toHashMap\n    \n    let iter = 100\n    let results = Array.zeroCreate iter\n    let rand = RandomSystem()\n    let inline res() =\n        HashMap.choose2 (fun _ l r -> \n            match l, r with\n                | None, r -> r\n                | l, None -> l\n                | Some l, Some r ->\n                    let r = l + r\n                    if r <> 0 then Some r\n                    else None\n        ) a b\n        |> HashSetDelta.ofHashMap\n\n    // warmup\n    for i in 0 .. iter / 10 do\n        results.[i] <- res()\n        \n    let results = Array.zeroCreate iter\n    System.GC.Collect()\n    System.GC.WaitForFullGCComplete() |> ignore\n\n    \n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    for i in 0 .. iter - 1 do\n        results.[i] <- res()\n    sw.Stop()\n    sw.MicroTime / iter\n\n\n\nopen System\nopen Aardvark.Geometry\nopen System.Runtime.Serialization.Formatters.Binary\nopen MBrace.FsPickler\nopen MBrace.FsPickler.Json\nopen System.Runtime.CompilerServices\n\ntype NativeMatrix =\n    static member inline Pin(matrix : inref<M44d>, action : NativeMatrix<float> -> 'r) =\n        action (NativeMatrix<float>(NativePtr.cast &&matrix, MatrixInfo(0L, V2l(4,4), V2l(1,4))))\n        \n    static member inline Pin(matrix : inref<M33d>, action : NativeMatrix<float> -> 'r) =\n        action (NativeMatrix<float>(NativePtr.cast &&matrix, MatrixInfo(0L, V2l(3,3), V2l(1,3))))\n\n    static member inline Pin(matrix : inref<M22d>, action : NativeMatrix<float> -> 'r) =\n        action (NativeMatrix<float>(NativePtr.cast &&matrix, MatrixInfo(0L, V2l(2,2), V2l(1,2))))\n\n    static member inline Pin(matrix : inref<M34d>, action : NativeMatrix<float> -> 'r) =\n        action (NativeMatrix<float>(NativePtr.cast &&matrix, MatrixInfo(0L, V2l(4,3), V2l(1,4))))\n\n    static member inline Pin(matrix : inref<M23d>, action : NativeMatrix<float> -> 'r) =\n        action (NativeMatrix<float>(NativePtr.cast &&matrix, MatrixInfo(0L, V2l(3,2), V2l(1,3))))\n\ntype NativeVector =\n    static member inline Pin(vector : inref<V4d>, action : NativeVector<float> -> 'r) =\n        action (NativeVector<float>(NativePtr.cast &&vector, VectorInfo(0L, 4L, 1L)))\n\n    static member inline Pin(vector : inref<V3d>, action : NativeVector<float> -> 'r) =\n        action (NativeVector<float>(NativePtr.cast &&vector, VectorInfo(0L, 3L, 1L)))\n\n    static member inline Pin(vector : inref<V2d>, action : NativeVector<float> -> 'r) =\n        action (NativeVector<float>(NativePtr.cast &&vector, VectorInfo(0L, 2L, 1L)))\n    \n    static member inline Pin(vector : inref<V4f>, action : NativeVector<float32> -> 'r) =\n        action (NativeVector<float32>(NativePtr.cast &&vector, VectorInfo(0L, 4L, 1L)))\n\n    static member inline Pin(vector : inref<V3f>, action : NativeVector<float32> -> 'r) =\n        action (NativeVector<float32>(NativePtr.cast &&vector, VectorInfo(0L, 3L, 1L)))\n\n    static member inline Pin(vector : inref<V2f>, action : NativeVector<float32> -> 'r) =\n        action (NativeVector<float32>(NativePtr.cast &&vector, VectorInfo(0L, 2L, 1L)))\n    \n    static member inline Pin(vector : inref<V4i>, action : NativeVector<int> -> 'r) =\n        action (NativeVector<int>(NativePtr.cast &&vector, VectorInfo(0L, 4L, 1L)))\n\n    static member inline Pin(vector : inref<V3i>, action : NativeVector<int> -> 'r) =\n        action (NativeVector<int>(NativePtr.cast &&vector, VectorInfo(0L, 3L, 1L)))\n\n    static member inline Pin(vector : inref<V2i>, action : NativeVector<int> -> 'r) =\n        action (NativeVector<int>(NativePtr.cast &&vector, VectorInfo(0L, 2L, 1L)))\n\nlet inline printMat (name : string) (fmt : string) (m : NativeMatrix< ^a >) =\n    let res = \n        Array.init (int m.SX) (fun c -> Array.init (int m.SY) (fun r -> \n            let str = (float m.[c,r]).ToString fmt\n            if str.StartsWith \"-\" then str\n            else \" \" + str\n        ))\n    let lens = res |> Array.map (fun col -> col |> Seq.map String.length |> Seq.max)\n    let pad (len : int) (s : string) =\n        if s.Length < len then s + (System.String(' ',len-s.Length))\n        else s\n\n    let padded =\n        res |> Array.mapi (fun i col -> \n            col |> Array.map (pad lens.[i])\n        )\n         \n    let section = not (String.IsNullOrWhiteSpace name)\n    if section then Report.Begin(\"{0}\", name)\n    for r in 0..int m.SY-1 do\n        let mutable line = \"\"\n        for c in 0..int m.SX-1 do\n            if c > 0 then line <- line + \" \"\n            line <- line + padded.[c].[r]\n        Report.Line(\"{0}\", line.TrimEnd())\n    if section then Report.End() |> ignore\n    \n[<AbstractClass; Sealed; Extension>]\ntype NativeMatrixExtensions private() =\n    [<Extension>]\n    static member LuFactorize(mat : NativeMatrix<float>, perm : NativeVector<int>) =\n        if mat.SX <> mat.SY then raise <| IndexOutOfRangeException()\n\n        perm.SetByCoord id\n\n        let n1 = int mat.SX - 1\n\n        let inline get (r : int) (c : int) =\n            mat.[c,r]\n\n        let inline set (r : int) (c : int) (v : float) =\n            mat.[c,r] <- v\n                \n        let inline swapRows (ri : int) (rj : int) =\n            if ri <> rj then\n                for c in 0 .. n1 do\n                    let t = get ri c\n                    set ri c (get rj c)\n                    set rj c t\n\n                let t = perm.[ri]\n                perm.[ri] <- perm.[rj]\n                perm.[rj] <- t\n\n        let mutable i = 0\n        while i < n1 do\n            // pivoting\n            let vii = \n                let mutable j = i\n                let mutable vmax = get i i\n                let mutable vmaxAbs = abs vmax\n                for ii in i+1 .. n1 do\n                    let vii = get ii i\n                    let viiAbs = abs vii\n                    if viiAbs > vmaxAbs then\n                        j <- ii\n                        vmax <- vii\n                        vmaxAbs <- viiAbs\n\n                swapRows i j\n                vmax\n\n            // elimination\n            if Fun.IsTiny vii then\n                // singular matrix\n                i <- Int32.MaxValue\n            else\n                for j in i + 1 .. n1 do\n                    let vji = get j i\n                    let f = vji / vii\n\n                    set j i f\n                    for c in i + 1 .. n1 do\n                        set j c (get j c - get i c * f) \n                i <- i + 1\n\n        if i > n1 then   \n            false\n        else\n            true\n\n    [<Extension>]\n    static member LuSolve(mat : NativeMatrix<float>, perm : NativeVector<int>, rhs : NativeVector<float>, res : NativeVector<float>) =\n        if mat.SX <> mat.SY || mat.SX <> perm.Size || mat.SX <> rhs.Size || mat.SX <> res.Size then raise <| IndexOutOfRangeException()\n        \n        let n1 = int mat.SX - 1\n        res.SetByCoord(fun (i : int) -> rhs.[perm.[i]])\n\n        for i in 0 .. n1 do\n            let pi = perm.[i]\n            for j in i + 1 .. n1 do\n                let f = mat.[i, j]\n                let pj = perm.[j]\n                rhs.[pj] <- rhs.[pj] - f * rhs.[pi]\n\n\n        // back substitution\n        for ri in 0 .. n1 do\n            let ri = n1 - ri\n\n            let mutable s = rhs.[perm.[ri]]\n            for c in ri + 1 .. n1 do\n                s <- s - mat.[c, ri] * res.[c]\n\n            res.[ri] <- s / mat.[ri, ri]\n\n        ()\n        \n    [<Extension>]\n    static member LuSolve(mat : NativeMatrix<float>, rhs : NativeVector<float>, res : NativeVector<float>) =\n        if mat.SX <> mat.SY || mat.SX <> rhs.Size || mat.SX <> res.Size then raise <| IndexOutOfRangeException()\n        \n        let n1 = int mat.SX - 1\n        res.SetByCoord(fun (i : int) -> rhs.[i])\n\n        for i in 0 .. n1 do\n            let pi = i\n            for j in i + 1 .. n1 do\n                let f = mat.[i, j]\n                let pj = j\n                rhs.[pj] <- rhs.[pj] - f * rhs.[pi]\n\n\n        // back substitution\n        for ri in 0 .. n1 do\n            let ri = n1 - ri\n\n            let mutable s = rhs.[ri]\n            for c in ri + 1 .. n1 do\n                s <- s - mat.[c, ri] * res.[c]\n\n            res.[ri] <- s / mat.[ri, ri]\n\n        ()\n        \n    [<Extension>]\n    static member LuInvert(mat : NativeMatrix<float>, inv : NativeMatrix<float>) =\n        if mat.SX <> mat.SY || mat.SX <> inv.SX || inv.SX <> inv.SY then raise <| IndexOutOfRangeException()\n        \n        let n = int mat.SY\n        let perm = NativePtr.stackalloc n\n        let pv = NativeVector<int>(perm, VectorInfo(n))\n        if mat.LuFactorize(pv) then\n            inv.SetByCoord(fun (c : V2i) ->\n                if c.X = NativePtr.get perm c.Y then 1.0\n                else 0.0\n            )\n\n            for c in 0 .. n - 1 do\n                mat.LuSolve(inv.[c, *], inv.[c, *])\n\n            true\n\n        else\n            false\n\n        \n    [<Extension; MethodImpl(MethodImplOptions.NoInlining)>]\n    static member LuFactorizeNew(m : byref<M44d>) =\n        NativeMatrix.Pin(&m, fun (tm : NativeMatrix<float>) ->\n            let pp = NativePtr.stackalloc<V4i> 1\n            let tp = NativeVector<int>(NativePtr.cast pp, VectorInfo(4))\n\n            if tm.LuFactorize(tp) then\n                NativePtr.read pp\n            else\n                V4i.Zero\n        )\n              \n    [<Extension; MethodImpl(MethodImplOptions.NoInlining)>]\n    static member LuSolveNew(m : inref<M44d>, perm : V4i, rhs : V4d) =\n        let mutable rhs = rhs\n        let mutable perm = perm\n\n        NativeMatrix.Pin(&m, fun (tm : NativeMatrix<float>) ->\n            NativeVector.Pin(&perm, fun (tp : NativeVector<int>) ->\n                NativeVector.Pin(&rhs, fun (tb : NativeVector<float>) ->\n                    let pr = NativePtr.stackalloc<V4d> 1\n                    let tr = NativeVector<float>(NativePtr.cast pr, VectorInfo(4))\n                    tm.LuSolve(tp, tb, tr)\n                    NativePtr.read pr\n                )\n            )\n        )\n        \n    [<Extension; MethodImpl(MethodImplOptions.NoInlining)>]\n    static member LuInvertNew(m : M44d) =\n        let pm = NativePtr.stackalloc<M44d> 1\n        NativePtr.write pm m\n        let tm = NativeMatrix<float>(NativePtr.cast pm, MatrixInfo(0L, V2l(4,4), V2l(1,4)))\n\n        let pi = NativePtr.stackalloc<M44d> 1\n        let ti = NativeMatrix<float>(NativePtr.cast pi, MatrixInfo(0L, V2l(4,4), V2l(1,4)))\n\n        if tm.LuInvert(ti) then\n            NativePtr.read pi\n        else\n            M44d.Zero\n              \n\n\n\nlet inline printM44d (name : string) (fmt : string) (mat : M44d) =\n    let mb = Matrix<float>(mat.ToArray(), V2l(4,4))\n    NativeMatrix.using mb (printMat name fmt)\n\n\nlet ellipsoidTest() =\n    let trafo =\n        Trafo3d.Scale(3.0, 2.0, 1.0) //*\n        //Trafo3d.Rotation(V3d.III.Normalized, 1.21312)\n        \n\n    let err = 0.0\n    let rand = RandomSystem()\n    let pts =\n        Array.init 2000 (fun _ ->\n            rand.UniformV3dDirection() * (1.0 + (rand.UniformDouble() - 0.5) * 2.0 * err) |> trafo.Forward.TransformPos\n        )\n\n\n    //let pts = \n    //    let rx = Regex @\"(-?[0-9]+)[ \\t]+(-?[0-9]+)[ \\t]+(-?[0-9]+)\"\n    //    File.readAllLines @\"C:\\Users\\Schorsch\\Development\\ellipsoid_fit_python\\mag_out.txt\"\n    //    |> Array.choose (fun l ->\n    //        let m = rx.Match l\n    //        if m.Success then Some (V3d(float m.Groups.[1].Value, float m.Groups.[2].Value, float m.Groups.[3].Value))\n    //        else None\n    //    )\n\n    let bb = Box3d(pts)\n    let f = 3.0 / bb.Size.NormMax\n    let c = bb.Center\n    let ellipsoid = EllipsoidRegression3d.ofArray pts |> EllipsoidRegression3d.getEllipsoid\n\n    let mutable minError = System.Double.PositiveInfinity\n    let mutable maxError = 0.0\n    let mutable sum = 0.0\n    let mutable sumSq = 0.0\n    let mutable cnt = 0\n    for p in pts do\n        let struct(p0, n0) = ellipsoid.GetClosestPointAndNormal(p)\n        let h = Vec.distance p p0\n        let dn = Vec.dot n0 (p - p0)\n        \n        minError <- min minError h\n        maxError <- max maxError h\n        sum <- sum + h\n        sumSq <- sumSq + sqr h\n        cnt <- cnt + 1\n        \n    let q = trafo.Forward.TransformPos (V3d(1,0,0))\n\n    let pt = q\n    let ps = ellipsoid.Euclidean.TransformPos ((ellipsoid.Euclidean.InvTransformPos(q) / ellipsoid.Radii).Normalized * ellipsoid.Radii)\n    let p0 = ellipsoid.GetClosestPoint(pt)\n\n\n\n    Log.start \"ellipsoid\"\n    Log.line \"r: %.5f %.5f %.5f\" ellipsoid.Radii.X ellipsoid.Radii.Y ellipsoid.Radii.Z\n    Log.line \"x: %s\" ((ellipsoid.Euclidean.TransformDir V3d.IOO).ToString \"0.00000\")\n    Log.line \"y: %s\" ((ellipsoid.Euclidean.TransformDir V3d.OIO).ToString \"0.00000\")\n    Log.line \"z: %s\" ((ellipsoid.Euclidean.TransformDir V3d.OOI).ToString \"0.00000\")\n    Log.stop()\n\n    Log.start \"errors\"\n    Log.line \"min: %.6e\" minError\n    Log.line \"max: %.6e\" maxError\n    Log.line \"avg: %.6e\" (sum / float cnt)\n    Log.line \"rms: %.6e\" (sqrt (sumSq / float cnt))\n    Log.stop()\n\n    \nlet sphereTest() =\n    let trafo =\n        Trafo3d.Scale(5.0) *\n        Trafo3d.Translation(1.0, 2.0, 3.0)\n        \n\n    let err = 0.1\n    let rand = RandomSystem()\n    let pts =\n        Array.init 1000 (fun _ ->\n            let dir = rand.UniformV3dDirection() |> trafo.Forward.TransformDir\n            let pos = trafo.Forward.C3.XYZ + dir\n\n            pos + Vec.normalize dir * ((rand.UniformDouble() - 0.5) * 2.0 * err)\n\n        )\n\n\n    //let pts = \n    //    let rx = Regex @\"(-?[0-9]+)[ \\t]+(-?[0-9]+)[ \\t]+(-?[0-9]+)\"\n    //    File.readAllLines @\"C:\\Users\\Schorsch\\Development\\ellipsoid_fit_python\\mag_out.txt\"\n    //    |> Array.choose (fun l ->\n    //        let m = rx.Match l\n    //        if m.Success then Some (V3d(float m.Groups.[1].Value, float m.Groups.[2].Value, float m.Groups.[3].Value))\n    //        else None\n    //    )\n\n    let bb = Box3d(pts)\n    let f = 3.0 / bb.Size.NormMax\n    let c = bb.Center\n    let sphere = \n        let r = (SphereRegression3d.Empty, pts) ||> Array.fold (fun r p -> r.Add p)\n        r.GetSphere()\n\n    let mutable minError = System.Double.PositiveInfinity\n    let mutable maxError = 0.0\n    let mutable sum = 0.0\n    let mutable sumSq = 0.0\n    let mutable cnt = 0\n    for p in pts do\n        let n0 = Vec.normalize (p - sphere.Center)\n        let p0 = n0 * sphere.Radius + sphere.Center\n        let h = Vec.distance p p0\n        let dn = Vec.dot n0 (p - p0)\n        \n        minError <- min minError h\n        maxError <- max maxError h\n        sum <- sum + h\n        sumSq <- sumSq + sqr h\n        cnt <- cnt + 1\n        \n    let q = trafo.Forward.TransformPos (V3d(1,0,0))\n\n\n    Log.start \"sphere\"\n    Log.line \"r: %.5f\" sphere.Radius\n    Log.line \"c: %s\" (sphere.Center.ToString \"0.00000\")\n    Log.stop()\n\n    Log.start \"errors\"\n    Log.line \"min: %.6e\" minError\n    Log.line \"max: %.6e\" maxError\n    Log.line \"avg: %.6e\" (sum / float cnt)\n    Log.line \"rms: %.6e\" (sqrt (sumSq / float cnt))\n    Log.stop()\n\n\n\n\nmodule Temp =\n\n    module Seq =\n        open System.Collections.Generic\n\n        [<AbstractClass>]\n        type AbstractEnumerator<'a>() =\n        \n            abstract member MoveNext : unit -> bool\n            abstract member Current : 'a\n            abstract member Reset : unit -> unit\n            abstract member Dispose : unit -> unit\n\n            interface IDisposable with\n                member x.Dispose() = x.Dispose()\n\n            interface System.Collections.IEnumerator with\n                member x.MoveNext() = x.MoveNext()\n                member x.Current = x.Current :> obj\n                member x.Reset() = x.Reset()\n\n            interface IEnumerator<'a> with\n                member x.Current = x.Current\n\n        module private Enumerators = \n\n            type FilterIndexEnumerator<'a>(seq : seq<'a>, predicate : OptimizedClosures.FSharpFunc<int, 'a, bool>) =\n                inherit AbstractEnumerator<'a>()\n\n                let e = seq.GetEnumerator()\n                let mutable i = -1\n                override x.MoveNext() =\n                    if e.MoveNext() then\n                        i <- i + 1\n                        if predicate.Invoke(i, e.Current) then\n                            true\n                        else\n                            x.MoveNext()\n                    else\n                        false\n\n                override x.Current = e.Current\n                override x.Reset() = \n                    i <- -1\n                    e.Reset()\n                override x.Dispose() =\n                    i <- -1\n                    e.Dispose()\n\n            type ChooseIndexEnumerator<'a, 'b>(seq : seq<'a>, mapping : OptimizedClosures.FSharpFunc<int, 'a, option<'b>>) =\n                inherit AbstractEnumerator<'b>()\n\n                let e = seq.GetEnumerator()\n                let mutable i = -1\n                let mutable current = Unchecked.defaultof<'b>\n\n                override x.MoveNext() =\n                    if e.MoveNext() then\n                        i <- i + 1\n                        match mapping.Invoke(i, e.Current) with\n                        | Some b ->\n                            current <- b\n                            true\n                        | None -> \n                            x.MoveNext()\n                    else\n                        false\n\n                override x.Current = current\n                override x.Reset() = \n                    current <- Unchecked.defaultof<_>\n                    i <- -1\n                    e.Reset()\n                override x.Dispose() =\n                    current <- Unchecked.defaultof<_>\n                    i <- -1\n                    e.Dispose()\n\n            type ChooseValueEnumerator<'a, 'b>(seq : seq<'a>, mapping : 'a -> voption<'b>) =\n                inherit AbstractEnumerator<'b>()\n\n                let e = seq.GetEnumerator()\n                let mutable current = Unchecked.defaultof<'b>\n\n                override x.MoveNext() =\n                    if e.MoveNext() then\n                        match mapping e.Current with\n                        | ValueSome b ->\n                            current <- b\n                            true\n                        | ValueNone -> \n                            x.MoveNext()\n                    else\n                        false\n\n                override x.Current = current\n                override x.Reset() = \n                    current <- Unchecked.defaultof<_>\n                    e.Reset()\n                override x.Dispose() =\n                    current <- Unchecked.defaultof<_>\n                    e.Dispose()\n\n            type ChooseValueIndexEnumerator<'a, 'b>(seq : seq<'a>, mapping : OptimizedClosures.FSharpFunc<int, 'a, voption<'b>>) =\n                inherit AbstractEnumerator<'b>()\n\n                let e = seq.GetEnumerator()\n                let mutable i = -1\n                let mutable current = Unchecked.defaultof<'b>\n\n                override x.MoveNext() =\n                    if e.MoveNext() then\n                        i <- i + 1\n                        match mapping.Invoke(i, e.Current) with\n                        | ValueSome b ->\n                            current <- b\n                            true\n                        | ValueNone -> \n                            x.MoveNext()\n                    else\n                        false\n\n                override x.Current = current\n                override x.Reset() = \n                    current <- Unchecked.defaultof<_>\n                    i <- -1\n                    e.Reset()\n                override x.Dispose() =\n                    current <- Unchecked.defaultof<_>\n                    i <- -1\n                    e.Dispose()\n                \n            type CollectIndexEnumerator<'a, 'b>(seq : seq<'a>, mapping : OptimizedClosures.FSharpFunc<int, 'a, seq<'b>>) =\n                inherit AbstractEnumerator<'b>()\n\n                let e = seq.GetEnumerator()\n                let mutable i = -1\n                let mutable current : voption<IEnumerator<'b>> = ValueNone\n\n                override x.MoveNext() =\n                    match current with\n                    | ValueSome inner ->\n                        if inner.MoveNext() then\n                            true\n                        elif e.MoveNext() then\n                            inner.Dispose()\n                            i <- i + 1\n                            let s = mapping.Invoke(i, e.Current)\n                            let ni = s.GetEnumerator()\n                            current <- ValueSome ni\n                            x.MoveNext()\n                        else\n                            false\n                    | ValueNone ->\n                        if e.MoveNext() then\n                            i <- i + 1\n                            let s = mapping.Invoke(i, e.Current)\n                            let ni = s.GetEnumerator()\n                            current <- ValueSome ni\n                            x.MoveNext()\n                        else\n                            false\n                    \n\n                override x.Current = \n                    current.Value.Current\n\n                override x.Reset() = \n                    match current with\n                    | ValueSome c -> \n                        c.Dispose()\n                        current <- ValueNone\n                    | ValueNone ->\n                        ()\n                    i <- -1\n                    e.Reset()\n                override x.Dispose() =\n                    match current with\n                    | ValueSome c -> \n                        c.Dispose()\n                        current <- ValueNone\n                    | ValueNone ->\n                        ()\n                    i <- -1\n                    e.Dispose()\n\n\n\n        let ofEnumerator (create : unit -> #IEnumerator<'a>) =\n            { new seq<'a> with\n                member x.GetEnumerator() = create() :> IEnumerator<'a>\n                member x.GetEnumerator() = create() :> System.Collections.IEnumerator\n            }\n\n        let filteri (predicate : int -> 'a -> bool) (source : seq<'a>) =   \n            let predicate = OptimizedClosures.FSharpFunc<int, 'a, bool>.Adapt predicate\n            ofEnumerator <| fun () -> new Enumerators.FilterIndexEnumerator<_>(source, predicate)\n\n        let choosei (mapping : int -> 'a -> option<'b>) (source : seq<'a>) =\n            let mapping = OptimizedClosures.FSharpFunc<int, 'a, option<'b>>.Adapt mapping\n            ofEnumerator <| fun () -> new Enumerators.ChooseIndexEnumerator<_,_>(source, mapping)\n            \n        let collecti (mapping : int -> 'a -> seq<'b>) (source : seq<'a>) =\n            let mapping = OptimizedClosures.FSharpFunc<int, 'a, seq<'b>>.Adapt mapping\n            ofEnumerator <| fun () -> new Enumerators.CollectIndexEnumerator<_,_>(source, mapping)\n\n        let chooseV (mapping : 'a -> voption<'b>) (source : seq<'a>) =\n            ofEnumerator <| fun () -> new Enumerators.ChooseValueEnumerator<_,_>(source, mapping)\n\n        let chooseiV (mapping : int -> 'a -> voption<'b>) (source : seq<'a>) =\n            let mapping = OptimizedClosures.FSharpFunc<int, 'a, voption<'b>>.Adapt mapping\n            ofEnumerator <| fun () -> new Enumerators.ChooseValueIndexEnumerator<_,_>(source, mapping)\n\n        let tryMin (source : seq<'a>) =\n            use e = source.GetEnumerator()\n            if e.MoveNext() then\n                let mutable best = e.Current\n                while e.MoveNext() do\n                    let c = e.Current\n                    if c < best then\n                        best <- c\n                Some best\n            else\n                None\n            \n        let tryMax (source : seq<'a>) =\n            use e = source.GetEnumerator()\n            if e.MoveNext() then\n                let mutable best = e.Current\n                while e.MoveNext() do\n                    let c = e.Current\n                    if c > best then\n                        best <- c\n                Some best\n            else\n                None\n\n        let tryMinBy (mapping : 'a -> 'b) (source : seq<'a>) =\n            use e = source.GetEnumerator()\n            if e.MoveNext() then\n                let mutable best = e.Current\n                let mutable bestValue = mapping best\n\n                while e.MoveNext() do\n                    let c = e.Current\n                    let v = mapping c\n                    if v < bestValue then\n                        best <- c\n                        bestValue <- v\n\n                Some best\n            else\n                None\n\n        let tryMaxBy (mapping : 'a -> 'b) (source : seq<'a>) =\n            use e = source.GetEnumerator()\n            if e.MoveNext() then\n                let mutable best = e.Current\n                let mutable bestValue = mapping best\n\n                while e.MoveNext() do\n                    let c = e.Current\n                    let v = mapping c\n                    if v > bestValue then\n                        best <- c\n                        bestValue <- v\n\n                Some best\n            else\n                None\n        \n        module Parallel =\n            open System.Threading.Tasks\n            open System.Linq\n\n            let map (mapping : 'a -> 'b) (source : seq<'a>) =\n                source.AsParallel().AsOrdered().Select(mapping) :> seq<_>\n                \n            let choose (mapping : 'a -> option<'b>) (source : seq<'a>) =\n                source.AsParallel().Select(mapping).Where(Option.isSome).Select(Option.get) :> seq<_>\n\n    module List =\n        open System.Reflection\n        open Microsoft.FSharp.Reflection\n        open Aardvark.Base.IL\n\n        type private SetTail<'a> private() =\n            static let tailProperty =\n                let tailField = typeof<list<'a>>.GetField(\"tail\", BindingFlags.NonPublic ||| BindingFlags.Instance)\n                tailField\n\n            static let setTail : list<'a> -> list<'a> -> unit =\n                cil {\n                    do! IL.ldarg 0\n                    do! IL.ldarg 1\n                    do! IL.stfld tailProperty\n                    do! IL.ret\n                }\n\n\n            static member SetTail(l : list<'a>, tail : list<'a>) =\n                setTail l tail\n\n        let inline private setTail (cons : list<'a>) (t : list<'a>) =\n            SetTail<'a>.SetTail(cons, t)\n\n        let rec chooseV (mapping : 'a -> voption<'b>) (source : list<'a>) =\n            match source with\n            | [] -> []\n            | h :: t -> \n                match mapping h with\n                | ValueSome r ->\n                    let start = [r]\n                    let mutable c = start\n\n                    for e in t do\n                        match mapping e with\n                        | ValueSome e ->\n                            let m = [e]\n                            setTail c m\n                            c <- m\n                        | ValueNone ->\n                            ()\n\n                    start\n                | ValueNone ->\n                    chooseV mapping t\n\n        let rec private chooseiAux (i : int) (mapping : OptimizedClosures.FSharpFunc<int, 'a, option<'b>>) (source : list<'a>) =\n            match source with\n            | [] ->\n                []\n            | h :: t ->\n                match mapping.Invoke(i, h) with\n                | Some r ->\n                    let start = [r]\n                    let mutable c = start\n                    let mutable i = i + 1\n                    for e in t do\n                        match mapping.Invoke(i, e) with\n                        | Some v ->\n                            let l = [v]\n                            setTail c l\n                            c <- l\n                        | None ->\n                            ()\n                    start\n                | None ->\n                    chooseiAux (i + 1) mapping t\n\n        let choosei (mapping : int -> 'a -> option<'b>) (source : list<'a>) =\n            let mapping = OptimizedClosures.FSharpFunc<int, 'a, option<'b>>.Adapt mapping\n            chooseiAux 0 mapping source\n\n        let rec private chooseiVAux (i : int) (mapping : OptimizedClosures.FSharpFunc<int, 'a, voption<'b>>) (source : list<'a>) =\n            match source with\n            | [] ->\n                []\n            | h :: t ->\n                match mapping.Invoke(i, h) with\n                | ValueSome r ->\n                    let start = [r]\n                    let mutable c = start\n                    let mutable i = i + 1\n                    for e in t do\n                        match mapping.Invoke(i, e) with\n                        | ValueSome v ->\n                            let l = [v]\n                            setTail c l\n                            c <- l\n                        | ValueNone ->\n                            ()\n                    start\n                | ValueNone ->\n                    chooseiVAux (i + 1) mapping t\n\n        let chooseiV (mapping : int -> 'a -> voption<'b>) (source : list<'a>) =\n            let mapping = OptimizedClosures.FSharpFunc<int, 'a, voption<'b>>.Adapt mapping\n            chooseiVAux 0 mapping source\n\n        let rec private collectiAux (i : int) (mapping : OptimizedClosures.FSharpFunc<int, 'a, list<'b>>) (source : list<'a>) =\n            match source with\n            | [] ->\n                []\n            | ha :: ta ->\n                match mapping.Invoke(i, ha) with\n                | [] ->\n                    collectiAux (i + 1) mapping ta\n                | hb :: tb ->\n                    let start = [hb]\n                    let mutable c = start\n                    for e in tb do\n                        let m = [e]\n                        setTail c m\n                        c <- m\n                         \n                    let mutable i = i + 1\n                    for a in ta do\n                        let res = mapping.Invoke(i, a)\n                        for e in res do\n                            let m = [e]\n                            setTail c m\n                            c <- m\n                        i <- i + 1\n                         \n                    start\n   \n        let collecti (mapping : int -> 'a -> list<'b>) (source : list<'a>) =\n            let mapping = OptimizedClosures.FSharpFunc<int, 'a, list<'b>>.Adapt mapping\n            collectiAux 0 mapping source\n                 \n\n    let test() =\n\n    \n        let a = [0;1;2;3] |> List.chooseV (fun v -> if v % 2 = 1 then ValueSome v else ValueNone)\n        let b = [0;1;2;3] |> List.collecti (fun i v -> if i % 2 = 1 then [v] else [])\n\n        printfn \"%A\" a\n        printfn \"%A\" b\n         \n[<EntryPoint; STAThread>]\nlet main argv = \n    Aardvark.Init()\n    let a = Array.init (1 <<< 20) id\n\n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    let x = a |> Temp.Seq.Parallel.map ((+) 2) |> Seq.toArray\n    printfn \"%A\" sw.MicroTime\n    sw.Restart()\n    let y = a |> Seq.map ((+) 2) |> Seq.toArray\n    printfn \"%A\" sw.MicroTime\n\n\n    //Packer.test()\n    exit 0\n\n    let s = MapExt.ofList [1,1;2,2;3,2;4,4]\n   \n    let pickler = FsPickler.CreateJsonSerializer(true, false)\n\n    let str = pickler.PickleToString(s)\n    printfn \"%s\" str\n    let test = pickler.UnPickleOfString<MapExt<int, int>> str\n    printfn \"%A\" test\n    \n    Environment.Exit 0\n\n\n\n    let shapeVertices1 = \n        [| \n            V2d(5.13737496260736, 1.65204532553747)\n            V2d(5.88809174207466, 1.16673346810404)\n            V2d(5.59715606644129, 0.71669234485868)\n            V2d(4.84643928697398, 1.20200420229211)\n            V2d(5.13737496260736, 1.65204532553747) \n        |]\n\n    let r = PolyRegion.ofArray shapeVertices1\n    //let res = PolygonTessellator.Combine([shapeVertices1], TessellationRule.EvenOdd)\n    \n    match r.Polygons with\n        | [l] -> printfn \"%A\" l.PointCount\n        | _ -> printfn \"error\"\n    Environment.Exit 0\n\n    let set = cset [1;2;3]\n\n    let m = cval (Some 10)\n    let d = m |> AVal.map (fun v -> printfn \"eval %A\" v; v)\n    let b = set |> ASet.chooseA (fun _ -> d)\n\n    \n    let r = b.GetReader()\n    r.GetChanges(AdaptiveToken.Top) |> printfn \"%A\"\n\n    transact (fun () -> set.Remove 1 |> ignore)\n    r.GetChanges(AdaptiveToken.Top) |> printfn \"%A\"\n\n    transact (fun () -> set.Remove 2 |> ignore)\n    r.GetChanges(AdaptiveToken.Top) |> printfn \"%A\"\n\n    transact (fun () -> m.Value <- Some 1000)\n    r.GetChanges(AdaptiveToken.Top) |> printfn \"%A\"\n    \n    transact (fun () -> set.Remove 3 |> ignore; m.Value <- Some 100)\n    r.GetChanges(AdaptiveToken.Top) |> printfn \"%A\"\n\n\n    System.Environment.Exit 0\n\n//    let a = Func<int, int, int>(fun a b -> printfn \"%A\" (a,b); a + b)\n//    let f : int -> int -> int = DelegateAdapters.wrap a\n//    f 0 1 |> printfn \"%A\"\n//    Environment.Exit 0\n\n\n\n\n//    let output = @\"C:\\Users\\Schorsch\\Desktop\\bla.csv\"\n//\n//    File.WriteAllText(output, \"n;m;ta;tu\\r\\n\")\n//    let n = 1000\n//    for i in 1 .. 50 do\n//        let n = i * 1000\n//        let mutable l = 0\n//        let mutable r = n / 3\n//\n//        while r - l > 0 do\n//            let m = (l + r) / 2\n//            let ta = testAddMany n m\n//            let tu = testUnion n m\n//            Log.line \"%d/%d: %A %A\" n m ta tu\n//            if ta > tu then\n//                r <- m - 1\n//            else\n//                l <- m + 1\n//        let m = l\n//        printf \" 0: %d/%d: \" n m\n//        let ta = testAddMany n m\n//        printf \"%A\" ta\n//        let tu = testUnion n m\n//        printfn \" %A\" tu\n//\n//        File.AppendAllLines(output, [sprintf \"%d;%d;%.3f;%.3f\" n l ta.TotalMicroseconds tu.TotalMicroseconds])\n//\n//    Environment.Exit 0\n\n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    for iter in 1..50 do\n        let cnt = iter * 1000\n        let arr = ASet.ofArray(Array.init(cnt) (fun i -> cval i :> aval<_>))\n\n        let arrr = arr |> ASet.collect (fun x -> \n                            x |> ASet.bind (fun y -> ASet.single y))\n\n        let r = arrr.GetReader()\n   \n        System.GC.Collect()\n        System.GC.WaitForFullGCComplete() |> ignore\n        printf \"%d \" cnt\n\n//        let worked = System.GC.TryStartNoGCRegion(1L <<< 30)\n\n        let sw = System.Diagnostics.Stopwatch.StartNew()\n        r.GetChanges AdaptiveToken.Top |> ignore\n        sw.Stop()\n//\n//        if worked then\n//            System.GC.EndNoGCRegion()\n//        else\n//            printf \" (BAD) \"\n\n        printfn \"took: %A\" sw.MicroTime\n\n        System.GC.Collect()\n        System.GC.WaitForFullGCComplete() |> ignore\n\n    Environment.Exit 0\n\n//    Program.test()\n\n    \n    let m = cval 10\n    \n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    let set = cset [1 .. 100000]\n    sw.Stop()\n    Log.line \"build: %A\" sw.MicroTime\n\n    let op = \n        m |> ASet.bind (fun a ->\n            printfn \"bind\"\n            set \n                |> ASet.collect (fun b -> if a <> b then ASet.ofList [a] else ASet.empty)\n                |> fun a -> printfn \"collect rebuild\"; a\n                |> ASet.collect ASet.single\n                |> ASet.collect ASet.single\n                |> ASet.collect ASet.single\n                |> ASet.collect ASet.single\n                |> ASet.collect ASet.single\n                |> ASet.collect ASet.single\n                |> ASet.collect ASet.single\n        )\n\n    let r = op.GetReader()\n\n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    r.GetChanges AdaptiveToken.Top |> ignore\n    sw.Stop()\n    Log.line \"took: %A\" sw.MicroTime\n\n    \n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    transact (fun () -> m.Value <- 1)\n    sw.Stop()\n    Log.line \"transact: %A\" sw.MicroTime\n    \n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    r.GetChanges AdaptiveToken.Top |> ignore\n    sw.Stop()\n    Log.line \"took: %A\" sw.MicroTime\n    \n    \n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    transact (fun () -> set.Add 0 |> ignore)\n    sw.Stop()\n    Log.line \"transact: %A\" sw.MicroTime\n    \n    let sw = System.Diagnostics.Stopwatch.StartNew()\n    r.GetChanges AdaptiveToken.Top |> ignore\n    sw.Stop()\n\n\n    Log.line \"took: %A\" sw.MicroTime\n    Environment.Exit 0\n\n\n\n    let rand = RandomSystem()\n    let g = UndirectedGraph.ofNodes (Set.ofList [0..127]) (fun li ri -> float (ri - li) |> Some)\n\n    let tree = UndirectedGraph.maximumSpanningTree compare g\n    printfn \"%A\" tree\n\n    printfn \"%A\" (Tree.weight tree / float (Tree.count tree))\n\n\n\n    //React.Test.run()\n    Environment.Exit 0\n\n    0 // return an integer exit code\n"
  },
  {
    "path": "src/Demo/Scratch/Scratch.fsproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <OutputType>Exe</OutputType>\r\n    <TargetFramework>net8.0</TargetFramework>\r\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\r\n    <WarnOn>3389;3390;3395</WarnOn>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup>\r\n\t<RunWorkingDirectory>$(OutputPath)\\net8.0</RunWorkingDirectory>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <None Include=\"paket.references\" />\r\n    <Compile Include=\"Store.fs\" />\r\n    <Compile Include=\"Program.fs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Incremental\\Aardvark.Base.Incremental.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Runtime\\Aardvark.Base.Runtime.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Geometry\\Aardvark.Geometry.fsproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Demo/Scratch/Store.fs",
    "content": "﻿module StoreTest\n\nopen System\nopen System.Text\nopen System.Diagnostics\nopen System.Security.Cryptography\nopen System.Runtime.InteropServices\nopen System.Runtime.CompilerServices\nopen Aardvark.Base\nopen Aardvark.Base.Native\nopen Aardvark.Base.Native.FileManager\nopen System.IO\nopen Microsoft.FSharp.NativeInterop\nopen System.Threading\n\n#nowarn \"9\"\n\nmodule FileManagerTypes =\n    let inline (++) (ptr : nativeptr<'a>) (v : 'a) = NativePtr.add ptr (int v)\n    let inline (!!) (ptr : nativeptr<'a>) = NativePtr.read ptr\n    let inline (<--) (ptr : nativeptr<'a>) c = NativePtr.write ptr c\n\n\n    let magic = Guid(\"CFD123CA-17BC-437A-9EFC-6EECE27188FF\")\n\n    [<Literal>]\n    let Red = 0\n\n    [<Literal>]\n    let Black = 1\n\n    [<StructLayout(LayoutKind.Explicit, Size = 32)>]\n    type Block =\n        struct\n            [<FieldOffset(0)>]\n            val mutable public Offset   : int64\n            [<FieldOffset(8)>]\n            val mutable public Size     : int64\n            [<FieldOffset(16)>]\n            val mutable public IsFree   : int\n            [<FieldOffset(20)>]\n            val mutable public Prev     : int\n            [<FieldOffset(24)>]\n            val mutable public Next     : int\n            [<FieldOffset(28)>]\n            val mutable public Chunk    : int\n\n            static member Invalid = Block(Offset = -1L, Size = -1L, IsFree = -1, Prev = -1, Next = -1, Chunk = -1)\n\n\n            override x.ToString() =\n                sprintf \"{ Offset = %d; Size = %d; IsFree = %A; Prev = %d; Next = %d; Chunk = %d }\" x.Offset x.Size (x.IsFree <> 0) x.Prev x.Next x.Chunk\n\n        end\n\n    [<StructLayout(LayoutKind.Explicit, Size = 32)>]\n    type DictEntry =\n        struct\n            [<FieldOffset(0)>]\n            val mutable public Key : Guid       // 16\n            [<FieldOffset(16)>]\n            val mutable public HashCode : int   // 20\n            [<FieldOffset(20)>]\n            val mutable public Next : int       // 24\n            [<FieldOffset(24)>]\n            val mutable public Block : int      // 28\n\n\n            static member Invalid = DictEntry(Key = Guid.Empty, HashCode = -1, Next = -1, Block = -1)\n\n\n\n        end\n        \n    [<StructLayout(LayoutKind.Explicit, Size = 32)>]\n    type Node =\n        struct  \n            [<FieldOffset(0)>]\n            val mutable public Offset : int64\n            [<FieldOffset(8)>]\n            val mutable public Size : int64\n            [<FieldOffset(16)>]\n            val mutable public Entry : int\n            [<FieldOffset(20)>]\n            val mutable public Left : int\n            [<FieldOffset(24)>]\n            val mutable public Right : int\n            [<FieldOffset(28)>]\n            val mutable public Color : int\n\n\n            static member Invalid = Node(Offset = -1L, Size = -1L, Entry = -1, Left = -1, Right = -1, Color = -1)\n\n\n        end\n\n\n    [<StructLayout(LayoutKind.Sequential, Size = 128)>]\n    type Header =\n        struct\n            val mutable public Magic        : Guid      // 16\n            val mutable public MFirst       : int       // 20\n            val mutable public MLast        : int       // 24\n            val mutable public MBlubb       : int64     // 32\n            val mutable public NRoot        : int       // 36\n            val mutable public NCount       : int       // 40\n            val mutable public NFreeList    : int       // 44\n            val mutable public NFreeCount   : int       // 48\n            val mutable public ECount       : int       // 52\n            val mutable public EFreeList    : int       // 56\n            val mutable public EFreeCount   : int       // 60\n            val mutable public DCapacity    : int       // 64\n            val mutable public DCapacityId  : int       // 68\n\n            val mutable public BCount       : int       // 72\n            val mutable public BFreeList    : int       // 76\n            val mutable public BFreeCount   : int       // 80\n            val mutable public BCapacity    : int       // 84\n            val mutable public Chunks       : int       // 88\n\n        end\n\n    type blockptr =\n        struct\n            val mutable public ptr : nativeint\n\n            member inline x.Offset      = NativePtr.ofNativeInt<int64>  x.ptr\n            member inline x.Size        = NativePtr.ofNativeInt<int64>  (8n + x.ptr)\n            member inline x.IsFree      = NativePtr.ofNativeInt<int>    (16n + x.ptr)\n            member inline x.Prev        = NativePtr.ofNativeInt<int>    (20n + x.ptr)\n            member inline x.Next        = NativePtr.ofNativeInt<int>    (24n + x.ptr)\n            member inline x.Chunk       = NativePtr.ofNativeInt<int>    (28n + x.ptr)\n \n \n            member x.Value  \n                with inline get() = NativePtr.read (NativePtr.ofNativeInt<Block> x.ptr)\n                and inline set v = NativePtr.write (NativePtr.ofNativeInt x.ptr) v\n\n            static member inline (+) (ptr : blockptr, index : int) = blockptr(ptr.ptr + nativeint (sizeof<Block> * index))\n            static member Null = blockptr(0n)\n\n            new(p) = { ptr = p }\n\n        end\n\n    type dentryptr =\n        struct\n            val mutable public ptr : nativeint\n            member inline x.Key         = (x.ptr) |> NativePtr.ofNativeInt<Guid>\n            member inline x.HashCode    = (x.ptr + 16n) |> NativePtr.ofNativeInt<int>\n            member inline x.Next        = (x.ptr + 20n) |> NativePtr.ofNativeInt<int>\n            member inline x.Block       = (x.ptr + 24n) |> NativePtr.ofNativeInt<int>\n\n\n            member x.Value  \n                with inline get() = NativePtr.read (NativePtr.ofNativeInt<DictEntry> x.ptr)\n                and inline set v = NativePtr.write (NativePtr.ofNativeInt x.ptr) v\n\n\n            static member inline (+) (ptr : dentryptr, index : int) = dentryptr(ptr.ptr + nativeint (sizeof<DictEntry> * index))\n            static member Null = dentryptr(0n)\n\n            new(p) = { ptr = p }\n        end\n\n    type nodeptr =\n        struct\n            val mutable public ptr : nativeint\n\n            member inline x.Offset      = NativePtr.ofNativeInt<int64> (x.ptr)\n            member inline x.Size        = NativePtr.ofNativeInt<int64> (8n + x.ptr)\n            member inline x.Entry       = NativePtr.ofNativeInt<int> (16n + x.ptr)\n            member inline x.Left        = NativePtr.ofNativeInt<int> (20n + x.ptr)\n            member inline x.Right       = NativePtr.ofNativeInt<int> (24n + x.ptr)\n            member inline x.Color       = NativePtr.ofNativeInt<int> (28n + x.ptr)\n\n            \n            member x.Value\n                with inline get() = NativePtr.read (NativePtr.ofNativeInt<Node> x.ptr)\n                and inline set n = NativePtr.write (NativePtr.ofNativeInt x.ptr) n\n\n            static member inline (+) (ptr : nodeptr, index : int) = nodeptr(ptr.ptr + nativeint (sizeof<Node> * index))\n            static member Null = nodeptr(0n)\n\n            new(p) = { ptr = p }\n        end\n\n    type headerptr =\n        struct\n            val mutable public ptr : nativeint\n            \n            member inline x.Magic           = NativePtr.ofNativeInt<Guid>   (0n + x.ptr)\n\n            member inline x.MFirst          = NativePtr.ofNativeInt<int>    (16n + x.ptr)\n            member inline x.MLast           = NativePtr.ofNativeInt<int>    (20n + x.ptr)\n\n            member inline x.NRoot           = NativePtr.ofNativeInt<int>    (32n + x.ptr)\n            member inline x.NCount          = NativePtr.ofNativeInt<int>    (36n + x.ptr)\n            member inline x.NFreeList       = NativePtr.ofNativeInt<int>    (40n + x.ptr)\n            member inline x.NFreeCount      = NativePtr.ofNativeInt<int>    (44n + x.ptr)\n\n            member inline x.ECount          = NativePtr.ofNativeInt<int>    (48n + x.ptr)\n            member inline x.EFreeList       = NativePtr.ofNativeInt<int>    (52n + x.ptr)\n            member inline x.EFreeCount      = NativePtr.ofNativeInt<int>    (56n + x.ptr)\n            member inline x.DCapacity       = NativePtr.ofNativeInt<int>    (60n + x.ptr)\n            member inline x.DCapacityId     = NativePtr.ofNativeInt<int>    (64n + x.ptr)\n\n            member inline x.BCount          = NativePtr.ofNativeInt<int>    (68n + x.ptr)\n            member inline x.BFreeList       = NativePtr.ofNativeInt<int>    (72n + x.ptr)\n            member inline x.BFreeCount      = NativePtr.ofNativeInt<int>    (76n + x.ptr)\n            member inline x.BCapacity       = NativePtr.ofNativeInt<int>    (80n + x.ptr)\n            member inline x.Chunks          = NativePtr.ofNativeInt<int>    (84n + x.ptr)\n \n\n            member inline x.Value = NativePtr.read (NativePtr.ofNativeInt<Header> x.ptr)\n\n            static member inline (+) (ptr : headerptr, index : int) = nodeptr(ptr.ptr + nativeint (sizeof<Header> * index))\n            static member Null = headerptr(0n)\n\n            new(p) = { ptr = p }\n        end\n\n    [<AllowNullLiteral>]\n    type VirtualNode(ptr : nodeptr, index : int) =\n\n        member x.Index = index\n            \n        override x.GetHashCode() =\n            index\n\n        override x.Equals o =\n            match o with\n                | :? VirtualNode as o -> index = o.Index\n                | _ -> false\n\n        interface IComparable with\n            member x.CompareTo o =\n                match o with\n                    | :? VirtualNode as o ->\n                        let c = compare x.Size o.Size\n                        if c = 0 then \n                            let c = compare x.Offset o.Offset\n                            if c = 0 then compare x.Entry o.Entry\n                            else c\n                        else c\n                    | _ ->\n                        failwith \"uncomparable\"\n\n        member x.Equals (o : VirtualNode) =\n            if isNull o then false\n            else index = o.Index\n\n        member x.Color\n            with get() = !!ptr.Color\n            and set v = ptr.Color <-- v\n\n        member x.Offset\n            with get() = !!ptr.Offset\n            and set v = ptr.Offset <-- v\n\n        member x.Size\n            with get() = !!ptr.Size\n            and set v = ptr.Size <-- v\n\n        member x.Entry\n            with get() = !!ptr.Entry\n            and set v = ptr.Entry <-- v\n\n        member x.Left\n            with get() = \n                let id = !!ptr.Left\n                if id < 0 then null\n                else VirtualNode(ptr + (id - x.Index), id)\n\n            and set (l : VirtualNode) =\n                if isNull l then ptr.Left <-- -1\n                else ptr.Left <-- l.Index\n\n        member x.Right\n            with get() = \n                let id = !!ptr.Right\n                if id < 0 then null\n                else VirtualNode(ptr + (id - x.Index), id)\n\n            and set (l : VirtualNode) =\n                if isNull l then ptr.Right <-- -1\n                else ptr.Right <-- l.Index\n\n    module Tree =\n\n        [<AutoOpen>]\n        module private Tools = \n        \n            type TreeRotation =\n                | Left\n                | Right\n                | RightLeft\n                | LeftRight\n\n            let inline isRed (n : VirtualNode) =\n                not (isNull n) && n.Color = Red\n\n            let inline isBlack (n : VirtualNode) =\n                not (isNull n) && n.Color = Black\n   \n            let inline isNullOrBlack (n : VirtualNode) =\n                isNull n || n.Color = Black\n            \n            let inline is4Node (n : VirtualNode) =\n                isRed n.Left && isRed n.Right\n\n            let inline is2Node (n : VirtualNode) =\n                assert (not (isNull n))\n                isBlack n && isNullOrBlack n.Left && isNullOrBlack n.Right\n\n            let split4Node (n : VirtualNode) =\n                n.Color <- Red\n                n.Left.Color <- Black\n                n.Right.Color <- Black\n\n            let merge2Nodes (parent : VirtualNode) (child1 : VirtualNode) (child2 : VirtualNode) =\n                assert (isRed parent)\n                parent.Color <- Black\n                child1.Color <- Red\n                child2.Color <- Red\n\n            let rotateLeft (n : VirtualNode) =\n                let x = n.Right\n                n.Right <- x.Left\n                x.Left <- n\n                x\n\n            let rotateRight (n : VirtualNode) : VirtualNode =\n                let x = n.Left\n                n.Left <- x.Right\n                x.Right <- n\n                x\n\n            let rotateLeftRight (n : VirtualNode) =\n                let child = n.Left\n                let grandChild = child.Right\n\n                n.Left <- grandChild.Right\n                grandChild.Right <- n\n                child.Right <- grandChild.Left\n                grandChild.Left <- child\n                grandChild\n\n            let rotateRightLeft (n : VirtualNode) =\n                let child = n.Right\n                let grandChild = child.Left\n\n                n.Right <- grandChild.Left\n                grandChild.Left <- n\n                child.Left <- grandChild.Right\n                grandChild.Right <- child\n                grandChild\n\n            let replaceChildOfNodeOrRoot(root : byref<VirtualNode>, parent : VirtualNode, child : VirtualNode, newChild : VirtualNode) =\n                if isNull parent then\n                    root <- newChild\n            \n                else\n                    if parent.Left = child then parent.Left <- newChild\n                    else parent.Right <- newChild\n\n            let replaceNode(root : byref<VirtualNode>, match_ : VirtualNode, parentOfMatch : VirtualNode, successor : VirtualNode, parentOfSuccessor : VirtualNode) =\n                let mutable successor = successor\n                if successor = match_ then\n                    assert (isNull match_.Right)\n                    successor <- match_.Left\n                else\n                    assert ( not (isNull parentOfSuccessor) && isNull successor.Left)\n                    assert ((isNull successor.Right && successor.Color = Red) || (successor.Right.Color = Red && successor.Color = Black))\n\n                    if not (isNull successor.Right) then\n                        successor.Right.Color <- Black\n\n                    if parentOfSuccessor <> match_ then\n                        parentOfSuccessor.Left <- successor.Right\n                        successor.Right <- match_.Right\n\n                    successor.Left <- match_.Left\n\n                if not (isNull successor) then\n                    successor.Color <- match_.Color\n\n                replaceChildOfNodeOrRoot(&root, parentOfMatch, match_, successor)\n\n            let sibling (n : VirtualNode) (p : VirtualNode) =\n                if n = p.Left then p.Right\n                else p.Left\n\n            let insertionBalance(root : byref<VirtualNode>, current : VirtualNode, parent : byref<VirtualNode>, grandParent : VirtualNode, greatGrandParent : VirtualNode) =\n                assert (not (isNull grandParent))\n\n                let parentIsOnRight = grandParent.Right = parent\n                let currentIsOnRight = parent.Right = current\n\n                let mutable newChildOfGreatGrandParent = null\n                if parentIsOnRight = currentIsOnRight then\n                    newChildOfGreatGrandParent <- if currentIsOnRight then rotateLeft grandParent else rotateRight grandParent\n                else\n                    newChildOfGreatGrandParent <- if currentIsOnRight then rotateLeftRight grandParent else rotateRightLeft grandParent\n                    parent <- greatGrandParent\n\n                grandParent.Color <- Red\n                newChildOfGreatGrandParent.Color <- Black\n\n                replaceChildOfNodeOrRoot(&root, greatGrandParent, grandParent, newChildOfGreatGrandParent)\n\n            let rotationNeeded (parent : VirtualNode) (current : VirtualNode) (sibling : VirtualNode) =\n                assert (isRed sibling.Left || isRed sibling.Right)\n\n                if isRed sibling.Left then\n                    if parent.Left = current then\n                        TreeRotation.RightLeft\n                    else\n                        TreeRotation.Right\n                else\n                    if parent.Left = current then\n                        TreeRotation.Left\n                    else\n                        TreeRotation.LeftRight\n\n        let insert (node : VirtualNode) (root : byref<VirtualNode>) =\n            node.Color <- Red\n\n            if isNull root then\n                node.Color <- Black\n                root <- node\n                true\n            else\n                let mutable current : VirtualNode           = root\n                let mutable parent : VirtualNode            = null\n                let mutable grandParent : VirtualNode       = null\n                let mutable greatGrandParent : VirtualNode  = null\n                let mutable order = 0\n                let mutable found = false\n\n                while not (found || isNull current) do\n                    order <- compare node current\n                    if order = 0 then\n                        root.Color <- Black\n                        found <- true\n\n                    else\n                        if is4Node current then\n                            split4Node current\n\n                            if isRed parent then\n                                insertionBalance(&root, current, &parent, grandParent, greatGrandParent)\n\n                        greatGrandParent <- grandParent\n                        grandParent <- parent\n                        parent <- current\n                        current <- if order < 0 then current.Left else current.Right\n                        ()\n\n                if found then \n                    false\n\n                else \n                    assert (not (isNull parent))\n\n                    if order > 0 then parent.Right <- node\n                    else parent.Left <- node\n\n                    if isRed parent then\n                        insertionBalance(&root, node, &parent, grandParent, greatGrandParent)\n\n                    root.Color <- Black\n                    true\n\n        let remove (node : VirtualNode) (root : byref<VirtualNode>) =\n            if isNull root then\n                false\n            else\n                let mutable current : VirtualNode           = root\n                let mutable parent : VirtualNode            = null\n                let mutable grandParent : VirtualNode       = null\n                let mutable match_ : VirtualNode            = null\n                let mutable parentOfMatch : VirtualNode     = null\n                let mutable foundMatch = false\n\n                while not (isNull current) do\n                    if is2Node current then\n                        if isNull parent then\n                            current.Color <- Red\n                        else\n                            let mutable sibling = sibling current parent\n                            if isRed sibling then\n\n                                assert(parent.Color <> Red)\n\n                                if parent.Right = sibling then rotateLeft parent |> ignore\n                                else rotateRight parent |> ignore\n\n                                parent.Color <- Red\n                                sibling.Color <- Black\n\n                                replaceChildOfNodeOrRoot(&root, grandParent, parent, sibling)\n\n                                grandParent <- sibling\n                                if parent = match_ then\n                                    parentOfMatch <- sibling\n\n                                sibling <- if parent.Left = current then parent.Right else parent.Left\n\n                            assert (not (isNull sibling) || sibling.Color <> Red)\n\n                            if is2Node sibling then\n                                merge2Nodes parent current sibling\n                            else\n                                let rotation = rotationNeeded parent current sibling\n                                let mutable newGrandParent = null\n\n                                match rotation with\n                                    | TreeRotation.Right ->\n                                        assert (parent.Left = sibling && sibling.Left.Color = Red)\n                                        sibling.Left.Color <- Black\n                                        newGrandParent <- rotateRight parent\n\n                                    | TreeRotation.Left ->\n                                        assert (parent.Right = sibling && sibling.Right.Color = Red)\n                                        sibling.Right.Color <- Black\n                                        newGrandParent <- rotateLeft parent\n\n                                    | TreeRotation.RightLeft ->\n                                        assert (parent.Right = sibling && sibling.Left.Color = Red)\n                                        newGrandParent <- rotateRightLeft parent\n\n                                    | TreeRotation.LeftRight ->\n                                        assert (parent.Left = sibling && sibling.Right.Color = Red)\n                                        newGrandParent <- rotateLeftRight parent\n\n                                newGrandParent.Color <- parent.Color\n                                parent.Color <- Black\n                                current.Color <- Red\n                                replaceChildOfNodeOrRoot(&root, grandParent, parent, newGrandParent)\n                                if parent = match_ then\n                                    parentOfMatch <- newGrandParent\n\n                                grandParent <- newGrandParent\n\n                    let order = if foundMatch then -1 else compare node current\n                    if order = 0 then\n                        foundMatch <- true\n                        match_ <- current\n                        parentOfMatch <- parent\n\n                    grandParent <- parent\n                    parent <- current\n\n                    current <- if order < 0 then current.Left else current.Right\n                \n                if not (isNull match_) then\n                    replaceNode(&root, match_, parentOfMatch, parent, grandParent)\n\n                if not (isNull root) then\n                    root.Color <- Black\n\n                foundMatch\n\n        let removeKey (offset : int64) (size : int64) (root : byref<VirtualNode>) =\n            if isNull root then\n                null\n            else\n                let mutable current : VirtualNode           = root\n                let mutable parent : VirtualNode            = null\n                let mutable grandParent : VirtualNode       = null\n                let mutable match_ : VirtualNode            = null\n                let mutable parentOfMatch : VirtualNode     = null\n                let mutable foundMatch = false\n\n                while not (isNull current) do\n                    if is2Node current then\n                        if isNull parent then\n                            current.Color <- Red\n                        else\n                            let mutable sibling = sibling current parent\n                            if isRed sibling then\n\n                                assert(parent.Color <> Red)\n\n                                if parent.Right = sibling then rotateLeft parent |> ignore\n                                else rotateRight parent |> ignore\n\n                                parent.Color <- Red\n                                sibling.Color <- Black\n\n                                replaceChildOfNodeOrRoot(&root, grandParent, parent, sibling)\n\n                                grandParent <- sibling\n                                if parent = match_ then\n                                    parentOfMatch <- sibling\n\n                                sibling <- if parent.Left = current then parent.Right else parent.Left\n\n                            assert (not (isNull sibling) || sibling.Color <> Red)\n\n                            if is2Node sibling then\n                                merge2Nodes parent current sibling\n                            else\n                                let rotation = rotationNeeded parent current sibling\n                                let mutable newGrandParent = null\n\n                                match rotation with\n                                    | TreeRotation.Right ->\n                                        assert (parent.Left = sibling && sibling.Left.Color = Red)\n                                        sibling.Left.Color <- Black\n                                        newGrandParent <- rotateRight parent\n\n                                    | TreeRotation.Left ->\n                                        assert (parent.Right = sibling && sibling.Right.Color = Red)\n                                        sibling.Right.Color <- Black\n                                        newGrandParent <- rotateLeft parent\n\n                                    | TreeRotation.RightLeft ->\n                                        assert (parent.Right = sibling && sibling.Left.Color = Red)\n                                        newGrandParent <- rotateRightLeft parent\n\n                                    | TreeRotation.LeftRight ->\n                                        assert (parent.Left = sibling && sibling.Right.Color = Red)\n                                        newGrandParent <- rotateLeftRight parent\n\n                                newGrandParent.Color <- parent.Color\n                                parent.Color <- Black\n                                current.Color <- Red\n                                replaceChildOfNodeOrRoot(&root, grandParent, parent, newGrandParent)\n                                if parent = match_ then\n                                    parentOfMatch <- newGrandParent\n\n                                grandParent <- newGrandParent\n\n                    let order = \n                        if foundMatch then \n                            -1 \n                        else \n                            let c = compare size current.Size\n                            if c = 0 then compare offset current.Offset\n                            else c\n\n                    if order = 0 then\n                        foundMatch <- true\n                        match_ <- current\n                        parentOfMatch <- parent\n\n                    grandParent <- parent\n                    parent <- current\n\n                    current <- if order < 0 then current.Left else current.Right\n                \n                if not (isNull match_) then\n                    replaceNode(&root, match_, parentOfMatch, parent, grandParent)\n\n                if not (isNull root) then\n                    root.Color <- Black\n\n                if not foundMatch then null\n                else match_\n\n        let findSmallestGreater (size : int64) (root : VirtualNode) =\n            if isNull root then\n                null\n            else\n                let mutable best = null\n                let mutable current = root\n                while not (isNull current) do\n                    let cmp = compare size current.Size\n\n\n                    if cmp = 0 then \n                        best <- current\n                        current <- null\n\n                    elif cmp > 0 then\n                        current <- current.Right\n\n                    else\n                        best <- current\n                        current <- current.Left\n\n                best\n\n        let removeSmallestGreater (size : int64) (root : byref<VirtualNode>) =\n            let n = findSmallestGreater size root\n\n            if isNull n then\n                null\n            else\n                let res = remove n &root\n                assert res\n                n\n        \n    let primeSizes =\n        [|\n            (*    prime no.           prime *)\n            (*           2                3       +  1 = 2^2 *)\n            (*           4 *) 7                // +  1 = 2^3, minimal size\n            (*           6 *) 13               // +  3 = 2^4\n            (*          11 *) 31               // +  1 = 2^5\n            (*          18 *) 61               // +  3 = 2^6\n            (*          31 *) 127              // +  1 = 2^7\n            (*          54 *) 251              // +  5 = 2^8\n            (*          97 *) 509              // +  3 = 2^9\n            (*         172 *) 1021             // +  3 = 2^10\n            (*         309 *) 2039             // +  9 = 2^11\n            (*         564 *) 4093             // +  3 = 2^12\n            (*        1028 *) 8191             // +  1 = 2^13\n            (*        1900 *) 16381            // +  3 = 2^14\n            (*        3512 *) 32749            // + 19 = 2^15\n            (*        6542 *) 65521            // + 15 = 2^16\n            (*       12251 *) 131071           // +  1 = 2^17\n            (*       23000 *) 262139           // +  5 = 2^18\n            (*       43390 *) 524287           // +  1 = 2^19\n            (*       82025 *) 1048573          // +  3 = 2^20\n            (*      155611 *) 2097143          // +  9 = 2^21\n            (*      295947 *) 4194301          // +  3 = 2^22\n            (*      564163 *) 8388593          // + 15 = 2^23\n            (*     1077871 *) 16777213         // +  3 = 2^24\n            (*     2063689 *) 33554393         // + 39 = 2^25\n            (*     3957809 *) 67108859         // +  5 = 2^26\n            (*     7603553 *) 134217689        // + 39 = 2^27\n            (*    14630843 *) 268435399        // + 57 = 2^28\n            (*    28192750 *) 536870909        // +  3 = 2^29\n            (*    54400028 *) 1073741789       // + 35 = 2^30\n            (*   105097565 *) 2147483647       // +  1 = 2^31\n        |]\n\n\n    [<AllowNullLiteral>]\n    type FileHandle =\n        class\n            val mutable internal EntryId : int\n            val mutable internal Length : int64\n            val public Id : Guid\n\n            member x.Size = x.Length\n            member x.Exists = x.EntryId >= 0\n\n            internal new(id : Guid, eid : int, length : int64) = { Id = id; EntryId = eid; Length = length }\n        end\n\n    type BlockHandle =\n        struct\n            val mutable internal BlockId : int\n            internal new(bid : int) = { BlockId = bid }\n        end\n\n    type FileManagerStatistics =\n        {\n            growManagerTime     : MicroTime\n            growDictTime        : MicroTime\n            growDataTime        : MicroTime\n            rehashTime          : MicroTime\n            reallocTime         : MicroTime\n            allocCount          : int64\n            freeCount           : int64\n            fileCount           : int\n            blockCount          : int\n        }\n\nopen FileManagerTypes\n\ntype FileManager(mem : Memory, getChunk : int -> Memory) =\n    static let initialCapacityId = 7\n    static let initialMemoryCapacity = 1L <<< 20\n    static let chunkSize = 2L <<< 30\n    static let isStore (m : Memory) =\n        if m.Size >= int64 sizeof<Header> then\n            let ptr = m.Pointer |> headerptr\n            magic.Equals !!ptr.Magic\n        else\n            false\n\n    static let headerSize = int64 sizeof<Header>\n\n    static let managerSize (bCapacity : int) =\n        let nCapacity = if bCapacity > 0 then bCapacity + 1 else 0\n\n        int64 sizeof<Node> * int64 nCapacity +\n        int64 sizeof<Block> * int64 bCapacity\n\n    static let dictSize (dCapacity : int) =\n        int64 (sizeof<int> + sizeof<DictEntry>) * int64 dCapacity\n\n\n    let mutable mem = mem\n\n    let chunks = System.Collections.Generic.List<Memory>()\n\n    let mutable header = headerptr.Null\n    let mutable nodes = nodeptr.Null\n    let mutable blocks = blockptr.Null\n    let mutable entries = dentryptr.Null\n    let mutable buckets = NativePtr.zero<int>\n\n    let growManagerTime = Stopwatch()\n    let growDictTime = Stopwatch()\n    let growDataTime = Stopwatch()\n    let rehashTime = Stopwatch()\n    let reallocTime = Stopwatch()\n    let mutable allocCount = 0L\n    let mutable freeCount = 0L\n        \n\n    let handleCache = Dict<Guid, FileHandle>()\n\n    let nCapacity() =\n        let cap = !!header.BCapacity\n        if cap > 0 then cap + 1 else 0\n\n    let bCapacity() = !!header.BCapacity\n    let dCapacity() = !!header.DCapacity\n\n    let setPointers() =\n        let ptr = mem.Pointer\n\n        header <- ptr |> headerptr\n        let ptr = ptr + nativeint headerSize\n\n        let nCapacity = nCapacity()\n        let bCapacity = bCapacity()\n        let dCapacity = dCapacity()\n\n        nodes <- ptr |> nodeptr\n        let ptr = ptr + (nativeint sizeof<Node> * nativeint nCapacity)\n\n        blocks <- ptr |> blockptr\n        let ptr = ptr + (nativeint sizeof<Block> * nativeint bCapacity)\n\n        entries <- ptr |> dentryptr\n        let ptr = ptr + (nativeint sizeof<DictEntry> * nativeint dCapacity)\n\n        buckets <- NativePtr.ofNativeInt ptr\n        let ptr = ptr + (nativeint sizeof<int> * nativeint dCapacity)\n\n        ()\n\n\n    let rec growManager() =\n        growManagerTime.Start()\n\n        let oldBCapacity = !!header.BCapacity\n        let newBCapacity = 2 * oldBCapacity\n        let oldNCapacity = if oldBCapacity = 0 then 0 else oldBCapacity + 1\n        let newNCapacity = if newBCapacity = 0 then 0 else newBCapacity + 1\n\n        let dictSize = dictSize !!header.DCapacity\n\n        let newTotalSize =\n            headerSize +\n            managerSize newBCapacity +\n            dictSize\n\n        let oldTotalSize =\n            headerSize +\n            managerSize oldBCapacity +\n            dictSize\n\n        header.BCapacity <-- newBCapacity\n        mem.Realloc(newTotalSize)\n            \n        let newPtr = mem.Pointer + nativeint newTotalSize\n        let oldPtr = mem.Pointer + nativeint oldTotalSize\n\n        // move the dict\n        let newPtr = newPtr - nativeint dictSize\n        let oldPtr = oldPtr - nativeint dictSize\n        Marshal.Move(oldPtr, newPtr, dictSize)\n\n        // move the Blocks\n        let oldSize = int64 sizeof<Block> * int64 oldBCapacity\n        let newSize = int64 sizeof<Block> * int64 newBCapacity\n        let newPtr = newPtr - nativeint newSize\n        let oldPtr = oldPtr - nativeint oldSize\n        Marshal.Move(oldPtr, newPtr, oldSize)\n        Marshal.Set(newPtr + nativeint oldSize, -1, newSize - oldSize)\n\n        // move the Nodes\n        let oldSize = int64 sizeof<Node> * int64 oldNCapacity\n        let newSize = int64 sizeof<Node> * int64 newNCapacity\n        let newPtr = newPtr - nativeint newSize\n        let oldPtr = oldPtr - nativeint oldSize\n        Marshal.Move(oldPtr, newPtr, oldSize)\n        Marshal.Set(newPtr + nativeint oldSize, -1, newSize - oldSize)\n\n            \n        setPointers()\n        growManagerTime.Stop()\n\n    and growDict() =\n        growDictTime.Start()\n        let oldDCapacityId = !!header.DCapacityId\n        let oldDCapacity = !!header.DCapacity\n        let newDCapacityId = 1 + oldDCapacityId\n        let newDCapacity = primeSizes.[newDCapacityId]\n\n        let oldDictSize = dictSize oldDCapacity\n        let newDictSize = dictSize newDCapacity\n\n        let managerSize = managerSize !!header.BCapacity\n\n        let newTotalSize =\n            headerSize +\n            managerSize +\n            newDictSize\n\n        let oldTotalSize =\n            headerSize +\n            managerSize +\n            oldDictSize\n                \n        header.DCapacityId <-- newDCapacityId\n        header.DCapacity <-- newDCapacity\n        reallocTime.Start()\n        mem.Realloc(newTotalSize)\n        reallocTime.Stop()\n\n        // move the dict\n        let newPtr = mem.Pointer + nativeint newTotalSize\n        let oldPtr = mem.Pointer + nativeint oldTotalSize\n\n\n        // set the buckets to 0\n        let newSize = int64 sizeof<int> * int64 newDCapacity\n        let oldSize = int64 sizeof<int> * int64 oldDCapacity\n        let newPtr = newPtr - nativeint newSize\n        let oldPtr = oldPtr - nativeint oldSize\n        Marshal.Set(newPtr, 0, newSize)\n\n        // move the DictEntries\n        let newSize = int64 sizeof<DictEntry> * int64 newDCapacity\n        let oldSize = int64 sizeof<DictEntry> * int64 oldDCapacity\n        let newPtr = newPtr - nativeint newSize\n        let oldPtr = oldPtr - nativeint oldSize\n        Marshal.Move(oldPtr, newPtr, oldSize)\n\n        setPointers()\n\n        rehashTime.Start()\n        rehash()\n        rehashTime.Stop()\n\n        growDictTime.Stop()\n\n    and growData(needed : int64) =\n        growDataTime.Start()\n\n        let chunkIndex = chunks.Count - 1\n\n        let oldLastId = !!header.MLast\n        let _, freeBlockId = newBlock()\n        let pFreeBlock = blocks + freeBlockId\n        pFreeBlock.Prev <-- oldLastId\n        pFreeBlock.Next <-- -1\n        pFreeBlock.IsFree <-- 0\n\n        if chunkIndex >= 0 && chunks.[chunkIndex].Size < chunkSize then\n            let lastChunk = chunks.[chunkIndex]\n            let oldChunkCapacity = lastChunk.Size\n            let newChunkCapacity = 2L * oldChunkCapacity\n            lastChunk.Realloc newChunkCapacity\n\n            let offset = chunkSize * int64 chunkIndex + oldChunkCapacity\n\n            // free the new block\n            pFreeBlock.Offset <-- offset\n            pFreeBlock.Size <-- newChunkCapacity - oldChunkCapacity\n            pFreeBlock.Chunk <-- chunkIndex\n\n        else\n            let chunkIndex = 1 + chunkIndex\n            let newChunk = getChunk chunkIndex\n            let newChunkCapacity = max (1L <<< 20) (Fun.NextPowerOfTwo needed)\n            newChunk.Clear newChunkCapacity\n            chunks.Add newChunk\n\n            let offset = chunkSize * int64 chunkIndex\n            pFreeBlock.Offset <-- offset\n            pFreeBlock.Size <-- newChunkCapacity\n            pFreeBlock.Chunk <-- chunkIndex\n\n            header.Chunks <-- !!header.Chunks + 1\n\n        if oldLastId < 0 then header.MFirst <-- freeBlockId\n        else (blocks + oldLastId).Next <-- freeBlockId\n\n        free freeBlockId\n        growDataTime.Stop()\n\n\n    and newBlock() : bool * int =\n        if !!header.BFreeCount > 0 then\n            let id = !!header.BFreeList\n            assert (id >= 0)\n\n            let b = blocks + id\n            header.BFreeList <-- !!b.Next\n            header.BFreeCount <-- !!header.BFreeCount - 1\n            b.Next <-- -1\n\n\n            false, id\n        else\n            let mutable resized = false\n            let cnt = !!header.BCount\n            if cnt >= bCapacity() then\n                resized <- true\n                growManager()\n\n            let id = cnt\n            header.BCount <-- cnt + 1\n            resized, id\n\n    and deleteBlock(bid : int) =\n        assert (bid >= 0)\n        let n = !!header.BFreeList\n        let mutable b = blocks + bid\n        b.Value <- Block.Invalid\n        b.Next <-- n\n        header.BFreeList <-- bid\n        header.BFreeCount <-- !!header.BFreeCount + 1\n\n    and newNode() : bool * int =\n        if !!header.NFreeCount > 0 then\n            let id = !!header.NFreeList\n            assert (id >= 0)\n\n            let n = nodes + id\n            header.NFreeList <-- !!n.Left\n            header.NFreeCount <-- !!header.NFreeCount - 1\n            n.Left <-- -1\n\n\n            false, id\n        else\n            let mutable resized = false\n            let cnt = !!header.NCount\n            if cnt >= nCapacity() then\n                resized <- true\n                growManager()\n\n            let id = cnt\n            header.NCount <-- cnt + 1\n            resized, id\n            \n    and deleteNode(nid : int) =\n        assert (nid >= 0)\n        let next = !!header.NFreeList\n        let mutable n = nodes + nid\n        n.Value <- Node.Invalid\n        n.Left <-- next\n        header.NFreeList <-- nid\n        header.NFreeCount <-- !!header.NFreeCount + 1   \n\n    and newEntry() : bool * int =\n        if !!header.EFreeCount > 0 then\n            let id = !!header.EFreeList\n            assert (id >= 0)\n\n            let e = entries + id\n            header.EFreeList <-- !!e.Next\n            header.EFreeCount <-- !!header.EFreeCount - 1\n            e.Next <-- -1\n\n            false, id\n        else\n            let mutable resized = false\n            let cnt = !!header.ECount\n            if cnt >= dCapacity() then\n                resized <- true\n                growDict()\n\n            let id = cnt\n            header.ECount <-- cnt + 1\n            resized, id\n\n    and deleteEntry(eid : int) =\n        assert (eid >= 0)\n\n        let next = !!header.EFreeList\n        let mutable e = entries + eid\n        e.Value <- DictEntry.Invalid\n        e.Next <-- next\n        header.EFreeList <-- eid\n        header.EFreeCount <-- !!header.EFreeCount + 1   \n\n\n\n    and withTree (f : ref<VirtualNode> -> 'a) =\n        let root = \n            let rid = !!header.NRoot\n            if rid < 0 then null\n            else VirtualNode(nodes + rid, rid)\n\n        let r = ref root\n        let res = f r\n        let root = !r\n\n        if isNull root then header.NRoot <-- -1\n        else header.NRoot <-- root.Index\n\n        res\n\n    and insertFreeBlock (bid : int) =\n        assert (bid >= 0)\n\n        let pBlock = blocks + bid\n        let size = !!pBlock.Size\n        let offset = !!pBlock.Offset\n        let _, nid = newNode()\n        let pEntry = ()\n\n        let pNode = nodes + nid\n        pNode.Offset <-- offset\n        pNode.Size <-- size\n        pNode.Left <-- -1\n        pNode.Right <-- -1\n        pNode.Entry <-- bid\n        pNode.Color <-- Red\n\n        withTree (fun root ->\n            let nn = VirtualNode(pNode, nid)\n            let worked = Tree.insert nn &root.contents\n            if not worked then\n                Log.warn \"could not add to freelist: %A\" (offset, size)\n                deleteNode nid\n                    \n        )\n\n    and removeFreeBlock (bid : int) =\n        assert (bid >= 0)\n\n        let pBlock = blocks + bid\n        let offset = !!pBlock.Offset\n        let size = !!pBlock.Size\n\n        let toKill =\n            withTree(fun root ->\n                Tree.removeKey offset size &root.contents\n            )\n\n        if not (isNull toKill) then\n            deleteNode toKill.Index\n            true\n        else\n            Log.warn \"could not remove from freelist: %A\" (offset, size)\n            false\n\n    and getFreeBlock (size : int64) : bool * int =\n        let node =\n            withTree (fun tree ->\n                Tree.removeSmallestGreater size &tree.contents\n            )\n\n        if isNull node then \n            growData size\n            let _, bid = getFreeBlock size\n            true, bid\n        else\n            let bid = node.Entry\n            assert (bid >= 0)\n            assert (!!(blocks + bid).Size >= size)\n            deleteNode node.Index\n            false, bid\n\n    and alloc (size : int64) =\n        if size <= 0L then\n            false, -1\n        else\n            allocCount <- allocCount + 1L\n            let mutable resized, bid = getFreeBlock size\n            let mutable pBlock = blocks + bid\n            let blockSize = !!pBlock.Size\n\n            if blockSize > size then\n                let r, rid = newBlock()\n                if r then\n                    pBlock <- blocks + bid\n                    resized <- true\n\n\n                let restNext = !!pBlock.Next\n\n                let mutable pRestBlock = blocks + rid\n                pRestBlock.Offset <-- !!pBlock.Offset + size\n                pRestBlock.Size <-- blockSize - size\n                pRestBlock.IsFree <-- 1\n                pRestBlock.Prev <-- bid\n                pRestBlock.Next <-- restNext\n                pRestBlock.Chunk <-- !!pBlock.Chunk\n\n                if restNext < 0 then header.MLast <-- rid\n                else (blocks + restNext).Prev <-- rid\n\n                pBlock.Size <-- size\n                pBlock.Next <-- rid \n                insertFreeBlock rid\n\n\n            pBlock.IsFree <-- 0\n            assert (!!pBlock.Size = size)\n            resized, bid\n\n    and free (bid : int) =\n        if bid >= 0 then\n            freeCount <- freeCount + 1L\n            let pBlock = blocks + bid\n            if !!pBlock.IsFree = 0 then\n                let chunk = !!pBlock.Chunk\n                let prev = !!pBlock.Prev\n                let next = !!pBlock.Next\n                let pPrevBlock = blocks + prev\n                let pNextBlock = blocks + next\n\n                if prev < 0 then\n                    header.MFirst <-- bid\n\n                elif !!pPrevBlock.IsFree <> 0 && !!pPrevBlock.Chunk = chunk then\n                    // merge with prev\n                    removeFreeBlock prev |> ignore\n\n                    pBlock.Offset <-- !!pPrevBlock.Offset\n                    pBlock.Size <-- !!pPrevBlock.Size + !!pBlock.Size\n\n\n                    let pp = !!pPrevBlock.Prev\n                    pBlock.Prev <-- pp\n                    if pp < 0 then header.MFirst <-- bid\n                    else (blocks + pp).Next <-- bid\n\n                    deleteBlock prev\n\n\n                if next < 0 then\n                    header.MLast <-- bid\n\n                elif !!pNextBlock.IsFree <> 0 && !!pNextBlock.Chunk = chunk then\n                    // merge with next\n                    removeFreeBlock next |> ignore\n\n                    pBlock.Size <-- !!pBlock.Size + !!pNextBlock.Size\n\n                    let nn = !!pNextBlock.Next\n                    pBlock.Next <-- nn\n                    if nn < 0 then header.MLast <-- bid\n                    else (blocks + nn).Prev <-- bid\n                    \n                    deleteBlock next\n\n                pBlock.IsFree <-- 1\n                insertFreeBlock bid\n\n        \n\n    and findEntry (key : Guid) (hashCode : int) =\n        let bid = hashCode % !!header.DCapacity\n        let pBucket = NativePtr.add buckets bid\n\n        let b = !!pBucket - 1\n        if b < 0 then\n            -1\n        else\n            let pEntry = entries + b\n            if !!pEntry.HashCode = hashCode && key.Equals !!pEntry.Key then\n                b\n            else\n                let rec search (id : int) (pEntry : dentryptr) = \n                    if id < 0 then\n                        -1\n                    elif !!pEntry.HashCode = hashCode && key.Equals !!pEntry.Key then\n                        id\n                    else\n                        let next = !!pEntry.Next\n                        search next (entries + next)\n\n                let next = !!pEntry.Next\n                search next (entries + next)\n\n//        and removeEntry (key : Guid) (hashCode : int) =\n//            let bid = hashCode % !!header.DCapacity\n//            let pBucket = NativePtr.add buckets bid\n//\n//            let b = !!pBucket - 1\n//            if b < 0 then\n//                -1\n//            else\n//                let pEntry = entries + b\n//                if !!pEntry.HashCode = hashCode && key.Equals !!pEntry.Key then\n//                    let block = !!pEntry.Block\n//                    deleteEntry b\n//                    pBucket <-- 0\n//                    block\n//                else\n//                    let rec search (last : dentryptr) (id : int) (pEntry : dentryptr) = \n//                        if id < 0 then\n//                            -1\n//                        elif !!pEntry.HashCode = hashCode && key.Equals !!pEntry.Key then\n//                            let next = !!pEntry.Next\n//                            last.Next <-- next\n//                            \n//                            let block = !!pEntry.Block\n//                            deleteEntry id\n//                            block\n//                        else\n//                            let next = !!pEntry.Next\n//                            search pEntry next (entries + next)\n//\n//                    let next = !!pEntry.Next\n//                    search pEntry next (entries + next) \n\n    and removeEntryPtr (eid : int) =\n        if eid >= 0 then\n            let pRemEntry = entries + eid\n            let hashCode = !!pRemEntry.HashCode\n            let bid = hashCode % !!header.DCapacity\n            let pBucket = NativePtr.add buckets bid\n\n            let b = !!pBucket - 1\n            if b < 0 then\n                false\n            else\n                let pEntry = entries + b\n                if b = eid then\n                    let next = !!pEntry.Next\n                    deleteEntry b\n                    pBucket <-- 1 + next\n                    true\n                else\n                    let rec search (last : dentryptr) (id : int) (pEntry : dentryptr) = \n                        if id < 0 then\n                            false\n                        elif id = eid then\n                            let next = !!pEntry.Next\n                            last.Next <-- next\n                            \n                            let block = !!pEntry.Block\n                            deleteEntry id\n                            true\n                        else\n                            let next = !!pEntry.Next\n                            search pEntry next (entries + next)\n\n                    let next = !!pEntry.Next\n                    search pEntry next (entries + next) \n        else\n            true\n\n    and setEntry (key : Guid) (hashCode : int) (value : int) =\n        let eid = findEntry key hashCode\n        if eid >= 0 then\n            let pEntry = entries + eid\n            pEntry.Block <-- value\n            eid\n        else\n            let _, eid = newEntry()\n               \n            let pEntry = entries + eid\n            pEntry.Key <-- key\n            pEntry.HashCode <-- hashCode\n            pEntry.Block <-- value\n            pEntry.Next <-- -1\n\n            let bid = hashCode % !!header.DCapacity\n            let pBucket = NativePtr.add buckets bid\n\n            let b = !!pBucket - 1\n            pEntry.Next <-- b\n            pBucket <-- eid + 1\n            eid\n\n    and rehash() =\n        let mutable pEntry = entries\n        let eCount = !!header.ECount\n        let dCapacity = !!header.DCapacity\n        for i in 0..eCount-1 do\n            let hash = !!pEntry.HashCode\n            if hash >= 0 then\n                let bid = hash % dCapacity\n                let pBucket = NativePtr.add buckets bid\n                let b = !!pBucket - 1\n                pEntry.Next <-- b\n                pBucket <-- i + 1\n\n            pEntry <- pEntry + 1\n\n\n\n    do  if isStore mem then\n            setPointers()\n\n            let numChunks = !!header.Chunks\n            for i in 0..numChunks-1 do\n                chunks.Add(getChunk i)\n\n        else\n            let dCapacityId = initialCapacityId\n            let dCapacity = primeSizes.[dCapacityId]\n            let bCapacity = Fun.NextPowerOfTwo dCapacity\n\n            let total =\n                headerSize +\n                managerSize bCapacity +\n                dictSize dCapacity\n\n            mem.Clear(total)\n\n            let c0 = getChunk 0\n            chunks.Add c0\n            c0.Clear(initialMemoryCapacity)\n\n            let initialHeader =\n                Header(\n                    Magic        = magic,\n                    MFirst       = -1,\n                    MLast        = -1,\n                    NRoot        = -1,\n                    NCount       = 0,\n                    NFreeList    = -1,\n                    NFreeCount   = 0,\n                    ECount       = 0,\n                    EFreeList    = -1,\n                    EFreeCount   = 0,\n                    DCapacity    = dCapacity,\n                    DCapacityId  = dCapacityId,\n                        \n                    BCount       = 0,\n                    BFreeList    = -1,\n                    BFreeCount   = 0,\n                    BCapacity    = bCapacity,\n                    Chunks       = 1  \n                )     \n                    \n            NativePtr.write (NativePtr.ofNativeInt mem.Pointer) initialHeader      \n            setPointers()\n\n            // create the new free-block\n            let _,bid = newBlock()\n            let pBlock = blocks + bid\n            pBlock.Offset <-- 0L\n            pBlock.Size <-- initialMemoryCapacity\n            pBlock.IsFree <-- 0\n            pBlock.Prev <-- -1\n            pBlock.Next <-- -1\n            pBlock.Chunk <-- 0\n\n            // store the free-block in a new entry\n            // and ensure its correct linkage\n            header.MFirst <-- bid\n            header.MLast <-- bid\n\n            // free the new block\n            free bid\n            \n    // ===================================================================================================\n    // Block API\n    // ===================================================================================================\n    member x.Alloc (size : int64) =\n        let _,bid = alloc size\n        BlockHandle bid\n\n    member x.Free (block : BlockHandle) =\n        free block.BlockId\n\n    member x.SizeOf(block : BlockHandle) =\n        let bid = block.BlockId\n        if bid < 0 then 0L\n        else\n            let pBlock = blocks + bid\n            !!pBlock.Size\n\n    member x.Copy(src : byte[], srcOffset : int64, dst : BlockHandle, dstOffset : int64, length : int64) =\n        if length <= 0L then\n            ()\n        else\n            let bid = dst.BlockId\n            if bid < 0 then failwithf \"[FileManager] cannot write %d bytes to block of size 0\" length\n            if isNull src then failwith \"[FileManager] cannot read from null array\"\n\n            let pBlock = blocks + bid\n            assert (!!pBlock.IsFree <> 1)\n\n            let blockSize = !!pBlock.Size\n            if length > blockSize then failwithf \"[FileManager] cannot write %d bytes to block of size %d\" length blockSize\n\n            let chunk = !!pBlock.Chunk\n            let memory = chunks.[chunk].Pointer - nativeint chunkSize * nativeint chunk\n\n            let gc = GCHandle.Alloc(src, GCHandleType.Pinned)\n            try\n                let dst = memory + nativeint !!pBlock.Offset + nativeint dstOffset\n                let src = gc.AddrOfPinnedObject() + nativeint srcOffset\n                Marshal.Copy(src, dst, length)\n            finally\n                gc.Free()\n\n    member x.Copy(src : BlockHandle, srcOffset : int64, dst : byte[], dstOffset : int64, length : int64) =\n        if length <= 0L then\n            ()\n        else\n            let bid = src.BlockId\n            if bid < 0 then failwithf \"[FileManager] cannot read %d bytes from block of size 0\" length\n            if isNull dst then failwith \"[FileManager] cannot write to null array\"\n\n            let pBlock = blocks + bid\n            assert (!!pBlock.IsFree <> 1)\n            let blockSize = !!pBlock.Size\n            if length > blockSize then failwithf \"[FileManager] cannot read %d bytes from block of size %d\" length blockSize\n                \n            let chunk = !!pBlock.Chunk\n            let memory = chunks.[chunk].Pointer - nativeint chunkSize * nativeint chunk\n\n\n            let gc = GCHandle.Alloc(dst, GCHandleType.Pinned)\n            try\n                let dst = gc.AddrOfPinnedObject() + nativeint dstOffset\n                let src = memory + nativeint !!pBlock.Offset + nativeint srcOffset\n                Marshal.Copy(src, dst, length)\n            finally\n                gc.Free()\n\n    member x.Copy(src : BlockHandle, srcOffset : int64, dst : BlockHandle, dstOffset : int64, length : int64) =\n        if length <= 0L then\n            ()\n        else\n            let sid = src.BlockId\n            let did = src.BlockId\n\n            if sid < 0 then failwithf \"[FileManager] cannot copy %d bytes from block of size 0\" length\n            if did < 0 then failwithf \"[FileManager] cannot copy %d bytes to block of size 0\" length\n\n            let pSrc = blocks + sid\n            let pDst = blocks + did\n\n            assert (!!pSrc.IsFree <> 1)\n            assert (!!pDst.IsFree <> 1)\n\n            let srcSize = !!pSrc.Size\n            let dstSize = !!pDst.Size\n\n\n\n            if length > srcSize then failwithf \"[FileManager] cannot copy %d bytes from block of size %d\" length srcSize\n            if length > dstSize then failwithf \"[FileManager] cannot copy %d bytes to block of size %d\" length dstSize\n\n            let dstChunk = !!pDst.Chunk\n            let dstMemory = chunks.[dstChunk].Pointer - nativeint chunkSize * nativeint dstChunk\n\n            let srcChunk = !!pSrc.Chunk\n            let srcMemory = chunks.[srcChunk].Pointer - nativeint chunkSize * nativeint srcChunk\n\n\n            Marshal.Copy(srcMemory + nativeint !!pSrc.Offset + nativeint srcOffset, dstMemory + nativeint !!pDst.Offset + nativeint dstOffset, length)\n\n    member x.Copy(src : BlockHandle, dst : byte[], dstOffset : int64, length : int64) = x.Copy(src, 0L, dst, dstOffset, length)\n    member x.Copy(src : BlockHandle, srcOffset : int64, dst : byte[], length : int64) = x.Copy(src, srcOffset, dst, 0L, length)\n    member x.Copy(src : BlockHandle, dst : byte[], length : int64) = x.Copy(src, 0L, dst, 0L, length)\n    member x.Copy(src : BlockHandle, dst : byte[]) = x.Copy(src, 0L, dst, 0L, dst.LongLength)\n    member x.Copy(src : byte[], dst : BlockHandle, dstOffset : int64, length : int64) = x.Copy(src, 0L, dst, dstOffset, length)\n    member x.Copy(src : byte[], srcOffset : int64, dst : BlockHandle, length : int64) = x.Copy(src, srcOffset, dst, 0L, length)\n    member x.Copy(src : byte[], dst : BlockHandle, length : int64) = x.Copy(src, 0L, dst, 0L, length)\n    member x.Copy(src : byte[], dst : BlockHandle) = x.Copy(src, 0L, dst, 0L, src.LongLength)\n    member x.Copy(src : BlockHandle, dst : BlockHandle, dstOffset : int64, length : int64) = x.Copy(src, 0L, dst, dstOffset, length)\n    member x.Copy(src : BlockHandle, srcOffset : int64, dst : BlockHandle, length : int64) = x.Copy(src, srcOffset, dst, 0L, length)\n    member x.Copy(src : BlockHandle, dst : BlockHandle, length : int64) = x.Copy(src, 0L, dst, 0L, length)\n    member x.Copy(src : BlockHandle, dst : BlockHandle) = x.Copy(src, 0L, dst, 0L, x.SizeOf src)\n\n    member x.Read(src : BlockHandle) =\n        if src.BlockId >= 0 then\n            let size = x.SizeOf src\n            let arr = Array.zeroCreate (int size)\n            x.Copy(src, 0L, arr, 0L, arr.LongLength)\n            arr\n        else\n            [||]\n\n\n    // ===================================================================================================\n    // File API\n    // ===================================================================================================\n\n    member x.Exists(file : FileHandle) =\n        file.EntryId >= 0\n\n    member x.GetCurrentBlock(file : FileHandle) =\n        if file.EntryId < 0 then\n            BlockHandle(-1)\n        else\n            let pEntry = entries + file.EntryId\n            BlockHandle(!!pEntry.Block)\n\n\n    member x.GetFile (key : Guid) =\n        handleCache.GetOrCreate(key, fun key ->\n            let hashCode = key.GetHashCode() &&& 0x7FFFFFFF\n            let eid = findEntry key hashCode\n            if eid < 0 then\n                FileHandle(key, -1, 0L)\n            else\n                let bid = !!(entries + eid).Block |> BlockHandle\n                let size = x.SizeOf bid\n                FileHandle(key, eid, size)\n        )\n\n    member x.TryGetFile (key : Guid, [<Out>] file : byref<FileHandle>) =\n        if handleCache.TryGetValue(key, &file) then\n            true\n        else\n            let hashCode = key.GetHashCode() &&& 0x7FFFFFFF\n            let eid = findEntry key hashCode\n            if eid < 0 then\n                false\n            else\n                let bid = !!(entries + eid).Block |> BlockHandle\n                let size = x.SizeOf bid\n                let res = FileHandle(key, eid, size)\n                handleCache.[key] <- res\n                file <- res\n                true\n\n    member x.Resize (file : FileHandle, newSize : int64) =\n        let eid = file.EntryId\n        if eid < 0 then\n            if newSize > 0L then\n                let _, bid = alloc newSize\n                let hashCode = file.Id.GetHashCode() &&& 0x7FFFFFFF\n                let eid = setEntry file.Id hashCode bid\n                file.EntryId <- eid\n                file.Length <- newSize\n\n            else\n                file.Length <- 0L\n\n        else\n\n            if newSize > 0L then\n                let mutable pEntry = entries + eid\n                let oldBlockId = !!pEntry.Block\n\n                if oldBlockId >= 0 then\n                    let pBlock = blocks + oldBlockId\n                    let oldSize = !!pBlock.Size\n\n                    if oldSize <> newSize then\n                        free oldBlockId\n                        let resized, newBlockId = alloc newSize\n                        if resized then \n                            pEntry <- entries + eid\n\n                        pEntry.Block <-- newBlockId\n\n                else\n                    let resized, bid = alloc newSize\n                    if resized then\n                        pEntry <- entries + eid\n\n                    pEntry.Block <-- bid\n\n                file.Length <- newSize\n\n            else\n                let pEntry = entries + eid\n                let bid = !!pEntry.Block\n                if bid >= 0 then\n                    pEntry.Block <-- -1\n                    free bid\n\n                file.Length <- 0L\n\n    member x.Delete(file : FileHandle) =\n        let eid = file.EntryId\n        if eid >= 0 then\n            file.EntryId <- -1\n\n            handleCache.Remove file.Id |> ignore\n                \n            let bid = !!(entries + eid).Block\n            let removed = removeEntryPtr eid\n            assert removed\n\n\n            if bid >= 0 then free bid\n         \n\n    member x.Copy(src : byte[], srcOffset : int64, dst : FileHandle, dstOffset : int64, length : int64) = x.Copy(src, srcOffset, x.GetCurrentBlock dst, dstOffset, length)\n    member x.Copy(src : byte[], dst : FileHandle, dstOffset : int64, length : int64) = x.Copy(src, 0L, x.GetCurrentBlock dst, dstOffset, length)\n    member x.Copy(src : byte[], srcOffset : int64, dst : FileHandle, length : int64) = x.Copy(src, srcOffset, x.GetCurrentBlock dst, 0L, length)\n    member x.Copy(src : byte[], dst : FileHandle, length : int64) = x.Copy(src, 0L, x.GetCurrentBlock dst, 0L, length)\n    member x.Copy(src : byte[], dst : FileHandle) = x.Copy(src, 0L, x.GetCurrentBlock dst, 0L, src.LongLength)\n\n    member x.Copy(src : FileHandle, srcOffset : int64, dst : byte[], dstOffset : int64, length : int64) = x.Copy(x.GetCurrentBlock src, srcOffset, dst, dstOffset, length) \n    member x.Copy(src : FileHandle, dst : byte[], dstOffset : int64, length : int64) = x.Copy(x.GetCurrentBlock src, 0L, dst, dstOffset, length)\n    member x.Copy(src : FileHandle, srcOffset : int64, dst : byte[], length : int64) = x.Copy(x.GetCurrentBlock src, srcOffset, dst, 0L, length)\n    member x.Copy(src : FileHandle, dst : byte[], length : int64) = x.Copy(x.GetCurrentBlock src, 0L, dst, 0L, length)\n    member x.Copy(src : FileHandle, dst : byte[]) = x.Copy(x.GetCurrentBlock src, 0L, dst, 0L, dst.LongLength)\n\n    member x.Read(src : FileHandle) =\n        if src.EntryId >= 0 then\n            let arr = Array.zeroCreate (int src.Length)\n            x.Copy(x.GetCurrentBlock src, 0L, arr, 0L, arr.LongLength)\n            arr\n        else\n            [||]\n\n\n\n    member x.TotalMemory = Mem mem.Size + Mem (chunks |> Seq.sumBy (fun m -> m.Size))\n    member x.Entries = !!header.BCount - !!header.BFreeCount\n    member x.Files = !!header.ECount - !!header.EFreeCount\n\n    member x.Statistics =\n        {\n            growManagerTime     = growManagerTime.MicroTime\n            growDictTime        = growDictTime.MicroTime\n            growDataTime        = growDataTime.MicroTime\n            rehashTime          = rehashTime.MicroTime\n            reallocTime         = reallocTime.MicroTime\n            allocCount          = allocCount\n            freeCount           = freeCount\n            fileCount           = !!header.ECount - !!header.EFreeCount\n            blockCount          = !!header.BCount - !!header.BFreeCount\n        }\n\n\n    member private x.Dispose(disposing : bool) =\n        if header.ptr <> 0n then\n            if disposing then GC.SuppressFinalize x\n            mem.Dispose()\n            chunks |> Seq.iter (fun c -> c.Dispose())\n            chunks.Clear()\n            header <- headerptr.Null\n            nodes <- nodeptr.Null\n            blocks <- blockptr.Null\n            entries <- dentryptr.Null\n            buckets <- NativePtr.zero<int>\n\n    member x.Dispose() = x.Dispose(true)\n    override x.Finalize() = x.Dispose(false)\n\n    interface IDisposable with\n        member x.Dispose() = x.Dispose(true)\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule FileManager =\n    \n    let directory (dir : string) =\n        let exists = Directory.Exists dir\n        if not exists then Directory.CreateDirectory dir |> ignore\n\n        let main = Path.Combine(dir, \"index.bin\") |> Memory.mapped\n        let get (i : int) =\n            Path.Combine(dir, sprintf \"store%d.bin\" i) |> Memory.mapped\n\n        new FileManager(main, get)\n    \n    let hglobal () =\n        let main = Memory.hglobal 0L\n        let get (i : int) =\n            Memory.hglobal 0L\n\n        new FileManager(main, get)\n            \n\nmodule FS = \n    module MemoryHelpers =\n        let mapped (f : Memory -> 'a) =\n            let path = Path.GetTempFileName()\n            if System.IO.File.Exists path then System.IO.File.Delete path\n\n            let mem = Memory.mapped path\n            Log.start \"File\"\n            try f mem\n            finally \n                Log.stop()\n                mem.Dispose()\n                System.IO.File.Delete path\n\n        let hglobal (f : Memory -> 'a) =\n            let mem = Memory.hglobal 0L\n            Log.start \"HGlobal\"\n            try f mem\n            finally \n                Log.stop()\n                mem.Dispose()\n\n    \n\n    let test() =\n        use s = FileManager.hglobal()\n        \n        let data = Array.init 200 byte\n        let e = s.Alloc(data.LongLength)\n\n        s.Copy(data, e)\n        let r = s.Read(e)\n        printfn \"%A\" r\n\n        s.Free(e)\n\n    let moreTest () =\n        //if File.Exists @\"C:\\Users\\Schorsch\\Desktop\\test.bin\" then File.Delete @\"C:\\Users\\Schorsch\\Desktop\\test.bin\"\n\n        use s = FileManager.directory  @\"C:\\Users\\Schorsch\\Desktop\\moreTest\"//(Memory.mapped @\"C:\\Users\\Schorsch\\Desktop\\test.bin\")\n\n        printfn \"(%d/%A)\" s.Entries s.TotalMemory\n\n        let r = System.Random()\n        let allocations = System.Collections.Generic.List()\n\n        let run () =\n            let op = r.NextDouble() \n            if op < 0.8 || allocations.Count <= 0 then\n                let ssize = 1+r.Next(1 <<< 20)\n                let e = s.Alloc(int64 ssize)\n                s.Copy(Array.create ssize (byte e.BlockId), e)\n                allocations.Add(e)\n            else \n                let index = r.Next(0,allocations.Count-1)\n                let a = allocations.[index]\n                let arr = s.Read a\n                let r = arr |> Array.forall (fun b -> b = byte a.BlockId)\n                if not r then printfn \"furious anger\"\n                s.Free(a)\n                allocations.RemoveAt index\n\n        for i in 0 .. 100000 do\n            if i%100 = 0 then printfn \"it: %d (%d/%A)\" i s.Entries s.TotalMemory\n            run ()\n\n        printfn \"living: %A\" allocations.Count\n        printfn \"%A\" s.Statistics\n\n        for a in allocations do\n            let arr = s.Read a\n            let r = arr |> Array.forall (fun b -> b = byte a.BlockId)\n            if not r then printfn \"furious anger\"\n            s.Free(a)\n\n        printfn \"%A\" s.Statistics\n\n    let moreFileTest () =\n        //if File.Exists @\"C:\\Users\\Schorsch\\Desktop\\test.bin\" then File.Delete @\"C:\\Users\\Schorsch\\Desktop\\test.bin\"\n\n        use s = FileManager.directory @\"C:\\Users\\Schorsch\\Desktop\\blabla\"\n\n        printfn \"(%d/%A)\" s.Files s.TotalMemory\n\n        let allocations = System.Collections.Generic.List()\n        let r = Random()\n\n        let run () =\n            let op = r.NextDouble() \n            if op < 0.6 || allocations.Count <= 0 then\n                let id = Guid.NewGuid()\n                let e = s.GetFile(id)\n                s.Resize(e, 16L)\n                s.Copy(id.ToByteArray(), e)\n                allocations.Add(e)\n            else \n                let index = r.Next(0,allocations.Count-1)\n                let a = allocations.[index]\n                allocations.RemoveAt index\n                let arr = s.Read a\n                let r = a.Id.ToByteArray() = arr\n                if not r then printfn \"furious anger\"\n                s.Delete(a)\n\n\n        for i in 0 .. 1000000 do\n            if i%100 = 0 then printfn \"it: %d (%d/%A)\" i s.Files s.TotalMemory\n            run ()\n\n        printfn \"%A\" s.Statistics\n        for a in allocations do\n            let arr = s.Read a\n            let r = a.Id.ToByteArray() = arr\n            if not r then printfn \"furious anger\"\n            s.Delete(a)\n\n        \n        printfn \"%A\" s.Statistics\n        printfn \"done\"\n\n//    let allocPerf() =\n//\n//        let log = @\"C:\\Users\\schorsch\\Desktop\\store.csv\"\n//\n//        let test (kind : string) (cnt : int) (mem : Memory) =\n//            mem.Clear(1024L)\n//            use s = new FileManager.FileManager(mem)\n//            let r = System.Random()\n//\n//            Log.line \"size: %d\" cnt\n//\n//            let mutable blocks = Array.zeroCreate cnt\n//            let sizes = Array.init cnt (fun _ -> int64 (1 + r.Next 255))\n//            let data = Array.zeroCreate 1024\n//\n//            let sw = Stopwatch()\n//            sw.Restart()\n//            for i in 0 .. cnt-1 do\n//                blocks.[i] <- s.Alloc sizes.[i]\n//            sw.Stop()\n//            let talloc = sw.MicroTime / float cnt\n//            Log.line \"alloc: %A\" talloc\n//\n//\n//            sw.Restart()\n//            for i in 0 .. cnt-1 do\n//                s.Copy(data, 0L, blocks.[i], 0L, sizes.[i])\n//            sw.Stop()\n//            let twrite = sw.MicroTime / float cnt\n//            Log.line \"write: %A\" twrite\n//\n//            blocks <- blocks.RandomOrder() |> Seq.toArray\n//            sw.Restart()\n//            for i in 0 .. cnt-1 do\n//                s.Free(blocks.[i])\n//            sw.Stop()\n//            let tfreer = sw.MicroTime / float cnt\n//            Log.line \"free:  %A (random order)\" tfreer\n//\n//            mem.Clear(1024L)\n//            use s = new FileManager.FileManager(mem)\n//            for i in 0 .. cnt-1 do\n//                blocks.[i] <- s.Alloc sizes.[i]\n//            sw.Restart()\n//            for i in 0 .. cnt-1 do\n//                s.Free(blocks.[i])\n//            sw.Stop()\n//            let tfrees = sw.MicroTime / float cnt\n//            Log.line \"free:  %A (sequential)\" tfrees\n//\n//\n//\n//            File.AppendAllLines(log, [sprintf \"%s;%d;%d;%d;%d;%d\" kind cnt talloc.TotalNanoseconds twrite.TotalNanoseconds tfreer.TotalNanoseconds tfrees.TotalNanoseconds])\n//\n//\n//        File.WriteAllLines(log, [\"mem;size;alloc [ns];write [ns];free (random) [ns]; free (sequential) [ns]\"])\n//        for i in 10 .. 20 do\n//            let cnt = 1 <<< 20\n//            MemoryHelpers.hglobal (test \"hglobal\" cnt)\n//            MemoryHelpers.mapped (test \"mapped\" cnt)\n\n    let fileTest() =\n        use s = BlobStore.directory @\"\" //new BlobStore(Memory.mapped @\"C:\\Users\\Schorsch\\Desktop\\test.bin\")\n\n        let a = s.Get (Guid \"d5993e65-6e27-4596-85c1-2a59491477c0\")\n        let b = s.Get (Guid \"d5993e65-6e27-4596-85c1-2a59491477c0\")\n\n        \n        match a.Exists with\n            | true -> \n                let arr = a.Read() \n                Log.line \"a = %A\" arr\n                let arr = Array.append arr [|123uy|]\n                a.Write arr\n\n                \n\n            | _ ->\n                a.Write(Array.init 10 byte)\n                a.Read() |> Log.line \"a = %A (created)\"\n"
  },
  {
    "path": "src/Demo/Scratch/paket.references",
    "content": "FSharp.Core\nAardvark.Build\nUnofficial.LibTessDotNet\nFsPickler\nFsPickler.Json \nFSharp.Data.Adaptive"
  },
  {
    "path": "src/Demo/Sketch/App.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<configuration>\n    <startup> \n        <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.5.2\" />\n    </startup>\n</configuration>"
  },
  {
    "path": "src/Demo/Sketch/FingerTree.fsx",
    "content": "#I @\"..\\..\\..\\bin\\Release\"\n#I @\"..\\..\\..\\Packages\\Rx-Core\\lib\\net45\"\n#I @\"..\\..\\..\\Packages\\Rx-Interfaces\\lib\\net45\"\n#I @\"..\\..\\..\\Packages\\Rx-Linq\\lib\\net45\"\n#r \"Aardvark.Base.dll\"\n#r \"Aardvark.Base.Essentials.dll\"\n#r \"Aardvark.Base.TypeProviders.dll\"\n#r \"Aardvark.Base.FSharp.dll\"\n#r \"Aardvark.Base.Incremental.dll\"\n#r \"System.Reactive.Core.dll\"\n#r \"System.Reactive.Interfaces.dll\"\n#r \"System.Reactive.Linq.dll\"\n\n\n\nopen System\nopen System.Runtime.CompilerServices\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\n\ntype Measure<'a, 'm> = { f : 'a -> 'm; add : 'm -> 'm -> 'm; zero : 'm}\n\n\n[<AutoOpen>]\nmodule private FingerTreeNode =\n\n\n    type Affix<'a, 'm> =\n        | One of 'm * 'a\n        | Two of 'm * 'a * 'a\n        | Three of 'm * 'a * 'a * 'a\n        | Four of 'm * 'a * 'a * 'a * 'a\n\n    type Node<'a, 'm> =\n        | Node2 of 'm * 'a * 'a\n        | Node3 of 'm * 'a * 'a * 'a\n\n    type Measure<'a, 'm> with\n        member x.one (v : 'a) = One(x.f v, v)\n        member x.two (a : 'a) (b : 'a) = Two(x.add (x.f a) (x.f b), a,b)\n        member x.three (a : 'a) (b : 'a) (c : 'a) = Three(x.add (x.add (x.f a) (x.f b)) (x.f c), a,b,c)\n        member x.four (a : 'a) (b : 'a) (c : 'a) (d : 'a) = Four(x.add (x.add (x.f a) (x.f b)) (x.add (x.f c) (x.f d)), a,b,c,d)\n\n        member x.node2 (a : 'a) (b : 'a) = Node2(x.add (x.f a) (x.f b), a,b)\n        member x.node3 (a : 'a) (b : 'a) (c : 'a) = Node3(x.add (x.add (x.f a) (x.f b)) (x.f c), a,b,c)\n\n        member x.compute ([<ParamArray>] values : 'a[]) =\n            values |> Array.fold (fun s e -> x.add s (x.f e)) x.zero\n\n        member x.NodeMeasure =\n            let measureNode (n : Node<'a, 'm>) =\n                match n with\n                    | Node2(m,_,_) -> m\n                    | Node3(m,_,_,_) -> m\n\n            { f = measureNode; add = x.add; zero = x.zero }\n\n    module Affix =\n        let single (ctx : Measure<'a, 'm>) (v : 'a) =\n            One(ctx.f v ,v)\n\n        let ofList (ctx : Measure<'a, 'm>) (l : list<'a>) =\n            match l with\n                | [a] -> One(ctx.compute(a), a)\n                | [a;b] -> Two(ctx.compute(a,b), a, b)\n                | [a;b;c] -> Three(ctx.compute(a,b,c), a, b, c)\n                | [a;b;c;d] -> Four(ctx.compute(a,b,c,d), a, b, c, d)\n                | _ -> failwith \"affix must have length 1 to 4\"\n\n\n        let prepend (ctx : Measure<'a, 'm>) (v : 'a) (a : Affix<'a, 'm>) =\n            match a with\n                | One(m, x) -> Two(ctx.add (ctx.f v) m,v,x)\n                | Two(m,x,y) -> Three(ctx.add (ctx.f v) m,v,x,y)\n                | Three(m,x,y,z) -> Four(ctx.add (ctx.f v) m,v,x,y,z)\n                | _ -> failwith \"affix must have length 1 to 4\"\n\n        let append (ctx : Measure<'a, 'm>) (v : 'a) (a : Affix<'a, 'm>) =\n            match a with\n                | One(m, x) -> Two(ctx.add (ctx.f v) m,x,v)\n                | Two(m,x,y) -> Three(ctx.add (ctx.f v) m,x,y,v)\n                | Three(m,x,y,z) -> Four(ctx.add (ctx.f v) m,x,y,z,v)\n                | _ -> failwith \"affix must have length 1 to 4\"\n\n        let toNode(a : Affix<'a,'m>) =\n            match a with\n                | Two(m,a,b) -> Node2(m, a,b)\n                | Three(m, a,b,c) -> Node3(m, a,b,c)\n                | _ -> failwith \"nodes must have length 2 or 3\"\n\n        let ofNode(n : Node<'a, 'm>) =\n            match n with\n                | Node2(m,a,b) -> Two(m,a,b)\n                | Node3(m,a,b,c) -> Three(m,a,b,c)\n\n        let viewl (a : Affix<'a, 'm>) =\n            match a with\n                | One(_,a) -> [a]\n                | Two(_,a,b) -> [a;b]\n                | Three(_,a,b,c) -> [a;b;c]\n                | Four(_,a,b,c,d) -> [a;b;c;d]\n\n        let viewr (a : Affix<'a, 'm>) =\n            match a with\n                | One(_,a) -> [a]\n                | Two(_,a,b) -> [b;a]\n                | Three(_,a,b,c) -> [c;b;a]\n                | Four(_,a,b,c,d) -> [d;c;b;a]\n\n        let size (a : Affix<'a, 'm>) =\n            match a with\n                | One(m,_) -> m\n                | Two(m,_,_) -> m\n                | Three(m,_,_,_) -> m\n                | Four(m,_,_,_,_) -> m\n\n        let first (a : Affix<'a, 'm>) =\n            match a with\n                | One(_,a) -> a\n                | Two(_,a,_) -> a\n                | Three(_,a,_,_) -> a\n                | Four(_,a,_,_,_) -> a\n  \n        let last (a : Affix<'a, 'm>) =\n            match a with\n                | One(_,a) -> a\n                | Two(_,_,a) -> a\n                | Three(_,_,_,a) -> a\n                | Four(_,_,_,_,a) -> a\n  \n    module Node =\n        let toAffix(n : Node<'a,'m>) = Affix.ofNode n\n\n        let fromAffix(a : Affix<'a, 'm>) = Affix.toNode a\n\n        let ofList (ctx : Measure<'a, 'm>) (l : list<'a>) =\n            match l with\n                | [a;b] -> Node2(ctx.compute(a,b), a, b)\n                | [a;b;c] -> Node3(ctx.compute(a,b,c), a, b, c)\n                | _ -> failwith \"nodes must have 2-3 elements\"\n\n        let size (n : Node<'a, 'm>) =\n            match n with\n                | Node2(m,_,_) -> m\n                | Node3(m,_,_,_) -> m\n\n        let viewl (a : Node<'a, 'm>) =\n            match a with\n                | Node2(_,a,b) -> [a;b]\n                | Node3(_,a,b,c) -> [a;b;c]\n\n        let viewr (a : Node<'a, 'm>) =\n            match a with\n                | Node2(_,a,b) -> [b;a]\n                | Node3(_,a,b,c) -> [c;b;a]\n\n    type Deep<'a, 'm> = { annotation : 'm; prefix : Affix<'a, 'm>; deeper : FingerTreeNode<Node<'a, 'm>, 'm>; suffix : Affix<'a, 'm> }\n\n    and FingerTreeNode<'a, 'm> = \n        | Empty \n        | Single of 'a \n        | Deep of Deep<'a, 'm> with\n\n            member x.ViewLeft : seq<'a> =\n                seq {\n                    match x with\n                        | Empty -> ()\n                        | Single (a) -> yield a\n                        | Deep { prefix = prefix; deeper = deeper; suffix = suffix } ->\n                            yield! Affix.viewl prefix\n                            for b in deeper.ViewLeft do\n                                yield! Node.viewl b\n                            yield! Affix.viewl suffix\n                }\n\n            member x.ViewRight : seq<'a> =\n                seq {\n                    match x with\n                        | Empty -> ()\n                        | Single (a) -> yield a\n                        | Deep { prefix = prefix; deeper = deeper; suffix = suffix } ->\n                            yield! Affix.viewr suffix\n                            for b in deeper.ViewRight do\n                                yield! Node.viewr b\n                            yield! Affix.viewr prefix\n                }\n\n\n\n\n    let rec prepend<'a, 'm> (ctx : Measure<'a, 'm>) (value : 'a) (node : FingerTreeNode<'a, 'm>) : FingerTreeNode<'a, 'm> =\n        match node with\n            | Empty -> \n                Single value\n\n            | Single y -> \n                Deep { \n                    annotation = ctx.compute(value,y)\n                    prefix = ctx.one value\n                    deeper = Empty\n                    suffix = ctx.one y\n                }\n\n            | Deep { annotation = annotation; prefix = Four(_,a,b,c,d); deeper = deeper; suffix = suffix } ->\n                Deep { \n                    annotation = ctx.add annotation (ctx.f value) \n                    prefix = ctx.two value a\n                    deeper = prepend ctx.NodeMeasure (ctx.node3 b c d) deeper\n                    suffix = suffix \n                }\n\n            | Deep deep ->\n\n                Deep { \n                    annotation = ctx.add (ctx.f value) deep.annotation\n                    prefix = Affix.prepend ctx value deep.prefix\n                    deeper = deep.deeper \n                    suffix = deep.suffix \n                }\n\n    let rec append<'a, 'm> (ctx : Measure<'a, 'm>) (value : 'a) (node : FingerTreeNode<'a, 'm>) : FingerTreeNode<'a, 'm> =\n        match node with\n            | Empty -> \n                Single value\n\n            | Single y -> \n                Deep { \n                    annotation = ctx.compute(value,y)\n                    prefix = ctx.one y\n                    deeper = Empty\n                    suffix = ctx.one value\n                }\n\n            | Deep { annotation = annotation; prefix = prefix; deeper = deeper; suffix = Four(_,a,b,c,d) } ->\n                Deep { \n                    annotation = ctx.add annotation (ctx.f value) \n                    prefix = prefix\n                    deeper = append ctx.NodeMeasure (ctx.node3 a b c) deeper\n                    suffix = ctx.two d value \n                }\n\n            | Deep deep ->\n                Deep { \n                    annotation = ctx.add (ctx.f value) deep.annotation\n                    prefix = deep.prefix\n                    deeper = deep.deeper \n                    suffix = Affix.append ctx value deep.suffix\n                }\n\n\n    type View<'a, 'm> =\n        | Nil\n        | Cons of 'a * FingerTreeNode<'a, 'm>\n\n    let private affixToTree (ctx : Measure<'a, 'm>) (a : Affix<'a, 'm>) =\n        match a with\n            | One(_,x) -> \n                Single x\n            | Two(m,x,y) -> \n                Deep { annotation = m; prefix = One(ctx.compute(x), x); deeper = Empty; suffix = One(ctx.compute(y), y) }\n            | Three(m,x,y,z) ->\n                Deep { annotation = m; prefix = One(ctx.compute(x), x); deeper = Empty; suffix = Two(ctx.compute(y,z), y,z) }\n            | Four(m,x,y,z,w) ->\n                Deep { annotation = m; prefix = Two(ctx.compute(x,y), x,y); deeper = Empty; suffix = Two(ctx.compute(z,w), z,w) }\n\n    let rec viewl<'a, 'm> (ctx : Measure<'a,'m>) (node : FingerTreeNode<'a, 'm>) : View<'a, 'm> =\n        match node with\n            | Empty -> Nil\n            | Single x -> Cons(x, Empty)\n            | Deep ({ prefix = One(_,x) } as deep) ->\n                match viewl ctx.NodeMeasure deep.deeper with\n                    | Cons(node, rest') ->\n                        let restMeasure =\n                            match rest' with\n                                | Empty -> ctx.zero\n                                | Single v -> ctx.NodeMeasure.compute(v)\n                                | Deep d -> d.annotation\n\n                        let pref = Affix.ofNode node\n                        let annot = ctx.add (ctx.add (Affix.size pref) restMeasure) (Affix.size deep.suffix)\n\n                        let rest = Deep { annotation = annot; prefix = pref; deeper = rest'; suffix = deep.suffix }\n                        Cons(x, rest)\n                    | _ ->\n                        Cons(x, affixToTree ctx deep.suffix)\n            | Deep deep ->\n                match Affix.viewl deep.prefix with\n                    | (x::xs) ->\n                        let newPrefix = Affix.ofList ctx xs\n\n                        let prefixMeasure = Affix.size newPrefix\n                        let suffixMeasure = Affix.size deep.suffix\n                        let deeperMeasure =\n                            match deep.deeper with\n                                | Empty -> ctx.zero\n                                | Single v -> ctx.NodeMeasure.compute(v)\n                                | Deep d -> d.annotation\n\n                        let sum = ctx.add (ctx.add prefixMeasure deeperMeasure) suffixMeasure\n\n                        Cons(x, Deep { annotation = sum; prefix = newPrefix; deeper = deep.deeper; suffix = deep.suffix })\n                    | [] ->\n                        failwith \"affixes cannot be empty\"\n\n    let rec viewr<'a, 'm> (ctx : Measure<'a,'m>) (node : FingerTreeNode<'a, 'm>) : View<'a, 'm> =\n        match node with\n            | Empty -> Nil\n            | Single v -> Cons(v, Empty)\n            | Deep ({ suffix = One(_,x) } as deep) ->\n                match viewr ctx.NodeMeasure deep.deeper with\n                    | Cons(n, rest') ->\n                        let restMeasure =\n                            match rest' with\n                                | Empty -> ctx.zero\n                                | Single v -> ctx.NodeMeasure.compute(v)\n                                | Deep d -> d.annotation\n\n                        let suff = Affix.ofNode n\n                        let annot = ctx.add (ctx.add (Affix.size deep.prefix) restMeasure) (Affix.size suff)\n\n                        let rest = Deep { annotation = annot; prefix = deep.prefix; deeper = rest'; suffix = suff }\n                        Cons(x, rest)\n\n                    | Nil -> \n                        Cons(x, affixToTree ctx deep.prefix)\n\n            | Deep deep -> \n                match Affix.viewr deep.suffix with\n                    | (x::xs) ->\n                        let newSuffix = Affix.ofList ctx (List.rev xs)\n\n                        let prefixMeasure = Affix.size deep.prefix\n                        let suffixMeasure = Affix.size newSuffix\n                        let deeperMeasure =\n                            match deep.deeper with\n                                | Empty -> ctx.zero\n                                | Single v -> ctx.NodeMeasure.compute(v)\n                                | Deep d -> d.annotation\n\n                        let sum = ctx.add (ctx.add prefixMeasure deeperMeasure) suffixMeasure\n\n                        Cons(x, Deep { annotation = sum; prefix = deep.prefix; deeper = deep.deeper; suffix = newSuffix })\n                    | [] ->\n                        failwith \"affixes cannot be empty\"\n\n\n\n    type Split<'a, 'm> = \n        | Split of FingerTreeNode<'a, 'm> * 'a * FingerTreeNode<'a, 'm>\n        | NoSplit\n\n    let rec private splitList (ctx : Measure<'a, 'm>) (cond : 'm -> bool) (start : 'm) (list : list<'a>) =\n        match list with\n            | [] -> [], []\n            | x::xs ->\n                let startNew = ctx.add start (ctx.f x)\n                if cond startNew then\n                    [], list\n                else\n                    let before, after = splitList ctx cond startNew xs\n                    (x::before, after)\n\n\n    let rec private deep<'a, 'm> (ctx : Measure<'a, 'm>) prefix (deeper : FingerTreeNode<Node<'a, 'm>, 'm>) suffix =\n        match prefix, suffix with\n            | [], [] -> \n                match viewl ctx.NodeMeasure deeper with\n                    | Nil -> Empty\n                    | Cons(x,rest) -> deep ctx (Node.viewl x) rest []\n\n            | [], _ ->\n                match viewr ctx.NodeMeasure deeper with\n                    | Nil -> suffix |> Affix.ofList ctx |> affixToTree ctx\n                    | Cons(node, deeper') -> deep ctx (Node.viewl node) deeper' suffix\n\n            | _, [] ->\n                match viewr ctx.NodeMeasure deeper with\n                    | Nil -> prefix |> Affix.ofList ctx |> affixToTree ctx\n                    | Cons(node, deeper') -> deep ctx prefix deeper' (Node.viewl node)\n            | _ ->\n                let pref = Affix.ofList ctx prefix\n                let suff = Affix.ofList ctx suffix\n\n                let deeperMeasure =\n                    match deeper with\n                        | Empty -> ctx.zero\n                        | Single v -> Node.size v\n                        | Deep d -> d.annotation\n\n                let sum = ctx.add (ctx.add (Affix.size pref) (Affix.size suff)) deeperMeasure\n\n                Deep { annotation = sum; prefix = pref; deeper = deeper; suffix = suff }\n\n    let rec split<'a, 'm> (ctx : Measure<'a, 'm>) (cond : 'm -> bool) (start : 'm) (node : FingerTreeNode<'a, 'm>) : Split<'a, 'm> =\n        match node with\n            | Empty -> NoSplit\n            | Single x ->\n                if cond (ctx.add start (ctx.compute(x))) then Split(Empty, x, Empty)\n                else NoSplit\n            | Deep { annotation = total; prefix = pref; deeper = deeper; suffix = suff } ->\n               \n                let inside = cond (ctx.add start total)\n                if not inside then\n                    NoSplit\n                else\n                    let prefix = Affix.viewl pref\n                    let suffix = Affix.viewl suff\n                    let startPref = ctx.add start (Affix.size pref)\n                    \n                    let chunkToTree l =\n                        match l with\n                            | [] -> Empty\n                            | xs -> xs |> Affix.ofList ctx |> affixToTree ctx\n\n                    if cond startPref then\n                        match splitList ctx cond start (Affix.viewl pref) with\n                            | (before, x::after) ->\n                                Split (chunkToTree before, x, deep ctx after deeper suffix)\n                            | _ ->\n                                failwith \"not possible\"\n\n                    else\n                        let deeperMeasure =\n                            match deeper with\n                                | Empty -> ctx.zero\n                                | Single v -> ctx.NodeMeasure.compute v\n                                | Deep d -> d.annotation\n\n                        let startSuff = ctx.add startPref deeperMeasure\n\n                        if cond startSuff then\n                            // inside deeper\n                            match split ctx.NodeMeasure cond startPref deeper with\n                                | Split(before, node, after) ->\n                                    \n                                    let beforeMeasure =\n                                        match before with\n                                            | Empty -> ctx.zero\n                                            | Single v -> ctx.NodeMeasure.compute v\n                                            | Deep d -> d.annotation\n\n                                    let start' = ctx.add (ctx.add start (Affix.size pref)) beforeMeasure\n\n                                    match splitList ctx cond start' (Node.viewl node) with\n                                        | (beforeNode, x::afterNode) ->\n                                            Split(deep ctx prefix before beforeNode, x, deep ctx afterNode after suffix)\n                                        | _ ->\n                                            failwith \"not possible\"\n\n                                | NoSplit ->\n                                    NoSplit\n\n                        else\n                            // in suffix\n                            match splitList ctx cond startSuff suffix with\n                                | (before, x::after) ->\n                                    Split(deep ctx prefix deeper before, x, chunkToTree after)\n                                | _ ->\n                                    failwith \"not possible\" \n\n    let rec concatWithMiddle<'a, 'm> (ctx : Measure<'a, 'm>) (l : FingerTreeNode<'a, 'm>) (middle : list<'a>) (r : FingerTreeNode<'a, 'm>) : FingerTreeNode<'a, 'm> =\n        \n        let rec allButLast (l : list<'a>) =\n            match l with\n                | [_] -> []\n                | x::xs -> x::allButLast xs\n                | [] -> failwith \"empty list\"\n\n        let rec nodes (l : list<'a>) : list<Node<'a, 'm>> =\n            match l with\n                | [] | [_] -> failwith \"not enough elements for nodes\"\n                | [x;y] -> [Node2(ctx.compute(x,y), x, y)]\n                | [x;y;z] -> [Node3(ctx.compute(x,y,z), x, y, z)]\n                | x::y::rest -> (ctx.node2 x y)::nodes rest\n\n        match l, middle, r with\n            | Empty,        [],         r           -> r\n            | Empty,        (x::xs),    r           -> prepend ctx x (concatWithMiddle ctx Empty xs r)\n            | Single y,     xs,         r           -> prepend ctx y (concatWithMiddle ctx Empty xs r)\n\n            | l,            [],         Empty       -> l\n            | l,            xs,         Empty       -> append ctx (List.last xs) (concatWithMiddle ctx l (allButLast xs) Empty)\n            | l,            xs,         Single y    -> append ctx y (concatWithMiddle ctx l xs Empty)\n\n            | Deep l,       m,          Deep r      ->\n                let mid' = List.concat [l.suffix |> Affix.viewl; m; r.prefix |> Affix.viewl] |> nodes\n                let deeper' = concatWithMiddle ctx.NodeMeasure l.deeper mid' r.deeper\n\n\n                let prefixMeasure = Affix.size l.prefix\n                let suffixMeasure = Affix.size r.suffix\n                let deeperMeasure =\n                    match deeper' with\n                        | Empty -> ctx.zero\n                        | Single n -> ctx.NodeMeasure.compute n\n                        | Deep d -> d.annotation\n\n                let sum = ctx.add (ctx.add prefixMeasure deeperMeasure) suffixMeasure\n\n                Deep { annotation = sum; prefix = l.prefix; deeper = deeper'; suffix = r.suffix }\n                \n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype FingerTree<'a, 'm> = private { ctx : Measure<'a, 'm>; root : FingerTreeNode<'a, 'm> } with\n\n    member x.ViewLeft = x.root.ViewLeft\n    member x.ViewRight = x.root.ViewRight\n\n    member private x.AsString =\n        x.ViewLeft |> Seq.toList |> sprintf \"F %A\"\n\n    interface IEnumerable<'a> with\n        member x.GetEnumerator() = x.ViewLeft.GetEnumerator()\n\n    interface IEnumerable with\n        member x.GetEnumerator() = (x.ViewLeft :> IEnumerable).GetEnumerator()\n\ntype Split<'a, 'm> =\n    | Split of FingerTree<'a, 'm> * 'a * FingerTree<'a, 'm>\n    | NoSplit\n\nmodule FingerTree =\n    \n    let custom<'a, 'm> (m : Measure<'a, 'm>) = \n        { ctx = m; root = Empty }\n\n\n    let total (t : FingerTree<'a, 'm>) : 'm =\n        match t.root with\n            | Empty -> t.ctx.zero\n            | Single v -> t.ctx.compute v\n            | Deep d -> d.annotation\n\n    let prepend (value : 'a) (t : FingerTree<'a, 'm>) =\n        { ctx = t.ctx; root = FingerTreeNode.prepend t.ctx value t.root }\n\n    let append (value : 'a) (t : FingerTree<'a, 'm>) =\n        { ctx = t.ctx; root = FingerTreeNode.append t.ctx value t.root }\n\n\n    let toSeq (t : FingerTree<'a, 'm>) =\n        t.root.ViewLeft\n\n    let toList (t : FingerTree<'a, 'm>) =\n        t.root.ViewLeft |> Seq.toList\n\n    let toArray (t : FingerTree<'a, 'm>) =\n        t.root.ViewLeft |> Seq.toArray\n\n    let ofSeq (m : Measure<'a, 'm>) (s : seq<'a>) =\n        let mutable r = Empty\n        for e in s do\n            r <- FingerTreeNode.append m e r\n\n        { ctx = m; root = r }\n\n    let ofList (m : Measure<'a, 'm>) (l : list<'a>) =\n        ofSeq m l\n\n    let ofArray (m : Measure<'a, 'm>) (l : 'a[]) =\n        ofSeq m l\n\n\n\n\n    let split (cond : 'm -> bool) (t : FingerTree<'a, 'm>) =\n        match FingerTreeNode.split t.ctx cond t.ctx.zero t.root with\n            | FingerTreeNode.Split(l,v,r) ->\n                Split({ t with root = l}, v, { t with root = r })\n            | _ ->\n                NoSplit\n\n    let concatWithMiddle (l : FingerTree<'a, 'm>) (m : list<'a>) (r : FingerTree<'a, 'm>) =\n        let newRoot = FingerTreeNode.concatWithMiddle l.ctx l.root m r.root\n        { l with root = newRoot }\n\n    let concat l r =\n        concatWithMiddle l [] r\n\n\n    let viewl (t : FingerTree<'a, 'm>) =\n        match FingerTreeNode.viewl t.ctx t.root with\n            | Cons(v,rest) -> Some(v, { t with root = rest })\n            | _ -> None\n\n    let viewr (t : FingerTree<'a, 'm>) =\n        match FingerTreeNode.viewr t.ctx t.root with\n            | Cons(v,rest) -> Some(v, { t with root = rest })\n            | _ -> None\n\n\n// immutable array built upon FingerTree\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype Arr<'a> = private { tree : FingerTree<'a, int> } with\n    member private x.AsString =\n        x.tree |> FingerTree.toList |> sprintf \"%A\"\n\nmodule Arr =\n    module Patterns =\n        let (|ArrCons|ArrNil|) (a : Arr<'a>) =\n            match FingerTree.viewl a.tree with\n                | Some(v,r) -> ArrCons(v, { tree = r })\n                | None -> ArrNil\n\n            \n    let private m<'a> : Measure<'a, int> =\n        {\n            zero = 0\n            add = (+)\n            f = fun _ -> 1\n        }\n\n    let empty<'a> : Arr<'a> =\n        { tree = FingerTree.custom m }\n\n    let ofSeq (l : seq<'a>) =\n        { tree = l |> FingerTree.ofSeq m }\n\n    let ofList (l : list<'a>) =\n        { tree = l |> FingerTree.ofList m }\n\n    let ofArray (l : 'a[]) =\n        { tree = l |> FingerTree.ofArray m }\n\n    let toSeq (a : Arr<'a>) =\n        a.tree |> FingerTree.toSeq\n\n    let toList (a : Arr<'a>) =\n        a.tree |> FingerTree.toList\n\n    let toArray (a : Arr<'a>) =\n        a.tree |> FingerTree.toArray\n\n\n    let length (a : Arr<'a>) =\n        a.tree |> FingerTree.total\n\n    let get (i : int) (a : Arr<'a>) =\n        if i < 0 then failwith \"index out of range\"\n\n        match a.tree |> FingerTree.split (fun id -> id > i) with\n            | Split(_,v,_) -> v\n            | NoSplit -> failwith \"index out of range\"\n\n    let set (i : int) (v : 'a) (a : Arr<'a>) =\n        if i < 0 then failwith \"index out of range\"\n\n        match a.tree |> FingerTree.split (fun id -> id > i) with\n            | Split(l,_,r) ->\n                { tree = FingerTree.concatWithMiddle l [v] r }\n            | NoSplit -> \n                failwith \"index out of range\"\n\n    let splitAt (i : int) (a : Arr<'a>) =\n        if i < 0 then \n            failwith \"index out of range\"\n        elif i = 0 then\n            empty, a\n        else\n            match a.tree |> FingerTree.split (fun id -> id > i) with\n                | Split(l,v,r) ->\n                    { tree = l }, { tree = FingerTree.prepend v r }\n                | _ ->\n                    failwith \"index out of range\"\n\n    let concatWithMiddle (l : Arr<'a>) (m : list<'a>) (r : Arr<'a>) =\n        { tree = FingerTree.concatWithMiddle l.tree m r.tree }\n\n    let replaceRange (first : int) (size : int) (newElements : list<'a>) (a : Arr<'a>) =\n        if first < 0 then failwith \"index out of range\"\n        if size < 0 then failwith \"replace does not take negative sizes\"\n\n        let (l,rest) = splitAt first a\n        let (_,r) = splitAt size rest\n        concatWithMiddle l newElements r\n\n    let viewl (a : Arr<'a>) =\n        match FingerTree.viewl a.tree with\n            | Some(v,r) -> Some(v, { tree = r })\n            | None -> None\n\n    let viewr (a : Arr<'a>) =\n        match FingerTree.viewr a.tree with\n            | Some(v,r) -> Some(v, { tree = r })\n            | None -> None\n\n\n// sorted list built upon FingerTree\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype SortedList<'a when 'a : comparison> = private { tree : FingerTree<'a, Option<'a>> } with\n    member private x.AsString =\n        x.tree |> FingerTree.toList |> sprintf \"%A\"\n\nmodule SortedList =\n    \n    let private m<'a when 'a : comparison> : Measure<'a, Option<'a>> =\n        {\n            zero = None\n            add = max\n            f = Some\n        }\n\n    let empty<'a when 'a : comparison> : SortedList<'a> =\n        { tree = FingerTree.custom m }\n\n    let add (v : 'a) (s : SortedList<'a>) =\n        match FingerTree.split (fun x -> x >= Some v) s.tree with\n            | Split(l,x,r) ->\n                let c = compare x v\n                if c = 0 then s\n                elif c > 0 then { tree = FingerTree.concatWithMiddle l [v;x] r }\n                else failwith \"\"\n            | NoSplit ->\n                { tree = FingerTree.append v s.tree }\n    \n    let remove (v : 'a) (s : SortedList<'a>) =\n        match FingerTree.split (fun x -> x >= Some v) s.tree with\n            | Split(l,x,r) ->\n                let c = compare x v\n                if c = 0 then { tree = FingerTree.concatWithMiddle l [] r }\n                elif c > 0 then s\n                else failwith \"\"\n            | NoSplit ->\n                s\n     \n    let ofSeq (vs : seq<'a>) =\n        let mutable current = empty\n        for v in vs do current <- add v current\n        current\n\n    let ofList (vs : list<'a>) =\n        vs |> ofSeq\n\n    let ofArray (vs : 'a[]) =\n        vs |> ofSeq\n\n    let toSeq (s : SortedList<'a>) =\n        s.tree.ViewLeft\n\n    let toList (s : SortedList<'a>) =\n        s.tree.ViewLeft |> Seq.toList\n    \n    let toArray (s : SortedList<'a>) =\n        s.tree.ViewLeft |> Seq.toArray\n\n    let splitLessOrEqual (v : 'a) (s : SortedList<'a>) =\n        match FingerTree.split (fun vi -> vi >= Some v) s.tree with\n            | Split(l,x,r) ->\n                let c = compare x v\n                if c > 0 then ({ tree = l }, { tree = FingerTree.prepend x r})\n                else ({ tree = FingerTree.append x l }, { tree = r })\n\n            | NoSplit ->\n                (s, empty)\n\n    let splitLess (v : 'a) (s : SortedList<'a>) =\n        match FingerTree.split (fun vi -> vi >= Some v) s.tree with\n            | Split(l,x,r) ->\n                let c = compare x v\n                if c < 0 then ({ tree = FingerTree.append x l }, { tree = r })\n                else ({ tree = l }, { tree = FingerTree.prepend x r})\n            | NoSplit ->\n                (s, empty)\n\n    let inline split (v : 'a) (s : SortedList<'a>) =\n        splitLessOrEqual v s\n\n    let minOpt (s : SortedList<'a>) =\n        match s.tree.root with\n            | Empty -> None\n            | Single x -> Some(x)\n            | Deep { prefix = p } ->\n                Some (Affix.first p)\n\n    let maxOpt (s : SortedList<'a>) =\n        match s.tree.root with\n            | Empty -> None\n            | Single x -> Some(x)\n            | Deep { suffix = s } ->\n                Some (Affix.last s)\n\n    let rangeOpt (s : SortedList<'a>) =\n        match s.tree.root with\n            | Empty -> None\n            | Single x -> Some(x,x)\n            | Deep { prefix = p; suffix = s } ->\n                Some (Affix.first p, Affix.last s)\n\n    let inline max (s : SortedList<'a>) =\n        s |> maxOpt |> Option.get\n\n    let inline min (s : SortedList<'a>) =\n        s |> minOpt |> Option.get\n\n    let inline range (s : SortedList<'a>) =\n        s |> rangeOpt |> Option.get\n\n    let isEmpty (s : SortedList<'a>) =\n        match s.tree.root with\n            | Empty -> true\n            | _ -> false\n\n\n    let union (l : SortedList<'a>) (r : SortedList<'a>) =\n        let lt = FingerTree.total l.tree\n        let rt = FingerTree.total r.tree\n\n        match lt, rt with\n            | None, None -> empty\n            | Some _, None -> l\n            | None, Some _ -> r\n            | Some lv, Some rv ->\n                let rightMin = min r\n                let leftMin = min l\n                if lv < rightMin then\n                    { tree = FingerTree.concat l.tree r.tree }\n                elif rv < leftMin then\n                    { tree = FingerTree.concat r.tree l.tree }\n                else\n                    let mutable res = l\n                    for e in r.tree.ViewLeft do\n                        res <- add e res\n                    res\n\n    let unsafeConcatWithMiddle (l : SortedList<'a>) (m : list<'a>) (r : SortedList<'a>) =\n        { tree = FingerTree.concatWithMiddle l.tree m r.tree }\n   \n    let unsafeAppendRange (l : SortedList<'a>) (r : list<'a>) =\n        { tree = FingerTree.concatWithMiddle l.tree r (FingerTree.custom m) }\n    \n    let unsafePrependRange (l : list<'a>) (r : SortedList<'a>) =\n        { tree = FingerTree.concatWithMiddle (FingerTree.custom m) l r.tree }\n\n\n    let viewl (l : SortedList<'a>) =\n        match FingerTree.viewl l.tree with\n            | Some(v,rest) -> Some(v, { tree = rest })\n            | None -> None\n\n    let viewr (l : SortedList<'a>) =\n        match FingerTree.viewr l.tree with\n            | Some(v,rest) -> Some(v, { tree = rest })\n            | None -> None\n\n    let replaceRangeInclusive (firstInclusive : 'a) (lastInclusive : 'a) (newElements : list<'a>) (s : SortedList<'a>) =\n        let inRange = newElements |> List.forall (fun v -> v >= firstInclusive && v <= lastInclusive)\n        let (l, rest) = splitLess firstInclusive s\n        let (_,r) = splitLessOrEqual lastInclusive rest\n\n        if inRange then\n            { tree = FingerTree.concatWithMiddle l.tree newElements r.tree }\n        else\n            let maxE = newElements |> List.max\n            let minE = newElements |> List.min\n\n            if maxE < min l then\n                let l' = List.foldBack FingerTree.prepend newElements l.tree\n                { tree = FingerTree.concat l' r.tree}\n            elif minE > max r then\n                let r' = List.fold (fun s e -> FingerTree.append e s) r.tree newElements\n                { tree = FingerTree.concat l.tree r' }\n            else\n                let mutable l = l\n                for e in newElements do l <- add e l\n                union l r\n\n    let replaceRangeExclusive (firstExclusive : 'a) (lastExclusive : 'a) (newElements : list<'a>) (s : SortedList<'a>) =\n        let inRange = newElements |> List.forall (fun v -> v > firstExclusive && v < lastExclusive)\n        let (l, rest) = splitLessOrEqual firstExclusive s\n        let (_,r) = splitLess lastExclusive rest\n\n        if inRange then\n            { tree = FingerTree.concatWithMiddle l.tree newElements r.tree }\n        else\n            let maxE = newElements |> List.max\n            let minE = newElements |> List.min\n\n            if maxE < min l then\n                let l' = List.foldBack FingerTree.prepend newElements l.tree\n                { tree = FingerTree.concat l' r.tree}\n            elif minE > max r then\n                let r' = List.fold (fun s e -> FingerTree.append e s) r.tree newElements\n                { tree = FingerTree.concat l.tree r' }\n            else\n                let mutable l = l\n                for e in newElements do l <- add e l\n                union l r\n\n\n\n[<CustomComparison; CustomEquality>]\ntype private HalfRange = \n    struct\n        val mutable public Value : int\n        val mutable public IsMax : bool\n\n        new(v,m) = { Value = v; IsMax = m }\n\n        interface IComparable with\n            member x.CompareTo(o) =\n                match o with\n                    | :? HalfRange as o -> \n                        let c = compare x.Value o.Value\n                        if c <> 0 then c\n                        else compare (if x.IsMax then 1 else 0) (if o.IsMax then 1 else 0)\n\n                    | _ -> failwith \"uncomparable\"\n\n        override x.GetHashCode() =\n            HashCode.Combine(x.Value.GetHashCode(), x.IsMax.GetHashCode())\n\n        override x.Equals o =\n            match o with\n                | :? HalfRange as o -> o.Value = x.Value && o.IsMax = x.IsMax\n                | _ -> false\n\n        override x.ToString() =\n            if x.IsMax then sprintf \"Leq %d\" x.Value\n            else sprintf \"Geq %d\" x.Value\n\n    end\n\n[<StructuredFormatDisplay(\"{AsString}\")>]\ntype IntervalTree = private { list : SortedList<HalfRange> } with\n\n    interface System.Collections.IEnumerable with\n        member x.GetEnumerator() = \n            new IntervalEnumerator(x.list |> SortedList.toSeq) :> System.Collections.IEnumerator\n\n    interface IEnumerable<Range1i> with\n        member x.GetEnumerator() = \n            new IntervalEnumerator(x.list |> SortedList.toSeq) :> IEnumerator<_>\n\n    member private x.AsString =\n        x |> Seq.toList |> sprintf \"%A\"\n\nand private IntervalEnumerator(input : seq<HalfRange>) =\n    let mutable e = input.GetEnumerator()\n    let mutable last = Unchecked.defaultof<HalfRange>\n    let mutable current = Unchecked.defaultof<HalfRange>\n\n    member x.Current =\n        Range1i(last.Value, current.Value - 1)\n\n    interface System.Collections.IEnumerator with\n        member x.MoveNext() =\n            if e.MoveNext() then\n                last <- e.Current\n                if e.MoveNext() then\n                    current <- e.Current\n                    true\n                else\n                    false\n            else\n                false\n        \n        member x.Current = x.Current :> obj\n        member x.Reset() =\n            e.Reset()\n            last <- Unchecked.defaultof<_>\n            current <- Unchecked.defaultof<_>\n\n    interface IEnumerator<Range1i> with\n        member x.Dispose() =\n            e.Dispose()\n\n        member x.Current = x.Current\n\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule IntervalTree = \n\n    [<AutoOpen>]\n    module private HalfRanges =\n        let Leq v =\n            HalfRange(v, true)\n\n        let Geq v =\n            HalfRange(v, false)\n\n        let (|Leq|Geq|) (r : HalfRange) =\n            if r.IsMax then Leq r.Value\n            else Geq r.Value\n        \n\n        let inline value (r : HalfRange) = r.Value\n\n    let empty = { list = SortedList.empty }\n\n    let min (t : IntervalTree) =\n        match SortedList.minOpt t.list with\n            | Some min -> min.Value\n            | None -> Int32.MaxValue\n\n    let max (t : IntervalTree) =\n        match SortedList.maxOpt t.list with\n            | Some max -> max.Value - 1\n            | None -> Int32.MinValue\n\n    let range (t : IntervalTree) =\n        match SortedList.rangeOpt t.list with\n            | Some (min,max) -> Range1i(min.Value,max.Value-1)\n            | None -> Range1i.Invalid\n\n    let computeCovered (t : IntervalTree) =\n        let mutable size = 0\n        for r in t do\n            size <- size + 1 + r.Size\n        size\n            \n\n    let computeDensity (t : IntervalTree) =\n        let covered = computeCovered t |> float\n        let overall = (range t).Size + 1 |> float\n\n        covered / overall\n\n\n    let insert (r : Range1i) (t : IntervalTree) =\n        let r = Range1i(r.Min, r.Max + 1)\n        if SortedList.isEmpty t.list then\n            { list = SortedList.ofList [Geq r.Min; Leq r.Max] }\n        else\n            let (left,rest) = t.list |> SortedList.splitLess (Leq r.Min)\n            let (inner,right) = rest |> SortedList.splitLessOrEqual (Geq r.Max)\n\n            let smaller = SortedList.viewr left |> Option.map fst\n            let greater = SortedList.viewl right  |> Option.map fst\n\n\n            match smaller, greater with\n                | None, None ->\n                    { list = SortedList.ofList [Geq r.Min; Leq r.Max] }\n                | Some s, None ->\n                    match s with\n                        | Leq v ->\n                            { list = SortedList.unsafeAppendRange left [Geq r.Min; Leq r.Max] }\n                        | Geq v ->\n                            { list = SortedList.unsafeAppendRange left [Leq r.Max] }\n\n                | None, Some g ->\n                    match g with\n                        | Leq v ->\n                            { list = SortedList.unsafePrependRange [Geq r.Min] right }\n                        | Geq v ->\n                            { list = SortedList.unsafePrependRange [Geq r.Min; Leq r.Max] right }\n\n                | Some s, Some g ->\n                    match s, g with\n                        | Leq lmax, Leq rmax ->\n                            { list = SortedList.unsafeConcatWithMiddle left [Geq r.Min] right }\n\n                        | Leq lmax, Geq rmin ->\n                            { list = SortedList.unsafeConcatWithMiddle left [Geq r.Min; Leq r.Max] right }\n\n                        | Geq lmin, Leq rmax ->\n                            { list = SortedList.unsafeConcatWithMiddle left [] right }\n\n                        | Geq lmin, Geq rmin ->\n                            { list = SortedList.unsafeConcatWithMiddle left [Leq r.Max] right }\n\n    let remove (r : Range1i) (t : IntervalTree) =\n        let r = Range1i(r.Min, r.Max + 1)\n\n        if SortedList.isEmpty t.list then\n            { list = t.list }\n        else\n            let (left,rest) = t.list |> SortedList.splitLess (Leq r.Min)\n            let (inner,right) = rest |> SortedList.splitLessOrEqual (Geq r.Max)\n\n            let smaller = SortedList.viewr left |> Option.map fst\n            let greater = SortedList.viewl right  |> Option.map fst\n\n\n            match smaller, greater with\n                | None, None ->\n                    { list = SortedList.ofList [] }\n                | Some s, None ->\n                    match s with\n                        | Leq v ->\n                            { list = left }\n                        | Geq v ->\n                            { list = SortedList.unsafeAppendRange left [Leq r.Min] }\n\n                | None, Some g ->\n                    match g with\n                        | Leq v ->\n                            { list = SortedList.unsafePrependRange [Geq r.Max] right }\n                        | Geq v ->\n                            { list = right }\n\n                | Some s, Some g ->\n                    match s, g with\n                        | Leq lmax, Leq rmax ->\n                            { list = SortedList.unsafeConcatWithMiddle left [Geq r.Max] right }\n\n                        | Leq lmax, Geq rmin ->\n                            { list = SortedList.unsafeConcatWithMiddle left [] right }\n\n                        | Geq lmin, Leq rmax ->\n                            { list = SortedList.unsafeConcatWithMiddle left [Leq r.Min; Geq r.Max] right }\n\n                        | Geq lmin, Geq rmin ->\n                            { list = SortedList.unsafeConcatWithMiddle left [Leq r.Min] right }\n\n\n    let toSeq (t : IntervalTree) = t :> seq<_>\n    let toList (t : IntervalTree) = t |> Seq.toList\n    let toArray (t : IntervalTree) = t |> Seq.toArray\n\n    let ofSeq (s : seq<Range1i>) =\n        let mutable res = empty\n        for r in s do res <- insert r res\n        res\n\n    let ofList (l : list<Range1i>) =\n        l |> ofSeq\n\n    let ofArray (a : Range1i[]) =\n        a |> ofSeq\n\n          \n\n// some tests\nmodule Test =\n    open Arr.Patterns\n\n    let run() =\n        let arr = Arr.ofList [0..9]\n\n\n        printfn \"length = %A\" (Arr.length arr)\n\n        printfn \"arr = %A\" (Arr.toList arr)\n        let e4 = Arr.get 4 arr\n        printfn \"arr[4] = %A\" e4\n\n\n        printfn \"arr[4] <- -1\"\n        let arr = Arr.set 4 -1 arr\n        printfn \"arr = %A\" (Arr.toList arr)\n\n        printfn \"Arr.replaceRange 1 2 [1000] \"\n        let arr = arr |> Arr.replaceRange 1 2 [1000] \n        printfn \"arr = %A\" (Arr.toList arr)\n\n        let (l,r) = arr |> Arr.splitAt 4\n        printfn \"arr.[0..3] = %A\" l\n        printfn \"arr.[4..] = %A\" r\n\n        match arr with\n            | ArrCons(v,rest) ->\n                printfn \"head = %A\" v\n                printfn \"tail = %A\" rest\n            | ArrNil ->\n                printfn \"empty\"\n\n\n    let run2() =\n        let l = SortedList.ofList [10;2;3;1;9;4;12]\n        printfn \"%A\" l\n\n        let sp = 4\n        let (left, right) = SortedList.split sp l\n        printfn \"l[<=%A] = %A\" sp left\n        printfn \"l[>%A] = %A\" sp right\n\n\n        let low = SortedList.ofList [1;2;3]\n        let high = SortedList.ofList [4;5;6]\n        printfn \"low = %A\" low\n        printfn \"high = %A\" high\n\n        let merged = SortedList.union low high\n        printfn \"merged = %A\" merged\n\n\n        let (low', high') = SortedList.split 3 merged\n        printfn \"low' = %A\" low'\n        printfn \"high' = %A\" high'\n\n\n        let a = SortedList.ofList [1;10;3]\n        let b = SortedList.ofList [4;5;6]\n        printfn \"a = %A\" a\n        printfn \"b = %A\" b\n        let merged = SortedList.union a b\n        printfn \"merged = %A\" merged\n\n        printfn \"range(a) = %A\" (SortedList.range a)\n        printfn \"range(b) = %A\" (SortedList.range b)\n\n\n        let test = l |> SortedList.replaceRangeInclusive 4 10 [8]\n        printfn \"l = %A\" l\n        printfn \"test = %A\" test\n\n\n    let run3() =\n        let res = IntervalTree.ofList [Range1i(0,4); Range1i(6,10); Range1i(12,20)]\n\n        printfn \"%A\" res\n"
  },
  {
    "path": "src/Demo/Sketch/FutureList.fsx",
    "content": "﻿#I @\"..\\..\\..\\bin\\Release\"\n\n#r \"Aardvark.Base.dll\"\n#r \"Aardvark.Base.Essentials.dll\"\n#r \"Aardvark.Base.TypeProviders.dll\"\n#r \"Aardvark.Base.FSharp.dll\"\n#r \"Aardvark.Base.Incremental.dll\"\n\nopen System\nopen System.Threading\nopen System.Linq\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\n\n[<AutoOpen>]\nmodule private FutureUtils =\n    let noDisposable = { new IDisposable with member x.Dispose() = () }\n\n\n\n/// defines a future-value\ntype Future<'a> =\n    abstract member OnReady : readyCallback : ('a -> unit) -> IDisposable\n\ntype FutureSubject<'a>() =\n    let mutable value = None\n    let callbacks = HashSet<'a -> unit>()\n\n    let add cb =\n        lock callbacks (fun () -> callbacks.Add cb)\n\n    let remove cb =\n        lock callbacks (fun () -> callbacks.Remove cb)\n\n\n    member x.Set(v : 'a) =\n        value <- Some v\n        let all = lock callbacks (fun () -> let arr = callbacks.ToArray() in callbacks.Clear(); arr)\n        for a in all do a v\n\n    member x.OnReady(cb : 'a -> unit) =\n        match value with\n            | Some v -> \n                cb v\n                noDisposable\n            | None -> \n                if add cb then\n                    { new IDisposable with member x.Dispose() = remove cb |> ignore }\n                else\n                    noDisposable\n\n    interface Future<'a> with\n        member x.OnReady cb = x.OnReady cb\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Future =\n\n\n    let subject() : FutureSubject<'a> = FutureSubject()\n\n    let custom (create : ('a -> unit) -> IDisposable) =\n        { new Future<'a> with\n            member x.OnReady(cb) = create cb\n        }  \n\n    let ofValue (v : 'a) =\n        custom (fun cb ->\n            cb v\n            noDisposable\n        )\n\n    let map (f : 'a -> 'b) (m : Future<'a>) =\n        custom (fun cb ->\n            m.OnReady(fun v ->\n                v |> f |> cb\n            )\n        )\n\n    let bind (f : 'a -> Future<'b>) (m : Future<'a>) =\n        custom (fun cb ->\n            let inner = ref noDisposable\n            let outer =\n                m.OnReady(fun a ->\n                    inner := (f a).OnReady cb\n                )\n\n            { new IDisposable with member x.Dispose() = inner.Value.Dispose(); outer.Dispose() }\n        )\n\n    let delay (f : unit -> Future<'a>) =\n        custom (fun cb ->\n            f().OnReady cb\n        )\n\n    let never<'a> : Future<'a> =\n        custom (fun _ -> noDisposable)\n\n    type private FutureMod<'a>(m : IMod<'a>) =\n        inherit Mod.AbstractMod<'a>()\n\n        let mutable finished = 0\n        let subject = FutureSubject()\n\n        override x.Compute() =\n            m.GetValue x\n\n        override x.Mark() =\n            let wasFinished = Interlocked.Exchange(&finished, 1)\n            if wasFinished = 0 then\n                try\n                    let v = x.GetValue null \n                    subject.Set v\n                with :? LevelChangedException ->\n                    finished <- wasFinished\n\n            false\n\n        interface Future<'a> with\n            member x.OnReady cb = subject.OnReady cb\n\n    let next (m : IMod<'a>) =\n        FutureMod(m) :> Future<'a>\n\n    let either (l : Future<'a>) (r : Future<'b>) =\n        custom (fun cb ->\n            let emitted = ref 0\n            let leftSub = ref noDisposable\n            let rightSub = ref noDisposable\n\n            leftSub :=\n                l.OnReady(fun l -> \n                    if Interlocked.Increment &emitted.contents = 1 then\n                        cb (Left l)\n                        rightSub.Value.Dispose()\n                    else\n                        leftSub.Value.Dispose()\n                )\n\n            rightSub :=\n                r.OnReady(fun r -> \n                    if Interlocked.Increment &emitted.contents = 1 then\n                        cb (Right r)\n                        leftSub.Value.Dispose()\n                    else\n                        rightSub.Value.Dispose()\n                )\n\n\n            { new IDisposable with member x.Dispose() = leftSub.Value.Dispose(); rightSub.Value.Dispose() }\n\n        )\n\n[<AutoOpen>]\nmodule ``Future Builder`` =\n    \n    type FutureBuilder() =\n        member x.Bind(m : Future<'a>, f : 'a -> Future<'b>) =\n            m |> Future.bind f\n\n        member x.Return(v) =\n            Future.ofValue v\n\n        member x.ReturnFrom (f : Future<'a>) =\n            f\n\n        member x.Delay (f : unit -> Future<'a>) =\n            Future.delay f\n\n    let future = FutureBuilder()\n\n\n\n/// define a future-list\ntype FutureList<'s, 'a> = { run : 's -> Future<'s * FutureListType<'s, 'a>> }\n\nand FutureListType<'s, 'a> = \n    | Nil\n    | Error of Exception\n    | Cons of 'a * FutureList<'s, 'a>\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule FutureList =\n    \n    type private EmptyImpl<'s, 'a>() =\n        static let instance : FutureList<'s, 'a> = { run = fun s -> Future.ofValue(s, Nil) }\n        static member Instance = instance\n\n    let empty<'s, 'a> = EmptyImpl<'s, 'a>.Instance\n\n    let single (value : 'a) : FutureList<'s, 'a> =\n        { run = fun s -> Future.ofValue(s, Cons(value, empty)) }\n\n    let rec ofList (values : list<'a>) : FutureList<'s, 'a> =\n        match values with\n            | [] -> empty\n            | v::vs ->\n                { run = fun s -> Future.ofValue(s, Cons(v, ofList vs)) }\n\n    let inline ofSeq (values : seq<'a>) =\n        values |> Seq.toList |> ofList\n\n    let inline ofArray (arr : 'a[]) =\n        arr |> Array.toList |> ofList\n\n\n    let rec map (f : 'a -> 'b) (l : FutureList<'s, 'a>) =\n        { run = fun s ->\n            future {\n                let! (s,l) = l.run s\n                match l with\n                    | Nil -> return s, Nil\n                    | Error e -> return s, Error e\n                    | Cons(v, rest) ->\n                        return s, Cons(f v, map f rest)\n            }\n        }\n\n    let rec append (l : FutureList<'s, 'a>) (r : FutureList<'s, 'a>) =\n        { run = fun s ->\n            future {\n                let! (s, l) = l.run s\n                match l with\n                    | Error e -> \n                        return s, Error e\n                    | Nil -> \n                        return! r.run s\n                    | Cons(v, rest) ->\n                        return s, Cons(v, append rest r)\n            }\n        }\n\n    let rec collect (f : 'a -> FutureList<'s, 'b>) (m : FutureList<'s, 'a>) =\n        { run = fun s ->\n            future {\n                let! (s,v) = m.run s\n                match v with\n                    | Error e -> return s, Error e\n                    | Nil -> return s, Nil\n                    | Cons(v, rest) ->\n                        return! (append (f v) (collect f rest)).run s\n            }\n        }\n\n    let inline concat (l : FutureList<'s, FutureList<'s, 'a>>) =\n        l |> collect id\n\n    let inline concat' (l : seq<FutureList<'s, 'a>>) =\n        l |> Seq.fold append empty\n\n    let rec choose (f : 'a -> Option<'b>) (m : FutureList<'s, 'a>) =\n        { run = fun s ->\n            future {\n                let! (s,v) = m.run s\n                match v with\n                    | Error e -> return s, Error e\n                    | Nil -> return s, Nil\n                    | Cons(v, rest) ->\n                        match f v with  \n                            | Some v -> return s, Cons(v, choose f rest)\n                            | None -> return! (choose f rest).run s\n            }\n        }\n\n    let rec filter (f : 'a -> bool) (m : FutureList<'s, 'a>) =\n        { run = fun s ->\n            future {\n                let! (s,v) = m.run s\n                match v with\n                    | Error e -> return s, Error e\n                    | Nil -> return s, Nil\n                    | Cons(v, rest) ->\n                        if f v then  \n                            return s, Cons(v, filter f rest)\n                        else\n                            return! (filter f rest).run s\n            }\n        }\n\n    let rec skip (n : int) (m : FutureList<'s, 'a>) =\n        if n = 0 then \n            m\n        else\n            { run = fun s ->\n                future {\n                    let! (s, c) = m.run s\n                    match c with\n                        | Nil -> return s, Nil\n                        | Error e -> return s, Error e\n                        | Cons(_,cont) -> return! (skip (n-1) cont).run s\n                }\n            }\n\n    let ofObservable (o : IObservable<'a>) : FutureList<'s, 'a> =\n        let first = Future.subject()\n        let mutable current = first\n\n        let subscription = ref noDisposable\n        subscription :=\n            o.Subscribe {\n                new IObserver<'a> with\n                    member x.OnNext(v) =\n                        let next = Future.subject()\n                        current.Set(Cons(v, { run = fun s -> next |> Future.map (fun v -> s, v) }))\n                        current <- next\n                    member x.OnError e =\n                        subscription.Value.Dispose()\n                        current.Set (Error e)\n                    member x.OnCompleted() =\n                        subscription.Value.Dispose()\n                        current.Set Nil\n            }\n\n        { run = fun s -> first |> Future.map (fun v -> s, v)}\n\n    let ofMod (m : IMod<'a>) : FutureList<'s, 'a> =\n        m |> Mod.toObservable |> ofObservable |> skip 1\n\n    let rec intersperse (l : FutureList<'s, 'a>) (r : FutureList<'s, 'b>) =\n        { run = fun s ->\n            future {\n                let lf = l.run s\n                let rf = r.run s\n\n                let! v = Future.either lf rf \n\n                match v with\n                    | Left (s,l) ->\n                        match l with\n                            | Nil -> return! (map Right r).run s\n                            | Cons(v,rest) -> return s, Cons(Left v, intersperse rest r)\n                            | Error e -> return s, Error e\n                    | Right (s,r) ->\n                        match r with\n                            | Nil -> return! (map Left l).run s\n                            | Cons(v,rest) -> return s, Cons(Right v, intersperse l rest)\n                            | Error e -> return s, Error e\n\n            }\n//\n//            Future.custom (fun cb ->\n//                let doneCount = ref 0\n//                let ls = ref noDisposable\n//                let rs = ref noDisposable\n//                let unsub() = ls.Value.Dispose(); rs.Value.Dispose()\n//\n//                ls := \n//                    lf.OnReady (fun (s, v) -> \n//                        match v with\n//                            | Error e ->\n//                                unsub()\n//                                cb (s,Error e)\n//                            | Nil ->\n//                                ls.Value.Dispose()\n//                                let dc = Interlocked.Increment(&doneCount.contents)\n//                                if dc = 2 then cb(s,Nil)\n//                            | Cons(v, rest) ->\n//                                unsub()\n//                                cb (s, Cons(Left v, intersperse rest r))\n//                    )\n//                \n//                rs := \n//                    rf.OnReady (fun (s, v) -> \n//                        match v with\n//                            | Error e ->\n//                                unsub()\n//                                cb (s,Error e)\n//                            | Nil ->\n//                                rs.Value.Dispose()\n//                                let dc = Interlocked.Increment(&doneCount.contents)\n//                                if dc = 2 then cb(s,Nil)\n//                            | Cons(v, rest) ->\n//                                unsub()\n//                                cb (s, Cons(Right v, intersperse l rest))\n//                    )\n//                { new IDisposable with member x.Dispose() = unsub() }\n//            )\n        }\n\n    let modifyState (f : 's -> 's) =\n        { run = fun s ->\n            Future.ofValue (f s, Cons((), empty))\n        }\n\n    let modifyState' (f : 's -> 's * 'a) =\n        { run = fun s ->\n            let s, r = f s\n            Future.ofValue (s, Cons(r, empty))\n        }\n\n\n    let getState<'s> : FutureList<'s, 's> =\n        { run = fun s ->\n            Future.ofValue(s, Cons(s, empty))\n        }\n\n    let putState (newState : 's) : FutureList<'s, unit> =\n        { run = fun _ ->\n            Future.ofValue(newState, Cons((), empty))\n        }\n\n\n    let rec subscribe (initial : 's) (cb : 's * 'a -> unit) (l : FutureList<'s, 'a>) =\n        let future = l.run initial\n        let inner = ref noDisposable\n        let outer = ref noDisposable\n\n        outer := \n            future.OnReady(fun (s, v) ->\n                match v with\n                    | Nil -> outer.Value.Dispose()\n                    | Error e -> outer.Value.Dispose()\n                    | Cons(v, rest) ->\n                        cb(s, v)\n                        inner := subscribe s cb rest\n            )\n\n        { new IDisposable with member x.Dispose() = inner.Value.Dispose(); outer.Value.Dispose() }\n\n\n    let rec private subscribeObs (initial : 's) (cb : IObserver<'a>) (l : FutureList<'s, 'a>) =\n        let future = l.run initial\n        let inner = ref noDisposable\n        let outer = ref noDisposable\n\n        outer := \n            future.OnReady(fun (s, v) ->\n                match v with\n                    | Nil -> \n                        cb.OnCompleted()\n                        outer.Value.Dispose()\n                    | Error e -> \n                        cb.OnError(e)\n                        outer.Value.Dispose()\n                    | Cons(v, rest) ->\n                        cb.OnNext(v)\n                        inner := subscribeObs s cb rest\n            )\n\n        { new IDisposable with member x.Dispose() = inner.Value.Dispose(); outer.Value.Dispose() }\n\n\n    let toObservable (initial : 's) (l : FutureList<'s, 'a>) =\n        let observers = HashSet<IObserver<'a>>()\n        \n        let all() = lock observers (fun () -> Seq.toArray observers)\n\n        let myObserver =\n            { new IObserver<'a> with\n                member x.OnNext(v) = \n                    for o in all() do o.OnNext v\n\n                member x.OnError e =\n                    for o in all() do o.OnError e\n\n                member x.OnCompleted() =\n                    for o in all() do o.OnCompleted()\n            }\n\n        let disp = l |> subscribeObs initial myObserver\n\n        { new IObservable<'a> with\n            member x.Subscribe o =\n                let added = lock observers (fun () -> observers.Add o)\n\n                if added then { new IDisposable with member x.Dispose() = lock observers (fun () -> observers.Remove o |> ignore)}\n                else noDisposable\n        }\n\n\n\n        \n\n[<AutoOpen>]\nmodule ``FutureList Builder`` =\n    \n    type FutureListBuilder() =\n        \n        member x.For(m : IObservable<'a>, f : 'a -> FutureList<'s, 'b>) =\n            m |> FutureList.ofObservable |> FutureList.collect f\n\n        member x.For(m : IMod<'a>, f : 'a -> FutureList<'s, 'b>) =\n            m |> FutureList.ofMod |> FutureList.collect f\n\n        member x.For(m : FutureList<'s, 'a>, f : 'a -> FutureList<'s, 'b>) =\n            m |> FutureList.collect f\n\n        member x.Yield (v : 'a) =\n            FutureList.single v\n\n        member x.Delay(f : unit -> FutureList<'s, 'a>) = f\n\n        member x.Run(f : unit -> FutureList<'s, 'a>) = f()\n\n        member x.Combine(l : FutureList<'s, 'a>, r : unit -> FutureList<'s, 'a>) =\n            FutureList.append l { run = fun s -> r().run s }\n\n        member x.Bind(m : FutureList<'s, 'a>, f : 'a -> FutureList<'s, 'b>) =\n            { run = fun s ->\n                future {\n                    let! (s, v) = m.run s\n                    match v with\n                        | Nil -> return s, Nil\n                        | Error e -> return s, Error e\n                        | Cons(v,_) -> return! (f v).run s\n                }\n            }\n\n        member x.Return(u : unit) =\n            FutureList.empty\n\n        member x.Zero() =\n            FutureList.empty\n\n\n        member x.While(guard : unit -> #IMod<bool>, body : unit -> FutureList<'s, 'a>) =\n            let guard = guard() :> IMod<bool> |> FutureList.ofMod\n\n            let rec kernel (both : FutureList<'s, Either<bool, 'a>>)=\n                { run = fun s ->\n                    future {\n                        let! (s,res) = both.run s\n                        match res with\n                            | Nil -> return s, Nil\n                            | Error e -> return s, Error e\n                            | Cons(v, rest) ->\n                                match v with\n                                    | Left b ->\n                                        if not b then return s, Nil\n                                        else return! (kernel rest).run s\n\n                                    | Right a -> \n                                        return s, Cons(a, kernel rest)\n                    }\n                }\n             \n            let rec wait(guard : FutureList<'s, bool>) =\n                { run = fun s ->\n                    future {\n                        let! (s, g) = guard.run s\n                        match g with\n                            | Nil -> return s, Nil\n                            | Error e -> return s, Error e\n                            | Cons(v, rest) ->\n                                if v then return! (kernel (FutureList.intersperse rest (body()))).run s\n                                else return! (wait rest).run s\n                    }\n                }\n\n            wait guard\n\n        member x.While(guard : unit -> bool, body : unit -> FutureList<'s, 'a>) =\n            { run = fun s ->\n                if guard() then\n                    let l = FutureList.append (body()) { run = fun s -> body().run s }\n                    l.run s\n                else\n                    Future.ofValue(s, Nil)\n            }\n\n\n    let flist = FutureListBuilder()\n\n    type ModRef<'a> with\n        member x.Emit(value : 'a) =\n            x.UnsafeCache <- value\n            x.MarkOutdated()\n\n\n\n/// define a worklfow \ntype WorkflowState =\n    {\n        refValues : Map<int, obj>\n        currentId : int\n    } with\n\n    static member Empty = { refValues = Map.empty; currentId = 0 }\n\ntype WorkflowResult<'i, 'f> =\n    | Final of 'f\n    | Update of 'i\n\ntype Workflow<'i, 'f> = { obs : IObservable<WorkflowResult<'i, 'f>> }\n\ntype StateWorkflow<'i, 'f> = { list : FutureList<WorkflowState, WorkflowResult<'i, 'f>> }\ntype WorkflowList<'a> = FutureList<WorkflowState, 'a>\n\nmodule Workflow =\n    \n    let updates (l : Workflow<'i, 'f>) =\n        l.obs |> Observable.choose (function Update v -> Some v | _ -> None)\n\n    let finals (l : Workflow<'i, 'f>) =\n        l.obs |> Observable.choose (function Final v -> Some v | _ -> None)\n\n    let all (l : Workflow<'i, 'f>) =\n        l.obs\n\n    let latestUpdate (def : 'i) (l : Workflow<'i, 'f>) =\n        let ref = Mod.init def\n\n        l.obs |> Observable.add (fun v ->\n            match v with\n                | Update v -> transact (fun () -> Mod.change ref v)\n                | Final v -> transact (fun () -> Mod.change ref def)\n        )\n\n        ref :> IMod<_>\n\n    let allFinal(l : Workflow<'i, 'f>) =\n        let ref = CSet.empty\n\n        l.obs |> Observable.add (fun v ->\n            match v with\n                | Update v -> ()\n                | Final v -> transact (fun () -> CSet.add v ref |> ignore)\n        )\n\n        ref :> aset<_>\n\n\n\n\n\n[<AutoOpen>]\nmodule ``Workflow Builder`` =\n    \n    type StateRef<'a> internal(id : int) =\n        member x.Id = id\n\n    let sref (value : 'a) =\n        FutureList.modifyState' (fun (s : WorkflowState) ->\n            let id = s.currentId\n            let newState = { s with refValues = Map.add id (value :> obj) s.refValues; currentId = s.currentId + 1}\n            newState, StateRef<'a>(id)\n        )\n\n    let read (r : StateRef<'a>) =\n        flist {\n            let! s = FutureList.getState\n            yield Map.find r.Id s.refValues |> unbox<'a>\n        }\n\n    let write (r : StateRef<'a>) (value : 'a) =\n        FutureList.modifyState (fun (s : WorkflowState) ->\n            { s with refValues = Map.add r.Id (value :> obj) s.refValues }\n        )\n\n    let modify (f : 'a -> 'a) (r : StateRef<'a>) =\n        FutureList.modifyState' (fun (s : WorkflowState) ->\n            let v = s.refValues |> Map.find r.Id |> unbox<'a> |> f\n            { s with refValues = Map.add r.Id (v :> obj) s.refValues }, ()\n        )\n\n    let modify' (f : 'a -> 'a) (r : StateRef<'a>) =\n        FutureList.modifyState' (fun (s : WorkflowState) ->\n            let v = s.refValues |> Map.find r.Id |> unbox<'a> |> f\n            { s with refValues = Map.add r.Id (v :> obj) s.refValues }, v\n        )\n\n    let resetState =\n        FutureList.putState WorkflowState.Empty\n\n    type WorkflowBuilder() =\n        \n        member x.For(s : WorkflowList<'a>, f : 'a -> StateWorkflow<'i, 'f>) =\n            { list = s |> FutureList.collect (fun v -> (f v).list) }\n\n        member x.For(s : IMod<'a>, f : 'a -> StateWorkflow<'i, 'f>) =\n            x.For(s |> FutureList.ofMod, f)\n\n        member x.For(s : IObservable<'a>, f : 'a -> StateWorkflow<'i, 'f>) =\n            x.For(s |> FutureList.ofObservable, f)\n\n        member x.Bind(m : WorkflowList<'a>, f : 'a -> StateWorkflow<'i, 'f>) =\n            { list = flist.Bind(m, fun v -> f(v).list) }\n\n\n        member x.Bind(m : StateRef<'a>, f : 'a -> StateWorkflow<'i, 'f>) =\n            { list = flist.Bind(read m, fun v -> f(v).list) }\n\n\n        member x.Return(u : unit) =\n            { list = flist.Return u }\n\n        member x.Zero() =\n            { list = flist.Zero() }\n\n        member x.Yield v =\n            { list = FutureList.single (Update v) }\n\n        member x.YieldFrom (f : WorkflowList<'i>) =\n            { list = f |> FutureList.map Update }\n\n        member x.YieldFrom (f : StateRef<'i>) =\n            { list = read f |> FutureList.map Update }\n\n\n        member x.Return v =\n            { list = FutureList.single (Final v) }\n\n        member x.ReturnFrom (f : WorkflowList<'f>) =\n            { list = f |> FutureList.map Final }\n\n        member x.ReturnFrom (f : StateRef<'i>) =\n            { list = read f |> FutureList.map Final }\n\n\n        member x.Combine(l : StateWorkflow<'i, 'f>, r : unit -> StateWorkflow<'i, 'f>) =\n            { list = flist.Combine(l.list, fun () -> r().list) }\n\n        member x.Delay(f : unit -> StateWorkflow<'i, 'f>) = f\n\n        member x.Run(f : unit -> StateWorkflow<'i, 'f>) = \n            { obs = f().list |> FutureList.toObservable { refValues = Map.empty; currentId = 0 } }\n\n        member x.While(guard : unit -> #IMod<bool>, body : unit -> StateWorkflow<'i, 'f>) =\n            { list = flist.While(guard, fun () -> body().list) }\n\n        member x.While(guard : unit -> bool, body : unit -> StateWorkflow<'i, 'f>) =\n            { list = flist.While(guard, fun () -> body().list) }\n\n\n\n    let inline (!=) (r : StateRef<'a>) (value : 'a) = write r value\n    let inline (!&) (r : StateRef<'a>) = read r\n\n    let workflow = WorkflowBuilder()\n\n\nmodule Test =\n    \n    let (<==) (m : ModRef<'a>) (value : 'a) =\n        transact (fun () -> m.Emit value)\n\n    let run() =\n        let active = Mod.init false\n        let positions = Mod.init 0\n\n\n        let test =\n            workflow {\n                    do! resetState\n                    let! r = sref []\n\n                    while active do\n                        for p in positions do\n                            do! r |> modify (fun l -> p::l)\n                            yield! r\n\n                    let! current = r\n                    return current |> List.rev |> List.toArray\n\n            }\n\n        test |> Workflow.latestUpdate [] |> Mod.unsafeRegisterCallbackKeepDisposable (fun v ->\n            printfn \"{ latest = %A }\" v\n        ) |> ignore\n\n        test |> Workflow.allFinal |> ASet.unsafeRegisterCallbackKeepDisposable (fun v ->\n            printfn \"{ finals = %A }\" v\n        ) |> ignore\n\n\n\n        active <== true\n        positions <== 1\n        positions <== 2\n        positions <== 3\n        positions <== 3\n        active <== false\n        positions <== 6\n        positions <== 7\n\n        active <== true\n        positions <== 5\n        positions <== 6\n        positions <== 7\n        positions <== 7\n        active <== false\n\n\n\n\n\n"
  },
  {
    "path": "src/Demo/Sketch/Lazy.fsx",
    "content": "﻿#I @\"..\\..\\..\\bin\\Release\"\n\n#r \"Aardvark.Base.dll\"\n#r \"Aardvark.Base.Essentials.dll\"\n#r \"Aardvark.Base.TypeProviders.dll\"\n#r \"Aardvark.Base.FSharp.dll\"\n#r \"Aardvark.Base.Incremental.dll\"\n\nopen System\nopen System.Threading\nopen System.Linq\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\n\n\n\ntype Time = DateTime\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule Time =\n    let now() : Time = DateTime.Now\n\n    let max (a : Time) (b : Time) : Time =\n        max a b\n\n    let min (a : Time) (b : Time) : Time =\n        min a b\n\n    let maxValue : Time = DateTime.MaxValue\n    let minValue : Time = DateTime.MinValue\n\ntype History<'a> = { values : list<Time * 'a>; finished : bool }\n\n[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]\nmodule History =\n    let rec private intersperse (l : list<Time * 'a>) (r : list<Time * 'a>) =\n        match l, r with\n            | [], r -> r\n            | l, [] -> l\n            | (tl,vl)::rl, (tr,vr)::rr ->\n                if tl < tr then (tl,vl)::intersperse rl r\n                else (tr,vr)::intersperse l rr\n\n    type private EmptyImpl<'a>() =\n        static let empty : History<'a> = { values = []; finished = false }\n        static member Empty = empty\n\n    let empty<'a> = EmptyImpl<'a>.Empty\n\n    let isEmpty (h : History<'a>) =\n        not h.finished && List.isEmpty h.values\n\n    let par (l : History<'a>) (r : History<'a>) =\n        { values = intersperse l.values r.values; finished = l.finished && r.finished }\n\n    let seq (l : History<'a>) (r : History<'a>) =\n        if l.finished then l\n        else { values = intersperse l.values r.values; finished = r.finished }\n\n    let concatPar (l : seq<History<'a>>) =\n        l |> Seq.fold par empty\n\n    let concatSeq (l : seq<History<'a>>) =\n        l |> Seq.fold seq empty\n\n    let map (f : 'a -> 'b) (h : History<'a>) =\n        { values = List.map (fun (t,v) -> t, f v) h.values; finished = h.finished }      \n\n\n[<AllowNullLiteral>]\ntype IEventReader<'a> =\n    inherit IAdaptiveObject\n    inherit IDisposable\n    abstract member SubscribeOnEvaluate : (History<'a> -> unit) -> IDisposable\n    abstract member GetHistory : IAdaptiveObject -> History<'a>\n    abstract member IsFinished : bool\n\ntype evt<'a> =\n    abstract member GetReader : unit -> IEventReader<'a>\n\n\nmodule EventReaders =\n    \n    let private wrap (scope : Ag.Scope) (f : 'a -> 'b) =\n        fun v -> Ag.useScope scope (fun () -> f v)\n\n    [<AbstractClass>]\n    type AbstractReader<'a>() =\n        inherit AdaptiveObject()\n\n        let lockObj = obj()\n        let mutable subscriptions : HashSet<History<'a> -> unit> = null\n\n        let addSubscription (cb : History<'a> -> unit) =\n            lock lockObj (fun () ->\n                if isNull subscriptions then\n                    subscriptions <- HashSet()\n\n                subscriptions.Add cb |> ignore\n            )\n\n        let removeSubscription (cb : History<'a> -> unit) =\n            lock lockObj (fun () ->\n                if not (isNull subscriptions) then\n                    subscriptions.Remove cb |> ignore\n                    if subscriptions.Count = 0 then \n                        subscriptions <- null\n            )\n\n\n        abstract member ComputeHistory : unit -> History<'a>\n        abstract member Release : unit -> unit\n        abstract member IsFinished : bool\n\n        member x.SubscribeOnEvaluate(cb : History<'a> -> unit) =\n            addSubscription cb\n            { new IDisposable with member x.Dispose() = removeSubscription cb }\n\n        member x.GetHistory(caller : IAdaptiveObject) =\n            x.EvaluateIfNeeded caller History.empty (fun () ->\n                let h = x.ComputeHistory()\n\n                if not (History.isEmpty h || isNull subscriptions) then\n                    let s = lock lockObj (fun () -> subscriptions.ToArray())\n                    for cb in s do cb h\n\n                h\n            )\n\n        member x.Dispose() = \n            subscriptions <- null\n            x.Release()\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n        interface IEventReader<'a> with\n            member x.GetHistory caller = x.GetHistory caller\n            member x.SubscribeOnEvaluate cb = x.SubscribeOnEvaluate cb\n            member x.IsFinished = x.IsFinished\n\n    type MapReader<'a, 'b>(scope : Ag.Scope, input : IEventReader<'a>, f : 'a -> 'b) =\n        inherit AbstractReader<'b>()\n        let f = wrap scope f\n\n        override x.IsFinished =\n            input.IsFinished\n\n        override x.Release() =\n            input.Dispose()\n\n        override x.ComputeHistory() =\n            input.GetHistory x |> History.map f\n\n        override x.Inputs =\n            Seq.singleton (input :> IAdaptiveObject)\n\n    type CollectReader<'a, 'b>(scope : Ag.Scope, input : IEventReader<'a>, f : 'a -> IEventReader<'b>) =\n        inherit AbstractReader<'b>()\n        let f = wrap scope f\n\n        let mutable outerHistory = History.empty\n        let mutable currentInnerTime = Time.minValue\n        let mutable currentInner : Option<IEventReader<'b>> = None\n\n        member private x.stepOuterNoEvaluate(pullOuter : bool) =\n            match outerHistory.values with\n                | (ot,ov)::rest ->\n\n                    outerHistory <- { outerHistory with values = rest }\n                    let inner = f ov\n                    currentInnerTime <- ot\n                    currentInner <- Some inner\n\n                    true\n\n                | [] -> \n                    if pullOuter then\n                        let o = input.GetHistory x\n                        outerHistory <- History.seq outerHistory o\n                        x.stepOuterNoEvaluate false\n                    else\n                        false\n\n        member private x.stepOuter() =\n            match outerHistory.values with\n                | (ot,ov)::rest ->\n\n                    outerHistory <- { outerHistory with values = rest }\n                    let inner = f ov\n                    currentInnerTime <- ot\n                    currentInner <- Some inner\n\n                    let ih = \n                        let h = inner.GetHistory x\n                        { h with values = h.values |> List.map (fun (t,v) -> (Time.max t ot), v) }\n\n                    if ih.finished then\n                        currentInner <- None\n\n                        let (next,f) = x.stepOuter()\n                        ih.values @ next, f\n                    else\n                        ih.values, false\n\n\n                | [] -> \n                    [], input.IsFinished\n\n        override x.InputChanged(o : IAdaptiveObject) =\n            match o with\n                | :? IEventReader<'b> as o when Some o = currentInner ->\n                    if o.IsFinished then\n                        let changed = x.stepOuterNoEvaluate(true)\n                        ()\n\n\n                | _ -> ()\n\n        override x.IsFinished =\n            (match currentInner with | Some i -> i.IsFinished | _ -> true) &&\n            input.IsFinished &&\n            List.isEmpty outerHistory.values\n\n        override x.Inputs =\n            seq {\n                yield input :> IAdaptiveObject\n                match currentInner with\n                    | Some i -> yield i :> IAdaptiveObject\n                    | _ -> ()\n            }\n\n        override x.Release() =\n            input.Dispose()\n\n        override x.ComputeHistory() =\n            let o = input.GetHistory x\n            outerHistory <- History.seq outerHistory o\n\n            match currentInner with\n                | Some inner ->\n                    let h = \n                        let h = inner.GetHistory x\n                        { h with values = h.values |> List.map (fun (t,v) -> (Time.max t currentInnerTime), v) }\n\n                    if h.finished then\n                        let (values, finished) = x.stepOuter()\n                        { values = h.values @ values; finished = finished }\n                    else\n                        h\n                | None ->\n                    let (values, finished) = x.stepOuter()\n                    { values = values; finished = finished }\n                    \n    type ParallelReader<'a, 'b>(scope : Ag.Scope, input : IReader<'a>, f : 'a -> IEventReader<'b>) as this =\n        inherit AbstractReader<'b>()\n        \n        let cache = Cache(scope, f)\n        let dirtySet = MutableVolatileDirtySet(fun (r : IEventReader<'b>) -> r.GetHistory this)\n\n        override x.IsFinished =\n            false\n\n        override x.Inputs =\n            seq {\n                yield input :> IAdaptiveObject\n                for r in cache.Values do\n                    yield r :> IAdaptiveObject\n            }\n\n        override x.Release() =\n            input.Dispose()    \n            cache.Clear(fun r -> r.RemoveOutput x)     \n            dirtySet.Clear()\n\n        override x.InputChanged(o : IAdaptiveObject) =\n            match o with\n                | :? IEventReader<'b> as r -> dirtySet.Push r\n                | _ -> ()\n\n        override x.ComputeHistory() =\n            let outer = input.GetDelta x\n\n            let outerHistories =\n                [ for o in outer do\n                    match o with\n                        | Add v ->\n                            let r = cache.Invoke v\n\n                            let res = r.GetHistory x\n                            dirtySet.Add r\n\n                            yield res\n\n                        | Rem v ->\n                            let r = cache.Revoke v\n\n                            dirtySet.Remove r\n\n                            r.Dispose()\n\n                            ()\n                ]\n            \n\n            let inner = dirtySet.Evaluate()\n\n            let history = outerHistories @ inner |> History.concatPar\n            { history with finished = false }\n\n    type ModReader<'a>(input : IMod<'a>) as this =\n        inherit AbstractReader<'a>()\n\n        let historyValues = List<Time * 'a> [Time.now(), input.GetValue this]\n\n        override x.IsFinished =\n            false\n\n        override x.Inputs =\n            Seq.singleton (input :> IAdaptiveObject)\n\n        override x.Mark() =\n            let v = input.GetValue x\n            historyValues.Add(Time.now(), v)\n\n            true\n\n        override x.Release() =\n            input.RemoveOutput x\n            historyValues.Clear()\n\n        override x.ComputeHistory() =\n            let l = historyValues |> Seq.toList\n            historyValues.Clear()\n            { values = l; finished = false }\n\n    type ConstantReader<'a>(values : list<Time * 'a>) =\n        inherit AbstractReader<'a>()\n        let mutable values = values\n\n        override x.IsFinished =\n            true\n\n        override x.Release() = values <- []\n\n        override x.ComputeHistory() =\n            let v = values\n            values <- []\n            { values = v; finished = true }\n\n    type EmitReader<'a>(remove : EmitReader<'a> -> unit) =\n        inherit AbstractReader<'a>()\n\n\n        let values = List<Time * 'a>()\n        let mutable finished = false\n\n        member x.Emit(v : seq<Time * 'a>) =\n            values.AddRange v\n            x.MarkOutdated()\n\n        member x.Finish() =\n            if not finished then\n                finished <- true\n                x.MarkOutdated()\n\n        override x.IsFinished =\n            finished\n\n        override x.Release() =\n            values.Clear()\n            finished <- true\n            remove x\n\n        override x.ComputeHistory() =\n            let l = values |> Seq.toList\n            values.Clear()\n            { values = l; finished = finished }\n\n    type CopyReader<'a>(input : IEventReader<'a>, remove : CopyReader<'a> -> unit) =\n        inherit AbstractReader<'a>()\n\n        let mutable buffer = History.empty\n        let s = input.SubscribeOnEvaluate (fun h -> buffer <- History.seq buffer h)\n\n        override x.IsFinished =\n            input.IsFinished\n\n        override x.Inputs = Seq.singleton (input :> IAdaptiveObject)\n\n        override x.ComputeHistory() =\n            input.GetHistory x |> ignore\n\n            let h = buffer\n            buffer <- History.empty\n            h\n\n        override x.Release() =\n            s.Dispose()\n            buffer <- History.empty\n            remove x\n\n    type WhileReader<'a>(guard : IMod<bool>, body : IEventReader<'a>) =\n        inherit AbstractReader<'a>()\n\n        let mutable guard = new ModReader<_>(guard) :> IEventReader<_>\n        let mutable inner : IEventReader<'a> = null\n        let mutable startTime = None\n        let mutable endTime = None\n\n\n        override x.IsFinished = Option.isSome endTime\n\n        override x.ComputeHistory() =\n            if not (isNull guard) then\n                let guardHistory = guard.GetHistory x\n\n                for (t,v) in guardHistory.values do\n                    if v && Option.isNone startTime then\n                        inner <- body\n                        startTime <- Some t\n                    elif not v && Option.isSome startTime then\n                        guard.Outputs.Remove x |> ignore\n                        guard.Dispose()\n                        guard <- null\n                        endTime <- Some t\n\n            if isNull inner then\n                History.empty\n            else\n                match startTime, endTime with\n                    | Some st, Some et ->\n                        let all = inner.GetHistory x \n                        inner.Outputs.Remove x |> ignore\n                        inner.Dispose()\n                        { values = List.filter (fun (t,_) -> t >= st && t <= et) all.values; finished = true}\n                    | Some st, None ->\n                        let all = inner.GetHistory x \n                        { all with values = List.filter (fun (t,_) -> t >= st) all.values }\n                    | _ -> \n                        History.empty\n\n        override x.Release() =\n            if not (isNull inner) then inner.Dispose()\n            if not (isNull guard) then guard.Dispose()\n\n\n\n\n\nmodule Evt =\n    \n    type Source<'a>() =\n        let readers = HashSet<EventReaders.EmitReader<'a>>()\n\n        let remove (r : EventReaders.EmitReader<'a>) =\n            lock readers (fun () ->\n                readers.Remove r |> ignore\n            )\n\n        let newReader () =\n            lock readers (fun () ->\n                let r = new EventReaders.EmitReader<'a>(remove)\n                readers.Add r |> ignore\n\n                r :> IEventReader<_>\n            )\n        \n        let pushValues (values : seq<Time * 'a>) =\n            lock readers (fun () ->\n                for r in readers do r.Emit values\n            )\n\n        let finish() =\n            lock readers (fun () ->\n                for r in readers do r.Finish()\n                readers.Clear()\n            )\n\n        member x.GetReader() =\n            newReader()\n\n        member x.Emit(values : seq<'a>) =\n            let t = Time.now()\n            pushValues (Seq.map (fun v -> t,v) values)\n\n        member x.Emit(value : 'a) =\n            let t = Time.now()\n            pushValues [t,value]\n\n        member x.Finish() =\n            transact (fun () -> finish())\n\n        interface evt<'a> with\n            member x.GetReader() = x.GetReader()\n\n    type Evt<'a>(newReader : unit -> IEventReader<'a>) =\n        \n        let mutable inputReader : Option<IEventReader<'a>> = Some (newReader())\n        let readers = HashSet<EventReaders.CopyReader<'a>>()\n\n        let remove (r : EventReaders.CopyReader<'a>) =\n            lock readers (fun () ->\n                readers.Remove r |> ignore\n                if readers.Count = 0 then\n                    match inputReader with\n                        | Some i -> \n                            i.Dispose() \n                            inputReader <- None\n                        | _ -> ()\n\n            )\n\n        let create() =\n            lock readers (fun () ->\n                let i = \n                    match inputReader with\n                        | Some i -> i\n                        | None ->\n                            let i = newReader()\n                            inputReader <- Some i\n                            i\n\n                let cp = new EventReaders.CopyReader<'a>(i, remove)\n                readers.Add cp |> ignore\n                cp :> IEventReader<_>\n            )\n\n\n        member x.GetReader() =\n            create()\n\n        interface evt<'a> with\n            member x.GetReader() = x.GetReader()\n\n    type Constant<'a>(values : list<'a>) =\n        let values = List.map (fun v -> Time.minValue, v) values\n\n        member x.GetReader() =\n            new EventReaders.ConstantReader<_>(values) :> IEventReader<_>\n\n        interface evt<'a> with\n            member x.GetReader() = x.GetReader()\n\n\n    let inline private evt (f : Ag.Scope -> #IEventReader<'a>) =\n        let scope = Ag.getContext()\n        Evt(fun () -> f scope :> IEventReader<_>) :> evt<_>\n\n\n    type private Empty<'a>() =\n        static let instance : evt<'a> = Constant [] :> evt<_>\n        static member Instance = instance\n\n    let empty<'a> = Empty<'a>.Instance\n    \n    let single(v : 'a) : evt<'a> = Constant [v] :> evt<_>\n   \n    let ofList(v : list<'a>) : evt<'a> = Constant v :> evt<_>\n    let inline ofSeq(v : seq<'a>) = v |> Seq.toList |> ofList\n    let inline ofArray(v : 'a[]) = v |> Array.toList |> ofList\n    \n\n    let source() : Source<'a> =\n        Source()\n\n    let map (f : 'a -> 'b) (e : evt<'a>) =\n        evt (fun scope -> new EventReaders.MapReader<_,_>(scope, e.GetReader(), f))\n\n    let forall (f : 'a -> evt<'b>) (e : aset<'a>) =\n        evt (fun scope -> new EventReaders.ParallelReader<_,_>(scope, e.GetReader(), fun v -> (f v).GetReader()))\n\n    let ofMod (e : IMod<'a>) =\n        evt (fun scope -> new EventReaders.ModReader<_>(e))\n\n    let collect (f : 'a -> evt<'b>) (e : evt<'a>) =\n        evt (fun scope -> new EventReaders.CollectReader<_,_>(scope, e.GetReader(), fun v -> (f v).GetReader()))\n\n    let choose (f : 'a -> Option<'b>) (e : evt<'a>) =\n        e |> collect (fun v ->\n            match f v with\n                | Some v -> single v\n                | None -> empty\n        )\n\n    let takeWhile (guard : IMod<bool>) (body : evt<'a>) =\n        evt (fun scope -> new EventReaders.WhileReader<_>(guard, body.GetReader()))\n \nmodule Test =\n    \n\n    let run() =\n        let s0 = Evt.source()\n        let s1 = Evt.source()\n        let s2 = Mod.init 10\n\n        let both = Evt.ofList [s0 :> evt<_>; s1 :> evt<_>; Evt.ofMod s2]\n\n        let res = both |> Evt.collect id\n\n        let sepp = res |> Evt.collect (fun v -> Evt.ofList [v; -v])\n\n        let r = sepp.GetReader()\n        r.GetHistory null |> printfn \"history: %A\"\n\n\n        transact(fun () ->\n            s0.Emit 1\n            s1.Emit 221323 // missed since no one listening (s0 not finished yet)\n            s0.Emit 10\n        )\n        r.GetHistory null |> printfn \"history: %A\"\n\n        transact(fun () ->\n            s1.Emit 1000 // missed since no one listening (s0 not finished yet)\n            s0.Finish()\n            s1.Emit 2 // should be seen (s0 now finished)\n        )\n        r.GetHistory null |> printfn \"history: %A\"\n\n\n        transact(fun () ->\n            s1.Finish()\n        )\n        r.GetHistory null |> printfn \"history: %A\"\n\n\n        transact(fun () ->\n            Mod.change s2 100\n        )\n        r.GetHistory null |> printfn \"history: %A\"\n\n\n\n"
  },
  {
    "path": "src/Demo/Sketch/Observable.fsx",
    "content": "﻿#I @\"..\\..\\..\\bin\\Release\"\n#I @\"..\\..\\..\\Packages\\Rx-Core\\lib\\net45\"\n#I @\"..\\..\\..\\Packages\\Rx-Interfaces\\lib\\net45\"\n#I @\"..\\..\\..\\Packages\\Rx-Linq\\lib\\net45\"\n#r \"Aardvark.Base.dll\"\n#r \"Aardvark.Base.Essentials.dll\"\n#r \"Aardvark.Base.TypeProviders.dll\"\n#r \"Aardvark.Base.FSharp.dll\"\n#r \"Aardvark.Base.Incremental.dll\"\n#r \"System.Reactive.Core.dll\"\n#r \"System.Reactive.Interfaces.dll\"\n#r \"System.Reactive.Linq.dll\"\n\nopen System\nopen System.Threading\nopen System.Linq\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen System.Reactive\nopen System.Reactive.Linq\n\n\nmodule Obs =\n    let private noDisposable = { new IDisposable with member x.Dispose() = () }\n\n    type private ConstantObservable<'a>(values : list<'a>) =\n        interface IObservable<'a> with\n            member x.Subscribe(obs : IObserver<'a>) =\n                for v in values do obs.OnNext v\n                obs.OnCompleted()\n                noDisposable\n\n\n    type private ObservableMod<'a>(input : IMod<'a>, emitFirstValue : bool) =\n        inherit Mod.AbstractMod<'a>()\n\n        let mutable subscriptionCount = 0\n        let subscriptions = HashSet<IObserver<'a>>()\n\n        interface IObservable<'a> with\n            member x.Subscribe(obs : IObserver<'a>) =\n                Interlocked.Increment &subscriptionCount |> ignore\n\n                // force the evaluation (in order to see subsequent markings)\n                let v = x.GetValue null\n                if emitFirstValue then\n                    obs.OnNext v\n\n                lock subscriptions (fun () -> subscriptions.Add obs |> ignore )\n                { new IDisposable with \n                    member x.Dispose() =\n                        Interlocked.Decrement &subscriptionCount |> ignore\n                        lock subscriptions (fun () -> subscriptions.Remove obs |> ignore)\n                }\n\n        override x.Mark() =\n            if subscriptionCount > 0 then\n                let v = x.GetValue null\n                let all = lock subscriptions (fun s -> subscriptions.ToArray())\n                for s in all do s.OnNext v\n\n            true\n\n        override x.Compute() =\n            input.GetValue x\n\n    type private ObservableNextValue<'a>(input : IMod<'a>) =\n        inherit Mod.AbstractMod<'a>()\n\n\n        let mutable subscriptionCount = 0\n        let subscriptions = HashSet<IObserver<'a>>()\n\n        interface IObservable<'a> with\n            member x.Subscribe(obs : IObserver<'a>) =\n                Interlocked.Increment &subscriptionCount |> ignore\n\n                // force the evaluation (in order to see subsequent markings)\n                let v = x.GetValue null\n\n                lock subscriptions (fun () -> subscriptions.Add obs |> ignore )\n                { new IDisposable with \n                    member x.Dispose() =\n                        Interlocked.Decrement &subscriptionCount |> ignore\n                        lock subscriptions (fun () -> subscriptions.Remove obs |> ignore)\n                }\n\n        override x.Mark() =\n            if subscriptionCount > 0 then\n                let v = x.GetValue null\n                let all = \n                    lock subscriptions (fun s -> \n                        let arr = subscriptions.ToArray()\n                        subscriptions.Clear()\n                        arr\n                    )\n\n                for s in all do \n                    s.OnNext v\n                    s.OnCompleted()\n\n            false\n\n        override x.Compute() =\n            input.GetValue x\n\n    type private ObserverMod<'a>(value : 'a, obs : IObservable<'a>) as this =\n        inherit Mod.AbstractMod<'a>()\n\n        let mutable value = value\n        let subscription = obs.Subscribe (fun v -> value <- v; this.MarkOutdated())\n\n\n        member x.Dispose() =\n            subscription.Dispose()\n\n        override x.Finalize() =\n            try subscription.Dispose()\n            with _ -> ()\n\n        override x.Compute() =\n            value\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n    type private OptionalObserverMod<'a>(obs : IObservable<'a>) as this =\n        inherit Mod.AbstractMod<Option<'a>>()\n\n        let mutable value = None\n        let subscription = obs.Subscribe (fun v -> value <- Some v; this.MarkOutdated())\n\n\n        member x.Dispose() =\n            subscription.Dispose()\n\n        override x.Finalize() =\n            try subscription.Dispose()\n            with _ -> ()\n\n        override x.Compute() =\n            value\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n    type private ObservableReader<'a>(obs : IObservable<Delta<'a>>, container : ref<Option<ObservableReader<'a>>>) as this =\n        inherit ASetReaders.AbstractReader<'a>()\n\n        let store = List<Delta<'a>>()\n\n        let push (d : Delta<'a>) =\n            lock store (fun () -> store.Add d)\n            let outdated = lock this (fun () -> this.OutOfDate)\n            if not outdated then transact (fun () -> this.MarkOutdated())\n\n        let sub = obs.Subscribe(fun d -> push d)\n\n        let consume() =\n            lock store (fun () ->\n                let l = store |> Seq.toList\n                store.Clear()\n                l\n            )\n\n        override x.ComputeDelta() =\n            consume()\n\n        override x.Release() =\n            container := None\n            store.Clear()\n            sub.Dispose()\n\n    type private EmptyImpl<'a>() =\n        static let instance = Observable.Empty<'a>()\n        static member Instance = instance\n\n    // constants\n    [<GeneralizableValue>]\n    let empty<'a> : IObservable<'a> = EmptyImpl<'a>.Instance\n    let ofList (l : list<'a>) = ConstantObservable l :> IObservable<'a>\n    let inline ofSeq (s : seq<'a>) = s |> Seq.toList |> ofList\n    let inline ofArray (s : 'a[]) = s |> Array.toList |> ofList\n    let inline single (v : 'a) = ofList [v] \n\n\n    let subject() = new Subjects.Subject<'a>()\n\n\n    // from adaptive to observable\n    let nextOf (m : IMod<'a>) : IObservable<'a> =\n        ObservableNextValue(m) :> _\n\n    let futureOf (m : IMod<'a>) : IObservable<'a> =\n        ObservableMod(m, false) :> _\n\n    let valuesOf (m : IMod<'a>) : IObservable<'a> =\n        ObservableMod(m, true) :> _\n\n    // from observable to adaptive\n    let latest (initial : 'a) (o : IObservable<'a>) : IMod<'a> =\n        new ObserverMod<_>(initial, o) :> _\n\n    let optionalLatest (o : IObservable<'a>) : IMod<Option<'a>> =\n        new OptionalObserverMod<_>(o) :> _    \n\n    let toASet (deltas : IObservable<Delta<'a>>) : aset<'a> =\n        let original = ref Unchecked.defaultof<_>\n        original := new ObservableReader<'a>(deltas, original) |> Some\n\n        ASet.AdaptiveSet(fun () -> \n            match !original with\n                | Some r -> \n                    r :> IReader<_>\n                | None ->\n                    let r = new ObservableReader<'a>(deltas, original)\n                    original := Some r\n                    r :> IReader<_>\n        ) :> aset<_>\n\n    let all (values : IObservable<'a>) : aset<'a> =\n        values.Select Add |> toASet\n\n\n    // higher order combinators\n    let map (f : 'a -> 'b) (o : IObservable<'a>) =\n        o.Select f\n\n    let collect (f : 'a -> IObservable<'b>) (o : IObservable<'a>) =\n        o.SelectMany f\n\n    let choose (f : 'a -> Option<'b>) (o : IObservable<'a>) =\n        Observable.choose f o\n\n    let filter (f : 'a -> bool) (o : IObservable<'a>) =\n        o.Where f\n\n    let foldMap (project : 's -> 'x) (f : 's -> 'a -> 's) (seed : 's) (o : IObservable<'a>) =\n        Observable.Create (fun (obs : IObserver<'x>) ->\n            let seed = ref seed\n            o.Subscribe {\n                new IObserver<'a> with\n                    member x.OnNext v = \n                        let s = f !seed v\n                        seed := s\n                        obs.OnNext (project s)\n                    member x.OnCompleted() = obs.OnCompleted()\n                    member x.OnError e = obs.OnError e\n            }\n\n        )\n\n    let inline fold (f : 's -> 'a -> 's) (seed : 's) (o : IObservable<'a>) =\n        foldMap id f seed o\n\n    let inline sum (o : IObservable<'a>) = fold (+) LanguagePrimitives.GenericZero o\n\n    let inline average (o : IObservable<'a>) : IObservable<'a> = \n        foldMap (uncurry LanguagePrimitives.DivideByInt) (fun (l, c) r -> (l + r, c+1)) (LanguagePrimitives.GenericZero, 0) o\n        \n    let inline sumBy (f : 'a -> 'b) (o : IObservable<'a>) : IObservable<'b> =\n        fold (fun l r -> l + f r) LanguagePrimitives.GenericZero o\n        \n    let inline averageBy (f : 'a -> 'b) (o : IObservable<'a>) : IObservable<'b> =\n        foldMap (uncurry LanguagePrimitives.DivideByInt) (fun (l, c) r -> (l + f r, c+1)) (LanguagePrimitives.GenericZero, 0) o\n        \n\n    let skip (n : int) (o : IObservable<'a>) : IObservable<'a> = \n        Observable.Create (fun (obs : IObserver<'a>) ->\n            let skip = ref n\n            o.Subscribe {\n                new IObserver<'a> with\n                    member x.OnNext(v) =\n                        let c = Interlocked.Decrement &skip.contents\n                        if c < 0 then obs.OnNext v\n                    member x.OnError e =\n                        obs.OnError e\n                    member x.OnCompleted() =\n                        obs.OnCompleted()\n            }\n\n        )\n        \n    let take (n : int) (o : IObservable<'a>) : IObservable<'a> =\n        Observable.Create (fun (obs : IObserver<'a>) ->\n            let take = ref n\n            let sub = ref noDisposable\n            sub := \n                o.Subscribe {\n                    new IObserver<'a> with\n                        member x.OnNext(v) =\n                            let t = Interlocked.Decrement &take.contents\n                            if t > 0 then \n                                obs.OnNext v\n                            else \n                                obs.OnCompleted()\n                                sub.Value.Dispose()\n                                sub := noDisposable\n                        member x.OnError e =\n                            obs.OnError e\n                        member x.OnCompleted() =\n                            obs.OnCompleted()\n                }\n\n            { new IDisposable with member x.Dispose() = sub.Value.Dispose() }\n\n        )\n\n\n    let takeWhile (m : IMod<bool>) (o : unit -> IObservable<'a>) =\n        Observable.Create (fun (obs : IObserver<'a>) ->\n\n            let m = valuesOf m\n\n            let active = ref false\n            let modSub = ref noDisposable\n            let innerSub = ref noDisposable\n\n\n            let stop(completed : bool) =\n                innerSub.Value.Dispose()\n                modSub.Value.Dispose()\n                innerSub := noDisposable\n                modSub := noDisposable\n                if completed then obs.OnCompleted()\n\n            let start() =\n                let inner = o()\n                innerSub :=\n                    inner.Subscribe { \n                        new IObserver<'a> with\n                            member x.OnNext(v) = obs.OnNext(v)\n                            member x.OnCompleted() = stop true\n                            member x.OnError(e) = \n                                obs.OnError(e)\n                                stop false\n                    }\n\n\n            modSub :=\n                m.Subscribe (fun v ->\n                    if not !active && v then\n                        start()\n                    elif !active && not v then\n                        stop true\n                        \n\n                    active := v\n                )\n\n            { new IDisposable with member x.Dispose() = modSub.Value.Dispose(); innerSub.Value.Dispose() }\n        )\n\n\n    // ground combinators\n    let append (l : IObservable<'a>) (r : IObservable<'a>) =\n        l.Concat(r)\n\n    let concat (obs : seq<IObservable<'a>>) =\n        Observable.Concat(obs)\n\n    let merge (obs : seq<IObservable<'a>>) =\n        Observable.Merge(obs)\n\n    let intersperse (l : IObservable<'a>) (r : IObservable<'b>) : IObservable<Either<'a, 'b>> =\n        Observable.Create(fun (obs : IObserver<Either<'a, 'b>>) ->\n            let mutable pending = 2\n            let comlete() =\n                let p = Interlocked.Decrement &pending\n                if p = 0 then obs.OnCompleted()\n\n\n            let left = \n                l.Subscribe {\n                    new IObserver<'a> with\n                        member x.OnNext v = obs.OnNext (Left v)\n                        member x.OnError e = obs.OnError e\n                        member x.OnCompleted() = comlete()\n                }\n\n            let right = \n                r.Subscribe {\n                    new IObserver<'b> with\n                        member x.OnNext v = obs.OnNext (Right v)\n                        member x.OnError e = obs.OnError e\n                        member x.OnCompleted() = comlete()\n                }\n\n            { new IDisposable with member x.Dispose() = left.Dispose(); right.Dispose() }\n        )\n\n    let intersperse3 (o0 : IObservable<'a>) (o1 : IObservable<'b>) (o2 : IObservable<'c>) : IObservable<Choice<'a, 'b, 'c>> =\n        Observable.Create(fun (obs : IObserver<Choice<'a, 'b, 'c>>) ->\n            let mutable pending = 3\n            let comlete() =\n                let p = Interlocked.Decrement &pending\n                if p = 0 then obs.OnCompleted()\n\n\n            let s0 = \n                o0.Subscribe {\n                    new IObserver<'a> with\n                        member x.OnNext v = obs.OnNext (Choice1Of3 v)\n                        member x.OnError e = obs.OnError e\n                        member x.OnCompleted() = comlete()\n                }\n\n            let s1 = \n                o1.Subscribe {\n                    new IObserver<'b> with\n                        member x.OnNext v = obs.OnNext (Choice2Of3 v)\n                        member x.OnError e = obs.OnError e\n                        member x.OnCompleted() = comlete()\n                }\n\n            let s2 = \n                o2.Subscribe {\n                    new IObserver<'c> with\n                        member x.OnNext v = obs.OnNext (Choice3Of3 v)\n                        member x.OnError e = obs.OnError e\n                        member x.OnCompleted() = comlete()\n                }\n\n            { new IDisposable with member x.Dispose() = s0.Dispose(); s1.Dispose(); s2.Dispose() }\n        )\n\n[<AutoOpen>]\nmodule ``Observable builder`` =\n    \n    type ObservableBuilder() =\n        member x.For(m : IObservable<'a>, f : 'a -> IObservable<'b>) =\n            m |> Obs.collect f\n\n        member x.For(m : IMod<'a>, f : 'a -> IObservable<'b>) =\n            m |> Obs.valuesOf |> Obs.collect f\n\n\n        member x.While(guard : unit -> bool, body : unit -> IObservable<'a>) =\n            if guard() then\n                Obs.append (body()) (Observable.Defer (fun () -> x.While(guard, body)))\n            else\n                Obs.empty\n\n        member x.While(guard : unit -> #IMod<bool>, body : unit -> IObservable<'a>) =\n            Obs.takeWhile (guard() :> IMod<_>) body\n\n        member x.Yield(v : 'a) =\n            Obs.single v\n\n        member x.YieldFrom (l : seq<'a>) =\n            Obs.ofSeq l\n\n        member x.YieldFrom(o : IObservable<'a>) = o\n\n        member x.Delay(f : unit -> IObservable<'a>) = f\n\n        member x.Combine(l : IObservable<'a>, r : unit -> IObservable<'a>) =\n            Obs.append l (Observable.Defer r)\n\n        member x.Run(f : unit -> IObservable<'a>) = f()\n       \n        member x.Zero() = Obs.empty\n\n    let obs = ObservableBuilder()\n\n\nmodule Test =\n    let run() =\n        \n        let active = Mod.init false\n        let pos = Obs.subject()\n\n\n        let res =\n            obs {\n                while true do\n                    let l = List()\n                    while active do\n                        yield Left []\n\n                        for p in pos do\n                            l.Add p\n                            yield l |> Seq.toList |> Left\n\n                    \n                    yield l |> Seq.toList |> Right\n            }\n\n        res.Add(printfn \"%A\")\n\n\n        printfn \"push(1)\"; pos.OnNext(1)\n        printfn \"push(2)\"; pos.OnNext(2)\n        printfn \"active = true\"; transact(fun () -> Mod.change active true)\n        printfn \"push(0)\"; pos.OnNext(0)\n        printfn \"push(1)\"; pos.OnNext(1)\n        printfn \"push(2)\"; pos.OnNext(2)\n        printfn \"active = false\"; transact(fun () -> Mod.change active false)\n        printfn \"push(3)\"; pos.OnNext(3)\n        printfn \"push(4)\"; pos.OnNext(4)\n        printfn \"active = true\"; transact(fun () -> Mod.change active true)\n\n\n"
  },
  {
    "path": "src/Demo/Sketch/Program.fs",
    "content": "﻿(*\nChallenge:\n\na) create a binary tree which stores single elements in leafs.\nb) provide a traversal function which extracts leaf nodes from the tree (fold).\nc) leaf node extraction should be incremental\nd) provide functional snapshots\ne) undelimited undo/redo while maintainging efficient updates.\n*)\n\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen Aardvark.Base.Incremental.Tests\n\nlet test a = if a then printfn \"OK\" else failwith \"assertion failed.\" a \n\n// Let us start with a binary tree\ntype PTree<'a> = PNode of left : PTree<'a> * right : PTree<'a>\n               | PLeaf of 'a\n\n// (a) done.\n\n// lets define a traversal which extracts leaf nodes from the tree\nlet rec leafNodesP t =\n    seq {\n        match t with \n         | PNode(l,r) -> \n            yield! leafNodesP l\n            yield! leafNodesP r\n         | PLeaf v ->\n            yield v\n    }\n\nlet testTree1 = PNode( PNode(PLeaf 1, PLeaf 2), PNode (PLeaf 3, PLeaf 4))\ntest ((testTree1 |> leafNodesP |> Seq.toList) = [1;2;3;4])\n                         \n// (b) done.\n\n// Let us convert the tree to an adaptive one\ntype Tree<'a> = Node of left : IMod<Tree<'a>> * right : IMod<Tree<'a>> \n              | Leaf of IMod<'a>\n\n// Let us define the adaptive version of leafNodes\nlet rec leafNodes t =\n    aset {\n        match t with \n         | Node(l,r) -> \n            let! (l,r) = l,r // children are mod, read them adaptively\n            yield! leafNodes l // then recurse and use yield! \n                               // since the rec call returns an aset\n            yield! leafNodes r\n         | Leaf v ->\n            yield v\n    } \n\n// there are many mods around. let us make convinience functions\n// for constructing mod trees from values more easily\nlet leaf v = Leaf (Mod.init v)\nlet node l r = Node (Mod.init l, Mod.init r)\n\nlet l1 = node (leaf 1) (leaf 2) |> Mod.init\nlet l2Original = node (leaf 3) (leaf 4) // just store the l2 for later usage\nlet l2 = l2Original |> Mod.init\nlet testTree2 = Node (l1, l2)\n\n// since we have asets, we have unordered outpus, so we need a utility for comparing\n// our results with expected results while respecting set semantics.\nlet setToSet aset = aset |> ASet.toList |> List.map Mod.force |> Set.ofList \nlet setEqual xs aset = (setToSet aset) = (Set.ofList xs)\n\nlet resultingLeafNodes = testTree2 |> leafNodes\n\ntest (resultingLeafNodes|> setEqual [1;2;3;4])\n\n// let verify that mod works as expected. Let us modify the tree by replacing the right subtrree with a leaf 10\ntransact (fun () -> Mod.change l2 (leaf 10)) \n\ntest (resultingLeafNodes |> setEqual [1;2;10])\n\n// (c) done. (incremental fold for adaptive binary trees)\n\n// Okay, we have incremental updates to trees. But what if we want functional snapshots?\n// let us adaptively convert our mod tree to a persistent one!\n\nlet rec buildPeristent t =\n    adaptive {\n        match t with \n         | Node(l,r) -> \n            let! l = l\n            let! r = r\n            let! lTree = buildPeristent l\n            let! rTree = buildPeristent r\n            return PNode(lTree, rTree)\n         | Leaf v ->\n            let! v = v\n            return PLeaf v\n    } \n\nlet testTree2InPersistent = testTree2 |> buildPeristent\ntest ((Mod.force testTree2InPersistent) = PNode(PNode(PLeaf(1),PLeaf(2)), PLeaf 10))\n\n// let us modify the mod tree and see how the persistent representation looks like\ntransact (fun () -> Mod.change l2 l2Original)\n\ntest ((Mod.force testTree2InPersistent) = PNode(PNode(PLeaf 1, PLeaf 2), PNode(PLeaf 3, PLeaf 4)))\n\n// (d) done. we have functional snapshots (we will see this is not sufficient for (e))\n\n// by the way, our modification also updated our leaf list\ntest (testTree2 |> leafNodes |> setEqual [1;2;3;4])\n\n// (just for presentation purpose i use a separate module which allows me to reuse variable names for top level bindings)\nmodule UndoRedo =\n    // lets go on and move on to undo-redo\n    // in order to implement undo redo generically, but not globally we introduce\n    // a scope (e.g. camera moves shall not be tracked globally).\n    // the undo redo scope acts as factory for IModRef values but tracks snapshots for them.\n    // please note that the undo-redo s<stem here was just a 40 line sketch by gh. But as you will see,\n    // this solution is so beautiful, concise, efficient and awesome.\n\n    let scope = UndoRedoScope()\n    // let us now create a tree just as before but we use special mod ctors \n\n    // let us now create the tree just like before but by using the undo redo scope\n    let leaf v = Leaf (scope.initMod v)\n    let node l r = Node (scope.initMod l, scope.initMod r)\n\n    let l1 = node (leaf 1) (leaf 2) |> scope.initMod\n    let l2Original = node (leaf 3) (leaf 4) \n    let l2 = l2Original |> scope.initMod\n    let testTree2 = Node (l1, l2)\n\n    let adaptiveLeafNodes = testTree2 |> leafNodes\n\n    // again, let us synthesize the leafs\n    test (adaptiveLeafNodes |> setEqual [1;2;3;4])\n\n    // Lets say, this tree should be saved as snapshot - project1\n    let project1 = scope.Snapshot()\n\n    // let us do some modification\n    transact (fun () -> Mod.change l2 (leaf 10))\n\n    test (adaptiveLeafNodes |> setEqual [1;2;10])\n\n    let project2 = scope.Snapshot()\n\n    // let us do some modification\n    transact (fun () -> Mod.change l1 (leaf 11))\n\n    test (adaptiveLeafNodes |> setEqual [11;10])\n\n    let project3 = scope.Snapshot()\n\n    // let us go back to project 1\n    transact (fun () -> project1.Restore())\n    test (adaptiveLeafNodes |> setEqual [1;2;3;4])\n\n    // again to project 2\n    transact (fun () -> project2.Restore())\n    test (adaptiveLeafNodes |> setEqual [1;2;10])\n\n    transact (fun () -> project3.Restore())\n    printfn \"%A\" (adaptiveLeafNodes |> ASet.toList |> List.map Mod.force)\n    test (adaptiveLeafNodes |> setEqual [11;10])\n\n    // as you can see, adaptively synthesized leaf nodes automatically update,\n    // functional snapshots automatically update and we have time travel.\n    // this completes challange (d).\n\n    \nopen System.Diagnostics\n// let us create a function for measuring performance\nlet timed f = \n    let sw = Stopwatch()\n    sw.Start()\n    let r = f ()\n    sw.Stop()\n    printfn \"function took: %f seconds\" sw.Elapsed.TotalSeconds\n    r,sw.Elapsed.TotalSeconds\n\nmodule Persistency =\n\n    // Let us now add persistency for adaptive undoable tree's.\n    // First, let us create a new subclass of serializationBean,\n    // register interceptors via dependency injection etc.\n    // :P\n\n    // No, let us define picklers for pickling and unpickling non-adaptive \n    // persistent binary trees\n    open Nessos.FsPickler\n    open Nessos.FsPickler.Combinators\n    open Nessos.FsPickler.Json\n    open System.Diagnostics\n    open System.IO\n    open System.Runtime.Serialization.Formatters.Binary\n\n    let p pElement =\n        Pickler.fix (fun self ->\n            Pickler.sum (fun t node leaf ->\n                match t with\n                | PNode (l,r) -> node (l, r)\n                | PLeaf  v    -> leaf v )\n            ^+ Pickler.case PNode (Pickler.pair self self) \n            ^. Pickler.case PLeaf pElement\n        )\n    let pPTree<'a> = p Pickler.auto<'a>\n\n    let bin = FsPickler.CreateBinarySerializer()\n    let json = FsPickler.CreateJsonSerializer()\n    let serialized = json.PickleToString(testTree1,pPTree)\n    printfn \"%s\" serialized\n\n    // let us test performance of this simple serialization function\n    let mutable root = PLeaf 1\n    let depth = 2\n    for i in 0 .. depth do\n        root <- PNode(root,root)\n\n\n    printfn \"pickling\"\n    let bytes,time = timed (fun () -> bin.Pickle(root,pPTree))\n    printfn \"pickling 2\"\n    let bytes3,time3 = timed (fun () -> bin.Pickle(root,pPTree))\n    printfn \"running .net\"\n\n    let bytes2, time2 = \n        timed (fun () ->\n            let formatter = new BinaryFormatter();\n            let stream = new MemoryStream()\n            formatter.Serialize(stream, obj);\n            stream.Close();\n            stream.GetBuffer()\n    )\n\n    root <- PLeaf 2\n    printfn \"serialization performed: %d bytes total, %d nodes, in %f seconds (%f mb/s)\" bytes.Length (pow 2 depth) time (float (float bytes.Length / float (1024 * 1024)) / float time)\n    printfn \"serialization performed: %d bytes total, %d nodes, in %f seconds (%f mb/s)\" bytes2.Length (pow 2 depth) time (float (float bytes2.Length / float (1024 * 1024)) / float time2)\n    printfn \"serialization performed: %d bytes total, %d nodes, in %f seconds (%f mb/s)\" bytes3.Length (pow 2 depth) time (float (float bytes2.Length / float (1024 * 1024)) / float time3)\n\n\nmodule Performance =\n    open System.Collections.Generic\n\n    let leaf v = Leaf (Mod.init v)\n    let node l r = Node (Mod.init l, Mod.init r)\n\n    let rec buildBigTree current = // 2^current inner nodes - 1, 2^current leafs\n        if current = 0 then \n            leaf 1, []\n        else\n            let l,lrefs = buildBigTree (current - 1) \n            let r,rrefs = buildBigTree (current - 1) \n            let lm = Mod.init l\n            let rm = Mod.init r\n            Node(lm, rm), lm::rm::(lrefs @ rrefs)\n\n    let rec extractLeafs t =    \n        seq {\n            match t with\n             | Node(l,r) ->\n                yield! extractLeafs (Mod.force l) \n                yield! extractLeafs (Mod.force r)\n             | Leaf v -> yield Mod.force v\n        }\n\n    let test () =\n\n\n        let (buildBigTree0,refs),elapsedBuild = timed (fun () -> buildBigTree 15)\n\n        let r,s = timed (fun () -> buildBigTree0 |> extractLeafs |> Seq.toArray)\n        printfn \"rebuild took: %As\" s\n    \n\n        let r = buildBigTree0 |> leafNodes\n\n        let reader = r |> ASet.toMod \n        //reader |> Mod.force |> ignore\n        //Aardvark.Base.Incremental.Validation.IAdaptiveObjectValidationExtensions.Dump(reader,10000) |> File.writeAllText @\"C:\\Aardwork\\dump.txt\"\n        //Aardvark.Base.Incremental.Validation.IAdaptiveObjectValidationExtensions.DumpDgml(reader,1000,@\"C:\\Aardwork\\Graph.dgml\") |> ignore\n\n        let list,elapsedFold = timed (fun () -> reader.GetValue() )\n        let l,elapsedPull = timed (fun () -> list |> Seq.toList |> List.map Mod.force)\n\n        let l,elapsedD = \n            timed (fun () -> \n                let x = HashSet(list |> Seq.toList)\n                let y = HashSet(list |> Seq.toList)\n                let a = x |> Seq.filter (fun s -> y.Contains s |> not) |> Seq.toList\n                let b = y |> Seq.filter (fun s -> x.Contains s |> not) |> Seq.toList\n                ())\n\n        printfn \"differnece took: %As\" elapsedD\n        printfn \"build took: %Ams, fold too: %As\" elapsedBuild elapsedFold \n        printfn \"force took: %As\" elapsedPull\n\n        let last = refs |> List.last \n        let _,reexElapsed = timed (fun () -> transact (fun () -> Mod.change last (leaf 10)); reader.GetValue() )\n        printfn \"reex: %As\" reexElapsed\n\n//build took: 0.0552271ms, fold too: 1.6827239s\n//force took: 0.0075516s\n//function took: 0.002544 seconds\n//reex: 0.002544s\n\nopen Aardvark.Base.Incremental\nopen System.Collections.Generic\n\nopen System.Runtime.InteropServices \ntype Dictionary<'a,'b> with\n    member x.TryRemove(k,[<Out>] r: byref<'b>) =\n        match x.TryGetValue k with\n         | (true,v) -> r <- v; true\n         | _ -> false\n\nmodule Delta =\n    let map f x =\n        match x with \n         | Add v -> Add <| f v\n         | Rem v -> Rem <| f v\n\nmodule IUList1 =\n\n    type IUList<'a> =\n        abstract member GetDelta : IAdaptiveObject -> list<Delta<'a>>\n\n    type UList<'a>(initial : seq<'a>) =\n        inherit AdaptiveObject()\n\n        let pending = HashSet<_>(initial |> Seq.map Add)\n    \n        member x.emit() =\n            if not x.OutOfDate then\n                match getCurrentTransaction() with\n                 | Some t ->  t.Enqueue x\n                 | None -> failwith \"not in transaction\"\n\n        member x.Add v =\n            pending.Add(Add v) |> ignore\n        \n            x.emit()\n        member x.Remove v =\n            pending.Add(Rem v) |> ignore\n            x.emit()\n\n        member x.GetDelta caller =\n            x.EvaluateIfNeeded x [] (fun () -> \n                let r = pending |> Seq.toList \n                pending.Clear()\n                r\n            )\n\n        interface IUList<'a> with\n            member x.GetDelta caller = x.GetDelta x\n\n    type Map<'a,'b>(s : IUList<'a>,f : 'a -> 'b) =\n        inherit AdaptiveObject()\n        member x.GetDelta caller =\n            x.EvaluateIfNeeded x [] (fun () -> \n                let invs = s.GetDelta x\n                invs |> List.map (Delta.map f)\n            )\n        interface IUList<'b> with\n            member x.GetDelta o = x.GetDelta o\n\n    type Collect<'a,'b when 'a : equality>(s : IUList<'a>, f : 'a -> IUList<'b>) =\n        inherit AdaptiveObject()\n        let removals = Dictionary<'a, list<Delta<'b>>>()\n        let activeOutputs = Dictionary<'a, IUList<'b>>()\n        member x.GetDelta caller = \n            let source = s.GetDelta caller\n            let ds = [ for op in source do \n                        match op with\n                            | Rem v -> \n                                activeOutputs.Remove v |> ignore\n                                match removals.TryGetValue v with\n                                    | (true,xs) -> yield! xs\n                                    | _ -> ()\n                            | Add fresh ->\n                                let newU = f fresh\n                                let boundOnFresh = newU.GetDelta x\n                                removals.Add(fresh, boundOnFresh)\n                                activeOutputs.Add(fresh, newU)\n                                yield! boundOnFresh\n                        ]\n            ds @ [ for (KeyValue(k,v)) in activeOutputs do yield! v.GetDelta x]\n        interface IUList<'b> with\n            member x.GetDelta o = x.GetDelta o\n        \n    type Observation<'a>(input : IUList<'a>) =\n        inherit AdaptiveObject()\n        let content = HashSet<_>()\n\n        member x.GetContent () =\n            x.EvaluateAlways x (fun () -> \n                for i in input.GetDelta x do\n                    match i with\n                     | Add v -> content.Add v |> ignore\n                     | Rem v -> content.Remove v |> ignore\n                content |> Seq.toList\n            )\n\n    type Bind<'a,'b>(m : IMod<'a>, f : 'a -> IUList<'b>) =\n        inherit AdaptiveObject()\n        let mutable lastA = Unchecked.defaultof<_>\n        let lastProduced = HashSet<Delta<'b>>()\n\n        member x.GetDelta caller =\n            x.EvaluateAlways x (fun () ->\n                let a = m.GetValue x\n                let r = f a\n                let outer = \n                    if Unchecked.equals r lastA then \n                        []\n                    else \n                        let er = lastProduced |> Seq.toList\n                        lastProduced.Clear()\n                        for p in r.GetDelta x do lastProduced.Add p |> ignore\n                        er\n                let inner = \n                    if Unchecked.equals Unchecked.defaultof<_> lastA then [] \n                    else \n                        let ne = lastA.GetDelta x\n                        for p in ne do lastProduced.Add p |> ignore\n                        ne\n                lastA <- r\n                inner @ outer\n            )\n\n        interface IUList<'b> with\n            member x.GetDelta caller = x.GetDelta caller  \n            \n    let collect f xs = Collect<_,_>(xs,f) :> IUList<_>\n    let map f xs = Map<_,_>(xs,f) :> IUList<_>\n    let observe xs = Observation<_>(xs) \n    let ulist xs = UList<_>(xs) :> IUList<_>\n    let bind m f = Bind<_,_>(m,f) :> IUList<_>\n\n    let test2 () =\n\n        let input = UList []\n\n        let a = UList []\n        let b = UList []\n        let mo = Mod.init 5\n        let ab = ulist [a :> IUList<_>;b :> _]\n        let ab = ab |> collect (fun a -> bind mo (fun v -> if v < 10 then a else input :> _))\n        let r = ab |> observe\n        //let r = observe col\n        printfn \"%A \" <| r.GetContent()\n\n        transact (fun () -> \n            a.Add 10 |> ignore\n        )\n    \n        printfn \"%A \" <| r.GetContent()\n\n        transact (fun () -> \n            Mod.change mo 15\n            a.Add 12 |> ignore\n        )\n    \n        printfn \"%A \" <| r.GetContent()\n\n\nmodule DirectWrite =\n\n    type WriteToSet<'v> =\n        abstract member Add : 'v -> (unit -> unit)\n\n    type Cause<'a> = Sink of WriteToSet<'a>\n                   | Cont of IList<'a>\n\n    and IUList<'a> =\n        abstract member Push : 'a -> (unit -> unit)\n\n    type OUList<'a when 'a : equality>(o : IUList<'a>) =\n        inherit AdaptiveObject()\n        let content = Dictionary<'a,unit->unit>()\n        let pending = Queue<'a>()\n        let removals = Queue<'a>()\n\n        member x.Add v =\n            pending.Enqueue v\n\n        member x.Rem v = \n            removals.Enqueue v\n        \n        member x.Update() =\n            while pending.Count > 0 do\n                let p = pending.Dequeue()\n                content.Add(p, o.Push p)\n            while removals.Count > 0 do\n                let r = removals.Dequeue()\n                match content.TryRemove r with\n                 | (true,v) -> v()\n                 | _ -> failwith \"\"\n\n    type Map<'a,'b>(output : IUList<'b>, f : 'a -> 'b) =\n        let pending = List<'a>()\n        interface IUList<'a> with\n            member x.Push a =\n                output.Push(f a)\n\n    type ID<'a when 'a: equality>(output : IUList<'a>) =\n        let ds = Dictionary<'a,unit->unit>()\n        interface IUList<'a> with\n            member x.Push a =\n                ds.Add(a, output.Push a)\n                fun () ->\n                    match ds.TryGetValue a with\n                     | (true,v) -> v()\n                     | _ -> failwith\"\"\n        member x.Dispose() =\n            for (KeyValue(k,v)) in ds do\n                v()\n\n\n    type Collect<'a,'b when 'a:equality and 'b:equality>(output : IUList<'b>, f : 'a -> IUList<'b>) =\n        let d = Dictionary<'a,ID<'b>>()\n        interface IUList<'a> with\n            member x.Push a =\n                let t = f a\n                let fuse = ID<'b>(output)\n                d.Add(a,fuse)\n                fun () ->\n                    match d.TryRemove a with\n                     | (true,v) -> v.Dispose()\n                     | _ -> failwith \"\"\n        \n    let culist o = OUList<_>(o) \n    let map f o = Map<_,_>(o,f) :> IUList<_>\n    let collect f o = Collect<_,_>(o,f) :> IUList<_>\n                    \n    let test2() =\n        OUList\n\n                    \n\n[<EntryPoint>]\nlet main args =\n\n    Performance.test(); \n    0"
  },
  {
    "path": "src/Demo/Sketch/Rampa.fsx",
    "content": "﻿#I @\"..\\..\\..\\bin\\Release\"\n#I @\"..\\..\\..\\Packages\\Rx-Core\\lib\\net45\"\n#I @\"..\\..\\..\\Packages\\Rx-Interfaces\\lib\\net45\"\n#I @\"..\\..\\..\\Packages\\Rx-Linq\\lib\\net45\"\n#r \"Aardvark.Base.dll\"\n#r \"Aardvark.Base.Essentials.dll\"\n#r \"Aardvark.Base.TypeProviders.dll\"\n#r \"Aardvark.Base.FSharp.dll\"\n#r \"Aardvark.Base.Incremental.dll\"\n#r \"System.Reactive.Core.dll\"\n#r \"System.Reactive.Interfaces.dll\"\n#r \"System.Reactive.Linq.dll\"\n\nopen System\nopen System.Threading\nopen System.Linq\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen System.Reactive\nopen System.Reactive.Linq\n\n\n\ntype IBuffer =\n    inherit IAdaptiveObject\n    inherit IDisposable\n    abstract member IsEmpty : bool\n\ntype IBuffer<'a> =\n    inherit IBuffer\n    abstract member Dequeue : IAdaptiveObject -> Option<'a>\n\n\ntype Token =\n    | Time\n    | Reactive of (unit -> IBuffer)\n\ntype Context(caller : IAdaptiveObject) =\n    static let startTicks = DateTime.Now.Ticks\n    let buffers = Dict<Token, IBuffer>()\n    let mutable containsTime = false\n    let mutable timePulled = false\n    let mutable lastTime = DateTime.MinValue\n    let mutable timeIndex = 0\n    member x.Caller = caller\n\n    member x.Restart() =\n        timePulled <- false\n\n    member x.TimePulled =\n        timePulled\n\n    member x.IsEmpty =\n        lock buffers (fun () -> buffers.Values |> Seq.forall (fun b -> b.IsEmpty))\n\n\n    member x.Listen(t : Token) =\n        match t with\n            | Time -> \n                containsTime <- true\n            | Reactive create ->\n                lock buffers (fun () -> buffers.[t] <- create())\n\n    member x.Unlisten(t : Token) =\n        match t with\n            | Time ->\n                containsTime <- false\n            | Reactive _ ->\n                match lock buffers (fun () -> buffers.TryRemove t) with\n                    | (true, b) -> b.Dispose()\n                    | _ -> ()\n\n    member x.DequeValue<'a>(t : Token) : Option<'a> =\n        match t with\n            | Time ->\n                let now = DateTime.Now\n\n                let ticks = \n                    if now = lastTime then\n                        let ti = Interlocked.Increment(&timeIndex)\n                        float (now.Ticks - startTicks) + (float ti * (1.0 / 4000.0))\n                    else\n                        timeIndex <- 0\n                        lastTime <- now\n                        float (now.Ticks - startTicks)\n\n                timePulled <- true\n                (float ticks / float TimeSpan.TicksPerSecond) |> unbox |> Some\n            | _ ->\n                match lock buffers (fun () -> buffers.TryGetValue t) with\n                    | (true, (:? IBuffer<'a> as b)) ->\n                        b.Dequeue caller\n                    | _ ->\n                        None\n\n\n\ntype Event<'a> =\n    | Event of 'a\n    | NoEvent\n\ntype sf<'a, 'b> =\n    abstract member run : Context -> 'a -> 'b * sf<'a, 'b>\n    abstract member dependencies : list<Token>\n\nmodule SF =\n\n    exception private EndExn\n\n    type private ModBuffer<'a>(m : IMod<'a>) as this =\n        inherit AdaptiveObject()\n\n        let mutable live = 1\n        let q = Queue<'a> [m.GetValue this]\n        \n\n        override x.Mark() =\n            if live = 1 then\n                let v = m.GetValue x\n                q.Enqueue v\n\n            true\n\n        member x.Dispose() =\n            let wasLive = Interlocked.Exchange(&live,0)\n            if wasLive = 1 then\n                lock x (fun () ->\n                    m.RemoveOutput x\n                    q.Clear()\n                )\n\n\n        member x.IsEmpty = lock x (fun () -> q.Count = 0)\n\n        member x.Dequeue(caller : IAdaptiveObject) =\n            x.EvaluateAlways caller (fun () ->\n                if live = 1 then \n                    if q.Count = 0 then None\n                    else q.Dequeue() |> Some\n                else \n                    None\n            )\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n        interface IBuffer with\n            member x.IsEmpty = x.IsEmpty\n\n        interface IBuffer<'a> with\n            member x.Dequeue caller = x.Dequeue caller\n\n    type private ObservableBuffer<'a>(o : IObservable<'a>) as this =\n        inherit AdaptiveObject()\n\n        let mutable live = 1\n        let mutable markingPending = 0\n        let q = Queue<'a>()\n\n\n\n        let push (v : 'a) =\n            lock this (fun () ->\n                q.Enqueue v\n            )\n\n            let alreadyMarking = Interlocked.Exchange(&markingPending, 1)\n            if alreadyMarking = 0 then\n                transact (fun () -> this.MarkOutdated())\n\n        let sub = o.Subscribe push\n\n        member x.Dispose() =\n            let wasLive = Interlocked.Exchange(&live,0)\n            if wasLive = 1 then\n                sub.Dispose()\n                lock x (fun () -> q.Clear())\n\n\n        member x.IsEmpty = lock q (fun () -> q.Count = 0)\n\n        member x.Dequeue(caller : IAdaptiveObject) =\n            x.EvaluateAlways caller (fun () ->\n                if live = 1 then \n                    if q.Count = 0 then None\n                    else q.Dequeue() |> Some\n                else \n                    None\n            )\n\n        interface IDisposable with\n            member x.Dispose() = x.Dispose()\n\n        interface IBuffer with\n            member x.IsEmpty = x.IsEmpty\n\n        interface IBuffer<'a> with\n            member x.Dequeue caller = x.Dequeue caller\n\n\n\n    type private ModSignal<'a, 'b>(e : IMod<'b>) =\n        let token = Reactive (fun () -> new ModBuffer<'b>(e) :> IBuffer)\n\n        member x.run (ctx : Context) (i : 'a) =\n            match ctx.DequeValue<'b> token with\n                | Some b -> Event b, x :> sf<_,_>\n                | None -> NoEvent, x :> sf<_,_>\n\n        interface sf<'a, Event<'b>> with\n            member x.run ctx i = x.run ctx i\n            member x.dependencies = [token]\n               \n    type private EventSignal<'a, 'b>(e : IObservable<'b>) =\n        let token = Reactive (fun () -> new ObservableBuffer<'b>(e) :> IBuffer)     \n\n        member x.run (ctx : Context) (i : 'a) =\n            match ctx.DequeValue<'b> token with\n                | Some b -> Event b, x :> sf<_,_>\n                | None -> NoEvent, x :> sf<_,_>\n\n        interface sf<'a, Event<'b>> with\n            member x.run ctx i = x.run ctx i\n            member x.dependencies = [token]\n         \n    type private SimpleSignal<'a, 'b>(f : 'a -> 'b) =\n        interface sf<'a, 'b> with\n            member x.run _ i = f i, x :> sf<_,_>\n            member x.dependencies = []\n      \n    type private ConstantSignal<'a, 'b>(value : 'b) =\n        interface sf<'a, 'b> with\n            member x.run _ _ = value, x :> sf<_,_>\n            member x.dependencies = []\n\n    type private CustomSignal<'a, 'b>(f : sf<'a,'b> -> Context -> 'a -> 'b * sf<'a, 'b>, deps : list<Token>) as this =\n        let f = f this\n        interface sf<'a, 'b> with\n            member x.run ctx v = f ctx v\n            member x.dependencies = deps\n     \n    type private EndSignal<'a, 'b> private() =\n        static let instance = EndSignal<'a,'b>() :> sf<'a, 'b>\n        \n        static member Instance = instance\n\n\n        interface sf<'a, 'b> with\n            member x.run _ _ = raise EndExn\n            member x.dependencies = []   \n\n    type private TimeSignal<'a> private() =\n        static let instance = TimeSignal<'a>() :> sf<'a, float>\n        let token = Time\n\n        static member Instance = instance\n\n        interface sf<'a, float> with\n            member x.run ctx _ = ctx.DequeValue<float>(token).Value, instance\n            member x.dependencies = [Time]\n\n   \n\n\n\n    let time<'a> = TimeSignal<'a>.Instance\n\n    let stop<'a, 'b> = EndSignal<'a, 'b>.Instance\n\n    let ofMod (m : IMod<'a>) : sf<'x, Event<'a>> =\n        ModSignal(m) :> _\n\n\n\n    let ofObservable (m : IObservable<'a>) : sf<'x, Event<'a>> =\n        EventSignal(m) :> _\n\n    let arr (f : 'a -> 'b) : sf<'a, 'b> =\n        SimpleSignal(f) :> _\n\n    let constant (v : 'b) : sf<'a, 'b> =\n        ConstantSignal(v) :> _\n\n    let custom (dependencies : list<Token>) (f : sf<'a, 'b> -> Context -> 'a -> 'b * sf<'a, 'b>) : sf<'a, 'b> =\n        CustomSignal(f, dependencies) :> _\n\n    let rec mapOut (f : 'b -> 'c) (sf : sf<'a, 'b>) =\n        custom sf.dependencies (fun self ctx a ->\n            let (b, cont) = sf.run ctx a\n            (f b), mapOut f cont\n        )\n\n    let rec mapIn (f : 'a -> 'b) (sf : sf<'b, 'c>) =\n        custom sf.dependencies (fun self ctx a ->\n            let (b, cont) = sf.run ctx (f a)\n            b, mapIn f cont\n        )\n\n    let rec switch (guard : sf<'a, Event<'b>>) (onEvent : sf<'b, 'c>) (noEvent : sf<'a, 'c>) : sf<'a, 'c> =\n        let deps = List.concat [guard.dependencies; onEvent.dependencies; noEvent.dependencies]\n        custom deps (fun _ ctx a ->\n            let (gv, gc) = guard.run ctx a\n            match gv with\n                | Event b ->\n                    let (ev, ec) = onEvent.run ctx b\n                    ev, switch gc ec noEvent\n\n                | NoEvent ->\n                    let (nv, nc) = noEvent.run ctx a\n                    nv, switch gc onEvent nc\n        )\n\n    let rec switch2 (guard : sf<'x, Event<'b>>) (onEvent : 'b -> sf<'x, 'c>) (noEvent : sf<'x, 'c>) : sf<'x, 'c> =\n        let deps = List.concat [guard.dependencies; onEvent.dependencies; noEvent.dependencies]\n        custom deps (fun _ ctx a ->\n            let (gv, gc) = guard.run ctx a\n            match gv with\n                | Event b ->\n                    let (ev, ec) = onEvent(b).run ctx a\n                    ev, switch2 gc (fun _ -> ec) noEvent\n\n                | NoEvent ->\n                    let (nv, nc) = noEvent.run ctx a\n                    nv, switch2 gc onEvent nc\n        )\n\n\n    let rec fold (seed : 's) (acc : 's -> 'a -> 's) (m : sf<'x, 'a>) =\n        custom m.dependencies (fun _ ctx x ->\n            let (mv,mc) = m.run ctx x\n            let s = acc seed mv\n            s, fold s acc mc\n        )\n\n    let rec zip (l : sf<'a, 'b>) (r : sf<'a, 'c>) =\n        custom (l.dependencies @ r.dependencies) (fun self ctx a ->\n            let (lv, lc) = l.run ctx a\n            let (rv, rc) = r.run ctx a\n\n            (lv,rv), zip lc rc\n\n        )\n\n    let inline integrate (f : sf<'a, 'b>) =\n        f |> fold LanguagePrimitives.GenericZero (+)\n\n    let inline differentiate (y : sf<'a, 'y>) (x : sf<'a, 'x>) =\n        zip y x \n            |> fold None (fun last (y,x) ->\n                match last with\n                    | Some (_, oy,ox) ->\n                        let v = (y - oy) / (x - ox)\n                        Some(v, y, x)\n                    | None ->\n                        Some(LanguagePrimitives.GenericZero, y, x)\n               ) \n            |> mapOut (fun o ->\n                match o with\n                    | Some(v,_,_) -> v\n                    | _ -> LanguagePrimitives.GenericZero\n               )\n\n\n    let switchTrue (guard : sf<'a, bool>) (ifTrue : sf<'a, 'b>) (ifFalse : sf<'a, 'b>) =\n        let rec run (currentlyTrue : Option<bool>) (guard : sf<'a, bool>) (ifTrue : sf<'a, 'b>) (ifFalse : sf<'a, 'b>) =\n            let deps = \n                match currentlyTrue with\n                    | Some true -> guard.dependencies @ ifTrue.dependencies\n                    | Some false -> guard.dependencies @ ifFalse.dependencies\n                    | None -> List.concat [guard.dependencies; ifTrue.dependencies; ifFalse.dependencies]\n\n            custom deps (fun _ ctx a ->\n                let (gv, gc) = guard.run ctx a\n                if gv then\n                    let (ev, ec) = ifTrue.run ctx a\n                    ev, run (Some true) gc ec ifFalse\n\n                else\n                    let (nv, nc) = ifFalse.run ctx a\n                    nv, run (Some false) gc ifTrue nc\n            )\n \n        run None guard ifTrue ifFalse\n\n    let bind (f : 'a -> sf<'x, 'y>) (m : IMod<'a>) : sf<'x, 'y> =\n        let rec run (oldA : Option<'a * sf<'x, 'y>>) =\n            let deps =\n                match oldA with \n                    | Some(_,old) -> old.dependencies\n                    | None -> []\n\n            custom deps (fun self ctx x ->\n                let a = m.GetValue ctx.Caller\n                match oldA with\n                    | Some(oa,old) when System.Object.Equals(oa, a) ->\n                        let (v,cont) = old.run ctx x\n                        v, run (Some(a, cont))\n                    | _ ->\n                        let inner = f a\n                        let (y, cont) = inner.run ctx x\n\n                        y, run (Some(a, cont))\n\n            )\n\n\n        run None \n\n    let latest (m : IMod<'a>) : sf<'x, 'a> =\n        custom [] (fun self ctx _ ->\n            let latestValue = m.GetValue ctx.Caller\n\n            latestValue, self\n        )\n\n    let withCancellation (ct : CancellationToken) (inner : sf<'a, 'b>) : sf<'a, 'b> =\n        let m = Mod.init false\n        let reg = ct.Register(fun () -> transact (fun () -> Mod.change m true))\n\n        switchTrue (latest m)\n            (stop |> mapIn (fun _ -> reg.Dispose()))\n            inner\n\n    //loop :: a (b, d) (c, d) -> a b c\n\n    //loop : sf<'b * 'd, 'c * 'd> -> sf<'b, 'c>\n    // sf<a * c, b * c> -> sf<a, b>\n\n\n    type private Reactimator<'a, 'b>(sf : sf<'a, 'b>, input : 'a, output : 'b -> unit) as this =\n        inherit AdaptiveObject()\n\n        let ctx = Context(this)\n        let evt = new ManualResetEventSlim(true)\n        let mutable initial = true\n        let mutable oldValue = None\n        let mutable current = sf\n        let mutable currentDeps =\n            let res = sf.dependencies |> HashSet\n            for a in res do ctx.Listen a\n            res\n\n        member x.StepEvent = evt\n\n        member x.Step() =\n            x.EvaluateAlways null (fun () ->\n                \n                ctx.Restart()\n\n                let rec run (top : bool) (latest : Option<'b>) =\n                    if not top && ctx.IsEmpty then\n                        if not ctx.TimePulled then\n                            match oldValue, latest with\n                                | Some o, Some l  when System.Object.Equals(o,l) ->\n                                    evt.Reset()\n                                | None, None ->\n                                    evt.Reset()\n                                | _ -> ()\n\n                        oldValue <- latest\n                        true\n                    else\n                        let res = \n                            try current.run ctx input |> Some\n                            with EndExn -> None\n                    \n                        match res with\n                            | Some(v, newSf) ->\n                                output v\n\n                        \n                                let newDeps = newSf.dependencies |> HashSet\n\n                                let added = newDeps |> Seq.filter (currentDeps.Contains >> not)\n                                let removed = currentDeps |> Seq.filter (newDeps.Contains >> not)\n\n                                for r in removed do ctx.Unlisten r\n                                for a in added do ctx.Listen a\n\n\n                                current <- newSf\n                                currentDeps <- newDeps\n                                run false (Some v)\n\n                            | None ->\n                                // todo: cleanup\n                                false\n\n                run true oldValue\n            )\n\n        override x.Mark() =\n            evt.Set()\n            true\n\n    let reactimate (output : 'b -> unit) (sf : sf<unit, 'b>) =\n        \n        let r = Reactimator(sf, (), output)\n        if r.Step() then\n\n            let rec run() =\n                async {\n                    do! Async.SwitchToThreadPool()\n\n                    let! worked = Async.AwaitWaitHandle r.StepEvent.WaitHandle\n\n                    if not worked then\n                        printfn \"reactimate failed\"\n                    else\n                        if r.Step() then\n                            return! run()\n                        else\n                            printfn \"finished\"\n\n                }\n\n            run()\n        else\n            async { return () }\n\n    let flatten (f : 'a -> sf<'x, 'y>) : sf<'a * 'x, 'y> =\n        let rec run (old : Option<sf<'x, 'y>>) =\n            let deps = \n                match old with\n                    | Some old -> old.dependencies\n                    | _ -> []\n            \n            custom deps (fun self ctx (a,x) ->\n                let(y,cont) = (f a).run ctx x\n                y, run (Some cont)\n            )\n\n        run None\n\n\n[<AutoOpen>]\nmodule Operators =\n\n    type SFBuilder() =\n        member x.Bind(m : IMod<'a>, f : 'a -> sf<'x, 'y>) =\n            m |> SF.bind f\n\n        member x.For(o : IMod<'a>, f : 'a -> sf<'x, 'x>) =\n            SF.switch2 (SF.ofMod o)\n                (SF.flatten f)\n                (SF.arr id)\n\n        member x.For(o : IObservable<'a>, f : 'a -> sf<'x, 'x>) =\n            SF.switch2 (SF.ofObservable o)\n                (SF.flatten f)\n                (SF.arr id)\n\n        member x.Return(f : 'a -> 'b) =\n            SF.arr f\n\n        member x.ReturnFrom(f : sf<'a, 'b>) =\n            f\n\n        member x.Yield(f : 'a -> 'b) =\n            SF.arr f\n\n        member x.Zero() = SF.arr id\n\n    let sf = SFBuilder()\n\n\n    let test (active : IMod<bool>) (clicks : IObservable<V2i>) =\n        sf {\n            let! a = active\n            if a then\n                for p in clicks do\n                    if p.X > 1000 then\n                        return! SF.stop\n                    else\n                        return fun (l : list<V2i>) ->\n                            p::l\n        }\n\n\n    let rec (>>>) (l : sf<'a, 'b>) (r : sf<'b, 'c>) : sf<'a, 'c> =\n        SF.custom (l.dependencies @ r.dependencies) (fun self ctx a ->\n            let (lv, lc) = l.run ctx a\n            let (rv, rc) = r.run ctx lv\n            rv, lc >>> rc\n        )\n\n    let (<<<) (r : sf<'b, 'c>) (l : sf<'a, 'b>) : sf<'a, 'c> =\n        l >>> r\n\n    let (||>) (l : sf<'a, 'b>) (r : 'b -> 'c) : sf<'a, 'c> =\n        l |> SF.mapOut r\n\n    let (<||) (r : 'b -> 'c) (l : sf<'a, 'b>) : sf<'a, 'c> =\n        l |> SF.mapOut r\n\n\n\n\nlet test () = \n    let step = Mod.init 0\n\n    // whenever we have a step use it otherwise step by 0\n    let delta = \n        SF.switch (SF.ofMod step) \n            (SF.arr (fun v -> [v]))\n            (SF.constant [])\n\n    // integrate all steps\n    let res = \n        delta \n            |> SF.fold [] (fun l e -> l @ e)\n            ||> List.rev\n            \n\n    let cts = new CancellationTokenSource()\n\n\n    // start the sf as task\n    res\n        |> SF.withCancellation cts.Token\n        |> SF.reactimate (printfn \"out: %A\") \n        |> Async.Start\n\n    \n\n\n    transact(fun () -> Mod.change step 10)\n\n    let mutable finish = false\n    while not finish do\n        let l = Console.ReadLine()\n\n        match Int32.TryParse l with\n            | (true, i) -> \n                transact(fun () -> Mod.change step i)\n            | _ -> \n                if l.StartsWith \"c\" then \n                    cts.Cancel()\n                elif l.StartsWith \"q\" then \n                    finish <- true\n                else ()\n\n    ()\n\nlet test2 () = \n    let active = Mod.init false\n    let noStep = Mod.init 0.0\n\n    let stepper = SF.constant 1.0 |> SF.integrate\n    let dt = SF.differentiate SF.time stepper\n\n//    let delta =\n//        SF.switchTrue (SF.latest active)\n//            (dt ||> fun v -> if v > 0.1 then 0.0 else v)\n//            (SF.constant 0.0)\n\n    let delta =\n        active |> SF.bind (fun v ->\n            if v then \n                dt ||> fun v -> if v > 0.1 then 0.0 else v\n            else \n                SF.constant 0.0\n        )\n\n    let result = SF.integrate delta\n\n\n    let cts = new CancellationTokenSource()\n\n\n    // start the sf as task\n    result \n        |> SF.withCancellation cts.Token\n        |> SF.reactimate (printfn \"out: %A\") \n        |> Async.Start\n\n\n    while true do\n        Console.ReadLine() |> ignore\n        transact(fun () -> Mod.change active (not active.Value))"
  },
  {
    "path": "src/Demo/Sketch/Sketch.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\n  <PropertyGroup>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <SchemaVersion>2.0</SchemaVersion>\n    <ProjectGuid>861e2024-8578-4380-a490-656d7e453f55</ProjectGuid>\n    <OutputType>Exe</OutputType>\n    <RootNamespace>Sketch</RootNamespace>\n    <AssemblyName>Sketch</AssemblyName>\n    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>\n    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>\n    <TargetFSharpCoreVersion>4.4.0.0</TargetFSharpCoreVersion>\n    <Name>Sketch</Name>\n\t<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <Tailcalls>false</Tailcalls>\n    <OutputPath>bin\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <WarningLevel>3</WarningLevel>\n    <PlatformTarget>AnyCPU</PlatformTarget>\n    <DocumentationFile>bin\\Debug\\Sketch.XML</DocumentationFile>\n    <Prefer32Bit>true</Prefer32Bit>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\n    <DebugType>pdbonly</DebugType>\n    <Optimize>true</Optimize>\n    <Tailcalls>true</Tailcalls>\n    <OutputPath>bin\\Release\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <WarningLevel>3</WarningLevel>\n    <PlatformTarget>AnyCPU</PlatformTarget>\n    <DocumentationFile>bin\\Release\\Sketch.XML</DocumentationFile>\n    <Prefer32Bit>true</Prefer32Bit>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"Aardvark.Base\">\n      <HintPath>..\\..\\..\\bin\\Release\\Aardvark.Base.dll</HintPath>\n    </Reference>\n    <Reference Include=\"Aardvark.Base.Essentials\">\n      <HintPath>..\\..\\..\\bin\\Release\\Aardvark.Base.Essentials.dll</HintPath>\n    </Reference>\n    <Reference Include=\"Aardvark.Base.FSharp\">\n      <HintPath>..\\..\\..\\bin\\Release\\Aardvark.Base.FSharp.dll</HintPath>\n    </Reference>\n    <Reference Include=\"Aardvark.Base.FSharp.Tests\">\n      <HintPath>..\\..\\..\\bin\\Release\\Aardvark.Base.FSharp.Tests.dll</HintPath>\n    </Reference>\n    <Reference Include=\"Aardvark.Base.Incremental\">\n      <HintPath>..\\..\\..\\bin\\Release\\Aardvark.Base.Incremental.dll</HintPath>\n    </Reference>\n    <Reference Include=\"Aardvark.Base.Incremental.Tests\">\n      <HintPath>..\\..\\..\\bin\\Release\\Aardvark.Base.Incremental.Tests.exe</HintPath>\n    </Reference>\n    <Reference Include=\"Aardvark.Base.Runtime\">\n      <HintPath>..\\..\\..\\bin\\Release\\Aardvark.Base.Runtime.dll</HintPath>\n    </Reference>\n    <Reference Include=\"mscorlib\" />\n    <Reference Include=\"FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n      <Private>True</Private>\n    </Reference>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.Core\" />\n    <Reference Include=\"System.Drawing\" />\n    <Reference Include=\"System.Numerics\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"Program.fs\" />\n    <None Include=\"App.config\" />\n  </ItemGroup>\n  <PropertyGroup>\n    <MinimumVisualStudioVersion Condition=\"'$(MinimumVisualStudioVersion)' == ''\">11</MinimumVisualStudioVersion>\n  </PropertyGroup>\n  <Choose>\n    <When Condition=\"'$(VisualStudioVersion)' == '11.0'\">\n      <PropertyGroup Condition=\"Exists('$(MSBuildExtensionsPath32)\\..\\Microsoft SDKs\\F#\\3.0\\Framework\\v4.0\\Microsoft.FSharp.Targets')\">\n        <FSharpTargetsPath>$(MSBuildExtensionsPath32)\\..\\Microsoft SDKs\\F#\\3.0\\Framework\\v4.0\\Microsoft.FSharp.Targets</FSharpTargetsPath>\n      </PropertyGroup>\n    </When>\n    <Otherwise>\n      <PropertyGroup Condition=\"Exists('$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\FSharp\\Microsoft.FSharp.Targets')\">\n        <FSharpTargetsPath>$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\FSharp\\Microsoft.FSharp.Targets</FSharpTargetsPath>\n      </PropertyGroup>\n    </Otherwise>\n  </Choose>\n  <Import Project=\"$(FSharpTargetsPath)\" />\n  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \n       Other similar extension points exist, see Microsoft.Common.targets.\n  <Target Name=\"BeforeBuild\">\n  </Target>\n  <Target Name=\"AfterBuild\">\n  </Target>\n  -->\n</Project>"
  },
  {
    "path": "src/Demo/Sketch/Sketch.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.23107.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{F2A71F9B-5D33-465A-A702-920D77279786}\") = \"Sketch\", \"Sketch.fsproj\", \"{861E2024-8578-4380-A490-656D7E453F55}\"\nEndProject\nGlobal\n\tGlobalSection(Performance) = preSolution\n\t\tHasPerformanceSessions = true\n\tEndGlobalSection\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{861E2024-8578-4380-A490-656D7E453F55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{861E2024-8578-4380-A490-656D7E453F55}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{861E2024-8578-4380-A490-656D7E453F55}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{861E2024-8578-4380-A490-656D7E453F55}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Demo/Sketch/UndoRedo.fsx",
    "content": "﻿#I @\"..\\..\\..\\bin\\Release\"\n#r \"Aardvark.Base.dll\"\n#r \"Aardvark.Base.Essentials.dll\"\n#r \"Aardvark.Base.TypeProviders.dll\"\n#r \"Aardvark.Base.FSharp.dll\"\n#r \"Aardvark.Base.Incremental.dll\"\n#r \"Aardvark.Base.Incremental.Tests.exe\"\n#r \"System.Reactive.Core.dll\"\n#r \"System.Reactive.Interfaces.dll\"\n#r \"System.Reactive.Linq.dll\"\n#r @\"..\\..\\..\\Packages\\Newtonsoft.Json\\lib\\net45\\Newtonsoft.Json.dll\"\n#r @\"..\\..\\..\\Packages\\FsPickler\\lib\\net45\\FsPickler.dll\"\n#r @\"..\\..\\..\\Packages\\FsPickler.Json\\lib\\net45\\FsPickler.Json.dll\"\n\n(*\nChallenge:\n\na) create a binary tree which stores single elements in leafs.\nb) provide a traversal function which extracts leaf nodes from the tree (fold).\nc) leaf node extraction should be incremental\nd) provide functional snapshots\ne) undelimited undo/redo while maintainging efficient updates.\n*)\n\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen Aardvark.Base.Incremental.Tests\n\nlet test a = if a then printfn \"OK\" else failwith \"assertion failed.\" a \n\n// Let us start with a binary tree\ntype PTree<'a> = PNode of left : PTree<'a> * right : PTree<'a>\n               | PLeaf of 'a\n\n// (a) done.\n\n// lets define a traversal which extracts leaf nodes from the tree\nlet rec leafNodesP t =\n    seq {\n        match t with \n         | PNode(l,r) -> \n            yield! leafNodesP l\n            yield! leafNodesP r\n         | PLeaf v ->\n            yield v\n    }\n\nlet testTree1 = PNode( PNode(PLeaf 1, PLeaf 2), PNode (PLeaf 3, PLeaf 4))\ntest ((testTree1 |> leafNodesP |> Seq.toList) = [1;2;3;4])\n                         \n// (b) done.\n\n// Let us convert the tree to an adaptive one\ntype Tree<'a> = Node of left : IMod<Tree<'a>> * right : IMod<Tree<'a>> \n              | Leaf of IMod<'a>\n\n// Let us define the adaptive version of leafNodes\nlet rec leafNodes t =\n    aset {\n        match t with \n         | Node(l,r) -> \n            let! (l,r) = l,r // children are mod, read them adaptively\n            yield! leafNodes l // then recurse and use yield! \n                               // since the rec call returns an aset\n            yield! leafNodes r\n         | Leaf v ->\n            yield v\n    } \n\n// there are many mods around. let us make convinience functions\n// for constructing mod trees from values more easily\nlet leaf v = Leaf (Mod.init v)\nlet node l r = Node (Mod.init l, Mod.init r)\n\nlet l1 = node (leaf 1) (leaf 2) |> Mod.init\nlet l2Original = node (leaf 3) (leaf 4) // just store the l2 for later usage\nlet l2 = l2Original |> Mod.init\nlet testTree2 = Node (l1, l2)\n\n// since we have asets, we have unordered outpus, so we need a utility for comparing\n// our results with expected results while respecting set semantics.\nlet setToSet aset = aset |> ASet.toList |> List.map Mod.force |> Set.ofList \nlet setEqual xs aset = (setToSet aset) = (Set.ofList xs)\n\nlet resultingLeafNodes = testTree2 |> leafNodes\n\ntest (resultingLeafNodes|> setEqual [1;2;3;4])\n\n// let verify that mod works as expected. Let us modify the tree by replacing the right subtrree with a leaf 10\ntransact (fun () -> Mod.change l2 (leaf 10)) \n\ntest (resultingLeafNodes |> setEqual [1;2;10])\n\n// (c) done. (incremental fold for adaptive binary trees)\n\n// Okay, we have incremental updates to trees. But what if we want functional snapshots?\n// let us adaptively convert our mod tree to a persistent one!\n\nlet rec buildPeristent t =\n    adaptive {\n        match t with \n         | Node(l,r) -> \n            let! l = l\n            let! r = r\n            let! lTree = buildPeristent l\n            let! rTree = buildPeristent r\n            return PNode(lTree, rTree)\n         | Leaf v ->\n            let! v = v\n            return PLeaf v\n    } \n\nlet testTree2InPersistent = testTree2 |> buildPeristent\ntest ((Mod.force testTree2InPersistent) = PNode(PNode(PLeaf(1),PLeaf(2)), PLeaf 10))\n\n// let us modify the mod tree and see how the persistent representation looks like\ntransact (fun () -> Mod.change l2 l2Original)\n\ntest ((Mod.force testTree2InPersistent) = PNode(PNode(PLeaf 1, PLeaf 2), PNode(PLeaf 3, PLeaf 4)))\n\n// (d) done. we have functional snapshots (we will see this is not sufficient for (e))\n\n// by the way, our modification also updated our leaf list\ntest (testTree2 |> leafNodes |> setEqual [1;2;3;4])\n\n// (just for presentation purpose i use a separate module which allows me to reuse variable names for top level bindings)\nmodule UndoRedo =\n    // lets go on and move on to undo-redo\n    // in order to implement undo redo generically, but not globally we introduce\n    // a scope (e.g. camera moves shall not be tracked globally).\n    // the undo redo scope acts as factory for IModRef values but tracks snapshots for them.\n    // please note that the undo-redo s<stem here was just a 40 line sketch by gh. But as you will see,\n    // this solution is so beautiful, concise, efficient and awesome.\n\n    let scope = UndoRedoScope()\n    // let us now create a tree just as before but we use special mod ctors \n\n    // let us now create the tree just like before but by using the undo redo scope\n    let leaf v = Leaf (scope.initMod v)\n    let node l r = Node (scope.initMod l, scope.initMod r)\n\n    let l1 = node (leaf 1) (leaf 2) |> scope.initMod\n    let l2Original = node (leaf 3) (leaf 4) \n    let l2 = l2Original |> scope.initMod\n    let testTree2 = Node (l1, l2)\n\n    let adaptiveLeafNodes = testTree2 |> leafNodes\n\n    // again, let us synthesize the leafs\n    test (adaptiveLeafNodes |> setEqual [1;2;3;4])\n\n    // Lets say, this tree should be saved as snapshot - project1\n    let project1 = scope.Snapshot()\n\n    // let us do some modification\n    transact (fun () -> Mod.change l2 (leaf 10))\n\n    test (adaptiveLeafNodes |> setEqual [1;2;10])\n\n    let project2 = scope.Snapshot()\n\n    // let us do some modification\n    transact (fun () -> Mod.change l1 (leaf 11))\n\n    test (adaptiveLeafNodes |> setEqual [11;10])\n\n    let project3 = scope.Snapshot()\n\n    // let us go back to project 1\n    transact (fun () -> project1.Restore())\n    test (adaptiveLeafNodes |> setEqual [1;2;3;4])\n\n    // again to project 2\n    transact (fun () -> project2.Restore())\n    test (adaptiveLeafNodes |> setEqual [1;2;10])\n\n    transact (fun () -> project3.Restore())\n    printfn \"%A\" (adaptiveLeafNodes |> ASet.toList |> List.map Mod.force)\n    test (adaptiveLeafNodes |> setEqual [11;10])\n\n    // as you can see, adaptively synthesized leaf nodes automatically update,\n    // functional snapshots automatically update and we have time travel.\n    // this completes challange (d).\n\n    \nopen System.Diagnostics\n// let us create a function for measuring performance\nlet timed f = \n    let sw = Stopwatch()\n    sw.Start()\n    let r = f ()\n    sw.Stop()\n    printfn \"function took: %f seconds\" sw.Elapsed.TotalSeconds\n    r,sw.Elapsed.TotalSeconds\n\nmodule Persistency =\n\n    // Let us now add persistency for adaptive undoable tree's.\n    // First, let us create a new subclass of serializationBean,\n    // register interceptors via dependency injection etc.\n    // :P\n\n    // No, let us define picklers for pickling and unpickling non-adaptive \n    // persistent binary trees\n    open Nessos.FsPickler\n    open Nessos.FsPickler.Combinators\n    open Nessos.FsPickler.Json\n    open System.Diagnostics\n    open System.IO\n    open System.Runtime.Serialization.Formatters.Binary\n\n    let p pElement =\n        Pickler.fix (fun self ->\n            Pickler.sum (fun t node leaf ->\n                match t with\n                | PNode (l,r) -> node (l, r)\n                | PLeaf  v    -> leaf v )\n            ^+ Pickler.case PNode (Pickler.pair self self) \n            ^. Pickler.case PLeaf pElement\n        )\n    let pPTree<'a> = p Pickler.auto<'a>\n\n    let bin = FsPickler.CreateBinarySerializer()\n    let json = FsPickler.CreateJsonSerializer()\n    let serialized = json.PickleToString(testTree1,pPTree)\n    printfn \"%s\" serialized\n\n    // let us test performance of this simple serialization function\n    let mutable root = PLeaf 1\n    let depth = 2\n    for i in 0 .. depth do\n        root <- PNode(root,root)\n\n\n    printfn \"pickling\"\n    let bytes,time = timed (fun () -> bin.Pickle(root,pPTree))\n    printfn \"pickling 2\"\n    let bytes3,time3 = timed (fun () -> bin.Pickle(root,pPTree))\n    printfn \"running .net\"\n\n    let bytes2, time2 = \n        timed (fun () ->\n            let formatter = new BinaryFormatter();\n            let stream = new MemoryStream()\n            formatter.Serialize(stream, obj);\n            stream.Close();\n            stream.GetBuffer()\n    )\n\n    root <- PLeaf 2\n    printfn \"serialization performed: %d bytes total, %d nodes, in %f seconds (%f mb/s)\" bytes.Length (pow 2 depth) time (float (float bytes.Length / float (1024 * 1024)) / float time)\n    printfn \"serialization performed: %d bytes total, %d nodes, in %f seconds (%f mb/s)\" bytes2.Length (pow 2 depth) time (float (float bytes2.Length / float (1024 * 1024)) / float time2)\n    printfn \"serialization performed: %d bytes total, %d nodes, in %f seconds (%f mb/s)\" bytes3.Length (pow 2 depth) time (float (float bytes2.Length / float (1024 * 1024)) / float time3)\n"
  },
  {
    "path": "src/Demo/Sketch/Yampa.fsx",
    "content": "﻿#I @\"..\\..\\..\\bin\\Release\"\n#I @\"..\\..\\..\\Packages\\Rx-Core\\lib\\net45\"\n#I @\"..\\..\\..\\Packages\\Rx-Interfaces\\lib\\net45\"\n#I @\"..\\..\\..\\Packages\\Rx-Linq\\lib\\net45\"\n#r \"Aardvark.Base.dll\"\n#r \"Aardvark.Base.Essentials.dll\"\n#r \"Aardvark.Base.TypeProviders.dll\"\n#r \"Aardvark.Base.FSharp.dll\"\n#r \"Aardvark.Base.Incremental.dll\"\n#r \"System.Reactive.Core.dll\"\n#r \"System.Reactive.Interfaces.dll\"\n#r \"System.Reactive.Linq.dll\"\n\nopen System\nopen System.Threading\nopen System.Linq\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen System.Reactive\nopen System.Reactive.Linq\n\n\nmodule Yampa =\n    type SF<'s, 'a, 'b> = { run : 's -> 'a -> 's * 'b }\n\n    module SF =\n        let arr (f : 'a -> 'b) =\n            { run = fun s a -> s,f a }\n\n        let compose(g : SF<'s, 'b, 'c>) (f : SF<'s, 'a, 'b>) =\n            { run = fun s a ->\n                let (s,b) = f.run s a\n                g.run s b\n            }\n\n        let first (f : SF<'s, 'a, 'b>) : SF<'s, 'x * 'a, 'x * 'b> =\n            { run = fun s (x,a) ->\n                let (s,b) = f.run s a\n                (s, (x,b))\n            }\n\n        let second (f : SF<'s, 'a, 'b>) : SF<'s, 'a * 'x, 'b * 'x> =\n            { run = fun s (a,x) ->\n                let (s,b) = f.run s a\n                (s, (b,x))\n            }\n\n        let map (f : 'b -> 'c) (m : SF<'s, 'a, 'b>) =\n            { run = fun s v ->\n                let (s,r) = m.run s v\n                (s, f r)\n            }\n\n        let par (f : SF<'s, 'a, 'b>) (g : SF<'s, 'a, 'c>) =\n            { run = fun s v ->\n                let (s, b) = f.run s v\n                let (s, c) = g.run s v\n\n                (s, (b,c))\n\n            }\n\n        let zip (f : SF<'s, 'a, 'b>) (g : SF<'s, 'x, 'y>) =\n            { run = fun s (a,x) ->\n                let (s,b) = f.run s a\n                let (s,y) = g.run s x\n                (s,(b,y))\n            }\n\n\nmodule FrpModEvents =\n\n    open Aardvark.Base\n    open Aardvark.Base.Incremental\n\n    [<ReferenceEquality;NoComparison>]\n    type Token = Token of IAdaptiveObject\n\n    let time = Token null\n    let mutable executionPending = 1\n\n    type private ObservableMod(input : IMod, emitFirstValue : bool) =\n        inherit Mod.AbstractMod<obj>()\n\n        let mutable subscriptionCount = 0\n        let subscriptions = HashSet<IObserver<obj>>()\n\n        interface IObservable<obj> with\n            member x.Subscribe(obs : IObserver<obj>) =\n                Interlocked.Increment &subscriptionCount |> ignore\n\n                // force the evaluation (in order to see subsequent markings)\n                let v = x.GetValue null\n                if emitFirstValue then\n                    obs.OnNext v\n\n                lock subscriptions (fun () -> subscriptions.Add obs |> ignore )\n                { new IDisposable with \n                    member x.Dispose() =\n                        Interlocked.Decrement &subscriptionCount |> ignore\n                        lock subscriptions (fun () -> subscriptions.Remove obs |> ignore)\n                }\n\n        override x.Mark() =\n            if subscriptionCount > 0 then\n                let v = x.GetValue null\n                let all = lock subscriptions (fun s -> subscriptions.ToArray())\n                for s in all do s.OnNext v\n\n            true\n\n        override x.Compute() =\n            input.GetValue x\n\n\n    type IContext =\n        abstract member ConsumeValue : Token -> Option<'a>\n\n    open System.Collections.Concurrent\n\n    type Context<'a, 'b>(sf : ISF<'a,'b>, initial : 'a, output : 'b -> unit) =\n        inherit AdaptiveObject()\n        let buffer = ConcurrentDict<Token, ConcurrentQueue<obj>>(Dict())\n        let buffers = Dictionary<Token,IDisposable>()\n\n        let mutable sf = sf\n        let mutable oldDeps = HashSet()\n\n        let ev = new System.Threading.ManualResetEventSlim(true)\n\n        let isDone () =\n            buffer.Count = 0\n\n        let mutable iterations = 1\n\n        member x.ShouldProcess = ev\n\n        member x.NextFixPoint() =\n            \n            //printfn \"running iteration: %A\" iterations\n            x.EvaluateAlways null (fun () ->\n                let newDeps = sf.Deps |> HashSet \n                let added = newDeps |> Seq.filter (oldDeps.Contains >> not)\n                let removed = oldDeps |> Seq.filter (newDeps.Contains >> not)\n                for a in added do x.Listen a\n                for r in removed do x.UnListen r\n                \n                let sfNew,b = sf.Run(x,initial)\n                output b\n                sf <- sfNew\n                oldDeps <- newDeps\n\n                if isDone () then \n                    Interlocked.Exchange(&executionPending, 0) |> ignore\n                    ev.Reset()\n            )\n            \n            //printfn \"done iteration: %A\" iterations\n            iterations <- iterations + 1\n\n        member x.Listen(Token(o) as token) =\n            match o with \n             | null -> \n                buffer.GetOrCreate(token, fun _ -> ConcurrentQueue()) |> ignore\n\n             | :? IMod as m -> \n                let obs = ObservableMod(m, true)\n                \n                let queue() = buffer.GetOrCreate(token, fun _ -> ConcurrentQueue())\n                let d = obs.Subscribe(fun v -> \n                    queue().Enqueue v; \n                    let pending = Interlocked.Exchange(&executionPending, 1)\n                    if pending = 0 then\n                        transact (fun () -> x.MarkOutdated())\n                )\n                buffers.Add(token, d) |> ignore\n             | _ -> \n                failwith\"\"\n\n        member x.UnListen(Token(o) as token) =\n            match o with \n             | null -> ()\n             | _ -> \n                o.Outputs.Remove x |> ignore\n                buffers.[token].Dispose()\n                buffer.Remove token |> ignore\n                buffers.Remove token |> ignore\n                \n        member x.ConsumeValue (t : Token) : Option<'x> =\n            match buffer.TryGetValue t with\n             | (true,v) ->\n                let res = \n                    match v.TryDequeue() with\n                        | (true, v) -> v |> unbox<'x> |> Some\n                        | _ -> None\n\n                if v.Count = 0 then buffer.Remove t |> ignore\n\n                res\n\n             | _ -> \n                None\n\n        override x.Mark() = \n            ev.Set()\n            false\n\n        interface IContext with\n            member x.ConsumeValue(t : Token) : Option<'x> = x.ConsumeValue t\n\n\n    and ISF<'a,'b> =\n        abstract member Run : IContext * 'a -> ISF<'a,'b> * 'b\n        abstract member Deps : list<Token>\n\n    type SF<'a,'b>(f : IContext * 'a -> ISF<'a,'b> * 'b, deps : list<Token>) =\n        interface ISF<'a,'b> with\n            member x.Run (ctx,v) = f (ctx,v)\n            member x.Deps = deps\n\n    type Event<'a> = Event of 'a | NoEvent\n\n    type Ev<'a,'b>(o : IMod<'b>) =\n        let t = Token o\n        interface ISF<'a,Event<'b>> with\n            member x.Run (ctx,_) = \n                let r = ctx.ConsumeValue t\n                let self = x :> ISF<'a,Event<'b>>\n                match r with \n                 | Some v -> self, Event v\n                 | None -> self, NoEvent\n            member x.Deps = [t]\n\n    let ev o = Ev<_,_>(o) :> ISF<_,_>\n    let sf f d = SF<_,_>(f,d) :> ISF<_,_>\n\n    let arr f = \n        let self = ref Unchecked.defaultof<_>\n        self := sf (fun v -> !self, f v) []\n        !self\n\n    let arrU d f = \n        let self = ref Unchecked.defaultof<_>\n        self := sf (fun (_,v) -> !self, f v) d\n        !self\n\n    let rec (>>>) (a:ISF<'a,'b>) (b:ISF<'b,'c>) : ISF<'a,'c> = \n        let f (ctx, v) = \n            let c, r1 = a.Run(ctx, v)\n            let d, r2 = b.Run(ctx, r1)\n            c >>> d, r2\n        sf f (a.Deps @ b.Deps)\n\n    let click = Mod.init 1111\n    let clickEv : ISF<unit,Event<int>> = ev click\n\n    let nowTime = arrU [Token null] (fun e -> e,DateTime.Now)\n\n    let urdar = clickEv >>> nowTime\n\n    let start (init : unit -> 'a) \n              (output : 'b -> unit) \n              (sfT : ISF<'a,'b>) =\n        \n\n        let ctx = Context(sfT, init(), output)\n        ctx.NextFixPoint()\n\n        let t = System.Threading.Thread(ThreadStart(fun _ -> \n            while true do\n                ctx.ShouldProcess.Wait()\n                ctx.NextFixPoint()\n        ))\n        t.IsBackground <- true\n        t.Start()\n\n        t\n\n    let toMod (sf : SF<'a,'b>) (v : 'a) =\n        let r = Mod.init Unchecked.defaultof<_>\n        let ctx = Context(sf, v, (fun v -> Mod.change r v))\n        ctx.NextFixPoint()\n        let t = System.Threading.Thread(ThreadStart(fun _ -> \n            while true do\n                ctx.ShouldProcess.Wait()\n                ctx.NextFixPoint()\n        ))\n        t.IsBackground <- true\n        t.Start()\n        r :> IMod<_>\n\n//    let rec flatten (f : ISF<'x, ISF<'x, 'y>>) : ISF<'x, 'y> =\n//        let run (ctx,x) =\n//            let cont1,inner = f.Run(ctx,x)\n//            let cont, v = inner.Run(ctx,x)\n//            failwith \"\"\n//        failwith \"\"\n//\n//    let sepp (i : ISF<'x,'a>) (f : 'a -> ISF<'x, 'y>) : ISF<'x, 'y> =\n//        failwith \"\"\n\n    let test () =\n        let t = start (constF ()) (fun (e,v) -> match e with | Event(_) as v -> printfn \"%A\" v | _ -> ()) urdar\n\n        for i in 0 .. 5 do\n            transact (fun () -> Mod.change click i)\n        \n        ()\n"
  },
  {
    "path": "src/Demo/Sketch/adventure.txt",
    "content": "My little Event adventure\n\nI came up with four different implementations for our event-system in the last few days, each of which has more\ncons than pros sadly. \nAfter all i decided to write it all down to get an overview.\n\nBasically we're at a bad point here. \nFor the first time in the history of ever the scientific monster does not seem to be the best solution here.\nFrom a scientific point of view the lazy implementation seems interesting (due to its novelty).\nHowever from a pragmatic point of view the observable implementation might be the thing we need.\n\n\nlazy (like aset/alist/etc.) [implementation: Lazy.fsx]\n\tpro:\n\t\t+ fits into our system\n\t\t+ pattern matching is easy\n\t\t+ state should be fairly easy to integrate (although order is sometimes undefined)\n\tcon:\n\t\t- adapters force eager evaluation (for mods/asets/etc.)\n\t\t- completion hard to handle\n\t\t- unexpected behaviour due to lazy reader-creation (missing events where no reader exists)\n\t\t\nasync-like [implementation: FutureList.fsx]\n\tpro:\n\t\t+ supports state: \n\t\t\ttype FutureList<'s, 'a> = { run : 's -> Future<'s * FutureListValue<'s, a>> }\n\t\t\tand  FutureListValue<'s, 'a> = \n\t\t\t\t| Nil\n\t\t\t\t| Error of Exception\n\t\t\t\t| Cons of 'a * FutureList<'s, 'a>\n\t\t+ seems to be natural for people which are not in too deep (since sm/msc/etc. invented it that way)\n\t\t+ no space-leaks for input adapters\n\tcon:\n\t\t- may leak events (when run is not subscribing to the cont immediately)\n\t\t- hard to implement from first principles\n\t\t- output-adapters leaking subscriptions\n\t\t- unexpected re-execution of functions due to different state\n\t\t\nobservable [implementation: Observable.fsx]\n\tpro:\n\t\t+ simple semantics (users understand effects easily)\n\t\t+ cannot miss events\n\t\t+ no conceptual space-leakage\n\t\t+ combinators are engineering monsters (thats a con too)\n\tcon:\n\t\t- adapters leaking subscriptions (at least for mods => need to resort to finalizers)\n\t\t- cannot think of state-support atm.\n\t\t- hard to get your head around subscription-things\n\t\t- combinators are engineering monsters (thats a pro too)\n\t\t\nyampa [no implementation atm.]\n\tpro:\n\t\t+ easy to implement\n\t\t+ pure\n\tcon:\n\t\t- does not compose with the rest of the system\n\t\t- re-execution of everything all the time\n\t\t- lots of closure allocations"
  },
  {
    "path": "src/Demo/Sketch/paket_.references",
    "content": "FsPickler.Json\nAardvark.Base.Incremental\nFSharp.Core"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Aardvark.Base.Benchmarks.csproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <ApplicationIcon />\n    <GenerateProgramFile>false</GenerateProgramFile>\n    <OutputType>Exe</OutputType>\n    <StartupObject />\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>.\\bin\\Release</OutputPath>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n    <DebugType>pdbonly</DebugType>\n    <DebugSymbols>true</DebugSymbols>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>.\\bin\\Debug</OutputPath>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n    <DebugType>pdbonly</DebugType>\n    <DebugSymbols>true</DebugSymbols>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Remove=\"**\\*_template.cs\" />\n    <Compile Remove=\"**\\*_generator.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"**\\*_template.cs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.IO\\Aardvark.Base.IO.csproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Telemetry\\Aardvark.Base.Telemetry.csproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/CodeGenTest.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.Intrinsics;\nusing System.Runtime.Intrinsics.X86;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    struct MyVector4\n    {\n        public float X;\n        public float Y;\n        public float Z;\n        public float W;\n\n        public MyVector4(float x, float y, float z, float w)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n            W = w;\n        }\n\n        public readonly float Length_Ref\n        {\n            get { return MathF.Sqrt(X * X + Y * Y + Z * Z + W * W); }\n        }\n\n        public float Length_Sse_V1\n        {\n            get\n            {\n                unsafe\n                {\n                    fixed (MyVector4* pthis = &this)\n                    {\n                        var mmx = Sse.LoadVector128((float*)pthis);\n                        mmx = Sse41.DotProduct(mmx, mmx, 0xF1);\n                        var l2 = mmx.GetElement(0);\n                        return MathF.Sqrt(l2);\n                    }\n                }\n            }\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        static unsafe float Length_Sse_V2_Helper(MyVector4 vec)\n        {\n            var ptr = (float*)&vec;\n            var mmx = Sse.LoadVector128(ptr);\n            mmx = Sse41.DotProduct(mmx, mmx, 0xF1);\n            var l2 = mmx.GetElement(0);\n            return MathF.Sqrt(l2);\n        }\n\n        public readonly float Length_Sse_V2\n        {\n            get { return Length_Sse_V2_Helper(this); }\n        }\n\n        public readonly float Length_Sse_V3\n        {\n            get \n            {\n                unsafe\n                {\n                    var vec = this;\n                    var ptr = (float*)&vec;\n                    var mmx = Sse.LoadVector128(ptr);\n                    mmx = Sse41.DotProduct(mmx, mmx, 0xF1);\n                    var l2 = mmx.GetElement(0);\n                    return MathF.Sqrt(l2);\n                }\n            }\n        }\n    }\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class CodeGenTests\n    {\n        readonly MyVector4[] arr = new MyVector4[1000000];\n\n        //[GlobalSetup]\n        public CodeGenTests()\n        {\n            var rnd1 = new Random(1);\n            for (int i = 0; i < arr.Length; i++)\n                arr[i] = new MyVector4((float)rnd1.NextDouble(), (float)rnd1.NextDouble(), (float)rnd1.NextDouble(), (float)rnd1.NextDouble());\n        }\n\n        [Benchmark]\n        public float Vec4Length_Reference()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n                sum += local[i].Length_Ref;\n            return sum;\n        }\n\n        [Benchmark]\n        public float Vec4Length_Sse_V1()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n                sum += local[i].Length_Sse_V1;\n            return sum;\n        }\n\n        [Benchmark]\n        public float Vec4Length_Sse_V2()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n                sum += local[i].Length_Sse_V2;\n            return sum;\n        }\n\n        [Benchmark]\n        public float Vec4Length_Sse_V3()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n                sum += local[i].Length_Sse_V3;\n            return sum;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/ColorConversion.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing System;\nusing System.Runtime.CompilerServices;\n\nnamespace Aardvark.Base.Benchmarks\n{   static class LocalCol\n    {\n        private const float c_byteToFloat = 1.0f / 255.0f;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public static float ByteToFloat(byte b) { return c_byteToFloat * (float)b; }\n\n        public static readonly Func<byte, float> ByteToFloatFunc = ByteToFloat;\n\n    }\n\n    //BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.2006 (21H2)\n    //AMD Ryzen 5 1500X, 1 CPU, 8 logical and 4 physical cores\n    //.NET SDK= 6.0.401\n    //  [Host] : .NET Core 3.1.29 (CoreCLR 4.700.22.41602, CoreFX 4.700.22.41702), X64 RyuJIT\n\n    //Job=InProcess Toolchain = InProcessEmitToolchain\n\n    //|                 Method |      Mean |     Error |    StdDev |    Median | Ratio |\n    //|----------------------- |----------:|----------:|----------:|----------:|------:|\n    //|  'C3b to C3f (Lambda)' | 14.354 us | 0.0366 us | 0.0305 us | 14.357 us |  1.00 |\n    //| 'C3b to C3f (Inlined)' |  1.603 us | 0.0317 us | 0.0716 us |  1.570 us |  0.12 |\n\n    [InProcess]\n    public class ColorConversion\n    {\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static C3f C3bToC3f(C3b color)\n            => new C3f(\n                LocalCol.ByteToFloatFunc(color.R),\n                LocalCol.ByteToFloatFunc(color.G),\n                LocalCol.ByteToFloatFunc(color.B)\n            );\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static C3f C3bToC3fInlined(C3b color)\n            => new C3f(\n                LocalCol.ByteToFloat(color.R),\n                LocalCol.ByteToFloat(color.G),\n                LocalCol.ByteToFloat(color.B)\n            );\n\n\n        C3b[] _cols;\n\n        [GlobalSetup]\n        public void Init()\n        {\n            var rnd = new RandomSystem(0);\n            _cols = new C3b[1000].SetByIndex(i => rnd.UniformC3f().ToC3b());\n        }\n\n        [Benchmark(Baseline = true, Description = \"C3b to C3f (Lambda)\")]\n        public C3f ToC3fFunc()\n        {\n            C3f sum = C3f.Black;\n            foreach (var x in _cols)\n                sum += C3bToC3f(x);\n            return sum;\n        }\n\n        [Benchmark(Description = \"C3b to C3f (Inlined)\")]\n        public C3f ToC3fInline()\n        {\n            C3f sum = C3f.Black;\n            foreach (var x in _cols)\n                sum += C3bToC3fInlined(x);\n            return sum;\n        }\n    }\n\n\n    //BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.2006 (21H2)\n    //AMD Ryzen 5 1500X, 1 CPU, 8 logical and 4 physical cores\n    //.NET SDK= 6.0.401\n    //  [Host] : .NET Core 3.1.29 (CoreCLR 4.700.22.41602, CoreFX 4.700.22.41702), X64 RyuJIT\n\n    //Job=InProcess Toolchain = InProcessEmitToolchain\n\n    //|                    Method |     Mean |    Error |   StdDev | Ratio | RatioSD |     Gen 0 |     Gen 1 |     Gen 2 | Allocated |\n    //|-------------------------- |---------:|---------:|---------:|------:|--------:|----------:|----------:|----------:|----------:|\n    //|  'Byte to Float (Lambda)' | 690.6 ms | 13.07 ms | 12.83 ms |  1.00 |    0.00 | 2000.0000 | 2000.0000 | 2000.0000 |    400 MB |\n    //| 'Byte to Float (Inlined)' | 656.8 ms | 12.83 ms | 16.68 ms |  0.95 |    0.02 | 2000.0000 | 2000.0000 | 2000.0000 |    400 MB |\n\n    [InProcess]\n    [MemoryDiagnoser]\n    public class ColorVolumeConversion\n    {\n        private static class Volume\n        {\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static Volume<float> ToFloatColor(Volume<byte> volume)\n                => volume.MapToImageWindow(LocalCol.ByteToFloat);\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public static Volume<float> ToFloatColorFunc(Volume<byte> volume)\n                => volume.MapToImageWindow(LocalCol.ByteToFloatFunc);\n\n        }\n\n        Volume<byte>[] volumes;\n\n        [GlobalSetup]\n        public void Init()\n        {\n            var rnd = new RandomSystem(0);\n            var size = new V3i(64, 128, 128);\n\n            volumes =\n                new Volume<byte>[100].SetByIndex(i =>\n                {\n                    var v = new Volume<byte>(size);\n                    v.SetByIndex(j => (byte)rnd.UniformInt());\n                    return v;\n                });\n        }\n\n        [Benchmark(Baseline = true, Description = \"Byte to Float (Lambda)\")]\n        public float ByteToFloatFunc()\n        {\n            float sum = 0;\n            foreach (var x in volumes)\n            {\n                var v = Volume.ToFloatColorFunc(x);\n                sum += v.Data[0];\n            }\n            return sum;\n        }\n\n        [Benchmark(Description = \"Byte to Float (Inlined)\")]\n        public float ByteToFloatInline()\n        {\n            float sum = 0;\n            foreach (var x in volumes)\n            {\n                var v = Volume.ToFloatColor(x);\n                sum += v.Data[0];\n            }\n            return sum;\n        }\n    }\n\n\n    //BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.2006 (21H2)\n    //AMD Ryzen 5 1500X, 1 CPU, 8 logical and 4 physical cores\n    //.NET SDK=6.0.401\n    //  [Host] : .NET Core 3.1.29 (CoreCLR 4.700.22.41602, CoreFX 4.700.22.41702), X64 RyuJIT\n\n    //Job=InProcess  Toolchain=InProcessEmitToolchain\n\n    //|                Method |     Mean |    Error |   StdDev | Ratio | RatioSD | Allocated |\n    //|---------------------- |---------:|---------:|---------:|------:|--------:|----------:|\n    //| 'C3f to HSL (Method)' | 20.95 us | 0.382 us | 0.339 us |  1.00 |    0.00 |         - |\n    //| 'C3f to HSL (Lambda)' | 22.47 us | 0.091 us | 0.085 us |  1.07 |    0.02 |         - |\n\n    [InProcess]\n    [MemoryDiagnoser]\n    public class ColorHSLConversion\n    {\n        private static class LocalCol\n        {\n            public static HSLf ToHSLf(C3f c)\n            {\n                double cr = 0.0, h6 = 0.0, l = 0.0;\n                if (c.R > c.G)\n                {\n                    if (c.R > c.B)\n                    {\n                        if (c.G > c.B) { cr = c.R - c.B; l = 0.5 * (c.R + c.B); }  // R > G > B\n                        else { cr = c.R - c.G; l = 0.5 * (c.R + c.G); }  // R > B >= G\n                        h6 = 0 + (c.G - c.B) / cr;\n                    }\n                    else                                                            // B >= R > G\n                    {\n                        cr = c.B - c.G; l = 0.5 * (c.B + c.G);\n                        h6 = 4 + (c.R - c.G) / cr;\n                    }\n                }\n                else                                                                // G >= R\n                {\n                    if (c.G > c.B)\n                    {\n                        if (c.R > c.B) { cr = c.G - c.B; l = 0.5 * (c.G + c.B); }  // G >= R > B\n                        else { cr = c.G - c.R; l = 0.5 * (c.G + c.R); }  // G > B >= R\n                        h6 = 2 + (c.B - c.R) / cr;\n                    }\n                    else                                                            // B >= G >= R\n                    {\n                        cr = c.B - c.R; l = 0.5 * (c.B + c.R);\n                        if (cr > 0.0) h6 = 4 + (c.R - c.G) / cr;\n                    }\n                }\n                return new HSLf(Fun.Frac(h6 * 1.0 / 6.0),\n                                cr > Constant<float>.PositiveTinyValue\n                                    ? cr / (1.0 - Fun.Abs(2.0 * l - 1.0)) : 0.0,\n                                l);\n            }\n\n            public static readonly Func<C3f, HSLf> HSLfFromC3f = ToHSLf;\n        }\n\n        C3f[] _cols;\n\n        [GlobalSetup]\n        public void Init()\n        {\n            var rnd = new RandomSystem(0);\n            _cols = new C3f[1000].SetByIndex(i => rnd.UniformC3f());\n        }\n\n        [Benchmark(Baseline = true, Description = \"C3f to HSL (Method)\")]\n        public HSLf C3fToHSLFunc()\n        {\n            HSLf sum = new HSLf();\n            foreach (var c in _cols)\n            {\n                var h = LocalCol.ToHSLf(c);\n                sum = new HSLf(sum.H + h.H, sum.S + h.S, sum.L + h.L);\n            }\n            return sum;\n        }\n\n        [Benchmark(Description = \"C3f to HSL (Lambda)\")]\n        public HSLf C3fToHSL()\n        {\n            HSLf sum = new HSLf();\n            foreach (var c in _cols)\n            {\n                var h = LocalCol.HSLfFromC3f(c);\n                sum = new HSLf(sum.H + h.H, sum.S + h.S, sum.L + h.L);\n            }\n            return sum;\n        }\n    }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/ConstantsBenchmark.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //|                Method |     Mean |   Error |  StdDev | Code Size |\n    //|---------------------- |---------:|--------:|--------:|----------:|\n    //|  ApproximateEqDefault | 214.2 μs | 0.75 μs | 0.66 μs |     279 B |\n    //|   ApproximateEqInline | 145.1 μs | 1.58 μs | 1.32 μs |     190 B |\n\n    // After simplifying computation of machine epsilon:\n\n    //| Method               | Mean     | Error    | StdDev   |\n    //|--------------------- |---------:|---------:|---------:|\n    //| ApproximateEqDefault | 84.80 us | 1.080 us | 1.010 us |\n    //| ApproximateEqInline  | 83.66 us | 1.240 us | 1.160 us |\n\n    [InProcess]\n    public class ConstantsBenchmark\n    {\n        public Ray3d[] rays;\n\n        public ConstantsBenchmark()\n        {\n            var rnd = new RandomSystem(1);\n            rays = new Ray3d[100000].SetByIndex(i => new Ray3d(rnd.UniformV3d() * 2 - 1, rnd.UniformV3dDirection()));\n        }\n\n        [Benchmark]\n        public int ApproximateEqDefault()\n        {\n            var a = rays;\n            var cnt = 0;\n            for (int i = 0; i < a.Length; i++)\n                if (a[i].Origin.ApproximateEquals(a[i].Direction))\n                    cnt++;\n            return cnt;\n        }\n\n        [Benchmark]\n        public int ApproximateEqInline()\n        {\n            var a = rays;\n            var cnt = 0;\n            for (int i = 0; i < a.Length; i++)\n                if (a[i].Origin.ApproximateEquals(a[i].Direction, 1e-16))\n                    cnt++;\n            return cnt;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Enumerators.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing Aardvark.Base;\nusing System.Linq;\nusing BenchmarkDotNet.Jobs;\nusing System.Runtime.InteropServices;\nusing System.Collections;\nusing Microsoft.CodeAnalysis.CSharp.Syntax;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //|                  Method | Count |        Mean |     Error |    StdDev |      Median |\n    //|------------------------ |------ |------------:|----------:|----------:|------------:|\n    //|            ForEachArray |     1 |   0.2825 ns | 0.0341 ns | 0.0379 ns |   0.2895 ns |\n    //|             ForEachList |     1 |   5.4612 ns | 0.1341 ns | 0.1596 ns |   5.4791 ns |\n    //|          ForEachHashSet |     1 |   5.6378 ns | 0.1343 ns | 0.1256 ns |   5.6246 ns |\n    //| ForEachDictionaryValues |     1 |   6.0464 ns | 0.0992 ns | 0.0928 ns |   6.0032 ns |\n    //|   ForEachDictionaryKeys |     1 |   6.0921 ns | 0.0758 ns | 0.0709 ns |   6.0765 ns |\n    //|       ForEachDictionary |     1 |  22.6252 ns | 0.2217 ns | 0.2074 ns |  22.6664 ns |\n    //|           ForEachIntSet |     1 |  17.9450 ns | 0.3709 ns | 0.5077 ns |\n    //|       ForEachDictValues |     1 |  47.0700 ns | 0.9420 ns | 0.8810 ns |                 -> TODO ValuesEnumerator\n    //|         ForEachDictKeys |     1 |  44.2800 ns | 0.2590 ns | 0.2420 ns |                 -> TODO KeysEnumerator\n    //|             ForEachDict |     1 |  31.9100 ns | 0.3090 ns | 0.2890 ns |\n    //| ForEachSymbolDictValues |     1 |  46.0600 ns | 0.9700 ns | 1.1910 ns |\n    //|            ForEachArray |    10 |   4.8354 ns | 0.0848 ns | 0.0793 ns |   4.8315 ns |\n    //|             ForEachList |    10 |  25.4319 ns | 0.7352 ns | 2.1093 ns |  24.2291 ns |\n    //|          ForEachHashSet |    10 |  31.0342 ns | 0.4605 ns | 0.4307 ns |  31.0219 ns |\n    //| ForEachDictionaryValues |    10 |  28.0571 ns | 0.2260 ns | 0.1887 ns |  28.0309 ns |\n    //|   ForEachDictionaryKeys |    10 |  27.8722 ns | 0.5367 ns | 0.5020 ns |  27.8217 ns |\n    //|       ForEachDictionary |    10 |  81.7141 ns | 0.5350 ns | 0.5004 ns |  81.7748 ns |\n    //|           ForEachIntSet |    10 |  28.5740 ns | 0.3391 ns | 0.3172 ns |\n    //|       ForEachDictValues |    10 | 109.1000 ns | 0.9110 ns | 0.7600 ns |                 -> TODO ValuesEnumerator\n    //|         ForEachDictKeys |    10 | 117.8300 ns | 2.3690 ns | 2.9960 ns |                 -> TODO KeysEnumerator\n    //|             ForEachDict |    10 |  97.1700 ns | 1.9020 ns | 1.6860 ns |\n    //| ForEachSymbolDictValues |    10 | 111.6800 ns | 2.1870 ns | 2.6040 ns |\n    //|            ForEachArray |   100 |  41.0627 ns | 0.3538 ns | 0.3309 ns |  41.0444 ns |\n    //|             ForEachList |   100 | 229.5243 ns | 2.7209 ns | 2.4120 ns | 229.6100 ns |\n    //|          ForEachHashSet |   100 | 284.1676 ns | 4.9822 ns | 4.6603 ns | 282.3070 ns |\n    //| ForEachDictionaryValues |   100 | 244.8932 ns | 5.2041 ns | 4.6133 ns | 244.5696 ns |\n    //|   ForEachDictionaryKeys |   100 | 260.9201 ns | 4.6225 ns | 4.3239 ns | 260.8970 ns |\n    //|       ForEachDictionary |   100 | 687.7312 ns | 3.6999 ns | 3.4609 ns | 687.1103 ns |\n    //|           ForEachIntSet |   100 | 302.3810 ns | 1.8455 ns | 1.7262 ns |\n    //|       ForEachDictValues |   100 | 693.5000 ns |13.5200 ns |12.6500 ns |                 -> TODO ValuesEnumerator\n    //|         ForEachDictKeys |   100 | 668.2000 ns |12.9200 ns |12.6800 ns |                 -> TODO KeysEnumerator\n    //|             ForEachDict |   100 | 692.1000 ns | 1.9000 ns | 1.6800 ns |\n    //| ForEachSymbolDictValues |   100 | 632.1000 ns | 7.6100 ns | 7.1200 ns |\n\n    [PlainExporter]\n    [MemoryDiagnoser]\n    [ShortRunJob]\n    public class Enumerators\n    {\n        int[] m_array;\n        List<int> m_list;\n        HashSet<int> m_hashSet;\n        Dictionary<int, int> m_dictionary;\n        IntSet m_intSet;\n        Dict<int, int> m_dict;\n        SymbolDict<int> m_symDict;\n\n        [Params(100)]\n        public int Count;\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            m_array = new int[Count].SetByIndex(i => i + 1);\n            m_list = new List<int>(1.UpTo(Count));\n            m_hashSet = new HashSet<int>(1.UpTo(Count));\n            m_dictionary = new Dictionary<int, int>(Count);\n            for (int i = 1; i <= Count; i++)\n                m_dictionary.Add(i, i);\n            m_intSet = new IntSet(1.UpTo(Count));\n            m_dict = new Dict<int, int>(Count);\n            for (int i = 1; i <= Count; i++)\n                m_dict.Add(i, i);\n            m_symDict = new SymbolDict<int>(Count);\n            for (int i = 1; i <= Count; i++)\n                m_symDict.Add(i.ToString(), i);\n        }\n\n        [Benchmark]\n        public int ForEachArray()\n        {\n            int sum = 0;\n            foreach (var x in m_array)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachList()\n        {\n            int sum = 0;\n            foreach (var x in m_list)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachHashSet()\n        {\n            int sum = 0;\n            foreach (var x in m_hashSet)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachDictionaryValues()\n        {\n            int sum = 0;\n            foreach (var x in m_dictionary.Values)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachDictionaryKeys()\n        {\n            int sum = 0;\n            foreach (var x in m_dictionary.Keys)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachDictionary()\n        {\n            int sum = 0;\n            foreach (var x in m_dictionary)\n                sum += x.Value;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachIntSet()\n        {\n            int sum = 0;\n            foreach (var x in m_intSet)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachDictValues()\n        {\n            int sum = 0;\n            foreach (var x in m_dict.Values)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachDictFastValues()\n        {\n            int sum = 0;\n            var values = m_dict.GetValuesEnumerator();\n            while (values.MoveNext())\n                sum += values.Current;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachDictKeys()\n        {\n            int sum = 0;\n            foreach (var x in m_dict.Keys)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachDict()\n        {\n            int sum = 0;\n            foreach (var x in m_dict)\n                sum += x.Value;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachSymbolDictValues()\n        {\n            int sum = 0;\n            foreach (var x in m_symDict.Values)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int ForEachSymbolDictFastValues()\n        {\n            int sum = 0;\n            var values = m_symDict.GetValuesEnumerator();\n            while (values.MoveNext())\n                sum += values.Current;\n            return sum;\n        }\n\n        [Test]\n        public void Test()\n        {\n            var rnd = new Random(1);\n            for (int i = 0; i < 1000; i++)\n            {\n                Count = rnd.Next() & 0xfff;\n                GlobalSetup();\n\n                var refSum = ForEachArray();\n                Assert.IsTrue(refSum == ForEachList());\n                Assert.IsTrue(refSum == ForEachHashSet());\n                Assert.IsTrue(refSum == ForEachDictionaryValues());\n                Assert.IsTrue(refSum == ForEachDictionaryKeys());\n                Assert.IsTrue(refSum == ForEachDictionary());\n                Assert.IsTrue(refSum == ForEachIntSet());\n                Assert.IsTrue(refSum == ForEachDictValues());\n                Assert.IsTrue(refSum == ForEachDictFastValues());\n                Assert.IsTrue(refSum == ForEachDictKeys());\n                Assert.IsTrue(refSum == ForEachDict());\n                Assert.IsTrue(refSum == ForEachSymbolDictValues());\n                Assert.IsTrue(refSum == ForEachSymbolDictFastValues());\n            }\n        }\n    }\n\n    //|                        Method | Count |      Mean |    Error |   StdDev |\n    //|------------------------------ |------ |----------:|---------:|---------:|\n    //|        CreateHashSetFromArray | 10000 | 177.68 us | 2.284 us | 2.137 us |\n    //|         CreateIntSetFromArray | 10000 | 127.80 us | 1.310 us | 1.160 us |\n    //| CreateHashSetFromArrayWithAdd | 10000 | 142.21 us | 2.390 us | 2.118 us |\n    //|  CreateIntSetFromArrayWithAdd | 10000 |  93.21 us | 0.503 us | 0.446 us |\n    //|         CreateHashSetFromList | 10000 | 195.84 us | 2.056 us | 1.923 us |\n    //|          CreateIntSetFromList | 10000 | 146.70 us | 2.740 us | 3.040 us |\n    //|  CreateHashSetFromListWithAdd | 10000 | 157.95 us | 1.004 us | 0.939 us |\n    //|   CreateIntSetFromListWithAdd | 10000 | 108.20 us | 0.909 us | 0.850 us |\n\n    [PlainExporter]\n    public class IntSetCreator\n    {\n        int[] m_array;\n        List<int> m_list;\n\n        [Params(10000)]\n        public int Count;\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            m_array = new int[Count].SetByIndex(i => i + 1);\n            m_list = new List<int>(1.UpTo(Count));\n        }\n\n        [Benchmark]\n        public int CreateHashSetFromArray()\n        {\n            return new HashSet<int>(m_array).Count;\n        }\n\n        [Benchmark]\n        public int CreateIntSetFromArray()\n        {\n            return new IntSet(m_array).Count;\n        }\n\n        [Benchmark]\n        public int CreateHashSetFromArrayWithAdd()\n        {\n            var set = new HashSet<int>(m_array.Length);\n            foreach (var x in m_array)\n                set.Add(x);\n            return set.Count;\n        }\n\n        [Benchmark]\n        public int CreateIntSetFromArrayWithAdd()\n        {\n            var set = new IntSet(m_array.Length);\n            foreach (var x in m_array)\n                set.Add(x);\n            return set.Count;\n        }\n\n        [Benchmark]\n        public int CreateHashSetFromList()\n        {\n            return new HashSet<int>(m_list).Count;\n        }\n\n        [Benchmark]\n        public int CreateIntSetFromList()\n        {\n            return new IntSet(m_list).Count;\n        }\n\n        [Benchmark]\n        public int CreateHashSetFromListWithAdd()\n        {\n            var set = new HashSet<int>(m_list.Count);\n            foreach (var x in m_list)\n                set.Add(x);\n            return set.Count;\n        }\n\n        [Benchmark]\n        public int CreateIntSetFromListWithAdd()\n        {\n            var set = new IntSet(m_list.Count);\n            foreach (var x in m_list)\n                set.Add(x);\n            return set.Count;\n        }\n    }\n\n\n    //|               Method | Count |      Mean |     Error |    StdDev |    Median |  Gen 0 | Gen 1 | Gen 2 | Allocated |\n    //|--------------------- |------ |----------:|----------:|----------:|----------:|-------:|------:|------:|----------:|\n    //|                 Loop |    10 |  5.107 ns | 0.0318 ns | 0.0282 ns |  5.093 ns |      - |     - |     - |         - |\n    //|           SetByIndex |    10 | 18.724 ns | 0.3955 ns | 0.7807 ns | 19.057 ns |      - |     - |     - |         - |\n    //|              ForEach |    10 | 28.495 ns | 0.1415 ns | 0.1255 ns | 28.484 ns | 0.0210 |     - |     - |      88 B |\n\n    [PlainExporter]\n    [MemoryDiagnoser]\n    public class ArrayInit\n    {\n        int[] m_array;\n\n        [Params(10)]\n        public int Count;\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            m_array = new int[Count];\n        }\n\n        [Benchmark]\n        public void Loop()\n        {\n            var arr = m_array;\n            var cnt = arr.Length;\n            for (int i = 0; i < cnt; i++)\n                arr[i] = i;\n        }\n\n        [Benchmark]\n        public void SetByIndex()\n        {\n            m_array.SetByIndex(i => i);\n        }\n\n        [Benchmark]\n        public void ForEach()\n        {\n            var arr = m_array;\n            arr.ForEach(i => arr[i] = i);\n        }\n    }\n\n    //|               Method | Count |      Mean |     Error |    StdDev |    Median |  Gen 0 | Gen 1 | Gen 2 | Allocated |\n    //|--------------------- |------ |----------:|----------:|----------:|----------:|-------:|------:|------:|----------:|\n    //|           SumWithFor |    10 |  3.524 ns | 0.0254 ns | 0.0237 ns |  3.519 ns |      - |     - |     - |         - |\n    //|       SumWithForEach |    10 |  2.811 ns | 0.0238 ns | 0.0223 ns |  2.814 ns |      - |     - |     - |         - | // !!! cannot be reproduced, currently runs in 5ns\n    //| SumWithForEachLambda |    10 | 27.273 ns | 0.1075 ns | 0.0898 ns | 27.272 ns | 0.0210 |     - |     - |      88 B |\n    //|     SumWithExtension |    10 | 49.211 ns | 0.3346 ns | 0.2966 ns | 49.188 ns | 0.0076 |     - |     - |      32 B |\n    [PlainExporter]\n    [MemoryDiagnoser]\n    public class ArraySum\n    {\n        int[] m_array;\n\n        [Params(10)]\n        public int Count = 10;\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            m_array = new int[Count].SetByIndex(i => i);\n        }\n\n        [Benchmark]\n        public int SumWithFor()\n        {\n            var arr = m_array;\n            var cnt = arr.Length;\n            var sum = 0;\n            for (int i = 0; i < cnt; i++)\n                sum += arr[i];\n            return sum;\n        }\n\n        [Benchmark]\n        public int SumWithForEach()\n        {\n            var sum = 0;\n            foreach (var x in m_array)\n                sum += x;\n            return sum;\n        }\n\n        [Benchmark]\n        public int SumWithForEachLambda()\n        {\n            var sum = 0;\n            m_array.ForEach(x => sum += x);\n            return sum;\n        }\n\n        [Benchmark]\n        public int SumWithExtension()\n        {\n            return m_array.Sum();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Geometry/PolygonTransform.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET Core SDK = 5.0.201\n\n    // [Host]     : .NET Core 3.1.13 (CoreCLR 4.700.21.11102, CoreFX 4.700.21.11602), X64 RyuJIT\n    //  DefaultJob : .NET Core 3.1.13 (CoreCLR 4.700.21.11102, CoreFX 4.700.21.11602), X64 RyuJIT\n\n    //|              Method | Count |      Mean |    Error |   StdDev |  Gen 0 |  Gen 1 | Gen 2 | Allocated |\n    //|-------------------- |------ |----------:|---------:|---------:|-------:|-------:|------:|----------:|\n    //| TransformMatrix_Map |     5 |  60.41 ns | 0.307 ns | 0.287 ns | 0.0408 |      - |     - |     256 B |\n    //|     TransformMatrix |     5 |  40.59 ns | 0.301 ns | 0.281 ns | 0.0166 |      - |     - |     104 B |\n    //|  TransformShift_Map |     5 |  31.36 ns | 0.113 ns | 0.094 ns | 0.0318 |      - |     - |     200 B |\n    //|      TransformShift |     5 |  16.92 ns | 0.144 ns | 0.128 ns | 0.0166 |      - |     - |     104 B |\n    //| TransformMatrix_Map |    20 | 180.79 ns | 0.921 ns | 0.861 ns | 0.0789 |      - |     - |     496 B |\n    //|     TransformMatrix |    20 | 128.61 ns | 0.418 ns | 0.391 ns | 0.0548 |      - |     - |     344 B |\n    //|  TransformShift_Map |    20 |  71.36 ns | 0.551 ns | 0.515 ns | 0.0701 | 0.0001 |     - |     440 B |\n    //|      TransformShift |    20 |  43.27 ns | 0.820 ns | 0.767 ns | 0.0548 | 0.0001 |     - |     344 B |\n    //| TransformMatrix_Map |   100 | 834.72 ns | 3.112 ns | 2.911 ns | 0.2823 | 0.0010 |     - |    1776 B |\n    //|     TransformMatrix |   100 | 531.93 ns | 1.654 ns | 1.466 ns | 0.2584 | 0.0010 |     - |    1624 B |\n    //|  TransformShift_Map |   100 | 370.42 ns | 1.636 ns | 1.530 ns | 0.2737 | 0.0014 |     - |    1720 B |\n    //|      TransformShift |   100 | 198.36 ns | 0.890 ns | 0.833 ns | 0.2587 | 0.0014 |     - |    1624 B |\n\n    [PlainExporter, MemoryDiagnoser]\n    public class PolygonTransform\n    {\n        public V2d offset = V2d.Zero;\n        public Polygon2d polyArray = new Polygon2d(new V2d[5].SetByIndex(i => new V2d(i)));\n\n        [Params(5, 20, 100)]\n        public int Count;\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            polyArray = new Polygon2d(new V2d[Count].SetByIndex(i => new V2d(i)));\n        }\n\n        [Benchmark]\n        public Polygon2d TransformMatrix()\n        {\n            return polyArray.Transformed(M33d.Translation(offset));\n        }\n\n        [Benchmark]\n        public Polygon2d TransformMatrix_Map()\n        {\n            var m = M33d.Translation(offset);\n            return polyArray.Map(v => m.TransformPos(v));\n        }\n\n        [Benchmark]\n        public Polygon2d TransformShift_Map()\n        {\n            var o = offset;\n            return polyArray.Map(v => v + o);\n        }\n\n        [Benchmark]\n        public Polygon2d TransformShift()\n        {\n            return polyArray.Transformed(new Shift2d(offset));\n        }\n\n        [Benchmark]\n        public Polygon2d InvTransformShift_Indirect()\n        {\n            var trafo = new Shift2d(offset);\n            return polyArray.Transformed(trafo.Inverse);\n        }\n\n        [Benchmark]\n        public Polygon2d InvTransformShift_Direct()\n        {\n            return polyArray.InvTransformed(new Shift2d(offset));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Geometry/RayHitTest.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n\n    //|               Method |     Mean |     Error |    StdDev |   Median | Gen 0 | Gen 1 | Gen 2 | Allocated |\n    //|--------------------- |---------:|----------:|----------:|---------:|------:|------:|------:|----------:|\n    //|         RaySphereHit | 3.228 ms | 0.0176 ms | 0.0156 ms | 3.227 ms |     - |     - |     - |       2 B |\n    //|      RaySphereHit_V2 | 2.300 ms | 0.0457 ms | 0.1205 ms | 2.273 ms |     - |     - |     - |         - |\n    //|    RaySphereHit_Slim | 1.759 ms | 0.0346 ms | 0.0862 ms | 1.715 ms |     - |     - |     - |         - |\n    //| RaySphereHit_Slim_V2 | 1.546 ms | 0.0086 ms | 0.0072 ms | 1.547 ms |     - |     - |     - |       3 B |\n\n    [PlainExporter, MemoryDiagnoser]\n    public class RayHitTest\n    {\n        public Ray3d[] rays;\n\n        public RayHitTest()\n        {\n            var rnd = new RandomSystem(1);\n            // generate random rays within box[-1, 1]\n            rays = new Ray3d[100000].SetByIndex(i => new Ray3d(rnd.UniformV3d() * 2 - 1, rnd.UniformV3dDirection()));\n        }\n        \n        public V3d GetRaySphereHit(Ray3d ray, Sphere3d sphere)\n        {\n            var hit = RayHit3d.MaxRange;\n            if (ray.Hits(sphere, ref hit))\n                return hit.Point;\n            return V3d.Zero;\n        }\n\n        public V3d GetRaySphereHit_Slim(Ray3d ray, Sphere3d sphere)\n        {\n            if (ray.Hits(sphere, out var hitT))\n                return ray.GetPointOnRay(hitT);\n            return V3d.Zero;\n        }\n\n        [Benchmark]\n        public V3d RaySphereHit()\n        {\n            var a = rays;\n            var s = V3d.Zero;\n            var sphere = new Sphere3d(V3d.OOO, 0.8);\n            for (int i = 0; i < a.Length; i++)\n                s += GetRaySphereHit(a[i], sphere);\n            return s;\n        }\n\n        [Benchmark]\n        public V3d RaySphereHit_V2()\n        {\n            var a = rays;\n            var s = V3d.Zero;\n            var sphere = new Sphere3d(V3d.OOO, 0.8);\n            var hit = RayHit3d.MaxRange;\n            for (int i = 0; i < a.Length; i++)\n            {\n                // reset hit\n                hit.T = double.MaxValue;\n                if (a[i].Hits(sphere, ref hit))\n                    s += hit.Point;\n            }\n            return s;\n        }\n\n        [Benchmark]\n        public V3d RaySphereHit_Slim()\n        {\n            var a = rays;\n            var s = V3d.Zero;\n            var sphere = new Sphere3d(V3d.OOO, 0.8);\n            for (int i = 0; i < a.Length; i++)\n                s += GetRaySphereHit_Slim(a[i], sphere);\n            return s;\n        }\n\n        [Benchmark]\n        public V3d RaySphereHit_Slim_V2()\n        {\n            var a = rays;\n            var s = V3d.Zero;\n            var sphere = new Sphere3d(V3d.OOO, 0.8);\n            for (int i = 0; i < a.Length; i++)\n                if (a[i].Hits(sphere, out var hitT))\n                    s += a[i].GetPointOnRay(hitT);\n            return s;\n        }\n\n        [Test]\n        public void RaySphereHit_Test()\n        {\n            var a = RaySphereHit();\n            var b = RaySphereHit_Slim();\n            if (a != b) // results must be identical\n                throw new InvalidOperationException();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Geometry/SolidAngle.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\n\nnamespace Aardvark.Base.Benchmarks.Geometry\n{\n    //BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.5737/22H2/2022Update)\n    //AMD Ryzen 9 7900, 1 CPU, 24 logical and 12 physical cores\n    //.NET SDK 8.0.408\n    //  [Host] : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI\n\n    //Job = InProcess  Toolchain=InProcessEmitToolchain\n\n    //| Method                      | Mean      | Error     | StdDev    |\n    //|---------------------------- |----------:|----------:|----------:|\n    //| Triangle_SolidAngle         |  6.148 ms | 0.0372 ms | 0.0329 ms |\n    //| Triangle_SolidAngle_Method2 | 10.277 ms | 0.0184 ms | 0.0163 ms |\n\n    [InProcess]\n    public class SolidAngle\n    {\n        public IRandomUniform _rnd = new RandomSystem();\n\n        public int Count { get; set; } = 100000;\n\n        [Benchmark]\n        public double Triangle_SolidAngle()\n        {\n            var sum = 0.0;\n            _rnd.ReSeed(123);\n            for (int j = 0; j < Count; j++)\n            {\n                var va = _rnd.UniformV3d();\n                var vb = _rnd.UniformV3d();\n                var vc = _rnd.UniformV3d();\n                sum += Triangle.SolidAngle(va, vb, vc);\n            }\n            return sum;\n\n        }\n\n        [Benchmark]\n        public double Triangle_SolidAngle_Method2()\n        {\n            var sum = 0.0;\n            _rnd.ReSeed(123);\n            for (int j = 0; j < Count; j++)\n            {\n                var va = _rnd.UniformV3d();\n                var vb = _rnd.UniformV3d();\n                var vc = _rnd.UniformV3d();\n                sum += CalcSolidAngle(va, vb, vc);\n            }\n            return sum;\n        }\n\n        /// <summary>\n        /// Numerically less stable version to calculate the solid angle of a triangle\n        /// https://en.wikipedia.org/wiki/Solid_angle#Tetrahedron\n        /// </summary>\n        public static double CalcSolidAngle(V3d va, V3d vb, V3d vc)\n        {\n            var crossVaVc = Vec.Cross(va, vc).Normalized;\n            var crossVaVb = Vec.Cross(va, vb).Normalized;\n            var crossVbVc = Vec.Cross(vb, vc).Normalized;\n\n            var alpha = Vec.Dot(crossVaVc, crossVaVb).AcosClamped();\n            var betha = (-Vec.Dot(crossVaVb, crossVbVc)).AcosClamped();\n            var gamma = Vec.Dot(crossVbVc, crossVaVc).AcosClamped();\n\n            return alpha + betha + gamma - Constant.Pi;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/HashCodeCombine.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing System;\nusing Aardvark.Base;\n\n// NOTE: A namespace with Aardvark.Base.XX automatically allows using Aardvark.Base methods and somehow also prefers \n//       the Aardvark.Base.HashCode combine and does not result in error CS0104: \n//       'HashCode' is an ambiguous reference between 'Aardvark.Base.HashCode' and 'System.HashCode'\nnamespace SomeApp\n//namespace Aardvark.Base.Benchmarks\n{\n    //BenchmarkDotNet=v0.12.0, OS=Windows 10.0.19041\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET Core SDK = 5.0.100\n\n    // [Host]     : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT\n    //  DefaultJob : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT\n\n    //|                  Method | Count |     Mean |    Error |   StdDev |   Gen 0 | Gen 1 | Gen 2 | Allocated |\n    //|------------------------ |------ |---------:|---------:|---------:|--------:|------:|------:|----------:|\n    //|       Combine2_Aardvark | 10000 | 14.88 us | 0.075 us | 0.070 us |       - |     - |     - |         - |\n    //|         Combine2_System | 10000 | 20.48 us | 0.249 us | 0.233 us |       - |     - |     - |         - |\n    //|       Combine3_Aardvark | 10000 | 25.43 us | 0.471 us | 0.462 us | 16.9983 |     - |     - |  106656 B |\n    //| Combine3_Aardvark (NEW) | 10000 | 13.83 us | 0.157 us | 0.147 us |       - |     - |     - |         - |\n    //|         Combine3_System | 10000 | 17.73 us | 0.096 us | 0.090 us |       - |     - |     - |         - |\n    //|       Combine4_Aardvark | 10000 | 22.78 us | 0.209 us | 0.195 us | 12.7258 |     - |     - |   80000 B |\n    //| Combine4_Aardvark (NEW) | 10000 | 13.27 us | 0.076 us | 0.068 us |       - |     - |     - |         - |\n    //|         Combine4_System | 10000 | 17.97 us | 0.303 us | 0.284 us |       - |     - |     - |         - |\n    //|       Combine8_Aardvark | 10000 | 21.55 us | 0.243 us | 0.203 us |  9.5520 |     - |     - |   60000 B |\n    //| Combine8_Aardvark (NEW) | 10000 | 13.32 us | 0.114 us | 0.101 us |       - |     - |     - |         - |\n    //|         Combine8_System | 10000 | 16.31 us | 0.061 us | 0.054 us |       - |     - |     - |         - |\n\n    //|                          Method | Count |        Mean |     Error |    StdDev |    Gen 0 | Gen 1 | Gen 2 | Allocated |\n    //|-------------------------------- |------ |------------:|----------:|----------:|---------:|------:|------:|----------:|\n    //|       M44d_GetHashCode_Aardvark | 10000 |   568.10 us |  7.470 us |  6.630 us | 126.9531 |     - |     - |  800001 B |\n    //| M44d_GetHashCode_Aardvark (NEW) | 10000 |   388.70 us |  3.600 us |  3.370 us |        - |     - |     - |       3 B |\n    //|     M44d_HashCode_SystemDefault | 10000 | 1,268.00 us |  9.000 us |  7.980 us | 228.5156 |     - |     - | 1440009 B |\n    //|      M44d_HashCode_SystemCustom | 10000 |   475.20 us |  3.880 us |  3.630 us |        - |     - |     - |         - |\n    //|        V4d_GetHashCode_Aardvark | 10000 |    85.05 us |  0.612 us |  0.511 us |        - |     - |     - |       1 B |\n    //|      V4d_HashCode_SystemDefault | 10000 | 1,079.64 us | 11.487 us | 10.745 us |  76.1719 |     - |     - |  480009 B |\n    //|       V4d_HashCode_SystemCustom | 10000 |   122.04 us |  2.286 us |  2.245 us |        - |     - |     - |         - |\n\n    [PlainExporter, MemoryDiagnoser]\n    public class HashCodeCombine\n    {\n        public double[] m_data;\n        public M44d[] m_mat;\n        public MyM44d[] m_myMat;\n        public V4d[] m_vec;\n        public MyV4d[] m_myVec;\n\n        [Params(10000)]\n        public int Count;\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            m_data = new double[Count].SetByIndex(i => i + 1);\n            m_mat = new M44d[Count].SetByIndex(i => new M44d(i));\n            m_myMat = new MyM44d[Count].SetByIndex(i => new MyM44d());\n            m_vec = new V4d[Count].SetByIndex(i => new V4d(i));\n            m_myVec = new MyV4d[Count].SetByIndex(i => new MyV4d());\n        }\n\n        [Benchmark]\n        public int Combine2_Aardvark()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 2;)\n                sum += Aardvark.Base.HashCode.Combine(\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode());\n            return sum;\n        }\n\n        //[Benchmark]\n        //public int Combine2_System()\n        //{\n        //    int sum = 0;\n        //    for (int i = 0; i <= m_data.Length - 2;)\n        //        sum += System.HashCode.Combine(\n        //                    m_data[i++],\n        //                    m_data[i++]);\n        //    return sum;\n        //}\n\n        [Benchmark]\n        public int Combine3_Aardvark()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 3;)\n                sum += Aardvark.Base.HashCode.Combine(\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode());\n            return sum;\n        }\n\n        [Benchmark]\n        public int Combine3_System()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 3;)\n                sum += System.HashCode.Combine(\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Combine4_Aardvark()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 4;)\n                sum += Aardvark.Base.HashCode.Combine(\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode());\n            return sum;\n        }\n\n        [Benchmark]\n        public int Combine4_System()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 4;)\n                sum += System.HashCode.Combine(\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Combine8_Aardvark()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 8;)\n                sum += Aardvark.Base.HashCode.Combine(\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode(),\n                            m_data[i++].GetHashCode());\n            return sum;\n        }\n\n        [Benchmark]\n        public int Combine8_System()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 8;)\n                sum += System.HashCode.Combine(\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++],\n                            m_data[i++]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int M44d_GetHashCode_Aardvark()\n        {\n            int sum = 0;\n            for (int i = 0; i < m_mat.Length; i++)\n                sum += m_mat[i].GetHashCode();\n            return sum;\n        }\n\n        [Benchmark]\n        public int M44d_HashCode_SystemDefault()\n        {\n            int sum = 0;\n            for (int i = 0; i < m_myMat.Length; i++)\n                sum += m_myMat[i].GetHashCode();\n            return sum;\n        }\n\n        [Benchmark]\n        public int M44d_HashCode_SystemCustom()\n        {\n            int sum = 0;\n            for (int i = 0; i < m_myMat.Length; i++)\n                sum += m_myMat[i].CustomHashCode();\n            return sum;\n        }\n\n        [Benchmark]\n        public int V4d_GetHashCode_Aardvark()\n        {\n            int sum = 0;\n            for (int i = 0; i < m_vec.Length; i++)\n                sum += m_vec[i].GetHashCode();\n            return sum;\n        }\n\n        [Benchmark]\n        public int V4d_HashCode_SystemDefault()\n        {\n            int sum = 0;\n            for (int i = 0; i < m_myVec.Length; i++)\n                sum += m_myVec[i].GetHashCode();\n            return sum;\n        }\n\n        [Benchmark]\n        public int V4d_HashCode_SystemCustom()\n        {\n            int sum = 0;\n            for (int i = 0; i < m_myVec.Length; i++)\n                sum += m_myVec[i].CustomHashCode();\n            return sum;\n        }\n\n        public readonly struct MyM44d\n        {\n\n#pragma warning disable CS0649\n            readonly double x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;\n#pragma warning restore CS0649\n\n            public int CustomHashCode()\n            {\n                return System.HashCode.Combine(\n                            System.HashCode.Combine(x0, x1, x2, x3, x4, x5, x6, x7),\n                            System.HashCode.Combine(x8, x9, x10, x11, x12, x13, x14, x15));\n            }\n        }\n\n        public readonly struct MyV4d\n        {\n#pragma warning disable CS0649\n            readonly double x0, x1, x2, x3;\n#pragma warning restore CS0649\n\n            public int CustomHashCode()\n            {\n                return System.HashCode.Combine(x0, x1, x2, x3);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Hashes.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Security.Cryptography;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base.Benchmarks\n{\n\n    //BenchmarkDotNet v0.13.9+228a464e8be6c580ad9408e98f18813f6407fb5a, Windows 10 (10.0.19045.4412/22H2/2022Update)\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET SDK 6.0.422\n    //  [Host]     : .NET 6.0.30 (6.0.3024.21525), X64 RyuJIT AVX2\n    //  DefaultJob : .NET 6.0.30 (6.0.3024.21525), X64 RyuJIT AVX2\n\n\n    //| Method     | Count | Mean       | Error     | StdDev    | Median     | Code Size | Gen0   | Allocated |\n    //|----------- |------ |-----------:|----------:|----------:|-----------:|----------:|-------:|----------:|\n    //| SHA1_Net48 | 16    |   788.3 ns |  10.64 ns |   9.43 ns |   788.6 ns |     262 B | 0.0629 |     400 B |\n    //| SHA1_Array | 16    |   440.3 ns |   6.48 ns |   5.41 ns |   437.2 ns |     107 B | 0.0076 |      48 B |\n    //| SHA1_T     | 16    |   406.7 ns |   8.08 ns |  13.04 ns |   403.7 ns |     149 B | 0.0076 |      48 B |\n    //| SHA1_Net48 | 128   | 1,566.4 ns |  30.87 ns |  65.11 ns | 1,541.1 ns |     262 B | 0.0629 |     400 B |\n    //| SHA1_Array | 128   | 1,090.6 ns |   9.32 ns |   8.26 ns | 1,090.7 ns |     107 B | 0.0076 |      48 B |\n    //| SHA1_T     | 128   | 1,063.4 ns |  17.39 ns |  17.85 ns | 1,060.4 ns |     149 B | 0.0076 |      48 B |\n    //| SHA1_Net48 | 1024  | 6,761.1 ns | 134.11 ns | 143.50 ns | 6,717.4 ns |     262 B | 0.0610 |     400 B |\n    //| SHA1_Array | 1024  | 6,169.2 ns |  80.47 ns |  75.27 ns | 6,140.3 ns |     107 B | 0.0076 |      48 B |\n    //| SHA1_T     | 1024  | 6,128.8 ns |  68.52 ns |  57.22 ns | 6,116.5 ns |     149 B | 0.0076 |      48 B |\n    [MemoryDiagnoser, DisassemblyDiagnoser]\n    public class HashBench\n    {\n        internal static unsafe T UseAsStream<T>(Array data, Func<UnmanagedMemoryStream, T> action)\n        {\n            var gc = GCHandle.Alloc(data, GCHandleType.Pinned);\n            var l = data.GetType().GetElementType().GetCLRSize() * data.Length;\n            try\n            {\n                using (var stream =\n                       new UnmanagedMemoryStream(((byte*)gc.AddrOfPinnedObject())!, l, l, FileAccess.Read))\n                {\n                    return action(stream);\n                }\n            }\n            finally\n            {\n                gc.Free();\n            }\n        }\n\n        public static unsafe byte[] ComputeSHA1HashNet48(Array data)\n        {\n            using (var sha = SHA1.Create())\n            {\n                return UseAsStream(data, (stream) => sha.ComputeHash(stream));\n            }\n        }\n\n        [Params(16, 128, 1024)]\n        public int Count;\n\n        float[] data;\n        Array dataArr;\n\n        [GlobalSetup]\n        public void Init()\n        {\n            data = new float[Count];\n            for (int i = 0; i < data.Length; i++)\n                data[i] = Random.Shared.NextSingle();\n            dataArr = data;\n        }\n\n        [Benchmark]\n        public byte[] SHA1_Net48()\n        {\n            return ComputeSHA1HashNet48(data);\n        }\n\n        [Benchmark]\n        public byte[] SHA1_Array()\n        {\n            return dataArr.ComputeSHA1Hash();\n        }\n\n        [Benchmark]\n        public byte[] SHA1_T()\n        {\n            return data.ComputeSHA1Hash();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Indexers_auto.cs",
    "content": "using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // Testing variants for indexer methods for matrix and vector types.\n    // There are three variants:\n    // (*) Flow control with switch (original method)\n    // (*) Flow control flow with if\n    // (*) Unsafe with pointers\n    // Using \"switch\" is problematic because it is never actually inlined (despite AggressiveInlining).\n    // Flow control with \"if\" seems strictly better for this reason, however there are noticable differences\n    // between different dimensions, i.e. the number of branches. In the case of element indexers, the \"if\" variant actually isn't always better.\n    // The final method to be tested uses unsafe and direct access with pointers. As expect this method is much more efficient than the other\n    // two in most cases. An exception to this are the row and column indexers for 4x4 matrices. Here, the flow control variants actually perform\n    // slightly better.\n\n    #region Indexers2\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n         //<DebugType>pdbonly</DebugType>\n         //<DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    //[DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class Indexers2\n    {\n        #region Vector\n\n        [StructLayout(LayoutKind.Sequential)]\n        private readonly struct Vector\n        {\n            #region Fields\n\n            public readonly double X, Y;\n\n            #endregion\n\n            #region Constructor\n\n            public Vector(double[] elems)\n            {\n                X = elems[0];\n                Y = elems[1];\n            }\n\n            #endregion\n\n            #region Indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return X;\n                    case 1: return Y;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemIf(int index)\n            {\n                if (index == 0) return X;\n                else if (index == 1) return Y;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe double ElemUnsafe(int index)\n            {\n                fixed (double* ptr = &X) { return ptr[index]; }\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        #region Matrix\n\n        [StructLayout(LayoutKind.Sequential)]\n        private readonly struct Matrix\n        {\n            #region Fields\n\n            public readonly double M00, M01;\n            public readonly double M10, M11;\n\n            #endregion\n\n            #region Rows\n\n            public V2d R0\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V2d( M00,  M01); }\n            }\n\n            public V2d R1\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V2d( M10,  M11); }\n            }\n\n            #endregion\n\n            #region Columns\n\n            public V2d C0\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V2d( M00,  M10); }\n            }\n\n            public V2d C1\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V2d( M01,  M11); }\n            }\n\n            #endregion\n\n            #region Constructor\n\n            public Matrix(double[] elems)\n            {\n                M00 = elems[0]; M01 = elems[1]; \n                M10 = elems[2]; M11 = elems[3]; \n            }\n\n            #endregion\n\n            #region Element indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemSwitch(int row, int column)\n            {\n                switch (row)\n                {\n                    case 0:\n                        switch (column)\n                        {\n                            case 0: return M00;\n                            case 1: return M01;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    case 1:\n                        switch (column)\n                        {\n                            case 0: return M10;\n                            case 1: return M11;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemIf(int row, int column)\n            {\n                if (row == 0)\n                {\n                    if (column == 0) return M00;\n                    else if (column == 1) return M01;\n                    else throw new IndexOutOfRangeException();\n                }\n                else if (row == 1)\n                {\n                    if (column == 0) return M10;\n                    else if (column == 1) return M11;\n                    else throw new IndexOutOfRangeException();\n                }\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe double ElemUnsafe(int row, int column)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return ptr[row * 2 + column];\n                }\n            }\n\n            #endregion\n\n            #region Row indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V2d RowSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return R0;\n                    case 1: return R1;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V2d RowIf(int index)\n            {\n                if (index == 0) return R0;\n                else if (index == 1) return R1;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe V2d RowUnsafe(int index)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return new V2d(ptr[index * 2], ptr[index * 2 + 1]);\n                }\n            }\n\n            #endregion\n\n            #region Column indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V2d ColSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return C0;\n                    case 1: return C1;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V2d ColIf(int index)\n            {\n                if (index == 0) return C0;\n                else if (index == 1) return C1;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe V2d ColUnsafe(int index)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return new V2d(ptr[index], ptr[index + 2]);\n                }\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        const int count = 1000000;\n        readonly V2i[] indices = new V2i[count];\n        readonly Vector[] vectors = new Vector[count];\n        readonly Matrix[] matrices = new Matrix[count];\n\n        public Indexers2()\n        {\n            var rnd = new RandomSystem(1);\n            indices.SetByIndex(i => rnd.UniformV2i(2));\n            vectors.SetByIndex(i => new Vector(rnd.CreateUniformDoubleArray(2)));\n            matrices.SetByIndex(i => new Matrix(rnd.CreateUniformDoubleArray(4)));\n        }\n\n        #region Tests\n\n        [Test]\n        public void VectorElementIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var vec = vectors[i];\n\n                var mif = vec.ElemIf(idx.X);\n                var msw = vec.ElemSwitch(idx.X);\n                var mus = vec.ElemUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixElementIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.ElemIf(idx.X, idx.Y);\n                var msw = mat.ElemSwitch(idx.X, idx.Y);\n                var mus = mat.ElemUnsafe(idx.X, idx.Y);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixRowIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.RowIf(idx.X);\n                var msw = mat.RowSwitch(idx.X);\n                var mus = mat.RowUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixColumnIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.ColIf(idx.X);\n                var msw = mat.ColSwitch(idx.X);\n                var mus = mat.ColUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        #endregion\n\n        #region Benchmarks for Vector Element Indexers\n\n        [Benchmark]\n        public double VectorElementIndexerSwitch()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemSwitch(idx);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double VectorElementIndexerIf()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemIf(idx);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double VectorElementIndexerUnsafe()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemUnsafe(idx);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Element Indexers\n\n        [Benchmark]\n        public double MatrixElementIndexerSwitch()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemSwitch(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double MatrixElementIndexerIf()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemIf(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double MatrixElementIndexerUnsafe()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemUnsafe(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Row Indexers\n\n        [Benchmark]\n        public V2d MatrixRowIndexerSwitch()\n        {\n            V2d accum = V2d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowSwitch(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V2d MatrixRowIndexerIf()\n        {\n            V2d accum = V2d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowIf(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V2d MatrixRowIndexerUnsafe()\n        {\n            V2d accum = V2d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowUnsafe(indices[i].X);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Column Indexers\n\n        [Benchmark]\n        public V2d MatrixColumnIndexerSwitch()\n        {\n            V2d accum = V2d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColSwitch(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V2d MatrixColumnIndexerIf()\n        {\n            V2d accum = V2d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColIf(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V2d MatrixColumnIndexerUnsafe()\n        {\n            V2d accum = V2d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColUnsafe(indices[i].X);\n            }\n\n            return accum;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Indexers3\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n         //<DebugType>pdbonly</DebugType>\n         //<DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    //[DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class Indexers3\n    {\n        #region Vector\n\n        [StructLayout(LayoutKind.Sequential)]\n        private readonly struct Vector\n        {\n            #region Fields\n\n            public readonly double X, Y, Z;\n\n            #endregion\n\n            #region Constructor\n\n            public Vector(double[] elems)\n            {\n                X = elems[0];\n                Y = elems[1];\n                Z = elems[2];\n            }\n\n            #endregion\n\n            #region Indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return X;\n                    case 1: return Y;\n                    case 2: return Z;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemIf(int index)\n            {\n                if (index == 0) return X;\n                else if (index == 1) return Y;\n                else if (index == 2) return Z;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe double ElemUnsafe(int index)\n            {\n                fixed (double* ptr = &X) { return ptr[index]; }\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        #region Matrix\n\n        [StructLayout(LayoutKind.Sequential)]\n        private readonly struct Matrix\n        {\n            #region Fields\n\n            public readonly double M00, M01, M02;\n            public readonly double M10, M11, M12;\n            public readonly double M20, M21, M22;\n\n            #endregion\n\n            #region Rows\n\n            public V3d R0\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V3d( M00,  M01,  M02); }\n            }\n\n            public V3d R1\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V3d( M10,  M11,  M12); }\n            }\n\n            public V3d R2\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V3d( M20,  M21,  M22); }\n            }\n\n            #endregion\n\n            #region Columns\n\n            public V3d C0\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V3d( M00,  M10,  M20); }\n            }\n\n            public V3d C1\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V3d( M01,  M11,  M21); }\n            }\n\n            public V3d C2\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V3d( M02,  M12,  M22); }\n            }\n\n            #endregion\n\n            #region Constructor\n\n            public Matrix(double[] elems)\n            {\n                M00 = elems[0]; M01 = elems[1]; M02 = elems[2]; \n                M10 = elems[3]; M11 = elems[4]; M12 = elems[5]; \n                M20 = elems[6]; M21 = elems[7]; M22 = elems[8]; \n            }\n\n            #endregion\n\n            #region Element indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemSwitch(int row, int column)\n            {\n                switch (row)\n                {\n                    case 0:\n                        switch (column)\n                        {\n                            case 0: return M00;\n                            case 1: return M01;\n                            case 2: return M02;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    case 1:\n                        switch (column)\n                        {\n                            case 0: return M10;\n                            case 1: return M11;\n                            case 2: return M12;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    case 2:\n                        switch (column)\n                        {\n                            case 0: return M20;\n                            case 1: return M21;\n                            case 2: return M22;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemIf(int row, int column)\n            {\n                if (row == 0)\n                {\n                    if (column == 0) return M00;\n                    else if (column == 1) return M01;\n                    else if (column == 2) return M02;\n                    else throw new IndexOutOfRangeException();\n                }\n                else if (row == 1)\n                {\n                    if (column == 0) return M10;\n                    else if (column == 1) return M11;\n                    else if (column == 2) return M12;\n                    else throw new IndexOutOfRangeException();\n                }\n                else if (row == 2)\n                {\n                    if (column == 0) return M20;\n                    else if (column == 1) return M21;\n                    else if (column == 2) return M22;\n                    else throw new IndexOutOfRangeException();\n                }\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe double ElemUnsafe(int row, int column)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return ptr[row * 3 + column];\n                }\n            }\n\n            #endregion\n\n            #region Row indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V3d RowSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return R0;\n                    case 1: return R1;\n                    case 2: return R2;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V3d RowIf(int index)\n            {\n                if (index == 0) return R0;\n                else if (index == 1) return R1;\n                else if (index == 2) return R2;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe V3d RowUnsafe(int index)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return new V3d(ptr[index * 3], ptr[index * 3 + 1], ptr[index * 3 + 2]);\n                }\n            }\n\n            #endregion\n\n            #region Column indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V3d ColSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return C0;\n                    case 1: return C1;\n                    case 2: return C2;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V3d ColIf(int index)\n            {\n                if (index == 0) return C0;\n                else if (index == 1) return C1;\n                else if (index == 2) return C2;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe V3d ColUnsafe(int index)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return new V3d(ptr[index], ptr[index + 3], ptr[index + 6]);\n                }\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        const int count = 1000000;\n        readonly V2i[] indices = new V2i[count];\n        readonly Vector[] vectors = new Vector[count];\n        readonly Matrix[] matrices = new Matrix[count];\n\n        public Indexers3()\n        {\n            var rnd = new RandomSystem(1);\n            indices.SetByIndex(i => rnd.UniformV2i(3));\n            vectors.SetByIndex(i => new Vector(rnd.CreateUniformDoubleArray(3)));\n            matrices.SetByIndex(i => new Matrix(rnd.CreateUniformDoubleArray(9)));\n        }\n\n        #region Tests\n\n        [Test]\n        public void VectorElementIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var vec = vectors[i];\n\n                var mif = vec.ElemIf(idx.X);\n                var msw = vec.ElemSwitch(idx.X);\n                var mus = vec.ElemUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixElementIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.ElemIf(idx.X, idx.Y);\n                var msw = mat.ElemSwitch(idx.X, idx.Y);\n                var mus = mat.ElemUnsafe(idx.X, idx.Y);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixRowIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.RowIf(idx.X);\n                var msw = mat.RowSwitch(idx.X);\n                var mus = mat.RowUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixColumnIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.ColIf(idx.X);\n                var msw = mat.ColSwitch(idx.X);\n                var mus = mat.ColUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        #endregion\n\n        #region Benchmarks for Vector Element Indexers\n\n        [Benchmark]\n        public double VectorElementIndexerSwitch()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemSwitch(idx);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double VectorElementIndexerIf()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemIf(idx);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double VectorElementIndexerUnsafe()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemUnsafe(idx);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Element Indexers\n\n        [Benchmark]\n        public double MatrixElementIndexerSwitch()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemSwitch(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double MatrixElementIndexerIf()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemIf(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double MatrixElementIndexerUnsafe()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemUnsafe(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Row Indexers\n\n        [Benchmark]\n        public V3d MatrixRowIndexerSwitch()\n        {\n            V3d accum = V3d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowSwitch(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V3d MatrixRowIndexerIf()\n        {\n            V3d accum = V3d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowIf(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V3d MatrixRowIndexerUnsafe()\n        {\n            V3d accum = V3d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowUnsafe(indices[i].X);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Column Indexers\n\n        [Benchmark]\n        public V3d MatrixColumnIndexerSwitch()\n        {\n            V3d accum = V3d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColSwitch(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V3d MatrixColumnIndexerIf()\n        {\n            V3d accum = V3d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColIf(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V3d MatrixColumnIndexerUnsafe()\n        {\n            V3d accum = V3d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColUnsafe(indices[i].X);\n            }\n\n            return accum;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n    #region Indexers4\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n         //<DebugType>pdbonly</DebugType>\n         //<DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    //[DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class Indexers4\n    {\n        #region Vector\n\n        [StructLayout(LayoutKind.Sequential)]\n        private readonly struct Vector\n        {\n            #region Fields\n\n            public readonly double X, Y, Z, W;\n\n            #endregion\n\n            #region Constructor\n\n            public Vector(double[] elems)\n            {\n                X = elems[0];\n                Y = elems[1];\n                Z = elems[2];\n                W = elems[3];\n            }\n\n            #endregion\n\n            #region Indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return X;\n                    case 1: return Y;\n                    case 2: return Z;\n                    case 3: return W;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemIf(int index)\n            {\n                if (index == 0) return X;\n                else if (index == 1) return Y;\n                else if (index == 2) return Z;\n                else if (index == 3) return W;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe double ElemUnsafe(int index)\n            {\n                fixed (double* ptr = &X) { return ptr[index]; }\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        #region Matrix\n\n        [StructLayout(LayoutKind.Sequential)]\n        private readonly struct Matrix\n        {\n            #region Fields\n\n            public readonly double M00, M01, M02, M03;\n            public readonly double M10, M11, M12, M13;\n            public readonly double M20, M21, M22, M23;\n            public readonly double M30, M31, M32, M33;\n\n            #endregion\n\n            #region Rows\n\n            public V4d R0\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V4d( M00,  M01,  M02,  M03); }\n            }\n\n            public V4d R1\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V4d( M10,  M11,  M12,  M13); }\n            }\n\n            public V4d R2\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V4d( M20,  M21,  M22,  M23); }\n            }\n\n            public V4d R3\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V4d( M30,  M31,  M32,  M33); }\n            }\n\n            #endregion\n\n            #region Columns\n\n            public V4d C0\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V4d( M00,  M10,  M20,  M30); }\n            }\n\n            public V4d C1\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V4d( M01,  M11,  M21,  M31); }\n            }\n\n            public V4d C2\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V4d( M02,  M12,  M22,  M32); }\n            }\n\n            public V4d C3\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new V4d( M03,  M13,  M23,  M33); }\n            }\n\n            #endregion\n\n            #region Constructor\n\n            public Matrix(double[] elems)\n            {\n                M00 = elems[0]; M01 = elems[1]; M02 = elems[2]; M03 = elems[3]; \n                M10 = elems[4]; M11 = elems[5]; M12 = elems[6]; M13 = elems[7]; \n                M20 = elems[8]; M21 = elems[9]; M22 = elems[10]; M23 = elems[11]; \n                M30 = elems[12]; M31 = elems[13]; M32 = elems[14]; M33 = elems[15]; \n            }\n\n            #endregion\n\n            #region Element indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemSwitch(int row, int column)\n            {\n                switch (row)\n                {\n                    case 0:\n                        switch (column)\n                        {\n                            case 0: return M00;\n                            case 1: return M01;\n                            case 2: return M02;\n                            case 3: return M03;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    case 1:\n                        switch (column)\n                        {\n                            case 0: return M10;\n                            case 1: return M11;\n                            case 2: return M12;\n                            case 3: return M13;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    case 2:\n                        switch (column)\n                        {\n                            case 0: return M20;\n                            case 1: return M21;\n                            case 2: return M22;\n                            case 3: return M23;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    case 3:\n                        switch (column)\n                        {\n                            case 0: return M30;\n                            case 1: return M31;\n                            case 2: return M32;\n                            case 3: return M33;\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemIf(int row, int column)\n            {\n                if (row == 0)\n                {\n                    if (column == 0) return M00;\n                    else if (column == 1) return M01;\n                    else if (column == 2) return M02;\n                    else if (column == 3) return M03;\n                    else throw new IndexOutOfRangeException();\n                }\n                else if (row == 1)\n                {\n                    if (column == 0) return M10;\n                    else if (column == 1) return M11;\n                    else if (column == 2) return M12;\n                    else if (column == 3) return M13;\n                    else throw new IndexOutOfRangeException();\n                }\n                else if (row == 2)\n                {\n                    if (column == 0) return M20;\n                    else if (column == 1) return M21;\n                    else if (column == 2) return M22;\n                    else if (column == 3) return M23;\n                    else throw new IndexOutOfRangeException();\n                }\n                else if (row == 3)\n                {\n                    if (column == 0) return M30;\n                    else if (column == 1) return M31;\n                    else if (column == 2) return M32;\n                    else if (column == 3) return M33;\n                    else throw new IndexOutOfRangeException();\n                }\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe double ElemUnsafe(int row, int column)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return ptr[row * 4 + column];\n                }\n            }\n\n            #endregion\n\n            #region Row indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V4d RowSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return R0;\n                    case 1: return R1;\n                    case 2: return R2;\n                    case 3: return R3;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V4d RowIf(int index)\n            {\n                if (index == 0) return R0;\n                else if (index == 1) return R1;\n                else if (index == 2) return R2;\n                else if (index == 3) return R3;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe V4d RowUnsafe(int index)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return new V4d(ptr[index * 4], ptr[index * 4 + 1], ptr[index * 4 + 2], ptr[index * 4 + 3]);\n                }\n            }\n\n            #endregion\n\n            #region Column indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V4d ColSwitch(int index)\n            {\n                switch (index)\n                {\n                    case 0: return C0;\n                    case 1: return C1;\n                    case 2: return C2;\n                    case 3: return C3;\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public V4d ColIf(int index)\n            {\n                if (index == 0) return C0;\n                else if (index == 1) return C1;\n                else if (index == 2) return C2;\n                else if (index == 3) return C3;\n                else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe V4d ColUnsafe(int index)\n            {\n                fixed (double* ptr = &M00)\n                {\n                    return new V4d(ptr[index], ptr[index + 4], ptr[index + 8], ptr[index + 12]);\n                }\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        const int count = 1000000;\n        readonly V2i[] indices = new V2i[count];\n        readonly Vector[] vectors = new Vector[count];\n        readonly Matrix[] matrices = new Matrix[count];\n\n        public Indexers4()\n        {\n            var rnd = new RandomSystem(1);\n            indices.SetByIndex(i => rnd.UniformV2i(4));\n            vectors.SetByIndex(i => new Vector(rnd.CreateUniformDoubleArray(4)));\n            matrices.SetByIndex(i => new Matrix(rnd.CreateUniformDoubleArray(16)));\n        }\n\n        #region Tests\n\n        [Test]\n        public void VectorElementIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var vec = vectors[i];\n\n                var mif = vec.ElemIf(idx.X);\n                var msw = vec.ElemSwitch(idx.X);\n                var mus = vec.ElemUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixElementIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.ElemIf(idx.X, idx.Y);\n                var msw = mat.ElemSwitch(idx.X, idx.Y);\n                var mus = mat.ElemUnsafe(idx.X, idx.Y);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixRowIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.RowIf(idx.X);\n                var msw = mat.RowSwitch(idx.X);\n                var mus = mat.RowUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixColumnIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.ColIf(idx.X);\n                var msw = mat.ColSwitch(idx.X);\n                var mus = mat.ColUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        #endregion\n\n        #region Benchmarks for Vector Element Indexers\n\n        [Benchmark]\n        public double VectorElementIndexerSwitch()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemSwitch(idx);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double VectorElementIndexerIf()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemIf(idx);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double VectorElementIndexerUnsafe()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].ElemUnsafe(idx);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Element Indexers\n\n        [Benchmark]\n        public double MatrixElementIndexerSwitch()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemSwitch(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double MatrixElementIndexerIf()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemIf(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public double MatrixElementIndexerUnsafe()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].ElemUnsafe(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Row Indexers\n\n        [Benchmark]\n        public V4d MatrixRowIndexerSwitch()\n        {\n            V4d accum = V4d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowSwitch(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V4d MatrixRowIndexerIf()\n        {\n            V4d accum = V4d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowIf(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V4d MatrixRowIndexerUnsafe()\n        {\n            V4d accum = V4d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].RowUnsafe(indices[i].X);\n            }\n\n            return accum;\n        }\n\n        #endregion\n\n        #region Benchmarks for Matrix Column Indexers\n\n        [Benchmark]\n        public V4d MatrixColumnIndexerSwitch()\n        {\n            V4d accum = V4d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColSwitch(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V4d MatrixColumnIndexerIf()\n        {\n            V4d accum = V4d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColIf(indices[i].X);\n            }\n\n            return accum;\n        }\n\n\n        [Benchmark]\n        public V4d MatrixColumnIndexerUnsafe()\n        {\n            V4d accum = V4d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].ColUnsafe(indices[i].X);\n            }\n\n            return accum;\n        }\n\n        #endregion\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Indexers_template.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // Testing variants for indexer methods for matrix and vector types.\n    // There are three variants:\n    // (*) Flow control with switch (original method)\n    // (*) Flow control flow with if\n    // (*) Unsafe with pointers\n    // Using \"switch\" is problematic because it is never actually inlined (despite AggressiveInlining).\n    // Flow control with \"if\" seems strictly better for this reason, however there are noticable differences\n    // between different dimensions, i.e. the number of branches. In the case of element indexers, the \"if\" variant actually isn't always better.\n    // The final method to be tested uses unsafe and direct access with pointers. As expect this method is much more efficient than the other\n    // two in most cases. An exception to this are the row and column indexers for 4x4 matrices. Here, the flow control variants actually perform\n    // slightly better.\n\n    //# string[] methods = new[] { \"Switch\", \"If\", \"Unsafe\" };\n    //# Action comma = () => Out(\", \");\n    //# Action el = () => Out(\"else \");\n    //# for (int d = 2; d <= 4; d++) {\n    //# var n = d;\n    //# var m = d;\n    //# var nm = n * m;\n    //# var type = \"Indexers\" + d;\n    //# var vtype = \"Vector\";\n    //# var nmtype = \"Matrix\";\n    //# var vntype = \"V\" + n + \"d\";\n    //# var vmtype = \"V\" + m + \"d\";\n    //# var fields = Meta.VecFields.Take(d).ToArray();\n    //# var vgetptr = \"&\" + fields[0];\n    //# var mgetptr = \"&M00\";\n    #region __type__\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n         //<DebugType>pdbonly</DebugType>\n         //<DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    //[DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class __type__\n    {\n        #region __vtype__\n\n        [StructLayout(LayoutKind.Sequential)]\n        private readonly struct __vtype__\n        {\n            #region Fields\n\n            public readonly double /*# fields.ForEach(f => { */__f__/*# }, comma); */;\n\n            #endregion\n\n            #region Constructor\n\n            public __vtype__(double[] elems)\n            {\n                //# fields.ForEach((f, i) => {\n                __f__ = elems[__i__];\n                //# });\n            }\n\n            #endregion\n\n            #region Indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemSwitch(int index)\n            {\n                switch (index)\n                {\n                    //# fields.ForEach((f, i) => {\n                    case __i__: return __f__;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemIf(int index)\n            {\n                /*# fields.ForEach((f, i) => { */if (index == __i__) return __f__;\n                /*# }, el); */else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe double ElemUnsafe(int index)\n            {\n                fixed (double* ptr = __vgetptr__) { return ptr[index]; }\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        #region __nmtype__\n\n        [StructLayout(LayoutKind.Sequential)]\n        private readonly struct __nmtype__\n        {\n            #region Fields\n\n            //# n.ForEach(i => {\n            public readonly double /*# d.ForEach(j => { */M__i____j__/*# }, comma); */;\n            //# });\n\n            #endregion\n\n            #region Rows\n\n            //# n.ForEach(i => {\n            public __vmtype__ R__i__\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new __vmtype__(/*# m.ForEach(j => {*/ M__i____j__/*#}, comma); */); }\n            }\n\n            //# });\n            #endregion\n\n            #region Columns\n\n            //# n.ForEach(j => {\n            public __vntype__ C__j__\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get { return new __vntype__(/*# n.ForEach(i => {*/ M__i____j__/*#}, comma); */); }\n            }\n\n            //# });\n            #endregion\n\n            #region Constructor\n\n            public __nmtype__(double[] elems)\n            {\n                //# n.ForEach(i => {\n                /*# m.ForEach(j => { var idx = i * d + j; */M__i____j__ = elems[__idx__]; /*# });*/\n                //# });\n            }\n\n            #endregion\n\n            #region Element indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemSwitch(int row, int column)\n            {\n                switch (row)\n                {\n                    //# n.ForEach(r => {\n                    case __r__:\n                        switch (column)\n                        {\n                            //# m.ForEach(c => {\n                            case __c__: return M__r____c__;\n                            //# });\n                            default: throw new IndexOutOfRangeException();\n                        }\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public double ElemIf(int row, int column)\n            {\n                /*# n.ForEach(i => { */if (row == __i__)\n                {\n                    /*# m.ForEach(j => { */if (column == __j__) return M__i____j__;\n                    /*# }, el); */else throw new IndexOutOfRangeException();\n                }\n                /*# }, el); */else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe double ElemUnsafe(int row, int column)\n            {\n                fixed (double* ptr = __mgetptr__)\n                {\n                    return ptr[row * __d__ + column];\n                }\n            }\n\n            #endregion\n\n            #region Row indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public __vmtype__ RowSwitch(int index)\n            {\n                switch (index)\n                {\n                    //# n.ForEach(i => {\n                    case __i__: return R__i__;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public __vmtype__ RowIf(int index)\n            {\n                /*# n.ForEach(i => { */if (index == __i__) return R__i__;\n                /*# }, el); */else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe __vmtype__ RowUnsafe(int index)\n            {\n                fixed (double* ptr = __mgetptr__)\n                {\n                    return new __vmtype__(/*# m.ForEach(j => {\n                        */ptr[index * __d__/*#\n                        if (j > 0) {*/ + __j__/*#\n                        }*/]/*# }, comma);*/);\n                }\n            }\n\n            #endregion\n\n            #region Column indexers\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public __vntype__ ColSwitch(int index)\n            {\n                switch (index)\n                {\n                    //# m.ForEach(i => {\n                    case __i__: return C__i__;\n                    //# });\n                    default: throw new IndexOutOfRangeException();\n                }\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public __vntype__ ColIf(int index)\n            {\n                /*# m.ForEach(i => { */if (index == __i__) return C__i__;\n                /*# }, el); */else throw new IndexOutOfRangeException();\n            }\n\n            [MethodImpl(MethodImplOptions.AggressiveInlining)]\n            public unsafe __vntype__ ColUnsafe(int index)\n            {\n                fixed (double* ptr = __mgetptr__)\n                {\n                    return new __vntype__(/*# n.ForEach(i => {\n                        var offset = i * d;\n                        */ptr[index/*#\n                        if (offset > 0) {*/ + __offset__/*#\n                        }*/]/*# }, comma);*/);\n                }\n            }\n\n            #endregion\n        }\n\n        #endregion\n\n        const int count = 1000000;\n        readonly V2i[] indices = new V2i[count];\n        readonly __vtype__[] vectors = new __vtype__[count];\n        readonly __nmtype__[] matrices = new __nmtype__[count];\n\n        public __type__()\n        {\n            var rnd = new RandomSystem(1);\n            indices.SetByIndex(i => rnd.UniformV2i(__n__));\n            vectors.SetByIndex(i => new __vtype__(rnd.CreateUniformDoubleArray(__n__)));\n            matrices.SetByIndex(i => new __nmtype__(rnd.CreateUniformDoubleArray(__nm__)));\n        }\n\n        #region Tests\n\n        [Test]\n        public void VectorElementIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var vec = vectors[i];\n\n                var mif = vec.ElemIf(idx.X);\n                var msw = vec.ElemSwitch(idx.X);\n                var mus = vec.ElemUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixElementIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.ElemIf(idx.X, idx.Y);\n                var msw = mat.ElemSwitch(idx.X, idx.Y);\n                var mus = mat.ElemUnsafe(idx.X, idx.Y);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixRowIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.RowIf(idx.X);\n                var msw = mat.RowSwitch(idx.X);\n                var mus = mat.RowUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        [Test]\n        public void MatrixColumnIndexerCorrectness()\n        {\n            for (int i = 0; i < count / 10; i++)\n            {\n                var idx = indices[i];\n                var mat = matrices[i];\n\n                var mif = mat.ColIf(idx.X);\n                var msw = mat.ColSwitch(idx.X);\n                var mus = mat.ColUnsafe(idx.X);\n                Assert.AreEqual(mif, msw);\n                Assert.AreEqual(mif, mus);\n            }\n        }\n\n        #endregion\n\n        #region Benchmarks for Vector Element Indexers\n\n        //# methods.ForEach(mth => {\n        [Benchmark]\n        public double VectorElementIndexer__mth__()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i].X;\n                accum += vectors[i].Elem__mth__(idx);\n            }\n\n            return accum;\n        }\n\n        //# });\n        #endregion\n\n        #region Benchmarks for Matrix Element Indexers\n\n        //# methods.ForEach(mth => {\n        [Benchmark]\n        public double MatrixElementIndexer__mth__()\n        {\n            double accum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                var idx = indices[i];\n                accum += matrices[i].Elem__mth__(idx.X, idx.Y);\n            }\n\n            return accum;\n        }\n\n        //# });\n        #endregion\n\n        #region Benchmarks for Matrix Row Indexers\n        //# methods.ForEach(mth => {\n\n        [Benchmark]\n        public __vmtype__ MatrixRowIndexer__mth__()\n        {\n            __vmtype__ accum = __vmtype__.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].Row__mth__(indices[i].X);\n            }\n\n            return accum;\n        }\n\n        //# });\n        #endregion\n\n        #region Benchmarks for Matrix Column Indexers\n        //# methods.ForEach(mth => {\n\n        [Benchmark]\n        public __vntype__ MatrixColumnIndexer__mth__()\n        {\n            __vntype__ accum = __vntype__.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += matrices[i].Col__mth__(indices[i].X);\n            }\n\n            return accum;\n        }\n\n        //# });\n        #endregion\n    }\n\n    #endregion\n\n    //# }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Lazy.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Runtime.CompilerServices;\nusing Microsoft.FSharp.Core;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class Lazy\n    {\n        #region CameraView implementations\n\n        private readonly struct CameraViewParams\n        {\n            public CameraViewParams(V3d l, V3d f, V3d u, V3d r)\n            {\n                Location = l;\n                Forward = f.Normalized;\n                Up = u.Normalized;\n                Right = r.Normalized;\n            }\n\n            public readonly V3d Location;\n            public readonly V3d Forward;\n            public readonly V3d Up;\n            public readonly V3d Right;\n        }\n\n        private class CameraViewLazy\n        {\n            private readonly V3d location;\n            private readonly V3d forward;\n            private readonly V3d up;\n            private readonly V3d right;\n            private readonly Lazy<Trafo3d> viewTrafo;\n\n            public CameraViewLazy(CameraViewParams p)\n            {\n                location = p.Location; forward = p.Forward; up = p.Up; right = p.Right;\n                viewTrafo = new Lazy<Trafo3d>(() => Trafo3d.ViewTrafo(location, right, up, -forward));\n            }\n\n            public V3d Location => location;\n            public V3d Forward => forward;\n            public V3d Up => up;\n            public V3d Right => right;\n            public Trafo3d ViewTrafo\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get => viewTrafo.Value;\n            }\n        }\n\n        private class CameraViewNullable\n        {\n            private readonly V3d location;\n            private readonly V3d forward;\n            private readonly V3d up;\n            private readonly V3d right;\n            private Trafo3d? viewTrafo;\n\n            public CameraViewNullable(CameraViewParams p)\n            {\n                location = p.Location; forward = p.Forward; up = p.Up; right = p.Right;\n                viewTrafo = null;\n            }\n\n            public V3d Location => location;\n            public V3d Forward => forward;\n            public V3d Up => up;\n            public V3d Right => right;\n            public Trafo3d ViewTrafo\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get\n                {\n                    if (viewTrafo == null)\n                    {\n                        viewTrafo = Trafo3d.ViewTrafo(location, right, up, -forward);\n                    }\n\n                    return viewTrafo.Value;\n                }\n            }\n        }\n\n        private class CameraViewOption\n        {\n            private readonly V3d location;\n            private readonly V3d forward;\n            private readonly V3d up;\n            private readonly V3d right;\n            private FSharpOption<Trafo3d> viewTrafo;\n\n            public CameraViewOption(CameraViewParams p)\n            {\n                location = p.Location; forward = p.Forward; up = p.Up; right = p.Right;\n                viewTrafo = FSharpOption<Trafo3d>.None;\n            }\n\n            public V3d Location => location;\n            public V3d Forward => forward;\n            public V3d Up => up;\n            public V3d Right => right;\n            public Trafo3d ViewTrafo\n            {\n                [MethodImpl(MethodImplOptions.AggressiveInlining)]\n                get\n                {\n                    if (viewTrafo == null)\n                    {\n                        viewTrafo = Trafo3d.ViewTrafo(location, right, up, -forward);\n                    }\n\n                    return viewTrafo.Value;\n                }\n            }\n        }\n\n        #endregion\n\n        const int count = 10000;\n        const int subcount = 100;\n        readonly CameraViewLazy[] lazy = new CameraViewLazy[count];\n        readonly CameraViewNullable[] nullable = new CameraViewNullable[count];\n        readonly CameraViewOption[] option = new CameraViewOption[count];\n\n        [GlobalSetup]\n        public void Setup()\n        {\n            var rnd = new RandomSystem(1);\n\n            var arr = new CameraViewParams[count];\n            arr.SetByIndex(i => new CameraViewParams(rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d()));\n            lazy.SetByIndex(i => new CameraViewLazy(arr[i]));\n            nullable.SetByIndex(i => new CameraViewNullable(arr[i]));\n            option.SetByIndex(i => new CameraViewOption(arr[i]));\n        }\n\n        [Benchmark]\n        public M44d LazyField()\n        {\n            var result = M44d.Zero;\n            for (int i = 0; i < count; i++)\n            {\n                for (int j = 0; j < subcount; j++)\n                {\n                    result += lazy[i].ViewTrafo.Forward;\n                }\n            }\n            return result;\n        }\n\n        [Benchmark]\n        public M44d NullableField()\n        {\n            var result = M44d.Zero;\n            for (int i = 0; i < count; i++)\n            {\n                for (int j = 0; j < subcount; j++)\n                {\n                    result += nullable[i].ViewTrafo.Forward;\n                }\n            }\n            return result;\n        }\n\n        [Benchmark]\n        public M44d OptionField()\n        {\n            var result = M44d.Zero;\n            for (int i = 0; i < count; i++)\n            {\n                for (int j = 0; j < subcount; j++)\n                {\n                    result += option[i].ViewTrafo.Forward;\n                }\n            }\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/AngleBetween_auto.cs",
    "content": "using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class AngleBetweenFloat\n    {\n        const int count = 10000000;\n        readonly V3f[] A = new V3f[count];\n        readonly V3f[] B = new V3f[count];\n        readonly float[] angles = new float[count];\n\n        public AngleBetweenFloat()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => rnd.UniformV3fDirection());\n            angles.SetByIndex(i => rnd.UniformFloat() * (float)Constant.Pi);\n            B.SetByIndex(i =>\n            {\n                V3f v;\n                do { v = rnd.UniformV3fDirection(); } \n                while (v.Dot(A[i]).IsTiny());\n\n                V3f axis = v.Cross(A[i]).Normalized;\n\n                return M44f.Rotation(axis, angles[i]).TransformDir(A[i]);\n            });\n        }\n\n        private double[] ComputeRelativeError(Func<V3f, V3f, float> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var v = (double) angles[i];\n                var va = (double) f(A[i], B[i]);\n\n                error[i] = Fun.Abs(v - va) / Fun.Abs(v);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            var methods = new Dictionary<string, Func<V3f, V3f, float>>()\n                {\n                    { \"Stable\", Vec.AngleBetween },\n                    { \"Fast\", Vec.AngleBetweenFast }\n                };\n\n            Console.WriteLine(\"Benchmarking numerical stability for AngleBetweenFloat\");\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeRelativeError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Relative error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Benchmark]\n        public float AngleBetweenStable()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].AngleBetween(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public float AngleBetweenFast()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].AngleBetweenFast(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void AngleBetweenStableTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var x = A[i].AngleBetween(B[i]);\n                var y = angles[i];\n\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, 0.01), \"{0} != {1}\", x, y);\n            }\n        }\n\n        [Test]\n        public void AngleBetweenFastTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var x = A[i].AngleBetweenFast(B[i]);\n                var y = angles[i];\n\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, 0.01), \"{0} != {1}\", x, y);\n            }\n        }\n    }\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class AngleBetweenDouble\n    {\n        const int count = 10000000;\n        readonly V3d[] A = new V3d[count];\n        readonly V3d[] B = new V3d[count];\n        readonly double[] angles = new double[count];\n\n        public AngleBetweenDouble()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => rnd.UniformV3dDirection());\n            angles.SetByIndex(i => rnd.UniformDouble() * (double)Constant.Pi);\n            B.SetByIndex(i =>\n            {\n                V3d v;\n                do { v = rnd.UniformV3dDirection(); } \n                while (v.Dot(A[i]).IsTiny());\n\n                V3d axis = v.Cross(A[i]).Normalized;\n\n                return M44d.Rotation(axis, angles[i]).TransformDir(A[i]);\n            });\n        }\n\n        private double[] ComputeRelativeError(Func<V3d, V3d, double> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var v = (double) angles[i];\n                var va = (double) f(A[i], B[i]);\n\n                error[i] = Fun.Abs(v - va) / Fun.Abs(v);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            var methods = new Dictionary<string, Func<V3d, V3d, double>>()\n                {\n                    { \"Stable\", Vec.AngleBetween },\n                    { \"Fast\", Vec.AngleBetweenFast }\n                };\n\n            Console.WriteLine(\"Benchmarking numerical stability for AngleBetweenDouble\");\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeRelativeError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Relative error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Benchmark]\n        public double AngleBetweenStable()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].AngleBetween(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public double AngleBetweenFast()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].AngleBetweenFast(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void AngleBetweenStableTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var x = A[i].AngleBetween(B[i]);\n                var y = angles[i];\n\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, 0.0001), \"{0} != {1}\", x, y);\n            }\n        }\n\n        [Test]\n        public void AngleBetweenFastTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var x = A[i].AngleBetweenFast(B[i]);\n                var y = angles[i];\n\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, 0.0001), \"{0} != {1}\", x, y);\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/AngleBetween_template.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var rt in Meta.RealTypes) {\n    //#     var rtype = rt.Name;\n    //#     var Rtype = rt.Caps;\n    //#     var v3rt = Meta.VecTypeOf(3, rt).Name;\n    //#     var m44rt = Meta.MatTypeOf(4, 4, rt).Name;\n    //#     var eps = (rt == Meta.DoubleType) ? 0.0001f : 0.01f;\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class AngleBetween__Rtype__\n    {\n        const int count = 10000000;\n        readonly __v3rt__[] A = new __v3rt__[count];\n        readonly __v3rt__[] B = new __v3rt__[count];\n        readonly __rtype__[] angles = new __rtype__[count];\n\n        public AngleBetween__Rtype__()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => rnd.Uniform__v3rt__Direction());\n            angles.SetByIndex(i => rnd.Uniform__Rtype__() * (__rtype__)Constant.Pi);\n            B.SetByIndex(i =>\n            {\n                __v3rt__ v;\n                do { v = rnd.Uniform__v3rt__Direction(); } \n                while (v.Dot(A[i]).IsTiny());\n\n                __v3rt__ axis = v.Cross(A[i]).Normalized;\n\n                return __m44rt__.Rotation(axis, angles[i]).TransformDir(A[i]);\n            });\n        }\n\n        private double[] ComputeRelativeError(Func<__v3rt__, __v3rt__, __rtype__> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var v = (double) angles[i];\n                var va = (double) f(A[i], B[i]);\n\n                error[i] = Fun.Abs(v - va) / Fun.Abs(v);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            var methods = new Dictionary<string, Func<__v3rt__, __v3rt__, __rtype__>>()\n                {\n                    { \"Stable\", Vec.AngleBetween },\n                    { \"Fast\", Vec.AngleBetweenFast }\n                };\n\n            Console.WriteLine(\"Benchmarking numerical stability for AngleBetween__Rtype__\");\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeRelativeError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Relative error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Benchmark]\n        public __rtype__ AngleBetweenStable()\n        {\n            __rtype__ sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].AngleBetween(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public __rtype__ AngleBetweenFast()\n        {\n            __rtype__ sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].AngleBetweenFast(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void AngleBetweenStableTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var x = A[i].AngleBetween(B[i]);\n                var y = angles[i];\n\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, __eps__), \"{0} != {1}\", x, y);\n            }\n        }\n\n        [Test]\n        public void AngleBetweenFastTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var x = A[i].AngleBetweenFast(B[i]);\n                var y = angles[i];\n\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, __eps__), \"{0} != {1}\", x, y);\n            }\n        }\n    }\n\n    //# }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/DistanceRot3_auto.cs",
    "content": "using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class DistanceRot3f\n    {\n        const int count = 10000000;\n        readonly Rot3f[] A = new Rot3f[count];\n        readonly Rot3f[] B = new Rot3f[count];\n        readonly float[] angles = new float[count];\n\n        private static V3f RndAxis(RandomSystem rnd)\n            => rnd.UniformV3fDirection();\n        \n        private static float RndAngle(RandomSystem rnd)\n            => rnd.UniformFloat() * (float)Constant.Pi;\n\n        private static Rot3f RndRot(RandomSystem rnd)\n            => Rot3f.Rotation(RndAxis(rnd), RndAngle(rnd));\n\n        public DistanceRot3f()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => RndRot(rnd));\n            angles.SetByIndex(i =>\n            {\n                float a = 0;\n                do { a = RndAngle(rnd); }\n                while (a == 0);\n\n                return a;\n            });\n\n            B.SetByIndex(i =>\n            {\n                var r = Rot3f.Rotation(RndAxis(rnd), angles[i]);\n                return r * A[i];\n            });\n        }\n\n        private double[] ComputeRelativeError(Func<Rot3f, Rot3f, float> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var v = (double)angles[i];\n                var va = (double)f(A[i], B[i]);\n\n                error[i] = Fun.Abs(v - va) / Fun.Abs(v);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            var methods = new Dictionary<string, Func<Rot3f, Rot3f, float>>()\n                {\n                    { \"Stable\", Rot.Distance },\n                    { \"Fast\", Rot.DistanceFast }\n                };\n\n            Console.WriteLine(\"Benchmarking numerical stability for Rot3f distance\");\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeRelativeError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Relative error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Benchmark]\n        public float DistanceStable()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].Distance(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public float DistanceFast()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].DistanceFast(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void ConsistentAndCorrect()\n        {\n            for (int i = 0; i < count / 100; i++)\n            {\n                var x = Rot.Distance(A[i], B[i]);\n                var y = Rot.DistanceFast(A[i], B[i]);\n\n                // Consistency\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, 0.01f),\n                        \"Solutions do not match{0} != {1}\", x, y);\n\n                // Correctness\n                Assert.GreaterOrEqual(x, 0);\n                Assert.LessOrEqual(x, (float)Constant.Pi);\n                Assert.IsTrue(Fun.ApproximateEquals(x, angles[i], 0.01f),\n                        \"Solution does not match reference {0} != {1}\", x, angles[i]);\n            }\n        }\n    }\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class DistanceRot3d\n    {\n        const int count = 10000000;\n        readonly Rot3d[] A = new Rot3d[count];\n        readonly Rot3d[] B = new Rot3d[count];\n        readonly double[] angles = new double[count];\n\n        private static V3d RndAxis(RandomSystem rnd)\n            => rnd.UniformV3dDirection();\n        \n        private static double RndAngle(RandomSystem rnd)\n            => rnd.UniformDouble() * Constant.Pi;\n\n        private static Rot3d RndRot(RandomSystem rnd)\n            => Rot3d.Rotation(RndAxis(rnd), RndAngle(rnd));\n\n        public DistanceRot3d()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => RndRot(rnd));\n            angles.SetByIndex(i =>\n            {\n                double a = 0;\n                do { a = RndAngle(rnd); }\n                while (a == 0);\n\n                return a;\n            });\n\n            B.SetByIndex(i =>\n            {\n                var r = Rot3d.Rotation(RndAxis(rnd), angles[i]);\n                return r * A[i];\n            });\n        }\n\n        private double[] ComputeRelativeError(Func<Rot3d, Rot3d, double> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var v = (double)angles[i];\n                var va = (double)f(A[i], B[i]);\n\n                error[i] = Fun.Abs(v - va) / Fun.Abs(v);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            var methods = new Dictionary<string, Func<Rot3d, Rot3d, double>>()\n                {\n                    { \"Stable\", Rot.Distance },\n                    { \"Fast\", Rot.DistanceFast }\n                };\n\n            Console.WriteLine(\"Benchmarking numerical stability for Rot3d distance\");\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeRelativeError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Relative error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Benchmark]\n        public double DistanceStable()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].Distance(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public double DistanceFast()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].DistanceFast(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void ConsistentAndCorrect()\n        {\n            for (int i = 0; i < count / 100; i++)\n            {\n                var x = Rot.Distance(A[i], B[i]);\n                var y = Rot.DistanceFast(A[i], B[i]);\n\n                // Consistency\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, 0.0001),\n                        \"Solutions do not match{0} != {1}\", x, y);\n\n                // Correctness\n                Assert.GreaterOrEqual(x, 0);\n                Assert.LessOrEqual(x, (double)Constant.Pi);\n                Assert.IsTrue(Fun.ApproximateEquals(x, angles[i], 0.0001),\n                        \"Solution does not match reference {0} != {1}\", x, angles[i]);\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/DistanceRot3_template.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var rt in Meta.RealTypes) {\n    //#     var rtype = rt.Name;\n    //#     var Rtype = rt.Caps;\n    //#     var fc = rt.Char;\n    //#     var rot3t = \"Rot3\" + fc;\n    //#     var v3rt = Meta.VecTypeOf(3, rt).Name;\n    //#     var m44rt = Meta.MatTypeOf(4, 4, rt).Name;\n    //#     var eps = (rt == Meta.DoubleType) ? \"0.0001\" : \"0.01f\";\n    //#     var half = (rt == Meta.DoubleType) ? \"0.5\" : \"0.5f\";\n    //#     var cast = (rt == Meta.DoubleType) ? \"\" : \"(\" + rtype + \")\"; \n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class DistanceRot3__fc__\n    {\n        const int count = 10000000;\n        readonly __rot3t__[] A = new __rot3t__[count];\n        readonly __rot3t__[] B = new __rot3t__[count];\n        readonly __rtype__[] angles = new __rtype__[count];\n\n        private static __v3rt__ RndAxis(RandomSystem rnd)\n            => rnd.Uniform__v3rt__Direction();\n        \n        private static __rtype__ RndAngle(RandomSystem rnd)\n            => rnd.Uniform__Rtype__() * __cast__Constant.Pi;\n\n        private static __rot3t__ RndRot(RandomSystem rnd)\n            => __rot3t__.Rotation(RndAxis(rnd), RndAngle(rnd));\n\n        public DistanceRot3__fc__()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => RndRot(rnd));\n            angles.SetByIndex(i =>\n            {\n                __rtype__ a = 0;\n                do { a = RndAngle(rnd); }\n                while (a == 0);\n\n                return a;\n            });\n\n            B.SetByIndex(i =>\n            {\n                var r = __rot3t__.Rotation(RndAxis(rnd), angles[i]);\n                return r * A[i];\n            });\n        }\n\n        private double[] ComputeRelativeError(Func<__rot3t__, __rot3t__, __rtype__> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var v = (double)angles[i];\n                var va = (double)f(A[i], B[i]);\n\n                error[i] = Fun.Abs(v - va) / Fun.Abs(v);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            var methods = new Dictionary<string, Func<__rot3t__, __rot3t__, __rtype__>>()\n                {\n                    { \"Stable\", Rot.Distance },\n                    { \"Fast\", Rot.DistanceFast }\n                };\n\n            Console.WriteLine(\"Benchmarking numerical stability for __rot3t__ distance\");\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeRelativeError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Relative error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Benchmark]\n        public __rtype__ DistanceStable()\n        {\n            __rtype__ sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].Distance(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public __rtype__ DistanceFast()\n        {\n            __rtype__ sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += A[i].DistanceFast(B[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void ConsistentAndCorrect()\n        {\n            for (int i = 0; i < count / 100; i++)\n            {\n                var x = Rot.Distance(A[i], B[i]);\n                var y = Rot.DistanceFast(A[i], B[i]);\n\n                // Consistency\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, __eps__),\n                        \"Solutions do not match{0} != {1}\", x, y);\n\n                // Correctness\n                Assert.GreaterOrEqual(x, 0);\n                Assert.LessOrEqual(x, (__rtype__)Constant.Pi);\n                Assert.IsTrue(Fun.ApproximateEquals(x, angles[i], __eps__),\n                        \"Solution does not match reference {0} != {1}\", x, angles[i]);\n            }\n        }\n    }\n\n    //# }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/DistanceToLine.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.1110 (2004/?/20H1)\n    //Intel Core i7-4790K CPU 4.00GHz(Haswell), 1 CPU, 8 logical and 4 physical cores\n    //.NET Core SDK = 5.0.302\n\n    // [Host]        : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT\n    // .NET Core 3.1 : .NET Core 3.1.17 (CoreCLR 4.700.21.31506, CoreFX 4.700.21.31502), X64 RyuJIT\n\n    //Job=.NET Core 3.1  Runtime=.NET Core 3.1  \n\n    //|                Method |     Mean |     Error |    StdDev | Code Size |\n    //|---------------------- |---------:|----------:|----------:|----------:|\n    //|    DistanceToLine_Opt | 1.014 ms | 0.0073 ms | 0.0064 ms |     599 B |\n    //|        DistanceToLine | 1.061 ms | 0.0123 ms | 0.0115 ms |     606 B |\n    //|  GetMinimalDistanceTo | 1.346 ms | 0.0093 ms | 0.0087 ms |     709 B |\n    //|   DistanceToLineF_Opt | 1.200 ms | 0.0106 ms | 0.0100 ms |     600 B |\n    //|       DistanceToLineF | 1.243 ms | 0.0069 ms | 0.0064 ms |     671 B |\n    //| GetMinimalDistanceToF | 1.231 ms | 0.0099 ms | 0.0088 ms |     687 B |\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class DistanceToLineTest\n    {\n        private static class Impl\n        {\n            public static float DistanceToLineF_Opt(V3f query, V3f p0, V3f p1)\n            {\n                var p0p1 = p1 - p0;\n                var p0q = query - p0;\n\n                var t = Vec.Dot(p0q, p0p1);\n                if (t <= 0) return p0q.Length;\n                var denom = p0p1.LengthSquared;\n                if (t >= denom) { return Vec.Distance(query, p1); }\n                t /= denom;\n                return (p0q - t * p0p1).Length;\n            }\n\n            public static float DistanceToLineF(V3f query, V3f p0, V3f p1)\n            {\n                var p0p1 = p1 - p0;\n                var p0q = query - p0;\n\n                var t = Vec.Dot(p0q, p0p1);\n                if (t <= 0) return Vec.Distance(query, p0);\n                var denom = p0p1.LengthSquared;\n                if (t >= denom) return Vec.Distance(query, p1);\n                t /= denom;\n                return Vec.Distance(query, p0 + t * p0p1);\n            }\n\n            public static float GetMinimalDistanceToF(V3f point, V3f p0, V3f p1)\n            {\n                var a = point - p0;\n                var u = p1 - p0;\n\n                var lu2 = u.LengthSquared;\n                var adu = Vec.Dot(a, u);\n\n                if (adu > lu2)\n                {\n                    var acu2 = Vec.Cross(a, u).LengthSquared;\n                    var s1 = (adu * adu - 2 * adu * lu2 + lu2 * lu2);\n\n                    return Fun.Sqrt((acu2 + s1) / lu2);\n                }\n                else if (adu >= 0)\n                {\n                    var acu2 = Vec.Cross(a, u).LengthSquared;\n                    return Fun.Sqrt(acu2 / lu2);\n                }\n                else\n                {\n                    return a.Length;\n                }\n            }\n\n            public static double DistanceToLine_Opt(V3d query, V3d p0, V3d p1)\n            {\n                var p0p1 = p1 - p0;\n                var p0q = query - p0;\n\n                var t = Vec.Dot(p0q, p0p1);\n                if (t <= 0) return p0q.Length;\n                var denom = p0p1.LengthSquared;\n                if (t >= denom) { return Vec.Distance(query, p1); }\n                t /= denom;\n                return (p0q - t * p0p1).Length;\n            }\n\n            public static double DistanceToLine(V3d query, V3d p0, V3d p1)\n            {\n                var p0p1 = p1 - p0;\n                var p0q = query - p0;\n\n                var t = Vec.Dot(p0q, p0p1);\n                if (t <= 0) { return Vec.Distance(query, p0); }\n                var denom = p0p1.LengthSquared;\n                if (t >= denom) { return Vec.Distance(query, p1); }\n                t /= denom;\n                return Vec.Distance(query, p0 + t * p0p1);\n            }\n\n            public static double GetMinimalDistanceTo(V3d point, V3d p0, V3d p1)\n            {\n                var a = point - p0;\n                var u = p1 - p0;\n\n                var lu2 = u.LengthSquared;\n                var adu = Vec.Dot(a, u);\n\n                if (adu > lu2)\n                {\n                    var acu2 = Vec.Cross(a, u).LengthSquared;\n                    var s1 = (adu * adu - 2 * adu * lu2 + lu2 * lu2);\n\n                    return Fun.Sqrt((acu2 + s1) / lu2);\n                }\n                else if (adu >= 0)\n                {\n                    var acu2 = Vec.Cross(a, u).LengthSquared;\n                    return Fun.Sqrt(acu2 / lu2);\n                }\n                else\n                {\n                    return a.Length;\n                }\n            }\n        }\n\n        const int count = 100000;\n        readonly V3d[] x = new V3d[count];\n        readonly V3d[] y = new V3d[count];\n        readonly V3d[] z = new V3d[count];\n        readonly V3f[] xf = new V3f[count];\n        readonly V3f[] yf = new V3f[count];\n        readonly V3f[] zf = new V3f[count];\n\n        public DistanceToLineTest()\n        {\n            var rnd = new RandomSystem(0);\n            x.SetByIndex(i => rnd.UniformV3d() * 1000);\n            y.SetByIndex(i => rnd.UniformV3d() * 1000);\n            z.SetByIndex(i => rnd.UniformV3d() * 1000);\n            var rnd2 = new RandomSystem(0);\n            xf.SetByIndex(i => rnd2.UniformV3f() * 1000);\n            yf.SetByIndex(i => rnd2.UniformV3f() * 1000);\n            zf.SetByIndex(i => rnd2.UniformV3f() * 1000);\n        }\n\n        [Benchmark]\n        public double DistanceToLine_Opt()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Impl.DistanceToLine_Opt(x[i], y[i], z[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public double DistanceToLine()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Impl.DistanceToLine(x[i], y[i], z[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public double GetMinimalDistanceTo()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Impl.GetMinimalDistanceTo(x[i], y[i], z[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public float DistanceToLineF_Opt()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Impl.DistanceToLineF_Opt(xf[i], yf[i], zf[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public float DistanceToLineF()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Impl.DistanceToLineF(xf[i], yf[i], zf[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public float GetMinimalDistanceToF()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Impl.GetMinimalDistanceToF(xf[i], yf[i], zf[i]);\n            }\n\n            return sum;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/FractTest.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n\n    [PlainExporter, MemoryDiagnoser]\n    public class FracTest\n    {\n        public double[] foo = new double[10000].SetByIndex(i => i);\n\n        public double Fract_Impl(double x)\n        {\n            return x - Math.Floor(x);\n        }\n\n        public double Fract_Impl2(double x)\n        {\n            return (x - Math.Floor(x)) % 1.0;\n        }\n\n        public double Fract_Impl3(double x)\n        {\n            var res = x - Math.Floor(x);\n            return res == 1.0 ? 0.0 : res;\n        }\n\n        [Benchmark]\n        public double Fract()\n        {\n            var a = foo;\n            var fs = 0.0;\n            for (int i = 0; i < a.Length; i++)\n                fs += Fract_Impl(a[i]);\n            return fs;\n        }\n\n        [Benchmark]\n        public double Fract2()\n        {\n            var a = foo;\n            var fs = 0.0;\n            for (int i = 0; i < a.Length; i++)\n                fs += Fract_Impl2(a[i]);\n            return fs;\n        }\n\n        [Benchmark]\n        public double Fract3()\n        {\n            var a = foo;\n            var fs = 0.0;\n            for (int i = 0; i < a.Length; i++)\n                fs += Fract_Impl3(a[i]);\n            return fs;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/IntegerPower_auto.cs",
    "content": "using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class IntegerPowerInt\n    {\n        const int count = 10000000;\n        readonly int[] numbers = new int[count];\n        readonly int[] exponents = new int[count];\n\n        public IntegerPowerInt()\n        {\n            var rnd = new RandomSystem(1);\n            numbers.SetByIndex(i =>\n            {\n                var x = rnd.UniformDouble() - 0.5;\n                x += 0.1 * Fun.Sign(x);\n                return (int)(x * 10);\n            });\n            exponents.SetByIndex(i => rnd.UniformInt(32));\n        }\n\n        [Benchmark]\n        public double Pow()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pow((double)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public int Pown()\n        {\n            int sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pown(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void IntegerPowerTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var n = numbers[i]; var e = exponents[i];\n                var x = Fun.Pown(n, e);\n                var y = Fun.Pow((double)n, (double)e);\n\n                if (y > int.MinValue && y < int.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class IntegerPowerUInt\n    {\n        const int count = 10000000;\n        readonly uint[] numbers = new uint[count];\n        readonly int[] exponents = new int[count];\n\n        public IntegerPowerUInt()\n        {\n            var rnd = new RandomSystem(1);\n            numbers.SetByIndex(i =>\n            {\n                var x = rnd.UniformDouble() - 0.5;\n                x += 0.1 * Fun.Sign(x);\n                return (uint)(x * 10);\n            });\n            exponents.SetByIndex(i => rnd.UniformInt(32));\n        }\n\n        [Benchmark]\n        public double Pow()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pow((double)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public uint Pown()\n        {\n            uint sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pown(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void IntegerPowerTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var n = numbers[i]; var e = exponents[i];\n                var x = Fun.Pown(n, e);\n                var y = Fun.Pow((double)n, (double)e);\n\n                if (y > uint.MinValue && y < uint.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class IntegerPowerLong\n    {\n        const int count = 10000000;\n        readonly long[] numbers = new long[count];\n        readonly int[] exponents = new int[count];\n\n        public IntegerPowerLong()\n        {\n            var rnd = new RandomSystem(1);\n            numbers.SetByIndex(i =>\n            {\n                var x = rnd.UniformDouble() - 0.5;\n                x += 0.1 * Fun.Sign(x);\n                return (long)(x * 10);\n            });\n            exponents.SetByIndex(i => rnd.UniformInt(32));\n        }\n\n        [Benchmark]\n        public double Pow()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pow((double)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public long Pown()\n        {\n            long sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pown(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void IntegerPowerTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var n = numbers[i]; var e = exponents[i];\n                var x = Fun.Pown(n, e);\n                var y = Fun.Pow((double)n, (double)e);\n\n                if (y > long.MinValue && y < long.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class IntegerPowerFloat\n    {\n        const int count = 10000000;\n        readonly float[] numbers = new float[count];\n        readonly int[] exponents = new int[count];\n\n        public IntegerPowerFloat()\n        {\n            var rnd = new RandomSystem(1);\n            numbers.SetByIndex(i =>\n            {\n                var x = rnd.UniformDouble() - 0.5;\n                x += 0.1 * Fun.Sign(x);\n                return (float)(x * 10);\n            });\n            exponents.SetByIndex(i => rnd.UniformInt(32));\n        }\n\n        [Benchmark]\n        public float Pow()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pow((float)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public float Pown()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pown(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void IntegerPowerTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var n = numbers[i]; var e = exponents[i];\n                var x = Fun.Pown(n, e);\n                var y = Fun.Pow((double)n, (double)e);\n\n                if (y > float.MinValue && y < float.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class IntegerPowerDouble\n    {\n        const int count = 10000000;\n        readonly double[] numbers = new double[count];\n        readonly int[] exponents = new int[count];\n\n        public IntegerPowerDouble()\n        {\n            var rnd = new RandomSystem(1);\n            numbers.SetByIndex(i =>\n            {\n                var x = rnd.UniformDouble() - 0.5;\n                x += 0.1 * Fun.Sign(x);\n                return (double)(x * 10);\n            });\n            exponents.SetByIndex(i => rnd.UniformInt(32));\n        }\n\n        [Benchmark]\n        public double Pow()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pow((double)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public double Pown()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pown(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void IntegerPowerTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var n = numbers[i]; var e = exponents[i];\n                var x = Fun.Pown(n, e);\n                var y = Fun.Pow((double)n, (double)e);\n\n                if (y > double.MinValue && y < double.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/IntegerPower_template.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var smalltypes = new [] { Meta.SByteType, Meta.ShortType, Meta.ByteType, Meta.UShortType };\n    //# foreach (var t in Meta.VecFieldTypes) {\n    //#     var type = t.Name;\n    //#     var Type = t.Caps;\n    //#     var rtype = (type == \"float\") ? \"float\" : \"double\";\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class IntegerPower__Type__\n    {\n        const int count = 10000000;\n        readonly __type__[] numbers = new __type__[count];\n        readonly int[] exponents = new int[count];\n\n        public IntegerPower__Type__()\n        {\n            var rnd = new RandomSystem(1);\n            numbers.SetByIndex(i =>\n            {\n                var x = rnd.UniformDouble() - 0.5;\n                x += 0.1 * Fun.Sign(x);\n                return (__type__)(x * 10);\n            });\n            exponents.SetByIndex(i => rnd.UniformInt(32));\n        }\n\n        [Benchmark]\n        public __rtype__ Pow()\n        {\n            __rtype__ sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pow((__rtype__)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public __type__ Pown()\n        {\n            __type__ sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += numbers[i].Pown(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void IntegerPowerTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var n = numbers[i]; var e = exponents[i];\n                var x = Fun.Pown(n, e);\n                var y = Fun.Pow((double)n, (double)e);\n\n                if (y > __type__.MinValue && y < __type__.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n    //# }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Log2Int.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18362\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET Core SDK = 3.1.201\n\n    // [Host]     : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT\n    // Job-RRXOFS : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT\n\n    //Runtime=.NET Core 3.0\n\n    //|                      Method |       Mean |    Error |   StdDev |\n    //|---------------------------- |-----------:|---------:|---------:|\n    //|      Log2Int_Float_FloatExp | 1,157.1 us |  8.47 us |  7.50 us |\n    //|          Log2Int_Float_Log2 | 5,136.2 us | 14.32 us | 13.39 us |\n    //|    Log2Int_Double_DoubleExp | 1,408.4 us | 10.12 us |  8.97 us |\n    //|         Log2Int_Double_Log2 | 9,366.9 us | 44.45 us | 41.58 us |\n    //|     Log2Int_Int_Bithack_Cmp | 6,088.0 us | 63.27 us | 56.08 us |\n    //| Log2Int_Int_Bithack_Convert | 5,982.9 us |  9.49 us |  7.41 us |\n    //|  Log2Int_Int_Bithack_Unsafe | 4,906.8 us | 22.28 us | 19.75 us |\n    //|  Log2Int_Int_Bithack_Unroll | 4,894.8 us |  9.66 us |  8.56 us |\n    //|        Log2Int_Int_Numerics |   687.1 us |  6.25 us |  5.85 us |\n    //|    Log2Int_Int_NumericsUint |   686.7 us |  4.32 us |  3.83 us |\n    //|        Log2Int_Int_FloatExp | 1,234.9 us | 12.14 us | 10.76 us |\n    //|       Log2Int_Int_DoubleExp | 1,381.9 us |  3.47 us |  2.71 us |\n\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class Log2Int\n    {\n        readonly int[] m_numbersInt = new int[1000000];\n        readonly uint[] m_numbersUInt = new uint[1000000];\n        readonly float[] m_numbersFloat = new float[1000000];\n        readonly double[] m_numbersDouble = new double[1000000];\n\n        public Log2Int()\n        {\n            var rnd1 = new Random(1);\n            m_numbersInt.SetByIndex(i => rnd1.Next());\n            m_numbersUInt.SetByIndex(i => (uint)rnd1.Next());\n            m_numbersFloat.SetByIndex(i => (float)rnd1.NextDouble());\n            m_numbersDouble.SetByIndex(i => rnd1.NextDouble());\n        }\n\n        [Benchmark]\n        public int Log2Int_Float_FloatExp()\n        {\n            var sum = 0;\n            var local = m_numbersFloat;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log2Int(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Float_Log2()\n        {\n            var sum = 0;\n            var local = m_numbersFloat;\n            for (int i = 0; i < local.Length; i++)\n                sum += (int)Fun.Log2(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Double_DoubleExp()\n        {\n            var sum = 0;\n            var local = m_numbersDouble;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log2Int(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Double_Log2()\n        {\n            var sum = 0;\n            var local = m_numbersDouble;\n            for (int i = 0; i < local.Length; i++)\n                sum += (int)Fun.Log2(local[i]);\n            return sum;\n        }\n\n        static int Log2Int_Bithack_Convert(int v)\n        {\n            var r = Convert.ToInt32(v > 0xFFFF) << 4; v >>= r;\n            var shift = Convert.ToInt32(v > 0xFF) << 3; v >>= shift; r |= shift;\n            shift = Convert.ToInt32(v > 0xF) << 2; v >>= shift; r |= shift;\n            shift = Convert.ToInt32(v > 0x3) << 1; v >>= shift; r |= shift;\n            return r |= (v >> 1);\n        }\n\n        static int Log2Int_Bithack_Cmp(int v)\n        {\n            var r = (v > 0xFFFF ? 1 : 0) << 4; v >>= r;\n            var shift = (v > 0xFF ? 1 : 0) << 3; v >>= shift; r |= shift;\n            shift = (v > 0xF ? 1 : 0) << 2; v >>= shift; r |= shift;\n            shift = (v > 0x3 ? 1 : 0) << 1; v >>= shift; r |= shift;\n            return r |= (v >> 1);\n        }\n\n        static unsafe int convert(bool input)\n        {\n            return (int)*((byte*)(&input));\n        }\n\n        static unsafe int Log2Int_Bithack_Unsafe(int v)\n        {\n            var r = convert(v > 0xFFFF) << 4; v >>= r;\n            var shift = convert(v > 0xFF) << 3; v >>= shift; r |= shift;\n            shift = convert(v > 0xF) << 2; v >>= shift; r |= shift;\n            shift = convert(v > 0x3) << 1; v >>= shift; r |= shift;\n            return r |= (v >> 1);\n        }\n\n        static unsafe int Log2Int_Bithack_Unroll(int v)\n        {\n            var r = 0;\n            if ((v & 0x7FFF0000) != 0) { v >>= 16; r |= 16; }\n            if ((v & 0xFF00) != 0) { v >>= 8; r |= 8; }\n            if ((v & 0xF0) != 0) { v >>= 4; r |= 4; }\n            if ((v & 0xC) != 0) { v >>= 2; r |= 2; }\n            if ((v & 0x2) != 0) { v >>= 1; r |= 1; }\n            return r;\n        }\n\n        [Benchmark]\n        public int Log2Int_Int_Bithack_Cmp()\n        {\n            var sum = 0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += Log2Int_Bithack_Cmp(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Int_Bithack_Convert()\n        {\n            var sum = 0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += Log2Int_Bithack_Convert(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Int_Bithack_Unsafe()\n        {\n            var sum = 0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += Log2Int_Bithack_Unsafe(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Int_Bithack_Unroll()\n        {\n            var sum = 0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += Log2Int_Bithack_Unsafe(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Int_Numerics()\n        {\n            var sum = 0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += System.Numerics.BitOperations.Log2((uint)local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Int_NumericsUint()\n        {\n            var sum = 0;\n            var local = m_numbersUInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += System.Numerics.BitOperations.Log2(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Int_FloatExp()\n        {\n            var sum = 0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log2Int((float)local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Int_DoubleExp()\n        {\n            var sum = 0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log2Int((double)local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public int Log2Int_Baseline()\n        {\n            var sum = 0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += (int)Fun.Log2(local[i]).Floor();\n            return sum;\n        }\n\n        [Test]\n        public void Log2Int_AardvarkFloatExp_Floor()\n        {\n            for(int i = 1; i < 1000; i++)\n            {\n                var a = Fun.Log2Int((float)i); // aardvark bithack\n                var b = (int)Math.Log2(i).Floor();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2Int_AardvarkFloatExp_Floor_Frac()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var v = i / 1000f;\n                var a = Fun.Log2Int(v); // aardvark bithack\n                var b = (int)Math.Log2(v).Floor();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2Int_AardvarkDoubleExp_Floor()\n        {\n            for(int i = 1; i < 1000; i++)\n            {\n                var a = Fun.Log2Int((double)i); // aardvark bithack\n                var b = (int)Math.Log2(i).Floor();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2Int_AardvarkDoubleExp_Floor_Frac()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var v = i / 1000.0;\n                var a = Fun.Log2Int(v); // aardvark bithack\n                var b = (int)Math.Log2(v).Floor();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2Int_NetCore()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var a = System.Numerics.BitOperations.Log2((uint)i);\n                var b = (int)Math.Log2(i).Floor();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2Int_SoftwareConvert()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var a = Log2Int_Bithack_Unsafe(i);\n                var b = (int)Math.Log2(i).Floor();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2Int_SoftwareCompare()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var a = Log2Int_Bithack_Cmp(i);\n                var b = (int)Math.Log2(i).Floor();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2CeilingInt_AardvarkFloatExp_Ceiling()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var a = Fun.Log2CeilingInt((float)i); // aardvark bithack\n                var b = (int)Math.Log2(i).Ceiling();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2CeilingInt_AardvarkFloatExp_Ceiling_Frac()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var v = i / 1000f;\n                var a = Fun.Log2CeilingInt(v); // aardvark bithack\n                var b = (int)Math.Log2(v).Ceiling();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2CeilingInt_AardvarkDoubleExp_Ceiling()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var a = Fun.Log2CeilingInt((double)i); // aardvark bithack\n                var b = (int)Math.Log2(i).Ceiling();\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        public void Log2CeilingInt_AardvarkDoubleExp_Ceiling_Frac()\n        {\n            for (int i = 1; i < 1000; i++)\n            {\n                var v = i / 1000.0;\n                var a = Fun.Log2CeilingInt(v); // aardvark bithack\n                var b = (int)Math.Log2(v).Ceiling();\n                Assert.AreEqual(a, b);\n            }\n        }\n    }\n\n    //BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18362\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET Core SDK = 3.1.201\n\n    // [Host]     : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT\n    // Job-AVRUGN : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT\n\n    //Runtime=.NET Core 3.0\n\n    //|                 Method |      Mean |     Error |    StdDev |\n    //|----------------------- |----------:|----------:|----------:|\n    //|    Log2_Int_MathDouble |  9.465 ms | 0.1865 ms | 0.1831 ms |\n    //|   Log2_Float_MathFLog2 | 25.313 ms | 0.0338 ms | 0.0264 ms |\n    //|    Log2_Float_MathFLog |  4.945 ms | 0.0338 ms | 0.0316 ms |\n    //|      Log2_Float_Double | 26.679 ms | 0.2531 ms | 0.2367 ms |\n    //| Log10_Float_MathFLog10 |  5.135 ms | 0.0388 ms | 0.0344 ms |\n    //|        Log10_Float_Log |  5.032 ms | 0.0326 ms | 0.0305 ms |\n    //|            Log10_Float |  5.156 ms | 0.0634 ms | 0.0529 ms |\n    //|            Log2_Double |  9.018 ms | 0.0563 ms | 0.0527 ms |\n\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class Log2\n    {\n        readonly int[] m_numbersInt = new int[1000000];\n        readonly float[] m_numbersFloat = new float[1000000];\n        readonly double[] m_numbersDouble = new double[1000000];\n\n        public Log2()\n        {\n            var rnd1 = new Random(1);\n            m_numbersInt.SetByIndex(i => rnd1.Next());\n            m_numbersFloat.SetByIndex(i => (float)rnd1.NextDouble());\n            m_numbersDouble.SetByIndex(i => rnd1.NextDouble());\n        }\n\n        [Benchmark]\n        public double Log2_Int_MathDouble()\n        {\n            var sum = 0.0;\n            var local = m_numbersInt;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log2(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public float Log2_Float_MathFLog2()\n        {\n            var sum = 0.0f;\n            var local = m_numbersFloat;\n            for (int i = 0; i < local.Length; i++)\n                sum += MathF.Log2(local[i]); // MathF.Log2 is super slow !?!? looks like it is using double conversion internally\n            return sum;\n        }\n\n        [Benchmark]\n        public float Log2_Float_MathFLog()\n        {\n            var sum = 0.0f;\n            var local = m_numbersFloat;\n            for (int i = 0; i < local.Length; i++)\n                sum += MathF.Log(local[i]) * (float)Constant.Ln2Inv;\n            return sum;\n        }\n\n        [Benchmark]\n        public float Log2_Float_Double()\n        {\n            var sum = 0.0f;\n            var local = m_numbersFloat;\n            for (int i = 0; i < local.Length; i++)\n                sum += (float)Math.Log2((double)local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public float Log10_Float_MathFLog10()\n        {\n            var sum = 0.0f;\n            var local = m_numbersFloat;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log10(local[i]);\n            return sum;\n        }\n\n        const float InvLog10 = 2.30258509f;\n\n        [Benchmark]\n        public float Log10_Float_Log()\n        {\n            var sum = 0.0f;\n            var local = m_numbersFloat;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log(local[i]) * InvLog10;\n            return sum;\n        }\n\n        [Benchmark]\n        public float Log10_Float()\n        {\n            var sum = 0.0f;\n            var local = m_numbersFloat;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log10(local[i]);\n            return sum;\n        }\n\n        [Benchmark]\n        public double Log2_Double()\n        {\n            var sum = 0.0;\n            var local = m_numbersDouble;\n            for (int i = 0; i < local.Length; i++)\n                sum += Fun.Log2(local[i]);\n            return sum;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/PowerOfTwo_auto.cs",
    "content": "using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class PowerOfTwoFloat\n    {\n        const int count = 10000000;\n        readonly int[] exponents = new int[count];\n\n        public PowerOfTwoFloat()\n        {\n            var rnd = new RandomSystem(1);\n            exponents.SetByIndex(i => rnd.UniformInt(64) - 32);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private float PowerOfTwoSigned(int exponent)\n        {\n            return (exponent < 0) ? 1.0f / Fun.PowerOfTwo(-exponent) : Fun.PowerOfTwo(exponent);\n        }\n\n        [Benchmark]\n        public float Pow()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Fun.Pow(2.0f, (float)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public float PowerOfTwoSigned()\n        {\n            float sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += PowerOfTwoSigned(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void PowerOfTwoTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var e = exponents[i];\n                var x = Fun.Pow(2.0f, e);\n                var y = PowerOfTwoSigned(e);\n\n                if (y > float.MinValue && y < float.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class PowerOfTwoDouble\n    {\n        const int count = 10000000;\n        readonly int[] exponents = new int[count];\n\n        public PowerOfTwoDouble()\n        {\n            var rnd = new RandomSystem(1);\n            exponents.SetByIndex(i => rnd.UniformInt(64) - 32);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private double PowerOfTwoSigned(int exponent)\n        {\n            return (exponent < 0) ? 1.0 / Fun.PowerOfTwo(-exponent) : Fun.PowerOfTwo(exponent);\n        }\n\n        [Benchmark]\n        public double Pow()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Fun.Pow(2.0, (double)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public double PowerOfTwoSigned()\n        {\n            double sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += PowerOfTwoSigned(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void PowerOfTwoTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var e = exponents[i];\n                var x = Fun.Pow(2.0, e);\n                var y = PowerOfTwoSigned(e);\n\n                if (y > double.MinValue && y < double.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/PowerOfTwo_template.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var t in Meta.RealTypes) {\n    //#     var type = t.Name;\n    //#     var Type = t.Caps;\n    //#     var rtype = (type == \"float\") ? \"float\" : \"double\";\n    //#     var one = (type == \"float\") ? \"1.0f\" : \"1.0\";\n    //#     var two = (type == \"float\") ? \"2.0f\" : \"2.0\";\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class PowerOfTwo__Type__\n    {\n        const int count = 10000000;\n        readonly int[] exponents = new int[count];\n\n        public PowerOfTwo__Type__()\n        {\n            var rnd = new RandomSystem(1);\n            exponents.SetByIndex(i => rnd.UniformInt(64) - 32);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private __rtype__ PowerOfTwoSigned(int exponent)\n        {\n            return (exponent < 0) ? __one__ / Fun.PowerOfTwo(-exponent) : Fun.PowerOfTwo(exponent);\n        }\n\n        [Benchmark]\n        public __rtype__ Pow()\n        {\n            __rtype__ sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += Fun.Pow(__two__, (__rtype__)exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public __rtype__ PowerOfTwoSigned()\n        {\n            __rtype__ sum = 0;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += PowerOfTwoSigned(exponents[i]);\n            }\n\n            return sum;\n        }\n\n        [Test]\n        public void PowerOfTwoTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var e = exponents[i];\n                var x = Fun.Pow(__two__, e);\n                var y = PowerOfTwoSigned(e);\n\n                if (y > __type__.MinValue && y < __type__.MaxValue)\n                {\n                    if (x != 0 && y != 0)\n                        Assert.IsTrue(Fun.ApproximateEquals(x / y, 1.0, 1e-3), \"{0} != {1}\", x, y);\n                }\n            }\n        }\n    }\n\n    //# }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Rot3GetEuler_auto.cs",
    "content": "using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Rot3f\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class Rot3fGetEuler\n    {\n        private static class Implementations\n        {\n            public static V3f Original(Rot3f r)\n            {\n                var test = r.W * r.Y - r.X * r.Z;\n                if (test > 0.5f - Constant<float>.PositiveTinyValue) // singularity at north pole\n                {\n                    return new V3f(\n                        2 * Fun.Atan2(r.X, r.W),\n                        ConstantF.PiHalf,\n                        0);\n                }\n                if (test < -0.5f + Constant<float>.PositiveTinyValue) // singularity at south pole\n                {\n                    return new V3f(\n                        2 * Fun.Atan2(r.X, r.W),\n                        -ConstantF.PiHalf,\n                        0);\n                }\n                // From Wikipedia, conversion between quaternions and Euler angles.\n                return new V3f(\n                            Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                      1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                            Fun.AsinClamped(2 * test),\n                            Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                      1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n            }\n\n            public static V3f CopySign(Rot3f r)\n            {\n                var test = r.W * r.Y - r.X * r.Z;\n\n                if (test.Abs() >= 0.5f - Constant<float>.PositiveTinyValue)\n                {\n                    return new V3f(\n                        2 * Fun.Atan2(r.X, r.W),\n                        Fun.CopySign(ConstantF.PiHalf, test),\n                        0);\n                }\n                else\n                {\n                    return new V3f(\n                                Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                          1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                                Fun.AsinClamped(2 * test),\n                                Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                          1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n                }\n            }\n\n            public static Dictionary<string, Func<Rot3f, V3f>> All\n            {\n                get => new Dictionary<string, Func<Rot3f, V3f>>()\n                {\n                    { \"Original\", Original },\n                    { \"CopySign\", CopySign }\n                };\n            }\n        }\n\n        const int count = 1000000;\n        readonly Rot3f[] Rots = new Rot3f[count];\n        readonly V3f[] EulerAngles = new V3f[count];\n\n        public Rot3fGetEuler()\n        {\n            var rnd = new RandomSystem(1);\n            EulerAngles.SetByIndex(i =>\n            {\n                var vrnd = rnd.UniformV3f() * ConstantF.Pi * 2;\n                var veps = (rnd.UniformDouble() < 0.5) ? rnd.UniformV3f() * (i / (float)100) * 1e-12f : V3f.Zero;\n                var vspc = new V3f(rnd.UniformV3i(4)) * ConstantF.PiHalf + veps;\n\n                float roll = (rnd.UniformDouble() < 0.5) ? vrnd.X : vspc.X;\n                float pitch = (rnd.UniformDouble() < 0.5) ? vrnd.Y : vspc.Y;\n                float yaw = (rnd.UniformDouble() < 0.5) ? vrnd.Z : vspc.Z;\n\n                return new V3f(roll, pitch, yaw);\n            });\n            Rots.SetByIndex(i => Rot3f.RotationEuler(EulerAngles[i]));\n        }\n\n        private double[] ComputeAbsoluteError(Func<Rot3f, V3f> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var r1 = Rots[i];\n                var r2 = Rot3f.RotationEuler(f(r1)).Normalized;\n\n                error[i] = Rot.Distance(r1, r2);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for Rot3f.GetEulerAngles() variants\");\n            Console.WriteLine();\n\n            foreach (var m in Implementations.All)\n            {\n                var errors = ComputeAbsoluteError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Test]\n        public void CorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.All)\n                {\n                    Rot3f r1 = Rots[i];\n                    Rot3f r2 = Rot3f.RotationEuler(f.Value(r1));\n\n                    Assert.Less(\n                        Rot.Distance(r1, r2), 1e-2f,\n                        string.Format(\"{0} implementation incorrect!\", f.Key)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public V3f Original()\n        {\n            V3f accum = V3f.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.Original(Rots[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public V3f CopySign()\n        {\n            V3f accum = V3f.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.CopySign(Rots[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    #region Rot3d\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class Rot3dGetEuler\n    {\n        private static class Implementations\n        {\n            public static V3d Original(Rot3d r)\n            {\n                var test = r.W * r.Y - r.X * r.Z;\n                if (test > 0.5 - Constant<double>.PositiveTinyValue) // singularity at north pole\n                {\n                    return new V3d(\n                        2 * Fun.Atan2(r.X, r.W),\n                        Constant.PiHalf,\n                        0);\n                }\n                if (test < -0.5 + Constant<double>.PositiveTinyValue) // singularity at south pole\n                {\n                    return new V3d(\n                        2 * Fun.Atan2(r.X, r.W),\n                        -Constant.PiHalf,\n                        0);\n                }\n                // From Wikipedia, conversion between quaternions and Euler angles.\n                return new V3d(\n                            Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                      1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                            Fun.AsinClamped(2 * test),\n                            Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                      1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n            }\n\n            public static V3d CopySign(Rot3d r)\n            {\n                var test = r.W * r.Y - r.X * r.Z;\n\n                if (test.Abs() >= 0.5 - Constant<double>.PositiveTinyValue)\n                {\n                    return new V3d(\n                        2 * Fun.Atan2(r.X, r.W),\n                        Fun.CopySign(Constant.PiHalf, test),\n                        0);\n                }\n                else\n                {\n                    return new V3d(\n                                Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                          1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                                Fun.AsinClamped(2 * test),\n                                Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                          1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n                }\n            }\n\n            public static Dictionary<string, Func<Rot3d, V3d>> All\n            {\n                get => new Dictionary<string, Func<Rot3d, V3d>>()\n                {\n                    { \"Original\", Original },\n                    { \"CopySign\", CopySign }\n                };\n            }\n        }\n\n        const int count = 1000000;\n        readonly Rot3d[] Rots = new Rot3d[count];\n        readonly V3d[] EulerAngles = new V3d[count];\n\n        public Rot3dGetEuler()\n        {\n            var rnd = new RandomSystem(1);\n            EulerAngles.SetByIndex(i =>\n            {\n                var vrnd = rnd.UniformV3d() * Constant.Pi * 2;\n                var veps = (rnd.UniformDouble() < 0.5) ? rnd.UniformV3d() * (i / (double)100) * 1e-22 : V3d.Zero;\n                var vspc = new V3d(rnd.UniformV3i(4)) * Constant.PiHalf + veps;\n\n                double roll = (rnd.UniformDouble() < 0.5) ? vrnd.X : vspc.X;\n                double pitch = (rnd.UniformDouble() < 0.5) ? vrnd.Y : vspc.Y;\n                double yaw = (rnd.UniformDouble() < 0.5) ? vrnd.Z : vspc.Z;\n\n                return new V3d(roll, pitch, yaw);\n            });\n            Rots.SetByIndex(i => Rot3d.RotationEuler(EulerAngles[i]));\n        }\n\n        private double[] ComputeAbsoluteError(Func<Rot3d, V3d> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var r1 = Rots[i];\n                var r2 = Rot3d.RotationEuler(f(r1)).Normalized;\n\n                error[i] = Rot.Distance(r1, r2);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for Rot3d.GetEulerAngles() variants\");\n            Console.WriteLine();\n\n            foreach (var m in Implementations.All)\n            {\n                var errors = ComputeAbsoluteError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Test]\n        public void CorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.All)\n                {\n                    Rot3d r1 = Rots[i];\n                    Rot3d r2 = Rot3d.RotationEuler(f.Value(r1));\n\n                    Assert.Less(\n                        Rot.Distance(r1, r2), 1e-7,\n                        string.Format(\"{0} implementation incorrect!\", f.Key)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public V3d Original()\n        {\n            V3d accum = V3d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.Original(Rots[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public V3d CopySign()\n        {\n            V3d accum = V3d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.CopySign(Rots[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Rot3GetEuler_template.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# var fields = new[] {\"X\", \"Y\", \"Z\"};\n    //# foreach (var rt in Meta.RealTypes) {\n    //#     var isDouble = rt == Meta.DoubleType;\n    //#     var rtype = rt.Name;\n    //#     var Rtype = rt.Caps;\n    //#     var fc = rt.Char;\n    //#     var rot3t = \"Rot3\" + fc;\n    //#     var rot2t = \"Rot2\" + fc;\n    //#     var quatt = \"Quaternion\" + fc.ToUpper();\n    //#     var v3t = Meta.VecTypeOf(3, rt).Name;\n    //#     var half = isDouble ? \"0.5\" : \"0.5f\";\n    //#     var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#     var piHalf = isDouble ? \"Constant.PiHalf\" : \"ConstantF.PiHalf\";\n    //#     var eps = isDouble ? \"1e-7\" : \"1e-2f\";\n    #region __rot3t__\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class __rot3t__GetEuler\n    {\n        private static class Implementations\n        {\n            public static __v3t__ Original(__rot3t__ r)\n            {\n                var test = r.W * r.Y - r.X * r.Z;\n                if (test > __half__ - Constant<__rtype__>.PositiveTinyValue) // singularity at north pole\n                {\n                    return new __v3t__(\n                        2 * Fun.Atan2(r.X, r.W),\n                        __piHalf__,\n                        0);\n                }\n                if (test < -__half__ + Constant<__rtype__>.PositiveTinyValue) // singularity at south pole\n                {\n                    return new __v3t__(\n                        2 * Fun.Atan2(r.X, r.W),\n                        -__piHalf__,\n                        0);\n                }\n                // From Wikipedia, conversion between quaternions and Euler angles.\n                return new __v3t__(\n                            Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                      1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                            Fun.AsinClamped(2 * test),\n                            Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                      1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n            }\n\n            public static __v3t__ CopySign(__rot3t__ r)\n            {\n                var test = r.W * r.Y - r.X * r.Z;\n\n                if (test.Abs() >= __half__ - Constant<__rtype__>.PositiveTinyValue)\n                {\n                    return new __v3t__(\n                        2 * Fun.Atan2(r.X, r.W),\n                        Fun.CopySign(__piHalf__, test),\n                        0);\n                }\n                else\n                {\n                    return new __v3t__(\n                                Fun.Atan2(2 * (r.W * r.X + r.Y * r.Z),\n                                          1 - 2 * (r.X * r.X + r.Y * r.Y)),\n                                Fun.AsinClamped(2 * test),\n                                Fun.Atan2(2 * (r.W * r.Z + r.X * r.Y),\n                                          1 - 2 * (r.Y * r.Y + r.Z * r.Z)));\n                }\n            }\n\n            public static Dictionary<string, Func<__rot3t__, __v3t__>> All\n            {\n                get => new Dictionary<string, Func<__rot3t__, __v3t__>>()\n                {\n                    { \"Original\", Original },\n                    { \"CopySign\", CopySign }\n                };\n            }\n        }\n\n        const int count = 1000000;\n        readonly __rot3t__[] Rots = new __rot3t__[count];\n        readonly __v3t__[] EulerAngles = new __v3t__[count];\n\n        public __rot3t__GetEuler()\n        {\n            var rnd = new RandomSystem(1);\n            EulerAngles.SetByIndex(i =>\n            {\n                //# var err = isDouble ? \"1e-22\" : \"1e-12f\";\n                var vrnd = rnd.Uniform__v3t__() * __pi__ * 2;\n                var veps = (rnd.UniformDouble() < 0.5) ? rnd.Uniform__v3t__() * (i / (__rtype__)100) * __err__ : __v3t__.Zero;\n                var vspc = new __v3t__(rnd.UniformV3i(4)) * __piHalf__ + veps;\n\n                __rtype__ roll = (rnd.UniformDouble() < 0.5) ? vrnd.X : vspc.X;\n                __rtype__ pitch = (rnd.UniformDouble() < 0.5) ? vrnd.Y : vspc.Y;\n                __rtype__ yaw = (rnd.UniformDouble() < 0.5) ? vrnd.Z : vspc.Z;\n\n                return new __v3t__(roll, pitch, yaw);\n            });\n            Rots.SetByIndex(i => __rot3t__.RotationEuler(EulerAngles[i]));\n        }\n\n        private double[] ComputeAbsoluteError(Func<__rot3t__, __v3t__> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var r1 = Rots[i];\n                var r2 = __rot3t__.RotationEuler(f(r1)).Normalized;\n\n                error[i] = Rot.Distance(r1, r2);\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for __rot3t__.GetEulerAngles() variants\");\n            Console.WriteLine();\n\n            foreach (var m in Implementations.All)\n            {\n                var errors = ComputeAbsoluteError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Test]\n        public void CorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.All)\n                {\n                    __rot3t__ r1 = Rots[i];\n                    __rot3t__ r2 = __rot3t__.RotationEuler(f.Value(r1));\n\n                    Assert.Less(\n                        Rot.Distance(r1, r2), __eps__,\n                        string.Format(\"{0} implementation incorrect!\", f.Key)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public __v3t__ Original()\n        {\n            __v3t__ accum = __v3t__.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.Original(Rots[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public __v3t__ CopySign()\n        {\n            __v3t__ accum = __v3t__.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.CopySign(Rots[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    //# }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Rot3dTransform.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class Rot3dTransform\n    {\n        readonly V3d[] arr = new V3d[100000];\n        Rot3d rotG = Rot3d.RotationX(Constant.Pi);\n        M33d matG = M33d.Identity;\n\n        //[GlobalSetup]\n        public Rot3dTransform()\n        {\n            var rnd1 = new Random(1);\n            for (int i = 0; i < arr.Length; i++)\n                arr[i] = new V3d(rnd1.NextDouble(), rnd1.NextDouble(), rnd1.NextDouble());\n        }\n\n        [Benchmark]\n        public void Rot3d_Transform()\n        {\n            var rot = rotG;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = rot.Transform(arr[i]);\n        }\n\n        static V3d TransformM33dPrecomputed(M33d mat, V3d v)\n        {\n            return mat.Transform(v);\n        }\n\n        [Benchmark]\n        public void Rot3d_TransformM33dPrecomputed()\n        {\n            var local = arr;\n            var mat = matG;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = TransformM33dPrecomputed(mat, arr[i]);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)] // does not fully inline without\n        static V3d TransformM33dPrecomputed_Inline(M33d m, V3d v)\n        {\n            return new V3d(\n                m.M00 * v.X + m.M01 * v.Y + m.M02 * v.Z,\n                m.M10 * v.X + m.M11 * v.Y + m.M12 * v.Z,\n                m.M20 * v.X + m.M21 * v.Y + m.M22 * v.Z\n                );\n        }\n\n        [Benchmark]\n        public void Rot3d_TransformM33dPrecomputed_Inline()\n        {\n            var local = arr;\n            var mat = matG;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = TransformM33dPrecomputed_Inline(mat, arr[i]);\n        }\n\n        static V3d TransformUsingM33d(Rot3d rot, V3d v)\n        {\n            return ((M33d)rot).Transform(v);\n        }\n\n        [Benchmark]\n        public void Rot3d_TransformUsingM33d()\n        {\n            var rot = rotG;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = TransformUsingM33d(rot, arr[i]);\n        }\n\n        static V3d TransformUsingQuaternion(Rot3d q, V3d v)\n        {\n            var r = q * new QuaternionD(0, v) * q.Inverse;\n            return new V3d(r.X, r.Y, r.Z);\n        }\n\n        [Benchmark]\n        public void Rot3d_TransformUsingQuaternion()\n        {\n            var rot = rotG;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = TransformUsingQuaternion(rot, arr[i]);\n        }\n\n        static V3d TransformUsingQuaternionOpt1(Rot3d rot, V3d v)\n        {\n            // Multiply(a, b)\n            //return new Rot3d(\n            //    a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z,\n            //    a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,\n            //    a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,\n            //    a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X\n            //    );\n\n            // rot * Rot3d(0, v)\n            var q = new QuaternionD(\n              - rot.X * v.X - rot.Y * v.Y - rot.Z * v.Z,\n                rot.W * v.X + rot.Y * v.Z - rot.Z * v.Y,\n                rot.W * v.Y + rot.Z * v.X - rot.X * v.Z,\n                rot.W * v.Z + rot.X * v.Y - rot.Y * v.X);\n            \n            // q * Rot3d(rot.W, -rot.V) (rot.Conungated)\n            return new V3d(\n                -q.W * rot.X + q.X * rot.W - q.Y * rot.Z + q.Z * rot.Y,\n                -q.W * rot.Y + q.Y * rot.W - q.Z * rot.X + q.X * rot.Z,\n                -q.W * rot.Z + q.Z * rot.W - q.X * rot.Y + q.Y * rot.X\n                );\n        }\n\n        static V3d TransformUsingQuaternionOpt2(Rot3d rot, V3d v)\n        {\n            // rot * Rot3d(0, v)\n            var W = -rot.X * v.X - rot.Y * v.Y - rot.Z * v.Z;\n            var X = rot.W * v.X + rot.Y * v.Z - rot.Z * v.Y;\n            var Y = rot.W * v.Y + rot.Z * v.X - rot.X * v.Z;\n            var Z = rot.W * v.Z + rot.X * v.Y - rot.Y * v.X;\n\n            // q * Rot3d(rot.W, -rot.V) (rot.Conungated)\n            return new V3d(\n                -W * rot.X + X * rot.W - Y * rot.Z + Z * rot.Y,\n                -W * rot.Y + Y * rot.W - Z * rot.X + X * rot.Z,\n                -W * rot.Z + Z * rot.W - X * rot.Y + Y * rot.X\n                );\n        }\n\n        [Benchmark]\n        public void Rot3d_TransformUsingQuaternionOpt1()\n        {\n            var rot = rotG;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = TransformUsingQuaternionOpt1(rot, arr[i]);\n        }\n\n        [Benchmark]\n        public void Rot3d_TransformUsingQuaternionOpt2()\n        {\n            var rot = rotG;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = TransformUsingQuaternionOpt2(rot, arr[i]);\n        }\n\n        [Test]\n        public static void Rot3dTransformTest()\n        {\n            var rnd = new RandomSystem(1);\n            for (int i = 0; i < 10000; i++)\n            {\n                var v = rnd.UniformV3d();\n                var axis = rnd.UniformV3dDirection();\n                var ang = rnd.UniformDouble();\n                var rot = Rot3d.Rotation(axis, ang);\n\n                var test1 = TransformUsingM33d(rot, v);\n                var test2 = rot.Transform(v);\n                var test3 = TransformUsingQuaternion(rot, v);\n                var test4 = TransformUsingQuaternionOpt1(rot, v);\n\n                Assert.IsTrue(test1.ApproximateEquals(test2, 1e-5));\n                Assert.IsTrue(test1.ApproximateEquals(test3, 1e-5));\n                Assert.IsTrue(test1.ApproximateEquals(test4, 1e-5));\n            }\n        }\n\n        static V3d InvTransformUsingM33d(Rot3d rot, V3d v)\n        {\n            return ((M33d)rot).TransposedTransform(v);\n        }\n\n        static V3d InvTransformUsingQuaternion(Rot3d rot, V3d v)\n        {\n            var r = rot.Inverse * new QuaternionD(0, v) * rot;\n            return new V3d(r.X, r.Y, r.Z);\n        }\n\n        static V3d InvTransformUsingQuaternionOpt(Rot3d rot, V3d v)\n        {\n            // TODO\n            // Multiply(a, b)\n            //return new Rot3d(\n            //    a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z,\n            //    a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,\n            //    a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,\n            //    a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X\n            //    );\n\n            // rot.Conungated * Rot3d(0, v)\n            var q = new QuaternionD(\n               +rot.X * v.X + rot.Y * v.Y + rot.Z * v.Z,\n                rot.W * v.X - rot.Y * v.Z + rot.Z * v.Y,\n                rot.W * v.Y - rot.Z * v.X + rot.X * v.Z,\n                rot.W * v.Z - rot.X * v.Y + rot.Y * v.X);\n\n            // q * rot\n\n            return new V3d(\n                q.W * rot.X + q.X * rot.W + q.Y * rot.Z - q.Z * rot.Y,\n                q.W * rot.Y + q.Y * rot.W + q.Z * rot.X - q.X * rot.Z,\n                q.W * rot.Z + q.Z * rot.W + q.X * rot.Y - q.Y * rot.X\n                );\n        }\n\n        [Test]\n        public static void Rot3dInvTransformTest()\n        {\n            var rnd = new RandomSystem(1);\n            for (int i = 0; i < 10000; i++)\n            {\n                var v = rnd.UniformV3d();\n                var axis = rnd.UniformV3dDirection();\n                var ang = rnd.UniformDouble();\n                var rot = Rot3d.Rotation(axis, ang);\n\n                var test1 = InvTransformUsingM33d(rot, v);\n                var test2 = rot.InvTransform(v);\n                var test3 = InvTransformUsingQuaternion(rot, v);\n                var test4 = InvTransformUsingQuaternionOpt(rot, v);\n\n                Assert.IsTrue(test1.ApproximateEquals(test2, 1e-5));\n                Assert.IsTrue(test1.ApproximateEquals(test3, 1e-5));\n                Assert.IsTrue(test1.ApproximateEquals(test4, 1e-5));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/RotateInto_auto.cs",
    "content": "using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region Rot3f\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class RotateIntoFloat\n    {\n        private static class Implementations\n        {\n            public static Rot3f Original(V3f from, V3f into)\n            {\n                var angle = from.AngleBetween(into);\n\n                if (angle < 1e-6f)\n                    return Rot3f.Identity;\n                else if (ConstantF.Pi - angle < 1e-6f)\n                    return new Rot3f(0, from.AxisAlignedNormal());\n                else\n                {\n                    V3f axis = Vec.Cross(from, into).Normalized;\n                    return Rot3f.Rotation(axis, angle);\n                }\n            }\n\n            // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another\n            public static Rot3f HalfWayVec(V3f from, V3f into)\n            {\n                if (from.Dot(into).ApproximateEquals(-1))\n                    return new Rot3f(0, from.AxisAlignedNormal());\n                else\n                {\n                    V3f half = Vec.Normalized(from + into);\n                    QuaternionF q = new QuaternionF(Vec.Dot(from, half), Vec.Cross(from, half));\n                    return new Rot3f(q.Normalized);\n                }\n            }\n\n            public static Rot3f HalfWayQuat(V3f from, V3f into)\n            {\n                var d = Vec.Dot(from, into);\n\n                if (d.ApproximateEquals(-1))\n                    return new Rot3f(0, from.AxisAlignedNormal());\n                else\n                {\n                    QuaternionF q = new QuaternionF(d + 1, Vec.Cross(from, into));\n                    return new Rot3f(q.Normalized);\n                }\n            }\n\n            public static Dictionary<string, Func<V3f, V3f, Rot3f>> All\n            {\n                get => new Dictionary<string, Func<V3f, V3f, Rot3f>>()\n                {\n                    { \"Original\", Original },\n                    { \"Half-way vector\", HalfWayVec },\n                    { \"Half-way quaternion\", HalfWayQuat }\n                };\n            }\n        }\n\n        const int count = 1000000;\n        readonly V3f[] A = new V3f[count];\n        readonly V3f[] B = new V3f[count];\n\n        private static V3f RndAxis(RandomSystem rnd)\n            => rnd.UniformV3fDirection();\n\n        public RotateIntoFloat()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => RndAxis(rnd));\n            B.SetByIndex(i =>\n            {\n                // type = 0 -> random\n                // type = 1 -> 0 or 180° degrees with some error\n                var type = rnd.UniformInt(2);\n\n                if (type == 0)\n                {\n                    return RndAxis(rnd);\n                }\n                else if (type == 1)\n                {\n                    // Some vectors will not normalize to 1.0 -> provoke numerical issues in V3f\n                    var v = Vec.Normalized(A[i] * rnd.UniformFloat());\n\n                    // Add some small error\n                    if (rnd.UniformDouble() < 0.5)\n                    {\n                        var eps = rnd.UniformV3f() * (i / 100) * 1e-12f;\n                        v = Vec.Normalized(v + eps);\n                    }\n\n                    // Flip\n                    if (rnd.UniformDouble() < 0.5)\n                        v = -v;\n\n                    return v;\n                }\n\n                return V3f.Zero;\n            });\n        }\n\n        private double[] ComputeAbsoluteError(Func<V3f, V3f, Rot3f> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                V3f from = A[i];\n                V3f into = B[i];\n\n                Rot3f r = f(from, into);\n                V3f res = r * from;\n\n                error[i] = Vec.AngleBetween(new V3d(res), new V3d(into));\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for Rot3f.RotateInto() variants\");\n            Console.WriteLine();\n\n            foreach (var m in Implementations.All)\n            {\n                var errors = ComputeAbsoluteError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Test]\n        public void CorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.All)\n                {\n                    V3f from = A[i];\n                    V3f into = B[i];\n\n                    Rot3f r = f.Value(from, into);\n                    V3f res = r * from;\n\n                    Assert.Less(\n                        res.AngleBetween(into), 1e-3f,\n                        string.Format(\"{0} implementation incorrect!\", f.Key)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public Rot3f Original()\n        {\n            Rot3f accum = Rot3f.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.Original(A[i], B[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public Rot3f HalfWayVec()\n        {\n            Rot3f accum = Rot3f.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.HalfWayVec(A[i], B[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public Rot3f HalfWayQuat()\n        {\n            Rot3f accum = Rot3f.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.HalfWayQuat(A[i], B[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    #region Rot3d\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class RotateIntoDouble\n    {\n        private static class Implementations\n        {\n            public static Rot3d Original(V3d from, V3d into)\n            {\n                var angle = from.AngleBetween(into);\n\n                if (angle < 1e-15)\n                    return Rot3d.Identity;\n                else if (Constant.Pi - angle < 1e-15)\n                    return new Rot3d(0, from.AxisAlignedNormal());\n                else\n                {\n                    V3d axis = Vec.Cross(from, into).Normalized;\n                    return Rot3d.Rotation(axis, angle);\n                }\n            }\n\n            // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another\n            public static Rot3d HalfWayVec(V3d from, V3d into)\n            {\n                if (from.Dot(into).ApproximateEquals(-1))\n                    return new Rot3d(0, from.AxisAlignedNormal());\n                else\n                {\n                    V3d half = Vec.Normalized(from + into);\n                    QuaternionD q = new QuaternionD(Vec.Dot(from, half), Vec.Cross(from, half));\n                    return new Rot3d(q.Normalized);\n                }\n            }\n\n            public static Rot3d HalfWayQuat(V3d from, V3d into)\n            {\n                var d = Vec.Dot(from, into);\n\n                if (d.ApproximateEquals(-1))\n                    return new Rot3d(0, from.AxisAlignedNormal());\n                else\n                {\n                    QuaternionD q = new QuaternionD(d + 1, Vec.Cross(from, into));\n                    return new Rot3d(q.Normalized);\n                }\n            }\n\n            public static Dictionary<string, Func<V3d, V3d, Rot3d>> All\n            {\n                get => new Dictionary<string, Func<V3d, V3d, Rot3d>>()\n                {\n                    { \"Original\", Original },\n                    { \"Half-way vector\", HalfWayVec },\n                    { \"Half-way quaternion\", HalfWayQuat }\n                };\n            }\n        }\n\n        const int count = 1000000;\n        readonly V3d[] A = new V3d[count];\n        readonly V3d[] B = new V3d[count];\n\n        private static V3d RndAxis(RandomSystem rnd)\n            => rnd.UniformV3dDirection();\n\n        public RotateIntoDouble()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => RndAxis(rnd));\n            B.SetByIndex(i =>\n            {\n                // type = 0 -> random\n                // type = 1 -> 0 or 180° degrees with some error\n                var type = rnd.UniformInt(2);\n\n                if (type == 0)\n                {\n                    return RndAxis(rnd);\n                }\n                else if (type == 1)\n                {\n                    // Some vectors will not normalize to 1.0 -> provoke numerical issues in V3d\n                    var v = Vec.Normalized(A[i] * rnd.UniformDouble());\n\n                    // Add some small error\n                    if (rnd.UniformDouble() < 0.5)\n                    {\n                        var eps = rnd.UniformV3d() * (i / 100) * 1e-22;\n                        v = Vec.Normalized(v + eps);\n                    }\n\n                    // Flip\n                    if (rnd.UniformDouble() < 0.5)\n                        v = -v;\n\n                    return v;\n                }\n\n                return V3d.Zero;\n            });\n        }\n\n        private double[] ComputeAbsoluteError(Func<V3d, V3d, Rot3d> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                V3d from = A[i];\n                V3d into = B[i];\n\n                Rot3d r = f(from, into);\n                V3d res = r * from;\n\n                error[i] = Vec.AngleBetween(new V3d(res), new V3d(into));\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for Rot3d.RotateInto() variants\");\n            Console.WriteLine();\n\n            foreach (var m in Implementations.All)\n            {\n                var errors = ComputeAbsoluteError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Test]\n        public void CorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.All)\n                {\n                    V3d from = A[i];\n                    V3d into = B[i];\n\n                    Rot3d r = f.Value(from, into);\n                    V3d res = r * from;\n\n                    Assert.Less(\n                        res.AngleBetween(into), 1e-12,\n                        string.Format(\"{0} implementation incorrect!\", f.Key)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public Rot3d Original()\n        {\n            Rot3d accum = Rot3d.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.Original(A[i], B[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public Rot3d HalfWayVec()\n        {\n            Rot3d accum = Rot3d.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.HalfWayVec(A[i], B[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public Rot3d HalfWayQuat()\n        {\n            Rot3d accum = Rot3d.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.HalfWayQuat(A[i], B[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/RotateInto_template.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# foreach (var rt in Meta.RealTypes) {\n    //#     var isDouble = rt == Meta.DoubleType;\n    //#     var rtype = rt.Name;\n    //#     var Rtype = rt.Caps;\n    //#     var fc = rt.Char;\n    //#     var rot3t = \"Rot3\" + fc;\n    //#     var quatt = \"Quaternion\" + fc.ToUpper();\n    //#     var v3t = Meta.VecTypeOf(3, rt).Name;\n    //#     var pi = isDouble ? \"Constant.Pi\" : \"ConstantF.Pi\";\n    //#     var piHalf = isDouble ? \"Constant.PiHalf\" : \"ConstantF.PiHalf\";\n    //#     var eps = isDouble ? \"1e-12\" : \"1e-3f\";\n    #region __rot3t__\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class RotateInto__Rtype__\n    {\n        private static class Implementations\n        {\n            public static __rot3t__ Original(__v3t__ from, __v3t__ into)\n            {\n                var angle = from.AngleBetween(into);\n\n                //# var rotIntoEps = isDouble ? \"1e-15\" : \"1e-6f\";\n                if (angle < __rotIntoEps__)\n                    return __rot3t__.Identity;\n                else if (__pi__ - angle < __rotIntoEps__)\n                    return new __rot3t__(0, from.AxisAlignedNormal());\n                else\n                {\n                    __v3t__ axis = Vec.Cross(from, into).Normalized;\n                    return __rot3t__.Rotation(axis, angle);\n                }\n            }\n\n            // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another\n            public static __rot3t__ HalfWayVec(__v3t__ from, __v3t__ into)\n            {\n                if (from.Dot(into).ApproximateEquals(-1))\n                    return new __rot3t__(0, from.AxisAlignedNormal());\n                else\n                {\n                    __v3t__ half = Vec.Normalized(from + into);\n                    __quatt__ q = new __quatt__(Vec.Dot(from, half), Vec.Cross(from, half));\n                    return new __rot3t__(q.Normalized);\n                }\n            }\n\n            public static __rot3t__ HalfWayQuat(__v3t__ from, __v3t__ into)\n            {\n                var d = Vec.Dot(from, into);\n\n                if (d.ApproximateEquals(-1))\n                    return new __rot3t__(0, from.AxisAlignedNormal());\n                else\n                {\n                    __quatt__ q = new __quatt__(d + 1, Vec.Cross(from, into));\n                    return new __rot3t__(q.Normalized);\n                }\n            }\n\n            public static Dictionary<string, Func<__v3t__, __v3t__, __rot3t__>> All\n            {\n                get => new Dictionary<string, Func<__v3t__, __v3t__, __rot3t__>>()\n                {\n                    { \"Original\", Original },\n                    { \"Half-way vector\", HalfWayVec },\n                    { \"Half-way quaternion\", HalfWayQuat }\n                };\n            }\n        }\n\n        const int count = 1000000;\n        readonly __v3t__[] A = new __v3t__[count];\n        readonly __v3t__[] B = new __v3t__[count];\n\n        private static __v3t__ RndAxis(RandomSystem rnd)\n            => rnd.Uniform__v3t__Direction();\n\n        public RotateInto__Rtype__()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => RndAxis(rnd));\n            B.SetByIndex(i =>\n            {\n                // type = 0 -> random\n                // type = 1 -> 0 or 180° degrees with some error\n                var type = rnd.UniformInt(2);\n\n                if (type == 0)\n                {\n                    return RndAxis(rnd);\n                }\n                else if (type == 1)\n                {\n                    // Some vectors will not normalize to 1.0 -> provoke numerical issues in __v3t__\n                    var v = Vec.Normalized(A[i] * rnd.Uniform__Rtype__());\n\n                    // Add some small error\n                    if (rnd.UniformDouble() < 0.5)\n                    {\n                        //# var err = isDouble ? \"1e-22\" : \"1e-12f\";\n                        var eps = rnd.Uniform__v3t__() * (i / 100) * __err__;\n                        v = Vec.Normalized(v + eps);\n                    }\n\n                    // Flip\n                    if (rnd.UniformDouble() < 0.5)\n                        v = -v;\n\n                    return v;\n                }\n\n                return __v3t__.Zero;\n            });\n        }\n\n        private double[] ComputeAbsoluteError(Func<__v3t__, __v3t__, __rot3t__> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                __v3t__ from = A[i];\n                __v3t__ into = B[i];\n\n                __rot3t__ r = f(from, into);\n                __v3t__ res = r * from;\n\n                error[i] = Vec.AngleBetween(new V3d(res), new V3d(into));\n            }\n\n            return error;\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for __rot3t__.RotateInto() variants\");\n            Console.WriteLine();\n\n            foreach (var m in Implementations.All)\n            {\n                var errors = ComputeAbsoluteError(m.Value);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        [Test]\n        public void CorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.All)\n                {\n                    __v3t__ from = A[i];\n                    __v3t__ into = B[i];\n\n                    __rot3t__ r = f.Value(from, into);\n                    __v3t__ res = r * from;\n\n                    Assert.Less(\n                        res.AngleBetween(into), __eps__,\n                        string.Format(\"{0} implementation incorrect!\", f.Key)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public __rot3t__ Original()\n        {\n            __rot3t__ accum = __rot3t__.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.Original(A[i], B[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public __rot3t__ HalfWayVec()\n        {\n            __rot3t__ accum = __rot3t__.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.HalfWayVec(A[i], B[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public __rot3t__ HalfWayQuat()\n        {\n            __rot3t__ accum = __rot3t__.Identity;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum *= Implementations.HalfWayQuat(A[i], B[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    //# }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Tensors/MatrixMinor.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class MatrixMinor\n    {\n        private static class Implementations\n        {\n            #region Version1\n\n            public static M33d Version1(M44d m, int rowToDelete, int columnToDelete)\n            {\n                M33d result = new M33d();\n                int checked_row = 0;\n                for (int actual_row = 0; actual_row < 4; actual_row++)\n                {\n                    int checked_column = 0;\n\n                    if (actual_row != rowToDelete)\n                    {\n                        for (int actual_column = 0; actual_column < 4; actual_column++)\n                        {\n                            if (actual_column != columnToDelete)\n                            {\n                                result[checked_row, checked_column] = m[actual_row, actual_column];\n                                checked_column++;\n                            }\n                        }\n                        checked_row++;\n                    }\n                }\n                return result;\n            }\n\n            #endregion\n\n            #region Version2\n\n            public static M33d Version2(M44d m, int row, int column)\n            {\n                M33d rs = new M33d();\n                var idx = 0;\n\n                for (int k = 0; k < 16; k++)\n                {\n                    var i = k / 4;\n                    var j = k % 4;\n\n                    if (i != row && j != column)\n                    {\n                        rs[idx++] = m[k];\n                    }\n                }\n\n                return rs;\n            }\n\n            #endregion\n\n            #region Version3\n\n            public static M33d Version3(M44d m, int row, int column)\n            {\n                M33d rs = new M33d();\n\n                for (int k = 0; k < 9; k++)\n                {\n                    var i = k / 3;\n                    var j = k % 3;\n                    var ii = (i < row) ? i : i + 1;\n                    var jj = (j < column) ? j : j + 1;\n\n                    rs[k] = m[ii * 4 + jj];\n                }\n\n                return rs;\n            }\n\n            #endregion\n        }\n\n        const int count = 100000;\n        readonly M44d[] A = new M44d[count];\n        readonly int[] rows = new int[count];\n        readonly int[] columns = new int[count];\n\n        public MatrixMinor()\n        {\n            var rnd = new RandomSystem(1);\n            A.SetByIndex(i => new M44d(rnd.CreateUniformDoubleArray(16)));\n            rows.SetByIndex(i => rnd.UniformInt(4));\n            columns.SetByIndex(i => rnd.UniformInt(4));\n        }\n\n        private M33d Benchmark(Func<M44d, int, int, M33d> method)\n        {\n            M33d sum = M33d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                sum += method(A[i], rows[i], columns[i]);\n            }\n\n            return sum;\n        }\n\n        [Benchmark]\n        public M33d MinorVersion1()\n            => Benchmark(Implementations.Version1);\n\n        [Benchmark]\n        public M33d MinorVersion2()\n            => Benchmark(Implementations.Version2);\n\n        [Benchmark]\n        public M33d MinorVersion3()\n            => Benchmark(Implementations.Version3);\n\n        [Test]\n        public void MatrixMinorTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                var x = Implementations.Version1(A[i], rows[i], columns[i]);\n                var y = Implementations.Version2(A[i], rows[i], columns[i]);\n                var z = Implementations.Version3(A[i], rows[i], columns[i]);\n\n                Assert.IsTrue(Fun.ApproximateEquals(x, y, 0.00001), \"Minor({0}, {1}, {2}) \\n{3} \\n{4}\", A[i], rows[i], columns[i], x, y);\n                Assert.IsTrue(Fun.ApproximateEquals(x, z, 0.00001), \"Minor({0}, {1}, {2}) \\n{3} \\n{4}\", A[i], rows[i], columns[i], x, z);\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Tensors/MatrixMultiply.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class MatrixMultiply\n    {\n        readonly M44d[] arr44 = new M44d[100000];\n        readonly M34d[] arr34 = new M34d[100000];\n\n        //[GlobalSetup]\n        public MatrixMultiply()\n        {\n            arr44.SetByIndex(i => M44d.Translation(i, i, i));\n            arr34.SetByIndex(i => M34d.Translation(i, i, i));\n        }\n\n        [Benchmark]\n        public void M44d_Multiply()\n        {\n            var mat = M44d.RotationZ(1);\n            var local = arr44;\n            for (int i = 0; i < local.Length; i++)\n                arr44[i] = mat * local[i];\n        }\n\n        [Benchmark]\n        public void M34d_Multiply_M44d()\n        {\n            var mat = M44d.RotationZ(1);\n            var local = arr34;\n            for (int i = 0; i < local.Length; i++)\n                local[i] = local[i] * mat;\n        }\n\n        //[Benchmark]\n        //public void M44d_Multiply_M33d()\n        //{\n        //    var mat = M33d.Rotation(1);\n        //    var local = arr44;\n        //    for (int i = 0; i < local.Length; i++)\n        //        local[i] = local[i] * mat;\n        //}\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Tensors/MatrixOrthogonalize_auto.cs",
    "content": "using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    #region M22f\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class MatrixOrthogonalizeM22f\n    {\n        private struct Implementation\n        {\n            public Func<M22f, M22f> Run;\n            public float Epsilon;\n        }\n\n        private static class Implementations\n        {\n            #region Modified Gram-Schmidt\n\n            private static M22f Mgs(M22f m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                return m;\n            }\n\n            private static M22f MgsNorm(M22f m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidt\n            {\n                get => new Implementation\n                {\n                    Run = Mgs,  \n                    Epsilon = 1e-2f\n                };\n            }\n\n            public static Implementation GramSchmidtNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsNorm,\n                    Epsilon = 1e-2f\n                };\n            }\n\n            #endregion\n\n            #region Modified Gram-Schmidt (with Reorthogonalization)\n            \n            private static M22f Mgsr(M22f m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                return m;\n            }\n\n            private static M22f MgsrNorm(M22f m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidtReortho\n            {\n                get => new Implementation\n                {\n                    Run = Mgsr,\n                    Epsilon = 1e-6f\n                };\n            }\n\n            public static Implementation GramSchmidtReorthoNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsrNorm,\n                    Epsilon = 1e-6f\n                };\n            }\n\n            #endregion\n\n            public static Dictionary<string, Implementation> Orthogonalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidt },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReortho }\n                };\n            }\n\n            public static Dictionary<string, Implementation> Orthonormalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidtNorm },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReorthoNorm }\n                };\n            }\n\n            public static Dictionary<string, Implementation> All\n            {\n                get => Orthogonalize.Combine(Orthogonalize);\n            }\n        }\n\n        const int count = 100000;\n        readonly M22f[] Matrices = new M22f[count];\n\n        public MatrixOrthogonalizeM22f()\n        {\n            var rnd = new RandomSystem(1);\n            Matrices.SetByIndex(i => new M22f(rnd.CreateUniformFloatArray(16)) * 10 );\n        }\n\n        // This is probably not optimal...\n        private double ErrorMeasure(M22f matrix)\n        {\n            var m = (M22d)matrix;\n            double error = 0;\n\n            error += Vec.Dot(m.C0, m.C1).Square();\n\n            return error;\n        }\n\n        private bool AreOrtho(M22f m, float epsilon)\n        {\n            return ErrorMeasure(m) < epsilon;\n        }\n\n        private double[] ComputeAbsoluteError(Func<M22f, M22f> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var m = f(Matrices[i]);\n                error[i] = ErrorMeasure(m);\n            }\n\n            return error;\n        }\n\n        private void BenchmarkNumericalStability(string name, Dictionary<string, Implementation> methods)\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for {0} variants\", name);\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeAbsoluteError(m.Value.Run);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            BenchmarkNumericalStability(\"M22f.Orthogonalized()\", Implementations.Orthogonalize);\n            BenchmarkNumericalStability(\"M22f.Orthonormalized()\", Implementations.Orthonormalize);\n        }\n\n        [Test]\n        public void OrthogonalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthogonalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        AreOrtho(y, f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Test]\n        public void OrthonormalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthonormalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        y.IsOrthonormal(f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public M22f GramSchmidt()\n        {\n            M22f accum = M22f.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidt.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public M22f GramSchmidtWithReortho()\n        {\n            M22f accum = M22f.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidtReortho.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtReorthoNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    #region M33f\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class MatrixOrthogonalizeM33f\n    {\n        private struct Implementation\n        {\n            public Func<M33f, M33f> Run;\n            public float Epsilon;\n        }\n\n        private static class Implementations\n        {\n            #region Modified Gram-Schmidt\n\n            private static M33f Mgs(M33f m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n\n                return m;\n            }\n\n            private static M33f MgsNorm(M33f m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 = m.C2.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidt\n            {\n                get => new Implementation\n                {\n                    Run = Mgs,  \n                    Epsilon = 1e-2f\n                };\n            }\n\n            public static Implementation GramSchmidtNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsNorm,\n                    Epsilon = 1e-2f\n                };\n            }\n\n            #endregion\n\n            #region Modified Gram-Schmidt (with Reorthogonalization)\n            \n            private static M33f Mgsr(M33f m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n\n                return m;\n            }\n\n            private static M33f MgsrNorm(M33f m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 = m.C2.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidtReortho\n            {\n                get => new Implementation\n                {\n                    Run = Mgsr,\n                    Epsilon = 1e-6f\n                };\n            }\n\n            public static Implementation GramSchmidtReorthoNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsrNorm,\n                    Epsilon = 1e-6f\n                };\n            }\n\n            #endregion\n\n            public static Dictionary<string, Implementation> Orthogonalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidt },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReortho }\n                };\n            }\n\n            public static Dictionary<string, Implementation> Orthonormalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidtNorm },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReorthoNorm }\n                };\n            }\n\n            public static Dictionary<string, Implementation> All\n            {\n                get => Orthogonalize.Combine(Orthogonalize);\n            }\n        }\n\n        const int count = 100000;\n        readonly M33f[] Matrices = new M33f[count];\n\n        public MatrixOrthogonalizeM33f()\n        {\n            var rnd = new RandomSystem(1);\n            Matrices.SetByIndex(i => new M33f(rnd.CreateUniformFloatArray(16)) * 10 );\n        }\n\n        // This is probably not optimal...\n        private double ErrorMeasure(M33f matrix)\n        {\n            var m = (M33d)matrix;\n            double error = 0;\n\n            error += Vec.Dot(m.C0, m.C1).Square();\n            error += Vec.Dot(m.C0, m.C2).Square();\n            error += Vec.Dot(m.C1, m.C2).Square();\n\n            return error;\n        }\n\n        private bool AreOrtho(M33f m, float epsilon)\n        {\n            return ErrorMeasure(m) < epsilon;\n        }\n\n        private double[] ComputeAbsoluteError(Func<M33f, M33f> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var m = f(Matrices[i]);\n                error[i] = ErrorMeasure(m);\n            }\n\n            return error;\n        }\n\n        private void BenchmarkNumericalStability(string name, Dictionary<string, Implementation> methods)\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for {0} variants\", name);\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeAbsoluteError(m.Value.Run);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            BenchmarkNumericalStability(\"M33f.Orthogonalized()\", Implementations.Orthogonalize);\n            BenchmarkNumericalStability(\"M33f.Orthonormalized()\", Implementations.Orthonormalize);\n        }\n\n        [Test]\n        public void OrthogonalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthogonalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        AreOrtho(y, f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Test]\n        public void OrthonormalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthonormalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        y.IsOrthonormal(f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public M33f GramSchmidt()\n        {\n            M33f accum = M33f.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidt.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public M33f GramSchmidtWithReortho()\n        {\n            M33f accum = M33f.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidtReortho.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtReorthoNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    #region M44f\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class MatrixOrthogonalizeM44f\n    {\n        private struct Implementation\n        {\n            public Func<M44f, M44f> Run;\n            public float Epsilon;\n        }\n\n        private static class Implementations\n        {\n            #region Modified Gram-Schmidt\n\n            private static M44f Mgs(M44f m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n\n                return m;\n            }\n\n            private static M44f MgsNorm(M44f m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 = m.C2.Normalized;\n\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n                m.C3 = m.C3.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidt\n            {\n                get => new Implementation\n                {\n                    Run = Mgs,  \n                    Epsilon = 1e-2f\n                };\n            }\n\n            public static Implementation GramSchmidtNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsNorm,\n                    Epsilon = 1e-2f\n                };\n            }\n\n            #endregion\n\n            #region Modified Gram-Schmidt (with Reorthogonalization)\n            \n            private static M44f Mgsr(M44f m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n\n                return m;\n            }\n\n            private static M44f MgsrNorm(M44f m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 = m.C2.Normalized;\n\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n                m.C3 = m.C3.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidtReortho\n            {\n                get => new Implementation\n                {\n                    Run = Mgsr,\n                    Epsilon = 1e-6f\n                };\n            }\n\n            public static Implementation GramSchmidtReorthoNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsrNorm,\n                    Epsilon = 1e-6f\n                };\n            }\n\n            #endregion\n\n            public static Dictionary<string, Implementation> Orthogonalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidt },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReortho }\n                };\n            }\n\n            public static Dictionary<string, Implementation> Orthonormalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidtNorm },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReorthoNorm }\n                };\n            }\n\n            public static Dictionary<string, Implementation> All\n            {\n                get => Orthogonalize.Combine(Orthogonalize);\n            }\n        }\n\n        const int count = 100000;\n        readonly M44f[] Matrices = new M44f[count];\n\n        public MatrixOrthogonalizeM44f()\n        {\n            var rnd = new RandomSystem(1);\n            Matrices.SetByIndex(i => new M44f(rnd.CreateUniformFloatArray(16)) * 10 );\n        }\n\n        // This is probably not optimal...\n        private double ErrorMeasure(M44f matrix)\n        {\n            var m = (M44d)matrix;\n            double error = 0;\n\n            error += Vec.Dot(m.C0, m.C1).Square();\n            error += Vec.Dot(m.C0, m.C2).Square();\n            error += Vec.Dot(m.C0, m.C3).Square();\n            error += Vec.Dot(m.C1, m.C2).Square();\n            error += Vec.Dot(m.C1, m.C3).Square();\n            error += Vec.Dot(m.C2, m.C3).Square();\n\n            return error;\n        }\n\n        private bool AreOrtho(M44f m, float epsilon)\n        {\n            return ErrorMeasure(m) < epsilon;\n        }\n\n        private double[] ComputeAbsoluteError(Func<M44f, M44f> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var m = f(Matrices[i]);\n                error[i] = ErrorMeasure(m);\n            }\n\n            return error;\n        }\n\n        private void BenchmarkNumericalStability(string name, Dictionary<string, Implementation> methods)\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for {0} variants\", name);\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeAbsoluteError(m.Value.Run);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            BenchmarkNumericalStability(\"M44f.Orthogonalized()\", Implementations.Orthogonalize);\n            BenchmarkNumericalStability(\"M44f.Orthonormalized()\", Implementations.Orthonormalize);\n        }\n\n        [Test]\n        public void OrthogonalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthogonalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        AreOrtho(y, f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Test]\n        public void OrthonormalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthonormalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        y.IsOrthonormal(f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public M44f GramSchmidt()\n        {\n            M44f accum = M44f.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidt.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public M44f GramSchmidtWithReortho()\n        {\n            M44f accum = M44f.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidtReortho.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtReorthoNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    #region M22d\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class MatrixOrthogonalizeM22d\n    {\n        private struct Implementation\n        {\n            public Func<M22d, M22d> Run;\n            public double Epsilon;\n        }\n\n        private static class Implementations\n        {\n            #region Modified Gram-Schmidt\n\n            private static M22d Mgs(M22d m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                return m;\n            }\n\n            private static M22d MgsNorm(M22d m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidt\n            {\n                get => new Implementation\n                {\n                    Run = Mgs,  \n                    Epsilon = 1e-10\n                };\n            }\n\n            public static Implementation GramSchmidtNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsNorm,\n                    Epsilon = 1e-10\n                };\n            }\n\n            #endregion\n\n            #region Modified Gram-Schmidt (with Reorthogonalization)\n            \n            private static M22d Mgsr(M22d m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                return m;\n            }\n\n            private static M22d MgsrNorm(M22d m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidtReortho\n            {\n                get => new Implementation\n                {\n                    Run = Mgsr,\n                    Epsilon = 1e-14\n                };\n            }\n\n            public static Implementation GramSchmidtReorthoNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsrNorm,\n                    Epsilon = 1e-14\n                };\n            }\n\n            #endregion\n\n            public static Dictionary<string, Implementation> Orthogonalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidt },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReortho }\n                };\n            }\n\n            public static Dictionary<string, Implementation> Orthonormalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidtNorm },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReorthoNorm }\n                };\n            }\n\n            public static Dictionary<string, Implementation> All\n            {\n                get => Orthogonalize.Combine(Orthogonalize);\n            }\n        }\n\n        const int count = 100000;\n        readonly M22d[] Matrices = new M22d[count];\n\n        public MatrixOrthogonalizeM22d()\n        {\n            var rnd = new RandomSystem(1);\n            Matrices.SetByIndex(i => new M22d(rnd.CreateUniformDoubleArray(16)) * 10 );\n        }\n\n        // This is probably not optimal...\n        private double ErrorMeasure(M22d matrix)\n        {\n            var m = (M22d)matrix;\n            double error = 0;\n\n            error += Vec.Dot(m.C0, m.C1).Square();\n\n            return error;\n        }\n\n        private bool AreOrtho(M22d m, double epsilon)\n        {\n            return ErrorMeasure(m) < epsilon;\n        }\n\n        private double[] ComputeAbsoluteError(Func<M22d, M22d> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var m = f(Matrices[i]);\n                error[i] = ErrorMeasure(m);\n            }\n\n            return error;\n        }\n\n        private void BenchmarkNumericalStability(string name, Dictionary<string, Implementation> methods)\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for {0} variants\", name);\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeAbsoluteError(m.Value.Run);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            BenchmarkNumericalStability(\"M22d.Orthogonalized()\", Implementations.Orthogonalize);\n            BenchmarkNumericalStability(\"M22d.Orthonormalized()\", Implementations.Orthonormalize);\n        }\n\n        [Test]\n        public void OrthogonalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthogonalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        AreOrtho(y, f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Test]\n        public void OrthonormalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthonormalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        y.IsOrthonormal(f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public M22d GramSchmidt()\n        {\n            M22d accum = M22d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidt.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public M22d GramSchmidtWithReortho()\n        {\n            M22d accum = M22d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidtReortho.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtReorthoNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    #region M33d\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class MatrixOrthogonalizeM33d\n    {\n        private struct Implementation\n        {\n            public Func<M33d, M33d> Run;\n            public double Epsilon;\n        }\n\n        private static class Implementations\n        {\n            #region Modified Gram-Schmidt\n\n            private static M33d Mgs(M33d m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n\n                return m;\n            }\n\n            private static M33d MgsNorm(M33d m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 = m.C2.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidt\n            {\n                get => new Implementation\n                {\n                    Run = Mgs,  \n                    Epsilon = 1e-10\n                };\n            }\n\n            public static Implementation GramSchmidtNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsNorm,\n                    Epsilon = 1e-10\n                };\n            }\n\n            #endregion\n\n            #region Modified Gram-Schmidt (with Reorthogonalization)\n            \n            private static M33d Mgsr(M33d m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n\n                return m;\n            }\n\n            private static M33d MgsrNorm(M33d m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 = m.C2.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidtReortho\n            {\n                get => new Implementation\n                {\n                    Run = Mgsr,\n                    Epsilon = 1e-14\n                };\n            }\n\n            public static Implementation GramSchmidtReorthoNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsrNorm,\n                    Epsilon = 1e-14\n                };\n            }\n\n            #endregion\n\n            public static Dictionary<string, Implementation> Orthogonalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidt },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReortho }\n                };\n            }\n\n            public static Dictionary<string, Implementation> Orthonormalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidtNorm },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReorthoNorm }\n                };\n            }\n\n            public static Dictionary<string, Implementation> All\n            {\n                get => Orthogonalize.Combine(Orthogonalize);\n            }\n        }\n\n        const int count = 100000;\n        readonly M33d[] Matrices = new M33d[count];\n\n        public MatrixOrthogonalizeM33d()\n        {\n            var rnd = new RandomSystem(1);\n            Matrices.SetByIndex(i => new M33d(rnd.CreateUniformDoubleArray(16)) * 10 );\n        }\n\n        // This is probably not optimal...\n        private double ErrorMeasure(M33d matrix)\n        {\n            var m = (M33d)matrix;\n            double error = 0;\n\n            error += Vec.Dot(m.C0, m.C1).Square();\n            error += Vec.Dot(m.C0, m.C2).Square();\n            error += Vec.Dot(m.C1, m.C2).Square();\n\n            return error;\n        }\n\n        private bool AreOrtho(M33d m, double epsilon)\n        {\n            return ErrorMeasure(m) < epsilon;\n        }\n\n        private double[] ComputeAbsoluteError(Func<M33d, M33d> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var m = f(Matrices[i]);\n                error[i] = ErrorMeasure(m);\n            }\n\n            return error;\n        }\n\n        private void BenchmarkNumericalStability(string name, Dictionary<string, Implementation> methods)\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for {0} variants\", name);\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeAbsoluteError(m.Value.Run);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            BenchmarkNumericalStability(\"M33d.Orthogonalized()\", Implementations.Orthogonalize);\n            BenchmarkNumericalStability(\"M33d.Orthonormalized()\", Implementations.Orthonormalize);\n        }\n\n        [Test]\n        public void OrthogonalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthogonalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        AreOrtho(y, f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Test]\n        public void OrthonormalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthonormalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        y.IsOrthonormal(f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public M33d GramSchmidt()\n        {\n            M33d accum = M33d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidt.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public M33d GramSchmidtWithReortho()\n        {\n            M33d accum = M33d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidtReortho.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtReorthoNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    #region M44d\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class MatrixOrthogonalizeM44d\n    {\n        private struct Implementation\n        {\n            public Func<M44d, M44d> Run;\n            public double Epsilon;\n        }\n\n        private static class Implementations\n        {\n            #region Modified Gram-Schmidt\n\n            private static M44d Mgs(M44d m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n\n                return m;\n            }\n\n            private static M44d MgsNorm(M44d m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 = m.C2.Normalized;\n\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n                m.C3 = m.C3.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidt\n            {\n                get => new Implementation\n                {\n                    Run = Mgs,  \n                    Epsilon = 1e-10\n                };\n            }\n\n            public static Implementation GramSchmidtNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsNorm,\n                    Epsilon = 1e-10\n                };\n            }\n\n            #endregion\n\n            #region Modified Gram-Schmidt (with Reorthogonalization)\n            \n            private static M44d Mgsr(M44d m)\n            {\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n\n                return m;\n            }\n\n            private static M44d MgsrNorm(M44d m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 -= (Vec.Dot(m.C0, m.C1) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C1 = m.C1.Normalized;\n\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 -= (Vec.Dot(m.C0, m.C2) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C2 -= (Vec.Dot(m.C1, m.C2) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C2 = m.C2.Normalized;\n\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n                m.C3 -= (Vec.Dot(m.C0, m.C3) / Vec.Dot(m.C0, m.C0)) * m.C0;\n                m.C3 -= (Vec.Dot(m.C1, m.C3) / Vec.Dot(m.C1, m.C1)) * m.C1;\n                m.C3 -= (Vec.Dot(m.C2, m.C3) / Vec.Dot(m.C2, m.C2)) * m.C2;\n                m.C3 = m.C3.Normalized;\n\n                return m;\n            }\n\n            public static Implementation GramSchmidtReortho\n            {\n                get => new Implementation\n                {\n                    Run = Mgsr,\n                    Epsilon = 1e-14\n                };\n            }\n\n            public static Implementation GramSchmidtReorthoNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsrNorm,\n                    Epsilon = 1e-14\n                };\n            }\n\n            #endregion\n\n            public static Dictionary<string, Implementation> Orthogonalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidt },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReortho }\n                };\n            }\n\n            public static Dictionary<string, Implementation> Orthonormalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidtNorm },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReorthoNorm }\n                };\n            }\n\n            public static Dictionary<string, Implementation> All\n            {\n                get => Orthogonalize.Combine(Orthogonalize);\n            }\n        }\n\n        const int count = 100000;\n        readonly M44d[] Matrices = new M44d[count];\n\n        public MatrixOrthogonalizeM44d()\n        {\n            var rnd = new RandomSystem(1);\n            Matrices.SetByIndex(i => new M44d(rnd.CreateUniformDoubleArray(16)) * 10 );\n        }\n\n        // This is probably not optimal...\n        private double ErrorMeasure(M44d matrix)\n        {\n            var m = (M44d)matrix;\n            double error = 0;\n\n            error += Vec.Dot(m.C0, m.C1).Square();\n            error += Vec.Dot(m.C0, m.C2).Square();\n            error += Vec.Dot(m.C0, m.C3).Square();\n            error += Vec.Dot(m.C1, m.C2).Square();\n            error += Vec.Dot(m.C1, m.C3).Square();\n            error += Vec.Dot(m.C2, m.C3).Square();\n\n            return error;\n        }\n\n        private bool AreOrtho(M44d m, double epsilon)\n        {\n            return ErrorMeasure(m) < epsilon;\n        }\n\n        private double[] ComputeAbsoluteError(Func<M44d, M44d> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var m = f(Matrices[i]);\n                error[i] = ErrorMeasure(m);\n            }\n\n            return error;\n        }\n\n        private void BenchmarkNumericalStability(string name, Dictionary<string, Implementation> methods)\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for {0} variants\", name);\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeAbsoluteError(m.Value.Run);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            BenchmarkNumericalStability(\"M44d.Orthogonalized()\", Implementations.Orthogonalize);\n            BenchmarkNumericalStability(\"M44d.Orthonormalized()\", Implementations.Orthonormalize);\n        }\n\n        [Test]\n        public void OrthogonalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthogonalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        AreOrtho(y, f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Test]\n        public void OrthonormalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthonormalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        y.IsOrthonormal(f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public M44d GramSchmidt()\n        {\n            M44d accum = M44d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidt.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public M44d GramSchmidtWithReortho()\n        {\n            M44d accum = M44d.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidtReortho.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtReorthoNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Tensors/MatrixOrthogonalize_template.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    // AUTO GENERATED CODE - DO NOT CHANGE!\n\n    //# Action comma = () => Out(\", \");\n    //# Action add = () => Out(\" + \");\n    //# Action xor = () => Out(\" ^ \");\n    //# Action andLit = () => Out(\" and \");\n    //# Action andand = () => Out(\" && \");\n    //# Action oror = () => Out(\" || \");\n    //# Action addqcomma = () => Out(\" + \\\",\\\" \");\n    //# Action addbetweenM = () => Out(\" + betweenM \");\n    //# var fields = new[] {\"X\", \"Y\", \"Z\", \"W\"};\n    //# foreach (var ft in Meta.RealTypes) {\n    //# for (int n = 2; n <= 4; n++) {\n    //#     var isDouble = ft == Meta.DoubleType;\n    //#     var ftype = ft.Name;\n    //#     var Ftype = ft.Caps;\n    //#     var fc = ft.Char;\n    //#     var mnnt = \"M\" + n + n + fc;\n    //#     var mnnd = \"M\" + n + n + \"d\";\n    //#     var epsgs = isDouble ? \"1e-10\" : \"1e-2f\";\n    //#     var epsgsr = isDouble ? \"1e-14\" : \"1e-6f\";\n    #region __mnnt__\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    // Uncomment following lines for assembly output, need to add\n    //     <DebugType>pdbonly</DebugType>\n    //     <DebugSymbols>true</DebugSymbols>\n    // to Aardvark.Base.csproj for Release configuration.\n    // [DisassemblyDiagnoser(printAsm: true, printSource: true)]\n    public class MatrixOrthogonalize__mnnt__\n    {\n        private struct Implementation\n        {\n            public Func<__mnnt__, __mnnt__> Run;\n            public __ftype__ Epsilon;\n        }\n\n        private static class Implementations\n        {\n            #region Modified Gram-Schmidt\n\n            private static __mnnt__ Mgs(__mnnt__ m)\n            {\n                //# for (int j = 1; j < n; j++) {\n                //# for (int k = 0; k < j; k++) { \n                m.C__j__ -= (Vec.Dot(m.C__k__, m.C__j__) / Vec.Dot(m.C__k__, m.C__k__)) * m.C__k__;\n                //# }\n\n                //# }\n                return m;\n            }\n\n            private static __mnnt__ MgsNorm(__mnnt__ m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                //# for (int j = 1; j < n; j++) {\n                //# for (int k = 0; k < j; k++) { \n                m.C__j__ -= (Vec.Dot(m.C__k__, m.C__j__) / Vec.Dot(m.C__k__, m.C__k__)) * m.C__k__;\n                //# }\n                m.C__j__ = m.C__j__.Normalized;\n\n                //# }\n                return m;\n            }\n\n            public static Implementation GramSchmidt\n            {\n                get => new Implementation\n                {\n                    Run = Mgs,  \n                    Epsilon = __epsgs__\n                };\n            }\n\n            public static Implementation GramSchmidtNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsNorm,\n                    Epsilon = __epsgs__\n                };\n            }\n\n            #endregion\n\n            #region Modified Gram-Schmidt (with Reorthogonalization)\n            \n            private static __mnnt__ Mgsr(__mnnt__ m)\n            {\n                //# for (int j = 1; j < n; j++) {\n                //# for (int i = 0; i < 2; i++) {\n                //# for (int k = 0; k < j; k++) { \n                m.C__j__ -= (Vec.Dot(m.C__k__, m.C__j__) / Vec.Dot(m.C__k__, m.C__k__)) * m.C__k__;\n                //# }\n                //# }\n\n                //# }\n                return m;\n            }\n\n            private static __mnnt__ MgsrNorm(__mnnt__ m)\n            {\n                m.C0 = m.C0.Normalized;\n\n                //# for (int j = 1; j < n; j++) {\n                //# for (int i = 0; i < 2; i++) {\n                //# for (int k = 0; k < j; k++) { \n                m.C__j__ -= (Vec.Dot(m.C__k__, m.C__j__) / Vec.Dot(m.C__k__, m.C__k__)) * m.C__k__;\n                //# }\n                //# }\n                m.C__j__ = m.C__j__.Normalized;\n\n                //# }\n                return m;\n            }\n\n            public static Implementation GramSchmidtReortho\n            {\n                get => new Implementation\n                {\n                    Run = Mgsr,\n                    Epsilon = __epsgsr__\n                };\n            }\n\n            public static Implementation GramSchmidtReorthoNorm\n            {\n                get => new Implementation\n                {\n                    Run = MgsrNorm,\n                    Epsilon = __epsgsr__\n                };\n            }\n\n            #endregion\n\n            public static Dictionary<string, Implementation> Orthogonalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidt },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReortho }\n                };\n            }\n\n            public static Dictionary<string, Implementation> Orthonormalize\n            {\n                get => new Dictionary<string, Implementation>()\n                {\n                    { \"Gram-Schmidt\", GramSchmidtNorm },\n                    { \"Gram-Schmidt with Reorthogonalization\", GramSchmidtReorthoNorm }\n                };\n            }\n\n            public static Dictionary<string, Implementation> All\n            {\n                get => Orthogonalize.Combine(Orthogonalize);\n            }\n        }\n\n        const int count = 100000;\n        readonly __mnnt__[] Matrices = new __mnnt__[count];\n\n        public MatrixOrthogonalize__mnnt__()\n        {\n            var rnd = new RandomSystem(1);\n            Matrices.SetByIndex(i => new __mnnt__(rnd.CreateUniform__Ftype__Array(16)) * 10 );\n        }\n\n        // This is probably not optimal...\n        private double ErrorMeasure(__mnnt__ matrix)\n        {\n            var m = (__mnnd__)matrix;\n            double error = 0;\n\n            //# for (int j = 0; j < n; j++) {\n            //# for (int k = j + 1; k < n; k++) {\n            error += Vec.Dot(m.C__j__, m.C__k__).Square();\n            //# }\n            //# }\n\n            return error;\n        }\n\n        private bool AreOrtho(__mnnt__ m, __ftype__ epsilon)\n        {\n            return ErrorMeasure(m) < epsilon;\n        }\n\n        private double[] ComputeAbsoluteError(Func<__mnnt__, __mnnt__> f)\n        {\n            double[] error = new double[count];\n\n            for (int i = 0; i < count; i++)\n            {\n                var m = f(Matrices[i]);\n                error[i] = ErrorMeasure(m);\n            }\n\n            return error;\n        }\n\n        private void BenchmarkNumericalStability(string name, Dictionary<string, Implementation> methods)\n        {\n            Console.WriteLine(\"Benchmarking numerical stability for {0} variants\", name);\n            Console.WriteLine();\n\n            foreach (var m in methods)\n            {\n                var errors = ComputeAbsoluteError(m.Value.Run);\n                var min = errors.Min();\n                var max = errors.Max();\n                var mean = errors.Mean();\n                var var = errors.Variance();\n\n                Report.Begin(\"Absolute error for '{0}'\", m.Key);\n                Report.Line(\"Min = {0}\", min);\n                Report.Line(\"Max = {0}\", max);\n                Report.Line(\"Mean = {0}\", mean);\n                Report.Line(\"Variance = {0}\", var);\n                Report.End();\n\n                Console.WriteLine();\n            }\n        }\n\n        public void BenchmarkNumericalStability()\n        {\n            BenchmarkNumericalStability(\"__mnnt__.Orthogonalized()\", Implementations.Orthogonalize);\n            BenchmarkNumericalStability(\"__mnnt__.Orthonormalized()\", Implementations.Orthonormalize);\n        }\n\n        [Test]\n        public void OrthogonalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthogonalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        AreOrtho(y, f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Test]\n        public void OrthonormalizeCorrectnessTest()\n        {\n            for (int i = 0; i < count; i++)\n            {\n                foreach (var f in Implementations.Orthonormalize)\n                {\n                    var x = Matrices[i];\n                    var y = f.Value.Run(x);\n\n                    Assert.IsTrue(\n                        y.IsOrthonormal(f.Value.Epsilon),\n                        string.Format(\"{0} failed.\\n\" +\n                        \"Input = {1}\\n\" +\n                        \"Output = {2}\",\n                        f.Key, x, y)\n                    );\n                }\n            }\n        }\n\n        [Benchmark]\n        public __mnnt__ GramSchmidt()\n        {\n            __mnnt__ accum = __mnnt__.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidt.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n\n        [Benchmark]\n        public __mnnt__ GramSchmidtWithReortho()\n        {\n            __mnnt__ accum = __mnnt__.Zero;\n\n            for (int i = 0; i < count; i++)\n            {\n                accum += Implementations.GramSchmidtReortho.Run(Matrices[i]);\n                accum += Implementations.GramSchmidtReorthoNorm.Run(Matrices[i]);\n            }\n\n            return accum;\n        }\n    }\n\n    #endregion\n\n    //# } }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Tensors/MatrixSampling.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //BenchmarkDotNet=v0.12.0, OS=Windows 10.0.19041\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET Core SDK = 5.0.100\n\n    // [Host]     : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT\n    // DefaultJob : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT\n\n    //|                  Method |     Mean |    Error |   StdDev |    Gen 0 | Gen 1 | Gen 2 | Allocated |\n    //|------------------------ |---------:|---------:|---------:|---------:|------:|------:|----------:|\n    //|          Sample4Clamped | 641.1 us | 12.65 us | 18.53 us | 203.1250 |     - |     - |   1.22 MB |\n    //|    Sample4Clamped (Old) | 140.0 us |  0.46 us |  0.43 us |        - |     - |     - |       1 B |\n    //| Sample4Clamped (ValTup) | 140.5 us |  0.86 us |  0.72 us |        - |     - |     - |       1 B |\n\n    [PlainExporter, MemoryDiagnoser]\n    public class MatrixSampling\n    {\n        public Matrix<float> m_mat;\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            m_mat = new Matrix<float>(100, 100, 1.0f);\n        }\n\n[Benchmark]\npublic float Sample4Clamped()\n{\n    var sum = 0f;\n    for(int x = 0; x < 100; x++)\n        for (int y = 0; y < 100; y++)\n            sum += m_mat.Sample4Clamped(x, x, (t, a, b) => Fun.Lerp((float)t, a, b), (t, a, b) => Fun.Lerp((float)t, a, b));\n    return sum;\n}\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Tensors/TensorMathBenchmark.cs",
    "content": "﻿using Aardvark.Base.IL;\nusing BenchmarkDotNet.Attributes;\nusing System;\nusing System.Runtime.CompilerServices;\nusing static Aardvark.Base.Monads.Optics;\nusing System.Runtime.Intrinsics.X86;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    /*\n     * Benchmark indicates that inlined implementations are noticeably more efficient than\n     * simply using Norm or InnerProduct and passing lambda functions. Therefore it may be wise to implement\n     * common tensor operations in a dumb inline way for optimization purposes. The InlineIfLambda attribute\n     * in F# might mitigate this but we are dealing with C# here.\n     *\n     * BenchmarkDotNet v0.13.9+228a464e8be6c580ad9408e98f18813f6407fb5a, Windows 10 (10.0.19045.4170/22H2/2022Update)\n     * AMD Ryzen 5 5600X, 1 CPU, 12 logical and 6 physical cores\n     * .NET SDK 6.0.420\n     *   [Host] : .NET 6.0.28 (6.0.2824.12007), X64 RyuJIT AVX2\n     *\n     * Job = InProcess  Toolchain=InProcessEmitToolchain\n     *\n     * | Method                     | Mean       | Error    | StdDev   | Ratio | RatioSD | Allocated | Alloc Ratio |\n     * |--------------------------- |-----------:|---------:|---------:|------:|--------:|----------:|------------:|\n     * | NormSquared                | 1,377.5 us | 24.30 us | 23.87 us |  1.00 |    0.00 |       6 B |        1.00 |\n     * | 'NormSquared (Predefined)' | 1,771.9 us | 35.15 us | 40.48 us |  1.28 |    0.04 |       1 B |        0.17 |\n     * | 'NormSquared (Inline)'     |   340.1 us |  1.77 us |  1.48 us |  0.25 |    0.00 |         - |        0.00 |\n     */\n\n    [InProcess]\n    [MemoryDiagnoser]\n    public class VectorNormSquared\n    {\n        private static readonly Func<float, float> SquareFunc = Fun.Square;\n        private static readonly Func<float, float, float> AddFunc = (x, y) => x + y;\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static float NormSquared(Vector<float> vector)\n            => vector.Norm(x => x * x, 0.0f, (x, y) => x + y);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static float NormSquaredPredefined(Vector<float> vector)\n            => vector.Norm(SquareFunc, 0.0f, AddFunc);\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static float NormSquaredInline(Vector<float> v)\n        {\n            float result = 0.0f;\n            long i = v.FirstIndex;\n            if (v.Info.DX == 1)\n            {\n                long xs = v.Info.SX;\n                for (long xe = i + xs; i != xe; i++)\n                {\n                    result += v.Data[i] * v.Data[i];\n                }\n            }\n            else\n            {\n                long xs = v.Info.DSX, xj = v.Info.JX;\n                for (long xe = i + xs; i != xe; i += xj)\n                {\n                    result += v.Data[i] * v.Data[i];\n                }\n            }\n            return result;\n        }\n\n        private static Vector<float> GenerateVector(RandomSystem rnd)\n            => Vector.Create(new float[4 + rnd.UniformInt(1000)].SetByIndex(i => rnd.UniformFloat()));\n\n        Vector<float>[] _data;\n\n        [GlobalSetup]\n        public void Init()\n        {\n            var rnd = new RandomSystem(0);\n            _data = new Vector<float>[1000].SetByIndex(i => GenerateVector(rnd));\n        }\n\n        [Benchmark(Baseline = true, Description = \"NormSquared\")]\n        public float NormSquared()\n        {\n            float sum = 0;\n            foreach (var x in _data)\n                sum += NormSquared(x);\n            return sum;\n        }\n\n        [Benchmark(Description = \"NormSquared (Predefined)\")]\n        public float NormSquaredPredfined()\n        {\n            float sum = 0;\n            foreach (var x in _data)\n                sum += NormSquaredPredefined(x);\n            return sum;\n        }\n\n        [Benchmark(Description = \"NormSquared (Inline)\")]\n        public float NormSquaredInline()\n        {\n            float sum = 0;\n            foreach (var x in _data)\n                sum += NormSquaredInline(x);\n            return sum;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/Transform.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18362\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET Core SDK = 3.1.201\n\n    // [Host]     : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT\n    // Job-HKXJIN : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT\n\n    //Runtime=.NET Core 3.0\n\n    //|               Method |       Mean |   Error |  StdDev |\n    //|--------------------- |-----------:|--------:|--------:|\n    //|  TrafoM44d_Transform |   711.2 us | 7.49 us | 6.64 us |\n    //|  Euclidean_Transform |   711.1 us | 4.77 us | 4.46 us |\n    //| Similarity_Transform | 1,639.8 us | 6.79 us | 6.35 us |\n    //|     Affine_Transform |   545.6 us | 3.12 us | 2.92 us |\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class TransformV3d\n    {\n        readonly V3d[] arr = new V3d[100000];\n\n        M44d trafo = M44d.RotationX(Constant.Pi);\n        Euclidean3d euclidean = Euclidean3d.RotationX(Constant.Pi);\n        Similarity3d similarity = Similarity3d.RotationX(Constant.Pi);\n        Affine3d affine = Affine3d.RotationX(Constant.Pi);\n\n        [Benchmark]\n        public void TrafoM44d_Transform()\n        {\n            var t = trafo;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = t.TransformPos(arr[i]);\n        }\n\n        [Benchmark]\n        public void Euclidean_Transform()\n        {\n            var t = euclidean;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = t.TransformPos(arr[i]);\n        }\n\n        [Benchmark]\n        public void Similarity_Transform()\n        {\n            var t = similarity;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = t.TransformPos(arr[i]);\n        }\n\n        [Benchmark]\n        public void Affine_Transform()\n        {\n            var t = affine;\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = t.TransformPos(arr[i]);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Math/VectorLength.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing NUnit.Framework;\nusing System;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //[SimpleJob(RuntimeMoniker.Net472)]\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class V4fLength\n    {\n        readonly V4f[] arr = new V4f[1000000];\n\n        //[GlobalSetup]\n        public V4fLength()\n        {\n            var rnd1 = new RandomSystem(1);\n            arr.SetByIndex(i => new V4f(rnd1.UniformFloat(), rnd1.UniformFloat(), rnd1.UniformFloat(), rnd1.UniformFloat()));\n        }\n\n        [Benchmark]\n        public float V4fLengthReference()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n            {\n                var v = local[i];\n                sum += MathF.Sqrt(v.X * v.X + v.Y * v.Y + v.Z * v.Z + v.W * v.W);\n            }\n            return sum;\n        }\n\n        [Benchmark]\n        public float V4fLengthSse()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n            {\n                sum += local[i].Length;\n            }\n            return sum;\n        }\n    }\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class V3fLength\n    {\n        readonly V3f[] arr = new V3f[1000000];\n\n        //[GlobalSetup]\n        public V3fLength()\n        {\n            var rnd1 = new RandomSystem(1);\n            arr.SetByIndex(i => new V3f(rnd1.UniformFloat(), rnd1.UniformFloat(), rnd1.UniformFloat()));\n        }\n\n        [Benchmark]\n        public float V3fLengthReference()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n            {\n                var v = local[i];\n                sum += MathF.Sqrt(v.X * v.X + v.Y * v.Y + v.Z * v.Z);\n            }\n            return sum;\n        }\n\n        [Benchmark]\n        public float V3fLengthSse()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n            {\n                sum += local[i].Length;\n            }\n            return sum;\n        }\n    }\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class V2fLength\n    {\n        readonly V2f[] arr = new V2f[1000000];\n\n        //[GlobalSetup]\n        public V2fLength()\n        {\n            var rnd1 = new RandomSystem(1);\n            arr.SetByIndex(i => new V2f(rnd1.UniformFloat(), rnd1.UniformFloat()));\n        }\n\n        [Benchmark]\n        public float V2fLengthReference()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n            {\n                var v = local[i];\n                sum += MathF.Sqrt(v.X * v.X + v.Y * v.Y);\n            }\n            return sum;\n        }\n\n        [Benchmark]\n        public float V2fLengthSse()\n        {\n            var local = arr;\n            var sum = 0.0f;\n            for (int i = 0; i < local.Length; i++)\n            {\n                sum += local[i].Length;\n            }\n            return sum;\n        }\n    }\n\n    public class Tests\n    {\n        [Test]\n        public void V2fLength()\n        {\n            var test = new V2fLength();\n            Assert.IsTrue(test.V2fLengthReference() == test.V2fLengthSse());\n        }\n\n        [Test]\n        public void V3fLength()\n        {\n            var test = new V3fLength();\n            Assert.IsTrue(test.V3fLengthReference() == test.V3fLengthSse());\n        }\n\n        [Test]\n        public void V4fLength()\n        {\n            var test = new V4fLength();\n            Assert.IsTrue(test.V4fLengthReference() == test.V4fLengthSse());\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/Program.cs",
    "content": "﻿using BenchmarkDotNet.Running;\nusing BenchmarkDotNet.Configs;\nusing Aardvark.Base.Benchmarks.Geometry;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var cfg = ManualConfig.Create(DefaultConfig.Instance).WithOptions(ConfigOptions.DisableOptimizationsValidator);\n            var switcher = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly);\n            if (args.Length > 0)\n            {\n                switcher.Run(args, cfg);\n                return;\n            }\n\n            //BenchmarkRunner.Run<HashBench>(cfg);\n            //BenchmarkRunner.Run<StreamWriterReader>(cfg);\n\n            BenchmarkRunner.Run<SolidAngle>(cfg);\n\n            //BenchmarkRunner.Run<V4fLength>();\n            //BenchmarkRunner.Run<V3fLeng\n            //BenchmarkRunner.Run<V2fLength>();\n            //BenchmarkRunner.Run<CodeGenTests>();\n            //BenchmarkRunner.Run<AngleBetweenFloat>();\n            //BenchmarkRunner.Run<AngleBetweenDouble>();\n\n            //var tf = new AngleBetweenFloat();\n            //tf.BenchmarkNumericalStability();\n\n            //var td = new AngleBetweenDouble();\n            //td.BenchmarkNumericalStability();\n\n            //var tf = new RotateIntoFloat();\n            //tf.BenchmarkNumericalStability();\n\n            //var td = new RotateIntoDouble();\n            //td.BenchmarkNumericalStability();\n\n            //var tf = new Rot3fGetEuler();\n            //tf.BenchmarkNumericalStability();\n\n            //var td = new Rot3dGetEuler();\n            //td.BenchmarkNumericalStability();\n\n            //var tf2 = new MatrixOrthogonalizeM22f();\n            //tf2.BenchmarkNumericalStability();\n\n            //var td2 = new MatrixOrthogonalizeM22d();\n            //td2.BenchmarkNumericalStability();\n\n            //var tf3 = new MatrixOrthogonalizeM33f();\n            //tf3.BenchmarkNumericalStability();\n\n            //var td3 = new MatrixOrthogonalizeM33d();\n            //td3.BenchmarkNumericalStability();\n\n            //var tf4 = new MatrixOrthogonalizeM44f();\n            //tf4.BenchmarkNumericalStability();\n\n            //var td4 = new MatrixOrthogonalizeM44d();\n            //td4.BenchmarkNumericalStability();\n\n            //BenchmarkRunner.Run<Rot3dTransform>();\n            //BenchmarkRunner.Run<StaticConstants>();\n            //BenchmarkRunner.Run<MatrixMultiply>();\n            //BenchmarkRunner.Run<IntegerPowerFloat>();\n            //BenchmarkRunner.Run<IntegerPowerDouble>();\n            //BenchmarkRunner.Run<IntegerPowerInt>();\n            //BenchmarkRunner.Run<IntegerPowerLong>();\n            //BenchmarkRunner.Run<RotateIntoFloat>();\n            //BenchmarkRunner.Run<RotateIntoDouble>();\n            //BenchmarkRunner.Run<Rot3fGetEuler>();\n            //BenchmarkRunner.Run<Rot3dGetEuler>();\n            //BenchmarkRunner.Run<MatrixOrthogonalizeM22f>();\n            //BenchmarkRunner.Run<MatrixOrthogonalizeM22d>();\n            //BenchmarkRunner.Run<Indexers2>();\n            //BenchmarkRunner.Run<Indexers3>();\n            //BenchmarkRunner.Run<Indexers4>();\n            //BenchmarkRunner.Run<MatrixMinor>();\n            //BenchmarkRunner.Run<TransformV3d>();\n            //BenchmarkRunner.Run<Log2Int>();\n            //BenchmarkRunner.Run<Log2>();\n            //BenchmarkRunner.Run<Enumerators>();\n            //BenchmarkRunner.Run<IntSetCreator>();\n            //BenchmarkRunner.Run<ArrayInit>();\n            //BenchmarkRunner.Run<ArraySum>();\n            //BenchmarkRunner.Run<SomeApp.HashCodeCombine>();\n            //BenchmarkRunner.Run<MatrixSampling>();\n            //BenchmarkRunner.Run<TelemetryProbesBenchmark>();\n\n            //new Enumerators().Test();\n\n            //BenchmarkRunner.Run<RayHitTest>();\n            //BenchmarkRunner.Run<ConstantsBenchmark>();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/StaticConstants.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    struct StructThing\n    {\n        public double X, Y, Z; // adding Z prevents automatic inlining of ConstX/Y\n\n        public static StructThing ConstXAggro { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new StructThing(1, 0, 0); }\n        public static StructThing ConstYAggro { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new StructThing(0, 1, 0); }\n\n        public static StructThing ConstX { get => new StructThing(1, 0, 0); }\n        public static StructThing ConstY { get => new StructThing(0, 1, 0); }\n\n        public static readonly StructThing ReadonlyX = new StructThing(1, 0, 0);\n        public static readonly StructThing ReadonlyY = new StructThing(0, 1, 0);\n\n        public StructThing(double x, double y, double z)\n        {\n            X = x;\n            Y = y;\n            Z = z;\n        }\n\n        public readonly StructThing DoMath(StructThing b)\n        {\n            return new StructThing(\n                Y * b.X - X * b.Y,\n                X * b.Y - Y * b.X,\n                Z * b.Z);\n        }\n    }\n\n    [SimpleJob(RuntimeMoniker.NetCoreApp31)]\n    [DisassemblyDiagnoser(printSource: true)]\n    public class StaticConstants\n    {\n        readonly StructThing[] arr = new StructThing[500000];\n\n        public StaticConstants()\n        {\n            var rnd1 = new Random(1);\n            for (int i = 0; i < arr.Length; i++)\n                arr[i] = new StructThing(rnd1.NextDouble(), rnd1.NextDouble(), rnd1.NextDouble());\n        }\n\n        [Benchmark]\n        public void ReadonlyConstant()\n        {\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = StructThing.ReadonlyX.DoMath(StructThing.ReadonlyY);\n        }\n\n        [Benchmark]\n        public void PropertyConstant()\n        {\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = StructThing.ConstX.DoMath(StructThing.ConstY);\n        }\n\n        [Benchmark]\n        public void PropertyConstantAggro()\n        {\n            var local = arr;\n            for (int i = 0; i < local.Length; i++)\n                arr[i] = StructThing.ConstXAggro.DoMath(StructThing.ConstYAggro);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/StreamWriterReader.cs",
    "content": "﻿using Aardvark.Base.Coder;\nusing BenchmarkDotNet.Attributes;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //BenchmarkDotNet v0.13.9+228a464e8be6c580ad9408e98f18813f6407fb5a, Windows 10 (10.0.19045.4291/22H2/2022Update)\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET SDK 6.0.421\n    //  [Host] : .NET 6.0.29 (6.0.2924.17105), X64 RyuJIT AVX2\n\n    //Job = InProcess  Toolchain=InProcessEmitToolchain\n\n    //| Method     | Size | Mean      | Error    | StdDev   | Allocated |\n    //|----------- |----- |----------:|---------:|---------:|----------:|\n    //| WriteArray | 10   |  39.21 ns | 0.062 ns | 0.048 ns |         - |\n    //| ReadArray  | 10   |  12.73 ns | 0.098 ns | 0.092 ns |         - |\n    //| WriteArray | 100  |  54.25 ns | 0.259 ns | 0.229 ns |         - |\n    //| ReadArray  | 100  |  17.63 ns | 0.129 ns | 0.114 ns |         - |\n    //| WriteArray | 1000 | 139.65 ns | 0.589 ns | 0.522 ns |         - |\n    //| ReadArray  | 1000 |  48.70 ns | 0.275 ns | 0.258 ns |         - |\n\n    // OLD: \n    //| Method     | Size | Mean        | Error     | StdDev    | Allocated |\n    //|----------- |----- |------------:|----------:|----------:|----------:|\n    //| WriteArray | 10   |    61.18 ns |  0.357 ns |  0.334 ns |         - |\n    //| ReadArray  | 10   |    34.82 ns |  0.189 ns |  0.158 ns |         - |\n    //| WriteArray | 100  |   316.98 ns |  0.696 ns |  0.617 ns |         - |\n    //| ReadArray  | 100  |    39.43 ns |  0.132 ns |  0.110 ns |         - |\n    //| WriteArray | 1000 | 2,883.07 ns | 24.201 ns | 20.209 ns |         - |\n    //| ReadArray  | 1000 |    74.27 ns |  0.193 ns |  0.171 ns |         - |\n\n    [InProcess]\n    [PlainExporter, MemoryDiagnoser]\n    public class StreamWriterReader\n    {\n        float[] _data;\n        StreamCodeWriter _writer;\n        StreamCodeReader _reader;\n\n        [Params(10, 100, 1000)]\n        public int Size;\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            _data = new float[Size].SetByIndex(i => i);\n            _writer = new StreamCodeWriter(new MemoryStream(_data.Length * 4));\n\n            var tmpWriter = new StreamCodeWriter(new MemoryStream(_data.Length * 4));\n            tmpWriter.WriteArray(_data, 0, _data.Length);\n            _reader = new StreamCodeReader(tmpWriter.BaseStream);\n        }\n\n        [Benchmark]\n        public void WriteArray()\n        {\n            _writer.BaseStream.Position = 0;\n            _writer.WriteArray(_data, 0, _data.Length);\n        }\n\n        [Benchmark]\n        public void ReadArray()\n        {\n            _reader.BaseStream.Position = 0;\n            _reader.ReadArray(_data, 0, _data.Length);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/TelemetryProbesBenchmark.cs",
    "content": "﻿using BenchmarkDotNet.Attributes;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Aardvark.Base.Benchmarks\n{\n    //BenchmarkDotNet=v0.12.0, OS=Windows 10.0.19041\n    //Intel Core i7-8700K CPU 3.70GHz(Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n    //.NET Core SDK = 5.0.100\n\n    // [Host]     : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT\n    // DefaultJob : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT\n\n    //|                       Method |     Mean |   Error |   StdDev |    Gen 0 | Gen 1 | Gen 2 | Allocated |\n    //|----------------------------- |---------:|--------:|---------:|---------:|------:|------:|----------:|\n    //|                StopWatchTime | 347.2 us | 6.90 us | 13.47 us | 127.4414 |     - |     - |  800000 B |\n    //|     StopWatchTime (No Alloc) | 258.1 us | 5.10 us |  9.70 us |  31.7383 |     - |     - |  200000 B |\n    //|                      CPUTime | 267.2 us | 5.84 us |  6.25 us |  76.1719 |     - |     - | 468.75 KB |\n    //|           CPUTime (No Alloc) | 197.6 us | 3.52 us |  2.94 us |        - |     - |     - |         - |\n    //|                    WallClock | 308.3 us | 4.79 us |  4.48 us |  69.8242 |     - |     - |  440000 B |\n    //|         WallClock (No Alloc) | 243.4 us | 2.94 us |  2.60 us |        - |     - |     - |       1 B |\n    //|                  CpuTimeUser | 266.9 us | 1.49 us |  1.40 us |  50.7813 |     - |     - |  320001 B |\n    //|       CpuTimeUser (No Alloc) | 234.4 us | 2.73 us |  2.28 us |        - |     - |     - |         - |\n    //|            CpuTimePrivileged | 279.9 us | 4.85 us |  4.05 us |  50.7813 |     - |     - |  320001 B |\n    //| CpuTimePrivileged (No Alloc) | 226.9 us | 5.45 us |  9.96 us |        - |     - |     - |         - |\n\n    [MemoryDiagnoser, PlainExporter]\n    public class TelemetryProbesBenchmark\n    {\n        readonly Telemetry.StopWatchTime StopWatchProbe = new Telemetry.StopWatchTime();\n        readonly Telemetry.CpuTime CPUProbe = new Telemetry.CpuTime();\n        readonly Telemetry.WallClockTime WallProbe = new Telemetry.WallClockTime();\n        readonly Telemetry.CpuTimeUser CPUUserProbe = new Telemetry.CpuTimeUser();\n        readonly Telemetry.CpuTimePrivileged CPUPrivilegedProbe = new Telemetry.CpuTimePrivileged();\n\n        readonly double[] m_data = new double[10000].SetByIndex(i => i + 1);\n\n        [Benchmark]\n        public int StopWatchTime()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 2;)\n                using (StopWatchProbe.Timer)\n                    sum += HashCode.Combine(m_data[i++].GetHashCode(), m_data[i++].GetHashCode());\n            return sum;\n        }\n\n        [Benchmark]\n        public int CPUTime()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 2;)\n                using (CPUProbe.Timer)\n                    sum += HashCode.Combine(m_data[i++].GetHashCode(), m_data[i++].GetHashCode());\n            return sum;\n        }\n\n        [Benchmark]\n        public int WallClock()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 2;)\n                using (WallProbe.Timer)\n                    sum += HashCode.Combine(m_data[i++].GetHashCode(), m_data[i++].GetHashCode());\n            return sum;\n        }\n\n        [Benchmark]\n        public int CpuTimeUser()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 2;)\n                using (CPUUserProbe.Timer)\n                    sum += HashCode.Combine(m_data[i++].GetHashCode(), m_data[i++].GetHashCode());\n            return sum;\n        }\n\n        [Benchmark]\n        public int CpuTimePrivileged()\n        {\n            int sum = 0;\n            for (int i = 0; i <= m_data.Length - 2;)\n                using (CPUPrivilegedProbe.Timer)\n                    sum += HashCode.Combine(m_data[i++].GetHashCode(), m_data[i++].GetHashCode());\n            return sum;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Benchmarks/paket.references",
    "content": "group Test\n\nBenchmarkDotNet\nNUnit\nNUnit3TestAdapter\nMicrosoft.NET.Test.Sdk"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/Aardvark.Base.FSharp.Benchmarks.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <GenerateProgramFile>false</GenerateProgramFile>\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n    <WarnOn>3389;3390;3395</WarnOn>\n    <Deterministic>false</Deterministic>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n    <DebugType>pdbonly</DebugType>\n    <DebugSymbols>true</DebugSymbols>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n    <DebugType>pdbonly</DebugType>\n    <DebugSymbols>true</DebugSymbols>\n  </PropertyGroup>\n  <ItemGroup>\n    <None Include=\"paket.references\" />\n    <None Include=\"Tuples_template.fs\" />\n    <Compile Include=\"Tuples_auto.fs\" />\n    <Compile Include=\"ActivePatterns.fs\" />\n    <Compile Include=\"TensorUtilitiesBench.fs\" />\n    <Compile Include=\"TensorMathBench.fs\" />\n    <Compile Include=\"DynamicDispatchBench.fs\" />\n    <Compile Include=\"TypePatternsBench.fs\" />\n    <Compile Include=\"ReferenceCountingSetBench.fs\" />\n    <Compile Include=\"NullCheckBench.fs\" />\n    <Compile Include=\"ArrayChooseBench.fs\" />\n    <Compile Include=\"BvhIntersectBench.fs\" />\n    <Compile Include=\"Program.fs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\n    <ProjectReference Include=\"..\\Aardvark.Base.FSharp.Tests\\Aardvark.Base.FSharp.Tests.fsproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/ActivePatterns.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\nopen Aardvark.Base\nopen BenchmarkDotNet.Attributes;\n\n// BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.4170/22H2/2022Update)\n// Intel Core i5-4690K CPU 3.50GHz (Haswell), 1 CPU, 4 logical and 4 physical cores\n// .NET SDK 8.0.202\n//   [Host] : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2 DEBUG\n//\n// Job=ShortRun  Toolchain=InProcessEmitToolchain  IterationCount=3\n// LaunchCount=1  WarmupCount=3\n//\n// | Method                    | Count | Mean         | Error         | StdDev     | Gen0    | Allocated |\n// |-------------------------- |------ |-------------:|--------------:|-----------:|--------:|----------:|\n// | 'No arguments'            | 10    |     25.14 ns |      2.280 ns |   0.125 ns |  0.0382 |     120 B |\n// | 'No arguments (struct)'   | 10    |     16.40 ns |      0.291 ns |   0.016 ns |       - |         - |\n// | 'Tuple argument'          | 10    |     50.27 ns |     10.427 ns |   0.572 ns |  0.0765 |     240 B |\n// | 'Tuple argument (struct)' | 10    |     30.82 ns |      1.718 ns |   0.094 ns |  0.0382 |     120 B |\n// | 'No arguments'            | 100   |    226.12 ns |     33.508 ns |   1.837 ns |  0.3595 |    1128 B |\n// | 'No arguments (struct)'   | 100   |    160.52 ns |      2.508 ns |   0.137 ns |       - |         - |\n// | 'Tuple argument'          | 100   |    484.78 ns |    131.758 ns |   7.222 ns |  0.7191 |    2256 B |\n// | 'Tuple argument (struct)' | 100   |    299.99 ns |     24.918 ns |   1.366 ns |  0.3595 |    1128 B |\n// | 'No arguments'            | 1000  |  2,357.40 ns |  1,561.574 ns |  85.595 ns |  3.7613 |   11808 B |\n// | 'No arguments (struct)'   | 1000  |  1,613.16 ns |    145.925 ns |   7.999 ns |       - |         - |\n// | 'Tuple argument'          | 1000  |  6,036.04 ns |    203.476 ns |  11.153 ns |  7.5226 |   23616 B |\n// | 'Tuple argument (struct)' | 1000  |  3,176.44 ns |    361.053 ns |  19.791 ns |  3.7613 |   11808 B |\n// | 'No arguments'            | 10000 | 47,907.05 ns |  4,206.151 ns | 230.553 ns | 37.7808 |  118536 B |\n// | 'No arguments (struct)'   | 10000 | 38,801.61 ns |    171.534 ns |   9.402 ns |       - |         - |\n// | 'Tuple argument'          | 10000 | 83,620.55 ns |  6,288.851 ns | 344.713 ns | 75.5615 |  237072 B |\n// | 'Tuple argument (struct)' | 10000 | 64,376.48 ns | 11,741.490 ns | 643.591 ns | 37.7197 |  118536 B |\n\nmodule ActivePatternsBenchmarks =\n\n    let inline (|Odd|_|) (value: int) =\n        if value % 2 = 1 then Some ()\n        else None\n\n    [<return: Struct>]\n    let inline (|OddV|_|) (value: int) =\n        if value % 2 = 1 then ValueSome ()\n        else ValueNone\n\n    let inline (|OddTuple|_|) (value: int) =\n        if value % 2 = 1 then Some (value, value)\n        else None\n\n    [<return: Struct>]\n    let inline (|OddTupleV|_|) (value: int) =\n        if value % 2 = 1 then ValueSome (value, value)\n        else ValueNone\n\n    [<MemoryDiagnoser>]\n    type ``Active Patterns``() =\n        let rnd = RandomSystem(0)\n        let mutable data = null\n\n        [<DefaultValue; Params(10, 100, 1000, 10000)>]\n        val mutable Count : int\n\n        [<GlobalSetup>]\n        member x.Init() =\n            data <- Array.init x.Count (ignore >> rnd.UniformInt)\n\n        [<Benchmark(Description = \"No arguments\")>]\n        member x.NoArguments() =\n            let mutable cnt = 0\n\n            for value in data do\n                match value with\n                | Odd -> cnt <- cnt + 1\n                | _ -> ()\n\n            cnt\n\n        [<Benchmark(Description = \"No arguments (struct)\")>]\n        member x.NoArgumentsStruct() =\n            let mutable cnt = 0\n\n            for value in data do\n                match value with\n                | OddV -> cnt <- cnt + 1\n                | _ -> ()\n\n            cnt\n\n        [<Benchmark(Description = \"Tuple argument\")>]\n        member x.TupleArgument() =\n            let mutable sum = 0\n\n            for value in data do\n                match value with\n                | OddTuple (a, b) -> sum <- a + b\n                | _ -> ()\n\n            sum\n\n        [<Benchmark(Description = \"Tuple argument (struct)\")>]\n        member x.TupleArgumentStruct() =\n            let mutable sum = 0\n\n            for value in data do\n                match value with\n                | OddTupleV (a, b) -> sum <- a + b\n                | _ -> ()\n\n            sum"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/ArrayChooseBench.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\nopen System\nopen Aardvark.Base\nopen BenchmarkDotNet.Attributes\n\n// | Method            | Size  | Density | Mean      | Error     | StdDev    | Ratio | RatioSD | Gen0    | Gen1   | Allocated | Alloc Ratio |\n// |------------------ |------ |-------- |----------:|----------:|----------:|------:|--------:|--------:|-------:|----------:|------------:|\n// | Choose            | 10000 | 0       |  6.635 us | 0.1194 us | 0.1058 us |  1.00 |    0.00 |       - |      - |      24 B |        1.00 |\n// | ChooseV           | 10000 | 0       |  6.524 us | 0.0078 us | 0.0065 us |  0.98 |    0.02 |       - |      - |         - |        0.00 |\n// | ResizeArrayChoose | 10000 | 0       |  4.733 us | 0.0099 us | 0.0092 us |  0.71 |    0.01 |  1.1902 | 0.0763 |   20056 B |      835.67 |\n// |                   |       |         |           |           |           |       |         |         |        |           |             |\n// | Choose            | 10000 | 0.1     | 25.416 us | 0.1203 us | 0.0939 us |  1.00 |    0.00 |  3.1738 | 0.0916 |   53392 B |        1.00 |\n// | ChooseV           | 10000 | 0.1     | 11.060 us | 0.0299 us | 0.0280 us |  0.43 |    0.00 |  1.6785 | 0.0458 |   28384 B |        0.53 |\n// | ResizeArrayChoose | 10000 | 0.1     |  6.715 us | 0.0361 us | 0.0338 us |  0.26 |    0.00 |  1.6937 | 0.1144 |   28408 B |        0.53 |\n// |                   |       |         |           |           |           |       |         |         |        |           |             |\n// | Choose            | 10000 | 0.5     | 34.344 us | 0.1547 us | 0.1292 us |  1.00 |    0.00 | 13.1836 | 1.5869 |  221376 B |        1.00 |\n// | ChooseV           | 10000 | 0.5     | 11.886 us | 0.0927 us | 0.0821 us |  0.35 |    0.00 |  5.9967 | 0.4883 |  100656 B |        0.45 |\n// | ResizeArrayChoose | 10000 | 0.5     | 18.194 us | 0.1907 us | 0.1690 us |  0.53 |    0.01 | 10.7422 | 2.6550 |  180360 B |        0.81 |\n// |                   |       |         |           |           |           |       |         |         |        |           |             |\n// | Choose            | 10000 | 0.9     | 42.948 us | 0.4031 us | 0.3366 us |  1.00 |    0.00 | 21.8506 | 3.2349 |  366232 B |        1.00 |\n// | ChooseV           | 10000 | 0.9     | 12.218 us | 0.0899 us | 0.0751 us |  0.28 |    0.00 |  8.9264 |      - |  149896 B |        0.41 |\n// | ResizeArrayChoose | 10000 | 0.9     | 23.243 us | 0.0698 us | 0.0619 us |  0.54 |    0.00 | 12.6343 |      - |  212232 B |        0.58 |\n// |                   |       |         |           |           |           |       |         |         |        |           |             |\n// | Choose            | 10000 | 1       | 42.972 us | 0.4753 us | 0.3969 us |  1.00 |    0.00 | 23.8037 | 0.0610 |  400096 B |        1.00 |\n// | ChooseV           | 10000 | 1       | 10.537 us | 0.0346 us | 0.0289 us |  0.25 |    0.00 |  9.5215 |      - |  160072 B |        0.40 |\n// | ResizeArrayChoose | 10000 | 1       | 20.142 us | 0.1999 us | 0.1772 us |  0.47 |    0.00 | 13.0920 | 3.2654 |  220128 B |        0.55 |\n\n[<AutoOpen>]\nmodule private ChooseImpl =\n\n    module Array =\n        let inline chooseV_Simple ([<InlineIfLambda>] chooser: 'T -> 'U voption) (array: 'T array) =\n            let res = ResizeArray<'U>(array.Length / 4)\n            for i = 0 to array.Length - 1 do\n                match chooser array.[i] with\n                | ValueSome b -> res.Add(b)\n                | ValueNone -> ()\n            res.ToArray()\n\n[<MemoryDiagnoser>]\ntype ChooseBenchmark() =\n    let mutable data = [||]\n\n    [<Params(10_000)>]\n    member val Size : int = 0 with get, set\n\n    [<Params(0.0, 0.1, 0.5, 0.9, 1.0)>]\n    member val Density : float = 0.0 with get, set\n\n    [<GlobalSetup>]\n    member self.Setup() =\n        let r = Random(42)\n        data <- Array.init self.Size (fun _ -> r.NextDouble())\n\n    [<Benchmark(Baseline = true)>]\n    member self.Choose() =\n        data |> Array.choose (fun x -> if x < self.Density then Some x else None)\n\n    [<Benchmark>]\n    member self.ChooseV() =\n        data |> Array.chooseV (fun x -> if x < self.Density then ValueSome x else ValueNone)\n\n    [<Benchmark>]\n    member self.ResizeArrayChoose() =\n        data |> Array.chooseV_Simple (fun x -> if x < self.Density then ValueSome x else ValueNone)"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/BvhIntersectBench.fs",
    "content": "namespace Aardvark.Base.FSharp.Benchmarks\n\nopen Aardvark.Base\nopen Aardvark.Base.Geometry\nopen BenchmarkDotNet.Attributes\n\n// | Method                | TreeSize | RayCount | Mean         | Error      | StdDev     | Ratio | RatioSD | Allocated | Alloc Ratio |\n// |---------------------- |--------- |--------- |-------------:|-----------:|-----------:|------:|--------:|----------:|------------:|\n// | Intersect_Option      | 1000     | 1000     |     2.347 ms |  0.0469 ms |  0.0461 ms |  1.00 |    0.00 |   11195 B |       1.000 |\n// | Intersect_ValueOption | 1000     | 1000     |     2.374 ms |  0.0288 ms |  0.0255 ms |  1.01 |    0.02 |       3 B |       0.000 |\n// |                       |          |          |              |            |            |       |         |           |             |\n// | Intersect_Option      | 1000     | 100000   |   235.429 ms |  1.9680 ms |  1.6434 ms |  1.00 |    0.00 | 1143877 B |       1.000 |\n// | Intersect_ValueOption | 1000     | 100000   |   232.502 ms |  3.6250 ms |  3.3908 ms |  0.99 |    0.02 |     229 B |       0.000 |\n// |                       |          |          |              |            |            |       |         |           |             |\n// | Intersect_Option      | 10000    | 1000     |    22.131 ms |  0.2575 ms |  0.2409 ms |  1.00 |    0.00 |   90430 B |       1.000 |\n// | Intersect_ValueOption | 10000    | 1000     |    22.212 ms |  0.3387 ms |  0.2828 ms |  1.00 |    0.02 |      22 B |       0.000 |\n// |                       |          |          |              |            |            |       |         |           |             |\n// | Intersect_Option      | 10000    | 100000   | 2,237.003 ms | 34.4206 ms | 32.1970 ms |  1.00 |    0.00 | 8953728 B |       1.000 |\n// | Intersect_ValueOption | 10000    | 100000   | 2,197.432 ms | 28.2317 ms | 26.4080 ms |  0.98 |    0.01 |     688 B |       0.000 |\n\n[<MemoryDiagnoser>]\ntype BvhIntersectBenchmark() =\n    let mutable bvh = BvhTree.ofArray Array.empty\n    let mutable rays = [||]\n\n    [<Params(1000, 10_000)>]\n    member val TreeSize : int = 0 with get, set\n\n    [<Params(1000, 100_000)>]\n    member val RayCount : int = 0 with get, set\n\n    [<GlobalSetup>]\n    member self.Setup() =\n        let rnd = RandomSystem(42)\n\n        let objects = Array.init self.TreeSize (fun _ ->\n            let c = rnd.UniformV3d() * 10.0\n            let s = Sphere3d.FromCenterAndRadius(c, 0.1)\n            struct (s, s.BoundingBox3d)\n        )\n        bvh <- BvhTree.ofArrayV objects\n\n        rays <- Array.init self.RayCount (fun _ ->\n            let origin = rnd.UniformV3d() * 10.0\n            RayPart.ofRay <| FastRay3d(origin, V3d.OII)\n        )\n\n    [<Benchmark(Baseline = true)>]\n    member self.Intersect_Option() =\n        let mutable hits = 0\n\n        let tryHit (ray: RayPart) (sphere: Sphere3d) =\n            match RayPart.intersect ray sphere with\n            | Some t -> Some <| RayHit(t, t)\n            | _ -> None\n\n        for ray in rays do\n            match BvhTree.intersect tryHit ray bvh with\n            | Some _ -> hits <- hits + 1\n            | None -> ()\n\n        hits\n\n    [<Benchmark>]\n    member self.Intersect_ValueOption() =\n        let mutable hits = 0\n\n        let tryHit (ray: RayPart) (sphere: Sphere3d) =\n            match RayPart.intersectV ray sphere with\n            | ValueSome t -> ValueSome <| RayHit(t, t)\n            | _ -> ValueNone\n\n        for ray in rays do\n            match BvhTree.intersectV tryHit ray bvh with\n            | ValueSome _ -> hits <- hits + 1\n            | ValueNone -> ()\n\n        hits"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/DynamicDispatchBench.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\nopen System\nopen System.Runtime.CompilerServices\nopen Aardvark.Base\nopen BenchmarkDotNet.Attributes\n\n// Benchmarks for dynamic dispatch pattern (e.g. creating a PixImage<T> from a given System.Type)\n//\n// Takeaways about dynamic invocation and delegates:\n//      - MakeGenericMethod() is expensive\n//      - Creating a delegate is also pretty expensive\n//      - Dynamic invocation (MethodInfo.Invoke()) is expensive\n//      - Calling a delegate is less expensive than dynamic invocation\n//\n// Takeaways about thread-safe caching:\n//      - ConcurrentDictionary seems to incur less overhead than ThreadLocal or a Dictionary with a simple lock for some reason\n//      - ConcurrentDictionary.TryGetValue() and manual insert is faster than ConcurrentDictionary.GetOrAdd()\n//      - try-finally pattern with Monitor.Enter() and Monitor.Exit() is faster than lock()\n//\n// BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.4529/22H2/2022Update)\n// AMD Ryzen 5 5600X, 1 CPU, 12 logical and 6 physical cores\n// .NET SDK 8.0.300\n//   [Host] : .NET 8.0.5 (8.0.524.21615), X64 RyuJIT AVX2 DEBUG\n\n// Job=ShortRun  Toolchain=InProcessEmitToolchain  IterationCount=3\n// LaunchCount=1  WarmupCount=3\n\n// | Method                                    | Mean       | Error      | StdDev    | Ratio  | RatioSD | Gen0   | Allocated | Alloc Ratio |\n// |------------------------------------------ |-----------:|-----------:|----------:|-------:|--------:|-------:|----------:|------------:|\n// | Direct                                    |   3.864 ns |  0.2973 ns | 0.0163 ns |   1.00 |    0.00 | 0.0014 |      24 B |        1.00 |\n// | Dispatch (uncached)                       | 245.382 ns |  4.7115 ns | 0.2583 ns |  63.51 |    0.23 | 0.0153 |     256 B |       10.67 |\n// | Dispatch (cached)                         |  43.992 ns |  2.6162 ns | 0.1434 ns |  11.39 |    0.08 | 0.0033 |      56 B |        2.33 |\n// | Dispatch (uncached delegate)              | 550.627 ns |  7.2393 ns | 0.3968 ns | 142.51 |    0.70 | 0.0172 |     288 B |       12.00 |\n// | Dispatch (cached delegate)                |  16.621 ns |  1.2594 ns | 0.0690 ns |   4.30 |    0.02 | 0.0014 |      24 B |        1.00 |\n// | Dispatch (cached thread-local delegate)   |  29.383 ns |  1.0146 ns | 0.0556 ns |   7.60 |    0.02 | 0.0052 |      88 B |        3.67 |\n// | Dispatch (cached locked delegate)         |  25.263 ns |  3.4076 ns | 0.1868 ns |   6.54 |    0.07 | 0.0052 |      88 B |        3.67 |\n// | Dispatch (predefined delegate)            |  11.809 ns | 52.8603 ns | 2.8975 ns |   3.06 |    0.76 | 0.0014 |      24 B |        1.00 |\n\n\ntype IArray =\n    abstract member Data: Array\n\ntype MyArray<'T>(data: 'T[]) =\n    member x.Data = data\n    interface IArray with\n        member x.Data = data :> Array\n\nmodule MyArray =\n    open System.Threading\n    open System.Reflection\n    open System.Collections.Concurrent\n    open System.Collections.Generic\n\n    [<AbstractClass; Sealed>]\n    type Dispatcher() =\n        static member Create<'T>(data: Array) : IArray = MyArray<'T>(unbox<'T[]> data)\n\n    type CreateDelegate = delegate of Array -> IArray\n\n    let private createMethod = typeof<Dispatcher>.GetMethod(nameof Dispatcher.Create, BindingFlags.Public ||| BindingFlags.Static)\n    let private createMethods = ConcurrentDictionary<Type, MethodInfo>()\n    let private createDelegates = ConcurrentDictionary<Type, CreateDelegate>()\n    let private createDelegatesThreadLocal = new ThreadLocal<Dictionary<Type, CreateDelegate>>((fun _ -> Dictionary()), false)\n    let private createDelegatesLocked = Dictionary<Type, CreateDelegate>()\n\n    let private makeDelegate t =\n        let mi = createMethod.MakeGenericMethod [| t |]\n        unbox<CreateDelegate> <| Delegate.CreateDelegate(typeof<CreateDelegate>, null, mi)\n\n    let private createFloatDelegate =\n        makeDelegate typeof<float>\n\n    [<NoCompilerInlining; MethodImpl(MethodImplOptions.NoInlining)>]\n    let create (data: 'T[]) : MyArray<'T> =\n        MyArray<'T>(data)\n\n    let createUntypedUncached (data: Array) : IArray =\n        let mi = createMethod.MakeGenericMethod(data.GetType().GetElementType())\n        mi.Invoke(null, [| data |]) |> unbox<IArray>\n\n    let createUntypedCached (data: Array) : IArray =\n        let t = data.GetType().GetElementType()\n\n        let mi =\n            match createMethods.TryGetValue t with\n            | (true, mi) -> mi\n            | _ ->\n                let mi = createMethod.MakeGenericMethod t\n                createMethods.[t] <- mi\n                mi\n\n        mi.Invoke(null, [| data |]) |> unbox<IArray>\n\n    let createUntypedUncachedDelegate (data: Array) : IArray =\n        let del = makeDelegate <| data.GetType().GetElementType()\n        del.Invoke(data)\n\n    let createUntypedCachedDelegate (data: Array) : IArray =\n        let t = data.GetType().GetElementType()\n\n        let del =\n            match createDelegates.TryGetValue t with\n            | (true, del) -> del\n            | _ ->\n                let del = makeDelegate t\n                createDelegates.[t] <- del\n                del\n\n        del.Invoke(data)\n\n    let createUntypedCachedThreadLocalDelegate (data: Array) : IArray =\n        let del = createDelegatesThreadLocal.Value.GetCreate(data.GetType().GetElementType(), makeDelegate)\n        del.Invoke(data)\n\n    let createUntypedCachedLockedDelegate (data: Array) : IArray =\n        let t = data.GetType().GetElementType()\n\n        let del =\n            let mutable taken = false\n            try\n                Monitor.Enter(createDelegatesLocked, &taken)\n\n                match createDelegatesLocked.TryGetValue t with\n                | (true, del) -> del\n                | _ ->\n                    let del = makeDelegate t\n                    createDelegatesLocked.[t] <- del\n                    del\n            finally\n                if taken then Monitor.Exit createDelegatesLocked\n\n        del.Invoke(data)\n\n    let createUntypedPredefinedDelegate (data: Array) : IArray =\n        createFloatDelegate.Invoke(data)\n\n[<MemoryDiagnoser>]\ntype Dispatch() =\n\n    [<DefaultValue>]\n    val mutable Data : float[]\n\n    [<GlobalSetup>]\n    member x.Setup() =\n        let rnd = RandomSystem 0\n        let arr = MyArray.create (Array.init 512 (ignore >> rnd.UniformDouble))\n        x.Data <- arr.Data\n\n    [<Benchmark(Description = \"Direct\", Baseline = true)>]\n    member x.Direct() : IArray =\n        MyArray.create x.Data\n\n    [<Benchmark(Description = \"Dispatch (uncached)\")>]\n    member x.DispatchUncached() : IArray =\n        MyArray.createUntypedUncached x.Data\n\n    [<Benchmark(Description = \"Dispatch (cached)\")>]\n    member x.DispatchCached() : IArray =\n        MyArray.createUntypedCached x.Data\n\n    [<Benchmark(Description = \"Dispatch (uncached delegate)\")>]\n    member x.DispatchUncachedDelegate() : IArray =\n        MyArray.createUntypedUncachedDelegate x.Data\n\n    [<Benchmark(Description = \"Dispatch (cached delegate)\")>]\n    member x.DispatchCachedDelegate() : IArray =\n        MyArray.createUntypedCachedDelegate x.Data\n\n    [<Benchmark(Description = \"Dispatch (cached thread-local delegate)\")>]\n    member x.DispatchCachedThreadLocalDelegate() : IArray =\n        MyArray.createUntypedCachedThreadLocalDelegate x.Data\n\n    [<Benchmark(Description = \"Dispatch (cached locked delegate)\")>]\n    member x.DispatchCachedLockedDelegate() : IArray =\n        MyArray.createUntypedCachedLockedDelegate x.Data\n\n    [<Benchmark(Description = \"Dispatch (predefined delegate)\")>]\n    member x.DispatchPredefinedDelegate() : IArray =\n        MyArray.createUntypedPredefinedDelegate x.Data"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/NullCheckBench.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\nopen System\nopen BenchmarkDotNet.Attributes\n\n// | Method              | Mean       | Error     | StdDev   | Ratio |\n// |-------------------- |-----------:|----------:|---------:|------:|\n// | 'F# Equality'       | 3,270.6 ns | 455.46 ns | 24.97 ns |  1.00 |\n// | 'Pattern match'     |   227.1 ns |  91.41 ns |  5.01 ns |  0.07 |\n// | obj.ReferenceEquals |   218.3 ns |  63.45 ns |  3.48 ns |  0.07 |\n\ntype ``Null check``() =\n\n    [<DefaultValue>]\n    val mutable Data : obj[]\n\n    [<GlobalSetup>]\n    member this.Setup() =\n        let rnd = Random 0\n        this.Data <- Array.init 512 (fun _ -> if rnd.NextDouble() < 0.5 then obj() else null)\n\n    [<Benchmark(Description = \"F# Equality\", Baseline = true)>]\n    member this.FSharpEquality() =\n        let mutable count = 0\n        for obj in this.Data do if obj = null then count <- count + 1\n        count\n\n    [<Benchmark(Description = \"Pattern match\")>]\n    member this.Match() =\n        let mutable count = 0\n        for obj in this.Data do match obj with null -> count <- count + 1 | _ -> ()\n        count\n\n    [<Benchmark(Description = \"obj.ReferenceEquals\")>]\n    member this.ReferenceEquality() =\n        let mutable count = 0\n        for obj in this.Data do if Object.ReferenceEquals(obj, null) then count <- count + 1\n        count"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/Program.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\nmodule Program =\n\n    open BenchmarkDotNet.Running;\n    open BenchmarkDotNet.Configs\n    open BenchmarkDotNet.Jobs\n    open BenchmarkDotNet.Toolchains\n\n    [<EntryPoint>]\n    let main argv =\n\n        let cfg =\n            let job = Job.Default.WithToolchain(InProcess.Emit.InProcessEmitToolchain.Instance)\n            ManualConfig.Create(DefaultConfig.Instance).WithOptions(ConfigOptions.DisableOptimizationsValidator).AddJob(job)\n\n        BenchmarkSwitcher.FromAssembly(typeof<ZipFloatArrays>.Assembly).Run(argv, cfg) |> ignore\n\n        //BenchmarkRunner.Run<RefCountingSet>(cfg) |> ignore\n\n        0"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/ReferenceCountingSetBench.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\nopen Aardvark.Base\nopen BenchmarkDotNet.Attributes\nopen BenchmarkDotNet.Order\nopen System\n\n//BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.4780/22H2/2022Update)\n//AMD Ryzen 9 7900, 1 CPU, 24 logical and 12 physical cores\n//.NET SDK 8.0.400\n//  [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI DEBUG\n\n//Job=ShortRun  Toolchain=InProcessEmitToolchain  IterationCount=3\n//LaunchCount=1  WarmupCount=3\n\n//| Method    | Count | Mean        | Error       | StdDev     | Gen0   | Allocated |\n//|---------- |------ |------------:|------------:|-----------:|-------:|----------:|\n//| Enumerate | 1     |    25.37 ns |    11.08 ns |   0.607 ns | 0.0052 |      88 B |\n//| Enumerate | 10    |   125.34 ns |    30.77 ns |   1.686 ns | 0.0052 |      88 B |\n//| Enumerate | 100   | 1,033.09 ns |   289.20 ns |  15.852 ns | 0.0038 |      88 B |\n//| Enumerate | 1000  | 9,871.15 ns | 1,857.34 ns | 101.807 ns |      - |      88 B |\n\n// struct enumerator\n//| Method    | Count | Mean         | Error       | StdDev    | Allocated |\n//|---------- |------ |-------------:|------------:|----------:|----------:|\n//| Enumerate | 1     |     2.789 ns |   0.0885 ns | 0.0049 ns |         - |\n//| Enumerate | 10    |    17.053 ns |   0.3215 ns | 0.0176 ns |         - |\n//| Enumerate | 100   |   154.362 ns |  10.5647 ns | 0.5791 ns |         - |\n//| Enumerate | 1000  | 1,560.785 ns | 122.1086 ns | 6.6932 ns |         - |\n\n// struct enumerator + struct tuple store\n//| Method    | Count | Mean         | Error      | StdDev    | Allocated |\n//|---------- |------ |-------------:|-----------:|----------:|----------:|\n//| Enumerate | 1     |     2.738 ns |  0.4081 ns | 0.0224 ns |         - |\n//| Enumerate | 10    |    17.059 ns |  0.9612 ns | 0.0527 ns |         - |\n//| Enumerate | 100   |   155.314 ns |  9.7062 ns | 0.5320 ns |         - |\n//| Enumerate | 1000  | 1,560.410 ns | 92.5061 ns | 5.0706 ns |         - |\n\n\n// value tuple\n//| Method | Count | Mean           | Error            | StdDev         | Gen0   | Gen1   | Allocated |\n//|------- |------ |---------------:|-----------------:|---------------:|-------:|-------:|----------:|\n//| AddNew | 1     |     364.166 ns |     2,432.966 ns |    133.3591 ns | 0.0048 | 0.0043 |      80 B |\n//| AddNew | 10    |   3,000.746 ns |     3,364.066 ns |    184.3958 ns | 0.0458 | 0.0420 |     800 B |\n//| AddNew | 100   |  36,692.566 ns |   152,969.685 ns |  8,384.7846 ns | 0.4578 | 0.4272 |    8000 B |\n//| AddNew | 1000  | 359,488.420 ns | 1,355,066.252 ns | 74,275.7537 ns | 4.6387 | 4.3945 |   80000 B |\n//| AddRef | 1     |       7.813 ns |         3.144 ns |      0.1723 ns |      - |      - |         - |\n//| AddRef | 10    |      66.662 ns |         2.616 ns |      0.1434 ns |      - |      - |         - |\n//| AddRef | 100   |     672.546 ns |        22.958 ns |      1.2584 ns |      - |      - |         - |\n//| AddRef | 1000  |   6,932.414 ns |       237.903 ns |     13.0403 ns |      - |      - |         - |\n\n// struct tuple\n//| Method | Count | Mean           | Error             | StdDev         | Median         | Gen0   | Gen1   | Allocated |\n//|------- |------ |---------------:|------------------:|---------------:|---------------:|-------:|-------:|----------:|\n//| AddNew | 1     |     315.227 ns |     1,498.7478 ns |     82.1514 ns |     279.821 ns | 0.0029 | 0.0024 |      48 B |\n//| AddNew | 10    |   2,816.089 ns |     3,086.4605 ns |    169.1793 ns |   2,846.089 ns | 0.0267 | 0.0229 |     480 B |\n//| AddNew | 100   |  40,502.010 ns |   333,244.1749 ns | 18,266.2377 ns |  31,060.260 ns | 0.2747 | 0.2441 |    4800 B |\n//| AddNew | 1000  | 304,053.206 ns | 1,264,386.0962 ns | 69,305.2684 ns | 265,995.361 ns | 2.4414 | 1.9531 |   48000 B |\n//| AddRef | 1     |       7.152 ns |         0.3564 ns |      0.0195 ns |       7.162 ns |      - |      - |         - |\n//| AddRef | 10    |      66.858 ns |         2.1365 ns |      0.1171 ns |      66.877 ns |      - |      - |         - |\n//| AddRef | 100   |     664.219 ns |        24.2442 ns |      1.3289 ns |     663.463 ns |      - |      - |         - |\n//| AddRef | 1000  |   6,797.345 ns |       158.1447 ns |      8.6684 ns |   6,795.523 ns |      - |      - |         - |\n\n[<MemoryDiagnoser>]\n[<Orderer(BenchmarkDotNet.Order.SummaryOrderPolicy.Method)>]\ntype RefCountingSet() =\n    let mutable stuff : Object[] = Unchecked.defaultof<_>\n    let mutable refSet : ReferenceCountingSet<Object> = Unchecked.defaultof<_>\n    let mutable cnt = 0\n\n    [<Params(1, 10, 100, 1000)>]\n    member x.Count\n        with get() = cnt\n        and set v = cnt <- v\n    \n    [<GlobalSetup>]\n    member x.Setup() =\n        stuff <- Array.init x.Count  (fun i -> Object())\n        refSet <- ReferenceCountingSet<Object>(stuff)\n\n    //[<Benchmark>]\n    //member x.Enumerate() : int =\n    //    let mutable xx = 0\n    //    for x in refSet do\n    //        xx <- xx ^^^ x.GetHashCode()\n    //    xx\n\n    [<Benchmark>]\n    member x.AddRef() =\n        for x in stuff do\n            refSet.Add x |> ignore\n\n    [<Benchmark>]\n    [<IterationCount(3)>]\n    member x.AddNew() =\n        for i in 1..(x.Count) do\n            refSet.Add (Object()) |> ignore"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/TensorMathBench.fs",
    "content": "namespace Aardvark.Base.FSharp.Benchmarks\n\nopen Aardvark.Base\nopen Aardvark.Base.FSharp.Tests\nopen BenchmarkDotNet.Attributes\n\n// ================================================================================================================\n// Vector\n// ================================================================================================================\n\n[<AbstractClass>]\ntype TensorVectorBenchmark() =\n\n    member _.Sizes = [\n        16\n        128\n        512\n        1024\n        4096\n    ]\n\n    [<DefaultValue>]\n    val mutable Vector : Vector<float>\n\n    [<DefaultValue; ParamsSource(\"Sizes\", Priority = 0)>]\n    val mutable Size : int\n\n    [<DefaultValue; Params(TensorKind.Full, TensorKind.Sub, Priority = 1)>]\n    val mutable Kind : TensorKind\n\n    abstract member Setup : unit -> unit\n\n    [<GlobalSetup>]\n    default x.Setup() =\n        TensorGeneration.init 0\n        x.Vector <- TensorGeneration.getVectorOfSize x.Kind x.Size\n\n[<AbstractClass>]\ntype TensorVectorBenchmark2() =\n    inherit TensorVectorBenchmark()\n\n    [<DefaultValue>]\n    val mutable Vector2 : Vector<float>\n\n    [<DefaultValue; Params(TensorKind.Full, TensorKind.Sub, Priority = 2)>]\n    val mutable Kind2 : TensorKind\n\n    override x.Setup() =\n        base.Setup()\n        x.Vector2 <- TensorGeneration.getVectorOfSize x.Kind2 x.Size\n\n[<MemoryDiagnoser>]\ntype TensorVector_Equals() =\n    inherit TensorVectorBenchmark()\n\n    [<Benchmark(Description = \"Vector<'T>.EqualTo()\", Baseline = true)>]\n    member x.CSharp() =\n        x.Vector.EqualTo x.Vector\n\n    [<Benchmark(Description = \"Vector.equals\")>]\n    member x.FSharp() =\n        (x.Vector, x.Vector) ||> Vector.equals\n\n[<MemoryDiagnoser>]\ntype TensorVector_DotProduct() =\n    inherit TensorVectorBenchmark2()\n\n    [<Benchmark(Description = \"Vector<'T>.DotProduct()\", Baseline = true)>]\n    member x.CSharp() =\n        x.Vector.DotProduct x.Vector2\n\n    [<Benchmark(Description = \"Vector.dot\")>]\n    member x.FSharp() =\n        (x.Vector, x.Vector2) ||> Vector.dot\n\n[<MemoryDiagnoser>]\ntype TensorVector_Distance() =\n    inherit TensorVectorBenchmark2()\n\n    [<Benchmark(Description = \"Vector<'T>.Dist2()\", Baseline = true)>]\n    member x.CSharp() =\n        x.Vector.Dist2 x.Vector2\n\n    [<Benchmark(Description = \"Vector.distance\")>]\n    member x.FSharp() =\n        (x.Vector, x.Vector2) ||> Vector.distance\n\n[<MemoryDiagnoser>]\ntype TensorVector_MultiplyTransposed() =\n    inherit TensorVectorBenchmark2()\n\n    [<Benchmark(Description = \"Vector<'T>.MultiplyTransposed()\", Baseline = true)>]\n    member x.CSharp() =\n        let r = x.Vector.MultiplyTransposed x.Vector2\n        r.Data[int r.Origin]\n\n    [<Benchmark(Description = \"Vector.multiplyTransposed\")>]\n    member x.FSharp() =\n        let r = (x.Vector, x.Vector2) ||> Vector.multiplyTransposed\n        r.Data[int r.Origin]\n\n// ================================================================================================================\n// Matrix\n// ================================================================================================================\n\n[<AbstractClass>]\ntype TensorMatrixBenchmark() =\n\n    member _.Sizes = [\n        V2i(4, 4)\n        V2i(64, 128)\n        V2i(256, 512)\n        V2i(1024, 32)\n        V2i(2048, 512)\n    ]\n\n    [<DefaultValue>]\n    val mutable Matrix : Matrix<float>\n\n    [<DefaultValue; ParamsSource(\"Sizes\", Priority = 0)>]\n    val mutable Size : V2i\n\n    [<DefaultValue; Params(TensorKind.Full, TensorKind.Sub, Priority = 1)>]\n    val mutable Kind : TensorKind\n\n    [<DefaultValue; Params(false, true, Priority = 3)>]\n    val mutable RowMajor : bool\n\n    abstract member Setup : unit -> unit\n\n    [<GlobalSetup>]\n    default x.Setup() =\n        TensorGeneration.init 0\n        x.Matrix <- TensorGeneration.getMatrixOfSize x.Kind x.RowMajor x.Size\n\n[<AbstractClass>]\ntype TensorMatrixBenchmark2() =\n    inherit TensorMatrixBenchmark()\n\n    [<DefaultValue>]\n    val mutable Matrix2 : Matrix<float>\n\n    [<DefaultValue; Params(TensorKind.Full, TensorKind.Sub, Priority = 2)>]\n    val mutable Kind2 : TensorKind\n\n    [<DefaultValue; Params(false, true, Priority = 4)>]\n    val mutable RowMajor2 : bool\n\n    override x.Setup() =\n        base.Setup()\n        x.Matrix2 <- TensorGeneration.getMatrixOfSize x.Kind2 x.RowMajor2 x.Size\n\n[<MemoryDiagnoser>]\ntype TensorMatrix_Add() =\n    inherit TensorMatrixBenchmark2()\n\n    [<Benchmark(Description = \"Matrix<'T>.Add()\", Baseline = true)>]\n    member x.CSharp() =\n        let m1 = x.Matrix\n        let m2 = x.Matrix2\n        let r = m1.Add(m2)\n        r.Data.[int r.Origin]\n\n    [<Benchmark(Description = \"Matrix.add\")>]\n    member x.FSharp() =\n        let m1 = x.Matrix\n        let m2 = x.Matrix2\n        let r = (m1, m2) ||> Matrix.add\n        r.Data.[int r.Origin]\n\n[<MemoryDiagnoser>]\ntype TensorMatrix_Transform() =\n    inherit TensorMatrixBenchmark2()\n\n    [<Benchmark(Description = \"Matrix<'T>.Multiply()\", Baseline = true)>]\n    member x.CSharp() =\n        let m = x.Matrix\n        let v = x.Matrix2.Row 0L\n        let r = m.Multiply(v)\n        r.Data.[int r.Origin]\n\n    [<Benchmark(Description = \"Matrix.transform\")>]\n    member x.FSharp() =\n        let m = x.Matrix\n        let v = x.Matrix2.Row 0L\n        let r = (m, v) ||> Matrix.transform\n        r.Data.[int r.Origin]\n\n[<MemoryDiagnoser>]\ntype TensorMatrix_Multiply() =\n    inherit TensorMatrixBenchmark2()\n\n    [<Benchmark(Description = \"Matrix<'T>.Multiply()\", Baseline = true)>]\n    member x.CSharp() =\n        let m1 = x.Matrix\n        let m2 = x.Matrix2.Transposed\n        let r = m1.Multiply(m2)\n        r.Data.[int r.Origin]\n\n    [<Benchmark(Description = \"Matrix.multiply\")>]\n    member x.FSharp() =\n        let m1 = x.Matrix\n        let m2 = x.Matrix2.Transposed\n        let r = (m1, m2) ||> Matrix.multiply\n        r.Data.[int r.Origin]"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/TensorUtilitiesBench.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\nopen Aardvark.Base\nopen Aardvark.Base.FSharp.Tests\nopen BenchmarkDotNet.Attributes\n\n// ================================================================================================================\n// Tensor4\n// ================================================================================================================\n\nmodule Tensor4 =\n\n    let inline iteri_naive ([<InlineIfLambda>] action: int64 -> unit) (t: Tensor4<'T>) =\n        let s0 = t.DSX\n        let j0 = t.Info.JX0\n        let s1 = t.DSY\n        let j1 = t.Info.JYX\n        let s2 = t.DSZ\n        let j2 = t.Info.JZY\n        let s3 = t.DSW\n        let j3 = t.Info.JWZ\n\n        let mutable i = t.FirstIndex\n\n        let e3 = i + s3\n        while i <> e3 do\n            let e2 = i + s2\n            while i <> e2 do\n                let e1 = i + s1\n                while i <> e1 do\n                    let e0 = i + s0\n                    while i <> e0 do\n                        action i\n                        i <- i + j0\n                    i <- i + j1\n                i <- i + j2\n            i <- i + j3\n\n    let inline iteri2_naive ([<InlineIfLambda>] action: int64 -> int64 -> unit) (t1: Tensor4<'T1>) (t2: Tensor4<'T2>) =\n        if t1.Size <> t2.Size then\n            raise <| System.ArgumentException($\"Mismatching Tensor4 size ({t1.Size} != {t2.Size})\")\n\n        let s0_1 = t1.DSX\n        let j0_1 = t1.Info.JX0\n        let j0_2 = t2.Info.JX0\n        let s1_1 = t1.DSY\n        let j1_1 = t1.Info.JYX\n        let j1_2 = t2.Info.JYX\n        let s2_1 = t1.DSZ\n        let j2_1 = t1.Info.JZY\n        let j2_2 = t2.Info.JZY\n        let s3_1 = t1.DSW\n        let j3_1 = t1.Info.JWZ\n        let j3_2 = t2.Info.JWZ\n\n        let mutable i1 = t1.FirstIndex\n        let mutable i2 = t2.FirstIndex\n\n        let e3_1 = i1 + s3_1\n        while i1 <> e3_1 do\n            let e2_1 = i1 + s2_1\n            while i1 <> e2_1 do\n                let e1_1 = i1 + s1_1\n                while i1 <> e1_1 do\n                    let e0_1 = i1 + s0_1\n                    while i1 <> e0_1 do\n                        action i1 i2\n                        i1 <- i1 + j0_1\n                        i2 <- i2 + j0_2\n                    i1 <- i1 + j1_1\n                    i2 <- i2 + j1_2\n                i1 <- i1 + j2_1\n                i2 <- i2 + j2_2\n            i1 <- i1 + j3_1\n            i2 <- i2 + j3_2\n\n[<AbstractClass>]\ntype Tensor4Benchmark() =\n\n    member _.Sizes = [\n        V4i(4, 4, 4, 4)\n        V4i(64, 32, 4, 3)\n        V4i(4, 128, 1, 256)\n        V4i(256, 256, 4, 3)\n        V4i(32, 32, 32, 32)\n    ]\n\n    [<DefaultValue>]\n    val mutable Tensor : Tensor4<float>\n\n    [<DefaultValue; ParamsSource(\"Sizes\", Priority = 0)>]\n    val mutable Size : V4i\n\n    [<DefaultValue; Params(TensorKind.Full, TensorKind.Sub, Priority = 1)>]\n    val mutable Kind : TensorKind\n\n    [<DefaultValue; Params(false, true, Priority = 3)>]\n    val mutable InnerW : bool\n\n    abstract member Setup : unit -> unit\n\n    [<GlobalSetup>]\n    default x.Setup() =\n        TensorGeneration.init 0\n        x.Tensor <- TensorGeneration.getTensor4OfSize x.Kind x.InnerW x.Size\n\n[<AbstractClass>]\ntype Tensor4Benchmark2() =\n    inherit Tensor4Benchmark()\n\n    [<DefaultValue>]\n    val mutable Tensor2 : Tensor4<float>\n\n    [<DefaultValue; Params(TensorKind.Full, TensorKind.Sub, Priority = 2)>]\n    val mutable Kind2 : TensorKind\n\n    [<DefaultValue; Params(false, true, Priority = 4)>]\n    val mutable InnerW2 : bool\n\n    override x.Setup() =\n        base.Setup()\n        x.Tensor2 <- TensorGeneration.getTensor4OfSize x.Kind2 x.InnerW2 x.Size\n\n[<MemoryDiagnoser>]\ntype Tensor4_Iter() =\n    inherit Tensor4Benchmark()\n\n    [<Benchmark(Description = \"Tensor4<'T>.ForeachIndex()\")>]\n    member x.CSharp() =\n        let t = x.Tensor\n        let mutable result = 0.0\n        t.ForeachIndex(fun i -> result <- result + t.Data.[int i])\n        result\n\n    [<Benchmark(Description = \"Tensor4.iter (naive)\", Baseline = true)>]\n    member x.FSharpNaive() =\n        let t = x.Tensor\n        let mutable result = 0.0\n        t |> Tensor4.iteri_naive (fun i -> result <- result + t.Data.[int i])\n        result\n\n    [<Benchmark(Description = \"Tensor4.iter (optimized)\")>]\n    member x.FSharp() =\n        let t = x.Tensor\n        let mutable result = 0.0\n        t |> Tensor4.iteri (fun i -> result <- result + t.Data.[int i])\n        result\n\n[<MemoryDiagnoser>]\ntype Tensor4_Iter2() =\n    inherit Tensor4Benchmark2()\n\n    [<Benchmark(Description = \"Tensor4<'T>.ForeachIndex()\")>]\n    member x.CSharp() =\n        let t1 = x.Tensor\n        let t2 = x.Tensor2\n        let mutable result = 0.0\n        t1.ForeachIndex(t2.Info, fun i1 i2 -> result <- result + t1.Data.[int i1] + t2.Data.[int i2])\n        result\n\n    [<Benchmark(Description = \"Tensor4.iter2 (naive)\", Baseline = true)>]\n    member x.FSharpNaive() =\n        let t1 = x.Tensor\n        let t2 = x.Tensor2\n        let mutable result = 0.0\n        (t1, t2) ||> Tensor4.iteri2_naive (fun i1 i2 -> result <- result + t1.Data.[int i1] + t2.Data.[int i2])\n        result\n\n    [<Benchmark(Description = \"Tensor4.iter2 (optimized)\")>]\n    member x.FSharp() =\n        let t1 = x.Tensor\n        let t2 = x.Tensor2\n        let mutable result = 0.0\n        (t1, t2) ||> Tensor4.iteri2 (fun i1 i2 -> result <- result + t1.Data.[int i1] + t2.Data.[int i2])\n        result"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/Tuples_auto.fs",
    "content": "namespace Aardvark.Base.FSharp.Benchmarks\n\nopen Aardvark.Base\nopen BenchmarkDotNet.Attributes;\n\nmodule List =\n    let zip' (x : 'T1 list) (y : 'T2 list) =\n        List.map2 (fun a b -> struct (a, b)) x y\n\nmodule Array =\n    let zip' (x : 'T1[]) (y : 'T2[]) =\n        Array.map2 (fun a b -> struct (a, b)) x y\n\n\n[<MemoryDiagnoser>]\ntype ZipShortLists() =\n    let mutable dataA = List.empty\n    let mutable dataB = List.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- List.init x.Count (ignore >> fun () -> int16 <| rnd.UniformInt())\n        dataB <- List.init x.Count (ignore >> fun () -> int16 <| rnd.UniformInt())\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        List.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        List.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipShortArrays() =\n    let mutable dataA = Array.empty\n    let mutable dataB = Array.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- Array.init x.Count (ignore >> fun () -> int16 <| rnd.UniformInt())\n        dataB <- Array.init x.Count (ignore >> fun () -> int16 <| rnd.UniformInt())\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        Array.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        Array.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipFloatLists() =\n    let mutable dataA = List.empty\n    let mutable dataB = List.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- List.init x.Count (ignore >> rnd.UniformFloat)\n        dataB <- List.init x.Count (ignore >> rnd.UniformFloat)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        List.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        List.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipFloatArrays() =\n    let mutable dataA = Array.empty\n    let mutable dataB = Array.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- Array.init x.Count (ignore >> rnd.UniformFloat)\n        dataB <- Array.init x.Count (ignore >> rnd.UniformFloat)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        Array.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        Array.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipDoubleLists() =\n    let mutable dataA = List.empty\n    let mutable dataB = List.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- List.init x.Count (ignore >> rnd.UniformDouble)\n        dataB <- List.init x.Count (ignore >> rnd.UniformDouble)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        List.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        List.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipDoubleArrays() =\n    let mutable dataA = Array.empty\n    let mutable dataB = Array.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- Array.init x.Count (ignore >> rnd.UniformDouble)\n        dataB <- Array.init x.Count (ignore >> rnd.UniformDouble)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        Array.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        Array.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipV2dLists() =\n    let mutable dataA = List.empty\n    let mutable dataB = List.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- List.init x.Count (ignore >> rnd.UniformV2d)\n        dataB <- List.init x.Count (ignore >> rnd.UniformV2d)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        List.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        List.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipV2dArrays() =\n    let mutable dataA = Array.empty\n    let mutable dataB = Array.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- Array.init x.Count (ignore >> rnd.UniformV2d)\n        dataB <- Array.init x.Count (ignore >> rnd.UniformV2d)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        Array.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        Array.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipV4dLists() =\n    let mutable dataA = List.empty\n    let mutable dataB = List.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- List.init x.Count (ignore >> rnd.UniformV4d)\n        dataB <- List.init x.Count (ignore >> rnd.UniformV4d)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        List.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        List.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipV4dArrays() =\n    let mutable dataA = Array.empty\n    let mutable dataB = Array.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- Array.init x.Count (ignore >> rnd.UniformV4d)\n        dataB <- Array.init x.Count (ignore >> rnd.UniformV4d)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        Array.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        Array.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipM44dLists() =\n    let mutable dataA = List.empty\n    let mutable dataB = List.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- List.init x.Count (ignore >> rnd.UniformM44d)\n        dataB <- List.init x.Count (ignore >> rnd.UniformM44d)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        List.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        List.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipM44dArrays() =\n    let mutable dataA = Array.empty\n    let mutable dataB = Array.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- Array.init x.Count (ignore >> rnd.UniformM44d)\n        dataB <- Array.init x.Count (ignore >> rnd.UniformM44d)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        Array.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        Array.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipTrafo3dLists() =\n    let mutable dataA = List.empty\n    let mutable dataB = List.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- List.init x.Count (ignore >> fun () -> Trafo3d(rnd.UniformM44d(), rnd.UniformM44d()))\n        dataB <- List.init x.Count (ignore >> fun () -> Trafo3d(rnd.UniformM44d(), rnd.UniformM44d()))\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        List.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        List.zip' dataA dataB\n\n\n[<MemoryDiagnoser>]\ntype ZipTrafo3dArrays() =\n    let mutable dataA = Array.empty\n    let mutable dataB = Array.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- Array.init x.Count (ignore >> fun () -> Trafo3d(rnd.UniformM44d(), rnd.UniformM44d()))\n        dataB <- Array.init x.Count (ignore >> fun () -> Trafo3d(rnd.UniformM44d(), rnd.UniformM44d()))\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        Array.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        Array.zip' dataA dataB\n\n\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/Tuples_template.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\nopen Aardvark.Base\nopen BenchmarkDotNet.Attributes;\n\nmodule List =\n    let zip' (x : 'T1 list) (y : 'T2 list) =\n        List.map2 (fun a b -> struct (a, b)) x y\n\nmodule Array =\n    let zip' (x : 'T1[]) (y : 'T2[]) =\n        Array.map2 (fun a b -> struct (a, b)) x y\n\n\n//# var types = new[] { \"Short\", \"Float\", \"Double\", \"V2d\", \"V4d\", \"M44d\", \"Trafo3d\" };\n//# var generators =\n//#     new[] {\n//#         \"fun () -> int16 <| rnd.UniformInt()\",\n//#         \"rnd.UniformFloat\",\n//#         \"rnd.UniformDouble\",\n//#         \"rnd.UniformV2d\",\n//#         \"rnd.UniformV4d\",\n//#         \"rnd.UniformM44d\",\n//#         \"fun () -> Trafo3d(rnd.UniformM44d(), rnd.UniformM44d())\"\n//#     };\n//#\n//# var collections = new[] { \"List\", \"Array\" };\n//# for(int i = 0; i < types.Length; i++) {\n    //# var t = types[i];\n    //# var gen = generators[i];\n    //#\n    //# foreach (var c in collections) {\n[<MemoryDiagnoser>]\ntype Zip__t____c__s() =\n    let mutable dataA = __c__.empty\n    let mutable dataB = __c__.empty\n\n    [<DefaultValue; Params(10, 1000, 100000)>]\n    val mutable Count : int\n\n    [<GlobalSetup>]\n    member x.Init() =\n        let rnd = RandomSystem(0)\n        dataA <- __c__.init x.Count (ignore >> __gen__)\n        dataB <- __c__.init x.Count (ignore >> __gen__)\n\n    [<Benchmark(Baseline = true)>]\n    member x.Zip() =\n        __c__.zip dataA dataB\n\n    [<Benchmark>]\n    member x.ZipValue() =\n        __c__.zip' dataA dataB\n\n\n//# } }"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/TypePatternsBench.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Benchmarks\n\n#nowarn \"44\"\n\nopen System\nopen Aardvark.Base\nopen Aardvark.Base.TypeInfo\nopen BenchmarkDotNet.Attributes\n\nmodule PatternsImpl =\n\n    module PatternsNaive =\n        let inline private typeInfo t = { simpleType = t } :> ITypeInfo\n\n        [<return: Struct>]\n        let inline (|Matrix|_|) (t : Type) =\n            if Set.contains (typeInfo t) MatrixTypes then\n                ValueSome ()\n            else\n                ValueNone\n\n        [<return: Struct>]\n        let inline (|MatrixOf|_|) (t : Type) =\n            MatrixTypes\n            |> Seq.tryFindV (fun vi -> vi.Type.Name = t.Name)\n            |> ValueOption.map (fun t ->\n                let mt = unbox<MatrixType> t\n                mt.dimension, mt.baseType.Type\n            )\n\n        [<return: Struct>]\n        let inline (|List|_|) (t : Type) =\n            if t.IsGenericType && t.GetGenericTypeDefinition() = TList.simpleType then\n                ValueSome <| t.GetGenericArguments().[0]\n            else\n                ValueNone\n\n[<MemoryDiagnoser>]\ntype ``TypePatterns Matrix``() =\n\n    member inline x.IsMatrixNaive (t: Type) =\n        match t with\n        | PatternsImpl.PatternsNaive.Matrix -> true\n        | _ -> false\n\n    member inline x.IsMatrixOptimized (t: Type) =\n        match t with\n        | TypeMeta.Patterns.Matrix -> true\n        | _ -> false\n\n    [<Benchmark(Description = \"Naive\", Baseline = true)>]\n    member x.Naive() =\n        x.IsMatrixNaive typeof<M44d> && x.IsMatrixNaive typeof<unit>\n\n    [<Benchmark(Description = \"Optimized\")>]\n    member x.Optimized() =\n        x.IsMatrixOptimized typeof<M44d> && x.IsMatrixOptimized typeof<unit>\n\n[<MemoryDiagnoser>]\ntype ``TypePatterns MatrixOf``() =\n\n    member inline x.IsMatrixNaive (t: Type) =\n        match t with\n        | PatternsImpl.PatternsNaive.MatrixOf(dim, baseType) -> true\n        | _ -> false\n\n    member inline x.IsMatrixOptimized (t: Type) =\n        match t with\n        | TypeMeta.Patterns.MatrixOf(dim, baseType) -> true\n        | _ -> false\n\n    [<Benchmark(Description = \"Naive\", Baseline = true)>]\n    member x.Naive() =\n        x.IsMatrixNaive typeof<M44d> && x.IsMatrixNaive typeof<unit>\n\n    [<Benchmark(Description = \"Optimized\")>]\n    member x.Optimized() =\n        x.IsMatrixOptimized typeof<M44d> && x.IsMatrixOptimized typeof<unit>\n\n[<MemoryDiagnoser>]\ntype ``TypePatterns List``() =\n\n    member inline x.IsListNaive (t: Type) =\n        match t with\n        | PatternsImpl.PatternsNaive.List(baseType) -> true\n        | _ -> false\n\n    member inline x.IsListOptimized (t: Type) =\n        match t with\n        | TypeMeta.Patterns.ListOf(baseType) -> true\n        | _ -> false\n\n    [<Benchmark(Description = \"Naive\", Baseline = true)>]\n    member x.Naive() =\n        x.IsListNaive typeof<list<M44d>> && x.IsListNaive typeof<unit>\n\n    [<Benchmark(Description = \"Optimized\")>]\n    member x.Optimized() =\n        x.IsListOptimized typeof<list<M44d>> && x.IsListOptimized typeof<unit>"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Benchmarks/paket.references",
    "content": "group Test\n\nFSharp.Core\nBenchmarkDotNet\nNUnit\nFsUnit\nNUnit3TestAdapter\nMicrosoft.NET.Test.Sdk"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Aardvark.Base.FSharp.Tests.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <GenerateProgramFile>false</GenerateProgramFile>\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n    <WarnOn>3389;3390;3395</WarnOn>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup>\n    <RunWorkingDirectory>$(OutputPath)\\net8.0</RunWorkingDirectory>\n  </PropertyGroup>\n  <ItemGroup>\n    <EmbeddedResource Include=\"data\\test.jpg\" />\n    <Compile Include=\"Math\\MathTests.fs\" />\n    <Compile Include=\"Math\\TrafoTests.fs\" />\n    <Compile Include=\"Math\\SVDTests.fs\" />\n    <Compile Include=\"Tensors\\TensorTests.fs\" />\n    <Compile Include=\"Tensors\\TensorMathTests.fs\" />\n    <Compile Include=\"Tensors\\PixTests.fs\" />\n    <Compile Include=\"Datastructures\\RangeSetTests.fs\" />\n    <Compile Include=\"Datastructures\\SortedSetExt.fs\" />\n    <Compile Include=\"Datastructures\\MapExt.fs\" />\n    <Compile Include=\"Datastructures\\OrderMaintenanceTrie.fs\" />\n    <Compile Include=\"Datastructures\\FSharpExtensionTests.fs\" />\n    <Compile Include=\"EnumTests.fs\" />\n    <Compile Include=\"CachesTest.fs\" />\n    <Compile Include=\"PureAgTests.fs\" />\n    <Compile Include=\"NativeMemory.fs\" />\n    <Compile Include=\"ControlTests.fs\" />\n    <Compile Include=\"SizeOfTests.fs\" />\n    <Compile Include=\"TypeMetaTests.fs\" />\n    <Compile Include=\"NullCoalesceTests.fs\" />\n    <Compile Include=\"PinnedValueTests.fs\" />\n    <Compile Include=\"GeometryValueOptionTests.fs\" />\n    <Compile Include=\"Program.fs\" />\n    <None Include=\"paket.references\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/CachesTest.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen System\nopen NUnit.Framework\nopen Expecto\nopen Aardvark.Base\nopen System.IO\nopen System.Diagnostics\nopen System.Threading\nopen System.Reflection\nopen System.Collections\n\nmodule Caches =\n    type RuntimeObject(name : string) =\n\n        static let mutable objCount = 0\n\n        let data = Array.zeroCreate 100000\n\n        let number = Interlocked.Increment &objCount\n\n        static member ObjCount = objCount\n\n        member x.Name\n            with get() = name\n\n        override x.Finalize() =\n            Interlocked.Decrement &objCount |> ignore\n\n        override x.ToString() = name\n\n    type ResultObject<'a, 'b>(a : 'a, b : 'b) =\n\n        static let mutable resCount = 0\n\n        do Interlocked.Increment &resCount |> ignore\n\n        static member ResCount = resCount\n\n        member x.A\n            with get() = a\n        member x.B\n            with get() = b\n\n        override x.ToString() =\n            a.ToString() + b.ToString()\n\n    let private collectAndFinalize() =\n        for _ in 1 .. 5 do\n            GC.Collect(3)\n            GC.WaitForPendingFinalizers()\n\n    [<Test>]\n    let ``[Caches] BinaryCache forward``() =\n\n        let a = \"hugo\"\n\n        let cache = BinaryCache<_, _, _>((fun a b -> a.ToString() + b.ToString()))\n\n        let sw = Stopwatch.StartNew()\n        let mutable i = 0\n        let random = Random(123)\n        let mutable temp = RuntimeObject(sprintf \"run-%i\" i)\n\n        while sw.Elapsed.TotalSeconds < 10.0 do\n\n            if random.NextDouble() < 0.1 || i = 0 then\n                temp <- RuntimeObject(sprintf \"run-%i\" i)\n\n            let result = cache.Invoke(a, temp)\n\n            if result <> a + temp.ToString() then\n                failwithf \"unexpected cached result: expected %s%s, got %s\" a temp.Name result\n\n            i <- i + 1\n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n        collectAndFinalize()\n\n        if RuntimeObject.ObjCount > 100 then\n            failwithf \"leak: RuntimeObject Count=%d\" RuntimeObject.ObjCount\n\n    [<Test>]\n    let ``[Caches] BinaryCache backward``() =\n\n        let a = \"hugo\"\n\n        let cache = BinaryCache<_, _, _>((fun a b -> a.ToString() + b.ToString()))\n\n        let sw = Stopwatch.StartNew()\n        let mutable i = 0\n        let random = Random(123)\n        let mutable temp = RuntimeObject(sprintf \"run-%i\" i)\n\n        while sw.Elapsed.TotalSeconds < 10.0 do\n\n            if random.NextDouble() < 0.1 || i = 0 then\n                temp <- RuntimeObject(sprintf \"run-%i\" i)\n\n            let result = cache.Invoke(temp, a)\n\n            if result <> temp.ToString() + a then\n                failwithf \"unexpected cached result: expected %s%s, got %s\" temp.Name a result\n\n            i <- i + 1\n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n        collectAndFinalize()\n\n        if RuntimeObject.ObjCount > 100 then\n            failwithf \"leak: RuntimeObject Count=%d\" RuntimeObject.ObjCount\n\n\n    [<Test>]\n    let ``[Caches] BinaryCache forward with ResultObject``() =\n\n        let a = \"hugo\"\n\n        let cache = BinaryCache<_, _, _>((fun a b -> ResultObject(a, b)))\n\n        let sw = Stopwatch.StartNew()\n        let mutable i = 0\n\n        let rnd = Random(123)\n        let mutable temp = Unchecked.defaultof<_>\n\n        while sw.Elapsed.TotalSeconds < 10.0 do\n\n            if rnd.NextDouble() < 0.1 || i = 0 then\n                temp <- RuntimeObject(sprintf \"run-%i\" i)\n\n            let result = cache.Invoke(a, temp)\n\n            if result.A <> a || not (obj.ReferenceEquals(result.B, temp)) then\n                failwith \"cache returned unexpected data\"\n\n            i <- i + 1\n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n        collectAndFinalize()\n\n        if RuntimeObject.ObjCount > 100 then\n            failwithf \"leak: RuntimeObject Count=%d\" RuntimeObject.ObjCount\n\n        let x = cache.Invoke(a, temp)\n        let y = cache.Invoke(a, temp)\n        if not (System.Object.ReferenceEquals(x,y)) then failwith \"not caching\"\n\n    [<Test>]\n    let ``[Caches] BinaryCache backward with ResultObject``() =\n\n        let a = \"hugo\"\n        let cache = BinaryCache<_, _, _>((fun a b -> ResultObject(a, b)))\n\n        let sw = Stopwatch.StartNew()\n        let mutable i = 0\n\n        let rnd = Random(123)\n        let mutable temp = Unchecked.defaultof<_>\n\n        while sw.Elapsed.TotalSeconds < 10.0 do\n\n            if rnd.NextDouble() < 0.1 || i = 0 then\n                temp <- RuntimeObject(sprintf \"run-%i\" i)\n\n            let result = cache.Invoke(temp, a)\n\n            if not (obj.ReferenceEquals(result.A, temp)) || result.B <> a then\n                failwith \"cache returned unexpected data\"\n\n            i <- i + 1\n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n        collectAndFinalize()\n\n        if RuntimeObject.ObjCount > 100 then\n            failwithf \"leak: RuntimeObject Count=%d\" RuntimeObject.ObjCount\n\n\n        let x = cache.Invoke(temp, a)\n        let y = cache.Invoke(temp, a)\n        if not (System.Object.ReferenceEquals(x,y)) then failwith \"not caching\"\n\n    [<Test>]\n    let ``[Caches] ConditionalWeakTable: input holding output``() =\n\n        let sw = Stopwatch.StartNew()\n        let mutable i = 0\n        while sw.Elapsed.TotalSeconds < 10.0 do\n\n            let temp = RuntimeObject(sprintf \"run-%i\" i)\n\n            let result = UnaryCache<_, _>(fun a -> a).Invoke temp\n\n            i <- i + 1\n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n        collectAndFinalize()\n\n        if RuntimeObject.ObjCount > 100 then\n            failwithf \"leak: RuntimeObject Count=%d\" RuntimeObject.ObjCount\n\n    [<Test>]\n    let ``[Caches] Introspection plugin cache``() =\n\n        // Don't want to make this type public just for a unit test, so we just use reflection?\n        let plugins = typeof<Aardvark>.GetNestedType(\"Plugins\", BindingFlags.NonPublic ||| BindingFlags.Public)\n        let cacheType = plugins.GetNestedType(\"PluginCache\", BindingFlags.NonPublic ||| BindingFlags.Public)\n\n        let dataType = cacheType.GetNestedType(\"Data\");\n        let dataCtor = dataType.GetConstructor([| typeof<DateTime>; typeof<bool> |])\n\n        let cacheCtor = cacheType.GetConstructor([||])\n        let serialize = cacheType.GetMethod(\"Serialize\", BindingFlags.NonPublic ||| BindingFlags.Instance, [| typeof<Stream> |])\n        let deserialize = cacheType.GetMethod(\"Deserialize\",  BindingFlags.NonPublic ||| BindingFlags.Static, [| typeof<Stream> |])\n        let add = cacheType.GetMethod(\"Add\", [| typeof<string>; dataType |])\n\n        let addEntry (path : string) (lastModified : DateTime) (isPlugin : bool) (cache : IDictionary) =\n            let data = dataCtor.Invoke([| lastModified; isPlugin |])\n            add.Invoke(cache, [| path; data |]) |> ignore\n\n        let cache = unbox<IDictionary> <| cacheCtor.Invoke([||])\n        cache |> addEntry \"foo.dll\" DateTime.Now true\n        cache |> addEntry \"bar.dll\" DateTime.Now false\n\n        use stream = new MemoryStream()\n        serialize.Invoke(cache, [| stream |]) |> ignore\n\n        stream.Seek(0L, SeekOrigin.Begin) |> ignore\n        let result = unbox<IDictionary> <| deserialize.Invoke(null, [| stream |])\n\n        Expect.equal result.Count cache.Count \"Unexpected entry count\"\n\n        for path in cache.Keys do\n            Expect.isTrue (result.Contains path) \"Result did not contain path\"\n            Expect.equal result.[path] cache.[path] \"Cache entry mismatch\"\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/ControlTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n#nowarn \"44\"\n\nopen System\nopen Aardvark.Base\nopen FsUnit\nopen NUnit.Framework\n\nmodule ``Control tests`` =\n\n    open Aardvark.Base.Cancellable\n    open Aardvark.Base.Cancellable.StatefulStepVar\n    \n    [<Test>]\n    [<Ignore(\"nondeterministic\")>]\n    let ``[Control] stateful step var cancellation test``() =\n\n        let r = System.Random()\n        let perStep = 10\n\n        let test n wait =\n            let activations = ref []\n            let undos = ref []\n            let perform (v:int) = \n                printfn \"performed: %d\" v\n                activations := v :: !activations\n            let unperform (v:int) =   \n                printfn \"activations: %A\" activations  \n                printfn \"undid: %d\" v\n                undos := v :: !undos\n\n            let things = [ for i in 0 .. n do \n                            let step = \n                                cancel {\n                                    try\n                                        System.Threading.Thread.Sleep perStep\n                                        return i\n                                    finally \n                                        perform i, fun i -> unperform i\n                                        \n                                }\n                            yield Step.ofFun (\n                                fun i -> step ) \n                         ]\n\n            let all = things |> List.fold (( *>)) (Step.ofFun (fun () -> cancel { return 1 }) )\n\n            let cts = new System.Threading.CancellationTokenSource()\n            cts.CancelAfter(r.Next(0,(n*2)*perStep))\n            let result = Step.runRef all cts.Token\n            System.Threading.Thread.Sleep ((n*2)*perStep+10)\n            match !result with\n                | Some v ->\n                    printfn \"compleded, activations: %A\" activations\n                    !undos |> should equal []\n                    (!activations |> List.sort) |> should equal [ 0 .. n ]\n                | None -> \n                    printfn \"undid: %A, activated: %A\" !undos !activations\n                    (!activations |> List.sort) |> should equal (!undos |> List.sort)\n\n        test 10 10"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Datastructures/FSharpExtensionTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen FsCheck\nopen FsCheck.NUnit\nopen Aardvark.Base\nopen System.Collections.Generic\n\nmodule Map =\n\n    type Key =\n        | A = 0\n        | B = 1\n        | C = 2\n\n    [<Property>]\n    let ``[Map] ofSeqWithDuplicates`` (data: list<Key * int>) =\n        let result = Map.ofSeqWithDuplicates data\n        let expected =\n            let d = Dictionary()\n            for k, v in data do\n                let set = d |> Dictionary.tryFind k |> Option.defaultValue Set.empty\n                d.[k] <- set |> Set.add v\n            d\n\n        result = Dictionary.toMap expected\n\nmodule Seq =\n\n    let private assertNullSourceArg (action : unit -> 'T) =\n        let ex =\n            NUnit.Framework.Assert.Throws<System.ArgumentNullException>(fun () -> action() |> ignore)\n\n        NUnit.Framework.Assert.That(ex.ParamName, NUnit.Framework.Is.EqualTo(\"source\"))\n\n    module Ref =\n\n        let choosei (chooser: int -> int -> int option) (data: int seq) =\n            let r = ResizeArray<int>()\n            let mutable i = 0\n            for d in data do\n                match chooser i d with\n                | Some v -> r.Add v\n                | _ -> ()\n                i <- i + 1\n            r :> seq<_>\n\n        let collecti (mapping: int -> int -> #seq<int>) (data: int seq) =\n            let r = ResizeArray<int>()\n            let mutable i = 0\n            for d in data do\n                r.AddRange(mapping i d)\n                i <- i + 1\n            r :> seq<_>\n\n        let foldi (folder: int -> int -> int -> int) (state: int) (data: int seq) =\n            let mutable state = state\n            let mutable i = 0\n            for d in data do\n                state <- folder i state d\n                i <- i + 1\n            state\n\n    [<Property>]\n    let ``[Seq] choosei`` (chooser: int -> int -> int option) (data: int list) =\n        let result =\n            data\n            |> Seq.choosei chooser\n            |> Seq.toArray\n\n        let expected =\n            data\n            |> Ref.choosei chooser\n            |> Seq.toArray\n\n        result = expected\n\n    [<Property>]\n    let ``[Seq] collecti`` (mapping: int -> int -> int list) (data: int list) =\n        let result =\n            data\n            |> Seq.collecti (fun i v -> mapping i v)\n            |> Seq.toArray\n\n        let expected =\n            data\n            |> Ref.collecti mapping\n            |> Seq.toArray\n\n        result = expected\n\n    [<Property>]\n    let ``[Seq] foldi`` (data: int list) =\n        let folder i state value = state + value + (i * 17)\n\n        let result =\n            data\n            |> Seq.foldi folder 0\n\n        let expected =\n            data\n            |> Ref.foldi folder 0\n\n        result = expected\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] foldi observes distinct indices`` () =\n        let data = [ 10; 20; 30 ]\n\n        let seen =\n            data\n            |> Seq.foldi (fun i acc value -> (i, value) :: acc) []\n            |> List.rev\n\n        let expected = [ (0, 10); (1, 20); (2, 30) ]\n        NUnit.Framework.Assert.That(seen, NUnit.Framework.Is.EqualTo(expected))\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] choosei rejects null source`` () =\n        assertNullSourceArg (fun () -> Seq.choosei (fun _ value -> Some value) (null : int seq) |> Seq.toArray)\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] collecti rejects null source`` () =\n        assertNullSourceArg (fun () -> Seq.collecti (fun _ value -> Seq.singleton value) (null : int seq) |> Seq.toArray)\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] foldi rejects null source`` () =\n        assertNullSourceArg (fun () -> Seq.foldi (fun _ state value -> state + value) 0 (null : int seq))\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] tryPickV rejects null source`` () =\n        assertNullSourceArg (fun () -> Seq.tryPickV (fun value -> ValueSome value) (null : int seq))\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] pickV rejects null source`` () =\n        assertNullSourceArg (fun () -> Seq.pickV (fun value -> ValueSome value) (null : int seq))\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] tryFindV rejects null source`` () =\n        assertNullSourceArg (fun () -> Seq.tryFindV (fun _ -> true) (null : int seq))\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] tryHeadV rejects null source`` () =\n        assertNullSourceArg (fun () -> Seq.tryHeadV (null : int seq))\n\n    [<NUnit.Framework.Test>]\n    let ``[Seq] tryLastV rejects null source`` () =\n        assertNullSourceArg (fun () -> Seq.tryLastV (null : int seq))\n\nmodule List =\n\n    [<Property>]\n    let ``[List] choosei`` (chooser: int -> int -> int option) (data: int list) =\n        let result =\n            data\n            |> List.choosei chooser\n            |> List.toArray\n\n        let expected =\n            data\n            |> Seq.Ref.choosei chooser\n            |> Seq.toArray\n\n        result = expected\n\n    [<Property>]\n    let ``[List] collecti`` (mapping: int -> int -> int list) (data: int list) =\n        let result =\n            data\n            |> List.collecti mapping\n            |> List.toArray\n\n        let expected =\n            data\n            |> Seq.Ref.collecti mapping\n            |> Seq.toArray\n\n        result = expected\n\nmodule Array =\n\n    let private toValueOption chooser value =\n        match chooser value with\n        | Some value -> ValueSome value\n        | None -> ValueNone\n\n    let private toIndexedValueOption chooser index value =\n        match chooser index value with\n        | Some value -> ValueSome value\n        | None -> ValueNone\n\n    let private toStructTupleArray (data : ('a * 'b)[]) =\n        data |> Array.map (fun (a, b) -> struct (a, b))\n\n    let private assertNullArrayArg (action : unit -> 'T) =\n        let ex =\n            NUnit.Framework.Assert.Throws<System.ArgumentNullException>(fun () -> action() |> ignore)\n\n        NUnit.Framework.Assert.That(ex.ParamName, NUnit.Framework.Is.EqualTo(\"array\"))\n\n    [<Property>]\n    let ``[Array] chooseV`` (chooser: int -> int option) (data: int[]) =\n        let result =\n            data\n            |> Array.chooseV (toValueOption chooser)\n\n        let expected =\n            data\n            |> Array.choose chooser\n\n        result = expected\n\n    [<Property>]\n    let ``[Array] choosei`` (chooser: int -> int -> int option) (data: int[]) =\n        let result =\n            data\n            |> Array.choosei chooser\n\n        let expected =\n            data\n            |> Seq.Ref.choosei chooser\n            |> Seq.toArray\n\n        result = expected\n\n    [<Property>]\n    let ``[Array] chooseiV`` (chooser: int -> int -> int option) (data: int[]) =\n        let result =\n            data\n            |> Array.chooseiV (toIndexedValueOption chooser)\n\n        let expected =\n            data\n            |> Seq.Ref.choosei chooser\n            |> Seq.toArray\n\n        result = expected\n\n    [<Property>]\n    let ``[Array] zipV`` (data : (int * int)[]) =\n        let left, right = Array.unzip data\n\n        let result =\n            Array.zipV left right\n\n        let expected =\n            Array.zip left right\n            |> toStructTupleArray\n\n        result = expected\n\n    [<Property>]\n    let ``[Array] unzipV`` (data : (int * int)[]) =\n        let structData = toStructTupleArray data\n\n        let struct (result1, result2) =\n            Array.unzipV structData\n\n        let expected1, expected2 =\n            Array.unzip data\n\n        result1 = expected1 && result2 = expected2\n\n    [<Property>]\n    let ``[Array] unzipV and zipV round-trip struct tuples`` (data : (int * int)[]) =\n        let structData = toStructTupleArray data\n        let struct (left, right) = Array.unzipV structData\n\n        let result =\n            Array.zipV left right\n\n        result = structData\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] zipV and unzipV support empty arrays`` () =\n        let zipped =\n            Array.zipV ([||] : string[]) ([||] : string[])\n\n        let struct (left : string[], right : string[]) =\n            Array.unzipV ([||] : struct (string * string)[])\n\n        NUnit.Framework.Assert.That(zipped, NUnit.Framework.Is.EqualTo([||] : struct (string * string)[]))\n        NUnit.Framework.Assert.That(left, NUnit.Framework.Is.EqualTo([||] : string[]))\n        NUnit.Framework.Assert.That(right, NUnit.Framework.Is.EqualTo([||] : string[]))\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] zipV and unzipV preserve reference payloads and nulls`` () =\n        let left = [| \"alpha\"; null; \"gamma\" |]\n        let right = [| \"one\"; \"two\"; null |]\n\n        let zipped =\n            Array.zipV left right\n\n        let expected =\n            [|\n                struct (\"alpha\", \"one\")\n                struct (null, \"two\")\n                struct (\"gamma\", null)\n            |]\n\n        let struct (unzippedLeft, unzippedRight) =\n            Array.unzipV zipped\n\n        NUnit.Framework.Assert.That(zipped, NUnit.Framework.Is.EqualTo(expected))\n        NUnit.Framework.Assert.That(unzippedLeft, NUnit.Framework.Is.EqualTo(left))\n        NUnit.Framework.Assert.That(unzippedRight, NUnit.Framework.Is.EqualTo(right))\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] zipV throws for different-length inputs`` () =\n        let left = [| 1; 2 |]\n        let right = [| 3 |]\n\n        let ex =\n            NUnit.Framework.Assert.Throws<System.ArgumentException>(fun () -> Array.zipV left right |> ignore)\n\n        NUnit.Framework.StringAssert.Contains(\"array1.Length = 2\", ex.Message)\n        NUnit.Framework.StringAssert.Contains(\"array2.Length = 1\", ex.Message)\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] zipV throws ArgumentNullException for null left input`` () =\n        let left : string[] = null\n        let right = [| \"value\" |]\n\n        let ex =\n            NUnit.Framework.Assert.Throws<System.ArgumentNullException>(fun () -> Array.zipV left right |> ignore)\n\n        NUnit.Framework.Assert.That(ex.ParamName, NUnit.Framework.Is.EqualTo(\"array1\"))\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] zipV throws ArgumentNullException for null right input`` () =\n        let left = [| \"value\" |]\n        let right : string[] = null\n\n        let ex =\n            NUnit.Framework.Assert.Throws<System.ArgumentNullException>(fun () -> Array.zipV left right |> ignore)\n\n        NUnit.Framework.Assert.That(ex.ParamName, NUnit.Framework.Is.EqualTo(\"array2\"))\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] unzipV throws ArgumentNullException for null input`` () =\n        let data : struct (string * string)[] = null\n\n        let ex =\n            NUnit.Framework.Assert.Throws<System.ArgumentNullException>(fun () -> Array.unzipV data |> ignore)\n\n        NUnit.Framework.Assert.That(ex.ParamName, NUnit.Framework.Is.EqualTo(\"array\"))\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] chooseV throws ArgumentNullException for null input`` () =\n        let data : int[] = null\n        assertNullArrayArg (fun () -> Array.chooseV (fun x -> ValueSome x) data)\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] chooseiV throws ArgumentNullException for null input`` () =\n        let data : int[] = null\n        assertNullArrayArg (fun () -> Array.chooseiV (fun _ x -> ValueSome x) data)\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] foldi throws ArgumentNullException for null input`` () =\n        let data : int[] = null\n        assertNullArrayArg (fun () -> Array.foldi (fun _ state value -> state + value) 0 data)\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] tryPickV throws ArgumentNullException for null input`` () =\n        let data : int[] = null\n        assertNullArrayArg (fun () -> Array.tryPickV (fun x -> ValueSome x) data)\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] pickV throws ArgumentNullException for null input`` () =\n        let data : int[] = null\n        assertNullArrayArg (fun () -> Array.pickV (fun x -> ValueSome x) data)\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] tryFindV throws ArgumentNullException for null input`` () =\n        let data : int[] = null\n        assertNullArrayArg (fun () -> Array.tryFindV (fun _ -> true) data)\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] tryHeadV throws ArgumentNullException for null input`` () =\n        let data : int[] = null\n        assertNullArrayArg (fun () -> Array.tryHeadV data)\n\n    [<NUnit.Framework.Test>]\n    let ``[Array] tryLastV throws ArgumentNullException for null input`` () =\n        let data : int[] = null\n        assertNullArrayArg (fun () -> Array.tryLastV data)\n\n    [<Property>]\n    let ``[Array] collecti`` (mapping: int -> int -> int[]) (data: int[]) =\n        let result =\n            data\n            |> Array.collecti mapping\n\n        let expected =\n            data\n            |> Seq.Ref.collecti mapping\n            |> Seq.toArray\n\n        result = expected\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Datastructures/MapExt.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen FsCheck\nopen FsCheck.NUnit\nopen FsUnit\nopen Aardvark.Base\nopen System.Collections.Generic\n\nmodule MapExt =\n\n    module List =\n        let all (l : list<bool>) =\n            l |> List.fold (&&) true\n\n    module MapExt =\n        let ofMap (m : Map<'K, 'V>) =\n            m |> Map.toSeq |> MapExt.ofSeq\n\n        let isValid (m : MapExt<'K, 'V>) =\n            let l = m |> MapExt.toList |> List.map fst\n            l = List.sort l\n\n        let equalToMap (m : Map<'K, 'V>) (me : MapExt<'K, 'V>) =\n            MapExt.toList me = Map.toList m\n\n    [<Property>]\n    let ``[MapExt] alter`` (m : Map<int, int>) (v : int) (f : Option<int> -> Option<int>) =\n        not (Map.containsKey v m) ==> lazy (\n            let me = MapExt.ofMap m\n\n            let alter (key : int) (f : Option<int> -> Option<int>) (m : Map<int, int>) =\n                match f (Map.tryFind key m) with\n                    | Some v -> Map.add key v m\n                    | None -> Map.remove key m\n\n            List.all [\n                MapExt.equalToMap (alter v f m) (MapExt.alter v f me)\n                MapExt.equalToMap (alter v f (Map.add v v m)) (MapExt.alter v f (MapExt.add v v me))\n            ]\n        )\n\n    [<Property>]\n    let ``[MapExt] choose`` (m : Map<int, int>) (f : int -> int -> Option<int>) =\n        let me = MapExt.ofMap m\n        let res = MapExt.choose f me\n\n        let choose (f : int -> int -> Option<int>) (m : Map<int, int>) =\n            let mutable res = Map.empty\n            for (k,v) in Map.toSeq m do\n                match f k v with\n                    | Some v -> res <- Map.add k v res\n                    | _ -> ()\n\n            res\n\n        List.all [\n            MapExt.isValid res\n            MapExt.equalToMap (choose f m) res\n        ]\n\n    type int2 = (struct (int * int))\n\n    [<Property(EndSize = 100000)>]\n    let ``[MapExt] choose2`` (k1: Set<int>) (k2: Set<int>) (f : int -> int2 option -> int2 option -> int2 option) =\n        let m1 = k1 |> Seq.map (fun k -> k, struct (1, k)) |> Map.ofSeq\n        let m2 = k2 |> Seq.map (fun k -> k, struct (2, k)) |> Map.ofSeq\n\n        let me1 = MapExt.ofMap m1\n        let me2 = MapExt.ofMap m2\n\n        let res =\n            (me1, me2) ||> MapExt.choose2 (fun k v1 v2 ->\n                v1 |> Option.iter (fstv >> should equal 1)\n                v2 |> Option.iter (fstv >> should equal 2)\n                f k v1 v2\n            )\n\n        let choose2 f (m1 : Map<_, _>) (m2 : Map<_, _>) =\n            let mutable res = Map.empty\n            for k in Map.keys (Map.union m1 m2) do\n                let v1 = Map.tryFind k m1\n                let v2 = Map.tryFind k m2\n                match f k v1 v2 with\n                | Some v -> res <- Map.add k v res\n                | _ -> ()\n            res\n\n        let valid = MapExt.isValid res\n\n        List.all [\n            valid\n            MapExt.equalToMap (choose2 f m1 m2) res\n        ]\n\n    [<Property(EndSize = 100000)>]\n    let ``[MapExt] map2`` (k1: Set<int>) (k2: Set<int>) (f : int -> int2 option -> int2 option -> int2) =\n        let m1 = k1 |> Seq.map (fun k -> k, struct (1, k)) |> Map.ofSeq\n        let m2 = k2 |> Seq.map (fun k -> k, struct (2, k)) |> Map.ofSeq\n\n        let me1 = MapExt.ofMap m1\n        let me2 = MapExt.ofMap m2\n\n        let res =\n            (me1, me2) ||> MapExt.map2 (fun k v1 v2 ->\n                v1 |> Option.iter (fstv >> should equal 1)\n                v2 |> Option.iter (fstv >> should equal 2)\n                f k v1 v2\n            )\n\n        let map2 f (m1 : Map<_, _>) (m2 : Map<_, _>) =\n            let mutable res = Map.empty\n            for k in Map.keys (Map.union m1 m2) do\n                let v1 = Map.tryFind k m1\n                let v2 = Map.tryFind k m2\n                let v = f k v1 v2\n                res <- Map.add k v res\n            res\n\n        let valid = MapExt.isValid res\n\n        List.all [\n            valid\n            MapExt.equalToMap (map2 f m1 m2) res\n        ]\n\n    [<Property>]\n    let ``[MapExt] range`` (m : Map<int, int>) (min : int) (max : int) =\n        (min <= max) ==> lazy (\n            let me = MapExt.ofMap m\n            let expected = me |> MapExt.filter (fun k _ -> k >= min && k <= max)\n            let actual = me |> MapExt.range min max\n            expected = actual\n        )\n\n    [<Property>]\n    let ``[MapExt] IDictionary item`` (m: Map<int, int>) =\n        let me = MapExt.ofMap m\n        let keys = m.Keys |> List.ofSeq\n        \n        keys |> List.map (fun key ->\n            let expected = (m :> IDictionary<_, _>).[key]\n            let actual = (me :> IDictionary<_, _>).[key]\n            expected = actual  \n        )\n        |> List.all\n\n    [<Property>]\n    let ``[MapExt] IDictionary keys`` (m: Map<int, int>) =\n        let me = MapExt.ofMap m\n        let kc = (me :> IDictionary<_, _>).Keys\n        let keys = m.Keys |> Array.ofSeq |> Array.sort\n\n        let contains =\n            keys |> Array.map kc.Contains\n\n        let enumerated =\n            kc |> Array.ofSeq |> Array.sort\n\n        let copied =\n            let arr = Array.zeroCreate<int> m.Count\n            kc.CopyTo(arr, 0)\n            Array.sort arr\n\n        List.all [\n            kc.Count = m.Count\n            copied = keys\n            enumerated = keys\n            yield! contains\n        ]\n\n    [<Property>]\n    let ``[MapExt] IDictionary values`` (m: Map<int, int>) =\n        let me = MapExt.ofMap m\n        let vc = (me :> IDictionary<_, _>).Values\n        let values = m.Values |> Array.ofSeq |> Array.sort\n\n        let contains =\n            values |> Array.map vc.Contains\n\n        let enumerated =\n            vc |> Array.ofSeq |> Array.sort\n\n        let copied =\n            let arr = Array.zeroCreate<int> m.Count\n            vc.CopyTo(arr, 0)\n            Array.sort arr\n\n        List.all [\n            vc.Count = m.Count\n            copied = values\n            enumerated = values\n            yield! contains\n        ]\n\n    [<Property>]\n    let ``[MapExt] IDictionary TryGetValue`` (m: Map<int, int>) =\n        let me = MapExt.ofMap m\n        let keys = m.Keys |> List.ofSeq\n\n        keys |> List.map (fun key ->\n            let exp, expv = (m :> IDictionary<_, _>).TryGetValue key\n            let act, actv = (me :> IDictionary<_, _>).TryGetValue key\n            act = exp && actv = expv\n        )\n        |> List.all\n\n    [<Property>]\n    let ``[MapExt] IReadOnlyDictionary TryGetValue`` (m: Map<int, int>) =\n        let me = MapExt.ofMap m\n        let keys = m.Keys |> List.ofSeq\n\n        keys |> List.map (fun key ->\n            let exp, expv = (m :> IReadOnlyDictionary<_, _>).TryGetValue key\n            let act, actv = (me :> IReadOnlyDictionary<_, _>).TryGetValue key\n            act = exp && actv = expv\n        )\n        |> List.all"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Datastructures/OrderMaintenanceTrie.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\n#nowarn \"1336\"\n\nopen Aardvark.Base.OrderMaintenanceTrieImplementation\nopen System.Collections.Generic\nopen NUnit.Framework\nopen Aardvark.Base\nopen FSharp.Data.Adaptive\n\nmodule OrderMaintenanceTrieTest =\n    let rec validateTree (x : OrderMaintenanceTrieNode<_,_>) =\n        if x.IsEmpty && not (List.isEmpty x.Path) then failwithf \"empty node with key: %A\" (List.rev x.Path)\n        \n        if not (isNull x.ChildrenDict) then\n            let mutable reached = HashSet.empty\n            let mutable missing = HashSet.ofSeq x.ChildrenDict.Keys\n            let mutable f = x.ChildrenDict.First\n            let mutable lastKey = ValueNone\n\n            let cmp = x.GetComparer(x.Level + 1)\n\n            while not (isNull f) do\n                let k = List.head f.Path\n\n                match lastKey with\n                | ValueSome last ->\n                    match cmp with\n                    | Some cmp -> \n                        if cmp.Compare(last, k) > 0 then failwithf \"inconsistent order on level %d (%A > %A)\" x.Level last k\n                    | None ->\n                        ()\n                | ValueNone ->\n                    ()\n\n                missing <- HashSet.remove k missing\n\n                if HashSet.contains k reached then\n                    failwithf \"duplicate key: %A\" k\n                reached <- HashSet.add k reached\n\n                if f.Parent <> x then\n                    failwithf \"bad parent for %A: %A\" (List.rev f.Path) (List.rev f.Parent.Path)\n\n                validateTree f\n\n                f <- f.Next\n                lastKey <- ValueSome k\n\n            if missing.Count > 0 then \n                failwithf \"not all keys reached: %A\" missing\n\n    let validateInternal (getComparer : int -> option<IComparer<'k>>) (t : OrderMaintenanceTrie<'k, 'v>) =\n        validateTree t.Root\n\n        let forward = \n            let res = System.Collections.Generic.List<list<'k> * 'v>()\n            let mutable c = t.First\n            while (ValueOption.isSome c) do\n                res.Add(c.Value.Key, c.Value.Value)\n                c <- c.Value.Next\n            res\n\n        let backward = \n            let res = System.Collections.Generic.List<list<'k> * 'v>()\n            let mutable c = t.Last\n            while (ValueOption.isSome c) do\n                res.Add(c.Value.Key, c.Value.Value)\n                c <- c.Value.Prev\n            res\n\n        let all =\n            let res = System.Collections.Generic.List<list<'k> * 'v>()\n            t.Iter(fun k v -> res.Add(k,v))\n            res\n\n\n        if forward.Count <> all.Count then \n            failwithf \"inconsistent forward count: %A vs %A\" forward.Count all.Count\n\n        if backward.Count <> all.Count then \n            failwithf \"inconsistent backward counts: %A vs %A\" backward.Count all.Count\n            \n        let mutable j = backward.Count - 1\n        for i in 0 .. forward.Count - 1 do\n            if forward.[i] <> backward.[j] then\n                failwithf \"error at position %d: %A vs %A\" i forward.[i] backward.[j]\n            if forward.[i] <> all.[i] then\n                failwithf \"error at position %d: %A vs %A\" i forward.[i] all.[j]\n            j <- j - 1\n\n    let validateAgainst (t : OrderMaintenanceTrie<'k, 'v>) (m : HashMap<list<'k>, 'v>) =\n        let mutable missing = m\n        t.Iter (fun k v ->\n            match HashMap.tryRemove k missing with\n            | Some (hv, r) ->\n                if v <> hv then failwithf \"inconsistent value %A vs %A\" v hv\n                missing <- r\n            | None ->\n                failwithf \"superflous value for %A: %A\" k v\n        )\n\n        if missing.Count > 0 then \n            failwithf \"missing values: %A\" missing\n\n    type ValidationTrie<'k, 'v when 'k : equality and 'v : equality>(getComparer : int -> option<IComparer<'k>>) =\n\n        let trie = OrderMaintenanceTrie<'k, 'v>(getComparer)\n        let mutable store = HashMap.empty\n\n        let check() =\n            validateInternal getComparer trie\n            validateAgainst trie store\n\n        member x.Forward =\n            let rec s (r : voption<TrieReference<_,_>>) =\n                match r with\n                | ValueSome r -> \n                    Seq.append\n                        (Seq.singleton (r.Key, r.Value))\n                        (Seq.delay (fun () -> s r.Next))\n                | ValueNone ->\n                    Seq.empty\n            s trie.First\n            \n        member x.Count = store.Count\n        member x.Content = store\n        member x.Trie = trie\n\n        member x.Set(key : list<'k>, value : 'v) =\n            trie.Set(key, value) |> ignore\n            store <- HashMap.add key value store\n            check()\n\n        member x.Remove(key : list<'k>) =\n            trie.TryRemove(key) |> ignore\n            store <- HashMap.remove key store\n            check()\n\n        member x.AddOrUpdate(key : list<'k>, create : voption<'v> -> 'v) =\n\n            let mutable other = None\n            let realCreate (o : voption<'v>) =\n                match other with\n                | Some (oo, on) ->\n                    if oo <> o then failwithf \"bad old value: %A vs %A\" oo o\n                    on\n                | None ->\n                    let r = create o\n                    other <- Some (o, r)\n                    r\n\n            trie.AddOrUpdate(key, realCreate) |> ignore\n            store <- store.AlterV(key, realCreate >> ValueSome)\n            check()\n\n\n    [<Test>]\n    let ``[OrderMaintenanceTrie] validation``() =\n        let rand = RandomSystem()\n        \n        let comparers =\n            Seq.initInfinite (fun i ->\n                if i % 2 = 0 then Comparer<int>.Default :> IComparer<_> |> Some\n                else None\n            ) |> Seq.cache\n        \n\n        let t = \n            ValidationTrie (fun l ->\n                Seq.item l comparers\n            )\n\n        let mutable updates = 0\n        let mutable adds = 0\n        let mutable removes = 0\n        let mutable dummyRemoves = 0\n        let mutable maxCount = 0\n\n        let add() =\n            if rand.UniformDouble() > 0.2 || t.Count = 0 then\n                // new key\n                let k = \n                    let len = rand.UniformInt(5) + 1\n                    List.init len (fun _ -> rand.UniformInt(20))\n\n                adds <- adds + 1\n                let v = List.sum k\n                t.Set(k, v)\n            else\n                // existing key \n                let k = t.Content |> Seq.item (rand.UniformInt t.Count) |> fst\n                updates <- updates + 1\n                if rand.UniformDouble() > 0.5 then\n                    t.Set(k, rand.UniformInt())\n                else\n                    t.AddOrUpdate(k, function ValueSome o -> 2*o | _ -> failwith \"should exist\")\n            maxCount <- max maxCount t.Count\n\n        let rem() = \n            if rand.UniformDouble() > 0.05 && t.Count > 0 then\n                // existing key\n                removes <- removes + 1\n                let k = t.Content |> Seq.item (rand.UniformInt t.Count) |> fst\n                t.Remove(k)\n            else\n                dummyRemoves <- dummyRemoves + 1\n                // non existing key\n                let k = \n                    let len = rand.UniformInt(5) + 1\n                    List.init len (fun _ -> rand.UniformInt(100))\n                t.Remove k\n            maxCount <- max maxCount t.Count\n\n        let randomOp () =\n            if t.Count > 1 then\n                if rand.UniformDouble() > 0.55 then\n                    rem()\n                else\n                    add()\n            else\n                add()\n                \n        let iter = 50000\n        Log.startTimed \"random ops\"\n        for i in 1 .. iter do\n            randomOp()\n\n        Log.line \"%d adds\" adds\n        Log.line \"%d updates\" updates\n        Log.line \"%d removes\" removes\n        Log.line \"%d removes of non existing\" dummyRemoves\n        Log.line \"%d maximal entries\" maxCount\n        Log.stop()\n\n        Log.start \"content\"\n        for (k, v) in t.Trie do\n            Log.line \"%A: %A\" k v\n        Log.stop()"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Datastructures/RangeSetTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen System\nopen Aardvark.Base\n\nmodule RangeSetTests =\n    open FsUnit\n    open NUnit.Framework\n\n    [<Theory>]\n    let ``[RangeSet] Insert`` (maxValue : bool) (mergeWithMaxValue : bool) =\n        let mutable s2 = RangeSet1l.empty\n\n        let add (r : Range1l) =\n            s2 <- s2 |> RangeSet1l.add r\n\n        let equal (expected : Range1l list) =\n            Seq.toList s2 |> should equal expected\n\n        add <| Range1l(0L, 1L)\n        add <| Range1l(1L, 2L)\n        equal [ Range1l(0L, 2L) ]\n\n        add <| Range1l(3L, 4L)\n        equal [ Range1l(0L, 4L) ]\n\n        add <| Range1l(6L, 8L)\n        equal [ Range1l(0L, 4L); Range1l(6L, 8L) ]\n\n        if maxValue then\n            add <| Range1l Int64.MaxValue\n            equal [ Range1l(0L, 4L); Range1l(6L, 8L); Range1l(Int64.MaxValue) ]\n\n            add <| Range1l(9L, 14L)\n            equal [ Range1l(0L, 4L); Range1l(6L, 14L); Range1l(Int64.MaxValue) ]\n\n            add <| Range1l(42L, if mergeWithMaxValue then Int64.MaxValue - 1L else Int64.MaxValue)\n            equal [ Range1l(0L, 4L); Range1l(6L, 14L); Range1l(42L, Int64.MaxValue) ]\n\n    [<Theory>]\n    let ``[RangeSet] Remove`` (maxValue : bool) =\n        let init = [ Range1l(0L, 4L); Range1l(6L, 8L); if maxValue then Range1l(42L, Int64.MaxValue) ]\n        let mutable s2 = RangeSet1l.ofList init\n\n        let rem (r : Range1l) =\n            s2 <- s2 |> RangeSet1l.remove r\n\n        let equal (expected : Range1l list) =\n            Seq.toList s2 |> should equal expected\n\n        rem <| Range1l(3L, 3L)\n        equal [ Range1l(0L, 2L); Range1l(4L, 4L); Range1l(6L, 8L); if maxValue then Range1l(42L, Int64.MaxValue) ]\n\n        rem <| Range1l(4L, 4L)\n        equal [ Range1l(0L, 2L); Range1l(6L, 8L); if maxValue then Range1l(42L, Int64.MaxValue) ]\n\n        rem <| Range1l(2L, 7L)\n        equal [ Range1l(0L, 1L); Range1l(8L, 8L); if maxValue then Range1l(42L, Int64.MaxValue) ]\n\n        rem <| Range1l(-12L, 7L)\n        equal [ Range1l(8L, 8L); if maxValue then Range1l(42L, Int64.MaxValue) ]\n\n        if maxValue then\n            rem <| Range1l(0L, Int64.MaxValue - 1L)\n            equal [ Range1l(Int64.MaxValue) ]\n\n            rem <| Range1l(Int64.MaxValue)\n            equal []\n\n            s2 <- RangeSet1l.ofList [ Range1l(0L, Int64.MaxValue) ]\n            rem <| Range1l(Int64.MaxValue)\n            equal [ Range1l(0L, Int64.MaxValue - 1L) ]\n\n    [<Theory>]\n    let ``[RangeSet] ToList`` (maxValue : bool) =\n        let init = [ Range1l(0L, 4L); Range1l(6L, 8L); if maxValue then Range1l(10L, Int64.MaxValue)  ]\n        let mutable s2 = RangeSet1l.ofList init\n        RangeSet1l.toList s2 |> should equal init\n\n    [<Theory>]\n    let ``[RangeSet] ToArray`` (maxValue : bool) =\n        let init = [ Range1l(0L, 4L); Range1l(6L, 8L); if maxValue then Range1l(10L, Int64.MaxValue) ]\n        let mutable s2 = RangeSet1l.ofList init\n        RangeSet1l.toArray s2 |> should equal (Array.ofList init)\n\n    [<Theory>]\n    let ``[RangeSet] ToSeq`` (maxValue : bool) =\n        let init = [ Range1l(0L, 4L); Range1l(6L, 8L); if maxValue then Range1l(10L, Int64.MaxValue) ]\n        let mutable s2 = RangeSet1l.ofList init\n        RangeSet1l.toSeq s2 |> Seq.toList |> should equal init\n\n    [<Theory>]\n    let ``[RangeSet] Min / Max / Range`` (maxValue : bool) =\n        let init = [ Range1l(-3L, -2L); Range1l(1L, 4L); Range1l(6L, 8L); if maxValue then Range1l(10L, Int64.MaxValue) ]\n        let min = init |> List.map (fun r -> r.Min) |> List.min\n        let max = init |> List.map (fun r -> r.Max) |> List.max\n\n        let mutable s2 = RangeSet1l.ofList init\n\n        s2.Min |> should equal min\n        s2.Max |> should equal max\n        s2.Range |> should equal (Range1l(min, max))\n\n    [<Theory>]\n    let ``[RangeSet] Intersect`` (hasMaxValue : bool) (testMaxValue : bool) =\n        let init = [ Range1l(-3L, -2L); Range1l(1L, 4L); Range1l(6L, 8L); if hasMaxValue then Range1l(10L, Int64.MaxValue)]\n        let s2 = RangeSet1l.ofList init\n\n        let intersect (r : Range1l) =\n            let r2 = s2 |> RangeSet1l.intersect r\n            RangeSet1l.toList r2\n\n        if testMaxValue then\n            Range1l(2L, Int64.MaxValue)   |> intersect |> should equal [ Range1l(2L, 4L); Range1l(6L, 8L); if hasMaxValue then Range1l(10L, Int64.MaxValue) ]\n            Range1l(5L, Int64.MaxValue)   |> intersect |> should equal [ Range1l(6L, 8L); if hasMaxValue then Range1l(10L, Int64.MaxValue) ]\n            Range1l(1L, Int64.MaxValue)   |> intersect |> should equal [ Range1l(1L, 4L); Range1l(6L, 8L); if hasMaxValue then Range1l(10L, Int64.MaxValue) ]\n            Range1l(4L, Int64.MaxValue)   |> intersect |> should equal [ Range1l(4L, 4L); Range1l(6L, 8L); if hasMaxValue then Range1l(10L, Int64.MaxValue) ]\n            Range1l(-3L, Int64.MaxValue)  |> intersect |> should equal init\n            Range1l(-42L, Int64.MaxValue) |> intersect |> should equal init\n        else\n            Range1l(2L, 3L)    |> intersect |> should equal [ Range1l(2L, 3L) ]\n            Range1l(5L, 6L)    |> intersect |> should equal [ Range1l(6L, 6L) ]\n            Range1l(-3L, 8L)   |> intersect |> should equal [ Range1l(-3L, -2L); Range1l(1L, 4L); Range1l(6L, 8L) ]\n            Range1l(-42L, 42L) |> intersect |> should equal [ Range1l(-3L, -2L); Range1l(1L, 4L); Range1l(6L, 8L); if hasMaxValue then Range1l(10L, 42L) ]\n            Range1l(-3L, -2L)  |> intersect |> should equal [ Range1l(-3L, -2L) ]\n            Range1l(-2L, -1L)  |> intersect |> should equal [ Range1l(-2L, -2L); ]\n            Range1l(-2L, 1L)   |> intersect |> should equal [ Range1l(-2L, -2L); Range1l(1L, 1L) ]\n            Range1l(-3L, 3L)   |> intersect |> should equal [ Range1l(-3L, -2L); Range1l(1L, 3L) ]\n            Range1l(-2L, 8L)   |> intersect |> should equal [ Range1l(-2L, -2L); Range1l(1L, 4L); Range1l(6L, 8L) ]\n\n    [<Theory>]\n    let ``[RangeSet] Enumerator`` (maxValue : bool) =\n        let init = [ Range1l(-3L, -2L); Range1l(1L, 4L); if maxValue then Range1l(6L, Int64.MaxValue) ]\n        let s2 = RangeSet1l.ofList init\n\n        let expected = Seq.ofList init\n        s2 :> seq<_> |> should equal expected\n\n    [<Theory>]\n    let ``[RangeSet] Equality`` (maxValue : bool) =\n        let init = [ Range1l(-3L, -2L); Range1l(1L, 4L); Range1l(6L, 8L); if maxValue then Range1l(34L, Int64.MaxValue) ]\n        let mutable a2 = RangeSet1l.ofList init\n        let mutable b2 = RangeSet1l.ofList init\n        (a2 = b2) |> should be True\n\n    [<Test>]\n    let ``[RangeSet] ofList`` () =\n        let rnd = RandomSystem(0)\n\n        let ranges =\n            List.init 5 (fun _ ->\n                let mutable l = Int64.MaxValue\n                let mutable r = Int64.MinValue\n\n                while l > r do\n                    l <- rnd.UniformLong()\n                    r <- l + rnd.UniformLong(100000L)\n\n                Range1l(l, r)\n            )\n\n        let expected = (RangeSet1l.empty, ranges) ||> List.fold (fun s r -> RangeSet1l.add r s)\n        let actual = RangeSet1l.ofList ranges\n        actual |> should equal expected\n\n    [<Theory>]\n    let ``[RangeSet] Contains Range`` (maxValue : bool) =\n        let set = RangeSet1l.ofList [ Range1l(-3L, -2L); Range1l(1L, 4L); Range1l(6L, 8L); Range1l(10L, if maxValue then Int64.MaxValue else 30L)]\n\n        set |> RangeSet1l.containsRange (Range1l(-3L, -2L)) |> should be True\n        set |> RangeSet1l.containsRange (Range1l(-3L, -3L)) |> should be True\n        set |> RangeSet1l.containsRange (Range1l(-3L, -2L)) |> should be True\n        set |> RangeSet1l.containsRange (Range1l(-2L, -2L)) |> should be True\n\n        set |> RangeSet1l.containsRange (Range1l(2L, 3L)) |> should be True\n        set |> RangeSet1l.containsRange (Range1l(3L, 3L)) |> should be True\n\n        set |> RangeSet1l.containsRange (Range1l(-2L, 3L)) |> should be False\n\n        set |> RangeSet1l.containsRange (Range1l(20L, Int64.MaxValue)) |> should equal maxValue"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Datastructures/SortedSetExt.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen System\nopen Aardvark.Base\nopen FsUnit\nopen NUnit.Framework\nopen System.Runtime.InteropServices\nopen System.Diagnostics\nopen System.Collections.Generic\n\n\n\nmodule SortedSetNeighbours =\n    \n\n    [<Test>]\n    let ``[SortedDict] neighbours``() =\n        \n        let values = HashSet [1..50000]\n        let r = Random()\n        let d = SortedDictionaryExt(compare)\n        let content = SortedSet []\n        \n        let slowNeighbours (v : int) =\n            let mutable last = None\n            let l = Seq.toList content\n\n            let rec find (v : int) (last : Option<int * int>) (l : list<int>) =\n                match l with\n                    | [] -> last,None\n                    | k::rest ->\n                        if k >= v then\n                            if k = v then\n                                last, (match rest with | r::_ -> Some (r,r) | _ -> None)\n                            else\n                                last, Some (k,k)\n                        else\n                            find v (Some (k,k)) rest\n\n            find v None l\n                    \n\n\n        for i in 0..10000 do\n            \n            let remove = r.NextDouble() > 0.5 && d.Count > 0\n\n            if remove && i > 200 then\n                let kvp = d |> Seq.item (r.Next(d.Count))\n                d.Remove kvp.Key |> should be True\n                values.Add kvp.Key |> should be True\n                content.Remove kvp.Key |> should be True\n\n\n                let l,s,r = d |> SortedDictionary.neighbourhood kvp.Key\n                let lc,rc = slowNeighbours kvp.Key\n\n                s |> should equal None\n                l |> should equal lc\n                r |> should equal rc\n\n                ()\n            else\n                let v = values |> Seq.item (r.Next values.Count)\n                values.Remove v |> should be True\n\n                let l,s,r = d |> SortedDictionary.neighbourhood v\n                let lc,rc = slowNeighbours v\n\n                s |> should equal None\n                l |> should equal lc\n                r |> should equal rc\n\n\n\n                d.Add(v,v)\n                content.Add v |> should be True\n\n                ()\n\n\n\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/EnumTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen System\nopen Aardvark.Base\n\nopen NUnit.Framework\nopen FsUnit\n\nmodule EnumTests =\n\n    type EnumUI8 =\n        | Zero = 0uy\n        | Two = 2uy\n\n    type EnumI32 =\n        | Two = 2\n        | Three = 3\n\n    type UnexpectedPassException() =\n        inherit Exception()\n\n    let inline shouldFailWith<'TExn> (f: unit -> unit) =\n        try\n            f() |> ignore\n            raise <| UnexpectedPassException()\n        with\n        | :? UnexpectedPassException -> failwith $\"Expected exception of type {typeof<'TExn>} but got none.\"\n        | exn when exn.GetType() <> typeof<'TExn> -> failwith $\"Expected exception of type {typeof<'TExn>} but got: {exn}\"\n        | _ -> ()\n\n    [<Test>]\n    let ``[Enum] convert`` () =\n        Enum.convert<_, EnumI32> 3 |> should equal EnumI32.Three\n        Enum.convert<_, EnumI32> 3uy |> should equal EnumI32.Three\n        Enum.convert<_, EnumI32> 3L |> should equal EnumI32.Three\n        Enum.convert<_, EnumI32> EnumI32.Three |> should equal EnumI32.Three\n        Enum.convert<_, EnumI32> EnumUI8.Two |> should equal EnumI32.Two\n        Enum.convert<_, EnumI32> 3.14 |> should equal EnumI32.Three\n        Enum.convert<_, EnumI32> \"3\" |> should equal EnumI32.Three\n\n        shouldFailWith<InvalidCastException> (fun _ -> Enum.convert<_, EnumI32> EnumUI8.Zero |> ignore)\n        shouldFailWith<FormatException> (fun _ -> Enum.convert<_, EnumI32> \"Foo\" |> ignore)"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/GeometryValueOptionTests.fs",
    "content": "namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\nopen Aardvark.Base.Geometry\n\nopen NUnit.Framework\nopen FsUnit\n\nmodule GeometryValueOptionTests =\n\n    let private toOption value =\n        match value with\n        | ValueSome value -> Some value\n        | ValueNone -> None\n\n    let private hitData<'a> (hit : option<RayHit<'a>>) =\n        hit |> Option.map (fun h -> h.T, h.Value)\n\n    let private intersectionsData<'a> (hits : seq<RayHit<'a>>) =\n        hits |> Seq.map (fun h -> h.T, h.Value) |> Seq.toArray\n\n    let private sphere center radius =\n        Sphere3d.FromCenterAndRadius(center, radius)\n\n    let private box center size =\n        Box3d.FromCenterAndSize(center, size)\n\n    let private hitRay =\n        RayPart.ofRay <| FastRay3d(V3d.Zero, V3d.OOI)\n\n    let private missRay =\n        RayPart.ofRay <| FastRay3d(V3d(3.0, 0.0, 0.0), V3d.OOI)\n\n    let private bvhData =\n        [|\n            let s = sphere (V3d(0.0, 0.0, 5.0)) 1.0\n            (0, s), s.BoundingBox3d\n\n            let s = sphere (V3d(0.0, 0.0, 8.0)) 1.0\n            (1, s), s.BoundingBox3d\n\n            let s = sphere (V3d(4.0, 0.0, 5.0)) 1.0\n            (2, s), s.BoundingBox3d\n        |]\n\n    let private bvh = BvhTree.ofArray bvhData\n\n    let private trySphere part ((id, sphere) : int * Sphere3d) =\n        match RayPart.intersect part sphere with\n        | Some t -> Some <| RayHit(t, id)\n        | None -> None\n\n    let private trySphereV part ((id, sphere) : int * Sphere3d) =\n        match RayPart.intersectV part sphere with\n        | ValueSome t -> ValueSome <| RayHit(t, id)\n        | ValueNone -> ValueNone\n\n    let private kdBoxes =\n        [|\n            box (V3d(0.0, 0.0, 5.0)) (V3d(2.0, 2.0, 2.0))\n            box (V3d(0.0, 0.0, 8.0)) (V3d(2.0, 2.0, 2.0))\n            box (V3d(5.0, 0.0, 5.0)) (V3d(2.0, 2.0, 2.0))\n        |]\n\n    let private kdTree = KdTree(Spatial.box, kdBoxes)\n\n    let private tryBox part (box : Box3d) =\n        match RayPart.intersect part box with\n        | Some t -> Some <| RayHit(t, box.Center.Z)\n        | None -> None\n\n    let private tryBoxV part (box : Box3d) =\n        match RayPart.intersectV part box with\n        | ValueSome t -> ValueSome <| RayHit(t, box.Center.Z)\n        | ValueNone -> ValueNone\n\n    [<Test>]\n    let ``[Geometry] BvhTree.intersectV matches intersect for hit and miss rays`` () =\n        let hit =\n            BvhTree.intersect trySphere hitRay bvh\n            |> hitData\n\n        let hitV =\n            BvhTree.intersectV trySphereV hitRay bvh\n            |> toOption\n            |> hitData\n\n        let miss =\n            BvhTree.intersect trySphere missRay bvh\n            |> hitData\n\n        let missV =\n            BvhTree.intersectV trySphereV missRay bvh\n            |> toOption\n            |> hitData\n\n        hitV |> should equal hit\n        missV |> should equal miss\n\n    [<Test>]\n    let ``[Geometry] BvhTree.IntersectionsV preserves ordered hit sequence`` () =\n        let hits =\n            bvh.Intersections(trySphere, hitRay)\n            |> intersectionsData\n\n        let hitsV =\n            bvh.IntersectionsV(trySphereV, hitRay)\n            |> intersectionsData\n\n        hitsV |> should equal hits\n        hitsV |> should equal [| (4.0, 0); (7.0, 1) |]\n\n    [<Test>]\n    let ``[Geometry] KdTree.intersectV matches intersect for hit and miss rays`` () =\n        let hit =\n            KdTree.intersect tryBox hitRay kdTree\n            |> hitData\n\n        let hitV =\n            KdTree.intersectV tryBoxV hitRay kdTree\n            |> toOption\n            |> hitData\n\n        let miss =\n            KdTree.intersect tryBox missRay kdTree\n            |> hitData\n\n        let missV =\n            KdTree.intersectV tryBoxV missRay kdTree\n            |> toOption\n            |> hitData\n\n        hitV |> should equal hit\n        missV |> should equal miss\n\n    [<Test>]\n    let ``[Geometry] nearest hit is preserved for BvhTree and KdTree`` () =\n        let bvhHit =\n            BvhTree.intersectV trySphereV hitRay bvh\n            |> toOption\n            |> hitData\n\n        let kdHit =\n            KdTree.intersectV tryBoxV hitRay kdTree\n            |> toOption\n            |> hitData\n\n        bvhHit |> should equal (Some (4.0, 0))\n        kdHit |> should equal (Some (4.0, 5.0))\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/HMap.fs",
    "content": "﻿module HashMap\n\nopen System\nopen NUnit\nopen FsCheck\nopen FsCheck.NUnit\nopen Aardvark.Base\n\nmodule List =\n    let all (l : list<bool>) =\n        l |> List.fold (&&) true\n\n[<CustomEquality; CustomComparison>]\ntype StupidHash = { value : int } with\n    \n    interface IComparable with\n        member x.CompareTo o =\n            match o with\n                | :? StupidHash as o -> compare x.value o.value\n                | _ -> failwith \"cannot compare\"\n\n    override x.GetHashCode() = abs x.value % 2\n    override x.Equals o =   \n        match o with\n            | :? StupidHash as o -> x.value = o.value\n            | _ -> false\n\n\n[<Property>]\nlet ``[HashMap] count`` (l : Map<int, int>) (a : int)  =\n    not (Map.containsKey a l) ==> lazy (\n        let map = l |> Map.toList |> HashMap.ofList\n        let mapWithA = HashMap.add a a map\n\n        List.all [\n            HashMap.count HashMap.empty = 0\n            HashMap.count mapWithA = HashMap.count map + 1\n            HashMap.count (HashMap.remove a mapWithA) = HashMap.count map\n            HashMap.count map = l.Count\n            HashMap.count (HashMap.union map map) = HashMap.count map\n            HashMap.count (HashMap.map (fun _ v -> v) map) = HashMap.count map\n            HashMap.count (HashMap.filter (fun _ _ -> true) map) = HashMap.count map\n            HashMap.count (HashMap.filter (fun _ _ -> false) map) = 0\n            HashMap.count (HashMap.choose (fun _ v -> Some v) map) = HashMap.count map\n            HashMap.count (HashMap.choose (fun _ _ -> None) map) = 0\n            HashMap.count (HashMap.alter a (fun _ -> None) mapWithA) = HashMap.count map\n            HashMap.count (HashMap.alter a (fun _ -> Some 5) mapWithA) = HashMap.count mapWithA\n            HashMap.count (HashMap.update a (fun _ -> 5) mapWithA) = HashMap.count mapWithA\n        ]\n    )\n\n[<Property>]\nlet ``[HashMap] tryFind`` (l : Map<int, int>) (a : int)  =\n    not (Map.containsKey a l) ==> lazy (\n        let map = l |> Map.toList |> HashMap.ofList\n        let mapWithA = HashMap.add a a map\n        \n        List.all [\n            HashMap.tryFind a mapWithA = Some a\n            HashMap.tryFind a map = None\n            HashMap.tryFind a (HashMap.add a 7 mapWithA) = Some 7\n            HashMap.tryFind a (HashMap.add a 7 map) = Some 7\n            HashMap.tryFind a (HashMap.remove a mapWithA) = None\n            HashMap.tryFind a (HashMap.union map mapWithA) = Some a\n            HashMap.tryFind a (HashMap.alter a (fun o -> Some 100) mapWithA) = Some 100\n            HashMap.tryFind a (HashMap.alter a (fun o -> None) mapWithA) = None\n            HashMap.tryFind a (HashMap.update a (fun o -> 123) mapWithA) = Some 123\n            HashMap.tryFind a (HashMap.update a (fun o -> 123) map) = Some 123\n            HashMap.tryFind a (HashMap.choose (fun _ v -> Some v) mapWithA) = Some a\n            HashMap.tryFind a (HashMap.choose (fun _ v -> None) mapWithA) = None\n            HashMap.tryFind a (HashMap.choose (fun _ v -> Some 7) mapWithA) = Some 7\n            HashMap.tryFind a (HashMap.filter (fun _ v -> true) mapWithA) = Some a\n            HashMap.tryFind a (HashMap.filter (fun _ v -> false) mapWithA) = None\n\n        ]\n\n    )\n\n[<Property>]\nlet ``[HashMap] containsKey`` (l : Map<int, int>) (a : int)  =\n    let map = l |> Map.toList |> HashMap.ofList\n    HashMap.containsKey a map = Option.isSome (HashMap.tryFind a map)\n\n[<Property>]\nlet ``[HashMap] find`` (l : Map<int, int>) (a : int)  =\n    let map = l |> Map.toList |> HashMap.ofList\n    let map = map |> HashMap.add a a\n    HashMap.find a map = a\n\n[<Property>]\nlet ``[HashMap] ofList`` (l : list<int * int>) =\n    List.sortBy fst (HashMap.toList (HashMap.ofList l)) = Map.toList (Map.ofList l)\n\n[<Property>]\nlet ``[HashMap] map2/choose2`` (lm : Map<int, int>) (rm : Map<int, int>) =\n    let l = lm |> Map.toList |> HashMap.ofList\n    let r = rm |> Map.toList |> HashMap.ofList\n\n    let map2 (f : 'k -> Option<'a> -> Option<'b> -> 'c) (l : Map<'k, 'a>) (r : Map<'k, 'b>) =\n        let mutable res = Map.empty\n\n        for (lk,lv) in Map.toSeq l do\n            match Map.tryFind lk r with\n                | Some rv -> res <- Map.add lk (f lk (Some lv) (Some rv)) res\n                | None -> res <- Map.add lk (f lk (Some lv) None) res\n\n        for (rk,rv) in Map.toSeq r do\n            match Map.tryFind rk l with\n                | Some _ -> ()\n                | None -> res <- Map.add rk (f rk None (Some rv)) res\n\n        res\n\n    let choose2 (f : 'k -> Option<'a> -> Option<'b> -> Option<'c>) (l : Map<'k, 'a>) (r : Map<'k, 'b>) =\n        let mutable res = Map.empty\n\n        for (lk,lv) in Map.toSeq l do\n            match Map.tryFind lk r with\n                | Some rv -> \n                    match f lk (Some lv) (Some rv) with\n                        | Some r ->\n                            res <- Map.add lk r res\n                        | None ->\n                            ()\n                | None -> \n                    match f lk (Some lv) None with\n                        | Some r -> res <- Map.add lk r res\n                        | None -> ()\n\n        for (rk,rv) in Map.toSeq r do\n            match Map.tryFind rk l with\n                | Some _ -> ()\n                | None -> \n                    match f rk None (Some rv) with\n                        | Some r -> res <- Map.add rk r res\n                        | None -> ()\n\n        res\n\n    let equal (l : hmap<'k, 'v>) (r : Map<'k, 'v>) =\n        let l = l |> HashMap.toList |> List.sortBy fst\n        let r = r |> Map.toList\n        l = r\n\n    let add (k : int) (l : Option<int>) (r : Option<int>) =\n        match l, r with\n            | Some l, Some r -> l + r\n            | None, Some r -> r\n            | Some l, None -> l\n            | None, None -> failwith \"that's bad (Map invented a key)\"\n\n    let add2 (k : int) (l : Option<int>) (r : Option<int>) =\n        match l, r with\n            | Some l, Some r -> if l > r then Some r else None\n            | None, Some r -> Some r\n            | Some l, None -> Some l\n            | None, None -> failwith \"that's bad (Map invented a key)\"\n\n    List.all [\n        equal (HashMap.map2 add l r) (map2 add lm rm)\n        equal (HashMap.choose2 (fun k l r -> add k l r |> Some) l r) (map2 add lm rm)\n        equal (HashMap.choose2 (fun k l r -> add2 k l r) l r) (choose2 add2 lm rm)\n    ]\n\n[<Property>]\nlet ``[HashMap] choose`` (m : Map<int, int>) (f : int -> int -> Option<int>) =\n    let h = HashMap.ofSeq (Map.toSeq m)\n\n    let tm =\n        let mutable res = Map.empty\n        for (KeyValue(k,v)) in m do\n            match f k v with\n                | Some v -> res <- Map.add k v res\n                | _ -> ()\n        res\n\n    let th = HashMap.choose f h |> Map.ofSeq\n\n    tm = th\n\n\n\n[<Property>]\nlet ``[HashMap] equality`` (h0 : StupidHash) =\n    let h1 = { value = h0.value + 1 }\n    let h2 = { value = h0.value + 2 }\n    let h3 = { value = h0.value + 3 }\n    let a = HashMap.empty |> HashMap.add h0 0 |> HashMap.add h1 1 |> HashMap.add h2 2 |> HashMap.add h3 3\n    let b = HashMap.empty |> HashMap.add h1 1 |> HashMap.add h2 2 |> HashMap.add h3 3 |> HashMap.add h0 0\n    let c = HashMap.empty |> HashMap.add h2 2 |> HashMap.add h3 3 |> HashMap.add h0 0 |> HashMap.add h1 1\n    let d = HashMap.empty |> HashMap.add h3 3 |> HashMap.add h0 0 |> HashMap.add h1 1 |> HashMap.add h2 2\n    \n    let x = d |> HashMap.add h3 4\n    let y = d |> HashMap.add { value = h0.value + 4 } 4\n\n    let ah = a.GetHashCode()\n    let bh = b.GetHashCode()\n    let ch = c.GetHashCode()\n    let dh = d.GetHashCode()\n\n    a = a && b = b && c = c && d = d && x = x && y = y &&\n\n    a = b && a = c && a = d && b = c && b = d && c = d && \n    b = a && c = a && d = a && c = b && d = b && d = c && \n\n    ah = bh && bh = ch && ch = dh &&\n\n    x <> a && x <> b && x <> c && x <> d &&\n    y <> a && y <> b && y <> c && y <> d &&\n    x <> y &&\n\n    a.Count = 4 && b.Count = 4 && c.Count = 4 && d.Count = 4 && \n    x.Count = 4 && y.Count = 5\n\n\n    \n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Math/MathTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\n\nopen NUnit.Framework\nopen FsUnit\nopen FsCheck\nopen FsCheck.NUnit\nopen System\n\nmodule MathTests =\n\n    let equalWithin x eps = (new NUnit.Framework.Constraints.EqualConstraint(x)).Within(eps)\n    \n    type RotationTestCase2D =\n        {\n            Src: V2d\n            Dst: V2d\n            Angle: float\n        }\n    \n    module Gen =\n        let floatUnit =\n            gen {\n            let! n = Arb.generate<uint32>\n            return float n / float UInt32.MaxValue\n            }\n    \n        let direction2d =\n            gen {\n                let! t = floatUnit\n                return Rot2d(t * Constant.PiTimesTwo) * V2d.XAxis\n            }\n    \n    type Generator private () =\n        static member AngleTestCase =\n            gen {\n                let! t = Gen.floatUnit\n                let angle = (t - 0.5) * Constant.PiTimesTwo\n    \n                let! src = Gen.direction2d\n                let rot = Rot2d angle\n                let dst = rot * src\n    \n                return { Src = src; Dst = dst; Angle = angle }\n            }\n            |> Arb.fromGen\n    \n    [<Test>]\n    let ``[Math] lerp`` () =\n        // Just making sure the parameter order is correct :S\n        lerp 50uy 100uy 0.5                     |> should equal (Fun.Lerp(0.5, 50uy, 100uy))\n        lerp 50uy 100uy 0.5f                    |> should equal (Fun.Lerp(0.5f, 50uy, 100uy))\n        lerp 50y 100y 0.5                       |> should equal (Fun.Lerp(0.5, 50y, 100y))\n        lerp 50y 100y 0.5f                      |> should equal (Fun.Lerp(0.5f, 50y, 100y))\n        lerp 50us 100us 0.5                     |> should equal (Fun.Lerp(0.5, 50us, 100us))\n        lerp 50us 100us 0.5f                    |> should equal (Fun.Lerp(0.5f, 50us, 100us))\n        lerp 50s 100s 0.5                       |> should equal (Fun.Lerp(0.5, 50s, 100s))\n        lerp 50s 100s 0.5f                      |> should equal (Fun.Lerp(0.5f, 50s, 100s))\n        lerp 50 100 0.5                         |> should equal (Fun.Lerp(0.5, 50, 100))\n        lerp 50 100 0.5f                        |> should equal (Fun.Lerp(0.5f, 50, 100))\n        lerp 50u 100u 0.5                       |> should equal (Fun.Lerp(0.5, 50u, 100u))\n        lerp 50u 100u 0.5f                      |> should equal (Fun.Lerp(0.5f, 50u, 100u))\n        lerp 50UL 100UL 0.5                     |> should equal (Fun.Lerp(0.5, 50UL, 100UL))\n        lerp 50UL 100UL 0.5f                    |> should equal (Fun.Lerp(0.5f, 50UL, 100UL))\n        lerp 50L 100L 0.5                       |> should equal (Fun.Lerp(0.5, 50L, 100L))\n        lerp 50L 100L 0.5f                      |> should equal (Fun.Lerp(0.5f, 50L, 100L))\n        lerp 50.0 100.0 0.5                     |> should equal (Fun.Lerp(0.5, 50.0, 100.0))\n        lerp 50.0f 100.0f 0.5f                  |> should equal (Fun.Lerp(0.5f, 50.0f, 100.0f))\n    \n        lerp (V2i(50)) (V2i(100)) 0.5           |> should equal (Fun.Lerp(0.5, V2i(50), V2i(100)))\n        lerp (V2i(50)) (V2i(100)) 0.5f          |> should equal (Fun.Lerp(0.5f, V2i(50), V2i(100)))\n        lerp (V2i(50)) (V2i(100)) (V2d(0.5))    |> should equal (Fun.Lerp(V2d(0.5), V2i(50), V2i(100)))\n        lerp (V2i(50)) (V2i(100)) (V2f(0.5f))   |> should equal (Fun.Lerp(V2f(0.5f), V2i(50), V2i(100)))\n    \n        lerp (V2ui(50)) (V2ui(100)) 0.5         |> should equal (Fun.Lerp(0.5, V2ui(50), V2ui(100)))\n        lerp (V2ui(50)) (V2ui(100)) 0.5f        |> should equal (Fun.Lerp(0.5f, V2ui(50), V2ui(100)))\n        lerp (V2ui(50)) (V2ui(100)) (V2d(0.5))  |> should equal (Fun.Lerp(V2d(0.5), V2ui(50), V2ui(100)))\n        lerp (V2ui(50)) (V2ui(100)) (V2f(0.5f)) |> should equal (Fun.Lerp(V2f(0.5f), V2ui(50), V2ui(100)))\n    \n        lerp (V2l(50)) (V2l(100)) 0.5           |> should equal (Fun.Lerp(0.5, V2l(50), V2l(100)))\n        lerp (V2l(50)) (V2l(100)) 0.5f          |> should equal (Fun.Lerp(0.5f, V2l(50), V2l(100)))\n        lerp (V2l(50)) (V2l(100)) (V2d(0.5))    |> should equal (Fun.Lerp(V2d(0.5), V2l(50), V2l(100)))\n        lerp (V2l(50)) (V2l(100)) (V2f(0.5f))   |> should equal (Fun.Lerp(V2f(0.5f), V2l(50), V2l(100)))\n    \n        lerp (V2f(50)) (V2f(100)) 0.5f          |> should equal (Fun.Lerp(0.5f, V2f(50), V2f(100)))\n        lerp (V2f(50)) (V2f(100)) (V2f(0.5f))   |> should equal (Fun.Lerp(V2f(0.5f), V2f(50), V2f(100)))\n    \n        lerp (V2d(50)) (V2d(100)) 0.5           |> should equal (Fun.Lerp(0.5, V2d(50), V2d(100)))\n        lerp (V2d(50)) (V2d(100)) (V2d(0.5))    |> should equal (Fun.Lerp(V2d(0.5), V2d(50), V2d(100)))\n    \n        lerp (C4d(50.0)) (C4d(100.0)) 0.5       |> should equal (Fun.Lerp(0.5, C4d(50.0), C4d(100.0)))\n    \n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Math] AngleBetween 2D`` (input: RotationTestCase2D) =\n        let result = Vec.AngleBetween(input.Src, input.Dst)\n        result |> should be (equalWithin (abs input.Angle) 0.00001)\n    \n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Math] AngleBetweenFast 2D`` (input: RotationTestCase2D) =\n        let result = Vec.AngleBetweenFast(input.Src, input.Dst)\n        result |> should be (equalWithin (abs input.Angle) 0.00001)\n    \n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Math] AngleBetweenSigned 2D`` (input: RotationTestCase2D) =\n        let result = Vec.AngleBetweenSigned(input.Src, input.Dst)\n        result |> should be (equalWithin input.Angle 0.00001)\n\n    let inline isPowerOfTwo (value: 'T) =\n        let rec check i =\n            if i > 63 then false\n            else\n                if uint64 value = (1UL <<< i) then true\n                else check (i + 1)\n        check 0\n\n    let arb32 = Arb.Default.DoNotSizeInt32()\n    let arb32u = Arb.Default.DoNotSizeUInt32()\n    let arb64 = Arb.Default.DoNotSizeInt64()\n    let arb64u = Arb.Default.DoNotSizeUInt64()\n\n    [<Property>]\n    let ``[Math] IsPowerOfTwo (int32)`` () =\n        Prop.forAll arb32 (fun (DoNotSize value) ->\n            let result = value.IsPowerOfTwo()\n            let expected = value = 0 || (value > 0 && isPowerOfTwo value)\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] IsPowerOfTwo (uint32)`` () =\n        Prop.forAll arb32u (fun (DoNotSize value) ->\n            let result = value.IsPowerOfTwo()\n            let expected = value = 0u || isPowerOfTwo value\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] IsPowerOfTwo (int64)`` () =\n        Prop.forAll arb64 (fun (DoNotSize value) ->\n            let result = value.IsPowerOfTwo()\n            let expected = value = 0L || (value > 0L && isPowerOfTwo value)\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] IsPowerOfTwo (uint64)`` () =\n        Prop.forAll arb64u (fun (DoNotSize value) ->\n            let result = value.IsPowerOfTwo()\n            let expected = value = 0UL || isPowerOfTwo value\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] NextPowerOfTwo (int32)`` () =\n        Prop.forAll arb32 (fun (DoNotSize value) ->\n            let result = value.NextPowerOfTwo()\n            let expected =\n                if value <= 0 then 0\n                elif value > (1 <<< 30) then Int32.MinValue\n                elif isPowerOfTwo value then value\n                else 1 <<< (Fun.Log2Int(value) + 1)\n\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] NextPowerOfTwo (uint32)`` () =\n        Prop.forAll arb32u (fun (DoNotSize value) ->\n            let result = value.NextPowerOfTwo()\n            let expected =\n                if value = 0u || value > (1u <<< 31) then 0u\n                elif isPowerOfTwo value then value\n                else 1u <<< (Fun.Log2Int(value) + 1)\n\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] NextPowerOfTwo (int64)`` () =\n        Prop.forAll arb64 (fun (DoNotSize value) ->\n            let result = value.NextPowerOfTwo()\n            let expected =\n                if value <= 0L then 0L\n                elif value > (1L <<< 62) then Int64.MinValue\n                elif isPowerOfTwo value then value\n                else 1L <<< (Fun.Log2Int(value) + 1)\n\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] NextPowerOfTwo (uint64)`` () =\n        Prop.forAll arb64u (fun (DoNotSize value) ->\n            let result = value.NextPowerOfTwo()\n            let expected =\n                if value = 0UL || value > (1UL <<< 63) then 0UL\n                elif isPowerOfTwo value then value\n                else 1UL <<< (Fun.Log2Int(value) + 1)\n\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] PrevPowerOfTwo (int32)`` () =\n        Prop.forAll arb32 (fun (DoNotSize value) ->\n            let result = value.PrevPowerOfTwo()\n            let expected =\n                if value <= 0 then 0\n                elif isPowerOfTwo value then value\n                else 1 <<< Fun.Log2Int(value)\n\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] PrevPowerOfTwo (uint32)`` () =\n        Prop.forAll arb32u (fun (DoNotSize value) ->\n            let result = value.PrevPowerOfTwo()\n            let expected =\n                if value = 0u then 0u\n                elif isPowerOfTwo value then value\n                else 1u <<< Fun.Log2Int(value)\n\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] PrevPowerOfTwo (int64)`` () =\n        Prop.forAll arb64 (fun (DoNotSize value) ->\n            let result = value.PrevPowerOfTwo()\n            let expected =\n                if value <= 0L then 0L\n                elif isPowerOfTwo value then value\n                else 1L <<< Fun.Log2Int(value)\n\n            result |> should be (equal expected)\n        )\n\n    [<Property>]\n    let ``[Math] PrevPowerOfTwo (uint64)`` () =\n        Prop.forAll arb64u (fun (DoNotSize value) ->\n            let result = value.PrevPowerOfTwo()\n            let expected =\n                if value = 0UL then 0UL\n                elif isPowerOfTwo value then value\n                else 1UL <<< Fun.Log2Int(value)\n\n            result |> should be (equal expected)\n        )"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Math/SVDTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen System\nopen Aardvark.Base\nopen FsUnit\nopen NUnit.Framework\nopen System.Runtime.InteropServices\nopen System.Diagnostics\nopen System.Collections.Generic\n\n#nowarn \"9\"\n\nmodule ExpectoSvdTests =\n    open System\n    open Aardvark.Base\n    open Expecto\n    open FsCheck\n\n    type DataDim =\n        | Mat of rows : int * cols : int\n        | M22\n        | M23\n        | M33\n        | M34\n        | M44\n\n    type MatrixTrafo =\n        | Id \n        | FlipX\n        | FlipY \n        | Transposed\n        | RandomMask\n\n    type MatrixShape =\n        | Full\n        | Diagonal\n        | Triangular of upper : bool\n        | ProperTriangular of upper : bool\n        | CopyRows\n        | CopyCols\n        | Symmetric\n\n    type MatrixKind<'a> =\n        | Arbitrary\n        | Constant of 'a\n        | Ones     \n        | Zeros\n\n\n\n\n        \n    type MatrixChoice =\n        | RealMatrix of Matrix<float>\n        | M22 of M22d\n        | M23 of M23d\n        | M33 of M33d\n        | M34 of M34d\n        | M44 of M44d\n        \n    type MatrixChoice32 =\n        | FRealMatrix of Matrix<float32>\n        | FM22 of M22f\n        | FM23 of M23f\n        | FM33 of M33f\n        | FM34 of M34f\n        | FM44 of M44f\n\n    type WideMatrix<'a> = \n        {\n            shape : MatrixShape\n            kind : MatrixKind<'a>\n            trafo : MatrixTrafo\n            dim : DataDim\n            value : MatrixChoice\n        }    \n\n    type PrettyMatrix<'a> = \n        {\n            shape : MatrixShape\n            kind : MatrixKind<'a>\n            trafo : MatrixTrafo\n            dim : DataDim\n            value : MatrixChoice\n        }    \n\n    type WideMatrix32<'a> = \n        {\n            shape : MatrixShape\n            kind : MatrixKind<'a>\n            trafo : MatrixTrafo\n            dim : DataDim\n            value : MatrixChoice32\n        }    \n\n    type PrettyMatrix32<'a> = \n        {\n            shape : MatrixShape\n            kind : MatrixKind<'a>\n            trafo : MatrixTrafo\n            dim : DataDim\n            value : MatrixChoice32\n        }    \n\n    let lineRx = System.Text.RegularExpressions.Regex @\"(\\r\\n)|\\n\"\n\n    let indent (str : string) =\n        lineRx.Split(str) |> Array.map ((+) \"    \") |> String.concat \"\\n\"\n\n    let inline matStr (m : Matrix< ^a >) =\n        let res = \n            Array.init (int m.SX) (fun c -> Array.init (int m.SY) (fun r -> \n                let str = sprintf \"%.3f\" (float m.[c,r])\n                if str.StartsWith \"-\" then str\n                else \" \" + str\n            ))\n        let lens = res |> Array.map (fun col -> col |> Seq.map String.length |> Seq.max)\n        let pad (len : int) (s : string) =\n            if s.Length < len then s + (System.String(' ',len-s.Length))\n            else s\n\n        let padded =\n            res |> Array.mapi (fun i col -> \n                col |> Array.map (pad lens.[i])\n            )\n\n        String.concat \"\\n\" [\n            for r in 0..int m.SY-1 do\n                let mutable line = \"\"\n                for c in 0..int m.SX-1 do\n                    line <- line + \" \" + padded.[c].[r]\n                yield line.Trim()\n        ]    \n\n    let inline printMat (name : string) (m : NativeMatrix< ^a >) =\n        let res = \n            Array.init (int m.SX) (fun c -> Array.init (int m.SY) (fun r -> \n                let str = sprintf \"%.3f\" (float m.[c,r])\n                if str.StartsWith \"-\" then str\n                else \" \" + str\n            ))\n        let lens = res |> Array.map (fun col -> col |> Seq.map String.length |> Seq.max)\n        let pad (len : int) (s : string) =\n            if s.Length < len then s + (System.String(' ',len-s.Length))\n            else s\n\n        let padded =\n            res |> Array.mapi (fun i col -> \n                col |> Array.map (pad lens.[i])\n            )\n            \n        System.Console.WriteLine(\"{0}\", name)\n        for r in 0..int m.SY-1 do\n            let mutable line = \"\"\n            for c in 0..int m.SX-1 do\n                line <- line + \" \" + padded.[c].[r]\n            System.Console.WriteLine(\"    {0}\", line.Trim())\n\n\n    let createMatrix (d : DataDim) (fs : float[]) =\n        match d with\n        | DataDim.Mat(r,c) -> Matrix<float>(fs, V2l(c,r)) |> RealMatrix\n        | DataDim.M22 -> M22d(fs) |> M22\n        | DataDim.M23 -> M23d(fs) |> M23\n        | DataDim.M33 -> M33d(fs) |> M33\n        | DataDim.M34 -> M34d(fs) |> M34\n        | DataDim.M44 -> M44d(fs) |> M44\n        \n    let createZeroMatrix (d : DataDim)  =\n        match d with\n        | DataDim.Mat(r,c) -> Matrix<float>(V2l(c,r)) |> RealMatrix\n        | DataDim.M22 -> M22d() |> M22\n        | DataDim.M23 -> M23d() |> M23\n        | DataDim.M33 -> M33d() |> M33\n        | DataDim.M34 -> M34d() |> M34\n        | DataDim.M44 -> M44d() |> M44\n\n    module DataDim =\n        let getRows (d : DataDim) =\n            match d with\n            | DataDim.Mat(r,c) -> r\n            | DataDim.M22 -> 2\n            | DataDim.M23 -> 2\n            | DataDim.M33 -> 3\n            | DataDim.M34 -> 3\n            | DataDim.M44 -> 4\n            \n        let getCols (d : DataDim) =\n            match d with\n            | DataDim.Mat(r,c) -> c\n            | DataDim.M22 -> 2\n            | DataDim.M23 -> 3\n            | DataDim.M33 -> 3\n            | DataDim.M34 -> 4\n            | DataDim.M44 -> 4\n\n    module MatrixChoice =\n        let toRealMat (mat : MatrixChoice) =\n            match mat with\n            | RealMatrix mat -> mat\n            | M22 mat ->       \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float>(fs, sizes)\n            | M33 mat ->           \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float>(fs, sizes)\n            | M44 mat ->        \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float>(fs, sizes)      \n            | M23 mat ->        \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float>(fs, sizes)\n            | M34 mat ->        \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float>(fs, sizes)\n        let toRealMat32 (mat : MatrixChoice32) =\n            match mat with\n            | FRealMatrix mat -> mat\n            | FM22 mat ->       \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float32>(fs, sizes)\n            | FM33 mat ->           \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float32>(fs, sizes)   \n            | FM44 mat ->        \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float32>(fs, sizes)      \n            | FM23 mat ->        \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float32>(fs, sizes)\n            | FM34 mat ->        \n                let fs = mat.ToArray()\n                let sizes = mat.Dim.YX\n                Matrix<float32>(fs, sizes)\n            \n        let to32 (m : MatrixChoice) =\n            match m with\n            | RealMatrix mat -> FRealMatrix (mat.Map(float32))\n            | M22 mat ->\n                FM22 <| M22f( \n                    float32 mat.M00, float32 mat.M01,\n                    float32 mat.M10, float32 mat.M11\n                )\n            | M23 mat ->\n                FM23 <| M23f( \n                    float32 mat.M00, float32 mat.M01, float32 mat.M02,\n                    float32 mat.M10, float32 mat.M11, float32 mat.M12\n                )\n            | M33 mat ->\n                FM33 <| M33f( \n                    float32 mat.M00, float32 mat.M01, float32 mat.M02,\n                    float32 mat.M10, float32 mat.M11, float32 mat.M12,\n                    float32 mat.M20, float32 mat.M21, float32 mat.M22\n                )\n            | M34 mat ->\n                FM34 <| M34f( \n                    float32 mat.M00, float32 mat.M01, float32 mat.M02, float32 mat.M03,\n                    float32 mat.M10, float32 mat.M11, float32 mat.M12, float32 mat.M13,\n                    float32 mat.M20, float32 mat.M21, float32 mat.M22, float32 mat.M23\n                )\n            | M44 mat ->\n                FM44 <| M44f( \n                    float32 mat.M00, float32 mat.M01, float32 mat.M02, float32 mat.M03,\n                    float32 mat.M10, float32 mat.M11, float32 mat.M12, float32 mat.M13,\n                    float32 mat.M20, float32 mat.M21, float32 mat.M22, float32 mat.M23,\n                    float32 mat.M30, float32 mat.M31, float32 mat.M32, float32 mat.M33\n                )\n\n        let copy (m : MatrixChoice) =\n            match m with\n            | RealMatrix mat -> RealMatrix (mat.Copy())\n            | M22 mat -> M22 (mat.Copy(id))\n            | M33 mat -> M33 (mat.Copy(id))\n            | M44 mat -> M44 (mat.Copy(id))\n            | M23 mat -> M23 (mat.Copy(id)) \n            | M34 mat -> M34 (mat.Copy(id)) \n\n        let get (i : V2l) (m : MatrixChoice) =\n            match m with\n            | RealMatrix mat -> mat.[i]\n            | M22 mat -> mat.[i]\n            | M33 mat -> mat.[i]\n            | M44 mat -> mat.[i]\n            | M23 mat -> mat.[i] \n            | M34 mat -> mat.[i] \n            \n        let geti (i : int64) (m : MatrixChoice) =\n            match m with\n            | RealMatrix mat -> mat.[i]\n            | M22 mat -> mat.ToArray().[int i]\n            | M33 mat -> mat.ToArray().[int i]\n            | M44 mat -> mat.ToArray().[int i]\n            | M23 mat -> mat.ToArray().[int i] \n            | M34 mat -> mat.ToArray().[int i] \n\n        let setByCoord (f : V2l -> float) (m : MatrixChoice) =\n            match m with\n            | RealMatrix mat -> mat.SetByCoord f |> RealMatrix\n            | M22 mat ->\n                M22 <| M22d( \n                    f(V2l(0,0)), f(V2l(1,0)), \n                    f(V2l(0,1)), f(V2l(1,1))\n                )\n            | M23 mat ->\n                M23 <| M23d( \n                    f(V2l(0,0)), f(V2l(1,0)), f(V2l(2,0)), \n                    f(V2l(0,1)), f(V2l(1,1)), f(V2l(2,1))\n                )\n            | M33 mat ->\n                M33 <| M33d( \n                    f(V2l(0,0)), f(V2l(1,0)), f(V2l(2,0)), \n                    f(V2l(0,1)), f(V2l(1,1)), f(V2l(2,1)),\n                    f(V2l(0,2)), f(V2l(1,2)), f(V2l(2,2))\n                )\n            | M34 mat ->\n                M34 <| M34d( \n                    f(V2l(0,0)), f(V2l(1,0)), f(V2l(2,0)), f(V2l(3,0)),\n                    f(V2l(0,1)), f(V2l(1,1)), f(V2l(2,1)), f(V2l(3,1)),\n                    f(V2l(0,2)), f(V2l(1,2)), f(V2l(2,2)), f(V2l(3,2))\n                )\n            | M44 mat ->\n                M44 <| M44d( \n                    f(V2l(0,0)), f(V2l(1,0)), f(V2l(2,0)), f(V2l(3,0)),\n                    f(V2l(0,1)), f(V2l(1,1)), f(V2l(2,1)), f(V2l(3,1)),\n                    f(V2l(0,2)), f(V2l(1,2)), f(V2l(2,2)), f(V2l(3,2)),\n                    f(V2l(0,3)), f(V2l(1,3)), f(V2l(2,3)), f(V2l(3,3))\n                )\n                \n        let setByIndex (f : int64 -> float) (m : MatrixChoice) =\n            match m with\n            | RealMatrix mat -> mat.SetByIndex f |> RealMatrix\n            | M22 mat ->\n                M22 <| M22d( \n                    f(0L), f(1L), \n                    f(2L), f(3L)\n                )\n            | M23 mat ->\n                M23 <| M23d( \n                    f(0L), f(1L), f(2L),\n                    f(3L), f(4L), f(5L)\n                )\n            | M33 mat ->\n                M33 <| M33d( \n                    f(0L), f(1L), f(2L),\n                    f(3L), f(4L), f(5L),\n                    f(6L), f(7L), f(8L)\n                )\n            | M34 mat ->\n                M34 <| M34d( \n                    f(0L), f(1L), f(2L), f(3L), \n                    f(4L), f(5L), f(6L), f(7L), \n                    f(8L), f(9L), f(10L), f(11L)\n                )\n            | M44 mat ->\n                M44 <| M44d( \n                    f(0L), f(1L), f(2L), f(3L), \n                    f(4L), f(5L), f(6L), f(7L), \n                    f(8L), f(9L), f(10L), f(11L),\n                    f(12L), f(13L), f(14L), f(15L)\n                )\n\n        let transposed (m : MatrixChoice) =\n            match m with \n            | RealMatrix mat -> RealMatrix mat.Transposed\n            | M22 mat ->        M22 mat.Transposed\n            | M33 mat ->        M33 mat.Transposed\n            | M44 mat ->        M44 mat.Transposed\n            | M23 mat -> \n                let fs = mat.ToArray()\n                let sizes = mat.Dim\n                RealMatrix <| Matrix<float>(fs, sizes).Transposed\n            | M34 mat -> \n                let fs = mat.ToArray()\n                let sizes = mat.Dim\n                RealMatrix <| Matrix<float>(fs, sizes).Transposed\n\n    type Arbitraries () = \n\n        static let properFloat =\n            Arb.generate |> Gen.filter (fun v -> not (isNaN(v) || isInfinity(v) || abs(v) > 1E20 || abs(v) < 1E-20))\n\n        static let arrayGen (k : MatrixKind<float>) (len : int)=\n            match k with\n            | Arbitrary -> \n                Gen.arrayOfLength len properFloat\n            | Constant v -> \n                Gen.constant (Array.create len v)\n            | Ones -> \n                Gen.constant (Array.create len 1.0)\n            | Zeros -> \n                Gen.constant (Array.zeroCreate len)\n\n        static member GenerateMatrix (d : DataDim, s : MatrixShape, k : MatrixKind<float>, t : MatrixTrafo) =\n            gen {\n                let r = DataDim.getRows d\n                let c = DataDim.getCols d\n                let arrGen = arrayGen k\n                let! mat = \n                    gen {\n                        match s with\n                        | Full -> \n                            let! fs = arrGen (r*c)\n                            return createMatrix d fs\n                        | Diagonal -> \n                            let! fs = arrGen (min r c)\n                            return createZeroMatrix d \n                                    |> MatrixChoice.setByCoord (fun (c : V2l) -> if c.X = c.Y then fs.[int c.X] else 0.0 )\n                        | CopyCols -> \n                            let! fs = arrGen r\n                            return createZeroMatrix d \n                                    |> MatrixChoice.setByCoord (fun (c : V2l) -> fs.[int c.Y])    \n                        | CopyRows -> \n                            let! fs = arrGen c\n                            return createZeroMatrix d \n                                    |> MatrixChoice.setByCoord (fun (c : V2l) -> fs.[int c.X])                              \n                        | Triangular(upper) -> \n                            let ct =\n                                match r <= c, upper with \n                                | true, true -> (r*(r+1))/2 + (c-r)*r\n                                | true, false -> (r*(r+1))/2\n                                | false, true -> (c*(c+1))/2\n                                | false, false -> (c*(c+1))/2 + (r-c)*c\n\n                            let! fs = arrGen ct\n                            let mutable i = 0\n                            return \n                                createZeroMatrix d\n                                |> MatrixChoice.setByCoord(fun (c : V2l) ->\n                                    if upper then\n                                        if c.Y <= c.X then\n                                            let v = fs.[i]\n                                            i <- i+1\n                                            v\n                                        else 0.0                        \n                                    else \n                                        if c.Y >= c.X then\n                                            let v = fs.[i]\n                                            i <- i+1\n                                            v    \n                                        else 0.0                       \n                                   )\n                           \n                        | ProperTriangular(upper) -> \n                            let ct =\n                                match r <= c, upper with \n                                | true, true -> (r*  (r-1))/2+(c-r)*r\n                                | true, false -> (r* (r-1))/2\n                                | false, true -> (c* (c-1))/2\n                                | false, false -> (c*(c-1))/2+(r-c)*c\n\n                            let! fs = arrGen ct\n                            let mutable i = 0\n                            return \n                                createZeroMatrix d\n                                |> MatrixChoice.setByCoord(fun (c : V2l) ->\n                                    if upper then\n                                        if c.Y < c.X then\n                                            let v = fs.[i]\n                                            i <- i+1\n                                            v\n                                        else 0.0                        \n                                    else \n                                        if c.Y > c.X then\n                                            let v = fs.[i]\n                                            i <- i+1\n                                            v    \n                                        else 0.0                       \n                                   )\n                        | Symmetric ->\n                            let ct =\n                                match r <= c with \n                                | true -> (r*(r+1))/2+(c-r)*r\n                                | false -> (c*(c+1))/2+(r-c)*c\n                            let! arr = arrGen ct\n\n                            let mutable idx = 0\n                            let cache = Dict()\n\n                            let get (c : V2l) =\n                                let k = \n                                    if c.X < c.Y then (c.X, c.Y)\n                                    else (c.Y, c.X)\n\n                                cache.GetOrCreate(k, fun k ->\n                                    let i = idx\n                                    idx <- idx + 1\n                                    arr.[i]\n                                )\n\n                            return \n                                createZeroMatrix d\n                                |> MatrixChoice.setByCoord get                       \n                    }                   \n                let! trafoed = \n                    gen {\n                        match t with\n                        | Id -> return mat\n                        | FlipX -> \n                            let mo = mat |> MatrixChoice.copy\n                            return mat |> MatrixChoice.setByCoord(fun (p : V2l) -> mo |> MatrixChoice.get (V2l(int64 c-1L-p.X, p.Y)))\n                        | FlipY -> \n                            let mo = mat |> MatrixChoice.copy\n                            return mat |> MatrixChoice.setByCoord(fun (p : V2l) -> mo |> MatrixChoice.get (V2l(p.X, int64 r-1L-p.Y)))\n                        | Transposed ->\n                            return mat |> MatrixChoice.transposed\n                        | RandomMask ->\n                            let! mask = Gen.arrayOfLength (r*c) Arb.generate<bool>\n                            return mat |> MatrixChoice.setByIndex(fun i -> if mask.[int i] then mat |> MatrixChoice.geti i else 0.0)\n                    }\n                \n                return trafoed            \n            }\n        \n        static member MatrixKind() = \n            gen {\n                let! ctor = Gen.frequency [1, Gen.constant Arbitrary; 1, Gen.constant Ones; 1, Gen.constant Zeros; 1, Gen.constant (Constant 0.0)]      \n                match ctor with\n                | Constant _ ->\n                    let! f = properFloat\n                    return Constant f\n                | e ->\n                    return e\n            } |> Arb.fromGen\n        \n        static member Matrix() =\n            gen {\n                let! square = Gen.frequency [1, Gen.constant true; 10, Gen.constant false]      \n                let! (r : int) = Gen.choose(1,25)\n                let! (c : int) = if square then Gen.constant r else Gen.choose(1,25)\n                let! d = \n                    Gen.frequency [\n                        5, Gen.constant (DataDim.Mat(r,c))\n                        1, Gen.constant (DataDim.M22)\n                        1, Gen.constant (DataDim.M23)\n                        1, Gen.constant (DataDim.M33)\n                        1, Gen.constant (DataDim.M34)\n                        1, Gen.constant (DataDim.M44)\n                    ]\n                let! s = Arb.generate<MatrixShape>\n                let! k = Arb.generate<MatrixKind<float>>\n                let! t = Arb.generate<MatrixTrafo>\n                \n\n\n                let! value = Arbitraries.GenerateMatrix(d, s, k,t)\n                return \n                    {\n                        PrettyMatrix.shape = s\n                        PrettyMatrix.kind = k                    \n                        PrettyMatrix.trafo = t\n                        PrettyMatrix.dim = d\n                        PrettyMatrix.value = value\n                    }                \n            } |> Arb.fromGen\n\n        static member MatrixFloat() =\n            gen {\n                let! square = Gen.frequency [1, Gen.constant true; 10, Gen.constant false]      \n                let! (r : int) = Gen.choose(1,25)\n                let! (c : int) = if square then Gen.constant r else Gen.choose(1,25)\n                let! d = \n                    Gen.frequency [\n                        5, Gen.constant (DataDim.Mat(r,c))\n                        1, Gen.constant (DataDim.M22)\n                        1, Gen.constant (DataDim.M23)\n                        1, Gen.constant (DataDim.M33)\n                        1, Gen.constant (DataDim.M34)\n                        1, Gen.constant (DataDim.M44)\n                    ]\n                let! s = Arb.generate<MatrixShape>\n                let! k = Arb.generate<MatrixKind<float>>\n                let! t = Arb.generate<MatrixTrafo>\n\n                let! value = Arbitraries.GenerateMatrix(d, s, k,t)\n                let k =\n                    match k with\n                    | Zeros -> Zeros\n                    | Ones -> Ones\n                    | Constant v -> Constant (float32 v)\n                    | Arbitrary -> Arbitrary\n\n                return \n                    {\n                        PrettyMatrix32.shape = s\n                        PrettyMatrix32.kind = k                    \n                        PrettyMatrix32.trafo = t\n                        PrettyMatrix32.dim = d\n                        PrettyMatrix32.value = MatrixChoice.to32 value\n                    }                \n            } |> Arb.fromGen\n        \n        static member WideMatrix() =\n            gen {\n                let! square = Gen.frequency [1, Gen.constant true; 10, Gen.constant false]      \n                let! (r : int) = Gen.choose(1,25)\n                let! (c : int) = if square then Gen.constant r else Gen.choose(r,26)\n                let! d = \n                    Gen.frequency [\n                        5, Gen.constant (DataDim.Mat(r,c))\n                        1, Gen.constant (DataDim.M22)\n                        1, Gen.constant (DataDim.M23)\n                        1, Gen.constant (DataDim.M33)\n                        1, Gen.constant (DataDim.M34)\n                        1, Gen.constant (DataDim.M44)\n                    ]\n                let! s = Arb.generate<MatrixShape>\n                let! k = Arb.generate<MatrixKind<float>>\n                let! t = Arb.generate<MatrixTrafo> |> Gen.filter (fun trafo -> trafo <> Transposed)\n\n                let! value = Arbitraries.GenerateMatrix(d, s, k,t)\n                return \n                    {\n                        WideMatrix.shape = s\n                        WideMatrix.kind = k                    \n                        WideMatrix.trafo = t\n                        WideMatrix.dim = d\n                        WideMatrix.value = value\n                    }                \n            } |> Arb.fromGen\n\n        static member WideMatrixFloat() =\n            gen {\n                let! square = Gen.frequency [1, Gen.constant true; 10, Gen.constant false]      \n                let! (r : int) = Gen.choose(1,25)\n                let! (c : int) = if square then Gen.constant r else Gen.choose(r,26)\n                let! d = \n                    Gen.frequency [\n                        5, Gen.constant (DataDim.Mat(r,c))\n                        1, Gen.constant (DataDim.M22)\n                        1, Gen.constant (DataDim.M23)\n                        1, Gen.constant (DataDim.M33)\n                        1, Gen.constant (DataDim.M34)\n                        1, Gen.constant (DataDim.M44)\n                    ]\n                let! s = Arb.generate<MatrixShape>\n                let! k = Arb.generate<MatrixKind<float>>\n                let! t = Arb.generate<MatrixTrafo> |> Gen.filter (fun trafo -> trafo <> Transposed)\n\n\n                let! value = Arbitraries.GenerateMatrix(d, s, k,t)            \n            \n                let k =\n                    match k with\n                    | Zeros -> Zeros\n                    | Ones -> Ones\n                    | Constant v -> Constant (float32 v)\n                    | Arbitrary -> Arbitrary\n\n                return \n                    {\n                        WideMatrix32.shape = s\n                        WideMatrix32.kind = k                    \n                        WideMatrix32.trafo = t\n                        WideMatrix32.dim = d\n                        WideMatrix32.value = MatrixChoice.to32 value\n                    }                             \n            } |> Arb.fromGen\n\n    let cfg : FsCheckConfig =\n        { FsCheckConfig.defaultConfig with \n            maxTest = 10000\n            arbitrary = [ typeof<Arbitraries> ] \n        }\n\n    let epsilon = 1E-8\n    let floatEpsilon = float32 1E-1\n\n    open System.Runtime.CompilerServices\n\n    [<Extension; Sealed; AbstractClass>]\n    type MatrixProperties private() =\n\n        [<Extension>]\n        static member IsIdentity(m : Matrix<float>) =\n            let mutable maxError = 0.0\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                let v = if x = y then 1.0 else 0.0\n                let err = abs (m.[i] - v)\n                maxError <- max maxError err\n            )\n            maxError <= epsilon\n\n        [<Extension>]\n        static member IsIdentity(m : Matrix<float32>) =\n            let mutable maxError = 0.0f\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                let v = if x = y then 1.0f else 0.0f\n                let err = abs (m.[i] - v)\n                maxError <- max maxError err\n            )\n            maxError <= floatEpsilon\n\n        [<Extension>]\n        static member IsOrtho(m : Matrix<float>) =\n            m.Multiply(m.Transposed).IsIdentity()\n\n        [<Extension>]\n        static member IsOrtho(m : Matrix<float32>) =\n            m.Multiply(m.Transposed).IsIdentity()\n\n\n        [<Extension>]\n        static member IsUpperRight(m : Matrix<float>) =\n            let mutable maxError = 0.0\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                if x < y then \n                    let err = abs m.[i]\n                    maxError <- max maxError err\n            )\n            maxError <= epsilon\n\n        [<Extension>]\n        static member IsUpperRight(m : Matrix<float32>) =\n            let mutable maxError = 0.0f\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                if x < y then \n                    let err = abs m.[i]\n                    maxError <- max maxError err\n            )\n            maxError <= floatEpsilon\n    \n\n        [<Extension>]\n        static member ApproximateEquals(a : Matrix<float>, b : Matrix<float>) =\n            let err = a.InnerProduct(b,(fun a b -> abs (a-b)),0.0,max)\n            err <= epsilon \n\n        [<Extension>]\n        static member ApproximateEquals(a : Matrix<float32>, b : Matrix<float32>) =\n            let err = a.InnerProduct(b,(fun a b -> abs (a-b)),0.0f,max)\n            err <= floatEpsilon    \n\n        [<Extension>]\n        static member MaxDiff(a : Matrix<float>, b : Matrix<float>) =\n            a.InnerProduct(b,(fun a b -> abs (a-b)),0.0,max)\n        \n        [<Extension>]\n        static member IsBidiagonal(m : Matrix<float>) =\n            let mutable maxError = 0.0\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                let err = if (x = y || x = y+1L) then 0.0 else abs m.[i]\n                maxError <- max maxError err\n            )\n            maxError <= epsilon \n\n\n        [<Extension>]\n        static member IsBidiagonal(m : Matrix<float32>) =\n            let mutable maxError = 0.0f\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                let err = if (x = y || x = y+1L) then 0.0f else abs m.[i]\n                maxError <- max maxError err\n            )\n            maxError <= floatEpsilon\n\n\n        [<Extension>]\n        static member IsDiagonal(m : Matrix<float>) =\n            let mutable maxError = 0.0\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                let err = if x = y then 0.0 else abs m.[i]\n                maxError <- max maxError err\n            )\n            maxError <= epsilon \n\n\n        [<Extension>]\n        static member IsDiagonal(m : Matrix<float32>) =\n            let mutable maxError = 0.0f\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                let err = if x = y then 0.0f else abs m.[i]\n                maxError <- max maxError err\n            )\n            maxError <= floatEpsilon\n\n\n        [<Extension>]\n        static member DecreasingDiagonal(m : Matrix<float>) =\n            let mutable wrong = []\n            let mutable last = System.Double.PositiveInfinity\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                if x = y then \n                    if m.[i] > last then\n                        wrong <- (last, m.[i]) :: wrong\n                    last <- m.[i]\n            )\n            match wrong with\n            | [] -> \n                true\n            | wrong ->\n                false\n\n\n        [<Extension>]\n        static member DecreasingDiagonal(m : Matrix<float32>) =\n            let mutable wrong = []\n            let mutable last = System.Single.PositiveInfinity\n            m.ForeachXYIndex (fun (x : int64) (y : int64) (i : int64) ->\n                if x = y then \n                    if m.[i] > last then\n                        wrong <- (last, m.[i]) :: wrong\n                    last <- m.[i]\n            )\n            match wrong with\n            | [] -> \n                true\n            | wrong ->\n                false\n\n    let qr =\n        testList \"[QR64] decompose\" [\n            testPropertyWithConfig cfg \"[QR64] Q*R = M\" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat ->     \n                    let (q,r) = QR.decompose mat\n                    let res = q.Multiply(r)\n                    res.ApproximateEquals(mat)\n                | M22 mat ->      \n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < epsilon\n                | M33 mat -> \n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < epsilon\n                | M44 mat -> \n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < epsilon\n                | M23 mat -> \n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < epsilon\n                | M34 mat ->\n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < epsilon\n            )\n\n            testPropertyWithConfig cfg \"[QR64] Q*Qt = ID\" (fun (mat : PrettyMatrix<float> ) -> \n                match mat.value with\n                | RealMatrix mat ->     \n                    let (q,r) = QR.decompose mat\n                    q.IsOrtho()\n                | M22 mat ->      \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M22 q)).IsOrtho()\n                | M33 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M33 q)).IsOrtho()\n                | M44 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M44 q)).IsOrtho()\n                | M23 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M22 q)).IsOrtho()\n                | M34 mat ->\n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M33 q)).IsOrtho()\n            )\n\n            testPropertyWithConfig cfg \"[QR64] R = right upper\" (fun (mat : PrettyMatrix<float> ) -> \n                match mat.value with\n                | RealMatrix mat ->     \n                    let (q,r) = QR.decompose mat\n                    r.IsUpperRight()\n                | M22 mat ->      \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M22 r)).IsUpperRight()\n                | M33 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M33 r)).IsUpperRight()\n                | M44 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M44 r)).IsUpperRight()\n                | M23 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M23 r)).IsUpperRight()\n                | M34 mat ->\n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat (M34 r)).IsUpperRight()\n            )\n        ]    \n\n    let rq =\n        testList \"[RQ64] decompose\" [\n            testPropertyWithConfig cfg \"[RQ64] R*Q = M\" (fun (mat : WideMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat ->     \n                    let (r,q) = RQ.decompose mat\n                    let res = r.Multiply(q)\n                    res.ApproximateEquals(mat)\n                | M22 mat ->      \n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < epsilon\n                | M33 mat -> \n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < epsilon\n                | M44 mat -> \n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < epsilon\n                | M23 mat -> \n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < epsilon\n                | M34 mat ->\n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < epsilon\n            )\n\n            testPropertyWithConfig cfg \"[RQ64] Q*Qt = ID\" (fun (mat : WideMatrix<float> ) -> \n                match mat.value with\n                | RealMatrix mat ->     \n                    let (r,q) = RQ.decompose mat\n                    q.IsOrtho()\n                | M22 mat ->      \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M22 q)).IsOrtho()\n                | M33 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M33 q)).IsOrtho()\n                | M44 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M44 q)).IsOrtho()\n                | M23 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M33 q)).IsOrtho()\n                | M34 mat ->\n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M44 q)).IsOrtho()\n            )\n\n            testPropertyWithConfig cfg \"[RQ64] R = right upper\" (fun (mat : WideMatrix<float> ) -> \n                match mat.value with\n                | RealMatrix mat ->     \n                    let (r,q) = RQ.decompose mat\n                    r.IsUpperRight()\n                | M22 mat ->      \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M22 r)).IsUpperRight()\n                | M33 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M33 r)).IsUpperRight()\n                | M44 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M44 r)).IsUpperRight()\n                | M23 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M23 r)).IsUpperRight()\n                | M34 mat ->\n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat (M34 r)).IsUpperRight()\n            )\n        ]    \n\n    let qrBidiag = \n        testList \"[QR64] bidiagonalize\" [\n            testPropertyWithConfig cfg \"[QR64] U*Ut = ID \" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    u.IsOrtho()\n                | M22 mat ->      \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M22 u)).IsOrtho()\n                | M33 mat -> \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M33 u)).IsOrtho()\n                | M44 mat -> \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M44 u)).IsOrtho()\n                | M23 mat -> \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M22 u)).IsOrtho()\n                | M34 mat ->\n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M33 u)).IsOrtho()\n            )\n\n            testPropertyWithConfig cfg \"[QR64] D is bidiagonal\" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    d.IsBidiagonal()\n                | M22 mat ->      \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M22 d)).IsBidiagonal()\n                | M33 mat -> \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M33 d)).IsBidiagonal()\n                | M44 mat -> \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M44 d)).IsBidiagonal()\n                | M23 mat -> \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M23 d)).IsBidiagonal()\n                | M34 mat ->\n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M34 d)).IsBidiagonal()\n            )\n\n            testPropertyWithConfig cfg \"[QR64] V*Vt = ID\" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    vt.IsOrtho()\n                | M22 mat ->      \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M22 vt)).IsOrtho()\n                | M33 mat -> \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M33 vt)).IsOrtho()\n                | M44 mat -> \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M44 vt)).IsOrtho()\n                | M23 mat -> \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M33 vt)).IsOrtho()\n                | M34 mat ->\n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat (M44 vt)).IsOrtho()\n            )        \n\n            testPropertyWithConfig cfg \"[QR64] U*D*Vt = M\" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u.Multiply(d.Multiply(vt))\n                    res.ApproximateEquals(mat)\n                | M22 mat ->      \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat (M22 res)).ApproximateEquals(MatrixChoice.toRealMat (M22 mat))\n                | M33 mat -> \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat (M33 res)).ApproximateEquals(MatrixChoice.toRealMat (M33 mat))\n                | M44 mat -> \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat (M44 res)).ApproximateEquals(MatrixChoice.toRealMat (M44 mat))\n                | M23 mat -> \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat (M23 res)).ApproximateEquals(MatrixChoice.toRealMat (M23 mat))\n                | M34 mat ->\n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat (M34 res)).ApproximateEquals(MatrixChoice.toRealMat (M34 mat))\n            )\n        ]    \n\n    let svd = \n        testList \"[SVD64] decompose\" [\n            testPropertyWithConfig cfg \"[SVD64] U*Ut = ID \" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> u.IsOrtho())\n                    |> Option.defaultValue true\n                | M22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat (M22 u)).IsOrtho())\n                    |> Option.defaultValue true\n                | M33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat (M33 u)).IsOrtho())\n                    |> Option.defaultValue true\n                | M44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat (M44 u)).IsOrtho())\n                    |> Option.defaultValue true\n                | M23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat (M22 u)).IsOrtho())\n                    |> Option.defaultValue true\n                | M34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat (M33 u)).IsOrtho())\n                    |> Option.defaultValue true\n            )\n\n            testPropertyWithConfig cfg \"[SVD64] S is diagonal\" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> s.IsDiagonal())\n                    |> Option.defaultValue true\n                | M22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M22 s)).IsDiagonal())\n                    |> Option.defaultValue true\n                | M33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M33 s)).IsDiagonal())\n                    |> Option.defaultValue true\n                | M44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M44 s)).IsDiagonal())\n                    |> Option.defaultValue true\n                | M23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M23 s)).IsDiagonal())\n                    |> Option.defaultValue true\n                | M34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M34 s)).IsDiagonal())\n                    |> Option.defaultValue true\n            )\n        \n            testPropertyWithConfig cfg \"[SVD64] S is decreasing\" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> s.DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | M22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M22 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | M33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M33 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | M44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M44 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | M23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M23 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | M34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat (M34 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n            )\n\n            testPropertyWithConfig cfg \"[SVD64] V*Vt = ID\" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> vt.IsOrtho())\n                    |> Option.defaultValue true\n                | M22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat (M22 vt)).IsOrtho())\n                    |> Option.defaultValue true\n                | M33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat (M33 vt)).IsOrtho())\n                    |> Option.defaultValue true\n                | M44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat (M44 vt)).IsOrtho())\n                    |> Option.defaultValue true\n                | M23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat (M33 vt)).IsOrtho())\n                    |> Option.defaultValue true\n                | M34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat (M44 vt)).IsOrtho())\n                    |> Option.defaultValue true\n            )        \n\n            testPropertyWithConfig cfg \"[SVD64] U*S*Vt = M\" (fun (mat : PrettyMatrix<float>) -> \n                match mat.value with\n                | RealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u.Multiply(s.Multiply(vt)) in res.ApproximateEquals(mat))\n                    |> Option.defaultValue true\n                | M22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat (M22 res)).ApproximateEquals(MatrixChoice.toRealMat (M22 mat)))\n                    |> Option.defaultValue true\n                | M33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat (M33 res)).ApproximateEquals(MatrixChoice.toRealMat (M33 mat)))\n                    |> Option.defaultValue true\n                | M44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat (M44 res)).ApproximateEquals(MatrixChoice.toRealMat (M44 mat)))\n                    |> Option.defaultValue true\n                | M23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat (M23 res)).ApproximateEquals(MatrixChoice.toRealMat (M23 mat)))\n                    |> Option.defaultValue true\n                | M34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat (M34 res)).ApproximateEquals(MatrixChoice.toRealMat (M34 mat)))\n                    |> Option.defaultValue true\n            )\n        ]   \n  \n    let qr32 =\n        testList \"[QR32] decompose\" [\n            testPropertyWithConfig cfg \"[QR32] Q*R = M\" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat ->     \n                    let (q,r) = QR.decompose mat\n                    let res = q.Multiply(r)\n                    res.ApproximateEquals(mat)\n                | FM22 mat ->      \n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n                | FM33 mat -> \n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n                | FM44 mat -> \n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n                | FM23 mat -> \n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n                | FM34 mat ->\n                    let (q,r) = QR.decompose mat\n                    let res = q * r\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n            )\n\n            testPropertyWithConfig cfg \"[QR32] Q*Qt = ID\" (fun (mat : PrettyMatrix32<float32> ) -> \n                match mat.value with\n                | FRealMatrix mat ->     \n                    let (q,r) = QR.decompose mat\n                    q.IsOrtho()\n                | FM22 mat ->      \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM22 q)).IsOrtho()\n                | FM33 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM33 q)).IsOrtho()\n                | FM44 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM44 q)).IsOrtho()\n                | FM23 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM22 q)).IsOrtho()\n                | FM34 mat ->\n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM33 q)).IsOrtho()\n            )\n\n            testPropertyWithConfig cfg \"[QR32] R = right upper\" (fun (mat : PrettyMatrix32<float32> ) -> \n                match mat.value with\n                | FRealMatrix mat ->     \n                    let (q,r) = QR.decompose mat\n                    r.IsUpperRight()\n                | FM22 mat ->      \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM22 r)).IsUpperRight()\n                | FM33 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM33 r)).IsUpperRight()\n                | FM44 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM44 r)).IsUpperRight()\n                | FM23 mat -> \n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM23 r)).IsUpperRight()\n                | FM34 mat ->\n                    let (q,r) = QR.decompose mat\n                    (MatrixChoice.toRealMat32 (FM34 r)).IsUpperRight()\n            )\n        ]    \n\n    let rq32 =\n        testList \"[RQ32] decompose\" [\n            testPropertyWithConfig cfg \"[RQ32] R*Q = M\" (fun (mat : WideMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat ->   \n                    let (r,q) = RQ.decompose mat\n                    let res = r.Multiply(q)\n                    res.ApproximateEquals(mat)\n                | FM22 mat ->      \n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n                | FM33 mat -> \n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n                | FM44 mat -> \n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n                | FM23 mat -> \n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n                | FM34 mat ->\n                    let (r,q) = RQ.decompose mat\n                    let res = r * q\n                    Mat.DistanceMax(res,mat) < floatEpsilon\n            )\n\n            testPropertyWithConfig cfg \"[RQ32] Q*Qt = ID\" (fun (mat : WideMatrix32<float32> ) -> \n                match mat.value with\n                | FRealMatrix mat ->     \n                    let (r,q) = RQ.decompose mat\n                    q.IsOrtho()\n                | FM22 mat ->      \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM22 q)).IsOrtho()\n                | FM33 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM33 q)).IsOrtho()\n                | FM44 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM44 q)).IsOrtho()\n                | FM23 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM33 q)).IsOrtho()\n                | FM34 mat ->\n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM44 q)).IsOrtho()\n            )\n\n            testPropertyWithConfig cfg \"[RQ32] R = right upper\" (fun (mat : WideMatrix32<float32> ) -> \n                match mat.value with\n                | FRealMatrix mat ->     \n                    let (r,q) = RQ.decompose mat\n                    r.IsUpperRight()\n                | FM22 mat ->      \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM22 r)).IsUpperRight()\n                | FM33 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM33 r)).IsUpperRight()\n                | FM44 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM44 r)).IsUpperRight()\n                | FM23 mat -> \n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM23 r)).IsUpperRight()\n                | FM34 mat ->\n                    let (r,q) = RQ.decompose mat\n                    (MatrixChoice.toRealMat32 (FM34 r)).IsUpperRight()\n            )\n        ]\n\n    let qrBidiag32 = \n        testList \"[QR32] Bidiagonalize\" [\n            testPropertyWithConfig cfg \"[QR32] U*Ut = ID \" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    u.IsOrtho()\n                | FM22 mat ->      \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM22 u)).IsOrtho()\n                | FM33 mat -> \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM33 u)).IsOrtho()\n                | FM44 mat -> \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM44 u)).IsOrtho()\n                | FM23 mat -> \n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM22 u)).IsOrtho()\n                | FM34 mat ->\n                    let (u,_,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM33 u)).IsOrtho()\n            )\n\n            testPropertyWithConfig cfg \"[QR32] D is bidiagonal\" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    d.IsBidiagonal()\n                | FM22 mat ->      \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM22 d)).IsBidiagonal()\n                | FM33 mat -> \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM33 d)).IsBidiagonal()\n                | FM44 mat -> \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM44 d)).IsBidiagonal()\n                | FM23 mat -> \n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM23 d)).IsBidiagonal()\n                | FM34 mat ->\n                    let (_,d,_) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM34 d)).IsBidiagonal()\n            )\n\n            testPropertyWithConfig cfg \"[QR32] V*Vt = ID\" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    vt.IsOrtho()\n                | FM22 mat ->      \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM22 vt)).IsOrtho()\n                | FM33 mat -> \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM33 vt)).IsOrtho()\n                | FM44 mat -> \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM44 vt)).IsOrtho()\n                | FM23 mat -> \n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM33 vt)).IsOrtho()\n                | FM34 mat ->\n                    let (_,_,vt) = QR.Bidiagonalize mat\n                    (MatrixChoice.toRealMat32 (FM44 vt)).IsOrtho()\n            )        \n\n            testPropertyWithConfig cfg \"[QR32] U*D*Vt = M\" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u.Multiply(d.Multiply(vt))\n                    res.ApproximateEquals(mat)\n                | FM22 mat ->      \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat32 (FM22 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM22 mat))\n                | FM33 mat -> \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat32 (FM33 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM33 mat))\n                | FM44 mat -> \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat32 (FM44 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM44 mat))\n                | FM23 mat -> \n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat32 (FM23 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM23 mat))\n                | FM34 mat ->\n                    let (u,d,vt) = QR.Bidiagonalize mat\n                    let res = u * d * vt\n                    (MatrixChoice.toRealMat32 (FM34 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM34 mat))\n            )\n        ]   \n\n    let svd32 = \n        testList \"[SVD32] decompose\" [\n            testPropertyWithConfig cfg \"[SVD32] U*Ut = ID \" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> u.IsOrtho())\n                    |> Option.defaultValue true\n                | FM22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat32 (FM22 u)).IsOrtho())\n                    |> Option.defaultValue true\n                | FM33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat32 (FM33 u)).IsOrtho())\n                    |> Option.defaultValue true\n                | FM44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat32 (FM44 u)).IsOrtho())\n                    |> Option.defaultValue true\n                | FM23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat32 (FM22 u)).IsOrtho())\n                    |> Option.defaultValue true\n                | FM34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (u,_,_) -> (MatrixChoice.toRealMat32 (FM33 u)).IsOrtho())\n                    |> Option.defaultValue true\n            )\n\n            testPropertyWithConfig cfg \"[SVD32] S is diagonal\" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> s.IsDiagonal())\n                    |> Option.defaultValue true\n                | FM22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM22 s)).IsDiagonal())\n                    |> Option.defaultValue true\n                | FM33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM33 s)).IsDiagonal())\n                    |> Option.defaultValue true\n                | FM44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM44 s)).IsDiagonal())\n                    |> Option.defaultValue true\n                | FM23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM23 s)).IsDiagonal())\n                    |> Option.defaultValue true\n                | FM34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM34 s)).IsDiagonal())\n                    |> Option.defaultValue true\n            )\n        \n            testPropertyWithConfig cfg \"[SVD32] S is decreasing\" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> s.DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | FM22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM22 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | FM33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM33 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | FM44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM44 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | FM23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM23 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n                | FM34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (_,s,_) -> (MatrixChoice.toRealMat32 (FM34 s)).DecreasingDiagonal())\n                    |> Option.defaultValue true\n            )\n\n            testPropertyWithConfig cfg \"[SVD32] V*Vt = ID\" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> vt.IsOrtho())\n                    |> Option.defaultValue true\n                | FM22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat32 (FM22 vt)).IsOrtho())\n                    |> Option.defaultValue true\n                | FM33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat32 (FM33 vt)).IsOrtho())\n                    |> Option.defaultValue true\n                | FM44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat32 (FM44 vt)).IsOrtho())\n                    |> Option.defaultValue true\n                | FM23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat32 (FM33 vt)).IsOrtho())\n                    |> Option.defaultValue true\n                | FM34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (_,_,vt) -> (MatrixChoice.toRealMat32 (FM44 vt)).IsOrtho())\n                    |> Option.defaultValue true\n            )        \n\n            testPropertyWithConfig cfg \"[SVD32] U*S*Vt = M\" (fun (mat : PrettyMatrix32<float32>) -> \n                match mat.value with\n                | FRealMatrix mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u.Multiply(s.Multiply(vt)) in res.ApproximateEquals(mat))\n                    |> Option.defaultValue true\n                | FM22 mat ->      \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat32 (FM22 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM22 mat)))\n                    |> Option.defaultValue true\n                | FM33 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat32 (FM33 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM33 mat)))\n                    |> Option.defaultValue true\n                | FM44 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat32 (FM44 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM44 mat)))\n                    |> Option.defaultValue true\n                | FM23 mat -> \n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat32 (FM23 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM23 mat)))\n                    |> Option.defaultValue true\n                | FM34 mat ->\n                    SVD.decompose mat \n                    |> Option.map (fun (u,s,vt) -> let res = u * s * vt in (MatrixChoice.toRealMat32 (FM34 res)).ApproximateEquals(MatrixChoice.toRealMat32 (FM34 mat)))\n                    |> Option.defaultValue true\n            )\n        ]   \n\n \n    [<Tests>]\n    let all =\n        testList \"QR and SVD\" [\n            qr\n            rq\n            qrBidiag\n            svd\n            //qr32\n            //rq32\n            //qrBidiag32\n            //svd32\n        ]\n\n\n\n\nmodule SVDTests =\n    open Microsoft.FSharp.NativeInterop\n    open System.Runtime.InteropServices\n\n    let DecomposeWithArraySingle(m : M33d) =\n        let U = [| M33d() |]\n        let S = [| m |]\n        let V = [| M33d() |]\n\n        use pU = fixed U\n        let pS = fixed S\n        let pV = fixed V\n\n        let tU  = NativeMatrix<float>(NativePtr.cast pU, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tS  = NativeMatrix<float>(NativePtr.cast pS, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tVt = NativeMatrix<float>(NativePtr.cast pV, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        \n        if SVD.DecomposeInPlace(tU, tS, tVt) then \n            Some (U.[0], S.[0], V.[0])\n        else\n            None\n\n    let DecomposeWithArray(m : M33d) =\n        let tmp = [| M33d(); m; M33d() |]\n\n        use pTmp = fixed tmp\n        let pS = NativePtr.add pTmp 1\n        let pV = NativePtr.add pTmp 2\n\n        let tU  = NativeMatrix<float>(NativePtr.cast pTmp,  MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tS  = NativeMatrix<float>(NativePtr.cast pS,  MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        let tVt = NativeMatrix<float>(NativePtr.cast pV, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n        \n        if SVD.DecomposeInPlace(tU, tS, tVt) then \n            Some (tmp.[0], tmp.[1], tmp.[2])\n        else\n            None\n\n    let DecomposeWithNative(m : M33d) =\n        let pU : nativeptr<M33d> = NativePtr.alloc 3\n        let pS : nativeptr<M33d> = NativePtr.alloc 3\n        let pVt : nativeptr<M33d> = NativePtr.alloc 3\n\n        try\n            let pU1 = NativePtr.add pU 1\n            let pS1 = NativePtr.add pS 1\n            let pV1 = NativePtr.add pVt 1\n\n            let pU2 = NativePtr.add pU 2\n            let pS2 = NativePtr.add pS 2\n            let pV2 = NativePtr.add pVt 2\n\n            let nanM33d = M33d(Array.create 9 Double.NaN)\n            NativePtr.write pU nanM33d\n            NativePtr.write pS nanM33d\n            NativePtr.write pVt nanM33d\n            NativePtr.write pU2 nanM33d\n            NativePtr.write pS2 nanM33d\n            NativePtr.write pV2 nanM33d\n\n            NativePtr.write pU1 (M33d())\n            NativePtr.write pS1 m\n            NativePtr.write pV1 (M33d())\n\n            let tU  = NativeMatrix<float>(NativePtr.cast pU1, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n            let tS  = NativeMatrix<float>(NativePtr.cast pS1, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n            let tVt = NativeMatrix<float>(NativePtr.cast pV1, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n\n            let suc : bool = SVD.DecomposeInPlace(tU, tS, tVt)\n\n            let testUl = NativePtr.read (pU)\n            let testUh = NativePtr.read (pU2)\n            let testSl = NativePtr.read (pS)\n            let testSh = NativePtr.read (pS2)\n            let testVl = NativePtr.read (pVt)\n            let testVh = NativePtr.read (pV2)\n            if testUl.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testUh.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testSl.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testSh.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testVl.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testVh.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n\n            let Ures = NativePtr.read pU1\n            let Sres =  NativePtr.read pS1\n            let Vres = NativePtr.read pV1\n\n            if Ures.Elements |> Seq.exists (fun x -> x.IsNaN()) then failwith \"any NaN\"\n            if Sres.Elements |> Seq.exists (fun x -> x.IsNaN()) then failwith \"any NaN\"\n            if Vres.Elements |> Seq.exists (fun x -> x.IsNaN()) then failwith \"any NaN\"\n\n            if suc then \n                Some (Ures, Sres, Vres)\n            else\n                None\n        finally\n            NativePtr.free pU\n            NativePtr.free pS\n            NativePtr.free pVt\n\n    let DecomposeWithNativeFloat32(m : M33f) =\n        let pU : nativeptr<M33f> = NativePtr.alloc 3\n        let pS : nativeptr<M33f> = NativePtr.alloc 3\n        let pVt : nativeptr<M33f> = NativePtr.alloc 3\n\n        try\n            let pU1 = NativePtr.add pU 1\n            let pS1 = NativePtr.add pS 1\n            let pV1 = NativePtr.add pVt 1\n\n            let pU2 = NativePtr.add pU 2\n            let pS2 = NativePtr.add pS 2\n            let pV2 = NativePtr.add pVt 2\n\n            let nanM33d = M33f(Array.create 9 Single.NaN)\n            NativePtr.write pU nanM33d\n            NativePtr.write pS nanM33d\n            NativePtr.write pVt nanM33d\n            NativePtr.write pU2 nanM33d\n            NativePtr.write pS2 nanM33d\n            NativePtr.write pV2 nanM33d\n\n            NativePtr.write pU1 (M33f())\n            NativePtr.write pS1 m\n            NativePtr.write pV1 (M33f())\n\n            let tU  = NativeMatrix<float32>(NativePtr.cast pU1, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n            let tS  = NativeMatrix<float32>(NativePtr.cast pS1, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n            let tVt = NativeMatrix<float32>(NativePtr.cast pV1, MatrixInfo(0L, V2l(3,3), V2l(1, 3)))\n\n            let suc : bool = SVD.DecomposeInPlace(tU, tS, tVt)\n\n            let testUl = NativePtr.read (pU)\n            let testUh = NativePtr.read (pU2)\n            let testSl = NativePtr.read (pS)\n            let testSh = NativePtr.read (pS2)\n            let testVl = NativePtr.read (pVt)\n            let testVh = NativePtr.read (pV2)\n            if testUl.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testUh.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testSl.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testSh.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testVl.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n            if testVh.Elements |> Seq.exists (fun x -> not (x.IsNaN())) then failwith \"not NaN\"\n\n            let Ures = NativePtr.read pU1\n            let Sres =  NativePtr.read pS1\n            let Vres = NativePtr.read pV1\n\n            if Ures.Elements |> Seq.exists (fun x -> x.IsNaN()) then failwith \"any NaN\"\n            if Sres.Elements |> Seq.exists (fun x -> x.IsNaN()) then failwith \"any NaN\"\n            if Vres.Elements |> Seq.exists (fun x -> x.IsNaN()) then failwith \"any NaN\"\n                        \n            if suc then \n                Some (Ures, Sres, Vres)\n            else\n                None\n        finally\n            NativePtr.free pU\n            NativePtr.free pS\n            NativePtr.free pVt\n\n    let DecomposeWithBuilder(m : M33d) =\n        let mutable S = m\n        let mutable U = M33d()\n        let mutable Vt = M33d()\n        let mutable suc = false\n        tensor {\n            let! pS = &S\n            let! pU = &U\n            let! pVt = &Vt\n            suc <- SVD.DecomposeInPlace(pU, pS, pVt)\n        }\n        if suc then\n            Some (U, S, Vt)\n        else\n            None\n\n    [<Test>]\n    let ``[SVD] DecomposeWithArraySingle``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M33d.FromCols(rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d())\n\n            let svd = DecomposeWithArraySingle mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n    [<Test>]\n    let ``[SVD] DecomposeWithArray``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M33d.FromCols(rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d())\n\n            let svd = DecomposeWithArray mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n            \n    [<Test>]\n    let ``[SVD] DecomposeWithNative``() =\n\n        let rnd = new RandomSystem(1)\n        let iter = 100000\n        for i in 0..iter do\n            let mat = M33d.FromCols(rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d())\n\n            let svd = DecomposeWithNative mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwithf \"NONE at %d\" i\n\n    [<Test>]\n    let ``[SVD] DecomposeWithNativeFloat32``() =\n\n        let rnd = new RandomSystem(1)\n        let iter = 100000\n        for i in 0..iter do\n            let mat = M33f.FromCols(rnd.UniformV3f(), rnd.UniformV3f(), rnd.UniformV3f())\n\n            let svd = DecomposeWithNativeFloat32 mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, float32 1e-3)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwithf \"NONE at %d\" i\n\n    [<Test; Ignore(\"Builder pattern is illegal for structs\")>]\n    let ``[SVD] DecomposeWithBuilder``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M33d.FromCols(rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d())\n\n            let svd = DecomposeWithBuilder mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n    [<Test>]\n    let ``[SVD] not 0``() =\n        for i in 0..100000 do\n            let mat = new M33d(100.0 + (float)i*1e-9, 0.0, 0.0,\n                                 0.0, 0.998672148110852, 0.051516410857669677,\n                                 0.0, -0.051516410857669677, 0.998672148110852)\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> if q = M33d.Zero then\n                                    failwithf \"ALL 0 at %d\" i\n            | _ -> failwith \"NONE\"\n\n    [<Test>]\n    let ``[SVD] random M22d``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M22d.FromCols(rnd.UniformV2d(), rnd.UniformV2d())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n    \n    [<Test>]\n    let ``[SVD] random M23d``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M23d.FromCols(rnd.UniformV2d(), rnd.UniformV2d(), rnd.UniformV2d())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n\n    [<Test>]\n    let ``[SVD] random M33d``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M33d.FromCols(rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n    [<Test>]\n    let ``[SVD] random M34d``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M34d.FromCols(rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n    [<Test>]\n    let ``[SVD] random M44d``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M44d.FromCols(rnd.UniformV4d(), rnd.UniformV4d(), rnd.UniformV4d(), rnd.UniformV4d())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n    [<Test>]\n    let ``[SVD] random M22f``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M22f.FromCols(rnd.UniformV2f(), rnd.UniformV2f())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, float32 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n\n    [<Test>]\n    let ``[SVD] random M23f``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M23f.FromCols(rnd.UniformV2f(), rnd.UniformV2f(), rnd.UniformV2f())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, float32 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n\n    [<Test>]\n    let ``[SVD] random M33f``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M33f.FromCols(rnd.UniformV3f(), rnd.UniformV3f(), rnd.UniformV3f())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, float32 1e-6)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n    [<Test>]\n    let ``[SVD] random M34f``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M34f.FromCols(rnd.UniformV3f(), rnd.UniformV3f(), rnd.UniformV3f(), rnd.UniformV3f())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, float32 1e-2)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n\n    [<Test>]\n    let ``[SVD] random M44f``() =\n\n        let rnd = new RandomSystem(1)\n        for i in 0..100000 do\n            let mat = M44f.FromCols(rnd.UniformV4f(), rnd.UniformV4f(), rnd.UniformV4f(), rnd.UniformV4f())\n\n            let svd = SVD.decompose mat\n\n            match svd with\n            | Some (q, s, v) -> let test = q * s * v\n                                if not (Fun.ApproximateEquals(test, mat, float32 1e-2)) then\n                                    failwithf \"Invalid SVD at %d\" i\n            | _ -> failwith \"NONE\"\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Math/TrafoTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\n\nopen NUnit.Framework\nopen FsCheck\nopen FsCheck.NUnit\nopen Expecto\n\nmodule TrafoTests =\n\n    module private Gen =\n\n        let floatReasonable =\n            Arb.generate<float> |> Gen.filter (fun x -> x > -32000.0 && x < 32000.0)\n\n        let v4d =\n            gen {\n                let! x = floatReasonable\n                let! y = floatReasonable\n                let! z = floatReasonable\n                let! w = floatReasonable\n                return V4d(x, y, z, w)\n            }\n\n    type ProjectionTestCase =\n        { Near  : float\n          Far   : float\n          Point : V4d }\n\n    type Generator private () =\n        static member ProjectionTestCase =\n            gen {\n                let! near = Gen.floatReasonable |> Gen.filter (fun x -> x > 0.001)\n                let! far = Arb.generate<float> |> Gen.filter (fun x -> x > 0.001 && (x < 32000.0 || isPositiveInfinity x))\n                let! point = Gen.v4d\n\n                return {\n                    Near = near\n                    Far = far\n                    Point = point\n                }\n            }\n            |> Arb.fromGen\n\n    let private compareMatrix (actual : M44d) (expected : M44d) =\n        for i = 0 to 3 do\n            for j = 0 to 3 do\n                Expect.floatClose Accuracy.medium actual.[i, j] expected.[i, j] $\"Unexpected M{i}{j}\"\n\n    let private testTrafo (point : V4d) (trafo : Trafo3d) =\n        let p = trafo.Transform point\n        let r = trafo.InvTransform p\n        let d = Vec.distance point r\n        Expect.floatClose Accuracy.medium d 0.0 \"Distance between re-transformed point and original too large\"\n\n    let private testNearPlaneCorners (rightHanded : bool) (expectedDepth : float) (trafo : Trafo3d) =\n        let points = [|\n            V3d(-100, -100, if rightHanded then -1 else 1)\n            V3d(-100,  100, if rightHanded then -1 else 1)\n            V3d( 100, -100, if rightHanded then -1 else 1)\n            V3d( 100,  100, if rightHanded then -1 else 1)\n        |]\n\n        let expected = [|\n            V3d(-1.0, -1.0, expectedDepth)\n            V3d(-1.0,  1.0, expectedDepth)\n            V3d( 1.0, -1.0, expectedDepth)\n            V3d( 1.0,  1.0, expectedDepth)\n        |]\n\n        let result =\n            points |> Array.map trafo.TransformPosProj\n\n        for i = 0 to points.Length - 1 do\n            for c = 0 to 2 do\n                Expect.floatClose Accuracy.medium result.[i].[c] expected.[i].[c] $\"{Meta.VecFields.[c]}-component of point {i} does not match\"\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Trafo] Perspective projection RH`` (input : ProjectionTestCase) =\n        let trafo = Trafo3d.PerspectiveProjectionRH(70.0, 1.0, input.Near, input.Far)\n        trafo |> testTrafo input.Point\n\n    [<Test>]\n    let ``[Trafo] Perspective projection RH frustum corners`` () =\n        let trafo = Trafo3d.PerspectiveProjectionRH(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n        trafo |> testNearPlaneCorners true 0.0\n\n    [<Test>]\n    let ``[Trafo] Perspective projection RH matches M44d`` () =\n        let trafo = Trafo3d.PerspectiveProjectionRH(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n        let matrix = M44d.PerspectiveProjectionTransformRH(-100.0, 100.0, 100.0, -100.0, 1.0, 10.0)\n        compareMatrix trafo.Forward matrix\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Trafo] Perspective projection reversed RH`` (input : ProjectionTestCase) =\n        let trafo = Trafo3d.PerspectiveProjectionReversedRH(70.0, 1.0, input.Near, input.Far)\n\n        let reference =\n            let P = Trafo3d.PerspectiveProjectionRH(70.0, 1.0, input.Near, input.Far)\n            let S = Trafo3d.Scale(1.0, 1.0, -1.0)\n            let T = Trafo3d.Translation(0.0, 0.0, 1.0)\n            P * S * T\n\n        compareMatrix trafo.Forward reference.Forward\n        compareMatrix trafo.Backward reference.Backward\n        trafo |> testTrafo input.Point\n\n    [<Test>]\n    let ``[Trafo] Perspective projection reversed RH frustum corners`` () =\n        let trafo = Trafo3d.PerspectiveProjectionReversedRH(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n        trafo |> testNearPlaneCorners true 1.0\n\n    // LH variants are broken, check the frustum corners test.\n    // Didn't bother to fix, since nobody seems to use them anyway.\n\n    //[<Test>]\n    //let ``[Trafo] Perspective projection LH frustum corners`` () =\n    //    let trafo = Trafo3d.PerspectiveProjectionLH(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n    //    trafo |> testNearPlaneCorners false 0.0\n\n    //[<Test>]\n    //let ``[Trafo] Perspective projection LH matches M44d`` () =\n    //    let trafo = Trafo3d.PerspectiveProjectionLH(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n    //    let matrix = M44d.PerspectiveProjectionTransformLH(-100.0, 100.0, 100.0, -100.0, 1.0, 10.0)\n    //    compareMatrix trafo.Forward matrix\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Trafo] Perspective projection GL`` (input : ProjectionTestCase) =\n        let trafo = Trafo3d.PerspectiveProjectionGL(70.0, 1.0, input.Near, input.Far)\n        trafo |> testTrafo input.Point\n\n    [<Test>]\n    let ``[Trafo] Perspective projection GL frustum corners`` () =\n        let trafo = Trafo3d.PerspectiveProjectionGL(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n        trafo |> testNearPlaneCorners true -1.0\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Trafo] Perspective projection reversed GL`` (input : ProjectionTestCase) =\n        let trafo = Trafo3d.PerspectiveProjectionReversedGL(70.0, 1.0, input.Near, input.Far)\n\n        let reference =\n            let P = Trafo3d.PerspectiveProjectionGL(70.0, 1.0, input.Near, input.Far)\n            let S = Trafo3d.Scale(1.0, 1.0, -1.0)\n            P * S\n\n        compareMatrix trafo.Forward reference.Forward\n        compareMatrix trafo.Backward reference.Backward\n        trafo |> testTrafo input.Point\n\n    [<Test>]\n    let ``[Trafo] Perspective projection reversed GL frustum corners`` () =\n        let trafo = Trafo3d.PerspectiveProjectionReversedGL(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n        trafo |> testNearPlaneCorners true 1.0\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Trafo] Orthographic projection RH`` (input : ProjectionTestCase) =\n        let far = if isFinite input.Far then input.Far else 32000.0\n        let trafo = Trafo3d.OrthoProjectionRH(-100.0, 100.0, -100.0, 100.0, input.Near, far)\n        trafo |> testTrafo input.Point\n\n    [<Test>]\n    let ``[Trafo] Orthographic projection RH frustum corners`` () =\n        let trafo = Trafo3d.OrthoProjectionRH(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n        trafo |> testNearPlaneCorners true 0.0\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[Trafo] Orthographic projection GL`` (input : ProjectionTestCase) =\n        let far = if isFinite input.Far then input.Far else 320000.0\n        let trafo = Trafo3d.OrthoProjectionGL(-100.0, 100.0, -100.0, 100.0, input.Near, far)\n        trafo |> testTrafo input.Point\n\n    [<Test>]\n    let ``[Trafo] Orthographic projection GL frustum corners`` () =\n        let trafo = Trafo3d.OrthoProjectionGL(-100.0, 100.0, -100.0, 100.0, 1.0, 10.0)\n        trafo |> testNearPlaneCorners true -1.0"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/NativeMemory.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n#nowarn \"44\"\n\nopen System\nopen System.Runtime.InteropServices\nopen System.Diagnostics\nopen System.Threading\nopen System.Threading.Tasks\nopen Aardvark.Base\n\nopen FsUnit\nopen NUnit.Framework\n\nmodule NativeUtilitiesTests =\n\n    [<Test>]\n    let ``[NativePtr] Pin array``() =\n        let array = [| 1UL; 2UL; 3UL; 4UL; 5UL |]\n\n        array |> NativePtr.pinArr (fun ptr ->\n            ptr.[0] <- 42UL\n            ptr.[3] <- 43UL\n            ptr.[4] <- 44UL\n        )\n\n        array |> should equal [| 42UL; 2UL; 3UL; 43UL; 44UL |]\n\n    [<Test>]\n    let ``[NativePtr] Pin array with index``() =\n        let array = [| 1UL; 2UL; 3UL; 4UL; 5UL |]\n\n        (0, array) ||> NativePtr.pinArri (fun ptr -> ptr.[0] <- 42UL)\n        array |> should equal [| 42UL; 2UL; 3UL; 4UL; 5UL |]\n\n        (3, array) ||> NativePtr.pinArri (fun ptr -> ptr.[0] <- 43UL)\n        array |> should equal [| 42UL; 2UL; 3UL; 43UL; 5UL |]\n\n        (4, array) ||> NativePtr.pinArri (fun ptr -> ptr.[0] <- 44UL)\n        array |> should equal [| 42UL; 2UL; 3UL; 43UL; 44UL |]\n\nmodule MemoryManagerTests =\n    \n    let create() = new MemoryManager(16n, Marshal.AllocHGlobal, fun ptr _ -> Marshal.FreeHGlobal ptr)\n\n    type Interlocked with\n        static member Change(location : byref<int>, f : int -> int) =\n            let mutable v = location\n            let mutable res = f v\n            let mutable r = Interlocked.CompareExchange(&location, res, v)\n\n            while v <> r do\n                v <- r\n                res <- f v\n                r <- Interlocked.CompareExchange(&location, res, v)\n\n            res\n\n\n\n    [<Test>]\n    let ``[Memory] simple alloc test``() =\n        let m = create()\n\n        let b0 = m.Alloc(10n)\n        let b1 = m.Alloc(6n)\n\n        m.Validate()\n\n    [<Test>]\n    let ``[Memory] simple free test``() =\n        let m = create()\n\n        let b0 = m.Alloc(10n)\n        m.Free b0\n\n\n        let b1 = m.Alloc(16n)\n        \n        m.Validate()\n\n    [<Test>]\n    let ``[Memory] free collapse left``() =\n        let m = create()\n\n        let b0 = m.Alloc(2n)\n        let b1 = m.Alloc(2n)\n        let b2 = m.Alloc(2n)\n        m.Free b0\n        m.Free b1\n\n        \n        m.Validate()\n\n    [<Test>]\n    let ``[Memory] free collapse right``() =\n        let m = create()\n\n        let b0 = m.Alloc(2n)\n        let b1 = m.Alloc(2n)\n        let b2 = m.Alloc(2n)\n        let r = m.Alloc(10n)\n        m.Free b2\n        m.Free b1\n\n        \n        m.Validate()\n\n    [<Test>]\n    let ``[Memory] free collapse both``() =\n        let m = create()\n\n        let b0 = m.Alloc(2n)\n        let b1 = m.Alloc(2n)\n        let b2 = m.Alloc(2n)\n        let r = m.Alloc(10n)\n        m.Free b2\n        m.Free b0\n        m.Free b1\n\n        \n        m.Validate()\n\n\n    [<Test>]\n    let ``[Memory] realloc move``() =\n        let m = create()\n\n        let b0 = m.Alloc(2n)\n        let b1 = m.Alloc(2n)\n        \n        m.Realloc(b0, 4n) |> should be True\n        m.Validate()\n\n        b0.Size |> should equal 4n\n        b0.Offset |> should equal 4n\n\n\n    [<Test>]\n    let ``[Memory] realloc exact space left``() =\n        let m = create()\n\n        let b0 = m.Alloc(2n)\n        let b1 = m.Alloc(4n)\n        let b2 = m.Alloc(2n)\n        \n        m.Free(b1)\n\n        m.Realloc(b0, 6n) |> should be False\n        m.Validate()\n\n\n    [<Test>]\n    let ``[Memory] realloc more space left``() =\n        let m = create()\n\n        let b0 = m.Alloc(2n)\n        let b1 = m.Alloc(5n)\n        let b2 = m.Alloc(2n)\n        \n        m.Free(b1)\n\n        m.Realloc(b0, 6n) |> should be False\n        m.Validate()\n\n\n    [<Test>]\n    let ``[Memory] realloc shrink``() =\n        let m = create()\n\n        let b0 = m.Alloc(2n)\n        let b1 = m.Alloc(4n)\n\n        m.Realloc(b0, 1n) |> should be False\n        m.Validate()\n\n\n    [<Test>]\n    let ``[Memory] realloc 0``() =\n        let m = create()\n\n        let b0 = m.Alloc(2n)\n        let b1 = m.Alloc(4n)\n\n        m.Realloc(b0, 0n) |> should be False\n        m.Validate()\n\n        b0.Size |> should equal 0n\n\n\n    [<Test>]\n    let ``[Memory] resize``() =\n        let m = create()\n\n        let b0 = m.Alloc(10n)\n        let b1 = m.Alloc(100n)\n\n        m.Validate()\n\n\n    [<Test>]\n    let ``[Memory Performance] allocations``() =\n        let m = create()\n        let r = Random()\n\n\n        // warm-up\n        for i in 0..100 do\n            m.Free(m.Alloc(r.Next(1 <<< 5) + 1 |> nativeint))\n\n\n        let sw = Stopwatch()\n        let mutable iterations = 0\n\n        sw.Start()\n        while sw.Elapsed.TotalMilliseconds < 1000.0 do\n            m.Alloc(r.Next(1 <<< 5) + 1 |> nativeint) |> ignore\n            iterations <- iterations + 1\n\n        sw.Stop()\n        let microseconds = sw.Elapsed.TotalMilliseconds * 1000.0\n\n        Console.WriteLine(\"{0} µs/allocation\", microseconds / float iterations)\n\n    [<Test>]\n    let ``[Memory Performance] free``() =\n        let m = create()\n        let r = Random()\n\n        // warm-up\n        for i in 0..100 do\n            m.Free(m.Alloc(r.Next(1 <<< 5) + 1 |> nativeint))\n\n        let sw = Stopwatch()\n\n        let blocks = Array.init (1 <<< 17) (fun _ -> m.Alloc(r.Next(1 <<< 5) + 1 |> nativeint))\n        let blocks = blocks.RandomOrder() |> Seq.toArray\n\n        sw.Start()\n        for i in 0..blocks.Length-1 do\n            m.Free(blocks.[i])\n        sw.Stop()\n        let microseconds = sw.Elapsed.TotalMilliseconds * 1000.0\n\n        Console.WriteLine(\"{0} µs/free\", microseconds / float blocks.Length)\n\n\n    [<Test>]\n    let ``[Memory Performance] realloc no space``() =\n        let m = create()\n        let r = Random()\n\n        // warm-up\n        for i in 0..100 do\n            let b = m.Alloc(r.Next(1 <<< 5) + 1 |> nativeint)\n            m.Realloc(b, b.Size + 1n) |> ignore\n            m.Free(b)\n\n        let sw = Stopwatch()\n\n        let blocks = Array.init (1 <<< 17) (fun _ -> m.Alloc(r.Next(1 <<< 5) + 1 |> nativeint))\n        let blocks = blocks.RandomOrder() |> Seq.toArray\n\n        sw.Start()\n        for i in 0..blocks.Length-1 do\n            m.Realloc(blocks.[i], blocks.[i].Size + 1n) |> ignore\n        sw.Stop()\n        let microseconds = sw.Elapsed.TotalMilliseconds * 1000.0\n\n        Console.WriteLine(\"{0} µs/realloc (no space left)\", microseconds / float blocks.Length)\n\n\n    [<Test>]\n    let ``[Memory Performance] realloc next free``() =\n        let m = create()\n        let r = Random()\n\n        // warm-up\n        for i in 0..100 do\n            let b = m.Alloc(r.Next(1 <<< 5) + 1 |> nativeint)\n            m.Realloc(b, b.Size + 1n) |> ignore\n            m.Free(b)\n\n\n        let sw = Stopwatch()\n\n        let blocks = Array.init (1 <<< 18) (fun _ -> m.Alloc(r.Next(1 <<< 5) + 1 |> nativeint))\n        for i in 0..2..blocks.Length-1 do\n            m.Free(blocks.[i])\n\n        let blocks = blocks |> Array.mapi (fun i a -> if i % 2 <> 0 then Some a else None) \n                            |> Array.choose id\n\n        let blocks = blocks.RandomOrder() |> Seq.toArray\n\n        sw.Start()\n        for i in 0..blocks.Length-1 do\n            m.Realloc(blocks.[i], blocks.[i].Size + 1n) |> ignore\n        sw.Stop()\n        let microseconds = sw.Elapsed.TotalMilliseconds * 1000.0\n\n        Console.WriteLine(\"{0} µs/realloc (next free)\", microseconds / float blocks.Length)\n\n\n    let startTask (f : unit -> unit) =\n        Task.Factory.StartNew(f, TaskCreationOptions.LongRunning) |> ignore\n\n    let run (f : unit -> unit) =\n        f()\n\n\n    [<Test; Ignore(\"Broken. Fails sporadically\")>]\n    let ``[Memory] concurrent allocations``() =\n        let cnt = 200uy\n        let mem = MemoryManager.createHGlobal()\n\n        let r = Random()\n        let start = new ManualResetEventSlim(false)\n        let finished = new SemaphoreSlim(0)\n        let allblocks = ref Map.empty\n        let currentWrites = ref 0\n        let maxParallelWrites = ref 0\n\n        for i in 0uy..cnt - 1uy do\n            startTask (fun () ->\n                let size = r.Next 100 + 1 |> nativeint\n                start.Wait()\n\n                let b = mem |> MemoryManager.alloc size\n\n                let current = Interlocked.Increment(&currentWrites.contents)\n                Interlocked.Change(&maxParallelWrites.contents, max current) |> ignore\n                b.Write(0, Array.create (int size) i)\n                Interlocked.Decrement(&currentWrites.contents) |> ignore\n\n                \n\n                Interlocked.Change(&allblocks.contents, Map.add i b) |> ignore\n\n                finished.Release() |> ignore\n            )\n\n        start.Set()\n\n        for i in 1uy..cnt do\n            finished.Wait()\n\n        mem.Validate()\n\n        for (i,b) in Map.toSeq !allblocks do\n            let data : byte[] = b |> ManagedPtr.readArray 0 \n            data |> should equal (Array.create (int b.Size) i)\n\n        Console.WriteLine(\"parallel writes: {0}\", !maxParallelWrites)\n        allblocks.Value.Count |> should equal (int cnt)\n        !maxParallelWrites |> should greaterThan 1\n\n\n    [<Test>]\n    let ``[Memory] concurrent allocations / frees``() =\n        let cnt = 200uy\n        let mem = MemoryManager.createHGlobal()\n\n        let r = Random()\n        let start = new ManualResetEventSlim(false)\n        let finished = new SemaphoreSlim(0)\n        let allblocks = ref Map.empty\n\n\n\n        for i in 0uy..cnt - 1uy do\n            startTask (fun () ->\n                let size = r.Next 100 + 1 |> nativeint\n                start.Wait()\n\n                let b = mem |> MemoryManager.alloc size\n                b.Write(0, Array.create (int size) i)\n\n                Interlocked.Change(&allblocks.contents, Map.add i b) |> ignore\n\n                finished.Release() |> ignore\n            )\n\n        start.Set()\n\n        for i in 1uy..cnt do\n            finished.Wait()\n\n        mem.Validate()\n\n\n\n        \n        start.Reset()\n\n        for i in 0uy..cnt - 1uy do\n            startTask (fun () ->\n                let free = r.Next(1) = 0\n                let b = Map.find i !allblocks\n                start.Wait()\n\n                if free then\n                    ManagedPtr.free b\n                else\n                    b |> ManagedPtr.realloc (b.Size + 2n) |> ignore\n                    b |> ManagedPtr.writeArray (int b.Size-2) [|i;i|]\n\n                finished.Release() |> ignore\n            )\n\n        start.Set()\n\n        for i in 1uy..cnt do\n            finished.Wait()\n\n        mem.Validate()\n\n        for (i,b) in Map.toSeq !allblocks do\n            if not b.Free then\n                let data : byte[] = b |> ManagedPtr.readArray 0 \n                data |> should equal (Array.create (int b.Size) i)\n            else\n                b.Size |> should equal 0n\n\n        allblocks.Value.Count |> should equal (int cnt)\n\n\n    [<Test>]\n    let ``[Memory] concurrent random operations``() =\n        let mem = MemoryManager.createHGlobal()\n        let r = Random()\n\n        let blocks = ref []\n\n        let removeAny (s : list<managedptr>) =\n            match s with\n                | h::t -> t, Some h\n                | _ -> [], None\n\n        let add (ptr : managedptr) (l : list<managedptr>) =\n            ptr::l\n\n        let cnt = 2000\n        let exns = ref []\n        let sem = new SemaphoreSlim(0)\n\n        for i in 1..cnt do\n            startTask (fun () ->\n            \n                let op = r.Next(6)\n\n                try\n                    try\n                        match op with\n                            | 0 | 1 | 2 -> \n                                let b = mem.Alloc (r.Next(100) + 1 |> nativeint)\n                                Interlocked.Change(&blocks.contents, add b) |> ignore\n\n                            | 3 -> \n                                let b = Interlocked.Change(&blocks.contents, removeAny)\n                                match b with\n                                    | Some b -> b |> ManagedPtr.free\n                                    | None -> ()\n\n                            | 4 -> \n                                let b = Interlocked.Change(&blocks.contents, removeAny)\n                                match b with\n                                    | Some b -> \n                                        b |> ManagedPtr.realloc (r.Next(100) + 1 |> nativeint) |> ignore\n                                        if b.Size > 0n then\n                                            Interlocked.Change(&blocks.contents, add b) |> ignore\n                                    | _ -> ()\n\n                            | _ ->\n                                let b = Interlocked.Change(&blocks.contents, removeAny)\n                                match b with\n                                    | Some b -> \n                                        let newBlock = ManagedPtr.spill b\n\n                                        Interlocked.Change(&blocks.contents, add b >> add newBlock) |> ignore\n                                    | _ -> \n                                        ()\n\n                    with e ->\n                        Interlocked.Change(&exns.contents, fun l -> e::l) |> ignore\n                finally \n                    sem.Release() |> ignore\n            )\n\n        for i in 1..cnt do\n            sem.Wait()\n\n        for e in !exns do\n            Console.WriteLine(\"{0}\", e)\n\n        !exns |> should be Empty\n\n    [<Test>]\n    let ``[Memory] random operations``() =\n        let mem = MemoryManager.createHGlobal()\n        let r = Random()\n\n        let blocks = ref []\n\n        let removeAny (s : list<managedptr>) =\n            match s with\n                | h::t -> t, Some h\n                | _ -> [], None\n\n        let add (ptr : managedptr) (l : list<managedptr>) =\n            ptr::l\n\n        let cnt = 2000\n        let exns = ref []\n        let sem = new SemaphoreSlim(0)\n\n        for i in 1..cnt do\n            run (fun () ->\n            \n                let op = r.Next(6)\n\n                try\n                    try\n                        match op with\n                            | 0 | 1 | 2 -> \n                                let b = mem.Alloc (r.Next(100) + 1 |> nativeint)\n                                Interlocked.Change(&blocks.contents, add b) |> ignore\n\n                            | 3 -> \n                                let b = Interlocked.Change(&blocks.contents, removeAny)\n                                match b with\n                                    | Some b -> b |> ManagedPtr.free\n                                    | None -> ()\n\n                            | 4 -> \n                                let b = Interlocked.Change(&blocks.contents, removeAny)\n                                match b with\n                                    | Some b -> \n                                        b |> ManagedPtr.realloc (r.Next(100) + 1 |> nativeint) |> ignore\n                                        if b.Size > 0n then\n                                            Interlocked.Change(&blocks.contents, add b) |> ignore\n                                    | _ -> ()\n\n                            | _ ->\n                                let b = Interlocked.Change(&blocks.contents, removeAny)\n                                match b with\n                                    | Some b -> \n                                        let newBlock = ManagedPtr.spill b\n\n                                        Interlocked.Change(&blocks.contents, add b >> add newBlock) |> ignore\n                                    | _ -> \n                                        ()\n\n                    with e ->\n                        Interlocked.Change(&exns.contents, fun l -> e::l) |> ignore\n                finally \n                    sem.Release() |> ignore\n            )\n\n        for i in 1..cnt do\n            sem.Wait()\n\n        for e in !exns do\n            Console.WriteLine(\"{0}\", e)\n\n        !exns |> should be Empty\n\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/NullCoalesceTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\nopen System\n\nopen FsUnit\nopen NUnit.Framework\n\nmodule CoalesceTests =\n\n    [<AllowNullLiteral>]\n    type Foo() = class end\n\n    type Container<'T>(value: 'T) =\n        let mutable getterInvoked = false\n\n        member x.Value =\n            getterInvoked <- true\n            value\n\n        member x.GetterInvoked =\n            getterInvoked\n\n    [<Test>]\n    let ``[Null Coalescing] Object``() =\n        let a: Foo = null\n        let b: Foo = Foo()\n        let c: Foo = Foo()\n        let cnt = Container c\n        let lzy = lazy c\n\n        (b ||? cnt.get_Value) |> should equal b\n        cnt.GetterInvoked |> should be False\n        (a ||? cnt.get_Value) |> should equal c\n\n        (b ||? lzy) |> should equal b\n        lzy.IsValueCreated |> should be False\n        (a ||? lzy.get_Value) |> should equal c\n\n        (a ||? b) |> should equal b\n        (b ||? a) |> should equal b\n\n    [<Test>]\n    let ``[Null Coalescing] Nullable``() =\n        let a: Nullable<int> = Nullable()\n        let b: int = 1\n        let c: int = 2\n        let cnt = Container c\n        let lzy = lazy c\n\n        (Nullable b ||? cnt.get_Value) |> should equal b\n        cnt.GetterInvoked |> should be False\n        (a ||? cnt.get_Value) |> should equal c\n\n        (Nullable b ||? lzy) |> should equal b\n        lzy.IsValueCreated |> should be False\n        (a ||? lzy.get_Value) |> should equal c\n\n        (a ||? b) |> should equal b\n        (Nullable b ||? c) |> should equal b\n\n    [<Test>]\n    let ``[Null Coalescing] Option``() =\n        let a: int option = None\n        let b: int = 1\n        let c: int = 2\n        let cnt = Container c\n        let lzy = lazy c\n\n        (Some b ||? cnt.get_Value) |> should equal b\n        cnt.GetterInvoked |> should be False\n        (a ||? cnt.get_Value) |> should equal c\n\n        (Some b ||? lzy) |> should equal b\n        lzy.IsValueCreated |> should be False\n        (a ||? lzy.get_Value) |> should equal c\n\n        (a ||? b) |> should equal b\n        (Some b ||? c) |> should equal b\n\n    [<Test>]\n    let ``[Null Coalescing] Value Option``() =\n        let a: int voption = ValueNone\n        let b: int = 1\n        let c: int = 2\n        let cnt = Container c\n        let lzy = lazy c\n\n        (ValueSome b ||? cnt.get_Value) |> should equal b\n        cnt.GetterInvoked |> should be False\n        (a ||? cnt.get_Value) |> should equal c\n\n        (ValueSome b ||? lzy) |> should equal b\n        lzy.IsValueCreated |> should be False\n        (a ||? lzy.get_Value) |> should equal c\n\n        (a ||? b) |> should equal b\n        (ValueSome b ||? c) |> should equal b"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/PinnedValueTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\nopen FSharp.NativeInterop\n\nopen FsUnit\nopen NUnit.Framework\n\n#nowarn \"9\"\n\nmodule PinnedValueTests =\n\n    [<Test>]\n    let ``[PinnedValue] Single value``() =\n        use value = new PinnedValue<_>(42UL)\n\n        value.Length |> should equal 1\n        value.Pointer.[0] |> should equal 42UL\n\n        NativePtr.write value.Pointer 43UL\n        value.Pointer.[0] |> should equal 43UL\n\n    [<Test>]\n    let ``[PinnedValue] Array``() =\n        let array = [| 42UL; 43UL; 44UL |]\n        use value = new PinnedValue<_>(array)\n\n        value.Length |> should equal 3\n        value.Pointer |> NativePtr.toArray value.Length |> should equal array\n\n        NativePtr.set value.Pointer 2 256UL\n        array.[2] |> should equal 256UL\n\n    [<Test>]\n    let ``[PinnedValue] Array as obj``() =\n        let array = [| 42UL; 43UL; 44UL |]\n        use value = new PinnedValue(array :> obj)\n\n        value.Length |> should equal 3\n        value.Address |> NativePtr.ofNativeInt<uint64> |> NativePtr.toArray value.Length |> should equal array"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Program.fs",
    "content": "﻿\nmodule Program\n\n    open Aardvark.Base.FSharp.Tests\n    open Aardvark.Base\n    open ExpectoSvdTests\n    open Expecto\n    open FsCheck\n    [<EntryPoint>]\n    let main argv = \n\n        //Caches.``[Caches] BinaryCache partial backward with ResultObject``()\n        //Caches.``[Caches] BinaryCache forward``()\n        //Caches.``[Caches] BinaryCache forward with ResultObject``()\n        //SVDTests.``[SVD] DecomposeWithArrayWeirdTranspose``()\n\n        //let m =\n        //    let mat = \n        //        Arbitraries.GenerateMatrix(DataDim.M44,Symmetric,Constant -0.5,FlipX) \n        //            |> Gen.eval 0 (FsCheck.Random.StdGen(889377570, 296706039))\n        //    match mat with\n        //        | RealMatrix mat ->     \n        //            let (q,r) = QR.decompose mat\n        //            q.IsUpperRight()\n        //        | M22 mat ->      \n        //            let (q,r) = QR.decompose mat\n        //            (MatrixChoice.toRealMat (M22 q)).IsUpperRight()\n        //        | M33 mat -> \n        //            let (q,r) = QR.decompose mat\n        //            (MatrixChoice.toRealMat (M33 q)).IsUpperRight()\n        //        | M44 mat -> \n        //            let (q,r) = QR.decompose mat\n        //            let real = MatrixChoice.toRealMat (M44 q)\n        //            real.IsUpperRight()\n        //        | M23 mat -> \n        //            let (q,r) = QR.decompose mat\n        //            (MatrixChoice.toRealMat (M22 q)).IsUpperRight()\n        //        | M34 mat ->\n        //            let (q,r) = QR.decompose mat\n        //            (MatrixChoice.toRealMat (M33 q)).IsUpperRight()\n        //Log.warn \"%A\" m\n        try\n            SVDTests.``[SVD] DecomposeWithNative``()\n        with e ->\n            printfn \"%s\" (e.ToString())\n            ()\n\n        0"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/PureAgTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n#nowarn \"44\"\n\nopen System\nopen System.Reflection\nopen Aardvark.Base\nopen FsUnit\nopen NUnit.Framework\nopen Aardvark.Base.Ag\n\nmodule ``Ag Tests`` =\n\n    type F = interface end\n    type FA() =\n        interface F\n\n    type G = interface end\n    type GA() =\n        interface G\n\n    [<Rule>]\n    type FSem() =\n        member x.SimpleInh(r : Root<F>, scope : Scope) = \n            r.Child?SimpleInh <- 1\n\n        member x.SimpleSyn(a : FA, scope : Scope) : int = \n            scope?SimpleInh\n        member x.Syn(f : FA, scope : Scope) : int = \n            scope?Inh\n        member x.Inh(r : Root<F>, scope : Scope) =     \n            r.Child?Inh <- 1\n\n    [<Rule>]\n    type GSem() =\n        member x.Syn(f : GA, scope : Scope) : int  = \n            scope?Inh\n\n        member x.Inh(r : Root<G>, scope : Scope) = \n            r.Child?Inh <- 0\n\n    [<Test>]\n    let ``[Ag] simple semantic root test``() =\n        Introspection.RegisterAssembly(typeof<F>.Assembly)\n        Aardvark.Init()\n\n        let f = FA()\n\n        let resultF = f?SimpleSyn(Scope.Root)\n\n        resultF |> should equal 1\n\n    [<Test>]\n    let ``[Ag] simple multiple syntactic families``() =\n        Introspection.RegisterAssembly(typeof<F>.Assembly)\n        Aardvark.Init()\n\n        let f = FA()\n        let g = GA()\n\n        let resultF = f?Syn(Scope.Root)\n        let resultG = g?Syn(Scope.Root)\n\n        resultF |> should equal 1\n        resultG |> should equal 0\n\n\n    type I = interface end\n    type Trafo(t : ref<int>, child : I) =\n        member x.T = t\n        member x.Child = child\n        interface I\n\n    type Leaf() =\n        interface I\n\n    [<Rule>]\n    type SomeSem() =\n\n        member x.Ts(y : Root<I>, scope : Scope) =\n            y.Child?Ts <- List.empty<ref<int>>\n\n        member x.Ts(t : Trafo, scope : Scope) =\n            t.Child?Ts <- t.T :: scope?Ts\n\n        member x.T(y : I, scope : Scope) : list<ref<int>> =\n            scope?Ts\n\n        member x.T(t : Trafo, scope : Scope) =\n            obj()\n\n//        member x.T(leaf : Leaf) =\n//            ()\n\n        member x.Scope(l : Leaf, scope : Scope) : Ag.Scope  = \n            scope\n\n        member x.Scope(t : Trafo, scope : Scope) : Ag.Scope =\n            t.Child?Scope(scope)\n        \n    [<Test>]\n    let ``[Ag] same attrib inh and syn``() =\n        Introspection.RegisterAssembly(typeof<F>.Assembly)\n        Aardvark.Init()\n\n        let t = Trafo(ref 1, Trafo (ref 2, Trafo (ref 3, Leaf ())))\n\n        let s : Ag.Scope = t?Scope(Scope.Root)\n\n        let ob : obj = s.Node.GetSynthesized(\"T\", s)\n        let theT : list<ref<int>> = unbox ob\n\n        assert (theT :> obj <> null)\n        ()\n\n\n\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/SizeOfTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\nopen System.Runtime.InteropServices\n\nopen FsUnit\nopen NUnit.Framework\n\nmodule SizeOfTests =\n\n    [<Struct; StructLayout(LayoutKind.Sequential)>]\n    type MyStruct =\n        val A : bool\n        val B : bool\n        val C : char\n\n    [<Test>]\n    let ``[GetCLRSize] Primitive types``() =\n        typeof<int64>.GetCLRSize() |> should equal 8\n        typeof<bool>.GetCLRSize() |> should equal 1\n        typeof<char>.GetCLRSize() |> should equal 2\n\n    [<Test>]\n    let ``[GetCLRSize] Struct``() =\n        typeof<MyStruct>.GetCLRSize() |> should equal 4\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Tensors/PixTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\n\nopen System\nopen NUnit.Framework\nopen FsUnit\nopen FsCheck\nopen FsCheck.NUnit\nopen Expecto\n\nmodule PixTests =\n\n    type PixType =\n        | UInt8   = 0\n        | UInt16  = 1\n        | UInt32  = 2\n        | Float16 = 3\n        | Float32 = 4\n        | Float64 = 5\n\n    module private PixVolume =\n\n        [<AutoOpen>]\n        module private Generators =\n\n            let private rng = RandomSystem(1)\n\n            let private random<'T> (getValue : unit -> 'T) (format : Col.Format) (size : V3i) : PixVolume =\n                let pi = PixVolume<'T>(format, size)\n                for c in pi.ChannelArray do\n                    c.SetByIndex(ignore >> getValue) |> ignore\n                pi\n\n            let random8ui  = random<uint8> (rng.UniformInt >> uint8)\n            let random16ui = random<uint16> (rng.UniformInt >> uint16)\n            let random32ui = random<uint32> (rng.UniformInt >> uint32)\n            let random16f  = random<float16> (rng.UniformFloat >> float16)\n            let random32f  = random<float32> (rng.UniformFloat)\n            let random64f  = random<float> (rng.UniformDouble)\n\n        let random (typ : PixType) : Col.Format -> V3i -> PixVolume =\n            match typ with\n            | PixType.UInt8   -> random8ui\n            | PixType.UInt16  -> random16ui\n            | PixType.UInt32  -> random32ui\n            | PixType.Float16 -> random16f\n            | PixType.Float32 -> random32f\n            | PixType.Float64 -> random64f\n            | _ -> failwithf \"Unknown pix type %A\" typ\n\n        let toTypeAndFormat (typ : PixType) (format : Col.Format) (pv : PixVolume) : PixVolume =\n            match typ with\n            | PixType.UInt8   -> new PixVolume<uint8>(format, pv)\n            | PixType.UInt16  -> new PixVolume<uint16>(format, pv)\n            | PixType.UInt32  -> new PixVolume<uint32>(format, pv)\n            | PixType.Float16 -> new PixVolume<float16>(format, pv)\n            | PixType.Float32 -> new PixVolume<float32>(format, pv)\n            | PixType.Float64 -> new PixVolume<float>(format, pv)\n            | _ -> failwithf \"Unknown pix type %A\" typ\n\n    module private PixImage =\n\n        [<AutoOpen>]\n        module private Generators =\n\n            let private rng = RandomSystem(1)\n\n            let private random<'T> (getValue : unit -> 'T) (format : Col.Format) (size : V2i) : PixImage =\n                let pi = PixImage<'T>(format, size)\n                for c in pi.ChannelArray do\n                    c.SetByIndex(ignore >> getValue) |> ignore\n                pi\n\n            let random8ui  = random<uint8> (rng.UniformInt >> uint8)\n            let random16ui = random<uint16> (rng.UniformInt >> uint16)\n            let random32ui = random<uint32> (rng.UniformInt >> uint32)\n            let random16f  = random<float16> (rng.UniformFloat >> float16)\n            let random32f  = random<float32> (rng.UniformFloat)\n            let random64f  = random<float> (rng.UniformDouble)\n\n        let random (typ : PixType) : Col.Format -> V2i -> PixImage =\n            match typ with\n            | PixType.UInt8   -> random8ui\n            | PixType.UInt16  -> random16ui\n            | PixType.UInt32  -> random32ui\n            | PixType.Float16 -> random16f\n            | PixType.Float32 -> random32f\n            | PixType.Float64 -> random64f\n            | _ -> failwithf \"Unknown pix type %A\" typ\n\n        let toTypeAndFormat (typ : PixType) (format : Col.Format) (pi : PixImage) : PixImage =\n            match typ with\n            | PixType.UInt8   -> new PixImage<uint8>(format, pi)\n            | PixType.UInt16  -> new PixImage<uint16>(format, pi)\n            | PixType.UInt32  -> new PixImage<uint32>(format, pi)\n            | PixType.Float16 -> new PixImage<float16>(format, pi)\n            | PixType.Float32 -> new PixImage<float32>(format, pi)\n            | PixType.Float64 -> new PixImage<float>(format, pi)\n            | _ -> failwithf \"Unknown pix type %A\" typ\n\n\n    module private Gen =\n\n        let format =\n            [ Col.Format.RGBA\n              Col.Format.BGRA\n              Col.Format.RGB\n              Col.Format.BGR ]\n            |> Gen.elements\n\n        let pixType =\n            [ PixType.UInt8\n              PixType.UInt16\n              PixType.UInt32\n              PixType.Float16\n              PixType.Float32\n              PixType.Float64 ]\n            |> Gen.elements\n\n        let size =\n            gen {\n                let! w = Gen.choose (32, 143)\n                let! h = Gen.choose (32, 256)\n                let! d = Gen.choose (8, 16)\n                return V3i(w, h, d)\n            }\n\n        let scaleFactor =\n            gen {\n                let! x = Gen.choose (0, 3000)\n                let! y = Gen.choose (0, 3000)\n                return V2d(x, y) / float 3000\n            }\n\n        let filter =\n            [ ImageInterpolation.Near\n              ImageInterpolation.Linear\n              ImageInterpolation.Cubic\n              ImageInterpolation.Lanczos ]\n            |> Gen.elements\n\n    type ConversionTestCase =\n        { Size : V3i\n          Type : PixType\n          SourceFormat : Col.Format\n          TargetFormat : Col.Format }\n\n    type ScalingTestCase =\n        { Size : V2i\n          Type : PixType\n          Format : Col.Format\n          Scale : V2d\n          Filter : ImageInterpolation }\n\n    type Generator private () =\n\n        static member ConversionTestCase =\n            gen {\n                let! size = Gen.size\n                let! typ = Gen.pixType\n                let! sourceFormat = Gen.format\n\n                let! swap = Gen.elements [true; false]\n\n                let targetFormat =\n                    if swap then\n                        match sourceFormat with\n                        | Col.Format.RGBA -> Col.Format.BGRA\n                        | Col.Format.BGRA -> Col.Format.RGBA\n                        | Col.Format.RGB  -> Col.Format.BGR\n                        | Col.Format.BGR  -> Col.Format.RGB\n                        | _ -> sourceFormat\n                    else\n                        sourceFormat\n\n                return {\n                    Size = size\n                    Type = typ\n                    SourceFormat = sourceFormat\n                    TargetFormat = targetFormat\n                }\n            }\n            |> Arb.fromGen\n\n        static member ScalingTestCase =\n            gen {\n                let! size = Gen.size |> Gen.map v2i\n                let! typ = Gen.pixType\n                let! format = Gen.format\n                let! scale = Gen.scaleFactor\n                let! filter = Gen.filter\n\n                return {\n                    Size = size\n                    Type = typ\n                    Format = format\n                    Scale = scale\n                    Filter = filter\n                }\n            }\n            |> Arb.fromGen\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[PixImage] Float16 Format and Type Conversion`` (input : ConversionTestCase) =\n        let src = PixImage.random PixType.Float16 input.SourceFormat input.Size.XY\n        let tmp = src |> PixImage.toTypeAndFormat input.Type input.TargetFormat\n        let dst = tmp |> PixImage.toTypeAndFormat PixType.Float16 input.SourceFormat\n\n        let src = src.AsPixImage<float16>()\n        let dst = dst.AsPixImage<float16>()\n\n        let eps = 0.005f\n\n        for c = 0 to src.ChannelCount - 1 do\n            let src = src.GetChannel(int64 c)\n            let dst = dst.GetChannel(int64 c)\n\n            for x = 0 to input.Size.X - 1 do\n                for y = 0 to input.Size.Y - 1 do\n                    let value = float32 dst.[x, y]\n                    let expected = float32 src.[x, y]\n\n                    if not <| Fun.ApproximateEquals(value, expected, eps) then\n                        Assert.Fail(\n                            sprintf \"Float16 PixImage conversion mismatch at (%d, %d), channel %d for size=%A type=%A source=%A target=%A: expected %A, got %A (eps=%A)\"\n                                x y c input.Size input.Type input.SourceFormat input.TargetFormat expected value eps\n                        )\n\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[PixVolume] Float16 Format and Type Conversion`` (input : ConversionTestCase) =\n        let src = PixVolume.random PixType.Float16 input.SourceFormat input.Size\n        let tmp = src |> PixVolume.toTypeAndFormat input.Type input.TargetFormat\n        let dst = tmp |> PixVolume.toTypeAndFormat PixType.Float16 input.SourceFormat\n\n        let src = src.AsPixVolume<float16>()\n        let dst = dst.AsPixVolume<float16>()\n\n        let eps = 0.005\n\n        for c = 0 to src.ChannelCount - 1 do\n            let src = src.GetChannel(int64 c)\n            let dst = dst.GetChannel(int64 c)\n\n            for x = 0 to input.Size.X - 1 do\n                for y = 0 to input.Size.Y - 1 do\n                    for z = 0 to input.Size.Z - 1 do\n                        let value = float dst.[x, y, z]\n                        let expected = float src.[x, y, z]\n\n                        if not <| Fun.ApproximateEquals(value, expected, eps) then\n                            Assert.Fail(\n                                sprintf \"Float16 PixVolume conversion mismatch at (%d, %d, %d), channel %d for size=%A type=%A source=%A target=%A: expected %A, got %A (eps=%A)\"\n                                    x y z c input.Size input.Type input.SourceFormat input.TargetFormat expected value eps\n                            )\n\n\n    let computePSNR =\n        let table : Type -> (PixImage -> PixImage -> float) =\n            LookupTable.lookup [\n                typeof<uint8>,   fun src dst -> PixImage.peakSignalToNoiseRatio (src.AsPixImage<uint8>()) (dst.AsPixImage<uint8>())\n                typeof<uint16>,  fun src dst -> PixImage.peakSignalToNoiseRatio (src.AsPixImage<uint16>()) (dst.AsPixImage<uint16>())\n                typeof<uint32>,  fun src dst -> PixImage.peakSignalToNoiseRatio (src.AsPixImage<uint32>()) (dst.AsPixImage<uint32>())\n                typeof<float16>, fun src dst -> PixImage.peakSignalToNoiseRatio (src.AsPixImage<float16>()) (dst.AsPixImage<float16>())\n                typeof<float32>, fun src dst -> PixImage.peakSignalToNoiseRatio (src.AsPixImage<float32>()) (dst.AsPixImage<float32>())\n                typeof<float>,   fun src dst -> PixImage.peakSignalToNoiseRatio (src.AsPixImage<float>()) (dst.AsPixImage<float>())\n            ]\n\n        fun (src : PixImage) (dst : PixImage) ->\n            table src.PixFormat.Type src dst\n\n    [<Property(Arbitrary = [| typeof<Generator> |])>]\n    let ``[PixImage] Scaling`` (input : ScalingTestCase) =\n        let src = PixImage.random input.Type input.Format input.Size\n        let upScaled = src.ScaledPixImage(1.0 + input.Scale, input.Filter)\n        let dst = upScaled.ResizedPixImage(input.Size, input.Filter)\n\n        let psnr = computePSNR src dst\n        psnr |> should be (greaterThan 10.0)\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Tensors/TensorMathTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\n\nopen FsUnit\nopen NUnit.Framework\n\nmodule ``Tensor Math Tests`` =\n\n    let equalApprox exp = equalWithin 0.0001 exp\n\n    module Vector =\n\n        module Ref =\n\n            let inline dot (a: Vector< ^T>) (b: Vector< ^T>) =\n                a.InnerProduct(b, (*), LanguagePrimitives.GenericZero< ^T>, (+))\n\n        let inline approxEqual (a: Vector<'T>) (b: Vector<'T>) =\n            if a.S <> b.S then\n                invalidArg \"size\" \"Mismatching size\"\n\n            a.ForeachIndex(b.Info, fun i1 i2 ->\n                a.Data.[int i1] |> should equalApprox b.Data.[int i2]\n            )\n\n    module Matrix =\n\n        module Ref =\n\n            let map2 (f: 'T1 -> 'T2 -> 'T3) (a: Matrix<'T1>) (b: Matrix<'T2>) =\n                if a.S <> b.S then\n                    invalidArg \"size\" \"Size mismatch\"\n\n                let c = Array.zeroCreate a.Data.Length\n                a.ForeachIndex(b.Info, fun i1 i2 ->\n                    c.[int i1] <- f a.Data.[int i1] b.Data.[int i2]\n                )\n                Matrix<'T3>(c, a.Origin, a.S, a.D, a.F)\n\n        let inline approxEqual (a: Matrix<'T>) (b: Matrix<'T>) =\n            if a.S <> b.S then\n                invalidArg \"size\" \"Mismatching size\"\n\n            a.ForeachIndex(b.Info, fun i1 i2 ->\n                a.Data.[int i1] |> should equalApprox b.Data.[int i2]\n            )\n\n    let iterations = 100\n    let oldImpl = false\n\n    [<SetUp>]\n    let setup() =\n        TensorGeneration.init 0\n\n    [<Theory>]\n    let ``[Vector] Dot product`` (tensor: TensorKind) =\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.DotProduct(b) else Vector.dot a b\n            r |> should equalApprox (Vector.Ref.dot a b)\n\n    [<Theory>]\n    let ``[Vector] Norm2 squared`` (tensor: TensorKind) =\n        let inline ref (v: Vector< ^T>) =\n            v.Norm(sqr, LanguagePrimitives.GenericZero< ^T>, (+))\n\n        for _ = 1 to iterations do\n            let v = TensorGeneration.getVector tensor\n            let r = if oldImpl then v.NormSquared() else Vector.lengthSquared v\n            r |> should equalApprox (ref v)\n\n    [<Theory>]\n    let ``[Vector] Dist1`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: Vector< ^T>) =\n            a.InnerProduct(b, (fun x y -> abs (x - y)), LanguagePrimitives.GenericZero< ^T>, (+))\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.Dist1(b) else Vector.distance1 a b\n            r |> should equalApprox (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Dist2`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: Vector< ^T>) =\n            sqrt <| a.InnerProduct(b, (fun x y -> sqr (x - y)), LanguagePrimitives.GenericZero< ^T>, (+))\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.Dist2(b) else Vector.distance a b\n            r |> should equalApprox (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Dist2 squared`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: Vector< ^T>) =\n            a.InnerProduct(b, (fun x y -> sqr (x - y)), LanguagePrimitives.GenericZero< ^T>, (+))\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.Dist2Squared(b) else Vector.distanceSquared a b\n            r |> should equalApprox (ref a b)\n\n    [<Theory>]\n    let ``[Vector] DistMax`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: Vector< ^T>) =\n            a.InnerProduct(b, (fun x y -> abs (x - y)), LanguagePrimitives.GenericZero< ^T>, max)\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.DistMax(b) else Vector.distanceMax a b\n            r |> should equalApprox (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Multiply`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: Vector< ^T>) =\n            let a = Array.ofSeq a.Elements\n            let b = Array.ofSeq b.Elements\n            (a, b) ||> Array.map2 (*) |> Vector.Create\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.Multiply(b) else Vector.multiply a b\n            Vector.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Multiply transposed`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: Vector< ^T>) =\n            let a = Array.ofSeq a.Elements\n            let b = Array.ofSeq b.Elements\n            let r = Array.zeroCreate (a.Length * b.Length)\n\n            let mutable i = 0\n            for y = 0 to a.Length - 1 do\n                for x = 0 to b.Length - 1 do\n                    r.[i] <- a.[y] * b.[x]\n                    inc &i\n\n            Matrix.Create(r, b.Length, a.Length)\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.MultiplyTransposed(b) else Vector.multiplyTransposed a b\n            Matrix.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Multiply scalar`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: ^T) =\n            a.Elements |> Array.ofSeq |> Array.map ((*) b) |> Vector.Create\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.rnd.UniformDouble() * 100.0\n            let r = if oldImpl then a.Multiply(b) else Vector.map ((*) b) a\n            Vector.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Subtract`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: Vector< ^T>) =\n            let a = Array.ofSeq a.Elements\n            let b = Array.ofSeq b.Elements\n            (a, b) ||> Array.map2 (-) |> Vector.Create\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.Subtract(b) else Vector.subtract a b\n            Vector.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Subtract scalar`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: ^T) =\n            a.Elements |> Array.ofSeq |> Array.map (fun x -> x - b) |> Vector.Create\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.rnd.UniformDouble() * 100.0\n            let r = if oldImpl then a.Subtract(b) else Vector.map (fun a -> a - b) a\n            Vector.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Add`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: Vector< ^T>) =\n            let a = Array.ofSeq a.Elements\n            let b = Array.ofSeq b.Elements\n            (a, b) ||> Array.map2 (+) |> Vector.Create\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.getVectorOfSize tensor a.Size\n            let r = if oldImpl then a.Add(b) else Vector.add a b\n            Vector.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Vector] Add scalar`` (tensor: TensorKind) =\n        let inline ref (a: Vector< ^T>) (b: ^T) =\n            a.Elements |> Array.ofSeq |> Array.map ((+) b) |> Vector.Create\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getVector tensor\n            let b = TensorGeneration.rnd.UniformDouble() * 100.0\n            let r = if oldImpl then a.Add(b) else Vector.map ((+) b) a\n            Vector.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Matrix] Transform`` (tensor: TensorKind) (rowMajor: bool) =\n        let inline ref (a: Matrix< ^T>) (b: Vector< ^T>) =\n            if a.SX <> b.S then\n                invalidArg \"size\" \"Size mismatch\"\n\n            Array.init (int a.SY) (fun i ->\n                Vector.Ref.dot (a.Row (a.FY + int64 i)) b\n            )\n            |> Vector.Create\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getMatrix tensor rowMajor\n            let b = TensorGeneration.getVectorOfSize tensor a.SX\n            let r = if oldImpl then a.Multiply(b) else Matrix.transform a b\n            Vector.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Matrix] Multiply`` (tensor: TensorKind) (rowMajorLeft: bool) (rowMajorRight: bool) =\n        let inline ref (a: Matrix< ^T>) (b: Matrix< ^T>) =\n            if a.SX <> b.SY then\n                invalidArg \"size\" \"Size mismatch\"\n\n            let r = Array.zeroCreate (int (b.SX * a.SY))\n            for y = 0 to int a.SY - 1 do\n                for x = 0 to int b.SX - 1 do\n                    r.[y * int b.SX + x] <- Vector.Ref.dot (a.Row(a.FY + int64 y)) (b.Col(b.FX + int64 x))\n\n            Matrix(r, V2l(b.SX, a.SY))\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getMatrix tensor rowMajorLeft\n            let b = TensorGeneration.getMatrixOfHeight tensor rowMajorRight a.SX\n            let r = if oldImpl then a.Multiply(b) else Matrix.multiply a b\n            Matrix.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Matrix] Subtract`` (tensor: TensorKind) (rowMajorLeft: bool) (rowMajorRight: bool) =\n        let inline ref (a: Matrix< ^T>) (b: Matrix< ^T>) =\n            Matrix.Ref.map2 (-) a b\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getMatrix tensor rowMajorLeft\n            let b = TensorGeneration.getMatrixOfSize tensor rowMajorRight a.S\n            let r = if oldImpl then a.Subtract(b) else Matrix.subtract a b\n            Matrix.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Matrix] Subtract scalar`` (tensor: TensorKind) (rowMajor: bool) =\n        let inline ref (a: Matrix< ^T>) (b: ^T) =\n            a.Map(fun x -> x - b)\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getMatrix tensor rowMajor\n            let b = TensorGeneration.rnd.UniformDouble() * 100.0\n            let r = if oldImpl then a.Subtract(b) else Matrix.map (fun a -> a - b) a\n            Matrix.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Matrix] Add`` (tensor: TensorKind) (rowMajorLeft: bool) (rowMajorRight: bool) =\n        let inline ref (a: Matrix< ^T>) (b: Matrix< ^T>) =\n            Matrix.Ref.map2 (+) a b\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getMatrix tensor rowMajorLeft\n            let b = TensorGeneration.getMatrixOfSize tensor rowMajorRight a.S\n            let r = if oldImpl then a.Add(b) else Matrix.add a b\n            Matrix.approxEqual r (ref a b)\n\n    [<Theory>]\n    let ``[Matrix] Add scalar`` (tensor: TensorKind) (rowMajor: bool) =\n        let inline ref (a: Matrix< ^T>) (b: ^T) =\n            a.Map((+) b)\n\n        for _ = 1 to iterations do\n            let a = TensorGeneration.getMatrix tensor rowMajor\n            let b = TensorGeneration.rnd.UniformDouble() * 100.0\n            let r = if oldImpl then a.Add(b) else Matrix.map ((+) b) a\n            Matrix.approxEqual r (ref a b)"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/Tensors/TensorTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen Aardvark.Base\n\nopen FsUnit\nopen NUnit.Framework\nopen Microsoft.FSharp.NativeInterop\nopen Operators.Checked\n\n#nowarn \"9\"\n\ntype TensorKind =\n    | Full = 0\n    | Sub = 1\n    | Window = 2\n\nmodule TensorGeneration =\n\n    let mutable rnd = Unchecked.defaultof<RandomSystem>\n\n    let init (seed: int) =\n        rnd <- RandomSystem seed\n\n    let inline getVectorOfSize' (f: RandomSystem -> int -> 'T) (t: TensorKind) (n: ^Int) =\n        let n = int n\n\n        match t with\n        | TensorKind.Full ->\n            Vector.Create <| Array.init n (f rnd)\n\n        | TensorKind.Sub ->\n            let d = 1 + rnd.UniformInt 4\n            let arr = Array.init (n * d + 4) (f rnd)\n            let f = rnd.UniformInt (arr.Length - (n - 1) * d)\n            Vector.Create(arr).SubVector(f, n, d)\n\n        | _ ->\n            let d = 1 + rnd.UniformInt 4\n            let arr = Array.init ((n + 1) * d) (f rnd)\n            let f = rnd.UniformInt ((arr.Length - (n - 1) * d) / d)\n            Vector.Create(arr).SubVectorWindow(f, n, d)\n\n    let getVector' (f: RandomSystem -> int -> 'T) (t: TensorKind) =\n        getVectorOfSize' f t (32 + rnd.UniformInt 128)\n\n    let inline getMatrixOfSize' (f: RandomSystem -> int -> 'T) (t: TensorKind) (rowMajor: bool) (s: 'v2i) =\n        let s = v2i s\n\n        match t with\n        | TensorKind.Full ->\n            let arr = Array.init (s.X * s.Y) (f rnd)\n            let d =\n                if rowMajor then V2i(1, s.X)\n                else V2i(s.Y, 1)\n\n            Matrix(arr, 0L, V2l s, V2l d)\n\n        | TensorKind.Sub ->\n            let d = 1 + rnd.UniformV2i 4\n            let S = s * d + 4\n            let arr = Array.init (S.X * S.Y) (f rnd)\n\n            let d =\n                if rowMajor then V2i(d.X, d.Y * S.X)\n                else V2i(d.X * S.Y, d.Y)\n\n            let n = 1 + Vec.dot (s - 1) d\n            let o = arr.Length - n\n            let f = V2i(o % S.X, o / S.X)\n\n            Matrix(arr, S).SubMatrix(f, s, d)\n\n        | _ ->\n            let d = 1 + rnd.UniformV2i 4\n            let S = (s + 1) * d\n            let arr = Array.init (S.X * S.Y) (f rnd)\n            let f = rnd.UniformV2i ((S - (s - 1) * d) / d)\n\n            let d =\n                if rowMajor then V2i(d.X, d.Y * S.X)\n                else V2i(d.X * S.Y, d.Y)\n\n            Matrix(arr, S).SubMatrixWindow(f, s, d)\n\n    let getMatrix' (f: RandomSystem -> int -> 'T) (t: TensorKind) (rowMajor: bool) =\n        getMatrixOfSize' f t rowMajor (16 + rnd.UniformV2i 64)\n\n    let inline getMatrixOfHeight' (f: RandomSystem -> int -> 'T) (t: TensorKind) (rowMajor: bool) (h: ^Int) =\n        getMatrixOfSize' f t rowMajor (V2i(16 + rnd.UniformInt 64, int h))\n\n    let inline getTensor4OfSize' (f: RandomSystem -> int -> 'T) (t: TensorKind) (innerW: bool) (s: ^V4i) =\n        let s = v4i s\n\n        match t with\n        | TensorKind.Full ->\n            let arr = Array.init (s.X * s.Y * s.Z * s.W) (f rnd)\n\n            let d =\n                if innerW then V4i(s.W, s.W * s.X, s.W * s.X * s.Y, 1)\n                else V4i(1, s.X, s.X * s.Y, s.X * s.Y * s.Z)\n\n            Tensor4<'T>(arr, 0L, V4l s, V4l d)\n\n        | TensorKind.Sub ->\n            let d = 1 + rnd.UniformV4i 4\n            let S = s * d + 4\n            let arr = Array.init (S.X * S.Y * S.Z * S.W) (f rnd)\n\n            let d =\n                if innerW then d * V4i(S.W, S.W * S.X, S.W * S.X * S.Y, 1)\n                else d * V4i(1, S.X, S.X * S.Y, S.X * S.Y * S.Z)\n\n            let n = 1 + Vec.dot (s - 1) d\n            let o = arr.Length - n\n            let f = V4i(o % S.X, (o / S.X) % S.Y, (o / (S.X * S.Y)) % S.Z, o / (S.X * S.Y * S.Z))\n\n            Tensor4<'T>(arr, S).SubTensor4(f, s, d)\n\n        | _ ->\n            let d = 1 + rnd.UniformV4i 3\n            let S = (s + 1) * d\n            let arr = Array.init (S.X * S.Y * S.Z * S.W) (f rnd)\n            let f = rnd.UniformV4i ((S - (s - 1) * d) / d)\n\n            let d =\n                if innerW then d * V4i(S.W, S.W * S.X, S.W * S.X * S.Y, 1)\n                else d * V4i(1, S.X, S.X * S.Y, S.X * S.Y * S.Z)\n\n            Tensor4<'T>(arr, S).SubTensor4Window(f, s, d)\n\n    let getTensor4' (f: RandomSystem -> int -> 'T) (t: TensorKind) (innerW: bool) =\n        getTensor4OfSize' f t innerW (4 + rnd.UniformV4i 4)\n\n    let inline getVectorOfSize (t: TensorKind) (n: ^Int) = getVectorOfSize' (fun rnd _ -> rnd.UniformDouble()) t n\n    let inline getVector (t: TensorKind) = getVector' (fun rnd _ -> rnd.UniformDouble()) t\n    let inline getMatrixOfSize (t: TensorKind) (rowMajor: bool) (s: 'v2i) = getMatrixOfSize' (fun rnd _ -> rnd.UniformDouble()) t rowMajor s\n    let inline getMatrix (t: TensorKind) (rowMajor: bool) = getMatrix' (fun rnd _ -> rnd.UniformDouble()) t rowMajor\n    let inline getMatrixOfHeight (t: TensorKind) (rowMajor: bool) (h: ^Int) = getMatrixOfHeight' (fun rnd _ -> rnd.UniformDouble()) t rowMajor h\n    let inline getTensor4OfSize (t: TensorKind) (innerW: bool) (s: ^V4i) = getTensor4OfSize' (fun rnd _ -> rnd.UniformDouble()) t innerW s\n    let inline getTensor4 (t: TensorKind) (innerW: bool) = getTensor4' (fun rnd _ -> rnd.UniformDouble()) t innerW\n\n    let inline getIntVectorOfSize (t: TensorKind) (n: ^Int) =\n        let offset = rnd.UniformInt 128\n        getVectorOfSize' (fun _ -> id >> (+) offset) t n\n\n    let inline getIntVector (t: TensorKind) =\n        let offset = rnd.UniformInt 128\n        getVector' (fun _ -> id >> (+) offset) t\n\n    let inline getIntMatrixOfSize (t: TensorKind) (rowMajor: bool) (s: 'v2i) =\n        let offset = rnd.UniformInt 128\n        getMatrixOfSize' (fun _ -> id >> (+) offset) t rowMajor s\n\n    let inline getIntMatrix (t: TensorKind) (rowMajor: bool) =\n        let offset = rnd.UniformInt 128\n        getMatrix' (fun _ -> id >> (+) offset) t rowMajor\n\n    let inline getIntMatrixOfHeight (t: TensorKind) (rowMajor: bool) (h: ^Int) =\n        let offset = rnd.UniformInt 128\n        getMatrixOfHeight' (fun _ -> id >> (+) offset) t rowMajor h\n\n    let inline getIntTensor4OfSize (t: TensorKind) (innerW: bool) (s: ^V4i) =\n        let offset = rnd.UniformInt 128\n        getTensor4OfSize' (fun _ -> id >> (+) offset) t innerW s\n\n    let inline getIntTensor4 (t: TensorKind) (innerW: bool) =\n        let offset = rnd.UniformInt 128\n        getTensor4' (fun _ -> id >> (+) offset) t innerW\n\nmodule ``Tensor Tests`` =\n\n    module private PixImage =\n\n        let rng = RandomSystem(1)\n\n        let random (size : V2i) =\n            let pi = PixImage<uint8>(Col.Format.RGBA, size)\n            for c in pi.ChannelArray do\n                c.SetByIndex(ignore >> rng.UniformUInt >> uint8) |> ignore\n            pi\n\n    [<Test>]\n    [<TestCase(2)>]\n    [<TestCase(4)>]\n    [<TestCase(16)>]\n    [<TestCase(123)>]\n    [<Ignore(\"Not an easy fix...\")>]\n    let ``[NativeTensor] PixImage copy mirrored as NativeTensor4``(size : int) =\n\n        let size = V2i size\n        let src = PixImage.random <| V2i size\n        let dst = PixImage<uint8>(Col.Format.RGBA, size)\n\n        PixImage.pin2 src dst (fun srcVolume dstVolume ->\n            let srcTensor = srcVolume.MirrorY().ToXYWTensor4()\n            let dstTensor = dstVolume.ToXYWTensor4()\n            NativeTensor4.copy srcTensor dstTensor\n        )\n\n        let srcMatrix = src.GetMatrix<C4b>()\n        let dstMatrix = dst.GetMatrix<C4b>()\n\n        for x = 0 to size.X - 1 do\n            for y = 0 to size.Y - 1 do\n                dstMatrix.[x, y] |> should equal srcMatrix.[x, size.Y - 1 - y]\n\n    [<Test>]\n    let ``[NativeTensor] iterPtr with non-byte elements``() =\n        let data = [| 42; 32; 108; -34 |]\n        let info = Tensor4Info(V4l(2, 2, 1, 1), V4l(1, 2, 4, 4))\n\n        data |> NativePtr.pinArr (fun ptr ->\n            let nv = NativeTensor4<int>(ptr, info)\n\n            let mutable index = 0\n            nv |> NativeTensor4.iterPtr (fun coord ptr ->\n                let value = NativePtr.read ptr\n                value |> should equal data.[index]\n                index <- index + 1\n            )\n        )\n\n    [<Test>]\n    let ``[NativeTensor] iterPtr2 with different element types``() =\n        let srcArray = [| 42; 32; 108; -34 |]\n        let dstArray = [| 0L; 0L; 0L; 0L |]\n        let info = Tensor4Info(V4l(2, 2, 1, 1), V4l(2, 1, 4, 4))\n\n        srcArray |> NativePtr.pinArr (fun srcPtr ->\n            dstArray |> NativePtr.pinArr (fun dstPtr ->\n                let src = NativeTensor4<int>(srcPtr, info)\n                let dst = NativeTensor4<int64>(dstPtr, info)\n\n                (src, dst) ||> NativeTensor4.iterPtr2 (fun coord src dst ->\n                    let value = NativePtr.read src\n                    value |> int64 |> NativePtr.write dst\n\n                    value |> should equal srcArray.[int <| coord.X * info.DX + coord.Y * info.DY]\n                )\n            )\n        )\n\n        (srcArray, dstArray) ||> Array.iter2 (fun a b ->\n            (int64 a) |> should equal b\n        )\n\n    [<Test>]\n    let ``[NativeTensor] copy untyped PixImage``() =\n        let size = V2i(123, 321)\n        let src = PixImage.random <| V2i size\n        let dst = PixImage<uint32>(Col.Format.RGBA, size)\n\n        PixImage.pin dst (fun dst ->\n            let info =\n                let info = dst.MirrorY().Info\n                VolumeInfo(info.Origin * 4L, info.Size, info.Delta * 4L)\n            src |> PixImage.copyToNative dst.Address info\n        )\n\n        for y = 0 to size.Y - 1 do\n            for x = 0 to size.X - 1 do\n                for c in 0L .. 3L do\n                    dst.GetChannel(c).[x, y] |> should equal (uint32 <| src.GetChannel(c).[x, size.Y - 1 - y])\n\n    [<SetUp>]\n    let setup() =\n        TensorGeneration.init 0\n\n    [<Theory>]\n    let ``[Vector] Iter`` (tensor: TensorKind) =\n        for _ = 1 to 100 do\n            let m = TensorGeneration.getIntVector tensor\n\n            let e = m.Elements |> HashSet.ofSeq\n\n            m |> Vector.iter (fun x ->\n                e |> HashSet.remove x |> should be True\n            )\n\n            e.Count |> should equal 0\n\n    [<Theory>]\n    let ``[Matrix] Iter`` (tensor: TensorKind) (rowMajor: bool) =\n        for _ = 1 to 100 do\n            let m = TensorGeneration.getIntMatrix tensor rowMajor\n\n            let expectedJumps =\n                if abs m.DX < abs m.DY then\n                    [ m.DX; m.DY - (m.SX - 1L) * m.DX ]\n                else\n                    [ m.DY; m.DX - (m.SY - 1L) * m.DY ]\n\n            let e = m.Elements |> HashSet.ofSeq\n            let mutable li = -1L\n\n            m |> Matrix.iteri (fun i ->\n                e |> HashSet.remove m.Data.[int i] |> should be True\n\n                if li <> -1L then\n                    expectedJumps |> should contain (i - li)\n\n                li <- i\n            )\n\n            e.Count |> should equal 0\n\n    [<Theory>]\n    let ``[Tensor4] Iter`` (tensor: TensorKind) (innerW: bool) =\n        for _ = 1 to 100 do\n            let m = TensorGeneration.getIntTensor4 tensor innerW\n            let e = m.Elements |> HashSet.ofSeq\n\n            m |> Tensor4.iter (fun x ->\n                e |> HashSet.remove x |> should be True\n            )\n\n            e.Count |> should equal 0\n\n    [<Theory>]\n    let ``[Tensor4] Map`` (tensor: TensorKind) (innerW: bool) =\n        for _ = 1 to 100 do\n            let a = TensorGeneration.getIntTensor4 tensor innerW\n            let b = TensorGeneration.rnd.UniformInt 100\n            let c = Tensor4.map ((+) b) a\n\n            let ref = a.Elements |> Seq.map ((+) b) |> HashSet.ofSeq\n\n            for x in c.Elements do\n                ref |> HashSet.remove x |> should be True\n\n            ref.Count |> should equal 0\n\n    [<Theory>]\n    let ``[Tensor4] Map2`` (tensor: TensorKind) (innerW0: bool) (innerW1: bool) =\n        for _ = 1 to 100 do\n            let a = TensorGeneration.getIntTensor4 tensor innerW0\n            let b = TensorGeneration.getIntTensor4OfSize tensor innerW1 a.Size\n            let c = Tensor4.map2 (+) a b\n\n            let ref = ReferenceCountingSet()\n            a.ForeachIndex(b.Info, fun i0 i1 ->\n                ref.Add (a.Data[int i0] + b.Data[int i1]) |> ignore\n            )\n\n            for x in c.Elements do\n                ref.Contains x |> should be True\n                ref.Remove x |> ignore\n\n            ref.Count |> should equal 0"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/TypeMetaTests.fs",
    "content": "﻿namespace Aardvark.Base.FSharp.Tests\n\nopen System\nopen Aardvark.Base\nopen Aardvark.Base.TypeMeta\n\nopen FsUnit\nopen NUnit.Framework\n\nmodule ``TypeMeta Tests`` =\n\n    [<Test>]\n    let ``[Patterns] MatrixOf``() =\n        let test43 (t: Type) =\n            match t with\n            | MatrixOf (s, Integral) -> s |> should equal (V2i(4, 3))\n            | _ -> failwith $\"failed pattern {t}\"\n\n        test43 typeof<M34i>\n        test43 typeof<M34l>\n\n    [<Test>]\n    let ``[Patterns] ListOf``() =\n        let test (t: Type) =\n            match t with\n            | ListOf Fractional -> ()\n            | _ -> failwithf $\"failed pattern {t}\"\n\n        test typeof<list<float16>>\n        test typeof<list<float32>>\n\n    [<Test>]\n    let ``[Patterns] ArrayOf``() =\n        let test (t: Type) =\n            match t with\n            | ArrayOf Fractional -> ()\n            | _ -> failwithf $\"failed pattern {t}\"\n\n        test typeof<float16[]>\n        test typeof<decimal[]>\n\n    [<Test>]\n    let ``[Patterns] ArrOf``() =\n        let test (expectedDim: int) (t: Type) =\n            match t with\n            | ArrOf (d, Fractional) -> d |> should equal expectedDim\n            | _ -> failwithf $\"failed pattern {t}\"\n\n        test 4 typeof<Arr<N<4>, float32>>\n        test 32 typeof<Arr<N<32>, float>>\n\n    [<Test>]\n    let ``[Patterns] SeqOf``() =\n        let test (t: Type) =\n            match t with\n            | SeqOf Numeric -> ()\n            | _ -> failwithf $\"failed pattern {t}\"\n\n        test typeof<seq<decimal>>\n        test typeof<seq<int8>>\n\n        match typeof<array<int8>> with\n        | SeqOf _ -> failwith \"should not match for array\"\n        | _ -> ()\n\n    [<Test>]\n    let ``[Patterns] EnumerableOf``() =\n        let test (t: Type) =\n            match t with\n            | EnumerableOf (VectorOf (_, Integral)) -> ()\n            | _ -> failwithf $\"failed pattern {t}\"\n\n        test typeof<seq<V2i>>\n        test typeof<list<V3ui>>\n        test typeof<array<V4l>>\n        test typeof<ResizeArray<V4i>>\n\n    [<Test>]\n    let ``[Patterns] RefOf``() =\n        let test (t: Type) =\n            match t with\n            | RefOf Vector -> ()\n            | _ -> failwithf $\"failed pattern {t}\"\n\n        test typeof<ref<V3ui>>\n        test typeof<ref<V2d>>"
  },
  {
    "path": "src/Tests/Aardvark.Base.FSharp.Tests/paket.references",
    "content": "group Test\n\nFsCheck\nFsCheck.NUnit\nExpecto\nExpecto.FsCheck\nFSharp.Core\nFsUnit\nNUnit\nNUnit3TestAdapter\nMicrosoft.NET.Test.Sdk\nYoloDev.Expecto.TestSdk"
  },
  {
    "path": "src/Tests/Aardvark.Base.Fonts.Tests/Aardvark.Base.Fonts.Tests.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <GenerateProgramFile>false</GenerateProgramFile>\n    <OutputType>Exe</OutputType>\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n    <RunSettingsFilePath>$(MSBuildThisFileDirectory)\\test.runsettings</RunSettingsFilePath>\n    <WarnOn>3389;3390;3395</WarnOn>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Debug\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Release\\</OutputPath>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"Common.fs\" />\n    <Compile Include=\"PathSegment.fs\" />\n    <Compile Include=\"Loading.fs\" />\n    <Compile Include=\"Program.fs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Fonts\\Aardvark.Base.Fonts.fsproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>"
  },
  {
    "path": "src/Tests/Aardvark.Base.Fonts.Tests/Common.fs",
    "content": "namespace Expecto\n\n\nopen Expecto\nopen Aardvark.Base\nopen Aardvark.Base.Fonts\nopen FsCheck\nopen FsCheck.TypeClass\n\ntype ZeroOne = ZeroOne of float\n\ntype Generators() =\n    static member V2d =\n        { new Arbitrary<V2d>() with\n            override x.Generator =\n                gen {\n                    let! (NormalFloat a) = Arb.generate<NormalFloat>\n                    let! (NormalFloat b)= Arb.generate<NormalFloat>\n                    return V2d(a,b)\n                }\n        }\n        \n    static member ZeroOne =\n        { new Arbitrary<ZeroOne>() with\n            override x.Generator =\n                gen {\n                    let! (NormalFloat a) = Arb.generate<NormalFloat>\n                    return ZeroOne (abs a % 1.0)\n                }\n        }\n\n    static member PathSegment =\n        { new Arbitrary<PathSegment>() with\n            override x.Generator =\n                gen {\n                    let! kind = Gen.elements [0;1;2;3]\n                    \n                    match kind with\n                    | 0 ->\n                        let! p0 = Arb.generate<V2d>\n                        let! p1 = Arb.generate<V2d> |> Gen.filter (fun p -> not (Fun.ApproximateEquals(p, p0, 1E-8)))\n                        return PathSegment.line p0 p1\n                    | 1 ->\n                        let! p0 = Arb.generate<V2d>\n                        let! p1 = Arb.generate<V2d> |> Gen.filter (fun p -> not (Fun.ApproximateEquals(p, p0, 1E-8)))\n                        let! p2 = Arb.generate<V2d> |> Gen.filter (fun p -> not (Fun.ApproximateEquals(p, p0, 1E-8)) && not (Fun.ApproximateEquals(p, p1, 1E-8)))\n                        return PathSegment.bezier2 p0 p1 p2\n                    | 2 ->\n                        let! center = Arb.generate<V2d>\n                        let! a0 = Arb.generate<V2d>\n                        let! a1 = Arb.generate<V2d> |> Gen.filter (fun p -> not (Fun.IsTiny(Vec.AngleBetween(Vec.normalize a0, Vec.normalize p), 1E-5)))\n                        \n                        let! (NormalFloat alpha0) = Arb.generate\n                        let! (NormalFloat dAlpha) = Arb.generate\n                        \n                        let dAlpha = dAlpha % Constant.PiHalf\n                        \n                        return PathSegment.arc alpha0 dAlpha (Ellipse2d(center, a0, a1))\n                    | _ ->\n                        let! p0 = Arb.generate<V2d>\n                        let! p1 = Arb.generate<V2d> |> Gen.filter (fun p -> not (Fun.ApproximateEquals(p, p0, 1E-8)))\n                        let! p2 = Arb.generate<V2d> |> Gen.filter (fun p -> not (Fun.ApproximateEquals(p, p0, 1E-8)) && not (Fun.ApproximateEquals(p, p1, 1E-8)))\n                        let! p3 = Arb.generate<V2d> |> Gen.filter (fun p -> not (Fun.ApproximateEquals(p, p0, 1E-8)) && not (Fun.ApproximateEquals(p, p1, 1E-8)) && not (Fun.ApproximateEquals(p, p2, 1E-8)))\n                        return PathSegment.bezier3 p0 p1 p2 p3\n                }\n        }\nmodule Expect =\n    let inline approxEqualAux< ^a, ^b when (^a or ^b) : (static member ApproximateEquals : ^a * ^a * float -> bool)> (foo : ^ b) (a : 'a) (b : 'a) (eps : float) =\n        (((^a or ^b) : (static member ApproximateEquals : ^a * ^a * float -> bool) (a, b, eps)))\n    \n    \n    let inline approxEquals a b eps msg =\n        if not (approxEqualAux Unchecked.defaultof<Fun> a b eps) then\n            Expect.equal a b msg\n    \n    let inline relativeApproxEquals (a : float) (b : float) eps msg =\n        \n        let scale = max (abs a) (abs b)\n        if not (Fun.IsTiny(scale, eps)) then\n            let ra = a / scale\n            let rb = b / scale\n            \n            if not (Fun.ApproximateEquals(ra, rb, eps)) then\n                Expect.equal a b msg\n    \n    \n    \n[<AutoOpen>]\nmodule ExpectoOverrides =\n        \n    let config =\n        { \n            FsCheckConfig.defaultConfig with \n                arbitrary = [ typeof<Generators> ]\n                maxTest = 100000\n        }\n            \n            \n    let testProperty a b =\n        testPropertyWithConfig config a b\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Fonts.Tests/Loading.fs",
    "content": "﻿module Aardvark.Base.Fonts.Tests.Loading\n\nopen Aardvark.Base\nopen Aardvark.Base.Fonts\nopen System.Runtime.InteropServices\nopen Expecto\n\n[<Tests>]\nlet tests =\n    testList \"Fonts.Loading\" [\n        test \"Embedded Symbola\" {\n            let font = Font.Symbola\n            Expect.equal font.Family \"Symbola\" \"Unexpected family name\"\n        }\n\n        test \"Resolve\" {\n            let font = Font(\"Arial\") // Finds font with family name most similar to Arial\n            Expect.isNotNull font.Family \"Family name is null\"\n            Expect.notEqual font.Family \"\" \"Family name is empty\"\n        }\n    ]"
  },
  {
    "path": "src/Tests/Aardvark.Base.Fonts.Tests/PathSegment.fs",
    "content": "module Aardvark.Base.Fonts.Tests.PathSegment\n\nopen Expecto\nopen Aardvark.Base\nopen Aardvark.Base.Fonts\nopen FsCheck\n\n[<Tests>]\nlet smartConstructors =\n    testList \"Fonts.PathSegment\" [\n        testProperty \"tryLine degenerate\" <| fun (p1 : V2d) ->\n            let line = PathSegment.tryLine p1 p1\n            Expect.isNone line \"impossible to create degenerate line\"\n\n        testProperty \"tryBezier2 line\" <| fun (p0 : V2d) (p2 : V2d) (ZeroOne t) ->\n            let p1 = lerp p0 p2 t\n            match PathSegment.tryBezier2 p0 p1 p2 with\n            | Some (Line(a,b)) ->\n                Expect.equal a p0 \"line start\"\n                Expect.equal b p2 \"line end\"\n            | None ->\n                Expect.equal p0 p2 \"degenerate bezier2\"\n            | Some other ->\n                failwithf \"degenerate bezier2 should be a line but is: %A\" other\n\n        testProperty \"tryBezier2 degenerate\" <| fun (p0 : V2d) ->\n            let bezier2 = PathSegment.tryBezier2 p0 p0 p0\n            Expect.isNone bezier2 \"impossible to create degenerate bezier2\"\n\n        testProperty \"tryArcSegment line\" <| fun (p0 : V2d) (p2 : V2d) (ZeroOne t) ->\n            let p1 = lerp p0 p2 t\n            match PathSegment.tryArcSegment p0 p1 p2 with\n            | Some (Line(a,b)) ->\n                Expect.equal a p0 \"line start\"\n                Expect.equal b p2 \"line end\"\n            | None ->\n                Expect.equal p0 p2 \"degenerate arc\"\n            | Some other ->\n                failwithf \"degenerate arc should be a line but is: %A\" other\n\n        testProperty \"tryArcSegment degenerate\" <| fun (p0 : V2d) ->\n            let arc = PathSegment.tryArcSegment p0 p0 p0\n            Expect.isNone arc \"impossible to create degenerate arc\"\n\n        testProperty \"tryBezier3 with bezier2 points\" <| fun (p0 : V2d) (p1 : V2d) (p2 : V2d) ->\n            let a = lerp p0 p1 (2.0 / 3.0)\n            let b = lerp p1 p2 (1.0 / 3.0)\n\n            match PathSegment.tryBezier3 p0 a b p2 with\n            | Some (Line(a, b)) ->\n                Expect.equal a p0 \"start\"\n                Expect.equal b p2 \"end\"\n            | None ->\n                Expect.equal p0 p1 \"degenerate bezier3\"\n                Expect.equal p0 p2 \"degenerate bezier3\"\n            | Some (Bezier2(a,b,c)) ->\n                Expect.equal a p0 \"start\"\n                Expect.approxEquals b p1 1E-13 \"control\"\n                Expect.equal c p2 \"end\"\n            | Some other ->\n                failwithf \"degenerate bezier3 should be a bezier2 but is: %A\" other\n\n        testProperty \"tryBezier3 with line points\" <| fun (p0 : V2d) (p3 : V2d) (ZeroOne t1) (ZeroOne t2) ->\n\n            let p1 = lerp p0 p3 (min t1 t2)\n            let p2 = lerp p0 p3 (max t1 t2)\n\n            match PathSegment.tryBezier3 p0 p1 p2 p3 with\n            | Some (Line(a, b)) ->\n                Expect.equal a p0 \"start\"\n                Expect.equal b p3 \"end\"\n            | None ->\n                Expect.approxEquals p0 p1 1E-14 \"degenerate bezier3\"\n            | Some other ->\n                failwithf \"degenerate bezier3 should be a line but is: %A\" other\n\n        testProperty \"tryBezier3 degenerate\" <| fun (p0 : V2d) ->\n            let arc = PathSegment.tryBezier3 p0 p0 p0 p0\n            Expect.isNone arc \"impossible to create degenerate arc\"\n\n        testProperty \"line degenerate\" <| fun (p1 : V2d) ->\n            let line = try Some (PathSegment.line p1 p1) with _ -> None\n            Expect.isNone line \"impossible to create degenerate line\"\n\n        testProperty \"bezier2 line\" <| fun (p0 : V2d) (p2 : V2d) (ZeroOne t) ->\n            let p1 = lerp p0 p2 t\n\n            let segment = try Some (PathSegment.bezier2 p0 p1 p2) with _ -> None\n\n            match segment with\n            | Some (Line(a,b)) ->\n                Expect.equal a p0 \"line start\"\n                Expect.equal b p2 \"line end\"\n            | None ->\n                Expect.equal p0 p2 \"degenerate bezier2\"\n            | Some other ->\n                failwithf \"degenerate bezier2 should be a line but is: %A\" other\n\n        testProperty \"bezier2 degenerate\" <| fun (p0 : V2d) ->\n            let bezier2 = try Some (PathSegment.bezier2 p0 p0 p0) with _ -> None\n            Expect.isNone bezier2 \"impossible to create degenerate bezier2\"\n\n        testProperty \"arcSegment line\" <| fun (p0 : V2d) (p2 : V2d) (ZeroOne t) ->\n            let p1 = lerp p0 p2 t\n            let segment = try Some (PathSegment.arcSegment p0 p1 p2) with _ -> None\n            match segment with\n            | Some (Line(a,b)) ->\n                Expect.equal a p0 \"line start\"\n                Expect.equal b p2 \"line end\"\n            | None ->\n                Expect.equal p0 p2 \"degenerate arc\"\n            | Some other ->\n                failwithf \"degenerate arc should be a line but is: %A\" other\n\n        testProperty \"arcSegment degenerate\" <| fun (p0 : V2d) ->\n            let arc = try Some (PathSegment.arcSegment p0 p0 p0) with _ -> None\n            Expect.isNone arc \"impossible to create degenerate arc\"\n\n        testProperty \"bezier3 with bezier2 points\" <| fun (p0 : V2d) (p1 : V2d) (p2 : V2d) ->\n            let a = lerp p0 p1 (2.0 / 3.0)\n            let b = lerp p1 p2 (1.0 / 3.0)\n\n            let segment = try Some (PathSegment.bezier3 p0 a b p2) with _ -> None\n            match segment with\n            | Some (Line(a, b)) ->\n                Expect.equal a p0 \"start\"\n                Expect.equal b p2 \"end\"\n            | None ->\n                Expect.equal p0 p1 \"degenerate bezier3\"\n                Expect.equal p0 p2 \"degenerate bezier3\"\n            | Some (Bezier2(a,b,c)) ->\n                Expect.equal a p0 \"start\"\n                Expect.approxEquals b p1 1E-13 \"control\"\n                Expect.equal c p2 \"end\"\n            | Some other ->\n                failwithf \"degenerate bezier3 should be a bezier2 but is: %A\" other\n\n        testProperty \"bezier3 with line points\" <| fun (p0 : V2d) (p3 : V2d) (ZeroOne t1) (ZeroOne t2) ->\n\n            let p1 = lerp p0 p3 (min t1 t2)\n            let p2 = lerp p0 p3 (max t1 t2)\n\n            let segment = try Some (PathSegment.bezier3 p0 p1 p2 p3) with _ -> None\n            match segment with\n            | Some (Line(a, b)) ->\n                Expect.equal a p0 \"start\"\n                Expect.equal b p3 \"end\"\n            | None ->\n                Expect.approxEquals p0 p1 1E-14 \"degenerate bezier3\"\n            | Some other ->\n                failwithf \"degenerate bezier3 should be a line but is: %A\" other\n\n        testProperty \"bezier3 degenerate\" <| fun (p0 : V2d) ->\n            let arc = try Some (PathSegment.bezier3 p0 p0 p0 p0) with _ -> None\n            Expect.isNone arc \"impossible to create degenerate arc\"\n\n\n\n\n    ]\n\n[<Tests>]\nlet splitMerge =\n    testList \"Fonts.PathSegment\" [\n        testProperty \"split at 0\" <| fun (seg : PathSegment) ->\n            let (l, r) = PathSegment.split 0.0 seg\n            Expect.isNone l \"left part should be empty\"\n            Expect.equal r (Some seg) \"right part should be entire segment\"\n\n        testProperty \"split at 1\" <| fun (seg : PathSegment) ->\n            let (l, r) = PathSegment.split 1.0 seg\n            Expect.isNone r \"right part should be empty\"\n            Expect.equal l (Some seg) \"left part should be entire segment\"\n\n        testProperty \"tryGetT\" <| fun (seg : PathSegment) (ZeroOne t) ->\n            let pt = PathSegment.point t seg\n            match PathSegment.tryGetT 1E-7 pt seg with\n            | Some res ->\n                Expect.approxEquals res t 1E-8 \"tryGetT\"\n            | None ->\n                failwithf \"could not get t for: %A (%A)\" t pt\n\n        testProperty \"withT0\" <| fun (seg : PathSegment) (ZeroOne t) ->\n            let t = min t 0.95\n            let sub = PathSegment.withT0 t seg\n            Expect.isSome sub \"sub should exist\"\n            let sub = sub.Value\n\n            Expect.approxEquals (PathSegment.point t seg) (PathSegment.startPoint sub) 1E-8 \"split point equal\"\n            Expect.approxEquals (PathSegment.tangent t seg) (PathSegment.tangent 0.0 sub) 1E-5 \"split tangent equal\"\n            Expect.relativeApproxEquals (PathSegment.curvature t seg) (PathSegment.curvature 0.0 sub) 1E-6 \"split curvature equal\"\n            Expect.relativeApproxEquals (PathSegment.curvatureDerivative t seg) (PathSegment.curvatureDerivative 0.0 sub) 1E-6 \"split curvature derivative equal\"\n\n        testProperty \"withT1\" <| fun (seg : PathSegment) (ZeroOne t) ->\n            let t = max t 0.05\n            let sub = PathSegment.withT1 t seg\n            Expect.isSome sub \"sub should exist\"\n            let sub = sub.Value\n\n            Expect.approxEquals (PathSegment.point t seg) (PathSegment.endPoint sub) 1E-8 \"split point equal\"\n            Expect.approxEquals (PathSegment.tangent t seg) (PathSegment.tangent 1.0 sub) 1E-5 \"split tangent equal\"\n            Expect.relativeApproxEquals (PathSegment.curvature t seg) (PathSegment.curvature 1.0 sub) 1E-6 \"split curvature equal\"\n            Expect.relativeApproxEquals (PathSegment.curvatureDerivative t seg) (PathSegment.curvatureDerivative 1.0 sub) 1E-6 \"split curvature derivative equal\"\n\n        testProperty \"split\" <| fun (seg : PathSegment) (ZeroOne t) (NonEmptyArray(tests : ZeroOne[])) ->\n\n            Tests.skiptest \"Broken!\"\n\n            // Fails for the following input:\n\n            //let seg = PathSegment.bezier2 (V2d(0.3987154326720799, 0.7488657942030035)) (V2d(0.3574107514673024, 0.7075611129976505)) (V2d(0.570837825059161, 0.9209882066126354))\n\n            //let t = 0.5790968411\n\n            //let tests = [| ZeroOne 0.1357913208 |]\n\n            let t = clamp 1E-2 (1.0 - 1E-2) t\n            let (l, r) = PathSegment.split t seg\n\n\n            Expect.isSome l \"left part should exist\"\n            Expect.isSome r \"right part should exist\"\n\n            match l with\n            | Some l ->\n                match r with\n                | Some r ->\n                    Expect.equal (PathSegment.endPoint l) (PathSegment.startPoint r) \"split point equal\"\n                    Expect.approxEquals (PathSegment.tangent 1.0 l) (PathSegment.tangent 0.0 r) 1E-5 \"split tangent equal\"\n                    Expect.relativeApproxEquals (PathSegment.curvature 1.0 l) (PathSegment.curvature 0.0 r) 1E-6 \"split curvature equal\"\n                    Expect.relativeApproxEquals (PathSegment.curvatureDerivative 1.0 l) (PathSegment.curvatureDerivative 0.0 r) 1E-6 \"split curvature derivative equal\"\n\n                    for (ZeroOne tt) in tests do\n                        let pt = PathSegment.point tt seg\n\n                        let tl = PathSegment.tryGetT 1E-7 pt l |> Option.map (fun t -> PathSegment.point t l)\n                        let tr = PathSegment.tryGetT 1E-7 pt r |> Option.map (fun t -> PathSegment.point t r)\n\n                        match tl with\n                        | Some pl -> Expect.approxEquals pl pt 1E-7 \"point on left part\"\n                        | None ->\n                            match tr with\n                            | Some pr -> Expect.approxEquals pr pt 1E-7 \"point on left part\"\n                            | None -> failwith \"different curves\"\n\n\n                | None ->\n                    ()\n                    //Expect.equal l seg \"split at end\"\n            | None ->\n                match r with\n                | Some r ->\n                    ()\n                    //Expect.equal r seg \"split at start\"\n                | None ->\n                    failwith \"should be impossible (both split parts empty)\"\n\n\n\n    ]"
  },
  {
    "path": "src/Tests/Aardvark.Base.Fonts.Tests/Program.fs",
    "content": "﻿open Expecto\nopen Expecto.Impl\n\n[<EntryPoint>]\nlet main args =\n    let cfg : ExpectoConfig = { ExpectoConfig.defaultConfig with runInParallel = false }\n    //runTests cfg Aardvark.Base.Fonts.Tests.PathSegment.splitMerge |> ignore\n    //runTestsWithCLIArgs [] args Aardvark.Rendering.Text.Tests.PathSegment.splitMerge |> ignore\n\n    0\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Fonts.Tests/paket.references",
    "content": "group Test\n\nFsCheck\nFsCheck.NUnit\nExpecto\nExpecto.FsCheck\nFSharp.Core\nFsUnit\nNUnit\nNUnit3TestAdapter\nMicrosoft.NET.Test.Sdk\nYoloDev.Expecto.TestSdk"
  },
  {
    "path": "src/Tests/Aardvark.Base.Fonts.Tests/test.runsettings",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RunSettings>\n  <LoggerRunSettings>\n    <Loggers>\n      <Logger friendlyName=\"console\" enabled=\"True\">\n        <Configuration>\n            <Verbosity>detailed</Verbosity>\n        </Configuration>\n      </Logger>\n    </Loggers>\n  </LoggerRunSettings>\n  <Expecto>\n    <Parallel>False</Parallel>\n  </Expecto>\n</RunSettings>"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/AListTests.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen System.Threading.Tasks\nopen System.Runtime.CompilerServices\n//\n//[<AbstractClass; Sealed; Extension>]\n//type ListReaderExtensions private() =\n//\n//    [<Extension>]\n//    static member GetSetDelta(x : IListReader<'a>) =\n//        let oldContent = x.State.Content\n//        x.GetOperations null \n//            |> DeltaList.toSeq\n//            |> Seq.map (fun (i,op) ->\n//                match op with\n//                    | Set v -> Add v\n//                    | Remove ->\n//                        MapExt.find i oldContent |> Rem\n//            )\n//            |> Seq.toList\n\nmodule ``simple list tests`` =\n    open Aardvark.Base.IL.Serializer.RefMap\n    open Aardvark.Base.CSharpList\n\n    module Delta =\n        let map (f : 'a -> 'b) (d : SetOperation<'a>) =\n            SetOperation(f d.Value, d.Count)\n\n\n    [<Test>]\n    let ``[AList] clist add / remove``() =\n        let l = clist [1;2;3]\n\n        let d = l |> AList.map (fun a -> 2 * a)\n\n        let r = d.GetReader()\n        let d = r.GetOperations().ToSeq() |> Seq.map (fun (a,b) -> b)\n        d |> should setEqual [Set 2; Set 4; Set 6]\n\n        transact (fun () ->\n            l.Append 4 |> ignore\n        )\n\n        let d = r.GetOperations().ToSeq() |> Seq.map (fun (a,b) -> b)\n        d |> should setEqual [Set 8]\n\n        let k5 =\n            transact (fun () ->\n                l.Insert(3, 4)\n            )\n\n        let d = r.GetOperations().ToSeq() |> Seq.map (fun (a,b) -> b)\n        d |> should setEqual [Set 8]\n\n\n        transact (fun () ->\n            l.RemoveAt 3 |> ignore\n        )\n        let d = r.GetOperations().ToSeq() |> Seq.map (fun (a,b) -> b)\n        d |> should setEqual [ElementOperation<int>.Remove]\n\n    [<Test>]\n    let ``[COrderedSet] contains``() =\n        \n        let a = \"a\"\n        let b = \"b\"\n        let c = \"c\"\n\n        let set = COrderedSet.ofSeq [a; b; c]\n                \n        set.Contains(a) |> should be True\n        set.Contains(b) |> should be True\n        set.Contains(c) |> should be True\n\n        ()\n\n    [<Test>]\n    let ``[AList] add/clear/evaluate``() =\n        \n        let l = CList.empty\n        let refSet = new HashSet<int>()\n        \n        let set = AList.toASet l\n\n        let rnd = Random()\n\n        for i in 0..10000 do\n            if rnd.NextDouble() < 0.5 then\n                printfn \"add\"\n                refSet.Add(i) |> ignore\n                transact(fun () -> l.Append i |> ignore)\n                printfn \" -> cnt=%d\" l.Count\n\n            if rnd.NextDouble() < 0.1 then\n                printfn \"clear\"\n                refSet.Clear()\n                transact(fun () -> l.Clear())\n                printfn \" -> cnt=%d\" l.Count\n                should equal 0 l.Count\n\n            if rnd.NextDouble() < 0.2 then\n                printfn \"eval\"\n                let test = ASet.toArray set\n                printfn \" -> list=%d set=%d\" l.Count test.Length\n                should equal test.Length l.Count\n                should equal test.Length refSet.Count\n                should equal test (Seq.toArray refSet) \n\n    [<Test>]\n    let ``[AList] toASet``() =\n        \n        // test should not crash\n        let l = CList.empty\n        \n        let set = AList.toASet l\n        \n        transact(fun () -> l.Append 1 |> ignore)\n\n        let test = ASet.toArray set\n        printf \"cnt=%d\" test.Length\n        should equal test.Length 1\n        should equal test.[0] 1\n\n        transact(fun () -> l.Append 2 |> ignore)\n        transact(fun () -> l.Clear())\n        transact(fun () -> l.Append 3 |> ignore)\n        \n        let test = ASet.toArray set\n        printf \"cnt=%d\" test.Length\n        should equal test.Length 1\n        should equal test.[0] 3\n\n        ()\n\n    [<Test>]\n    let ``[AList] choose test``() =\n        let stuff = CList.ofSeq [ 1; 2; 3;]\n\n        let filteredList = stuff |> AList.choose (fun x -> if x % 2 = 0 then Some x else None)\n\n        let r = filteredList.GetReader()\n        r.GetOperations() |> ignore\n        printfn \"%A\" (filteredList |> AList.toArray)\n        \n        let rnd = new Random(1)\n        for i in 0..10000 do\n            if rnd.NextDouble() < 0.2 && stuff.Count > 0 then // rem\n                let index = rnd.Next(stuff.Count)\n                transact(fun () ->\n                    stuff.RemoveAt(index) |> ignore\n                )\n\n            if rnd.NextDouble() < 0.2 then // append\n                transact(fun () ->\n                    stuff.Append(rnd.Next()) |> ignore\n                )\n\n            if rnd.NextDouble() < 0.2 then // prepend\n                transact(fun () ->\n                    stuff.Prepend(rnd.Next()) |> ignore\n                )\n            \n            if rnd.NextDouble() < 0.2 then // insert\n                let insertIndex = rnd.Next(stuff.Count)\n                transact(fun () ->\n                    stuff.Insert(insertIndex, rnd.Next())\n                )\n\n            if rnd.NextDouble() < 0.2 then // evaluate\n                r.GetOperations() |> ignore\n                printfn \"%A\" (filteredList |> AList.toArray)\n\n            if rnd.NextDouble() < 0.2 then // clear\n                transact(fun () ->\n                    stuff.Clear())\n\n        ()\n\n\n//    [<Test>]\n//    let ``[AList] collect``() =\n//        let l0 = clist []\n//        let l1 = clist []\n//        let l2 = clist []\n//        let l = clist [l0 :> alist<_>; l1 :> alist<_>]\n//\n//        let d = l |> AList.concat\n//        let r = d.GetReader()\n//\n//\n//        r.GetSetDelta() |> should setEqual []\n//\n//        let k1 = transact (fun () -> l0.Append 1)\n//        r.GetSetDelta() |> should setEqual [Add 1]\n//\n//        let kl2 = transact (fun () -> l.Append l2)\n//        r.GetSetDelta() |> should setEqual []\n//\n//        let k5 = transact (fun () -> l2.Append 5)\n//        r.GetSetDelta() |> should setEqual [Add 5]\n//\n//\n//        transact (fun () ->\n//            l2.Append 6 |> ignore\n//            l.Remove kl2 |> ignore\n//        )\n//        r.GetSetDelta() |> should setEqual [Rem 5]\n//\n//\n//    [<Test>]\n//    let ``[AList] alist collect outer reomve``() =\n//        let l0 = AList.ofList [ 1; 2 ]\n//        let l1 = AList.ofList [ 3; 4 ]\n//        let l2 = AList.ofList []\n//        let l = clist [l0]\n//\n//        let d = l |> AList.concat\n//        let r = d.GetReader()\n//\n//        r.GetSetDelta() |> should setEqual [ Add 1 ; Add 2]\n//        r.State.Count |> should equal 2\n//\n//        transact (fun () -> l.Append l1 |> ignore; l.RemoveAt 0)\n//        r.GetSetDelta() |> should setEqual [Add 3; Add 4; Rem 1; Rem 2]\n//        r.State.Count |> should equal 2\n//\n//        transact (fun () -> l.Append l0 |> ignore; l.RemoveAt 0)\n//        r.GetSetDelta() |> should setEqual [Rem 3; Rem 4; Add 1; Add 2]\n//        r.State.Count |> should equal 2\n//\n//        transact (fun () -> l.Append l1 |> ignore; l.RemoveAt 0)\n//        r.GetSetDelta() |> should setEqual [Add 3; Add 4; Rem 1; Rem 2]\n//        r.State.Count |> should equal 2\n//\n//        transact (fun () -> l.Append l2 |> ignore; l.RemoveAt 0)\n//        r.GetSetDelta() |> should setEqual [Rem 3; Rem 4]\n//        r.State.Count |> should equal 0\n//\n//    [<Test>]\n//    let ``[AList] alist order``() =\n//        let l0 = clist []\n//        let l1 = clist []\n//        let l2 = clist []\n//        let l = clist []\n//\n//        let kl0 = transact (fun () -> l.Append (l0 :> alist<_>))\n//        let kl1 = transact (fun () -> l.Append (l1 :> alist<_>))\n//\n//        let d = l |> AList.concat\n//\n//        d |> AList.toList |> should equal []\n//\n//        let kl2 = transact (fun () -> l.Append l2)\n//        d |> AList.toList |> should equal []\n//\n//        let k21 = transact (fun () -> l2.Append 1)\n//        let ll = d |> AList.toList\n//        ll |> should equal [1]\n//\n//        let k01 = transact (fun () -> l0.Append 1)\n//        d |> AList.toList |> should equal [1; 1]\n//\n//        let k12 = transact (fun () -> l1.Append 2)\n//        d |> AList.toList |> should equal [1; 2; 1]\n//\n//        let k13 = transact (fun () -> l1.Append 3)\n//        d |> AList.toList |> should equal [1; 2; 3; 1]\n//\n//        transact (fun () -> l.Remove kl1)\n//        d |> AList.toList |> should equal [1; 1]\n//\n////    [<Test>]\n////    let ``[AList] ordered set test``() =\n////        let s = corderedset [1;2;3]\n////        let d = s |> AList.map (fun a -> 2 * a)\n////\n////        let r = d.GetReader()\n////        d |> AList.toList |> should equal [2;4;6]\n////        r.GetSetDelta() |> should setEqual [Add 2; Add 4; Add 6]\n////\n////\n////        transact (fun () -> s.InsertAfter(2, 6)) |> ignore\n////        d |> AList.toList |> should equal [2;4;12;6]\n////        r.GetSetDelta() |> should setEqual [Add 12]\n////\n////    [<Test>]\n////    let ``[AList] choose reader time-density``() =\n////        let l = corderedset []\n////\n////        let validateTimeDensity(r : IListReader<'a>) =\n////            r.GetDelta() |> ignore\n////            ()\n//////            let mutable t = r.RootTime.Root.Next\n//////            while t <> r.RootTime.Root do\n//////                match r.Content.TryGetValue t with\n//////                    | (true, v) -> ()\n//////                    | _ -> failwithf \"no value associated with time %A\" t\n//////                t <- t.Next\n////\n////        let add v = l.Add v |> ignore\n////        let content (r : IListReader<'a>) = \n////            r.GetDelta() |> ignore\n////            r.Content.All |> Seq.sortBy fst |> Seq.map snd |> Seq.toList\n////        // get only those elements being even\n////        let m2 = l |> AList.choose (fun a -> if a % 2 = 0 then Some a else None)\n////        let r = m2.GetReader()\n////\n////        r |> validateTimeDensity\n////\n////        transact (fun () -> add 1; add 2)\n////        r |> content |> should equal [2]\n////        r |> validateTimeDensity\n////\n////        transact (fun () -> l.InsertAfter(1, 4) |> ignore)\n////        r |> content |> should equal [4; 2]\n////        r |> validateTimeDensity\n////\n////        transact (fun () -> l.InsertBefore(4, 6) |> ignore)\n////        r |> content |> should equal [6; 4; 2]\n////        r |> validateTimeDensity\n////\n////        transact (fun () -> l.Remove(4) |> ignore)\n////        r |> content |> should equal [6; 2]\n////        r |> validateTimeDensity\n////\n////        transact (fun () -> l.Clear())\n////        r |> content |> should equal []\n////        r |> validateTimeDensity\n////\n////\n////\n////        ()\n//\n////    [<Test>]\n////    let ``[AList] callback survive test``() =\n////        let subscribe cb (l : alist<'a>) =\n////            let s = l |> AList.unsafeRegisterCallbackNoGcRoot cb\n////            // s is ignored here (going out of scope)\n////            ()\n////\n////        let deltaRef = ref []\n////        let callback (d  : list<Delta<ISortKey * int>>) = deltaRef := !deltaRef @ (d |> List.map (Delta.map snd))\n////\n////        let deltas() =\n////            let l = !deltaRef\n////            deltaRef := []\n////            l\n////\n////        let l = corderedset [1]\n////        subscribe callback l\n////        System.GC.AddMemoryPressure(1L <<< 30)\n////        System.GC.Collect()\n////\n////\n////        deltas() |> should setEqual [Add 1]\n////\n////        transact (fun () -> l.Add 2 |> ignore; l.Add 3 |> ignore)\n////        deltas() |> should setEqual [Add 2; Add 3]\n////\n////        transact (fun () -> l.Remove 1 |> ignore)\n////        deltas() |> should setEqual [Rem 1]\n////\n////\n////        ()\n//\n//    [<Test>]\n//    let ``[AList] clist indexing test``() =\n//        let c = clist [1;2;3;4]\n//        \n//        // stupid obfuscated identity\n//        let d = c |> AList.collect AList.single |> AList.choose Some\n//\n//        let r = d.GetReader()\n//        let content (r : IListReader<'a>) = \n//            r.GetDelta() |> ignore\n//            r.State |> PList.toList\n//\n//        r |> content |> should equal [1;2;3;4]\n//        c |> Seq.length |> should equal 4\n//\n//        transact (fun () -> c.Insert(0, 0))\n//        r |> content |> should equal [0;1;2;3;4]\n//        c |> Seq.length |> should equal 5\n//\n//        transact (fun () -> c.RemoveAt 1)\n//        r |> content |> should equal [0;2;3;4]\n//        c |> Seq.length |> should equal 4\n//\n//        transact (fun () -> c.Insert(1, 2); c.Insert(1, 1))\n//        r |> content |> should equal [0;1;2;2;3;4]\n//        c |> Seq.length |> should equal 6\n//\n//        transact (fun () -> c |> CList.removeRange 1 2)\n//        r |> content |> should equal [0;2;3;4]\n//        c |> Seq.length |> should equal 4\n//\n//        c.[0] |> should equal 0\n//        c.[1] |> should equal 2\n//        c.[2] |> should equal 3\n//        c.[3] |> should equal 4\n//\n//        transact (fun () -> c.[0] <- 1)\n//        r |> content |> should equal [1;2;3;4]\n//        c |> CList.count |> should equal 4\n//\n//        transact (fun () -> c.[3] <- 1)\n//        r |> content |> should equal [1;2;3;1]\n//        c |> CList.count |> should equal 4\n//\n//        transact (fun () -> c |> CList.add 5)\n//        r |> content |> should equal [1;2;3;1;5]\n//        c |> CList.count |> should equal 5\n//\n//        transact (fun () -> c |> CList.addRange [6;7])\n//        r |> content |> should equal [1;2;3;1;5;6;7]\n//        c |> CList.count |> should equal 7\n//\n//        c |> CList.tryGet -1 |> should equal None\n//        c |> CList.tryGet 7 |> should equal None\n//        c |> CList.tryGet 0 |> should equal (Some 1)\n//        c |> CList.tryGet 6 |> should equal (Some 7)\n//\n//        transact (fun () -> c |> CList.clear)\n//        r |> content |> should equal []\n//        c |> CList.count |> should equal 0\n//\n//        \n//        CList.empty<int> = CList.empty<int> |> should be False\n//\n//        ()\n//\n//    [<Test>]\n//    let ``[AList] set sorting``() =\n//        let s = CSet.ofList [4;3;2;1]\n//\n//        let l = s |> ASet.sort\n//        let r = l.GetReader()\n//\n//        let content (r : IListReader<'a>) = \n//            r.GetDelta() |> ignore\n//            r.Content.All |> Seq.sortBy fst |> Seq.map snd |> Seq.toList\n//\n//        r |> content |>  should equal [1;2;3;4]\n//        \n//        transact (fun () -> CSet.add 5 s |> ignore)\n//        r |> content |>  should equal [1;2;3;4;5]\n//\n//        transact (fun () -> CSet.remove 3 s |> ignore)\n//        r |> content |>  should equal [1;2;4;5]\n//\n//        transact (fun () -> CSet.add 3 s |> ignore)\n//        r |> content |>  should equal [1;2;3;4;5]\n//\n//        transact (fun () -> CSet.clear s )\n//        r |> content |>  should equal []\n//        \n//\n//    [<Test>]\n//    let ``[AList] alist construction of aset``() =\n//\n//        let set = CSet.ofList [ 1; 2; 3 ]\n//\n//        let list = AList.ofASet set\n//\n//\n//        let r = list.GetReader()\n//        let content (r : IListReader<'a>) = \n//            r.GetDelta() |> ignore\n//            r.Content.All |> Seq.sortBy fst |> Seq.map snd |> Seq.toList\n//\n//        transact (fun () -> CSet.add 12 set |> ignore)\n//        r |> content |> should equal [  1; 2; 3; 12; ]\n//\n//        transact (fun () -> CSet.remove 3 set |> ignore)\n//        r |> content |> should equal [  1; 2; 12 ]\n//\n//\n//    [<Test>]\n//    let ``[AList] alist construction of aset with selection``() =\n//\n//        let set = CSet.ofList [ 1; 2; 3 ]\n//        \n//        let list =\n//            alist {\n//                for x in AList.ofASet set do\n//                    yield x * 2\n//            }\n//\n//        let r = list.GetReader()\n//        let content (r : IListReader<'a>) = \n//            r.GetDelta() |> ignore\n//            r.Content.All |> Seq.sortBy fst |> Seq.map snd |> Seq.toList\n//\n//        transact (fun () -> CSet.add 12 set |> ignore)\n//        r |> content |> should equal [ 2; 4; 6; 24]\n//\n//    [<Test>]\n//    let ``[AList] ASet -> sortWith -> AList``() =\n//\n//        let input = CSet.ofList [ 1..10 ]\n//\n//        let set = input |> ASet.map id\n//\n//        let alist = set |> ASet.sortWith (fun _ _ -> 0)\n//\n//        let mapped = alist |> AList.map id\n//\n//        let r = mapped.GetReader()\n//        let delta (r : IListReader<'a>) = r.GetDelta() |> List.map (Delta.map snd)\n//\n//        r |> delta |> should setEqual  [ for i in 1 .. 10 do yield Add i] \n//\n//        transact (fun () -> CSet.add 11 input |> ignore )\n//\n//        r |> delta |> should setEqual  [ Add 11 ] \n//\n//        transact (fun () -> CSet.add 12 input |> ignore )\n//        transact (fun () -> CSet.add 13 input |> ignore )\n//\n//        r |> delta |> should setEqual  [ Add 12; Add 13 ] \n//\n//        r.Content.All |> Seq.sortBy fst |> Seq.map snd |> Seq.toList |> should setEqual [ 1..13 ]\n//\n//    [<Test>]\n//    let ``[AList] toASet test``() =\n//        let list = CList.empty\n//\n//        let lm = AList.toMod list\n//        let set = AList.toASet list\n//        let setMod = ASet.toMod set\n//\n//        //let setReader = ASetReaders.ReferenceCountedReader(fun () -> set.GetReader())\n//        //let reader = setReader.GetReference()\n//\n//        let test() =\n//            let lc = list.Count \n//            let sc = setMod.GetValue().Count\n//            let rc = lm.GetValue().Count\n//            //reader.GetDelta() |> ignore\n//            //let sc = reader.Content.Count\n//            sprintf \"ListCount=%d SetCount=%d ReaderCount=%d\" lc sc rc |> Console.WriteLine\n//            rc |> should equal lc\n//            sc |> should equal lc\n//\n//        test()\n//\n//        transact (fun () -> list.Add(new Object()) |> ignore )\n//\n//        test()\n//\n//        transact (fun () -> list.Add(new Object()) |> ignore )\n//\n//        test()\n//\n//        transact (fun () -> list.Clear() )\n//\n//        test()\n//\n//        transact (fun () -> list.Add(new Object()) |> ignore )\n//        transact (fun () -> list.Add(new Object()) |> ignore )\n//        transact (fun () -> list.Add(new Object()) |> ignore )\n//        transact (fun () -> list.Add(new Object()) |> ignore )\n//\n//        test()\n//        \n//        transact (fun () -> list.Clear() )\n//\n//        test()\n//\n//        transact (fun () -> \n//            list.Clear() \n//            list.Clear() \n//            list.Add(new Object()) |> ignore\n//            list.Add(new Object()) |> ignore\n//            list.Add(new Object()) |> ignore\n//        )\n//\n//        test()\n//\n//        transact (fun () -> \n//            list.Clear() \n//            list.Add(new Object()) |> ignore\n//            list.Add(new Object()) |> ignore\n//            list.Add(new Object()) |> ignore\n//        )\n//\n//        test()\n//\n//        transact (fun () -> list.Clear() )\n//\n//        transact (fun () -> \n//            list.Add(new Object()) |> ignore\n//            list.Add(new Object()) |> ignore\n//            list.Add(new Object()) |> ignore\n//        )\n//\n//        test()\n//\n//        transact (fun () -> \n//            list.Add(new Object()) |> ignore\n//        )\n//\n//        test()\n//\n//        transact (fun () -> list.Clear() )\n//\n//        transact (fun () -> \n//            list.Add(new Object()) |> ignore\n//        )\n//\n//        test()\n//\n//\n//\n//    [<Test>]\n//    let ``[CList] concurrent reader-reset``() =\n//        \n//        let list = CList.ofList [1..10]\n//\n//        let r = (list :> alist<_>).GetReader()\n//        let running = ref true\n//\n//        Task.Factory.StartNew(fun () ->\n//            while !running do\n//                list.Clear() // causing reset\n//                list.AddRange [1..10] // changing content\n//        ) |> ignore\n//\n//        for i in 0..100 do\n//            r.GetDelta() |> ignore\n//\n//        running := false\n//\n//    [<Test>]\n//    let ``[COrderedSet] concurrent reader-reset``() =\n//        \n//        let set = COrderedSet.ofList [1..10]\n//\n//        let r = (set :> alist<_>).GetReader()\n//        let running = ref true\n//\n//        Task.Factory.StartNew(fun () ->\n//            while !running do\n//                set.Clear() // causing reset\n//                set.UnionWith [1..10] // changing content\n//        ) |> ignore\n//\n//        for i in 0..100 do\n//            r.GetDelta() |> ignore\n//\n//        running := false\n//\n//    [<Test>]\n//    let ``[COrderedSet] add remove clear test``() =\n//        \n//        let objects = [Object; Object; Object; Object; Object; Object; Object; Object; Object; Object;]\n//        let set = COrderedSet.empty\n//        \n//        let rnd = Random()\n//\n//        let mutable readerCount = 0\n//        let foo = \n//            set |> ASet.map id \n//                |> ASet.unsafeRegisterCallbackNoGcRoot (fun dl -> \n//                    for d in dl do\n//                        match d with\n//                            | Add _ -> readerCount <- readerCount + 1\n//                            | Rem _ -> readerCount <- readerCount - 1\n//                   )\n//\n//        for i in 0..1000 do\n//            if (i % 10) = 0 then\n//                transact ( fun () -> COrderedSet.clear set )\n//                should equal 0 set.Count\n//                should equal 0 readerCount\n//            else\n//                let add = rnd.NextDouble() < 0.5\n//                let origCnt = set.Count\n//                //let n = rnd.Next(10)\n//                let o = objects.[rnd.Next(9)]\n//                let contains = set.Contains o\n//                let suc = \n//                    transact ( fun () ->\n//                        if add then set.Add o\n//                        else set.Remove o\n//                    )\n//\n//                if add then\n//                    // contains = true -> suc = false\n//                    // contains = false -> suc = true\n//                    should equal (contains <> suc) true\n//                else // if rem\n//                    // contains = true -> suc = true\n//                    // contains = false -> suc = false\n//                    should equal contains suc\n//\n//                should equal set.Count readerCount\n//\n//\n//        foo.Dispose()\n//\n//    type Leak(cnt : ref<int>) =\n//        let value = !cnt\n//        do cnt := !cnt + 1\n//        member x.Value = value\n//        override x.Finalize() = cnt := !cnt - 1\n//\n//    [<Test>]\n//    let ``[AList] memory leak``() =\n//        let list = CList.empty<Leak>;\n//        let list2 = list |> AList.map (fun x -> (x.Value) * 2)\n//        let cnt = ref 0\n//\n//        let check() =\n//\n//            printfn \"%A\" (list2 |> AList.toList)\n//\n//            GC.Collect ()\n//            GC.WaitForPendingFinalizers()\n//        \n//            printfn \"%A\" !cnt\n//               \n//            !cnt |> should equal list.Count\n//\n//        // intial adds\n//        transact (fun () -> list.Add(Leak(cnt)) |> ignore)\n//\n//        transact (fun () -> list.Add(Leak(cnt)) |> ignore)\n//\n//        transact (fun () -> list.Add(Leak(cnt)) |> ignore)\n//\n//        check() // should be 3\n//        \n//        transact (fun () -> list.Clear())\n//\n//        check() // should be 0\n//\n//        transact (fun () -> list.Add(Leak(cnt)) |> ignore)\n//\n//        transact (fun () -> list.Add(Leak(cnt)) |> ignore)\n//\n//        check() // should be 2\n//\n//        transact (fun () -> list.Add(Leak(cnt)) |> ignore)\n//\n//        check() // should be 3\n//        \n//        ()"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/AListTestsNew.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen System\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen System.Threading\nopen System.Threading.Tasks\n\nmodule AListTestsNew =\n\n\n    type MkDispose(mkSource : string) =\n        let mutable isDisposed = false\n        member x.Source = mkSource\n        member x.IsDisposed = isDisposed\n        interface IDisposable with\n            member x.Dispose () = \n                if isDisposed then failwith \"doublefree\"\n                printfn \"dispose: %A\" mkSource\n                isDisposed <- true\n\n    let testMapUse () =\n        \n        let input = [\"a\";\"b\";\"b\";\"c\"] |> CList.ofSeq \n        let mkd = input |> AList.mapUse  (fun a -> new MkDispose(a))\n        let m = AList.toMod mkd\n\n        let original = m |> Mod.force |> PList.toArray\n\n        let check wanted =\n            let is = m |> Mod.force |> PList.toList |> List.map (fun a -> a.Source)\n            should equal is wanted\n\n        transact (fun _ -> \n            let r = CList.removeElement \"c\" input\n            r |> should equal true\n        )\n        check [\"a\";\"b\";\"b\"]\n        should equal original.[3].IsDisposed true\n\n        transact (fun _ -> \n            let r = CList.removeElement \"b\" input\n            r |> should equal true\n        )\n        check [\"a\";\"b\"]\n        should equal original.[1].IsDisposed false\n\n        transact (fun _ -> \n            let r = CList.removeElement \"b\" input\n            r |> should equal true\n        )\n        check [\"a\"]\n        should equal original.[1].IsDisposed true\n        \n        transact (fun _ -> \n            let r = CList.removeElement \"a\" input\n            r |> should equal true\n        )\n        check []\n        should equal original.[0].IsDisposed true\n\n        for a in original do should equal a.IsDisposed true\n\n        ()\n\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/AMapTests.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\n\nopen System\nopen System.Collections.Generic\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\n\nmodule ``simple cmap tests`` =\n    open Aardvark.Base.HashMap\n\n//\n//    let dictEqual (xs : list<'k * 'v>) (set : IVersionedDictionary<'k,IVersionedSet<'v>>) =\n//        let kvs = set |> Seq.collect (fun (KeyValue(k,v)) ->\n//            v |> Seq.map (fun v ->\n//                k,v\n//            )\n//        )\n//        let set = HashSet(kvs)\n//        set.SetEquals(xs) |> should be True\n//            \n//        \n//\n//    [<Test>]\n//    let ``[CMap] cmap add remove``() =\n//        let l = CMap.empty\n//\n//        transact (fun () -> \n//            l |> CMap.set 1 2 \n//            l |> CMap.set 1 3\n//        )\n//\n//        let m = AMap.toMod l\n//        m |> Mod.force |> dictEqual [ 1, 3 ]\n//\n//        transact (fun () -> \n//            l |> CMap.set 5 2 \n//            l |> CMap.set 1 6\n//        )\n//\n//        m |> Mod.force |> dictEqual [ 1, 6; 5, 2]\n//\n//        transact (fun () -> \n//            l |> CMap.remove 5\n//        ) |> should be True\n//\n//        m |> Mod.force |> dictEqual [ 1, 6; ]\n//        \n//    [<Test>]\n//    let ``[AMap] test duplicates``() =\n//        let l = CMap.ofList [1,2]\n//        let r = CMap.ofList [1,3]\n//        let comp = AMap.union' [l;r]\n//        let m = comp |> AMap.toMod\n//\n//        let lookup = AMap.tryFindAll 1 comp\n//        let reader = lookup.GetReader()\n//        \n//        m |> Mod.force |> dictEqual [ 1, 2; 1, 3 ]\n//        let delta = reader.GetDelta() \n//        printfn \"delt %A\" delta\n//        delta |> should setEqual [ Add (2); Add (3)]\n//\n//        transact (fun () -> \n//            l |> CMap.remove 1 \n//        ) |> should be True\n//\n//        m |> Mod.force |> dictEqual [ 1, 3 ]\n//        reader.GetDelta() |> should setEqual [ Rem (2) ]\n//\n//        transact (fun () -> \n//            r |> CMap.remove 1 \n//        ) |> should be True\n//\n//        m |> Mod.force |> dictEqual [ ]\n//        reader.GetDelta() |> should setEqual [  Rem (3)]\n//\n//        transact (fun () -> \n//            r |> CMap.add 1 2\n//        ) \n//\n//        m |> Mod.force |> dictEqual [ 1,2 ]\n//        reader.GetDelta() |> should setEqual [ Add (2)]\n//\n//    [<Test>]\n//    let ``[CMap] test clear``() =\n//        let l = CMap.ofList [1,2]\n//        let r = l |> AMap.map (fun k v -> v * 2)\n//\n//        let m = r |> AMap.toMod\n//\n//        m |> Mod.force |> dictEqual [ 1,4 ]\n//\n//        transact (fun () ->\n//            l.Clear ()\n//        )\n//        \n//        m |> Mod.force |> dictEqual [ ]\n//\n//\n//\n//\n\n    [<Test>]\n    let ``[AMap] add/clear/evaluate``() =\n        \n        let m = CMap.empty<int,int>\n        let refSet = new HashSet<int*int>()\n        \n        let set = AMap.toASet m\n\n        let rnd = Random()\n\n        for i in 0..10000 do\n            if rnd.NextDouble() < 0.5 then\n                printfn \"add\"\n                refSet.Add((i,i)) |> ignore\n                transact(fun () -> m.[i] <- i)\n                printfn \" -> cnt=%d\" m.Count\n\n            if rnd.NextDouble() < 0.1 then\n                printfn \"clear\"\n                refSet.Clear()\n                transact(fun () -> m.Clear())\n                printfn \" -> cnt=%d\" m.Count\n                should equal 0 m.Count\n\n            if rnd.NextDouble() < 0.2 then\n                printfn \"eval\"\n                let test = ASet.toArray set\n                printfn \" -> map=%d set=%d\" m.Count test.Length\n                should equal test.Length m.Count\n                should equal test.Length refSet.Count\n                should setEqual test (Seq.toArray refSet) \n        ()\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/ASetFoldTest.csv",
    "content": "Date;ElapsedBuild;elapsedFold;reexElapsed;Memory\n16.12.2015 16:11:32;0.084533;1.626972;0.018623;;AsetBuild\n16.12.2015 16:13:24;0.084489;2.489830;0.020242;;ASetComb\n16.12.2015 16:17:22;0.082790;2.230165;0.017848;;ASetBuild correct\n16.12.2015 16:21:21;0.086101;2.026896;0.020969;;ASetComb bindReader\n16.12.2015 16:26:34;0.085224;1.867386;0.014720;;ASetComb smallUnion\n16.12.2015 16:35:59;0.084959;1.567857;0.018796;;wrong aset apply\n16.12.2015 16:36:52;0.081118;0.842385;0.015624;;as wrong and as good as fuck\n16.12.2015 16:51:48;0.080622;0.722214;0.015762;;\n16.12.2015 16:51:58;0.084662;0.718879;0.015260;;\n16.12.2015 16:54:16;0.083061;0.715398;0.015577;133082992\n16.12.2015 16:54:54;0.085431;0.767270;0.015704;126.744949\n16.12.2015 16:56:17;0.085591;2.025549;0.015283;237.493401\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/ASetPerformance.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen System.Diagnostics\nopen Aardvark.Base\n\nmodule ``performance tests`` =\n\n    let timed name f =\n        let sw = Stopwatch()\n        sw.Start()\n        let r = f()\n        sw.Stop()\n        let str = sprintf \"%s took: %.2fms\" name sw.Elapsed.TotalMilliseconds\n        Console.WriteLine str\n        r\n\n    [<Test>]\n    let ``[ASet] collect performance``() =\n        \n        let input = CSet.ofList []\n\n        let step (s : aset<'a>) =\n            s |> ASet.collect ASet.single\n\n        let rec stepN n s =\n            if n <= 0 then s\n            else stepN (n-1) (step s)\n            \n           \n\n        let test = stepN 100 input\n        let r = test.GetReader()\n        r.GetOperations() |> ignore\n\n\n        for i in 0..200 do\n            transact (fun () ->\n                input.UnionWith [i]\n            )\n            r.GetOperations() |> ignore\n\n        transact (fun () ->\n            input.Clear()\n        )\n        r.GetOperations() |> ignore\n  \n\n\n        let changeTime = Stopwatch()\n        let evalTime = Stopwatch()\n        let iter = 200\n        for i in 1..iter do\n            changeTime.Start()\n            transact (fun () ->\n                input.Add i |> ignore\n            )\n            changeTime.Stop()\n\n            evalTime.Start()\n            r.GetOperations() |> ignore\n            evalTime.Stop()\n\n        Console.WriteLine(\"Aset.collect change: {0:0.00000}ms eval: {1:0.00000}ms\", \n            changeTime.Elapsed.TotalMilliseconds / float iter, \n            evalTime.Elapsed.TotalMilliseconds / float iter)\n        ()\n\n    [<Test>]\n    let ``[ASet] map performance``() =\n        \n        let input = CSet.ofList []\n\n        let step (s : aset<'a>) =\n            s |> ASet.map id\n\n        let rec stepN n s =\n            if n <= 0 then s\n            else stepN (n-1) (step s)\n            \n                \n        let test = stepN 100 input\n        let r = test.GetReader()\n\n        r.GetOperations() |> ignore\n\n\n        for i in 0..400 do\n            transact (fun () ->\n                input.UnionWith [i]\n            )\n            r.GetOperations() |> ignore\n\n        transact (fun () ->\n            input.Clear()\n        )\n        r.GetOperations() |> ignore\n\n\n        let changeTime = Stopwatch()\n        let evalTime = Stopwatch()\n        let iter = 400\n        for i in 1..iter do\n            changeTime.Start()\n            transact (fun () ->\n                input.Add i |> ignore\n            )\n            changeTime.Stop()\n\n            evalTime.Start()\n            r.GetOperations() |> ignore\n            evalTime.Stop()\n\n        Console.WriteLine(\"ASet.map     change: {0:0.00000}ms eval: {1:0.00000}ms\", \n            changeTime.Elapsed.TotalMilliseconds / float iter, \n            evalTime.Elapsed.TotalMilliseconds / float iter)\n        ()\n\n    [<Test>]\n    let ``[Mod] bind performance``() =\n        \n        let input = Mod.init 0\n\n        let step (s : aval<'a>) =\n            s |> Mod.bind (Mod.constant)\n\n        let rec stepN n s =\n            if n <= 0 then s\n            else stepN (n-1) (step s)\n            \n                \n\n        let test = stepN 100 input\n        \n        Mod.force test |> ignore\n\n        for i in 0..100 do\n            transact (fun () ->\n                Mod.change input i\n            )\n            Mod.force test |> ignore\n\n        transact (fun () ->\n            Mod.change input -1\n        )\n        Mod.force test |> ignore\n\n\n        let changeTime = Stopwatch()\n        let evalTime = Stopwatch()\n        let iter = 1000\n        for i in 1..iter do\n            changeTime.Start()\n            transact (fun () ->\n                Mod.change input i\n            )\n            changeTime.Stop()\n\n            evalTime.Start()\n            Mod.force test |> ignore\n            evalTime.Stop()\n\n        Console.WriteLine(\"Mod.bind     change: {0:0.00000}ms eval: {1:0.00000}ms\", \n            changeTime.Elapsed.TotalMilliseconds / float iter, \n            evalTime.Elapsed.TotalMilliseconds / float iter)\n        ()\n\n    [<Test>]\n    let ``[Mod] map performance``() =\n        \n        let input = Mod.init 0\n\n        let step (s : aval<'a>) =\n            s |> Mod.map id\n\n        let rec stepN n s =\n            if n <= 0 then s\n            else stepN (n-1) (step s)\n            \n                \n\n        let test = stepN 100 input\n        \n        Mod.force test |> ignore\n\n        for i in 0..100 do\n            transact (fun () ->\n                Mod.change input i\n            )\n            Mod.force test |> ignore\n\n        transact (fun () ->\n            Mod.change input -1\n        )\n        Mod.force test |> ignore\n\n\n        let changeTime = Stopwatch()\n        let evalTime = Stopwatch()\n        let iter = 1000\n        for i in 1..iter do\n            changeTime.Start()\n            transact (fun () ->\n                Mod.change input i\n            )\n            changeTime.Stop()\n\n            evalTime.Start()\n            Mod.force test |> ignore\n            evalTime.Stop()\n\n        Console.WriteLine(\"Mod.map      change: {0:0.00000}ms eval: {1:0.00000}ms\", \n            changeTime.Elapsed.TotalMilliseconds / float iter, \n            evalTime.Elapsed.TotalMilliseconds / float iter)\n        ()\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/ASetPerformanceTests.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen Aardvark.Base.Incremental\n\nmodule TreeFlattenPerformance =\n\n    open System.Diagnostics\n    // let us create a function for measuring performance\n    let timed f = \n        let sw = Stopwatch()\n        sw.Start()\n        let r = f ()\n        sw.Stop()\n        r,sw.Elapsed.TotalSeconds\n\n        // Let us convert the tree to an adaptive one\n    type Tree<'a> = Node of left : aval<Tree<'a>> * right : aval<Tree<'a>> \n                  | Leaf of aval<'a>\n\n    // Let us define the adaptive version of leafNodes\n    let rec leafNodes t =\n        aset {\n            match t with \n             | Node(l,r) ->\n                let s = ASet.ofList [l;r] |> ASet.flattenM\n                for e in s do\n                    yield! leafNodes e // then recurse and use yield! \n                                   // since the rec call returns an aset\n             | Leaf v ->\n                yield v\n        } \n\n    let rec leafNodesComb t =\n        match t with\n         | Node(a,b) ->\n            let a = a |> ASet.bind leafNodesComb\n            let b = b |> ASet.bind leafNodesComb\n            ASet.union a b\n         | Leaf v -> ASet.single v\n\n    (* 2^15 leafs: 2^15 leaf values, \n    // 2^15 - 1 inner: 2 child Mod ptr, \n    2^16 bind reader\n    2^15 unionSmallReader\n    2^15+2^16 copy reader -> 3*2^15 copyreaders\n    per aset: 1899.128 (bytes)\n    per reader: 949.564 (bytes)\n    2kb * 3*2^15 -> 187 MB\n    *)\n\n    open System.Collections.Generic\n    open System.IO\n\n    let leaf v = Leaf (Mod.init v)\n    let node l r = Node (Mod.init l, Mod.init r)\n\n    let rec buildBigTree current = // 2^current inner nodes - 1, 2^current leafs\n        if current = 0 then \n            leaf 1, []\n        else\n            let l,lrefs = buildBigTree (current - 1) \n            let r,rrefs = buildBigTree (current - 1) \n            let lm = Mod.init l\n            let rm = Mod.init r\n            Node(lm, rm), lm::rm::(lrefs @ rrefs)\n\n    let rec extractLeafs t =    \n        seq {\n            match t with\n             | Node(l,r) ->\n                yield! extractLeafs (Mod.force l) \n                yield! extractLeafs (Mod.force r)\n             | Leaf v -> yield Mod.force v\n        }\n\n    let test () =\n\n        // test with 15, profile with 18\n        let (buildBigTree0,refs),elapsedBuild = timed (fun () -> buildBigTree 15)\n\n        let r,s = timed (fun () -> buildBigTree0 |> extractLeafs |> Seq.toArray)\n        printfn \"rebuild took: %As\" s\n    \n\n        let r = buildBigTree0 |> leafNodesComb\n\n        let reader = r |> ASet.toMod \n\n        let before = System.GC.GetTotalMemory(true)\n        let list,elapsedFold = timed (fun () -> reader.GetValue() )\n        //let l,elapsedPull = timed (fun () -> list |> Seq.toList |> List.map Mod.force)\n        let after = System.GC.GetTotalMemory(true)\n\n        printfn \"build took,%As\\nfold took: %As\" elapsedBuild elapsedFold \n\n        let last = refs |> List.rev |> List.head\n        let _,reexElapsed = timed (fun () -> transact (fun () -> Mod.change last (leaf 10)); reader.GetValue() )\n        printfn \"rexecution: %As\" reexElapsed\n\n        let measurement = sprintf \"%A;%f;%f;%f;%f\" System.DateTime.Now elapsedBuild elapsedFold reexElapsed (float (after-before) / float (1024*1024))\n        System.Console.Read() |> ignore\n        let perfName = Path.Combine(__SOURCE_DIRECTORY__, \"ASetFoldTest.csv\")\n        if File.Exists perfName then File.AppendAllLines(perfName,[|measurement|])\n        else File.WriteAllLines(perfName,[|\"Date;ElapsedBuild;elapsedFold;reexElapsed;Memory\";measurement|])\n            "
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/ASetTests.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen System\nopen System.Threading\nopen System.Threading.Tasks\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen Aardvark.Base\n\n\n[<AutoOpen>]\nmodule ``utils`` =\n\n    type Tree<'a> = Node of aset_check<Tree<'a>> | Leaf of aset_check<'a>\n\n    type DeltaList<'a>() =\n        let store = List<hdeltaset<'a>>()\n\n        member x.push (deltas : list<SetOperation<'a>>) =\n            store.Add (HDeltaSet.ofList deltas) \n\n        member x.read() =\n            let res = store |> Seq.toList\n            store.Clear()\n            res\n\nmodule ``collect tests`` =\n\n    [<Test>]\n    let ``[ASet] duplicate handling in collect``() =\n        let i0 = CSetCheck.ofList [1;2;3]\n        let i1 = CSetCheck.ofList [3;4;5]\n        let s = CSetCheck.ofList [i0 :> aset_check<_>]\n\n        // union {{1,2,3}}\n        let d = s |> ASetCheck.collect id\n        let r = d.GetReader()\n        r.GetDelta() |> should setEqual [Add 1; Add 2; Add 3]\n        r.Content |> should setEqual [1;2;3]\n        \n        // union {{1,2,3}, {3,4,5}} -> { Add 4, Add 5 }\n        transact (fun () ->\n            s.Add i1 |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Add 4; Add 5]\n        r.Content |> should setEqual [1;2;3;4;5]\n\n        // union {{3,4,5}} -> { Rem 1, Rem 2 }\n        transact (fun () ->\n            s.Remove i0 |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Rem 1; Rem 2]\n        r.Content |> should setEqual [3;4;5]\n\n        // union {{4,5}} -> { Rem 3 }\n        transact (fun () ->\n            i1.Remove 3 |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Rem 3]\n        r.Content |> should setEqual [4;5]\n\n        // union {{1,2,3}, {4,5}} -> { Add 1, Add 2, Add 3 }\n        transact (fun () ->\n            s.Add i0 |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Add 1; Add 2; Add 3]\n        r.Content |> should setEqual [1;2;3;4;5]\n\n        // union {{1,2,3}, {3,4,5}} -> { }\n        transact (fun () ->\n            i1.Add 3 |> should equal true\n        )\n        r.GetDelta() |> should setEqual List.empty<SetOperation<int>>\n        r.Content |> should setEqual [1;2;3;4;5]\n\n        // union {{1,2}, {3,4,5}} -> { }\n        transact (fun () ->\n            i0.Remove 3 |> should equal true\n        )\n        r.GetDelta() |> should setEqual List.empty<SetOperation<int>>\n        r.Content |> should setEqual [1;2;3;4;5]\n\n        // union {{1,2}, {4,5}} -> { Rem 3 }\n        transact (fun () ->\n            i1.Remove 3 |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Rem 3]\n        r.Content |> should setEqual [1;2;4;5]\n\n    [<Test>]\n    let ``[ASet] move test``() =\n        let c0 = CSetCheck.ofList [1]\n        let c1 = CSetCheck.ofList [2]\n\n        let s = CSetCheck.ofList[c0 :> aset_check<_>;c1 :> aset_check<_>]\n\n        let res = s |> ASetCheck.collect id\n        let r = res.GetReader()\n\n        // union {{1},{2}}\n        r.GetDelta() |> should setEqual [Add 1; Add 2]\n        r.Content |> should setEqual [1;2]\n\n        // union {{2},{1}}\n        transact (fun () ->\n            c0.Remove 1 |> should equal true\n            c1.Add 1 |> should equal true\n            c1.Remove 2 |> should equal true\n            c0.Add 2 |> should equal true\n        )\n        r.GetDelta() |> should setEqual List.empty<SetOperation<int>>\n        r.Content |> should setEqual [1;2]\n    \n[<AutoOpen>]\nmodule OtherASetTests =\n\n    [<Test>]\n    let ``[ASet] tree flatten test``() =\n        let rec flatten (t : Tree<'a>) =\n            match t with\n                | Node children -> children |> ASetCheck.collect (flatten)\n                | Leaf values -> values\n\n        let l2 = CSetCheck.ofList [1]\n        let l1 = CSetCheck.ofList [Leaf l2]\n        let l0 = CSetCheck.ofList [Node l1]\n        let t = Node (l0)\n\n        // Node { Node { Leaf { 1 } } }\n        let s = flatten t\n        let r = s.GetReader()\n        r.GetDelta() |> should setEqual [Add 1]\n        r.Content |> should setEqual [1]\n\n\n        // Node { Node { Leaf { 1, 3 }, Leaf { 2 } } }\n        let l22 = CSetCheck.ofList [2] :> aset_check<_> |> Leaf\n        transact (fun () ->\n            l1.Add l22 |> should equal true\n            l2.Add 3 |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Add 2; Add 3]\n        r.Content |> should setEqual [1; 2; 3]\n\n\n        // Node { Leaf { 1, 5 } , Node { Leaf { 1, 3 }, Leaf { 2 } } }\n        let l12 = CSetCheck.ofList [1;5] :> aset_check<_> |> Leaf\n        transact (fun () ->\n            l0.Add l12 |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Add 5]\n        r.Content |> should setEqual [1; 2; 3; 5]\n\n        // Node { Leaf { 1, 5 } , Node { Leaf { 2 } } }\n        transact (fun () ->\n            l1.Remove (Leaf l2) |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Rem 3]\n        r.Content |> should setEqual [1; 2; 5]\n\n        // Node { Leaf { 1, 5 } , Node { Leaf { 2 }, Node { Leaf { 17 } } } }\n        let n = Node (CSetCheck.ofList [Leaf (CSetCheck.ofList [17])])\n        transact (fun () ->\n            l1.Add n |> should equal true\n        )\n        r.GetDelta() |> should setEqual [Add 17]\n        r.Content |> should setEqual [1; 2; 5; 17]\n\n        ()\n\n    [<Test>]\n    let ``[ASet] callback test``() =\n\n        let deltas = DeltaList<int>()\n\n        let set = cset [1;2;3;4]\n        let m = set |> ASet.map (fun a -> 2 * a)\n        let s = m |> ASet.unsafeRegisterCallbackNoGcRoot deltas.push\n\n        // { 1, 2, 3, 4 } -> [Add 2; Add 4; Add 6; Add 8]\n        deltas.read() |> should deltaListEqual [HDeltaSet.ofList [Add 2; Add 4; Add 6; Add 8]]\n\n        // { 1, 3, 4, 5 } -> [Add 10; Rem 4]\n        transact (fun () ->\n            set.Add 5 |> ignore\n            set.Remove 2 |> ignore\n        )\n        deltas.read() |> should deltaListEqual [HDeltaSet.ofList [Rem 4; Add 10]]\n\n        // { 1, 4, 5, 6 } -> [Add 12; Rem 6]\n        transact (fun () ->\n            set.Add 6 |> ignore\n            set.Remove 3 |> ignore\n        )\n        deltas.read() |> should deltaListEqual [HDeltaSet.ofList [Rem 6; Add 12]]\n\n        // { 1, 4, 5, 6, 7 } -> [Add 14]\n        transact (fun () -> set.Add 7 |> ignore)\n\n        // { 1, 4, 5, 6, 7, 8 } -> [Add 16]\n        transact (fun () -> set.Add 8 |> ignore)\n        deltas.read() |> should deltaListEqual [HDeltaSet.ofList [Add 14]; HDeltaSet.ofList [Add 16]]\n\n\n        s.Dispose()\n\n        // { 1, 4, 5, 6, 7 } -> [] (unsubscribed)\n        transact (fun () -> set.Add 9 |> ignore)\n        deltas.read() |> should deltaListEqual ([] : list<hdeltaset<int>>)\n\n\n\n\n        ()\n\n    [<Test>]\n    let ``[ASet] callback changing other list``() =\n        \n        let set = cset [1;2]\n\n        let derived = set |> ASet.map (fun a -> 1 + a)\n        let inner = cset []\n\n        let s = derived |> ASet.unsafeRegisterCallbackKeepDisposable (fun delta ->\n            for d in delta do\n                match d with\n                    | Add(_,v) -> inner.Add v |> ignore\n                    | Rem(_,v) -> inner.Remove v |> ignore\n        )\n\n        \n        let dervivedInner = inner |> ASet.map id\n\n        let r = dervivedInner.GetReader()\n        r.GetOperations() |> should setEqual [Add 2; Add 3]\n\n        transact (fun () ->\n            set.Add 3 |> should equal true\n        )\n        r.GetOperations() |> should setEqual [Add 4]\n\n    [<Test>]\n    let ``[ASet] toMod triggering even with equal set referece``() =\n        \n        let s = CSet.empty\n\n        let triggerCount = ref 0\n        let hasTriggered() =\n            let c = !triggerCount\n            triggerCount := 0\n            c > 0\n\n        let leak = \n            s |> ASet.toMod |> Mod.unsafeRegisterCallbackNoGcRoot (fun set ->\n                triggerCount := !triggerCount + 1\n            )\n\n        hasTriggered() |> should equal true\n\n\n        transact(fun () ->\n            CSet.add 1 s |> ignore\n        )\n        hasTriggered() |> should equal true\n\n        transact(fun () ->\n            CSet.add 1 s |> ignore\n        )\n        hasTriggered() |> should equal false\n\n        transact(fun () ->\n            CSet.remove 1 s |> ignore\n        )\n        hasTriggered() |> should equal true\n\n\n        //pretend leak is used\n        ignore leak\n\n\n\n    [<Test>]\n    let ``[ASet] concurrency collect test``() =\n\n        let l = obj()\n        let set = CSet.empty\n        let derived = set |> ASet.collect id\n        use reader = derived.GetReader()\n        let numbers = [0..9999]\n\n        use sem = new SemaphoreSlim(0)\n        use cancel = new CancellationTokenSource()\n        let ct = cancel.Token\n\n        // pull from the system\n        Task.Factory.StartNew(fun () ->\n            while true do\n                ct.ThrowIfCancellationRequested()\n                let delta = reader.GetOperations()\n                //Thread.Sleep(10)\n                ()\n        ) |> ignore\n\n\n        // submit into the system\n        for n in numbers do\n            let s = ASet.single n\n            Task.Factory.StartNew(fun () ->\n                transact (fun () ->\n                    lock l (fun () ->\n                        set.Add(s) |> ignore\n                    )\n                )\n                sem.Release() |> ignore\n            ) |> ignore\n\n        // wait for all submissions to be done\n        for n in numbers do\n            sem.Wait()\n\n        cancel.Cancel()\n\n        reader.GetOperations() |> ignore\n\n\n        let content = reader.State |> Seq.toList |> List.sort\n\n        content |> should equal numbers\n\n    [<Test>]\n    let ``[ASet] concurrency multi reader test``() =\n\n        let l = obj()\n        let set = CSet.empty\n        let derived = set |> ASet.collect id\n        let numbers = [0..1000]\n\n        use sem = new SemaphoreSlim(0)\n        use cancel = new CancellationTokenSource()\n        let ct = cancel.Token\n\n\n        let readers = [1..3] |> List.map (fun _ -> derived.GetReader())\n        // pull from the system\n\n        for r in readers do\n            Task.Factory.StartNew(fun () ->\n                while true do\n                    ct.ThrowIfCancellationRequested()\n                    let delta = r.GetOperations()\n                    \n                    //if not (List.isEmpty delta) then\n                    //    Console.WriteLine(\"delta: {0}\", List.length delta)\n                    //Thread.Sleep(1)\n                    ()\n            ) |> ignore\n\n\n        // submit into the system\n        for n in numbers do\n            let s = ASet.single n\n            Task.Factory.StartNew(fun () ->\n                transact (fun () ->\n                    lock l (fun () ->\n                        set.Add(s) |> ignore\n                    )\n                )\n                sem.Release() |> ignore\n            ) |> ignore\n\n        // wait for all submissions to be done\n        for n in numbers do\n            sem.Wait()\n\n        cancel.Cancel()\n\n        for r in readers do\n            r.GetOperations() |> ignore\n            let content = r.State |> Seq.toList |> List.sort\n            content |> should equal numbers\n\n\n    type Leak(cnt : ref<int>) =\n        do cnt := !cnt + 1\n        override x.Finalize() = cnt := !cnt - 1\n\n    [<Test>]\n    [<Ignore(\"deadlock\")>]\n    let ``[ASet] memory leak test`` () =\n        let mutable independenSource = Mod.init 10\n        let cnt = ref 0\n        let f () =\n            let mutable leak = Leak(cnt)\n            let normalSource = CSet.ofList [ leak ]\n            let mapped = \n                normalSource \n                    |> ASet.map (fun l -> \n                        let m = independenSource |> Mod.map (fun i -> l)\n                        Mod.force m |> ignore\n                        m\n                    ) \n            mapped |> ASet.toArray |> ignore\n            transact (fun () -> normalSource |> CSet.remove leak |> should be True)\n            leak <- Unchecked.defaultof<_>\n        f()\n        GC.Collect ()\n        GC.WaitForPendingFinalizers()\n        !cnt |> should equal 0  \n        printfn \"%A\" independenSource \n        ()\n\n    [<Test>]\n    let ``[ASet] concurrency buffered reader test``() =\n\n        let l = obj()\n        let set = CSet.empty\n\n        let derived = set |> ASet.collect id |> ASet.map id // |> ASet.choose Some |> ASet.collect ASet.single |> ASet.collect ASet.single\n        use reader = derived.GetReader()\n        let numbers = [0..9999]\n\n        use sem = new SemaphoreSlim(0)\n        use cancel = new CancellationTokenSource()\n        let ct = cancel.Token\n\n        // pull from the system\n        Task.Factory.StartNew(fun () ->\n            while true do\n                ct.ThrowIfCancellationRequested()\n                let delta = reader.GetOperations()\n                //Thread.Sleep(10)\n                ()\n        ) |> ignore\n\n\n        // submit into the system\n        for n in numbers do\n            let s = ASet.single n\n            Task.Factory.StartNew(fun () ->\n                transact (fun () ->\n                    lock l (fun () ->\n                        set.Add(s) |> ignore\n                    )\n                )\n                sem.Release() |> ignore\n            ) |> ignore\n\n        // wait for all submissions to be done\n        for n in numbers do\n            sem.Wait()\n\n        cancel.Cancel()\n\n        reader.GetOperations() |> ignore\n\n\n        let content = reader.State |> Seq.toList |> List.sort\n\n        content |> should equal numbers\n\n\n    [<Test>]\n    let ``[ASet] concurrency overkill test``() =\n\n        let l = obj()\n        let set = CSet.empty\n\n        let derived = set |> ASet.collect id |> ASet.map id |> ASet.choose Some |> ASet.collect ASet.single |> ASet.collect ASet.single\n        let readers = [1..3] |> List.map (fun _ -> derived.GetReader())\n        let numbers = [0..1000]\n\n        use sem = new SemaphoreSlim(0)\n        use cancel = new CancellationTokenSource()\n        let ct = cancel.Token\n\n\n        for r in readers do\n            // pull from the system\n            Task.Factory.StartNew(fun () ->\n                while true do\n                    ct.ThrowIfCancellationRequested()\n                    let delta = r.GetOperations()\n                    Thread.Sleep(1)\n                    ()\n            , TaskCreationOptions.LongRunning) |> ignore\n\n\n        // submit into the system\n        for n in numbers do\n            let s = CSet.ofList [n]\n            Task.Factory.StartNew(fun () ->\n                transact (fun () ->\n                    lock l (fun () ->\n                        set.Add(s) |> ignore\n                    )\n                )\n                sem.Release() |> ignore\n            , TaskCreationOptions.LongRunning) |> ignore\n\n        // wait for all submissions to be done\n        for n in numbers do\n            sem.Wait()\n\n        cancel.Cancel()\n\n        for r in readers do\n            r.GetOperations() |> ignore\n\n\n        for r in readers do\n            let content = r.State |> Seq.toList |> List.sort\n\n            content |> should equal numbers\n\n    [<Test>]\n    let ``[ASet] stacked deltas test`` () =\n\n        let set = CSet.empty\n\n        let derived = set |> ASet.collect id |> ASet.map id |> ASet.choose Some |> ASet.collect ASet.single |> ASet.collect ASet.single\n\n        let readers = Array.init 10 (fun _ -> derived.GetReader())\n\n        for r in readers do\n            r.Update()\n            r.State |> Seq.toList |> should equal List.empty<int>\n\n\n        transact (fun () ->\n            \n            set.Add (ASet.ofList [1;3;4]) |> ignore\n            set.Add (ASet.single 2) |> ignore\n        )\n\n        for r in readers do\n            r.GetOperations() |> should setEqual [Add 1; Add 2; Add 3; Add 4]\n            r.State |> Seq.sort |> Seq.toList |> should equal [1; 2; 3; 4]\n\n\n        transact (fun () ->\n            \n            set.Add (ASet.ofList [5;6;7]) |> ignore\n            set.Add (ASet.single 8) |> ignore\n        )\n\n        for r in readers do\n            r.GetOperations() |> should setEqual [Add 5; Add 6; Add 7; Add 8]\n            r.State |> Seq.sort |> Seq.toList |> should equal [1; 2; 3; 4; 5; 6; 7; 8]\n\n\n\n\n\n        ()\n\n\n    [<Test>]\n    let ``[ASet] concurrent readers``() =\n\n        let l = obj()\n        let set = CSet.empty\n        let derived = set |> ASet.collect id\n        let numbers = [0..9999]\n\n        use cancel = new CancellationTokenSource()\n        let ct = cancel.Token\n\n\n        let readers = [|0..5|] |> Array.map (fun _ -> derived.GetReader())\n        // pull from the system\n\n        let lists = Array.init readers.Length (fun _ -> System.Collections.Generic.List())\n\n\n        for i in 0..readers.Length-1 do\n            let r = readers.[i]\n            let deltas = lists.[i]\n            Task.Factory.StartNew(fun () ->\n                while true do\n                    ct.ThrowIfCancellationRequested()\n                    let delta = r.GetOperations()\n\n\n                    deltas.AddRange delta\n                    if not (HDeltaSet.isEmpty delta) then\n                        Console.WriteLine(\"delta: {0}\", HDeltaSet.count delta)\n                    //Thread.Sleep(1)\n                    ()\n            ) |> ignore\n\n\n        // submit into the system\n        for n in numbers do\n            if n % 2 = 0 then\n                let s = ASet.single n\n                transact (fun () ->\n                    lock l (fun () ->\n                        set.Add(s) |> ignore\n                        set.Add(ASet.single (n+1)) |> ignore\n                    )\n                )\n\n        cancel.Cancel()\n\n        for i in 0..readers.Length-1 do\n            let r = readers.[i]\n            let deltas = lists.[i]\n            r.GetOperations() |> deltas.AddRange\n\n            let content = r.State |> Seq.toList |> List.sort\n            content |> should equal numbers\n\n            let deltas = deltas |> Seq.toList |> List.sort\n            deltas |> should equal (numbers |> List.map Add)\n\n\n    [<Test>]\n    let ``[CSet] delta elimination``() =\n        \n        let set = CSet.empty\n        let r = (set :> aset<_>).GetReader()\n\n        r.Update()\n\n        transact (fun () -> set.Add 1 |> ignore; set.Remove 1 |> ignore)\n\n        r.GetOperations() |> should setEqual List.empty<SetOperation<int>>\n        r.State.Count |> should equal 0\n\n    [<Test>]\n    let ``[ASet] mapM test duplicate``() =\n\n        let testSet = COrderedSet.ofSeq [ Mod.init 1; ]\n        \n        let rnd = new Random(1)\n\n        let op3 = testSet |> ASet.mapM (fun x -> Mod.constant(10))\n\n        let r = op3.GetReader()\n                \n        transact(fun () ->\n            testSet.Add (Mod.init 1) |> ignore)\n            \n        printfn \"%A\" (r.GetOperations())\n\n        transact(fun () ->    \n                    testSet.Clear())\n\n        printfn \"%A\" (r.GetOperations())\n\n\n    [<Test>]\n    let ``[ASet] finalizers working``() =\n        let input = CSet.ofList [1]\n\n        let getDerivedReader(input : aset<'a>) =\n            let r = input |> ASet.map id |> ASet.map id\n\n            r.GetReader()\n        let reader = getDerivedReader input\n        //let reader = set.GetReader()\n\n        System.GC.Collect()\n        System.GC.WaitForFullGCComplete() |> ignore\n        System.GC.Collect()\n        System.GC.WaitForFullGCComplete() |> ignore\n\n        reader.GetOperations() |> should setEqual [Add 1]\n        reader.Dispose()\n\n    [<Test>]\n    let ``[ASet] mapM test``() =\n        let stuff = CSet.ofList [ Mod.init(1); Mod.init(2); Mod.init(3); ]\n\n        let mapm = stuff |> ASet.mapM (fun i -> i :> aval<_>)\n\n        let r = mapm.GetReader()\n        r.GetOperations() |> should equal [Add(1); Add(2); Add(3)]\n\n        printfn \"%A\" (mapm |> ASet.toArray)\n\n        transact(fun () ->\n            Mod.change (stuff |> Seq.head) 99\n            stuff.Remove(stuff |> Seq.head) |> ignore\n            )\n\n        r.GetOperations() |> should equal [Rem(1)]\n\n        printfn \"%A\" (mapm |> ASet.toArray)\n        \n    [<Test>]\n    let ``[ASet] mapM test simulation``() =\n\n        let testSet = COrderedSet.ofSeq [ 1; 2; 3; ]\n\n        let op1 = testSet |> ASet.collect (fun x -> (x + 1) |> ASet.single)\n\n        let op2 = op1 |> ASet.choose (fun x -> Some x)\n\n        let rnd = new Random(2)\n\n        let op3 = op2 |> ASet.mapM (fun x -> Mod.constant (rnd.Next(10)))\n\n        let r = op3.GetReader()\n\n        let stuffList = new System.Collections.Generic.List<int>()\n        \n        for i in 0..10000 do\n            \n            if rnd.NextDouble() < 0.8 then\n                transact(fun () ->\n                    let e = stuffList.Count\n                    testSet.Add e |> ignore\n                    stuffList.Add e)\n\n            if rnd.NextDouble() < 0.1 then\n                if stuffList.Count > 0 then\n                    transact(fun () ->\n                        let e = stuffList.[rnd.Next(stuffList.Count)]\n                        stuffList.Remove(e) |> ignore\n                        testSet.Remove e |> ignore)\n\n            if rnd.NextDouble() < 0.3 then\n                if stuffList.Count > 0 then\n                    transact(fun () ->\n                        let e = stuffList.[stuffList.Count - 1]\n                        stuffList.RemoveAt(stuffList.Count - 1)\n                        testSet.Remove e |> ignore)\n\n            if rnd.NextDouble() < 0.05 then\n                transact(fun () ->    \n                    testSet.Clear())\n\n            if rnd.NextDouble() < 0.5 then\n                 printfn \"%A\" (r.GetOperations())\n\n    [<Test>]\n    let ``[ASet] flattenM test``() =\n        let stuff = CSet.ofList [ Mod.init(1) :> aval<_>; Mod.init(2) :> aval<_>; Mod.init(3) :> aval<_>; ]\n\n        let flatSet = stuff |> ASet.flattenM\n\n        let r = flatSet.GetReader()\n        r.GetOperations() |> should equal [Add(1); Add(2); Add(3)]\n\n        printfn \"%A\" (flatSet |> ASet.toArray)\n\n        transact(fun () ->\n            Mod.change (stuff |> Seq.head :?> ModRef<int>) 99\n            stuff.Remove(stuff |> Seq.head) |> ignore\n            )\n\n        r.GetOperations() |> should equal [Rem(1)]\n\n        printfn \"%A\" (flatSet |> ASet.toArray)\n\n        let stuff2 = stuff |> ASet.map (fun x -> x |> Mod.map (fun v -> v * 2))\n        let flatStuff2 = stuff2 |> ASet.flattenM\n\n        flatStuff2 |> ASet.toArray |> Array.length |> should equal 2\n\n        let sum = flatStuff2 |> ASet.sum |> Mod.force\n        sum |> should equal ((2 + 3) * 2)\n\n\n//\n//        \n//    module GCHelper =\n//\n//        let ``create, registerCallback and return and make sure that the stack frame dies``  () =\n//            let cset = CSet.ofList [ ]\n//            let mutable x = cset |> ASet.map ((*)2) |> ASet.filter ((>)(-1000)) |> ASet.groupBy id |> AMap.toASet\n//        \n//            let called = ref (-2)\n//            let y = ASet.unsafeRegisterCallbackNoGcRoot (fun _ -> called := !called + 1; ) x\n//\n//            x <- Unchecked.defaultof<_>\n//            called, cset, y\n//\n//        let ``create, registerCallbackAndKeepDisposable and return and make sure that the stack frame dies``  () =\n//            let cset = CSet.ofList [ ]\n//            let mutable x = cset |> ASet.map ((*)2) |> ASet.filter ((>)(-1000)) |> ASet.groupBy id |> AMap.toASet\n//        \n//            let called = ref (-2)\n//            let y = ASet.unsafeRegisterCallbackKeepDisposable (fun _ -> called := !called + 1; ) x\n//\n//            x <- Unchecked.defaultof<_>\n//            called, cset\n//\n//        let ``create, register marking and return and make sure that the stack frame dies`` () =\n//            let cset = CSet.ofList [ ]\n//            let mutable x = cset |> ASet.map ((*)2) |> ASet.filter ((>)(-1000)) |> ASet.groupBy id |> AMap.toASet\n//        \n//            let called = ref 0\n//            let reader = x.GetReader()\n//            let mutable y = reader.AddMarkingCallback (fun _ -> called := !called + 1; ) \n//\n//            y <- null\n//            x <- Unchecked.defaultof<_>\n//            called, cset, reader\n//            \n//\n//    [<Test>]\n//    let ``[ASet] registerCallback holds no gc root``() =\n//        let called, inputSet, d = GCHelper.``create, registerCallback and return and make sure that the stack frame dies`` ()\n//\n//        let cnt = 100\n//        for i in 0 .. cnt do\n//            transact (fun () -> CSet.add i inputSet |> ignore)\n//            //printfn \"should equal i=%d called=%d\" i !called\n//            !called |> should equal i\n//            Thread.Sleep 5\n//            if i % 10 = 0 then printfn \"done: %d/%d\" i cnt; GC.Collect()\n//\n//        printfn \"%A\" d\n//\n//    [<Test>]\n//    let ``[ASet] registerCallbackKeepDisposable holds gc root``() =\n//        let called, inputSet = GCHelper.``create, registerCallbackAndKeepDisposable and return and make sure that the stack frame dies`` ()\n//\n//        let cnt = 100\n//        for i in 0 .. cnt do\n//            transact (fun () -> CSet.add i inputSet |> ignore)\n//            //printfn \"should equal i=%d called=%d\" i !called\n//            should equal  i !called\n//            Thread.Sleep 5\n//            if i % 10 = 0 then printfn \"done: %d/%d\" i cnt; GC.Collect()\n//\n//    [<Test>]\n//    let ``[ASet] markingCallback holds gc root``() =\n//        let called, inputSet, reader = GCHelper.``create, register marking and return and make sure that the stack frame dies`` ()\n//\n//        let cnt = 100\n//        for i in 0 .. cnt do\n//            transact (fun () -> CSet.add i inputSet |> ignore)\n//            //printfn \"should equal i=%d called=%d\" i !called\n//            reader.GetDelta() |> ignore\n//            //printfn \"works? %A == %A\" i !called\n//            should equal  i !called\n//            GC.Collect()\n//            GC.WaitForPendingFinalizers()\n//            Thread.Sleep 5\n//            if i % 10 = 0 then printfn \"done: %d/%d\" i cnt; GC.Collect()\n//        printfn \"done\"\n//\n//\n//    [<Test>]\n//    let ``[ASet] Mod.async in asets is a memory leak?``() =\n//        \n//        let mutable t = Task.Factory.StartNew(fun () -> \n//            System.Threading.Thread.Sleep 10\n//            1\n//        )\n//\n//        let input = Mod.asyncTask t\n//        t <- null\n//\n//        let reult = \n//            aset {\n//                let! input = input\n//                match input with\n//                 | Some v -> \n//                    yield 2\n//                 | None -> ()\n//            }\n//        GC.Collect ()\n//        GC.WaitForPendingFinalizers()\n//        printfn \"ok\"\n//\n//    let private createLeakAndForgetAboutStackFrame () =\n//        let refCnt = ref 0\n//        let mutable l = Leak refCnt\n//\n//        Mod.init l, refCnt\n//\n//    [<Test>]\n//    let ``[ASet] ToMod is a memory leak due to inputs``() =\n//\n//        // situation: all is leaky. If i remove input tracking\n//        // leaks get less but still in the end pendinging delta processing\n//        // holds on to things. \n//        \n//        let mutable tup = createLeakAndForgetAboutStackFrame()\n//        let mutable spuriousInput = Weak(fst tup)\n//        let refCnt = snd tup\n//        let input = Mod.init (Some 1)\n//\n//        let result = \n//            aset {\n//                let! i = input\n//                match i with\n//                 | Some v -> \n//                    let! si = spuriousInput.Target\n//                    yield i\n//                 | None -> ()\n//            } |> ASet.toMod\n//        result |> Mod.force |> ignore\n//        result |> Mod.unsafeRegisterCallbackKeepDisposable (printfn \"%A\") |> ignore\n//        tup <- Unchecked.defaultof<_>\n//        transact (fun () -> Mod.change input None)\n//        should equal  1 !refCnt\n//        //result |> Mod.force |> ignore // without forcing this test fails\n//        //transact (fun () -> spuriousInput.Target.Value <- Leak (ref 0)) // this does not help\n//        GC.Collect()\n//        GC.WaitForPendingFinalizers()\n//        printfn \"now checkit \"\n//        should equal  0 !refCnt\n//\n//\n//    [<Test>]\n//    let ``[ASet] async registerCallback``() =\n//        \n//        let inputSet = CSet.ofSeq [0; 1; 2; 3]\n//        let adaptive = inputSet |> ASet.map ((*)2)\n//\n//        let mutable threadCount = 0\n//        let cnt = 1000\n//        for i in 0 .. cnt - 1 do\n//            Task.Factory.StartNew(fun () ->\n//                \n//                    //printfn \"thread In\";\n//                    let foo = adaptive |> ASet.unsafeRegisterCallbackNoGcRoot (fun d -> ())\n//                    //printfn \"thread Out\";\n//\n//                    System.Threading.Interlocked.Increment(&threadCount) |> ignore\n//                    \n//                    ()\n//                ) |> ignore\n//        ()\n//\n//        printfn \"all threads started....\"\n//\n//        let maxWait = 10000\n//        let mutable waitCnt = 0\n//        while (threadCount <> cnt && waitCnt < maxWait) do\n//            //printfn \"wating for threads to finish %d / %d\" threadCount cnt\n//            waitCnt <- waitCnt + 1\n//            Thread.Sleep(10)\n//\n//        let passed = threadCount = cnt || waitCnt < maxWait\n//        printfn \"passed %A\" passed\n//\n//        should equal passed true\n//\n//        ()\n//\n//    [<Test>]\n//    let ``[ASet] Mod.async supports zombie mods`` () =\n//        \n//        let AwaitTaskVoid : (Task -> Async<unit>) =\n//            Async.AwaitIAsyncResult >> Async.Ignore\n//\n//        let set = CSet.ofList [ 1 .. 100 ]\n//\n//        let result =\n//            aset {\n//                for x in set :> aset<_> do\n//                    let! r = \n//                        Mod.async <| \n//                            async {\n//                                let! _ = AwaitTaskVoid <| Task.Delay 1\n//                                return x * 10\n//                            }\n//                    yield r\n//            }\n//\n//        let result = ASet.map id result\n//\n//        let resultReader = result.GetReader()\n//\n//        let t = Task.Factory.StartNew(fun () ->\n//            for i in 101 .. 200 do\n//                transact (fun () -> CSet.add i set |> ignore)\n//                transact (fun () -> CSet.remove (i-100) set |> ignore)\n//                System.Threading.Thread.Sleep 2\n//                if i % 100 = 0 then resultReader.GetDelta() |> ignore\n//        )\n//        t.Wait()\n//\n//        //result |> ASet.unsafeRegisterCallbackKeepDisposable (printfn \"%A\") |> ignore\n//        ()\n//\n//\n//    [<Test>]\n//    let ``[ASet] task bindings``() =\n//        \n//        let start = new ManualResetEventSlim()\n//        let rand = Random()\n//        let tasks =\n//            Array.init 100 (fun i ->\n//                Async.StartAsTask <| \n//                    async {\n//                        let! _ =  Async.AwaitWaitHandle start.WaitHandle\n//                        let t = rand.Next(1000)\n//                        do! Async.Sleep t\n//                        return i\n//                    }\n//            )\n//\n//        let sets =\n//            tasks |> Array.map (fun t ->\n//                aset {\n//                    let! v = t\n//                    yield v\n//                }\n//            )\n//\n//        let all = sets |> ASet.union'\n//        let r = all.GetReader()\n//        start.Set()\n//\n//        while r.Content.Count < 100 do\n//            let deltas = r.GetDelta()\n//            ()\n//\n//        r.Content |> Seq.toList |> List.sort |> should equal [0..99]\n//\n//\nmodule ASetPerformance =\n    open System.Diagnostics\n\n\n    let printfn fmt = Printf.kprintf (fun str -> Console.WriteLine(\"{0}\", str)) fmt\n\n\n    type IProbe =\n        abstract member Start : unit -> unit\n        abstract member Stop : unit -> unit\n        \n    [<Struct>]\n    type DeltaTime(ticks : float) =\n        static let ticksPerSecond = float TimeSpan.TicksPerSecond\n        static let ticksPerMillisecond = float TimeSpan.TicksPerMillisecond\n        static let ticksPerMicrosecond = ticksPerMillisecond / 1000.0\n\n        member x.Ticks = ticks\n        member x.Seconds = ticks / ticksPerSecond\n        member x.Milliseconds = ticks / ticksPerMillisecond\n        member x.Microseconds = ticks / ticksPerMicrosecond\n\n\n        override x.ToString() =\n            if x.Seconds >= 0.2 then sprintf \"%.3fs\" x.Seconds\n            elif x.Milliseconds >= 2.0 then sprintf \"%.3fms\" x.Milliseconds\n            else sprintf \"%.1fµs\" x.Microseconds\n\n        static member (+) (l : DeltaTime, r : DeltaTime) =\n            DeltaTime(l.Ticks + r.Ticks)\n\n        static member (-) (l : DeltaTime, r : DeltaTime) =\n            DeltaTime(l.Ticks - r.Ticks)\n\n        static member (*) (l : DeltaTime, r : float) =\n            DeltaTime(l.Ticks * r)\n\n        static member (*) (l : float, r : DeltaTime) =\n            DeltaTime(l * r.Ticks)\n\n        static member (*) (l : DeltaTime, r : int) =\n            DeltaTime(l.Ticks * float r)\n\n        static member (*) (l : int, r : DeltaTime) =\n            DeltaTime(float l * r.Ticks)\n\n        static member (/) (l : DeltaTime, r : float) =\n            DeltaTime(l.Ticks / r)\n\n        static member (/) (l : DeltaTime, r : int) =\n            DeltaTime(l.Ticks / float r)\n\n    type TimeProbe() =\n        let sw = Stopwatch()\n\n        member x.Start() = sw.Start()\n        member x.Stop() = sw.Stop()\n        member x.Reset() = sw.Reset()\n        \n        member x.Elapsed = DeltaTime(float sw.Elapsed.Ticks)\n\n\n        interface IProbe with\n            member x.Start() = x.Start()\n            member x.Stop() = x.Stop()\n\n    module Probe =\n        let private current = new ThreadLocal<Option<IProbe>>(fun _ -> None)\n\n        let time() = TimeProbe()\n\n        let using (f : unit -> 'a) (x : IProbe) =\n            let old =\n                match current.Value with\n                    | Some c -> \n                        c.Stop()\n                        Some c\n                    | _ -> None\n            try\n                current.Value <- Some x\n                x.Start()\n                f()\n            finally\n                x.Stop()\n                match old with\n                    | Some o -> \n                        current.Value <- Some o\n                        o.Start()\n                    | _ ->\n                        current.Value <- None\n\n\n\n\n    [<Test>]\n    let ``[ASet Performance] map``() =\n        \n        //System.Runtime.GCSettings.LatencyMode <- Runtime.GCLatencyMode.Batch\n        //while true do\n            for s in 1000..1000..20000 do\n                System.GC.Collect()\n                System.GC.Collect()\n                System.GC.WaitForFullGCComplete() |> ignore\n                System.GC.WaitForFullGCComplete() |> ignore\n        \n                printfn \"size: %d\" s\n                let tTransact = Stopwatch()\n                let tSubmit = Stopwatch()\n                let tPull = Stopwatch()\n\n\n                let input = CSet.empty\n                let mapped = input |> ASet.map id\n                let r = mapped.GetReader()\n\n                transact (fun () ->\n                    CSet.add 0 input |> ignore\n                )\n                r.Update()\n\n                let cnt = s\n                for i in 1..cnt do\n                    tTransact.Start()\n                    transact (fun () ->\n                        tSubmit.Start()\n                        CSet.add i input |> ignore\n                        tSubmit.Stop()\n                    )\n                    tTransact.Stop()\n                \n                    tPull.Start()\n                    r.Update()\n                    tPull.Stop()\n\n                \n    //                System.GC.Collect()\n    //                System.GC.WaitForFullGCComplete() |> ignore\n\n                printfn \"  submit:   %A\" (tSubmit.MicroTime / cnt)\n                printfn \"  transact: %A\" ((tTransact.MicroTime - tSubmit.MicroTime) / cnt)\n                printfn \"  pull:     %A\" (tPull.MicroTime / cnt)\n    \n    [<Test>]\n    let ``[ASet Performance] collect``() =\n        \n        for s in 1000..1000..10000 do\n            System.GC.Collect()\n            System.GC.WaitForFullGCApproach() |> ignore\n        \n            printfn \"size: %d\" s\n            let tTransact = Stopwatch()\n            let tSubmit = Stopwatch()\n            let tPull = Stopwatch()\n\n\n            let input = CSet.empty\n            let mapped = input |> ASet.collect ASet.single\n            let r = mapped.GetReader()\n\n            transact (fun () ->\n                CSet.add 0 input |> ignore\n            )\n            r.Update()\n\n            let cnt = 10000\n            for i in 1..cnt do\n                tTransact.Start()\n                transact (fun () ->\n                    tSubmit.Start()\n                    CSet.add i input |> ignore\n                    tSubmit.Stop()\n                )\n                tTransact.Stop()\n\n                tPull.Start()\n                r.Update()\n                tPull.Stop()\n\n            printfn \"  submit:   %A\" (tSubmit.MicroTime / cnt)\n            printfn \"  transact: %A\" ((tTransact.MicroTime - tSubmit.MicroTime) / cnt)\n            printfn \"  pull:     %A\" (tPull.MicroTime / cnt)\n\n    [<Test>]\n    let ``[ASet] bind caching``() =\n\n        let set = cset [1;2;3;4;5;6;7;8;9]\n\n        let sel = set |> ASet.map (fun x -> printfn \"first map: %A\" x; x * 2)\n\n        let modul = Mod.init 3\n        \n        let tes = ASet.filter (fun n -> (n % 2) = 0) set\n\n        let b = modul |> ASet.bind (fun m -> sel |> ASet.filter (fun n -> (n % m) = 0))\n                \n        let b2 = b |> ASet.map (fun n -> printfn \"second map: %A\" n; n * 3)\n\n        let o = ASet.toMod b2\n\n        printfn \"initial\"\n\n        let force = o.GetValue()\n\n        printfn \"change modul\"\n\n        transact (fun () -> Mod.change modul 2)\n\n        let force = o.GetValue()\n\n        printfn \"done\"\n\n        ()\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/Aardvark.Base.Incremental.Tests.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <!--\n    Legacy incremental test suite.\n    This project is intentionally excluded from src/Aardvark.sln and the default\n    test.sh / test.cmd path. A retargeting attempt exposed broad incompatibilities\n    with older adaptive test helpers and APIs, so removal-or-migration is tracked\n    explicitly in GitHub issue #94 instead of being treated as part of the normal\n    green test suite.\n  -->\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>netcoreapp3.0</TargetFramework>\n\t<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup>\r\n\t<RunWorkingDirectory>$(OutputPath)\\netcoreapp3.0</RunWorkingDirectory>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"ModTests.fs\" />\r\n    <Compile Include=\"ASetTests.fs\" />\r\n    <Compile Include=\"AListTests.fs\" />\r\n    <Compile Include=\"AListTestsNew.fs\" />\r\n    <Compile Include=\"AMapTests.fs\" />\r\n    <Compile Include=\"ASetPerformance.fs\" />\r\n    <Compile Include=\"AgTests.fs\" />\r\n    <Compile Include=\"Performance.fs\" />\r\n    <Compile Include=\"UndoRedo.fs\" />\r\n    <Compile Include=\"SizeOfVariousAdaptiveObjects.fs\" />\r\n    <Compile Include=\"ASetPerformanceTests.fs\" />\r\n    <Compile Include=\"Mutables.fs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Essentials\\Aardvark.Base.Essentials.csproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Incremental\\Aardvark.Base.Incremental.fsproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/AgTests.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n//\n//open System\n//open System.Threading\n//open System.Threading.Tasks\n//open System.Collections\n//open System.Collections.Generic\n//open Aardvark.Base\n//open Aardvark.Base.Ag\n//open NUnit.Framework\n//open FsUnit\n//\n//module AgTests =\n//    \n//    type ITreeNode = interface end\n//    type TreeNode(name : string) =\n//        let mutable children = List.empty<TreeNode>\n//        interface ITreeNode\n//        member x.Children \n//            with get() = children\n//            and set value =\n//                children <- value\n//        member x.Name = name\n//        member x.Garbage = Array.zeroCreate(1 <<< 10)\n//\n//    type SynTreeNode(n : TreeNode, s : Ag.Scope) =\n//        member x.Node = n\n//        member x.Scope = s\n//        \n//    [<Semantic>]\n//    type AgTestSemantics() =\n//       \n//        //let fakeChild = obj()\n//\n//        member x.SynTree(node : TreeNode) : SynTreeNode[] =\n//            let sn = SynTreeNode(node, Ag.getContext())\n//            let mutable temp = sn.IntoArray()\n//            for x in node.Children do\n//                let sub : SynTreeNode[] = x?SynTree()\n//                temp <- Array.append temp sub\n//            temp\n//\n//        member x.FlattenTree(node : TreeNode) : TreeNode[] =\n//            let mutable temp = [ node ]\n//            for x in node.Children do\n//                let sub : TreeNode[] = x?FlattenTree()\n//                temp <- List.append temp (List.ofArray sub)\n//            temp |> List.toArray\n//\n//        member x.TraverseTree(node : TreeNode) : obj =\n//            for x in node.Children do\n//                let sub : obj = x?TraverseTree()\n//                ()\n//            obj()\n//\n//        member x.ConcatNameList(node : TreeNode) : list<string> =\n////            let fakeChildScope = Ag.getContext().GetChildScope(node)\n////            let mutable temp = [ fakeChildScope?ConcatName ]\n//            let mutable temp = [ node.AllChildren?ConcatName ]\n//            for x in node.Children do\n//                let sub : list<string> = x?ConcatNameList()\n//                temp <- List.append temp sub\n//            temp\n//\n//        member x.DoAnyObjectStuff(node : TreeNode) : string =\n//            let fakeChildScope = Ag.getContext().GetChildScope(node)\n//            let temp : string = fakeChildScope?ConcatName\n//            //let temp : string = node.AllChildren?ConcatName\n//            printfn \"concatName: %s\" temp\n//            for c in node.Children do\n//                let foo : string = c?DoAnyObjectStuff()\n//                ()\n//            temp\n//\n//        member x.ConcatName(r : Root<ITreeNode>) =\n//            x.AllChildren?ConcatName <- \"0\"\n//\n//        member x.ConcatName(node : TreeNode) : unit =\n//            x.AllChildren?ConcatName <- node?ConcatName + \"|\" + node.Name\n//\n//        member x.SynName(r : Root<ITreeNode>) : string =\n//            \"0\"\n//\n//        member x.SynName(n : SynTreeNode) : string =\n//            n.Node.Name\n//\n//        member x.ScopeName(n : TreeNode) : string =\n//            n.Name\n//\n////        member x.ConcatName(node : TreeNode) : string =\n////            node?ConcatNameInh + \"|\" + node.Name\n//\n//    let generateNewStuff (root : TreeNode, nodeRegistry : HashSet<WeakReference<TreeNode>>, gen : int) =\n//        let someNode = TreeNode (\"node\" + gen.ToString())\n//        let someOther = TreeNode (\"other\" + gen.ToString())\n//        let child = TreeNode (\"child\" + gen.ToString())\n//        let subchild = TreeNode (\"subchild\" + gen.ToString())\n//\n//        nodeRegistry.Add (WeakReference<TreeNode>(someNode)) |> ignore\n//        nodeRegistry.Add (WeakReference<TreeNode>(someOther)) |> ignore\n//        nodeRegistry.Add (WeakReference<TreeNode>(child)) |> ignore\n//        nodeRegistry.Add (WeakReference<TreeNode>(subchild)) |> ignore\n//\n//        child.Children <- [ subchild ]\n//\n//        someOther.Children <- [ child ]\n//\n//        root.Children <- [ someNode; someOther ]\n//\n//    [<Test>]\n//    let ``[Ag] AnyObjectTest``() =\n//\n//        Ag.initialize()\n//\n//        let mutable root = TreeNode \"root\"\n//        let nodeRegistry = new HashSet<WeakReference<TreeNode>>()\n//\n//        let rec printTree (n : TreeNode ) =\n//            printfn \"%s\" n.Name\n//            for c in n.Children do\n//                printTree c\n//\n//        let mutable root = TreeNode \"root\"\n//        for i in 1..10 do\n//        //let mutable i = 0\n//        //while true do\n//\n//            root <- TreeNode \"root\"\n//\n//            //i <- i + 1\n//            generateNewStuff(root, nodeRegistry, i)\n//\n//            //let foo = root?DoAnyObjectStuff()\n//            let st : SynTreeNode[] = root?SynTree()\n//            \n//            GC.Collect()\n////            Thread.Sleep(1000)\n////\n////            GC.AddMemoryPressure(1L <<< 20);\n////            GC.Collect()\n////            Thread.Sleep(1000)\n//\n//            for x in st do\n//                //printfn \"%s\" (Ag.useScope (x.Scope.GetChildScope x.Node) (fun () -> x?ConcatName))\n//                //printfn \"%s\" (x?SynName())\n//                printfn \"%s\" (x.Scope?ScopeName())\n//\n//            let aliveCount = nodeRegistry |> (Seq.filter (fun w ->  match w.TryGetTarget() with\n//                                                                    | (true, v) -> true\n//                                                                    | _ -> false)) |> Seq.toArray |> Array.length\n//\n//            //printfn \"Tree:\"\n//            //printTree root\n//\n//            //let flatTree : list<TreeNode> = root?FlattenTree()\n//            //let nameList : list<string> = root?ConcatNameList()\n//\n//            // do ag queries\n////            printfn \"flatNodeCount=%d\" flatTree.Length\n//            printfn \"generated=%d alive=%d\" nodeRegistry.Count aliveCount\n//\n//            ()\n//\n//        ()\n//        \n//    open Aardvark.Base.Incremental\n//    type IL = interface end\n//    type LNode(children : aset<IL>) =\n//        interface IL\n//        member x.Children = children\n//    type LLeaf(v : int) =\n//        interface IL\n//        member x.V = v\n//\n//    type Leak(cnt : ref<int>) =\n//        do cnt := !cnt + 1\n//        override x.Finalize() = cnt := !cnt - 1\n//\n//        \n//    let leakCnt = ref 0\n//\n//    type LS = Leak * Ag.Scope * aval<int>* int\n//\n//    [<Semantic>]\n//    type LSemantics() =\n//        \n//        member x.Flatten(n : LNode) : aset<Leak>=\n//            aset {\n//                for i in n.Children do\n//                    yield! i?Flatten()\n//            }\n//\n//        member x.Flatten(l : LLeaf) : aset<Leak> =\n//            aset {\n//                yield Leak leakCnt\n//            }\n//\n//        member x.Flatten2(n : LNode) : aset<LS>=\n//            aset {\n//                for i in n.Children do\n//                    let a : aval<int> = n?SomeInhValue\n//                    let! ab = a\n//                    printfn \"AB:%A\" ab\n//                    yield! i?Flatten2()\n//            }\n//\n//        member x.Flatten2(l : LLeaf) : aset<LS> =\n//            aset {\n//                let vm : aval<int> = l?SomeInhValue\n//                let! v = vm\n//                yield Leak leakCnt, Ag.getContext(), l?SomeInhValue, v\n//            }\n//\n//        member x.SomeInhValue(r : Root<IL>) = r.Child?SomeInhValue <- Mod.init 1\n//\n//    [<Test>]\n//    let ``[Ag] Leaky leaky test``() =\n//\n//        Ag.initialize()\n//\n//        let xs = CSet.ofList [ for i in 0 .. 10 do yield LLeaf i :> IL ]\n//        let root = LNode (xs :> aset<_>)\n//\n//        let leaks : aset<Leak> = root?Flatten()\n//        let r = leaks.GetReader()\n//        let run () =\n//            r.GetDelta() |> ignore\n//        \n//            !leakCnt |> should equal 11 \n//\n//            transact (fun () -> xs |> CSet.clear)\n//\n//            GC.Collect()\n//            GC.WaitForPendingFinalizers()\n//        \n//            r.GetDelta() |> printfn \"delta1: %A\"\n//\n//        run ()\n//\n//        GC.Collect()\n//        GC.WaitForPendingFinalizers()\n//\n//        !leakCnt |> should equal 0 \n//\n//        r.GetDelta() |> printfn \"delta2=%A\"\n//        printfn \"c=%A\" r.Content\n//        ()     \n//\n//\n//    [<Test>]\n//    let ``[Ag] Leaky leaky test 2``() =\n//\n//        Ag.initialize()\n//\n//        let xs = CSet.ofList [ for i in 0 .. 10 do yield LLeaf i :> IL ]\n//        let root = LNode (xs :> aset<_>)\n//\n//        let leaks : aset<LS> = root?Flatten2()\n//        let r = leaks.GetReader()\n//        let run () =\n//            r.GetDelta() |> ignore\n//        \n//            !leakCnt |> should equal 11 \n//\n//            transact (fun () -> xs |> CSet.clear)\n//\n//            GC.Collect()\n//            GC.WaitForPendingFinalizers()\n//        \n//            r.GetDelta() |> printfn \"delta1: %A\"\n//\n//        run ()\n//\n//        GC.Collect()\n//        GC.WaitForPendingFinalizers()\n//\n//        !leakCnt |> should equal 0 \n//\n//        r.GetDelta() |> printfn \"delta2=%A\"\n//        printfn \"c=%A\" r.Content\n//        ()    \n//        \n////    [<EntryPoint>]\n////    let main args =\n////        AnyObjectTest()\n////        0"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/ModTests.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen Aardvark.Base\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen System.Threading\nopen System.Threading.Tasks\nopen System.Runtime.CompilerServices\nopen System.Diagnostics\n\nmodule ``Basic Mod Tests`` =\n    open System.Collections.Generic\n    open System.Diagnostics\n\n    type ExecutionTracker() =\n        let ops = List<string>()\n\n        member x.push fmt =\n            Printf.kprintf (fun str -> ops.Add str) fmt\n\n        member x.read() =\n            let l = ops |> Seq.toList\n            ops.Clear()\n            l\n    \n    [<Test>]\n    let ``[Mod] basic map test``() =\n        let cell = Mod.init 1\n\n        let derived = cell |> Mod.map (fun a -> 2 * a)\n\n        derived.OutOfDate |> should equal true\n        derived |> Mod.force |> should equal 2\n\n        transact (fun () ->\n            Mod.change cell 2\n        )\n\n        derived.OutOfDate |> should equal true\n        derived |> Mod.force |> should equal 4\n\n    [<Test>]\n    let ``[Mod] constant map test``() =\n        let cell = Mod.constant 1\n\n        let derived = cell |> Mod.map (fun a -> 2 * a)\n\n        derived.IsConstant |> should equal true\n        derived |> Mod.force |> should equal 2\n\n\n    [<Test>]\n    let ``[Mod] basic map2 test``() =\n        let cell1 = Mod.init 1\n        let cell2 = Mod.init 1\n\n        let derived = Mod.map2 (fun a b -> a + b) cell1 cell2\n\n        derived.IsConstant |> should equal false\n        derived |> Mod.force |> should equal 2\n\n        transact (fun () ->\n            Mod.change cell1 2\n            Mod.change cell2 3\n        )\n\n        derived.OutOfDate |> should equal true\n        derived |> Mod.force |> should equal 5\n\n        transact (fun () ->\n            Mod.change cell1 1\n        )\n\n        derived.OutOfDate |> should equal true\n        derived |> Mod.force |> should equal 4\n\n        transact (fun () ->\n            Mod.change cell2 2\n        )\n\n        derived.OutOfDate |> should equal true\n        derived |> Mod.force |> should equal 3\n\n    [<Test>]\n    let ``[Mod] constant map2 test``() =\n        let c1 = Mod.constant 1\n        let c2 = Mod.constant 1\n        let m1 = Mod.init 1\n        let m2 = Mod.init 1\n\n        let derivedc = Mod.map2 (fun a b -> a + b) c1 c2\n        let derived1 = Mod.map2 (fun a b -> a + b) m1 c2\n        let derived2 = Mod.map2 (fun a b -> a + b) c1 m2\n\n        derivedc.IsConstant |> should equal true\n        derivedc |> Mod.force |> should equal 2\n\n        derived1.IsConstant |> should equal false\n        derived1 |> Mod.force |> should equal 2\n\n        derived2.IsConstant |> should equal false\n        derived2 |> Mod.force |> should equal 2\n\n\n        transact (fun () ->\n            Mod.change m1 2\n        )\n        derived1.OutOfDate |> should equal true\n        derived1 |> Mod.force |> should equal 3\n\n\n        transact (fun () ->\n            Mod.change m2 2\n        )\n        derived2.OutOfDate |> should equal true\n        derived2 |> Mod.force |> should equal 3\n\n    [<Test>]\n    let ``[Mod] transaction with onPush``() =\n        let a0 = Mod.init 0\n        let a1 = a0 |> Mod.onPush\n\n        let b0 = Mod.init 1\n        let b1 = b0 |> Mod.map (fun x -> \n            transact (fun () -> Mod.change a0 10)\n            x + a1.GetValue())\n        let b2 = b1 |> Mod.map (fun x -> x + 1 )\n        let b3 = b2 |> Mod.map (fun x -> x + 1)\n\n        b3.GetValue() |> should equal 13\n\n    [<Test>]\n    let ``[Mod] basic bind test``() =\n        let cell1 = Mod.init true\n        let cell2 = Mod.init 2\n        let cell3 = Mod.init 3\n\n        let derived =\n            Mod.bind (fun v -> if v then cell2 else cell3) cell1\n\n        derived.IsConstant |> should equal false\n        derived |> Mod.force |> should equal 2\n\n        transact (fun () ->\n            Mod.change cell1 false\n        )\n        derived.OutOfDate |> should equal true\n        derived |> Mod.force |> should equal 3\n\n        transact (fun () ->\n            Mod.change cell2 5\n        )\n        derived.OutOfDate |> should equal false\n\n\n        transact (fun () ->\n            Mod.change cell3 100\n        )\n        derived.OutOfDate |> should equal true\n        derived |> Mod.force |> should equal 100\n\n        transact (fun () ->\n            Mod.change cell1 true\n        )\n        derived.OutOfDate |> should equal true\n        derived |> Mod.force |> should equal 5\n\n    [<Test>]\n    [<Ignore(\"eager evaluation broken atm.\")>]\n    let ``[Mod] level changing bind``() =\n        let ex = ExecutionTracker()\n        let a = ModRef 1 \n        let a0 = a :> aval<_>\n        let a1 = a |> Mod.map id |> Mod.map id |> Mod.map id |> Mod.map (fun a -> ex.push \"%A * 2\" a; a * 2)\n        let c = ModRef true\n\n        let res = \n            c |> Mod.bind (fun c ->\n                ex.push \"bind: %A\" c\n                if c then a0\n                else a1\n            ) |> Mod.onPush\n\n        let res = res |> Mod.map (fun a -> ex.push \"cont\"; a)// |> Mod.always\n\n        let s = res |> Mod.unsafeRegisterCallbackNoGcRoot (fun v -> printfn \"cb: %A\" v)\n\n        res.GetValue() |> should equal 1\n        ex.read() |> should equal [\"bind: true\"; \"cont\"]\n\n        transact(fun () ->\n            a.Value <- 10\n            c.Value <- false\n        )\n\n        res.GetValue() |> should equal 20\n        \n        let read = ex.read()\n        read |> should equal [\"bind: false\"; \"10 * 2\"; \"cont\"]\n\n        s.Dispose()\n\n        transact(fun () ->\n            a.Value <- 20\n            c.Value <- true\n        )\n        res.GetValue() |> should equal 20\n        ex.read() |> should equal [\"bind: true\"]\n\n\n        ()\n\n    [<Test>]\n    [<Ignore(\"eager evaluation broken atm.\")>]\n    let ``[Mod] bind in bind``() =\n        let a = Mod.init false\n        let b = Mod.init 10\n        let c =\n            adaptive {\n                let! a = a \n                if a then\n                    let! b = b \n                    return b\n                else\n                    return 0\n            }\n\n        let c = c |> Mod.onPush\n\n        c.GetValue() |> should equal 0\n\n        transact(fun () -> Mod.change a true)\n        c.GetValue() |> should equal 10\n\n        transact(fun () -> Mod.change a false)\n        c.GetValue() |> should equal 0\n\n\n    [<Test>]\n    [<Ignore(\"takes way too long\")>]\n    let ``[Mod] mod concurrency test``() =\n        \n        let pulledValues = List<int>()\n\n        let input = Mod.init 1\n\n        let derived = input |> Mod.map id //|> Mod.map id \n\n        let sem = new SemaphoreSlim(0)\n        let trigger = new ManualResetEventSlim()\n        for t in 1..1000 do\n            Task.Factory.StartNew(fun () ->\n                trigger.Wait()\n                let v = derived |> Mod.force\n\n                lock pulledValues (fun () -> pulledValues.Add v)\n\n                sem.Release() |> ignore\n            ) |> ignore\n\n        trigger.Set()\n\n        for i in 1..1000 do\n            sem.Wait()\n\n\n        let values = pulledValues |> Seq.countBy id |> Map.ofSeq\n        System.Console.WriteLine(\"{0}\", sprintf \"%A\" values)\n        values |> Map.toSeq |> Seq.map fst |> should equal [1]\n        \n\n    [<Test>]\n    let ``[Mod] fan out, different eval strategy``() =\n\n        let input = Mod.init 10\n\n        let middle = input |> Mod.map id\n        let outputA = middle |> Mod.map id\n        let outputB = middle |> Mod.map id\n        let mutable marked = false\n        let v = outputB.AddMarkingCallback(fun () -> marked <- true)\n\n        outputB |> Mod.force |> ignore // comment and reactivate the one after transact\n        transact (fun () -> Mod.change input 11)\n        //outputB |> Mod.force |> ignore\n\n        outputA |> Mod.force |> should equal 11\n        marked |> should equal true\n        v.Dispose()\n\n\n    [<Test>]\n    [<Ignore(\"takes way too long\")>]\n    let ``[Mod] mod concurrency test super crazy callbacks``() =\n        \n        let pulledValues = List<int>()\n\n        let input = Mod.init 1\n        let middle = Mod.init 1\n\n        let derived = middle |> Mod.map id |> Mod.map (fun s -> Thread.Sleep 5; s) \n\n        let maxCnt = 400\n        let mutable abort = false\n        let mutable currentValue = 0\n        let inputThread = System.Threading.Thread(ThreadStart(fun _ ->\n            for i in 1 ..maxCnt do\n                let newValue = Interlocked.Increment(&currentValue)\n                transact (fun () -> Mod.change input newValue)\n            abort <- true\n        ))\n\n        let mutable marked = 0\n        let d = derived.AddMarkingCallback (fun _ -> Interlocked.Increment(&marked) |> ignore)\n\n        let collection = new System.Collections.Concurrent.BlockingCollection<int>()\n\n        let middle = System.Threading.Thread(ThreadStart(fun _ ->\n            let result = ref Unchecked.defaultof<_>\n            while collection.Count > 0 || not abort do\n                if collection.TryTake(result, 10) then\n                    transact (fun () -> Mod.change middle !result)\n        ))\n\n        input |> Mod.unsafeRegisterCallbackKeepDisposable (fun v ->\n             collection.Add v |> ignore\n        ) |> ignore\n\n        let mutable result = 0\n        let resultCb = derived |>  Mod.unsafeRegisterCallbackKeepDisposable (fun v ->\n            result <- v\n        )\n\n        let mutable r = 0\n        let puller = System.Threading.Thread(ThreadStart(fun _ ->\n            while not abort do\n                r <- derived |> Mod.force\n        ))\n\n\n        puller.Start()\n        middle.Start()\n        inputThread.Start()\n\n        inputThread.Join()\n        middle.Join()\n        puller.Join()\n\n        //collection.Count |> should equal 0\n        printfn \"awaited\"\n        result |> should equal currentValue\n        derived |> Mod.force |> should equal currentValue\n        printfn \"done\"\n\n\n    [<Test>]\n    let ``[Mod] DefaultingModRef can be set`` () =\n\n        let source = Mod.init 10\n        let x = Mod.initDefault source\n\n        x |> Mod.force |> should equal 10\n\n        transact (fun () -> Mod.change source 5)\n        x |> Mod.force |> should equal 5\n\n        transact (fun () -> Mod.change x 100)\n        x |> Mod.force |> should equal 100\n\n        transact (fun () -> Mod.change source 7)\n\n        x.OutOfDate |> should be False\n        x |> Mod.force |> should equal 100\n\n        transact (fun () -> x.Reset())\n        x |> Mod.force |> should equal 7\n\n\n\n    [<Test>]\n    let ``[Mod] bind bind`` () =\n\n        let otherInner = Mod.init 3\n        let inner = Mod.init 10\n        let x = Mod.init inner\n\n        let r = Mod.bind id x\n\n        r |> Mod.force |> should equal 10\n\n        transact (fun () -> Mod.change inner 11)\n        transact (fun () -> Mod.change x otherInner)\n\n        r |> Mod.force |> should equal 3\n\n\n//    [<Test>]\n//    let ``[VolatileCollection] memory test`` () =\n//        let count = 10000\n//        let arr = Array.zeroCreate count\n//        let objects = Array.init count (fun _ -> obj())\n//\n//        let before = System.GC.GetTotalMemory(true)\n//\n//        for i in 0..count-1 do\n//            arr.[i] <- VolatileCollection()\n//            ignore (arr.[i].Add(objects.[i]))\n//\n//        let after = System.GC.GetTotalMemory(true)\n//\n//        let mem = after - before\n//        let perInstance = float mem / float count\n//        System.Console.WriteLine(\"real:      {0}\", perInstance)\n//\n//        let dummy = arr |> Array.exists (fun c -> c.IsEmpty)\n//        if dummy then\n//            printfn \"asdlkasndksajmdlkasmdl\"\n\n    [<Test>]\n    let ``[Mod] deep hierarchy test`` () =\n\n        let root = Mod.init (Trafo3d.Translation(1.0, 2.0, 3.0))\n\n        let rec buildTree (m, l, c) =\n            \n            [for i in 1..c do\n                let x = Mod.init (Trafo3d.RotationX 360.0)\n                let foo = Mod.map2 ((*)) m x \n\n                if l < 2 then\n                    yield foo\n                else\n                    yield! buildTree(foo, l - 1, c)\n            ]\n\n        let tree = buildTree(root, 5, 5)\n\n        let sw = System.Diagnostics.Stopwatch()\n        \n        Log.line \"LeafCount=%A\" tree.Length\n\n        for j in 1..4 do\n            \n            sw.Restart()\n            transact(fun () -> \n                root.Value <- Trafo3d.RotationX (float j)\n                )\n            sw.Stop()\n            Log.line \"marking:  %As\" sw.Elapsed.TotalSeconds\n\n            sw.Restart()\n            for leaf in tree do\n                leaf.GetValue() |> ignore\n            sw.Stop()\n            Log.line \"evaluate:  %As\" sw.Elapsed.TotalSeconds\n            \n        ()\n\n        \n    [<Test>]\n    let ``[Mod] mapN test``() =\n        \n        let mods = Array.init 10 (fun i -> Mod.init i)\n\n        let sum = mods |> Mod.mapN Seq.sum\n        sum |> Mod.force |> should equal 45\n\n        transact (fun () -> Mod.change (mods.[0]) 100)\n        sum |> Mod.force |> should equal 145\n\n        transact (fun () -> Mod.change (mods.[5]) 100)\n        sum |> Mod.force |> should equal 240\n\n\n    [<Test>]\n    [<Ignore(\"takes way too long\")>]\n    let ``[Mod] consistent concurrency test``() =\n        let i = Mod.init 10\n\n        let a = i |> Mod.map id |> Mod.map id \n        let b = i |> Mod.map (fun a -> -a)\n        \n        let mutable values = 0\n        let apb = \n            Mod.map2 (fun a b -> \n                Interlocked.Increment(&values) |> ignore\n                a + b\n            ) a b\n        apb |> Mod.force |> ignore\n\n        values <- 0\n        let pullers = 1\n        let changers = 1\n\n        let countdown = new CountdownEvent(pullers)\n        let mutable iterations = 0\n        let mutable changes = 0\n        let mutable exn = None\n\n\n        let r = System.Random()\n        let changer = \n            async {\n                do! Async.SwitchToNewThread()\n\n                do\n                    while true do\n                        transact (fun () -> Mod.change i (r.Next()))\n                        Interlocked.Increment &changes |> ignore\n            }\n\n\n        let puller =\n            async {\n                let sw = System.Diagnostics.Stopwatch()\n                sw.Start()\n                do! Async.SwitchToNewThread()\n                do\n                    try\n                        while sw.Elapsed.TotalSeconds < 10.0 do\n                            if apb.OutOfDate then\n                                let r = Mod.force apb\n                                if r <> 0 then \n                                    exn <- Some (sprintf \"hate :%d\" iterations)\n                                    failwithf \"hate :%d\" iterations\n                                Interlocked.Increment(&iterations) |> ignore\n                    finally\n                        countdown.Signal() |> ignore\n            }\n\n\n        for i in 1 .. changers do \n            Async.Start changer\n\n        for i in 1 .. pullers do \n            Async.Start puller\n\n\n        countdown.Wait()\n\n        match exn with\n            | Some e -> failwith e\n            | None -> ()\n\n//        let sw = System.Diagnostics.Stopwatch()\n//        sw.Start()\n//        while sw.Elapsed.TotalSeconds < 10.0 do\n//            let r = Mod.force apb\n//            if r <> 0 then failwithf \"hate :%d\" iterations\n//            iterations <- iterations + 1\n//            if iterations % 10000 = 0 then\n//                let progress = sw.Elapsed.TotalSeconds / 10.0\n//                printfn \"%.2f%%\" (100.0 * progress)\n\n        printfn \"values: %A\" values\n        printfn \"done: %A\" iterations\n        printfn \"changes: %A\" changes\n    \n    [<Test>]\n    [<Ignore(\"takes way too long\")>]\n    let ``[Mod] consistent concurrency dirty set``() =\n        //let i = Mod.init 10\n\n        let set = CSet.empty\n        let v = set |> ASet.toMod |> Mod.map (fun s -> s.Count)\n\n        let a = v |> Mod.map id |> Mod.map id \n        let b = v |> Mod.map (fun a -> -a)\n\n        let r = System.Random()\n        let changer = \n            async {\n                do! Async.SwitchToNewThread()\n                while true do\n                    //do! Async.Sleep 0\n                    transact (fun () -> \n                        set.Add (r.Next()) |> ignore\n                        //Mod.change i (r.Next())\n                    )\n            }\n\n\n\n        for i in 0 .. 3 do \n            Async.Start changer\n\n        let mutable markings = 0\n        let ab =\n            let scratch = Dict<obj, HashSet<aval<int>>>()\n            let dirty = HashSet<aval<int>> [a;b]\n            let mutable initial = true\n            { new Mod.AbstractDirtyTrackingMod<aval<int>, int>() with\n                member x.Compute(token, dirty) =\n                    if initial then\n                        a.GetValue(token) |> ignore\n                        b.GetValue(token) |> ignore\n                        2\n                    else\n                        let cnt = dirty.Count\n                        for d in dirty do d.GetValue(token) |> ignore\n                        dirty.Count\n            }\n//\n//            { new Mod.AbstractMod<int>() with\n//                override x.InputChanged(t,i) =\n//                    match i with\n//                        | :? aval<int> as i ->\n//                            lock scratch (fun () ->\n//                                let set = scratch.GetOrCreate(t, fun t -> HashSet())\n//                                set.Add i |> ignore\n//                            )\n//                        | _ -> ()\n//\n//                override x.AllInputsProcessed(t) =\n//                    markings <- markings + 1\n//                    match lock scratch (fun () -> scratch.TryRemove t) with\n//                        | (true, s) -> dirty.UnionWith s\n//                        | _ -> ()\n//\n//                override x.Compute() =\n//                    let cnt = dirty.Count\n//                    for d in dirty do d.GetValue(x) |> ignore\n//                    dirty.Clear()\n//                    cnt\n//            }\n\n        let sw = System.Diagnostics.Stopwatch()\n        let mutable iterations = 0\n        sw.Start()\n        while sw.Elapsed.TotalSeconds < 10.0 do\n            //Thread.Sleep(1)\n            let r = Mod.force ab\n            if r <> 2 then failwithf \"hate : %d/%d\" r iterations\n            iterations <- iterations + 1\n\n        printfn \"markings: %A\" markings\n        printfn \"evals:    %A\" iterations\n\n    [<Test>]\n    [<Ignore(\"takes way too long\")>]\n    let ``[Mod] consistent concurrency multiple evaluators test``() =\n        let i = Mod.init 10\n\n        let a = i |> Mod.map id |> Mod.map id \n        let b = i |> Mod.map (fun a -> -a)\n\n        let apb = Mod.map2 (+) a b\n\n        let r = System.Random()\n\n        let mutable badResults = 0\n        let mutable evaluations = 0\n        let mutable changes = 0\n        let mutable running = true\n\n        let changers = 20\n        let evaluators = 5\n        let sem = new SemaphoreSlim(0)\n\n        let changer = \n            async {\n                do! Async.SwitchToNewThread()\n                while true do\n                    //do! Async.Sleep 0\n                    transact (fun () -> Mod.change i (r.Next()))\n                    Interlocked.Increment &changes |> ignore\n            }\n\n        let evaluator =\n            async {\n                do! Async.SwitchToNewThread()\n                while Volatile.Read(&running) do\n                    let r = Mod.force apb\n                    Interlocked.Increment &evaluations |> ignore\n                    if r <> 0 then Interlocked.Increment(&badResults) |> ignore\n                sem.Release() |> ignore\n            }\n\n        for i in 1 .. changers do \n            Async.Start changer\n\n        for i in 1 .. evaluators do \n            Async.Start evaluator\n\n\n\n        let sw = System.Diagnostics.Stopwatch()\n        sw.Start()\n        while sw.Elapsed.TotalSeconds < 10.0 do\n            Thread.Sleep(500)\n            let progress = sw.Elapsed.TotalSeconds / 10.0 |> clamp 0.0 1.0\n            printfn \"%.2f%%\" (100.0 * progress)\n\n            if badResults > 0 then\n                failwithf \"hate: %A\" badResults\n\n        running <- false\n        for i in 1..evaluators do sem.Wait()\n        \n        printfn \"evaluations: %A\" evaluations\n        printfn \"changes:     %A\" changes\n        if badResults > 0 then\n            failwithf \"hate: %A\" badResults\n             \n        printfn \"done\"\n\n    [<Test>]\n    [<Ignore(\"eager evaluation broken atm.\")>]\n    let ``[Mod] eager mod trigger test``() =\n        let a = Mod.init 1\n        let b = Mod.onPushCustomEq (fun x y -> y < 5) a\n        \n        let mutable count = 0\n        b |> Mod.unsafeRegisterCallbackKeepDisposable (fun v -> count <- count + 1; printfn \"%A\" v) |> ignore\n\n        should equal count 1\n\n        transact(fun () ->\n            Mod.change a 2)\n\n        should equal count 1\n                \n        transact(fun () ->\n            Mod.change a 3)\n\n        should equal count 1\n\n        transact(fun () ->\n            Mod.change a 4)\n\n        should equal count 1\n\n        transact(fun () ->\n            Mod.change a 5)\n\n        should equal count 2\n\n        ()\n\n\n    [<Test>]\n    [<Ignore(\"throwing exception during evaluation will result in deadlock atm.\")>]\n    let ``[Mod] exception during evaluation`` () =\n\n        let input = Mod.init 10\n        let input2 = Mod.init 2\n        \n        let res = input |> Mod.map (fun v -> if (v &&& 0x1) <> 0 then failwith \"does not divide by 2\" else v >>> 1)\n        //let res = res |> Mod.map (fun v -> v * 2)\n        \n        transact(fun () -> Mod.change input 6)\n        try\n            printfn \"%d\" (Mod.force res) \n        with e -> printfn \"%A\" e\n\n        transact(fun () -> Mod.change input 5)\n        try\n            printfn \"%d\" (Mod.force res)  // evaluation will throw exception -> AdaptiveObject locks are not release\n        with e -> printfn \"%A\" e\n\n        transact(fun () -> Mod.change input 4) // marking will block as AdaptiveObject locks have not been release due to exception\n        try\n            printfn \"%d\" (Mod.force res) \n        with e -> printfn \"%A\" e\n        \n\n    [<Test>]\n    [<Ignore(\"takes way too long\")>]\n    let ``[Mod] parallel consistent concurrency test``() =\n        let a = Mod.init 10\n        let b = Mod.init -10\n\n        let a' = a |> Mod.map id |> Mod.map id \n        let b' = b :> aval<_>\n\n        let apb = Mod.map2 (+) a' b'\n\n        let r = System.Random()\n        let changer = \n            async {\n                do! Async.SwitchToNewThread()\n                while true do\n                    //do! Async.Sleep 0\n                    let v = r.Next()\n\n                    transact (fun () -> \n                        Mod.change a v\n                        Mod.change b -v\n                    )\n            }\n\n\n\n        for i in 0 .. 3 do \n            Async.Start changer\n\n        let mutable finished = false\n        try\n            let sw = System.Diagnostics.Stopwatch()\n            let mutable iterations = 0\n            sw.Start()\n            while sw.Elapsed.TotalSeconds < 10.0 do\n                let r = Mod.force apb\n                if r <> 0 then failwithf \"hate :%d\" iterations\n                iterations <- iterations + 1\n            finished <- true\n        with _ ->\n            ()\n\n        if finished then failwith \"that was unexpected\"\n\n\n    [<Test>]\n    let ``[Mod] recursive transact`` () =\n\n        let x = Mod.init 10\n        let y = Mod.init 20\n\n        let cb = x |> Mod.unsafeRegisterCallbackNoGcRoot (fun v ->\n                        transact(fun () ->\n                            Mod.change y v))\n\n        transact(fun () ->\n            Mod.change x 5)\n\n        let t = getCurrentTransaction()\n\n        t.IsNone |> should be True\n        y |> Mod.force |> should equal 5\n\n        let cb2 = x |> Mod.unsafeRegisterCallbackNoGcRoot (fun v ->\n                        using(Aardvark.Base.Incremental.CSharp.Adaptive.Transaction) (fun _ -> Mod.change y v)\n                    )\n\n        using(Aardvark.Base.Incremental.CSharp.Adaptive.Transaction) (fun _ -> Mod.change x 3)\n\n        let t = getCurrentTransaction()\n\n        t.IsNone |> should be True\n        y |> Mod.force |> should equal 3\n\n    [<Test>]\n    let ``[Mod] eval and mark performance`` () =\n\n        let mutable garbage = [ ]\n\n        for j in 0..0 do // loop used for repeated testing in standalone executable\n            let mutable totalMarkTime = 0.0\n            let mutable totalEvalTime = 0.0\n            let iter = 1\n            for k in 1..iter do\n                //let root = Mod.init Trafo3d.Identity\n                let root = Mod.init 10\n                let mutable leafs = [ root :> aval<_> ]\n                let rnd = RandomSystem(1)\n\n                // configuration 1: average of 2-3 outputs, less depth\n                let depth = int (10.0 * pow 1.1 (float k))\n                let stdWidth = 1.2\n\n                // configuration 2: average 1-2 outputs, deeper tree\n                //let depth = int (10.0 * pow 1.5 (float k))\n                //let stdWidth = 0.3\n\n                let mutable nodeCount = 0\n                //Log.startTimed \"Create Tree: Depth=%d StdWidth=%.2f\" depth stdWidth\n                for i in 1..depth do\n                    let mutable nextLevel = [ ]\n                    for l in leafs do\n                        let subCnt = rnd.Gaussian(0.0, stdWidth)\n                        let refine = (abs subCnt) |> int\n                        for r in 0..refine do\n                            let n = l |> Mod.map (fun x -> x * 2)\n                            //let xx = Mod.init Trafo3d.Identity\n                            //let n = Mod.map2 (fun a b -> a * b) xx l\n                            nextLevel <- nextLevel @ [n]\n                            nodeCount <- nodeCount + 1 \n                        ()\n                    leafs <- nextLevel\n                //Log.stop \"\"\n\n                let leafCount = List.length leafs\n                let runs = 10 + 2000000 / nodeCount \n                let swMark = Stopwatch()\n                let swEval = Stopwatch()\n            \n                //Log.start \"Depth=%-3d StdWidth=%.2f Nodes/Leafs=%-11s\" depth stdWidth (sprintf \"%d/%d\" nodeCount leafCount)\n                for i in 1..runs do\n                    if i > 5 then swMark.Start()\n                    //transact(fun () -> Mod.change root (Trafo3d.Translation(V3d(i, i, i))))\n                    transact(fun () -> Mod.change root i)\n                    if i > 5 then swMark.Stop()\n\n                    if i > 5 then swEval.Start()\n                    for l in leafs do\n                        l |> Mod.force |> ignore\n                    if i > 5 then swEval.Stop()\n\n                let markTime = (float swMark.ElapsedTicks / float Stopwatch.Frequency)\n                let evalTime = (float swEval.ElapsedTicks / float Stopwatch.Frequency)\n                //Log.stop \" MarkTime=%.2fs EvalTime=%.2fs\" markTime evalTime\n\n                totalMarkTime <- totalMarkTime + markTime\n                totalEvalTime <- totalEvalTime + evalTime\n            \n                garbage <- garbage @ leafs\n\n            Log.line \"Total: MarkTime=%.2fs EvalTime=%.2fs\" totalMarkTime totalEvalTime\n        \n    [<Test>]\n    let ``[AdaptiveObject] callback dispose test``() =\n\n        let a = Mod.init true\n        let b = Mod.init 1\n\n        let mutable registered = false\n        let mutable rx = Unchecked.defaultof<System.IDisposable>\n        let cb1 = a |> Mod.unsafeRegisterCallbackNoGcRoot (fun x -> \n                            Log.line \"outer Callback %A\" x\n                            if rx <> null then\n                                rx.Dispose()\n                                rx <- null\n                                registered <- false\n\n                            if x then\n                                registered <- true\n                                rx <- b |> Mod.unsafeRegisterCallbackNoGcRoot(fun x -> Log.line \"inner Callback %d\" x; if not registered then failwith \"invoked disposed callback\")\n                        )\n\n        transact(fun () ->\n            b.Value <- 2)\n        \n        transact(fun () ->\n            a.Value <- false)\n\n        transact(fun () ->\n            a.Value <- true)\n\n        // this transaction will push both callbacks to marking queue  \n        // the evaluation will first trigger the outer callback then disposes the inner\n        // as it is already on the marking queue, it will be still invoked -> this should not happen\n        transact(fun () ->\n            a.Value <- false\n            b.Value <- 3)\n\n        ()\n\n    [<AutoOpen>]\n    module Validation =\n        open Aardvark.Base.Incremental.Validation\n        [<Test>]\n        let ``[Mod] DotSerialization`` () =\n            let x = Mod.init 10\n            let y = Mod.init 20\n            let z = Mod.map2 ((+)) x y\n            let path = System.IO.Path.GetTempFileName()\n            z.DumpDotFile (1000, path) |> ignore\n\n        [<Test>]\n        let ``[Mod] DgmlSerialization`` () =\n            let x = Mod.init 10\n            let y = Mod.init 20\n            let z = Mod.map2 ((+)) x y\n            let path = System.IO.Path.GetTempFileName()\n            z.DumpDgml (1000, path) |> ignore\n\n            \n    type RuntimeObject(name : string) =\n\n        static let mutable objCount = 0\n\n        let data = Array.zeroCreate 100000\n\n        let number = Interlocked.Increment &objCount\n\n        do\n            Log.line \"Create %s %d\" name number\n\n        static member ObjCount = objCount\n\n        member x.Name \n            with get() = name\n\n        override x.Finalize() = \n            Interlocked.Decrement &objCount |> ignore\n            Log.line \"Collect %s %d\" name number\n\n    [<Test>]\n    let ``[Caches] BinaryCache Mod``() =\n    \n        let a = Mod.init \"hugo\" \n\n        let funf : aval<string> -> aval<string> -> aval<string> = \n            //BinaryCache<aval<string>, aval<string>, aval<string>>(Mod.map2 (+)).Invoke\n            BinaryCache<aval<string>, aval<string>, aval<string>>(Mod.map2 (fun a b -> a + b)).Invoke\n\n        let sw = Stopwatch.StartNew()\n        let mutable i = 0\n        while sw.Elapsed.TotalSeconds < 10.0 do\n        \n            let temp = Mod.init (RuntimeObject(sprintf \"run-%i\" i))\n            let str = temp |> Mod.map (fun r -> r.Name)\n        \n            let cacheFun = funf str // creates function closure that holds str ? // function will be used as key ???\n            let result = cacheFun a\n\n            Log.line \"created: %s\" (result.GetValue())\n\n            i <- i + 1 \n\n            System.GC.Collect(3)\n            System.GC.WaitForFullGCComplete() |> ignore\n\n        System.GC.Collect(3)\n        System.GC.WaitForFullGCComplete() |> ignore\n\n        Log.line \"RuntimeObject Count=%d\" RuntimeObject.ObjCount\n\n        if RuntimeObject.ObjCount > 100 then\n            failwith \"leak\"\n\n\n    [<Test>]\n    let ``[Mod] Concurrency + callback + GetValue``() =\n        let a = Mod.init 4\n        let b = Mod.init 13\n\n        let comp = Mod.map2 (fun a b -> let mutable res = 0 \n                                        for i in 0..a do\n                                             for j in 0..b do\n                                                 res <- res ^^^ (i * j)\n                                        res) a b\n\n        // if marking callback is registered to \"comp\" instead of \"a\" it works fine\n        //  -> not allowed to do this !!\n        //let foo = a.AddMarkingCallback (fun () -> \n        //                                        let res = comp |> Mod.force\n        //                                        Log.line \"mark: %d\" res)\n\n        // safe way of realizing similar functionality\n        let foo = a.AddMarkingCallback (fun () -> \n                                Transaction.Running.Value.AddFinalizer(fun () ->\n                                                let res = comp |> Mod.force\n                                                Log.line \"mark: %d\" res))\n                                                \n        let mutable updateCount = 0\n        let mutable running = true\n\n        let readerThread = System.Threading.Thread(ThreadStart(fun _ ->\n            while running do\n                let res = comp |> Mod.force\n                Log.line \"read: %d\" res\n                ()\n            ()\n        ))\n\n        let updateThread = System.Threading.Thread(ThreadStart(fun _ ->\n            let rnd = System.Random(55)\n            while running do\n                transact(fun () ->\n                    a.Value <- rnd.Next(19999)\n                )\n                Log.line \"update\"\n                updateCount <- updateCount + 1\n            ()\n        ))\n\n        updateThread.Start()\n        readerThread.Start()\n\n        // run for 10 sec\n        let mutable lastCount = -1\n        Thread.Sleep(100)\n        for i in 0..100 do \n            if lastCount = updateCount then\n                failwith \"deadlock\"\n            lastCount <- updateCount\n            Thread.Sleep(100)\n        ()\n\n        running <- false"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/Mutables.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen System\nopen System.Threading\nopen System.Threading.Tasks\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen Aardvark.Base\nopen FsCheck\n\n\nmodule MutableTests =\n    let seed() = \n        let r = Random()\n        r.Next(), r.Next()\n\n    [<Test>]\n    let ``[MSet] update working as expected``() =\n        let generator = Arb.generate<Set<int>>\n        let seed = Random.StdGen (seed())\n\n        let dst = MSet.empty\n        let reader = (dst :> aset<_>).GetReader()\n\n        let generator = generator |> Gen.listOfLength 100\n\n        let sets = generator |> Gen.eval 100 seed\n        for set in sets do\n            transact (fun () -> dst.Value <- HSet.ofSeq set)\n            printfn \"%A\" set\n            let ops = reader.GetOperations()\n            let content = reader.State |> Set.ofSeq\n            content |> should equal set\n\n    [<Test>]\n    let ``[MList] update working as expected``() =\n        let generator = Arb.generate<list<int>>\n        let seed = Random.StdGen (seed())\n\n        let dst = MList.empty\n        let reader = (dst :> alist<_>).GetReader()\n\n        let generator = generator |> Gen.listOfLength 100\n\n        let sets = generator |> Gen.eval 100 seed\n        for set in sets do\n            transact (fun () -> dst.Value <- PList.ofList set)\n            printfn \"%A\" set\n            let ops = reader.GetOperations()\n            let content = reader.State |> PList.toList\n            content |> should equal set\n\n    [<Test>]\n    let ``[MMap] update working as expected``() =\n        let generator = Arb.generate<Map<int, int>>\n        let seed = Random.StdGen (seed())\n\n        let dst = MMap.empty\n        let reader = (dst :> amap<_,_>).GetReader()\n\n        let generator = generator |> Gen.listOfLength 100\n\n        let sets = generator |> Gen.eval 100 seed\n        for set in sets do\n            transact (fun () -> dst.Value <- HashMap.ofMap set)\n            printfn \"%A\" set\n            let ops = reader.GetOperations()\n            let content = reader.State |> HashMap.toMap\n            content |> should equal set"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/Performance.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen System.Diagnostics\nopen Aardvark.Base\n\nmodule SimplePerfTests =\n\n    [<Test>]\n    let ``[Mod Performance] deep bind``() =\n        \n        let mods = List.init 500 (fun i -> Mod.init i)\n\n        let rec flatten l =\n            match l with\n                | [] -> Mod.constant 0\n                | x::xs ->\n                    adaptive {\n                        let! v = x\n                        let! rest = flatten xs\n                        return v + rest\n                    }\n\n        let sum = flatten mods\n\n        // warmup\n        sum |> Mod.force |> ignore\n\n\n        let sum = flatten mods\n        let sw = Stopwatch()\n        sw.Start()\n        sum |> Mod.force |> ignore\n        sw.Stop()\n\n        Console.WriteLine(\"elapsed: {0}ms\", sw.Elapsed.TotalMilliseconds)\n\n\n    [<Test>]\n    let ``[Mod Performance] deep bind with fixed levels``() =\n        \n        let mods = List.init 500 (fun i -> Mod.init i)\n\n        let rec flatten level l =\n            match l with\n                | [] -> Mod.constant 0\n                | x::xs ->\n                    let res = \n                        adaptive {\n                            let! v = x\n                            let! rest = flatten (level - 3) xs\n                            return v + rest\n                        }\n                    res.Level <- level\n                    res\n\n        let sum = flatten 2000 mods\n\n        // warmup\n        sum |> Mod.force |> ignore\n\n\n        let sum = flatten 2000 mods\n        let sw = Stopwatch()\n        sw.Start()\n        sum |> Mod.force |> ignore\n        sw.Stop()\n\n        Console.WriteLine(\"elapsed: {0}ms\", sw.Elapsed.TotalMilliseconds)\n\n\n    [<Test>]\n    let ``[Mod Performance] flat sum``() =\n        \n        let mods = List.init 500 (fun i -> Mod.init i)\n\n        let sum = \n            Mod.custom (fun self ->\n                mods |> List.map (fun s -> s.GetValue self) |> List.sum\n            )\n        // warmup\n        sum |> Mod.force |> ignore\n\n\n        let sum = \n            Mod.custom (fun self ->\n                mods |> List.map (fun s -> s.GetValue self) |> List.sum\n            )\n\n        let sw = Stopwatch()\n        sw.Start()\n        sum |> Mod.force |> ignore\n        sw.Stop()\n\n        Console.WriteLine(\"elapsed: {0}ms\", sw.Elapsed.TotalMilliseconds)\n\n    [<Test>]\n    let ``[ASet] value dependent nop change``() =\n        let vt = Mod.init V3d.Zero\n        let iter = 100\n\n        let instances =\n            aset {\n                let mutable i = 0\n                for x in 0..20 do\n                    for y in 0..20 do\n                        for z in 0..20 do\n                            yield (i, fun (i : int) -> obj()) //V3i(x,y,z)\n                            i <- i + 1\n            }\n\n        let current = Array.zeroCreate (21*21*21)\n        let getLevel'(index : int, f) (m : V3d) =\n            let level = \n                match V3d.Distance(m, m) with   \n                    | v when v < 100.0 -> 0\n                    | _ -> 0\n\n            match current.[index] with\n                | Some(ol,ov) when ol = level -> ov\n                | _ ->\n                    let n = f level\n                    current.[index] <- Some(level, n)\n                    n\n\n        let getLevel (m : aval<V3d>) (f : int -> obj) =\n            let mutable current = None\n            m |> Mod.map (fun m ->\n                let level = \n                    match V3d.Distance(m, m) with   \n                        | v when v < 100.0 -> 0\n                        | _ -> 0\n\n                match current with\n                    | Some (l,v) when l = level ->\n                        v\n                    | _ ->\n                        let v = f level\n                        current <- Some (level, v)\n                        v\n            )\n\n        let final =\n            vt |> ASet.bind (fun v ->\n                instances |> ASet.map (fun a -> getLevel' a v)\n            )\n//\n//        let finaldsfsdf = \n//            instances |> ASet.mapM failwith \"\"//(getLevel vt)\n\n        let r = final.GetReader()\n\n        r.GetOperations() |> ignore\n\n        printf \"started incremental version: \"\n        let sw = Stopwatch()\n        sw.Start()\n        for i in 1..iter do\n            transact (fun () -> Mod.change vt (vt.Value + V3d.III))\n            r.GetOperations() |> ignore\n        sw.Stop()\n        printfn \"%.3fms\" (sw.Elapsed.TotalMilliseconds / float iter)\n        r.Dispose()\n\n\n        let creators = instances |> ASet.toArray |> Array.map snd\n        let final = cset()\n                \n\n        let r = (final :> aset<_>).GetReader()\n        printf \"started non-incremental version: \"\n        let sw = Stopwatch()\n        sw.Start()\n        let current = Array.zeroCreate creators.Length\n\n        let update (m : V3d) =\n            for i in 0..creators.Length-1 do\n                let level = \n                    match V3d.Distance(m, m) with   \n                        | v when v < 100.0 -> 0\n                        | _ -> 0\n\n                match current.[i] with\n                    | Some (l,v) ->\n                        if l <> level then\n                            let n = creators.[i] level\n                            current.[i] <- Some (level, n)\n                            transact (fun () -> \n                                CSet.remove v final |> ignore\n                                CSet.add n final |> ignore\n                            )\n\n                    | _ ->\n                        let v = creators.[i] level\n                        current.[i] <- Some (level, v)\n                        transact (fun () -> CSet.add v final |> ignore)\n\n        update V3d.Zero\n\n        for i in 1..iter do\n            let m = V3d(i,i,i)\n            update m\n            r.GetOperations() |> ignore\n\n        sw.Stop()\n        printfn \"%.3fms\" (sw.Elapsed.TotalMilliseconds / float iter)\n        r.Dispose()\n\n\n\n\n      \n\n\n\n\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/SizeOfVariousAdaptiveObjects.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen System\nopen System.Threading\nopen System.Threading.Tasks\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen Aardvark.Base\n\nmodule SizeOfAdaptiveObjects = \n\n    [<Test>]\n    let ``[MemoryOverhead] memory test`` () =\n\n        //total e9206773e69bfe38e737c434d5496c9d56332160: \n        //total: \n        //5346872L\n        //, per aset: \n        //5346.872\n        // (bytes)\n        let t = Thread(ThreadStart(fun () ->\n            \n            let mutable m = CSet.ofList [0] :> aset<_>\n\n            let empty = ASet.empty\n            m <- ASet.union m empty\n\n            let r = m.GetReader()\n            r.Update()\n\n            let mem = System.GC.GetTotalMemory(true)\n\n\n            //Console.ReadLine()\n            let size = 100\n\n            let empty = ASet.empty\n            for i in 1 .. size do\n                m <- ASet.union m empty\n\n            let r = m.GetReader()\n            r.Update()\n\n            //Console.ReadLine()\n\n            let memAfter = System.GC.GetTotalMemory(true)\n            let diff = memAfter - mem\n            let sizePerMod = float diff / float (2 * size)\n\n            printfn \"per aset: %A (bytes)\" (float diff / float size)\n            printfn \"per reader: %A (bytes)\" sizePerMod\n\n\n            r.Update()\n            r.Dispose()\n        ), 100000000)\n        t.Start()\n        t.Join()\n\n    [<Test>]\n    let ``[MemoryOverhead] adaptiveObject`` () =\n\n        let xs = Array.zeroCreate 100000\n        let mem = System.GC.GetTotalMemory(true)\n\n        for x in 0 .. xs.Length - 1 do\n            xs.[x] <- AdaptiveObject()\n\n        let after = System.GC.GetTotalMemory(true)\n        printfn \"%f bytes.\" (float (after - mem) / float xs.Length)\n        printfn \"%A\" (xs |> Array.sumBy (fun s -> uint64 s.Id))\n\n//    [<Test>]\n//    let ``[MemoryOverhead] copy reader`` () =\n//\n//        let xs = Array.zeroCreate 100000\n//        let mem = System.GC.GetTotalMemory(true)\n//\n//        for x in 0 .. xs.Length - 1 do\n//            xs.[x] <- new ASetReaders.CopyReader<int>(Unchecked.defaultof<_>)\n//\n//        let after = System.GC.GetTotalMemory(true)\n//        printfn \"%f bytes.\" (float (after - mem) / float xs.Length)\n//        printfn \"%A\" (xs |> Array.sumBy (fun s -> uint64 s.Id))\n\n    [<Test>]\n    let ``[MemoryOverhead] ReaderSize`` () =\n\n        let xs = Array.zeroCreate 100000\n        let mem = System.GC.GetTotalMemory(true)\n\n        for x in 0 .. xs.Length - 1 do\n            xs.[x] <- ASet.create(fun _ -> Unchecked.defaultof<ISetReader<int>>)\n\n        let after = System.GC.GetTotalMemory(true)\n        printfn \"%f bytes.\" (float (after - mem) / float xs.Length)\n        printfn \"%A\" (xs |> Array.sumBy (fun s -> 0.01 * float (s.GetHashCode())))"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/UndoRedo.fs",
    "content": "﻿namespace Aardvark.Base.Incremental.Tests\n\nopen System\nopen System.Collections\nopen System.Collections.Generic\nopen Aardvark.Base.Incremental\nopen NUnit.Framework\nopen FsUnit\nopen System.Diagnostics\nopen System.Linq\n\ntype ISnapshot =\n    abstract member Restore : unit -> unit\n\ntype ISnapshotThingy =\n    abstract member NewSnapshot : unit -> ISnapshot\n\ntype Snapshot(inner : list<ISnapshot>) =\n    member x.Restore() =\n        for i in inner do i.Restore()\n\n    member x.Count = List.length inner\n\n\n    interface ISnapshot with\n        member x.Restore() = x.Restore()\n\n\n\ntype UndoRedoScope() =\n    let dirty = HashSet<ISnapshotThingy>()\n\n    member x.Changed(o : ISnapshotThingy) =\n        lock dirty (fun () -> dirty.Add o |> ignore)\n\n    member x.Snapshot() =\n        let dirty =\n            lock dirty (fun () ->\n                let res = dirty.ToArray()\n                dirty.Clear()\n                res |> Array.toList\n            )\n\n        dirty\n            |> List.map (fun d -> d.NewSnapshot() )\n            |> Snapshot\n\n\n[<AutoOpen>]\nmodule ScopeExtensions =\n\n    type private UndoRedoModRef<'a>(scope : UndoRedoScope, value : 'a) =\n        inherit Mod.AbstractMod<'a>()\n\n        let mutable value = value\n\n        member x.Value\n            with get() = value\n            and set v =\n                value <- v\n                scope.Changed x\n                x.MarkOutdated()\n\n        member x.UnsafeCache\n            with get() = value\n            and set v = value <- v\n\n        interface ISnapshotThingy with\n            member x.NewSnapshot() =\n                let v = x.GetValue()\n                { new ISnapshot with member y.Restore() = x.Value <- v }\n    \n\n        interface IModRef<'a> with\n            member x.Value\n                with get() = value\n                and set v = x.Value <- v\n\n            member x.UnsafeCache\n                with get() = value\n                and set v = value <- v\n\n            [<CLIEvent>]\n            member x.Changed = Unchecked.defaultof<IEvent<_,_>>\n\n        override x.Compute(t) =\n            value\n\n\n    type UndoRedoScope with\n        member x.initMod (v : 'a) = \n            let res = UndoRedoModRef(x, v)\n            x.Changed res\n            res :> IModRef<_>\n\n\nmodule SimpleTest =\n    \n    let run() =\n        let scope = UndoRedoScope()\n\n        let m = scope.initMod 10\n        let d = m |> Mod.map (fun a -> a * 2)\n        d |> Mod.force |> printfn \"d = %A\"\n\n\n        // create a snapshot\n        let s0 = scope.Snapshot()\n\n\n        // change the system a little\n        transact (fun () ->\n            Mod.change m 1000\n        )\n        d |> Mod.force |> printfn \"d = %A\"\n\n        // create a second snapshot\n        let s1 = scope.Snapshot()\n\n        // restore s0\n        transact (fun () -> s0.Restore())\n        d |> Mod.force |> printfn \"s0: d = %A\"\n        \n        // restore s1\n        transact (fun () -> s1.Restore())\n        d |> Mod.force |> printfn \"s1: d = %A\"\n\n\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Incremental.Tests/paket.references",
    "content": "group Test\n\nFsUnit\nFsCheck\nFsCheck.NUnit\nFSharp.Core\nNUnit\nNUnit3TestAdapter\nMicrosoft.NET.Test.Sdk"
  },
  {
    "path": "src/Tests/Aardvark.Base.Runtime.Tests/Aardvark.Base.Runtime.Tests.fsproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <OutputType>Exe</OutputType>\r\n    <TargetFramework>net8.0</TargetFramework>\r\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\r\n    <WarnOn>3389;3390;3395</WarnOn>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup>\r\n\t<RunWorkingDirectory>$(OutputPath)\\net8.0</RunWorkingDirectory>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"CoderTests.fs\" />\r\n    <Compile Include=\"ReflectionTests.fs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Essentials\\Aardvark.Base.Essentials.csproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.FSharp\\Aardvark.Base.FSharp.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Incremental\\Aardvark.Base.Incremental.fsproj\" />\r\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Runtime\\Aardvark.Base.Runtime.fsproj\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>"
  },
  {
    "path": "src/Tests/Aardvark.Base.Runtime.Tests/CoderTests.fs",
    "content": "﻿namespace Aardvark.Base.Runtime.Tests\n\n#nowarn \"9\"\n#nowarn \"51\"\n\nopen System\nopen System.Threading\nopen System.Threading.Tasks\nopen System.Collections.Generic\nopen System.Runtime.InteropServices\nopen System.Runtime.CompilerServices\nopen Microsoft.FSharp.NativeInterop\nopen Aardvark.Base\nopen Aardvark.Base.Runtime\nopen NUnit.Framework\nopen FsUnit\nopen System.IO\n\n[<AbstractClass; Sealed; Extension>]\ntype CoderExtensions private() =\n    \n    [<Extension>]\n    static member Code(c : ICoder, value : ref<Symbol>) =\n        code {\n            if c.IsReading then \n                let! str = c.ReadString()\n                value := Symbol.Create str\n            else\n                do! c.WriteString (value.Value.ToString())\n        }\n\n    [<Extension>]\n    static member Code(c : ICoder, l : ref<list<'a>>) =\n        code {\n            if c.IsReading then\n                let! arr = c.ReadState()\n                l := Array.toList arr\n            else\n                let arr = !l |> List.toArray\n                do! c.WriteState arr\n        }\n\n\n\nmodule CoderTests =\n    open Aardvark.Base.Runtime.FieldCoders\n\n    do  let ass = typeof<CoderExtensions>.Assembly\n        System.Environment.CurrentDirectory <- System.IO.Path.GetDirectoryName(ass.Location)\n        IntrospectionProperties.CustomEntryAssembly <- ass\n        \n        Aardvark.Init()\n\n    [<AutoOpen>]\n    module Utilities = \n        type private ArrayCoerce<'a, 'b when 'a : unmanaged and 'b : unmanaged>() =\n            \n            static let sa = sizeof<'a>\n            static let sb = sizeof<'b>\n\n//            static let lengthOffset = sizeof<nativeint> |> nativeint\n//            static let typeOffset = 2n * lengthOffset\n\n            static let idb : nativeint =\n                let gc = GCHandle.Alloc(Array.zeroCreate<'b> 1, GCHandleType.Pinned)\n                try \n                    let ptr = gc.AddrOfPinnedObject() |> NativePtr.ofNativeInt\n                    NativePtr.get ptr -2\n                finally\n                    gc.Free()\n\n\n            static member Copy (a : 'a[]) : 'b[] =\n                let bytes = (a.Length * sa) |> nativeint\n                let gc = GCHandle.Alloc(a, GCHandleType.Pinned)\n                let res : 'b[] = Array.zeroCreate (int (bytes / nativeint sb))\n                let gcDst = GCHandle.Alloc(res, GCHandleType.Pinned)\n\n                try\n                    Marshal.Copy(gc.AddrOfPinnedObject(), gcDst.AddrOfPinnedObject(), bytes)\n                    res\n\n                finally\n                    gc.Free()\n                    gcDst.Free()\n\n            //static member CoercedApply (f : 'b[] -> 'r) (a : 'a[]) : 'r =\n                \n            //    let newLength = (a.Length * sa) / sb |> nativeint\n            //    let gc = GCHandle.Alloc(a, GCHandleType.Pinned)\n            //    try\n            //        let ptr = gc.AddrOfPinnedObject() |> NativePtr.ofNativeInt<nativeint>\n\n            //        let oldLength = NativePtr.get ptr -1\n            //        let oldType = NativePtr.get ptr -2\n\n            //        NativePtr.set ptr -1 newLength\n            //        NativePtr.set ptr -2 idb\n\n            //        try\n            //            a |> unbox<'b[]> |> f\n            //        finally\n            //            NativePtr.set ptr -1 oldLength\n            //            NativePtr.set ptr -2 oldType\n\n            //    finally\n            //        gc.Free()\n\n\n        type StreamWriter(stream : Stream) =\n            let bin = new BinaryWriter(stream)\n\n            member x.WritePrimitive (v : 'a) =\n                let mutable v = v\n                let ptr : byte[] = &&v |> NativePtr.cast |> NativePtr.toArray sizeof<'a>\n                code { return bin.Write(ptr) }\n\n            interface IWriter with\n                member x.WritePrimitive (v : 'a) = x.WritePrimitive v\n                member x.WritePrimitiveArray(data : 'a[]) =\n                    code {\n                        if isNull data then\n                            do! x.WritePrimitive -1\n                        else\n                            do! x.WritePrimitive data.Length\n                            let bytes = data |> ArrayCoerce<'a, byte>.Copy \n                            bin.Write bytes\n                    }\n\n                member x.WriteBool(v : bool) =\n                    code { return bin.Write(v) }\n\n                member x.WriteString (str : string) =\n                    code { return bin.Write(str) }\n\n            interface IReader with\n                member x.ReadPrimitive() = failwith \"[StreamWriter] cannot read\"\n                member x.ReadPrimitiveArray() = failwith \"[StreamWriter] cannot read\"\n                member x.ReadBool() = failwith \"[StreamWriter] cannot read\"\n                member x.ReadString() = failwith \"[StreamWriter] cannot read\"\n\n            interface ICoder with\n                member x.IsReading = false\n\n            interface IDisposable with\n                member x.Dispose() = bin.Dispose()\n\n        type StreamReader(stream : Stream) =\n            let bin = new BinaryReader(stream)\n\n            member x.ReadPrimitive () : Code<'a> =\n                let read() : 'a =\n                    let arr = bin.ReadBytes sizeof<'a>\n                    let gc = GCHandle.Alloc(arr, GCHandleType.Pinned)\n                    let res = gc.AddrOfPinnedObject() |> NativePtr.ofNativeInt |> NativePtr.read\n                    gc.Free()\n                    res\n\n                code { return read() }\n            interface IReader with\n                member x.ReadPrimitive () = x.ReadPrimitive()\n\n                member x.ReadPrimitiveArray() : Code<'a[]> =\n                    code {\n                        let! length = x.ReadPrimitive()\n                        if length < 0 then\n                            return null\n                        else\n                            let data = bin.ReadBytes(sizeof<'a> * length)\n                            return ArrayCoerce<byte, 'a>.Copy data\n                    }\n\n                member x.ReadBool() =\n                    code { return bin.ReadBoolean() }\n\n                member x.ReadString () =\n                    code { return bin.ReadString() }\n\n            interface IWriter with\n                member x.WritePrimitive _ = failwith \"[StreamReader] cannot write\"\n                member x.WritePrimitiveArray _ = failwith \"[StreamReader] cannot write\"\n                member x.WriteBool _ = failwith \"[StreamReader] cannot write\"\n                member x.WriteString _ = failwith \"[StreamReader] cannot write\"\n\n            interface ICoder with\n                member x.IsReading = true\n\n            interface IDisposable with\n                member x.Dispose() = bin.Dispose()\n\n        let toArray (v : 'a) =\n            use ms = new MemoryStream()\n            use w = new StreamWriter(ms)\n            w.Write(v)\n            ms.ToArray()\n\n        let ofArray<'a> (arr : byte[]) : 'a =\n            use r = new StreamReader(new MemoryStream(arr))\n            r.Read()\n\n        let roundtrip (value : 'a) : 'a =\n            let arr = toArray value\n            ofArray arr\n\n        let simpletest a =\n            let res = roundtrip a\n            res |> should equal a\n\n\n\n    [<Version(1)>]\n    type FieldCodedClass (a : int, b : float32) =\n\n        member x.A = a\n        member x.B = b\n\n        override x.ToString() =\n            sprintf \"{ A = %A; B = %A }\" a b\n\n        override x.GetHashCode() = HashCode.Combine(a.GetHashCode(), b.GetHashCode())\n\n        override x.Equals o =\n            match o with\n                | :? FieldCodedClass as o -> a = o.A && b = o.B\n                | _ -> false\n\n        member x.Coders(v : int) =\n            coders {\n                do! a <-> ValueCoder.coder\n\n                if v < 1 then\n                    do! b <-> (ValueCoder.coder<float> |>> float32)\n                else\n                    do! b <-> ValueCoder.coder\n            }\n\n    type ExtensionFieldCodedClass (a : int, b : float32) =\n        let mutable a = a\n        let mutable b = b\n        member x.A\n            with get() = a\n            and private set v = a <- v\n\n        member x.B\n            with get() = b\n            and private set v = b <- v\n\n        override x.ToString() =\n            sprintf \"{ A = %A; B = %A }\" a b\n\n        override x.GetHashCode() = HashCode.Combine(a.GetHashCode(), b.GetHashCode())\n\n        override x.Equals o =\n            match o with\n                | :? ExtensionFieldCodedClass as o -> a = o.A && b = o.B\n                | _ -> false\n\n\n    let mutable extensionInvoked = false\n\n    [<Extension>]\n    type FieldCodeableExtension private() =\n\n//        [<Extension; Version(1)>]\n//        static member Coders(x : ExtensionFieldCodedClass, v : int) =\n//            extensionInvoked <- true\n//            coders {\n//                do! x.A <-> ValueCoder.coder\n//\n//                if v < 1 then\n//                    do! x.B <-> (ValueCoder.coder<float> |>> float32)\n//                else\n//                    do! x.B <-> ValueCoder.coder\n//            }\n\n        [<Extension; Version(1)>]\n        static member Coders(x : ExtensionFieldCodedClass, v : int) =\n            extensionInvoked <- true\n            let a = typeof<ExtensionFieldCodedClass>.GetProperty(\"A\")\n            let b = typeof<ExtensionFieldCodedClass>.GetProperty(\"B\")\n            [\n                yield Property(a, ValueCoder.coder<int>)\n                if v < 1 then\n                    yield Skip(ValueCoder.coder<float>)\n                    yield Property(b, ValueCoder.coder<float> |>> float32)\n                else\n                    yield Property(b, ValueCoder.coder<float32>)\n                    \n            ]\n\n    type Class =\n        class\n            val mutable public ClassA : int\n            val mutable public ClassB : obj\n\n            new() = { ClassA = 0; ClassB = null }\n        end\n\n\n    type Struct =\n        struct\n            val mutable public StructA : int\n            val mutable public StructB : obj\n\n        end\n\n    type Rec =\n        {\n            RecA : int\n            RecB : obj\n        }\n\n    type BlittableStruct =\n        struct\n            val mutable public BlitA : int\n            val mutable public BlitB : float\n\n        end\n\n    type Union =\n        | A of int\n        | B of obj\n\n    type Enum32 =\n        | A = 1\n        | B = 2\n        | C = 3\n\n    type Enum8 =\n        | A = 1uy\n        | B = 2uy\n        | C = 3uy\n\n\n    [<Test>]\n    let ``[Coder] int``() = simpletest 1\n\n    [<Test>]\n    let ``[Coder] decimal``() = simpletest (1.0m)\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] Symbol``() = simpletest (Symbol.Create \"blabla\")\n\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] DateTime``() = simpletest DateTime.Now\n\n\n    [<Test>]\n    let ``[Coder] bool``() = simpletest true\n\n    [<Test>]\n    let ``[Coder] string``() = simpletest \"hi there äü³²#\"\n\n    [<Test>]\n    let ``[Coder] Type``() = simpletest typeof<int * obj * string>\n\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] Class``() =\n        let a = Class()\n        a.ClassB <- a\n        a.ClassA <- 10\n\n        let arr = toArray a\n        Log.line \"data: %A\" arr\n\n        let tmp = ofArray<Class> arr\n\n        tmp.ClassA |> should equal a.ClassA\n        tmp.ClassB == (tmp :> obj) |> should be True\n\n\n        ()\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] Struct (non blittable)``() =\n        let mutable input = Struct()\n        input.StructA <- 100\n        input.StructB <- \"hi there\"\n        let test = roundtrip input\n\n        test.StructA |> should equal input.StructA\n        test.StructB |> should equal input.StructB\n\n    [<Test>]\n    let ``[Coder] Struct (blittable)``() =\n        let mutable input = BlittableStruct()\n        input.BlitA <- 100\n        input.BlitB <- 10.0123456\n        let test = roundtrip input\n\n        test.BlitA |> should equal input.BlitA\n        test.BlitB |> should equal input.BlitB\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] Record``() =\n        let input = { RecA = 10; RecB = \"sadsad\" }\n        let test = roundtrip input\n        test |> should equal input\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] Union``() =\n        simpletest (A 10)\n        simpletest (B \"asdsad\")\n\n    [<Test>]\n    let ``[Coder] Enum32``() = simpletest Enum32.A\n\n    [<Test>]\n    let ``[Coder] Enum8``() = simpletest Enum8.A\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] Option<int>``() =\n        simpletest (Some 10)\n        simpletest Option<int>.None\n\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] Option<obj>``() =\n        simpletest (Some (10 :> obj))\n        simpletest Option<obj>.None\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] int * float * string``() =\n        simpletest (10, 10.012345, \"hi there\")\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] Choice<int, string>``() =\n        let input : Choice<int, string> = Choice1Of2 1\n        simpletest input\n        let input : Choice<int, string> = Choice2Of2 \"bla\"\n        simpletest input\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] list<int>``() =\n        simpletest [1;2;3;4;5]\n\n    [<Test>]\n    let ``[Coder] int[]``() =\n        simpletest [|1;2;3;4;5|]\n\n    [<Test>]\n    let ``[Coder] int[,]``() =\n        let input = Array2D.init 10 10 (fun x y -> x + y)\n        simpletest input\n\n    [<Test>]\n    let ``[Coder] int[] (null)``() =\n        let input : int[] = null\n        simpletest input\n\n    [<Test>]\n    let ``[Coder] int[,] (null)``() =\n        let input : int[,] = null\n        simpletest input\n\n    [<Test>]\n    let ``[Coder] int[,,]``() =\n        let input = Array3D.init 10 10 10 (fun x y z -> x + y + z)\n        simpletest input\n\n    [<Test>]\n    let ``[Coder] obj[]``() =\n        simpletest [|\"asdas\" :> obj; 2 :> obj; null; [|1;2;3|] :> obj|]\n\n\n\n\n    [<Test>]\n    let ``[Coder] write int read obj``() =\n        let arr = toArray 1\n        let o : obj = ofArray arr\n        o |> should equal 1\n\n    [<Test>]\n    let ``[Coder] write obj(int) read int``() =\n        let arr = toArray (1 :> obj)\n        let o : int = ofArray arr\n        o |> should equal 1\n\n    [<Test>]\n    let ``[Coder] write obj(float) read int``() =\n        let arr = toArray (1.0 :> obj)\n        try\n            let o : int = ofArray arr\n            failwith \"should not be able to read int when double was written\"\n        with _ ->\n            ()\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] FieldCodedClass``() =\n\n        let v0Stub = \n            [|\n                0x8Auy; 0x01uy; 0x41uy; 0x61uy; 0x72uy; 0x64uy; 0x76uy; 0x61uy; 0x72uy; 0x6Buy; 0x2Euy; 0x42uy; 0x61uy; 0x73uy; 0x65uy; 0x2Euy; 0x52uy; 0x75uy; 0x6Euy; 0x74uy; 0x69uy; 0x6Duy; 0x65uy; 0x2Euy; 0x54uy; 0x65uy; 0x73uy; 0x74uy; 0x73uy; 0x2Euy; 0x43uy; 0x6Fuy; 0x64uy; 0x65uy; 0x72uy; 0x54uy; 0x65uy; 0x73uy; 0x74uy; 0x73uy; 0x2Buy; 0x46uy; 0x69uy; 0x65uy; 0x6Cuy; 0x64uy; 0x43uy; 0x6Fuy; 0x64uy; 0x65uy; 0x64uy; 0x43uy; 0x6Cuy; 0x61uy; 0x73uy; 0x73uy; 0x2Cuy; 0x20uy; 0x41uy; 0x61uy; 0x72uy; 0x64uy; 0x76uy; 0x61uy; 0x72uy; 0x6Buy; 0x2Euy; 0x42uy; 0x61uy; 0x73uy; 0x65uy; 0x2Euy; 0x52uy; 0x75uy; 0x6Euy; 0x74uy; 0x69uy; 0x6Duy; 0x65uy; 0x2Euy; 0x54uy; 0x65uy; 0x73uy; 0x74uy; 0x73uy; 0x2Cuy; 0x20uy; 0x56uy; 0x65uy; 0x72uy; 0x73uy; 0x69uy; 0x6Fuy; 0x6Euy; 0x3Duy; 0x30uy; 0x2Euy; 0x30uy; 0x2Euy; 0x30uy; 0x2Euy; 0x30uy; 0x2Cuy; 0x20uy; 0x43uy; 0x75uy; 0x6Cuy; 0x74uy; 0x75uy; 0x72uy; 0x65uy; 0x3Duy; 0x6Euy; 0x65uy; 0x75uy; 0x74uy; 0x72uy; 0x61uy; 0x6Cuy; 0x2Cuy; 0x20uy; 0x50uy; 0x75uy; 0x62uy; 0x6Cuy; 0x69uy; 0x63uy; 0x4Buy; 0x65uy; 0x79uy; 0x54uy; 0x6Fuy; 0x6Buy; 0x65uy; 0x6Euy; 0x3Duy; 0x6Euy; 0x75uy; 0x6Cuy; 0x6Cuy; 0x4Cuy; 0xADuy; 0x59uy; 0x1Euy; 0x16uy; 0xE4uy; 0x5Auy; 0x47uy; 0xB7uy; 0xEAuy; 0xBBuy; 0x25uy; 0xBFuy; 0x8Auy; 0xC0uy; 0x44uy; 0x00uy; 0x00uy; 0x00uy; 0x00uy; \n                // int : 0x01uy; 0x00uy; 0x00uy; 0x00uy; \n                // float : 0x00uy; 0x00uy; 0x00uy; 0x00uy; 0x00uy; 0x00uy; 0xF0uy; 0x3Fuy\n            |]\n\n        let v0Data (a : int) (b : float) =\n            Array.concat [\n                v0Stub\n                BitConverter.GetBytes(a)\n                BitConverter.GetBytes(b)\n            ]\n\n        v0Data 1 1.0 |> ofArray<FieldCodedClass> |> should equal (FieldCodedClass(1, 1.0f))\n        v0Data 2 5.0 |> ofArray<FieldCodedClass> |> should equal (FieldCodedClass(2, 5.0f))\n\n        simpletest (FieldCodedClass(1, 1.0f))\n\n\n\n    [<Test>][<Ignore(\"Is this coder fully implemented, or just a sketch?\")>]\n    let ``[Coder] ExtensionFieldCodedClass``() =\n        simpletest (ExtensionFieldCodedClass(1, 1.0f))\n        extensionInvoked |> should be True\n\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Runtime.Tests/ReflectionTests.fs",
    "content": "﻿namespace Aardvark.Base.Runtime.Tests\n\nopen System\nopen System.Threading\nopen System.Threading.Tasks\nopen System.Collections.Generic\nopen System.Runtime.InteropServices\nopen System.Runtime.CompilerServices\nopen Microsoft.FSharp.NativeInterop\nopen Aardvark.Base\nopen Aardvark.Base.Runtime\nopen NUnit.Framework\nopen FsUnit\nopen System.IO\nopen FSharp.Data.Adaptive\n\n\nmodule RefelectionTests =\n    open Aardvark.Base.Runtime.FieldCoders\n    type private Marker = Marker\n\n    let mutable initialized = false\n\n    let init() =\n        if not initialized then\n            initialized <- true\n            let ass = typeof<Marker>.Assembly\n            Report.LogFileName <- System.IO.Path.GetDirectoryName(ass.Location) + \"\\\\Aardvark.log\"\n            System.Environment.CurrentDirectory <- System.IO.Path.GetDirectoryName(ass.Location)\n            IntrospectionProperties.CustomEntryAssembly <- ass\n            Aardvark.Init()\n\n    do init()\n\n    let tryUnify (decl : Type) (real : Type) =\n        match decl.TryUnifyWith real with\n            | Some ass ->\n                decl.GetGenericArguments() |> Array.map (fun a -> HashMap.find a ass) |> Array.toList |> Some\n            | None ->\n                None\n\n    let shouldWork (l : Option<list<Type>>) =\n        match l with\n            | Some [] -> ()\n            | _ -> failwithf \"got %A but expected %A\" l (Some [])\n\n\n\n    [<Test>]\n    let ``[Unification] seq<'a> <-> list<int>``() =\n        tryUnify typedefof<seq<_>> typeof<list<int>> |> should equal (Some [typeof<int>])\n\n    [<Test>]\n    let ``[Unification] seq<'a> <-> Dictionary<int, float>``() =\n        tryUnify typedefof<seq<_>> typeof<Dictionary<int, float>> |> should equal (Some [typeof<KeyValuePair<int, float>>])\n\n    [<Test>]\n    let ``[Unification] FSharpFunc<'a, 'b> <-> lambda``() =\n        let test = fun a -> a + 1\n        tryUnify typedefof<_ -> _> (test.GetType()) |> should equal (Some [typeof<int>; typeof<int>])\n\n    [<Test>]\n    let ``[Unification] IEnumerable <-> List<int>``() =\n        tryUnify typeof<System.Collections.IEnumerable> typeof<List<int>> |> shouldWork\n\n    [<Test>]\n    let ``[Unification] Array <-> int[]``() =\n        tryUnify typedefof<Array> typeof<int[]> |> shouldWork\n\n\n    [<Test>]\n    let ``[Extensions] List<int>.Set[int]``() =\n        init()\n        typeof<List<int>>.GetMethodOrExtension(\"Set\", [|typeof<int>|]) |> should not' (be Null)\n\n    [<Test>]\n    let ``[Extensions] int[].Set[int]``() =\n        init()\n        typeof<int[]>.GetMethodOrExtension(\"Set\", [|typeof<int>|]) |> should not' (be Null)\n\n    [<Test>]\n    let ``[Extensions] int[].SetByIndex[Func<int, int>]``() =\n        init()\n        typeof<int[]>.GetMethodOrExtension(\"SetByIndex\", [| typeof<Func<int, int>> |]) |> should not' (be Null)"
  },
  {
    "path": "src/Tests/Aardvark.Base.Runtime.Tests/paket.references",
    "content": "group Test\n\nFsUnit\nFSharp.Core\nNUnit\nNUnit3TestAdapter\nMicrosoft.NET.Test.Sdk"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Aardvark.Base.Tests.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project Sdk=\"Microsoft.NET.Sdk\">\r\n  <PropertyGroup>\r\n    <OutputType>Exe</OutputType>\r\n    <TargetFramework>net8.0</TargetFramework>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\r\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\r\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\r\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r\n  </PropertyGroup>\r\n  <PropertyGroup>\r\n\t<RunWorkingDirectory>$(OutputPath)\\net8.0</RunWorkingDirectory>\r\n\t<GenerateProgramFile>false</GenerateProgramFile>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Compile Remove=\"Properties\\**\" />\r\n    <EmbeddedResource Remove=\"Properties\\**\" />\r\n    <None Remove=\"Properties\\**\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\CodeGenerator\\CodeGenerator.csproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Essentials\\Aardvark.Base.Essentials.csproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Telemetry\\Aardvark.Base.Telemetry.csproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.IO\\Aardvark.Base.IO.csproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\n  </ItemGroup>\n  <ItemGroup>\r\n    <None Include=\"Trafos\\Scale3dTests.cs\" />\r\n  </ItemGroup>\r\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\r\n</Project>\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/AlgoDat/DictTests.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class DictTests : TestSuite\n    {\n        private sealed class CollisionKey : IEquatable<CollisionKey>\n        {\n            public int Id { get; }\n\n            public CollisionKey(int id)\n            {\n                Id = id;\n            }\n\n            public bool Equals(CollisionKey other)\n            {\n                return other != null && Id == other.Id;\n            }\n\n            public override bool Equals(object obj)\n            {\n                return obj is CollisionKey other && Equals(other);\n            }\n\n            public override int GetHashCode()\n            {\n                return 0;\n            }\n        }\n\n        public DictTests() : base() { }\n        public DictTests(TestSuite.Options options) : base(options) { }\n\n        string[] m_stringTable;\n        string[] m_stringSubsetTable;\n        Symbol[] m_symbolTable;\n        Symbol[] m_symbolSubsetTable;\n\n        [Test]\n        public void TestDict()\n        {\n            CreateStringTable(50000, 5000);\n            SymbolDictTestQuiet(5);\n            ConcurrentSymbolDictTestQuiet(5, 100);\n        }\n\n        public void Run() // performance tests\n        {\n            int count = 1000000;\n            // int growingRounds = 500;\n            int preallocRounds = 5000;\n\n            Report.Begin(\"Symbol Tests\");\n\n            CreateStringTable(count, count/50);\n\n            // SymbolDictInitializationTest();\n            // ConcurrentSymbolDictTest();\n            // SymbolDictTest();\n\n            foreach (var prealloc in new[] { false, true })\n            {\n                //StringTest(growingRounds, prealloc, false); DictStringTest(growingRounds, prealloc, false);\n                //SymbolTest(growingRounds, prealloc, false); DictSymbolTest(growingRounds, prealloc, false);\n                //SymbolDictTest(growingRounds, prealloc, false);\n\n                StringTest(preallocRounds, prealloc, true); DictStringTest(preallocRounds, prealloc, true);\n                SymbolTest(preallocRounds, prealloc, true); DictSymbolTest(preallocRounds, prealloc, true);\n                SymbolDictTest(preallocRounds, prealloc, true);\n            }\n            Report.End();\n\n        }\n\n        public void CreateStringTable(int count, int subCount)\n        {\n            Report.BeginTimed(\"creating string table with {0} items\", count);\n            m_stringTable = new string[count];\n            for (int i = 0; i < count; i++)\n                m_stringTable[i] = Guid.NewGuid().ToString();\n                                    //+ Guid.NewGuid().ToString() + Guid.NewGuid().ToString()\n                                    //+ Guid.NewGuid().ToString() + Guid.NewGuid().ToString();\n            Report.End();\n            m_symbolTable = new Symbol[count];\n            Report.BeginTimed(\"create symbols from strings\");\n            for (int i = 0; i < count; i++)\n                m_symbolTable[i] = Symbol.Create(m_stringTable[i]);\n            Report.End();\n            Report.BeginTimed(\"create subset\");\n            var rnd = new RandomSystem(13);\n            var perm = rnd.CreatePermutationArray(count);\n            m_stringSubsetTable = new string[subCount];\n            m_symbolSubsetTable = new Symbol[subCount];\n            for (int i = 0; i < subCount; i++)\n            {\n                m_stringSubsetTable[i] = m_stringTable[perm[i]];\n                m_symbolSubsetTable[i] = m_symbolTable[perm[i]];\n            }\n            Report.End();        \n        }\n\n        public void StringTest(int rounds, bool prealloc, bool subset)\n        {\n            var table = subset ? m_stringSubsetTable : m_stringTable;\n            int count = table.Length;\n            var map = prealloc ? new Dictionary<string, int>(count) : new Dictionary<string, int>();\n            Report.Begin(\"Dictionary<string, int>\" + (subset ? \" subset\" : \"\") +\n                       \" tests\" + (prealloc ? \" (prealloc)\" : \"\"));\n            Report.BeginTimed(\"create {0}\", count);\n            for (int i = 0; i < count; i++) map[table[i]] = i;\n            Report.End();\n            Test.Begin(\"access {0} x {1}\", count, rounds);\n            for (int j = 0; j < rounds; j++)\n                for (int i = 0; i < count; i++)\n                    Test.IsTrue(map[table[i]] == i);\n            Test.End();\n            Report.End();\n        }\n\n        public void SymbolTest(int rounds, bool prealloc, bool subset)\n        {\n            var table = subset ? m_symbolSubsetTable : m_symbolTable;\n            int count = table.Length;\n            var map = prealloc ? new Dictionary<Symbol, int>(count) : new Dictionary<Symbol, int>();\n            Report.Begin(\"Dictionary<Symbol, int>\" + (subset ? \" subset\" : \"\") +\n                       \" tests\" + (prealloc ? \" (prealloc)\" : \"\"));\n            Report.BeginTimed(\"create {0}\", count);\n            for (int i = 0; i < count; i++) map[table[i]] = i;\n            Report.End();\n            Test.Begin(\"access {0} x {1}\", count, rounds);\n            for (int j = 0; j < rounds; j++)\n                for (int i = 0; i < count; i++)\n                    Test.IsTrue(map[table[i]] == i);\n            Test.End();\n            Report.End();\n        }\n\n        public void DictStringTest(int rounds, bool prealloc, bool subset)\n        {\n            var table = subset ? m_stringSubsetTable : m_stringTable;\n            int count = table.Length;\n            Report.Begin(\"Dict<string, int>\" + (subset ? \" subset\" : \"\") +\n                       \" tests\" + (prealloc ? \" (prealloc)\" : \"\"));\n            var map = prealloc ? new Dict<string, int>(count) : new Dict<string, int>();\n            // map.Report = DictReport.Resize;\n            Report.BeginTimed(\"create {0}\", count);\n            for (int i = 0; i < count; i++) map[table[i]] = i;\n            Report.End();\n            Test.Begin(\"access {0} x {1}\", count, rounds);\n            for (int j = 0; j < rounds; j++)\n                for (int i = 0; i < count; i++)\n                    Test.IsTrue(map[table[i]] == i);\n            Test.End();\n            Report.End();\n        }\n\n        public void DictSymbolTest(int rounds, bool prealloc, bool subset)\n        {\n            var table = subset ? m_symbolSubsetTable : m_symbolTable;\n            int count = table.Length;\n            var map = prealloc ? new Dict<Symbol, int>(count) : new Dict<Symbol, int>();\n            // map.Report = DictReport.Resize;\n            Report.Begin(\"Dict<Symbol, int>\" + (subset ? \" subset\" : \"\") +\n                       \" tests\" + (prealloc ? \" (prealloc)\" : \"\"));\n            Report.BeginTimed(\"create {0}\", count);\n            for (int i = 0; i < count; i++) map[table[i]] = i;\n            Report.End();\n            Test.Begin(\"access {0} x {1}\", count, rounds);\n            for (int j = 0; j < rounds; j++)\n                for (int i = 0; i < count; i++)\n                    Test.IsTrue(map[table[i]] == i);\n            Test.End();\n            Report.End();\n        }\n\n        public void SymbolDictTest(int rounds, bool prealloc, bool subset)\n        {\n            var table = subset ? m_symbolSubsetTable : m_symbolTable;\n            int count = table.Length;\n            var map = prealloc ? new SymbolDict<int>(count) : new SymbolDict<int>();\n            // map.Report = DictReport.Resize;\n            Report.Begin(\"SymbolDict<int>\" + (subset ? \" subset\" : \"\") +\n                       \" tests\" + (prealloc ? \" (prealloc)\" : \"\"));\n            Report.BeginTimed(\"create {0}\", count);\n            for (int i = 0; i < count; i++) map[table[i]] = i;\n            Report.End();\n            Test.Begin(\"access {0} x {1}\", count, rounds);\n            for (int j = 0; j < rounds; j++)\n                for (int i = 0; i < count; i++)\n                    Test.IsTrue(map[table[i]] == i);\n            Test.End();\n            Report.End();\n        }\n\n        public void SymbolDictInitializationTest()\n        {\n            var map = new SymbolDict<int>()\n            {\n                { \"zero\", 0 },\n                { \"one\", 1 },\n                { \"two\", 2 },\n                { \"three\", 3 },\n                { \"four\", 4 },\n                { \"five\", 5 },\n                { \"six\", 6 },\n                { \"seven\", 7 },\n                { \"eight\", 8 },\n                { \"nine\", 9 },\n                { \"ten\", 10 },\n            };\n\n            foreach (var kvp in map)\n            {\n                Report.Line(\"{0}: {1}\", kvp.Key, kvp.Value);\n            }\n\n            var set = new SymbolSet()\n            {\n                \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\",\n                \"nine\", \"ten\",\n            };\n\n            foreach (var item in set)\n            {\n                Report.Line(\"{0}, \", item);\n            }\n\n        }\n\n        public void ConcurrentSymbolDictTest(int rounds, int tasks)\n        {\n            int count = m_stringTable.Length;\n            int block = count / tasks;\n\n            var rnd = new RandomSystem();\n            var perm = new int[count].SetByIndex(i => i);\n\n            var map = new SymbolDict<int>().AsConcurrent();\n            // var map = new FastConcurrentSymbolDict<int>();\n\n            Test.Begin(\"parallel adding and removing tests {0}\", count);\n            for (int r = 0; r < rounds; r++)\n            {\n                Test.Begin(\"round {0}\", r);\n                Test.Begin(\"adding in parallel\");\n                Parallel.For(0, tasks, t =>\n                {\n                    for (int i = t * block, e = i + block; i < e; i++)\n                        map[m_symbolTable[perm[i]]] = i;\n                });\n                Test.IsTrue(count == map.Count);\n                Test.End();\n\n                Test.Begin(\"checking\");\n                for (int i = 0; i < count; i++)\n                    Test.IsTrue(map[m_symbolTable[perm[i]]] == i);\n                Test.End();\n\n                rnd.Randomize(perm);\n                Test.Begin(\"removing in parallel\");\n                Parallel.For(0, tasks, t =>\n                {\n                    for (int i = t * block, e = i + block; i < e; i++)\n                        map.Remove(m_symbolTable[perm[i]]);\n                });\n                Test.IsTrue(map.Count == 0);\n                Test.End();\n                Test.End();\n            }\n            Test.End();\n        }\n\n        private void ConcurrentSymbolDictTestQuiet(int rounds, int tasks)\n        {\n            int count = m_stringTable.Length;\n            int block = count / tasks;\n\n            var rnd = new RandomSystem();\n            var perm = new int[count].SetByIndex(i => i);\n\n            var map = new SymbolDict<int>().AsConcurrent();\n\n            for (int r = 0; r < rounds; r++)\n            {\n                Parallel.For(0, tasks, t =>\n                {\n                    for (int i = t * block, e = i + block; i < e; i++)\n                        map[m_symbolTable[perm[i]]] = i;\n                });\n\n                Assert.That(map.Count, Is.EqualTo(count), $\"parallel add count mismatch in round {r}\");\n\n                for (int i = 0; i < count; i++)\n                {\n                    var key = m_symbolTable[perm[i]];\n                    Assert.That(map[key], Is.EqualTo(i), $\"parallel add/check mismatch in round {r} for key {key}\");\n                }\n\n                rnd.Randomize(perm);\n                Parallel.For(0, tasks, t =>\n                {\n                    for (int i = t * block, e = i + block; i < e; i++)\n                        map.Remove(m_symbolTable[perm[i]]);\n                });\n\n                Assert.That(map.Count, Is.Zero, $\"parallel remove count mismatch in round {r}\");\n            }\n        }\n\n        public void SymbolDictTest(int rounds)\n        {\n            int count = m_stringTable.Length;\n            int block = count / 10;\n\n            var rnd = new RandomSystem();\n            var perm = new int[count].SetByIndex(i => i);\n\n            var map = new SymbolDict<int>();\n\n            Test.Begin(\"adding removing tests {0}\", count);\n\n            for (int r = 0; r < rounds; r++)\n            {\n                Test.Begin(\"round {0}\", r);\n                int added = 0;\n                while (added < count)\n                {\n                    Test.Begin(\"adding 20%\");\n                    for (int i = added; i < added + 2 * block; i++)\n                        map[m_symbolTable[perm[i]]] = i;\n                    added += 2 * block;\n                    Test.IsTrue(added == map.Count);\n                    Test.End();\n\n                    if (added == count) break;\n\n                    Test.Begin(\"removing 10%\");\n                    for (int i = added - block; i < added; i++)\n                    {\n                        int index = 0;\n                        var removed = map.TryRemove(m_symbolTable[perm[i]], out index);\n                        Test.IsTrue(removed);\n                        Test.IsTrue(index == i);\n                    }\n                    added -= block;\n                    Test.IsTrue(added == map.Count);\n                    Test.End();\n                }\n                Test.Begin(\"checking\");\n                for (int i = 0; i < count; i++)\n                    Test.IsTrue(map[m_symbolTable[perm[i]]] == i);\n                Test.IsTrue(count == map.Count);\n                Test.End();\n                added += 2 * block;\n                rnd.Randomize(perm);\n                Test.Begin(\"removing 100%\");\n                if ((r & 1) == 0)\n                {\n                    for (int i = 0; i < count; i++)\n                    {\n                        int index = 0;\n                        bool removed = map.TryRemove(m_symbolTable[perm[i]], out index);\n                        Test.IsTrue(removed);\n                    }\n                }\n                else\n                    map.Clear();\n                Test.IsTrue(map.Count == 0);\n                Test.End();\n                Test.End();\n            }\n            Test.End();\n        }\n\n        private void SymbolDictTestQuiet(int rounds)\n        {\n            int count = m_stringTable.Length;\n            int block = count / 10;\n\n            var rnd = new RandomSystem();\n            var perm = new int[count].SetByIndex(i => i);\n\n            var map = new SymbolDict<int>();\n\n            for (int r = 0; r < rounds; r++)\n            {\n                int added = 0;\n                while (added < count)\n                {\n                    for (int i = added; i < added + 2 * block; i++)\n                        map[m_symbolTable[perm[i]]] = i;\n\n                    added += 2 * block;\n                    Assert.That(map.Count, Is.EqualTo(added), $\"count mismatch after add phase in round {r}\");\n\n                    if (added == count) break;\n\n                    for (int i = added - block; i < added; i++)\n                    {\n                        var key = m_symbolTable[perm[i]];\n                        Assert.That(map.TryRemove(key, out var index), Is.True, $\"remove failed in round {r} for key {key}\");\n                        Assert.That(index, Is.EqualTo(i), $\"removed value mismatch in round {r} for key {key}\");\n                    }\n\n                    added -= block;\n                    Assert.That(map.Count, Is.EqualTo(added), $\"count mismatch after partial remove in round {r}\");\n                }\n\n                for (int i = 0; i < count; i++)\n                {\n                    var key = m_symbolTable[perm[i]];\n                    Assert.That(map[key], Is.EqualTo(i), $\"lookup mismatch in round {r} for key {key}\");\n                }\n\n                Assert.That(map.Count, Is.EqualTo(count), $\"full map count mismatch in round {r}\");\n\n                added += 2 * block;\n                rnd.Randomize(perm);\n\n                if ((r & 1) == 0)\n                {\n                    for (int i = 0; i < count; i++)\n                    {\n                        var key = m_symbolTable[perm[i]];\n                        Assert.That(map.TryRemove(key, out _), Is.True, $\"final remove failed in round {r} for key {key}\");\n                    }\n                }\n                else\n                {\n                    map.Clear();\n                }\n\n                Assert.That(map.Count, Is.Zero, $\"map not empty after cleanup in round {r}\");\n            }\n        }\n\n        // should work / works if there are no collisions and resizes / works with Dictionary / would also work if GetOrCreate would be implemented as extension using ContainsKey + Add\n        // BUT it is implemented directly in Dict and at first makes the lookup with the given key and if not found invokes the createFunc \n        // it then does not check if the Dict has been modified during that and records the new entry to where it was previously tried be found -> location potentially invalid\n        // NOTE: This is pattern is useful in recursive conversion (with cache) of graph like data structures\n        [Test]\n        public void TestDictGetCreate()\n        {\n            var dict = new Dict<string, string>();\n\n            var rnd = new Random(0);\n\n            for (int i = 0; i < 1000; i++)\n            {\n                var key = i.ToString();\n                var test = dict.GetOrCreate(key, x =>\n                {\n                    var recKey = \"rec - \" + rnd.Next(0, 1000).ToString();\n                    var testRec = dict.GetOrCreate(recKey, r => r);\n\n                    Test.IsTrue(dict.ContainsKey(recKey), $\"dict.ContainsKey({recKey})\");\n                    Test.IsTrue(dict[testRec] == recKey, $\"dict[{testRec}] == {testRec}\");\n\n                    return x;\n                });\n\n                Test.IsTrue(dict.ContainsKey(key), $\"dict.ContainsKey({key})\");\n                var foo = dict[test];\n                Test.IsTrue(foo == key, $\"dict[{test}] == {key}\");\n            }\n        }\n\n        // Explicitly enumerates the sequences\n        public static IEnumerable<T> Enumerate<T>(IEnumerable<T> data)\n        {\n            var res = new List<T>();\n            foreach (T item in data) { res.Add(item); }\n            return res;\n        }\n\n        [Test]\n        public void ContainsKeyValueForCollisionChainEntry()\n        {\n            var dict = new Dict<CollisionKey, string>();\n            var firstKey = new CollisionKey(1);\n            var secondKey = new CollisionKey(2);\n\n            dict.Add(firstKey, \"first\");\n            dict.Add(secondKey, \"second\");\n\n            Assert.IsTrue(dict.Contains(firstKey, \"first\"));\n            Assert.IsTrue(dict.Contains(secondKey, \"second\"));\n            Assert.IsFalse(dict.Contains(secondKey, \"first\"));\n        }\n\n        [Test]\n        public void ContainsKeyValueForStackedDuplicateKeyEntry()\n        {\n            var dict = new Dict<CollisionKey, string>(stackDuplicateKeys: true);\n            var key = new CollisionKey(1);\n\n            dict.Add(key, \"first\");\n            dict.Add(key, \"second\");\n\n            Assert.IsTrue(dict.Contains(key, \"second\"));\n            Assert.IsTrue(dict.Contains(key, \"first\"));\n            Assert.IsFalse(dict.Contains(key, \"third\"));\n        }\n\n        [Test]\n        public void ContainsAndContainsValueSupportNullForOrdinaryStringEntries()\n        {\n            var dict = new Dict<string, string>();\n\n            dict.Add(\"ordinary\", null);\n\n            Assert.IsTrue(dict.Contains(\"ordinary\", null));\n            Assert.IsTrue(dict.ContainsValue(null));\n            Assert.IsFalse(dict.Contains(\"ordinary\", \"value\"));\n        }\n\n        [Test]\n        public void ContainsAndContainsValueSupportNullForCollisionChainStringEntries()\n        {\n            const int forcedHash = 1;\n            var dict = new Dict<string, string>();\n\n            dict.Add(\"first\", forcedHash, \"value\");\n            dict.Add(\"second\", forcedHash, null);\n\n            Assert.IsTrue(dict.Contains(\"second\", forcedHash, null));\n            Assert.IsTrue(dict.ContainsValue(null));\n            Assert.IsFalse(dict.Contains(\"second\", forcedHash, \"value\"));\n        }\n\n        [Test]\n        public void ContainsAndContainsValueSupportNullForStackedDuplicateStringEntries()\n        {\n            var dict = new Dict<string, string>(stackDuplicateKeys: true);\n\n            dict.Add(\"duplicate\", \"value\");\n            dict.Add(\"duplicate\", null);\n\n            Assert.IsTrue(dict.Contains(\"duplicate\", null));\n            Assert.IsTrue(dict.ContainsValue(null));\n            Assert.IsFalse(dict.Contains(\"duplicate\", \"missing\"));\n        }\n\n        [Test]\n        public void SingleEntryDictSetterUpdatesExistingKeyWithoutThrowing()\n        {\n            var dict = new SingleEntryDict<string, int>(\"key\", 1);\n\n            Assert.DoesNotThrow(() => dict[\"key\"] = 2);\n            Assert.AreEqual(2, dict[\"key\"]);\n            Assert.Throws<ArgumentException>(() => dict[\"other\"] = 3);\n        }\n\n        [Test]\n        public void SingleEntryDictTryGetValueReportsPresentAndMissingKeys()\n        {\n            var dict = new SingleEntryDict<string, int>(\"key\", 1);\n\n            Assert.IsTrue(dict.TryGetValue(\"key\", out var value));\n            Assert.AreEqual(1, value);\n            Assert.IsFalse(dict.TryGetValue(\"other\", out value));\n            Assert.AreEqual(default(int), value);\n        }\n\n        [Test]\n        public void SingleEntryDictRemoveOnlyRemovesMatchingKey()\n        {\n            var dict = new SingleEntryDict<string, int>(\"key\", 1);\n\n            Assert.IsFalse(dict.Remove(\"other\"));\n            Assert.IsTrue(dict.ContainsKey(\"key\"));\n\n            Assert.IsTrue(dict.Remove(\"key\"));\n            Assert.IsFalse(dict.ContainsKey(\"key\"));\n            Assert.IsFalse(dict.TryGetValue(\"key\", out var value));\n            Assert.AreEqual(default(int), value);\n            Assert.Throws<KeyNotFoundException>(() => { var _ = dict[\"key\"]; });\n            CollectionAssert.IsEmpty(dict.Keys);\n            CollectionAssert.IsEmpty(dict.Values);\n            CollectionAssert.IsEmpty(dict.KeyValuePairs);\n        }\n\n        [Test]\n        public void SingleEntryDictAddRestoresRemovedEntryAndRejectsInvalidAdds()\n        {\n            var dict = new SingleEntryDict<string, int>(\"key\", 1);\n\n            Assert.Throws<ArgumentException>(() => dict.Add(\"key\", 2));\n            Assert.Throws<ArgumentException>(() => dict.Add(\"other\", 2));\n\n            Assert.IsTrue(dict.Remove(\"key\"));\n            Assert.DoesNotThrow(() => dict.Add(\"key\", 3));\n            Assert.IsTrue(dict.ContainsKey(\"key\"));\n            Assert.AreEqual(3, dict[\"key\"]);\n            CollectionAssert.AreEqual(new[] { \"key\" }, dict.Keys);\n            CollectionAssert.AreEqual(new[] { 3 }, dict.Values);\n        }\n\n        [Test]\n        public void SingleEntryDictSupportsNullKey()\n        {\n            var dict = new SingleEntryDict<string, int>(null, 1);\n\n            Assert.IsTrue(dict.ContainsKey(null));\n            Assert.IsTrue(dict.TryGetValue(null, out var value));\n            Assert.AreEqual(1, value);\n            Assert.IsTrue(dict.Remove(null));\n            Assert.IsFalse(dict.ContainsKey(null));\n            Assert.DoesNotThrow(() => dict[null] = 2);\n            Assert.AreEqual(2, dict[null]);\n        }\n\n        [Test]\n        public void SingleValueDictSetterAndAddAcceptSharedValueWithoutThrowing()\n        {\n            var dict = new SingleValueDict<string, int>(new DictSet<string>(), 7);\n\n            Assert.DoesNotThrow(() => dict[\"first\"] = 7);\n            Assert.IsTrue(dict.ContainsKey(\"first\"));\n            Assert.AreEqual(7, dict[\"first\"]);\n\n            Assert.DoesNotThrow(() => dict.Add(\"second\", 7));\n            Assert.IsTrue(dict.ContainsKey(\"second\"));\n            Assert.AreEqual(7, dict[\"second\"]);\n\n            Assert.Throws<ArgumentException>(() => dict[\"third\"] = 8);\n            Assert.Throws<ArgumentException>(() => dict.Add(\"fourth\", 8));\n            Assert.IsFalse(dict.ContainsKey(\"third\"));\n            Assert.IsFalse(dict.ContainsKey(\"fourth\"));\n        }\n\n        [Test]\n        public void SingleValueDictValueOnlyConstructorCreatesUsableEmptyDict()\n        {\n            var dict = new SingleValueDict<string, int>(7);\n\n            CollectionAssert.IsEmpty(dict.Keys);\n            CollectionAssert.IsEmpty(dict.KeyValuePairs);\n            Assert.IsFalse(dict.ContainsKey(\"missing\"));\n            Assert.IsFalse(dict.TryGetValue(\"missing\", out var missing));\n            Assert.AreEqual(default(int), missing);\n            Assert.Throws<KeyNotFoundException>(() => { var _ = dict[\"missing\"]; });\n\n            Assert.DoesNotThrow(() => dict.Add(\"first\", 7));\n            Assert.DoesNotThrow(() => dict[\"second\"] = 7);\n\n            Assert.IsTrue(dict.ContainsKey(\"first\"));\n            Assert.IsTrue(dict.ContainsKey(\"second\"));\n            Assert.AreEqual(7, dict[\"first\"]);\n            Assert.AreEqual(7, dict[\"second\"]);\n            Assert.IsTrue(dict.TryGetValue(\"first\", out var value));\n            Assert.AreEqual(7, value);\n\n            CollectionAssert.AreEquivalent(new[] { \"first\", \"second\" }, dict.Keys);\n            CollectionAssert.AreEquivalent(\n                new[]\n                {\n                    new KeyValuePair<string, int>(\"first\", 7),\n                    new KeyValuePair<string, int>(\"second\", 7),\n                },\n                dict.KeyValuePairs);\n\n            Assert.Throws<ArgumentException>(() => dict.Add(\"third\", 8));\n            Assert.Throws<ArgumentException>(() => dict[\"third\"] = 8);\n            Assert.IsFalse(dict.ContainsKey(\"third\"));\n\n            Assert.IsTrue(dict.Remove(\"first\"));\n            Assert.IsFalse(dict.Remove(\"first\"));\n            Assert.IsFalse(dict.ContainsKey(\"first\"));\n            Assert.IsTrue(dict.ContainsKey(\"second\"));\n        }\n\n        [Test]\n        public void SingleValueSymbolDictValueOnlyConstructorCreatesUsableEmptyDict()\n        {\n            var dict = new SingleValueSymbolDict<int>(7);\n            var first = Symbol.Create(\"single-value-symbol-dict-first\");\n            var second = Symbol.Create(\"single-value-symbol-dict-second\");\n            var third = Symbol.Create(\"single-value-symbol-dict-third\");\n            var fourth = Symbol.Create(\"single-value-symbol-dict-fourth\");\n            var missingKey = Symbol.Create(\"single-value-symbol-dict-missing\");\n\n            CollectionAssert.IsEmpty(dict.Keys);\n            CollectionAssert.IsEmpty(dict.KeyValuePairs);\n            Assert.IsFalse(dict.ContainsKey(missingKey));\n            Assert.IsFalse(dict.TryGetValue(missingKey, out var missing));\n            Assert.AreEqual(default(int), missing);\n            Assert.Throws<KeyNotFoundException>(() => { var _ = dict[missingKey]; });\n\n            Assert.DoesNotThrow(() => dict.Add(first, 7));\n            Assert.DoesNotThrow(() => dict[second] = 7);\n\n            Assert.IsTrue(dict.ContainsKey(first));\n            Assert.IsTrue(dict.ContainsKey(second));\n            Assert.AreEqual(7, dict[first]);\n            Assert.AreEqual(7, dict[second]);\n            Assert.IsTrue(dict.TryGetValue(first, out var value));\n            Assert.AreEqual(7, value);\n\n            CollectionAssert.AreEquivalent(new[] { first, second }, dict.Keys);\n            CollectionAssert.AreEquivalent(\n                new[]\n                {\n                    new KeyValuePair<Symbol, int>(first, 7),\n                    new KeyValuePair<Symbol, int>(second, 7),\n                },\n                dict.KeyValuePairs);\n\n            Assert.Throws<ArgumentException>(() => dict.Add(third, 8));\n            Assert.Throws<ArgumentException>(() => dict[fourth] = 8);\n            Assert.IsFalse(dict.ContainsKey(third));\n            Assert.IsFalse(dict.ContainsKey(fourth));\n\n            Assert.IsTrue(dict.Remove(first));\n            Assert.IsFalse(dict.Remove(first));\n            Assert.IsFalse(dict.ContainsKey(first));\n            Assert.IsTrue(dict.ContainsKey(second));\n            CollectionAssert.AreEqual(new[] { second }, dict.Keys);\n            CollectionAssert.AreEqual(new[] { new KeyValuePair<Symbol, int>(second, 7) }, dict.KeyValuePairs);\n        }\n\n        [Theory]\n        public void ContainsValue(bool stackDuplicateKeys)\n        {\n            Dict<int, int> dict = new(stackDuplicateKeys)\n            {\n                {1, 2},\n                {2, 3},\n                {3, 4},\n                {42, 5},\n                {-13, 7},\n            };\n\n            if (stackDuplicateKeys)\n            {\n                dict.Add(42, 80);\n                dict.Add(42, -80);\n                Assert.IsTrue(dict.ContainsValue(-80));\n            }\n\n            var actualValues = dict.Values.ToArray();\n            int[] expectedValues = stackDuplicateKeys ? [-80, 2, 3, 4, 5, 7, 80] : [ 2, 3, 4, 5, 7 ];\n            Array.Sort(actualValues);\n\n            Assert.IsTrue(dict.ContainsValue(7));\n            Assert.IsFalse(dict.ContainsValue(6));\n            Assert.AreEqual(expectedValues, actualValues);\n        }\n\n        [Theory]\n        public void FastValuesEnumeratorMatchesValues(bool stackDuplicateKeys)\n        {\n            Dict<int, int> dict = new(stackDuplicateKeys)\n            {\n                {1, 2},\n                {2, 3},\n                {3, 4},\n                {42, 5},\n                {-13, 7},\n            };\n\n            if (stackDuplicateKeys)\n            {\n                dict.Add(42, 80);\n                dict.Add(42, -80);\n            }\n\n            CollectionAssert.AreEqual(dict.Values.ToArray(), EnumerateFastValues(dict));\n        }\n\n        [Test]\n        public void FastValuesEnumeratorEmpty()\n        {\n            var dict = new Dict<int, int>();\n            var values = dict.GetValuesEnumerator();\n            Assert.IsFalse(values.MoveNext());\n\n            var symbolDict = new SymbolDict<int>();\n            var symbolValues = symbolDict.GetValuesEnumerator();\n            Assert.IsFalse(symbolValues.MoveNext());\n        }\n\n        [Test]\n        public void SymbolDictFastValuesEnumeratorMatchesValues()\n        {\n            var dict = new SymbolDict<int>\n            {\n                { \"one\", 1 },\n                { \"two\", 2 },\n                { \"three\", 3 },\n                { \"four\", 4 },\n            };\n\n            CollectionAssert.AreEqual(dict.Values.ToArray(), EnumerateFastValues(dict));\n        }\n\n        [Theory]\n        public void IDictionaryKeys(bool stackDuplicateKeys)\n        {\n            Dict<int, int> dict = new(stackDuplicateKeys)\n            {\n                {1, 2},\n                {2, 3},\n                {3, 4},\n                {42, 5},\n                {-13, 7},\n            };\n\n            int[] expectedKeys;\n\n            if (stackDuplicateKeys)\n            {\n                dict.Add(42, 80);\n                dict.Add(42, -80);\n                expectedKeys = [-13, 1, 2, 3, 42, 42, 42];\n            }\n            else\n            {\n                expectedKeys = [-13, 1, 2, 3, 42];\n            }\n\n            var keys = ((IDictionary<int, int>)dict).Keys;\n            var actualKeys = Enumerable.Order(Enumerate(keys));\n\n            Assert.AreEqual(expectedKeys.Length, keys.Count);\n            Assert.AreEqual(expectedKeys, actualKeys);\n        }\n\n        [Theory]\n        public void IDictionaryValues(bool stackDuplicateKeys)\n        {\n            Dict<int, int> dict = new(stackDuplicateKeys)\n            {\n                {1, 2},\n                {2, 3},\n                {3, 4},\n                {42, 5},\n                {-13, 7},\n            };\n\n            int[] expectedValues;\n\n            if (stackDuplicateKeys)\n            {\n                dict.Add(42, 80);\n                dict.Add(42, -80);\n                expectedValues = [-80, 2, 3, 4, 5, 7, 80];\n            }\n            else\n            {\n                expectedValues = [2, 3, 4, 5, 7];\n            }\n\n            var values = ((IDictionary<int, int>)dict).Values;\n            var actualValues = Enumerable.Order(Enumerate(values));\n\n            Assert.AreEqual(expectedValues.Length, values.Count);\n            Assert.AreEqual(expectedValues, actualValues);\n        }\n\n        private static int[] EnumerateFastValues(Dict<int, int> dict)\n        {\n            var result = new List<int>();\n            var values = dict.GetValuesEnumerator();\n\n            while (values.MoveNext())\n                result.Add(values.Current);\n\n            return result.ToArray();\n        }\n\n        private static int[] EnumerateFastValues(SymbolDict<int> dict)\n        {\n            var result = new List<int>();\n            var values = dict.GetValuesEnumerator();\n\n            while (values.MoveNext())\n                result.Add(values.Current);\n\n            return result.ToArray();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/AlgoDat/HigherOrderFunctionsTests.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class HighFunTests : TestSuite\n    {\n        public HighFunTests() : base() { }\n        public HighFunTests(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public void TestHighFun()\n        {\n            FixedPointTests();\n            CurryingTests();\n        }\n\n        public void FixedPointTests()\n        {\n            Test.Begin(\"fixed point combinator tests\");\n            var fib = HighFun.Y<int, int>(\n                            f => n => n > 1 ? f(n - 1) + f(n - 2) : n);\n            var fact = HighFun.Y<int, int>(\n                            f => n => n > 1 ? n * f(n - 1) : 1);\n            var factk = HighFun.Y<int, int, int>(\n                            f => (n, k) => n > 1 ? n * f(n - k, k) : 1);\n            var fastfib = HighFun.Y<int, int, int, int>(\n                            f => (n, a, b) => n < 2 ? b : f(n - 1, b, a + b))\n                        .ApplyArg1Arg2(0, 1);\n\n            Test.IsTrue(fib(7) == 13, \"fib(7) != 13\");\n            Test.IsTrue(fastfib(7) == 13, \"ffib(7) != 13\");\n            Test.IsTrue(fib(8) == 21, \"fib(8) != 21\");\n            Test.IsTrue(fastfib(8) == 21, \"ffib(8) != 21\");\n            Test.IsTrue(fact(6) == 720, \"fact(6) != 120\");\n            Test.IsTrue(factk(7, 2) == 105, \"factk(7,2) != 105\");\n            Test.End();\n        }\n\n        public void CurryingTests()\n        {\n            Test.Begin(\"currying tests\");\n            Func<double, double, double> Power = Fun.Pow;\n            var CurriedPower = Power.Curry();\n            var PowerOfThree = CurriedPower(3.0);\n            var Cube = Power.ApplyArg1(3.0); // we start counting args at 0\n\n            for (var x = 0.0; x < 10.01; x += 0.5)\n            {\n                Test.IsTrue(Cube(x) == Fun.Pow(x, 3.0),\n                        \"Cube({0}) != Fun.Pow({0}, 3.0)\", x);\n                Test.IsTrue(PowerOfThree(x) == Fun.Pow(3.0, x),\n                        \"PowerOfThree({0}) == Fun.Pow(3.0,{0})\", x);\n            }\n            Test.End();\n        }\n    \n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/AlgoDat/SortingTests.cs",
    "content": "using Aardvark.Base;\nusing Aardvark.Base.Sorting;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class SortingTests : TestSuite\n    {\n        public SortingTests() : base() { }\n        public SortingTests(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public void TestSorting()\n        {\n            SortTests(1 << 10);\n            MedianTests(1 << 10);\n        }\n\n        public void Run()\n        {\n            DetailedSortTests(      // too long for N-Unit, just for performance measurements\n                    1 << 20, // 26\n                    1 << 4,\n                    4.0);\n        }\n\n        public void MedianTests(int maxCount)\n        {\n            Test.Begin(\"median tests\");\n            foreach (var pm in new[] { false, true })\n            {\n                for (int count = 1; count <= maxCount; count *= 2)\n                {\n                    var rnd = new RandomSystem(count);\n                    var array = rnd.CreatePermutationArray(count);\n                    var a = new int[count];\n\n                    Test.Begin(\"{0}quick-median {1} items\", pm ? \"permutation \" : \"\", count);\n                    if (pm)\n                        for (int i = 0; i < a.Length; i++)\n                        {\n                            a.SetByIndex(pi => pi);\n                            a.PermutationQuickMedianAscending(array, i);\n                            Test.IsTrue(array[a[i]] == i);\n                        }\n                    else\n                        for (int i = 0; i < a.Length; i++)\n                        {\n                            array.CopyTo(a, 0);\n                            a.QuickMedianAscending(i);\n                            Test.IsTrue(a[i] == i);\n                        }\n                    Test.End();\n                }\n            }\n            Test.End();\n        }\n\n        public void SortTests(int maxCount)\n        {\n            var sortDict = new Dict<string, Action<int[]>>\n            {\n                { \"heap\", SortingExtensions.HeapSortAscending },\n                { \"quick\", SortingExtensions.QuickSortAscending },\n                { \"smooth\", SortingExtensions.SmoothSortAscending },\n                { \"tim\", SortingExtensions.TimSortAscending },\n            };\n\n            var permSortDict = new Dict<string, Action<int[],int[]>>\n            {\n                { \"heap\", SortingExtensions.PermutationHeapSortAscending },\n                { \"quick\", SortingExtensions.PermutationQuickSortAscending },\n                { \"smooth\", SortingExtensions.PermutationSmoothSortAscending },\n                { \"tim\", SortingExtensions.PermutationTimSortAscending },\n            };\n\n            Test.Begin(\"sort tests\");\n            foreach (var pm in new[] { false, true })\n            {\n                for (int count = 1; count <= maxCount; count *= 2)\n                {\n                    var rnd = new RandomSystem(count);\n                    var array = rnd.CreatePermutationArray(count);\n                    var a = new int[count];\n\n                    foreach (var sort in new[] { \"heap\", \"quick\", \"smooth\", \"tim\" })\n                    {\n                        Test.Begin(\"{0}{1}-sort {2} items\", pm ? \"permutation \" : \"\", sort, count);\n                        if (pm)\n                        {\n                            a.SetByIndex(pi => pi);\n                            permSortDict[sort](a, array);\n                            for (int i = 0; i < count; i++)\n                                Test.IsTrue(array[a[i]] == i);\n                        }\n                        else\n                        {\n                            array.CopyTo(a, 0);\n                            sortDict[sort](a);\n                            for (int i = 0; i < count; i++)\n                                Test.IsTrue(a[i] == i);\n                        }\n                        Test.End();\n                    }\n                }\n            }\n            Test.End();\n        }\n\n        public abstract class Sorter\n        {\n            public Symbol Name;\n            public Type Type;\n            public Type PermType;\n            public bool UseCmp;\n            public abstract object SortFunction { get; }\n            public Sorter(Symbol name, Type type, Type permType, bool useCmp)\n            { Name = name; Type = type; PermType = permType; UseCmp = useCmp; }\n        }\n\n        public class SimpleSorter<T> : Sorter\n        {\n            public Action<T[], long, long> Sort;\n            public SimpleSorter(Symbol name, Action<T[], long, long> sort)\n                : base(name, typeof(T), null, false)\n            { Sort = sort; }\n            public override object SortFunction  { get { return Sort; } }\n        }\n\n        public class FunSorter<T> : Sorter\n        {\n            public Action<T[], Func<T, T, int>, long, long> Sort;\n            public FunSorter(Symbol name, Action<T[], Func<T, T, int>, long, long> sort)\n                : base(name, typeof(T), null, true)\n            { Sort = sort; }\n            public override object SortFunction { get { return Sort; } }\n        }\n\n        public class PermSorter<Tp, T> : Sorter\n        {\n            public Action<Tp[], T[], Tp, Tp> Sort;\n            public PermSorter(Symbol name, Action<Tp[], T[], Tp, Tp> sort)\n                : base(name, typeof(T), typeof(Tp), false)\n            { Sort = sort; }\n            public override object SortFunction { get { return Sort; } }\n        }\n\n        public class PermFunSorter<Tp, T> : Sorter\n        {\n            public Action<Tp[], T[], Func<T, T, int>, Tp, Tp> Sort;\n            public PermFunSorter(Symbol name, Action<Tp[], T[], Func<T, T, int>, Tp, Tp> sort)\n                : base(name, typeof(T), typeof(Tp), true)\n            { Sort = sort; }\n            public override object SortFunction { get { return Sort; } }\n        }\n\n        public abstract class SortArray\n        {\n            public Type Type;\n            public Type PermType;\n            public bool UseCmp;\n\n            public SortArray(Type type, Type permType) { Type = type; PermType = permType; }\n            public abstract void CopyFrom(long[] master, long count);\n            public abstract void Sort(object sortFunction, long count, long repeat);\n            public abstract void Test(Func<bool, bool> testFunction, long count, long repeat);\n\n        }\n\n        public class SortArray<T> : SortArray\n        {\n            public Func<long, T> TofLong;\n            public T[] Array;\n            public Func<T, T, int> Cmp;\n\n            public SortArray(long count, Func<long, T> tOfLong, Func<T, T, int> cmp)\n                : base(typeof(T), null)\n            { TofLong = tOfLong; Array = new T[count]; Cmp = cmp; UseCmp = false; }\n\n            public override void CopyFrom(long[] master, long count)\n            {\n                for (long i = 0; i < count; i++) Array[i] = TofLong(master[i]);\n            }\n\n            public override void Sort(object sortFunction, long count, long repeat)\n            {\n                var typedSortFunction = (Action<T[], long, long>)sortFunction;\n                for (long start = 0, end = count; repeat-- > 0; start = end, end += count)\n                    typedSortFunction(Array, start, end);\n            }\n\n            public override void Test(Func<bool, bool> testFunction, long count, long repeat)\n            {\n                long fails = 0;\n                for (long start = 0, end = count; repeat-- > 0; start = end, end += count)\n                {\n                    var last = Array[start];\n                    for (var i = start + 1; i < end; i++)\n                    {\n                        var item = Array[i];\n                        var check = Cmp(last, item) <= 0;\n                        if (!check)\n                            ++fails;\n                        last = item;\n                    }\n                }\n                testFunction(fails == 0);\n            }\n        }\n\n        public class FunSortArray<T> : SortArray<T>\n        {\n            public FunSortArray(long count, Func<long, T> tOfLong, Func<T, T, int> cmp)\n                : base(count, tOfLong, cmp)\n            { UseCmp = true; }\n\n            public override void Sort(object sortFunction, long count, long repeat)\n            {\n                var typedSortFunction = (Action<T[], Func<T,T,int>, long, long>)sortFunction;\n                for (long start = 0, end = count; repeat-- > 0; start = end, end += count)\n                    typedSortFunction(Array, Cmp, start, end);\n            }\n        }\n\n        public class PermSortArray<Tp, T> : SortArray\n        {\n            public Func<long, T> TOfLong;\n            public Func<long, Tp> TpOfLong;\n            public Func<Tp, long> LongOfTp;\n            public Tp[] PermArray;\n            public T[] Array;\n            public Func<T, T, int> Cmp;\n\n            public PermSortArray(long count, Func<long, Tp> tpOfLong, Func<Tp, long> longOfTp,\n                    Func<long, T> tOfLong, Func<T, T, int> cmp)\n                : base(typeof(T), typeof(Tp))\n            {\n                TOfLong = tOfLong; TpOfLong = tpOfLong; LongOfTp = longOfTp;\n                PermArray = new Tp[count]; Array = new T[count];\n                Cmp = cmp; UseCmp = false;\n            }\n\n            public override void CopyFrom(long[] master, long count)\n            {\n                for (long i = 0; i < count; i++) { Array[i] = TOfLong(master[i]); PermArray[i] = TpOfLong(i); }\n            }\n\n            public override void Sort(object sortFunction, long count, long repeat)\n            {\n                var typedSortFunction = (Action<Tp[], T[], Tp, Tp>)sortFunction;\n                for (long start = 0, end = count; repeat-- > 0; start = end, end += count)\n                    typedSortFunction(PermArray, Array, TpOfLong(start), TpOfLong(end));\n            }\n\n            public override void Test(Func<bool, bool> testFunction, long count, long repeat)\n            {\n                long fails = 0;\n                for (long start = 0, end = count; repeat-- > 0; start = end, end += count)\n                {\n                    var last = Array[LongOfTp(PermArray[start])];\n                    for (var i = start; i < end; i++)\n                    {\n                        var item = Array[LongOfTp(PermArray[i])];\n                        var check = Cmp(last, item) <= 0;\n                        if (!check)\n                            ++fails;\n                        last = item;\n                    }\n                }\n                testFunction(fails == 0);\n            }\n        }\n\n        public class PermFunSortArray<Tp, T> : PermSortArray<Tp, T>\n        {\n            public PermFunSortArray(long count, Func<long, Tp> tpOfLong, Func<Tp, long> longOfTp,\n                    Func<long, T> tOfLong, Func<T, T, int> cmp)\n                : base(count, tpOfLong, longOfTp, tOfLong, cmp)\n            { UseCmp = true; }\n\n            public override void Sort(object sortFunction, long count, long repeat)\n            {\n                var typedSortFunction = (Action<Tp[], T[], Func<T, T, int>, Tp, Tp>)sortFunction;\n                for (long start = 0, end = count; repeat-- > 0; start = end, end += count)\n                    typedSortFunction(PermArray, Array, Cmp, TpOfLong(start), TpOfLong(end));\n            }\n        }\n\n        public class Initializer\n        {\n            public string Name;\n            public Action<long[], long, long, long> Init;\n            public Initializer(string name, Action<long[], long, long, long> init) { Name = name; Init = init; }\n        }\n\n        public static readonly Symbol QuickSort = \"quick\";\n        public static readonly Symbol HeapSort = \"heap\";\n        public static readonly Symbol SmoothSort = \"smooth\";\n        public static readonly Symbol TimSort = \"tim\";\n\n        static readonly Func<V3d, V3d, int> V3dCmp = (a, b) => a.Z < b.Z ? -1 : a.Z > b.Z ? 1 : 0;\n        static readonly Func<V2d, V2d, int> V2dCmp = (a, b) => a.Y < b.Y ? -1 : a.Y > b.Y ? 1 : 0;\n        static readonly Func<double, double, int> DCmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;\n        static readonly Func<float, float, int> FCmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;\n        static readonly Func<long, long, int> LCmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;\n        static readonly Func<int, int, int> ICmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;\n\n        public void DetailedSortTests(int arrayCount, int minimalCount, double countFactor)\n        {\n            // re-order this array to see certain results first\n            var arrayCreators = new Func<long, SortArray>[]\n            {\n                c => new SortArray<int>(c, i => (int)i, ICmp),\n                c => new SortArray<long>(c, i => i, LCmp),\n                c => new SortArray<float>(c, i => i, FCmp),\n                c => new SortArray<double>(c, i => i, DCmp),\n                c => new FunSortArray<V2d>(c, i => new V2d(0,i), V2dCmp),\n                c => new FunSortArray<V3d>(c, i => new V3d(0,0,i), V3dCmp),\n\n                c => new PermSortArray<int, int>(c, i => (int)i, i => i, i => (int)i, ICmp),\n                c => new PermSortArray<int, long>(c, i => (int)i, i => i, i => i, LCmp),\n                c => new PermSortArray<int, float>(c, i => (int)i, i => i, i => i, FCmp),\n                c => new PermSortArray<int, double>(c, i => (int)i, i => i, i => i, DCmp),\n                c => new PermFunSortArray<int, V2d>(c, i => (int)i, i => i, i => new V2d(0,i), V2dCmp),\n                c => new PermFunSortArray<int, V3d>(c, i => (int)i, i => i, i => new V3d(0,0,i), V3dCmp),                \n\n                c => new PermSortArray<long, int>(c, i => i, i => i, i => (int)i, ICmp),\n                c => new PermSortArray<long, long>(c, i => i, i => i, i => i, LCmp),\n                c => new PermSortArray<long, float>(c, i => i, i => i, i => i, FCmp),\n                c => new PermSortArray<long, double>(c, i => i, i => i, i => i, DCmp),\n                c => new PermFunSortArray<long, V2d>(c, i => i, i => i, i => new V2d(0,i), V2dCmp),\n                c => new PermFunSortArray<long, V3d>(c, i => i, i => i, i => new V3d(0,0,i), V3dCmp),\n            };\n\n            const int seed = 19680713;\n\n            Action<long[], long, long, long, double> randomFraction = (a, count, repeat, total, fraction) =>\n            {\n                var rc = (long)(count * fraction);\n                var rnd = new RandomSystem(seed);\n                for (long s = 0; s < total; s += count)\n                {\n                    for (long r = rc; r > 0; r--)\n                    {\n                        long i = -1; do { i = s + rnd.UniformLong(count); } while (a[i] < 0);\n                        long j = -1; do { j = s + rnd.UniformLong(count); } while (j == i);\n                        var aj = a[j]; if (aj >= 0) { --r; aj = -1 - aj; }\n                        var ai = -1 - a[i]; a[i] = aj; a[j] = ai;\n                    }\n                }\n                a.Apply(v => v < 0 ? -1 - v : v);\n            };\n\n            // re-order this array to see certain results first\n            var initializers = new Initializer[]\n            {\n                new Initializer(\"randomized\", (a, c, r, t) =>\n                    { a.SetByIndexLong(t, i => i); new RandomSystem(seed).Randomize(a, t); }),\n                new Initializer(\"sorted\", (a, c, r, t) => a.SetByIndexLong(t, i => i)),\n                new Initializer(\"sorted, 1% random\", (a, c, r, t) =>\n                    { a.SetByIndexLong(t, i => i); randomFraction(a, c, r, t, 0.01); }),\n                new Initializer(\"sorted, 10% random\", (a, c, r, t) =>\n                    { a.SetByIndexLong(t, i => i); randomFraction(a, c, r, t, 0.1); }),\n                new Initializer(\"sorted, 30% random\", (a, c, r, t) =>\n                    { a.SetByIndexLong(t, i => i); randomFraction(a, c, r, t, 0.3); }),\n                new Initializer(\"reversed\", (a, c, r, t) => a.SetByIndexLong(t, i => t - 1 - i)),\n                new Initializer(\"reversed, 1% random\", (a, c, r, t) =>\n                    { a.SetByIndexLong(t, i => t - 1 - i); randomFraction(a, c, r, t, 0.01); }),\n                new Initializer(\"reversed, 10% random\", (a, c, r, t) =>\n                    { a.SetByIndexLong(t, i => t - 1 - i); randomFraction(a, c, r, t, 0.1); }),\n                new Initializer(\"reversed, 30% random\", (a, c, r, t) =>\n                    { a.SetByIndexLong(t, i => t - 1 - i); randomFraction(a, c, r, t, 0.3); }),\n                new Initializer(\"all equal\", (a, c, r, t) => a.Set(t, 0)),\n            };\n\n            var sortNames = new Symbol[] { HeapSort, QuickSort, SmoothSort, TimSort };\n            var sorters = new Sorter[]\n            {\n                new SimpleSorter<int>       (HeapSort,      SortingExtensions.HeapSortAscending),\n                new SimpleSorter<long>      (HeapSort,      SortingExtensions.HeapSortAscending),\n                new SimpleSorter<float>     (HeapSort,      SortingExtensions.HeapSortAscending),\n                new SimpleSorter<double>    (HeapSort,      SortingExtensions.HeapSortAscending),\n                new FunSorter<V2d>          (HeapSort,      SortingExtensions.HeapSort),\n                new FunSorter<V3d>          (HeapSort,      SortingExtensions.HeapSort),\n\n                new PermSorter<int, int>        (HeapSort,      SortingExtensions.PermutationHeapSortAscending),\n                new PermSorter<int, long>       (HeapSort,      SortingExtensions.PermutationHeapSortAscending),\n                new PermSorter<int, float>      (HeapSort,      SortingExtensions.PermutationHeapSortAscending),\n                new PermSorter<int, double>     (HeapSort,      SortingExtensions.PermutationHeapSortAscending),\n                new PermFunSorter<int, V2d>     (HeapSort,      SortingExtensions.PermutationHeapSort),\n                new PermFunSorter<int, V3d>     (HeapSort,      SortingExtensions.PermutationHeapSort),\n\n                new PermSorter<long, int>       (HeapSort,      SortingExtensions.PermutationHeapSortAscending),\n                new PermSorter<long, long>      (HeapSort,      SortingExtensions.PermutationHeapSortAscending),\n                new PermSorter<long, float>     (HeapSort,      SortingExtensions.PermutationHeapSortAscending),\n                new PermSorter<long, double>    (HeapSort,      SortingExtensions.PermutationHeapSortAscending),\n                new PermFunSorter<long, V2d>    (HeapSort,      SortingExtensions.PermutationHeapSort),\n                new PermFunSorter<long, V3d>    (HeapSort,      SortingExtensions.PermutationHeapSort),\n\n                new SimpleSorter<int>       (QuickSort,     SortingExtensions.QuickSortAscending),\n                new SimpleSorter<long>      (QuickSort,     SortingExtensions.QuickSortAscending),\n                new SimpleSorter<float>     (QuickSort,     SortingExtensions.QuickSortAscending),\n                new SimpleSorter<double>    (QuickSort,     SortingExtensions.QuickSortAscending),\n                new FunSorter<V2d>          (QuickSort,     SortingExtensions.QuickSort),\n                new FunSorter<V3d>          (QuickSort,     SortingExtensions.QuickSort),\n\n                new PermSorter<int, int>        (QuickSort,     SortingExtensions.PermutationQuickSortAscending),\n                new PermSorter<int, long>       (QuickSort,     SortingExtensions.PermutationQuickSortAscending),\n                new PermSorter<int, float>      (QuickSort,     SortingExtensions.PermutationQuickSortAscending),\n                new PermSorter<int, double>     (QuickSort,     SortingExtensions.PermutationQuickSortAscending),\n                new PermFunSorter<int, V2d>     (QuickSort,     SortingExtensions.PermutationQuickSort),\n                new PermFunSorter<int, V3d>     (QuickSort,     SortingExtensions.PermutationQuickSort),\n\n                new PermSorter<long, int>       (QuickSort,     SortingExtensions.PermutationQuickSortAscending),\n                new PermSorter<long, long>      (QuickSort,     SortingExtensions.PermutationQuickSortAscending),\n                new PermSorter<long, float>     (QuickSort,     SortingExtensions.PermutationQuickSortAscending),\n                new PermSorter<long, double>    (QuickSort,     SortingExtensions.PermutationQuickSortAscending),\n                new PermFunSorter<long, V2d>    (QuickSort,     SortingExtensions.PermutationQuickSort),\n                new PermFunSorter<long, V3d>    (QuickSort,     SortingExtensions.PermutationQuickSort),\n\n                new SimpleSorter<int>       (SmoothSort,    SortingExtensions.SmoothSortAscending),\n                new SimpleSorter<long>      (SmoothSort,    SortingExtensions.SmoothSortAscending),\n                new SimpleSorter<float>     (SmoothSort,    SortingExtensions.SmoothSortAscending),\n                new SimpleSorter<double>    (SmoothSort,    SortingExtensions.SmoothSortAscending),\n                new FunSorter<V2d>          (SmoothSort,    SortingExtensions.SmoothSort),\n                new FunSorter<V3d>          (SmoothSort,    SortingExtensions.SmoothSort),\n\n                new PermSorter<int, int>        (SmoothSort,    SortingExtensions.PermutationSmoothSortAscending),\n                new PermSorter<int, long>       (SmoothSort,    SortingExtensions.PermutationSmoothSortAscending),\n                new PermSorter<int, float>      (SmoothSort,    SortingExtensions.PermutationSmoothSortAscending),\n                new PermSorter<int, double>     (SmoothSort,    SortingExtensions.PermutationSmoothSortAscending),\n                new PermFunSorter<int, V2d>     (SmoothSort,    SortingExtensions.PermutationSmoothSort),\n                new PermFunSorter<int, V3d>     (SmoothSort,    SortingExtensions.PermutationSmoothSort),\n\n                new PermSorter<long, int>       (SmoothSort,    SortingExtensions.PermutationSmoothSortAscending),\n                new PermSorter<long, long>      (SmoothSort,    SortingExtensions.PermutationSmoothSortAscending),\n                new PermSorter<long, float>     (SmoothSort,    SortingExtensions.PermutationSmoothSortAscending),\n                new PermSorter<long, double>    (SmoothSort,    SortingExtensions.PermutationSmoothSortAscending),\n                new PermFunSorter<long, V2d>    (SmoothSort,    SortingExtensions.PermutationSmoothSort),\n                new PermFunSorter<long, V3d>    (SmoothSort,    SortingExtensions.PermutationSmoothSort),\n\n                new SimpleSorter<int>       (TimSort,       SortingExtensions.TimSortAscending),\n                new SimpleSorter<long>      (TimSort,       SortingExtensions.TimSortAscending),\n                new SimpleSorter<float>     (TimSort,       SortingExtensions.TimSortAscending),\n                new SimpleSorter<double>    (TimSort,       SortingExtensions.TimSortAscending),\n                new FunSorter<V2d>          (TimSort,       SortingExtensions.TimSort),\n                new FunSorter<V3d>          (TimSort,       SortingExtensions.TimSort),\n\n                new PermSorter<int, int>        (TimSort,       SortingExtensions.PermutationTimSortAscending),\n                new PermSorter<int, long>       (TimSort,       SortingExtensions.PermutationTimSortAscending),\n                new PermSorter<int, float>      (TimSort,       SortingExtensions.PermutationTimSortAscending),\n                new PermSorter<int, double>     (TimSort,       SortingExtensions.PermutationTimSortAscending),\n                new PermFunSorter<int, V2d>     (TimSort,       SortingExtensions.PermutationTimSort),\n                new PermFunSorter<int, V3d>     (TimSort,       SortingExtensions.PermutationTimSort),\n\n                new PermSorter<long, int>       (TimSort,       SortingExtensions.PermutationTimSortAscending),\n                new PermSorter<long, long>      (TimSort,       SortingExtensions.PermutationTimSortAscending),\n                new PermSorter<long, float>     (TimSort,       SortingExtensions.PermutationTimSortAscending),\n                new PermSorter<long, double>    (TimSort,       SortingExtensions.PermutationTimSortAscending),\n                new PermFunSorter<long, V2d>    (TimSort,       SortingExtensions.PermutationTimSort),\n                new PermFunSorter<long, V3d>    (TimSort,       SortingExtensions.PermutationTimSort),\n            };\n\n            var trialCounts = new List<long>();\n            for (double doubleCount = minimalCount; doubleCount < 0.5 + arrayCount; doubleCount *= countFactor)\n                trialCounts.Add((long)doubleCount);\n\n            var sorterMap = new Dict<(Symbol, Type, Type, bool), Sorter>(\n                    from s in sorters select KeyValuePairs.Create((s.Name, s.PermType, s.Type, s.UseCmp), s));\n\n            var master = new long[arrayCount];\n\n            foreach (var creator in arrayCreators)\n            {\n                var sortArray = creator(arrayCount);\n                var type = sortArray.Type;\n                var permType = sortArray.PermType;\n                var useCmp = sortArray.UseCmp;\n                foreach (var initializer in initializers)\n                {\n                    string permText = permType == null ? \"\" : String.Format(\"{0} permuted \", permType.Name);\n                    string sectionText = String.Format(\"{0}{1} {2}s\", permText, initializer.Name, type.Name);\n                    Test.Begin(sectionText);\n                    var results = new Tup<long, double>[sortNames.Length, trialCounts.Count];\n                    trialCounts.ForEach((trialCount, tci) =>\n                    {\n                        Test.Begin(\"array size {0}\", trialCount);\n                        var trialRepeat = arrayCount / trialCount;\n                        var totalCount = trialRepeat * trialCount;\n                        initializer.Init(master, trialCount, trialRepeat, totalCount);\n                        for (int si = 0; si < sortNames.Length; si++)\n                            for (int i = 0; i < sortNames.Length; i++)\n                            {\n                                var sni = (si + i) % sortNames.Length;\n                                var sorter = sorterMap[(sortNames[sni], permType, type, useCmp)];\n                                sortArray.CopyFrom(master, totalCount);\n                                Report.BeginTimed(\"{0} sorting {1}x {2} {3}s\",\n                                                  sorter.Name, trialRepeat, trialCount, type.Name);\n                                sortArray.Sort(sorter.SortFunction, trialCount, trialRepeat);\n                                var time = Report.End();\n                                results[sni, tci].E0 += totalCount;\n                                results[sni, tci].E1 += time;\n                                sortArray.Test(Test.IsTrue, trialCount, trialRepeat);\n                            }\n                        Test.End(\" [{0}x]\", sortNames.LongLength * trialRepeat);\n                    });\n                    Test.End();\n                    Report.Begin(\"{0} [microsecs/item]:\", sectionText);\n                    Report.Text(\"{0,10} :\", \"length\");\n                    for (int sni = 0; sni < sortNames.Length; sni++)\n                        Report.Text(\" {0,8}\", sortNames[sni]);\n                    Report.Line();\n\n                    for (int tci = 0; tci < trialCounts.Count; tci++)\n                    {\n                        Report.Text(\"{0, 10} :\", trialCounts[tci]);\n                        for (int sni = 0; sni < sortNames.Length; sni++)\n                        {\n                            var microsecs = 1000000.0 * results[sni, tci].E1 / results[sni, tci].E0;\n                            Report.Text(\" {0,8:0.0000}\", microsecs);\n                        }\n                        Report.Line();\n                    }\n                    Report.End();\n                }\n            }\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/CodeGenerator/CodeGeneratorTests.cs",
    "content": "using System;\nusing System.IO;\nusing System.Linq;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests.CodeGenerator\n{\n    [TestFixture]\n    public class CodeGeneratorTests\n    {\n        private static string WriteConfig(params string[] lines)\n        {\n            var path = Path.Combine(Path.GetTempPath(), $\"codegenerator-{Guid.NewGuid():N}.conf\");\n            File.WriteAllLines(path, lines);\n            return path;\n        }\n\n        [Test]\n        public void ParseConfigFileAcceptsValidRowsBlankLinesAndComments()\n        {\n            var configPath = WriteConfig(\n                \"\",\n                \"   \",\n                \"# comment only\",\n                \"template1.cs output1.cs\",\n                \"\\ttemplate2.fs\\toutput2.fs\\t\",\n                \"   # another comment\"\n            );\n\n            try\n            {\n                var entries = global::CodeGenerator.Program.ParseConfigFile(configPath);\n\n                Assert.That(entries.Count, Is.EqualTo(2));\n                Assert.That(entries[0].TemplateFileName, Is.EqualTo(\"template1.cs\"));\n                Assert.That(entries[0].OutputFileName, Is.EqualTo(\"output1.cs\"));\n                Assert.That(entries[1].TemplateFileName, Is.EqualTo(\"template2.fs\"));\n                Assert.That(entries[1].OutputFileName, Is.EqualTo(\"output2.fs\"));\n            }\n            finally\n            {\n                File.Delete(configPath);\n            }\n        }\n\n        [Test]\n        public void ParseConfigFileRejectsMalformedRowsWithClearMessage()\n        {\n            var configPath = WriteConfig(\n                \"template1.cs output1.cs\",\n                \"malformed-only-one-column\"\n            );\n\n            try\n            {\n                var ex = Assert.Throws<InvalidDataException>(() => global::CodeGenerator.Program.ParseConfigFile(configPath));\n                Assert.That(ex.Message, Does.Contain(Path.GetFileName(configPath)));\n                Assert.That(ex.Message, Does.Contain(\"line 2\"));\n                Assert.That(ex.Message, Does.Contain(\"expected '<template> <output>'\"));\n                Assert.That(ex.Message, Does.Contain(\"malformed-only-one-column\"));\n            }\n            finally\n            {\n                File.Delete(configPath);\n            }\n        }\n\n        [Test]\n        public void RunReturnsNonZeroForMalformedConfig()\n        {\n            var configPath = WriteConfig(\n                \"template1.cs output1.cs\",\n                \"too many columns here\"\n            );\n\n            try\n            {\n                var exitCode = global::CodeGenerator.Program.Run(new[] { configPath });\n                Assert.That(exitCode, Is.Not.EqualTo(0));\n            }\n            finally\n            {\n                File.Delete(configPath);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/Arrays.cs",
    "content": "﻿using NUnit.Framework;\nusing System;\nusing Aardvark.Base;\n\nnamespace Aardvark.Tests.Extensions\n{\n    static class Arrays\n    {\n        [Test]\n        public unsafe static void CopyArrayToNative()\n        {\n            var src = new ushort[] { 5, 3, 8, 12, 83 };\n            var dst = new ushort[3];\n\n            fixed (ushort* ptr = dst)\n            {\n                src.CopyTo(1, 3, (IntPtr)ptr);\n            }\n\n            Assert.AreEqual(src[1], dst[0]);\n            Assert.AreEqual(src[2], dst[1]);\n            Assert.AreEqual(src[3], dst[2]);\n        }\n\n        [Test]\n        public unsafe static void CopyNativeToArray()\n        {\n            var src = new ushort[] { 5, 3, 8, 12, 83 };\n            var dst = new ushort[5];\n\n            fixed (ushort* ptr = src)\n            {\n                ((IntPtr)ptr).CopyTo(dst, 1, 3);\n            }\n\n            Assert.AreEqual(src[0], dst[1]);\n            Assert.AreEqual(src[1], dst[2]);\n            Assert.AreEqual(src[2], dst[3]);\n        }\n\n        [Test]\n        public unsafe static void CopyNativeToNative()\n        {\n            var src = new ushort[] { 5, 3, 8, 12, 83 };\n            var dst = new ushort[src.Length];\n\n            fixed (ushort* srcPtr = src, dstPtr = dst)\n            {\n                ((IntPtr)srcPtr).CopyTo((IntPtr)dstPtr, sizeof(ushort) * src.Length);\n            }\n\n            for (int i = 0; i < src.Length; i++)\n                Assert.AreEqual(src[i], dst[i]);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/DateTime.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Reflection;\nusing System.Reflection.Emit;\nusing System.Runtime.CompilerServices;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Tests.Extensions\n{\n    [TestFixture]\n    public class DateTimeTests : TestSuite\n    {\n        [MethodImpl(MethodImplOptions.NoInlining)]\n        static double ComputeJulianDayInt(DateTime date)\n        {\n            var y = date.Year;\n            var m = date.Month;\n            var d = date.Day;\n\n            var jd = ComputeJulianDay(y, m, d) - 0.5; // julian day with fraction 0 represents 12:00 noon UT -> subtract 0.5 to start at 00:00\n\n            return jd + date.TimeOfDay.TotalDays; \n        }\n\n        static int ComputeJulianDay(int y, int m, int d)\n        {\n            if (m < 3)\n            {\n                m += 13;\n                y--;\n            }\n            else\n            {\n                m += 1;\n            }\n\n            int c = 2 - y / 100 + y / 400;\n\n            return (1461 * (y + 4716) / 4) + (153 * m / 5) + d + c - 1524; // NOTE: subtract 1524.5 to get proper floating point julian day\n        }\n\n        [MethodImpl(MethodImplOptions.NoInlining)]\n        static double ComputeJulianDayNREL(DateTime date)\n        {\n            // algorithm from NREL spa.c\n            // https://www.nrel.gov/docs/fy08osti/34302.pdf\n\n            var y = date.Year;\n            var m = date.Month; // between 1 and 12\n            var d = date.Day;\n            var dt = date.TimeOfDay.TotalDays;\n\n            // in case of feb or jan, overflow months m => 13 or 14 (y = y - 1)\n            if (m < 3)\n            {\n                m = m + 12;\n                y--;\n            }\n            \n            // 30.6001 is the days per month approximation (365-31-28)/10 (ie av month days without jan & feb)\n            var jd = Fun.Floor(365.25 * (y + 4716.0)) + Fun.Floor(30.6001 * (m + 1)) + d + dt - 1524.5;\n            //if (jd > 2299160.0) // for gregorian calendar ?\n            {\n                var a = y / 100;\n                jd += 2 - a + (a / 4);\n            }\n\n            // http://radixpro.com/a4a-start/julian-day-and-julian-day-number/\n\n            return jd;\n        }\n\n        [MethodImpl(MethodImplOptions.NoInlining)]\n        static double ComputeJulianDayInt2(DateTime date)\n        {\n            var y = date.Year;\n            var m = date.Month;\n            var d = date.Day;\n            var dt = date.TimeOfDay.TotalDays;\n\n            if (m < 3)\n            {\n                m = m + 12;\n                y = y - 1;\n            }\n\n            int jd = d + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400);\n\n            // JD 1721119 is about year 0 ?\n            return jd + 1721118.5 + dt;\n        }\n\n        [MethodImpl(MethodImplOptions.NoInlining)]\n        static double ComputeJulianDayMeeus(DateTime date)\n        {\n            var y = date.Year;\n            var m = date.Month; // between 1 and 12\n            var d = date.Day;\n            var dt = date.TimeOfDay.TotalDays;\n\n            // http://mathforum.org/library/drmath/view/62338.html\n            //The following algorithm is adapted from Jean Meeus' \"Astronomical \n            //Formulae for Calculators.\" \n\n            //Given a year YYYY, a month MM, and a day D, if the month is January\n            //or February(M = 1 or 2), replace let y = YYYY - 1 and let m = M + 13.\n            //Otherwise, let y = YYYY and m = M + 1.\n\n            //Compute A = int(y / 100), and let B = 2 - A + int(A / 4).\n\n            //Then the Julian Day number JD of this date is\n            //JD = int(365.25 * y) + int(30.6001 * m) + B + D + 1720995.\n\n            if (m < 3)\n            {\n                m = m + 13;\n                y--;\n            }\n            else\n            {\n                m += 1;\n            }\n\n            // 30.6001 is the days per month approximation (365-31-28)/10 (ie av month days without jan & feb)\n            var A = y / 100;\n            var B = 2 - A + A / 4;\n            var jd = Fun.Floor(365.25 * y) + Fun.Floor(30.6001 * m) + B + d + dt + 1720995;\n\n            return jd - 0.5;\n        }\n\n        static double ComputeGregorianDay(DateTime date)\n        {\n            var J = date.ComputeJulianDay();\n\n            // the following calculates the day of the month of a JD -> date.Day + date.TimeOfDay.TotalDays 1?\n            int p = (int)Fun.Floor(J + 0.5);\n            int s1 = p + 68569;\n            int n = (int)Fun.Floor(4 * s1 / (double)146097);\n            int s2 = s1 - (int)Fun.Floor(((double)146097 * n + 3) / 4);\n            int i = (int)Fun.Floor((double)4000 * (s2 + 1) / 1461001);\n            int s3 = s2 - (int)Fun.Floor((double)1461 * i / 4) + 31;\n            int q = (int)Fun.Floor((double)80 * s3 / 2447);\n            int e = s3 - (int)Fun.Floor((double)2447 * q / 80);\n            // int s4 = (int)System.Math.Floor((double)q / 11);\n            // int m = q + 2 - 12 * s4;\n            // int y = 100 * (n - 49) + i + s4;\n            double d = e + J - p + 0.5;\n            return d;\n        }\n\n        [Test]\n        public static void JulianDay()\n        {\n            var rnd = new RandomSystem(123);\n\n            TestDate(new DateTime(2019, 3, 5, 12, 0, 0, 0));\n            TestDate(new DateTime(2019, 3, 5, 12, 1, 0, 0));\n            TestDate(new DateTime(2019, 3, 5, 11, 59, 0, 0));\n\n            // https://en.wikipedia.org/wiki/Julian_day\n            // 00:30:00.0 UT January 1, 2013, is 2 456 293.520 833\n            var test2 = new DateTime(2013, 1, 1, 0, 30, 0);\n            TestDate(test2);\n\n            for (int i = 0; i < 10000000; i++)\n            {\n                var lg = rnd.UniformLong();\n                if (lg > DateTime.MaxValue.Ticks || lg < DateTime.MinValue.Ticks)\n                    continue;\n\n                var dt = new DateTime(lg);\n\n                TestDate(dt);\n            }\n\n            Report.Line(\"Times: (NOTE benchmark meaningless, measurement of first algorithm will always have x3 time)\");\n            Report.Line(\"GetDatePart: {0}ms\", sw0.Elapsed.TotalMilliseconds);\n            Report.Line(\"ComputeJulianDayNREL: {0}ms\", sw1.Elapsed.TotalMilliseconds);\n            Report.Line(\"ComputeJulianDayInt2: {0}ms\", sw2.Elapsed.TotalMilliseconds);\n            Report.Line(\"ComputeJulianDayMeeus: {0}ms\", sw3.Elapsed.TotalMilliseconds);\n            Report.Line(\"ComputeJulianDayInt: {0}ms\", sw4.Elapsed.TotalMilliseconds);\n            Report.Line(\"ComputeJulianDayRaw: {0}ms\", sw5.Elapsed.TotalMilliseconds);\n        }\n\n        static readonly Stopwatch sw0 = new Stopwatch();\n        static readonly Stopwatch sw1 = new Stopwatch();\n        static readonly Stopwatch sw2 = new Stopwatch();\n        static readonly Stopwatch sw3 = new Stopwatch();\n        static readonly Stopwatch sw4 = new Stopwatch();\n        static readonly Stopwatch sw5 = new Stopwatch();\n        static int warpup = 10000;\n\n        static void TestDate(DateTime date)\n        {\n            warpup--;\n\n            // NOTE: benchmark meaningless, first algorithm will have x3 time\n            if (warpup < 0) sw1.Start();\n            var jd1 = ComputeJulianDayNREL(date); // has strange condition for gregorian date < year 1582\n            if (warpup < 0) sw1.Stop();\n\n            if (warpup < 0) sw2.Start();\n            var jd2 = ComputeJulianDayInt2(date);\n            if (warpup < 0) sw2.Stop();\n\n            if (warpup < 0) sw3.Start();\n            var jd3 = ComputeJulianDayMeeus(date);\n            if (warpup < 0) sw3.Stop();\n\n            if (warpup < 0) sw4.Start();\n            var jd4 = ComputeJulianDayInt(date);\n            if (warpup < 0) sw4.Stop();\n\n            // NOTE: there would be any internal void GetDatePart(out int year, out int month, out int day) hidden in the .net framework\n            if (warpup < 0) sw0.Start();\n            var year = date.Year;\n            var month = date.Month;\n            var day = date.Day;\n            if (warpup < 0) sw0.Stop();\n\n            if (warpup < 0) sw5.Start();\n            var jd5 = (double)ComputeJulianDay(year, month, day);\n            if (warpup < 0) sw5.Stop();\n\n            jd5 += date.TimeOfDay.TotalDays - 0.5;\n\n            var jdAard = date.ComputeJulianDay();\n\n            //Report.Line(\"Date={0} Julian Day NREL: {1} ALT:{2}\", date, (int)jd1, (int)jd2);\n\n            if (!jd1.ApproximateEquals(jd2, 1e-07) || !jd1.ApproximateEquals(jd3, 1e-07) || !jd1.ApproximateEquals(jd4, 1e-07) || !jd1.ApproximateEquals(jdAard, 1e-7))\n            {\n                Report.Line(\"Date={0} Julian Day NREL: {1} ALT:{2}\", date, (int)jd1, (int)jd2);\n                Report.Line(\"FAIL\");\n            }\n\n            var gd = ComputeGregorianDay(date);\n            var gd1 = date.Day + date.TimeOfDay.TotalDays;\n\n            var gdAard = DateTimeExtensions.GregorianDayOfMonthFromJulianDay(jd1);\n\n            if (!gd.ApproximateEquals(gd1, 1e-5) || !gd.ApproximateEquals(gdAard, 1e-5))\n            {\n                Report.Line(\"Date={0} Julian Day: {1} Gregorian Day: {2} {3} {4}\", date, jd1, gd, gd1, gdAard);\n                Report.Line(\"FAIL\");\n            }\n\n\n            var date2 = DateTimeExtensions.ComputeDateFromJulianDay(jd1);\n            var dt = date - date2;\n            if ((int)dt.TotalSeconds != 0)\n            {\n                Report.Line(\"DateIn={0} Julian Day={1} DateOut={2}\", date, jd1, date2);\n                Report.Line(\"FAIL\");\n            }\n\n            if (year > 1)\n            {\n                var date3 = DateTimeExtensions.ComputeDateFromJulianDay((int)jd1);\n                var tmp = new DateTime(year, month, day, 12, 0, 0); // 12h noon\n                if (jd1.Frac() > 0.5)\n                    tmp = tmp.AddDays(-1);\n                var dt2 = tmp - date3;\n                if ((int)dt2.TotalSeconds != 0)\n                {\n                    Report.Line(\"DateIn={0} Julian Day={1} DateOut={2}\", tmp, jd1, date3);\n                    Report.Line(\"FAIL\");\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/Enumerable.cs",
    "content": "﻿using NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing Aardvark.Base;\nusing System.Linq;\n\nnamespace Aardvark.Tests.Extensions\n{\n    static class Enumerables\n    {\n        private sealed class SingleUseEnumerable<T> : IEnumerable<T>\n        {\n            private readonly IEnumerable<T> m_values;\n            private bool m_used;\n\n            public SingleUseEnumerable(IEnumerable<T> values)\n            {\n                m_values = values;\n            }\n\n            public int EnumeratorCount { get; private set; }\n\n            public IEnumerator<T> GetEnumerator()\n            {\n                if (m_used)\n                    throw new InvalidOperationException(\"The sequence was enumerated more than once.\");\n\n                m_used = true;\n                EnumeratorCount++;\n                return m_values.GetEnumerator();\n            }\n\n            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();\n        }\n\n        [Test]\n        public static void MaxIndex()\n        {\n            var en = 0.UpTo(5);\n\n            var maxIndex = en.MaxIndex();\n            var maxValue = en.Max();\n            Assert.True(en.ElementAt(maxIndex) == maxValue);\n\n            Assert.True(0.IntoIEnumerable().MaxIndex() == 0);\n\n            Assert.True(Enumerable.Empty<int>().MaxIndex() < 0);\n        }\n\n        [Test]\n        public static void MinIndex()\n        {\n            var en = 0.UpTo(5);\n\n            var minIndex = en.MinIndex();\n            var minValue = en.Min();\n            Assert.True(en.ElementAt(minIndex) == minValue);\n\n            Assert.True(0.IntoIEnumerable().MinIndex() == 0);\n\n            Assert.True(Enumerable.Empty<int>().MinIndex() < 0);\n        }\n\n        [Test]\n        public static void SelectToListFromArray()\n        {\n            var source = new[] { 1, 2, 3 };\n\n            var result = source.SelectToList(x => $\"v{x * 2}\");\n\n            CollectionAssert.AreEqual(new[] { \"v2\", \"v4\", \"v6\" }, result);\n        }\n\n        [Test]\n        public static void SelectToListFromList()\n        {\n            var source = new List<string> { \"a\", \"bb\", \"ccc\" };\n\n            var result = source.SelectToList(x => x.Length);\n\n            CollectionAssert.AreEqual(new[] { 1, 2, 3 }, result);\n        }\n\n        [Test]\n        public static void AllDistinctHandlesTrivialAndNormalCases()\n        {\n            IEnumerable<int> nullValues = null;\n\n            Assert.IsTrue(nullValues.AllDistinct());\n            Assert.IsTrue(Enumerable.Empty<int>().AllDistinct());\n            Assert.IsTrue(new[] { 1 }.AllDistinct());\n            Assert.IsTrue(new[] { 1, 2, 3 }.AllDistinct());\n            Assert.IsFalse(new[] { 1, 2, 1 }.AllDistinct());\n        }\n\n        [Test]\n        public static void AllEqualHandlesTrivialAndNormalCases()\n        {\n            IEnumerable<int> nullValues = null;\n\n            Assert.IsTrue(nullValues.AllEqual());\n            Assert.IsTrue(Enumerable.Empty<int>().AllEqual());\n            Assert.IsTrue(new[] { 1 }.AllEqual());\n            Assert.IsTrue(new[] { 1, 1, 1 }.AllEqual());\n            Assert.IsFalse(new[] { 1, 1, 2 }.AllEqual());\n        }\n\n        [Test]\n        public static void AllDistinctUsesOneEnumerator()\n        {\n            var distinct = new SingleUseEnumerable<int>(new[] { 1, 2, 3 });\n            var duplicate = new SingleUseEnumerable<int>(new[] { 1, 2, 1 });\n\n            Assert.IsTrue(distinct.AllDistinct());\n            Assert.AreEqual(1, distinct.EnumeratorCount);\n\n            Assert.IsFalse(duplicate.AllDistinct());\n            Assert.AreEqual(1, duplicate.EnumeratorCount);\n        }\n\n        [Test]\n        public static void AllEqualUsesOneEnumerator()\n        {\n            var equal = new SingleUseEnumerable<int>(new[] { 1, 1, 1 });\n            var unequal = new SingleUseEnumerable<int>(new[] { 1, 1, 2 });\n\n            Assert.IsTrue(equal.AllEqual());\n            Assert.AreEqual(1, equal.EnumeratorCount);\n\n            Assert.IsFalse(unequal.AllEqual());\n            Assert.AreEqual(1, unequal.EnumeratorCount);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/Hashes.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection.Emit;\nusing System.Runtime.InteropServices;\nusing System.Security.Cryptography;\n\nnamespace Aardvark.Tests.Extensions\n{\n    public static class Hashes\n    {\n        [Test]\n        public static void ArrayHashExtensions()\n        {\n            var floats = new float[10].SetByIndex(i => i);\n\n\n            var inty = new int[20].SetByIndex(i => i);\n            var v2iy = new V2i[10].SetByIndex(i => new V2i(2 * i, 2 * i + 1));\n\n            var intHash = inty.ComputeSHA1Hash().ToHex();\n            var v2iHash = v2iy.ComputeSHA1Hash().ToHex();\n            \n            Assert.IsTrue(intHash == v2iHash);\n            \n            \n            \n            var md5 = floats.ComputeMD5Hash();\n            Report.Line(\"MD5: {0}\", md5.ToHex());\n            Assert.IsTrue(md5.Length == 16);\n\n            var sha1 = floats.ComputeSHA1Hash();\n            Report.Line(\"SHA1: {0}\", sha1.ToHex());\n            Assert.IsTrue(sha1.Length == 20);\n\n            var sha256 = floats.ComputeSHA256Hash();\n            Report.Line(\"SHA256: {0}\", sha256.ToHex());\n            Assert.IsTrue(sha256.Length == 32);\n\n            var sha512 = floats.ComputeSHA512Hash();\n            Report.Line(\"SHA512: {0}\", sha512.ToHex());\n            Assert.IsTrue(sha512.Length == 64);\n\n            var adler = floats.ComputeAdler32Checksum();\n            Report.Line(\"Checksum: {0:X}\", adler);\n\n            floats[9] = 10;\n\n            var md5New = floats.ComputeMD5Hash();\n            Report.Line(\"MD5: {0}\", md5New.ToHex());\n            Assert.True(md5New.ToHex() != md5.ToHex());\n\n            var sha1New = floats.ComputeSHA1Hash();\n            Report.Line(\"SHA1: {0}\", sha1New.ToHex());\n            Assert.True(sha1New.ToHex() != sha1.ToHex());\n\n            var sha256New = floats.ComputeSHA256Hash();\n            Report.Line(\"SHA256: {0}\", sha256New.ToHex());\n            Assert.True(sha256New.ToHex() != sha256.ToHex());\n\n            var sha512New = floats.ComputeSHA512Hash();\n            Report.Line(\"SHA512: {0}\", sha512New.ToHex());\n            Assert.True(sha512New.ToHex() != sha512.ToHex());\n\n            var adlerNew = floats.ComputeAdler32Checksum();\n            Report.Line(\"Checksum: {0:X}\", adlerNew);\n            Assert.True(adlerNew != adler);\n        }\n\n        [Test]\n        public static void Adler32UpdateByteArrayNullThrowsArgumentNullException()\n        {\n            var adler = new Adler32();\n\n            var ex = Assert.Throws<ArgumentNullException>(() => adler.Update((byte[])null));\n            Assert.AreEqual(\"buffer\", ex.ParamName);\n        }\n\n        [Test]\n        public static void Adler32UpdateStreamNullThrowsArgumentNullException()\n        {\n            var adler = new Adler32();\n\n            var ex = Assert.Throws<ArgumentNullException>(() => adler.Update((Stream)null));\n            Assert.AreEqual(\"stream\", ex.ParamName);\n        }\n\n        [TestCase(-1, 1)]\n        [TestCase(0, -1)]\n        [TestCase(2, 3)]\n        [TestCase(int.MaxValue, 1)]\n        public static void Adler32UpdateInvalidArrayRangeThrowsArgumentOutOfRangeException(int offset, int length)\n        {\n            var adler = new Adler32();\n\n            Assert.Throws<ArgumentOutOfRangeException>(() => adler.Update(new byte[4], offset, length));\n        }\n\n        [Test]\n        public static void Adler32UpdateValidRangePreservesChecksum()\n        {\n            var adler = new Adler32();\n\n            adler.Update(new byte[] { 1, 2, 3, 4, 5 }, 1, 3);\n\n            Assert.AreEqual(0x0013000Au, adler.Checksum);\n        }\n\n        [Test]\n        public static void ArrayHashPerformance()\n        {\n            var mb = 256;\n            var huge = new byte[(1 << 20) * mb].SetByIndex(i => (byte)((i * 7L) & 0xff));\n\n            Report.BeginTimed(\"Computing MD5 Hash of {0}MB data array\", mb);\n            huge.ComputeMD5Hash();\n            Report.End();\n\n            Report.BeginTimed(\"Computing SHA1 Hash of {0}MB data array\", mb);\n            huge.ComputeSHA1Hash();\n            Report.End();\n\n            Report.BeginTimed(\"Computing SHA256 Hash of {0}MB data array\", mb);\n            huge.ComputeSHA256Hash();\n            Report.End();\n\n            Report.BeginTimed(\"Computing SHA512 Hash of {0}MB data array\", mb);\n            huge.ComputeSHA512Hash();\n            Report.End();\n\n            Report.BeginTimed(\"Computing Adler-32 Checksum of {0}MB data array\", mb);\n            huge.ComputeAdler32Checksum();\n            Report.End();\n        }\n\n        /// <summary>\n        /// Would be nice utils but are not .net standard compatible\n        /// </summary>\n        public static class CLRUtils\n        {\n            public static int SizeOf<T>(T obj)\n            {\n                return SizeOfCache<T>.SizeOf;\n            }\n\n            private static class SizeOfCache<T>\n            {\n                public static readonly int SizeOf;\n\n                static SizeOfCache()\n                {\n                    var dm = new DynamicMethod(\"func\", typeof(int),\n                                               Type.EmptyTypes, typeof(CLRUtils));\n\n                    ILGenerator il = dm.GetILGenerator();\n                    il.Emit(OpCodes.Sizeof, typeof(T));\n                    il.Emit(OpCodes.Ret);\n\n                    var func = (Func<int>)dm.CreateDelegate(typeof(Func<int>));\n                    SizeOf = func();\n                }\n            }\n\n            private static readonly Dictionary<Type, int> _sizeCache = new Dictionary<Type, int>();\n            public static int SizeOf(Type type)\n            {\n                return _sizeCache.GetCreate(type, t =>\n                {\n                    var dm = new DynamicMethod(\"func\", typeof(int),\n                                                   Type.EmptyTypes, typeof(CLRUtils));\n\n                    ILGenerator il = dm.GetILGenerator();\n                    il.Emit(OpCodes.Sizeof, t);\n                    il.Emit(OpCodes.Ret);\n\n                    var func = (Func<int>)dm.CreateDelegate(typeof(Func<int>));\n                    return func();\n                });\n            }\n        }\n\n        [Test]\n        public static void HashEquality()\n        {   // -> scroll                                                                                                                                                                                                                                                                   //######################//\n            var a = \"PFDMHE3qf5BD2GVXHSb7Pw==Xu6fEt3zjgNOhgcgU6P3VA==hrptgTUY1q95BRjYpBlcuA==rKx+IsdlT3wMNiC1su/Ciw==yWz34lIfOgRXNbbCM2Xg6Q==OkYVqxAg1+r/xOoNgTzO5w==jHm9kCMmSmFskgSQYae3EA==9osN2zSiH4XFSOdNoQq7Yg==xhvrPfi5l7GYy0Ka4pwp7w==aWze5ohFCFkxZMZPqTLfsA==iUU+2nRevMAYlHQgrjKfyQ==74FhaizLzpPAPHZ0h/Emsw==KbzIWiTHRlFG5Whs3YYzyA==M/G8RpD5bp9kRKLDFHy9qg==Wv+3r9IY0lfPq+LUAtNPsQ==j8/23gUX4FzrEOPzcpAhcA==\";\n            var b = \"PFDMHE3qf5BD2GVXHSb7Pw==Xu6fEt3zjgNOhgcgU6P3VA==hrptgTUY1q95BRjYpBlcuA==rKx+IsdlT3wMNiC1su/Ciw==yWz34lIfOgRXNbbCM2Xg6Q==OkYVqxAg1+r/xOoNgTzO5w==jHm9kCMmSmFskgSQYae3EA==9osN2zSiH4XFSOdNoQq7Yg==xhvrPfi5l7GYy0Ka4pwp7w==aWze5ohFCFkxZMZPqTLfsA==iUU+2nRevMAYlHQgrjKfyQ==dqrZpWI5/PzQhFpHLVPaKw==KbzIWiTHRlFG5Whs3YYzyA==M/G8RpD5bp9kRKLDFHy9qg==Wv+3r9IY0lfPq+LUAtNPsQ==j8/23gUX4FzrEOPzcpAhcA==\";\n\n            var arrayA = a.ToArray();\n            var arrayB = b.ToArray();\n\n            var md5A = arrayA.ComputeMD5Hash().ToHex();\n            var md5B = arrayB.ComputeMD5Hash().ToHex();\n\n            if (md5A == md5B)\n                Assert.Fail(\"MD5 BAD -> actually UnsafeCoerce char to byte fails due to Marshal.SizeOf != sizeof()\");\n            \n            var etA = arrayA.GetType().GetElementType();\n            var clrSizeA = CLRUtils.SizeOf(etA); // 2\n            var marshalSizeA = Marshal.SizeOf(etA); // 1\n            \n            var bytesA = arrayA.Map(x => (short)x);\n            var bytesB = arrayB.Map(x => (short)x);\n\n            var byteHashA = bytesA.ComputeMD5Hash().ToHex();\n            var byteHashB = bytesB.ComputeMD5Hash().ToHex();\n\n            if (byteHashA == byteHashB)\n                Assert.Fail(\"MD5 REAL BAD\");\n\n            if (byteHashA != md5A)\n                Assert.Fail(\"HASH A BAD\");\n\n            if (byteHashB != md5B)\n                Assert.Fail(\"HASH B BAD\");\n        }\n\n        public struct MyStruct1\n        {\n            public bool fun1;\n            public bool fun2;\n        }\n\n        public struct MyStruct2\n        {\n            public char fun1;\n            public char fun2;\n        }\n\n        public struct MyStruct3\n        {\n            public bool fun1;\n            public char fun2;\n        }\n\n        public struct MyStruct4\n        {\n            public MyStruct2 fun1;\n            public MyStruct1 fun2;\n        }\n\n        public static void SizeOfTest()\n        {\n            TestSize<byte>();\n            TestSize<short>();;\n            TestSize<int>();\n            TestSize<long>();\n            TestSize<char>();\n            TestSize<float>();\n            TestSize<double>();\n            TestSize<decimal>();\n            TestSize<bool>();\n            TestSize<MyStruct1>();\n            TestSize<MyStruct2>();\n            TestSize<MyStruct3>();\n            TestSize<MyStruct4>();\n        }\n\n        static void TestSize<T>()\n        {\n            var clrSize = CLRUtils.SizeOf(typeof(T));\n            var marshalSize = Marshal.SizeOf<T>();\n            if (clrSize != marshalSize)\n                Report.Line(\"{0} size {1} != {2}\", typeof(T).Name, clrSize, marshalSize);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/ListHeapTests.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class ListHeapTests : TestSuite\n    {\n        public ListHeapTests() : base() { }\n        public ListHeapTests(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public void TestListHeap()\n        {\n            ListHeapTest(1 << 18, i => false);\n            ListHeapRandomDequeueTest(1 << 18, i => false);\n        }\n\n        public void Run()\n        {\n            ListHeapTest(1 << 22, i => i <= 256);\n            ListHeapRandomDequeueTest(1 << 22, i => i <= 256);\n        }\n\n        public void ListHeapTest(int maxCount, Func<int, bool> count_printFun)\n        {\n            Test.Begin(\"HeapTest\");\n            for (int i = 1; i <= maxCount; i *= 2)\n                ListHeapTest(i, count_printFun(i));\n            Test.End();\n        }\n\n        public void ListHeapTest(int count, bool print)\n        {\n            Test.Begin(\"heap size {0}\", count);\n            var rnd = new RandomSystem(count);\n            Report.BeginTimed(\"creating array\");\n            var array = rnd.CreatePermutationArray(count);\n            Report.End();\n            var heap = new List<int>();\n\n            Report.BeginTimed(\"enqueueing items\");\n            foreach (var item in array)\n                heap.HeapAscendingEnqueue(item);\n            Report.End();\n\n            Test.Begin(\"dequeueing items\");\n\n            var pos = 0;\n            if (print)\n            {\n                while (heap.Count > 0)\n                {\n                    var item = heap.HeapAscendingDequeue();\n                    Test.IsTrue(pos == item, \"item[{0}] = {1}\", pos, item);\n                    ++pos;\n                    Report.Text(\"{0,3},\", item);\n                    if ((pos & 0xf) == 0) Report.Line();\n                }\n            }\n            else\n            {\n                while (heap.Count > 0)\n                {\n                    var item = heap.HeapAscendingDequeue();\n                    Test.IsTrue(pos == item, \"item[{0}] = {1}\", pos, item);\n                    ++pos;\n                }\n            }\n            Test.End();\n            Test.End();\n        }\n\n        public void ListHeapRandomDequeueTest(int maxCount, Func<int, bool> count_printFun)\n        {\n            Report.BeginTimed(\"HeapRandomDequeueTest\");\n            for (int i = 1; i <= maxCount; i *= 2)\n                ListHeapRandomDequeueTest(i, count_printFun(i));\n            Report.End();\n        }\n\n        public void ListHeapRandomDequeueTest(int count, bool print)\n        {\n            Test.Begin(\"heap size {0}\", count);\n            var rnd = new RandomSystem(count);\n            Report.BeginTimed(\"creating array\");\n            var array = rnd.CreatePermutationArray(count);\n            Report.End();\n            var heap = new List<int>();\n\n            Report.BeginTimed(\"enqueueing items\");\n            foreach (var item in array)\n                heap.HeapAscendingEnqueue(item);\n            Report.End();\n\n            Report.BeginTimed(\"dequeueing random items\");\n\n            var last = -1;\n            int removed;\n            for (removed = 0; last != 0; removed++)\n                last = heap.HeapAscendingRemoveAt(rnd.UniformInt(heap.Count));\n\n            Report.End(\": {0}\", removed);\n\n            Test.Begin(\"dequeueing items\");\n\n            if (print)\n            {\n                int pos = 0;\n                int old = -1;\n                while (heap.Count > 0)\n                {\n                    var item = heap.HeapAscendingDequeue();\n                    Test.IsTrue(old <= item, \"wrong order: {0} > {1}\", old, item);\n                    old = item;\n                    Report.Text(\"{0,3},\", item);\n                    if ((++pos & 0xf) == 0) Report.Line();\n                }\n            }\n            else\n            {\n                int old = -1;\n                while (heap.Count > 0)\n                {\n                    var item = heap.HeapAscendingDequeue();\n                    Test.IsTrue(old <= item, \"wrong order: {0} > {1}\", old, item);\n                    old = item;\n                }\n            }\n            Test.End();\n            Test.End();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/Lists.cs",
    "content": "using NUnit.Framework;\nusing Aardvark.Base;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Tests.Extensions\n{\n    static class Lists\n    {\n        [Test]\n        public static void ListFunMap3TruncatesToThirdList()\n        {\n            var list0 = new List<int> { 10, 20, 30, 40 };\n            var list1 = new List<int> { 1, 2, 3, 4 };\n            var list2 = new List<int> { 100, 200 };\n\n            var result = list0.Map3(list1, list2, (a, b, c) => a + b + c);\n\n            CollectionAssert.AreEqual(new[] { 111, 222 }, result);\n        }\n\n        [Test]\n        public static void ListFunMap3IndexedTruncatesToThirdListAndPreservesIndex()\n        {\n            var list0 = new List<string> { \"a\", \"b\", \"c\" };\n            var list1 = new List<string> { \"x\", \"y\", \"z\" };\n            var list2 = new List<string> { \"p\", \"q\" };\n\n            var result = list0.Map3(list1, list2, (a, b, c, i) => $\"{i}:{a}{b}{c}\");\n\n            CollectionAssert.AreEqual(new[] { \"0:axp\", \"1:byq\" }, result);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/StreamTests.cs",
    "content": "﻿using NUnit.Framework;\nusing System;\nusing System.Reflection;\nusing System.IO;\nusing Aardvark.Base;\nusing System.Runtime.ExceptionServices;\n\nnamespace Aardvark.Tests.Extensions\n{\n    internal class TestStream(Stream inner) : Stream\n    {\n        private bool isDiposed = false;\n        private readonly RandomSystem rnd = new RandomSystem();\n\n        public TestStream(byte[] data) : this(new MemoryStream(data))\n        { }\n\n        public override bool CanRead => inner.CanRead;\n\n        public override bool CanSeek => inner.CanSeek;\n\n        public override bool CanWrite => inner.CanWrite;\n\n        public override long Length => inner.Length;\n\n        public override long Position\n        {\n            get => inner.Position;\n            set => inner.Position = value;\n        }\n\n        public override void Flush() => inner.Flush();\n\n        public override long Seek(long offset, SeekOrigin origin) => inner.Seek(offset, origin);\n\n        public override void SetLength(long value) => inner.SetLength(value);\n\n        public override int Read(byte[] buffer, int offset, int count)\n        {\n            if (count > 1)\n            {\n                count = 1 + rnd.UniformInt(count - 1);\n            }\n\n            return inner.Read(buffer, offset, count);\n        }\n\n        public override void Write(byte[] buffer, int offset, int count)\n        {\n            inner.Write(buffer, offset, count);\n        }\n\n        protected override void Dispose(bool disposing)\n        {\n            if (!isDiposed) inner.Dispose();\n            isDiposed = true;\n        }\n    }\n\n    static class StreamTests\n    {\n        private static MethodInfo NetStandardReadBytesMethod\n        {\n            get\n            {\n                var outputDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);\n                var assemblyPath = Path.GetFullPath(Path.Combine(outputDirectory!, \"..\", \"netstandard2.0\", \"Aardvark.Base.dll\"));\n\n                Assert.That(\n                    File.Exists(assemblyPath),\n                    Is.True,\n                    $\"Expected sibling netstandard2.0 Aardvark.Base assembly at '{assemblyPath}'.\"\n                );\n\n                // We want to test the netstandard2.0 implementation, is there an easier way?\n                var asm = Assembly.LoadFile(assemblyPath);\n                var ext = asm.GetType($\"Aardvark.Base.{nameof(StreamExtensions)}\");\n                Type[] parameters = [typeof(Stream), typeof(byte[]), typeof(int), typeof(int)];\n                return ext.GetMethod(nameof(StreamExtensions.ReadBytes), parameters);\n            }\n        }\n\n        private static void ReadBytes(bool netStandard20, Stream stream, byte[] buffer, int offset = 0, int count = -1)\n        {\n            if (netStandard20)\n            {\n                try\n                {\n                    NetStandardReadBytesMethod.Invoke(null, [stream, buffer, offset, count]);\n                }\n                catch (TargetInvocationException e) when (e.InnerException != null)\n                {\n                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();\n                }\n            }\n            else\n            {\n                stream.ReadBytes(buffer, offset, count);\n            }\n        }\n\n        [Test]\n        public static void ReadBytes([Values(false, true)] bool netStandard20)\n        {\n            var rnd = new RandomSystem();\n            var data = new byte[1234];\n            for (int i = 0; i < data.Length; i++) data[i] = (byte)rnd.UniformInt();\n\n            using TestStream s = new TestStream(data);\n            var result = new byte[57];\n            var offset = 3;\n            var count = result.Length - offset;\n\n            ReadBytes(netStandard20, s, result, offset, count);\n\n            for (int i = 0; i < count; i++)\n                Assert.AreEqual(data[i], result[i + offset]);\n        }\n\n        [Test]\n        public static void ReadBytesRejectsNullStream([Values(false, true)] bool netStandard20)\n        {\n            var e = Assert.Throws<ArgumentNullException>(() => ReadBytes(netStandard20, null, new byte[1]));\n            Assert.AreEqual(\"stream\", e.ParamName);\n        }\n\n        [Test]\n        public static void ReadBytesRejectsNullBufferWithDefaultCount([Values(false, true)] bool netStandard20)\n        {\n            using TestStream s = new TestStream([1]);\n\n            var e = Assert.Throws<ArgumentNullException>(() => ReadBytes(netStandard20, s, null));\n            Assert.AreEqual(\"buffer\", e.ParamName);\n        }\n\n        [Test]\n        public static void ReadBytesRejectsNegativeOffset([Values(false, true)] bool netStandard20)\n        {\n            using TestStream s = new TestStream([1]);\n\n            var e = Assert.Throws<ArgumentOutOfRangeException>(() => ReadBytes(netStandard20, s, new byte[1], -1, 1));\n            Assert.AreEqual(\"offset\", e.ParamName);\n        }\n\n        [Test]\n        public static void ReadBytesRejectsCountPastBufferEnd([Values(false, true)] bool netStandard20)\n        {\n            using TestStream s = new TestStream([1, 2]);\n\n            var e = Assert.Throws<ArgumentException>(() => ReadBytes(netStandard20, s, new byte[2], 1, 2));\n            Assert.AreEqual(\"count\", e.ParamName);\n        }\n\n        [Test]\n        public static void ReadBytesThrowsEndOfStreamWhenSourceIsShort([Values(false, true)] bool netStandard20)\n        {\n            using TestStream s = new TestStream([1]);\n\n            Assert.Throws<EndOfStreamException>(() => ReadBytes(netStandard20, s, new byte[2], 0, 2));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/Strings.cs",
    "content": "using NUnit.Framework;\nusing Aardvark.Base;\n\nnamespace Aardvark.Tests.Extensions\n{\n    static class Strings\n    {\n        [Test]\n        public static void PluralHandlesEmptyString()\n        {\n            Assert.AreEqual(\"s\", \"\".Plural(2));\n        }\n\n        [Test]\n        public static void PluralHandlesOneCharacterWord()\n        {\n            Assert.AreEqual(\"xs\", \"x\".Plural(2));\n        }\n\n        [Test]\n        public static void PluralWithCountOneReturnsOriginalShortWord()\n        {\n            Assert.AreEqual(\"x\", \"x\".Plural(1));\n        }\n\n        [Test]\n        public static void PluralPreservesExistingSuffixRule()\n        {\n            Assert.AreEqual(\"indices\", \"index\".Plural(2));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Extensions/TaskWithCancellationTests.cs",
    "content": "using Aardvark.Base;\nusing NUnit.Framework;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Tests.Extensions\n{\n    static class TaskWithCancellationTests\n    {\n        [Test]\n        public static void WithCancellationReturnsCanceledTaskForAlreadyCanceledToken()\n        {\n            using var cts = new CancellationTokenSource();\n            cts.Cancel();\n\n            var source = new TaskCompletionSource<int>();\n            var result = source.Task.WithCancellation(cts.Token);\n\n            Assert.That(result.IsCompleted, Is.True);\n            Assert.That(result.IsCanceled, Is.True);\n        }\n\n        [Test]\n        public static void WithCancellationReturnsCanceledTaskForAlreadyCanceledNullableToken()\n        {\n            using var cts = new CancellationTokenSource();\n            cts.Cancel();\n\n            var source = new TaskCompletionSource<int>();\n            var result = source.Task.WithCancellation((CancellationToken?)cts.Token);\n\n            Assert.That(result.IsCompleted, Is.True);\n            Assert.That(result.IsCanceled, Is.True);\n        }\n\n        [Test]\n        public static void WithCancellationKeepsCompletedTaskForAlreadyCanceledToken()\n        {\n            using var cts = new CancellationTokenSource();\n            cts.Cancel();\n\n            var task = Task.FromResult(1);\n            var result = task.WithCancellation(cts.Token);\n\n            Assert.That(result, Is.SameAs(task));\n            Assert.That(result.Result, Is.EqualTo(1));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Geometry/Circle2dTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing static System.Math;\n\nnamespace Aardvark.Tests.Geometry\n{\n    [TestFixture]\n    public class Circle2dTests\n    {\n        [Test]\n        public void Circle2d_Constructor1()\n        {\n            var a = new Circle2d(new V2d(1.2, 4.7), 3.14);\n            Assert.IsTrue(a.Center == new V2d(1.2, 4.7));\n            Assert.IsTrue(a.Radius == 3.14);\n            Assert.IsTrue(!a.IsInvalid);\n            Assert.IsTrue(a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Constructor2()\n        {\n            var a = new Circle2d(new V2d(1.2, 4.7), new V2d(1.2, 6.7));\n            Assert.IsTrue(a.Center == new V2d(1.2, 4.7));\n            Assert.IsTrue(a.Radius == 2);\n            Assert.IsTrue(!a.IsInvalid);\n            Assert.IsTrue(a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Constructor3()\n        {\n            var a = new Circle2d(new V2d(1, 0), new V2d(2, 1), new V2d(3, 0));\n            Assert.IsTrue(a.Center == new V2d(2, 0));\n            Assert.IsTrue(a.Radius == 1);\n            Assert.IsTrue(!a.IsInvalid);\n            Assert.IsTrue(a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Zero()\n        {\n            var a = Circle2d.Zero;\n            Assert.IsTrue(!a.IsInvalid);\n            Assert.IsTrue(a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Unit()\n        {\n            var a = Circle2d.Unit;\n            Assert.IsTrue(!a.IsInvalid);\n            Assert.IsTrue(a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Invalid()\n        {\n            var a = Circle2d.Invalid;\n            Assert.IsTrue(a.IsInvalid);\n            Assert.IsTrue(!a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Invalid2()\n        {\n            var a = new Circle2d(V2d.NaN, 1.0);\n            Assert.IsTrue(a.IsInvalid);\n            Assert.IsTrue(!a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Invalid3()\n        {\n            var a = new Circle2d(V2d.Zero, double.NaN);\n            Assert.IsTrue(a.IsInvalid);\n            Assert.IsTrue(!a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Invalid4()\n        {\n            var a = new Circle2d(V2d.NaN, double.NaN);\n            Assert.IsTrue(a.IsInvalid);\n            Assert.IsTrue(!a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_Invalid5()\n        {\n            var a = new Circle2d(V2d.Zero, -1);\n            Assert.IsTrue(a.IsInvalid);\n            Assert.IsTrue(!a.IsValid);\n        }\n\n        [Test]\n        public void Circle2d_RadiusSquared()\n        {\n            var a = new Circle2d(V2d.Zero, 2.0);\n            Assert.IsTrue(a.RadiusSquared == 4.0);\n        }\n\n        [Test]\n        public void Circle2d_Circumference()\n        {\n            var a = new Circle2d(V2d.Zero, 3.0);\n            Assert.IsTrue(a.Circumference == 6 * PI);\n        }\n        \n        [Test]\n        public void Circle2d_Area()\n        {\n            var a = new Circle2d(V2d.Zero, 3.0);\n            Assert.IsTrue(a.Area == 9 * PI);\n        }\n\n        [Test]\n        public void Circle2d_Contains()\n        {\n            var a = new Circle2d(new V2d(5, 0), 3);\n            Assert.IsTrue(a.Contains(new V2d(7, 2)));\n            Assert.IsTrue(a.Contains(new V2d(8, 0)));\n            Assert.IsTrue(!a.Contains(new V2d(0, 0)));\n            Assert.IsTrue(!a.Contains(new V2d(5, 9)));\n            Assert.IsTrue(!a.Contains(new V2d(8.000001, 0)));\n        }\n\n        [Test]\n        public void Circle2d_InscribedSquare()\n        {\n            var a = new Circle2d(V2d.Zero, Constant.Sqrt2);\n            var s = a.InscribedSquare;\n            Assert.IsTrue(s.Center == V2d.Zero);\n            Assert.IsTrue(s.Min == new V2d(-1));\n            Assert.IsTrue(s.Max == new V2d(+1));\n        }\n\n        [Test]\n        public void Circle2d_HashCode1()\n        {\n            var a = new Circle2d(V2d.Zero, 1.0);\n            var b = new Circle2d(V2d.Zero, 2.0);\n            Assert.IsTrue(a.GetHashCode() != b.GetHashCode());\n        }\n\n        [Test]\n        public void Circle2d_HashCode2()\n        {\n            var a = new Circle2d(V2d.Zero, 1.0);\n            var b = new Circle2d(V2d.Zero, double.NaN);\n            Assert.IsTrue(a.GetHashCode() != b.GetHashCode());\n        }\n\n        [Test]\n        public void Circle2d_HashCode3()\n        {\n            var a = new Circle2d(V2d.Zero, 1.0);\n            var b = new Circle2d(V2d.NaN, 1.0);\n            Assert.IsTrue(a.GetHashCode() != b.GetHashCode());\n        }\n\n        [Test]\n        public void Circle2d_Equals()\n        {\n            var a = new Circle2d(V2d.Zero, 1.0);\n            var b = new Circle2d(V2d.Zero, 1.0);\n            Assert.IsTrue(a.Equals(b));\n            Assert.IsTrue(!a.Equals(null));\n        }\n\n        [Test]\n        public void Circle2d_Parse1()\n        {\n            var a = new Circle2d(new V2d(1.2, 3.4), 5.6);\n            var b = Circle2d.Parse(a.ToString());\n            Assert.IsTrue(a.Equals(b));\n        }\n\n        [Test]\n        public void Circle2d_Parse2()\n        {\n            var a = new Circle2d(new V2d(1.2, 3.4), double.NaN);\n            Assert.IsTrue(Circle2d.Parse(a.ToString()).IsInvalid);\n        }\n\n        [Test]\n        public void Circle2d_Parse3()\n        {\n            var a = new Circle2d(new V2d(double.NaN, 3.4), 5.6);\n            Assert.IsTrue(Circle2d.Parse(a.ToString()).IsInvalid);\n        }\n\n        [Test]\n        public void Circle2d_Parse4()\n        {\n            var a = new Circle2d(new V2d(1.2, double.NaN), 5.6);\n            Assert.IsTrue(Circle2d.Parse(a.ToString()).IsInvalid);\n        }\n\n        [Test]\n        public void Circle2d_Parse5()\n        {\n            var a = new Circle2d(V2d.NaN, 5.6);\n            Assert.IsTrue(Circle2d.Parse(a.ToString()).IsInvalid);\n        }\n\n        [Test]\n        public void Circle2d_Parse6()\n        {\n            var a = new Circle2d(V2d.NaN, double.NaN);\n            Assert.IsTrue(Circle2d.Parse(a.ToString()).IsInvalid);\n        }\n\n        [Test]\n        public void Circle2d_BoundingBox1()\n        {\n            var a = Circle2d.Unit;\n            Assert.IsTrue(a.BoundingBox2d == new Box2d(new V2d(-1, -1), new V2d(+1, +1)));\n        }\n        \n        [Test]\n        public void Circle2d_BoundingBox2()\n        {\n            var a = Circle2d.Invalid;\n            var bb = a.BoundingBox2d;\n            Assert.IsTrue(bb.IsInvalid);\n        }\n\n        [Test]\n        public void Circle2d_BoundingCircle2d()\n        {\n            var a = Box2d.Unit;\n            var b = a.BoundingCircle2d;\n            var c = new Circle2d(new V2d(0.5, 0.5), Constant.Sqrt2Half);\n            Assert.IsTrue(b.Equals(c));\n        }\n\n        [Test]\n        public void Circle2d_BoundingCircle2d_Invalid()\n        {\n            var a = Box2d.Invalid;\n            var b = a.BoundingCircle2d;\n            Assert.IsTrue(b.IsInvalid);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Geometry/Hull2dTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests.Geometry\n{\n    [TestFixture]\n    public class Hull2dTests\n    {\n        [Test]\n        public void ComputeCorners_Square()\n        {\n            var hull = new Hull2d(new[]\n            {\n                new Plane2d(-V2d.IO, V2d.Zero),\n                new Plane2d(-V2d.OI, V2d.Zero),\n                new Plane2d(V2d.IO, V2d.One),\n                new Plane2d(V2d.OI, V2d.One),\n            });\n\n            var corners = hull.ComputeCorners();\n\n            var expectedCorners = new [] { V2d.OO, V2d.OI, V2d.IO, V2d.II };\n\n            Assert.IsTrue(corners.SetEquals(expectedCorners));\n        }\n\n        [Test]\n        public void ComputeCorners_Frustum()\n        {\n            var hull = new Hull2d(new[]\n            {\n                new Plane2d(new V2d(0, -1), V2d.OO),\n                new Plane2d(new V2d(0, +1), new V2d(0, 0.25)),\n                new Plane2d(new V2d(-1, +1).Normalized, V2d.OO),\n                new Plane2d(new V2d(+1, +1).Normalized, V2d.IO),\n            });\n\n            var expectedCorners = new []\n            {\n                V2d.OO, V2d.IO,\n                new V2d(0.25, 0.25),\n                new V2d(0.75, 0.25),\n            };\n\n            var corners = hull.ComputeCorners();\n\n            Assert.IsTrue(corners.SetEquals(expectedCorners));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Geometry/Hull3dTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests.Geometry\n{\n    [TestFixture]\n    public class Hull3dTests\n    {\n        [Test]\n        public void ComputeCorners_Cube()\n        {\n            var hull = new Hull3d(new[]\n            {\n                new Plane3d(-V3d.XAxis, V3d.Zero),\n                new Plane3d(-V3d.YAxis, V3d.Zero),\n                new Plane3d(-V3d.ZAxis, V3d.Zero),\n                new Plane3d(V3d.XAxis, V3d.One),\n                new Plane3d(V3d.YAxis, V3d.One),\n                new Plane3d(V3d.ZAxis, V3d.One)\n            });\n\n            var corners = hull.ComputeCorners();\n\n            var expectedCorners = new [] { V3d.OOO, V3d.OOI, V3d.OIO, V3d.OII, V3d.IOO, V3d.IOI, V3d.IIO, V3d.III };\n\n            Assert.IsTrue(corners.SetEquals(expectedCorners));\n        }\n\n        [Test]\n        public void ComputeCorners_Frustum()\n        {\n            var hull = new Hull3d(new[]\n            {\n                new Plane3d(new V3d(0, 0, -1), V3d.OOO),\n                new Plane3d(new V3d(0, 0, +1), new V3d(0, 0, 0.25)),\n                new Plane3d(new V3d(-1, 0, +1).Normalized, V3d.OOO),\n                new Plane3d(new V3d(+1, 0, +1).Normalized, V3d.IOO),\n                new Plane3d(new V3d(0, -1, +1).Normalized, V3d.OOO),\n                new Plane3d(new V3d(0, +1, +1).Normalized, V3d.OIO),\n            });\n\n            var expectedCorners = new []\n            {\n                V3d.OOO, V3d.IOO, V3d.IIO, V3d.OIO,\n                new V3d(0.25, 0.25, 0.25),\n                new V3d(0.75, 0.25, 0.25),\n                new V3d(0.75, 0.75, 0.25),\n                new V3d(0.25, 0.75, 0.25),\n            };\n\n            var corners = hull.ComputeCorners();\n\n            Assert.IsTrue(corners.SetEquals(expectedCorners));\n        }\n\n        [Test]\n        public void VisualHullTest()\n        {\n            var view = Trafo3d.ViewTrafoRH(V3d.III, V3d.OOI, V3d.IOO);\n            var proj = Trafo3d.PerspectiveProjectionGL(-1, 1, -1, 1, 1, 100);\n            var vpTrafo = view * proj;\n            var frustumCorners = new Box3d(-V3d.III, V3d.III).ComputeCorners();\n\n            //Min,                             0 near left bottom\n            //new V3d(Max.X, Min.Y, Min.Z),    1 near right bottom\n            //new V3d(Min.X, Max.Y, Min.Z),    2 near left top\n            //new V3d(Max.X, Max.Y, Min.Z),    3 near right top\n            //new V3d(Min.X, Min.Y, Max.Z),    4 far left bottom\n            //new V3d(Max.X, Min.Y, Max.Z),    5 far right bottom\n            //new V3d(Min.X, Max.Y, Max.Z),    6 far left top\n            //Max                              7 far right top\n\n            // use inverse view-projection to get vertices in world space\n            frustumCorners.Apply(c => vpTrafo.Backward.TransformPosProj(c));\n\n            // hull planes should point outside, assume right-handed transformation to build planes\n            var refHull = new Hull3d(new[]\n            {\n                new Plane3d(frustumCorners[0], frustumCorners[2], frustumCorners[4]), // left\n                new Plane3d(frustumCorners[1], frustumCorners[5], frustumCorners[3]), // right\n                new Plane3d(frustumCorners[0], frustumCorners[4], frustumCorners[1]), // bottom\n                new Plane3d(frustumCorners[2], frustumCorners[3], frustumCorners[6]), // top\n                new Plane3d(frustumCorners[0], frustumCorners[1], frustumCorners[2]), // near\n                new Plane3d(frustumCorners[4], frustumCorners[6], frustumCorners[5]), // far\n            });\n\n            var newHull = vpTrafo.GetVisualHull();\n\n            // camera position should have height 1.0 from near-plane\n            var hRef = refHull.PlaneArray[4].Height(view.GetViewPosition());\n            var hNew = newHull.PlaneArray[4].Height(view.GetViewPosition());\n            Assert.True(hRef.ApproximateEquals(1.0, 1e-7) && hRef.ApproximateEquals(hNew, 1e-7));\n            \n            for (int i = 0; i < 6; i++)\n            {\n                var oldPlane = newHull.PlaneArray[i];\n                var newPlane = refHull.PlaneArray[i];\n                Assert.True(\n                    oldPlane.Coefficients.ApproximateEquals(newPlane.Coefficients, 1e-7),\n                    $\"Plane {i} mismatch. computed={oldPlane} expected={newPlane}\"\n                );\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Geometry/IntersectionTestsTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing static System.Math;\n\nnamespace Aardvark.Tests.Geometry\n{\n    [TestFixture]\n    public class IntersectionTestsTests\n    {\n        #region Contains\n\n        #region Triangle2d contains *\n\n        [Test]\n        public void Contains_Triangle2d_V2d()\n        {\n            var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2));\n            Assert.IsTrue(t.Contains(new V2d(1, 1)));\n            Assert.IsTrue(t.Contains(new V2d(2, 0)));\n            Assert.IsTrue(!t.Contains(new V2d(0, 0.000001)));\n        }\n\n        [Test]\n        public void Contains_Triangle2d_Line2d()\n        {\n            var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2));\n            Assert.IsTrue(t.Contains(new Line2d(new V2d(0, 0), new V2d(2, 0))));\n            Assert.IsTrue(t.Contains(new Line2d(new V2d(2, 0), new V2d(1, 2))));\n            Assert.IsTrue(t.Contains(new Line2d(new V2d(1, 2), new V2d(0, 0))));\n            Assert.IsTrue(t.Contains(new Line2d(new V2d(0.5, 0.1), new V2d(1.5, 0.2))));\n            Assert.IsTrue(!t.Contains(new Line2d(new V2d(0.5, 0.1), new V2d(2, 2))));\n            Assert.IsTrue(!t.Contains(new Line2d(new V2d(0.1, 0.2), new V2d(1.1, 10))));\n        }\n\n        [Test]\n        public void Contains_Triangle2d_Triangle2d()\n        {\n            var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2));\n            Assert.IsTrue(t.Contains(new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2))));\n            Assert.IsTrue(t.Contains(new Triangle2d(new V2d(0.2, 0.1), new V2d(1.5, 0.5), new V2d(1, 1.5))));\n            Assert.IsTrue(!t.Contains(new Triangle2d(new V2d(0.2, 0.1), new V2d(1.5, 0.5), new V2d(1, 2.000001))));\n            Assert.IsTrue(!t.Contains(new Triangle2d(new V2d(-1, -1), new V2d(3, -1), new V2d(1, 5))));\n        }\n\n        [Test]\n        public void Contains_Triangle2d_Quad2d()\n        {\n            var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2));\n            Assert.IsTrue(t.Contains(new Quad2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2), new V2d(1, 2))));\n            Assert.IsTrue(t.Contains(new Quad2d(new V2d(0, 0), new V2d(2, 0), new V2d(1.5, 0.2), new V2d(0.5, 0.2))));\n            Assert.IsTrue(!t.Contains(new Quad2d(new V2d(0, 0), new V2d(2, 0), new V2d(1.5, 0.2), new V2d(0.5, 1.1))));\n            Assert.IsTrue(!t.Contains(new Quad2d(new V2d(-1, -1), new V2d(5, -1), new V2d(5, 5), new V2d(0, 5))));\n        }\n\n        [Test]\n        public void Contains_Triangle2d_Circle2d()\n        {\n            var t = new Triangle2d(new V2d(0, 0), new V2d(2, 0), new V2d(1, 2));\n            Assert.IsTrue(t.Contains(new Circle2d(new V2d(1, 1), 0.4)));\n            Assert.IsTrue(t.Contains(new Circle2d(new V2d(1, 1), 1.0 / Sqrt(5.0))));\n            Assert.IsTrue(t.Contains(new Circle2d(new V2d(1, 2), 0.0)));\n            Assert.IsTrue(!t.Contains(new Circle2d(new V2d(1, 0.1), 0.100001)));\n            Assert.IsTrue(!t.Contains(new Circle2d(new V2d(1, 2), 10)));\n        }\n\n        [Test]\n        public void Contains_Triangle2f_Circle2f()\n        {\n            var t = new Triangle2f(new V2f(0, 0), new V2f(4, 0), new V2f(0, 3));\n            Assert.IsTrue(t.Contains(new Circle2f(new V2f(1, 1), 0.5f)));\n            Assert.IsTrue(t.Contains(new Circle2f(new V2f(1, 1), 1.0f)));\n            Assert.IsTrue(!t.Contains(new Circle2f(new V2f(1, 1), 1.000001f)));\n            Assert.IsTrue(!t.Contains(new Circle2f(new V2f(3, 2), 0.0f)));\n        }\n\n        #endregion\n\n        #region Quad2d contains *\n\n        [Test]\n        public void Contains_Quad2d_Line2d()\n        {\n            var q = new Quad2d(new V2d(0, 0), new V2d(4, 0), new V2d(4, 3), new V2d(0, 3));\n            Assert.IsTrue(q.Contains(new Line2d(new V2d(1, 1), new V2d(3, 2))));\n            Assert.IsTrue(q.Contains(new Line2d(new V2d(0, 0), new V2d(4, 0))));\n            Assert.IsTrue(!q.Contains(new Line2d(new V2d(1, 1), new V2d(5, 1))));\n        }\n\n        [Test]\n        public void Contains_Quad2d_Triangle2d()\n        {\n            var q = new Quad2d(new V2d(0, 0), new V2d(4, 0), new V2d(4, 3), new V2d(0, 3));\n            Assert.IsTrue(q.Contains(new Triangle2d(new V2d(1, 1), new V2d(3, 1), new V2d(2, 2))));\n            Assert.IsTrue(q.Contains(new Triangle2d(new V2d(0, 0), new V2d(4, 0), new V2d(0, 3))));\n            Assert.IsTrue(!q.Contains(new Triangle2d(new V2d(1, 1), new V2d(3, 1), new V2d(2, 4))));\n        }\n\n        [Test]\n        public void Contains_Quad2d_Quad2d()\n        {\n            var q = new Quad2d(new V2d(0, 0), new V2d(4, 0), new V2d(4, 3), new V2d(0, 3));\n            Assert.IsTrue(q.Contains(new Quad2d(new V2d(1, 1), new V2d(3, 1), new V2d(3, 2), new V2d(1, 2))));\n            Assert.IsTrue(q.Contains(new Quad2d(new V2d(0, 0), new V2d(4, 0), new V2d(4, 3), new V2d(0, 3))));\n            Assert.IsTrue(!q.Contains(new Quad2d(new V2d(1, 1), new V2d(5, 1), new V2d(5, 2), new V2d(1, 2))));\n        }\n\n        [Test]\n        public void Contains_Quad2d_Circle2d()\n        {\n            var q = new Quad2d(new V2d(0, 0), new V2d(4, 0), new V2d(4, 3), new V2d(0, 3));\n            Assert.IsTrue(q.Contains(new Circle2d(new V2d(2, 1.5), 1.0)));\n            Assert.IsTrue(q.Contains(new Circle2d(new V2d(2, 1.5), 1.5)));\n            Assert.IsTrue(q.Contains(new Circle2d(new V2d(0, 0), 0.0)));\n            Assert.IsTrue(!q.Contains(new Circle2d(new V2d(2, 1.5), 1.500001)));\n            Assert.IsTrue(!q.Contains(new Circle2d(new V2d(5, 1.5), 0.0)));\n        }\n\n        [Test]\n        public void Contains_Quad2f_Circle2f()\n        {\n            var q = new Quad2f(new V2f(0, 0), new V2f(4, 0), new V2f(4, 3), new V2f(0, 3));\n            Assert.IsTrue(q.Contains(new Circle2f(new V2f(2, 1.5f), 1.5f)));\n            Assert.IsTrue(!q.Contains(new Circle2f(new V2f(2, 1.5f), 1.500001f)));\n        }\n\n        #endregion\n\n        #region Circle2d contains *\n\n        [Test]\n        public void Contains_Circle2d_Circle2d()\n        {\n            Assert.IsTrue(!new Circle2d(new V2d(0, 0), 0.5).Contains(new Circle2d(new V2d(0, 0), 1)));\n            Assert.IsTrue(new Circle2d(new V2d(0, 0), 1).Contains(new Circle2d(new V2d(0, 0), 1)));\n            Assert.IsTrue(new Circle2d(new V2d(0, 0), 1).Contains(new Circle2d(new V2d(0, 0), 0.5)));\n            Assert.IsTrue(!new Circle2d(new V2d(0, 0), 1).Contains(new Circle2d(new V2d(1, 0), 1)));\n            Assert.IsTrue(!new Circle2d(new V2d(0, 0), 1).Contains(new Circle2d(new V2d(2, 0), 1)));\n\n            Assert.IsTrue(!new Circle2d(new V2d(0, 0), 1).Contains(new Circle2d(new V2d(2.000001, 0), 1)));\n        }\n\n        #endregion\n\n        #endregion\n\n        #region Intersects\n\n        [Test]\n        public void Intersects_Circle2d_Circle2d()\n        {\n            Assert.IsTrue(new Circle2d(new V2d(0, 0), 1).Intersects(new Circle2d(new V2d(0, 0), 1)));\n            Assert.IsTrue(new Circle2d(new V2d(0, 0), 1).Intersects(new Circle2d(new V2d(0, 0), 0.5)));\n            Assert.IsTrue(new Circle2d(new V2d(0, 0), 0.5).Intersects(new Circle2d(new V2d(0, 0), 1)));\n            Assert.IsTrue(new Circle2d(new V2d(0, 0), 1).Intersects(new Circle2d(new V2d(1, 0), 1)));\n            Assert.IsTrue(new Circle2d(new V2d(0, 0), 1).Intersects(new Circle2d(new V2d(2, 0), 1)));\n            \n            Assert.IsTrue(!new Circle2d(new V2d(0, 0), 1).Intersects(new Circle2d(new V2d(2.000001, 0), 1)));\n        }\n\n        [Test]\n        public void Intersects_Line2d_Line2d()\n        {\n            // non-parallel, crossing\n            Assert.IsTrue(\n                new Line2d(new V2d(0,  0), new V2d(2, 0)).Intersects(\n                new Line2d(new V2d(1, -1), new V2d(1, 1))\n                ));\n\n            // non-parallel, touching\n            Assert.IsTrue(\n                new Line2d(new V2d(0, 0), new V2d(2, 0)).Intersects(\n                new Line2d(new V2d(1, 0), new V2d(1, 1))\n                ));\n\n            // non-parallel, almost touching\n            Assert.IsTrue(!\n                new Line2d(new V2d(0, 0), new V2d(2, 0)).Intersects(\n                new Line2d(new V2d(1, 0.000001), new V2d(1, 1))\n                ));\n\n            // identical\n            Assert.IsTrue(\n                new Line2d(new V2d(0, 0), new V2d(2, 0)).Intersects(\n                new Line2d(new V2d(0, 0), new V2d(2, 0))\n                ));\n            \n            // on same line, almost touching\n            Assert.IsTrue(!\n                new Line2d(new V2d(0, 0), new V2d(2, 0)).Intersects(\n                new Line2d(new V2d(2.000001, 0), new V2d(4, 0))\n                ));\n\n            // on same line, not touching\n            Assert.IsTrue(!\n                new Line2d(new V2d(0, 0), new V2d(2, 0)).Intersects(\n                new Line2d(new V2d(3, 0), new V2d(5, 0))\n                ));\n        }\n\n        [Test]\n        public void Intersects_Line2d_Line2d_ParallelAndNotTouching()\n        {\n            // parallel, not touching\n            Assert.IsTrue(!\n                new Line2d(new V2d(1, 0), new V2d(3, 0)).Intersects(\n                new Line2d(new V2d(2, 5), new V2d(4, 5))\n                ));\n        }\n\n        [Test]\n        public void Intersects_Line2d_Line2d_Overlapping()\n        {\n\n            // on same line, overlapping\n            Assert.IsTrue(\n                new Line2d(new V2d(0, 0), new V2d(2, 0)).IntersectsLine(\n                new V2d(1, 0), new V2d(3, 0), true, out var foo1\n                ));\n\n            // on same line, touching\n            Assert.IsTrue(\n                new Line2d(new V2d(0, 0), new V2d(2, 0)).IntersectsLine(\n                new V2d(2, 0), new V2d(4, 0), true, out var foo2\n                ));\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Geometry/LineDistance.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests.Geometry\n{\n    [TestFixture]\n    public class LineDistance\n    {\n        const int Iter = 10000;\n        const int SubDiv = 100;\n\n        [Test]\n        public void DistanceToLineAndGetMinimalDistanceToConsistency()\n        {\n            var line = new Line3d(new V3d(1, 2, 3), new V3d(1, 2, 3));\n            var p = V3d.OOO;\n\n            var x = p.DistanceToLine(line.P0, line.P1);\n            var md = p.GetMinimalDistanceTo(line);\n\n            Assert.AreEqual(x, md);\n        }\n\n        [Test]\n        public void LineToPointDistance2d()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < Iter; i++)\n            {\n                var p00 = rnd.UniformV2d();\n                var line0 = new Line2d(p00, p00 + rnd.UniformV2d() * rnd.UniformDouble() * 0.2);\n\n                var p01 = rnd.UniformV2d();\n\n                var dist = p01.GetMinimalDistanceTo(line0);\n\n                var refDist = 5.0;\n                var r0 = line0.Ray2d;\n                for (int j = 0; j <= SubDiv; j++)\n                {\n                    var x0 = r0.GetPointOnRay(j / (double)SubDiv);\n                    refDist = Fun.Min(refDist, Vec.Distance(x0, p01));\n                }\n                var e = 0.2 / SubDiv;\n                Assert.IsTrue(refDist.ApproximateEquals(dist, e));\n            }\n        }\n\n        [Test]\n        public void LineToLineDistance2d()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < Iter; i++)\n            {\n                var p00 = rnd.UniformV2d();\n                var line0 = new Line2d(p00, p00 + rnd.UniformV2d() * rnd.UniformDouble() * 0.2);\n\n                var p01 = rnd.UniformV2d();\n                var line1 = new Line2d(p01, p01 + rnd.UniformV2d() * rnd.UniformDouble() * 0.2);\n\n                var dist = line0.GetMinimalDistanceTo(line1);\n\n                // Alternative: assuming Line3d distance is correct\n                //var refDist = new Line3d(line0.P0.XYO, line0.P1.XYO).GetMinimalDistanceTo(new Line3d(line1.P0.XYO, line1.P1.XYO)); \n\n                var refDist = 5.0;\n                var r0 = line0.Ray2d;\n                var r1 = line1.Ray2d;\n                for (int j = 0; j <= SubDiv; j++)\n                {\n                    var x0 = r0.GetPointOnRay(j / (double)SubDiv);\n                    for (int k = 0; k <= SubDiv; k++)\n                    {\n                        var x1 = r1.GetPointOnRay(k / (double)SubDiv);\n                        refDist = Fun.Min(refDist, Vec.Distance(x0, x1));\n                    }\n                }\n                var e = 0.2 / SubDiv;\n                Assert.IsTrue(refDist.ApproximateEquals(dist, e));\n            }\n        }\n\n        [Test]\n        public void LineToPointDistance3d()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < Iter; i++)\n            {\n                var p00 = rnd.UniformV3d();\n                var line0 = new Line3d(p00, p00 + rnd.UniformV3d() * rnd.UniformDouble() * 0.2);\n\n                var p01 = rnd.UniformV3d();\n\n                var dist = p01.GetMinimalDistanceTo(line0);\n\n                var refDist = 5.0;\n                var r0 = line0.Ray3d;\n                for (int j = 0; j <= SubDiv; j++)\n                {\n                    var x0 = r0.GetPointOnRay(j / (double)SubDiv);\n                    refDist = Fun.Min(refDist, Vec.Distance(x0, p01));\n                }\n                var e = 0.2 / SubDiv;\n                Assert.IsTrue(refDist.ApproximateEquals(dist, e));\n            }\n        }\n\n        [Test]\n        public void LineToLineDistance3d()\n        {\n            var rnd = new RandomSystem(2);\n\n            for (int i = 0; i < Iter; i++)\n            {\n                var p00 = rnd.UniformV3d();\n                var line0 = new Line3d(p00, p00 + rnd.UniformV3d() * rnd.UniformDouble() * 0.2);\n\n                var p01 = rnd.UniformV3d();\n                var line1 = new Line3d(p01, p01 + rnd.UniformV3d() * rnd.UniformDouble() * 0.2);\n\n                var dist = line0.GetMinimalDistanceTo(line1);\n                var refDist = 5.0;\n                var r0 = line0.Ray3d;\n                var r1 = line1.Ray3d;\n                for (int j = 0; j <= SubDiv; j++)\n                {\n                    var x0 = r0.GetPointOnRay(j / (double)SubDiv);\n                    for (int k = 0; k <= SubDiv; k++)\n                    {\n                        var x1 = r1.GetPointOnRay(k / (double)SubDiv);\n                        refDist = Fun.Min(refDist, Vec.Distance(x0, x1));\n                    }\n                }\n                var e = 0.2 / SubDiv;\n                Assert.IsTrue(refDist.ApproximateEquals(dist, e));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Geometry/Plane3dTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing static System.Math;\n\nnamespace Aardvark.Tests.Geometry\n{\n    [TestFixture]\n    public class Plane3dTests\n    {\n        [Test]\n        public void Plane3d_Constructor1()\n        {\n            var a = new Plane3d();\n            Assert.IsTrue(!a.IsValid);\n            Assert.IsTrue(a.IsInvalid);\n        }\n\n        [Test]\n        public void Plane3d_Constructor2()\n        {\n            var a = new Plane3d(V3d.ZAxis, 1.5);\n            Assert.IsTrue(a.IsValid);\n            Assert.IsTrue(!a.IsInvalid);\n            Assert.IsTrue(a.Normal == V3d.ZAxis && a.Distance == 1.5);\n        }\n\n        [Test]\n        public void Plane3d_Constructor3()\n        {\n            var a = new Plane3d(V3d.ZAxis, new V3d(123.345, 4556.234, 1.5));\n            Assert.IsTrue(a.IsValid);\n            Assert.IsTrue(!a.IsInvalid);\n            Assert.IsTrue(a.Normal == V3d.ZAxis && a.Distance == 1.5);\n        }\n\n        [Test]\n        public void Plane3d_Constructor4()\n        {\n            var a = new Plane3d(new V3d(12, 46, 1.5), new V3d(-2, 412, 1.5), new V3d(876, -23, 1.5));\n            Assert.IsTrue(a.IsValid);\n            Assert.IsTrue(!a.IsInvalid);\n            Assert.IsTrue((a.Normal == V3d.ZAxis && a.Distance == 1.5) ||\n                          (a.Normal == -V3d.ZAxis && a.Distance == -1.5));\n        }\n\n        [Test]\n        public void ProjectPointArrayAllowsFullArrayRange()\n        {\n            var plane = new Plane3d(V3d.ZAxis, 1.5);\n            var points = new[]\n            {\n                new V3d(1, 2, 5),\n                new V3d(-3, 4, -1),\n                new V3d(0.25, -0.5, 1.5),\n            };\n\n            var result = plane.Project(points, 0, points.Length);\n\n            Assert.AreEqual(points.Length, result.Length);\n            for (var i = 0; i < points.Length; i++)\n                Assert.AreEqual(new V3d(points[i].X, points[i].Y, 1.5), result[i]);\n        }\n\n        [Test]\n        public void ProjectPointArrayAlongDirectionAllowsFullArrayRange()\n        {\n            var plane = new Plane3d(V3d.ZAxis, 1.5);\n            var direction = -V3d.ZAxis;\n            var points = new[]\n            {\n                new V3d(1, 2, 2),\n                new V3d(-3, 4, 8),\n                new V3d(0.25, -0.5, 3),\n            };\n\n            var result = plane.Project(points, direction, 0, points.Length);\n\n            Assert.AreEqual(points.Length, result.Length);\n            for (var i = 0; i < points.Length; i++)\n                Assert.AreEqual(new V3d(points[i].X, points[i].Y, 1.5), result[i]);\n        }\n\n        [Test]\n        public void ProjectPointArrayAllowsSliceEndingAtArrayLength()\n        {\n            var plane = new Plane3d(V3d.ZAxis, 1.5);\n            var points = new[]\n            {\n                new V3d(100, 200, 300),\n                new V3d(1, 2, 5),\n                new V3d(-3, 4, -1),\n            };\n\n            var result = plane.Project(points, 1, points.Length - 1);\n\n            Assert.AreEqual(2, result.Length);\n            Assert.AreEqual(new V3d(1, 2, 1.5), result[0]);\n            Assert.AreEqual(new V3d(-3, 4, 1.5), result[1]);\n        }\n\n        [Test]\n        public void ToStringAndParse()\n        {\n            var a = new Plane3d(new V3d(12, 46, 1.5), new V3d(-2, 412, 1.5), new V3d(876, -23, 1.5));\n            var b = Plane3d.Parse(a.ToString());\n            Assert.AreEqual(a, b);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Geometry/PolygonClipping.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Tests.Geometry\n{\n\n    [TestFixture]\n    public class PolygonClipping : TestSuite\n    {\n        public PolygonClipping() : base() { }\n        public PolygonClipping(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public void TestConvexClipped()\n        {\n            var points = new[] { V3d.OOO, V3d.IOO, V3d.OIO };\n            var poly = new Polygon3d(points);\n            var box = Box3d.FromMinAndSize(-V3d.OOI, new V3d(1, 0.5, 2));\n            var newHull = new Hull3d(box).Reversed(); // requires non-intuitive reversed\n            var polyClipped = poly.ConvexClipped(newHull); // will return positive part of planes (outside of Hull3d)\n            var clippedBox = polyClipped.BoundingBox3d;\n            var test = new Box3d(0, 0, 0, 1, 0.5, 0);\n            Test.IsTrue(clippedBox == test);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/IO/UberStreamTests.cs",
    "content": "using Aardvark.Base.Coder;\nusing NUnit.Framework;\nusing System;\nusing System.IO;\n\nnamespace Aardvark.Tests.IO\n{\n    static class UberStreamTests\n    {\n        [Test]\n        public static void SingleStreamReadAndWriteRespectSlice()\n        {\n            using (var stream = new UberStream(new MemoryStream(new byte[] { 0, 1, 2, 3, 4 }), 2, 2))\n            {\n                var buffer = new byte[2];\n\n                Assert.AreEqual(2, stream.Read(buffer, 0, buffer.Length));\n                CollectionAssert.AreEqual(new byte[] { 2, 3 }, buffer);\n            }\n\n            var bytes = new byte[] { 0, 1, 2, 3, 4 };\n            using (var stream = new UberStream(new MemoryStream(bytes, true), 1, 3))\n            {\n                stream.Write(new byte[] { 9, 8, 7 }, 0, 3);\n            }\n\n            CollectionAssert.AreEqual(new byte[] { 0, 9, 8, 7, 4 }, bytes);\n        }\n\n        [Test]\n        public static void MultipleStreamReadAndWriteCrossBoundaries()\n        {\n            using (var stream = new UberStream(\n                new Stream[]\n                {\n                    new MemoryStream(new byte[] { 1, 2 }),\n                    new MemoryStream(new byte[] { 3, 4, 5 })\n                },\n                1,\n                3))\n            {\n                var buffer = new byte[3];\n\n                Assert.AreEqual(3, stream.Read(buffer, 0, buffer.Length));\n                CollectionAssert.AreEqual(new byte[] { 2, 3, 4 }, buffer);\n            }\n\n            var first = new byte[2];\n            var second = new byte[3];\n            using (var stream = new UberStream(\n                new Stream[]\n                {\n                    new MemoryStream(first, true),\n                    new MemoryStream(second, true)\n                },\n                1,\n                3))\n            {\n                stream.Write(new byte[] { 9, 8, 7 }, 0, 3);\n            }\n\n            CollectionAssert.AreEqual(new byte[] { 0, 9 }, first);\n            CollectionAssert.AreEqual(new byte[] { 8, 7, 0 }, second);\n        }\n\n        [Test]\n        public static void ConstructorsRejectInvalidArguments()\n        {\n            var singleNull = Assert.Throws<ArgumentNullException>(() => new UberStream((Stream)null, 0, 1));\n            Assert.AreEqual(\"stream\", singleNull.ParamName);\n\n            using (var source = new MemoryStream(new byte[1]))\n            {\n                var start = Assert.Throws<ArgumentOutOfRangeException>(() => new UberStream(source, -1, 1));\n                Assert.AreEqual(\"startPos\", start.ParamName);\n            }\n\n            using (var source = new MemoryStream(new byte[1]))\n            {\n                var length = Assert.Throws<ArgumentOutOfRangeException>(() => new UberStream(source, 0, -1));\n                Assert.AreEqual(\"numOfBytes\", length.ParamName);\n            }\n\n            var arrayNull = Assert.Throws<ArgumentNullException>(() => new UberStream((Stream[])null, 0, 1));\n            Assert.AreEqual(\"streams\", arrayNull.ParamName);\n\n            var emptyArray = Assert.Throws<ArgumentException>(() => new UberStream(Array.Empty<Stream>(), 0, 0));\n            Assert.AreEqual(\"streams\", emptyArray.ParamName);\n\n            var arrayStart = Assert.Throws<ArgumentOutOfRangeException>(() => new UberStream(new Stream[] { new MemoryStream(new byte[1]) }, -1, 1));\n            Assert.AreEqual(\"startPos\", arrayStart.ParamName);\n\n            var arrayLength = Assert.Throws<ArgumentOutOfRangeException>(() => new UberStream(new Stream[] { new MemoryStream(new byte[1]) }, 0, -1));\n            Assert.AreEqual(\"numOfBytes\", arrayLength.ParamName);\n\n            var arrayElementNull = Assert.Throws<ArgumentNullException>(() => new UberStream(new Stream[] { new MemoryStream(), null }, 0, 0));\n            Assert.AreEqual(\"streams\", arrayElementNull.ParamName);\n        }\n\n        [Test]\n        public static void ReadRejectsInvalidArgumentsBeforeReading()\n        {\n            using (var stream = new UberStream(new MemoryStream(new byte[4]), 0, 4))\n            {\n                var nullBuffer = Assert.Throws<ArgumentNullException>(() => stream.Read(null, 0, 1));\n                Assert.AreEqual(\"buffer\", nullBuffer.ParamName);\n\n                var negativeOffset = Assert.Throws<ArgumentOutOfRangeException>(() => stream.Read(new byte[2], -1, 1));\n                Assert.AreEqual(\"offset\", negativeOffset.ParamName);\n\n                var negativeCount = Assert.Throws<ArgumentOutOfRangeException>(() => stream.Read(new byte[2], 0, -1));\n                Assert.AreEqual(\"count\", negativeCount.ParamName);\n\n                var invalidRange = Assert.Throws<ArgumentException>(() => stream.Read(new byte[2], 1, 2));\n                Assert.AreEqual(\"count\", invalidRange.ParamName);\n            }\n        }\n\n        [Test]\n        public static void WriteRejectsInvalidArgumentsBeforeWriting()\n        {\n            using (var stream = new UberStream(new MemoryStream(new byte[4], true), 0, 4))\n            {\n                var nullBuffer = Assert.Throws<ArgumentNullException>(() => stream.Write(null, 0, 1));\n                Assert.AreEqual(\"buffer\", nullBuffer.ParamName);\n\n                var negativeOffset = Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(new byte[2], -1, 1));\n                Assert.AreEqual(\"offset\", negativeOffset.ParamName);\n\n                var negativeCount = Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(new byte[2], 0, -1));\n                Assert.AreEqual(\"count\", negativeCount.ParamName);\n\n                var invalidRange = Assert.Throws<ArgumentException>(() => stream.Write(new byte[2], 1, 2));\n                Assert.AreEqual(\"count\", invalidRange.ParamName);\n            }\n        }\n\n        [Test]\n        public static void WriteRejectsReadOnlyStreams()\n        {\n            using (var stream = new UberStream(new MemoryStream(new byte[1], false), 0, 1))\n            {\n                Assert.Throws<NotSupportedException>(() => stream.Write(new byte[] { 1 }, 0, 1));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Images/PixImageTests.cs",
    "content": "﻿using NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing Aardvark.Base;\nusing float16 = Aardvark.Base.Half;\n\nnamespace Aardvark.Tests.Images\n{\n    [TestFixture]\n    class PixImageTests\n    {\n        static readonly RandomSystem rnd = new(0);\n\n        #region Mipmap\n\n        [Test]\n        public void MipMapCreate1x1()\n        {\n            var pix = new PixImage<byte>(1, 1, 4);\n            var mip = PixImageMipMap.Create(pix);\n            Assert.IsTrue(mip.LevelCount == 1);\n        }\n\n        [Test]\n        public void MipMapCreate2x2()\n        {\n            var pix = new PixImage<byte>(2, 2, 4);\n            var mip = PixImageMipMap.Create(pix);\n            Assert.IsTrue(mip.LevelCount == 2);\n        }\n\n        [Test]\n        public void MipMapCreate3x3()\n        {\n            var pix = new PixImage<byte>(3, 3, 4);\n            var mip = PixImageMipMap.Create(pix);\n            Assert.IsTrue(mip.LevelCount == 2);\n        }\n\n        [Test]\n        public void MipMapCreate256()\n        {\n            var pix = new PixImage<byte>(256, 256, 4);\n            var mip = PixImageMipMap.Create(pix);\n            Assert.IsTrue(mip.LevelCount == 9);\n        }\n\n        [Test]\n        public void MipMapCreate255()\n        {\n            var pix = new PixImage<byte>(255, 255, 4);\n            var mip = PixImageMipMap.Create(pix);\n            Assert.IsTrue(mip.LevelCount == 8);\n        }\n\n        [Test]\n        public void MipMapCreate257()\n        {\n            var pix = new PixImage<byte>(257, 257, 4);\n            var mip = PixImageMipMap.Create(pix);\n            Assert.IsTrue(mip.LevelCount == 9);\n        }\n\n        [Test]\n        public void MipMapCreate57x43()\n        {\n            var pix = new PixImage<byte>(57, 43, 4);\n            var mip = PixImageMipMap.Create(pix);\n            Assert.IsTrue(mip.LevelCount == 6);\n            //level 0: 57x43\n            //level 1: 28x21\n            //level 2: 14x10\n            //level 3: 7x5\n            //level 4: 3x2\n            //level 5: 1x1\n        }\n\n        [Test]\n        public void MipMapCreate57x11()\n        {\n            var pix = new PixImage<byte>(57, 11, 4);\n            var mip = PixImageMipMap.Create(pix);\n            Assert.IsTrue(mip.LevelCount == 6);\n            //level 0: 57x11\n            //level 1: 28x5\n            //level 2: 14x2\n            //level 3: 7x1\n            //level 4: 3x1\n            //level 5: 1x1\n        }\n\n        #endregion\n\n        #region Format Conversions\n\n        internal static readonly Dictionary<Type, Func<RandomSystem, object>> s_randomValues = new ()\n        {\n            { typeof(byte), rnd => (byte)rnd.UniformInt(256) },\n            { typeof(ushort), rnd => (ushort)rnd.UniformInt(Col.Info<ushort>.MaxValue + 1) },\n            { typeof(uint), rnd => rnd.UniformUInt() },\n            { typeof(float16), rnd => (float16)rnd.UniformFloat() },\n            { typeof(float), rnd => rnd.UniformFloat() },\n            { typeof(double), rnd => rnd.UniformDouble() },\n        };\n\n        private static T[] GetArray<T>(PixImage<T> pi, V2l coord)\n        {\n            var arr = new T[pi.ChannelCount];\n            arr.SetByIndex(i => pi.Volume[new V3l(coord, i)]);\n            return arr;\n        }\n\n        private static Tc GetColor<T, Tc>(PixImage<T> pi, V2l coord)\n            => pi.GetMatrix<Tc>()[coord];\n\n        private static void FormatConversion<T1, T2, Tc1, Tc2>(Col.Format sourceFormat, Col.Format targetFormat,\n                                                               Func<PixImage<T1>, V2l, Tc1> getInput,\n                                                               Func<PixImage<T2>, V2l, Tc2> getActual,\n                                                               Func<Tc1, Tc2> expectedConversion,\n                                                               bool subImageWindow)\n        {\n\n            var getRandom = s_randomValues[typeof(T1)];\n            var src = new PixImage<T1>(sourceFormat, 43, 81);\n            src.Volume.Data.SetByIndex((_) => (T1)getRandom(rnd));\n\n            if (subImageWindow)\n                src = new PixImage<T1>(sourceFormat, src.Volume.SubImageWindow(2, 3, 33, 67));\n\n            var dst = new PixImage<T2>(targetFormat, src);\n\n            src.GetChannel(0L).ForeachCoord((coord) =>\n            {\n                var expected = expectedConversion(getInput(src, coord));\n                var actual = getActual(dst, coord);\n                Assert.AreEqual(expected, actual);\n            });\n        }\n\n        private static void FormatConversionArrays<T1, T2>(Col.Format sourceFormat, Col.Format targetFormat, Func<T1[], T2[]> expectedConversion, bool subImageWindow = false)\n            => FormatConversion<T1, T2, T1[], T2[]>(sourceFormat, targetFormat, GetArray, GetArray, expectedConversion, subImageWindow);\n\n        private static void FormatConversionFromArray<T1, T2, Tc2>(Col.Format sourceFormat, Col.Format targetFormat, Func<T1[], Tc2> expectedConversion, bool subImageWindow = false)\n            => FormatConversion<T1, T2, T1[], Tc2>(sourceFormat, targetFormat, GetArray, GetColor<T2, Tc2>, expectedConversion, subImageWindow);\n\n        private static void FormatConversionToArray<T1, T2, Tc1>(Col.Format sourceFormat, Col.Format targetFormat, Func<Tc1, T2[]> expectedConversion, bool subImageWindow = false)\n            => FormatConversion<T1, T2, Tc1, T2[]>(sourceFormat, targetFormat, GetColor<T1, Tc1>, GetArray, expectedConversion, subImageWindow);\n\n        private static void FormatConversion<T1, T2, Tc1, Tc2>(Col.Format sourceFormat, Col.Format targetFormat, Func<Tc1, Tc2> expectedConversion, bool subImageWindow = false)\n            => FormatConversion<T1, T2, Tc1, Tc2>(sourceFormat, targetFormat, GetColor<T1, Tc1>, GetColor<T2, Tc2>, expectedConversion, subImageWindow);\n\n        #region From Gray\n\n        [Test]\n        public void FormatConversionGrayToGrayAlpha()\n            => FormatConversionToArray<byte, byte, byte>(Col.Format.Gray, Col.Format.GrayAlpha, gray => new byte[] { gray, 255 });\n\n        [Test]\n        public void FormatConversionGrayToAlpha()\n            => FormatConversion<byte, byte, byte, byte>(Col.Format.Gray, Col.Format.Alpha, gray => 255);\n\n        [Test]\n        public void FormatConversionGrayToRGB()\n            => FormatConversion<byte, byte, byte, C3b>(Col.Format.Gray, Col.Format.RGB, gray => new C3b(gray));\n\n        [Test]\n        public void FormatConversionGrayToBGR()\n            => FormatConversion<byte, byte, byte, C3b>(Col.Format.Gray, Col.Format.BGR, gray => new C3b(gray));\n\n        [Test]\n        public void FormatConversionGrayToRGBA()\n            => FormatConversion<byte, byte, byte, C4b>(Col.Format.Gray, Col.Format.RGBA, gray => new C4b(gray));\n\n        [Test]\n        public void FormatConversionGrayToBGRA()\n            => FormatConversion<byte, byte, byte, C4b>(Col.Format.Gray, Col.Format.BGRA, gray => new C4b(gray));\n\n        [Test]\n        public void FormatConversionGrayToRG()\n            => FormatConversionToArray<byte, byte, byte>(Col.Format.Gray, Col.Format.RG, gray => new byte[] { gray, gray });\n\n        #endregion\n\n        #region From GrayAlpha\n\n        [Test]\n        public void FormatConversionGrayAlphaToGray()\n            => FormatConversionFromArray<byte, byte, byte>(Col.Format.GrayAlpha, Col.Format.Gray, gray => gray[0]);\n\n        [Test]\n        public void FormatConversionGrayAlphaToAlpha()\n            => FormatConversionFromArray<byte, byte, byte>(Col.Format.GrayAlpha, Col.Format.Alpha, gray => gray[1]);\n\n        [Test]\n        public void FormatConversionGrayAlphaToRGB()\n            => FormatConversionFromArray<byte, byte, C3b>(Col.Format.GrayAlpha, Col.Format.RGB, gray => new C3b(gray[0]));\n\n        [Test]\n        public void FormatConversionGrayAlphaToBGR()\n            => FormatConversionFromArray<byte, byte, C3b>(Col.Format.GrayAlpha, Col.Format.BGR, gray => new C3b(gray[0]));\n\n        [Test]\n        public void FormatConversionGrayAlphaToRGBA()\n            => FormatConversionFromArray<byte, byte, C4b>(Col.Format.GrayAlpha, Col.Format.RGBA, gray => new C4b(gray[0], gray[0], gray[0], gray[1]));\n\n        [Test]\n        public void FormatConversionGrayAlphaToBGRA()\n            => FormatConversionFromArray<byte, byte, C4b>(Col.Format.GrayAlpha, Col.Format.BGRA, gray => new C4b(gray[0], gray[0], gray[0], gray[1]));\n\n        [Test]\n        public void FormatConversionGrayAlphaToRG()\n            => FormatConversionArrays<byte, byte>(Col.Format.GrayAlpha, Col.Format.RG, gray => new byte[] { gray[0], gray[0] });\n\n        #endregion\n\n        #region From RGBA\n\n        [Test]\n        public void FormatConversionRGBAToRGBA()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.RGBA, Col.Format.RGBA, (c => c));\n\n        [Test]\n        public void FormatConversionRGBAToRGBAWindow()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.RGBA, Col.Format.RGBA, (c => c), true);\n\n        [Test]\n        public void FormatConversionRGBAToBGRA()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c);\n\n        [Test]\n        public void FormatConversionRGBAToBGRAWindow()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.RGBA, Col.Format.BGRA, (c => c), true);\n\n        [Test]\n        public void FormatConversionRGBAToRGB()\n            => FormatConversion<byte, byte, C4b, C3b>(Col.Format.RGBA, Col.Format.RGB, c => c.RGB);\n\n        [Test]\n        public void FormatConversionRGBAToBGR()\n            => FormatConversion<byte, byte, C4b, C3b>(Col.Format.RGBA, Col.Format.BGR, c => c.RGB);\n\n        [Test]\n        public void FormatConversionRGBAToGray()\n            => FormatConversion<byte, byte, C4b, byte>(Col.Format.RGBA, Col.Format.Gray, c => c.ToGrayByte());\n\n        [Test]\n        public void FormatConversionRGBAToGrayAlpha()\n            => FormatConversionToArray<byte, byte, C4b>(Col.Format.RGBA, Col.Format.GrayAlpha, c => new byte[] { c.ToGrayByte(), c.A });\n\n        [Test]\n        public void FormatConversionRGBAToRG()\n            => FormatConversionToArray<byte, byte, C4b>(Col.Format.RGBA, Col.Format.RG, c => new byte[] { c.R, c.G });\n\n        #region Byte to BGRA (other types)\n\n        [Test]\n        public void TypeConversionByteToUShort()\n            => FormatConversion<byte, ushort, C4b, C4us>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4us());\n\n        [Test]\n        public void TypeConversionByteToUInt()\n            => FormatConversion<byte, uint, C4b, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4ui());\n\n        [Test]\n        public void TypeConversionByteToHalf()\n            => FormatConversionToArray<byte, float16, C4b>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.ByteToHalf(), c.G.ByteToHalf(), c.R.ByteToHalf(), c.A.ByteToHalf() }\n            );\n\n        [Test]\n        public void TypeConversionByteToFloat()\n            => FormatConversion<byte, float, C4b, C4f>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4f());\n\n        [Test]\n        public void TypeConversionByteToDouble()\n            => FormatConversion<byte, double, C4b, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #region UShort to BGRA (other types)\n\n        [Test]\n        public void TypeConversionUShortToByte()\n            => FormatConversion<ushort, byte, C4us, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void TypeConversionUShortToUInt()\n            => FormatConversion<ushort, uint, C4us, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4ui());\n\n        [Test]\n        public void TypeConversionUShortToHalf()\n            => FormatConversionToArray<ushort, float16, C4us>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.UShortToHalf(), c.G.UShortToHalf(), c.R.UShortToHalf(), c.A.UShortToHalf() }\n            );\n\n        [Test]\n        public void TypeConversionUShortToFloat()\n            => FormatConversion<ushort, float, C4us, C4f>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4f());\n\n        [Test]\n        public void TypeConversionUShortToDouble()\n            => FormatConversion<ushort, double, C4us, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #region UInt to BGRA (other types)\n\n        [Test]\n        public void TypeConversionUIntToByte()\n            => FormatConversion<uint, byte, C4ui, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void TypeConversionUIntToUShort()\n            => FormatConversion<uint, ushort, C4ui, C4us>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4us());\n\n        [Test]\n        public void TypeConversionUIntToHalf()\n            => FormatConversionToArray<uint, float16, C4ui>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.UIntToHalf(), c.G.UIntToHalf(), c.R.UIntToHalf(), c.A.UIntToHalf() }\n            );\n\n        [Test]\n        public void TypeConversionUIntToFloat()\n            => FormatConversion<uint, float, C4ui, C4f>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4f());\n\n        [Test]\n        public void TypeConversionUIntToDouble()\n            => FormatConversion<uint, double, C4ui, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #region Half to BGRA (other types)\n\n        [Test]\n        public void TypeConversionHalfToByte()\n            => FormatConversionFromArray<float16, byte, C4b>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4b(c[0].HalfToByte(), c[1].HalfToByte(), c[2].HalfToByte(), c[3].HalfToByte())\n            );\n\n        [Test]\n        public void TypeConversionHalfToUShort()\n            => FormatConversionFromArray<float16, ushort, C4us>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4us(c[0].HalfToUShort(), c[1].HalfToUShort(), c[2].HalfToUShort(), c[3].HalfToUShort())\n            );\n\n        [Test]\n        public void TypeConversionHalfToUInt()\n            => FormatConversionFromArray<float16, uint, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4ui(c[0].HalfToUInt(), c[1].HalfToUInt(), c[2].HalfToUInt(), c[3].HalfToUInt())\n            );\n\n        [Test]\n        public void TypeConversionHalfToFloat()\n            => FormatConversionFromArray<float16, float, C4f>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4f(c[0], c[1], c[2], c[3])\n            );\n\n        [Test]\n        public void TypeConversionHalfToDouble()\n            => FormatConversionFromArray<float16, double, C4d>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4d(c[0], c[1], c[2], c[3])\n            );\n\n        #endregion\n\n        #region Float to BGRA (other types)\n\n        [Test]\n        public void TypeConversionFloatToByte()\n            => FormatConversion<float, byte, C4f, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void TypeConversionFloatToUShort()\n            => FormatConversion<float, ushort, C4f, C4us>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4us());\n\n        [Test]\n        public void TypeConversionFloatToUInt()\n            => FormatConversion<float, uint, C4f, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4ui());\n\n        [Test]\n        public void TypeConversionFloatToHalf()\n            => FormatConversionToArray<float, float16, C4f>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.FloatToHalf(), c.G.FloatToHalf(), c.R.FloatToHalf(), c.A.FloatToHalf() }\n            );\n\n\n        [Test]\n        public void TypeConversionFloatToDouble()\n            => FormatConversion<float, double, C4f, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #region Double to BGRA (other types)\n\n        [Test]\n        public void TypeConversionDoubleToByte()\n            => FormatConversion<double, byte, C4d, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void TypeConversionDoubleToUShort()\n            => FormatConversion<double, ushort, C4d, C4us>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4us());\n\n        [Test]\n        public void TypeConversionDoubleToUInt()\n            => FormatConversion<double, uint, C4d, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4ui());\n\n        [Test]\n        public void TypeConversionDoubleToHalf()\n            => FormatConversionToArray<double, float16, C4d>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.DoubleToHalf(), c.G.DoubleToHalf(), c.R.DoubleToHalf(), c.A.DoubleToHalf() }\n            );\n\n        [Test]\n        public void TypeConversionDoubleToFloat()\n            => FormatConversion<double, float, C4f, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #endregion\n\n        #region From BGRA\n\n        [Test]\n        public void FormatConversionBGRAToRGBA()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.BGRA, Col.Format.RGBA, c => c);\n\n        [Test]\n        public void FormatConversionBGRAToRGB()\n            => FormatConversion<byte, byte, C4b, C3b>(Col.Format.BGRA, Col.Format.RGB, c => c.RGB);\n\n        [Test]\n        public void FormatConversionBGRAToBGR()\n            => FormatConversion<byte, byte, C4b, C3b>(Col.Format.BGRA, Col.Format.BGR, c => c.RGB);\n\n        [Test]\n        public void FormatConversionBGRAToGray()\n            => FormatConversion<byte, byte, C4b, byte>(Col.Format.BGRA, Col.Format.Gray, c => c.ToGrayByte());\n\n        [Test]\n        public void FormatConversionBGRAToGrayAlpha()\n            => FormatConversionToArray<byte, byte, C4b>(Col.Format.BGRA, Col.Format.GrayAlpha, c => new byte[] { c.ToGrayByte(), c.A });\n\n        [Test]\n        public void FormatConversionBGRAToRG()\n            => FormatConversionToArray<byte, byte, C4b>(Col.Format.BGRA, Col.Format.RG, c => new byte[] { c.R, c.G });\n\n        #endregion\n\n        #region From RGB\n\n        [Test]\n        public void FormatConversionRGBToRGBWithAdditionalChannel()\n        {\n            var getRandom = s_randomValues[typeof(byte)];\n            var volume = ImageTensors.CreateImageVolume<byte>(new V3l(54, 23, 4));\n            volume.Data.SetByIndex((_) => (byte)getRandom(rnd));\n            var src = new PixImage<byte>(Col.Format.RGB, volume);\n            var dst = new PixImage<byte>(Col.Format.RGB, src);\n\n            src.GetChannel(0L).ForeachCoord((coord) =>\n            {\n                var expected = GetColor<byte, C3b>(src, coord);\n                var actual = GetColor<byte, C3b>(dst, coord);\n                Assert.AreEqual(expected, actual);\n            });\n        }\n\n        [Test]\n        public void FormatConversionRGBToBGRA()\n            => FormatConversion<byte, byte, C3b, C4b>(Col.Format.RGB, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void FormatConversionRGBToRGBA()\n            => FormatConversion<byte, byte, C3b, C4b>(Col.Format.RGB, Col.Format.RGBA, c => c.ToC4b());\n\n        [Test]\n        public void FormatConversionRGBToBGR()\n            => FormatConversion<byte, byte, C3b, C3b>(Col.Format.RGB, Col.Format.BGR, c => c);\n\n        [Test]\n        public void FormatConversionRGBToGray()\n            => FormatConversion<byte, byte, C3b, byte>(Col.Format.RGB, Col.Format.Gray, c => c.ToGrayByte());\n\n        [Test]\n        public void FormatConversionRGBToGrayAlpha()\n            => FormatConversionToArray<byte, byte, C3b>(Col.Format.RGB, Col.Format.GrayAlpha, c => new byte[] { c.ToGrayByte(), 255 });\n\n        [Test]\n        public void FormatConversionRGBToRG()\n            => FormatConversionToArray<byte, byte, C3b>(Col.Format.RGB, Col.Format.RG, c => new byte[] { c.R, c.G });\n\n        #endregion\n\n        #region From BGR\n\n        [Test]\n        public void FormatConversionBGRToBGRA()\n            => FormatConversion<byte, byte, C3b, C4b>(Col.Format.BGR, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void FormatConversionBGRToRGBA()\n            => FormatConversion<byte, byte, C3b, C4b>(Col.Format.BGR, Col.Format.RGBA, c => c.ToC4b());\n\n        [Test]\n        public void FormatConversionBGRToRGB()\n            => FormatConversion<byte, byte, C3b, C3b>(Col.Format.BGR, Col.Format.RGB, c => c);\n\n        [Test]\n        public void FormatConversionBGRToGray()\n            => FormatConversion<byte, byte, C3b, byte>(Col.Format.BGR, Col.Format.Gray, c => c.ToGrayByte());\n\n        [Test]\n        public void FormatConversionBGRToGrayAlpha()\n            => FormatConversionToArray<byte, byte, C3b>(Col.Format.BGR, Col.Format.GrayAlpha, c => new byte[] { c.ToGrayByte(), 255 });\n\n        [Test]\n        public void FormatConversionBGRToRG()\n            => FormatConversionToArray<byte, byte, C3b>(Col.Format.BGR, Col.Format.RG, c => new byte[] { c.R, c.G });\n\n        #endregion\n\n        #region From RG\n\n        [Test]\n        public void FormatConversionRGToBGRA()\n            => FormatConversionFromArray<byte, byte, C4b>(Col.Format.RG, Col.Format.BGRA, c => new C4b(c[0], c[1], (byte)0, (byte)255));\n\n        [Test]\n        public void FormatConversionRGToRGBA()\n            => FormatConversionFromArray<byte, byte, C4b>(Col.Format.RG, Col.Format.RGBA, c => new C4b(c[0], c[1], (byte)0, (byte)255));\n\n        [Test]\n        public void FormatConversionRGToRGB()\n            => FormatConversionFromArray<byte, byte, C3b>(Col.Format.RG, Col.Format.RGB, c => new C3b(c[0], c[1], (byte)0));\n\n        [Test]\n        public void FormatConversionRGToBGR()\n            => FormatConversionFromArray<byte, byte, C3b>(Col.Format.RG, Col.Format.BGR, c => new C3b(c[0], c[1], (byte)0));\n\n        #endregion\n\n        #endregion\n\n        #region Creation\n\n        struct Foo\n        {\n            public string Hugo;\n            public int Bar;\n        }\n\n        [Test]\n        public void CreateWithCustomFormat()\n        {\n            var format = new PixFormat(typeof(Foo), Col.Format.RG);\n            var pi = PixImage.Create(format, 4, 4).AsPixImage<Foo>();\n\n            pi.Volume[3, 2, 0] = new Foo() { Hugo = \"Hey\", Bar = 43 };\n\n            var result = pi.Volume[3, 2, 0];\n            Assert.AreEqual(\"Hey\", result.Hugo);\n            Assert.AreEqual(43, result.Bar);\n        }\n\n        [Test]\n        public void CreateArrayWithCustomFormat()\n        {\n            var data = new Foo[]\n            {\n                new Foo() { Hugo = \"A\", Bar = 1 },\n                new Foo() { Hugo = \"B\", Bar = 2 },\n                new Foo() { Hugo = \"C\", Bar = 3 },\n                new Foo() { Hugo = \"D\", Bar = 4 },\n            };\n\n            var pi = PixImage.Create(data, Col.Format.Gray, 2, 2).AsPixImage<Foo>();\n\n            for (int i = 0; i < data.Length; i++)\n            {\n                Assert.AreEqual(data[i], pi.Matrix[i % 2, i / 2]);\n            }\n        }\n\n        #endregion\n\n        #region  Stitch\n\n        [Test]\n        public void Stitch()\n        {\n            // Arrange tiles with varying sizes and null at [0,0]; ensure tiles do not align perfectly\n            // Grid layout (rows x columns):\n            // . G(2x2)\n            // B(3x1) R(3x2)\n            var red = new PixImage<byte>(Col.Format.RGB, new V2i(3, 2));\n            red.GetMatrix<C3b>().SetByCoord((x, y) => new C3b(255, 0, 0));\n\n            var green = new PixImage<byte>(Col.Format.RGB, new V2i(2, 2));\n            green.GetMatrix<C3b>().SetByCoord((x, y) => new C3b(0, 255, 0));\n\n            var blue = new PixImage<byte>(Col.Format.RGB, new V2i(3, 1));\n            blue.GetMatrix<C3b>().SetByCoord((x, y) => new C3b(0, 0, 255));\n\n            // Note: null at [0,0], sizes cause gaps (non-perfect alignment)\n            var grid = new[]\n            {\n                new[] { null,  green },\n                new[] { blue,  red }\n            };\n\n            // Act (generic overload)\n            var stitched = grid.Stitch();\n\n            // Assert size:\n            // sizesX = [max(0,3)=3, max(2,3)=3] -> 6; sizesY = [max(0,2)=2, max(1,2)=2] -> 4\n            Assert.AreEqual(new V2i(6, 4), stitched.Size);\n\n            var m = stitched.GetMatrix<C3b>();\n\n            // Top-left 3x2 should be black (null tile)\n            for (int y = 0; y < 2; y++)\n                for (int x = 0; x < 3; x++)\n                    Assert.AreEqual(new C3b(0, 0, 0), m[x, y], $\"Expected black at ({x},{y})\");\n\n            // Top-right area width is 3 but green is only 2 wide -> last column should be black\n            for (int y = 0; y < 2; y++)\n            {\n                for (int x = 3; x < 5; x++) Assert.AreEqual(new C3b(0, 255, 0), m[x, y], $\"Expected green at ({x},{y})\");\n                Assert.AreEqual(new C3b(0, 0, 0), m[5, y], $\"Expected black gap at (5,{y})\");\n            }\n\n            // Bottom-left row height is 2 but blue is only 1 high -> y=2 blue, y=3 black\n            for (int x = 0; x < 3; x++) Assert.AreEqual(new C3b(0, 0, 255), m[x, 2], $\"Expected blue at ({x},2)\");\n            for (int x = 0; x < 3; x++) Assert.AreEqual(new C3b(0, 0, 0), m[x, 3], $\"Expected black at ({x},3)\");\n\n            // Bottom-right 3x2 should be red\n            for (int y = 2; y < 4; y++)\n                for (int x = 3; x < 6; x++)\n                    Assert.AreEqual(new C3b(255, 0, 0), m[x, y], $\"Expected red at ({x},{y})\");\n\n            // Also test non-generic overload with base PixImage[][] dispatch and compare size and a sample pixel\n            PixImage[][] baseGrid =\n            [\n                [null, green],\n                [blue, red]\n            ];\n            var stitchedBase = baseGrid.Stitch();\n            Assert.IsNotNull(stitchedBase);\n            Assert.AreEqual(stitched.Size, stitchedBase.Size);\n            // Check a few sample pixels\n            var mb = stitchedBase.AsPixImage<byte>().GetMatrix<C3b>();\n            Assert.AreEqual(new C3b(0, 0, 0), mb[0, 0]);    // null tile area\n            Assert.AreEqual(new C3b(0, 255, 0), mb[3, 0]);  // green start\n            Assert.AreEqual(new C3b(0, 0, 0), mb[5, 0]);    // green gap column\n            Assert.AreEqual(new C3b(0, 0, 255), mb[0, 2]);  // blue row\n            Assert.AreEqual(new C3b(255, 0, 0), mb[3, 2]);  // red area\n\n            // Mismatching formats should throw\n            var gray = new PixImage<byte>(Col.Format.Gray, new V2i(1, 1));\n            var badGrid = new PixImage<byte>[][] { [red, gray] };\n            Assert.Throws<ArgumentException>(() => badGrid.Stitch());\n\n            // Null and empty inputs should return null (extension methods accept null receivers)\n            Assert.IsNull(PixImageExtensions.Stitch(null));\n            Assert.IsNull(Array.Empty<PixImage<byte>[]>().Stitch());\n        }\n\n        [Test]\n        public void StitchSquare()\n        {\n            // Arrange: 5 images with varying sizes to force gaps when arranged in a 3x3 near-square grid\n            // Index mapping (row-major into 3x3):\n            // [0]=R(2x1) [1]=G(1x2) [2]=B(3x1)\n            // [3]=Y(1x1) [4]=M(2x2) [5]=null (implicit)\n            // Row2 is entirely null\n            var red = new PixImage<byte>(Col.Format.RGB, new V2i(2, 1));\n            red.GetMatrix<C3b>().SetByCoord((x, y) => new C3b(255, 0, 0));\n\n            var green = new PixImage<byte>(Col.Format.RGB, new V2i(1, 2));\n            green.GetMatrix<C3b>().SetByCoord((x, y) => new C3b(0, 255, 0));\n\n            var blue = new PixImage<byte>(Col.Format.RGB, new V2i(3, 1));\n            blue.GetMatrix<C3b>().SetByCoord((x, y) => new C3b(0, 0, 255));\n\n            var yellow = new PixImage<byte>(Col.Format.RGB, new V2i(1, 1));\n            yellow.GetMatrix<C3b>().SetByCoord((x, y) => new C3b(255, 255, 0));\n\n            var magenta = new PixImage<byte>(Col.Format.RGB, new V2i(2, 2));\n            magenta.GetMatrix<C3b>().SetByCoord((x, y) => new C3b(255, 0, 255));\n\n            var list = new PixImage<byte>[] { red, green, blue, yellow, magenta };\n\n            // Act (generic overload)\n            var stitched = list.StitchSquare();\n\n            // Compute expected stitched size:\n            // squareSize = ceil(sqrt(5)) = 3\n            // Column widths = max per column across rows:\n            // col0: max(2,1,0)=2; col1: max(1,2,0)=2; col2: max(3,0,0)=3 -> width = 7\n            // Row heights = max per row across columns:\n            // row0: max(1,2,1)=2; row1: max(1,2,0)=2; row2: 0 -> height = 4\n            Assert.AreEqual(new V2i(7, 4), stitched.Size);\n\n            var m = stitched.GetMatrix<C3b>();\n\n            // Validate row 0 placements and gaps\n            // Red (2x1) at x=[0..1], y=0; gap at y=1\n            Assert.AreEqual(new C3b(255, 0, 0), m[0, 0]);\n            Assert.AreEqual(new C3b(255, 0, 0), m[1, 0]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[0, 1]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[1, 1]);\n\n            // Green (1x2) at x=2, y=[0..1]; gap column x=3 should be black (since column width=2)\n            Assert.AreEqual(new C3b(0, 255, 0), m[2, 0]);\n            Assert.AreEqual(new C3b(0, 255, 0), m[2, 1]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[3, 0]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[3, 1]);\n\n            // Blue (3x1) at x=[4..6], y=0; gap at y=1 for the whole band\n            Assert.AreEqual(new C3b(0, 0, 255), m[4, 0]);\n            Assert.AreEqual(new C3b(0, 0, 255), m[5, 0]);\n            Assert.AreEqual(new C3b(0, 0, 255), m[6, 0]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[4, 1]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[5, 1]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[6, 1]);\n\n            // Validate row 1 placements and gaps (y=2..3)\n            // Yellow (1x1) at (0,2); rest of its cell should be black\n            Assert.AreEqual(new C3b(255, 255, 0), m[0, 2]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[1, 2]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[0, 3]);\n\n            // Magenta (2x2) at x=[2..3], y=[2..3]\n            Assert.AreEqual(new C3b(255, 0, 255), m[2, 2]);\n            Assert.AreEqual(new C3b(255, 0, 255), m[3, 2]);\n            Assert.AreEqual(new C3b(255, 0, 255), m[2, 3]);\n            Assert.AreEqual(new C3b(255, 0, 255), m[3, 3]);\n\n            // Right-most band in row 1 (x=4..6) should be black (no image in that cell)\n            Assert.AreEqual(new C3b(0, 0, 0), m[4, 2]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[5, 2]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[6, 2]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[4, 3]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[5, 3]);\n            Assert.AreEqual(new C3b(0, 0, 0), m[6, 3]);\n\n            // Also test non-generic overload with base PixImage[] dispatch\n            PixImage[] baseList = [red, green, blue, yellow, magenta];\n            var stitchedBase = baseList.StitchSquare();\n            Assert.IsNotNull(stitchedBase);\n            Assert.AreEqual(stitched.Size, stitchedBase.Size);\n            var mb = stitchedBase.AsPixImage<byte>().GetMatrix<C3b>();\n            Assert.AreEqual(new C3b(255, 0, 0), mb[0, 0]);   // red\n            Assert.AreEqual(new C3b(0, 255, 0), mb[2, 1]);   // green column\n            Assert.AreEqual(new C3b(0, 0, 255), mb[6, 0]);   // blue\n            Assert.AreEqual(new C3b(255, 255, 0), mb[0, 2]); // yellow\n            Assert.AreEqual(new C3b(255, 0, 255), mb[3, 3]); // magenta\n\n            // Mismatching formats should throw\n            var gray = new PixImage<byte>(Col.Format.Gray, new V2i(1, 1));\n            Assert.Throws<ArgumentException>(() => new PixImage<byte>[] { red, gray }.StitchSquare());\n\n            // Null and empty inputs should return null (extension methods accept null receivers)\n            Assert.IsNull(PixImageExtensions.StitchSquare<byte>(null));\n            Assert.IsNull(Array.Empty<PixImage<byte>>().StitchSquare());\n        }\n\n        [Test]\n        public void PixCubeProperties()\n        {\n            var cube = new PixCube();\n            Assert.IsTrue(cube.IsEmpty);\n\n            cube[CubeSide.NegativeX] = new PixImageMipMap();\n            Assert.IsTrue(cube.IsEmpty);\n\n            cube[CubeSide.PositiveZ] = new PixImageMipMap(new PixImage<float>(Col.Format.RG, 42, 31));\n            Assert.IsFalse(cube.IsEmpty);\n            Assert.AreEqual(cube.PixFormat, PixFormat.FloatRG);\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Images/PixSaveParamsTests.cs",
    "content": "﻿using NUnit.Framework;\nusing System;\nusing Aardvark.Base;\n\nnamespace Aardvark.Tests.Images\n{\n    [TestFixture]\n    public class PixSaveParamsTests\n    {\n        [TestCase(-1)]\n        [TestCase(101)]\n        public void InvalidJpegQualityReportsNumericValue(int quality)\n        {\n            var e = Assert.Throws<ArgumentException>(() => new PixJpegSaveParams(quality));\n            Assert.AreEqual($\"Quality must be within 0 - 100, is {quality}.\", e.Message);\n        }\n\n        [TestCase(-1)]\n        [TestCase(101)]\n        public void InvalidWebpQualityReportsNumericValue(int quality)\n        {\n            var e = Assert.Throws<ArgumentException>(() => new PixWebpSaveParams(quality));\n            Assert.AreEqual($\"Quality must be within 0 - 100, is {quality}.\", e.Message);\n        }\n\n        [TestCase(-1)]\n        [TestCase(10)]\n        public void InvalidPngCompressionLevelReportsNumericValue(int compressionLevel)\n        {\n            var e = Assert.Throws<ArgumentException>(() => new PixPngSaveParams(compressionLevel));\n            Assert.AreEqual($\"Compression level must be within 0 - 9, is {compressionLevel}.\", e.Message);\n        }\n\n        [TestCase(0)]\n        [TestCase(100)]\n        public void JpegQualityBoundariesAreValid(int quality)\n        {\n            var p = new PixJpegSaveParams(quality);\n\n            Assert.AreEqual(PixFileFormat.Jpeg, p.Format);\n            Assert.AreEqual(quality, p.Quality);\n        }\n\n        [TestCase(0)]\n        [TestCase(100)]\n        public void WebpQualityBoundariesAreValid(int quality)\n        {\n            var p = new PixWebpSaveParams(quality);\n\n            Assert.AreEqual(PixFileFormat.Webp, p.Format);\n            Assert.AreEqual(quality, p.Quality);\n            Assert.IsFalse(p.Lossless);\n        }\n\n        [TestCase(0)]\n        [TestCase(9)]\n        public void PngCompressionLevelBoundariesAreValid(int compressionLevel)\n        {\n            var p = new PixPngSaveParams(compressionLevel);\n\n            Assert.AreEqual(PixFileFormat.Png, p.Format);\n            Assert.AreEqual(compressionLevel, p.CompressionLevel);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Images/PixVolumeTests.cs",
    "content": "﻿using NUnit.Framework;\nusing System;\nusing Aardvark.Base;\nusing float16 = Aardvark.Base.Half;\n\nnamespace Aardvark.Tests.Images\n{\n    [TestFixture]\n    class PixVolumeTests\n    {\n        static readonly RandomSystem rnd = new(0);\n\n        #region Format Conversions\n\n        private static T[] GetArray<T>(PixVolume<T> pi, V3l coord)\n        {\n            var arr = new T[pi.ChannelCount];\n            arr.SetByIndex(i => pi.Tensor4[new V4l(coord, i)]);\n            return arr;\n        }\n\n        private static Tc GetColor<T, Tc>(PixVolume<T> pi, V3l coord)\n            => pi.GetVolume<Tc>()[coord];\n\n        private static void FormatConversion<T1, T2, Tc1, Tc2>(Col.Format sourceFormat, Col.Format targetFormat,\n                                                               Func<PixVolume<T1>, V3l, Tc1> getInput,\n                                                               Func<PixVolume<T2>, V3l, Tc2> getActual,\n                                                               Func<Tc1, Tc2> expectedConversion,\n                                                               bool subImageWindow)\n        {\n            var getRandom = PixImageTests.s_randomValues[typeof(T1)];\n            var src = new PixVolume<T1>(sourceFormat, 43, 31, 23);\n            src.Tensor4.Data.SetByIndex((_) => (T1)getRandom(rnd));\n\n            if (subImageWindow)\n                src = new PixVolume<T1>(sourceFormat, src.Tensor4.SubImageWindow(11, 7, 3, 27, 13, 8));\n\n            var dst = new PixVolume<T2>(targetFormat, src);\n\n            src.GetChannel(0L).ForeachCoord((coord) =>\n            {\n                var expected = expectedConversion(getInput(src, coord));\n                var actual = getActual(dst, coord);\n                Assert.AreEqual(expected, actual);\n            });\n        }\n\n        private static void FormatConversionArrays<T1, T2>(Col.Format sourceFormat, Col.Format targetFormat, Func<T1[], T2[]> expectedConversion, bool subImageWindow = false)\n            => FormatConversion<T1, T2, T1[], T2[]>(sourceFormat, targetFormat, GetArray, GetArray, expectedConversion, subImageWindow);\n\n        private static void FormatConversionFromArray<T1, T2, Tc2>(Col.Format sourceFormat, Col.Format targetFormat, Func<T1[], Tc2> expectedConversion, bool subImageWindow = false)\n            => FormatConversion<T1, T2, T1[], Tc2>(sourceFormat, targetFormat, GetArray, GetColor<T2, Tc2>, expectedConversion, subImageWindow);\n\n        private static void FormatConversionToArray<T1, T2, Tc1>(Col.Format sourceFormat, Col.Format targetFormat, Func<Tc1, T2[]> expectedConversion, bool subImageWindow = false)\n            => FormatConversion<T1, T2, Tc1, T2[]>(sourceFormat, targetFormat, GetColor<T1, Tc1>, GetArray, expectedConversion, subImageWindow);\n\n        private static void FormatConversion<T1, T2, Tc1, Tc2>(Col.Format sourceFormat, Col.Format targetFormat, Func<Tc1, Tc2> expectedConversion, bool subImageWindow = false)\n            => FormatConversion<T1, T2, Tc1, Tc2>(sourceFormat, targetFormat, GetColor<T1, Tc1>, GetColor<T2, Tc2>, expectedConversion, subImageWindow);\n\n        #region From Gray\n\n        [Test]\n        public void FormatConversionGrayToGrayAlpha()\n            => FormatConversionToArray<byte, byte, byte>(Col.Format.Gray, Col.Format.GrayAlpha, gray => new byte[] { gray, 255 });\n\n        [Test]\n        public void FormatConversionGrayToAlpha()\n            => FormatConversion<byte, byte, byte, byte>(Col.Format.Gray, Col.Format.Alpha, gray => 255);\n\n        [Test]\n        public void FormatConversionGrayToRGB()\n            => FormatConversion<byte, byte, byte, C3b>(Col.Format.Gray, Col.Format.RGB, gray => new C3b(gray));\n\n        [Test]\n        public void FormatConversionGrayToBGR()\n            => FormatConversion<byte, byte, byte, C3b>(Col.Format.Gray, Col.Format.BGR, gray => new C3b(gray));\n\n        [Test]\n        public void FormatConversionGrayToRGBA()\n            => FormatConversion<byte, byte, byte, C4b>(Col.Format.Gray, Col.Format.RGBA, gray => new C4b(gray));\n\n        [Test]\n        public void FormatConversionGrayToBGRA()\n            => FormatConversion<byte, byte, byte, C4b>(Col.Format.Gray, Col.Format.BGRA, gray => new C4b(gray));\n\n        [Test]\n        public void FormatConversionGrayToRG()\n            => FormatConversionToArray<byte, byte, byte>(Col.Format.Gray, Col.Format.RG, gray => new byte[] { gray, gray });\n\n        #endregion\n\n        #region From GrayAlpha\n\n        [Test]\n        public void FormatConversionGrayAlphaToGray()\n            => FormatConversionFromArray<byte, byte, byte>(Col.Format.GrayAlpha, Col.Format.Gray, gray => gray[0]);\n\n        [Test]\n        public void FormatConversionGrayAlphaToAlpha()\n            => FormatConversionFromArray<byte, byte, byte>(Col.Format.GrayAlpha, Col.Format.Alpha, gray => gray[1]);\n\n        [Test]\n        public void FormatConversionGrayAlphaToRGB()\n            => FormatConversionFromArray<byte, byte, C3b>(Col.Format.GrayAlpha, Col.Format.RGB, gray => new C3b(gray[0]));\n\n        [Test]\n        public void FormatConversionGrayAlphaToBGR()\n            => FormatConversionFromArray<byte, byte, C3b>(Col.Format.GrayAlpha, Col.Format.BGR, gray => new C3b(gray[0]));\n\n        [Test]\n        public void FormatConversionGrayAlphaToRGBA()\n            => FormatConversionFromArray<byte, byte, C4b>(Col.Format.GrayAlpha, Col.Format.RGBA, gray => new C4b(gray[0], gray[0], gray[0], gray[1]));\n\n        [Test]\n        public void FormatConversionGrayAlphaToBGRA()\n            => FormatConversionFromArray<byte, byte, C4b>(Col.Format.GrayAlpha, Col.Format.BGRA, gray => new C4b(gray[0], gray[0], gray[0], gray[1]));\n\n        [Test]\n        public void FormatConversionGrayAlphaToRG()\n            => FormatConversionArrays<byte, byte>(Col.Format.GrayAlpha, Col.Format.RG, gray => new byte[] { gray[0], gray[0] });\n\n        #endregion\n\n        #region From RGBA\n\n        [Test]\n        public void FormatConversionRGBAToRGBA()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.RGBA, Col.Format.RGBA, c => c);\n\n        [Test]\n        public void FormatConversionRGBAToRGBAWindow()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.RGBA, Col.Format.RGBA, c => c, true);\n\n        [Test]\n        public void FormatConversionRGBAToBGRA()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c);\n\n        [Test]\n        public void FormatConversionRGBAToBGRAWindow()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c, true);\n\n        [Test]\n        public void FormatConversionRGBAToRGB()\n            => FormatConversion<byte, byte, C4b, C3b>(Col.Format.RGBA, Col.Format.RGB, c => c.RGB);\n\n        [Test]\n        public void FormatConversionRGBAToBGR()\n            => FormatConversion<byte, byte, C4b, C3b>(Col.Format.RGBA, Col.Format.BGR, c => c.RGB);\n\n        [Test]\n        public void FormatConversionRGBAToGray()\n            => FormatConversion<byte, byte, C4b, byte>(Col.Format.RGBA, Col.Format.Gray, c => c.ToGrayByte());\n\n        [Test]\n        public void FormatConversionRGBAToGrayAlpha()\n            => FormatConversionToArray<byte, byte, C4b>(Col.Format.RGBA, Col.Format.GrayAlpha, c => new byte[] { c.ToGrayByte(), c.A });\n\n        [Test]\n        public void FormatConversionRGBAToRG()\n            => FormatConversionToArray<byte, byte, C4b>(Col.Format.RGBA, Col.Format.RG, c => new byte[] { c.R, c.G });\n\n        #endregion\n\n        #region From BGRA\n\n        [Test]\n        public void FormatConversionBGRAToRGBA()\n            => FormatConversion<byte, byte, C4b, C4b>(Col.Format.BGRA, Col.Format.RGBA, c => c);\n\n        [Test]\n        public void FormatConversionBGRAToRGB()\n            => FormatConversion<byte, byte, C4b, C3b>(Col.Format.BGRA, Col.Format.RGB, c => c.RGB);\n\n        [Test]\n        public void FormatConversionBGRAToBGR()\n            => FormatConversion<byte, byte, C4b, C3b>(Col.Format.BGRA, Col.Format.BGR, c => c.RGB);\n\n        [Test]\n        public void FormatConversionBGRAToGray()\n            => FormatConversion<byte, byte, C4b, byte>(Col.Format.BGRA, Col.Format.Gray, c => c.ToGrayByte());\n\n        [Test]\n        public void FormatConversionBGRAToGrayAlpha()\n            => FormatConversionToArray<byte, byte, C4b>(Col.Format.BGRA, Col.Format.GrayAlpha, c => new byte[] { c.ToGrayByte(), c.A });\n\n        [Test]\n        public void FormatConversionBGRAToRG()\n            => FormatConversionToArray<byte, byte, C4b>(Col.Format.BGRA, Col.Format.RG, c => new byte[] { c.R, c.G });\n\n        #region Byte to BGRA (other types)\n\n        [Test]\n        public void TypeConversionByteToUShort()\n            => FormatConversion<byte, ushort, C4b, C4us>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4us());\n\n        [Test]\n        public void TypeConversionByteToUInt()\n            => FormatConversion<byte, uint, C4b, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4ui());\n\n        [Test]\n        public void TypeConversionByteToHalf()\n            => FormatConversionToArray<byte, float16, C4b>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.ByteToHalf(), c.G.ByteToHalf(), c.R.ByteToHalf(), c.A.ByteToHalf() }\n            );\n\n        [Test]\n        public void TypeConversionByteToFloat()\n            => FormatConversion<byte, float, C4b, C4f>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4f());\n\n        [Test]\n        public void TypeConversionByteToDouble()\n            => FormatConversion<byte, double, C4b, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #region UShort to BGRA (other types)\n\n        [Test]\n        public void TypeConversionUShortToByte()\n            => FormatConversion<ushort, byte, C4us, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void TypeConversionUShortToUInt()\n            => FormatConversion<ushort, uint, C4us, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4ui());\n\n        [Test]\n        public void TypeConversionUShortToHalf()\n            => FormatConversionToArray<ushort, float16, C4us>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.UShortToHalf(), c.G.UShortToHalf(), c.R.UShortToHalf(), c.A.UShortToHalf() }\n            );\n\n        [Test]\n        public void TypeConversionUShortToFloat()\n            => FormatConversion<ushort, float, C4us, C4f>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4f());\n\n        [Test]\n        public void TypeConversionUShortToDouble()\n            => FormatConversion<ushort, double, C4us, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #region UInt to BGRA (other types)\n\n        [Test]\n        public void TypeConversionUIntToByte()\n            => FormatConversion<uint, byte, C4ui, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void TypeConversionUIntToUShort()\n            => FormatConversion<uint, ushort, C4ui, C4us>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4us());\n\n        [Test]\n        public void TypeConversionUIntToHalf()\n            => FormatConversionToArray<uint, float16, C4ui>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.UIntToHalf(), c.G.UIntToHalf(), c.R.UIntToHalf(), c.A.UIntToHalf() }\n            );\n\n        [Test]\n        public void TypeConversionUIntToFloat()\n            => FormatConversion<uint, float, C4ui, C4f>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4f());\n\n        [Test]\n        public void TypeConversionUIntToDouble()\n            => FormatConversion<uint, double, C4ui, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #region Half to BGRA (other types)\n\n        [Test]\n        public void TypeConversionHalfToByte()\n            => FormatConversionFromArray<float16, byte, C4b>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4b(c[0].HalfToByte(), c[1].HalfToByte(), c[2].HalfToByte(), c[3].HalfToByte())\n            );\n\n        [Test]\n        public void TypeConversionHalfToUShort()\n            => FormatConversionFromArray<float16, ushort, C4us>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4us(c[0].HalfToUShort(), c[1].HalfToUShort(), c[2].HalfToUShort(), c[3].HalfToUShort())\n            );\n\n        [Test]\n        public void TypeConversionHalfToUInt()\n            => FormatConversionFromArray<float16, uint, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4ui(c[0].HalfToUInt(), c[1].HalfToUInt(), c[2].HalfToUInt(), c[3].HalfToUInt())\n            );\n\n        [Test]\n        public void TypeConversionHalfToFloat()\n            => FormatConversionFromArray<float16, float, C4f>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4f(c[0], c[1], c[2], c[3])\n            );\n\n        [Test]\n        public void TypeConversionHalfToDouble()\n            => FormatConversionFromArray<float16, double, C4d>(Col.Format.RGBA, Col.Format.BGRA, c =>\n                new C4d(c[0], c[1], c[2], c[3])\n            );\n\n        #endregion\n\n        #region Float to BGRA (other types)\n\n        [Test]\n        public void TypeConversionFloatToByte()\n            => FormatConversion<float, byte, C4f, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void TypeConversionFloatToUShort()\n            => FormatConversion<float, ushort, C4f, C4us>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4us());\n\n        [Test]\n        public void TypeConversionFloatToUInt()\n            => FormatConversion<float, uint, C4f, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4ui());\n\n        [Test]\n        public void TypeConversionFloatToHalf()\n            => FormatConversionToArray<float, float16, C4f>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.FloatToHalf(), c.G.FloatToHalf(), c.R.FloatToHalf(), c.A.FloatToHalf() }\n            );\n\n\n        [Test]\n        public void TypeConversionFloatToDouble()\n            => FormatConversion<float, double, C4f, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #region Double to BGRA (other types)\n\n        [Test]\n        public void TypeConversionDoubleToByte()\n            => FormatConversion<double, byte, C4d, C4b>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void TypeConversionDoubleToUShort()\n            => FormatConversion<double, ushort, C4d, C4us>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4us());\n\n        [Test]\n        public void TypeConversionDoubleToUInt()\n            => FormatConversion<double, uint, C4d, C4ui>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4ui());\n\n        [Test]\n        public void TypeConversionDoubleToHalf()\n            => FormatConversionToArray<double, float16, C4d>(Col.Format.RGBA, Col.Format.BGRA,\n                c => new float16[] { c.B.DoubleToHalf(), c.G.DoubleToHalf(), c.R.DoubleToHalf(), c.A.DoubleToHalf() }\n            );\n\n        [Test]\n        public void TypeConversionDoubleToFloat()\n            => FormatConversion<double, float, C4f, C4d>(Col.Format.RGBA, Col.Format.BGRA, c => c.ToC4d());\n\n        #endregion\n\n        #endregion\n\n        #region From RGB\n\n        [Test]\n        public void FormatConversionRGBToRGBWithAdditionalChannel()\n        {\n            var getRandom = PixImageTests.s_randomValues[typeof(byte)];\n            var tensor = ImageTensors.CreateImageTensor4<byte>(new V4l(54, 23, 11, 4));\n            tensor.Data.SetByIndex((_) => (byte)getRandom(rnd));\n            var src = new PixVolume<byte>(Col.Format.RGB, tensor);\n            var dst = new PixVolume<byte>(Col.Format.RGB, src);\n\n            src.GetChannel(0L).ForeachCoord((coord) =>\n            {\n                var expected = GetColor<byte, C3b>(src, coord);\n                var actual = GetColor<byte, C3b>(dst, coord);\n                Assert.AreEqual(expected, actual);\n            });\n        }\n\n        [Test]\n        public void FormatConversionRGBToBGRA()\n            => FormatConversion<byte, byte, C3b, C4b>(Col.Format.RGB, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void FormatConversionRGBToRGBA()\n            => FormatConversion<byte, byte, C3b, C4b>(Col.Format.RGB, Col.Format.RGBA, c => c.ToC4b());\n\n        [Test]\n        public void FormatConversionRGBToBGR()\n            => FormatConversion<byte, byte, C3b, C3b>(Col.Format.RGB, Col.Format.BGR, c => c);\n\n        [Test]\n        public void FormatConversionRGBToGray()\n            => FormatConversion<byte, byte, C3b, byte>(Col.Format.RGB, Col.Format.Gray, c => c.ToGrayByte());\n\n        [Test]\n        public void FormatConversionRGBToGrayAlpha()\n            => FormatConversionToArray<byte, byte, C3b>(Col.Format.RGB, Col.Format.GrayAlpha, c => new byte[] { c.ToGrayByte(), 255 });\n\n        [Test]\n        public void FormatConversionRGBToRG()\n            => FormatConversionToArray<byte, byte, C3b>(Col.Format.RGB, Col.Format.RG, c => new byte[] { c.R, c.G });\n\n        #endregion\n\n        #region From BGR\n\n        [Test]\n        public void FormatConversionBGRToBGRA()\n            => FormatConversion<byte, byte, C3b, C4b>(Col.Format.BGR, Col.Format.BGRA, c => c.ToC4b());\n\n        [Test]\n        public void FormatConversionBGRToRGBA()\n            => FormatConversion<byte, byte, C3b, C4b>(Col.Format.BGR, Col.Format.RGBA, c => c.ToC4b());\n\n        [Test]\n        public void FormatConversionBGRToRGB()\n            => FormatConversion<byte, byte, C3b, C3b>(Col.Format.BGR, Col.Format.RGB, c => c);\n\n        [Test]\n        public void FormatConversionBGRToGray()\n            => FormatConversion<byte, byte, C3b, byte>(Col.Format.BGR, Col.Format.Gray, c => c.ToGrayByte());\n\n        [Test]\n        public void FormatConversionBGRToGrayAlpha()\n            => FormatConversionToArray<byte, byte, C3b>(Col.Format.BGR, Col.Format.GrayAlpha, c => new byte[] { c.ToGrayByte(), 255 });\n\n        [Test]\n        public void FormatConversionBGRToRG()\n            => FormatConversionToArray<byte, byte, C3b>(Col.Format.BGR, Col.Format.RG, c => new byte[] { c.R, c.G });\n\n        #endregion\n\n        #region From RG\n\n        [Test]\n        public void FormatConversionRGToBGRA()\n            => FormatConversionFromArray<byte, byte, C4b>(Col.Format.RG, Col.Format.BGRA, c => new C4b(c[0], c[1], (byte)0, (byte)255));\n\n        [Test]\n        public void FormatConversionRGToRGBA()\n            => FormatConversionFromArray<byte, byte, C4b>(Col.Format.RG, Col.Format.RGBA, c => new C4b(c[0], c[1], (byte)0, (byte)255));\n\n        [Test]\n        public void FormatConversionRGToRGB()\n            => FormatConversionFromArray<byte, byte, C3b>(Col.Format.RG, Col.Format.RGB, c => new C3b(c[0], c[1], (byte)0));\n\n        [Test]\n        public void FormatConversionRGToBGR()\n            => FormatConversionFromArray<byte, byte, C3b>(Col.Format.RG, Col.Format.BGR, c => new C3b(c[0], c[1], (byte)0));\n\n        #endregion\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Images/SystemDrawingTests.cs",
    "content": "﻿//using Aardvark.Base;\n//using NUnit.Framework;\n//using System.Drawing;\n//using System.IO;\n//using System.Net;\n\n//namespace Aardvark.Tests.Images\n//{\n//    [TestFixture]\n//    public class SystemDrawingTests\n//    {\n//        private static string TestImageUrl = @\"https://github.com/aardvark-platform/aardvark.docs/wiki/gallery/HelloWorld.jpg\";\n//        private static byte[] TestImageBuffer = new WebClient().DownloadData(TestImageUrl);\n\n//        [Test]\n//        public void SystemDrawingBitmap_ToPixImage()\n//        {\n//            using (var stream = new MemoryStream(TestImageBuffer))\n//            {\n//                var a = (Bitmap)Image.FromStream(stream);\n//                var b = a.ToPixImage();\n//                Assert.IsTrue(a.Width == b.Size.X && a.Height == b.Size.Y);\n//            }\n//        }\n\n//        [Test]\n//        public void SystemDrawingImage_ToPixImage()\n//        {\n//            using (var stream = new MemoryStream(TestImageBuffer))\n//            {\n//                var a = Image.FromStream(stream);\n//                var b = a.ToPixImage();\n//                Assert.IsTrue(a.Width == b.Size.X && a.Height == b.Size.Y);\n//            }\n//        }\n\n//        [Test]\n//        public void PixImage_ToSystemDrawingBitmap()\n//        {\n//            using (var stream = new MemoryStream(TestImageBuffer))\n//            {\n//                var a = PixImage.Create(stream);\n//                var b = a.ToSystemDrawingBitmap();\n\n//                Assert.IsTrue(a.Size.X == b.Width && a.Size.Y == b.Height);\n//            }\n//        }\n        \n//        [Test]\n//        public void SaveViaSystemDrawing_Png()\n//        {\n//            using (var stream = new MemoryStream(TestImageBuffer))\n//            {\n//                var a = PixImage.Create(stream);\n\n//                using (var store = new MemoryStream())\n//                {\n//                    var success = a.SaveViaSystemDrawing(store, PixFileFormat.Png, PixSaveOptions.Default, 100);\n//                    Assert.IsTrue(success);\n//                    store.Seek(0, SeekOrigin.Begin);\n//                    var b = PixImage.Create(store);\n//                    Assert.IsTrue(a.Size == b.Size);\n//                }\n//            }\n//        }\n\n//        [Test]\n//        public void SaveViaSystemDrawing_Jpg()\n//        {\n//            using (var stream = new MemoryStream(TestImageBuffer))\n//            {\n//                var a = PixImage.Create(stream);\n\n//                using (var store = new MemoryStream())\n//                {\n//                    var success = a.SaveViaSystemDrawing(store, PixFileFormat.Jpeg, PixSaveOptions.Default, 90);\n//                    Assert.IsTrue(success);\n//                    store.Seek(0, SeekOrigin.Begin);\n//                    var b = PixImage.Create(store);\n//                    Assert.IsTrue(a.Size == b.Size);\n//                }\n//            }\n//        }\n//    }\n//}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Json/SystemTextJsonTests.cs",
    "content": "﻿using NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Text.Json;\nusing System.Text.Json.Serialization;\n\nnamespace Aardvark.Base.Tests.Json\n{\n    public static class JsonConverterExtensions\n    {\n        #region Colors\n\n        public static void W(this Utf8JsonWriter writer, in C3b value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3b value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetByte();\n                reader.Read(); value.G = reader.GetByte();\n                reader.Read(); value.B = reader.GetByte();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetDouble();\n                reader.Read(); value.G = reader.GetDouble();\n                reader.Read(); value.B = reader.GetDouble();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetSingle();\n                reader.Read(); value.G = reader.GetSingle();\n                reader.Read(); value.B = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C3ui value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3ui value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetUInt32();\n                reader.Read(); value.G = reader.GetUInt32();\n                reader.Read(); value.B = reader.GetUInt32();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C3us value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C3us value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetUInt16();\n                reader.Read(); value.G = reader.GetUInt16();\n                reader.Read(); value.B = reader.GetUInt16();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in C4b value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteNumberValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4b value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetByte();\n                reader.Read(); value.G = reader.GetByte();\n                reader.Read(); value.B = reader.GetByte();\n                reader.Read(); value.A = reader.GetByte();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C4d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteNumberValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetDouble();\n                reader.Read(); value.G = reader.GetDouble();\n                reader.Read(); value.B = reader.GetDouble();\n                reader.Read(); value.A = reader.GetDouble();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C4f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteNumberValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetSingle();\n                reader.Read(); value.G = reader.GetSingle();\n                reader.Read(); value.B = reader.GetSingle();\n                reader.Read(); value.A = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C4ui value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteNumberValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4ui value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetUInt32();\n                reader.Read(); value.G = reader.GetUInt32();\n                reader.Read(); value.B = reader.GetUInt32();\n                reader.Read(); value.A = reader.GetUInt32();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in C4us value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.R);\n            writer.WriteNumberValue(value.G);\n            writer.WriteNumberValue(value.B);\n            writer.WriteNumberValue(value.A);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out C4us value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.R = reader.GetUInt16();\n                reader.Read(); value.G = reader.GetUInt16();\n                reader.Read(); value.B = reader.GetUInt16();\n                reader.Read(); value.A = reader.GetUInt16();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in CieLabf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.L);\n            writer.WriteNumberValue(value.a);\n            writer.WriteNumberValue(value.b);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CieLabf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.L = reader.GetSingle();\n                reader.Read(); value.a = reader.GetSingle();\n                reader.Read(); value.b = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in CieLuvf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.L);\n            writer.WriteNumberValue(value.u);\n            writer.WriteNumberValue(value.v);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CieLuvf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.L = reader.GetSingle();\n                reader.Read(); value.u = reader.GetSingle();\n                reader.Read(); value.v = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in CieXYZf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CieXYZf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetSingle();\n                reader.Read(); value.Y = reader.GetSingle();\n                reader.Read(); value.Z = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in CieYxyf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.x);\n            writer.WriteNumberValue(value.y);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CieYxyf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Y = reader.GetSingle();\n                reader.Read(); value.x = reader.GetSingle();\n                reader.Read(); value.y = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in CMYKf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.C);\n            writer.WriteNumberValue(value.M);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.K);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out CMYKf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.C = reader.GetSingle();\n                reader.Read(); value.M = reader.GetSingle();\n                reader.Read(); value.Y = reader.GetSingle();\n                reader.Read(); value.K = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in HSLf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.H);\n            writer.WriteNumberValue(value.S);\n            writer.WriteNumberValue(value.L);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out HSLf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.H = reader.GetSingle();\n                reader.Read(); value.S = reader.GetSingle();\n                reader.Read(); value.L = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in HSVf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.H);\n            writer.WriteNumberValue(value.S);\n            writer.WriteNumberValue(value.V);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out HSVf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.H = reader.GetSingle();\n                reader.Read(); value.S = reader.GetSingle();\n                reader.Read(); value.V = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Yuvf value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.u);\n            writer.WriteNumberValue(value.v);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Yuvf value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Y = reader.GetSingle();\n                reader.Read(); value.u = reader.GetSingle();\n                reader.Read(); value.v = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Euclidean\n\n        public static void W(this Utf8JsonWriter writer, in Euclidean2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Rot\"); writer.W(value.Rot, options);\n            writer.WritePropertyName(\"Trans\"); writer.W(value.Trans, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Euclidean2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"rot\": case \"Rot\": reader.R(out result.Rot, options); break;\n                        case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Euclidean2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Rot\"); writer.W(value.Rot, options);\n            writer.WritePropertyName(\"Trans\"); writer.W(value.Trans, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Euclidean2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"rot\": case \"Rot\": reader.R(out result.Rot, options); break;\n                        case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Euclidean3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Rot\"); writer.W(value.Rot, options);\n            writer.WritePropertyName(\"Trans\"); writer.W(value.Trans, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Euclidean3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"rot\": case \"Rot\": reader.R(out result.Rot, options); break;\n                        case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Euclidean3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Rot\"); writer.W(value.Rot, options);\n            writer.WritePropertyName(\"Trans\"); writer.W(value.Trans, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Euclidean3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"rot\": case \"Rot\": reader.R(out result.Rot, options); break;\n                        case \"trans\": case \"Trans\": reader.R(out result.Trans, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Lines\n\n        public static void W(this Utf8JsonWriter writer, in Line2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"P0\"); writer.W(value.P0, options);\n            writer.WritePropertyName(\"P1\"); writer.W(value.P1, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Line2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                        case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Line2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"P0\"); writer.W(value.P0, options);\n            writer.WritePropertyName(\"P1\"); writer.W(value.P1, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Line2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                        case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Line3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"P0\"); writer.W(value.P0, options);\n            writer.WritePropertyName(\"P1\"); writer.W(value.P1, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Line3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                        case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Line3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"P0\"); writer.W(value.P0, options);\n            writer.WritePropertyName(\"P1\"); writer.W(value.P1, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Line3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"p0\": case \"P0\": reader.R(out result.P0, options); break;\n                        case \"p1\": case \"P1\": reader.R(out result.P1, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Matrices\n\n        public static void W(this Utf8JsonWriter writer, in M22d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M22d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new double[4];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetDouble();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M22d(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M22f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M22f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new float[4];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetSingle();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M22f(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M33d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M33d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new double[9];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetDouble();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M33d(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M33f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M33f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new float[9];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetSingle();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M33f(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M44d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M44d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new double[16];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetDouble();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M44d(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in M44f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            var xs = value.ToArray();\n            for (var i = 0; i < xs.Length; i++) writer.WriteNumberValue(xs[i]);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out M44f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new float[16];\n                for (var i = 0; i < xs.Length; i++)\n                {\n                    reader.Read();\n                    xs[i] = reader.GetSingle();\n                }\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n                value = new M44f(xs);\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Planes\n\n        public static void W(this Utf8JsonWriter writer, in Plane2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Normal\");\n            writer.W(value.Normal, options);\n            writer.WriteNumber(\"Distance\", value.Distance);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                        case \"distance\": case \"Distance\": result.Distance = reader.GetDouble(); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Plane2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Normal\");\n            writer.W(value.Normal, options);\n            writer.WriteNumber(\"Distance\", value.Distance);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                        case \"distance\": case \"Distance\": result.Distance = reader.GetSingle(); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Plane3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Normal\");\n            writer.W(value.Normal, options);\n            writer.WriteNumber(\"Distance\", value.Distance);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                        case \"distance\": case \"Distance\": result.Distance = reader.GetDouble(); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Plane3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Normal\");\n            writer.W(value.Normal, options);\n            writer.WriteNumber(\"Distance\", value.Distance);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"normal\": case \"Normal\": reader.R(out result.Normal, options); break;\n                        case \"distance\": case \"Distance\": result.Distance = reader.GetSingle(); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n                              \n        public static void W(this Utf8JsonWriter writer, IEnumerable<Plane2d> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane2d[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<Plane2d>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    var x = default(Plane2d);\n                    reader.R(ref x, options);\n                    xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<Plane2f> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane2f[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<Plane2f>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    var x = default(Plane2f);\n                    reader.R(ref x, options);\n                    xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<Plane3d> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane3d[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<Plane3d>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    var x = default(Plane3d);\n                    reader.R(ref x, options);\n                    xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<Plane3f> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Plane3f[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<Plane3f>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    var x = default(Plane3f);\n                    reader.R(ref x, options);\n                    xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Rays\n\n        public static void W(this Utf8JsonWriter writer, in Ray2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Origin\"); writer.W(value.Origin, options);\n            writer.WritePropertyName(\"Direction\"); writer.W(value.Direction, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Ray2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                        case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Ray2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Origin\"); writer.W(value.Origin, options);\n            writer.WritePropertyName(\"Direction\"); writer.W(value.Direction, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Ray2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                        case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Ray3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Origin\"); writer.W(value.Origin, options);\n            writer.WritePropertyName(\"Direction\"); writer.W(value.Direction, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Ray3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                        case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Ray3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WritePropertyName(\"Origin\"); writer.W(value.Origin, options);\n            writer.WritePropertyName(\"Direction\"); writer.W(value.Direction, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Ray3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"origin\": case \"Origin\": reader.R(out result.Origin, options); break;\n                        case \"direction\": case \"Direction\": reader.R(out result.Direction, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Rotations, Quaternions\n\n        public static void W(this Utf8JsonWriter writer, in Rot2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Angle);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Rot2d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Angle = reader.GetDouble();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Rot2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.Angle);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Rot2f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.Angle = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in Rot3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.W);\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Rot3d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.W = reader.GetDouble();\n                reader.Read(); value.X = reader.GetDouble();\n                reader.Read(); value.Y = reader.GetDouble();\n                reader.Read(); value.Z = reader.GetDouble();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Rot3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.W);\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out Rot3f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.W = reader.GetSingle();\n                reader.Read(); value.X = reader.GetSingle();\n                reader.Read(); value.Y = reader.GetSingle();\n                reader.Read(); value.Z = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, in QuaternionD value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.W);\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out QuaternionD value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.W = reader.GetDouble();\n                reader.Read(); value.X = reader.GetDouble();\n                reader.Read(); value.Y = reader.GetDouble();\n                reader.Read(); value.Z = reader.GetDouble();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in QuaternionF value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.W);\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out QuaternionF value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.W = reader.GetSingle();\n                reader.Read(); value.X = reader.GetSingle();\n                reader.Read(); value.Y = reader.GetSingle();\n                reader.Read(); value.Z = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Similarity\n\n        public static void W(this Utf8JsonWriter writer, in Similarity2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WriteNumber(\"Scale\", value.Scale);\n            writer.WritePropertyName(\"Euclidean\"); writer.W(value.Euclidean, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Similarity2d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"scale\": case \"Scale\": result.Scale = reader.GetDouble(); break;\n                        case \"euclidean\": case \"Euclidean\": reader.R(ref result.Euclidean, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Similarity2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WriteNumber(\"Scale\", value.Scale);\n            writer.WritePropertyName(\"Euclidean\"); writer.W(value.Euclidean, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Similarity2f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"scale\": case \"Scale\": result.Scale = reader.GetSingle(); break;\n                        case \"euclidean\": case \"Euclidean\": reader.R(ref result.Euclidean, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Similarity3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WriteNumber(\"Scale\", value.Scale);\n            writer.WritePropertyName(\"Euclidean\"); writer.W(value.Euclidean, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Similarity3d result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"scale\": case \"Scale\": result.Scale = reader.GetDouble(); break;\n                        case \"euclidean\": case \"Euclidean\": reader.R(ref result.Euclidean, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in Similarity3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartObject();\n            writer.WriteNumber(\"Scale\", value.Scale);\n            writer.WritePropertyName(\"Euclidean\"); writer.W(value.Euclidean, options);\n            writer.WriteEndObject();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref Similarity3f result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndObject) break;\n\n                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);\n                    var p = reader.GetString();\n                    reader.Read();\n                    switch (p)\n                    {\n                        case \"scale\": case \"Scale\": result.Scale = reader.GetSingle(); break;\n                        case \"euclidean\": case \"Euclidean\": reader.R(ref result.Euclidean, options); break;\n                        default: throw new JsonException($\"Invalid property {p}.\");\n                    }\n                }\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n\n        #region Vectors\n\n        public static void W(this Utf8JsonWriter writer, in V2d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out V2d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetDouble();\n                reader.Read(); value.Y = reader.GetDouble();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in V2f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out V2f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetSingle();\n                reader.Read(); value.Y = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in V3d value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out V3d value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetDouble();\n                reader.Read(); value.Y = reader.GetDouble();\n                reader.Read(); value.Z = reader.GetDouble();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, in V3f value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            writer.WriteNumberValue(value.X);\n            writer.WriteNumberValue(value.Y);\n            writer.WriteNumberValue(value.Z);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, out V3f value, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                reader.Read(); value.X = reader.GetSingle();\n                reader.Read(); value.Y = reader.GetSingle();\n                reader.Read(); value.Z = reader.GetSingle();\n                reader.Read(); if (reader.TokenType != JsonTokenType.EndArray) throw new JsonException();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        public static void W(this Utf8JsonWriter writer, IEnumerable<V2d> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref V2d[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<V2d>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    reader.R(out V2d x, options); xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<V2f> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref V2f[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<V2f>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    reader.R(out V2f x, options); xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<V3d> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref V3d[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<V3d>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    reader.R(out V3d x, options); xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n        public static void W(this Utf8JsonWriter writer, IEnumerable<V3f> value, JsonSerializerOptions options)\n        {\n            writer.WriteStartArray();\n            foreach (var x in value) writer.W(x, options);\n            writer.WriteEndArray();\n        }\n        public static void R(this ref Utf8JsonReader reader, ref V3f[] result, JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var xs = new List<V3f>();\n                while (reader.Read())\n                {\n                    if (reader.TokenType == JsonTokenType.EndArray) break;\n                    reader.R(out V3f x, options); xs.Add(x);\n                }\n                result = xs.ToArray();\n            }\n            else\n            {\n                throw new JsonException();\n            }\n        }\n\n        #endregion\n    }\n\n    [TestFixture]\n    class SystemTextJsonTests\n    {\n        #region Helpers\n\n        private static readonly List<JsonConverter> _converters = new()\n        {\n        };\n        private static readonly JsonSerializerOptions _options;\n        static SystemTextJsonTests()\n        {\n            _options = new()\n            {\n                AllowTrailingCommas = true,\n                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,\n                PropertyNameCaseInsensitive = true,\n                ReadCommentHandling = JsonCommentHandling.Skip,\n                //WriteIndented = true,\n                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,\n                NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals | JsonNumberHandling.AllowReadingFromString,\n                Converters =\n                {\n                    new JsonStringEnumConverter(),\n                },\n            };\n\n            _options.Converters.AddRange(_converters);\n        }\n\n        private static void SerializeTest<T>(T a, string s) where T : IEquatable<T>\n        {\n            var json = JsonSerializer.Serialize(a, _options);\n            Assert.IsTrue(json == s);\n        }\n        private static void DeserializeTest<T>(string json, T a) where T : IEquatable<T>\n        {\n            var b = JsonSerializer.Deserialize<T>(json, _options);\n            Assert.IsTrue(a.Equals(b));\n        }\n        private static void RoundtripTest<T>(T a) where T : IEquatable<T>\n        {\n            var json = JsonSerializer.Serialize(a, _options);\n            var b = JsonSerializer.Deserialize<T>(json, _options);\n            Assert.IsTrue(a.Equals(b));\n        }\n\n        #endregion\n\n        #region Affine[23][df]\n\n        [Test] public void Affine2d_Roundtrip() => RoundtripTest(new Affine2d(M22d.Identity));\n        [Test] public void Affine2f_Roundtrip() => RoundtripTest(new Affine2f(M22f.Identity));\n        [Test] public void Affine3d_Roundtrip() => RoundtripTest(new Affine3d(M33d.Identity));\n        [Test] public void Affine3f_Roundtrip() => RoundtripTest(new Affine3f(M33f.Identity));\n\n        #endregion\n\n        #region Box[23][dfil]\n\n        [Test] public void Box2i_Roundtrip()            => RoundtripTest(new Box2i(new V2i(1, -2), new V2i(-17, 0)));\n        [Test] public void Box2i_Roundtrip_Infinite()   => RoundtripTest(Box2i.Infinite);\n        [Test] public void Box2i_Roundtrip_Invalid()    => RoundtripTest(Box2i.Invalid);\n\n        [Test] public void Box2l_Roundtrip()            => RoundtripTest(new Box2l(new V2l(1, -2), new V2l(-17, 0)));\n        [Test] public void Box2l_Roundtrip_Infinite()   => RoundtripTest(Box2l.Infinite);\n        [Test] public void Box2l_Roundtrip_Invalid()    => RoundtripTest(Box2l.Invalid);\n\n        [Test] public void Box2f_Roundtrip()            => RoundtripTest(new Box2f(new V2f(1.1, -2.2), new V2f(-17.17, 0)));\n        [Test] public void Box2f_Roundtrip_Infinite()   => RoundtripTest(Box2f.Infinite);\n        [Test] public void Box2f_Roundtrip_Invalid()    => RoundtripTest(Box2f.Invalid);\n\n        [Test] public void Box2d_Roundtrip()            => RoundtripTest(new Box2d(new V2d(1.1, -2.2), new V2d(-17.17, 0)));\n        [Test] public void Box2d_Roundtrip_Infinite()   => RoundtripTest(Box2d.Infinite);\n        [Test] public void Box2d_Roundtrip_Invalid()    => RoundtripTest(Box2d.Invalid);\n\n        [Test] public void Box3i_Roundtrip()            => RoundtripTest(new Box3i(new V3i(1, -2, 0), new V3i(-17, 42, -555555555)));\n        [Test] public void Box3i_Roundtrip_Infinite()   => RoundtripTest(Box3i.Infinite);\n        [Test] public void Box3i_Roundtrip_Invalid()    => RoundtripTest(Box3i.Invalid);\n\n        [Test] public void Box3l_Roundtrip()            => RoundtripTest(new Box3l(new V3l(1, -2, 0), new V3l(-17, 42, -555555555)));\n        [Test] public void Box3l_Roundtrip_Infinite()   => RoundtripTest(Box3l.Infinite);\n        [Test] public void Box3l_Roundtrip_Invalid()    => RoundtripTest(Box3l.Invalid);\n\n        [Test] public void Box3f_Roundtrip()            => RoundtripTest(new Box3f(new V3f(1.1, -2.2, 0), new V3f(-17.17, 42.42, -555.001)));\n        [Test] public void Box3f_Roundtrip_Infinite()   => RoundtripTest(Box3f.Infinite);\n        [Test] public void Box3f_Roundtrip_Invalid()    => RoundtripTest(Box3f.Invalid);\n\n        [Test] public void Box3d_Roundtrip()            => RoundtripTest(new Box3d(new V3d(1.1, -2.2, 0), new V3d(-17.18, 42.42, -555.001)));\n        [Test] public void Box3d_Roundtrip_Infinite()   => RoundtripTest(Box3d.Infinite);\n        [Test] public void Box3d_Roundtrip_Invalid()    => RoundtripTest(Box3d.Invalid);\n\n        #endregion\n\n        #region C[34][b|d|f|ui|us], CieLabf, CieLuvf, CieXYZf, CieYxyf, CMYKf, HSLf, HSVf, Yuvf\n\n        [Test] public void C3b_Roundtrip() => RoundtripTest(new C3b(1,2,3));\n        [Test] public void C3d_Roundtrip() => RoundtripTest(new C3b(1.2, 2.3, 3.4));\n        [Test] public void C3f_Roundtrip() => RoundtripTest(new C3f(1.2, 2.3, 3.4));\n        [Test] public void C3ui_Roundtrip() => RoundtripTest(new C3ui(1, 2, 3));\n        [Test] public void C3us_Roundtrip() => RoundtripTest(new C3us(1, 2, 3));\n\n        [Test] public void C4b_Roundtrip() => RoundtripTest(new C4b(1, 2, 3, 4));\n        [Test] public void C4d_Roundtrip() => RoundtripTest(new C4b(1.2, 2.3, 3.4, 4.5));\n        [Test] public void C4f_Roundtrip() => RoundtripTest(new C4f(1.2, 2.3, 3.4, 4.5));\n        [Test] public void C4ui_Roundtrip() => RoundtripTest(new C4ui(1, 2, 3, 4));\n        [Test] public void C4us_Roundtrip() => RoundtripTest(new C4us(1, 2, 3, 4));\n\n        [Test] public void CieLabf_Roundtrip() => RoundtripTest(new CieLabf(0.1, 0.2, 0.3));\n        [Test] public void CIeLuvf_Roundtrip() => RoundtripTest(new CieLuvf(0.1, 0.2, 0.3));\n        [Test] public void CieXYZf_Roundtrip() => RoundtripTest(new CieXYZf(0.1, 0.2, 0.3));\n        [Test] public void CieYxyf_Roundtrip() => RoundtripTest(new CieYxyf(0.1, 0.2, 0.3));\n        [Test] public void CMYKf_Roundtrip() => RoundtripTest(new CMYKf(0.1, 0.2, 0.3, 0.4));\n        [Test] public void HSLf_Roundtrip() => RoundtripTest(new HSLf(0.1, 0.2, 0.3));\n        [Test] public void HSVf_Roundtrip() => RoundtripTest(new HSVf(0.1, 0.2, 0.3));\n        [Test] public void Yuvf_Roundtrip() => RoundtripTest(new Yuvf(0.1, 0.2, 0.3));\n\n        #endregion\n\n        #region Capsule3[df]\n\n        [Test] public void Capsule3d_Roundtrip() => RoundtripTest(new Capsule3d(new V3d(1, -2, 3), new V3d(-4, 5, -6), 7.14));\n        [Test] public void Capsule3f_Roundtrip() => RoundtripTest(new Capsule3f(new V3f(1, -2, 3), new V3f(-4, 5, -6), 7.14f));\n\n        #endregion\n\n        #region Cell, Cell2d\n\n        [Test]\n        public void Cell2d_Serialize()\n        {\n            SerializeTest(new Cell2d(1, 2, -1), \"[1,2,-1]\");\n            SerializeTest(new Cell2d(10), \"[10]\");\n            SerializeTest(Cell2d.Invalid, $\"[{int.MinValue}]\");\n        }\n        [Test]\n        public void Cell2d_Deserialize()\n        {\n            DeserializeTest(\"\\\"[1,2,-1]\\\"\", new Cell2d(1, 2, -1));\n            DeserializeTest(\"[1,2,-1]\", new Cell2d(1, 2, -1));\n            DeserializeTest(\"{\\\"x\\\":1,\\\"y\\\":2,\\\"e\\\":-1}\", new Cell2d(1, 2, -1));\n            DeserializeTest(\"{\\\"X\\\":1,\\\"Y\\\":2,\\\"E\\\":-1}\", new Cell2d(1, 2, -1));\n\n            DeserializeTest(\"\\\"[10]\\\"\", new Cell2d(10));\n            DeserializeTest(\"[10]\", new Cell2d(10));\n            DeserializeTest(\"{\\\"e\\\":10}\", new Cell2d(10));\n            DeserializeTest(\"{\\\"E\\\":10}\", new Cell2d(10));\n\n            DeserializeTest($\"\\\"[{int.MinValue}]\\\"\", Cell2d.Invalid);\n            DeserializeTest($\"[{int.MinValue}]\", Cell2d.Invalid);\n            DeserializeTest($\"{{\\\"e\\\":{int.MinValue}}}\", Cell2d.Invalid);\n            DeserializeTest($\"{{\\\"E\\\":{int.MinValue}}}\", Cell2d.Invalid);\n        }\n        [Test]\n        public void Cell2d_Roundtrip()\n        {\n            RoundtripTest(new Cell2d(1, 2, -1));\n            RoundtripTest(new Cell2d(10));\n            RoundtripTest(Cell2d.Invalid);\n        }\n\n        [Test]\n        public void Cell_Serialize()\n        {\n            SerializeTest(new Cell(1, 2, 3, -1), \"[1,2,3,-1]\");\n            SerializeTest(new Cell(10), \"[10]\");\n            SerializeTest(Cell.Invalid, $\"[{int.MinValue}]\");\n        }\n        [Test]\n        public void Cell_Deserialize()\n        {\n            DeserializeTest(\"\\\"[1,2,3,-1]\\\"\", new Cell(1, 2, 3, -1));\n            DeserializeTest(\"[1,2,3,-1]\", new Cell(1, 2, 3, -1));\n            DeserializeTest(\"{\\\"x\\\":1,\\\"y\\\":2,\\\"z\\\":3,\\\"e\\\":-1}\", new Cell(1, 2, 3, -1));\n            DeserializeTest(\"{\\\"X\\\":1,\\\"Y\\\":2,\\\"Z\\\":3,\\\"E\\\":-1}\", new Cell(1, 2, 3, -1));\n\n            DeserializeTest(\"\\\"[10]\\\"\", new Cell(10));\n            DeserializeTest(\"[10]\", new Cell(10));\n            DeserializeTest(\"{\\\"e\\\":10}\", new Cell(10));\n            DeserializeTest(\"{\\\"E\\\":10}\", new Cell(10));\n\n            DeserializeTest($\"\\\"[{int.MinValue}]\\\"\", Cell.Invalid);\n            DeserializeTest($\"[{int.MinValue}]\", Cell.Invalid);\n            DeserializeTest($\"{{\\\"e\\\":{int.MinValue}}}\", Cell.Invalid);\n            DeserializeTest($\"{{\\\"E\\\":{int.MinValue}}}\", Cell.Invalid);\n        }\n        [Test]\n        public void Cell_Roundtrip()\n        {\n            RoundtripTest(new Cell(1, 2, 3, -1));\n            RoundtripTest(new Cell(10));\n            RoundtripTest(Cell.Invalid);\n        }\n\n        #endregion\n\n        #region Circle[23][df]\n\n        [Test] public void Circle2d_Roundtrip() => RoundtripTest(new Circle2d(new V2d(1.2, -3.4), 5.6));\n        [Test] public void Circle2f_Roundtrip() => RoundtripTest(new Circle2f(new V2f(1.2f, -3.4f), 5.6f));\n        [Test] public void Circle3d_Roundtrip() => RoundtripTest(new Circle3d(new V3d(1.2, -3.4, 5.6), new V3d(1,2,3).Normalized, 5.6));\n        [Test] public void Circle3f_Roundtrip() => RoundtripTest(new Circle3f(new V3f(1.2, -3.4, 5.6), new V3f(1, 2, 3).Normalized, 5.6f));\n\n        #endregion\n\n        #region Cone3[df]\n\n        [Test] public void Cone3d_Roundtrip() => RoundtripTest(new Cone3d(new V3d(1, -2, 3), new V3d(-4, 5, -6), 7.14));\n        [Test] public void Cone3f_Roundtrip() => RoundtripTest(new Cone3f(new V3f(1, -2, 3), new V3f(-4, 5, -6), 7.14f));\n\n        #endregion\n\n        #region Cylinder3[df]\n\n        [Test] public void Cylinder3d_Roundtrip() => RoundtripTest(new Cylinder3d(new V3d(1, -2, 3), new V3d(-4, 5, -6), 7.14));\n        [Test] public void Cylinder3f_Roundtrip() => RoundtripTest(new Cylinder3f(new V3f(1, -2, 3), new V3f(-4, 5, -6), 7.14f));\n\n        #endregion\n\n        #region Ellipse[23][df]\n\n        //[Test] public void Ellipse3d_Roundtrip() => RoundtripTest(new Ellipse3d(new V3d(1.2, -2.3, 3.4), new V3d(-4.5, 5.6, -6.7), new V3d(7.8, -8.9, 9.10), new V3d(-10.11, 11.12, -12.13)));\n        //[Test] public void Ellipse3f_Roundtrip() => RoundtripTest(new Ellipse3f(new V3f(1.2, -2.3, 3.4), new V3f(-4.5, 5.6, -6.7), new V3f(7.8, -8.9, 9.10), new V3f(-10.11, 11.12, -12.13)));\n\n        #endregion\n\n        #region Euclidean[23][df]\n\n        [Test] public void Euclidean2d_Roundtrip() => RoundtripTest(new Euclidean2d(Rot2d.FromDegrees(42.17)));\n        [Test] public void Euclidean2f_Roundtrip() => RoundtripTest(new Euclidean2f(Rot2f.FromDegrees(42.17f)));\n        [Test] public void Euclidean3d_Roundtrip() => RoundtripTest(new Euclidean3d(Rot3d.FromAngleAxis(new V3d(1.2, -2.3, 3.4))));\n        [Test] public void Euclidean3f_Roundtrip() => RoundtripTest(new Euclidean3f(Rot3f.FromAngleAxis(new V3f(1.2, -2.3, 3.4))));\n\n        #endregion\n\n        #region Fraction\n\n        //[Test] public void Fraction_Roundtrip() => RoundtripTest(new Fraction(-123, 456789));\n\n        #endregion\n\n        #region Hull[23][df]\n\n        [Test] public void Hull2d_Roundtrip() => RoundtripTest(new Hull2d(Box2d.Unit));\n        [Test] public void Hull2f_Roundtrip() => RoundtripTest(new Hull2f(Box2f.Unit));\n\n        [Test] public void Hull3d_Roundtrip() => RoundtripTest(new Hull3d(Box3d.Unit));\n        [Test] public void Hull3f_Roundtrip() => RoundtripTest(new Hull3f(Box3f.Unit));\n\n        #endregion\n\n        #region Line[23][df]\n\n        [Test] public void Line2d_Roundtrip() => RoundtripTest(new Line2d(new V2d(1.2, -2.3), new V2d(-4.5, 5.6)));\n        [Test] public void Line2f_Roundtrip() => RoundtripTest(new Line2f(new V2f(1.2, -2.3), new V2f(-4.5, 5.6)));\n        [Test] public void Line3d_Roundtrip() => RoundtripTest(new Line3d(new V3d(1.2, -2.3, 3.4), new V3d(-4.5, 5.6, -6.7)));\n        [Test] public void Line3f_Roundtrip() => RoundtripTest(new Line3f(new V3f(1.2, -2.3, 3.4), new V3f(-4.5, 5.6, -6.7)));\n\n        #endregion\n\n        #region M[22|23|33|34|44][dfil]\n\n        [Test] public void M22d_Roundtrip() => RoundtripTest(new M22d(1.2, -2.3, 3.4, -4.5));\n        [Test] public void M22f_Roundtrip() => RoundtripTest(new M22f(1.2f, -2.3f, 3.4f, -4.5f));\n        [Test] public void M22i_Roundtrip() => RoundtripTest(new M22i(1, -2, 3, -4));\n        [Test] public void M22l_Roundtrip() => RoundtripTest(new M22l(1, -2, 3, -4));\n\n        [Test] public void M23d_Roundtrip() => RoundtripTest(new M23d(1.2, -2.3, 3.4, -4.5, 5.6, -6.7));\n        [Test] public void M23f_Roundtrip() => RoundtripTest(new M23f(1.2f, -2.3f, 3.4f, -4.5f, 5.6f, -6.7f));\n        [Test] public void M23i_Roundtrip() => RoundtripTest(new M23i(1, -2, 3, -4, 5, -6));\n        [Test] public void M23l_Roundtrip() => RoundtripTest(new M23l(1, -2, 3, -4, 6, -6));\n\n        [Test] public void M33d_Roundtrip() => RoundtripTest(new M33d(1.2, -2.3, 3.4, -4.5, 5.6, -6.7, 7.8, -8.9, 9.10));\n        [Test] public void M33f_Roundtrip() => RoundtripTest(new M33f(1.2f, -2.3f, 3.4f, -4.5f, 5.6f, -6.7f, 7.8f, -8.9f, 9.10f));\n        [Test] public void M33i_Roundtrip() => RoundtripTest(new M33i(1, -2, 3, -4, 5, -6, 7, -8, 9));\n        [Test] public void M33l_Roundtrip() => RoundtripTest(new M33l(1, -2, 3, -4, 6, -6, 7, -8, 9));\n\n        [Test] public void M34d_Roundtrip() => RoundtripTest(new M34d(1.2, -2.3, 3.4, -4.5, 5.6, -6.7, 7.8, -8.9, 9.10, -10.11, 11.12, -12.13));\n        [Test] public void M34f_Roundtrip() => RoundtripTest(new M34f(1.2f, -2.3f, 3.4f, -4.5f, 5.6f, -6.7f, 7.8f, -8.9f, 9.10f, -10.11f, 11.12f, -12.13f));\n        [Test] public void M34i_Roundtrip() => RoundtripTest(new M34i(1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12));\n        [Test] public void M34l_Roundtrip() => RoundtripTest(new M34l(1, -2, 3, -4, 6, -6, 7, -8, 9, -10, 11, -12));\n\n        [Test] public void M44d_Roundtrip() => RoundtripTest(new M44d(1.2, -2.3, 3.4, -4.5, 5.6, -6.7, 7.8, -8.9, 9.10, -10.11, 11.12, -12.13, 13.14, -14.15, 15.16, -16.17));\n        [Test] public void M44f_Roundtrip() => RoundtripTest(new M44f(1.2f, -2.3f, 3.4f, -4.5f, 5.6f, -6.7f, 7.8f, -8.9f, 9.10f, -10.11f, 11.12f, -12.13f, 13.14f, -14.15f, 15.16f, -16.17f));\n        [Test] public void M44i_Roundtrip() => RoundtripTest(new M44i(1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16));\n        [Test] public void M44l_Roundtrip() => RoundtripTest(new M44l(1, -2, 3, -4, 6, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16));\n\n        #endregion\n\n        #region OrientedBox[23][df]\n\n        //[Test] public void OrientedBox2d_Roundtrip() => RoundtripTest(new OrientedBox2d(Box2d.Unit));\n        //[Test] public void OrientedBox2f_Roundtrip() => RoundtripTest(new OrientedBox2f(Box2f.Unit));\n        //[Test] public void OrientedBox3d_Roundtrip() => RoundtripTest(new OrientedBox3d(Box3d.Unit));\n        //[Test] public void OrientedBox3f_Roundtrip() => RoundtripTest(new OrientedBox3f(Box3f.Unit));\n\n        #endregion\n\n        #region Plane[23][df]\n\n        [Test] public void Plane2d_Roundtrip() => RoundtripTest(new Plane2d(new V2d(1.2, -3.4).Normalized, new V2d(-5.6, 7.8)));\n        [Test] public void Plane2f_Roundtrip() => RoundtripTest(new Plane2f(new V2f(1.2, -3.4).Normalized, new V2f(-5.6, 7.8)));\n        [Test] public void Plane3d_Roundtrip() => RoundtripTest(new Plane3d(new V3d(1.2, -3.4, 5.6).Normalized, new V3d(-7.8, 9.10, -11.12)));\n        [Test] public void Plane3f_Roundtrip() => RoundtripTest(new Plane3f(new V3f(1.2, -3.4, 5.6).Normalized, new V3f(-7.8, 9.10, -11.12)));\n\n        #endregion\n\n        #region Polygon[23][df]\n\n        [Test] public void Polygon2d_Roundtrip() => RoundtripTest(new Polygon2d(new[] { new V2d(1.2, -2.3), new V2d(3.4, -4.5), new V2d(-5.6, 6.7) }));\n        [Test] public void Polygon2f_Roundtrip() => RoundtripTest(new Polygon2f(new[] { new V2f(1.2, -2.3), new V2f(3.4, -4.5), new V2f(-5.6, 6.7) }));\n        [Test] public void Polygon3d_Roundtrip() => RoundtripTest(new Polygon3d(new[] { new V3d(1.2, -2.3, 0.1), new V3d(3.4, -4.5, -0.2), new V3d(-5.6, 6.7, -0.3) }));\n        [Test] public void Polygon3f_Roundtrip() => RoundtripTest(new Polygon3f(new[] { new V3f(1.2, -2.3, 0.1), new V3f(3.4, -4.5, -0.2), new V3f(-5.6, 6.7, -0.3) }));\n\n        #endregion\n\n        #region Quad[23][df]\n\n        [Test] public void Quad2d_Roundtrip() => RoundtripTest(new Quad2d(new V2d(1.2, -2.3), new V2d(3.4, -4.5), new V2d(5.6, 6.7), new V2d(-7.8, 8.9)));\n        [Test] public void Quad2f_Roundtrip() => RoundtripTest(new Quad2f(new V2f(1.2, -2.3), new V2f(3.4, -4.5), new V2f(5.6, 6.7), new V2f(-7.8, 8.9)));\n        [Test] public void Quad3d_Roundtrip() => RoundtripTest(new Quad3d(new V3d(1.2, -2.3, 0.1), new V3d(3.4, -4.5, 0.1), new V3d(5.6, 6.7, 0.1), new V3d(-7.8, 8.9, 0.1)));\n        [Test] public void Quad3f_Roundtrip() => RoundtripTest(new Quad3f(new V3f(1.2, -2.3, 0.1), new V3f(3.4, -4.5, 0.1), new V3f(5.6, 6.7, 0.1), new V3f(-7.8, 8.9, 0.1)));\n\n        #endregion\n\n        #region Quaternion[DF]\n\n        [Test] public void QuaternionD_Roundtrip() => RoundtripTest(new QuaternionD(1.2, -2.3, 3.4, 1.0));\n        [Test] public void QuaternionF_Roundtrip() => RoundtripTest(new QuaternionF(1.2f, -2.3f, 3.4f, 1.0f));\n\n        #endregion\n\n        #region Range1*\n\n        [Test] public void Range1b_Roundtrip() => RoundtripTest(new Range1b(7, 42));\n        [Test] public void Range1d_Roundtrip() => RoundtripTest(new Range1d(-7.1, 42.2));\n        [Test] public void Range1f_Roundtrip() => RoundtripTest(new Range1f(-7.1f, 42.2f));\n        [Test] public void Range1i_Roundtrip() => RoundtripTest(new Range1i(-7, 42));\n        [Test] public void Range1l_Roundtrip() => RoundtripTest(new Range1l(-7, 42));\n        [Test] public void Range1s_Roundtrip() => RoundtripTest(new Range1s(-7, 42));\n        [Test] public void Range1sb_Roundtrip() => RoundtripTest(new Range1sb(-7, 42));\n        [Test] public void Range1ui_Roundtrip() => RoundtripTest(new Range1ui(7, 42));\n        [Test] public void Range1ul_Roundtrip() => RoundtripTest(new Range1ul(7, 42));\n        [Test] public void Range1us_Roundtrip() => RoundtripTest(new Range1us(7, 42));\n\n        #endregion\n\n        #region Ray[23][df], FastRay[23][df]\n\n        [Test] public void Ray2d_Roundtrip() => RoundtripTest(new Ray2d(new V2d(-1.2, 2.3), new V2d(3.4, -4.5).Normalized));\n        [Test] public void Ray2f_Roundtrip() => RoundtripTest(new Ray2f(new V2f(-1.2, 2.3), new V2f(3.4, -4.5).Normalized));\n        [Test] public void Ray3d_Roundtrip() => RoundtripTest(new Ray3d(new V3d(-1.2, 2.3, -3.4), new V3d(3.4, -4.5, 5.6).Normalized));\n        [Test] public void Ray3f_Roundtrip() => RoundtripTest(new Ray3f(new V3f(-1.2, 2.3, -3.4), new V3f(3.4, -4.5, 5.6).Normalized));\n\n        #endregion\n\n        #region Rot[23][df]\n\n        [Test] public void Rot2d_Roundtrip() => RoundtripTest(Rot2d.FromDegrees(123.456));\n        [Test] public void Rot2f_Roundtrip() => RoundtripTest(Rot2f.FromDegrees(123.456f));\n        [Test] public void Rot3d_Roundtrip() => RoundtripTest(Rot3d.FromAngleAxis(new V3d(1.2, -2.3, 3.4)));\n        [Test] public void Rot3f_Roundtrip() => RoundtripTest(Rot3f.FromAngleAxis(new V3f(1.2, -2.3, 3.4)));\n\n        #endregion\n\n        #region Scale[23][df]\n\n        [Test] public void Scale2d_Roundtrip() => RoundtripTest(new Scale2d(1.2, 2.3));\n        [Test] public void Scale2f_Roundtrip() => RoundtripTest(new Scale2f(1.2f, 2.3f));\n        [Test] public void Scale3d_Roundtrip() => RoundtripTest(new Scale3d(1.2, 2.3, 3.4));\n        [Test] public void Scale3f_Roundtrip() => RoundtripTest(new Scale3f(1.2f, 2.3f, 3.4f));\n\n        #endregion\n\n        #region Shift[23][df]\n\n        [Test] public void Shift2d_Roundtrip() => RoundtripTest(new Shift2d(1.2, 2.3));\n        [Test] public void Shift2f_Roundtrip() => RoundtripTest(new Shift2f(1.2f, 2.3f));\n        [Test] public void Shift3d_Roundtrip() => RoundtripTest(new Shift3d(1.2, 2.3, 3.4));\n        [Test] public void Shift3f_Roundtrip() => RoundtripTest(new Shift3f(1.2f, 2.3f, 3.4f));\n\n        #endregion\n\n        #region Similarity[23][df]\n\n        [Test] public void Similarity2d_Roundtrip() => RoundtripTest(new Similarity2d(Rot2d.FromDegrees(123.456), 1.2, 2.3));\n        [Test] public void Similarity2f_Roundtrip() => RoundtripTest(new Similarity2f(Rot2f.FromDegrees(123.456f), 1.2f, 2.3f));\n        [Test] public void Similarity3d_Roundtrip() => RoundtripTest(new Similarity3d(Rot3d.FromAngleAxis(new V3d(1.2, -2.3, 3.4)), 2.3, 3.4, 4.5));\n        [Test] public void Similarity3f_Roundtrip() => RoundtripTest(new Similarity3f(Rot3f.FromAngleAxis(new V3f(1.2, -2.3, 3.4)), 2.3f, 3.4f, 4.5f));\n\n        #endregion\n\n        #region Spectrum\n\n        //[Test] public void Spectrum_Roundtrip() => RoundtripTest(new Spectrum(300.5, 800.7, new[] { 1.2, 3.4,5.6, 7.8, 9.10 } ));\n\n        #endregion\n\n        #region Sphere3[df]\n\n        [Test] public void Sphere3d_Roundtrip() => RoundtripTest(new Sphere3d(new V3d(1.2, -2.3, 3.4), 4.5));\n        [Test] public void Sphere3f_Roundtrip() => RoundtripTest(new Sphere3f(new V3f(1.2, -2.3, 3.4), 4.5f));\n\n        #endregion\n\n        #region Torus3[df]\n\n        [Test] public void Torus3d_Roundtrip() => RoundtripTest(new Torus3d(new V3d(1.2, -2.3, 3.4), new V3d(1.2, -2.3, 3.4).Normalized, 5.6, 4.5));\n        [Test] public void Torus3f_Roundtrip() => RoundtripTest(new Torus3f(new V3f(1.2, -2.3, 3.4), new V3f(1.2, -2.3, 3.4).Normalized, 5.6f, 4.5f));\n\n        #endregion\n\n        #region Trafo[23][df]\n\n        [Test] public void Trafo2d_Roundtrip() => RoundtripTest(new Trafo2d(Rot2d.FromDegrees(123.456)));\n        [Test] public void Trafo2f_Roundtrip() => RoundtripTest(new Trafo2f(Rot2f.FromDegrees(123.456f)));\n        [Test] public void Trafo3d_Roundtrip() => RoundtripTest(new Trafo3d(Rot3d.FromAngleAxis(new V3d(1.2, -2.3, 3.4))));\n        [Test] public void Trafo3f_Roundtrip() => RoundtripTest(new Trafo3f(Rot3f.FromAngleAxis(new V3f(1.2, -2.3, 3.4))));\n\n        #endregion\n\n        #region Triangle[23][df]\n\n        [Test] public void Triangle2d_Roundtrip() => RoundtripTest(new Triangle2d(new V2d(1.2, -2.3), new V2d(3.4, -4.5), new V2d(5.6, 6.7)));\n        [Test] public void Triangle2f_Roundtrip() => RoundtripTest(new Triangle2f(new V2f(1.2, -2.3), new V2f(3.4, -4.5), new V2f(5.6, 6.7)));\n        [Test] public void Triangle3d_Roundtrip() => RoundtripTest(new Triangle3d(new V3d(1.2, -2.3, 0.1), new V3d(3.4, -4.5, 0.1), new V3d(5.6, 6.7, 0.1)));\n        [Test] public void Triangle3f_Roundtrip() => RoundtripTest(new Triangle3f(new V3f(1.2, -2.3, 0.1), new V3f(3.4, -4.5, 0.1), new V3f(5.6, 6.7, 0.1)));\n\n        #endregion\n\n        #region V[234][dfil]\n\n        [Test] public void V2f_Roundtrip()                  => RoundtripTest(new V2f(1.1, -2.2));\n        [Test] public void V2f_Roundtrip_MinValue()         => RoundtripTest(V2f.MinValue);\n        [Test] public void V2f_Roundtrip_MaxValue()         => RoundtripTest(V2f.MaxValue);\n        [Test] public void V2f_Roundtrip_NegativeInfinity() => RoundtripTest(V2f.NegativeInfinity);\n        [Test] public void V2f_Roundtrip_PositiveInfinity() => RoundtripTest(V2f.PositiveInfinity);\n        [Test] public void V2f_Roundtrip_NaN()              => RoundtripTest(V2f.NaN);\n\n        [Test] public void V2d_Roundtrip()                  => RoundtripTest(new V2d(1.1, -2.2));\n        [Test] public void V2d_Roundtrip_MinValue()         => RoundtripTest(V2d.MinValue);\n        [Test] public void V2d_Roundtrip_MaxValue()         => RoundtripTest(V2d.MaxValue);\n        [Test] public void V2d_Roundtrip_NegativeInfinity() => RoundtripTest(V2d.NegativeInfinity);\n        [Test] public void V2d_Roundtrip_PositiveInfinity() => RoundtripTest(V2d.PositiveInfinity);\n        [Test] public void V2d_Roundtrip_NaN()              => RoundtripTest(V2d.NaN);\n\n        [Test] public void V2i_Roundtrip()                  => RoundtripTest(new V2i(1, -2));\n        [Test] public void V2i_Roundtrip_MinValue()         => RoundtripTest(V2i.MinValue);\n        [Test] public void V2i_Roundtrip_MaxValue()         => RoundtripTest(V2i.MaxValue);\n\n        [Test] public void V2l_Roundtrip()                  => RoundtripTest(new V2l(1, -2));\n        [Test] public void V2l_Roundtrip_MinValue()         => RoundtripTest(V2l.MinValue);\n        [Test] public void V2l_Roundtrip_MaxValue()         => RoundtripTest(V2l.MaxValue);\n\n\n\n        [Test] public void V3f_Roundtrip()                  => RoundtripTest(new V3f(1.1, 0, -2.2));\n        [Test] public void V3f_Roundtrip_MinValue()         => RoundtripTest(V3f.MinValue);\n        [Test] public void V3f_Roundtrip_MaxValue()         => RoundtripTest(V3f.MaxValue);\n        [Test] public void V3f_Roundtrip_NegativeInfinity() => RoundtripTest(V3f.NegativeInfinity);\n        [Test] public void V3f_Roundtrip_PositiveInfinity() => RoundtripTest(V3f.PositiveInfinity);\n        [Test] public void V3f_Roundtrip_NaN()              => RoundtripTest(V3f.NaN);\n\n        [Test] public void V3d_Roundtrip()                  => RoundtripTest(new V3d(1.1, 0, -2.2));\n        [Test] public void V3d_Roundtrip_MinValue()         => RoundtripTest(V3d.MinValue);\n        [Test] public void V3d_Roundtrip_MaxValue()         => RoundtripTest(V3d.MaxValue);\n        [Test] public void V3d_Roundtrip_NegativeInfinity() => RoundtripTest(V3d.NegativeInfinity);\n        [Test] public void V3d_Roundtrip_PositiveInfinity() => RoundtripTest(V3d.PositiveInfinity);\n        [Test] public void V3d_Roundtrip_NaN()              => RoundtripTest(V3d.NaN);\n\n        [Test] public void V3i_Roundtrip()                  => RoundtripTest(new V3i(1, 0, -2));\n        [Test] public void V3i_Roundtrip_MinValue()         => RoundtripTest(V3i.MinValue);\n        [Test] public void V3i_Roundtrip_MaxValue()         => RoundtripTest(V3i.MaxValue);\n\n        [Test] public void V3l_Roundtrip()                  => RoundtripTest(new V3l(1, 0, -2));\n        [Test] public void V3l_Roundtrip_MinValue()         => RoundtripTest(V3l.MinValue);\n        [Test] public void V3l_Roundtrip_MaxValue()         => RoundtripTest(V3l.MaxValue);\n\n\n\n        [Test] public void V4f_Roundtrip()                  => RoundtripTest(new V4f(1.1, 0, -2.2, 3.3));\n        [Test] public void V4f_Roundtrip_MinValue()         => RoundtripTest(V4f.MinValue);\n        [Test] public void V4f_Roundtrip_MaxValue()         => RoundtripTest(V4f.MaxValue);\n        [Test] public void V4f_Roundtrip_NegativeInfinity() => RoundtripTest(V4f.NegativeInfinity);\n        [Test] public void V4f_Roundtrip_PositiveInfinity() => RoundtripTest(V4f.PositiveInfinity);\n        [Test] public void V4f_Roundtrip_NaN()              => RoundtripTest(V4f.NaN);\n\n        [Test] public void V4d_Roundtrip()                  => RoundtripTest(new V4d(1.1, 0, -2.2, 3.3));\n        [Test] public void V4d_Roundtrip_MinValue()         => RoundtripTest(V4d.MinValue);\n        [Test] public void V4d_Roundtrip_MaxValue()         => RoundtripTest(V4d.MaxValue);\n        [Test] public void V4d_Roundtrip_NegativeInfinity() => RoundtripTest(V4d.NegativeInfinity);\n        [Test] public void V4d_Roundtrip_PositiveInfinity() => RoundtripTest(V4d.PositiveInfinity);\n        [Test] public void V4d_Roundtrip_NaN()              => RoundtripTest(V4d.NaN);\n\n        [Test] public void V4i_Roundtrip()                  => RoundtripTest(new V4i(1, 0, -2, 3));\n        [Test] public void V4i_Roundtrip_MinValue()         => RoundtripTest(V4i.MinValue);\n        [Test] public void V4i_Roundtrip_MaxValue()         => RoundtripTest(V4i.MaxValue);\n\n        [Test] public void V4l_Roundtrip()                  => RoundtripTest(new V4l(1, 0, -2, 3));\n        [Test] public void V4l_Roundtrip_MinValue()         => RoundtripTest(V4l.MinValue);\n        [Test] public void V4l_Roundtrip_MaxValue()         => RoundtripTest(V4l.MaxValue);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Math/AliasTable.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class AliasTable : TestSuite\n    {\n        static void PrintHistogram(double[] pdf, int[] hist)\n        {\n            var colWidth = 8;\n            var row0 = new StringBuilder();\n            var row1 = new StringBuilder();\n            var row2 = new StringBuilder();\n            var pdfSum = pdf.Sum();\n            var histSum = hist.Sum();\n            for (int i = 0; i < pdf.Length; i++)\n            {\n                row0.Append(pdf[i].ToString(\"0.000\").PadLeft(colWidth));\n                row1.Append(hist[i].ToString().PadLeft(colWidth));\n                var target = pdf[i] / pdfSum;\n                var real = hist[i] / (double)histSum;\n                var ratio = real / target;\n                row2.Append(ratio.ToString(\"0.000\").PadLeft(colWidth));\n                if (i < pdf.Length - 1)\n                {\n                    row0.Append(\" | \");\n                    row1.Append(\" | \");\n                    row2.Append(\" | \");\n                }\n            }\n\n            Report.Line(row0.ToString());\n            Report.Line(row1.ToString());\n            Report.Line(new String('-', pdf.Length * (colWidth + 3) - 3));\n            Report.Line(row2.ToString());\n        }\n\n        static void EvaluateHistogram(double[] pdf, int[] hist)\n        {\n            var pdfSum = pdf.Sum();\n            var histSum = hist.Sum();\n            var rmin = double.MaxValue;\n            var rmax = 0.0;\n            var ravg = 0.0;\n            for (int i = 0; i < pdf.Length; i++)\n            {\n                var target = pdf[i] / pdfSum;\n                var real = hist[i] / (double)histSum;\n                var ratio = real / target;\n                ravg += ratio;\n                if (ratio < rmin) rmin = ratio;\n                if (ratio > rmax) rmax = ratio;\n            }\n            Report.Line(\"Min: {0:0.000} Max: {1:0.000} Avg: {2:0.000}\", rmin, rmax, ravg / pdf.Length);\n\n            Assert.IsTrue(rmin.ApproximateEquals(1, 0.05));\n            Assert.IsTrue(rmax.ApproximateEquals(1, 0.05));\n        }\n\n        [Test]\n        public void SampleTest()\n        {\n            int sampleCount = 100000000;\n            var pdfLength = 1000;\n\n            var rnd = new RandomSystem(0);\n            //var pdf = new[] { 0.1, 0.2, 0.5, 0.012, 0.99, 1.4, 0.33 };\n            var pdf = new double[pdfLength].SetByIndex(_ => (0.1 + rnd.UniformDouble() * 0.9).Square());\n            Report.BeginTimed(\"Generate CDF\");\n            var df = new DistributionFunction(pdf);\n            Report.End();\n\n            Report.BeginTimed(\"CDF sampling with binary search:\");\n            var bin = new int[pdf.Length];\n            for (int i = 0; i < sampleCount; i++)\n            {\n                var s = df.Sample(rnd);\n                bin[s]++;\n            }\n            Report.End();\n\n            Report.Line();\n            PrintHistogram(pdf, bin);\n            EvaluateHistogram(pdf, bin);\n            Report.Line();\n            Report.Line();\n            Report.Line();\n\n            Report.BeginTimed(\"Generate alias table:\");\n            var at = new AliasTableD(pdf, 1 / pdf.Sum());\n            Report.End();\n\n            bin.Set(0);\n            Report.BeginTimed(\"Alias table sampling:\");\n            for (int i = 0; i < sampleCount; i++)\n            {\n                var s = at.Sample(rnd.UniformDouble());\n                bin[s]++;\n            }\n            Report.End();\n\n            Report.Line();\n            PrintHistogram(pdf, bin);\n            EvaluateHistogram(pdf, bin);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Math/ColorTests.cs",
    "content": "﻿using System.Linq;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class ColorTests : TestSuite\n    {\n        public ColorTests() : base() { }\n        public ColorTests(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public void TestColor()\n        {\n            ConversionTests();\n        }\n\n        public void ConversionTests()\n        {\n            using (Report.JobTimed(\"color conversion tests\"))\n            {\n                Report.BeginTimed(\"create color arrays\");\n                var c3bVol = new Volume<C3b>(17, 17, 17).SetByCoord((r, g, b) => new C3b(15 * r, 15 * g, 15 * b));\n                var c3bArray = c3bVol.Data;\n                var c3fArray = c3bArray.Map(C3f.FromC3b);\n                var cieXYZArray = c3fArray.Map(c => c.SRGBToCieXYZf());\n                Report.End();\n\n                var count = c3bArray.Length;\n\n                Test.Begin(\"CieXYZ tests\");\n                for (int i = 0; i < count; i++)\n                {\n                    var ciexyz = cieXYZArray[i];\n                    var c3b = ciexyz.ToSRGB().ToC3b();\n                    var original = c3bArray[i];\n                    Test.IsFalse(c3b.AnyDifferent(original), \"{0} != {1}\", c3b, original);\n                }\n                Test.End();\n\n                Test.Begin(\"CieYxy tests\");\n                for (int i = 0; i < count; i++)\n                {\n                    var cieyxy = cieXYZArray[i].ToCieYxyf();\n                    var c3b = cieyxy.ToCieXYZf().ToSRGB().ToC3b();\n                    var original = c3bArray[i];\n                    Test.IsFalse(c3b.AnyDifferent(original), \"{0} != {1}\", c3b, original);\n                }\n                Test.End();\n\n                Test.Begin(\"HSV tests\");\n                for (int i = 0; i < count; i++)\n                {\n                    var hsvf = c3fArray[i].ToHSVf();\n                    var c3b = hsvf.ToC3f().ToC3b();\n                    var original = c3bArray[i];\n                    Test.IsFalse(c3b.AnyDifferent(original), \"{0} != {1}\", c3b, original);\n                }\n                Test.End();\n\n                Test.Begin(\"HSL tests\");\n                for (int i = 0; i < count; i++)\n                {\n                    var hslf = c3fArray[i].ToHSLf();\n                    var c3b = hslf.ToC3f().ToC3b();\n                    var original = c3bArray[i];\n                    Test.IsFalse(c3b.AnyDifferent(original), \"{0} != {1}\", c3b, original);\n                }\n                Test.End();\n\n            }\n        }\n\n        [Test]\n        public void IndexerC4b()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 32; i++)\n            {\n                var color = new C4b(rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt());\n\n                Assert.AreEqual(color.R, color[0]);\n                Assert.AreEqual(color.G, color[1]);\n                Assert.AreEqual(color.B, color[2]);\n                Assert.AreEqual(color.A, color[3]);\n            }\n        }\n\n        [Test]\n        public void IndexerC4us()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 32; i++)\n            {\n                var color = new C4us(rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt(), rnd.UniformInt());\n\n                Assert.AreEqual(color.R, color[0]);\n                Assert.AreEqual(color.G, color[1]);\n                Assert.AreEqual(color.B, color[2]);\n                Assert.AreEqual(color.A, color[3]);\n            }\n        }\n\n        [Test]\n        public void IndexerC4ui()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 32; i++)\n            {\n                var color = rnd.UniformC4ui();\n\n                Assert.AreEqual(color.R, color[0]);\n                Assert.AreEqual(color.G, color[1]);\n                Assert.AreEqual(color.B, color[2]);\n                Assert.AreEqual(color.A, color[3]);\n            }\n        }\n\n        [Test]\n        public void IndexerC4f()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 32; i++)\n            {\n                var color = rnd.UniformC4f();\n\n                Assert.AreEqual(color.R, color[0]);\n                Assert.AreEqual(color.G, color[1]);\n                Assert.AreEqual(color.B, color[2]);\n                Assert.AreEqual(color.A, color[3]);\n            }\n        }\n\n        [Test]\n        public void IndexerC4d()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 32; i++)\n            {\n                var color = rnd.UniformC4d();\n\n                Assert.AreEqual(color.R, color[0]);\n                Assert.AreEqual(color.G, color[1]);\n                Assert.AreEqual(color.B, color[2]);\n                Assert.AreEqual(color.A, color[3]);\n            }\n        }\n\n        [Test]\n        public void Parse()\n        {\n            var rnd = new RandomSystem(0);\n\n            for (int i = 0; i < 100; i++)\n            {\n                var c = rnd.UniformC4ui();\n                var s1 = $\"[{c.R}, {c.G}, {c.B}, {c.A}]\";\n                var s2 = $\"[{c.R}, {c.G}, {c.B}]\";\n\n                Assert.AreEqual(c.RGB, C3ui.Parse(s1));\n                Assert.AreEqual(c, C4ui.Parse(s1));\n                Assert.AreEqual(c.RGB, C3ui.Parse(s2));\n                Assert.AreEqual(new C4ui(c.RGB, uint.MaxValue), C4ui.Parse(s2));\n            }\n        }\n\n        [Test]\n        public void ParseTooManyComponents()\n        {\n            var t1 = new Text(\"[1,2,3\");\n            var c1 = t1.NestedBracketSplitCount2(1);\n            var r1 = t1.NestedBracketSplit(1).ToArray();\n\n            var t2 = new Text(\"[42]\");\n            var c2 = t2.NestedBracketSplitCount2(1);\n            var r2 = t2.NestedBracketSplit(1).ToArray();\n\n            var t3 = new Text(\"[42,43]\");\n            var c3 = t3.NestedBracketSplitCount2(1);\n            var r3 = t3.NestedBracketSplit(1).ToArray();\n\n            Assert.AreEqual(r1.Length, c1);\n            Assert.AreEqual(r2.Length, c2);\n            Assert.AreEqual(r3.Length, c3);\n\n            Assert.IsFalse(C4d.TryParse(\"[1, 2, 3, 4, 5]\", out C4d _));\n        }\n\n        [Test]\n        public void ParseHex()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 100; i++)\n            {\n                var color = rnd.UniformC4d().ToC4b();\n                var str = color.ToHexString();\n\n                Assert.IsTrue(Col.TryParseHex(str, out C4b result));\n                Assert.IsTrue(C4b.TryParse(str, out C4b result2));\n                Assert.AreEqual(color, result);\n                Assert.AreEqual(result, result2);\n            }\n        }\n\n        [Test]\n        public void ParseHexSingleDigit()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 100; i++)\n            {\n                var str = rnd.UniformC4d().ToHexString();\n                var dbl = $\"#{str[0]}{str[0]}{str[2]}{str[2]}{str[4]}{str[4]}\";\n                var sgl = $\"0x{str[0]}{str[2]}{str[4]}F\";\n\n                Assert.IsTrue(Col.TryParseHex(dbl, out C4b a));\n                Assert.IsTrue(C4b.TryParse(sgl, out C4b b));\n                Assert.AreEqual(a, b);\n            }\n        }\n\n        [Test]\n        [SetCulture(\"de-DE\")]\n        public void ParseWithBadCulture()\n        {\n            var rnd = new RandomSystem(1);\n            var col = rnd.UniformC4d();\n            var str = col.ToString();\n            var res = C4d.Parse(str);\n\n            Assert.True(Fun.ApproximateEquals(col, res));\n        }\n\n        [Test]\n        public void C4fArithmetic()\n        {\n            var rnd = new RandomSystem(1);\n            var c0 = rnd.UniformC4f();\n            var c1 = rnd.UniformC4f();\n\n            Assert.AreEqual( c0.ToV4f() * c1.ToV4f(), (c0   * c1).ToV4f()   );\n            Assert.AreEqual( c0.ToV4f() * c1.R,       (c0   * c1.R).ToV4f() );\n            Assert.AreEqual( c0.R       * c1.ToV4f(), (c0.R * c1).ToV4f()   );\n\n            Assert.AreEqual( c0.ToV4f() / c1.ToV4f(), (c0   / c1).ToV4f()   );\n            Assert.AreEqual( c0.ToV4f() / c1.R,       (c0   / c1.R).ToV4f() );\n            Assert.AreEqual( c0.R       / c1.ToV4f(), (c0.R / c1).ToV4f()   );\n\n            Assert.AreEqual( c0.ToV4f() + c1.ToV4f(), (c0   + c1).ToV4f()   );\n            Assert.AreEqual( c0.ToV4f() + c1.R,       (c0   + c1.R).ToV4f() );\n            Assert.AreEqual( c0.R       + c1.ToV4f(), (c0.R + c1).ToV4f()   );\n\n            Assert.AreEqual( c0.ToV4f() - c1.ToV4f(), (c0   - c1).ToV4f()   );\n            Assert.AreEqual( c0.ToV4f() - c1.R,       (c0   - c1.R).ToV4f() );\n            Assert.AreEqual( c0.R       - c1.ToV4f(), (c0.R - c1).ToV4f()   );\n        }\n\n        [Test]\n        public void C4bArithmetic()\n        {\n            var c0 = new C4b(199, 203, 151, 130);\n            var c1 = new C4b(35, 11, 66, 47);\n\n            Assert.AreEqual( c0.ToV4i() + c1.ToV4i(),      (c0   + c1).ToV4i()   );\n            Assert.AreEqual( c0.ToV4i() + c1.R,            (c0   + c1.R).ToV4i() );\n            Assert.AreEqual( c1.R       + c0.ToV4i(),      (c1.R + c0).ToV4i()   );\n\n            Assert.AreEqual( C3b.White.ToV4i(),            (c0   + c0).ToV4i()   );\n            Assert.AreEqual( C3b.White.ToV4i(),            (c0   + c0.R).ToV4i() );\n            Assert.AreEqual( C3b.White.ToV4i(),            (c0.R + c0).ToV4i()   );\n\n            Assert.AreEqual( c0.ToV4i() - c1.ToV4i(),      (c0   - c1).ToV4i()   );\n            Assert.AreEqual( c0.ToV4i() - c1.R,            (c0   - c1.R).ToV4i() );\n            Assert.AreEqual( c0.R       - c1.ToV4i(),      (c0.R - c1).ToV4i()   );\n\n            Assert.AreEqual( V4i.Zero,                     (c1   - c0).ToV4i()   );\n            Assert.AreEqual( V4i.Zero,                     (c1   - c0.R).ToV4i() );\n            Assert.AreEqual( V4i.Zero,                     (c1.R - c0).ToV4i()   );\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Math/ComplexTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\n\nusing Num = System.Numerics;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class ComplexTests\n    {\n        private static readonly int Iterations = 10000;\n\n        private static readonly double Epsilon = 1e-8;\n\n        private static bool IsZero(this Num.Complex x)\n            => x.Real == 0 && x.Imaginary == 0;\n\n        private static void AreEqual(Num.Complex a, ComplexD b)\n        {\n            bool cond =\n                (a.Real.ApproximateEquals(b.Real, Epsilon) &&\n                a.Imaginary.ApproximateEquals(b.Imag, Epsilon)) ||\n                (a.Real.Equals(b.Real) && a.Imaginary.Equals(b.Imag));\n\n            if (!cond) Debugger.Break();\n            Assert.IsTrue(cond, \"{0} != {1}\", a, b);\n        }\n\n        private static void AreEqualAngle(Num.Complex a, ComplexD b)\n        {\n            AreEqual(\n                new Num.Complex(a.Real % Constant.PiHalf, a.Imaginary), \n                new ComplexD(b.Real % Constant.PiHalf, b.Imag)\n            );\n        }\n\n        private static void AreEqual(dynamic a, dynamic b)\n        {\n            bool cond = Fun.ApproximateEquals(a, b, Epsilon) || a.Equals(b);\n\n            if (!cond) Debugger.Break();\n            Assert.IsTrue(cond, \"{0} != {1}\", a, b);\n        }\n\n        private static void GetRandomComplex(RandomSystem rnd, out Num.Complex c1, out ComplexD c2, bool withInf = true)\n        {\n            var type = rnd.UniformDouble();\n            \n            if (type < 0.1)\n            {\n                var v = rnd.UniformV2i(2);\n                c1 = new Num.Complex(v.X, v.Y);\n                c2 = new ComplexD(v.X, v.Y);\n            }\n            else if (type < 0.2 && withInf)\n            {\n                var i = rnd.UniformV2i(3);\n                var v = new V2d(\n                    (i.X == 0) ? 0 : ((i.X == 1) ? double.NegativeInfinity : double.PositiveInfinity),\n                    (i.Y == 0) ? 0 : ((i.Y == 1) ? double.NegativeInfinity : double.PositiveInfinity)\n                );\n\n                c1 = new Num.Complex(v.X, v.Y);\n                c2 = new ComplexD(v.X, v.Y);\n            }\n            else\n            {\n                var v = (rnd.UniformV2d() - 0.5) * 100;\n                if (type < 0.4)\n                {\n                    c1 = new Num.Complex(v.X, 0);\n                    c2 = new ComplexD(v.X, 0);\n                }\n                else if (type < 0.5)\n                {\n                    c1 = new Num.Complex(0, v.Y);\n                    c2 = new ComplexD(0, v.Y);\n                }\n                else\n                {\n                    c1 = new Num.Complex(v.X, v.Y);\n                    c2 = new ComplexD(v.X, v.Y);\n                }\n            }\n        }\n\n        private static void GenericTest(Action<RandomSystem, int> f)\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < Iterations; i++)\n            {\n                f(rnd, i);\n            }\n        }\n\n        private static void GenericTest(Action<RandomSystem> f)\n            => GenericTest((rnd, i) => f(rnd));\n\n        private static void UnaryTest(Func<Num.Complex, Num.Complex> fa, Func<ComplexD, ComplexD> fb, bool withInf = true)\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex a, out ComplexD b, withInf);\n                AreEqual(fa(a), fb(b));\n            });\n\n        private static void UnaryAngleTest(Func<Num.Complex, Num.Complex> fa, Func<ComplexD, ComplexD> fb)\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex a, out ComplexD b);\n                AreEqualAngle(fa(a), fb(b));\n            });\n\n        private static void UnaryRealTest(Func<Num.Complex, double> fa, Func<ComplexD, double> fb)\n            => UnaryTest(\n                c => new Num.Complex(fa(c), 0),\n                c => new ComplexD(fb(c), 0)\n            );\n\n        private static void BinaryTest(Func<Num.Complex, Num.Complex, Num.Complex> fa, Func<ComplexD, ComplexD, ComplexD> fb, bool withInf = true)\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex a1, out ComplexD b1, withInf);\n                GetRandomComplex(rnd, out Num.Complex a2, out ComplexD b2, withInf);\n                AreEqual(fa(a1, a2), fb(b1, b2));\n            });\n\n        private static void BinaryPowTest(Func<Num.Complex, Num.Complex, Num.Complex> fa, Func<ComplexD, ComplexD, ComplexD> fb, bool withInf = true)\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex a1, out ComplexD b1, withInf);\n                GetRandomComplex(rnd, out Num.Complex a2, out ComplexD b2, withInf);\n                var a = fa(a1, a2);\n\n                var tmp = fb(b1, b2);\n                var b = new Num.Complex(tmp.Real, tmp.Imag);\n\n                if (!a.Equals(b))\n                    AreEqual(a / b, ComplexD.One);\n            });\n\n        private static void UnaryPowTest(Func<Num.Complex, Num.Complex> fa, Func<ComplexD, ComplexD> fb, bool withInf = true)\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex a, out ComplexD b, withInf);\n                var x = fa(a);\n\n                var tmp = fb(b);\n                var y = new Num.Complex(tmp.Real, tmp.Imag);\n \n                if (!x.Equals(y))\n                    AreEqual(x / y, ComplexD.One);\n            });\n\n        #region ToString and Parse\n\n        [Test]\n        public static void ToStringAndParse()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c);\n                var str = c.ToString();\n                var x = ComplexD.Parse(str);\n\n                AreEqual(c, x);\n            });\n\n        #endregion\n\n        #region Properties\n\n        [Test]\n        public static void Conjugated()\n            => UnaryTest(\n                Num.Complex.Conjugate,\n                Complex.Conjugated\n            );\n\n        [Test]\n        public static void NormSquared()\n            => UnaryRealTest(\n                c => c.Magnitude * c.Magnitude,\n                Complex.NormSquared\n            );\n\n        [Test]\n        public static void Norm()\n            => UnaryRealTest(\n                c => c.Magnitude,\n                Complex.Norm\n            );\n\n        [Test]\n        public static void Argument()\n            => UnaryRealTest(\n                c => c.Phase,\n                Complex.Argument\n            );\n\n        #endregion\n\n        #region Binary operations\n\n        [Test]\n        public static void Addition()\n            => BinaryTest(\n                (a, b) => a + b,\n                (a, b) => a + b\n            );\n\n        [Test]\n        public static void AdditionReal()\n            => BinaryTest(\n                (a, b) => b.Real + a + b.Real,\n                (a, b) => b.Real + a + b.Real\n            );\n\n        [Test]\n        public static void Subtraction()\n            => BinaryTest(\n                (a, b) => a - b,\n                (a, b) => a - b\n            );\n\n        [Test]\n        public static void SubtractionReal()\n            => BinaryTest(\n                (a, b) => b.Real - a - b.Real,\n                (a, b) => b.Real - a - b.Real\n            );\n\n        [Test]\n        public static void Multiplication()\n            => BinaryTest(\n                (a, b) => a * b,\n                (a, b) => a * b\n            );\n\n        [Test]\n        public static void MultiplicationReal()\n            => BinaryTest(\n                (a, b) => b.Real * a * b.Real,\n                (a, b) => b.Real * a * b.Real,\n                false\n            );\n\n        [Test]\n        public static void Divison()\n            => BinaryTest(\n                (a, b) => (b.Magnitude != 0) ? (a / b) : Num.Complex.Zero,\n                (a, b) => (b.Norm != 0) ? (a / b) : ComplexD.Zero,\n                false\n            );\n\n        [Test]\n        public static void DivisionReal()\n            => BinaryTest(\n                (a, b) => (a.Magnitude != 0 && b.Real != 0) ? (b.Real / a / b.Real) : Num.Complex.Zero,\n                (a, b) => (a.Norm != 0 && b.Real != 0) ? (b.Real / a / b.Real) : ComplexD.Zero,\n                false\n            );\n\n        #endregion\n\n        #region Fun methods\n\n        [Test]\n        public static void Power()\n            => BinaryPowTest(\n                (a, b) =>\n                {\n                    if (a.IsZero() && b.IsZero())\n                        return Num.Complex.Zero;\n                    else\n                        return Num.Complex.Pow(a, b);\n                },\n                (a, b) =>\n                {\n                    if (a.IsZero && b.IsZero)\n                        return ComplexD.Zero;\n                    else\n                        return Fun.Pow(a, b);\n                }\n            );\n\n        [Test]\n        public static void PowerReal()\n            => BinaryPowTest(\n                (a, b) =>\n                {\n                    if ((a.Real == 0 && b.IsZero()) || (a.IsZero() && b.Real == 0))\n                        return Num.Complex.Zero;\n                    else\n                        return Num.Complex.Pow(a.Real, b) + Num.Complex.Pow(a, b.Real);\n                },\n                (a, b) =>\n                {\n                    if ((a.Real == 0 && b.IsZero) || (a.IsZero && b.Real == 0))\n                        return ComplexD.Zero;\n                    else\n                        return Fun.Pow(a.Real, b) + Fun.Pow(a, b.Real);\n                },\n                false\n            );\n\n        [Test]\n        public static void Acos()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n                var x = Fun.Cos(Fun.Acos(c));\n                AreEqual(c, x);\n            });\n\n        [Test]\n        public static void Acosh()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n                var x = Fun.Cosh(Fun.Acosh(c));\n                AreEqual(c, x);\n            });\n\n        [Test]\n        public static void Cosh()\n            => UnaryPowTest(\n                Num.Complex.Cosh,\n                Fun.Cosh\n            );\n\n        [Test]\n        public static void Cos()\n            => UnaryPowTest(\n                Num.Complex.Cos,\n                Fun.Cos\n            );\n\n        [Test]\n        public static void Asin()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n                var x = Fun.Sin(Fun.Asin(c));\n                AreEqual(c, x);\n            });\n\n        [Test]\n        public static void Asinh()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n                var x = Fun.Sinh(Fun.Asinh(c));\n                AreEqual(c, x);\n            });\n\n        [Test]\n        public static void Sinh()\n            => UnaryPowTest(\n                Num.Complex.Sinh,\n                Fun.Sinh\n            );\n\n        [Test]\n        public static void Sin()\n            => UnaryPowTest(\n                Num.Complex.Sin,\n                Fun.Sin\n            );\n\n        [Test]\n        public static void Atan()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex a, out ComplexD b);\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n\n                // https://mathworld.wolfram.com/InverseTangent.html\n                var values = new Dictionary<ComplexD, ComplexD>()\n                {\n                    { ComplexD.NegativeInfinity, new ComplexD(-Constant.PiHalf) },\n                    { ComplexD.PositiveInfinity, new ComplexD(Constant.PiHalf) },\n                    { ComplexD.I, new ComplexD(0, double.PositiveInfinity) },\n                    { -ComplexD.I, new ComplexD(0, double.NegativeInfinity) },\n                    { ComplexD.Zero, ComplexD.Zero },\n                };\n\n                Num.Complex x;\n\n                if (values.TryGetValue(b, out ComplexD reference))\n                    x = new Num.Complex(reference.Real, reference.Imag);\n                else\n                    x = Num.Complex.Atan(a);\n\n                var y = Fun.Atan(b);\n\n                AreEqualAngle(x, y);  \n                AreEqual(c, Fun.Tan(Fun.Atan(c)));\n            });\n\n        [Test]\n        public static void Atanh()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex a, out ComplexD b);\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n\n                // https://mathworld.wolfram.com/InverseHyperbolicTangent.html\n                var values = new Dictionary<ComplexD, ComplexD>()\n                {\n                    { ComplexD.Zero, ComplexD.Zero },\n                    { ComplexD.One, ComplexD.PositiveInfinity },\n                    { ComplexD.PositiveInfinity, -Constant.PiHalf * ComplexD.I },\n                    { ComplexD.I, Constant.PiQuarter * ComplexD.I }\n                };\n\n                if (values.TryGetValue(b, out ComplexD reference))\n                {\n                    var x = new Num.Complex(reference.Real, reference.Imag);\n                    var y = Fun.Atanh(b);\n                    AreEqualAngle(x, y);\n                }\n\n                AreEqual(c, Fun.Tanh(Fun.Atanh(c)));\n            });\n\n        [Test]\n        public static void Tanh()\n            => UnaryPowTest(\n                Num.Complex.Tanh,\n                Fun.Tanh,\n                false\n            );\n\n        [Test]\n        public static void Tan()\n            => UnaryPowTest(\n                Num.Complex.Tan,\n                Fun.Tan,\n                false\n            );\n\n        [Test]\n        public static void Sqrt()\n            => UnaryTest(\n                Num.Complex.Sqrt,\n                Fun.Sqrt,\n                false\n            );\n\n        [Test]\n        public static void Exp()\n            => UnaryTest(\n                Num.Complex.Exp,\n                Fun.Exp\n            );\n\n        [Test]\n        public static void Ln()\n            => UnaryTest(\n                c => c.IsZero() ? Num.Complex.Zero : Num.Complex.Log(c),\n                c => c.IsZero ? ComplexD.Zero : Fun.Log(c)\n            );\n\n        [Test]\n        public static void Log()\n            => BinaryTest(\n                (c, basis) =>\n                {\n                    if (c.IsZero() || basis.Real.Abs() <= 1)\n                        return Num.Complex.Zero;\n                    else\n                        return Num.Complex.Log(c, basis.Real.Abs());\n                },\n                (c, basis) =>\n                {\n                    if (c.IsZero || basis.Real.Abs() <= 1)\n                        return ComplexD.Zero;\n                    else\n                        return Fun.Log(c, basis.Real.Abs());\n                },\n                false\n            );\n\n        [Test]\n        public static void Log10()\n            => UnaryTest(\n                c => c.IsZero() ? Num.Complex.Zero : Num.Complex.Log10(c),\n                c => c.IsZero ? ComplexD.Zero : Fun.Log10(c),\n                false\n            );\n\n        [Test]\n        public static void Log2()\n            => UnaryTest(\n                c => c.IsZero() ? Num.Complex.Zero : Num.Complex.Log(c) * Constant.Ln2Inv,\n                c => c.IsZero ? ComplexD.Zero : Fun.Log2(c),\n                false\n            );\n\n        [Test]\n        public static void Cbrt()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n                var x = c.Cbrt();\n                var y = c.Root(3);\n                AreEqual(x * x * x, c);\n                AreEqual(x, y[0]);\n            });\n\n        [Test]\n        public static void Csqrt()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n                c = new ComplexD(c.Real, 0);\n                var x = c.Sqrt();\n\n                var y = c.Real.Csqrt();\n                var z = c.Csqrt();\n                var w = c.Root(2);\n\n                AreEqual(x, y);\n                AreEqual(x, z[0]);\n                AreEqual(x, w[0]);\n            });\n\n        [Test]\n        public static void Root()\n            => GenericTest(rnd =>\n            {\n                GetRandomComplex(rnd, out Num.Complex _, out ComplexD c, false);\n                int order = 2 + rnd.UniformInt(14);\n\n                var roots = Fun.Root(c, order);\n\n                foreach (var r in roots)\n                {\n                    var result = r;\n                    for (int i = 1; i < order; i++)\n                        result *= r;\n\n                    AreEqual(c, result);\n                }\n            });\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Math/Distributions.cs",
    "content": "﻿using NUnit.Framework;\nusing Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Tests\n{\n    public static class Distributions\n    {\n        [Test]\n        public static void CDFSampling()\n        {\n            var cdfSampleTestCount = 2000000;\n            var pdfSizes = new[] { 5, 10, 25, 50, 100, 250 };\n\n            var rnd = new RandomSystem(0);\n\n            foreach (var pz in pdfSizes)\n            {\n                var pdf = new double[pz].SetByIndex(i => rnd.UniformDouble());\n                var sum = pdf.Sum();\n\n                var cdf = new DistributionFunction(pdf);\n                Assert.True(cdf.Norm.ApproximateEquals(sum, 1e-10));\n\n                rnd.ReSeed(0);\n                var sc1 = new int[pdf.Length];\n                Report.BeginTimed(\"Sample Binary Search\");\n                for (int i = 0; i < cdfSampleTestCount; i++)\n                {\n                    var ind = cdf.Sample(rnd.UniformDouble());\n                    sc1[ind]++;\n                }\n                Report.End();\n\n                rnd.ReSeed(0);\n                var sc2 = new int[pdf.Length];\n                Report.BeginTimed(\"Sample Linear Search\");\n                for (int i = 0; i < cdfSampleTestCount; i++)\n                {\n                    var ind = SamplePDFLinear(pdf, sum, rnd.UniformDouble());\n                    sc2[ind]++;\n                }\n                Report.End();\n\n                for (int i = 0; i < pdf.Length; i++)\n                    Assert.True(sc1[i] == sc2[i]);\n            }\n        }\n\n        static int SamplePDFLinear(double[] pdf, double sum, double rnd)\n        {\n            var valueToFind = rnd * sum;\n            int index = 0;\n            double aggregate = 0;\n            // Linear Search\n            for (; index < pdf.Length - 1; index++)\n            {\n                aggregate += pdf[index];\n                if (valueToFind <= aggregate)\n                    break;\n            }\n            return index;\n        }\n\n        [Test]\n        public static void GaussTest()\n        {\n            // sample normal distribution function from -10 to 10\n            var range = new Range1d(-10, 10);\n            var sampleCount = 201; // uneven values with give symmetrical pdf\n            var pdf = new double[sampleCount].SetByIndex(i =>\n            {\n                var x = i / (sampleCount - 1.0);\n                var p = range.Lerp(x);\n                return Fun.Gauss(p, 1.0);\n            });\n\n            // integrate sampled gauss distribution\n            var stepSize = range.Size / (sampleCount - 1.0);\n            var integral = pdf.Sum() * stepSize;\n            // Gauss must integrate to 1.0\n            Assert.True(integral.ApproximateEquals(1.0, 1e-10)); \n        }\n\n        [Test]\n        public static void Gauss2dTest()\n        {\n            // sample 2d normal distribution function from -10 to 10 with 201x201 samples\n            var range = 10;\n            var area = new Box2d(-range, -range, range, range);\n            var sampleCount = 201; // uneven values with give symmetrical pdf\n            var pdf = new Matrix<double>(sampleCount, sampleCount);\n            pdf.SetByCoord((x,y) =>\n            {\n                var px = x / (sampleCount - 1.0);\n                var py = y / (sampleCount - 1.0);\n                var p = area.Lerp(px, py);\n                return Fun.Gauss2d(p.X, p.Y, 1.0);\n            });\n\n            // integrate sampled gauss distribution\n            var stepSize = range * 2.0 / (sampleCount - 1.0);\n            var integral = pdf.Data.Sum() * stepSize * stepSize;\n            // Gauss must integrate to 1.0\n            Assert.True(integral.ApproximateEquals(1.0, 1e-10));\n        }\n\n        [Test]\n        public static void Gauss2dEllipticalTest()\n        {\n            // sample 2d normal distribution function from -10 to 10 with 201x201 samples\n            var range = 10;\n            var area = new Box2d(-range, -range, range, range);\n            var sampleCount = 201; // uneven values with give symmetrical pdf\n            var pdf = new Matrix<double>(sampleCount, sampleCount);\n            pdf.SetByCoord((x, y) =>\n            {\n                var px = x / (sampleCount - 1.0);\n                var py = y / (sampleCount - 1.0);\n                var p = area.Lerp(px, py);\n                return Fun.Gauss2d(p.X, p.Y, 1.0, 1.5);\n            });\n\n            // integrate sampled gauss distribution\n            var stepSize = range * 2.0 / (sampleCount - 1.0);\n            var integral = pdf.Data.Sum() * stepSize * stepSize;\n            // Gauss must integrate to 1.0\n            Assert.True(integral.ApproximateEquals(1.0, 1e-10));\n        }\n\n        [Test]\n        public static void ErfTest()\n        {\n            // reference solution\n            var erf = new[]\n            {\n                0,\n                0.84270079294971486934122063508261, // 1\n                0.99532226501895273416206925636725, // 2\n                0.99997790950300141455862722387042, // 3\n                0.99999998458274209971998114784033, // 4\n                0.99999999999846254020557196514981, // 5\n            };\n\n            for (int i = -5; i < 5; i++)\n            {\n                var f1 = Fun.Erf(i);\n                var f2 = Fun.Erf2(i);\n                var should = erf[i.Abs()] * i.Sign();\n                var e1 = (f1 - should).Abs();\n                var e2 = (f2 - should).Abs();\n\n                Report.Line(\"Erf1 error {0}\", e1);\n                Report.Line(\"Erf2 error {0}\", e2);\n\n                if (e1 < e2)\n                    Report.Line(\"Erf1\");\n                else\n                    Report.Line(\"Erf2\");\n\n                var test1 = e1.ApproximateEquals(0, 1e-6);\n                Report.Line(\"Erf1 valid={0}\", test1);\n                Assert.True(test1);\n                var test2 = e2.ApproximateEquals(0, 1e-6);\n                Report.Line(\"Erf2 valid={0}\", test2);\n                Assert.True(test2);\n            }\n\n            // reference solution\n            var erfClose = new[]\n            {\n                0,\n                0.1124629160182848922032750717439683832216962991597025, // 0.1\n                0.2227025892104784541401390068001438163882690384302276, // 0.2\n                0.3286267594591274276389140478667565511699180962626758, // 0.3\n                0.4283923550466684551036038453201724441218629285225903, // 0.4\n                0.5204998778130465376827466538919645287364515757579637, // 0.5\n                0.6038560908479259225626224360567232065642733648000979, // 0.6\n                0.6778011938374184729756288092441513967162881743348702, // 0.7\n                0.7421009647076604861671105865029458773176895799147087, // 0.8\n                0.7969082124228321285187247851418859375486580415858037, // 0.9\n            };\n\n            for (int i = 1; i < 10; i++)\n            {\n                var v = i / 10.0;\n                var f1 = Fun.Erf(v);\n                var f2 = Fun.Erf2(v);\n                var should = erfClose[i.Abs()] * i.Sign();\n                var e1 = (f1 - should).Abs();\n                var e2 = (f2 - should).Abs();\n\n                Report.Line(\"Erf1 error {0}\", e1);\n                Report.Line(\"Erf2 error {0}\", e2);\n\n                if (e1 < e2)\n                    Report.Line(\"Erf1\");\n                else\n                    Report.Line(\"Erf2\");\n\n                var test1 = e1.ApproximateEquals(0, 1e-6);\n                Report.Line(\"Erf1 valid={0}\", test1);\n                Assert.True(test1);\n                var test2 = e2.ApproximateEquals(0, 1e-6);\n                Report.Line(\"Erf2 valid={0}\", test2);\n                Assert.True(test2);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Math/FunTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class FunTests : TestSuite\n    {\n        public FunTests() : base() { }\n        public FunTests(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public static void AngleDistanceTest()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 1000; i++)\n            {\n                var alpha = rnd.UniformDouble() * Constant.PiTimesTwo;\n                var delta = (rnd.UniformDouble() - 0.5) * 2.0 * Constant.Pi;\n                var beta = alpha + (delta + Constant.PiTimesTwo * rnd.UniformInt(10));\n\n                var dist = alpha.AngleDistance(beta);\n                Assert.AreEqual(dist, Fun.Abs(delta), 1e-8);\n            }\n        }\n\n        [Test]\n        public static void AngleDifferenceTest()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < 1000; i++)\n            {\n                var alpha = rnd.UniformDouble() * Constant.PiTimesTwo * rnd.UniformInt(10);\n                var delta = (rnd.UniformDouble() - 0.5) * Constant.Pi;\n                if (delta == Constant.Pi)\n                    delta = -Constant.Pi;\n\n                var beta = alpha + (delta + Constant.PiTimesTwo * rnd.UniformInt(10));\n\n                var dist = alpha.AngleDifference(beta);\n                Assert.AreEqual(dist, delta, 1e-8);\n            }\n        }\n\n        [Test]\n        public void MinMaxVarArg()\n        {\n            var rnd = new RandomSystem(1);\n            var a = rnd.UniformInt();\n            var b = rnd.UniformInt();\n            var c = rnd.UniformInt();\n            var d = rnd.UniformInt();\n            var e = rnd.UniformInt();\n\n            var min = Fun.Min(a, b, c, d, e);\n            var min_ref = Fun.Min(Fun.Min(Fun.Min(Fun.Min(a, b), c), d), e);\n            Assert.AreEqual(min, min_ref, \"Min not equal to reference\");\n\n            var max = Fun.Max(a, b, c, d, e);\n            var max_ref = Fun.Max(Fun.Max(Fun.Max(Fun.Max(a, b), c), d), e);\n            Assert.AreEqual(max, max_ref, \"Max not equal to reference\");\n        }\n\n        [Test]\n        public void MinMaxVecVarArg()\n        {\n            var rnd = new RandomSystem(1);\n            var a = rnd.UniformV4i();\n            var b = rnd.UniformV4i();\n            var c = rnd.UniformV4i();\n            var d = rnd.UniformV4i();\n            var e = rnd.UniformV4i();\n\n            var min = Fun.Min(a, b, c, d, e);\n            var min_ref = Fun.Min(Fun.Min(Fun.Min(Fun.Min(a, b), c), d), e);\n            Assert.AreEqual(min, min_ref, \"Min not equal to reference\");\n\n            var max = Fun.Max(a, b, c, d, e);\n            var max_ref = Fun.Max(Fun.Max(Fun.Max(Fun.Max(a, b), c), d), e);\n            Assert.AreEqual(max, max_ref, \"Max not equal to reference\");\n        }\n\n        private static double NextAfter(double input, int dir)\n            => BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(input) + dir);\n\n        private static float NextAfter(float input, int dir)\n            => BitConverter.Int32BitsToSingle(BitConverter.SingleToInt32Bits(input) + dir);\n\n        private static float SincFloatImpl(float x)\n        {\n            return MathF.Sin(ConstantF.Pi * x) / (ConstantF.Pi * x);\n        }\n\n        private static double SincDoubleImpl(double x)\n        {\n            return Math.Sin(Constant.Pi * x) / (Constant.Pi * x);\n        }\n\n        private static string FormatBits(float x)\n        {\n            return $\"0x{BitConverter.SingleToInt32Bits(x):X8}\";\n        }\n\n        private static string FormatBits(double x)\n        {\n            return $\"0x{BitConverter.DoubleToInt64Bits(x):X16}\";\n        }\n\n        private static float FindFirstFloatSincNotOne(float startInclusive, int maxUlps)\n        {\n            var x = startInclusive;\n\n            for (var i = 0; i <= maxUlps; i++)\n            {\n                if (SincFloatImpl(x) != 1.0f)\n                    return x;\n\n                x = NextAfter(x, 1);\n            }\n\n            Assert.Fail(\n                \"Could not find float x with raw sinc(x) != 1 within {0} ULPs from x = {1:R} ({2})\",\n                maxUlps,\n                startInclusive,\n                FormatBits(startInclusive)\n            );\n\n            return default;\n        }\n\n        private static double FindFirstDoubleSincNotOne(double startInclusive, int maxUlps)\n        {\n            var x = startInclusive;\n\n            for (var i = 0; i <= maxUlps; i++)\n            {\n                if (SincDoubleImpl(x) != 1.0)\n                    return x;\n\n                x = NextAfter(x, 1);\n            }\n\n            Assert.Fail(\n                \"Could not find double x with raw sinc(x) != 1 within {0} ULPs from x = {1:R} ({2})\",\n                maxUlps,\n                startInclusive,\n                FormatBits(startInclusive)\n            );\n\n            return default;\n        }\n\n        [Test]\n        public void SincTest()\n        {\n            const int searchUlps = 4096;\n            const int verifyUlps = 256;\n\n            // Keep the current implementation cutoffs in sync with Fun.Sinc.\n            {\n                const float cutoff = 0.00017791694f;\n                float[] thresholds = { cutoff, -cutoff };\n\n                foreach (var threshold in thresholds)\n                {\n                    var insideCutoff = NextAfter(threshold, -1);\n                    Assert.AreEqual(\n                        1.0f,\n                        Fun.Sinc(insideCutoff),\n                        \"Expected Fun.Sinc(x) = 1 one ULP inside the float cutoff, but got x = {0:R} ({1})\",\n                        insideCutoff,\n                        FormatBits(insideCutoff)\n                    );\n\n                    var firstNonOne = FindFirstFloatSincNotOne(threshold, searchUlps);\n                    Assert.AreNotEqual(\n                        1.0f,\n                        Fun.Sinc(firstNonOne),\n                        \"Expected Fun.Sinc(x) != 1 at or above the float cutoff, but got x = {0:R} ({1})\",\n                        firstNonOne,\n                        FormatBits(firstNonOne)\n                    );\n\n                    var x = firstNonOne;\n                    for (var i = 0; i < verifyUlps; i++)\n                    {\n                        Assert.AreNotEqual(\n                            1.0f,\n                            Fun.Sinc(x),\n                            \"Expected Fun.Sinc(x) != 1 in the verified float window above the cutoff, but got x = {0:R} ({1})\",\n                            x,\n                            FormatBits(x)\n                        );\n\n                        x = NextAfter(x, 1);\n                    }\n                }\n            }\n\n            {\n                const double cutoff = 6.840859302478615E-09;\n                double[] thresholds = { cutoff, -cutoff };\n\n                foreach (var threshold in thresholds)\n                {\n                    var insideCutoff = NextAfter(threshold, -1);\n                    Assert.AreEqual(\n                        1.0,\n                        Fun.Sinc(insideCutoff),\n                        \"Expected Fun.Sinc(x) = 1 one ULP inside the double cutoff, but got x = {0:R} ({1})\",\n                        insideCutoff,\n                        FormatBits(insideCutoff)\n                    );\n\n                    var firstNonOne = FindFirstDoubleSincNotOne(threshold, searchUlps);\n                    Assert.AreNotEqual(\n                        1.0,\n                        Fun.Sinc(firstNonOne),\n                        \"Expected Fun.Sinc(x) != 1 at or above the double cutoff, but got x = {0:R} ({1})\",\n                        firstNonOne,\n                        FormatBits(firstNonOne)\n                    );\n\n                    var x = firstNonOne;\n                    for (var i = 0; i < verifyUlps; i++)\n                    {\n                        Assert.AreNotEqual(\n                            1.0,\n                            Fun.Sinc(x),\n                            \"Expected Fun.Sinc(x) != 1 in the verified double window above the cutoff, but got x = {0:R} ({1})\",\n                            x,\n                            FormatBits(x)\n                        );\n\n                        x = NextAfter(x, 1);\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Math/HalfTests.cs",
    "content": "﻿using System;\nusing System.Globalization;\nusing System.Threading;\nusing Aardvark.Base;\nusing NUnit.Framework;\nusing Half = Aardvark.Base.Half;\n\nnamespace Aardvark.Tests\n{\n    // Code by Ladislav Lang: https://sourceforge.net/projects/csharp-half/\n\n    /// <summary>\n    ///This is a test class for HalfTest and is intended\n    ///to contain all HalfTest Unit Tests\n    ///</summary>\n    [TestFixture]\n    public class HalfTest\n    {\n        [OneTimeSetUp]\n        public static void HalfTestInitialize()\n        {\n            Thread.CurrentThread.CurrentCulture = new CultureInfo(\"en-US\");\n        }\n\n        [Test]\n        public unsafe void TestAllPossibleHalfValues()\n        {\n            for (ushort i = ushort.MinValue; i < ushort.MaxValue; i++)\n            {\n                Half half1 = Half.ToHalf(i);\n                Half half2 = (Half)((float)half1);\n\n                Assert.IsTrue(half1.Equals(half2));\n            }\n        }\n\n        /// <summary>\n        ///A test for TryParse\n        ///</summary>\n        [Test]\n        public void TryParseTest1()\n        {\n            Thread.CurrentThread.CurrentCulture = new CultureInfo(\"cs-CZ\");\n\n            string value = \"1234,567e-2\";\n            float resultExpected = (float)12.34567f;\n\n            bool expected = true;\n            float result;\n            bool actual = float.TryParse(value, out result);\n            Assert.AreEqual(resultExpected, result);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for TryParse\n        ///</summary>\n        [Test]\n        public void TryParseTest()\n        {\n            string value = \"777\";\n            NumberStyles style = NumberStyles.None;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            Half result;\n            Half resultExpected = (Half)777f;\n            bool expected = true;\n            bool actual = Half.TryParse(value, style, provider, out result);\n            Assert.AreEqual(resultExpected, result);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for ToString\n        ///</summary>\n        [Test]\n        public void ToStringTest4()\n        {\n            Half target = Half.Epsilon;\n            string format = \"e\";\n            string expected = \"5.960464e-008\";\n            string actual = target.ToString(format);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for ToString\n        ///</summary>\n        [Test]\n        public void ToStringTest3()\n        {\n            Half target = (Half)333.333f;\n            string format = \"G\";\n            IFormatProvider formatProvider = CultureInfo.CreateSpecificCulture(\"cs-CZ\");\n            string expected = \"333,25\";\n            string actual = target.ToString(format, formatProvider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for ToString\n        ///</summary>\n        [Test]\n        public void ToStringTest2()\n        {\n            Half target = (Half)0.001f;\n            IFormatProvider formatProvider = CultureInfo.CreateSpecificCulture(\"cs-CZ\");\n            string expected = \"0,0009994507\";\n            string actual = target.ToString(formatProvider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for ToString\n        ///</summary>\n        [Test]\n        public void ToStringTest1()\n        {\n            Half target = (Half)10000.00001f;\n            string expected = \"10000\";\n            string actual = target.ToString();\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for ToHalf\n        ///</summary>\n        [Test]\n        public void ToHalfTest1()\n        {\n            byte[] value = { 0x11, 0x22, 0x33, 0x44 };\n            int startIndex = 1;\n            Half expected = Half.ToHalf(0x3322);\n            Half actual = Half.ToHalf(value, startIndex);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for ToHalf\n        ///</summary>\n        [Test]\n        public void ToHalfTest()\n        {\n            ushort bits = 0x3322;\n            Half expected = (Half)0.2229004f;\n            Half actual = Half.ToHalf(bits);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToUInt64\n        ///</summary>\n        [Test]\n        public void ToUInt64Test()\n        {\n            IConvertible target = (Half)12345.999f;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            ulong expected = 12344;\n            ulong actual = target.ToUInt64(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToUInt32\n        ///</summary>\n        [Test]\n        public void ToUInt32Test()\n        {\n            IConvertible target = (Half)9999;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            uint expected = 9992;\n            uint actual = target.ToUInt32(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToUInt16\n        ///</summary>\n        [Test]\n        public void ToUInt16Test()\n        {\n            IConvertible target = (Half)33.33;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            ushort expected = 33;\n            ushort actual = target.ToUInt16(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToType\n        ///</summary>\n        [Test]\n        public void ToTypeTest()\n        {\n            IConvertible target = (Half)111.111f;\n            Type conversionType = typeof(double);\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            object expected = 111.0625;\n            object actual = target.ToType(conversionType, provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToString\n        ///</summary>\n        [Test]\n        public void ToStringTest()\n        {\n            IConvertible target = (Half)888.888;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            string expected = \"888.5\";\n            string actual = target.ToString(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToSingle\n        ///</summary>\n        [Test]\n        public void ToSingleTest()\n        {\n            IConvertible target = (Half)55.77f;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            float expected = 55.75f;\n            float actual = target.ToSingle(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToSByte\n        ///</summary>\n        [Test]\n        public void ToSByteTest()\n        {\n            IConvertible target = 123.5678f;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            sbyte expected = 124;\n            sbyte actual = target.ToSByte(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToInt64\n        ///</summary>\n        [Test]\n        public void ToInt64Test()\n        {\n            IConvertible target = (Half)8562;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            long expected = 8560;\n            long actual = target.ToInt64(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToInt32\n        ///</summary>\n        [Test]\n        public void ToInt32Test()\n        {\n            IConvertible target = (Half)555.5;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            int expected = 556;\n            int actual = target.ToInt32(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToInt16\n        ///</summary>\n        [Test]\n        public void ToInt16Test()\n        {\n            IConvertible target = (Half)365;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            short expected = 365;\n            short actual = target.ToInt16(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToChar\n        ///</summary>\n        [Test]\n        public void ToCharTest()\n        {\n            IConvertible target = (Half)64UL;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n\n            try\n            {\n                char actual = target.ToChar(provider);\n                Assert.Fail();\n            }\n            catch (InvalidCastException) { }\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToDouble\n        ///</summary>\n        [Test]\n        public void ToDoubleTest()\n        {\n            IConvertible target = Half.MaxValue;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            double expected = 65504;\n            double actual = target.ToDouble(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToDecimal\n        ///</summary>\n        [Test]\n        public void ToDecimalTest()\n        {\n            IConvertible target = (Half)146.33f;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            Decimal expected = new Decimal(146.25f);\n            Decimal actual = target.ToDecimal(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToDateTime\n        ///</summary>\n        [Test]\n        public void ToDateTimeTest()\n        {\n            IConvertible target = (Half)0;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n\n            try\n            {\n                DateTime actual = target.ToDateTime(provider);\n                Assert.Fail();\n            }\n            catch (InvalidCastException) { }\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToByte\n        ///</summary>\n        [Test]\n        public void ToByteTest()\n        {\n            IConvertible target = (Half)111;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            byte expected = 111;\n            byte actual = target.ToByte(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.ToBoolean\n        ///</summary>\n        [Test]\n        public void ToBooleanTest()\n        {\n            IConvertible target = (Half)77;\n            IFormatProvider provider = CultureInfo.InvariantCulture;\n            bool expected = true;\n            bool actual = target.ToBoolean(provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for System.IConvertible.GetTypeCode\n        ///</summary>\n        [Test]\n        public void GetTypeCodeTest1()\n        {\n            IConvertible target = (Half)33;\n            TypeCode expected = (TypeCode)255;\n            TypeCode actual = target.GetTypeCode();\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Subtract\n        ///</summary>\n        [Test]\n        public void SubtractTest()\n        {\n            Half half1 = (Half)1.12345f;\n            Half half2 = (Half)0.01234f;\n            Half expected = (Half)1.11111f;\n            Half actual = Half.Subtract(half1, half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Sign\n        ///</summary>\n        [Test]\n        public void SignTest()\n        {\n            Assert.AreEqual(1, Half.Sign((Half)333.5));\n            Assert.AreEqual(1, Half.Sign(10));\n            Assert.AreEqual(-1, Half.Sign((Half)(-333.5)));\n            Assert.AreEqual(-1, Half.Sign(-10));\n            Assert.AreEqual(0, Half.Sign(0));\n        }\n\n        /// <summary>\n        ///A test for Parse\n        ///</summary>\n        [Test]\n        public void ParseTest3()\n        {\n            string value = \"112,456e-1\";\n            IFormatProvider provider = new CultureInfo(\"cs-CZ\");\n            Half expected = (Half)11.2456;\n            Half actual = Half.Parse(value, provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Parse\n        ///</summary>\n        [Test]\n        public void ParseTest2()\n        {\n            string value = \"55.55\";\n            Half expected = (Half)55.55;\n            Half actual = Half.Parse(value);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Parse\n        ///</summary>\n        [Test]\n        public void ParseTest1()\n        {\n            string value = \"-1.063E-02\";\n            NumberStyles style = NumberStyles.AllowExponent | NumberStyles.Number;\n            IFormatProvider provider = CultureInfo.CreateSpecificCulture(\"en-US\");\n            Half expected = (Half)(-0.01062775);\n            Half actual = Half.Parse(value, style, provider);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Parse\n        ///</summary>\n        [Test]\n        public void ParseTest()\n        {\n            string value = \"-7\";\n            NumberStyles style = NumberStyles.Number;\n            Half expected = (Half)(-7);\n            Half actual = Half.Parse(value, style);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_UnaryPlus\n        ///</summary>\n        [Test]\n        public void op_UnaryPlusTest()\n        {\n            Half half = (Half)77;\n            Half expected = (Half)77;\n            Half actual = +(half);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_UnaryNegation\n        ///</summary>\n        [Test]\n        public void op_UnaryNegationTest()\n        {\n            Half half = (Half)77;\n            Half expected = (Half)(-77);\n            Half actual = -(half);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Subtraction\n        ///</summary>\n        [Test]\n        public void op_SubtractionTest()\n        {\n            Half half1 = (Half)77.99;\n            Half half2 = (Half)17.88;\n            Half expected = (Half)60.0625;\n            Half actual = (half1 - half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Multiply\n        ///</summary>\n        [Test]\n        public void op_MultiplyTest()\n        {\n            Half half1 = (Half)11.1;\n            Half half2 = (Half)5;\n            Half expected = (Half)55.46879;\n            Half actual = (half1 * half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_LessThanOrEqual\n        ///</summary>\n        [Test]\n        public void op_LessThanOrEqualTest()\n        {\n            {\n                Half half1 = (Half)111;\n                Half half2 = (Half)120;\n                bool expected = true;\n                bool actual = (half1 <= half2);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half1 = (Half)111;\n                Half half2 = (Half)111;\n                bool expected = true;\n                bool actual = (half1 <= half2);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for op_LessThan\n        ///</summary>\n        [Test]\n        public void op_LessThanTest()\n        {\n            {\n                Half half1 = (Half)111;\n                Half half2 = (Half)120;\n                bool expected = true;\n                bool actual = (half1 <= half2);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half1 = (Half)111;\n                Half half2 = (Half)111;\n                bool expected = true;\n                bool actual = (half1 <= half2);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for op_Inequality\n        ///</summary>\n        [Test]\n        public void op_InequalityTest()\n        {\n            {\n                Half half1 = (Half)0;\n                Half half2 = (Half)1;\n                bool expected = true;\n                bool actual = (half1 != half2);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half1 = Half.MaxValue;\n                Half half2 = Half.MaxValue;\n                bool expected = false;\n                bool actual = (half1 != half2);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for op_Increment\n        ///</summary>\n        [Test]\n        public void op_IncrementTest()\n        {\n            Half half = (Half)125.33f;\n            Half expected = (Half)126.33f;\n            Half actual = ++(half);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest10()\n        {\n            Half value = (Half)55.55f;\n            float expected = 55.53125f;\n            float actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest9()\n        {\n            long value = 1295;\n            Half expected = (Half)1295;\n            Half actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest8()\n        {\n            sbyte value = -15;\n            Half expected = (Half)(-15);\n            Half actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest7()\n        {\n            Half value = Half.Epsilon;\n            double expected = 5.9604644775390625e-8;\n            double actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest6()\n        {\n            short value = 15555;\n            Half expected = (Half)15552;\n            Half actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest5()\n        {\n            byte value = 77;\n            Half expected = (Half)77;\n            Half actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest4()\n        {\n            int value = 7777;\n            Half expected = (Half)7776;\n            Half actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest3()\n        {\n            char value = '@';\n            Half expected = 64;\n            Half actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest2()\n        {\n            ushort value = 546;\n            Half expected = 546;\n            Half actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest1()\n        {\n            ulong value = 123456UL;\n            Half expected = Half.PositiveInfinity;\n            Half actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Implicit\n        ///</summary>\n        [Test]\n        public void op_ImplicitTest()\n        {\n            uint value = 728;\n            Half expected = 728;\n            Half actual;\n            actual = value;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_GreaterThanOrEqual\n        ///</summary>\n        [Test]\n        public void op_GreaterThanOrEqualTest()\n        {\n            {\n                Half half1 = (Half)111;\n                Half half2 = (Half)120;\n                bool expected = false;\n                bool actual = (half1 >= half2);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half1 = (Half)111;\n                Half half2 = (Half)111;\n                bool expected = true;\n                bool actual = (half1 >= half2);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for op_GreaterThan\n        ///</summary>\n        [Test]\n        public void op_GreaterThanTest()\n        {\n            {\n                Half half1 = (Half)111;\n                Half half2 = (Half)120;\n                bool expected = false;\n                bool actual = (half1 > half2);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half1 = (Half)111;\n                Half half2 = (Half)111;\n                bool expected = false;\n                bool actual = (half1 > half2);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest12()\n        {\n            Half value = 1245;\n            uint expected = 1245;\n            uint actual = ((uint)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest11()\n        {\n            Half value = 3333;\n            ushort expected = 3332;\n            ushort actual = ((ushort)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest10()\n        {\n            float value = 0.1234f;\n            Half expected = (Half)0.1234f;\n            Half actual = ((Half)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest9()\n        {\n            Half value = 9777;\n            Decimal expected = 9776;\n            Decimal actual = ((Decimal)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest8()\n        {\n            Half value = (Half)5.5;\n            sbyte expected = 5;\n            sbyte actual = ((sbyte)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest7()\n        {\n            Half value = 666;\n            ulong expected = 666;\n            ulong actual = ((ulong)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest6()\n        {\n            double value = -666.66;\n            Half expected = (Half)(-666.66);\n            Half actual = ((Half)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest5()\n        {\n            Half value = (Half)33.3;\n            short expected = 33;\n            short actual = ((short)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest4()\n        {\n            Half value = 12345;\n            long expected = 12344;\n            long actual = ((long)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest3()\n        {\n            Half value = (Half)15.15;\n            int expected = 15;\n            int actual = ((int)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest2()\n        {\n            Decimal value = new Decimal(333.1);\n            Half expected = (Half)333.1;\n            Half actual = ((Half)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest1()\n        {\n            Half value = (Half)(-77);\n            byte expected = unchecked((byte)(-77));\n            byte actual = ((byte)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Explicit\n        ///</summary>\n        [Test]\n        public void op_ExplicitTest()\n        {\n            Half value = 64;\n            char expected = '@';\n            char actual = ((char)(value));\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Equality\n        ///</summary>\n        [Test]\n        public void op_EqualityTest()\n        {\n            {\n                Half half1 = Half.MaxValue;\n                Half half2 = Half.MaxValue;\n                bool expected = true;\n                bool actual = (half1 == half2);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half1 = Half.NaN;\n                Half half2 = Half.NaN;\n                bool expected = false;\n                bool actual = (half1 == half2);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for op_Division\n        ///</summary>\n        [Test]\n        public void op_DivisionTest()\n        {\n            Half half1 = 333;\n            Half half2 = 3;\n            Half expected = 111;\n            Half actual = (half1 / half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Decrement\n        ///</summary>\n        [Test]\n        public void op_DecrementTest()\n        {\n            Half half = 1234;\n            Half expected = 1233;\n            Half actual = --(half);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for op_Addition\n        ///</summary>\n        [Test]\n        public void op_AdditionTest()\n        {\n            Half half1 = (Half)1234.5f;\n            Half half2 = (Half)1234.5f;\n            Half expected = (Half)2469f;\n            Half actual = (half1 + half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Negate\n        ///</summary>\n        [Test]\n        public void NegateTest()\n        {\n            Half half = new Half(658.51);\n            Half expected = new Half(-658.51);\n            Half actual = Half.Negate(half);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Multiply\n        ///</summary>\n        [Test]\n        public void MultiplyTest()\n        {\n            Half half1 = 7;\n            Half half2 = 12;\n            Half expected = 84;\n            Half actual = Half.Multiply(half1, half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Min\n        ///</summary>\n        [Test]\n        public void MinTest()\n        {\n            Half val1 = -155;\n            Half val2 = 155;\n            Half expected = -155;\n            Half actual = Half.Min(val1, val2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Max\n        ///</summary>\n        [Test]\n        public void MaxTest()\n        {\n            Half val1 = new Half(333);\n            Half val2 = new Half(332);\n            Half expected = new Half(333);\n            Half actual = Half.Max(val1, val2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for IsPositiveInfinity\n        ///</summary>\n        [Test]\n        public void IsPositiveInfinityTest()\n        {\n            {\n                Half half = Half.PositiveInfinity;\n                bool expected = true;\n                bool actual = Half.IsPositiveInfinity(half);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half = (Half)1234.5678f;\n                bool expected = false;\n                bool actual = Half.IsPositiveInfinity(half);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for IsNegativeInfinity\n        ///</summary>\n        [Test]\n        public void IsNegativeInfinityTest()\n        {\n            {\n                Half half = Half.NegativeInfinity;\n                bool expected = true;\n                bool actual = Half.IsNegativeInfinity(half);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half = (Half)1234.5678f;\n                bool expected = false;\n                bool actual = Half.IsNegativeInfinity(half);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for IsNaN\n        ///</summary>\n        [Test]\n        public void IsNaNTest()\n        {\n            {\n                Half half = Half.NaN;\n                bool expected = true;\n                bool actual = Half.IsNaN(half);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half = (Half)1234.5678f;\n                bool expected = false;\n                bool actual = Half.IsNaN(half);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for IsInfinity\n        ///</summary>\n        [Test]\n        public void IsInfinityTest()\n        {\n            {\n                Half half = Half.NegativeInfinity;\n                bool expected = true;\n                bool actual = Half.IsInfinity(half);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half = Half.PositiveInfinity;\n                bool expected = true;\n                bool actual = Half.IsInfinity(half);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half half = (Half)1234.5678f;\n                bool expected = false;\n                bool actual = Half.IsInfinity(half);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for GetTypeCode\n        ///</summary>\n        [Test]\n        public void GetTypeCodeTest()\n        {\n            Half target = new Half();\n            TypeCode expected = (TypeCode)255;\n            TypeCode actual = target.GetTypeCode();\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for GetHashCode\n        ///</summary>\n        [Test]\n        public void GetHashCodeTest()\n        {\n            Half target = 777;\n            int expected = 25106;\n            int actual = target.GetHashCode();\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for GetBytes\n        ///</summary>\n        [Test]\n        public void GetBytesTest()\n        {\n            Half value = Half.ToHalf(0x1234);\n            byte[] expected = { 0x34, 0x12 };\n            byte[] actual = Half.GetBytes(value);\n            Assert.AreEqual(expected[0], actual[0]);\n            Assert.AreEqual(expected[1], actual[1]);\n        }\n\n        /// <summary>\n        ///A test for GetBits\n        ///</summary>\n        [Test]\n        public void GetBitsTest()\n        {\n            Half value = new Half(555.555);\n            ushort expected = 24663;\n            ushort actual = Half.GetBits(value);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Equals\n        ///</summary>\n        [Test]\n        public void EqualsTest1()\n        {\n            {\n                Half target = Half.MinValue;\n                Half half = Half.MinValue;\n                bool expected = true;\n                bool actual = target.Equals(half);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half target = 12345;\n                Half half = 12345;\n                bool expected = true;\n                bool actual = target.Equals(half);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        /// <summary>\n        ///A test for Equals\n        ///</summary>\n        [Test]\n        public void EqualsTest()\n        {\n            {\n                Half target = new Half();\n                object obj = new Single();\n                bool expected = false;\n                bool actual = target.Equals(obj);\n                Assert.AreEqual(expected, actual);\n            }\n            {\n                Half target = new Half();\n                object obj = (Half)111;\n                bool expected = false;\n                bool actual = target.Equals(obj);\n                Assert.AreEqual(expected, actual);\n            }\n        }\n\n        [Test]\n        public void ZeroTest()\n        {\n            Half expected = new Half(0);\n            Half actual = Half.Zero;\n            Assert.AreEqual(expected, actual);\n        }\n\n        [Test]\n        public void OneTest()\n        {\n            Half expected = new Half(1);\n            Half actual = Half.One;\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Divide\n        ///</summary>\n        [Test]\n        public void DivideTest()\n        {\n            Half half1 = (Half)626.046f;\n            Half half2 = (Half)8790.5f;\n            Half expected = (Half)0.07122803f;\n            Half actual = Half.Divide(half1, half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Divide by zero\n        ///</summary>\n        [Test]\n        public void DivideByZeroTest()\n        {\n            Half half1 = (Half)626.046f;\n            Half half2 = Half.Zero;\n            Half expected = Half.PositiveInfinity;\n            Half actual = Half.Divide(half1, half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for CompareTo\n        ///</summary>\n        [Test]\n        public void CompareToTest1()\n        {\n            Half target = 1;\n            Half half = 2;\n            int expected = -1;\n            int actual = target.CompareTo(half);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for CompareTo\n        ///</summary>\n        [Test]\n        public void CompareToTest()\n        {\n            Half target = 666;\n            object obj = (Half)555;\n            int expected = 1;\n            int actual = target.CompareTo(obj);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Add\n        ///</summary>\n        [Test]\n        public void AddTest()\n        {\n            Half half1 = (Half)33.33f;\n            Half half2 = (Half)66.66f;\n            Half expected = (Half)99.99f;\n            Half actual = Half.Add(half1, half2);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Abs\n        ///</summary>\n        [Test]\n        public void AbsTest()\n        {\n            Half value = -55;\n            Half expected = 55;\n            Half actual = Half.Abs(value);\n            Assert.AreEqual(expected, actual);\n        }\n\n        /// <summary>\n        ///A test for Half Constructor\n        ///</summary>\n        [Test]\n        public void HalfConstructorTest6()\n        {\n            long value = 44;\n            Half target = new Half(value);\n            Assert.AreEqual((long)target, 44);\n        }\n\n        /// <summary>\n        ///A test for Half Constructor\n        ///</summary>\n        [Test]\n        public void HalfConstructorTest5()\n        {\n            int value = 789; // TODO: Initialize to an appropriate value\n            Half target = new Half(value);\n            Assert.AreEqual((int)target, 789);\n        }\n\n        /// <summary>\n        ///A test for Half Constructor\n        ///</summary>\n        [Test]\n        public void HalfConstructorTest4()\n        {\n            float value = -0.1234f;\n            Half target = new Half(value);\n            Assert.AreEqual(target, (Half)(-0.1233521f));\n        }\n\n        /// <summary>\n        ///A test for Half Constructor\n        ///</summary>\n        [Test]\n        public void HalfConstructorTest3()\n        {\n            double value = 11.11;\n            Half target = new Half(value);\n            Assert.AreEqual((double)target, 11.109375);\n        }\n\n        /// <summary>\n        ///A test for Half Constructor\n        ///</summary>\n        [Test]\n        public void HalfConstructorTest2()\n        {\n            ulong value = 99999999;\n            Half target = new Half(value);\n            Assert.AreEqual(target, Half.PositiveInfinity);\n        }\n\n        /// <summary>\n        ///A test for Half Constructor\n        ///</summary>\n        [Test]\n        public void HalfConstructorTest1()\n        {\n            uint value = 3330;\n            Half target = new Half(value);\n            Assert.AreEqual((uint)target, (uint)3330);\n        }\n\n        /// <summary>\n        ///A test for Half Constructor\n        ///</summary>\n        [Test]\n        public void HalfConstructorTest()\n        {\n            Decimal value = new Decimal(-11.11);\n            Half target = new Half(value);\n            Assert.AreEqual((Decimal)target, (Decimal)(-11.10938));\n        }\n    }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Math/PolynomialTests.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class PolynomialTests : TestSuite\n    {\n        public PolynomialTests() : base() { }\n        public PolynomialTests(Options options) : base(options) { }\r\n\r\n#if !TRAVIS_CI\n\n        [Test]\n        public void TestPolynomial()\n        {\n            RootsTest3(0.04);\n            RootsTest4(0.125);\n        }\n\n        [Test]\n        public void RealRoots_LinearAscendingCoefficients()\n        {\n            var roots = new[] { -6.0, 2.0 }.RealRoots();\n\n            Assert.That(roots, Has.Length.EqualTo(1));\n            Assert.That(roots[0], Is.EqualTo(3.0).Within(1e-12));\n        }\n\n        [Test]\n        public void RealRoots_ConstantPolynomialHasNoRoots()\n        {\n            var roots = new[] { -6.0, 0.0 }.RealRoots();\n\n            Assert.That(roots, Is.Empty);\n        }\n\n        public void Run()\n        {\n            RootsTest3(0.01);\n            RootsTest4(0.05);\n        }\n\n        public void RootsTest3(double step)\n        {\n            Test.Begin(\"cubic roots tests\");\n            var range = new Range1d(-1.0, 1.0);\n            double half = 0.5 * step;\n            double epsilon = Fun.Cbrt(Constant<double>.PositiveTinyValue);\n            Report.Value(\"epsilon\", epsilon);\n            var stats = Stats<bool>.ComputeMaxMean;\n            var uniqueStats = Stats<bool>.ComputeMaxMean;\n            var multipleStats = Stats<bool>.ComputeMaxMean;\n            var residualStats = Stats<bool>.ComputeMaxMean;\n            var uniqueHisto = new Histogram(-16, -8, 8);\n            var multipleHisto = new Histogram(-16, 0, 16);\n            var uniqueResidualStats = Stats<bool>.ComputeMaxMean;\n            var multipleResidualStats = Stats<bool>.ComputeMaxMean;\n            long multipleCount = 0;\n            for (double x0 = range.Min; x0 < range.Max + half; x0 += step)\n            {\n                var p0 = new double[] { -x0, 1.0 };\n                for (double x1 = range.Min; x1 < range.Max + half; x1 += step)\n                {\n                    var p1 = new double[] { -x1, 1.0 };\n                    var p01 = Polynomial.Multiply(p0, p1);\n                    for (double x2 = range.Min; x2 < range.Max + half; x2 += step)\n                    {\n                        var p2 = new double[] { -x2, 1.0 };\n                        var p012 = Polynomial.Multiply(p01, p2);\n\n                        var t = Aardvark.Base.TupleExtensions.CreateAscending(x0, x1, x2);\n                        var exact = new double[] { t.Item1, t.Item2, t.Item3 };\n                        var roots = p012.RealRoots();\n\n                        var multiple = CountDoubles(exact, 0.0001);\n                        if (multiple > 0) ++multipleCount;\n\n                        var rootCountsOk = exact.Length == roots.Length;\n                        Test.IsTrue(rootCountsOk, \"wrong number of roots found\");\n                        if (!rootCountsOk)\n                        {\n                            using (Report.Job(\"problematic roots:\"))\n                            {\n                                Report.Line(\"exact: [\" + exact.Select(x => x.ToString()).Join(\",\") + \"]\");\n                                Report.Line(\"roots: [\" + roots.Select(x => x.ToString()).Join(\",\") + \"]\");\n                            }\n                            continue;\n                        }\n                        for (int i = 0; i < 3; i++)\n                        {\n                            var err = (exact[i] - roots[i]).Abs();\n                            Test.IsTrue(err < epsilon, \"root differs significantly from exact value {0}\", err);\n                            double res = p012.Evaluate(roots[i]).Abs();\n                            stats.Add(err);\n                            residualStats.Add(res);\n                            if (multiple == 0)\n                            {\n                                uniqueStats.Add(err);\n                                uniqueHisto.AddLog10(err);\n                                uniqueResidualStats.Add(res);\n                            }\n                            else\n                            {\n                                multipleStats.Add(err);\n                                multipleHisto.AddLog10(err);\n                                multipleResidualStats.Add(res);\n                            }\n                        }\n                    }\n                }\n            }\n            Report.Value(\"roots error\", stats);\n            Report.Value(\"unique roots error\", uniqueStats);\n            Report.Value(\"unique roots log error histogram\", uniqueHisto);\n            Report.Value(\"multiple roots error\", multipleStats);\n            Report.Value(\"multiple roots log error histogram\", multipleHisto);\n            Report.Value(\"residual error\", residualStats);\n            Report.Value(\"unique roots residual error\", uniqueResidualStats);\n            Report.Value(\"multiple residual error\", multipleResidualStats);\n            Test.End();\n        }\n\n        public void RootsTest4(double step)\n        {\n            Test.Begin(\"quartic roots tests\");\n            var range = new Range1d(-1.0, 1.0);\n            double half = 0.5 * step;\n            double epsilon = 4 * Fun.Cbrt(Constant<double>.PositiveTinyValue);\n            Report.Value(\"epsilon\", epsilon);\n            var stats = Stats<bool>.ComputeMaxMean;\n            var uniqueStats = Stats<bool>.ComputeMaxMean;\n            var multipleStats = Stats<bool>.ComputeMaxMean;\n            var uniqueHisto = new Histogram(-16, -8, 8);\n            var multipleHisto = new Histogram(-16, 0, 16);\n            var residualStats = Stats<bool>.ComputeMaxMean;\n            var uniqueResidualStats = Stats<bool>.ComputeMaxMean;\n            var multipleResidualStats = Stats<bool>.ComputeMaxMean;\n            long multipleCount = 0;\n            for (double x0 = range.Min; x0 < range.Max + half; x0 += step)\n            {\n                var p0 = new double[] { -x0, 1.0 };\n                for (double x1 = range.Min; x1 < range.Max + half; x1 += step)\n                {\n                    var p1 = new double[] { -x1, 1.0 };\n                    var p01 = Polynomial.Multiply(p0, p1);\n                    for (double x2 = range.Min; x2 < range.Max + half; x2 += step)\n                    {\n                        var p2 = new double[] { -x2, 1.0 };\n                        var p012 = p01.Multiply(p2);  \n                        var t = Aardvark.Base.TupleExtensions.CreateAscending(x0, x1, x2);\n\n                        for (double x3 = range.Min; x3 < range.Max + half; x3 += step)\n                        {\n                            var p3 = new double[] { -x3, 1.0 };\n                            var p0123 = Polynomial.Multiply(p012, p3);\n                            var exact = x3.IntoArray().MergeAscending(\n                                    new double[] { t.Item1, t.Item2, t.Item3 });\n                            var roots = p0123.RealRoots();\n\n                            var multiple = CountDoubles(exact, epsilon);\n                            if (multiple > 0) ++multipleCount;\n\n                            if (roots.Length != exact.Length)\n                            {\n                                exact = exact.WithoutDoubleRoots(epsilon);\n                                roots = roots.WithoutDoubleRoots(epsilon);\n\n                                var rootCountsOk = exact.Length == roots.Length;\n                                Test.IsTrue(rootCountsOk, \"wrong number of roots found\");\n                                if (!rootCountsOk)\n                                {\n                                    using (Report.Job(\"problematic roots:\"))\n                                    {\n                                        Report.Line(\"exact: [\" + exact.Select(x => x.ToString()).Join(\",\") + \"]\");\n                                        Report.Line(\"roots: [\" + roots.Select(x => x.ToString()).Join(\",\") + \"]\");\n                                    }\n                                    continue;\n                                }\n                            }\n\n                            for (int i = 0; i < exact.Length; i++)\n                            {\n                                var err = (exact[i] - roots[i]).Abs();\n                                Test.IsTrue(err < epsilon, \"root differs significantly from exact value {0}\", err);\n                                double res = p0123.Evaluate(roots[i]).Abs();\n                                stats.Add(err);\n                                residualStats.Add(res);\n                                if (multiple == 0)\n                                {\n                                    uniqueStats.Add(err);\n                                    uniqueHisto.AddLog10(err);\n                                    uniqueResidualStats.Add(res);\n                                }\n                                else\n                                {\n                                    multipleStats.Add(err);\n                                    multipleHisto.AddLog10(err);\n                                    multipleResidualStats.Add(res);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            Report.Value(\"roots error\", stats);\n            Report.Value(\"unique roots error\", uniqueStats);\n            Report.Value(\"unique roots log error histogram\", uniqueHisto);\n            Report.Value(\"multiple roots error\", multipleStats);\n            Report.Value(\"multiple roots log error histogram\", multipleHisto);\n            Report.Value(\"residual error\", residualStats);\n            Report.Value(\"unique roots residual error\", uniqueResidualStats);\n            Report.Value(\"multiple residual error\", multipleResidualStats);\n            Test.End();\n        }\n\n#endif\n\r\n        static int CountDoubles(double[] a, double eps)\n        {\n            int len = a.Length;\n            if (len < 2) return 0;\n            int count = 0;\n            if ((a[0] - a[1]).Abs() < eps) count++;\n            if (len < 3) return count;\n            if ((a[1] - a[2]).Abs() < eps) count++;\n            if (len < 4) return count;\n            if ((a[2] - a[3]).Abs() < eps) count++;\n            return count;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Math/QuaternionTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class QuaternionTests\n    {\n        private static readonly int iterations = 10000;\n\n        private static QuaternionD GetRandomQuat(RandomSystem rnd)\n        {\n            return new QuaternionD(rnd.UniformV4d() * 10);\n        }\n\n        [Test]\n        public static void Comparison()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < iterations; i++)\n            {\n                var q0 = GetRandomQuat(rnd);\n                var q1 = new QuaternionD((V4d)q0 + V4d.OIOI);\n\n                Assert.IsFalse(q0.Equals(q1));\n                Assert.IsFalse(q0 == q1);\n                Assert.IsTrue(q0 != q1);\n            }\n        }\n\n        [Test]\n        public static void HamiltonTest()\n        {\n            var i = QuaternionD.I;\n            var j = QuaternionD.J;\n            var k = QuaternionD.K;\n            var minus_one = new QuaternionD(-1, 0, 0, 0);\n\n            Assert.IsTrue(Fun.ApproximateEquals(i * i, minus_one, 0.00001));\n            Assert.IsTrue(Fun.ApproximateEquals(j * j, minus_one, 0.00001));\n            Assert.IsTrue(Fun.ApproximateEquals(k * k, minus_one, 0.00001));\n            Assert.IsTrue(Fun.ApproximateEquals(i * j * k, minus_one, 0.00001));\n        }\n\n        [Test]\n        public static void IdentityTest()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < iterations; i++)\n            {\n                var q = GetRandomQuat(rnd);\n                var id = QuaternionD.Identity;\n\n                Assert.IsTrue(Fun.ApproximateEquals(q * id, q, 0.00001));\n                Assert.IsTrue(Fun.ApproximateEquals(id * q, q, 0.00001));\n                Assert.IsTrue(Fun.ApproximateEquals(id * id, id, 0.00001));\n            }\n        }\n\n        [Test]\n        public static void NormalizeTest()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < iterations; i++)\n            {\n                var q = GetRandomQuat(rnd);\n\n                // Normalized property\n                var q1 = q.Normalized;\n\n                // Normalize method\n                var q2 = new QuaternionD(q);\n                Quaternion.Normalize(ref q2);\n\n                Assert.IsTrue(Fun.ApproximateEquals(q1.Norm, 1, 0.00001));\n                Assert.IsTrue(Fun.ApproximateEquals(q2.Norm, 1, 0.00001));\n            }\n        }\n\n        [Test]\n        public static void InverseTest()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < iterations; i++)\n            {\n                var q = GetRandomQuat(rnd);\n                var id = QuaternionD.Identity;\n\n                // Inverse property\n                var qi1 = q.Inverse;\n\n                // Invert method\n                var qi2 = new QuaternionD(q);\n                Quaternion.Invert(ref qi2);\n\n                Assert.IsTrue(Fun.ApproximateEquals(q * qi1, id, 0.00001));\n                Assert.IsTrue(Fun.ApproximateEquals(qi1 * q, id, 0.00001));\n                Assert.IsTrue(Fun.ApproximateEquals(q * qi2, id, 0.00001));\n                Assert.IsTrue(Fun.ApproximateEquals(qi2 * q, id, 0.00001));\n            }\n        }\n\n        [Test]\n        public static void ConjugateTest()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int n = 0; n < iterations; n++)\n            {\n                var q1 = GetRandomQuat(rnd);\n                var q2 = GetRandomQuat(rnd);\n\n                var q1_x_q2_conj = Quaternion.Conjugated(q1 * q2);\n                var q2_conj_x_q1_conj = q2.Conjugated * q1.Conjugated;\n\n                Assert.IsTrue(Fun.ApproximateEquals(q1_x_q2_conj, q2_conj_x_q1_conj, 0.00001));\n\n                var i = QuaternionD.I;\n                var j = QuaternionD.J;\n                var k = QuaternionD.K;\n                var q1_conj = -0.5 * (q1 + (i * q1 * i) + (j * q1 * j) + (k * q1 * k));\n\n                Assert.IsTrue(Fun.ApproximateEquals(q1.Conjugated, q1_conj, 0.00001));\n            }\n        }\n\n        [Test]\n        public static void NormTest()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int n = 0; n < iterations; n++)\n            {\n                var q1 = GetRandomQuat(rnd);\n                var q2 = GetRandomQuat(rnd);\n\n                var s = rnd.UniformDouble() * 100;\n                var q1_x_s_norm = Quaternion.Norm(q1 * s);\n                var q1_norm_x_s_norm = q1.Norm * s;\n\n                Assert.IsTrue(Fun.ApproximateEquals(q1_x_s_norm, q1_norm_x_s_norm, 0.00001));\n\n                var q1_x_q2_norm = Quaternion.Norm(q1 * q2);\n                var q1_norm_x_q2_norm = q1.Norm * q2.Norm;\n\n                Assert.IsTrue(Fun.ApproximateEquals(q1_x_q2_norm, q1_norm_x_q2_norm, 0.00001));\n            }\n        }\n\n        [Test]\n        [Obsolete]\n        public static void MatrixRepresentation()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < iterations; i++)\n            {\n                var q1 = GetRandomQuat(rnd);\n                var q2 = GetRandomQuat(rnd);\n\n                var m1 = (M44d)q1;\n                var m2 = (M44d)q2;\n\n                var q1_plus_q2 = (M44d)(q1 + q2);\n                var m1_plus_m2 = m1 + m2;\n\n                var q1q2 = (M44d)(q1 * q2);\n                var m1m2 = m1 * m2;\n\n                var q2q1 = (M44d)(q2 * q1);\n                var m2m1 = m2 * m1;\n\n                Assert.IsTrue(Fun.ApproximateEquals(q1_plus_q2, m1_plus_m2, 0.00001));\n                Assert.IsTrue(Fun.ApproximateEquals(q1q2, m1m2, 0.00001));\n                Assert.IsTrue(Fun.ApproximateEquals(q2q1, m2m1, 0.00001));\n            }\n        }\n\n        [Test]\n        public static void ToStringAndParse()\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < iterations; i++)\n            {\n                var q = GetRandomQuat(rnd);\n\n                var str = q.ToString();\n                var parsed = QuaternionD.Parse(str);\n\n                Assert.IsTrue(Fun.ApproximateEquals(parsed, q, 0.00001));\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Plane/PlaneTest.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class PlaneTest : TestSuite\n    {\n        public PlaneTest() { }\n        public PlaneTest(Options options) : base(options) { }\n        \n        [Test]\n        public void TransformedTrafo()\n        {\n            var rand = new RandomSystem();\n            for(int i = 0; i < 100; i++) \n            {\n                var p = new Plane3d(rand.UniformV3dDirection() * rand.UniformDouble(), rand.UniformDouble());\n                var trafo = \n                    Trafo3d.Rotation(rand.UniformV3dDirection(), rand.UniformDouble() * Constant.PiTimesTwo) *\n                    Trafo3d.Translation(rand.UniformV3d()) *\n                    Trafo3d.Scale(rand.UniformV3d()) *\n                    Trafo3d.Rotation(rand.UniformV3dDirection(), rand.UniformDouble() * Constant.PiTimesTwo) *\n                    Trafo3d.Translation(rand.UniformV3d());\n\n                var p0 = p.Point;\n                var p1 = p0 + 3.0 * p.Normal;\n\n                var h00 = p.Height(p0);\n                var h01 = p.Transformed(trafo).Height(trafo.TransformPos(p0));\n                if(!Fun.ApproximateEquals(h00, h01, 1E-8)) throw new Exception(\"heights differ\");\n                if(!Fun.ApproximateEquals(h00, 0.0, 1E-8)) throw new Exception(\"heights not zero\");\n                \n\n                var h10 = p.Height(p1);\n                var h11 = p.Transformed(trafo).Height(trafo.TransformPos(p1));\n                if(!Fun.ApproximateEquals(h10, h11, 1E-8)) throw new Exception(\"heights differ\");\n            }\n        }\n\n        [Test]\n        public void TransformedMatrix()\n        {\n            var rand = new RandomSystem();\n            for(int i = 0; i < 100; i++) \n            {\n                var p = new Plane3d(rand.UniformV3dDirection() * rand.UniformDouble() , rand.UniformDouble());\n                var trafo = \n                    M44d.Translation(rand.UniformV3d()) *\n                    M44d.Rotation(rand.UniformV3dDirection(), rand.UniformDouble() * Constant.PiTimesTwo) *\n                    M44d.Translation(rand.UniformV3d());\n\n                var p0 = p.Point;\n                var p1 = p0 + 3.0 * p.Normal;\n\n                var h00 = p.Height(p0);\n                var h01 = p.Transformed(trafo).Height(trafo.TransformPos(p0));\n                if(!Fun.ApproximateEquals(h00, h01, 1E-8)) throw new Exception(\"heights differ\");\n                if(!Fun.ApproximateEquals(h00, 0.0, 1E-8)) throw new Exception(\"heights not zero\");\n                \n\n                var h10 = p.Height(p1);\n                var h11 = p.Transformed(trafo).Height(trafo.TransformPos(p1));\n                if(!Fun.ApproximateEquals(h10, h11, 1E-8)) throw new Exception(\"heights differ\");\n            }\n        }\n\n\n        [Test]\n        public void TransformedEuclidean()\n        {\n            var rand = new RandomSystem();\n            for(int i = 0; i < 100; i++) \n            {\n                var p = new Plane3d(rand.UniformV3dDirection() * rand.UniformDouble(), rand.UniformDouble());\n                var trafo = \n                    Euclidean3d.Translation(rand.UniformV3d()) *\n                    Euclidean3d.Rotation(rand.UniformV3dDirection(), rand.UniformDouble() * Constant.PiTimesTwo);\n\n                var p0 = p.Point;\n                var p1 = p0 + 3.0 * p.Normal;\n\n                var h00 = p.Height(p0);\n                var h01 = p.Transformed(trafo).Height(trafo.TransformPos(p0));\n                if(!Fun.ApproximateEquals(h00, h01, 1E-8)) throw new Exception(\"heights differ\");\n                if(!Fun.ApproximateEquals(h00, 0.0, 1E-8)) throw new Exception(\"heights not zero\");\n                \n\n                var h10 = p.Height(p1);\n                var h11 = p.Transformed(trafo).Height(trafo.TransformPos(p1));\n                if(!Fun.ApproximateEquals(h10, h11, 1E-8)) throw new Exception(\"heights differ\");\n            }\n        }\n\n        [Test]\n        public void ProjectUnprojectTest()\n        {\n            var normal = new V3d(-3.38012399699281E-17, -0.000407306344606881, -0.999999917050768);\n            var distance = -13.109839358218661;\n            var plane = new Plane3d(normal, distance);\n\n            var testPoint = new V3d(-97.076092093139, -148.399088699813, 13.170284341045);\n\n            // NOTE: Rot3d in Euclidean3d has numerical issue\n            var projectedPoint = plane.ProjectToPlaneSpace(testPoint);\n            var unprojectedPoint = plane.Unproject(projectedPoint);\n\n            var planeTrafo = Trafo3d.FromNormalFrame(plane.Point, plane.Normal);\n            var projectedPoint2 = planeTrafo.Backward.TransformPos(testPoint).XY;\n            var unprojectedPoint2 = planeTrafo.Forward.TransformPos(projectedPoint2.XYO);\n\n            if (!((unprojectedPoint - unprojectedPoint2).Length < 0.01)) throw new Exception();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Program.cs",
    "content": "﻿using Aardvark.Base;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Text.Json;\n\nnamespace Aardvark.Tests\n{\n    public static class Program\n    {\n        [STAThread]\n        public static void Main(string[] args)\n        {\n            var o = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true };\n            Console.WriteLine(JsonSerializer.Serialize(V3d.XAxis), o);\n            Console.WriteLine(new Hull2d());\n            var h = Hull2d.Parse(new Hull2d().ToString());\n\n            //new DictTests().Run();\n            //Aardvark.Tests.Extensions.DateTimeTests.JulianDay();\n            //new Aardvark.Tests.TrafoTests().TrafoDecomposeTest();\n            //Aardvark.Tests.Rot3dTests.FromM33d();\n            //Aardvark.Tests.Rot3dTests.FromEuler();\n            //Aardvark.Tests.Rot3dTests.FromInto();\n            //new Aardvark.Tests.Images.PixImageTests().MipMapCreate1x1();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Random/RandomIEnumerableExtensionsTests.cs",
    "content": "using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Linq;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class RandomIEnumerableExtensionsTests\n    {\n        private sealed class ConstantRandom : IRandomUniform\n        {\n            private readonly double m_value;\n\n            public ConstantRandom(double value)\n            {\n                m_value = value;\n            }\n\n            public int RandomBits => 31;\n\n            public bool GeneratesFullDoubles => false;\n\n            public void ReSeed(int seed) { }\n\n            public int UniformInt() => throw new NotSupportedException();\n\n            public uint UniformUInt() => throw new NotSupportedException();\n\n            public long UniformLong() => throw new NotSupportedException();\n\n            public ulong UniformULong() => throw new NotSupportedException();\n\n            public float UniformFloat() => (float)m_value;\n\n            public float UniformFloatClosed() => (float)m_value;\n\n            public float UniformFloatOpen() => (float)m_value;\n\n            public double UniformDouble() => m_value;\n\n            public double UniformDoubleClosed() => m_value;\n\n            public double UniformDoubleOpen() => m_value;\n        }\n\n        private static readonly int[] s_values = { 1, 2, 3 };\n\n        [Test]\n        public void TakeRandomlyRejectsNaNProbabilityWhenEnumerated()\n        {\n            var exception = Assert.Throws<ArgumentOutOfRangeException>(\n                () => s_values.TakeRandomly(double.NaN).ToArray());\n\n            Assert.AreEqual(\"p\", exception.ParamName);\n        }\n\n        [Test]\n        public void TakeRandomlyWithSelectorRejectsNaNProbabilityWhenEnumerated()\n        {\n            var exception = Assert.Throws<ArgumentOutOfRangeException>(\n                () => s_values.TakeRandomly(v => v.ToString(), double.NaN).ToArray());\n\n            Assert.AreEqual(\"p\", exception.ParamName);\n        }\n\n        [TestCase(-0.01)]\n        [TestCase(1.01)]\n        public void TakeRandomlyRejectsOutOfRangeProbabilities(double p)\n        {\n            var exception = Assert.Throws<ArgumentOutOfRangeException>(\n                () => s_values.TakeRandomly(p).ToArray());\n\n            Assert.AreEqual(\"p\", exception.ParamName);\n        }\n\n        [TestCase(-0.01)]\n        [TestCase(1.01)]\n        public void TakeRandomlyWithSelectorRejectsOutOfRangeProbabilities(double p)\n        {\n            var exception = Assert.Throws<ArgumentOutOfRangeException>(\n                () => s_values.TakeRandomly(v => v.ToString(), p).ToArray());\n\n            Assert.AreEqual(\"p\", exception.ParamName);\n        }\n\n        [Test]\n        public void TakeRandomlyAcceptsBoundaryProbabilities()\n        {\n            var random = new ConstantRandom(0.5);\n\n            CollectionAssert.IsEmpty(s_values.TakeRandomly(0.0, random).ToArray());\n            CollectionAssert.AreEqual(s_values, s_values.TakeRandomly(1.0, random).ToArray());\n        }\n\n        [Test]\n        public void TakeRandomlyWithSelectorAcceptsBoundaryProbabilities()\n        {\n            var random = new ConstantRandom(0.5);\n\n            CollectionAssert.IsEmpty(s_values.TakeRandomly(v => v.ToString(), 0.0, random).ToArray());\n            CollectionAssert.AreEqual(new[] { \"1\", \"2\", \"3\" }, s_values.TakeRandomly(v => v.ToString(), 1.0, random).ToArray());\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Random/RandomSystemTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class RandomSystemTests\n    {\n        private sealed class ByteSequenceRandom : Random\n        {\n            private readonly byte[][] m_values;\n            private int m_index;\n\n            public ByteSequenceRandom(params byte[][] values)\n            {\n                m_values = values;\n            }\n\n            public override void NextBytes(byte[] buffer)\n            {\n                Array.Clear(buffer, 0, buffer.Length);\n\n                var value = m_values[m_index++];\n                Array.Copy(value, buffer, Fun.Min(value.Length, buffer.Length));\n            }\n        }\n\n        private static RandomSystem Create(params byte[][] values)\n        {\n            return new RandomSystem(0)\n            {\n                Generator = new ByteSequenceRandom(values)\n            };\n        }\n\n        private static byte[] Bytes(uint value) => BitConverter.GetBytes(value);\n\n        [Test]\n        public void UniformIntCanReturnIntMaxValue()\n        {\n            var random = Create(Bytes(uint.MaxValue));\n\n            Assert.AreEqual(int.MaxValue, random.UniformInt());\n        }\n\n        [Test]\n        public void UniformFloatClosedMapsZeroAndMaxToClosedBoundaries()\n        {\n            Assert.AreEqual(0.0f, Create(Bytes(0u)).UniformFloatClosed());\n            Assert.AreEqual(1.0f, Create(Bytes(uint.MaxValue)).UniformFloatClosed());\n        }\n\n        [Test]\n        public void UniformDoubleClosedMapsZeroAndMaxToClosedBoundaries()\n        {\n            Assert.AreEqual(0.0, Create(Bytes(0u)).UniformDoubleClosed());\n            Assert.AreEqual(1.0, Create(Bytes(uint.MaxValue)).UniformDoubleClosed());\n        }\n\n        [Test]\n        public void UniformDoubleOpenSkipsZero()\n        {\n            var value = Create(Bytes(0u), Bytes(1u)).UniformDoubleOpen();\n\n            Assert.AreEqual(1.0 / 2147483648.0, value);\n            Assert.IsTrue(value > 0.0);\n            Assert.IsTrue(value < 1.0);\n        }\n\n        [Test]\n        public void UniformDoubleOpenKeepsMaxBelowOne()\n        {\n            var value = Create(Bytes(uint.MaxValue)).UniformDoubleOpen();\n\n            Assert.AreEqual(int.MaxValue * (1.0 / 2147483648.0), value);\n            Assert.IsTrue(value > 0.0);\n            Assert.IsTrue(value < 1.0);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/RangesBoxes/BoxTests.cs",
    "content": "﻿/*\n    Copyright (C) 2017. Aardvark Platform Team. http://github.com/aardvark-platform.\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\nusing Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class BoxTests\n    {\n        #region Construction\n\n        [Test]\n        public void BoxFromEmptyArrayShouldBeInvalid()\n        {\n            var ps = Array.Empty<V3d>();\n            var bb = new Box3d(ps);\n            Assert.IsTrue(bb.IsInvalid);\n        }\n\n        [Test]\n        public void BoxFromEmptyListShouldBeInvalid()\n        {\n            List<V3d> ps = [];\n            var bb = new Box3d(ps);\n            Assert.IsTrue(bb.IsInvalid);\n        }\n\n        [Test]\n        public void RangeFromEmptyArrayShouldBeInvalid()\n        {\n            var ps = Array.Empty<double>();\n            var r = new Range1d(ps);\n            Assert.IsTrue(r.IsInvalid);\n        }\n\n        [Test]\n        public void RangeFromEmptyListShouldBeInvalid()\n        {\n            List<double> ps = [];\n            var r = new Range1d(ps);\n            Assert.IsTrue(r.IsInvalid);\n        }\n\n        [Test]\n        public void BoxFromNullArrayShouldBeInvalid()\n        {\n            V3d[] ps = null;\n            var bb = new Box3d(ps);\n            Assert.IsTrue(bb.IsInvalid);\n        }\n\n        [Test]\n        public void BoxFromNullListShouldBeInvalid()\n        {\n            List<V3d> ps = null;\n            var bb = new Box3d(ps);\n            Assert.IsTrue(bb.IsInvalid);\n        }\n\n        [Test]\n        public void RangeFromNullArrayShouldBeInvalid()\n        {\n            double[] ps = null;\n            var r = new Range1d(ps);\n            Assert.IsTrue(r.IsInvalid);\n        }\n\n        [Test]\n        public void RangeFromNullListShouldBeInvalid()\n        {\n            List<double> ps = null;\n            var r = new Range1d(ps);\n            Assert.IsTrue(r.IsInvalid);\n        }\n\n        #endregion\n\n        #region contains/intersects\n\n        [Test]\n        public void ValidBoxContainsItself()\n        {\n            var a = Box3d.Unit;\n            Assert.IsTrue(a.Contains(a));\n        }\n\n        [Test]\n        public void ValidBoxContainsValidBox()\n        {\n            var a = new Box3d(new V3d(0, 0, 0), new V3d(3, 3, 3));\n            var b = new Box3d(new V3d(1, 1, 1), new V3d(2, 2, 2));\n            Assert.IsTrue(a.Contains(b));\n        }\n\n        [Test]\n        [Ignore(\"Check for invalid box is not implemented for performance reasons.\")]\n        public void InvalidBoxDoesNotContainItself()\n        {\n            var a = Box3d.Invalid;\n            Assert.IsTrue(!a.Contains(a));\n        }\n\n        [Test]\n        [Ignore(\"Check for invalid box is not implemented for performance reasons.\")]\n        public void ValidBoxDoesNotContainInvalidBox()\n        {\n            var a = new Box3d(new V3d(0, 0, 0), new V3d(3, 3, 3));\n            var b = Box3d.Invalid;\n            Assert.IsTrue(!a.Contains(b));\n        }\n\n        [Test]\n        public void InvalidBoxDoesNotContainValidBox()\n        {\n            var a = Box3d.Invalid;\n            var b = new Box3d(new V3d(1, 1, 1), new V3d(2, 2, 2));\n            Assert.IsTrue(!a.Contains(b));\n        }\n\n\n\n        [Test]\n        public void ValidBoxIntersectsItself()\n        {\n            var a = Box3d.Unit;\n            Assert.IsTrue(a.Intersects(a));\n        }\n\n        [Test]\n        public void InvalidBoxDoesNotIntersectItself()\n        {\n            var a = Box3d.Invalid;\n            Assert.IsTrue(!a.Intersects(a));\n        }\n\n        [Test]\n        public void ValidBoxDoesNotIntersectInvalidBox()\n        {\n            var a = new Box3d(new V3d(0, 0, 0), new V3d(1, 1, 1));\n            var b = Box3d.Invalid;\n            Assert.IsTrue(!a.Intersects(b));\n        }\n\n        [Test]\n        public void InvalidBoxDoesNotIntersectValidBox()\n        {\n            var a = Box3d.Invalid;\n            var b = new Box3d(new V3d(1, 0, 0), new V3d(2, 1, 1));\n            Assert.IsTrue(!a.Intersects(b));\n        }\n\n        [Test]\n        public void TouchingBoxesDoNotIntersect()\n        {\n            var a = new Box3d(new V3d(0, 0, 0), new V3d(1, 1, 1));\n            var b = new Box3d(new V3d(1, 0, 0), new V3d(2, 1, 1));\n            Assert.IsTrue(!a.Intersects(b));\n        }\n\n        [Test]\n        public void BoxDoesIntersectItself()\n        {\n            var a = new Box3d(new V3d(1, 2, 3), new V3d(4, 5, 6));\n            Assert.IsTrue(a.Intersects(a));\n        }\n\n        [Test]\n        public void ContainedBoxesDoIntersect()\n        {\n            var a = new Box3d(new V3d(0, 0, 0), new V3d(3, 3, 3));\n            var b = new Box3d(new V3d(1, 1, 1), new V3d(2, 2, 2));\n            Assert.IsTrue(a.Intersects(b));\n        }\n\n        #endregion\n\n        #region Transformed\n\n        static Box3d Transform1(Box3d box, M44d trafo)\n        {\n            var res = Box3d.Invalid;\n            if (!box.IsInvalid)\n            {\n                res.ExtendBy(trafo.TransformPos((V3d)box.Min));\n                res.ExtendBy(trafo.TransformPos((V3d)new V3d(box.Max.X, box.Min.Y, box.Min.Z)));\n                res.ExtendBy(trafo.TransformPos((V3d)new V3d(box.Min.X, box.Max.Y, box.Min.Z)));\n                res.ExtendBy(trafo.TransformPos((V3d)new V3d(box.Max.X, box.Max.Y, box.Min.Z)));\n                res.ExtendBy(trafo.TransformPos((V3d)new V3d(box.Min.X, box.Min.Y, box.Max.Z)));\n                res.ExtendBy(trafo.TransformPos((V3d)new V3d(box.Max.X, box.Min.Y, box.Max.Z)));\n                res.ExtendBy(trafo.TransformPos((V3d)new V3d(box.Min.X, box.Max.Y, box.Max.Z)));\n                res.ExtendBy(trafo.TransformPos((V3d)box.Max));\n            }\n            return res;\n        }\n\n        static Box3d Transform2(Box3d box, M44d trafo)\n        {\n            var xa = trafo.C0.XYZ * box.Min.X;\n            var xb = trafo.C0.XYZ * box.Max.X;\n\n            var ya = trafo.C1.XYZ * box.Min.Y;\n            var yb = trafo.C1.XYZ * box.Max.Y;\n\n            var za = trafo.C2.XYZ * box.Min.Z;\n            var zb = trafo.C2.XYZ * box.Max.Z;\n\n            return new Box3d(\n                Fun.Min(xa, xb) + Fun.Min(ya, yb) + Fun.Min(za, zb) + trafo.C3.XYZ,\n                Fun.Max(xa, xb) + Fun.Max(ya, yb) + Fun.Max(za, zb) + trafo.C3.XYZ);\n        }\n\n        static Box3d Transform3(Box3d box, M44d trafo)\n        {\n            var min = new V3d(trafo.M03, trafo.M13, trafo.M23);\n            var max = min;\n            for (int i = 0; i < 3; i++)\n                for (int j = 0; j < 3; j++)\n                {\n                    var a = trafo[i, j];\n                    var av = a * box.Min[j];\n                    var bv = a * box.Max[j];\n                    if (av < bv)\n                    {\n                        min[i] += av;\n                        max[i] += bv;\n                    }\n                    else\n                    {\n                        min[i] += bv;\n                        max[i] += av;\n                    }\n                }\n            return new Box3d(min, max);\n        }\n\n        static Box3d Transform4(Box3d box, M44d trafo)\n        {\n            //if (!box.IsValid) return Box3d.Invalid;\n            //if (box.IsInvalid) return Box3d.Invalid;\n            var t = new V3d(trafo.M03, trafo.M13, trafo.M23);\n            var res = new Box3d(t, t);\n            // unrolled\n            double av, bv;\n            av = trafo.M00 * box.Min.X;\n            bv = trafo.M00 * box.Max.X;\n            if (av < bv)\n            {\n                res.Min.X += av;\n                res.Max.X += bv;\n            }\n            else\n            {\n                res.Min.X += bv;\n                res.Max.X += av;\n            }\n\n            av = trafo.M01 * box.Min.Y;\n            bv = trafo.M01 * box.Max.Y;\n            if (av < bv)\n            {\n                res.Min.X += av;\n                res.Max.X += bv;\n            }\n            else\n            {\n                res.Min.X += bv;\n                res.Max.X += av;\n            }\n\n            av = trafo.M02 * box.Min.Z;\n            bv = trafo.M02 * box.Max.Z;\n            if (av < bv)\n            {\n                res.Min.X += av;\n                res.Max.X += bv;\n            }\n            else\n            {\n                res.Min.X += bv;\n                res.Max.X += av;\n            }\n\n            av = trafo.M10 * box.Min.X;\n            bv = trafo.M10 * box.Max.X;\n            if (av < bv)\n            {\n                res.Min.Y += av;\n                res.Max.Y += bv;\n            }\n            else\n            {\n                res.Min.Y += bv;\n                res.Max.Y += av;\n            }\n\n            av = trafo.M11 * box.Min.Y;\n            bv = trafo.M11 * box.Max.Y;\n            if (av < bv)\n            {\n                res.Min.Y += av;\n                res.Max.Y += bv;\n            }\n            else\n            {\n                res.Min.Y += bv;\n                res.Max.Y += av;\n            }\n\n            av = trafo.M12 * box.Min.Z;\n            bv = trafo.M12 * box.Max.Z;\n            if (av < bv)\n            {\n                res.Min.Y += av;\n                res.Max.Y += bv;\n            }\n            else\n            {\n                res.Min.Y += bv;\n                res.Max.Y += av;\n            }\n\n            av = trafo.M20 * box.Min.X;\n            bv = trafo.M20 * box.Max.X;\n            if (av < bv)\n            {\n                res.Min.Z += av;\n                res.Max.Z += bv;\n            }\n            else\n            {\n                res.Min.Z += bv;\n                res.Max.Z += av;\n            }\n\n            av = trafo.M21 * box.Min.Y;\n            bv = trafo.M21 * box.Max.Y;\n            if (av < bv)\n            {\n                res.Min.Z += av;\n                res.Max.Z += bv;\n            }\n            else\n            {\n                res.Min.Z += bv;\n                res.Max.Z += av;\n            }\n\n            av = trafo.M22 * box.Min.Z;\n            bv = trafo.M22 * box.Max.Z;\n            if (av < bv)\n            {\n                res.Min.Z += av;\n                res.Max.Z += bv;\n            }\n            else\n            {\n                res.Min.Z += bv;\n                res.Max.Z += av;\n            }\n\n            return res;\n        }\n\n        [Test]\n        public void BoxTransformTest()\n        {\n            var cnt = 10000;\n            var rnd = new RandomSystem(1);\n            var trafos = new M44d[cnt].SetByIndex(i => new M44d(rnd.CreateUniformDoubleArray(16)));\n            //var trafos = new M44d[cnt].SetByIndex(i => M44d.FromBasis(rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d(), rnd.UniformV3d()));\n            //var trafos = new M44d[cnt].SetByIndex(i => M44d.Translation(rnd.UniformV3d()));\n            //var trafos = new M44d[cnt].SetByIndex(i => M44d.Rotation(rnd.UniformV3d()) * M44d.Translation(rnd.UniformV3d()));\n            var boxes = new Box3d[cnt].SetByIndex(i => Box3d.FromCenterAndSize(rnd.UniformV3d(), rnd.UniformV3d()));\n            var refBoxes = boxes.Map((b, i) => Transform1(b, trafos[i]));\n\n            for (int j = 0; j < 10; j++)\n            {\n                Report.BeginTimed(\"Transform Boxes Aardvark\");\n                for (int i = 0; i < trafos.Length; i++)\n                {\n                    var test = boxes[i].Transformed(trafos[i]);\n                    Assert.IsTrue(test.Min.ApproximateEquals(refBoxes[i].Min, 1e-7) && test.Max.ApproximateEquals(refBoxes[i].Max, 1e-7));\n                }\n                Report.End();\n\n                Report.BeginTimed(\"Transform Boxes1\");\n                for (int i = 0; i < trafos.Length; i++)\n                {\n                    var test = Transform1(boxes[i], trafos[i]);\n                    Assert.IsTrue(test.Min.ApproximateEquals(refBoxes[i].Min, 1e-7) && test.Max.ApproximateEquals(refBoxes[i].Max, 1e-7));\n                }\n                Report.End();\n\n\n                Report.BeginTimed(\"Transform Boxes2\");\n                for (int i = 0; i < trafos.Length; i++)\n                {\n                    var test = Transform2(boxes[i], trafos[i]);\n                    Assert.IsTrue(test.Min.ApproximateEquals(refBoxes[i].Min, 1e-7) && test.Max.ApproximateEquals(refBoxes[i].Max, 1e-7));\n                }\n                Report.End();\n\n                Report.BeginTimed(\"Transform Boxes3\");\n                for (int i = 0; i < trafos.Length; i++)\n                {\n                    var test = Transform3(boxes[i], trafos[i]);\n                    Assert.IsTrue(test.Min.ApproximateEquals(refBoxes[i].Min, 1e-7) && test.Max.ApproximateEquals(refBoxes[i].Max, 1e-7));\n                }\n                Report.End();\n\n                Report.BeginTimed(\"Transform Boxes4\");\n                for (int i = 0; i < trafos.Length; i++)\n                {\n                    var test = Transform4(boxes[i], trafos[i]);\n                    Assert.IsTrue(test.Min.ApproximateEquals(refBoxes[i].Min, 1e-7) && test.Max.ApproximateEquals(refBoxes[i].Max, 1e-7));\n                }\n                Report.End();\n            }\n\n        }\n\n        [Test]\n        public void TransformedEmpty()\n        {\n            var rnd = new RandomSystem(123);\n            for (int i = 0; i < 1000; i++)\n            {\n                var mat = new M44d(rnd.CreateUniformDoubleArray(16));\n                var test = Box3d.Invalid.Transformed(mat);\n                Assert.True(test.IsEmpty);\n                Assert.False(test.Max.AnyNaN || test.Min.AnyNaN || test.IsNonEmpty);\n            }\n        }\n\n        [Test]\n        public void TransformedInfinite()\n        {\n            var rnd = new RandomSystem(123);\n            for (int i = 0; i < 1000; i++)\n            {\n                var mat = new M44d(rnd.CreateUniformDoubleArray(16));\n                var test = Box3d.Infinite.Transformed(mat);\n                Assert.False(test.Max.AnyNaN || test.Min.AnyNaN || test.IsEmpty);\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/RangesBoxes/Cell2dTests.cs",
    "content": "﻿/*\n    Copyright (C) 2017. Aardvark Platform Team. http://github.com/aardvark-platform.\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\nusing Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class Cell2dTests\n    {\n        #region creation\n\n        [Test]\n        public void UnitCell()\n        {\n            Assert.IsTrue(Cell2d.Unit.X == 0 && Cell2d.Unit.Y == 0);\n            Assert.IsTrue(Cell2d.Unit.Exponent == 0);\n            Assert.IsTrue(Cell2d.Unit.BoundingBox == Box2d.Unit);\n        }\n\n        [Test]\n        public void CanCreateCell()\n        {\n            var a = new Cell2d(1, 2, -1);\n            Assert.IsTrue(a.X == 1 && a.Y == 2 && a.Exponent == -1);\n        }\n\n        [Test]\n        public void CanCreateCell2()\n        {\n            var a = new Cell2d(1, 2, -1);\n            var b = new Cell2d(new V2l(1, 2), -1);\n            Assert.IsTrue(a == b);\n        }\n\n        [Test]\n        public void CanCreateCell_CenteredAtOrigin()\n        {\n            var a = new Cell2d(1).BoundingBox;\n            Assert.IsTrue(a.Min == new V2d(-1, -1));\n            Assert.IsTrue(a.Max == new V2d(+1, +1));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBox_Centered()\n        {\n            var a = new Cell2d(new Box2d(new V2d(-1.3, 0), new V2d(0.1, 1)));\n            Assert.IsTrue(a == new Cell2d(2));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBox_Centered_PowerOfTwo()\n        {\n            var a = new Cell2d(new Box2d(new V2d(-1, -1), new V2d(0.1, 1)));\n            Assert.IsTrue(a == new Cell2d(1));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBox()\n        {\n            var a = new Cell2d(new Box2d(new V2d(0.1, 0), new V2d(1.3, 1)));\n            Assert.IsTrue(a == new Cell2d(0, 0, 1));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBoxWithMaxIncludingOrigin()\n        {\n            var box = new Box2d(new V2d(4, -0.5), new V2d(4.5, 0));\n            var cell = new Cell2d(box);\n            Assert.IsTrue(cell.BoundingBox.Contains(box));\n        }\n\n        [Test]\n        public void CellBoundingBoxContainsBoxTheCellWasCreatedFrom()\n        {\n            var bb = new Box2d(new V2d(-7163.84, 256990.58), new V2d(-7146.66, 257016.8));\n            var cell = new Cell2d(bb);\n            var cellBoundingBox = cell.BoundingBox;\n            Assert.IsTrue(cellBoundingBox.Contains(bb));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBox_PowerOfTwo()\n        {\n            var a = new Cell2d(new Box2d(new V2d(0, 0), new V2d(2, 2)));\n            Assert.IsTrue(a == new Cell2d(0, 0, 2));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBox_Point()\n        {\n            var bb = new Box2d(new V2d(1.3), new V2d(1.3));\n            var a = new Cell2d(bb);\n            Assert.IsTrue(a.BoundingBox.ApproximateEquals(bb));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBox_Point_PowerOfTwo()\n        {\n            var bb = new Box2d(new V2d(long.MaxValue >> 1), new V2d(long.MaxValue >> 1));\n            var a = new Cell2d(bb);\n            // for cells far far away, floating point precision DOES matter,\n            // so we can't use the default tolerance of PositiveTinyValue.\n            var tolerance = Math.Pow(2.0, a.Exponent);\n            Assert.IsTrue(a.BoundingBox.ApproximateEquals(bb, tolerance));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBoxf()\n        {\n            var a = new Cell2d(new Box2f(new V2f(-1.3, 0), new V2f(0.1, 1)));\n            Assert.IsTrue(a == new Cell2d(2));\n        }\n\n        [Test]\n        public void CanCreateCell_FromV2ds()\n        {\n            var a = new Cell2d(new[] { new V2d(-1.3, 0), new V2d(0.1, 1) });\n            Assert.IsTrue(a == new Cell2d(2));\n        }\n\n        [Test]\n        public void CanCreateCell_FromV2fs()\n        {\n            var a = new Cell2d(new[] { new V2f(-1.3, 0), new V2f(0.1, 1) });\n            Assert.IsTrue(a == new Cell2d(2));\n        }\n\n        [Test]\n        public void CanCreateCell_FromV2dEnumerable()\n        {\n            var a = new Cell2d((IEnumerable<V2d>)new[] { new V2d(-1.3, 0), new V2d(0.1, 1) });\n            Assert.IsTrue(a == new Cell2d(2));\n        }\n\n        [Test]\n        public void CanCreateCell_FromV2fEnumerable()\n        {\n            var a = new Cell2d((IEnumerable<V2f>)new[] { new V2f(-1.3, 0), new V2f(0.1, 1) });\n            Assert.IsTrue(a == new Cell2d(2));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBox2()\n        {\n            var a = new Cell2d(new Box2d(new V2d(0.1, 0.8), new V2d(0.8, 0.9)));\n            Assert.IsTrue(a == new Cell2d(0, 0, 0));\n        }\n\n        [Test]\n        public void CanCreateCell_FromBox3()\n        {\n            var a = new Cell2d(new Box2d(new V2d(1.1, 0.8), new V2d(1.8, 0.9)));\n            Assert.IsTrue(a == new Cell2d(1, 0, 0));\n        }\n\n        [Test]\n        public void CanCreateCell_FromPoint()\n        {\n            var p = new V2d(0.1, 0.2);\n            var a = new Cell2d(p);\n            Assert.IsTrue(a.BoundingBox.Contains(p));\n        }\n\n        [Test]\n        public void CanCreateCell_FromPointAtPowerOfTwoLocation()\n        {\n            for (var e = -1024; e <= 1023; e++)\n            {\n                var p = new V2d(Math.Pow(2.0, e));\n                var a = new Cell2d(p);\n                Assert.IsTrue(a.BoundingBox.Contains(p));\n            }\n        }\n\n        [Test]\n        public void CanCreateCell_FromPoint_Origin()\n        {\n            var p = V2d.Zero;\n            var a = new Cell2d(p);\n            Assert.IsTrue(a.BoundingBox.Contains(p));\n        }\n\n        [Test]\n        public void CanCreateCell_FromPoint_MaxNegative()\n        {\n            var p = new V2d(-double.MaxValue, -double.MaxValue);\n            var a = new Cell2d(p);\n            Assert.IsTrue(a.BoundingBox.Contains(p));\n        }\n\n        [Test]\n        public void CanCreateCell_FromPoint_MaxPositive()\n        {\n            var p = new V2d(double.MaxValue, double.MaxValue);\n            var a = new Cell2d(p);\n            Assert.IsTrue(a.BoundingBox.Contains(p));\n        }\n\n        #endregion\n\n        #region serialization\n        \n        [Test]\n        public void CanSerializeCellToBinary()\n        {\n            var a = new Cell2d(1, 2, -1);\n            _ = a.ToByteArray();\n        }\n\n        [Test]\n        public void CanDeserializeCellFromBinary()\n        {\n            var a = new Cell2d(1, 2, -1);\n            var buffer = a.ToByteArray();\n\n            var b = Cell2d.Parse(buffer);\n\n            Assert.IsTrue(a == b);\n        }\n\n        [Test]\n        public void CanDeserializeCellFromString()\n        {\n            var a = new Cell2d(1, 2, -1);\n            var s = a.ToString();\n\n            var b = Cell2d.Parse(s);\n\n            Assert.IsTrue(a == b);\n        }\n\n        //[Test]\n        //public void CanRoundtripCell2dWithSystemTextJsonAndNewtonsoft()\n        //{\n        //    var a = new Cell2d(1, 2, -1);\n        //    var json = System.Text.Json.JsonSerializer.Serialize(a);\n        //    var b = Newtonsoft.Json.JsonConvert.DeserializeObject<Cell2d>(json);\n        //    Assert.IsTrue(a == b);\n        //}\n\n        [Test]\n        public void CanRoundtripCell2dWithNewtonsoft()\n        {\n            var a = new Cell2d(1, 2, -1);\n            var json = Newtonsoft.Json.JsonConvert.SerializeObject(a);\n            var b = Newtonsoft.Json.JsonConvert.DeserializeObject<Cell2d>(json);\n            Assert.IsTrue(a == b);\n        }\n\n        [Test]\n        public void CanRoundtripCell2dWithNewtonsoftAndSystemTextJson()\n        {\n            var a = new Cell2d(1, 2, -1);\n            var json = Newtonsoft.Json.JsonConvert.SerializeObject(a);\n            var b = System.Text.Json.JsonSerializer.Deserialize<Cell2d>(json);\n            Assert.IsTrue(a == b);\n        }\n\n        #endregion\n\n        #region CellIsCenteredAtOrigin\n\n        [Test]\n        public void CellIsCenteredAtOrigin()\n        {\n            var a = new Cell2d(10);\n            Assert.IsTrue(a.IsCenteredAtOrigin);\n        }\n\n        [Test]\n        public void CellIsNotCenteredAtOrigin()\n        {\n            var a = new Cell2d(1, 2, 4);\n            Assert.IsTrue(!a.IsCenteredAtOrigin);\n        }\n\n        #endregion\n\n        #region IsValid, IsInvalid\n\n        [Test]\n        public void CellIsValidInvalid()\n        {\n            var a = Cell2d.Invalid;\n            Assert.IsTrue(a.IsInvalid);\n            Assert.IsFalse(a.IsValid);\n\n            var b = Cell2d.Unit;\n            Assert.IsTrue(b.IsValid);\n            Assert.IsFalse(b.IsInvalid);\n        }\n\n        #endregion\n\n        #region equality\n\n        [Test]\n        public void CellIsEqualToItself()\n        {\n            var a = new Cell2d(1, 2, -1);\n\n            Assert.IsTrue(a.Equals((object)a));\n            Assert.IsTrue(a.Equals(a));\n        }\n\n        [Test]\n        public void Cell_Equality()\n        {\n            var a = new Cell2d(1, 2, -1);\n            var b = new Cell2d(1, 2, -1);\n\n            Assert.IsTrue(a.Equals((object)b));\n            Assert.IsTrue(a.Equals(b));\n            Assert.IsTrue(a == b);\n        }\n\n        [Test]\n        public void Cell_Inequality()\n        {\n            Assert.IsTrue(new Cell2d(0, 0, 0) != new Cell2d(1, 0, 0));\n            Assert.IsTrue(new Cell2d(0, 0, 0) != new Cell2d(0, 1, 0));\n            Assert.IsTrue(new Cell2d(0, 0, 0) != new Cell2d(0, 0, 1));\n        }\n\n        [Test]\n        public void Cell_GetHashCode()\n        {\n            var a = new Cell2d(1, 0, 0).GetHashCode();\n            var b = new Cell2d(0, 1, 0).GetHashCode();\n            var c = new Cell2d(0, 0, 0).GetHashCode();\n            var d = new Cell2d(0, 0, 1).GetHashCode();\n\n            Assert.IsTrue(a != b && a != c && a != d && b != c && b != d && c != d);\n        }\n\n        #endregion\n\n        #region ToString\n\n        [Test]\n        public void Cell_ToString()\n        {\n            var s = new Cell2d(1, 2, -1).ToString();\n            Assert.IsTrue(s == \"[1, 2, -1]\");\n        }\n\n        #endregion\n\n        #region BoundingBox\n\n        [Test]\n        public void Cell_Box2d()\n        {\n            Assert.IsTrue(new Cell2d(0, 0, 0).BoundingBox   == new Box2d(new V2d(0, 0),    new V2d(1, 1)));\n            Assert.IsTrue(new Cell2d(0, 0, 1).BoundingBox   == new Box2d(new V2d(0, 0),    new V2d(2, 2)));\n            Assert.IsTrue(new Cell2d(1, 2, 4).BoundingBox   == new Box2d(new V2d(16, 32),  new V2d(32, 48)));\n            Assert.IsTrue(new Cell2d(0, 0, -1).BoundingBox  == new Box2d(new V2d(0, 0),    new V2d(0.5, 0.5)));\n            Assert.IsTrue(new Cell2d(-1, 0, -1).BoundingBox == new Box2d(new V2d(-0.5, 0), new V2d(0.0, 0.5)));\n        }\n\n        #endregion\n\n        #region children\n\n        [Test]\n        public void Cell_Centered_Children()\n        {\n            var xs = new Cell2d(1).Children;\n            Assert.IsTrue(xs[0] == new Cell2d(-1, -1, 0));\n            Assert.IsTrue(xs[1] == new Cell2d( 0, -1, 0));\n            Assert.IsTrue(xs[2] == new Cell2d(-1,  0, 0));\n            Assert.IsTrue(xs[3] == new Cell2d( 0,  0, 0));\n        }\n\n        [Test]\n        public void Cell_Children1()\n        {\n            var xs = new Cell2d(0, 0, 0).Children;\n            Assert.IsTrue(xs[0] == new Cell2d(0, 0, -1));\n            Assert.IsTrue(xs[1] == new Cell2d(1, 0, -1));\n            Assert.IsTrue(xs[2] == new Cell2d(0, 1, -1));\n            Assert.IsTrue(xs[3] == new Cell2d(1, 1, -1));\n        }\n\n        [Test]\n        public void Cell_Children2()\n        {\n            var xs = new Cell2d(-2, 0, 1).Children;\n            Assert.IsTrue(xs[0] == new Cell2d(-4, 0, 0));\n            Assert.IsTrue(xs[1] == new Cell2d(-3, 0, 0));\n            Assert.IsTrue(xs[2] == new Cell2d(-4, 1, 0));\n            Assert.IsTrue(xs[3] == new Cell2d(-3, 1, 0));\n        }\n\n        #endregion\n\n        #region parent\n\n        [Test]\n        public void Cell_Centered_Parent()\n        {\n            Assert.IsTrue(new Cell2d(-1).Parent == new Cell2d(0));\n            Assert.IsTrue(new Cell2d(0).Parent  == new Cell2d(1));\n            Assert.IsTrue(new Cell2d(1).Parent  == new Cell2d(2));\n        }\n\n        [Test]\n        public void Cell_Parent1()\n        {\n            Assert.IsTrue(new Cell2d(0, 0, 0).Parent == new Cell2d(0, 0, 1));\n            Assert.IsTrue(new Cell2d(1, 0, 0).Parent == new Cell2d(0, 0, 1));\n            Assert.IsTrue(new Cell2d(0, 1, 0).Parent == new Cell2d(0, 0, 1));\n            Assert.IsTrue(new Cell2d(1, 1, 0).Parent == new Cell2d(0, 0, 1));\n        }\n\n        [Test]\n        public void Cell_Parent2()\n        {\n            Assert.IsTrue(new Cell2d(-1, 0, 0).Parent == new Cell2d(-1, 0, 1));\n            Assert.IsTrue(new Cell2d(-2, 0, 0).Parent == new Cell2d(-1, 0, 1));\n            Assert.IsTrue(new Cell2d(-3, 0, 0).Parent == new Cell2d(-2, 0, 1));\n            Assert.IsTrue(new Cell2d(-4, 0, 0).Parent == new Cell2d(-2, 0, 1));\n        }\n\n        #endregion\n\n        #region common root cell\n\n        [Test]\n        public void Cell_CommonRootCell_1()\n        {\n            var r = Cell2d.GetCommonRoot(new Cell2d(1, 2, 3), new Cell2d(1, 2, 3));\n            Assert.IsTrue(r == new Cell2d(1, 2, 3));\n        }\n\n        [Test]\n        public void Cell_CommonRootCell_2()\n        {\n            var r = Cell2d.GetCommonRoot(new Cell2d(-5), new Cell2d(-5));\n            Assert.IsTrue(r == new Cell2d(-5));\n        }\n\n        [Test]\n        public void Cell_CommonRootCell_3()\n        {\n            var r = Cell2d.GetCommonRoot(new Cell2d(3), new Cell2d(2));\n            Assert.IsTrue(r == new Cell2d(3));\n            r = Cell2d.GetCommonRoot(new Cell2d(2), new Cell2d(3));\n            Assert.IsTrue(r == new Cell2d(3));\n        }\n\n        [Test]\n        public void Cell_CommonRootCell_4a()\n        {\n            var r = Cell2d.GetCommonRoot(new Cell2d(1), new Cell2d(0, 0, 0));\n            Assert.IsTrue(r == new Cell2d(1));\n            r = Cell2d.GetCommonRoot(new Cell2d(0, 0, 0), new Cell2d(1));\n            Assert.IsTrue(r == new Cell2d(1));\n        }\n\n        [Test]\n        public void Cell_CommonRootCell_4b()\n        {\n            var r = Cell2d.GetCommonRoot(new Cell2d(1), new Cell2d(-1, 0, 0));\n            Assert.IsTrue(r == new Cell2d(1));\n            r = Cell2d.GetCommonRoot(new Cell2d(0, -1, 0), new Cell2d(1));\n            Assert.IsTrue(r == new Cell2d(1));\n        }\n\n        [Test]\n        public void Cell_CommonRootCell_5()\n        {\n            var r = Cell2d.GetCommonRoot(new Cell2d(0, 0, 0), new Cell2d(1, 0, -1));\n            Assert.IsTrue(r == new Cell2d(0, 0, 0));\n            r = Cell2d.GetCommonRoot(new Cell2d(0, 0, 0), new Cell2d(1, -3, -5));\n            Assert.IsTrue(r == new Cell2d(1));\n        }\n\n        [Test]\n        public void Cell_CommonRootCell_6()\n        {\n            var r = Cell2d.GetCommonRoot(new Cell2d(0, 0, 0), new Cell2d(1, 0, 0), new Cell2d(0));\n            Assert.IsTrue(r == new Cell2d(2));\n        }\n\n        [Test]\n        public void Cell_CommonRootCell_7()\n        {\n            var r = Cell2d.GetCommonRoot(new Cell2d(3, 3, 6), new Cell2d(1, -1, 7));\n            Assert.IsTrue(r == new Cell2d(9));\n        }\n\n        #endregion\n\n        #region touches origin\n\n        [Test]\n        public void CenteredCellDoesNotTouchOrigin()\n        {\n            Assert.IsTrue(new Cell2d(-1).TouchesOrigin == false);\n            Assert.IsTrue(new Cell2d(0).TouchesOrigin == false);\n            Assert.IsTrue(new Cell2d(1).TouchesOrigin == false);\n        }\n\n        [Test]\n        public void CellTouchOrigin()\n        {\n            Assert.IsTrue(new Cell2d( 0,  0, 0).TouchesOrigin == true);\n            Assert.IsTrue(new Cell2d(-1,  0, 0).TouchesOrigin == true);\n            Assert.IsTrue(new Cell2d( 0, -1, 0).TouchesOrigin == true);\n            Assert.IsTrue(new Cell2d(-1, -1, 0).TouchesOrigin == true);\n\n            Assert.IsTrue(new Cell2d(1, 0, 0).TouchesOrigin == false);\n            Assert.IsTrue(new Cell2d(0, 1, 0).TouchesOrigin == false);\n            Assert.IsTrue(new Cell2d(1, 1, 0).TouchesOrigin == false);\n        }\n\n        #endregion\n\n        #region contains/intersects\n\n        [Test]\n        public void Cell_Contains()\n        {\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(-1, -1, 7)) == true);\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(-1,  0, 7)) == true);\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d( 0, -1, 7)) == true);\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d( 0,  0, 7)) == true);\n\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(-2, -2, 7)) == false);\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(-2,  1, 7)) == false);\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d( 1, -2, 7)) == false);\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d( 1,  1, 7)) == false);\n\n            Assert.IsTrue(new Cell2d(9).Contains(new Cell2d(-2, -2, 7)) == true);\n            Assert.IsTrue(new Cell2d(9).Contains(new Cell2d(-2,  1, 7)) == true);\n            Assert.IsTrue(new Cell2d(9).Contains(new Cell2d( 1, -2, 7)) == true);\n            Assert.IsTrue(new Cell2d(9).Contains(new Cell2d( 1,  1, 7)) == true);\n\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(3, 3, 6)) == false);\n            Assert.IsTrue(new Cell2d(9).Contains(new Cell2d(3, 3, 6)) == true);\n\n\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(7)) == true);\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(8)) == true);\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(9)) == false);\n\n            Assert.IsTrue(new Cell2d(8).Contains(new Cell2d(0, 0, 8)) == false);\n\n            Assert.IsTrue(new Cell2d(0, 0, 8).Contains(new Cell2d(7)) == false);\n\n\n            Assert.IsTrue(new Cell2d(0, 0, 8).Contains(new Cell2d(0, 0, 7)) == true);\n            Assert.IsTrue(new Cell2d(0, 0, 8).Contains(new Cell2d(1, 0, 7)) == true);\n            Assert.IsTrue(new Cell2d(0, 0, 8).Contains(new Cell2d(2, 0, 7)) == false);\n        }\n        [Test]\n        public void Cell_InsideOutside_ContainsEqual()\n        {\n            var a = new Cell2d(1, 2, 4);\n            var b = new Cell2d(1, 2, 4);\n            Assert.IsTrue(a.Contains(b));\n            Assert.IsTrue(b.Contains(a));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Inside()\n        {\n            var a = new Cell2d(0, 0, 0);\n            var b = new Cell2d(1, 2,-4);\n            Assert.IsTrue(a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_InsideTouching()\n        {\n            var a = new Cell2d(0, 0, 0);\n            var b = new Cell2d(0, 0, -1);\n            Assert.IsTrue(a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Outside()\n        {\n            var a = new Cell2d(0, 0, 0);\n            var b = new Cell2d(2, 0, 0);\n            Assert.IsTrue(!a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_OutsideTouching()\n        {\n            var a = new Cell2d(0, 0, 0);\n            var b = new Cell2d(1, 0, 0);\n            Assert.IsTrue(!a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Centered1()\n        {\n            var a = new Cell2d(1);\n            Assert.IsTrue(a.Contains(new Cell2d(-1, -1, 0)));\n            Assert.IsTrue(a.Contains(new Cell2d(0, -1, 0)));\n            Assert.IsTrue(a.Contains(new Cell2d(-1, 0, 0)));\n            Assert.IsTrue(a.Contains(new Cell2d(0, 0, 0)));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Centered2()\n        {\n            var a = new Cell2d(1);\n            var b = new Cell2d(0);\n            Assert.IsTrue(a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Centered3()\n        {\n            var a = new Cell2d(1);\n            var b = new Cell2d(0);\n            Assert.IsTrue(!b.Contains(a));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Centered4()\n        {\n            var a = new Cell2d(2);\n            var b = new Cell2d(2);\n            Assert.IsTrue(a.Contains(b));\n            Assert.IsTrue(b.Contains(a));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Centered5()\n        {\n            var a = new Cell2d(2);\n            var b = new Cell2d(0, 0, 2);\n            Assert.IsTrue(!a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Centered6()\n        {\n            var a = new Cell2d(2);\n            var b = new Cell2d(10, 10, 1);\n            Assert.IsTrue(!a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Centered7()\n        {\n            var a = new Cell2d(2);\n            var b = new Cell2d(0, 0, 3);\n            Assert.IsTrue(!a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_Centered8()\n        {\n            var a = new Cell2d(0, 0, 2);\n            var b = new Cell2d(1);\n            Assert.IsTrue(!a.Contains(b));\n        }\n        \n        [Test]\n        public void Cell_InsideOutside_Intersects_Itself_1()\n        {\n            var a = Cell2d.Unit;\n            Assert.IsTrue(a.Intersects(a));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_Itself_2()\n        {\n            var a = new Cell2d(1, -2, -4);\n            Assert.IsTrue(a.Intersects(a));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_Itself_3()\n        {\n            var a = new Cell2d(1, 12345678910111213, 2);\n            Assert.IsTrue(a.Intersects(a));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_Itself_4()\n        {\n            var a = new Cell2d(7);\n            Assert.IsTrue(a.Intersects(a));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_Itself_5()\n        {\n            var a = new Cell2d(-123456789);\n            Assert.IsTrue(a.Intersects(a));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_Contained_NotTouching()\n        {\n            var a = new Cell2d(0, 0, 2);\n            var b = new Cell2d(1, 2, 0);\n            Assert.IsTrue(a.Intersects(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_InsideTouching()\n        {\n            Assert.IsTrue(new Cell2d(0, 0, 0).Intersects(new Cell2d(0, 0, -1)));\n            Assert.IsTrue(new Cell2d(0, 0, 0).Intersects(new Cell2d(1, 0, -1)));\n            Assert.IsTrue(new Cell2d(0, 0, 0).Intersects(new Cell2d(0, 1, -1)));\n            Assert.IsTrue(new Cell2d(0, 0, 0).Intersects(new Cell2d(1, 1, -1)));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_OutsideTouchingMin()\n        {\n            var a = new Cell2d(2, 0, 0);\n            var b = new Cell2d(1, 0, 0);\n            Assert.IsTrue(!a.Intersects(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_OutsideTouchingMax()\n        {\n            var a = new Cell2d(1, 0, 0);\n            var b = new Cell2d(2, 0, 0);\n            Assert.IsTrue(!a.Intersects(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Contains_ExponentDeltaGreaterThan63()\n        {\n            // {[0, 0, 0, 3]}\n            // {[4408771833616582656, 3234636573324969984, 4552195268789674496, -62]}\n            var a = new Cell2d(0, 0, 3);\n            var b = new Cell2d(4408771833616582656, 3234636573324969984, -62);\n            Assert.IsTrue(a.Contains(b));\n        }\n        \n        [Test]\n        public void Cell_InsideOutside_Contains_ExponentLessThanMinus64()\n        {\n            var a = new Cell2d(12345678910111213, 1000, -100);\n            var b= new Cell2d(12345678910111213*2+1, 2000, -101);\n            Assert.IsTrue(a.Contains(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_ExponentLessThanMinus64_1()\n        {\n            var a = new Cell2d(12345678910111213, 1000, -100);\n            var b = new Cell2d(12345678910111213 + 1, 2000, -100);\n            Assert.IsTrue(!a.Intersects(b));\n        }\n\n        [Test]\n        public void Cell_InsideOutside_Intersects_ExponentLessThanMinus64_2()\n        {\n            var a = new Cell2d(12345678910111213, 1000, -100);\n            var b = new Cell2d(12345678910111213, 2000, -100);\n            Assert.IsTrue(!a.Intersects(b));\n        }\n\n        #endregion\n\n        #region quadrant\n        \n        [Test]\n        public void Cell_GetQuadrant()\n        {\n            var c = new Cell2d(-2, 0, 1);\n            var xs = new[] { c.GetQuadrant(0), c.GetQuadrant(1), c.GetQuadrant(2), c.GetQuadrant(3) };\n            Assert.IsTrue(xs[0] == new Cell2d(-4, 0, 0));\n            Assert.IsTrue(xs[1] == new Cell2d(-3, 0, 0));\n            Assert.IsTrue(xs[2] == new Cell2d(-4, 1, 0));\n            Assert.IsTrue(xs[3] == new Cell2d(-3, 1, 0));\n        }\n\n        [Test]\n        public void Cell_GetQuadrantOfCell_TooBig()\n        {\n            var c = new Cell2d(0, 0, 1);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 0, 1)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 0, 2)) == null);\n        }\n\n        [Test]\n        public void Cell_GetQuadrantOfCell_Centered()\n        {\n            var c = new Cell2d(1);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(1)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(2)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 0, 1)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 0, 2)) == null);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(-1, -1, 0)) == 0);\n            _ = c.GetQuadrant(new Cell2d(0, -1, 0));\n            Assert.IsTrue(c.GetQuadrant(new Cell2d( 0, -1, 0)) == 1);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(-1,  0, 0)) == 2);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d( 0,  0, 0)) == 3);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(-2, -1, 0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d( 1, -1, 0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(-1, -2, 0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(-1,  1, 0)) == null);\n        }\n\n        [Test]\n        public void Cell_GetQuadrantOfCell_1()\n        {\n            var c = new Cell2d(0, 0, 1);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 0, 0)) == 0);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(1, 0, 0)) == 1);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 1, 0)) == 2);\n        }\n\n        [Test]\n        public void Cell_GetQuadrantOfCell_1_Outside()\n        {\n            var c = new Cell2d(0, 0, 1);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(-1, 0, 0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, -1, 0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(2, 0, 0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 2, 0)) == null);\n        }\n\n\n        [Test]\n        public void Cell_GetQuadrantOfCell_2()\n        {\n            var c = new Cell2d(0, 1, 1);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 2, 0)) == 0);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(1, 2, 0)) == 1);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 3, 0)) == 2);\n        }\n\n        [Test]\n        public void Cell_GetQuadrantOfCell_2_Outside()\n        {\n            var c = new Cell2d(0, 1, 1);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(-1, 2, 0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(1, 1, 0)) == null);\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 4, 0)) == null);\n        }\n\n        [Test]\n        public void Cell_GetQuadrantOfCell_3()\n        {\n            var c = new Cell2d(0, 1, 2);\n\n            Assert.IsTrue(c.GetQuadrant(new Cell2d(0, 6, 0)) == 2);\n        }\n\n        #endregion\n\n        #region operators\n\n        #region operator >>\n\n        [Test]\n        public void Cell_RightShift_0()\n        {\n            var c = new Cell2d(1, -2, 4) >> 0;\n            Assert.IsTrue(c == new Cell2d(1, -2, 4));\n            Assert.IsTrue(new Cell2d(1, -2, 4).BoundingBox.Min == c.BoundingBox.Min);\n        }\n\n        [Test]\n        public void Cell_RightShift_1()\n        {\n            var c = new Cell2d(1, -2, 4) >> 1;\n            Assert.IsTrue(c == new Cell2d(2, -4, 3));\n            Assert.IsTrue(new Cell2d(1, -2, 4).BoundingBox.Min == c.BoundingBox.Min);\n        }\n\n        [Test]\n        public void Cell_RightShift_2()\n        {\n            var c = new Cell2d(1, -2, 4) >> 2;\n            Assert.IsTrue(c == new Cell2d(4, -8, 2));\n            Assert.IsTrue(new Cell2d(1, -2, 4).BoundingBox.Min == c.BoundingBox.Min);\n        }\n\n        [Test]\n        public void Cell_RightShift_m1()\n        {\n            var c = new Cell2d(1, -2, 4) >> -1;\n            Assert.IsTrue(c == new Cell2d(1, -2, 4));\n            Assert.IsTrue(new Cell2d(1, -2, 4).BoundingBox.Min == c.BoundingBox.Min);\n        }\n\n        [Test]\n        public void Cell_RightShift_c0()\n        {\n            var c = new Cell2d(4) >> 0;\n            Assert.IsTrue(c == new Cell2d(4));\n            Assert.IsTrue(c.IsCenteredAtOrigin);\n        }\n\n        [Test]\n        public void Cell_RightShift_c1()\n        {\n            var c = new Cell2d(4) >> 1;\n            Assert.IsTrue(c == new Cell2d(3));\n            Assert.IsTrue(c.IsCenteredAtOrigin);\n        }\n\n        [Test]\n        public void Cell_RightShift_cm1()\n        {\n            var c = new Cell2d(4) >> -1;\n            Assert.IsTrue(c == new Cell2d(4));\n            Assert.IsTrue(c.IsCenteredAtOrigin);\n        }\n\n        #endregion\n\n        #region operator <<\n\n        [Test]\n        public void Cell_LeftShift_0()\n        {\n            var c = new Cell2d(1, -2, 4) << 0;\n            Assert.IsTrue(c == new Cell2d(1, -2, 4));\n            Assert.IsTrue(new Cell2d(1, -2, 4).BoundingBox.Min == c.BoundingBox.Min);\n        }\n\n        [Test]\n        public void Cell_LeftShift_1()\n        {\n            var c = new Cell2d(1, -2, 4) << 1;\n            Assert.IsTrue(c == new Cell2d(0, -1, 5));\n            Assert.IsTrue(new Cell2d(0, -2, 4).BoundingBox.Min == c.BoundingBox.Min);\n        }\n\n        [Test]\n        public void Cell_LeftShift_2()\n        {\n            var c = new Cell2d(1, -2, 4) << 2;\n            Assert.IsTrue(c == new Cell2d(0, -1, 6));\n            Assert.IsTrue(new Cell2d(0, -4, 4).BoundingBox.Min == c.BoundingBox.Min);\n        }\n\n        [Test]\n        public void Cell_LeftShift_m1()\n        {\n            var c = new Cell2d(1, -2, 4) << -1;\n            Assert.IsTrue(c == new Cell2d(1, -2, 4));\n            Assert.IsTrue(new Cell2d(1, -2, 4).BoundingBox.Min == c.BoundingBox.Min);\n        }\n\n        [Test]\n        public void Cell_LeftShift_c0()\n        {\n            var c = new Cell2d(4) << 0;\n            Assert.IsTrue(c == new Cell2d(4));\n            Assert.IsTrue(c.IsCenteredAtOrigin);\n        }\n\n        [Test]\n        public void Cell_LeftShift_c1()\n        {\n            var c = new Cell2d(4) << 1;\n            Assert.IsTrue(c == new Cell2d(5));\n            Assert.IsTrue(c.IsCenteredAtOrigin);\n        }\n\n        [Test]\n        public void Cell_LeftShift_cm1()\n        {\n            var c = new Cell2d(4) << -1;\n            Assert.IsTrue(c == new Cell2d(4));\n            Assert.IsTrue(c.IsCenteredAtOrigin);\n        }\n\n        #endregion\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/RangesBoxes/CellTests.cs",
    "content": "﻿/*\r\n    Copyright (C) 2017. Aardvark Platform Team. http://github.com/aardvark-platform.\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\r\n*/\r\nusing Aardvark.Base;\r\nusing NUnit.Framework;\r\nusing System;\r\nusing System.Collections.Generic;\r\n\r\nnamespace Aardvark.Tests\r\n{\r\n    [TestFixture]\r\n    public class CellTests\r\n    {\r\n        #region creation\r\n\r\n        [Test]\r\n        public void UnitCell()\r\n        {\r\n            Assert.IsTrue(Cell.Unit.X == 0 && Cell.Unit.Y == 0 && Cell.Unit.Z == 0);\r\n            Assert.IsTrue(Cell.Unit.Exponent == 0);\r\n            Assert.IsTrue(Cell.Unit.BoundingBox == Box3d.Unit);\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n            Assert.IsTrue(a.X == 1 && a.Y == 2 && a.Z == 3 && a.Exponent == -1);\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell2()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n            var b = new Cell(new V3l(1, 2, 3), -1);\r\n            Assert.IsTrue(a == b);\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_CenteredAtOrigin()\r\n        {\r\n            var a = new Cell(1).BoundingBox;\r\n            Assert.IsTrue(a.Min == new V3d(-1, -1, -1));\r\n            Assert.IsTrue(a.Max == new V3d(+1, +1, +1));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBox_Centered()\r\n        {\r\n            var a = new Cell(new Box3d(new V3d(-1.3, 0, 0), new V3d(0.1, 1, 1)));\r\n            Assert.IsTrue(a == new Cell(2));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBox_Centered_Unit()\r\n        {\r\n            var a = new Cell(new Box3d(new V3d(-1, -1, -1), new V3d(1, 1, 1)));\r\n            Assert.IsTrue(a == new Cell(1));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBox()\r\n        {\r\n            var a = new Cell(new Box3d(new V3d(0.1, 0, 0), new V3d(1.3, 1, 1)));\r\n            Assert.IsTrue(a == new Cell(0, 0, 0, 1));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBoxWithMaxIncludingOrigin()\r\n        {\r\n            var box = new Box3d(new V3d(4, -0.5, 539.5), new V3d(4.5, 0, 540));\r\n            var cell = new Cell(box);\r\n            Assert.IsTrue(cell.BoundingBox.Contains(box));\r\n        }\r\n\r\n        [Test]\r\n        public void CellBoundingBoxContainsBoxTheCellWasCreatedFrom()\r\n        {\r\n            var bb = new Box3d(new V3d(-7163.84, 256990.58, 702.67), new V3d(-7146.66, 257016.8, 717.04));\r\n            var cell = new Cell(bb);\r\n            var cellBoundingBox = cell.BoundingBox;\r\n            Assert.IsTrue(cellBoundingBox.Contains(bb));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBox_PowerOfTwo()\r\n        {\r\n            var a = new Cell(new Box3d(new V3d(0, 0, 0), new V3d(2, 2, 2)));\r\n            // box.Max is interpreted as inclusive, but Cell.Max is exclusive,\r\n            // therefore (2,2,2) is not contained in Box(0,0,0,1) and we\r\n            // have to use next bigger cell\r\n            Assert.IsTrue(a == new Cell(0, 0, 0, 2));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBox_Point()\r\n        {\r\n            var bb = new Box3d(new V3d(1.3), new V3d(1.3));\r\n            var a = new Cell(bb);\r\n            Assert.IsTrue(a.BoundingBox.ApproximateEquals(bb));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBox_Point_PowerOfTwo()\r\n        {\r\n            var bb = new Box3d(new V3d(long.MaxValue >> 1), new V3d(long.MaxValue >> 1));\r\n            var a = new Cell(bb);\r\n            // for cells far far away, floating point precision DOES matter,\r\n            // so we can't use the default tolerance of PositiveTinyValue.\r\n            var tolerance = Math.Pow(2.0, a.Exponent);\r\n            Assert.IsTrue(a.BoundingBox.ApproximateEquals(bb, tolerance));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBoxf()\r\n        {\r\n            var a = new Cell(new Box3f(new V3f(-1.3, 0, 0), new V3f(0.1, 1, 1)));\r\n            Assert.IsTrue(a == new Cell(2));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromV3ds()\r\n        {\r\n            var a = new Cell(new[] { new V3d(-1.3, 0, 0), new V3d(0.1, 1, 1) });\r\n            Assert.IsTrue(a == new Cell(2));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromV3fs()\r\n        {\r\n            var a = new Cell(new[] { new V3f(-1.3, 0, 0), new V3f(0.1, 1, 1) });\r\n            Assert.IsTrue(a == new Cell(2));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromV3dEnumerable()\r\n        {\r\n            var a = new Cell((IEnumerable<V3d>)new[] { new V3d(-1.3, 0, 0), new V3d(0.1, 1, 1) });\r\n            Assert.IsTrue(a == new Cell(2));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromV3fEnumerable()\r\n        {\r\n            var a = new Cell((IEnumerable<V3f>)new[] { new V3f(-1.3, 0, 0), new V3f(0.1, 1, 1) });\r\n            Assert.IsTrue(a == new Cell(2));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBox2()\r\n        {\r\n            var a = new Cell(new Box3d(new V3d(0.1, 0.8, 0.8), new V3d(0.8, 0.9, 0.9)));\r\n            Assert.IsTrue(a == new Cell(0, 0, 0, 0));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromBox3()\r\n        {\r\n            var a = new Cell(new Box3d(new V3d(1.1, 0.8, 0.8), new V3d(1.8, 0.9, 0.9)));\r\n            Assert.IsTrue(a == new Cell(1, 0, 0, 0));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromPoint()\r\n        {\r\n            var p = new V3d(0.1, 0.2, -0.3);\r\n            var a = new Cell(p);\r\n            Assert.IsTrue(a.BoundingBox.Contains(p));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromPointAtPowerOfTwoLocation()\r\n        {\r\n            for (var e = -1024; e <= 1023; e++)\r\n            {\r\n                var p = new V3d(Math.Pow(2.0, e));\r\n                var a = new Cell(p);\r\n                Assert.IsTrue(a.BoundingBox.Contains(p));\r\n            }\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromPoint_Origin()\r\n        {\r\n            var p = V3d.Zero;\r\n            var a = new Cell(p);\r\n            Assert.IsTrue(a.BoundingBox.Contains(p));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromPoint_MaxNegative()\r\n        {\r\n            var p = new V3d(-double.MaxValue, -double.MaxValue, -double.MaxValue);\r\n            var a = new Cell(p);\r\n            Assert.IsTrue(a.BoundingBox.Contains(p));\r\n        }\r\n\r\n        [Test]\r\n        public void CanCreateCell_FromPoint_MaxPositive()\r\n        {\r\n            var p = new V3d(double.MaxValue, double.MaxValue, double.MaxValue);\r\n            var a = new Cell(p);\r\n            Assert.IsTrue(a.BoundingBox.Contains(p));\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region serialization\r\n        \r\n        [Test]\r\n        public void CanSerializeCellToBinary()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n            _ = a.ToByteArray();\r\n        }\r\n\r\n        [Test]\r\n        public void CanDeserializeCellFromBinary()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n            var buffer = a.ToByteArray();\r\n\r\n            var b = Cell.Parse(buffer);\r\n\r\n            Assert.IsTrue(a == b);\r\n        }\r\n\r\n        [Test]\r\n        public void CanDeserializeCellFromString()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n            var s = a.ToString();\r\n\r\n            var b = Cell.Parse(s);\r\n\r\n            Assert.IsTrue(a == b);\r\n        }\r\n\r\n        //[Test]\r\n        //public void CanRoundtripCellWithSystemTextJsonAndNewtonsoft()\r\n        //{\r\n        //    var a = new Cell(1, 2, 3, -1);\r\n        //    var json = System.Text.Json.JsonSerializer.Serialize(a);\r\n        //    var b = Newtonsoft.Json.JsonConvert.DeserializeObject<Cell>(json);\r\n        //    Assert.IsTrue(a == b);\r\n        //}\r\n\r\n        [Test]\r\n        public void CanRoundtripCellWithNewtonsoft()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n            var json = Newtonsoft.Json.JsonConvert.SerializeObject(a);\r\n            var b = Newtonsoft.Json.JsonConvert.DeserializeObject<Cell>(json);\r\n            Assert.IsTrue(a == b);\r\n        }\r\n\r\n        [Test]\r\n        public void CanRoundtripCellWithNewtonsoftAndSystemTextJson()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n            var json = Newtonsoft.Json.JsonConvert.SerializeObject(a);\r\n            var b = System.Text.Json.JsonSerializer.Deserialize<Cell>(json);\r\n            Assert.IsTrue(a == b);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region CellIsCenteredAtOrigin\r\n\r\n        [Test]\r\n        public void CellIsCenteredAtOrigin()\r\n        {\r\n            var a = new Cell(10);\r\n            Assert.IsTrue(a.IsCenteredAtOrigin);\r\n        }\r\n\r\n        [Test]\r\n        public void CellIsNotCenteredAtOrigin()\r\n        {\r\n            var a = new Cell(1, 2, 3, 4);\r\n            Assert.IsTrue(!a.IsCenteredAtOrigin);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region IsValid, IsInvalid\r\n\r\n        [Test]\r\n        public void CellIsValidInvalid()\r\n        {\r\n            var a = Cell.Invalid;\r\n            Assert.IsTrue(a.IsInvalid);\r\n            Assert.IsFalse(a.IsValid);\r\n\r\n            var b = Cell.Unit;\r\n            Assert.IsTrue(b.IsValid);\r\n            Assert.IsFalse(b.IsInvalid);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region equality\r\n\r\n        [Test]\r\n        public void CellIsEqualToItself()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n\r\n            Assert.IsTrue(a.Equals((object)a));\r\n            Assert.IsTrue(a.Equals(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_Equality()\r\n        {\r\n            var a = new Cell(1, 2, 3, -1);\r\n            var b = new Cell(1, 2, 3, -1);\r\n\r\n            Assert.IsTrue(a.Equals((object)b));\r\n            Assert.IsTrue(a.Equals(b));\r\n            Assert.IsTrue(a == b);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_Inequality()\r\n        {\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0) != new Cell(1, 0, 0, 0));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0) != new Cell(0, 1, 0, 0));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0) != new Cell(0, 0, 1, 0));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0) != new Cell(0, 0, 0, 1));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_GetHashCode()\r\n        {\r\n            var a = new Cell(1, 0, 0, 0).GetHashCode();\r\n            var b = new Cell(0, 1, 0, 0).GetHashCode();\r\n            var c = new Cell(0, 0, 1, 0).GetHashCode();\r\n            var d = new Cell(0, 0, 0, 1).GetHashCode();\r\n\r\n            Assert.IsTrue(a != b && a != c && a != d && b != c && b != d && c != d);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region ToString\r\n\r\n        [Test]\r\n        public void Cell_ToString()\r\n        {\r\n            var s = new Cell(1, 2, 3, -1).ToString();\r\n            Assert.IsTrue(s == \"[1, 2, 3, -1]\");\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region BoundingBox\r\n\r\n        [Test]\r\n        public void Cell_Box3d()\r\n        {\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).BoundingBox == new Box3d(new V3d(0, 0, 0), new V3d(1, 1, 1)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 1).BoundingBox == new Box3d(new V3d(0, 0, 0), new V3d(2, 2, 2)));\r\n            Assert.IsTrue(new Cell(1, 2, 3, 4).BoundingBox == new Box3d(new V3d(16, 32, 48), new V3d(32, 48, 64)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, -1).BoundingBox == new Box3d(new V3d(0, 0, 0), new V3d(0.5, 0.5, 0.5)));\r\n            Assert.IsTrue(new Cell(-1, 0, 0, -1).BoundingBox == new Box3d(new V3d(-0.5, 0, 0), new V3d(0.0, 0.5, 0.5)));\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region children\r\n\r\n        [Test]\r\n        public void Cell_Centered_Children()\r\n        {\r\n            var xs = new Cell(1).Children;\r\n            Assert.IsTrue(xs[0] == new Cell(-1, -1, -1, 0));\r\n            Assert.IsTrue(xs[1] == new Cell( 0, -1, -1, 0));\r\n            Assert.IsTrue(xs[2] == new Cell(-1,  0, -1, 0));\r\n            Assert.IsTrue(xs[3] == new Cell( 0,  0, -1, 0));\r\n            Assert.IsTrue(xs[4] == new Cell(-1, -1,  0, 0));\r\n            Assert.IsTrue(xs[5] == new Cell( 0, -1,  0, 0));\r\n            Assert.IsTrue(xs[6] == new Cell(-1,  0,  0, 0));\r\n            Assert.IsTrue(xs[7] == new Cell( 0,  0,  0, 0));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_Children1()\r\n        {\r\n            var xs = new Cell(0, 0, 0, 0).Children;\r\n            Assert.IsTrue(xs[0] == new Cell(0, 0, 0, -1));\r\n            Assert.IsTrue(xs[1] == new Cell(1, 0, 0, -1));\r\n            Assert.IsTrue(xs[2] == new Cell(0, 1, 0, -1));\r\n            Assert.IsTrue(xs[3] == new Cell(1, 1, 0, -1));\r\n            Assert.IsTrue(xs[4] == new Cell(0, 0, 1, -1));\r\n            Assert.IsTrue(xs[5] == new Cell(1, 0, 1, -1));\r\n            Assert.IsTrue(xs[6] == new Cell(0, 1, 1, -1));\r\n            Assert.IsTrue(xs[7] == new Cell(1, 1, 1, -1));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_Children2()\r\n        {\r\n            var xs = new Cell(-2, 0, 10, 1).Children;\r\n            Assert.IsTrue(xs[0] == new Cell(-4, 0, 20, 0));\r\n            Assert.IsTrue(xs[1] == new Cell(-3, 0, 20, 0));\r\n            Assert.IsTrue(xs[2] == new Cell(-4, 1, 20, 0));\r\n            Assert.IsTrue(xs[3] == new Cell(-3, 1, 20, 0));\r\n            Assert.IsTrue(xs[4] == new Cell(-4, 0, 21, 0));\r\n            Assert.IsTrue(xs[5] == new Cell(-3, 0, 21, 0));\r\n            Assert.IsTrue(xs[6] == new Cell(-4, 1, 21, 0));\r\n            Assert.IsTrue(xs[7] == new Cell(-3, 1, 21, 0));\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region parent\r\n\r\n        [Test]\r\n        public void Cell_Centered_Parent()\r\n        {\r\n            Assert.IsTrue(new Cell(-1).Parent == new Cell(0));\r\n            Assert.IsTrue(new Cell(0).Parent == new Cell(1));\r\n            Assert.IsTrue(new Cell(1).Parent == new Cell(2));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_Parent1()\r\n        {\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Parent == new Cell(0, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(1, 0, 0, 0).Parent == new Cell(0, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(0, 1, 0, 0).Parent == new Cell(0, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(1, 1, 0, 0).Parent == new Cell(0, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(0, 0, 1, 0).Parent == new Cell(0, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(1, 0, 1, 0).Parent == new Cell(0, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(0, 1, 1, 0).Parent == new Cell(0, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(1, 1, 1, 0).Parent == new Cell(0, 0, 0, 1));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_Parent2()\r\n        {\r\n            Assert.IsTrue(new Cell(-1, 0, 0, 0).Parent == new Cell(-1, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(-2, 0, 0, 0).Parent == new Cell(-1, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(-3, 0, 0, 0).Parent == new Cell(-2, 0, 0, 1));\r\n            Assert.IsTrue(new Cell(-4, 0, 0, 0).Parent == new Cell(-2, 0, 0, 1));\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region common root cell\r\n\r\n        [Test]\r\n        public void Cell_CommonRootCell_1()\r\n        {\r\n            var r = Cell.GetCommonRoot(new Cell(1, 2, 3, 4), new Cell(1, 2, 3, 4));\r\n            Assert.IsTrue(r == new Cell(1, 2, 3, 4));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_CommonRootCell_2()\r\n        {\r\n            var r = Cell.GetCommonRoot(new Cell(-5), new Cell(-5));\r\n            Assert.IsTrue(r == new Cell(-5));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_CommonRootCell_3()\r\n        {\r\n            var r = Cell.GetCommonRoot(new Cell(3), new Cell(2));\r\n            Assert.IsTrue(r == new Cell(3));\r\n            r = Cell.GetCommonRoot(new Cell(2), new Cell(3));\r\n            Assert.IsTrue(r == new Cell(3));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_CommonRootCell_4a()\r\n        {\r\n            var r = Cell.GetCommonRoot(new Cell(1), new Cell(0,0,0,0));\r\n            Assert.IsTrue(r == new Cell(1));\r\n            r = Cell.GetCommonRoot(new Cell(0, 0, 0, 0), new Cell(1));\r\n            Assert.IsTrue(r == new Cell(1));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_CommonRootCell_4b()\r\n        {\r\n            var r = Cell.GetCommonRoot(new Cell(1), new Cell(-1, 0, 0, 0));\r\n            Assert.IsTrue(r == new Cell(1));\r\n            r = Cell.GetCommonRoot(new Cell(0, -1, 0, 0), new Cell(1));\r\n            Assert.IsTrue(r == new Cell(1));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_CommonRootCell_5()\r\n        {\r\n            var r = Cell.GetCommonRoot(new Cell(0,0,0,0), new Cell(1,0,0,-1));\r\n            Assert.IsTrue(r == new Cell(0,0,0,0));\r\n            r = Cell.GetCommonRoot(new Cell(0, 0, 0, 0), new Cell(1, -3, 0, -5));\r\n            Assert.IsTrue(r == new Cell(1));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_CommonRootCell_6()\r\n        {\r\n            var r = Cell.GetCommonRoot(new Cell(0, 0, 0, 0), new Cell(1, 0, 0, 0), new Cell(0));\r\n            Assert.IsTrue(r == new Cell(2));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_CommonRootCell_7()\r\n        {\r\n            var r = Cell.GetCommonRoot(new Cell(3, 3, 0, 6), new Cell(1, 1, -1, 7));\r\n            Assert.IsTrue(r == new Cell(9));\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region touches origin\r\n\r\n        [Test]\r\n        public void CenteredCellDoesNotTouchOrigin()\r\n        {\r\n            Assert.IsTrue(new Cell(-1).TouchesOrigin == false);\r\n            Assert.IsTrue(new Cell(0).TouchesOrigin == false);\r\n            Assert.IsTrue(new Cell(1).TouchesOrigin == false);\r\n        }\r\n\r\n        [Test]\r\n        public void CellTouchOrigin()\r\n        {\r\n            Assert.IsTrue(new Cell( 0,  0,  0, 0).TouchesOrigin == true);\r\n            Assert.IsTrue(new Cell(-1,  0,  0, 0).TouchesOrigin == true);\r\n            Assert.IsTrue(new Cell( 0, -1,  0, 0).TouchesOrigin == true);\r\n            Assert.IsTrue(new Cell(-1, -1,  0, 0).TouchesOrigin == true);\r\n            Assert.IsTrue(new Cell( 0,  0, -1, 0).TouchesOrigin == true);\r\n            Assert.IsTrue(new Cell(-1,  0, -1, 0).TouchesOrigin == true);\r\n            Assert.IsTrue(new Cell( 0, -1, -1, 0).TouchesOrigin == true);\r\n            Assert.IsTrue(new Cell(-1, -1, -1, 0).TouchesOrigin == true);\r\n\r\n            Assert.IsTrue(new Cell(1, 0, 0, 0).TouchesOrigin == false);\r\n            Assert.IsTrue(new Cell(0, 1, 0, 0).TouchesOrigin == false);\r\n            Assert.IsTrue(new Cell(1, 1, 0, 0).TouchesOrigin == false);\r\n            Assert.IsTrue(new Cell(0, 0, 1, 0).TouchesOrigin == false);\r\n            Assert.IsTrue(new Cell(1, 0, 1, 0).TouchesOrigin == false);\r\n            Assert.IsTrue(new Cell(0, 1, 1, 0).TouchesOrigin == false);\r\n            Assert.IsTrue(new Cell(1, 1, 1, 0).TouchesOrigin == false);\r\n            \r\n        }\r\n\r\n        #endregion\r\n\r\n        #region contains/intersects\r\n\r\n        [Test]\r\n        public void Cell_Contains()\r\n        {\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(-1, -1, -1, 7)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(-1, -1,  0, 7)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(-1,  0, -1, 7)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(-1,  0,  0, 7)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell( 0, -1, -1, 7)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell( 0, -1,  0, 7)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell( 0,  0, -1, 7)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell( 0,  0,  0, 7)) == true);\r\n\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(-2, -2, -2, 7)) == false);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(-2, -2,  1, 7)) == false);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(-2,  1, -2, 7)) == false);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(-2,  1,  1, 7)) == false);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell( 1, -2, -2, 7)) == false);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell( 1, -2,  1, 7)) == false);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell( 1,  1, -2, 7)) == false);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell( 1,  1,  1, 7)) == false);\r\n\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell(-2, -2, -2, 7)) == true);\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell(-2, -2,  1, 7)) == true);\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell(-2,  1, -2, 7)) == true);\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell(-2,  1,  1, 7)) == true);\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell( 1, -2, -2, 7)) == true);\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell( 1, -2,  1, 7)) == true);\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell( 1,  1, -2, 7)) == true);\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell( 1,  1,  1, 7)) == true);\r\n\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(3, 3, 0, 6)) == false);\r\n            Assert.IsTrue(new Cell(9).Contains(new Cell(3, 3, 0, 6)) == true);\r\n\r\n\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(7)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(8)) == true);\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(9)) == false);\r\n\r\n            Assert.IsTrue(new Cell(8).Contains(new Cell(0, 0, 0, 8)) == false);\r\n\r\n            Assert.IsTrue(new Cell(0, 0, 0, 8).Contains(new Cell(7)) == false);\r\n\r\n\r\n            Assert.IsTrue(new Cell(0, 0, 0, 8).Contains(new Cell(0, 0, 0, 7)) == true);\r\n            Assert.IsTrue(new Cell(0, 0, 0, 8).Contains(new Cell(1, 0, 0, 7)) == true);\r\n            Assert.IsTrue(new Cell(0, 0, 0, 8).Contains(new Cell(2, 0, 0, 7)) == false);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_ContainsEqual()\r\n        {\r\n            var a = new Cell(1, 2, 3, 4);\r\n            var b = new Cell(1, 2, 3, 4);\r\n            Assert.IsTrue(a.Contains(b));\r\n            Assert.IsTrue(b.Contains(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Inside()\r\n        {\r\n            var a = new Cell(0, 0, 0, 0);\r\n            var b = new Cell(1, 2, 3, -4);\r\n            Assert.IsTrue(a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_InsideTouching()\r\n        {\r\n            var a = new Cell(0, 0, 0, 0);\r\n            var b = new Cell(0, 0, 0, -1);\r\n            Assert.IsTrue(a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Outside()\r\n        {\r\n            var a = new Cell(0, 0, 0, 0);\r\n            var b = new Cell(2, 0, 0, 0);\r\n            Assert.IsTrue(!a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_OutsideTouching()\r\n        {\r\n            var a = new Cell(0, 0, 0, 0);\r\n            var b = new Cell(1, 0, 0, 0);\r\n            Assert.IsTrue(!a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Centered1()\r\n        {\r\n            var a = new Cell(1);\r\n            Assert.IsTrue(a.Contains(new Cell(-1, -1, -1, 0)));\r\n            Assert.IsTrue(a.Contains(new Cell(0, -1, -1, 0)));\r\n            Assert.IsTrue(a.Contains(new Cell(-1, 0, -1, 0)));\r\n            Assert.IsTrue(a.Contains(new Cell(0, 0, -1, 0)));\r\n            Assert.IsTrue(a.Contains(new Cell(-1, -1, 0, 0)));\r\n            Assert.IsTrue(a.Contains(new Cell(0, -1, 0, 0)));\r\n            Assert.IsTrue(a.Contains(new Cell(-1, 0, 0, 0)));\r\n            Assert.IsTrue(a.Contains(new Cell(0, 0, 0, 0)));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Centered2()\r\n        {\r\n            var a = new Cell(1);\r\n            var b = new Cell(0);\r\n            Assert.IsTrue(a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Centered3()\r\n        {\r\n            var a = new Cell(1);\r\n            var b = new Cell(0);\r\n            Assert.IsTrue(!b.Contains(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Centered4()\r\n        {\r\n            var a = new Cell(2);\r\n            var b = new Cell(2);\r\n            Assert.IsTrue(a.Contains(b));\r\n            Assert.IsTrue(b.Contains(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Centered5()\r\n        {\r\n            var a = new Cell(2);\r\n            var b = new Cell(0, 0, 0, 2);\r\n            Assert.IsTrue(!a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Centered6()\r\n        {\r\n            var a = new Cell(2);\r\n            var b = new Cell(10, 10, 10, 1);\r\n            Assert.IsTrue(!a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Centered7()\r\n        {\r\n            var a = new Cell(2);\r\n            var b = new Cell(0, 0, 0, 3);\r\n            Assert.IsTrue(!a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_Centered8()\r\n        {\r\n            var a = new Cell(0, 0, 0, 2);\r\n            var b = new Cell(1);\r\n            Assert.IsTrue(!a.Contains(b));\r\n        }\r\n        \r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_Itself_1()\r\n        {\r\n            var a = Cell.Unit;\r\n            Assert.IsTrue(a.Intersects(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_Itself_2()\r\n        {\r\n            var a = new Cell(1, -2, 3, -4);\r\n            Assert.IsTrue(a.Intersects(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_Itself_3()\r\n        {\r\n            var a = new Cell(1, -2, 12345678910111213, 2);\r\n            Assert.IsTrue(a.Intersects(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_Itself_4()\r\n        {\r\n            var a = new Cell(7);\r\n            Assert.IsTrue(a.Intersects(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_Itself_5()\r\n        {\r\n            var a = new Cell(-123456789);\r\n            Assert.IsTrue(a.Intersects(a));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_Contained_NotTouching()\r\n        {\r\n            var a = new Cell(0, 0, 0, 2);\r\n            var b = new Cell(1, 2, 1, 0);\r\n            Assert.IsTrue(a.Intersects(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_InsideTouching()\r\n        {\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Intersects(new Cell(0, 0, 0, -1)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Intersects(new Cell(1, 0, 0, -1)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Intersects(new Cell(0, 1, 0, -1)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Intersects(new Cell(1, 1, 0, -1)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Intersects(new Cell(0, 0, 1, -1)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Intersects(new Cell(1, 0, 1, -1)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Intersects(new Cell(0, 1, 1, -1)));\r\n            Assert.IsTrue(new Cell(0, 0, 0, 0).Intersects(new Cell(1, 1, 1, -1)));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_OutsideTouchingMin()\r\n        {\r\n            var a = new Cell(2, 0, 0, 0);\r\n            var b = new Cell(1, 0, 0, 0);\r\n            Assert.IsTrue(!a.Intersects(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_OutsideTouchingMax()\r\n        {\r\n            var a = new Cell(1, 0, 0, 0);\r\n            var b = new Cell(2, 0, 0, 0);\r\n            Assert.IsTrue(!a.Intersects(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_ExponentDeltaGreaterThan63()\r\n        {\r\n            // {[0, 0, 0, 3]}\r\n            // {[4408771833616582656, 3234636573324969984, 4552195268789674496, -62]}\r\n            var a = new Cell(0, 0, 0, 3);\r\n            var b = new Cell(4408771833616582656, 3234636573324969984, 4552195268789674496, -62);\r\n            Assert.IsTrue(a.Contains(b));\r\n        }\r\n        \r\n        [Test]\r\n        public void Cell_InsideOutside_Contains_ExponentLessThanMinus64()\r\n        {\r\n            var a = new Cell(12345678910111213, 1000, 2000, -100);\r\n            var b= new Cell(12345678910111213*2+1, 2000, 4000, -101);\r\n            Assert.IsTrue(a.Contains(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_ExponentLessThanMinus64_1()\r\n        {\r\n            var a = new Cell(12345678910111213, 1000, 2000, -100);\r\n            var b = new Cell(12345678910111213 + 1, 2000, 4000, -100);\r\n            Assert.IsTrue(!a.Intersects(b));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_InsideOutside_Intersects_ExponentLessThanMinus64_2()\r\n        {\r\n            var a = new Cell(12345678910111213, 1000, 2000, -100);\r\n            var b = new Cell(12345678910111213, 2000, 4000, -100);\r\n            Assert.IsTrue(!a.Intersects(b));\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region octant\r\n        \r\n        [Test]\r\n        public void Cell_GetOctant()\r\n        {\r\n            var c = new Cell(-2, 0, 10, 1);\r\n            var xs = new[] { c.GetOctant(0), c.GetOctant(1), c.GetOctant(2), c.GetOctant(3), c.GetOctant(4), c.GetOctant(5), c.GetOctant(6), c.GetOctant(7) };\r\n            Assert.IsTrue(xs[0] == new Cell(-4, 0, 20, 0));\r\n            Assert.IsTrue(xs[1] == new Cell(-3, 0, 20, 0));\r\n            Assert.IsTrue(xs[2] == new Cell(-4, 1, 20, 0));\r\n            Assert.IsTrue(xs[3] == new Cell(-3, 1, 20, 0));\r\n            Assert.IsTrue(xs[4] == new Cell(-4, 0, 21, 0));\r\n            Assert.IsTrue(xs[5] == new Cell(-3, 0, 21, 0));\r\n            Assert.IsTrue(xs[6] == new Cell(-4, 1, 21, 0));\r\n            Assert.IsTrue(xs[7] == new Cell(-3, 1, 21, 0));\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_GetOctantOfCell_TooBig()\r\n        {\r\n            var c = new Cell(0, 0, 0, 1);\r\n\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 0, 0, 1)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 0, 0, 2)) == null);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_GetOctantOfCell_Centered()\r\n        {\r\n            var c = new Cell(1);\r\n\r\n            Assert.IsTrue(c.GetOctant(new Cell(0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(1)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(2)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 0, 0, 1)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 0, 0, 2)) == null);\r\n\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1, -1, -1, 0)) == 0);\r\n            Assert.IsTrue(c.GetOctant(new Cell( 0, -1, -1, 0)) == 1);\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1,  0, -1, 0)) == 2);\r\n            Assert.IsTrue(c.GetOctant(new Cell( 0,  0, -1, 0)) == 3);\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1, -1,  0, 0)) == 4);\r\n            Assert.IsTrue(c.GetOctant(new Cell( 0, -1,  0, 0)) == 5);\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1,  0,  0, 0)) == 6);\r\n            Assert.IsTrue(c.GetOctant(new Cell( 0,  0,  0, 0)) == 7);\r\n\r\n            Assert.IsTrue(c.GetOctant(new Cell(-2, -1, -1, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell( 1, -1, -1, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1, -2, -1, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1,  1, -1, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1, -1, -2, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1, -1,  1, 0)) == null);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_GetOctantOfCell_1()\r\n        {\r\n            var c = new Cell(0, 0, 0, 1);\r\n\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 0, 0, 0)) == 0);\r\n            Assert.IsTrue(c.GetOctant(new Cell(1, 0, 0, 0)) == 1);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 1, 0, 0)) == 2);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 0, 1, 0)) == 4);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_GetOctantOfCell_1_Outside()\r\n        {\r\n            var c = new Cell(0, 0, 0, 1);\r\n\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1, 0, 0, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, -1, 0, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 0, -1, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(2, 0, 0, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 2, 0, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 0, 2, 0)) == null);\r\n        }\r\n\r\n\r\n        [Test]\r\n        public void Cell_GetOctantOfCell_2()\r\n        {\r\n            var c = new Cell(0, 1, 0, 1);\r\n\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 2, 0, 0)) == 0);\r\n            Assert.IsTrue(c.GetOctant(new Cell(1, 2, 0, 0)) == 1);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 3, 0, 0)) == 2);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 2, 1, 0)) == 4);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_GetOctantOfCell_2_Outside()\r\n        {\r\n            var c = new Cell(0, 1, 0, 1);\r\n\r\n            Assert.IsTrue(c.GetOctant(new Cell(-1, 2, 0, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(1, 1, 0, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 4, 0, 0)) == null);\r\n            Assert.IsTrue(c.GetOctant(new Cell(0, 2, 2, 0)) == null);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region operators\r\n\r\n        #region operator >>\r\n\r\n        [Test]\r\n        public void Cell_RightShift_0()\r\n        {\r\n            var c = new Cell(1, -2, 3, 4) >> 0;\r\n            Assert.IsTrue(c == new Cell(1, -2, 3, 4));\r\n            Assert.IsTrue(new Cell(1, -2, 3, 4).BoundingBox.Min == c.BoundingBox.Min);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_RightShift_1()\r\n        {\r\n            var c = new Cell(1, -2, 3, 4) >> 1;\r\n            Assert.IsTrue(c == new Cell(2, -4, 6, 3));\r\n            Assert.IsTrue(new Cell(1, -2, 3, 4).BoundingBox.Min == c.BoundingBox.Min);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_RightShift_2()\r\n        {\r\n            var c = new Cell(1, -2, 3, 4) >> 2;\r\n            Assert.IsTrue(c == new Cell(4, -8, 12, 2));\r\n            Assert.IsTrue(new Cell(1, -2, 3, 4).BoundingBox.Min == c.BoundingBox.Min);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_RightShift_m1()\r\n        {\r\n            var c = new Cell(1, -2, 3, 4) >> -1;\r\n            Assert.IsTrue(c == new Cell(1, -2, 3, 4));\r\n            Assert.IsTrue(new Cell(1, -2, 3, 4).BoundingBox.Min == c.BoundingBox.Min);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_RightShift_c0()\r\n        {\r\n            var c = new Cell(4) >> 0;\r\n            Assert.IsTrue(c == new Cell(4));\r\n            Assert.IsTrue(c.IsCenteredAtOrigin);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_RightShift_c1()\r\n        {\r\n            var c = new Cell(4) >> 1;\r\n            Assert.IsTrue(c == new Cell(3));\r\n            Assert.IsTrue(c.IsCenteredAtOrigin);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_RightShift_cm1()\r\n        {\r\n            var c = new Cell(4) >> -1;\r\n            Assert.IsTrue(c == new Cell(4));\r\n            Assert.IsTrue(c.IsCenteredAtOrigin);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #region operator <<\r\n\r\n        [Test]\r\n        public void Cell_LeftShift_0()\r\n        {\r\n            var c = new Cell(1, -2, 3, 4) << 0;\r\n            Assert.IsTrue(c == new Cell(1, -2, 3, 4));\r\n            Assert.IsTrue(new Cell(1, -2, 3, 4).BoundingBox.Min == c.BoundingBox.Min);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_LeftShift_1()\r\n        {\r\n            var c = new Cell(1, -2, 3, 4) << 1;\r\n            Assert.IsTrue(c == new Cell(0, -1, 1, 5));\r\n            Assert.IsTrue(new Cell(0, -2, 2, 4).BoundingBox.Min == c.BoundingBox.Min);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_LeftShift_2()\r\n        {\r\n            var c = new Cell(1, -2, 3, 4) << 2;\r\n            Assert.IsTrue(c == new Cell(0, -1, 0, 6));\r\n            Assert.IsTrue(new Cell(0, -4, 0, 4).BoundingBox.Min == c.BoundingBox.Min);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_LeftShift_m1()\r\n        {\r\n            var c = new Cell(1, -2, 3, 4) << -1;\r\n            Assert.IsTrue(c == new Cell(1, -2, 3, 4));\r\n            Assert.IsTrue(new Cell(1, -2, 3, 4).BoundingBox.Min == c.BoundingBox.Min);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_LeftShift_c0()\r\n        {\r\n            var c = new Cell(4) << 0;\r\n            Assert.IsTrue(c == new Cell(4));\r\n            Assert.IsTrue(c.IsCenteredAtOrigin);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_LeftShift_c1()\r\n        {\r\n            var c = new Cell(4) << 1;\r\n            Assert.IsTrue(c == new Cell(5));\r\n            Assert.IsTrue(c.IsCenteredAtOrigin);\r\n        }\r\n\r\n        [Test]\r\n        public void Cell_LeftShift_cm1()\r\n        {\r\n            var c = new Cell(4) << -1;\r\n            Assert.IsTrue(c == new Cell(4));\r\n            Assert.IsTrue(c.IsCenteredAtOrigin);\r\n        }\r\n\r\n        #endregion\r\n\r\n        #endregion\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Reporting/ReportingTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class ReportingTests : TestSuite\n    {\n        public ReportingTests() : base() { }\n\n        [Test]\n        public void DoubleEnd()\n        {\n            var previousRootTarget = Report.RootTarget;\n            var output = new StringBuilder();\n            var target = new TextLogTarget((threadIndex, type, level, message) => output.Append(message))\n            {\n                Verbosity = int.MaxValue,\n                LogCompleteLinesOnly = true,\n            };\n            target.PrefixFun = _ => \"\";\n\n            try\n            {\n                Report.RootTarget = target;\n\n                Report.Begin(\"begin\");\n                Report.End();\n                Report.End(); // bad end -> should report warning, but not throw exception\n\n                Report.Begin(\"begin\");\n                Report.End();\n                Report.End(\"end without begin\"); // bad end -> text should be reported\n\n                Report.Line(\"passed\");\n            }\n            finally\n            {\n                target.Dispose();\n                Report.RootTarget = previousRootTarget;\n            }\n\n            var text = output.ToString();\n            StringAssert.Contains(\"superfluous Report.End() encountered\", text);\n            StringAssert.Contains(\"end without begin\", text);\n            StringAssert.Contains(\"passed\", text);\n        }\n\n        [Test]\n        public void MultiThread()\n        {\n            new Thread(() =>\n            {\n                for (int i = 0; i < 1000; i ++)\n                {\n                    Report.BeginTimed(\"Thread 1 time\");\n                    Report.Line(\"This is thread 1 reporting {0}\", i);\n                    Report.End(\" - end 1\");\n                }\n            }).Start();\n\n            new Thread(() =>\n            {\n                for (int i = 0; i < 1000; i++)\n                {\n                    Report.BeginTimed(\"Thread 2 time\");\n                    Report.Line(\"This is thread 2 reporting {0}\", i);\n                    Report.End();\n                }\n            }).Start();\n\n            new Thread(() =>\n            {\n                for (int i = 0; i < 2000; i++)\n                {\n                    Report.Line(\"This is thread 3 reporting {0}\", i);\n                }\n            }).Start();\n\n            new Thread(() =>\n            {\n                for (int i = 0; i < 2000; i++)\n                {\n                    Report.Warn(\"WARNING\");\n                }\n            }).Start();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/System/EventSourceSlimTests.cs",
    "content": "using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class EventSourceSlimTests\n    {\n        [Test]\n        public void LatestReturnsInitialValueAndUpdatesAfterEmit()\n        {\n            var source = new EventSourceSlim<int>(10);\n\n            Assert.That(source.Latest, Is.EqualTo(10));\n\n            source.Emit(20);\n\n            Assert.That(source.Latest, Is.EqualTo(20));\n        }\n\n        [Test]\n        public void NextCompletesWithNextEmittedValueAndRefreshes()\n        {\n            var source = new EventSourceSlim<int>(0);\n            var first = source.Next;\n\n            Assert.That(first.IsCompleted, Is.False);\n\n            source.Emit(1);\n\n            Assert.That(first.IsCompleted, Is.True);\n            Assert.That(first.Result, Is.EqualTo(1));\n\n            var second = source.Next;\n\n            Assert.That(second, Is.Not.SameAs(first));\n            Assert.That(second.IsCompleted, Is.False);\n\n            source.Emit(2);\n\n            Assert.That(second.IsCompleted, Is.True);\n            Assert.That(second.Result, Is.EqualTo(2));\n        }\n\n        [Test]\n        public void NonGenericNextCompletesWithoutThrowing()\n        {\n            var source = new EventSourceSlim<string>(\"initial\");\n            var genericEvent = (IEvent<string>)source;\n            var nonGenericEvent = (IEvent)source;\n\n            var typedNext = genericEvent.Next;\n            var next = nonGenericEvent.Next;\n\n            Assert.That(next, Is.SameAs(typedNext));\n            Assert.That(next.IsCompleted, Is.False);\n\n            source.Emit(\"next\");\n\n            Assert.That(next.IsCompleted, Is.True);\n            Assert.DoesNotThrow(() => next.GetAwaiter().GetResult());\n            Assert.That(typedNext.Result, Is.EqualTo(\"next\"));\n        }\n\n        [Test]\n        public void NonGenericValuesEmitUnitNotifications()\n        {\n            var source = new EventSourceSlim<int>(0);\n            var observer = new RecordingObserver<Unit>();\n\n            using (((IEvent)source).Values.Subscribe(observer))\n            {\n                source.Emit(1);\n                source.Emit(2);\n            }\n\n            Assert.That(observer.Values.Count, Is.EqualTo(2));\n            Assert.That(observer.Values[0], Is.SameAs(Unit.Default));\n            Assert.That(observer.Values[1], Is.SameAs(Unit.Default));\n            Assert.That(observer.Error, Is.Null);\n            Assert.That(observer.CompletedCount, Is.EqualTo(0));\n        }\n\n        private sealed class RecordingObserver<T> : IObserver<T>\n        {\n            public readonly List<T> Values = new List<T>();\n            public Exception Error;\n            public int CompletedCount;\n\n            public void OnCompleted()\n            {\n                CompletedCount++;\n            }\n\n            public void OnError(Exception error)\n            {\n                Error = error;\n            }\n\n            public void OnNext(T value)\n            {\n                Values.Add(value);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Telemetry/TelemetryTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class TelemetryTests : TestSuite\n    {\n        public TelemetryTests() : base() { }\n        public TelemetryTests(Options options) : base(options) { }\n\n        public void NUnitRun()\n        {\n            Test.Begin(\"Telemetry tests\");\n            SnapshotProbeLong_CanBeCreated();\n            SnapshotProbeLong_Works();\n            SnapshotProbeDouble_CanBeCreated();\n            SnapshotProbeDouble_Works();\n            SnapshotProbeTimeSpan_CanBeCreated();\n            SnapshotProbeTimeSpan_Works();\n            Test.End();\n        }\n\n        #region Snapshot probes\n\n        [Test]\n        public void SnapshotProbeLong_CanBeCreated()\n        {\n            Test.Begin(\"SnapshotProbeLong can be created\");\n            var a = new Telemetry.Counter();\n            a.Set(100);\n\n            var s = new Telemetry.SnapshotProbeLong(a);\n\n            Test.IsTrue(s.Value == 0);\n            Test.End();\n        }\n\n        [Test]\n        public void SnapshotProbeLong_Works()\n        {\n            Test.Begin(\"SnapshotProbeLong works\");\n            var a = new Telemetry.Counter();\n            a.Set(100);\n            \n            var s = new Telemetry.SnapshotProbeLong(a);\n            \n            a.Increment();\n            Test.IsTrue(s.Value == 1);\n\n            a.Increment();\n            Test.IsTrue(s.Value == 2);\n\n            a.Decrement();\n            Test.IsTrue(s.Value == 1);\n\n            a.Decrement(2);\n            Test.IsTrue(s.Value == -1);\n            Test.End();\n        }\n\n        [Test]\n        public void SnapshotProbeDouble_CanBeCreated()\n        {\n            Test.Begin(\"SnapshotProbeDouble can be created\");\n            double x = 5.1;\n            var a = new Telemetry.CustomProbeDouble(() => x);\n\n            var s = new Telemetry.SnapshotProbeDouble(a);\n\n            Test.IsTrue(s.Value == 0.0);\n            Test.End();\n        }\n\n        [Test]\n        public void SnapshotProbeDouble_Works()\n        {\n            Test.Begin(\"SnapshotProbeDouble works\");\n            double x = 5.1;\n            var a = new Telemetry.CustomProbeDouble(() => x);\n\n            var s = new Telemetry.SnapshotProbeDouble(a);\n\n            x = 6.1;\n            Test.IsTrue(s.Value == 1.0);\n\n            x = 10.1;\n            Test.IsTrue(s.Value == 5.0);\n\n            x = 0.0;\n            Test.IsTrue(s.Value == -5.1);\n            Test.End();\n        }\n\n        [Test]\n        public void SnapshotProbeTimeSpan_CanBeCreated()\n        {\n            Test.Begin(\"SnapshotProbeTimeSpan can be created\");\n            var x = TimeSpan.FromSeconds(60);\n            var a = new Telemetry.CustomProbeTimeSpan(() => x);\n\n            var s = new Telemetry.SnapshotProbeTimeSpan(a);\n\n            Test.IsTrue(s.Value == TimeSpan.FromSeconds(0));\n            Test.End();\n        }\n\n        [Test]\n        public void SnapshotProbeTimeSpan_Works()\n        {\n            Test.Begin(\"SnapshotProbeTimeSpan works\");\n            var x = TimeSpan.FromSeconds(60);\n            var a = new Telemetry.CustomProbeTimeSpan(() => x);\n\n            var s = new Telemetry.SnapshotProbeTimeSpan(a);\n\n            x = TimeSpan.FromSeconds(70);\n            Test.IsTrue(s.Value == TimeSpan.FromSeconds(10.0));\n\n            x = TimeSpan.FromSeconds(120);\n            Test.IsTrue(s.Value == TimeSpan.FromSeconds(60.0));\n\n            x = TimeSpan.FromSeconds(0);\n            Test.IsTrue(s.Value == TimeSpan.FromSeconds(-60.0));\n            Test.End();\n        }\n\n        #endregion\n\n        #region Timing probes\n\n        [Test]\n        public void StopwatchTime_Works()\n        {\n            var t = new Telemetry.StopWatchTime();\n            using (t.Timer)\n            {\n                Thread.Sleep(1000);\n            }\n\n            Assert.IsTrue(t.Value.TotalSeconds >= 1.0);\n        }\n\n        [Test]\n        public void WallclockTime_Works()\n        {\n            var t = new Telemetry.WallClockTime();\n\n            Task.WaitAll(Enumerable.Range(0, 2).Select(_ => Task.Run(() =>\n                {\n                    using (t.Timer)\n                    {\n                        Thread.Sleep(1000);\n                    }\n                })\n            ).ToArray());\n\n            Assert.IsTrue(t.Value.TotalSeconds >= 1.0 && t.Value.TotalSeconds < 1.1);\n        }\n\n        [Test]\n        public void WallclockTime_DoubleDisposeDoesNotThrowAndProbeRemainsUsable()\n        {\n            var t = new Telemetry.WallClockTime();\n            var timer = t.Timer;\n\n            Thread.Sleep(50);\n\n            Assert.DoesNotThrow(() => timer.Dispose());\n            Assert.DoesNotThrow(() => timer.Dispose());\n\n            var elapsedAfterDoubleDispose = t.Value;\n\n            using (t.Timer)\n            {\n                Thread.Sleep(50);\n            }\n\n            Assert.That(t.Value, Is.GreaterThan(elapsedAfterDoubleDispose));\n        }\n\n        [Test]\n        public void CpuTime_Works()\n        {\n            var t0 = new Telemetry.CpuTime();\n            using (t0.Timer) for (var i = 0; i < 100000000; i++) ;\n\n            var t = new Telemetry.CpuTime();\n            Task.WaitAll(Enumerable.Range(0, 2).Select(_ => Task.Run(() =>\n            {\n                using (t.Timer)\n                {\n                    for (var i = 0; i < 100000000; i++) ;\n                    Thread.Sleep(100);\n                }\n            })\n            ).ToArray());\n\n            Assert.IsTrue(t.Value.TotalSeconds >= t0.Value.TotalSeconds * 2);\n        }\n\n        private static void RunCpuAndSyscallHeavyWorkload()\n        {\n            for (var i = 0; i < 100000000; i++) ;\n            for (var i = 0; i < 500; i++) Directory.GetFiles(\".\");\n        }\n\n        private static bool RuntimeSupportsPrivilegedProcessorTime()\n        {\n            var process = Process.GetCurrentProcess();\n            var before = process.PrivilegedProcessorTime;\n\n            RunCpuAndSyscallHeavyWorkload();\n            process.Refresh();\n\n            return process.PrivilegedProcessorTime > before;\n        }\n\n        private static void MeasureOnDedicatedThread(Action action)\n        {\n            Exception exception = null;\n            var thread = new Thread(() =>\n            {\n                try\n                {\n                    action();\n                }\n                catch (Exception e)\n                {\n                    exception = e;\n                }\n            });\n\n            thread.Start();\n            thread.Join();\n\n            if (exception != null) throw exception;\n        }\n\n        private static ThreadLocal<ProcessThread> GetCachedProcessThreadStore(object probe)\n        {\n            var field = probe.GetType().GetField(\"m_threadLocalProcessThread\", BindingFlags.Instance | BindingFlags.NonPublic);\n            Assert.That(field, Is.Not.Null);\n            return (ThreadLocal<ProcessThread>)field.GetValue(probe);\n        }\n\n        private static void PoisonCurrentThreadProcessThreadCache(object probe)\n        {\n            GetCachedProcessThreadStore(probe).Value = null;\n        }\n\n        private static void AssertCpuProbeDisposeRecoversAfterCachePoison<TProbe>(\n            TProbe probe,\n            Func<TProbe, IDisposable> getTimer,\n            Func<TProbe, double> getValue)\n        {\n            MeasureOnDedicatedThread(() =>\n            {\n                var timer = getTimer(probe);\n                var cache = GetCachedProcessThreadStore(probe);\n                if (cache.Value == null)\n                {\n                    Assert.Ignore(\"ProcessThread lookup is unavailable on this runtime/thread.\");\n                }\n\n                PoisonCurrentThreadProcessThreadCache(probe);\n                Assert.That(cache.Value, Is.Null, \"test setup failed to poison the ProcessThread cache\");\n\n                Assert.DoesNotThrow(() => timer.Dispose());\n\n                Assert.DoesNotThrow(() =>\n                {\n                    using (getTimer(probe))\n                    {\n                        for (var i = 0; i < 1000000; i++) ;\n                    }\n                });\n\n                Assert.That(cache.Value, Is.Not.Null, \"subsequent timer acquisition should repopulate the ProcessThread cache\");\n                Assert.That(getValue(probe), Is.GreaterThanOrEqualTo(0.0));\n            });\n        }\n\n        [Test]\n        public void CpuTimePrivileged_Works()\n        {\n            var supportsPrivilegedProcessorTime = RuntimeSupportsPrivilegedProcessorTime();\n            var t = new Telemetry.CpuTime();\n            var tUser = t.UserTime;\n            var tPriv = t.PrivilegedTime;\n\n            MeasureOnDedicatedThread(() =>\n            {\n                using (t.Timer) RunCpuAndSyscallHeavyWorkload();\n            });\n\n            if (t.Value <= TimeSpan.Zero || tUser.Value <= TimeSpan.Zero)\n                Assert.Ignore(\"Telemetry.CpuTime did not report positive total/user CPU time on this runtime.\");\n\n            Assert.IsTrue(t.Value.TotalSeconds > 0.0);\n            Assert.IsTrue(tUser.Value.TotalSeconds > 0.0);\n\n            if (supportsPrivilegedProcessorTime)\n            {\n                Assert.IsTrue(tPriv.Value > TimeSpan.Zero);\n            }\n            else\n            {\n                Assert.IsTrue(tPriv.Value >= TimeSpan.Zero);\n                Assert.DoesNotThrow(() =>\n                {\n                    MeasureOnDedicatedThread(() =>\n                    {\n                        using (t.Timer) RunCpuAndSyscallHeavyWorkload();\n                    });\n                });\n                Assert.IsTrue(tPriv.Value >= TimeSpan.Zero);\n            }\n        }\n\n        [Test]\n        public void CpuTime_DisposeRecoversFromPoisonedProcessThreadCache()\n        {\n            var t = new Telemetry.CpuTime();\n            AssertCpuProbeDisposeRecoversAfterCachePoison(\n                t,\n                probe => probe.Timer,\n                probe => probe.ValueDouble\n            );\n        }\n\n        [Test]\n        public void CpuTimeUser_DisposeRecoversFromPoisonedProcessThreadCache()\n        {\n            var t = new Telemetry.CpuTimeUser();\n            AssertCpuProbeDisposeRecoversAfterCachePoison(\n                t,\n                probe => probe.Timer,\n                probe => probe.ValueDouble\n            );\n        }\n\n        [Test]\n        public void CpuTimePrivileged_DisposeRecoversFromPoisonedProcessThreadCache()\n        {\n            var t = new Telemetry.CpuTimePrivileged();\n            AssertCpuProbeDisposeRecoversAfterCachePoison(\n                t,\n                probe => probe.Timer,\n                probe => probe.ValueDouble\n            );\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Tensors/TensorMatrixTests.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing NUnit.Framework;\nusing Aardvark.Base;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class TensorMatrixTests : TestSuite\n    {\n        [Test]\n        public void MatrixTranspose()\n        {\n            var matT = Matrix.Create(new[] { 1.0, -1.0, 2.0,\n                                            0.0, -3.0, 1.0 }, 3, 2).Transposed;\n            \n            var res = Matrix.Create(new[] { 1.0,  0.0,\n                                           -1.0, -3.0,\n                                            2.0,  1.0}, 2, 3);\n\n            Assert.True(res.EqualTo(matT));\n            //Assert.True(matT.Elements.ZipTuples(res.Elements).All(x => x.E0 == x.E1)); // Elements orderd by index ?!\n\n            var mat2T = Matrix.Create(new[] { 7.0, 14.0,\n                                             9.0, 18.0}, 2, 2).Transposed;\n\n            var res2 = Matrix.Create(new[] { 7.0,  9.0,\n                                           14.0, 18.0}, 2, 2);\n\n            Assert.True(res2.EqualTo(mat2T));\n            //Assert.True(mat2T.Elements.ZipTuples(res2.Elements).All(x => x.E0 == x.E1)); // Elements orderd by index ?!\n        }\n\n        [Test]\n        public void MatrixVectorMult()\n        {\n            var a = new Matrix<double>(new[] { 1.0, -1.0, 2.0,\n                                               0.0, -3.0, 1.0 }, 3, 2);\n            var b = new Vector<double>(new[] { 2.0, 1.0, 0.0 });\n            \n            var mul = a.Multiply(b);\n\n            var res = new Vector<double>(new[] { 1.0, -3.0, });\n            var res2 = new Vector<double>(a.Dim.Y).SetByCoord(x => a.GetRow((int)x).DotProduct(b));\n\n            res.Data.ForEach((x, i) => Assert.True(x == mul.Data[i], \"Wrong result\"));\n\n            Assert.True(res.EqualTo(mul));\n            Assert.True(res2.EqualTo(mul));\n        }\n\n        [Test]\n        public void MatrixVectorMultTransposed()\n        {\n            var a = new Matrix<double>(new[] { 1.0,  0.0,\n                                              -1.0, -3.0,\n                                               2.0,  1.0 }, 2, 3);\n            var b = new Vector<double>(new[] { 2.0, 1.0, 0.0 });\n\n            var mul = a.Transposed.Multiply(b);\n\n            var res = new Vector<double>(new[] { 1.0, -3.0, });\n\n            res.Data.ForEach((x, i) => Assert.True(x == mul.Data[i], \"Wrong result\"));\n\n            Assert.True(res.EqualTo(mul));\n        }\n\n        [Test]\n        public void MatrixMatrixMult()\n        {\n            var a = new Matrix<double>(new[] { 0.0,  4.0, -2.0,\n                                              -4.0, -3.0,  0.0 }, 3, 2);\n            var b = new Matrix<double>(new[] { 0.0,  1.0,\n                                               1.0, -1.0,\n                                               2.0,  3.0}, 2, 3);\n\n            var mul = a.Multiply(b);\n\n            var res = new Matrix<double>(new[] { 0.0, -10.0,\n                                                -3.0, -1.0 }, 2, 2);\n\n            res.Data.ForEach((x, i) => Assert.True(x == mul.Data[i], \"Wrong result\"));\n\n            Assert.True(res.EqualTo(mul));\n        }\n\n        [Test]\n        public void MatrixMatrixMultTranspose()\n        {\n            var a = Matrix.Create(new[] { 1.0, 2.0, 3.0,\n                                          4.0, 5.0, 6.0 }, 3, 2);\n            var b = Matrix.Create(new[] { 7.0, 9.0, 11.0,\n                                          8.0, 10.0, 12.0 }, 3, 2);\n\n            var mul = a.Multiply(b.Transposed);\n\n            var res = Matrix.Create(new[] { 58.0,  64.0,\n                                           139.0, 154.0 }, 2, 2);\n            \n            Assert.True(res.EqualTo(mul));\n        }\n\n        [Test]\n        public void VectorVectorMult()\n        {\n            var a = Vector.Create(new[] { 1.0, 2.0, 3.0 });\n            var b = Vector.Create(new[] { 7.0, 9.0, 11.0});\n\n            var mul = a.Multiply(b);\n\n            var res = Vector.Create(new[] { 7.0, 18.0, 33.0 });\n            \n            Assert.True(res.EqualTo(mul));\n            \n            var mat = a.MultiplyTransposed(b);\n\n            var matRes1 = new Matrix<double>(b.Dim, a.Dim).SetByCoord(crd => a[crd.Y] * b[crd.X]);\n\n            var matRes2 = Matrix.Create(new[] { 7.0, 14.0, 21.0,\n                                               9.0, 18.0, 27.0,\n                                              11.0, 22.0, 33.0}, 3, 3).Transposed;\n            \n            var m1 = Matrix.Create(a.Data, 3, 1);\n            var m2 = Matrix.Create(b.Data, 3, 1);\n\n            var matRes3 = m1.Transposed.Multiply(m2);\n\n            Assert.True(mat.EqualTo(matRes1));\n            Assert.True(mat.EqualTo(matRes2));\n            Assert.True(mat.EqualTo(matRes3));\n        }\n\n        [Test]\n        public void MatrixArithmetic()\n        {\n            var a = Matrix.Create(new[] { 1.0, 2.0, 3.0,\n                                          4.0, 5.0, 6.0 }, 3, 2);\n            var b = Matrix.Create(new[] { 7.0, 9.0, 11.0,\n                                          8.0, 10.0, 12.0 }, 3, 2);\n\n            var ab = a.Add(b);\n            var addRes = Matrix.Create(new[] { 8.0, 11.0, 14.0,\n                                               12.0, 15.0, 18.0}, 3, 2);\n\n            Assert.True(ab.EqualTo(addRes));\n\n            var a2 = a.Add(2);\n            var addRes2 = Matrix.Create(new[] { 3.0, 4.0, 5.0,\n                                                6.0, 7.0, 8.0}, 3, 2);\n\n            Assert.True(a2.EqualTo(addRes2));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/TestSuite/TestSuite.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n\n    /// <summary>\n    /// The TestSuite is configured to use NUnit by default, but can\n    /// be constructed to be used without NUnit.\n    /// </summary>\n    public class TestSuite\n    {\n        public Options Opt;\n\n        [Flags]\n        public enum Options\n        {\n            None = 0x0000,\n            UseLogTarget = 0x0001,\n            UseNUnit = 0x0002,\n\n            Default = UseNUnit,\n        }\n\n        /// <summary>\n        /// This member provides the API for running tests,\n        /// e.g. Test.Begin(...); Test.IsTrue(...); Test.End();\n        /// </summary>\n        public Info Test;\n\n        /// <summary>\n        /// The default constructor uses NUnit, and turns off the log\n        /// file to make it work with TeamCity/NUnit.\n        /// </summary>\n        public TestSuite() : this(Options.Default)  { }\n\n\n        public TestSuite(Options options)\n        {\n            Opt = options;\n            if ((options & Options.UseLogTarget) == 0) Report.Targets.Remove(Report.LogTarget);\n            Test = new Info(TestInfo.Empty, (options & Options.UseNUnit) != 0);\n        }\n\n        public class Info\n        {\n            internal TestInfo m_ti;\n            internal bool m_useNUnit;\n\n            public Info(TestInfo ti, bool useNUnit) { m_ti = ti; m_useNUnit = useNUnit; }\n\n            /// <summary>\n            /// Begin a named, timed test.\n            /// </summary>\n            public void Begin(string testName, params object[] args)\n            {\n                Report.BeginTimed(testName, args);\n                m_ti = TestInfo.Empty;\n            }\n\n            /// <summary>\n            /// Begin a named, timed test.\n            /// </summary>\n            public void Begin(int level, string testName, params object[] args)\n            {\n                Report.BeginTimed(level, testName, args);\n                m_ti = TestInfo.Empty;\n            }\n\n            /// <summary>\n            /// End the test, and report results.\n            /// </summary>\n            public void End()\n            {\n                Report.Tests(m_ti); Report.End();\n                m_ti = TestInfo.Empty;\n            }\n\n            /// <summary>\n            /// End the test, and report results.\n            /// </summary>\n            public void End(string message, params object[] args)\n            {\n                Report.Tests(m_ti); Report.End(message, args);\n                m_ti = TestInfo.Empty;\n            }\n\n            /// <summary>\n            /// End the test, and report results.\n            /// </summary>\n            public void End(int level)\n            {\n                Report.Tests(m_ti); Report.End(level);\n                m_ti = TestInfo.Empty;\n            }\n\n            /// <summary>\n            /// End the test, and report results.\n            /// </summary>\n            public void End(int level, string message, params object[] args)\n            {\n                Report.Tests(m_ti); Report.End(level, message, args);\n                m_ti = TestInfo.Empty;\n            }\n\n            /// <summary>\n            /// Test if the supplied condition is true.\n            /// </summary>\n            public bool IsTrue(bool condition)\n            {\n                if (m_useNUnit) Assert.IsTrue(condition);\n                if (condition)\n                {\n                    m_ti.PassedCount++; return true;\n                }\n                else\n                {\n                    m_ti.FailedCount++; return false;\n                }\n            }\n\n            /// <summary>\n            /// Test if the supplied condition is false.\n            /// </summary>\n            public bool IsFalse(bool condition)\n            {\n                if (m_useNUnit) Assert.IsFalse(condition);\n                if (condition)\n                {\n                    m_ti.FailedCount++; return false;\n                }\n                else\n                {\n                    m_ti.PassedCount++; return true;\n                }\n            }\n\n            /// <summary>\n            /// Test if the supplied condition is true. Warn if this is not the case,\n            /// using the supplied massage.\n            /// </summary>\n            public bool IsTrue(bool condition, string messageIfFalse, params object[] args)\n            {\n                if (m_useNUnit) Assert.IsTrue(condition);\n                if (condition)\n                {\n                    m_ti.PassedCount++; return true;\n                }\n                else\n                {\n                    m_ti.FailedCount++;\n                    Report.Warn(messageIfFalse, args);\n                    return false;\n                }\n            }\n\n            /// <summary>\n            /// Test if the supplied condition is false. Warn if this is not the case,\n            /// using the supplied massage.\n            /// </summary>\n            public bool IsFalse(bool condition, string messageIfTrue, params object[] args)\n            {\n                if (m_useNUnit) Assert.IsFalse(condition);\n                if (condition)\n                {\n                    m_ti.FailedCount++;\n                    Report.Warn(messageIfTrue, args);\n                    return true;\n                }\n                else\n                {\n                    m_ti.PassedCount++;\n                    return false;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/AffineTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class AffineTests\n    {\n        [Test]\n        public static void FromM34d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomAffine, a => (M34d)a, b => Affine3d.FromM34d(b));\n\n        [Test]\n        public static void FromM44d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomAffine, a => (M44d)a, b => Affine3d.FromM44d(b));\n\n        [Test]\n        public static void FromTrafo3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomAffine, a => (Trafo3d)a, b => Affine3d.FromTrafo3d(b));\n\n        [Test]\n        public static void Comparison()\n            => TrafoTesting.GenericComparisonTest(TrafoTesting.GetRandomAffine, a => new Affine3d(a.Linear, a.Trans + V3d.OII));\n\n        [Test]\n        public static void InverseTest()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var a = TrafoTesting.GetRandomAffine(rnd);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var q = a.TransformPos(p);\n\n                // Inverse property\n                var res = a.Inverse.TransformPos(q);\n\n                // Invert method\n                Affine.Invert(ref a);\n                var res2 = a.TransformPos(q);\n\n                TrafoTesting.AreEqual(p, res);\n                TrafoTesting.AreEqual(p, res2);\n            });\n\n        [Test]\n        public static void Multiplication3x3Test()\n            => TrafoTesting.GenericMatrixMultiplicationTest<Affine3d, M33d, M34d>(\n                rnd => TrafoTesting.GetRandomAffine(rnd, false),\n                Affine.TransformPos,\n                Mat.Transform,\n                Mat.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ,\n                (m, v) => m * v,\n                (m, v) => m * new V4d(v, 1));\n\n        [Test]\n        public static void Multiplication3x4Test()\n            => TrafoTesting.Generic3x4MultiplicationTest(\n                TrafoTesting.GetRandomAffine,\n                Affine.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ);\n\n        [Test]\n        public static void Multiplication4x4Test()\n            => TrafoTesting.Generic4x4MultiplicationTest(\n                TrafoTesting.GetRandomAffine,\n                Affine.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ);\n\n        [Test]\n        public static void MultiplicationAffine3x4Test()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var a = TrafoTesting.GetRandomAffine(rnd);\n                var b = TrafoTesting.GetRandomAffine(rnd);\n                var ma = (M34d) a;\n                var mb = (M34d) b;\n\n                var a_x_b = a * b;\n                var ma_x_mb = Mat.MultiplyAffine(ma, mb);\n\n                TrafoTesting.AreEqual((M34d)a_x_b, ma_x_mb);\n            });\n\n        [Test]\n        public static void MultiplicationFull4x4Test()\n            => TrafoTesting.GenericFull4x4MultiplicationTest(TrafoTesting.GetRandomAffine);\n\n        [Test]\n        public static void MultiplicationAffineTest()\n            => TrafoTesting.GenericMultiplicationTest<Affine3d, Affine3d, Affine3d>(TrafoTesting.GetRandomAffine, TrafoTesting.GetRandomAffine, Affine.TransformPos);\n\n        [Test]\n        public static void MultiplicationEuclideanTest()\n            => TrafoTesting.GenericMultiplicationTest<Affine3d, Euclidean3d, Affine3d>(TrafoTesting.GetRandomAffine, TrafoTesting.GetRandomEuclidean, Affine.TransformPos);\n\n        [Test]\n        public static void MultiplicationRotTest()\n            => TrafoTesting.GenericMultiplicationTest<Affine3d, Rot3d, Affine3d>(TrafoTesting.GetRandomAffine, TrafoTesting.GetRandomRot3, Affine.TransformPos);\n\n        [Test]\n        public static void MultiplicationScaleTest()\n            => TrafoTesting.GenericMultiplicationTest<Affine3d, Scale3d, Affine3d>(TrafoTesting.GetRandomAffine, TrafoTesting.GetRandomScale3, Affine.TransformPos);\n\n        [Test]\n        public static void MultiplicationShiftTest()\n            => TrafoTesting.GenericMultiplicationTest<Affine3d, Shift3d, Affine3d>(TrafoTesting.GetRandomAffine, TrafoTesting.GetRandomShift3, Affine.TransformPos);\n\n        [Test]\n        public static void MultiplicationSimilarityTest()\n            => TrafoTesting.GenericMultiplicationTest<Affine3d, Similarity3d, Affine3d>(TrafoTesting.GetRandomAffine, TrafoTesting.GetRandomSimilarity, Affine.TransformPos);\n\n        [Test]\n        public static void ToStringAndParse()\n            => TrafoTesting.GenericToStringAndParseTest(TrafoTesting.GetRandomAffine, Affine3d.Parse);\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/EuclideanTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class EuclideanTests\n    {\n        [Test]\n        public static void FromM33dAndV3d()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var a = TrafoTesting.GetRandomEuclidean(rnd);\n                var m = (M33d)a.Rot;\n                var t = a.Trans;\n\n                var restored = Euclidean3d.FromM33dAndV3d(m, t);\n                TrafoTesting.AreEqual(a, restored);\n            });\n\n        [Test]\n        public static void FromM34d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomEuclidean, a => (M34d)a, b => Euclidean3d.FromM34d(b));\n\n        [Test]\n        public static void FromM44d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomEuclidean, a => (M44d)a, b => Euclidean3d.FromM44d(b));\n\n        [Test]\n        public static void FromSimilarity3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomEuclidean, a => (Similarity3d)a, b => Euclidean3d.FromSimilarity3d(b));\n\n        [Test]\n        public static void FromAffine3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomEuclidean, a => (Affine3d)a, b => Euclidean3d.FromAffine3d(b));\n\n        [Test]\n        public static void FromTrafo3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomEuclidean, a => (Trafo3d)a, b => Euclidean3d.FromTrafo3d(b));\n\n        [Test]\n        public static void Comparison()\n            => TrafoTesting.GenericComparisonTest(TrafoTesting.GetRandomEuclidean, a => new Euclidean3d(a.Rot, a.Trans + V3d.OII));\n\n        [Test]\n        public static void InverseTest()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var e = TrafoTesting.GetRandomEuclidean(rnd);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var q = e.TransformPos(p);\n\n                // Inverse property\n                var res = e.Inverse.TransformPos(q);\n\n                // Invert method\n                Euclidean.Invert(ref e);\n                var res2 = e.TransformPos(q);\n\n                TrafoTesting.AreEqual(p, res);\n                TrafoTesting.AreEqual(p, res2);\n            });\n\n        [Test]\n        public static void Multiplication3x3Test()\n            => TrafoTesting.GenericMatrixMultiplicationTest<Euclidean3d, M33d, M34d>(\n                rnd => TrafoTesting.GetRandomEuclidean(rnd, false),\n                Euclidean.TransformPos,\n                Mat.Transform,\n                Mat.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ,\n                (m, v) => m * v,\n                (m, v) => m * new V4d(v, 1));\n\n        [Test]\n        public static void Multiplication3x4Test()\n            => TrafoTesting.Generic3x4MultiplicationTest(\n                TrafoTesting.GetRandomEuclidean,\n                Euclidean.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ);\n\n        [Test]\n        public static void Multiplication4x4Test()\n            => TrafoTesting.Generic4x4MultiplicationTest(\n                TrafoTesting.GetRandomEuclidean,\n                Euclidean.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ);\n\n        [Test]\n        public static void MultiplicationFull4x4Test()\n            => TrafoTesting.GenericFull4x4MultiplicationTest(TrafoTesting.GetRandomEuclidean);\n\n        [Test]\n        public static void ConsistentWithMatrixRotationAndShiftTest()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var trans = rnd.UniformV3d() * 10;\n\n                var axis = rnd.UniformV3dDirection();\n                var angle = rnd.UniformDouble() * Constant.PiTimesTwo;\n\n                var m = M44d.Translation(trans) * M44d.Rotation(axis, angle);\n                var e = new Euclidean3d(Rot3d.Rotation(axis, angle), trans);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var res = m.TransformPos(p);\n                var res2 = e.TransformPos(p);\n\n                TrafoTesting.AreEqual(res, res2);\n            });\n\n        [Test]\n        public static void MultiplicationEuclideanTest()\n            => TrafoTesting.GenericMultiplicationTest<Euclidean3d, Euclidean3d, Euclidean3d>(TrafoTesting.GetRandomEuclidean, TrafoTesting.GetRandomEuclidean, Euclidean.TransformPos);\n\n        [Test]\n        public static void MultiplicationRotTest()\n            => TrafoTesting.GenericMultiplicationTest<Euclidean3d, Rot3d, Euclidean3d>(TrafoTesting.GetRandomEuclidean, TrafoTesting.GetRandomRot3, Euclidean.TransformPos);\n\n        [Test]\n        public static void MultiplicationShiftTest()\n            => TrafoTesting.GenericMultiplicationTest<Euclidean3d, Shift3d, Euclidean3d>(TrafoTesting.GetRandomEuclidean, TrafoTesting.GetRandomShift3, Euclidean.TransformPos);\n\n        [Test]\n        public static void MultiplicationScaleTest()\n            => TrafoTesting.GenericMultiplicationTest<Euclidean3d, Scale3d, Affine3d>(TrafoTesting.GetRandomEuclidean, TrafoTesting.GetRandomScale3, Affine.TransformPos);\n\n        [Test]\n        public static void ToStringAndParse()\n            => TrafoTesting.GenericToStringAndParseTest(TrafoTesting.GetRandomEuclidean, Euclidean3d.Parse);\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/MatrixTests.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class MatrixTests : TestSuite\n    {\n        public MatrixTests() : base() { }\n        public MatrixTests(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public void BitwiseOperationsTest()\n        {\n            var m = new M22l(1, 2, 3, 4);\n            Assert.AreEqual(~m, new M22l(~m.M00, ~m.M01, ~m.M10, ~m.M11));\n            Assert.AreEqual(m << 1, new M22l(2, 4, 6, 8));\n            Assert.AreEqual(m >> 1, new M22l(0, 1, 1, 2));\n            Assert.AreEqual(m | 1, new M22l(m.M00 | 1, m.M01 | 1, m.M10 | 1, m.M11 | 1));\n            Assert.AreEqual(1 | m, new M22l(1 | m.M00, 1 | m.M01, 1 | m.M10, 1 | m.M11));\n            Assert.AreEqual(m | m, new M22l(m.M00 | m.M00, m.M01 | m.M01, m.M10 | m.M10, m.M11 | m.M11));\n            Assert.AreEqual(m & 1, new M22l(m.M00 & 1, m.M01 & 1, m.M10 & 1, m.M11 & 1));\n            Assert.AreEqual(1 & m, new M22l(1 & m.M00, 1 & m.M01, 1 & m.M10, 1 & m.M11));\n            Assert.AreEqual(m & m, new M22l(m.M00 & m.M00, m.M01 & m.M01, m.M10 & m.M10, m.M11 & m.M11));\n            Assert.AreEqual(m ^ 1, new M22l(m.M00 ^ 1, m.M01 ^ 1, m.M10 ^ 1, m.M11 ^ 1));\n            Assert.AreEqual(1 ^ m, new M22l(1 ^ m.M00, 1 ^ m.M01, 1 ^ m.M10, 1 ^ m.M11));\n            Assert.AreEqual(m ^ m, new M22l(m.M00 ^ m.M00, m.M01 ^ m.M01, m.M10 ^ m.M10, m.M11 ^ m.M11));\n        }\n\n        [Test]\n        public void MinMaxElementTest()\n        {\n            var rnd = new RandomSystem(1);\n            var m = rnd.UniformM44i();\n\n            var min1 = m.MinElement;\n            var min2 = Mat.MinElement(m);\n            var min_ref = m.ToArray().Min();\n\n            Assert.AreEqual(min1, min_ref);\n            Assert.AreEqual(min2, min_ref);\n\n            var max1 = m.MaxElement;\n            var max2 = Mat.MaxElement(m);\n            var max_ref = m.ToArray().Max();\n\n            Assert.AreEqual(max1, max_ref);\n            Assert.AreEqual(max2, max_ref);\n        }\n\n        [Test]\n        public void InPlaceTransposeTest()\n        {\n            var rand = new RandomSystem();\n\n            var m = new M44d(rand.CreateUniformDoubleArray(16));\n            var transposed = m.Transposed;\n            Mat.Transpose(ref m);\n\n            Assert.IsTrue(Fun.ApproximateEquals(m, transposed, 0.0001));\n        }\n\n        [Test]\n        public void InverseTest()\n        {\n            MatrixInverseTest(1, 1 << 16);\n        }\n\n        [Test]\n        public void MultiplicationTest()\n        {\n            MatrixMultiplicationTest();\n        }\n\n        public void Run()\n        {\n            MatrixMultiplicationTest();\n            MatrixInverseTest(16, 1 << 20);\n        }\n\n        public void MatrixMultiplicationTest()\n        {\n            using (Report.JobTimed(\"Matrix multiplication tests\"))\n            {\n                var rand = new RandomSystem();\n\n                Test.Begin(\"Row vector with matrix\");\n                var m = new M44d(rand.CreateUniformDoubleArray(16));\n                var v = new V4d(rand.CreateUniformDoubleArray(4));\n\n                Test.IsTrue(v * m == m.Transposed * v);\n                Test.End();\n            }\n        }\n\n        public void MatrixInverseTest(int rounds, int count,\n                                      bool doLuM = true, bool doLuV = true, bool doLu2 = true,\n                                      bool doGj2 = false,\n                                      bool doQrI = true, bool doQr2 = true)\n        {\n            bool doMul = true;\n            double luEpsilon = 1e-5;\n            double qrEpsilon = 4e-5;\n            Test.Begin(\"matrix inverse tests\");\n            Report.Line(\"epsilon for lu tests: {0:e0}\", luEpsilon);\n            Report.Line(\"epsilon for qr tests: {0:e0}\", qrEpsilon);\n            bool showWorst = true;\n            bool showTypes = true;\n            var rnd = new RandomSystem(19680713);\n\n            var tc = 4;\n            var typeStatsOpt = Stats<M44d>.ComputeCountMaxMean;\n            Stats<M44d>[] luiTypeStats = new Stats<M44d>[tc].Set(typeStatsOpt);\n            Stats<M44d>[] lumTypeStats = new Stats<M44d>[tc].Set(typeStatsOpt);\n            Stats<M44d>[] luvTypeStats = new Stats<M44d>[tc].Set(typeStatsOpt);\n            Stats<M44d>[] lu2TypeStats = new Stats<M44d>[tc].Set(typeStatsOpt);\n            Stats<M44d>[] gj2TypeStats = new Stats<M44d>[tc].Set(typeStatsOpt);\n            Stats<M44d>[] qriTypeStats = new Stats<M44d>[tc].Set(typeStatsOpt);\n            Stats<M44d>[] qr2TypeStats = new Stats<M44d>[tc].Set(typeStatsOpt);\n            string[] typenames = new string[] { \"Rotation\", \"Scale\", \"Translation\", \"Mixed\" };\n\n            var histoStatsOpt = StatsOptions.MaxMean;\n            var luiHistoStats = new HistogramAndStats<M44d>(-16, 0, 16, histoStatsOpt);\n            var lumHistoStats = new HistogramAndStats<M44d>(-16, 0, 16, histoStatsOpt);\n            var luvHistoStats = new HistogramAndStats<M44d>(-16, 0, 16, histoStatsOpt);\n            var lu2HistoStats = new HistogramAndStats<M44d>(-16, 0, 16, histoStatsOpt);\n            var gj2HistoStats = new HistogramAndStats<M44d>(-16, 0, 16, histoStatsOpt);\n            var qriHistoStats = new HistogramAndStats<M44d>(-16, 0, 16, histoStatsOpt);\n            var qr2HistoStats = new HistogramAndStats<M44d>(-16, 0, 16, histoStatsOpt);\n\n            M44d[] mats = new M44d[count];\n            M44d[] luis = new M44d[count];\n            M44d[] lums = new M44d[count];\n            M44d[] luvs = new M44d[count];\n            M44d[] lu2s = new M44d[count];\n            M44d[] gj2s = new M44d[count];\n            M44d[] qris = new M44d[count];\n            M44d[] qr2s = new M44d[count];\n            int[] types = new int[count].SetByIndex(i => -1);\n\n            bool failedLuM = false, failedLuV = false, failedLu2 = false;\n            bool failedQr2 = false;\n            var chainStats = new Stats<bool>(StatsOptions.MaxMean);\n\n            for (int j = 0; j < rounds; j++)\n            {\n                using (Report.JobTimed(\"creating {0} matrices round {1} of {2}\", count, j + 1, rounds))\n                    for (int i = 0; i < count; i++)\n                    {\n                        M44d mat = M44d.Identity;\n                        var chainLength = 0;\n                        do\n                        {\n                            int type = rnd.UniformInt(3);\n                            if (types[i] == -1) types[i] = type;\n                            else if (types[i] != type)\n                                types[i] = 3; //mixed type\n                            switch (type)\n                            {\n                                case 0:\n                                    V3d axis = V3d.Zero;\n                                    double squaredLength = 0.0;\n                                    do\n                                    {\n                                        axis = new V3d(2 * rnd.UniformDoubleFullClosed() - 1,\n                                                       2 * rnd.UniformDoubleFullClosed() - 1,\n                                                       2 * rnd.UniformDoubleFullClosed() - 1);\n                                        squaredLength = axis.LengthSquared;\n                                    }\n                                    while (squaredLength == 0);\n                                    axis *= 1.0 / Fun.Sqrt(squaredLength);\n                                    double alpha = 2 * Constant.Pi * rnd.UniformDoubleFull()\n                                                   - Constant.Pi;\n                                    M44d rot = M44d.Rotation(axis, alpha);\n                                    mat = rot * mat;\n                                    chainLength++;\n                                    break;\n                                case 1:\n                                    var s0 = rnd.UniformDouble() < 0.5 ? -4.0 : 4.0;\n                                    var s1 = rnd.UniformDouble() < 0.5 ? -4.0 : 4.0;\n                                    var s2 = rnd.UniformDouble() < 0.5 ? -4.0 : 4.0;\n                                    M44d scale = M44d.Scale(\n                                                    s0 * (1.0 - rnd.UniformDoubleFull()),\n                                                    s1 * (1.0 - rnd.UniformDoubleFull()),\n                                                    s2 * (1.0 - rnd.UniformDoubleFull()));\n                                    mat = scale * mat;\n                                    chainLength++;\n                                    break;\n                                case 2:\n                                    M44d shift = M44d.Translation(\n                                                    32 * rnd.UniformDoubleFullClosed() - 16,\n                                                    32 * rnd.UniformDoubleFullClosed() - 16,\n                                                    32 * rnd.UniformDoubleFullClosed() - 16);\n                                    mat = shift * mat;\n                                    chainLength++;\n                                    break;\n                                default:\n                                    break;\n                            }\n                        }\n                        while (rnd.UniformDouble() > 0.25);\n                        mats[i] = mat;\n                        chainStats.Add(chainLength);\n                    }\n\n                if (doQr2)\n                    using (Report.JobTimed(\"qr [,] factorization\"))\n                        for (int i = 0; i < count; i++)\n                            qr2s[i] = mats[i].QrInverse2();\n\n                if (doQrI)\n                    using (Report.JobTimed(\"qr factorization\"))\n                        for (int i = 0; i < count; i++)\n                            qris[i] = mats[i].QrInverse();\n\n                if (doGj2)\n                    using (Report.JobTimed(\"gauss jordan\"))\n                        for (int i = 0; i < count; i++)\n                            gj2s[i] = mats[i].NumericallyInstableGjInverse2();\n\n                if (doLu2)\n                    using (Report.JobTimed(\"lu [,] factorization\"))\n                        for (int i = 0; i < count; i++)\n                            lu2s[i] = mats[i].LuInverse2();\n\n                if (doLuV)\n                    using (Report.JobTimed(\"lu vector solve factorization\"))\n                        for (int i = 0; i < count; i++)\n                            luvs[i] = mats[i].LuInverseV();\n\n                if (doLuM)\n                    using (Report.JobTimed(\"lu matrix solve factorization\"))\n                        for (int i = 0; i < count; i++)\n                            lums[i] = mats[i].LuInverseM();\n\n                using (Report.JobTimed(\"lu factorization\"))\n                    for (int i = 0; i < count; i++)\n                        luis[i] = mats[i].LuInverse();\n\n                Test.Begin(\"analysis\");\n                for (int i = 0; i < count; i++)\n                {\n                    M44d luid = mats[i] * luis[i];\n                    double plErr = Mat.DistanceMax(luid, M44d.Identity);\n                    Test.IsTrue(plErr < luEpsilon);\n                    luiHistoStats.AddLog10Hist(plErr, mats[i]);\n                    luiTypeStats[types[i]].Add(plErr);\n                    if (doMul)\n                    {\n                        var m0 = new Matrix<double>((double[])mats[i], 4, 4);\n                        var m1 = new Matrix<double>((double[])luis[i], 4, 4);\n                        var id = m0.Multiply(m1);\n                        double deltaErr = Mat.Distance1(luid, new M44d(id.Data));\n                        Test.IsTrue(deltaErr == 0.0);\n                    }\n\n\n                    if (doLuM)\n                    {\n                        M44d msid = mats[i] * lums[i];\n                        double error = Mat.DistanceMax(msid, M44d.Identity);\n                        lumHistoStats.AddLog10Hist(error, mats[i]);\n                        lumTypeStats[types[i]].Add(error);\n                        double deltaErr = Mat.Distance1(luis[i], lums[i]);\n                        if (!Test.IsTrue(deltaErr == 0.0)) failedLuM = true;\n                    }\n                    if (doLuV)\n                    {\n                        M44d vsid = mats[i] * luvs[i];\n                        double error = Mat.DistanceMax(vsid, M44d.Identity);\n                        luvHistoStats.AddLog10Hist(error, mats[i]);\n                        luvTypeStats[types[i]].Add(error);\n                        double deltaErr = Mat.Distance1(luis[i], luvs[i]);\n                        if (!Test.IsTrue(deltaErr == 0.0)) failedLuV = true;\n                    }\n                    if (doLu2)\n                    {\n                        M44d a2id = mats[i] * lu2s[i];\n                        double error = Mat.DistanceMax(a2id, M44d.Identity);\n                        lu2HistoStats.AddLog10Hist(error, mats[i]);\n                        lu2TypeStats[types[i]].Add(error);\n                        double deltaErr = Mat.Distance1(luis[i], lu2s[i]);\n                        if (!Test.IsTrue(deltaErr == 0.0)) failedLu2 = true;\n                    }\n                    if (doGj2)\n                    {\n                        M44d gjid = mats[i] * gj2s[i];\n                        double error = Mat.DistanceMax(gjid, M44d.Identity);\n                        gj2HistoStats.AddLog10Hist(error, mats[i]);\n                        gj2TypeStats[types[i]].Add(error);\n                    }\n                    if (doQrI)\n                    {\n                        M44d qrid = mats[i] * qris[i];\n                        double error = Mat.DistanceMax(qrid, M44d.Identity);\n                        qriHistoStats.AddLog10Hist(error, mats[i]);\n                        qriTypeStats[types[i]].Add(error);\n                        Test.IsTrue(error < qrEpsilon);\n                    }\n                    if (doQr2)\n                    {\n                        M44d qrid = mats[i] * qr2s[i];\n                        double error = Mat.DistanceMax(qrid, M44d.Identity);\n                        qr2HistoStats.AddLog10Hist(error, mats[i]);\n                        qr2TypeStats[types[i]].Add(error);\n                        double deltaErr = Mat.Distance1(qris[i], qr2s[i]);\n                        if (!Test.IsTrue(deltaErr == 0.0)) failedQr2 = true;\n                    }\n                }\n                Test.End();\n            }\n\n            Report.Value(\"matrix chain lengths\", chainStats);\n            Report.Value(\"lu factorization error\", luiHistoStats.Stats);\n            if (showTypes)\n                for (int ti = 0; ti < tc; ti++)\n                    Report.Value(\"lu \" + typenames[ti] + \" matrix factorization error\",\n                        luiTypeStats[ti]);\n            Report.Value(\"lu factorization log error histogram\", luiHistoStats.Histogram);\n\n            if (showWorst)\n            {\n                using (Report.Job(\"worst matrix\")) WriteMat(luiHistoStats.Stats.MaxData);\n                using (Report.Job(\"worst inverse\")) WriteMat(luiHistoStats.Stats.MaxData.LuInverse());\n                using (Report.Job(\"worst result\")) WriteMat(luiHistoStats.Stats.MaxData\n                                                            * luiHistoStats.Stats.MaxData.LuInverse());\n            }\n\n            if (failedLuM)\n            {\n                Report.Value(\"lu matrix solve factorization error\", lumHistoStats.Stats);\n                if (showTypes)\n                    for (int ti = 0; ti < tc; ti++)\n                        Report.Value(\"lu matrix solve \" + typenames[ti] + \" matrix factorization error\",\n                            lumTypeStats[ti]);\n                Report.Value(\"lu matrix solve factorization log error histogram\", lumHistoStats.Histogram);\n                if (showWorst)\n                {\n                    using (Report.Job(\"worst matrix\")) WriteMat(lumHistoStats.Stats.MaxData);\n                    using (Report.Job(\"worst inverse\")) WriteMat(lumHistoStats.Stats.MaxData.LuInverseM());\n                    using (Report.Job(\"worst result\")) WriteMat(lumHistoStats.Stats.MaxData\n                                                                * lumHistoStats.Stats.MaxData.LuInverseM());\n                }\n            }\n\n            if (failedLuV)\n            {\n                Report.Value(\"lu vector solve factorization error\", luvHistoStats.Stats);\n                if (showTypes)\n                    for (int ti = 0; ti < tc; ti++)\n                        Report.Value(\"lu vector solve \" + typenames[ti] + \" matrix factorization error\",\n                            luvTypeStats[ti]);\n                Report.Value(\"lu vector solve factorization log error histogram\", luvHistoStats.Histogram);\n                if (showWorst)\n                {\n                    using (Report.Job(\"worst matrix\")) WriteMat(luvHistoStats.Stats.MaxData);\n                    using (Report.Job(\"worst inverse\")) WriteMat(luvHistoStats.Stats.MaxData.LuInverseV());\n                    using (Report.Job(\"worst result\")) WriteMat(luvHistoStats.Stats.MaxData\n                                                                * luvHistoStats.Stats.MaxData.LuInverseV());\n                }\n            }\n\n            if (failedLu2)\n            {\n                Report.Value(\"lu [,] factorization error\", lu2HistoStats.Stats);\n                if (showTypes)\n                    for (int ti = 0; ti < tc; ti++)\n                        Report.Value(\"lu [,] \" + typenames[ti] + \" matrix factorization error\",\n                            lu2TypeStats[ti]);\n                Report.Value(\"lu [,] factorization log error histogram\", lu2HistoStats.Histogram);\n                if (showWorst)\n                {\n                    using (Report.Job(\"worst matrix\")) WriteMat(lu2HistoStats.Stats.MaxData);\n                    using (Report.Job(\"worst inverse\")) WriteMat(lu2HistoStats.Stats.MaxData.LuInverse2());\n                    using (Report.Job(\"worst result\")) WriteMat(lu2HistoStats.Stats.MaxData\n                                                                * lu2HistoStats.Stats.MaxData.LuInverse2());\n                }\n            }\n\n            if (doGj2)\n            {\n                Report.Value(\"gauss jordan error\", gj2HistoStats.Stats);\n                if (showTypes)\n                    for (int ti = 0; ti < tc; ti++)\n                        Report.Value(\"gj \" + typenames[ti] + \" matrix factorization error\",\n                            gj2TypeStats[ti]);\n                Report.Value(\"gauss jordan log error histogram\", gj2HistoStats.Histogram);\n                if (showWorst)\n                {\n                    using (Report.Job(\"worst matrix\")) WriteMat(gj2HistoStats.Stats.MaxData);\n                    using (Report.Job(\"worst inverse\")) WriteMat(gj2HistoStats.Stats.MaxData.NumericallyInstableGjInverse2());\n                    using (Report.Job(\"worst result\")) WriteMat(gj2HistoStats.Stats.MaxData\n                                                                * gj2HistoStats.Stats.MaxData.NumericallyInstableGjInverse2());\n                }\n            }\n\n            if (doQrI)\n            {\n                Report.Value(\"qr factorization error\", qr2HistoStats.Stats);\n                if (showTypes)\n                    for (int ti = 0; ti < tc; ti++)\n                        Report.Value(\"qr \" + typenames[ti] + \" matrix factorization error\",\n                            qriTypeStats[ti]);\n                Report.Value(\"qr factorization log error histogram\", qriHistoStats.Histogram);\n                if (showWorst)\n                {\n                    using (Report.Job(\"worst matrix\")) WriteMat(qriHistoStats.Stats.MaxData);\n                    using (Report.Job(\"worst inverse\")) WriteMat(qriHistoStats.Stats.MaxData.QrInverse());\n                    using (Report.Job(\"worst result\")) WriteMat(qriHistoStats.Stats.MaxData\n                                                                * qriHistoStats.Stats.MaxData.QrInverse());\n                }\n            }\n            if (failedQr2)\n            {\n                Report.Value(\"qr [,] factorization error\", qr2HistoStats.Stats);\n                if (showTypes)\n                    for (int ti = 0; ti < tc; ti++)\n                        Report.Value(\"qr [,] \" + typenames[ti] + \" matrix factorization error\",\n                            qr2TypeStats[ti]);\n                Report.Value(\"qr [,] factorization log error histogram\", qr2HistoStats.Histogram);\n                if (showWorst)\n                {\n                    using (Report.Job(\"worst matrix\")) WriteMat(qr2HistoStats.Stats.MaxData);\n                    using (Report.Job(\"worst inverse\")) WriteMat(qr2HistoStats.Stats.MaxData.QrInverse2());\n                    using (Report.Job(\"worst result\")) WriteMat(qr2HistoStats.Stats.MaxData\n                                                                * qr2HistoStats.Stats.MaxData.QrInverse2());\n                }\n            }\n            Test.End();\n        }\n\n        public static void WriteMat(M44d mat)\n        {\n            Report.Line(\"[ {0},\", mat.R0.ToString(\"g4\"));\n            Report.Line(\"  {0},\", mat.R1.ToString(\"g4\"));\n            Report.Line(\"  {0},\", mat.R2.ToString(\"g4\"));\n            Report.Line(\"  {0} ]\", mat.R3.ToString(\"g4\"));\n        }\n    }\n\n    public static class MatrixTestExtensions\n    {\n        public static M44d LuInverse2(this M44d m)\n        {\n            var lu = (double[,])m;\n            return (M44d)lu.LuInverse(lu.LuFactorize());\n        }\n\n        /// <summary>\n        /// Calculates the inverse Matrix to A using Householder-Transformations\n        /// </summary>\n        public static M44d QrInverse2(this M44d mat)\n        {\n            double[,] qr = (double[,])mat;\n            double[] diag = qr.QrFactorize();\n            double[,] inv = new double[4, 4];\n            qr.QrInverse(diag, inv);\n            return (M44d)inv;\n        }\n\n        public static readonly V2l s_luSize = new V2l(4, 4);\n        public static readonly V2l s_luDelta = new V2l(1, 4);\n        public static readonly Matrix<double> s_unit = new Matrix<double>(\n                new double[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, 0, s_luSize, s_luDelta);\n\n        public static M44d LuInverseM(this M44d m)\n        {\n            var lu = new Matrix<double>((double[])m, 0, s_luSize, s_luDelta);\n            return (M44d)(lu.LuSolve(lu.LuFactorize(), s_unit).Data);\n        }\n\n        public static readonly Vector<double> s_c0 = new Vector<double>(new double[] { 1, 0, 0, 0 });\n        public static readonly Vector<double> s_c1 = new Vector<double>(new double[] { 0, 1, 0, 0 });\n        public static readonly Vector<double> s_c2 = new Vector<double>(new double[] { 0, 0, 1, 0 });\n        public static readonly Vector<double> s_c3 = new Vector<double>(new double[] { 0, 0, 0, 1 });\n\n        public static M44d LuInverseV(this M44d m)\n        {\n            var lu = new Matrix<double>((double[])m, 0, s_luSize, s_luDelta);\n            var p = lu.LuFactorize();\n            var inv = new M44d();\n            var c0 = lu.LuSolve(p, s_c0); inv.M00 = c0.Data[0]; inv.M10 = c0.Data[1]; inv.M20 = c0.Data[2]; inv.M30 = c0.Data[3];\n            var c1 = lu.LuSolve(p, s_c1); inv.M01 = c1.Data[0]; inv.M11 = c1.Data[1]; inv.M21 = c1.Data[2]; inv.M31 = c1.Data[3];\n            var c2 = lu.LuSolve(p, s_c2); inv.M02 = c2.Data[0]; inv.M12 = c2.Data[1]; inv.M22 = c2.Data[2]; inv.M32 = c2.Data[3];\n            var c3 = lu.LuSolve(p, s_c3); inv.M03 = c3.Data[0]; inv.M13 = c3.Data[1]; inv.M23 = c3.Data[2]; inv.M33 = c3.Data[3];\n            return inv;\n        }\n\n        /// <summary>\n        /// Calculates the inverse using gauss elemination.\n        /// This is a more accurate calculation of the inverse (but slower).\n        /// This method returns the inverse of the matrix to a new object.\n        /// </summary>\n        /// <returns>Returns the inverse of the matrix.</returns>\n        public static M44d NumericallyInstableGjInverse2(this M44d mat)\n        {\n            int i, j, k;\n\n            var work = (double[,])mat;\n            var result = (double[,])M44d.Identity;\n\n            for (i = 0; i < 3; i++)\n            {\n                int pivot = i;\n                double pivotsize = System.Math.Abs(work[i, i]);\n\n                for (j = i + 1; j < 4; j++)\n                {\n                    double r = work[j, i];\n\n                    if (r < 0) r = -r;\n\n                    if (r > pivotsize)\n                    {\n                        pivot = j;\n                        pivotsize = r;\n                    }\n                }\n\n                if (pivotsize == 0.0)\n                    throw new ArgumentException(\n                                \"cannot invert singular matrix\");\n\n                if (pivot != i)\n                {\n                    for (j = 0; j < 4; j++)\n                    {\n                        double r;\n\n                        r = work[i, j];\n                        work[i, j] = work[pivot, j];\n                        work[pivot, j] = r;\n\n                        r = result[i, j];\n                        result[i, j] = result[pivot, j];\n                        result[pivot, j] = r;\n                    }\n                }\n\n                for (j = i + 1; j < 4; j++)\n                {\n                    double f = work[j, i] / work[i, i];\n\n                    for (k = 0; k < 4; k++)\n                    {\n                        work[j, k] -= f * work[i, k];\n                        result[j, k] -= f * result[i, k];\n                    }\n                }\n            }\n\n            //backward substitution\n            for (i = 3; i >= 0; --i)\n            {\n                double f;\n\n                if ((f = work[i, i]) == 0)\n                    throw new ArgumentException(\"cannot invert singular matrix\");\n\n                for (j = 0; j < 4; j++)\n                {\n                    work[i, j] /= f;\n                    result[i, j] /= f;\n                }\n\n                for (j = 0; j < i; j++)\n                {\n                    f = work[j, i];\n\n                    for (k = 0; k < 4; k++)\n                    {\n                        work[j, k] -= f * work[i, k];\n                        result[j, k] -= f * result[i, k];\n                    }\n                }\n            }\n            return (M44d)result;\n        }\n\n    }\n\n    public class HartleyTests : TestSuite\n    {\n        public HartleyTests() : base() { }\n        public HartleyTests(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public void TestHartley()\n        {\n            BitReversedIndexTest(20);\n        }\n\n        public static string BitString(int value, int bits)\n        {\n            StringBuilder s = new StringBuilder(bits);\n            for (int mask = 1 << (bits - 1); mask > 0; mask >>= 1)\n                s.Append((value & mask) != 0 ? 'I' : 'O');\n            return s.ToString();\n        }\n\n        public void BitReversedIndexTest(int maxBits, bool report = false)\n        {\n            Test.Begin(\"BitReversedIndex tests\");\n            for (var bits = 1; bits <= maxBits; bits++)\n            {\n                int n = 1 << bits;\n                Test.Begin(\"int[{0}]\", n);\n                var original = new int[n].SetByIndex(i => i);\n                var reversed = original.BitReversedIndexCopy(0, n);\n                var revTwice = reversed.Copy();\n                revTwice.BitReverseIndex(0, n, 1);\n                for (int i = 0; i < n; i++)\n                    Test.IsTrue(original[i] == revTwice[i]);\n                if (report && n < 32)\n                    for (int i = 0; i < n; i++)\n                        Report.Line(\"{0} -> {1}\", BitString(original[i], bits), BitString(reversed[i], bits));\n                Test.End();\n            }\n            Test.End();\n        }\n\n    }\n}"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/Rot2dTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class Rot2dTests\n    {\n        [Test]\n        public static void DistanceTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var delta = (rnd.UniformDouble() - 0.5) * 2.0 * Constant.Pi;\n                var r1 = TrafoTesting.GetRandomRot2(rnd);\n                var r2 = new Rot2d(r1.Angle + (delta + Constant.PiTimesTwo * rnd.UniformInt(10)));\n\n                var dist = r1.Distance(r2);\n                TrafoTesting.AreEqual(dist, Fun.Abs(delta));\n            });\n        }\n\n        [Test]\n        public static void InverseTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var r = TrafoTesting.GetRandomRot2(rnd);\n                \n                var p = rnd.UniformV2d() * rnd.UniformInt(1000);\n                var q = r.Transform(p);\n\n                // Inverse property\n                var res = r.Inverse.Transform(q);\n\n                // Invert method\n                Rot.Invert(ref r);\n                var res2 = r.Transform(q);\n\n                TrafoTesting.AreEqual(p, res);\n                TrafoTesting.AreEqual(p, res2);\n            });\n        }\n\n        [Test]\n        public static void Multiplication2x2Test()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var r1 = TrafoTesting.GetRandomRot2(rnd);\n                var r2 = TrafoTesting.GetRandomRot2(rnd);\n                var r = r1 * r2;\n                var rm = (M22d)r1 * r2;\n                var mr = r1 * (M22d)r2;\n                var m = (M22d)r1 * (M22d)r2;\n\n                {\n                    var p = rnd.UniformV2d() * rnd.UniformInt(1000);\n                    var res = r.Transform(p);\n                    var res2 = m.Transform(p);\n                    var res3 = rm.Transform(p);\n                    var res4 = mr.Transform(p);\n\n                    TrafoTesting.AreEqual(res, res2);\n                    TrafoTesting.AreEqual(res, res3);\n                    TrafoTesting.AreEqual(res, res4);\n                }\n            });\n        }\n\n        [Test]\n        public static void Multiplication2x3Test()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var r1 = TrafoTesting.GetRandomRot2(rnd);\n                var r2 = TrafoTesting.GetRandomRot2(rnd);\n                var r = r1 * r2;\n                var rm = (M23d)r1 * r2;\n                var mr = r1 * (M23d)r2;\n\n                {\n                    var p = rnd.UniformV2d() * rnd.UniformInt(1000);\n                    var res = r.Transform(p);\n                    var res2 = rm.TransformPos(p);\n                    var res3 = mr.TransformPos(p);\n\n                    TrafoTesting.AreEqual(res, res2);\n                    TrafoTesting.AreEqual(res, res3);\n                }\n            });\n        }\n\n        [Test]\n        public static void MultiplicationFull2x3Test()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var m = TrafoTesting.GetRandom2x3(rnd);\n                var r = TrafoTesting.GetRandomRot2(rnd);\n\n                var mr = m * r;\n                var rm = r * m;\n\n                var mr_ref = m * (M33d)r;\n                var rm_ref = (M23d)r * (M33d)m;\n\n                {\n                    var p = rnd.UniformV2d() * rnd.UniformInt(1000);\n                    var res_mr = mr.TransformPos(p);\n                    var res_mr_ref = mr_ref.TransformPos(p);\n                    var res_rm = rm.TransformPos(p);\n                    var res_rm_ref = rm_ref.TransformPos(p);\n\n                    TrafoTesting.AreEqual(res_mr, res_mr_ref);\n                    TrafoTesting.AreEqual(res_rm, res_rm_ref);\n                }\n            });\n        }\n\n        [Test]\n        public static void Multiplication3x3Test()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var r1 = TrafoTesting.GetRandomRot2(rnd);\n                var r2 = TrafoTesting.GetRandomRot2(rnd);\n                var r = r1 * r2;\n                var rm = (M33d)r1 * r2;\n                var mr = r1 * (M33d)r2;\n                var m = (M33d)r1 * (M33d)r2;\n\n                {\n                    var p = rnd.UniformV2d() * rnd.UniformInt(1000);\n                    var res = r.Transform(p);\n                    var res2 = m.TransformPos(p);\n                    var res3 = rm.TransformPos(p);\n                    var res4 = mr.TransformPos(p);\n\n                    TrafoTesting.AreEqual(res, res2);\n                    TrafoTesting.AreEqual(res, res3);\n                    TrafoTesting.AreEqual(res, res4);\n                }\n            });\n        }\n\n        [Test]\n        public static void FromM22d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot2, a => (M22d)a, Rot2d.FromM22d);\n\n        [Test]\n        public static void FromM33d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot2, a => (M33d)a, b => Rot2d.FromM33d(b));\n\n        [Test]\n        public static void FromEuclidean2d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot2, a => (Euclidean2d)a, b => Rot2d.FromEuclidean2d(b));\n\n        [Test]\n        public static void FromSimilarity2d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot2, a => (Similarity2d)a, b => Rot2d.FromSimilarity2d(b));\n\n        [Test]\n        public static void FromAffine2d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot2, a => (Affine2d)a, b => Rot2d.FromAffine2d(b));\n\n        [Test]\n        public static void FromTrafo2d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot2, a => (Trafo2d)a, b => Rot2d.FromTrafo2d(b));\n\n        [Test]\n        public static void MultiplicationShiftTest()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var a = TrafoTesting.GetRandomRot2(rnd);\n                var b = TrafoTesting.GetRandomShift2(rnd);\n\n                var p = rnd.UniformV2d() * rnd.UniformInt(1000);\n\n                {\n                    var trafo = a * b;\n                    var res = trafo.TransformPos(p);\n\n                    var trafoRef = (M33d)a * (M33d)b;\n                    var resRef = trafoRef.TransformPos(p);\n\n                    TrafoTesting.AreEqual(res, resRef);\n                }\n\n                {\n                    var trafo = b * a;\n                    var res = trafo.TransformPos(p);\n\n                    var trafoRef = (M33d)b * (M33d)a;\n                    var resRef = trafoRef.TransformPos(p);\n\n                    TrafoTesting.AreEqual(res, resRef);\n                }\n            });\n        \n        [Test]\n        public static void MultiplicationScaleTest()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var a = TrafoTesting.GetRandomRot2(rnd);\n                var b = TrafoTesting.GetRandomScale2(rnd);\n\n                var p = rnd.UniformV2d() * rnd.UniformInt(1000);\n\n                {\n                    var trafo = a * b;\n                    var res = trafo.TransformPos(p);\n\n                    var trafoRef = (M33d)a * (M33d)b;\n                    var resRef = trafoRef.TransformPos(p);\n\n                    TrafoTesting.AreEqual(res, resRef);\n                }\n\n                {\n                    var trafo = b * a;\n                    var res = trafo.TransformPos(p);\n\n                    var trafoRef = (M33d)b * (M33d)a;\n                    var resRef = trafoRef.TransformPos(p);\n\n                    TrafoTesting.AreEqual(res, resRef);\n                }\n            });\n\n        [Test]\n        public static void ConsistentWithMatrixRotationTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var angle = rnd.UniformDouble() * Constant.PiTimesTwo;\n                var m = M22d.Rotation(angle);\n                var r = new Rot2d(angle);\n\n                var p = rnd.UniformV2d() * rnd.UniformInt(1000);\n                var res = m.Transform(p);\n                var res2 = r.Transform(p);\n\n                TrafoTesting.AreEqual(res, res2);\n            });\n        }\n\n        [Test]\n        public static void ToStringAndParse()\n            => TrafoTesting.GenericToStringAndParseTest(TrafoTesting.GetRandomRot2, Rot2d.Parse);\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/Rot3dTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class Rot3dTests\n    {\n\n        [Test]\n        public static void FromM33d()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var rot = rnd.UniformV3dFull() * Constant.PiTimesFour - Constant.PiTimesTwo;\n\n                var mat = M44d.RotationEuler(rot);\n                var mat2 = (M44d)Rot3d.FromM33d((M33d)mat);\n\n                Assert.IsFalse(mat.Elements.Any(x => x.IsNaN()), \"NaN\");\n\n                if (!Fun.ApproximateEquals(mat, mat2, 1e-9))\n                    Assert.Fail(\"FAIL\");\n            });\n        }\n\n        [Test]\n        public static void FromM44d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot3, a => (M44d)a, b => Rot3d.FromM44d(b));\n\n        [Test]\n        public static void FromEuclidean3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot3, a => (Euclidean3d)a, b => Rot3d.FromEuclidean3d(b));\n\n        [Test]\n        public static void FromSimilarity3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot3, a => (Similarity3d)a, b => Rot3d.FromSimilarity3d(b));\n\n        [Test]\n        public static void FromAffine3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot3, a => (Affine3d)a, b => Rot3d.FromAffine3d(b));\n\n        [Test]\n        public static void FromTrafo3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomRot3, a => (Trafo3d)a, b => Rot3d.FromTrafo3d(b));\n\n        [Test]\n        public static void ToStringAndParse()\n            => TrafoTesting.GenericToStringAndParseTest(TrafoTesting.GetRandomRot3, Rot3d.Parse);\n\n        [Test]\n        public static void MultiplicationRotTest()\n            => TrafoTesting.GenericMultiplicationTest<Rot3d, Rot3d, Rot3d>(TrafoTesting.GetRandomRot3, TrafoTesting.GetRandomRot3, Rot.Transform); \n\n        [Test]\n        public static void MultiplicationShiftTest()\n            => TrafoTesting.GenericMultiplicationTest<Rot3d, Shift3d, Euclidean3d>(TrafoTesting.GetRandomRot3, TrafoTesting.GetRandomShift3, Euclidean.TransformPos);        \n        [Test]\n        public static void MultiplicationScaleTest()\n            => TrafoTesting.GenericMultiplicationTest<Rot3d, Scale3d, Affine3d>(TrafoTesting.GetRandomRot3, TrafoTesting.GetRandomScale3, Affine.TransformPos);\n\n        [Test]\n        public static void Multiplication3x3Test()\n            => TrafoTesting.Generic3x3MultiplicationTest(\n                TrafoTesting.GetRandomRot3,\n                Rot.Transform,\n                (r, v) => r * v);\n\n        [Test]\n        public static void Multiplication3x4Test()\n            => TrafoTesting.Generic3x4MultiplicationTest(\n                TrafoTesting.GetRandomRot3,\n                Rot.Transform,\n                (r, v) => r * v);\n\n        [Test]\n        public static void MultiplicationFull3x4Test()\n            => TrafoTesting.GenericFull3x4MultiplicationTest(TrafoTesting.GetRandomRot3);\n\n        [Test]\n        public static void Multiplication4x4Test()\n            => TrafoTesting.Generic4x4MultiplicationTest(\n                TrafoTesting.GetRandomRot3,\n                Rot.Transform,\n                (r, v) => r * v);\n\n        [Test]\n        public static void MultiplicationFull4x4Test()\n            => TrafoTesting.GenericFull3x4MultiplicationTest(TrafoTesting.GetRandomRot3);\n\n        [Test]\n        public static void RotationXYZ()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var angle = rnd.UniformDouble() * Constant.PiTimesFour - Constant.PiTimesTwo;\n\n                var rotX1 = Rot3d.RotationX(angle);\n                var rotX2 = Rot3d.Rotation(V3d.XAxis, angle);\n\n                TrafoTesting.AreEqual(rotX1, rotX2);\n\n                var rotY1 = Rot3d.RotationY(angle);\n                var rotY2 = Rot3d.Rotation(V3d.YAxis, angle);\n\n                TrafoTesting.AreEqual(rotY1, rotY2);\n\n                var rotZ1 = Rot3d.RotationZ(angle);\n                var rotZ2 = Rot3d.Rotation(V3d.ZAxis, angle);\n\n                TrafoTesting.AreEqual(rotZ1, rotZ2);\n            });\n        }\n\n        [Test]\n        public static void FromEuler()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var euler = rnd.UniformV3dFull() * Constant.PiTimesFour - Constant.PiTimesTwo;\n\n                var rot = Rot3d.RotationEuler(euler);\n\n                var qx = Rot3d.RotationX(euler.X);\n                var qy = Rot3d.RotationY(euler.Y);\n                var qz = Rot3d.RotationZ(euler.Z);\n                var test = qz * qy * qx;\n\n                TrafoTesting.AreEqual(rot, test);\n\n                var euler2 = rot.GetEulerAngles();\n                var rot2 = Rot3d.RotationEuler(euler2);\n\n                var rot2M = (M33d)rot2;\n                var rotM = (M33d)rot;\n\n                if (!Fun.ApproximateEquals(rot2M, rotM, 1e-6))\n                    Report.Line(\"FA\");\n\n                Assert.IsTrue(Fun.ApproximateEquals(rot2M, rotM, 1e-6));\n            });\n        }\n\n        [Test]\n        public static void YawPitchRoll()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var yaw = rnd.UniformDouble() * Constant.PiTimesFour - Constant.PiTimesTwo;\n                var pitch = rnd.UniformDouble() * Constant.PiTimesFour - Constant.PiTimesTwo;\n                var roll = rnd.UniformDouble() * Constant.PiTimesFour - Constant.PiTimesTwo;\n\n                // Aardvark euler angles: roll (X), pitch (Y), yaw (Z). Ther are applied in reversed order.\n                var mat = (M33d)(M44d.RotationZ(yaw) * M44d.RotationY(pitch) * M44d.RotationX(roll));\n                var mat2 = (M33d)M44d.RotationEuler(roll, pitch, yaw);\n                var mat3 = (M33d)(Rot3d.RotationZ(yaw) * Rot3d.RotationY(pitch) * Rot3d.RotationX(roll));\n                var mat4 = (M33d)Rot3d.RotationEuler(roll, pitch, yaw);\n\n                Assert.IsTrue(Fun.ApproximateEquals(mat, mat2, 1e-7));\n                Assert.IsTrue(Fun.ApproximateEquals(mat, mat3, 1e-7));\n                Assert.IsTrue(Fun.ApproximateEquals(mat, mat4, 1e-7));\n            });\n        }\n\n        [Test]\n        public static void RotIntoCornerCase()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                // some vectors will not normalize to 1.0 -> provoke numerical issues in Rot3d\n                var vecd = new V3d(0, 0, -rnd.UniformDouble());\n                var rotd = Rot3d.RotateInto(V3d.OOI, vecd.Normalized);\n                var testd = rotd.Transform(V3d.OOI);\n                Assert.True((testd + V3d.OOI).Length < 1e-8);\n\n                var vecf = new V3f(0, 0, -rnd.UniformDouble());\n                var rotf = Rot3f.RotateInto(V3f.OOI, vecf.Normalized);\n                var testf = rotf.Transform(V3f.OOI);\n                Assert.True((testf + V3f.OOI).Length < 1e-5);\n            });\n        }\n\n        [Test]\n        public static void FromInto()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var dir = rnd.UniformV3d().Normalized;\n                var rotId = Rot3d.RotateInto(dir, dir);\n                var matId = (M33d)rotId;\n\n                Assert.IsTrue(matId.IsIdentity(0));\n\n                var rot = Rot3d.RotateInto(dir, -dir);\n                var invDir = rot.Transform(dir);\n\n                Assert.IsTrue(invDir.ApproximateEquals(-dir, 1e-14));\n\n                var dirF = rnd.UniformV3f().Normalized;\n                var rotIdF = Rot3f.RotateInto(dirF, dirF);\n                var matIdF = (M33f)rotIdF;\n\n                Assert.IsTrue(matIdF.IsIdentity(0));\n\n                var rotF = Rot3f.RotateInto(dirF, -dirF);\n                var invDirF = rotF.Transform(dirF);\n\n                Assert.IsTrue(invDirF.ApproximateEquals(-dirF, 1e-6f));\n            });\n        }\n\n        [Test]\n        public static void FromIntoEpislon()\n        {\n            TrafoTesting.GenericTest((rnd, i) =>\n            {\n                var dir = rnd.UniformV3d().Normalized;\n                var eps = rnd.UniformV3d() * (i / 100) * 1e-22;\n                var rotId = Rot3d.RotateInto(dir, (dir + eps).Normalized);\n                var matId = (M33d)rotId;\n\n                Assert.IsTrue(matId.IsIdentity(1e-10));\n\n                var dirF = rnd.UniformV3f().Normalized;\n                var epsF = rnd.UniformV3f() * (i / 100) * 1e-12f;\n                var rotIdF = Rot3f.RotateInto(dirF, (dirF + epsF).Normalized);\n                var matIdF = (M33f)rotIdF;\n\n                Assert.IsTrue(matIdF.IsIdentity(1e-7f));\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/Scale3dTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class Scale3dTests\n    {\n        [Test]\n        public static void FromM33d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomScale3, a => (M33d)a, b => Scale3d.FromM33d(b));\n\n        [Test]\n        public static void FromM44d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomScale3, a => (M44d)a, b => Scale3d.FromM44d(b));\n\n        [Test]\n        public static void FromSimilarity3d()\n            => TrafoTesting.GenericConversionTest(rnd => new Scale3d(rnd.UniformDouble() * 10), a => Similarity3d.FromScale3d(a), b => Scale3d.FromSimilarity3d(b));\n\n        [Test]\n        public static void FromAffine3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomScale3, a => (Affine3d)a, b => Scale3d.FromAffine3d(b));\n\n        [Test]\n        public static void FromTrafo3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomScale3, a => (Trafo3d)a, b => Scale3d.FromTrafo3d(b));\n\n        [Test]\n        public static void Comparison()\n            => TrafoTesting.GenericComparisonTest(TrafoTesting.GetRandomScale3, a => new Scale3d(a.V + V3d.OII));\n\n        [Test]\n        public static void InverseTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var s = TrafoTesting.GetRandomScale3(rnd);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var q = s.Transform(p);\n\n                // Inverse property\n                var res = s.Inverse.Transform(q);\n\n                // InvTransform\n                var res2 = s.InvTransform(q);\n\n                // Invert method\n                Scale.Invert(ref s);\n                var res3 = s.Transform(q);\n\n                TrafoTesting.AreEqual(p, res);\n                TrafoTesting.AreEqual(p, res2);\n                TrafoTesting.AreEqual(p, res3);\n            });\n        }\n\n        [Test]\n        public static void Multiplication3x3Test()\n            => TrafoTesting.Generic3x3MultiplicationTest(\n                TrafoTesting.GetRandomScale3,\n                Scale.Transform,\n                (r, v) => r * v);\n\n        [Test]\n        public static void Multiplication3x4Test()\n            => TrafoTesting.Generic3x4MultiplicationTest(\n                TrafoTesting.GetRandomScale3,\n                Scale.Transform,\n                (r, v) => r * v);\n\n        [Test]\n        public static void MultiplicationFull3x4Test()\n            => TrafoTesting.GenericFull3x4MultiplicationTest(TrafoTesting.GetRandomScale3);\n\n        [Test]\n        public static void Multiplication4x4Test()\n            => TrafoTesting.Generic4x4MultiplicationTest(\n                TrafoTesting.GetRandomScale3,\n                Scale.Transform,\n                (r, v) => r * v);\n\n        [Test]\n        public static void MultiplicationFull4x4Test()\n            => TrafoTesting.GenericFull3x4MultiplicationTest(TrafoTesting.GetRandomScale3);\n\n        [Test]\n        public static void MultiplicationScaleTest()\n            => TrafoTesting.GenericMultiplicationTest<Scale3d, Scale3d, Scale3d>(TrafoTesting.GetRandomScale3, TrafoTesting.GetRandomScale3, Scale.Transform);  \n\n        [Test]\n        public static void MultiplicationRotTest()\n            => TrafoTesting.GenericMultiplicationTest<Scale3d, Rot3d, Affine3d>(TrafoTesting.GetRandomScale3, TrafoTesting.GetRandomRot3, Affine.TransformPos);  \n        \n        [Test]\n        public static void MultiplicationShiftTest()\n            => TrafoTesting.GenericMultiplicationTest<Scale3d, Shift3d, Affine3d>(TrafoTesting.GetRandomScale3, TrafoTesting.GetRandomShift3, Affine.TransformPos);\n\n        [Test]\n        public static void ConsistentWithMatrixScaleTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var scale = rnd.UniformV3d() * 10;\n                var m = M33d.Scale(scale);\n                var r = new Scale3d(scale);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var res = m.Transform(p);\n                var res2 = r.Transform(p);\n\n                TrafoTesting.AreEqual(res, res2);\n            });\n        }\n\n        [Test]\n        public static void ToStringAndParse()\n            => TrafoTesting.GenericToStringAndParseTest(TrafoTesting.GetRandomScale3, Scale3d.Parse);\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/Shift3dTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class Shift3dTests\n    {\n        [Test]\n        public static void FromM34d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomShift3, a => (M34d)a, b => Shift3d.FromM34d(b));\n\n        [Test]\n        public static void FromM44d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomShift3, a => (M44d)a, b => Shift3d.FromM44d(b));\n\n        [Test]\n        public static void FromEuclidean3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomShift3, a => (Euclidean3d)a, b => Shift3d.FromEuclidean3d(b));\n\n        [Test]\n        public static void FromSimilarity3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomShift3, a => (Similarity3d)a, b => Shift3d.FromSimilarity3d(b));\n\n        [Test]\n        public static void FromAffine3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomShift3, a => (Affine3d)a, b => Shift3d.FromAffine3d(b));\n\n        [Test]\n        public static void FromTrafo3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomShift3, a => (Trafo3d)a, b => Shift3d.FromTrafo3d(b));\n\n        [Test]\n        public static void Comparison()\n            => TrafoTesting.GenericComparisonTest(TrafoTesting.GetRandomShift3, a => new Shift3d(a.V + V3d.OII));\n\n        [Test]\n        public static void InverseTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var s = TrafoTesting.GetRandomShift3(rnd);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var q = s.Transform(p);\n\n                // Inverse property\n                var res = s.Inverse.Transform(q);\n\n                // InvTransform\n                var res2 = s.InvTransform(q);\n\n                // Invert method\n                Shift.Invert(ref s);\n                var res3 = s.Transform(q);\n\n                TrafoTesting.AreEqual(p, res);\n                TrafoTesting.AreEqual(p, res2);\n                TrafoTesting.AreEqual(p, res3);\n            });\n        }\n\n        [Test]\n        public static void Multiplication3x4Test()\n            => TrafoTesting.Generic3x4MultiplicationTest(\n                TrafoTesting.GetRandomShift3,\n                Shift.Transform,\n                (r, v) => r * v);\n\n        [Test]\n        public static void Multiplication4x4Test()\n            => TrafoTesting.Generic4x4MultiplicationTest(\n                TrafoTesting.GetRandomShift3,\n                Shift.Transform,\n                (r, v) => r * v);\n\n        [Test]\n        public static void MultiplicationFull4x4Test()\n            => TrafoTesting.GenericFull3x4MultiplicationTest(TrafoTesting.GetRandomShift3);\n        [Test]\n        public static void MultiplicationShiftTest()\n            => TrafoTesting.GenericMultiplicationTest<Shift3d, Shift3d, Shift3d>(TrafoTesting.GetRandomShift3, TrafoTesting.GetRandomShift3, Shift.Transform);   \n\n        [Test]\n        public static void MultiplicationRotTest()\n            => TrafoTesting.GenericMultiplicationTest<Shift3d, Rot3d, Euclidean3d>(TrafoTesting.GetRandomShift3, TrafoTesting.GetRandomRot3, Euclidean.TransformPos);        \n        [Test]\n        public static void MultiplicationScaleTest()\n            => TrafoTesting.GenericMultiplicationTest<Shift3d, Scale3d, Affine3d>(TrafoTesting.GetRandomShift3, TrafoTesting.GetRandomScale3, Affine.TransformPos);\n\n        [Test]\n        public static void ConsistentWithMatrixShiftTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var shift = rnd.UniformV3d() * 10;\n                var m = M34d.Translation(shift);\n                var r = new Shift3d(shift);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var res = m.TransformPos(p);\n                var res2 = r.Transform(p);\n\n                TrafoTesting.AreEqual(res, res2);\n            });\n        }\n\n        [Test]\n        public static void ToStringAndParse()\n            => TrafoTesting.GenericToStringAndParseTest(TrafoTesting.GetRandomShift3, Shift3d.Parse);\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/SimilarityTests.cs",
    "content": "﻿using Aardvark.Base;\nusing NUnit.Framework;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public static class SimilarityTests\n    {\n        [Test]\n        public static void FromM33dAndV3d()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var a = TrafoTesting.GetRandomSimilarity(rnd);\n                var tmp = (M34d)a;\n                var m = (M33d)tmp;\n                var t = tmp.C3;\n\n                var restored = Similarity3d.FromM33dAndV3d(m, t);\n                TrafoTesting.AreEqual(a, restored);\n            });\n\n        [Test]\n        public static void FromM34d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomSimilarity, a => (M34d)a, b => Similarity3d.FromM34d(b));\n\n        [Test]\n        public static void FromM44d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomSimilarity, a => (M44d)a, b => Similarity3d.FromM44d(b));\n\n        [Test]\n        public static void FromAffine3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomSimilarity, a => (Affine3d)a, b => Similarity3d.FromAffine3d(b));\n\n        [Test]\n        public static void FromTrafo3d()\n            => TrafoTesting.GenericConversionTest(TrafoTesting.GetRandomSimilarity, a => (Trafo3d)a, b => Similarity3d.FromTrafo3d(b));\n\n        [Test]\n        public static void Comparison()\n            => TrafoTesting.GenericComparisonTest(TrafoTesting.GetRandomSimilarity, a => new Similarity3d(a.Scale + 1, a.Euclidean));\n\n        [Test]\n        public static void InverseTest()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var s = TrafoTesting.GetRandomSimilarity(rnd);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var q = s.TransformPos(p);\n\n                // Inverse property\n                var res = s.Inverse.TransformPos(q);\n\n                // Invert method\n                Similarity.Invert(ref s);\n                var res2 = s.TransformPos(q);\n\n                TrafoTesting.AreEqual(p, res);\n                TrafoTesting.AreEqual(p, res2);\n            });\n\n        [Test]\n        public static void Multiplication3x3Test()\n            => TrafoTesting.GenericMatrixMultiplicationTest<Similarity3d, M33d, M34d>(\n                rnd => TrafoTesting.GetRandomSimilarity(rnd, false),\n                Similarity.TransformPos,\n                Mat.Transform,\n                Mat.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ,\n                (m, v) => m * v,\n                (m, v) => m * new V4d(v, 1));\n\n        [Test]\n        public static void Multiplication3x4Test()\n            => TrafoTesting.Generic3x4MultiplicationTest(\n                TrafoTesting.GetRandomSimilarity,\n                Similarity.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ);\n\n        [Test]\n        public static void Multiplication4x4Test()\n            => TrafoTesting.Generic4x4MultiplicationTest(\n                TrafoTesting.GetRandomSimilarity,\n                Similarity.TransformPos,\n                (a, v) => (a * new V4d(v, 1)).XYZ);\n\n        [Test]\n        public static void MultiplicationFull4x4Test()\n            => TrafoTesting.GenericFull4x4MultiplicationTest(TrafoTesting.GetRandomSimilarity);\n\n        [Test]\n        public static void ConsistentWithMatrixRotationShiftAndScaleTest()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var trans = rnd.UniformV3d() * 10;\n\n                var axis = rnd.UniformV3dDirection();\n                var angle = rnd.UniformDouble() * Constant.PiTimesTwo;\n\n                var scale = rnd.UniformDouble() * 5;\n\n                var m = M44d.Translation(trans) * M44d.Rotation(axis, angle) * M44d.Scale(scale, scale, scale);\n                var e = new Similarity3d(scale, Rot3d.Rotation(axis, angle), trans);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var res = m.TransformPos(p);\n                var res2 = e.TransformPos(p);\n\n                TrafoTesting.AreEqual(res, res2);\n            });\n\n        [Test]\n        public static void MultiplicationSimilarityTest()\n            => TrafoTesting.GenericMultiplicationTest <Similarity3d, Similarity3d, Similarity3d>(TrafoTesting.GetRandomSimilarity, TrafoTesting.GetRandomSimilarity, Similarity.TransformPos);\n\n        [Test]\n        public static void MultiplicationEuclideanTest()\n            => TrafoTesting.GenericMultiplicationTest <Similarity3d, Euclidean3d, Similarity3d>(TrafoTesting.GetRandomSimilarity, TrafoTesting.GetRandomEuclidean, Similarity.TransformPos);\n\n        [Test]\n        public static void MultiplicationRotTest()\n            => TrafoTesting.GenericMultiplicationTest<Similarity3d, Rot3d, Similarity3d>(TrafoTesting.GetRandomSimilarity, TrafoTesting.GetRandomRot3, Similarity.TransformPos);\n\n        [Test]\n        public static void MultiplicationShiftTest()\n            => TrafoTesting.GenericMultiplicationTest<Similarity3d, Shift3d, Similarity3d>(TrafoTesting.GetRandomSimilarity, TrafoTesting.GetRandomShift3, Similarity.TransformPos);\n\n        [Test]\n        public static void MultiplicationScaleTest()\n            => TrafoTesting.GenericMultiplicationTest<Similarity3d, Scale3d, Affine3d>(TrafoTesting.GetRandomSimilarity, TrafoTesting.GetRandomScale3, Affine.TransformPos);\n\n        [Test]\n        public static void ToStringAndParse()\n            => TrafoTesting.GenericToStringAndParseTest(TrafoTesting.GetRandomSimilarity, Similarity3d.Parse);\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/TrafoTesting.cs",
    "content": "﻿using System;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    public static class TrafoTesting\n    {\n        public static readonly int Iterations = 10000;\n\n        public static readonly double Epsilon = 1e-8;\n\n        public static void AreEqual(dynamic a, dynamic b)\n            => Assert.IsTrue(Fun.ApproximateEquals(a, b, Epsilon), \"{0} != {1}\", a, b);\n\n        public static M23d GetRandom2x3(RandomSystem rnd)\n            => new M23d(rnd.CreateUniformDoubleArray(16));\n\n        public static M33d GetRandom3x3(RandomSystem rnd)\n            => new M33d(rnd.CreateUniformDoubleArray(16));\n\n        public static M34d GetRandom3x4(RandomSystem rnd)\n            => new M34d(rnd.CreateUniformDoubleArray(16));\n\n        public static M44d GetRandom4x4(RandomSystem rnd)\n            => new M44d(rnd.CreateUniformDoubleArray(16));\n\n        public static Scale2d GetRandomScale2(RandomSystem rnd)\n            => new Scale2d(rnd.UniformV2d() * 5);\n\n        public static Scale3d GetRandomScale3(RandomSystem rnd)\n            => new Scale3d(rnd.UniformV3d() * 5);\n\n        public static Rot2d GetRandomRot2(RandomSystem rnd)\n            => new Rot2d(rnd.UniformDouble() * Constant.PiTimesTwo);\n\n        public static Rot3d GetRandomRot3(RandomSystem rnd)\n            => Rot3d.Rotation(rnd.UniformV3dDirection(), rnd.UniformDouble() * Constant.PiTimesTwo);\n\n        public static Shift2d GetRandomShift2(RandomSystem rnd)\n            => new Shift2d(rnd.UniformV2d() * 10);\n\n        public static Shift3d GetRandomShift3(RandomSystem rnd)\n            => new Shift3d(rnd.UniformV3d() * 10);\n\n        public static Euclidean3d GetRandomEuclidean(RandomSystem rnd, bool withTranslation)\n        {\n            var translation = withTranslation ? GetRandomShift3(rnd).V : V3d.Zero;\n            return new Euclidean3d(GetRandomRot3(rnd), translation);\n        }\n\n        public static Euclidean3d GetRandomEuclidean(RandomSystem rnd)\n            => GetRandomEuclidean(rnd, true);\n\n        public static Similarity3d GetRandomSimilarity(RandomSystem rnd, bool withTranslation)\n            => new Similarity3d(GetRandomScale3(rnd).X, GetRandomEuclidean(rnd, withTranslation));\n\n        public static Similarity3d GetRandomSimilarity(RandomSystem rnd)\n            => GetRandomSimilarity(rnd, true);\n\n        public static Affine3d GetRandomAffine(RandomSystem rnd, bool withTranslation)\n            => (Affine3d)GetRandomSimilarity(rnd, withTranslation);\n\n        public static Affine3d GetRandomAffine(RandomSystem rnd)\n            => GetRandomAffine(rnd, true);\n\n        public static Trafo3d GetRandomTrafo(RandomSystem rnd, bool withPerspective)\n        {\n            var rot = rnd.UniformV3dFull() * Constant.PiTimesFour - Constant.PiTimesTwo;\n            var trans = rnd.UniformV3dFull() * 10 - 5;\n            var scale = rnd.UniformV3dFull() * 4 - 2;\n\n            var trafo = Trafo3d.FromComponents(scale, rot, trans);\n            if (withPerspective)\n            {\n                trafo *= Trafo3d.PerspectiveProjectionRH(-1, 1, -1, 1, rnd.UniformDouble(), rnd.UniformDouble() * 100);\n            }\n\n            return trafo;\n        }\n\n        public static Trafo3d GetRandomTrafo(RandomSystem rnd)\n            => GetRandomTrafo(rnd, true);\n\n        /// <summary>\n        /// Runs the given test function multiple times and provides a RandomSystem.\n        /// </summary>\n        public static void GenericTest(Action<RandomSystem, int> f)\n        {\n            var rnd = new RandomSystem(1);\n\n            for (int i = 0; i < Iterations; i++)\n            {\n                f(rnd, i);\n            }\n        }\n\n        /// <summary>\n        /// Runs the given test function multiple times and provides a RandomSystem.\n        /// </summary>\n        public static void GenericTest(Action<RandomSystem> f)\n            => GenericTest((rnd, i) => f(rnd));\n\n        /// <summary>\n        /// Tests if the comparison operators and Equals work as intended. The mutate function\n        /// takes a T trafo as input and returns a different one.\n        /// </summary>\n        public static void GenericComparisonTest<T>(Func<RandomSystem, T> frnd, Func<T, T> mutate)\n        {\n            GenericTest(rnd =>\n            {\n                dynamic a = frnd(rnd);\n                dynamic b = mutate(a);\n\n                Assert.IsFalse(a.Equals(b));\n                Assert.IsFalse(a == b);\n                Assert.IsTrue(a != b);\n            });\n        }\n\n        /// <summary>\n        /// Tests if the conversion from T1 to T2 and back is working, that is the same trafo is returned as initially generated.\n        /// </summary>\n        public static void GenericConversionTest<T1, T2>(Func<RandomSystem, T1> frnd, Func<T1, T2> cast, Func<T2, T1> restore)\n        {\n            GenericTest(rnd =>\n            {\n                dynamic a = frnd(rnd);\n                dynamic b = cast(a);\n\n                dynamic restored = restore(b);\n                AreEqual(a, restored);\n            });\n        }\n\n        /// <summary>\n        /// Tests if the multiplication between a T1 and T2 trafo (resulting in a U trafo) is consistent with multiplying the corresponding matrix representations.\n        /// </summary>\n        public static void GenericMultiplicationTest<T1, T2, U>(Func<RandomSystem, T1> frnd1, Func<RandomSystem, T2> frnd2, Func<U, V3d, V3d> transform)\n        {\n            GenericTest(rnd =>\n            {\n                dynamic a = frnd1(rnd);\n                dynamic b = frnd2(rnd);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n\n                {\n                    var trafo = a * b;\n                    var res = transform(trafo, p);\n\n                    var trafoRef = (M44d)a * (M44d)b;\n                    var resRef = trafoRef.TransformPos(p);\n\n                    AreEqual(res, resRef);\n                }\n\n                {\n                    var trafo = b * a;\n                    var res = transform(trafo, p);\n\n                    var trafoRef = (M44d)b * (M44d)a;\n                    var resRef = trafoRef.TransformPos(p);\n\n                    AreEqual(res, resRef);\n                }\n            });\n        }\n\n        /// <summary>\n        /// Tests multiplication of T trafos with their M matrix representations.\n        /// </summary>\n        public static void GenericMatrixMultiplicationTest<T, M, M2>(\n                Func<RandomSystem, T> frnd,\n                Func<T, V3d, V3d> trafoTransform,\n                Func<M, V3d, V3d> matrixTransform,\n                Func<M2, V3d, V3d> matrixTransform2,\n                Func<T, V3d, V3d> trafoMul,\n                Func<M, V3d, V3d> matrixMul,\n                Func<M2, V3d, V3d> matrixMul2,\n                bool squareMatrix = true)\n            => GenericTest(rnd =>\n            {\n                dynamic a = frnd(rnd);\n                dynamic b = frnd(rnd);\n                dynamic ma = (M)a;\n                dynamic mb = (M)b;\n\n                var a_x_b = a * b;\n                var ma_x_b = ma * b;\n                var a_x_mb = a * mb;\n                var ma_x_mb = (squareMatrix) ? ma * mb : null;\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n\n                {\n                    var res = trafoTransform(a_x_b, p);\n                    var res2 = matrixTransform2(ma_x_b, p);\n                    var res3 = matrixTransform2(a_x_mb, p);\n                    var res4 = squareMatrix ? matrixTransform(ma_x_mb, p) : res3;\n\n                    TrafoTesting.AreEqual(res, res2);\n                    TrafoTesting.AreEqual(res, res3);\n                    TrafoTesting.AreEqual(res, res4);\n                }\n\n                {\n                    var res = trafoMul(a_x_b, p);\n                    var res2 = matrixMul2(ma_x_b, p);\n                    var res3 = matrixMul2(a_x_mb, p);\n                    var res4 = squareMatrix ? matrixMul(ma_x_mb, p) : res3;\n\n                    TrafoTesting.AreEqual(res, res2);\n                    TrafoTesting.AreEqual(res, res3);\n                    TrafoTesting.AreEqual(res, res4);\n                }\n            });\n\n        /// <summary>\n        /// Tests multiplication of T trafos with random M matrices.\n        /// </summary>\n        public static void GenericFullMatrixMultiplicationTest<T, M, MAugmented>(\n                Func<RandomSystem, T> frnd,\n                Func<RandomSystem, M> frndMatrix,\n                Func<M, V3d, V3d> matrixTransform,\n                Func<M, V3d, V3d> matrixMul)\n            => GenericTest(rnd =>\n            {\n                dynamic m = frndMatrix(rnd);\n                dynamic t = frnd(rnd);\n                dynamic maugm = (MAugmented)m;\n                dynamic maugt = (MAugmented)t;\n                dynamic mt = (M)t;\n\n                var m_x_t = m * t;\n                var t_x_m = t * m;\n\n                var m_x_t_ref = m * maugt;\n                var t_x_m_ref = mt * maugm;\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n\n                {\n                    var res_mt = matrixTransform(m_x_t, p);\n                    var res_mt_ref = matrixTransform(m_x_t_ref, p);\n                    var res_tm = matrixTransform(t_x_m, p);\n                    var res_tm_ref = matrixTransform(t_x_m_ref, p);\n\n                    TrafoTesting.AreEqual(res_mt, res_mt_ref);\n                    TrafoTesting.AreEqual(res_tm, res_tm_ref);\n                }\n\n                {\n                    var res_mt = matrixMul(m_x_t, p);\n                    var res_mt_ref = matrixMul(m_x_t_ref, p);\n                    var res_tm = matrixMul(t_x_m, p);\n                    var res_tm_ref = matrixMul(t_x_m_ref, p);\n\n                    TrafoTesting.AreEqual(res_mt, res_mt_ref);\n                    TrafoTesting.AreEqual(res_tm, res_tm_ref);\n                }\n            });\n\n\n        /// <summary>\n        /// Tests multiplication of T trafos with their 3x3 matrix representation.\n        /// </summary>\n        public static void Generic3x3MultiplicationTest<T>(Func<RandomSystem, T> frnd, Func<T, V3d, V3d> trafoTransform, Func<T, V3d, V3d> trafoMul)\n            => GenericMatrixMultiplicationTest<T, M33d, M33d>(\n                    frnd,\n                    trafoTransform,\n                    Mat.Transform,\n                    Mat.Transform, \n                    trafoMul,\n                    (m, v) => m * v,\n                    (m, v) => m * v);\n\n        /// <summary>\n        /// Tests multiplication of T trafos with their 3x4 matrix representation.\n        /// </summary>\n        public static void Generic3x4MultiplicationTest<T>(Func<RandomSystem, T> frnd, Func<T, V3d, V3d> trafoTransform, Func<T, V3d, V3d> trafoMul)\n            => GenericMatrixMultiplicationTest<T, M34d, M34d>(\n                    frnd,\n                    trafoTransform,\n                    Mat.TransformPos,\n                    Mat.TransformPos,\n                    trafoMul,\n                    (m, v) => (m * new V4d(v, 1)),\n                    (m, v) => (m * new V4d(v, 1)),\n                    false);\n\n        /// <summary>\n        /// Tests multiplication of T trafos with random 3x4 matrices.\n        /// </summary>\n        public static void GenericFull3x4MultiplicationTest<T>(Func<RandomSystem, T> frnd)\n            => GenericFullMatrixMultiplicationTest<T, M34d, M44d>(\n                    frnd,\n                    GetRandom3x4,\n                    Mat.TransformPos,\n                    (m, v) => (m * new V4d(v, 1)));\n\n        /// <summary>\n        /// Tests multiplication of T trafos with their 4x4 matrix representation.\n        /// </summary>\n        public static void Generic4x4MultiplicationTest<T>(Func<RandomSystem, T> frnd, Func<T, V3d, V3d> trafoTransform, Func<T, V3d, V3d> trafoMul)\n            => GenericMatrixMultiplicationTest<T, M44d, M44d>(\n                    frnd,\n                    trafoTransform, \n                    Mat.TransformPos,\n                    Mat.TransformPos,\n                    trafoMul,\n                    (m, v) => (m * new V4d(v, 1)).XYZ,\n                    (m, v) => (m * new V4d(v, 1)).XYZ);\n\n        /// <summary>\n        /// Tests multiplication of T trafos with random 4x4 matrices.\n        /// </summary>\n        public static void GenericFull4x4MultiplicationTest<T>(Func<RandomSystem, T> frnd)\n            => GenericFullMatrixMultiplicationTest<T, M44d, M44d>(\n                    frnd,\n                    GetRandom4x4,\n                    Mat.TransformPos,\n                    (m, v) => (m * new V4d(v, 1)).XYZ);\n\n        /// <summary>\n        /// Tests if a T trafo can be converted into its string representation and parsed from it again.\n        /// </summary>\n        public static void GenericToStringAndParseTest<T>(Func<RandomSystem, T> frnd, Func<string, T> fparse)\n            => GenericConversionTest(frnd, a => a.ToString(), fparse);\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Trafos/TrafoTests.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing NUnit.Framework;\nusing Aardvark.Base;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class TrafoTests : TestSuite\n    {\n        [Test]\n        public static void Comparison()\n            => TrafoTesting.GenericComparisonTest(TrafoTesting.GetRandomTrafo,\n                t => new Trafo3d(t.Forward + 1, t.Backward + 1));\n\n        [Test]\n        public static void InverseTest()\n            => TrafoTesting.GenericTest(rnd =>\n            {\n                var t = TrafoTesting.GetRandomTrafo(rnd, false);\n\n                var p = rnd.UniformV3d() * rnd.UniformInt(1000);\n                var q = t.Forward.TransformPos(p);\n\n                // Inverse property\n                var res = t.Inverse.Forward.TransformPos(q);\n\n                // Backward\n                var res2 = t.Backward.TransformPos(q);\n\n                TrafoTesting.AreEqual(p, res);\n                TrafoTesting.AreEqual(p, res2);\n            });\n\n        [Test]\n        public static void ToStringAndParse()\n            => TrafoTesting.GenericToStringAndParseTest(TrafoTesting.GetRandomTrafo, Trafo3d.Parse);\n\n        [Test]\n        public void TrafoDecomposeCornerCasesTest()\n        {\n            TrafoTesting.GenericTest((rnd, i) =>\n            {\n                var jitter = (i / 100) * 1e-15;\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.XAxis, V3d.YAxis, V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.XAxis, V3d.ZAxis, V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.YAxis, V3d.XAxis, V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.YAxis, V3d.ZAxis, V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.ZAxis, V3d.YAxis, V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.ZAxis, V3d.XAxis, V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.XAxis, V3d.YAxis, V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.XAxis, V3d.ZAxis, V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.YAxis, V3d.XAxis, V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.YAxis, V3d.ZAxis, V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.ZAxis, V3d.YAxis, V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.ZAxis, V3d.XAxis, V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.XAxis, -V3d.YAxis, V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.XAxis, -V3d.ZAxis, V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.YAxis, -V3d.XAxis, V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.YAxis, -V3d.ZAxis, V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.ZAxis, -V3d.YAxis, V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.ZAxis, -V3d.XAxis, V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.XAxis, V3d.YAxis, -V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.XAxis, V3d.ZAxis, -V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.YAxis, V3d.XAxis, -V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.YAxis, V3d.ZAxis, -V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.ZAxis, V3d.YAxis, -V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.ZAxis, V3d.XAxis, -V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.XAxis, -V3d.YAxis, V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.XAxis, -V3d.ZAxis, V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.YAxis, -V3d.XAxis, V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.YAxis, -V3d.ZAxis, V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.ZAxis, -V3d.YAxis, V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.ZAxis, -V3d.XAxis, V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.XAxis, V3d.YAxis, -V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.XAxis, V3d.ZAxis, -V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.YAxis, V3d.XAxis, -V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.YAxis, V3d.ZAxis, -V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.ZAxis, V3d.YAxis, -V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.ZAxis, V3d.XAxis, -V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.XAxis, -V3d.YAxis, -V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.XAxis, -V3d.ZAxis, -V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.YAxis, -V3d.XAxis, -V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.YAxis, -V3d.ZAxis, -V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.ZAxis, -V3d.YAxis, -V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(V3d.ZAxis, -V3d.XAxis, -V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.XAxis, -V3d.YAxis, -V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.XAxis, -V3d.ZAxis, -V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.YAxis, -V3d.XAxis, -V3d.ZAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.YAxis, -V3d.ZAxis, -V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.ZAxis, -V3d.YAxis, -V3d.XAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n                TestDecompose(Trafo3d.FromOrthoNormalBasis(-V3d.ZAxis, -V3d.XAxis, -V3d.YAxis), Rot3d.Rotation(rnd.UniformV3dDirection(), jitter * rnd.UniformDouble()));\n            });\n        }\n\n        void TestDecompose(Trafo3d trafo, Rot3d jitter)\n        {\n            var x = (M44d)jitter;\n            trafo = trafo * new Trafo3d(x, x.Inverse);\n\n            V3d r_d, s_d, t_d;\n            trafo.Decompose(out s_d, out r_d, out t_d);\n\n            var recomposed = Trafo3d.FromComponents(s_d, r_d, t_d);\n\n            Assert.IsFalse(s_d.AnyNaN || r_d.AnyNaN || t_d.AnyNaN, \"something NaN\");\n\n            var dt = trafo.Forward - recomposed.Forward;\n            var e = dt.NormMax.Abs();\n            Assert.IsTrue(e < 1e-9, \"DIFF\");\n\n            var eq = CheckForwardBackwardConsistency(new Trafo3d(trafo.Forward, recomposed.Backward))\n                && CheckForwardBackwardConsistency(new Trafo3d(recomposed.Forward, trafo.Backward));\n\n\n\n            Assert.True(eq, \"trafo not consistent\");\n        }\n\n        [Test]\n        public void TrafoDecomposeTest()\n        {\n            TrafoTesting.GenericTest((rnd, i) =>\n            {\n                var rot = rnd.UniformV3dFull() * Constant.PiTimesFour - Constant.PiTimesTwo;\n                var trans = rnd.UniformV3dFull() * 10 - 5;\n                var scale = rnd.UniformV3dFull() * 4 - 2;\n\n                TestDecompose(scale, rot, trans);\n            });\n        }\n\n        void TestDecompose(V3d scale, V3d rotation, V3d translation)\n        {\n            var trafo = Trafo3d.FromComponents(scale, rotation, translation);\n            V3d r_d, s_d, t_d;\n            trafo.Decompose(out s_d, out r_d, out t_d);\n\n            var recomposed = Trafo3d.FromComponents(s_d, r_d, t_d);\n\n            Assert.IsFalse(s_d.AnyNaN || r_d.AnyNaN || t_d.AnyNaN, \"something NaN\");\n\n            var e_scale = (s_d.Abs() - scale.Abs()).LengthSquared;\n            var e_trans = (t_d - translation).LengthSquared;\n            Assert.True(e_scale < 1e-5, \"Scale\");\n            Assert.True(e_trans < 1e-5, \"Translation\");\n\n            ValidateTrafos(trafo, recomposed);\n        }\n\n        [Test]\n        public void TrafoRotIntoTest()\n        {\n            TrafoTesting.GenericTest((rnd, i) =>\n            {\n                var rx = new V3d(rnd.UniformDouble() * 1e-17, 0, 0) * (rnd.UniformDouble() > 0.5 ? 1 : -1);\n                var ry = new V3d(0, rnd.UniformDouble() * 1e-17, 0) * (rnd.UniformDouble() > 0.5 ? 1 : -1);\n                var rz = new V3d(0, 0, rnd.UniformDouble() * 1e-17) * (rnd.UniformDouble() > 0.5 ? 1 : -1);\n\n                // equal cases\n                var req = new[]\n                {\n                    Trafo3d.RotateInto(V3d.XAxis, (V3d.XAxis + ry).Normalized),\n                    Trafo3d.RotateInto(V3d.YAxis, (V3d.YAxis + rz).Normalized),\n                    Trafo3d.RotateInto(V3d.ZAxis, (V3d.ZAxis + rx).Normalized),\n                };\n                foreach (var r in req)\n                    Assert.True(CheckForwardBackwardConsistency(r));\n\n                // 180° cases\n                var r180 = new[]\n                {\n                    Trafo3d.RotateInto(-V3d.XAxis, ( V3d.XAxis + ry).Normalized),\n                    Trafo3d.RotateInto( V3d.XAxis, (-V3d.XAxis + rz).Normalized),\n                    Trafo3d.RotateInto(-V3d.YAxis, ( V3d.YAxis + rz).Normalized),\n                    Trafo3d.RotateInto( V3d.YAxis, (-V3d.YAxis + rx).Normalized),\n                    Trafo3d.RotateInto(-V3d.ZAxis, ( V3d.ZAxis + rx).Normalized),\n                    Trafo3d.RotateInto( V3d.ZAxis, (-V3d.ZAxis + ry).Normalized)\n                };\n                foreach (var r in r180)\n                    Assert.True(CheckForwardBackwardConsistency(r));\n\n                // 90° cases\n                var r90 = new[]\n                {\n                    Trafo3d.RotateInto((-V3d.XAxis + rz).Normalized, V3d.ZAxis),\n                    Trafo3d.RotateInto(( V3d.XAxis + ry).Normalized, V3d.ZAxis),\n                    Trafo3d.RotateInto((-V3d.YAxis + rx).Normalized, V3d.ZAxis),\n                    Trafo3d.RotateInto(( V3d.YAxis + rz).Normalized, V3d.ZAxis),\n\n                    Trafo3d.RotateInto(-V3d.XAxis, (-V3d.ZAxis + rx).Normalized),\n                    Trafo3d.RotateInto( V3d.XAxis, (-V3d.ZAxis + rx).Normalized),\n                    Trafo3d.RotateInto(-V3d.YAxis, (-V3d.ZAxis + ry).Normalized),\n                    Trafo3d.RotateInto( V3d.YAxis, (-V3d.ZAxis + ry).Normalized),\n                };\n                foreach (var r in r90)\n                    Assert.True(CheckForwardBackwardConsistency(r));\n            });\n        }\n        \n        void ValidateTrafos(Trafo3d a, Trafo3d b)\n        {\n            var e = Mat.DistanceMax(a.Forward, b.Forward);\n            Assert.IsTrue(e.Abs() < 1e-8, \"not equal\");\n\n            var eq = CheckForwardBackwardConsistency(new Trafo3d(a.Forward, b.Backward))\n                  && CheckForwardBackwardConsistency(new Trafo3d(b.Forward, a.Backward));\n\n            Assert.True(eq, \"trafo not consistent\");\n        }\n\n        bool CheckForwardBackwardConsistency(Trafo3d trafo)\n        {\n            var i = trafo.Forward * trafo.Backward;\n            // i should be Identity\n            return i.C0.ApproximateEquals(V4d.IOOO, 1e-7)\n                && i.C1.ApproximateEquals(V4d.OIOO, 1e-7)\n                && i.C2.ApproximateEquals(V4d.OOIO, 1e-7)\n                && i.C3.ApproximateEquals(V4d.OOOI, 1e-7);\n        }\n        \n        [Test]\n        public void CoordsystemTransformTest()\n        {\n            var sys = new[] \n                {\n                  new CoordinateSystem.Info(1, CoordinateSystem.Handedness.Left, CoordinateSystem.Axis.X),\n                  new CoordinateSystem.Info(1, CoordinateSystem.Handedness.Right, CoordinateSystem.Axis.X),\n                  new CoordinateSystem.Info(1, CoordinateSystem.Handedness.Left, CoordinateSystem.Axis.Y),\n                  new CoordinateSystem.Info(1, CoordinateSystem.Handedness.Right, CoordinateSystem.Axis.Y),\n                  new CoordinateSystem.Info(1, CoordinateSystem.Handedness.Left, CoordinateSystem.Axis.Z),\n                  new CoordinateSystem.Info(1, CoordinateSystem.Handedness.Right, CoordinateSystem.Axis.Z),\n                  new CoordinateSystem.Info(10, CoordinateSystem.Handedness.Left, CoordinateSystem.Axis.X),\n                  new CoordinateSystem.Info(10, CoordinateSystem.Handedness.Right, CoordinateSystem.Axis.X),\n                  new CoordinateSystem.Info(10, CoordinateSystem.Handedness.Left, CoordinateSystem.Axis.Y),\n                  new CoordinateSystem.Info(10, CoordinateSystem.Handedness.Right, CoordinateSystem.Axis.Y),\n                  new CoordinateSystem.Info(10, CoordinateSystem.Handedness.Left, CoordinateSystem.Axis.Z),\n                  new CoordinateSystem.Info(10, CoordinateSystem.Handedness.Right, CoordinateSystem.Axis.Z)\n                };\n\n            //foreach(var from in sys)\n            //    foreach(var to in sys)\n            //    {\n            //        // TODO: think about what the correct validation is and implement this test properly...\n\n            //        var direct = CoordinateSystem.FromTo(from, to);\n            //        var usingAardvark = CoordinateSystem.ToAardvark(to).Inverse * CoordinateSystem.ToAardvark(from);\n\n            //        ValidateTrafos(direct, usingAardvark);\n            //    }\n        }\n        \n        [Test]\n        public static void NormalFrame()\n        {\n            TrafoTesting.GenericTest((rnd, i) =>\n            {\n                var n = rnd.UniformV3d().Normalized;\n\n                var basis = M33d.NormalFrame(n);\n\n                Assert.IsTrue(basis.C0.Length.ApproximateEquals(1, 1e-7));\n                Assert.IsTrue(basis.C1.Length.ApproximateEquals(1, 1e-7));\n                Assert.IsTrue(basis.C2.Length.ApproximateEquals(1, 1e-7));\n\n                Assert.IsTrue(basis.C0.AngleBetween(basis.C1).ApproximateEquals(Constant.PiHalf, 1e-7));\n                Assert.IsTrue(basis.C0.AngleBetween(basis.C2).ApproximateEquals(Constant.PiHalf, 1e-7));\n                Assert.IsTrue(basis.C1.AngleBetween(basis.C2).ApproximateEquals(Constant.PiHalf, 1e-7));\n            });\n        }\n\n        [Test]\n        public static void OrthoNormalOrientation()\n        {\n            // Previous implementation\n            Func<Trafo3d, Trafo3d> reference = trafo =>\n            {\n                var x = trafo.Forward.C0.XYZ.Normalized; // TransformDir(V3f.XAxis)\n                var y = trafo.Forward.C1.XYZ.Normalized; // TransformDir(V3f.YAxis)\n                var z = trafo.Forward.C2.XYZ.Normalized; // TransformDir(V3f.ZAxis)\n\n                y = z.Cross(x).Normalized;\n                z = x.Cross(y).Normalized;\n\n                return Trafo3d.FromBasis(x, y, z, V3d.Zero);\n            };\n\n            var rnd = new RandomSystem(1);\n\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var trafo = TrafoTesting.GetRandomTrafo(rnd);\n\n                var res = trafo.GetOrthoNormalOrientation();\n                var res_ref = reference(trafo);\n\n                TrafoTesting.AreEqual(res, res_ref);\n            });\n        }\n\n        [Test]\n        public static void TransformTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var trafo = TrafoTesting.GetRandomTrafo(rnd);\n                var v3d = rnd.UniformV3d() * rnd.UniformInt(100);\n                var v4d = rnd.UniformV4d() * rnd.UniformInt(100);\n\n                Assert.AreEqual(trafo.Transform(v4d), trafo.Forward.Transform(v4d));\n                Assert.AreEqual(trafo.TransformPos(v3d), trafo.Forward.TransformPos(v3d));\n                Assert.AreEqual(trafo.TransformDir(v3d), trafo.Forward.TransformDir(v3d));\n                Assert.AreEqual(trafo.TransformNormal(v3d), trafo.Backward.TransposedTransformDir(v3d));\n            });\n        }\n\n        [Test]\n        public static void InvTransformTest()\n        {\n            TrafoTesting.GenericTest(rnd =>\n            {\n                var trafo = TrafoTesting.GetRandomTrafo(rnd);\n                var v3d = rnd.UniformV3d() * rnd.UniformInt(100);\n                var v4d = rnd.UniformV4d() * rnd.UniformInt(100);\n\n                Assert.AreEqual(trafo.InvTransform(v4d), trafo.Backward.Transform(v4d));\n                Assert.AreEqual(trafo.InvTransformPos(v3d), trafo.Backward.TransformPos(v3d));\n                Assert.AreEqual(trafo.InvTransformDir(v3d), trafo.Backward.TransformDir(v3d));\n                Assert.AreEqual(trafo.InvTransformNormal(v3d), trafo.Forward.TransposedTransformDir(v3d));\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Vectors/V3fCoderTests.cs",
    "content": "using System;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class V3fCoderTests : TestSuite\n    {\n        public V3fCoderTests() : base() { }\n        public V3fCoderTests(TestSuite.Options options) : base(options) { }\n\n        [Test]\n        public void TestV3fCoder()\n        {\n            foreach (var bits in new[] { 5, 8, 12, 16, 20, 24, 32 })\n                RasterTest(V3fCoder.RasterForBits(bits));\n        }\n\n        public void RasterTest(uint raster)\n        {\n            int iraster = (int)raster;\n\n            V3fCoder coder = new V3fCoder(raster);\n\n            uint step = 1;\n            bool large = false;\n\n            if (iraster > 52) { step = 7; large = true; }\n            if (iraster > 591) step = 63;\n            if (iraster > 6688) step = 2039;\n\n            int bits = (int)Fun.Ceiling(Fun.Log2(coder.Count));\n\n            Test.Begin(\"normal coder raster {0} ({1} bits)\", iraster, bits);\n            /*\n            Console.WriteLine(\"  raster = {0}\", m_raster);\n            Console.WriteLine(\"  rasterMul2Sub1 = {0}\", m_r2Sub1);\n            Console.WriteLine(\"  doubleRaster = {0}\", m_doubleRaster);\n            Console.WriteLine(\"  invDoubleRaster = {0}\", m_invDoubleRaster);\n            Console.WriteLine(\"  edgeBasis = {0}\", m_edgeBasis);\n            Console.WriteLine(\"  cornerBasis = {0}\", m_cornerBasis);\n            */\n            Test.Begin(\"testing {0} of {1} codes\", 1 + ((long)coder.Count - 1) / (long)step, coder.Count);\n            for (uint code = 0; code < coder.Count; code += step)\n            {\n                V3f dir = coder.Decode(code);\n                uint newCode = coder.Encode(dir);\n                Test.IsTrue(code == newCode);\n            }\n            Test.End();\n\n            double minDot = 1.0;\n\n            float eps = Constant<float>.PositiveTinyValue;\n\n            float[] factorTable = { 1.0f - eps, 1.0f, 1.0f + eps };\n\n            for (int sign = -1; sign < 2; sign += 2)\n            {\n                for (int axis = 0; axis < 3; axis++)\n                {\n                    float factor = factorTable[axis];\n\n                    for (int xi = -2 * iraster; xi <= 2 * iraster; xi++)\n                    {\n                        if (large && (xi > 3 - 2 * iraster) && (xi < -3))\n                            continue;\n                        if (large && (xi < 2 * iraster - 3) && (xi > +3))\n                            continue;\n                        double x = (double)xi * factor / (2 * iraster);\n                        #if (!V3FCODER_NO_WARP)\n                        x = V3fCoder.SphericalOfBox(x);\n                        #endif\n                        for (int yi = -2 * iraster; yi <= 2 * iraster; yi++)\n                        {\n                            if (large && (yi > 3 - 2 * iraster) && (yi < -3))\n                                continue;\n                            if (large && (yi < 2 * iraster - 3) && (yi > +3))\n                                continue;\n                            double y = (double)yi * factor / (2 * iraster);\n\n                            #if (!V3FCODER_NO_WARP)\n                            y = V3fCoder.SphericalOfBox(y);\n                            #endif\n                            V3f n = new V3f(0, 0, 0); // init to make compiler h.\n                            n[axis] = sign;\n                            n[(axis + 1) % 3] = (float)x;\n                            n[(axis + 2) % 3] = (float)y;\n\n                            n.Normalize();\n\n                            uint code = coder.Encode(n);\n                            V3f newN = coder.Decode(code);\n\n                            double newDot = Vec.Dot(n, newN);\n                            if (newDot < minDot) minDot = newDot;\n                        }\n                    }\n                }\n            }\n            double maxErr = System.Math.Acos(minDot) * 180.0 / System.Math.PI;\n            Report.Line(\"maximal error {0:g4} degrees\", maxErr);\n            Test.End();\n        }\n\n\n        public void NeigbourTest(uint raster)\n        {\n            var coder = new V3fCoder(raster);\n            for (uint code = 0; code < coder.Count; code++)\n            {\n                uint[] neighbours = new uint[8];\n                V3f n = coder.DecodeOnCube(code, false);\n                uint nCount = coder.NeighbourCodes(code, neighbours);\n\n                float min = float.MaxValue;\n                float max = float.MinValue;\n                for (uint nc = 0; nc < nCount; nc++)\n                {\n                    V3f nv = coder.DecodeOnCube(neighbours[nc], false);\n                    float diff = (nv - n).Length;\n                    if (diff < min) min = diff;\n                    if (diff > max) max = diff;\n                }\n\n                if (min < 0.000001) Console.WriteLine(\"min too small\");\n                if (max > 2.0 * min) Console.WriteLine(\"max too large\");\n\n                if (raster < 3)\n                {\n                    Console.WriteLine(\"code {0} min {1} max {2}\",\n                                      code, min, max);\n                }\n\n                min *= 0.99f;\n\n                for (uint nc0 = 0; nc0 < nCount; nc0++)\n                {\n                    V3f nv0 = coder.DecodeOnCube(neighbours[nc0], false);\n                    for (uint nc1 = nc0 + 1; nc1 < nCount; nc1++)\n                    {\n                        V3f nv1 = coder.DecodeOnCube(neighbours[nc1], false);\n                        float diff = (nv1 - nv0).Length;\n                        if (diff < min) Console.Write(\"neighbours too close\");\n                    }\n                }\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/Vectors/VectorTests.cs",
    "content": "using System;\nusing Aardvark.Base;\nusing NUnit.Framework;\n\nnamespace Aardvark.Tests\n{\n    [TestFixture]\n    public class VectorTests\n    {\n        [Test]\n        public void Vector_MinMaxElement()\n        {\n            var rnd = new RandomSystem(1);\n            var v = rnd.UniformV4i();\n\n            var min1 = v.MinElement;\n            var min2 = Vec.MinElement(v);\n            var min_ref = v.ToArray().Min();\n\n            Assert.AreEqual(min1, min_ref);\n            Assert.AreEqual(min2, min_ref);\n\n            var max1 = v.MaxElement;\n            var max2 = Vec.MaxElement(v);\n            var max_ref = v.ToArray().Max();\n\n            Assert.AreEqual(max1, max_ref);\n            Assert.AreEqual(max2, max_ref);\n        }\n\n        [Test]\n        public void Vector_Invalid1()\n        {\n            Assert.IsTrue(new V2d(double.NaN, double.NaN).IsNaN);\n        }\n\n        [Test]\n        public void Vector_Invalid2()\n        {\n            Assert.IsTrue(new V2d(double.NaN, 0.0).IsNaN);\n        }\n\n        [Test]\n        public void Vector_Invalid3()\n        {\n            Assert.IsTrue(new V2d(0.0, double.NaN).IsNaN);\n        }\n\n        [Test]\n        public void Vector_Invalid4()\n        {\n            Assert.IsTrue(!new V2d(0.0, 0.0).IsNaN);\n        }\n\n        [Test]\n        public void Vector_Bitwise()\n        {\n            var v = new V2l(1, 2);\n            Assert.AreEqual(~v, new V2l(~v.X, ~v.Y));\n            Assert.AreEqual(v << 1, new V2l(2, 4));\n            Assert.AreEqual(v >> 1, new V2l(0, 1));\n            Assert.AreEqual(v | 1, new V2l(v.X | 1,   v.Y | 1));\n            Assert.AreEqual(1 | v, new V2l(1   | v.X, 1   | v.Y));\n            Assert.AreEqual(v | v, new V2l(v.X | v.X, v.Y | v.Y));\n            Assert.AreEqual(v & 1, new V2l(v.X & 1,   v.Y & 1));\n            Assert.AreEqual(1 & v, new V2l(1   & v.X, 1   & v.Y));\n            Assert.AreEqual(v & v, new V2l(v.X & v.X, v.Y & v.Y));\n            Assert.AreEqual(v ^ 1, new V2l(v.X ^ 1,   v.Y ^ 1));\n            Assert.AreEqual(1 ^ v, new V2l(1   ^ v.X, 1   ^ v.Y));\n            Assert.AreEqual(v ^ v, new V2l(v.X ^ v.X, v.Y ^ v.Y));\n        }\n\n        [Test]\n        public void Vector_SwizzleSetters()\n        {\n            var v = new V4l(1, 2, 3, 4);\n\n            v.WX = new V2l(7, 8);\n            Assert.AreEqual(v, new V4l(8, 2, 3, 7));\n\n            v.WYX = new V3l(3, 5, 2);\n            Assert.AreEqual(v, new V4l(2, 5, 3, 3));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Tests/Aardvark.Base.Tests/paket.references",
    "content": "group Test\n\nNUnit\nNUnit3TestAdapter\nMicrosoft.NET.Test.Sdk"
  },
  {
    "path": "src/Tests/Aardvark.Geometry.Tests/Aardvark.Geometry.Tests.fsproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>\n    <GenerateProgramFile>false</GenerateProgramFile>\n    <WarnOn>3389;3390;3395</WarnOn>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Debug</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|AnyCPU'\">\n    <OutputPath>..\\..\\..\\bin\\Release</OutputPath>\n  </PropertyGroup>\n  <PropertyGroup>\n\t<RunWorkingDirectory>$(OutputPath)\\net8.0</RunWorkingDirectory>\n  </PropertyGroup>\n  <ItemGroup>\n    <Compile Include=\"PolyRegion2dTests.fs\" />\n    <Compile Include=\"Regression.fs\" />\n    <Compile Include=\"TexturePacking.fs\" />\n    <Compile Include=\"Program.fs\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\Aardvark.Base.Tensors\\Aardvark.Base.Tensors.fsproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Base\\Aardvark.Base.csproj\" />\n    <ProjectReference Include=\"..\\..\\Aardvark.Geometry\\Aardvark.Geometry.fsproj\" />\n  </ItemGroup>\n  <Import Project=\"..\\..\\..\\.paket\\Paket.Restore.targets\" />\n</Project>"
  },
  {
    "path": "src/Tests/Aardvark.Geometry.Tests/PolyRegion2dTests.fs",
    "content": "﻿namespace Aardvark.Geometry.Tests\n\nopen NUnit.Framework\nopen FsUnit\n\nopen Aardvark.Base\nopen Aardvark.Geometry\n\nmodule PolyRegion2dTests =\n    \n    [<Test>]\n    let ``Subtract small from large PolyRegion``() =\n        \n        let A = PolyRegion.ofList [ V2d(1.0, 1.0); V2d(-1.0, 1.0); V2d(-1.0, -1.0); V2d(1.0, -1.0)]\n        let B = PolyRegion.ofList [ V2d(1.5, 1.5); V2d(0.5, 1.5); V2d(0.5, 0.5); V2d(1.5, 0.5)]\n\n        let Diff = (A - B).Polygons.Head.Points |> Seq.toList\n        \n        Diff |> should equal ([ V2d(-1, 1); V2d(-1, -1); V2d(1, -1); V2d(1.0, 0.5); V2d(0.5, 0.5); V2d(0.5, 1.0);])\n\n    [<Test>]\n    let ``Subtract large from small PolyRegion``() =\n        \n        let A = PolyRegion.ofList [ V2d(1.0, 1.0); V2d(-1.0, 1.0); V2d(-1.0, -1.0); V2d(1.0, -1.0)]\n        let B = PolyRegion.ofList [ V2d(10, 10); V2d(0.5, 10.0); V2d(0.5, 0.5); V2d(10.0, 0.5)]\n\n        let Diff = (A - B).Polygons.Head.Points |> Seq.toList\n        \n        Diff |> should equal ([ V2d(-1, 1); V2d(-1, -1); V2d(1, -1); V2d(1.0, 0.5); V2d(0.5, 0.5); V2d(0.5, 1.0);])\n\n    [<Test>]\n    let ``Subtract combined PolyRegion from PolyRegion``() =\n        \n        let A = PolyRegion.ofList [ V2d(1.0, 1.0); V2d(-1.0, 1.0); V2d(-1.0, -1.0); V2d(1.0, -1.0)]\n        \n        let B = PolyRegion.ofList ([ V2d(1.0, 1.0); V2d(-1.0, 1.0); V2d(-1.0, -1.0); V2d(1.0, -1.0) ] |> List.map (fun v -> v + V2d(0.5, 0.5)))\n        let C = PolyRegion.ofList ([ V2d(1.0, 1.0); V2d(-1.0, 1.0); V2d(-1.0, -1.0); V2d(1.0, -1.0) ] |> List.map (fun v -> v - V2d(0.5, 0.5)))\n\n        let Diff = (A - (B + C))\n        \n        let Diff0 = (Diff.Polygons.Item 0).Points |> Seq.toList\n        let Diff1 = (Diff.Polygons.Item 1).Points |> Seq.toList\n\n        Diff0 |> should equal ([ V2d(-0.5, 1.0); V2d(-1, 1); V2d(-1.0, 0.5); V2d(-0.5, 0.5)])\n        Diff1 |> should equal ([ V2d(1.0, -0.5); V2d(0.5, -0.5); V2d(0.5, -1.0); V2d(1, -1)])\n\n    [<Test>]\n    let ``Subtract intersection with combined PolyRegion from PolyRegion``() =\n        \n        let A = PolyRegion.ofList [ V2d(1.0, 1.0); V2d(-1.0, 1.0); V2d(-1.0, -1.0); V2d(1.0, -1.0)]\n        \n        let B = PolyRegion.ofList ([ V2d(1.0, 1.0); V2d(-1.0, 1.0); V2d(-1.0, -1.0); V2d(1.0, -1.0) ] |> List.map (fun v -> v + V2d(0.5, 0.5)))\n        let C = PolyRegion.ofList ([ V2d(1.0, 1.0); V2d(-1.0, 1.0); V2d(-1.0, -1.0); V2d(1.0, -1.0) ] |> List.map (fun v -> v - V2d(0.5, 0.5)))\n\n        let Diff = (A - (A * (B + C)))\n        \n        let Diff0 = (Diff.Polygons.Item 0).Points |> Seq.toList\n        let Diff1 = (Diff.Polygons.Item 1).Points |> Seq.toList\n\n        Diff0 |> should equal ([ V2d(-0.5, 1.0); V2d(-1, 1); V2d(-1.0, 0.5); V2d(-0.5, 0.5)])\n        Diff1 |> should equal ([ V2d(1.0, -0.5); V2d(0.5, -0.5); V2d(0.5, -1.0); V2d(1, -1)])\n\n    [<Test>]\n    [<Ignore(\"are the expected results correct?\")>]\n    let ``Subtract intersection with large combined PolyRegion from PolyRegion``() =\n        \n        let A = PolyRegion.ofList [ V2d(8, 3); V2d(0, 3); V2d(0, 0); V2d(8, 0)]\n        \n        let B = PolyRegion.ofList ([ V2d(7.5, 2.5); V2d(-4.0, 2.5); V2d(-4, -4); V2d(7.5, -4.0) ])\n        let C = PolyRegion.ofList ([ V2d(14.0, 7.5); V2d(0.4, 7.5); V2d(0.4, 0.3); V2d(14.0, 0.3)])\n        \n        let Diff = (A - (A * (B + C)))\n\n        let Diff0 = (Diff.Polygons.Item 0).Points |> Seq.toList\n        let Diff1 = (Diff.Polygons.Item 1).Points |> Seq.toList\n\n        Diff0 |> should equal ([ V2d(0.4, 3.0); V2d(0, 3); V2d(0.0, 2.5); V2d(0.4, 2.5)])\n        Diff1 |> should equal ([ V2d(8.0, 0.3); V2d(7.5, 0.3); V2d(7.5, 0.0); V2d(8, 0)])\n\n    [<Test>]\n    let ``Small PolyRegion contained in large PolyRegion`` () =\n\n        let p1 = PolyRegion.ofArray([|V2d(0.5,0.5);V2d(-0.5,0.5);V2d(-0.5,-0.5);V2d(0.5,-0.5)|])\n        let p2 = PolyRegion.ofArray([|V2d(1.0,1.0);V2d(-1.0,1.0);V2d(-1.0,-1.0);V2d(1.0,-1.0)|])\n        \n        p1 |> PolyRegion.containsRegion p2 |> should equal true\n"
  },
  {
    "path": "src/Tests/Aardvark.Geometry.Tests/Program.fs",
    "content": "﻿module Program\n\nopen Aardvark.Geometry.Tests\n\n[<EntryPoint>]\nlet main args = \n    TexturePackingTests.run args"
  },
  {
    "path": "src/Tests/Aardvark.Geometry.Tests/Regression.fs",
    "content": "﻿namespace Aardvark.Geometry.Tests\n\nopen System\nopen NUnit.Framework\nopen FsUnit\nopen FsCheck\nopen FsCheck.NUnit\n\nopen Aardvark.Base\nopen Aardvark.Geometry\n\nmodule Regression3dTests =\n    \n    module Gen =\n\n        /// generates a float in [0,1]\n        let uniformFloat =\n            // choose two ints with 22/31 bits, create an uint64 from these and normalize to float.\n            // this creates a full-precision float since float has 53 \"effective\" significand bits.\n            (Gen.choose (0, 4194303), Gen.choose (0, Int32.MaxValue)) ||> Gen.map2 (fun a b ->\n                let v = (uint64 a <<< 31) ||| uint64 b\n                float v / 9007199254740991.0\n            )                \n\n        /// generates a float in [min, max]\n        let uniform (min : float) (max : float) =\n            uniformFloat |> Gen.map (fun v ->\n                min + v * (max - min)\n            )\n\n        /// generates a float from N(avg, dev)\n        let gauss (avg : float) (dev : float) =\n            uniform -1.0 1.0 |> Gen.map (fun v ->\n                let side = sign v\n                let v = abs v |> max 1E-9\n                let x = sqrt (-log v)\n                let n01 = x * float side\n                n01 * dev + avg\n            )\n\n        /// generates a normalized V3d direction\n        let direction =\n            gen {\n                let! phi = uniform 0.0 Constant.PiTimesTwo\n                let! z = uniform -1.0 1.0\n\n                let xy = sqrt(1.0 - sqr z)\n\n                return \n                    V3d(\n                        cos phi * xy,\n                        sin phi * xy,\n                        z\n                    )\n            }\n\n    type AtLeast<'d, 'a when 'd :> INatural>(value : 'a[]) =\n        member x.Value = value\n        override x.ToString() =\n            sprintf \"%d: %A\" value.Length value\n\n    type ZeroOneFloat =\n        ZeroOneFloat of float\n    type GaussFloat =\n        GaussFloat of float\n\n\n    type EuclideanGenerator private() =\n\n        static member ZeroOneFloat =\n            Gen.uniformFloat |> Gen.map ZeroOneFloat |> Arb.fromGen\n\n        static member GaussFloat =\n            Gen.gauss 0.0 1.0 |> Gen.map GaussFloat |> Arb.fromGen\n\n        static member AtLeast<'d, 'a when 'd :> INatural>() =\n            gen {\n                let d = typeSize<'d>\n\n                let! rest = Arb.generate<'a[]>\n                let fin = Array.zeroCreate (rest.Length + d)\n\n\n                let mutable oi = 0\n                let rec exists (i : int) (v : 'a) =\n                    if i >= oi then \n                        false\n                    else    \n                        if Unchecked.equals fin.[oi] v then true\n                        else exists (i+1) v\n\n                while oi < d do\n                    let! v = Arb.generate<'a>\n                    if not (exists 0 v) then\n                        fin.[oi] <- v\n                        oi <- oi + 1\n\n                fin.[d..] <- rest\n\n                return fin |> AtLeast<'d, 'a>\n            }|> Arb.fromGen\n\n        static member V2d =\n            gen {\n                let! x = Gen.gauss 0.0 500.0\n                let! y = Gen.gauss 0.0 100.0\n                return V2d(x,y)\n            } |> Arb.fromGen\n            \n        static member V3d =\n            gen {\n                let! x = Gen.gauss 0.0 500.0\n                let! y = Gen.gauss 0.0 100.0\n                let! z = Gen.gauss 0.0 300.0\n                return V3d(x,y,z)\n            } |> Arb.fromGen\n            \n        static member Euclidean2d =\n            gen {\n                let! x = Gen.gauss 0.0 300.0\n                let! y = Gen.gauss 0.0 300.0\n                let! angle = Gen.uniform 0.0 Constant.PiTimesTwo\n\n                return Euclidean2d(Rot2d angle, V2d(x,y))\n\n            } |> Arb.fromGen\n        static member Euclidean3d =\n            gen {\n                let! x = Gen.gauss 0.0 300.0\n                let! y = Gen.gauss 0.0 300.0\n                let! z = Gen.gauss 0.0 300.0\n\n                let! axis = Gen.direction\n                let! angle = Gen.uniform 0.0 Constant.PiTimesTwo\n\n                let rot = Rot3d.FromAngleAxis(angle * axis)\n                return Euclidean3d(rot, V3d(x,y,z))\n\n            } |> Arb.fromGen\n\n    let checkPlane (r : LinearRegression3d) (points : V3d[]) =\n        let plane = r.GetPlane()\n        let error = points |> Array.map (plane.Height >> abs) |> Array.max\n        error |> should be (lessThanOrEqualTo 1E-6)\n\n    let checkTrafo (r : LinearRegression3d) (points : V3d[]) =\n        let trafo = r.GetTrafo()\n        let error = points |> Array.map (fun p -> trafo.Backward.TransformPos(p).Z |> abs) |> Array.max\n        error |> should be (lessThanOrEqualTo 1E-6)\n        \n    let check (points : V3d[]) (r : LinearRegression3d) =\n        checkPlane r points\n        checkTrafo r points\n        \n    let checkPlane2d (r : LinearRegression2d) (points : V2d[]) =\n        let struct(plane, _) = r.GetPlaneAndConfidence()\n        let error = points |> Array.map (plane.Height >> abs) |> Array.max\n        error |> should be (lessThanOrEqualTo 1E-6)\n        \n    let checkTrafo2d (r : LinearRegression2d) (points : V2d[]) =\n        let trafo = r.GetTrafo()\n        let error = points |> Array.map (fun p -> trafo.Backward.TransformPos(p).Y |> abs) |> Array.max\n        error |> should be (lessThanOrEqualTo 1E-6)\n        \n    let check2d (points : V2d[]) (r : LinearRegression2d) =\n        checkPlane2d r points\n        checkTrafo2d r points\n\n        \n    let checkSphere (points : V3d[]) (r : SphereRegression3d) =\n        let s = r.GetSphere()\n        let error = points |> Array.map (fun p -> abs (Vec.distance p s.Center - s.Radius)) |> Array.max\n        error |> should be (lessThanOrEqualTo 1E-6)\n\n    [<Property(Arbitrary = [| typeof<EuclideanGenerator> |])>]\n    let ``LinearRegression3d working`` (trafo : Euclidean3d) (points : AtLeast<8 N, V2d>) =\n        let pts = \n            points.Value\n            |> Array.map (fun p -> trafo.TransformPos(V3d(p, 0.0)))\n\n        // add working\n        pts |> Array.fold (+) LinearRegression3d.empty |> check pts\n\n        // ofArray/ofSeq working\n        pts |> LinearRegression3d.ofArray |> check pts\n        pts |> LinearRegression3d.ofSeq |> check pts\n\n        // constructor working\n        pts |> LinearRegression3d |> check pts\n\n        // regression addition working\n        let n2 = pts.Length / 2\n        LinearRegression3d.ofArray pts.[..n2-1] + LinearRegression3d.ofArray pts.[n2..] |> check pts\n\n        // remove working\n        pts |> Array.fold (+) (LinearRegression3d V3d.Zero) |> LinearRegression3d.remove V3d.Zero |> check pts\n        \n\n    [<Property(Arbitrary = [| typeof<EuclideanGenerator> |])>]\n    let ``LinearRegression2d working`` (trafo : Euclidean2d) (points : AtLeast<8 N, GaussFloat>) =\n        let pts = points.Value |> Array.map (fun (GaussFloat v) -> trafo.TransformPos(V2d(v * 10.0, 0.0)))\n        \n        // add working\n        pts |> Array.fold (+) LinearRegression2d.empty |> check2d pts\n\n        // ofArray/ofSeq working\n        pts |> LinearRegression2d.ofArray |> check2d pts\n        pts |> LinearRegression2d.ofSeq |> check2d pts\n\n        // constructor working\n        pts |> LinearRegression2d |> check2d pts\n\n        // regression addition working\n        let n2 = pts.Length / 2\n        LinearRegression2d.ofArray pts.[..n2-1] + LinearRegression2d.ofArray pts.[n2..] |> check2d pts\n\n        // remove working\n        pts |> Array.fold (+) (LinearRegression2d V2d.Zero) |> LinearRegression2d.remove V2d.Zero |> check2d pts\n\n    [<Property(Arbitrary = [| typeof<EuclideanGenerator> |])>]\n    let ``SphereRegression3d working`` (center : V3d) (GaussFloat radius) (bad : V3d) (points : AtLeast<100 N, V2d>) =\n        let pts = \n            points.Value\n            |> Array.map (fun p -> center + p.CartesianFromSpherical() * radius)\n\n        let bb = Box3d pts\n        let r = (bad / bb.Size)\n        let somePoint = bb.Center + bb.Size * r / r.NormMax\n\n        // add working\n        pts |> Array.fold (+) SphereRegression3d.empty |> checkSphere pts\n\n        // ofArray/ofSeq working\n        pts |> SphereRegression3d.ofArray |> checkSphere pts\n        pts |> SphereRegression3d.ofSeq |> checkSphere pts\n\n        // constructor working\n        pts |> SphereRegression3d |> checkSphere pts\n\n        // regression addition working\n        let n2 = pts.Length / 2\n        SphereRegression3d.ofArray pts.[..n2-1] + SphereRegression3d.ofArray pts.[n2..] |> checkSphere pts\n\n        // remove working\n        pts |> Array.fold (+) (SphereRegression3d somePoint) |> SphereRegression3d.remove somePoint |> checkSphere pts\n        \n\n"
  },
  {
    "path": "src/Tests/Aardvark.Geometry.Tests/TexturePacking.fs",
    "content": "﻿namespace Aardvark.Geometry.Tests\n\nopen System\nopen NUnit.Framework\nopen FsUnit\nopen FsCheck\nopen FsCheck.NUnit\n\nopen FSharp.Data.Adaptive\nopen Aardvark.Base\nopen Aardvark.Geometry\n\nmodule TexturePackingTests =\n\n    [<Struct>]\n    type Size = Size of V2i\n\n    type SizeGenerator() =\n        static member SizeGen =\n            (Gen.choose (1, 64), Gen.choose (1,64)) ||> Gen.map2 (fun x y -> V2i(x,y) |> Size)\n\n        static member Size() =\n            (Gen.choose (1, 64), Gen.choose (1,64)) ||> Gen.map2 (fun x y -> V2i(x,y) |> Size) |> Arb.fromGen\n\n\n    [<Property(Arbitrary = [| typeof<SizeGenerator> |])>]\n    let ``square producing correct results``(NonEmptyArray (sizes)) =\n        let sizes = sizes |> Array.mapi (fun i (Size s) -> i, s)\n        let packing = TexturePacking.square sizes\n\n        let mutable res = packing\n        for i,_ in sizes do\n            res <- res.Remove i\n\n\n        let bb = Box2i(V2i.Zero, packing.Size - V2i.II)\n\n        // non overlapping and in range\n        let rects = packing |> TexturePacking.toArray\n        for i in 0 .. rects.Length - 1 do\n            let (_, ri) = rects.[i]\n            bb.Contains ri |> should be True\n            for j in i + 1 .. rects.Length - 1 do\n                let (_, rj) = rects.[j]\n                ri.Intersects rj |> should be False\n\n        let mutable all = packing.Used\n\n        // matching sizes\n        for id, size in sizes do\n            match HashMap.tryFind id packing.Used with\n            | Some box ->\n                all <- HashMap.remove id all\n                let s = box.Max - box.Min + V2i.II\n                if s <> size && s.YX <> size then\n                    failwithf \"inconsistent sizes: %A vs %A\" s size\n\n            | None ->\n                failwithf \"missing id: %A\" id\n\n        // no extra rects\n        all.IsEmpty |> should be True\n\n\n    let run args =\n        \n        let gen = SizeGenerator()\n        let seed = Random.mkStdGen 239856472398472L\n\n\n        for size in [1;2;5;10;30] do\n            let tests = Gen.eval size seed (Gen.listOfLength 1000 (Gen.nonEmptyListOf SizeGenerator.SizeGen))\n\n            let tests = ( List.init size (fun _ -> Size(V2i(37,37))) ) :: tests\n\n            for t in tests do\n                try\n                    ``square producing correct results`` (NonEmptyArray (List.toArray t))\n                with e ->\n                    failwithf \"TexturePackingTests.run failed for size=%d case=%A\\n%s\" size t e.Message\n        0\n\n    //[<Test>]\n    //let ``occupancy``() =\n\n    //    let rand = RandomSystem()\n\n    //    for cnt in [10;50;100] do\n    //        let histogram = Array.zeroCreate 20\n    //        let binSize = 1.0 / float histogram.Length\n\n    //        printfn \"%d:\" cnt\n    //        let iter = 100\n    //        let mutable oMin = 1.0\n    //        let mutable oMax = 0.0\n    //        let mutable oSum = 0.0\n    //        for i in 1 .. iter do\n    //            let sizes = Array.init cnt (fun i -> i, rand.UniformV2i(63) + V2i.II)\n    //            let packing = TexturePacking.square sizes\n\n    //            let o = packing.Occupancy\n\n    //            let bin = floor (o * float histogram.Length) |> int |> clamp 0 (histogram.Length - 1)\n    //            histogram.[bin] <- histogram.[bin] + 1\n\n    //            oMin <- min oMin o\n    //            oMax <- max oMax o\n    //            oSum <- oSum + o\n\n    //        let oAvg = oSum / float iter\n\n    //        printfn \"  min: %.2f%%\" (100.0 * oMin)\n    //        printfn \"  max: %.2f%%\" (100.0 * oMax)\n    //        printfn \"  avg: %.2f%%\" (100.0 * oAvg)\n\n\n    //        let maxHisto = Array.max histogram\n    //        let w = 10\n    //        let mutable minValue = 0.0\n    //        let mutable maxValue = binSize\n    //        let mutable started = false\n    //        for h in histogram do\n    //            let p = float h / float iter\n    //            if h > 0 then started <- true\n\n    //            if started then\n    //                let barWidth = (float w * float h / float maxHisto) |> round |> int\n    //                let bar = System.String('#', barWidth) + System.String(' ', w - barWidth)\n\n    //                if maxValue >= 0.999999 then\n    //                    printfn \"   >= %.0f%%    %s %.2f%%\" (100.0 * minValue) bar (100.0 * p)\n\n    //                else \n    //                    printfn \"  [%.0f%%, %.0f%%) %s %.2f%%\" (100.0 * minValue) (100.0 * maxValue) bar (100.0 * p)\n    //            minValue <- minValue + binSize\n    //            maxValue <- maxValue + binSize\n"
  },
  {
    "path": "src/Tests/Aardvark.Geometry.Tests/paket.references",
    "content": "group Test\n\nFsCheck\nFsCheck.NUnit\nFSharp.Core\nFsUnit\nNUnit\nNUnit3TestAdapter\nMicrosoft.NET.Test.Sdk"
  },
  {
    "path": "test.cmd",
    "content": "@echo off\nREM Intentionally runs only the maintained test projects.\nREM The deprecated incremental test project is excluded on purpose; see issue #94.\ndotnet tool restore\nIF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\nREM `dotnet paket restore` alone does not recreate Paket.Restore.targets if it is missing.\nIF NOT EXIST \".paket\\Paket.Restore.targets\" (\n    dotnet paket install\n    IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\n) ELSE (\n    dotnet paket restore\n    IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\n)\ndotnet test src\\Tests\\Aardvark.Base.Tests\\Aardvark.Base.Tests.csproj\nIF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\ndotnet test src\\Tests\\Aardvark.Base.Runtime.Tests\\Aardvark.Base.Runtime.Tests.fsproj\nIF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\ndotnet test src\\Tests\\Aardvark.Base.Fonts.Tests\\Aardvark.Base.Fonts.Tests.fsproj\nIF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\ndotnet test src\\Tests\\Aardvark.Geometry.Tests\\Aardvark.Geometry.Tests.fsproj\nIF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\ndotnet test src\\Tests\\Aardvark.Base.FSharp.Tests\\Aardvark.Base.FSharp.Tests.fsproj\nIF ERRORLEVEL 1 EXIT /B %ERRORLEVEL%\n"
  },
  {
    "path": "test.sh",
    "content": "#!/bin/bash\n\nset -eu\n\n# Intentionally runs only the maintained test projects.\n# The deprecated incremental test project is excluded on purpose; see issue #94.\ndotnet tool restore\n# `dotnet paket restore` alone does not recreate Paket.Restore.targets if it is missing.\nif [ ! -f \".paket/Paket.Restore.targets\" ]; then\n    dotnet paket install\nelse\n    dotnet paket restore\nfi\ndotnet test src/Tests/Aardvark.Base.Tests/Aardvark.Base.Tests.csproj\ndotnet test src/Tests/Aardvark.Base.Runtime.Tests/Aardvark.Base.Runtime.Tests.fsproj\ndotnet test src/Tests/Aardvark.Base.Fonts.Tests/Aardvark.Base.Fonts.Tests.fsproj\ndotnet test src/Tests/Aardvark.Geometry.Tests/Aardvark.Geometry.Tests.fsproj\ndotnet test src/Tests/Aardvark.Base.FSharp.Tests/Aardvark.Base.FSharp.Tests.fsproj\n"
  },
  {
    "path": "tools/DocsChecker/DocsAnalyzer.cs",
    "content": "using System.Text.RegularExpressions;\n\ninternal sealed class DocsAnalyzer\n{\n    private static readonly Regex s_markdownLinkPattern = new(@\"\\[[^\\]]+\\]\\(([^)]+)\\)\", RegexOptions.Compiled);\n\n    private readonly DocsRules m_rules;\n\n    public DocsAnalyzer(DocsRules? rules = null)\n    {\n        m_rules = rules ?? DocsRules.CreateDefault();\n    }\n\n    public IReadOnlyList<string> Analyze(string root)\n    {\n        var fullRoot = Path.GetFullPath(root);\n        var failures = new List<string>();\n\n        CheckRequiredFiles(fullRoot, failures);\n        CheckMarkdownFiles(fullRoot, failures);\n        CheckForbiddenPatterns(fullRoot, failures);\n        CheckRequiredPatterns(fullRoot, failures);\n        CheckSourceAnchors(fullRoot, failures);\n\n        return failures;\n    }\n\n    private void CheckRequiredFiles(string root, List<string> failures)\n    {\n        foreach (var rel in m_rules.RequiredFiles)\n        {\n            var full = FullPath(root, rel);\n            if (!File.Exists(full))\n            {\n                failures.Add($\"Missing required file: {rel}\");\n                continue;\n            }\n\n            if (new FileInfo(full).Length == 0)\n                failures.Add($\"Empty required file: {rel}\");\n        }\n    }\n\n    private void CheckMarkdownFiles(string root, List<string> failures)\n    {\n        foreach (var markdownFile in EnumerateMarkdownFiles(root))\n        {\n            var relPath = Relative(root, markdownFile);\n            var text = File.ReadAllText(markdownFile);\n\n            foreach (var token in m_rules.MojibakeTokens)\n            {\n                if (!text.Contains(token, StringComparison.Ordinal)) continue;\n                failures.Add($\"Potential mojibake token '{token}' found in {relPath}\");\n                break;\n            }\n\n            ValidateMarkdownLinks(root, markdownFile, relPath, text, failures);\n        }\n    }\n\n    private void CheckForbiddenPatterns(string root, List<string> failures)\n    {\n        foreach (var rule in m_rules.ForbiddenPatterns)\n        {\n            var full = FullPath(root, rule.File);\n            if (!File.Exists(full)) continue;\n\n            var text = File.ReadAllText(full);\n            if (text.Contains(rule.Pattern, StringComparison.Ordinal))\n                failures.Add($\"Forbidden pattern in {rule.File}: '{rule.Pattern}'. {rule.Reason}\");\n        }\n    }\n\n    private void CheckRequiredPatterns(string root, List<string> failures)\n    {\n        foreach (var rule in m_rules.RequiredPatterns)\n        {\n            var full = FullPath(root, rule.File);\n            if (!File.Exists(full))\n            {\n                failures.Add($\"Missing required file for pattern check: {rule.File}\");\n                continue;\n            }\n\n            var text = File.ReadAllText(full);\n            if (!text.Contains(rule.Pattern, StringComparison.Ordinal))\n                failures.Add($\"Missing required pattern in {rule.File}: '{rule.Pattern}'. {rule.Reason}\");\n        }\n    }\n\n    private void CheckSourceAnchors(string root, List<string> failures)\n    {\n        foreach (var rule in m_rules.SourceAnchors)\n        {\n            var full = FullPath(root, rule.File);\n            if (!File.Exists(full))\n            {\n                failures.Add($\"Missing source anchor file: {rule.File}\");\n                continue;\n            }\n\n            var text = File.ReadAllText(full);\n            if (!text.Contains(rule.Snippet, StringComparison.Ordinal))\n                failures.Add($\"Source anchor not found in {rule.File}: '{rule.Snippet}'\");\n        }\n    }\n\n    private static IEnumerable<string> EnumerateMarkdownFiles(string root)\n    {\n        var readme = FullPath(root, \"README.md\");\n        if (File.Exists(readme))\n            yield return readme;\n\n        var ai = FullPath(root, \"ai\");\n        if (Directory.Exists(ai))\n        {\n            foreach (var file in Directory.EnumerateFiles(ai, \"*.md\", SearchOption.TopDirectoryOnly))\n                yield return file;\n        }\n\n        var docs = FullPath(root, \"docs\");\n        if (Directory.Exists(docs))\n        {\n            foreach (var file in Directory.EnumerateFiles(docs, \"*.md\", SearchOption.TopDirectoryOnly))\n                yield return file;\n        }\n\n        var agents = FullPath(root, \"AGENTS.md\");\n        if (File.Exists(agents))\n            yield return agents;\n    }\n\n    private void ValidateMarkdownLinks(\n        string root,\n        string markdownFile,\n        string relPath,\n        string text,\n        List<string> failures)\n    {\n        if (m_rules.LinkValidationIgnoreFiles.Contains(relPath))\n            return;\n\n        foreach (Match match in s_markdownLinkPattern.Matches(text))\n        {\n            if (match.Groups.Count < 2) continue;\n            var rawLink = match.Groups[1].Value.Trim();\n            if (string.IsNullOrEmpty(rawLink)) continue;\n\n            var linkPath = NormalizeMarkdownDestination(rawLink);\n            if (string.IsNullOrWhiteSpace(linkPath)) continue;\n\n            if (linkPath.StartsWith(\"http://\", StringComparison.OrdinalIgnoreCase) ||\n                linkPath.StartsWith(\"https://\", StringComparison.OrdinalIgnoreCase) ||\n                linkPath.StartsWith(\"#\", StringComparison.Ordinal))\n            {\n                continue;\n            }\n\n            if (linkPath.Contains(\"://\", StringComparison.Ordinal)) continue;\n\n            var relativeBase = Path.GetDirectoryName(markdownFile) ?? root;\n            var normalized = linkPath.Replace('/', Path.DirectorySeparatorChar);\n            var target = Path.GetFullPath(Path.Combine(relativeBase, normalized));\n\n            if (!target.StartsWith(root, StringComparison.OrdinalIgnoreCase))\n            {\n                failures.Add($\"Suspicious out-of-repo link in {relPath}: {rawLink}\");\n                continue;\n            }\n\n            if (!File.Exists(target) && !Directory.Exists(target))\n                failures.Add($\"Broken local link in {relPath}: {rawLink}\");\n        }\n    }\n\n    private static string NormalizeMarkdownDestination(string rawLink)\n    {\n        var trimmed = rawLink.Trim();\n        if (trimmed.Length == 0) return string.Empty;\n\n        string destination;\n\n        if (trimmed[0] == '<')\n        {\n            var closing = trimmed.IndexOf('>');\n            destination = closing > 0 ? trimmed[1..closing] : trimmed;\n        }\n        else\n        {\n            destination = trimmed;\n\n            for (var i = 0; i < trimmed.Length - 1; i++)\n            {\n                if (!char.IsWhiteSpace(trimmed[i])) continue;\n\n                var next = trimmed[i + 1];\n                if (next == '\"' || next == '\\'')\n                {\n                    destination = trimmed[..i];\n                    break;\n                }\n            }\n        }\n\n        destination = destination.Trim();\n        if (destination.Length >= 2 && destination[0] == '<' && destination[^1] == '>')\n            destination = destination[1..^1].Trim();\n\n        var fragmentIndex = destination.IndexOf('#');\n        if (fragmentIndex >= 0)\n            destination = destination[..fragmentIndex];\n\n        return destination.Trim();\n    }\n\n    internal static string FullPath(string root, string rel)\n        => Path.GetFullPath(Path.Combine(root, rel.Replace('/', Path.DirectorySeparatorChar)));\n\n    internal static string Relative(string root, string full)\n        => Path.GetRelativePath(root, full).Replace('\\\\', '/');\n}\n"
  },
  {
    "path": "tools/DocsChecker/DocsChecker.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n  </PropertyGroup>\n</Project>\n"
  },
  {
    "path": "tools/DocsChecker/DocsRules.cs",
    "content": "internal readonly record struct PatternRule(string File, string Pattern, string Reason);\n\ninternal readonly record struct SourceAnchorRule(string File, string Snippet);\n\ninternal sealed class DocsRules\n{\n    public required IReadOnlyList<string> RequiredFiles { get; init; }\n    public required IReadOnlyList<PatternRule> ForbiddenPatterns { get; init; }\n    public required IReadOnlyList<PatternRule> RequiredPatterns { get; init; }\n    public required IReadOnlyList<SourceAnchorRule> SourceAnchors { get; init; }\n    public required IReadOnlySet<string> LinkValidationIgnoreFiles { get; init; }\n    public required IReadOnlyList<string> MojibakeTokens { get; init; }\n\n    public static DocsRules CreateDefault()\n        => new()\n        {\n            RequiredFiles =\n            [\n                \"AGENTS.md\",\n                \"ai/README.md\",\n                \"ai/SYMBOL_INDEX.md\",\n                \"ai/SEMANTICS_LINEAR_ALGEBRA.md\",\n                \"ai/SEMANTICS_GEOMETRY_CORE.md\",\n                \"ai/PRIMITIVE_TYPES.md\",\n                \"ai/UTILITIES.md\",\n                \"ai/COLLECTIONS.md\",\n                \"ai/ALGORITHMS.md\",\n                \"ai/PIXIMAGE.md\",\n                \"ai/TENSORS.md\",\n                \"ai/FSHARP_INTEROP.md\",\n                \"ai/INCREMENTAL.md\",\n                \"ai/SERIALIZATION.md\",\n                \"docs/CONTRIBUTING.md\",\n                \"docs/INTEROP.md\",\n                \"docs/TROUBLESHOOTING.md\",\n            ],\n            ForbiddenPatterns =\n            [\n                new(\"docs/CONTRIBUTING.md\", \"--config\", \"build.sh/build.cmd do not support --config.\"),\n                new(\"docs/CONTRIBUTING.md\", \"./build.sh --project\", \"build.sh/build.cmd do not support --project.\"),\n                new(\"docs/CONTRIBUTING.md\", \".\\\\build.cmd --project\", \"build.sh/build.cmd do not support --project.\"),\n                new(\"docs/CONTRIBUTING.md\", \"./test.sh --filter\", \"Use dotnet test ... --filter for filtered runs.\"),\n                new(\"docs/CONTRIBUTING.md\", \".\\\\test.cmd --filter\", \"Use dotnet test ... --filter for filtered runs.\"),\n                new(\"docs/INTEROP.md\", \"F# Projects Reference C#, Never the Reverse\", \"Repository intentionally has mixed C#/F# reference directions.\"),\n                new(\"ai/UTILITIES.md\", \"Telemetry.Reset()\", \"Actual API is Telemetry.ResetTelemetrySystem().\"),\n                new(\"ai/UTILITIES.md\", \"Constant<float>.Pi\", \"Pi/E are on Constant / ConstantF, not Constant<T>.\"),\n                new(\"ai/UTILITIES.md\", \"Constant<double>.Pi\", \"Pi/E are on Constant / ConstantF, not Constant<T>.\"),\n                new(\"ai/PIXIMAGE.md\", \"PixImage.Load<byte>\", \"Static generic PixImage.Load<T> is not available.\"),\n                new(\"ai/PIXIMAGE.md\", \"PixImage.Load<float>\", \"Static generic PixImage.Load<T> is not available.\"),\n                new(\"ai/COLLECTIONS.md\", \"TryRemove(item)\", \"ConcurrentHashSet<T> uses Remove, not TryRemove.\"),\n                new(\"ai/TENSORS.md\", \"class Matrix<\", \"Generated tensor containers are structs.\"),\n                new(\"ai/TENSORS.md\", \"class Volume<\", \"Generated tensor containers are structs.\"),\n            ],\n            RequiredPatterns =\n            [\n                new(\"AGENTS.md\", \"check-docs.sh\", \"AGENTS should expose docs checker command.\"),\n                new(\"AGENTS.md\", \"check-docs.cmd\", \"AGENTS should expose docs checker command.\"),\n                new(\"ai/README.md\", \"SYMBOL_INDEX.md\", \"README should expose symbol index.\"),\n                new(\"ai/README.md\", \"SEMANTICS_LINEAR_ALGEBRA.md\", \"README should expose semantic deep-dive docs.\"),\n                new(\"ai/README.md\", \"SEMANTICS_GEOMETRY_CORE.md\", \"README should expose semantic deep-dive docs.\"),\n                new(\"ai/SEMANTICS_LINEAR_ALGEBRA.md\", \"row-major\", \"Linear algebra semantics should state row-major storage.\"),\n                new(\"ai/SEMANTICS_LINEAR_ALGEBRA.md\", \"FromCols\", \"Linear algebra semantics should include conversion guidance.\"),\n                new(\"ai/SEMANTICS_GEOMETRY_CORE.md\", \"TransformPos\", \"Geometry semantics should explicitly reference TransformPos/TransformDir.\"),\n                new(\"ai/PIXIMAGE.md\", \"No static `PixImage.Load<T>(...)` API exists.\", \"PixImage docs should guard against stale generic load examples.\"),\n                new(\"ai/UTILITIES.md\", \"ResetTelemetrySystem\", \"Utilities docs should use correct telemetry reset API.\"),\n                new(\"ai/TENSORS.md\", \"`struct` types\", \"Tensor docs should call out struct container reality.\"),\n                new(\"docs/CONTRIBUTING.md\", \"dotnet test src/Aardvark.sln --filter\", \"Contributing guide should show valid filtered test command.\"),\n                new(\"docs/INTEROP.md\", \"mixed C#/F# project references\", \"Interop guide must reflect actual dependency reality.\"),\n            ],\n            SourceAnchors =\n            [\n                new(\"src/Aardvark.Base/Math/Trafos/Matrix_auto.cs\", \"public partial struct M44d\"),\n                new(\"src/Aardvark.Base/Math/Trafos/Matrix_auto.cs\", \"public static M44d FromCols(V4d col0, V4d col1, V4d col2, V4d col3)\"),\n                new(\"src/Aardvark.Base/Math/Trafos/Matrix_auto.cs\", \"public static V4d operator *(M44d m, V4d v)\"),\n                new(\"src/Aardvark.Base/Math/Trafos/Matrix_auto.cs\", \"public static V3d TransformPos(this M44d m, V3d p)\"),\n                new(\"src/Aardvark.Base/Math/Trafos/Matrix_auto.cs\", \"public static V3d TransposedTransformPos(this M44d m, V3d p)\"),\n                new(\"src/Aardvark.Base/Math/Trafos/Trafo_auto.cs\", \"public readonly partial struct Trafo3d : IEquatable<Trafo3d>\"),\n                new(\"src/Aardvark.Base/Math/Trafos/Trafo_auto.cs\", \"public static Trafo3d operator *(Trafo3d t0, Trafo3d t1)\"),\n                new(\"src/Aardvark.Base/Math/Colors/Color.cs\", \"public readonly struct PixFormat : IEquatable<PixFormat>\"),\n                new(\"src/Aardvark.Base.Tensors.CSharp/Tensor_auto.cs\", \"public partial struct Matrix<Td> : IValidity, IMatrix<Td>, IArrayMatrix\"),\n                new(\"src/Aardvark.Base.Tensors.CSharp/Tensor_auto.cs\", \"public partial struct Volume<Td> : IValidity, IVolume<Td>, IArrayVolume\"),\n                new(\"src/Aardvark.Base.Tensors.CSharp/Tensor_auto.cs\", \"public partial struct Tensor4<Td> : IValidity, ITensor4<Td>, IArrayTensor4\"),\n                new(\"src/Aardvark.Base.Tensors.CSharp/PixImage/PixImage.cs\", \"public static PixImage Load(string filename, IPixLoader loader = null)\"),\n                new(\"src/Aardvark.Base.Tensors.CSharp/PixImage/PixImage.cs\", \"public void SaveAsJpeg(string filename, int quality = PixJpegSaveParams.DefaultQuality,\"),\n                new(\"src/Aardvark.Base.Tensors.CSharp/PixImage/PixImage.cs\", \"public static PixImageInfo GetInfoFromFile(string filename, IPixLoader loader = null)\"),\n                new(\"src/Aardvark.Base.Tensors.CSharp/Tensors/ImageTensors.cs\", \"public static bool HasImageLayout<T>(this Volume<T> volume)\"),\n                new(\"src/Aardvark.Base.Telemetry/IProbe.cs\", \"public static void ResetTelemetrySystem()\"),\n                new(\"src/Aardvark.Base/Reporting/Report.cs\", \"public static void Trace([Localizable(true)] string line, params object[] args)\"),\n                new(\"src/Aardvark.Base/Random/RandomSample.cs\", \"public static V3d Lambertian(V3d normal, IRandomSeries rnds, int seriesIndex)\"),\n                new(\"src/Aardvark.Base/Random/HaltonRandomSeries.cs\", \"public class HaltonRandomSeries : IRandomSeries\"),\n                new(\"src/Aardvark.Base/Geodesy/GeoConversion.cs\", \"public static V3d XyzFromLonLatHeight(V3d lonLatHeight, GeoEllipsoid ellipsoid)\"),\n                new(\"src/Aardvark.Base/Geodesy/GeoConsts.cs\", \"public static readonly GeoEllipsoid Wgs84 = FromAF(6378137.0, 1.0 / 298.257223563);\"),\n                new(\"src/Aardvark.Base/Symbol/Symbol.cs\", \"public readonly struct Symbol : IEquatable<Symbol>, IComparable<Symbol>, IComparable\"),\n                new(\"src/Aardvark.Base/AlgoDat/LruCache.cs\", \"public class LruCache<TKey, TValue>\"),\n                new(\"src/Aardvark.Base/AlgoDat/ConcurrentHashSet.cs\", \"public bool Remove(T item) => m_entries.TryRemove(item, out int dummy);\"),\n                new(\"src/Aardvark.Base/AlgoDat/ShortestPath.cs\", \"public class ShortestPath<T> : IShortestPath<T>\"),\n                new(\"src/Aardvark.Base/Geometry/BbTree.cs\", \"public class BbTree\"),\n                new(\"src/Aardvark.Base/Math/Base/DistributionFunction.cs\", \"public class DistributionFunction\"),\n                new(\"src/Aardvark.Base/Math/Numerics/Polynomial.cs\", \"public static class Polynomial\"),\n            ],\n            LinkValidationIgnoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase)\n            {\n                \"ai/RECIPE_AI_FRIENDLINESS.md\",\n            },\n            MojibakeTokens = [\"â\", \"Ã\", \"Â\", \"�\"],\n        };\n}\n"
  },
  {
    "path": "tools/DocsChecker/Program.cs",
    "content": "internal static class Program\n{\n    private static int Main(string[] args)\n    {\n        var root = args.Length > 0\n            ? Path.GetFullPath(args[0])\n            : Directory.GetCurrentDirectory();\n\n        var analyzer = new DocsAnalyzer();\n        var failures = analyzer.Analyze(root);\n\n        if (failures.Count > 0)\n        {\n            Console.Error.WriteLine(\"Docs check failed:\");\n            foreach (var failure in failures)\n                Console.Error.WriteLine($\"- {failure}\");\n            return 1;\n        }\n\n        Console.WriteLine(\"Docs check passed.\");\n        return 0;\n    }\n}\n"
  },
  {
    "path": "tools/DocsChecker/Properties/AssemblyInfo.cs",
    "content": "using System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"DocsChecker.Tests\")]\n"
  },
  {
    "path": "tools/DocsChecker.Tests/DocsAnalyzerTests.cs",
    "content": "using System.Text;\nusing Xunit;\n\npublic sealed class DocsAnalyzerTests\n{\n    [Fact]\n    public void ValidFixture_PassesWithoutFailures()\n    {\n        using var repo = TempRepo.CreateValid();\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.Empty(failures);\n    }\n\n    [Fact]\n    public void BrokenLink_IsReported()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Append(\"ai/README.md\", \"\\n[broken](missing.md)\\n\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.Contains(\"Broken local link in ai/README.md: missing.md\", failures);\n    }\n\n    [Fact]\n    public void RootReadmeBrokenLink_IsReported()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Append(\"README.md\", \"\\n[broken](missing.md)\\n\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.Contains(\"Broken local link in README.md: missing.md\", failures);\n    }\n\n    [Fact]\n    public void MarkdownLinkWithTitle_ToExistingFile_IsAccepted()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Append(\"README.md\", \"\\n[guide](docs/INTEROP.md \\\"interop\\\")\\n\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.DoesNotContain(\"Broken local link in README.md: docs/INTEROP.md \\\"interop\\\"\", failures);\n    }\n\n    [Fact]\n    public void MarkdownLinkWithAngleBracketDestination_ToExistingFile_IsAccepted()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Append(\"README.md\", \"\\n[guide](<docs/INTEROP.md>)\\n\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.DoesNotContain(\"Broken local link in README.md: <docs/INTEROP.md>\", failures);\n    }\n\n    [Fact]\n    public void ForbiddenPattern_IsReported()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Append(\"docs/CONTRIBUTING.md\", \"\\n./build.sh --project src/Aardvark.Base/Aardvark.Base.csproj\\n\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.Contains(failures, f => f.Contains(\"Forbidden pattern in docs/CONTRIBUTING.md\", StringComparison.Ordinal));\n    }\n\n    [Fact]\n    public void MissingRequiredPattern_IsReported()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Write(\"ai/SEMANTICS_LINEAR_ALGEBRA.md\", \"layout notes without required token\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.Contains(\n            \"Missing required pattern in ai/SEMANTICS_LINEAR_ALGEBRA.md: 'row-major'. Linear algebra semantics should state row-major storage.\",\n            failures);\n    }\n\n    [Fact]\n    public void MissingSourceAnchor_IsReported()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Write(\"src/Aardvark.Base/Symbol/Symbol.cs\", \"public sealed class NotASymbol {}\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.Contains(\n            \"Source anchor not found in src/Aardvark.Base/Symbol/Symbol.cs: 'public readonly struct Symbol : IEquatable<Symbol>, IComparable<Symbol>, IComparable'\",\n            failures);\n    }\n\n    [Fact]\n    public void MojibakeToken_IsReported()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Append(\"ai/UTILITIES.md\", \"\\nPotential mojibake: Ã\\n\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        Assert.Contains(\"Potential mojibake token 'Ã' found in ai/UTILITIES.md\", failures);\n    }\n\n    [Fact]\n    public void IntegrationFixture_ReportsExactFailureMessages()\n    {\n        using var repo = TempRepo.CreateValid();\n        repo.Append(\"ai/README.md\", \"\\n[broken](missing.md)\\n\");\n        repo.Write(\"src/Aardvark.Base/Math/Numerics/Polynomial.cs\", \"public static class NotPolynomial {}\");\n        var analyzer = new DocsAnalyzer();\n\n        var failures = analyzer.Analyze(repo.Root);\n\n        var expected = new[]\n        {\n            \"Broken local link in ai/README.md: missing.md\",\n            \"Source anchor not found in src/Aardvark.Base/Math/Numerics/Polynomial.cs: 'public static class Polynomial'\",\n        };\n\n        foreach (var e in expected)\n            Assert.Contains(e, failures);\n    }\n\n    private sealed class TempRepo : IDisposable\n    {\n        private readonly string m_root;\n        private bool m_disposed;\n\n        public string Root => m_root;\n\n        private TempRepo(string root)\n        {\n            m_root = root;\n        }\n\n        public static TempRepo CreateValid()\n        {\n            var root = Path.Combine(Path.GetTempPath(), \"docs-checker-tests\", Guid.NewGuid().ToString(\"N\"));\n            Directory.CreateDirectory(root);\n\n            var repo = new TempRepo(root);\n            repo.InitializeValidFixture();\n            return repo;\n        }\n\n        public void Write(string relPath, string content)\n        {\n            var full = Path.Combine(m_root, relPath.Replace('/', Path.DirectorySeparatorChar));\n            var dir = Path.GetDirectoryName(full);\n            if (!string.IsNullOrEmpty(dir))\n                Directory.CreateDirectory(dir);\n\n            File.WriteAllText(full, content, new UTF8Encoding(false));\n        }\n\n        public void Append(string relPath, string content)\n        {\n            var full = Path.Combine(m_root, relPath.Replace('/', Path.DirectorySeparatorChar));\n            File.AppendAllText(full, content, new UTF8Encoding(false));\n        }\n\n        private void InitializeValidFixture()\n        {\n            var rules = DocsRules.CreateDefault();\n\n            foreach (var rel in rules.RequiredFiles)\n                Write(rel, \"# placeholder\");\n\n            Write(\"README.md\", \"[agents](AGENTS.md)\\n[ai](./ai/)\\n[docs](docs/CONTRIBUTING.md)\\n\");\n            Write(\"AGENTS.md\", \"check-docs.sh\\ncheck-docs.cmd\\n\");\n            Write(\"ai/README.md\", \"SYMBOL_INDEX.md\\nSEMANTICS_LINEAR_ALGEBRA.md\\nSEMANTICS_GEOMETRY_CORE.md\\n\");\n            Write(\"ai/SEMANTICS_LINEAR_ALGEBRA.md\", \"row-major\\nFromCols\\n\");\n            Write(\"ai/SEMANTICS_GEOMETRY_CORE.md\", \"TransformPos and TransformDir semantics\\n\");\n            Write(\"ai/PIXIMAGE.md\", \"No static `PixImage.Load<T>(...)` API exists.\\n\");\n            Write(\"ai/UTILITIES.md\", \"Use ResetTelemetrySystem for reset.\\n\");\n            Write(\"ai/TENSORS.md\", \"These are `struct` types in generated code.\\n\");\n            Write(\"docs/CONTRIBUTING.md\", \"dotnet test src/Aardvark.sln --filter \\\"FullyQualifiedName~Vector\\\"\\n\");\n            Write(\"docs/INTEROP.md\", \"This repo has mixed C#/F# project references.\\n\");\n\n            foreach (var group in rules.SourceAnchors.GroupBy(x => x.File))\n            {\n                var content = string.Join(\"\\n\", group.Select(x => x.Snippet)) + \"\\n\";\n                Write(group.Key, content);\n            }\n        }\n\n        public void Dispose()\n        {\n            if (m_disposed) return;\n            m_disposed = true;\n\n            if (Directory.Exists(m_root))\n            {\n                try\n                {\n                    Directory.Delete(m_root, recursive: true);\n                }\n                catch\n                {\n                    // Best effort cleanup for temp fixtures.\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "tools/DocsChecker.Tests/DocsChecker.Tests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>net8.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.11.1\" />\n    <PackageReference Include=\"xunit\" Version=\"2.9.2\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.8.2\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"coverlet.collector\" Version=\"6.0.2\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\DocsChecker\\DocsChecker.csproj\" />\n  </ItemGroup>\n</Project>\n"
  }
]